From d42183a165f5d5e13b7f0ec4919a45f1bcce98e4 Mon Sep 17 00:00:00 2001 From: Bernhard Tittelbach Date: Tue, 5 Feb 2013 04:02:57 +0000 Subject: hhd70dongle OOK Beacon Test git-svn-id: https://svn.spreadspace.org/mur.sat@663 7de4ea59-55d0-425e-a1af-a3118ea81d4c --- software/hhd70dongle/c1101lib.c | 193 ++++++++++++++++++++++++++++--------- software/hhd70dongle/c1101lib.h | 11 ++- software/hhd70dongle/hhd70.c | 20 ++++ software/hhd70dongle/hhd70.h | 5 + software/hhd70dongle/hhd70dongle.c | 68 ++++++++++--- 5 files changed, 240 insertions(+), 57 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) diff --git a/software/hhd70dongle/c1101lib.h b/software/hhd70dongle/c1101lib.h index 1742bdd..8bd80ae 100644 --- a/software/hhd70dongle/c1101lib.h +++ b/software/hhd70dongle/c1101lib.h @@ -34,6 +34,8 @@ #define C1101_FIFO_MAX_LEN 64 +#include + //read/write config registers: #define SPIC1101_ADDR_IOCFG2 0x00 #define SPIC1101_ADDR_IOCFG1 0x01 @@ -147,9 +149,12 @@ void c1101_handleStatusByte(char sb); char c1101_getStatus(void); uint16_t c1101_measureTemp(void); void c1101_spi_dump_registers_to_usb(void); -void c1101_setFrequency(uint32_t freq, uint8_t freq_offset, uint8_t if_freq); - -void c1101_transmitData(char *buffer, uint8_t len); +void c1101_permanently_save_current_rx_tx_freqoffset_auto_compensation(void); +bool c1101_setFrequency(uint32_t freq_hz); +bool c1101_changeFrequencyByRelativeValue(int32_t freq_change_hz); +uint32_t c1101_getCurrentCarrierFrequencyHz(void); +bool c1101_setIFFrequency(uint32_t freq_hz); +bool c1101_transmitData(char *buffer, uint8_t len); void c1101_transmitData_infPktMode(char *buffer, uint8_t len); void c1101_recieveData(void); diff --git a/software/hhd70dongle/hhd70.c b/software/hhd70dongle/hhd70.c index 0abe61d..e8c973b 100644 --- a/software/hhd70dongle/hhd70.c +++ b/software/hhd70dongle/hhd70.c @@ -44,6 +44,26 @@ void hhd70_init(void) // SPSR = (1< + #define SPI_DDR DDRB #define SPI_PORT PORTB #define SPI_PINB_REG PINB @@ -61,5 +63,8 @@ void hhd70_palna_txmode(void); void hhd70_palna_rxmode(void); void hhd70_palna_off(void); int8_t hhd70_rx_data_available(void); +void hhd70_config_GDO0_OOK_output(bool output_mode); +void hhd70_set_OOK_GDO0_high(void); +void hhd70_set_OOK_GDO0_low(void); #endif diff --git a/software/hhd70dongle/hhd70dongle.c b/software/hhd70dongle/hhd70dongle.c index d031a4a..34635a4 100644 --- a/software/hhd70dongle/hhd70dongle.c +++ b/software/hhd70dongle/hhd70dongle.c @@ -167,11 +167,12 @@ int main(void) enable_beacon_part=false; int8_t fdev_m = 1; int8_t fdev_e = 1; + uint32_t prev_ook_freq = c1101_getCurrentCarrierFrequencyHz(); - char mursat_beacon[256]; - for(int i=0;i 0 ? "up" : "down"), (change_freq > 0 ? 1 : -1) * change_freq / 1000); + CDC_Device_SendString(&VirtualSerial_CDC_Interface, write_buffer); + c1101_changeFrequencyByRelativeValue(change_freq); + prev_ook_freq = c1101_getCurrentCarrierFrequencyHz(); + } + sprintf(write_buffer,"Frequency is now: %lu Hz\r\n", c1101_getCurrentCarrierFrequencyHz()); + CDC_Device_SendString(&VirtualSerial_CDC_Interface, write_buffer); + } } CDC_Device_USBTask(&VirtualSerial_CDC_Interface); @@ -339,11 +377,19 @@ int main(void) if (enable_beacon_part) { -// char mursat_beacon[8] = {0b11101110, 0b11100010, 0b00111010, 0b10101000, 0b10001110, 0b11101110, 0b00101011, 0b10100000}; //OE6EOF - led_on(); + //char mursat_beacon[8] = {0b11101110, 0b11100010, 0b00111010, 0b10101000, 0b10001110, 0b11101110, 0b00101011, 0b10100000}; //OE6EOF CDC_Device_SendString(&VirtualSerial_CDC_Interface,"OOK Sending Beacon\r\n"); - c1101_transmitData_infPktMode(mursat_beacon,sizeof(mursat_beacon)); + led_on(); + //c1101_transmitData_infPktMode(mursat_beacon,sizeof(mursat_beacon)); + hhd70_palna_txmode(); + c1101_spi_strobe_command(SPIC1101_ADDR_STX); + hhd70_set_OOK_GDO0_high(); + _delay_ms(1000); led_off(); + hhd70_set_OOK_GDO0_low(); + c1101_spi_strobe_command(SPIC1101_ADDR_SIDLE); + hhd70_palna_rxmode(); + _delay_ms(200); } } } -- cgit v1.2.3