/* * Author: Klusjesman, modified bij supersjimmie for Arduino/ESP8266 */ #include "CC1101.h" // default constructor CC1101::CC1101(int8_t CSpin, int8_t MISOpin, SPIClass& spi) : _CSpin(CSpin), _MISOpin(MISOpin), _spi(spi) { // SPI.begin(); // Done already by ESPEasy pinMode(_CSpin, OUTPUT); } // CC1101 // default destructor CC1101::~CC1101() {} // ~CC1101 /***********************/ // SPI helper functions select() and deselect() inline void CC1101::select(void) { digitalWrite(_CSpin, LOW); } inline void CC1101::deselect(void) { digitalWrite(_CSpin, HIGH); } void CC1101::spi_waitMiso() { uint32_t maxWait = millis() + ITHO_MAX_WAIT; // Wait for max. x seconds while (digitalRead(_MISOpin) == HIGH && millis() < maxWait) { yield(); } } void CC1101::init() { reset(); } void CC1101::reset() { deselect(); delayMicroseconds(5); select(); delayMicroseconds(10); deselect(); delayMicroseconds(45); select(); spi_waitMiso(); _spi.transfer(CC1101_SRES); delay(10); spi_waitMiso(); deselect(); } uint8_t CC1101::writeCommand(uint8_t command) { uint8_t result; select(); spi_waitMiso(); result = _spi.transfer(command); deselect(); return result; } void CC1101::writeRegister(uint8_t address, uint8_t data) { select(); spi_waitMiso(); _spi.transfer(address); _spi.transfer(data); deselect(); } uint8_t CC1101::readRegister(uint8_t address) { uint8_t val; select(); spi_waitMiso(); _spi.transfer(address); val = _spi.transfer(0); deselect(); return val; } uint8_t CC1101::readRegisterMedian3(uint8_t address) { uint8_t val, val1, val2, val3; select(); spi_waitMiso(); _spi.transfer(address); val1 = _spi.transfer(0); _spi.transfer(address); val2 = _spi.transfer(0); _spi.transfer(address); val3 = _spi.transfer(0); deselect(); // reverse sort (largest in val1) because this is te expected order for TX_BUFFER if (val3 > val2) { val = val3; val3 = val2; val2 = val; } // Swap(val3,val2) if (val2 > val1) { val = val2; val2 = val1, val1 = val; } // Swap(val2,val1) if (val3 > val2) { val = val3; val3 = val2, val2 = val; } // Swap(val3,val2) return val2; } /* Known SPI/26MHz synchronization bug (see CC1101 errata) This issue affects the following registers: SPI status byte (fields STATE and FIFO_BYTES_AVAILABLE), FREQEST or RSSI while the receiver is active, MARCSTATE at any time other than an IDLE radio state, RXBYTES when receiving or TXBYTES when transmitting, and WORTIME1/WORTIME0 at any time.*/ // uint8_t CC1101::readRegisterWithSyncProblem(uint8_t address, uint8_t registerType) uint8_t /* ICACHE_RAM_ATTR */ CC1101::readRegisterWithSyncProblem(uint8_t address, uint8_t registerType) { uint8_t value1, value2; value1 = readRegister(address | registerType); // if two consecutive reads gives us the same result then we know we are ok do { value2 = value1; value1 = readRegister(address | registerType); } while (value1 != value2); return value1; } // registerType = CC1101_CONFIG_REGISTER or CC1101_STATUS_REGISTER uint8_t CC1101::readRegister(uint8_t address, uint8_t registerType) { switch (address) { case CC1101_FREQEST: case CC1101_MARCSTATE: case CC1101_RXBYTES: case CC1101_TXBYTES: case CC1101_WORTIME1: case CC1101_WORTIME0: return readRegisterWithSyncProblem(address, registerType); default: return readRegister(address | registerType); } } void CC1101::writeBurstRegister(uint8_t address, uint8_t *data, uint8_t length) { uint8_t i; select(); spi_waitMiso(); _spi.transfer(address | CC1101_WRITE_BURST); for (i = 0; i < length; i++) { _spi.transfer(pgm_read_byte(&(data[i]))); } deselect(); } void CC1101::readBurstRegister(uint8_t *buffer, uint8_t address, uint8_t length) { uint8_t i; select(); spi_waitMiso(); _spi.transfer(address | CC1101_READ_BURST); for (i = 0; i < length; i++) { buffer[i] = _spi.transfer(0x00); } deselect(); } // wait for fixed length in rx fifo uint8_t CC1101::receiveData(CC1101Packet *packet, uint8_t length) { uint8_t rxBytes = readRegisterWithSyncProblem(CC1101_RXBYTES, CC1101_STATUS_REGISTER); rxBytes = rxBytes & CC1101_BITS_RX_BYTES_IN_FIFO; // check for rx fifo overflow if ((readRegisterWithSyncProblem(CC1101_MARCSTATE, CC1101_STATUS_REGISTER) & CC1101_BITS_MARCSTATE) == CC1101_MARCSTATE_RXFIFO_OVERFLOW) { writeCommand(CC1101_SIDLE); // idle writeCommand(CC1101_SFRX); // flush RX buffer writeCommand(CC1101_SRX); // switch to RX state } else if (rxBytes == length) { readBurstRegister(packet->data, CC1101_RXFIFO, rxBytes); // continue RX writeCommand(CC1101_SIDLE); // idle writeCommand(CC1101_SFRX); // flush RX buffer writeCommand(CC1101_SRX); // switch to RX state packet->length = rxBytes; } else { // empty fifo packet->length = 0; writeCommand(CC1101_SIDLE); // idle writeCommand(CC1101_SFRX); // flush RX buffer writeCommand(CC1101_SRX); // switch to RX state } return packet->length; } // This function is able to send packets bigger then the FIFO size. void CC1101::sendData(CC1101Packet *packet) { uint8_t index = 0; uint8_t txStatus, MarcState; uint8_t length; writeCommand(CC1101_SIDLE); // idle txStatus = readRegisterWithSyncProblem(CC1101_TXBYTES, CC1101_STATUS_REGISTER); // clear TX fifo if needed if (txStatus & CC1101_BITS_TX_FIFO_UNDERFLOW) { writeCommand(CC1101_SIDLE); // idle writeCommand(CC1101_SFTX); // flush TX buffer } writeCommand(CC1101_SIDLE); // idle // determine how many bytes to send length = (packet->length <= CC1101_DATA_LEN ? packet->length : CC1101_DATA_LEN); writeBurstRegister(CC1101_TXFIFO, packet->data, length); writeCommand(CC1101_SIDLE); // start sending packet writeCommand(CC1101_STX); // continue sending when packet is bigger than 64 bytes if (packet->length > CC1101_DATA_LEN) { index += length; // loop until all bytes are transmitted while (index < packet->length) { // check if there is free space in the fifo uint32_t maxWait = millis() + ITHO_MAX_WAIT; // Wait for max. x seconds while ((txStatus = (readRegisterMedian3(CC1101_TXBYTES | CC1101_STATUS_REGISTER) & CC1101_BITS_RX_BYTES_IN_FIFO)) > (CC1101_DATA_LEN - 2) && millis() < maxWait) { } // calculate how many bytes we can send length = (CC1101_DATA_LEN - txStatus); length = ((packet->length - index) < length ? (packet->length - index) : length); // send some more bytes for (int i = 0; i < length; i++) { writeRegister(CC1101_TXFIFO, packet->data[index + i]); } index += length; } } // wait until transmission is finished (TXOFF_MODE is expected to be set to 0/IDLE or TXFIFO_UNDERFLOW) uint32_t maxWait = millis() + ITHO_MAX_WAIT; // Wait for max. x seconds do { MarcState = (readRegisterWithSyncProblem(CC1101_MARCSTATE, CC1101_STATUS_REGISTER) & CC1101_BITS_MARCSTATE); // if (MarcState == CC1101_MARCSTATE_TXFIFO_UNDERFLOW) Serial.print(F("TXFIFO_UNDERFLOW occured in sendData() \n")); } while ((MarcState != CC1101_MARCSTATE_IDLE) && (MarcState != CC1101_MARCSTATE_TXFIFO_UNDERFLOW) && millis() < maxWait); }