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.c771
1 files changed, 0 insertions, 771 deletions
diff --git a/software/hhd70dongle/c1101lib.c b/software/hhd70dongle/c1101lib.c
deleted file mode 100644
index 209ccee..0000000
--- a/software/hhd70dongle/c1101lib.c
+++ /dev/null
@@ -1,771 +0,0 @@
-/*
- *
- * mur.sat
- *
- * Somewhen in the year 20xx, mur.at will have a nano satellite launched
- * into a low earth orbit (310 km above the surface of our planet). The
- * satellite itself is a TubeSat personal satellite kit, developed and
- * launched by interorbital systems. mur.sat is a joint venture of mur.at,
- * ESC im Labor and realraum.
- *
- * Please visit the project hompage at sat.mur.at for further information.
- *
- *
- * Copyright (C) 2012 Bernhard Tittelbach <xro@realraum.at>
- * 2015 Christian Pointner <equinox@mur.at>
- *
- * This file is part of mur.sat.
- *
- * mur.sat is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * any later version.
- *
- * mur.sat is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with mur.sat. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <avr/io.h>
-#include <util/delay.h>
-
-#include "c1101lib.h"
-#include "cc1101_defines.h"
-#include "hhd70.h"
-#include "util.h"
-
-// internal functions
-
-#define CC1101_MAX_WAIT_RDY 21
-
-static int16_t c1101_spi_write_byte_ok_get_status(uint8_t data)
-{
- uint8_t sb;
- unsigned int attempts = 0;
- do
- {
- sb = hhd70_spi_exchange_byte(data);
- //Note: content of returned StatusByte is actually context depenedant on sent command
- // i.e. we won't get Fifo Byte count or overflow status on normal command and so on
- // e.g. we only get TX Fifo Free Byte count while writing to TX Fifo
- // thus it makes sense to only check for CHIP_RDY here
- if (attempts++ > CC1101_MAX_WAIT_RDY)
- return -1;
- } while (CC1101_STATUS_CHIP_NOT_RDY(sb));
- return sb;
-}
-
-int16_t c1101_spi_strobe_command(uint8_t cmd)
-{
- if(cmd < CC1101_CMD_MIN || cmd > CC1101_CMD_MAX)
- return -1;
-
- hhd70_spi_cs_enable();
- hhd70_c1101_wait_chip_rdy();
- uint8_t rbyte = c1101_spi_write_byte_ok_get_status(CC1101_HEADER_COMMAND | cmd);
- if(rbyte < 0)
- return -1;
- hhd70_spi_cs_disable();
- return rbyte;
-}
-
-int16_t c1101_spi_read_register(uint8_t addr)
-{
- if(addr > CC1101_ADDR_MAX)
- return -1;
-
- if(addr > CC1101_REG_RW_MAX)
- addr |= CC1101_HEADER_READONLY;
- else
- addr |= CC1101_HEADER_READ;
-
- hhd70_spi_cs_enable();
- hhd70_c1101_wait_chip_rdy();
- if(c1101_spi_write_byte_ok_get_status(addr) < 0)
- return -1;
- uint8_t rbyte = hhd70_spi_read_byte();
- hhd70_spi_cs_disable();
- return rbyte;
-}
-
-int16_t c1101_spi_write_register(uint8_t addr, uint8_t byte)
-{
- if(addr > CC1101_REG_RW_MAX)
- return -1;
-
- hhd70_spi_cs_enable();
- hhd70_c1101_wait_chip_rdy();
- if(c1101_spi_write_byte_ok_get_status(CC1101_HEADER_WRITE | addr) < 0)
- return -1;
- _delay_ms(2); // TODO: why wait here???
- if(c1101_spi_write_byte_ok_get_status(byte) < 0)
- return -1;
- hhd70_spi_cs_disable();
- return 1;
-}
-
-void c1101_spi_dump_registers(void)
-{
- int c = 0;
- char debug_sb[6];
- hhd70_spi_cs_enable();
- hhd70_c1101_wait_chip_rdy();
- if (c1101_spi_write_byte_ok_get_status(CC1101_HEADER_READ | CC1101_HEADER_BURST | 0x00) < 0)
- return;
- printf("dump all 46 registers:\r\n");
- for (c = 0; c < CC1101_REG_RW_MAX; c++) {
- debug_sprint_int16hex(debug_sb, hhd70_spi_read_byte());
- printf("%s", debug_sb);
- printf("\r\n");
- }
- hhd70_spi_cs_disable();
-}
-
-int c1101_spi_read_rxfifo(int leave_num_bytes, uint8_t *buffer, int maxlen)
-{
- int num_read = 0;
- uint8_t num_available = 0;
- hhd70_spi_cs_enable();
- hhd70_c1101_wait_chip_rdy();
- if (c1101_spi_write_byte_ok_get_status(CC1101_HEADER_READONLY | CC1101_REG_RO_RXBYTES) < 0)
- return -1;
-
- num_available = hhd70_spi_read_byte();
- if (num_available == 0)
- return 0;
- if (c1101_spi_write_byte_ok_get_status(CC1101_HEADER_READ | CC1101_HEADER_BURST | CC1101_REG_FIFO) < 0)
- return -1;
- while (maxlen-- > 0 && num_available - num_read > leave_num_bytes)
- buffer[num_read++] = hhd70_spi_read_byte();
-
- hhd70_spi_cs_disable();
- return num_read;
-}
-
-//note: currently this function reads at most 15 bytes
-int c1101_spi_read_rxfifo_max15(int leave_num_bytes, uint8_t *buffer, int maxlen)
-{
- int16_t sb;
- int num_read = 0;
- hhd70_spi_cs_enable();
- hhd70_c1101_wait_chip_rdy();
- sb = c1101_spi_write_byte_ok_get_status(CC1101_HEADER_READ | CC1101_HEADER_BURST | CC1101_REG_FIFO);
- if (sb < 0)
- return -1;
- //note if CC1101_STATUS_FIFO_BYTES_AVAILABLE(sb) == 15 then 15 or more bytes are available
- while (maxlen-- > 0 && CC1101_STATUS_FIFO_BYTES_AVAILABLE(sb) - num_read > leave_num_bytes) {
- //hope this works !!
- buffer[num_read++] = hhd70_spi_read_byte();
- }
- hhd70_spi_cs_disable();
- return num_read;
-}
-
-//note: always check if num_written returned == len given
-int c1101_spi_write_txfifo(uint8_t *buffer, int len)
-{
- uint8_t sb;
- int num_written = 0;
- hhd70_spi_cs_enable();
- hhd70_c1101_wait_chip_rdy();
- sb = c1101_spi_write_byte_ok_get_status(CC1101_HEADER_READ | CC1101_HEADER_BURST | CC1101_REG_FIFO);
- if (sb < 0)
- return -1;
- while (len-- > 0 && CC1101_STATUS_FIFO_BYTES_AVAILABLE(sb) > 2) {
- sb = c1101_spi_write_byte_ok_get_status(buffer[num_written++]);
- }
- hhd70_spi_cs_disable();
- return num_written;
-}
-
-//patable muste be uint8_t array of length 8
-int c1101_spi_write_patable(uint8_t const patable[])
-{
- int16_t sb;
- int8_t len = 8;
- hhd70_spi_cs_enable();
- hhd70_c1101_wait_chip_rdy();
- sb = c1101_spi_write_byte_ok_get_status(CC1101_HEADER_WRITE | CC1101_HEADER_BURST | CC1101_REG_PATABLE);
- if (sb < 0)
- return -1;
- while (len-- > 0) {
- sb = c1101_spi_write_byte_ok_get_status(*patable);
- patable++;
- }
- hhd70_spi_cs_disable();
- return sb;
-}
-
-static uint8_t const pa_table_values_[] = { 0x00, 0x30, 0x20, 0x10, 0x01, 0x02, 0x11, 0x03,
- 0x12, 0x04, 0x05, 0x13, 0x06, 0x07, 0x21, 0x14, 0x08, 0x09, 0x0A, 0x15,
- 0x0B, 0x31, 0x16, 0x0C, 0x0D, 0x0E, 0x17, 0x0F, 0x22, 0x18, 0x19, 0x1A,
- 0x1B, 0x32, 0x23, 0x1C, 0x6F, 0x1D, 0x1E, 0x1F, 0x24, 0x33, 0x25, 0x34,
- 0x26, 0x6E, 0x27, 0x35, 0x28, 0x6D, 0x6C, 0x29, 0x36, 0x6B, 0x2A, 0x6A,
- 0x37, 0x69, 0x2B, 0x68, 0x38, 0x2C, 0x8F, 0x67, 0x2D, 0x57, 0x39, 0x66,
- 0x2E, 0x56, 0x3A, 0x2F, 0x65, 0x55, 0x3B, 0x64, 0x54, 0x3C, 0x63, 0x3D,
- 0x53, 0x3E, 0x62, 0x3F, 0x52, 0x40, 0x61, 0x51, 0x60, 0x50, 0x8E, 0x8D,
- 0x8C, 0xCF, 0x8B, 0x8A, 0x89, 0x88, 0x87, 0x86, 0x85, 0xCE, 0x84, 0x83,
- 0xCD, 0x82, 0xCC, 0x81, 0xCB, 0x80, 0xCA, 0xC9, 0xC8, 0xC7, 0xC6, 0xC5,
- 0xC4, 0xC3, 0xC2, 0xC1, 0xC0 };
-
-#define PA_TABLE_VALUES_MAX ((sizeof(pa_table_values_)/sizeof(uint8_t))-1)
-static uint8_t ook_power_ = 83; // ==> 3F
-
-
-/**** External Functions ****/
-
-uint16_t c1101_setFSKDeviationFromCarrier(int8_t m, int8_t e)
-{
- c1101_spi_write_register(CC1101_REG_RW_DEVIATN, (m & 0x7) | ((e & 0x7) << 4));
- return (1983u * (8u+((uint32_t)m)) * (1u << ((uint32_t)e))) / 100; //return +- deviation in 10Hz Steps
-}
-
-void c1101_init(void)
-{
- //reset C1101
- c1101_spi_strobe_command(CC1101_CMD_SRES);
- _delay_ms(100);
- //flush FIFOs
- c1101_spi_strobe_command(CC1101_CMD_SFRX);
- c1101_spi_strobe_command(CC1101_CMD_SFTX);
- //dump pre-init default values to stdout
- c1101_spi_dump_registers();
- //enable analog temperature sensor on GDO0
- c1101_spi_write_register(CC1101_REG_RW_IOCFG0, 0x80);
- //enable RX FIFO interrupt (i.e. GPO2 pulls high if >= FIFOTHR bytes are in RX FIFO)
- c1101_spi_write_register(CC1101_REG_RW_IOCFG2, 0x41 ); //0x40, 0x42, 0x44, 0x47
- // FIFOTHR RX FIFO and TX FIFO Thresholds
- // pull GPO high (interrupt) if more than 12 bytes in rx buffer (or less than 53 in tx)
- //c1101_spi_write_register(CC1101_REG_RW_FIFOTHR, 2); //assert at 12 bytes in RX Fifo and 53 in TX Fifo
- c1101_spi_write_register(CC1101_REG_RW_FIFOTHR, 0); //assert at 4 bytes in RX Fifo and 61 in TX Fifo
- // PKTCTRL0 Packet Automation Control
- //c1101_spi_write_register(CC1101_REG_RW_PKTCTRL0, 0b0000000010); //crc disabled; use FIFOs; infinite packet length mode
- c1101_spi_write_register(CC1101_REG_RW_PKTCTRL0, 0b0000000001); //crc disabled; use FIFOs; variable packet length mode (first TX FIFO byte must be length)
- //c1101_spi_write_register(CC1101_REG_RW_PKTCTRL0, 0b0000000101); //crc enabled; use FIFOs; variable packet length mode (first TX FIFO byte must be length)
- c1101_spi_write_register(CC1101_REG_RW_PKTCTRL1, 0x00); //no address check, no append rssi and crc_ok to packet
- // FSCTRL1 Frequency Synthesizer Control
- c1101_spi_write_register(CC1101_REG_RW_FSCTRL1, 0x06);
- // FREQn Frequency Control Words
- c1101_spi_write_register(CC1101_REG_RW_FREQ2, 0x10); //should be 435.125 mhz
- c1101_spi_write_register(CC1101_REG_RW_FREQ1, 0xBF);
- c1101_spi_write_register(CC1101_REG_RW_FREQ0, 0xEF);
- c1101_spi_write_register(CC1101_REG_RW_FSCTRL0, 0); //frequency offset
- // MDMCFGn Modem Configuration
- c1101_spi_write_register(CC1101_REG_RW_MDMCFG4, 0xF8);
- c1101_spi_write_register(CC1101_REG_RW_MDMCFG3, 0x83);
- c1101_spi_write_register(CC1101_REG_RW_MDMCFG2, 0x12); //gfsk, 15/16 sync word
- c1101_spi_write_register(CC1101_REG_RW_MDMCFG1, 0x00);
- //Sync Word
- c1101_spi_write_register(CC1101_REG_RW_SYNC1, 0x21);
- c1101_spi_write_register(CC1101_REG_RW_SYNC0, 0x42);
- // DEVIATN Modem Deviation Setting
- c1101_spi_write_register(CC1101_REG_RW_DEVIATN, 0x11); //0x11 equals deviation of 3.5kHz; 0x27 equals deviation of 11.9kHz
- // MCSM0 Main Radio Control State Machine Configuration
- c1101_spi_write_register(CC1101_REG_RW_MCSM0, 0x18);
- c1101_spi_write_register(CC1101_REG_RW_MCSM1, 0b00111100); // State RX after recieving packet-> stay in RX; State TX after sending packet -> IDLE
- // FOCCFG Frequency Offset Compensation Configuration
- c1101_spi_write_register(CC1101_REG_RW_FOCCFG, 0x16);
- // WORCTRL Wake On Radio Control
- c1101_spi_write_register(CC1101_REG_RW_WORCTRL, 0xFB);
- // FSCALn Frequency Synthesizer Calibration
- c1101_spi_write_register(CC1101_REG_RW_FSCAL3, 0xE9);
- c1101_spi_write_register(CC1101_REG_RW_FSCAL2, 0x2A);
- c1101_spi_write_register(CC1101_REG_RW_FSCAL1, 0x00);
- c1101_spi_write_register(CC1101_REG_RW_FSCAL0, 0x1F);
- //FREN0 TX Power:
- c1101_spi_write_register(CC1101_REG_RW_FREND0, 0x10); //should be set using RF-Studio !!, for now, only use PA-Table Entry[0] no power ramping !! (FIXME: but should maybe be used)
- c1101_spi_write_register(CC1101_REG_PATABLE, 0xC0); //write PATABLE[0] only, rest needs to be written in Burst-Mode ! set to max power 10dBm
-
- // note: for now: assume f_xosc to be 26 Mhz
- // for ~433.125 Mhz -> freq = 1091741, freq_offset = 0
- //c1101_setFrequency(1091741,0,15);
-
- //AFU Satellite Band: 435.000 - 438.000 kHz
- //AFU Salellite Band Max Bandwith: 20 kHz
-
- hhd70_config_GDO0_OOK_output(false);
-}
-
-//Note for comparision:
-void c1101_init_w_rfstudiosettings1(void)
-{
- // Sync word qualifier mode = 30/32 sync word bits detected
- // CRC autoflush = false
- // Channel spacing = 199.951172
- // Data format = Normal mode
- // Data rate = 9.59587
- // RX filter BW = 58.035714
- // PA ramping = true
- // Preamble count = 4
- // Address config = No address check
- // Whitening = false
- // Carrier frequency = 435.124695
- // Device address = 0
- // TX power = 10
- // Manchester enable = false
- // CRC enable = true
- // Deviation = 11.901855
- // Modulation format = GFSK
- // Base frequency = 435.124695
- // Modulated = true
- // Channel number = 0
- // PA table
- uint8_t const pa_table[8] = {0x00,0x12,0x0e,0x34,0x60,0xc5,0xc1,0xc0};
- //
- // Rf settings for CC1101
- //
- //reset C1101
- c1101_spi_strobe_command(CC1101_CMD_SRES);
- _delay_ms(100);
- //flush FIFOs
- c1101_spi_strobe_command(CC1101_CMD_SFRX);
- c1101_spi_strobe_command(CC1101_CMD_SFTX);
- //enable analog temperature sensor on GDO0
- c1101_spi_write_register(CC1101_REG_RW_IOCFG0, 0x80);
- //enable RX FIFO interrupt (i.e. GPO2 pulls high if >= FIFOTHR bytes are in RX FIFO)
- c1101_spi_write_register(CC1101_REG_RW_IOCFG2, 0x41 ); //0x40, 0x42, 0x44, 0x47
-
- //Values from SmartRFStudio:
- c1101_spi_write_patable(pa_table);
-
- hhd70_config_GDO0_OOK_output(false);
-}
-
-
-void c1101_init_ook_beacon(void)
-{
- // Sync word qualifier mode = No preamble/sync
- // CRC autoflush = false
- // Channel spacing = 49.987793
- // Data format = Synchronous serial mode
- // Data rate = 1.00112
- // RX filter BW = 58.035714
- // PA ramping = true
- // Preamble count = 2
- // Address config = No address check
- // Whitening = false
- // Carrier frequency = 437.524902 MHz
- // Device address = 0
- // TX power = 10
- // Manchester enable = false
- // CRC enable = false
- // Deviation = 2.975464
- // Modulation format = ASK/OOK
- // Base frequency = 437.524902 MHz
- // Channel number = 0
- // PA table by TI
-
- //reset C1101
- c1101_spi_strobe_command(CC1101_CMD_SRES);
- _delay_ms(100);
- //flush FIFOs
- c1101_spi_strobe_command(CC1101_CMD_SFRX);
- c1101_spi_strobe_command(CC1101_CMD_SFTX);
-
- //
- // Rf settings for CC1101
- //
- c1101_spi_write_register(CC1101_REG_RW_IOCFG0, 0x00);
- //enable RX FIFO interrupt (i.e. GPO2 pulls high if >= FIFOTHR bytes are in RX FIFO)
- c1101_spi_write_register(CC1101_REG_RW_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(CC1101_REG_RW_FIFOTHR,0x47); //RX FIFO and TX FIFO Thresholds
- c1101_spi_write_register(CC1101_REG_RW_FIFOTHR, 0); //assert at 4 bytes in RX Fifo and 61 in TX Fifo
- //c1101_spi_write_register(CC1101_REG_RW_PKTCTRL0,0x12);//Packet Automation Control
- //c1101_spi_write_register(CC1101_REG_RW_PKTCTRL0, 0b0000000001); //crc disabled; use FIFOs; variable packet length mode (first TX FIFO byte must be length)
- c1101_spi_write_register(CC1101_REG_RW_PKTCTRL0, 0b0000110001); //crc disabled; asynchronous serial input on GDO0
- c1101_spi_write_register(CC1101_REG_RW_FSCTRL1,0x06); //Frequency Synthesizer Control
- c1101_spi_write_register(CC1101_REG_RW_FREQ2,0x10); //Frequency Control Word, High Byte
- c1101_spi_write_register(CC1101_REG_RW_FREQ1,0xD3); //Frequency Control Word, Middle Byte
- c1101_spi_write_register(CC1101_REG_RW_FREQ0,0xF0); //Frequency Control Word, Low Byte
- c1101_spi_write_register(CC1101_REG_RW_MDMCFG4,0xF5); //Modem Configuration
- c1101_spi_write_register(CC1101_REG_RW_MDMCFG3,0x43); //Modem Configuration
- c1101_spi_write_register(CC1101_REG_RW_MDMCFG2,0x30); //Modem Configuration
- c1101_spi_write_register(CC1101_REG_RW_MDMCFG1,0x00); //Modem Configuration
- c1101_spi_write_register(CC1101_REG_RW_DEVIATN,0x07); //Modem Deviation Setting
- c1101_spi_write_register(CC1101_REG_RW_MCSM0,0x18); //Main Radio Control State Machine Configuration
- c1101_spi_write_register(CC1101_REG_RW_FOCCFG,0x16); //Frequency Offset Compensation Configuration
- c1101_spi_write_register(CC1101_REG_RW_WORCTRL,0xFB); //Wake On Radio Control
- c1101_spi_write_register(CC1101_REG_RW_FREND0,0x11); //Front End TX Configuration // PA_POWER[2:0] = 1
- c1101_spi_write_register(CC1101_REG_RW_FSCAL3,0xE9); //Frequency Synthesizer Calibration
- c1101_spi_write_register(CC1101_REG_RW_FSCAL2,0x2A); //Frequency Synthesizer Calibration
- c1101_spi_write_register(CC1101_REG_RW_FSCAL1,0x00); //Frequency Synthesizer Calibration
- c1101_spi_write_register(CC1101_REG_RW_FSCAL0,0x1F); //Frequency Synthesizer Calibration
-
- c1101_ook_power_set(ook_power_);
- hhd70_config_GDO0_OOK_output(true);
-}
-
-uint8_t c1101_ook_power_get()
-{
- return ook_power_;
-}
-
-uint8_t c1101_ook_power_get_raw()
-{
- return pa_table_values_[ook_power_];
-}
-
-void c1101_ook_power_set(uint8_t power)
-{
- uint8_t val = pa_table_values_[(power <= PA_TABLE_VALUES_MAX) ? power : PA_TABLE_VALUES_MAX];
- uint8_t const pa_table[8] = {0x00, val ,0x00,0x00,0x00,0x00,0x00,0x00};
- c1101_spi_write_patable(pa_table);
-}
-
-void c1101_ook_power_inc()
-{
- ook_power_ = (ook_power_ < PA_TABLE_VALUES_MAX) ? ook_power_ + 1 : PA_TABLE_VALUES_MAX;
- uint8_t const pa_table[8] = {0x00, pa_table_values_[ook_power_] ,0x00,0x00,0x00,0x00,0x00,0x00};
- c1101_spi_write_patable(pa_table);
-}
-
-void c1101_ook_power_dec()
-{
- ook_power_ = (ook_power_ > 0) ? ook_power_ - 1 : 0;
- uint8_t const pa_table[8] = {0x00, pa_table_values_[ook_power_] ,0x00,0x00,0x00,0x00,0x00,0x00};
- c1101_spi_write_patable(pa_table);
-}
-
-// 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()
-{
- int16_t freq_offset;
- freq_offset = c1101_spi_read_register(CC1101_REG_RO_FREQUEST);
- if (freq_offset >= 0)
- {
- c1101_spi_write_register(CC1101_REG_RW_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.
-uint8_t c1101_putToSleep(void)
-{
- return c1101_spi_strobe_command(CC1101_CMD_SPWD);
-}
-
-uint16_t c1101_measureTemp(void)
-{
- uint16_t temp;
- uint8_t ptest_value=0x7F;
- ptest_value = c1101_spi_read_register(CC1101_REG_RW_PTEST);
- c1101_spi_write_register(CC1101_REG_RW_PTEST, 0xBF);
- _delay_ms(5);
- temp = adc_read(ADCMUX_INTERNALTEMP);
- c1101_spi_write_register(CC1101_REG_RW_PTEST, ptest_value);
- return temp;
-}
-
-void c1101_handleMARCStatusByte(uint8_t sb)
-{
- //on RXFifo Overflow, Flush RX Fifo
- if (sb == 0x11)
- {
- c1101_spi_strobe_command(CC1101_CMD_SFRX);
- printf("RX fifo flushed\r\n");
- }
- //on TXFifo Overflow, Flush TX Fifo
- else if (sb == 0x16)
- {
- c1101_spi_strobe_command(CC1101_CMD_SFTX);
- printf("TX fifo flushed\r\n");
- }
-}
-
-void c1101_handleStatusByte(uint8_t sb)
-{
- //on RXFifo Overflow, Flush RX Fifo
- if (CC1101_STATUS_RXFIFO_OVERFLOW(sb))
- {
- c1101_spi_strobe_command(CC1101_CMD_SFRX);
- printf("RX fifo flushed\r\n");
- }
- //on TXFifo Overflow, Flush TX Fifo
- if (CC1101_STATUS_TXFIFO_OVERFLOW(sb))
- {
- c1101_spi_strobe_command(CC1101_CMD_SFTX);
- printf("TX fifo flushed\r\n");
- }
-}
-
-uint8_t c1101_getStatus(void)
-{
- uint8_t sb=0;
- hhd70_spi_cs_enable();
- hhd70_c1101_wait_chip_rdy();
- sb = c1101_spi_write_byte_ok_get_status(CC1101_HEADER_COMMAND | CC1101_CMD_SNOP);
- hhd70_spi_cs_disable();
- c1101_handleStatusByte(sb);
- return sb;
-}
-
-uint8_t c1101_getMARCState(void)
-{
- uint8_t sb=0;
- sb = c1101_spi_read_register(CC1101_REG_RO_MARCSTATE);
- sb &= 0x1F;
- //debug start
- /* uint8_t debug_sb[6]; */
- /* printf("c1101 MARCState:\r\n"); */
- /* debug_sprint_int16hex(debug_sb, sb); */
- /* printf("%s", debug_sb); */
- /* printf("\r\n"); */
- //debug end
- return sb;
-}
-
-uint8_t c1101_getNumBytesInTXFifo(void)
-{
- return c1101_spi_read_register(CC1101_REG_RO_TXBYTES);
-}
-
-
-//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 (CC1101_STATUS_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(CC1101_REG_RW_FREQ0, freq & 0xFF);
- c1101_spi_write_register(CC1101_REG_RW_FREQ1, (freq >> 8) & 0xFF);
- c1101_spi_write_register(CC1101_REG_RW_FREQ2, (freq >> 16) & 0x3F);
-
- //set channel 0
- c1101_spi_write_register(CC1101_REG_RW_CHANNR, 0);
- return true;
-}
-
-uint32_t c1101_readFrequencyRegisters(void)
-{
- uint32_t freq = 0;
- freq = ((uint8_t) c1101_spi_read_register(CC1101_REG_RW_FREQ2)) & 0x3F;
- freq = freq << 8;
- freq |= ((uint8_t) c1101_spi_read_register(CC1101_REG_RW_FREQ1));
- freq = freq << 8;
- freq |= ((uint8_t) c1101_spi_read_register(CC1101_REG_RW_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 = (uint32_t)((float)freq_hz / CC1101_FREQ_CORR);
- 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 = (int32_t)((float)freq_change_hz / CC1101_FREQ_CORR);
- 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 (uint32_t)((float)c1101_readFrequencyRegisters() * CC1101_FREQ_CORR);
-}
-
-// 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(CC1101_REG_RW_FSCTRL1, if_freq & 0x1F);
- return true;
-}
-
-bool c1101_transmitData(uint8_t *buffer, uint8_t len)
-{
- //~ uint8_t debug_sb[6];
- uint8_t num_written = 0;
- bool success = true;
- //~ uint8_t mcsm1 = c1101_spi_read_register(CC1101_REG_RW_MCSM1);
- //~ //configure state machine to automatically go to IDLE, once packet was transmitted
- //~ mcsm1 = (mcsm1 & 0b11111100) | 0b00;
- //~ c1101_spi_write_register(CC1101_REG_RW_MCSM1, 0x18);
- //~ c1101_spi_write_register(CC1101_REG_RW_PKTCTRL0, 0b0000000001); //crc disabled; use FIFOs; variable packet length mode (first TX FIFO byte must be length)
- // flush TX FIFO
- c1101_spi_strobe_command(CC1101_CMD_SFTX);
-
- //~ //fill buffer
- //~ num_written = c1101_spi_write_txfifo(buffer, len);
- //~ buffer += num_written;
- //~ len -= num_written;
-
- //~ ((uint8_t*)"TX num written",255);
- //~ debug_sprint_int16hex(debug_sb, num_written);
- //~ (debug_sb,255);
- //~ ((uint8_t*)"TX len",255);
- //~ debug_sprint_int16hex(debug_sb, len);
- //~ (debug_sb,255);
-
- //~ c1101_getStatus();
- //~ ((uint8_t*)"TX bytes",255);
- //~ debug_sprint_int16hex(debug_sb, c1101_getNumBytesInTXFifo());
- //~ (debug_sb,255);
-
- //start transmitting
- //num_written = c1101_spi_strobe_command(CC1101_CMD_STX);
- //~ num_written = hhd70_spi_exchange_byte(CC1101_CMD_STX);
- //~ ((uint8_t*)"Strobe STX",255);
- //~ debug_sprint_int16hex(debug_sb, num_written);
- //~ (debug_sb,255);
-
- //enable Power Amplifier
- hhd70_palna_txmode(); //should actually be done by c1101 itself, by connecting PTT function of GPO0 pin to LNA/PA toggle
-
- //keep buffer filled
- do
- {
- c1101_getStatus();
- num_written = c1101_spi_write_txfifo(buffer, len );
- buffer += num_written;
- len -= num_written;
-
- //wait until in IDLE or RX State:
- if (! c1101_waitUntilIDLEorRXState(10000)) //wait for max 10s
- {
- success = false;
- goto c1101_transmitData_cleanup;
- }
- //from state IDLE or RX go to TX
- num_written = c1101_spi_strobe_command(CC1101_CMD_STX);
-
- //~ ((uint8_t*)"TX2 num written",255);
- //~ debug_sprint_int16hex(debug_sb, num_written);
- //~ (debug_sb,255);
- //~ ((uint8_t*)"TX2 len",255);
- //~ debug_sprint_int16hex(debug_sb, len);
- //~ (debug_sb,255);
- //~ ((uint8_t*)"TX2 bytes",255);
- //~ debug_sprint_int16hex(debug_sb, c1101_getNumBytesInTXFifo());
- //~ (debug_sb,255);
- } while (len > 0);
-
- //wait until TX finished
- if (!c1101_waitUntilTXFinished(10000)) //wait 10s max, then just shut down PA
- {
- success = false;
- goto c1101_transmitData_cleanup;
- }
-
- 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(uint8_t *buffer, uint8_t len)
-{
- //in infinite Packet Mode, prepend length to buffer:
- uint8_t *new_buffer = malloc(len+1);
- new_buffer[0] = len;
- memcpy(new_buffer+1, buffer, len);
- //variable packet length: write length of packet to TX FIFO:
- c1101_transmitData(new_buffer, len+1);
- free(new_buffer);
-}
-
-void c1101_recieveData(void)
-{
- uint8_t const max_len=255;
- uint8_t recv_data[256];
- uint8_t num_recv = 0;
- uint8_t num_recv_total = 0;
- uint8_t num_leave_in_fifo = 1;
- do
- {
- num_recv = c1101_spi_read_rxfifo( num_leave_in_fifo, recv_data+num_recv_total, max_len - num_recv_total);
- num_recv_total += num_recv;
-
- //variable packet length:
- //don't read last byte in fifo unless packet has finished receiving
- num_leave_in_fifo = (recv_data[0] - num_recv_total < 64)? 0 : 1;
- } while (num_recv > 0);
- recv_data[num_recv_total]=0;
- printf("RX: Data Recieved: ");
- printf("%s", recv_data);
- printf("\r\n");
- c1101_getStatus(); // get status and handle possiblble RX Fifo Overflow
-}
-
-//max returned: 64 bytes
-int c1101_readRXFifo(uint8_t *buffer)
-{
- //check RXBYTES.NUM_RXBYTES
- // never read more bytes than avaiblabe or we will read garbage
-
- //note: if RX transmission fills fifo buffer at exact same time as last RX Fifo Bit is read via SPI, Fifo Pointer will not be properly updated
- // and last read byte will be duplicated.
- // thus: don't last avialable FIFO Bytes unless we can be sure that it will be the last byte of a packet and we can be sure that a following duplicated byte is actually an Fifo duplication and not an actually recieved byte !
-
- return 0;
-}