diff --git a/src/modules/CC1101.cpp b/src/modules/CC1101.cpp index c3be390a..1e455d6c 100644 --- a/src/modules/CC1101.cpp +++ b/src/modules/CC1101.cpp @@ -9,7 +9,7 @@ int16_t CC1101::begin(float freq, float br, float rxBw, float freqDev, int8_t po _mod->SPIreadCommand = CC1101_CMD_READ; _mod->SPIwriteCommand = CC1101_CMD_WRITE; _mod->init(USE_SPI, INT_0); - + // try to find the CC1101 chip uint8_t i = 0; bool flagFound = false; @@ -22,7 +22,7 @@ int16_t CC1101::begin(float freq, float br, float rxBw, float freqDev, int8_t po Serial.print(F("CC1101 not found! (")); Serial.print(i + 1); Serial.print(F(" of 10 tries) CC1101_REG_VERSION == ")); - + char buffHex[7]; sprintf(buffHex, "0x%04X", version); Serial.print(buffHex); @@ -33,7 +33,7 @@ int16_t CC1101::begin(float freq, float br, float rxBw, float freqDev, int8_t po i++; } } - + if(!flagFound) { DEBUG_PRINTLN(F("No CC1101 found!")); SPI.end(); @@ -41,156 +41,83 @@ int16_t CC1101::begin(float freq, float br, float rxBw, float freqDev, int8_t po } else { DEBUG_PRINTLN(F("Found CC1101! (match by CC1101_REG_VERSION == 0x14)")); } - + // configure settings not accessible by API int16_t state = config(); if(state != ERR_NONE) { return(state); } - + // configure publicly accessible settings state = setFrequency(freq); if(state != ERR_NONE) { return(state); } - + state = setBitRate(br); if(state != ERR_NONE) { return(state); } - + state = setRxBandwidth(rxBw); if(state != ERR_NONE) { return(state); } - + state = setFrequencyDeviation(freqDev); if(state != ERR_NONE) { return(state); } - + state = setOutputPower(power); if(state != ERR_NONE) { return(state); } - + // flush FIFOs SPIsendCommand(CC1101_CMD_FLUSH_RX); SPIsendCommand(CC1101_CMD_FLUSH_TX); - + return(state); } int16_t CC1101::transmit(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); + // start transmission + int16_t state = startTransmit(data, len, addr); if(state != ERR_NONE) { return(state); } - - // write packet length - SPIwriteRegister(CC1101_REG_FIFO, len); - - // check address filtering - uint8_t filter = SPIgetRegValue(CC1101_REG_PKTCTRL1, 1, 0); - if(filter != CC1101_ADR_CHK_NONE) { - SPIwriteRegister(CC1101_REG_FIFO, addr); - } - - // write packet to FIFO - SPIwriteRegisterBurst(CC1101_REG_FIFO, data, len); - - // set mode to transmit - SPIsendCommand(CC1101_CMD_TX); - + // wait for transmission start while(!digitalRead(_mod->getInt0())); - + // wait for transmission end while(digitalRead(_mod->getInt0())); - + // set mode to standby standby(); - + // flush Tx FIFO SPIsendCommand(CC1101_CMD_FLUSH_TX); - + return(state); } int16_t CC1101::receive(uint8_t* data, size_t len) { - // 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); + // start reception + int16_t state = startReceive(); if(state != ERR_NONE) { return(state); } - - // set mode to receive - SPIsendCommand(CC1101_CMD_RX); - + // wait for sync word while(!digitalRead(_mod->getInt0())); - + // wait for packet end while(digitalRead(_mod->getInt0())); - - // get packet length - size_t length = SPIreadRegister(CC1101_REG_RXBYTES) - 2; - - // check address filtering - uint8_t filter = SPIgetRegValue(CC1101_REG_PKTCTRL1, 1, 0); - if(filter != CC1101_ADR_CHK_NONE) { - SPIreadRegister(CC1101_REG_FIFO); - } // 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 - data[length] = 0; - - // flush Rx FIFO - SPIsendCommand(CC1101_CMD_FLUSH_RX); - - // set mode to standby - standby(); - - // check CRC - if((val & 0b10000000) == 0b00000000) { - return(ERR_CRC_MISMATCH); - } - - return(state); + return(readData(data, len)); } int16_t CC1101::standby() { @@ -204,16 +131,16 @@ int16_t CC1101::transmitDirect(uint32_t FRF) { SPIwriteRegister(CC1101_REG_FREQ2, (FRF & 0xFF0000) >> 16); SPIwriteRegister(CC1101_REG_FREQ1, (FRF & 0x00FF00) >> 8); SPIwriteRegister(CC1101_REG_FREQ0, FRF & 0x0000FF); - + SPIsendCommand(CC1101_CMD_TX); } - + // activate direct mode int16_t state = directMode(); if(state != ERR_NONE) { return(state); } - + // start transmitting SPIsendCommand(CC1101_CMD_TX); return(state); @@ -225,7 +152,7 @@ int16_t CC1101::receiveDirect() { if(state != ERR_NONE) { return(state); } - + // start receiving SPIsendCommand(CC1101_CMD_RX); return(ERR_NONE); @@ -239,87 +166,65 @@ void CC1101::setGdo2Action(void (*func)(void), uint8_t dir) { attachInterrupt(digitalPinToInterrupt(_mod->getInt1()), 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); - + // check address filtering uint8_t filter = SPIgetRegValue(CC1101_REG_PKTCTRL1, 1, 0); if(filter != CC1101_ADR_CHK_NONE) { SPIwriteRegister(CC1101_REG_FIFO, addr); } - + // 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; - + // check address filtering uint8_t filter = SPIgetRegValue(CC1101_REG_PKTCTRL1, 1, 0); if(filter != CC1101_ADR_CHK_NONE) { @@ -334,34 +239,31 @@ int16_t CC1101::readData(uint8_t* data, size_t len) { 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; - } - + data[length] = 0; + // flush Rx FIFO SPIsendCommand(CC1101_CMD_FLUSH_RX); - - // set mode to receive - SPIsendCommand(CC1101_CMD_RX); - + + // set mode to standby + standby(); + // 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)) || @@ -369,21 +271,21 @@ int16_t CC1101::setFrequency(float freq) { ((freq > 779.0) && (freq < 928.0)))) { return(ERR_INVALID_FREQUENCY); } - + // set mode to standby SPIsendCommand(CC1101_CMD_IDLE); - + //set carrier frequency uint32_t base = 1; uint32_t FRF = (freq * (base << 16)) / 26.0; int16_t state = SPIsetRegValue(CC1101_REG_FREQ2, (FRF & 0xFF0000) >> 16, 7, 0); state |= SPIsetRegValue(CC1101_REG_FREQ1, (FRF & 0x00FF00) >> 8, 7, 0); state |= SPIsetRegValue(CC1101_REG_FREQ0, FRF & 0x0000FF, 7, 0); - + if(state == ERR_NONE) { _freq = freq; } - + return(state); } @@ -392,15 +294,15 @@ int16_t CC1101::setBitRate(float br) { if(!((br >= 0.025) && (br <= 600.0))) { return(ERR_INVALID_BIT_RATE); } - + // set mode to standby SPIsendCommand(CC1101_CMD_IDLE); - + // calculate exponent and mantisa values uint8_t e = 0; uint8_t m = 0; getExpMant(br * 1000.0, 256, 28, 14, e, m); - + // set bit rate value int16_t state = SPIsetRegValue(CC1101_REG_MDMCFG4, e, 3, 0); state |= SPIsetRegValue(CC1101_REG_MDMCFG3, m); @@ -412,10 +314,10 @@ int16_t CC1101::setRxBandwidth(float rxBw) { if(!((rxBw >= 58) && (rxBw <= 812))) { return(ERR_INVALID_RX_BANDWIDTH); } - + // set mode to standby SPIsendCommand(CC1101_CMD_IDLE); - + // calculate exponent and mantisa values for(int8_t e = 3; e >= 0; e--) { for(int8_t m = 3; m >= 0; m --) { @@ -426,7 +328,7 @@ int16_t CC1101::setRxBandwidth(float rxBw) { } } } - + return(ERR_UNKNOWN); } @@ -442,15 +344,15 @@ int16_t CC1101::setFrequencyDeviation(float freqDev) { if(!((freqDev >= 1.587) && (freqDev <= 380.8))) { return(ERR_INVALID_FREQUENCY_DEVIATION); } - + // set mode to standby SPIsendCommand(CC1101_CMD_IDLE); - + // calculate exponent and mantisa values uint8_t e = 0; uint8_t m = 0; getExpMant(freqDev * 1000.0, 8, 17, 7, e, m); - + // set frequency deviation value int16_t state = SPIsetRegValue(CC1101_REG_DEVIATN, (e << 4), 6, 4); state |= SPIsetRegValue(CC1101_REG_DEVIATN, m, 2, 0); @@ -480,7 +382,7 @@ int16_t CC1101::setOutputPower(int8_t power) { // 915 MHz f = 3; } - + // get raw power setting uint8_t paTable[8][4] = {{0x12, 0x12, 0x03, 0x03}, {0x0D, 0x0E, 0x0F, 0x0E}, @@ -520,7 +422,7 @@ int16_t CC1101::setOutputPower(int8_t power) { default: return(ERR_INVALID_OUTPUT_POWER); } - + // write raw power setting return(SPIsetRegValue(CC1101_REG_PATABLE, powerRaw)); } @@ -535,7 +437,7 @@ int16_t CC1101::setNodeAddress(uint8_t nodeAddr, uint8_t numBroadcastAddrs) { if(state != ERR_NONE) { return(state); } - + // set node address return(SPIsetRegValue(CC1101_REG_ADDR, nodeAddr)); } @@ -546,7 +448,7 @@ int16_t CC1101::disableAddressFiltering() { if(state != ERR_NONE) { return(state); } - + // set node address to default (0x00) return(SPIsetRegValue(CC1101_REG_ADDR, 0x00)); } @@ -566,31 +468,31 @@ uint8_t CC1101::getLQI() { } int16_t CC1101::config() { - // enable automatic frequency synthesizer calibration + // enable automatic frequency synthesizer calibration int16_t state = SPIsetRegValue(CC1101_REG_MCSM0, CC1101_FS_AUTOCAL_IDLE_TO_RXTX, 5, 4); if(state != ERR_NONE) { return(state); } - + // set packet mode - state = SPIsetRegValue(CC1101_REG_PKTCTRL1, CC1101_CRC_AUTOFLUSH_OFF | CC1101_APPEND_STATUS_ON | CC1101_ADR_CHK_NONE, 3, 0); + state = SPIsetRegValue(CC1101_REG_PKTCTRL1, CC1101_CRC_AUTOFLUSH_OFF | CC1101_APPEND_STATUS_ON | CC1101_ADR_CHK_NONE, 3, 0); state |= SPIsetRegValue(CC1101_REG_PKTCTRL0, CC1101_WHITE_DATA_OFF | CC1101_PKT_FORMAT_NORMAL, 6, 4); state |= SPIsetRegValue(CC1101_REG_PKTCTRL0, CC1101_CRC_ON | CC1101_LENGTH_CONFIG_VARIABLE, 2, 0); if(state != ERR_NONE) { return(state); } - + return(state); } int16_t CC1101::directMode() { // set mode to standby SPIsendCommand(CC1101_CMD_IDLE); - + // set GDO0 and GDO2 mapping int16_t state = SPIsetRegValue(CC1101_REG_IOCFG0, CC1101_GDOX_SERIAL_CLOCK , 5, 0); state |= SPIsetRegValue(CC1101_REG_IOCFG2, CC1101_GDOX_SERIAL_DATA_SYNC , 5, 0); - + // set continuous mode state |= SPIsetRegValue(CC1101_REG_PKTCTRL0, CC1101_PKT_FORMAT_SYNCHRONOUS, 5, 4); return(state); @@ -599,37 +501,35 @@ int16_t CC1101::directMode() { void CC1101::getExpMant(float target, uint16_t mantOffset, uint8_t divExp, uint8_t expMax, uint8_t& exp, uint8_t& mant) { // get table origin point (exp = 0, mant = 0) float origin = (mantOffset * CC1101_CRYSTAL_FREQ * 1000000.0)/((uint32_t)1 << divExp); - + // iterate over possible exponent values for(int8_t e = expMax; e >= 0; e--) { // get table column start value (exp = e, mant = 0); float intervalStart = ((uint32_t)1 << e) * origin; - + // check if target value is in this column if(target >= intervalStart) { // save exponent value exp = e; - + // calculate size of step between table rows float stepSize = intervalStart/(float)mantOffset; - + // get target point position (exp = e, mant = m) mant = ((target - intervalStart) / stepSize); - + // we only need the first match, terminate return; } } } - - int16_t CC1101::SPIgetRegValue(uint8_t reg, uint8_t msb, uint8_t lsb) { // status registers require special command if(reg > CC1101_REG_TEST0) { reg |= CC1101_CMD_ACCESS_STATUS_REG; } - + return(_mod->SPIgetRegValue(reg, msb, lsb)); } @@ -638,7 +538,7 @@ int16_t CC1101::SPIsetRegValue(uint8_t reg, uint8_t value, uint8_t msb, uint8_t if(reg > CC1101_REG_TEST0) { reg |= CC1101_CMD_ACCESS_STATUS_REG; } - + return(_mod->SPIsetRegValue(reg, value, msb, lsb, checkInterval)); } @@ -660,7 +560,7 @@ void CC1101::SPIwriteRegister(uint8_t reg, uint8_t data) { if(reg > CC1101_REG_TEST0) { reg |= CC1101_CMD_ACCESS_STATUS_REG; } - + return(_mod->SPIwriteRegister(reg, data)); } diff --git a/src/modules/CC1101.h b/src/modules/CC1101.h index 82ac04c3..94285ec5 100644 --- a/src/modules/CC1101.h +++ b/src/modules/CC1101.h @@ -139,9 +139,9 @@ #define CC1101_GDOX_CLK_256 0x26 // 5 0 256 Hz clock #define CC1101_GDOX_CLK_32K 0x27 // 5 0 32 kHz clock #define CC1101_GDOX_CHIP_RDYN 0x29 // 5 0 (default for GDO2) -#define CC1101_GDOX_XOSC_STABLE 0x2B // 5 0 +#define CC1101_GDOX_XOSC_STABLE 0x2B // 5 0 #define CC1101_GDOX_HIGH_Z 0x2E // 5 0 high impedance state (default for GDO1) -#define CC1101_GDOX_HW_TO_0 0x2F // 5 0 +#define CC1101_GDOX_HW_TO_0 0x2F // 5 0 #define CC1101_GDOX_CLOCK_XOSC_1 0x30 // 5 0 crystal oscillator clock: f = f(XOSC)/1 #define CC1101_GDOX_CLOCK_XOSC_1_5 0x31 // 5 0 f = f(XOSC)/1.5 #define CC1101_GDOX_CLOCK_XOSC_2 0x32 // 5 0 f = f(XOSC)/2 @@ -166,7 +166,7 @@ #define CC1101_RX_ATTEN_6_DB 0b00010000 // 5 4 6 dB #define CC1101_RX_ATTEN_12_DB 0b00100000 // 5 4 12 dB #define CC1101_RX_ATTEN_18_DB 0b00110000 // 5 4 18 dB -#define CC1101_FIFO_THR 0b00000111 // 5 4 Rx FIFO threshold [bytes] = CC1101_FIFO_THR * 4; Tx FIFO threshold [bytes] = 65 - (CC1101_FIFO_THR * 4) +#define CC1101_FIFO_THR 0b00000111 // 5 4 Rx FIFO threshold [bytes] = CC1101_FIFO_THR * 4; Tx FIFO threshold [bytes] = 65 - (CC1101_FIFO_THR * 4) // CC1101_REG_SYNC1 #define CC1101_SYNC_WORD_MSB 0xD3 // 7 0 sync word MSB @@ -227,7 +227,7 @@ #define CC1101_DRATE_M 0x22 // 7 0 default value for 26 MHz crystal: 115 051 Baud // CC1101_REG_MDMCFG2 -#define CC1101_DEM_DCFILT_OFF 0b10000000 // 7 7 digital DC filter: disabled +#define CC1101_DEM_DCFILT_OFF 0b10000000 // 7 7 digital DC filter: disabled #define CC1101_DEM_DCFILT_ON 0b00000000 // 7 7 enabled - only for data rates above 250 kBaud (default) #define CC1101_MOD_FORMAT_2_FSK 0b00000000 // 6 4 modulation format: 2-FSK (default) #define CC1101_MOD_FORMAT_GFSK 0b00010000 // 6 4 GFSK @@ -482,7 +482,7 @@ // CC1101_REG_WORTIME1 + REG_WORTIME0 #define CC1101_WORTIME_MSB 0x00 // 7 0 WOR timer value -#define CC1101_WORTIME_LSB 0x00 // 7 0 +#define CC1101_WORTIME_LSB 0x00 // 7 0 // CC1101_REG_PKTSTATUS #define CC1101_CRC_OK 0b10000000 // 7 7 CRC check passed @@ -499,10 +499,12 @@ class CC1101: public PhysicalLayer { // introduce PhysicalLayer overloads using PhysicalLayer::transmit; using PhysicalLayer::receive; - + using PhysicalLayer::startTransmit; + using PhysicalLayer::readData; + // constructor CC1101(Module* module); - + // basic methods int16_t begin(float freq = 868.0, float br = 4.8, float rxBw = 325.0, float freqDev = 48.0, int8_t power = 0); int16_t transmit(uint8_t* data, size_t len, uint8_t addr = 0); @@ -510,17 +512,14 @@ class CC1101: public PhysicalLayer { int16_t standby(); int16_t transmitDirect(uint32_t FRF = 0); int16_t receiveDirect(); - + // interrupt methods void setGdo0Action(void (*func)(void), uint8_t dir = FALLING); void setGdo2Action(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); @@ -532,18 +531,18 @@ class CC1101: public PhysicalLayer { int16_t disableAddressFiltering(); float getRSSI(); uint8_t getLQI(); - + private: Module* _mod; - + float _freq; uint8_t _rawRSSI; uint8_t _rawLQI; - + int16_t config(); int16_t directMode(); void getExpMant(float target, uint16_t mantOffset, uint8_t divExp, uint8_t expMax, uint8_t& exp, uint8_t& mant); - + // SPI read overrides to set bit for burst write and status registers access int16_t SPIgetRegValue(uint8_t reg, uint8_t msb = 7, uint8_t lsb = 0); int16_t SPIsetRegValue(uint8_t reg, uint8_t value, uint8_t msb = 7, uint8_t lsb = 0, uint8_t checkInterval = 2); @@ -551,7 +550,7 @@ class CC1101: public PhysicalLayer { uint8_t SPIreadRegister(uint8_t reg); void SPIwriteRegisterBurst(uint8_t reg, uint8_t* data, size_t len); void SPIwriteRegister(uint8_t reg, uint8_t data); - + void SPIsendCommand(uint8_t cmd); };