1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2025-01-17 02:52:12 +01:00

RFM22B: Fixed status reporting and connection status for OPLink.

This commit is contained in:
Brian Webb 2012-10-21 19:51:27 -04:00 committed by Brian Webb
parent 15fc29560a
commit 9f43e1151c
2 changed files with 161 additions and 122 deletions

View File

@ -192,11 +192,16 @@ static void systemTask(void *parameters)
prev_tx_count = tx_count;
prev_rx_count = rx_count;
}
oplinkStatus.LinkState = OPLINKSTATUS_LINKSTATE_DISCONNECTED;
if (radio_stats.connected)
{
oplinkStatus.LinkState = OPLINKSTATUS_LINKSTATE_CONNECTED;
LINK_LED_ON;
}
else
{
oplinkStatus.LinkState = OPLINKSTATUS_LINKSTATE_DISCONNECTED;
LINK_LED_OFF;
}
// Update the object
OPLinkStatusSet(&oplinkStatus);

View File

@ -178,6 +178,7 @@ static bool rfm22_sendStatus(struct pios_rfm22b_dev *rfm22b_dev);
static void rfm22b_add_rx_status(struct pios_rfm22b_dev *rfm22b_dev, enum pios_rfm22b_rx_packet_status status);
static bool rfm22_receivePacket(struct pios_rfm22b_dev *rfm22b_dev, PHPacketHandle p, uint16_t rx_len);
static void rfm22_setNominalCarrierFrequency(struct pios_rfm22b_dev *rfm22b_dev, uint32_t frequency_hz);
static void rfm22_calculateLinkQuality(struct pios_rfm22b_dev *rfm22b_dev);
// SPI read/write functions
static void rfm22_assertCs();
@ -661,56 +662,25 @@ void PIOS_RFM22B_GetStats(uint32_t rfm22b_id, struct rfm22b_stats *stats) {
struct pios_rfm22b_dev *rfm22b_dev = (struct pios_rfm22b_dev *)rfm22b_id;
if(!PIOS_RFM22B_validate(rfm22b_dev))
return;
*stats = rfm22b_dev->stats;
// Add the RX packet statistics
stats->rx_good = 0;
stats->rx_corrected = 0;
stats->rx_error = 0;
stats->rx_missed = 0;
for (uint8_t i = 0; i < RFM22B_RX_PACKET_STATS_LEN; ++i)
{
uint32_t val = rfm22b_dev->rx_packet_stats[i];
for (uint8_t j = 0; j < 16; ++j)
{
switch ((val >> (j * 2)) & 0x3)
{
case RFM22B_GOOD_RX_PACKET:
stats->rx_good++;
break;
case RFM22B_CORRECTED_RX_PACKET:
stats->rx_corrected++;
break;
case RFM22B_ERROR_RX_PACKET:
stats->rx_error++;
break;
case RFM22B_MISSED_RX_PACKET:
stats->rx_missed++;
break;
}
}
}
// Calculate the link quality metric, which is related to the number of good packets in relation to the number of bad packets.
// Note: This assumes that the number of packets sampled for the stats is 64.
// Using this equation, error and missed packets are counted as -2, and corrected packets are counted as -1.
// The rage is 0 (all error or missed packets) to 128 (all good packets).
stats->link_quality = 64 + stats->rx_good - stats->rx_error - stats->rx_missed;
// Calculate the current link quality
rfm22_calculateLinkQuality(rfm22b_dev);
// We are connected if our destination ID is in the pair stats.
stats->connected = false;
rfm22b_dev->stats.connected = false;
if (rfm22b_dev->destination_id != 0xffffffff)
for (uint8_t i = 0; i < OPLINKSTATUS_PAIRIDS_NUMELEM; ++i)
{
if ((rfm22b_dev->pair_stats[i].pairID == rfm22b_dev->destination_id) &&
(rfm22b_dev->pair_stats[i].rssi > -127))
{
stats->rssi = rfm22b_dev->pair_stats[i].rssi;
stats->afc_correction = rfm22b_dev->pair_stats[i].afc_correction;
stats->connected = true;
rfm22b_dev->stats.rssi = rfm22b_dev->pair_stats[i].rssi;
rfm22b_dev->stats.afc_correction = rfm22b_dev->pair_stats[i].afc_correction;
rfm22b_dev->stats.connected = true;
break;
}
}
*stats = rfm22b_dev->stats;
}
/**
@ -847,6 +817,90 @@ static void PIOS_RFM22B_Task(void *parameters)
}
}
// ************************************
// 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 rfm22b_id, enum rfm22b_datarate datarate, bool data_whitening)
{
struct pios_rfm22b_dev * rfm22b_dev = (struct pios_rfm22b_dev *)rfm22b_id;
if(!PIOS_RFM22B_validate(rfm22b_dev))
return;
uint32_t datarate_bps = data_rate[datarate];
rfm22b_dev->datarate = datarate;
rfm22b_dev->max_packet_time = (uint16_t)((float)(PIOS_PH_MAX_PACKET * 8 * 1000) / (float)(datarate_bps) + 0.5);
// rfm22_if_filter_bandwidth
rfm22_write(0x1C, reg_1C[datarate]);
// rfm22_afc_loop_gearshift_override
rfm22_write(0x1D, reg_1D[datarate]);
// RFM22_afc_timing_control
rfm22_write(0x1E, reg_1E[datarate]);
// RFM22_clk_recovery_gearshift_override
rfm22_write(0x1F, reg_1F[datarate]);
// rfm22_clk_recovery_oversampling_ratio
rfm22_write(0x20, reg_20[datarate]);
// rfm22_clk_recovery_offset2
rfm22_write(0x21, reg_21[datarate]);
// rfm22_clk_recovery_offset1
rfm22_write(0x22, reg_22[datarate]);
// rfm22_clk_recovery_offset0
rfm22_write(0x23, reg_23[datarate]);
// rfm22_clk_recovery_timing_loop_gain1
rfm22_write(0x24, reg_24[datarate]);
// rfm22_clk_recovery_timing_loop_gain0
rfm22_write(0x25, reg_25[datarate]);
// rfm22_afc_limiter
rfm22_write(0x2A, reg_2A[datarate]);
/* This breaks all bit rates < 100000!
if (datarate_bps < 100000)
// rfm22_chargepump_current_trimming_override
rfm22_write(0x58, 0x80);
else
// rfm22_chargepump_current_trimming_override
rfm22_write(0x58, 0xC0);
*/
// rfm22_tx_data_rate1
rfm22_write(0x6E, reg_6E[datarate]);
// rfm22_tx_data_rate0
rfm22_write(0x6F, reg_6F[datarate]);
// 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_modulation_mode_control1
rfm22_write(0x70, reg_70[datarate] & ~RFM22_mmc1_enwhite);
else
// rfm22_modulation_mode_control1
rfm22_write(0x70, reg_70[datarate] | RFM22_mmc1_enwhite);
// rfm22_modulation_mode_control2
rfm22_write(0x71, reg_71[datarate]);
// rfm22_frequency_deviation
rfm22_write(0x72, reg_72[datarate]);
rfm22_write(RFM22_ook_counter_value1, 0x00);
rfm22_write(RFM22_ook_counter_value2, 0x00);
}
// ************************************
// SPI read/write
@ -1026,99 +1080,54 @@ static void rfm22_setNominalCarrierFrequency(struct pios_rfm22b_dev *rfm22b_dev,
rfm22_write(RFM22_nominal_carrier_frequency0, fc & 0xff);
}
void rfm22_setFreqHopChannel(uint8_t channel)
/*
static void rfm22_setFreqHopChannel(uint8_t channel)
{ // set the frequency hopping channel
g_rfm22b_dev->frequency_hop_channel = channel;
rfm22_write(RFM22_frequency_hopping_channel_select, channel);
}
uint32_t rfm22_freqHopSize(void)
static uint32_t rfm22_freqHopSize(void)
{ // return the frequency hopping step size
return ((uint32_t)g_rfm22b_dev->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 rfm22b_id, enum rfm22b_datarate datarate, bool data_whitening)
{
struct pios_rfm22b_dev * rfm22b_dev = (struct pios_rfm22b_dev *)rfm22b_id;
if(!PIOS_RFM22B_validate(rfm22b_dev))
return;
uint32_t datarate_bps = data_rate[datarate];
rfm22b_dev->datarate = datarate;
rfm22b_dev->max_packet_time = (uint16_t)((float)(PIOS_PH_MAX_PACKET * 8 * 1000) / (float)(datarate_bps) + 0.5);
// rfm22_if_filter_bandwidth
rfm22_write(0x1C, reg_1C[datarate]);
// rfm22_afc_loop_gearshift_override
rfm22_write(0x1D, reg_1D[datarate]);
// RFM22_afc_timing_control
rfm22_write(0x1E, reg_1E[datarate]);
// RFM22_clk_recovery_gearshift_override
rfm22_write(0x1F, reg_1F[datarate]);
// rfm22_clk_recovery_oversampling_ratio
rfm22_write(0x20, reg_20[datarate]);
// rfm22_clk_recovery_offset2
rfm22_write(0x21, reg_21[datarate]);
// rfm22_clk_recovery_offset1
rfm22_write(0x22, reg_22[datarate]);
// rfm22_clk_recovery_offset0
rfm22_write(0x23, reg_23[datarate]);
// rfm22_clk_recovery_timing_loop_gain1
rfm22_write(0x24, reg_24[datarate]);
// rfm22_clk_recovery_timing_loop_gain0
rfm22_write(0x25, reg_25[datarate]);
// rfm22_afc_limiter
rfm22_write(0x2A, reg_2A[datarate]);
/* This breaks all bit rates < 100000!
if (datarate_bps < 100000)
// rfm22_chargepump_current_trimming_override
rfm22_write(0x58, 0x80);
else
// rfm22_chargepump_current_trimming_override
rfm22_write(0x58, 0xC0);
*/
// rfm22_tx_data_rate1
rfm22_write(0x6E, reg_6E[datarate]);
// rfm22_tx_data_rate0
rfm22_write(0x6F, reg_6F[datarate]);
static void rfm22_calculateLinkQuality(struct pios_rfm22b_dev *rfm22b_dev)
{
// Add the RX packet statistics
rfm22b_dev->stats.rx_good = 0;
rfm22b_dev->stats.rx_corrected = 0;
rfm22b_dev->stats.rx_error = 0;
rfm22b_dev->stats.rx_missed = 0;
for (uint8_t i = 0; i < RFM22B_RX_PACKET_STATS_LEN; ++i)
{
uint32_t val = rfm22b_dev->rx_packet_stats[i];
for (uint8_t j = 0; j < 16; ++j)
{
switch ((val >> (j * 2)) & 0x3)
{
case RFM22B_GOOD_RX_PACKET:
rfm22b_dev->stats.rx_good++;
break;
case RFM22B_CORRECTED_RX_PACKET:
rfm22b_dev->stats.rx_corrected++;
break;
case RFM22B_ERROR_RX_PACKET:
rfm22b_dev->stats.rx_error++;
break;
case RFM22B_MISSED_RX_PACKET:
rfm22b_dev->stats.rx_missed++;
break;
}
}
}
// 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_modulation_mode_control1
rfm22_write(0x70, reg_70[datarate] & ~RFM22_mmc1_enwhite);
else
// rfm22_modulation_mode_control1
rfm22_write(0x70, reg_70[datarate] | RFM22_mmc1_enwhite);
// rfm22_modulation_mode_control2
rfm22_write(0x71, reg_71[datarate]);
// rfm22_frequency_deviation
rfm22_write(0x72, reg_72[datarate]);
rfm22_write(RFM22_ook_counter_value1, 0x00);
rfm22_write(RFM22_ook_counter_value2, 0x00);
// Calculate the link quality metric, which is related to the number of good packets in relation to the number of bad packets.
// Note: This assumes that the number of packets sampled for the stats is 64.
// Using this equation, error and missed packets are counted as -2, and corrected packets are counted as -1.
// The rage is 0 (all error or missed packets) to 128 (all good packets).
rfm22b_dev->stats.link_quality = 64 + rfm22b_dev->stats.rx_good - rfm22b_dev->stats.rx_error - rfm22b_dev->stats.rx_missed;
}
// ************************************
@ -1248,10 +1257,15 @@ static bool rfm22_sendStatus(struct pios_rfm22b_dev *rfm22b_dev)
{
PHPacketHandle sph = (PHPacketHandle)&(rfm22b_dev->status_packet);
// Update the link quality metric.
rfm22_calculateLinkQuality(rfm22b_dev);
// Queue the status message
rfm22b_dev->status_packet.header.destination_id = 0xffffffff; // Broadcast
rfm22b_dev->status_packet.header.type = PACKET_TYPE_STATUS;
rfm22b_dev->status_packet.header.data_size = PH_STATUS_DATA_SIZE(&(rfm22b_dev->status_packet));
rfm22b_dev->status_packet.link_quality = rfm22b_dev->stats.link_quality;
rfm22b_dev->status_packet.received_rssi = rfm22b_dev->rssi_dBm;
if (xQueueSend(rfm22b_dev->packetQueue, &sph, 0) != pdTRUE)
return false;
@ -1406,7 +1420,8 @@ static bool rfm22_receivePacket(struct pios_rfm22b_dev *rfm22b_dev, PHPacketHand
rx_error = false;
}
} else
}
else
rfm22b_add_rx_status(rfm22b_dev, RFM22B_GOOD_RX_PACKET);
return !rx_error;
@ -1625,6 +1640,9 @@ static enum pios_rfm22b_event rfm22_receiveStatus(struct pios_rfm22b_dev *rfm22b
rfm22b_dev->pair_stats[min_idx].lastContact = 0;
}
rfm22b_dev->stats.link_quality = status->link_quality;
rfm22b_dev->stats.rssi = status->received_rssi;
return RFM22B_EVENT_RX_COMPLETE;
}
@ -1904,6 +1922,14 @@ static enum pios_rfm22b_event rfm22_timeout(struct pios_rfm22b_dev *rfm22b_dev)
{
rfm22b_dev->resets++;
rfm22b_dev->packet_start_ticks = 0;
// Release the Tx packet if it's set.
if (rfm22b_dev->tx_packet != 0)
{
PHReleaseTXPacket(pios_packet_handler, rfm22b_dev->tx_packet);
rfm22b_dev->tx_packet = 0;
rfm22b_dev->tx_data_rd = rfm22b_dev->tx_data_wr = 0;
}
rfm22b_dev->rx_buffer_wr = 0;
return RFM22B_EVENT_TX_START;
}
@ -1911,6 +1937,14 @@ static enum pios_rfm22b_event rfm22_error(struct pios_rfm22b_dev *rfm22b_dev)
{
rfm22b_dev->resets++;
rfm22b_dev->packet_start_ticks = 0;
// Release the Tx packet if it's set.
if (rfm22b_dev->tx_packet != 0)
{
PHReleaseTXPacket(pios_packet_handler, rfm22b_dev->tx_packet);
rfm22b_dev->tx_packet = 0;
rfm22b_dev->tx_data_rd = rfm22b_dev->tx_data_wr = 0;
}
rfm22b_dev->rx_buffer_wr = 0;
return RFM22B_EVENT_INITIALIZE;
}