diff --git a/Examples/LED_Control_Gateway/LED_Control_Gateway.ino b/Examples/LED_Control_Gateway/LED_Control_Gateway.ino index 996c62e..72c939f 100644 --- a/Examples/LED_Control_Gateway/LED_Control_Gateway.ino +++ b/Examples/LED_Control_Gateway/LED_Control_Gateway.ino @@ -103,8 +103,8 @@ void loop() { digitalWrite(LED,1); Serial.print('[');Serial.print(radio.GetSender(), DEC);Serial.print("] "); - for (byte i = 0; i < *radio.DataLen; i++) - Serial.print((char)radio.Data[i]); + for (byte i = 0; i < radio.GetDataLen(); i++) + Serial.print((char)radio.GetData()[i]); if (radio.ACKRequested()) { @@ -140,9 +140,10 @@ void sendMessage() // wait up to ACK_TIME for proper ACK, return true if received static bool waitForAck() { long now = millis(); - while (millis() - now <= ACK_TIME) + do { if (radio.ACKReceived(nodeId)) return true; + } while (millis() - now <= ACK_TIME); return false; } diff --git a/Examples/LED_Control_Node/LED_Control_Node.ino b/Examples/LED_Control_Node/LED_Control_Node.ino index 04e0255..bcde261 100644 --- a/Examples/LED_Control_Node/LED_Control_Node.ino +++ b/Examples/LED_Control_Node/LED_Control_Node.ino @@ -81,16 +81,16 @@ void loop() if (radio.CRCPass()) { Serial.print('[');Serial.print(radio.GetSender(), DEC);Serial.print("] "); - for (byte i = 0; i < *radio.DataLen; i++) - Serial.print((char)radio.Data[i]); + for (byte i = 0; i < radio.GetDataLen(); i++) + Serial.print((char)radio.GetData()[i]); Serial.print(" - "); //check for a LED blink/pulse/stop request - if (*radio.DataLen == 3 - && (radio.Data[0]=='b' || radio.Data[0]=='p' || radio.Data[0]=='o') - && radio.Data[1] == ':' - && (radio.Data[2]=='s' || radio.Data[2]=='m' || radio.Data[2]=='f')) - handleRequest(radio.Data[0], radio.Data[2]); + if (radio.GetDataLen() == 3 + && (radio.GetData()[0]=='b' || radio.GetData()[0]=='p' || radio.GetData()[0]=='o') + && radio.GetData()[1] == ':' + && (radio.GetData()[2]=='s' || radio.GetData()[2]=='m' || radio.GetData()[2]=='f')) + handleRequest(radio.GetData()[0], radio.GetData()[2]); if (radio.ACKRequested()) { diff --git a/Examples/RFM12B_Struct_gateway/RFM12B_Struct_gateway.ino b/Examples/RFM12B_Struct_gateway/RFM12B_Struct_gateway.ino index c77f91c..73d1e86 100644 --- a/Examples/RFM12B_Struct_gateway/RFM12B_Struct_gateway.ino +++ b/Examples/RFM12B_Struct_gateway/RFM12B_Struct_gateway.ino @@ -75,11 +75,11 @@ void loop() { { Serial.print('[');Serial.print(radio.GetSender(), DEC);Serial.print("] "); - if (*radio.DataLen != sizeof(Payload)) + if (radio.GetDataLen() != sizeof(Payload)) Serial.print("Invalid payload received, not matching Payload struct!"); else { - theData = *(Payload*)radio.Data; //assume radio.DATA actually contains our struct and not something else + theData = *(Payload*)radio.GetData(); //assume radio.DATA actually contains our struct and not something else Serial.print(" nodeId="); Serial.print(theData.nodeId); Serial.print(" uptime="); @@ -119,9 +119,9 @@ void Blink(byte PIN, int DELAY_MS) // wait a few milliseconds for proper ACK to me, return true if indeed received static bool waitForAck(byte theNodeID) { long now = millis(); - while (millis() - now <= ACK_TIME) { + do { if (radio.ACKReceived(theNodeID)) return true; - } + } while (millis() - now <= ACK_TIME); return false; } diff --git a/Examples/RFM12B_Struct_node/RFM12B_Struct_node.ino b/Examples/RFM12B_Struct_node/RFM12B_Struct_node.ino index d4f33f9..c46d991 100644 --- a/Examples/RFM12B_Struct_node/RFM12B_Struct_node.ino +++ b/Examples/RFM12B_Struct_node/RFM12B_Struct_node.ino @@ -87,8 +87,8 @@ void loop() { if (radio.CRCPass()) { Serial.print('[');Serial.print(radio.GetSender(), DEC);Serial.print("] "); - for (byte i = 0; i < *radio.DataLen; i++) - Serial.print((char)radio.Data[i]); + for (byte i = 0; i < radio.GetDataLen(); i++) + Serial.print((char)radio.GetData()[i]); if (radio.ACKRequested()) { @@ -138,9 +138,9 @@ void Blink(byte PIN, int DELAY_MS) // wait a few milliseconds for proper ACK to me, return true if indeed received static bool waitForAck(byte theNodeID) { long now = millis(); - while (millis() - now <= ACK_TIME) { + do { if (radio.ACKReceived(theNodeID)) return true; - } + } while (millis() - now <= ACK_TIME); return false; } diff --git a/Examples/Receive/Receive.ino b/Examples/Receive/Receive.ino index 7e4884a..3786bce 100644 --- a/Examples/Receive/Receive.ino +++ b/Examples/Receive/Receive.ino @@ -36,8 +36,8 @@ void loop() if (radio.CRCPass()) { Serial.print('[');Serial.print(radio.GetSender());Serial.print("] "); - for (byte i = 0; i < *radio.DataLen; i++) //can also use radio.GetDataLen() if you don't like pointers - Serial.print((char)radio.Data[i]); + for (byte i = 0; i < radio.GetDataLen(); i++) //can also use radio.GetDataLen() if you don't like pointers + Serial.print((char)radio.GetData()[i]); if (radio.ACKRequested()) { @@ -50,4 +50,4 @@ void loop() Serial.println(); } -} +} diff --git a/Examples/Send/Send.ino b/Examples/Send/Send.ino index 9ed801c..b0b8697 100644 --- a/Examples/Send/Send.ino +++ b/Examples/Send/Send.ino @@ -81,8 +81,10 @@ void loop() // wait a few milliseconds for proper ACK, return true if received static bool waitForAck() { long now = millis(); - while (millis() - now <= ACK_TIME) + do + { if (radio.ACKReceived(GATEWAYID)) return true; + } while (millis() - now <= ACK_TIME); return false; -} +} diff --git a/Examples/Test_2way_gateway/Test_2way_gateway.ino b/Examples/Test_2way_gateway/Test_2way_gateway.ino index 4a2de20..1834964 100644 --- a/Examples/Test_2way_gateway/Test_2way_gateway.ino +++ b/Examples/Test_2way_gateway/Test_2way_gateway.ino @@ -38,8 +38,8 @@ void loop() { digitalWrite(9,1); Serial.print('[');Serial.print(radio.GetSender(), DEC);Serial.print("] "); - for (byte i = 0; i < *radio.DataLen; i++) - Serial.print((char)radio.Data[i]); + for (byte i = 0; i < radio.GetDataLen(); i++) + Serial.print((char)radio.GetData()[i]); if (radio.ACKRequested()) { @@ -67,9 +67,9 @@ void loop() // wait a few milliseconds for proper ACK to me, return true if indeed received static bool waitForAck(byte theNodeID) { long now = millis(); - while (millis() - now <= ACK_TIME) { + do { if (radio.ACKReceived(theNodeID)) return true; - } + } while (millis() - now <= ACK_TIME); return false; } diff --git a/Examples/Test_2way_node/Test_2way_node.ino b/Examples/Test_2way_node/Test_2way_node.ino index beda4c4..b7154e2 100644 --- a/Examples/Test_2way_node/Test_2way_node.ino +++ b/Examples/Test_2way_node/Test_2way_node.ino @@ -55,8 +55,8 @@ void loop() if (radio.CRCPass()) { Serial.print('[');Serial.print(radio.GetSender(), DEC);Serial.print("] "); - for (byte i = 0; i < *radio.DataLen; i++) - Serial.print((char)radio.Data[i]); + for (byte i = 0; i < radio.GetDataLen(); i++) + Serial.print((char)radio.GetData()[i]); if (radio.ACKRequested()) { @@ -95,10 +95,10 @@ void loop() // wait a few milliseconds for proper ACK to me, return true if indeed received static bool waitForAck(byte theNodeID) { long now = millis(); - while (millis() - now <= ACK_TIME) { + do { if (radio.ACKReceived(theNodeID)) return true; - } + } while (millis() - now <= ACK_TIME); return false; } diff --git a/Examples/Test_2way_node_withFlash/Test_2way_node_withFlash.ino b/Examples/Test_2way_node_withFlash/Test_2way_node_withFlash.ino index f50273a..ce2c8c8 100644 --- a/Examples/Test_2way_node_withFlash/Test_2way_node_withFlash.ino +++ b/Examples/Test_2way_node_withFlash/Test_2way_node_withFlash.ino @@ -84,8 +84,8 @@ void loop() if (radio.CRCPass()) { Serial.print('[');Serial.print(radio.GetSender(), DEC);Serial.print("] "); - for (byte i = 0; i < *radio.DataLen; i++) - Serial.print((char)radio.Data[i]); + for (byte i = 0; i < radio.GetDataLen(); i++) + Serial.print((char)radio.GetData()[i]); if (radio.ACKRequested()) { @@ -126,10 +126,10 @@ void loop() // wait a few milliseconds for proper ACK to me, return true if indeed received static bool waitForAck(byte theNodeID) { long now = millis(); - while (millis() - now <= ACK_TIME) { + do { if (radio.ACKReceived(theNodeID)) return true; - } + } while (millis() - now <= ACK_TIME); return false; } diff --git a/Examples/WirelessProgramming_gateway/WirelessProgramming_gateway.ino b/Examples/WirelessProgramming_gateway/WirelessProgramming_gateway.ino index 745f159..acb4608 100644 --- a/Examples/WirelessProgramming_gateway/WirelessProgramming_gateway.ino +++ b/Examples/WirelessProgramming_gateway/WirelessProgramming_gateway.ino @@ -87,8 +87,8 @@ void loop(){ { if (radio.CRCPass()) { - for (byte i = 0; i < *radio.DataLen; i++) - Serial.print((char)radio.Data[i]); + for (byte i = 0; i < radio.GetDataLen(); i++) + Serial.print((char)radio.GetData()[i]); if (radio.ACKRequested()) { diff --git a/Examples/WirelessProgramming_node/WirelessProgramming_node.ino b/Examples/WirelessProgramming_node/WirelessProgramming_node.ino index 583a235..3f91842 100644 --- a/Examples/WirelessProgramming_node/WirelessProgramming_node.ino +++ b/Examples/WirelessProgramming_node/WirelessProgramming_node.ino @@ -113,10 +113,10 @@ void loop(){ if (radio.CRCPass()) { Serial.print("Got ["); - Serial.print(*radio.DataLen); + Serial.print(radio.GetDataLen()); Serial.print("] > "); - for (byte i = 0; i < *radio.DataLen; i++) - Serial.print((char)radio.Data[i], HEX); + for (byte i = 0; i < radio.GetDataLen(); i++) + Serial.print((char)radio.GetData()[i], HEX); Serial.println(); CheckForWirelessHEX(radio, flash, true); diff --git a/RFM12B.cpp b/RFM12B.cpp index 9aca8e4..e0835ba 100644 --- a/RFM12B.cpp +++ b/RFM12B.cpp @@ -5,6 +5,12 @@ #include "RFM12B.h" +#if !defined(RF69_COMPAT) +#define CRC16(A,B) _crc16_update(A,B) +#else +#define CRC16(A,B) _crc_xmodem_update(A,B) +#endif + uint8_t RFM12B::cs_pin; // CS pin for SPI uint8_t RFM12B::nodeID; // address of this node uint8_t RFM12B::networkID; // network group ID @@ -127,7 +133,23 @@ void RFM12B::Initialize(uint8_t ID, uint8_t freqBand, uint8_t networkid, uint8_t XFER(0x0000); XFER(0x80C7 | (freqBand << 4)); // EL (ena TX), EF (ena RX FIFO), 12.0pF +#if !defined(RF69_COMPAT) XFER(0xA640); // Frequency is exactly 434/868/915MHz (whatever freqBand is) +#else + switch (freqBand) // Frequency is exactly 433/868/915Mhz + { + case RF12_433MHZ: + XFER(0xA4B0); + break; + case RF12_915MHZ: + XFER(0xA7D0); + break; + case RF12_868MHZ: + default: + XFER(0xA640); + break; + } +#endif XFER(0xC600 + airKbps); //Air transmission baud rate: 0x08= ~38.31Kbps XFER(0x94A2); // VDI,FAST,134kHz,0dBm,-91dBm XFER(0xC2AC); // AL,!ml,DIG,DQD4 @@ -206,25 +228,39 @@ void RFM12B::InterruptHandler() { if (rxfill == 0 && networkID != 0) rf12_buf[rxfill++] = networkID; - //Serial.print(out, HEX); Serial.print(' '); + //Serial.print(in, HEX); Serial.print(' '); rf12_buf[rxfill++] = in; - rf12_crc = _crc16_update(rf12_crc, in); + rf12_crc = CRC16(rf12_crc, in); +#if !defined(RF69_COMPAT) if (rxfill >= rf12_len + 6 || rxfill >= RF_MAX) +#else + if (rxfill >= rf12_len + 4 || rxfill >= RF_MAX) +#endif XFER(RF_IDLE_MODE); } else { uint8_t out; if (rxstate < 0) { +#if !defined(RF69_COMPAT) uint8_t pos = 4 + rf12_len + rxstate++; +#else + uint8_t pos = 2 + rf12_len + rxstate++; +#endif out = rf12_buf[pos]; - rf12_crc = _crc16_update(rf12_crc, out); + rf12_crc = CRC16(rf12_crc, out); } else switch (rxstate++) { case TXSYN1: out = 0x2D; break; +#if !defined(RF69_COMPAT) case TXSYN2: out = networkID; rxstate = -(3 + rf12_len); break; case TXCRC1: out = rf12_crc; break; case TXCRC2: out = rf12_crc >> 8; break; +#else + case TXSYN2: out = networkID; rxstate = -(1 + rf12_len); break; + case TXCRC1: out = ~rf12_crc >> 8; break; + case TXCRC2: out = ~rf12_crc; break; +#endif case TXDONE: XFER(RF_IDLE_MODE); // fall through default: out = 0xAA; } @@ -256,15 +292,27 @@ void RFM12B::InterruptHandler() { void RFM12B::ReceiveStart() { rxfill = rf12_len = 0; +#if !defined(RF69_COMPAT) rf12_crc = ~0; if (networkID != 0) - rf12_crc = _crc16_update(~0, networkID); + rf12_crc = CRC16(~0, networkID); +#else + rf12_crc = 0x1d0f; +#endif rxstate = TXRECV; XFER(RF_RECEIVER_ON); } +bool RFM12B::ReceiveStarted() { + return rxstate == TXRECV && rxfill > (&rf12_hdr1 - rf12_buf) && (RF12_DESTID == 0 || RF12_DESTID == nodeID); +} + bool RFM12B::ReceiveComplete() { +#if !defined(RF69_COMPAT) if (rxstate == TXRECV && (rxfill >= rf12_len + 6 || rxfill >= RF_MAX)) { +#else + if (rxstate == TXRECV && (rxfill >= rf12_len + 4 || rxfill >= RF_MAX)) { +#endif rxstate = TXIDLE; if (rf12_len > RF12_MAXDATA) rf12_crc = 1; // force bad crc if packet length is invalid @@ -284,7 +332,11 @@ bool RFM12B::ReceiveComplete() { bool RFM12B::CanSend() { // no need to test with interrupts disabled: state TXRECV is only reached // outside of ISR and we don't care if rxfill jumps from 0 to 1 here +#if DISABLE_RSSI_CHECK + if (rxstate == TXRECV && rxfill == 0) { +#else if (rxstate == TXRECV && rxfill == 0 && (Byte(0x00) & (RF_RSSI_BIT >> 8)) == 0) { +#endif XFER(RF_IDLE_MODE); // stop receiver //XXX just in case, don't know whether these RF12 reads are needed! // rf12_XFER(0x0000); // status register @@ -296,17 +348,28 @@ bool RFM12B::CanSend() { } void RFM12B::SendStart(uint8_t toNodeID, bool requestACK, bool sendACK) { +#if !defined(RF69_COMPAT) rf12_hdr1 = toNodeID | (sendACK ? RF12_HDR_ACKCTLMASK : 0); rf12_hdr2 = nodeID | (requestACK ? RF12_HDR_ACKCTLMASK : 0); if (crypter != 0) crypter(true); rf12_crc = ~0; - rf12_crc = _crc16_update(rf12_crc, networkID); + rf12_crc = CRC16(rf12_crc, networkID); +#else + rf12_hdr1 = toNodeID; + rf12_hdr2 = nodeID; + rf12_hdr3 = (sendACK ? 0x80 : 0) | (requestACK ? 0x40 : 0); + if (crypter != 0) crypter(true); + rf12_crc = 0x1d0f; +#endif rxstate = TXPRE1; XFER(RF_XMITTER_ON); // bytes will be fed via interrupts } void RFM12B::SendStart(uint8_t toNodeID, const void* sendBuf, uint8_t sendLen, bool requestACK, bool sendACK, uint8_t waitMode) { rf12_len = sendLen; +#if defined(RF69_COMPAT) + rf12_len += 3; +#endif memcpy((void*) rf12_data, sendBuf, sendLen); SendStart(toNodeID, requestACK, sendACK); SendWait(waitMode); @@ -368,7 +431,11 @@ uint8_t RFM12B::GetSender(){ } volatile uint8_t * RFM12B::GetData() { return rf12_data; } +#if !defined(RF69_COMPAT) uint8_t RFM12B::GetDataLen() { return *DataLen; } +#else +uint8_t RFM12B::GetDataLen() { return *DataLen - 3; } +#endif bool RFM12B::ACKRequested() { return RF12_WANTS_ACK; } /// Should be polled immediately after sending a packet with ACK request @@ -377,8 +444,13 @@ bool RFM12B::ACKReceived(uint8_t fromNodeID) { return CRCPass() && RF12_DESTID == nodeID && (RF12_SOURCEID == fromNodeID || fromNodeID == 0) && +#if !defined(RF69_COMPAT) (rf12_hdr1 & RF12_HDR_ACKCTLMASK) && !(rf12_hdr2 & RF12_HDR_ACKCTLMASK); +#else + (rf12_hdr3 & 0x80) && + !(rf12_hdr3 & 0x40); +#endif return false; } @@ -439,6 +511,9 @@ void RFM12B::CryptFunction(bool sending) { void RFM12B::Encrypt(const uint8_t* key, uint8_t keyLen) { // by using a pointer to CryptFunction, we only link it in when actually used if (key != 0) { +#if defined(RF69_COMPAT) + Serial.println("***** RFM69 compatible encryption not supported ***"); +#endif for (uint8_t i = 0; i < keyLen; ++i) ((uint8_t*) cryptKey)[i] = key[i]; crypter = CryptFunction; diff --git a/RFM12B.h b/RFM12B.h index 424a45e..fdb2bef 100644 --- a/RFM12B.h +++ b/RFM12B.h @@ -6,6 +6,9 @@ #ifndef RFM12B_h #define RFM12B_h +#define RF69_COMPAT 1 +#define DISABLE_RSSI_CHECK 0 + #include #include #include @@ -58,12 +61,18 @@ #define RF12_SOURCEID (rf12_hdr2 & RF12_HDR_IDMASK) // shorthands to simplify sending out the proper ACK when requested +#if !defined(RF69_COMPAT) #define RF12_WANTS_ACK ((rf12_hdr2 & RF12_HDR_ACKCTLMASK) && !(rf12_hdr1 & RF12_HDR_ACKCTLMASK)) +#else +#define RF12_WANTS_ACK ((rf12_hdr3 & 0x40) && !(rf12_hdr1 & 0x80)) +#endif // options for RF12_sleep() #define RF12_SLEEP 0 #define RF12_WAKEUP -1 +#if !defined(RF69_COMPAT) + /// Shorthand for RF12 group byte in rf12_buf. #define rf12_grp rf12_buf[0] /// pointer to 1st header byte in rf12_buf (CTL + DESTINATIONID) @@ -75,6 +84,22 @@ #define rf12_len rf12_buf[3] /// Shorthand for first RF12 data byte in rf12_buf. #define rf12_data (rf12_buf + 4) +#else +/// Shorthand for RF12 group byte in rf12_buf. +#define rf12_grp rf12_buf[0] +/// pointer to 1st header byte in rf12_buf (DESTINATIONID) +#define rf12_hdr1 rf12_buf[2] +/// pointer to 2nd header byte in rf12_buf (SOURCEID) +#define rf12_hdr2 rf12_buf[3] +/// pointer to 3rd header byte in rf12_bug (CTL + ACK) +#define rf12_hdr3 rf12_buf[4] + +/// Shorthand for RF12 length byte in rf12_buf +#define rf12_len rf12_buf[1] +/// Shorthand for first RF12 data byte in rf12_buf. +#define rf12_data (rf12_buf + 5) + +#endif // pin change interrupts are currently only supported on ATmega328's @@ -175,21 +200,28 @@ class RFM12B static void XFER(uint16_t cmd); void SPIInit(); + +#if defined(RF69_COMPAT) + volatile uint8_t* Data; + volatile uint8_t* DataLen; +#endif public: //constructor - RFM12B():Data(rf12_data),DataLen(&rf12_buf[3]){} + RFM12B():Data(rf12_data),DataLen(&rf12_len){} static uint8_t networkID; // network group static uint8_t nodeID; // address of this node static const byte DATAMAXLEN; +#if !defined(RF69_COMPAT) //don't hold the same values in COMPAT mode, so use the accessor functions volatile uint8_t* Data; volatile uint8_t* DataLen; +#endif static void InterruptHandler(); //Defaults: Group: 0xAA=170, transmit power: 0(max), KBPS: 38.3Kbps (air transmission baud - has to be same on all radios in same group) - void Initialize(uint8_t nodeid, uint8_t freqBand, uint8_t groupid=0xAA, uint8_t txPower=0, uint8_t airKbps=0x08, uint8_t lowVoltageThreshold=RF12_2v75); + void Initialize(uint8_t nodeid, uint8_t freqBand, uint8_t groupid=0xAA, uint8_t txPower=0, uint8_t airKbps=0x7F, uint8_t lowVoltageThreshold=RF12_2v75); void SetCS(uint8_t pin); void ReceiveStart(); bool ReceiveComplete(); @@ -215,7 +247,12 @@ class RFM12B bool ACKReceived(uint8_t fromNodeID=0); static void CryptFunction(bool sending); void Encrypt(const uint8_t* key, uint8_t keyLen = 16); +#if !defined(RF69_COMPAT) bool CRCPass() { return rf12_crc == 0; } +#else + bool CRCPass() { return rf12_crc == 0x1d0f; } +#endif + bool ReceiveStarted(); }; #endif