X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=blobdiff_plain;f=src%2Fdrivers%2Fao_cc1120.c;h=b42ca54c1fdabf74c9103eebca808f2a505ddbff;hp=95b21170f597e0b1c468cef9e1d3f97a13c5b014;hb=628076aa90e7bc9a894646e417dd8e1fe149b60d;hpb=73c26f39b1a08fcc13e23a5b1a4293bc7df9f163 diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 95b21170..b42ca54c 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -18,14 +18,23 @@ #include #include #include +#include +#include uint8_t ao_radio_wake; uint8_t ao_radio_mutex; uint8_t ao_radio_abort; #define CC1120_DEBUG 1 +#define CC1120_TRACE 0 -uint32_t ao_radio_cal = 1186611; +#if CC1120_TRACE +#define fec_dump_bytes(b,l,n) ao_fec_dump_bytes(b,l,n) +#else +#define fec_dump_bytes(b,l,n) +#endif + +uint32_t ao_radio_cal = 0x6ca333; #define FOSC 32000000 @@ -42,7 +51,7 @@ ao_radio_reg_read(uint16_t addr) uint8_t data[2]; uint8_t d; -#if CC1120_DEBUG +#if CC1120_TRACE printf("\t\tao_radio_reg_read (%04x): ", addr); flush(); #endif if (CC1120_IS_EXTENDED(addr)) { @@ -61,7 +70,7 @@ ao_radio_reg_read(uint16_t addr) ao_radio_spi_send(data, d); ao_radio_spi_recv(data, 1); ao_radio_deselect(); -#if CC1120_DEBUG +#if CC1120_TRACE printf (" %02x\n", data[0]); #endif return data[0]; @@ -73,17 +82,17 @@ ao_radio_reg_write(uint16_t addr, uint8_t value) uint8_t data[3]; uint8_t d; -#if CC1120_DEBUG +#if CC1120_TRACE printf("\t\tao_radio_reg_write (%04x): %02x\n", addr, value); #endif if (CC1120_IS_EXTENDED(addr)) { - data[0] = ((1 << CC1120_READ) | + data[0] = ((0 << CC1120_READ) | (0 << CC1120_BURST) | CC1120_EXTENDED); data[1] = addr; d = 2; } else { - data[0] = ((1 << CC1120_READ) | + data[0] = ((0 << CC1120_READ) | (0 << CC1120_BURST) | addr); d = 1; @@ -94,19 +103,48 @@ ao_radio_reg_write(uint16_t addr, uint8_t value) ao_radio_deselect(); } +static void +ao_radio_burst_read_start (uint16_t addr) +{ + uint8_t data[2]; + uint8_t d; + + if (CC1120_IS_EXTENDED(addr)) { + data[0] = ((1 << CC1120_READ) | + (1 << CC1120_BURST) | + CC1120_EXTENDED); + data[1] = addr; + d = 2; + } else { + data[0] = ((1 << CC1120_READ) | + (1 << CC1120_BURST) | + addr); + d = 1; + } + ao_radio_select(); + ao_radio_spi_send(data, d); +} + +static void +ao_radio_burst_read_stop (void) +{ + ao_radio_deselect(); +} + + static uint8_t ao_radio_strobe(uint8_t addr) { uint8_t in; -#if CC1120_DEBUG +#if CC1120_TRACE printf("\t\tao_radio_strobe (%02x): ", addr); flush(); #endif ao_radio_select(); ao_radio_duplex(&addr, &in, 1); ao_radio_deselect(); -#if CC1120_DEBUG - printf("%02x\n", in); +#if CC1120_TRACE + printf("%02x\n", in); flush(); #endif return in; } @@ -149,12 +187,10 @@ ao_radio_fifo_write_fixed(uint8_t data, uint8_t len) CC1120_FIFO); uint8_t status; - printf ("num tx bytes: %d\n", ao_radio_reg_read(CC1120_NUM_TXBYTES)); ao_radio_select(); ao_radio_duplex(&addr, &status, 1); ao_radio_spi_send_fixed(data, len); ao_radio_deselect(); - printf ("num tx bytes: %d\n", ao_radio_reg_read(CC1120_NUM_TXBYTES)); return status; } @@ -197,8 +233,8 @@ ao_radio_recv_abort(void) * * To make the tone last for 200ms, we need 2000 * .2 = 400 bits or 50 bytes */ -#define RDF_DRATE_E 6 -#define RDF_DRATE_M 511705 +#define RDF_DRATE_E 5 +#define RDF_DRATE_M 25166 #define RDF_PACKET_LEN 50 static const uint16_t rdf_setup[] = { @@ -216,12 +252,13 @@ static const uint16_t rdf_setup[] = { (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) | (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) | (0 << CC1120_PKT_CFG1_APPEND_STATUS)), + CC1120_PKT_CFG0, ((0 << CC1120_PKT_CFG0_RESERVED7) | + (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) | + (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) | + (0 << CC1120_PKT_CFG0_UART_MODE_EN) | + (0 << CC1120_PKT_CFG0_UART_SWAP_EN)), }; -#define int_pin(w) printf("\t%s: %d\n", \ - w,\ - (AO_CC1120_INT_PORT.idr >> AO_CC1120_INT_PIN) & 1) - static uint8_t ao_radio_marc_status(void) { @@ -240,42 +277,42 @@ ao_radio_rx_done(void) return ao_radio_marc_status() == CC1120_MARC_STATUS1_RX_FINISHED; } +static void +ao_radio_tx_isr(void) +{ + ao_exti_disable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); + ao_radio_wake = 1; + ao_wakeup(&ao_radio_wake); +} + +static void +ao_radio_start_tx(void) +{ + ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG); + ao_exti_set_callback(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_tx_isr); + ao_exti_enable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); + ao_radio_strobe(CC1120_STX); +} + void ao_radio_rdf(uint8_t len) { int i; ao_radio_get(len); - ao_radio_abort = 0; + ao_radio_wake = 0; for (i = 0; i < sizeof (rdf_setup) / sizeof (rdf_setup[0]); i += 2) ao_radio_reg_write(rdf_setup[i], rdf_setup[i+1]); - ao_radio_reg_write(CC1120_PKT_LEN, len); - int_pin ("Before CFG"); - ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG); - int_pin ("After CFG"); - ao_radio_strobe(CC1120_STX); - ao_exti_enable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); - int_pin ("After strobe"); - ao_delay(AO_MS_TO_TICKS(100)); + ao_radio_fifo_write_fixed(ao_radio_rdf_value, len); - int_pin ("After delay"); + + ao_radio_start_tx(); + cli(); - for (i = 0; i < 20; i++) { -#if CC1120_DEBUG - ao_delay(AO_MS_TO_TICKS(50)); - int_pin ("Waited"); - printf ("Status %02x num_tx_bytes %d marc status %x\n", - ao_radio_status(), - ao_radio_reg_read(CC1120_NUM_TXBYTES), - ao_radio_marc_status()); -#else + while (!ao_radio_wake && !ao_radio_abort) ao_sleep(&ao_radio_wake); -#endif - } + sei(); - printf ("num_tx_bytes %d marc status %x\n", - ao_radio_reg_read(CC1120_NUM_TXBYTES), - ao_radio_marc_status()); if (!ao_radio_tx_done()) ao_radio_idle(); ao_radio_set_packet(); @@ -309,7 +346,7 @@ ao_radio_test(void) #endif ao_radio_get(0xff); ao_radio_strobe(CC1120_STX); -#if CC1120_DEBUG +#if CC1120_TRACE { int t; for (t = 0; t < 10; t++) { printf ("status: %02x\n", ao_radio_status()); @@ -337,54 +374,119 @@ ao_radio_test(void) void ao_radio_send(void *d, uint8_t size) { - uint8_t marc_status; + uint8_t marc_status; + uint8_t encode[size + AO_FEC_PREPARE_EXTRA]; + uint8_t encode_len; + + encode_len = ao_fec_encode(d, size, encode); + + ao_radio_get(encode_len); + ao_radio_fifo_write(encode, encode_len); - ao_radio_get(size); ao_radio_wake = 0; - ao_radio_fifo_write(d, size); - ao_exti_enable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); - ao_radio_strobe(CC1120_STX); + + ao_radio_start_tx(); + cli(); - for (;;) { - if (ao_radio_wake) { - marc_status = ao_radio_marc_status(); - if (marc_status != CC1120_MARC_STATUS1_NO_FAILURE) - break; - ao_radio_wake = 0; - } + while (!ao_radio_wake && !ao_radio_abort) ao_sleep(&ao_radio_wake); - } sei(); + if (!ao_radio_tx_done()) + ao_radio_idle(); ao_radio_put(); } +#define AO_RADIO_MAX_RECV 90 + +static uint8_t rx_data[2048]; +static uint16_t rx_data_count; +static uint16_t rx_data_cur; +static uint8_t rx_ignore; + +static void +ao_radio_rx_isr(void) +{ + if (rx_ignore == 0) { + rx_data[rx_data_cur++] = stm_spi2.dr; + if (rx_data_cur >= rx_data_count) { + ao_exti_disable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); + ao_radio_wake = 1; + ao_wakeup(&ao_radio_wake); + } + } else { + (void) stm_spi2.dr; + --rx_ignore; + } + stm_spi2.dr = 0x00; +} + uint8_t ao_radio_recv(__xdata void *d, uint8_t size) { - uint8_t marc_status = CC1120_MARC_STATUS1_NO_FAILURE; + uint8_t len; + uint16_t i; + uint8_t rssi; + + size -= 2; /* status bytes */ + len = size + 2; /* CRC bytes */ + len += 1 + ~(len & 1); /* 1 or two pad bytes */ + len *= 2; /* 1/2 rate convolution */ + rx_data_count = len * 8; /* bytes to bits */ + rx_data_cur = 0; + rx_ignore = 2; + + printf ("len %d rx_data_count %d\n", len, rx_data_count); /* configure interrupt pin */ - ao_radio_get(size); + ao_radio_get(len); ao_radio_wake = 0; + ao_radio_abort = 0; + + ao_radio_reg_write(CC1120_PKT_CFG2, + (CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) | + (CC1120_PKT_CFG2_PKT_FORMAT_SYNCHRONOUS_SERIAL << CC1120_PKT_CFG2_PKT_FORMAT)); + + ao_radio_reg_write(CC1120_EXT_CTRL, 0); + + ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT); + + stm_spi2.cr2 = 0; + + /* clear any RXNE */ + (void) stm_spi2.dr; + + ao_exti_set_callback(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_rx_isr); ao_exti_enable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); + ao_radio_strobe(CC1120_SRX); + + ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT); cli(); - for (;;) { - if (ao_radio_abort) - break; - if (ao_radio_wake) { - marc_status = ao_radio_marc_status(); - if (marc_status != CC1120_MARC_STATUS1_NO_FAILURE) - break; - ao_radio_wake = 0; - } + while (!ao_radio_wake && !ao_radio_abort) ao_sleep(&ao_radio_wake); - } sei(); - if (marc_status != CC1120_MARC_STATUS1_RX_FINISHED) - ao_radio_fifo_read(d, size); + ao_radio_burst_read_stop(); + + /* Convert from 'real' rssi to cc1111-style values */ + + rssi = (((int8_t) ao_radio_reg_read(CC1120_RSSI1)) + 74) * 2; + + ao_radio_strobe(CC1120_SIDLE); + ao_radio_put(); - return marc_status == CC1120_MARC_STATUS1_RX_FINISHED; + + /* Construct final packet */ + + ao_fec_decode(rx_data, rx_data_cur, d, size + 2); + + if (ao_fec_check_crc(d, size)) + ((uint8_t *) d)[size + 1] = 0x80; + else + ((uint8_t *) d)[size + 1] = 0x00; + + ((uint8_t *) d)[size] = (uint8_t) rssi; + + return 1; } /* @@ -401,17 +503,16 @@ ao_radio_recv(__xdata void *d, uint8_t size) /* * For our packet data, set the symbol rate to 38360 Baud * - * (2**20 - DATARATE_M) * 2 ** DATARATE_E + * (2**20 + DATARATE_M) * 2 ** DATARATE_E * Rdata = -------------------------------------- * fosc * 2 ** 39 * - * DATARATE_M = 405002 - * DATARATE_E = 10 * - * To make the tone last for 200ms, we need 2000 * .2 = 400 bits or 50 bytes + * DATARATE_M = 239914 + * DATARATE_E = 9 */ -#define PACKET_DRATE_E 10 -#define PACKET_DRATE_M 405002 +#define PACKET_DRATE_E 9 +#define PACKET_DRATE_M 239914 static const uint16_t packet_setup[] = { CC1120_DEVIATION_M, PACKET_DEV_M, @@ -424,10 +525,15 @@ static const uint16_t packet_setup[] = { CC1120_DRATE0, ((PACKET_DRATE_M >> 0) & 0xff), CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) | (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)), - CC1120_PKT_CFG1, ((1 << CC1120_PKT_CFG1_WHITE_DATA) | + CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) | (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) | (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) | (1 << CC1120_PKT_CFG1_APPEND_STATUS)), + CC1120_PKT_CFG0, ((0 << CC1120_PKT_CFG0_RESERVED7) | + (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) | + (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) | + (0 << CC1120_PKT_CFG0_UART_MODE_EN) | + (0 << CC1120_PKT_CFG0_UART_SWAP_EN)), }; void @@ -457,13 +563,6 @@ static const uint16_t radio_setup[] = { static uint8_t ao_radio_configured = 0; -static void -ao_radio_isr(void) -{ - ao_exti_disable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); - ao_radio_wake = 1; - ao_wakeup(&ao_radio_wake); -} static void ao_radio_setup(void) @@ -475,14 +574,10 @@ ao_radio_setup(void) for (i = 0; i < sizeof (radio_setup) / sizeof (radio_setup[0]); i += 2) ao_radio_reg_write(radio_setup[i], radio_setup[i+1]); - /* Enable marc status interrupt on gpio 2 pin */ - ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_MARC_MCU_WAKEUP); + ao_radio_set_packet(); - /* Enable the EXTI interrupt for the appropriate pin */ - ao_enable_port(AO_CC1120_INT_PORT); - ao_exti_setup(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, AO_EXTI_MODE_FALLING, ao_radio_isr); + ao_config_get(); - ao_radio_set_packet(); ao_radio_configured = 1; } @@ -492,6 +587,9 @@ ao_radio_get(uint8_t len) ao_mutex_get(&ao_radio_mutex); if (!ao_radio_configured) ao_radio_setup(); + ao_radio_reg_write(CC1120_FREQ2, ao_config.radio_setting >> 16); + ao_radio_reg_write(CC1120_FREQ1, ao_config.radio_setting >> 8); + ao_radio_reg_write(CC1120_FREQ0, ao_config.radio_setting); ao_radio_reg_write(CC1120_PKT_LEN, len); } @@ -708,7 +806,28 @@ static void ao_radio_show(void) { } static void ao_radio_beep(void) { - ao_radio_rdf(120); + ao_radio_rdf(RDF_PACKET_LEN); +} + +static void ao_radio_packet(void) { + static uint8_t packet[] = { +#if 1 + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, +#else + 3, 1, 2, 3 +#endif + }; + + ao_radio_send(packet, sizeof (packet)); +} + +void +ao_radio_test_recv() +{ + ao_radio_recv(0, 34); } #endif @@ -717,7 +836,9 @@ static const struct ao_cmds ao_radio_cmds[] = { { ao_radio_test, "C <1 start, 0 stop, none both>\0Radio carrier test" }, #if CC1120_DEBUG { ao_radio_show, "R\0Show CC1120 status" }, - { ao_radio_beep, "B\0Emit an RDF beacon" }, + { ao_radio_beep, "b\0Emit an RDF beacon" }, + { ao_radio_packet, "p\0Send a test packet" }, + { ao_radio_test_recv, "q\0Recv a test packet" }, #endif { 0, NULL } }; @@ -725,8 +846,23 @@ static const struct ao_cmds ao_radio_cmds[] = { void ao_radio_init(void) { + int i; + ao_radio_configured = 0; ao_spi_init_cs (AO_CC1120_SPI_CS_PORT, (1 << AO_CC1120_SPI_CS_PIN)); + AO_CC1120_SPI_CS_PORT.bsrr = ((uint32_t) (1 << AO_CC1120_SPI_CS_PIN)); + for (i = 0; i < 10000; i++) { + if ((SPI_2_GPIO.idr & (1 << SPI_2_MISO)) == 0) + break; + } + AO_CC1120_SPI_CS_PORT.bsrr = (1 << AO_CC1120_SPI_CS_PIN); + if (i == 10000) + ao_panic(AO_PANIC_SELF_TEST); + + /* Enable the EXTI interrupt for the appropriate pin */ + ao_enable_port(AO_CC1120_INT_PORT); + ao_exti_setup(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, AO_EXTI_MODE_FALLING, ao_radio_tx_isr); + ao_cmd_register(&ao_radio_cmds[0]); }