diff options
Diffstat (limited to 'software/hhd70dongle/c1101lib.c')
-rw-r--r-- | software/hhd70dongle/c1101lib.c | 193 |
1 files changed, 150 insertions, 43 deletions
diff --git a/software/hhd70dongle/c1101lib.c b/software/hhd70dongle/c1101lib.c index 1fbb2fc..cdc1270 100644 --- a/software/hhd70dongle/c1101lib.c +++ b/software/hhd70dongle/c1101lib.c @@ -300,6 +300,8 @@ void c1101_init(void) //AFU Satellite Band: 435.000 - 438.000 kHz //AFU Salellite Band Max Bandwith: 20 kHz + + hhd70_config_GDO0_OOK_output(false); } //Note for comparision: @@ -343,6 +345,8 @@ void c1101_init_w_rfstudiosettings1(void) //Values from SmartRFStudio: c1101_spi_write_patable(pa_table); + + hhd70_config_GDO0_OOK_output(false); } @@ -354,7 +358,7 @@ void c1101_init_ook_beacon(void) // Data format = Synchronous serial mode // Data rate = 1.00112 // RX filter BW = 58.035714 - // PA ramping = false + // PA ramping = true // Preamble count = 2 // Address config = No address check // Whitening = false @@ -367,8 +371,12 @@ void c1101_init_ook_beacon(void) // Modulation format = ASK/OOK // Base frequency = 435.199677 // Channel number = 0 - // PA table - char const pa_table[8] = {0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + // PA table by TI + //char const pa_table[8] = {0x00,0x12,0x0e,0x34,0x60,0xc5,0xc1,0xc0}; + // not recommended for OOK even with PA ramping set to false + //char const pa_table[8] = {0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + // correct PA table for OOK (only first two values matter) + char const pa_table[8] = {0x00,0xc5,0xc5,0xc5,0xc5,0xc5,0xc5,0xc5}; //reset C1101 c1101_spi_strobe_command(SPIC1101_ADDR_SRES); @@ -380,17 +388,15 @@ void c1101_init_ook_beacon(void) // // Rf settings for CC1101 // - c1101_spi_write_register(SPIC1101_ADDR_IOCFG0, 0x80); + c1101_spi_write_register(SPIC1101_ADDR_IOCFG0, 0x00); //enable RX FIFO interrupt (i.e. GPO2 pulls high if >= FIFOTHR bytes are in RX FIFO) c1101_spi_write_register(SPIC1101_ADDR_IOCFG2, 0x41 ); //0x40, 0x42, 0x44, 0x47 // pull GPO high (interrupt) if more than 12 bytes in rx buffer (or less than 53 in tx) - //c1101_spi_write_register(SPIC1101_ADDR_FIFOTHR,0x47); //RX FIFO and TX FIFO Thresholds c1101_spi_write_register(SPIC1101_ADDR_FIFOTHR, 0); //assert at 4 bytes in RX Fifo and 61 in TX Fifo - //c1101_spi_write_register(SPIC1101_ADDR_PKTCTRL0,0x12);//Packet Automation Control - c1101_spi_write_register(SPIC1101_ADDR_PKTCTRL0, 0b0000000001); //crc disabled; use FIFOs; variable packet length mode (first TX FIFO byte must be length) - + //c1101_spi_write_register(SPIC1101_ADDR_PKTCTRL0, 0b0000000001); //crc disabled; use FIFOs; variable packet length mode (first TX FIFO byte must be length) + c1101_spi_write_register(SPIC1101_ADDR_PKTCTRL0, 0b0000110001); //crc disabled; asynchronous serial input on GDO0 c1101_spi_write_register(SPIC1101_ADDR_FSCTRL1,0x06); //Frequency Synthesizer Control c1101_spi_write_register(SPIC1101_ADDR_FREQ2,0x10); //Frequency Control Word, High Byte c1101_spi_write_register(SPIC1101_ADDR_FREQ1,0xBD); //Frequency Control Word, Middle Byte @@ -403,45 +409,35 @@ void c1101_init_ook_beacon(void) c1101_spi_write_register(SPIC1101_ADDR_MCSM0,0x18); //Main Radio Control State Machine Configuration c1101_spi_write_register(SPIC1101_ADDR_FOCCFG,0x16); //Frequency Offset Compensation Configuration c1101_spi_write_register(SPIC1101_ADDR_WORCTRL,0xFB); //Wake On Radio Control - c1101_spi_write_register(SPIC1101_ADDR_FREND0,0x11); //Front End TX Configuration + c1101_spi_write_register(SPIC1101_ADDR_FREND0,0x11); //Front End TX Configuration // PA_POWER[2:0] = 1 c1101_spi_write_register(SPIC1101_ADDR_FSCAL3,0xE9); //Frequency Synthesizer Calibration c1101_spi_write_register(SPIC1101_ADDR_FSCAL2,0x2A); //Frequency Synthesizer Calibration c1101_spi_write_register(SPIC1101_ADDR_FSCAL1,0x00); //Frequency Synthesizer Calibration c1101_spi_write_register(SPIC1101_ADDR_FSCAL0,0x1F); //Frequency Synthesizer Calibration c1101_spi_write_patable(pa_table); + + hhd70_config_GDO0_OOK_output(true); } -//f_XOSC = 26Mhz -// freq: desired_carrier_freq [Hz] *2^16 / f_XOSC -// freq_offset: desired frequency offset [Hz] *2^14 / f_XOSC -// if_freq: desired intermidiate rx frequency [Hz] *2^10 / f_XOSC -void c1101_setFrequency(uint32_t freq, uint8_t freq_offset, uint8_t if_freq) +// see Datasheet Chapter 14.1 Frequency Offset Compensation +// freq_offset: desired frequency offset [Hz] *2^14 / f_XTAL +//f_XTAL = 26Mhz +void c1101_permanently_save_current_rx_tx_freqoffset_auto_compensation() { - //make sure we are in idle mode - char sb=0; - do + int16_t freq_offset; + freq_offset = c1101_spi_read_register(SPIC1101_ADDR_FREQUEST); + if (freq_offset >= 0) { - sb = c1101_getStatus(); - } while (! (SPIC1101_SB_IDLE(sb))); - //programm frequency - c1101_spi_write_register(SPIC1101_ADDR_FREQ0, freq & 0xFF); - c1101_spi_write_register(SPIC1101_ADDR_FREQ1, (freq >> 8) & 0xFF); - c1101_spi_write_register(SPIC1101_ADDR_FREQ2, (freq >> 16) & 0x3F); - - //set frequency offset - c1101_spi_write_register(SPIC1101_ADDR_FSCTRL0, freq_offset); - //c1101_spi_write_register(SPIC1101_ADDR_FSCTRL1, if_freq & 0x1F); - - //set channel 0 - c1101_spi_write_register(SPIC1101_ADDR_CHANNR, 0); + c1101_spi_write_register(SPIC1101_ADDR_FSCTRL0, (uint8_t) freq_offset); + } } +// WARNING: All content of the PATABLE except for the first byte (index 0) is lost when entering the SLEEP state. char c1101_putToSleep(void) { return c1101_spi_strobe_command(SPIC1101_ADDR_SPWD); } - uint16_t c1101_measureTemp(void) { uint16_t temp; @@ -517,10 +513,124 @@ uint8_t c1101_getNumBytesInTXFifo(void) return c1101_spi_read_register(SPIC1101_ADDR_TXBYTES); } -void c1101_transmitData(char *buffer, uint8_t len) + +//true if IDLE state reached before timeout [ms] +bool c1101_waitUntilIDLEState(uint16_t timeout_ms) +{ + uint8_t sb; + for (uint16_t c = 0; c < timeout_ms; c++) + { + sb = c1101_getStatus(); + if (SPIC1101_SB_IDLE(sb)) + return true; + _delay_ms(1); + } + return false; +} + +//wait until C1101 left TX State +bool c1101_waitUntilTXFinished(uint16_t timeout_ms) +{ + uint8_t c1101_state; + for (uint16_t c = 0; c < timeout_ms; c++) + { + c1101_state = c1101_getMARCState(); + c1101_handleMARCStatusByte(c1101_state); + _delay_ms(1); + if (! (c1101_state == 19 || c1101_state == 20)) + return true; + } + return false; +} + +//wait until in IDLE or RX State: +bool c1101_waitUntilIDLEorRXState(uint16_t timeout_ms) +{ + uint8_t c1101_state; + for (uint16_t c = 0; c < timeout_ms; c++) + { + c1101_state = c1101_getMARCState(); + c1101_handleMARCStatusByte(c1101_state); + _delay_ms(1); + if (c1101_state == 1 || (c1101_state >= 13 && c1101_state <= 15)) + return true; + } + return false; +} + +bool c1101_writeFrequencyRegisters(uint32_t freq) +{ + if (! c1101_waitUntilIDLEState(2000)) //wait 2sec max + return false; + //programm frequency + c1101_spi_write_register(SPIC1101_ADDR_FREQ0, freq & 0xFF); + c1101_spi_write_register(SPIC1101_ADDR_FREQ1, (freq >> 8) & 0xFF); + c1101_spi_write_register(SPIC1101_ADDR_FREQ2, (freq >> 16) & 0x3F); + + //set channel 0 + c1101_spi_write_register(SPIC1101_ADDR_CHANNR, 0); + return true; +} + +uint32_t c1101_readFrequencyRegisters(void) +{ + uint32_t freq = 0; + freq = ((uint8_t) c1101_spi_read_register(SPIC1101_ADDR_FREQ2)) & 0x3F; + freq = freq << 8; + freq |= ((uint8_t) c1101_spi_read_register(SPIC1101_ADDR_FREQ1)); + freq = freq << 8; + freq |= ((uint8_t) c1101_spi_read_register(SPIC1101_ADDR_FREQ0)); + return freq; +} + +//f_XOSC = 26Mhz +// freq: desired_carrier_freq [Hz] *2^16 / f_XOSC +bool c1101_setFrequency(uint32_t freq_hz) +{ + uint32_t freq = freq_hz / 397; + if ( freq <= 0x3FFFFF) + return c1101_writeFrequencyRegisters(freq); + else + return false; +} + +//f_XOSC = 26Mhz +// freq: desired_carrier_freq [Hz] *2^16 / f_XOSC +bool c1101_changeFrequencyByRelativeValue(int32_t freq_change_hz) +{ + int32_t freq_change = freq_change_hz / 397; + int32_t freq = (int32_t) c1101_readFrequencyRegisters(); + + freq += freq_change; + + if ( freq >= 0 && freq <= 0x3FFFFF ) + return c1101_writeFrequencyRegisters((uint32_t) freq); + else + return false; +} + +uint32_t c1101_getCurrentCarrierFrequencyHz(void) +{ + return c1101_readFrequencyRegisters() * 397; +} + +// if_freq: desired intermidiate rx frequency [Hz] *2^10 / f_XOSC +bool c1101_setIFFrequency(uint32_t freq_hz) +{ + uint8_t if_freq = freq_hz / 25391; + //make sure we are in idle mode + if (! c1101_waitUntilIDLEState(2000)) //wait 2sec max + return false; + + c1101_spi_write_register(SPIC1101_ADDR_FSCTRL1, if_freq & 0x1F); + return true; +} + +bool c1101_transmitData(char *buffer, uint8_t len) { //~ uint8_t debug_sb[6]; uint8_t num_written = 0; + bool success = true; //~ uint8_t mcsm1 = c1101_spi_read_register(SPIC1101_ADDR_MCSM1); //~ //configure state machine to automatically go to IDLE, once packet was transmitted //~ mcsm1 = (mcsm1 & 0b11111100) | 0b00; @@ -557,7 +667,6 @@ void c1101_transmitData(char *buffer, uint8_t len) hhd70_palna_txmode(); //should actually be done by c1101 itself, by connecting PTT function of GPO0 pin to LNA/PA toggle //keep buffer filled - uint8_t c1101_state=0; do { c1101_getStatus(); @@ -566,13 +675,11 @@ void c1101_transmitData(char *buffer, uint8_t len) len -= num_written; //wait until in IDLE or RX State: - do + if (! c1101_waitUntilIDLEorRXState(10000)) //wait for max 10s { - c1101_state = c1101_getMARCState(); - _delay_ms(100); - c1101_handleMARCStatusByte(c1101_state); + success = false; + goto c1101_transmitData_cleanup; } - while (!(c1101_state == 1 || (c1101_state >= 13 && c1101_state <= 15))); //from state IDLE or RX go to TX num_written = c1101_spi_strobe_command(SPIC1101_ADDR_STX); @@ -588,17 +695,17 @@ void c1101_transmitData(char *buffer, uint8_t len) } while (len > 0); //wait until TX finished - do + if (!c1101_waitUntilTXFinished(10000)) //wait 10s max, then just shut down PA { - c1101_state = c1101_getMARCState(); - _delay_ms(100); - c1101_handleMARCStatusByte(c1101_state); + success = false; + goto c1101_transmitData_cleanup; } - while (c1101_state == 19 || c1101_state == 20); + c1101_transmitData_cleanup: //disable Power Amplifier //FIXME, instead use PTT function of GPO0 -> interrupt handler -> toggle rx/tx hhd70_palna_rxmode(); + return success; } void c1101_transmitData_infPktMode(char *buffer, uint8_t len) |