uint8_t CC110x::detectBurst(void) { // wake up CC1101 from power down state // 10 7/10 5 in front of the received string; 33 after received string // 10 - 00001010 - sync word found // 7 - 00000111 - GDO0 = 1, GDO2 = 1 // 5 - 00000101 - GDO0 = 1, GDO2 = 1 // 33 - 00100001 - GDO0 = 1, preamble quality reached // 96 - 01100000 - burst sent // 48 - 00110000 - in receive mode // // Status byte table: // 0 current GDO0 value // 1 reserved // 2 GDO2 // 3 sync word found // 4 channel is clear // 5 preamble quality reached // 6 carrier sense // 7 CRC ok // // possible solution for finding a burst is to check for bit 6, carrier sense // set RXTX module in receive mode cc1101_Select(); // select CC1101 wait_Miso(); // wait until MISO goes low cc1101_Deselect(); // deselect CC1101 cmdStrobe(CC1101_SRX); // set RX mode again _delay_ms(3); // wait a short time to set RX mode // todo: check carrier sense for 5ms to avoid wakeup due to normal transmition //Serial << F("rx\n"); // return bitRead(hm.cc.monitorStatus(),6); // return the detected signal return bitRead(monitorStatus(),6); // return the detected signal }
// Reset CC1101 (requires implementation here since microsecond delay can't be done reliably via serial) void resetRf() { cc1101_Deselect(); delayMicroseconds(5); cc1101_Select(); delayMicroseconds(10); cc1101_Deselect(); delayMicroseconds(41); cc1101_Select(); wait_Miso(); SPI.transfer(0x30); // SRES wait_Miso(); cc1101_Deselect(); }
/** * readReg * * Read CC1101 register via SPI * * 'regAddr' Register address * 'regType' Type of register: CC1101_CONFIG_REGISTER or CC1101_STATUS_REGISTER * * Return: * Data byte returned by the CC1101 IC */ byte CC1101_readReg(byte regAddr, byte regType) { byte addr, val; addr = regAddr | regType; cc1101_Select(); // Select CC1101 wait_Miso(); // Wait until MISO goes low // // have to do it twice for some reason, first read fails // spi_send(addr); // Send register address // //val = spi_send(addr); // DSK6713_waitusec(5); // //DSK6713_waitusec(25); // val = spi_send(0x00); // Read result // DSK6713_waitusec(20); // // spi_send(addr); // Send register address // DSK6713_waitusec(5); // val = spi_send(0x00); // Read result // DSK6713_waitusec(20); val = spiReadReg(addr); cc1101_Deselect(); // Deselect CC1101 return val; }
void CC110x::writeBurst(uint8_t regAddr, uint8_t *buf, uint8_t len) { // write multiple registers into the CC1101 IC via SPI cc1101_Select(); // select CC1101 wait_Miso(); // wait until MISO goes low sendSPI(regAddr | WRITE_BURST); // send register address for(uint8_t i=0 ; i<len ; i++) sendSPI(buf[i]); // send value cc1101_Deselect(); // deselect CC1101 }
void CC110x::readBurst(uint8_t *buf, uint8_t regAddr, uint8_t len) { // read burst data from CC1101 via SPI cc1101_Select(); // select CC1101 wait_Miso(); // wait until MISO goes low sendSPI(regAddr | READ_BURST); // send register address for(uint8_t i=0 ; i<len ; i++) buf[i] = sendSPI(0x00); // read result byte by byte cc1101_Deselect(); // deselect CC1101 }
/** * cmdStrobe * * Send command strobe to the CC1101 IC via SPI * * 'cmd' Command strobe */ void CC1101::cmdStrobe(byte cmd) { cc1101_Select(); // Select CC1101 wait_Miso(); // Wait until MISO goes low spi.send(cmd); // Send strobe command cc1101_Deselect(); // Deselect CC1101 }
void CC110x::writeReg(uint8_t regAddr, uint8_t val) { // write single register into the CC1101 IC via SPI cc1101_Select(); // select CC1101 wait_Miso(); // wait until MISO goes low sendSPI(regAddr); // send register address sendSPI(val); // send value cc1101_Deselect(); // deselect CC1101 }
/** * writeReg * * Write single register into the CC1101 IC via SPI * * 'regAddr' Register address * 'value' Value to be writen */ void CC1101::writeReg(byte regAddr, byte value) { cc1101_Select(); // Select CC1101 wait_Miso(); // Wait until MISO goes low spi.send(regAddr); // Send register address spi.send(value); // Send value cc1101_Deselect(); // Deselect CC1101 }
uint8_t CC110x::readReg(uint8_t regAddr, uint8_t regType) { // read CC1101 register via SPI cc1101_Select(); // select CC1101 wait_Miso(); // wait until MISO goes low sendSPI(regAddr | regType); // send register address uint8_t val = sendSPI(0x00); // read result cc1101_Deselect(); // deselect CC1101 return val; }
/* * initialize CC1101 */ void cc1101Init(uint8_t mode100k) { cli(); bitSet(DDR_SPI, PIN_SPI_SS); // set B2(SS) as Output bitSet(DDR_SPI, PIN_SPI_MOSI); // set B3(MOSI) as Output bitClear(DDR_SPI, PIN_SPI_MISO); // set B4(MISO) as Input bitSet(DDR_SPI, PIN_SPI_SCK); // set B5(SCK) as Output bitClear(DDR_GDO0, PIN_GDO0); // set B2(SS) as Input bitSet(PORT_SPI, PIN_SPI_SS); // set SS high bitSet(PORT_SPI, PIN_SPI_SCK); // set SCK high bitClear(PORT_SPI, PIN_SPI_MOSI); // set MOSI high SPCR = _BV(SPE) | _BV(MSTR); // SPI speed = CLK/4 cc1101_Deselect(); // some deselect and selects to initialize the TRX868modul _delay_us(30); cc1101_Select(); _delay_us(30); cc1101_Deselect(); _delay_us(45); cmdStrobe(CC1101_SRES); // send reset _delay_us(100); for (uint8_t i=0; i<sizeof(initVal); i += 2) { // write initialize value to cc1101 writeReg(pgm_read_byte(&initVal[i]), pgm_read_byte(&initVal[i+1])); } if (mode100k) { // switch to 100k mode for (uint8_t i=0; i<sizeof(initValUpdate); i += 2) { // write initialize value to cc1101 writeReg( pgm_read_byte(&initValUpdate[i]), pgm_read_byte(&initValUpdate[i+1]) ); } } cmdStrobe(CC1101_SCAL); // calibrate frequency synthesizer and turn it off _delay_ms(4); do { cmdStrobe(CC1101_SRX); } while (readReg(CC1101_MARCSTATE, CC1101_STATUS) != 0x0D); writeReg(CC1101_PATABLE, PA_MaxPower); // configure PATABLE cmdStrobe(CC1101_SRX); // flush the RX buffer cmdStrobe(CC1101_SWORRST); // reset real time clock _delay_ms(3); sei(); }
/** * reset * * Reset CC1101 */ void CC1101::reset(void) { cc1101_Deselect(); // Deselect CC1101 delayMicroseconds(5); cc1101_Select(); // Select CC1101 delayMicroseconds(10); cc1101_Deselect(); // Deselect CC1101 delayMicroseconds(41); cc1101_Select(); // Select CC1101 wait_Miso(); // Wait until MISO goes low spi.send(CC1101_SRES); // Send reset command strobe wait_Miso(); // Wait until MISO goes low cc1101_Deselect(); // Deselect CC1101 setDefaultRegs(); // Reconfigure CC1101 setRegsFromEeprom(); // Take user settings from EEPROM }
/** * reset * * Reset CC1101 */ void CC1101_reset(void) { cc1101_Deselect(); // Deselect CC1101 DSK6713_waitusec(5); cc1101_Select(); // Select CC1101 DSK6713_waitusec(10); cc1101_Deselect(); // Deselect CC1101 DSK6713_waitusec(41); cc1101_Select(); // Select CC1101 wait_Miso(); // Wait until MISO goes low //spi_send(CC1101_SRES); // Send reset command strobe spiWriteReg(CC1101_SRES,0x00); wait_Miso(); // Wait until MISO goes low cc1101_Deselect(); // Deselect CC1101 CC1101_setDefaultRegs(); // Reconfigure CC1101 //setRegsFromEeprom(); // Take user settings from EEPROM }
/** * readBurstReg * * Read burst data from CC1101 via SPI * * 'buffer' Buffer where to copy the result to * 'regAddr' Register address * 'len' Data length */ void CC1101::readBurstReg(byte * buffer, byte regAddr, byte len) { byte addr, i; addr = regAddr | READ_BURST; cc1101_Select(); // Select CC1101 wait_Miso(); // Wait until MISO goes low spi.send(addr); // Send register address for(i=0 ; i<len ; i++) buffer[i] = spi.send(0x00); // Read result byte by byte cc1101_Deselect(); // Deselect CC1101 }
/** * readReg * * Read CC1101 register via SPI * * 'regAddr' Register address * 'regType' Type of register: CC1101_CONFIG_REGISTER or CC1101_STATUS_REGISTER * * Return: * Data byte returned by the CC1101 IC */ byte CC1101::readReg(byte regAddr, byte regType) { byte addr, val; addr = regAddr | regType; cc1101_Select(); // Select CC1101 wait_Miso(); // Wait until MISO goes low spi.send(addr); // Send register address val = spi.send(0x00); // Read result cc1101_Deselect(); // Deselect CC1101 return val; }
/** * writeBurstReg * * Write multiple registers into the CC1101 IC via SPI * * 'regAddr' Register address * 'buffer' Data to be writen * 'len' Data length */ void CC1101::writeBurstReg(byte regAddr, byte* buffer, byte len) { byte addr, i; addr = regAddr | WRITE_BURST; // Enable burst transfer cc1101_Select(); // Select CC1101 wait_Miso(); // Wait until MISO goes low spi.send(addr); // Send register address for(i=0 ; i<len ; i++) spi.send(buffer[i]); // Send value cc1101_Deselect(); // Deselect CC1101 }
/** * CC1101_writeReg * * Write single register into the CC1101 IC via SPI * * 'regAddr' Register address * 'value' Value to be writen */ void CC1101_writeReg(byte regAddr, byte value) { cc1101_Select(); // Select CC1101 wait_Miso(); // Wait until MISO goes low // // waits are needed since CSn is triggered by GPIO which is not in accordance with SPI peripheral which takes few cycles to shift out after you order it // spi_send(regAddr); // Send register address // DSK6713_waitusec(5); // spi_send(value); // Send value // DSK6713_waitusec(20); spiWriteReg(regAddr, value); cc1101_Deselect(); // Deselect CC1101 }
/** * cmdStrobe * * Send command strobe to the CC1101 IC via SPI * * 'cmd' Command strobe */ void CC1101_cmdStrobe(byte cmd) { cc1101_Select(); // Select CC1101 wait_Miso(); // Wait until MISO goes low // spi_send(cmd); // Send strobe command // // // send again, for some reason first send does not work // DSK6713_waitusec(10); // spi_send(cmd); // Send strobe command // // DSK6713_waitusec(20); spiWriteReg(cmd,0x00); // basically we only need to send 1 byte cc1101_Deselect(); // Deselect CC1101 }
/** * writeBurstReg * * Write multiple registers into the CC1101 IC via SPI * * 'regAddr' Register address * 'buffer' Data to be writen * 'len' Data length */ void CC1101_writeBurstReg(byte regAddr, byte* buffer, byte len) { byte addr, i; addr = regAddr | WRITE_BURST; // Enable burst transfer cc1101_Select(); // Select CC1101 wait_Miso(); // Wait until MISO goes low //spi_send(addr); // Send register address spiWriteAddr(addr); //DSK6713_waitusec(5); for(i=0 ; i<len ; i++) { //spi_send(buffer[i]); // Send value spiWriteData(buffer[i]); //DSK6713_waitusec(10); } //DSK6713_waitusec(20); cc1101_Deselect(); // Deselect CC1101 }
/** * readBurstReg * * Read burst data from CC1101 via SPI * * 'buffer' Buffer where to copy the result to * 'regAddr' Register address * 'len' Data length */ void CC1101_readBurstReg(byte * buffer, byte regAddr, byte len) { byte addr, i; addr = regAddr | READ_BURST; cc1101_Select(); // Select CC1101 wait_Miso(); // Wait until MISO goes low //spi_send(addr); // Send register address spiWriteAddr(addr); //DSK6713_waitusec(5); for(i=0 ; i<len ; i++) { //buffer[i] = spi_send(0x00); // Read result byte by byte buffer[i] = spiReadData(); // Read result byte by byte //DSK6713_waitusec(15); } //DSK6713_waitusec(20); cc1101_Deselect(); // Deselect CC1101 }
void CC110x::cmdStrobe(uint8_t cmd) { // send command strobe to the CC1101 IC via SPI cc1101_Select(); // select CC1101 wait_Miso(); // wait until MISO goes low sendSPI(cmd); // send strobe command cc1101_Deselect(); // deselect CC1101 }
void CC110x::init(void) { // initialize CC1101 #if defined(CC_DBG) Serial << F("CC1101_init: "); #endif pinMode(csPin, OUTPUT); // set pins for SPI communication pinMode(mosiPin, OUTPUT); pinMode(misoPin, INPUT); pinMode(sckPin, OUTPUT); pinMode(gdo0Pin, INPUT); // config GDO0 as input digitalWrite(csPin, HIGH); // SPI init digitalWrite(sckPin, HIGH); digitalWrite(mosiPin, LOW); SPCR = _BV(SPE) | _BV(MSTR); // SPI speed = CLK/4 cc1101_Deselect(); // some deselect and selects to init the TRX868modul _delay_us(5); cc1101_Select(); _delay_us(10); cc1101_Deselect(); _delay_us(41); cmdStrobe(CC1101_SRES); // send reset _delay_ms(10); #if defined(CC_DBG) Serial << F("1"); #endif // define init settings for TRX868 static const uint8_t initVal[] PROGMEM = { CC1101_IOCFG2, 0x2E, // non inverted GDO2, high impedance tri state //CC1101_IOCFG1, 0x2E, (default) // low output drive strength, non inverted GD=1, high impedance tri state CC1101_IOCFG0, 0x06, // packet CRC ok // disable temperature sensor, non inverted GDO0, CC1101_FIFOTHR, 0x0D, // 0 ADC retention, 0 close in RX, TX FIFO = 9 / RX FIFO = 56 byte CC1101_SYNC1, 0xE9, CC1101_SYNC0, 0xCA, CC1101_PKTLEN, 0x3D, // packet length 61 CC1101_PKTCTRL1, 0x0C, // PQT = 0, CRC auto flush = 1, append status = 1, no address check CC1101_FSCTRL1, 0x06, // 868.299866 MHz //CC1101_FREQ2, 0x21, //CC1101_FREQ1, 0x65, //CC1101_FREQ0, 0x6A, // 868.2895508 CC1101_FREQ2, 0x21, CC1101_FREQ1, 0x65, CC1101_FREQ0, 0x50, CC1101_MDMCFG4, 0xC8, CC1101_MDMCFG3, 0x93, CC1101_MDMCFG2, 0x03, CC1101_DEVIATN, 0x34, // 19.042969 kHz CC1101_MCSM2, 0x01, //CC1101_MCSM1, 0x30, (default) // always go into IDLE CC1101_MCSM0, 0x18, CC1101_FOCCFG, 0x16, CC1101_AGCCTRL2, 0x43, //CC1101_WOREVT1, 0x28, // tEVENT0 = 50 ms, RX timeout = 390 us //7CC1101_WOREVT0, 0xA0, //CC1101_WORCTRL, 0xFB, //EVENT1 = 3, WOR_RES = 0 CC1101_FREND1, 0x56, // CC1101_FSCAL1, 0x00, CC1101_FSCAL0, 0x11, CC1101_TEST1, 0x35, CC1101_PATABLE, 0xC3, }; for (uint8_t i=0; i<sizeof(initVal); i+=2) { // write init value to TRX868 writeReg(pgm_read_byte(&initVal[i]), pgm_read_byte(&initVal[i+1])); } #if defined(CC_DBG) Serial << F("2"); #endif cmdStrobe(CC1101_SCAL); // calibrate frequency synthesizer and turn it off while (readReg(CC1101_MARCSTATE, CC1101_STATUS) != 1) { // waits until module gets ready _delay_us(1); #if defined(CC_DBG) Serial << F("."); #endif } #if defined(CC_DBG) Serial << F("3"); #endif writeReg(CC1101_PATABLE, PA_MaxPower); // configure PATABLE cmdStrobe(CC1101_SRX); // flush the RX buffer cmdStrobe(CC1101_SWORRST); // reset real time clock #if defined(CC_DBG) Serial << F(" - ready\n"); #endif }
void loop() { if (Serial.available() > 0) { char inChar = Serial.read(); // Filter all requests by having first char start with '{' and last char with '}' // Prevents serial garbage from affecting the parser (e.g. other app probing all serial ports) if (!isReading) { if (inChar == '{') { isReading = true; } else { return; } } // read incoming serial data: inputBuffer[bufferIndex] = inChar; bufferIndex++; if (bufferIndex == 5) { bufferIndex = 0; } if (inChar == '}') { isReading = false; bufferIndex = 0; if (inputBuffer[4] != '}') { // command is not terminated correctly Serial.print("z0"); } else { byte command = inputBuffer[1]; byte firstParameter = (convertCharToByte(inputBuffer[2]) << 4) | convertCharToByte(inputBuffer[3]); if (command == 'a') { resetRf(); Serial.println("a1"); } else if (command == 'b') { delay(firstParameter); Serial.println("b1"); } else if (command == 'c') { cc1101_Select(); Serial.println("c1"); } else if (command == 'd') { cc1101_Deselect(); Serial.println("d1"); } else if (command == 'e') { wait_Miso(); Serial.println("e1"); } else if (command == 'f') { SPI.transfer(firstParameter); Serial.println("f1"); } else if (command == 'g') { Serial.println("ATMEGA328P PRO MINI 0.1"); } } } } }
void CC110x::init(void) { // initialize CC1101 #if defined(CC_DBG) Serial << F("CC1101_init: "); #endif pinMode(csPin, OUTPUT); // set pins for SPI communication pinMode(mosiPin, OUTPUT); pinMode(misoPin, INPUT); pinMode(sckPin, OUTPUT); pinMode(gdo0Pin, INPUT); // config GDO0 as input digitalWrite(csPin, HIGH); // SPI init digitalWrite(sckPin, HIGH); digitalWrite(mosiPin, LOW); SPCR = _BV(SPE) | _BV(MSTR); // SPI speed = CLK/4 cc1101_Deselect(); // some deselect and selects to init the TRX868modul _delay_us(5); cc1101_Select(); _delay_us(10); cc1101_Deselect(); _delay_us(41); cmdStrobe(CC1101_SRES); // send reset _delay_ms(10); #if defined(CC_DBG) Serial << '1'; #endif static prog_uint8_t initVal[] PROGMEM = { // define init settings for TRX868 0x00, 0x2E, // IOCFG2: tristate // non inverted GDO2, high impedance tri state 0x01, 0x2E, // IOCFG1: tristate // low output drive strength, non inverted GD=1, high impedance tri state 0x02, 0x06, // IOCFG0: packet CRC ok // disable temperature sensor, non inverted GDO0, asserts when a sync word has been sent/received, and de-asserts at the end of the packet. in RX, the pin will also de-assert when a package is discarded due to address or maximum length filtering 0x03, 0x0D, // FIFOTHR: TX:9 / RX:56 // 0 ADC retention, 0 close in RX, TX FIFO = 9 / RX FIFO = 56 byte 0x04, 0xE9, // SYNC1 // Sync word 0x05, 0xCA, // SYNC0 0x06, 0x3D, // PKTLEN(x): 61 // packet length 61 0x07, 0x0C, // PKTCTRL1: // PQT = 0, CRC auto flush = 1, append status = 1, no address check 0x0B, 0x06, // FSCTRL1: // frequency synthesizer control 0x0D, 0x21, // FREQ2 0x0E, 0x65, // FREQ1 0x0F, 0x6A, // FREQ0 0x10, 0xC8, // MDMCFG4 0x11, 0x93, // MDMCFG3 0x12, 0x03, // MDMCFG2 0x15, 0x34, // DEVIATN 0x16, 0x01, // MCSM2 0x17, 0x30, // MCSM1: always go into IDLE 0x18, 0x18, // MCSM0 0x19, 0x16, // FOCCFG 0x1B, 0x43, // AGCTRL2 //0x1E, 0x28, // ..WOREVT1: tEVENT0 = 50 ms, RX timeout = 390 us //0x1F, 0xA0, // ..WOREVT0: //0x20, 0xFB, // ..WORCTRL: EVENT1 = 3, WOR_RES = 0 0x21, 0x56, // FREND1 0x25, 0x00, 0x26, 0x11, // FSCAL0 0x2D, 0x35, // TEST1 0x3E, 0xC3, // ? }; for (uint8_t i=0; i<sizeof(initVal); i++) { // write init value to TRX868 writeReg(pgm_read_byte(&initVal[i++]), pgm_read_byte(&initVal[i])); } #if defined(CC_DBG) Serial << '2'; #endif cmdStrobe(CC1101_SCAL); // calibrate frequency synthesizer and turn it off while (readReg(CC1101_MARCSTATE, CC1101_STATUS) != 1) { // waits until module gets ready _delay_us(1); #if defined(CC_DBG) Serial << '.'; #endif } #if defined(CC_DBG) Serial << '3'; #endif writeReg(CC1101_PATABLE, PA_MaxPower); // configure PATABLE cmdStrobe(CC1101_SRX); // flush the RX buffer cmdStrobe(CC1101_SWORRST); // reset real time clock #if defined(CC_DBG) Serial << F(" - ready\r\n"); #endif }
/** * wakeUp * * Wake up CC1101 from Power Down state */ void CC1101::wakeUp(void) { cc1101_Select(); // Select CC1101 wait_Miso(); // Wait until MISO goes low cc1101_Deselect(); // Deselect CC1101 }