X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=blobdiff_plain;f=src%2Fcc1111%2Fao_radio.c;h=166d14d5e9e67cd5e4b92828714bb0bc64af0342;hp=75f241d4d2391e3664181fc3a0b230919e283e89;hb=382b3ef62a09e580834b07faf9ed2d00e5ce1621;hpb=c8a00bb9ccdf0d4257f037c2bf996ce5e6b0b0c0 diff --git a/src/cc1111/ao_radio.c b/src/cc1111/ao_radio.c index 75f241d4..166d14d5 100644 --- a/src/cc1111/ao_radio.c +++ b/src/cc1111/ao_radio.c @@ -3,7 +3,8 @@ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of @@ -16,6 +17,9 @@ */ #include "ao.h" +#if HAS_PAD +#include +#endif /* Values from SmartRF® Studio for: * @@ -37,6 +41,42 @@ #define IF_FREQ_CONTROL 6 /* + * http://www.ntia.doc.gov/files/ntia/publications/84-168.pdf + * + * Necessary bandwidth for a FSK modulated signal: + * + * bw = 2.6d + 0.55b 1.5 < m < 5.5 + * bw = 2.1d + 1.9b 5.5 < m < 20 + * + * b is the modulation rate in bps + * d is the peak deviation (from the center) + * + * m = 2d / b + * + * 20.5 kHz deviation 38.4kbps signal: + * + * m = 41 / 38.4, which is < 5.5: + * + * bw = 2.6 * 20.5 + 0.55 * 38.4 = 74.42kHz + * + * M = 1, E = 3, bw = 75kHz + * + * 5.125 kHz deviation, 9.6kbps signal + * + * m = 10.25 / 9.6, which is < 5.5: + * + * bw = 2.6 * 5.125 + 0.55 * 9.6 = 18.6kHz + * + * M = 2, E = 3, bw = 53.6kHz + * + * 1.28125kHz deviation, 2.4kbps signal + * + * m = 2.565 / 2.4, which is < 5.5: + * + * bw = 2.6 * 20.5 + 1.9 * 2.4 = 47.61kHz + * + * M = 3, E = 3, bw = 53.6kHz + * * For channel bandwidth of 93.75 kHz, the CHANBW_E and CHANBW_M values are * * BW = 24e6 / (8 * (4 + M) * 2 ** E) @@ -44,7 +84,9 @@ * So, M = 0 and E = 3 */ -#define CHANBW_M 0 +#define CHANBW_M_384 1 +#define CHANBW_M_96 3 +#define CHANBW_M_24 3 #define CHANBW_E 3 /* @@ -52,22 +94,41 @@ * * R = (256 + M) * 2** E * 24e6 / 2**28 * - * So M is 163 and E is 10 + * So for 38360kBaud, M is 163 and E is 10 */ -#define DRATE_E 10 #define DRATE_M 163 +#define DRATE_E_384 10 + +/* For 9600 baud, M is 163 and E is 8 + */ + +#define DRATE_E_96 8 + +/* For 2400 baud, M is 163 and E is 6 + */ + +#define DRATE_E_24 6 + /* * For a channel deviation of 20.5kHz, the DEVIATION_E and DEVIATION_M values are: * * F = 24e6/2**17 * (8 + DEVIATION_M) * 2**DEVIATION_E * - * So M is 6 and E is 3 + * For 20.5kHz deviation, M is 6 and E is 3 + * For 5.125kHz deviation, M is 6 and E is 1 + * For 1.28125kHz deviation, M is 0 and E is 0 */ -#define DEVIATION_M 6 -#define DEVIATION_E 3 +#define DEVIATION_M_384 6 +#define DEVIATION_E_384 3 + +#define DEVIATION_M_96 6 +#define DEVIATION_E_96 1 + +#define DEVIATION_M_24 0 +#define DEVIATION_E_24 0 /* * For our RDF beacon, set the symbol rate to 2kBaud (for a 1kHz tone), @@ -119,13 +180,10 @@ static __code uint8_t radio_setup[] = { RF_FSCTRL1_OFF, (IF_FREQ_CONTROL << RF_FSCTRL1_FREQ_IF_SHIFT), RF_FSCTRL0_OFF, (0 << RF_FSCTRL0_FREQOFF_SHIFT), - RF_MDMCFG4_OFF, ((CHANBW_E << RF_MDMCFG4_CHANBW_E_SHIFT) | - (CHANBW_M << RF_MDMCFG4_CHANBW_M_SHIFT) | - (DRATE_E << RF_MDMCFG4_DRATE_E_SHIFT)), RF_MDMCFG3_OFF, (DRATE_M << RF_MDMCFG3_DRATE_M_SHIFT), - RF_MDMCFG2_OFF, (RF_MDMCFG2_DEM_DCFILT_OFF | + RF_MDMCFG2_OFF, (RF_MDMCFG2_DEM_DCFILT_ON | RF_MDMCFG2_MOD_FORMAT_GFSK | - RF_MDMCFG2_SYNC_MODE_15_16_THRES), + RF_MDMCFG2_SYNC_MODE_15_16), RF_MDMCFG1_OFF, (RF_MDMCFG1_FEC_EN | RF_MDMCFG1_NUM_PREAMBLE_4 | (2 << RF_MDMCFG1_CHANSPC_E_SHIFT)), @@ -133,9 +191,6 @@ static __code uint8_t radio_setup[] = { RF_CHANNR_OFF, 0, - RF_DEVIATN_OFF, ((DEVIATION_E << RF_DEVIATN_DEVIATION_E_SHIFT) | - (DEVIATION_M << RF_DEVIATN_DEVIATION_M_SHIFT)), - /* SmartRF says set LODIV_BUF_CURRENT_TX to 0 * And, we're not using power ramping, so use PA_POWER 0 */ @@ -152,8 +207,8 @@ static __code uint8_t radio_setup[] = { RF_FSCAL1_OFF, 0x00, RF_FSCAL0_OFF, 0x1F, - RF_TEST2_OFF, 0x88, - RF_TEST1_OFF, 0x31, + RF_TEST2_OFF, RF_TEST2_RX_LOW_DATA_RATE_MAGIC, + RF_TEST1_OFF, RF_TEST1_RX_LOW_DATA_RATE_MAGIC, RF_TEST0_OFF, 0x09, /* default sync values */ @@ -184,10 +239,16 @@ static __code uint8_t radio_setup[] = { RF_BSCFG_BS_POST_KI_PRE_KI| RF_BSCFG_BS_POST_KP_PRE_KP| RF_BSCFG_BS_LIMIT_0), - RF_AGCCTRL2_OFF, 0x43, - RF_AGCCTRL1_OFF, 0x40, - RF_AGCCTRL0_OFF, 0x91, - + RF_AGCCTRL2_OFF, (RF_AGCCTRL2_MAX_DVGA_GAIN_ALL| + RF_AGCCTRL2_MAX_LNA_GAIN_0| + RF_AGCCTRL2_MAGN_TARGET_33dB), + RF_AGCCTRL1_OFF, (RF_AGCCTRL1_AGC_LNA_PRIORITY_0 | + RF_AGCCTRL1_CARRIER_SENSE_REL_THR_DISABLE | + RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_0DB), + RF_AGCCTRL0_OFF, (RF_AGCCTRL0_HYST_LEVEL_NONE | + RF_AGCCTRL0_WAIT_TIME_8 | + RF_AGCCTRL0_AGC_FREEZE_NORMAL | + RF_AGCCTRL0_FILTER_LENGTH_8), RF_IOCFG2_OFF, 0x00, RF_IOCFG1_OFF, 0x00, RF_IOCFG0_OFF, 0x00, @@ -195,12 +256,12 @@ static __code uint8_t radio_setup[] = { static __code uint8_t rdf_setup[] = { RF_MDMCFG4_OFF, ((CHANBW_E << RF_MDMCFG4_CHANBW_E_SHIFT) | - (CHANBW_M << RF_MDMCFG4_CHANBW_M_SHIFT) | + (CHANBW_M_384 << RF_MDMCFG4_CHANBW_M_SHIFT) | (RDF_DRATE_E << RF_MDMCFG4_DRATE_E_SHIFT)), RF_MDMCFG3_OFF, (RDF_DRATE_M << RF_MDMCFG3_DRATE_M_SHIFT), RF_MDMCFG2_OFF, (RF_MDMCFG2_DEM_DCFILT_OFF | RF_MDMCFG2_MOD_FORMAT_GFSK | - RF_MDMCFG2_SYNC_MODE_15_16_THRES), + RF_MDMCFG2_SYNC_MODE_NONE), RF_MDMCFG1_OFF, (RF_MDMCFG1_FEC_DIS | RF_MDMCFG1_NUM_PREAMBLE_2 | (2 << RF_MDMCFG1_CHANSPC_E_SHIFT)), @@ -209,26 +270,30 @@ static __code uint8_t rdf_setup[] = { (RDF_DEVIATION_M << RF_DEVIATN_DEVIATION_M_SHIFT)), /* packet length is set in-line */ - RF_PKTCTRL1_OFF, ((1 << PKTCTRL1_PQT_SHIFT)| + RF_PKTCTRL1_OFF, ((0 << PKTCTRL1_PQT_SHIFT)| PKTCTRL1_ADR_CHK_NONE), RF_PKTCTRL0_OFF, (RF_PKTCTRL0_PKT_FORMAT_NORMAL| RF_PKTCTRL0_LENGTH_CONFIG_FIXED), }; static __code uint8_t fixed_pkt_setup[] = { +#if !HAS_RADIO_RATE RF_MDMCFG4_OFF, ((CHANBW_E << RF_MDMCFG4_CHANBW_E_SHIFT) | - (CHANBW_M << RF_MDMCFG4_CHANBW_M_SHIFT) | - (DRATE_E << RF_MDMCFG4_DRATE_E_SHIFT)), + (CHANBW_M_384 << RF_MDMCFG4_CHANBW_M_SHIFT) | + (DRATE_E_384 << RF_MDMCFG4_DRATE_E_SHIFT)), +#endif RF_MDMCFG3_OFF, (DRATE_M << RF_MDMCFG3_DRATE_M_SHIFT), - RF_MDMCFG2_OFF, (RF_MDMCFG2_DEM_DCFILT_OFF | + RF_MDMCFG2_OFF, (RF_MDMCFG2_DEM_DCFILT_ON | RF_MDMCFG2_MOD_FORMAT_GFSK | - RF_MDMCFG2_SYNC_MODE_15_16_THRES), + RF_MDMCFG2_SYNC_MODE_15_16), RF_MDMCFG1_OFF, (RF_MDMCFG1_FEC_EN | RF_MDMCFG1_NUM_PREAMBLE_4 | (2 << RF_MDMCFG1_CHANSPC_E_SHIFT)), - RF_DEVIATN_OFF, ((DEVIATION_E << RF_DEVIATN_DEVIATION_E_SHIFT) | - (DEVIATION_M << RF_DEVIATN_DEVIATION_M_SHIFT)), +#if !HAS_RADIO_RATE + RF_DEVIATN_OFF, ((DEVIATION_E_384 << RF_DEVIATN_DEVIATION_E_SHIFT) | + (DEVIATION_M_384 << RF_DEVIATN_DEVIATION_M_SHIFT)), +#endif /* max packet length -- now set inline */ RF_PKTCTRL1_OFF, ((1 << PKTCTRL1_PQT_SHIFT)| @@ -240,12 +305,56 @@ static __code uint8_t fixed_pkt_setup[] = { RF_PKTCTRL0_LENGTH_CONFIG_FIXED), }; +#if HAS_RADIO_RATE +static __code struct { + uint8_t mdmcfg4; + uint8_t deviatn; +} packet_rate_setup[] = { + /* 38400 */ + { + ((CHANBW_E << RF_MDMCFG4_CHANBW_E_SHIFT) | + (CHANBW_M_384 << RF_MDMCFG4_CHANBW_M_SHIFT) | + (DRATE_E_384 << RF_MDMCFG4_DRATE_E_SHIFT)), + ((DEVIATION_E_384 << RF_DEVIATN_DEVIATION_E_SHIFT) | + (DEVIATION_M_384 << RF_DEVIATN_DEVIATION_M_SHIFT)), + }, + /* 9600 */ + { + ((CHANBW_E << RF_MDMCFG4_CHANBW_E_SHIFT) | + (CHANBW_M_96 << RF_MDMCFG4_CHANBW_M_SHIFT) | + (DRATE_E_96 << RF_MDMCFG4_DRATE_E_SHIFT)), + ((DEVIATION_E_96 << RF_DEVIATN_DEVIATION_E_SHIFT) | + (DEVIATION_M_96 << RF_DEVIATN_DEVIATION_M_SHIFT)), + }, + /* 2400 */ + { + ((CHANBW_E << RF_MDMCFG4_CHANBW_E_SHIFT) | + (CHANBW_M_24 << RF_MDMCFG4_CHANBW_M_SHIFT) | + (DRATE_E_24 << RF_MDMCFG4_DRATE_E_SHIFT)), + ((DEVIATION_E_24 << RF_DEVIATN_DEVIATION_E_SHIFT) | + (DEVIATION_M_24 << RF_DEVIATN_DEVIATION_M_SHIFT)), + }, +}; +#endif + __xdata uint8_t ao_radio_dma; __xdata uint8_t ao_radio_dma_done; __xdata uint8_t ao_radio_done; __xdata uint8_t ao_radio_abort; __xdata uint8_t ao_radio_mutex; +#if PACKET_HAS_MASTER || HAS_AES +#define NEED_RADIO_RSSI 1 +#endif + +#ifndef NEED_RADIO_RSSI +#define NEED_RADIO_RSSI 0 +#endif + +#if NEED_RADIO_RSSI +__xdata int8_t ao_radio_rssi; +#endif + void ao_radio_general_isr(void) __interrupt 16 { @@ -260,7 +369,7 @@ ao_radio_general_isr(void) __interrupt 16 } } -void +static void ao_radio_set_packet(void) { uint8_t i; @@ -268,7 +377,7 @@ ao_radio_set_packet(void) RF[fixed_pkt_setup[i]] = fixed_pkt_setup[i+1]; } -void +static void ao_radio_idle(void) { if (RF_MARCSTATE != RF_MARCSTATE_IDLE) @@ -280,17 +389,23 @@ ao_radio_idle(void) } } -void +#define ao_radio_put() ao_mutex_put(&ao_radio_mutex) + +static void ao_radio_get(uint8_t len) { ao_config_get(); ao_mutex_get(&ao_radio_mutex); ao_radio_idle(); - RF_CHANNR = ao_config.radio_channel; + RF_CHANNR = 0; RF_FREQ2 = (uint8_t) (ao_config.radio_setting >> 16); RF_FREQ1 = (uint8_t) (ao_config.radio_setting >> 8); RF_FREQ0 = (uint8_t) (ao_config.radio_setting); RF_PKTLEN = len; +#if HAS_RADIO_RATE + RF_MDMCFG4 = packet_rate_setup[ao_config.radio_rate].mdmcfg4; + RF_DEVIATN = packet_rate_setup[ao_config.radio_rate].deviatn; +#endif } @@ -317,7 +432,7 @@ ao_radio_send(__xdata void *packet, uint8_t size) __reentrant } uint8_t -ao_radio_recv(__xdata void *packet, uint8_t size) __reentrant +ao_radio_recv(__xdata void *packet, uint8_t size, uint8_t timeout) __reentrant { ao_radio_abort = 0; ao_radio_get(size - 2); @@ -338,7 +453,7 @@ ao_radio_recv(__xdata void *packet, uint8_t size) __reentrant * get aborted or for a receive timeout to fire */ __critical while (!ao_radio_dma_done && !ao_radio_abort) - if (ao_sleep(&ao_radio_dma_done)) + if (ao_sleep_for(&ao_radio_dma_done, timeout)) break; /* If recv was aborted, clean up by stopping the DMA engine @@ -347,7 +462,14 @@ ao_radio_recv(__xdata void *packet, uint8_t size) __reentrant if (!ao_radio_dma_done) { ao_dma_abort(ao_radio_dma); ao_radio_idle(); +#if NEED_RADIO_RSSI + ao_radio_rssi = 0; +#endif } +#if NEED_RADIO_RSSI + else + ao_radio_rssi = AO_RSSI_FROM_RADIO(((uint8_t *)packet)[size - 2]); +#endif ao_radio_put(); return ao_radio_dma_done; } @@ -364,29 +486,22 @@ ao_radio_recv_abort(void) ao_wakeup(&ao_radio_dma_done); } -__xdata ao_radio_rdf_value = 0x55; +__code ao_radio_rdf_value = 0x55; -void -ao_radio_rdf(uint8_t pkt_len) +static void +ao_radio_rdf_start(void) { uint8_t i; - ao_radio_abort = 0; - ao_radio_get(pkt_len); + ao_radio_get(AO_RADIO_RDF_LEN); ao_radio_done = 0; for (i = 0; i < sizeof (rdf_setup); i += 2) RF[rdf_setup[i]] = rdf_setup[i+1]; +} - ao_dma_set_transfer(ao_radio_dma, - &ao_radio_rdf_value, - &RFDXADDR, - pkt_len, - DMA_CFG0_WORDSIZE_8 | - DMA_CFG0_TMODE_SINGLE | - DMA_CFG0_TRIGGER_RADIO, - DMA_CFG1_SRCINC_0 | - DMA_CFG1_DESTINC_0 | - DMA_CFG1_PRIORITY_HIGH); +static void +ao_radio_rdf_run(void) +{ ao_dma_start(ao_radio_dma); RFST = RFST_STX; __critical while (!ao_radio_done && !ao_radio_abort) @@ -399,6 +514,70 @@ ao_radio_rdf(uint8_t pkt_len) ao_radio_put(); } +void +ao_radio_rdf(void) +{ + ao_radio_rdf_start(); + + ao_dma_set_transfer(ao_radio_dma, + CODE_TO_XDATA(&ao_radio_rdf_value), + &RFDXADDR, + AO_RADIO_RDF_LEN, + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_RADIO, + DMA_CFG1_SRCINC_0 | + DMA_CFG1_DESTINC_0 | + DMA_CFG1_PRIORITY_HIGH); + ao_radio_rdf_run(); +} + +#define PA 0x00 +#define BE 0x55 + +#define CONT_PAUSE_8 PA, PA, PA, PA, PA, PA, PA, PA +#define CONT_PAUSE_16 CONT_PAUSE_8, CONT_PAUSE_8 +#define CONT_PAUSE_24 CONT_PAUSE_16, CONT_PAUSE_8 + +#define CONT_BEEP_8 BE, BE, BE, BE, BE, BE, BE, BE + +#if AO_RADIO_CONT_PAUSE_LEN == 24 +#define CONT_PAUSE CONT_PAUSE_24 +#endif + +#if AO_RADIO_CONT_TONE_LEN == 8 +#define CONT_BEEP CONT_BEEP_8 +#define CONT_PAUSE_SHORT CONT_PAUSE_8 +#endif + +#define CONT_ADDR(c) CODE_TO_XDATA(&ao_radio_cont[(3-(c)) * (AO_RADIO_CONT_PAUSE_LEN + AO_RADIO_CONT_TONE_LEN)]) + +__code uint8_t ao_radio_cont[] = { + CONT_PAUSE, CONT_BEEP, + CONT_PAUSE, CONT_BEEP, + CONT_PAUSE, CONT_BEEP, + CONT_PAUSE, CONT_PAUSE_SHORT, + CONT_PAUSE, CONT_PAUSE_SHORT, + CONT_PAUSE, +}; + +void +ao_radio_continuity(uint8_t c) +{ + ao_radio_rdf_start(); + ao_dma_set_transfer(ao_radio_dma, + CONT_ADDR(c), + &RFDXADDR, + AO_RADIO_CONT_TOTAL_LEN, + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_RADIO, + DMA_CFG1_SRCINC_1 | + DMA_CFG1_DESTINC_0 | + DMA_CFG1_PRIORITY_HIGH); + ao_radio_rdf_run(); +} + void ao_radio_rdf_abort(void) { @@ -408,8 +587,44 @@ ao_radio_rdf_abort(void) /* Output carrier */ + +static __xdata radio_test_on; + void -ao_radio_test(void) +ao_radio_test(uint8_t on) +{ + if (on) { + if (!radio_test_on) { +#if HAS_MONITOR + ao_monitor_disable(); +#endif +#if PACKET_HAS_SLAVE + ao_packet_slave_stop(); +#endif +#if HAS_PAD + ao_pad_disable(); +#endif + ao_radio_get(0xff); + RFST = RFST_STX; + radio_test_on = 1; + } + } else { + if (radio_test_on) { + ao_radio_idle(); + ao_radio_put(); + radio_test_on = 0; +#if HAS_MONITOR + ao_monitor_enable(); +#endif +#if HAS_PAD + ao_pad_enable(); +#endif + } + } +} + +static void +ao_radio_test_cmd(void) { uint8_t mode = 2; static __xdata radio_on; @@ -419,31 +634,42 @@ ao_radio_test(void) mode = (uint8_t) ao_cmd_lex_u32; } mode++; - if ((mode & 2) && !radio_on) { -#if HAS_MONITOR - ao_set_monitor(0); -#endif -#if PACKET_HAS_SLAVE - ao_packet_slave_stop(); -#endif - ao_radio_get(0xff); - RFST = RFST_STX; - radio_on = 1; - } + if ((mode & 2)) + ao_radio_test(1); if (mode == 3) { printf ("Hit a character to stop..."); flush(); getchar(); putchar('\n'); } - if ((mode & 1) && radio_on) { - ao_radio_idle(); - ao_radio_put(); - radio_on = 0; + if ((mode & 1)) + ao_radio_test(0); +} + +#if AO_RADIO_REG_TEST +static void +ao_radio_set_reg(void) +{ + uint8_t offset; + ao_cmd_hex(); + offset = ao_cmd_lex_i; + if (ao_cmd_status != ao_cmd_success) + return; + ao_cmd_hex(); + printf("RF[%x] %x", offset, RF[offset]); + if (ao_cmd_status == ao_cmd_success) { + RF[offset] = ao_cmd_lex_i; + printf (" -> %x", RF[offset]); } + ao_cmd_status = ao_cmd_success; + printf("\n"); } +#endif __code struct ao_cmds ao_radio_cmds[] = { - { ao_radio_test, "C <1 start, 0 stop, none both>\0Radio carrier test" }, + { ao_radio_test_cmd, "C <1 start, 0 stop, none both>\0Radio carrier test" }, +#if AO_RADIO_REG_TEST + { ao_radio_set_reg, "V \0Set radio register" }, +#endif { 0, NULL }, };