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_duplex(data, data, d + 1);
90 printf (" %02x\n", data[d]);
96 ao_radio_reg_write(uint16_t addr, uint8_t value)
102 printf("\t\tao_radio_reg_write (%04x): %02x\n", addr, value);
104 if (CC1200_IS_EXTENDED(addr)) {
105 data[0] = ((0 << CC1200_READ) |
106 (0 << CC1200_BURST) |
108 data[1] = (uint8_t) addr;
111 data[0] = ((0 << CC1200_READ) |
112 (0 << CC1200_BURST) |
118 ao_radio_spi_send(data, d+1);
121 (void) ao_radio_reg_read(addr);
126 ao_radio_strobe(uint8_t addr)
131 printf("\t\tao_radio_strobe (%02x): ", addr); flush();
134 ao_radio_duplex(&addr, &in, 1);
137 printf("%02x\n", in); flush();
143 ao_radio_fifo_read(uint8_t *data, uint8_t len)
145 uint8_t addr = ((1 << CC1200_READ) |
146 (1 << CC1200_BURST) |
151 ao_radio_duplex(&addr, &status, 1);
152 ao_radio_spi_recv(data, len);
158 ao_radio_fifo_write_start(void)
160 uint8_t addr = ((0 << CC1200_READ) |
161 (1 << CC1200_BURST) |
166 ao_radio_duplex(&addr, &status, 1);
170 static inline uint8_t ao_radio_fifo_write_stop(uint8_t status) {
176 ao_radio_fifo_write(const uint8_t *data, uint8_t len)
178 uint8_t status = ao_radio_fifo_write_start();
179 ao_radio_spi_send(data, len);
180 return ao_radio_fifo_write_stop(status);
184 ao_radio_fifo_write_fixed(uint8_t data, uint8_t len)
186 uint8_t status = ao_radio_fifo_write_start();
187 ao_radio_spi_send_fixed(data, len);
188 return ao_radio_fifo_write_stop(status);
192 ao_radio_int_pin(void)
194 return ao_gpio_get(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN);
198 ao_radio_status(void)
200 return ao_radio_strobe (CC1200_SNOP);
204 ao_radio_recv_abort(void)
207 ao_wakeup(&ao_radio_wake);
210 #define ao_radio_rdf_value 0x55
216 ao_wakeup(&ao_radio_wake);
220 ao_radio_start_tx(void)
222 ao_radio_strobe(CC1200_STX);
226 ao_radio_start_rx(void)
228 ao_radio_strobe(CC1200_SRX);
235 uint8_t state = (ao_radio_strobe(CC1200_SIDLE) >> CC1200_STATUS_STATE) & CC1200_STATUS_STATE_MASK;
236 if (state == CC1200_STATUS_STATE_IDLE)
238 if (state == CC1200_STATUS_STATE_TX_FIFO_ERROR)
239 ao_radio_strobe(CC1200_SFTX);
240 if (state == CC1200_STATUS_STATE_RX_FIFO_ERROR)
241 ao_radio_strobe(CC1200_SFRX);
243 /* Flush any pending data in the fifos */
244 ao_radio_strobe(CC1200_SFTX);
245 ao_radio_strobe(CC1200_SFRX);
246 /* Make sure the RF calibration is current */
247 ao_radio_strobe(CC1200_SCAL);
253 * fdev = fosc >> 22 * (256 + dev_m) << dev_e
255 * Deviation for 38400 baud should be 20.5kHz:
257 * 40e6 / (2 ** 22) * (256 + 13) * (2 ** 3) = 20523Hz
259 * Deviation for 9600 baud should be 5.125kHz:
261 * 40e6 / (2 ** 22) * (256 + 13) * (2 ** 1) = 5131Hz
263 * Deviation for 2400 baud should be 1.28125kHz, but cc1111 and
264 * cc115l can't do that, so we'll use 1.5kHz instead:
266 * 40e6 / (2 ** 21) * (79) = 1506Hz
269 #define PACKET_DEV_M_384 13
270 #define PACKET_DEV_E_384 3
272 #define PACKET_DEV_M_96 13
273 #define PACKET_DEV_E_96 1
275 #define PACKET_DEV_M_24 79
276 #define PACKET_DEV_E_24 0
279 * For our packet data
281 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
282 * Rdata = -------------------------------------- * fosc
285 * Given the bit period of the baseband, T, the bandwidth of the
286 * baseband signal is B = 1/(2T). The overall bandwidth of the
287 * modulated signal is then Channel bandwidth = 2Δf + 2B.
289 * 38400 -- 2 * 20500 + 38400 = 79.4 kHz
290 * 9600 -- 2 * 5.125 + 9600 = 19.9 kHz
291 * 2400 -- 2 * 1.5 + 2400 = 5.4 khz
293 * Symbol rate 38400 Baud:
295 * DATARATE_M = 1013008
299 * Symbol rate 9600 Baud:
301 * DATARATE_M = 1013008
303 * CHANBW = 26.042 (round to 19.8)
305 * Symbol rate 2400 Baud:
307 * DATARATE_M = 1013008
309 * CHANBW = 5.0 (round to 9.5)
313 #define PACKET_SYMBOL_RATE_M 1013008
314 #define PACKET_SYMBOL_RATE_E_384 8
315 #define PACKET_SYMBOL_RATE_E_96 6
316 #define PACKET_SYMBOL_RATE_E_24 4
320 #define PACKET_SYMBOL_RATE_M 239914
321 #define PACKET_SYMBOL_RATE_E_384 9
322 #define PACKET_SYMBOL_RATE_E_96 7
323 #define PACKET_SYMBOL_RATE_E_24 5
327 #define PACKET_CHAN_BW_384 ((CC1200_CHAN_BW_ADC_CIC_DECFACT_12 << CC1200_CHAN_BW_ADC_CIC_DECFACT) | \
328 (16 << CC1200_CHAN_BW_BB_CIC_DECFACT))
331 * CC1201 doesn't support our low bandwidth receive setups, so we use
332 * larger values for that part, leaving the bandwidth at over 50kHz
336 #define PACKET_CHAN_BW_96_CC1200 ((CC1200_CHAN_BW_ADC_CIC_DECFACT_48 << CC1200_CHAN_BW_ADC_CIC_DECFACT) | \
337 (16 << CC1200_CHAN_BW_BB_CIC_DECFACT))
339 #define PACKET_CHAN_BW_96_CC1201 ((CC1200_CHAN_BW_ADC_CIC_DECFACT_48 << CC1200_CHAN_BW_ADC_CIC_DECFACT) | \
340 (8 << CC1200_CHAN_BW_BB_CIC_DECFACT))
343 #define PACKET_CHAN_BW_24_CC1200 ((CC1200_CHAN_BW_ADC_CIC_DECFACT_48 << CC1200_CHAN_BW_ADC_CIC_DECFACT) | \
344 (44 << CC1200_CHAN_BW_BB_CIC_DECFACT))
346 #define PACKET_CHAN_BW_24_CC1201 ((CC1200_CHAN_BW_ADC_CIC_DECFACT_48 << CC1200_CHAN_BW_ADC_CIC_DECFACT) | \
347 (8 << CC1200_CHAN_BW_BB_CIC_DECFACT))
349 static const uint16_t packet_setup[] = {
350 CC1200_SYMBOL_RATE1, ((PACKET_SYMBOL_RATE_M >> 8) & 0xff),
351 CC1200_SYMBOL_RATE0, ((PACKET_SYMBOL_RATE_M >> 0) & 0xff),
352 CC1200_PKT_CFG2, /* Packet Configuration Reg. 2 */
353 ((0 << CC1200_PKT_CFG2_FG_MODE_EN) |
354 (CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) |
355 (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)),
356 CC1200_PKT_CFG1, /* Packet Configuration Reg. 1 */
357 ((1 << CC1200_PKT_CFG1_FEC_EN) |
358 (1 << CC1200_PKT_CFG1_WHITE_DATA) |
359 (0 << CC1200_PKT_CFG1_PN9_SWAP_EN) |
360 (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) |
361 (CC1200_PKT_CFG1_CRC_CFG_CRC16_INIT_ONES << CC1200_PKT_CFG1_CRC_CFG) |
362 (1 << CC1200_PKT_CFG1_APPEND_STATUS)),
363 CC1200_PREAMBLE_CFG1, ((CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES << CC1200_PREAMBLE_CFG1_NUM_PREAMBLE) |
364 (CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1200_PREAMBLE_CFG1_PREAMBLE_WORD)),
367 static const uint16_t packet_setup_384[] = {
368 CC1200_DEVIATION_M, PACKET_DEV_M_384,
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_384 << CC1200_MODCFG_DEV_E_DEV_E)),
372 CC1200_SYMBOL_RATE2, ((PACKET_SYMBOL_RATE_E_384 << 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_384,
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_8 << CC1200_MDMCFG2_UPSAMPLER_P) |
379 (0 << CC1200_MDMCFG2_CFM_DATA_EN)),
382 static const uint16_t packet_setup_96[] = {
383 CC1200_DEVIATION_M, PACKET_DEV_M_96,
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_96 << CC1200_MODCFG_DEV_E_DEV_E)),
387 CC1200_SYMBOL_RATE2, ((PACKET_SYMBOL_RATE_E_96 << 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_MDMCFG2, /* General Modem Parameter Configuration Reg. 2 */
390 ((CC1200_MDMCFG2_ASK_SHAPE_8 << CC1200_MDMCFG2_ASK_SHAPE) |
391 (CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) |
392 (CC1200_MDMCFG2_UPSAMPLER_P_32 << CC1200_MDMCFG2_UPSAMPLER_P) |
393 (0 << CC1200_MDMCFG2_CFM_DATA_EN)),
396 static const uint16_t packet_setup_24[] = {
397 CC1200_DEVIATION_M, PACKET_DEV_M_24,
398 CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) |
399 (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) |
400 (PACKET_DEV_E_24 << CC1200_MODCFG_DEV_E_DEV_E)),
401 CC1200_SYMBOL_RATE2, ((PACKET_SYMBOL_RATE_E_24 << CC1200_SYMBOL_RATE2_DATARATE_E) |
402 (((PACKET_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)),
403 CC1200_MDMCFG2, /* General Modem Parameter Configuration Reg. 2 */
404 ((CC1200_MDMCFG2_ASK_SHAPE_8 << CC1200_MDMCFG2_ASK_SHAPE) |
405 (CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) |
406 (CC1200_MDMCFG2_UPSAMPLER_P_64 << CC1200_MDMCFG2_UPSAMPLER_P) |
407 (0 << CC1200_MDMCFG2_CFM_DATA_EN)),
411 * RDF deviation is 3kHz
413 * fdev = fosc >> 22 * (256 + dev_m) << dev_e dev_e != 0
414 * fdev = fosc >> 21 * dev_m dev_e == 0
416 * 40e6 / (2 ** 21) * 157 = 2995Hz
420 #define RDF_DEV_M 157
423 * For our RDF beacon, set the symbol rate to 2kBaud (for a 1kHz tone)
425 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
426 * Rdata = -------------------------------------- * fosc
429 * DATARATE_M = 669411
432 * To make the tone last for 200ms, we need 2000 * .2 = 400 bits or 50 bytes
434 #define RDF_SYMBOL_RATE_E 4
435 #define RDF_SYMBOL_RATE_M 669411
436 #define RDF_PACKET_LEN 50
438 static const uint16_t rdf_setup[] = {
439 CC1200_DEVIATION_M, RDF_DEV_M,
440 CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) |
441 (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) |
442 (RDF_DEV_E << CC1200_MODCFG_DEV_E_DEV_E)),
443 CC1200_SYMBOL_RATE2, ((RDF_SYMBOL_RATE_E << CC1200_SYMBOL_RATE2_DATARATE_E) |
444 (((RDF_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)),
445 CC1200_SYMBOL_RATE1, ((RDF_SYMBOL_RATE_M >> 8) & 0xff),
446 CC1200_SYMBOL_RATE0, ((RDF_SYMBOL_RATE_M >> 0) & 0xff),
447 CC1200_PKT_CFG2, /* Packet Configuration Reg. 2 */
448 ((0 << CC1200_PKT_CFG2_FG_MODE_EN) |
449 (CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) |
450 (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)),
451 CC1200_PKT_CFG1, /* Packet Configuration Reg. 1 */
452 ((0 << CC1200_PKT_CFG1_FEC_EN) |
453 (0 << CC1200_PKT_CFG1_WHITE_DATA) |
454 (0 << CC1200_PKT_CFG1_PN9_SWAP_EN) |
455 (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) |
456 (CC1200_PKT_CFG1_CRC_CFG_DISABLED << CC1200_PKT_CFG1_CRC_CFG) |
457 (0 << CC1200_PKT_CFG1_APPEND_STATUS)),
458 CC1200_PREAMBLE_CFG1,
459 ((CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1200_PREAMBLE_CFG1_NUM_PREAMBLE) |
460 (CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1200_PREAMBLE_CFG1_PREAMBLE_WORD)),
461 CC1200_MDMCFG2, /* General Modem Parameter Configuration Reg. 2 */
462 ((0 << CC1200_MDMCFG2_ASK_SHAPE) |
463 (0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) |
464 (12 << CC1200_MDMCFG2_UPSAMPLER_P) |
465 (0 << CC1200_MDMCFG2_CFM_DATA_EN)),
469 * APRS deviation is 3kHz
471 * fdev = fosc >> 22 * (256 + dev_m) << dev_e dev_e != 0
472 * fdev = fosc >> 21 * dev_m dev_e == 0
474 * 40e6 / (2 ** 21) * 157 = 2995Hz
478 #define APRS_DEV_M 157
481 * For our APRS beacon, set the symbol rate to 9.6kBaud (8x oversampling for 1200 baud data rate)
483 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
484 * Rdata = -------------------------------------- * fosc
487 * DATARATE_M = 1013008
490 * Rdata = 9599.998593330383301
493 #define APRS_SYMBOL_RATE_E 6
494 #define APRS_SYMBOL_RATE_M 1013008
495 #define APRS_BUFFER_SIZE 64
497 static const uint16_t aprs_setup[] = {
498 CC1200_DEVIATION_M, APRS_DEV_M,
499 CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) |
500 (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) |
501 (APRS_DEV_E << CC1200_MODCFG_DEV_E_DEV_E)),
502 CC1200_SYMBOL_RATE2, ((APRS_SYMBOL_RATE_E << CC1200_SYMBOL_RATE2_DATARATE_E) |
503 (((APRS_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)),
504 CC1200_SYMBOL_RATE1, ((APRS_SYMBOL_RATE_M >> 8) & 0xff),
505 CC1200_SYMBOL_RATE0, ((APRS_SYMBOL_RATE_M >> 0) & 0xff),
506 CC1200_PKT_CFG2, /* Packet Configuration Reg. 2 */
507 ((0 << CC1200_PKT_CFG2_FG_MODE_EN) |
508 (CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) |
509 (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)),
510 CC1200_PKT_CFG1, /* Packet Configuration Reg. 1 */
511 ((0 << CC1200_PKT_CFG1_FEC_EN) |
512 (0 << CC1200_PKT_CFG1_WHITE_DATA) |
513 (0 << CC1200_PKT_CFG1_PN9_SWAP_EN) |
514 (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) |
515 (CC1200_PKT_CFG1_CRC_CFG_DISABLED << CC1200_PKT_CFG1_CRC_CFG) |
516 (0 << CC1200_PKT_CFG1_APPEND_STATUS)),
517 CC1200_PKT_CFG0, /* Packet Configuration Reg. 0 */
518 ((CC1200_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1200_PKT_CFG0_LENGTH_CONFIG) |
519 (0 << CC1200_PKT_CFG0_PKG_BIT_LEN) |
520 (0 << CC1200_PKT_CFG0_UART_MODE_EN) |
521 (0 << CC1200_PKT_CFG0_UART_SWAP_EN)),
522 CC1200_PREAMBLE_CFG1,
523 ((CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1200_PREAMBLE_CFG1_NUM_PREAMBLE) |
524 (CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1200_PREAMBLE_CFG1_PREAMBLE_WORD)),
525 CC1200_MDMCFG2, /* General Modem Parameter Configuration Reg. 2 */
526 ((CC1200_MDMCFG2_ASK_SHAPE_8 << CC1200_MDMCFG2_ASK_SHAPE) |
527 (CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) |
528 (CC1200_MDMCFG2_UPSAMPLER_P_8 << CC1200_MDMCFG2_UPSAMPLER_P) |
529 (0 << CC1200_MDMCFG2_CFM_DATA_EN)),
531 ((0 << CC1200_FIFO_CFG_CRC_AUTOFLUSH) |
532 (APRS_BUFFER_SIZE << CC1200_FIFO_CFG_FIFO_THR)),
536 * For Test mode, we want an unmodulated carrier. To do that, we
537 * set the deviation to zero and enable a preamble so that the radio
538 * turns on before we send any data
541 static const uint16_t test_setup[] = {
542 CC1200_DEVIATION_M, 0,
543 CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) |
544 (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) |
545 (0 << CC1200_MODCFG_DEV_E_DEV_E)),
546 CC1200_SYMBOL_RATE2, ((APRS_SYMBOL_RATE_E << CC1200_SYMBOL_RATE2_DATARATE_E) |
547 (((APRS_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)),
548 CC1200_SYMBOL_RATE1, ((APRS_SYMBOL_RATE_M >> 8) & 0xff),
549 CC1200_SYMBOL_RATE0, ((APRS_SYMBOL_RATE_M >> 0) & 0xff),
550 CC1200_PKT_CFG2, ((CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) |
551 (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)),
552 CC1200_PKT_CFG1, ((0 << CC1200_PKT_CFG1_WHITE_DATA) |
553 (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) |
554 (CC1200_PKT_CFG1_CRC_CFG_DISABLED << CC1200_PKT_CFG1_CRC_CFG) |
555 (0 << CC1200_PKT_CFG1_APPEND_STATUS)),
556 CC1200_PREAMBLE_CFG1, ((CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES << CC1200_PREAMBLE_CFG1_NUM_PREAMBLE) |
557 (CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1200_PREAMBLE_CFG1_PREAMBLE_WORD)),
560 #define AO_PKT_CFG0_INFINITE ((CC1200_PKT_CFG0_LENGTH_CONFIG_INFINITE << 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 #define AO_PKT_CFG0_FIXED ((CC1200_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1200_PKT_CFG0_LENGTH_CONFIG) | \
566 (0 << CC1200_PKT_CFG0_PKG_BIT_LEN) | \
567 (0 << CC1200_PKT_CFG0_UART_MODE_EN) | \
568 (0 << CC1200_PKT_CFG0_UART_SWAP_EN))
570 static uint16_t ao_radio_mode;
572 #define AO_RADIO_MODE_BITS_PACKET 1
573 #define AO_RADIO_MODE_BITS_TX_BUF 4
574 #define AO_RADIO_MODE_BITS_FINISH 8
575 #define AO_RADIO_MODE_BITS_RDF 32
576 #define AO_RADIO_MODE_BITS_APRS 64
577 #define AO_RADIO_MODE_BITS_TEST 128
578 #define AO_RADIO_MODE_BITS_INFINITE 256
579 #define AO_RADIO_MODE_BITS_FIXED 512
581 #define AO_RADIO_MODE_NONE 0
582 #define AO_RADIO_MODE_PACKET_TX (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_FINISH)
583 #define AO_RADIO_MODE_PACKET_RX (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_FINISH)
584 #define AO_RADIO_MODE_RDF (AO_RADIO_MODE_BITS_RDF | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_FINISH)
585 #define AO_RADIO_MODE_APRS_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF)
586 #define AO_RADIO_MODE_APRS_LAST_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_BUF)
587 #define AO_RADIO_MODE_APRS_FINISH (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_FINISH)
588 #define AO_RADIO_MODE_TEST (AO_RADIO_MODE_BITS_TEST | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF)
591 _ao_radio_set_regs(const uint16_t *regs, int nreg)
595 for (i = 0; i < nreg; i++) {
596 ao_radio_reg_write(regs[0], (uint8_t) regs[1]);
601 #define ao_radio_set_regs(setup) _ao_radio_set_regs(setup, (sizeof (setup) / sizeof(setup[0])) >> 1)
604 ao_radio_set_mode(uint16_t new_mode)
608 if (new_mode == ao_radio_mode)
611 changes = (uint16_t) (new_mode & (~ao_radio_mode));
613 if (changes & AO_RADIO_MODE_BITS_PACKET) {
614 ao_radio_set_regs(packet_setup);
616 switch (ao_config.radio_rate) {
618 case AO_RADIO_RATE_38400:
619 ao_radio_set_regs(packet_setup_384);
621 case AO_RADIO_RATE_9600:
622 ao_radio_set_regs(packet_setup_96);
624 ao_radio_reg_write(CC1200_CHAN_BW, PACKET_CHAN_BW_96_CC1201);
626 ao_radio_reg_write(CC1200_CHAN_BW, PACKET_CHAN_BW_96_CC1200);
628 case AO_RADIO_RATE_2400:
629 ao_radio_set_regs(packet_setup_24);
631 ao_radio_reg_write(CC1200_CHAN_BW, PACKET_CHAN_BW_24_CC1201);
633 ao_radio_reg_write(CC1200_CHAN_BW, PACKET_CHAN_BW_24_CC1200);
638 if (changes & AO_RADIO_MODE_BITS_TX_BUF) {
639 ao_radio_reg_write(AO_CC1200_INT_GPIO_IOCFG, CC1200_IOCFG_GPIO_CFG_TXFIFO_THR);
642 if (changes & AO_RADIO_MODE_BITS_FINISH) {
643 ao_radio_reg_write(AO_CC1200_INT_GPIO_IOCFG, CC1200_IOCFG_GPIO_CFG_PKT_SYNC_RXTX);
646 if (changes & AO_RADIO_MODE_BITS_RDF)
647 ao_radio_set_regs(rdf_setup);
649 if (changes & AO_RADIO_MODE_BITS_APRS)
650 ao_radio_set_regs(aprs_setup);
652 if (changes & AO_RADIO_MODE_BITS_TEST)
653 ao_radio_set_regs(test_setup);
655 if (changes & AO_RADIO_MODE_BITS_INFINITE)
656 ao_radio_reg_write(CC1200_PKT_CFG0, AO_PKT_CFG0_INFINITE);
658 if (changes & AO_RADIO_MODE_BITS_FIXED)
659 ao_radio_reg_write(CC1200_PKT_CFG0, AO_PKT_CFG0_FIXED);
661 ao_radio_mode = new_mode;
664 static const uint16_t radio_setup[] = {
665 #include "ao_cc1200_CC1200.h"
668 static uint8_t ao_radio_configured = 0;
673 uint8_t partnumber = ao_radio_reg_read(CC1200_PARTNUMBER);
675 if (partnumber == CC1200_PARTNUMBER_CC1201)
678 ao_radio_strobe(CC1200_SRES);
680 ao_radio_set_regs(radio_setup);
688 ao_radio_configured = 1;
692 ao_radio_set_len(uint8_t len)
694 static uint8_t last_len;
696 if (len != last_len) {
697 ao_radio_reg_write(CC1200_PKT_LEN, len);
703 ao_radio_get(uint8_t len)
705 static uint32_t last_radio_setting;
706 static uint8_t last_radio_rate;
707 static uint8_t last_radio_10mw;
709 ao_mutex_get(&ao_radio_mutex);
711 if (!ao_radio_configured)
713 if (ao_config.radio_setting != last_radio_setting) {
714 ao_radio_reg_write(CC1200_FREQ2, (uint8_t) (ao_config.radio_setting >> 16));
715 ao_radio_reg_write(CC1200_FREQ1, (uint8_t) (ao_config.radio_setting >> 8));
716 ao_radio_reg_write(CC1200_FREQ0, (uint8_t) ao_config.radio_setting);
717 last_radio_setting = ao_config.radio_setting;
718 ao_radio_strobe(CC1200_SCAL);
720 if (ao_config.radio_rate != last_radio_rate) {
721 ao_radio_mode &= (uint16_t) ~AO_RADIO_MODE_BITS_PACKET;
722 last_radio_rate = ao_config.radio_rate;
724 if(ao_config.radio_10mw != last_radio_10mw) {
725 last_radio_10mw = ao_config.radio_10mw;
727 * 0x37 "should" be 10dBm, but measurements on TBT
728 * v4.0 show that too hot, so use * 0x32 to make sure
731 if (ao_config.radio_10mw)
732 ao_radio_reg_write(CC1200_PA_CFG1, 0x32);
734 ao_radio_reg_write(CC1200_PA_CFG1, 0x3f);
736 ao_radio_set_len(len);
739 #define ao_radio_put() ao_mutex_put(&ao_radio_mutex)
741 static inline uint8_t
744 return (ao_radio_status() >> CC1200_STATUS_STATE) & CC1200_STATUS_STATE_MASK;
749 ao_radio_show_state(char *where)
751 printf("%s: state %d len %d rxbytes %d\n",
752 where, ao_radio_state(),
753 ao_radio_reg_read(CC1200_PKT_LEN),
754 ao_radio_reg_read(CC1200_NUM_RXBYTES));
757 #define ao_radio_show_state(where)
760 /* Wait for the radio to signal an interrupt
763 _ao_radio_wait_isr(AO_TICK_TYPE timeout)
765 while (!ao_radio_wake && !ao_radio_abort)
766 if (ao_sleep_for(&ao_radio_wake, timeout))
771 ao_radio_wait_isr(AO_TICK_TYPE timeout)
773 ao_arch_block_interrupts();
774 _ao_radio_wait_isr(timeout);
775 ao_arch_release_interrupts();
779 ao_rdf_start(uint8_t len)
784 ao_radio_set_mode(AO_RADIO_MODE_RDF);
794 ao_radio_wait_isr(0);
803 ao_rdf_start(AO_RADIO_RDF_LEN);
805 ao_radio_fifo_write_fixed(ao_radio_rdf_value, AO_RADIO_RDF_LEN);
811 ao_radio_continuity(uint8_t c)
816 ao_rdf_start(AO_RADIO_CONT_TOTAL_LEN);
818 status = ao_radio_fifo_write_start();
819 for (i = 0; i < 3; i++) {
820 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN);
822 ao_radio_spi_send_fixed(ao_radio_rdf_value, AO_RADIO_CONT_TONE_LEN);
824 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_TONE_LEN);
826 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN);
827 status = ao_radio_fifo_write_stop(status);
833 ao_radio_rdf_abort(void)
836 ao_wakeup(&ao_radio_wake);
839 static uint8_t radio_on;
842 ao_radio_test_on(void)
846 ao_monitor_disable();
849 ao_packet_slave_stop();
855 ao_radio_set_mode(AO_RADIO_MODE_TEST);
856 ao_radio_strobe(CC1200_STX);
859 for (t = 0; t < 10; t++) {
860 printf ("status: %02x\n", ao_radio_status());
861 ao_delay(AO_MS_TO_TICKS(100));
870 ao_radio_test_off(void)
886 ao_radio_test_cmd(void)
890 if (ao_cmd_lex_c != '\n')
891 mode = (uint8_t) ao_cmd_decimal();
896 printf ("Hit a character to stop..."); flush();
905 ao_radio_send(const void *d, uint8_t size)
908 ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX);
910 ao_radio_fifo_write(d, size);
916 ao_radio_send_aprs(ao_radio_fill_func fill)
918 uint8_t buf[APRS_BUFFER_SIZE];
927 while (!done && !ao_radio_abort) {
928 cnt = (*fill)(buf, sizeof(buf));
935 /* At the last buffer, set the total length */
937 ao_radio_set_len((uint8_t) (total & 0xff));
939 /* Wait for some space in the fifo */
940 ao_arch_block_interrupts();
941 while (started && ao_radio_int_pin() != 0 && !ao_radio_abort) {
943 _ao_radio_wait_isr(AO_MS_TO_TICKS(1000));
945 ao_arch_release_interrupts();
950 ao_radio_set_mode(AO_RADIO_MODE_APRS_FINISH);
952 ao_radio_set_mode(AO_RADIO_MODE_APRS_BUF);
954 ao_radio_fifo_write(buf, (uint8_t) cnt);
956 ao_radio_strobe(CC1200_STX);
960 /* Wait for the transmitter to go idle */
961 ao_arch_block_interrupts();
962 while (started && ao_radio_int_pin() != 0 && !ao_radio_abort) {
964 _ao_radio_wait_isr(AO_MS_TO_TICKS(1000));
966 ao_arch_release_interrupts();
974 ao_radio_marc_state(void)
976 return ao_radio_reg_read(CC1200_MARCSTATE);
980 ao_radio_modem_status1(void)
982 return ao_radio_reg_read(CC1200_MODEM_STATUS1);
986 ao_radio_modem_status0(void)
988 return ao_radio_reg_read(CC1200_MODEM_STATUS0);
991 struct ao_radio_state {
994 uint8_t marc_status1;
995 uint8_t marc_status0;
996 uint8_t modem_status1;
997 uint8_t modem_status0;
1001 ao_radio_fill_state(char *where, struct ao_radio_state *s)
1003 strcpy(s->where, where);
1004 s->marc_state = ao_radio_marc_state();
1005 s->marc_status1 = ao_radio_reg_read(CC1200_MARC_STATUS1);
1006 s->marc_status0 = ao_radio_reg_read(CC1200_MARC_STATUS0);
1007 s->modem_status1 = ao_radio_modem_status1();
1008 s->modem_status0 = ao_radio_modem_status0();
1012 ao_radio_dump_state(struct ao_radio_state *s)
1014 printf ("%s: marc %2x marc1 %2x marc0 %2x modem1 %2x modem0 %2x\n",
1015 s->where, s->marc_state, s->marc_status1, s->marc_status0, s->modem_status1, s->modem_status0);
1020 ao_radio_recv(void *d, uint8_t size, AO_TICK_TYPE timeout)
1022 uint8_t success = 0;
1025 ao_radio_get(size - 2);
1026 ao_radio_set_mode(AO_RADIO_MODE_PACKET_RX);
1028 ao_radio_start_rx();
1030 while (!ao_radio_abort) {
1031 ao_radio_wait_isr(timeout);
1034 if (ao_radio_wake) {
1035 uint8_t marc_status1 = ao_radio_reg_read(CC1200_MARC_STATUS1);
1037 /* Check the receiver status to see what happened
1039 switch (marc_status1) {
1040 case CC1200_MARC_STATUS1_RX_FINISHED:
1041 case CC1200_MARC_STATUS1_ADDRESS:
1042 case CC1200_MARC_STATUS1_CRC:
1043 /* Normal return, go fetch the bytes from the FIFO
1044 * and give them back to the caller
1048 case CC1200_MARC_STATUS1_RX_TIMEOUT:
1049 case CC1200_MARC_STATUS1_RX_TERMINATION:
1050 case CC1200_MARC_STATUS1_EWOR_SYNC_LOST:
1051 case CC1200_MARC_STATUS1_MAXIMUM_LENGTH:
1052 case CC1200_MARC_STATUS1_RX_FIFO_OVERFLOW:
1053 case CC1200_MARC_STATUS1_RX_FIFO_UNDERFLOW:
1054 /* Something weird happened; reset the radio and
1060 /* some other status; go wait for the radio to do something useful
1066 uint8_t modem_status1 = ao_radio_reg_read(CC1200_MODEM_STATUS1);
1068 /* Check to see if the packet header has been seen, in which case we'll
1069 * want to keep waiting for the rest of the packet to appear
1071 if (modem_status1 & (1 << CC1200_MODEM_STATUS1_SYNC_FOUND))
1075 /* Set a timeout based on the packet length so that we make sure to
1076 * wait long enough to receive the whole thing.
1078 * timeout = bits * FEC expansion / rate
1080 switch (ao_config.radio_rate) {
1082 case AO_RADIO_RATE_38400:
1083 timeout = AO_MS_TO_TICKS((AO_TICK_TYPE) size * (8 * 2 * 10) / 384) + 1;
1085 case AO_RADIO_RATE_9600:
1086 timeout = AO_MS_TO_TICKS((AO_TICK_TYPE) size * (8 * 2 * 10) / 96) + 1;
1088 case AO_RADIO_RATE_2400:
1089 timeout = AO_MS_TO_TICKS((AO_TICK_TYPE) size * (8 * 2 * 10) / 24) + 1;
1100 status = ao_radio_fifo_read(d, size);
1102 rssi = ((int8_t *) d)[size - 2];
1103 ao_radio_rssi = rssi;
1105 /* Bound it to the representable range */
1109 /* Write it back to the packet */
1110 ((uint8_t *) d)[size-2] = AO_RADIO_FROM_RSSI(rssi);
1122 static char *cc1200_state_name[] = {
1123 [CC1200_STATUS_STATE_IDLE] = "IDLE",
1124 [CC1200_STATUS_STATE_RX] = "RX",
1125 [CC1200_STATUS_STATE_TX] = "TX",
1126 [CC1200_STATUS_STATE_FSTXON] = "FSTXON",
1127 [CC1200_STATUS_STATE_CALIBRATE] = "CALIBRATE",
1128 [CC1200_STATUS_STATE_SETTLING] = "SETTLING",
1129 [CC1200_STATUS_STATE_RX_FIFO_ERROR] = "RX_FIFO_ERROR",
1130 [CC1200_STATUS_STATE_TX_FIFO_ERROR] = "TX_FIFO_ERROR",
1133 struct ao_cc1200_reg {
1138 static const struct ao_cc1200_reg ao_cc1200_reg[] = {
1139 { .addr = CC1200_IOCFG3, .name = "IOCFG3" },
1140 { .addr = CC1200_IOCFG2, .name = "IOCFG2" },
1141 { .addr = CC1200_IOCFG1, .name = "IOCFG1" },
1142 { .addr = CC1200_IOCFG0, .name = "IOCFG0" },
1143 { .addr = CC1200_SYNC3, .name = "SYNC3" },
1144 { .addr = CC1200_SYNC2, .name = "SYNC2" },
1145 { .addr = CC1200_SYNC1, .name = "SYNC1" },
1146 { .addr = CC1200_SYNC0, .name = "SYNC0" },
1147 { .addr = CC1200_SYNC_CFG1, .name = "SYNC_CFG1" },
1148 { .addr = CC1200_SYNC_CFG0, .name = "SYNC_CFG0" },
1149 { .addr = CC1200_DEVIATION_M, .name = "DEVIATION_M" },
1150 { .addr = CC1200_MODCFG_DEV_E, .name = "MODCFG_DEV_E" },
1151 { .addr = CC1200_DCFILT_CFG, .name = "DCFILT_CFG" },
1152 { .addr = CC1200_PREAMBLE_CFG1, .name = "PREAMBLE_CFG1" },
1153 { .addr = CC1200_PREAMBLE_CFG0, .name = "PREAMBLE_CFG0" },
1154 { .addr = CC1200_IQIC, .name = "IQIC" },
1155 { .addr = CC1200_CHAN_BW, .name = "CHAN_BW" },
1156 { .addr = CC1200_MDMCFG2, .name = "MDMCFG2" },
1157 { .addr = CC1200_MDMCFG1, .name = "MDMCFG1" },
1158 { .addr = CC1200_MDMCFG0, .name = "MDMCFG0" },
1159 { .addr = CC1200_SYMBOL_RATE2, .name = "SYMBOL_RATE2" },
1160 { .addr = CC1200_SYMBOL_RATE1, .name = "SYMBOL_RATE1" },
1161 { .addr = CC1200_SYMBOL_RATE0, .name = "SYMBOL_RATE0" },
1162 { .addr = CC1200_AGC_REF, .name = "AGC_REF" },
1163 { .addr = CC1200_AGC_CS_THR, .name = "AGC_CS_THR" },
1164 { .addr = CC1200_AGC_GAIN_ADJUST, .name = "AGC_GAIN_ADJUST" },
1165 { .addr = CC1200_AGC_CFG3, .name = "AGC_CFG3" },
1166 { .addr = CC1200_AGC_CFG2, .name = "AGC_CFG2" },
1167 { .addr = CC1200_AGC_CFG1, .name = "AGC_CFG1" },
1168 { .addr = CC1200_AGC_CFG0, .name = "AGC_CFG0" },
1169 { .addr = CC1200_FIFO_CFG, .name = "FIFO_CFG" },
1170 { .addr = CC1200_DEV_ADDR, .name = "DEV_ADDR" },
1171 { .addr = CC1200_SETTLING_CFG, .name = "SETTLING_CFG" },
1172 { .addr = CC1200_FS_CFG, .name = "FS_CFG" },
1173 { .addr = CC1200_WOR_CFG1, .name = "WOR_CFG1" },
1174 { .addr = CC1200_WOR_CFG0, .name = "WOR_CFG0" },
1175 { .addr = CC1200_WOR_EVENT0_MSB, .name = "WOR_EVENT0_MSB" },
1176 { .addr = CC1200_WOR_EVENT0_LSB, .name = "WOR_EVENT0_LSB" },
1177 { .addr = CC1200_RXDCM_TIME, .name = "RXDCM_TIME" },
1178 { .addr = CC1200_PKT_CFG2, .name = "PKT_CFG2" },
1179 { .addr = CC1200_PKT_CFG1, .name = "PKT_CFG1" },
1180 { .addr = CC1200_PKT_CFG0, .name = "PKT_CFG0" },
1181 { .addr = CC1200_RFEND_CFG1, .name = "RFEND_CFG1" },
1182 { .addr = CC1200_RFEND_CFG0, .name = "RFEND_CFG0" },
1183 { .addr = CC1200_PA_CFG1, .name = "PA_CFG1" },
1184 { .addr = CC1200_PA_CFG0, .name = "PA_CFG0" },
1185 { .addr = CC1200_PKT_LEN, .name = "PKT_LEN" },
1186 { .addr = CC1200_IF_MIX_CFG, .name = "IF_MIX_CFG" },
1187 { .addr = CC1200_FREQOFF_CFG, .name = "FREQOFF_CFG" },
1188 { .addr = CC1200_TOC_CFG, .name = "TOC_CFG" },
1189 { .addr = CC1200_MARC_SPARE, .name = "MARC_SPARE" },
1190 { .addr = CC1200_ECG_CFG, .name = "ECG_CFG" },
1191 { .addr = CC1200_EXT_CTRL, .name = "EXT_CTRL" },
1192 { .addr = CC1200_RCCAL_FINE, .name = "RCCAL_FINE" },
1193 { .addr = CC1200_RCCAL_COARSE, .name = "RCCAL_COARSE" },
1194 { .addr = CC1200_RCCAL_OFFSET, .name = "RCCAL_OFFSET" },
1195 { .addr = CC1200_FREQOFF1, .name = "FREQOFF1" },
1196 { .addr = CC1200_FREQOFF0, .name = "FREQOFF0" },
1197 { .addr = CC1200_FREQ2, .name = "FREQ2" },
1198 { .addr = CC1200_FREQ1, .name = "FREQ1" },
1199 { .addr = CC1200_FREQ0, .name = "FREQ0" },
1200 { .addr = CC1200_IF_ADC2, .name = "IF_ADC2" },
1201 { .addr = CC1200_IF_ADC1, .name = "IF_ADC1" },
1202 { .addr = CC1200_IF_ADC0, .name = "IF_ADC0" },
1203 { .addr = CC1200_FS_DIG1, .name = "FS_DIG1" },
1204 { .addr = CC1200_FS_DIG0, .name = "FS_DIG0" },
1205 { .addr = CC1200_FS_CAL3, .name = "FS_CAL3" },
1206 { .addr = CC1200_FS_CAL2, .name = "FS_CAL2" },
1207 { .addr = CC1200_FS_CAL1, .name = "FS_CAL1" },
1208 { .addr = CC1200_FS_CAL0, .name = "FS_CAL0" },
1209 { .addr = CC1200_FS_CHP, .name = "FS_CHP" },
1210 { .addr = CC1200_FS_DIVTWO, .name = "FS_DIVTWO" },
1211 { .addr = CC1200_FS_DSM1, .name = "FS_DSM1" },
1212 { .addr = CC1200_FS_DSM0, .name = "FS_DSM0" },
1213 { .addr = CC1200_FS_DVC1, .name = "FS_DVC1" },
1214 { .addr = CC1200_FS_DVC0, .name = "FS_DVC0" },
1215 { .addr = CC1200_FS_LBI, .name = "FS_LBI" },
1216 { .addr = CC1200_FS_PFD, .name = "FS_PFD" },
1217 { .addr = CC1200_FS_PRE, .name = "FS_PRE" },
1218 { .addr = CC1200_FS_REG_DIV_CML, .name = "FS_REG_DIV_CML" },
1219 { .addr = CC1200_FS_SPARE, .name = "FS_SPARE" },
1220 { .addr = CC1200_FS_VCO4, .name = "FS_VCO4" },
1221 { .addr = CC1200_FS_VCO3, .name = "FS_VCO3" },
1222 { .addr = CC1200_FS_VCO2, .name = "FS_VCO2" },
1223 { .addr = CC1200_FS_VCO1, .name = "FS_VCO1" },
1224 { .addr = CC1200_FS_VCO0, .name = "FS_VCO0" },
1225 { .addr = CC1200_GBIAS6, .name = "GBIAS6" },
1226 { .addr = CC1200_GBIAS5, .name = "GBIAS5" },
1227 { .addr = CC1200_GBIAS4, .name = "GBIAS4" },
1228 { .addr = CC1200_GBIAS3, .name = "GBIAS3" },
1229 { .addr = CC1200_GBIAS2, .name = "GBIAS2" },
1230 { .addr = CC1200_GBIAS1, .name = "GBIAS1" },
1231 { .addr = CC1200_GBIAS0, .name = "GBIAS0" },
1232 { .addr = CC1200_IFAMP, .name = "IFAMP" },
1233 { .addr = CC1200_LNA, .name = "LNA" },
1234 { .addr = CC1200_RXMIX, .name = "RXMIX" },
1235 { .addr = CC1200_XOSC5, .name = "XOSC5" },
1236 { .addr = CC1200_XOSC4, .name = "XOSC4" },
1237 { .addr = CC1200_XOSC3, .name = "XOSC3" },
1238 { .addr = CC1200_XOSC2, .name = "XOSC2" },
1239 { .addr = CC1200_XOSC1, .name = "XOSC1" },
1240 { .addr = CC1200_XOSC0, .name = "XOSC0" },
1241 { .addr = CC1200_ANALOG_SPARE, .name = "ANALOG_SPARE" },
1242 { .addr = CC1200_PA_CFG3, .name = "PA_CFG3" },
1243 { .addr = CC1200_WOR_TIME1, .name = "WOR_TIME1" },
1244 { .addr = CC1200_WOR_TIME0, .name = "WOR_TIME0" },
1245 { .addr = CC1200_WOR_CAPTURE1, .name = "WOR_CAPTURE1" },
1246 { .addr = CC1200_WOR_CAPTURE0, .name = "WOR_CAPTURE0" },
1247 { .addr = CC1200_BIST, .name = "BIST" },
1248 { .addr = CC1200_DCFILTOFFSET_I1, .name = "DCFILTOFFSET_I1" },
1249 { .addr = CC1200_DCFILTOFFSET_I0, .name = "DCFILTOFFSET_I0" },
1250 { .addr = CC1200_DCFILTOFFSET_Q1, .name = "DCFILTOFFSET_Q1" },
1251 { .addr = CC1200_DCFILTOFFSET_Q0, .name = "DCFILTOFFSET_Q0" },
1252 { .addr = CC1200_IQIE_I1, .name = "IQIE_I1" },
1253 { .addr = CC1200_IQIE_I0, .name = "IQIE_I0" },
1254 { .addr = CC1200_IQIE_Q1, .name = "IQIE_Q1" },
1255 { .addr = CC1200_IQIE_Q0, .name = "IQIE_Q0" },
1256 { .addr = CC1200_RSSI1, .name = "RSSI1" },
1257 { .addr = CC1200_RSSI0, .name = "RSSI0" },
1258 { .addr = CC1200_MARCSTATE, .name = "MARCSTATE" },
1259 { .addr = CC1200_LQI_VAL, .name = "LQI_VAL" },
1260 { .addr = CC1200_PQT_SYNC_ERR, .name = "PQT_SYNC_ERR" },
1261 { .addr = CC1200_DEM_STATUS, .name = "DEM_STATUS" },
1262 { .addr = CC1200_FREQOFF_EST1, .name = "FREQOFF_EST1" },
1263 { .addr = CC1200_FREQOFF_EST0, .name = "FREQOFF_EST0" },
1264 { .addr = CC1200_AGC_GAIN3, .name = "AGC_GAIN3" },
1265 { .addr = CC1200_AGC_GAIN2, .name = "AGC_GAIN2" },
1266 { .addr = CC1200_AGC_GAIN1, .name = "AGC_GAIN1" },
1267 { .addr = CC1200_AGC_GAIN0, .name = "AGC_GAIN0" },
1268 { .addr = CC1200_SOFT_RX_DATA_OUT, .name = "SOFT_RX_DATA_OUT" },
1269 { .addr = CC1200_SOFT_TX_DATA_IN, .name = "SOFT_TX_DATA_IN" },
1270 { .addr = CC1200_ASK_SOFT_RX_DATA, .name = "ASK_SOFT_RX_DATA" },
1271 { .addr = CC1200_RNDGEN, .name = "RNDGEN" },
1272 { .addr = CC1200_MAGN2, .name = "MAGN2" },
1273 { .addr = CC1200_MAGN1, .name = "MAGN1" },
1274 { .addr = CC1200_MAGN0, .name = "MAGN0" },
1275 { .addr = CC1200_ANG1, .name = "ANG1" },
1276 { .addr = CC1200_ANG0, .name = "ANG0" },
1277 { .addr = CC1200_CHFILT_I2, .name = "CHFILT_I2" },
1278 { .addr = CC1200_CHFILT_I1, .name = "CHFILT_I1" },
1279 { .addr = CC1200_CHFILT_I0, .name = "CHFILT_I0" },
1280 { .addr = CC1200_CHFILT_Q2, .name = "CHFILT_Q2" },
1281 { .addr = CC1200_CHFILT_Q1, .name = "CHFILT_Q1" },
1282 { .addr = CC1200_CHFILT_Q0, .name = "CHFILT_Q0" },
1283 { .addr = CC1200_GPIO_STATUS, .name = "GPIO_STATUS" },
1284 { .addr = CC1200_FSCAL_CTRL, .name = "FSCAL_CTRL" },
1285 { .addr = CC1200_PHASE_ADJUST, .name = "PHASE_ADJUST" },
1286 { .addr = CC1200_PARTNUMBER, .name = "PARTNUMBER" },
1287 { .addr = CC1200_PARTVERSION, .name = "PARTVERSION" },
1288 { .addr = CC1200_SERIAL_STATUS, .name = "SERIAL_STATUS" },
1289 { .addr = CC1200_MODEM_STATUS1, .name = "MODEM_STATUS1" },
1290 { .addr = CC1200_MODEM_STATUS0, .name = "MODEM_STATUS0" },
1291 { .addr = CC1200_MARC_STATUS1, .name = "MARC_STATUS1" },
1292 { .addr = CC1200_MARC_STATUS0, .name = "MARC_STATUS0" },
1293 { .addr = CC1200_PA_IFAMP_TEST, .name = "PA_IFAMP_TEST" },
1294 { .addr = CC1200_FSRF_TEST, .name = "FSRF_TEST" },
1295 { .addr = CC1200_PRE_TEST, .name = "PRE_TEST" },
1296 { .addr = CC1200_PRE_OVR, .name = "PRE_OVR" },
1297 { .addr = CC1200_ADC_TEST, .name = "ADC_TEST" },
1298 { .addr = CC1200_DVC_TEST, .name = "DVC_TEST" },
1299 { .addr = CC1200_ATEST, .name = "ATEST" },
1300 { .addr = CC1200_ATEST_LVDS, .name = "ATEST_LVDS" },
1301 { .addr = CC1200_ATEST_MODE, .name = "ATEST_MODE" },
1302 { .addr = CC1200_XOSC_TEST1, .name = "XOSC_TEST1" },
1303 { .addr = CC1200_XOSC_TEST0, .name = "XOSC_TEST0" },
1304 { .addr = CC1200_RXFIRST, .name = "RXFIRST" },
1305 { .addr = CC1200_TXFIRST, .name = "TXFIRST" },
1306 { .addr = CC1200_RXLAST, .name = "RXLAST" },
1307 { .addr = CC1200_TXLAST, .name = "TXLAST" },
1308 { .addr = CC1200_NUM_TXBYTES, .name = "NUM_TXBYTES" },
1309 { .addr = CC1200_NUM_RXBYTES, .name = "NUM_RXBYTES" },
1310 { .addr = CC1200_FIFO_NUM_TXBYTES, .name = "FIFO_NUM_TXBYTES" },
1311 { .addr = CC1200_FIFO_NUM_RXBYTES, .name = "FIFO_NUM_RXBYTES" },
1314 #define AO_NUM_CC1200_REG (sizeof ao_cc1200_reg / sizeof ao_cc1200_reg[0])
1317 ao_radio_get_marc_status(void)
1319 return ao_radio_reg_read(CC1200_MARC_STATUS1);
1322 static void ao_radio_show(void) {
1326 ao_mutex_get(&ao_radio_mutex);
1327 status = ao_radio_status();
1328 printf ("Status: %02x\n", status);
1329 printf ("CHIP_RDY: %d\n", (status >> CC1200_STATUS_CHIP_RDY) & 1);
1330 printf ("STATE: %s\n", cc1200_state_name[(status >> CC1200_STATUS_STATE) & CC1200_STATUS_STATE_MASK]);
1331 printf ("MARC: %02x\n", ao_radio_get_marc_status());
1333 for (i = 0; i < AO_NUM_CC1200_REG; i++)
1334 printf ("\t%02x %-20.20s\n", ao_radio_reg_read(ao_cc1200_reg[i].addr), ao_cc1200_reg[i].name);
1339 static void ao_radio_beep(void) {
1343 static void ao_radio_packet(void) {
1344 static const uint8_t packet[] = {
1346 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1347 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1348 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1349 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1355 ao_radio_send(packet, sizeof (packet));
1359 ao_radio_test_recv(void)
1361 static uint8_t bytes[34];
1364 if (ao_radio_recv(bytes, 34, 0)) {
1365 if (bytes[33] & 0x80)
1369 printf (" RSSI %d", AO_RSSI_FROM_RADIO(bytes[32]));
1370 for (b = 0; b < 32; b++)
1371 printf (" %02x", bytes[b]);
1373 printf (" RSSI %02x LQI %02x", bytes[32], bytes[33]);
1379 #include <ao_aprs.h>
1384 #if PACKET_HAS_SLAVE
1385 ao_packet_slave_stop();
1392 #if CC1200_LOW_LEVEL_DEBUG
1394 ao_radio_strobe_test(void)
1399 addr = ao_cmd_hex();
1400 if (ao_cmd_status != ao_cmd_success)
1402 r = ao_radio_strobe(addr);
1403 printf ("Strobe %02x -> %02x (rdy %d state %d)\n",
1411 ao_radio_write_test(void)
1416 addr = ao_cmd_hex();
1417 if (ao_cmd_status != ao_cmd_success)
1419 data = ao_cmd_hex();
1420 if (ao_cmd_status != ao_cmd_success)
1422 printf ("Write %04x = %02x\n", addr, data);
1423 ao_radio_reg_write(addr, data);
1427 ao_radio_read_test(void)
1432 addr = ao_cmd_hex();
1433 if (ao_cmd_status != ao_cmd_success)
1435 data = ao_radio_reg_read(addr);
1436 printf ("Read %04x = %02x\n", addr, data);
1440 static const struct ao_cmds ao_radio_cmds[] = {
1441 { ao_radio_test_cmd, "C <1 start, 0 stop, none both>\0Radio carrier test" },
1444 { ao_radio_aprs, "G\0Send APRS packet" },
1446 { ao_radio_show, "R\0Show CC1200 status" },
1447 { ao_radio_beep, "b\0Emit an RDF beacon" },
1448 { ao_radio_packet, "p\0Send a test packet" },
1449 { ao_radio_test_recv, "q\0Recv a test packet" },
1451 #if CC1200_LOW_LEVEL_DEBUG
1452 { ao_radio_strobe_test, "A <value>\0Strobe radio" },
1453 { ao_radio_write_test, "W <addr> <value>\0Write radio reg" },
1454 { ao_radio_read_test, "B <addr>\0Read radio reg" },
1462 ao_radio_configured = 0;
1463 ao_spi_init_cs (AO_CC1200_SPI_CS_PORT, (1 << AO_CC1200_SPI_CS_PIN));
1466 AO_CC1200_SPI_CS_PORT->bsrr = ((uint32_t) (1 << AO_CC1200_SPI_CS_PIN));
1467 for (i = 0; i < 10000; i++) {
1468 if ((SPI_2_PORT->idr & (1 << SPI_2_MISO_PIN)) == 0)
1471 AO_CC1200_SPI_CS_PORT->bsrr = (1 << AO_CC1200_SPI_CS_PIN);
1473 ao_panic(AO_PANIC_SELF_TEST_CC1200);
1476 /* Enable the EXTI interrupt for the appropriate pin */
1477 ao_enable_port(AO_CC1200_INT_PORT);
1478 ao_exti_setup(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN,
1479 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH,
1482 ao_exti_enable(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN);
1484 ao_cmd_register(&ao_radio_cmds[0]);