From 2c3e5406371fe89002b67a603bc28d1d62c117e8 Mon Sep 17 00:00:00 2001 From: pip Date: Tue, 1 Feb 2011 23:40:40 +0000 Subject: [PATCH] Code added to allow GCS to configure modem. Not yet finished - modem needs rebooting after uploading new config - for the time being. git-svn-id: svn://svn.openpilot.org/OpenPilot/trunk@2687 ebee16cc-31ac-478f-84a7-5cbb03baadba --- flight/PipXtreme/Makefile | 3 +- flight/PipXtreme/api_config.c | 559 ++++++++++++++++++++++++++ flight/PipXtreme/crc.c | 16 +- flight/PipXtreme/inc/api_config.h | 40 ++ flight/PipXtreme/inc/crc.h | 8 +- flight/PipXtreme/inc/rfm22b.h | 6 +- flight/PipXtreme/main.c | 56 +-- flight/PipXtreme/packet_handler.c | 26 +- flight/PipXtreme/reserved/api_comms.c | 500 +++++++++++++++++++++++ flight/PipXtreme/reserved/api_comms.h | 40 ++ flight/PipXtreme/rfm22b.c | 21 +- flight/PipXtreme/saved_settings.c | 8 +- 12 files changed, 1218 insertions(+), 65 deletions(-) create mode 100644 flight/PipXtreme/api_config.c create mode 100644 flight/PipXtreme/inc/api_config.h create mode 100644 flight/PipXtreme/reserved/api_comms.c create mode 100644 flight/PipXtreme/reserved/api_comms.h diff --git a/flight/PipXtreme/Makefile b/flight/PipXtreme/Makefile index 4dcaa8955..dc8ef9fe1 100644 --- a/flight/PipXtreme/Makefile +++ b/flight/PipXtreme/Makefile @@ -115,7 +115,8 @@ SRC += $(HOME_DIR)/aes.c SRC += $(HOME_DIR)/rfm22b.c SRC += $(HOME_DIR)/packet_handler.c SRC += $(HOME_DIR)/transparent_comms.c -SRC += $(HOME_DIR)/api_comms.c +#SRC += $(HOME_DIR)/api_comms.c +SRC += $(HOME_DIR)/api_config.c SRC += $(HOME_DIR)/saved_settings.c SRC += $(HOME_DIR)/gpio_in.c SRC += $(HOME_DIR)/stopwatch.c diff --git a/flight/PipXtreme/api_config.c b/flight/PipXtreme/api_config.c new file mode 100644 index 000000000..01f03a077 --- /dev/null +++ b/flight/PipXtreme/api_config.c @@ -0,0 +1,559 @@ +/** + ****************************************************************************** + * + * @file apiconfig_config.h + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief RF Module hardware layer + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * 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; either version 3 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 MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#include "stm32f10x.h" +#include "gpio_in.h" +#include "api_config.h" +#include "rfm22b.h" +#include "packet_handler.h" +#include "saved_settings.h" +#include "crc.h" +#include "main.h" + +#if defined(PIOS_COM_DEBUG) + #define APICONFIG_DEBUG +#endif + +// ***************************************************************************** +// modem configuration packets + +#define pipx_header_marker 0x76b38a52 + +#define pipx_packet_type_req_config 1 +#define pipx_packet_type_config 2 + +typedef struct +{ + uint32_t marker; + uint32_t serial_number; + uint8_t type; + uint8_t spare; + uint16_t data_size; + uint32_t header_crc; + uint32_t data_crc; +// uint8_t data[0]; +} __attribute__((__packed__)) t_pipx_config_header; + +typedef struct +{ + uint8_t mode; + uint8_t state; +} __attribute__((__packed__)) t_pipx_config_data_mode_state; + +typedef struct +{ + uint32_t serial_baudrate; // serial uart baudrate + + uint32_t destination_id; + + uint32_t min_frequency_Hz; + uint32_t max_frequency_Hz; + float frequency_Hz; + + uint32_t max_rf_bandwidth; + + uint8_t max_tx_power; + + uint8_t frequency_band; + + uint8_t rf_xtal_cap; + + bool aes_enable; + uint8_t aes_key[16]; + + float frequency_step_size; +} __attribute__((__packed__)) t_pipx_config_data_settings; + +typedef struct +{ + float start_frequency; + float frequency_step_size; + uint16_t magnitudes; +// int8_t magnitude[0]; +} __attribute__((__packed__)) t_pipx_config_data_spectrum; + +// ***************************************************************************** +// local variables + +int8_t apiconfig_previous_com_port = -1; + +volatile uint16_t apiconfig_rx_timer = 0; +volatile uint16_t apiconfig_tx_timer = 0; + +uint8_t apiconfig_rx_buffer[256] __attribute__ ((aligned(4))); +uint16_t apiconfig_rx_buffer_wr; + +uint8_t apiconfig_tx_buffer[256] __attribute__ ((aligned(4))); +uint16_t apiconfig_tx_buffer_wr; + +uint8_t apiconfig_tx_config_buffer[128] __attribute__ ((aligned(4))); +uint16_t apiconfig_tx_config_buffer_wr; + +// ***************************************************************************** + +int apiconfig_sendConfigPacket() +{ + if (sizeof(apiconfig_tx_config_buffer) - apiconfig_tx_config_buffer_wr < sizeof(t_pipx_config_header) + sizeof(t_pipx_config_data_settings)) + return -1; // not enough room in the tx buffer for the packet we were going to send + + t_pipx_config_header *header = (t_pipx_config_header *)(apiconfig_tx_config_buffer + apiconfig_tx_config_buffer_wr); + t_pipx_config_data_settings *settings = (t_pipx_config_data_settings *)((uint8_t *)header + sizeof(t_pipx_config_header)); + + header->marker = pipx_header_marker; + header->serial_number = serial_number_crc32; + header->type = pipx_packet_type_config; + header->spare = 0; + header->data_size = sizeof(t_pipx_config_data_settings); + + settings->serial_baudrate = saved_settings.serial_baudrate; + settings->destination_id = saved_settings.destination_id; + settings->min_frequency_Hz = saved_settings.min_frequency_Hz; + settings->max_frequency_Hz = saved_settings.max_frequency_Hz; + settings->frequency_Hz = saved_settings.frequency_Hz; + settings->max_rf_bandwidth = saved_settings.max_rf_bandwidth; + settings->max_tx_power = saved_settings.max_tx_power; + settings->frequency_band = saved_settings.frequency_band; + settings->rf_xtal_cap = saved_settings.rf_xtal_cap; + settings->aes_enable = saved_settings.aes_enable; + memcpy((char *)settings->aes_key, (char *)saved_settings.aes_key, sizeof(settings->aes_key)); + settings->frequency_step_size = rfm22_getFrequencyStepSize(); + + header->data_crc = updateCRC32Data(0xffffffff, settings, header->data_size); + header->header_crc = 0; + header->header_crc = updateCRC32Data(0xffffffff, header, sizeof(t_pipx_config_header)); + + int total_packet_size = sizeof(t_pipx_config_header) + header->data_size; + + apiconfig_tx_config_buffer_wr += total_packet_size; + + #if defined(APICONFIG_DEBUG) + DEBUG_PRINTF("TX api config: config\r\n"); + #endif + + return total_packet_size; +} + +void apiconfig_processInputPacket(void *buf, uint16_t len) +{ + if (len <= 0) + return; + + t_pipx_config_header *header = (t_pipx_config_header *)buf; + uint8_t *data = (uint8_t *)header + sizeof(t_pipx_config_header); + + switch (header->type) + { + case pipx_packet_type_req_config: // they are requesting our configuration + + #if defined(APICONFIG_DEBUG) + DEBUG_PRINTF("RX api config: req_config\r\n"); + #endif + + if (header->serial_number == 0 || header->serial_number == 0xffffffff || header->serial_number == serial_number_crc32) + apiconfig_sendConfigPacket(); + break; + + case pipx_packet_type_config: // they have sent us new configuration settings + #if defined(APICONFIG_DEBUG) + DEBUG_PRINTF("RX api config: config\r\n"); + #endif + + if (header->serial_number == serial_number_crc32) + { // the packet is meant for us + + t_pipx_config_data_settings *settings = (t_pipx_config_data_settings *)data; + + saved_settings.destination_id = settings->destination_id; + + saved_settings.frequency_Hz = settings->frequency_Hz; + + saved_settings.max_tx_power = settings->max_tx_power; + + saved_settings.max_rf_bandwidth = settings->max_rf_bandwidth; + + saved_settings.rf_xtal_cap = settings->rf_xtal_cap; + + saved_settings.serial_baudrate = settings->serial_baudrate; + + saved_settings.aes_enable = settings->aes_enable; + memcpy((char *)saved_settings.aes_key, (char *)settings->aes_key, sizeof(saved_settings.aes_key)); + + saved_settings_save(); // save the new settings + } + break; + + default: + #if defined(APICONFIG_DEBUG) + DEBUG_PRINTF("RX api config: unknown type [%u]\r\n", header->type); + #endif + break; + } +} + +uint16_t apiconfig_scanForConfigPacket(void *buf, uint16_t *len, bool rf_packet) +{ + uint16_t length = *len; + uint16_t i = 0; + + while (TRUE) + { + uint32_t crc1, crc2; + + t_pipx_config_header *header = (t_pipx_config_header *)buf + i; + uint8_t *data = (uint8_t *)header + sizeof(t_pipx_config_header); + + if (i + sizeof(t_pipx_config_header) > length) + { // not enough data for a packet + if (i >= sizeof(header->marker)) + i -= sizeof(header->marker); + else + i = 0; + break; + } + + if (header->marker != pipx_header_marker) + { // no packet marker found + i++; + continue; + } + + // check the header is error free + crc1 = header->header_crc; + header->header_crc = 0; + crc2 = updateCRC32Data(0xffffffff, header, sizeof(t_pipx_config_header)); + header->header_crc = crc1; + if (crc2 != crc1) + { // faulty header or not really a header + i++; + continue; + } + + // valid header found! + + #if defined(APICONFIG_DEBUG) + DEBUG_PRINTF("RX api config: header found\r\n"); + #endif + + if (!rf_packet) + apiconfig_rx_timer = 0; // reset the timer + + int total_packet_size = sizeof(t_pipx_config_header) + header->data_size; + + if (i + total_packet_size > length) + { // not yet got a full packet + break; + } + + if (header->data_size > 0) + { // check the data is error free + crc1 = header->data_crc; + crc2 = updateCRC32Data(0xffffffff, data, header->data_size); + if (crc2 != crc1) + { // faulty data .. remove the entire packet + length -= total_packet_size; + if (length - i > 0) + memmove(buf + i, buf + i + total_packet_size, length - i); + continue; + } + } + + if (!rf_packet) + apiconfig_processInputPacket(buf + i, length - i); + + // remove the packet from the buffer + length -= total_packet_size; + if (length - i > 0) + memmove(buf + i, buf + i + total_packet_size, length - i); + + break; + } + + *len = length; + + return i; +} + +// ***************************************************************************** +// can be called from an interrupt if you wish + +void apiconfig_1ms_tick(void) +{ // call this once every 1ms + + if (apiconfig_rx_timer < 0xffff) apiconfig_rx_timer++; + if (apiconfig_tx_timer < 0xffff) apiconfig_tx_timer++; +} + +// ***************************************************************************** +// call this as often as possible - not from an interrupt + +void apiconfig_process(void) +{ // copy data from comm-port RX buffer to RF packet handler TX buffer, and from RF packet handler RX buffer to comm-port TX buffer + + // ******************** + // decide which comm-port we are using (usart or usb) + + bool usb_comms = false; // TRUE if we are using the usb port for comms. + uint8_t comm_port = PIOS_COM_SERIAL; // default to using the usart comm-port + + #if defined(PIOS_INCLUDE_USB_HID) + if (PIOS_USB_HID_CheckAvailable(0)) + { // USB comms is up, use the USB comm-port instead of the USART comm-port + usb_comms = true; + comm_port = PIOS_COM_TELEM_USB; + } + #endif + + // ******************** + // check to see if the local communication port has changed (usart/usb) + + if (apiconfig_previous_com_port < 0 && apiconfig_previous_com_port != comm_port) + { // the local communications port has changed .. remove any data in the buffers + apiconfig_rx_buffer_wr = 0; + apiconfig_tx_buffer_wr = 0; + } + else + if (usb_comms) + { // we're using the USB for comms - keep the USART rx buffer empty + int32_t bytes = PIOS_COM_ReceiveBufferUsed(PIOS_COM_SERIAL); + while (bytes > 0) + { + PIOS_COM_ReceiveBuffer(PIOS_COM_SERIAL); + bytes--; + } + } + + apiconfig_previous_com_port = comm_port; // remember the current comm-port we are using + + // ******************** + + uint16_t connection_index = 0; // the RF connection we are using + + // ******************** + // send the data received from the local comm-port to the RF packet handler TX buffer + + while (TRUE) + { + // free space size in the RF packet handler tx buffer + uint16_t ph_num = ph_putData_free(connection_index); + + // get the number of data bytes received down the comm-port + int32_t com_num = PIOS_COM_ReceiveBufferUsed(comm_port); + + // set the USART RTS handshaking line + if (!usb_comms && ph_connected(connection_index)) + { + if (ph_num < 32) + SERIAL_RTS_CLEAR; // lower the USART RTS line - we don't have space in the buffer for anymore bytes + else + SERIAL_RTS_SET; // release the USART RTS line - we have space in the buffer for now bytes + } + else + SERIAL_RTS_SET; // release the USART RTS line + + // limit number of bytes we will get to how much space we have in our RX buffer + if (com_num > sizeof(apiconfig_rx_buffer) - apiconfig_rx_buffer_wr) + com_num = sizeof(apiconfig_rx_buffer) - apiconfig_rx_buffer_wr; + + while (com_num > 0) + { // fetch a byte from the comm-port RX buffer and save it into our RX buffer + apiconfig_rx_buffer[apiconfig_rx_buffer_wr++] = PIOS_COM_ReceiveBuffer(comm_port); + com_num--; + } + + uint16_t data_size = apiconfig_scanForConfigPacket(apiconfig_rx_buffer, &apiconfig_rx_buffer_wr, false); + + if (data_size == 0 && apiconfig_rx_timer >= 10) + { // no config packet found in the buffer within the timeout period, treat any data in the buffer as data to be sent over the air + data_size = apiconfig_rx_buffer_wr; + } + + if (data_size == 0) + break; // no data to send over the air + + #if defined(APICONFIG_DEBUG) + DEBUG_PRINTF("RX api config: data size %u\r\n", data_size); + #endif + + if (ph_connected(connection_index)) + { // we have an RF link to a remote modem + + if (ph_num < data_size) + break; // not enough room in the RF packet handler TX buffer for the data + + // copy the data into the RF packet handler TX buffer for sending over the RF link + data_size = ph_putData(connection_index, apiconfig_rx_buffer, data_size); + } + + // remove the data from our RX buffer + apiconfig_rx_buffer_wr -= data_size; + if (apiconfig_rx_buffer_wr > 0) + memmove(apiconfig_rx_buffer, apiconfig_rx_buffer + data_size, apiconfig_rx_buffer_wr); + } + + // ******************** + // send data down the local comm port + + if (apiconfig_tx_config_buffer_wr > 0) + { // send any config packets in the config buffer + + while (TRUE) + { + uint16_t data_size = apiconfig_tx_config_buffer_wr; + + if (data_size > 32) + data_size = 32; + + if (!usb_comms && !GPIO_IN(SERIAL_CTS_PIN)) + break; // we can't yet send data down the comm-port + + // send the data out the comm-port + int32_t res; +// if (usb_comms) +// res = PIOS_COM_SendBuffer(comm_port, apiconfig_tx_config_buffer, data_size); +// else + res = PIOS_COM_SendBufferNonBlocking(comm_port, apiconfig_tx_config_buffer, data_size); + if (res < 0) + { // failed to send the data out the comm-port + + #if defined(APICONFIG_DEBUG) + DEBUG_PRINTF("PIOS_COM_SendBuffer %d %d\r\n", data_size, res); + #endif + + if (apiconfig_tx_timer >= 5000) + { // seems we can't send our data for at least the last 5 seconds - delete it + apiconfig_tx_config_buffer_wr = 0; + } + + break; + } + + // data was sent out the comm-port OK .. remove the sent data from our buffer + + #if defined(APICONFIG_DEBUG) + DEBUG_PRINTF("TX api config: data [%u]\r\n", data_size); + #endif + + apiconfig_tx_config_buffer_wr -= data_size; + if (apiconfig_tx_config_buffer_wr > 0) + memmove(apiconfig_tx_config_buffer, apiconfig_tx_config_buffer + data_size, apiconfig_tx_config_buffer_wr); + + apiconfig_tx_timer = 0; + + break; + } + } + else + { // send the data received via the RF link out the comm-port + + while (TRUE) + { + // get number of data bytes received via the RF link + uint16_t ph_num = ph_getData_used(connection_index); + + // limit to how much space we have in the temp TX buffer + if (ph_num > sizeof(apiconfig_tx_buffer) - apiconfig_tx_buffer_wr) + ph_num = sizeof(apiconfig_tx_buffer) - apiconfig_tx_buffer_wr; + + if (ph_num > 0) + { // fetch the data bytes received via the RF link and save into our temp buffer + ph_num = ph_getData(connection_index, apiconfig_tx_buffer + apiconfig_tx_buffer_wr, ph_num); + apiconfig_tx_buffer_wr += ph_num; + } + + uint16_t data_size = apiconfig_tx_buffer_wr; + if (data_size == 0) + break; // no data to send + +// uint16_t data_size = apiconfig_scanForConfigPacket(apiconfig_tx_buffer, &apiconfig_tx_buffer_wr, true); +// if (data_size == 0) +// break; // no data to send + + // we have data to send down the comm-port +/* + #if (defined(PIOS_COM_DEBUG) && (PIOS_COM_DEBUG == PIOS_COM_SERIAL)) + if (!usb_comms) + { // the serial-port is being used for debugging - don't send data down it + apiconfig_tx_buffer_wr = 0; + apiconfig_tx_timer = 0; + continue; + } + #endif +*/ + if (!usb_comms && !GPIO_IN(SERIAL_CTS_PIN)) + break; // we can't yet send data down the comm-port + + // send the data out the comm-port + int32_t res; +// if (usb_comms) +// res = PIOS_COM_SendBuffer(comm_port, apiconfig_tx_buffer, data_size); +// else + res = PIOS_COM_SendBufferNonBlocking(comm_port, apiconfig_tx_buffer, data_size); + if (res < 0) + { // failed to send the data out the comm-port + + #if defined(APICONFIG_DEBUG) + DEBUG_PRINTF("PIOS_COM_SendBuffer %d %d\r\n", data_size, res); + #endif + + if (apiconfig_tx_timer >= 5000) + { // seems we can't send our data for at least the last 5 seconds - delete it + apiconfig_tx_buffer_wr = 0; + } + + break; + } + + // data was sent out the comm-port OK .. remove the sent data from our buffer + + apiconfig_tx_buffer_wr -= data_size; + if (apiconfig_tx_buffer_wr > 0) + memmove(apiconfig_tx_buffer, apiconfig_tx_buffer + data_size, apiconfig_tx_buffer_wr); + + apiconfig_tx_timer = 0; + } + } + + // ******************** +} + +// ***************************************************************************** + +void apiconfig_init(void) +{ + apiconfig_previous_com_port = -1; + + apiconfig_rx_buffer_wr = 0; + + apiconfig_tx_buffer_wr = 0; + + apiconfig_tx_config_buffer_wr = 0; + + apiconfig_rx_timer = 0; + apiconfig_tx_timer = 0; +} + +// ***************************************************************************** diff --git a/flight/PipXtreme/crc.c b/flight/PipXtreme/crc.c index 7c9c72fb9..1c297a165 100644 --- a/flight/PipXtreme/crc.c +++ b/flight/PipXtreme/crc.c @@ -103,12 +103,12 @@ static const uint32_t CRC_Table32[] = { // ************************************************************************** // 16-bit CRC -inline uint16_t UpdateCRC16(uint16_t crc, uint8_t b) +inline uint16_t updateCRC16(uint16_t crc, uint8_t b) { // update the crc - table method return ((crc >> 8) ^ CRC_Table16[(crc & 0xff) ^ b]); } /* -uint16_t UpdateCRC16(uint16_t crc, uint8_t b) +uint16_t updateCRC16(uint16_t crc, uint8_t b) { // update the fcs - bit band method register uint8_t f = (uint8_t)(crc >> 8); crc = (crc & 0x00ff) ^ b; @@ -117,7 +117,7 @@ uint16_t UpdateCRC16(uint16_t crc, uint8_t b) return (crc ^ f); } */ -uint16_t UpdateCRC16Data(uint16_t crc, void *data, uint32_t len) +uint16_t updateCRC16Data(uint16_t crc, void *data, uint32_t len) { register uint8_t *p = (uint8_t *)data; register uint16_t _crc = crc; @@ -128,7 +128,7 @@ uint16_t UpdateCRC16Data(uint16_t crc, void *data, uint32_t len) } /* // Generate the CRC table -void MakeCRC_Table16(void) +void makeCRC_Table16(void) { for (uint16_t i = 0; i < 256; i++) { @@ -142,12 +142,12 @@ void MakeCRC_Table16(void) // ************************************************************************** // 32-bit CRC -inline uint32_t UpdateCRC32(uint32_t crc, uint8_t b) +inline uint32_t updateCRC32(uint32_t crc, uint8_t b) { return ((crc << 8) ^ CRC_Table32[(crc >> 24) ^ b]); } /* -uint32_t UpdateCRC32(uint32_t crc, uint8_t b) +uint32_t updateCRC32(uint32_t crc, uint8_t b) { // update the crc - bit bang method register uint32_t f = crc << 8; crc = (crc >> 24) ^ b; @@ -156,7 +156,7 @@ uint32_t UpdateCRC32(uint32_t crc, uint8_t b) return (crc ^ f); } */ -uint32_t UpdateCRC32Data(uint32_t crc, void *data, uint32_t len) +uint32_t updateCRC32Data(uint32_t crc, void *data, uint32_t len) { register uint8_t *p = (uint8_t *)data; register uint32_t _crc = crc; @@ -167,7 +167,7 @@ uint32_t UpdateCRC32Data(uint32_t crc, void *data, uint32_t len) } /* // Generate the CRC table -void MakeCRC_Table32(void) +void makeCRC_Table32(void) { for (uint32_t i = 0; i < 256; i++) { diff --git a/flight/PipXtreme/inc/api_config.h b/flight/PipXtreme/inc/api_config.h new file mode 100644 index 000000000..5fcc2e064 --- /dev/null +++ b/flight/PipXtreme/inc/api_config.h @@ -0,0 +1,40 @@ +/** + ****************************************************************************** + * + * @file api_config.h + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief RF Module hardware layer + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * 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; either version 3 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 MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __API_CONFIG_H__ +#define __API_CONFIG_H__ + +#include "stdint.h" + +// ***************************************************************************** + +void apiconfig_1ms_tick(void); +void apiconfig_process(void); + +void apiconfig_init(void); + +// ***************************************************************************** + +#endif diff --git a/flight/PipXtreme/inc/crc.h b/flight/PipXtreme/inc/crc.h index 3d5cf1680..bb27dd5ad 100644 --- a/flight/PipXtreme/inc/crc.h +++ b/flight/PipXtreme/inc/crc.h @@ -30,11 +30,11 @@ // ******************************************************************** -uint16_t UpdateCRC16(uint16_t crc, uint8_t b); -uint16_t UpdateCRC16Data(uint16_t crc, void *data, uint32_t len); +uint16_t updateCRC16(uint16_t crc, uint8_t b); +uint16_t updateCRC16Data(uint16_t crc, void *data, uint32_t len); -uint32_t UpdateCRC32(uint32_t crc, uint8_t b); -uint32_t UpdateCRC32Data(uint32_t crc, void *data, uint32_t len); +uint32_t updateCRC32(uint32_t crc, uint8_t b); +uint32_t updateCRC32Data(uint32_t crc, void *data, uint32_t len); void CRC_init(void); diff --git a/flight/PipXtreme/inc/rfm22b.h b/flight/PipXtreme/inc/rfm22b.h index 07defa55b..39b227e15 100644 --- a/flight/PipXtreme/inc/rfm22b.h +++ b/flight/PipXtreme/inc/rfm22b.h @@ -578,8 +578,10 @@ uint32_t rfm22_getDatarate(void); void rfm22_setTxPower(uint8_t tx_pwr); uint8_t rfm22_getTxPower(void); -void rfm22_setNominalCarrierFrequency(uint32_t frequency_hz); -uint32_t rfm22_getNominalCarrierFrequency(void); +void rfm22_setNominalCarrierFrequency(float frequency_hz); +float rfm22_getNominalCarrierFrequency(void); + +float rfm22_getFrequencyStepSize(void); void rfm22_setFreqHopChannel(uint8_t channel); uint8_t rfm22_freqHopChannel(void); diff --git a/flight/PipXtreme/main.c b/flight/PipXtreme/main.c index 3f8e02994..5faf3b0dc 100644 --- a/flight/PipXtreme/main.c +++ b/flight/PipXtreme/main.c @@ -38,7 +38,8 @@ #include "rfm22b.h" #include "packet_handler.h" #include "transparent_comms.h" -#include "api_comms.h" +//#include "api_comms.h" +#include "api_config.h" #include "gpio_in.h" #include "stopwatch.h" #include "watchdog.h" @@ -273,7 +274,8 @@ void TIMER_INT_FUNC(void) if (!API_Mode) trans_1ms_tick(); // transparent communications tick else - api_1ms_tick(); // api communications tick +// api_1ms_tick(); // api communications tick + apiconfig_1ms_tick(); // api communications tick // *********** } @@ -362,8 +364,8 @@ void get_CPUDetails(void) } // create a 32-bit crc from the serial number hex string - serial_number_crc32 = UpdateCRC32Data(0xffffffff, serial_number_str, j); - serial_number_crc32 = UpdateCRC32(serial_number_crc32, j); + serial_number_crc32 = updateCRC32Data(0xffffffff, serial_number_str, j); + serial_number_crc32 = updateCRC32(serial_number_crc32, j); // reset_addr = (uint32_t)&Reset_Handler; } @@ -563,8 +565,8 @@ int main() // temp_adc = -1; // psu_adc = -1; - API_Mode = FALSE; -// API_Mode = TRUE; // TEST ONLY +// API_Mode = FALSE; + API_Mode = TRUE; // TEST ONLY second_tick_timer = 0; second_tick = FALSE; @@ -626,7 +628,8 @@ int main() trans_init(); // initialise the tranparent communications module - api_init(); // initialise the API communications module +// api_init(); // initialise the API communications module + apiconfig_init(); // initialise the API communications module setup_TimerInt(1000); // setup a 1kHz timer interrupt @@ -686,13 +689,13 @@ int main() switch (saved_settings.frequency_band) { case freqBand_434MHz: -// if (saved_settings.frequency_Hz == 0xffffffff) + if (saved_settings.min_frequency_Hz == 0xffffffff) { saved_settings.frequency_Hz = 434000000; - saved_settings.min_frequency_Hz = 434000000 - 2000000; - saved_settings.max_frequency_Hz = 434000000 + 2000000; + saved_settings.min_frequency_Hz = saved_settings.frequency_Hz - 2000000; + saved_settings.max_frequency_Hz = saved_settings.frequency_Hz + 2000000; } -// if (saved_settings.max_rf_bandwidth == 0xffffffff) + if (saved_settings.max_rf_bandwidth == 0xffffffff) { // saved_settings.max_rf_bandwidth = 500; // saved_settings.max_rf_bandwidth = 1000; @@ -708,7 +711,7 @@ int main() saved_settings.max_rf_bandwidth = 128000; // saved_settings.max_rf_bandwidth = 192000; } -// if (saved_settings.max_tx_power == 0xff) + if (saved_settings.max_tx_power == 0xff) { // saved_settings.max_tx_power = 0; // +1dBm ... 1.25mW // saved_settings.max_tx_power = 1; // +2dBm ... 1.6mW @@ -722,13 +725,13 @@ int main() break; case freqBand_868MHz: -// if (saved_settings.frequency_Hz == 0xffffffff) + if (saved_settings.min_frequency_Hz == 0xffffffff) { saved_settings.frequency_Hz = 868000000; - saved_settings.min_frequency_Hz = 868000000 - 10000000; - saved_settings.max_frequency_Hz = 868000000 + 10000000; + saved_settings.min_frequency_Hz = saved_settings.frequency_Hz - 10000000; + saved_settings.max_frequency_Hz = saved_settings.frequency_Hz + 10000000; } -// if (saved_settings.max_rf_bandwidth == 0xffffffff) + if (saved_settings.max_rf_bandwidth == 0xffffffff) { // saved_settings.max_rf_bandwidth = 500; // saved_settings.max_rf_bandwidth = 1000; @@ -744,7 +747,7 @@ int main() saved_settings.max_rf_bandwidth = 128000; // saved_settings.max_rf_bandwidth = 192000; } -// if (saved_settings.max_tx_power == 0xff) + if (saved_settings.max_tx_power == 0xff) { // saved_settings.max_tx_power = 0; // +1dBm ... 1.25mW // saved_settings.max_tx_power = 1; // +2dBm ... 1.6mW @@ -758,13 +761,13 @@ int main() break; case freqBand_915MHz: -// if (saved_settings.frequency_Hz == 0xffffffff) + if (saved_settings.min_frequency_Hz == 0xffffffff) { saved_settings.frequency_Hz = 915000000; - saved_settings.min_frequency_Hz = 915000000 - 13000000; - saved_settings.max_frequency_Hz = 915000000 + 13000000; + saved_settings.min_frequency_Hz = saved_settings.frequency_Hz - 13000000; + saved_settings.max_frequency_Hz = saved_settings.frequency_Hz + 13000000; } -// if (saved_settings.max_rf_bandwidth == 0xffffffff) + if (saved_settings.max_rf_bandwidth == 0xffffffff) { // saved_settings.max_rf_bandwidth = 500; // saved_settings.max_rf_bandwidth = 1000; @@ -780,7 +783,7 @@ int main() saved_settings.max_rf_bandwidth = 128000; // saved_settings.max_rf_bandwidth = 192000; } -// if (saved_settings.max_tx_power == 0xff) + if (saved_settings.max_tx_power == 0xff) { // saved_settings.max_tx_power = 0; // +1dBm ... 1.25mW // saved_settings.max_tx_power = 1; // +2dBm ... 1.6mW @@ -862,8 +865,8 @@ int main() for (;;) { - random32 = UpdateCRC32(random32, PIOS_DELAY_TIMER->CNT >> 8); - random32 = UpdateCRC32(random32, PIOS_DELAY_TIMER->CNT); + random32 = updateCRC32(random32, PIOS_DELAY_TIMER->CNT >> 8); + random32 = updateCRC32(random32, PIOS_DELAY_TIMER->CNT); if (second_tick) { @@ -913,9 +916,10 @@ int main() ph_process(); // packet handler processing if (!API_Mode) - trans_process(); // tranparent local communication processing (serial port and usb port) + trans_process(); // tranparent local communication processing (serial port and usb port) else - api_process(); // API local communication processing (serial port and usb port) +// api_process(); // API local communication processing (serial port and usb port) + apiconfig_process(); // API local communication processing (serial port and usb port) diff --git a/flight/PipXtreme/packet_handler.c b/flight/PipXtreme/packet_handler.c index 3ac6b9cfc..0d1425f78 100644 --- a/flight/PipXtreme/packet_handler.c +++ b/flight/PipXtreme/packet_handler.c @@ -273,7 +273,7 @@ uint16_t ph_getData(const int connection_index, void *data, uint16_t len) int ph_startConnect(int connection_index, uint32_t sn) { - random32 = UpdateCRC32(random32, 0xff); + random32 = updateCRC32(random32, 0xff); if (connection_index < 0 || connection_index >= PH_MAX_CONNECTIONS) return -1; @@ -443,7 +443,7 @@ bool ph_sendPacket(int connection_index, bool encrypt, uint8_t packet_type, bool // ensure the 1st byte is not zero - to indicate this packet is encrypted while (enc_cbc[0] == 0) { - random32 = UpdateCRC32(random32, 0xff); + random32 = updateCRC32(random32, 0xff); enc_cbc[0] ^= random32; } @@ -481,9 +481,9 @@ bool ph_sendPacket(int connection_index, bool encrypt, uint8_t packet_type, bool // complete the packet header by adding the CRC if (encrypt) - header->crc = UpdateCRC32Data(0xffffffff, header, packet_size - AES_BLOCK_SIZE); + header->crc = updateCRC32Data(0xffffffff, header, packet_size - AES_BLOCK_SIZE); else - header->crc = UpdateCRC32Data(0xffffffff, header, packet_size - 1); + header->crc = updateCRC32Data(0xffffffff, header, packet_size - 1); // ****************** // encrypt the packet @@ -600,7 +600,7 @@ void ph_processPacket2(bool was_encrypted, t_packet_header *header, uint8_t *dat uint16_t data_size = header->data_size; // update the ramdon number - random32 = UpdateCRC32(random32, 0xff); + random32 = updateCRC32(random32, 0xff); // ********************* // debug stuff @@ -1105,7 +1105,7 @@ void ph_processRxPacket(void) return; } - random32 = UpdateCRC32(random32 ^ header->crc, 0xff); // help randomize the random number + random32 = updateCRC32(random32 ^ header->crc, 0xff); // help randomize the random number // ********************* // help to randomize the tx aes cbc bytes by using the received packet @@ -1192,9 +1192,9 @@ void ph_processRxPacket(void) crc1 = header->crc; header->crc = 0; if (encrypted) - crc2 = UpdateCRC32Data(0xffffffff, header, packet_size - AES_BLOCK_SIZE); + crc2 = updateCRC32Data(0xffffffff, header, packet_size - AES_BLOCK_SIZE); else - crc2 = UpdateCRC32Data(0xffffffff, header, packet_size - 1); + crc2 = updateCRC32Data(0xffffffff, header, packet_size - 1); if (crc1 != crc2) { // corrupt packet #if defined(PACKET_DEBUG) @@ -1222,7 +1222,7 @@ void ph_processLinks(int connection_index) if (connection_index < 0 || connection_index >= PH_MAX_CONNECTIONS) return; - random32 = UpdateCRC32(random32, 0xff); + random32 = updateCRC32(random32, 0xff); t_connection *conn = &connection[connection_index]; @@ -1427,7 +1427,7 @@ void ph_set_AES128_key(const void *key) int ph_set_remote_serial_number(int connection_index, uint32_t sn) { - random32 = UpdateCRC32(random32, 0xff); + random32 = updateCRC32(random32, 0xff); if (ph_startConnect(connection_index, sn) >= 0) { @@ -1453,7 +1453,7 @@ void ph_1ms_tick(void) register uint32_t *cbc = (uint32_t *)&enc_cbc; for (int i = 0; i < sizeof(enc_cbc) / 4; i++) { - random32 = UpdateCRC32(random32, 0xff); + random32 = updateCRC32(random32, 0xff); *cbc++ ^= random32; } @@ -1516,7 +1516,7 @@ void ph_init(uint32_t our_sn, uint32_t datarate_bps, uint8_t tx_power) for (int i = 0; i < PH_MAX_CONNECTIONS; i++) { - random32 = UpdateCRC32(random32, 0xff); + random32 = updateCRC32(random32, 0xff); t_connection *conn = &connection[i]; @@ -1570,7 +1570,7 @@ void ph_init(uint32_t our_sn, uint32_t datarate_bps, uint8_t tx_power) // try too randomize the tx AES CBC bytes for (uint32_t j = 0, k = 0; j < 123 + (random32 & 1023); j++) { - random32 = UpdateCRC32(random32, 0xff); + random32 = updateCRC32(random32, 0xff); enc_cbc[k] ^= random32 >> 3; if (++k >= sizeof(enc_cbc)) k = 0; } diff --git a/flight/PipXtreme/reserved/api_comms.c b/flight/PipXtreme/reserved/api_comms.c new file mode 100644 index 000000000..7abf89349 --- /dev/null +++ b/flight/PipXtreme/reserved/api_comms.c @@ -0,0 +1,500 @@ +/** + ****************************************************************************** + * + * @file api_comms.h + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief RF Module hardware layer + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * 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; either version 3 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 MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + + + +// see http://newwiki.openpilot.org/display/Doc/UAVTalk .. for UAVTalk protocol description +// +// This module scans for OP UAVTalk packets in the comm-port or RF data streams. +// It will discard any corrupt/invalid packets and only pass valid ones. + + + +#include + +#include "stm32f10x.h" +#include "gpio_in.h" +#include "api_comms.h" +#include "packet_handler.h" +#include "main.h" + +#if defined(PIOS_COM_DEBUG) + #define API_DEBUG +#endif + +// ***************************************************************************** +// modem configuration packets + +typedef struct +{ + uint32_t marker; + uint32_t serial_number; + uint8_t type; + uint8_t spare; + uint16_t data_size; + uint32_t header_crc; + uint32_t data_crc; +// uint8_t data[0]; +} __attribute__((__packed__)) t_pipx_config_header; + +typedef struct +{ + uint8_t mode; + uint8_t state; +} __attribute__((__packed__)) t_pipx_config_data_mode_state; + +typedef struct +{ + uint32_t serial_baudrate; // serial uart baudrate + + uint32_t destination_id; + + uint32_t min_frequency_Hz; + uint32_t max_frequency_Hz; + uint32_t frequency_Hz; + + uint32_t max_rf_bandwidth; + + uint8_t max_tx_power; + + uint8_t frequency_band; + + uint8_t rf_xtal_cap; + + bool aes_enable; + uint8_t aes_key[16]; + + uint16_t frequency_step_size; +} __attribute__((__packed__)) t_pipx_config_data_settings; + +typedef struct +{ + uint32_t start_frequency; + uint16_t frequency_step_size; + uint16_t magnitudes; +// int8_t magnitude[0]; +} __attribute__((__packed__)) t_pipx_config_data_spectrum; + +// ***************************************************************************** + +typedef struct +{ + uint8_t sync_byte; + uint8_t message_type; + uint16_t packet_size; // not including CRC byte + uint32_t object_id; +} __attribute__((__packed__)) t_uav_header1; + +typedef struct +{ + uint8_t sync_byte; + uint8_t message_type; + uint16_t packet_size; // not including CRC byte + uint32_t object_id; + uint16_t instance_id; +} __attribute__((__packed__)) t_uav_header2; + +#define SYNC_VAL 0x3C +#define TYPE_MASK 0xFC +#define TYPE_VER 0x20 +#define TYPE_OBJ (TYPE_VER | 0x00) +#define TYPE_OBJ_REQ (TYPE_VER | 0x01) +#define TYPE_OBJ_ACK (TYPE_VER | 0x02) +#define TYPE_ACK (TYPE_VER | 0x03) + +#define MIN_HEADER_LENGTH sizeof(t_uav_header1) +#define MAX_HEADER_LENGTH sizeof(t_uav_header2) +#define MAX_PAYLOAD_LENGTH 256 +#define CHECKSUM_LENGTH 1 + +#define MAX_PACKET_LENGTH (MAX_HEADER_LENGTH + MAX_PAYLOAD_LENGTH + CHECKSUM_LENGTH) + +// CRC lookup table +static const uint8_t crc_table[256] = { + 0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15, 0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d, + 0x70, 0x77, 0x7e, 0x79, 0x6c, 0x6b, 0x62, 0x65, 0x48, 0x4f, 0x46, 0x41, 0x54, 0x53, 0x5a, 0x5d, + 0xe0, 0xe7, 0xee, 0xe9, 0xfc, 0xfb, 0xf2, 0xf5, 0xd8, 0xdf, 0xd6, 0xd1, 0xc4, 0xc3, 0xca, 0xcd, + 0x90, 0x97, 0x9e, 0x99, 0x8c, 0x8b, 0x82, 0x85, 0xa8, 0xaf, 0xa6, 0xa1, 0xb4, 0xb3, 0xba, 0xbd, + 0xc7, 0xc0, 0xc9, 0xce, 0xdb, 0xdc, 0xd5, 0xd2, 0xff, 0xf8, 0xf1, 0xf6, 0xe3, 0xe4, 0xed, 0xea, + 0xb7, 0xb0, 0xb9, 0xbe, 0xab, 0xac, 0xa5, 0xa2, 0x8f, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9d, 0x9a, + 0x27, 0x20, 0x29, 0x2e, 0x3b, 0x3c, 0x35, 0x32, 0x1f, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0d, 0x0a, + 0x57, 0x50, 0x59, 0x5e, 0x4b, 0x4c, 0x45, 0x42, 0x6f, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7d, 0x7a, + 0x89, 0x8e, 0x87, 0x80, 0x95, 0x92, 0x9b, 0x9c, 0xb1, 0xb6, 0xbf, 0xb8, 0xad, 0xaa, 0xa3, 0xa4, + 0xf9, 0xfe, 0xf7, 0xf0, 0xe5, 0xe2, 0xeb, 0xec, 0xc1, 0xc6, 0xcf, 0xc8, 0xdd, 0xda, 0xd3, 0xd4, + 0x69, 0x6e, 0x67, 0x60, 0x75, 0x72, 0x7b, 0x7c, 0x51, 0x56, 0x5f, 0x58, 0x4d, 0x4a, 0x43, 0x44, + 0x19, 0x1e, 0x17, 0x10, 0x05, 0x02, 0x0b, 0x0c, 0x21, 0x26, 0x2f, 0x28, 0x3d, 0x3a, 0x33, 0x34, + 0x4e, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5c, 0x5b, 0x76, 0x71, 0x78, 0x7f, 0x6a, 0x6d, 0x64, 0x63, + 0x3e, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2c, 0x2b, 0x06, 0x01, 0x08, 0x0f, 0x1a, 0x1d, 0x14, 0x13, + 0xae, 0xa9, 0xa0, 0xa7, 0xb2, 0xb5, 0xbc, 0xbb, 0x96, 0x91, 0x98, 0x9f, 0x8a, 0x8d, 0x84, 0x83, + 0xde, 0xd9, 0xd0, 0xd7, 0xc2, 0xc5, 0xcc, 0xcb, 0xe6, 0xe1, 0xe8, 0xef, 0xfa, 0xfd, 0xf4, 0xf3 +}; + +// ***************************************************************************** +// local variables + +int8_t api_previous_com_port = -1; + +volatile uint16_t api_rx_timer = 0; +volatile uint16_t api_tx_timer = 0; + +uint8_t api_rx_buffer[MAX_PACKET_LENGTH] __attribute__ ((aligned(4))); +uint16_t api_rx_buffer_wr; + +uint8_t api_tx_buffer[MAX_PACKET_LENGTH] __attribute__ ((aligned(4))); +uint16_t api_tx_buffer_wr; + +// ***************************************************************************** +// 8-bit CRC updating + +uint8_t api_updateCRC_byte(uint8_t crc, uint8_t b) +{ + return crc_table[crc ^ b]; +} + +uint8_t api_updateCRC_buffer(uint8_t crc, const void *data, int32_t length) +{ + // use registers for speed + register uint8_t crc8 = crc; + register const uint8_t *p = (uint8_t *)data; + + for (register int32_t i = length; i > 0; i--) + crc8 = crc_table[crc8 ^ *p++]; + + return crc8; +} + +// returned value < 0 if no valid packet detected. +// otherwise returned value is the total size of the valid UAVTalk packet found in the buffer. +// +// any corrupt/invalid UAVTalk packets/data are deleted from the buffer and we scan for the next valid packet. +int16_t api_scanForUAVTalkPacket(void *buf, uint16_t *len) +{ + uint8_t *buffer = (uint8_t *)buf; + + t_uav_header1 *header1 = (t_uav_header1 *)buf; +// t_uav_header2 *header2 = (t_uav_header2 *)buf; + + register uint16_t num_bytes = *len; + + if (num_bytes < MIN_HEADER_LENGTH + CHECKSUM_LENGTH) + return -1; // not yet enough bytes for a complete packet + + while (TRUE) + { + // scan the buffer for the start of a UAVTalk packet + for (uint16_t i = 0; i < num_bytes; i++) + { + if (api_rx_buffer[i] != SYNC_VAL) + continue; // not the start of a packet - move on to the next byte in the buffer + + // possible start of packet found - we found a SYNC byte + + if (i > 0) + { // remove/delete leading bytes before the SYNC byte + num_bytes -= i; + if (num_bytes > 0) + memmove(buffer, buffer + i, num_bytes); + *len = num_bytes; + } + break; + } + + if (num_bytes < MIN_HEADER_LENGTH + CHECKSUM_LENGTH) + return -2; // not yet enough bytes for a complete packet + + if (header1->sync_byte != SYNC_VAL) + { // SYNC byte was not found - start of UAVTalk packet not found in any of the data in the buffer + *len = 0; // empty the entire buffer + return -3; + } + + if (header1->packet_size < MIN_HEADER_LENGTH || header1->packet_size > MAX_HEADER_LENGTH + MAX_PAYLOAD_LENGTH) + { // the packet size value is too small or too big - assume either a corrupt UAVTalk packet or we are at the start of a packet +// if (--num_bytes > 0) +// memmove(buffer, buffer + 1, num_bytes); // remove 1st byte +// *len = num_bytes; + buffer[0] ^= 0xaa; // corrupt the sync byte - we'll move the buffer bytes down further up in the code + continue; // continue scanning for a valid packet in the buffer + } + + if (num_bytes < header1->packet_size + CHECKSUM_LENGTH) + { // not yet enough bytes for a complete packet + return -4; + } + + // check the packet CRC + uint8_t crc1 = api_updateCRC_buffer(0, buffer, header1->packet_size); + uint8_t crc2 = buffer[header1->packet_size]; + if (crc1 != crc2) + { // faulty CRC +// if (--num_bytes > 0) +// memmove(buffer, buffer + 1, num_bytes); // remove 1st byte +// *len = num_bytes; + buffer[0] ^= 0xaa; // corrupt the sync byte - we'll move the buffer bytes down further up in the code + + #if defined(API_DEBUG) + DEBUG_PRINTF("UAVTalk packet corrupt %d\r\n", header1->packet_size + 1); + #endif + + continue; // continue scanning for a valid packet in the buffer + } + + #if defined(API_DEBUG) + DEBUG_PRINTF("UAVTalk packet found %d\r\n", header1->packet_size + 1); + #endif + + return (header1->packet_size + CHECKSUM_LENGTH); // return the size of the UAVTalk packet + } + + return -5; +} + +// ***************************************************************************** + +int16_t api_scanForConfigPacket(void *buf, uint16_t *len) +{ + return -1; +} + +// ***************************************************************************** +// can be called from an interrupt if you wish + +void api_1ms_tick(void) +{ // call this once every 1ms + + if (api_rx_timer < 0xffff) api_rx_timer++; + if (api_tx_timer < 0xffff) api_tx_timer++; +} + +// ***************************************************************************** +// call this as often as possible - not from an interrupt + +void api_process(void) +{ // copy data from comm-port RX buffer to RF packet handler TX buffer, and from RF packet handler RX buffer to comm-port TX buffer + + // ******************** + // decide which comm-port we are using (usart or usb) + + bool usb_comms = false; // TRUE if we are using the usb port for comms. + uint8_t comm_port = PIOS_COM_SERIAL; // default to using the usart comm-port + + #if defined(PIOS_INCLUDE_USB_HID) + if (PIOS_USB_HID_CheckAvailable(0)) + { // USB comms is up, use the USB comm-port instead of the USART comm-port + usb_comms = true; + comm_port = PIOS_COM_TELEM_USB; + } + #endif + + // ******************** + // check to see if the local communication port has changed (usart/usb) + + if (api_previous_com_port < 0 && api_previous_com_port != comm_port) + { // the local communications port has changed .. remove any data in the buffers + api_rx_buffer_wr = 0; + api_tx_buffer_wr = 0; + } + else + if (usb_comms) + { // we're using the USB for comms - keep the USART rx buffer empty + int32_t bytes = PIOS_COM_ReceiveBufferUsed(PIOS_COM_SERIAL); + while (bytes > 0) + { + PIOS_COM_ReceiveBuffer(PIOS_COM_SERIAL); + bytes--; + } + } + + api_previous_com_port = comm_port; // remember the current comm-port we are using + + // ******************** + + uint16_t connection_index = 0; // the RF connection we are using + + // ******************** + // send the data received from the local comm-port to the RF packet handler TX buffer + + while (TRUE) + { + int16_t packet_size; + + // free space size in the RF packet handler tx buffer + uint16_t ph_num = ph_putData_free(connection_index); + + // get the number of data bytes received down the comm-port + int32_t com_num = PIOS_COM_ReceiveBufferUsed(comm_port); + + // set the USART RTS handshaking line + if (!usb_comms && ph_connected(connection_index)) + { + if (ph_num < 32) + SERIAL_RTS_CLEAR; // lower the USART RTS line - we don't have space in the buffer for anymore bytes + else + SERIAL_RTS_SET; // release the USART RTS line - we have space in the buffer for now bytes + } + else + SERIAL_RTS_SET; // release the USART RTS line + + // limit number of bytes we will get to how much space we have in our RX buffer + if (com_num > sizeof(api_rx_buffer) - api_rx_buffer_wr) + com_num = sizeof(api_rx_buffer) - api_rx_buffer_wr; + + while (com_num > 0) + { // fetch a byte from the comm-port RX buffer and save it into our RX buffer + api_rx_buffer[api_rx_buffer_wr++] = PIOS_COM_ReceiveBuffer(comm_port); + com_num--; + } + +// packet_size = api_scanForConfigPacket(api_rx_buffer, &api_rx_buffer_wr); + + packet_size = api_scanForUAVTalkPacket(api_rx_buffer, &api_rx_buffer_wr); + if (packet_size < 0) + break; // no UAVTalk packet in our RX buffer + + api_rx_timer = 0; + + if (!ph_connected(connection_index)) + { // we don't have a link to a remote modem .. remove the UAVTalk packet from our RX buffer + if (api_rx_buffer_wr > packet_size) + { + api_rx_buffer_wr -= packet_size; + memmove(api_rx_buffer, api_rx_buffer + packet_size, api_rx_buffer_wr); + } + else + api_rx_buffer_wr = 0; + continue; + } + + if (ph_num < packet_size) + break; // not enough room in the RF packet handler TX buffer for the UAVTalk packet + + // copy the rx'ed UAVTalk packet into the RF packet handler TX buffer for sending over the RF link + ph_putData(connection_index, api_rx_buffer, packet_size); + + // remove the UAVTalk packet from our RX buffer + if (api_rx_buffer_wr > packet_size) + { + api_rx_buffer_wr -= packet_size; + memmove(api_rx_buffer, api_rx_buffer + packet_size, api_rx_buffer_wr); + } + else + api_rx_buffer_wr = 0; + } + + // ******************** + // send the data received via the RF link out the comm-port + + while (TRUE) + { + // get number of data bytes received via the RF link + uint16_t ph_num = ph_getData_used(connection_index); + + // limit to how much space we have in the temp TX buffer + if (ph_num > sizeof(api_tx_buffer) - api_tx_buffer_wr) + ph_num = sizeof(api_tx_buffer) - api_tx_buffer_wr; + + if (ph_num > 0) + { // fetch the data bytes received via the RF link and save into our temp buffer + ph_num = ph_getData(connection_index, api_tx_buffer + api_tx_buffer_wr, ph_num); + api_tx_buffer_wr += ph_num; + } + + int16_t packet_size = api_scanForUAVTalkPacket(api_tx_buffer, &api_tx_buffer_wr); + + if (packet_size <= 0) + break; // no UAV Talk packet found + + // we have a UAVTalk packet to send down the comm-port +/* + #if (defined(PIOS_COM_DEBUG) && (PIOS_COM_DEBUG == PIOS_COM_SERIAL)) + if (!usb_comms) + { // the serial-port is being used for debugging - don't send data down it + api_tx_buffer_wr = 0; + api_tx_timer = 0; + continue; + } + #endif +*/ + if (!usb_comms && !GPIO_IN(SERIAL_CTS_PIN)) + break; // we can't yet send data down the comm-port + + // send the data out the comm-port + int32_t res; +// if (usb_comms) +// res = PIOS_COM_SendBuffer(comm_port, api_tx_buffer, packet_size); +// else + res = PIOS_COM_SendBufferNonBlocking(comm_port, api_tx_buffer, packet_size); // this one doesn't work properly with USB :( + if (res < 0) + { // failed to send the data out the comm-port + #if defined(API_DEBUG) + DEBUG_PRINTF("PIOS_COM_SendBuffer %d %d\r\n", packet_size, res); + #endif + + if (api_tx_timer >= 5000) + { // seems we can't send our data for at least the last 5 seconds - delete it + if (api_tx_buffer_wr > packet_size) + { + api_tx_buffer_wr -= packet_size; + memmove(api_tx_buffer, api_tx_buffer + packet_size, api_tx_buffer_wr); + } + else + api_tx_buffer_wr = 0; + } + + break; + } + + // data was sent out the comm-port OK .. remove the sent data from our buffer + + if (api_tx_buffer_wr > packet_size) + { + api_tx_buffer_wr -= packet_size; + memmove(api_tx_buffer, api_tx_buffer + packet_size, api_tx_buffer_wr); + } + else + api_tx_buffer_wr = 0; + + api_tx_timer = 0; + } + + // ******************** +} + +// ***************************************************************************** + +void api_init(void) +{ + api_previous_com_port = -1; + + api_rx_buffer_wr = 0; + + api_tx_buffer_wr = 0; + + api_rx_timer = 0; + api_tx_timer = 0; +} + +// ***************************************************************************** diff --git a/flight/PipXtreme/reserved/api_comms.h b/flight/PipXtreme/reserved/api_comms.h new file mode 100644 index 000000000..9f9cece0f --- /dev/null +++ b/flight/PipXtreme/reserved/api_comms.h @@ -0,0 +1,40 @@ +/** + ****************************************************************************** + * + * @file api_comms.h + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief RF Module hardware layer + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * 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; either version 3 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 MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __API_COMMS_H__ +#define __API_COMMS_H__ + +#include "stdint.h" + +// ***************************************************************************** + +void api_1ms_tick(void); +void api_process(void); + +void api_init(void); + +// ***************************************************************************** + +#endif diff --git a/flight/PipXtreme/rfm22b.c b/flight/PipXtreme/rfm22b.c index ed07d3020..a96790dcb 100644 --- a/flight/PipXtreme/rfm22b.c +++ b/flight/PipXtreme/rfm22b.c @@ -175,7 +175,7 @@ volatile uint8_t rf_mode; // holds our current RF mode uint32_t lower_carrier_frequency_limit_Hz; // the minimum RF frequency we can use uint32_t upper_carrier_frequency_limit_Hz; // the maximum RF frequency we can use -uint32_t carrier_frequency_hz; // the current RF frequency we are on +float carrier_frequency_hz; // the current RF frequency we are on uint32_t carrier_datarate_bps; // the RF data rate we are using @@ -547,7 +547,7 @@ uint8_t rfm22_getTxPower(void) // ************************************ -void rfm22_setNominalCarrierFrequency(uint32_t frequency_hz) +void rfm22_setNominalCarrierFrequency(float frequency_hz) { #if defined(RFM22_EXT_INT_USE) @@ -562,13 +562,13 @@ void rfm22_setNominalCarrierFrequency(uint32_t frequency_hz) carrier_frequency_hz = frequency_hz; - if (frequency_hz < 480000000ul) + if (frequency_hz < 480000000) hbsel = 1; else hbsel = 2; - uint8_t fb = frequency_hz / (10000000ul * hbsel); + uint8_t fb = (uint8_t)(frequency_hz / (10000000 * hbsel)); - uint32_t fc = frequency_hz - (10000000ul * hbsel * fb); + uint32_t fc = (uint32_t)(frequency_hz - (10000000 * hbsel * fb)); fc = (fc * 64u) / (10000ul * hbsel); fb -= 24; @@ -592,7 +592,7 @@ void rfm22_setNominalCarrierFrequency(uint32_t frequency_hz) // ******* #if defined(RFM22_DEBUG) - DEBUG_PRINTF("rf setFreq: %u\r\n", carrier_frequency_hz); + DEBUG_PRINTF("rf setFreq: %0.2f\r\n", carrier_frequency_hz); #endif #if defined(RFM22_EXT_INT_USE) @@ -601,11 +601,16 @@ void rfm22_setNominalCarrierFrequency(uint32_t frequency_hz) } -uint32_t rfm22_getNominalCarrierFrequency(void) +float rfm22_getNominalCarrierFrequency(void) { return carrier_frequency_hz; } +float rfm22_getFrequencyStepSize(void) +{ + return frequency_step_size; +} + void rfm22_setFreqHopChannel(uint8_t channel) { // set the frequency hopping channel frequency_hop_channel = channel; @@ -1541,7 +1546,7 @@ void rfm22_process(void) if (power_on_reset) { // we need to re-initialize the RF module - it told us it's reset itself - uint32_t current_freq = carrier_frequency_hz; // fetch current rf nominal frequency + float current_freq = carrier_frequency_hz; // fetch current rf nominal frequency uint32_t freq_hop_step_size = (uint32_t)frequency_hop_step_size_reg * 10000; // fetch the frequency hoppping step size rfm22_init(lower_carrier_frequency_limit_Hz, upper_carrier_frequency_limit_Hz, freq_hop_step_size); rfm22_setNominalCarrierFrequency(current_freq); // restore the nominal carrier frequency diff --git a/flight/PipXtreme/saved_settings.c b/flight/PipXtreme/saved_settings.c index a5f72aa38..8e585f668 100644 --- a/flight/PipXtreme/saved_settings.c +++ b/flight/PipXtreme/saved_settings.c @@ -109,7 +109,7 @@ int32_t saved_settings_read(void) // calculate and check the CRC uint32_t crc1 = tmp_settings.crc; tmp_settings.crc = 0; - uint32_t crc2 = UpdateCRC32Data(0xffffffff, (void *)&tmp_settings, sizeof(t_saved_settings)); + uint32_t crc2 = updateCRC32Data(0xffffffff, (void *)&tmp_settings, sizeof(t_saved_settings)); if (crc2 != crc1) { #if defined(SAVED_SETTINGS_DEBUG) @@ -151,7 +151,7 @@ int32_t saved_settings_save(void) // calculate and add the CRC saved_settings.crc = 0; - saved_settings.crc = UpdateCRC32Data(0xffffffff, (void *)&saved_settings, sizeof(t_saved_settings)); + saved_settings.crc = updateCRC32Data(0xffffffff, (void *)&saved_settings, sizeof(t_saved_settings)); // ***************************************** // first check to see if we need to save the settings @@ -304,8 +304,10 @@ void saved_settings_init(void) saved_settings.aes_enable = FALSE; memmove((void *)&saved_settings.aes_key, saved_settings_default_aes_key, sizeof(saved_settings.aes_key)); + saved_settings.serial_baudrate = 57600; + // saved_settings.crc = 0; -// saved_settings.crc = UpdateCRC32Data(0xffffffff, (void *)&saved_settings, sizeof(t_saved_settings)); +// saved_settings.crc = updateCRC32Data(0xffffffff, (void *)&saved_settings, sizeof(t_saved_settings)); // **********