summaryrefslogtreecommitdiff
path: root/software/hhd70dongle/c1101lib.c
diff options
context:
space:
mode:
Diffstat (limited to 'software/hhd70dongle/c1101lib.c')
-rw-r--r--software/hhd70dongle/c1101lib.c193
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)