From c127a27446a6c00c6d969d55337b1a5c0511a7a9 Mon Sep 17 00:00:00 2001 From: jgromes Date: Sun, 10 Feb 2019 11:48:21 +0100 Subject: [PATCH] [CC1101] Implemented interrupt-driven methods --- .../CC1101_Receive_Interrupt.ino | 124 ++++++++++++++++ .../CC1101_Transmit_Interrupt.ino | 97 +++++++++++++ keywords.txt | 2 + src/modules/CC1101.cpp | 136 +++++++++++++++++- src/modules/CC1101.h | 10 ++ 5 files changed, 365 insertions(+), 4 deletions(-) create mode 100644 examples/CC1101/CC1101_Receive_Interrupt/CC1101_Receive_Interrupt.ino create mode 100644 examples/CC1101/CC1101_Transmit_Interrupt/CC1101_Transmit_Interrupt.ino diff --git a/examples/CC1101/CC1101_Receive_Interrupt/CC1101_Receive_Interrupt.ino b/examples/CC1101/CC1101_Receive_Interrupt/CC1101_Receive_Interrupt.ino new file mode 100644 index 00000000..5d0ec8b5 --- /dev/null +++ b/examples/CC1101/CC1101_Receive_Interrupt/CC1101_Receive_Interrupt.ino @@ -0,0 +1,124 @@ +/* + RadioLib CC1101 Receive with Interrupts Example + + This example listens for FSK transmissions and tries to + receive them. Once a packet is received, an interrupt is + triggered. +*/ + +// include the library +#include + +// CC1101 module is in slot A on the shield +CC1101 cc = RadioShield.ModuleA; + +void setup() { + Serial.begin(9600); + + // initialize CC1101 with default settings + Serial.print(F("[CC1101] Initializing ... ")); + // carrier frequency: 868.0 MHz + // bit rate: 4.8 kbps + // Rx bandwidth: 325.0 kHz + // frequency deviation: 48.0 kHz + // sync word: 0xD391 + int state = cc.begin(); + if (state == ERR_NONE) { + Serial.println(F("success!")); + } else { + Serial.print(F("failed, code ")); + Serial.println(state); + while (true); + } + + // set the function that will be called + // when new packet is received + cc.setGdo0Action(setFlag); + + // start listening for packets + Serial.print(F("[CC1101] Starting to listen ... ")); + state = cc.startReceive(); + if (state == ERR_NONE) { + Serial.println(F("success!")); + } else { + Serial.print(F("failed, code ")); + Serial.println(state); + while (true); + } + + // if needed, 'listen' mode can be disabled by calling + // any of the following methods: + // + // cc.standby() + // cc.sleep() + // cc.transmit(); + // cc.receive(); + // cc.scanChannel(); +} + +// flag to indicate that a packet was received +volatile bool receivedFlag = false; + +// disable interrupt when it's not needed +volatile bool enableInterrupt = true; + +// this function is called when a complete packet +// is received by the module +// IMPORTANT: this function MUST be 'void' type +// and MUST NOT have any arguments! +void setFlag(void) { + // check if the interrupt is enabled + if(!enableInterrupt) { + return; + } + + // we got a packet, set the flag + receivedFlag = true; +} + +void loop() { + // check if the flag is set + if(receivedFlag) { + // disable the interrupt service routine while + // processing the data + enableInterrupt = false; + + // reset flag + receivedFlag = false; + + // you can read received data as an Arduino String + String str; + int state = cc.readData(str); + + // you can also read received data as byte array + /* + byte byteArr[8]; + int state = cc.receive(byteArr, 8); + */ + + if (state == ERR_NONE) { + // packet was successfully received + Serial.println("[CC1101] Received packet!"); + + // print data of the packet + Serial.print("[CC1101] Data:\t\t"); + Serial.println(str); + + // print RSSI (Received Signal Strength Indicator) + // of the last received packet + Serial.print("[CC1101] RSSI:\t\t"); + Serial.print(cc.getRSSI()); + Serial.println(" dBm"); + + // print LQI (Link Quality Indicator) + // of the last received packet, lower is better + Serial.print("[CC1101] LQI:\t\t"); + Serial.println(cc.getLQI()); + } + + // we're ready to receive more packets, + // enable interrupt service routine + enableInterrupt = true; + } + +} diff --git a/examples/CC1101/CC1101_Transmit_Interrupt/CC1101_Transmit_Interrupt.ino b/examples/CC1101/CC1101_Transmit_Interrupt/CC1101_Transmit_Interrupt.ino new file mode 100644 index 00000000..cb0914f3 --- /dev/null +++ b/examples/CC1101/CC1101_Transmit_Interrupt/CC1101_Transmit_Interrupt.ino @@ -0,0 +1,97 @@ +/* + RadioLib CC1101 Transmit with Interrupts Example + + This example transmits FSK packets with one second delays + between them. Each packet contains up to 64 bytes + of data, in the form of: + - Arduino String + - null-terminated char array (C-string) + - arbitrary binary data (byte array) +*/ + +// include the library +#include + +// CC1101 module is in slot A on the shield +CC1101 cc = RadioShield.ModuleA; + +void setup() { + Serial.begin(9600); + + // initialize CC1101 with default settings + Serial.print(F("[CC1101] Initializing ... ")); + // carrier frequency: 868.0 MHz + // bit rate: 4.8 kbps + // Rx bandwidth: 325.0 kHz + // frequency deviation: 48.0 kHz + // sync word: 0xD391 + int state = cc.begin(); + if (state == ERR_NONE) { + Serial.println(F("success!")); + } else { + Serial.print(F("failed, code ")); + Serial.println(state); + while (true); + } + + // set the function that will be called + // when packet transmission is finished + cc.setGdo0Action(setFlag); + + // start transmitting the first packet + Serial.print(F("[CC1101] Sending first packet ... ")); + + // you can transmit C-string or Arduino string up to + // 64 characters long + state = cc.startTransmit("Hello World!"); + + // you can also transmit byte array up to 64 bytes long + /* + byte byteArr[] = {0x01, 0x23, 0x45, 0x56, + 0x78, 0xAB, 0xCD, 0xEF}; + state = cc.transmit(byteArr, 8); + */ + + if (state != ERR_NONE) { + Serial.print(F("failed, code ")); + Serial.println(state); + } +} + +// flag to indicate that a packet was received +volatile bool transmittedFlag = false; + +void setFlag(void) { + // packet transmission is finished, set the flag + transmittedFlag = true; +} + +void loop() { + // check if the previous transmission finished + if(transmittedFlag) { + Serial.println(F("[CC1101] Packet transmission finished!")); + + // wait one second before next transmission + delay(1000); + + // send another packet + Serial.print(F("[CC1101] Sending another packet ... ")); + + // you can transmit C-string or Arduino string up to + // 64 characters long + int state = cc.startTransmit("Hello World!"); + + // you can also transmit byte array up to 256 bytes long + /* + byte byteArr[] = {0x01, 0x23, 0x45, 0x56, + 0x78, 0xAB, 0xCD, 0xEF}; + int state = cc.transmit(byteArr, 8); + */ + + if (state != ERR_NONE) { + Serial.print(F("failed, code ")); + Serial.println(state); + } + } + +} diff --git a/keywords.txt b/keywords.txt index cf14ef4a..fd020ec1 100644 --- a/keywords.txt +++ b/keywords.txt @@ -89,6 +89,8 @@ setAmbientTemperature KEYWORD2 # CC1101-specific getLQI KEYWORD2 +setGdo0Action KEYWORD2 +setGdo1Action KEYWORD2 # ESP8266 join KEYWORD2 diff --git a/src/modules/CC1101.cpp b/src/modules/CC1101.cpp index 82095294..cf60e02a 100644 --- a/src/modules/CC1101.cpp +++ b/src/modules/CC1101.cpp @@ -93,8 +93,14 @@ int16_t CC1101::transmit(uint8_t* data, size_t len, uint8_t addr) { // set mode to standby standby(); + // flush Tx FIFO + SPIsendCommand(CC1101_CMD_FLUSH_TX); + // set GDO0 mapping - SPIsetRegValue(CC1101_REG_IOCFG0, CC1101_GDOX_SYNC_WORD_SENT_OR_RECEIVED); + int state = SPIsetRegValue(CC1101_REG_IOCFG0, CC1101_GDOX_SYNC_WORD_SENT_OR_RECEIVED); + if(state != ERR_NONE) { + return(state); + } // write packet length SPIwriteRegister(CC1101_REG_FIFO, len); @@ -117,7 +123,7 @@ int16_t CC1101::transmit(uint8_t* data, size_t len, uint8_t addr) { // flush Tx FIFO SPIsendCommand(CC1101_CMD_FLUSH_TX); - return(ERR_NONE); + return(state); } int16_t CC1101::receive(String& str, size_t len) { @@ -142,7 +148,10 @@ int16_t CC1101::receive(uint8_t* data, size_t len) { SPIsendCommand(CC1101_CMD_FLUSH_RX); // set GDO0 mapping - SPIsetRegValue(CC1101_REG_IOCFG0, CC1101_GDOX_SYNC_WORD_SENT_OR_RECEIVED); + int state = SPIsetRegValue(CC1101_REG_IOCFG0, CC1101_GDOX_SYNC_WORD_SENT_OR_RECEIVED); + if(state != ERR_NONE) { + return(state); + } // set mode to receive SPIsendCommand(CC1101_CMD_RX); @@ -188,7 +197,7 @@ int16_t CC1101::receive(uint8_t* data, size_t len) { return(ERR_CRC_MISMATCH); } - return(ERR_NONE); + return(state); } int16_t CC1101::standby() { @@ -229,6 +238,125 @@ int16_t CC1101::receiveDirect() { return(ERR_NONE); } +void CC1101::setGdo0Action(void (*func)(void), uint8_t dir) { + attachInterrupt(digitalPinToInterrupt(_mod->getInt0()), func, dir); +} + +void CC1101::setGdo1Action(void (*func)(void), uint8_t dir) { + attachInterrupt(digitalPinToInterrupt(_mod->getInt0()), func, dir); +} + +int16_t CC1101::startTransmit(String& str, uint8_t addr) { + return(CC1101::startTransmit(str.c_str(), addr)); +} + +int16_t CC1101::startTransmit(const char* str, uint8_t addr) { + return(CC1101::startTransmit((uint8_t*)str, strlen(str), addr)); +} + +int16_t CC1101::startTransmit(uint8_t* data, size_t len, uint8_t addr) { + // check packet length + if(len > 63) { + return(ERR_PACKET_TOO_LONG); + } + + // set mode to standby + standby(); + + // flush Tx FIFO + SPIsendCommand(CC1101_CMD_FLUSH_TX); + + // set GDO0 mapping + int state = SPIsetRegValue(CC1101_REG_IOCFG0, CC1101_GDOX_SYNC_WORD_SENT_OR_RECEIVED); + if(state != ERR_NONE) { + return(state); + } + + // write packet length + SPIwriteRegister(CC1101_REG_FIFO, len); + + // write packet to FIFO + SPIwriteRegisterBurst(CC1101_REG_FIFO, data, len); + + // set mode to transmit + SPIsendCommand(CC1101_CMD_TX); + + return(state); +} + +int16_t CC1101::startReceive() { + // set mode to standby + standby(); + + // flush Rx FIFO + SPIsendCommand(CC1101_CMD_FLUSH_RX); + + // set GDO0 mapping + int state = SPIsetRegValue(CC1101_REG_IOCFG0, CC1101_GDOX_SYNC_WORD_SENT_OR_RECEIVED); + if(state != ERR_NONE) { + return(state); + } + + // set mode to receive + SPIsendCommand(CC1101_CMD_RX); + + return(state); +} + +int16_t CC1101::readData(String& str, size_t len) { + // create temporary array to store received data + char* data = new char[len]; + int16_t state = CC1101::readData((uint8_t*)data, len); + + // if packet was received successfully, copy data into String + if(state == ERR_NONE) { + str = String(data); + } + + delete[] data; + return(state); +} + +int16_t CC1101::readData(uint8_t* data, size_t len) { + // get packet length + size_t length = SPIreadRegister(CC1101_REG_RXBYTES) - 2; + + // read packet data + if(len == 0) { + // argument len equal to zero indicates String call, which means dynamically allocated data array + // dispose of the original and create a new one + delete[] data; + data = new uint8_t[length + 1]; + } + SPIreadRegisterBurst(CC1101_REG_FIFO, length, data); + + // read RSSI byte + _rawRSSI = SPIgetRegValue(CC1101_REG_FIFO); + + // read LQI and CRC byte + uint8_t val = SPIgetRegValue(CC1101_REG_FIFO); + _rawLQI = val & 0x7F; + + // add terminating null + if(len == 0) { + data[length] = 0; + } + + // flush Rx FIFO + SPIsendCommand(CC1101_CMD_FLUSH_RX); + + // set mode to receive + SPIsendCommand(CC1101_CMD_RX); + + // check CRC + if((val & 0b10000000) == 0b00000000) { + return(ERR_CRC_MISMATCH); + } + + return(ERR_NONE); +} + + int16_t CC1101::setFrequency(float freq) { // check allowed frequency range if(!(((freq > 300.0) && (freq < 348.0)) || diff --git a/src/modules/CC1101.h b/src/modules/CC1101.h index 479af514..e7d637c6 100644 --- a/src/modules/CC1101.h +++ b/src/modules/CC1101.h @@ -510,6 +510,16 @@ class CC1101: public PhysicalLayer { int16_t transmitDirect(uint32_t FRF = 0); int16_t receiveDirect(); + // interrupt methods + void setGdo0Action(void (*func)(void), uint8_t dir = FALLING); + void setGdo1Action(void (*func)(void), uint8_t dir = FALLING); + int16_t startTransmit(String& str, uint8_t addr = 0); + int16_t startTransmit(const char* str, uint8_t addr = 0); + int16_t startTransmit(uint8_t* data, size_t len, uint8_t addr = 0); + int16_t startReceive(); + int16_t readData(String& str, size_t len = 0); + int16_t readData(uint8_t* data, size_t len); + // configuration methods int16_t setFrequency(float freq); int16_t setBitRate(float br);