2 * Copyright © 2012 Keith Packard <keithp@keithp.com>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
19 #include <ao_cc1200.h>
22 #include <ao_packet.h>
24 static uint8_t ao_radio_mutex;
26 static uint8_t ao_radio_wake; /* radio ready. Also used as sleep address */
27 static uint8_t ao_radio_abort; /* radio operation should abort */
29 int8_t ao_radio_rssi; /* Last received RSSI value */
31 #define CC1200_DEBUG 0
32 #define CC1200_LOW_LEVEL_DEBUG 0
33 #define CC1200_TRACE 0
34 #define CC1200_APRS_TRACE 0
36 extern const uint32_t ao_radio_cal;
40 #define ao_radio_select() ao_spi_get_mask(AO_CC1200_SPI_CS_PORT,(1 << AO_CC1200_SPI_CS_PIN),AO_CC1200_SPI_BUS,AO_SPI_SPEED_125kHz)
41 #define ao_radio_deselect() ao_spi_put_mask(AO_CC1200_SPI_CS_PORT,(1 << AO_CC1200_SPI_CS_PIN),AO_CC1200_SPI_BUS)
42 #define ao_radio_spi_send(d,l) ao_spi_send((d), (l), AO_CC1200_SPI_BUS)
43 #define ao_radio_spi_send_fixed(d,l) ao_spi_send_fixed((d), (l), AO_CC1200_SPI_BUS)
44 #define ao_radio_spi_recv(d,l) ao_spi_recv((d), (l), AO_CC1200_SPI_BUS)
45 #define ao_radio_duplex(o,i,l) ao_spi_duplex((o), (i), (l), AO_CC1200_SPI_BUS)
48 ao_radio_reg_read(uint16_t addr)
54 printf("\t\tao_radio_reg_read (%04x): ", addr); flush();
56 if (CC1200_IS_EXTENDED(addr)) {
57 data[0] = ((1 << CC1200_READ) |
63 data[0] = ((1 << CC1200_READ) |
69 ao_radio_spi_send(data, d);
70 ao_radio_spi_recv(data, 1);
73 printf (" %02x\n", data[0]);
79 ao_radio_reg_write(uint16_t addr, uint8_t value)
85 printf("\t\tao_radio_reg_write (%04x): %02x\n", addr, value);
87 if (CC1200_IS_EXTENDED(addr)) {
88 data[0] = ((0 << CC1200_READ) |
94 data[0] = ((0 << CC1200_READ) |
101 ao_radio_spi_send(data, d+1);
104 (void) ao_radio_reg_read(addr);
109 ao_radio_strobe(uint8_t addr)
114 printf("\t\tao_radio_strobe (%02x): ", addr); flush();
117 ao_radio_duplex(&addr, &in, 1);
120 printf("%02x\n", in); flush();
126 ao_radio_fifo_read(uint8_t *data, uint8_t len)
128 uint8_t addr = ((1 << CC1200_READ) |
129 (1 << CC1200_BURST) |
134 ao_radio_duplex(&addr, &status, 1);
135 ao_radio_spi_recv(data, len);
141 ao_radio_fifo_write_start(void)
143 uint8_t addr = ((0 << CC1200_READ) |
144 (1 << CC1200_BURST) |
149 ao_radio_duplex(&addr, &status, 1);
153 static inline uint8_t ao_radio_fifo_write_stop(uint8_t status) {
159 ao_radio_fifo_write(const uint8_t *data, uint8_t len)
161 uint8_t status = ao_radio_fifo_write_start();
162 ao_radio_spi_send(data, len);
163 return ao_radio_fifo_write_stop(status);
167 ao_radio_fifo_write_fixed(uint8_t data, uint8_t len)
169 uint8_t status = ao_radio_fifo_write_start();
170 ao_radio_spi_send_fixed(data, len);
171 return ao_radio_fifo_write_stop(status);
175 ao_radio_tx_fifo_space(void)
177 return CC1200_FIFO_SIZE - ao_radio_reg_read(CC1200_NUM_TXBYTES);
181 ao_radio_status(void)
183 return ao_radio_strobe (CC1200_SNOP);
187 ao_radio_recv_abort(void)
190 ao_wakeup(&ao_radio_wake);
193 #define ao_radio_rdf_value 0x55
198 ao_exti_disable(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN);
200 ao_wakeup(&ao_radio_wake);
204 ao_radio_start_tx(void)
206 ao_exti_enable(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN);
207 ao_radio_strobe(CC1200_STX);
211 ao_radio_start_rx(void)
213 ao_exti_enable(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN);
214 ao_radio_strobe(CC1200_SRX);
221 uint8_t state = (ao_radio_strobe(CC1200_SIDLE) >> CC1200_STATUS_STATE) & CC1200_STATUS_STATE_MASK;
222 if (state == CC1200_STATUS_STATE_IDLE) {
223 ao_radio_strobe(CC1200_SFTX);
224 ao_radio_strobe(CC1200_SFRX);
227 if (state == CC1200_STATUS_STATE_TX_FIFO_ERROR)
228 ao_radio_strobe(CC1200_SFTX);
229 if (state == CC1200_STATUS_STATE_RX_FIFO_ERROR)
230 ao_radio_strobe(CC1200_SFRX);
232 /* Flush any pending TX bytes */
233 ao_radio_strobe(CC1200_SFTX);
239 * fdev = fosc >> 22 * (256 + dev_m) << dev_e
241 * Deviation for 38400 baud should be 20.5kHz:
243 * 40e6 / (2 ** 22) * (256 + 13) * (2 ** 3) = 20523Hz
245 * Deviation for 9600 baud should be 5.125kHz:
247 * 40e6 / (2 ** 22) * (256 + 13) * (2 ** 1) = 5131Hz
249 * Deviation for 2400 baud should be 1.28125kHz, but cc1111 and
250 * cc115l can't do that, so we'll use 1.5kHz instead:
252 * 40e6 / (2 ** 21) * (79) = 1506Hz
255 #define PACKET_DEV_M_384 13
256 #define PACKET_DEV_E_384 3
258 #define PACKET_DEV_M_96 13
259 #define PACKET_DEV_E_96 1
261 #define PACKET_DEV_M_24 79
262 #define PACKET_DEV_E_24 0
265 * For our packet data
267 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
268 * Rdata = -------------------------------------- * fosc
271 * Given the bit period of the baseband, T, the bandwidth of the
272 * baseband signal is B = 1/(2T). The overall bandwidth of the
273 * modulated signal is then Channel bandwidth = 2Δf + 2B.
275 * 38400 -- 2 * 20500 + 38400 = 79.4 kHz
276 * 9600 -- 2 * 5.125 + 9600 = 19.9 kHz
277 * 2400 -- 2 * 1.5 + 2400 = 5.4 khz
279 * Symbol rate 38400 Baud:
281 * DATARATE_M = 1013008
285 * Symbol rate 9600 Baud:
287 * DATARATE_M = 1013008
289 * CHANBW = 26.042 (round to 19.8)
291 * Symbol rate 2400 Baud:
293 * DATARATE_M = 1013008
295 * CHANBW = 5.0 (round to 9.5)
298 #define PACKET_SYMBOL_RATE_M 1013008
300 #define PACKET_SYMBOL_RATE_E_384 8
303 #define PACKET_CHAN_BW_384 ((CC1200_CHAN_BW_ADC_CIC_DECFACT_12 << CC1200_CHAN_BW_ADC_CIC_DECFACT) | \
304 (16 << CC1200_CHAN_BW_BB_CIC_DECFACT))
306 #define PACKET_SYMBOL_RATE_E_96 6
308 #define PACKET_CHAN_BW_96 ((CC1200_CHAN_BW_ADC_CIC_DECFACT_48 << CC1200_CHAN_BW_ADC_CIC_DECFACT) | \
309 (16 << CC1200_CHAN_BW_BB_CIC_DECFACT))
311 #define PACKET_SYMBOL_RATE_E_24 4
313 #define PACKET_CHAN_BW_24 ((CC1200_CHAN_BW_ADC_CIC_DECFACT_48 << CC1200_CHAN_BW_ADC_CIC_DECFACT) | \
314 (44 << CC1200_CHAN_BW_BB_CIC_DECFACT))
316 static const uint16_t packet_setup[] = {
317 CC1200_SYMBOL_RATE1, ((PACKET_SYMBOL_RATE_M >> 8) & 0xff),
318 CC1200_SYMBOL_RATE0, ((PACKET_SYMBOL_RATE_M >> 0) & 0xff),
319 CC1200_PKT_CFG2, /* Packet Configuration Reg. 2 */
320 ((0 << CC1200_PKT_CFG2_FG_MODE_EN) |
321 (CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) |
322 (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)),
323 CC1200_PKT_CFG1, /* Packet Configuration Reg. 1 */
324 ((1 << CC1200_PKT_CFG1_FEC_EN) |
325 (1 << CC1200_PKT_CFG1_WHITE_DATA) |
326 (0 << CC1200_PKT_CFG1_PN9_SWAP_EN) |
327 (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) |
328 (CC1200_PKT_CFG1_CRC_CFG_CRC16_INIT_ONES << CC1200_PKT_CFG1_CRC_CFG) |
329 (1 << CC1200_PKT_CFG1_APPEND_STATUS)),
330 CC1200_PREAMBLE_CFG1, ((CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES << CC1200_PREAMBLE_CFG1_NUM_PREAMBLE) |
331 (CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1200_PREAMBLE_CFG1_PREAMBLE_WORD)),
334 static const uint16_t packet_setup_384[] = {
335 CC1200_DEVIATION_M, PACKET_DEV_M_384,
336 CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) |
337 (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) |
338 (PACKET_DEV_E_384 << CC1200_MODCFG_DEV_E_DEV_E)),
339 CC1200_SYMBOL_RATE2, ((PACKET_SYMBOL_RATE_E_384 << CC1200_SYMBOL_RATE2_DATARATE_E) |
340 (((PACKET_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)),
341 CC1200_CHAN_BW, PACKET_CHAN_BW_384,
342 CC1200_MDMCFG2, /* General Modem Parameter Configuration Reg. 2 */
343 ((CC1200_MDMCFG2_ASK_SHAPE_8 << CC1200_MDMCFG2_ASK_SHAPE) |
344 (CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) |
345 (CC1200_MDMCFG2_UPSAMPLER_P_8 << CC1200_MDMCFG2_UPSAMPLER_P) |
346 (0 << CC1200_MDMCFG2_CFM_DATA_EN)),
349 static const uint16_t packet_setup_96[] = {
350 CC1200_DEVIATION_M, PACKET_DEV_M_96,
351 CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) |
352 (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) |
353 (PACKET_DEV_E_96 << CC1200_MODCFG_DEV_E_DEV_E)),
354 CC1200_SYMBOL_RATE2, ((PACKET_SYMBOL_RATE_E_96 << CC1200_SYMBOL_RATE2_DATARATE_E) |
355 (((PACKET_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)),
356 CC1200_CHAN_BW, PACKET_CHAN_BW_96,
357 CC1200_MDMCFG2, /* General Modem Parameter Configuration Reg. 2 */
358 ((CC1200_MDMCFG2_ASK_SHAPE_8 << CC1200_MDMCFG2_ASK_SHAPE) |
359 (CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) |
360 (CC1200_MDMCFG2_UPSAMPLER_P_32 << CC1200_MDMCFG2_UPSAMPLER_P) |
361 (0 << CC1200_MDMCFG2_CFM_DATA_EN)),
364 static const uint16_t packet_setup_24[] = {
365 CC1200_DEVIATION_M, PACKET_DEV_M_24,
366 CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) |
367 (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) |
368 (PACKET_DEV_E_24 << CC1200_MODCFG_DEV_E_DEV_E)),
369 CC1200_SYMBOL_RATE2, ((PACKET_SYMBOL_RATE_E_24 << CC1200_SYMBOL_RATE2_DATARATE_E) |
370 (((PACKET_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)),
371 CC1200_CHAN_BW, PACKET_CHAN_BW_24,
372 CC1200_MDMCFG2, /* General Modem Parameter Configuration Reg. 2 */
373 ((CC1200_MDMCFG2_ASK_SHAPE_8 << CC1200_MDMCFG2_ASK_SHAPE) |
374 (CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) |
375 (CC1200_MDMCFG2_UPSAMPLER_P_64 << CC1200_MDMCFG2_UPSAMPLER_P) |
376 (0 << CC1200_MDMCFG2_CFM_DATA_EN)),
380 * RDF deviation is 3kHz
382 * fdev = fosc >> 22 * (256 + dev_m) << dev_e dev_e != 0
383 * fdev = fosc >> 21 * dev_m dev_e == 0
385 * 40e6 / (2 ** 21) * 157 = 2995Hz
389 #define RDF_DEV_M 157
392 * For our RDF beacon, set the symbol rate to 2kBaud (for a 1kHz tone)
394 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
395 * Rdata = -------------------------------------- * fosc
398 * DATARATE_M = 669411
401 * To make the tone last for 200ms, we need 2000 * .2 = 400 bits or 50 bytes
403 #define RDF_SYMBOL_RATE_E 4
404 #define RDF_SYMBOL_RATE_M 669411
405 #define RDF_PACKET_LEN 50
407 static const uint16_t rdf_setup[] = {
408 CC1200_DEVIATION_M, RDF_DEV_M,
409 CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) |
410 (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) |
411 (RDF_DEV_E << CC1200_MODCFG_DEV_E_DEV_E)),
412 CC1200_SYMBOL_RATE2, ((RDF_SYMBOL_RATE_E << CC1200_SYMBOL_RATE2_DATARATE_E) |
413 (((RDF_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)),
414 CC1200_SYMBOL_RATE1, ((RDF_SYMBOL_RATE_M >> 8) & 0xff),
415 CC1200_SYMBOL_RATE0, ((RDF_SYMBOL_RATE_M >> 0) & 0xff),
416 CC1200_PKT_CFG2, /* Packet Configuration Reg. 2 */
417 ((0 << CC1200_PKT_CFG2_FG_MODE_EN) |
418 (CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) |
419 (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)),
420 CC1200_PKT_CFG1, /* Packet Configuration Reg. 1 */
421 ((0 << CC1200_PKT_CFG1_FEC_EN) |
422 (0 << CC1200_PKT_CFG1_WHITE_DATA) |
423 (0 << CC1200_PKT_CFG1_PN9_SWAP_EN) |
424 (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) |
425 (CC1200_PKT_CFG1_CRC_CFG_DISABLED << CC1200_PKT_CFG1_CRC_CFG) |
426 (0 << CC1200_PKT_CFG1_APPEND_STATUS)),
427 CC1200_PREAMBLE_CFG1,
428 ((CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1200_PREAMBLE_CFG1_NUM_PREAMBLE) |
429 (CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1200_PREAMBLE_CFG1_PREAMBLE_WORD)),
430 CC1200_MDMCFG2, /* General Modem Parameter Configuration Reg. 2 */
431 ((0 << CC1200_MDMCFG2_ASK_SHAPE) |
432 (0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) |
433 (12 << CC1200_MDMCFG2_UPSAMPLER_P) |
434 (0 << CC1200_MDMCFG2_CFM_DATA_EN)),
438 * APRS deviation is 3kHz
440 * fdev = fosc >> 22 * (256 + dev_m) << dev_e dev_e != 0
441 * fdev = fosc >> 21 * dev_m dev_e == 0
443 * 40e6 / (2 ** 21) * 157 = 2995Hz
447 #define APRS_DEV_M 157
450 * For our APRS beacon, set the symbol rate to 9.6kBaud (8x oversampling for 1200 baud data rate)
452 * (2**20 + DATARATE_M) * 2 ** DATARATE_E
453 * Rdata = -------------------------------------- * fosc
456 * DATARATE_M = 1013008
459 * Rdata = 9599.998593330383301
462 #define APRS_SYMBOL_RATE_E 6
463 #define APRS_SYMBOL_RATE_M 1013008
465 static const uint16_t aprs_setup[] = {
466 CC1200_DEVIATION_M, APRS_DEV_M,
467 CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) |
468 (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) |
469 (APRS_DEV_E << CC1200_MODCFG_DEV_E_DEV_E)),
470 CC1200_SYMBOL_RATE2, ((APRS_SYMBOL_RATE_E << CC1200_SYMBOL_RATE2_DATARATE_E) |
471 (((APRS_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)),
472 CC1200_SYMBOL_RATE1, ((APRS_SYMBOL_RATE_M >> 8) & 0xff),
473 CC1200_SYMBOL_RATE0, ((APRS_SYMBOL_RATE_M >> 0) & 0xff),
474 CC1200_PKT_CFG2, /* Packet Configuration Reg. 2 */
475 ((0 << CC1200_PKT_CFG2_FG_MODE_EN) |
476 (CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) |
477 (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)),
478 CC1200_PKT_CFG1, /* Packet Configuration Reg. 1 */
479 ((0 << CC1200_PKT_CFG1_FEC_EN) |
480 (0 << CC1200_PKT_CFG1_WHITE_DATA) |
481 (0 << CC1200_PKT_CFG1_PN9_SWAP_EN) |
482 (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) |
483 (CC1200_PKT_CFG1_CRC_CFG_DISABLED << CC1200_PKT_CFG1_CRC_CFG) |
484 (0 << CC1200_PKT_CFG1_APPEND_STATUS)),
485 CC1200_PKT_CFG0, /* Packet Configuration Reg. 0 */
486 ((CC1200_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1200_PKT_CFG0_LENGTH_CONFIG) |
487 (0 << CC1200_PKT_CFG0_PKG_BIT_LEN) |
488 (0 << CC1200_PKT_CFG0_UART_MODE_EN) |
489 (0 << CC1200_PKT_CFG0_UART_SWAP_EN)),
490 CC1200_PREAMBLE_CFG1,
491 ((CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1200_PREAMBLE_CFG1_NUM_PREAMBLE) |
492 (CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1200_PREAMBLE_CFG1_PREAMBLE_WORD)),
493 CC1200_MDMCFG2, /* General Modem Parameter Configuration Reg. 2 */
494 ((CC1200_MDMCFG2_ASK_SHAPE_8 << CC1200_MDMCFG2_ASK_SHAPE) |
495 (CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) |
496 (CC1200_MDMCFG2_UPSAMPLER_P_8 << CC1200_MDMCFG2_UPSAMPLER_P) |
497 (0 << CC1200_MDMCFG2_CFM_DATA_EN)),
501 * For Test mode, we want an unmodulated carrier. To do that, we
502 * set the deviation to zero and enable a preamble so that the radio
503 * turns on before we send any data
506 static const uint16_t test_setup[] = {
507 CC1200_DEVIATION_M, 0,
508 CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) |
509 (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) |
510 (0 << CC1200_MODCFG_DEV_E_DEV_E)),
511 CC1200_SYMBOL_RATE2, ((APRS_SYMBOL_RATE_E << CC1200_SYMBOL_RATE2_DATARATE_E) |
512 (((APRS_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)),
513 CC1200_SYMBOL_RATE1, ((APRS_SYMBOL_RATE_M >> 8) & 0xff),
514 CC1200_SYMBOL_RATE0, ((APRS_SYMBOL_RATE_M >> 0) & 0xff),
515 CC1200_PKT_CFG2, ((CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) |
516 (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)),
517 CC1200_PKT_CFG1, ((0 << CC1200_PKT_CFG1_WHITE_DATA) |
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_PREAMBLE_CFG1, ((CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES << CC1200_PREAMBLE_CFG1_NUM_PREAMBLE) |
522 (CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1200_PREAMBLE_CFG1_PREAMBLE_WORD)),
525 #define AO_PKT_CFG0_INFINITE ((CC1200_PKT_CFG0_LENGTH_CONFIG_INFINITE << CC1200_PKT_CFG0_LENGTH_CONFIG) | \
526 (0 << CC1200_PKT_CFG0_PKG_BIT_LEN) | \
527 (0 << CC1200_PKT_CFG0_UART_MODE_EN) | \
528 (0 << CC1200_PKT_CFG0_UART_SWAP_EN))
530 #define AO_PKT_CFG0_FIXED ((CC1200_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1200_PKT_CFG0_LENGTH_CONFIG) | \
531 (0 << CC1200_PKT_CFG0_PKG_BIT_LEN) | \
532 (0 << CC1200_PKT_CFG0_UART_MODE_EN) | \
533 (0 << CC1200_PKT_CFG0_UART_SWAP_EN))
535 static uint16_t ao_radio_mode;
537 #define AO_RADIO_MODE_BITS_PACKET 1
538 #define AO_RADIO_MODE_BITS_TX_BUF 4
539 #define AO_RADIO_MODE_BITS_TX_FINISH 8
540 #define AO_RADIO_MODE_BITS_RX 16
541 #define AO_RADIO_MODE_BITS_RDF 32
542 #define AO_RADIO_MODE_BITS_APRS 64
543 #define AO_RADIO_MODE_BITS_TEST 128
544 #define AO_RADIO_MODE_BITS_INFINITE 256
545 #define AO_RADIO_MODE_BITS_FIXED 512
547 #define AO_RADIO_MODE_NONE 0
548 #define AO_RADIO_MODE_PACKET_TX (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_FINISH)
549 #define AO_RADIO_MODE_PACKET_RX (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_RX)
550 #define AO_RADIO_MODE_RDF (AO_RADIO_MODE_BITS_RDF | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_FINISH)
551 #define AO_RADIO_MODE_APRS_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF)
552 #define AO_RADIO_MODE_APRS_LAST_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_BUF)
553 #define AO_RADIO_MODE_APRS_FINISH (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_FINISH)
554 #define AO_RADIO_MODE_TEST (AO_RADIO_MODE_BITS_TEST | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF)
557 _ao_radio_set_regs(const uint16_t *regs, int nreg)
561 for (i = 0; i < nreg; i++) {
562 ao_radio_reg_write(regs[0], regs[1]);
567 #define ao_radio_set_regs(setup) _ao_radio_set_regs(setup, (sizeof (setup) / sizeof(setup[0])) >> 1)
570 ao_radio_set_mode(uint16_t new_mode)
574 if (new_mode == ao_radio_mode)
577 changes = new_mode & (~ao_radio_mode);
579 if (changes & AO_RADIO_MODE_BITS_PACKET) {
580 ao_radio_set_regs(packet_setup);
582 switch (ao_config.radio_rate) {
584 case AO_RADIO_RATE_38400:
585 ao_radio_set_regs(packet_setup_384);
587 case AO_RADIO_RATE_9600:
588 ao_radio_set_regs(packet_setup_96);
590 case AO_RADIO_RATE_2400:
591 ao_radio_set_regs(packet_setup_24);
596 if (changes & AO_RADIO_MODE_BITS_TX_BUF)
597 ao_radio_reg_write(AO_CC1200_INT_GPIO_IOCFG, CC1200_IOCFG_GPIO_CFG_TXFIFO_THR);
599 if (changes & AO_RADIO_MODE_BITS_TX_FINISH)
600 ao_radio_reg_write(AO_CC1200_INT_GPIO_IOCFG, CC1200_IOCFG_GPIO_CFG_PKT_SYNC_RXTX);
602 if (changes & AO_RADIO_MODE_BITS_RX)
603 ao_radio_reg_write(AO_CC1200_INT_GPIO_IOCFG, CC1200_IOCFG_GPIO_CFG_PKT_SYNC_RXTX);
605 if (changes & AO_RADIO_MODE_BITS_RDF)
606 ao_radio_set_regs(rdf_setup);
608 if (changes & AO_RADIO_MODE_BITS_APRS)
609 ao_radio_set_regs(aprs_setup);
611 if (changes & AO_RADIO_MODE_BITS_TEST)
612 ao_radio_set_regs(test_setup);
614 if (changes & AO_RADIO_MODE_BITS_INFINITE)
615 ao_radio_reg_write(CC1200_PKT_CFG0, AO_PKT_CFG0_INFINITE);
617 if (changes & AO_RADIO_MODE_BITS_FIXED)
618 ao_radio_reg_write(CC1200_PKT_CFG0, AO_PKT_CFG0_FIXED);
620 ao_radio_mode = new_mode;
623 static const uint16_t radio_setup[] = {
624 #include "ao_cc1200_CC1200.h"
627 static uint8_t ao_radio_configured = 0;
632 ao_radio_strobe(CC1200_SRES);
634 ao_radio_set_regs(radio_setup);
640 ao_radio_configured = 1;
644 ao_radio_set_len(uint8_t len)
646 static uint8_t last_len;
648 if (len != last_len) {
649 ao_radio_reg_write(CC1200_PKT_LEN, len);
655 ao_radio_get(uint8_t len)
657 static uint32_t last_radio_setting;
658 static uint8_t last_radio_rate;
660 ao_mutex_get(&ao_radio_mutex);
662 if (!ao_radio_configured)
664 if (ao_config.radio_setting != last_radio_setting) {
665 ao_radio_reg_write(CC1200_FREQ2, ao_config.radio_setting >> 16);
666 ao_radio_reg_write(CC1200_FREQ1, ao_config.radio_setting >> 8);
667 ao_radio_reg_write(CC1200_FREQ0, ao_config.radio_setting);
668 last_radio_setting = ao_config.radio_setting;
670 if (ao_config.radio_rate != last_radio_rate) {
671 ao_radio_mode &= ~AO_RADIO_MODE_BITS_PACKET;
672 last_radio_rate = ao_config.radio_rate;
674 ao_radio_set_len(len);
677 #define ao_radio_put() ao_mutex_put(&ao_radio_mutex)
679 static inline uint8_t
682 return (ao_radio_status() >> CC1200_STATUS_STATE) & CC1200_STATUS_STATE_MASK;
687 ao_radio_show_state(char *where)
689 printf("%s: state %d len %d rxbytes %d\n",
690 where, ao_radio_state(),
691 ao_radio_reg_read(CC1200_PKT_LEN),
692 ao_radio_reg_read(CC1200_NUM_RXBYTES));
695 #define ao_radio_show_state(where)
698 /* Wait for the radio to signal an interrupt
701 ao_radio_wait_isr(uint16_t timeout)
705 state = ao_radio_state();
707 case CC1200_STATUS_STATE_IDLE:
708 case CC1200_STATUS_STATE_RX_FIFO_ERROR:
709 case CC1200_STATUS_STATE_TX_FIFO_ERROR:
710 #if CC1200_LOW_LEVEL_DEBUG
711 printf("before wait, state %d\n", state); flush();
720 ao_arch_block_interrupts();
721 while (!ao_radio_wake && !ao_radio_abort)
722 if (ao_sleep(&ao_radio_wake))
724 ao_arch_release_interrupts();
730 ao_rdf_start(uint8_t len)
735 ao_radio_set_mode(AO_RADIO_MODE_RDF);
743 ao_radio_wait_isr(0);
752 ao_rdf_start(AO_RADIO_RDF_LEN);
754 ao_radio_fifo_write_fixed(ao_radio_rdf_value, AO_RADIO_RDF_LEN);
760 ao_radio_continuity(uint8_t c)
765 ao_rdf_start(AO_RADIO_CONT_TOTAL_LEN);
767 status = ao_radio_fifo_write_start();
768 for (i = 0; i < 3; i++) {
769 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN);
771 ao_radio_spi_send_fixed(ao_radio_rdf_value, AO_RADIO_CONT_TONE_LEN);
773 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_TONE_LEN);
775 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN);
776 status = ao_radio_fifo_write_stop(status);
782 ao_radio_rdf_abort(void)
785 ao_wakeup(&ao_radio_wake);
789 ao_radio_test_cmd(void)
792 static uint8_t radio_on;
794 if (ao_cmd_lex_c != '\n') {
796 mode = (uint8_t) ao_cmd_lex_u32;
799 if ((mode & 2) && !radio_on) {
801 ao_monitor_disable();
804 ao_packet_slave_stop();
807 ao_radio_set_mode(AO_RADIO_MODE_TEST);
808 ao_radio_strobe(CC1200_STX);
811 for (t = 0; t < 10; t++) {
812 printf ("status: %02x\n", ao_radio_status());
813 ao_delay(AO_MS_TO_TICKS(100));
820 printf ("Hit a character to stop..."); flush();
824 if ((mode & 1) && radio_on) {
835 ao_radio_send(const void *d, uint8_t size)
838 ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX);
840 ao_radio_fifo_write(d, size);
846 #define AO_RADIO_LOTS 64
849 ao_radio_send_aprs(ao_radio_fill_func fill)
851 uint8_t buf[AO_RADIO_LOTS], *b;
859 fifo_space = CC1200_FIFO_SIZE;
861 cnt = (*fill)(buf, sizeof(buf));
866 #if CC1200_APRS_TRACE
867 printf("APRS fill %d bytes done %d\n", cnt, done);
871 /* At the last buffer, set the total length */
873 ao_radio_set_len(total & 0xff);
877 uint8_t this_len = cnt;
879 /* Wait for some space in the fifo */
880 while (!ao_radio_abort && (fifo_space = ao_radio_tx_fifo_space()) == 0) {
881 #if CC1200_APRS_TRACE
882 printf("APRS space %d cnt %d\n", fifo_space, cnt); flush();
885 ao_radio_wait_isr(AO_MS_TO_TICKS(1000));
889 if (this_len > fifo_space)
890 this_len = fifo_space;
896 ao_radio_set_mode(AO_RADIO_MODE_APRS_LAST_BUF);
898 ao_radio_set_mode(AO_RADIO_MODE_APRS_FINISH);
900 ao_radio_set_mode(AO_RADIO_MODE_APRS_BUF);
902 ao_exti_enable(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN);
904 ao_radio_fifo_write(b, this_len);
906 #if CC1200_APRS_TRACE
907 printf("APRS write fifo %d space now %d\n", this_len, ao_radio_tx_fifo_space());
910 #if CC1200_APRS_TRACE
911 printf("APRS start\n");
913 ao_radio_strobe(CC1200_STX);
914 #if CC1200_APRS_TRACE
916 for (t = 0; t < 20; t++) {
917 uint8_t status = ao_radio_status();
918 uint8_t space = ao_radio_tx_fifo_space();
919 printf ("status: %02x fifo %d\n", status, space);
920 if ((status >> 4) == 2)
922 ao_delay(AO_MS_TO_TICKS(0));
929 if (ao_radio_abort) {
934 /* Wait for the transmitter to go idle */
936 #if CC1200_APRS_TRACE
937 printf("APRS wait idle\n"); flush();
939 ao_radio_wait_isr(AO_MS_TO_TICKS(1000));
940 #if CC1200_APRS_TRACE
941 printf("APRS abort %d\n", ao_radio_abort);
948 ao_radio_marc_state(void)
950 return ao_radio_reg_read(CC1200_MARCSTATE);
954 ao_radio_modem_status1(void)
956 return ao_radio_reg_read(CC1200_MODEM_STATUS1);
960 ao_radio_modem_status0(void)
962 return ao_radio_reg_read(CC1200_MODEM_STATUS0);
965 struct ao_radio_state {
968 uint8_t marc_status1;
969 uint8_t marc_status0;
970 uint8_t modem_status1;
971 uint8_t modem_status0;
975 ao_radio_fill_state(char *where, struct ao_radio_state *s)
977 strcpy(s->where, where);
978 s->marc_state = ao_radio_marc_state();
979 s->marc_status1 = ao_radio_reg_read(CC1200_MARC_STATUS1);
980 s->marc_status0 = ao_radio_reg_read(CC1200_MARC_STATUS0);
981 s->modem_status1 = ao_radio_modem_status1();
982 s->modem_status0 = ao_radio_modem_status0();
986 ao_radio_dump_state(struct ao_radio_state *s)
988 printf ("%s: marc %2x marc1 %2x marc0 %2x modem1 %2x modem0 %2x\n",
989 s->where, s->marc_state, s->marc_status1, s->marc_status0, s->modem_status1, s->modem_status0);
994 ao_radio_recv(__xdata void *d, uint8_t size, uint8_t timeout)
998 ao_radio_get(size - 2);
1000 ao_radio_set_mode(AO_RADIO_MODE_PACKET_RX);
1002 ao_radio_start_rx();
1003 ao_radio_wait_isr(timeout);
1004 if (ao_radio_wake) {
1008 status = ao_radio_fifo_read(d, size);
1010 rssi = ((int8_t *) d)[size - 2];
1011 ao_radio_rssi = rssi;
1013 /* Bound it to the representable range */
1017 /* Write it back to the packet */
1018 ((int8_t *) d)[size-2] = AO_RADIO_FROM_RSSI(rssi);
1025 return ao_radio_wake;
1030 static char *cc1200_state_name[] = {
1031 [CC1200_STATUS_STATE_IDLE] = "IDLE",
1032 [CC1200_STATUS_STATE_RX] = "RX",
1033 [CC1200_STATUS_STATE_TX] = "TX",
1034 [CC1200_STATUS_STATE_FSTXON] = "FSTXON",
1035 [CC1200_STATUS_STATE_CALIBRATE] = "CALIBRATE",
1036 [CC1200_STATUS_STATE_SETTLING] = "SETTLING",
1037 [CC1200_STATUS_STATE_RX_FIFO_ERROR] = "RX_FIFO_ERROR",
1038 [CC1200_STATUS_STATE_TX_FIFO_ERROR] = "TX_FIFO_ERROR",
1041 struct ao_cc1200_reg {
1046 static const struct ao_cc1200_reg ao_cc1200_reg[] = {
1047 { .addr = CC1200_IOCFG3, .name = "IOCFG3" },
1048 { .addr = CC1200_IOCFG2, .name = "IOCFG2" },
1049 { .addr = CC1200_IOCFG1, .name = "IOCFG1" },
1050 { .addr = CC1200_IOCFG0, .name = "IOCFG0" },
1051 { .addr = CC1200_SYNC3, .name = "SYNC3" },
1052 { .addr = CC1200_SYNC2, .name = "SYNC2" },
1053 { .addr = CC1200_SYNC1, .name = "SYNC1" },
1054 { .addr = CC1200_SYNC0, .name = "SYNC0" },
1055 { .addr = CC1200_SYNC_CFG1, .name = "SYNC_CFG1" },
1056 { .addr = CC1200_SYNC_CFG0, .name = "SYNC_CFG0" },
1057 { .addr = CC1200_DEVIATION_M, .name = "DEVIATION_M" },
1058 { .addr = CC1200_MODCFG_DEV_E, .name = "MODCFG_DEV_E" },
1059 { .addr = CC1200_DCFILT_CFG, .name = "DCFILT_CFG" },
1060 { .addr = CC1200_PREAMBLE_CFG1, .name = "PREAMBLE_CFG1" },
1061 { .addr = CC1200_PREAMBLE_CFG0, .name = "PREAMBLE_CFG0" },
1062 { .addr = CC1200_IQIC, .name = "IQIC" },
1063 { .addr = CC1200_CHAN_BW, .name = "CHAN_BW" },
1064 { .addr = CC1200_MDMCFG2, .name = "MDMCFG2" },
1065 { .addr = CC1200_MDMCFG1, .name = "MDMCFG1" },
1066 { .addr = CC1200_MDMCFG0, .name = "MDMCFG0" },
1067 { .addr = CC1200_SYMBOL_RATE2, .name = "SYMBOL_RATE2" },
1068 { .addr = CC1200_SYMBOL_RATE1, .name = "SYMBOL_RATE1" },
1069 { .addr = CC1200_SYMBOL_RATE0, .name = "SYMBOL_RATE0" },
1070 { .addr = CC1200_AGC_REF, .name = "AGC_REF" },
1071 { .addr = CC1200_AGC_CS_THR, .name = "AGC_CS_THR" },
1072 { .addr = CC1200_AGC_GAIN_ADJUST, .name = "AGC_GAIN_ADJUST" },
1073 { .addr = CC1200_AGC_CFG3, .name = "AGC_CFG3" },
1074 { .addr = CC1200_AGC_CFG2, .name = "AGC_CFG2" },
1075 { .addr = CC1200_AGC_CFG1, .name = "AGC_CFG1" },
1076 { .addr = CC1200_AGC_CFG0, .name = "AGC_CFG0" },
1077 { .addr = CC1200_FIFO_CFG, .name = "FIFO_CFG" },
1078 { .addr = CC1200_DEV_ADDR, .name = "DEV_ADDR" },
1079 { .addr = CC1200_SETTLING_CFG, .name = "SETTLING_CFG" },
1080 { .addr = CC1200_FS_CFG, .name = "FS_CFG" },
1081 { .addr = CC1200_WOR_CFG1, .name = "WOR_CFG1" },
1082 { .addr = CC1200_WOR_CFG0, .name = "WOR_CFG0" },
1083 { .addr = CC1200_WOR_EVENT0_MSB, .name = "WOR_EVENT0_MSB" },
1084 { .addr = CC1200_WOR_EVENT0_LSB, .name = "WOR_EVENT0_LSB" },
1085 { .addr = CC1200_RXDCM_TIME, .name = "RXDCM_TIME" },
1086 { .addr = CC1200_PKT_CFG2, .name = "PKT_CFG2" },
1087 { .addr = CC1200_PKT_CFG1, .name = "PKT_CFG1" },
1088 { .addr = CC1200_PKT_CFG0, .name = "PKT_CFG0" },
1089 { .addr = CC1200_RFEND_CFG1, .name = "RFEND_CFG1" },
1090 { .addr = CC1200_RFEND_CFG0, .name = "RFEND_CFG0" },
1091 { .addr = CC1200_PA_CFG1, .name = "PA_CFG1" },
1092 { .addr = CC1200_PA_CFG0, .name = "PA_CFG0" },
1093 { .addr = CC1200_PKT_LEN, .name = "PKT_LEN" },
1094 { .addr = CC1200_IF_MIX_CFG, .name = "IF_MIX_CFG" },
1095 { .addr = CC1200_FREQOFF_CFG, .name = "FREQOFF_CFG" },
1096 { .addr = CC1200_TOC_CFG, .name = "TOC_CFG" },
1097 { .addr = CC1200_MARC_SPARE, .name = "MARC_SPARE" },
1098 { .addr = CC1200_ECG_CFG, .name = "ECG_CFG" },
1099 { .addr = CC1200_EXT_CTRL, .name = "EXT_CTRL" },
1100 { .addr = CC1200_RCCAL_FINE, .name = "RCCAL_FINE" },
1101 { .addr = CC1200_RCCAL_COARSE, .name = "RCCAL_COARSE" },
1102 { .addr = CC1200_RCCAL_OFFSET, .name = "RCCAL_OFFSET" },
1103 { .addr = CC1200_FREQOFF1, .name = "FREQOFF1" },
1104 { .addr = CC1200_FREQOFF0, .name = "FREQOFF0" },
1105 { .addr = CC1200_FREQ2, .name = "FREQ2" },
1106 { .addr = CC1200_FREQ1, .name = "FREQ1" },
1107 { .addr = CC1200_FREQ0, .name = "FREQ0" },
1108 { .addr = CC1200_IF_ADC2, .name = "IF_ADC2" },
1109 { .addr = CC1200_IF_ADC1, .name = "IF_ADC1" },
1110 { .addr = CC1200_IF_ADC0, .name = "IF_ADC0" },
1111 { .addr = CC1200_FS_DIG1, .name = "FS_DIG1" },
1112 { .addr = CC1200_FS_DIG0, .name = "FS_DIG0" },
1113 { .addr = CC1200_FS_CAL3, .name = "FS_CAL3" },
1114 { .addr = CC1200_FS_CAL2, .name = "FS_CAL2" },
1115 { .addr = CC1200_FS_CAL1, .name = "FS_CAL1" },
1116 { .addr = CC1200_FS_CAL0, .name = "FS_CAL0" },
1117 { .addr = CC1200_FS_CHP, .name = "FS_CHP" },
1118 { .addr = CC1200_FS_DIVTWO, .name = "FS_DIVTWO" },
1119 { .addr = CC1200_FS_DSM1, .name = "FS_DSM1" },
1120 { .addr = CC1200_FS_DSM0, .name = "FS_DSM0" },
1121 { .addr = CC1200_FS_DVC1, .name = "FS_DVC1" },
1122 { .addr = CC1200_FS_DVC0, .name = "FS_DVC0" },
1123 { .addr = CC1200_FS_LBI, .name = "FS_LBI" },
1124 { .addr = CC1200_FS_PFD, .name = "FS_PFD" },
1125 { .addr = CC1200_FS_PRE, .name = "FS_PRE" },
1126 { .addr = CC1200_FS_REG_DIV_CML, .name = "FS_REG_DIV_CML" },
1127 { .addr = CC1200_FS_SPARE, .name = "FS_SPARE" },
1128 { .addr = CC1200_FS_VCO4, .name = "FS_VCO4" },
1129 { .addr = CC1200_FS_VCO3, .name = "FS_VCO3" },
1130 { .addr = CC1200_FS_VCO2, .name = "FS_VCO2" },
1131 { .addr = CC1200_FS_VCO1, .name = "FS_VCO1" },
1132 { .addr = CC1200_FS_VCO0, .name = "FS_VCO0" },
1133 { .addr = CC1200_GBIAS6, .name = "GBIAS6" },
1134 { .addr = CC1200_GBIAS5, .name = "GBIAS5" },
1135 { .addr = CC1200_GBIAS4, .name = "GBIAS4" },
1136 { .addr = CC1200_GBIAS3, .name = "GBIAS3" },
1137 { .addr = CC1200_GBIAS2, .name = "GBIAS2" },
1138 { .addr = CC1200_GBIAS1, .name = "GBIAS1" },
1139 { .addr = CC1200_GBIAS0, .name = "GBIAS0" },
1140 { .addr = CC1200_IFAMP, .name = "IFAMP" },
1141 { .addr = CC1200_LNA, .name = "LNA" },
1142 { .addr = CC1200_RXMIX, .name = "RXMIX" },
1143 { .addr = CC1200_XOSC5, .name = "XOSC5" },
1144 { .addr = CC1200_XOSC4, .name = "XOSC4" },
1145 { .addr = CC1200_XOSC3, .name = "XOSC3" },
1146 { .addr = CC1200_XOSC2, .name = "XOSC2" },
1147 { .addr = CC1200_XOSC1, .name = "XOSC1" },
1148 { .addr = CC1200_XOSC0, .name = "XOSC0" },
1149 { .addr = CC1200_ANALOG_SPARE, .name = "ANALOG_SPARE" },
1150 { .addr = CC1200_PA_CFG3, .name = "PA_CFG3" },
1151 { .addr = CC1200_WOR_TIME1, .name = "WOR_TIME1" },
1152 { .addr = CC1200_WOR_TIME0, .name = "WOR_TIME0" },
1153 { .addr = CC1200_WOR_CAPTURE1, .name = "WOR_CAPTURE1" },
1154 { .addr = CC1200_WOR_CAPTURE0, .name = "WOR_CAPTURE0" },
1155 { .addr = CC1200_BIST, .name = "BIST" },
1156 { .addr = CC1200_DCFILTOFFSET_I1, .name = "DCFILTOFFSET_I1" },
1157 { .addr = CC1200_DCFILTOFFSET_I0, .name = "DCFILTOFFSET_I0" },
1158 { .addr = CC1200_DCFILTOFFSET_Q1, .name = "DCFILTOFFSET_Q1" },
1159 { .addr = CC1200_DCFILTOFFSET_Q0, .name = "DCFILTOFFSET_Q0" },
1160 { .addr = CC1200_IQIE_I1, .name = "IQIE_I1" },
1161 { .addr = CC1200_IQIE_I0, .name = "IQIE_I0" },
1162 { .addr = CC1200_IQIE_Q1, .name = "IQIE_Q1" },
1163 { .addr = CC1200_IQIE_Q0, .name = "IQIE_Q0" },
1164 { .addr = CC1200_RSSI1, .name = "RSSI1" },
1165 { .addr = CC1200_RSSI0, .name = "RSSI0" },
1166 { .addr = CC1200_MARCSTATE, .name = "MARCSTATE" },
1167 { .addr = CC1200_LQI_VAL, .name = "LQI_VAL" },
1168 { .addr = CC1200_PQT_SYNC_ERR, .name = "PQT_SYNC_ERR" },
1169 { .addr = CC1200_DEM_STATUS, .name = "DEM_STATUS" },
1170 { .addr = CC1200_FREQOFF_EST1, .name = "FREQOFF_EST1" },
1171 { .addr = CC1200_FREQOFF_EST0, .name = "FREQOFF_EST0" },
1172 { .addr = CC1200_AGC_GAIN3, .name = "AGC_GAIN3" },
1173 { .addr = CC1200_AGC_GAIN2, .name = "AGC_GAIN2" },
1174 { .addr = CC1200_AGC_GAIN1, .name = "AGC_GAIN1" },
1175 { .addr = CC1200_AGC_GAIN0, .name = "AGC_GAIN0" },
1176 { .addr = CC1200_SOFT_RX_DATA_OUT, .name = "SOFT_RX_DATA_OUT" },
1177 { .addr = CC1200_SOFT_TX_DATA_IN, .name = "SOFT_TX_DATA_IN" },
1178 { .addr = CC1200_ASK_SOFT_RX_DATA, .name = "ASK_SOFT_RX_DATA" },
1179 { .addr = CC1200_RNDGEN, .name = "RNDGEN" },
1180 { .addr = CC1200_MAGN2, .name = "MAGN2" },
1181 { .addr = CC1200_MAGN1, .name = "MAGN1" },
1182 { .addr = CC1200_MAGN0, .name = "MAGN0" },
1183 { .addr = CC1200_ANG1, .name = "ANG1" },
1184 { .addr = CC1200_ANG0, .name = "ANG0" },
1185 { .addr = CC1200_CHFILT_I2, .name = "CHFILT_I2" },
1186 { .addr = CC1200_CHFILT_I1, .name = "CHFILT_I1" },
1187 { .addr = CC1200_CHFILT_I0, .name = "CHFILT_I0" },
1188 { .addr = CC1200_CHFILT_Q2, .name = "CHFILT_Q2" },
1189 { .addr = CC1200_CHFILT_Q1, .name = "CHFILT_Q1" },
1190 { .addr = CC1200_CHFILT_Q0, .name = "CHFILT_Q0" },
1191 { .addr = CC1200_GPIO_STATUS, .name = "GPIO_STATUS" },
1192 { .addr = CC1200_FSCAL_CTRL, .name = "FSCAL_CTRL" },
1193 { .addr = CC1200_PHASE_ADJUST, .name = "PHASE_ADJUST" },
1194 { .addr = CC1200_PARTNUMBER, .name = "PARTNUMBER" },
1195 { .addr = CC1200_PARTVERSION, .name = "PARTVERSION" },
1196 { .addr = CC1200_SERIAL_STATUS, .name = "SERIAL_STATUS" },
1197 { .addr = CC1200_MODEM_STATUS1, .name = "MODEM_STATUS1" },
1198 { .addr = CC1200_MODEM_STATUS0, .name = "MODEM_STATUS0" },
1199 { .addr = CC1200_MARC_STATUS1, .name = "MARC_STATUS1" },
1200 { .addr = CC1200_MARC_STATUS0, .name = "MARC_STATUS0" },
1201 { .addr = CC1200_PA_IFAMP_TEST, .name = "PA_IFAMP_TEST" },
1202 { .addr = CC1200_FSRF_TEST, .name = "FSRF_TEST" },
1203 { .addr = CC1200_PRE_TEST, .name = "PRE_TEST" },
1204 { .addr = CC1200_PRE_OVR, .name = "PRE_OVR" },
1205 { .addr = CC1200_ADC_TEST, .name = "ADC_TEST" },
1206 { .addr = CC1200_DVC_TEST, .name = "DVC_TEST" },
1207 { .addr = CC1200_ATEST, .name = "ATEST" },
1208 { .addr = CC1200_ATEST_LVDS, .name = "ATEST_LVDS" },
1209 { .addr = CC1200_ATEST_MODE, .name = "ATEST_MODE" },
1210 { .addr = CC1200_XOSC_TEST1, .name = "XOSC_TEST1" },
1211 { .addr = CC1200_XOSC_TEST0, .name = "XOSC_TEST0" },
1212 { .addr = CC1200_RXFIRST, .name = "RXFIRST" },
1213 { .addr = CC1200_TXFIRST, .name = "TXFIRST" },
1214 { .addr = CC1200_RXLAST, .name = "RXLAST" },
1215 { .addr = CC1200_TXLAST, .name = "TXLAST" },
1216 { .addr = CC1200_NUM_TXBYTES, .name = "NUM_TXBYTES" },
1217 { .addr = CC1200_NUM_RXBYTES, .name = "NUM_RXBYTES" },
1218 { .addr = CC1200_FIFO_NUM_TXBYTES, .name = "FIFO_NUM_TXBYTES" },
1219 { .addr = CC1200_FIFO_NUM_RXBYTES, .name = "FIFO_NUM_RXBYTES" },
1222 #define AO_NUM_CC1200_REG (sizeof ao_cc1200_reg / sizeof ao_cc1200_reg[0])
1225 ao_radio_get_marc_status(void)
1227 return ao_radio_reg_read(CC1200_MARC_STATUS1);
1230 static void ao_radio_show(void) {
1234 ao_mutex_get(&ao_radio_mutex);
1235 status = ao_radio_status();
1236 printf ("Status: %02x\n", status);
1237 printf ("CHIP_RDY: %d\n", (status >> CC1200_STATUS_CHIP_RDY) & 1);
1238 printf ("STATE: %s\n", cc1200_state_name[(status >> CC1200_STATUS_STATE) & CC1200_STATUS_STATE_MASK]);
1239 printf ("MARC: %02x\n", ao_radio_get_marc_status());
1241 for (i = 0; i < AO_NUM_CC1200_REG; i++)
1242 printf ("\t%02x %-20.20s\n", ao_radio_reg_read(ao_cc1200_reg[i].addr), ao_cc1200_reg[i].name);
1247 static void ao_radio_beep(void) {
1251 static void ao_radio_packet(void) {
1252 static const uint8_t packet[] = {
1254 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1255 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1256 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1257 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1263 ao_radio_send(packet, sizeof (packet));
1267 ao_radio_test_recv(void)
1272 if (ao_radio_recv(bytes, 34, 0)) {
1273 if (bytes[33] & 0x80)
1277 printf (" RSSI %d", AO_RSSI_FROM_RADIO(bytes[32]));
1278 for (b = 0; b < 32; b++)
1279 printf (" %02x", bytes[b]);
1281 printf (" RSSI %02x LQI %02x", bytes[32], bytes[33]);
1287 #include <ao_aprs.h>
1292 #if PACKET_HAS_SLAVE
1293 ao_packet_slave_stop();
1300 #if CC1200_LOW_LEVEL_DEBUG
1302 ao_radio_strobe_test(void)
1307 if (ao_cmd_status != ao_cmd_success)
1309 r = ao_radio_strobe(ao_cmd_lex_i);
1310 printf ("Strobe %02x -> %02x (rdy %d state %d)\n",
1318 ao_radio_write_test(void)
1324 if (ao_cmd_status != ao_cmd_success)
1326 addr = ao_cmd_lex_i;
1328 if (ao_cmd_status != ao_cmd_success)
1330 data = ao_cmd_lex_i;
1331 printf ("Write %04x = %02x\n", addr, data);
1332 ao_radio_reg_write(addr, data);
1336 ao_radio_read_test(void)
1342 if (ao_cmd_status != ao_cmd_success)
1344 addr = ao_cmd_lex_i;
1345 data = ao_radio_reg_read(addr);
1346 printf ("Read %04x = %02x\n", addr, data);
1350 static const struct ao_cmds ao_radio_cmds[] = {
1351 { ao_radio_test_cmd, "C <1 start, 0 stop, none both>\0Radio carrier test" },
1354 { ao_radio_aprs, "G\0Send APRS packet" },
1356 { ao_radio_show, "R\0Show CC1200 status" },
1357 { ao_radio_beep, "b\0Emit an RDF beacon" },
1358 { ao_radio_packet, "p\0Send a test packet" },
1359 { ao_radio_test_recv, "q\0Recv a test packet" },
1361 #if CC1200_LOW_LEVEL_DEBUG
1362 { ao_radio_strobe_test, "A <value>\0Strobe radio" },
1363 { ao_radio_write_test, "W <addr> <value>\0Write radio reg" },
1364 { ao_radio_read_test, "B <addr>\0Read radio reg" },
1372 ao_radio_configured = 0;
1373 ao_spi_init_cs (AO_CC1200_SPI_CS_PORT, (1 << AO_CC1200_SPI_CS_PIN));
1376 AO_CC1200_SPI_CS_PORT->bsrr = ((uint32_t) (1 << AO_CC1200_SPI_CS_PIN));
1377 for (i = 0; i < 10000; i++) {
1378 if ((SPI_2_PORT->idr & (1 << SPI_2_MISO_PIN)) == 0)
1381 AO_CC1200_SPI_CS_PORT->bsrr = (1 << AO_CC1200_SPI_CS_PIN);
1383 ao_panic(AO_PANIC_SELF_TEST_CC1200);
1386 /* Enable the EXTI interrupt for the appropriate pin */
1387 ao_enable_port(AO_CC1200_INT_PORT);
1388 ao_exti_setup(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN,
1389 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH,
1392 ao_cmd_register(&ao_radio_cmds[0]);