16const uint8_t READ = 0x80;
17const uint8_t BURST = 0x40;
20const uint8_t REG_CHANNR = 0x0A;
21const uint8_t STROBE_SRES = 0x30;
22const uint8_t STROBE_SRX = 0x34;
23const uint8_t STROBE_STX = 0x35;
24const uint8_t STROBE_SIDLE = 0x36;
25const uint8_t STROBE_SFRX = 0x3A;
26const uint8_t STROBE_SFTX = 0x3B;
27const uint8_t STAT_VERSION = 0x31;
28const uint8_t STAT_RXBYTES = 0x3B;
29const uint8_t FIFO = 0x3F;
32const uint8_t STATE_IDLE = 0;
34void write_reg(
const pc_cc1101_bus *b, uint8_t addr, uint8_t val)
36 uint8_t tx[2] = {addr, val};
37 uint8_t rx[2] = {0, 0};
38 b->spi(tx, rx, 2, b->ctx);
41uint8_t read_reg(
const pc_cc1101_bus *b, uint8_t addr,
bool status)
44 uint8_t hdr = (uint8_t)(addr | READ | (status ? BURST : 0));
45 uint8_t tx[2] = {hdr, 0};
46 uint8_t rx[2] = {0, 0};
47 b->spi(tx, rx, 2, b->ctx);
51void strobe(
const pc_cc1101_bus *b, uint8_t cmd)
53 uint8_t tx[1] = {cmd};
55 b->spi(tx, rx, 1, b->ctx);
58uint8_t status_byte(
const pc_cc1101_bus *b)
60 uint8_t tx[1] = {(uint8_t)(0x3D | READ | BURST)};
62 b->spi(tx, rx, 1, b->ctx);
67int16_t pc_cc1101_rssi_dbm(uint8_t raw)
70 int16_t r = raw >= 128 ? (int16_t)raw - 256 : (int16_t)raw;
71 return (int16_t)(r / 2 - 74);
74bool pc_cc1101_init(
const pc_cc1101_bus *bus,
const pc_cc1101_config *cfg)
76 if (!bus || !bus->spi || !cfg)
80 strobe(bus, STROBE_SRES);
81 for (
size_t i = 0; i < cfg->nregs && cfg->regs; i++)
83 write_reg(bus, cfg->regs[i].addr, cfg->regs[i].value);
85 write_reg(bus, REG_CHANNR, cfg->channel);
86 uint8_t ver = read_reg(bus, STAT_VERSION,
true);
87 return ver != 0x00 && ver != 0xFF;
90bool pc_cc1101_send(
const pc_cc1101_bus *bus,
const uint8_t *data, uint8_t len)
92 if (!bus || !bus->spi || !data || len == 0 || len > 63)
96 strobe(bus, STROBE_SIDLE);
97 strobe(bus, STROBE_SFTX);
101 tx[0] = (uint8_t)(FIFO | BURST);
103 for (uint8_t i = 0; i < len; i++)
107 bus->spi(tx, rx, (uint8_t)(2 + len), bus->ctx);
108 strobe(bus, STROBE_STX);
112bool pc_cc1101_tx_done(
const pc_cc1101_bus *bus)
114 if (!bus || !bus->spi)
118 uint8_t st = (uint8_t)((status_byte(bus) >> 4) & 0x07);
119 return st == STATE_IDLE;
122void pc_cc1101_set_rx(
const pc_cc1101_bus *bus)
124 if (!bus || !bus->spi)
128 strobe(bus, STROBE_SIDLE);
129 strobe(bus, STROBE_SFRX);
130 strobe(bus, STROBE_SRX);
133int pc_cc1101_recv(
const pc_cc1101_bus *bus, uint8_t *buf, uint8_t cap, int16_t *rssi_dbm)
135 if (!bus || !bus->spi || !buf)
139 uint8_t rxbytes = (uint8_t)(read_reg(bus, STAT_RXBYTES,
true) & 0x7F);
144 uint8_t len = read_reg(bus, FIFO,
false);
145 if (len == 0 || len > 63)
147 strobe(bus, STROBE_SFRX);
153 uint8_t n = (uint8_t)(len + 2);
154 tx[0] = (uint8_t)(FIFO | READ | BURST);
155 for (uint8_t i = 0; i < n; i++)
159 bus->spi(tx, rx, (uint8_t)(1 + n), bus->ctx);
162 *rssi_dbm = pc_cc1101_rssi_dbm(rx[1 + len]);
164 uint8_t out = len < cap ? len : cap;
165 for (uint8_t i = 0; i < out; i++)
CC1101 sub-GHz radio driver (PC_ENABLE_CC1101) - TI 300-928 MHz over SPI.