Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rssi: calculate signal and noise in firmware #240

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 23 additions & 21 deletions firmware/bluetooth_rxtx/bluetooth_rxtx.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ volatile uint8_t modulation = MOD_BT_BASIC_RATE;
/* specan stuff */
volatile uint16_t low_freq = 2400;
volatile uint16_t high_freq = 2483;
volatile int8_t rssi_threshold = -30; // -54dBm - 30 = -84dBm
volatile int8_t rssi_threshold = -84;

/* Generic TX stuff */
generic_tx_packet tx_pkt;
Expand Down Expand Up @@ -140,10 +140,12 @@ static int enqueue(uint8_t type, uint8_t* buf)
f->clkn_high = idle_buf_clkn_high;
f->clk100ns = idle_buf_clk100ns;
f->channel = (uint8_t)((idle_buf_channel - 2402) & 0xff);
f->rssi_min = rssi_min;
f->rssi_max = rssi_max;
f->rssi_avg = rssi_get_avg(idle_buf_channel);
f->rssi_count = rssi_count;
f->rssi_min = rssi_get_min();
f->rssi_max = rssi_get_max();
f->rssi_noise = rssi_get_noise();
f->rssi_signal = rssi_get_signal();
f->rssi_avg = rssi_get_avg();
f->rssi_count = rssi_get_cnt();
}

memcpy(f->data, buf, DMA_SIZE);
Expand Down Expand Up @@ -400,7 +402,7 @@ static int vendor_request_handler(uint8_t request, uint16_t* request_params, uin
case UBERTOOTH_LED_SPECAN:
if (request_params[0] > 256)
return 0;
rssi_threshold = 54 - request_params[0];
rssi_threshold = request_params[0];
requested_mode = MODE_LED_SPECAN;
*data_len = 0;
break;
Expand Down Expand Up @@ -1270,12 +1272,11 @@ void bt_stream_rx()
* at multiple trigger points there. The MAX() below
* helps with statistics in the case that cs_trigger
* happened before the loop started. */
rssi_reset();
rssi_at_trigger = INT8_MIN;
while (!rx_tc) {
rssi = (int8_t)(cc2400_get(RSSI) >> 8);
rssi = cc2400_rssi();
if (cs_trigger && (rssi_at_trigger == INT8_MIN)) {
rssi = MAX(rssi,(cs_threshold_cur+54));
rssi = MAX(rssi, cs_threshold_cur);
rssi_at_trigger = rssi;
}
rssi_add(rssi);
Expand All @@ -1284,6 +1285,7 @@ void bt_stream_rx()

/* If timer says time to hop, do it. */
if (do_hop) {
rssi_reset();
hop();
} else {
TXLED_CLR;
Expand All @@ -1307,8 +1309,6 @@ void bt_stream_rx()
dma_discard = 0;
}

rssi_iir_update(channel);

/* Set squelch hold if there was either a CS trigger, squelch
* is disabled, or if the current rssi_max is above the same
* threshold. Currently, this is redundant, but allows for
Expand All @@ -1318,12 +1318,14 @@ void bt_stream_rx()
cs_trigger = 0;
}

if (rssi_max >= (cs_threshold_cur + 54)) {
if (rssi_get_max() >= cs_threshold_cur) {
status |= RSSI_TRIGGER;
}

enqueue(BR_PACKET, (uint8_t*)idle_rxbuf);

rssi_reset();

handle_usb(clkn);
rx_tc = 0;
rx_err = 0;
Expand Down Expand Up @@ -1548,9 +1550,9 @@ void bt_generic_le(u8 active_mode)
rssi_at_trigger = INT8_MIN;
while ((rx_tc == 0) && (rx_err == 0))
{
rssi = (int8_t)(cc2400_get(RSSI) >> 8);
rssi = cc2400_rssi();
if (cs_trigger && (rssi_at_trigger == INT8_MIN)) {
rssi = MAX(rssi,(cs_threshold_cur+54));
rssi = MAX(rssi,cs_threshold_cur);
rssi_at_trigger = rssi;
}
rssi_add(rssi);
Expand All @@ -1568,8 +1570,6 @@ void bt_generic_le(u8 active_mode)
if (rx_tc > 1)
status |= DMA_OVERFLOW;

rssi_iir_update(channel);

/* Set squelch hold if there was either a CS trigger, squelch
* is disabled, or if the current rssi_max is above the same
* threshold. Currently, this is redundant, but allows for
Expand All @@ -1580,7 +1580,7 @@ void bt_generic_le(u8 active_mode)
cs_trigger = 0;
}

if (rssi_max >= (cs_threshold_cur + 54)) {
if (rssi_get_max(channel) >= cs_threshold_cur) {
status |= RSSI_TRIGGER;
hold = CS_HOLD_TIME;
}
Expand Down Expand Up @@ -1670,8 +1670,8 @@ void bt_le_sync(u8 active_mode)
while ((rx_tc == 0) && (rx_err == 0) && (do_hop == 0) && requested_mode == active_mode)
;

rssi = (int8_t)(cc2400_get(RSSI) >> 8);
rssi_min = rssi_max = rssi;
rssi = cc2400_rssi();
rssi_add(rssi);

if (requested_mode != active_mode) {
goto cleanup;
Expand Down Expand Up @@ -1747,6 +1747,8 @@ void bt_le_sync(u8 active_mode)
enqueue(LE_PACKET, (uint8_t *)packet);
le.last_packet = CLK100NS;

rssi_reset();

rx_flush:
// this might happen twice, but it's safe to do so
cc2400_strobe(SFSON);
Expand Down Expand Up @@ -2438,7 +2440,7 @@ void specan()
volatile u32 j = 500; while (--j); //FIXME crude delay
buf[3 * i] = (f >> 8) & 0xFF;
buf[(3 * i) + 1] = f & 0xFF;
buf[(3 * i) + 2] = cc2400_get(RSSI) >> 8;
buf[(3 * i) + 2] = cc2400_rssi();
i++;
if (i == 16) {
enqueue(SPECAN, buf);
Expand Down Expand Up @@ -2484,7 +2486,7 @@ void led_specan()

/* give the CC2400 time to acquire RSSI reading */
volatile u32 j = 500; while (--j); //FIXME crude delay
lvl = (int8_t)((cc2400_get(RSSI) >> 8) & 0xff);
lvl = cc2400_rssi();
if (lvl > rssi_threshold) {
switch (i) {
case 0:
Expand Down
119 changes: 81 additions & 38 deletions firmware/bluetooth_rxtx/ubertooth_rssi.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,58 +23,101 @@

#include <string.h>

#define RSSI_IIR_ALPHA 3 // 3/256 = .012
#define RINGBUFFER_SIZE 40

int32_t rssi_sum;
int16_t rssi_iir[79] = {0};
size_t pointer = 0;
size_t size = 0;
int8_t values[RINGBUFFER_SIZE] = {0};

int8_t max = -120;
int8_t min = 0;

void rssi_reset(void)
{
memset(rssi_iir, 0, sizeof(rssi_iir));
memset(values, 0, size);
pointer = 0;
size = 0;

rssi_count = 0;
rssi_sum = 0;
rssi_max = INT8_MIN;
rssi_min = INT8_MAX;
max = -120;
min = 0;
}

void rssi_add(int8_t v)
{
rssi_max = (v > rssi_max) ? v : rssi_max;
rssi_min = (v < rssi_min) ? v : rssi_min;
rssi_sum += ((int32_t)v * 256); // scaled int math (x256)
rssi_count += 1;
max = (v > max) ? v : max;
min = (v < min) ? v : min;

values[pointer] = v;
pointer = (pointer + 1) % RINGBUFFER_SIZE;

size = size < RINGBUFFER_SIZE ? size + 1 : RINGBUFFER_SIZE;
}

int8_t rssi_get_avg()
{
int32_t sum = 0;

for (size_t i = 0; i < size; i++)
{
sum += values[i];
}

uint8_t avg = (int8_t)(sum / (int)size);

return avg;
}

/* For sweep mode, update IIR per channel. Otherwise, use single value. */
void rssi_iir_update(uint16_t channel)
int8_t rssi_get_signal()
{
int32_t avg;
int32_t rssi_iir_acc;

/* Use array to track 79 Bluetooth channels, or just first slot
* of array if the frequency is not a valid Bluetooth channel. */
if ( channel < 2402 || channel < 2480 )
channel = 2402;

int i = channel - 2402;

// IIR using scaled int math (x256)
if (rssi_count != 0)
avg = (rssi_sum + 128) / rssi_count;
else
avg = 0; // really an error
rssi_iir_acc = rssi_iir[i] * (256-RSSI_IIR_ALPHA);
rssi_iir_acc += avg * RSSI_IIR_ALPHA;
rssi_iir[i] = (int16_t)((rssi_iir_acc + 128) / 256);
int32_t sum = 0;
size_t num = 0;
int8_t avg = ((int16_t)min + (int16_t)max) / 2;

for (size_t i = 0; i < size; i++)
{
if (values[i] > avg)
{
sum += values[i];
num++;
}
}

int8_t signal = (int8_t)(sum / (int)num);

return signal;
}

int8_t rssi_get_avg(uint16_t channel)
int8_t rssi_get_noise()
{
/* Use array to track 79 Bluetooth channels, or just first slot
* of array if the frequency is not a valid Bluetooth channel. */
if ( channel < 2402 || channel < 2480 )
channel = 2402;
int32_t sum = 0;
size_t num = 0;
int8_t avg = ((int16_t)min + (int16_t)max) / 2;

return (rssi_iir[channel-2402] + 128) / 256;
for (size_t i = 0; i < size; i++)
{
if (values[i] <= avg)
{
sum += values[i];
num++;
}
}

int8_t noise = (int8_t)(sum / (int)num);

return noise;
}

uint8_t rssi_get_cnt()
{
return (uint8_t)size;
}

int8_t rssi_get_min()
{
return min;
}

int8_t rssi_get_max()
{
return max;
}
14 changes: 7 additions & 7 deletions firmware/bluetooth_rxtx/ubertooth_rssi.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,13 @@

#include "inttypes.h"

int8_t rssi_max;
int8_t rssi_min;
uint8_t rssi_count;

void rssi_reset(void);
void rssi_reset();
void rssi_add(int8_t v);
void rssi_iir_update(uint16_t channel);
int8_t rssi_get_avg(uint16_t channel);
int8_t rssi_get_avg();
int8_t rssi_get_signal();
int8_t rssi_get_noise();
int8_t rssi_get_min();
int8_t rssi_get_max();
uint8_t rssi_get_cnt();

#endif
15 changes: 10 additions & 5 deletions firmware/common/ubertooth.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ void wait_us(u32 us)
*/
void gpio_init()
{
/*
/*
* Set all pins for GPIO. This shouldn't be necessary after a reset, but
* we might get called at other times.
*/
Expand Down Expand Up @@ -306,6 +306,11 @@ u16 cc2400_get(u8 reg)
return in & 0xFFFF;
}

int8_t cc2400_rssi()
{
return (int8_t)(cc2400_get(RSSI) >> 8) - 54;
}

/* write 16 bit value to a register */
void cc2400_set(u8 reg, u16 val)
{
Expand Down Expand Up @@ -374,7 +379,7 @@ void cc2400_fifo_write(u8 len, u8 *data) {
SCLK_SET;
SCLK_CLR;
}

spi_delay();
/* end transaction by raising CSN */
CSN_SET;
Expand Down Expand Up @@ -531,9 +536,9 @@ void reset()
USRLED_CLR;
WDMOD |= WDMOD_WDEN | WDMOD_WDRESET;
WDFEED_SEQUENCE;

/* Set watchdog timeout to 256us (minimum) */

/* sleep for 1s (minimum) */
wait(1);
}
Expand Down Expand Up @@ -633,7 +638,7 @@ void get_part_num(uint8_t *buffer, int *len)
buffer[3] = (result[1] >> 16) & 0xFF;
buffer[4] = (result[1] >> 24) & 0xFF;
*len = 5;

}

void get_device_serial(uint8_t *buffer, int *len)
Expand Down
1 change: 1 addition & 0 deletions firmware/common/ubertooth.h
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,7 @@ void atest_init(void);
void cc2400_init(void);
u32 cc2400_spi(u8 len, u32 data);
u16 cc2400_get(u8 reg);
int8_t cc2400_rssi();
void cc2400_set(u8 reg, u16 val);
u8 cc2400_get8(u8 reg);
void cc2400_set8(u8 reg, u8 val);
Expand Down
Loading