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 #define AO_CC1200_SPI_SPEED ao_spi_speed(7700000) /* 7.7MHz max for extended memory reads */
56 #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)
57 #define ao_radio_deselect() ao_spi_put_mask(AO_CC1200_SPI_CS_PORT,(1 << AO_CC1200_SPI_CS_PIN),AO_CC1200_SPI_BUS)
58 #define ao_radio_spi_send(d,l) ao_spi_send((d), (l), AO_CC1200_SPI_BUS)
59 #define ao_radio_spi_send_fixed(d,l) ao_spi_send_fixed((d), (l), AO_CC1200_SPI_BUS)
60 #define ao_radio_spi_recv(d,l) ao_spi_recv((d), (l), AO_CC1200_SPI_BUS)
61 #define ao_radio_duplex(o,i,l) ao_spi_duplex((o), (i), (l), AO_CC1200_SPI_BUS)
64 ao_radio_reg_read(uint16_t addr)
70 printf("\t\tao_radio_reg_read (%04x): ", addr); flush();
72 if (CC1200_IS_EXTENDED(addr)) {
73 data[0] = ((1 << CC1200_READ) |
79 data[0] = ((1 << CC1200_READ) |
85 ao_radio_spi_send(data, d);
86 ao_radio_spi_recv(data, 1);
89 printf (" %02x\n", data[0]);
95 ao_radio_reg_write(uint16_t addr, uint8_t value)
101 printf("\t\tao_radio_reg_write (%04x): %02x\n", addr, value);
103 if (CC1200_IS_EXTENDED(addr)) {
104 data[0] = ((0 << CC1200_READ) |
105 (0 << CC1200_BURST) |
110 data[0] = ((0 << CC1200_READ) |
111 (0 << CC1200_BURST) |
117 ao_radio_spi_send(data, d+1);
120 (void) ao_radio_reg_read(addr);
125 ao_radio_strobe(uint8_t addr)
130 printf("\t\tao_radio_strobe (%02x): ", addr); flush();
133 ao_radio_duplex(&addr, &in, 1);
136 printf("%02x\n", in); flush();
142 ao_radio_fifo_read(uint8_t *data, uint8_t len)
144 uint8_t addr = ((1 << CC1200_READ) |
145 (1 << CC1200_BURST) |
150 ao_radio_duplex(&addr, &status, 1);
151 ao_radio_spi_recv(data, len);
157 ao_radio_fifo_write_start(void)
159 uint8_t addr = ((0 << CC1200_READ) |
160 (1 << CC1200_BURST) |
165 ao_radio_duplex(&addr, &status, 1);
169 static inline uint8_t ao_radio_fifo_write_stop(uint8_t status) {
175 ao_radio_fifo_write(const uint8_t *data, uint8_t len)
177 uint8_t status = ao_radio_fifo_write_start();
178 ao_radio_spi_send(data, len);
179 return ao_radio_fifo_write_stop(status);
183 ao_radio_fifo_write_fixed(uint8_t data, uint8_t len)
185 uint8_t status = ao_radio_fifo_write_start();
186 ao_radio_spi_send_fixed(data, len);
187 return ao_radio_fifo_write_stop(status);
191 ao_radio_int_pin(void)
193 return ao_gpio_get(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN);
197 ao_radio_status(void)
199 return ao_radio_strobe (CC1200_SNOP);
203 ao_radio_recv_abort(void)
206 ao_wakeup(&ao_radio_wake);
209 #define ao_radio_rdf_value 0x55
214 ao_exti_disable(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN);
216 ao_wakeup(&ao_radio_wake);
220 ao_radio_start_tx(void)
222 ao_exti_enable(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN);
223 ao_radio_strobe(CC1200_STX);
227 ao_radio_start_rx(void)
229 ao_exti_enable(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN);
230 ao_radio_strobe(CC1200_SRX);
237 uint8_t state = (ao_radio_strobe(CC1200_SIDLE) >> CC1200_STATUS_STATE) & CC1200_STATUS_STATE_MASK;
238 if (state == CC1200_STATUS_STATE_IDLE)
240 if (state == CC1200_STATUS_STATE_TX_FIFO_ERROR)
241 ao_radio_strobe(CC1200_SFTX);
242 if (state == CC1200_STATUS_STATE_RX_FIFO_ERROR)
243 ao_radio_strobe(CC1200_SFRX);
245 /* Flush any pending data in the fifos */
246 ao_radio_strobe(CC1200_SFTX);
247 ao_radio_strobe(CC1200_SFRX);
248 /* Make sure the RF calibration is current */
249 ao_radio_strobe(CC1200_SCAL);
255 * fdev = fosc >> 22 * (256 + dev_m) << dev_e
257 * Deviation for 38400 baud should be 20.5kHz:
259 * 40e6 / (2 ** 22) * (256 + 13) * (2 ** 3) = 20523Hz
261 * Deviation for 9600 baud should be 5.125kHz:
263 * 40e6 / (2 ** 22) * (256 + 13) * (2 ** 1) = 5131Hz
265 * Deviation for 2400 baud should be 1.28125kHz, but cc1111 and
266 * cc115l can't do that, so we'll use 1.5kHz instead:
268 * 40e6 / (2 ** 21) * (79) = 1506Hz
271 #define PACKET_DEV_M_384 13
272 #define PACKET_DEV_E_384 3
274 #define PACKET_DEV_M_96 13
275 #define PACKET_DEV_E_96 1
277 #define PACKET_DEV_M_24 79
278 #define PACKET_DEV_E_24 0
281 * For our packet data
283 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
284 * Rdata = -------------------------------------- * fosc
287 * Given the bit period of the baseband, T, the bandwidth of the
288 * baseband signal is B = 1/(2T). The overall bandwidth of the
289 * modulated signal is then Channel bandwidth = 2Δf + 2B.
291 * 38400 -- 2 * 20500 + 38400 = 79.4 kHz
292 * 9600 -- 2 * 5.125 + 9600 = 19.9 kHz
293 * 2400 -- 2 * 1.5 + 2400 = 5.4 khz
295 * Symbol rate 38400 Baud:
297 * DATARATE_M = 1013008
301 * Symbol rate 9600 Baud:
303 * DATARATE_M = 1013008
305 * CHANBW = 26.042 (round to 19.8)
307 * Symbol rate 2400 Baud:
309 * DATARATE_M = 1013008
311 * CHANBW = 5.0 (round to 9.5)
315 #define PACKET_SYMBOL_RATE_M 1013008
316 #define PACKET_SYMBOL_RATE_E_384 8
317 #define PACKET_SYMBOL_RATE_E_96 6
318 #define PACKET_SYMBOL_RATE_E_24 4
322 #define PACKET_SYMBOL_RATE_M 239914
323 #define PACKET_SYMBOL_RATE_E_384 9
324 #define PACKET_SYMBOL_RATE_E_96 7
325 #define PACKET_SYMBOL_RATE_E_24 5
329 #define PACKET_CHAN_BW_384 ((CC1200_CHAN_BW_ADC_CIC_DECFACT_12 << CC1200_CHAN_BW_ADC_CIC_DECFACT) | \
330 (16 << CC1200_CHAN_BW_BB_CIC_DECFACT))
333 #define PACKET_CHAN_BW_96 ((CC1200_CHAN_BW_ADC_CIC_DECFACT_48 << CC1200_CHAN_BW_ADC_CIC_DECFACT) | \
334 (16 << CC1200_CHAN_BW_BB_CIC_DECFACT))
337 #define PACKET_CHAN_BW_24 ((CC1200_CHAN_BW_ADC_CIC_DECFACT_48 << CC1200_CHAN_BW_ADC_CIC_DECFACT) | \
338 (44 << CC1200_CHAN_BW_BB_CIC_DECFACT))
340 static const uint16_t packet_setup[] = {
341 CC1200_SYMBOL_RATE1, ((PACKET_SYMBOL_RATE_M >> 8) & 0xff),
342 CC1200_SYMBOL_RATE0, ((PACKET_SYMBOL_RATE_M >> 0) & 0xff),
343 CC1200_PKT_CFG2, /* Packet Configuration Reg. 2 */
344 ((0 << CC1200_PKT_CFG2_FG_MODE_EN) |
345 (CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) |
346 (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)),
347 CC1200_PKT_CFG1, /* Packet Configuration Reg. 1 */
348 ((1 << CC1200_PKT_CFG1_FEC_EN) |
349 (1 << CC1200_PKT_CFG1_WHITE_DATA) |
350 (0 << CC1200_PKT_CFG1_PN9_SWAP_EN) |
351 (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) |
352 (CC1200_PKT_CFG1_CRC_CFG_CRC16_INIT_ONES << CC1200_PKT_CFG1_CRC_CFG) |
353 (1 << CC1200_PKT_CFG1_APPEND_STATUS)),
354 CC1200_PREAMBLE_CFG1, ((CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES << CC1200_PREAMBLE_CFG1_NUM_PREAMBLE) |
355 (CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1200_PREAMBLE_CFG1_PREAMBLE_WORD)),
358 static const uint16_t packet_setup_384[] = {
359 CC1200_DEVIATION_M, PACKET_DEV_M_384,
360 CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) |
361 (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) |
362 (PACKET_DEV_E_384 << CC1200_MODCFG_DEV_E_DEV_E)),
363 CC1200_SYMBOL_RATE2, ((PACKET_SYMBOL_RATE_E_384 << CC1200_SYMBOL_RATE2_DATARATE_E) |
364 (((PACKET_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)),
365 CC1200_CHAN_BW, PACKET_CHAN_BW_384,
366 CC1200_MDMCFG2, /* General Modem Parameter Configuration Reg. 2 */
367 ((CC1200_MDMCFG2_ASK_SHAPE_8 << CC1200_MDMCFG2_ASK_SHAPE) |
368 (CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) |
369 (CC1200_MDMCFG2_UPSAMPLER_P_8 << CC1200_MDMCFG2_UPSAMPLER_P) |
370 (0 << CC1200_MDMCFG2_CFM_DATA_EN)),
373 static const uint16_t packet_setup_96[] = {
374 CC1200_DEVIATION_M, PACKET_DEV_M_96,
375 CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) |
376 (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) |
377 (PACKET_DEV_E_96 << CC1200_MODCFG_DEV_E_DEV_E)),
378 CC1200_SYMBOL_RATE2, ((PACKET_SYMBOL_RATE_E_96 << CC1200_SYMBOL_RATE2_DATARATE_E) |
379 (((PACKET_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)),
380 CC1200_CHAN_BW, PACKET_CHAN_BW_96,
381 CC1200_MDMCFG2, /* General Modem Parameter Configuration Reg. 2 */
382 ((CC1200_MDMCFG2_ASK_SHAPE_8 << CC1200_MDMCFG2_ASK_SHAPE) |
383 (CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) |
384 (CC1200_MDMCFG2_UPSAMPLER_P_32 << CC1200_MDMCFG2_UPSAMPLER_P) |
385 (0 << CC1200_MDMCFG2_CFM_DATA_EN)),
388 static const uint16_t packet_setup_24[] = {
389 CC1200_DEVIATION_M, PACKET_DEV_M_24,
390 CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) |
391 (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) |
392 (PACKET_DEV_E_24 << CC1200_MODCFG_DEV_E_DEV_E)),
393 CC1200_SYMBOL_RATE2, ((PACKET_SYMBOL_RATE_E_24 << CC1200_SYMBOL_RATE2_DATARATE_E) |
394 (((PACKET_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)),
395 CC1200_CHAN_BW, PACKET_CHAN_BW_24,
396 CC1200_MDMCFG2, /* General Modem Parameter Configuration Reg. 2 */
397 ((CC1200_MDMCFG2_ASK_SHAPE_8 << CC1200_MDMCFG2_ASK_SHAPE) |
398 (CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) |
399 (CC1200_MDMCFG2_UPSAMPLER_P_64 << CC1200_MDMCFG2_UPSAMPLER_P) |
400 (0 << CC1200_MDMCFG2_CFM_DATA_EN)),
404 * RDF deviation is 3kHz
406 * fdev = fosc >> 22 * (256 + dev_m) << dev_e dev_e != 0
407 * fdev = fosc >> 21 * dev_m dev_e == 0
409 * 40e6 / (2 ** 21) * 157 = 2995Hz
413 #define RDF_DEV_M 157
416 * For our RDF beacon, set the symbol rate to 2kBaud (for a 1kHz tone)
418 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
419 * Rdata = -------------------------------------- * fosc
422 * DATARATE_M = 669411
425 * To make the tone last for 200ms, we need 2000 * .2 = 400 bits or 50 bytes
427 #define RDF_SYMBOL_RATE_E 4
428 #define RDF_SYMBOL_RATE_M 669411
429 #define RDF_PACKET_LEN 50
431 static const uint16_t rdf_setup[] = {
432 CC1200_DEVIATION_M, RDF_DEV_M,
433 CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) |
434 (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) |
435 (RDF_DEV_E << CC1200_MODCFG_DEV_E_DEV_E)),
436 CC1200_SYMBOL_RATE2, ((RDF_SYMBOL_RATE_E << CC1200_SYMBOL_RATE2_DATARATE_E) |
437 (((RDF_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)),
438 CC1200_SYMBOL_RATE1, ((RDF_SYMBOL_RATE_M >> 8) & 0xff),
439 CC1200_SYMBOL_RATE0, ((RDF_SYMBOL_RATE_M >> 0) & 0xff),
440 CC1200_PKT_CFG2, /* Packet Configuration Reg. 2 */
441 ((0 << CC1200_PKT_CFG2_FG_MODE_EN) |
442 (CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) |
443 (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)),
444 CC1200_PKT_CFG1, /* Packet Configuration Reg. 1 */
445 ((0 << CC1200_PKT_CFG1_FEC_EN) |
446 (0 << CC1200_PKT_CFG1_WHITE_DATA) |
447 (0 << CC1200_PKT_CFG1_PN9_SWAP_EN) |
448 (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) |
449 (CC1200_PKT_CFG1_CRC_CFG_DISABLED << CC1200_PKT_CFG1_CRC_CFG) |
450 (0 << CC1200_PKT_CFG1_APPEND_STATUS)),
451 CC1200_PREAMBLE_CFG1,
452 ((CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1200_PREAMBLE_CFG1_NUM_PREAMBLE) |
453 (CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1200_PREAMBLE_CFG1_PREAMBLE_WORD)),
454 CC1200_MDMCFG2, /* General Modem Parameter Configuration Reg. 2 */
455 ((0 << CC1200_MDMCFG2_ASK_SHAPE) |
456 (0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) |
457 (12 << CC1200_MDMCFG2_UPSAMPLER_P) |
458 (0 << CC1200_MDMCFG2_CFM_DATA_EN)),
462 * APRS deviation is 3kHz
464 * fdev = fosc >> 22 * (256 + dev_m) << dev_e dev_e != 0
465 * fdev = fosc >> 21 * dev_m dev_e == 0
467 * 40e6 / (2 ** 21) * 157 = 2995Hz
471 #define APRS_DEV_M 157
474 * For our APRS beacon, set the symbol rate to 9.6kBaud (8x oversampling for 1200 baud data rate)
476 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
477 * Rdata = -------------------------------------- * fosc
480 * DATARATE_M = 1013008
483 * Rdata = 9599.998593330383301
486 #define APRS_SYMBOL_RATE_E 6
487 #define APRS_SYMBOL_RATE_M 1013008
488 #define APRS_BUFFER_SIZE 64
490 static const uint16_t aprs_setup[] = {
491 CC1200_DEVIATION_M, APRS_DEV_M,
492 CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) |
493 (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) |
494 (APRS_DEV_E << CC1200_MODCFG_DEV_E_DEV_E)),
495 CC1200_SYMBOL_RATE2, ((APRS_SYMBOL_RATE_E << CC1200_SYMBOL_RATE2_DATARATE_E) |
496 (((APRS_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)),
497 CC1200_SYMBOL_RATE1, ((APRS_SYMBOL_RATE_M >> 8) & 0xff),
498 CC1200_SYMBOL_RATE0, ((APRS_SYMBOL_RATE_M >> 0) & 0xff),
499 CC1200_PKT_CFG2, /* Packet Configuration Reg. 2 */
500 ((0 << CC1200_PKT_CFG2_FG_MODE_EN) |
501 (CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) |
502 (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)),
503 CC1200_PKT_CFG1, /* Packet Configuration Reg. 1 */
504 ((0 << CC1200_PKT_CFG1_FEC_EN) |
505 (0 << CC1200_PKT_CFG1_WHITE_DATA) |
506 (0 << CC1200_PKT_CFG1_PN9_SWAP_EN) |
507 (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) |
508 (CC1200_PKT_CFG1_CRC_CFG_DISABLED << CC1200_PKT_CFG1_CRC_CFG) |
509 (0 << CC1200_PKT_CFG1_APPEND_STATUS)),
510 CC1200_PKT_CFG0, /* Packet Configuration Reg. 0 */
511 ((CC1200_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1200_PKT_CFG0_LENGTH_CONFIG) |
512 (0 << CC1200_PKT_CFG0_PKG_BIT_LEN) |
513 (0 << CC1200_PKT_CFG0_UART_MODE_EN) |
514 (0 << CC1200_PKT_CFG0_UART_SWAP_EN)),
515 CC1200_PREAMBLE_CFG1,
516 ((CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1200_PREAMBLE_CFG1_NUM_PREAMBLE) |
517 (CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1200_PREAMBLE_CFG1_PREAMBLE_WORD)),
518 CC1200_MDMCFG2, /* General Modem Parameter Configuration Reg. 2 */
519 ((CC1200_MDMCFG2_ASK_SHAPE_8 << CC1200_MDMCFG2_ASK_SHAPE) |
520 (CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) |
521 (CC1200_MDMCFG2_UPSAMPLER_P_8 << CC1200_MDMCFG2_UPSAMPLER_P) |
522 (0 << CC1200_MDMCFG2_CFM_DATA_EN)),
524 ((0 << CC1200_FIFO_CFG_CRC_AUTOFLUSH) |
525 (APRS_BUFFER_SIZE << CC1200_FIFO_CFG_FIFO_THR)),
529 * For Test mode, we want an unmodulated carrier. To do that, we
530 * set the deviation to zero and enable a preamble so that the radio
531 * turns on before we send any data
534 static const uint16_t test_setup[] = {
535 CC1200_DEVIATION_M, 0,
536 CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) |
537 (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) |
538 (0 << CC1200_MODCFG_DEV_E_DEV_E)),
539 CC1200_SYMBOL_RATE2, ((APRS_SYMBOL_RATE_E << CC1200_SYMBOL_RATE2_DATARATE_E) |
540 (((APRS_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)),
541 CC1200_SYMBOL_RATE1, ((APRS_SYMBOL_RATE_M >> 8) & 0xff),
542 CC1200_SYMBOL_RATE0, ((APRS_SYMBOL_RATE_M >> 0) & 0xff),
543 CC1200_PKT_CFG2, ((CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) |
544 (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)),
545 CC1200_PKT_CFG1, ((0 << CC1200_PKT_CFG1_WHITE_DATA) |
546 (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) |
547 (CC1200_PKT_CFG1_CRC_CFG_DISABLED << CC1200_PKT_CFG1_CRC_CFG) |
548 (0 << CC1200_PKT_CFG1_APPEND_STATUS)),
549 CC1200_PREAMBLE_CFG1, ((CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES << CC1200_PREAMBLE_CFG1_NUM_PREAMBLE) |
550 (CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1200_PREAMBLE_CFG1_PREAMBLE_WORD)),
553 #define AO_PKT_CFG0_INFINITE ((CC1200_PKT_CFG0_LENGTH_CONFIG_INFINITE << CC1200_PKT_CFG0_LENGTH_CONFIG) | \
554 (0 << CC1200_PKT_CFG0_PKG_BIT_LEN) | \
555 (0 << CC1200_PKT_CFG0_UART_MODE_EN) | \
556 (0 << CC1200_PKT_CFG0_UART_SWAP_EN))
558 #define AO_PKT_CFG0_FIXED ((CC1200_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1200_PKT_CFG0_LENGTH_CONFIG) | \
559 (0 << CC1200_PKT_CFG0_PKG_BIT_LEN) | \
560 (0 << CC1200_PKT_CFG0_UART_MODE_EN) | \
561 (0 << CC1200_PKT_CFG0_UART_SWAP_EN))
563 static uint16_t ao_radio_mode;
565 #define AO_RADIO_MODE_BITS_PACKET 1
566 #define AO_RADIO_MODE_BITS_TX_BUF 4
567 #define AO_RADIO_MODE_BITS_TX_FINISH 8
568 #define AO_RADIO_MODE_BITS_RX 16
569 #define AO_RADIO_MODE_BITS_RDF 32
570 #define AO_RADIO_MODE_BITS_APRS 64
571 #define AO_RADIO_MODE_BITS_TEST 128
572 #define AO_RADIO_MODE_BITS_INFINITE 256
573 #define AO_RADIO_MODE_BITS_FIXED 512
575 #define AO_RADIO_MODE_NONE 0
576 #define AO_RADIO_MODE_PACKET_TX (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_FINISH)
577 #define AO_RADIO_MODE_PACKET_RX (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_RX)
578 #define AO_RADIO_MODE_RDF (AO_RADIO_MODE_BITS_RDF | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_FINISH)
579 #define AO_RADIO_MODE_APRS_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF)
580 #define AO_RADIO_MODE_APRS_LAST_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_BUF)
581 #define AO_RADIO_MODE_APRS_FINISH (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_FINISH)
582 #define AO_RADIO_MODE_TEST (AO_RADIO_MODE_BITS_TEST | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF)
585 _ao_radio_set_regs(const uint16_t *regs, int nreg)
589 for (i = 0; i < nreg; i++) {
590 ao_radio_reg_write(regs[0], regs[1]);
595 #define ao_radio_set_regs(setup) _ao_radio_set_regs(setup, (sizeof (setup) / sizeof(setup[0])) >> 1)
598 ao_radio_set_mode(uint16_t new_mode)
602 if (new_mode == ao_radio_mode)
605 changes = new_mode & (~ao_radio_mode);
607 if (changes & AO_RADIO_MODE_BITS_PACKET) {
608 ao_radio_set_regs(packet_setup);
610 switch (ao_config.radio_rate) {
612 case AO_RADIO_RATE_38400:
613 ao_radio_set_regs(packet_setup_384);
615 case AO_RADIO_RATE_9600:
616 ao_radio_set_regs(packet_setup_96);
618 case AO_RADIO_RATE_2400:
619 ao_radio_set_regs(packet_setup_24);
624 if (changes & AO_RADIO_MODE_BITS_TX_BUF) {
625 ao_radio_reg_write(AO_CC1200_INT_GPIO_IOCFG, CC1200_IOCFG_GPIO_CFG_TXFIFO_THR);
626 ao_exti_set_mode(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN, AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH);
629 if (changes & AO_RADIO_MODE_BITS_TX_FINISH) {
630 ao_radio_reg_write(AO_CC1200_INT_GPIO_IOCFG, CC1200_IOCFG_GPIO_CFG_PKT_SYNC_RXTX);
631 ao_exti_set_mode(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN, AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH);
634 if (changes & AO_RADIO_MODE_BITS_RX) {
635 ao_radio_reg_write(AO_CC1200_INT_GPIO_IOCFG, CC1200_IOCFG_GPIO_CFG_MARC_MCU_WAKEUP);
636 ao_exti_set_mode(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN, AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_HIGH);
639 if (changes & AO_RADIO_MODE_BITS_RDF)
640 ao_radio_set_regs(rdf_setup);
642 if (changes & AO_RADIO_MODE_BITS_APRS)
643 ao_radio_set_regs(aprs_setup);
645 if (changes & AO_RADIO_MODE_BITS_TEST)
646 ao_radio_set_regs(test_setup);
648 if (changes & AO_RADIO_MODE_BITS_INFINITE)
649 ao_radio_reg_write(CC1200_PKT_CFG0, AO_PKT_CFG0_INFINITE);
651 if (changes & AO_RADIO_MODE_BITS_FIXED)
652 ao_radio_reg_write(CC1200_PKT_CFG0, AO_PKT_CFG0_FIXED);
654 ao_radio_mode = new_mode;
657 static const uint16_t radio_setup[] = {
658 #include "ao_cc1200_CC1200.h"
661 static uint8_t ao_radio_configured = 0;
666 ao_radio_strobe(CC1200_SRES);
668 ao_radio_set_regs(radio_setup);
676 ao_radio_configured = 1;
680 ao_radio_set_len(uint8_t len)
682 static uint8_t last_len;
684 if (len != last_len) {
685 ao_radio_reg_write(CC1200_PKT_LEN, len);
691 ao_radio_get(uint8_t len)
693 static uint32_t last_radio_setting;
694 static uint8_t last_radio_rate;
696 ao_mutex_get(&ao_radio_mutex);
698 if (!ao_radio_configured)
700 if (ao_config.radio_setting != last_radio_setting) {
701 ao_radio_reg_write(CC1200_FREQ2, ao_config.radio_setting >> 16);
702 ao_radio_reg_write(CC1200_FREQ1, ao_config.radio_setting >> 8);
703 ao_radio_reg_write(CC1200_FREQ0, ao_config.radio_setting);
704 last_radio_setting = ao_config.radio_setting;
705 ao_radio_strobe(CC1200_SCAL);
707 if (ao_config.radio_rate != last_radio_rate) {
708 ao_radio_mode &= ~AO_RADIO_MODE_BITS_PACKET;
709 last_radio_rate = ao_config.radio_rate;
711 ao_radio_set_len(len);
714 #define ao_radio_put() ao_mutex_put(&ao_radio_mutex)
716 static inline uint8_t
719 return (ao_radio_status() >> CC1200_STATUS_STATE) & CC1200_STATUS_STATE_MASK;
724 ao_radio_show_state(char *where)
726 printf("%s: state %d len %d rxbytes %d\n",
727 where, ao_radio_state(),
728 ao_radio_reg_read(CC1200_PKT_LEN),
729 ao_radio_reg_read(CC1200_NUM_RXBYTES));
732 #define ao_radio_show_state(where)
735 /* Wait for the radio to signal an interrupt
738 ao_radio_wait_isr(uint16_t timeout)
740 ao_arch_block_interrupts();
741 while (!ao_radio_wake && !ao_radio_abort)
742 if (ao_sleep_for(&ao_radio_wake, timeout))
744 ao_arch_release_interrupts();
748 ao_rdf_start(uint8_t len)
753 ao_radio_set_mode(AO_RADIO_MODE_RDF);
763 ao_radio_wait_isr(0);
772 ao_rdf_start(AO_RADIO_RDF_LEN);
774 ao_radio_fifo_write_fixed(ao_radio_rdf_value, AO_RADIO_RDF_LEN);
780 ao_radio_continuity(uint8_t c)
785 ao_rdf_start(AO_RADIO_CONT_TOTAL_LEN);
787 status = ao_radio_fifo_write_start();
788 for (i = 0; i < 3; i++) {
789 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN);
791 ao_radio_spi_send_fixed(ao_radio_rdf_value, AO_RADIO_CONT_TONE_LEN);
793 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_TONE_LEN);
795 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN);
796 status = ao_radio_fifo_write_stop(status);
802 ao_radio_rdf_abort(void)
805 ao_wakeup(&ao_radio_wake);
808 static uint8_t radio_on;
811 ao_radio_test_on(void)
815 ao_monitor_disable();
818 ao_packet_slave_stop();
824 ao_radio_set_mode(AO_RADIO_MODE_TEST);
825 ao_radio_strobe(CC1200_STX);
828 for (t = 0; t < 10; t++) {
829 printf ("status: %02x\n", ao_radio_status());
830 ao_delay(AO_MS_TO_TICKS(100));
839 ao_radio_test_off(void)
855 ao_radio_test_cmd(void)
859 if (ao_cmd_lex_c != '\n')
860 mode = ao_cmd_decimal();
865 printf ("Hit a character to stop..."); flush();
874 ao_radio_send(const void *d, uint8_t size)
877 ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX);
879 ao_radio_fifo_write(d, size);
885 ao_radio_send_aprs(ao_radio_fill_func fill)
887 uint8_t buf[APRS_BUFFER_SIZE];
896 while (!done && !ao_radio_abort) {
897 cnt = (*fill)(buf, sizeof(buf));
904 /* At the last buffer, set the total length */
906 ao_radio_set_len(total & 0xff);
908 /* Wait for some space in the fifo */
909 while (started && ao_radio_int_pin() != 0 && !ao_radio_abort) {
911 ao_exti_enable(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN);
912 ao_radio_wait_isr(AO_MS_TO_TICKS(1000));
918 ao_radio_set_mode(AO_RADIO_MODE_APRS_FINISH);
920 ao_radio_set_mode(AO_RADIO_MODE_APRS_BUF);
922 ao_radio_fifo_write(buf, cnt);
924 ao_radio_strobe(CC1200_STX);
928 /* Wait for the transmitter to go idle */
929 while (started && ao_radio_int_pin() != 0 && !ao_radio_abort) {
931 ao_exti_enable(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN);
932 ao_radio_wait_isr(AO_MS_TO_TICKS(1000));
941 ao_radio_marc_state(void)
943 return ao_radio_reg_read(CC1200_MARCSTATE);
947 ao_radio_modem_status1(void)
949 return ao_radio_reg_read(CC1200_MODEM_STATUS1);
953 ao_radio_modem_status0(void)
955 return ao_radio_reg_read(CC1200_MODEM_STATUS0);
958 struct ao_radio_state {
961 uint8_t marc_status1;
962 uint8_t marc_status0;
963 uint8_t modem_status1;
964 uint8_t modem_status0;
968 ao_radio_fill_state(char *where, struct ao_radio_state *s)
970 strcpy(s->where, where);
971 s->marc_state = ao_radio_marc_state();
972 s->marc_status1 = ao_radio_reg_read(CC1200_MARC_STATUS1);
973 s->marc_status0 = ao_radio_reg_read(CC1200_MARC_STATUS0);
974 s->modem_status1 = ao_radio_modem_status1();
975 s->modem_status0 = ao_radio_modem_status0();
979 ao_radio_dump_state(struct ao_radio_state *s)
981 printf ("%s: marc %2x marc1 %2x marc0 %2x modem1 %2x modem0 %2x\n",
982 s->where, s->marc_state, s->marc_status1, s->marc_status0, s->modem_status1, s->modem_status0);
987 ao_radio_recv(void *d, uint8_t size, uint8_t timeout)
992 ao_radio_get(size - 2);
993 ao_radio_set_mode(AO_RADIO_MODE_PACKET_RX);
997 while (!ao_radio_abort) {
998 ao_radio_wait_isr(timeout);
1000 uint8_t marc_status1 = ao_radio_reg_read(CC1200_MARC_STATUS1);
1002 /* Check the receiver status to see what happened
1004 switch (marc_status1) {
1005 case CC1200_MARC_STATUS1_RX_FINISHED:
1006 case CC1200_MARC_STATUS1_ADDRESS:
1007 case CC1200_MARC_STATUS1_CRC:
1008 /* Normal return, go fetch the bytes from the FIFO
1009 * and give them back to the caller
1013 case CC1200_MARC_STATUS1_RX_TIMEOUT:
1014 case CC1200_MARC_STATUS1_RX_TERMINATION:
1015 case CC1200_MARC_STATUS1_EWOR_SYNC_LOST:
1016 case CC1200_MARC_STATUS1_MAXIMUM_LENGTH:
1017 case CC1200_MARC_STATUS1_RX_FIFO_OVERFLOW:
1018 case CC1200_MARC_STATUS1_RX_FIFO_UNDERFLOW:
1019 /* Something weird happened; reset the radio and
1025 /* some other status; go wait for the radio to do something useful
1031 uint8_t modem_status1 = ao_radio_reg_read(CC1200_MODEM_STATUS1);
1033 /* Check to see if the packet header has been seen, in which case we'll
1034 * want to keep waiting for the rest of the packet to appear
1036 if (modem_status1 & (1 << CC1200_MODEM_STATUS1_SYNC_FOUND))
1040 /* Set a timeout based on the packet length so that we make sure to
1041 * wait long enough to receive the whole thing.
1043 * timeout = bits * FEC expansion / rate
1045 switch (ao_config.radio_rate) {
1047 case AO_RADIO_RATE_38400:
1048 timeout = AO_MS_TO_TICKS(size * (8 * 2 * 10) / 384) + 1;
1050 case AO_RADIO_RATE_9600:
1051 timeout = AO_MS_TO_TICKS(size * (8 * 2 * 10) / 96) + 1;
1053 case AO_RADIO_RATE_2400:
1054 timeout = AO_MS_TO_TICKS(size * (8 * 2 * 10) / 24) + 1;
1065 status = ao_radio_fifo_read(d, size);
1067 rssi = ((int8_t *) d)[size - 2];
1068 ao_radio_rssi = rssi;
1070 /* Bound it to the representable range */
1074 /* Write it back to the packet */
1075 ((int8_t *) d)[size-2] = AO_RADIO_FROM_RSSI(rssi);
1087 static char *cc1200_state_name[] = {
1088 [CC1200_STATUS_STATE_IDLE] = "IDLE",
1089 [CC1200_STATUS_STATE_RX] = "RX",
1090 [CC1200_STATUS_STATE_TX] = "TX",
1091 [CC1200_STATUS_STATE_FSTXON] = "FSTXON",
1092 [CC1200_STATUS_STATE_CALIBRATE] = "CALIBRATE",
1093 [CC1200_STATUS_STATE_SETTLING] = "SETTLING",
1094 [CC1200_STATUS_STATE_RX_FIFO_ERROR] = "RX_FIFO_ERROR",
1095 [CC1200_STATUS_STATE_TX_FIFO_ERROR] = "TX_FIFO_ERROR",
1098 struct ao_cc1200_reg {
1103 static const struct ao_cc1200_reg ao_cc1200_reg[] = {
1104 { .addr = CC1200_IOCFG3, .name = "IOCFG3" },
1105 { .addr = CC1200_IOCFG2, .name = "IOCFG2" },
1106 { .addr = CC1200_IOCFG1, .name = "IOCFG1" },
1107 { .addr = CC1200_IOCFG0, .name = "IOCFG0" },
1108 { .addr = CC1200_SYNC3, .name = "SYNC3" },
1109 { .addr = CC1200_SYNC2, .name = "SYNC2" },
1110 { .addr = CC1200_SYNC1, .name = "SYNC1" },
1111 { .addr = CC1200_SYNC0, .name = "SYNC0" },
1112 { .addr = CC1200_SYNC_CFG1, .name = "SYNC_CFG1" },
1113 { .addr = CC1200_SYNC_CFG0, .name = "SYNC_CFG0" },
1114 { .addr = CC1200_DEVIATION_M, .name = "DEVIATION_M" },
1115 { .addr = CC1200_MODCFG_DEV_E, .name = "MODCFG_DEV_E" },
1116 { .addr = CC1200_DCFILT_CFG, .name = "DCFILT_CFG" },
1117 { .addr = CC1200_PREAMBLE_CFG1, .name = "PREAMBLE_CFG1" },
1118 { .addr = CC1200_PREAMBLE_CFG0, .name = "PREAMBLE_CFG0" },
1119 { .addr = CC1200_IQIC, .name = "IQIC" },
1120 { .addr = CC1200_CHAN_BW, .name = "CHAN_BW" },
1121 { .addr = CC1200_MDMCFG2, .name = "MDMCFG2" },
1122 { .addr = CC1200_MDMCFG1, .name = "MDMCFG1" },
1123 { .addr = CC1200_MDMCFG0, .name = "MDMCFG0" },
1124 { .addr = CC1200_SYMBOL_RATE2, .name = "SYMBOL_RATE2" },
1125 { .addr = CC1200_SYMBOL_RATE1, .name = "SYMBOL_RATE1" },
1126 { .addr = CC1200_SYMBOL_RATE0, .name = "SYMBOL_RATE0" },
1127 { .addr = CC1200_AGC_REF, .name = "AGC_REF" },
1128 { .addr = CC1200_AGC_CS_THR, .name = "AGC_CS_THR" },
1129 { .addr = CC1200_AGC_GAIN_ADJUST, .name = "AGC_GAIN_ADJUST" },
1130 { .addr = CC1200_AGC_CFG3, .name = "AGC_CFG3" },
1131 { .addr = CC1200_AGC_CFG2, .name = "AGC_CFG2" },
1132 { .addr = CC1200_AGC_CFG1, .name = "AGC_CFG1" },
1133 { .addr = CC1200_AGC_CFG0, .name = "AGC_CFG0" },
1134 { .addr = CC1200_FIFO_CFG, .name = "FIFO_CFG" },
1135 { .addr = CC1200_DEV_ADDR, .name = "DEV_ADDR" },
1136 { .addr = CC1200_SETTLING_CFG, .name = "SETTLING_CFG" },
1137 { .addr = CC1200_FS_CFG, .name = "FS_CFG" },
1138 { .addr = CC1200_WOR_CFG1, .name = "WOR_CFG1" },
1139 { .addr = CC1200_WOR_CFG0, .name = "WOR_CFG0" },
1140 { .addr = CC1200_WOR_EVENT0_MSB, .name = "WOR_EVENT0_MSB" },
1141 { .addr = CC1200_WOR_EVENT0_LSB, .name = "WOR_EVENT0_LSB" },
1142 { .addr = CC1200_RXDCM_TIME, .name = "RXDCM_TIME" },
1143 { .addr = CC1200_PKT_CFG2, .name = "PKT_CFG2" },
1144 { .addr = CC1200_PKT_CFG1, .name = "PKT_CFG1" },
1145 { .addr = CC1200_PKT_CFG0, .name = "PKT_CFG0" },
1146 { .addr = CC1200_RFEND_CFG1, .name = "RFEND_CFG1" },
1147 { .addr = CC1200_RFEND_CFG0, .name = "RFEND_CFG0" },
1148 { .addr = CC1200_PA_CFG1, .name = "PA_CFG1" },
1149 { .addr = CC1200_PA_CFG0, .name = "PA_CFG0" },
1150 { .addr = CC1200_PKT_LEN, .name = "PKT_LEN" },
1151 { .addr = CC1200_IF_MIX_CFG, .name = "IF_MIX_CFG" },
1152 { .addr = CC1200_FREQOFF_CFG, .name = "FREQOFF_CFG" },
1153 { .addr = CC1200_TOC_CFG, .name = "TOC_CFG" },
1154 { .addr = CC1200_MARC_SPARE, .name = "MARC_SPARE" },
1155 { .addr = CC1200_ECG_CFG, .name = "ECG_CFG" },
1156 { .addr = CC1200_EXT_CTRL, .name = "EXT_CTRL" },
1157 { .addr = CC1200_RCCAL_FINE, .name = "RCCAL_FINE" },
1158 { .addr = CC1200_RCCAL_COARSE, .name = "RCCAL_COARSE" },
1159 { .addr = CC1200_RCCAL_OFFSET, .name = "RCCAL_OFFSET" },
1160 { .addr = CC1200_FREQOFF1, .name = "FREQOFF1" },
1161 { .addr = CC1200_FREQOFF0, .name = "FREQOFF0" },
1162 { .addr = CC1200_FREQ2, .name = "FREQ2" },
1163 { .addr = CC1200_FREQ1, .name = "FREQ1" },
1164 { .addr = CC1200_FREQ0, .name = "FREQ0" },
1165 { .addr = CC1200_IF_ADC2, .name = "IF_ADC2" },
1166 { .addr = CC1200_IF_ADC1, .name = "IF_ADC1" },
1167 { .addr = CC1200_IF_ADC0, .name = "IF_ADC0" },
1168 { .addr = CC1200_FS_DIG1, .name = "FS_DIG1" },
1169 { .addr = CC1200_FS_DIG0, .name = "FS_DIG0" },
1170 { .addr = CC1200_FS_CAL3, .name = "FS_CAL3" },
1171 { .addr = CC1200_FS_CAL2, .name = "FS_CAL2" },
1172 { .addr = CC1200_FS_CAL1, .name = "FS_CAL1" },
1173 { .addr = CC1200_FS_CAL0, .name = "FS_CAL0" },
1174 { .addr = CC1200_FS_CHP, .name = "FS_CHP" },
1175 { .addr = CC1200_FS_DIVTWO, .name = "FS_DIVTWO" },
1176 { .addr = CC1200_FS_DSM1, .name = "FS_DSM1" },
1177 { .addr = CC1200_FS_DSM0, .name = "FS_DSM0" },
1178 { .addr = CC1200_FS_DVC1, .name = "FS_DVC1" },
1179 { .addr = CC1200_FS_DVC0, .name = "FS_DVC0" },
1180 { .addr = CC1200_FS_LBI, .name = "FS_LBI" },
1181 { .addr = CC1200_FS_PFD, .name = "FS_PFD" },
1182 { .addr = CC1200_FS_PRE, .name = "FS_PRE" },
1183 { .addr = CC1200_FS_REG_DIV_CML, .name = "FS_REG_DIV_CML" },
1184 { .addr = CC1200_FS_SPARE, .name = "FS_SPARE" },
1185 { .addr = CC1200_FS_VCO4, .name = "FS_VCO4" },
1186 { .addr = CC1200_FS_VCO3, .name = "FS_VCO3" },
1187 { .addr = CC1200_FS_VCO2, .name = "FS_VCO2" },
1188 { .addr = CC1200_FS_VCO1, .name = "FS_VCO1" },
1189 { .addr = CC1200_FS_VCO0, .name = "FS_VCO0" },
1190 { .addr = CC1200_GBIAS6, .name = "GBIAS6" },
1191 { .addr = CC1200_GBIAS5, .name = "GBIAS5" },
1192 { .addr = CC1200_GBIAS4, .name = "GBIAS4" },
1193 { .addr = CC1200_GBIAS3, .name = "GBIAS3" },
1194 { .addr = CC1200_GBIAS2, .name = "GBIAS2" },
1195 { .addr = CC1200_GBIAS1, .name = "GBIAS1" },
1196 { .addr = CC1200_GBIAS0, .name = "GBIAS0" },
1197 { .addr = CC1200_IFAMP, .name = "IFAMP" },
1198 { .addr = CC1200_LNA, .name = "LNA" },
1199 { .addr = CC1200_RXMIX, .name = "RXMIX" },
1200 { .addr = CC1200_XOSC5, .name = "XOSC5" },
1201 { .addr = CC1200_XOSC4, .name = "XOSC4" },
1202 { .addr = CC1200_XOSC3, .name = "XOSC3" },
1203 { .addr = CC1200_XOSC2, .name = "XOSC2" },
1204 { .addr = CC1200_XOSC1, .name = "XOSC1" },
1205 { .addr = CC1200_XOSC0, .name = "XOSC0" },
1206 { .addr = CC1200_ANALOG_SPARE, .name = "ANALOG_SPARE" },
1207 { .addr = CC1200_PA_CFG3, .name = "PA_CFG3" },
1208 { .addr = CC1200_WOR_TIME1, .name = "WOR_TIME1" },
1209 { .addr = CC1200_WOR_TIME0, .name = "WOR_TIME0" },
1210 { .addr = CC1200_WOR_CAPTURE1, .name = "WOR_CAPTURE1" },
1211 { .addr = CC1200_WOR_CAPTURE0, .name = "WOR_CAPTURE0" },
1212 { .addr = CC1200_BIST, .name = "BIST" },
1213 { .addr = CC1200_DCFILTOFFSET_I1, .name = "DCFILTOFFSET_I1" },
1214 { .addr = CC1200_DCFILTOFFSET_I0, .name = "DCFILTOFFSET_I0" },
1215 { .addr = CC1200_DCFILTOFFSET_Q1, .name = "DCFILTOFFSET_Q1" },
1216 { .addr = CC1200_DCFILTOFFSET_Q0, .name = "DCFILTOFFSET_Q0" },
1217 { .addr = CC1200_IQIE_I1, .name = "IQIE_I1" },
1218 { .addr = CC1200_IQIE_I0, .name = "IQIE_I0" },
1219 { .addr = CC1200_IQIE_Q1, .name = "IQIE_Q1" },
1220 { .addr = CC1200_IQIE_Q0, .name = "IQIE_Q0" },
1221 { .addr = CC1200_RSSI1, .name = "RSSI1" },
1222 { .addr = CC1200_RSSI0, .name = "RSSI0" },
1223 { .addr = CC1200_MARCSTATE, .name = "MARCSTATE" },
1224 { .addr = CC1200_LQI_VAL, .name = "LQI_VAL" },
1225 { .addr = CC1200_PQT_SYNC_ERR, .name = "PQT_SYNC_ERR" },
1226 { .addr = CC1200_DEM_STATUS, .name = "DEM_STATUS" },
1227 { .addr = CC1200_FREQOFF_EST1, .name = "FREQOFF_EST1" },
1228 { .addr = CC1200_FREQOFF_EST0, .name = "FREQOFF_EST0" },
1229 { .addr = CC1200_AGC_GAIN3, .name = "AGC_GAIN3" },
1230 { .addr = CC1200_AGC_GAIN2, .name = "AGC_GAIN2" },
1231 { .addr = CC1200_AGC_GAIN1, .name = "AGC_GAIN1" },
1232 { .addr = CC1200_AGC_GAIN0, .name = "AGC_GAIN0" },
1233 { .addr = CC1200_SOFT_RX_DATA_OUT, .name = "SOFT_RX_DATA_OUT" },
1234 { .addr = CC1200_SOFT_TX_DATA_IN, .name = "SOFT_TX_DATA_IN" },
1235 { .addr = CC1200_ASK_SOFT_RX_DATA, .name = "ASK_SOFT_RX_DATA" },
1236 { .addr = CC1200_RNDGEN, .name = "RNDGEN" },
1237 { .addr = CC1200_MAGN2, .name = "MAGN2" },
1238 { .addr = CC1200_MAGN1, .name = "MAGN1" },
1239 { .addr = CC1200_MAGN0, .name = "MAGN0" },
1240 { .addr = CC1200_ANG1, .name = "ANG1" },
1241 { .addr = CC1200_ANG0, .name = "ANG0" },
1242 { .addr = CC1200_CHFILT_I2, .name = "CHFILT_I2" },
1243 { .addr = CC1200_CHFILT_I1, .name = "CHFILT_I1" },
1244 { .addr = CC1200_CHFILT_I0, .name = "CHFILT_I0" },
1245 { .addr = CC1200_CHFILT_Q2, .name = "CHFILT_Q2" },
1246 { .addr = CC1200_CHFILT_Q1, .name = "CHFILT_Q1" },
1247 { .addr = CC1200_CHFILT_Q0, .name = "CHFILT_Q0" },
1248 { .addr = CC1200_GPIO_STATUS, .name = "GPIO_STATUS" },
1249 { .addr = CC1200_FSCAL_CTRL, .name = "FSCAL_CTRL" },
1250 { .addr = CC1200_PHASE_ADJUST, .name = "PHASE_ADJUST" },
1251 { .addr = CC1200_PARTNUMBER, .name = "PARTNUMBER" },
1252 { .addr = CC1200_PARTVERSION, .name = "PARTVERSION" },
1253 { .addr = CC1200_SERIAL_STATUS, .name = "SERIAL_STATUS" },
1254 { .addr = CC1200_MODEM_STATUS1, .name = "MODEM_STATUS1" },
1255 { .addr = CC1200_MODEM_STATUS0, .name = "MODEM_STATUS0" },
1256 { .addr = CC1200_MARC_STATUS1, .name = "MARC_STATUS1" },
1257 { .addr = CC1200_MARC_STATUS0, .name = "MARC_STATUS0" },
1258 { .addr = CC1200_PA_IFAMP_TEST, .name = "PA_IFAMP_TEST" },
1259 { .addr = CC1200_FSRF_TEST, .name = "FSRF_TEST" },
1260 { .addr = CC1200_PRE_TEST, .name = "PRE_TEST" },
1261 { .addr = CC1200_PRE_OVR, .name = "PRE_OVR" },
1262 { .addr = CC1200_ADC_TEST, .name = "ADC_TEST" },
1263 { .addr = CC1200_DVC_TEST, .name = "DVC_TEST" },
1264 { .addr = CC1200_ATEST, .name = "ATEST" },
1265 { .addr = CC1200_ATEST_LVDS, .name = "ATEST_LVDS" },
1266 { .addr = CC1200_ATEST_MODE, .name = "ATEST_MODE" },
1267 { .addr = CC1200_XOSC_TEST1, .name = "XOSC_TEST1" },
1268 { .addr = CC1200_XOSC_TEST0, .name = "XOSC_TEST0" },
1269 { .addr = CC1200_RXFIRST, .name = "RXFIRST" },
1270 { .addr = CC1200_TXFIRST, .name = "TXFIRST" },
1271 { .addr = CC1200_RXLAST, .name = "RXLAST" },
1272 { .addr = CC1200_TXLAST, .name = "TXLAST" },
1273 { .addr = CC1200_NUM_TXBYTES, .name = "NUM_TXBYTES" },
1274 { .addr = CC1200_NUM_RXBYTES, .name = "NUM_RXBYTES" },
1275 { .addr = CC1200_FIFO_NUM_TXBYTES, .name = "FIFO_NUM_TXBYTES" },
1276 { .addr = CC1200_FIFO_NUM_RXBYTES, .name = "FIFO_NUM_RXBYTES" },
1279 #define AO_NUM_CC1200_REG (sizeof ao_cc1200_reg / sizeof ao_cc1200_reg[0])
1282 ao_radio_get_marc_status(void)
1284 return ao_radio_reg_read(CC1200_MARC_STATUS1);
1287 static void ao_radio_show(void) {
1291 ao_mutex_get(&ao_radio_mutex);
1292 status = ao_radio_status();
1293 printf ("Status: %02x\n", status);
1294 printf ("CHIP_RDY: %d\n", (status >> CC1200_STATUS_CHIP_RDY) & 1);
1295 printf ("STATE: %s\n", cc1200_state_name[(status >> CC1200_STATUS_STATE) & CC1200_STATUS_STATE_MASK]);
1296 printf ("MARC: %02x\n", ao_radio_get_marc_status());
1298 for (i = 0; i < AO_NUM_CC1200_REG; i++)
1299 printf ("\t%02x %-20.20s\n", ao_radio_reg_read(ao_cc1200_reg[i].addr), ao_cc1200_reg[i].name);
1304 static void ao_radio_beep(void) {
1308 static void ao_radio_packet(void) {
1309 static const uint8_t packet[] = {
1311 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1312 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1313 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1314 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1320 ao_radio_send(packet, sizeof (packet));
1324 ao_radio_test_recv(void)
1326 static uint8_t bytes[34];
1329 if (ao_radio_recv(bytes, 34, 0)) {
1330 if (bytes[33] & 0x80)
1334 printf (" RSSI %d", AO_RSSI_FROM_RADIO(bytes[32]));
1335 for (b = 0; b < 32; b++)
1336 printf (" %02x", bytes[b]);
1338 printf (" RSSI %02x LQI %02x", bytes[32], bytes[33]);
1344 #include <ao_aprs.h>
1349 #if PACKET_HAS_SLAVE
1350 ao_packet_slave_stop();
1357 #if CC1200_LOW_LEVEL_DEBUG
1359 ao_radio_strobe_test(void)
1364 addr = ao_cmd_hex();
1365 if (ao_cmd_status != ao_cmd_success)
1367 r = ao_radio_strobe(addr);
1368 printf ("Strobe %02x -> %02x (rdy %d state %d)\n",
1376 ao_radio_write_test(void)
1381 addr = ao_cmd_hex();
1382 if (ao_cmd_status != ao_cmd_success)
1384 data = ao_cmd_hex();
1385 if (ao_cmd_status != ao_cmd_success)
1387 printf ("Write %04x = %02x\n", addr, data);
1388 ao_radio_reg_write(addr, data);
1392 ao_radio_read_test(void)
1397 addr = ao_cmd_hex();
1398 if (ao_cmd_status != ao_cmd_success)
1400 data = ao_radio_reg_read(addr);
1401 printf ("Read %04x = %02x\n", addr, data);
1405 static const struct ao_cmds ao_radio_cmds[] = {
1406 { ao_radio_test_cmd, "C <1 start, 0 stop, none both>\0Radio carrier test" },
1409 { ao_radio_aprs, "G\0Send APRS packet" },
1411 { ao_radio_show, "R\0Show CC1200 status" },
1412 { ao_radio_beep, "b\0Emit an RDF beacon" },
1413 { ao_radio_packet, "p\0Send a test packet" },
1414 { ao_radio_test_recv, "q\0Recv a test packet" },
1416 #if CC1200_LOW_LEVEL_DEBUG
1417 { ao_radio_strobe_test, "A <value>\0Strobe radio" },
1418 { ao_radio_write_test, "W <addr> <value>\0Write radio reg" },
1419 { ao_radio_read_test, "B <addr>\0Read radio reg" },
1427 ao_radio_configured = 0;
1428 ao_spi_init_cs (AO_CC1200_SPI_CS_PORT, (1 << AO_CC1200_SPI_CS_PIN));
1431 AO_CC1200_SPI_CS_PORT->bsrr = ((uint32_t) (1 << AO_CC1200_SPI_CS_PIN));
1432 for (i = 0; i < 10000; i++) {
1433 if ((SPI_2_PORT->idr & (1 << SPI_2_MISO_PIN)) == 0)
1436 AO_CC1200_SPI_CS_PORT->bsrr = (1 << AO_CC1200_SPI_CS_PIN);
1438 ao_panic(AO_PANIC_SELF_TEST_CC1200);
1441 /* Enable the EXTI interrupt for the appropriate pin */
1442 ao_enable_port(AO_CC1200_INT_PORT);
1443 ao_exti_setup(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN,
1444 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH,
1447 ao_cmd_register(&ao_radio_cmds[0]);