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; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
20 #include <ao_cc1200.h>
23 #include <ao_packet.h>
28 static uint8_t ao_radio_mutex;
30 static uint8_t ao_radio_wake; /* radio ready. Also used as sleep address */
31 static uint8_t ao_radio_abort; /* radio operation should abort */
33 int8_t ao_radio_rssi; /* Last received RSSI value */
36 #define CC1200_DEBUG 0
39 #ifndef CC1200_LOW_LEVEL_DEBUG
40 #define CC1200_LOW_LEVEL_DEBUG 0
43 #define CC1200_TRACE 0
44 #define CC1200_APRS_TRACE 0
46 extern const uint32_t ao_radio_cal;
49 #define FOSC AO_CC1200_FOSC
54 #ifndef AO_CC1200_SPI_SPEED
55 #error AO_CC1200_SPI_SPEED undefined
58 #define ao_radio_select() ao_spi_get_mask(AO_CC1200_SPI_CS_PORT,(1 << AO_CC1200_SPI_CS_PIN),AO_CC1200_SPI_BUS,AO_CC1200_SPI_SPEED)
59 #define ao_radio_deselect() ao_spi_put_mask(AO_CC1200_SPI_CS_PORT,(1 << AO_CC1200_SPI_CS_PIN),AO_CC1200_SPI_BUS)
60 #define ao_radio_spi_send(d,l) ao_spi_send((d), (l), AO_CC1200_SPI_BUS)
61 #define ao_radio_spi_send_fixed(d,l) ao_spi_send_fixed((d), (l), AO_CC1200_SPI_BUS)
62 #define ao_radio_spi_recv(d,l) ao_spi_recv((d), (l), AO_CC1200_SPI_BUS)
63 #define ao_radio_duplex(o,i,l) ao_spi_duplex((o), (i), (l), AO_CC1200_SPI_BUS)
66 ao_radio_reg_read(uint16_t addr)
72 printf("\t\tao_radio_reg_read (%04x): ", addr); flush();
74 if (CC1200_IS_EXTENDED(addr)) {
75 data[0] = ((1 << CC1200_READ) |
81 data[0] = ((1 << CC1200_READ) |
87 ao_radio_spi_send(data, d);
88 ao_radio_spi_recv(data, 1);
91 printf (" %02x\n", data[0]);
97 ao_radio_reg_write(uint16_t addr, uint8_t value)
103 printf("\t\tao_radio_reg_write (%04x): %02x\n", addr, value);
105 if (CC1200_IS_EXTENDED(addr)) {
106 data[0] = ((0 << CC1200_READ) |
107 (0 << CC1200_BURST) |
112 data[0] = ((0 << CC1200_READ) |
113 (0 << CC1200_BURST) |
119 ao_radio_spi_send(data, d+1);
122 (void) ao_radio_reg_read(addr);
127 ao_radio_strobe(uint8_t addr)
132 printf("\t\tao_radio_strobe (%02x): ", addr); flush();
135 ao_radio_duplex(&addr, &in, 1);
138 printf("%02x\n", in); flush();
144 ao_radio_fifo_read(uint8_t *data, uint8_t len)
146 uint8_t addr = ((1 << CC1200_READ) |
147 (1 << CC1200_BURST) |
152 ao_radio_duplex(&addr, &status, 1);
153 ao_radio_spi_recv(data, len);
159 ao_radio_fifo_write_start(void)
161 uint8_t addr = ((0 << CC1200_READ) |
162 (1 << CC1200_BURST) |
167 ao_radio_duplex(&addr, &status, 1);
171 static inline uint8_t ao_radio_fifo_write_stop(uint8_t status) {
177 ao_radio_fifo_write(const uint8_t *data, uint8_t len)
179 uint8_t status = ao_radio_fifo_write_start();
180 ao_radio_spi_send(data, len);
181 return ao_radio_fifo_write_stop(status);
185 ao_radio_fifo_write_fixed(uint8_t data, uint8_t len)
187 uint8_t status = ao_radio_fifo_write_start();
188 ao_radio_spi_send_fixed(data, len);
189 return ao_radio_fifo_write_stop(status);
193 ao_radio_int_pin(void)
195 return ao_gpio_get(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN, AO_CC1200_INT);
199 ao_radio_status(void)
201 return ao_radio_strobe (CC1200_SNOP);
205 ao_radio_recv_abort(void)
208 ao_wakeup(&ao_radio_wake);
211 #define ao_radio_rdf_value 0x55
216 ao_exti_disable(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN);
218 ao_wakeup(&ao_radio_wake);
222 ao_radio_start_tx(void)
224 ao_exti_enable(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN);
225 ao_radio_strobe(CC1200_STX);
229 ao_radio_start_rx(void)
231 ao_exti_enable(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN);
232 ao_radio_strobe(CC1200_SRX);
239 uint8_t state = (ao_radio_strobe(CC1200_SIDLE) >> CC1200_STATUS_STATE) & CC1200_STATUS_STATE_MASK;
240 if (state == CC1200_STATUS_STATE_IDLE)
242 if (state == CC1200_STATUS_STATE_TX_FIFO_ERROR)
243 ao_radio_strobe(CC1200_SFTX);
244 if (state == CC1200_STATUS_STATE_RX_FIFO_ERROR)
245 ao_radio_strobe(CC1200_SFRX);
247 /* Flush any pending data in the fifos */
248 ao_radio_strobe(CC1200_SFTX);
249 ao_radio_strobe(CC1200_SFRX);
250 /* Make sure the RF calibration is current */
251 ao_radio_strobe(CC1200_SCAL);
257 * fdev = fosc >> 22 * (256 + dev_m) << dev_e
259 * Deviation for 38400 baud should be 20.5kHz:
261 * 40e6 / (2 ** 22) * (256 + 13) * (2 ** 3) = 20523Hz
263 * Deviation for 9600 baud should be 5.125kHz:
265 * 40e6 / (2 ** 22) * (256 + 13) * (2 ** 1) = 5131Hz
267 * Deviation for 2400 baud should be 1.28125kHz, but cc1111 and
268 * cc115l can't do that, so we'll use 1.5kHz instead:
270 * 40e6 / (2 ** 21) * (79) = 1506Hz
273 #define PACKET_DEV_M_384 13
274 #define PACKET_DEV_E_384 3
276 #define PACKET_DEV_M_96 13
277 #define PACKET_DEV_E_96 1
279 #define PACKET_DEV_M_24 79
280 #define PACKET_DEV_E_24 0
283 * For our packet data
285 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
286 * Rdata = -------------------------------------- * fosc
289 * Given the bit period of the baseband, T, the bandwidth of the
290 * baseband signal is B = 1/(2T). The overall bandwidth of the
291 * modulated signal is then Channel bandwidth = 2Δf + 2B.
293 * 38400 -- 2 * 20500 + 38400 = 79.4 kHz
294 * 9600 -- 2 * 5.125 + 9600 = 19.9 kHz
295 * 2400 -- 2 * 1.5 + 2400 = 5.4 khz
297 * Symbol rate 38400 Baud:
299 * DATARATE_M = 1013008
303 * Symbol rate 9600 Baud:
305 * DATARATE_M = 1013008
307 * CHANBW = 26.042 (round to 19.8)
309 * Symbol rate 2400 Baud:
311 * DATARATE_M = 1013008
313 * CHANBW = 5.0 (round to 9.5)
317 #define PACKET_SYMBOL_RATE_M 1013008
318 #define PACKET_SYMBOL_RATE_E_384 8
319 #define PACKET_SYMBOL_RATE_E_96 6
320 #define PACKET_SYMBOL_RATE_E_24 4
324 #define PACKET_SYMBOL_RATE_M 239914
325 #define PACKET_SYMBOL_RATE_E_384 9
326 #define PACKET_SYMBOL_RATE_E_96 7
327 #define PACKET_SYMBOL_RATE_E_24 5
331 #define PACKET_CHAN_BW_384 ((CC1200_CHAN_BW_ADC_CIC_DECFACT_12 << CC1200_CHAN_BW_ADC_CIC_DECFACT) | \
332 (16 << CC1200_CHAN_BW_BB_CIC_DECFACT))
335 #define PACKET_CHAN_BW_96 ((CC1200_CHAN_BW_ADC_CIC_DECFACT_48 << CC1200_CHAN_BW_ADC_CIC_DECFACT) | \
336 (16 << CC1200_CHAN_BW_BB_CIC_DECFACT))
339 #define PACKET_CHAN_BW_24 ((CC1200_CHAN_BW_ADC_CIC_DECFACT_48 << CC1200_CHAN_BW_ADC_CIC_DECFACT) | \
340 (44 << CC1200_CHAN_BW_BB_CIC_DECFACT))
342 static const uint16_t packet_setup[] = {
343 CC1200_SYMBOL_RATE1, ((PACKET_SYMBOL_RATE_M >> 8) & 0xff),
344 CC1200_SYMBOL_RATE0, ((PACKET_SYMBOL_RATE_M >> 0) & 0xff),
345 CC1200_PKT_CFG2, /* Packet Configuration Reg. 2 */
346 ((0 << CC1200_PKT_CFG2_FG_MODE_EN) |
347 (CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) |
348 (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)),
349 CC1200_PKT_CFG1, /* Packet Configuration Reg. 1 */
350 ((1 << CC1200_PKT_CFG1_FEC_EN) |
351 (1 << CC1200_PKT_CFG1_WHITE_DATA) |
352 (0 << CC1200_PKT_CFG1_PN9_SWAP_EN) |
353 (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) |
354 (CC1200_PKT_CFG1_CRC_CFG_CRC16_INIT_ONES << CC1200_PKT_CFG1_CRC_CFG) |
355 (1 << CC1200_PKT_CFG1_APPEND_STATUS)),
356 CC1200_PREAMBLE_CFG1, ((CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES << CC1200_PREAMBLE_CFG1_NUM_PREAMBLE) |
357 (CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1200_PREAMBLE_CFG1_PREAMBLE_WORD)),
360 static const uint16_t packet_setup_384[] = {
361 CC1200_DEVIATION_M, PACKET_DEV_M_384,
362 CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) |
363 (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) |
364 (PACKET_DEV_E_384 << CC1200_MODCFG_DEV_E_DEV_E)),
365 CC1200_SYMBOL_RATE2, ((PACKET_SYMBOL_RATE_E_384 << CC1200_SYMBOL_RATE2_DATARATE_E) |
366 (((PACKET_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)),
367 CC1200_CHAN_BW, PACKET_CHAN_BW_384,
368 CC1200_MDMCFG2, /* General Modem Parameter Configuration Reg. 2 */
369 ((CC1200_MDMCFG2_ASK_SHAPE_8 << CC1200_MDMCFG2_ASK_SHAPE) |
370 (CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) |
371 (CC1200_MDMCFG2_UPSAMPLER_P_8 << CC1200_MDMCFG2_UPSAMPLER_P) |
372 (0 << CC1200_MDMCFG2_CFM_DATA_EN)),
375 static const uint16_t packet_setup_96[] = {
376 CC1200_DEVIATION_M, PACKET_DEV_M_96,
377 CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) |
378 (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) |
379 (PACKET_DEV_E_96 << CC1200_MODCFG_DEV_E_DEV_E)),
380 CC1200_SYMBOL_RATE2, ((PACKET_SYMBOL_RATE_E_96 << CC1200_SYMBOL_RATE2_DATARATE_E) |
381 (((PACKET_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)),
382 CC1200_CHAN_BW, PACKET_CHAN_BW_96,
383 CC1200_MDMCFG2, /* General Modem Parameter Configuration Reg. 2 */
384 ((CC1200_MDMCFG2_ASK_SHAPE_8 << CC1200_MDMCFG2_ASK_SHAPE) |
385 (CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) |
386 (CC1200_MDMCFG2_UPSAMPLER_P_32 << CC1200_MDMCFG2_UPSAMPLER_P) |
387 (0 << CC1200_MDMCFG2_CFM_DATA_EN)),
390 static const uint16_t packet_setup_24[] = {
391 CC1200_DEVIATION_M, PACKET_DEV_M_24,
392 CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) |
393 (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) |
394 (PACKET_DEV_E_24 << CC1200_MODCFG_DEV_E_DEV_E)),
395 CC1200_SYMBOL_RATE2, ((PACKET_SYMBOL_RATE_E_24 << CC1200_SYMBOL_RATE2_DATARATE_E) |
396 (((PACKET_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)),
397 CC1200_CHAN_BW, PACKET_CHAN_BW_24,
398 CC1200_MDMCFG2, /* General Modem Parameter Configuration Reg. 2 */
399 ((CC1200_MDMCFG2_ASK_SHAPE_8 << CC1200_MDMCFG2_ASK_SHAPE) |
400 (CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) |
401 (CC1200_MDMCFG2_UPSAMPLER_P_64 << CC1200_MDMCFG2_UPSAMPLER_P) |
402 (0 << CC1200_MDMCFG2_CFM_DATA_EN)),
406 * RDF deviation is 3kHz
408 * fdev = fosc >> 22 * (256 + dev_m) << dev_e dev_e != 0
409 * fdev = fosc >> 21 * dev_m dev_e == 0
411 * 40e6 / (2 ** 21) * 157 = 2995Hz
415 #define RDF_DEV_M 157
418 * For our RDF beacon, set the symbol rate to 2kBaud (for a 1kHz tone)
420 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
421 * Rdata = -------------------------------------- * fosc
424 * DATARATE_M = 669411
427 * To make the tone last for 200ms, we need 2000 * .2 = 400 bits or 50 bytes
429 #define RDF_SYMBOL_RATE_E 4
430 #define RDF_SYMBOL_RATE_M 669411
431 #define RDF_PACKET_LEN 50
433 static const uint16_t rdf_setup[] = {
434 CC1200_DEVIATION_M, RDF_DEV_M,
435 CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) |
436 (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) |
437 (RDF_DEV_E << CC1200_MODCFG_DEV_E_DEV_E)),
438 CC1200_SYMBOL_RATE2, ((RDF_SYMBOL_RATE_E << CC1200_SYMBOL_RATE2_DATARATE_E) |
439 (((RDF_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)),
440 CC1200_SYMBOL_RATE1, ((RDF_SYMBOL_RATE_M >> 8) & 0xff),
441 CC1200_SYMBOL_RATE0, ((RDF_SYMBOL_RATE_M >> 0) & 0xff),
442 CC1200_PKT_CFG2, /* Packet Configuration Reg. 2 */
443 ((0 << CC1200_PKT_CFG2_FG_MODE_EN) |
444 (CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) |
445 (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)),
446 CC1200_PKT_CFG1, /* Packet Configuration Reg. 1 */
447 ((0 << CC1200_PKT_CFG1_FEC_EN) |
448 (0 << CC1200_PKT_CFG1_WHITE_DATA) |
449 (0 << CC1200_PKT_CFG1_PN9_SWAP_EN) |
450 (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) |
451 (CC1200_PKT_CFG1_CRC_CFG_DISABLED << CC1200_PKT_CFG1_CRC_CFG) |
452 (0 << CC1200_PKT_CFG1_APPEND_STATUS)),
453 CC1200_PREAMBLE_CFG1,
454 ((CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1200_PREAMBLE_CFG1_NUM_PREAMBLE) |
455 (CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1200_PREAMBLE_CFG1_PREAMBLE_WORD)),
456 CC1200_MDMCFG2, /* General Modem Parameter Configuration Reg. 2 */
457 ((0 << CC1200_MDMCFG2_ASK_SHAPE) |
458 (0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) |
459 (12 << CC1200_MDMCFG2_UPSAMPLER_P) |
460 (0 << CC1200_MDMCFG2_CFM_DATA_EN)),
464 * APRS deviation is 3kHz
466 * fdev = fosc >> 22 * (256 + dev_m) << dev_e dev_e != 0
467 * fdev = fosc >> 21 * dev_m dev_e == 0
469 * 40e6 / (2 ** 21) * 157 = 2995Hz
473 #define APRS_DEV_M 157
476 * For our APRS beacon, set the symbol rate to 9.6kBaud (8x oversampling for 1200 baud data rate)
478 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
479 * Rdata = -------------------------------------- * fosc
482 * DATARATE_M = 1013008
485 * Rdata = 9599.998593330383301
488 #define APRS_SYMBOL_RATE_E 6
489 #define APRS_SYMBOL_RATE_M 1013008
490 #define APRS_BUFFER_SIZE 64
492 static const uint16_t aprs_setup[] = {
493 CC1200_DEVIATION_M, APRS_DEV_M,
494 CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) |
495 (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) |
496 (APRS_DEV_E << CC1200_MODCFG_DEV_E_DEV_E)),
497 CC1200_SYMBOL_RATE2, ((APRS_SYMBOL_RATE_E << CC1200_SYMBOL_RATE2_DATARATE_E) |
498 (((APRS_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)),
499 CC1200_SYMBOL_RATE1, ((APRS_SYMBOL_RATE_M >> 8) & 0xff),
500 CC1200_SYMBOL_RATE0, ((APRS_SYMBOL_RATE_M >> 0) & 0xff),
501 CC1200_PKT_CFG2, /* Packet Configuration Reg. 2 */
502 ((0 << CC1200_PKT_CFG2_FG_MODE_EN) |
503 (CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) |
504 (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)),
505 CC1200_PKT_CFG1, /* Packet Configuration Reg. 1 */
506 ((0 << CC1200_PKT_CFG1_FEC_EN) |
507 (0 << CC1200_PKT_CFG1_WHITE_DATA) |
508 (0 << CC1200_PKT_CFG1_PN9_SWAP_EN) |
509 (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) |
510 (CC1200_PKT_CFG1_CRC_CFG_DISABLED << CC1200_PKT_CFG1_CRC_CFG) |
511 (0 << CC1200_PKT_CFG1_APPEND_STATUS)),
512 CC1200_PKT_CFG0, /* Packet Configuration Reg. 0 */
513 ((CC1200_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1200_PKT_CFG0_LENGTH_CONFIG) |
514 (0 << CC1200_PKT_CFG0_PKG_BIT_LEN) |
515 (0 << CC1200_PKT_CFG0_UART_MODE_EN) |
516 (0 << CC1200_PKT_CFG0_UART_SWAP_EN)),
517 CC1200_PREAMBLE_CFG1,
518 ((CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1200_PREAMBLE_CFG1_NUM_PREAMBLE) |
519 (CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1200_PREAMBLE_CFG1_PREAMBLE_WORD)),
520 CC1200_MDMCFG2, /* General Modem Parameter Configuration Reg. 2 */
521 ((CC1200_MDMCFG2_ASK_SHAPE_8 << CC1200_MDMCFG2_ASK_SHAPE) |
522 (CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) |
523 (CC1200_MDMCFG2_UPSAMPLER_P_8 << CC1200_MDMCFG2_UPSAMPLER_P) |
524 (0 << CC1200_MDMCFG2_CFM_DATA_EN)),
526 ((0 << CC1200_FIFO_CFG_CRC_AUTOFLUSH) |
527 (APRS_BUFFER_SIZE << CC1200_FIFO_CFG_FIFO_THR)),
531 * For Test mode, we want an unmodulated carrier. To do that, we
532 * set the deviation to zero and enable a preamble so that the radio
533 * turns on before we send any data
536 static const uint16_t test_setup[] = {
537 CC1200_DEVIATION_M, 0,
538 CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) |
539 (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) |
540 (0 << CC1200_MODCFG_DEV_E_DEV_E)),
541 CC1200_SYMBOL_RATE2, ((APRS_SYMBOL_RATE_E << CC1200_SYMBOL_RATE2_DATARATE_E) |
542 (((APRS_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)),
543 CC1200_SYMBOL_RATE1, ((APRS_SYMBOL_RATE_M >> 8) & 0xff),
544 CC1200_SYMBOL_RATE0, ((APRS_SYMBOL_RATE_M >> 0) & 0xff),
545 CC1200_PKT_CFG2, ((CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) |
546 (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)),
547 CC1200_PKT_CFG1, ((0 << CC1200_PKT_CFG1_WHITE_DATA) |
548 (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) |
549 (CC1200_PKT_CFG1_CRC_CFG_DISABLED << CC1200_PKT_CFG1_CRC_CFG) |
550 (0 << CC1200_PKT_CFG1_APPEND_STATUS)),
551 CC1200_PREAMBLE_CFG1, ((CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES << CC1200_PREAMBLE_CFG1_NUM_PREAMBLE) |
552 (CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1200_PREAMBLE_CFG1_PREAMBLE_WORD)),
555 #define AO_PKT_CFG0_INFINITE ((CC1200_PKT_CFG0_LENGTH_CONFIG_INFINITE << CC1200_PKT_CFG0_LENGTH_CONFIG) | \
556 (0 << CC1200_PKT_CFG0_PKG_BIT_LEN) | \
557 (0 << CC1200_PKT_CFG0_UART_MODE_EN) | \
558 (0 << CC1200_PKT_CFG0_UART_SWAP_EN))
560 #define AO_PKT_CFG0_FIXED ((CC1200_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1200_PKT_CFG0_LENGTH_CONFIG) | \
561 (0 << CC1200_PKT_CFG0_PKG_BIT_LEN) | \
562 (0 << CC1200_PKT_CFG0_UART_MODE_EN) | \
563 (0 << CC1200_PKT_CFG0_UART_SWAP_EN))
565 static uint16_t ao_radio_mode;
567 #define AO_RADIO_MODE_BITS_PACKET 1
568 #define AO_RADIO_MODE_BITS_TX_BUF 4
569 #define AO_RADIO_MODE_BITS_TX_FINISH 8
570 #define AO_RADIO_MODE_BITS_RX 16
571 #define AO_RADIO_MODE_BITS_RDF 32
572 #define AO_RADIO_MODE_BITS_APRS 64
573 #define AO_RADIO_MODE_BITS_TEST 128
574 #define AO_RADIO_MODE_BITS_INFINITE 256
575 #define AO_RADIO_MODE_BITS_FIXED 512
577 #define AO_RADIO_MODE_NONE 0
578 #define AO_RADIO_MODE_PACKET_TX (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_FINISH)
579 #define AO_RADIO_MODE_PACKET_RX (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_RX)
580 #define AO_RADIO_MODE_RDF (AO_RADIO_MODE_BITS_RDF | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_FINISH)
581 #define AO_RADIO_MODE_APRS_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF)
582 #define AO_RADIO_MODE_APRS_LAST_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_BUF)
583 #define AO_RADIO_MODE_APRS_FINISH (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_FINISH)
584 #define AO_RADIO_MODE_TEST (AO_RADIO_MODE_BITS_TEST | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF)
587 _ao_radio_set_regs(const uint16_t *regs, int nreg)
591 for (i = 0; i < nreg; i++) {
592 ao_radio_reg_write(regs[0], regs[1]);
597 #define ao_radio_set_regs(setup) _ao_radio_set_regs(setup, (sizeof (setup) / sizeof(setup[0])) >> 1)
600 ao_radio_set_mode(uint16_t new_mode)
604 if (new_mode == ao_radio_mode)
607 changes = new_mode & (~ao_radio_mode);
609 if (changes & AO_RADIO_MODE_BITS_PACKET) {
610 ao_radio_set_regs(packet_setup);
612 switch (ao_config.radio_rate) {
614 case AO_RADIO_RATE_38400:
615 ao_radio_set_regs(packet_setup_384);
617 case AO_RADIO_RATE_9600:
618 ao_radio_set_regs(packet_setup_96);
620 case AO_RADIO_RATE_2400:
621 ao_radio_set_regs(packet_setup_24);
626 if (changes & AO_RADIO_MODE_BITS_TX_BUF) {
627 ao_radio_reg_write(AO_CC1200_INT_GPIO_IOCFG, CC1200_IOCFG_GPIO_CFG_TXFIFO_THR);
628 ao_exti_set_mode(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN, AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH);
631 if (changes & AO_RADIO_MODE_BITS_TX_FINISH) {
632 ao_radio_reg_write(AO_CC1200_INT_GPIO_IOCFG, CC1200_IOCFG_GPIO_CFG_PKT_SYNC_RXTX);
633 ao_exti_set_mode(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN, AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH);
636 if (changes & AO_RADIO_MODE_BITS_RX) {
637 ao_radio_reg_write(AO_CC1200_INT_GPIO_IOCFG, CC1200_IOCFG_GPIO_CFG_MARC_MCU_WAKEUP);
638 ao_exti_set_mode(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN, AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_HIGH);
641 if (changes & AO_RADIO_MODE_BITS_RDF)
642 ao_radio_set_regs(rdf_setup);
644 if (changes & AO_RADIO_MODE_BITS_APRS)
645 ao_radio_set_regs(aprs_setup);
647 if (changes & AO_RADIO_MODE_BITS_TEST)
648 ao_radio_set_regs(test_setup);
650 if (changes & AO_RADIO_MODE_BITS_INFINITE)
651 ao_radio_reg_write(CC1200_PKT_CFG0, AO_PKT_CFG0_INFINITE);
653 if (changes & AO_RADIO_MODE_BITS_FIXED)
654 ao_radio_reg_write(CC1200_PKT_CFG0, AO_PKT_CFG0_FIXED);
656 ao_radio_mode = new_mode;
659 static const uint16_t radio_setup[] = {
660 #include "ao_cc1200_CC1200.h"
663 static uint8_t ao_radio_configured = 0;
668 ao_radio_strobe(CC1200_SRES);
670 ao_radio_set_regs(radio_setup);
678 ao_radio_configured = 1;
682 ao_radio_set_len(uint8_t len)
684 static uint8_t last_len;
686 if (len != last_len) {
687 ao_radio_reg_write(CC1200_PKT_LEN, len);
693 ao_radio_get(uint8_t len)
695 static uint32_t last_radio_setting;
696 static uint8_t last_radio_rate;
698 ao_mutex_get(&ao_radio_mutex);
700 if (!ao_radio_configured)
702 if (ao_config.radio_setting != last_radio_setting) {
703 ao_radio_reg_write(CC1200_FREQ2, ao_config.radio_setting >> 16);
704 ao_radio_reg_write(CC1200_FREQ1, ao_config.radio_setting >> 8);
705 ao_radio_reg_write(CC1200_FREQ0, ao_config.radio_setting);
706 last_radio_setting = ao_config.radio_setting;
707 ao_radio_strobe(CC1200_SCAL);
709 if (ao_config.radio_rate != last_radio_rate) {
710 ao_radio_mode &= ~AO_RADIO_MODE_BITS_PACKET;
711 last_radio_rate = ao_config.radio_rate;
713 ao_radio_set_len(len);
716 #define ao_radio_put() ao_mutex_put(&ao_radio_mutex)
718 static inline uint8_t
721 return (ao_radio_status() >> CC1200_STATUS_STATE) & CC1200_STATUS_STATE_MASK;
726 ao_radio_show_state(char *where)
728 printf("%s: state %d len %d rxbytes %d\n",
729 where, ao_radio_state(),
730 ao_radio_reg_read(CC1200_PKT_LEN),
731 ao_radio_reg_read(CC1200_NUM_RXBYTES));
734 #define ao_radio_show_state(where)
737 /* Wait for the radio to signal an interrupt
740 ao_radio_wait_isr(uint16_t timeout)
742 ao_arch_block_interrupts();
743 while (!ao_radio_wake && !ao_radio_abort)
744 if (ao_sleep_for(&ao_radio_wake, timeout))
746 ao_arch_release_interrupts();
750 ao_rdf_start(uint8_t len)
755 ao_radio_set_mode(AO_RADIO_MODE_RDF);
765 ao_radio_wait_isr(0);
774 ao_rdf_start(AO_RADIO_RDF_LEN);
776 ao_radio_fifo_write_fixed(ao_radio_rdf_value, AO_RADIO_RDF_LEN);
782 ao_radio_continuity(uint8_t c)
787 ao_rdf_start(AO_RADIO_CONT_TOTAL_LEN);
789 status = ao_radio_fifo_write_start();
790 for (i = 0; i < 3; i++) {
791 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN);
793 ao_radio_spi_send_fixed(ao_radio_rdf_value, AO_RADIO_CONT_TONE_LEN);
795 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_TONE_LEN);
797 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN);
798 status = ao_radio_fifo_write_stop(status);
804 ao_radio_rdf_abort(void)
807 ao_wakeup(&ao_radio_wake);
810 static uint8_t radio_on;
813 ao_radio_test_on(void)
817 ao_monitor_disable();
820 ao_packet_slave_stop();
826 ao_radio_set_mode(AO_RADIO_MODE_TEST);
827 ao_radio_strobe(CC1200_STX);
830 for (t = 0; t < 10; t++) {
831 printf ("status: %02x\n", ao_radio_status());
832 ao_delay(AO_MS_TO_TICKS(100));
841 ao_radio_test_off(void)
857 ao_radio_test_cmd(void)
861 if (ao_cmd_lex_c != '\n') {
863 mode = (uint8_t) ao_cmd_lex_u32;
869 printf ("Hit a character to stop..."); flush();
878 ao_radio_send(const void *d, uint8_t size)
881 ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX);
883 ao_radio_fifo_write(d, size);
889 ao_radio_send_aprs(ao_radio_fill_func fill)
891 uint8_t buf[APRS_BUFFER_SIZE];
900 while (!done && !ao_radio_abort) {
901 cnt = (*fill)(buf, sizeof(buf));
908 /* At the last buffer, set the total length */
910 ao_radio_set_len(total & 0xff);
912 /* Wait for some space in the fifo */
913 while (started && ao_radio_int_pin() != 0 && !ao_radio_abort) {
915 ao_exti_enable(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN);
916 ao_radio_wait_isr(AO_MS_TO_TICKS(1000));
922 ao_radio_set_mode(AO_RADIO_MODE_APRS_FINISH);
924 ao_radio_set_mode(AO_RADIO_MODE_APRS_BUF);
926 ao_radio_fifo_write(buf, cnt);
928 ao_radio_strobe(CC1200_STX);
932 /* Wait for the transmitter to go idle */
933 while (started && ao_radio_int_pin() != 0 && !ao_radio_abort) {
935 ao_exti_enable(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN);
936 ao_radio_wait_isr(AO_MS_TO_TICKS(1000));
945 ao_radio_marc_state(void)
947 return ao_radio_reg_read(CC1200_MARCSTATE);
951 ao_radio_modem_status1(void)
953 return ao_radio_reg_read(CC1200_MODEM_STATUS1);
957 ao_radio_modem_status0(void)
959 return ao_radio_reg_read(CC1200_MODEM_STATUS0);
962 struct ao_radio_state {
965 uint8_t marc_status1;
966 uint8_t marc_status0;
967 uint8_t modem_status1;
968 uint8_t modem_status0;
972 ao_radio_fill_state(char *where, struct ao_radio_state *s)
974 strcpy(s->where, where);
975 s->marc_state = ao_radio_marc_state();
976 s->marc_status1 = ao_radio_reg_read(CC1200_MARC_STATUS1);
977 s->marc_status0 = ao_radio_reg_read(CC1200_MARC_STATUS0);
978 s->modem_status1 = ao_radio_modem_status1();
979 s->modem_status0 = ao_radio_modem_status0();
983 ao_radio_dump_state(struct ao_radio_state *s)
985 printf ("%s: marc %2x marc1 %2x marc0 %2x modem1 %2x modem0 %2x\n",
986 s->where, s->marc_state, s->marc_status1, s->marc_status0, s->modem_status1, s->modem_status0);
991 ao_radio_recv(__xdata void *d, uint8_t size, uint8_t timeout)
996 ao_radio_get(size - 2);
997 ao_radio_set_mode(AO_RADIO_MODE_PACKET_RX);
1001 while (!ao_radio_abort) {
1002 ao_radio_wait_isr(timeout);
1003 if (ao_radio_wake) {
1004 uint8_t marc_status1 = ao_radio_reg_read(CC1200_MARC_STATUS1);
1006 /* Check the receiver status to see what happened
1008 switch (marc_status1) {
1009 case CC1200_MARC_STATUS1_RX_FINISHED:
1010 case CC1200_MARC_STATUS1_ADDRESS:
1011 case CC1200_MARC_STATUS1_CRC:
1012 /* Normal return, go fetch the bytes from the FIFO
1013 * and give them back to the caller
1017 case CC1200_MARC_STATUS1_RX_TIMEOUT:
1018 case CC1200_MARC_STATUS1_RX_TERMINATION:
1019 case CC1200_MARC_STATUS1_EWOR_SYNC_LOST:
1020 case CC1200_MARC_STATUS1_MAXIMUM_LENGTH:
1021 case CC1200_MARC_STATUS1_RX_FIFO_OVERFLOW:
1022 case CC1200_MARC_STATUS1_RX_FIFO_UNDERFLOW:
1023 /* Something weird happened; reset the radio and
1029 /* some other status; go wait for the radio to do something useful
1035 uint8_t modem_status1 = ao_radio_reg_read(CC1200_MODEM_STATUS1);
1037 /* Check to see if the packet header has been seen, in which case we'll
1038 * want to keep waiting for the rest of the packet to appear
1040 if (modem_status1 & (1 << CC1200_MODEM_STATUS1_SYNC_FOUND))
1044 /* Set a timeout based on the packet length so that we make sure to
1045 * wait long enough to receive the whole thing.
1047 * timeout = bits * FEC expansion / rate
1049 switch (ao_config.radio_rate) {
1051 case AO_RADIO_RATE_38400:
1052 timeout = AO_MS_TO_TICKS(size * (8 * 2 * 10) / 384) + 1;
1054 case AO_RADIO_RATE_9600:
1055 timeout = AO_MS_TO_TICKS(size * (8 * 2 * 10) / 96) + 1;
1057 case AO_RADIO_RATE_2400:
1058 timeout = AO_MS_TO_TICKS(size * (8 * 2 * 10) / 24) + 1;
1069 status = ao_radio_fifo_read(d, size);
1071 rssi = ((int8_t *) d)[size - 2];
1072 ao_radio_rssi = rssi;
1074 /* Bound it to the representable range */
1078 /* Write it back to the packet */
1079 ((int8_t *) d)[size-2] = AO_RADIO_FROM_RSSI(rssi);
1091 static char *cc1200_state_name[] = {
1092 [CC1200_STATUS_STATE_IDLE] = "IDLE",
1093 [CC1200_STATUS_STATE_RX] = "RX",
1094 [CC1200_STATUS_STATE_TX] = "TX",
1095 [CC1200_STATUS_STATE_FSTXON] = "FSTXON",
1096 [CC1200_STATUS_STATE_CALIBRATE] = "CALIBRATE",
1097 [CC1200_STATUS_STATE_SETTLING] = "SETTLING",
1098 [CC1200_STATUS_STATE_RX_FIFO_ERROR] = "RX_FIFO_ERROR",
1099 [CC1200_STATUS_STATE_TX_FIFO_ERROR] = "TX_FIFO_ERROR",
1102 struct ao_cc1200_reg {
1107 static const struct ao_cc1200_reg ao_cc1200_reg[] = {
1108 { .addr = CC1200_IOCFG3, .name = "IOCFG3" },
1109 { .addr = CC1200_IOCFG2, .name = "IOCFG2" },
1110 { .addr = CC1200_IOCFG1, .name = "IOCFG1" },
1111 { .addr = CC1200_IOCFG0, .name = "IOCFG0" },
1112 { .addr = CC1200_SYNC3, .name = "SYNC3" },
1113 { .addr = CC1200_SYNC2, .name = "SYNC2" },
1114 { .addr = CC1200_SYNC1, .name = "SYNC1" },
1115 { .addr = CC1200_SYNC0, .name = "SYNC0" },
1116 { .addr = CC1200_SYNC_CFG1, .name = "SYNC_CFG1" },
1117 { .addr = CC1200_SYNC_CFG0, .name = "SYNC_CFG0" },
1118 { .addr = CC1200_DEVIATION_M, .name = "DEVIATION_M" },
1119 { .addr = CC1200_MODCFG_DEV_E, .name = "MODCFG_DEV_E" },
1120 { .addr = CC1200_DCFILT_CFG, .name = "DCFILT_CFG" },
1121 { .addr = CC1200_PREAMBLE_CFG1, .name = "PREAMBLE_CFG1" },
1122 { .addr = CC1200_PREAMBLE_CFG0, .name = "PREAMBLE_CFG0" },
1123 { .addr = CC1200_IQIC, .name = "IQIC" },
1124 { .addr = CC1200_CHAN_BW, .name = "CHAN_BW" },
1125 { .addr = CC1200_MDMCFG2, .name = "MDMCFG2" },
1126 { .addr = CC1200_MDMCFG1, .name = "MDMCFG1" },
1127 { .addr = CC1200_MDMCFG0, .name = "MDMCFG0" },
1128 { .addr = CC1200_SYMBOL_RATE2, .name = "SYMBOL_RATE2" },
1129 { .addr = CC1200_SYMBOL_RATE1, .name = "SYMBOL_RATE1" },
1130 { .addr = CC1200_SYMBOL_RATE0, .name = "SYMBOL_RATE0" },
1131 { .addr = CC1200_AGC_REF, .name = "AGC_REF" },
1132 { .addr = CC1200_AGC_CS_THR, .name = "AGC_CS_THR" },
1133 { .addr = CC1200_AGC_GAIN_ADJUST, .name = "AGC_GAIN_ADJUST" },
1134 { .addr = CC1200_AGC_CFG3, .name = "AGC_CFG3" },
1135 { .addr = CC1200_AGC_CFG2, .name = "AGC_CFG2" },
1136 { .addr = CC1200_AGC_CFG1, .name = "AGC_CFG1" },
1137 { .addr = CC1200_AGC_CFG0, .name = "AGC_CFG0" },
1138 { .addr = CC1200_FIFO_CFG, .name = "FIFO_CFG" },
1139 { .addr = CC1200_DEV_ADDR, .name = "DEV_ADDR" },
1140 { .addr = CC1200_SETTLING_CFG, .name = "SETTLING_CFG" },
1141 { .addr = CC1200_FS_CFG, .name = "FS_CFG" },
1142 { .addr = CC1200_WOR_CFG1, .name = "WOR_CFG1" },
1143 { .addr = CC1200_WOR_CFG0, .name = "WOR_CFG0" },
1144 { .addr = CC1200_WOR_EVENT0_MSB, .name = "WOR_EVENT0_MSB" },
1145 { .addr = CC1200_WOR_EVENT0_LSB, .name = "WOR_EVENT0_LSB" },
1146 { .addr = CC1200_RXDCM_TIME, .name = "RXDCM_TIME" },
1147 { .addr = CC1200_PKT_CFG2, .name = "PKT_CFG2" },
1148 { .addr = CC1200_PKT_CFG1, .name = "PKT_CFG1" },
1149 { .addr = CC1200_PKT_CFG0, .name = "PKT_CFG0" },
1150 { .addr = CC1200_RFEND_CFG1, .name = "RFEND_CFG1" },
1151 { .addr = CC1200_RFEND_CFG0, .name = "RFEND_CFG0" },
1152 { .addr = CC1200_PA_CFG1, .name = "PA_CFG1" },
1153 { .addr = CC1200_PA_CFG0, .name = "PA_CFG0" },
1154 { .addr = CC1200_PKT_LEN, .name = "PKT_LEN" },
1155 { .addr = CC1200_IF_MIX_CFG, .name = "IF_MIX_CFG" },
1156 { .addr = CC1200_FREQOFF_CFG, .name = "FREQOFF_CFG" },
1157 { .addr = CC1200_TOC_CFG, .name = "TOC_CFG" },
1158 { .addr = CC1200_MARC_SPARE, .name = "MARC_SPARE" },
1159 { .addr = CC1200_ECG_CFG, .name = "ECG_CFG" },
1160 { .addr = CC1200_EXT_CTRL, .name = "EXT_CTRL" },
1161 { .addr = CC1200_RCCAL_FINE, .name = "RCCAL_FINE" },
1162 { .addr = CC1200_RCCAL_COARSE, .name = "RCCAL_COARSE" },
1163 { .addr = CC1200_RCCAL_OFFSET, .name = "RCCAL_OFFSET" },
1164 { .addr = CC1200_FREQOFF1, .name = "FREQOFF1" },
1165 { .addr = CC1200_FREQOFF0, .name = "FREQOFF0" },
1166 { .addr = CC1200_FREQ2, .name = "FREQ2" },
1167 { .addr = CC1200_FREQ1, .name = "FREQ1" },
1168 { .addr = CC1200_FREQ0, .name = "FREQ0" },
1169 { .addr = CC1200_IF_ADC2, .name = "IF_ADC2" },
1170 { .addr = CC1200_IF_ADC1, .name = "IF_ADC1" },
1171 { .addr = CC1200_IF_ADC0, .name = "IF_ADC0" },
1172 { .addr = CC1200_FS_DIG1, .name = "FS_DIG1" },
1173 { .addr = CC1200_FS_DIG0, .name = "FS_DIG0" },
1174 { .addr = CC1200_FS_CAL3, .name = "FS_CAL3" },
1175 { .addr = CC1200_FS_CAL2, .name = "FS_CAL2" },
1176 { .addr = CC1200_FS_CAL1, .name = "FS_CAL1" },
1177 { .addr = CC1200_FS_CAL0, .name = "FS_CAL0" },
1178 { .addr = CC1200_FS_CHP, .name = "FS_CHP" },
1179 { .addr = CC1200_FS_DIVTWO, .name = "FS_DIVTWO" },
1180 { .addr = CC1200_FS_DSM1, .name = "FS_DSM1" },
1181 { .addr = CC1200_FS_DSM0, .name = "FS_DSM0" },
1182 { .addr = CC1200_FS_DVC1, .name = "FS_DVC1" },
1183 { .addr = CC1200_FS_DVC0, .name = "FS_DVC0" },
1184 { .addr = CC1200_FS_LBI, .name = "FS_LBI" },
1185 { .addr = CC1200_FS_PFD, .name = "FS_PFD" },
1186 { .addr = CC1200_FS_PRE, .name = "FS_PRE" },
1187 { .addr = CC1200_FS_REG_DIV_CML, .name = "FS_REG_DIV_CML" },
1188 { .addr = CC1200_FS_SPARE, .name = "FS_SPARE" },
1189 { .addr = CC1200_FS_VCO4, .name = "FS_VCO4" },
1190 { .addr = CC1200_FS_VCO3, .name = "FS_VCO3" },
1191 { .addr = CC1200_FS_VCO2, .name = "FS_VCO2" },
1192 { .addr = CC1200_FS_VCO1, .name = "FS_VCO1" },
1193 { .addr = CC1200_FS_VCO0, .name = "FS_VCO0" },
1194 { .addr = CC1200_GBIAS6, .name = "GBIAS6" },
1195 { .addr = CC1200_GBIAS5, .name = "GBIAS5" },
1196 { .addr = CC1200_GBIAS4, .name = "GBIAS4" },
1197 { .addr = CC1200_GBIAS3, .name = "GBIAS3" },
1198 { .addr = CC1200_GBIAS2, .name = "GBIAS2" },
1199 { .addr = CC1200_GBIAS1, .name = "GBIAS1" },
1200 { .addr = CC1200_GBIAS0, .name = "GBIAS0" },
1201 { .addr = CC1200_IFAMP, .name = "IFAMP" },
1202 { .addr = CC1200_LNA, .name = "LNA" },
1203 { .addr = CC1200_RXMIX, .name = "RXMIX" },
1204 { .addr = CC1200_XOSC5, .name = "XOSC5" },
1205 { .addr = CC1200_XOSC4, .name = "XOSC4" },
1206 { .addr = CC1200_XOSC3, .name = "XOSC3" },
1207 { .addr = CC1200_XOSC2, .name = "XOSC2" },
1208 { .addr = CC1200_XOSC1, .name = "XOSC1" },
1209 { .addr = CC1200_XOSC0, .name = "XOSC0" },
1210 { .addr = CC1200_ANALOG_SPARE, .name = "ANALOG_SPARE" },
1211 { .addr = CC1200_PA_CFG3, .name = "PA_CFG3" },
1212 { .addr = CC1200_WOR_TIME1, .name = "WOR_TIME1" },
1213 { .addr = CC1200_WOR_TIME0, .name = "WOR_TIME0" },
1214 { .addr = CC1200_WOR_CAPTURE1, .name = "WOR_CAPTURE1" },
1215 { .addr = CC1200_WOR_CAPTURE0, .name = "WOR_CAPTURE0" },
1216 { .addr = CC1200_BIST, .name = "BIST" },
1217 { .addr = CC1200_DCFILTOFFSET_I1, .name = "DCFILTOFFSET_I1" },
1218 { .addr = CC1200_DCFILTOFFSET_I0, .name = "DCFILTOFFSET_I0" },
1219 { .addr = CC1200_DCFILTOFFSET_Q1, .name = "DCFILTOFFSET_Q1" },
1220 { .addr = CC1200_DCFILTOFFSET_Q0, .name = "DCFILTOFFSET_Q0" },
1221 { .addr = CC1200_IQIE_I1, .name = "IQIE_I1" },
1222 { .addr = CC1200_IQIE_I0, .name = "IQIE_I0" },
1223 { .addr = CC1200_IQIE_Q1, .name = "IQIE_Q1" },
1224 { .addr = CC1200_IQIE_Q0, .name = "IQIE_Q0" },
1225 { .addr = CC1200_RSSI1, .name = "RSSI1" },
1226 { .addr = CC1200_RSSI0, .name = "RSSI0" },
1227 { .addr = CC1200_MARCSTATE, .name = "MARCSTATE" },
1228 { .addr = CC1200_LQI_VAL, .name = "LQI_VAL" },
1229 { .addr = CC1200_PQT_SYNC_ERR, .name = "PQT_SYNC_ERR" },
1230 { .addr = CC1200_DEM_STATUS, .name = "DEM_STATUS" },
1231 { .addr = CC1200_FREQOFF_EST1, .name = "FREQOFF_EST1" },
1232 { .addr = CC1200_FREQOFF_EST0, .name = "FREQOFF_EST0" },
1233 { .addr = CC1200_AGC_GAIN3, .name = "AGC_GAIN3" },
1234 { .addr = CC1200_AGC_GAIN2, .name = "AGC_GAIN2" },
1235 { .addr = CC1200_AGC_GAIN1, .name = "AGC_GAIN1" },
1236 { .addr = CC1200_AGC_GAIN0, .name = "AGC_GAIN0" },
1237 { .addr = CC1200_SOFT_RX_DATA_OUT, .name = "SOFT_RX_DATA_OUT" },
1238 { .addr = CC1200_SOFT_TX_DATA_IN, .name = "SOFT_TX_DATA_IN" },
1239 { .addr = CC1200_ASK_SOFT_RX_DATA, .name = "ASK_SOFT_RX_DATA" },
1240 { .addr = CC1200_RNDGEN, .name = "RNDGEN" },
1241 { .addr = CC1200_MAGN2, .name = "MAGN2" },
1242 { .addr = CC1200_MAGN1, .name = "MAGN1" },
1243 { .addr = CC1200_MAGN0, .name = "MAGN0" },
1244 { .addr = CC1200_ANG1, .name = "ANG1" },
1245 { .addr = CC1200_ANG0, .name = "ANG0" },
1246 { .addr = CC1200_CHFILT_I2, .name = "CHFILT_I2" },
1247 { .addr = CC1200_CHFILT_I1, .name = "CHFILT_I1" },
1248 { .addr = CC1200_CHFILT_I0, .name = "CHFILT_I0" },
1249 { .addr = CC1200_CHFILT_Q2, .name = "CHFILT_Q2" },
1250 { .addr = CC1200_CHFILT_Q1, .name = "CHFILT_Q1" },
1251 { .addr = CC1200_CHFILT_Q0, .name = "CHFILT_Q0" },
1252 { .addr = CC1200_GPIO_STATUS, .name = "GPIO_STATUS" },
1253 { .addr = CC1200_FSCAL_CTRL, .name = "FSCAL_CTRL" },
1254 { .addr = CC1200_PHASE_ADJUST, .name = "PHASE_ADJUST" },
1255 { .addr = CC1200_PARTNUMBER, .name = "PARTNUMBER" },
1256 { .addr = CC1200_PARTVERSION, .name = "PARTVERSION" },
1257 { .addr = CC1200_SERIAL_STATUS, .name = "SERIAL_STATUS" },
1258 { .addr = CC1200_MODEM_STATUS1, .name = "MODEM_STATUS1" },
1259 { .addr = CC1200_MODEM_STATUS0, .name = "MODEM_STATUS0" },
1260 { .addr = CC1200_MARC_STATUS1, .name = "MARC_STATUS1" },
1261 { .addr = CC1200_MARC_STATUS0, .name = "MARC_STATUS0" },
1262 { .addr = CC1200_PA_IFAMP_TEST, .name = "PA_IFAMP_TEST" },
1263 { .addr = CC1200_FSRF_TEST, .name = "FSRF_TEST" },
1264 { .addr = CC1200_PRE_TEST, .name = "PRE_TEST" },
1265 { .addr = CC1200_PRE_OVR, .name = "PRE_OVR" },
1266 { .addr = CC1200_ADC_TEST, .name = "ADC_TEST" },
1267 { .addr = CC1200_DVC_TEST, .name = "DVC_TEST" },
1268 { .addr = CC1200_ATEST, .name = "ATEST" },
1269 { .addr = CC1200_ATEST_LVDS, .name = "ATEST_LVDS" },
1270 { .addr = CC1200_ATEST_MODE, .name = "ATEST_MODE" },
1271 { .addr = CC1200_XOSC_TEST1, .name = "XOSC_TEST1" },
1272 { .addr = CC1200_XOSC_TEST0, .name = "XOSC_TEST0" },
1273 { .addr = CC1200_RXFIRST, .name = "RXFIRST" },
1274 { .addr = CC1200_TXFIRST, .name = "TXFIRST" },
1275 { .addr = CC1200_RXLAST, .name = "RXLAST" },
1276 { .addr = CC1200_TXLAST, .name = "TXLAST" },
1277 { .addr = CC1200_NUM_TXBYTES, .name = "NUM_TXBYTES" },
1278 { .addr = CC1200_NUM_RXBYTES, .name = "NUM_RXBYTES" },
1279 { .addr = CC1200_FIFO_NUM_TXBYTES, .name = "FIFO_NUM_TXBYTES" },
1280 { .addr = CC1200_FIFO_NUM_RXBYTES, .name = "FIFO_NUM_RXBYTES" },
1283 #define AO_NUM_CC1200_REG (sizeof ao_cc1200_reg / sizeof ao_cc1200_reg[0])
1286 ao_radio_get_marc_status(void)
1288 return ao_radio_reg_read(CC1200_MARC_STATUS1);
1291 static void ao_radio_show(void) {
1295 ao_mutex_get(&ao_radio_mutex);
1296 status = ao_radio_status();
1297 printf ("Status: %02x\n", status);
1298 printf ("CHIP_RDY: %d\n", (status >> CC1200_STATUS_CHIP_RDY) & 1);
1299 printf ("STATE: %s\n", cc1200_state_name[(status >> CC1200_STATUS_STATE) & CC1200_STATUS_STATE_MASK]);
1300 printf ("MARC: %02x\n", ao_radio_get_marc_status());
1302 for (i = 0; i < AO_NUM_CC1200_REG; i++)
1303 printf ("\t%02x %-20.20s\n", ao_radio_reg_read(ao_cc1200_reg[i].addr), ao_cc1200_reg[i].name);
1308 static void ao_radio_beep(void) {
1312 static void ao_radio_packet(void) {
1313 static const uint8_t packet[] = {
1315 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1316 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1317 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1318 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1324 ao_radio_send(packet, sizeof (packet));
1328 ao_radio_test_recv(void)
1330 static uint8_t bytes[34];
1333 if (ao_radio_recv(bytes, 34, 0)) {
1334 if (bytes[33] & 0x80)
1338 printf (" RSSI %d", AO_RSSI_FROM_RADIO(bytes[32]));
1339 for (b = 0; b < 32; b++)
1340 printf (" %02x", bytes[b]);
1342 printf (" RSSI %02x LQI %02x", bytes[32], bytes[33]);
1348 #include <ao_aprs.h>
1353 #if PACKET_HAS_SLAVE
1354 ao_packet_slave_stop();
1361 #if CC1200_LOW_LEVEL_DEBUG
1363 ao_radio_strobe_test(void)
1368 if (ao_cmd_status != ao_cmd_success)
1370 r = ao_radio_strobe(ao_cmd_lex_i);
1371 printf ("Strobe %02x -> %02x (rdy %d state %d)\n",
1379 ao_radio_write_test(void)
1385 if (ao_cmd_status != ao_cmd_success)
1387 addr = ao_cmd_lex_i;
1389 if (ao_cmd_status != ao_cmd_success)
1391 data = ao_cmd_lex_i;
1392 printf ("Write %04x = %02x\n", addr, data);
1393 ao_radio_reg_write(addr, data);
1397 ao_radio_read_test(void)
1403 if (ao_cmd_status != ao_cmd_success)
1405 addr = ao_cmd_lex_i;
1406 data = ao_radio_reg_read(addr);
1407 printf ("Read %04x = %02x\n", addr, data);
1411 static const struct ao_cmds ao_radio_cmds[] = {
1412 { ao_radio_test_cmd, "C <1 start, 0 stop, none both>\0Radio carrier test" },
1415 { ao_radio_aprs, "G\0Send APRS packet" },
1417 { ao_radio_show, "R\0Show CC1200 status" },
1418 { ao_radio_beep, "b\0Emit an RDF beacon" },
1419 { ao_radio_packet, "p\0Send a test packet" },
1420 { ao_radio_test_recv, "q\0Recv a test packet" },
1422 #if CC1200_LOW_LEVEL_DEBUG
1423 { ao_radio_strobe_test, "A <value>\0Strobe radio" },
1424 { ao_radio_write_test, "W <addr> <value>\0Write radio reg" },
1425 { ao_radio_read_test, "B <addr>\0Read radio reg" },
1433 ao_radio_configured = 0;
1434 ao_spi_init_cs (AO_CC1200_SPI_CS_PORT, (1 << AO_CC1200_SPI_CS_PIN));
1437 AO_CC1200_SPI_CS_PORT->bsrr = ((uint32_t) (1 << AO_CC1200_SPI_CS_PIN));
1438 for (i = 0; i < 10000; i++) {
1439 if ((SPI_2_PORT->idr & (1 << SPI_2_MISO_PIN)) == 0)
1442 AO_CC1200_SPI_CS_PORT->bsrr = (1 << AO_CC1200_SPI_CS_PIN);
1444 ao_panic(AO_PANIC_SELF_TEST_CC1200);
1447 /* Enable the EXTI interrupt for the appropriate pin */
1448 ao_enable_port(AO_CC1200_INT_PORT);
1449 ao_exti_setup(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN,
1450 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH,
1453 ao_cmd_register(&ao_radio_cmds[0]);