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)
224 if (state == CC1200_STATUS_STATE_TX_FIFO_ERROR)
225 ao_radio_strobe(CC1200_SFTX);
226 if (state == CC1200_STATUS_STATE_RX_FIFO_ERROR)
227 ao_radio_strobe(CC1200_SFRX);
229 /* Flush any pending data in the fifos */
230 ao_radio_strobe(CC1200_SFTX);
231 ao_radio_strobe(CC1200_SFRX);
232 /* Make sure the RF calibration is current */
233 ao_radio_strobe(CC1200_SCAL);
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);
642 ao_radio_configured = 1;
646 ao_radio_set_len(uint8_t len)
648 static uint8_t last_len;
650 if (len != last_len) {
651 ao_radio_reg_write(CC1200_PKT_LEN, len);
657 ao_radio_get(uint8_t len)
659 static uint32_t last_radio_setting;
660 static uint8_t last_radio_rate;
662 ao_mutex_get(&ao_radio_mutex);
664 if (!ao_radio_configured)
666 if (ao_config.radio_setting != last_radio_setting) {
667 ao_radio_reg_write(CC1200_FREQ2, ao_config.radio_setting >> 16);
668 ao_radio_reg_write(CC1200_FREQ1, ao_config.radio_setting >> 8);
669 ao_radio_reg_write(CC1200_FREQ0, ao_config.radio_setting);
670 last_radio_setting = ao_config.radio_setting;
671 ao_radio_strobe(CC1200_SCAL);
673 if (ao_config.radio_rate != last_radio_rate) {
674 ao_radio_mode &= ~AO_RADIO_MODE_BITS_PACKET;
675 last_radio_rate = ao_config.radio_rate;
677 ao_radio_set_len(len);
680 #define ao_radio_put() ao_mutex_put(&ao_radio_mutex)
682 static inline uint8_t
685 return (ao_radio_status() >> CC1200_STATUS_STATE) & CC1200_STATUS_STATE_MASK;
690 ao_radio_show_state(char *where)
692 printf("%s: state %d len %d rxbytes %d\n",
693 where, ao_radio_state(),
694 ao_radio_reg_read(CC1200_PKT_LEN),
695 ao_radio_reg_read(CC1200_NUM_RXBYTES));
698 #define ao_radio_show_state(where)
701 /* Wait for the radio to signal an interrupt
704 ao_radio_wait_isr(uint16_t timeout)
708 state = ao_radio_state();
710 case CC1200_STATUS_STATE_IDLE:
711 case CC1200_STATUS_STATE_RX_FIFO_ERROR:
712 case CC1200_STATUS_STATE_TX_FIFO_ERROR:
713 #if CC1200_LOW_LEVEL_DEBUG
714 printf("before wait, state %d\n", state); flush();
723 ao_arch_block_interrupts();
724 while (!ao_radio_wake && !ao_radio_abort)
725 if (ao_sleep(&ao_radio_wake))
727 ao_arch_release_interrupts();
733 ao_rdf_start(uint8_t len)
738 ao_radio_set_mode(AO_RADIO_MODE_RDF);
746 ao_radio_wait_isr(0);
755 ao_rdf_start(AO_RADIO_RDF_LEN);
757 ao_radio_fifo_write_fixed(ao_radio_rdf_value, AO_RADIO_RDF_LEN);
763 ao_radio_continuity(uint8_t c)
768 ao_rdf_start(AO_RADIO_CONT_TOTAL_LEN);
770 status = ao_radio_fifo_write_start();
771 for (i = 0; i < 3; i++) {
772 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN);
774 ao_radio_spi_send_fixed(ao_radio_rdf_value, AO_RADIO_CONT_TONE_LEN);
776 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_TONE_LEN);
778 ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN);
779 status = ao_radio_fifo_write_stop(status);
785 ao_radio_rdf_abort(void)
788 ao_wakeup(&ao_radio_wake);
792 ao_radio_test_cmd(void)
795 static uint8_t radio_on;
797 if (ao_cmd_lex_c != '\n') {
799 mode = (uint8_t) ao_cmd_lex_u32;
802 if ((mode & 2) && !radio_on) {
804 ao_monitor_disable();
807 ao_packet_slave_stop();
810 ao_radio_set_mode(AO_RADIO_MODE_TEST);
811 ao_radio_strobe(CC1200_STX);
814 for (t = 0; t < 10; t++) {
815 printf ("status: %02x\n", ao_radio_status());
816 ao_delay(AO_MS_TO_TICKS(100));
823 printf ("Hit a character to stop..."); flush();
827 if ((mode & 1) && radio_on) {
838 ao_radio_send(const void *d, uint8_t size)
841 ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX);
843 ao_radio_fifo_write(d, size);
849 #define AO_RADIO_LOTS 64
852 ao_radio_send_aprs(ao_radio_fill_func fill)
854 uint8_t buf[AO_RADIO_LOTS], *b;
862 fifo_space = CC1200_FIFO_SIZE;
864 cnt = (*fill)(buf, sizeof(buf));
869 #if CC1200_APRS_TRACE
870 printf("APRS fill %d bytes done %d\n", cnt, done);
874 /* At the last buffer, set the total length */
876 ao_radio_set_len(total & 0xff);
880 uint8_t this_len = cnt;
882 /* Wait for some space in the fifo */
883 while (!ao_radio_abort && (fifo_space = ao_radio_tx_fifo_space()) == 0) {
884 #if CC1200_APRS_TRACE
885 printf("APRS space %d cnt %d\n", fifo_space, cnt); flush();
888 ao_radio_wait_isr(AO_MS_TO_TICKS(1000));
892 if (this_len > fifo_space)
893 this_len = fifo_space;
899 ao_radio_set_mode(AO_RADIO_MODE_APRS_LAST_BUF);
901 ao_radio_set_mode(AO_RADIO_MODE_APRS_FINISH);
903 ao_radio_set_mode(AO_RADIO_MODE_APRS_BUF);
905 ao_exti_enable(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN);
907 ao_radio_fifo_write(b, this_len);
909 #if CC1200_APRS_TRACE
910 printf("APRS write fifo %d space now %d\n", this_len, ao_radio_tx_fifo_space());
913 #if CC1200_APRS_TRACE
914 printf("APRS start\n");
916 ao_radio_strobe(CC1200_STX);
917 #if CC1200_APRS_TRACE
919 for (t = 0; t < 20; t++) {
920 uint8_t status = ao_radio_status();
921 uint8_t space = ao_radio_tx_fifo_space();
922 printf ("status: %02x fifo %d\n", status, space);
923 if ((status >> 4) == 2)
925 ao_delay(AO_MS_TO_TICKS(0));
932 if (ao_radio_abort) {
937 /* Wait for the transmitter to go idle */
939 #if CC1200_APRS_TRACE
940 printf("APRS wait idle\n"); flush();
942 ao_radio_wait_isr(AO_MS_TO_TICKS(1000));
943 #if CC1200_APRS_TRACE
944 printf("APRS abort %d\n", ao_radio_abort);
951 ao_radio_marc_state(void)
953 return ao_radio_reg_read(CC1200_MARCSTATE);
957 ao_radio_modem_status1(void)
959 return ao_radio_reg_read(CC1200_MODEM_STATUS1);
963 ao_radio_modem_status0(void)
965 return ao_radio_reg_read(CC1200_MODEM_STATUS0);
968 struct ao_radio_state {
971 uint8_t marc_status1;
972 uint8_t marc_status0;
973 uint8_t modem_status1;
974 uint8_t modem_status0;
978 ao_radio_fill_state(char *where, struct ao_radio_state *s)
980 strcpy(s->where, where);
981 s->marc_state = ao_radio_marc_state();
982 s->marc_status1 = ao_radio_reg_read(CC1200_MARC_STATUS1);
983 s->marc_status0 = ao_radio_reg_read(CC1200_MARC_STATUS0);
984 s->modem_status1 = ao_radio_modem_status1();
985 s->modem_status0 = ao_radio_modem_status0();
989 ao_radio_dump_state(struct ao_radio_state *s)
991 printf ("%s: marc %2x marc1 %2x marc0 %2x modem1 %2x modem0 %2x\n",
992 s->where, s->marc_state, s->marc_status1, s->marc_status0, s->modem_status1, s->modem_status0);
997 ao_radio_recv(__xdata void *d, uint8_t size, uint8_t timeout)
1001 ao_radio_get(size - 2);
1002 ao_radio_set_mode(AO_RADIO_MODE_PACKET_RX);
1004 ao_radio_start_rx();
1005 ao_radio_wait_isr(timeout);
1006 if (ao_radio_wake) {
1010 status = ao_radio_fifo_read(d, size);
1012 rssi = ((int8_t *) d)[size - 2];
1013 ao_radio_rssi = rssi;
1015 /* Bound it to the representable range */
1019 /* Write it back to the packet */
1020 ((int8_t *) d)[size-2] = AO_RADIO_FROM_RSSI(rssi);
1027 return ao_radio_wake;
1032 static char *cc1200_state_name[] = {
1033 [CC1200_STATUS_STATE_IDLE] = "IDLE",
1034 [CC1200_STATUS_STATE_RX] = "RX",
1035 [CC1200_STATUS_STATE_TX] = "TX",
1036 [CC1200_STATUS_STATE_FSTXON] = "FSTXON",
1037 [CC1200_STATUS_STATE_CALIBRATE] = "CALIBRATE",
1038 [CC1200_STATUS_STATE_SETTLING] = "SETTLING",
1039 [CC1200_STATUS_STATE_RX_FIFO_ERROR] = "RX_FIFO_ERROR",
1040 [CC1200_STATUS_STATE_TX_FIFO_ERROR] = "TX_FIFO_ERROR",
1043 struct ao_cc1200_reg {
1048 static const struct ao_cc1200_reg ao_cc1200_reg[] = {
1049 { .addr = CC1200_IOCFG3, .name = "IOCFG3" },
1050 { .addr = CC1200_IOCFG2, .name = "IOCFG2" },
1051 { .addr = CC1200_IOCFG1, .name = "IOCFG1" },
1052 { .addr = CC1200_IOCFG0, .name = "IOCFG0" },
1053 { .addr = CC1200_SYNC3, .name = "SYNC3" },
1054 { .addr = CC1200_SYNC2, .name = "SYNC2" },
1055 { .addr = CC1200_SYNC1, .name = "SYNC1" },
1056 { .addr = CC1200_SYNC0, .name = "SYNC0" },
1057 { .addr = CC1200_SYNC_CFG1, .name = "SYNC_CFG1" },
1058 { .addr = CC1200_SYNC_CFG0, .name = "SYNC_CFG0" },
1059 { .addr = CC1200_DEVIATION_M, .name = "DEVIATION_M" },
1060 { .addr = CC1200_MODCFG_DEV_E, .name = "MODCFG_DEV_E" },
1061 { .addr = CC1200_DCFILT_CFG, .name = "DCFILT_CFG" },
1062 { .addr = CC1200_PREAMBLE_CFG1, .name = "PREAMBLE_CFG1" },
1063 { .addr = CC1200_PREAMBLE_CFG0, .name = "PREAMBLE_CFG0" },
1064 { .addr = CC1200_IQIC, .name = "IQIC" },
1065 { .addr = CC1200_CHAN_BW, .name = "CHAN_BW" },
1066 { .addr = CC1200_MDMCFG2, .name = "MDMCFG2" },
1067 { .addr = CC1200_MDMCFG1, .name = "MDMCFG1" },
1068 { .addr = CC1200_MDMCFG0, .name = "MDMCFG0" },
1069 { .addr = CC1200_SYMBOL_RATE2, .name = "SYMBOL_RATE2" },
1070 { .addr = CC1200_SYMBOL_RATE1, .name = "SYMBOL_RATE1" },
1071 { .addr = CC1200_SYMBOL_RATE0, .name = "SYMBOL_RATE0" },
1072 { .addr = CC1200_AGC_REF, .name = "AGC_REF" },
1073 { .addr = CC1200_AGC_CS_THR, .name = "AGC_CS_THR" },
1074 { .addr = CC1200_AGC_GAIN_ADJUST, .name = "AGC_GAIN_ADJUST" },
1075 { .addr = CC1200_AGC_CFG3, .name = "AGC_CFG3" },
1076 { .addr = CC1200_AGC_CFG2, .name = "AGC_CFG2" },
1077 { .addr = CC1200_AGC_CFG1, .name = "AGC_CFG1" },
1078 { .addr = CC1200_AGC_CFG0, .name = "AGC_CFG0" },
1079 { .addr = CC1200_FIFO_CFG, .name = "FIFO_CFG" },
1080 { .addr = CC1200_DEV_ADDR, .name = "DEV_ADDR" },
1081 { .addr = CC1200_SETTLING_CFG, .name = "SETTLING_CFG" },
1082 { .addr = CC1200_FS_CFG, .name = "FS_CFG" },
1083 { .addr = CC1200_WOR_CFG1, .name = "WOR_CFG1" },
1084 { .addr = CC1200_WOR_CFG0, .name = "WOR_CFG0" },
1085 { .addr = CC1200_WOR_EVENT0_MSB, .name = "WOR_EVENT0_MSB" },
1086 { .addr = CC1200_WOR_EVENT0_LSB, .name = "WOR_EVENT0_LSB" },
1087 { .addr = CC1200_RXDCM_TIME, .name = "RXDCM_TIME" },
1088 { .addr = CC1200_PKT_CFG2, .name = "PKT_CFG2" },
1089 { .addr = CC1200_PKT_CFG1, .name = "PKT_CFG1" },
1090 { .addr = CC1200_PKT_CFG0, .name = "PKT_CFG0" },
1091 { .addr = CC1200_RFEND_CFG1, .name = "RFEND_CFG1" },
1092 { .addr = CC1200_RFEND_CFG0, .name = "RFEND_CFG0" },
1093 { .addr = CC1200_PA_CFG1, .name = "PA_CFG1" },
1094 { .addr = CC1200_PA_CFG0, .name = "PA_CFG0" },
1095 { .addr = CC1200_PKT_LEN, .name = "PKT_LEN" },
1096 { .addr = CC1200_IF_MIX_CFG, .name = "IF_MIX_CFG" },
1097 { .addr = CC1200_FREQOFF_CFG, .name = "FREQOFF_CFG" },
1098 { .addr = CC1200_TOC_CFG, .name = "TOC_CFG" },
1099 { .addr = CC1200_MARC_SPARE, .name = "MARC_SPARE" },
1100 { .addr = CC1200_ECG_CFG, .name = "ECG_CFG" },
1101 { .addr = CC1200_EXT_CTRL, .name = "EXT_CTRL" },
1102 { .addr = CC1200_RCCAL_FINE, .name = "RCCAL_FINE" },
1103 { .addr = CC1200_RCCAL_COARSE, .name = "RCCAL_COARSE" },
1104 { .addr = CC1200_RCCAL_OFFSET, .name = "RCCAL_OFFSET" },
1105 { .addr = CC1200_FREQOFF1, .name = "FREQOFF1" },
1106 { .addr = CC1200_FREQOFF0, .name = "FREQOFF0" },
1107 { .addr = CC1200_FREQ2, .name = "FREQ2" },
1108 { .addr = CC1200_FREQ1, .name = "FREQ1" },
1109 { .addr = CC1200_FREQ0, .name = "FREQ0" },
1110 { .addr = CC1200_IF_ADC2, .name = "IF_ADC2" },
1111 { .addr = CC1200_IF_ADC1, .name = "IF_ADC1" },
1112 { .addr = CC1200_IF_ADC0, .name = "IF_ADC0" },
1113 { .addr = CC1200_FS_DIG1, .name = "FS_DIG1" },
1114 { .addr = CC1200_FS_DIG0, .name = "FS_DIG0" },
1115 { .addr = CC1200_FS_CAL3, .name = "FS_CAL3" },
1116 { .addr = CC1200_FS_CAL2, .name = "FS_CAL2" },
1117 { .addr = CC1200_FS_CAL1, .name = "FS_CAL1" },
1118 { .addr = CC1200_FS_CAL0, .name = "FS_CAL0" },
1119 { .addr = CC1200_FS_CHP, .name = "FS_CHP" },
1120 { .addr = CC1200_FS_DIVTWO, .name = "FS_DIVTWO" },
1121 { .addr = CC1200_FS_DSM1, .name = "FS_DSM1" },
1122 { .addr = CC1200_FS_DSM0, .name = "FS_DSM0" },
1123 { .addr = CC1200_FS_DVC1, .name = "FS_DVC1" },
1124 { .addr = CC1200_FS_DVC0, .name = "FS_DVC0" },
1125 { .addr = CC1200_FS_LBI, .name = "FS_LBI" },
1126 { .addr = CC1200_FS_PFD, .name = "FS_PFD" },
1127 { .addr = CC1200_FS_PRE, .name = "FS_PRE" },
1128 { .addr = CC1200_FS_REG_DIV_CML, .name = "FS_REG_DIV_CML" },
1129 { .addr = CC1200_FS_SPARE, .name = "FS_SPARE" },
1130 { .addr = CC1200_FS_VCO4, .name = "FS_VCO4" },
1131 { .addr = CC1200_FS_VCO3, .name = "FS_VCO3" },
1132 { .addr = CC1200_FS_VCO2, .name = "FS_VCO2" },
1133 { .addr = CC1200_FS_VCO1, .name = "FS_VCO1" },
1134 { .addr = CC1200_FS_VCO0, .name = "FS_VCO0" },
1135 { .addr = CC1200_GBIAS6, .name = "GBIAS6" },
1136 { .addr = CC1200_GBIAS5, .name = "GBIAS5" },
1137 { .addr = CC1200_GBIAS4, .name = "GBIAS4" },
1138 { .addr = CC1200_GBIAS3, .name = "GBIAS3" },
1139 { .addr = CC1200_GBIAS2, .name = "GBIAS2" },
1140 { .addr = CC1200_GBIAS1, .name = "GBIAS1" },
1141 { .addr = CC1200_GBIAS0, .name = "GBIAS0" },
1142 { .addr = CC1200_IFAMP, .name = "IFAMP" },
1143 { .addr = CC1200_LNA, .name = "LNA" },
1144 { .addr = CC1200_RXMIX, .name = "RXMIX" },
1145 { .addr = CC1200_XOSC5, .name = "XOSC5" },
1146 { .addr = CC1200_XOSC4, .name = "XOSC4" },
1147 { .addr = CC1200_XOSC3, .name = "XOSC3" },
1148 { .addr = CC1200_XOSC2, .name = "XOSC2" },
1149 { .addr = CC1200_XOSC1, .name = "XOSC1" },
1150 { .addr = CC1200_XOSC0, .name = "XOSC0" },
1151 { .addr = CC1200_ANALOG_SPARE, .name = "ANALOG_SPARE" },
1152 { .addr = CC1200_PA_CFG3, .name = "PA_CFG3" },
1153 { .addr = CC1200_WOR_TIME1, .name = "WOR_TIME1" },
1154 { .addr = CC1200_WOR_TIME0, .name = "WOR_TIME0" },
1155 { .addr = CC1200_WOR_CAPTURE1, .name = "WOR_CAPTURE1" },
1156 { .addr = CC1200_WOR_CAPTURE0, .name = "WOR_CAPTURE0" },
1157 { .addr = CC1200_BIST, .name = "BIST" },
1158 { .addr = CC1200_DCFILTOFFSET_I1, .name = "DCFILTOFFSET_I1" },
1159 { .addr = CC1200_DCFILTOFFSET_I0, .name = "DCFILTOFFSET_I0" },
1160 { .addr = CC1200_DCFILTOFFSET_Q1, .name = "DCFILTOFFSET_Q1" },
1161 { .addr = CC1200_DCFILTOFFSET_Q0, .name = "DCFILTOFFSET_Q0" },
1162 { .addr = CC1200_IQIE_I1, .name = "IQIE_I1" },
1163 { .addr = CC1200_IQIE_I0, .name = "IQIE_I0" },
1164 { .addr = CC1200_IQIE_Q1, .name = "IQIE_Q1" },
1165 { .addr = CC1200_IQIE_Q0, .name = "IQIE_Q0" },
1166 { .addr = CC1200_RSSI1, .name = "RSSI1" },
1167 { .addr = CC1200_RSSI0, .name = "RSSI0" },
1168 { .addr = CC1200_MARCSTATE, .name = "MARCSTATE" },
1169 { .addr = CC1200_LQI_VAL, .name = "LQI_VAL" },
1170 { .addr = CC1200_PQT_SYNC_ERR, .name = "PQT_SYNC_ERR" },
1171 { .addr = CC1200_DEM_STATUS, .name = "DEM_STATUS" },
1172 { .addr = CC1200_FREQOFF_EST1, .name = "FREQOFF_EST1" },
1173 { .addr = CC1200_FREQOFF_EST0, .name = "FREQOFF_EST0" },
1174 { .addr = CC1200_AGC_GAIN3, .name = "AGC_GAIN3" },
1175 { .addr = CC1200_AGC_GAIN2, .name = "AGC_GAIN2" },
1176 { .addr = CC1200_AGC_GAIN1, .name = "AGC_GAIN1" },
1177 { .addr = CC1200_AGC_GAIN0, .name = "AGC_GAIN0" },
1178 { .addr = CC1200_SOFT_RX_DATA_OUT, .name = "SOFT_RX_DATA_OUT" },
1179 { .addr = CC1200_SOFT_TX_DATA_IN, .name = "SOFT_TX_DATA_IN" },
1180 { .addr = CC1200_ASK_SOFT_RX_DATA, .name = "ASK_SOFT_RX_DATA" },
1181 { .addr = CC1200_RNDGEN, .name = "RNDGEN" },
1182 { .addr = CC1200_MAGN2, .name = "MAGN2" },
1183 { .addr = CC1200_MAGN1, .name = "MAGN1" },
1184 { .addr = CC1200_MAGN0, .name = "MAGN0" },
1185 { .addr = CC1200_ANG1, .name = "ANG1" },
1186 { .addr = CC1200_ANG0, .name = "ANG0" },
1187 { .addr = CC1200_CHFILT_I2, .name = "CHFILT_I2" },
1188 { .addr = CC1200_CHFILT_I1, .name = "CHFILT_I1" },
1189 { .addr = CC1200_CHFILT_I0, .name = "CHFILT_I0" },
1190 { .addr = CC1200_CHFILT_Q2, .name = "CHFILT_Q2" },
1191 { .addr = CC1200_CHFILT_Q1, .name = "CHFILT_Q1" },
1192 { .addr = CC1200_CHFILT_Q0, .name = "CHFILT_Q0" },
1193 { .addr = CC1200_GPIO_STATUS, .name = "GPIO_STATUS" },
1194 { .addr = CC1200_FSCAL_CTRL, .name = "FSCAL_CTRL" },
1195 { .addr = CC1200_PHASE_ADJUST, .name = "PHASE_ADJUST" },
1196 { .addr = CC1200_PARTNUMBER, .name = "PARTNUMBER" },
1197 { .addr = CC1200_PARTVERSION, .name = "PARTVERSION" },
1198 { .addr = CC1200_SERIAL_STATUS, .name = "SERIAL_STATUS" },
1199 { .addr = CC1200_MODEM_STATUS1, .name = "MODEM_STATUS1" },
1200 { .addr = CC1200_MODEM_STATUS0, .name = "MODEM_STATUS0" },
1201 { .addr = CC1200_MARC_STATUS1, .name = "MARC_STATUS1" },
1202 { .addr = CC1200_MARC_STATUS0, .name = "MARC_STATUS0" },
1203 { .addr = CC1200_PA_IFAMP_TEST, .name = "PA_IFAMP_TEST" },
1204 { .addr = CC1200_FSRF_TEST, .name = "FSRF_TEST" },
1205 { .addr = CC1200_PRE_TEST, .name = "PRE_TEST" },
1206 { .addr = CC1200_PRE_OVR, .name = "PRE_OVR" },
1207 { .addr = CC1200_ADC_TEST, .name = "ADC_TEST" },
1208 { .addr = CC1200_DVC_TEST, .name = "DVC_TEST" },
1209 { .addr = CC1200_ATEST, .name = "ATEST" },
1210 { .addr = CC1200_ATEST_LVDS, .name = "ATEST_LVDS" },
1211 { .addr = CC1200_ATEST_MODE, .name = "ATEST_MODE" },
1212 { .addr = CC1200_XOSC_TEST1, .name = "XOSC_TEST1" },
1213 { .addr = CC1200_XOSC_TEST0, .name = "XOSC_TEST0" },
1214 { .addr = CC1200_RXFIRST, .name = "RXFIRST" },
1215 { .addr = CC1200_TXFIRST, .name = "TXFIRST" },
1216 { .addr = CC1200_RXLAST, .name = "RXLAST" },
1217 { .addr = CC1200_TXLAST, .name = "TXLAST" },
1218 { .addr = CC1200_NUM_TXBYTES, .name = "NUM_TXBYTES" },
1219 { .addr = CC1200_NUM_RXBYTES, .name = "NUM_RXBYTES" },
1220 { .addr = CC1200_FIFO_NUM_TXBYTES, .name = "FIFO_NUM_TXBYTES" },
1221 { .addr = CC1200_FIFO_NUM_RXBYTES, .name = "FIFO_NUM_RXBYTES" },
1224 #define AO_NUM_CC1200_REG (sizeof ao_cc1200_reg / sizeof ao_cc1200_reg[0])
1227 ao_radio_get_marc_status(void)
1229 return ao_radio_reg_read(CC1200_MARC_STATUS1);
1232 static void ao_radio_show(void) {
1236 ao_mutex_get(&ao_radio_mutex);
1237 status = ao_radio_status();
1238 printf ("Status: %02x\n", status);
1239 printf ("CHIP_RDY: %d\n", (status >> CC1200_STATUS_CHIP_RDY) & 1);
1240 printf ("STATE: %s\n", cc1200_state_name[(status >> CC1200_STATUS_STATE) & CC1200_STATUS_STATE_MASK]);
1241 printf ("MARC: %02x\n", ao_radio_get_marc_status());
1243 for (i = 0; i < AO_NUM_CC1200_REG; i++)
1244 printf ("\t%02x %-20.20s\n", ao_radio_reg_read(ao_cc1200_reg[i].addr), ao_cc1200_reg[i].name);
1249 static void ao_radio_beep(void) {
1253 static void ao_radio_packet(void) {
1254 static const uint8_t packet[] = {
1256 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1257 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1258 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1259 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1265 ao_radio_send(packet, sizeof (packet));
1269 ao_radio_test_recv(void)
1274 if (ao_radio_recv(bytes, 34, 0)) {
1275 if (bytes[33] & 0x80)
1279 printf (" RSSI %d", AO_RSSI_FROM_RADIO(bytes[32]));
1280 for (b = 0; b < 32; b++)
1281 printf (" %02x", bytes[b]);
1283 printf (" RSSI %02x LQI %02x", bytes[32], bytes[33]);
1289 #include <ao_aprs.h>
1294 #if PACKET_HAS_SLAVE
1295 ao_packet_slave_stop();
1302 #if CC1200_LOW_LEVEL_DEBUG
1304 ao_radio_strobe_test(void)
1309 if (ao_cmd_status != ao_cmd_success)
1311 r = ao_radio_strobe(ao_cmd_lex_i);
1312 printf ("Strobe %02x -> %02x (rdy %d state %d)\n",
1320 ao_radio_write_test(void)
1326 if (ao_cmd_status != ao_cmd_success)
1328 addr = ao_cmd_lex_i;
1330 if (ao_cmd_status != ao_cmd_success)
1332 data = ao_cmd_lex_i;
1333 printf ("Write %04x = %02x\n", addr, data);
1334 ao_radio_reg_write(addr, data);
1338 ao_radio_read_test(void)
1344 if (ao_cmd_status != ao_cmd_success)
1346 addr = ao_cmd_lex_i;
1347 data = ao_radio_reg_read(addr);
1348 printf ("Read %04x = %02x\n", addr, data);
1352 static const struct ao_cmds ao_radio_cmds[] = {
1353 { ao_radio_test_cmd, "C <1 start, 0 stop, none both>\0Radio carrier test" },
1356 { ao_radio_aprs, "G\0Send APRS packet" },
1358 { ao_radio_show, "R\0Show CC1200 status" },
1359 { ao_radio_beep, "b\0Emit an RDF beacon" },
1360 { ao_radio_packet, "p\0Send a test packet" },
1361 { ao_radio_test_recv, "q\0Recv a test packet" },
1363 #if CC1200_LOW_LEVEL_DEBUG
1364 { ao_radio_strobe_test, "A <value>\0Strobe radio" },
1365 { ao_radio_write_test, "W <addr> <value>\0Write radio reg" },
1366 { ao_radio_read_test, "B <addr>\0Read radio reg" },
1374 ao_radio_configured = 0;
1375 ao_spi_init_cs (AO_CC1200_SPI_CS_PORT, (1 << AO_CC1200_SPI_CS_PIN));
1378 AO_CC1200_SPI_CS_PORT->bsrr = ((uint32_t) (1 << AO_CC1200_SPI_CS_PIN));
1379 for (i = 0; i < 10000; i++) {
1380 if ((SPI_2_PORT->idr & (1 << SPI_2_MISO_PIN)) == 0)
1383 AO_CC1200_SPI_CS_PORT->bsrr = (1 << AO_CC1200_SPI_CS_PIN);
1385 ao_panic(AO_PANIC_SELF_TEST_CC1200);
1388 /* Enable the EXTI interrupt for the appropriate pin */
1389 ao_enable_port(AO_CC1200_INT_PORT);
1390 ao_exti_setup(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN,
1391 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH,
1394 ao_cmd_register(&ao_radio_cmds[0]);