2 * Copyright © 2013 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_cc115l.h>
21 #include <ao_telemetry.h>
24 #define AO_RADIO_MAX_SEND sizeof (struct ao_telemetry_generic)
26 uint8_t ao_radio_mutex;
28 static uint8_t ao_radio_fifo; /* fifo drained interrupt received */
29 static uint8_t ao_radio_done; /* tx done interrupt received */
30 static uint8_t ao_radio_wake; /* sleep address for radio interrupts */
31 static uint8_t ao_radio_abort; /* radio operation should abort */
33 /* Debugging commands */
34 #define CC115L_DEBUG 0
37 #define CC115L_TRACE 0
41 #define ao_radio_select() ao_spi_get_mask(AO_CC115L_SPI_CS_PORT,(1 << AO_CC115L_SPI_CS_PIN),AO_CC115L_SPI_BUS,AO_SPI_SPEED_1MHz)
42 #define ao_radio_deselect() ao_spi_put_mask(AO_CC115L_SPI_CS_PORT,(1 << AO_CC115L_SPI_CS_PIN),AO_CC115L_SPI_BUS)
43 #define ao_radio_spi_send(d,l) ao_spi_send((d), (l), AO_CC115L_SPI_BUS)
44 #define ao_radio_spi_send_fixed(d,l) ao_spi_send_fixed((d), (l), AO_CC115L_SPI_BUS)
45 #define ao_radio_spi_recv(d,l) ao_spi_recv((d), (l), AO_CC115L_SPI_BUS)
46 #define ao_radio_duplex(o,i,l) ao_spi_duplex((o), (i), (l), AO_CC115L_SPI_BUS)
48 struct ao_cc115l_reg {
55 static const struct ao_cc115l_reg ao_cc115l_reg[];
56 static const char *cc115l_state_name[];
58 enum ao_cc115l_trace_type {
66 struct ao_cc115l_trace {
67 enum ao_cc115l_trace_type type;
75 static struct ao_cc115l_trace trace[NUM_TRACE];
77 static int trace_disable;
79 static void trace_add(enum ao_cc115l_trace_type type, int16_t addr, int16_t value, const char *comment)
86 comment = ao_cc115l_reg[addr].name;
89 comment = cc115l_state_name[(value >> 4) & 0x7];
94 trace[trace_i].type = type;
95 trace[trace_i].addr = addr;
96 trace[trace_i].value = value;
97 trace[trace_i].comment = comment;
98 if (++trace_i == NUM_TRACE)
102 #define trace_add(t,a,v,c)
106 ao_radio_reg_read(uint8_t addr)
110 data[0] = ((1 << CC115L_READ) |
111 (0 << CC115L_BURST) |
114 ao_radio_spi_send(data, 1);
115 ao_radio_spi_recv(data, 1);
117 trace_add(trace_read, addr, data[0], NULL);
122 ao_radio_reg_write(uint8_t addr, uint8_t value)
126 trace_add(trace_write, addr, value, NULL);
127 data[0] = ((0 << CC115L_READ) |
128 (0 << CC115L_BURST) |
132 ao_radio_spi_send(data, 2);
138 ao_radio_burst_read_start (uint16_t addr)
142 data[0] = ((1 << CC115L_READ) |
143 (1 << CC115L_BURST) |
146 ao_radio_spi_send(data, 1);
150 ao_radio_burst_read_stop (void)
158 ao_radio_strobe(uint8_t addr)
163 ao_radio_duplex(&addr, &in, 1);
165 trace_add(trace_strobe, addr, in, NULL);
170 ao_radio_fifo_write_start(void)
172 uint8_t addr = ((0 << CC115L_READ) |
173 (1 << CC115L_BURST) |
178 ao_radio_duplex(&addr, &status, 1);
182 static inline uint8_t ao_radio_fifo_write_stop(uint8_t status) {
188 ao_radio_fifo_write(uint8_t *data, uint8_t len)
190 uint8_t status = ao_radio_fifo_write_start();
191 trace_add(trace_dma, CC115L_FIFO, len, NULL);
192 ao_radio_spi_send(data, len);
193 return ao_radio_fifo_write_stop(status);
197 ao_radio_tx_fifo_space(void)
199 return CC115L_FIFO_SIZE - (ao_radio_reg_read(CC115L_TXBYTES) & CC115L_TXBYTES_NUM_TX_BYTES_MASK);
204 ao_radio_status(void)
206 return ao_radio_strobe (CC115L_SNOP);
210 ao_radio_get_marcstate(void)
212 return ao_radio_reg_read(CC115L_MARCSTATE) & CC115L_MARCSTATE_MASK;
216 #define ao_radio_rdf_value 0x55
219 ao_radio_done_isr(void)
221 ao_exti_disable(AO_CC115L_DONE_INT_PORT, AO_CC115L_DONE_INT_PIN);
222 trace_add(trace_line, __LINE__, 0, "done_isr");
224 ao_wakeup(&ao_radio_wake);
228 ao_radio_fifo_isr(void)
230 ao_exti_disable(AO_CC115L_FIFO_INT_PORT, AO_CC115L_FIFO_INT_PIN);
231 trace_add(trace_line, __LINE__, 0, "fifo_isr");
233 ao_wakeup(&ao_radio_wake);
241 uint8_t state = ao_radio_strobe(CC115L_SIDLE);
242 if ((state >> CC115L_STATUS_STATE) == CC115L_STATUS_STATE_IDLE)
244 if ((state >> CC115L_STATUS_STATE) == CC115L_STATUS_STATE_TX_FIFO_UNDERFLOW)
245 ao_radio_strobe(CC115L_SFTX);
247 /* Flush any pending TX bytes */
248 ao_radio_strobe(CC115L_SFTX);
252 * Packet deviation is 20.5kHz
254 * fdev = fosc >> 17 * (8 + dev_m) << dev_e
256 * 26e6 / (2 ** 17) * (8 + 5) * (2 ** 3) = 20630Hz
259 #define PACKET_DEV_E 3
260 #define PACKET_DEV_M 5
263 * For our packet data, set the symbol rate to 38400 Baud
265 * (256 + DATARATE_M) * 2 ** DATARATE_E
266 * Rdata = -------------------------------------- * fosc
269 * (256 + 131) * (2 ** 10) / (2**28) * 26e6 = 38383
272 * DATARATE_E_384 = 10
276 #define PACKET_DRATE_M 131
278 #define PACKET_DRATE_E_384 10
279 #define PACKET_DRATE_E_96 8
280 #define PACKET_DRATE_E_24 6
282 static const uint16_t packet_rate_setup[] = {
283 [AO_RADIO_RATE_38400] = ((0xf << 4) |
284 (PACKET_DRATE_E_384 << CC115L_MDMCFG4_DRATE_E)),
286 [AO_RADIO_RATE_9600] = ((0xf << 4) |
287 (PACKET_DRATE_E_96 << CC115L_MDMCFG4_DRATE_E)),
289 [AO_RADIO_RATE_2400] = ((0xf << 4) |
290 (PACKET_DRATE_E_24 << CC115L_MDMCFG4_DRATE_E)),
293 static const uint16_t packet_setup[] = {
294 CC115L_DEVIATN, ((PACKET_DEV_E << CC115L_DEVIATN_DEVIATION_E) |
295 (PACKET_DEV_M << CC115L_DEVIATN_DEVIATION_M)),
296 CC115L_MDMCFG3, (PACKET_DRATE_M),
297 CC115L_MDMCFG2, (0x00 |
298 (CC115L_MDMCFG2_MOD_FORMAT_GFSK << CC115L_MDMCFG2_MOD_FORMAT) |
299 (0 << CC115L_MDMCFG2_MANCHESTER_EN) |
300 (CC115L_MDMCFG2_SYNC_MODE_16BITS << CC115L_MDMCFG2_SYNC_MODE)),
305 * RDF deviation is 5kHz
307 * fdev = fosc >> 17 * (8 + dev_m) << dev_e
309 * 26e6 / (2 ** 17) * (8 + 4) * (2 ** 1) = 4761Hz
316 * For our RDF beacon, set the symbol rate to 2kBaud (for a 1kHz tone)
318 * (256 + DATARATE_M) * 2 ** DATARATE_E
319 * Rdata = -------------------------------------- * fosc
322 * (256 + 67) * (2 ** 6) / (2**28) * 26e6 = 2002
327 #define RDF_DRATE_E 6
328 #define RDF_DRATE_M 67
330 static const uint16_t rdf_setup[] = {
331 CC115L_DEVIATN, ((RDF_DEV_E << CC115L_DEVIATN_DEVIATION_E) |
332 (RDF_DEV_M << CC115L_DEVIATN_DEVIATION_M)),
333 CC115L_MDMCFG4, ((0xf << 4) |
334 (RDF_DRATE_E << CC115L_MDMCFG4_DRATE_E)),
335 CC115L_MDMCFG3, (RDF_DRATE_M),
336 CC115L_MDMCFG2, (0x00 |
337 (CC115L_MDMCFG2_MOD_FORMAT_GFSK << CC115L_MDMCFG2_MOD_FORMAT) |
338 (0 << CC115L_MDMCFG2_MANCHESTER_EN) |
339 (CC115L_MDMCFG2_SYNC_MODE_NONE << CC115L_MDMCFG2_SYNC_MODE)),
343 * APRS deviation is 3kHz
345 * 26e6 / (2 ** 17) * (8 + 7) * (2 ** 0) = 2975
352 * For our APRS beacon, set the symbol rate to 9.6kBaud (8x oversampling for 1200 baud data rate)
354 * (256 + DATARATE_M) * 2 ** DATARATE_E
355 * Rdata = -------------------------------------- * fosc
358 * (256 + 131) * (2 ** 8) / (2**28) * 26e6 = 9596
364 #define APRS_DRATE_E 8
365 #define APRS_DRATE_M 131
367 static const uint16_t aprs_setup[] = {
368 CC115L_DEVIATN, ((APRS_DEV_E << CC115L_DEVIATN_DEVIATION_E) |
369 (APRS_DEV_M << CC115L_DEVIATN_DEVIATION_M)),
370 CC115L_MDMCFG4, ((0xf << 4) |
371 (APRS_DRATE_E << CC115L_MDMCFG4_DRATE_E)),
372 CC115L_MDMCFG3, (APRS_DRATE_M),
373 CC115L_MDMCFG2, (0x00 |
374 (CC115L_MDMCFG2_MOD_FORMAT_GFSK << CC115L_MDMCFG2_MOD_FORMAT) |
375 (0 << CC115L_MDMCFG2_MANCHESTER_EN) |
376 (CC115L_MDMCFG2_SYNC_MODE_NONE << CC115L_MDMCFG2_SYNC_MODE)),
379 #define AO_PKTCTRL0_INFINITE ((CC115L_PKTCTRL0_PKT_FORMAT_NORMAL << CC115L_PKTCTRL0_PKT_FORMAT) | \
380 (0 << CC115L_PKTCTRL0_PKT_CRC_EN) | \
381 (CC115L_PKTCTRL0_PKT_LENGTH_CONFIG_INFINITE << CC115L_PKTCTRL0_PKT_LENGTH_CONFIG))
382 #define AO_PKTCTRL0_FIXED ((CC115L_PKTCTRL0_PKT_FORMAT_NORMAL << CC115L_PKTCTRL0_PKT_FORMAT) | \
383 (0 << CC115L_PKTCTRL0_PKT_CRC_EN) | \
384 (CC115L_PKTCTRL0_PKT_LENGTH_CONFIG_FIXED << CC115L_PKTCTRL0_PKT_LENGTH_CONFIG))
386 static uint16_t ao_radio_mode;
390 * These set the data rate and modulation parameters
392 #define AO_RADIO_MODE_BITS_PACKET_TX 1
393 #define AO_RADIO_MODE_BITS_RDF 2
394 #define AO_RADIO_MODE_BITS_APRS 4
397 * Flips between infinite packet mode and fixed packet mode;
398 * we use infinite mode until the sender gives us the
401 #define AO_RADIO_MODE_BITS_INFINITE 40
402 #define AO_RADIO_MODE_BITS_FIXED 80
404 #define AO_RADIO_MODE_NONE 0
406 #define AO_RADIO_MODE_RDF AO_RADIO_MODE_BITS_RDF
407 #define AO_RADIO_MODE_PACKET_TX AO_RADIO_MODE_BITS_PACKET_TX
408 #define AO_RADIO_MODE_APRS AO_RADIO_MODE_BITS_APRS
411 ao_radio_set_mode(uint16_t new_mode)
416 if (new_mode == ao_radio_mode)
419 changes = new_mode & (~ao_radio_mode);
420 if (changes & AO_RADIO_MODE_BITS_PACKET_TX) {
421 ao_radio_reg_write(CC115L_MDMCFG4, packet_rate_setup[ao_config.radio_rate]);
423 for (i = 0; i < sizeof (packet_setup) / sizeof (packet_setup[0]); i += 2)
424 ao_radio_reg_write(packet_setup[i], packet_setup[i+1]);
427 if (changes & AO_RADIO_MODE_BITS_RDF)
428 for (i = 0; i < sizeof (rdf_setup) / sizeof (rdf_setup[0]); i += 2)
429 ao_radio_reg_write(rdf_setup[i], rdf_setup[i+1]);
431 if (changes & AO_RADIO_MODE_BITS_APRS)
432 for (i = 0; i < sizeof (aprs_setup) / sizeof (aprs_setup[0]); i += 2)
433 ao_radio_reg_write(aprs_setup[i], aprs_setup[i+1]);
435 if (changes & AO_RADIO_MODE_BITS_INFINITE)
436 ao_radio_reg_write(CC115L_PKTCTRL0, AO_PKTCTRL0_INFINITE);
438 if (changes & AO_RADIO_MODE_BITS_FIXED)
439 ao_radio_reg_write(CC115L_PKTCTRL0, AO_PKTCTRL0_FIXED);
441 ao_radio_mode = new_mode;
444 /***************************************************************
445 * SmartRF Studio(tm) Export
447 * Radio register settings specifed with address, value
451 ***************************************************************/
453 static const uint16_t radio_setup[] = {
455 /* High when FIFO is above threshold, low when fifo is below threshold */
456 AO_CC115L_FIFO_INT_GPIO_IOCFG, CC115L_IOCFG_GPIO_CFG_TXFIFO_THR,
458 /* High when transmitter is running, low when off */
459 AO_CC115L_DONE_INT_GPIO_IOCFG, CC115L_IOCFG_GPIO_CFG_PA_PD | (1 << CC115L_IOCFG_GPIO_INV),
461 CC115L_FIFOTHR, 0x47, /* TX FIFO Thresholds */
462 CC115L_MDMCFG1, (0x00 |
463 (CC115L_MDMCFG1_NUM_PREAMBLE_4 << CC115L_MDMCFG1_NUM_PREAMBLE) |
464 (1 << CC115L_MDMCFG1_CHANSPC_E)),
465 CC115L_MDMCFG0, 248, /* Channel spacing M value (100kHz channels) */
466 CC115L_MCSM0, 0x38, /* Main Radio Control State Machine Configuration */
467 CC115L_RESERVED_0X20, 0xfb, /* Use setting from SmartRF Studio */
468 CC115L_FSCAL3, 0xe9, /* Frequency Synthesizer Calibration */
469 CC115L_FSCAL2, 0x2a, /* Frequency Synthesizer Calibration */
470 CC115L_FSCAL1, 0x00, /* Frequency Synthesizer Calibration */
471 CC115L_FSCAL0, 0x1f, /* Frequency Synthesizer Calibration */
472 CC115L_TEST2, 0x81, /* Various Test Settings */
473 CC115L_TEST1, 0x35, /* Various Test Settings */
474 CC115L_TEST0, 0x09, /* Various Test Settings */
477 static uint8_t ao_radio_configured = 0;
484 ao_radio_strobe(CC115L_SRES);
485 ao_delay(AO_MS_TO_TICKS(10));
487 for (i = 0; i < sizeof (radio_setup) / sizeof (radio_setup[0]); i += 2)
488 ao_radio_reg_write(radio_setup[i], radio_setup[i+1]);
494 ao_radio_strobe(CC115L_SCAL);
496 ao_radio_configured = 1;
500 ao_radio_set_len(uint8_t len)
502 static uint8_t last_len;
504 if (len != last_len) {
505 ao_radio_reg_write(CC115L_PKTLEN, len);
513 static uint32_t last_radio_setting;
514 static uint8_t last_radio_rate;
516 ao_mutex_get(&ao_radio_mutex);
517 if (!ao_radio_configured)
519 if (ao_config.radio_setting != last_radio_setting) {
520 ao_radio_reg_write(CC115L_FREQ2, ao_config.radio_setting >> 16);
521 ao_radio_reg_write(CC115L_FREQ1, ao_config.radio_setting >> 8);
522 ao_radio_reg_write(CC115L_FREQ0, ao_config.radio_setting);
523 last_radio_setting = ao_config.radio_setting;
525 if (ao_config.radio_rate != last_radio_rate) {
526 ao_radio_mode &= ~AO_RADIO_MODE_BITS_PACKET_TX;
527 last_radio_rate = ao_config.radio_rate;
532 _ao_radio_send_lots(ao_radio_fill_func fill, uint8_t mode);
534 #define ao_radio_put() ao_mutex_put(&ao_radio_mutex)
536 struct ao_radio_tone {
541 struct ao_radio_tone *ao_radio_tone;
542 uint8_t ao_radio_tone_count;
543 uint8_t ao_radio_tone_current;
544 uint8_t ao_radio_tone_offset;
547 ao_radio_tone_fill(uint8_t *buf, int16_t len)
553 struct ao_radio_tone *t;
555 /* Figure out how many to send of the current value */
556 t = &ao_radio_tone[ao_radio_tone_current];
557 this_time = t->len - ao_radio_tone_offset;
562 memset(buf, t->value, this_time);
566 ao_radio_tone_offset += this_time;
569 if (ao_radio_tone_offset >= t->len) {
570 ao_radio_tone_offset = 0;
571 ao_radio_tone_current++;
572 if (ao_radio_tone_current >= ao_radio_tone_count) {
573 trace_add(trace_line, __LINE__, ret, "done with tone");
578 trace_add(trace_line, __LINE__, ret, "got some tone");
583 ao_radio_tone_run(struct ao_radio_tone *tones, int ntones)
586 ao_radio_tone = tones;
587 ao_radio_tone_current = 0;
588 ao_radio_tone_offset = 0;
589 ao_radio_tone_count = ntones;
590 _ao_radio_send_lots(ao_radio_tone_fill, AO_RADIO_MODE_RDF);
597 struct ao_radio_tone tone;
599 tone.value = ao_radio_rdf_value;
600 tone.len = AO_RADIO_RDF_LEN;
601 ao_radio_tone_run(&tone, 1);
605 ao_radio_continuity(uint8_t c)
607 struct ao_radio_tone tones[7];
611 for (i = 0; i < 3; i++) {
612 tones[count].value = 0x00;
613 tones[count].len = AO_RADIO_CONT_PAUSE_LEN;
616 tones[count].value = ao_radio_rdf_value;
618 tones[count].value = 0x00;
619 tones[count].len = AO_RADIO_CONT_TONE_LEN;
622 tones[count].value = 0x00;
623 tones[count].len = AO_RADIO_CONT_PAUSE_LEN;
625 ao_radio_tone_run(tones, count);
629 ao_radio_rdf_abort(void)
632 ao_wakeup(&ao_radio_wake);
635 #define POWER_STEP 0x08
638 #define RADIO_POWER ao_config.radio_power
640 #define RADIO_POWER 0xc0
648 ao_radio_reg_write(CC115L_PA, 0);
649 ao_radio_strobe(CC115L_STX);
650 for (power = POWER_STEP; power < RADIO_POWER; power += POWER_STEP)
651 ao_radio_reg_write(CC115L_PA, power);
652 if (power != RADIO_POWER)
653 ao_radio_reg_write(CC115L_PA, RADIO_POWER);
657 ao_radio_test_cmd(void)
660 static uint8_t radio_on;
662 if (ao_cmd_lex_c != '\n') {
664 mode = (uint8_t) ao_cmd_lex_u32;
667 if ((mode & 2) && !radio_on) {
669 ao_monitor_disable();
672 ao_packet_slave_stop();
675 ao_radio_strobe(CC115L_SFTX);
676 ao_radio_set_len(0xff);
677 ao_radio_set_mode(AO_RADIO_MODE_RDF);
682 printf ("Hit a character to stop..."); flush();
686 if ((mode & 1) && radio_on) {
697 static inline int16_t
698 ao_radio_gpio_bits(void)
700 return ((ao_gpio_get(AO_CC115L_DONE_INT_PORT, AO_CC115L_DONE_INT_PIN, AO_CC115L_DONE_INT) << 1) |
701 ao_gpio_get(AO_CC115L_FIFO_INT_PORT, AO_CC115L_FIFO_INT_PIN, AO_CC115L_FIFO_INT));
706 ao_radio_wait_fifo(void)
708 ao_arch_block_interrupts();
709 while (!ao_radio_fifo && !ao_radio_done && !ao_radio_abort) {
710 trace_add(trace_line, __LINE__, ao_radio_gpio_bits(), "wait_fifo");
711 ao_sleep(&ao_radio_wake);
713 ao_arch_release_interrupts();
714 trace_add(trace_line, __LINE__, ao_radio_gpio_bits(), "wake bits");
715 trace_add(trace_line, __LINE__, ao_radio_fifo, "wake fifo");
716 trace_add(trace_line, __LINE__, ao_radio_done, "wake done");
717 trace_add(trace_line, __LINE__, ao_radio_abort, "wake abort");
721 ao_radio_wait_done(void)
723 ao_arch_block_interrupts();
724 while (!ao_radio_done && !ao_radio_abort) {
725 trace_add(trace_line, __LINE__, ao_radio_gpio_bits(), "wait_done");
726 ao_sleep(&ao_radio_wake);
728 ao_arch_release_interrupts();
729 trace_add(trace_line, __LINE__, ao_radio_gpio_bits(), "wake bits");
730 trace_add(trace_line, __LINE__, ao_radio_fifo, "wake fifo");
731 trace_add(trace_line, __LINE__, ao_radio_done, "wake done");
732 trace_add(trace_line, __LINE__, ao_radio_abort, "wake abort");
735 static uint8_t tx_data[(AO_RADIO_MAX_SEND + 4) * 2];
737 static uint8_t *ao_radio_send_buf;
738 static int16_t ao_radio_send_len;
741 ao_radio_send_fill(uint8_t *buf, int16_t len)
745 this_time = ao_radio_send_len;
748 memcpy(buf, ao_radio_send_buf, this_time);
749 ao_radio_send_buf += this_time;
750 ao_radio_send_len -= this_time;
751 if (ao_radio_send_len == 0)
757 ao_radio_send(const void *d, uint8_t size)
760 ao_radio_send_len = ao_fec_encode(d, size, tx_data);
761 ao_radio_send_buf = tx_data;
762 _ao_radio_send_lots(ao_radio_send_fill, AO_RADIO_MODE_PACKET_TX);
766 #define AO_RADIO_LOTS 64
769 _ao_radio_send_lots(ao_radio_fill_func fill, uint8_t mode)
771 uint8_t buf[AO_RADIO_LOTS], *b;
778 fifo_space = CC115L_FIFO_SIZE;
781 ao_radio_strobe(CC115L_SFTX);
786 cnt = (*fill)(buf, sizeof(buf));
787 trace_add(trace_line, __LINE__, cnt, "send data count");
794 /* At the last buffer, set the total length */
796 ao_radio_set_len(total & 0xff);
797 ao_radio_set_mode(mode | AO_RADIO_MODE_BITS_FIXED);
799 ao_radio_set_len(0xff);
800 ao_radio_set_mode(mode | AO_RADIO_MODE_BITS_INFINITE);
805 uint8_t this_len = cnt;
807 /* Wait for some space in the fifo */
808 while (!ao_radio_abort && (fifo_space = ao_radio_tx_fifo_space()) == 0) {
809 trace_add(trace_line, __LINE__, this_len, "wait for space");
810 ao_radio_wait_fifo();
812 if (ao_radio_abort || ao_radio_done)
814 trace_add(trace_line, __LINE__, fifo_space, "got space");
815 if (this_len > fifo_space)
816 this_len = fifo_space;
822 ao_radio_fifo_write(b, this_len);
825 ao_exti_enable(AO_CC115L_FIFO_INT_PORT, AO_CC115L_FIFO_INT_PIN);
826 ao_exti_enable(AO_CC115L_DONE_INT_PORT, AO_CC115L_DONE_INT_PIN);
833 if (ao_radio_abort || ao_radio_done)
838 ao_radio_wait_done();
843 ao_radio_send_aprs(ao_radio_fill_func fill)
846 _ao_radio_send_lots(fill, AO_RADIO_MODE_APRS);
851 static const char *cc115l_state_name[] = {
852 [CC115L_STATUS_STATE_IDLE] = "IDLE",
853 [CC115L_STATUS_STATE_TX] = "TX",
854 [CC115L_STATUS_STATE_FSTXON] = "FSTXON",
855 [CC115L_STATUS_STATE_CALIBRATE] = "CALIBRATE",
856 [CC115L_STATUS_STATE_SETTLING] = "SETTLING",
857 [CC115L_STATUS_STATE_TX_FIFO_UNDERFLOW] = "TX_FIFO_UNDERFLOW",
860 static const struct ao_cc115l_reg ao_cc115l_reg[] = {
861 { .addr = CC115L_IOCFG2, .name = "IOCFG2" },
862 { .addr = CC115L_IOCFG1, .name = "IOCFG1" },
863 { .addr = CC115L_IOCFG0, .name = "IOCFG0" },
864 { .addr = CC115L_FIFOTHR, .name = "FIFOTHR" },
865 { .addr = CC115L_SYNC1, .name = "SYNC1" },
866 { .addr = CC115L_SYNC0, .name = "SYNC0" },
867 { .addr = CC115L_PKTLEN, .name = "PKTLEN" },
868 { .addr = CC115L_PKTCTRL0, .name = "PKTCTRL0" },
869 { .addr = CC115L_CHANNR, .name = "CHANNR" },
870 { .addr = CC115L_FSCTRL0, .name = "FSCTRL0" },
871 { .addr = CC115L_FREQ2, .name = "FREQ2" },
872 { .addr = CC115L_FREQ1, .name = "FREQ1" },
873 { .addr = CC115L_FREQ0, .name = "FREQ0" },
874 { .addr = CC115L_MDMCFG4, .name = "MDMCFG4" },
875 { .addr = CC115L_MDMCFG3, .name = "MDMCFG3" },
876 { .addr = CC115L_MDMCFG2, .name = "MDMCFG2" },
877 { .addr = CC115L_MDMCFG1, .name = "MDMCFG1" },
878 { .addr = CC115L_MDMCFG0, .name = "MDMCFG0" },
879 { .addr = CC115L_DEVIATN, .name = "DEVIATN" },
880 { .addr = CC115L_MCSM1, .name = "MCSM1" },
881 { .addr = CC115L_MCSM0, .name = "MCSM0" },
882 { .addr = CC115L_RESERVED_0X20, .name = "RESERVED_0X20" },
883 { .addr = CC115L_FREND0, .name = "FREND0" },
884 { .addr = CC115L_FSCAL3, .name = "FSCAL3" },
885 { .addr = CC115L_FSCAL2, .name = "FSCAL2" },
886 { .addr = CC115L_FSCAL1, .name = "FSCAL1" },
887 { .addr = CC115L_FSCAL0, .name = "FSCAL0" },
888 { .addr = CC115L_RESERVED_0X29, .name = "RESERVED_0X29" },
889 { .addr = CC115L_RESERVED_0X2A, .name = "RESERVED_0X2A" },
890 { .addr = CC115L_RESERVED_0X2B, .name = "RESERVED_0X2B" },
891 { .addr = CC115L_TEST2, .name = "TEST2" },
892 { .addr = CC115L_TEST1, .name = "TEST1" },
893 { .addr = CC115L_TEST0, .name = "TEST0" },
894 { .addr = CC115L_PARTNUM, .name = "PARTNUM" },
895 { .addr = CC115L_VERSION, .name = "VERSION" },
896 { .addr = CC115L_MARCSTATE, .name = "MARCSTATE" },
897 { .addr = CC115L_PKTSTATUS, .name = "PKTSTATUS" },
898 { .addr = CC115L_TXBYTES, .name = "TXBYTES" },
899 { .addr = CC115L_PA, .name = "PA" },
902 #define AO_NUM_CC115L_REG (sizeof ao_cc115l_reg / sizeof ao_cc115l_reg[0])
904 static void ao_radio_show(void) {
905 uint8_t status = ao_radio_status();
909 status = ao_radio_status();
910 printf ("Status: %02x\n", status);
911 printf ("CHIP_RDY: %d\n", (status >> CC115L_STATUS_CHIP_RDY) & 1);
912 printf ("STATE: %s\n", cc115l_state_name[(status >> CC115L_STATUS_STATE) & CC115L_STATUS_STATE_MASK]);
913 printf ("MARC: %02x\n", ao_radio_get_marcstate());
915 for (i = 0; i < AO_NUM_CC115L_REG; i++)
916 printf ("\t%02x %-20.20s\n", ao_radio_reg_read(ao_cc115l_reg[i].addr), ao_cc115l_reg[i].name);
920 static void ao_radio_beep(void) {
924 static void ao_radio_packet(void) {
925 static const uint8_t packet[] = {
927 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
928 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
929 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
930 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
936 ao_radio_send(packet, sizeof (packet));
947 ao_packet_slave_stop();
952 #endif /* CC115L_DEBUG */
954 static const struct ao_cmds ao_radio_cmds[] = {
955 { ao_radio_test_cmd, "C <1 start, 0 stop, none both>\0Radio carrier test" },
958 { ao_radio_aprs, "G\0Send APRS packet" },
960 { ao_radio_show, "R\0Show CC115L status" },
961 { ao_radio_beep, "b\0Emit an RDF beacon" },
962 { ao_radio_packet, "p\0Send a test packet" },
974 ao_radio_configured = 0;
975 ao_spi_init_cs (AO_CC115L_SPI_CS_PORT, (1 << AO_CC115L_SPI_CS_PIN));
978 AO_CC115L_SPI_CS_PORT->bsrr = ((uint32_t) (1 << AO_CC115L_SPI_CS_PIN));
979 for (i = 0; i < 10000; i++) {
980 if ((SPI_2_PORT->idr & (1 << SPI_2_MISO_PIN)) == 0)
983 AO_CC115L_SPI_CS_PORT->bsrr = (1 << AO_CC115L_SPI_CS_PIN);
985 ao_panic(AO_PANIC_SELF_TEST_CC115L);
988 /* Enable the fifo threhold interrupt pin */
989 ao_enable_port(AO_CC115L_FIFO_INT_PORT);
990 ao_exti_setup(AO_CC115L_FIFO_INT_PORT, AO_CC115L_FIFO_INT_PIN,
991 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH,
994 /* Enable the tx done interrupt pin */
995 ao_enable_port(AO_CC115L_DONE_INT_PORT);
996 ao_exti_setup(AO_CC115L_DONE_INT_PORT, AO_CC115L_DONE_INT_PIN,
997 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_MED,
1002 ao_cmd_register(&ao_radio_cmds[0]);