Hi all,
I'm very new to this, both the Moteino and posting, so please forgive any errors.
I've been working on a project to get a POCSAG protocol working on the Moteino-USB with a RFM69HCW. I saw a great example code here: http://www.f4huy.fr/?p=1140 It even included a POCSAG encoding library :).
Since I haven't been able to get a hold of an RFM22 module, I've been trying to modify the code to accept the RFM69. It compiles fine, but there doesn't seem to be any transmission. The state machine is a little convoluted, but it's just parsing info based off a particular format as shown in the link above. Here's the code I've been working with: #include <SPI.h>
#include <RH_RF69.h>
// pocsag message generation library
#include <Pocsag.h>
// Singleton instance of the radio
RH_RF69 rf69;
Pocsag pocsag;
// frequency
float freq;
void setup()
{
pinMode(4, OUTPUT);
digitalWrite(4, HIGH);
Serial.begin(38400);
while (!Serial) ; // Wait for serial port to be available
if (rf69.init()) {
Serial.println("rf69 init OK");
} else {
Serial.println("rf69 init FAILED");
}; // end if
// Set frequency. AfcPullinRange set to 50 Khz (unused, we are not receiving)
//rf69.setFrequency(433.9000, 0.00);
rf69.setFrequency(439.9875, 0.050); // subtract 30 Khz for crystal correction
// this correction-value will differ per device.
// to be determined experimental
// set to 512 bps FSK, 4.5 Khz deviation (POCSAG 1200)
rf69.setModemConfig(RH_RF69::FSK_Rb2_4Fd4_8 );
// 6 mW TX power (EU ISM legislation)
rf69.setTxPower(14);
}
void loop() {
//vars
int rc;
int state; // state machine for CLI input
// bell = ascii 0x07
char bell=0x07;
// data
long int address;
int addresssource;
int repeat;
char textmsg[42]; // to store text message;
int msgsize;
int freqsize;
int freq1; // freq MHZ part (3 digits)
int freq2; // freq. 100 Hz part (4 digits)
// read input:
// format: "P <address> <source> <repeat> <message>"
// format: "F <freqmhz> <freq100Hz>"
Serial.println("Format:");
Serial.println("P <address> <source> <repeat> <message>");
Serial.println("F <freqmhz> <freq100Hz>");
// init var
state=0;
address=0;
addresssource=0;
msgsize=0;
freqsize=0;
freq1=0; freq2=0;
while (state >= 0) {
char c;
// loop until we get a character from serial input
while (!Serial.available()) {
}; // end while
c=Serial.read();
// break out on ESC
if (c == 0x1b) {
state=-999;
break;
}; // end if
// state machine
if (state == 0) {
// state 0: wait for command
// P = PAGE
// F = FREQUENCY
if ((c == 'p') || (c == 'P')) {
// ok, got our "p" -> go to state 1
state=1;
// echo back char
Serial.write(c);
} else if ((c == 'f') || (c == 'F')) {
// ok, got our "f" -> go to state 1
state=10;
// echo back char
Serial.write(c);
} else {
// error: echo "bell"
Serial.write(bell);
}; // end else - if
// get next char
continue;
}; // end state 0
// state 1: space (" ") or first digit of address ("0" to "9")
if (state == 1) {
if (c == ' ') {
// space -> go to state 2 and get next char
state=2;
// echo back char
Serial.write(c);
// get next char
continue;
} else if ((c >= '0') && (c <= '9')) {
// digit -> first digit of address. Go to state 2 and process
state=2;
// continue to state 2 without fetching next char
} else {
// error: echo "bell"
Serial.write(bell);
// get next char
continue;
}; // end else - if
}; // end state 1
// state 2: address ("0" to "9")
if (state == 2) {
if ((c >= '0') && (c <= '9')) {
long int newaddress;
newaddress = address * 10 + (c - '0');
if (newaddress <= 0x1FFFFF) {
// valid address
address=newaddress;
Serial.write(c);
} else {
// address to high. Send "beep"
Serial.write(bell);
}; // end else - if
} else if (c == ' ') {
// received space, go to next field (address source)
Serial.write(c);
state=3;
} else {
// error: echo "bell"
Serial.write(bell);
}; // end else - elsif - if
// get next char
continue;
}; // end state 2
// state 3: address source: one single digit from 0 to 3
if (state == 3) {
if ((c >= '0') && (c <= '3')) {
addresssource= c - '0';
Serial.write(c);
state=4;
} else {
// invalid: sound bell
Serial.write(bell);
}; // end if
// get next char
continue;
}; // end state 3
// state 4: space between source and repeat
if (state == 4) {
if (c == ' ') {
Serial.write(c);
state=6; // go from state 4 to state 6
// (No state 5, callsign removed)
} else {
// invalid: sound bell
Serial.write(bell);
}; // end if
// get next char
continue;
}; // end state 4
// state 5: callsign: REMOVED in non-ham version
// state 6: repeat: 1-digit value between 0 and 9
if (state == 6) {
if ((c >= '0') && (c <= '9')) {
Serial.write(c);
repeat=c - '0';
// move to next state
state=7;
} else {
Serial.write(bell);
}; // end if
// get next char
continue;
}; // end state 6
// state 7: space between repeat and message
if (state == 7) {
if (c == ' ') {
Serial.write(c);
// move to next state
state=8;
} else {
// invalid char
Serial.write(bell);
}; // end else - if
// get next char
continue;
}; // end state 7
// state 8: message, up to 40 chars, terminate with cr (0x0d) or lf (0x0a)
if (state == 8) {
// accepted is everything between space (ascii 0x20) and ~ (ascii 0x7e)
if ((c >= 0x20) && (c <= 0x7e)) {
// accept up to 40 chars
if (msgsize < 40) {
Serial.write(c);
textmsg[msgsize]=c;
msgsize++;
} else {
// to long
Serial.write(bell);
}; // end else - if
} else if ((c == 0x0a) || (c == 0x0d) || (c == 0x2e)) {
// done
Serial.println("");
// add terminating NULL
textmsg[msgsize]=0x00;
// break out of loop
state=-1;
break;
} else {
// invalid char
Serial.write(bell);
}; // end else - elsif - if
// get next char
continue;
}; // end state 8;
// PART 2: frequency
// state 10: space (" ") or first digit of address ("0" to "9")
if (state == 10) {
if (c == ' ') {
// space -> go to state 11 and get next char
state=11;
// echo back char
Serial.write(c);
// get next char
continue;
} else if ((c >= '0') && (c <= '9')) {
// digit -> first digit of address. Go to state 2 and process
state=11;
// init freqsize;
freqsize=0;
// continue to state 2 without fetching next char
} else {
// error: echo "bell"
Serial.write(bell);
// get next char
continue;
}; // end else - if
}; // end state 10
// state 11: freq. Mhz part: 3 digits needed
if (state == 11) {
if ((c >= '0') && (c <= '9')) {
if (freqsize < 3) {
freq1 *= 10;
freq1 += (c - '0');
freqsize++;
Serial.write(c);
// go to state 12 (wait for space) if 3 digits received
if (freqsize == 3) {
state=12;
}; // end if
} else {
// too large: error
Serial.write(bell);
}; // end else - if
} else {
// unknown char: error
Serial.write(bell);
}; // end else - if
// get next char
continue;
}; // end state 11
// state 12: space between freq part 1 and freq part 2
if (state == 12) {
if (c == ' ') {
// space received, go to state 13
state = 13;
Serial.write(c);
// reinit freqsize;
freqsize=0;
} else {
// unknown char
Serial.write(bell);
}; // end else - if
// get next char
continue;
}; // end state 12;
// state 13: part 2 of freq. (100 Hz part). 4 digits needed
if (state == 13) {
if ((c >= '0') && (c <= '9')) {
if (freqsize < 4) {
freq2 *= 10;
freq2 += (c - '0');
freqsize++;
Serial.write(c);
} else {
// too large: error
Serial.write(bell);
}; // end else - if
// get next char
continue;
} else if ((c == 0x0a) || (c == 0x0d)) {
if (freqsize == 4) {
// 4 digits received, done
state = -2;
Serial.println("");
// break out
break;
} else {
// not yet 3 digits
Serial.write(bell);
// get next char;
continue;
}; // end else - if
} else {
// unknown char
Serial.write(bell);
// get next char
continue;
}; // end else - elsif - if
}; // end state 12;
}; // end while
// Function "P": Send PAGE
if (state == -1) {
Serial.print("address: ");
Serial.println(address);
Serial.print("addresssource: ");
Serial.println(addresssource);
Serial.print("repeat: ");
Serial.println(repeat);
Serial.print("message: ");
Serial.println(textmsg);
// create pocsag message
// batch2 option = 0 (truncate message)
// invert option1 (invert)
rc=pocsag.CreatePocsag(address,addresssource,textmsg,0,1);
if (!rc) {
Serial.print("Error in createpocsag! Error: ");
Serial.println(pocsag.GetError());
// sleep 10 seconds
delay(10000);
} else {
// send at least once + repeat
for (int l=-1; l < repeat; l++) {
Serial.println("POCSAG SEND");
Serial.println(pocsag.GetSize());
rf69.send((uint8_t *)pocsag.GetMsgPointer(), pocsag.GetSize());
rf69.waitPacketSent();
delay(3000);
}; // end for
}; // end else - if;
}; // end function P (send PAGE)
// function "F": change frequency
if (state == -2) {
float newfreq;
newfreq=((float)freq1)+((float)freq2)/10000.0F; // f1 = MHz, F2 = 100 Hz
// ISM band: 434.050 to 434.800 and 863 to 870
if ( ((newfreq >= 430.050F) && (newfreq <= 440.8F)) ||
((newfreq >= 863.0) && (newfreq < 870.0F)) ) {
Serial.print("switching to new frequency: ");
Serial.println(newfreq);
freq=newfreq;
rf69.setFrequency(freq, 0.05); // set frequency, AfcPullinRange not used (receive-only)
} else {
Serial.print("Error: invalid frequency (should be 433.050-434.800 or 853-8670 Mhz) ");
Serial.println(newfreq);
}; // end if
}; // end function F (frequency)
}; // end main application
The serial prints to the serial monitor work fine, but the frequency spectrum is empty. Is there something obvious I missed, like initializing pins and outputs? Or perhaps there is an easier way to go about this, perhaps the RFM69 library? Thank you all ahead of time for any help.