Skorp subghz capture refactoring (#569)

* SubGhz: changing the operation of the capture timer, and the logic of the work of parsers
* Add toolbox lib. Move levels to toolbox. Subghz switch to levels.
* Subghz: update worker signatures
* SubGhz: pluggable level duration implementations.
* SubGhz : test drawing pictures in Gui
* SubGhz: Added a callback with the parser structure as argument
* SubGhz: copy protocol data to model
* SubGhz: refactoing code
* SubGhz: cleanup and format sources
* SubGhz: remove comments

Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
Co-authored-by: DrZlo13 <who.just.the.doctor@gmail.com>
This commit is contained in:
Skorpionm 2021-07-07 23:49:45 +04:00 committed by GitHub
parent a7283280ef
commit 4ce41a3e6f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 328 additions and 150 deletions

View File

@ -216,19 +216,16 @@ void subghz_cli_command_tx(Cli* cli, string_t args, void* context) {
volatile bool subghz_cli_overrun = false;
void subghz_cli_command_rx_callback(
ApiHalSubGhzCaptureLevel level,
uint32_t duration,
void* context) {
void subghz_cli_command_rx_callback(bool level, uint32_t duration, void* context) {
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
LevelPair pair = {.level = level, .duration = duration};
LevelDuration level_duration = level_duration_make(level, duration);
if(subghz_cli_overrun) {
subghz_cli_overrun = false;
pair.level = ApiHalSubGhzCaptureLevelOverrun;
level_duration = level_duration_reset();
}
size_t ret =
xStreamBufferSendFromISR(context, &pair, sizeof(LevelPair), &xHigherPriorityTaskWoken);
if(sizeof(LevelPair) != ret) subghz_cli_overrun = true;
size_t ret = xStreamBufferSendFromISR(
context, &level_duration, sizeof(LevelDuration), &xHigherPriorityTaskWoken);
if(sizeof(LevelDuration) != ret) subghz_cli_overrun = true;
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
@ -257,13 +254,13 @@ void subghz_cli_command_rx(Cli* cli, string_t args, void* context) {
SubGhzProtocol* protocol = subghz_protocol_alloc();
subghz_protocol_load_keeloq_file(protocol, "/assets/subghz/keeloq_mfcodes");
subghz_protocol_load_nice_flor_s_file(protocol, "/assets/subghz/nice_floor_s_rx");
subghz_protocol_enable_dump(protocol, NULL, NULL);
subghz_protocol_enable_dump_text(protocol, NULL, NULL);
frequency = api_hal_subghz_set_frequency_and_path(frequency);
hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow);
StreamBufferHandle_t rx_stream =
xStreamBufferCreate(sizeof(LevelPair) * 1024, sizeof(LevelPair));
xStreamBufferCreate(sizeof(LevelDuration) * 1024, sizeof(LevelDuration));
api_hal_subghz_set_capture_callback(subghz_cli_command_rx_callback, rx_stream);
api_hal_subghz_enable_capture();
@ -272,15 +269,17 @@ void subghz_cli_command_rx(Cli* cli, string_t args, void* context) {
api_hal_subghz_rx();
printf("Listening at %lu. Press CTRL+C to stop\r\n", frequency);
LevelPair pair;
LevelDuration level_duration;
while(!cli_cmd_interrupt_received(cli)) {
int ret = xStreamBufferReceive(rx_stream, &pair, sizeof(LevelPair), 10);
if(ret == sizeof(LevelPair)) {
if(pair.level == ApiHalSubGhzCaptureLevelOverrun) {
int ret = xStreamBufferReceive(rx_stream, &level_duration, sizeof(LevelDuration), 10);
if(ret == sizeof(LevelDuration)) {
if(level_duration_is_reset(level_duration)) {
printf(".");
subghz_protocol_reset(protocol);
} else {
subghz_protocol_parse(protocol, pair);
bool level = level_duration_get_level(level_duration);
uint32_t duration = level_duration_get_duration(level_duration);
subghz_protocol_parse(protocol, level, duration);
}
}
}

View File

@ -11,6 +11,8 @@
#include <fl_subghz/subghz_worker.h>
#include <fl_subghz/protocols/subghz_protocol.h>
#include <assets_icons.h>
struct SubghzCapture {
View* view;
SubGhzWorker* worker;
@ -22,6 +24,8 @@ typedef struct {
uint32_t real_frequency;
uint32_t counter;
string_t text;
uint16_t scene;
SubGhzProtocolCommon parser;
} SubghzCaptureModel;
static const char subghz_symbols[] = {'-', '\\', '|', '/'};
@ -41,8 +45,22 @@ void subghz_capture_draw(Canvas* canvas, SubghzCaptureModel* model) {
subghz_symbols[model->counter % 4]);
canvas_draw_str(canvas, 0, 8, buffer);
switch(model->scene) {
case 1:
canvas_draw_icon(canvas, 0, 10, &I_RFIDDolphinReceive_97x61);
canvas_invert_color(canvas);
canvas_draw_box(canvas, 80, 12, 20, 20);
canvas_invert_color(canvas);
canvas_draw_icon(canvas, 75, 18, &I_sub1_10px);
elements_multiline_text_aligned(
canvas, 90, 38, AlignCenter, AlignTop, "Detecting\r\nSubGhz");
break;
default:
canvas_set_font(canvas, FontSecondary);
elements_multiline_text(canvas, 0, 20, string_get_cstr(model->text));
break;
}
}
bool subghz_capture_input(InputEvent* event, void* context) {
@ -87,6 +105,34 @@ void subghz_capture_text_callback(string_t text, void* context) {
subghz_capture->view, (SubghzCaptureModel * model) {
model->counter++;
string_set(model->text, text);
model->scene = 0;
return true;
});
}
void subghz_capture_protocol_callback(SubGhzProtocolCommon* parser, void* context) {
furi_assert(context);
SubghzCapture* subghz_capture = context;
char buffer[64];
snprintf(
buffer,
sizeof(buffer),
"%s\r\n"
"K:%lX%lX\r\n"
"SN:%lX\r\n"
"BTN:%X",
parser->name,
(uint32_t)(parser->code_found >> 32),
(uint32_t)(parser->code_found & 0x00000000FFFFFFFF),
parser->serial,
parser->btn);
with_view_model(
subghz_capture->view, (SubghzCaptureModel * model) {
model->counter++;
model->parser = *parser;
string_set(model->text, buffer);
model->scene = 0;
return true;
});
}
@ -104,6 +150,7 @@ void subghz_capture_enter(void* context) {
model->frequency = subghz_frequencies_433_92;
model->real_frequency =
api_hal_subghz_set_frequency_and_path(subghz_frequencies[model->frequency]);
model->scene = 1;
return true;
});
@ -163,7 +210,7 @@ SubghzCapture* subghz_capture_alloc() {
subghz_protocol_load_keeloq_file(subghz_capture->protocol, "/assets/subghz/keeloq_mfcodes");
subghz_protocol_load_nice_flor_s_file(
subghz_capture->protocol, "/assets/subghz/nice_floor_s_rx");
subghz_protocol_enable_dump(
subghz_protocol_enable_dump_text(
subghz_capture->protocol, subghz_capture_text_callback, subghz_capture);
return subghz_capture;

View File

@ -2,6 +2,7 @@
#include <stdbool.h>
#include <stdint.h>
#include <toolbox/level_duration.h>
#ifdef __cplusplus
extern "C" {
@ -107,21 +108,8 @@ uint32_t api_hal_subghz_set_frequency(uint32_t value);
*/
void api_hal_subghz_set_path(ApiHalSubGhzPath path);
/** Front Definition for capture callback */
typedef enum {
ApiHalSubGhzCaptureLevelHigh,
ApiHalSubGhzCaptureLevelLow,
ApiHalSubGhzCaptureLevelOverrun,
ApiHalSubGhzCaptureLevelUnderrun,
} ApiHalSubGhzCaptureLevel;
typedef struct {
ApiHalSubGhzCaptureLevel level;
uint32_t duration;
} LevelPair;
/** Signal Timings Capture callback */
typedef void (*ApiHalSubGhzCaptureCallback)(ApiHalSubGhzCaptureLevel level, uint32_t time, void* context);
typedef void (*ApiHalSubGhzCaptureCallback)(bool level, uint32_t duration, void* context);
/** Set signal timings capture callback
* @param callback - your callback for front capture

View File

@ -292,9 +292,7 @@ static void api_hal_subghz_capture_ISR() {
LL_TIM_ClearFlag_CC1(TIM2);
api_hal_subghz_capture_delta_duration = LL_TIM_IC_GetCaptureCH1(TIM2);
if (api_hal_subghz_capture_callback) {
api_hal_subghz_capture_callback(
ApiHalSubGhzCaptureLevelHigh,
api_hal_subghz_capture_delta_duration,
api_hal_subghz_capture_callback(true, api_hal_subghz_capture_delta_duration,
(void*)api_hal_subghz_capture_callback_context
);
}
@ -303,9 +301,7 @@ static void api_hal_subghz_capture_ISR() {
if(LL_TIM_IsActiveFlag_CC2(TIM2)) {
LL_TIM_ClearFlag_CC2(TIM2);
if (api_hal_subghz_capture_callback) {
api_hal_subghz_capture_callback(
ApiHalSubGhzCaptureLevelLow,
LL_TIM_IC_GetCaptureCH2(TIM2) - api_hal_subghz_capture_delta_duration,
api_hal_subghz_capture_callback(false, LL_TIM_IC_GetCaptureCH2(TIM2) - api_hal_subghz_capture_delta_duration,
(void*)api_hal_subghz_capture_callback_context
);
}
@ -323,7 +319,7 @@ void api_hal_subghz_enable_capture() {
LL_TIM_InitTypeDef TIM_InitStruct = {0};
TIM_InitStruct.Prescaler = 64-1;
TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
TIM_InitStruct.Autoreload = 0xFFFFFFFF;
TIM_InitStruct.Autoreload = 0x7FFFFFFE;
TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
LL_TIM_Init(TIM2, &TIM_InitStruct);

View File

@ -22,9 +22,11 @@ struct SubGhzProtocol {
SubGhzProtocolTextCallback text_callback;
void* text_callback_context;
SubGhzProtocolCommonCallbackDump parser_callback;
void* parser_callback_context;
};
static void subghz_protocol_came_rx_callback(SubGhzProtocolCommon* parser, void* context) {
static void subghz_protocol_text_rx_callback(SubGhzProtocolCommon* parser, void* context) {
SubGhzProtocol* instance = context;
string_t output;
@ -38,6 +40,13 @@ static void subghz_protocol_came_rx_callback(SubGhzProtocolCommon* parser, void*
string_clear(output);
}
static void subghz_protocol_parser_rx_callback(SubGhzProtocolCommon* parser, void* context) {
SubGhzProtocol* instance = context;
if (instance->parser_callback) {
instance->parser_callback(parser, instance->parser_callback_context);
}
}
SubGhzProtocol* subghz_protocol_alloc() {
SubGhzProtocol* instance = furi_alloc(sizeof(SubGhzProtocol));
@ -62,19 +71,31 @@ void subghz_protocol_free(SubGhzProtocol* instance) {
free(instance);
}
void subghz_protocol_enable_dump(SubGhzProtocol* instance, SubGhzProtocolTextCallback callback, void* context) {
void subghz_protocol_enable_dump_text(SubGhzProtocol* instance, SubGhzProtocolTextCallback callback, void* context) {
furi_assert(instance);
subghz_protocol_common_set_callback((SubGhzProtocolCommon*)instance->came, subghz_protocol_came_rx_callback, instance);
subghz_protocol_common_set_callback((SubGhzProtocolCommon*)instance->keeloq, subghz_protocol_came_rx_callback, instance);
subghz_protocol_common_set_callback((SubGhzProtocolCommon*)instance->princeton, subghz_protocol_came_rx_callback, instance);
subghz_protocol_common_set_callback((SubGhzProtocolCommon*)instance->nice_flo, subghz_protocol_came_rx_callback, instance);
subghz_protocol_common_set_callback((SubGhzProtocolCommon*)instance->nice_flor_s, subghz_protocol_came_rx_callback, instance);
subghz_protocol_common_set_callback((SubGhzProtocolCommon*)instance->came, subghz_protocol_text_rx_callback, instance);
subghz_protocol_common_set_callback((SubGhzProtocolCommon*)instance->keeloq, subghz_protocol_text_rx_callback, instance);
subghz_protocol_common_set_callback((SubGhzProtocolCommon*)instance->princeton, subghz_protocol_text_rx_callback, instance);
subghz_protocol_common_set_callback((SubGhzProtocolCommon*)instance->nice_flo, subghz_protocol_text_rx_callback, instance);
subghz_protocol_common_set_callback((SubGhzProtocolCommon*)instance->nice_flor_s, subghz_protocol_text_rx_callback, instance);
instance->text_callback = callback;
instance->text_callback_context = context;
}
void subghz_protocol_enable_dump(SubGhzProtocol* instance, SubGhzProtocolCommonCallbackDump callback, void* context) {
furi_assert(instance);
subghz_protocol_common_set_callback((SubGhzProtocolCommon*)instance->came, subghz_protocol_parser_rx_callback, instance);
subghz_protocol_common_set_callback((SubGhzProtocolCommon*)instance->keeloq, subghz_protocol_parser_rx_callback, instance);
subghz_protocol_common_set_callback((SubGhzProtocolCommon*)instance->princeton, subghz_protocol_parser_rx_callback, instance);
subghz_protocol_common_set_callback((SubGhzProtocolCommon*)instance->nice_flo, subghz_protocol_parser_rx_callback, instance);
subghz_protocol_common_set_callback((SubGhzProtocolCommon*)instance->nice_flor_s, subghz_protocol_parser_rx_callback, instance);
instance->parser_callback = callback;
instance->parser_callback_context = context;
}
static void subghz_protocol_load_keeloq_file_process_line(SubGhzProtocol* instance, string_t line) {
uint64_t key = 0;
uint16_t type = 0;
@ -123,12 +144,17 @@ void subghz_protocol_load_keeloq_file(SubGhzProtocol* instance, const char* file
}
void subghz_protocol_reset(SubGhzProtocol* instance) {
subghz_protocol_came_reset(instance->came);
subghz_protocol_keeloq_reset(instance->keeloq);
subghz_protocol_princeton_reset(instance->princeton);
subghz_protocol_nice_flo_reset(instance->nice_flo);
subghz_protocol_nice_flor_s_reset(instance->nice_flor_s);
}
void subghz_protocol_parse(SubGhzProtocol* instance, LevelPair data) {
subghz_protocol_came_parse(instance->came, data);
subghz_protocol_keeloq_parse(instance->keeloq, data);
subghz_protocol_princeton_parse(instance->princeton, data);
subghz_protocol_nice_flo_parse(instance->nice_flo, data);
subghz_protocol_nice_flor_s_parse(instance->nice_flor_s, data);
void subghz_protocol_parse(SubGhzProtocol* instance, bool level, uint32_t duration) {
subghz_protocol_came_parse(instance->came, level, duration);
subghz_protocol_keeloq_parse(instance->keeloq, level, duration);
subghz_protocol_princeton_parse(instance->princeton, level, duration);
subghz_protocol_nice_flo_parse(instance->nice_flo, level, duration);
subghz_protocol_nice_flor_s_parse(instance->nice_flor_s, level, duration);
}

View File

@ -3,6 +3,7 @@
#include "subghz_protocol_common.h"
typedef void (*SubGhzProtocolTextCallback)(string_t text, void* context);
typedef void (*SubGhzProtocolCommonCallbackDump)(SubGhzProtocolCommon *parser, void* context);
typedef struct SubGhzProtocol SubGhzProtocol;
@ -18,16 +19,21 @@ SubGhzProtocol* subghz_protocol_alloc();
*/
void subghz_protocol_free(SubGhzProtocol* instance);
/** Outputting data from all parsers
/** Outputting data text from all parsers
*
* @param instance - SubGhzProtocol instance
* @param callback - SubGhzProtocolTextCallback callback
* @param context
*/
void subghz_protocol_enable_dump(
SubGhzProtocol* instance,
SubGhzProtocolTextCallback callback,
void* context);
void subghz_protocol_enable_dump_text(SubGhzProtocol* instance,SubGhzProtocolTextCallback callback,void* context);
/** Outputting data SubGhzProtocol from all parsers
*
* @param instance - SubGhzProtocol instance
* @param callback - SubGhzProtocolTextCallback callback
* @param context
*/
void subghz_protocol_enable_dump( SubGhzProtocol* instance, SubGhzProtocolCommonCallbackDump callback, void* context);
/** File name rainbow table Nice Flor-S
*
@ -52,6 +58,7 @@ void subghz_protocol_reset(SubGhzProtocol* instance);
/** Loading data into all parsers
*
* @param instance - SubGhzProtocol instance
* @param data - LevelPair data
* @param level - true is high, false if low
* @param duration - level duration in microseconds
*/
void subghz_protocol_parse(SubGhzProtocol* instance, LevelPair data);
void subghz_protocol_parse(SubGhzProtocol* instance, bool level, uint32_t duration);

View File

@ -63,11 +63,15 @@ void subghz_protocol_came_send_key(SubGhzProtocolCame* instance, uint64_t key, u
}
}
void subghz_protocol_came_parse(SubGhzProtocolCame* instance, LevelPair data) {
void subghz_protocol_came_reset(SubGhzProtocolCame* instance) {
instance->common.parser_step = 0;
}
void subghz_protocol_came_parse(SubGhzProtocolCame* instance, bool level, uint32_t duration) {
switch (instance->common.parser_step) {
case 0:
if ((data.level == ApiHalSubGhzCaptureLevelLow)
&& (DURATION_DIFF(data.duration,instance->common.te_shot * 51)< instance->common.te_delta * 51)) { //Need protocol 36 te_shot
if ((!level)
&& (DURATION_DIFF(duration, instance->common.te_shot * 51)< instance->common.te_delta * 51)) { //Need protocol 36 te_shot
//Found header CAME
instance->common.parser_step = 1;
} else {
@ -75,9 +79,9 @@ void subghz_protocol_came_parse(SubGhzProtocolCame* instance, LevelPair data) {
}
break;
case 1:
if (data.level == ApiHalSubGhzCaptureLevelLow) {
if (!level) {
break;
} else if (DURATION_DIFF(data.duration,instance->common.te_shot)< instance->common.te_delta) {
} else if (DURATION_DIFF(duration, instance->common.te_shot)< instance->common.te_delta) {
//Found start bit CAME
instance->common.parser_step = 2;
instance->common.code_found = 0;
@ -87,33 +91,34 @@ void subghz_protocol_came_parse(SubGhzProtocolCame* instance, LevelPair data) {
}
break;
case 2:
if (data.level == ApiHalSubGhzCaptureLevelLow) { //save interval
if (data.duration >= (instance->common.te_shot * 4)) {
if (!level) { //save interval
if (duration >= (instance->common.te_shot * 4)) {
instance->common.parser_step = 1;
if (instance->common.code_count_bit>= instance->common.code_min_count_bit_for_found) {
//ToDo out data display
instance->common.serial = 0x0;
instance->common.btn = 0x0;
if (instance->common.callback)
instance->common.callback((SubGhzProtocolCommon*)instance, instance->common.context);
}
break;
}
instance->common.te_last = data.duration;
instance->common.te_last = duration;
instance->common.parser_step = 3;
} else {
instance->common.parser_step = 0;
}
break;
case 3:
if (data.level == ApiHalSubGhzCaptureLevelHigh) {
if (level) {
if ((DURATION_DIFF(instance->common.te_last,instance->common.te_shot) < instance->common.te_delta)
&& (DURATION_DIFF(data.duration,instance->common.te_long)< instance->common.te_delta)) {
&& (DURATION_DIFF(duration, instance->common.te_long)< instance->common.te_delta)) {
subghz_protocol_common_add_bit(&instance->common, 0);
instance->common.parser_step = 2;
} else if ((DURATION_DIFF(instance->common.te_last,instance->common.te_long)< instance->common.te_delta)
&& (DURATION_DIFF(data.duration,instance->common.te_shot)< instance->common.te_delta)) {
&& (DURATION_DIFF(duration, instance->common.te_shot)< instance->common.te_delta)) {
subghz_protocol_common_add_bit(&instance->common, 1);
instance->common.parser_step = 2;
} else

View File

@ -25,9 +25,14 @@ void subghz_protocol_came_free(SubGhzProtocolCame* instance);
*/
void subghz_protocol_came_send_key(SubGhzProtocolCame* instance, uint64_t key, uint8_t bit, uint8_t repeat);
/** Reset internal state
* @param instance - SubGhzProtocolCame instance
*/
void subghz_protocol_came_reset(SubGhzProtocolCame* instance);
/** Parse accepted duration
*
* @param instance - SubGhzProtocolCame instance
* @param data - LevelPair data
* @param data - LevelDuration level_duration
*/
void subghz_protocol_came_parse(SubGhzProtocolCame* instance, LevelPair data);
void subghz_protocol_came_parse(SubGhzProtocolCame* instance, bool level, uint32_t duration);;

View File

@ -27,6 +27,7 @@ void subghz_protocol_common_set_callback(SubGhzProtocolCommon* common, SubGhzPro
common->context = context;
}
void subghz_protocol_common_to_str(SubGhzProtocolCommon* instance, string_t output) {
if (instance->to_string) {
instance->to_string(instance, output);

View File

@ -11,7 +11,7 @@
#define SUBGHZ_TX_PIN_HIGTH()
#define SUBGHZ_TX_PIN_LOW()
#define DURATION_DIFF(x,y) ((x < y) ? (y - x) : (x - y))
#define DURATION_DIFF(x, y) ((x < y) ? (y - x) : (x - y))
typedef struct SubGhzProtocolCommon SubGhzProtocolCommon;
@ -29,7 +29,7 @@ struct SubGhzProtocolCommon {
uint8_t code_count_bit;
uint8_t code_min_count_bit_for_found;
uint8_t parser_step;
uint16_t te_last;
uint32_t te_last;
uint8_t header_count;
uint16_t cnt;
uint32_t serial;

View File

@ -271,10 +271,14 @@ void subghz_protocol_keeloq_send_key(SubGhzProtocolKeeloq* instance, uint64_t ke
}
}
void subghz_protocol_keeloq_parse(SubGhzProtocolKeeloq* instance, LevelPair data) {
void subghz_protocol_keeloq_reset(SubGhzProtocolKeeloq* instance) {
instance->common.parser_step = 0;
}
void subghz_protocol_keeloq_parse(SubGhzProtocolKeeloq* instance, bool level, uint32_t duration) {
switch (instance->common.parser_step) {
case 0:
if ((data.level == ApiHalSubGhzCaptureLevelHigh) && DURATION_DIFF(data.duration, instance->common.te_shot)< instance->common.te_delta) {
if ((level) && DURATION_DIFF(duration, instance->common.te_shot)< instance->common.te_delta) {
instance->common.parser_step = 1;
instance->common.header_count++;
} else {
@ -283,11 +287,11 @@ void subghz_protocol_keeloq_parse(SubGhzProtocolKeeloq* instance, LevelPair data
break;
case 1:
if ((data.level == ApiHalSubGhzCaptureLevelLow) && (DURATION_DIFF(data.duration, instance->common.te_shot ) < instance->common.te_delta)) {
if ((!level) && (DURATION_DIFF(duration, instance->common.te_shot ) < instance->common.te_delta)) {
instance->common.parser_step = 0;
break;
}
if ((instance->common.header_count > 2) && ( DURATION_DIFF(data.duration, instance->common.te_shot * 10)< instance->common.te_delta * 10)) {
if ((instance->common.header_count > 2) && ( DURATION_DIFF(duration, instance->common.te_shot * 10)< instance->common.te_delta * 10)) {
// Found header
instance->common.parser_step = 2;
instance->common.code_found = 0;
@ -298,21 +302,19 @@ void subghz_protocol_keeloq_parse(SubGhzProtocolKeeloq* instance, LevelPair data
}
break;
case 2:
if (data.level == ApiHalSubGhzCaptureLevelHigh) {
instance->common.te_last = data.duration;
if (level) {
instance->common.te_last = duration;
instance->common.parser_step = 3;
}
break;
case 3:
if (data.level == ApiHalSubGhzCaptureLevelLow) {
if (data.duration >= (instance->common.te_shot * 2 + instance->common.te_delta)) {
if (!level) {
if (duration >= (instance->common.te_shot * 2 + instance->common.te_delta)) {
// Found end TX
instance->common.parser_step = 0;
if (instance->common.code_count_bit >= instance->common.code_min_count_bit_for_found) {
//&& (instance->common.code_last_found != instance->common.code_found )) {
instance->common.code_last_found = instance->common.code_found;
//ToDo out data display
subghz_protocol_keeloq_check_remote_controller(instance);
instance->common.code_found = 0;
@ -321,13 +323,13 @@ void subghz_protocol_keeloq_parse(SubGhzProtocolKeeloq* instance, LevelPair data
}
break;
} else if ((DURATION_DIFF(instance->common.te_last, instance->common.te_shot) < instance->common.te_delta)
&& (DURATION_DIFF(data.duration, instance->common.te_long) < instance->common.te_delta)) {
&& (DURATION_DIFF(duration, instance->common.te_long) < instance->common.te_delta)) {
if (instance->common.code_count_bit < instance->common.code_min_count_bit_for_found) {
subghz_protocol_common_add_bit(&instance->common, 1);
}
instance->common.parser_step = 2;
} else if ((DURATION_DIFF(instance->common.te_last, instance->common.te_long) < instance->common.te_delta)
&& (DURATION_DIFF(data.duration, instance->common.te_shot) < instance->common.te_delta)) {
&& (DURATION_DIFF(duration, instance->common.te_shot) < instance->common.te_delta)) {
if (instance->common.code_count_bit < instance->common.code_min_count_bit_for_found) {
subghz_protocol_common_add_bit(&instance->common, 0);
}

View File

@ -34,12 +34,17 @@ void subghz_protocol_keeloq_add_manafacture_key(SubGhzProtocolKeeloq* instance,
*/
void subghz_protocol_keeloq_send_key(SubGhzProtocolKeeloq* instance, uint64_t key, uint8_t bit, uint8_t repeat);
/** Reset internal state
* @param instance - SubGhzProtocolKeeloq instance
*/
void subghz_protocol_keeloq_reset(SubGhzProtocolKeeloq* instance);
/** Parse accepted duration
*
* @param instance - SubGhzProtocolKeeloq instance
* @param data - LevelPair data
* @param data - LevelDuration level_duration
*/
void subghz_protocol_keeloq_parse(SubGhzProtocolKeeloq* instance, LevelPair data);
void subghz_protocol_keeloq_parse(SubGhzProtocolKeeloq* instance, bool level, uint32_t duration);;
/** Outputting information from the parser
*

View File

@ -62,11 +62,15 @@ void subghz_protocol_nice_flo_send_key(SubGhzProtocolNiceFlo* instance, uint64_t
}
}
void subghz_protocol_nice_flo_parse(SubGhzProtocolNiceFlo* instance, LevelPair data) {
void subghz_protocol_nice_flo_reset(SubGhzProtocolNiceFlo* instance) {
instance->common.parser_step = 0;
}
void subghz_protocol_nice_flo_parse(SubGhzProtocolNiceFlo* instance, bool level, uint32_t duration) {
switch (instance->common.parser_step) {
case 0:
if ((data.level == ApiHalSubGhzCaptureLevelLow)
&& (DURATION_DIFF(data.duration,instance->common.te_shot * 36)< instance->common.te_delta * 36)) {
if ((!level)
&& (DURATION_DIFF(duration, instance->common.te_shot * 36)< instance->common.te_delta * 36)) {
//Found header Nice Flo
instance->common.parser_step = 1;
} else {
@ -74,9 +78,9 @@ void subghz_protocol_nice_flo_parse(SubGhzProtocolNiceFlo* instance, LevelPair d
}
break;
case 1:
if (data.level == ApiHalSubGhzCaptureLevelLow) {
if (!level) {
break;
} else if (DURATION_DIFF(data.duration,instance->common.te_shot)< instance->common.te_delta) {
} else if (DURATION_DIFF(duration, instance->common.te_shot)< instance->common.te_delta) {
//Found start bit Nice Flo
instance->common.parser_step = 2;
instance->common.code_found = 0;
@ -86,31 +90,30 @@ void subghz_protocol_nice_flo_parse(SubGhzProtocolNiceFlo* instance, LevelPair d
}
break;
case 2:
if (data.level == ApiHalSubGhzCaptureLevelLow) { //save interval
if (data.duration >= (instance->common.te_shot * 4)) {
if (!level) { //save interval
if (duration >= (instance->common.te_shot * 4)) {
instance->common.parser_step = 1;
if (instance->common.code_count_bit>= instance->common.code_min_count_bit_for_found) {
//ToDo out data display
//instance->common.serial = 0x12345;
if (instance->common.callback) instance->common.callback((SubGhzProtocolCommon*)instance, instance->common.context);
}
break;
}
instance->common.te_last = data.duration;
instance->common.te_last = duration;
instance->common.parser_step = 3;
} else {
instance->common.parser_step = 0;
}
break;
case 3:
if (data.level == ApiHalSubGhzCaptureLevelHigh) {
if (level) {
if ((DURATION_DIFF(instance->common.te_last,instance->common.te_shot) < instance->common.te_delta)
&& (DURATION_DIFF(data.duration,instance->common.te_long)< instance->common.te_delta)) {
&& (DURATION_DIFF(duration, instance->common.te_long)< instance->common.te_delta)) {
subghz_protocol_common_add_bit(&instance->common, 0);
instance->common.parser_step = 2;
} else if ((DURATION_DIFF(instance->common.te_last,instance->common.te_long)< instance->common.te_delta)
&& (DURATION_DIFF(data.duration,instance->common.te_shot)< instance->common.te_delta)) {
&& (DURATION_DIFF(duration, instance->common.te_shot)< instance->common.te_delta)) {
subghz_protocol_common_add_bit(&instance->common, 1);
instance->common.parser_step = 2;
} else

View File

@ -25,9 +25,14 @@ void subghz_protocol_nice_flo_free(SubGhzProtocolNiceFlo* instance);
*/
void subghz_protocol_nice_flo_send_key(SubGhzProtocolNiceFlo* instance, uint64_t key, uint8_t bit, uint8_t repeat);
/** Reset internal state
* @param instance - SubGhzProtocolNiceFlo instance
*/
void subghz_protocol_nice_flo_reset(SubGhzProtocolNiceFlo* instance);
/** Parse accepted duration
*
* @param instance - SubGhzProtocolNiceFlo instance
* @param data - LevelPair data
* @param data - LevelDuration level_duration
*/
void subghz_protocol_nice_flo_parse(SubGhzProtocolNiceFlo* instance, LevelPair data);
void subghz_protocol_nice_flo_parse(SubGhzProtocolNiceFlo* instance, bool level, uint32_t duration);;

View File

@ -144,11 +144,15 @@ void subghz_nice_flor_s_decoder_decrypt(SubGhzProtocolNiceFlorS* instance) {
if(instance->common.callback) instance->common.callback((SubGhzProtocolCommon*)instance, instance->common.context);
}
void subghz_protocol_nice_flor_s_parse(SubGhzProtocolNiceFlorS* instance, LevelPair data) {
void subghz_protocol_nice_flor_s_reset(SubGhzProtocolNiceFlorS* instance) {
instance->common.parser_step = 0;
}
void subghz_protocol_nice_flor_s_parse(SubGhzProtocolNiceFlorS* instance, bool level, uint32_t duration) {
switch(instance->common.parser_step) {
case 0:
if((data.level == ApiHalSubGhzCaptureLevelLow)
&& (DURATION_DIFF(data.duration, instance->common.te_shot * 38) < instance->common.te_delta * 38)) {
if((!level)
&& (DURATION_DIFF(duration, instance->common.te_shot * 38) < instance->common.te_delta * 38)) {
//Found start header Nice Flor-S
instance->common.parser_step = 1;
} else {
@ -156,8 +160,8 @@ void subghz_protocol_nice_flor_s_parse(SubGhzProtocolNiceFlorS* instance, LevelP
}
break;
case 1:
if((data.level == ApiHalSubGhzCaptureLevelHigh)
&& (DURATION_DIFF(data.duration, instance->common.te_shot * 3) < instance->common.te_delta * 3)) {
if((level)
&& (DURATION_DIFF(duration, instance->common.te_shot * 3) < instance->common.te_delta * 3)) {
//Found next header Nice Flor-S
instance->common.parser_step = 2;
} else {
@ -165,8 +169,8 @@ void subghz_protocol_nice_flor_s_parse(SubGhzProtocolNiceFlorS* instance, LevelP
}
break;
case 2:
if((data.level == ApiHalSubGhzCaptureLevelLow)
&& (DURATION_DIFF(data.duration, instance->common.te_shot * 3) < instance->common.te_delta * 3)) {
if((!level)
&& (DURATION_DIFF(duration, instance->common.te_shot * 3) < instance->common.te_delta * 3)) {
//Found header Nice Flor-S
instance->common.parser_step = 3;
instance->common.code_found = 0;
@ -176,31 +180,32 @@ void subghz_protocol_nice_flor_s_parse(SubGhzProtocolNiceFlorS* instance, LevelP
}
break;
case 3:
if(data.level == ApiHalSubGhzCaptureLevelHigh) {
if(DURATION_DIFF(data.duration, instance->common.te_shot * 3) < instance->common.te_delta) {
if(level) {
if(DURATION_DIFF(duration, instance->common.te_shot * 3) < instance->common.te_delta) {
//Found STOP bit
instance->common.parser_step = 0;
if(instance->common.code_count_bit >=instance->common.code_min_count_bit_for_found) {
//ToDo out data display
subghz_nice_flor_s_decoder_decrypt(instance);
}
break;
} else {
//save interval
instance->common.te_last = data.duration;
instance->common.te_last = duration;
instance->common.parser_step = 4;
}
}
break;
case 4:
if(data.level == ApiHalSubGhzCaptureLevelLow) {
if(!level) {
if((DURATION_DIFF(instance->common.te_last, instance->common.te_shot) < instance->common.te_delta)
&&(DURATION_DIFF(data.duration, instance->common.te_long) < instance->common.te_delta)) {
&&(DURATION_DIFF(duration, instance->common.te_long) < instance->common.te_delta)) {
subghz_protocol_common_add_bit(&instance->common, 0);
instance->common.parser_step = 3;
} else if(
(DURATION_DIFF(instance->common.te_last, instance->common.te_long) < instance->common.te_delta)
&&(DURATION_DIFF(data.duration, instance->common.te_shot) < instance->common.te_delta)) {
&&(DURATION_DIFF(duration, instance->common.te_shot) < instance->common.te_delta)) {
subghz_protocol_common_add_bit(&instance->common, 1);
instance->common.parser_step = 3;
} else

View File

@ -32,12 +32,17 @@ void subghz_protocol_nice_flor_s_name_file(SubGhzProtocolNiceFlorS* instance, co
*/
void subghz_protocol_nice_flor_s_send_key(SubGhzProtocolNiceFlorS* instance, uint64_t key, uint8_t bit, uint8_t repeat);
/** Reset internal state
* @param instance - SubGhzProtocolNiceFlorS instance
*/
void subghz_protocol_nice_flor_s_reset(SubGhzProtocolNiceFlorS* instance);
/** Parse accepted duration
*
* @param instance - SubGhzProtocolNiceFlorS instance
* @param data - LevelPair data
* @param data - LevelDuration level_duration
*/
void subghz_protocol_nice_flor_s_parse(SubGhzProtocolNiceFlorS* instance, LevelPair data);
void subghz_protocol_nice_flor_s_parse(SubGhzProtocolNiceFlorS* instance, bool level, uint32_t duration);;
/** Outputting information from the parser
*

View File

@ -62,11 +62,15 @@ void subghz_protocol_princeton_send_key(SubGhzProtocolPrinceton* instance, uint6
}
}
void subghz_protocol_princeton_parse(SubGhzProtocolPrinceton* instance, LevelPair data) {
void subghz_protocol_princeton_reset(SubGhzProtocolPrinceton* instance) {
instance->common.parser_step = 0;
}
void subghz_protocol_princeton_parse(SubGhzProtocolPrinceton* instance, bool level, uint32_t duration) {
switch (instance->common.parser_step) {
case 0:
if ((data.level == ApiHalSubGhzCaptureLevelLow)
&& (DURATION_DIFF(data.duration,instance->common.te_shot * 36)< instance->common.te_delta * 36)) {
if ((!level)
&& (DURATION_DIFF(duration,instance->common.te_shot * 36)< instance->common.te_delta * 36)) {
//Found Preambula
instance->common.parser_step = 1;
instance->common.code_found = 0;
@ -77,20 +81,21 @@ void subghz_protocol_princeton_parse(SubGhzProtocolPrinceton* instance, LevelPai
break;
case 1:
//save duration
if (data.level == ApiHalSubGhzCaptureLevelHigh) {
instance->common.te_last = data.duration;
if (level) {
instance->common.te_last = duration;
instance->common.parser_step = 2;
}
break;
case 2:
if (data.level == ApiHalSubGhzCaptureLevelLow) {
if (data.duration>= (instance->common.te_shot * 10+ instance->common.te_delta)) {
if (!level) {
if (duration >= (instance->common.te_shot * 10 + instance->common.te_delta)) {
instance->common.parser_step = 1;
if (instance->common.code_count_bit>= instance->common.code_min_count_bit_for_found) {
//ToDo out data display
instance->common.serial = instance->common.code_found >> 4;
instance->common.btn = (uint8_t)instance->common.code_found & 0x00000F;
if (instance->common.callback) instance->common.callback((SubGhzProtocolCommon*)instance, instance->common.context);
}
instance->common.code_found = 0;
instance->common.code_count_bit = 0;
@ -98,11 +103,11 @@ void subghz_protocol_princeton_parse(SubGhzProtocolPrinceton* instance, LevelPai
}
if ((DURATION_DIFF(instance->common.te_last,instance->common.te_shot)< instance->common.te_delta)
&& (DURATION_DIFF(data.duration,instance->common.te_long)< instance->common.te_delta*3)) {
&& (DURATION_DIFF(duration,instance->common.te_long)< instance->common.te_delta*3)) {
subghz_protocol_common_add_bit(&instance->common, 0);
instance->common.parser_step = 1;
} else if ((DURATION_DIFF(instance->common.te_last,instance->common.te_long)< instance->common.te_delta*3)
&& (DURATION_DIFF(data.duration,instance->common.te_shot)< instance->common.te_delta)) {
&& (DURATION_DIFF(duration,instance->common.te_shot)< instance->common.te_delta)) {
subghz_protocol_common_add_bit(&instance->common, 1);
instance->common.parser_step = 1;
} else {

View File

@ -25,12 +25,17 @@ void subghz_protocol_princeton_free(SubGhzProtocolPrinceton* instance);
*/
void subghz_protocol_princeton_send_key(SubGhzProtocolPrinceton* instance, uint64_t key, uint8_t bit, uint8_t repeat);
/** Reset internal state
* @param instance - SubGhzProtocolPrinceton instance
*/
void subghz_protocol_princeton_reset(SubGhzProtocolPrinceton* instance);
/** Parse accepted duration
*
* @param instance - SubGhzProtocolPrinceton instance
* @param data - LevelPair data
* @param data - LevelDuration level_duration
*/
void subghz_protocol_princeton_parse(SubGhzProtocolPrinceton* instance, LevelPair data);
void subghz_protocol_princeton_parse(SubGhzProtocolPrinceton* instance, bool level, uint32_t duration);;
/** Outputting information from the parser
*

View File

@ -21,22 +21,18 @@ struct SubGhzWorker {
* @param duration received signal duration
* @param context
*/
void subghz_worker_rx_callback(
ApiHalSubGhzCaptureLevel level,
uint32_t duration,
void* context) {
void subghz_worker_rx_callback(bool level, uint32_t duration, void* context) {
SubGhzWorker* instance = context;
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
LevelPair pair = {.level = level, .duration = duration};
LevelDuration level_duration = level_duration_make(level, duration);
if(instance->overrun) {
instance->overrun = false;
pair.level = ApiHalSubGhzCaptureLevelOverrun;
level_duration = level_duration_reset();
}
size_t ret =
xStreamBufferSendFromISR(instance->stream, &pair, sizeof(LevelPair), &xHigherPriorityTaskWoken);
if(sizeof(LevelPair) != ret) instance->overrun = true;
xStreamBufferSendFromISR(instance->stream, &level_duration, sizeof(LevelDuration), &xHigherPriorityTaskWoken);
if(sizeof(LevelDuration) != ret) instance->overrun = true;
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
@ -48,15 +44,17 @@ void subghz_worker_rx_callback(
static int32_t subghz_worker_thread_callback(void* context) {
SubGhzWorker* instance = context;
LevelPair pair;
LevelDuration level_duration;
while(instance->running) {
int ret = xStreamBufferReceive(instance->stream, &pair, sizeof(LevelPair), 10);
if(ret == sizeof(LevelPair)) {
if(pair.level == ApiHalSubGhzCaptureLevelOverrun) {
int ret = xStreamBufferReceive(instance->stream, &level_duration, sizeof(LevelDuration), 10);
if(ret == sizeof(LevelDuration)) {
if(level_duration_is_reset(level_duration)) {
printf(".");
if (instance->overrun_callback) instance->overrun_callback(instance->context);
} else {
if (instance->pair_callback) instance->pair_callback(instance->context, pair);
bool level = level_duration_get_level(level_duration);
uint32_t duration = level_duration_get_duration(level_duration);
if (instance->pair_callback) instance->pair_callback(instance->context, level, duration);
}
}
}
@ -73,7 +71,7 @@ SubGhzWorker* subghz_worker_alloc() {
furi_thread_set_context(instance->thread, instance);
furi_thread_set_callback(instance->thread, subghz_worker_thread_callback);
instance->stream = xStreamBufferCreate(sizeof(LevelPair) * 1024, sizeof(LevelPair));
instance->stream = xStreamBufferCreate(sizeof(LevelDuration) * 1024, sizeof(LevelDuration));
return instance;
}

View File

@ -6,9 +6,9 @@ typedef struct SubGhzWorker SubGhzWorker;
typedef void (*SubGhzWorkerOverrunCallback)(void* context);
typedef void (*SubGhzWorkerPairCallback)(void* context, LevelPair pair);
typedef void (*SubGhzWorkerPairCallback)(void* context, bool level, uint32_t duration);
void subghz_worker_rx_callback(ApiHalSubGhzCaptureLevel level, uint32_t duration, void* context);
void subghz_worker_rx_callback(bool level, uint32_t duration, void* context);
/** Allocate SubGhzWorker
*

View File

@ -0,0 +1,71 @@
#pragma once
#include <stdint.h>
#define LEVEL_DURATION_BIG
#ifdef LEVEL_DURATION_BIG
#define LEVEL_DURATION_RESET 0U
#define LEVEL_DURATION_LEVEL_LOW 1U
#define LEVEL_DURATION_LEVEL_HIGH 2U
#define LEVEL_DURATION_RESERVED 0x800000U
typedef struct {
uint32_t level;
uint32_t duration;
} LevelDuration;
static inline LevelDuration level_duration_make(bool level, uint32_t duration) {
LevelDuration level_duration;
level_duration.level = level ? LEVEL_DURATION_LEVEL_HIGH : LEVEL_DURATION_LEVEL_LOW;
level_duration.duration = duration;
return level_duration;
}
static inline LevelDuration level_duration_reset() {
LevelDuration level_duration;
level_duration.level = LEVEL_DURATION_RESET;
return level_duration;
}
static inline bool level_duration_is_reset(LevelDuration level_duration) {
return level_duration.level == LEVEL_DURATION_RESET;
}
static inline bool level_duration_get_level(LevelDuration level_duration) {
return level_duration.level == LEVEL_DURATION_LEVEL_HIGH;
}
static inline uint32_t level_duration_get_duration(LevelDuration level_duration) {
return level_duration.duration;
}
#else
#define LEVEL_DURATION_RESET 0U
#define LEVEL_DURATION_RESERVED 0x800000U
typedef int32_t LevelDuration;
static inline LevelDuration level_duration(bool level, uint32_t duration) {
return level ? duration : -(int32_t)duration;
}
static inline LevelDuration level_duration_reset() {
return LEVEL_DURATION_RESET;
}
static inline bool level_duration_is_reset(LevelDuration level_duration) {
return (level_duration == LEVEL_DURATION_RESET);
}
static inline bool level_duration_get_level(LevelDuration level_duration) {
return (level_duration > 0);
}
static inline uint32_t level_duration_get_duration(LevelDuration level_duration) {
return (level_duration >= 0) ? level_duration : -level_duration;
}
#endif