2 * Copyright © 2012 Keith Packard <keithp@keithp.com>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
19 #include <ao_cc1200.h>
22 #include <ao_packet.h>
24 static uint8_t ao_radio_mutex;
26 static uint8_t ao_radio_wake; /* radio ready. Also used as sleep address */
27 static uint8_t ao_radio_abort; /* radio operation should abort */
29 int8_t ao_radio_rssi; /* Last received RSSI value */
32 #define CC1200_DEBUG 0
35 #ifndef CC1200_LOW_LEVEL_DEBUG
36 #define CC1200_LOW_LEVEL_DEBUG 0
39 #define CC1200_TRACE 0
40 #define CC1200_APRS_TRACE 0
42 extern const uint32_t ao_radio_cal;
45 #define FOSC AO_CC1200_FOSC
50 #define ao_radio_select() ao_spi_get_mask(AO_CC1200_SPI_CS_PORT,(1 << AO_CC1200_SPI_CS_PIN),AO_CC1200_SPI_BUS,AO_SPI_SPEED_FAST)
51 #define ao_radio_deselect() ao_spi_put_mask(AO_CC1200_SPI_CS_PORT,(1 << AO_CC1200_SPI_CS_PIN),AO_CC1200_SPI_BUS)
52 #define ao_radio_spi_send(d,l) ao_spi_send((d), (l), AO_CC1200_SPI_BUS)
53 #define ao_radio_spi_send_fixed(d,l) ao_spi_send_fixed((d), (l), AO_CC1200_SPI_BUS)
54 #define ao_radio_spi_recv(d,l) ao_spi_recv((d), (l), AO_CC1200_SPI_BUS)
55 #define ao_radio_duplex(o,i,l) ao_spi_duplex((o), (i), (l), AO_CC1200_SPI_BUS)
58 ao_radio_reg_read(uint16_t addr)
64 printf("\t\tao_radio_reg_read (%04x): ", addr); flush();
66 if (CC1200_IS_EXTENDED(addr)) {
67 data[0] = ((1 << CC1200_READ) |
73 data[0] = ((1 << CC1200_READ) |
79 ao_radio_spi_send(data, d);
80 ao_radio_spi_recv(data, 1);
83 printf (" %02x\n", data[0]);
89 ao_radio_reg_write(uint16_t addr, uint8_t value)
95 printf("\t\tao_radio_reg_write (%04x): %02x\n", addr, value);
97 if (CC1200_IS_EXTENDED(addr)) {
98 data[0] = ((0 << CC1200_READ) |
104 data[0] = ((0 << CC1200_READ) |
105 (0 << CC1200_BURST) |
111 ao_radio_spi_send(data, d+1);
114 (void) ao_radio_reg_read(addr);
119 ao_radio_strobe(uint8_t addr)
124 printf("\t\tao_radio_strobe (%02x): ", addr); flush();
127 ao_radio_duplex(&addr, &in, 1);
130 printf("%02x\n", in); flush();
136 ao_radio_fifo_read(uint8_t *data, uint8_t len)
138 uint8_t addr = ((1 << CC1200_READ) |
139 (1 << CC1200_BURST) |
144 ao_radio_duplex(&addr, &status, 1);
145 ao_radio_spi_recv(data, len);
151 ao_radio_fifo_write_start(void)
153 uint8_t addr = ((0 << CC1200_READ) |
154 (1 << CC1200_BURST) |
159 ao_radio_duplex(&addr, &status, 1);
163 static inline uint8_t ao_radio_fifo_write_stop(uint8_t status) {
169 ao_radio_fifo_write(const uint8_t *data, uint8_t len)
171 uint8_t status = ao_radio_fifo_write_start();
172 ao_radio_spi_send(data, len);
173 return ao_radio_fifo_write_stop(status);
177 ao_radio_fifo_write_fixed(uint8_t data, uint8_t len)
179 uint8_t status = ao_radio_fifo_write_start();
180 ao_radio_spi_send_fixed(data, len);
181 return ao_radio_fifo_write_stop(status);
185 ao_radio_tx_fifo_space(void)
187 return CC1200_FIFO_SIZE - ao_radio_reg_read(CC1200_NUM_TXBYTES);
191 ao_radio_status(void)
193 return ao_radio_strobe (CC1200_SNOP);
197 ao_radio_recv_abort(void)
200 ao_wakeup(&ao_radio_wake);
203 #define ao_radio_rdf_value 0x55
208 ao_exti_disable(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN);
210 ao_wakeup(&ao_radio_wake);
214 ao_radio_start_tx(void)
216 ao_exti_enable(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN);
217 ao_radio_strobe(CC1200_STX);
221 ao_radio_start_rx(void)
223 ao_exti_enable(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN);
224 ao_radio_strobe(CC1200_SRX);
231 uint8_t state = (ao_radio_strobe(CC1200_SIDLE) >> CC1200_STATUS_STATE) & CC1200_STATUS_STATE_MASK;
232 if (state == CC1200_STATUS_STATE_IDLE)
234 if (state == CC1200_STATUS_STATE_TX_FIFO_ERROR)
235 ao_radio_strobe(CC1200_SFTX);
236 if (state == CC1200_STATUS_STATE_RX_FIFO_ERROR)
237 ao_radio_strobe(CC1200_SFRX);
239 /* Flush any pending data in the fifos */
240 ao_radio_strobe(CC1200_SFTX);
241 ao_radio_strobe(CC1200_SFRX);
242 /* Make sure the RF calibration is current */
243 ao_radio_strobe(CC1200_SCAL);
249 * fdev = fosc >> 22 * (256 + dev_m) << dev_e
251 * Deviation for 38400 baud should be 20.5kHz:
253 * 40e6 / (2 ** 22) * (256 + 13) * (2 ** 3) = 20523Hz
255 * Deviation for 9600 baud should be 5.125kHz:
257 * 40e6 / (2 ** 22) * (256 + 13) * (2 ** 1) = 5131Hz
259 * Deviation for 2400 baud should be 1.28125kHz, but cc1111 and
260 * cc115l can't do that, so we'll use 1.5kHz instead:
262 * 40e6 / (2 ** 21) * (79) = 1506Hz
265 #define PACKET_DEV_M_384 13
266 #define PACKET_DEV_E_384 3
268 #define PACKET_DEV_M_96 13
269 #define PACKET_DEV_E_96 1
271 #define PACKET_DEV_M_24 79
272 #define PACKET_DEV_E_24 0
275 * For our packet data
277 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
278 * Rdata = -------------------------------------- * fosc
281 * Given the bit period of the baseband, T, the bandwidth of the
282 * baseband signal is B = 1/(2T). The overall bandwidth of the
283 * modulated signal is then Channel bandwidth = 2Δf + 2B.
285 * 38400 -- 2 * 20500 + 38400 = 79.4 kHz
286 * 9600 -- 2 * 5.125 + 9600 = 19.9 kHz
287 * 2400 -- 2 * 1.5 + 2400 = 5.4 khz
289 * Symbol rate 38400 Baud:
291 * DATARATE_M = 1013008
295 * Symbol rate 9600 Baud:
297 * DATARATE_M = 1013008
299 * CHANBW = 26.042 (round to 19.8)
301 * Symbol rate 2400 Baud:
303 * DATARATE_M = 1013008
305 * CHANBW = 5.0 (round to 9.5)
309 #define PACKET_SYMBOL_RATE_M 1013008
310 #define PACKET_SYMBOL_RATE_E_384 8
311 #define PACKET_SYMBOL_RATE_E_96 6
312 #define PACKET_SYMBOL_RATE_E_24 4
316 #define PACKET_SYMBOL_RATE_M 239914
317 #define PACKET_SYMBOL_RATE_E_384 9
318 #define PACKET_SYMBOL_RATE_E_96 7
319 #define PACKET_SYMBOL_RATE_E_24 5
323 #define PACKET_CHAN_BW_384 ((CC1200_CHAN_BW_ADC_CIC_DECFACT_12 << CC1200_CHAN_BW_ADC_CIC_DECFACT) | \
324 (16 << CC1200_CHAN_BW_BB_CIC_DECFACT))
327 #define PACKET_CHAN_BW_96 ((CC1200_CHAN_BW_ADC_CIC_DECFACT_48 << CC1200_CHAN_BW_ADC_CIC_DECFACT) | \
328 (16 << CC1200_CHAN_BW_BB_CIC_DECFACT))
331 #define PACKET_CHAN_BW_24 ((CC1200_CHAN_BW_ADC_CIC_DECFACT_48 << CC1200_CHAN_BW_ADC_CIC_DECFACT) | \
332 (44 << CC1200_CHAN_BW_BB_CIC_DECFACT))
334 static const uint16_t packet_setup[] = {
335 CC1200_SYMBOL_RATE1, ((PACKET_SYMBOL_RATE_M >> 8) & 0xff),
336 CC1200_SYMBOL_RATE0, ((PACKET_SYMBOL_RATE_M >> 0) & 0xff),
337 CC1200_PKT_CFG2, /* Packet Configuration Reg. 2 */
338 ((0 << CC1200_PKT_CFG2_FG_MODE_EN) |
339 (CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) |
340 (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)),
341 CC1200_PKT_CFG1, /* Packet Configuration Reg. 1 */
342 ((1 << CC1200_PKT_CFG1_FEC_EN) |
343 (1 << CC1200_PKT_CFG1_WHITE_DATA) |
344 (0 << CC1200_PKT_CFG1_PN9_SWAP_EN) |
345 (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) |
346 (CC1200_PKT_CFG1_CRC_CFG_CRC16_INIT_ONES << CC1200_PKT_CFG1_CRC_CFG) |
347 (1 << CC1200_PKT_CFG1_APPEND_STATUS)),
348 CC1200_PREAMBLE_CFG1, ((CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES << CC1200_PREAMBLE_CFG1_NUM_PREAMBLE) |
349 (CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1200_PREAMBLE_CFG1_PREAMBLE_WORD)),
352 static const uint16_t packet_setup_384[] = {
353 CC1200_DEVIATION_M, PACKET_DEV_M_384,
354 CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) |
355 (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) |
356 (PACKET_DEV_E_384 << CC1200_MODCFG_DEV_E_DEV_E)),
357 CC1200_SYMBOL_RATE2, ((PACKET_SYMBOL_RATE_E_384 << CC1200_SYMBOL_RATE2_DATARATE_E) |
358 (((PACKET_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)),
359 CC1200_CHAN_BW, PACKET_CHAN_BW_384,
360 CC1200_MDMCFG2, /* General Modem Parameter Configuration Reg. 2 */
361 ((CC1200_MDMCFG2_ASK_SHAPE_8 << CC1200_MDMCFG2_ASK_SHAPE) |
362 (CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) |
363 (CC1200_MDMCFG2_UPSAMPLER_P_8 << CC1200_MDMCFG2_UPSAMPLER_P) |
364 (0 << CC1200_MDMCFG2_CFM_DATA_EN)),
367 static const uint16_t packet_setup_96[] = {
368 CC1200_DEVIATION_M, PACKET_DEV_M_96,
369 CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) |
370 (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) |
371 (PACKET_DEV_E_96 << CC1200_MODCFG_DEV_E_DEV_E)),
372 CC1200_SYMBOL_RATE2, ((PACKET_SYMBOL_RATE_E_96 << CC1200_SYMBOL_RATE2_DATARATE_E) |
373 (((PACKET_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)),
374 CC1200_CHAN_BW, PACKET_CHAN_BW_96,
375 CC1200_MDMCFG2, /* General Modem Parameter Configuration Reg. 2 */
376 ((CC1200_MDMCFG2_ASK_SHAPE_8 << CC1200_MDMCFG2_ASK_SHAPE) |
377 (CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) |
378 (CC1200_MDMCFG2_UPSAMPLER_P_32 << CC1200_MDMCFG2_UPSAMPLER_P) |
379 (0 << CC1200_MDMCFG2_CFM_DATA_EN)),
382 static const uint16_t packet_setup_24[] = {
383 CC1200_DEVIATION_M, PACKET_DEV_M_24,
384 CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) |
385 (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) |
386 (PACKET_DEV_E_24 << CC1200_MODCFG_DEV_E_DEV_E)),
387 CC1200_SYMBOL_RATE2, ((PACKET_SYMBOL_RATE_E_24 << CC1200_SYMBOL_RATE2_DATARATE_E) |
388 (((PACKET_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)),
389 CC1200_CHAN_BW, PACKET_CHAN_BW_24,
390 CC1200_MDMCFG2, /* General Modem Parameter Configuration Reg. 2 */
391 ((CC1200_MDMCFG2_ASK_SHAPE_8 << CC1200_MDMCFG2_ASK_SHAPE) |
392 (CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) |
393 (CC1200_MDMCFG2_UPSAMPLER_P_64 << CC1200_MDMCFG2_UPSAMPLER_P) |
394 (0 << CC1200_MDMCFG2_CFM_DATA_EN)),
398 * RDF deviation is 3kHz
400 * fdev = fosc >> 22 * (256 + dev_m) << dev_e dev_e != 0
401 * fdev = fosc >> 21 * dev_m dev_e == 0
403 * 40e6 / (2 ** 21) * 157 = 2995Hz
407 #define RDF_DEV_M 157
410 * For our RDF beacon, set the symbol rate to 2kBaud (for a 1kHz tone)
412 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
413 * Rdata = -------------------------------------- * fosc
416 * DATARATE_M = 669411
419 * To make the tone last for 200ms, we need 2000 * .2 = 400 bits or 50 bytes
421 #define RDF_SYMBOL_RATE_E 4
422 #define RDF_SYMBOL_RATE_M 669411
423 #define RDF_PACKET_LEN 50
425 static const uint16_t rdf_setup[] = {
426 CC1200_DEVIATION_M, RDF_DEV_M,
427 CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) |
428 (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) |
429 (RDF_DEV_E << CC1200_MODCFG_DEV_E_DEV_E)),
430 CC1200_SYMBOL_RATE2, ((RDF_SYMBOL_RATE_E << CC1200_SYMBOL_RATE2_DATARATE_E) |
431 (((RDF_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)),
432 CC1200_SYMBOL_RATE1, ((RDF_SYMBOL_RATE_M >> 8) & 0xff),
433 CC1200_SYMBOL_RATE0, ((RDF_SYMBOL_RATE_M >> 0) & 0xff),
434 CC1200_PKT_CFG2, /* Packet Configuration Reg. 2 */
435 ((0 << CC1200_PKT_CFG2_FG_MODE_EN) |
436 (CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) |
437 (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)),
438 CC1200_PKT_CFG1, /* Packet Configuration Reg. 1 */
439 ((0 << CC1200_PKT_CFG1_FEC_EN) |
440 (0 << CC1200_PKT_CFG1_WHITE_DATA) |
441 (0 << CC1200_PKT_CFG1_PN9_SWAP_EN) |
442 (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) |
443 (CC1200_PKT_CFG1_CRC_CFG_DISABLED << CC1200_PKT_CFG1_CRC_CFG) |
444 (0 << CC1200_PKT_CFG1_APPEND_STATUS)),
445 CC1200_PREAMBLE_CFG1,
446 ((CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1200_PREAMBLE_CFG1_NUM_PREAMBLE) |
447 (CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1200_PREAMBLE_CFG1_PREAMBLE_WORD)),
448 CC1200_MDMCFG2, /* General Modem Parameter Configuration Reg. 2 */
449 ((0 << CC1200_MDMCFG2_ASK_SHAPE) |
450 (0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) |
451 (12 << CC1200_MDMCFG2_UPSAMPLER_P) |
452 (0 << CC1200_MDMCFG2_CFM_DATA_EN)),
456 * APRS deviation is 3kHz
458 * fdev = fosc >> 22 * (256 + dev_m) << dev_e dev_e != 0
459 * fdev = fosc >> 21 * dev_m dev_e == 0
461 * 40e6 / (2 ** 21) * 157 = 2995Hz
465 #define APRS_DEV_M 157
468 * For our APRS beacon, set the symbol rate to 9.6kBaud (8x oversampling for 1200 baud data rate)
470 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
471 * Rdata = -------------------------------------- * fosc
474 * DATARATE_M = 1013008
477 * Rdata = 9599.998593330383301
480 #define APRS_SYMBOL_RATE_E 6
481 #define APRS_SYMBOL_RATE_M 1013008
483 static const uint16_t aprs_setup[] = {
484 CC1200_DEVIATION_M, APRS_DEV_M,
485 CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) |
486 (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) |
487 (APRS_DEV_E << CC1200_MODCFG_DEV_E_DEV_E)),
488 CC1200_SYMBOL_RATE2, ((APRS_SYMBOL_RATE_E << CC1200_SYMBOL_RATE2_DATARATE_E) |
489 (((APRS_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)),
490 CC1200_SYMBOL_RATE1, ((APRS_SYMBOL_RATE_M >> 8) & 0xff),
491 CC1200_SYMBOL_RATE0, ((APRS_SYMBOL_RATE_M >> 0) & 0xff),
492 CC1200_PKT_CFG2, /* Packet Configuration Reg. 2 */
493 ((0 << CC1200_PKT_CFG2_FG_MODE_EN) |
494 (CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) |
495 (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)),
496 CC1200_PKT_CFG1, /* Packet Configuration Reg. 1 */
497 ((0 << CC1200_PKT_CFG1_FEC_EN) |
498 (0 << CC1200_PKT_CFG1_WHITE_DATA) |
499 (0 << CC1200_PKT_CFG1_PN9_SWAP_EN) |
500 (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) |
501 (CC1200_PKT_CFG1_CRC_CFG_DISABLED << CC1200_PKT_CFG1_CRC_CFG) |
502 (0 << CC1200_PKT_CFG1_APPEND_STATUS)),
503 CC1200_PKT_CFG0, /* Packet Configuration Reg. 0 */
504 ((CC1200_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1200_PKT_CFG0_LENGTH_CONFIG) |
505 (0 << CC1200_PKT_CFG0_PKG_BIT_LEN) |
506 (0 << CC1200_PKT_CFG0_UART_MODE_EN) |
507 (0 << CC1200_PKT_CFG0_UART_SWAP_EN)),
508 CC1200_PREAMBLE_CFG1,
509 ((CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1200_PREAMBLE_CFG1_NUM_PREAMBLE) |
510 (CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1200_PREAMBLE_CFG1_PREAMBLE_WORD)),
511 CC1200_MDMCFG2, /* General Modem Parameter Configuration Reg. 2 */
512 ((CC1200_MDMCFG2_ASK_SHAPE_8 << CC1200_MDMCFG2_ASK_SHAPE) |
513 (CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) |
514 (CC1200_MDMCFG2_UPSAMPLER_P_8 << CC1200_MDMCFG2_UPSAMPLER_P) |
515 (0 << CC1200_MDMCFG2_CFM_DATA_EN)),
519 * For Test mode, we want an unmodulated carrier. To do that, we
520 * set the deviation to zero and enable a preamble so that the radio
521 * turns on before we send any data
524 static const uint16_t test_setup[] = {
525 CC1200_DEVIATION_M, 0,
526 CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) |
527 (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) |
528 (0 << CC1200_MODCFG_DEV_E_DEV_E)),
529 CC1200_SYMBOL_RATE2, ((APRS_SYMBOL_RATE_E << CC1200_SYMBOL_RATE2_DATARATE_E) |
530 (((APRS_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)),
531 CC1200_SYMBOL_RATE1, ((APRS_SYMBOL_RATE_M >> 8) & 0xff),
532 CC1200_SYMBOL_RATE0, ((APRS_SYMBOL_RATE_M >> 0) & 0xff),
533 CC1200_PKT_CFG2, ((CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) |
534 (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)),
535 CC1200_PKT_CFG1, ((0 << CC1200_PKT_CFG1_WHITE_DATA) |
536 (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) |
537 (CC1200_PKT_CFG1_CRC_CFG_DISABLED << CC1200_PKT_CFG1_CRC_CFG) |
538 (0 << CC1200_PKT_CFG1_APPEND_STATUS)),
539 CC1200_PREAMBLE_CFG1, ((CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES << CC1200_PREAMBLE_CFG1_NUM_PREAMBLE) |
540 (CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1200_PREAMBLE_CFG1_PREAMBLE_WORD)),
543 #define AO_PKT_CFG0_INFINITE ((CC1200_PKT_CFG0_LENGTH_CONFIG_INFINITE << CC1200_PKT_CFG0_LENGTH_CONFIG) | \
544 (0 << CC1200_PKT_CFG0_PKG_BIT_LEN) | \
545 (0 << CC1200_PKT_CFG0_UART_MODE_EN) | \
546 (0 << CC1200_PKT_CFG0_UART_SWAP_EN))
548 #define AO_PKT_CFG0_FIXED ((CC1200_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1200_PKT_CFG0_LENGTH_CONFIG) | \
549 (0 << CC1200_PKT_CFG0_PKG_BIT_LEN) | \
550 (0 << CC1200_PKT_CFG0_UART_MODE_EN) | \
551 (0 << CC1200_PKT_CFG0_UART_SWAP_EN))
553 static uint16_t ao_radio_mode;
555 #define AO_RADIO_MODE_BITS_PACKET 1
556 #define AO_RADIO_MODE_BITS_TX_BUF 4
557 #define AO_RADIO_MODE_BITS_TX_FINISH 8
558 #define AO_RADIO_MODE_BITS_RX 16
559 #define AO_RADIO_MODE_BITS_RDF 32
560 #define AO_RADIO_MODE_BITS_APRS 64
561 #define AO_RADIO_MODE_BITS_TEST 128
562 #define AO_RADIO_MODE_BITS_INFINITE 256
563 #define AO_RADIO_MODE_BITS_FIXED 512
565 #define AO_RADIO_MODE_NONE 0
566 #define AO_RADIO_MODE_PACKET_TX (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_FINISH)
567 #define AO_RADIO_MODE_PACKET_RX (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_RX)
568 #define AO_RADIO_MODE_RDF (AO_RADIO_MODE_BITS_RDF | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_FINISH)
569 #define AO_RADIO_MODE_APRS_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF)
570 #define AO_RADIO_MODE_APRS_LAST_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_BUF)
571 #define AO_RADIO_MODE_APRS_FINISH (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_FINISH)
572 #define AO_RADIO_MODE_TEST (AO_RADIO_MODE_BITS_TEST | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF)
575 _ao_radio_set_regs(const uint16_t *regs, int nreg)
579 for (i = 0; i < nreg; i++) {
580 ao_radio_reg_write(regs[0], regs[1]);
585 #define ao_radio_set_regs(setup) _ao_radio_set_regs(setup, (sizeof (setup) / sizeof(setup[0])) >> 1)
588 ao_radio_set_mode(uint16_t new_mode)
592 if (new_mode == ao_radio_mode)
595 changes = new_mode & (~ao_radio_mode);
597 if (changes & AO_RADIO_MODE_BITS_PACKET) {
598 ao_radio_set_regs(packet_setup);
600 switch (ao_config.radio_rate) {
602 case AO_RADIO_RATE_38400:
603 ao_radio_set_regs(packet_setup_384);
605 case AO_RADIO_RATE_9600:
606 ao_radio_set_regs(packet_setup_96);
608 case AO_RADIO_RATE_2400:
609 ao_radio_set_regs(packet_setup_24);
614 if (changes & AO_RADIO_MODE_BITS_TX_BUF) {
615 ao_radio_reg_write(AO_CC1200_INT_GPIO_IOCFG, CC1200_IOCFG_GPIO_CFG_TXFIFO_THR);
616 ao_exti_set_mode(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN, AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH);
619 if (changes & AO_RADIO_MODE_BITS_TX_FINISH) {
620 ao_radio_reg_write(AO_CC1200_INT_GPIO_IOCFG, CC1200_IOCFG_GPIO_CFG_PKT_SYNC_RXTX);
621 ao_exti_set_mode(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN, AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH);
624 if (changes & AO_RADIO_MODE_BITS_RX) {
625 ao_radio_reg_write(AO_CC1200_INT_GPIO_IOCFG, CC1200_IOCFG_GPIO_CFG_MARC_MCU_WAKEUP);
626 ao_exti_set_mode(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN, AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_HIGH);
629 if (changes & AO_RADIO_MODE_BITS_RDF)
630 ao_radio_set_regs(rdf_setup);
632 if (changes & AO_RADIO_MODE_BITS_APRS)
633 ao_radio_set_regs(aprs_setup);
635 if (changes & AO_RADIO_MODE_BITS_TEST)
636 ao_radio_set_regs(test_setup);
638 if (changes & AO_RADIO_MODE_BITS_INFINITE)
639 ao_radio_reg_write(CC1200_PKT_CFG0, AO_PKT_CFG0_INFINITE);
641 if (changes & AO_RADIO_MODE_BITS_FIXED)
642 ao_radio_reg_write(CC1200_PKT_CFG0, AO_PKT_CFG0_FIXED);
644 ao_radio_mode = new_mode;
647 static const uint16_t radio_setup[] = {
648 #include "ao_cc1200_CC1200.h"
651 static uint8_t ao_radio_configured = 0;
656 ao_radio_strobe(CC1200_SRES);
658 ao_radio_set_regs(radio_setup);
666 ao_radio_configured = 1;
670 ao_radio_set_len(uint8_t len)
672 static uint8_t last_len;
674 if (len != last_len) {
675 ao_radio_reg_write(CC1200_PKT_LEN, len);
681 ao_radio_get(uint8_t len)
683 static uint32_t last_radio_setting;
684 static uint8_t last_radio_rate;
686 ao_mutex_get(&ao_radio_mutex);
688 if (!ao_radio_configured)
690 if (ao_config.radio_setting != last_radio_setting) {
691 ao_radio_reg_write(CC1200_FREQ2, ao_config.radio_setting >> 16);
692 ao_radio_reg_write(CC1200_FREQ1, ao_config.radio_setting >> 8);
693 ao_radio_reg_write(CC1200_FREQ0, ao_config.radio_setting);
694 last_radio_setting = ao_config.radio_setting;
695 ao_radio_strobe(CC1200_SCAL);
697 if (ao_config.radio_rate != last_radio_rate) {
698 ao_radio_mode &= ~AO_RADIO_MODE_BITS_PACKET;
699 last_radio_rate = ao_config.radio_rate;
701 ao_radio_set_len(len);
704 #define ao_radio_put() ao_mutex_put(&ao_radio_mutex)
706 static inline uint8_t
709 return (ao_radio_status() >> CC1200_STATUS_STATE) & CC1200_STATUS_STATE_MASK;
714 ao_radio_show_state(char *where)
716 printf("%s: state %d len %d rxbytes %d\n",
717 where, ao_radio_state(),
718 ao_radio_reg_read(CC1200_PKT_LEN),
719 ao_radio_reg_read(CC1200_NUM_RXBYTES));
722 #define ao_radio_show_state(where)
725 /* Wait for the radio to signal an interrupt
728 ao_radio_wait_isr(uint16_t timeout)
730 ao_arch_block_interrupts();
731 while (!ao_radio_wake && !ao_radio_abort)
732 if (ao_sleep_for(&ao_radio_wake, timeout))
734 ao_arch_release_interrupts();
738 ao_rdf_start(uint8_t len)
743 ao_radio_set_mode(AO_RADIO_MODE_RDF);
753 ao_radio_wait_isr(0);
762 ao_rdf_start(AO_RADIO_RDF_LEN);
764 ao_radio_fifo_write_fixed(ao_radio_rdf_value, AO_RADIO_RDF_LEN);
770 ao_radio_continuity(uint8_t c)
775 ao_rdf_start(AO_RADIO_CONT_TOTAL_LEN);
777 status = ao_radio_fifo_write_start();
778 for (i = 0; i < 3; i++) {
779 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN);
781 ao_radio_spi_send_fixed(ao_radio_rdf_value, AO_RADIO_CONT_TONE_LEN);
783 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_TONE_LEN);
785 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN);
786 status = ao_radio_fifo_write_stop(status);
792 ao_radio_rdf_abort(void)
795 ao_wakeup(&ao_radio_wake);
799 ao_radio_test_cmd(void)
802 static uint8_t radio_on;
804 if (ao_cmd_lex_c != '\n') {
806 mode = (uint8_t) ao_cmd_lex_u32;
809 if ((mode & 2) && !radio_on) {
811 ao_monitor_disable();
814 ao_packet_slave_stop();
817 ao_radio_set_mode(AO_RADIO_MODE_TEST);
818 ao_radio_strobe(CC1200_STX);
821 for (t = 0; t < 10; t++) {
822 printf ("status: %02x\n", ao_radio_status());
823 ao_delay(AO_MS_TO_TICKS(100));
830 printf ("Hit a character to stop..."); flush();
834 if ((mode & 1) && radio_on) {
845 ao_radio_send(const void *d, uint8_t size)
848 ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX);
850 ao_radio_fifo_write(d, size);
856 #define AO_RADIO_LOTS 64
859 ao_radio_send_aprs(ao_radio_fill_func fill)
861 uint8_t buf[AO_RADIO_LOTS], *b;
870 fifo_space = CC1200_FIFO_SIZE;
872 cnt = (*fill)(buf, sizeof(buf));
877 #if CC1200_APRS_TRACE
878 printf("APRS fill %d bytes done %d\n", cnt, done);
882 /* At the last buffer, set the total length */
884 ao_radio_set_len(total & 0xff);
888 uint8_t this_len = cnt;
890 /* Wait for some space in the fifo */
891 while (!ao_radio_abort && (fifo_space = ao_radio_tx_fifo_space()) == 0) {
892 #if CC1200_APRS_TRACE
893 printf("APRS space %d cnt %d\n", fifo_space, cnt); flush();
896 ao_radio_wait_isr(AO_MS_TO_TICKS(1000));
900 if (this_len > fifo_space)
901 this_len = fifo_space;
907 ao_radio_set_mode(AO_RADIO_MODE_APRS_LAST_BUF);
909 ao_radio_set_mode(AO_RADIO_MODE_APRS_FINISH);
911 ao_radio_set_mode(AO_RADIO_MODE_APRS_BUF);
913 ao_exti_enable(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN);
915 ao_radio_fifo_write(b, this_len);
917 #if CC1200_APRS_TRACE
918 printf("APRS write fifo %d space now %d\n", this_len, ao_radio_tx_fifo_space());
921 #if CC1200_APRS_TRACE
922 printf("APRS start\n");
924 ao_radio_strobe(CC1200_STX);
925 #if CC1200_APRS_TRACE
927 for (t = 0; t < 20; t++) {
928 uint8_t status = ao_radio_status();
929 uint8_t space = ao_radio_tx_fifo_space();
930 printf ("status: %02x fifo %d\n", status, space);
931 if ((status >> 4) == 2)
933 ao_delay(AO_MS_TO_TICKS(0));
940 if (ao_radio_abort) {
945 /* Wait for the transmitter to go idle */
947 #if CC1200_APRS_TRACE
948 printf("APRS wait idle\n"); flush();
950 ao_radio_wait_isr(AO_MS_TO_TICKS(1000));
951 #if CC1200_APRS_TRACE
952 printf("APRS abort %d\n", ao_radio_abort);
959 ao_radio_marc_state(void)
961 return ao_radio_reg_read(CC1200_MARCSTATE);
965 ao_radio_modem_status1(void)
967 return ao_radio_reg_read(CC1200_MODEM_STATUS1);
971 ao_radio_modem_status0(void)
973 return ao_radio_reg_read(CC1200_MODEM_STATUS0);
976 struct ao_radio_state {
979 uint8_t marc_status1;
980 uint8_t marc_status0;
981 uint8_t modem_status1;
982 uint8_t modem_status0;
986 ao_radio_fill_state(char *where, struct ao_radio_state *s)
988 strcpy(s->where, where);
989 s->marc_state = ao_radio_marc_state();
990 s->marc_status1 = ao_radio_reg_read(CC1200_MARC_STATUS1);
991 s->marc_status0 = ao_radio_reg_read(CC1200_MARC_STATUS0);
992 s->modem_status1 = ao_radio_modem_status1();
993 s->modem_status0 = ao_radio_modem_status0();
997 ao_radio_dump_state(struct ao_radio_state *s)
999 printf ("%s: marc %2x marc1 %2x marc0 %2x modem1 %2x modem0 %2x\n",
1000 s->where, s->marc_state, s->marc_status1, s->marc_status0, s->modem_status1, s->modem_status0);
1005 ao_radio_recv(__xdata void *d, uint8_t size, uint8_t timeout)
1007 uint8_t success = 0;
1010 ao_radio_get(size - 2);
1011 ao_radio_set_mode(AO_RADIO_MODE_PACKET_RX);
1013 ao_radio_start_rx();
1015 while (!ao_radio_abort) {
1016 ao_radio_wait_isr(timeout);
1017 if (ao_radio_wake) {
1018 uint8_t marc_status1 = ao_radio_reg_read(CC1200_MARC_STATUS1);
1020 /* Check the receiver status to see what happened
1022 switch (marc_status1) {
1023 case CC1200_MARC_STATUS1_RX_FINISHED:
1024 case CC1200_MARC_STATUS1_ADDRESS:
1025 case CC1200_MARC_STATUS1_CRC:
1026 /* Normal return, go fetch the bytes from the FIFO
1027 * and give them back to the caller
1031 case CC1200_MARC_STATUS1_RX_TIMEOUT:
1032 case CC1200_MARC_STATUS1_RX_TERMINATION:
1033 case CC1200_MARC_STATUS1_EWOR_SYNC_LOST:
1034 case CC1200_MARC_STATUS1_MAXIMUM_LENGTH:
1035 case CC1200_MARC_STATUS1_RX_FIFO_OVERFLOW:
1036 case CC1200_MARC_STATUS1_RX_FIFO_UNDERFLOW:
1037 /* Something weird happened; reset the radio and
1043 /* some other status; go wait for the radio to do something useful
1049 uint8_t modem_status1 = ao_radio_reg_read(CC1200_MODEM_STATUS1);
1051 /* Check to see if the packet header has been seen, in which case we'll
1052 * want to keep waiting for the rest of the packet to appear
1054 if (modem_status1 & (1 << CC1200_MODEM_STATUS1_SYNC_FOUND))
1058 /* Set a timeout based on the packet length so that we make sure to
1059 * wait long enough to receive the whole thing.
1061 * timeout = bits * FEC expansion / rate
1063 switch (ao_config.radio_rate) {
1065 case AO_RADIO_RATE_38400:
1066 timeout = AO_MS_TO_TICKS(size * (8 * 2 * 10) / 384) + 1;
1068 case AO_RADIO_RATE_9600:
1069 timeout = AO_MS_TO_TICKS(size * (8 * 2 * 10) / 96) + 1;
1071 case AO_RADIO_RATE_2400:
1072 timeout = AO_MS_TO_TICKS(size * (8 * 2 * 10) / 24) + 1;
1083 status = ao_radio_fifo_read(d, size);
1085 rssi = ((int8_t *) d)[size - 2];
1086 ao_radio_rssi = rssi;
1088 /* Bound it to the representable range */
1092 /* Write it back to the packet */
1093 ((int8_t *) d)[size-2] = AO_RADIO_FROM_RSSI(rssi);
1105 static char *cc1200_state_name[] = {
1106 [CC1200_STATUS_STATE_IDLE] = "IDLE",
1107 [CC1200_STATUS_STATE_RX] = "RX",
1108 [CC1200_STATUS_STATE_TX] = "TX",
1109 [CC1200_STATUS_STATE_FSTXON] = "FSTXON",
1110 [CC1200_STATUS_STATE_CALIBRATE] = "CALIBRATE",
1111 [CC1200_STATUS_STATE_SETTLING] = "SETTLING",
1112 [CC1200_STATUS_STATE_RX_FIFO_ERROR] = "RX_FIFO_ERROR",
1113 [CC1200_STATUS_STATE_TX_FIFO_ERROR] = "TX_FIFO_ERROR",
1116 struct ao_cc1200_reg {
1121 static const struct ao_cc1200_reg ao_cc1200_reg[] = {
1122 { .addr = CC1200_IOCFG3, .name = "IOCFG3" },
1123 { .addr = CC1200_IOCFG2, .name = "IOCFG2" },
1124 { .addr = CC1200_IOCFG1, .name = "IOCFG1" },
1125 { .addr = CC1200_IOCFG0, .name = "IOCFG0" },
1126 { .addr = CC1200_SYNC3, .name = "SYNC3" },
1127 { .addr = CC1200_SYNC2, .name = "SYNC2" },
1128 { .addr = CC1200_SYNC1, .name = "SYNC1" },
1129 { .addr = CC1200_SYNC0, .name = "SYNC0" },
1130 { .addr = CC1200_SYNC_CFG1, .name = "SYNC_CFG1" },
1131 { .addr = CC1200_SYNC_CFG0, .name = "SYNC_CFG0" },
1132 { .addr = CC1200_DEVIATION_M, .name = "DEVIATION_M" },
1133 { .addr = CC1200_MODCFG_DEV_E, .name = "MODCFG_DEV_E" },
1134 { .addr = CC1200_DCFILT_CFG, .name = "DCFILT_CFG" },
1135 { .addr = CC1200_PREAMBLE_CFG1, .name = "PREAMBLE_CFG1" },
1136 { .addr = CC1200_PREAMBLE_CFG0, .name = "PREAMBLE_CFG0" },
1137 { .addr = CC1200_IQIC, .name = "IQIC" },
1138 { .addr = CC1200_CHAN_BW, .name = "CHAN_BW" },
1139 { .addr = CC1200_MDMCFG2, .name = "MDMCFG2" },
1140 { .addr = CC1200_MDMCFG1, .name = "MDMCFG1" },
1141 { .addr = CC1200_MDMCFG0, .name = "MDMCFG0" },
1142 { .addr = CC1200_SYMBOL_RATE2, .name = "SYMBOL_RATE2" },
1143 { .addr = CC1200_SYMBOL_RATE1, .name = "SYMBOL_RATE1" },
1144 { .addr = CC1200_SYMBOL_RATE0, .name = "SYMBOL_RATE0" },
1145 { .addr = CC1200_AGC_REF, .name = "AGC_REF" },
1146 { .addr = CC1200_AGC_CS_THR, .name = "AGC_CS_THR" },
1147 { .addr = CC1200_AGC_GAIN_ADJUST, .name = "AGC_GAIN_ADJUST" },
1148 { .addr = CC1200_AGC_CFG3, .name = "AGC_CFG3" },
1149 { .addr = CC1200_AGC_CFG2, .name = "AGC_CFG2" },
1150 { .addr = CC1200_AGC_CFG1, .name = "AGC_CFG1" },
1151 { .addr = CC1200_AGC_CFG0, .name = "AGC_CFG0" },
1152 { .addr = CC1200_FIFO_CFG, .name = "FIFO_CFG" },
1153 { .addr = CC1200_DEV_ADDR, .name = "DEV_ADDR" },
1154 { .addr = CC1200_SETTLING_CFG, .name = "SETTLING_CFG" },
1155 { .addr = CC1200_FS_CFG, .name = "FS_CFG" },
1156 { .addr = CC1200_WOR_CFG1, .name = "WOR_CFG1" },
1157 { .addr = CC1200_WOR_CFG0, .name = "WOR_CFG0" },
1158 { .addr = CC1200_WOR_EVENT0_MSB, .name = "WOR_EVENT0_MSB" },
1159 { .addr = CC1200_WOR_EVENT0_LSB, .name = "WOR_EVENT0_LSB" },
1160 { .addr = CC1200_RXDCM_TIME, .name = "RXDCM_TIME" },
1161 { .addr = CC1200_PKT_CFG2, .name = "PKT_CFG2" },
1162 { .addr = CC1200_PKT_CFG1, .name = "PKT_CFG1" },
1163 { .addr = CC1200_PKT_CFG0, .name = "PKT_CFG0" },
1164 { .addr = CC1200_RFEND_CFG1, .name = "RFEND_CFG1" },
1165 { .addr = CC1200_RFEND_CFG0, .name = "RFEND_CFG0" },
1166 { .addr = CC1200_PA_CFG1, .name = "PA_CFG1" },
1167 { .addr = CC1200_PA_CFG0, .name = "PA_CFG0" },
1168 { .addr = CC1200_PKT_LEN, .name = "PKT_LEN" },
1169 { .addr = CC1200_IF_MIX_CFG, .name = "IF_MIX_CFG" },
1170 { .addr = CC1200_FREQOFF_CFG, .name = "FREQOFF_CFG" },
1171 { .addr = CC1200_TOC_CFG, .name = "TOC_CFG" },
1172 { .addr = CC1200_MARC_SPARE, .name = "MARC_SPARE" },
1173 { .addr = CC1200_ECG_CFG, .name = "ECG_CFG" },
1174 { .addr = CC1200_EXT_CTRL, .name = "EXT_CTRL" },
1175 { .addr = CC1200_RCCAL_FINE, .name = "RCCAL_FINE" },
1176 { .addr = CC1200_RCCAL_COARSE, .name = "RCCAL_COARSE" },
1177 { .addr = CC1200_RCCAL_OFFSET, .name = "RCCAL_OFFSET" },
1178 { .addr = CC1200_FREQOFF1, .name = "FREQOFF1" },
1179 { .addr = CC1200_FREQOFF0, .name = "FREQOFF0" },
1180 { .addr = CC1200_FREQ2, .name = "FREQ2" },
1181 { .addr = CC1200_FREQ1, .name = "FREQ1" },
1182 { .addr = CC1200_FREQ0, .name = "FREQ0" },
1183 { .addr = CC1200_IF_ADC2, .name = "IF_ADC2" },
1184 { .addr = CC1200_IF_ADC1, .name = "IF_ADC1" },
1185 { .addr = CC1200_IF_ADC0, .name = "IF_ADC0" },
1186 { .addr = CC1200_FS_DIG1, .name = "FS_DIG1" },
1187 { .addr = CC1200_FS_DIG0, .name = "FS_DIG0" },
1188 { .addr = CC1200_FS_CAL3, .name = "FS_CAL3" },
1189 { .addr = CC1200_FS_CAL2, .name = "FS_CAL2" },
1190 { .addr = CC1200_FS_CAL1, .name = "FS_CAL1" },
1191 { .addr = CC1200_FS_CAL0, .name = "FS_CAL0" },
1192 { .addr = CC1200_FS_CHP, .name = "FS_CHP" },
1193 { .addr = CC1200_FS_DIVTWO, .name = "FS_DIVTWO" },
1194 { .addr = CC1200_FS_DSM1, .name = "FS_DSM1" },
1195 { .addr = CC1200_FS_DSM0, .name = "FS_DSM0" },
1196 { .addr = CC1200_FS_DVC1, .name = "FS_DVC1" },
1197 { .addr = CC1200_FS_DVC0, .name = "FS_DVC0" },
1198 { .addr = CC1200_FS_LBI, .name = "FS_LBI" },
1199 { .addr = CC1200_FS_PFD, .name = "FS_PFD" },
1200 { .addr = CC1200_FS_PRE, .name = "FS_PRE" },
1201 { .addr = CC1200_FS_REG_DIV_CML, .name = "FS_REG_DIV_CML" },
1202 { .addr = CC1200_FS_SPARE, .name = "FS_SPARE" },
1203 { .addr = CC1200_FS_VCO4, .name = "FS_VCO4" },
1204 { .addr = CC1200_FS_VCO3, .name = "FS_VCO3" },
1205 { .addr = CC1200_FS_VCO2, .name = "FS_VCO2" },
1206 { .addr = CC1200_FS_VCO1, .name = "FS_VCO1" },
1207 { .addr = CC1200_FS_VCO0, .name = "FS_VCO0" },
1208 { .addr = CC1200_GBIAS6, .name = "GBIAS6" },
1209 { .addr = CC1200_GBIAS5, .name = "GBIAS5" },
1210 { .addr = CC1200_GBIAS4, .name = "GBIAS4" },
1211 { .addr = CC1200_GBIAS3, .name = "GBIAS3" },
1212 { .addr = CC1200_GBIAS2, .name = "GBIAS2" },
1213 { .addr = CC1200_GBIAS1, .name = "GBIAS1" },
1214 { .addr = CC1200_GBIAS0, .name = "GBIAS0" },
1215 { .addr = CC1200_IFAMP, .name = "IFAMP" },
1216 { .addr = CC1200_LNA, .name = "LNA" },
1217 { .addr = CC1200_RXMIX, .name = "RXMIX" },
1218 { .addr = CC1200_XOSC5, .name = "XOSC5" },
1219 { .addr = CC1200_XOSC4, .name = "XOSC4" },
1220 { .addr = CC1200_XOSC3, .name = "XOSC3" },
1221 { .addr = CC1200_XOSC2, .name = "XOSC2" },
1222 { .addr = CC1200_XOSC1, .name = "XOSC1" },
1223 { .addr = CC1200_XOSC0, .name = "XOSC0" },
1224 { .addr = CC1200_ANALOG_SPARE, .name = "ANALOG_SPARE" },
1225 { .addr = CC1200_PA_CFG3, .name = "PA_CFG3" },
1226 { .addr = CC1200_WOR_TIME1, .name = "WOR_TIME1" },
1227 { .addr = CC1200_WOR_TIME0, .name = "WOR_TIME0" },
1228 { .addr = CC1200_WOR_CAPTURE1, .name = "WOR_CAPTURE1" },
1229 { .addr = CC1200_WOR_CAPTURE0, .name = "WOR_CAPTURE0" },
1230 { .addr = CC1200_BIST, .name = "BIST" },
1231 { .addr = CC1200_DCFILTOFFSET_I1, .name = "DCFILTOFFSET_I1" },
1232 { .addr = CC1200_DCFILTOFFSET_I0, .name = "DCFILTOFFSET_I0" },
1233 { .addr = CC1200_DCFILTOFFSET_Q1, .name = "DCFILTOFFSET_Q1" },
1234 { .addr = CC1200_DCFILTOFFSET_Q0, .name = "DCFILTOFFSET_Q0" },
1235 { .addr = CC1200_IQIE_I1, .name = "IQIE_I1" },
1236 { .addr = CC1200_IQIE_I0, .name = "IQIE_I0" },
1237 { .addr = CC1200_IQIE_Q1, .name = "IQIE_Q1" },
1238 { .addr = CC1200_IQIE_Q0, .name = "IQIE_Q0" },
1239 { .addr = CC1200_RSSI1, .name = "RSSI1" },
1240 { .addr = CC1200_RSSI0, .name = "RSSI0" },
1241 { .addr = CC1200_MARCSTATE, .name = "MARCSTATE" },
1242 { .addr = CC1200_LQI_VAL, .name = "LQI_VAL" },
1243 { .addr = CC1200_PQT_SYNC_ERR, .name = "PQT_SYNC_ERR" },
1244 { .addr = CC1200_DEM_STATUS, .name = "DEM_STATUS" },
1245 { .addr = CC1200_FREQOFF_EST1, .name = "FREQOFF_EST1" },
1246 { .addr = CC1200_FREQOFF_EST0, .name = "FREQOFF_EST0" },
1247 { .addr = CC1200_AGC_GAIN3, .name = "AGC_GAIN3" },
1248 { .addr = CC1200_AGC_GAIN2, .name = "AGC_GAIN2" },
1249 { .addr = CC1200_AGC_GAIN1, .name = "AGC_GAIN1" },
1250 { .addr = CC1200_AGC_GAIN0, .name = "AGC_GAIN0" },
1251 { .addr = CC1200_SOFT_RX_DATA_OUT, .name = "SOFT_RX_DATA_OUT" },
1252 { .addr = CC1200_SOFT_TX_DATA_IN, .name = "SOFT_TX_DATA_IN" },
1253 { .addr = CC1200_ASK_SOFT_RX_DATA, .name = "ASK_SOFT_RX_DATA" },
1254 { .addr = CC1200_RNDGEN, .name = "RNDGEN" },
1255 { .addr = CC1200_MAGN2, .name = "MAGN2" },
1256 { .addr = CC1200_MAGN1, .name = "MAGN1" },
1257 { .addr = CC1200_MAGN0, .name = "MAGN0" },
1258 { .addr = CC1200_ANG1, .name = "ANG1" },
1259 { .addr = CC1200_ANG0, .name = "ANG0" },
1260 { .addr = CC1200_CHFILT_I2, .name = "CHFILT_I2" },
1261 { .addr = CC1200_CHFILT_I1, .name = "CHFILT_I1" },
1262 { .addr = CC1200_CHFILT_I0, .name = "CHFILT_I0" },
1263 { .addr = CC1200_CHFILT_Q2, .name = "CHFILT_Q2" },
1264 { .addr = CC1200_CHFILT_Q1, .name = "CHFILT_Q1" },
1265 { .addr = CC1200_CHFILT_Q0, .name = "CHFILT_Q0" },
1266 { .addr = CC1200_GPIO_STATUS, .name = "GPIO_STATUS" },
1267 { .addr = CC1200_FSCAL_CTRL, .name = "FSCAL_CTRL" },
1268 { .addr = CC1200_PHASE_ADJUST, .name = "PHASE_ADJUST" },
1269 { .addr = CC1200_PARTNUMBER, .name = "PARTNUMBER" },
1270 { .addr = CC1200_PARTVERSION, .name = "PARTVERSION" },
1271 { .addr = CC1200_SERIAL_STATUS, .name = "SERIAL_STATUS" },
1272 { .addr = CC1200_MODEM_STATUS1, .name = "MODEM_STATUS1" },
1273 { .addr = CC1200_MODEM_STATUS0, .name = "MODEM_STATUS0" },
1274 { .addr = CC1200_MARC_STATUS1, .name = "MARC_STATUS1" },
1275 { .addr = CC1200_MARC_STATUS0, .name = "MARC_STATUS0" },
1276 { .addr = CC1200_PA_IFAMP_TEST, .name = "PA_IFAMP_TEST" },
1277 { .addr = CC1200_FSRF_TEST, .name = "FSRF_TEST" },
1278 { .addr = CC1200_PRE_TEST, .name = "PRE_TEST" },
1279 { .addr = CC1200_PRE_OVR, .name = "PRE_OVR" },
1280 { .addr = CC1200_ADC_TEST, .name = "ADC_TEST" },
1281 { .addr = CC1200_DVC_TEST, .name = "DVC_TEST" },
1282 { .addr = CC1200_ATEST, .name = "ATEST" },
1283 { .addr = CC1200_ATEST_LVDS, .name = "ATEST_LVDS" },
1284 { .addr = CC1200_ATEST_MODE, .name = "ATEST_MODE" },
1285 { .addr = CC1200_XOSC_TEST1, .name = "XOSC_TEST1" },
1286 { .addr = CC1200_XOSC_TEST0, .name = "XOSC_TEST0" },
1287 { .addr = CC1200_RXFIRST, .name = "RXFIRST" },
1288 { .addr = CC1200_TXFIRST, .name = "TXFIRST" },
1289 { .addr = CC1200_RXLAST, .name = "RXLAST" },
1290 { .addr = CC1200_TXLAST, .name = "TXLAST" },
1291 { .addr = CC1200_NUM_TXBYTES, .name = "NUM_TXBYTES" },
1292 { .addr = CC1200_NUM_RXBYTES, .name = "NUM_RXBYTES" },
1293 { .addr = CC1200_FIFO_NUM_TXBYTES, .name = "FIFO_NUM_TXBYTES" },
1294 { .addr = CC1200_FIFO_NUM_RXBYTES, .name = "FIFO_NUM_RXBYTES" },
1297 #define AO_NUM_CC1200_REG (sizeof ao_cc1200_reg / sizeof ao_cc1200_reg[0])
1300 ao_radio_get_marc_status(void)
1302 return ao_radio_reg_read(CC1200_MARC_STATUS1);
1305 static void ao_radio_show(void) {
1309 ao_mutex_get(&ao_radio_mutex);
1310 status = ao_radio_status();
1311 printf ("Status: %02x\n", status);
1312 printf ("CHIP_RDY: %d\n", (status >> CC1200_STATUS_CHIP_RDY) & 1);
1313 printf ("STATE: %s\n", cc1200_state_name[(status >> CC1200_STATUS_STATE) & CC1200_STATUS_STATE_MASK]);
1314 printf ("MARC: %02x\n", ao_radio_get_marc_status());
1316 for (i = 0; i < AO_NUM_CC1200_REG; i++)
1317 printf ("\t%02x %-20.20s\n", ao_radio_reg_read(ao_cc1200_reg[i].addr), ao_cc1200_reg[i].name);
1322 static void ao_radio_beep(void) {
1326 static void ao_radio_packet(void) {
1327 static const uint8_t packet[] = {
1329 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1330 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1331 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1332 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1338 ao_radio_send(packet, sizeof (packet));
1342 ao_radio_test_recv(void)
1347 if (ao_radio_recv(bytes, 34, 0)) {
1348 if (bytes[33] & 0x80)
1352 printf (" RSSI %d", AO_RSSI_FROM_RADIO(bytes[32]));
1353 for (b = 0; b < 32; b++)
1354 printf (" %02x", bytes[b]);
1356 printf (" RSSI %02x LQI %02x", bytes[32], bytes[33]);
1362 #include <ao_aprs.h>
1367 #if PACKET_HAS_SLAVE
1368 ao_packet_slave_stop();
1375 #if CC1200_LOW_LEVEL_DEBUG
1377 ao_radio_strobe_test(void)
1382 if (ao_cmd_status != ao_cmd_success)
1384 r = ao_radio_strobe(ao_cmd_lex_i);
1385 printf ("Strobe %02x -> %02x (rdy %d state %d)\n",
1393 ao_radio_write_test(void)
1399 if (ao_cmd_status != ao_cmd_success)
1401 addr = ao_cmd_lex_i;
1403 if (ao_cmd_status != ao_cmd_success)
1405 data = ao_cmd_lex_i;
1406 printf ("Write %04x = %02x\n", addr, data);
1407 ao_radio_reg_write(addr, data);
1411 ao_radio_read_test(void)
1417 if (ao_cmd_status != ao_cmd_success)
1419 addr = ao_cmd_lex_i;
1420 data = ao_radio_reg_read(addr);
1421 printf ("Read %04x = %02x\n", addr, data);
1425 static const struct ao_cmds ao_radio_cmds[] = {
1426 { ao_radio_test_cmd, "C <1 start, 0 stop, none both>\0Radio carrier test" },
1429 { ao_radio_aprs, "G\0Send APRS packet" },
1431 { ao_radio_show, "R\0Show CC1200 status" },
1432 { ao_radio_beep, "b\0Emit an RDF beacon" },
1433 { ao_radio_packet, "p\0Send a test packet" },
1434 { ao_radio_test_recv, "q\0Recv a test packet" },
1436 #if CC1200_LOW_LEVEL_DEBUG
1437 { ao_radio_strobe_test, "A <value>\0Strobe radio" },
1438 { ao_radio_write_test, "W <addr> <value>\0Write radio reg" },
1439 { ao_radio_read_test, "B <addr>\0Read radio reg" },
1447 ao_radio_configured = 0;
1448 ao_spi_init_cs (AO_CC1200_SPI_CS_PORT, (1 << AO_CC1200_SPI_CS_PIN));
1451 AO_CC1200_SPI_CS_PORT->bsrr = ((uint32_t) (1 << AO_CC1200_SPI_CS_PIN));
1452 for (i = 0; i < 10000; i++) {
1453 if ((SPI_2_PORT->idr & (1 << SPI_2_MISO_PIN)) == 0)
1456 AO_CC1200_SPI_CS_PORT->bsrr = (1 << AO_CC1200_SPI_CS_PIN);
1458 ao_panic(AO_PANIC_SELF_TEST_CC1200);
1461 /* Enable the EXTI interrupt for the appropriate pin */
1462 ao_enable_port(AO_CC1200_INT_PORT);
1463 ao_exti_setup(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN,
1464 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH,
1467 ao_cmd_register(&ao_radio_cmds[0]);