| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120 |
- #include "bin_raw.h"
- #include "../blocks/const.h"
- #include "../blocks/decoder.h"
- #include "../blocks/encoder.h"
- #include "../blocks/generic.h"
- #include "../blocks/math.h"
- #include <lib/toolbox/float_tools.h>
- #include <lib/toolbox/stream/stream.h>
- #include <lib/flipper_format/flipper_format_i.h>
- #define TAG "SubGhzProtocolBinRAW"
- //change very carefully, RAM ends at the most inopportune moment
- #define BIN_RAW_BUF_RAW_SIZE 2048
- #define BIN_RAW_BUF_DATA_SIZE 512
- #define BIN_RAW_THRESHOLD_RSSI -85.0f
- #define BIN_RAW_DELTA_RSSI 7.0f
- #define BIN_RAW_SEARCH_CLASSES 20
- #define BIN_RAW_TE_MIN_COUNT 40
- #define BIN_RAW_BUF_MIN_DATA_COUNT 128
- #define BIN_RAW_MAX_MARKUP_COUNT 20
- //#define BIN_RAW_DEBUG
- #ifdef BIN_RAW_DEBUG
- #define bin_raw_debug(...) FURI_LOG_RAW_D(__VA_ARGS__)
- #define bin_raw_debug_tag(tag, ...) \
- FURI_LOG_RAW_D("\033[0;32m[" tag "]\033[0m "); \
- FURI_LOG_RAW_D(__VA_ARGS__)
- #else
- #define bin_raw_debug(...)
- #define bin_raw_debug_tag(...)
- #endif
- static const SubGhzBlockConst subghz_protocol_bin_raw_const = {
- .te_short = 30,
- .te_long = 65000,
- .te_delta = 0,
- .min_count_bit_for_found = 0,
- };
- typedef enum {
- BinRAWDecoderStepReset = 0,
- BinRAWDecoderStepWrite,
- BinRAWDecoderStepBufFull,
- BinRAWDecoderStepNoParse,
- } BinRAWDecoderStep;
- typedef enum {
- BinRAWTypeUnknown = 0,
- BinRAWTypeNoGap,
- BinRAWTypeGap,
- BinRAWTypeGapRecurring,
- BinRAWTypeGapRolling,
- BinRAWTypeGapUnknown,
- } BinRAWType;
- struct BinRAW_Markup {
- uint16_t byte_bias;
- uint16_t bit_count;
- };
- typedef struct BinRAW_Markup BinRAW_Markup;
- struct SubGhzProtocolDecoderBinRAW {
- SubGhzProtocolDecoderBase base;
- SubGhzBlockDecoder decoder;
- SubGhzBlockGeneric generic;
- int32_t* data_raw;
- uint8_t* data;
- BinRAW_Markup data_markup[BIN_RAW_MAX_MARKUP_COUNT];
- size_t data_raw_ind;
- uint32_t te;
- float adaptive_threshold_rssi;
- };
- struct SubGhzProtocolEncoderBinRAW {
- SubGhzProtocolEncoderBase base;
- SubGhzProtocolBlockEncoder encoder;
- SubGhzBlockGeneric generic;
- uint8_t* data;
- BinRAW_Markup data_markup[BIN_RAW_MAX_MARKUP_COUNT];
- uint32_t te;
- };
- const SubGhzProtocolDecoder subghz_protocol_bin_raw_decoder = {
- .alloc = subghz_protocol_decoder_bin_raw_alloc,
- .free = subghz_protocol_decoder_bin_raw_free,
- .feed = subghz_protocol_decoder_bin_raw_feed,
- .reset = subghz_protocol_decoder_bin_raw_reset,
- .get_hash_data = subghz_protocol_decoder_bin_raw_get_hash_data,
- .serialize = subghz_protocol_decoder_bin_raw_serialize,
- .deserialize = subghz_protocol_decoder_bin_raw_deserialize,
- .get_string = subghz_protocol_decoder_bin_raw_get_string,
- };
- const SubGhzProtocolEncoder subghz_protocol_bin_raw_encoder = {
- .alloc = subghz_protocol_encoder_bin_raw_alloc,
- .free = subghz_protocol_encoder_bin_raw_free,
- .deserialize = subghz_protocol_encoder_bin_raw_deserialize,
- .stop = subghz_protocol_encoder_bin_raw_stop,
- .yield = subghz_protocol_encoder_bin_raw_yield,
- };
- const SubGhzProtocol subghz_protocol_bin_raw = {
- .name = SUBGHZ_PROTOCOL_BIN_RAW_NAME,
- .type = SubGhzProtocolTypeStatic,
- #ifdef BIN_RAW_DEBUG
- .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_868 |
- SubGhzProtocolFlag_AM | SubGhzProtocolFlag_FM | SubGhzProtocolFlag_Decodable |
- SubGhzProtocolFlag_Load | SubGhzProtocolFlag_Save | SubGhzProtocolFlag_Send,
- #else
- .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_868 |
- SubGhzProtocolFlag_AM | SubGhzProtocolFlag_FM | SubGhzProtocolFlag_BinRAW |
- SubGhzProtocolFlag_Load | SubGhzProtocolFlag_Save | SubGhzProtocolFlag_Send,
- #endif
- .decoder = &subghz_protocol_bin_raw_decoder,
- .encoder = &subghz_protocol_bin_raw_encoder,
- };
- static uint16_t subghz_protocol_bin_raw_get_full_byte(uint16_t bit_count) {
- if(bit_count & 0x7) {
- return (bit_count >> 3) + 1;
- } else {
- return (bit_count >> 3);
- }
- }
- void* subghz_protocol_encoder_bin_raw_alloc(SubGhzEnvironment* environment) {
- UNUSED(environment);
- SubGhzProtocolEncoderBinRAW* instance = malloc(sizeof(SubGhzProtocolEncoderBinRAW));
- instance->base.protocol = &subghz_protocol_bin_raw;
- instance->generic.protocol_name = instance->base.protocol->name;
- instance->encoder.repeat = 10;
- instance->encoder.size_upload = BIN_RAW_BUF_DATA_SIZE * 5;
- instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration));
- instance->data = malloc(instance->encoder.size_upload * sizeof(uint8_t));
- memset(instance->data_markup, 0x00, BIN_RAW_MAX_MARKUP_COUNT * sizeof(BinRAW_Markup));
- instance->encoder.is_running = false;
- return instance;
- }
- void subghz_protocol_encoder_bin_raw_free(void* context) {
- furi_assert(context);
- SubGhzProtocolEncoderBinRAW* instance = context;
- free(instance->encoder.upload);
- free(instance->data);
- free(instance);
- }
- /**
- * Generating an upload from data.
- * @param instance Pointer to a SubGhzProtocolEncoderBinRAW instance
- * @return true On success
- */
- static bool subghz_protocol_encoder_bin_raw_get_upload(SubGhzProtocolEncoderBinRAW* instance) {
- furi_assert(instance);
- //we glue all the pieces of the package into 1 long sequence with left alignment,
- //in the uploaded data we have right alignment.
- bin_raw_debug_tag(TAG, "Recovery of offset bits in sequences\r\n");
- uint16_t i = 0;
- uint16_t ind = 0;
- bin_raw_debug("\tind byte_bias\tbit_count\tbit_bias\r\n");
- while((i < BIN_RAW_MAX_MARKUP_COUNT) && (instance->data_markup[i].bit_count != 0)) {
- uint8_t bit_bias =
- subghz_protocol_bin_raw_get_full_byte(instance->data_markup[i].bit_count) * 8 -
- instance->data_markup[i].bit_count;
- bin_raw_debug(
- "\t%d\t%d\t%d :\t\t%d\r\n",
- i,
- instance->data_markup[i].byte_bias,
- instance->data_markup[i].bit_count,
- bit_bias);
- for(uint16_t y = instance->data_markup[i].byte_bias * 8;
- y < instance->data_markup[i].byte_bias * 8 +
- subghz_protocol_bin_raw_get_full_byte(instance->data_markup[i].bit_count) * 8 -
- bit_bias;
- y++) {
- subghz_protocol_blocks_set_bit_array(
- subghz_protocol_blocks_get_bit_array(instance->data, y + bit_bias),
- instance->data,
- ind++,
- BIN_RAW_BUF_DATA_SIZE);
- }
- i++;
- }
- bin_raw_debug("\r\n");
- #ifdef BIN_RAW_DEBUG
- bin_raw_debug_tag(TAG, "Restored Sequence left aligned\r\n");
- for(uint16_t y = 0; y < subghz_protocol_bin_raw_get_full_byte(ind); y++) {
- bin_raw_debug("%02X ", instance->data[y]);
- }
- bin_raw_debug("\r\n\tbin_count_result= %d\r\n\r\n", ind);
- bin_raw_debug_tag(
- TAG, "Maximum levels encoded in upload %zu\r\n", instance->encoder.size_upload);
- #endif
- instance->encoder.size_upload = subghz_protocol_blocks_get_upload_from_bit_array(
- instance->data,
- ind,
- instance->encoder.upload,
- instance->encoder.size_upload,
- instance->te,
- SubGhzProtocolBlockAlignBitLeft);
- bin_raw_debug_tag(TAG, "The result %zu is levels\r\n", instance->encoder.size_upload);
- bin_raw_debug_tag(TAG, "Remaining free memory %zu\r\n", memmgr_get_free_heap());
- return true;
- }
- bool subghz_protocol_encoder_bin_raw_deserialize(void* context, FlipperFormat* flipper_format) {
- furi_assert(context);
- SubGhzProtocolEncoderBinRAW* instance = context;
- bool res = false;
- uint32_t temp_data = 0;
- do {
- if(!flipper_format_rewind(flipper_format)) {
- FURI_LOG_E(TAG, "Rewind error");
- break;
- }
- if(!flipper_format_read_uint32(flipper_format, "Bit", (uint32_t*)&temp_data, 1)) {
- FURI_LOG_E(TAG, "Missing Bit");
- break;
- }
- instance->generic.data_count_bit = (uint16_t)temp_data;
- if(!flipper_format_read_uint32(flipper_format, "TE", (uint32_t*)&instance->te, 1)) {
- FURI_LOG_E(TAG, "Missing TE");
- break;
- }
- temp_data = 0;
- uint16_t ind = 0;
- uint16_t byte_bias = 0;
- uint16_t byte_count = 0;
- memset(instance->data_markup, 0x00, BIN_RAW_MAX_MARKUP_COUNT * sizeof(BinRAW_Markup));
- while(flipper_format_read_uint32(flipper_format, "Bit_RAW", (uint32_t*)&temp_data, 1)) {
- if(ind >= BIN_RAW_MAX_MARKUP_COUNT) {
- FURI_LOG_E(TAG, "Markup overflow");
- break;
- }
- byte_count += subghz_protocol_bin_raw_get_full_byte(temp_data);
- if(byte_count > BIN_RAW_BUF_DATA_SIZE) {
- FURI_LOG_E(TAG, "Receive buffer overflow");
- break;
- }
- instance->data_markup[ind].bit_count = temp_data;
- instance->data_markup[ind].byte_bias = byte_bias;
- byte_bias += subghz_protocol_bin_raw_get_full_byte(temp_data);
- if(!flipper_format_read_hex(
- flipper_format,
- "Data_RAW",
- instance->data + instance->data_markup[ind].byte_bias,
- subghz_protocol_bin_raw_get_full_byte(temp_data))) {
- instance->data_markup[ind].bit_count = 0;
- FURI_LOG_E(TAG, "Missing Data_RAW");
- break;
- }
- ind++;
- }
- #ifdef BIN_RAW_DEBUG
- uint16_t i = 0;
- bin_raw_debug_tag(TAG, "Download data to encoder\r\n");
- bin_raw_debug("\tind byte_bias\tbit_count\t\tbin_data");
- while((i < BIN_RAW_MAX_MARKUP_COUNT) && (instance->data_markup[i].bit_count != 0)) {
- bin_raw_debug(
- "\r\n\t%d\t%d\t%d :\t",
- i,
- instance->data_markup[i].byte_bias,
- instance->data_markup[i].bit_count);
- for(uint16_t y = instance->data_markup[i].byte_bias;
- y < instance->data_markup[i].byte_bias +
- subghz_protocol_bin_raw_get_full_byte(instance->data_markup[i].bit_count);
- y++) {
- bin_raw_debug("%02X ", instance->data[y]);
- }
- i++;
- }
- bin_raw_debug("\r\n\r\n");
- #endif
- if(!flipper_format_rewind(flipper_format)) {
- FURI_LOG_E(TAG, "Rewind error");
- break;
- }
- //optional parameter parameter
- flipper_format_read_uint32(
- flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1);
- if(!subghz_protocol_encoder_bin_raw_get_upload(instance)) break;
- instance->encoder.is_running = true;
- res = true;
- } while(0);
- return res;
- }
- void subghz_protocol_encoder_bin_raw_stop(void* context) {
- SubGhzProtocolEncoderBinRAW* instance = context;
- instance->encoder.is_running = false;
- }
- LevelDuration subghz_protocol_encoder_bin_raw_yield(void* context) {
- SubGhzProtocolEncoderBinRAW* instance = context;
- if(instance->encoder.repeat == 0 || !instance->encoder.is_running) {
- instance->encoder.is_running = false;
- return level_duration_reset();
- }
- LevelDuration ret = instance->encoder.upload[instance->encoder.front];
- if(++instance->encoder.front == instance->encoder.size_upload) {
- instance->encoder.repeat--;
- instance->encoder.front = 0;
- }
- return ret;
- }
- void* subghz_protocol_decoder_bin_raw_alloc(SubGhzEnvironment* environment) {
- UNUSED(environment);
- SubGhzProtocolDecoderBinRAW* instance = malloc(sizeof(SubGhzProtocolDecoderBinRAW));
- instance->base.protocol = &subghz_protocol_bin_raw;
- instance->generic.protocol_name = instance->base.protocol->name;
- instance->data_raw_ind = 0;
- instance->data_raw = malloc(BIN_RAW_BUF_RAW_SIZE * sizeof(int32_t));
- instance->data = malloc(BIN_RAW_BUF_RAW_SIZE * sizeof(uint8_t));
- memset(instance->data_markup, 0x00, BIN_RAW_MAX_MARKUP_COUNT * sizeof(BinRAW_Markup));
- instance->adaptive_threshold_rssi = BIN_RAW_THRESHOLD_RSSI;
- return instance;
- }
- void subghz_protocol_decoder_bin_raw_free(void* context) {
- furi_assert(context);
- SubGhzProtocolDecoderBinRAW* instance = context;
- free(instance->data_raw);
- free(instance->data);
- free(instance);
- }
- void subghz_protocol_decoder_bin_raw_reset(void* context) {
- furi_assert(context);
- SubGhzProtocolDecoderBinRAW* instance = context;
- #ifdef BIN_RAW_DEBUG
- UNUSED(instance);
- #else
- instance->decoder.parser_step = BinRAWDecoderStepNoParse;
- instance->data_raw_ind = 0;
- #endif
- }
- void subghz_protocol_decoder_bin_raw_feed(void* context, bool level, uint32_t duration) {
- furi_assert(context);
- SubGhzProtocolDecoderBinRAW* instance = context;
- if(instance->decoder.parser_step == BinRAWDecoderStepWrite) {
- if(instance->data_raw_ind == BIN_RAW_BUF_RAW_SIZE) {
- instance->decoder.parser_step = BinRAWDecoderStepBufFull;
- } else {
- instance->data_raw[instance->data_raw_ind++] = (level ? duration : -duration);
- }
- }
- }
- /**
- * Analysis of received data
- * @param instance Pointer to a SubGhzProtocolDecoderBinRAW* instance
- */
- static bool
- subghz_protocol_bin_raw_check_remote_controller(SubGhzProtocolDecoderBinRAW* instance) {
- struct {
- float data;
- uint16_t count;
- } classes[BIN_RAW_SEARCH_CLASSES];
- size_t ind = 0;
- memset(classes, 0x00, sizeof(classes));
- uint16_t data_markup_ind = 0;
- memset(instance->data_markup, 0x00, BIN_RAW_MAX_MARKUP_COUNT * sizeof(BinRAW_Markup));
- if(instance->data_raw_ind < 512) {
- ind =
- instance->data_raw_ind -
- 100; //there is usually garbage at the end of the record, we exclude it from the classification
- } else {
- ind = 512;
- }
- //sort the durations to find the shortest correlated interval
- for(size_t i = 0; i < ind; i++) {
- for(size_t k = 0; k < BIN_RAW_SEARCH_CLASSES; k++) {
- if(classes[k].count == 0) {
- classes[k].data = (float)(abs(instance->data_raw[i]));
- classes[k].count++;
- break;
- } else if(
- DURATION_DIFF((float)(abs(instance->data_raw[i])), (classes[k].data)) <
- (classes[k].data / 4)) { //if the test value does not differ by more than 25%
- classes[k].data += ((float)(abs(instance->data_raw[i])) - classes[k].data) *
- 0.05f; //running average k=0.05
- classes[k].count++;
- break;
- }
- }
- }
- // if(classes[BIN_RAW_SEARCH_CLASSES - 1].count != 0) {
- // //filling the classifier, it means that they received an unclean signal
- // return false;
- // }
- //looking for the minimum te with an occurrence greater than BIN_RAW_TE_MIN_COUNT
- instance->te = subghz_protocol_bin_raw_const.te_long * 2;
- bool te_ok = false;
- uint16_t gap_ind = 0;
- uint16_t gap_delta = 0;
- uint32_t gap = 0;
- int data_temp = 0;
- BinRAWType bin_raw_type = BinRAWTypeUnknown;
- //sort by number of occurrences
- bool swap = true;
- while(swap) {
- swap = false;
- for(size_t i = 1; i < BIN_RAW_SEARCH_CLASSES; i++) {
- if(classes[i].count > classes[i - 1].count) {
- uint32_t data = classes[i - 1].data;
- uint32_t count = classes[i - 1].count;
- classes[i - 1].data = classes[i].data;
- classes[i - 1].count = classes[i].count;
- classes[i].data = data;
- classes[i].count = count;
- swap = true;
- }
- }
- }
- #ifdef BIN_RAW_DEBUG
- bin_raw_debug_tag(TAG, "Sorted durations\r\n");
- bin_raw_debug("\t\tind\tcount\tus\r\n");
- for(size_t k = 0; k < BIN_RAW_SEARCH_CLASSES; k++) {
- bin_raw_debug("\t\t%zu\t%u\t%lu\r\n", k, classes[k].count, (uint32_t)classes[k].data);
- }
- bin_raw_debug("\r\n");
- #endif
- if((classes[0].count > BIN_RAW_TE_MIN_COUNT) && (classes[1].count == 0)) {
- //adopted only the preamble
- instance->te = (uint32_t)classes[0].data;
- te_ok = true;
- gap = 0; //gap no
- } else {
- //take the 2 most common durations
- //check that there are enough
- if((classes[0].count < BIN_RAW_TE_MIN_COUNT) ||
- (classes[1].count < (BIN_RAW_TE_MIN_COUNT >> 1)))
- return false;
- //arrange the first 2 date values in ascending order
- if(classes[0].data > classes[1].data) {
- uint32_t data = classes[1].data;
- classes[0].data = classes[1].data;
- classes[1].data = data;
- }
- //determine the value to be corrected
- for(uint8_t k = 1; k < 5; k++) {
- float delta = (classes[1].data / (classes[0].data / k));
- bin_raw_debug_tag(TAG, "K_div= %f\r\n", (double)(delta));
- delta -= (uint32_t)delta;
- if((delta < 0.20f) || (delta > 0.80f)) {
- instance->te = (uint32_t)classes[0].data / k;
- bin_raw_debug_tag(TAG, "K= %d\r\n", k);
- te_ok = true; //found a correlated duration
- break;
- }
- }
- if(!te_ok) {
- //did not find the minimum TE satisfying the condition
- return false;
- }
- bin_raw_debug_tag(TAG, "TE= %lu\r\n\r\n", instance->te);
- //looking for a gap
- for(size_t k = 2; k < BIN_RAW_SEARCH_CLASSES; k++) {
- if((classes[k].count > 2) && (classes[k].data > gap)) {
- gap = (uint32_t)classes[k].data;
- gap_delta = gap / 5; //calculate 20% deviation from ideal value
- }
- }
- if((gap / instance->te) <
- 10) { //make an assumption, the longest gap should be more than 10 TE
- gap = 0; //check that our signal has a gap greater than 10*TE
- bin_raw_type = BinRAWTypeNoGap;
- } else {
- bin_raw_type = BinRAWTypeGap;
- //looking for the last occurrence of gap
- ind = instance->data_raw_ind - 1;
- while((ind > 0) && (DURATION_DIFF(abs(instance->data_raw[ind]), gap) > gap_delta)) {
- ind--;
- }
- gap_ind = ind;
- }
- }
- //if we consider that there is a gap, then we divide the signal with respect to this gap
- //processing input data from the end
- if(bin_raw_type == BinRAWTypeGap) {
- bin_raw_debug_tag(TAG, "Tinted sequence\r\n");
- ind = (BIN_RAW_BUF_DATA_SIZE * 8);
- uint16_t bit_count = 0;
- do {
- gap_ind--;
- data_temp = (int)(round((float)(instance->data_raw[gap_ind]) / instance->te));
- bin_raw_debug("%d ", data_temp);
- if(data_temp == 0) bit_count++; //there is noise in the package
- for(size_t i = 0; i < abs(data_temp); i++) {
- bit_count++;
- if(ind) {
- ind--;
- } else {
- break;
- }
- if(data_temp > 0) {
- subghz_protocol_blocks_set_bit_array(
- true, instance->data, ind, BIN_RAW_BUF_DATA_SIZE);
- } else {
- subghz_protocol_blocks_set_bit_array(
- false, instance->data, ind, BIN_RAW_BUF_DATA_SIZE);
- }
- }
- //split into full bytes if gap is caught
- if(DURATION_DIFF(abs(instance->data_raw[gap_ind]), gap) < gap_delta) {
- instance->data_markup[data_markup_ind].byte_bias = ind >> 3;
- instance->data_markup[data_markup_ind++].bit_count = bit_count;
- bit_count = 0;
- if(data_markup_ind == BIN_RAW_MAX_MARKUP_COUNT) break;
- ind &= 0xFFFFFFF8; //jump to the pre whole byte
- }
- } while(gap_ind != 0);
- if((data_markup_ind != BIN_RAW_MAX_MARKUP_COUNT) && (ind != 0)) {
- instance->data_markup[data_markup_ind].byte_bias = ind >> 3;
- instance->data_markup[data_markup_ind++].bit_count = bit_count;
- }
- bin_raw_debug("\r\n\t count bit= %zu\r\n\r\n", (BIN_RAW_BUF_DATA_SIZE * 8) - ind);
- //reset the classifier and classify the received data
- memset(classes, 0x00, sizeof(classes));
- bin_raw_debug_tag(TAG, "Sort the found pieces by the number of bits in them\r\n");
- for(size_t i = 0; i < data_markup_ind; i++) {
- for(size_t k = 0; k < BIN_RAW_SEARCH_CLASSES; k++) {
- if(classes[k].count == 0) {
- classes[k].data = instance->data_markup[i].bit_count;
- classes[k].count++;
- break;
- } else if(instance->data_markup[i].bit_count == (uint16_t)classes[k].data) {
- classes[k].count++;
- break;
- }
- }
- }
- #ifdef BIN_RAW_DEBUG
- bin_raw_debug("\t\tind\tcount\tus\r\n");
- for(size_t k = 0; k < BIN_RAW_SEARCH_CLASSES; k++) {
- bin_raw_debug("\t\t%zu\t%u\t%lu\r\n", k, classes[k].count, (uint32_t)classes[k].data);
- }
- bin_raw_debug("\r\n");
- #endif
- //choose the value with the maximum repetition
- data_temp = 0;
- for(size_t i = 0; i < BIN_RAW_SEARCH_CLASSES; i++) {
- if((classes[i].count > 1) && (data_temp < classes[i].count))
- data_temp = (int)classes[i].data;
- }
- //if(data_markup_ind == 0) return false;
- #ifdef BIN_RAW_DEBUG
- //output in reverse order
- bin_raw_debug_tag(TAG, "Found sequences\r\n");
- bin_raw_debug("\tind byte_bias\tbit_count\t\tbin_data\r\n");
- uint16_t data_markup_ind_temp = data_markup_ind;
- if(data_markup_ind) {
- data_markup_ind_temp--;
- for(size_t i = (ind / 8); i < BIN_RAW_BUF_DATA_SIZE; i++) {
- if(instance->data_markup[data_markup_ind_temp].byte_bias == i) {
- bin_raw_debug(
- "\r\n\t%d\t%d\t%d :\t",
- data_markup_ind_temp,
- instance->data_markup[data_markup_ind_temp].byte_bias,
- instance->data_markup[data_markup_ind_temp].bit_count);
- if(data_markup_ind_temp != 0) data_markup_ind_temp--;
- }
- bin_raw_debug("%02X ", instance->data[i]);
- }
- bin_raw_debug("\r\n\r\n");
- }
- //compare data in chunks with the same number of bits
- bin_raw_debug_tag(TAG, "Analyze sequences of long %d bit\r\n\r\n", data_temp);
- #endif
- //if(data_temp == 0) data_temp = (int)classes[0].data;
- if(data_temp != 0) {
- //check that data in transmission is repeated every packet
- for(uint16_t i = 0; i < data_markup_ind - 1; i++) {
- if((instance->data_markup[i].bit_count == data_temp) &&
- (instance->data_markup[i + 1].bit_count == data_temp)) {
- //if the number of bits in adjacent parcels is the same, compare the data
- bin_raw_debug_tag(
- TAG,
- "Comparison of neighboring sequences ind_1=%d ind_2=%d %02X=%02X .... %02X=%02X\r\n",
- i,
- i + 1,
- instance->data[instance->data_markup[i].byte_bias],
- instance->data[instance->data_markup[i + 1].byte_bias],
- instance->data
- [instance->data_markup[i].byte_bias +
- subghz_protocol_bin_raw_get_full_byte(
- instance->data_markup[i].bit_count) -
- 1],
- instance->data
- [instance->data_markup[i + 1].byte_bias +
- subghz_protocol_bin_raw_get_full_byte(
- instance->data_markup[i + 1].bit_count) -
- 1]);
- uint16_t byte_count =
- subghz_protocol_bin_raw_get_full_byte(instance->data_markup[i].bit_count);
- if(memcmp(
- instance->data + instance->data_markup[i].byte_bias,
- instance->data + instance->data_markup[i + 1].byte_bias,
- byte_count - 1) == 0) {
- bin_raw_debug_tag(
- TAG, "Match found bin_raw_type=BinRAWTypeGapRecurring\r\n\r\n");
- //place in 1 element the offset to valid data
- instance->data_markup[0].bit_count = instance->data_markup[i].bit_count;
- instance->data_markup[0].byte_bias = instance->data_markup[i].byte_bias;
- //markup end sign
- instance->data_markup[1].bit_count = 0;
- instance->data_markup[1].byte_bias = 0;
- bin_raw_type = BinRAWTypeGapRecurring;
- i = data_markup_ind;
- break;
- }
- }
- }
- }
- if(bin_raw_type == BinRAWTypeGap) {
- // check that retry occurs every n packets
- for(uint16_t i = 0; i < data_markup_ind - 2; i++) {
- uint16_t byte_count =
- subghz_protocol_bin_raw_get_full_byte(instance->data_markup[i].bit_count);
- for(uint16_t y = i + 1; y < data_markup_ind - 1; y++) {
- bin_raw_debug_tag(
- TAG,
- "Comparison every N sequences ind_1=%d ind_2=%d %02X=%02X .... %02X=%02X\r\n",
- i,
- y,
- instance->data[instance->data_markup[i].byte_bias],
- instance->data[instance->data_markup[y].byte_bias],
- instance->data
- [instance->data_markup[i].byte_bias +
- subghz_protocol_bin_raw_get_full_byte(
- instance->data_markup[i].bit_count) -
- 1],
- instance->data
- [instance->data_markup[y].byte_bias +
- subghz_protocol_bin_raw_get_full_byte(
- instance->data_markup[y].bit_count) -
- 1]);
- if(byte_count ==
- subghz_protocol_bin_raw_get_full_byte(
- instance->data_markup[y].bit_count)) { //if the length in bytes matches
- if((memcmp(
- instance->data + instance->data_markup[i].byte_bias,
- instance->data + instance->data_markup[y].byte_bias,
- byte_count - 1) == 0) &&
- (memcmp(
- instance->data + instance->data_markup[i + 1].byte_bias,
- instance->data + instance->data_markup[y + 1].byte_bias,
- byte_count - 1) == 0)) {
- uint8_t index = 0;
- #ifdef BIN_RAW_DEBUG
- bin_raw_debug_tag(
- TAG, "Match found bin_raw_type=BinRAWTypeGapRolling\r\n\r\n");
- //output in reverse order
- bin_raw_debug("\tind byte_bias\tbit_count\t\tbin_data\r\n");
- index = y - 1;
- for(size_t z = instance->data_markup[y].byte_bias + byte_count;
- z < instance->data_markup[i].byte_bias + byte_count;
- z++) {
- if(instance->data_markup[index].byte_bias == z) {
- bin_raw_debug(
- "\r\n\t%d\t%d\t%d :\t",
- index,
- instance->data_markup[index].byte_bias,
- instance->data_markup[index].bit_count);
- if(index != 0) index--;
- }
- bin_raw_debug("%02X ", instance->data[z]);
- }
- bin_raw_debug("\r\n\r\n");
- #endif
- //todo can be optimized
- BinRAW_Markup markup_temp[BIN_RAW_MAX_MARKUP_COUNT];
- memcpy(
- markup_temp,
- instance->data_markup,
- BIN_RAW_MAX_MARKUP_COUNT * sizeof(BinRAW_Markup));
- memset(
- instance->data_markup,
- 0x00,
- BIN_RAW_MAX_MARKUP_COUNT * sizeof(BinRAW_Markup));
- for(index = i; index < y; index++) {
- instance->data_markup[index - i].bit_count =
- markup_temp[y - index - 1].bit_count;
- instance->data_markup[index - i].byte_bias =
- markup_temp[y - index - 1].byte_bias;
- }
- bin_raw_type = BinRAWTypeGapRolling;
- i = data_markup_ind;
- break;
- }
- }
- }
- }
- }
- //todo can be optimized
- if(bin_raw_type == BinRAWTypeGap) {
- if(data_temp != 0) { //there are sequences with the same number of bits
- BinRAW_Markup markup_temp[BIN_RAW_MAX_MARKUP_COUNT];
- memcpy(
- markup_temp,
- instance->data_markup,
- BIN_RAW_MAX_MARKUP_COUNT * sizeof(BinRAW_Markup));
- memset(
- instance->data_markup, 0x00, BIN_RAW_MAX_MARKUP_COUNT * sizeof(BinRAW_Markup));
- uint16_t byte_count = subghz_protocol_bin_raw_get_full_byte(data_temp);
- uint16_t index = 0;
- uint16_t it = BIN_RAW_MAX_MARKUP_COUNT;
- do {
- it--;
- if(subghz_protocol_bin_raw_get_full_byte(markup_temp[it].bit_count) ==
- byte_count) {
- instance->data_markup[index].bit_count = markup_temp[it].bit_count;
- instance->data_markup[index].byte_bias = markup_temp[it].byte_bias;
- index++;
- bin_raw_type = BinRAWTypeGapUnknown;
- }
- } while(it != 0);
- }
- }
- if(bin_raw_type != BinRAWTypeGap)
- return true;
- else
- return false;
- } else {
- // if bin_raw_type == BinRAWTypeGap
- bin_raw_debug_tag(TAG, "Sequence analysis without gap\r\n");
- ind = 0;
- for(size_t i = 0; i < instance->data_raw_ind; i++) {
- int data_temp = (int)(round((float)(instance->data_raw[i]) / instance->te));
- if(data_temp == 0) break; //found an interval 2 times shorter than TE, this is noise
- bin_raw_debug("%d ", data_temp);
- for(size_t k = 0; k < abs(data_temp); k++) {
- if(data_temp > 0) {
- subghz_protocol_blocks_set_bit_array(
- true, instance->data, ind++, BIN_RAW_BUF_DATA_SIZE);
- } else {
- subghz_protocol_blocks_set_bit_array(
- false, instance->data, ind++, BIN_RAW_BUF_DATA_SIZE);
- }
- if(ind == BIN_RAW_BUF_DATA_SIZE * 8) {
- i = instance->data_raw_ind;
- break;
- }
- }
- }
- if(ind != 0) {
- bin_raw_type = BinRAWTypeNoGap;
- //right alignment
- uint8_t bit_bias = (subghz_protocol_bin_raw_get_full_byte(ind) << 3) - ind;
- #ifdef BIN_RAW_DEBUG
- bin_raw_debug(
- "\r\n\t count bit= %zu\tcount full byte= %d\tbias bit= %d\r\n\r\n",
- ind,
- subghz_protocol_bin_raw_get_full_byte(ind),
- bit_bias);
- for(size_t i = 0; i < subghz_protocol_bin_raw_get_full_byte(ind); i++) {
- bin_raw_debug("%02X ", instance->data[i]);
- }
- bin_raw_debug("\r\n\r\n");
- #endif
- //checking that the received sequence contains useful data
- bool data_check = false;
- for(size_t i = 0; i < subghz_protocol_bin_raw_get_full_byte(ind); i++) {
- if(instance->data[i] != 0) {
- data_check = true;
- break;
- }
- }
- if(data_check) {
- for(size_t i = subghz_protocol_bin_raw_get_full_byte(ind) - 1; i > 0; i--) {
- instance->data[i] = (instance->data[i - 1] << (8 - bit_bias)) |
- (instance->data[i] >> bit_bias);
- }
- instance->data[0] = (instance->data[0] >> bit_bias);
- #ifdef BIN_RAW_DEBUG
- bin_raw_debug_tag(TAG, "Data right alignment\r\n");
- for(size_t i = 0; i < subghz_protocol_bin_raw_get_full_byte(ind); i++) {
- bin_raw_debug("%02X ", instance->data[i]);
- }
- bin_raw_debug("\r\n\r\n");
- #endif
- instance->data_markup[0].bit_count = ind;
- instance->data_markup[0].byte_bias = 0;
- return true;
- } else {
- return false;
- }
- } else {
- return false;
- }
- }
- return false;
- }
- void subghz_protocol_decoder_bin_raw_data_input_rssi(
- SubGhzProtocolDecoderBinRAW* instance,
- float rssi) {
- furi_assert(instance);
- switch(instance->decoder.parser_step) {
- case BinRAWDecoderStepReset:
- bin_raw_debug("%ld %ld :", (int32_t)rssi, (int32_t)instance->adaptive_threshold_rssi);
- if(rssi > (instance->adaptive_threshold_rssi + BIN_RAW_DELTA_RSSI)) {
- instance->data_raw_ind = 0;
- memset(instance->data_raw, 0x00, BIN_RAW_BUF_RAW_SIZE * sizeof(int32_t));
- memset(instance->data, 0x00, BIN_RAW_BUF_RAW_SIZE * sizeof(uint8_t));
- instance->decoder.parser_step = BinRAWDecoderStepWrite;
- bin_raw_debug_tag(TAG, "RSSI\r\n");
- } else {
- //adaptive noise level adjustment
- instance->adaptive_threshold_rssi += (rssi - instance->adaptive_threshold_rssi) * 0.2f;
- }
- break;
- case BinRAWDecoderStepBufFull:
- case BinRAWDecoderStepWrite:
- #ifdef BIN_RAW_DEBUG
- if(rssi > (instance->adaptive_threshold_rssi + BIN_RAW_DELTA_RSSI)) {
- bin_raw_debug("\033[0;32m%ld \033[0m ", (int32_t)rssi);
- } else {
- bin_raw_debug("%ld ", (int32_t)rssi);
- }
- #endif
- if(rssi < instance->adaptive_threshold_rssi + BIN_RAW_DELTA_RSSI) {
- #ifdef BIN_RAW_DEBUG
- bin_raw_debug("\r\n\r\n");
- bin_raw_debug_tag(TAG, "Data for analysis, positive high, negative low, us\r\n");
- for(size_t i = 0; i < instance->data_raw_ind; i++) {
- bin_raw_debug("%ld ", instance->data_raw[i]);
- }
- bin_raw_debug("\r\n\t count data= %zu\r\n\r\n", instance->data_raw_ind);
- #endif
- instance->decoder.parser_step = BinRAWDecoderStepReset;
- instance->generic.data_count_bit = 0;
- if(instance->data_raw_ind >= BIN_RAW_BUF_MIN_DATA_COUNT) {
- if(subghz_protocol_bin_raw_check_remote_controller(instance)) {
- bin_raw_debug_tag(TAG, "Sequence found\r\n");
- bin_raw_debug("\tind byte_bias\tbit_count\t\tbin_data");
- uint16_t i = 0;
- while((i < BIN_RAW_MAX_MARKUP_COUNT) &&
- (instance->data_markup[i].bit_count != 0)) {
- instance->generic.data_count_bit += instance->data_markup[i].bit_count;
- #ifdef BIN_RAW_DEBUG
- bin_raw_debug(
- "\r\n\t%d\t%d\t%d :\t",
- i,
- instance->data_markup[i].byte_bias,
- instance->data_markup[i].bit_count);
- for(uint16_t y = instance->data_markup[i].byte_bias;
- y < instance->data_markup[i].byte_bias +
- subghz_protocol_bin_raw_get_full_byte(
- instance->data_markup[i].bit_count);
- y++) {
- bin_raw_debug("%02X ", instance->data[y]);
- }
- #endif
- i++;
- }
- bin_raw_debug("\r\n");
- if(instance->base.callback)
- instance->base.callback(&instance->base, instance->base.context);
- }
- }
- }
- break;
- default:
- //if instance->decoder.parser_step == BinRAWDecoderStepNoParse or others, restore the initial state
- if(rssi < instance->adaptive_threshold_rssi + BIN_RAW_DELTA_RSSI) {
- instance->decoder.parser_step = BinRAWDecoderStepReset;
- }
- break;
- }
- }
- uint8_t subghz_protocol_decoder_bin_raw_get_hash_data(void* context) {
- furi_assert(context);
- SubGhzProtocolDecoderBinRAW* instance = context;
- return subghz_protocol_blocks_add_bytes(
- instance->data + instance->data_markup[0].byte_bias,
- subghz_protocol_bin_raw_get_full_byte(instance->data_markup[0].bit_count));
- }
- bool subghz_protocol_decoder_bin_raw_serialize(
- void* context,
- FlipperFormat* flipper_format,
- SubGhzRadioPreset* preset) {
- furi_assert(context);
- SubGhzProtocolDecoderBinRAW* instance = context;
- bool res = false;
- FuriString* temp_str;
- temp_str = furi_string_alloc();
- do {
- stream_clean(flipper_format_get_raw_stream(flipper_format));
- if(!flipper_format_write_header_cstr(
- flipper_format, SUBGHZ_KEY_FILE_TYPE, SUBGHZ_KEY_FILE_VERSION)) {
- FURI_LOG_E(TAG, "Unable to add header");
- break;
- }
- if(!flipper_format_write_uint32(flipper_format, "Frequency", &preset->frequency, 1)) {
- FURI_LOG_E(TAG, "Unable to add Frequency");
- break;
- }
- subghz_block_generic_get_preset_name(furi_string_get_cstr(preset->name), temp_str);
- if(!flipper_format_write_string_cstr(
- flipper_format, "Preset", furi_string_get_cstr(temp_str))) {
- FURI_LOG_E(TAG, "Unable to add Preset");
- break;
- }
- if(!strcmp(furi_string_get_cstr(temp_str), "FuriHalSubGhzPresetCustom")) {
- if(!flipper_format_write_string_cstr(
- flipper_format, "Custom_preset_module", "CC1101")) {
- FURI_LOG_E(TAG, "Unable to add Custom_preset_module");
- break;
- }
- if(!flipper_format_write_hex(
- flipper_format, "Custom_preset_data", preset->data, preset->data_size)) {
- FURI_LOG_E(TAG, "Unable to add Custom_preset_data");
- break;
- }
- }
- if(!flipper_format_write_string_cstr(
- flipper_format, "Protocol", instance->generic.protocol_name)) {
- FURI_LOG_E(TAG, "Unable to add Protocol");
- break;
- }
- uint32_t temp = instance->generic.data_count_bit;
- if(!flipper_format_write_uint32(flipper_format, "Bit", &temp, 1)) {
- FURI_LOG_E(TAG, "Unable to add Bit");
- break;
- }
- if(!flipper_format_write_uint32(flipper_format, "TE", &instance->te, 1)) {
- FURI_LOG_E(TAG, "Unable to add TE");
- break;
- }
- uint16_t i = 0;
- while((i < BIN_RAW_MAX_MARKUP_COUNT) && (instance->data_markup[i].bit_count != 0)) {
- temp = instance->data_markup[i].bit_count;
- if(!flipper_format_write_uint32(flipper_format, "Bit_RAW", &temp, 1)) {
- FURI_LOG_E(TAG, "Bit_RAW");
- break;
- }
- if(!flipper_format_write_hex(
- flipper_format,
- "Data_RAW",
- instance->data + instance->data_markup[i].byte_bias,
- subghz_protocol_bin_raw_get_full_byte(instance->data_markup[i].bit_count))) {
- FURI_LOG_E(TAG, "Unable to add Data_RAW");
- break;
- }
- i++;
- }
- res = true;
- } while(false);
- furi_string_free(temp_str);
- return res;
- }
- bool subghz_protocol_decoder_bin_raw_deserialize(void* context, FlipperFormat* flipper_format) {
- furi_assert(context);
- SubGhzProtocolDecoderBinRAW* instance = context;
- bool res = false;
- uint32_t temp_data = 0;
- do {
- if(!flipper_format_rewind(flipper_format)) {
- FURI_LOG_E(TAG, "Rewind error");
- break;
- }
- if(!flipper_format_read_uint32(flipper_format, "Bit", (uint32_t*)&temp_data, 1)) {
- FURI_LOG_E(TAG, "Missing Bit");
- break;
- }
- instance->generic.data_count_bit = (uint16_t)temp_data;
- if(!flipper_format_read_uint32(flipper_format, "TE", (uint32_t*)&instance->te, 1)) {
- FURI_LOG_E(TAG, "Missing TE");
- break;
- }
- temp_data = 0;
- uint16_t ind = 0;
- uint16_t byte_bias = 0;
- uint16_t byte_count = 0;
- memset(instance->data_markup, 0x00, BIN_RAW_MAX_MARKUP_COUNT * sizeof(BinRAW_Markup));
- while(flipper_format_read_uint32(flipper_format, "Bit_RAW", (uint32_t*)&temp_data, 1)) {
- if(ind >= BIN_RAW_MAX_MARKUP_COUNT) {
- FURI_LOG_E(TAG, "Markup overflow");
- break;
- }
- byte_count += subghz_protocol_bin_raw_get_full_byte(temp_data);
- if(byte_count > BIN_RAW_BUF_DATA_SIZE) {
- FURI_LOG_E(TAG, "Receive buffer overflow");
- break;
- }
- instance->data_markup[ind].bit_count = temp_data;
- instance->data_markup[ind].byte_bias = byte_bias;
- byte_bias += subghz_protocol_bin_raw_get_full_byte(temp_data);
- if(!flipper_format_read_hex(
- flipper_format,
- "Data_RAW",
- instance->data + instance->data_markup[ind].byte_bias,
- subghz_protocol_bin_raw_get_full_byte(temp_data))) {
- instance->data_markup[ind].bit_count = 0;
- FURI_LOG_E(TAG, "Missing Data_RAW");
- break;
- }
- ind++;
- }
- res = true;
- } while(0);
- return res;
- }
- void subghz_protocol_decoder_bin_raw_get_string(void* context, FuriString* output) {
- furi_assert(context);
- SubGhzProtocolDecoderBinRAW* instance = context;
- furi_string_cat_printf(
- output,
- "%s %dbit\r\n"
- "Key:",
- instance->generic.protocol_name,
- instance->generic.data_count_bit);
- uint16_t byte_count = subghz_protocol_bin_raw_get_full_byte(instance->generic.data_count_bit);
- for(size_t i = 0; (byte_count < 36 ? i < byte_count : i < 36); i++) {
- furi_string_cat_printf(output, "%02X", instance->data[i]);
- }
- furi_string_cat_printf(output, "\r\nTe:%luus\r\n", instance->te);
- }
|