/* * spreadspace avr utils * * * Copyright (C) 2013-2018 Christian Pointner * * This file is part of spreadspace avr utils. * * spreadspace avr utils 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. * * spreadspace avr utils 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 spreadspace avr utils. If not, see . */ #include #include #include "cc1101.h" #include "cc1101_defines.h" static cc1101_driver_conf_t drv = { .spi_cs_enable = NULL, .spi_cs_disable = NULL, .spi_read_miso = NULL, .spi_write_byte = NULL, .spi_read_byte = NULL, .spi_transfer_byte = NULL, .freq_corr = 1.0 }; 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) /* * internal functions */ #define CC1101_CHIP_RDY_TIMEOUT 10 static inline uint8_t cc1101_spi_wait_rdy(void) { uint16_t timeout = CC1101_CHIP_RDY_TIMEOUT; while(drv.spi_read_miso()) if(!(--timeout)) return 1; return 0; } static uint8_t cc1101_spi_strobe_command(const uint8_t cmd) { if(cmd < CC1101_CMD_MIN || cmd > CC1101_CMD_MAX) return -1; uint8_t status = 0x80; drv.spi_cs_enable(); if(!cc1101_spi_wait_rdy()) { status = drv.spi_transfer_byte(CC1101_HEADER_COMMAND | cmd); } drv.spi_cs_disable(); return status; } static uint8_t cc1101_spi_read_register(const uint8_t addr) { if(addr > CC1101_ADDR_MAX) return 0xFF; uint8_t hdr = addr; if(addr >= CC1101_REG_RO_MIN && addr <= CC1101_REG_RO_MAX) hdr |= CC1101_HEADER_READONLY; else hdr |= CC1101_HEADER_READ; uint8_t data = 0xFF; drv.spi_cs_enable(); if(!cc1101_spi_wait_rdy()) { drv.spi_write_byte(hdr); data = drv.spi_read_byte(); } drv.spi_cs_disable(); return data; } static uint8_t cc1101_spi_write_register(const uint8_t addr, const uint8_t data) { uint8_t status = 0x80; if(addr > CC1101_REG_RW_MAX && addr != CC1101_REG_PATABLE && addr != CC1101_REG_FIFO) return status; drv.spi_cs_enable(); if(!cc1101_spi_wait_rdy()) { drv.spi_write_byte(CC1101_HEADER_WRITE | addr); status = drv.spi_transfer_byte(data); } drv.spi_cs_disable(); return status; } // this is an internal-internal function - never use this outside of internal functions static uint8_t cc1101_spi_read_register_burst_raw(const uint8_t addr, uint8_t* data, const uint8_t l) { uint8_t i = 0; drv.spi_cs_enable(); if(!cc1101_spi_wait_rdy()) { drv.spi_write_byte(CC1101_HEADER_READ | CC1101_HEADER_BURST | addr); for(i = 0; i < l; ++i) data[i] = drv.spi_read_byte(); } drv.spi_cs_disable(); return i; } static uint8_t cc1101_spi_read_register_burst(const uint8_t addr, uint8_t* data, const uint8_t len) { if(addr <= CC1101_REG_RW_MAX) { uint8_t l = (CC1101_REG_RW_MAX - addr) + 1; l = (len > l) ? l : len; return cc1101_spi_read_register_burst_raw(addr, data, l); } else if(addr == CC1101_REG_PATABLE) { uint8_t l = (len > CC1101_PATABLE_SIZE) ? CC1101_PATABLE_SIZE : len; return cc1101_spi_read_register_burst_raw(addr, data, l); } else if(addr == CC1101_REG_FIFO) { uint8_t l = (len > CC1101_FIFO_MAX_LEN) ? CC1101_FIFO_MAX_LEN : len; return cc1101_spi_read_register_burst_raw(addr, data, l); } return 0; } // this is an internal-internal function - never use this outside of internal functions static uint8_t cc1101_spi_write_register_burst_raw(const uint8_t addr, const uint8_t* data, const uint8_t l) { uint8_t i = 0; drv.spi_cs_enable(); if(!cc1101_spi_wait_rdy()) { drv.spi_write_byte(CC1101_HEADER_WRITE | CC1101_HEADER_BURST | addr); for(i = 0; i < l; ++i) drv.spi_write_byte(data[i]); } drv.spi_cs_disable(); return i; } static uint8_t cc1101_spi_write_register_burst(const uint8_t addr, const uint8_t* data, const uint8_t len) { if(addr <= CC1101_REG_RW_MAX) { uint8_t l = (CC1101_REG_RW_MAX - addr) + 1; l = (len > l) ? l : len; return cc1101_spi_write_register_burst_raw(addr, data, l); } else if(addr == CC1101_REG_PATABLE) { uint8_t l = (len > CC1101_PATABLE_SIZE) ? CC1101_PATABLE_SIZE : len; return cc1101_spi_write_register_burst_raw(addr, data, l); } else if(addr == CC1101_REG_FIFO) { uint8_t l = (len > CC1101_FIFO_MAX_LEN) ? CC1101_FIFO_MAX_LEN : len; return cc1101_spi_write_register_burst_raw(addr, data, l); } return 0; } /* * EXTERNAL INTERFACE */ void cc1101_init(cc1101_driver_conf_t conf) { drv = conf; cc1101_soft_reset(); } void cc1101_reg_init(void) { cc1101_set_iocfg0(CC1101_GDO_CFG_3STATE); cc1101_set_iocfg1(CC1101_GDO_CFG_3STATE); cc1101_set_iocfg2(CC1101_GDO_CFG_3STATE); } void cc1101_soft_reset(void) { cc1101_spi_strobe_command(CC1101_CMD_SRES); } void cc1101_powerdown(void) { cc1101_spi_strobe_command(CC1101_CMD_SPWD); } void cc1101_idle(void) { cc1101_spi_strobe_command(CC1101_CMD_SIDLE); } void cc1101_osc_off(void) { cc1101_spi_strobe_command(CC1101_CMD_SXOFF); } void cc1101_calibrate(void) { cc1101_spi_strobe_command(CC1101_CMD_SCAL); } void cc1101_fasttxon(void) { cc1101_spi_strobe_command(CC1101_CMD_SFSTXON); } void cc1101_rx(void) { cc1101_spi_strobe_command(CC1101_CMD_SRX); } void cc1101_tx(void) { cc1101_spi_strobe_command(CC1101_CMD_STX); } void cc1101_reset_rx_fifo(void) { cc1101_spi_strobe_command(CC1101_CMD_SFRX); } void cc1101_reset_tx_fifo(void) { cc1101_spi_strobe_command(CC1101_CMD_SFTX); } char* cc1101_state_to_string(cc1101_state_t state) { switch(state) { case sleep: return "sleep"; case idle: return "idle"; case xoff: return "xoff"; case mancal: return "mancal"; case fs_wakeup: return "fs_wakeup"; case calibrate: return "calibrate"; case settling: return "settling"; case rx: return "rx"; case txrx_settling: return "txrx_settling"; case rxfifo_overflow: return "rxfifo_overflow"; case fstxon: return "fstxon"; case tx: return "tx"; case rxtx_settling: return "rxtx_settling"; case txfifo_underflow: return "txfifo_underflow"; default: return "unknown"; } } static cc1101_state_t cc1101_marcstate_to_state(uint8_t marcstate) { switch(marcstate) { case CC1101_MARCSTATE_SLEEP: return sleep; case CC1101_MARCSTATE_IDLE: return idle; case CC1101_MARCSTATE_XOFF: return xoff; case CC1101_MARCSTATE_VCOON_MC: case CC1101_MARCSTATE_REGON_MC: case CC1101_MARCSTATE_MANCAL: return mancal; case CC1101_MARCSTATE_VCOON: case CC1101_MARCSTATE_REGON: return fs_wakeup; case CC1101_MARCSTATE_STARTCAL: return calibrate; case CC1101_MARCSTATE_BWBOOST: case CC1101_MARCSTATE_FS_LOCK: case CC1101_MARCSTATE_IFADCON: return settling; case CC1101_MARCSTATE_ENDCAL: return calibrate; case CC1101_MARCSTATE_RX: case CC1101_MARCSTATE_RX_END: case CC1101_MARCSTATE_RX_RST: return rx; case CC1101_MARCSTATE_TXRX_SWITCH: return txrx_settling; case CC1101_MARCSTATE_RXFIFO_OVERFLOW: return rxfifo_overflow; case CC1101_MARCSTATE_FSTXON: return fstxon; case CC1101_MARCSTATE_TX: case CC1101_MARCSTATE_TX_END: return tx; case CC1101_MARCSTATE_RXTX_SWITCH: return rxtx_settling; case CC1101_MARCSTATE_TXFIFO_UNDERFLOW: return txfifo_underflow; default: return unknown; } } cc1101_state_t cc1101_get_state(void) { return cc1101_marcstate_to_state(cc1101_get_marcstate()); } uint32_t cc1101_get_freq_hz(void) { return (uint32_t)((float)(cc1101_get_freq()) * drv.freq_corr); } void cc1101_set_freq_hz(uint32_t hz) { uint32_t freq = (uint32_t)((float)hz / drv.freq_corr); cc1101_set_freq(freq); } // normalized register access uint8_t cc1101_get_iocfg0(void) { return cc1101_spi_read_register(CC1101_REG_RW_IOCFG0) & CC1101_REG_RW_IOCFG0_MASK; } void cc1101_set_iocfg0(uint8_t iocfg) { cc1101_spi_write_register(CC1101_REG_RW_IOCFG0, iocfg & CC1101_REG_RW_IOCFG0_MASK); } uint8_t cc1101_get_iocfg1(void) { return cc1101_spi_read_register(CC1101_REG_RW_IOCFG1) & CC1101_REG_RW_IOCFG1_MASK; } void cc1101_set_iocfg1(uint8_t iocfg) { cc1101_spi_write_register(CC1101_REG_RW_IOCFG1, iocfg & CC1101_REG_RW_IOCFG1_MASK); } uint8_t cc1101_get_iocfg2(void) { return cc1101_spi_read_register(CC1101_REG_RW_IOCFG2) & CC1101_REG_RW_IOCFG2_MASK; } void cc1101_set_iocfg2(uint8_t iocfg) { cc1101_spi_write_register(CC1101_REG_RW_IOCFG2, iocfg & CC1101_REG_RW_IOCFG2_MASK); } uint8_t cc1101_get_fifothr(void) { return cc1101_spi_read_register(CC1101_REG_RW_FIFOTHR) & CC1101_REG_RW_FIFOTHR_MASK; } void cc1101_set_fifothr(uint8_t fifothr) { cc1101_spi_write_register(CC1101_REG_RW_FIFOTHR, fifothr & CC1101_REG_RW_FIFOTHR_MASK); } uint16_t cc1101_get_sync(void) { uint8_t data[2]; cc1101_spi_read_register_burst(CC1101_REG_RW_SYNC1, data, 2); uint16_t sync = data[0] & CC1101_REG_RW_SYNC1_MASK; sync = sync << 8; sync |= data[1] & CC1101_REG_RW_SYNC0_MASK; return sync; } void cc1101_set_sync(uint16_t sync) { uint8_t data[2]; data[1] = (uint8_t)sync & CC1101_REG_RW_SYNC0_MASK; sync = sync >> 8; data[0] = (uint8_t)sync & CC1101_REG_RW_SYNC1_MASK; cc1101_spi_write_register_burst(CC1101_REG_RW_SYNC1, data, 2); } uint8_t cc1101_get_pktlen(void) { return cc1101_spi_read_register(CC1101_REG_RW_PKTLEN) & CC1101_REG_RW_PKTLEN_MASK; } void cc1101_set_pktlen(uint8_t len) { cc1101_spi_write_register(CC1101_REG_RW_PKTLEN, len & CC1101_REG_RW_PKTLEN_MASK); } uint16_t cc1101_get_pktctrl(void) { uint8_t data[2]; cc1101_spi_read_register_burst(CC1101_REG_RW_PKTCTRL1, data, 2); uint16_t ctrl = data[0] & CC1101_REG_RW_PKTCTRL1_MASK; ctrl = ctrl << 8; ctrl |= data[1] & CC1101_REG_RW_PKTCTRL0_MASK; return ctrl; } void cc1101_set_pktctrl(uint16_t ctrl) { uint8_t data[2]; data[1] = (uint8_t)ctrl & CC1101_REG_RW_PKTCTRL0_MASK; ctrl = ctrl >> 8; data[0] = (uint8_t)ctrl & CC1101_REG_RW_PKTCTRL1_MASK; cc1101_spi_write_register_burst(CC1101_REG_RW_PKTCTRL1, data, 2); } uint8_t cc1101_get_addr(void) { return cc1101_spi_read_register(CC1101_REG_RW_ADDR) & CC1101_REG_RW_ADDR_MASK; } void cc1101_set_addr(uint8_t addr) { cc1101_spi_write_register(CC1101_REG_RW_ADDR, addr & CC1101_REG_RW_ADDR_MASK); } uint8_t cc1101_get_channr(void) { return cc1101_spi_read_register(CC1101_REG_RW_CHANNR) & CC1101_REG_RW_CHANNR_MASK; } void cc1101_set_channr(uint8_t nr) { cc1101_spi_write_register(CC1101_REG_RW_CHANNR, nr & CC1101_REG_RW_CHANNR_MASK); } uint8_t cc1101_get_iffreq(void) { return cc1101_spi_read_register(CC1101_REG_RW_FSCTRL1) & CC1101_REG_RW_FSCTRL1_MASK; } void cc1101_set_iffreq(uint8_t iffreq) { cc1101_spi_write_register(CC1101_REG_RW_FSCTRL1, iffreq & CC1101_REG_RW_FSCTRL1_MASK); } uint8_t cc1101_get_freq_offset(void) { return cc1101_spi_read_register(CC1101_REG_RW_FSCTRL0) & CC1101_REG_RW_FSCTRL0_MASK; } void cc1101_set_freq_offset(uint8_t freqoff) { cc1101_spi_write_register(CC1101_REG_RW_FSCTRL0, freqoff & CC1101_REG_RW_FSCTRL0_MASK); } uint32_t cc1101_get_freq(void) { uint8_t data[3]; cc1101_spi_read_register_burst(CC1101_REG_RW_FREQ2, data, 3); uint32_t freq = data[0] & CC1101_REG_RW_FREQ2_MASK; freq = freq << 8; freq |= data[1] & CC1101_REG_RW_FREQ1_MASK; freq = freq << 8; freq |= data[2] & CC1101_REG_RW_FREQ0_MASK; return freq; } void cc1101_set_freq(uint32_t freq) { uint8_t data[3]; data[2] = (uint8_t)freq & CC1101_REG_RW_FREQ0_MASK; freq = freq >> 8; data[1] = (uint8_t)freq & CC1101_REG_RW_FREQ1_MASK; freq = freq >> 8; data[0] = (uint8_t)freq & CC1101_REG_RW_FREQ2_MASK; cc1101_spi_write_register_burst(CC1101_REG_RW_FREQ2, data, 3); } uint32_t cc1101_get_modemcfg(void) { uint8_t data[3]; cc1101_spi_read_register_burst(CC1101_REG_RW_MDMCFG2, data, 3); uint32_t cfg = data[0] & CC1101_REG_RW_MDMCFG2_MASK; cfg = cfg << 8; cfg |= data[1] & CC1101_REG_RW_MDMCFG1_MASK; cfg = cfg << 8; cfg |= data[2] & CC1101_REG_RW_MDMCFG0_MASK; return cfg; } void cc1101_set_modemcfg(uint32_t cfg) { uint8_t data[3]; data[2] = (uint8_t)cfg & CC1101_REG_RW_MDMCFG0_MASK; cfg = cfg >> 8; data[1] = (uint8_t)cfg & CC1101_REG_RW_MDMCFG1_MASK; cfg = cfg >> 8; data[0] = (uint8_t)cfg & CC1101_REG_RW_MDMCFG2_MASK; cc1101_spi_write_register_burst(CC1101_REG_RW_MDMCFG2, data, 3); } uint16_t cc1101_get_drate_bw(void) { uint8_t data[2]; cc1101_spi_read_register_burst(CC1101_REG_RW_MDMCFG4, data, 2); uint16_t cfg = data[0] & CC1101_REG_RW_MDMCFG4_MASK; cfg = cfg << 8; cfg |= data[1] & CC1101_REG_RW_MDMCFG3_MASK; return cfg; } void cc1101_set_drate_bw(uint16_t cfg) { uint8_t data[2]; data[1] = (uint8_t)cfg & CC1101_REG_RW_MDMCFG3_MASK; cfg = cfg >> 8; data[0] = (uint8_t)cfg & CC1101_REG_RW_MDMCFG4_MASK; cc1101_spi_write_register_burst(CC1101_REG_RW_MDMCFG4, data, 2); } uint8_t cc1101_get_deviatn(void) { return cc1101_spi_read_register(CC1101_REG_RW_DEVIATN) & CC1101_REG_RW_DEVIATN_MASK; } void cc1101_set_deviatn(uint8_t dev) { cc1101_spi_write_register(CC1101_REG_RW_DEVIATN, dev & CC1101_REG_RW_DEVIATN_MASK); } uint32_t cc1101_get_mcsm(void) { uint8_t data[3]; cc1101_spi_read_register_burst(CC1101_REG_RW_MCSM2, data, 3); uint32_t cfg = data[0] & CC1101_REG_RW_MCSM2_MASK; cfg = cfg << 8; cfg |= cc1101_spi_read_register(CC1101_REG_RW_MCSM1) & CC1101_REG_RW_MCSM1_MASK; cfg = cfg << 8; cfg |= cc1101_spi_read_register(CC1101_REG_RW_MCSM0) & CC1101_REG_RW_MCSM0_MASK; return cfg; } void cc1101_set_mcsm(uint32_t cfg) { uint8_t data[3]; data[2] = (uint8_t)cfg & CC1101_REG_RW_MCSM0_MASK; cfg = cfg >> 8; data[1] = (uint8_t)cfg & CC1101_REG_RW_MCSM1_MASK; cfg = cfg >> 8; data[0] = (uint8_t)cfg & CC1101_REG_RW_MCSM2_MASK; cc1101_spi_write_register_burst(CC1101_REG_RW_MCSM2, data, 3); } uint8_t cc1101_get_foccfg(void) { return cc1101_spi_read_register(CC1101_REG_RW_FOCCFG) & CC1101_REG_RW_FOCCFG_MASK; } void cc1101_set_foccfg(uint8_t cfg) { cc1101_spi_write_register(CC1101_REG_RW_FOCCFG, cfg & CC1101_REG_RW_FOCCFG_MASK); } uint8_t cc1101_get_bscfg(void) { return cc1101_spi_read_register(CC1101_REG_RW_BSCFG) & CC1101_REG_RW_BSCFG_MASK; } void cc1101_set_bscfg(uint8_t cfg) { cc1101_spi_write_register(CC1101_REG_RW_BSCFG, cfg & CC1101_REG_RW_BSCFG_MASK); } uint32_t cc1101_get_agcctrl(void) { uint8_t data[3]; cc1101_spi_read_register_burst(CC1101_REG_RW_AGCCTRL2, data, 3); uint32_t ctrl = data[0] & CC1101_REG_RW_AGCCTRL2_MASK; ctrl = ctrl << 8; ctrl |= data[1] & CC1101_REG_RW_AGCCTRL1_MASK; ctrl = ctrl << 8; ctrl |= data[2] & CC1101_REG_RW_AGCCTRL0_MASK; return ctrl; } void cc1101_set_agcctrl(uint32_t ctrl) { uint8_t data[3]; data[2] = (uint8_t)ctrl & CC1101_REG_RW_AGCCTRL0_MASK; ctrl = ctrl >> 8; data[1] = (uint8_t)ctrl & CC1101_REG_RW_AGCCTRL1_MASK; ctrl = ctrl >> 8; data[0] = (uint8_t)ctrl & CC1101_REG_RW_AGCCTRL2_MASK; cc1101_spi_write_register_burst(CC1101_REG_RW_AGCCTRL2, data, 3); } uint16_t cc1101_get_worevt(void) { uint8_t data[2]; cc1101_spi_read_register_burst(CC1101_REG_RW_WOREVT1, data, 2); uint16_t timeout = data[0] & CC1101_REG_RW_WOREVT1_MASK; timeout = timeout << 8; timeout |= data[1] & CC1101_REG_RW_WOREVT0_MASK; return timeout; } void cc1101_set_worevt(uint16_t timeout) { uint8_t data[2]; data[1] = (uint8_t)timeout & CC1101_REG_RW_WOREVT0_MASK; timeout = timeout >> 8; data[0] = (uint8_t)timeout & CC1101_REG_RW_WOREVT1_MASK; cc1101_spi_write_register_burst(CC1101_REG_RW_WOREVT1, data, 2); } uint8_t cc1101_get_worctrl(void) { return cc1101_spi_read_register(CC1101_REG_RW_WORCTRL) & CC1101_REG_RW_WORCTRL_MASK; } void cc1101_set_worctrl(uint8_t ctrl) { cc1101_spi_write_register(CC1101_REG_RW_WORCTRL, ctrl & CC1101_REG_RW_WORCTRL_MASK); } uint16_t cc1101_get_frend(void) { uint8_t data[2]; cc1101_spi_read_register_burst(CC1101_REG_RW_FREND1, data, 2); uint16_t cfg = data[0] & CC1101_REG_RW_FREND1_MASK; cfg = cfg << 8; cfg |= data[1] & CC1101_REG_RW_FREND0_MASK; return cfg; } void cc1101_set_frend(uint16_t cfg) { uint8_t data[2]; data[1] = (uint8_t)cfg & CC1101_REG_RW_FREND0_MASK; cfg = cfg >> 8; data[0] = (uint8_t)cfg & CC1101_REG_RW_FREND1_MASK; cc1101_spi_write_register_burst(CC1101_REG_RW_FREND1, data, 2); } uint32_t cc1101_get_fscal(void) { uint8_t data[4]; cc1101_spi_read_register_burst(CC1101_REG_RW_FSCAL3, data, 4); uint32_t cal = data[0] & CC1101_REG_RW_FSCAL3_MASK; cal = cal << 8; cal |= data[1] & CC1101_REG_RW_FSCAL2_MASK; cal = cal << 8; cal |= data[2] & CC1101_REG_RW_FSCAL1_MASK; cal = cal << 8; cal |= data[3] & CC1101_REG_RW_FSCAL0_MASK; return cal; } void cc1101_set_fscal(uint32_t cal) { uint8_t data[4]; data[3] = (uint8_t)cal & CC1101_REG_RW_FSCAL0_MASK; cal = cal >> 8; data[2] = (uint8_t)cal & CC1101_REG_RW_FSCAL1_MASK; cal = cal >> 8; data[1] = (uint8_t)cal & CC1101_REG_RW_FSCAL2_MASK; cal = cal >> 8; data[0] = (uint8_t)cal & CC1101_REG_RW_FSCAL3_MASK; cc1101_spi_write_register_burst(CC1101_REG_RW_FSCAL3, data, 4); } uint16_t cc1101_get_rcctrl(void) { uint8_t data[2]; cc1101_spi_read_register_burst(CC1101_REG_RW_RCCTRL1, data, 2); uint16_t ctrl = data[0] & CC1101_REG_RW_RCCTRL1_MASK; ctrl = ctrl << 8; ctrl |= data[1] & CC1101_REG_RW_RCCTRL0_MASK; return ctrl; } void cc1101_set_rcctrl(uint16_t ctrl) { uint8_t data[2]; data[1] = (uint8_t)ctrl & CC1101_REG_RW_RCCTRL0_MASK; ctrl = ctrl >> 8; data[0] = (uint8_t)ctrl & CC1101_REG_RW_RCCTRL1_MASK; cc1101_spi_write_register_burst(CC1101_REG_RW_RCCTRL1, data, 2); } uint8_t cc1101_get_fstest(void) { return cc1101_spi_read_register(CC1101_REG_RW_FSTEST) & CC1101_REG_RW_FSTEST_MASK; } void cc1101_set_fstest(uint8_t test) { cc1101_spi_write_register(CC1101_REG_RW_FSTEST, test & CC1101_REG_RW_FSTEST_MASK); } uint8_t cc1101_get_ptest(void) { return cc1101_spi_read_register(CC1101_REG_RW_PTEST) & CC1101_REG_RW_PTEST_MASK; } void cc1101_set_ptest(uint8_t test) { cc1101_spi_write_register(CC1101_REG_RW_PTEST, test & CC1101_REG_RW_PTEST_MASK); } uint8_t cc1101_get_agctest(void) { return cc1101_spi_read_register(CC1101_REG_RW_AGCTEST) & CC1101_REG_RW_AGCTEST_MASK; } void cc1101_set_agctest(uint8_t test) { cc1101_spi_write_register(CC1101_REG_RW_AGCTEST, test & CC1101_REG_RW_AGCTEST_MASK); } uint8_t cc1101_get_test0(void) { return cc1101_spi_read_register(CC1101_REG_RW_TEST0) & CC1101_REG_RW_TEST0_MASK; } void cc1101_set_test0(uint8_t test) { cc1101_spi_write_register(CC1101_REG_RW_TEST0, test & CC1101_REG_RW_TEST0_MASK); } uint8_t cc1101_get_test1(void) { return cc1101_spi_read_register(CC1101_REG_RW_TEST1) & CC1101_REG_RW_TEST1_MASK; } void cc1101_set_test1(uint8_t test) { cc1101_spi_write_register(CC1101_REG_RW_TEST1, test & CC1101_REG_RW_TEST1_MASK); } uint8_t cc1101_get_test2(void) { return cc1101_spi_read_register(CC1101_REG_RW_TEST2) & CC1101_REG_RW_TEST2_MASK; } void cc1101_set_test2(uint8_t test) { cc1101_spi_write_register(CC1101_REG_RW_TEST2, test & CC1101_REG_RW_TEST2_MASK); } uint8_t cc1101_get_partnum(void) { return cc1101_spi_read_register(CC1101_REG_RO_PARTNUM) & CC1101_REG_RO_PARTNUM_MASK; } uint8_t cc1101_get_chip_version(void) { return cc1101_spi_read_register(CC1101_REG_RO_VERSION) & CC1101_REG_RO_VERSION_MASK; } uint8_t cc1101_get_freq_offset_est(void) { return cc1101_spi_read_register(CC1101_REG_RO_FREQUEST) & CC1101_REG_RO_FREQUEST_MASK; } uint8_t cc1101_get_lqi(void) { return cc1101_spi_read_register(CC1101_REG_RO_LQI) & CC1101_REG_RO_LQI_MASK; } int8_t cc1101_get_rssi(void) { return (int8_t)cc1101_spi_read_register(CC1101_REG_RO_RSSI) & CC1101_REG_RO_RSSI_MASK; } uint8_t cc1101_get_marcstate(void) { return cc1101_spi_read_register(CC1101_REG_RO_MARCSTATE) & CC1101_REG_RO_MARCSTATE_MASK; } uint16_t cc1101_get_wortime(void) { uint16_t w = cc1101_spi_read_register(CC1101_REG_RO_WORTIME1) & CC1101_REG_RO_WORTIME1_MASK; w = w << 8; w |= cc1101_spi_read_register(CC1101_REG_RO_WORTIME0) & CC1101_REG_RO_WORTIME0_MASK; return w; } uint8_t cc1101_get_pkt_status(void) { return cc1101_spi_read_register(CC1101_REG_RO_PKTSTATUS) & CC1101_REG_RO_PKTSTATUS_MASK; } uint8_t cc1101_get_vco_vc_dac(void) { return cc1101_spi_read_register(CC1101_REG_RO_VCO_VC_DAC) & CC1101_REG_RO_VCO_VC_DAC_MASK; } uint8_t cc1101_get_tx_bytes(void) { uint8_t tx_bytes = cc1101_spi_read_register(CC1101_REG_RO_TXBYTES) & CC1101_REG_RO_TXBYTES_MASK; return (tx_bytes > CC1101_FIFO_MAX_LEN) ? 0x00 : tx_bytes; } uint8_t cc1101_get_rx_bytes(void) { uint8_t rx_bytes = cc1101_spi_read_register(CC1101_REG_RO_RXBYTES) & CC1101_REG_RO_RXBYTES_MASK; return (rx_bytes > CC1101_FIFO_MAX_LEN) ? 0x00 : rx_bytes; } uint8_t cc1101_get_rcctrl0_status(void) { return cc1101_spi_read_register(CC1101_REG_RO_RCCTRL0_STATUS) & CC1101_REG_RO_RCCTRL0_STATUS_MASK; } uint8_t cc1101_get_rcctrl1_status(void) { return cc1101_spi_read_register(CC1101_REG_RO_RCCTRL1_STATUS) & CC1101_REG_RO_RCCTRL1_STATUS_MASK; } uint8_t cc1101_read_patable(uint8_t* data, const uint8_t len) { return cc1101_spi_read_register_burst(CC1101_REG_PATABLE, data, len); } uint8_t cc1101_write_patable(const uint8_t* data, const uint8_t len) { return cc1101_spi_write_register_burst(CC1101_REG_PATABLE, data, len); } uint8_t cc1101_read_rxfifo(uint8_t* data, const uint8_t len) { uint8_t rx_bytes = cc1101_get_rx_bytes(); return cc1101_spi_read_register_burst(CC1101_REG_FIFO, data, (len < rx_bytes) ? len : rx_bytes); } uint8_t cc1101_write_txfifo(const uint8_t* data, const uint8_t len) { uint8_t tx_bytes = cc1101_get_tx_bytes(); uint8_t l = CC1101_FIFO_MAX_LEN - tx_bytes; return cc1101_spi_write_register_burst(CC1101_REG_FIFO, data, (len < l) ? len : l); } static char* cc1101_config_reg_to_string(uint8_t addr) { switch(addr) { case CC1101_REG_RW_IOCFG2: return "IOCFG2"; case CC1101_REG_RW_IOCFG1: return "IOCFG1"; case CC1101_REG_RW_IOCFG0: return "IOCFG0"; case CC1101_REG_RW_FIFOTHR: return "FIFOTHR"; case CC1101_REG_RW_SYNC1: return "SYNC1"; case CC1101_REG_RW_SYNC0: return "SYNC0"; case CC1101_REG_RW_PKTLEN: return "PKTLEN"; case CC1101_REG_RW_PKTCTRL1: return "PKTCTRL1"; case CC1101_REG_RW_PKTCTRL0: return "PKTCTRL0"; case CC1101_REG_RW_ADDR: return "ADDR"; case CC1101_REG_RW_CHANNR: return "CHANNR"; case CC1101_REG_RW_FSCTRL1: return "FSCTRL1"; case CC1101_REG_RW_FSCTRL0: return "FSCTRL0"; case CC1101_REG_RW_FREQ2: return "FREQ2"; case CC1101_REG_RW_FREQ1: return "FREQ1"; case CC1101_REG_RW_FREQ0: return "FREQ0"; case CC1101_REG_RW_MDMCFG4: return "MDMCFG4"; case CC1101_REG_RW_MDMCFG3: return "MDMCFG3"; case CC1101_REG_RW_MDMCFG2: return "MDMCFG2"; case CC1101_REG_RW_MDMCFG1: return "MDMCFG1"; case CC1101_REG_RW_MDMCFG0: return "MDMCFG0"; case CC1101_REG_RW_DEVIATN: return "DEVIATN"; case CC1101_REG_RW_MCSM2: return "MCSM2"; case CC1101_REG_RW_MCSM1: return "MCSM1"; case CC1101_REG_RW_MCSM0: return "MCSM0"; case CC1101_REG_RW_FOCCFG: return "FOCCFG"; case CC1101_REG_RW_BSCFG: return "BSCFG"; case CC1101_REG_RW_AGCCTRL2: return "AGCCTRL2"; case CC1101_REG_RW_AGCCTRL1: return "AGCCTRL1"; case CC1101_REG_RW_AGCCTRL0: return "AGCCTRL0"; case CC1101_REG_RW_WOREVT1: return "WOREVT1"; case CC1101_REG_RW_WOREVT0: return "WOREVT0"; case CC1101_REG_RW_WORCTRL: return "WORCTRL"; case CC1101_REG_RW_FREND1: return "FREND1"; case CC1101_REG_RW_FREND0: return "FREND0"; case CC1101_REG_RW_FSCAL3: return "FSCAL3"; case CC1101_REG_RW_FSCAL2: return "FSCAL2"; case CC1101_REG_RW_FSCAL1: return "FSCAL1"; case CC1101_REG_RW_FSCAL0: return "FSCAL0"; case CC1101_REG_RW_RCCTRL1: return "RCCTRL1"; case CC1101_REG_RW_RCCTRL0: return "RCCTRL0"; case CC1101_REG_RW_FSTEST: return "FSTEST"; case CC1101_REG_RW_PTEST: return "PTEST"; case CC1101_REG_RW_AGCTEST: return "AGCTEST"; case CC1101_REG_RW_TEST2: return "TEST2"; case CC1101_REG_RW_TEST1: return "TEST1"; case CC1101_REG_RW_TEST0: return "TEST0"; default: return "unknown"; } } static char* cc1101_status_reg_to_string(uint8_t addr) { switch(addr) { case CC1101_REG_RO_PARTNUM: return "PARTNUM"; case CC1101_REG_RO_VERSION: return "VERSION"; case CC1101_REG_RO_FREQUEST: return "FREQUEST"; case CC1101_REG_RO_LQI: return "LQI"; case CC1101_REG_RO_RSSI: return "RSSI"; case CC1101_REG_RO_MARCSTATE: return "MARCSTATE"; case CC1101_REG_RO_WORTIME1: return "WORTIME1"; case CC1101_REG_RO_WORTIME0: return "WORTIME0"; case CC1101_REG_RO_PKTSTATUS: return "PKTSTATUS"; case CC1101_REG_RO_VCO_VC_DAC: return "VCO_VC_DAC"; case CC1101_REG_RO_TXBYTES: return "TXBYTES"; case CC1101_REG_RO_RXBYTES: return "RXBYTES"; case CC1101_REG_RO_RCCTRL1_STATUS: return "RCCTRL1_STATUS"; case CC1101_REG_RO_RCCTRL0_STATUS: return "RCCTRL0_STATUS"; default: return "unknown"; } } void cc1101_dump_register(void) { printf_P(PSTR("CC1101: register dump\r\n\r\n")); int i; printf_P(PSTR(" config (read/write) register:\r\n")); uint8_t data[(CC1101_REG_RW_MAX-CC1101_REG_RW_MIN) + 1]; uint8_t l = cc1101_spi_read_register_burst(CC1101_REG_RW_MIN, data, sizeof(data)); for(i=0; i