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 cc1201;
30 static uint8_t ao_radio_mutex;
32 static uint8_t ao_radio_wake; /* radio ready. Also used as sleep address */
33 static uint8_t ao_radio_abort; /* radio operation should abort */
35 int8_t ao_radio_rssi; /* Last received RSSI value */
38 #define CC1200_DEBUG 0
41 #ifndef CC1200_LOW_LEVEL_DEBUG
42 #define CC1200_LOW_LEVEL_DEBUG 0
45 #define CC1200_TRACE 0
46 #define CC1200_APRS_TRACE 0
48 extern const uint32_t ao_radio_cal;
51 #define FOSC AO_CC1200_FOSC
56 #define AO_CC1200_SPI_SPEED ao_spi_speed(7700000) /* 7.7MHz max for extended memory reads */
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) |
78 data[1] = (uint8_t) addr;
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) |
109 data[1] = (uint8_t) addr;
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);
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 * CC1201 doesn't support our low bandwidth receive setups, so we use
336 * larger values for that part, leaving the bandwidth at over 50kHz
340 #define PACKET_CHAN_BW_96_CC1200 ((CC1200_CHAN_BW_ADC_CIC_DECFACT_48 << CC1200_CHAN_BW_ADC_CIC_DECFACT) | \
341 (16 << CC1200_CHAN_BW_BB_CIC_DECFACT))
343 #define PACKET_CHAN_BW_96_CC1201 ((CC1200_CHAN_BW_ADC_CIC_DECFACT_48 << CC1200_CHAN_BW_ADC_CIC_DECFACT) | \
344 (8 << CC1200_CHAN_BW_BB_CIC_DECFACT))
347 #define PACKET_CHAN_BW_24_CC1200 ((CC1200_CHAN_BW_ADC_CIC_DECFACT_48 << CC1200_CHAN_BW_ADC_CIC_DECFACT) | \
348 (44 << CC1200_CHAN_BW_BB_CIC_DECFACT))
350 #define PACKET_CHAN_BW_24_CC1201 ((CC1200_CHAN_BW_ADC_CIC_DECFACT_48 << CC1200_CHAN_BW_ADC_CIC_DECFACT) | \
351 (8 << CC1200_CHAN_BW_BB_CIC_DECFACT))
353 static const uint16_t packet_setup[] = {
354 CC1200_SYMBOL_RATE1, ((PACKET_SYMBOL_RATE_M >> 8) & 0xff),
355 CC1200_SYMBOL_RATE0, ((PACKET_SYMBOL_RATE_M >> 0) & 0xff),
356 CC1200_PKT_CFG2, /* Packet Configuration Reg. 2 */
357 ((0 << CC1200_PKT_CFG2_FG_MODE_EN) |
358 (CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) |
359 (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)),
360 CC1200_PKT_CFG1, /* Packet Configuration Reg. 1 */
361 ((1 << CC1200_PKT_CFG1_FEC_EN) |
362 (1 << CC1200_PKT_CFG1_WHITE_DATA) |
363 (0 << CC1200_PKT_CFG1_PN9_SWAP_EN) |
364 (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) |
365 (CC1200_PKT_CFG1_CRC_CFG_CRC16_INIT_ONES << CC1200_PKT_CFG1_CRC_CFG) |
366 (1 << CC1200_PKT_CFG1_APPEND_STATUS)),
367 CC1200_PREAMBLE_CFG1, ((CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES << CC1200_PREAMBLE_CFG1_NUM_PREAMBLE) |
368 (CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1200_PREAMBLE_CFG1_PREAMBLE_WORD)),
371 static const uint16_t packet_setup_384[] = {
372 CC1200_DEVIATION_M, PACKET_DEV_M_384,
373 CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) |
374 (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) |
375 (PACKET_DEV_E_384 << CC1200_MODCFG_DEV_E_DEV_E)),
376 CC1200_SYMBOL_RATE2, ((PACKET_SYMBOL_RATE_E_384 << CC1200_SYMBOL_RATE2_DATARATE_E) |
377 (((PACKET_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)),
378 CC1200_CHAN_BW, PACKET_CHAN_BW_384,
379 CC1200_MDMCFG2, /* General Modem Parameter Configuration Reg. 2 */
380 ((CC1200_MDMCFG2_ASK_SHAPE_8 << CC1200_MDMCFG2_ASK_SHAPE) |
381 (CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) |
382 (CC1200_MDMCFG2_UPSAMPLER_P_8 << CC1200_MDMCFG2_UPSAMPLER_P) |
383 (0 << CC1200_MDMCFG2_CFM_DATA_EN)),
386 static const uint16_t packet_setup_96[] = {
387 CC1200_DEVIATION_M, PACKET_DEV_M_96,
388 CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) |
389 (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) |
390 (PACKET_DEV_E_96 << CC1200_MODCFG_DEV_E_DEV_E)),
391 CC1200_SYMBOL_RATE2, ((PACKET_SYMBOL_RATE_E_96 << CC1200_SYMBOL_RATE2_DATARATE_E) |
392 (((PACKET_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)),
393 CC1200_MDMCFG2, /* General Modem Parameter Configuration Reg. 2 */
394 ((CC1200_MDMCFG2_ASK_SHAPE_8 << CC1200_MDMCFG2_ASK_SHAPE) |
395 (CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) |
396 (CC1200_MDMCFG2_UPSAMPLER_P_32 << CC1200_MDMCFG2_UPSAMPLER_P) |
397 (0 << CC1200_MDMCFG2_CFM_DATA_EN)),
400 static const uint16_t packet_setup_24[] = {
401 CC1200_DEVIATION_M, PACKET_DEV_M_24,
402 CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) |
403 (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) |
404 (PACKET_DEV_E_24 << CC1200_MODCFG_DEV_E_DEV_E)),
405 CC1200_SYMBOL_RATE2, ((PACKET_SYMBOL_RATE_E_24 << CC1200_SYMBOL_RATE2_DATARATE_E) |
406 (((PACKET_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)),
407 CC1200_MDMCFG2, /* General Modem Parameter Configuration Reg. 2 */
408 ((CC1200_MDMCFG2_ASK_SHAPE_8 << CC1200_MDMCFG2_ASK_SHAPE) |
409 (CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) |
410 (CC1200_MDMCFG2_UPSAMPLER_P_64 << CC1200_MDMCFG2_UPSAMPLER_P) |
411 (0 << CC1200_MDMCFG2_CFM_DATA_EN)),
415 * RDF deviation is 3kHz
417 * fdev = fosc >> 22 * (256 + dev_m) << dev_e dev_e != 0
418 * fdev = fosc >> 21 * dev_m dev_e == 0
420 * 40e6 / (2 ** 21) * 157 = 2995Hz
424 #define RDF_DEV_M 157
427 * For our RDF beacon, set the symbol rate to 2kBaud (for a 1kHz tone)
429 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
430 * Rdata = -------------------------------------- * fosc
433 * DATARATE_M = 669411
436 * To make the tone last for 200ms, we need 2000 * .2 = 400 bits or 50 bytes
438 #define RDF_SYMBOL_RATE_E 4
439 #define RDF_SYMBOL_RATE_M 669411
440 #define RDF_PACKET_LEN 50
442 static const uint16_t rdf_setup[] = {
443 CC1200_DEVIATION_M, RDF_DEV_M,
444 CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) |
445 (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) |
446 (RDF_DEV_E << CC1200_MODCFG_DEV_E_DEV_E)),
447 CC1200_SYMBOL_RATE2, ((RDF_SYMBOL_RATE_E << CC1200_SYMBOL_RATE2_DATARATE_E) |
448 (((RDF_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)),
449 CC1200_SYMBOL_RATE1, ((RDF_SYMBOL_RATE_M >> 8) & 0xff),
450 CC1200_SYMBOL_RATE0, ((RDF_SYMBOL_RATE_M >> 0) & 0xff),
451 CC1200_PKT_CFG2, /* Packet Configuration Reg. 2 */
452 ((0 << CC1200_PKT_CFG2_FG_MODE_EN) |
453 (CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) |
454 (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)),
455 CC1200_PKT_CFG1, /* Packet Configuration Reg. 1 */
456 ((0 << CC1200_PKT_CFG1_FEC_EN) |
457 (0 << CC1200_PKT_CFG1_WHITE_DATA) |
458 (0 << CC1200_PKT_CFG1_PN9_SWAP_EN) |
459 (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) |
460 (CC1200_PKT_CFG1_CRC_CFG_DISABLED << CC1200_PKT_CFG1_CRC_CFG) |
461 (0 << CC1200_PKT_CFG1_APPEND_STATUS)),
462 CC1200_PREAMBLE_CFG1,
463 ((CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1200_PREAMBLE_CFG1_NUM_PREAMBLE) |
464 (CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1200_PREAMBLE_CFG1_PREAMBLE_WORD)),
465 CC1200_MDMCFG2, /* General Modem Parameter Configuration Reg. 2 */
466 ((0 << CC1200_MDMCFG2_ASK_SHAPE) |
467 (0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) |
468 (12 << CC1200_MDMCFG2_UPSAMPLER_P) |
469 (0 << CC1200_MDMCFG2_CFM_DATA_EN)),
473 * APRS deviation is 3kHz
475 * fdev = fosc >> 22 * (256 + dev_m) << dev_e dev_e != 0
476 * fdev = fosc >> 21 * dev_m dev_e == 0
478 * 40e6 / (2 ** 21) * 157 = 2995Hz
482 #define APRS_DEV_M 157
485 * For our APRS beacon, set the symbol rate to 9.6kBaud (8x oversampling for 1200 baud data rate)
487 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
488 * Rdata = -------------------------------------- * fosc
491 * DATARATE_M = 1013008
494 * Rdata = 9599.998593330383301
497 #define APRS_SYMBOL_RATE_E 6
498 #define APRS_SYMBOL_RATE_M 1013008
499 #define APRS_BUFFER_SIZE 64
501 static const uint16_t aprs_setup[] = {
502 CC1200_DEVIATION_M, APRS_DEV_M,
503 CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) |
504 (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) |
505 (APRS_DEV_E << CC1200_MODCFG_DEV_E_DEV_E)),
506 CC1200_SYMBOL_RATE2, ((APRS_SYMBOL_RATE_E << CC1200_SYMBOL_RATE2_DATARATE_E) |
507 (((APRS_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)),
508 CC1200_SYMBOL_RATE1, ((APRS_SYMBOL_RATE_M >> 8) & 0xff),
509 CC1200_SYMBOL_RATE0, ((APRS_SYMBOL_RATE_M >> 0) & 0xff),
510 CC1200_PKT_CFG2, /* Packet Configuration Reg. 2 */
511 ((0 << CC1200_PKT_CFG2_FG_MODE_EN) |
512 (CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) |
513 (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)),
514 CC1200_PKT_CFG1, /* Packet Configuration Reg. 1 */
515 ((0 << CC1200_PKT_CFG1_FEC_EN) |
516 (0 << CC1200_PKT_CFG1_WHITE_DATA) |
517 (0 << CC1200_PKT_CFG1_PN9_SWAP_EN) |
518 (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) |
519 (CC1200_PKT_CFG1_CRC_CFG_DISABLED << CC1200_PKT_CFG1_CRC_CFG) |
520 (0 << CC1200_PKT_CFG1_APPEND_STATUS)),
521 CC1200_PKT_CFG0, /* Packet Configuration Reg. 0 */
522 ((CC1200_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1200_PKT_CFG0_LENGTH_CONFIG) |
523 (0 << CC1200_PKT_CFG0_PKG_BIT_LEN) |
524 (0 << CC1200_PKT_CFG0_UART_MODE_EN) |
525 (0 << CC1200_PKT_CFG0_UART_SWAP_EN)),
526 CC1200_PREAMBLE_CFG1,
527 ((CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1200_PREAMBLE_CFG1_NUM_PREAMBLE) |
528 (CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1200_PREAMBLE_CFG1_PREAMBLE_WORD)),
529 CC1200_MDMCFG2, /* General Modem Parameter Configuration Reg. 2 */
530 ((CC1200_MDMCFG2_ASK_SHAPE_8 << CC1200_MDMCFG2_ASK_SHAPE) |
531 (CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) |
532 (CC1200_MDMCFG2_UPSAMPLER_P_8 << CC1200_MDMCFG2_UPSAMPLER_P) |
533 (0 << CC1200_MDMCFG2_CFM_DATA_EN)),
535 ((0 << CC1200_FIFO_CFG_CRC_AUTOFLUSH) |
536 (APRS_BUFFER_SIZE << CC1200_FIFO_CFG_FIFO_THR)),
540 * For Test mode, we want an unmodulated carrier. To do that, we
541 * set the deviation to zero and enable a preamble so that the radio
542 * turns on before we send any data
545 static const uint16_t test_setup[] = {
546 CC1200_DEVIATION_M, 0,
547 CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) |
548 (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) |
549 (0 << CC1200_MODCFG_DEV_E_DEV_E)),
550 CC1200_SYMBOL_RATE2, ((APRS_SYMBOL_RATE_E << CC1200_SYMBOL_RATE2_DATARATE_E) |
551 (((APRS_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)),
552 CC1200_SYMBOL_RATE1, ((APRS_SYMBOL_RATE_M >> 8) & 0xff),
553 CC1200_SYMBOL_RATE0, ((APRS_SYMBOL_RATE_M >> 0) & 0xff),
554 CC1200_PKT_CFG2, ((CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) |
555 (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)),
556 CC1200_PKT_CFG1, ((0 << CC1200_PKT_CFG1_WHITE_DATA) |
557 (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) |
558 (CC1200_PKT_CFG1_CRC_CFG_DISABLED << CC1200_PKT_CFG1_CRC_CFG) |
559 (0 << CC1200_PKT_CFG1_APPEND_STATUS)),
560 CC1200_PREAMBLE_CFG1, ((CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES << CC1200_PREAMBLE_CFG1_NUM_PREAMBLE) |
561 (CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1200_PREAMBLE_CFG1_PREAMBLE_WORD)),
564 #define AO_PKT_CFG0_INFINITE ((CC1200_PKT_CFG0_LENGTH_CONFIG_INFINITE << CC1200_PKT_CFG0_LENGTH_CONFIG) | \
565 (0 << CC1200_PKT_CFG0_PKG_BIT_LEN) | \
566 (0 << CC1200_PKT_CFG0_UART_MODE_EN) | \
567 (0 << CC1200_PKT_CFG0_UART_SWAP_EN))
569 #define AO_PKT_CFG0_FIXED ((CC1200_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1200_PKT_CFG0_LENGTH_CONFIG) | \
570 (0 << CC1200_PKT_CFG0_PKG_BIT_LEN) | \
571 (0 << CC1200_PKT_CFG0_UART_MODE_EN) | \
572 (0 << CC1200_PKT_CFG0_UART_SWAP_EN))
574 static uint16_t ao_radio_mode;
576 #define AO_RADIO_MODE_BITS_PACKET 1
577 #define AO_RADIO_MODE_BITS_TX_BUF 4
578 #define AO_RADIO_MODE_BITS_TX_FINISH 8
579 #define AO_RADIO_MODE_BITS_RX 16
580 #define AO_RADIO_MODE_BITS_RDF 32
581 #define AO_RADIO_MODE_BITS_APRS 64
582 #define AO_RADIO_MODE_BITS_TEST 128
583 #define AO_RADIO_MODE_BITS_INFINITE 256
584 #define AO_RADIO_MODE_BITS_FIXED 512
586 #define AO_RADIO_MODE_NONE 0
587 #define AO_RADIO_MODE_PACKET_TX (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_FINISH)
588 #define AO_RADIO_MODE_PACKET_RX (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_RX)
589 #define AO_RADIO_MODE_RDF (AO_RADIO_MODE_BITS_RDF | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_FINISH)
590 #define AO_RADIO_MODE_APRS_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF)
591 #define AO_RADIO_MODE_APRS_LAST_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_BUF)
592 #define AO_RADIO_MODE_APRS_FINISH (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_FINISH)
593 #define AO_RADIO_MODE_TEST (AO_RADIO_MODE_BITS_TEST | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF)
596 _ao_radio_set_regs(const uint16_t *regs, int nreg)
600 for (i = 0; i < nreg; i++) {
601 ao_radio_reg_write(regs[0], (uint8_t) regs[1]);
606 #define ao_radio_set_regs(setup) _ao_radio_set_regs(setup, (sizeof (setup) / sizeof(setup[0])) >> 1)
609 ao_radio_set_mode(uint16_t new_mode)
613 if (new_mode == ao_radio_mode)
616 changes = (uint16_t) (new_mode & (~ao_radio_mode));
618 if (changes & AO_RADIO_MODE_BITS_PACKET) {
619 ao_radio_set_regs(packet_setup);
621 switch (ao_config.radio_rate) {
623 case AO_RADIO_RATE_38400:
624 ao_radio_set_regs(packet_setup_384);
626 case AO_RADIO_RATE_9600:
627 ao_radio_set_regs(packet_setup_96);
629 ao_radio_reg_write(CC1200_CHAN_BW, PACKET_CHAN_BW_96_CC1201);
631 ao_radio_reg_write(CC1200_CHAN_BW, PACKET_CHAN_BW_96_CC1200);
633 case AO_RADIO_RATE_2400:
634 ao_radio_set_regs(packet_setup_24);
636 ao_radio_reg_write(CC1200_CHAN_BW, PACKET_CHAN_BW_24_CC1201);
638 ao_radio_reg_write(CC1200_CHAN_BW, PACKET_CHAN_BW_24_CC1200);
643 if (changes & AO_RADIO_MODE_BITS_TX_BUF) {
644 ao_radio_reg_write(AO_CC1200_INT_GPIO_IOCFG, CC1200_IOCFG_GPIO_CFG_TXFIFO_THR);
645 ao_exti_set_mode(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN, AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH);
648 if (changes & AO_RADIO_MODE_BITS_TX_FINISH) {
649 ao_radio_reg_write(AO_CC1200_INT_GPIO_IOCFG, CC1200_IOCFG_GPIO_CFG_PKT_SYNC_RXTX);
650 ao_exti_set_mode(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN, AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH);
653 if (changes & AO_RADIO_MODE_BITS_RX) {
654 ao_radio_reg_write(AO_CC1200_INT_GPIO_IOCFG, CC1200_IOCFG_GPIO_CFG_MARC_MCU_WAKEUP);
655 ao_exti_set_mode(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN, AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_HIGH);
658 if (changes & AO_RADIO_MODE_BITS_RDF)
659 ao_radio_set_regs(rdf_setup);
661 if (changes & AO_RADIO_MODE_BITS_APRS)
662 ao_radio_set_regs(aprs_setup);
664 if (changes & AO_RADIO_MODE_BITS_TEST)
665 ao_radio_set_regs(test_setup);
667 if (changes & AO_RADIO_MODE_BITS_INFINITE)
668 ao_radio_reg_write(CC1200_PKT_CFG0, AO_PKT_CFG0_INFINITE);
670 if (changes & AO_RADIO_MODE_BITS_FIXED)
671 ao_radio_reg_write(CC1200_PKT_CFG0, AO_PKT_CFG0_FIXED);
673 ao_radio_mode = new_mode;
676 static const uint16_t radio_setup[] = {
677 #include "ao_cc1200_CC1200.h"
680 static uint8_t ao_radio_configured = 0;
685 uint8_t partnumber = ao_radio_reg_read(CC1200_PARTNUMBER);
687 if (partnumber == CC1200_PARTNUMBER_CC1201)
690 ao_radio_strobe(CC1200_SRES);
692 ao_radio_set_regs(radio_setup);
700 ao_radio_configured = 1;
704 ao_radio_set_len(uint8_t len)
706 static uint8_t last_len;
708 if (len != last_len) {
709 ao_radio_reg_write(CC1200_PKT_LEN, len);
715 ao_radio_get(uint8_t len)
717 static uint32_t last_radio_setting;
718 static uint8_t last_radio_rate;
719 static uint8_t last_radio_10mw;
721 ao_mutex_get(&ao_radio_mutex);
723 if (!ao_radio_configured)
725 if (ao_config.radio_setting != last_radio_setting) {
726 ao_radio_reg_write(CC1200_FREQ2, (uint8_t) (ao_config.radio_setting >> 16));
727 ao_radio_reg_write(CC1200_FREQ1, (uint8_t) (ao_config.radio_setting >> 8));
728 ao_radio_reg_write(CC1200_FREQ0, (uint8_t) ao_config.radio_setting);
729 last_radio_setting = ao_config.radio_setting;
730 ao_radio_strobe(CC1200_SCAL);
732 if (ao_config.radio_rate != last_radio_rate) {
733 ao_radio_mode &= (uint16_t) ~AO_RADIO_MODE_BITS_PACKET;
734 last_radio_rate = ao_config.radio_rate;
736 if(ao_config.radio_10mw != last_radio_10mw) {
737 last_radio_10mw = ao_config.radio_10mw;
739 * 0x37 "should" be 10dBm, but measurements on TBT
740 * v4.0 show that too hot, so use * 0x32 to make sure
743 if (ao_config.radio_10mw)
744 ao_radio_reg_write(CC1200_PA_CFG1, 0x32);
746 ao_radio_reg_write(CC1200_PA_CFG1, 0x3f);
748 ao_radio_set_len(len);
751 #define ao_radio_put() ao_mutex_put(&ao_radio_mutex)
753 static inline uint8_t
756 return (ao_radio_status() >> CC1200_STATUS_STATE) & CC1200_STATUS_STATE_MASK;
761 ao_radio_show_state(char *where)
763 printf("%s: state %d len %d rxbytes %d\n",
764 where, ao_radio_state(),
765 ao_radio_reg_read(CC1200_PKT_LEN),
766 ao_radio_reg_read(CC1200_NUM_RXBYTES));
769 #define ao_radio_show_state(where)
772 /* Wait for the radio to signal an interrupt
775 ao_radio_wait_isr(AO_TICK_TYPE timeout)
777 ao_arch_block_interrupts();
778 while (!ao_radio_wake && !ao_radio_abort)
779 if (ao_sleep_for(&ao_radio_wake, timeout))
781 ao_arch_release_interrupts();
785 ao_rdf_start(uint8_t len)
790 ao_radio_set_mode(AO_RADIO_MODE_RDF);
800 ao_radio_wait_isr(0);
809 ao_rdf_start(AO_RADIO_RDF_LEN);
811 ao_radio_fifo_write_fixed(ao_radio_rdf_value, AO_RADIO_RDF_LEN);
817 ao_radio_continuity(uint8_t c)
822 ao_rdf_start(AO_RADIO_CONT_TOTAL_LEN);
824 status = ao_radio_fifo_write_start();
825 for (i = 0; i < 3; i++) {
826 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN);
828 ao_radio_spi_send_fixed(ao_radio_rdf_value, AO_RADIO_CONT_TONE_LEN);
830 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_TONE_LEN);
832 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN);
833 status = ao_radio_fifo_write_stop(status);
839 ao_radio_rdf_abort(void)
842 ao_wakeup(&ao_radio_wake);
845 static uint8_t radio_on;
848 ao_radio_test_on(void)
852 ao_monitor_disable();
855 ao_packet_slave_stop();
861 ao_radio_set_mode(AO_RADIO_MODE_TEST);
862 ao_radio_strobe(CC1200_STX);
865 for (t = 0; t < 10; t++) {
866 printf ("status: %02x\n", ao_radio_status());
867 ao_delay(AO_MS_TO_TICKS(100));
876 ao_radio_test_off(void)
892 ao_radio_test_cmd(void)
896 if (ao_cmd_lex_c != '\n')
897 mode = (uint8_t) ao_cmd_decimal();
902 printf ("Hit a character to stop..."); flush();
911 ao_radio_send(const void *d, uint8_t size)
914 ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX);
916 ao_radio_fifo_write(d, size);
922 ao_radio_send_aprs(ao_radio_fill_func fill)
924 uint8_t buf[APRS_BUFFER_SIZE];
933 while (!done && !ao_radio_abort) {
934 cnt = (*fill)(buf, sizeof(buf));
941 /* At the last buffer, set the total length */
943 ao_radio_set_len((uint8_t) (total & 0xff));
945 /* Wait for some space in the fifo */
946 while (started && ao_radio_int_pin() != 0 && !ao_radio_abort) {
948 ao_exti_enable(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN);
949 ao_radio_wait_isr(AO_MS_TO_TICKS(1000));
955 ao_radio_set_mode(AO_RADIO_MODE_APRS_FINISH);
957 ao_radio_set_mode(AO_RADIO_MODE_APRS_BUF);
959 ao_radio_fifo_write(buf, (uint8_t) cnt);
961 ao_radio_strobe(CC1200_STX);
965 /* Wait for the transmitter to go idle */
966 while (started && ao_radio_int_pin() != 0 && !ao_radio_abort) {
968 ao_exti_enable(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN);
969 ao_radio_wait_isr(AO_MS_TO_TICKS(1000));
978 ao_radio_marc_state(void)
980 return ao_radio_reg_read(CC1200_MARCSTATE);
984 ao_radio_modem_status1(void)
986 return ao_radio_reg_read(CC1200_MODEM_STATUS1);
990 ao_radio_modem_status0(void)
992 return ao_radio_reg_read(CC1200_MODEM_STATUS0);
995 struct ao_radio_state {
998 uint8_t marc_status1;
999 uint8_t marc_status0;
1000 uint8_t modem_status1;
1001 uint8_t modem_status0;
1005 ao_radio_fill_state(char *where, struct ao_radio_state *s)
1007 strcpy(s->where, where);
1008 s->marc_state = ao_radio_marc_state();
1009 s->marc_status1 = ao_radio_reg_read(CC1200_MARC_STATUS1);
1010 s->marc_status0 = ao_radio_reg_read(CC1200_MARC_STATUS0);
1011 s->modem_status1 = ao_radio_modem_status1();
1012 s->modem_status0 = ao_radio_modem_status0();
1016 ao_radio_dump_state(struct ao_radio_state *s)
1018 printf ("%s: marc %2x marc1 %2x marc0 %2x modem1 %2x modem0 %2x\n",
1019 s->where, s->marc_state, s->marc_status1, s->marc_status0, s->modem_status1, s->modem_status0);
1024 ao_radio_recv(void *d, uint8_t size, AO_TICK_TYPE timeout)
1026 uint8_t success = 0;
1029 ao_radio_get(size - 2);
1030 ao_radio_set_mode(AO_RADIO_MODE_PACKET_RX);
1032 ao_radio_start_rx();
1034 while (!ao_radio_abort) {
1035 ao_radio_wait_isr(timeout);
1036 if (ao_radio_wake) {
1037 uint8_t marc_status1 = ao_radio_reg_read(CC1200_MARC_STATUS1);
1039 /* Check the receiver status to see what happened
1041 switch (marc_status1) {
1042 case CC1200_MARC_STATUS1_RX_FINISHED:
1043 case CC1200_MARC_STATUS1_ADDRESS:
1044 case CC1200_MARC_STATUS1_CRC:
1045 /* Normal return, go fetch the bytes from the FIFO
1046 * and give them back to the caller
1050 case CC1200_MARC_STATUS1_RX_TIMEOUT:
1051 case CC1200_MARC_STATUS1_RX_TERMINATION:
1052 case CC1200_MARC_STATUS1_EWOR_SYNC_LOST:
1053 case CC1200_MARC_STATUS1_MAXIMUM_LENGTH:
1054 case CC1200_MARC_STATUS1_RX_FIFO_OVERFLOW:
1055 case CC1200_MARC_STATUS1_RX_FIFO_UNDERFLOW:
1056 /* Something weird happened; reset the radio and
1062 /* some other status; go wait for the radio to do something useful
1068 uint8_t modem_status1 = ao_radio_reg_read(CC1200_MODEM_STATUS1);
1070 /* Check to see if the packet header has been seen, in which case we'll
1071 * want to keep waiting for the rest of the packet to appear
1073 if (modem_status1 & (1 << CC1200_MODEM_STATUS1_SYNC_FOUND))
1077 /* Set a timeout based on the packet length so that we make sure to
1078 * wait long enough to receive the whole thing.
1080 * timeout = bits * FEC expansion / rate
1082 switch (ao_config.radio_rate) {
1084 case AO_RADIO_RATE_38400:
1085 timeout = AO_MS_TO_TICKS((AO_TICK_TYPE) size * (8 * 2 * 10) / 384) + 1;
1087 case AO_RADIO_RATE_9600:
1088 timeout = AO_MS_TO_TICKS((AO_TICK_TYPE) size * (8 * 2 * 10) / 96) + 1;
1090 case AO_RADIO_RATE_2400:
1091 timeout = AO_MS_TO_TICKS((AO_TICK_TYPE) size * (8 * 2 * 10) / 24) + 1;
1102 status = ao_radio_fifo_read(d, size);
1104 rssi = ((int8_t *) d)[size - 2];
1105 ao_radio_rssi = rssi;
1107 /* Bound it to the representable range */
1111 /* Write it back to the packet */
1112 ((uint8_t *) d)[size-2] = AO_RADIO_FROM_RSSI(rssi);
1124 static char *cc1200_state_name[] = {
1125 [CC1200_STATUS_STATE_IDLE] = "IDLE",
1126 [CC1200_STATUS_STATE_RX] = "RX",
1127 [CC1200_STATUS_STATE_TX] = "TX",
1128 [CC1200_STATUS_STATE_FSTXON] = "FSTXON",
1129 [CC1200_STATUS_STATE_CALIBRATE] = "CALIBRATE",
1130 [CC1200_STATUS_STATE_SETTLING] = "SETTLING",
1131 [CC1200_STATUS_STATE_RX_FIFO_ERROR] = "RX_FIFO_ERROR",
1132 [CC1200_STATUS_STATE_TX_FIFO_ERROR] = "TX_FIFO_ERROR",
1135 struct ao_cc1200_reg {
1140 static const struct ao_cc1200_reg ao_cc1200_reg[] = {
1141 { .addr = CC1200_IOCFG3, .name = "IOCFG3" },
1142 { .addr = CC1200_IOCFG2, .name = "IOCFG2" },
1143 { .addr = CC1200_IOCFG1, .name = "IOCFG1" },
1144 { .addr = CC1200_IOCFG0, .name = "IOCFG0" },
1145 { .addr = CC1200_SYNC3, .name = "SYNC3" },
1146 { .addr = CC1200_SYNC2, .name = "SYNC2" },
1147 { .addr = CC1200_SYNC1, .name = "SYNC1" },
1148 { .addr = CC1200_SYNC0, .name = "SYNC0" },
1149 { .addr = CC1200_SYNC_CFG1, .name = "SYNC_CFG1" },
1150 { .addr = CC1200_SYNC_CFG0, .name = "SYNC_CFG0" },
1151 { .addr = CC1200_DEVIATION_M, .name = "DEVIATION_M" },
1152 { .addr = CC1200_MODCFG_DEV_E, .name = "MODCFG_DEV_E" },
1153 { .addr = CC1200_DCFILT_CFG, .name = "DCFILT_CFG" },
1154 { .addr = CC1200_PREAMBLE_CFG1, .name = "PREAMBLE_CFG1" },
1155 { .addr = CC1200_PREAMBLE_CFG0, .name = "PREAMBLE_CFG0" },
1156 { .addr = CC1200_IQIC, .name = "IQIC" },
1157 { .addr = CC1200_CHAN_BW, .name = "CHAN_BW" },
1158 { .addr = CC1200_MDMCFG2, .name = "MDMCFG2" },
1159 { .addr = CC1200_MDMCFG1, .name = "MDMCFG1" },
1160 { .addr = CC1200_MDMCFG0, .name = "MDMCFG0" },
1161 { .addr = CC1200_SYMBOL_RATE2, .name = "SYMBOL_RATE2" },
1162 { .addr = CC1200_SYMBOL_RATE1, .name = "SYMBOL_RATE1" },
1163 { .addr = CC1200_SYMBOL_RATE0, .name = "SYMBOL_RATE0" },
1164 { .addr = CC1200_AGC_REF, .name = "AGC_REF" },
1165 { .addr = CC1200_AGC_CS_THR, .name = "AGC_CS_THR" },
1166 { .addr = CC1200_AGC_GAIN_ADJUST, .name = "AGC_GAIN_ADJUST" },
1167 { .addr = CC1200_AGC_CFG3, .name = "AGC_CFG3" },
1168 { .addr = CC1200_AGC_CFG2, .name = "AGC_CFG2" },
1169 { .addr = CC1200_AGC_CFG1, .name = "AGC_CFG1" },
1170 { .addr = CC1200_AGC_CFG0, .name = "AGC_CFG0" },
1171 { .addr = CC1200_FIFO_CFG, .name = "FIFO_CFG" },
1172 { .addr = CC1200_DEV_ADDR, .name = "DEV_ADDR" },
1173 { .addr = CC1200_SETTLING_CFG, .name = "SETTLING_CFG" },
1174 { .addr = CC1200_FS_CFG, .name = "FS_CFG" },
1175 { .addr = CC1200_WOR_CFG1, .name = "WOR_CFG1" },
1176 { .addr = CC1200_WOR_CFG0, .name = "WOR_CFG0" },
1177 { .addr = CC1200_WOR_EVENT0_MSB, .name = "WOR_EVENT0_MSB" },
1178 { .addr = CC1200_WOR_EVENT0_LSB, .name = "WOR_EVENT0_LSB" },
1179 { .addr = CC1200_RXDCM_TIME, .name = "RXDCM_TIME" },
1180 { .addr = CC1200_PKT_CFG2, .name = "PKT_CFG2" },
1181 { .addr = CC1200_PKT_CFG1, .name = "PKT_CFG1" },
1182 { .addr = CC1200_PKT_CFG0, .name = "PKT_CFG0" },
1183 { .addr = CC1200_RFEND_CFG1, .name = "RFEND_CFG1" },
1184 { .addr = CC1200_RFEND_CFG0, .name = "RFEND_CFG0" },
1185 { .addr = CC1200_PA_CFG1, .name = "PA_CFG1" },
1186 { .addr = CC1200_PA_CFG0, .name = "PA_CFG0" },
1187 { .addr = CC1200_PKT_LEN, .name = "PKT_LEN" },
1188 { .addr = CC1200_IF_MIX_CFG, .name = "IF_MIX_CFG" },
1189 { .addr = CC1200_FREQOFF_CFG, .name = "FREQOFF_CFG" },
1190 { .addr = CC1200_TOC_CFG, .name = "TOC_CFG" },
1191 { .addr = CC1200_MARC_SPARE, .name = "MARC_SPARE" },
1192 { .addr = CC1200_ECG_CFG, .name = "ECG_CFG" },
1193 { .addr = CC1200_EXT_CTRL, .name = "EXT_CTRL" },
1194 { .addr = CC1200_RCCAL_FINE, .name = "RCCAL_FINE" },
1195 { .addr = CC1200_RCCAL_COARSE, .name = "RCCAL_COARSE" },
1196 { .addr = CC1200_RCCAL_OFFSET, .name = "RCCAL_OFFSET" },
1197 { .addr = CC1200_FREQOFF1, .name = "FREQOFF1" },
1198 { .addr = CC1200_FREQOFF0, .name = "FREQOFF0" },
1199 { .addr = CC1200_FREQ2, .name = "FREQ2" },
1200 { .addr = CC1200_FREQ1, .name = "FREQ1" },
1201 { .addr = CC1200_FREQ0, .name = "FREQ0" },
1202 { .addr = CC1200_IF_ADC2, .name = "IF_ADC2" },
1203 { .addr = CC1200_IF_ADC1, .name = "IF_ADC1" },
1204 { .addr = CC1200_IF_ADC0, .name = "IF_ADC0" },
1205 { .addr = CC1200_FS_DIG1, .name = "FS_DIG1" },
1206 { .addr = CC1200_FS_DIG0, .name = "FS_DIG0" },
1207 { .addr = CC1200_FS_CAL3, .name = "FS_CAL3" },
1208 { .addr = CC1200_FS_CAL2, .name = "FS_CAL2" },
1209 { .addr = CC1200_FS_CAL1, .name = "FS_CAL1" },
1210 { .addr = CC1200_FS_CAL0, .name = "FS_CAL0" },
1211 { .addr = CC1200_FS_CHP, .name = "FS_CHP" },
1212 { .addr = CC1200_FS_DIVTWO, .name = "FS_DIVTWO" },
1213 { .addr = CC1200_FS_DSM1, .name = "FS_DSM1" },
1214 { .addr = CC1200_FS_DSM0, .name = "FS_DSM0" },
1215 { .addr = CC1200_FS_DVC1, .name = "FS_DVC1" },
1216 { .addr = CC1200_FS_DVC0, .name = "FS_DVC0" },
1217 { .addr = CC1200_FS_LBI, .name = "FS_LBI" },
1218 { .addr = CC1200_FS_PFD, .name = "FS_PFD" },
1219 { .addr = CC1200_FS_PRE, .name = "FS_PRE" },
1220 { .addr = CC1200_FS_REG_DIV_CML, .name = "FS_REG_DIV_CML" },
1221 { .addr = CC1200_FS_SPARE, .name = "FS_SPARE" },
1222 { .addr = CC1200_FS_VCO4, .name = "FS_VCO4" },
1223 { .addr = CC1200_FS_VCO3, .name = "FS_VCO3" },
1224 { .addr = CC1200_FS_VCO2, .name = "FS_VCO2" },
1225 { .addr = CC1200_FS_VCO1, .name = "FS_VCO1" },
1226 { .addr = CC1200_FS_VCO0, .name = "FS_VCO0" },
1227 { .addr = CC1200_GBIAS6, .name = "GBIAS6" },
1228 { .addr = CC1200_GBIAS5, .name = "GBIAS5" },
1229 { .addr = CC1200_GBIAS4, .name = "GBIAS4" },
1230 { .addr = CC1200_GBIAS3, .name = "GBIAS3" },
1231 { .addr = CC1200_GBIAS2, .name = "GBIAS2" },
1232 { .addr = CC1200_GBIAS1, .name = "GBIAS1" },
1233 { .addr = CC1200_GBIAS0, .name = "GBIAS0" },
1234 { .addr = CC1200_IFAMP, .name = "IFAMP" },
1235 { .addr = CC1200_LNA, .name = "LNA" },
1236 { .addr = CC1200_RXMIX, .name = "RXMIX" },
1237 { .addr = CC1200_XOSC5, .name = "XOSC5" },
1238 { .addr = CC1200_XOSC4, .name = "XOSC4" },
1239 { .addr = CC1200_XOSC3, .name = "XOSC3" },
1240 { .addr = CC1200_XOSC2, .name = "XOSC2" },
1241 { .addr = CC1200_XOSC1, .name = "XOSC1" },
1242 { .addr = CC1200_XOSC0, .name = "XOSC0" },
1243 { .addr = CC1200_ANALOG_SPARE, .name = "ANALOG_SPARE" },
1244 { .addr = CC1200_PA_CFG3, .name = "PA_CFG3" },
1245 { .addr = CC1200_WOR_TIME1, .name = "WOR_TIME1" },
1246 { .addr = CC1200_WOR_TIME0, .name = "WOR_TIME0" },
1247 { .addr = CC1200_WOR_CAPTURE1, .name = "WOR_CAPTURE1" },
1248 { .addr = CC1200_WOR_CAPTURE0, .name = "WOR_CAPTURE0" },
1249 { .addr = CC1200_BIST, .name = "BIST" },
1250 { .addr = CC1200_DCFILTOFFSET_I1, .name = "DCFILTOFFSET_I1" },
1251 { .addr = CC1200_DCFILTOFFSET_I0, .name = "DCFILTOFFSET_I0" },
1252 { .addr = CC1200_DCFILTOFFSET_Q1, .name = "DCFILTOFFSET_Q1" },
1253 { .addr = CC1200_DCFILTOFFSET_Q0, .name = "DCFILTOFFSET_Q0" },
1254 { .addr = CC1200_IQIE_I1, .name = "IQIE_I1" },
1255 { .addr = CC1200_IQIE_I0, .name = "IQIE_I0" },
1256 { .addr = CC1200_IQIE_Q1, .name = "IQIE_Q1" },
1257 { .addr = CC1200_IQIE_Q0, .name = "IQIE_Q0" },
1258 { .addr = CC1200_RSSI1, .name = "RSSI1" },
1259 { .addr = CC1200_RSSI0, .name = "RSSI0" },
1260 { .addr = CC1200_MARCSTATE, .name = "MARCSTATE" },
1261 { .addr = CC1200_LQI_VAL, .name = "LQI_VAL" },
1262 { .addr = CC1200_PQT_SYNC_ERR, .name = "PQT_SYNC_ERR" },
1263 { .addr = CC1200_DEM_STATUS, .name = "DEM_STATUS" },
1264 { .addr = CC1200_FREQOFF_EST1, .name = "FREQOFF_EST1" },
1265 { .addr = CC1200_FREQOFF_EST0, .name = "FREQOFF_EST0" },
1266 { .addr = CC1200_AGC_GAIN3, .name = "AGC_GAIN3" },
1267 { .addr = CC1200_AGC_GAIN2, .name = "AGC_GAIN2" },
1268 { .addr = CC1200_AGC_GAIN1, .name = "AGC_GAIN1" },
1269 { .addr = CC1200_AGC_GAIN0, .name = "AGC_GAIN0" },
1270 { .addr = CC1200_SOFT_RX_DATA_OUT, .name = "SOFT_RX_DATA_OUT" },
1271 { .addr = CC1200_SOFT_TX_DATA_IN, .name = "SOFT_TX_DATA_IN" },
1272 { .addr = CC1200_ASK_SOFT_RX_DATA, .name = "ASK_SOFT_RX_DATA" },
1273 { .addr = CC1200_RNDGEN, .name = "RNDGEN" },
1274 { .addr = CC1200_MAGN2, .name = "MAGN2" },
1275 { .addr = CC1200_MAGN1, .name = "MAGN1" },
1276 { .addr = CC1200_MAGN0, .name = "MAGN0" },
1277 { .addr = CC1200_ANG1, .name = "ANG1" },
1278 { .addr = CC1200_ANG0, .name = "ANG0" },
1279 { .addr = CC1200_CHFILT_I2, .name = "CHFILT_I2" },
1280 { .addr = CC1200_CHFILT_I1, .name = "CHFILT_I1" },
1281 { .addr = CC1200_CHFILT_I0, .name = "CHFILT_I0" },
1282 { .addr = CC1200_CHFILT_Q2, .name = "CHFILT_Q2" },
1283 { .addr = CC1200_CHFILT_Q1, .name = "CHFILT_Q1" },
1284 { .addr = CC1200_CHFILT_Q0, .name = "CHFILT_Q0" },
1285 { .addr = CC1200_GPIO_STATUS, .name = "GPIO_STATUS" },
1286 { .addr = CC1200_FSCAL_CTRL, .name = "FSCAL_CTRL" },
1287 { .addr = CC1200_PHASE_ADJUST, .name = "PHASE_ADJUST" },
1288 { .addr = CC1200_PARTNUMBER, .name = "PARTNUMBER" },
1289 { .addr = CC1200_PARTVERSION, .name = "PARTVERSION" },
1290 { .addr = CC1200_SERIAL_STATUS, .name = "SERIAL_STATUS" },
1291 { .addr = CC1200_MODEM_STATUS1, .name = "MODEM_STATUS1" },
1292 { .addr = CC1200_MODEM_STATUS0, .name = "MODEM_STATUS0" },
1293 { .addr = CC1200_MARC_STATUS1, .name = "MARC_STATUS1" },
1294 { .addr = CC1200_MARC_STATUS0, .name = "MARC_STATUS0" },
1295 { .addr = CC1200_PA_IFAMP_TEST, .name = "PA_IFAMP_TEST" },
1296 { .addr = CC1200_FSRF_TEST, .name = "FSRF_TEST" },
1297 { .addr = CC1200_PRE_TEST, .name = "PRE_TEST" },
1298 { .addr = CC1200_PRE_OVR, .name = "PRE_OVR" },
1299 { .addr = CC1200_ADC_TEST, .name = "ADC_TEST" },
1300 { .addr = CC1200_DVC_TEST, .name = "DVC_TEST" },
1301 { .addr = CC1200_ATEST, .name = "ATEST" },
1302 { .addr = CC1200_ATEST_LVDS, .name = "ATEST_LVDS" },
1303 { .addr = CC1200_ATEST_MODE, .name = "ATEST_MODE" },
1304 { .addr = CC1200_XOSC_TEST1, .name = "XOSC_TEST1" },
1305 { .addr = CC1200_XOSC_TEST0, .name = "XOSC_TEST0" },
1306 { .addr = CC1200_RXFIRST, .name = "RXFIRST" },
1307 { .addr = CC1200_TXFIRST, .name = "TXFIRST" },
1308 { .addr = CC1200_RXLAST, .name = "RXLAST" },
1309 { .addr = CC1200_TXLAST, .name = "TXLAST" },
1310 { .addr = CC1200_NUM_TXBYTES, .name = "NUM_TXBYTES" },
1311 { .addr = CC1200_NUM_RXBYTES, .name = "NUM_RXBYTES" },
1312 { .addr = CC1200_FIFO_NUM_TXBYTES, .name = "FIFO_NUM_TXBYTES" },
1313 { .addr = CC1200_FIFO_NUM_RXBYTES, .name = "FIFO_NUM_RXBYTES" },
1316 #define AO_NUM_CC1200_REG (sizeof ao_cc1200_reg / sizeof ao_cc1200_reg[0])
1319 ao_radio_get_marc_status(void)
1321 return ao_radio_reg_read(CC1200_MARC_STATUS1);
1324 static void ao_radio_show(void) {
1328 ao_mutex_get(&ao_radio_mutex);
1329 status = ao_radio_status();
1330 printf ("Status: %02x\n", status);
1331 printf ("CHIP_RDY: %d\n", (status >> CC1200_STATUS_CHIP_RDY) & 1);
1332 printf ("STATE: %s\n", cc1200_state_name[(status >> CC1200_STATUS_STATE) & CC1200_STATUS_STATE_MASK]);
1333 printf ("MARC: %02x\n", ao_radio_get_marc_status());
1335 for (i = 0; i < AO_NUM_CC1200_REG; i++)
1336 printf ("\t%02x %-20.20s\n", ao_radio_reg_read(ao_cc1200_reg[i].addr), ao_cc1200_reg[i].name);
1341 static void ao_radio_beep(void) {
1345 static void ao_radio_packet(void) {
1346 static const uint8_t packet[] = {
1348 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1349 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1350 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1351 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1357 ao_radio_send(packet, sizeof (packet));
1361 ao_radio_test_recv(void)
1363 static uint8_t bytes[34];
1366 if (ao_radio_recv(bytes, 34, 0)) {
1367 if (bytes[33] & 0x80)
1371 printf (" RSSI %d", AO_RSSI_FROM_RADIO(bytes[32]));
1372 for (b = 0; b < 32; b++)
1373 printf (" %02x", bytes[b]);
1375 printf (" RSSI %02x LQI %02x", bytes[32], bytes[33]);
1381 #include <ao_aprs.h>
1386 #if PACKET_HAS_SLAVE
1387 ao_packet_slave_stop();
1394 #if CC1200_LOW_LEVEL_DEBUG
1396 ao_radio_strobe_test(void)
1401 addr = ao_cmd_hex();
1402 if (ao_cmd_status != ao_cmd_success)
1404 r = ao_radio_strobe(addr);
1405 printf ("Strobe %02x -> %02x (rdy %d state %d)\n",
1413 ao_radio_write_test(void)
1418 addr = ao_cmd_hex();
1419 if (ao_cmd_status != ao_cmd_success)
1421 data = ao_cmd_hex();
1422 if (ao_cmd_status != ao_cmd_success)
1424 printf ("Write %04x = %02x\n", addr, data);
1425 ao_radio_reg_write(addr, data);
1429 ao_radio_read_test(void)
1434 addr = ao_cmd_hex();
1435 if (ao_cmd_status != ao_cmd_success)
1437 data = ao_radio_reg_read(addr);
1438 printf ("Read %04x = %02x\n", addr, data);
1442 static const struct ao_cmds ao_radio_cmds[] = {
1443 { ao_radio_test_cmd, "C <1 start, 0 stop, none both>\0Radio carrier test" },
1446 { ao_radio_aprs, "G\0Send APRS packet" },
1448 { ao_radio_show, "R\0Show CC1200 status" },
1449 { ao_radio_beep, "b\0Emit an RDF beacon" },
1450 { ao_radio_packet, "p\0Send a test packet" },
1451 { ao_radio_test_recv, "q\0Recv a test packet" },
1453 #if CC1200_LOW_LEVEL_DEBUG
1454 { ao_radio_strobe_test, "A <value>\0Strobe radio" },
1455 { ao_radio_write_test, "W <addr> <value>\0Write radio reg" },
1456 { ao_radio_read_test, "B <addr>\0Read radio reg" },
1464 ao_radio_configured = 0;
1465 ao_spi_init_cs (AO_CC1200_SPI_CS_PORT, (1 << AO_CC1200_SPI_CS_PIN));
1468 AO_CC1200_SPI_CS_PORT->bsrr = ((uint32_t) (1 << AO_CC1200_SPI_CS_PIN));
1469 for (i = 0; i < 10000; i++) {
1470 if ((SPI_2_PORT->idr & (1 << SPI_2_MISO_PIN)) == 0)
1473 AO_CC1200_SPI_CS_PORT->bsrr = (1 << AO_CC1200_SPI_CS_PIN);
1475 ao_panic(AO_PANIC_SELF_TEST_CC1200);
1478 /* Enable the EXTI interrupt for the appropriate pin */
1479 ao_enable_port(AO_CC1200_INT_PORT);
1480 ao_exti_setup(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN,
1481 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH,
1484 ao_cmd_register(&ao_radio_cmds[0]);