| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279 |
- #include "subghz_frequency_analyzer_worker.h"
- #include <lib/drivers/cc1101.h>
- #include <furi.h>
- #define TAG "SubghzFrequencyAnalyzerWorker"
- #define SUBGHZ_FREQUENCY_ANALYZER_THRESHOLD -95.0f
- static const uint8_t subghz_preset_ook_58khz[][2] = {
- {CC1101_MDMCFG4, 0b11110111}, // Rx BW filter is 58.035714kHz
- /* End */
- {0, 0},
- };
- static const uint8_t subghz_preset_ook_650khz[][2] = {
- {CC1101_MDMCFG4, 0b00010111}, // Rx BW filter is 650.000kHz
- /* End */
- {0, 0},
- };
- struct SubGhzFrequencyAnalyzerWorker {
- FuriThread* thread;
- volatile bool worker_running;
- uint8_t sample_hold_counter;
- FrequencyRSSI frequency_rssi_buf;
- SubGhzSetting* setting;
- float filVal;
- SubGhzFrequencyAnalyzerWorkerPairCallback pair_callback;
- void* context;
- };
- static void subghz_frequency_analyzer_worker_load_registers(const uint8_t data[][2]) {
- furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz);
- size_t i = 0;
- while(data[i][0]) {
- cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, data[i][0], data[i][1]);
- i++;
- }
- furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz);
- }
- // running average with adaptive coefficient
- static uint32_t subghz_frequency_analyzer_worker_expRunningAverageAdaptive(
- SubGhzFrequencyAnalyzerWorker* instance,
- uint32_t newVal) {
- float k;
- float newValFloat = newVal;
- // the sharpness of the filter depends on the absolute value of the difference
- if(fabs(newValFloat - instance->filVal) > 500000)
- k = 0.9;
- else
- k = 0.03;
- instance->filVal += (newValFloat - instance->filVal) * k;
- return (uint32_t)instance->filVal;
- }
- /** Worker thread
- *
- * @param context
- * @return exit code
- */
- static int32_t subghz_frequency_analyzer_worker_thread(void* context) {
- SubGhzFrequencyAnalyzerWorker* instance = context;
- FrequencyRSSI frequency_rssi = {.frequency = 0, .rssi = 0};
- float rssi = 0;
- uint32_t frequency = 0;
- CC1101Status status;
- //Start CC1101
- furi_hal_subghz_reset();
- furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz);
- cc1101_flush_rx(&furi_hal_spi_bus_handle_subghz);
- cc1101_flush_tx(&furi_hal_spi_bus_handle_subghz);
- cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHW);
- cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_MDMCFG3,
- 0b01111111); // symbol rate
- cc1101_write_reg(
- &furi_hal_spi_bus_handle_subghz,
- CC1101_AGCCTRL2,
- 0b00000111); // 00 - DVGA all; 000 - MAX LNA+LNA2; 111 - MAGN_TARGET 42 dB
- cc1101_write_reg(
- &furi_hal_spi_bus_handle_subghz,
- CC1101_AGCCTRL1,
- 0b00001000); // 0; 0 - LNA 2 gain is decreased to minimum before decreasing LNA gain; 00 - Relative carrier sense threshold disabled; 1000 - Absolute carrier sense threshold disabled
- cc1101_write_reg(
- &furi_hal_spi_bus_handle_subghz,
- CC1101_AGCCTRL0,
- 0b00110000); // 00 - No hysteresis, medium asymmetric dead zone, medium gain ; 11 - 64 samples agc; 00 - Normal AGC, 00 - 4dB boundary
- furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz);
- furi_hal_subghz_set_path(FuriHalSubGhzPathIsolate);
- while(instance->worker_running) {
- osDelay(10);
- float rssi_min = 26.0f;
- float rssi_avg = 0;
- size_t rssi_avg_samples = 0;
- frequency_rssi.rssi = -127.0f;
- furi_hal_subghz_idle();
- subghz_frequency_analyzer_worker_load_registers(subghz_preset_ook_650khz);
- // First stage: coarse scan
- for(size_t i = 0; i < subghz_setting_get_frequency_count(instance->setting); i++) {
- if(furi_hal_subghz_is_frequency_valid(
- subghz_setting_get_frequency(instance->setting, i))) {
- furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz);
- cc1101_switch_to_idle(&furi_hal_spi_bus_handle_subghz);
- frequency = cc1101_set_frequency(
- &furi_hal_spi_bus_handle_subghz,
- subghz_setting_get_frequency(instance->setting, i));
- cc1101_calibrate(&furi_hal_spi_bus_handle_subghz);
- do {
- status = cc1101_get_status(&furi_hal_spi_bus_handle_subghz);
- } while(status.STATE != CC1101StateIDLE);
- cc1101_switch_to_rx(&furi_hal_spi_bus_handle_subghz);
- furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz);
- // delay will be in range between 1 and 2ms
- osDelay(3);
- rssi = furi_hal_subghz_get_rssi();
- rssi_avg += rssi;
- rssi_avg_samples++;
- if(rssi < rssi_min) rssi_min = rssi;
- if(frequency_rssi.rssi < rssi) {
- frequency_rssi.rssi = rssi;
- frequency_rssi.frequency = frequency;
- }
- }
- }
- FURI_LOG_T(
- TAG,
- "RSSI: avg %f, max %f at %u, min %f",
- (double)(rssi_avg / rssi_avg_samples),
- (double)frequency_rssi.rssi,
- frequency_rssi.frequency,
- (double)rssi_min);
- // Second stage: fine scan
- if(frequency_rssi.rssi > SUBGHZ_FREQUENCY_ANALYZER_THRESHOLD) {
- FURI_LOG_D(TAG, "~:%u:%f", frequency_rssi.frequency, (double)frequency_rssi.rssi);
- frequency_rssi.rssi = -127.0;
- furi_hal_subghz_idle();
- subghz_frequency_analyzer_worker_load_registers(subghz_preset_ook_58khz);
- //-0.3 ... 433.92 ... +0.3 step 10KHz
- for(uint32_t i = frequency_rssi.frequency - 300000;
- i < frequency_rssi.frequency + 300000;
- i += 20000) {
- if(furi_hal_subghz_is_frequency_valid(i)) {
- furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz);
- cc1101_switch_to_idle(&furi_hal_spi_bus_handle_subghz);
- frequency = cc1101_set_frequency(&furi_hal_spi_bus_handle_subghz, i);
- cc1101_calibrate(&furi_hal_spi_bus_handle_subghz);
- do {
- status = cc1101_get_status(&furi_hal_spi_bus_handle_subghz);
- } while(status.STATE != CC1101StateIDLE);
- cc1101_switch_to_rx(&furi_hal_spi_bus_handle_subghz);
- furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz);
- // delay will be in range between 1 and 2ms
- osDelay(3);
- rssi = furi_hal_subghz_get_rssi();
- FURI_LOG_T(TAG, "#:%u:%f", frequency, (double)rssi);
- if(frequency_rssi.rssi < rssi) {
- frequency_rssi.rssi = rssi;
- frequency_rssi.frequency = frequency;
- }
- }
- }
- }
- // Deliver results
- if(frequency_rssi.rssi > SUBGHZ_FREQUENCY_ANALYZER_THRESHOLD) {
- FURI_LOG_D(TAG, "=:%u:%f", frequency_rssi.frequency, (double)frequency_rssi.rssi);
- instance->sample_hold_counter = 20;
- if(instance->filVal) {
- frequency_rssi.frequency =
- subghz_frequency_analyzer_worker_expRunningAverageAdaptive(
- instance, frequency_rssi.frequency);
- }
- // Deliver callback
- if(instance->pair_callback) {
- instance->pair_callback(
- instance->context, frequency_rssi.frequency, frequency_rssi.rssi);
- }
- } else {
- if(instance->sample_hold_counter > 0) {
- instance->sample_hold_counter--;
- } else {
- instance->filVal = 0;
- if(instance->pair_callback) instance->pair_callback(instance->context, 0, 0);
- }
- }
- }
- //Stop CC1101
- furi_hal_subghz_idle();
- furi_hal_subghz_sleep();
- return 0;
- }
- SubGhzFrequencyAnalyzerWorker* subghz_frequency_analyzer_worker_alloc(void* context) {
- furi_assert(context);
- SubGhzFrequencyAnalyzerWorker* instance = malloc(sizeof(SubGhzFrequencyAnalyzerWorker));
- instance->thread = furi_thread_alloc();
- furi_thread_set_name(instance->thread, "SubGhzFAWorker");
- furi_thread_set_stack_size(instance->thread, 2048);
- furi_thread_set_context(instance->thread, instance);
- furi_thread_set_callback(instance->thread, subghz_frequency_analyzer_worker_thread);
- SubGhz* subghz = context;
- instance->setting = subghz->setting;
- return instance;
- }
- void subghz_frequency_analyzer_worker_free(SubGhzFrequencyAnalyzerWorker* instance) {
- furi_assert(instance);
- furi_thread_free(instance->thread);
- free(instance);
- }
- void subghz_frequency_analyzer_worker_set_pair_callback(
- SubGhzFrequencyAnalyzerWorker* instance,
- SubGhzFrequencyAnalyzerWorkerPairCallback callback,
- void* context) {
- furi_assert(instance);
- furi_assert(context);
- instance->pair_callback = callback;
- instance->context = context;
- }
- void subghz_frequency_analyzer_worker_start(SubGhzFrequencyAnalyzerWorker* instance) {
- furi_assert(instance);
- furi_assert(!instance->worker_running);
- instance->worker_running = true;
- furi_thread_start(instance->thread);
- }
- void subghz_frequency_analyzer_worker_stop(SubGhzFrequencyAnalyzerWorker* instance) {
- furi_assert(instance);
- furi_assert(instance->worker_running);
- instance->worker_running = false;
- furi_thread_join(instance->thread);
- }
- bool subghz_frequency_analyzer_worker_is_running(SubGhzFrequencyAnalyzerWorker* instance) {
- furi_assert(instance);
- return instance->worker_running;
- }
|