From 406d830fb652bb0a8791efd28357bb50e1f9640a Mon Sep 17 00:00:00 2001 From: Max Lapan Date: Wed, 26 Oct 2022 15:37:58 +0200 Subject: [PATCH 1/4] Oregon2 extra (#1924) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add support for temp-humid sensor 0x1D20 * Fix protocol type and flags, humidity decoding Co-authored-by: あく --- .../weather_station/protocols/oregon2.c | 42 ++++++++++++------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/applications/plugins/weather_station/protocols/oregon2.c b/applications/plugins/weather_station/protocols/oregon2.c index c4e4471a0..76bc3f0a1 100644 --- a/applications/plugins/weather_station/protocols/oregon2.c +++ b/applications/plugins/weather_station/protocols/oregon2.c @@ -19,7 +19,7 @@ static const SubGhzBlockConst ws_oregon2_const = { }; #define OREGON2_PREAMBLE_BITS 19 -#define OREGON2_PREAMBLE_MASK ((1 << (OREGON2_PREAMBLE_BITS + 1)) - 1) +#define OREGON2_PREAMBLE_MASK 0b1111111111111111111 #define OREGON2_SENSOR_ID(d) (((d) >> 16) & 0xFFFF) #define OREGON2_CHECKSUM_BITS 8 @@ -103,6 +103,7 @@ static ManchesterEvent level_and_duration_to_event(bool level, uint32_t duration // From sensor id code return amount of bits in variable section static uint8_t oregon2_sensor_id_var_bits(uint16_t sensor_id) { if(sensor_id == 0xEC40) return 16; + if(sensor_id == 0x1D20) return 24; return 0; } @@ -119,18 +120,30 @@ static void ws_oregon2_decode_const_data(WSBlockGeneric* ws_block) { ws_block->battery_low = (ws_block->data & OREGON2_FLAG_BAT_LOW) ? 1 : 0; } -static void - ws_oregon2_decode_var_data(WSBlockGeneric* ws_block, uint16_t sensor_id, uint32_t var_data) { - int16_t temp_val; - if(sensor_id == 0xEC40) { - temp_val = ((var_data >> 4) & 0xF) * 10 + ((var_data >> 8) & 0xF); - temp_val *= 10; - temp_val += (var_data >> 12) & 0xF; - if(var_data & 0xF) temp_val = -temp_val; - } else - return; +uint16_t bcd_decode_short(uint32_t data) { + return (data & 0xF) * 10 + ((data >> 4) & 0xF); +} - ws_block->temp = (float)temp_val / 10.0; +static float ws_oregon2_decode_temp(uint32_t data) { + int32_t temp_val; + temp_val = bcd_decode_short(data >> 4); + temp_val *= 10; + temp_val += (data >> 12) & 0xF; + if(data & 0xF) temp_val = -temp_val; + return (float)temp_val / 10.0; +} + +static void ws_oregon2_decode_var_data(WSBlockGeneric* ws_b, uint16_t sensor_id, uint32_t data) { + switch(sensor_id) { + case 0xEC40: + ws_b->temp = ws_oregon2_decode_temp(data); + ws_b->humidity = WS_NO_HUMIDITY; + break; + case 0x1D20: + ws_b->humidity = bcd_decode_short(data); + ws_b->temp = ws_oregon2_decode_temp(data >> 8); + break; + } } void ws_protocol_decoder_oregon2_feed(void* context, bool level, uint32_t duration) { @@ -346,9 +359,8 @@ const SubGhzProtocolDecoder ws_protocol_oregon2_decoder = { const SubGhzProtocol ws_protocol_oregon2 = { .name = WS_PROTOCOL_OREGON2_NAME, - .type = SubGhzProtocolTypeStatic, - .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable | - SubGhzProtocolFlag_Load | SubGhzProtocolFlag_Save, + .type = SubGhzProtocolWeatherStation, + .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable, .decoder = &ws_protocol_oregon2_decoder, }; From 378bf050684b9e56d71c84fd2e44a57caa507ee2 Mon Sep 17 00:00:00 2001 From: Skorpionm <85568270+Skorpionm@users.noreply.github.com> Date: Wed, 26 Oct 2022 18:56:54 +0400 Subject: [PATCH 2/4] [FL-2934] WS: add protocol Acurite 592TXR (#1916) * WS: add protocol Acurite 592TXR * WS: fix decoder Acurite_592TXR * SubGhz: proper types in math Co-authored-by: Aleksandr Kutuzov --- .../helpers/weather_station_types.h | 2 +- .../protocols/acurite_592txr.c | 307 ++++++++++++++++++ .../protocols/acurite_592txr.h | 79 +++++ .../protocols/protocol_items.c | 1 + .../protocols/protocol_items.h | 1 + firmware/targets/f7/api_symbols.csv | 6 +- lib/subghz/blocks/math.c | 30 ++ lib/subghz/blocks/math.h | 31 ++ 8 files changed, 455 insertions(+), 2 deletions(-) create mode 100644 applications/plugins/weather_station/protocols/acurite_592txr.c create mode 100644 applications/plugins/weather_station/protocols/acurite_592txr.h diff --git a/applications/plugins/weather_station/helpers/weather_station_types.h b/applications/plugins/weather_station/helpers/weather_station_types.h index 275d23329..479638b98 100644 --- a/applications/plugins/weather_station/helpers/weather_station_types.h +++ b/applications/plugins/weather_station/helpers/weather_station_types.h @@ -3,7 +3,7 @@ #include #include -#define WS_VERSION_APP "0.2" +#define WS_VERSION_APP "0.3" #define WS_DEVELOPED "SkorP" #define WS_GITHUB "https://github.com/flipperdevices/flipperzero-firmware" diff --git a/applications/plugins/weather_station/protocols/acurite_592txr.c b/applications/plugins/weather_station/protocols/acurite_592txr.c new file mode 100644 index 000000000..db05af095 --- /dev/null +++ b/applications/plugins/weather_station/protocols/acurite_592txr.c @@ -0,0 +1,307 @@ +#include "acurite_592txr.h" + +#define TAG "WSProtocolAcurite_592TXR" + +/* + * Help + * https://github.com/merbanan/rtl_433/blob/5bef4e43133ac4c0e2d18d36f87c52b4f9458453/src/devices/acurite.c + * + * Acurite 592TXR Temperature Humidity sensor decoder + * Message Type 0x04, 7 bytes + * | Byte 0 | Byte 1 | Byte 2 | Byte 3 | Byte 4 | Byte 5 | Byte 6 | + * | --------- | --------- | --------- | --------- | --------- | --------- | --------- | + * | CCII IIII | IIII IIII | pB00 0100 | pHHH HHHH | p??T TTTT | pTTT TTTT | KKKK KKKK | + * - C: Channel 00: C, 10: B, 11: A, (01 is invalid) + * - I: Device ID (14 bits) + * - B: Battery, 1 is battery OK, 0 is battery low + * - M: Message type (6 bits), 0x04 + * - T: Temperature Celsius (11 - 14 bits?), + 1000 * 10 + * - H: Relative Humidity (%) (7 bits) + * - K: Checksum (8 bits) + * - p: Parity bit + * Notes: + * - Temperature + * - Encoded as Celsius + 1000 * 10 + * - only 11 bits needed for specified range -40 C to 70 C (-40 F - 158 F) + * - However 14 bits available for temperature, giving possible range of -100 C to 1538.4 C + * - @todo - check if high 3 bits ever used for anything else + * + */ + +static const SubGhzBlockConst ws_protocol_acurite_592txr_const = { + .te_short = 200, + .te_long = 400, + .te_delta = 90, + .min_count_bit_for_found = 56, +}; + +struct WSProtocolDecoderAcurite_592TXR { + SubGhzProtocolDecoderBase base; + + SubGhzBlockDecoder decoder; + WSBlockGeneric generic; + + uint16_t header_count; +}; + +struct WSProtocolEncoderAcurite_592TXR { + SubGhzProtocolEncoderBase base; + + SubGhzProtocolBlockEncoder encoder; + WSBlockGeneric generic; +}; + +typedef enum { + Acurite_592TXRDecoderStepReset = 0, + Acurite_592TXRDecoderStepCheckPreambule, + Acurite_592TXRDecoderStepSaveDuration, + Acurite_592TXRDecoderStepCheckDuration, +} Acurite_592TXRDecoderStep; + +const SubGhzProtocolDecoder ws_protocol_acurite_592txr_decoder = { + .alloc = ws_protocol_decoder_acurite_592txr_alloc, + .free = ws_protocol_decoder_acurite_592txr_free, + + .feed = ws_protocol_decoder_acurite_592txr_feed, + .reset = ws_protocol_decoder_acurite_592txr_reset, + + .get_hash_data = ws_protocol_decoder_acurite_592txr_get_hash_data, + .serialize = ws_protocol_decoder_acurite_592txr_serialize, + .deserialize = ws_protocol_decoder_acurite_592txr_deserialize, + .get_string = ws_protocol_decoder_acurite_592txr_get_string, +}; + +const SubGhzProtocolEncoder ws_protocol_acurite_592txr_encoder = { + .alloc = NULL, + .free = NULL, + + .deserialize = NULL, + .stop = NULL, + .yield = NULL, +}; + +const SubGhzProtocol ws_protocol_acurite_592txr = { + .name = WS_PROTOCOL_ACURITE_592TXR_NAME, + .type = SubGhzProtocolWeatherStation, + .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_868 | + SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable, + + .decoder = &ws_protocol_acurite_592txr_decoder, + .encoder = &ws_protocol_acurite_592txr_encoder, +}; + +void* ws_protocol_decoder_acurite_592txr_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); + WSProtocolDecoderAcurite_592TXR* instance = malloc(sizeof(WSProtocolDecoderAcurite_592TXR)); + instance->base.protocol = &ws_protocol_acurite_592txr; + instance->generic.protocol_name = instance->base.protocol->name; + return instance; +} + +void ws_protocol_decoder_acurite_592txr_free(void* context) { + furi_assert(context); + WSProtocolDecoderAcurite_592TXR* instance = context; + free(instance); +} + +void ws_protocol_decoder_acurite_592txr_reset(void* context) { + furi_assert(context); + WSProtocolDecoderAcurite_592TXR* instance = context; + instance->decoder.parser_step = Acurite_592TXRDecoderStepReset; +} + +static bool ws_protocol_acurite_592txr_check_crc(WSProtocolDecoderAcurite_592TXR* instance) { + uint8_t msg[] = { + instance->decoder.decode_data >> 48, + instance->decoder.decode_data >> 40, + instance->decoder.decode_data >> 32, + instance->decoder.decode_data >> 24, + instance->decoder.decode_data >> 16, + instance->decoder.decode_data >> 8}; + + if((subghz_protocol_blocks_add_bytes(msg, 6) == + (uint8_t)(instance->decoder.decode_data & 0xFF)) && + (!subghz_protocol_blocks_parity_bytes(&msg[2], 4))) { + return true; + } else { + return false; + } +} + +/** + * Analysis of received data + * @param instance Pointer to a WSBlockGeneric* instance + */ +static void ws_protocol_acurite_592txr_remote_controller(WSBlockGeneric* instance) { + uint8_t channel[] = {3, 0, 2, 1}; + uint8_t channel_raw = ((instance->data >> 54) & 0x03); + instance->channel = channel[channel_raw]; + instance->id = (instance->data >> 40) & 0x3FFF; + instance->battery_low = !((instance->data >> 38) & 1); + instance->humidity = (instance->data >> 24) & 0x7F; + + uint16_t temp_raw = ((instance->data >> 9) & 0xF80) | ((instance->data >> 8) & 0x7F); + instance->temp = ((float)(temp_raw)-1000) / 10.0f; + + instance->btn = WS_NO_BTN; +} + +void ws_protocol_decoder_acurite_592txr_feed(void* context, bool level, uint32_t duration) { + furi_assert(context); + WSProtocolDecoderAcurite_592TXR* instance = context; + + switch(instance->decoder.parser_step) { + case Acurite_592TXRDecoderStepReset: + if((level) && (DURATION_DIFF(duration, ws_protocol_acurite_592txr_const.te_short * 3) < + ws_protocol_acurite_592txr_const.te_delta * 2)) { + instance->decoder.parser_step = Acurite_592TXRDecoderStepCheckPreambule; + instance->decoder.te_last = duration; + instance->header_count = 0; + } + break; + + case Acurite_592TXRDecoderStepCheckPreambule: + if(level) { + instance->decoder.te_last = duration; + } else { + if((DURATION_DIFF( + instance->decoder.te_last, ws_protocol_acurite_592txr_const.te_short * 3) < + ws_protocol_acurite_592txr_const.te_delta * 2) && + (DURATION_DIFF(duration, ws_protocol_acurite_592txr_const.te_short * 3) < + ws_protocol_acurite_592txr_const.te_delta * 2)) { + //Found preambule + instance->header_count++; + } else if((instance->header_count > 2) && (instance->header_count < 5)) { + if((DURATION_DIFF( + instance->decoder.te_last, ws_protocol_acurite_592txr_const.te_short) < + ws_protocol_acurite_592txr_const.te_delta) && + (DURATION_DIFF(duration, ws_protocol_acurite_592txr_const.te_long) < + ws_protocol_acurite_592txr_const.te_delta)) { + instance->decoder.decode_data = 0; + instance->decoder.decode_count_bit = 0; + subghz_protocol_blocks_add_bit(&instance->decoder, 0); + instance->decoder.parser_step = Acurite_592TXRDecoderStepSaveDuration; + } else if( + (DURATION_DIFF( + instance->decoder.te_last, ws_protocol_acurite_592txr_const.te_long) < + ws_protocol_acurite_592txr_const.te_delta) && + (DURATION_DIFF(duration, ws_protocol_acurite_592txr_const.te_short) < + ws_protocol_acurite_592txr_const.te_delta)) { + instance->decoder.decode_data = 0; + instance->decoder.decode_count_bit = 0; + subghz_protocol_blocks_add_bit(&instance->decoder, 1); + instance->decoder.parser_step = Acurite_592TXRDecoderStepSaveDuration; + } else { + instance->decoder.parser_step = Acurite_592TXRDecoderStepReset; + } + } else { + instance->decoder.parser_step = Acurite_592TXRDecoderStepReset; + } + } + break; + + case Acurite_592TXRDecoderStepSaveDuration: + if(level) { + instance->decoder.te_last = duration; + instance->decoder.parser_step = Acurite_592TXRDecoderStepCheckDuration; + } else { + instance->decoder.parser_step = Acurite_592TXRDecoderStepReset; + } + break; + + case Acurite_592TXRDecoderStepCheckDuration: + if(!level) { + if(duration >= ((uint32_t)ws_protocol_acurite_592txr_const.te_short * 5)) { + if((instance->decoder.decode_count_bit == + ws_protocol_acurite_592txr_const.min_count_bit_for_found) && + ws_protocol_acurite_592txr_check_crc(instance)) { + instance->generic.data = instance->decoder.decode_data; + instance->generic.data_count_bit = instance->decoder.decode_count_bit; + ws_protocol_acurite_592txr_remote_controller(&instance->generic); + if(instance->base.callback) + instance->base.callback(&instance->base, instance->base.context); + } + instance->decoder.decode_data = 0; + instance->decoder.decode_count_bit = 0; + instance->decoder.parser_step = Acurite_592TXRDecoderStepReset; + break; + } else if( + (DURATION_DIFF( + instance->decoder.te_last, ws_protocol_acurite_592txr_const.te_short) < + ws_protocol_acurite_592txr_const.te_delta) && + (DURATION_DIFF(duration, ws_protocol_acurite_592txr_const.te_long) < + ws_protocol_acurite_592txr_const.te_delta)) { + subghz_protocol_blocks_add_bit(&instance->decoder, 0); + instance->decoder.parser_step = Acurite_592TXRDecoderStepSaveDuration; + } else if( + (DURATION_DIFF( + instance->decoder.te_last, ws_protocol_acurite_592txr_const.te_long) < + ws_protocol_acurite_592txr_const.te_delta) && + (DURATION_DIFF(duration, ws_protocol_acurite_592txr_const.te_short) < + ws_protocol_acurite_592txr_const.te_delta)) { + subghz_protocol_blocks_add_bit(&instance->decoder, 1); + instance->decoder.parser_step = Acurite_592TXRDecoderStepSaveDuration; + } else { + instance->decoder.parser_step = Acurite_592TXRDecoderStepReset; + } + } else { + instance->decoder.parser_step = Acurite_592TXRDecoderStepReset; + } + break; + } +} + +uint8_t ws_protocol_decoder_acurite_592txr_get_hash_data(void* context) { + furi_assert(context); + WSProtocolDecoderAcurite_592TXR* instance = context; + return subghz_protocol_blocks_get_hash_data( + &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); +} + +bool ws_protocol_decoder_acurite_592txr_serialize( + void* context, + FlipperFormat* flipper_format, + SubGhzRadioPreset* preset) { + furi_assert(context); + WSProtocolDecoderAcurite_592TXR* instance = context; + return ws_block_generic_serialize(&instance->generic, flipper_format, preset); +} + +bool ws_protocol_decoder_acurite_592txr_deserialize(void* context, FlipperFormat* flipper_format) { + furi_assert(context); + WSProtocolDecoderAcurite_592TXR* instance = context; + bool ret = false; + do { + if(!ws_block_generic_deserialize(&instance->generic, flipper_format)) { + break; + } + if(instance->generic.data_count_bit != + ws_protocol_acurite_592txr_const.min_count_bit_for_found) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + break; + } + ret = true; + } while(false); + return ret; +} + +void ws_protocol_decoder_acurite_592txr_get_string(void* context, FuriString* output) { + furi_assert(context); + WSProtocolDecoderAcurite_592TXR* instance = context; + furi_string_printf( + output, + "%s %dbit\r\n" + "Key:0x%lX%08lX\r\n" + "Sn:0x%lX Ch:%d Bat:%d\r\n" + "Temp:%d.%d C Hum:%d%%", + instance->generic.protocol_name, + instance->generic.data_count_bit, + (uint32_t)(instance->generic.data >> 32), + (uint32_t)(instance->generic.data), + instance->generic.id, + instance->generic.channel, + instance->generic.battery_low, + (int16_t)instance->generic.temp, + abs(((int16_t)(instance->generic.temp * 10) - (((int16_t)instance->generic.temp) * 10))), + instance->generic.humidity); +} diff --git a/applications/plugins/weather_station/protocols/acurite_592txr.h b/applications/plugins/weather_station/protocols/acurite_592txr.h new file mode 100644 index 000000000..ac0371d89 --- /dev/null +++ b/applications/plugins/weather_station/protocols/acurite_592txr.h @@ -0,0 +1,79 @@ +#pragma once + +#include + +#include +#include +#include +#include "ws_generic.h" +#include + +#define WS_PROTOCOL_ACURITE_592TXR_NAME "Acurite 592TXR" + +typedef struct WSProtocolDecoderAcurite_592TXR WSProtocolDecoderAcurite_592TXR; +typedef struct WSProtocolEncoderAcurite_592TXR WSProtocolEncoderAcurite_592TXR; + +extern const SubGhzProtocolDecoder ws_protocol_acurite_592txr_decoder; +extern const SubGhzProtocolEncoder ws_protocol_acurite_592txr_encoder; +extern const SubGhzProtocol ws_protocol_acurite_592txr; + +/** + * Allocate WSProtocolDecoderAcurite_592TXR. + * @param environment Pointer to a SubGhzEnvironment instance + * @return WSProtocolDecoderAcurite_592TXR* pointer to a WSProtocolDecoderAcurite_592TXR instance + */ +void* ws_protocol_decoder_acurite_592txr_alloc(SubGhzEnvironment* environment); + +/** + * Free WSProtocolDecoderAcurite_592TXR. + * @param context Pointer to a WSProtocolDecoderAcurite_592TXR instance + */ +void ws_protocol_decoder_acurite_592txr_free(void* context); + +/** + * Reset decoder WSProtocolDecoderAcurite_592TXR. + * @param context Pointer to a WSProtocolDecoderAcurite_592TXR instance + */ +void ws_protocol_decoder_acurite_592txr_reset(void* context); + +/** + * Parse a raw sequence of levels and durations received from the air. + * @param context Pointer to a WSProtocolDecoderAcurite_592TXR instance + * @param level Signal level true-high false-low + * @param duration Duration of this level in, us + */ +void ws_protocol_decoder_acurite_592txr_feed(void* context, bool level, uint32_t duration); + +/** + * Getting the hash sum of the last randomly received parcel. + * @param context Pointer to a WSProtocolDecoderAcurite_592TXR instance + * @return hash Hash sum + */ +uint8_t ws_protocol_decoder_acurite_592txr_get_hash_data(void* context); + +/** + * Serialize data WSProtocolDecoderAcurite_592TXR. + * @param context Pointer to a WSProtocolDecoderAcurite_592TXR instance + * @param flipper_format Pointer to a FlipperFormat instance + * @param preset The modulation on which the signal was received, SubGhzRadioPreset + * @return true On success + */ +bool ws_protocol_decoder_acurite_592txr_serialize( + void* context, + FlipperFormat* flipper_format, + SubGhzRadioPreset* preset); + +/** + * Deserialize data WSProtocolDecoderAcurite_592TXR. + * @param context Pointer to a WSProtocolDecoderAcurite_592TXR instance + * @param flipper_format Pointer to a FlipperFormat instance + * @return true On success + */ +bool ws_protocol_decoder_acurite_592txr_deserialize(void* context, FlipperFormat* flipper_format); + +/** + * Getting a textual representation of the received data. + * @param context Pointer to a WSProtocolDecoderAcurite_592TXR instance + * @param output Resulting text + */ +void ws_protocol_decoder_acurite_592txr_get_string(void* context, FuriString* output); diff --git a/applications/plugins/weather_station/protocols/protocol_items.c b/applications/plugins/weather_station/protocols/protocol_items.c index 0740691a2..3ec9e995a 100644 --- a/applications/plugins/weather_station/protocols/protocol_items.c +++ b/applications/plugins/weather_station/protocols/protocol_items.c @@ -8,6 +8,7 @@ const SubGhzProtocol* weather_station_protocol_registry_items[] = { &ws_protocol_acurite_606tx, &ws_protocol_lacrosse_tx141thbv2, &ws_protocol_oregon2, + &ws_protocol_acurite_592txr, }; const SubGhzProtocolRegistry weather_station_protocol_registry = { diff --git a/applications/plugins/weather_station/protocols/protocol_items.h b/applications/plugins/weather_station/protocols/protocol_items.h index edc078cd6..8f3eb53d7 100644 --- a/applications/plugins/weather_station/protocols/protocol_items.h +++ b/applications/plugins/weather_station/protocols/protocol_items.h @@ -8,5 +8,6 @@ #include "acurite_606tx.h" #include "lacrosse_tx141thbv2.h" #include "oregon2.h" +#include "acurite_592txr.h" extern const SubGhzProtocolRegistry weather_station_protocol_registry; diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index 4c48d9abd..17a8a675a 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,5.0,, +Version,+,5.1,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -2271,6 +2271,7 @@ Function,-,subghz_keystore_raw_encrypted_save,_Bool,"const char*, const char*, u Function,-,subghz_keystore_raw_get_data,_Bool,"const char*, size_t, uint8_t*, size_t" Function,-,subghz_keystore_save,_Bool,"SubGhzKeystore*, const char*, uint8_t*" Function,+,subghz_protocol_blocks_add_bit,void,"SubGhzBlockDecoder*, uint8_t" +Function,+,subghz_protocol_blocks_add_bytes,uint8_t,"const uint8_t[], size_t" Function,+,subghz_protocol_blocks_crc16,uint16_t,"const uint8_t[], unsigned, uint16_t, uint16_t" Function,+,subghz_protocol_blocks_crc16lsb,uint16_t,"const uint8_t[], unsigned, uint16_t, uint16_t" Function,+,subghz_protocol_blocks_crc4,uint8_t,"const uint8_t[], unsigned, uint8_t, uint8_t" @@ -2284,8 +2285,11 @@ Function,+,subghz_protocol_blocks_get_upload,size_t,"uint8_t[], size_t, LevelDur Function,+,subghz_protocol_blocks_lfsr_digest16,uint16_t,"const uint8_t[], unsigned, uint16_t, uint16_t" Function,+,subghz_protocol_blocks_lfsr_digest8,uint8_t,"const uint8_t[], unsigned, uint8_t, uint8_t" Function,+,subghz_protocol_blocks_lfsr_digest8_reflect,uint8_t,"const uint8_t[], int, uint8_t, uint8_t" +Function,+,subghz_protocol_blocks_parity8,int,uint8_t +Function,+,subghz_protocol_blocks_parity_bytes,int,"const uint8_t[], size_t" Function,+,subghz_protocol_blocks_reverse_key,uint64_t,"uint64_t, uint8_t" Function,+,subghz_protocol_blocks_set_bit_array,void,"_Bool, uint8_t[], size_t, size_t" +Function,+,subghz_protocol_blocks_xor_bytes,uint8_t,"const uint8_t[], size_t" Function,-,subghz_protocol_decoder_base_deserialize,_Bool,"SubGhzProtocolDecoderBase*, FlipperFormat*" Function,+,subghz_protocol_decoder_base_get_hash_data,uint8_t,SubGhzProtocolDecoderBase* Function,+,subghz_protocol_decoder_base_get_string,_Bool,"SubGhzProtocolDecoderBase*, FuriString*" diff --git a/lib/subghz/blocks/math.c b/lib/subghz/blocks/math.c index 588d4effc..d2b8e3d11 100644 --- a/lib/subghz/blocks/math.c +++ b/lib/subghz/blocks/math.c @@ -216,4 +216,34 @@ uint16_t subghz_protocol_blocks_lfsr_digest16( } } return sum; +} + +uint8_t subghz_protocol_blocks_add_bytes(uint8_t const message[], size_t num_bytes) { + int result = 0; + for(size_t i = 0; i < num_bytes; ++i) { + result += message[i]; + } + return (uint8_t)result; +} + +int subghz_protocol_blocks_parity8(uint8_t byte) { + byte ^= byte >> 4; + byte &= 0xf; + return (0x6996 >> byte) & 1; +} + +int subghz_protocol_blocks_parity_bytes(uint8_t const message[], size_t num_bytes) { + int result = 0; + for(size_t i = 0; i < num_bytes; ++i) { + result ^= subghz_protocol_blocks_parity8(message[i]); + } + return result; +} + +uint8_t subghz_protocol_blocks_xor_bytes(uint8_t const message[], size_t num_bytes) { + uint8_t result = 0; + for(size_t i = 0; i < num_bytes; ++i) { + result ^= message[i]; + } + return result; } \ No newline at end of file diff --git a/lib/subghz/blocks/math.h b/lib/subghz/blocks/math.h index 275889484..8cddf4c0b 100644 --- a/lib/subghz/blocks/math.h +++ b/lib/subghz/blocks/math.h @@ -161,6 +161,37 @@ uint16_t subghz_protocol_blocks_lfsr_digest16( uint16_t gen, uint16_t key); +/** + * Compute Addition of a number of bytes. + * @param message bytes of message data + * @param num_bytes number of bytes to sum + * @return summation value + **/ +uint8_t subghz_protocol_blocks_add_bytes(uint8_t const message[], size_t num_bytes); + +/** + * Compute bit parity of a single byte (8 bits). + * @param byte single byte to check + * @return 1 odd parity, 0 even parity + **/ +int subghz_protocol_blocks_parity8(uint8_t byte); + +/** + * Compute bit parity of a number of bytes. + * @param message bytes of message data + * @param num_bytes number of bytes to sum + * @return 1 odd parity, 0 even parity + **/ +int subghz_protocol_blocks_parity_bytes(uint8_t const message[], size_t num_bytes); + +/** + * Compute XOR (byte-wide parity) of a number of bytes. + * @param message bytes of message data + * @param num_bytes number of bytes to sum + * @return summation value, per bit-position 1 odd parity, 0 even parity + **/ +uint8_t subghz_protocol_blocks_xor_bytes(uint8_t const message[], size_t num_bytes); + #ifdef __cplusplus } #endif From 5c8df66b7c2d10c4e17c831ebf9852d5690205fc Mon Sep 17 00:00:00 2001 From: Skorpionm <85568270+Skorpionm@users.noreply.github.com> Date: Wed, 26 Oct 2022 19:13:00 +0400 Subject: [PATCH 3/4] [FL-2927] SubGhz: add RAW Read threshold rssi (#1911) * SubGhz: add RAW Read threshold rssi * SubGhz: update indicator RSSI * SubGhz: fix record file Co-authored-by: Aleksandr Kutuzov --- .../subghz/scenes/subghz_scene_read_raw.c | 50 ++++++++++-- .../scenes/subghz_scene_receiver_config.c | 52 +++++++++++++ applications/main/subghz/subghz.c | 1 + applications/main/subghz/subghz_i.h | 3 + .../main/subghz/views/subghz_read_raw.c | 77 ++++++++++++++++--- .../main/subghz/views/subghz_read_raw.h | 7 +- firmware/targets/f7/api_symbols.csv | 1 + lib/subghz/protocols/raw.c | 12 ++- lib/subghz/protocols/raw.h | 7 ++ 9 files changed, 192 insertions(+), 18 deletions(-) diff --git a/applications/main/subghz/scenes/subghz_scene_read_raw.c b/applications/main/subghz/scenes/subghz_scene_read_raw.c index 5dacefd66..8ac9bf5ba 100644 --- a/applications/main/subghz/scenes/subghz_scene_read_raw.c +++ b/applications/main/subghz/scenes/subghz_scene_read_raw.c @@ -6,6 +6,7 @@ #define RAW_FILE_NAME "Raw_signal_" #define TAG "SubGhzSceneReadRAW" +#define RAW_THRESHOLD_RSSI_LOW_COUNT 10 bool subghz_scene_read_raw_update_filename(SubGhz* subghz) { bool ret = false; @@ -72,24 +73,33 @@ void subghz_scene_read_raw_on_enter(void* context) { switch(subghz->txrx->rx_key_state) { case SubGhzRxKeyStateBack: - subghz_read_raw_set_status(subghz->subghz_read_raw, SubGhzReadRAWStatusIDLE, ""); + subghz_read_raw_set_status( + subghz->subghz_read_raw, SubGhzReadRAWStatusIDLE, "", subghz->txrx->raw_threshold_rssi); break; case SubGhzRxKeyStateRAWLoad: path_extract_filename(subghz->file_path, file_name, true); subghz_read_raw_set_status( subghz->subghz_read_raw, SubGhzReadRAWStatusLoadKeyTX, - furi_string_get_cstr(file_name)); + furi_string_get_cstr(file_name), + subghz->txrx->raw_threshold_rssi); subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE; break; case SubGhzRxKeyStateRAWSave: path_extract_filename(subghz->file_path, file_name, true); subghz_read_raw_set_status( - subghz->subghz_read_raw, SubGhzReadRAWStatusSaveKey, furi_string_get_cstr(file_name)); + subghz->subghz_read_raw, + SubGhzReadRAWStatusSaveKey, + furi_string_get_cstr(file_name), + subghz->txrx->raw_threshold_rssi); subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE; break; default: - subghz_read_raw_set_status(subghz->subghz_read_raw, SubGhzReadRAWStatusStart, ""); + subghz_read_raw_set_status( + subghz->subghz_read_raw, + SubGhzReadRAWStatusStart, + "", + subghz->txrx->raw_threshold_rssi); subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE; break; } @@ -273,7 +283,7 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) { if(subghz->txrx->rx_key_state != SubGhzRxKeyStateIDLE) { scene_manager_next_scene(subghz->scene_manager, SubGhzSceneNeedSaving); } else { - //subghz_get_preset_name(subghz, subghz->error_str); + subghz->txrx->raw_threshold_rssi_low_count = RAW_THRESHOLD_RSSI_LOW_COUNT; if(subghz_protocol_raw_save_to_file_init( (SubGhzProtocolDecoderRAW*)subghz->txrx->decoder_result, RAW_FILE_NAME, @@ -319,7 +329,35 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) { subghz->subghz_read_raw, subghz_protocol_raw_get_sample_write( (SubGhzProtocolDecoderRAW*)subghz->txrx->decoder_result)); - subghz_read_raw_add_data_rssi(subghz->subghz_read_raw, furi_hal_subghz_get_rssi()); + + float rssi = furi_hal_subghz_get_rssi(); + + if(subghz->txrx->raw_threshold_rssi == SUBGHZ_RAW_TRESHOLD_MIN) { + subghz_read_raw_add_data_rssi(subghz->subghz_read_raw, rssi, true); + subghz_protocol_raw_save_to_file_pause( + (SubGhzProtocolDecoderRAW*)subghz->txrx->decoder_result, false); + } else { + if(rssi < subghz->txrx->raw_threshold_rssi) { + subghz->txrx->raw_threshold_rssi_low_count++; + if(subghz->txrx->raw_threshold_rssi_low_count > RAW_THRESHOLD_RSSI_LOW_COUNT) { + subghz->txrx->raw_threshold_rssi_low_count = RAW_THRESHOLD_RSSI_LOW_COUNT; + } + subghz_read_raw_add_data_rssi(subghz->subghz_read_raw, rssi, false); + } else { + subghz->txrx->raw_threshold_rssi_low_count = 0; + } + + if(subghz->txrx->raw_threshold_rssi_low_count == RAW_THRESHOLD_RSSI_LOW_COUNT) { + subghz_read_raw_add_data_rssi(subghz->subghz_read_raw, rssi, false); + subghz_protocol_raw_save_to_file_pause( + (SubGhzProtocolDecoderRAW*)subghz->txrx->decoder_result, true); + } else { + subghz_read_raw_add_data_rssi(subghz->subghz_read_raw, rssi, true); + subghz_protocol_raw_save_to_file_pause( + (SubGhzProtocolDecoderRAW*)subghz->txrx->decoder_result, false); + } + } + break; case SubGhzNotificationStateTx: notification_message(subghz->notifications, &sequence_blink_magenta_10); diff --git a/applications/main/subghz/scenes/subghz_scene_receiver_config.c b/applications/main/subghz/scenes/subghz_scene_receiver_config.c index 5f022d6e1..fd42829b5 100644 --- a/applications/main/subghz/scenes/subghz_scene_receiver_config.c +++ b/applications/main/subghz/scenes/subghz_scene_receiver_config.c @@ -1,10 +1,41 @@ #include "../subghz_i.h" +#include enum SubGhzSettingIndex { SubGhzSettingIndexFrequency, SubGhzSettingIndexHopping, SubGhzSettingIndexModulation, SubGhzSettingIndexLock, + SubGhzSettingIndexRAWThesholdRSSI, +}; + +#define RAW_THRESHOLD_RSSI_COUNT 11 +const char* const raw_theshold_rssi_text[RAW_THRESHOLD_RSSI_COUNT] = { + "-----", + "-85.0", + "-80.0", + "-75.0", + "-70.0", + "-65.0", + "-60.0", + "-55.0", + "-50.0", + "-45.0", + "-40.0", + +}; +const float raw_theshold_rssi_value[RAW_THRESHOLD_RSSI_COUNT] = { + -90.0f, + -85.0f, + -80.0f, + -75.0f, + -70.0f, + -65.0f, + -60.0f, + -55.0f, + -50.0f, + -45.0f, + -40.0f, }; #define HOPPING_COUNT 2 @@ -136,6 +167,14 @@ static void subghz_scene_receiver_config_set_hopping_running(VariableItem* item) subghz->txrx->hopper_state = hopping_value[index]; } +static void subghz_scene_receiver_config_set_raw_threshold_rssi(VariableItem* item) { + SubGhz* subghz = variable_item_get_context(item); + uint8_t index = variable_item_get_current_value_index(item); + + variable_item_set_current_value_text(item, raw_theshold_rssi_text[index]); + subghz->txrx->raw_threshold_rssi = raw_theshold_rssi_value[index]; +} + static void subghz_scene_receiver_config_var_list_enter_callback(void* context, uint32_t index) { furi_assert(context); SubGhz* subghz = context; @@ -204,6 +243,19 @@ void subghz_scene_receiver_config_on_enter(void* context) { subghz_scene_receiver_config_var_list_enter_callback, subghz); } + if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) == + SubGhzCustomEventManagerSet) { + item = variable_item_list_add( + subghz->variable_item_list, + "RSSI Threshold:", + RAW_THRESHOLD_RSSI_COUNT, + subghz_scene_receiver_config_set_raw_threshold_rssi, + subghz); + value_index = value_index_float( + subghz->txrx->raw_threshold_rssi, raw_theshold_rssi_value, RAW_THRESHOLD_RSSI_COUNT); + variable_item_set_current_value_index(item, value_index); + variable_item_set_current_value_text(item, raw_theshold_rssi_text[value_index]); + } view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdVariableItemList); } diff --git a/applications/main/subghz/subghz.c b/applications/main/subghz/subghz.c index ba70f36d1..df5a76525 100644 --- a/applications/main/subghz/subghz.c +++ b/applications/main/subghz/subghz.c @@ -178,6 +178,7 @@ SubGhz* subghz_alloc() { subghz->txrx->txrx_state = SubGhzTxRxStateSleep; subghz->txrx->hopper_state = SubGhzHopperStateOFF; subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE; + subghz->txrx->raw_threshold_rssi = SUBGHZ_RAW_TRESHOLD_MIN; subghz->txrx->history = subghz_history_alloc(); subghz->txrx->worker = subghz_worker_alloc(); subghz->txrx->fff_data = flipper_format_string_alloc(); diff --git a/applications/main/subghz/subghz_i.h b/applications/main/subghz/subghz_i.h index 284f7ccf5..09830ba05 100644 --- a/applications/main/subghz/subghz_i.h +++ b/applications/main/subghz/subghz_i.h @@ -54,6 +54,9 @@ struct SubGhzTxRx { uint8_t hopper_timeout; uint8_t hopper_idx_frequency; SubGhzRxKeyState rx_key_state; + + float raw_threshold_rssi; + uint8_t raw_threshold_rssi_low_count; }; typedef struct SubGhzTxRx SubGhzTxRx; diff --git a/applications/main/subghz/views/subghz_read_raw.c b/applications/main/subghz/views/subghz_read_raw.c index 2d951b11a..6120a210b 100644 --- a/applications/main/subghz/views/subghz_read_raw.c +++ b/applications/main/subghz/views/subghz_read_raw.c @@ -23,10 +23,12 @@ typedef struct { FuriString* sample_write; FuriString* file_name; uint8_t* rssi_history; + uint8_t rssi_curret; bool rssi_history_end; uint8_t ind_write; uint8_t ind_sin; SubGhzReadRAWStatus status; + float raw_threshold_rssi; } SubGhzReadRAWModel; void subghz_read_raw_set_callback( @@ -54,21 +56,27 @@ void subghz_read_raw_add_data_statusbar( true); } -void subghz_read_raw_add_data_rssi(SubGhzReadRAW* instance, float rssi) { +void subghz_read_raw_add_data_rssi(SubGhzReadRAW* instance, float rssi, bool trace) { furi_assert(instance); uint8_t u_rssi = 0; - if(rssi < -90) { + if(rssi < SUBGHZ_RAW_TRESHOLD_MIN) { u_rssi = 0; } else { - u_rssi = (uint8_t)((rssi + 90) / 2.7); + u_rssi = (uint8_t)((rssi - SUBGHZ_RAW_TRESHOLD_MIN) / 2.7); } with_view_model( instance->view, SubGhzReadRAWModel * model, { - model->rssi_history[model->ind_write++] = u_rssi; + model->rssi_curret = u_rssi; + if(trace) { + model->rssi_history[model->ind_write++] = u_rssi; + } else { + model->rssi_history[model->ind_write] = u_rssi; + } + if(model->ind_write > SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE) { model->rssi_history_end = true; model->ind_write = 0; @@ -187,24 +195,53 @@ void subghz_read_raw_draw_scale(Canvas* canvas, SubGhzReadRAWModel* model) { void subghz_read_raw_draw_rssi(Canvas* canvas, SubGhzReadRAWModel* model) { int ind = 0; int base = 0; + uint8_t width = 2; if(model->rssi_history_end == false) { for(int i = model->ind_write; i >= 0; i--) { canvas_draw_line(canvas, i, 47, i, 47 - model->rssi_history[i]); } + canvas_draw_line( + canvas, model->ind_write + 1, 47, model->ind_write + 1, 47 - model->rssi_curret); if(model->ind_write > 3) { - canvas_draw_line(canvas, model->ind_write, 47, model->ind_write, 13); + canvas_draw_line( + canvas, model->ind_write - 1, 47, model->ind_write - 1, 47 - model->rssi_curret); + + for(uint8_t i = 13; i < 47; i += width * 2) { + canvas_draw_line(canvas, model->ind_write, i, model->ind_write, i + width); + } canvas_draw_line(canvas, model->ind_write - 2, 12, model->ind_write + 2, 12); canvas_draw_line(canvas, model->ind_write - 1, 13, model->ind_write + 1, 13); } } else { + int i = 0; base = SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE - model->ind_write; - for(int i = SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE; i >= 0; i--) { + for(i = SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE; i > 0; i--) { ind = i - base; if(ind < 0) ind += SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE; canvas_draw_line(canvas, i, 47, i, 47 - model->rssi_history[ind]); } + canvas_draw_line( - canvas, SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE, 47, SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE, 13); + canvas, + SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE - 1, + 47, + SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE - 1, + 47 - model->rssi_curret); + canvas_draw_line( + canvas, + SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE + 1, + 47, + SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE + 1, + 47 - model->rssi_curret); + + for(uint8_t i = 13; i < 47; i += width * 2) { + canvas_draw_line( + canvas, + SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE, + i, + SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE, + i + width); + } canvas_draw_line( canvas, SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE - 2, @@ -220,6 +257,24 @@ void subghz_read_raw_draw_rssi(Canvas* canvas, SubGhzReadRAWModel* model) { } } +void subghz_read_raw_draw_threshold_rssi(Canvas* canvas, SubGhzReadRAWModel* model) { + uint8_t x = 118; + uint8_t y = 48; + + if(model->raw_threshold_rssi > SUBGHZ_RAW_TRESHOLD_MIN) { + uint8_t x = 118; + y -= (uint8_t)((model->raw_threshold_rssi - SUBGHZ_RAW_TRESHOLD_MIN) / 2.7); + + uint8_t width = 3; + for(uint8_t i = 0; i < x; i += width * 2) { + canvas_draw_line(canvas, i, y, i + width, y); + } + } + canvas_draw_line(canvas, x, y - 2, x, y + 2); + canvas_draw_line(canvas, x - 1, y - 1, x - 1, y + 1); + canvas_draw_dot(canvas, x - 2, y); +} + void subghz_read_raw_draw(Canvas* canvas, SubGhzReadRAWModel* model) { uint8_t graphics_mode = 1; canvas_set_color(canvas, ColorBlack); @@ -278,8 +333,9 @@ void subghz_read_raw_draw(Canvas* canvas, SubGhzReadRAWModel* model) { } else { subghz_read_raw_draw_rssi(canvas, model); subghz_read_raw_draw_scale(canvas, model); + subghz_read_raw_draw_threshold_rssi(canvas, model); canvas_set_font_direction(canvas, CanvasDirectionBottomToTop); - canvas_draw_str(canvas, 126, 40, "RSSI"); + canvas_draw_str(canvas, 128, 40, "RSSI"); canvas_set_font_direction(canvas, CanvasDirectionLeftToRight); } } @@ -433,7 +489,8 @@ bool subghz_read_raw_input(InputEvent* event, void* context) { void subghz_read_raw_set_status( SubGhzReadRAW* instance, SubGhzReadRAWStatus status, - const char* file_name) { + const char* file_name, + float raw_threshold_rssi) { furi_assert(instance); switch(status) { @@ -447,6 +504,7 @@ void subghz_read_raw_set_status( model->ind_write = 0; furi_string_reset(model->file_name); furi_string_set(model->sample_write, "0 spl."); + model->raw_threshold_rssi = raw_threshold_rssi; }, true); break; @@ -536,6 +594,7 @@ SubGhzReadRAW* subghz_read_raw_alloc() { model->sample_write = furi_string_alloc(); model->file_name = furi_string_alloc(); model->rssi_history = malloc(SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE * sizeof(uint8_t)); + model->raw_threshold_rssi = -127.0f; }, true); diff --git a/applications/main/subghz/views/subghz_read_raw.h b/applications/main/subghz/views/subghz_read_raw.h index 1d4bb7dc0..bc8711923 100644 --- a/applications/main/subghz/views/subghz_read_raw.h +++ b/applications/main/subghz/views/subghz_read_raw.h @@ -3,6 +3,8 @@ #include #include "../helpers/subghz_custom_event.h" +#define SUBGHZ_RAW_TRESHOLD_MIN -90.0f + typedef struct SubGhzReadRAW SubGhzReadRAW; typedef void (*SubGhzReadRAWCallback)(SubGhzCustomEvent event, void* context); @@ -40,11 +42,12 @@ void subghz_read_raw_stop_send(SubGhzReadRAW* instance); void subghz_read_raw_update_sin(SubGhzReadRAW* instance); -void subghz_read_raw_add_data_rssi(SubGhzReadRAW* instance, float rssi); +void subghz_read_raw_add_data_rssi(SubGhzReadRAW* instance, float rssi, bool trace); void subghz_read_raw_set_status( SubGhzReadRAW* instance, SubGhzReadRAWStatus status, - const char* file_name); + const char* file_name, + float raw_threshold_rssi); View* subghz_read_raw_get_view(SubGhzReadRAW* subghz_static); diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index 17a8a675a..8bad0b830 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -2310,6 +2310,7 @@ Function,+,subghz_protocol_raw_file_encoder_worker_set_callback_end,void,"SubGhz Function,+,subghz_protocol_raw_gen_fff_data,void,"FlipperFormat*, const char*" Function,+,subghz_protocol_raw_get_sample_write,size_t,SubGhzProtocolDecoderRAW* Function,+,subghz_protocol_raw_save_to_file_init,_Bool,"SubGhzProtocolDecoderRAW*, const char*, SubGhzRadioPreset*" +Function,+,subghz_protocol_raw_save_to_file_pause,void,"SubGhzProtocolDecoderRAW*, _Bool" Function,+,subghz_protocol_raw_save_to_file_stop,void,SubGhzProtocolDecoderRAW* Function,+,subghz_receiver_alloc_init,SubGhzReceiver*,SubGhzEnvironment* Function,+,subghz_receiver_decode,void,"SubGhzReceiver*, _Bool, uint32_t" diff --git a/lib/subghz/protocols/raw.c b/lib/subghz/protocols/raw.c index b8e93c3d5..b639c93b9 100644 --- a/lib/subghz/protocols/raw.c +++ b/lib/subghz/protocols/raw.c @@ -32,6 +32,7 @@ struct SubGhzProtocolDecoderRAW { FuriString* file_name; size_t sample_write; bool last_level; + bool pause; }; struct SubGhzProtocolEncoderRAW { @@ -158,6 +159,7 @@ bool subghz_protocol_raw_save_to_file_init( instance->upload_raw = malloc(SUBGHZ_DOWNLOAD_MAX_SIZE * sizeof(int32_t)); instance->file_is_open = RAWFileIsOpenWrite; instance->sample_write = 0; + instance->pause = false; init = true; } while(0); @@ -199,6 +201,14 @@ void subghz_protocol_raw_save_to_file_stop(SubGhzProtocolDecoderRAW* instance) { instance->file_is_open = RAWFileIsOpenClose; } +void subghz_protocol_raw_save_to_file_pause(SubGhzProtocolDecoderRAW* instance, bool pause) { + furi_assert(instance); + + if(instance->pause != pause) { + instance->pause = pause; + } +} + size_t subghz_protocol_raw_get_sample_write(SubGhzProtocolDecoderRAW* instance) { return instance->sample_write + instance->ind_write; } @@ -234,7 +244,7 @@ void subghz_protocol_decoder_raw_feed(void* context, bool level, uint32_t durati furi_assert(context); SubGhzProtocolDecoderRAW* instance = context; - if(instance->upload_raw != NULL) { + if(!instance->pause && (instance->upload_raw != NULL)) { if(duration > subghz_protocol_raw_const.te_short) { if(instance->last_level != level) { instance->last_level = (level ? true : false); diff --git a/lib/subghz/protocols/raw.h b/lib/subghz/protocols/raw.h index 96c77553a..44c7faec5 100644 --- a/lib/subghz/protocols/raw.h +++ b/lib/subghz/protocols/raw.h @@ -103,6 +103,13 @@ void subghz_protocol_encoder_raw_free(void* context); */ void subghz_protocol_encoder_raw_stop(void* context); +/** + * pause writing to flash. + * @param context Pointer to a SubGhzProtocolEncoderRAW instance + * @param pause pause writing + */ +void subghz_protocol_raw_save_to_file_pause(SubGhzProtocolDecoderRAW* instance, bool pause); + /** * Set callback on completion of file transfer. * @param instance Pointer to a SubGhzProtocolEncoderRAW instance From a8edb41eae75c7796e4f16f31b0fa8c5d6440e01 Mon Sep 17 00:00:00 2001 From: hedger Date: Wed, 26 Oct 2022 19:18:06 +0400 Subject: [PATCH 4/4] fbt, docs: typo fixes; vscode: fixed deprecated target names (#1926) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: あく --- .vscode/example/tasks.json | 4 ++-- documentation/fbt.md | 2 +- firmware.scons | 3 ++- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.vscode/example/tasks.json b/.vscode/example/tasks.json index 3946d05cc..9baaf97b4 100644 --- a/.vscode/example/tasks.json +++ b/.vscode/example/tasks.json @@ -109,13 +109,13 @@ "label": "[Debug] Build FAPs", "group": "build", "type": "shell", - "command": "./fbt plugin_dist" + "command": "./fbt fap_dist" }, { "label": "[Release] Build FAPs", "group": "build", "type": "shell", - "command": "./fbt COMPACT=1 DEBUG=0 plugin_dist" + "command": "./fbt COMPACT=1 DEBUG=0 fap_dist" }, { "label": "[Debug] Launch App on Flipper", diff --git a/documentation/fbt.md b/documentation/fbt.md index 659170519..2bf9ea28e 100644 --- a/documentation/fbt.md +++ b/documentation/fbt.md @@ -54,7 +54,7 @@ To run cleanup (think of `make clean`) for specified targets, add `-c` option. - `blackmagic` - debug firmware with Blackmagic probe (WiFi dev board) - `openocd` - just start OpenOCD - `get_blackmagic` - output blackmagic address in gdb remote format. Useful for IDE integration -- `get_stlink` - output serial numbers for attached STLink probes. Ued for `OPENOCD_ADAPTER_SERIAL=...`. +- `get_stlink` - output serial numbers for attached STLink probes. Used for specifying an adapter with `OPENOCD_ADAPTER_SERIAL=...`. - `lint`, `format` - run clang-format on C source code to check and reformat it according to `.clang-format` specs - `lint_py`, `format_py` - run [black](https://black.readthedocs.io/en/stable/index.html) on Python source code, build system files & application manifests - `cli` - start Flipper CLI session over USB diff --git a/firmware.scons b/firmware.scons index d0b89a763..d501996b3 100644 --- a/firmware.scons +++ b/firmware.scons @@ -292,9 +292,10 @@ Alias(fwenv["FIRMWARE_BUILD_CFG"] + "_all", fw_artifacts) if fwenv["IS_BASE_FIRMWARE"]: sdk_source = fwenv.SDKPrebuilder( "sdk_origin", + # Deps on root SDK headers and generated files (fwenv["SDK_HEADERS"], fwenv["FW_ASSETS_HEADERS"]), ) - # Extra deps for root headers and generated files + # Extra deps on headers included in deeper levels Depends(sdk_source, fwenv.ProcessSdkDepends("sdk_origin.d")) fwenv["SDK_DIR"] = fwenv.Dir("sdk")