From 6b5797bbf49fe704d563a3b01b9320dd51dac8d9 Mon Sep 17 00:00:00 2001 From: aanper Date: Sun, 18 Oct 2020 07:47:49 +0300 Subject: [PATCH] rx example --- .../cc1101-workaround/cc1101-workaround.cpp | 283 ++++++++---------- 1 file changed, 126 insertions(+), 157 deletions(-) diff --git a/applications/cc1101-workaround/cc1101-workaround.cpp b/applications/cc1101-workaround/cc1101-workaround.cpp index 79b06f0a..f149c0bc 100644 --- a/applications/cc1101-workaround/cc1101-workaround.cpp +++ b/applications/cc1101-workaround/cc1101-workaround.cpp @@ -2,37 +2,11 @@ #include "cc1101-workaround/cc1101.h" -#define MIN_DBM -120 -#define STEP_DBM 10 -#define RSSI_DELAY 600 //rssi delay in micro second - -#define RSSI_THRESHOLD -60 - -#define START_SUB_BAND 3 -#define STOP_SUB_BAND 3 +#define RSSI_DELAY 5000 //rssi delay in micro second #define NUM_OF_SUB_BANDS 7 -#define CAL_INT 20 // cal every 10 channels(every 1MHz) - -// variables used to calculate rssi -uint8_t rssi_dec; -int16_t rssi_dBm; -uint8_t rssi_offset[NUM_OF_SUB_BANDS] = {74, 74, 74, 74, 74, 74, 74}; - #define CHAN_SPA 0.05 // channel spacing -// no change in TEST0 WHERE (>430.5MHz) one should change from TEST0=0x0B to 0x09 -uint16_t limitTest0Reg[NUM_OF_SUB_BANDS] = {256, 256, 256, 103, 0, 0, 0}; - -/* setting to use 50khz channel spacing whole band*****************************************/ - -int16_t rssiTable[256]; -uint16_t channelNumber[256]; - -// counter used to keep track on how many CS has been asserted -uint8_t carrierSenseCounter = 0; - - -int16_t calRSSI(uint8_t rssi_dec, uint8_t rssiOffset) { +int16_t rssi_to_dbm(uint8_t rssi_dec, uint8_t rssiOffset) { int16_t rssi; if(rssi_dec >= 128) { @@ -44,131 +18,12 @@ int16_t calRSSI(uint8_t rssi_dec, uint8_t rssiOffset) { return rssi; } -/* -void scanFreq(CC1101* cc1101) { - uint8_t calCounter; // to determine when to calibrate - uint8_t subBand; - uint16_t channel; - uint16_t i; - - float freq; - - cc1101->SpiWriteReg(CC1101_MCSM0, 0x08); // disalbe FS_AUTOCAL - cc1101->SpiWriteReg(CC1101_AGCCTRL2, 0x43 | 0x0C); // MAX_DVGA_GAIN to 11 for fast rssi - cc1101->SpiWriteReg(CC1101_AGCCTRL0, 0xB0); // max AGC WAIT_TIME; 0 filter_length - cc1101->SetMod(GFSK); // set to GFSK for fast rssi measurement | +8 is dcfilter off - - // 1) loop through all sub bands - for(subBand = START_SUB_BAND; subBand < STOP_SUB_BAND + 1; subBand++) { - // 1.1) set subBands freq by FREQ2, FREQ1, FREQ0 - cc1101->SetFreq( - freqSettings[subBand][0], freqSettings[subBand][1], freqSettings[subBand][2]); - // 1.2) set TEST0--maybe! - // 1.3) reset calibration counter - calCounter = 0; - // 1.4) loop throuhg all channels - for(channel = firstChannel[subBand]; channel <= lastChannel[subBand]; channel++) { - uint8_t pktStatus; - // 1.4.1) set channel register - cc1101->SetChannel(channel); - - // 1.4.2) set TEST0 - if(channel == limitTest0Reg[subBand]) { - //set test0 to 0x09 - cc1101->SpiWriteReg(CC1101_TEST0, 0x09); - //set FSCAL2 to 0x2A to force VCO HIGH - cc1101->SpiWriteReg(CC1101_FSCAL2, 0x2A); - //clear calCounter to invoke mannual calibration - calCounter = 0; - } - // 1.4.3) calibrate every 1MHz - if(calCounter++ == 0) { - // perform a manual calibration by issuing SCAL command - cc1101->SpiStrobe(CC1101_SCAL); - } - // 1.4.4) reset calCounter when 1MHz reached - if(calCounter == CAL_INT) { - calCounter = 0; - } - // 1.4.5-6 enter rx mode - cc1101->SetReceive(); - // 1.4.7 wait for RSSI to be valid: less than 1.5ms - delayMicroseconds(RSSI_DELAY); - // 1.4.8) read PKTSTATUS register while the radio is in RX state - pktStatus = cc1101->SpiReadStatus(CC1101_PKTSTATUS); - // 1.4.9) enter IDLE state by issuing a SIDLE command - cc1101->SpiStrobe(CC1101_SIDLE); - // 1.4.10) check if CS is assearted - // //read rssi value and converto to dBm form - rssi_dec = (uint8_t)cc1101->SpiReadStatus(CC1101_RSSI); - rssi_dBm = calRSSI(rssi_dec, rssi_offset[subBand]); - - // rssiData[subBand][channel]=rssi_dBm; - if(pktStatus & 0x40) { //CS assearted - // store rssi value and corresponding channel number - rssiTable[carrierSenseCounter] = rssi_dBm; - channelNumber[carrierSenseCounter] = channel; - carrierSenseCounter++; - } - -#ifdef CC1101_DEBUG - printf("rssi_dBm: %d\n", rssi_dBm); -#endif - } // end channel lop - - // 1.5)before moving to next sub band, - // scan through rssiTable to find highest rssi value - for(i = 0; i < carrierSenseCounter; i++) { - if(rssiTable[i] > highRSSI[subBand]) { - highRSSI[subBand] = rssiTable[i]; - selectedChannel[subBand] = channelNumber[i]; - } - } - - // printf("subBand:------------------>"); - // Serial.println(subBand); - // Serial.print("selectedChannel:"); - // Serial.println(selectedChannel[subBand]); - // Serial.print("highRSSI:"); - // Serial.println(highRSSI[subBand]); - - // 1.6) reset carrierSenseCounter - carrierSenseCounter = 0; - } // end band loop - - // 2) when all sub bands has been scanned , find best subband and channel - int16_t tempRssi = MIN_DBM; - for(subBand = 0; subBand < NUM_OF_SUB_BANDS; subBand++) { - if(highRSSI[subBand] > tempRssi) { - tempRssi = highRSSI[subBand]; - activeChannel = selectedChannel[subBand]; - activeBand = subBand; - } - } - - // printf("activeBand:**********> %d, activeChannel %d,\n", activeBand, activeChannel); - - cc1101->SpiWriteReg(CC1101_MCSM0, 0x18); //enable FS_AUTOCAL - cc1101->SpiWriteReg(CC1101_AGCCTRL2, 0x43); //back to recommended config - cc1101->SpiWriteReg(CC1101_AGCCTRL0, 0x91); //back to recommended config -} - -void tx(CC1101* cc1101, uint8_t band, uint16_t channel, uint16_t miniSec) { - cc1101->SetFreq(freqSettings[band][0], freqSettings[band][1], freqSettings[band][2]); - cc1101->SetChannel(channel); - // digitalWrite(19,0); - cc1101->SetTransmit(); - delay(miniSec); - - cc1101->SpiStrobe(CC1101_SIDLE); -} -*/ - typedef struct { float base_freq; - uint8_t settings[3]; // FREQ2, FREQ1, FREQ0 + uint8_t reg[3]; // FREQ2, FREQ1, FREQ0 uint8_t first_channel; uint8_t last_channel; + uint8_t rssi_offset; } Band; typedef struct { @@ -176,14 +31,65 @@ typedef struct { uint16_t channel; } FreqConfig; +void setup_freq(CC1101* cc1101, FreqConfig* config) { + cc1101->SpiWriteReg(CC1101_MCSM0, 0x08); // disalbe FS_AUTOCAL + cc1101->SpiWriteReg(CC1101_AGCCTRL2, 0x43 | 0x0C); // MAX_DVGA_GAIN to 11 for fast rssi + cc1101->SpiWriteReg(CC1101_AGCCTRL0, 0xB0); // max AGC WAIT_TIME; 0 filter_length + cc1101->SetMod(GFSK); // set to GFSK for fast rssi measurement | +8 is dcfilter off + + cc1101->SetFreq(config->band->reg[0], config->band->reg[1], config->band->reg[2]); + cc1101->SetChannel(config->channel); + + //set test0 to 0x09 + cc1101->SpiWriteReg(CC1101_TEST0, 0x09); + //set FSCAL2 to 0x2A to force VCO HIGH + cc1101->SpiWriteReg(CC1101_FSCAL2, 0x2A); + + // perform a manual calibration by issuing SCAL command + cc1101->SpiStrobe(CC1101_SCAL); + + /* + // Cleanup: + cc1101->SpiWriteReg(CC1101_MCSM0, 0x18); //enable FS_AUTOCAL + cc1101->SpiWriteReg(CC1101_AGCCTRL2, 0x43); //back to recommended config + cc1101->SpiWriteReg(CC1101_AGCCTRL0, 0x91); //back to recommended config + */ +} + +int16_t rx_rssi(CC1101* cc1101, FreqConfig* config) { + cc1101->SetReceive(); + + delayMicroseconds(RSSI_DELAY); + + // 1.4.8) read PKTSTATUS register while the radio is in RX state + uint8_t _pkt_status = cc1101->SpiReadStatus(CC1101_PKTSTATUS); + + // 1.4.9) enter IDLE state by issuing a SIDLE command + cc1101->SpiStrobe(CC1101_SIDLE); + + // //read rssi value and converto to dBm form + uint8_t rssi_dec = (uint8_t)cc1101->SpiReadStatus(CC1101_RSSI); + int16_t rssi_dBm = rssi_to_dbm(rssi_dec, config->band->rssi_offset); + + return rssi_dBm; +} + +void tx(CC1101* cc1101) { + cc1101->SetTransmit(); +} + +void idle(CC1101* cc1101) { + cc1101->SpiStrobe(CC1101_SIDLE); +} + Band bands[NUM_OF_SUB_BANDS] = { - {387, {0x0E, 0xE2, 0x76}, 0, 255}, - {399.8, {0x0F, 0x60, 0x76}, 0, 255}, - {412.6, {0x0F, 0xDE, 0x76}, 0, 255}, - {425.4, {0x10, 0x5C, 0x76}, 160, 180}, - {438.2, {0x10, 0xDA, 0x76}, 0, 255}, - {451, {0x11, 0x58, 0x8F}, 0, 255}, - {463.8, {0x11, 0xD6, 0x8F}, 0, 4}, + {387, {0x0E, 0xE2, 0x76}, 0, 255, 74}, + {399.8, {0x0F, 0x60, 0x76}, 0, 255, 74}, + {412.6, {0x0F, 0xDE, 0x76}, 0, 255, 74}, + {425.4, {0x10, 0x5C, 0x76}, 160, 180, 74}, + {438.2, {0x10, 0xDA, 0x76}, 0, 255, 74}, + {451, {0x11, 0x58, 0x8F}, 0, 255, 74}, + {463.8, {0x11, 0xD6, 0x8F}, 0, 4, 74}, }; FreqConfig FREQ_LIST[] = { @@ -237,6 +143,8 @@ typedef enum { typedef struct { Mode mode; size_t active_freq; + int16_t last_rssi; + bool need_cc1101_conf; } State; static void render_callback(CanvasApi* canvas, void* ctx) { @@ -257,6 +165,30 @@ static void render_callback(CanvasApi* canvas, void* ctx) { canvas->draw_str(canvas, 2, 25, buf); } + { + canvas->set_font(canvas, FontSecondary); + + if(state->need_cc1101_conf) { + canvas->draw_str(canvas, 2, 36, "mode: configuring..."); + } else if(state->mode == ModeRx) { + canvas->draw_str(canvas, 2, 36, "mode: RX"); + } else if(state->mode == ModeTx) { + canvas->draw_str(canvas, 2, 36, "mode: TX"); + } else { + canvas->draw_str(canvas, 2, 36, "mode: unknown"); + } + } + + { + if(!state->need_cc1101_conf && state->mode == ModeRx) { + char buf[24]; + sprintf(buf, "RSSI: %d dBm", state->last_rssi); + + canvas->set_font(canvas, FontSecondary); + canvas->draw_str(canvas, 2, 48, buf); + } + } + release_mutex((ValueMutex*)ctx, state); } @@ -277,6 +209,8 @@ extern "C" void cc1101_workaround(void* p) { State _state; _state.mode = ModeRx; _state.active_freq = 0; + _state.need_cc1101_conf = true; + _state.last_rssi = 0; ValueMutex state_mutex; if(!init_mutex(&state_mutex, &_state, sizeof(State))) { @@ -318,9 +252,17 @@ extern "C" void cc1101_workaround(void* p) { // 50khz channel spacing cc1101.SpiWriteReg(CC1101_MDMCFG0, 0xF8); + // create pin + GpioPin led = {GPIOA, GPIO_PIN_8}; + + // configure pin + pinMode(led, GpioModeOpenDrain); + + const int16_t RSSI_THRESHOLD = -89; + Event event; while(1) { - if(osMessageQueueGet(event_queue, &event, NULL, osWaitForever) == osOK) { + if(osMessageQueueGet(event_queue, &event, NULL, 150) == osOK) { State* state = (State*)acquire_mutex_block(&state_mutex); if(event.type == EventTypeKey) { @@ -334,16 +276,43 @@ extern "C" void cc1101_workaround(void* p) { if(event.value.input.state && event.value.input.input == InputUp) { if(state->active_freq > 0) { state->active_freq--; + state->need_cc1101_conf = true; } } if(event.value.input.state && event.value.input.input == InputDown) { if(state->active_freq < (sizeof(FREQ_LIST)/sizeof(FREQ_LIST[0]) - 1)) { state->active_freq++; + state->need_cc1101_conf = true; } } } + if(state->need_cc1101_conf) { + setup_freq(&cc1101, &FREQ_LIST[state->active_freq]); + + if(state->mode == ModeRx) { + state->last_rssi = rx_rssi(&cc1101, &FREQ_LIST[state->active_freq]); + } else if(state->mode == ModeTx) { + tx(&cc1101); + } + + state->need_cc1101_conf = false; + } + + digitalWrite(led, state->last_rssi > RSSI_THRESHOLD ? LOW : HIGH); + + release_mutex(&state_mutex, state); + widget_update(widget); + } else { + State* state = (State*)acquire_mutex_block(&state_mutex); + + if(!state->need_cc1101_conf && state->mode == ModeRx) { + state->last_rssi = rx_rssi(&cc1101, &FREQ_LIST[state->active_freq]); + } + + digitalWrite(led, state->last_rssi > RSSI_THRESHOLD ? LOW : HIGH); + release_mutex(&state_mutex, state); widget_update(widget); }