1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2024-11-29 07:24:13 +01:00
LibrePilot/flight/PipXtreme/api_config.c
Stacey Sheldon 5f8760a55c com: Move buffering out of USART/HID layer and into COM layer
This allows the spektrum and sbus receiver drivers to bind
directly to the usart layer using a properly exported API
rather than overriding the interrupt handler.

Bytes are now pushed directly from the usart layer into the
com layer without any buffering.  The com layer performs all
of the buffering.

A further benefit from this approach is that we can put all
blocking/non-blocking behaviour into the COM layer and not
in the underlying drivers.

Misc related changes:
 - Remove obsolete .handler field from irq configs
 - Adapt all users of PIOS_COM_* functions to new API
 - Fixup callers of PIOS_USB_HID_Init()
2011-07-27 19:45:38 -04:00

868 lines
29 KiB
C

/**
******************************************************************************
*
* @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 <string.h>
#include "stm32f10x.h"
#include "gpio_in.h"
#include "api_config.h"
#include "rfm22b.h"
#include "packet_handler.h"
#include "stream.h"
#include "ppm.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
enum {
PIPX_PACKET_TYPE_REQ_DETAILS = 0,
PIPX_PACKET_TYPE_DETAILS,
PIPX_PACKET_TYPE_REQ_SETTINGS,
PIPX_PACKET_TYPE_SETTINGS,
PIPX_PACKET_TYPE_REQ_STATE,
PIPX_PACKET_TYPE_STATE,
PIPX_PACKET_TYPE_SPECTRUM
};
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 major_version;
uint8_t minor_version;
uint32_t serial_number;
uint32_t min_frequency_Hz;
uint32_t max_frequency_Hz;
uint8_t frequency_band;
float frequency_step_size;
} __attribute__((__packed__)) t_pipx_config_details;
typedef struct
{
uint8_t mode;
uint8_t link_state;
int16_t rssi;
int32_t afc;
uint16_t retries;
} __attribute__((__packed__)) t_pipx_config_state;
typedef struct
{
uint8_t mode;
uint32_t serial_baudrate; // serial usart baudrate
uint32_t destination_id;
uint32_t frequency_Hz;
uint32_t max_rf_bandwidth;
uint8_t max_tx_power;
uint8_t rf_xtal_cap;
bool aes_enable;
uint8_t aes_key[16];
uint8_t rts_time;
uint8_t spare[16];
} __attribute__((__packed__)) t_pipx_config_settings;
typedef struct
{
uint32_t start_frequency;
uint16_t frequency_step_size;
uint16_t magnitudes;
// int8_t magnitude[0];
} __attribute__((__packed__)) t_pipx_config_spectrum;
// *****************************************************************************
// local variables
uint32_t apiconfig_previous_com_port = 0;
volatile uint16_t apiconfig_rx_config_timer = 0;
volatile uint16_t apiconfig_rx_timer = 0;
volatile uint16_t apiconfig_tx_timer = 0;
volatile uint16_t apiconfig_ss_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;
// for scanning the spectrum
int8_t apiconfig_spec_buffer[64] __attribute__ ((aligned(4)));
uint16_t apiconfig_spec_buffer_wr;
uint32_t apiconfig_spec_start_freq;
uint32_t apiconfig_spec_freq;
bool apiconfig_usb_comms;
uint32_t apiconfig_comm_port;
uint16_t apiconfig_connection_index; // the RF connection we are using
uint8_t led_counter;
// *****************************************************************************
int apiconfig_sendDetailsPacket(void)
{
if (sizeof(apiconfig_tx_config_buffer) - apiconfig_tx_config_buffer_wr < sizeof(t_pipx_config_header) + sizeof(t_pipx_config_details))
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_details *details = (t_pipx_config_details *)((uint8_t *)header + sizeof(t_pipx_config_header));
header->marker = PIPX_HEADER_MARKER;
header->serial_number = serial_number_crc32;
header->type = PIPX_PACKET_TYPE_DETAILS;
header->spare = 0;
header->data_size = sizeof(t_pipx_config_details);
details->major_version = VERSION_MAJOR;
details->minor_version = VERSION_MINOR;
details->serial_number = serial_number_crc32;
details->min_frequency_Hz = saved_settings.min_frequency_Hz;
details->max_frequency_Hz = saved_settings.max_frequency_Hz;
details->frequency_band = saved_settings.frequency_band;
details->frequency_step_size = rfm22_getFrequencyStepSize();
header->data_crc = updateCRC32Data(0xffffffff, details, 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: details\r\n");
#endif
return total_packet_size;
}
int apiconfig_sendStatePacket(void)
{
if (sizeof(apiconfig_tx_config_buffer) - apiconfig_tx_config_buffer_wr < sizeof(t_pipx_config_header) + sizeof(t_pipx_config_state))
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_state *state = (t_pipx_config_state *)((uint8_t *)header + sizeof(t_pipx_config_header));
header->marker = PIPX_HEADER_MARKER;
header->serial_number = serial_number_crc32;
header->type = PIPX_PACKET_TYPE_STATE;
header->spare = 0;
header->data_size = sizeof(t_pipx_config_state);
state->mode = 0;
state->link_state = ph_getCurrentLinkState(0);
state->rssi = ph_getLastRSSI(0);
state->afc = ph_getLastAFC(0);
state->retries = ph_getRetries(0);
header->data_crc = updateCRC32Data(0xffffffff, state, 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: state\r\n");
#endif
return total_packet_size;
}
int apiconfig_sendSettingsPacket(void)
{
if (sizeof(apiconfig_tx_config_buffer) - apiconfig_tx_config_buffer_wr < sizeof(t_pipx_config_header) + sizeof(t_pipx_config_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_settings *settings = (t_pipx_config_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_SETTINGS;
header->spare = 0;
header->data_size = sizeof(t_pipx_config_settings);
settings->mode = saved_settings.mode;
settings->destination_id = saved_settings.destination_id;
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->rf_xtal_cap = saved_settings.rf_xtal_cap;
settings->serial_baudrate = saved_settings.serial_baudrate;
settings->aes_enable = saved_settings.aes_enable;
memcpy((char *)settings->aes_key, (char *)saved_settings.aes_key, sizeof(settings->aes_key));
settings->rts_time = saved_settings.rts_time;
memset(settings->spare, 0xff, sizeof(settings->spare));
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: settings\r\n");
#endif
return total_packet_size;
}
int apiconfig_sendSpectrumPacket(uint32_t start_frequency, uint16_t freq_step_size, void *spectrum_data, uint32_t spectrum_data_size)
{
if (sizeof(apiconfig_tx_config_buffer) - apiconfig_tx_config_buffer_wr < sizeof(t_pipx_config_header) + sizeof(t_pipx_config_spectrum) + spectrum_data_size)
return -1; // not enough room in the tx buffer for the packet we were going to send
if (!spectrum_data || spectrum_data_size <= 0)
return -2; // nothing to send
t_pipx_config_header *header = (t_pipx_config_header *)(apiconfig_tx_config_buffer + apiconfig_tx_config_buffer_wr);
t_pipx_config_spectrum *spectrum = (t_pipx_config_spectrum *)((uint8_t *)header + sizeof(t_pipx_config_header));
uint8_t *data = (uint8_t *)spectrum + sizeof(t_pipx_config_spectrum);
header->marker = PIPX_HEADER_MARKER;
header->serial_number = serial_number_crc32;
header->type = PIPX_PACKET_TYPE_SPECTRUM;
header->spare = 0;
header->data_size = sizeof(t_pipx_config_spectrum) + spectrum_data_size;
spectrum->start_frequency = start_frequency;
spectrum->frequency_step_size = freq_step_size;
spectrum->magnitudes = spectrum_data_size;
memmove(data, spectrum_data, spectrum_data_size);
header->data_crc = updateCRC32Data(0xffffffff, spectrum, 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: spectrum\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_DETAILS:
#if defined(APICONFIG_DEBUG)
DEBUG_PRINTF("RX api config: req_details\r\n");
#endif
if (header->serial_number == 0 || header->serial_number == 0xffffffff || header->serial_number == serial_number_crc32)
apiconfig_sendDetailsPacket();
break;
case PIPX_PACKET_TYPE_REQ_STATE:
#if defined(APICONFIG_DEBUG)
DEBUG_PRINTF("RX api config: req_state\r\n");
#endif
if (header->serial_number == serial_number_crc32)
apiconfig_sendStatePacket();
break;
case PIPX_PACKET_TYPE_REQ_SETTINGS: // they are requesting our configuration
#if defined(APICONFIG_DEBUG)
DEBUG_PRINTF("RX api config: req_settings\r\n");
#endif
if (header->serial_number == serial_number_crc32)
apiconfig_sendSettingsPacket();
break;
case PIPX_PACKET_TYPE_SETTINGS: // they have sent us new configuration settings
#if defined(APICONFIG_DEBUG)
DEBUG_PRINTF("RX api config: settings\r\n");
#endif
if (header->serial_number == serial_number_crc32)
{ // the packet is meant for us
booting = true;
ph_set_remote_serial_number(0, 0); // stop the packet handler trying to communicate
// ******
// save the new settings
t_pipx_config_settings *settings = (t_pipx_config_settings *)data;
saved_settings.mode = settings->mode;
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.rts_time = settings->rts_time;
saved_settings_save(); // save them into flash
// ******
ph_deinit();
stream_deinit();
ppm_deinit();
PIOS_COM_ChangeBaud(PIOS_COM_SERIAL, saved_settings.serial_baudrate);
switch (saved_settings.mode)
{
case MODE_NORMAL: // normal 2-way packet mode
case MODE_STREAM_TX: // 1-way continuous tx packet mode
case MODE_STREAM_RX: // 1-way continuous rx packet mode
case MODE_PPM_TX: // PPM tx mode
case MODE_PPM_RX: // PPM rx mode
case MODE_SCAN_SPECTRUM: // scan the receiver over the whole band
case MODE_TX_BLANK_CARRIER_TEST: // blank carrier Tx mode (for calibrating the carrier frequency say)
case MODE_TX_SPECTRUM_TEST: // pseudo random Tx data mode (for checking the Tx carrier spectrum)
break;
default: // unknown mode
saved_settings.mode = MODE_NORMAL;
break;
}
switch (saved_settings.mode)
{
case MODE_NORMAL: // normal 2-way packet mode
ph_init(serial_number_crc32); // initialise the packet handler
break;
case MODE_STREAM_TX: // 1-way continuous tx packet mode
case MODE_STREAM_RX: // 1-way continuous rx packet mode
stream_init(serial_number_crc32); // initialise the continuous packet stream module
break;
case MODE_PPM_TX: // PPM tx mode
case MODE_PPM_RX: // PPM rx mode
ppm_init(serial_number_crc32); // initialise the PPM module
break;
case MODE_SCAN_SPECTRUM: // scan the receiver over the whole band
rfm22_init_scan_spectrum(saved_settings.min_frequency_Hz, saved_settings.max_frequency_Hz);
rfm22_setFreqCalibration(saved_settings.rf_xtal_cap);
apiconfig_spec_start_freq = saved_settings.min_frequency_Hz;
apiconfig_spec_freq = apiconfig_spec_start_freq;
apiconfig_spec_buffer_wr = 0;
apiconfig_ss_timer = 0;
break;
case MODE_TX_BLANK_CARRIER_TEST: // blank carrier Tx mode (for calibrating the carrier frequency say)
rfm22_init_normal(saved_settings.min_frequency_Hz, saved_settings.max_frequency_Hz, rfm22_freqHopSize());
rfm22_setFreqCalibration(saved_settings.rf_xtal_cap);
rfm22_setNominalCarrierFrequency(saved_settings.frequency_Hz);
rfm22_setDatarate(saved_settings.max_rf_bandwidth, TRUE);
rfm22_setTxPower(saved_settings.max_tx_power);
rfm22_setTxCarrierMode();
break;
case MODE_TX_SPECTRUM_TEST: // pseudo random Tx data mode (for checking the Tx carrier spectrum)
rfm22_init_normal(saved_settings.min_frequency_Hz, saved_settings.max_frequency_Hz, rfm22_freqHopSize());
rfm22_setFreqCalibration(saved_settings.rf_xtal_cap);
rfm22_setNominalCarrierFrequency(saved_settings.frequency_Hz);
rfm22_setDatarate(saved_settings.max_rf_bandwidth, TRUE);
rfm22_setTxPower(saved_settings.max_tx_power);
rfm22_setTxPNMode();
break;
}
// ******
booting = false;
}
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_config_timer = 0; // reset timer
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;
}
// *****************************************************************************
// send the data received from the local comm-port to the RF packet handler TX buffer
void apiconfig_processTx(void)
{
while (TRUE)
{
// scan for a configuration packet in the rx buffer
uint16_t data_size = apiconfig_scanForConfigPacket(apiconfig_rx_buffer, &apiconfig_rx_buffer_wr, false);
uint16_t time_out = 5; // ms
if (!apiconfig_usb_comms) time_out = (15000 * sizeof(t_pipx_config_header)) / saved_settings.serial_baudrate; // allow enough time to rx a config header
if (time_out < 5) time_out = 5;
if (data_size == 0 && apiconfig_rx_timer >= time_out)
// 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 (saved_settings.mode == MODE_NORMAL || saved_settings.mode == MODE_STREAM_TX)
{
// free space size in the RF packet handler tx buffer
uint16_t ph_num = ph_putData_free(apiconfig_connection_index);
// set the USART RTS handshaking line
if (!apiconfig_usb_comms && ph_connected(apiconfig_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
#if defined(APICONFIG_DEBUG)
DEBUG_PRINTF("RX api config: data size %u\r\n", data_size);
#endif
if (ph_connected(apiconfig_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(apiconfig_connection_index, apiconfig_rx_buffer, data_size);
}
}
else
{
SERIAL_RTS_SET; // release the USART RTS line - we have space in the buffer for now bytes
}
// 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
void apiconfig_processRx(void)
{
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 (!apiconfig_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 = PIOS_COM_SendBufferNonBlocking(apiconfig_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;
}
return;
}
if (saved_settings.mode == MODE_NORMAL || saved_settings.mode == MODE_STREAM_RX)
{
// 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(apiconfig_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(apiconfig_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
// we have data to send down the comm-port
/*
#if (defined(PIOS_COM_DEBUG) && (PIOS_COM_DEBUG == PIOS_COM_SERIAL))
if (!apiconfig_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 (!apiconfig_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 = PIOS_COM_SendBufferNonBlocking(apiconfig_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_process_scan_spectrum(void)
{
if (saved_settings.mode != MODE_SCAN_SPECTRUM)
return;
if (apiconfig_ss_timer < 1) return; // 1ms
apiconfig_ss_timer = 0;
if (++led_counter >= 30)
{
led_counter = 0;
// RX_LED_TOGGLE;
LINK_LED_TOGGLE;
}
// uint16_t freq_step_size = (uint16_t)(rfm22_getFrequencyStepSize() * 4 + 0.5f);
uint16_t freq_step_size = (uint16_t)(rfm22_getFrequencyStepSize() * 20 + 0.5f);
// fetch the current rssi level
int16_t rssi_dbm = rfm22_getRSSI();
if (rssi_dbm < -128) rssi_dbm = -128;
else
if (rssi_dbm > 0) rssi_dbm = 0;
// onto next frequency
apiconfig_spec_freq += freq_step_size;
if (apiconfig_spec_freq >= rfm22_maxFrequency()) apiconfig_spec_freq = rfm22_minFrequency();
rfm22_setNominalCarrierFrequency(apiconfig_spec_freq);
// rfm22_setRxMode(RX_SCAN_SPECTRUM, true);
// add the RSSI value to the buffer
apiconfig_spec_buffer[apiconfig_spec_buffer_wr] = rssi_dbm;
if (++apiconfig_spec_buffer_wr >= sizeof(apiconfig_spec_buffer))
{ // send the buffer
apiconfig_sendSpectrumPacket(apiconfig_spec_start_freq, freq_step_size, apiconfig_spec_buffer, apiconfig_spec_buffer_wr);
apiconfig_spec_buffer_wr = 0;
apiconfig_spec_start_freq = apiconfig_spec_freq;
}
}
// *****************************************************************************
// 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
apiconfig_process_scan_spectrum();
// ********************
// decide which comm-port we are using (usart or usb)
apiconfig_usb_comms = false; // TRUE if we are using the usb port for comms.
apiconfig_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
apiconfig_usb_comms = true;
apiconfig_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 != apiconfig_comm_port)
{ // the local communications port has changed .. remove any data in the buffers
apiconfig_rx_buffer_wr = 0;
apiconfig_tx_buffer_wr = 0;
apiconfig_tx_config_buffer_wr = 0;
}
else
if (apiconfig_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)
{
uint8_t c;
PIOS_COM_ReceiveBuffer(PIOS_COM_SERIAL, &c, 1, 0);
bytes--;
}
}
apiconfig_previous_com_port = apiconfig_comm_port; // remember the current comm-port we are using
apiconfig_connection_index = 0; // the RF connection we are using
// *******************
// fetch the data received via the comm-port
// get the number of data bytes received down the comm-port
int32_t com_num = PIOS_COM_ReceiveBufferUsed(apiconfig_comm_port);
// 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
uint8_t c;
PIOS_COM_ReceiveBuffer(apiconfig_comm_port, &c, 1, 0);
apiconfig_rx_buffer[apiconfig_rx_buffer_wr++] = c;
com_num--;
}
apiconfig_processTx();
apiconfig_processRx();
// speed the pinging speed up if the GCS is connected and monitoring the signal level etc
ph_setFastPing(apiconfig_rx_config_timer < 2000);
}
// *****************************************************************************
// can be called from an interrupt if you wish
void apiconfig_1ms_tick(void)
{ // call this once every 1ms
if (apiconfig_rx_config_timer < 0xffff) apiconfig_rx_config_timer++;
if (apiconfig_rx_timer < 0xffff) apiconfig_rx_timer++;
if (apiconfig_tx_timer < 0xffff) apiconfig_tx_timer++;
if (apiconfig_ss_timer < 0xffff) apiconfig_ss_timer++;
}
// *****************************************************************************
void apiconfig_init(void)
{
apiconfig_previous_com_port = 0;
apiconfig_rx_buffer_wr = 0;
apiconfig_tx_buffer_wr = 0;
apiconfig_tx_config_buffer_wr = 0;
apiconfig_rx_config_timer = 0xffff;
apiconfig_rx_timer = 0;
apiconfig_tx_timer = 0;
apiconfig_ss_timer = 0;
apiconfig_spec_buffer_wr = 0;
apiconfig_spec_start_freq = 0;
led_counter = 0;
}
// *****************************************************************************