mirror of
https://bitbucket.org/librepilot/librepilot.git
synced 2025-01-18 03:52:11 +01:00
Merge branch 'Brian-PipXtreme-V2' of ssh://git.openpilot.org/OpenPilot into Brian-PipXtreme-V2
This commit is contained in:
commit
0734f64817
@ -1,7 +1,7 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @addtogroup OpenPilotModules OpenPilot Modules
|
||||
* @brief The OpenPilot Modules do the majority of the control in OpenPilot. The
|
||||
* @brief The OpenPilot Modules do the majority of the control in OpenPilot. The
|
||||
* @ref PipXtremeModule The PipXtreme Module is the equivalanet of the System
|
||||
* Module for the PipXtreme modem. it starts all the other modules.
|
||||
# This is done through the @ref PIOS "PIOS Hardware abstraction layer",
|
||||
@ -47,12 +47,6 @@
|
||||
#define SYSTEM_UPDATE_PERIOD_MS 1000
|
||||
#define LED_BLINK_RATE_HZ 5
|
||||
|
||||
#ifndef IDLE_COUNTS_PER_SEC_AT_NO_LOAD
|
||||
#define IDLE_COUNTS_PER_SEC_AT_NO_LOAD 995998 // calibrated by running tests/test_cpuload.c
|
||||
// must be updated if the FreeRTOS or compiler
|
||||
// optimisation options are changed.
|
||||
#endif
|
||||
|
||||
#if defined(PIOS_SYSTEM_STACK_SIZE)
|
||||
#define STACK_SIZE_BYTES PIOS_SYSTEM_STACK_SIZE
|
||||
#else
|
||||
@ -108,7 +102,7 @@ int32_t PipXtremeModInitialize(void)
|
||||
const struct pios_board_info * bdinfo = &pios_board_info_blob;
|
||||
|
||||
pipxStatus.BoardType= bdinfo->board_type;
|
||||
//PIOS_BL_HELPER_FLASH_Read_Description(pipxStatus.Description, PIPXSTATUS_DESCRIPTION_NUMELEM);
|
||||
PIOS_BL_HELPER_FLASH_Read_Description(pipxStatus.Description, PIPXSTATUS_DESCRIPTION_NUMELEM);
|
||||
PIOS_SYS_SerialNumberGetBinary(pipxStatus.CPUSerial);
|
||||
pipxStatus.BoardRevision= bdinfo->board_rev;
|
||||
|
||||
@ -159,50 +153,6 @@ static void systemTask(void *parameters)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef NEVER
|
||||
/**
|
||||
* Called periodically to update the system stats
|
||||
*/
|
||||
static uint16_t GetFreeIrqStackSize(void)
|
||||
{
|
||||
uint32_t i = 0x200;
|
||||
|
||||
#if !defined(ARCH_POSIX) && !defined(ARCH_WIN32) && defined(CHECK_IRQ_STACK)
|
||||
extern uint32_t _irq_stack_top;
|
||||
extern uint32_t _irq_stack_end;
|
||||
uint32_t pattern = 0x0000A5A5;
|
||||
uint32_t *ptr = &_irq_stack_end;
|
||||
|
||||
#if 1 /* the ugly way accurate but takes more time, useful for debugging */
|
||||
uint32_t stack_size = (((uint32_t)&_irq_stack_top - (uint32_t)&_irq_stack_end) & ~3 ) / 4;
|
||||
|
||||
for (i=0; i< stack_size; i++)
|
||||
{
|
||||
if (ptr[i] != pattern)
|
||||
{
|
||||
i=i*4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else /* faster way but not accurate */
|
||||
if (*(volatile uint32_t *)((uint32_t)ptr + IRQSTACK_LIMIT_CRITICAL) != pattern)
|
||||
{
|
||||
i = IRQSTACK_LIMIT_CRITICAL - 1;
|
||||
}
|
||||
else if (*(volatile uint32_t *)((uint32_t)ptr + IRQSTACK_LIMIT_WARNING) != pattern)
|
||||
{
|
||||
i = IRQSTACK_LIMIT_WARNING - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
i = IRQSTACK_LIMIT_WARNING;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
return i;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Called by the RTOS when the CPU is idle, used to measure the CPU idle time.
|
||||
*/
|
||||
|
@ -630,7 +630,7 @@ static void transparentCommTask(void * parameters)
|
||||
|
||||
// Receive data from the com port
|
||||
uint32_t cur_rx_bytes = PIOS_COM_ReceiveBuffer(PIOS_COM_TRANS_COM, p->data + p->header.data_size,
|
||||
PH_MAX_DATA - p->header.data_size, timeout);
|
||||
PH_MAX_DATA - p->header.data_size, timeout);
|
||||
|
||||
// Do we have an data to send?
|
||||
p->header.data_size += cur_rx_bytes;
|
||||
|
@ -1,852 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @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"
|
||||
#include "pios_usb.h" /* PIOS_USB_* */
|
||||
|
||||
#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)
|
||||
if (PIOS_USB_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
|
||||
uint8_t c;
|
||||
while (PIOS_COM_ReceiveBuffer(PIOS_COM_SERIAL, &c, 1, 0) > 0);
|
||||
}
|
||||
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
|
||||
uint16_t buf_avail = sizeof(apiconfig_rx_buffer) - apiconfig_rx_buffer_wr;
|
||||
|
||||
PIOS_COM_ReceiveBuffer(apiconfig_comm_port, &(apiconfig_rx_buffer[apiconfig_rx_buffer_wr]), buf_avail, 0);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
@ -1,189 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file crc.c
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief Serial communication port handling routines
|
||||
* @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 "crc.h"
|
||||
|
||||
// **************************************************************************
|
||||
|
||||
#define Poly16 0x8408 // HDLC polynomial: 1 + x**5 + x**12 + x**16
|
||||
#define Poly32 0x04c11db7 // 32-bit polynomial .. this should produce the same as the STM32 hardware CRC
|
||||
|
||||
static const uint16_t CRC_Table16[] = { // HDLC polynomial
|
||||
0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
|
||||
0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
|
||||
0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
|
||||
0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
|
||||
0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
|
||||
0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
|
||||
0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
|
||||
0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
|
||||
0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
|
||||
0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
|
||||
0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
|
||||
0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
|
||||
0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
|
||||
0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
|
||||
0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
|
||||
0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
|
||||
0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
|
||||
0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
|
||||
0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
|
||||
0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
|
||||
0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
|
||||
0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
|
||||
0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
|
||||
0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
|
||||
0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
|
||||
0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
|
||||
0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
|
||||
0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
|
||||
0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
|
||||
0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
|
||||
0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
|
||||
0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
|
||||
};
|
||||
|
||||
static const uint32_t CRC_Table32[] = {
|
||||
0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
|
||||
0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
|
||||
0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
|
||||
0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
|
||||
0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
|
||||
0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
|
||||
0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
|
||||
0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
|
||||
0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
|
||||
0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
|
||||
0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
|
||||
0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
|
||||
0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
|
||||
0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
|
||||
0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
|
||||
0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
|
||||
0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
|
||||
0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
|
||||
0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
|
||||
0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
|
||||
0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
|
||||
0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
|
||||
0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
|
||||
0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
|
||||
0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
|
||||
0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
|
||||
0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
|
||||
0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
|
||||
0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
|
||||
0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
|
||||
0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
|
||||
0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
|
||||
};
|
||||
|
||||
// **************************************************************************
|
||||
// 16-bit CRC
|
||||
|
||||
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)
|
||||
{ // update the fcs - bit band method
|
||||
register uint8_t f = (uint8_t)(crc >> 8);
|
||||
crc = (crc & 0x00ff) ^ b;
|
||||
for (int i = 8; i > 0; i--)
|
||||
crc = (crc & 1) ? (crc >> 1) ^ Poly16 : crc >> 1;
|
||||
return (crc ^ f);
|
||||
}
|
||||
*/
|
||||
uint16_t updateCRC16Data(uint16_t crc, void *data, uint32_t len)
|
||||
{
|
||||
register uint8_t *p = (uint8_t *)data;
|
||||
register uint16_t _crc = crc;
|
||||
for (register uint32_t i = len; i > 0; i--)
|
||||
_crc = (_crc >> 8) ^ CRC_Table16[(_crc ^ *p++) & 0xff];
|
||||
// _crc = UpdateCRC16(_crc, *p++);
|
||||
return _crc;
|
||||
}
|
||||
/*
|
||||
// Generate the CRC table
|
||||
void makeCRC_Table16(void)
|
||||
{
|
||||
for (uint16_t i = 0; i < 256; i++)
|
||||
{
|
||||
uint16_t crc = i;
|
||||
for (int j = 8; j > 0; j--)
|
||||
crc = (crc & 1) ? (crc >> 1) ^ Poly16 : crc >> 1;
|
||||
CRC_Table16[i] = crc;
|
||||
}
|
||||
}
|
||||
*/
|
||||
// **************************************************************************
|
||||
// 32-bit CRC
|
||||
|
||||
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)
|
||||
{ // update the crc - bit bang method
|
||||
register uint32_t f = crc << 8;
|
||||
crc = (crc >> 24) ^ b;
|
||||
for (int i = 8; i > 0; i--)
|
||||
crc = (crc & 1) ? (crc << 1) ^ Poly32 : crc << 1;
|
||||
return (crc ^ f);
|
||||
}
|
||||
*/
|
||||
uint32_t updateCRC32Data(uint32_t crc, void *data, uint32_t len)
|
||||
{
|
||||
register uint8_t *p = (uint8_t *)data;
|
||||
register uint32_t _crc = crc;
|
||||
for (register uint32_t i = len; i > 0; i--)
|
||||
_crc = (_crc << 8) ^ CRC_Table32[(_crc >> 24) ^ *p++];
|
||||
// _crc = UpdateCRC32(_crc, *p++);
|
||||
return _crc;
|
||||
}
|
||||
/*
|
||||
// Generate the CRC table
|
||||
void makeCRC_Table32(void)
|
||||
{
|
||||
for (uint32_t i = 0; i < 256; i++)
|
||||
{
|
||||
uint32_t crc = i;
|
||||
for (int j = 8; j > 0; j--)
|
||||
crc = (crc & 1) ? (crc << 1) ^ Poly32 : crc << 1;
|
||||
CRC_Table32[i] = crc;
|
||||
}
|
||||
}
|
||||
*/
|
||||
// **************************************************************************
|
||||
|
||||
void CRC_init(void)
|
||||
{
|
||||
// MakeCRC_Table16();
|
||||
// MakeCRC_Table32();
|
||||
}
|
||||
|
||||
// **************************************************************************
|
@ -1,182 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file gpio_in.c
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief GPIO input functions
|
||||
* @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
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* *****************************************************************
|
||||
// Example pin definitions .. this would go into your pios_board.h file
|
||||
|
||||
// GPIO_Mode_AIN Analog Input
|
||||
// GPIO_Mode_IN_FLOATING Input Floating
|
||||
// GPIO_Mode_IPD Input Pull-Down
|
||||
// GPIO_Mode_IPU Input Pull-up
|
||||
|
||||
// API mode line
|
||||
#define GPIO_IN_0_PORT GPIOB
|
||||
#define GPIO_IN_0_PIN GPIO_Pin_13
|
||||
#define GPIO_IN_0_MODE GPIO_Mode_IPU
|
||||
|
||||
// Serial port CTS line
|
||||
#define GPIO_IN_1_PORT GPIOB
|
||||
#define GPIO_IN_1_PIN GPIO_Pin_14
|
||||
#define GPIO_IN_1_MODE GPIO_Mode_IPU
|
||||
|
||||
#define GPIO_IN_NUM 2
|
||||
#define GPIO_IN_PORTS { GPIO_IN_0_PORT, GPIO_IN_1_PORT }
|
||||
#define GPIO_IN_PINS { GPIO_IN_0_PIN, GPIO_IN_1_PIN }
|
||||
#define GPIO_IN_MODES { GPIO_IN_0_MODE, GPIO_IN_1_MODE }
|
||||
|
||||
#define API_MODE_PIN 0
|
||||
#define SERIAL_CTS_PIN 1
|
||||
|
||||
*********************************************************************
|
||||
Example usage ..
|
||||
|
||||
{
|
||||
|
||||
|
||||
|
||||
// setup all the GPIO input pins
|
||||
GPIO_IN_Init();
|
||||
|
||||
|
||||
|
||||
|
||||
if (!GPIO_IN(API_MODE_PIN))
|
||||
{ // pin is LOW
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{ // pin is HIGH
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
***************************************************************************** */
|
||||
|
||||
|
||||
|
||||
|
||||
#include <pios.h>
|
||||
|
||||
#include "gpio_in.h"
|
||||
|
||||
// *****************************************************************************
|
||||
// setup the GPIO input pins
|
||||
|
||||
// PORT ..
|
||||
// GPIOA
|
||||
// GPIOB
|
||||
// GPIOC
|
||||
// GPIOD
|
||||
// GPIOE
|
||||
// GPIOF
|
||||
// GPIOG
|
||||
|
||||
// PIN ..
|
||||
// GPIO_Pin_0
|
||||
// GPIO_Pin_1
|
||||
// GPIO_Pin_2
|
||||
// GPIO_Pin_3
|
||||
// GPIO_Pin_4
|
||||
// GPIO_Pin_5
|
||||
// GPIO_Pin_6
|
||||
// GPIO_Pin_7
|
||||
// GPIO_Pin_8
|
||||
// GPIO_Pin_9
|
||||
// GPIO_Pin_10
|
||||
// GPIO_Pin_11
|
||||
// GPIO_Pin_12
|
||||
// GPIO_Pin_13
|
||||
// GPIO_Pin_14
|
||||
// GPIO_Pin_15
|
||||
|
||||
// MODE ..
|
||||
// GPIO_Mode_AIN Analog Input
|
||||
// GPIO_Mode_IN_FLOATING Input Floating
|
||||
// GPIO_Mode_IPD Input Pull-Down
|
||||
// GPIO_Mode_IPU Input Pull-up
|
||||
|
||||
#if defined(GPIO_IN_NUM) && defined(GPIO_IN_PORTS) && defined(GPIO_IN_PINS) && defined(GPIO_IN_MODES)
|
||||
// #if defined(PIOS_INCLUDE_GPIO_IN) && defined(PIOS_GPIO_IN_NUM) && defined(PIOS_GPIO_IN_PORTS) && defined(PIOS_GPIO_IN_PINS) && defined(PIOS_GPIO_IN_MODES)
|
||||
|
||||
// Local Variables
|
||||
static GPIO_TypeDef *GPIO_IN_PORT[GPIO_IN_NUM] = GPIO_IN_PORTS;
|
||||
static const uint32_t GPIO_IN_PIN[GPIO_IN_NUM] = GPIO_IN_PINS;
|
||||
static const uint32_t GPIO_IN_MODE[GPIO_IN_NUM] = GPIO_IN_MODES;
|
||||
|
||||
/**
|
||||
* Initialises all the GPIO INPUT's
|
||||
*/
|
||||
void GPIO_IN_Init(void)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
|
||||
for (int i = 0; i < GPIO_IN_NUM; i++)
|
||||
{
|
||||
switch ((uint32_t)GPIO_IN_PORT[i])
|
||||
{
|
||||
case (uint32_t)GPIOA: RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); break;
|
||||
case (uint32_t)GPIOB: RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); break;
|
||||
case (uint32_t)GPIOC: RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); break;
|
||||
case (uint32_t)GPIOD: RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE); break;
|
||||
case (uint32_t)GPIOE: RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE); break;
|
||||
case (uint32_t)GPIOF: RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF, ENABLE); break;
|
||||
case (uint32_t)GPIOG: RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG, ENABLE); break;
|
||||
}
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_IN_PIN[i];
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_IN_MODE[i];
|
||||
GPIO_Init(GPIO_IN_PORT[i], &GPIO_InitStructure);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read input pin level
|
||||
* \param[num] Pin Pin Number
|
||||
*/
|
||||
bool GPIO_IN(uint8_t num)
|
||||
{ // return ..
|
||||
// FALSE if the input pin is LOW
|
||||
// TRUE if the input pin is HIGH
|
||||
if (num >= GPIO_IN_NUM) return FALSE;
|
||||
return ((GPIO_IN_PORT[num]->IDR & GPIO_IN_PIN[num]) != 0);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// ***********************************************************************************
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
@ -1,40 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @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
|
@ -1,43 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file crc.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief Serial communication port handling routines
|
||||
* @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 _CRC_H_
|
||||
#define _CRC_H_
|
||||
|
||||
#include "stm32f10x.h"
|
||||
|
||||
// ********************************************************************
|
||||
|
||||
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);
|
||||
|
||||
void CRC_init(void);
|
||||
|
||||
// ********************************************************************
|
||||
|
||||
#endif
|
@ -1,41 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file gpio_in.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief GPIO functions header.
|
||||
* @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 __GPIO_IN_H__
|
||||
#define __GPIO_IN_H__
|
||||
|
||||
// *****************************************************************
|
||||
|
||||
void GPIO_IN_Init(void);
|
||||
bool GPIO_IN(uint8_t num);
|
||||
|
||||
// *****************************************************************
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
@ -1,74 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file main.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief Main modem header.
|
||||
* @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 __MAIN_H__
|
||||
#define __MAIN_H__
|
||||
|
||||
#include <pios.h>
|
||||
|
||||
// *****************************************************************************
|
||||
|
||||
// firmware version
|
||||
#define VERSION_MAJOR 0 // 0 to 255
|
||||
#define VERSION_MINOR 9 // 0 to 255
|
||||
|
||||
// macro's for reading internal flash memory
|
||||
#define mem8(addr) (*((volatile uint8_t *)(addr)))
|
||||
#define mem16(addr) (*((volatile uint16_t *)(addr)))
|
||||
#define mem32(addr) (*((volatile uint32_t *)(addr)))
|
||||
|
||||
enum {
|
||||
FREQBAND_UNKNOWN = 0,
|
||||
FREQBAND_434MHz,
|
||||
FREQBAND_868MHz,
|
||||
FREQBAND_915MHz
|
||||
};
|
||||
|
||||
enum {
|
||||
MODE_NORMAL = 0, // normal 2-way packet mode
|
||||
MODE_STREAM_TX, // 1-way continuous tx packet mode
|
||||
MODE_STREAM_RX, // 1-way continuous rx packet mode
|
||||
MODE_PPM_TX, // PPM tx mode
|
||||
MODE_PPM_RX, // PPM rx mode
|
||||
MODE_SCAN_SPECTRUM, // scan the receiver over the whole band
|
||||
MODE_TX_BLANK_CARRIER_TEST, // blank carrier Tx mode (for calibrating the carrier frequency say)
|
||||
MODE_TX_SPECTRUM_TEST // pseudo random Tx data mode (for checking the Tx carrier spectrum)
|
||||
};
|
||||
|
||||
// *****************************************************************************
|
||||
|
||||
extern volatile uint32_t random32;
|
||||
|
||||
extern bool booting;
|
||||
|
||||
extern uint32_t flash_size;
|
||||
|
||||
extern char serial_number_str[25];
|
||||
extern uint32_t serial_number_crc32;
|
||||
|
||||
// *****************************************************************************
|
||||
|
||||
#endif
|
@ -1,76 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file packet_handler.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief Modem packet handling routines
|
||||
* @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 __PACKET_HANDLER_H__
|
||||
#define __PACKET_HANDLER_H__
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
// *****************************************************************************
|
||||
|
||||
#define PH_MAX_CONNECTIONS 1 // maximum number of remote connections
|
||||
|
||||
// *****************************************************************************
|
||||
|
||||
void ph_1ms_tick(void);
|
||||
void ph_process(void);
|
||||
|
||||
bool ph_connected(const int connection_index);
|
||||
|
||||
uint16_t ph_putData_free(const int connection_index);
|
||||
uint16_t ph_putData(const int connection_index, const void *data, uint16_t len);
|
||||
|
||||
uint16_t ph_getData_used(const int connection_index);
|
||||
uint16_t ph_getData(const int connection_index, void *data, uint16_t len);
|
||||
|
||||
void ph_setFastPing(bool fast);
|
||||
|
||||
uint16_t ph_getRetries(const int connection_index);
|
||||
|
||||
uint8_t ph_getCurrentLinkState(const int connection_index);
|
||||
|
||||
int16_t ph_getLastRSSI(const int connection_index);
|
||||
int32_t ph_getLastAFC(const int connection_index);
|
||||
|
||||
void ph_setNominalCarrierFrequency(uint32_t frequency_hz);
|
||||
uint32_t ph_getNominalCarrierFrequency(void);
|
||||
|
||||
void ph_setDatarate(uint32_t datarate_bps);
|
||||
uint32_t ph_getDatarate(void);
|
||||
|
||||
void ph_setTxPower(uint8_t tx_power);
|
||||
uint8_t ph_getTxPower(void);
|
||||
|
||||
void ph_set_AES128_key(const void *key);
|
||||
|
||||
int ph_set_remote_serial_number(int connection_index, uint32_t sn);
|
||||
void ph_set_remote_encryption(int connection_index, bool enabled, const void *key);
|
||||
|
||||
void ph_deinit(void);
|
||||
void ph_init(uint32_t our_sn);
|
||||
|
||||
// *****************************************************************************
|
||||
|
||||
#endif
|
@ -1,45 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file pios_config.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief PiOS configuration header.
|
||||
* - Central compile time config for the project.
|
||||
* @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 PIOS_CONFIG_H
|
||||
#define PIOS_CONFIG_H
|
||||
|
||||
/* Enable/Disable PiOS Modules */
|
||||
#define PIOS_INCLUDE_ADC
|
||||
#define PIOS_INCLUDE_DELAY
|
||||
#define PIOS_INCLUDE_IRQ
|
||||
#define PIOS_INCLUDE_LED
|
||||
#define PIOS_INCLUDE_SPI
|
||||
#define PIOS_INCLUDE_SYS
|
||||
#define PIOS_INCLUDE_USART
|
||||
#define PIOS_INCLUDE_COM
|
||||
#define PIOS_INCLUDE_GPIO
|
||||
#define PIOS_INCLUDE_EXTI
|
||||
#define PIOS_INCLUDE_USB
|
||||
#define PIOS_INCLUDE_USB_HID
|
||||
|
||||
#endif /* PIOS_CONFIG_H */
|
@ -1,43 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @addtogroup PIOS PIOS Core hardware abstraction layer
|
||||
* @{
|
||||
* @addtogroup PIOS_USB_BOARD Board specific USB definitions
|
||||
* @brief Board specific USB definitions
|
||||
* @{
|
||||
*
|
||||
* @file pios_usb_board_data.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief Board specific USB definitions
|
||||
* @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 PIOS_USB_BOARD_DATA_H
|
||||
#define PIOS_USB_BOARD_DATA_H
|
||||
|
||||
#define PIOS_USB_BOARD_HID_DATA_LENGTH 64
|
||||
|
||||
#define PIOS_USB_BOARD_EP_NUM 2
|
||||
|
||||
#include "pios_usb_defs.h" /* struct usb_* */
|
||||
|
||||
#define PIOS_USB_BOARD_PRODUCT_ID USB_PRODUCT_ID_PIPXTREME
|
||||
#define PIOS_USB_BOARD_DEVICE_VER USB_OP_DEVICE_VER(USB_OP_BOARD_ID_PIPXTREME, USB_OP_BOARD_MODE_FW)
|
||||
|
||||
#endif /* PIOS_USB_BOARD_DATA_H */
|
@ -1,40 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file ppm.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief Sends or Receives the ppm values to/from the remote unit
|
||||
* @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 PPM_H_
|
||||
#define PPM_H_
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
// *************************************************************
|
||||
|
||||
void ppm_1ms_tick(void);
|
||||
void ppm_process(void);
|
||||
void ppm_deinit(void);
|
||||
void ppm_init(uint32_t our_sn);
|
||||
|
||||
// *************************************************************
|
||||
|
||||
#endif
|
@ -1,643 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file rfm22b.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 __RFM22B_H__
|
||||
#define __RFM22B_H__
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
// ************************************
|
||||
|
||||
#define RFM22_DEVICE_VERSION_V2 0x02
|
||||
#define RFM22_DEVICE_VERSION_A0 0x04
|
||||
#define RFM22_DEVICE_VERSION_B1 0x06
|
||||
|
||||
// ************************************
|
||||
|
||||
#define RFM22_MIN_CARRIER_FREQUENCY_HZ 240000000ul
|
||||
#define RFM22_MAX_CARRIER_FREQUENCY_HZ 930000000ul
|
||||
|
||||
// ************************************
|
||||
|
||||
enum { RX_SCAN_SPECTRUM = 0,
|
||||
RX_WAIT_PREAMBLE_MODE,
|
||||
RX_WAIT_SYNC_MODE,
|
||||
RX_DATA_MODE,
|
||||
TX_DATA_MODE,
|
||||
TX_STREAM_MODE,
|
||||
TX_CARRIER_MODE,
|
||||
TX_PN_MODE};
|
||||
|
||||
// ************************************
|
||||
|
||||
#define BIT0 (1u << 0)
|
||||
#define BIT1 (1u << 1)
|
||||
#define BIT2 (1u << 2)
|
||||
#define BIT3 (1u << 3)
|
||||
#define BIT4 (1u << 4)
|
||||
#define BIT5 (1u << 5)
|
||||
#define BIT6 (1u << 6)
|
||||
#define BIT7 (1u << 7)
|
||||
|
||||
// ************************************
|
||||
|
||||
#define RFM22_DEVICE_TYPE 0x00 // R
|
||||
#define RFM22_DT_MASK 0x1F
|
||||
|
||||
#define RFM22_DEVICE_VERSION 0x01 // R
|
||||
#define RFM22_DV_MASK 0x1F
|
||||
|
||||
#define RFM22_device_status 0x02 // R
|
||||
#define RFM22_ds_cps_mask 0x03 // Chip Power State mask
|
||||
#define RFM22_ds_cps_idle 0x00 // IDLE Chip Power State
|
||||
#define RFM22_ds_cps_rx 0x01 // RX Chip Power State
|
||||
#define RFM22_ds_cps_tx 0x02 // TX Chip Power State
|
||||
//#define RFM22_ds_lockdet 0x04 //
|
||||
//#define RFM22_ds_freqerr 0x08 //
|
||||
#define RFM22_ds_headerr 0x10 // Header Error Status. Indicates if the received packet has a header check error
|
||||
#define RFM22_ds_rxffem 0x20 // RX FIFO Empty Status
|
||||
#define RFM22_ds_ffunfl 0x40 // RX/TX FIFO Underflow Status
|
||||
#define RFM22_ds_ffovfl 0x80 // RX/TX FIFO Overflow Status
|
||||
|
||||
#define RFM22_interrupt_status1 0x03 // R
|
||||
#define RFM22_is1_icrerror BIT0 // CRC Error. When set to 1 the cyclic redundancy check is failed.
|
||||
#define RFM22_is1_ipkvalid BIT1 // Valid Packet Received.When set to 1 a valid packet has been received.
|
||||
#define RFM22_is1_ipksent BIT2 // Packet Sent Interrupt. When set to1 a valid packet has been transmitted.
|
||||
#define RFM22_is1_iext BIT3 // External Interrupt. When set to 1 an interrupt occurred on one of the GPIO’s if it is programmed so. The status can be checked in register 0Eh. See GPIOx Configuration section for the details.
|
||||
#define RFM22_is1_irxffafull BIT4 // RX FIFO Almost Full.When set to 1 the RX FIFO has met its almost full threshold and needs to be read by the microcontroller.
|
||||
#define RFM22_is1_ixtffaem BIT5 // TX FIFO Almost Empty. When set to 1 the TX FIFO is almost empty and needs to be filled.
|
||||
#define RFM22_is1_itxffafull BIT6 // TX FIFO Almost Full. When set to 1 the TX FIFO has met its almost full threshold and needs to be transmitted.
|
||||
#define RFM22_is1_ifferr BIT7 // FIFO Underflow/Overflow Error. When set to 1 the TX or RX FIFO has overflowed or underflowed.
|
||||
|
||||
#define RFM22_interrupt_status2 0x04 // R
|
||||
#define RFM22_is2_ipor BIT0 // Power-on-Reset (POR). When the chip detects a Power on Reset above the desired setting this bit will be set to 1.
|
||||
#define RFM22_is2_ichiprdy BIT1 // Chip Ready (XTAL). When a chip ready event has been detected this bit will be set to 1.
|
||||
#define RFM22_is2_ilbd BIT2 // Low Battery Detect. When a low battery event is been detected this bit will be set to 1. This interrupt event is saved even if it is not enabled by the mask register bit and causes an interrupt after it is enabled.
|
||||
#define RFM22_is2_iwut BIT3 // Wake-Up-Timer. On the expiration of programmed wake-up timer this bit will be set to 1.
|
||||
#define RFM22_is2_irssi BIT4 // RSSI. When RSSI level exceeds the programmed threshold this bit will be set to 1.
|
||||
#define RFM22_is2_ipreainval BIT5 // Invalid Preamble Detected. When the preamble is not found within a period of time set by the invalid preamble detection threshold in Register 54h, this bit will be set to 1.
|
||||
#define RFM22_is2_ipreaval BIT6 // Valid Preamble Detected. When a preamble is detected this bit will be set to 1.
|
||||
#define RFM22_is2_iswdet BIT7 // Sync Word Detected. When a sync word is detected this bit will be set to 1.
|
||||
|
||||
#define RFM22_interrupt_enable1 0x05 // R/W
|
||||
#define RFM22_ie1_encrcerror BIT0 // Enable CRC Error. When set to 1 the CRC Error interrupt will be enabled.
|
||||
#define RFM22_ie1_enpkvalid BIT1 // Enable Valid Packet Received. When ipkvalid = 1 the Valid Packet Received Interrupt will be enabled.
|
||||
#define RFM22_ie1_enpksent BIT2 // Enable Packet Sent. When ipksent =1 the Packet Sense Interrupt will be enabled.
|
||||
#define RFM22_ie1_enext BIT3 // Enable External Interrupt. When set to 1 the External Interrupt will be enabled.
|
||||
#define RFM22_ie1_enrxffafull BIT4 // Enable RX FIFO Almost Full. When set to 1 the RX FIFO Almost Full interrupt will be enabled.
|
||||
#define RFM22_ie1_entxffaem BIT5 // Enable TX FIFO Almost Empty. When set to 1 the TX FIFO Almost Empty interrupt will be enabled.
|
||||
#define RFM22_ie1_entxffafull BIT6 // Enable TX FIFO Almost Full. When set to 1 the TX FIFO Almost Full interrupt will be enabled.
|
||||
#define RFM22_ie1_enfferr BIT7 // Enable FIFO Underflow/Overflow. When set to 1 the FIFO Underflow/Overflow interrupt will be enabled.
|
||||
|
||||
#define RFM22_interrupt_enable2 0x06 // R/W
|
||||
#define RFM22_ie2_enpor BIT0 // Enable POR. When set to 1 the POR interrupt will be enabled.
|
||||
#define RFM22_ie2_enchiprdy BIT1 // Enable Chip Ready (XTAL). When set to 1 the Chip Ready interrupt will be enabled.
|
||||
#define RFM22_ie2_enlbd BIT2 // Enable Low Battery Detect. When set to 1 the Low Battery Detect interrupt will be enabled.
|
||||
#define RFM22_ie2_enwut BIT3 // Enable Wake-Up Timer. When set to 1 the Wake-Up Timer interrupt will be enabled.
|
||||
#define RFM22_ie2_enrssi BIT4 // Enable RSSI. When set to 1 the RSSI Interrupt will be enabled.
|
||||
#define RFM22_ie2_enpreainval BIT5 // Enable Invalid Preamble Detected. When mpreadet =1 the Invalid Preamble Detected Interrupt will be enabled.
|
||||
#define RFM22_ie2_enpreaval BIT6 // Enable Valid Preamble Detected. When mpreadet =1 the Valid Preamble Detected Interrupt will be enabled.
|
||||
#define RFM22_ie2_enswdet BIT7 // Enable Sync Word Detected. When mpreadet =1 the Preamble Detected Interrupt will be enabled.
|
||||
|
||||
#define RFM22_op_and_func_ctrl1 0x07 // R/W
|
||||
#define RFM22_opfc1_xton 0x01 // READY Mode (Xtal is ON).
|
||||
#define RFM22_opfc1_pllon 0x02 // TUNE Mode (PLL is ON). When pllon = 1 the PLL will remain enabled in Idle State. This will for faster turn-around time at the cost of increased current consumption in Idle State.
|
||||
#define RFM22_opfc1_rxon 0x04 // RX on in Manual Receiver Mode. Automatically cleared if Multiple Packets config. is disabled and a valid packet received.
|
||||
#define RFM22_opfc1_txon 0x08 // TX on in Manual Transmit Mode. Automatically cleared in FIFO mode once the packet is sent. Transmission can be aborted during packet transmission, however, when no data has been sent yet, transmission can only be aborted after the device is programmed to “unmodulated carrier” ("Register 71h. Modulation Mode Control 2").
|
||||
#define RFM22_opfc1_x32ksel 0x10 // 32,768 kHz Crystal Oscillator Select. 0: RC oscillator 1: 32 kHz crystal
|
||||
#define RFM22_opfc1_enwt 0x20 // Enable Wake-Up-Timer. Enabled when enwt = 1. If the Wake-up-Timer function is enabled it will operate in any mode and notify the microcontroller through the GPIO interrupt when the timer expires.
|
||||
#define RFM22_opfc1_enlbd 0x40 // Enable Low Battery Detect. When this bit is set to 1 the Low Battery Detector circuit and threshold comparison will be enabled.
|
||||
#define RFM22_opfc1_swres 0x80 // Software Register Reset Bit. This bit may be used to reset all registers simultaneously to a DEFAULT state, without the need for sequentially writing to each individual register. The RESET is accomplished by setting swres = 1. This bit will be automatically cleared.
|
||||
|
||||
#define RFM22_op_and_func_ctrl2 0x08 // R/W
|
||||
#define RFM22_opfc2_ffclrtx 0x01 // TX FIFO Reset/Clear. This has to be a two writes operation: Setting ffclrtx =1 followed by ffclrtx = 0 will clear the contents of the TX FIFO.
|
||||
#define RFM22_opfc2_ffclrrx 0x02 // RX FIFO Reset/Clear. This has to be a two writes operation: Setting ffclrrx =1 followed by ffclrrx = 0 will clear the contents of the RX FIFO.
|
||||
#define RFM22_opfc2_enldm 0x04 // Enable Low Duty Cycle Mode. If this bit is set to 1 then the chip turns on the RX regularly. The frequency should be set in the Wake-Up Timer Period register, while the minimum ON time should be set in the Low-Duty Cycle Mode Duration register. The FIFO mode should be enabled also.
|
||||
#define RFM22_opfc2_autotx 0x08 // Automatic Transmission. When autotx = 1 the transceiver will enter automatically TX State when the FIFO is almost full. When the FIFO is empty it will automatically return to the Idle State.
|
||||
#define RFM22_opfc2_rxmpk 0x10 // RX Multi Packet. When the chip is selected to use FIFO Mode (dtmod[1:0]) and RX Packet Handling (enpacrx) then it will fill up the FIFO with multiple valid packets if this bit is set, otherwise the transceiver will automatically leave the RX State after the first valid packet has been received.
|
||||
#define RFM22_opfc2_antdiv_mask 0xE0 // Enable Antenna Diversity. The GPIO must be configured for Antenna Diversity for the algorithm to work properly.
|
||||
|
||||
#define RFM22_xtal_osc_load_cap 0x09 // R/W
|
||||
#define RFM22_xolc_xlc_mask 0x7F // Tuning Capacitance for the 30 MHz XTAL.
|
||||
#define RFM22_xolc_xtalshft 0x80 // Additional capacitance to course shift the frequency if xlc[6:0] is not sufficient. Not binary with xlc[6:0].
|
||||
|
||||
#define RFM22_cpu_output_clk 0x0A // R/W
|
||||
#define RFM22_coc_30MHz 0x00
|
||||
#define RFM22_coc_15MHz 0x01
|
||||
#define RFM22_coc_10MHz 0x02
|
||||
#define RFM22_coc_4MHz 0x03
|
||||
#define RFM22_coc_3MHz 0x04
|
||||
#define RFM22_coc_2MHz 0x05
|
||||
#define RFM22_coc_1MHz 0x06
|
||||
#define RFM22_coc_32768Hz 0x07
|
||||
#define RFM22_coc_enlfc 0x08
|
||||
#define RFM22_coc_0cycle 0x00
|
||||
#define RFM22_coc_128cycles 0x10
|
||||
#define RFM22_coc_256cycles 0x20
|
||||
#define RFM22_coc_512cycles 0x30
|
||||
|
||||
#define RFM22_gpio0_config 0x0B // R/W
|
||||
#define RFM22_gpio0_config_por 0x00 // Power-On-Reset (output)
|
||||
#define RFM22_gpio0_config_wut 0x01 // Wake-Up Timer: 1 when WUT has expired (output)
|
||||
#define RFM22_gpio0_config_lbd 0x02 // Low Battery Detect: 1 when battery is below threshold setting (output)
|
||||
#define RFM22_gpio0_config_ddi 0x03 // Direct Digital Input
|
||||
#define RFM22_gpio0_config_eife 0x04 // External Interrupt, falling edge (input)
|
||||
#define RFM22_gpio0_config_eire 0x05 // External Interrupt, rising edge (input)
|
||||
#define RFM22_gpio0_config_eisc 0x06 // External Interrupt, state change (input)
|
||||
#define RFM22_gpio0_config_ai 0x07 // ADC Analog Input
|
||||
#define RFM22_gpio0_config_atni 0x08 // Reserved (Analog Test N Input)
|
||||
#define RFM22_gpio0_config_atpi 0x09 // Reserved (Analog Test P Input)
|
||||
#define RFM22_gpio0_config_ddo 0x0A // Direct Digital Output
|
||||
#define RFM22_gpio0_config_dto 0x0B // Reserved (Digital Test Output)
|
||||
#define RFM22_gpio0_config_atno 0x0C // Reserved (Analog Test N Output)
|
||||
#define RFM22_gpio0_config_atpo 0x0D // Reserved (Analog Test P Output)
|
||||
#define RFM22_gpio0_config_rv 0xOE // Reference Voltage (output)
|
||||
#define RFM22_gpio0_config_dclk 0x0F // TX/RX Data CLK output to be used in conjunction with TX/RX Data pin (output)
|
||||
#define RFM22_gpio0_config_txd 0x10 // TX Data input for direct modulation (input)
|
||||
#define RFM22_gpio0_config_err 0x11 // External Retransmission Request (input)
|
||||
#define RFM22_gpio0_config_txstate 0x12 // TX State (output)
|
||||
#define RFM22_gpio0_config_txfifoaf 0x13 // TX FIFO Almost Full (output)
|
||||
#define RFM22_gpio0_config_rxd 0x14 // RX Data (output)
|
||||
#define RFM22_gpio0_config_rxstate 0x15 // RX State (output)
|
||||
#define RFM22_gpio0_config_rxfifoaf 0x16 // RX FIFO Almost Full (output)
|
||||
#define RFM22_gpio0_config_antswt1 0x17 // Antenna 1 Switch used for antenna diversity (output)
|
||||
#define RFM22_gpio0_config_antswt2 0x18 // Antenna 2 Switch used for antenna diversity (output)
|
||||
#define RFM22_gpio0_config_vpd 0x19 // Valid Preamble Detected (output)
|
||||
#define RFM22_gpio0_config_ipd 0x1A // Invalid Preamble Detected (output)
|
||||
#define RFM22_gpio0_config_swd 0x1B // Sync Word Detected (output)
|
||||
#define RFM22_gpio0_config_cca 0x1C // Clear Channel Assessment (output)
|
||||
#define RFM22_gpio0_config_vdd 0x1D // VDD
|
||||
#define RFM22_gpio0_config_pup 0x20
|
||||
#define RFM22_gpio0_config_drv0 0x00 // output drive level
|
||||
#define RFM22_gpio0_config_drv1 0x40 // output drive level
|
||||
#define RFM22_gpio0_config_drv2 0x80 // output drive level
|
||||
#define RFM22_gpio0_config_drv3 0xC0 // output drive level
|
||||
|
||||
#define RFM22_gpio1_config 0x0C // R/W
|
||||
#define RFM22_gpio1_config_ipor 0x00 // Inverted Power-On-Reset (output)
|
||||
#define RFM22_gpio1_config_wut 0x01 // Wake-Up Timer: 1 when WUT has expired (output)
|
||||
#define RFM22_gpio1_config_lbd 0x02 // Low Battery Detect: 1 when battery is below threshold setting (output)
|
||||
#define RFM22_gpio1_config_ddi 0x03 // Direct Digital Input
|
||||
#define RFM22_gpio1_config_eife 0x04 // External Interrupt, falling edge (input)
|
||||
#define RFM22_gpio1_config_eire 0x05 // External Interrupt, rising edge (input)
|
||||
#define RFM22_gpio1_config_eisc 0x06 // External Interrupt, state change (input)
|
||||
#define RFM22_gpio1_config_ai 0x07 // ADC Analog Input
|
||||
#define RFM22_gpio1_config_atni 0x08 // Reserved (Analog Test N Input)
|
||||
#define RFM22_gpio1_config_atpi 0x09 // Reserved (Analog Test P Input)
|
||||
#define RFM22_gpio1_config_ddo 0x0A // Direct Digital Output
|
||||
#define RFM22_gpio1_config_dto 0x0B // Reserved (Digital Test Output)
|
||||
#define RFM22_gpio1_config_atno 0x0C // Reserved (Analog Test N Output)
|
||||
#define RFM22_gpio1_config_atpo 0x0D // Reserved (Analog Test P Output)
|
||||
#define RFM22_gpio1_config_rv 0xOE // Reference Voltage (output)
|
||||
#define RFM22_gpio1_config_dclk 0x0F // TX/RX Data CLK output to be used in conjunction with TX/RX Data pin (output)
|
||||
#define RFM22_gpio1_config_txd 0x10 // TX Data input for direct modulation (input)
|
||||
#define RFM22_gpio1_config_err 0x11 // External Retransmission Request (input)
|
||||
#define RFM22_gpio1_config_txstate 0x12 // TX State (output)
|
||||
#define RFM22_gpio1_config_txfifoaf 0x13 // TX FIFO Almost Full (output)
|
||||
#define RFM22_gpio1_config_rxd 0x14 // RX Data (output)
|
||||
#define RFM22_gpio1_config_rxstate 0x15 // RX State (output)
|
||||
#define RFM22_gpio1_config_rxfifoaf 0x16 // RX FIFO Almost Full (output)
|
||||
#define RFM22_gpio1_config_antswt1 0x17 // Antenna 1 Switch used for antenna diversity (output)
|
||||
#define RFM22_gpio1_config_antswt2 0x18 // Antenna 2 Switch used for antenna diversity (output)
|
||||
#define RFM22_gpio1_config_vpd 0x19 // Valid Preamble Detected (output)
|
||||
#define RFM22_gpio1_config_ipd 0x1A // Invalid Preamble Detected (output)
|
||||
#define RFM22_gpio1_config_swd 0x1B // Sync Word Detected (output)
|
||||
#define RFM22_gpio1_config_cca 0x1C // Clear Channel Assessment (output)
|
||||
#define RFM22_gpio1_config_vdd 0x1D // VDD
|
||||
#define RFM22_gpio1_config_pup 0x20
|
||||
#define RFM22_gpio1_config_drv0 0x00 // output drive level
|
||||
#define RFM22_gpio1_config_drv1 0x40 // output drive level
|
||||
#define RFM22_gpio1_config_drv2 0x80 // output drive level
|
||||
#define RFM22_gpio1_config_drv3 0xC0 // output drive level
|
||||
|
||||
#define RFM22_gpio2_config 0x0D // R/W
|
||||
#define RFM22_gpio2_config_mc 0x00 // Microcontroller Clock (output)
|
||||
#define RFM22_gpio2_config_wut 0x01 // Wake-Up Timer: 1 when WUT has expired (output)
|
||||
#define RFM22_gpio2_config_lbd 0x02 // Low Battery Detect: 1 when battery is below threshold setting (output)
|
||||
#define RFM22_gpio2_config_ddi 0x03 // Direct Digital Input
|
||||
#define RFM22_gpio2_config_eife 0x04 // External Interrupt, falling edge (input)
|
||||
#define RFM22_gpio2_config_eire 0x05 // External Interrupt, rising edge (input)
|
||||
#define RFM22_gpio2_config_eisc 0x06 // External Interrupt, state change (input)
|
||||
#define RFM22_gpio2_config_ai 0x07 // ADC Analog Input
|
||||
#define RFM22_gpio2_config_atni 0x08 // Reserved (Analog Test N Input)
|
||||
#define RFM22_gpio2_config_atpi 0x09 // Reserved (Analog Test P Input)
|
||||
#define RFM22_gpio2_config_ddo 0x0A // Direct Digital Output
|
||||
#define RFM22_gpio2_config_dto 0x0B // Reserved (Digital Test Output)
|
||||
#define RFM22_gpio2_config_atno 0x0C // Reserved (Analog Test N Output)
|
||||
#define RFM22_gpio2_config_atpo 0x0D // Reserved (Analog Test P Output)
|
||||
#define RFM22_gpio2_config_rv 0xOE // Reference Voltage (output)
|
||||
#define RFM22_gpio2_config_dclk 0x0F // TX/RX Data CLK output to be used in conjunction with TX/RX Data pin (output)
|
||||
#define RFM22_gpio2_config_txd 0x10 // TX Data input for direct modulation (input)
|
||||
#define RFM22_gpio2_config_err 0x11 // External Retransmission Request (input)
|
||||
#define RFM22_gpio2_config_txstate 0x12 // TX State (output)
|
||||
#define RFM22_gpio2_config_txfifoaf 0x13 // TX FIFO Almost Full (output)
|
||||
#define RFM22_gpio2_config_rxd 0x14 // RX Data (output)
|
||||
#define RFM22_gpio2_config_rxstate 0x15 // RX State (output)
|
||||
#define RFM22_gpio2_config_rxfifoaf 0x16 // RX FIFO Almost Full (output)
|
||||
#define RFM22_gpio2_config_antswt1 0x17 // Antenna 1 Switch used for antenna diversity (output)
|
||||
#define RFM22_gpio2_config_antswt2 0x18 // Antenna 2 Switch used for antenna diversity (output)
|
||||
#define RFM22_gpio2_config_vpd 0x19 // Valid Preamble Detected (output)
|
||||
#define RFM22_gpio2_config_ipd 0x1A // Invalid Preamble Detected (output)
|
||||
#define RFM22_gpio2_config_swd 0x1B // Sync Word Detected (output)
|
||||
#define RFM22_gpio2_config_cca 0x1C // Clear Channel Assessment (output)
|
||||
#define RFM22_gpio2_config_vdd 0x1D // VDD
|
||||
#define RFM22_gpio2_config_pup 0x20
|
||||
#define RFM22_gpio2_config_drv0 0x00 // output drive level
|
||||
#define RFM22_gpio2_config_drv1 0x40 // output drive level
|
||||
#define RFM22_gpio2_config_drv2 0x80 // output drive level
|
||||
#define RFM22_gpio2_config_drv3 0xC0 // output drive level
|
||||
|
||||
#define RFM22_io_port_config 0x0E // R/W
|
||||
#define RFM22_io_port_extitst2 0x40 // External Interrupt Status. If the GPIO2 is programmed to be external interrupt sources then the status can be read here.
|
||||
#define RFM22_io_port_extitst1 0x20 // External Interrupt Status. If the GPIO1 is programmed to be external interrupt sources then the status can be read here.
|
||||
#define RFM22_io_port_extitst0 0x10 // External Interrupt Status. If the GPIO0 is programmed to be external interrupt sources then the status can be read here.
|
||||
#define RFM22_io_port_itsdo 0x08 // Interrupt Request Output on the SDO Pin. nIRQ output is present on the SDO pin if this bit is set and the nSEL input is inactive (high).
|
||||
#define RFM22_io_port_dio2 0x04 // Direct I/O for GPIO2. If the GPIO2 is configured to be a direct output then the value on the GPIO pin can be set here. If the GPIO2 is configured to be a direct input then the value of the pin can be read here.
|
||||
#define RFM22_io_port_dio1 0x02 // Direct I/O for GPIO1. If the GPIO1 is configured to be a direct output then the value on the GPIO pin can be set here. If the GPIO1 is configured to be a direct input then the value of the pin can be read here.
|
||||
#define RFM22_io_port_dio0 0x01 // Direct I/O for GPIO0. If the GPIO0 is configured to be a direct output then the value on the GPIO pin can be set here. If the GPIO0 is configured to be a direct input then the value of the pin can be read here.
|
||||
#define RFM22_io_port_default 0x00 // GPIO pins are default
|
||||
|
||||
#define RFM22_adc_config 0x0F // R/W
|
||||
#define RFM22_ac_adcgain0 0x00
|
||||
#define RFM22_ac_adcgain1 0x01
|
||||
#define RFM22_ac_adcgain2 0x02
|
||||
#define RFM22_ac_adcgain3 0x03
|
||||
#define RFM22_ac_adcref_bg 0x00
|
||||
#define RFM22_ac_adcref_vdd3 0x08
|
||||
#define RFM22_ac_adcref_vdd2 0x0C
|
||||
#define RFM22_ac_adcsel_temp_sensor 0x00
|
||||
#define RFM22_ac_adcsel_gpio0 0x10
|
||||
#define RFM22_ac_adcsel_gpio1 0x20
|
||||
#define RFM22_ac_adcsel_gpio2 0x30
|
||||
#define RFM22_ac_adcsel_gpio01 0x40
|
||||
#define RFM22_ac_adcsel_gpio12 0x50
|
||||
#define RFM22_ac_adcsel_gpio02 0x60
|
||||
#define RFM22_ac_adcsel_gpio_gnd 0x70
|
||||
#define RFM22_ac_adcstartbusy 0x80
|
||||
|
||||
#define RFM22_adc_sensor_amp_offset 0x10 // R/W
|
||||
#define RFM22_asao_adcoffs_mask 0x0F // ADC Sensor Amplifier Offset. The offset can be calculated as Offset = adcoffs[2:0] x VDD/1000; MSB = adcoffs[3] = Sign bit.
|
||||
|
||||
#define RFM22_adc_value 0x11 // R .. Internal 8 bit ADC Output Value.
|
||||
|
||||
#define RFM22_temp_sensor_calib 0x12 // R/W
|
||||
#define RFM22_tsc_tstrim_mask 0x0F // Temperature Sensor Trim Value.
|
||||
#define RFM22_tsc_entstrim 0x10 // Temperature Sensor Trim Enable.
|
||||
#define RFM22_tsc_entsoffs 0x20 // Temperature Sensor Offset to Convert from K to ºC.
|
||||
#define RFM22_tsc_tsrange0 0x00 // Temperature Sensor Range Selection. –64C to +64C 0.5C resolution
|
||||
#define RFM22_tsc_tsrange1 0x40 // -40 to +85C with 1.0C resolution
|
||||
#define RFM22_tsc_tsrange2 0x80 // 0C to 85C with 0.5C resolution
|
||||
#define RFM22_tsc_tsrange3 0xC0 // -40F to 216F with 1.0F resolution
|
||||
|
||||
#define RFM22_temp_value_offset 0x13 // R/W
|
||||
|
||||
#define RFM22_wakeup_timer_period1 0x14 // R/W
|
||||
#define RFM22_wakeup_timer_period2 0x15 // R/W
|
||||
#define RFM22_wakeup_timer_period3 0x16 // R/W
|
||||
|
||||
#define RFM22_wakeup_timer_value1 0x17 // R
|
||||
#define RFM22_wakeup_timer_value2 0x18 // R
|
||||
|
||||
#define RFM22_low_dutycycle_mode_duration 0x19 // R/W
|
||||
#define RFM22_low_battery_detector_threshold 0x1A // R/W
|
||||
|
||||
#define RFM22_battery_volateg_level 0x1B // R
|
||||
|
||||
#define RFM22_if_filter_bandwidth 0x1C // R/W
|
||||
#define RFM22_iffbw_filset_mask 0x0F
|
||||
#define RFM22_iffbw_ndec_exp_mask 0x70
|
||||
#define RFM22_iffbw_dwn3_bypass 0x80
|
||||
|
||||
#define RFM22_afc_loop_gearshift_override 0x1D // R/W
|
||||
#define RFM22_afc_lp_gs_ovrd_afcgearl_mask 0x07 // AFC Low Gear Setting.
|
||||
#define RFM22_afc_lp_gs_ovrd_afcgearh_mask 0x38 // AFC High Gear Setting.
|
||||
#define RFM22_afc_lp_gs_ovrd_enafc 0x40 // AFC Enable.
|
||||
#define RFM22_afc_lp_gs_ovrd_afcbd 0x80 // If set, the tolerated AFC frequency error will be halved.
|
||||
|
||||
#define RFM22_afc_timing_control 0x1E // R/W
|
||||
|
||||
#define RFM22_clk_recovery_gearshift_override 0x1F // R/W
|
||||
#define RFM22_clk_recovery_oversampling_ratio 0x20 // R/W
|
||||
#define RFM22_clk_recovery_offset2 0x21 // R/W
|
||||
#define RFM22_clk_recovery_offset1 0x22 // R/W
|
||||
#define RFM22_clk_recovery_offset0 0x23 // R/W
|
||||
#define RFM22_clk_recovery_timing_loop_gain1 0x24 // R/W
|
||||
#define RFM22_clk_recovery_timing_loop_gain0 0x25 // R/W
|
||||
|
||||
#define RFM22_rssi 0x26 // R
|
||||
#define RFM22_rssi_threshold_clear_chan_indicator 0x27 // R/W
|
||||
|
||||
#define RFM22_antenna_diversity_register1 0x28 // R
|
||||
#define RFM22_antenna_diversity_register2 0x29 // R
|
||||
|
||||
#define RFM22_afc_limiter 0x2A // R/W .. AFC_pull_in_range = ±AFCLimiter[7:0] x (hbsel+1) x 625 Hz
|
||||
|
||||
#define RFM22_afc_correction_read 0x2B // R
|
||||
|
||||
#define RFM22_ook_counter_value1 0x2C // R/W
|
||||
#define RFM22_ook_counter_value2 0x2D // R/W
|
||||
|
||||
#define RFM22_slicer_peak_hold 0x2E // R/W
|
||||
|
||||
#define RFM22_data_access_control 0x30 // R/W
|
||||
#define RFM22_dac_crc_ccitt 0x00 //
|
||||
#define RFM22_dac_crc_crc16 0x01 //
|
||||
#define RFM22_dac_crc_iec16 0x02 //
|
||||
#define RFM22_dac_crc_biacheva 0x03 //
|
||||
#define RFM22_dac_encrc 0x04 // CRC Enable. Cyclic Redundancy Check generation is enabled if this bit is set.
|
||||
#define RFM22_dac_enpactx 0x08 // Enable Packet TX Handling. If FIFO Mode (dtmod = 10) is being used automatic packet handling may be enabled. Setting enpactx = 1 will enable automatic packet handling in the TX path. Register 30–4D allow for various configurations of the packet structure. Setting enpactx = 0 will not do any packet handling in the TX path. It will only transmit what is loaded to the FIFO.
|
||||
#define RFM22_dac_skip2ph 0x10 // Skip 2nd Phase of Preamble Detection. If set, we skip the second phase of the preamble detection (under certain conditions) if antenna diversity is enabled.
|
||||
#define RFM22_dac_crcdonly 0x20 // CRC Data Only Enable. When this bit is set to 1 the CRC is calculated on and checked against the packet data fields only.
|
||||
#define RFM22_dac_lsbfrst 0x40 // LSB First Enable. The LSB of the data will be transmitted/received first if this bit is set.
|
||||
#define RFM22_dac_enpacrx 0x80 // Enable Packet RX Handling. If FIFO Mode (dtmod = 10) is being used automatic packet handling may be enabled. Setting enpacrx = 1 will enable automatic packet handling in the RX path. Register 30–4D allow for various configurations of the packet structure. Setting enpacrx = 0 will not do any packet handling in the RX path. It will only receive everything after the sync word and fill up the RX FIFO.
|
||||
|
||||
#define RFM22_ezmac_status 0x31 // R
|
||||
#define RFM22_ezmac_status_pksent 0x01 // Packet Sent. A 1 a packet has been sent by the radio. (Same bit as in register 03, but reading it does not reset the IRQ)
|
||||
#define RFM22_ezmac_status_pktx 0x02 // Packet Transmitting. When 1 the radio is currently transmitting a packet.
|
||||
#define RFM22_ezmac_status_crcerror 0x04 // CRC Error. When 1 a Cyclic Redundancy Check error has been detected. (Same bit as in register 03, but reading it does not reset the IRQ)
|
||||
#define RFM22_ezmac_status_pkvalid 0x08 // Valid Packet Received. When a 1 a valid packet has been received by the receiver. (Same bit as in register 03, but reading it does not reset the IRQ)
|
||||
#define RFM22_ezmac_status_pkrx 0x10 // Packet Receiving. When 1 the radio is currently receiving a valid packet.
|
||||
#define RFM22_ezmac_status_pksrch 0x20 // Packet Searching. When 1 the radio is searching for a valid packet.
|
||||
#define RFM22_ezmac_status_rxcrc1 0x40 // If high, it indicates the last CRC received is all one’s. May indicated Transmitter underflow in case of CRC error.
|
||||
|
||||
#define RFM22_header_control1 0x32 // R/W
|
||||
#define RFM22_header_cntl1_bcen_none 0x00 // No broadcast address enable.
|
||||
#define RFM22_header_cntl1_bcen_0 0x10 // Broadcast address enable for header byte 0.
|
||||
#define RFM22_header_cntl1_bcen_1 0x20 // Broadcast address enable for header byte 1.
|
||||
#define RFM22_header_cntl1_bcen_01 0x30 // Broadcast address enable for header bytes 0 & 1.
|
||||
#define RFM22_header_cntl1_hdch_none 0x00 // No Received Header check
|
||||
#define RFM22_header_cntl1_hdch_0 0x01 // Received Header check for byte 0.
|
||||
#define RFM22_header_cntl1_hdch_1 0x02 // Received Header check for byte 1.
|
||||
#define RFM22_header_cntl1_hdch_01 0x03 // Received Header check for bytes 0 & 1.
|
||||
|
||||
#define RFM22_header_control2 0x33 // R/W
|
||||
#define RFM22_header_cntl2_prealen 0x01 // MSB of Preamble Length. See register Preamble Length.
|
||||
#define RFM22_header_cntl2_synclen_3 0x00 // Synchronization Word 3
|
||||
#define RFM22_header_cntl2_synclen_32 0x02 // Synchronization Word 3 followed by 2
|
||||
#define RFM22_header_cntl2_synclen_321 0x04 // Synchronization Word 3 followed by 2 followed by 1
|
||||
#define RFM22_header_cntl2_synclen_3210 0x06 // Synchronization Word 3 followed by 2 followed by 1 followed by 0
|
||||
#define RFM22_header_cntl2_fixpklen 0x08 // Fix Packet Length. When fixpklen = 1 the packet length (pklen[7:0]) is not included in the header. When fixpklen = 0 the packet length is included in the header.
|
||||
#define RFM22_header_cntl2_hdlen_none 0x00 // no header
|
||||
#define RFM22_header_cntl2_hdlen_3 0x10 // header 3
|
||||
#define RFM22_header_cntl2_hdlen_32 0x20 // header 3 and 2
|
||||
#define RFM22_header_cntl2_hdlen_321 0x30 // header 3 and 2 and 1
|
||||
#define RFM22_header_cntl2_hdlen_3210 0x40 // header 3 and 2 and 1 and 0
|
||||
#define RFM22_header_cntl2_skipsyn 0x80 // If high, the system will ignore the syncword search timeout reset. The chip will not return to searching for Preamble, but instead will remain searching for Sync word.
|
||||
|
||||
#define RFM22_preamble_length 0x34 // R/W
|
||||
|
||||
#define RFM22_preamble_detection_ctrl1 0x35 // R/W
|
||||
#define RFM22_pre_det_ctrl1_preath_mask 0xF8 // Number of nibbles processed during detection.
|
||||
#define RFM22_pre_det_ctrl1_rssi_offset_mask 0x07 // Value added as offset to RSSI calculation. Every increment in this register results in an increment of +4 dB in the RSSI.
|
||||
|
||||
#define RFM22_sync_word3 0x36 // R/W
|
||||
#define RFM22_sync_word2 0x37 // R/W
|
||||
#define RFM22_sync_word1 0x38 // R/W
|
||||
#define RFM22_sync_word0 0x39 // R/W
|
||||
|
||||
#define RFM22_transmit_header3 0x3A // R/W
|
||||
#define RFM22_transmit_header2 0x3B // R/W
|
||||
#define RFM22_transmit_header1 0x3C // R/W
|
||||
#define RFM22_transmit_header0 0x3D // R/W
|
||||
|
||||
#define RFM22_transmit_packet_length 0x3E // R/W
|
||||
|
||||
#define RFM22_check_header3 0x3F // R/W
|
||||
#define RFM22_check_header2 0x40 // R/W
|
||||
#define RFM22_check_header1 0x41 // R/W
|
||||
#define RFM22_check_header0 0x42 // R/W
|
||||
|
||||
#define RFM22_header_enable3 0x43 // R/W
|
||||
#define RFM22_header_enable2 0x44 // R/W
|
||||
#define RFM22_header_enable1 0x45 // R/W
|
||||
#define RFM22_header_enable0 0x46 // R/W
|
||||
|
||||
#define RFM22_received_header3 0x47 // R
|
||||
#define RFM22_received_header2 0x48 // R
|
||||
#define RFM22_received_header1 0x49 // R
|
||||
#define RFM22_received_header0 0x4A // R
|
||||
|
||||
#define RFM22_received_packet_length 0x4B // R
|
||||
|
||||
#define RFM22_adc8_control 0x4F // R/W
|
||||
/*
|
||||
#define RFM22_analog_test_bus 0x50 // R/W
|
||||
#define RFM22_digital_test_bus 0x51 // R/W
|
||||
#define RFM22_tx_ramp_control 0x52 // R/W
|
||||
#define RFM22_pll_tune_time 0x53 // R/W
|
||||
|
||||
#define RFM22_calibration_control 0x55 // R/W
|
||||
|
||||
#define RFM22_modem_test 0x56 // R/W
|
||||
|
||||
#define RFM22_chargepump_test 0x57 // R/W
|
||||
#define RFM22_chargepump_current_trimming_override 0x58 // R/W
|
||||
|
||||
#define RFM22_divider_current_trimming 0x59 // R/W
|
||||
|
||||
#define RFM22_vco_current_trimming 0x5A // R/W
|
||||
#define RFM22_vco_calibration_override 0x5B // R/W
|
||||
|
||||
#define RFM22_synthersizer_test 0x5C // R/W
|
||||
|
||||
#define RFM22_block_enable_override1 0x5D // R/W
|
||||
#define RFM22_block_enable_override2 0x5E // R/W
|
||||
#define RFM22_block_enable_override3 0x5F // R/W
|
||||
*/
|
||||
#define RFM22_channel_filter_coeff_addr 0x60 // R/W
|
||||
#define RFM22_ch_fil_coeff_ad_inv_pre_th_mask 0xF0 //
|
||||
#define RFM22_ch_fil_coeff_ad_chfiladd_mask 0x0F // Channel Filter Coefficient Look-up Table Address. The address for channel filter coefficients used in the RX path.
|
||||
|
||||
|
||||
//#define RFM22_channel_filter_coeff_value 0x61 // R/W
|
||||
|
||||
#define RFM22_xtal_osc_por_ctrl 0x62 // R/W
|
||||
#define RFM22_xtal_osc_por_ctrl_pwst_mask 0xE0 // Internal Power States of the Chip.
|
||||
#define RFM22_xtal_osc_por_ctrl_clkhyst 0x10 // Clock Hysteresis Setting.
|
||||
#define RFM22_xtal_osc_por_ctrl_enbias2x 0x08 // 2 Times Higher Bias Current Enable.
|
||||
#define RFM22_xtal_osc_por_ctrl_enamp2x 0x04 // 2 Times Higher Amplification Enable.
|
||||
#define RFM22_xtal_osc_por_ctrl_bufovr 0x02 // Output Buffer Enable Override.
|
||||
#define RFM22_xtal_osc_por_ctrl_enbuf 0x01 // Output Buffer Enable.
|
||||
/*
|
||||
#define RFM22_rc_osc_coarse_calbration_override 0x63 // R/W
|
||||
#define RFM22_rc_osc_fine_calbration_override 0x64 // R/W
|
||||
|
||||
#define RFM22_ldo_control_override 0x65 // R/W
|
||||
#define RFM22_ldo_level_setting 0x66 // R/W
|
||||
|
||||
#define RFM22_deltasigma_adc_tuning1 0x67 // R/W
|
||||
#define RFM22_deltasigma_adc_tuning2 0x68 // R/W
|
||||
*/
|
||||
#define RFM22_agc_override1 0x69 // R/W
|
||||
#define RFM22_agc_ovr1_sgi 0x40 // AGC Loop, Set Gain Increase. If set to 0 then gain increasing will not be allowed. If set to 1 then gain increasing is allowed, default is 0.
|
||||
#define RFM22_agc_ovr1_agcen 0x20 // Automatic Gain Control Enable. When this bit is set then the result of the control can be read out from bits [4:0], otherwise the gain can be controlled manually by writing into bits [4:0].
|
||||
#define RFM22_agc_ovr1_lnagain 0x10 // LNA Gain Select. 0 = min gain = 5dB, 1 = max gain = 25 dB.
|
||||
#define RFM22_agc_ovr1_pga_mask 0x0F // PGA Gain Override Value.
|
||||
|
||||
//#define RFM22_agc_override2 0x6A // R/W
|
||||
|
||||
//#define RFM22_gfsk_fir_coeff_addr 0x6B // R/W
|
||||
//#define RFM22_gfsk_fir_coeff_value 0x6C // R/W
|
||||
|
||||
#define RFM22_tx_power 0x6D // R/W
|
||||
#define RFM22_tx_pwr_txpow_0 0x00 // +1dBm .. 1.25mW
|
||||
#define RFM22_tx_pwr_txpow_1 0x01 // +2dBm .. 1.6mW
|
||||
#define RFM22_tx_pwr_txpow_2 0x02 // +5dBm .. 3.16mW
|
||||
#define RFM22_tx_pwr_txpow_3 0x03 // +8dBm .. 6.3mW
|
||||
#define RFM22_tx_pwr_txpow_4 0x04 // +11dBm .. 12.6mW
|
||||
#define RFM22_tx_pwr_txpow_5 0x05 // +14dBm .. 25mW
|
||||
#define RFM22_tx_pwr_txpow_6 0x06 // +17dBm .. 50mW
|
||||
#define RFM22_tx_pwr_txpow_7 0x07 // +20dBm .. 100mW
|
||||
#define RFM22_tx_pwr_lna_sw 0x08 // LNA Switch Controller. If set, lna_sw control from the digital will go high during TX modes, and low during other times. If reset, the digital control signal is low at all times.
|
||||
#define RFM22_tx_pwr_papeaklvl_0 0x10 // " "
|
||||
#define RFM22_tx_pwr_papeaklvl_1 0x20 // PA Peak Detect Level (direct from register). 00 = 6.5, 01 = 7, 10 = 7.5, 11 = 8, 00 = default
|
||||
#define RFM22_tx_pwr_papeaken 0x40 // PA Peak Detector Enable.
|
||||
#define RFM22_tx_pwr_papeakval 0x80 // PA Peak Detector Value Read Register. Reading a 1 in this register when the papeaken=1 then the PA drain voltage is too high and the match network needs adjusting for optimal efficiency.
|
||||
|
||||
#define RFM22_tx_data_rate1 0x6E // R/W
|
||||
#define RFM22_tx_data_rate0 0x6F // R/W
|
||||
|
||||
#define RFM22_modulation_mode_control1 0x70 // R/W
|
||||
#define RFM22_mmc1_enwhite 0x01 // Data Whitening is Enabled if this bit is set.
|
||||
#define RFM22_mmc1_enmanch 0x02 // Manchester Coding is Enabled if this bit is set.
|
||||
#define RFM22_mmc1_enmaninv 0x04 // Manchester Data Inversion is Enabled if this bit is set.
|
||||
#define RFM22_mmc1_manppol 0x08 // Manchester Preamble Polarity (will transmit a series of 1 if set, or series of 0 if reset).
|
||||
#define RFM22_mmc1_enphpwdn 0x10 // If set, the Packet Handler will be powered down when chip is in low power mode.
|
||||
#define RFM22_mmc1_txdtrtscale 0x20 // This bit should be set for Data Rates below 30 kbps.
|
||||
|
||||
#define RFM22_modulation_mode_control2 0x71 // R/W
|
||||
#define RFM22_mmc2_modtyp_mask 0x03 // Modulation type.
|
||||
#define RFM22_mmc2_modtyp_none 0x00 //
|
||||
#define RFM22_mmc2_modtyp_ook 0x01 //
|
||||
#define RFM22_mmc2_modtyp_fsk 0x02 //
|
||||
#define RFM22_mmc2_modtyp_gfsk 0x03 //
|
||||
#define RFM22_mmc2_fd 0x04 // MSB of Frequency Deviation Setting, see "Register 72h. Frequency Deviation".
|
||||
#define RFM22_mmc2_eninv 0x08 // Invert TX and RX Data.
|
||||
#define RFM22_mmc2_dtmod_mask 0x30 // Modulation source.
|
||||
#define RFM22_mmc2_dtmod_dm_gpio 0x00 //
|
||||
#define RFM22_mmc2_dtmod_dm_sdi 0x10 //
|
||||
#define RFM22_mmc2_dtmod_fifo 0x20 //
|
||||
#define RFM22_mmc2_dtmod_pn9 0x30 //
|
||||
#define RFM22_mmc2_trclk_mask 0xC0 // TX Data Clock Configuration.
|
||||
#define RFM22_mmc2_trclk_clk_none 0x00 //
|
||||
#define RFM22_mmc2_trclk_clk_gpio 0x40 //
|
||||
#define RFM22_mmc2_trclk_clk_sdo 0x80 //
|
||||
#define RFM22_mmc2_trclk_clk_nirq 0xC0 //
|
||||
|
||||
#define RFM22_frequency_deviation 0x72 // R/W
|
||||
|
||||
#define RFM22_frequency_offset1 0x73 // R/W
|
||||
#define RFM22_frequency_offset2 0x74 // R/W
|
||||
|
||||
#define RFM22_frequency_band_select 0x75 // R/W
|
||||
#define RFM22_fb_mask 0x1F
|
||||
#define RFM22_fbs_hbsel 0x20
|
||||
#define RFM22_fbs_sbse 0x40
|
||||
|
||||
#define RFM22_nominal_carrier_frequency1 0x76 // R/W
|
||||
#define RFM22_nominal_carrier_frequency0 0x77 // R/W
|
||||
|
||||
#define RFM22_frequency_hopping_channel_select 0x79 // R/W
|
||||
#define RFM22_frequency_hopping_step_size 0x7A // R/W
|
||||
|
||||
#define RFM22_tx_fifo_control1 0x7C // R/W .. TX FIFO Almost Full Threshold (0 - 63)
|
||||
#define RFM22_tx_fifo_control1_mask 0x3F
|
||||
|
||||
#define RFM22_tx_fifo_control2 0x7D // R/W .. TX FIFO Almost Empty Threshold (0 - 63)
|
||||
#define RFM22_tx_fifo_control2_mask 0x3F
|
||||
|
||||
#define RFM22_rx_fifo_control 0x7E // R/W .. RX FIFO Almost Full Threshold (0 - 63)
|
||||
#define RFM22_rx_fifo_control_mask 0x3F
|
||||
|
||||
#define RFM22_fifo_access 0x7F // R/W
|
||||
|
||||
// ************************************
|
||||
|
||||
typedef int16_t ( *t_rfm22_TxDataByteCallback ) (void);
|
||||
typedef bool ( *t_rfm22_RxDataCallback ) (void *data, uint8_t len);
|
||||
|
||||
// ************************************
|
||||
|
||||
uint32_t rfm22_minFrequency(void);
|
||||
uint32_t rfm22_maxFrequency(void);
|
||||
|
||||
void rfm22_setNominalCarrierFrequency(uint32_t frequency_hz);
|
||||
uint32_t rfm22_getNominalCarrierFrequency(void);
|
||||
|
||||
float rfm22_getFrequencyStepSize(void);
|
||||
|
||||
void rfm22_setFreqHopChannel(uint8_t channel);
|
||||
uint8_t rfm22_freqHopChannel(void);
|
||||
|
||||
uint32_t rfm22_freqHopSize(void);
|
||||
|
||||
void rfm22_setDatarate(uint32_t datarate_bps, bool data_whitening);
|
||||
uint32_t rfm22_getDatarate(void);
|
||||
|
||||
void rfm22_setRxMode(uint8_t mode, bool multi_packet_mode);
|
||||
|
||||
int16_t rfm22_getRSSI(void);
|
||||
|
||||
int16_t rfm22_receivedRSSI(void);
|
||||
int32_t rfm22_receivedAFCHz(void);
|
||||
uint16_t rfm22_receivedLength(void);
|
||||
uint8_t * rfm22_receivedPointer(void);
|
||||
void rfm22_receivedDone(void);
|
||||
|
||||
int32_t rfm22_sendData(void *data, uint16_t length, bool send_immediately);
|
||||
|
||||
void rfm22_setFreqCalibration(uint8_t value);
|
||||
uint8_t rfm22_getFreqCalibration(void);
|
||||
|
||||
void rfm22_setTxPower(uint8_t tx_pwr);
|
||||
uint8_t rfm22_getTxPower(void);
|
||||
|
||||
void rfm22_setTxStream(void); // TEST ONLY
|
||||
|
||||
void rfm22_setTxNormal(void);
|
||||
void rfm22_setTxCarrierMode(void);
|
||||
void rfm22_setTxPNMode(void);
|
||||
|
||||
int8_t rfm22_currentMode(void);
|
||||
bool rfm22_transmitting(void);
|
||||
|
||||
bool rfm22_channelIsClear(void);
|
||||
|
||||
bool rfm22_txReady(void);
|
||||
|
||||
void rfm22_1ms_tick(void);
|
||||
void rfm22_process(void);
|
||||
|
||||
void rfm22_TxDataByte_SetCallback(t_rfm22_TxDataByteCallback new_function);
|
||||
void rfm22_RxData_SetCallback(t_rfm22_RxDataCallback new_function);
|
||||
|
||||
int rfm22_init_scan_spectrum(uint32_t min_frequency_hz, uint32_t max_frequency_hz);
|
||||
int rfm22_init_tx_stream(uint32_t min_frequency_hz, uint32_t max_frequency_hz);
|
||||
int rfm22_init_rx_stream(uint32_t min_frequency_hz, uint32_t max_frequency_hz);
|
||||
int rfm22_init_normal(uint32_t min_frequency_hz, uint32_t max_frequency_hz, uint32_t freq_hop_step_size);
|
||||
|
||||
// ************************************
|
||||
|
||||
#endif
|
@ -1,80 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file saved_settings.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 _SAVED_SETTINGS_H_
|
||||
#define _SAVED_SETTINGS_H_
|
||||
|
||||
// *****************************************************************
|
||||
|
||||
#include "stm32f10x.h"
|
||||
#include "stm32f10x_flash.h"
|
||||
|
||||
// *****************************************************************
|
||||
|
||||
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];
|
||||
|
||||
uint8_t mode;
|
||||
|
||||
uint8_t rts_time;
|
||||
|
||||
uint8_t spare[30]; // allow for future unknown settings
|
||||
|
||||
uint32_t crc;
|
||||
} __attribute__((__packed__)) t_saved_settings;
|
||||
|
||||
// *****************************************************************
|
||||
// public variables
|
||||
|
||||
extern volatile t_saved_settings saved_settings __attribute__ ((aligned(4))); // a RAM copy of the settings stored in EEPROM
|
||||
|
||||
// *****************************************************************
|
||||
// public functions
|
||||
|
||||
int32_t saved_settings_save(void);
|
||||
|
||||
void saved_settings_init(void);
|
||||
|
||||
// *****************************************************************
|
||||
|
||||
#endif
|
@ -1,40 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file stopwatch.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief Stop watch function
|
||||
* @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 __STOPWATCH_H__
|
||||
#define __STOPWATCH_H__
|
||||
|
||||
#include "stm32f10x.h"
|
||||
|
||||
// *****************************************************************************
|
||||
|
||||
void STOPWATCH_init(uint32_t resolution);
|
||||
void STOPWATCH_reset(void);
|
||||
uint32_t STOPWATCH_get_count(void);
|
||||
uint32_t STOPWATCH_get_us(void);
|
||||
|
||||
// *****************************************************************************
|
||||
|
||||
#endif
|
@ -1,40 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file stream.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief Sends or Receives a continuous packet stream to/from the remote unit
|
||||
* @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 STREAM_H_
|
||||
#define STREAM_H_
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
// *************************************************************
|
||||
|
||||
void stream_1ms_tick(void);
|
||||
void stream_process(void);
|
||||
void stream_deinit(void);
|
||||
void stream_init(uint32_t our_sn);
|
||||
|
||||
// *************************************************************
|
||||
|
||||
#endif
|
@ -1,40 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file transparent_comms.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief Serial communication port handling routines
|
||||
* @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 __TRANSPARENT_COMMS_H__
|
||||
#define __TRANSPARENT_COMMS_H__
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
// *****************************************************************************
|
||||
|
||||
void trans_1ms_tick(void);
|
||||
void trans_process(void);
|
||||
|
||||
void trans_init(void);
|
||||
|
||||
// *****************************************************************************
|
||||
|
||||
#endif
|
@ -1,32 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file watchdog.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 _WATCHDOG_H_
|
||||
#define _WATCHDOG_H_
|
||||
|
||||
uint16_t watchdog_Init(uint16_t delayMs);
|
||||
void watchdog_Clear(void);
|
||||
|
||||
#endif
|
@ -1,939 +0,0 @@
|
||||
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file main.c
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief Main modem functions
|
||||
* @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
|
||||
*/
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
|
||||
#define USE_WATCHDOG // comment this out if you don't want to use the watchdog
|
||||
|
||||
// *****************************************************************************
|
||||
// OpenPilot Includes
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "crc.h"
|
||||
#include "aes.h"
|
||||
#include "rfm22b.h"
|
||||
#include "packet_handler.h"
|
||||
#include "stream.h"
|
||||
#include "ppm.h"
|
||||
#include "transparent_comms.h"
|
||||
//#include "api_comms.h"
|
||||
#include "api_config.h"
|
||||
#include "gpio_in.h"
|
||||
#include "stopwatch.h"
|
||||
#include "watchdog.h"
|
||||
#include "saved_settings.h"
|
||||
|
||||
#include "main.h"
|
||||
|
||||
/* Prototype of PIOS_Board_Init() function */
|
||||
extern void PIOS_Board_Init(void);
|
||||
|
||||
// *****************************************************************************
|
||||
// ADC data
|
||||
|
||||
#define ADC_REF 3.3f // ADC reference voltage
|
||||
#define ADC_FULL_RANGE 4096 // 12 bit ADC
|
||||
|
||||
#define ADC_PSU_RESISTOR_TOP 10000.0f // 10k upper resistor
|
||||
#define ADC_PSU_RESISTOR_BOTTOM 2700.0f // 2k7 lower resistor
|
||||
#define ADC_PSU_RATIO (ADC_PSU_RESISTOR_BOTTOM / (ADC_PSU_RESISTOR_TOP + ADC_PSU_RESISTOR_BOTTOM))
|
||||
#define ADC_PSU_mV_SCALE ((ADC_REF * 1000) / (ADC_FULL_RANGE * ADC_PSU_RATIO))
|
||||
|
||||
// *****************************************************************************
|
||||
// Global Variables
|
||||
|
||||
uint32_t flash_size;
|
||||
|
||||
char serial_number_str[25];
|
||||
uint32_t serial_number_crc32;
|
||||
|
||||
uint32_t reset_addr;
|
||||
|
||||
bool API_Mode;
|
||||
|
||||
bool booting;
|
||||
|
||||
volatile uint32_t random32;
|
||||
|
||||
// *****************************************************************************
|
||||
// Local Variables
|
||||
|
||||
#if defined(USE_WATCHDOG)
|
||||
volatile uint16_t watchdog_timer;
|
||||
uint16_t watchdog_delay;
|
||||
#endif
|
||||
|
||||
volatile bool inside_timer_int;
|
||||
volatile uint32_t uptime_ms;
|
||||
|
||||
volatile uint16_t second_tick_timer;
|
||||
volatile bool second_tick;
|
||||
|
||||
//volatile int32_t temp_adc;
|
||||
//volatile int32_t psu_adc;
|
||||
|
||||
// *****************************************************************************
|
||||
|
||||
#if defined(USE_WATCHDOG)
|
||||
|
||||
void processWatchdog(void)
|
||||
{
|
||||
// random32 = UpdateCRC32(random32, IWDG->SR);
|
||||
|
||||
if (watchdog_timer < watchdog_delay)
|
||||
return;
|
||||
|
||||
// the watchdog needs resetting
|
||||
|
||||
watchdog_timer = 0;
|
||||
|
||||
watchdog_Clear();
|
||||
}
|
||||
|
||||
void enableWatchdog(void)
|
||||
{ // enable a watchdog
|
||||
watchdog_timer = 0;
|
||||
watchdog_delay = watchdog_Init(1000); // 1 second watchdog timeout
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// *****************************************************************************
|
||||
|
||||
void sequenceLEDs(void)
|
||||
{
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
USB_LED_ON;
|
||||
PIOS_DELAY_WaitmS(80);
|
||||
USB_LED_OFF;
|
||||
|
||||
LINK_LED_ON;
|
||||
PIOS_DELAY_WaitmS(80);
|
||||
LINK_LED_OFF;
|
||||
|
||||
RX_LED_ON;
|
||||
PIOS_DELAY_WaitmS(80);
|
||||
RX_LED_OFF;
|
||||
|
||||
TX_LED_ON;
|
||||
PIOS_DELAY_WaitmS(80);
|
||||
TX_LED_OFF;
|
||||
|
||||
#if defined(USE_WATCHDOG)
|
||||
processWatchdog(); // process the watchdog
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// timer interrupt
|
||||
|
||||
void TIMER_INT_FUNC(void)
|
||||
{
|
||||
inside_timer_int = TRUE;
|
||||
|
||||
if (TIM_GetITStatus(TIMER_INT_TIMER, TIM_IT_Update) != RESET)
|
||||
{
|
||||
// Clear timer interrupt pending bit
|
||||
TIM_ClearITPendingBit(TIMER_INT_TIMER, TIM_IT_Update);
|
||||
|
||||
// random32 = UpdateCRC32(random32, PIOS_DELAY_GetuS() >> 8);
|
||||
// random32 = UpdateCRC32(random32, PIOS_DELAY_GetuS());
|
||||
|
||||
uptime_ms++;
|
||||
|
||||
#if defined(USE_WATCHDOG)
|
||||
watchdog_timer++;
|
||||
#endif
|
||||
|
||||
// ***********
|
||||
|
||||
if (!booting)
|
||||
{
|
||||
// ***********
|
||||
|
||||
if (++second_tick_timer >= 1000)
|
||||
{
|
||||
second_tick_timer -= 1000;
|
||||
second_tick = TRUE;
|
||||
}
|
||||
|
||||
// ***********
|
||||
|
||||
// read the chip temperature
|
||||
// temp_adc = PIOS_ADC_PinGet(0);
|
||||
|
||||
// read the psu voltage
|
||||
// psu_adc = PIOS_ADC_PinGet(1);
|
||||
|
||||
// ***********
|
||||
|
||||
uint8_t mode = saved_settings.mode;
|
||||
// modeTxBlankCarrierTest, // blank carrier Tx mode (for calibrating the carrier frequency say)
|
||||
// modeTxSpectrumTest // pseudo random Tx data mode (for checking the Tx carrier spectrum)
|
||||
|
||||
rfm22_1ms_tick(); // rf module tick
|
||||
|
||||
if (mode == MODE_NORMAL)
|
||||
ph_1ms_tick(); // packet handler tick
|
||||
|
||||
if (mode == MODE_STREAM_TX || mode == MODE_STREAM_RX)
|
||||
stream_1ms_tick(); // continuous data stream tick
|
||||
|
||||
if (mode == MODE_PPM_TX || mode == MODE_PPM_RX)
|
||||
ppm_1ms_tick(); // ppm tick
|
||||
|
||||
if (!API_Mode)
|
||||
trans_1ms_tick(); // transparent communications tick
|
||||
else
|
||||
// api_1ms_tick(); // api communications tick
|
||||
apiconfig_1ms_tick(); // api communications tick
|
||||
|
||||
// ***********
|
||||
}
|
||||
}
|
||||
|
||||
inside_timer_int = FALSE;
|
||||
}
|
||||
|
||||
void setup_TimerInt(uint16_t Hz)
|
||||
{ // setup the timer interrupt
|
||||
|
||||
// enable timer clock
|
||||
switch ((uint32_t)TIMER_INT_TIMER)
|
||||
{
|
||||
case (uint32_t)TIM1: RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); break;
|
||||
case (uint32_t)TIM2: RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); break;
|
||||
case (uint32_t)TIM3: RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); break;
|
||||
case (uint32_t)TIM4: RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); break;
|
||||
#ifdef STM32F10X_HD
|
||||
case (uint32_t)TIM5: RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE); break;
|
||||
case (uint32_t)TIM6: RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE); break;
|
||||
case (uint32_t)TIM7: RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7, ENABLE); break;
|
||||
case (uint32_t)TIM8: RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8, ENABLE); break;
|
||||
#endif
|
||||
}
|
||||
|
||||
// enable timer interrupt
|
||||
NVIC_InitTypeDef NVIC_InitStructure;
|
||||
switch ((uint32_t)TIMER_INT_TIMER)
|
||||
{
|
||||
// case (uint32_t)TIM1: NVIC_InitStructure.NVIC_IRQChannel = TIM1_IRQn; break;
|
||||
case (uint32_t)TIM2: NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; break;
|
||||
case (uint32_t)TIM3: NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; break;
|
||||
case (uint32_t)TIM4: NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn; break;
|
||||
#ifdef STM32F10X_HD
|
||||
case (uint32_t)TIM5: NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn; break;
|
||||
case (uint32_t)TIM6: NVIC_InitStructure.NVIC_IRQChannel = TIM6_IRQn; break;
|
||||
case (uint32_t)TIM7: NVIC_InitStructure.NVIC_IRQChannel = TIM7_IRQn; break;
|
||||
// case (uint32_t)TIM8: NVIC_InitStructure.NVIC_IRQChannel = TIM8_IRQn; break;
|
||||
#endif
|
||||
}
|
||||
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = TIMER_INT_PRIORITY;
|
||||
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
|
||||
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
|
||||
NVIC_Init(&NVIC_InitStructure);
|
||||
|
||||
// Time base configuration
|
||||
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
|
||||
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
|
||||
TIM_TimeBaseStructure.TIM_Period = (1000000 / Hz) - 1;
|
||||
TIM_TimeBaseStructure.TIM_Prescaler = (PIOS_MASTER_CLOCK / 1000000) - 1; // For 1 uS accuracy
|
||||
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
|
||||
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
|
||||
TIM_TimeBaseInit(TIMER_INT_TIMER, &TIM_TimeBaseStructure);
|
||||
|
||||
// Enable the CC2 Interrupt Request
|
||||
TIM_ITConfig(TIMER_INT_TIMER, TIM_IT_Update, ENABLE);
|
||||
|
||||
// Clear update pending flag
|
||||
TIM_ClearFlag(TIMER_INT_TIMER, TIM_FLAG_Update);
|
||||
|
||||
// Enable counter
|
||||
TIM_Cmd(TIMER_INT_TIMER, ENABLE);
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// read the CPU's flash and ram sizes
|
||||
|
||||
void get_CPUDetails(void)
|
||||
{
|
||||
// read the flash size
|
||||
flash_size = (uint32_t)mem16(0x1FFFF7E0) * 1024;
|
||||
|
||||
int j = 0;
|
||||
|
||||
// read the CPU electronic signature (12-bytes)
|
||||
serial_number_str[j] = 0;
|
||||
for (int i = 0; i < 12; i++)
|
||||
{
|
||||
uint8_t ms_nibble = mem8(0x1ffff7e8 + i) >> 4;
|
||||
uint8_t ls_nibble = mem8(0x1ffff7e8 + i) & 0x0f;
|
||||
if (j > sizeof(serial_number_str) - 3) break;
|
||||
serial_number_str[j++] = ((ms_nibble > 9) ? ('A' - 10) : '0') + ms_nibble;
|
||||
serial_number_str[j++] = ((ls_nibble > 9) ? ('A' - 10) : '0') + ls_nibble;
|
||||
serial_number_str[j] = 0;
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
// reset_addr = (uint32_t)&Reset_Handler;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
|
||||
void init_RF_module(void)
|
||||
{
|
||||
int i = -100;
|
||||
|
||||
switch (saved_settings.frequency_band)
|
||||
{
|
||||
case FREQBAND_434MHz:
|
||||
case FREQBAND_868MHz:
|
||||
case FREQBAND_915MHz:
|
||||
i = rfm22_init_normal(saved_settings.min_frequency_Hz, saved_settings.max_frequency_Hz, 50000);
|
||||
break;
|
||||
|
||||
default:
|
||||
#if defined(PIOS_COM_DEBUG)
|
||||
DEBUG_PRINTF("UNKNOWN BAND ERROR\r\n\r\n", i);
|
||||
#endif
|
||||
|
||||
for (int j = 0; j < 16; j++)
|
||||
{
|
||||
USB_LED_ON;
|
||||
LINK_LED_OFF;
|
||||
RX_LED_ON;
|
||||
TX_LED_OFF;
|
||||
|
||||
PIOS_DELAY_WaitmS(200);
|
||||
|
||||
USB_LED_OFF;
|
||||
LINK_LED_ON;
|
||||
RX_LED_OFF;
|
||||
TX_LED_ON;
|
||||
|
||||
PIOS_DELAY_WaitmS(200);
|
||||
|
||||
#if defined(USE_WATCHDOG)
|
||||
processWatchdog();
|
||||
#endif
|
||||
}
|
||||
|
||||
PIOS_DELAY_WaitmS(1000);
|
||||
|
||||
PIOS_SYS_Reset();
|
||||
|
||||
while (1);
|
||||
break;
|
||||
}
|
||||
|
||||
if (i < 0)
|
||||
{ // RF module error .. flash the LED's
|
||||
|
||||
#if defined(PIOS_COM_DEBUG)
|
||||
DEBUG_PRINTF("RF ERROR res: %d\r\n\r\n", i);
|
||||
#endif
|
||||
|
||||
for (int j = 0; j < 16; j++)
|
||||
{
|
||||
USB_LED_ON;
|
||||
LINK_LED_ON;
|
||||
RX_LED_OFF;
|
||||
TX_LED_OFF;
|
||||
|
||||
PIOS_DELAY_WaitmS(200);
|
||||
|
||||
USB_LED_OFF;
|
||||
LINK_LED_OFF;
|
||||
RX_LED_ON;
|
||||
TX_LED_ON;
|
||||
|
||||
PIOS_DELAY_WaitmS(200);
|
||||
|
||||
#if defined(USE_WATCHDOG)
|
||||
processWatchdog();
|
||||
#endif
|
||||
}
|
||||
|
||||
PIOS_DELAY_WaitmS(1000);
|
||||
|
||||
PIOS_SYS_Reset();
|
||||
|
||||
while (1);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// find out what caused our reset and act on it
|
||||
|
||||
void processReset(void)
|
||||
{
|
||||
if (RCC_GetFlagStatus(RCC_FLAG_IWDGRST) != RESET)
|
||||
{ // Independant Watchdog Reset
|
||||
|
||||
#if defined(PIOS_COM_DEBUG)
|
||||
DEBUG_PRINTF("\r\nINDEPENDANT WATCHDOG CAUSED A RESET\r\n");
|
||||
#endif
|
||||
|
||||
// all led's ON
|
||||
USB_LED_ON;
|
||||
LINK_LED_ON;
|
||||
RX_LED_ON;
|
||||
TX_LED_ON;
|
||||
|
||||
PIOS_DELAY_WaitmS(500); // delay a bit
|
||||
|
||||
// all led's OFF
|
||||
USB_LED_OFF;
|
||||
LINK_LED_OFF;
|
||||
RX_LED_OFF;
|
||||
TX_LED_OFF;
|
||||
|
||||
}
|
||||
/*
|
||||
if (RCC_GetFlagStatus(RCC_FLAG_WWDGRST) != RESET)
|
||||
{ // Window Watchdog Reset
|
||||
|
||||
DEBUG_PRINTF("\r\nWINDOW WATCHDOG CAUSED A REBOOT\r\n");
|
||||
|
||||
// all led's ON
|
||||
USB_LED_ON;
|
||||
LINK_LED_ON;
|
||||
RX_LED_ON;
|
||||
TX_LED_ON;
|
||||
|
||||
PIOS_DELAY_WaitmS(500); // delay a bit
|
||||
|
||||
// all led's OFF
|
||||
USB_LED_OFF;
|
||||
LINK_LED_OFF;
|
||||
RX_LED_OFF;
|
||||
TX_LED_OFF;
|
||||
}
|
||||
*/
|
||||
if (RCC_GetFlagStatus(RCC_FLAG_PORRST) != RESET)
|
||||
{ // Power-On Reset
|
||||
#if defined(PIOS_COM_DEBUG)
|
||||
DEBUG_PRINTF("\r\nPOWER-ON-RESET\r\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
if (RCC_GetFlagStatus(RCC_FLAG_SFTRST) != RESET)
|
||||
{ // Software Reset
|
||||
#if defined(PIOS_COM_DEBUG)
|
||||
DEBUG_PRINTF("\r\nSOFTWARE RESET\r\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
if (RCC_GetFlagStatus(RCC_FLAG_LPWRRST) != RESET)
|
||||
{ // Low-Power Reset
|
||||
#if defined(PIOS_COM_DEBUG)
|
||||
DEBUG_PRINTF("\r\nLOW POWER RESET\r\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
if (RCC_GetFlagStatus(RCC_FLAG_PINRST) != RESET)
|
||||
{ // Pin Reset
|
||||
#if defined(PIOS_COM_DEBUG)
|
||||
DEBUG_PRINTF("\r\nPIN RESET\r\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
// Clear reset flags
|
||||
RCC_ClearFlag();
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// Main function
|
||||
|
||||
int main()
|
||||
{
|
||||
// *************
|
||||
// init various variables
|
||||
|
||||
booting = TRUE;
|
||||
|
||||
inside_timer_int = FALSE;
|
||||
|
||||
uptime_ms = 0;
|
||||
|
||||
flash_size = 0;
|
||||
|
||||
serial_number_str[0] = 0;
|
||||
serial_number_crc32 = 0;
|
||||
|
||||
reset_addr = 0;
|
||||
|
||||
// temp_adc = -1;
|
||||
// psu_adc = -1;
|
||||
|
||||
// API_Mode = FALSE;
|
||||
API_Mode = TRUE; // TEST ONLY
|
||||
|
||||
second_tick_timer = 0;
|
||||
second_tick = FALSE;
|
||||
|
||||
saved_settings.frequency_band = FREQBAND_UNKNOWN;
|
||||
|
||||
// *************
|
||||
|
||||
PIOS_Board_Init();
|
||||
|
||||
CRC_init();
|
||||
|
||||
// read the CPU details
|
||||
get_CPUDetails();
|
||||
|
||||
// setup the GPIO input pins
|
||||
GPIO_IN_Init();
|
||||
|
||||
// *************
|
||||
// set various GPIO pin states
|
||||
|
||||
// uart serial RTS line high
|
||||
SERIAL_RTS_ENABLE;
|
||||
SERIAL_RTS_SET;
|
||||
|
||||
// RF module chip-select line high
|
||||
RF_CS_ENABLE;
|
||||
RF_CS_HIGH;
|
||||
|
||||
// PPM OUT low
|
||||
PPM_OUT_ENABLE;
|
||||
PPM_OUT_LOW;
|
||||
|
||||
// pin high
|
||||
SPARE1_ENABLE;
|
||||
SPARE1_HIGH;
|
||||
|
||||
// pin high
|
||||
SPARE2_ENABLE;
|
||||
SPARE2_HIGH;
|
||||
|
||||
// pin high
|
||||
SPARE3_ENABLE;
|
||||
SPARE3_HIGH;
|
||||
|
||||
// pin high
|
||||
SPARE4_ENABLE;
|
||||
SPARE4_HIGH;
|
||||
|
||||
// pin high
|
||||
SPARE5_ENABLE;
|
||||
SPARE5_HIGH;
|
||||
|
||||
// *************
|
||||
|
||||
random32 ^= serial_number_crc32; // try to randomise the random number
|
||||
// random32 ^= serial_number_crc32 ^ CRC_IDR; // try to randomise the random number
|
||||
|
||||
trans_init(); // initialise the transparent communications module
|
||||
|
||||
// api_init(); // initialise the API communications module
|
||||
apiconfig_init(); // initialise the API communications module
|
||||
|
||||
setup_TimerInt(1000); // setup a 1kHz timer interrupt
|
||||
|
||||
#if defined(USE_WATCHDOG)
|
||||
enableWatchdog(); // enable the watchdog
|
||||
#endif
|
||||
|
||||
// *************
|
||||
// do a simple LED flash test sequence so the user knows all the led's are working and that we have booted
|
||||
|
||||
PIOS_DELAY_WaitmS(100);
|
||||
|
||||
// turn all the leds off
|
||||
USB_LED_OFF;
|
||||
LINK_LED_OFF;
|
||||
RX_LED_OFF;
|
||||
TX_LED_OFF;
|
||||
|
||||
PIOS_DELAY_WaitmS(200);
|
||||
|
||||
sequenceLEDs();
|
||||
|
||||
// turn all the leds off
|
||||
USB_LED_OFF;
|
||||
LINK_LED_OFF;
|
||||
RX_LED_OFF;
|
||||
TX_LED_OFF;
|
||||
|
||||
// *************
|
||||
|
||||
#if defined(PIOS_COM_DEBUG)
|
||||
DEBUG_PRINTF("\r\n");
|
||||
DEBUG_PRINTF("PipXtreme v%u.%u rebooted\r\n", VERSION_MAJOR, VERSION_MINOR);
|
||||
DEBUG_PRINTF("\r\n");
|
||||
DEBUG_PRINTF("CPU flash size: %u\r\n", flash_size);
|
||||
DEBUG_PRINTF("CPU serial number: %s %08X\r\n", serial_number_str, serial_number_crc32);
|
||||
// DEBUG_PRINTF("Reset address: %08X\r\n", reset_addr);
|
||||
#endif
|
||||
|
||||
// *************
|
||||
// initialise the saved settings module
|
||||
|
||||
saved_settings_init();
|
||||
|
||||
if (saved_settings.mode == 0xff ||
|
||||
saved_settings.mode == MODE_TX_BLANK_CARRIER_TEST ||
|
||||
saved_settings.mode == MODE_TX_SPECTRUM_TEST ||
|
||||
saved_settings.mode == MODE_SCAN_SPECTRUM)
|
||||
saved_settings.mode = MODE_NORMAL; // go back to NORMAL mode
|
||||
|
||||
if (saved_settings.rts_time == 0xff || saved_settings.rts_time > 100)
|
||||
saved_settings.rts_time = 10; // default to 10ms
|
||||
|
||||
#if !defined(PIOS_COM_DEBUG)
|
||||
if (saved_settings.serial_baudrate != 0xffffffff)
|
||||
PIOS_COM_ChangeBaud(PIOS_COM_SERIAL, saved_settings.serial_baudrate);
|
||||
#endif
|
||||
|
||||
// *************
|
||||
// read the API mode pin
|
||||
|
||||
if (!GPIO_IN(API_MODE_PIN))
|
||||
API_Mode = TRUE;
|
||||
|
||||
#if defined(PIOS_COM_DEBUG)
|
||||
if (!API_Mode)
|
||||
DEBUG_PRINTF("TRANSPARENT mode\r\n");
|
||||
else
|
||||
DEBUG_PRINTF("API mode\r\n");
|
||||
#endif
|
||||
|
||||
// *************
|
||||
// read the 434/868/915 jumper options
|
||||
|
||||
if (!GPIO_IN(_868MHz_PIN) && !GPIO_IN(_915MHz_PIN)) saved_settings.frequency_band = FREQBAND_434MHz; // 434MHz band
|
||||
else
|
||||
if (!GPIO_IN(_868MHz_PIN) && GPIO_IN(_915MHz_PIN)) saved_settings.frequency_band = FREQBAND_868MHz; // 868MHz band
|
||||
else
|
||||
if ( GPIO_IN(_868MHz_PIN) && !GPIO_IN(_915MHz_PIN)) saved_settings.frequency_band = FREQBAND_915MHz; // 915MHz band
|
||||
|
||||
// set some defaults if they are not set
|
||||
switch (saved_settings.frequency_band)
|
||||
{
|
||||
case FREQBAND_434MHz:
|
||||
|
||||
if (saved_settings.min_frequency_Hz == 0xffffffff)
|
||||
{
|
||||
saved_settings.frequency_Hz = 434000000;
|
||||
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)
|
||||
{
|
||||
// saved_settings.max_rf_bandwidth = 500;
|
||||
// saved_settings.max_rf_bandwidth = 1000;
|
||||
// saved_settings.max_rf_bandwidth = 2000;
|
||||
// saved_settings.max_rf_bandwidth = 4000;
|
||||
// saved_settings.max_rf_bandwidth = 8000;
|
||||
// saved_settings.max_rf_bandwidth = 9600;
|
||||
// saved_settings.max_rf_bandwidth = 16000;
|
||||
// saved_settings.max_rf_bandwidth = 19200;
|
||||
// saved_settings.max_rf_bandwidth = 24000;
|
||||
// saved_settings.max_rf_bandwidth = 32000;
|
||||
// saved_settings.max_rf_bandwidth = 64000;
|
||||
saved_settings.max_rf_bandwidth = 128000;
|
||||
// saved_settings.max_rf_bandwidth = 192000;
|
||||
}
|
||||
if (saved_settings.max_tx_power == 0xff)
|
||||
{
|
||||
saved_settings.max_tx_power = RFM22_tx_pwr_txpow_0; // +1dBm ... 1.25mW
|
||||
// saved_settings.max_tx_power = RFM22_tx_pwr_txpow_1; // +2dBm ... 1.6mW
|
||||
// saved_settings.max_tx_power = RFM22_tx_pwr_txpow_2; // +5dBm ... 3.16mW
|
||||
// saved_settings.max_tx_power = RFM22_tx_pwr_txpow_3; // +8dBm ... 6.3mW
|
||||
// saved_settings.max_tx_power = RFM22_tx_pwr_txpow_4; // +11dBm .. 12.6mW
|
||||
// saved_settings.max_tx_power = RFM22_tx_pwr_txpow_5; // +14dBm .. 25mW
|
||||
// saved_settings.max_tx_power = RFM22_tx_pwr_txpow_6; // +17dBm .. 50mW
|
||||
// saved_settings.max_tx_power = RFM22_tx_pwr_txpow_7; // +20dBm .. 100mW
|
||||
}
|
||||
break;
|
||||
|
||||
case FREQBAND_868MHz:
|
||||
if (saved_settings.min_frequency_Hz == 0xffffffff)
|
||||
{
|
||||
saved_settings.frequency_Hz = 868000000;
|
||||
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)
|
||||
saved_settings.max_rf_bandwidth = 128000;
|
||||
if (saved_settings.max_tx_power == 0xff)
|
||||
saved_settings.max_tx_power = RFM22_tx_pwr_txpow_0; // +1dBm ... 1.25mW
|
||||
break;
|
||||
|
||||
case FREQBAND_915MHz:
|
||||
if (saved_settings.min_frequency_Hz == 0xffffffff)
|
||||
{
|
||||
saved_settings.frequency_Hz = 915000000;
|
||||
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)
|
||||
saved_settings.max_rf_bandwidth = 128000;
|
||||
if (saved_settings.max_tx_power == 0xff)
|
||||
saved_settings.max_tx_power = RFM22_tx_pwr_txpow_0; // +1dBm ... 1.25mW
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
#if defined(PIOS_COM_DEBUG)
|
||||
switch (saved_settings.frequency_band)
|
||||
{
|
||||
case FREQBAND_UNKNOWN: DEBUG_PRINTF("UNKNOWN band\r\n"); break;
|
||||
case FREQBAND_434MHz: DEBUG_PRINTF("434MHz band\r\n"); break;
|
||||
case FREQBAND_868MHz: DEBUG_PRINTF("868MHz band\r\n"); break;
|
||||
case FREQBAND_915MHz: DEBUG_PRINTF("915MHz band\r\n"); break;
|
||||
}
|
||||
#endif
|
||||
|
||||
// *************
|
||||
|
||||
processReset(); // Determine what caused the reset/reboot
|
||||
|
||||
init_RF_module(); // initialise the RF module
|
||||
|
||||
// *************
|
||||
|
||||
#if defined(PIOS_COM_DEBUG)
|
||||
DEBUG_PRINTF("\r\n");
|
||||
DEBUG_PRINTF("RF datarate: %dbps\r\n", ph_getDatarate());
|
||||
DEBUG_PRINTF("RF frequency: %dHz\r\n", rfm22_getNominalCarrierFrequency());
|
||||
DEBUG_PRINTF("RF TX power: %d\r\n", ph_getTxPower());
|
||||
|
||||
DEBUG_PRINTF("\r\nUnit mode: ");
|
||||
switch (saved_settings.mode)
|
||||
{
|
||||
case MODE_NORMAL: DEBUG_PRINTF("NORMAL\r\n"); break;
|
||||
case MODE_STREAM_TX: DEBUG_PRINTF("STREAM-TX\r\n"); break;
|
||||
case MODE_STREAM_RX: DEBUG_PRINTF("STREAM-RX\r\n"); break;
|
||||
case MODE_PPM_TX: DEBUG_PRINTF("PPM-TX\r\n"); break;
|
||||
case MODE_PPM_RX: DEBUG_PRINTF("PPM-RX\r\n"); break;
|
||||
case MODE_SCAN_SPECTRUM: DEBUG_PRINTF("SCAN-SPECTRUM\r\n"); break;
|
||||
case MODE_TX_BLANK_CARRIER_TEST: DEBUG_PRINTF("TX-BLANK-CARRIER\r\n"); break;
|
||||
case MODE_TX_SPECTRUM_TEST: DEBUG_PRINTF("TX_SPECTRUM\r\n"); break;
|
||||
default: DEBUG_PRINTF("UNKNOWN [%u]\r\n", saved_settings.mode); break;
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (saved_settings.mode)
|
||||
{
|
||||
case MODE_NORMAL:
|
||||
ph_init(serial_number_crc32); // initialise the packet handler
|
||||
break;
|
||||
|
||||
case MODE_STREAM_TX:
|
||||
case MODE_STREAM_RX:
|
||||
stream_init(serial_number_crc32); // initialise the continuous packet stream module
|
||||
break;
|
||||
|
||||
case MODE_PPM_TX:
|
||||
case MODE_PPM_RX:
|
||||
ppm_init(serial_number_crc32); // initialise the ppm module
|
||||
break;
|
||||
|
||||
case MODE_SCAN_SPECTRUM:
|
||||
case MODE_TX_BLANK_CARRIER_TEST:
|
||||
case MODE_TX_SPECTRUM_TEST:
|
||||
break;
|
||||
}
|
||||
|
||||
// *************
|
||||
// Main executive loop
|
||||
|
||||
saved_settings_save();
|
||||
|
||||
booting = FALSE;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
random32 = updateCRC32(random32, PIOS_DELAY_GetuS() >> 8);
|
||||
random32 = updateCRC32(random32, PIOS_DELAY_GetuS());
|
||||
|
||||
if (second_tick)
|
||||
{
|
||||
second_tick = FALSE;
|
||||
|
||||
// *************************
|
||||
// display the up-time .. HH:MM:SS
|
||||
|
||||
// #if defined(PIOS_COM_DEBUG)
|
||||
// uint32_t _uptime_ms = uptime_ms;
|
||||
// uint32_t _uptime_sec = _uptime_ms / 1000;
|
||||
// DEBUG_PRINTF("Uptime: %02d:%02d:%02d.%03d\r\n", _uptime_sec / 3600, (_uptime_sec / 60) % 60, _uptime_sec % 60, _uptime_ms % 1000);
|
||||
// #endif
|
||||
|
||||
// *************************
|
||||
// process the Temperature
|
||||
|
||||
// if (temp_adc >= 0)
|
||||
// {
|
||||
// int32_t degress_C = temp_adc;
|
||||
//
|
||||
// #if defined(PIOS_COM_DEBUG)
|
||||
// DEBUG_PRINTF("TEMP: %d %d\r\n", temp_adc, degress_C);
|
||||
// #endif
|
||||
// }
|
||||
|
||||
// *************************
|
||||
// process the PSU voltage level
|
||||
|
||||
// if (psu_adc >= 0)
|
||||
// {
|
||||
// int32_t psu_mV = psu_adc * ADC_PSU_mV_SCALE;
|
||||
//
|
||||
// #if defined(PIOS_COM_DEBUG)
|
||||
// DEBUG_PRINTF("PSU: %d, %dmV\r\n", psu_adc, psu_mV);
|
||||
// #endif
|
||||
// }
|
||||
|
||||
// *************************
|
||||
}
|
||||
|
||||
rfm22_process(); // rf hardware layer processing
|
||||
|
||||
uint8_t mode = saved_settings.mode;
|
||||
// modeTxBlankCarrierTest, // blank carrier Tx mode (for calibrating the carrier frequency say)
|
||||
// modeTxSpectrumTest // pseudo random Tx data mode (for checking the Tx carrier spectrum)
|
||||
|
||||
if (mode == MODE_NORMAL)
|
||||
ph_process(); // packet handler processing
|
||||
|
||||
if (mode == MODE_STREAM_TX || mode == MODE_STREAM_RX)
|
||||
stream_process(); // continuous data stream processing
|
||||
|
||||
if (mode == MODE_PPM_TX || mode == MODE_PPM_RX)
|
||||
ppm_process(); // ppm processing
|
||||
|
||||
if (!API_Mode)
|
||||
trans_process(); // tranparent local communication processing (serial port and usb port)
|
||||
else
|
||||
// api_process(); // API local communication processing (serial port and usb port)
|
||||
apiconfig_process(); // API local communication processing (serial port and usb port)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ******************
|
||||
// TEST ONLY ... get/put data over the radio link .. speed testing .. comment out trans_process() and api_process() if testing with this
|
||||
/*
|
||||
int connection_index = 0;
|
||||
|
||||
if (ph_connected(connection_index))
|
||||
{ // we have a connection to a remote modem
|
||||
|
||||
uint8_t buffer[128];
|
||||
|
||||
uint16_t num = ph_getData_used(connection_index); // number of bytes waiting for us to get
|
||||
if (num > 0)
|
||||
{ // their is data in the received buffer - fetch it
|
||||
if (num > sizeof(buffer)) num = sizeof(buffer);
|
||||
num = ph_getData(connection_index, buffer, num); // fetch the received data
|
||||
}
|
||||
|
||||
// keep the tx buffer topped up
|
||||
num = ph_putData_free(connection_index);
|
||||
if (num > 0)
|
||||
{ // their is space available in the transmit buffer - top it up
|
||||
if (num > sizeof(buffer)) num = sizeof(buffer);
|
||||
for (int16_t i = 0; i < num; i++) buffer[i] = i;
|
||||
num = ph_putData(connection_index, buffer, num);
|
||||
}
|
||||
}
|
||||
*/
|
||||
// ******************
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#if defined(USE_WATCHDOG)
|
||||
processWatchdog(); // process the watchdog
|
||||
#endif
|
||||
}
|
||||
|
||||
// *************
|
||||
// we should never arrive here
|
||||
|
||||
// disable all interrupts
|
||||
PIOS_IRQ_Disable();
|
||||
|
||||
// turn off all leds
|
||||
USB_LED_OFF;
|
||||
LINK_LED_OFF;
|
||||
RX_LED_OFF;
|
||||
TX_LED_OFF;
|
||||
|
||||
PIOS_SYS_Reset();
|
||||
|
||||
while (1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
@ -1,1724 +0,0 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* @file packet_handler.c
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief Modem packet handling routines
|
||||
* @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
|
||||
*/
|
||||
|
||||
|
||||
// ********
|
||||
|
||||
// We use 128-bit AES CBC encryption if encryption is enabled
|
||||
|
||||
|
||||
// encrypted packet format
|
||||
// 16-byte CBC .. 1st byte must not be zero
|
||||
// 4-byte source id
|
||||
// 4-byte destination id
|
||||
// 1-byte packet type
|
||||
// 1-byte tx sequence value
|
||||
// 1-byte rx sequence value
|
||||
// 1-byte data size
|
||||
// 4-byte crc of entire packet not including CBC bytes
|
||||
|
||||
|
||||
// unencrypted packet format
|
||||
// 1-byte null byte .. set to zero to indicate packet is not encrypted
|
||||
// 4-byte source id
|
||||
// 4-byte destination id
|
||||
// 1-byte packet type
|
||||
// 1-byte tx sequence value
|
||||
// 1-byte rx sequence value
|
||||
// 1-byte data size
|
||||
// 4-byte crc of entire packet not including the null byte
|
||||
|
||||
// ********
|
||||
|
||||
#include <string.h> // memmove
|
||||
|
||||
#include "main.h"
|
||||
#include "rfm22b.h"
|
||||
#include "fifo_buffer.h"
|
||||
#include "aes.h"
|
||||
#include "crc.h"
|
||||
#include "saved_settings.h"
|
||||
#include "packet_handler.h"
|
||||
|
||||
#if defined(PIOS_COM_DEBUG)
|
||||
// #define PACKET_DEBUG
|
||||
#endif
|
||||
|
||||
// *****************************************************************************
|
||||
|
||||
#define PH_FIFO_BUFFER_SIZE 2048 // FIFO buffer size
|
||||
|
||||
// *****************************************************************************
|
||||
|
||||
#define AES_BLOCK_SIZE 16 // AES encryption does it in 16-byte blocks ONLY
|
||||
|
||||
// default aes 128-bit encryption key
|
||||
const uint8_t default_aes_key[AES_BLOCK_SIZE] = {0x65, 0x3b, 0x71, 0x89, 0x4a, 0xf4, 0xc8, 0xcb, 0x18, 0xd4, 0x9b, 0x4d, 0x4a, 0xbe, 0xc8, 0x37};
|
||||
|
||||
// *****************************************************************************
|
||||
|
||||
#define RETRY_RECONNECT_COUNT 60 // if transmission retries this many times then reset the link to the remote modem
|
||||
|
||||
#define PACKET_TYPE_DATA_COMP_BIT 0x80 // data compressed bit. if set then the data in the packet is compressed
|
||||
#define PACKET_TYPE_MASK 0x7f // packet type mask
|
||||
|
||||
enum {
|
||||
PACKET_TYPE_NONE = 0,
|
||||
|
||||
PACKET_TYPE_CONNECT, // for requesting a connection
|
||||
PACKET_TYPE_CONNECT_ACK, // ack
|
||||
|
||||
PACKET_TYPE_DISCONNECT, // to tell the other modem they cannot connect to us
|
||||
|
||||
PACKET_TYPE_DATA, // data packet (packet contains user data)
|
||||
PACKET_TYPE_DATA_ACK, // ack
|
||||
|
||||
PACKET_TYPE_READY, // tells the other modem we are ready to accept more data
|
||||
PACKET_TYPE_READY_ACK, // ack
|
||||
|
||||
PACKET_TYPE_NOTREADY, // tells the other modem we're not ready to accept more data - we can also send user data in this packet type
|
||||
PACKET_TYPE_NOTREADY_ACK, // ack
|
||||
|
||||
PACKET_TYPE_DATARATE, // for changing the RF data rate
|
||||
PACKET_TYPE_DATARATE_ACK, // ack
|
||||
|
||||
PACKET_TYPE_PING, // used to check link is still up
|
||||
PACKET_TYPE_PONG, // ack
|
||||
|
||||
PACKET_TYPE_ADJUST_TX_PWR, // used to ask the other modem to adjust it's tx power
|
||||
PACKET_TYPE_ADJUST_TX_PWR_ACK // ack
|
||||
};
|
||||
|
||||
#define BROADCAST_ADDR 0xffffffff
|
||||
|
||||
//#pragma pack(push)
|
||||
//#pragma pack(1)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t source_id;
|
||||
uint32_t destination_id;
|
||||
uint8_t type;
|
||||
uint8_t tx_seq;
|
||||
uint8_t rx_seq;
|
||||
uint8_t data_size;
|
||||
uint32_t crc;
|
||||
} __attribute__((__packed__)) t_packet_header;
|
||||
|
||||
// this structure must be a multiple of 'AES_BLOCK_SIZE' bytes in size and no more than 255 bytes in size
|
||||
typedef struct
|
||||
{
|
||||
uint8_t cbc[AES_BLOCK_SIZE]; // AES encryption Cipher-Block-Chaining key .. 1st byte must not be zero - to indicate the packet is encrypted
|
||||
t_packet_header header;
|
||||
uint8_t data[240 - sizeof(t_packet_header) - AES_BLOCK_SIZE];
|
||||
} __attribute__((__packed__)) t_encrypted_packet;
|
||||
|
||||
// this structure must be no more than 255 bytes in size (255 = the maximum packet size)
|
||||
typedef struct
|
||||
{
|
||||
uint8_t null_byte; // this must be set to zero - to indicate the packet is unencrypted
|
||||
t_packet_header header;
|
||||
uint8_t data[255 - sizeof(t_packet_header) - 1];
|
||||
} __attribute__((__packed__)) t_unencrypted_packet;
|
||||
|
||||
//#pragma pack(pop)
|
||||
|
||||
// *****************************************************************************
|
||||
// link state for each remote connection
|
||||
|
||||
enum {
|
||||
LINK_DISCONNECTED = 0,
|
||||
LINK_CONNECTING,
|
||||
LINK_CONNECTED
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t serial_number; // their serial number
|
||||
|
||||
uint8_t tx_buffer[PH_FIFO_BUFFER_SIZE] __attribute__ ((aligned(4)));
|
||||
t_fifo_buffer tx_fifo_buffer; // holds the data to be transmitted to the other modem
|
||||
|
||||
uint8_t rx_buffer[PH_FIFO_BUFFER_SIZE] __attribute__ ((aligned(4)));
|
||||
t_fifo_buffer rx_fifo_buffer; // holds the data received from the other modem
|
||||
|
||||
uint8_t link_state; // holds our current RF link state
|
||||
|
||||
uint8_t tx_sequence; // incremented with each data packet transmitted, sent in every packet transmitted
|
||||
uint8_t tx_sequence_data_size; // the size of data we sent in our last packet
|
||||
|
||||
uint8_t rx_sequence; // incremented with each data packet received contain data, sent in every packet transmitted
|
||||
|
||||
volatile uint16_t tx_packet_timer; // ms .. used for packet timing
|
||||
|
||||
uint16_t tx_retry_time_slots; // add's some random packet transmission timing - to try to prevent transmission collisions
|
||||
uint16_t tx_retry_time_slot_len; // ms .. " " "
|
||||
uint16_t tx_retry_time; // ms .. " " "
|
||||
uint16_t tx_retry_counter; // incremented on each transmission, reset back to '0' when we receive an ack to our transmission
|
||||
|
||||
volatile uint16_t data_speed_timer; // used for calculating the transmit/receive data rate
|
||||
volatile uint32_t tx_data_speed_count; // incremented with the number of data bits we send in our transmit packets
|
||||
volatile uint32_t tx_data_speed; // holds the number of data bits we have sent each second
|
||||
volatile uint32_t rx_data_speed_count; // incremented with the number of data bits we send in our transmit packets
|
||||
volatile uint32_t rx_data_speed; // holds the number of data bits we have received each second
|
||||
|
||||
uint16_t ping_time; // ping timer
|
||||
uint16_t fast_ping_time; // ping timer
|
||||
bool pinging; // TRUE if we are doing a ping test with the other modem - to check if it is still present
|
||||
|
||||
bool rx_not_ready_mode; // TRUE if we have told the other modem we cannot receive data (due to buffer filling up).
|
||||
// we set it back to FALSE when our received buffer starts to empty
|
||||
|
||||
volatile int16_t ready_to_send_timer; // ms .. used to hold off packet transmission to wait a bit for data to mount up for transmission (improves data thru-put speed)
|
||||
|
||||
volatile int32_t not_ready_timer; // ms .. >= 0 while we have been asked not to send anymore data to the other modem, -1 when we are allowed to send data
|
||||
|
||||
bool send_encrypted; // TRUE if we are to AES encrypt in every packet we transmit
|
||||
|
||||
int16_t rx_rssi_dBm; // the strength of the received packet
|
||||
int32_t rx_afc_Hz; // the frequency offset of the received packet
|
||||
|
||||
} t_connection;
|
||||
|
||||
// *****************************************************************************
|
||||
|
||||
uint32_t our_serial_number = 0; // our serial number
|
||||
|
||||
t_connection connection[PH_MAX_CONNECTIONS]; // holds each connection state
|
||||
|
||||
uint8_t aes_key[AES_BLOCK_SIZE] __attribute__ ((aligned(4))); // holds the aes encryption key - the same for ALL connections
|
||||
uint8_t dec_aes_key[AES_BLOCK_SIZE] __attribute__ ((aligned(4))); // holds the pre-calculated decryption key
|
||||
uint8_t enc_cbc[AES_BLOCK_SIZE] __attribute__ ((aligned(4))); // holds the tx aes cbc bytes
|
||||
|
||||
uint8_t ph_tx_buffer[256] __attribute__ ((aligned(4))); // holds the transmit packet
|
||||
|
||||
uint8_t ph_rx_buffer[256] __attribute__ ((aligned(4))); // holds the received packet
|
||||
|
||||
int16_t rx_rssi_dBm;
|
||||
int32_t rx_afc_Hz;
|
||||
|
||||
bool fast_ping;
|
||||
|
||||
// *****************************************************************************
|
||||
// return TRUE if we are connected to the remote modem
|
||||
|
||||
bool ph_connected(const int connection_index)
|
||||
{
|
||||
if (connection_index < 0 || connection_index >= PH_MAX_CONNECTIONS)
|
||||
return FALSE;
|
||||
|
||||
t_connection *conn = &connection[connection_index];
|
||||
|
||||
return (conn->link_state == LINK_CONNECTED);
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// public tx buffer functions
|
||||
|
||||
uint16_t ph_putData_free(const int connection_index)
|
||||
{ // return the free space size
|
||||
if (connection_index < 0 || connection_index >= PH_MAX_CONNECTIONS)
|
||||
return 0;
|
||||
|
||||
return fifoBuf_getFree(&connection[connection_index].tx_fifo_buffer);
|
||||
}
|
||||
|
||||
uint16_t ph_putData(const int connection_index, const void *data, uint16_t len)
|
||||
{ // add data to our tx buffer to be sent
|
||||
if (connection_index < 0 || connection_index >= PH_MAX_CONNECTIONS)
|
||||
return 0;
|
||||
|
||||
return fifoBuf_putData(&connection[connection_index].tx_fifo_buffer, data, len);
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// public rx buffer functions
|
||||
|
||||
uint16_t ph_getData_used(const int connection_index)
|
||||
{ // return the number of bytes available in the rx buffer
|
||||
if (connection_index < 0 || connection_index >= PH_MAX_CONNECTIONS)
|
||||
return 0;
|
||||
|
||||
return fifoBuf_getUsed(&connection[connection_index].rx_fifo_buffer);
|
||||
}
|
||||
|
||||
uint16_t ph_getData(const int connection_index, void *data, uint16_t len)
|
||||
{ // get data from our rx buffer
|
||||
if (connection_index < 0 || connection_index >= PH_MAX_CONNECTIONS)
|
||||
return 0;
|
||||
|
||||
return fifoBuf_getData(&connection[connection_index].rx_fifo_buffer, data, len);
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// start a connection to another modem
|
||||
|
||||
int ph_startConnect(int connection_index, uint32_t sn)
|
||||
{
|
||||
random32 = updateCRC32(random32, 0xff);
|
||||
|
||||
if (connection_index < 0 || connection_index >= PH_MAX_CONNECTIONS)
|
||||
return -1;
|
||||
|
||||
t_connection *conn = &connection[connection_index];
|
||||
|
||||
conn->link_state = LINK_DISCONNECTED;
|
||||
|
||||
LINK_LED_OFF;
|
||||
|
||||
conn->serial_number = sn;
|
||||
|
||||
conn->tx_sequence = 0;
|
||||
conn->tx_sequence_data_size = 0;
|
||||
conn->rx_sequence = 0;
|
||||
|
||||
// fifoBuf_init(&conn->tx_fifo_buffer, conn->tx_buffer, PH_FIFO_BUFFER_SIZE);
|
||||
// fifoBuf_init(&conn->rx_fifo_buffer, conn->rx_buffer, PH_FIFO_BUFFER_SIZE);
|
||||
|
||||
conn->tx_packet_timer = 0;
|
||||
|
||||
conn->tx_retry_time_slots = 5;
|
||||
|
||||
uint32_t ms = 1280000ul / rfm22_getDatarate();
|
||||
if (ms < 10) ms = 10;
|
||||
else
|
||||
if (ms > 32000) ms = 32000;
|
||||
conn->tx_retry_time_slot_len = ms;
|
||||
|
||||
conn->tx_retry_time = conn->tx_retry_time_slot_len * 4 + (random32 % conn->tx_retry_time_slots) * conn->tx_retry_time_slot_len * 4;
|
||||
|
||||
conn->tx_retry_counter = 0;
|
||||
|
||||
conn->data_speed_timer = 0;
|
||||
conn->tx_data_speed_count = 0;
|
||||
conn->tx_data_speed = 0;
|
||||
conn->rx_data_speed_count = 0;
|
||||
conn->rx_data_speed = 0;
|
||||
|
||||
conn->ping_time = 8000 + (random32 % 100) * 10;
|
||||
conn->fast_ping_time = 600 + (random32 % 50) * 10;
|
||||
conn->pinging = false;
|
||||
|
||||
conn->rx_not_ready_mode = false;
|
||||
|
||||
conn->ready_to_send_timer = -1;
|
||||
|
||||
conn->not_ready_timer = -1;
|
||||
|
||||
// conn->send_encrypted = true;
|
||||
// conn->send_encrypted = false;
|
||||
|
||||
conn->rx_rssi_dBm = -200;
|
||||
conn->rx_afc_Hz = 0;
|
||||
|
||||
if (sn != 0 && sn == our_serial_number)
|
||||
return -2; // same as our own
|
||||
|
||||
if (sn == BROADCAST_ADDR)
|
||||
{
|
||||
|
||||
return -3;
|
||||
}
|
||||
|
||||
if (conn->serial_number != 0)
|
||||
conn->link_state = LINK_CONNECTING;
|
||||
|
||||
return connection_index;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// return a byte for the tx packet transmission.
|
||||
//
|
||||
// return value < 0 if no more bytes available, otherwise return byte to be sent
|
||||
|
||||
int16_t ph_TxDataByteCallback(void)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
// *************************************************************
|
||||
// we are being given a block of received bytes
|
||||
//
|
||||
// return TRUE to continue current packet receive, otherwise return FALSE to halt current packet reception
|
||||
|
||||
bool ph_RxDataCallback(void *data, uint8_t len)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// transmit a packet
|
||||
|
||||
bool ph_sendPacket(int connection_index, bool encrypt, uint8_t packet_type, bool send_immediately)
|
||||
{
|
||||
uint8_t key[AES_BLOCK_SIZE];
|
||||
|
||||
t_connection *conn = NULL;
|
||||
|
||||
// ***********
|
||||
|
||||
t_encrypted_packet *encrypted_packet = (t_encrypted_packet*)&ph_tx_buffer; // point to the tx buffer
|
||||
t_unencrypted_packet *unencrypted_packet = (t_unencrypted_packet*)&ph_tx_buffer; // point to the tx buffer
|
||||
|
||||
t_packet_header *header;
|
||||
uint8_t *data;
|
||||
uint16_t max_data_size;
|
||||
|
||||
if (encrypt)
|
||||
{
|
||||
header = (t_packet_header *)&encrypted_packet->header;
|
||||
data = (uint8_t *)&encrypted_packet->data;
|
||||
max_data_size = sizeof(encrypted_packet->data);
|
||||
}
|
||||
else
|
||||
{
|
||||
header = (t_packet_header *)&unencrypted_packet->header;
|
||||
data = (uint8_t *)&unencrypted_packet->data;
|
||||
max_data_size = sizeof(unencrypted_packet->data);
|
||||
}
|
||||
|
||||
// ***********
|
||||
|
||||
if (!rfm22_txReady())
|
||||
return false;
|
||||
|
||||
if ((packet_type & PACKET_TYPE_MASK) == PACKET_TYPE_NONE)
|
||||
return false;
|
||||
|
||||
if (connection_index >= PH_MAX_CONNECTIONS)
|
||||
return false;
|
||||
|
||||
if (connection_index >= 0)
|
||||
conn = (t_connection *)&connection[connection_index];
|
||||
else
|
||||
return false;
|
||||
|
||||
// ******************
|
||||
// stuff
|
||||
|
||||
uint8_t pack_type = packet_type & PACKET_TYPE_MASK;
|
||||
|
||||
bool data_packet = (pack_type == PACKET_TYPE_DATA || pack_type == PACKET_TYPE_NOTREADY);
|
||||
|
||||
// ******************
|
||||
// calculate how many user data bytes we are going to add to the packet
|
||||
|
||||
uint16_t data_size = 0;
|
||||
|
||||
if (data_packet && conn)
|
||||
{ // we're adding user data to the packet
|
||||
data_size = fifoBuf_getUsed(&connection[connection_index].tx_fifo_buffer); // the number of data bytes waiting to be sent
|
||||
|
||||
if (data_size > max_data_size)
|
||||
data_size = max_data_size;
|
||||
|
||||
if (conn->tx_sequence_data_size > 0)
|
||||
{ // we are re-sending data the same data
|
||||
if (data_size > conn->tx_sequence_data_size)
|
||||
data_size = conn->tx_sequence_data_size;
|
||||
}
|
||||
}
|
||||
|
||||
// ******************
|
||||
// calculate the total packet size (including null data bytes if we have to add null data byte in AES encrypted packets)
|
||||
|
||||
uint32_t packet_size;
|
||||
|
||||
if (encrypt)
|
||||
{
|
||||
packet_size = AES_BLOCK_SIZE + sizeof(t_packet_header) + data_size;
|
||||
|
||||
// total packet size must be a multiple of 'AES_BLOCK_SIZE' bytes - aes encryption works on 16-byte blocks
|
||||
packet_size = (packet_size + (AES_BLOCK_SIZE - 1)) & ~(AES_BLOCK_SIZE - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
packet_size = 1 + sizeof(t_packet_header) + data_size;
|
||||
}
|
||||
|
||||
// ******************
|
||||
// construct the packets entire header
|
||||
|
||||
if (encrypt)
|
||||
{
|
||||
memmove(key, aes_key, sizeof(key)); // fetch the encryption key
|
||||
aes_encrypt_cbc_128(enc_cbc, key, NULL); // help randomize the CBC bytes
|
||||
|
||||
// ensure the 1st byte is not zero - to indicate this packet is encrypted
|
||||
while (enc_cbc[0] == 0)
|
||||
{
|
||||
random32 = updateCRC32(random32, 0xff);
|
||||
enc_cbc[0] ^= random32;
|
||||
}
|
||||
|
||||
memmove(encrypted_packet->cbc, enc_cbc, AES_BLOCK_SIZE); // copy the AES CBC bytes into the packet
|
||||
}
|
||||
else
|
||||
unencrypted_packet->null_byte = 0; // packet is not encrypted
|
||||
|
||||
header->source_id = our_serial_number; // our serial number
|
||||
// header->destination_id = BROADCAST_ADDR; // broadcast packet
|
||||
header->destination_id = conn->serial_number; // the other modems serial number
|
||||
header->type = packet_type; // packet type
|
||||
header->tx_seq = conn->tx_sequence; // our TX sequence number
|
||||
header->rx_seq = conn->rx_sequence; // our RX sequence number
|
||||
header->data_size = data_size; // the number of user data bytes in the packet
|
||||
header->crc = 0; // the CRC of the header and user data bytes
|
||||
|
||||
// ******************
|
||||
// add the user data to the packet
|
||||
|
||||
if (data_packet)
|
||||
{ // we're adding user data to the packet
|
||||
fifoBuf_getDataPeek(&connection[connection_index].tx_fifo_buffer, data, data_size);
|
||||
|
||||
if (encrypt)
|
||||
{ // zero unused bytes
|
||||
if (data_size < max_data_size)
|
||||
memset(data + data_size, 0, max_data_size - data_size);
|
||||
}
|
||||
|
||||
conn->tx_sequence_data_size = data_size; // remember how much data we are sending in this packet
|
||||
}
|
||||
|
||||
// ******************
|
||||
// complete the packet header by adding the CRC
|
||||
|
||||
if (encrypt)
|
||||
header->crc = updateCRC32Data(0xffffffff, header, packet_size - AES_BLOCK_SIZE);
|
||||
else
|
||||
header->crc = updateCRC32Data(0xffffffff, header, packet_size - 1);
|
||||
|
||||
// ******************
|
||||
// encrypt the packet
|
||||
|
||||
if (encrypt)
|
||||
{ // encrypt the packet .. 'AES_BLOCK_SIZE' bytes at a time
|
||||
uint8_t *p = (uint8_t *)encrypted_packet;
|
||||
|
||||
// encrypt the cbc
|
||||
memmove(key, aes_key, sizeof(key)); // fetch the encryption key
|
||||
aes_encrypt_cbc_128(p, key, NULL); // encrypt block of data (the CBC bytes)
|
||||
p += AES_BLOCK_SIZE;
|
||||
|
||||
// encrypt the rest of the packet
|
||||
for (uint16_t i = AES_BLOCK_SIZE; i < packet_size; i += AES_BLOCK_SIZE)
|
||||
{
|
||||
memmove(key, aes_key, sizeof(key)); // fetch the encryption key
|
||||
aes_encrypt_cbc_128(p, key, enc_cbc); // encrypt block of data
|
||||
p += AES_BLOCK_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
// ******************
|
||||
// send the packet
|
||||
|
||||
int32_t res = rfm22_sendData(&ph_tx_buffer, packet_size, send_immediately);
|
||||
|
||||
// ******************
|
||||
|
||||
if (data_size > 0 && conn->tx_retry_counter == 0)
|
||||
conn->tx_data_speed_count += data_size * 8; // + the number of data bits we just sent .. used for calculating the transmit data rate
|
||||
|
||||
// ******************
|
||||
// debug stuff
|
||||
|
||||
#if defined(PACKET_DEBUG)
|
||||
|
||||
DEBUG_PRINTF("T-PACK ");
|
||||
switch (pack_type)
|
||||
{
|
||||
case PACKET_TYPE_NONE: DEBUG_PRINTF("none"); break;
|
||||
case PACKET_TYPE_CONNECT: DEBUG_PRINTF("connect"); break;
|
||||
case PACKET_TYPE_CONNECT_ACK: DEBUG_PRINTF("connect_ack"); break;
|
||||
case PACKET_TYPE_DISCONNECT: DEBUG_PRINTF("disconnect"); break;
|
||||
case PACKET_TYPE_DATA: DEBUG_PRINTF("data"); break;
|
||||
case PACKET_TYPE_DATA_ACK: DEBUG_PRINTF("data_ack"); break;
|
||||
case PACKET_TYPE_READY: DEBUG_PRINTF("ready"); break;
|
||||
case PACKET_TYPE_READY_ACK: DEBUG_PRINTF("ready_ack"); break;
|
||||
case PACKET_TYPE_NOTREADY: DEBUG_PRINTF("notready"); break;
|
||||
case PACKET_TYPE_NOTREADY_ACK: DEBUG_PRINTF("notready_ack"); break;
|
||||
case PACKET_TYPE_DATARATE: DEBUG_PRINTF("datarate"); break;
|
||||
case PACKET_TYPE_DATARATE_ACK: DEBUG_PRINTF("datarate_ack"); break;
|
||||
case PACKET_TYPE_PING: DEBUG_PRINTF("ping"); break;
|
||||
case PACKET_TYPE_PONG: DEBUG_PRINTF("pong"); break;
|
||||
case PACKET_TYPE_ADJUST_TX_PWR: DEBUG_PRINTF("PACKET_TYPE_ADJUST_TX_PWR"); break;
|
||||
case PACKET_TYPE_ADJUST_TX_PWR_ACK: DEBUG_PRINTF("PACKET_TYPE_ADJUST_TX_PWR_ACK"); break;
|
||||
default: DEBUG_PRINTF("UNKNOWN [%d]", pack_type); break;
|
||||
}
|
||||
DEBUG_PRINTF(" tseq:%d rseq:%d", conn->tx_sequence, conn->rx_sequence);
|
||||
DEBUG_PRINTF(" drate:%dbps", conn->tx_data_speed);
|
||||
if (data_size > 0) DEBUG_PRINTF(" data_size:%d", data_size);
|
||||
if (conn->tx_retry_counter > 0) DEBUG_PRINTF(" retry:%d", conn->tx_retry_counter);
|
||||
DEBUG_PRINTF("\r\n");
|
||||
#endif
|
||||
|
||||
// ******************
|
||||
|
||||
switch (pack_type)
|
||||
{
|
||||
case PACKET_TYPE_CONNECT:
|
||||
case PACKET_TYPE_DISCONNECT:
|
||||
case PACKET_TYPE_DATA:
|
||||
case PACKET_TYPE_READY:
|
||||
case PACKET_TYPE_NOTREADY:
|
||||
case PACKET_TYPE_DATARATE:
|
||||
case PACKET_TYPE_PING:
|
||||
case PACKET_TYPE_ADJUST_TX_PWR:
|
||||
if (conn->tx_retry_counter < 0xffff)
|
||||
conn->tx_retry_counter++;
|
||||
break;
|
||||
|
||||
case PACKET_TYPE_CONNECT_ACK:
|
||||
case PACKET_TYPE_DATA_ACK:
|
||||
case PACKET_TYPE_READY_ACK:
|
||||
case PACKET_TYPE_NOTREADY_ACK:
|
||||
case PACKET_TYPE_DATARATE_ACK:
|
||||
case PACKET_TYPE_PONG:
|
||||
case PACKET_TYPE_ADJUST_TX_PWR_ACK:
|
||||
break;
|
||||
|
||||
case PACKET_TYPE_NONE:
|
||||
break;
|
||||
}
|
||||
|
||||
return (res >= packet_size);
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
|
||||
void ph_processPacket2(bool was_encrypted, t_packet_header *header, uint8_t *data)
|
||||
{ // process the received decrypted error-free packet
|
||||
|
||||
USB_LED_TOGGLE; // TEST ONLY
|
||||
|
||||
// ***********
|
||||
|
||||
// fetch the data compressed bit
|
||||
bool compressed_data = (header->type & PACKET_TYPE_DATA_COMP_BIT) != 0;
|
||||
|
||||
// fetch the packet type
|
||||
uint8_t packet_type = header->type & PACKET_TYPE_MASK;
|
||||
|
||||
// fetch the number of data bytes in the packet
|
||||
uint16_t data_size = header->data_size;
|
||||
|
||||
// update the ramdon number
|
||||
random32 = updateCRC32(random32, 0xff);
|
||||
|
||||
// *********************
|
||||
// debug stuff
|
||||
/*
|
||||
#if defined(PACKET_DEBUG)
|
||||
if (data_size > 0)
|
||||
{
|
||||
DEBUG_PRINTF("rx packet:");
|
||||
for (uint16_t i = 0; i < data_size; i++)
|
||||
DEBUG_PRINTF(" %u", data[i]);
|
||||
DEBUG_PRINTF("\r\n");
|
||||
}
|
||||
#endif
|
||||
*/
|
||||
// ***********
|
||||
// debug stuff
|
||||
|
||||
#if defined(PACKET_DEBUG)
|
||||
DEBUG_PRINTF("R-PACK ");
|
||||
switch (packet_type)
|
||||
{
|
||||
case PACKET_TYPE_NONE: DEBUG_PRINTF("none"); break;
|
||||
case PACKET_TYPE_CONNECT: DEBUG_PRINTF("connect"); break;
|
||||
case PACKET_TYPE_CONNECT_ACK: DEBUG_PRINTF("connect_ack"); break;
|
||||
case PACKET_TYPE_DISCONNECT: DEBUG_PRINTF("disconnect"); break;
|
||||
case PACKET_TYPE_DATA: DEBUG_PRINTF("data"); break;
|
||||
case PACKET_TYPE_DATA_ACK: DEBUG_PRINTF("data_ack"); break;
|
||||
case PACKET_TYPE_READY: DEBUG_PRINTF("ready"); break;
|
||||
case PACKET_TYPE_READY_ACK: DEBUG_PRINTF("ready_ack"); break;
|
||||
case PACKET_TYPE_NOTREADY: DEBUG_PRINTF("notready"); break;
|
||||
case PACKET_TYPE_NOTREADY_ACK: DEBUG_PRINTF("notready_ack"); break;
|
||||
case PACKET_TYPE_DATARATE: DEBUG_PRINTF("datarate"); break;
|
||||
case PACKET_TYPE_DATARATE_ACK: DEBUG_PRINTF("datarate_ack"); break;
|
||||
case PACKET_TYPE_PING: DEBUG_PRINTF("ping"); break;
|
||||
case PACKET_TYPE_PONG: DEBUG_PRINTF("pong"); break;
|
||||
case PACKET_TYPE_ADJUST_TX_PWR: DEBUG_PRINTF("PACKET_TYPE_ADJUST_TX_PWR"); break;
|
||||
case PACKET_TYPE_ADJUST_TX_PWR_ACK: DEBUG_PRINTF("PACKET_TYPE_ADJUST_TX_PWR_ACK"); break;
|
||||
default: DEBUG_PRINTF("UNKNOWN [%d]", packet_type); break;
|
||||
}
|
||||
DEBUG_PRINTF(" tseq-%d rseq-%d", header->tx_seq, header->rx_seq);
|
||||
// DEBUG_PRINTF(" drate:%dbps", conn->rx_data_speed);
|
||||
if (data_size > 0) DEBUG_PRINTF(" data_size:%d", data_size);
|
||||
DEBUG_PRINTF(" %ddBm", rx_rssi_dBm);
|
||||
DEBUG_PRINTF(" %dHz", rx_afc_Hz);
|
||||
DEBUG_PRINTF("\r\n");
|
||||
#endif
|
||||
|
||||
// *********************
|
||||
|
||||
if (header->source_id == our_serial_number)
|
||||
return; // it's our own packet .. ignore it
|
||||
|
||||
if (header->destination_id == BROADCAST_ADDR)
|
||||
{ // it's a broadcast packet
|
||||
|
||||
|
||||
|
||||
// todo:
|
||||
|
||||
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (header->destination_id != our_serial_number)
|
||||
return; // the packet is not meant for us
|
||||
|
||||
// *********************
|
||||
// find out which remote connection this packet is from
|
||||
|
||||
int connection_index = 0;
|
||||
while (connection_index < PH_MAX_CONNECTIONS)
|
||||
{
|
||||
uint32_t sn = connection[connection_index].serial_number;
|
||||
if (sn != 0)
|
||||
{ // connection used
|
||||
if (header->source_id == sn)
|
||||
break; // found it
|
||||
}
|
||||
connection_index++;
|
||||
}
|
||||
|
||||
if (connection_index >= PH_MAX_CONNECTIONS)
|
||||
{ // the packet is from an unknown source ID (unknown modem)
|
||||
|
||||
if (packet_type != PACKET_TYPE_NONE)
|
||||
{ // send a disconnect packet back to them
|
||||
// ph_sendPacket(-1, was_encrypted, PACKET_TYPE_DISCONNECT, true);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
t_connection *conn = &connection[connection_index];
|
||||
|
||||
// ***********
|
||||
|
||||
conn->rx_rssi_dBm = rx_rssi_dBm; // remember the packets signal strength
|
||||
conn->rx_afc_Hz = rx_afc_Hz; // remember the packets frequency offset
|
||||
|
||||
// ***********
|
||||
// decompress the data
|
||||
|
||||
if (compressed_data && data_size > 0)
|
||||
{
|
||||
|
||||
|
||||
// todo:
|
||||
|
||||
|
||||
}
|
||||
|
||||
// ***********
|
||||
|
||||
if (packet_type == PACKET_TYPE_NONE)
|
||||
return;
|
||||
|
||||
if (packet_type == PACKET_TYPE_DISCONNECT)
|
||||
{
|
||||
conn->link_state = LINK_DISCONNECTED;
|
||||
LINK_LED_OFF;
|
||||
return;
|
||||
}
|
||||
|
||||
if (packet_type == PACKET_TYPE_CONNECT)
|
||||
{
|
||||
LINK_LED_ON;
|
||||
|
||||
// fifoBuf_init(&conn->tx_fifo_buffer, conn->tx_buffer, PH_FIFO_BUFFER_SIZE);
|
||||
// fifoBuf_init(&conn->rx_fifo_buffer, conn->rx_buffer, PH_FIFO_BUFFER_SIZE);
|
||||
|
||||
conn->tx_packet_timer = 0;
|
||||
|
||||
conn->tx_retry_counter = 0;
|
||||
conn->tx_retry_time = conn->tx_retry_time_slot_len + (random32 % conn->tx_retry_time_slots) * conn->tx_retry_time_slot_len;
|
||||
|
||||
conn->rx_sequence = header->tx_seq;
|
||||
conn->tx_sequence = 0;
|
||||
conn->tx_sequence_data_size = 0;
|
||||
|
||||
conn->data_speed_timer = 0;
|
||||
conn->tx_data_speed_count = 0;
|
||||
conn->tx_data_speed = 0;
|
||||
conn->rx_data_speed_count = 0;
|
||||
conn->rx_data_speed = 0;
|
||||
|
||||
conn->ping_time = 8000 + (random32 % 100) * 10;
|
||||
conn->fast_ping_time = 600 + (random32 % 50) * 10;
|
||||
conn->pinging = false;
|
||||
|
||||
conn->rx_not_ready_mode = false;
|
||||
|
||||
conn->ready_to_send_timer = -1;
|
||||
|
||||
conn->not_ready_timer = -1;
|
||||
|
||||
conn->link_state = LINK_CONNECTED;
|
||||
|
||||
// send an ack back
|
||||
if (ph_sendPacket(connection_index, conn->send_encrypted, PACKET_TYPE_CONNECT_ACK, true))
|
||||
{
|
||||
conn->tx_packet_timer = 0;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (packet_type == PACKET_TYPE_CONNECT_ACK)
|
||||
{
|
||||
LINK_LED_ON;
|
||||
|
||||
if (conn->link_state != LINK_CONNECTING)
|
||||
{ // reset the link
|
||||
ph_set_remote_serial_number(connection_index, conn->serial_number);
|
||||
return;
|
||||
}
|
||||
|
||||
conn->tx_packet_timer = 0;
|
||||
|
||||
conn->tx_retry_counter = 0;
|
||||
conn->tx_retry_time = conn->tx_retry_time_slot_len + (random32 % conn->tx_retry_time_slots) * conn->tx_retry_time_slot_len;
|
||||
|
||||
conn->rx_sequence = header->tx_seq;
|
||||
conn->tx_sequence = 0;
|
||||
conn->tx_sequence_data_size = 0;
|
||||
|
||||
conn->data_speed_timer = 0;
|
||||
conn->tx_data_speed_count = 0;
|
||||
conn->tx_data_speed = 0;
|
||||
conn->rx_data_speed_count = 0;
|
||||
conn->rx_data_speed = 0;
|
||||
|
||||
conn->ping_time = 8000 + (random32 % 100) * 10;
|
||||
conn->fast_ping_time = 600 + (random32 % 50) * 10;
|
||||
conn->pinging = false;
|
||||
|
||||
conn->rx_not_ready_mode = false;
|
||||
|
||||
conn->ready_to_send_timer = -1;
|
||||
|
||||
conn->not_ready_timer = -1;
|
||||
|
||||
conn->link_state = LINK_CONNECTED;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if (conn->link_state == LINK_CONNECTING)
|
||||
{ // we are trying to connect to them .. reply with a connect request packet
|
||||
if (ph_sendPacket(connection_index, conn->send_encrypted, PACKET_TYPE_CONNECT, true))
|
||||
{
|
||||
conn->tx_packet_timer = 0;
|
||||
conn->tx_retry_time = conn->tx_retry_time_slot_len * 4 + (random32 % conn->tx_retry_time_slots) * conn->tx_retry_time_slot_len * 4;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (conn->link_state != LINK_CONNECTED)
|
||||
{ // they have sent us a packet when we are not in a connected state - start a connection
|
||||
ph_startConnect(connection_index, conn->serial_number);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// check to make sure it's a wanted packet type
|
||||
switch (packet_type)
|
||||
{
|
||||
case PACKET_TYPE_DATA:
|
||||
case PACKET_TYPE_DATA_ACK:
|
||||
case PACKET_TYPE_READY:
|
||||
case PACKET_TYPE_READY_ACK:
|
||||
case PACKET_TYPE_NOTREADY:
|
||||
case PACKET_TYPE_NOTREADY_ACK:
|
||||
case PACKET_TYPE_DATARATE:
|
||||
case PACKET_TYPE_DATARATE_ACK:
|
||||
case PACKET_TYPE_PING:
|
||||
case PACKET_TYPE_PONG:
|
||||
case PACKET_TYPE_ADJUST_TX_PWR:
|
||||
case PACKET_TYPE_ADJUST_TX_PWR_ACK:
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if ((conn->tx_sequence_data_size > 0) && (header->rx_seq == (uint8_t)(conn->tx_sequence + 1)))
|
||||
{ // they received our last data packet
|
||||
|
||||
// remove the data we have sent and they have acked
|
||||
fifoBuf_removeData(&conn->tx_fifo_buffer, conn->tx_sequence_data_size);
|
||||
|
||||
conn->tx_sequence++;
|
||||
conn->tx_retry_counter = 0;
|
||||
conn->tx_sequence_data_size = 0;
|
||||
conn->not_ready_timer = -1; // stop timer
|
||||
}
|
||||
|
||||
uint16_t size = fifoBuf_getUsed(&conn->tx_fifo_buffer); // the size of data waiting to be sent
|
||||
|
||||
|
||||
|
||||
|
||||
if (packet_type == PACKET_TYPE_DATA || packet_type == PACKET_TYPE_DATA_ACK)
|
||||
{
|
||||
if (packet_type == PACKET_TYPE_DATA && header->tx_seq == conn->rx_sequence)
|
||||
{ // the packet number is what we expected
|
||||
|
||||
if (data_size > 0)
|
||||
{ // save the data
|
||||
|
||||
conn->rx_data_speed_count += data_size * 8; // + the number of data bits we just received
|
||||
|
||||
uint16_t num = fifoBuf_getFree(&conn->rx_fifo_buffer);
|
||||
if (num < data_size)
|
||||
{ // error .. we don't have enough space left in our fifo buffer to save the data .. discard it and tell them to hold off a sec
|
||||
// conn->rx_not_ready_mode = true;
|
||||
}
|
||||
else
|
||||
{ // save the received data into our fifo buffer
|
||||
fifoBuf_putData(&conn->rx_fifo_buffer, data, data_size);
|
||||
conn->rx_sequence++;
|
||||
conn->rx_not_ready_mode = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (size >= 200 || (conn->ready_to_send_timer >= 10 && size > 0) || (conn->tx_sequence_data_size > 0 && size > 0))
|
||||
{ // send data
|
||||
uint8_t pack_type = PACKET_TYPE_DATA;
|
||||
if (conn->rx_not_ready_mode)
|
||||
pack_type = PACKET_TYPE_NOTREADY;
|
||||
|
||||
if (ph_sendPacket(connection_index, conn->send_encrypted, pack_type, true))
|
||||
{
|
||||
conn->tx_packet_timer = 0;
|
||||
conn->tx_retry_time = conn->tx_retry_time_slot_len + (random32 % conn->tx_retry_time_slots) * conn->tx_retry_time_slot_len;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (packet_type == PACKET_TYPE_DATA)
|
||||
{ // send an ack back
|
||||
uint8_t pack_type = PACKET_TYPE_DATA_ACK;
|
||||
if (conn->rx_not_ready_mode)
|
||||
pack_type = PACKET_TYPE_NOTREADY_ACK;
|
||||
|
||||
if (ph_sendPacket(connection_index, conn->send_encrypted, pack_type, true))
|
||||
{
|
||||
conn->tx_packet_timer = 0;
|
||||
conn->tx_retry_time = conn->tx_retry_time_slot_len + (random32 % conn->tx_retry_time_slots) * conn->tx_retry_time_slot_len;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (packet_type == PACKET_TYPE_READY)
|
||||
{
|
||||
conn->not_ready_timer = -1; // stop timer
|
||||
|
||||
// send an ack back
|
||||
if (ph_sendPacket(connection_index, conn->send_encrypted, PACKET_TYPE_READY_ACK, true))
|
||||
{
|
||||
conn->tx_packet_timer = 0;
|
||||
conn->tx_retry_time = conn->tx_retry_time_slot_len * 4 + (random32 % conn->tx_retry_time_slots) * conn->tx_retry_time_slot_len * 4;
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (packet_type == PACKET_TYPE_READY_ACK)
|
||||
{
|
||||
conn->rx_not_ready_mode = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (packet_type == PACKET_TYPE_NOTREADY)
|
||||
{
|
||||
// conn->not_ready_timer = 0; // start timer
|
||||
|
||||
if (header->tx_seq == conn->rx_sequence)
|
||||
{ // the packet number is what we expected
|
||||
|
||||
if (data_size > 0)
|
||||
{ // save the data
|
||||
|
||||
conn->rx_data_speed_count += data_size * 8; // + the number of data bits we just received
|
||||
|
||||
uint16_t num = fifoBuf_getFree(&conn->rx_fifo_buffer);
|
||||
if (num < data_size)
|
||||
{ // error .. we don't have enough space left in our fifo buffer to save the data .. discard it and tell them to hold off a sec
|
||||
// conn->rx_not_ready_mode = true;
|
||||
}
|
||||
else
|
||||
{ // save the received data into our fifo buffer
|
||||
fifoBuf_putData(&conn->rx_fifo_buffer, data, data_size);
|
||||
conn->rx_sequence++;
|
||||
conn->rx_not_ready_mode = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// send an ack back
|
||||
if (ph_sendPacket(connection_index, conn->send_encrypted, PACKET_TYPE_NOTREADY_ACK, true))
|
||||
{
|
||||
conn->tx_packet_timer = 0;
|
||||
conn->tx_retry_time = conn->tx_retry_time_slot_len * 4 + (random32 % conn->tx_retry_time_slots) * conn->tx_retry_time_slot_len * 4;
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (packet_type == PACKET_TYPE_NOTREADY_ACK)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (packet_type == PACKET_TYPE_PING)
|
||||
{ // send a pong back
|
||||
if (ph_sendPacket(connection_index, conn->send_encrypted, PACKET_TYPE_PONG, true))
|
||||
{
|
||||
conn->tx_packet_timer = 0;
|
||||
conn->tx_retry_time = conn->tx_retry_time_slot_len + (random32 % conn->tx_retry_time_slots) * conn->tx_retry_time_slot_len;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (packet_type == PACKET_TYPE_PONG)
|
||||
{
|
||||
if (conn->pinging)
|
||||
{
|
||||
conn->pinging = false;
|
||||
conn->tx_retry_counter = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (packet_type == PACKET_TYPE_DATARATE)
|
||||
{
|
||||
// send an ack back
|
||||
if (ph_sendPacket(connection_index, conn->send_encrypted, PACKET_TYPE_DATARATE_ACK, true))
|
||||
{
|
||||
conn->tx_packet_timer = 0;
|
||||
conn->tx_retry_time = conn->tx_retry_time_slot_len + (random32 % conn->tx_retry_time_slots) * conn->tx_retry_time_slot_len;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (packet_type == PACKET_TYPE_DATARATE_ACK)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (packet_type == PACKET_TYPE_ADJUST_TX_PWR)
|
||||
{
|
||||
// send an ack back
|
||||
if (ph_sendPacket(connection_index, conn->send_encrypted, PACKET_TYPE_ADJUST_TX_PWR_ACK, true))
|
||||
{
|
||||
conn->tx_packet_timer = 0;
|
||||
conn->tx_retry_time = conn->tx_retry_time_slot_len + (random32 % conn->tx_retry_time_slots) * conn->tx_retry_time_slot_len;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (packet_type == PACKET_TYPE_ADJUST_TX_PWR_ACK)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// *********************
|
||||
}
|
||||
|
||||
void ph_processRxPacket(void)
|
||||
{
|
||||
uint32_t crc1, crc2;
|
||||
uint8_t key[AES_BLOCK_SIZE];
|
||||
register uint8_t *p;
|
||||
|
||||
// ***********
|
||||
// fetch the received packet
|
||||
|
||||
uint16_t packet_size = rfm22_receivedLength();
|
||||
if (packet_size == 0)
|
||||
return; // nothing received
|
||||
|
||||
if (packet_size > sizeof(ph_rx_buffer))
|
||||
{ // packet too big .. discard it
|
||||
rfm22_receivedDone();
|
||||
return;
|
||||
}
|
||||
|
||||
rx_rssi_dBm = rfm22_receivedRSSI(); // fetch the packets signal stength
|
||||
rx_afc_Hz = rfm22_receivedAFCHz(); // fetch the packets frequency offset
|
||||
|
||||
// copy the received packet into our own buffer
|
||||
memmove(ph_rx_buffer, rfm22_receivedPointer(), packet_size);
|
||||
|
||||
rfm22_receivedDone(); // the received packet has been saved
|
||||
|
||||
// *********************
|
||||
// if the 1st byte in the packet is not zero, then the packet is encrypted
|
||||
|
||||
bool encrypted = (ph_rx_buffer[0] != 0);
|
||||
|
||||
// ***********
|
||||
|
||||
t_encrypted_packet *encrypted_packet = (t_encrypted_packet *)&ph_rx_buffer; // point to the rx buffer
|
||||
t_unencrypted_packet *unencrypted_packet = (t_unencrypted_packet *)&ph_rx_buffer; // point to the rx buffer
|
||||
|
||||
t_packet_header *header;
|
||||
uint8_t *data;
|
||||
uint16_t min_packet_size;
|
||||
uint16_t max_data_size;
|
||||
|
||||
if (encrypted)
|
||||
{
|
||||
header = (t_packet_header *)&encrypted_packet->header;
|
||||
data = (uint8_t *)&encrypted_packet->data;
|
||||
min_packet_size = AES_BLOCK_SIZE + sizeof(t_packet_header);
|
||||
max_data_size = sizeof(encrypted_packet->data);
|
||||
}
|
||||
else
|
||||
{
|
||||
header = (t_packet_header *)&unencrypted_packet->header;
|
||||
data = (uint8_t *)&unencrypted_packet->data;
|
||||
min_packet_size = 1 + sizeof(t_packet_header);
|
||||
max_data_size = sizeof(unencrypted_packet->data);
|
||||
}
|
||||
|
||||
if (packet_size < min_packet_size)
|
||||
{ // packet too small .. discard it
|
||||
return;
|
||||
}
|
||||
|
||||
random32 = updateCRC32(random32 ^ header->crc, 0xff); // help randomize the random number
|
||||
|
||||
// *********************
|
||||
// help to randomize the tx aes cbc bytes by using the received packet
|
||||
|
||||
p = (uint8_t *)&ph_rx_buffer;
|
||||
for (uint16_t i = 0; i < packet_size; i += AES_BLOCK_SIZE)
|
||||
{
|
||||
for (int j = AES_BLOCK_SIZE - 1; j >= 0; j--)
|
||||
enc_cbc[j] ^= *p++;
|
||||
}
|
||||
|
||||
// *********************
|
||||
// check the packet size
|
||||
|
||||
if (encrypted)
|
||||
{
|
||||
if ((packet_size & (AES_BLOCK_SIZE - 1)) != 0)
|
||||
return; // packet must be a multiple of 'AES_BLOCK_SIZE' bytes in length - for the aes decryption
|
||||
}
|
||||
|
||||
// *********************
|
||||
// decrypt the packet
|
||||
|
||||
if (encrypted)
|
||||
{
|
||||
p = (uint8_t *)encrypted_packet; // point to the received packet
|
||||
|
||||
// decrypt the cbc
|
||||
memmove(key, (void *)dec_aes_key, sizeof(key)); // fetch the decryption key
|
||||
aes_decrypt_cbc_128(p, key, NULL); // decrypt the cbc bytes
|
||||
p += AES_BLOCK_SIZE;
|
||||
|
||||
// decrypt the rest of the packet
|
||||
for (uint16_t i = AES_BLOCK_SIZE; i < packet_size; i += AES_BLOCK_SIZE)
|
||||
{
|
||||
memmove(key, (void *)dec_aes_key, sizeof(key)); // fetch the decryption key
|
||||
aes_decrypt_cbc_128(p, key, (void *)encrypted_packet->cbc);
|
||||
p += AES_BLOCK_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
// *********************
|
||||
|
||||
#if defined(PACKET_DEBUG)
|
||||
DEBUG_PRINTF("rx packet: ");
|
||||
DEBUG_PRINTF("%s", encrypted ? "encrypted " : "unencrypted");
|
||||
if (encrypted)
|
||||
{
|
||||
for (int i = 0; i < AES_BLOCK_SIZE; i++)
|
||||
DEBUG_PRINTF("%02X", encrypted_packet->cbc[i]);
|
||||
}
|
||||
DEBUG_PRINTF(" %08X %08X %u %u %u %u %08X\r\n",
|
||||
header->source_id,
|
||||
header->destination_id,
|
||||
header->type,
|
||||
header->tx_seq,
|
||||
header->rx_seq,
|
||||
header->data_size,
|
||||
header->crc);
|
||||
|
||||
if (header->data_size > 0)
|
||||
{
|
||||
DEBUG_PRINTF("rx packet [%u]: ", header->data_size);
|
||||
for (int i = 0; i < header->data_size; i++)
|
||||
DEBUG_PRINTF("%02X", data[i]);
|
||||
DEBUG_PRINTF("\r\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
// *********************
|
||||
|
||||
uint32_t data_size = header->data_size;
|
||||
|
||||
if (packet_size < (min_packet_size + data_size))
|
||||
return; // packet too small
|
||||
|
||||
#if defined(PACKET_DEBUG)
|
||||
// DEBUG_PRINTF("rx packet size: %d\r\n", packet_size);
|
||||
#endif
|
||||
|
||||
// *********************
|
||||
// check the packet is error free
|
||||
|
||||
crc1 = header->crc;
|
||||
header->crc = 0;
|
||||
if (encrypted)
|
||||
crc2 = updateCRC32Data(0xffffffff, header, packet_size - AES_BLOCK_SIZE);
|
||||
else
|
||||
crc2 = updateCRC32Data(0xffffffff, header, packet_size - 1);
|
||||
if (crc1 != crc2)
|
||||
{ // corrupt packet
|
||||
#if defined(PACKET_DEBUG)
|
||||
if (encrypted)
|
||||
DEBUG_PRINTF("ENC-R-PACK corrupt %08X %08X\r\n", crc1, crc2);
|
||||
else
|
||||
DEBUG_PRINTF("R-PACK corrupt %08X %08X\r\n", crc1, crc2);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
// *********************
|
||||
// process the data
|
||||
|
||||
ph_processPacket2(encrypted, header, data);
|
||||
|
||||
// *********************
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// do all the link/packet handling stuff - request connection/disconnection, send data, acks etc
|
||||
|
||||
void ph_processLinks(int connection_index)
|
||||
{
|
||||
if (connection_index < 0 || connection_index >= PH_MAX_CONNECTIONS)
|
||||
return;
|
||||
|
||||
random32 = updateCRC32(random32, 0xff);
|
||||
|
||||
t_connection *conn = &connection[connection_index];
|
||||
|
||||
bool canTx = (!rfm22_transmitting() && rfm22_channelIsClear());// TRUE is we can transmit
|
||||
|
||||
bool timeToRetry = (rfm22_txReady() && conn->tx_packet_timer >= conn->tx_retry_time);
|
||||
|
||||
bool tomanyRetries = (conn->tx_retry_counter >= RETRY_RECONNECT_COUNT);
|
||||
|
||||
if (conn->tx_retry_counter > 3)
|
||||
conn->rx_rssi_dBm = -200;
|
||||
|
||||
switch (conn->link_state)
|
||||
{
|
||||
case LINK_DISCONNECTED:
|
||||
if (!canTx)
|
||||
{
|
||||
conn->tx_packet_timer = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!rfm22_txReady() || conn->tx_packet_timer < 60000)
|
||||
break;
|
||||
|
||||
if (our_serial_number != 0 && conn->serial_number != 0)
|
||||
{ // try to reconnect with the remote modem
|
||||
ph_startConnect(connection_index, conn->serial_number);
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case LINK_CONNECTING:
|
||||
if (!canTx)
|
||||
{
|
||||
conn->tx_packet_timer = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!timeToRetry)
|
||||
break;
|
||||
|
||||
if (ph_sendPacket(connection_index, conn->send_encrypted, PACKET_TYPE_CONNECT, false))
|
||||
{
|
||||
conn->tx_packet_timer = 0;
|
||||
conn->tx_retry_time = conn->tx_retry_time_slot_len * 4 + (random32 % conn->tx_retry_time_slots) * conn->tx_retry_time_slot_len * 4;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case LINK_CONNECTED:
|
||||
if (!canTx)
|
||||
{
|
||||
conn->tx_packet_timer = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!timeToRetry)
|
||||
break;
|
||||
|
||||
if (tomanyRetries)
|
||||
{ // reset the link if we have sent tomany retries
|
||||
ph_startConnect(connection_index, conn->serial_number);
|
||||
break;
|
||||
}
|
||||
|
||||
if (conn->pinging)
|
||||
{ // we are trying to ping them
|
||||
if (ph_sendPacket(connection_index, conn->send_encrypted, PACKET_TYPE_PING, false))
|
||||
{
|
||||
conn->tx_packet_timer = 0;
|
||||
conn->tx_retry_time = conn->tx_retry_time_slot_len * 4 + (random32 % conn->tx_retry_time_slots) * conn->tx_retry_time_slot_len * 4;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
uint16_t ping_time = conn->ping_time;
|
||||
if (fast_ping) ping_time = conn->fast_ping_time;
|
||||
if (conn->tx_packet_timer >= ping_time)
|
||||
{ // start pinging
|
||||
if (ph_sendPacket(connection_index, conn->send_encrypted, PACKET_TYPE_PING, false))
|
||||
{
|
||||
conn->ping_time = 8000 + (random32 % 100) * 10;
|
||||
conn->fast_ping_time = 600 + (random32 % 50) * 10;
|
||||
conn->tx_packet_timer = 0;
|
||||
conn->tx_retry_time = conn->tx_retry_time_slot_len * 4 + (random32 % conn->tx_retry_time_slots) * conn->tx_retry_time_slot_len * 4;
|
||||
conn->pinging = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// ***********
|
||||
// exit rx not ready mode if we have space in our rx buffer for more data
|
||||
/*
|
||||
if (conn->rx_not_ready_mode)
|
||||
{
|
||||
uint16_t size = fifoBuf_getFree(&conn->rx_fifo_buffer);
|
||||
if (size >= conn->rx_fifo_buffer.buf_size / 6)
|
||||
{ // leave 'rx not ready' mode
|
||||
if (ph_sendPacket(connection_index, conn->send_encrypted, PACKET_TYPE_READY, false))
|
||||
{
|
||||
conn->tx_packet_timer = 0;
|
||||
conn->tx_retry_time = conn->tx_retry_time_slot_len + (random32 % conn->tx_retry_time_slots) * conn->tx_retry_time_slot_len;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
// ***********
|
||||
// send data packets
|
||||
|
||||
// if (conn->not_ready_timer < 0)
|
||||
{
|
||||
uint16_t size = fifoBuf_getUsed(&conn->tx_fifo_buffer);
|
||||
|
||||
if (size == 0)
|
||||
conn->ready_to_send_timer = -1; // no data to send
|
||||
else
|
||||
if (conn->ready_to_send_timer < 0)
|
||||
conn->ready_to_send_timer = 0; // start timer
|
||||
|
||||
if (size >= 200 || (conn->ready_to_send_timer >= saved_settings.rts_time && size > 0) || (conn->tx_sequence_data_size > 0 && size > 0))
|
||||
{ // send data
|
||||
|
||||
uint8_t pack_type = PACKET_TYPE_DATA;
|
||||
if (conn->rx_not_ready_mode)
|
||||
pack_type = PACKET_TYPE_NOTREADY;
|
||||
|
||||
if (ph_sendPacket(connection_index, conn->send_encrypted, pack_type, false))
|
||||
{
|
||||
conn->tx_packet_timer = 0;
|
||||
conn->tx_retry_time = conn->tx_retry_time_slot_len + (random32 % conn->tx_retry_time_slots) * conn->tx_retry_time_slot_len;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// ***********
|
||||
|
||||
break;
|
||||
|
||||
default: // we should never end up here - maybe we should do a reboot?
|
||||
conn->link_state = LINK_DISCONNECTED;
|
||||
/*
|
||||
// disable all interrupts
|
||||
PIOS_IRQ_Disable();
|
||||
|
||||
// turn off all leds
|
||||
USB_LED_OFF;
|
||||
LINK_LED_OFF;
|
||||
RX_LED_OFF;
|
||||
TX_LED_OFF;
|
||||
|
||||
PIOS_SYS_Reset();
|
||||
|
||||
while (1);
|
||||
*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
|
||||
void ph_setFastPing(bool fast)
|
||||
{
|
||||
fast_ping = fast;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
|
||||
uint8_t ph_getCurrentLinkState(const int connection_index)
|
||||
{
|
||||
if (connection_index < 0 || connection_index >= PH_MAX_CONNECTIONS)
|
||||
return 0;
|
||||
|
||||
return connection[connection_index].link_state;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
|
||||
uint16_t ph_getRetries(const int connection_index)
|
||||
{
|
||||
if (connection_index < 0 || connection_index >= PH_MAX_CONNECTIONS)
|
||||
return 0;
|
||||
|
||||
return connection[connection_index].tx_retry_counter;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
|
||||
int16_t ph_getLastRSSI(const int connection_index)
|
||||
{
|
||||
if (connection_index < 0 || connection_index >= PH_MAX_CONNECTIONS)
|
||||
return 0;
|
||||
|
||||
return connection[connection_index].rx_rssi_dBm;
|
||||
}
|
||||
|
||||
int32_t ph_getLastAFC(const int connection_index)
|
||||
{
|
||||
if (connection_index < 0 || connection_index >= PH_MAX_CONNECTIONS)
|
||||
return 0;
|
||||
|
||||
return connection[connection_index].rx_afc_Hz;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// set/get the carrier frequency
|
||||
|
||||
void ph_setNominalCarrierFrequency(uint32_t frequency_hz)
|
||||
{
|
||||
rfm22_setNominalCarrierFrequency(frequency_hz);
|
||||
}
|
||||
|
||||
uint32_t ph_getNominalCarrierFrequency(void)
|
||||
{
|
||||
return rfm22_getNominalCarrierFrequency();
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// set/get the RF datarate
|
||||
|
||||
void ph_setDatarate(uint32_t datarate_bps)
|
||||
{
|
||||
rfm22_setDatarate(datarate_bps, TRUE);
|
||||
|
||||
uint32_t ms = 1280000ul / rfm22_getDatarate();
|
||||
if (ms < 10) ms = 10;
|
||||
else
|
||||
if (ms > 32000) ms = 32000;
|
||||
|
||||
for (int i = 0; i < PH_MAX_CONNECTIONS; i++)
|
||||
connection[i].tx_retry_time_slot_len = ms;
|
||||
}
|
||||
|
||||
uint32_t ph_getDatarate(void)
|
||||
{
|
||||
return rfm22_getDatarate();
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
|
||||
void ph_setTxPower(uint8_t tx_power)
|
||||
{
|
||||
rfm22_setTxPower(tx_power);
|
||||
}
|
||||
|
||||
uint8_t ph_getTxPower(void)
|
||||
{
|
||||
return rfm22_getTxPower();
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// set the AES encryption key
|
||||
|
||||
void ph_set_AES128_key(const void *key)
|
||||
{
|
||||
if (!key)
|
||||
return;
|
||||
|
||||
memmove(aes_key, key, sizeof(aes_key));
|
||||
|
||||
// create the AES decryption key
|
||||
aes_decrypt_key_128_create(aes_key, (void *)&dec_aes_key);
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
|
||||
int ph_set_remote_serial_number(int connection_index, uint32_t sn)
|
||||
{
|
||||
random32 = updateCRC32(random32, 0xff);
|
||||
|
||||
if (ph_startConnect(connection_index, sn) >= 0)
|
||||
{
|
||||
t_connection *conn = &connection[connection_index];
|
||||
|
||||
// wipe any user data present in the buffers
|
||||
fifoBuf_init(&conn->tx_fifo_buffer, conn->tx_buffer, PH_FIFO_BUFFER_SIZE);
|
||||
fifoBuf_init(&conn->rx_fifo_buffer, conn->rx_buffer, PH_FIFO_BUFFER_SIZE);
|
||||
|
||||
return connection_index;
|
||||
}
|
||||
|
||||
return -4;
|
||||
}
|
||||
|
||||
void ph_set_remote_encryption(int connection_index, bool enabled, const void *key)
|
||||
{
|
||||
if (connection_index < 0 || connection_index >= PH_MAX_CONNECTIONS)
|
||||
return;
|
||||
|
||||
ph_set_AES128_key(key);
|
||||
|
||||
connection[connection_index].send_encrypted = enabled;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// can be called from an interrupt if you wish.
|
||||
// call this once every ms
|
||||
|
||||
void ph_1ms_tick(void)
|
||||
{
|
||||
if (booting) return;
|
||||
|
||||
if (saved_settings.mode == MODE_NORMAL)
|
||||
{
|
||||
// help randomize the encryptor cbc bytes
|
||||
register uint32_t *cbc = (uint32_t *)&enc_cbc;
|
||||
for (int i = 0; i < sizeof(enc_cbc) / 4; i++)
|
||||
{
|
||||
random32 = updateCRC32(random32, 0xff);
|
||||
*cbc++ ^= random32;
|
||||
}
|
||||
|
||||
for (int i = 0; i < PH_MAX_CONNECTIONS; i++)
|
||||
{
|
||||
t_connection *conn = &connection[i];
|
||||
|
||||
if (conn->tx_packet_timer < 0xffff)
|
||||
conn->tx_packet_timer++;
|
||||
|
||||
if (conn->link_state == LINK_CONNECTED)
|
||||
{ // we are connected
|
||||
|
||||
if (conn->ready_to_send_timer >= 0 && conn->ready_to_send_timer < 0x7fff)
|
||||
conn->ready_to_send_timer++;
|
||||
|
||||
if (conn->not_ready_timer >= 0 && conn->not_ready_timer < 0x7fffffff)
|
||||
conn->not_ready_timer++;
|
||||
|
||||
if (conn->data_speed_timer < 0xffff)
|
||||
{
|
||||
if (++conn->data_speed_timer >= 1000)
|
||||
{ // 1 second gone by
|
||||
conn->data_speed_timer = 0;
|
||||
conn->tx_data_speed = (conn->tx_data_speed + conn->tx_data_speed_count) >> 1;
|
||||
conn->tx_data_speed_count = 0;
|
||||
conn->rx_data_speed = (conn->rx_data_speed + conn->rx_data_speed_count) >> 1;
|
||||
conn->rx_data_speed_count = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // we are not connected
|
||||
if (conn->data_speed_timer) conn->data_speed_timer = 0;
|
||||
if (conn->tx_data_speed_count) conn->tx_data_speed_count = 0;
|
||||
if (conn->tx_data_speed) conn->tx_data_speed = 0;
|
||||
if (conn->rx_data_speed_count) conn->rx_data_speed_count = 0;
|
||||
if (conn->rx_data_speed) conn->rx_data_speed = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// call this as often as possible - not from an interrupt
|
||||
|
||||
void ph_process(void)
|
||||
{
|
||||
if (booting) return;
|
||||
|
||||
if (saved_settings.mode == MODE_NORMAL)
|
||||
{
|
||||
ph_processRxPacket();
|
||||
|
||||
for (int i = 0; i < PH_MAX_CONNECTIONS; i++)
|
||||
ph_processLinks(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
|
||||
void ph_disconnectAll(void)
|
||||
{
|
||||
for (int i = 0; i < PH_MAX_CONNECTIONS; i++)
|
||||
{
|
||||
random32 = updateCRC32(random32, 0xff);
|
||||
|
||||
t_connection *conn = &connection[i];
|
||||
|
||||
conn->serial_number = 0;
|
||||
|
||||
conn->tx_sequence = 0;
|
||||
conn->tx_sequence_data_size = 0;
|
||||
|
||||
conn->rx_sequence = 0;
|
||||
|
||||
fifoBuf_init(&conn->tx_fifo_buffer, conn->tx_buffer, PH_FIFO_BUFFER_SIZE);
|
||||
fifoBuf_init(&conn->rx_fifo_buffer, conn->rx_buffer, PH_FIFO_BUFFER_SIZE);
|
||||
|
||||
conn->link_state = LINK_DISCONNECTED;
|
||||
|
||||
conn->tx_packet_timer = 0;
|
||||
|
||||
conn->tx_retry_time_slots = 5;
|
||||
conn->tx_retry_time_slot_len = 40;
|
||||
conn->tx_retry_time = conn->tx_retry_time_slot_len * 4 + (random32 % conn->tx_retry_time_slots) * conn->tx_retry_time_slot_len * 4;
|
||||
conn->tx_retry_counter = 0;
|
||||
|
||||
conn->data_speed_timer = 0;
|
||||
conn->tx_data_speed_count = 0;
|
||||
conn->tx_data_speed = 0;
|
||||
conn->rx_data_speed_count = 0;
|
||||
conn->rx_data_speed = 0;
|
||||
|
||||
conn->ping_time = 8000 + (random32 % 100) * 10;
|
||||
conn->fast_ping_time = 600 + (random32 % 50) * 10;
|
||||
conn->pinging = false;
|
||||
|
||||
conn->rx_not_ready_mode = false;
|
||||
|
||||
conn->ready_to_send_timer = -1;
|
||||
|
||||
conn->not_ready_timer = -1;
|
||||
|
||||
conn->send_encrypted = false;
|
||||
|
||||
conn->rx_rssi_dBm = -200;
|
||||
conn->rx_afc_Hz = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
|
||||
void ph_deinit(void)
|
||||
{
|
||||
ph_disconnectAll();
|
||||
}
|
||||
|
||||
void ph_init(uint32_t our_sn)
|
||||
{
|
||||
our_serial_number = our_sn; // remember our own serial number
|
||||
|
||||
fast_ping = false;
|
||||
|
||||
ph_disconnectAll();
|
||||
|
||||
// set the AES encryption key using the default AES key
|
||||
ph_set_AES128_key(default_aes_key);
|
||||
|
||||
// try too randomise the tx AES CBC bytes
|
||||
for (uint32_t j = 0, k = 0; j < 123 + (random32 & 1023); j++)
|
||||
{
|
||||
random32 = updateCRC32(random32, 0xff);
|
||||
enc_cbc[k] ^= random32 >> 3;
|
||||
if (++k >= sizeof(enc_cbc)) k = 0;
|
||||
}
|
||||
|
||||
// ******
|
||||
|
||||
rfm22_init_normal(saved_settings.min_frequency_Hz, saved_settings.max_frequency_Hz, rfm22_freqHopSize());
|
||||
|
||||
rfm22_TxDataByte_SetCallback(ph_TxDataByteCallback);
|
||||
rfm22_RxData_SetCallback(ph_RxDataCallback);
|
||||
|
||||
rfm22_setFreqCalibration(saved_settings.rf_xtal_cap);
|
||||
ph_setNominalCarrierFrequency(saved_settings.frequency_Hz);
|
||||
ph_setDatarate(saved_settings.max_rf_bandwidth);
|
||||
ph_setTxPower(saved_settings.max_tx_power);
|
||||
|
||||
ph_set_remote_encryption(0, saved_settings.aes_enable, (const void *)saved_settings.aes_key);
|
||||
ph_set_remote_serial_number(0, saved_settings.destination_id);
|
||||
|
||||
// ******
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
@ -1,112 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file pios_board.c
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief Defines board specific static initializers for hardware for the PipBee board.
|
||||
* @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
|
||||
*/
|
||||
|
||||
/* Pull in the board-specific static HW definitions.
|
||||
* Including .c files is a bit ugly but this allows all of
|
||||
* the HW definitions to be const and static to limit their
|
||||
* scope.
|
||||
*
|
||||
* NOTE: THIS IS THE ONLY PLACE THAT SHOULD EVER INCLUDE THIS FILE
|
||||
*/
|
||||
#include "board_hw_defs.c"
|
||||
|
||||
#include <pios.h>
|
||||
|
||||
#define PIOS_COM_TELEM_USB_RX_BUF_LEN 192
|
||||
#define PIOS_COM_TELEM_USB_TX_BUF_LEN 192
|
||||
|
||||
static uint8_t pios_com_telem_usb_rx_buffer[PIOS_COM_TELEM_USB_RX_BUF_LEN];
|
||||
static uint8_t pios_com_telem_usb_tx_buffer[PIOS_COM_TELEM_USB_TX_BUF_LEN];
|
||||
|
||||
#define PIOS_COM_SERIAL_RX_BUF_LEN 192
|
||||
#define PIOS_COM_SERIAL_TX_BUF_LEN 192
|
||||
|
||||
static uint8_t pios_com_serial_rx_buffer[PIOS_COM_SERIAL_RX_BUF_LEN];
|
||||
static uint8_t pios_com_serial_tx_buffer[PIOS_COM_SERIAL_TX_BUF_LEN];
|
||||
|
||||
uint32_t pios_com_serial_id;
|
||||
uint32_t pios_com_telem_usb_id;
|
||||
|
||||
/**
|
||||
* PIOS_Board_Init()
|
||||
* initializes all the core subsystems on this specific hardware
|
||||
* called from System/openpilot.c
|
||||
*/
|
||||
void PIOS_Board_Init(void) {
|
||||
// Bring up System using CMSIS functions, enables the LEDs.
|
||||
PIOS_SYS_Init();
|
||||
|
||||
// turn all the leds on
|
||||
USB_LED_ON;
|
||||
LINK_LED_ON;
|
||||
RX_LED_ON;
|
||||
TX_LED_ON;
|
||||
|
||||
// Delay system
|
||||
PIOS_DELAY_Init();
|
||||
|
||||
uint32_t pios_usart_serial_id;
|
||||
if (PIOS_USART_Init(&pios_usart_serial_id, &pios_usart_serial_cfg)) {
|
||||
PIOS_DEBUG_Assert(0);
|
||||
}
|
||||
if (PIOS_COM_Init(&pios_com_serial_id, &pios_usart_com_driver, pios_usart_serial_id,
|
||||
pios_com_serial_rx_buffer, sizeof(pios_com_serial_rx_buffer),
|
||||
pios_com_serial_tx_buffer, sizeof(pios_com_serial_tx_buffer))) {
|
||||
PIOS_DEBUG_Assert(0);
|
||||
}
|
||||
|
||||
#if defined(PIOS_INCLUDE_USB)
|
||||
/* Initialize board specific USB data */
|
||||
PIOS_USB_BOARD_DATA_Init();
|
||||
|
||||
if (PIOS_USB_DESC_HID_ONLY_Init()) {
|
||||
PIOS_Assert(0);
|
||||
}
|
||||
|
||||
uint32_t pios_usb_id;
|
||||
PIOS_USB_Init(&pios_usb_id, &pios_usb_main_cfg);
|
||||
|
||||
#if defined(PIOS_INCLUDE_USB_HID) && defined(PIOS_INCLUDE_COM)
|
||||
uint32_t pios_usb_hid_id;
|
||||
if (PIOS_USB_HID_Init(&pios_usb_hid_id, &pios_usb_hid_cfg, pios_usb_id)) {
|
||||
PIOS_Assert(0);
|
||||
}
|
||||
if (PIOS_COM_Init(&pios_com_telem_usb_id, &pios_usb_hid_com_driver, pios_usb_hid_id,
|
||||
pios_com_telem_usb_rx_buffer, sizeof(pios_com_telem_usb_rx_buffer),
|
||||
pios_com_telem_usb_tx_buffer, sizeof(pios_com_telem_usb_tx_buffer))) {
|
||||
PIOS_Assert(0);
|
||||
}
|
||||
#endif /* PIOS_INCLUDE_USB_HID && PIOS_INCLUDE_COM */
|
||||
|
||||
#endif /* PIOS_INCLUDE_USB_HID */
|
||||
|
||||
// ADC system
|
||||
// PIOS_ADC_Init();
|
||||
|
||||
// SPI link to master
|
||||
if (PIOS_SPI_Init(&pios_spi_port_id, &pios_spi_port_cfg)) {
|
||||
PIOS_DEBUG_Assert(0);
|
||||
}
|
||||
}
|
@ -1,119 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @addtogroup PIOS PIOS Core hardware abstraction layer
|
||||
* @{
|
||||
* @addtogroup PIOS_USB_BOARD Board specific USB definitions
|
||||
* @brief Board specific USB definitions
|
||||
* @{
|
||||
*
|
||||
* @file pios_usb_board_data.c
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief Board specific USB definitions
|
||||
* @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 "pios_usb_board_data.h" /* struct usb_*, USB_* */
|
||||
#include "pios_sys.h" /* PIOS_SYS_SerialNumberGet */
|
||||
#include "pios_usbhook.h" /* PIOS_USBHOOK_* */
|
||||
|
||||
static const uint8_t usb_product_id[20] = {
|
||||
sizeof(usb_product_id),
|
||||
USB_DESC_TYPE_STRING,
|
||||
'P', 0,
|
||||
'i', 0,
|
||||
'p', 0,
|
||||
'X', 0,
|
||||
't', 0,
|
||||
'r', 0,
|
||||
'e', 0,
|
||||
'm', 0,
|
||||
'e', 0,
|
||||
};
|
||||
|
||||
static uint8_t usb_serial_number[52] = {
|
||||
sizeof(usb_serial_number),
|
||||
USB_DESC_TYPE_STRING,
|
||||
0, 0,
|
||||
0, 0,
|
||||
0, 0,
|
||||
0, 0,
|
||||
0, 0,
|
||||
0, 0,
|
||||
0, 0,
|
||||
0, 0,
|
||||
0, 0,
|
||||
0, 0,
|
||||
0, 0,
|
||||
0, 0,
|
||||
0, 0,
|
||||
0, 0,
|
||||
0, 0,
|
||||
0, 0,
|
||||
0, 0,
|
||||
0, 0,
|
||||
0, 0,
|
||||
0, 0,
|
||||
0, 0,
|
||||
0, 0,
|
||||
0, 0,
|
||||
0, 0,
|
||||
0, 0
|
||||
};
|
||||
|
||||
static const struct usb_string_langid usb_lang_id = {
|
||||
.bLength = sizeof(usb_lang_id),
|
||||
.bDescriptorType = USB_DESC_TYPE_STRING,
|
||||
.bLangID = htousbs(USB_LANGID_ENGLISH_UK),
|
||||
};
|
||||
|
||||
static const uint8_t usb_vendor_id[28] = {
|
||||
sizeof(usb_vendor_id),
|
||||
USB_DESC_TYPE_STRING,
|
||||
'o', 0,
|
||||
'p', 0,
|
||||
'e', 0,
|
||||
'n', 0,
|
||||
'p', 0,
|
||||
'i', 0,
|
||||
'l', 0,
|
||||
'o', 0,
|
||||
't', 0,
|
||||
'.', 0,
|
||||
'o', 0,
|
||||
'r', 0,
|
||||
'g', 0
|
||||
};
|
||||
|
||||
int32_t PIOS_USB_BOARD_DATA_Init(void)
|
||||
{
|
||||
/* Load device serial number into serial number string */
|
||||
uint8_t sn[25];
|
||||
PIOS_SYS_SerialNumberGet((char *)sn);
|
||||
for (uint8_t i = 0; sn[i] != '\0' && (2 * i) < usb_serial_number[0]; i++) {
|
||||
usb_serial_number[2 + 2 * i] = sn[i];
|
||||
}
|
||||
|
||||
PIOS_USBHOOK_RegisterString(USB_STRING_DESC_PRODUCT, (uint8_t *)&usb_product_id, sizeof(usb_product_id));
|
||||
PIOS_USBHOOK_RegisterString(USB_STRING_DESC_SERIAL, (uint8_t *)&usb_serial_number, sizeof(usb_serial_number));
|
||||
|
||||
PIOS_USBHOOK_RegisterString(USB_STRING_DESC_LANG, (uint8_t *)&usb_lang_id, sizeof(usb_lang_id));
|
||||
PIOS_USBHOOK_RegisterString(USB_STRING_DESC_VENDOR, (uint8_t *)&usb_vendor_id, sizeof(usb_vendor_id));
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,631 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file ppm.c
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief Sends or Receives the ppm values to/from the remote unit
|
||||
* @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> // memmove
|
||||
|
||||
#include "main.h"
|
||||
#include "rfm22b.h"
|
||||
#include "saved_settings.h"
|
||||
#include "ppm.h"
|
||||
|
||||
#if defined(PIOS_COM_DEBUG)
|
||||
#define PPM_DEBUG
|
||||
#endif
|
||||
|
||||
// *************************************************************
|
||||
|
||||
#define PPM_OUT_FRAME_PERIOD_US 20000 // microseconds
|
||||
#define PPM_OUT_HIGH_PULSE_US 480 // microseconds
|
||||
#define PPM_OUT_MIN_CHANNEL_PULSE_US 850 // microseconds
|
||||
#define PPM_OUT_MAX_CHANNEL_PULSE_US 2200 // microseconds
|
||||
|
||||
#define PPM_IN_MIN_SYNC_PULSE_US 7000 // microseconds .. Pip's 6-chan TX goes down to 8.8ms
|
||||
#define PPM_IN_MIN_CHANNEL_PULSE_US 750 // microseconds
|
||||
#define PPM_IN_MAX_CHANNEL_PULSE_US 2400 // microseconds
|
||||
|
||||
// *************************************************************
|
||||
|
||||
uint8_t ppm_mode;
|
||||
|
||||
volatile bool ppm_initialising = true;
|
||||
|
||||
volatile uint32_t ppm_In_PrevFrames = 0;
|
||||
volatile uint32_t ppm_In_LastValidFrameTimer = 0;
|
||||
volatile uint32_t ppm_In_Frames = 0;
|
||||
volatile uint32_t ppm_In_ErrorFrames = 0;
|
||||
volatile uint8_t ppm_In_NoisyChannelCounter = 0;
|
||||
volatile int8_t ppm_In_ChannelsDetected = 0;
|
||||
volatile int8_t ppm_In_ChannelPulseIndex = -1;
|
||||
volatile int32_t ppm_In_PreviousValue = -1;
|
||||
volatile uint32_t ppm_In_PulseWidth = 0;
|
||||
volatile uint32_t ppm_In_ChannelPulseWidthNew[PIOS_PPM_MAX_CHANNELS];
|
||||
volatile uint32_t ppm_In_ChannelPulseWidth[PIOS_PPM_MAX_CHANNELS];
|
||||
|
||||
volatile uint16_t ppm_Out_ChannelPulseWidth[PIOS_PPM_MAX_CHANNELS];
|
||||
volatile uint32_t ppm_Out_SyncPulseWidth = PPM_OUT_FRAME_PERIOD_US;
|
||||
volatile int8_t ppm_Out_ChannelPulseIndex = -1;
|
||||
volatile uint8_t ppm_Out_ChannelsUsed = 0;
|
||||
|
||||
// *************************************************************
|
||||
|
||||
// Initialise the PPM INPUT
|
||||
void ppm_In_Init(void)
|
||||
{
|
||||
TIM_ICInitTypeDef TIM_ICInitStructure;
|
||||
|
||||
// disable the timer
|
||||
TIM_Cmd(PIOS_PPM_TIM, DISABLE);
|
||||
|
||||
ppm_In_PrevFrames = 0;
|
||||
ppm_In_NoisyChannelCounter = 0;
|
||||
ppm_In_LastValidFrameTimer = 0;
|
||||
ppm_In_Frames = 0;
|
||||
ppm_In_ErrorFrames = 0;
|
||||
ppm_In_ChannelsDetected = 0;
|
||||
ppm_In_ChannelPulseIndex = -1;
|
||||
ppm_In_PreviousValue = -1;
|
||||
ppm_In_PulseWidth = 0;
|
||||
|
||||
for (int i = 0; i < PIOS_PPM_MAX_CHANNELS; i++)
|
||||
{
|
||||
ppm_In_ChannelPulseWidthNew[i] = 0;
|
||||
ppm_In_ChannelPulseWidth[i] = 0;
|
||||
}
|
||||
|
||||
// Enable timer clock
|
||||
PIOS_PPM_TIMER_EN_RCC_FUNC;
|
||||
|
||||
// Enable timer interrupts
|
||||
NVIC_InitTypeDef NVIC_InitStructure;
|
||||
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID;
|
||||
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
|
||||
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
|
||||
NVIC_InitStructure.NVIC_IRQChannel = PIOS_PPM_TIM_IRQ;
|
||||
NVIC_Init(&NVIC_InitStructure);
|
||||
|
||||
// Init PPM IN pin
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
GPIO_StructInit(&GPIO_InitStructure);
|
||||
GPIO_InitStructure.GPIO_Pin = PPM_IN_PIN;
|
||||
GPIO_InitStructure.GPIO_Mode = PPM_IN_MODE;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
GPIO_Init(PPM_IN_PORT, &GPIO_InitStructure);
|
||||
|
||||
// remap the pin to switch it to timer mode
|
||||
if (PIOS_PPM_TIM == TIM2)
|
||||
{
|
||||
// GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2, ENABLE);
|
||||
GPIO_PinRemapConfig(GPIO_PartialRemap2_TIM2, ENABLE);
|
||||
// GPIO_PinRemapConfig(GPIO_FullRemap_TIM2, ENABLE);
|
||||
}
|
||||
|
||||
// Configure timer for input capture
|
||||
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
|
||||
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
|
||||
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
|
||||
TIM_ICInitStructure.TIM_ICFilter = 15; // 0 to 15
|
||||
TIM_ICInitStructure.TIM_Channel = PIOS_PPM_IN_TIM_CHANNEL;
|
||||
TIM_ICInit(PIOS_PPM_TIM_PORT, &TIM_ICInitStructure);
|
||||
|
||||
// Configure timer clocks
|
||||
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
|
||||
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
|
||||
TIM_TimeBaseStructure.TIM_Period = 25000 - 1; // 25ms - can be anything you like now really - up to 65536us
|
||||
TIM_TimeBaseStructure.TIM_Prescaler = (PIOS_MASTER_CLOCK / 1000000) - 1;
|
||||
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
|
||||
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
|
||||
TIM_InternalClockConfig(PIOS_PPM_TIM_PORT);
|
||||
TIM_TimeBaseInit(PIOS_PPM_TIM_PORT, &TIM_TimeBaseStructure);
|
||||
|
||||
// Enable the Capture Compare and Update Interrupts
|
||||
TIM_ITConfig(PIOS_PPM_TIM_PORT, PIOS_PPM_IN_TIM_CCR | TIM_IT_Update, ENABLE);
|
||||
|
||||
// Clear TIMER Capture compare and update interrupt pending bits
|
||||
TIM_ClearITPendingBit(PIOS_PPM_TIM_PORT, PIOS_PPM_IN_TIM_CCR | TIM_IT_Update);
|
||||
|
||||
// Enable timer
|
||||
TIM_Cmd(PIOS_PPM_TIM, ENABLE);
|
||||
|
||||
// Setup local variable which stays in this scope
|
||||
// Doing this here and using a local variable saves doing it in the ISR
|
||||
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
|
||||
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
|
||||
TIM_ICInitStructure.TIM_ICFilter = 0x0;
|
||||
|
||||
#ifdef PPM_DEBUG
|
||||
DEBUG_PRINTF("ppm_in: initialised\r\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
// TIMER capture/compare/update interrupt
|
||||
void PIOS_PPM_IN_CC_IRQ(void)
|
||||
{
|
||||
uint16_t new_value = 0;
|
||||
uint32_t period = (uint32_t)PIOS_PPM_TIM->ARR + 1;
|
||||
|
||||
if (booting || ppm_initialising)
|
||||
{ // clear the interrupts
|
||||
TIM_ClearITPendingBit(PIOS_PPM_TIM_PORT, PIOS_PPM_IN_TIM_CCR | TIM_IT_Update);
|
||||
return;
|
||||
}
|
||||
|
||||
// determine the interrupt source(s)
|
||||
bool update_int = TIM_GetITStatus(PIOS_PPM_TIM_PORT, TIM_IT_Update) == SET; // timer/counter overflow occured
|
||||
bool capture_int = TIM_GetITStatus(PIOS_PPM_TIM_PORT, PIOS_PPM_IN_TIM_CCR) == SET; // PPM input capture
|
||||
|
||||
if (capture_int)
|
||||
new_value = PIOS_PPM_IN_TIM_GETCAP_FUNC(PIOS_PPM_TIM_PORT);
|
||||
|
||||
// clear the interrupts
|
||||
TIM_ClearITPendingBit(PIOS_PPM_TIM_PORT, PIOS_PPM_IN_TIM_CCR | TIM_IT_Update);
|
||||
|
||||
// ********
|
||||
|
||||
uint32_t ticks = 0;
|
||||
if (update_int)
|
||||
{ // timer/counter overflowed
|
||||
|
||||
if (ppm_In_PreviousValue >= 0)
|
||||
ticks = (period - ppm_In_PreviousValue) + new_value;
|
||||
else
|
||||
{
|
||||
ticks = period;
|
||||
if (capture_int) ticks += new_value;
|
||||
}
|
||||
ppm_In_PreviousValue = -1;
|
||||
}
|
||||
else
|
||||
if (capture_int)
|
||||
{
|
||||
if (ppm_In_PreviousValue >= 0)
|
||||
ticks = new_value - ppm_In_PreviousValue;
|
||||
else
|
||||
ticks += new_value;
|
||||
}
|
||||
|
||||
ppm_In_PulseWidth += ticks;
|
||||
if (ppm_In_PulseWidth > 0x7fffffff)
|
||||
ppm_In_PulseWidth = 0x7fffffff; // prevent overflows
|
||||
|
||||
ppm_In_LastValidFrameTimer += ticks;
|
||||
if (ppm_In_LastValidFrameTimer > 0x7fffffff)
|
||||
ppm_In_LastValidFrameTimer = 0x7fffffff; // prevent overflows
|
||||
|
||||
if (capture_int)
|
||||
ppm_In_PreviousValue = new_value;
|
||||
|
||||
// ********
|
||||
|
||||
#ifdef PPM_DEBUG
|
||||
// DEBUG_PRINTF("ppm_in:");
|
||||
// if (update_int) DEBUG_PRINTF(" update");
|
||||
// if (capture_int) DEBUG_PRINTF(" capture");
|
||||
// DEBUG_PRINTF(" %u %u\r\n", ppm_In_LastValidFrameTimer, ppm_In_PulseWidth);
|
||||
#endif
|
||||
|
||||
if (ppm_In_LastValidFrameTimer >= 200000 && ppm_In_Frames > 0)
|
||||
{ // we haven't seen a valid PPM frame for at least 200ms
|
||||
for (int i = 0; i < PIOS_PPM_MAX_CHANNELS; i++)
|
||||
ppm_In_ChannelPulseWidth[i] = 0;
|
||||
ppm_In_Frames = 0;
|
||||
ppm_In_ErrorFrames = 0;
|
||||
}
|
||||
|
||||
if (ppm_In_ChannelPulseIndex < 0 || ppm_In_PulseWidth > PPM_IN_MAX_CHANNEL_PULSE_US)
|
||||
{ // we are looking for a SYNC pulse, or we are receiving one
|
||||
|
||||
if (ppm_In_ChannelPulseIndex >= 0)
|
||||
{ // it's either the start of a sync pulse or a noisy channel .. assume it's the end of a PPM frame
|
||||
|
||||
if (ppm_In_ChannelPulseIndex > 0)
|
||||
{
|
||||
if (ppm_In_Frames < 0xffffffff)
|
||||
ppm_In_Frames++; // update frame counter
|
||||
|
||||
#ifdef PPM_DEBUG
|
||||
// DEBUG_PRINTF("ppm_in: %u %u\r\n", ppm_In_ChannelsDetected, ppm_In_ChannelPulseIndex);
|
||||
#endif
|
||||
|
||||
if (ppm_In_ChannelsDetected > 0 &&
|
||||
ppm_In_ChannelsDetected == ppm_In_ChannelPulseIndex &&
|
||||
ppm_In_NoisyChannelCounter <= 2)
|
||||
{ // detected same number of channels as in previous PPM frame .. save the new channel PWM values
|
||||
#ifdef PPM_DEBUG
|
||||
// DEBUG_PRINTF("ppm_in: %u channels detected\r\n", ppm_In_ChannelPulseIndex);
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < PIOS_PPM_MAX_CHANNELS; i++)
|
||||
ppm_In_ChannelPulseWidth[i] = ppm_In_ChannelPulseWidthNew[i];
|
||||
|
||||
ppm_In_LastValidFrameTimer = 0; // reset timer
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((ppm_In_ChannelsDetected > 0 && ppm_In_ChannelsDetected != ppm_In_ChannelPulseIndex) ||
|
||||
ppm_In_NoisyChannelCounter >= 2)
|
||||
{
|
||||
if (ppm_In_ErrorFrames < 0xffffffff)
|
||||
ppm_In_ErrorFrames++;
|
||||
}
|
||||
}
|
||||
ppm_In_ChannelsDetected = ppm_In_ChannelPulseIndex; // the number of channels we found in this frame
|
||||
}
|
||||
|
||||
ppm_In_ChannelPulseIndex = -1; // back to looking for a SYNC pulse
|
||||
}
|
||||
|
||||
if (ppm_In_PulseWidth >= PPM_IN_MIN_SYNC_PULSE_US)
|
||||
{ // SYNC pulse found
|
||||
ppm_In_NoisyChannelCounter = 0; // reset noisy channel detector
|
||||
ppm_In_ChannelPulseIndex = 0; // start of PPM frame
|
||||
}
|
||||
}
|
||||
else
|
||||
if (capture_int)
|
||||
{ // CHANNEL pulse
|
||||
|
||||
if (ppm_In_PulseWidth < PPM_IN_MIN_CHANNEL_PULSE_US)
|
||||
{ // bad/noisy channel pulse .. reset state to wait for next SYNC pulse
|
||||
ppm_In_ChannelPulseIndex = -1;
|
||||
|
||||
if (ppm_In_ErrorFrames < 0xffffffff)
|
||||
ppm_In_ErrorFrames++;
|
||||
}
|
||||
else
|
||||
{ // pulse width is within the accepted tolerance range for a channel
|
||||
if (ppm_In_ChannelPulseIndex < PIOS_PPM_MAX_CHANNELS)
|
||||
{
|
||||
if (ppm_In_ChannelPulseWidthNew[ppm_In_ChannelPulseIndex] > 0)
|
||||
{
|
||||
int32_t difference = (int32_t)ppm_In_PulseWidth - ppm_In_ChannelPulseWidthNew[ppm_In_ChannelPulseIndex];
|
||||
if (abs(difference) >= 600)
|
||||
ppm_In_NoisyChannelCounter++; // possibly a noisy channel - or an RC switch was moved
|
||||
}
|
||||
|
||||
ppm_In_ChannelPulseWidthNew[ppm_In_ChannelPulseIndex] = ppm_In_PulseWidth; // save it
|
||||
}
|
||||
|
||||
if (ppm_In_ChannelPulseIndex < 127)
|
||||
ppm_In_ChannelPulseIndex++; // next channel
|
||||
}
|
||||
}
|
||||
|
||||
if (capture_int)
|
||||
ppm_In_PulseWidth = 0;
|
||||
|
||||
// ********
|
||||
}
|
||||
|
||||
uint32_t ppm_In_NewFrame(void)
|
||||
{
|
||||
if (booting || ppm_initialising)
|
||||
return 0;
|
||||
|
||||
if (ppm_In_Frames >= 2 && ppm_In_Frames != ppm_In_PrevFrames)
|
||||
{ // we have a new PPM frame
|
||||
ppm_In_PrevFrames = ppm_In_Frames;
|
||||
return ppm_In_PrevFrames;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t ppm_In_GetChannelPulseWidth(uint8_t channel)
|
||||
{
|
||||
if (booting || ppm_initialising)
|
||||
return -1;
|
||||
|
||||
// Return error if channel not available
|
||||
if (channel >= PIOS_PPM_MAX_CHANNELS || channel >= ppm_In_ChannelsDetected)
|
||||
return -2;
|
||||
|
||||
return ppm_In_ChannelPulseWidth[channel]; // return channel pulse width
|
||||
}
|
||||
|
||||
// *************************************************************
|
||||
|
||||
// Initialise the PPM INPUT
|
||||
void ppm_Out_Init(void)
|
||||
{
|
||||
// disable the timer
|
||||
TIM_Cmd(PIOS_PPM_TIM, DISABLE);
|
||||
|
||||
ppm_Out_SyncPulseWidth = PPM_OUT_FRAME_PERIOD_US;
|
||||
ppm_Out_ChannelPulseIndex = -1;
|
||||
ppm_Out_ChannelsUsed = 0;
|
||||
for (int i = 0; i < PIOS_PPM_MAX_CHANNELS; i++)
|
||||
ppm_Out_ChannelPulseWidth[i] = 1000;
|
||||
// ppm_Out_ChannelPulseWidth[i] = 1000 + i * 100; // TEST ONLY
|
||||
|
||||
// ppm_Out_ChannelsUsed = 5; // TEST ONLY
|
||||
|
||||
// Enable timer clock
|
||||
PIOS_PPM_TIMER_EN_RCC_FUNC;
|
||||
|
||||
// Init PPM OUT pin
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
GPIO_StructInit(&GPIO_InitStructure);
|
||||
GPIO_InitStructure.GPIO_Pin = PPM_OUT_PIN;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
|
||||
GPIO_Init(PPM_OUT_PORT, &GPIO_InitStructure);
|
||||
|
||||
// remap the pin to switch it to timer mode
|
||||
// GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2, ENABLE);
|
||||
// GPIO_PinRemapConfig(GPIO_PartialRemap2_TIM2, ENABLE);
|
||||
GPIO_PinRemapConfig(GPIO_FullRemap_TIM2, ENABLE);
|
||||
|
||||
// Enable timer interrupt
|
||||
NVIC_InitTypeDef NVIC_InitStructure;
|
||||
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID;
|
||||
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
|
||||
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
|
||||
NVIC_InitStructure.NVIC_IRQChannel = PIOS_PPM_TIM_IRQ;
|
||||
NVIC_Init(&NVIC_InitStructure);
|
||||
|
||||
// Time base configuration
|
||||
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
|
||||
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
|
||||
TIM_TimeBaseStructure.TIM_Period = ppm_Out_SyncPulseWidth - 1;
|
||||
TIM_TimeBaseStructure.TIM_Prescaler = (PIOS_MASTER_CLOCK / 1000000) - 1;
|
||||
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
|
||||
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
|
||||
TIM_InternalClockConfig(PIOS_PPM_TIM_PORT);
|
||||
TIM_TimeBaseInit(PIOS_PPM_TIM_PORT, &TIM_TimeBaseStructure);
|
||||
|
||||
// Set up for output compare function
|
||||
TIM_OCInitTypeDef TIM_OCInitStructure;
|
||||
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
|
||||
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
|
||||
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;
|
||||
TIM_OCInitStructure.TIM_Pulse = PPM_OUT_HIGH_PULSE_US;
|
||||
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
|
||||
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCPolarity_High;
|
||||
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
|
||||
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;
|
||||
TIM_OC3Init(PIOS_PPM_TIM, &TIM_OCInitStructure);
|
||||
TIM_OC3PreloadConfig(PIOS_PPM_TIM, TIM_OCPreload_Enable);
|
||||
|
||||
TIM_ARRPreloadConfig(PIOS_PPM_TIM, ENABLE);
|
||||
|
||||
// TIMER Main Output Enable
|
||||
TIM_CtrlPWMOutputs(PIOS_PPM_TIM, ENABLE);
|
||||
|
||||
// TIM IT enable
|
||||
TIM_ITConfig(PIOS_PPM_TIM, PIOS_PPM_OUT_TIM_CCR, ENABLE);
|
||||
|
||||
// Clear TIMER Capture compare interrupt pending bit
|
||||
TIM_ClearITPendingBit(PIOS_PPM_TIM_PORT, PIOS_PPM_IN_TIM_CCR);
|
||||
|
||||
// Enable timer
|
||||
TIM_Cmd(PIOS_PPM_TIM, ENABLE);
|
||||
|
||||
#ifdef PPM_DEBUG
|
||||
DEBUG_PRINTF("ppm_out: initialised\r\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
// TIMER capture/compare interrupt
|
||||
void PIOS_PPM_OUT_CC_IRQ(void)
|
||||
{
|
||||
// clear the interrupt
|
||||
TIM_ClearITPendingBit(PIOS_PPM_TIM_PORT, PIOS_PPM_OUT_TIM_CCR);
|
||||
|
||||
if (booting || ppm_initialising)
|
||||
return;
|
||||
|
||||
// *************************
|
||||
// update the TIMER period (channel pulse width)
|
||||
|
||||
if (ppm_Out_ChannelPulseIndex < 0)
|
||||
{ // SYNC PULSE
|
||||
TIM_SetAutoreload(PIOS_PPM_TIM, ppm_Out_SyncPulseWidth - 1); // sync pulse length
|
||||
ppm_Out_SyncPulseWidth = PPM_OUT_FRAME_PERIOD_US; // reset sync period
|
||||
|
||||
if (ppm_Out_ChannelsUsed > 0)
|
||||
ppm_Out_ChannelPulseIndex = 0; // onto channel-1
|
||||
}
|
||||
else
|
||||
{ // CHANNEL PULSE
|
||||
uint16_t pulse_width = ppm_Out_ChannelPulseWidth[ppm_Out_ChannelPulseIndex];
|
||||
if (pulse_width < PPM_OUT_MIN_CHANNEL_PULSE_US) pulse_width = PPM_OUT_MIN_CHANNEL_PULSE_US;
|
||||
else
|
||||
if (pulse_width > PPM_OUT_MAX_CHANNEL_PULSE_US) pulse_width = PPM_OUT_MAX_CHANNEL_PULSE_US;
|
||||
|
||||
TIM_SetAutoreload(PIOS_PPM_TIM, pulse_width - 1); // channel pulse width
|
||||
ppm_Out_SyncPulseWidth -= pulse_width; // maintain constant PPM frame period
|
||||
|
||||
// TEST ONLY
|
||||
// pulse_width += 4;
|
||||
// if (pulse_width > 2000) pulse_width = 1000;
|
||||
// ppm_Out_ChannelPulseWidth[ppm_Out_ChannelPulseIndex] = pulse_width;
|
||||
|
||||
ppm_Out_ChannelPulseIndex++;
|
||||
if (ppm_Out_ChannelPulseIndex >= ppm_Out_ChannelsUsed || ppm_Out_ChannelPulseIndex >= PIOS_PPM_MAX_CHANNELS)
|
||||
ppm_Out_ChannelPulseIndex = -1; // back to SYNC pulse
|
||||
}
|
||||
|
||||
// *************************
|
||||
}
|
||||
|
||||
// *************************************************************
|
||||
// TIMER capture/compare interrupt
|
||||
|
||||
void PIOS_PPM_CC_IRQ_FUNC(void)
|
||||
{
|
||||
if (ppm_mode == MODE_PPM_TX)
|
||||
PIOS_PPM_IN_CC_IRQ();
|
||||
else
|
||||
if (ppm_mode == MODE_PPM_RX)
|
||||
PIOS_PPM_OUT_CC_IRQ();
|
||||
else
|
||||
TIM_ClearITPendingBit(PIOS_PPM_TIM_PORT, PIOS_PPM_IN_TIM_CCR | TIM_IT_Update); // clear the interrupts
|
||||
}
|
||||
|
||||
// *************************************************************
|
||||
// can be called from an interrupt if you wish
|
||||
// call this once every ms
|
||||
|
||||
void ppm_1ms_tick(void)
|
||||
{
|
||||
if (booting || ppm_initialising)
|
||||
return;
|
||||
|
||||
|
||||
}
|
||||
|
||||
// *************************************************************
|
||||
// return a byte for the tx packet transmission.
|
||||
//
|
||||
// return value < 0 if no more bytes available, otherwise return byte to be sent
|
||||
|
||||
int16_t ppm_TxDataByteCallback(void)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
// *************************************************************
|
||||
// we are being given a block of received bytes
|
||||
//
|
||||
// return TRUE to continue current packet receive, otherwise return FALSE to halt current packet reception
|
||||
|
||||
bool ppm_RxDataCallback(void *data, uint8_t len)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// *************************************************************
|
||||
// call this from the main loop (not interrupt) as often as possible
|
||||
|
||||
void ppm_process(void)
|
||||
{
|
||||
if (booting || ppm_initialising)
|
||||
return;
|
||||
|
||||
if (ppm_mode == MODE_PPM_TX)
|
||||
{
|
||||
if (ppm_In_NewFrame() > 0)
|
||||
{ // we have a new PPM frame to send
|
||||
|
||||
#ifdef PPM_DEBUG
|
||||
DEBUG_PRINTF("ppm_in: %5u %5u ..", ppm_In_Frames, ppm_In_ErrorFrames);
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < PIOS_PPM_MAX_CHANNELS && i < ppm_In_ChannelsDetected; i++)
|
||||
{
|
||||
// int32_t pwm = ppm_In_GetChannelPulseWidth(i);
|
||||
|
||||
#ifdef PPM_DEBUG
|
||||
DEBUG_PRINTF(" %4u", ppm_In_GetChannelPulseWidth(i));
|
||||
#endif
|
||||
|
||||
// TODO:
|
||||
}
|
||||
|
||||
#ifdef PPM_DEBUG
|
||||
DEBUG_PRINTF("\r\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
if (ppm_mode == MODE_PPM_RX)
|
||||
{
|
||||
// TODO:
|
||||
}
|
||||
}
|
||||
|
||||
// *************************************************************
|
||||
|
||||
void ppm_deinit(void)
|
||||
{
|
||||
ppm_initialising = true;
|
||||
|
||||
ppm_mode = 0;
|
||||
|
||||
// disable timer
|
||||
TIM_Cmd(PIOS_PPM_TIM, DISABLE);
|
||||
|
||||
// Disable timer clock
|
||||
PIOS_PPM_TIMER_DIS_RCC_FUNC;
|
||||
|
||||
// TIM IT disable
|
||||
TIM_ITConfig(PIOS_PPM_TIM, PIOS_PPM_IN_TIM_CCR | PIOS_PPM_OUT_TIM_CCR, DISABLE);
|
||||
|
||||
// TIMER Main Output Disable
|
||||
TIM_CtrlPWMOutputs(PIOS_PPM_TIM, DISABLE);
|
||||
|
||||
// un-remap the PPM pins
|
||||
GPIO_PinRemapConfig(GPIO_FullRemap_TIM2, DISABLE);
|
||||
|
||||
// Disable timer interrupt
|
||||
NVIC_InitTypeDef NVIC_InitStructure;
|
||||
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID;
|
||||
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
|
||||
NVIC_InitStructure.NVIC_IRQChannelCmd = DISABLE;
|
||||
NVIC_InitStructure.NVIC_IRQChannel = PIOS_PPM_TIM_IRQ;
|
||||
NVIC_Init(&NVIC_InitStructure);
|
||||
|
||||
ppm_initialising = false;
|
||||
}
|
||||
|
||||
void ppm_init(uint32_t our_sn)
|
||||
{
|
||||
ppm_deinit();
|
||||
|
||||
ppm_initialising = true;
|
||||
|
||||
ppm_mode = saved_settings.mode;
|
||||
|
||||
#if defined(PPM_DEBUG)
|
||||
DEBUG_PRINTF("\r\nPPM init\r\n");
|
||||
#endif
|
||||
|
||||
if (ppm_mode == MODE_PPM_TX)
|
||||
{
|
||||
ppm_In_Init();
|
||||
rfm22_init_tx_stream(saved_settings.min_frequency_Hz, saved_settings.max_frequency_Hz);
|
||||
}
|
||||
else
|
||||
if (ppm_mode == MODE_PPM_RX)
|
||||
{
|
||||
ppm_Out_Init();
|
||||
rfm22_init_rx_stream(saved_settings.min_frequency_Hz, saved_settings.max_frequency_Hz);
|
||||
}
|
||||
|
||||
rfm22_TxDataByte_SetCallback(ppm_TxDataByteCallback);
|
||||
rfm22_RxData_SetCallback(ppm_RxDataCallback);
|
||||
|
||||
rfm22_setFreqCalibration(saved_settings.rf_xtal_cap);
|
||||
rfm22_setNominalCarrierFrequency(saved_settings.frequency_Hz);
|
||||
rfm22_setDatarate(saved_settings.max_rf_bandwidth, FALSE);
|
||||
rfm22_setTxPower(saved_settings.max_tx_power);
|
||||
|
||||
if (ppm_mode == MODE_PPM_TX)
|
||||
rfm22_setTxStream();
|
||||
|
||||
ppm_initialising = false;
|
||||
}
|
||||
|
||||
// *************************************************************
|
@ -1,500 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @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 <string.h>
|
||||
|
||||
#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
|
||||
|
||||
uint32_t api_previous_com_port = 0;
|
||||
|
||||
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.
|
||||
uint32_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 = 0;
|
||||
|
||||
api_rx_buffer_wr = 0;
|
||||
|
||||
api_tx_buffer_wr = 0;
|
||||
|
||||
api_rx_timer = 0;
|
||||
api_tx_timer = 0;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
@ -1,40 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @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
|
@ -1,2491 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file rfm22b.c
|
||||
* @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
|
||||
*/
|
||||
|
||||
// *****************************************************************
|
||||
// RFM22B hardware layer
|
||||
//
|
||||
// This module uses the RFM22B's internal packet handling hardware to encapsulate our own packet data.
|
||||
//
|
||||
// The RFM22B internal hardware packet handler configuration is as follows ..
|
||||
//
|
||||
// 4-byte (32-bit) preamble .. alternating 0's & 1's
|
||||
// 4-byte (32-bit) sync
|
||||
// 1-byte packet length (number of data bytes to follow)
|
||||
// 0 to 255 user data bytes
|
||||
//
|
||||
// Our own packet data will also contain it's own header and 32-bit CRC as a single 16-bit CRC is not sufficient for wireless comms.
|
||||
//
|
||||
// *****************************************************************
|
||||
|
||||
#include <string.h> // memmove
|
||||
|
||||
#include "stm32f10x.h"
|
||||
#include "main.h"
|
||||
#include "stopwatch.h"
|
||||
#include "gpio_in.h"
|
||||
#include "rfm22b.h"
|
||||
|
||||
#if defined(PIOS_COM_DEBUG)
|
||||
// #define RFM22_DEBUG
|
||||
// #define RFM22_INT_TIMEOUT_DEBUG
|
||||
#endif
|
||||
|
||||
// *****************************************************************
|
||||
// forward delarations
|
||||
|
||||
#if defined(RFM22_EXT_INT_USE)
|
||||
void rfm22_processInt(void);
|
||||
#endif
|
||||
|
||||
// ************************************
|
||||
// this is too adjust the RF module so that it is on frequency
|
||||
|
||||
#define OSC_LOAD_CAP 0x7F // cap = 12.5pf .. default
|
||||
|
||||
#define OSC_LOAD_CAP_1 0x7D // board 1
|
||||
#define OSC_LOAD_CAP_2 0x7B // board 2
|
||||
#define OSC_LOAD_CAP_3 0x7E // board 3
|
||||
#define OSC_LOAD_CAP_4 0x7F // board 4
|
||||
|
||||
// ************************************
|
||||
|
||||
#define TX_TEST_MODE_TIMELIMIT_MS 30000 // TX test modes time limit (in ms)
|
||||
|
||||
//#define TX_PREAMBLE_NIBBLES 8 // 7 to 511 (number of nibbles)
|
||||
//#define RX_PREAMBLE_NIBBLES 5 // 5 to 31 (number of nibbles)
|
||||
#define TX_PREAMBLE_NIBBLES 12 // 7 to 511 (number of nibbles)
|
||||
#define RX_PREAMBLE_NIBBLES 6 // 5 to 31 (number of nibbles)
|
||||
|
||||
#define FIFO_SIZE 64 // the size of the rf modules internal FIFO buffers
|
||||
|
||||
#define TX_FIFO_HI_WATERMARK 62 // 0-63
|
||||
#define TX_FIFO_LO_WATERMARK 32 // 0-63
|
||||
|
||||
#define RX_FIFO_HI_WATERMARK 32 // 0-63
|
||||
|
||||
#define PREAMBLE_BYTE 0x55 // preamble byte (preceeds SYNC_BYTE's)
|
||||
|
||||
#define SYNC_BYTE_1 0x2D // RF sync bytes (32-bit in all)
|
||||
#define SYNC_BYTE_2 0xD4 //
|
||||
#define SYNC_BYTE_3 0x4B //
|
||||
#define SYNC_BYTE_4 0x59 //
|
||||
|
||||
// ************************************
|
||||
// the default TX power level
|
||||
|
||||
#define RFM22_DEFAULT_RF_POWER RFM22_tx_pwr_txpow_0 // +1dBm ... 1.25mW
|
||||
//#define RFM22_DEFAULT_RF_POWER RFM22_tx_pwr_txpow_1 // +2dBm ... 1.6mW
|
||||
//#define RFM22_DEFAULT_RF_POWER RFM22_tx_pwr_txpow_2 // +5dBm ... 3.16mW
|
||||
//#define RFM22_DEFAULT_RF_POWER RFM22_tx_pwr_txpow_3 // +8dBm ... 6.3mW
|
||||
//#define RFM22_DEFAULT_RF_POWER RFM22_tx_pwr_txpow_4 // +11dBm .. 12.6mW
|
||||
//#define RFM22_DEFAULT_RF_POWER RFM22_tx_pwr_txpow_5 // +14dBm .. 25mW
|
||||
//#define RFM22_DEFAULT_RF_POWER RFM22_tx_pwr_txpow_6 // +17dBm .. 50mW
|
||||
//#define RFM22_DEFAULT_RF_POWER RFM22_tx_pwr_txpow_7 // +20dBm .. 100mW
|
||||
|
||||
// ************************************
|
||||
// the default RF datarate
|
||||
|
||||
//#define RFM22_DEFAULT_RF_DATARATE 500 // 500 bits per sec
|
||||
//#define RFM22_DEFAULT_RF_DATARATE 1000 // 1k bits per sec
|
||||
//#define RFM22_DEFAULT_RF_DATARATE 2000 // 2k bits per sec
|
||||
//#define RFM22_DEFAULT_RF_DATARATE 4000 // 4k bits per sec
|
||||
//#define RFM22_DEFAULT_RF_DATARATE 8000 // 8k bits per sec
|
||||
//#define RFM22_DEFAULT_RF_DATARATE 9600 // 9.6k bits per sec
|
||||
//#define RFM22_DEFAULT_RF_DATARATE 16000 // 16k bits per sec
|
||||
//#define RFM22_DEFAULT_RF_DATARATE 19200 // 19k2 bits per sec
|
||||
//#define RFM22_DEFAULT_RF_DATARATE 24000 // 24k bits per sec
|
||||
//#define RFM22_DEFAULT_RF_DATARATE 32000 // 32k bits per sec
|
||||
//#define RFM22_DEFAULT_RF_DATARATE 64000 // 64k bits per sec
|
||||
#define RFM22_DEFAULT_RF_DATARATE 128000 // 128k bits per sec
|
||||
//#define RFM22_DEFAULT_RF_DATARATE 192000 // 192k bits per sec
|
||||
//#define RFM22_DEFAULT_RF_DATARATE 256000 // 256k bits per sec .. NOT YET WORKING
|
||||
|
||||
// ************************************
|
||||
|
||||
#define RFM22_DEFAULT_SS_RF_DATARATE 125 // 128bps
|
||||
|
||||
// ************************************
|
||||
// Normal data streaming
|
||||
// GFSK modulation
|
||||
// no manchester encoding
|
||||
// data whitening
|
||||
// FIFO mode
|
||||
// 5-nibble rx preamble length detection
|
||||
// 10-nibble tx preamble length
|
||||
// AFC enabled
|
||||
|
||||
#define LOOKUP_SIZE 14
|
||||
|
||||
// xtal 10 ppm, 434MHz
|
||||
const uint32_t data_rate[LOOKUP_SIZE] = { 500, 1000, 2000, 4000, 8000, 9600, 16000, 19200, 24000, 32000, 64000, 128000, 192000, 256000};
|
||||
const uint8_t modulation_index[LOOKUP_SIZE] = { 16, 8, 4, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
|
||||
const uint32_t freq_deviation[LOOKUP_SIZE] = { 4000, 4000, 4000, 4000, 4000, 4800, 8000, 9600, 12000, 16000, 32000, 64000, 96000, 128000};
|
||||
const uint32_t rx_bandwidth[LOOKUP_SIZE] = { 17500, 17500, 17500, 17500, 17500, 19400, 32200, 38600, 51200, 64100, 137900, 269300, 420200, 518800};
|
||||
const int8_t est_rx_sens_dBm[LOOKUP_SIZE] = { -118, -118, -117, -116, -115, -115, -112, -112, -110, -109, -106, -103, -101, -100}; // estimated receiver sensitivity for BER = 1E-3
|
||||
|
||||
const uint8_t reg_1C[LOOKUP_SIZE] = { 0x37, 0x37, 0x37, 0x37, 0x3A, 0x3B, 0x26, 0x28, 0x2E, 0x16, 0x07, 0x83, 0x8A, 0x8C}; // rfm22_if_filter_bandwidth
|
||||
|
||||
const uint8_t reg_1D[LOOKUP_SIZE] = { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44}; // rfm22_afc_loop_gearshift_override
|
||||
const uint8_t reg_1E[LOOKUP_SIZE] = { 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x02}; // rfm22_afc_timing_control
|
||||
|
||||
const uint8_t reg_1F[LOOKUP_SIZE] = { 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03}; // rfm22_clk_recovery_gearshift_override
|
||||
const uint8_t reg_20[LOOKUP_SIZE] = { 0xE8, 0xF4, 0xFA, 0x70, 0x3F, 0x34, 0x3F, 0x34, 0x2A, 0x3F, 0x3F, 0x5E, 0x3F, 0x2F}; // rfm22_clk_recovery_oversampling_ratio
|
||||
const uint8_t reg_21[LOOKUP_SIZE] = { 0x60, 0x20, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x03, 0x02, 0x02, 0x01, 0x02, 0x02}; // rfm22_clk_recovery_offset2
|
||||
const uint8_t reg_22[LOOKUP_SIZE] = { 0x20, 0x41, 0x83, 0x06, 0x0C, 0x75, 0x0C, 0x75, 0x12, 0x0C, 0x0C, 0x5D, 0x0C, 0xBB}; // rfm22_clk_recovery_offset1
|
||||
const uint8_t reg_23[LOOKUP_SIZE] = { 0xC5, 0x89, 0x12, 0x25, 0x4A, 0x25, 0x4A, 0x25, 0x6F, 0x4A, 0x4A, 0x86, 0x4A, 0x0D}; // rfm22_clk_recovery_offset0
|
||||
const uint8_t reg_24[LOOKUP_SIZE] = { 0x00, 0x00, 0x00, 0x02, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x05, 0x07, 0x07}; // rfm22_clk_recovery_timing_loop_gain1
|
||||
const uint8_t reg_25[LOOKUP_SIZE] = { 0x0A, 0x23, 0x85, 0x0E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x74, 0xFF, 0xFF}; // rfm22_clk_recovery_timing_loop_gain0
|
||||
|
||||
const uint8_t reg_2A[LOOKUP_SIZE] = { 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0D, 0x0D, 0x0E, 0x12, 0x17, 0x31, 0x50, 0x50, 0x50}; // rfm22_afc_limiter .. AFC_pull_in_range = ±AFCLimiter[7:0] x (hbsel+1) x 625 Hz
|
||||
|
||||
const uint8_t reg_6E[LOOKUP_SIZE] = { 0x04, 0x08, 0x10, 0x20, 0x41, 0x4E, 0x83, 0x9D, 0xC4, 0x08, 0x10, 0x20, 0x31, 0x41}; // rfm22_tx_data_rate1
|
||||
const uint8_t reg_6F[LOOKUP_SIZE] = { 0x19, 0x31, 0x62, 0xC5, 0x89, 0xA5, 0x12, 0x49, 0x9C, 0x31, 0x62, 0xC5, 0x27, 0x89}; // rfm22_tx_data_rate0
|
||||
|
||||
const uint8_t reg_70[LOOKUP_SIZE] = { 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D}; // rfm22_modulation_mode_control1
|
||||
const uint8_t reg_71[LOOKUP_SIZE] = { 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23}; // rfm22_modulation_mode_control2
|
||||
|
||||
const uint8_t reg_72[LOOKUP_SIZE] = { 0x06, 0x06, 0x06, 0x06, 0x06, 0x08, 0x0D, 0x0F, 0x13, 0x1A, 0x33, 0x66, 0x9A, 0xCD}; // rfm22_frequency_deviation
|
||||
|
||||
// ************************************
|
||||
// Scan Spectrum settings
|
||||
// GFSK modulation
|
||||
// no manchester encoding
|
||||
// data whitening
|
||||
// FIFO mode
|
||||
// 5-nibble rx preamble length detection
|
||||
// 10-nibble tx preamble length
|
||||
// AFC disabled
|
||||
|
||||
#define SS_LOOKUP_SIZE 2
|
||||
|
||||
// xtal 1 ppm, 434MHz
|
||||
const uint32_t ss_rx_bandwidth[SS_LOOKUP_SIZE] = { 2600, 10600};
|
||||
|
||||
const uint8_t ss_reg_1C[SS_LOOKUP_SIZE] = { 0x51, 0x32}; // rfm22_if_filter_bandwidth
|
||||
const uint8_t ss_reg_1D[SS_LOOKUP_SIZE] = { 0x00, 0x00}; // rfm22_afc_loop_gearshift_override
|
||||
|
||||
const uint8_t ss_reg_20[SS_LOOKUP_SIZE] = { 0xE8, 0x38}; // rfm22_clk_recovery_oversampling_ratio
|
||||
const uint8_t ss_reg_21[SS_LOOKUP_SIZE] = { 0x60, 0x02}; // rfm22_clk_recovery_offset2
|
||||
const uint8_t ss_reg_22[SS_LOOKUP_SIZE] = { 0x20, 0x4D}; // rfm22_clk_recovery_offset1
|
||||
const uint8_t ss_reg_23[SS_LOOKUP_SIZE] = { 0xC5, 0xD3}; // rfm22_clk_recovery_offset0
|
||||
const uint8_t ss_reg_24[SS_LOOKUP_SIZE] = { 0x00, 0x07}; // rfm22_clk_recovery_timing_loop_gain1
|
||||
const uint8_t ss_reg_25[SS_LOOKUP_SIZE] = { 0x0F, 0xFF}; // rfm22_clk_recovery_timing_loop_gain0
|
||||
|
||||
const uint8_t ss_reg_2A[SS_LOOKUP_SIZE] = { 0xFF, 0xFF}; // rfm22_afc_limiter .. AFC_pull_in_range = ±AFCLimiter[7:0] x (hbsel+1) x 625 Hz
|
||||
|
||||
const uint8_t ss_reg_70[SS_LOOKUP_SIZE] = { 0x24, 0x2D}; // rfm22_modulation_mode_control1
|
||||
const uint8_t ss_reg_71[SS_LOOKUP_SIZE] = { 0x2B, 0x23}; // rfm22_modulation_mode_control2
|
||||
|
||||
// ************************************
|
||||
|
||||
volatile bool initialized = false;
|
||||
|
||||
#if defined(RFM22_EXT_INT_USE)
|
||||
volatile bool exec_using_spi; // set this if you want to access the SPI bus outside of the interrupt
|
||||
volatile bool inside_ext_int; // this is set whenever we are inside the interrupt
|
||||
#endif
|
||||
|
||||
uint8_t device_type; // the RF chips device ID number
|
||||
uint8_t device_version; // the RF chips revision number
|
||||
|
||||
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
|
||||
|
||||
uint32_t carrier_datarate_bps; // the RF data rate we are using
|
||||
|
||||
uint32_t rf_bandwidth_used; // the RF bandwidth currently used
|
||||
uint32_t ss_rf_bandwidth_used; // the RF bandwidth currently used
|
||||
|
||||
uint8_t hbsel; // holds the hbsel (1 or 2)
|
||||
float frequency_step_size; // holds the minimum frequency step size
|
||||
|
||||
uint8_t frequency_hop_channel; // current frequency hop channel
|
||||
|
||||
uint8_t frequency_hop_step_size_reg; //
|
||||
|
||||
uint8_t adc_config; // holds the adc config reg value
|
||||
|
||||
volatile uint8_t device_status; // device status register
|
||||
volatile uint8_t int_status1; // interrupt status register 1
|
||||
volatile uint8_t int_status2; // interrupt status register 2
|
||||
volatile uint8_t ezmac_status; // ezmac status register
|
||||
|
||||
volatile int16_t afc_correction; // afc correction reading
|
||||
volatile int32_t afc_correction_Hz; // afc correction reading (in Hz)
|
||||
|
||||
volatile int16_t temperature_reg; // the temperature sensor reading
|
||||
|
||||
#if defined(RFM22_DEBUG)
|
||||
volatile uint8_t prev_device_status; // just for debugging
|
||||
volatile uint8_t prev_int_status1; // " "
|
||||
volatile uint8_t prev_int_status2; // " "
|
||||
volatile uint8_t prev_ezmac_status; // " "
|
||||
|
||||
bool debug_outputted;
|
||||
#endif
|
||||
|
||||
volatile uint8_t osc_load_cap; // xtal frequency calibration value
|
||||
|
||||
volatile uint8_t rssi; // the current RSSI (register value)
|
||||
volatile int16_t rssi_dBm; // dBm value
|
||||
|
||||
uint8_t tx_power; // the transmit power to use for data transmissions
|
||||
volatile uint8_t tx_pwr; // the tx power register read back
|
||||
|
||||
volatile uint8_t rx_buffer_current; // the current receive buffer in use (double buffer)
|
||||
volatile uint8_t rx_buffer[256] __attribute__ ((aligned(4))); // the receive buffer .. received packet data is saved here
|
||||
volatile uint16_t rx_buffer_wr; // the receive buffer write index
|
||||
|
||||
volatile uint8_t rx_packet_buf[256] __attribute__ ((aligned(4))); // the received packet
|
||||
volatile uint16_t rx_packet_wr; // the receive packet write index
|
||||
volatile int16_t rx_packet_start_rssi_dBm; //
|
||||
volatile int32_t rx_packet_start_afc_Hz; //
|
||||
volatile int16_t rx_packet_rssi_dBm; // the received packet signal strength
|
||||
volatile int32_t rx_packet_afc_Hz; // the receive packet frequency offset
|
||||
|
||||
volatile uint8_t *tx_data_addr; // the address of the data we send in the transmitted packets
|
||||
volatile uint16_t tx_data_rd; // the tx data read index
|
||||
volatile uint16_t tx_data_wr; // the tx data write index
|
||||
|
||||
//volatile uint8_t tx_fifo[FIFO_SIZE]; //
|
||||
|
||||
volatile uint8_t rx_fifo[FIFO_SIZE]; //
|
||||
volatile uint8_t rx_fifo_wr; //
|
||||
|
||||
int lookup_index;
|
||||
int ss_lookup_index;
|
||||
|
||||
volatile bool power_on_reset; // set if the RF module has reset itself
|
||||
|
||||
volatile uint16_t rfm22_int_timer; // used to detect if the RF module stops responding. thus act accordingly if it does stop responding.
|
||||
volatile uint16_t rfm22_int_time_outs; // counter
|
||||
volatile uint16_t prev_rfm22_int_time_outs; //
|
||||
|
||||
uint32_t clear_channel_count = (TX_PREAMBLE_NIBBLES + 4) * 2; // minimum clear channel time before allowing transmit
|
||||
|
||||
uint16_t timeout_ms = 20000; //
|
||||
uint16_t timeout_sync_ms = 3; //
|
||||
uint16_t timeout_data_ms = 20; //
|
||||
|
||||
t_rfm22_TxDataByteCallback tx_data_byte_callback_function = NULL;
|
||||
t_rfm22_RxDataCallback rx_data_callback_function = NULL;
|
||||
|
||||
// ************************************
|
||||
// SPI read/write
|
||||
|
||||
void rfm22_startBurstWrite(uint8_t addr)
|
||||
{
|
||||
// wait 1us .. so we don't toggle the CS line to quickly
|
||||
PIOS_DELAY_WaituS(1);
|
||||
|
||||
// chip select line LOW
|
||||
PIOS_SPI_RC_PinSet(RFM22_PIOS_SPI, 0);
|
||||
|
||||
PIOS_SPI_TransferByte(RFM22_PIOS_SPI, 0x80 | addr);
|
||||
}
|
||||
|
||||
inline void rfm22_burstWrite(uint8_t data)
|
||||
{
|
||||
PIOS_SPI_TransferByte(RFM22_PIOS_SPI, data);
|
||||
}
|
||||
|
||||
void rfm22_endBurstWrite(void)
|
||||
{
|
||||
// chip select line HIGH
|
||||
PIOS_SPI_RC_PinSet(RFM22_PIOS_SPI, 1);
|
||||
}
|
||||
|
||||
void rfm22_write(uint8_t addr, uint8_t data)
|
||||
{
|
||||
// wait 1us .. so we don't toggle the CS line to quickly
|
||||
PIOS_DELAY_WaituS(1);
|
||||
|
||||
// chip select line LOW
|
||||
PIOS_SPI_RC_PinSet(RFM22_PIOS_SPI, 0);
|
||||
|
||||
PIOS_SPI_TransferByte(RFM22_PIOS_SPI, 0x80 | addr);
|
||||
PIOS_SPI_TransferByte(RFM22_PIOS_SPI, data);
|
||||
|
||||
// chip select line HIGH
|
||||
PIOS_SPI_RC_PinSet(RFM22_PIOS_SPI, 1);
|
||||
}
|
||||
|
||||
void rfm22_startBurstRead(uint8_t addr)
|
||||
{
|
||||
// wait 1us .. so we don't toggle the CS line to quickly
|
||||
PIOS_DELAY_WaituS(1);
|
||||
|
||||
// chip select line LOW
|
||||
PIOS_SPI_RC_PinSet(RFM22_PIOS_SPI, 0);
|
||||
|
||||
PIOS_SPI_TransferByte(RFM22_PIOS_SPI, addr & 0x7f);
|
||||
}
|
||||
|
||||
inline uint8_t rfm22_burstRead(void)
|
||||
{
|
||||
return PIOS_SPI_TransferByte(RFM22_PIOS_SPI, 0xff);
|
||||
}
|
||||
|
||||
void rfm22_endBurstRead(void)
|
||||
{
|
||||
// chip select line HIGH
|
||||
PIOS_SPI_RC_PinSet(RFM22_PIOS_SPI, 1);
|
||||
}
|
||||
|
||||
uint8_t rfm22_read(uint8_t addr)
|
||||
{
|
||||
uint8_t rdata;
|
||||
|
||||
// wait 1us .. so we don't toggle the CS line to quickly
|
||||
PIOS_DELAY_WaituS(1);
|
||||
|
||||
// chip select line LOW
|
||||
PIOS_SPI_RC_PinSet(RFM22_PIOS_SPI, 0);
|
||||
|
||||
PIOS_SPI_TransferByte(RFM22_PIOS_SPI, addr & 0x7f);
|
||||
rdata = PIOS_SPI_TransferByte(RFM22_PIOS_SPI, 0xff);
|
||||
|
||||
// chip select line HIGH
|
||||
PIOS_SPI_RC_PinSet(RFM22_PIOS_SPI, 1);
|
||||
|
||||
return rdata;
|
||||
}
|
||||
|
||||
// ************************************
|
||||
// external interrupt
|
||||
|
||||
#if defined(RFM22_EXT_INT_USE)
|
||||
|
||||
void RFM22_EXT_INT_FUNC(void)
|
||||
{
|
||||
inside_ext_int = TRUE;
|
||||
|
||||
if (EXTI_GetITStatus(RFM22_EXT_INT_LINE) != RESET)
|
||||
{
|
||||
// Clear the EXTI line pending bit
|
||||
EXTI_ClearITPendingBit(RFM22_EXT_INT_LINE);
|
||||
|
||||
// USB_LED_TOGGLE; // TEST ONLY
|
||||
|
||||
if (!booting && !exec_using_spi)
|
||||
{
|
||||
// while (!GPIO_IN(RF_INT_PIN) && !exec_using_spi)
|
||||
{ // stay here until the interrupt line returns HIGH
|
||||
rfm22_processInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inside_ext_int = FALSE;
|
||||
}
|
||||
|
||||
void rfm22_disableExtInt(void)
|
||||
{
|
||||
// Configure the external interrupt
|
||||
GPIO_EXTILineConfig(RFM22_EXT_INT_PORT_SOURCE, RFM22_EXT_INT_PIN_SOURCE);
|
||||
EXTI_InitTypeDef EXTI_InitStructure;
|
||||
EXTI_InitStructure.EXTI_Line = RFM22_EXT_INT_LINE;
|
||||
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
|
||||
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
|
||||
EXTI_InitStructure.EXTI_LineCmd = DISABLE;
|
||||
EXTI_Init(&EXTI_InitStructure);
|
||||
|
||||
EXTI_ClearFlag(RFM22_EXT_INT_LINE);
|
||||
}
|
||||
|
||||
void rfm22_enableExtInt(void)
|
||||
{
|
||||
// Configure the external interrupt
|
||||
GPIO_EXTILineConfig(RFM22_EXT_INT_PORT_SOURCE, RFM22_EXT_INT_PIN_SOURCE);
|
||||
EXTI_InitTypeDef EXTI_InitStructure;
|
||||
EXTI_InitStructure.EXTI_Line = RFM22_EXT_INT_LINE;
|
||||
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
|
||||
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
|
||||
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
|
||||
EXTI_Init(&EXTI_InitStructure);
|
||||
|
||||
EXTI_ClearFlag(RFM22_EXT_INT_LINE);
|
||||
|
||||
// Enable and set the external interrupt
|
||||
NVIC_InitTypeDef NVIC_InitStructure;
|
||||
NVIC_InitStructure.NVIC_IRQChannel = RFM22_EXT_INT_IRQn;
|
||||
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = RFM22_EXT_INT_PRIORITY;
|
||||
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
|
||||
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
|
||||
NVIC_Init(&NVIC_InitStructure);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************
|
||||
// set/get the current tx power setting
|
||||
|
||||
void rfm22_setTxPower(uint8_t tx_pwr)
|
||||
{
|
||||
switch (tx_pwr)
|
||||
{
|
||||
case 0: tx_power = RFM22_tx_pwr_txpow_0; break; // +1dBm ... 1.25mW
|
||||
case 1: tx_power = RFM22_tx_pwr_txpow_1; break; // +2dBm ... 1.6mW
|
||||
case 2: tx_power = RFM22_tx_pwr_txpow_2; break; // +5dBm ... 3.16mW
|
||||
case 3: tx_power = RFM22_tx_pwr_txpow_3; break; // +8dBm ... 6.3mW
|
||||
case 4: tx_power = RFM22_tx_pwr_txpow_4; break; // +11dBm .. 12.6mW
|
||||
case 5: tx_power = RFM22_tx_pwr_txpow_5; break; // +14dBm .. 25mW
|
||||
case 6: tx_power = RFM22_tx_pwr_txpow_6; break; // +17dBm .. 50mW
|
||||
case 7: tx_power = RFM22_tx_pwr_txpow_7; break; // +20dBm .. 100mW
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t rfm22_getTxPower(void)
|
||||
{
|
||||
return tx_power;
|
||||
}
|
||||
|
||||
// ************************************
|
||||
|
||||
uint32_t rfm22_minFrequency(void)
|
||||
{
|
||||
return lower_carrier_frequency_limit_Hz;
|
||||
}
|
||||
uint32_t rfm22_maxFrequency(void)
|
||||
{
|
||||
return upper_carrier_frequency_limit_Hz;
|
||||
}
|
||||
|
||||
void rfm22_setNominalCarrierFrequency(uint32_t frequency_hz)
|
||||
{
|
||||
|
||||
#if defined(RFM22_EXT_INT_USE)
|
||||
exec_using_spi = TRUE;
|
||||
#endif
|
||||
|
||||
// *******
|
||||
|
||||
if (frequency_hz < lower_carrier_frequency_limit_Hz) frequency_hz = lower_carrier_frequency_limit_Hz;
|
||||
else
|
||||
if (frequency_hz > upper_carrier_frequency_limit_Hz) frequency_hz = upper_carrier_frequency_limit_Hz;
|
||||
|
||||
if (frequency_hz < 480000000)
|
||||
hbsel = 1;
|
||||
else
|
||||
hbsel = 2;
|
||||
uint8_t fb = (uint8_t)(frequency_hz / (10000000 * hbsel));
|
||||
|
||||
uint32_t fc = (uint32_t)(frequency_hz - (10000000 * hbsel * fb));
|
||||
|
||||
fc = (fc * 64u) / (10000ul * hbsel);
|
||||
fb -= 24;
|
||||
|
||||
// carrier_frequency_hz = frequency_hz;
|
||||
carrier_frequency_hz = ((uint32_t)fb + 24 + ((float)fc / 64000)) * 10000000 * hbsel;
|
||||
|
||||
if (hbsel > 1)
|
||||
fb |= RFM22_fbs_hbsel;
|
||||
|
||||
fb |= RFM22_fbs_sbse; // is this the RX LO polarity?
|
||||
|
||||
frequency_step_size = 156.25f * hbsel;
|
||||
|
||||
rfm22_write(RFM22_frequency_hopping_channel_select, frequency_hop_channel); // frequency hopping channel (0-255)
|
||||
|
||||
rfm22_write(RFM22_frequency_offset1, 0); // no frequency offset
|
||||
rfm22_write(RFM22_frequency_offset2, 0); // no frequency offset
|
||||
|
||||
rfm22_write(RFM22_frequency_band_select, fb); // set the carrier frequency
|
||||
rfm22_write(RFM22_nominal_carrier_frequency1, fc >> 8); // " "
|
||||
rfm22_write(RFM22_nominal_carrier_frequency0, fc & 0xff); // " "
|
||||
|
||||
// *******
|
||||
|
||||
#if defined(RFM22_DEBUG)
|
||||
DEBUG_PRINTF("rf setFreq: %u\r\n", carrier_frequency_hz);
|
||||
// DEBUG_PRINTF("rf setFreq frequency_step_size: %0.2f\r\n", frequency_step_size);
|
||||
#endif
|
||||
|
||||
#if defined(RFM22_EXT_INT_USE)
|
||||
exec_using_spi = FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t 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;
|
||||
rfm22_write(RFM22_frequency_hopping_channel_select, frequency_hop_channel);
|
||||
}
|
||||
|
||||
uint8_t rfm22_freqHopChannel(void)
|
||||
{ // return the current frequency hopping channel
|
||||
return frequency_hop_channel;
|
||||
}
|
||||
|
||||
uint32_t rfm22_freqHopSize(void)
|
||||
{ // return the frequency hopping step size
|
||||
return ((uint32_t)frequency_hop_step_size_reg * 10000);
|
||||
}
|
||||
|
||||
// ************************************
|
||||
// radio datarate about 19200 Baud
|
||||
// radio frequency deviation 45kHz
|
||||
// radio receiver bandwidth 67kHz.
|
||||
//
|
||||
// Carson's rule:
|
||||
// The signal bandwidth is about 2(Delta-f + fm) ..
|
||||
//
|
||||
// Delta-f = frequency deviation
|
||||
// fm = maximum frequency of the signal
|
||||
//
|
||||
// This gives 2(45 + 9.6) = 109.2kHz.
|
||||
|
||||
void rfm22_setDatarate(uint32_t datarate_bps, bool data_whitening)
|
||||
{
|
||||
|
||||
#if defined(RFM22_EXT_INT_USE)
|
||||
exec_using_spi = TRUE;
|
||||
#endif
|
||||
// *******
|
||||
|
||||
lookup_index = 0;
|
||||
while (lookup_index < (LOOKUP_SIZE - 1) && data_rate[lookup_index] < datarate_bps)
|
||||
lookup_index++;
|
||||
|
||||
carrier_datarate_bps = datarate_bps = data_rate[lookup_index];
|
||||
|
||||
rf_bandwidth_used = rx_bandwidth[lookup_index];
|
||||
|
||||
// ********************************
|
||||
|
||||
#if defined(RFM22_DEBUG)
|
||||
uint32_t frequency_deviation = freq_deviation[lookup_index]; // Hz
|
||||
uint32_t modulation_bandwidth = datarate_bps + (2 * frequency_deviation);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
rfm22_write(0x1C, reg_1C[lookup_index]); // rfm22_if_filter_bandwidth
|
||||
|
||||
rfm22_write(0x1D, reg_1D[lookup_index]); // rfm22_afc_loop_gearshift_override
|
||||
rfm22_write(0x1E, reg_1E[lookup_index]); // RFM22_afc_timing_control
|
||||
|
||||
rfm22_write(0x1F, reg_1F[lookup_index]); // RFM22_clk_recovery_gearshift_override
|
||||
rfm22_write(0x20, reg_20[lookup_index]); // rfm22_clk_recovery_oversampling_ratio
|
||||
rfm22_write(0x21, reg_21[lookup_index]); // rfm22_clk_recovery_offset2
|
||||
rfm22_write(0x22, reg_22[lookup_index]); // rfm22_clk_recovery_offset1
|
||||
rfm22_write(0x23, reg_23[lookup_index]); // rfm22_clk_recovery_offset0
|
||||
rfm22_write(0x24, reg_24[lookup_index]); // rfm22_clk_recovery_timing_loop_gain1
|
||||
rfm22_write(0x25, reg_25[lookup_index]); // rfm22_clk_recovery_timing_loop_gain0
|
||||
|
||||
rfm22_write(0x2A, reg_2A[lookup_index]); // rfm22_afc_limiter
|
||||
|
||||
if (carrier_datarate_bps < 100000)
|
||||
rfm22_write(0x58, 0x80); // rfm22_chargepump_current_trimming_override
|
||||
else
|
||||
rfm22_write(0x58, 0xC0); // rfm22_chargepump_current_trimming_override
|
||||
|
||||
rfm22_write(0x6E, reg_6E[lookup_index]); // rfm22_tx_data_rate1
|
||||
rfm22_write(0x6F, reg_6F[lookup_index]); // rfm22_tx_data_rate0
|
||||
|
||||
// Enable data whitening
|
||||
// uint8_t txdtrtscale_bit = rfm22_read(RFM22_modulation_mode_control1) & RFM22_mmc1_txdtrtscale;
|
||||
// rfm22_write(RFM22_modulation_mode_control1, txdtrtscale_bit | RFM22_mmc1_enwhite);
|
||||
|
||||
if (!data_whitening)
|
||||
rfm22_write(0x70, reg_70[lookup_index] & ~RFM22_mmc1_enwhite); // rfm22_modulation_mode_control1
|
||||
else
|
||||
rfm22_write(0x70, reg_70[lookup_index] | RFM22_mmc1_enwhite); // rfm22_modulation_mode_control1
|
||||
|
||||
rfm22_write(0x71, reg_71[lookup_index]); // rfm22_modulation_mode_control2
|
||||
|
||||
rfm22_write(0x72, reg_72[lookup_index]); // rfm22_frequency_deviation
|
||||
|
||||
rfm22_write(RFM22_ook_counter_value1, 0x00);
|
||||
rfm22_write(RFM22_ook_counter_value2, 0x00);
|
||||
|
||||
// ********************************
|
||||
// calculate the TX register values
|
||||
/*
|
||||
uint16_t fd = frequency_deviation / 625;
|
||||
|
||||
uint8_t mmc1 = RFM22_mmc1_enphpwdn | RFM22_mmc1_manppol;
|
||||
uint16_t txdr;
|
||||
if (datarate_bps < 30000)
|
||||
{
|
||||
txdr = (datarate_bps * 20972) / 10000;
|
||||
mmc1 |= RFM22_mmc1_txdtrtscale;
|
||||
}
|
||||
else
|
||||
txdr = (datarate_bps * 6553) / 100000;
|
||||
|
||||
uint8_t mmc2 = RFM22_mmc2_dtmod_fifo | RFM22_mmc2_modtyp_gfsk; // FIFO mode, GFSK
|
||||
// uint8_t mmc2 = RFM22_mmc2_dtmod_pn9 | RFM22_mmc2_modtyp_gfsk; // PN9 mode, GFSK .. TX TEST MODE
|
||||
if (fd & 0x100) mmc2 |= RFM22_mmc2_fd;
|
||||
|
||||
rfm22_write(RFM22_frequency_deviation, fd); // set the TX peak frequency deviation
|
||||
|
||||
rfm22_write(RFM22_modulation_mode_control1, mmc1);
|
||||
rfm22_write(RFM22_modulation_mode_control2, mmc2);
|
||||
|
||||
rfm22_write(RFM22_tx_data_rate1, txdr >> 8); // set the TX data rate
|
||||
rfm22_write(RFM22_tx_data_rate0, txdr); // " "
|
||||
*/
|
||||
// ********************************
|
||||
// determine a clear channel time
|
||||
|
||||
// initialise the stopwatch with a suitable resolution for the datarate
|
||||
STOPWATCH_init(4000000ul / carrier_datarate_bps); // set resolution to the time for 1 nibble (4-bits) at rf datarate
|
||||
|
||||
// ********************************
|
||||
// determine suitable time-out periods
|
||||
|
||||
timeout_sync_ms = (8000ul * 16) / carrier_datarate_bps; // milliseconds
|
||||
if (timeout_sync_ms < 3)
|
||||
timeout_sync_ms = 3; // because out timer resolution is only 1ms
|
||||
|
||||
timeout_data_ms = (8000ul * 100) / carrier_datarate_bps; // milliseconds
|
||||
if (timeout_data_ms < 3)
|
||||
timeout_data_ms = 3; // because out timer resolution is only 1ms
|
||||
|
||||
// ********************************
|
||||
|
||||
#if defined(RFM22_DEBUG)
|
||||
DEBUG_PRINTF("rf datarate_bps: %d\r\n", datarate_bps);
|
||||
DEBUG_PRINTF("rf frequency_deviation: %d\r\n", frequency_deviation);
|
||||
DEBUG_PRINTF("rf modulation_bandwidth: %u\r\n", modulation_bandwidth);
|
||||
DEBUG_PRINTF("rf_rx_bandwidth[%u]: %u\r\n", lookup_index, rx_bandwidth[lookup_index]);
|
||||
DEBUG_PRINTF("rf est rx sensitivity[%u]: %ddBm\r\n", lookup_index, est_rx_sens_dBm[lookup_index]);
|
||||
#endif
|
||||
|
||||
// *******
|
||||
|
||||
#if defined(RFM22_EXT_INT_USE)
|
||||
exec_using_spi = FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t rfm22_getDatarate(void)
|
||||
{
|
||||
return carrier_datarate_bps;
|
||||
}
|
||||
|
||||
// ************************************
|
||||
|
||||
void rfm22_setSSBandwidth(uint32_t bandwidth_index)
|
||||
{
|
||||
|
||||
#if defined(RFM22_EXT_INT_USE)
|
||||
exec_using_spi = TRUE;
|
||||
#endif
|
||||
// *******
|
||||
|
||||
ss_lookup_index = bandwidth_index;
|
||||
|
||||
ss_rf_bandwidth_used = ss_rx_bandwidth[lookup_index];
|
||||
|
||||
// ********************************
|
||||
|
||||
rfm22_write(0x1C, ss_reg_1C[ss_lookup_index]); // rfm22_if_filter_bandwidth
|
||||
rfm22_write(0x1D, ss_reg_1D[ss_lookup_index]); // rfm22_afc_loop_gearshift_override
|
||||
|
||||
rfm22_write(0x20, ss_reg_20[ss_lookup_index]); // rfm22_clk_recovery_oversampling_ratio
|
||||
rfm22_write(0x21, ss_reg_21[ss_lookup_index]); // rfm22_clk_recovery_offset2
|
||||
rfm22_write(0x22, ss_reg_22[ss_lookup_index]); // rfm22_clk_recovery_offset1
|
||||
rfm22_write(0x23, ss_reg_23[ss_lookup_index]); // rfm22_clk_recovery_offset0
|
||||
rfm22_write(0x24, ss_reg_24[ss_lookup_index]); // rfm22_clk_recovery_timing_loop_gain1
|
||||
rfm22_write(0x25, ss_reg_25[ss_lookup_index]); // rfm22_clk_recovery_timing_loop_gain0
|
||||
|
||||
rfm22_write(0x2A, ss_reg_2A[ss_lookup_index]); // rfm22_afc_limiter
|
||||
|
||||
rfm22_write(0x58, 0x80); // rfm22_chargepump_current_trimming_override
|
||||
|
||||
rfm22_write(0x70, ss_reg_70[ss_lookup_index]); // rfm22_modulation_mode_control1
|
||||
rfm22_write(0x71, ss_reg_71[ss_lookup_index]); // rfm22_modulation_mode_control2
|
||||
|
||||
rfm22_write(RFM22_ook_counter_value1, 0x00);
|
||||
rfm22_write(RFM22_ook_counter_value2, 0x00);
|
||||
|
||||
// ********************************
|
||||
|
||||
#if defined(RFM22_DEBUG)
|
||||
DEBUG_PRINTF("ss_rf_rx_bandwidth[%u]: %u\r\n", ss_lookup_index, ss_rx_bandwidth[ss_lookup_index]);
|
||||
#endif
|
||||
|
||||
// *******
|
||||
|
||||
#if defined(RFM22_EXT_INT_USE)
|
||||
exec_using_spi = FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
// ************************************
|
||||
|
||||
void rfm22_setRxMode(uint8_t mode, bool multi_packet_mode)
|
||||
{
|
||||
#if defined(RFM22_EXT_INT_USE)
|
||||
exec_using_spi = TRUE;
|
||||
#endif
|
||||
|
||||
// disable interrupts
|
||||
rfm22_write(RFM22_interrupt_enable1, 0x00);
|
||||
rfm22_write(RFM22_interrupt_enable2, 0x00);
|
||||
|
||||
// disable the receiver and transmitter
|
||||
// rfm22_write(RFM22_op_and_func_ctrl1, RFM22_opfc1_xton); // READY mode
|
||||
rfm22_write(RFM22_op_and_func_ctrl1, RFM22_opfc1_pllon); // TUNE mode
|
||||
|
||||
RX_LED_OFF;
|
||||
TX_LED_OFF;
|
||||
|
||||
// rfm22_write(RFM22_rx_fifo_control, RX_FIFO_HI_WATERMARK); // RX FIFO Almost Full Threshold (0 - 63)
|
||||
|
||||
if (rf_mode == TX_CARRIER_MODE || rf_mode == TX_PN_MODE)
|
||||
{ // FIFO mode, GFSK modulation
|
||||
uint8_t fd_bit = rfm22_read(RFM22_modulation_mode_control2) & RFM22_mmc2_fd;
|
||||
rfm22_write(RFM22_modulation_mode_control2, fd_bit | RFM22_mmc2_dtmod_fifo | RFM22_mmc2_modtyp_gfsk);
|
||||
}
|
||||
|
||||
rx_buffer_wr = 0; // empty the rx buffer
|
||||
|
||||
rfm22_int_timer = 0; // reset the timer
|
||||
|
||||
rf_mode = mode;
|
||||
|
||||
if (mode != RX_SCAN_SPECTRUM)
|
||||
{
|
||||
STOPWATCH_reset(); // reset clear channel detect timer
|
||||
|
||||
// enable RX interrupts
|
||||
rfm22_write(RFM22_interrupt_enable1, RFM22_ie1_encrcerror | RFM22_ie1_enpkvalid | RFM22_ie1_enrxffafull | RFM22_ie1_enfferr);
|
||||
rfm22_write(RFM22_interrupt_enable2, RFM22_ie2_enpreainval | RFM22_ie2_enpreaval | RFM22_ie2_enswdet);
|
||||
}
|
||||
|
||||
// read interrupt status - clear interrupts
|
||||
rfm22_read(RFM22_interrupt_status1);
|
||||
rfm22_read(RFM22_interrupt_status2);
|
||||
|
||||
// clear FIFOs
|
||||
if (!multi_packet_mode)
|
||||
{
|
||||
rfm22_write(RFM22_op_and_func_ctrl2, RFM22_opfc2_ffclrrx | RFM22_opfc2_ffclrtx);
|
||||
rfm22_write(RFM22_op_and_func_ctrl2, 0x00);
|
||||
}
|
||||
else
|
||||
{
|
||||
rfm22_write(RFM22_op_and_func_ctrl2, RFM22_opfc2_rxmpk | RFM22_opfc2_ffclrrx | RFM22_opfc2_ffclrtx);
|
||||
rfm22_write(RFM22_op_and_func_ctrl2, RFM22_opfc2_rxmpk);
|
||||
}
|
||||
|
||||
// enable the receiver
|
||||
// rfm22_write(RFM22_op_and_func_ctrl1, RFM22_opfc1_xton | RFM22_opfc1_rxon);
|
||||
rfm22_write(RFM22_op_and_func_ctrl1, RFM22_opfc1_pllon | RFM22_opfc1_rxon);
|
||||
|
||||
#if defined(RFM22_EXT_INT_USE)
|
||||
exec_using_spi = FALSE;
|
||||
#endif
|
||||
|
||||
#if defined(RFM22_DEBUG)
|
||||
DEBUG_PRINTF(" RX Mode\r\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
// ************************************
|
||||
|
||||
uint16_t rfm22_addHeader(uint8_t mode)
|
||||
{
|
||||
uint16_t i = 0;
|
||||
|
||||
if (mode == TX_STREAM_MODE)
|
||||
{ // add header
|
||||
for (uint16_t j = (TX_PREAMBLE_NIBBLES + 1) / 2; j > 0; j--)
|
||||
{
|
||||
rfm22_burstWrite(PREAMBLE_BYTE);
|
||||
i++;
|
||||
}
|
||||
rfm22_burstWrite(SYNC_BYTE_1); i++;
|
||||
rfm22_burstWrite(SYNC_BYTE_2); i++;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
// ************************************
|
||||
|
||||
void rfm22_setTxMode(uint8_t mode)
|
||||
{
|
||||
if (mode != TX_DATA_MODE && mode != TX_STREAM_MODE && mode != TX_CARRIER_MODE && mode != TX_PN_MODE)
|
||||
return; // invalid mode
|
||||
|
||||
#if defined(RFM22_EXT_INT_USE)
|
||||
exec_using_spi = TRUE;
|
||||
#endif
|
||||
|
||||
// *******************
|
||||
|
||||
// disable interrupts
|
||||
rfm22_write(RFM22_interrupt_enable1, 0x00);
|
||||
rfm22_write(RFM22_interrupt_enable2, 0x00);
|
||||
|
||||
// rfm22_write(RFM22_op_and_func_ctrl1, RFM22_opfc1_xton); // READY mode
|
||||
rfm22_write(RFM22_op_and_func_ctrl1, RFM22_opfc1_pllon); // TUNE mode
|
||||
|
||||
RX_LED_OFF;
|
||||
|
||||
// set the tx power
|
||||
// rfm22_write(RFM22_tx_power, RFM22_tx_pwr_lna_sw | tx_power);
|
||||
// rfm22_write(RFM22_tx_power, RFM22_tx_pwr_papeaken | RFM22_tx_pwr_papeaklvl_0 | RFM22_tx_pwr_lna_sw | tx_power);
|
||||
rfm22_write(RFM22_tx_power, RFM22_tx_pwr_papeaken | RFM22_tx_pwr_papeaklvl_1 | RFM22_tx_pwr_papeaklvl_0 | RFM22_tx_pwr_lna_sw | tx_power);
|
||||
|
||||
uint8_t fd_bit = rfm22_read(RFM22_modulation_mode_control2) & RFM22_mmc2_fd;
|
||||
if (mode == TX_CARRIER_MODE)
|
||||
{ // blank carrier mode - for testing
|
||||
rfm22_write(RFM22_modulation_mode_control2, fd_bit | RFM22_mmc2_dtmod_pn9 | RFM22_mmc2_modtyp_none); // FIFO mode, Blank carrier
|
||||
}
|
||||
else
|
||||
if (mode == TX_PN_MODE)
|
||||
{ // psuedo random data carrier mode - for testing
|
||||
rfm22_write(RFM22_modulation_mode_control2, fd_bit | RFM22_mmc2_dtmod_pn9 | RFM22_mmc2_modtyp_gfsk); // FIFO mode, PN9 carrier
|
||||
}
|
||||
else
|
||||
{ // data transmission
|
||||
rfm22_write(RFM22_modulation_mode_control2, fd_bit | RFM22_mmc2_dtmod_fifo | RFM22_mmc2_modtyp_gfsk); // FIFO mode, GFSK modulation
|
||||
}
|
||||
|
||||
// rfm22_write(0x72, reg_72[lookup_index]); // rfm22_frequency_deviation
|
||||
|
||||
// clear FIFOs
|
||||
rfm22_write(RFM22_op_and_func_ctrl2, RFM22_opfc2_ffclrrx | RFM22_opfc2_ffclrtx);
|
||||
rfm22_write(RFM22_op_and_func_ctrl2, 0x00);
|
||||
|
||||
// *******************
|
||||
// add some data to the chips TX FIFO before enabling the transmitter
|
||||
|
||||
{
|
||||
uint16_t rd = 0;
|
||||
uint16_t wr = tx_data_wr;
|
||||
if (!tx_data_addr) wr = 0;
|
||||
|
||||
if (mode == TX_DATA_MODE)
|
||||
rfm22_write(RFM22_transmit_packet_length, wr); // set the total number of data bytes we are going to transmit
|
||||
|
||||
uint16_t max_bytes = FIFO_SIZE - 1;
|
||||
|
||||
uint16_t i = 0;
|
||||
|
||||
rfm22_startBurstWrite(RFM22_fifo_access);
|
||||
|
||||
if (mode == TX_STREAM_MODE)
|
||||
{
|
||||
if (rd >= wr)
|
||||
{ // no data to send - yet .. just send preamble pattern
|
||||
while (true)
|
||||
{
|
||||
rfm22_burstWrite(PREAMBLE_BYTE);
|
||||
if (++i >= max_bytes) break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // add the RF heaader
|
||||
i += rfm22_addHeader(mode);
|
||||
}
|
||||
}
|
||||
|
||||
// add some data
|
||||
for (uint16_t j = wr - rd; j > 0; j--)
|
||||
{
|
||||
// int16_t b = -1;
|
||||
// if (tx_data_byte_callback_function)
|
||||
// b = tx_data_byte_callback_function();
|
||||
|
||||
rfm22_burstWrite(tx_data_addr[rd++]);
|
||||
if (++i >= max_bytes) break;
|
||||
}
|
||||
|
||||
rfm22_endBurstWrite();
|
||||
|
||||
tx_data_rd = rd;
|
||||
}
|
||||
|
||||
// *******************
|
||||
|
||||
rfm22_int_timer = 0; // reset the timer
|
||||
|
||||
rf_mode = mode;
|
||||
|
||||
// enable TX interrupts
|
||||
// rfm22_write(RFM22_interrupt_enable1, RFM22_ie1_enpksent | RFM22_ie1_entxffaem | RFM22_ie1_enfferr);
|
||||
rfm22_write(RFM22_interrupt_enable1, RFM22_ie1_enpksent | RFM22_ie1_entxffaem);
|
||||
|
||||
// read interrupt status - clear interrupts
|
||||
rfm22_read(RFM22_interrupt_status1);
|
||||
rfm22_read(RFM22_interrupt_status2);
|
||||
|
||||
// enable the transmitter
|
||||
// rfm22_write(RFM22_op_and_func_ctrl1, RFM22_opfc1_xton | RFM22_opfc1_txon);
|
||||
rfm22_write(RFM22_op_and_func_ctrl1, RFM22_opfc1_pllon | RFM22_opfc1_txon);
|
||||
|
||||
TX_LED_ON;
|
||||
|
||||
// *******************
|
||||
// create new slightly random clear channel detector count value
|
||||
|
||||
uint32_t ccc = (TX_PREAMBLE_NIBBLES + 8) + 4; // minimum clear channel time before allowing transmit
|
||||
clear_channel_count = ccc + (random32 % (ccc * 2)); // plus a some randomness
|
||||
|
||||
// *******************
|
||||
|
||||
#if defined(RFM22_EXT_INT_USE)
|
||||
exec_using_spi = FALSE;
|
||||
#endif
|
||||
|
||||
#if defined(RFM22_DEBUG)
|
||||
if (rf_mode == TX_DATA_MODE) DEBUG_PRINTF(" TX_Data_Mode\r\n");
|
||||
else
|
||||
if (rf_mode == TX_STREAM_MODE) DEBUG_PRINTF(" TX_Stream_Mode\r\n");
|
||||
else
|
||||
if (rf_mode == TX_CARRIER_MODE) DEBUG_PRINTF(" TX_Carrier_Mode\r\n");
|
||||
else
|
||||
if (rf_mode == TX_PN_MODE) DEBUG_PRINTF(" TX_PN_Mode\r\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
// ************************************
|
||||
// external interrupt line triggered (or polled) from the rf chip
|
||||
|
||||
void rfm22_processRxInt(void)
|
||||
{
|
||||
register uint8_t int_stat1 = int_status1;
|
||||
register uint8_t int_stat2 = int_status2;
|
||||
|
||||
if (int_stat2 & RFM22_is2_ipreaval)
|
||||
{ // Valid preamble detected
|
||||
|
||||
if (rf_mode == RX_WAIT_PREAMBLE_MODE)
|
||||
{
|
||||
rfm22_int_timer = 0; // reset the timer
|
||||
rf_mode = RX_WAIT_SYNC_MODE;
|
||||
RX_LED_ON;
|
||||
|
||||
#if defined(RFM22_DEBUG) && !defined(RFM22_EXT_INT_USE)
|
||||
DEBUG_PRINTF(" pream_det");
|
||||
debug_outputted = true;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
/* else
|
||||
if (int_stat2 & RFM22_is2_ipreainval)
|
||||
{ // Invalid preamble detected
|
||||
|
||||
if (rf_mode == RX_WAIT_SYNC_MODE)
|
||||
{
|
||||
#if defined(RFM22_DEBUG) && !defined(RFM22_EXT_INT_USE)
|
||||
DEBUG_PRINTF(" invalid_preamble");
|
||||
debug_outputted = true;
|
||||
#endif
|
||||
|
||||
rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
}
|
||||
*/
|
||||
if (int_stat2 & RFM22_is2_iswdet)
|
||||
{ // Sync word detected
|
||||
|
||||
STOPWATCH_reset(); // reset timer
|
||||
|
||||
if (rf_mode == RX_WAIT_PREAMBLE_MODE || rf_mode == RX_WAIT_SYNC_MODE)
|
||||
{
|
||||
rfm22_int_timer = 0; // reset the timer
|
||||
rf_mode = RX_DATA_MODE;
|
||||
RX_LED_ON;
|
||||
|
||||
// read the 10-bit signed afc correction value
|
||||
afc_correction = (uint16_t)rfm22_read(RFM22_afc_correction_read) << 8; // bits 9 to 2
|
||||
afc_correction |= (uint16_t)rfm22_read(RFM22_ook_counter_value1) & 0x00c0; // bits 1 & 0
|
||||
afc_correction >>= 6;
|
||||
afc_correction_Hz = (int32_t)(frequency_step_size * afc_correction + 0.5f); // convert the afc value to Hz
|
||||
|
||||
rx_packet_start_rssi_dBm = rssi_dBm; // remember the rssi for this packet
|
||||
rx_packet_start_afc_Hz = afc_correction_Hz; // remember the afc value for this packet
|
||||
|
||||
#if defined(RFM22_DEBUG) && !defined(RFM22_EXT_INT_USE)
|
||||
DEBUG_PRINTF(" sync_det");
|
||||
DEBUG_PRINTF(" AFC_%d_%dHz", afc_correction, afc_correction_Hz);
|
||||
debug_outputted = true;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (int_stat1 & RFM22_is1_irxffafull)
|
||||
{ // RX FIFO almost full, it needs emptying
|
||||
|
||||
if (rf_mode == RX_DATA_MODE)
|
||||
{ // read data from the rf chips FIFO buffer
|
||||
rfm22_int_timer = 0; // reset the timer
|
||||
|
||||
register uint16_t len = rfm22_read(RFM22_received_packet_length); // read the total length of the packet data
|
||||
|
||||
register uint16_t wr = rx_buffer_wr;
|
||||
|
||||
if ((wr + RX_FIFO_HI_WATERMARK) > len)
|
||||
{ // some kind of error in the RF module
|
||||
#if defined(RFM22_DEBUG) && !defined(RFM22_EXT_INT_USE)
|
||||
DEBUG_PRINTF(" r_size_error1");
|
||||
debug_outputted = true;
|
||||
#endif
|
||||
|
||||
rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (((wr + RX_FIFO_HI_WATERMARK) >= len) && !(int_stat1 & RFM22_is1_ipkvalid))
|
||||
{ // some kind of error in the RF module
|
||||
#if defined(RFM22_DEBUG) && !defined(RFM22_EXT_INT_USE)
|
||||
DEBUG_PRINTF(" r_size_error2");
|
||||
debug_outputted = true;
|
||||
#endif
|
||||
|
||||
rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false);
|
||||
return;
|
||||
}
|
||||
|
||||
// fetch the rx'ed data from the rf chips RX FIFO
|
||||
rfm22_startBurstRead(RFM22_fifo_access);
|
||||
rx_fifo_wr = 0;
|
||||
for (register uint8_t i = RX_FIFO_HI_WATERMARK; i > 0; i--)
|
||||
rx_fifo[rx_fifo_wr++] = rfm22_burstRead(); // read a byte from the rf modules RX FIFO buffer
|
||||
rfm22_endBurstRead();
|
||||
|
||||
uint16_t i = rx_fifo_wr;
|
||||
if (wr + i > sizeof(rx_buffer)) i = sizeof(rx_buffer) - wr;
|
||||
memcpy((void *)(rx_buffer + wr), (void *)rx_fifo, i); // save the new bytes into our rx buffer
|
||||
wr += i;
|
||||
|
||||
rx_buffer_wr = wr;
|
||||
|
||||
if (rx_data_callback_function)
|
||||
{ // pass the new data onto whoever wanted it
|
||||
if (!rx_data_callback_function((void *)rx_fifo, rx_fifo_wr))
|
||||
{
|
||||
rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(RFM22_DEBUG) && !defined(RFM22_EXT_INT_USE)
|
||||
// DEBUG_PRINTF(" r_data_%u/%u", rx_buffer_wr, len);
|
||||
// debug_outputted = true;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{ // just clear the RX FIFO
|
||||
rfm22_startBurstRead(RFM22_fifo_access);
|
||||
for (register uint16_t i = RX_FIFO_HI_WATERMARK; i > 0; i--)
|
||||
rfm22_burstRead(); // read a byte from the rf modules RX FIFO buffer
|
||||
rfm22_endBurstRead();
|
||||
}
|
||||
}
|
||||
|
||||
if (int_stat1 & RFM22_is1_icrerror)
|
||||
{ // CRC error .. discard the received data
|
||||
|
||||
if (rf_mode == RX_DATA_MODE)
|
||||
{
|
||||
rfm22_int_timer = 0; // reset the timer
|
||||
|
||||
#if defined(RFM22_DEBUG) && !defined(RFM22_EXT_INT_USE)
|
||||
DEBUG_PRINTF(" CRC_ERR");
|
||||
debug_outputted = true;
|
||||
#endif
|
||||
|
||||
rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); // reset the receiver
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// if (int_stat2 & RFM22_is2_irssi)
|
||||
// { // RSSI level is >= the set threshold
|
||||
// }
|
||||
|
||||
// if (device_status & RFM22_ds_rxffem)
|
||||
// { // RX FIFO empty
|
||||
// }
|
||||
|
||||
// if (device_status & RFM22_ds_headerr)
|
||||
// { // Header check error
|
||||
// }
|
||||
|
||||
if (int_stat1 & RFM22_is1_ipkvalid)
|
||||
{ // Valid packet received
|
||||
|
||||
if (rf_mode == RX_DATA_MODE)
|
||||
{
|
||||
rfm22_int_timer = 0; // reset the timer
|
||||
|
||||
// disable the receiver
|
||||
// rfm22_write(RFM22_op_and_func_ctrl1, RFM22_opfc1_xton); // READY mode
|
||||
rfm22_write(RFM22_op_and_func_ctrl1, RFM22_opfc1_pllon); // TUNE mode
|
||||
|
||||
register uint16_t len = rfm22_read(RFM22_received_packet_length); // read the total length of the packet data
|
||||
|
||||
register uint16_t wr = rx_buffer_wr;
|
||||
|
||||
if (wr < len)
|
||||
{ // their must still be data in the RX FIFO we need to get
|
||||
|
||||
// fetch the rx'ed data from the rf chips RX FIFO
|
||||
rfm22_startBurstRead(RFM22_fifo_access);
|
||||
rx_fifo_wr = 0;
|
||||
for (register uint8_t i = len - wr; i > 0; i--)
|
||||
rx_fifo[rx_fifo_wr++] = rfm22_burstRead(); // read a byte from the rf modules RX FIFO buffer
|
||||
rfm22_endBurstRead();
|
||||
|
||||
uint16_t i = rx_fifo_wr;
|
||||
if (wr + i > sizeof(rx_buffer)) i = sizeof(rx_buffer) - wr;
|
||||
memcpy((void *)(rx_buffer + wr), (void *)rx_fifo, i); // save the new bytes into our rx buffer
|
||||
wr += i;
|
||||
|
||||
rx_buffer_wr = wr;
|
||||
|
||||
if (rx_data_callback_function)
|
||||
{ // pass the new data onto whoever wanted it
|
||||
if (!rx_data_callback_function((void *)rx_fifo, rx_fifo_wr))
|
||||
{
|
||||
// rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false);
|
||||
// return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); // reset the receiver
|
||||
|
||||
if (wr != len)
|
||||
{ // we have a packet length error .. discard the packet
|
||||
#if defined(RFM22_DEBUG) && !defined(RFM22_EXT_INT_USE)
|
||||
DEBUG_PRINTF(" r_pack_len_error_%u_%u", len, wr);
|
||||
debug_outputted = true;
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// we have a valid received packet
|
||||
#if defined(RFM22_DEBUG) && !defined(RFM22_EXT_INT_USE)
|
||||
DEBUG_PRINTF(" VALID_R_PACKET_%u", wr);
|
||||
debug_outputted = true;
|
||||
#endif
|
||||
|
||||
if (rx_packet_wr == 0)
|
||||
{ // save the received packet for further processing
|
||||
rx_packet_rssi_dBm = rx_packet_start_rssi_dBm; // remember the rssi for this packet
|
||||
rx_packet_afc_Hz = rx_packet_start_afc_Hz; // remember the afc offset for this packet
|
||||
memmove((void *)rx_packet_buf, (void *)rx_buffer, wr); // copy the packet data
|
||||
rx_packet_wr = wr; // save the length of the data
|
||||
}
|
||||
else
|
||||
{ // the save buffer is still in use .. nothing we can do but to drop the packet
|
||||
}
|
||||
|
||||
// return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); // reset the receiver
|
||||
// return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t rfm22_topUpRFTxFIFO(void)
|
||||
{
|
||||
rfm22_int_timer = 0; // reset the timer
|
||||
|
||||
uint16_t rd = tx_data_rd;
|
||||
uint16_t wr = tx_data_wr;
|
||||
|
||||
if (rf_mode == TX_DATA_MODE && (!tx_data_addr || rd >= wr))
|
||||
return 0; // no more data to send
|
||||
|
||||
uint16_t max_bytes = FIFO_SIZE - TX_FIFO_LO_WATERMARK - 1;
|
||||
|
||||
uint16_t i = 0;
|
||||
|
||||
// top-up the rf chips TX FIFO buffer
|
||||
rfm22_startBurstWrite(RFM22_fifo_access);
|
||||
|
||||
// add some data
|
||||
for (uint16_t j = wr - rd; j > 0; j--)
|
||||
{
|
||||
// int16_t b = -1;
|
||||
// if (tx_data_byte_callback_function)
|
||||
// b = tx_data_byte_callback_function();
|
||||
|
||||
rfm22_burstWrite(tx_data_addr[rd++]);
|
||||
if (++i >= max_bytes) break;
|
||||
}
|
||||
tx_data_rd = rd;
|
||||
|
||||
if (rf_mode == TX_STREAM_MODE && rd >= wr)
|
||||
{ // all data sent .. need to start sending RF header again
|
||||
|
||||
tx_data_addr = NULL;
|
||||
tx_data_rd = tx_data_wr = 0;
|
||||
|
||||
while (i < max_bytes)
|
||||
{
|
||||
rfm22_burstWrite(PREAMBLE_BYTE); // preamble byte
|
||||
i++;
|
||||
}
|
||||
|
||||
// todo:
|
||||
|
||||
// add the RF heaader
|
||||
// i += rfm22_addHeader(rf_mode);
|
||||
}
|
||||
|
||||
rfm22_endBurstWrite();
|
||||
|
||||
#if defined(RFM22_DEBUG) && !defined(RFM22_EXT_INT_USE)
|
||||
// DEBUG_PRINTF(" added_%d_bytes", i);
|
||||
// debug_outputted = true;
|
||||
#endif
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
void rfm22_processTxInt(void)
|
||||
{
|
||||
register uint8_t int_stat1 = int_status1;
|
||||
// register uint8_t int_stat2 = int_status2;
|
||||
|
||||
/*
|
||||
if (int_stat1 & RFM22_is1_ifferr)
|
||||
{ // FIFO underflow/overflow error
|
||||
rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false);
|
||||
tx_data_addr = NULL;
|
||||
tx_data_rd = tx_data_wr = 0;
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
if (int_stat1 & RFM22_is1_ixtffaem)
|
||||
{ // TX FIFO almost empty, it needs filling up
|
||||
|
||||
#if defined(RFM22_DEBUG) && !defined(RFM22_EXT_INT_USE)
|
||||
// DEBUG_PRINTF(" T_FIFO_AE");
|
||||
// debug_outputted = true;
|
||||
#endif
|
||||
|
||||
// uint8_t bytes_added = rfm22_topUpRFTxFIFO();
|
||||
rfm22_topUpRFTxFIFO();
|
||||
}
|
||||
|
||||
if (int_stat1 & RFM22_is1_ipksent)
|
||||
{ // Packet has been sent
|
||||
#if defined(RFM22_DEBUG) && !defined(RFM22_EXT_INT_USE)
|
||||
DEBUG_PRINTF(" T_Sent");
|
||||
debug_outputted = true;
|
||||
#endif
|
||||
|
||||
if (rf_mode == TX_DATA_MODE)
|
||||
{
|
||||
rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); // back to receive mode
|
||||
|
||||
tx_data_addr = NULL;
|
||||
tx_data_rd = tx_data_wr = 0;
|
||||
return;
|
||||
}
|
||||
else
|
||||
if (rf_mode == TX_STREAM_MODE)
|
||||
{
|
||||
tx_data_addr = NULL;
|
||||
tx_data_rd = tx_data_wr = 0;
|
||||
|
||||
rfm22_setTxMode(TX_STREAM_MODE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// if (int_stat1 & RFM22_is1_itxffafull)
|
||||
// { // TX FIFO almost full, it needs to be transmitted
|
||||
// }
|
||||
}
|
||||
|
||||
void rfm22_processInt(void)
|
||||
{ // this is called from the external interrupt handler
|
||||
|
||||
#if !defined(RFM22_EXT_INT_USE)
|
||||
if (GPIO_IN(RF_INT_PIN))
|
||||
return; // the external int line is high (no signalled interrupt)
|
||||
#endif
|
||||
|
||||
if (!initialized || power_on_reset)
|
||||
return; // we haven't yet been initialized
|
||||
|
||||
#if defined(RFM22_DEBUG)
|
||||
debug_outputted = false;
|
||||
#endif
|
||||
|
||||
// ********************************
|
||||
// read the RF modules current status registers
|
||||
|
||||
// read device status register
|
||||
device_status = rfm22_read(RFM22_device_status);
|
||||
|
||||
// read ezmac status register
|
||||
ezmac_status = rfm22_read(RFM22_ezmac_status);
|
||||
|
||||
// read interrupt status registers - clears the interrupt line
|
||||
int_status1 = rfm22_read(RFM22_interrupt_status1);
|
||||
int_status2 = rfm22_read(RFM22_interrupt_status2);
|
||||
|
||||
if (rf_mode != TX_DATA_MODE && rf_mode != TX_STREAM_MODE && rf_mode != TX_CARRIER_MODE && rf_mode != TX_PN_MODE)
|
||||
{
|
||||
rssi = rfm22_read(RFM22_rssi); // read rx signal strength .. 45 = -100dBm, 205 = -20dBm
|
||||
rssi_dBm = ((int16_t)rssi / 2) - 122; // convert to dBm
|
||||
|
||||
// calibrate the RSSI value (rf bandwidth appears to affect it)
|
||||
// if (rf_bandwidth_used > 0)
|
||||
// rssi_dBm -= 10000 / rf_bandwidth_used;
|
||||
}
|
||||
else
|
||||
{
|
||||
tx_pwr = rfm22_read(RFM22_tx_power); // read the tx power register
|
||||
}
|
||||
|
||||
if (int_status2 & RFM22_is2_ipor)
|
||||
{ // the RF module has gone and done a reset - we need to re-initialize the rf module
|
||||
initialized = FALSE;
|
||||
power_on_reset = TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
// ********************************
|
||||
// debug stuff
|
||||
|
||||
#if defined(RFM22_DEBUG) && !defined(RFM22_EXT_INT_USE)
|
||||
if (prev_device_status != device_status || prev_int_status1 != int_status1 || prev_int_status2 != int_status2 || prev_ezmac_status != ezmac_status)
|
||||
{
|
||||
DEBUG_PRINTF("%02x %02x %02x %02x %dC", device_status, int_status1, int_status2, ezmac_status, temperature_reg);
|
||||
|
||||
if ((device_status & RFM22_ds_cps_mask) == RFM22_ds_cps_rx)
|
||||
DEBUG_PRINTF(" %ddBm", rssi_dBm); // rx mode
|
||||
else
|
||||
if ((device_status & RFM22_ds_cps_mask) == RFM22_ds_cps_tx)
|
||||
DEBUG_PRINTF(" %s", (tx_pwr & RFM22_tx_pwr_papeakval) ? "ANT_MISMATCH" : "ant_ok"); // tx mode
|
||||
|
||||
debug_outputted = true;
|
||||
|
||||
prev_device_status = device_status;
|
||||
prev_int_status1 = int_status1;
|
||||
prev_int_status2 = int_status2;
|
||||
prev_ezmac_status = ezmac_status;
|
||||
}
|
||||
#endif
|
||||
|
||||
// ********************************
|
||||
// read the ADC - temperature sensor .. this can only be used in IDLE mode
|
||||
/*
|
||||
if (!(rfm22_read(RFM22_adc_config) & RFM22_ac_adcstartbusy))
|
||||
{ // the ADC has completed it's conversion
|
||||
|
||||
// read the ADC sample
|
||||
temperature_reg = (int16_t)rfm22_read(RFM22_adc_value) * 0.5f - 64;
|
||||
|
||||
// start a new ADC conversion
|
||||
rfm22_write(RFM22_adc_config, adc_config | RFM22_ac_adcstartbusy);
|
||||
|
||||
#if defined(RFM22_DEBUG) && !defined(RFM22_EXT_INT_USE)
|
||||
DEBUG_PRINTF(", %dC", temperature_reg);
|
||||
debug_outputted = true;
|
||||
#endif
|
||||
}
|
||||
*/
|
||||
// ********************************
|
||||
|
||||
register uint16_t timer_ms = rfm22_int_timer;
|
||||
|
||||
switch (rf_mode)
|
||||
{
|
||||
case RX_SCAN_SPECTRUM:
|
||||
break;
|
||||
|
||||
case RX_WAIT_PREAMBLE_MODE:
|
||||
case RX_WAIT_SYNC_MODE:
|
||||
case RX_DATA_MODE:
|
||||
|
||||
if (device_status & (RFM22_ds_ffunfl | RFM22_ds_ffovfl))
|
||||
{ // FIFO under/over flow error
|
||||
|
||||
#if defined(RFM22_DEBUG) && !defined(RFM22_EXT_INT_USE)
|
||||
DEBUG_PRINTF(" R_UNDER/OVERRUN");
|
||||
debug_outputted = true;
|
||||
#endif
|
||||
|
||||
rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); // reset the receiver
|
||||
tx_data_rd = tx_data_wr = 0; // wipe TX buffer
|
||||
break;
|
||||
}
|
||||
|
||||
if (rf_mode == RX_WAIT_SYNC_MODE && timer_ms >= timeout_sync_ms)
|
||||
{
|
||||
rfm22_int_time_outs++;
|
||||
|
||||
#if defined(RFM22_DEBUG) && !defined(RFM22_EXT_INT_USE)
|
||||
DEBUG_PRINTF(" R_SYNC_TIMEOUT");
|
||||
debug_outputted = true;
|
||||
#endif
|
||||
|
||||
rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); // reset the receiver
|
||||
tx_data_rd = tx_data_wr = 0; // wipe TX buffer
|
||||
break;
|
||||
}
|
||||
|
||||
if (rf_mode == RX_DATA_MODE && timer_ms >= timeout_data_ms)
|
||||
{ // missing interrupts
|
||||
rfm22_int_time_outs++;
|
||||
rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); // reset the receiver
|
||||
tx_data_rd = tx_data_wr = 0; // wipe TX buffer
|
||||
break;
|
||||
}
|
||||
|
||||
if ((device_status & RFM22_ds_cps_mask) != RFM22_ds_cps_rx)
|
||||
{ // the rf module is not in rx mode
|
||||
if (timer_ms >= 100)
|
||||
{
|
||||
rfm22_int_time_outs++;
|
||||
|
||||
#if defined(RFM22_DEBUG) && !defined(RFM22_EXT_INT_USE)
|
||||
DEBUG_PRINTF(" R_TIMEOUT");
|
||||
debug_outputted = true;
|
||||
#endif
|
||||
|
||||
rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); // reset the receiver
|
||||
tx_data_rd = tx_data_wr = 0; // wipe TX buffer
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
rfm22_processRxInt(); // process the interrupt
|
||||
break;
|
||||
|
||||
case TX_DATA_MODE:
|
||||
|
||||
if (device_status & (RFM22_ds_ffunfl | RFM22_ds_ffovfl))
|
||||
{ // FIFO under/over flow error
|
||||
|
||||
#if defined(RFM22_DEBUG) && !defined(RFM22_EXT_INT_USE)
|
||||
DEBUG_PRINTF(" T_UNDER/OVERRUN");
|
||||
debug_outputted = true;
|
||||
#endif
|
||||
|
||||
rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); // back to rx mode
|
||||
tx_data_rd = tx_data_wr = 0; // wipe TX buffer
|
||||
break;
|
||||
}
|
||||
|
||||
if (timer_ms >= timeout_data_ms)
|
||||
{
|
||||
rfm22_int_time_outs++;
|
||||
rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); // back to rx mode
|
||||
tx_data_rd = tx_data_wr = 0; // wipe TX buffer
|
||||
break;
|
||||
}
|
||||
|
||||
if ((device_status & RFM22_ds_cps_mask) != RFM22_ds_cps_tx)
|
||||
{ // the rf module is not in tx mode
|
||||
if (timer_ms >= 100)
|
||||
{
|
||||
rfm22_int_time_outs++;
|
||||
|
||||
#if defined(RFM22_DEBUG) && !defined(RFM22_EXT_INT_USE)
|
||||
DEBUG_PRINTF(" T_TIMEOUT");
|
||||
debug_outputted = true;
|
||||
#endif
|
||||
|
||||
rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); // back to rx mode
|
||||
tx_data_rd = tx_data_wr = 0; // wipe TX buffer
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
rfm22_processTxInt(); // process the interrupt
|
||||
break;
|
||||
|
||||
case TX_STREAM_MODE:
|
||||
|
||||
// todo:
|
||||
rfm22_processTxInt(); // process the interrupt
|
||||
|
||||
break;
|
||||
|
||||
case TX_CARRIER_MODE:
|
||||
case TX_PN_MODE:
|
||||
|
||||
// if (timer_ms >= TX_TEST_MODE_TIMELIMIT_MS) // 'nn'ms limit
|
||||
// {
|
||||
// rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); // back to rx mode
|
||||
// tx_data_rd = tx_data_wr = 0; // wipe TX buffer
|
||||
// break;
|
||||
// }
|
||||
|
||||
break;
|
||||
|
||||
default: // unknown mode - this should NEVER happen, maybe we should do a complete CPU reset here
|
||||
rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); // to rx mode
|
||||
tx_data_rd = tx_data_wr = 0; // wipe TX buffer
|
||||
break;
|
||||
}
|
||||
|
||||
// ********************************
|
||||
|
||||
#if defined(RFM22_DEBUG) && !defined(RFM22_EXT_INT_USE)
|
||||
if (debug_outputted)
|
||||
{
|
||||
switch (rf_mode)
|
||||
{
|
||||
case RX_SCAN_SPECTRUM:
|
||||
DEBUG_PRINTF(" R_SCAN_SPECTRUM\r\n");
|
||||
break;
|
||||
case RX_WAIT_PREAMBLE_MODE:
|
||||
DEBUG_PRINTF(" R_WAIT_PREAMBLE\r\n");
|
||||
break;
|
||||
case RX_WAIT_SYNC_MODE:
|
||||
DEBUG_PRINTF(" R_WAIT_SYNC\r\n");
|
||||
break;
|
||||
case RX_DATA_MODE:
|
||||
DEBUG_PRINTF(" R_DATA\r\n");
|
||||
break;
|
||||
case TX_DATA_MODE:
|
||||
DEBUG_PRINTF(" T_DATA\r\n");
|
||||
break;
|
||||
case TX_STREAM_MODE:
|
||||
DEBUG_PRINTF(" T_STREAM\r\n");
|
||||
break;
|
||||
case TX_CARRIER_MODE:
|
||||
DEBUG_PRINTF(" T_CARRIER\r\n");
|
||||
break;
|
||||
case TX_PN_MODE:
|
||||
DEBUG_PRINTF(" T_PN\r\n");
|
||||
break;
|
||||
default:
|
||||
DEBUG_PRINTF(" UNKNOWN_MODE\r\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// ********************************
|
||||
}
|
||||
|
||||
// ************************************
|
||||
|
||||
int16_t rfm22_getRSSI(void)
|
||||
{
|
||||
#if defined(RFM22_EXT_INT_USE)
|
||||
exec_using_spi = TRUE;
|
||||
#endif
|
||||
|
||||
rssi = rfm22_read(RFM22_rssi); // read rx signal strength .. 45 = -100dBm, 205 = -20dBm
|
||||
rssi_dBm = ((int16_t)rssi / 2) - 122; // convert to dBm
|
||||
|
||||
#if defined(RFM22_EXT_INT_USE)
|
||||
exec_using_spi = FALSE;
|
||||
#endif
|
||||
|
||||
return rssi_dBm;
|
||||
}
|
||||
|
||||
int16_t rfm22_receivedRSSI(void)
|
||||
{ // return the packets signal strength
|
||||
if (!initialized)
|
||||
return -200;
|
||||
else
|
||||
return rx_packet_rssi_dBm;
|
||||
}
|
||||
|
||||
int32_t rfm22_receivedAFCHz(void)
|
||||
{ // return the packets offset frequency
|
||||
if (!initialized)
|
||||
return 0;
|
||||
else
|
||||
return rx_packet_afc_Hz;
|
||||
}
|
||||
|
||||
uint16_t rfm22_receivedLength(void)
|
||||
{ // return the size of the data received
|
||||
if (!initialized)
|
||||
return 0;
|
||||
else
|
||||
return rx_packet_wr;
|
||||
}
|
||||
|
||||
uint8_t * rfm22_receivedPointer(void)
|
||||
{ // return the address of the data
|
||||
return (uint8_t *)&rx_packet_buf;
|
||||
}
|
||||
|
||||
void rfm22_receivedDone(void)
|
||||
{ // empty the rx packet buffer
|
||||
rx_packet_wr = 0;
|
||||
}
|
||||
|
||||
// ************************************
|
||||
|
||||
int32_t rfm22_sendData(void *data, uint16_t length, bool send_immediately)
|
||||
{
|
||||
if (!initialized)
|
||||
return -1; // we are not yet initialized
|
||||
|
||||
if (length == 0)
|
||||
return -2; // no data to send
|
||||
|
||||
if (!data || length > 255)
|
||||
return -3; // no data or too much data to send
|
||||
|
||||
if (tx_data_wr > 0)
|
||||
return -4; // already have data to be sent
|
||||
|
||||
if (rf_mode == TX_DATA_MODE || rf_mode == TX_STREAM_MODE || rf_mode == TX_CARRIER_MODE || rf_mode == TX_PN_MODE || rf_mode == RX_SCAN_SPECTRUM)
|
||||
return -5; // we are currently transmitting or scanning the spectrum
|
||||
|
||||
tx_data_addr = data;
|
||||
tx_data_rd = 0;
|
||||
tx_data_wr = length;
|
||||
|
||||
#if defined(RFM22_DEBUG)
|
||||
DEBUG_PRINTF("rf sendData(0x%08x %u)\r\n", (uint32_t)tx_data_addr, tx_data_wr);
|
||||
#endif
|
||||
|
||||
if (send_immediately || rfm22_channelIsClear()) // is the channel clear to transmit on?
|
||||
rfm22_setTxMode(TX_DATA_MODE); // transmit NOW
|
||||
|
||||
return tx_data_wr;
|
||||
}
|
||||
|
||||
// ************************************
|
||||
|
||||
void rfm22_setTxStream(void) // TEST ONLY
|
||||
{
|
||||
if (!initialized)
|
||||
return;
|
||||
|
||||
tx_data_rd = tx_data_wr = 0;
|
||||
|
||||
rfm22_setTxMode(TX_STREAM_MODE);
|
||||
}
|
||||
|
||||
// ************************************
|
||||
|
||||
void rfm22_setTxNormal(void)
|
||||
{
|
||||
if (!initialized)
|
||||
return;
|
||||
|
||||
// if (rf_mode == TX_CARRIER_MODE || rf_mode == TX_PN_MODE)
|
||||
if (rf_mode != RX_SCAN_SPECTRUM)
|
||||
{
|
||||
rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false);
|
||||
tx_data_rd = tx_data_wr = 0;
|
||||
|
||||
rx_packet_wr = 0;
|
||||
rx_packet_start_rssi_dBm = 0;
|
||||
rx_packet_start_afc_Hz = 0;
|
||||
rx_packet_rssi_dBm = 0;
|
||||
rx_packet_afc_Hz = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// enable a blank tx carrier (for frequency alignment)
|
||||
void rfm22_setTxCarrierMode(void)
|
||||
{
|
||||
if (!initialized)
|
||||
return;
|
||||
|
||||
if (rf_mode != TX_CARRIER_MODE && rf_mode != RX_SCAN_SPECTRUM)
|
||||
rfm22_setTxMode(TX_CARRIER_MODE);
|
||||
}
|
||||
|
||||
// enable a psuedo random data tx carrier (for spectrum inspection)
|
||||
void rfm22_setTxPNMode(void)
|
||||
{
|
||||
if (!initialized)
|
||||
return;
|
||||
|
||||
if (rf_mode != TX_PN_MODE && rf_mode != RX_SCAN_SPECTRUM)
|
||||
rfm22_setTxMode(TX_PN_MODE);
|
||||
}
|
||||
|
||||
// ************************************
|
||||
|
||||
// return the current mode
|
||||
int8_t rfm22_currentMode(void)
|
||||
{
|
||||
return rf_mode;
|
||||
}
|
||||
|
||||
// return TRUE if we are transmitting
|
||||
bool rfm22_transmitting(void)
|
||||
{
|
||||
return (rf_mode == TX_DATA_MODE || rf_mode == TX_STREAM_MODE || rf_mode == TX_CARRIER_MODE || rf_mode == TX_PN_MODE);
|
||||
}
|
||||
|
||||
// return TRUE if the channel is clear to transmit on
|
||||
bool rfm22_channelIsClear(void)
|
||||
{
|
||||
if (!initialized)
|
||||
return FALSE; // we haven't yet been initialized
|
||||
|
||||
if (rf_mode != RX_WAIT_PREAMBLE_MODE && rf_mode != RX_WAIT_SYNC_MODE)
|
||||
return FALSE; // we are receiving something or we are transmitting or we are scanning the spectrum
|
||||
|
||||
return TRUE;
|
||||
// return (STOPWATCH_get_count() > clear_channel_count);
|
||||
}
|
||||
|
||||
// return TRUE if the transmiter is ready for use
|
||||
bool rfm22_txReady(void)
|
||||
{
|
||||
if (!initialized)
|
||||
return FALSE; // we haven't yet been initialized
|
||||
|
||||
return (tx_data_rd == 0 && tx_data_wr == 0 && rf_mode != TX_DATA_MODE && rf_mode != TX_STREAM_MODE && rf_mode != TX_CARRIER_MODE && rf_mode != TX_PN_MODE && rf_mode != RX_SCAN_SPECTRUM);
|
||||
}
|
||||
|
||||
// ************************************
|
||||
// set/get the frequency calibration value
|
||||
|
||||
void rfm22_setFreqCalibration(uint8_t value)
|
||||
{
|
||||
osc_load_cap = value;
|
||||
|
||||
if (!initialized || power_on_reset)
|
||||
return; // we haven't yet been initialized
|
||||
|
||||
uint8_t prev_rf_mode = rf_mode;
|
||||
|
||||
if (rf_mode == TX_CARRIER_MODE || rf_mode == TX_PN_MODE)
|
||||
{
|
||||
rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false);
|
||||
tx_data_rd = tx_data_wr = 0;
|
||||
}
|
||||
|
||||
#if defined(RFM22_EXT_INT_USE)
|
||||
exec_using_spi = TRUE;
|
||||
#endif
|
||||
|
||||
rfm22_write(RFM22_xtal_osc_load_cap, osc_load_cap);
|
||||
|
||||
#if defined(RFM22_EXT_INT_USE)
|
||||
exec_using_spi = FALSE;
|
||||
#endif
|
||||
|
||||
if (prev_rf_mode == TX_CARRIER_MODE || prev_rf_mode == TX_PN_MODE)
|
||||
rfm22_setTxMode(prev_rf_mode);
|
||||
}
|
||||
|
||||
uint8_t rfm22_getFreqCalibration(void)
|
||||
{
|
||||
return osc_load_cap;
|
||||
}
|
||||
|
||||
// ************************************
|
||||
// can be called from an interrupt if you wish
|
||||
|
||||
void rfm22_1ms_tick(void)
|
||||
{ // call this once every ms
|
||||
if (booting) return;
|
||||
if (!initialized) return; // we haven't yet been initialized
|
||||
|
||||
if (rf_mode != RX_SCAN_SPECTRUM)
|
||||
{
|
||||
if (rfm22_int_timer < 0xffff) rfm22_int_timer++;
|
||||
}
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// call this as often as possible - not from an interrupt
|
||||
|
||||
void rfm22_process(void)
|
||||
{
|
||||
if (booting) return;
|
||||
if (!initialized) return; // we haven't yet been initialized
|
||||
|
||||
#if !defined(RFM22_EXT_INT_USE)
|
||||
if (rf_mode != RX_SCAN_SPECTRUM)
|
||||
rfm22_processInt(); // manually poll the interrupt line routine
|
||||
#endif
|
||||
|
||||
if (power_on_reset)
|
||||
{ // we need to re-initialize the RF module - it told us it's reset itself
|
||||
if (rf_mode != RX_SCAN_SPECTRUM)
|
||||
{ // normal data mode
|
||||
uint32_t current_freq = carrier_frequency_hz; // fetch current rf nominal frequency
|
||||
rfm22_init_normal(lower_carrier_frequency_limit_Hz, upper_carrier_frequency_limit_Hz, rfm22_freqHopSize());
|
||||
rfm22_setNominalCarrierFrequency(current_freq); // restore the nominal carrier frequency
|
||||
}
|
||||
else
|
||||
{ // we are scanning the spectrum
|
||||
rfm22_init_scan_spectrum(lower_carrier_frequency_limit_Hz, upper_carrier_frequency_limit_Hz);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
switch (rf_mode)
|
||||
{
|
||||
case RX_SCAN_SPECTRUM: // we are scanning the spectrum
|
||||
|
||||
// read device status register
|
||||
device_status = rfm22_read(RFM22_device_status);
|
||||
|
||||
// read ezmac status register
|
||||
ezmac_status = rfm22_read(RFM22_ezmac_status);
|
||||
|
||||
// read interrupt status registers - clears the interrupt line
|
||||
int_status1 = rfm22_read(RFM22_interrupt_status1);
|
||||
int_status2 = rfm22_read(RFM22_interrupt_status2);
|
||||
|
||||
if (int_status2 & RFM22_is2_ipor)
|
||||
{ // the RF module has gone and done a reset - we need to re-initialize the rf module
|
||||
initialized = FALSE;
|
||||
power_on_reset = TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case RX_WAIT_PREAMBLE_MODE:
|
||||
|
||||
if (rfm22_int_timer >= timeout_ms)
|
||||
{ // assume somethings locked up
|
||||
rfm22_int_time_outs++;
|
||||
rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); // reset the RF module to rx mode
|
||||
tx_data_rd = tx_data_wr = 0; // wipe TX buffer
|
||||
break;
|
||||
}
|
||||
|
||||
// go to transmit mode if we have data to send and the channel is clear to transmit on
|
||||
if (tx_data_rd == 0 && tx_data_wr > 0 && rfm22_channelIsClear())
|
||||
{
|
||||
rfm22_setTxMode(TX_DATA_MODE); // transmit packet NOW
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case RX_WAIT_SYNC_MODE:
|
||||
|
||||
if (rfm22_int_timer >= timeout_sync_ms)
|
||||
{ // assume somethings locked up
|
||||
rfm22_int_time_outs++;
|
||||
rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); // reset the RF module to rx mode
|
||||
tx_data_rd = tx_data_wr = 0; // wipe TX buffer
|
||||
break;
|
||||
}
|
||||
|
||||
// go to transmit mode if we have data to send and the channel is clear to transmit on
|
||||
if (tx_data_rd == 0 && tx_data_wr > 0 && rfm22_channelIsClear())
|
||||
{
|
||||
rfm22_setTxMode(TX_DATA_MODE); // transmit packet NOW
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case RX_DATA_MODE:
|
||||
case TX_DATA_MODE:
|
||||
|
||||
if (rfm22_int_timer >= timeout_data_ms)
|
||||
{ // assume somethings locked up
|
||||
rfm22_int_time_outs++;
|
||||
rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); // reset the RF module to rx mode
|
||||
tx_data_rd = tx_data_wr = 0; // wipe TX buffer
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case TX_STREAM_MODE:
|
||||
|
||||
// todo:
|
||||
|
||||
break;
|
||||
|
||||
case TX_CARRIER_MODE:
|
||||
case TX_PN_MODE:
|
||||
|
||||
// if (rfm22_int_timer >= TX_TEST_MODE_TIMELIMIT_MS)
|
||||
// {
|
||||
// rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); // back to rx mode
|
||||
// tx_data_rd = tx_data_wr = 0; // wipe TX buffer
|
||||
// break;
|
||||
// }
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
// unknown mode - this should never happen, maybe we should do a complete CPU reset here?
|
||||
rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false); // to rx mode
|
||||
tx_data_rd = tx_data_wr = 0; // wipe TX buffer
|
||||
break;
|
||||
}
|
||||
|
||||
#if defined(RFM22_INT_TIMEOUT_DEBUG)
|
||||
if (prev_rfm22_int_time_outs != rfm22_int_time_outs)
|
||||
{
|
||||
prev_rfm22_int_time_outs = rfm22_int_time_outs;
|
||||
DEBUG_PRINTF("rf int timeouts %d\r\n", rfm22_int_time_outs);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// ************************************
|
||||
|
||||
void rfm22_TxDataByte_SetCallback(t_rfm22_TxDataByteCallback new_function)
|
||||
{
|
||||
tx_data_byte_callback_function = new_function;
|
||||
}
|
||||
|
||||
void rfm22_RxData_SetCallback(t_rfm22_RxDataCallback new_function)
|
||||
{
|
||||
rx_data_callback_function = new_function;
|
||||
}
|
||||
|
||||
// ************************************
|
||||
// reset the RF module
|
||||
|
||||
int rfm22_resetModule(uint8_t mode, uint32_t min_frequency_hz, uint32_t max_frequency_hz)
|
||||
{
|
||||
initialized = false;
|
||||
|
||||
#if defined(RFM22_EXT_INT_USE)
|
||||
rfm22_disableExtInt();
|
||||
#endif
|
||||
|
||||
power_on_reset = false;
|
||||
|
||||
// ****************
|
||||
|
||||
#if defined(RFM22_EXT_INT_USE)
|
||||
exec_using_spi = TRUE;
|
||||
#endif
|
||||
|
||||
// ****************
|
||||
// setup the SPI port
|
||||
|
||||
// chip select line HIGH
|
||||
PIOS_SPI_RC_PinSet(RFM22_PIOS_SPI, 1);
|
||||
|
||||
// set SPI port SCLK frequency .. 4.5MHz
|
||||
PIOS_SPI_SetClockSpeed(RFM22_PIOS_SPI, PIOS_SPI_PRESCALER_16);
|
||||
// set SPI port SCLK frequency .. 2.25MHz
|
||||
// PIOS_SPI_SetClockSpeed(RFM22_PIOS_SPI, PIOS_SPI_PRESCALER_32);
|
||||
|
||||
// set SPI port SCLK frequency .. 285kHz .. purely for hardware fault finding
|
||||
// PIOS_SPI_SetClockSpeed(RFM22_PIOS_SPI, PIOS_SPI_PRESCALER_256);
|
||||
|
||||
// ****************
|
||||
// software reset the RF chip .. following procedure according to Si4x3x Errata (rev. B)
|
||||
|
||||
rfm22_write(RFM22_op_and_func_ctrl1, RFM22_opfc1_swres); // software reset the radio
|
||||
|
||||
PIOS_DELAY_WaitmS(26); // wait 26ms
|
||||
|
||||
for (int i = 50; i > 0; i--)
|
||||
{
|
||||
PIOS_DELAY_WaitmS(1); // wait 1ms
|
||||
|
||||
// read the status registers
|
||||
int_status1 = rfm22_read(RFM22_interrupt_status1);
|
||||
int_status2 = rfm22_read(RFM22_interrupt_status2);
|
||||
if (int_status2 & RFM22_is2_ichiprdy) break;
|
||||
}
|
||||
|
||||
// ****************
|
||||
|
||||
// read status - clears interrupt
|
||||
device_status = rfm22_read(RFM22_device_status);
|
||||
int_status1 = rfm22_read(RFM22_interrupt_status1);
|
||||
int_status2 = rfm22_read(RFM22_interrupt_status2);
|
||||
ezmac_status = rfm22_read(RFM22_ezmac_status);
|
||||
|
||||
// disable all interrupts
|
||||
rfm22_write(RFM22_interrupt_enable1, 0x00);
|
||||
rfm22_write(RFM22_interrupt_enable2, 0x00);
|
||||
|
||||
// ****************
|
||||
|
||||
#if defined(RFM22_EXT_INT_USE)
|
||||
exec_using_spi = FALSE;
|
||||
#endif
|
||||
|
||||
// ****************
|
||||
|
||||
#if defined(RFM22_EXT_INT_USE)
|
||||
inside_ext_int = FALSE;
|
||||
#endif
|
||||
|
||||
rf_mode = mode;
|
||||
|
||||
device_status = int_status1 = int_status2 = ezmac_status = 0;
|
||||
|
||||
rssi = 0;
|
||||
rssi_dBm = -200;
|
||||
|
||||
tx_data_byte_callback_function = NULL;
|
||||
rx_data_callback_function = NULL;
|
||||
|
||||
rx_buffer_current = 0;
|
||||
rx_buffer_wr = 0;
|
||||
rx_packet_wr = 0;
|
||||
rx_packet_rssi_dBm = -200;
|
||||
rx_packet_afc_Hz = 0;
|
||||
|
||||
tx_data_addr = NULL;
|
||||
tx_data_rd = tx_data_wr = 0;
|
||||
|
||||
lookup_index = 0;
|
||||
ss_lookup_index = 0;
|
||||
|
||||
rf_bandwidth_used = 0;
|
||||
ss_rf_bandwidth_used = 0;
|
||||
|
||||
rfm22_int_timer = 0;
|
||||
rfm22_int_time_outs = 0;
|
||||
prev_rfm22_int_time_outs = 0;
|
||||
|
||||
hbsel = 0;
|
||||
frequency_step_size = 0.0f;
|
||||
|
||||
frequency_hop_channel = 0;
|
||||
|
||||
afc_correction = 0;
|
||||
afc_correction_Hz = 0;
|
||||
|
||||
temperature_reg = 0;
|
||||
|
||||
// set the TX power
|
||||
tx_power = RFM22_DEFAULT_RF_POWER;
|
||||
|
||||
tx_pwr = 0;
|
||||
|
||||
// ****************
|
||||
// read the RF chip ID bytes
|
||||
|
||||
device_type = rfm22_read(RFM22_DEVICE_TYPE) & RFM22_DT_MASK; // read the device type
|
||||
device_version = rfm22_read(RFM22_DEVICE_VERSION) & RFM22_DV_MASK; // read the device version
|
||||
|
||||
#if defined(RFM22_DEBUG)
|
||||
DEBUG_PRINTF("rf device type: %d\r\n", device_type);
|
||||
DEBUG_PRINTF("rf device version: %d\r\n", device_version);
|
||||
#endif
|
||||
|
||||
if (device_type != 0x08)
|
||||
{
|
||||
#if defined(RFM22_DEBUG)
|
||||
DEBUG_PRINTF("rf device type: INCORRECT - should be 0x08\r\n");
|
||||
#endif
|
||||
return -1; // incorrect RF module type
|
||||
}
|
||||
|
||||
// if (device_version != RFM22_DEVICE_VERSION_V2) // V2
|
||||
// return -2; // incorrect RF module version
|
||||
// if (device_version != RFM22_DEVICE_VERSION_A0) // A0
|
||||
// return -2; // incorrect RF module version
|
||||
if (device_version != RFM22_DEVICE_VERSION_B1) // B1
|
||||
{
|
||||
#if defined(RFM22_DEBUG)
|
||||
DEBUG_PRINTF("rf device version: INCORRECT\r\n");
|
||||
#endif
|
||||
return -2; // incorrect RF module version
|
||||
}
|
||||
|
||||
// ****************
|
||||
// set the minimum and maximum carrier frequency allowed
|
||||
|
||||
if (min_frequency_hz < RFM22_MIN_CARRIER_FREQUENCY_HZ) min_frequency_hz = RFM22_MIN_CARRIER_FREQUENCY_HZ;
|
||||
else
|
||||
if (min_frequency_hz > RFM22_MAX_CARRIER_FREQUENCY_HZ) min_frequency_hz = RFM22_MAX_CARRIER_FREQUENCY_HZ;
|
||||
|
||||
if (max_frequency_hz < RFM22_MIN_CARRIER_FREQUENCY_HZ) max_frequency_hz = RFM22_MIN_CARRIER_FREQUENCY_HZ;
|
||||
else
|
||||
if (max_frequency_hz > RFM22_MAX_CARRIER_FREQUENCY_HZ) max_frequency_hz = RFM22_MAX_CARRIER_FREQUENCY_HZ;
|
||||
|
||||
if (min_frequency_hz > max_frequency_hz)
|
||||
{ // swap them over
|
||||
uint32_t tmp = min_frequency_hz;
|
||||
min_frequency_hz = max_frequency_hz;
|
||||
max_frequency_hz = tmp;
|
||||
}
|
||||
|
||||
lower_carrier_frequency_limit_Hz = min_frequency_hz;
|
||||
upper_carrier_frequency_limit_Hz = max_frequency_hz;
|
||||
|
||||
// ****************
|
||||
// calibrate our RF module to be exactly on frequency .. different for every module
|
||||
|
||||
osc_load_cap = OSC_LOAD_CAP; // default
|
||||
rfm22_write(RFM22_xtal_osc_load_cap, osc_load_cap);
|
||||
|
||||
// ****************
|
||||
|
||||
// disable Low Duty Cycle Mode
|
||||
rfm22_write(RFM22_op_and_func_ctrl2, 0x00);
|
||||
|
||||
rfm22_write(RFM22_cpu_output_clk, RFM22_coc_1MHz); // 1MHz clock output
|
||||
|
||||
rfm22_write(RFM22_op_and_func_ctrl1, RFM22_opfc1_xton); // READY mode
|
||||
// rfm22_write(RFM22_op_and_func_ctrl1, RFM22_opfc1_pllon); // TUNE mode
|
||||
|
||||
// choose the 3 GPIO pin functions
|
||||
rfm22_write(RFM22_io_port_config, RFM22_io_port_default); // GPIO port use default value
|
||||
rfm22_write(RFM22_gpio0_config, RFM22_gpio0_config_drv3 | RFM22_gpio0_config_txstate); // GPIO0 = TX State (to control RF Switch)
|
||||
rfm22_write(RFM22_gpio1_config, RFM22_gpio1_config_drv3 | RFM22_gpio1_config_rxstate); // GPIO1 = RX State (to control RF Switch)
|
||||
rfm22_write(RFM22_gpio2_config, RFM22_gpio2_config_drv3 | RFM22_gpio2_config_cca); // GPIO2 = Clear Channel Assessment
|
||||
|
||||
// ****************
|
||||
|
||||
return 0; // OK
|
||||
}
|
||||
|
||||
// ************************************
|
||||
|
||||
int rfm22_init_scan_spectrum(uint32_t min_frequency_hz, uint32_t max_frequency_hz)
|
||||
{
|
||||
#if defined(RFM22_DEBUG)
|
||||
DEBUG_PRINTF("\r\nRF init scan spectrum\r\n");
|
||||
#endif
|
||||
|
||||
int res = rfm22_resetModule(RX_SCAN_SPECTRUM, min_frequency_hz, max_frequency_hz);
|
||||
if (res < 0)
|
||||
return res;
|
||||
|
||||
// rfm22_setSSBandwidth(0);
|
||||
rfm22_setSSBandwidth(1);
|
||||
|
||||
// FIFO mode, GFSK modulation
|
||||
uint8_t fd_bit = rfm22_read(RFM22_modulation_mode_control2) & RFM22_mmc2_fd;
|
||||
rfm22_write(RFM22_modulation_mode_control2, RFM22_mmc2_trclk_clk_none | RFM22_mmc2_dtmod_fifo | fd_bit | RFM22_mmc2_modtyp_gfsk);
|
||||
|
||||
rfm22_write(RFM22_cpu_output_clk, RFM22_coc_1MHz); // 1MHz clock output
|
||||
|
||||
rfm22_write(RFM22_rssi_threshold_clear_chan_indicator, 0);
|
||||
|
||||
rfm22_write(RFM22_preamble_detection_ctrl1, 31 << 3); // 31-nibbles rx preamble detection
|
||||
|
||||
// avoid packet detection
|
||||
rfm22_write(RFM22_data_access_control, RFM22_dac_enpacrx | RFM22_dac_encrc);
|
||||
rfm22_write(RFM22_header_control1, 0x0f);
|
||||
rfm22_write(RFM22_header_control2, 0x77);
|
||||
|
||||
rfm22_write(RFM22_sync_word3, SYNC_BYTE_1);
|
||||
rfm22_write(RFM22_sync_word2, SYNC_BYTE_2);
|
||||
rfm22_write(RFM22_sync_word1, SYNC_BYTE_3 ^ 0xff);
|
||||
rfm22_write(RFM22_sync_word0, SYNC_BYTE_4 ^ 0xff);
|
||||
|
||||
// all the bits to be checked
|
||||
rfm22_write(RFM22_header_enable3, 0xff);
|
||||
rfm22_write(RFM22_header_enable2, 0xff);
|
||||
rfm22_write(RFM22_header_enable1, 0xff);
|
||||
rfm22_write(RFM22_header_enable0, 0xff);
|
||||
|
||||
// rfm22_write(RFM22_frequency_hopping_step_size, 0); // set frequency hopping channel step size (multiples of 10kHz)
|
||||
|
||||
rfm22_setNominalCarrierFrequency(min_frequency_hz); // set our nominal carrier frequency
|
||||
|
||||
rfm22_write(RFM22_tx_power, RFM22_tx_pwr_lna_sw | 0); // set minimum tx power
|
||||
|
||||
rfm22_write(RFM22_agc_override1, RFM22_agc_ovr1_sgi | RFM22_agc_ovr1_agcen);
|
||||
|
||||
// rfm22_write(RFM22_vco_current_trimming, 0x7f);
|
||||
// rfm22_write(RFM22_vco_calibration_override, 0x40);
|
||||
// rfm22_write(RFM22_chargepump_current_trimming_override, 0x80);
|
||||
|
||||
#if defined(RFM22_EXT_INT_USE)
|
||||
// Enable RF module external interrupt
|
||||
rfm22_enableExtInt();
|
||||
#endif
|
||||
|
||||
rfm22_setRxMode(RX_SCAN_SPECTRUM, true);
|
||||
|
||||
initialized = true;
|
||||
|
||||
return 0; // OK
|
||||
}
|
||||
|
||||
// ************************************
|
||||
|
||||
int rfm22_init_tx_stream(uint32_t min_frequency_hz, uint32_t max_frequency_hz)
|
||||
{
|
||||
#if defined(RFM22_DEBUG)
|
||||
DEBUG_PRINTF("\r\nRF init TX stream\r\n");
|
||||
#endif
|
||||
|
||||
int res = rfm22_resetModule(TX_STREAM_MODE, min_frequency_hz, max_frequency_hz);
|
||||
if (res < 0)
|
||||
return res;
|
||||
|
||||
frequency_hop_step_size_reg = 0;
|
||||
|
||||
// set the RF datarate
|
||||
rfm22_setDatarate(RFM22_DEFAULT_RF_DATARATE, FALSE);
|
||||
|
||||
// FIFO mode, GFSK modulation
|
||||
uint8_t fd_bit = rfm22_read(RFM22_modulation_mode_control2) & RFM22_mmc2_fd;
|
||||
rfm22_write(RFM22_modulation_mode_control2, RFM22_mmc2_trclk_clk_none | RFM22_mmc2_dtmod_fifo | fd_bit | RFM22_mmc2_modtyp_gfsk);
|
||||
|
||||
// disable the internal Tx & Rx packet handlers (without CRC)
|
||||
rfm22_write(RFM22_data_access_control, 0);
|
||||
|
||||
rfm22_write(RFM22_preamble_length, TX_PREAMBLE_NIBBLES); // x-nibbles tx preamble
|
||||
rfm22_write(RFM22_preamble_detection_ctrl1, RX_PREAMBLE_NIBBLES << 3); // x-nibbles rx preamble detection
|
||||
|
||||
rfm22_write(RFM22_header_control1, RFM22_header_cntl1_bcen_none | RFM22_header_cntl1_hdch_none); // header control - we are not using the header
|
||||
rfm22_write(RFM22_header_control2, RFM22_header_cntl2_fixpklen | RFM22_header_cntl2_hdlen_none | RFM22_header_cntl2_synclen_32 | ((TX_PREAMBLE_NIBBLES >> 8) & 0x01)); // no header bytes, synchronization word length 3, 2 used, packet length not included in header (fixed packet length).
|
||||
|
||||
rfm22_write(RFM22_sync_word3, SYNC_BYTE_1); // sync word
|
||||
rfm22_write(RFM22_sync_word2, SYNC_BYTE_2); //
|
||||
|
||||
// rfm22_write(RFM22_modem_test, 0x01);
|
||||
|
||||
rfm22_write(RFM22_agc_override1, RFM22_agc_ovr1_agcen);
|
||||
// rfm22_write(RFM22_agc_override1, RFM22_agc_ovr1_sgi | RFM22_agc_ovr1_agcen);
|
||||
|
||||
rfm22_write(RFM22_frequency_hopping_step_size, frequency_hop_step_size_reg); // set frequency hopping channel step size (multiples of 10kHz)
|
||||
|
||||
rfm22_setNominalCarrierFrequency((min_frequency_hz + max_frequency_hz) / 2); // set our nominal carrier frequency
|
||||
|
||||
rfm22_write(RFM22_tx_power, RFM22_tx_pwr_papeaken | RFM22_tx_pwr_papeaklvl_0 | RFM22_tx_pwr_lna_sw | tx_power); // set the tx power
|
||||
// rfm22_write(RFM22_tx_power, RFM22_tx_pwr_lna_sw | tx_power); // set the tx power
|
||||
|
||||
// rfm22_write(RFM22_vco_current_trimming, 0x7f);
|
||||
// rfm22_write(RFM22_vco_calibration_override, 0x40);
|
||||
// rfm22_write(RFM22_chargepump_current_trimming_override, 0x80);
|
||||
|
||||
rfm22_write(RFM22_tx_fifo_control1, TX_FIFO_HI_WATERMARK); // TX FIFO Almost Full Threshold (0 - 63)
|
||||
rfm22_write(RFM22_tx_fifo_control2, TX_FIFO_LO_WATERMARK); // TX FIFO Almost Empty Threshold (0 - 63)
|
||||
|
||||
#if defined(RFM22_EXT_INT_USE)
|
||||
// Enable RF module external interrupt
|
||||
rfm22_enableExtInt();
|
||||
#endif
|
||||
|
||||
initialized = true;
|
||||
|
||||
return 0; // OK
|
||||
}
|
||||
|
||||
// ************************************
|
||||
|
||||
int rfm22_init_rx_stream(uint32_t min_frequency_hz, uint32_t max_frequency_hz)
|
||||
{
|
||||
#if defined(RFM22_DEBUG)
|
||||
DEBUG_PRINTF("\r\nRF init RX stream\r\n");
|
||||
#endif
|
||||
|
||||
int res = rfm22_resetModule(RX_WAIT_PREAMBLE_MODE, min_frequency_hz, max_frequency_hz);
|
||||
if (res < 0)
|
||||
return res;
|
||||
|
||||
frequency_hop_step_size_reg = 0;
|
||||
|
||||
// set the RF datarate
|
||||
rfm22_setDatarate(RFM22_DEFAULT_RF_DATARATE, FALSE);
|
||||
|
||||
// FIFO mode, GFSK modulation
|
||||
uint8_t fd_bit = rfm22_read(RFM22_modulation_mode_control2) & RFM22_mmc2_fd;
|
||||
rfm22_write(RFM22_modulation_mode_control2, RFM22_mmc2_trclk_clk_none | RFM22_mmc2_dtmod_fifo | fd_bit | RFM22_mmc2_modtyp_gfsk);
|
||||
|
||||
// disable the internal Tx & Rx packet handlers (without CRC)
|
||||
rfm22_write(RFM22_data_access_control, 0);
|
||||
|
||||
rfm22_write(RFM22_preamble_length, TX_PREAMBLE_NIBBLES); // x-nibbles tx preamble
|
||||
rfm22_write(RFM22_preamble_detection_ctrl1, RX_PREAMBLE_NIBBLES << 3); // x-nibbles rx preamble detection
|
||||
|
||||
rfm22_write(RFM22_header_control1, RFM22_header_cntl1_bcen_none | RFM22_header_cntl1_hdch_none); // header control - we are not using the header
|
||||
rfm22_write(RFM22_header_control2, RFM22_header_cntl2_fixpklen | RFM22_header_cntl2_hdlen_none | RFM22_header_cntl2_synclen_32 | ((TX_PREAMBLE_NIBBLES >> 8) & 0x01)); // no header bytes, synchronization word length 3, 2 used, packet length not included in header (fixed packet length).
|
||||
|
||||
rfm22_write(RFM22_sync_word3, SYNC_BYTE_1); // sync word
|
||||
rfm22_write(RFM22_sync_word2, SYNC_BYTE_2); //
|
||||
|
||||
// no header bits to be checked
|
||||
rfm22_write(RFM22_header_enable3, 0x00);
|
||||
rfm22_write(RFM22_header_enable2, 0x00);
|
||||
rfm22_write(RFM22_header_enable1, 0x00);
|
||||
rfm22_write(RFM22_header_enable0, 0x00);
|
||||
|
||||
// rfm22_write(RFM22_modem_test, 0x01);
|
||||
|
||||
rfm22_write(RFM22_agc_override1, RFM22_agc_ovr1_agcen);
|
||||
// rfm22_write(RFM22_agc_override1, RFM22_agc_ovr1_sgi | RFM22_agc_ovr1_agcen);
|
||||
|
||||
rfm22_write(RFM22_frequency_hopping_step_size, frequency_hop_step_size_reg); // set frequency hopping channel step size (multiples of 10kHz)
|
||||
|
||||
rfm22_setNominalCarrierFrequency((min_frequency_hz + max_frequency_hz) / 2); // set our nominal carrier frequency
|
||||
|
||||
// rfm22_write(RFM22_vco_current_trimming, 0x7f);
|
||||
// rfm22_write(RFM22_vco_calibration_override, 0x40);
|
||||
// rfm22_write(RFM22_chargepump_current_trimming_override, 0x80);
|
||||
|
||||
rfm22_write(RFM22_rx_fifo_control, RX_FIFO_HI_WATERMARK); // RX FIFO Almost Full Threshold (0 - 63)
|
||||
|
||||
#if defined(RFM22_EXT_INT_USE)
|
||||
// Enable RF module external interrupt
|
||||
rfm22_enableExtInt();
|
||||
#endif
|
||||
|
||||
rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false);
|
||||
|
||||
initialized = true;
|
||||
|
||||
return 0; // OK
|
||||
}
|
||||
|
||||
// ************************************
|
||||
// Initialise this hardware layer module and the rf module
|
||||
|
||||
int rfm22_init_normal(uint32_t min_frequency_hz, uint32_t max_frequency_hz, uint32_t freq_hop_step_size)
|
||||
{
|
||||
#if defined(RFM22_DEBUG)
|
||||
DEBUG_PRINTF("\r\nRF init normal\r\n");
|
||||
#endif
|
||||
|
||||
int res = rfm22_resetModule(RX_WAIT_PREAMBLE_MODE, min_frequency_hz, max_frequency_hz);
|
||||
if (res < 0)
|
||||
return res;
|
||||
|
||||
// ****************
|
||||
|
||||
freq_hop_step_size /= 10000; // in 10kHz increments
|
||||
if (freq_hop_step_size > 255) freq_hop_step_size = 255;
|
||||
|
||||
frequency_hop_step_size_reg = freq_hop_step_size;
|
||||
|
||||
// ****************
|
||||
|
||||
// set the RF datarate
|
||||
rfm22_setDatarate(RFM22_DEFAULT_RF_DATARATE, TRUE);
|
||||
|
||||
// FIFO mode, GFSK modulation
|
||||
uint8_t fd_bit = rfm22_read(RFM22_modulation_mode_control2) & RFM22_mmc2_fd;
|
||||
rfm22_write(RFM22_modulation_mode_control2, RFM22_mmc2_trclk_clk_none | RFM22_mmc2_dtmod_fifo | fd_bit | RFM22_mmc2_modtyp_gfsk);
|
||||
|
||||
// setup to read the internal temperature sensor
|
||||
adc_config = RFM22_ac_adcsel_temp_sensor | RFM22_ac_adcref_bg; // ADC used to sample the temperature sensor
|
||||
rfm22_write(RFM22_adc_config, adc_config); //
|
||||
rfm22_write(RFM22_adc_sensor_amp_offset, 0); // adc offset
|
||||
rfm22_write(RFM22_temp_sensor_calib, RFM22_tsc_tsrange0 | RFM22_tsc_entsoffs); // temp sensor calibration .. –40C to +64C 0.5C resolution
|
||||
rfm22_write(RFM22_temp_value_offset, 0); // temp sensor offset
|
||||
rfm22_write(RFM22_adc_config, adc_config | RFM22_ac_adcstartbusy); // start an ADC conversion
|
||||
|
||||
rfm22_write(RFM22_rssi_threshold_clear_chan_indicator, (-90 + 122) * 2); // set the RSSI threshold interrupt to about -90dBm
|
||||
|
||||
// enable the internal Tx & Rx packet handlers (with CRC)
|
||||
// rfm22_write(RFM22_data_access_control, RFM22_dac_enpacrx | RFM22_dac_enpactx | RFM22_dac_encrc | RFM22_dac_crc_crc16);
|
||||
// enable the internal Tx & Rx packet handlers (without CRC)
|
||||
rfm22_write(RFM22_data_access_control, RFM22_dac_enpacrx | RFM22_dac_enpactx);
|
||||
|
||||
rfm22_write(RFM22_preamble_length, TX_PREAMBLE_NIBBLES); // x-nibbles tx preamble
|
||||
rfm22_write(RFM22_preamble_detection_ctrl1, RX_PREAMBLE_NIBBLES << 3); // x-nibbles rx preamble detection
|
||||
|
||||
rfm22_write(RFM22_header_control1, RFM22_header_cntl1_bcen_none | RFM22_header_cntl1_hdch_none); // header control - we are not using the header
|
||||
rfm22_write(RFM22_header_control2, RFM22_header_cntl2_hdlen_none | RFM22_header_cntl2_synclen_3210 | ((TX_PREAMBLE_NIBBLES >> 8) & 0x01)); // no header bytes, synchronization word length 3, 2, 1 & 0 used, packet length included in header.
|
||||
|
||||
rfm22_write(RFM22_sync_word3, SYNC_BYTE_1); // sync word
|
||||
rfm22_write(RFM22_sync_word2, SYNC_BYTE_2); //
|
||||
rfm22_write(RFM22_sync_word1, SYNC_BYTE_3); //
|
||||
rfm22_write(RFM22_sync_word0, SYNC_BYTE_4); //
|
||||
/*
|
||||
rfm22_write(RFM22_transmit_header3, 'p'); // set tx header
|
||||
rfm22_write(RFM22_transmit_header2, 'i'); //
|
||||
rfm22_write(RFM22_transmit_header1, 'p'); //
|
||||
rfm22_write(RFM22_transmit_header0, ' '); //
|
||||
|
||||
rfm22_write(RFM22_check_header3, 'p'); // set expected rx header
|
||||
rfm22_write(RFM22_check_header2, 'i'); //
|
||||
rfm22_write(RFM22_check_header1, 'p'); //
|
||||
rfm22_write(RFM22_check_header0, ' '); //
|
||||
|
||||
// all the bits to be checked
|
||||
rfm22_write(RFM22_header_enable3, 0xff);
|
||||
rfm22_write(RFM22_header_enable2, 0xff);
|
||||
rfm22_write(RFM22_header_enable1, 0xff);
|
||||
rfm22_write(RFM22_header_enable0, 0xff);
|
||||
*/ // no bits to be checked
|
||||
rfm22_write(RFM22_header_enable3, 0x00);
|
||||
rfm22_write(RFM22_header_enable2, 0x00);
|
||||
rfm22_write(RFM22_header_enable1, 0x00);
|
||||
rfm22_write(RFM22_header_enable0, 0x00);
|
||||
|
||||
// rfm22_write(RFM22_modem_test, 0x01);
|
||||
|
||||
rfm22_write(RFM22_agc_override1, RFM22_agc_ovr1_agcen);
|
||||
// rfm22_write(RFM22_agc_override1, RFM22_agc_ovr1_sgi | RFM22_agc_ovr1_agcen);
|
||||
|
||||
rfm22_write(RFM22_frequency_hopping_step_size, frequency_hop_step_size_reg); // set frequency hopping channel step size (multiples of 10kHz)
|
||||
|
||||
rfm22_setNominalCarrierFrequency((min_frequency_hz + max_frequency_hz) / 2); // set our nominal carrier frequency
|
||||
|
||||
rfm22_write(RFM22_tx_power, RFM22_tx_pwr_papeaken | RFM22_tx_pwr_papeaklvl_0 | RFM22_tx_pwr_lna_sw | tx_power); // set the tx power
|
||||
// rfm22_write(RFM22_tx_power, RFM22_tx_pwr_lna_sw | tx_power); // set the tx power
|
||||
|
||||
// rfm22_write(RFM22_vco_current_trimming, 0x7f);
|
||||
// rfm22_write(RFM22_vco_calibration_override, 0x40);
|
||||
// rfm22_write(RFM22_chargepump_current_trimming_override, 0x80);
|
||||
|
||||
rfm22_write(RFM22_tx_fifo_control1, TX_FIFO_HI_WATERMARK); // TX FIFO Almost Full Threshold (0 - 63)
|
||||
rfm22_write(RFM22_tx_fifo_control2, TX_FIFO_LO_WATERMARK); // TX FIFO Almost Empty Threshold (0 - 63)
|
||||
|
||||
rfm22_write(RFM22_rx_fifo_control, RX_FIFO_HI_WATERMARK); // RX FIFO Almost Full Threshold (0 - 63)
|
||||
|
||||
#if defined(RFM22_EXT_INT_USE)
|
||||
// Enable RF module external interrupt
|
||||
rfm22_enableExtInt();
|
||||
#endif
|
||||
|
||||
rfm22_setRxMode(RX_WAIT_PREAMBLE_MODE, false);
|
||||
|
||||
initialized = true;
|
||||
|
||||
return 0; // ok
|
||||
}
|
||||
|
||||
// ************************************
|
@ -1,326 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file saved_settings.c
|
||||
* @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> // memmove, memset
|
||||
|
||||
#include "crc.h"
|
||||
#include "gpio_in.h"
|
||||
#include "saved_settings.h"
|
||||
#include "main.h"
|
||||
|
||||
#if defined(PIOS_COM_DEBUG)
|
||||
#define SAVED_SETTINGS_DEBUG
|
||||
#endif
|
||||
|
||||
// *****************************************************************
|
||||
|
||||
// default aes 128-bit encryption key
|
||||
const uint8_t saved_settings_default_aes_key[16] = {0x65, 0x3b, 0x71, 0x89, 0x4a, 0xf4, 0xc8, 0xcb, 0x18, 0xd4, 0x9b, 0x4d, 0x4a, 0xbe, 0xc8, 0x37};
|
||||
|
||||
// *****************************************************************
|
||||
|
||||
#define pages 1 // number of flash pages to use
|
||||
|
||||
uint32_t eeprom_addr; // the address of the emulated EEPROM area in program flash area
|
||||
uint16_t eeprom_page_size; // flash page size
|
||||
|
||||
volatile t_saved_settings saved_settings __attribute__ ((aligned(4))); // a RAM copy of the settings stored in EEPROM
|
||||
t_saved_settings tmp_settings __attribute__ ((aligned(4)));
|
||||
|
||||
// *****************************************************************
|
||||
// Private functions
|
||||
|
||||
bool saved_settings_page_empty(int page)
|
||||
{ // return TRUE if the flash page is emtpy (erased), otherwise return FALSE
|
||||
|
||||
if (page < 0 || page >= pages)
|
||||
return FALSE;
|
||||
|
||||
__IO uint32_t *addr = (__IO uint32_t *)(eeprom_addr + eeprom_page_size * page);
|
||||
int32_t len = eeprom_page_size / 4;
|
||||
|
||||
for (int32_t i = len; i > 0; i--)
|
||||
if (*addr++ != 0xffffffff)
|
||||
return FALSE; // the page is not erased
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool saved_settings_settings_empty(uint32_t addr)
|
||||
{ // return TRUE if the settings flash area is emtpy (erased), otherwise return FALSE
|
||||
|
||||
__IO uint8_t *p = (__IO uint8_t *)addr;
|
||||
|
||||
for (int32_t i = sizeof(t_saved_settings); i > 0; i--)
|
||||
if (*p++ != 0xff)
|
||||
return FALSE; // the flash area is not empty/erased
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// *****************************************************************
|
||||
|
||||
int32_t saved_settings_read(void)
|
||||
{ // look for the last valid settings saved in EEPROM
|
||||
|
||||
uint32_t flash_addr;
|
||||
__IO uint8_t *p1;
|
||||
uint8_t *p2;
|
||||
|
||||
flash_addr = eeprom_addr;
|
||||
|
||||
if (saved_settings_settings_empty(flash_addr))
|
||||
{
|
||||
#if defined(SAVED_SETTINGS_DEBUG)
|
||||
DEBUG_PRINTF("settings Read, no settings found at %08X\r\n", flash_addr);
|
||||
#endif
|
||||
|
||||
return -1; // no settings found at the specified addr
|
||||
}
|
||||
|
||||
// copy the data from program flash area into temp settings area
|
||||
p1 = (__IO uint8_t *)flash_addr;
|
||||
p2 = (uint8_t *)&tmp_settings;
|
||||
for (int32_t i = 0; i < sizeof(t_saved_settings); i++)
|
||||
*p2++ = *p1++;
|
||||
|
||||
// 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));
|
||||
if (crc2 != crc1)
|
||||
{
|
||||
#if defined(SAVED_SETTINGS_DEBUG)
|
||||
DEBUG_PRINTF("settings Read crc error: %08X %08X\r\n", crc1, crc2);
|
||||
#endif
|
||||
|
||||
return -2; // error
|
||||
}
|
||||
|
||||
memmove((void *)&saved_settings, (void *)&tmp_settings, sizeof(t_saved_settings));
|
||||
|
||||
#if defined(SAVED_SETTINGS_DEBUG)
|
||||
DEBUG_PRINTF("settings Read OK!\r\n");
|
||||
#endif
|
||||
|
||||
return 0; // OK
|
||||
}
|
||||
|
||||
// *****************************************************************
|
||||
// Public functions
|
||||
|
||||
int32_t saved_settings_save(void)
|
||||
{ // save the settings into EEPROM
|
||||
|
||||
FLASH_Status fs;
|
||||
uint32_t flash_addr;
|
||||
uint8_t *p1;
|
||||
__IO uint8_t *p2;
|
||||
uint32_t *p3;
|
||||
bool do_save;
|
||||
|
||||
// size of the settings aligned to 4 bytes
|
||||
// uint16_t settings_size = (uint16_t)(sizeof(t_saved_settings) + 3) & 0xfffc;
|
||||
|
||||
// address of settings in FLASH area
|
||||
flash_addr = eeprom_addr;
|
||||
|
||||
// *****************************************
|
||||
// calculate and add the CRC
|
||||
|
||||
saved_settings.crc = 0;
|
||||
saved_settings.crc = updateCRC32Data(0xffffffff, (void *)&saved_settings, sizeof(t_saved_settings));
|
||||
|
||||
// *****************************************
|
||||
// first check to see if we need to save the settings
|
||||
|
||||
p1 = (uint8_t *)&saved_settings;
|
||||
p2 = (__IO uint8_t *)flash_addr;
|
||||
do_save = FALSE;
|
||||
|
||||
for (int32_t i = 0; i < sizeof(t_saved_settings); i++)
|
||||
{
|
||||
if (*p1++ != *p2++)
|
||||
{ // we need to save the settings
|
||||
do_save = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!do_save)
|
||||
{
|
||||
#if defined(SAVED_SETTINGS_DEBUG)
|
||||
DEBUG_PRINTF("settings already saved OK\r\n");
|
||||
#endif
|
||||
|
||||
return 0; // settings already saved .. all OK
|
||||
}
|
||||
|
||||
// *****************************************
|
||||
|
||||
// Unlock the Flash Program Erase controller
|
||||
FLASH_Unlock();
|
||||
|
||||
if (!saved_settings_page_empty(0))
|
||||
{ // erase the page
|
||||
#if defined(SAVED_SETTINGS_DEBUG)
|
||||
DEBUG_PRINTF("settings erasing page .. ");
|
||||
#endif
|
||||
|
||||
fs = FLASH_ErasePage(eeprom_addr);
|
||||
if (fs != FLASH_COMPLETE)
|
||||
{ // error
|
||||
FLASH_Lock();
|
||||
|
||||
#if defined(SAVED_SETTINGS_DEBUG)
|
||||
DEBUG_PRINTF("error %d\r\n", fs);
|
||||
#endif
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if defined(SAVED_SETTINGS_DEBUG)
|
||||
DEBUG_PRINTF("OK\r\n");
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined(SAVED_SETTINGS_DEBUG)
|
||||
DEBUG_PRINTF("settings page already erased\r\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
// *****************************************
|
||||
// save the settings into flash area (emulated EEPROM area)
|
||||
|
||||
p1 = (uint8_t *)&saved_settings;
|
||||
p3 = (uint32_t *)flash_addr;
|
||||
|
||||
// write 4 bytes at a time into program flash area (emulated EEPROM area)
|
||||
for (int32_t i = 0; i < sizeof(t_saved_settings); p3++)
|
||||
{
|
||||
uint32_t value = 0;
|
||||
if (i < sizeof(t_saved_settings)) value |= (uint32_t)*p1++ << 0; else value |= 0x000000ff; i++;
|
||||
if (i < sizeof(t_saved_settings)) value |= (uint32_t)*p1++ << 8; else value |= 0x0000ff00; i++;
|
||||
if (i < sizeof(t_saved_settings)) value |= (uint32_t)*p1++ << 16; else value |= 0x00ff0000; i++;
|
||||
if (i < sizeof(t_saved_settings)) value |= (uint32_t)*p1++ << 24; else value |= 0xff000000; i++;
|
||||
|
||||
fs = FLASH_ProgramWord((uint32_t)p3, value); // write a 32-bit value
|
||||
if (fs != FLASH_COMPLETE)
|
||||
{
|
||||
FLASH_Lock();
|
||||
|
||||
#if defined(SAVED_SETTINGS_DEBUG)
|
||||
DEBUG_PRINTF("settings FLASH_ProgramWord error: %d\r\n", fs);
|
||||
#endif
|
||||
|
||||
return -2; // error
|
||||
}
|
||||
}
|
||||
|
||||
// Lock the Flash Program Erase controller
|
||||
FLASH_Lock();
|
||||
|
||||
// *****************************************
|
||||
// now error check it by reading it back (simple compare)
|
||||
|
||||
p1 = (uint8_t *)&saved_settings;
|
||||
p2 = (__IO uint8_t *)flash_addr;
|
||||
|
||||
for (int32_t i = 0; i < sizeof(t_saved_settings); i++)
|
||||
{
|
||||
if (*p1++ != *p2++)
|
||||
{
|
||||
#if defined(SAVED_SETTINGS_DEBUG)
|
||||
DEBUG_PRINTF("settings WriteSettings compare error\r\n");
|
||||
#endif
|
||||
|
||||
return -3; // error
|
||||
}
|
||||
}
|
||||
|
||||
// *****************************************
|
||||
|
||||
#if defined(SAVED_SETTINGS_DEBUG)
|
||||
DEBUG_PRINTF("settings Save OK!\r\n");
|
||||
#endif
|
||||
|
||||
return 0; // OK
|
||||
}
|
||||
|
||||
void saved_settings_init(void)
|
||||
{
|
||||
// **********
|
||||
// determine emulated EEPROM details
|
||||
|
||||
if (flash_size < 256000)
|
||||
eeprom_page_size = 1024; // 1 kByte
|
||||
else
|
||||
eeprom_page_size = 2048; // 2 kByte
|
||||
|
||||
// place emulated eeprom at end of program flash area
|
||||
eeprom_addr = (0x08000000 + flash_size) - (eeprom_page_size * pages);
|
||||
|
||||
#if defined(SAVED_SETTINGS_DEBUG)
|
||||
DEBUG_PRINTF("\r\n");
|
||||
DEBUG_PRINTF("settings eeprom addr: %08x\r\n", eeprom_addr);
|
||||
DEBUG_PRINTF("settings eeprom page size: %u\r\n", eeprom_page_size);
|
||||
DEBUG_PRINTF("settings eeprom pages: %u\r\n", pages);
|
||||
#endif
|
||||
|
||||
// **********
|
||||
// default settings
|
||||
|
||||
memset((void *)&saved_settings, 0xff, sizeof(t_saved_settings));
|
||||
|
||||
saved_settings.mode = MODE_NORMAL;
|
||||
|
||||
saved_settings.destination_id = 0;
|
||||
|
||||
saved_settings.frequency_band = FREQBAND_UNKNOWN;
|
||||
|
||||
saved_settings.rf_xtal_cap = 0x7f;
|
||||
|
||||
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.rts_time = 10; // ms
|
||||
|
||||
// saved_settings.crc = 0;
|
||||
// saved_settings.crc = updateCRC32Data(0xffffffff, (void *)&saved_settings, sizeof(t_saved_settings));
|
||||
|
||||
// **********
|
||||
|
||||
// Lock the Flash Program Erase controller
|
||||
FLASH_Lock();
|
||||
|
||||
saved_settings_read();
|
||||
|
||||
// **********
|
||||
}
|
||||
|
||||
// *****************************************************************
|
@ -1,156 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file stopwatch.c
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief Stop watch function
|
||||
* @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 "stopwatch.h"
|
||||
#include "main.h"
|
||||
|
||||
// *****************************************************************************
|
||||
|
||||
uint32_t resolution_us = 0;
|
||||
|
||||
// *****************************************************************************
|
||||
// initialise the stopwatch
|
||||
|
||||
void STOPWATCH_init(uint32_t resolution)
|
||||
{
|
||||
resolution_us = resolution;
|
||||
|
||||
if (resolution_us == 0)
|
||||
return;
|
||||
|
||||
// enable timer clock
|
||||
switch ((uint32_t)STOPWATCH_TIMER)
|
||||
{
|
||||
case (uint32_t)TIM1: RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); break;
|
||||
case (uint32_t)TIM2: RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); break;
|
||||
case (uint32_t)TIM3: RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); break;
|
||||
case (uint32_t)TIM4: RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); break;
|
||||
#ifdef STM32F10X_HD
|
||||
case (uint32_t)TIM5: RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE); break;
|
||||
case (uint32_t)TIM6: RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE); break;
|
||||
case (uint32_t)TIM7: RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7, ENABLE); break;
|
||||
case (uint32_t)TIM8: RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8, ENABLE); break;
|
||||
#endif
|
||||
}
|
||||
|
||||
// time base configuration
|
||||
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
|
||||
TIM_TimeBaseStructure.TIM_Period = 0xffff; // max period
|
||||
TIM_TimeBaseStructure.TIM_Prescaler = ((PIOS_MASTER_CLOCK / 1000000) * resolution_us) - 1; // <resolution> uS accuracy @ 72 MHz
|
||||
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
|
||||
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
|
||||
TIM_TimeBaseInit(STOPWATCH_TIMER, &TIM_TimeBaseStructure);
|
||||
|
||||
// enable interrupt request
|
||||
TIM_ITConfig(STOPWATCH_TIMER, TIM_IT_Update, ENABLE);
|
||||
|
||||
// start counter
|
||||
TIM_Cmd(STOPWATCH_TIMER, ENABLE);
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// timer interrupt
|
||||
/*
|
||||
#ifdef STM32F10X_MD
|
||||
#if (STOPWATCH_TIMER == TIM1)
|
||||
void TIM1_IRQHandler(void)
|
||||
#if (STOPWATCH_TIMER == TIM2)
|
||||
void TIM2_IRQHandler(void)
|
||||
#elif (STOPWATCH_TIMER == TIM3)
|
||||
void TIM3_IRQHandler(void)
|
||||
#elif (STOPWATCH_TIMER == TIM4)
|
||||
void TIM4_IRQHandler(void)
|
||||
#endif
|
||||
#endif
|
||||
#ifdef STM32F10X_HD
|
||||
#if (STOPWATCH_TIMER == TIM1)
|
||||
void TIM1_IRQHandler(void)
|
||||
#if (STOPWATCH_TIMER == TIM2)
|
||||
void TIM2_IRQHandler(void)
|
||||
#elif (STOPWATCH_TIMER == TIM3)
|
||||
void TIM3_IRQHandler(void)
|
||||
#elif (STOPWATCH_TIMER == TIM4)
|
||||
void TIM4_IRQHandler(void)
|
||||
#elif (STOPWATCH_TIMER == TIM5)
|
||||
void TIM5_IRQHandler(void)
|
||||
#elif (STOPWATCH_TIMER == TIM6)
|
||||
void TIM6_IRQHandler(void)
|
||||
#elif (STOPWATCH_TIMER == TIM7)
|
||||
void TIM7_IRQHandler(void)
|
||||
#elif (STOPWATCH_TIMER == TIM8)
|
||||
void TIM8_IRQHandler(void)
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
|
||||
}
|
||||
*/
|
||||
// *****************************************************************************
|
||||
// resets the stopwatch
|
||||
|
||||
void STOPWATCH_reset(void)
|
||||
{
|
||||
if (resolution_us > 0)
|
||||
{ // reset the counter
|
||||
STOPWATCH_TIMER->CNT = 1; // set to 1 instead of 0 to avoid new IRQ request
|
||||
TIM_ClearITPendingBit(STOPWATCH_TIMER, TIM_IT_Update);
|
||||
}
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// returns the timer count since the last STOPWATCH_reset() call
|
||||
// return 0xffffffff if counter overrun or not initialised
|
||||
|
||||
uint32_t STOPWATCH_get_count(void)
|
||||
{
|
||||
uint32_t value = STOPWATCH_TIMER->CNT; // get counter value ASAP
|
||||
|
||||
if (resolution_us == 0)
|
||||
return 0xffffffff; // not initialized
|
||||
|
||||
if (TIM_GetITStatus(STOPWATCH_TIMER, TIM_IT_Update) != RESET)
|
||||
return 0xffffffff; // timer overfloaw
|
||||
|
||||
return value; // return the timer count
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// returns number of us since the last STOPWATCH_reset() call
|
||||
// return 0xffffffff if counter overrun or not initialised
|
||||
|
||||
uint32_t STOPWATCH_get_us(void)
|
||||
{
|
||||
uint32_t value = STOPWATCH_TIMER->CNT; // get counter value ASAP
|
||||
|
||||
if (resolution_us == 0)
|
||||
return 0xffffffff; // not initialized
|
||||
|
||||
if (TIM_GetITStatus(STOPWATCH_TIMER, TIM_IT_Update) != RESET)
|
||||
return 0xffffffff; // timer overfloaw
|
||||
|
||||
return (value * resolution_us); // return number of micro seconds
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
@ -1,122 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file stream.c
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief Sends or Receives a continuous packet stream to/from the remote unit
|
||||
* @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> // memmove
|
||||
|
||||
#include "main.h"
|
||||
#include "rfm22b.h"
|
||||
#include "fifo_buffer.h"
|
||||
#include "aes.h"
|
||||
#include "crc.h"
|
||||
#include "saved_settings.h"
|
||||
#include "stream.h"
|
||||
|
||||
#if defined(PIOS_COM_DEBUG)
|
||||
#define STREAM_DEBUG
|
||||
#endif
|
||||
|
||||
// *************************************************************
|
||||
// can be called from an interrupt if you wish
|
||||
// call this once every ms
|
||||
|
||||
void stream_1ms_tick(void)
|
||||
{
|
||||
if (booting) return;
|
||||
|
||||
if (saved_settings.mode == MODE_STREAM_TX)
|
||||
{
|
||||
}
|
||||
else
|
||||
if (saved_settings.mode == MODE_STREAM_RX)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
// *************************************************************
|
||||
// return a byte for the tx packet transmission.
|
||||
//
|
||||
// return value < 0 if no more bytes available, otherwise return byte to be sent
|
||||
|
||||
int16_t stream_TxDataByteCallback(void)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
// *************************************************************
|
||||
// we are being given a block of received bytes
|
||||
//
|
||||
// return TRUE to continue current packet receive, otherwise return FALSE to halt current packet reception
|
||||
|
||||
bool stream_RxDataCallback(void *data, uint8_t len)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// *************************************************************
|
||||
// call this from the main loop (not interrupt) as often as possible
|
||||
|
||||
void stream_process(void)
|
||||
{
|
||||
if (booting) return;
|
||||
|
||||
if (saved_settings.mode == MODE_STREAM_TX)
|
||||
{
|
||||
}
|
||||
else
|
||||
if (saved_settings.mode == MODE_STREAM_RX)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
// *************************************************************
|
||||
|
||||
void stream_deinit(void)
|
||||
{
|
||||
}
|
||||
|
||||
void stream_init(uint32_t our_sn)
|
||||
{
|
||||
#if defined(STREAM_DEBUG)
|
||||
DEBUG_PRINTF("\r\nSTREAM init\r\n");
|
||||
#endif
|
||||
|
||||
if (saved_settings.mode == MODE_STREAM_TX)
|
||||
rfm22_init_tx_stream(saved_settings.min_frequency_Hz, saved_settings.max_frequency_Hz);
|
||||
else
|
||||
if (saved_settings.mode == MODE_STREAM_RX)
|
||||
rfm22_init_rx_stream(saved_settings.min_frequency_Hz, saved_settings.max_frequency_Hz);
|
||||
|
||||
rfm22_TxDataByte_SetCallback(stream_TxDataByteCallback);
|
||||
rfm22_RxData_SetCallback(stream_RxDataCallback);
|
||||
|
||||
rfm22_setFreqCalibration(saved_settings.rf_xtal_cap);
|
||||
rfm22_setNominalCarrierFrequency(saved_settings.frequency_Hz);
|
||||
rfm22_setDatarate(saved_settings.max_rf_bandwidth, FALSE);
|
||||
rfm22_setTxPower(saved_settings.max_tx_power);
|
||||
|
||||
rfm22_setTxStream(); // TEST ONLY
|
||||
}
|
||||
|
||||
// *************************************************************
|
@ -1,218 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file transparent_comms.c
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief Serial communication port handling routines
|
||||
* @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 "transparent_comms.h"
|
||||
#include "packet_handler.h"
|
||||
#include "saved_settings.h"
|
||||
#include "main.h"
|
||||
#include "pios_usb.h" /* PIOS_USB_* */
|
||||
|
||||
#if defined(PIOS_COM_DEBUG)
|
||||
#define TRANS_DEBUG
|
||||
#endif
|
||||
|
||||
// *****************************************************************************
|
||||
// local variables
|
||||
|
||||
uint32_t trans_previous_com_port = 0;
|
||||
|
||||
volatile uint16_t trans_rx_timer = 0;
|
||||
volatile uint16_t trans_tx_timer = 0;
|
||||
|
||||
uint8_t trans_temp_buffer1[128];
|
||||
|
||||
uint8_t trans_temp_buffer2[128];
|
||||
uint16_t trans_temp_buffer2_wr;
|
||||
|
||||
// *****************************************************************************
|
||||
// can be called from an interrupt if you wish
|
||||
|
||||
void trans_1ms_tick(void)
|
||||
{ // call this once every 1ms
|
||||
if (trans_rx_timer < 0xffff) trans_rx_timer++;
|
||||
if (trans_tx_timer < 0xffff) trans_tx_timer++;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// call this as often as possible - not from an interrupt
|
||||
|
||||
void trans_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.
|
||||
uint32_t comm_port = PIOS_COM_SERIAL; // default to using the usart comm-port
|
||||
|
||||
#if defined(PIOS_INCLUDE_USB)
|
||||
if (PIOS_USB_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 (trans_previous_com_port == 0 && trans_previous_com_port != comm_port)
|
||||
{ // the local communications port has changed .. remove any data in the buffers
|
||||
trans_temp_buffer2_wr = 0;
|
||||
}
|
||||
else
|
||||
if (usb_comms)
|
||||
{ // we're using the USB for comms - keep the USART rx buffer empty
|
||||
uint8_t c;
|
||||
while (PIOS_COM_ReceiveBuffer(PIOS_COM_SERIAL, &c, 1, 0) > 0);
|
||||
}
|
||||
|
||||
trans_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 down the comm-port to the RF packet handler TX buffer
|
||||
|
||||
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(connection_index);
|
||||
|
||||
// set the USART RTS handshaking line
|
||||
if (!usb_comms)
|
||||
{
|
||||
if (ph_num < 32 || !ph_connected(connection_index))
|
||||
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 the size of the temp buffer
|
||||
if (ph_num > sizeof(trans_temp_buffer1))
|
||||
ph_num = sizeof(trans_temp_buffer1);
|
||||
|
||||
// copy data received down the comm-port into our temp buffer
|
||||
register uint16_t bytes_saved = 0;
|
||||
bytes_saved = PIOS_COM_ReceiveBuffer(comm_port, trans_temp_buffer1, ph_num, 0);
|
||||
|
||||
// put the received comm-port data bytes into the RF packet handler TX buffer
|
||||
if (bytes_saved > 0)
|
||||
{
|
||||
trans_rx_timer = 0;
|
||||
ph_putData(connection_index, trans_temp_buffer1, bytes_saved);
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // empty the comm-ports rx buffer
|
||||
uint8_t c;
|
||||
while (PIOS_COM_ReceiveBuffer(comm_port, &c, 1, 0) > 0);
|
||||
}
|
||||
|
||||
// ********************
|
||||
// send the data received via the RF link out the comm-port
|
||||
|
||||
if (saved_settings.mode == MODE_NORMAL || saved_settings.mode == MODE_STREAM_RX)
|
||||
{
|
||||
if (trans_temp_buffer2_wr < sizeof(trans_temp_buffer2))
|
||||
{
|
||||
// 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 buffer
|
||||
if (ph_num > sizeof(trans_temp_buffer2) - trans_temp_buffer2_wr)
|
||||
ph_num = sizeof(trans_temp_buffer2) - trans_temp_buffer2_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, trans_temp_buffer2 + trans_temp_buffer2_wr, ph_num);
|
||||
trans_temp_buffer2_wr += ph_num;
|
||||
}
|
||||
}
|
||||
|
||||
#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
|
||||
trans_temp_buffer2_wr = 0;
|
||||
trans_tx_timer = 0;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (trans_temp_buffer2_wr > 0)
|
||||
{ // we have data in our temp buffer that needs sending out the comm-port
|
||||
|
||||
if (usb_comms || (!usb_comms && GPIO_IN(SERIAL_CTS_PIN)))
|
||||
{ // we are OK to send the data out the comm-port
|
||||
|
||||
// send the data out the comm-port
|
||||
int32_t res = PIOS_COM_SendBufferNonBlocking(comm_port, trans_temp_buffer2, trans_temp_buffer2_wr); // this one doesn't work properly with USB :(
|
||||
if (res >= 0)
|
||||
{ // data was sent out the comm-port OK .. remove the sent data from the temp buffer
|
||||
trans_temp_buffer2_wr = 0;
|
||||
trans_tx_timer = 0;
|
||||
}
|
||||
else
|
||||
{ // failed to send the data out the comm-port
|
||||
#if defined(TRANS_DEBUG)
|
||||
DEBUG_PRINTF("PIOS_COM_SendBuffer %d %d\r\n", trans_temp_buffer2_wr, res);
|
||||
#endif
|
||||
|
||||
if (trans_tx_timer >= 5000)
|
||||
trans_temp_buffer2_wr = 0; // seems we can't send our data for at least the last 5 seconds - delete it
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // empty the buffer
|
||||
trans_temp_buffer2_wr = 0;
|
||||
trans_tx_timer = 0;
|
||||
}
|
||||
|
||||
// ********************
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
|
||||
void trans_init(void)
|
||||
{
|
||||
trans_previous_com_port = 0;
|
||||
|
||||
trans_temp_buffer2_wr = 0;
|
||||
|
||||
trans_rx_timer = 0;
|
||||
trans_tx_timer = 0;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
@ -1,71 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file watchdog.c
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief Modem packet handling routines
|
||||
* @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 "pios.h"
|
||||
#include "stm32f10x_iwdg.h"
|
||||
#include "stm32f10x_dbgmcu.h"
|
||||
|
||||
/**
|
||||
* @brief Initialize the watchdog timer for a specified timeout
|
||||
*
|
||||
* It is important to note that this function returns the achieved timeout
|
||||
* for this hardware. For hardware indendence this should be checked when
|
||||
* scheduling updates. Other hardware dependent details may need to be
|
||||
* considered such as a window time which sets a minimum update time,
|
||||
* and this function should return a recommended delay for clearing.
|
||||
*
|
||||
* For the STM32 nominal clock rate is 32 khz, but for the maximum clock rate of
|
||||
* 60 khz and a prescalar of 4 yields a clock rate of 15 khz. The delay that is
|
||||
* set in the watchdog assumes the nominal clock rate, but the delay for FreeRTOS
|
||||
* to use is 75% of the minimal delay.
|
||||
*
|
||||
* @param[in] delayMs The delay period in ms
|
||||
* @returns Maximum recommended delay between updates
|
||||
*/
|
||||
uint16_t watchdog_Init(uint16_t delayMs)
|
||||
{
|
||||
uint16_t delay = ((uint32_t)delayMs * 60) / 16;
|
||||
if (delay > 0x0fff)
|
||||
delay = 0x0fff;
|
||||
|
||||
DBGMCU_Config(DBGMCU_IWDG_STOP, ENABLE); // make the watchdog stop counting in debug mode
|
||||
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
|
||||
IWDG_SetPrescaler(IWDG_Prescaler_16);
|
||||
IWDG_SetReload(delay);
|
||||
IWDG_ReloadCounter();
|
||||
IWDG_Enable();
|
||||
|
||||
return ((((uint32_t)delay * 16) / 60) * .75f);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear the watchdog timer
|
||||
*
|
||||
* This function must be called at the appropriate delay to prevent a reset event occuring
|
||||
*/
|
||||
void watchdog_Clear(void)
|
||||
{
|
||||
IWDG_ReloadCounter();
|
||||
}
|
@ -1,230 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
version="1.1"
|
||||
width="48"
|
||||
height="48"
|
||||
id="svg2474">
|
||||
<metadata
|
||||
id="metadata33">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs2476">
|
||||
<linearGradient
|
||||
id="linearGradient3533">
|
||||
<stop
|
||||
id="stop3535"
|
||||
style="stop-color:#93b9dd;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop3545"
|
||||
style="stop-color:#6396cd;stop-opacity:1"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3266">
|
||||
<stop
|
||||
id="stop3268"
|
||||
style="stop-color:#387ab8;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop3270"
|
||||
style="stop-color:#387ab8;stop-opacity:0"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3276">
|
||||
<stop
|
||||
id="stop3278"
|
||||
style="stop-color:#6396cd;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop3280"
|
||||
style="stop-color:#83acd5;stop-opacity:0"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
x1="108.5625"
|
||||
y1="102.78125"
|
||||
x2="108.5625"
|
||||
y2="71.78125"
|
||||
id="linearGradient5497"
|
||||
xlink:href="#linearGradient5491"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(-95.99949,-49.00038)" />
|
||||
<linearGradient
|
||||
id="linearGradient5491">
|
||||
<stop
|
||||
id="stop5493"
|
||||
style="stop-color:#ffffff;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop5495"
|
||||
style="stop-color:#ffffff;stop-opacity:0"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
x1="102.5625"
|
||||
y1="49.78125"
|
||||
x2="103.5625"
|
||||
y2="72.78125"
|
||||
id="linearGradient5480"
|
||||
xlink:href="#linearGradient5474"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(-95.99949,-49.00038)" />
|
||||
<linearGradient
|
||||
id="linearGradient5474">
|
||||
<stop
|
||||
id="stop5476"
|
||||
style="stop-color:#ffffff;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop5478"
|
||||
style="stop-color:#ffffff;stop-opacity:0"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
x1="118.47968"
|
||||
y1="55.060318"
|
||||
x2="118.47968"
|
||||
y2="91.941895"
|
||||
id="linearGradient4593-5-8-1-5-2"
|
||||
xlink:href="#linearGradient3533"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(-100.99949,-49.00038)" />
|
||||
<linearGradient
|
||||
x1="34.980953"
|
||||
y1="53.837799"
|
||||
x2="35.996098"
|
||||
y2="83.57618"
|
||||
id="linearGradient4593-5-8-1-5-2-3"
|
||||
xlink:href="#linearGradient3533"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(-5,0)" />
|
||||
<radialGradient
|
||||
cx="33.875"
|
||||
cy="197.29688"
|
||||
r="4.84375"
|
||||
fx="33.875"
|
||||
fy="197.29688"
|
||||
id="radialGradient5147-5"
|
||||
xlink:href="#linearGradient6462-6-8-548-9-2-7"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1,0,0,0.33870968,0,130.47051)" />
|
||||
<linearGradient
|
||||
id="linearGradient6462-6-8-548-9-2-7">
|
||||
<stop
|
||||
id="stop6464-5-9-94-5-4-4"
|
||||
style="stop-color:#000000;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop6466-3-6-1-7-2-8"
|
||||
style="stop-color:#000000;stop-opacity:0"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient6462-6-8-548-9-5">
|
||||
<stop
|
||||
id="stop6464-5-9-94-5-8"
|
||||
style="stop-color:#000000;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop6466-3-6-1-7-5"
|
||||
style="stop-color:#000000;stop-opacity:0"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
cx="33.875"
|
||||
cy="197.29688"
|
||||
r="4.84375"
|
||||
fx="33.875"
|
||||
fy="197.29688"
|
||||
id="radialGradient6081"
|
||||
xlink:href="#linearGradient6462-6-8-548-9-5"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1,0,0,0.33870968,0,130.47051)" />
|
||||
<linearGradient
|
||||
x1="42.030777"
|
||||
y1="84.719109"
|
||||
x2="53.808601"
|
||||
y2="73.263672"
|
||||
id="linearGradient4008"
|
||||
xlink:href="#linearGradient3276"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(-5,0)" />
|
||||
<linearGradient
|
||||
x1="39.843277"
|
||||
y1="83.781609"
|
||||
x2="50.683601"
|
||||
y2="75.138672"
|
||||
id="linearGradient4018"
|
||||
xlink:href="#linearGradient3266"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
</defs>
|
||||
<path
|
||||
d="m 38.71875,197.29687 a 4.84375,1.640625 0 1 1 -9.6875,0 4.84375,1.640625 0 1 1 9.6875,0 z"
|
||||
transform="matrix(3.3032251,0,0,1.6761866,-89.458749,-288.73764)"
|
||||
id="path6460-6-4-4-3-3"
|
||||
style="opacity:0.2;color:#000000;fill:url(#radialGradient5147-5);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new" />
|
||||
<path
|
||||
d="M 46.405989,78.610714 A 13.125,13.125 0 0 1 33.62701,84.097034"
|
||||
transform="matrix(1.0666665,0,0,1.0666665,-14.49949,-51.367037)"
|
||||
id="path4010"
|
||||
style="color:#000000;fill:none;stroke:url(#linearGradient4018);stroke-width:8.43750095;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new" />
|
||||
<path
|
||||
d="m 38.71875,197.29687 a 4.84375,1.640625 0 1 1 -9.6875,0 4.84375,1.640625 0 1 1 9.6875,0 z"
|
||||
transform="matrix(4.541935,0,0,1.9809503,-131.42005,-348.86656)"
|
||||
id="path6460-6-4-4-4"
|
||||
style="opacity:0.1;color:#000000;fill:url(#radialGradient6081);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new" />
|
||||
<path
|
||||
d="M 35.542313,84.24974 A 13.125,13.125 0 1 1 47.171703,64.884866"
|
||||
transform="matrix(1.0666665,0,0,1.0666665,-14.49949,-51.367037)"
|
||||
id="path4788-6"
|
||||
style="color:#000000;fill:none;stroke:#387ab8;stroke-width:8.43750095;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new" />
|
||||
<path
|
||||
d="m 38.50051,9.4996196 0,11.0000004 -11,0"
|
||||
id="path4847"
|
||||
style="color:#000000;fill:none;stroke:#387ab8;stroke-width:7;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new" />
|
||||
<path
|
||||
d="m 46.386659,78.638476 a 13.125,13.125 0 0 1 -13.412517,5.34104"
|
||||
transform="matrix(1.0666665,0,0,1.0666665,-14.49949,-51.367037)"
|
||||
id="path4006"
|
||||
style="color:#000000;fill:none;stroke:url(#linearGradient4008);stroke-width:6.56250095;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new" />
|
||||
<path
|
||||
d="m 37.320778,84.13999 a 13.125,13.125 0 1 1 9.33779,-20.123155"
|
||||
transform="matrix(1.0666665,0,0,1.0666665,-14.49949,-51.367037)"
|
||||
id="path4788"
|
||||
style="color:#000000;fill:none;stroke:url(#linearGradient4593-5-8-1-5-2-3);stroke-width:6.56250095;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new" />
|
||||
<path
|
||||
d="m 38.50051,9.4996196 0,11.0000004 -11,0"
|
||||
id="path4847-1"
|
||||
style="color:#000000;fill:none;stroke:url(#linearGradient4593-5-8-1-5-2);stroke-width:5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new" />
|
||||
<path
|
||||
d="m 29.740794,33.593555 c -3.674085,2.533277 -8.663315,2.652831 -12.552784,-0.06269 -5.010358,-3.498088 -6.216831,-10.333397 -2.718751,-15.34375 3.498091,-5.010353 10.3334,-6.216833 15.343751,-2.71875 1.16116,0.810688 2.10377,1.843969 2.875,3.03125 l -5.1875,0 c -1.056625,-0.01494 -2.028484,0.943269 -2.028484,2 0,1.056731 0.971859,2.014943 2.028484,2 l 11,0 c 1.062499,0.28125 2.062499,-0.71875 2,-2 l 0,-11.0000004 c 0.01671,-1.0680358 -0.963214,-2.0479629 -2.03125,-2.0312505 -0.06245,-0.00293 -0.125046,-0.00293 -0.1875,0 -0.982752,0.107995 -1.802514,1.0428108 -1.78125,2.0312505 l 0,4.0625004 c -0.9534,-1.127853 -2.06667,-2.152011 -3.28125,-3 l -0.09375,-0.0625 c -2.85203,-1.9610889 -6.0733,-2.9220479 -9.312501,-2.9687509 -5.46224,-0.07875 -10.90353,2.4568065 -14.2500005,7.2500009 -5.354351,7.669111 -3.450361,18.3019 4.2187505,23.65625 6.255407,4.367344 14.482569,3.905673 20.208772,-0.574695"
|
||||
id="path4788-2"
|
||||
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;opacity:0.23999999;color:#000000;fill:none;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans" />
|
||||
<path
|
||||
d="m 36.50052,13.562118 c -0.9534,-1.127853 -2.06667,-2.152011 -3.28125,-3 l -0.0937,-0.0625 c -2.85203,-1.9610889 -6.0733,-2.9220479 -9.312501,-2.9687509 -5.46224,-0.07875 -10.90354,2.4568065 -14.2500105,7.2500009 -5.354351,7.669111 -3.450361,18.3019 4.2187505,23.65625"
|
||||
id="path4788-2-3"
|
||||
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;opacity:0.3;color:#000000;fill:none;stroke:url(#linearGradient5480);stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans" />
|
||||
<path
|
||||
d="M 32.53183,30.81212 C 29.03374,35.822473 22.198429,37.028952 17.18808,33.53087 12.177699,30.032787 10.971229,23.197473 14.469309,18.18712 17.96742,13.176767 24.802729,11.970287 29.81308,15.46837"
|
||||
id="path4788-2-3-4"
|
||||
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;opacity:0.3;color:#000000;fill:none;stroke:url(#linearGradient5497);stroke-width:1;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans" />
|
||||
</svg>
|
Before Width: | Height: | Size: 12 KiB |
@ -1,13 +0,0 @@
|
||||
<plugin name="PipXtreme" version="1.0.0" compatVersion="1.0.0">
|
||||
<vendor>The OpenPilot Project</vendor>
|
||||
<copyright>(C) 2011 Cathy Moss A.K.A. Pip</copyright>
|
||||
<license>The GNU Public License (GPL) Version 3</license>
|
||||
<description>A plugin to configure the PipXtreme OP modem via USB HID or Serial Port</description>
|
||||
<url>http://www.openpilot.org</url>
|
||||
<dependencyList>
|
||||
<dependency name="Core" version="1.0.0"/>
|
||||
<dependency name="UAVObjects" version="1.0.0"/>
|
||||
<dependency name="UAVTalk" version="1.0.0"/>
|
||||
<dependency name="RAWHid" version="1.0.0"/>
|
||||
</dependencyList>
|
||||
</plugin>
|
@ -1,38 +0,0 @@
|
||||
TEMPLATE = lib
|
||||
TARGET = PipXtreme
|
||||
|
||||
QT += svg
|
||||
QT += opengl
|
||||
|
||||
include(../../openpilotgcsplugin.pri)
|
||||
include(../../plugins/coreplugin/coreplugin.pri)
|
||||
include(../../plugins/uavobjects/uavobjects.pri)
|
||||
include(../../plugins/uavtalk/uavtalk.pri)
|
||||
include(../../plugins/rawhid/rawhid.pri)
|
||||
|
||||
INCLUDEPATH += ../../libs/qextserialport/src
|
||||
|
||||
HEADERS += pipxtremegadget.h \
|
||||
pipxtremegadgetconfiguration.h \
|
||||
pipxtremegadgetfactory.h \
|
||||
pipxtremegadgetoptionspage.h \
|
||||
pipxtremegadgetwidget.h \
|
||||
pipxtremeplugin.h \
|
||||
widgetbar.h
|
||||
|
||||
SOURCES += pipxtremegadget.cpp \
|
||||
pipxtremegadgetconfiguration.cpp \
|
||||
pipxtremegadgetfactory.cpp \
|
||||
pipxtremegadgetoptionspage.cpp \
|
||||
pipxtremegadgetwidget.cpp \
|
||||
pipxtremeplugin.cpp \
|
||||
widgetbar.cpp
|
||||
|
||||
OTHER_FILES += pipxtreme.pluginspec
|
||||
|
||||
FORMS += \
|
||||
pipxtreme.ui \
|
||||
pipxtremegadgetoptionspage.ui
|
||||
|
||||
RESOURCES += \
|
||||
pipxtreme.qrc
|
@ -1,5 +0,0 @@
|
||||
<RCC>
|
||||
<qresource prefix="/pipxtreme">
|
||||
<file>images/view-refresh.svg</file>
|
||||
</qresource>
|
||||
</RCC>
|
@ -1,1026 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>PipXtremeWidget</class>
|
||||
<widget class="QWidget" name="PipXtremeWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>571</width>
|
||||
<height>527</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="3" column="4">
|
||||
<widget class="QComboBox" name="comboBox_SerialBaudrate">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>The PC port serial baud rate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="3" colspan="2">
|
||||
<widget class="QComboBox" name="comboBox_Ports">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Set the PC port the modem is connected too</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QPushButton" name="connectButton">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="mouseTracking">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Connect to the modem (when normal telemetry is not used)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string> Connect </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="5">
|
||||
<widget class="QToolButton" name="refreshPorts">
|
||||
<property name="toolTip">
|
||||
<string>Refresh the list of serial and USB ports available</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="3" column="3">
|
||||
<widget class="QLabel" name="label_15">
|
||||
<property name="text">
|
||||
<string>Serial Baudrate</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Serial Number (hex)</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" colspan="2">
|
||||
<widget class="QLineEdit" name="lineEdit_SerialNumber">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<italic>false</italic>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="acceptDrops">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>The modems serial number</string>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QLineEdit {
|
||||
border: none;
|
||||
border-radius: 1px;
|
||||
padding: 0 8px;
|
||||
background: rgba(0, 0, 0, 16);
|
||||
/* background: transparent; */
|
||||
/* selection-background-color: darkgray;*/
|
||||
}</string>
|
||||
</property>
|
||||
<property name="frame">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="text">
|
||||
<string>Frequency Band</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1" colspan="2">
|
||||
<widget class="QLineEdit" name="lineEdit_FrequencyBand">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>The modems frequency band</string>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QLineEdit {
|
||||
border: none;
|
||||
border-radius: 1px;
|
||||
padding: 0 8px;
|
||||
background: rgba(0, 0, 0, 16);
|
||||
/* background: transparent; */
|
||||
/* selection-background-color: darkgray;*/
|
||||
}</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Min Frequency</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1" colspan="2">
|
||||
<widget class="QLineEdit" name="lineEdit_MinFrequency">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>The modems minimum allowed frequency</string>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QLineEdit {
|
||||
border: none;
|
||||
border-radius: 1px;
|
||||
padding: 0 8px;
|
||||
background: rgba(0, 0, 0, 16);
|
||||
/* background: transparent; */
|
||||
/* selection-background-color: darkgray;*/
|
||||
}</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Max Frequency</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1" colspan="2">
|
||||
<widget class="QLineEdit" name="lineEdit_MaxFrequency">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>The modems maximum allowed frequency</string>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QLineEdit {
|
||||
border: none;
|
||||
border-radius: 1px;
|
||||
padding: 0 8px;
|
||||
background: rgba(0, 0, 0, 16);
|
||||
/* background: transparent; */
|
||||
/* selection-background-color: darkgray;*/
|
||||
}</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_12">
|
||||
<property name="text">
|
||||
<string>Frequency Step Size</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1" colspan="2">
|
||||
<widget class="QLineEdit" name="lineEdit_FrequencyStepSize">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>The modems minimum frequency step size</string>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QLineEdit {
|
||||
border: none;
|
||||
border-radius: 1px;
|
||||
padding: 0 8px;
|
||||
background: rgba(0, 0, 0, 16);
|
||||
/* background: transparent; */
|
||||
/* selection-background-color: darkgray;*/
|
||||
}</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_11">
|
||||
<property name="text">
|
||||
<string>Link State</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1" colspan="2">
|
||||
<widget class="QLineEdit" name="lineEdit_LinkState">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>The modems current state</string>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QLineEdit {
|
||||
border: none;
|
||||
border-radius: 1px;
|
||||
padding: 0 8px;
|
||||
background: rgba(0, 0, 0, 16);
|
||||
/* background: transparent; */
|
||||
/* selection-background-color: darkgray;*/
|
||||
}</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="label_RSSI">
|
||||
<property name="text">
|
||||
<string>RSSI</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1" colspan="2">
|
||||
<widget class="WidgetBar" name="widgetRSSI" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>1</width>
|
||||
<height>1</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="mouseTracking">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background-color: rgb(112, 112, 112);</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="label_17">
|
||||
<property name="text">
|
||||
<string>Rx AFC</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1" colspan="2">
|
||||
<widget class="QLineEdit" name="lineEdit_RxAFC">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QLineEdit {
|
||||
border: none;
|
||||
border-radius: 1px;
|
||||
padding: 0 8px;
|
||||
background: rgba(0, 0, 0, 16);
|
||||
/* background: transparent; */
|
||||
/* selection-background-color: darkgray;*/
|
||||
}</string>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>Firmware Version</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" colspan="2">
|
||||
<widget class="QLineEdit" name="lineEdit_FirmwareVersion">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QLineEdit {
|
||||
border: none;
|
||||
border-radius: 1px;
|
||||
padding: 0 8px;
|
||||
background: rgba(0, 0, 0, 16);
|
||||
/* background: transparent; */
|
||||
/* selection-background-color: darkgray;*/
|
||||
}</string>
|
||||
</property>
|
||||
<property name="frame">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="4">
|
||||
<widget class="QSpinBox" name="spinBox_FrequencyCalibration">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Calibrate the modems RF carrier frequency</string>
|
||||
</property>
|
||||
<property name="accelerated">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>255</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="3">
|
||||
<widget class="QLabel" name="label_13">
|
||||
<property name="text">
|
||||
<string>Frequency Calibration</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="4">
|
||||
<widget class="QDoubleSpinBox" name="doubleSpinBox_Frequency">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Set the modems RF carrier frequency</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="accelerated">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>8</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1000.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.000001000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="3">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Frequency (MHz)</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="4">
|
||||
<widget class="QComboBox" name="comboBox_MaxRFBandwidth">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Set the maximum RF datarate/channel bandwidth the modem will use</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="3">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Max RF Datarate (bits/s)</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="4">
|
||||
<widget class="QComboBox" name="comboBox_MaxRFTxPower">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Set the maximum TX output power the modem will use</string>
|
||||
</property>
|
||||
<property name="layoutDirection">
|
||||
<enum>Qt::LeftToRight</enum>
|
||||
</property>
|
||||
<property name="modelColumn">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="3">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Max RF Tx Power</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="4">
|
||||
<widget class="QComboBox" name="comboBox_SerialPortSpeed">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Set the modems serial port speed</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="3">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>Serial Port Speed</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QLabel" name="label_14">
|
||||
<property name="text">
|
||||
<string>Mode</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="4">
|
||||
<widget class="QComboBox" name="comboBox_Mode">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Set the modems operating mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="4">
|
||||
<widget class="QLineEdit" name="lineEdit_PairedSerialNumber">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Serial number of the remote modem you want to pair with</string>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="maxLength">
|
||||
<number>8</number>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="3">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Paired Serial Number (hex)</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<widget class="QLabel" name="label_18">
|
||||
<property name="text">
|
||||
<string>Retries</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="1" colspan="2">
|
||||
<widget class="QLineEdit" name="lineEdit_Retries">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QLineEdit {
|
||||
border: none;
|
||||
border-radius: 1px;
|
||||
padding: 0 8px;
|
||||
background: rgba(0, 0, 0, 16);
|
||||
/* background: transparent; */
|
||||
/* selection-background-color: darkgray;*/
|
||||
}</string>
|
||||
</property>
|
||||
<property name="frame">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="3">
|
||||
<widget class="QLabel" name="label_16">
|
||||
<property name="text">
|
||||
<string>RTS time (ms)</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="4">
|
||||
<widget class="QSpinBox" name="spinBox_RTSTime">
|
||||
<property name="toolTip">
|
||||
<string>Ready-To-Send time is the maximum time the modem waits for more data before sending it. This is to try and make the RF link a little more efficient by creating larger packets.</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_10">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_AESkey">
|
||||
<property name="text">
|
||||
<string>AES Encryption Key</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="lineEdit_AESKey">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Courier New</family>
|
||||
<pointsize>9</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>The AES encryption key - has to be the same key on the remote modem.</string>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="maxLength">
|
||||
<number>32</number>
|
||||
</property>
|
||||
<property name="frame">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_AESKeyRandom">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Radomise the AES encryption key</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string> Rand</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBox_AESEnable">
|
||||
<property name="toolTip">
|
||||
<string>Enable/Disable AES encryption</string>
|
||||
</property>
|
||||
<property name="layoutDirection">
|
||||
<enum>Qt::RightToLeft</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>AES Enable</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_Import">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Restore the settings from a file</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Import</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_Export">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Save the settings into a file</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Export</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_Save">
|
||||
<property name="toolTip">
|
||||
<string>Click to save your new settings into PipX flash</string>
|
||||
</property>
|
||||
<property name="statusTip">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string> Save to flash </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_19">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_11">
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_ScanSpectrum">
|
||||
<property name="toolTip">
|
||||
<string>Scan whole band to see where their is interference and/or used channels</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string> Scan Spectrum </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_8">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_12">
|
||||
<item>
|
||||
<widget class="QGraphicsView" name="graphicsView_Spectrum">
|
||||
<property name="backgroundBrush">
|
||||
<brush brushstyle="NoBrush">
|
||||
<color alpha="255">
|
||||
<red>0</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</property>
|
||||
<property name="foregroundBrush">
|
||||
<brush brushstyle="NoBrush">
|
||||
<color alpha="255">
|
||||
<red>0</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</property>
|
||||
<property name="interactive">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>WidgetBar</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>widgetbar.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
@ -1,48 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file pipxtremegadget.cpp
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @addtogroup GCSPlugins GCS Plugins
|
||||
* @{
|
||||
* @{
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* 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 "pipxtremegadget.h"
|
||||
#include "pipxtremegadgetwidget.h"
|
||||
#include "pipxtremegadgetconfiguration.h"
|
||||
|
||||
PipXtremeGadget::PipXtremeGadget(QString classId, PipXtremeGadgetWidget *widget, QWidget *parent) :
|
||||
IUAVGadget(classId, parent),
|
||||
m_widget(widget)
|
||||
{
|
||||
}
|
||||
|
||||
PipXtremeGadget::~PipXtremeGadget()
|
||||
{
|
||||
delete m_widget;
|
||||
m_widget = NULL;
|
||||
}
|
||||
|
||||
// Loads a configuration.
|
||||
void PipXtremeGadget::loadConfiguration(IUAVGadgetConfiguration* config)
|
||||
{
|
||||
Q_UNUSED(config);
|
||||
/* PipXtremeGadgetConfiguration *m = qobject_cast< PipXtremeGadgetConfiguration*>(config);
|
||||
*/
|
||||
}
|
||||
|
@ -1,55 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file pipxtremegadget.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @addtogroup GCSPlugins GCS Plugins
|
||||
* @{
|
||||
* @{
|
||||
* @brief The YModem protocol serial uploader plugin
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* 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 PIPXTREMEGADGET_H
|
||||
#define PIPXTREMEGADGET_H
|
||||
|
||||
#include <coreplugin/iuavgadget.h>
|
||||
#include "pipxtremegadgetwidget.h"
|
||||
|
||||
class IUAVGadget;
|
||||
class QWidget;
|
||||
class QString;
|
||||
class PipXtremeGadgetWidget;
|
||||
|
||||
using namespace Core;
|
||||
|
||||
class PipXtremeGadget : public Core::IUAVGadget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
PipXtremeGadget(QString classId, PipXtremeGadgetWidget *widget, QWidget *parent = 0);
|
||||
~PipXtremeGadget();
|
||||
|
||||
QWidget *widget() { return m_widget; }
|
||||
void loadConfiguration(IUAVGadgetConfiguration* config);
|
||||
|
||||
private:
|
||||
PipXtremeGadgetWidget *m_widget;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -1,66 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file pipxtremegadgetconfiguration.cpp
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @addtogroup GCSPlugins GCS Plugins
|
||||
* @{
|
||||
* @{
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* 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 "pipxtremegadgetconfiguration.h"
|
||||
#include <qextserialport/src/qextserialport.h>
|
||||
|
||||
/**
|
||||
* Loads a saved configuration or defaults if non exist.
|
||||
*
|
||||
*/
|
||||
PipXtremeGadgetConfiguration::PipXtremeGadgetConfiguration(QString classId, QSettings* qSettings, QObject *parent) :
|
||||
IUAVGadgetConfiguration(classId, parent)
|
||||
{
|
||||
//if a saved configuration exists load it
|
||||
if (qSettings != 0)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
PipXtremeGadgetConfiguration::~PipXtremeGadgetConfiguration()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Clones a configuration.
|
||||
*
|
||||
*/
|
||||
IUAVGadgetConfiguration *PipXtremeGadgetConfiguration::clone()
|
||||
{
|
||||
PipXtremeGadgetConfiguration *m = new PipXtremeGadgetConfiguration(this->classId());
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves a configuration.
|
||||
*
|
||||
*/
|
||||
void PipXtremeGadgetConfiguration::saveConfig(QSettings *qSettings) const
|
||||
{
|
||||
if (qSettings)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file pipxtremegadgetconfiguration.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @addtogroup GCSPlugins GCS Plugins
|
||||
* @{
|
||||
* @{
|
||||
* @brief The YModem protocol serial uploader plugin
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* 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 PIPXTREMEGADGETCONFIGURATION_H
|
||||
#define PIPXTREMEGADGETCONFIGURATION_H
|
||||
|
||||
#include <coreplugin/iuavgadgetconfiguration.h>
|
||||
#include <qextserialport/src/qextserialport.h>
|
||||
|
||||
using namespace Core;
|
||||
|
||||
class PipXtremeGadgetConfiguration : public IUAVGadgetConfiguration
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit PipXtremeGadgetConfiguration(QString classId, QSettings* qSettings = 0, QObject *parent = 0);
|
||||
~PipXtremeGadgetConfiguration();
|
||||
|
||||
void saveConfig(QSettings *settings) const;
|
||||
IUAVGadgetConfiguration *clone();
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
#endif
|
@ -1,51 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file pipxtremegadgetfactory.cpp
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @addtogroup GCSPlugins GCS Plugins
|
||||
* @{
|
||||
* @{
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* 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 "pipxtremegadgetfactory.h"
|
||||
#include "pipxtremegadgetwidget.h"
|
||||
#include "pipxtremegadget.h"
|
||||
#include "pipxtremegadgetconfiguration.h"
|
||||
#include "pipxtremegadgetoptionspage.h"
|
||||
#include <coreplugin/iuavgadget.h>
|
||||
|
||||
PipXtremeGadgetFactory::PipXtremeGadgetFactory(QObject *parent) :
|
||||
IUAVGadgetFactory(QString("PipXtreme"), tr("PipXtreme"), parent)
|
||||
{
|
||||
}
|
||||
|
||||
PipXtremeGadgetFactory::~PipXtremeGadgetFactory()
|
||||
{
|
||||
}
|
||||
|
||||
Core::IUAVGadget* PipXtremeGadgetFactory::createGadget(QWidget *parent)
|
||||
{
|
||||
PipXtremeGadgetWidget *gadgetWidget = new PipXtremeGadgetWidget(parent);
|
||||
return new PipXtremeGadget(QString("PipXtreme"), gadgetWidget, parent);
|
||||
}
|
||||
|
||||
IUAVGadgetConfiguration * PipXtremeGadgetFactory::createConfiguration(QSettings *qSettings)
|
||||
{
|
||||
return new PipXtremeGadgetConfiguration(QString("PipXtreme"), qSettings);
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file pipxtremegadgetfactory.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @addtogroup GCSPlugins GCS Plugins
|
||||
* @{
|
||||
* @{
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* 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 PIPXTREMEGADGETFACTORY_H
|
||||
#define PIPXTREMEGADGETFACTORY_H
|
||||
|
||||
#include <coreplugin/iuavgadgetfactory.h>
|
||||
|
||||
namespace Core {
|
||||
class IUAVGadget;
|
||||
class IUAVGadgetFactory;
|
||||
}
|
||||
|
||||
using namespace Core;
|
||||
|
||||
class PipXtremeGadgetFactory : public Core::IUAVGadgetFactory
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
PipXtremeGadgetFactory(QObject *parent = 0);
|
||||
~PipXtremeGadgetFactory();
|
||||
|
||||
Core::IUAVGadget * createGadget(QWidget *parent);
|
||||
IUAVGadgetConfiguration * createConfiguration(QSettings *qSettings);
|
||||
};
|
||||
|
||||
#endif
|
@ -1,72 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file pipxtremegadgetoptionspage.cpp
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @addtogroup GCSPlugins GCS Plugins
|
||||
* @{
|
||||
* @{
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* 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 "pipxtremegadgetoptionspage.h"
|
||||
#include "pipxtremegadgetconfiguration.h"
|
||||
#include "ui_pipxtremegadgetoptionspage.h"
|
||||
|
||||
PipXtremeGadgetOptionsPage::PipXtremeGadgetOptionsPage(PipXtremeGadgetConfiguration *config, QObject *parent) :
|
||||
IOptionsPage(parent),
|
||||
options_page(NULL),
|
||||
m_config(config)
|
||||
{
|
||||
}
|
||||
|
||||
//creates options page widget
|
||||
QWidget *PipXtremeGadgetOptionsPage::createPage(QWidget *parent)
|
||||
{
|
||||
// QWidget *widget = new QWidget;
|
||||
// return widget;
|
||||
|
||||
options_page = new Ui::PipXtremeGadgetOptionsPage();
|
||||
QWidget *optionsPageWidget = new QWidget;
|
||||
options_page->setupUi(optionsPageWidget);
|
||||
|
||||
|
||||
|
||||
|
||||
return optionsPageWidget;
|
||||
}
|
||||
/**
|
||||
* Called when the user presses apply or OK.
|
||||
*
|
||||
* Saves the current values
|
||||
*
|
||||
*/
|
||||
void PipXtremeGadgetOptionsPage::apply()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void PipXtremeGadgetOptionsPage::finish()
|
||||
{
|
||||
if (options_page)
|
||||
{
|
||||
delete options_page;
|
||||
options_page = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,62 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file pipxtremegadgetoptionspage.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @addtogroup GCSPlugins GCS Plugins
|
||||
* @{
|
||||
* @{
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* 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 PIPXTREMEGADGETOPTIONSPAGE_H
|
||||
#define PIPXTREMEGADGETOPTIONSPAGE_H
|
||||
|
||||
#include <qextserialport/src/qextserialenumerator.h>
|
||||
#include "coreplugin/dialogs/ioptionspage.h"
|
||||
#include "QString"
|
||||
#include <QStringList>
|
||||
#include <QDebug>
|
||||
|
||||
namespace Core {
|
||||
class IUAVGadgetConfiguration;
|
||||
}
|
||||
|
||||
class PipXtremeGadgetConfiguration;
|
||||
|
||||
namespace Ui {
|
||||
class PipXtremeGadgetOptionsPage;
|
||||
}
|
||||
|
||||
using namespace Core;
|
||||
|
||||
class PipXtremeGadgetOptionsPage : public IOptionsPage
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit PipXtremeGadgetOptionsPage(PipXtremeGadgetConfiguration *config, QObject *parent = 0);
|
||||
|
||||
QWidget *createPage(QWidget *parent);
|
||||
void apply();
|
||||
void finish();
|
||||
|
||||
private:
|
||||
Ui::PipXtremeGadgetOptionsPage *options_page;
|
||||
PipXtremeGadgetConfiguration *m_config;
|
||||
};
|
||||
|
||||
#endif
|
@ -1,51 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>PipXtremeGadgetOptionsPage</class>
|
||||
<widget class="QWidget" name="PipXtremeGadgetOptionsPage">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>587</width>
|
||||
<height>359</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QWidget" name="widget" native="true">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>No options to set</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
@ -1,1464 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file pipxtremegadgetwidget.cpp
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @addtogroup GCSPlugins GCS Plugins
|
||||
* @{
|
||||
* @{
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* 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 <QDebug>
|
||||
#include <QtOpenGL/QGLWidget>
|
||||
#include <QSettings>
|
||||
#include <QFileInfo>
|
||||
#include <QDir>
|
||||
#include <QFileDialog>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <pipxsettings.h>
|
||||
#include <pipxstatus.h>
|
||||
#include "pipxtremegadgetwidget.h"
|
||||
|
||||
#define NO_PORT 0
|
||||
#define SERIAL_PORT 1
|
||||
#define USB_PORT 2
|
||||
|
||||
// ***************************************************************************************
|
||||
// config packet details
|
||||
|
||||
#define MAX_RETRIES 7
|
||||
#define RETRY_TIME 500 // ms
|
||||
|
||||
#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
|
||||
};
|
||||
|
||||
enum {
|
||||
FREQBAND_UNKNOWN = 0,
|
||||
FREQBAND_434MHz,
|
||||
FREQBAND_868MHz,
|
||||
FREQBAND_915MHz
|
||||
};
|
||||
|
||||
enum {
|
||||
LINK_DISCONNECTED = 0,
|
||||
LINK_CONNECTING,
|
||||
LINK_CONNECTED
|
||||
};
|
||||
|
||||
// ***************************************************************************************
|
||||
|
||||
enum {
|
||||
MODE_NORMAL = 0, // normal 2-way packet mode
|
||||
MODE_STREAM_TX, // 1-way continuous tx packet mode
|
||||
MODE_STREAM_RX, // 1-way continuous rx packet mode
|
||||
MODE_PPM_TX, // PPM tx mode
|
||||
MODE_PPM_RX, // PPM rx mode
|
||||
MODE_SCAN_SPECTRUM, // scan the receiver over the whole band
|
||||
MODE_TX_BLANK_CARRIER_TEST, // blank carrier Tx mode (for calibrating the carrier frequency say)
|
||||
MODE_TX_SPECTRUM_TEST // pseudo random Tx data mode (for checking the Tx carrier spectrum)
|
||||
};
|
||||
|
||||
// ***************************************************************************************
|
||||
|
||||
#define Poly32 0x04c11db7 // 32-bit polynomial .. this should produce the same as the STM32 hardware CRC
|
||||
|
||||
uint32_t CRC_Table32[] = {
|
||||
0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
|
||||
0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
|
||||
0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
|
||||
0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
|
||||
0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
|
||||
0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
|
||||
0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
|
||||
0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
|
||||
0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
|
||||
0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
|
||||
0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
|
||||
0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
|
||||
0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
|
||||
0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
|
||||
0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
|
||||
0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
|
||||
0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
|
||||
0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
|
||||
0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
|
||||
0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
|
||||
0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
|
||||
0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
|
||||
0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
|
||||
0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
|
||||
0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
|
||||
0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
|
||||
0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
|
||||
0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
|
||||
0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
|
||||
0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
|
||||
0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
|
||||
0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
|
||||
};
|
||||
|
||||
// ***************************************************************************************
|
||||
|
||||
// constructor
|
||||
PipXtremeGadgetWidget::PipXtremeGadgetWidget(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
m_widget(NULL),
|
||||
m_ioDevice(NULL),
|
||||
m_stage(PIPX_IDLE)
|
||||
{
|
||||
m_widget = new Ui_PipXtremeWidget();
|
||||
m_widget->setupUi(this);
|
||||
|
||||
#if QT_VERSION >= 0x040700
|
||||
qsrand(QDateTime::currentDateTime().toMSecsSinceEpoch());
|
||||
#else
|
||||
qsrand(QDateTime::currentDateTime().toTime_t());
|
||||
#endif
|
||||
// Connect to the PipXStatus object updates
|
||||
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
|
||||
UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
|
||||
pipxStatusObj = dynamic_cast<UAVDataObject*>(objManager->getObject("PipXStatus"));
|
||||
if (pipxStatusObj != NULL ) {
|
||||
connect(pipxStatusObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(updateStatus(UAVObject*)));
|
||||
} else {
|
||||
qDebug() << "Error: Object is unknown (PipXStatus).";
|
||||
}
|
||||
|
||||
device_input_buffer.size = 8192;
|
||||
device_input_buffer.used = 0;
|
||||
device_input_buffer.buffer = new quint8 [device_input_buffer.size];
|
||||
|
||||
memset(&pipx_config_details, 0, sizeof(pipx_config_details));
|
||||
memset(&pipx_config_settings, 0, sizeof(pipx_config_settings));
|
||||
|
||||
m_widget->comboBox_SerialBaudrate->clear();
|
||||
m_widget->comboBox_SerialBaudrate->addItem("1200", 1200);
|
||||
m_widget->comboBox_SerialBaudrate->addItem("2400", 2400);
|
||||
m_widget->comboBox_SerialBaudrate->addItem("4800", 4800);
|
||||
m_widget->comboBox_SerialBaudrate->addItem("9600", 9600);
|
||||
m_widget->comboBox_SerialBaudrate->addItem("19200", 19200);
|
||||
m_widget->comboBox_SerialBaudrate->addItem("38400", 38400);
|
||||
m_widget->comboBox_SerialBaudrate->addItem("57600", 57600);
|
||||
m_widget->comboBox_SerialBaudrate->addItem("115200", 115200);
|
||||
#if (defined Q_OS_WIN)
|
||||
m_widget->comboBox_SerialBaudrate->addItem("230400", 230400);
|
||||
m_widget->comboBox_SerialBaudrate->addItem("460800", 460800);
|
||||
m_widget->comboBox_SerialBaudrate->addItem("921600", 921600);
|
||||
#endif
|
||||
m_widget->comboBox_SerialBaudrate->setCurrentIndex(m_widget->comboBox_SerialBaudrate->findText("57600"));
|
||||
|
||||
m_widget->comboBox_Mode->clear();
|
||||
m_widget->comboBox_Mode->addItem("Normal", MODE_NORMAL);
|
||||
m_widget->comboBox_Mode->addItem("Continuous Stream Tx", MODE_STREAM_TX);
|
||||
m_widget->comboBox_Mode->addItem("Continuous Stream Rx", MODE_STREAM_RX);
|
||||
m_widget->comboBox_Mode->addItem("PPM Tx", MODE_PPM_TX);
|
||||
m_widget->comboBox_Mode->addItem("PPM Rx", MODE_PPM_RX);
|
||||
m_widget->comboBox_Mode->addItem("Scan Spectrum", MODE_SCAN_SPECTRUM);
|
||||
m_widget->comboBox_Mode->addItem("Test Tx Blank Carrier Frequency", MODE_TX_BLANK_CARRIER_TEST);
|
||||
m_widget->comboBox_Mode->addItem("Test Tx Spectrum", MODE_TX_SPECTRUM_TEST);
|
||||
|
||||
m_widget->comboBox_SerialPortSpeed->clear();
|
||||
for (int i = 0; i < m_widget->comboBox_SerialBaudrate->count(); i++)
|
||||
m_widget->comboBox_SerialPortSpeed->addItem(m_widget->comboBox_SerialBaudrate->itemText(i), m_widget->comboBox_SerialBaudrate->itemData(i));
|
||||
m_widget->comboBox_SerialPortSpeed->setCurrentIndex(m_widget->comboBox_SerialPortSpeed->findText("57600"));
|
||||
|
||||
m_widget->comboBox_MaxRFBandwidth->clear();
|
||||
m_widget->comboBox_MaxRFBandwidth->addItem("500", 500);
|
||||
m_widget->comboBox_MaxRFBandwidth->addItem("1000", 1000);
|
||||
m_widget->comboBox_MaxRFBandwidth->addItem("2000", 2000);
|
||||
m_widget->comboBox_MaxRFBandwidth->addItem("4000", 4000);
|
||||
m_widget->comboBox_MaxRFBandwidth->addItem("8000", 8000);
|
||||
m_widget->comboBox_MaxRFBandwidth->addItem("9600", 9600);
|
||||
m_widget->comboBox_MaxRFBandwidth->addItem("16000", 16000);
|
||||
m_widget->comboBox_MaxRFBandwidth->addItem("19200", 19200);
|
||||
m_widget->comboBox_MaxRFBandwidth->addItem("24000", 24000);
|
||||
m_widget->comboBox_MaxRFBandwidth->addItem("32000", 32000);
|
||||
m_widget->comboBox_MaxRFBandwidth->addItem("64000", 64000);
|
||||
m_widget->comboBox_MaxRFBandwidth->addItem("128000", 128000);
|
||||
m_widget->comboBox_MaxRFBandwidth->addItem("192000", 192000);
|
||||
m_widget->comboBox_MaxRFBandwidth->addItem("256000", 256000);
|
||||
m_widget->comboBox_MaxRFBandwidth->setCurrentIndex(m_widget->comboBox_MaxRFBandwidth->findText("128000"));
|
||||
|
||||
m_widget->comboBox_MaxRFTxPower->clear();
|
||||
m_widget->comboBox_MaxRFTxPower->addItem("1.25mW", 0);
|
||||
m_widget->comboBox_MaxRFTxPower->addItem("1.6mW", 1);
|
||||
m_widget->comboBox_MaxRFTxPower->addItem("3.16mW", 2);
|
||||
m_widget->comboBox_MaxRFTxPower->addItem("6.3mW", 3);
|
||||
m_widget->comboBox_MaxRFTxPower->addItem("12.6mW", 4);
|
||||
m_widget->comboBox_MaxRFTxPower->addItem("25mW", 5);
|
||||
m_widget->comboBox_MaxRFTxPower->addItem("50mW", 6);
|
||||
m_widget->comboBox_MaxRFTxPower->addItem("100mW", 7);
|
||||
m_widget->comboBox_MaxRFTxPower->setCurrentIndex(m_widget->comboBox_MaxRFTxPower->findText("12.6mW"));
|
||||
|
||||
m_widget->doubleSpinBox_Frequency->setSingleStep(0.00015625);
|
||||
|
||||
m_widget->widgetRSSI->setMinimum(-120);
|
||||
m_widget->widgetRSSI->setMaximum(0);
|
||||
m_widget->widgetRSSI->setValue(m_widget->widgetRSSI->minimum());
|
||||
|
||||
m_widget->label_RSSI->setText("RSSI");
|
||||
|
||||
m_widget->graphicsView_Spectrum->setScene(new QGraphicsScene(this));
|
||||
m_widget->graphicsView_Spectrum->setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers)));
|
||||
// m_widget->graphicsView_Spectrum->setViewport(new QWidget);
|
||||
m_widget->graphicsView_Spectrum->setCacheMode(QGraphicsView::CacheBackground);
|
||||
m_widget->graphicsView_Spectrum->setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform | QPainter::HighQualityAntialiasing);
|
||||
QGraphicsScene *spec_scene = m_widget->graphicsView_Spectrum->scene();
|
||||
if (spec_scene)
|
||||
{
|
||||
spec_scene->setBackgroundBrush(QColor(80, 80, 80));
|
||||
spec_scene->clear();
|
||||
|
||||
// spec_scene->addItem(m_background);
|
||||
// spec_scene->addItem(m_joystickEnd);
|
||||
// spec_scene->setSceneRect(m_background->boundingRect());
|
||||
}
|
||||
|
||||
m_widget->pushButton_Save->setEnabled(false);
|
||||
m_widget->pushButton_ScanSpectrum->setEnabled(false);
|
||||
m_widget->pushButton_Import->setEnabled(false);
|
||||
m_widget->pushButton_Export->setEnabled(false);
|
||||
|
||||
QIcon rbi;
|
||||
rbi.addFile(QString(":pipxtreme/images/view-refresh.svg"));
|
||||
m_widget->refreshPorts->setIcon(rbi);
|
||||
|
||||
// Listen to telemetry connection events
|
||||
ExtensionSystem::PluginManager *pluginManager = ExtensionSystem::PluginManager::instance();
|
||||
if (pluginManager)
|
||||
{
|
||||
TelemetryManager *telemetryManager = pluginManager->getObject<TelemetryManager>();
|
||||
if (telemetryManager)
|
||||
{
|
||||
connect(telemetryManager, SIGNAL(myStart()), this, SLOT(onTelemetryStart()));
|
||||
connect(telemetryManager, SIGNAL(myStop()), this, SLOT(onTelemetryStop()));
|
||||
connect(telemetryManager, SIGNAL(connected()), this, SLOT(onTelemetryConnect()));
|
||||
connect(telemetryManager, SIGNAL(disconnected()), this, SLOT(onTelemetryDisconnect()));
|
||||
}
|
||||
}
|
||||
|
||||
getPorts();
|
||||
|
||||
connect(m_widget->connectButton, SIGNAL(clicked()), this, SLOT(connectDisconnect()));
|
||||
connect(m_widget->refreshPorts, SIGNAL(clicked()), this, SLOT(getPorts()));
|
||||
connect(m_widget->pushButton_AESKeyRandom, SIGNAL(clicked()), this, SLOT(randomiseAESKey()));
|
||||
connect(m_widget->pushButton_ScanSpectrum, SIGNAL(clicked()), this, SLOT(scanSpectrum()));
|
||||
connect(m_widget->pushButton_Save, SIGNAL(clicked()), this, SLOT(saveToFlash()));
|
||||
connect(m_widget->lineEdit_AESKey, SIGNAL(textChanged(const QString &)), this, SLOT(textChangedAESKey(const QString &)));
|
||||
connect(m_widget->pushButton_Import, SIGNAL(clicked()), this, SLOT(importSettings()));
|
||||
connect(m_widget->pushButton_Export, SIGNAL(clicked()), this, SLOT(exportSettings()));
|
||||
}
|
||||
|
||||
// destructor .. this never gets called :(
|
||||
PipXtremeGadgetWidget::~PipXtremeGadgetWidget()
|
||||
{
|
||||
disconnectPort(false);
|
||||
|
||||
device_input_buffer.mutex.lock();
|
||||
if (device_input_buffer.buffer)
|
||||
{
|
||||
delete [] device_input_buffer.buffer;
|
||||
device_input_buffer.buffer = NULL;
|
||||
device_input_buffer.size = 0;
|
||||
device_input_buffer.used = 0;
|
||||
}
|
||||
device_input_buffer.mutex.unlock();
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Called by updates to @PipXStatus
|
||||
*/
|
||||
void PipXtremeGadgetWidget::updateStatus(UAVObject *object) {
|
||||
UAVObjectField* rssiField = object->getField("RSSI");
|
||||
if (rssiField) {
|
||||
m_widget->widgetRSSI->setValue(rssiField->getDouble());
|
||||
} else {
|
||||
qDebug() << "PipXtremeGadgetWidget: Count not read RSSI field.";
|
||||
}
|
||||
UAVObjectField* idField = object->getField("DeviceID");
|
||||
if (idField) {
|
||||
m_widget->lineEdit_SerialNumber->setText(QString::number(idField->getValue().toInt(), 16).toUpper());
|
||||
} else {
|
||||
qDebug() << "PipXtremeGadgetWidget: Count not read RSSI field.";
|
||||
}
|
||||
UAVObjectField* linkField = object->getField("linkState");
|
||||
if (idField) {
|
||||
char *msg = "Unknown";
|
||||
switch (linkField->getValue().toInt())
|
||||
{
|
||||
case PipXStatus::LINKSTATE_DISCONNECTED:
|
||||
msg = "Disconnected";
|
||||
break;
|
||||
case PipXStatus::LINKSTATE_CONNECTING:
|
||||
msg = "Connecting";
|
||||
break;
|
||||
case PipXStatus::LINKSTATE_CONNECTED:
|
||||
msg = "Connected";
|
||||
break;
|
||||
}
|
||||
m_widget->lineEdit_LinkState->setText(msg);
|
||||
} else {
|
||||
qDebug() << "PipXtremeGadgetWidget: Count not read link state field.";
|
||||
}
|
||||
}
|
||||
|
||||
// ***************************************************************************************
|
||||
|
||||
void PipXtremeGadgetWidget::resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
if (m_widget)
|
||||
{
|
||||
if (m_widget->graphicsView_Spectrum)
|
||||
{
|
||||
QGraphicsScene *spec_scene = m_widget->graphicsView_Spectrum->scene();
|
||||
if (spec_scene)
|
||||
{
|
||||
// spec_scene->setSceneRect(QRect(QPoint(0, 0), event->size()));
|
||||
// spec_scene->setBackgroundBrush(Qt::black);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PipXtremeGadgetWidget::resizeEvent(event);
|
||||
}
|
||||
|
||||
// ***************************************************************************************
|
||||
|
||||
void PipXtremeGadgetWidget::onComboBoxPorts_currentIndexChanged(int index)
|
||||
{
|
||||
if (index < 0)
|
||||
{
|
||||
m_widget->comboBox_SerialBaudrate->setEnabled(false);
|
||||
return;
|
||||
}
|
||||
|
||||
int type = m_widget->comboBox_Ports->itemData(index).toInt();
|
||||
|
||||
m_widget->comboBox_SerialBaudrate->setEnabled(type == SERIAL_PORT);
|
||||
}
|
||||
|
||||
// ***************************************************************************************
|
||||
|
||||
uint32_t PipXtremeGadgetWidget::updateCRC32(uint32_t crc, uint8_t b)
|
||||
{
|
||||
return (crc << 8) ^ CRC_Table32[(crc >> 24) ^ b];
|
||||
}
|
||||
|
||||
uint32_t PipXtremeGadgetWidget::updateCRC32Data(uint32_t crc, void *data, int len)
|
||||
{
|
||||
register uint8_t *p = (uint8_t *)data;
|
||||
register uint32_t _crc = crc;
|
||||
for (int i = len; i > 0; i--)
|
||||
_crc = (_crc << 8) ^ CRC_Table32[(_crc >> 24) ^ *p++];
|
||||
return _crc;
|
||||
}
|
||||
|
||||
// Generate the CRC table
|
||||
void PipXtremeGadgetWidget::makeCRC_Table32()
|
||||
{
|
||||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
uint32_t crc = i;
|
||||
for (int j = 8; j > 0; j--)
|
||||
crc = (crc & 1) ? (crc << 1) ^ Poly32 : crc << 1;
|
||||
CRC_Table32[i] = crc;
|
||||
}
|
||||
}
|
||||
|
||||
// ***************************************************************************************
|
||||
|
||||
QString PipXtremeGadgetWidget::getSerialPortDevice(const QString &friendName)
|
||||
{
|
||||
QList<QextPortInfo> ports = QextSerialEnumerator::getPorts();
|
||||
|
||||
foreach (QextPortInfo port, ports)
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
if (port.friendName == friendName)
|
||||
return port.portName;
|
||||
#else
|
||||
if (port.friendName == friendName)
|
||||
return port.physName;
|
||||
#endif
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
bool sortSerialPorts(const QextPortInfo &s1, const QextPortInfo &s2)
|
||||
{
|
||||
return (s1.portName < s2.portName);
|
||||
}
|
||||
|
||||
void PipXtremeGadgetWidget::getPorts()
|
||||
{
|
||||
disconnect(m_widget->comboBox_Ports, 0, 0, 0);
|
||||
|
||||
m_widget->comboBox_Ports->clear();
|
||||
|
||||
// ********************************
|
||||
// Populate the telemetry combo box with serial ports
|
||||
|
||||
QList<QextPortInfo> serial_ports = QextSerialEnumerator::getPorts();
|
||||
|
||||
qSort(serial_ports.begin(), serial_ports.end(), sortSerialPorts);
|
||||
|
||||
QStringList list;
|
||||
|
||||
foreach (QextPortInfo port, serial_ports)
|
||||
list.append(port.friendName);
|
||||
|
||||
for (int i = 0; i < list.count(); i++)
|
||||
m_widget->comboBox_Ports->addItem("com: " + list.at(i), SERIAL_PORT);
|
||||
|
||||
// ********************************
|
||||
// Populate the telemetry combo box with usb ports
|
||||
|
||||
pjrc_rawhid *rawHidHandle = new pjrc_rawhid();
|
||||
if (rawHidHandle)
|
||||
{
|
||||
int opened = rawHidHandle->open(10, 0x20A0, 0x415C, 0xFF9C, 0x0001);
|
||||
if (opened > 0)
|
||||
{
|
||||
QList<QString> usb_ports;
|
||||
|
||||
for (int i = 0; i < opened; i++)
|
||||
usb_ports.append(rawHidHandle->getserial(i));
|
||||
|
||||
qSort(usb_ports.begin(), usb_ports.end());
|
||||
|
||||
for (int i = 0; i < usb_ports.count(); i++)
|
||||
m_widget->comboBox_Ports->addItem("usb: " + usb_ports.at(i), USB_PORT);
|
||||
}
|
||||
|
||||
delete rawHidHandle;
|
||||
}
|
||||
|
||||
// ********************************
|
||||
|
||||
connect(m_widget->comboBox_Ports, SIGNAL(currentIndexChanged(int)), this, SLOT(onComboBoxPorts_currentIndexChanged(int)));
|
||||
|
||||
onComboBoxPorts_currentIndexChanged(m_widget->comboBox_Ports->currentIndex());
|
||||
|
||||
// ********************************
|
||||
}
|
||||
|
||||
// ***************************************************************************************
|
||||
|
||||
void PipXtremeGadgetWidget::onTelemetryStart()
|
||||
{
|
||||
setEnabled(false);
|
||||
|
||||
// m_widget->connectButton->setEnabled(false);
|
||||
// m_widget->comboBox_Ports->setEnabled(false);
|
||||
// m_widget->refreshPorts->setEnabled(false);
|
||||
// m_widget->comboBox_SerialBaudrate->setEnabled(false);
|
||||
}
|
||||
|
||||
void PipXtremeGadgetWidget::onTelemetryStop()
|
||||
{
|
||||
setEnabled(true);
|
||||
|
||||
// m_widget->connectButton->setEnabled(true);
|
||||
// m_widget->comboBox_Ports->setEnabled(true);
|
||||
// m_widget->refreshPorts->setEnabled(true);
|
||||
// m_widget->comboBox_SerialBaudrate->setEnabled(true);
|
||||
}
|
||||
|
||||
// ***************************************************************************************
|
||||
|
||||
void PipXtremeGadgetWidget::onTelemetryConnect()
|
||||
{
|
||||
}
|
||||
|
||||
void PipXtremeGadgetWidget::onTelemetryDisconnect()
|
||||
{
|
||||
}
|
||||
|
||||
// ***************************************************************************************
|
||||
|
||||
void PipXtremeGadgetWidget::disableTelemetry()
|
||||
{ // Suspend telemetry & polling
|
||||
|
||||
Core::ConnectionManager *cm = Core::ICore::instance()->connectionManager();
|
||||
if (!cm) return;
|
||||
|
||||
cm->disconnectDevice();
|
||||
cm->suspendPolling();
|
||||
}
|
||||
|
||||
void PipXtremeGadgetWidget::enableTelemetry()
|
||||
{ // Restart the polling thread
|
||||
|
||||
Core::ConnectionManager *cm = Core::ICore::instance()->connectionManager();
|
||||
if (!cm) return;
|
||||
|
||||
cm->resumePolling();
|
||||
}
|
||||
|
||||
// ***************************************************************************************
|
||||
|
||||
void PipXtremeGadgetWidget::randomiseAESKey()
|
||||
{
|
||||
#if QT_VERSION >= 0x040700
|
||||
uint32_t crc = ((uint32_t)qrand() << 16) ^ qrand() ^ QDateTime::currentDateTime().toMSecsSinceEpoch(); // only available with Qt 4.7.1 and later
|
||||
#else
|
||||
uint32_t crc = ((uint32_t)qrand() << 16) ^ qrand() ^ QDateTime::currentDateTime().toTime_t();
|
||||
#endif
|
||||
|
||||
QString key = "";
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
for (int i = 0; i < (27 + (qrand() & 0x7f)); i++)
|
||||
crc = updateCRC32(crc, qrand());
|
||||
|
||||
key += QString::number(crc, 16).rightJustified(8, '0');
|
||||
}
|
||||
|
||||
m_widget->lineEdit_AESKey->setText(key);
|
||||
}
|
||||
|
||||
void PipXtremeGadgetWidget::scanSpectrum()
|
||||
{
|
||||
}
|
||||
|
||||
void PipXtremeGadgetWidget::saveToFlash()
|
||||
{
|
||||
QMutexLocker locker_dev(&device_mutex);
|
||||
QMutexLocker locker_inbuf(&device_input_buffer.mutex);
|
||||
|
||||
if (!m_ioDevice) return;
|
||||
if (!m_ioDevice->isOpen()) return;
|
||||
|
||||
if (pipx_config_details.serial_number == 0) return; // we first need some details before sending new setings
|
||||
|
||||
QString s;
|
||||
bool ok;
|
||||
|
||||
t_pipx_config_settings settings;
|
||||
|
||||
settings.mode = m_widget->comboBox_Mode->itemData(m_widget->comboBox_Mode->currentIndex()).toUInt();
|
||||
|
||||
s = m_widget->lineEdit_PairedSerialNumber->text().trimmed().toLower();
|
||||
s.replace(' ', ""); // remove all spaces
|
||||
if (s.startsWith("0x"))
|
||||
{
|
||||
s.remove(0, 2);
|
||||
s = s.trimmed();
|
||||
}
|
||||
settings.destination_id = s.toUInt(&ok, 16);
|
||||
if (s.isEmpty() || !ok)
|
||||
{
|
||||
error("Check your \"Paired Serial Number\" entry!", 0);
|
||||
return;
|
||||
}
|
||||
|
||||
settings.rf_xtal_cap = m_widget->spinBox_FrequencyCalibration->value();
|
||||
|
||||
s = m_widget->doubleSpinBox_Frequency->text().trimmed();
|
||||
s.replace(' ', ""); // remove all spaces
|
||||
settings.frequency_Hz = (uint32_t)(s.toDouble(&ok) * 1e6);
|
||||
if (ok) // round it to the 'frequency step size'
|
||||
settings.frequency_Hz = (uint32_t)(((double)settings.frequency_Hz + pipx_config_details.frequency_step_size / 2) / pipx_config_details.frequency_step_size) * pipx_config_details.frequency_step_size;
|
||||
if (s.isEmpty() || !ok || settings.frequency_Hz < pipx_config_details.min_frequency_Hz || settings.frequency_Hz > pipx_config_details.max_frequency_Hz)
|
||||
{
|
||||
error("Check your \"Frequency\" entry!", 0);
|
||||
return;
|
||||
}
|
||||
|
||||
settings.max_rf_bandwidth = m_widget->comboBox_MaxRFBandwidth->itemData(m_widget->comboBox_MaxRFBandwidth->currentIndex()).toInt();
|
||||
settings.max_tx_power = m_widget->comboBox_MaxRFTxPower->itemData(m_widget->comboBox_MaxRFTxPower->currentIndex()).toInt();
|
||||
settings.serial_baudrate = m_widget->comboBox_SerialPortSpeed->itemData(m_widget->comboBox_SerialPortSpeed->currentIndex()).toInt();
|
||||
settings.aes_enable = m_widget->checkBox_AESEnable->isChecked();
|
||||
settings.rts_time = m_widget->spinBox_RTSTime->value();
|
||||
|
||||
memset(settings.aes_key, 0, sizeof(settings.aes_key));
|
||||
s = m_widget->lineEdit_AESKey->text().trimmed();
|
||||
s.replace(' ', ""); // remove all spaces
|
||||
while (s.length() < 32) s = '0' + s;
|
||||
if (settings.aes_enable && s.length() != 32)
|
||||
{
|
||||
error("Check your \"AES Key\" entry! .. it must be 32 hex characters long", 0);
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < (int)sizeof(settings.aes_key); i++)
|
||||
{
|
||||
QString s2 = s.left(2);
|
||||
s.remove(0, 2);
|
||||
s = s.trimmed();
|
||||
settings.aes_key[i] = s2.toUInt(&ok, 16);
|
||||
if (!ok)
|
||||
{
|
||||
error("Check your \"AES Key\" entry! .. it must contain only hex characters (0-9, a-f)", 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// send the new settings to the modem
|
||||
sendSettings(pipx_config_details.serial_number, &settings);
|
||||
|
||||
// retrieve them back
|
||||
m_stage_retries = 0;
|
||||
m_stage = PIPX_REQ_SETTINGS;
|
||||
}
|
||||
|
||||
void PipXtremeGadgetWidget::textChangedAESKey(const QString &text)
|
||||
{
|
||||
QString s = text;
|
||||
s.replace(' ', "");
|
||||
m_widget->label_AESkey->setText("AES Encryption Key (" + QString::number(s.length()) + ")");
|
||||
}
|
||||
|
||||
// ***************************************************************************************
|
||||
// send various packets
|
||||
|
||||
void PipXtremeGadgetWidget::sendRequestDetails(uint32_t serial_number)
|
||||
{
|
||||
// *****************
|
||||
// create the packet
|
||||
|
||||
t_pipx_config_header header;
|
||||
header.marker = PIPX_HEADER_MARKER;
|
||||
header.serial_number = serial_number;
|
||||
header.type = PIPX_PACKET_TYPE_REQ_DETAILS;
|
||||
header.spare = 0;
|
||||
header.data_size = 0;
|
||||
header.data_crc = 0xffffffff;
|
||||
header.header_crc = 0;
|
||||
header.header_crc = updateCRC32Data(0xffffffff, &header, sizeof(t_pipx_config_header));
|
||||
|
||||
// *****************
|
||||
// send the packet
|
||||
|
||||
// QMutexLocker locker_dev(&device_mutex);
|
||||
if (!m_ioDevice) return;
|
||||
if (!m_ioDevice->isOpen()) return;
|
||||
qint64 bytes_written = m_ioDevice->write((const char*)&header, sizeof(t_pipx_config_header));
|
||||
|
||||
Q_UNUSED(bytes_written)
|
||||
|
||||
// *****************
|
||||
}
|
||||
|
||||
void PipXtremeGadgetWidget::sendRequestSettings(uint32_t serial_number)
|
||||
{
|
||||
if (serial_number == 0)
|
||||
return;
|
||||
|
||||
// *****************
|
||||
// create the packet
|
||||
|
||||
t_pipx_config_header header;
|
||||
header.marker = PIPX_HEADER_MARKER;
|
||||
header.serial_number = serial_number;
|
||||
header.type = PIPX_PACKET_TYPE_REQ_SETTINGS;
|
||||
header.spare = 0;
|
||||
header.data_size = 0;
|
||||
header.data_crc = 0xffffffff;
|
||||
header.header_crc = 0;
|
||||
header.header_crc = updateCRC32Data(0xffffffff, &header, sizeof(t_pipx_config_header));
|
||||
|
||||
// *****************
|
||||
// send the packet
|
||||
|
||||
// QMutexLocker locker_dev(&device_mutex);
|
||||
if (!m_ioDevice) return;
|
||||
if (!m_ioDevice->isOpen()) return;
|
||||
qint64 bytes_written = m_ioDevice->write((const char*)&header, sizeof(t_pipx_config_header));
|
||||
|
||||
// qDebug() << "PipX m_ioDevice->write: " << QString::number(bytes_written) << endl;
|
||||
|
||||
Q_UNUSED(bytes_written)
|
||||
|
||||
// error("Bytes written", bytes_written); // TEST ONLY
|
||||
|
||||
// *****************
|
||||
}
|
||||
|
||||
void PipXtremeGadgetWidget::sendRequestState(uint32_t serial_number)
|
||||
{
|
||||
if (serial_number == 0)
|
||||
return;
|
||||
|
||||
// *****************
|
||||
// create the packet
|
||||
|
||||
t_pipx_config_header header;
|
||||
header.marker = PIPX_HEADER_MARKER;
|
||||
header.serial_number = serial_number;
|
||||
header.type = PIPX_PACKET_TYPE_REQ_STATE;
|
||||
header.spare = 0;
|
||||
header.data_size = 0;
|
||||
header.data_crc = 0xffffffff;
|
||||
header.header_crc = 0;
|
||||
header.header_crc = updateCRC32Data(0xffffffff, &header, sizeof(t_pipx_config_header));
|
||||
|
||||
// *****************
|
||||
// send the packet
|
||||
|
||||
// QMutexLocker locker_dev(&device_mutex);
|
||||
if (!m_ioDevice) return;
|
||||
if (!m_ioDevice->isOpen()) return;
|
||||
qint64 bytes_written = m_ioDevice->write((const char*)&header, sizeof(t_pipx_config_header));
|
||||
|
||||
// qDebug() << "PipX m_ioDevice->write: " << QString::number(bytes_written) << endl;
|
||||
|
||||
Q_UNUSED(bytes_written)
|
||||
|
||||
// error("Bytes written", bytes_written); // TEST ONLY
|
||||
|
||||
// *****************
|
||||
}
|
||||
|
||||
void PipXtremeGadgetWidget::sendSettings(uint32_t serial_number, t_pipx_config_settings *settings)
|
||||
{
|
||||
if (serial_number == 0)
|
||||
return;
|
||||
|
||||
if (!settings)
|
||||
return;
|
||||
|
||||
uint8_t buffer[sizeof(t_pipx_config_header) + sizeof(t_pipx_config_settings)];
|
||||
|
||||
t_pipx_config_header *header = (t_pipx_config_header *)buffer;
|
||||
uint8_t *data = (uint8_t *) header + sizeof(t_pipx_config_header);
|
||||
|
||||
// *****************
|
||||
// create the packet
|
||||
|
||||
memcpy(data, settings, sizeof(t_pipx_config_settings));
|
||||
|
||||
header->marker = PIPX_HEADER_MARKER;
|
||||
header->serial_number = serial_number;
|
||||
header->type = PIPX_PACKET_TYPE_SETTINGS;
|
||||
header->spare = 0;
|
||||
header->data_size = sizeof(t_pipx_config_settings);
|
||||
header->data_crc = updateCRC32Data(0xffffffff, data, header->data_size);
|
||||
header->header_crc = 0;
|
||||
header->header_crc = updateCRC32Data(0xffffffff, header, sizeof(t_pipx_config_header));
|
||||
|
||||
// *****************
|
||||
// send the packet
|
||||
|
||||
// QMutexLocker locker_dev(&device_mutex);
|
||||
if (!m_ioDevice) return;
|
||||
if (!m_ioDevice->isOpen()) return;
|
||||
qint64 bytes_written = m_ioDevice->write((const char*)buffer, sizeof(t_pipx_config_header) + header->data_size);
|
||||
|
||||
// error("Bytes written", bytes_written); // TEST ONLY
|
||||
|
||||
Q_UNUSED(bytes_written)
|
||||
|
||||
// *****************
|
||||
}
|
||||
|
||||
// ***************************************************************************************
|
||||
// process rx stream data
|
||||
|
||||
void PipXtremeGadgetWidget::processRxStream()
|
||||
{
|
||||
QMutexLocker locker_dev(&device_mutex);
|
||||
QMutexLocker locker_inbuf(&device_input_buffer.mutex);
|
||||
|
||||
if (!m_ioDevice) return;
|
||||
if (!m_ioDevice->isOpen()) return;
|
||||
|
||||
QTimer::singleShot(100, this, SLOT(processRxStream()));
|
||||
|
||||
qint64 bytes_available = m_ioDevice->bytesAvailable();
|
||||
if (bytes_available <= 0) return;
|
||||
|
||||
// ensure we have buffer space for the new data
|
||||
if (!device_input_buffer.buffer)
|
||||
{ // allocate a buffer for the data
|
||||
device_input_buffer.size = bytes_available * 2;
|
||||
device_input_buffer.used = 0;
|
||||
device_input_buffer.buffer = new quint8 [device_input_buffer.size];
|
||||
if (!device_input_buffer.buffer) return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((device_input_buffer.used + (bytes_available * 2)) > device_input_buffer.size)
|
||||
{ // need to increase the buffer size
|
||||
|
||||
// create a new larger buffer
|
||||
int new_size = device_input_buffer.used + bytes_available * 2;
|
||||
quint8 *new_buf = new quint8 [new_size];
|
||||
if (!new_buf) return;
|
||||
|
||||
// copy the data from the old buffer into the new buffer
|
||||
memmove(new_buf, device_input_buffer.buffer, device_input_buffer.used);
|
||||
|
||||
// delete the old buffer
|
||||
delete [] device_input_buffer.buffer;
|
||||
|
||||
// keep the new buffer
|
||||
device_input_buffer.buffer = new_buf;
|
||||
device_input_buffer.size = new_size;
|
||||
}
|
||||
}
|
||||
|
||||
// add the new data into the buffer
|
||||
qint64 bytes_read = m_ioDevice->read((char *)(device_input_buffer.buffer + device_input_buffer.used), device_input_buffer.size - device_input_buffer.used);
|
||||
if (bytes_read <= 0) return;
|
||||
device_input_buffer.used += bytes_read;
|
||||
|
||||
processRxBuffer();
|
||||
}
|
||||
|
||||
void PipXtremeGadgetWidget::processRxBuffer()
|
||||
{ // scan the buffer for a valid packet
|
||||
|
||||
if (!device_input_buffer.buffer || device_input_buffer.used < (int)sizeof(t_pipx_config_header))
|
||||
return; // no data as yet or not yet enough data
|
||||
|
||||
while (device_input_buffer.used >= (int)sizeof(t_pipx_config_header))
|
||||
{
|
||||
uint32_t crc1, crc2;
|
||||
|
||||
t_pipx_config_header *header = (t_pipx_config_header *)device_input_buffer.buffer;
|
||||
uint8_t *data = (uint8_t *)header + sizeof(t_pipx_config_header);
|
||||
|
||||
// check packet marker
|
||||
if (header->marker != PIPX_HEADER_MARKER)
|
||||
{ // marker not yet found
|
||||
// remove a byte
|
||||
int i = 1;
|
||||
if (i < device_input_buffer.used)
|
||||
memmove(device_input_buffer.buffer, device_input_buffer.buffer + i, device_input_buffer.used - i);
|
||||
device_input_buffer.used -= i;
|
||||
continue;
|
||||
}
|
||||
|
||||
// check the header CRC
|
||||
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
|
||||
int i = 1;
|
||||
if (i < device_input_buffer.used)
|
||||
memmove(device_input_buffer.buffer, device_input_buffer.buffer + i, device_input_buffer.used - i);
|
||||
device_input_buffer.used -= i;
|
||||
continue;
|
||||
}
|
||||
|
||||
// valid error free header found!
|
||||
|
||||
int total_packet_size = sizeof(t_pipx_config_header) + header->data_size;
|
||||
|
||||
if (device_input_buffer.used < total_packet_size)
|
||||
{ // not yet got a full packet
|
||||
break;
|
||||
}
|
||||
|
||||
if (header->data_size > 0)
|
||||
{
|
||||
// check the data crc
|
||||
crc1 = header->data_crc;
|
||||
crc2 = updateCRC32Data(0xffffffff, data, header->data_size);
|
||||
if (crc2 != crc1)
|
||||
{ // faulty data
|
||||
int i = 1;
|
||||
if (i < device_input_buffer.used)
|
||||
memmove(device_input_buffer.buffer, device_input_buffer.buffer + i, device_input_buffer.used - i);
|
||||
device_input_buffer.used -= i;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
processRxPacket(device_input_buffer.buffer, total_packet_size);
|
||||
|
||||
// remove the packet from the buffer
|
||||
if (total_packet_size < device_input_buffer.used)
|
||||
memmove(device_input_buffer.buffer, device_input_buffer.buffer + total_packet_size, device_input_buffer.used - total_packet_size);
|
||||
device_input_buffer.used -= total_packet_size;
|
||||
}
|
||||
}
|
||||
|
||||
void PipXtremeGadgetWidget::processRxPacket(quint8 *packet, int packet_size)
|
||||
{
|
||||
if (!packet || packet_size <= 0)
|
||||
return;
|
||||
|
||||
t_pipx_config_header *header = (t_pipx_config_header *)packet;
|
||||
uint8_t *data = (uint8_t *)header + sizeof(t_pipx_config_header);
|
||||
|
||||
switch (header->type)
|
||||
{
|
||||
case PIPX_PACKET_TYPE_REQ_DETAILS:
|
||||
break;
|
||||
|
||||
case PIPX_PACKET_TYPE_DETAILS:
|
||||
if (m_stage == PIPX_REQ_DETAILS)
|
||||
{
|
||||
m_stage_retries = 0;
|
||||
m_stage = PIPX_REQ_SETTINGS;
|
||||
|
||||
if (packet_size < (int)sizeof(t_pipx_config_header) + (int)sizeof(t_pipx_config_details))
|
||||
break; // packet size is too small - error
|
||||
|
||||
memcpy(&pipx_config_details, data, sizeof(t_pipx_config_details));
|
||||
|
||||
if (pipx_config_details.major_version < 0 || (pipx_config_details.major_version <= 0 && pipx_config_details.minor_version < 6))
|
||||
{
|
||||
QMessageBox msgBox;
|
||||
msgBox.setIcon(QMessageBox::Critical);
|
||||
msgBox.setText("You need to update your PipX modem firmware to V0.5 or later");
|
||||
msgBox.exec();
|
||||
disconnectPort(true);
|
||||
return;
|
||||
}
|
||||
|
||||
m_widget->lineEdit_FirmwareVersion->setText(QString::number(pipx_config_details.major_version) + "." + QString::number(pipx_config_details.minor_version));
|
||||
|
||||
m_widget->lineEdit_SerialNumber->setText(QString::number(pipx_config_details.serial_number, 16).toUpper());
|
||||
|
||||
if (pipx_config_details.frequency_band == FREQBAND_434MHz)
|
||||
m_widget->lineEdit_FrequencyBand->setText("434MHz");
|
||||
else
|
||||
if (pipx_config_details.frequency_band == FREQBAND_868MHz)
|
||||
m_widget->lineEdit_FrequencyBand->setText("868MHz");
|
||||
else
|
||||
if (pipx_config_details.frequency_band == FREQBAND_915MHz)
|
||||
m_widget->lineEdit_FrequencyBand->setText("915MHz");
|
||||
else
|
||||
m_widget->lineEdit_FrequencyBand->setText("UNKNOWN [" + QString::number(pipx_config_details.frequency_band) + "]");
|
||||
|
||||
m_widget->lineEdit_MinFrequency->setText(QString::number((double)pipx_config_details.min_frequency_Hz / 1e6, 'f', 6) + "MHz");
|
||||
m_widget->lineEdit_MaxFrequency->setText(QString::number((double)pipx_config_details.max_frequency_Hz / 1e6, 'f', 6) + "MHz");
|
||||
|
||||
m_widget->doubleSpinBox_Frequency->setMinimum((double)pipx_config_details.min_frequency_Hz / 1e6);
|
||||
m_widget->doubleSpinBox_Frequency->setMaximum((double)pipx_config_details.max_frequency_Hz / 1e6);
|
||||
m_widget->doubleSpinBox_Frequency->setSingleStep(((double)pipx_config_details.frequency_step_size * 4) / 1e6);
|
||||
|
||||
m_widget->lineEdit_FrequencyStepSize->setText(QString::number(pipx_config_details.frequency_step_size, 'f', 2) + "Hz");
|
||||
|
||||
m_widget->pushButton_Save->setEnabled(true);
|
||||
m_widget->pushButton_ScanSpectrum->setEnabled(true);
|
||||
m_widget->pushButton_Import->setEnabled(true);
|
||||
m_widget->pushButton_Export->setEnabled(true);
|
||||
}
|
||||
break;
|
||||
|
||||
case PIPX_PACKET_TYPE_REQ_SETTINGS:
|
||||
break;
|
||||
|
||||
case PIPX_PACKET_TYPE_SETTINGS:
|
||||
if (m_stage == PIPX_REQ_SETTINGS && pipx_config_details.serial_number != 0)
|
||||
{
|
||||
if (packet_size < (int)sizeof(t_pipx_config_header) + (int)sizeof(t_pipx_config_settings))
|
||||
break; // packet size is too small - error
|
||||
|
||||
m_stage_retries = 0;
|
||||
m_stage = PIPX_REQ_STATE;
|
||||
|
||||
memcpy(&pipx_config_settings, data, sizeof(t_pipx_config_settings));
|
||||
|
||||
m_widget->comboBox_Mode->setCurrentIndex(m_widget->comboBox_Mode->findData(pipx_config_settings.mode));
|
||||
m_widget->lineEdit_PairedSerialNumber->setText(QString::number(pipx_config_settings.destination_id, 16).toUpper());
|
||||
m_widget->spinBox_FrequencyCalibration->setValue(pipx_config_settings.rf_xtal_cap);
|
||||
m_widget->doubleSpinBox_Frequency->setValue((double)pipx_config_settings.frequency_Hz / 1e6);
|
||||
m_widget->comboBox_MaxRFBandwidth->setCurrentIndex(m_widget->comboBox_MaxRFBandwidth->findData(pipx_config_settings.max_rf_bandwidth));
|
||||
m_widget->comboBox_MaxRFTxPower->setCurrentIndex(m_widget->comboBox_MaxRFTxPower->findData(pipx_config_settings.max_tx_power));
|
||||
m_widget->comboBox_SerialPortSpeed->setCurrentIndex(m_widget->comboBox_SerialPortSpeed->findData(pipx_config_settings.serial_baudrate));
|
||||
m_widget->spinBox_RTSTime->setValue(pipx_config_settings.rts_time);
|
||||
|
||||
QString key = "";
|
||||
for (int i = 0; i < (int)sizeof(pipx_config_settings.aes_key); i++)
|
||||
key += QString::number(pipx_config_settings.aes_key[i], 16).rightJustified(2, '0');
|
||||
m_widget->lineEdit_AESKey->setText(key);
|
||||
m_widget->checkBox_AESEnable->setChecked(pipx_config_settings.aes_enable);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PIPX_PACKET_TYPE_REQ_STATE:
|
||||
break;
|
||||
|
||||
case PIPX_PACKET_TYPE_STATE:
|
||||
if (m_stage == PIPX_REQ_STATE && pipx_config_details.serial_number != 0)
|
||||
{
|
||||
if (packet_size < (int)sizeof(t_pipx_config_header) + (int)sizeof(t_pipx_config_state))
|
||||
break; // packet size is too small - error
|
||||
|
||||
m_stage_retries = 0;
|
||||
// m_stage = PIPX_REQ_STATE;
|
||||
|
||||
memcpy(&pipx_config_state, data, sizeof(t_pipx_config_state));
|
||||
|
||||
if (pipx_config_state.rssi < m_widget->widgetRSSI->minimum())
|
||||
m_widget->widgetRSSI->setValue(m_widget->widgetRSSI->minimum());
|
||||
else
|
||||
if (pipx_config_state.rssi > m_widget->widgetRSSI->maximum())
|
||||
m_widget->widgetRSSI->setValue(m_widget->widgetRSSI->maximum());
|
||||
else
|
||||
m_widget->widgetRSSI->setValue(pipx_config_state.rssi);
|
||||
m_widget->label_RSSI->setText("RSSI " + QString::number(pipx_config_state.rssi) + "dBm");
|
||||
m_widget->lineEdit_RxAFC->setText(QString::number(pipx_config_state.afc) + "Hz");
|
||||
m_widget->lineEdit_Retries->setText(QString::number(pipx_config_state.retries));
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PIPX_PACKET_TYPE_SPECTRUM: // a packet with scanned spectrum data
|
||||
if (pipx_config_details.serial_number != 0)
|
||||
{
|
||||
if (packet_size < (int)sizeof(t_pipx_config_header) + (int)sizeof(t_pipx_config_spectrum))
|
||||
break; // packet size is too small - error
|
||||
|
||||
memcpy(&pipx_config_spectrum, data, sizeof(t_pipx_config_spectrum));
|
||||
int8_t *spec_data = (int8_t *)(data + sizeof(t_pipx_config_spectrum));
|
||||
|
||||
if (pipx_config_spectrum.magnitudes > 0)
|
||||
{
|
||||
m_widget->label_19->setText(QString::number(pipx_config_spectrum.start_frequency) + " " + QString::number(pipx_config_spectrum.frequency_step_size) + " " + QString::number(pipx_config_spectrum.magnitudes));
|
||||
/*
|
||||
QGraphicsScene *spec_scene = m_widget->graphicsView_Spectrum->scene();
|
||||
if (spec_scene)
|
||||
{
|
||||
if (pipx_config_spectrum.start_frequency - pipx_config_details.min_frequency_Hz <= 0)
|
||||
spec_scene->clear();
|
||||
|
||||
int w = 500;
|
||||
int h = 500;
|
||||
|
||||
float xscale = (float)w / (pipx_config_details.max_frequency_Hz - pipx_config_details.min_frequency_Hz);
|
||||
float yscale = h / 128.0f;
|
||||
|
||||
float xs = xscale * (pipx_config_spectrum.start_frequency - pipx_config_details.min_frequency_Hz);
|
||||
|
||||
for (int i = 0; i < pipx_config_spectrum.magnitudes; i++)
|
||||
{
|
||||
int x = -(w / 2) + xs + (xscale * i * pipx_config_spectrum.frequency_step_size);
|
||||
int rssi = (int)spec_data[i] + 128;
|
||||
int y = yscale * rssi;
|
||||
spec_scene->addLine(x, -h / 2, x, (-h / 2) - y, QPen(Qt::green, 1, Qt::SolidLine, Qt::SquareCap));
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ***************************************************************************************
|
||||
|
||||
void PipXtremeGadgetWidget::processStream()
|
||||
{
|
||||
QMutexLocker locker_dev(&device_mutex);
|
||||
QMutexLocker locker_inbuf(&device_input_buffer.mutex);
|
||||
|
||||
if (!m_ioDevice) return;
|
||||
if (!m_ioDevice->isOpen()) return;
|
||||
|
||||
switch (m_stage)
|
||||
{
|
||||
case PIPX_IDLE:
|
||||
QTimer::singleShot(RETRY_TIME, this, SLOT(processStream()));
|
||||
break;
|
||||
|
||||
case PIPX_REQ_DETAILS:
|
||||
if (++m_stage_retries > MAX_RETRIES)
|
||||
{
|
||||
disconnectPort(true, false);
|
||||
break;
|
||||
}
|
||||
sendRequestDetails(0);
|
||||
QTimer::singleShot(RETRY_TIME, this, SLOT(processStream()));
|
||||
break;
|
||||
|
||||
case PIPX_REQ_SETTINGS:
|
||||
if (++m_stage_retries > MAX_RETRIES)
|
||||
{
|
||||
disconnectPort(true, false);
|
||||
break;
|
||||
}
|
||||
sendRequestSettings(pipx_config_details.serial_number);
|
||||
QTimer::singleShot(RETRY_TIME, this, SLOT(processStream()));
|
||||
break;
|
||||
|
||||
case PIPX_REQ_STATE:
|
||||
if (++m_stage_retries > MAX_RETRIES)
|
||||
{
|
||||
disconnectPort(true, false);
|
||||
break;
|
||||
}
|
||||
sendRequestState(pipx_config_details.serial_number);
|
||||
QTimer::singleShot(RETRY_TIME, this, SLOT(processStream()));
|
||||
break;
|
||||
|
||||
default:
|
||||
m_stage_retries = 0;
|
||||
m_stage = PIPX_IDLE;
|
||||
QTimer::singleShot(RETRY_TIME, this, SLOT(processStream()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// ***************************************************************************************
|
||||
|
||||
void PipXtremeGadgetWidget::disconnectPort(bool enable_telemetry, bool lock_stuff)
|
||||
{ // disconnect the comms port
|
||||
|
||||
if (lock_stuff)
|
||||
{
|
||||
QMutexLocker locker_dev(&device_mutex);
|
||||
QMutexLocker locker_inbuf(&device_input_buffer.mutex);
|
||||
}
|
||||
|
||||
m_stage_retries = 0;
|
||||
m_stage = PIPX_IDLE;
|
||||
|
||||
device_input_buffer.used = 0;
|
||||
|
||||
memset(&pipx_config_details, 0, sizeof(pipx_config_details));
|
||||
memset(&pipx_config_settings, 0, sizeof(pipx_config_settings));
|
||||
|
||||
if (m_ioDevice)
|
||||
{
|
||||
m_ioDevice->close();
|
||||
disconnect(m_ioDevice, 0, 0, 0);
|
||||
delete m_ioDevice;
|
||||
m_ioDevice = NULL;
|
||||
}
|
||||
|
||||
m_widget->connectButton->setText("Connect");
|
||||
m_widget->comboBox_SerialBaudrate->setEnabled(true);
|
||||
m_widget->comboBox_Ports->setEnabled(true);
|
||||
m_widget->refreshPorts->setEnabled(true);
|
||||
m_widget->pushButton_ScanSpectrum->setEnabled(false);
|
||||
m_widget->pushButton_Save->setEnabled(false);
|
||||
m_widget->pushButton_Import->setEnabled(false);
|
||||
m_widget->pushButton_Export->setEnabled(false);
|
||||
|
||||
m_widget->lineEdit_FirmwareVersion->setText("");
|
||||
m_widget->lineEdit_SerialNumber->setText("");
|
||||
m_widget->lineEdit_FrequencyBand->setText("");
|
||||
m_widget->lineEdit_MinFrequency->setText("");
|
||||
m_widget->lineEdit_MaxFrequency->setText("");
|
||||
m_widget->lineEdit_FrequencyStepSize->setText("");
|
||||
m_widget->lineEdit_LinkState->setText("");
|
||||
m_widget->widgetRSSI->setValue(m_widget->widgetRSSI->minimum());
|
||||
m_widget->label_RSSI->setText("RSSI");
|
||||
m_widget->lineEdit_RxAFC->setText("");
|
||||
m_widget->lineEdit_Retries->setText("");
|
||||
m_widget->lineEdit_PairedSerialNumber->setText("");
|
||||
m_widget->spinBox_FrequencyCalibration->setValue(0);
|
||||
m_widget->doubleSpinBox_Frequency->setValue(0);
|
||||
m_widget->lineEdit_AESKey->setText("");
|
||||
m_widget->checkBox_AESEnable->setChecked(false);
|
||||
|
||||
if (enable_telemetry)
|
||||
enableTelemetry();
|
||||
}
|
||||
|
||||
void PipXtremeGadgetWidget::connectPort()
|
||||
{ // connect the comms port
|
||||
|
||||
disconnectPort(true);
|
||||
|
||||
QMutexLocker locker_dev(&device_mutex);
|
||||
|
||||
int device_idx = m_widget->comboBox_Ports->currentIndex();
|
||||
if (device_idx < 0)
|
||||
return;
|
||||
|
||||
QString device_str = m_widget->comboBox_Ports->currentText().trimmed();
|
||||
if (device_str.isEmpty())
|
||||
return;
|
||||
|
||||
int type = NO_PORT;
|
||||
if (device_str.toLower().startsWith("com: "))
|
||||
{
|
||||
type = SERIAL_PORT;
|
||||
device_str.remove(0, 5);
|
||||
device_str = device_str.trimmed();
|
||||
}
|
||||
else
|
||||
if (device_str.toLower().startsWith("usb: "))
|
||||
{
|
||||
type = USB_PORT;
|
||||
device_str.remove(0, 5);
|
||||
device_str = device_str.trimmed();
|
||||
}
|
||||
|
||||
// type = m_widget->comboBox_Ports->itemData(device_idx).toInt();
|
||||
|
||||
// qDebug() << QString::number(type) << ": " << device_str;
|
||||
|
||||
// Suspend GCS telemety & polling
|
||||
disableTelemetry();
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case SERIAL_PORT: // serial port
|
||||
{
|
||||
QString str = getSerialPortDevice(device_str);
|
||||
if (str.isEmpty())
|
||||
break;
|
||||
|
||||
int br_idx = m_widget->comboBox_SerialBaudrate->currentIndex();
|
||||
if (br_idx < 0)
|
||||
break;
|
||||
|
||||
int baudrate = m_widget->comboBox_SerialBaudrate->itemData(br_idx).toInt();
|
||||
|
||||
BaudRateType bdt = BAUD57600;
|
||||
switch (baudrate)
|
||||
{
|
||||
case 1200: bdt = BAUD1200; break;
|
||||
case 2400: bdt = BAUD2400; break;
|
||||
case 4800: bdt = BAUD4800; break;
|
||||
case 9600: bdt = BAUD9600; break;
|
||||
case 19200: bdt = BAUD19200; break;
|
||||
case 38400: bdt = BAUD38400; break;
|
||||
case 57600: bdt = BAUD57600; break;
|
||||
case 115200: bdt = BAUD115200; break;
|
||||
case 128000: bdt = BAUD128000; break;
|
||||
case 256000: bdt = BAUD256000; break;
|
||||
#if (defined Q_OS_WIN)
|
||||
case 230400: bdt = BAUD230400; break;
|
||||
case 460800: bdt = BAUD460800; break;
|
||||
case 921600: bdt = BAUD921600; break;
|
||||
#endif
|
||||
}
|
||||
|
||||
PortSettings settings;
|
||||
settings.BaudRate = bdt;
|
||||
settings.DataBits = DATA_8;
|
||||
settings.Parity = PAR_NONE;
|
||||
settings.StopBits = STOP_1;
|
||||
settings.FlowControl = FLOW_OFF;
|
||||
settings.Timeout_Millisec = 1000;
|
||||
// settings.setQueryMode(QextSerialBase::EventDriven);
|
||||
|
||||
// QextSerialPort *serial_dev = new QextSerialPort(str, settings, QextSerialPort::Polling);
|
||||
// QextSerialPort *serial_dev = new QextSerialPort(str, settings, QextSerialPort::EventDriven);
|
||||
QextSerialPort *serial_dev = new QextSerialPort(str, settings);
|
||||
if (!serial_dev)
|
||||
break;
|
||||
|
||||
// if (!serial_dev->open(QIODevice::ReadWrite | QIODevice::Unbuffered))
|
||||
if (!serial_dev->open(QIODevice::ReadWrite))
|
||||
{
|
||||
delete serial_dev;
|
||||
break;
|
||||
}
|
||||
|
||||
m_ioDevice = serial_dev;
|
||||
break;
|
||||
}
|
||||
|
||||
case USB_PORT: // USB port
|
||||
{
|
||||
RawHID *usb_dev = new RawHID(device_str);
|
||||
if (!usb_dev)
|
||||
break;
|
||||
|
||||
// if (!usb_dev->open(QIODevice::ReadWrite | QIODevice::Unbuffered))
|
||||
if (!usb_dev->open(QIODevice::ReadWrite))
|
||||
{
|
||||
delete usb_dev;
|
||||
break;
|
||||
}
|
||||
|
||||
m_ioDevice = usb_dev;
|
||||
break;
|
||||
}
|
||||
|
||||
default: // unknown port type
|
||||
break;
|
||||
}
|
||||
|
||||
if (!m_ioDevice)
|
||||
{ // failed to connect .. restore GCS telemetry and polling
|
||||
enableTelemetry();
|
||||
}
|
||||
else
|
||||
{ // connected OK
|
||||
memset(&pipx_config_details, 0, sizeof(pipx_config_details));
|
||||
memset(&pipx_config_settings, 0, sizeof(pipx_config_settings));
|
||||
|
||||
m_widget->connectButton->setText("Disconnect");
|
||||
m_widget->comboBox_SerialBaudrate->setEnabled(false);
|
||||
m_widget->comboBox_Ports->setEnabled(false);
|
||||
m_widget->refreshPorts->setEnabled(false);
|
||||
|
||||
m_ioDevice->setTextModeEnabled(false);
|
||||
QTimer::singleShot(100, this, SLOT(processRxStream()));
|
||||
// connect(m_ioDevice, SIGNAL(readyRead()), this, SLOT(processRxStream()));
|
||||
|
||||
m_stage_retries = 0;
|
||||
m_stage = PIPX_REQ_DETAILS;
|
||||
QTimer::singleShot(100, this, SLOT(processStream()));
|
||||
}
|
||||
}
|
||||
|
||||
// ***************************************************************************************
|
||||
|
||||
void PipXtremeGadgetWidget::connectDisconnect()
|
||||
{
|
||||
if (m_ioDevice)
|
||||
disconnectPort(true); // disconnect
|
||||
else
|
||||
connectPort(); // connect
|
||||
}
|
||||
|
||||
// ***************************************************************************************
|
||||
|
||||
void PipXtremeGadgetWidget::importSettings()
|
||||
{
|
||||
QString filename = "pipx_" + QString::number(pipx_config_details.serial_number, 16).rightJustified(8, '0') + ".ini";
|
||||
|
||||
QFileDialog::Options options;
|
||||
QString selectedFilter;
|
||||
filename = QFileDialog::getOpenFileName(this,
|
||||
tr("Load from PipX settings file"),
|
||||
filename,
|
||||
tr("PipX settings (*.ini)"),
|
||||
&selectedFilter,
|
||||
options
|
||||
).trimmed();
|
||||
if (filename.isEmpty())
|
||||
return;
|
||||
|
||||
if (!QFileInfo(filename).isReadable())
|
||||
{
|
||||
QMessageBox msgBox;
|
||||
msgBox.setText(tr("Can't read file ") + QFileInfo(filename).absoluteFilePath());
|
||||
msgBox.exec();
|
||||
return;
|
||||
}
|
||||
|
||||
QSettings settings(filename, QSettings::IniFormat);
|
||||
|
||||
uint32_t serial_number = settings.value("details/serial_number", 0).toUInt();
|
||||
if (serial_number && serial_number != pipx_config_details.serial_number)
|
||||
{
|
||||
// return;
|
||||
}
|
||||
|
||||
pipx_config_settings.mode = settings.value("settings/mode", 0).toUInt();
|
||||
pipx_config_settings.destination_id = settings.value("settings/paired_serial_number", 0).toUInt();
|
||||
pipx_config_settings.rf_xtal_cap = settings.value("settings/frequency_calibration", 0x7f).toUInt();
|
||||
pipx_config_settings.frequency_Hz = settings.value("settings/frequency", (pipx_config_details.min_frequency_Hz + pipx_config_details.max_frequency_Hz) / 2).toUInt();
|
||||
pipx_config_settings.max_rf_bandwidth = settings.value("settings/max_rf_bandwidth", 128000).toUInt();
|
||||
pipx_config_settings.max_tx_power = settings.value("settings/max_tx_power", 4).toUInt();
|
||||
pipx_config_settings.serial_baudrate = settings.value("settings/serial_baudrate", 57600).toUInt();
|
||||
pipx_config_settings.aes_enable = settings.value("settings/aes_enable", false).toBool();
|
||||
for (int i = 0; i < (int)sizeof(pipx_config_settings.aes_key); i++)
|
||||
pipx_config_settings.aes_key[i] = settings.value("settings/aes_key_" + QString::number(i), 0).toUInt();
|
||||
pipx_config_settings.rts_time = settings.value("settings/ready_to_send_time", 10).toUInt();
|
||||
|
||||
m_widget->comboBox_Mode->setCurrentIndex(m_widget->comboBox_Mode->findData(pipx_config_settings.mode));
|
||||
m_widget->lineEdit_PairedSerialNumber->setText(QString::number(pipx_config_settings.destination_id, 16).toUpper());
|
||||
m_widget->spinBox_FrequencyCalibration->setValue(pipx_config_settings.rf_xtal_cap);
|
||||
m_widget->doubleSpinBox_Frequency->setValue((double)pipx_config_settings.frequency_Hz / 1e6);
|
||||
m_widget->comboBox_MaxRFBandwidth->setCurrentIndex(m_widget->comboBox_MaxRFBandwidth->findData(pipx_config_settings.max_rf_bandwidth));
|
||||
m_widget->comboBox_MaxRFTxPower->setCurrentIndex(m_widget->comboBox_MaxRFTxPower->findData(pipx_config_settings.max_tx_power));
|
||||
m_widget->comboBox_SerialPortSpeed->setCurrentIndex(m_widget->comboBox_SerialPortSpeed->findData(pipx_config_settings.serial_baudrate));
|
||||
m_widget->spinBox_RTSTime->setValue(pipx_config_settings.rts_time);
|
||||
|
||||
QString key = "";
|
||||
for (int i = 0; i < (int)sizeof(pipx_config_settings.aes_key); i++)
|
||||
key += QString::number(pipx_config_settings.aes_key[i], 16).rightJustified(2, '0');
|
||||
m_widget->lineEdit_AESKey->setText(key);
|
||||
m_widget->checkBox_AESEnable->setChecked(pipx_config_settings.aes_enable);
|
||||
}
|
||||
|
||||
void PipXtremeGadgetWidget::exportSettings()
|
||||
{
|
||||
QString filename = "pipx_" + QString::number(pipx_config_details.serial_number, 16).rightJustified(8, '0') + ".ini";
|
||||
|
||||
filename = QFileDialog::getSaveFileName(this,
|
||||
tr("Save to PipX settings file"),
|
||||
filename,
|
||||
tr("PipX settings (*.ini)")
|
||||
).trimmed();
|
||||
if (filename.isEmpty())
|
||||
return;
|
||||
/*
|
||||
if (QFileInfo(filename).exists())
|
||||
{
|
||||
QMessageBox msgBox;
|
||||
msgBox.setText(tr("File already exists."));
|
||||
msgBox.setInformativeText(tr("Do you want to overwrite the existing file?"));
|
||||
msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
|
||||
msgBox.setDefaultButton(QMessageBox::Ok);
|
||||
if (msgBox.exec() == QMessageBox::Ok)
|
||||
QFileInfo(filename).absoluteDir().remove(QFileInfo(filename).fileName());
|
||||
else
|
||||
return;
|
||||
}
|
||||
*/ QDir dir = QFileInfo(filename).absoluteDir();
|
||||
if (!dir.exists())
|
||||
{
|
||||
QMessageBox msgBox;
|
||||
msgBox.setText(tr("Can't write file ") + QFileInfo(filename).absoluteFilePath() + " since directory " + dir.absolutePath() + " doesn't exist!");
|
||||
msgBox.exec();
|
||||
return;
|
||||
}
|
||||
|
||||
QSettings settings(filename, QSettings::IniFormat);
|
||||
settings.setValue("details/serial_number", pipx_config_details.serial_number);
|
||||
settings.setValue("details/min_frequency", pipx_config_details.min_frequency_Hz);
|
||||
settings.setValue("details/max_frequency", pipx_config_details.max_frequency_Hz);
|
||||
settings.setValue("details/frequency_band", pipx_config_details.frequency_band);
|
||||
settings.setValue("settings/mode", pipx_config_settings.mode);
|
||||
settings.setValue("settings/paired_serial_number", pipx_config_settings.destination_id);
|
||||
settings.setValue("settings/frequency_calibration", pipx_config_settings.rf_xtal_cap);
|
||||
settings.setValue("settings/frequency", pipx_config_settings.frequency_Hz);
|
||||
settings.setValue("settings/max_rf_bandwidth", pipx_config_settings.max_rf_bandwidth);
|
||||
settings.setValue("settings/max_tx_power", pipx_config_settings.max_tx_power);
|
||||
settings.setValue("settings/serial_baudrate", pipx_config_settings.serial_baudrate);
|
||||
settings.setValue("settings/aes_enable", pipx_config_settings.aes_enable);
|
||||
settings.setValue("settings/ready_to_send_time", pipx_config_settings.rts_time);
|
||||
for (int i = 0; i < (int)sizeof(pipx_config_settings.aes_key); i++)
|
||||
settings.setValue("settings/aes_key_" + QString::number(i), pipx_config_settings.aes_key[i]);
|
||||
}
|
||||
|
||||
// ***************************************************************************************
|
||||
// Shows a message box with an error string.
|
||||
|
||||
void PipXtremeGadgetWidget::error(QString errorString, int errorNumber)
|
||||
{
|
||||
QMessageBox msgBox;
|
||||
msgBox.setIcon(QMessageBox::Critical);
|
||||
msgBox.setText(errorString + " [" + QString::number(errorNumber) + "]");
|
||||
msgBox.exec();
|
||||
}
|
||||
|
||||
// ***************************************************************************************
|
@ -1,211 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file pipxtremegadgetwidget.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @addtogroup GCSPlugins GCS Plugins
|
||||
* @{
|
||||
* @{
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* 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 PIPXTREMEGADGETWIDGET_H
|
||||
#define PIPXTREMEGADGETWIDGET_H
|
||||
|
||||
#include "ui_pipxtreme.h"
|
||||
|
||||
#include <qextserialport.h>
|
||||
#include <qextserialenumerator.h>
|
||||
|
||||
#include "uavtalk/telemetrymanager.h"
|
||||
#include "extensionsystem/pluginmanager.h"
|
||||
#include "uavobjects/uavobjectmanager.h"
|
||||
#include "uavobjects/uavobject.h"
|
||||
|
||||
#include "coreplugin/icore.h"
|
||||
#include "coreplugin/connectionmanager.h"
|
||||
|
||||
#include "rawhid/rawhidplugin.h"
|
||||
|
||||
#include <QtGui/QWidget>
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
#include <QThread>
|
||||
#include <QMessageBox>
|
||||
#include <QTimer>
|
||||
#include <QtCore/QVector>
|
||||
#include <QtCore/QIODevice>
|
||||
#include <QtCore/QLinkedList>
|
||||
#include <QMutex>
|
||||
#include <QMutexLocker>
|
||||
#include "widgetbar.h"
|
||||
|
||||
// *************************
|
||||
// pipx config comms packets
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
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];
|
||||
} 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;
|
||||
} t_pipx_config_details;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t mode;
|
||||
uint8_t link_state;
|
||||
int16_t rssi;
|
||||
int32_t afc;
|
||||
uint16_t retries;
|
||||
} t_pipx_config_state;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t mode;
|
||||
uint32_t serial_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];
|
||||
} t_pipx_config_settings;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t start_frequency;
|
||||
uint16_t frequency_step_size;
|
||||
uint16_t magnitudes;
|
||||
// int8_t magnitude[0];
|
||||
} t_pipx_config_spectrum;
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
// *************************
|
||||
|
||||
typedef struct
|
||||
{
|
||||
quint8 *buffer;
|
||||
int size;
|
||||
int used;
|
||||
QMutex mutex;
|
||||
} t_buffer;
|
||||
|
||||
// *************************
|
||||
|
||||
class PipXtremeGadgetWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
PipXtremeGadgetWidget(QWidget *parent = 0);
|
||||
~PipXtremeGadgetWidget();
|
||||
|
||||
public slots:
|
||||
void onTelemetryStart();
|
||||
void onTelemetryStop();
|
||||
void onTelemetryConnect();
|
||||
void onTelemetryDisconnect();
|
||||
|
||||
void onComboBoxPorts_currentIndexChanged(int index);
|
||||
|
||||
public slots:
|
||||
void updateStatus(UAVObject *object1);
|
||||
|
||||
protected:
|
||||
void resizeEvent(QResizeEvent *event);
|
||||
|
||||
private:
|
||||
typedef enum { PIPX_IDLE, PIPX_REQ_DETAILS, PIPX_REQ_SETTINGS, PIPX_REQ_STATE} PipXStage;
|
||||
|
||||
Ui_PipXtremeWidget *m_widget;
|
||||
|
||||
QIODevice *m_ioDevice;
|
||||
QMutex device_mutex;
|
||||
|
||||
t_buffer device_input_buffer;
|
||||
|
||||
PipXStage m_stage;
|
||||
int m_stage_retries;
|
||||
|
||||
// The PipXtreme status UAVObject
|
||||
UAVDataObject* pipxStatusObj;
|
||||
|
||||
// QVector<quint8> buffer;
|
||||
|
||||
t_pipx_config_details pipx_config_details;
|
||||
t_pipx_config_settings pipx_config_settings;
|
||||
t_pipx_config_state pipx_config_state;
|
||||
t_pipx_config_spectrum pipx_config_spectrum;
|
||||
|
||||
uint32_t updateCRC32(uint32_t crc, uint8_t b);
|
||||
uint32_t updateCRC32Data(uint32_t crc, void *data, int len);
|
||||
void makeCRC_Table32();
|
||||
|
||||
QString getSerialPortDevice(const QString &friendName);
|
||||
|
||||
void disableTelemetry();
|
||||
void enableTelemetry();
|
||||
|
||||
void sendRequestDetails(uint32_t serial_number);
|
||||
void sendRequestSettings(uint32_t serial_number);
|
||||
void sendRequestState(uint32_t serial_number);
|
||||
void sendSettings(uint32_t serial_number, t_pipx_config_settings *settings);
|
||||
|
||||
void processRxBuffer();
|
||||
void processRxPacket(quint8 *packet, int packet_size);
|
||||
|
||||
void disconnectPort(bool enable_telemetry, bool lock_stuff = true);
|
||||
void connectPort();
|
||||
|
||||
private slots:
|
||||
void importSettings();
|
||||
void exportSettings();
|
||||
void connectDisconnect();
|
||||
void error(QString errorString, int errorNumber);
|
||||
void getPorts();
|
||||
void randomiseAESKey();
|
||||
void scanSpectrum();
|
||||
void saveToFlash();
|
||||
void textChangedAESKey(const QString &text);
|
||||
void processStream();
|
||||
void processRxStream();
|
||||
|
||||
};
|
||||
|
||||
#endif
|
@ -1,61 +0,0 @@
|
||||
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file pipxtremeplugin.cpp
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @addtogroup GCSPlugins GCS Plugins
|
||||
* @{
|
||||
* @{
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* 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 "pipxtremeplugin.h"
|
||||
#include "pipxtremegadgetfactory.h"
|
||||
#include <QtPlugin>
|
||||
#include <QStringList>
|
||||
#include <extensionsystem/pluginmanager.h>
|
||||
|
||||
PipXtremePlugin::PipXtremePlugin()
|
||||
{
|
||||
mf = NULL;
|
||||
}
|
||||
|
||||
PipXtremePlugin::~PipXtremePlugin()
|
||||
{
|
||||
}
|
||||
|
||||
bool PipXtremePlugin::initialize(const QStringList &args, QString *errMsg)
|
||||
{
|
||||
Q_UNUSED(args);
|
||||
Q_UNUSED(errMsg);
|
||||
|
||||
mf = new PipXtremeGadgetFactory(this);
|
||||
addAutoReleasedObject(mf);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PipXtremePlugin::extensionsInitialized()
|
||||
{
|
||||
}
|
||||
|
||||
void PipXtremePlugin::shutdown()
|
||||
{
|
||||
}
|
||||
|
||||
Q_EXPORT_PLUGIN(PipXtremePlugin)
|
@ -1,48 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file pipxtremeplugin.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @addtogroup GCSPlugins GCS Plugins
|
||||
* @{
|
||||
* @{
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* 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 PIPXTREMEPLUGIN_H
|
||||
#define PIPXTREMEPLUGIN_H
|
||||
|
||||
#include <extensionsystem/iplugin.h>
|
||||
|
||||
class PipXtremeGadgetFactory;
|
||||
|
||||
class PipXtremePlugin : public ExtensionSystem::IPlugin
|
||||
{
|
||||
public:
|
||||
PipXtremePlugin();
|
||||
~PipXtremePlugin();
|
||||
|
||||
void extensionsInitialized();
|
||||
bool initialize(const QStringList & arguments, QString * errorString);
|
||||
void shutdown();
|
||||
|
||||
private:
|
||||
PipXtremeGadgetFactory *mf;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
@ -1,157 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file widgetbar.cpp
|
||||
* @author Cathy Moss Copyright (C) 2011.
|
||||
* Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2010.
|
||||
* @addtogroup GCSPlugins GCS Plugins
|
||||
* @{
|
||||
* @addtogroup ConfigPlugin Configuration Plugin
|
||||
* @{
|
||||
* @brief A bar display widget
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* 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 <QtGui>
|
||||
|
||||
#include "widgetbar.h"
|
||||
|
||||
WidgetBar::WidgetBar(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
m_maximum = 0;
|
||||
m_minimum = -120;
|
||||
m_value = -60;
|
||||
|
||||
// m_orientation = Qt::Vertical;
|
||||
m_orientation = Qt::Horizontal;
|
||||
|
||||
setBackgroundRole(QPalette::Base);
|
||||
setAutoFillBackground(true);
|
||||
}
|
||||
|
||||
QSize WidgetBar::minimumSizeHint() const
|
||||
{
|
||||
return QSize(8, 8);
|
||||
}
|
||||
|
||||
// QSize WidgetBar::sizeHint() const
|
||||
// {
|
||||
// return QSize(200, 400);
|
||||
// }
|
||||
|
||||
void WidgetBar::setMaximum(int value)
|
||||
{
|
||||
m_maximum = value;
|
||||
update();
|
||||
}
|
||||
|
||||
void WidgetBar::setMinimum(int value)
|
||||
{
|
||||
m_minimum = value;
|
||||
update();
|
||||
}
|
||||
|
||||
void WidgetBar::setValue(int value)
|
||||
{
|
||||
if (value < m_minimum) value = m_minimum;
|
||||
else
|
||||
if (value > m_maximum) value = m_maximum;
|
||||
|
||||
m_value = value;
|
||||
update();
|
||||
}
|
||||
|
||||
void WidgetBar::setOrientation(Qt::Orientation orientation)
|
||||
{
|
||||
m_orientation = orientation;
|
||||
update();
|
||||
}
|
||||
|
||||
void WidgetBar::paintEvent(QPaintEvent * /* event */)
|
||||
{
|
||||
QPainter painter(this);
|
||||
painter.setRenderHint(QPainter::Antialiasing, false);
|
||||
|
||||
int range = abs(m_maximum - m_minimum);
|
||||
if (range < 1) range = 1;
|
||||
|
||||
int value = m_value;
|
||||
if (value < m_minimum) value = m_minimum;
|
||||
else
|
||||
if (value > m_maximum) value = m_maximum;
|
||||
|
||||
float level = (float)(value - m_minimum) / range; // 0.0 to +1.0
|
||||
|
||||
int length = 0;
|
||||
QRect rect;
|
||||
|
||||
switch (m_orientation)
|
||||
{
|
||||
case Qt::Horizontal:
|
||||
{
|
||||
length = (int)((width() - 5) * level + 0.5f);
|
||||
rect.setLeft(2);
|
||||
rect.setTop(2);
|
||||
rect.setWidth(length);
|
||||
rect.setHeight(height() - 5);
|
||||
}
|
||||
break;
|
||||
|
||||
case Qt::Vertical:
|
||||
{
|
||||
length = (int)((height() - 5) * level + 0.5f);
|
||||
rect.setLeft(2);
|
||||
rect.setTop(height() - 3 - length);
|
||||
rect.setWidth(width() - 5);
|
||||
rect.setHeight(length);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// background
|
||||
painter.setPen(QColor(160, 160, 160));
|
||||
painter.setBrush(QColor(255, 255, 255));
|
||||
// painter.setPen(QColor(80, 80, 80));
|
||||
// painter.setPen(QColor(160, 160, 160));
|
||||
// painter.setBrush(QColor(160, 160, 160));
|
||||
painter.drawRect(QRect(0, 0, width() - 1, height() - 1));
|
||||
|
||||
if ((m_maximum - m_minimum) > 0)
|
||||
{
|
||||
// solid bar
|
||||
painter.setPen(QColor(128, 128, 255));
|
||||
painter.setBrush(QColor(128, 128, 255));
|
||||
painter.drawRoundRect(rect, 3, 3);
|
||||
/*
|
||||
// colourful bar
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
if (!(i & 1))
|
||||
painter.setPen(QColor(0, 0, 0)); // black
|
||||
else
|
||||
painter.setPen(QColor(128, 255, 128)); // green
|
||||
// painter.setPen(QColor(128, 128, 255)); // blue
|
||||
|
||||
if (m_orientation == Qt::Horizontal)
|
||||
painter.drawLine(rect.left() + i, rect.top(), rect.left() + i, rect.bottom() + 1); // horizontal bar
|
||||
else
|
||||
painter.drawLine(rect.left(), rect.bottom() + 1 - i, rect.right() + 1, rect.bottom() + 1 - i); // vertical bar
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file widgetbar.h
|
||||
* @author Cathy Moss Copyright (C) 2011.
|
||||
* Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2010.
|
||||
* @addtogroup GCSPlugins GCS Plugins
|
||||
* @{
|
||||
* @addtogroup ConfigPlugin Configuration Plugin
|
||||
* @{
|
||||
* @brief A bar display widget
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* 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 WIDGETBAR_H
|
||||
#define WIDGETBAR_H
|
||||
|
||||
#include <QBrush>
|
||||
#include <QPen>
|
||||
#include <QPixmap>
|
||||
#include <QWidget>
|
||||
|
||||
QT_MODULE(Gui)
|
||||
|
||||
class WidgetBar : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(int maximum READ maximum WRITE setMaximum)
|
||||
Q_PROPERTY(int minimum READ minimum WRITE setMinimum)
|
||||
Q_PROPERTY(int value READ value WRITE setValue)
|
||||
|
||||
Q_PROPERTY(Qt::Orientation orientation READ orientation WRITE setOrientation)
|
||||
|
||||
public:
|
||||
WidgetBar(QWidget *parent = 0);
|
||||
|
||||
QSize minimumSizeHint() const;
|
||||
// QSize sizeHint() const;
|
||||
|
||||
void setMaximum(int value);
|
||||
void setMinimum(int value);
|
||||
void setValue(int value);
|
||||
|
||||
int maximum() { return m_maximum; }
|
||||
int minimum() { return m_minimum; }
|
||||
int value() { return m_value; }
|
||||
|
||||
Qt::Orientation orientation() const { return m_orientation; }
|
||||
void setOrientation(Qt::Orientation orientation);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *event);
|
||||
|
||||
private:
|
||||
int m_maximum;
|
||||
int m_minimum;
|
||||
int m_value;
|
||||
|
||||
Qt::Orientation m_orientation;
|
||||
};
|
||||
|
||||
#endif
|
@ -173,13 +173,6 @@ SUBDIRS += plugin_gcscontrol
|
||||
#plugin_antennatrack.depends += plugin_uavtalk
|
||||
#SUBDIRS += plugin_antennatrack
|
||||
|
||||
#PipXtreme gadget
|
||||
plugin_pipxtreme.subdir = pipxtreme
|
||||
plugin_pipxtreme.depends = plugin_coreplugin
|
||||
plugin_pipxtreme.depends += plugin_uavobjects
|
||||
plugin_pipxtreme.depends += plugin_rawhid
|
||||
SUBDIRS += plugin_pipxtreme
|
||||
|
||||
#Scope OpenGL Gadget
|
||||
#plugin_scopeogl.subdir = scopeogl
|
||||
#plugin_scopeogl.depends = plugin_coreplugin
|
||||
|
Loading…
x
Reference in New Issue
Block a user