Git: set git attributes to automatically manage line endings. (#771)
* Git: set git attributes to automatically manage line endings. * Git: cleanup gitignore file
This commit is contained in:
@@ -1,228 +1,228 @@
|
||||
#include "subghz_protocol_came.h"
|
||||
#include "subghz_protocol_common.h"
|
||||
|
||||
/*
|
||||
* Help
|
||||
* https://phreakerclub.com/447
|
||||
*
|
||||
*/
|
||||
|
||||
struct SubGhzProtocolCame {
|
||||
SubGhzProtocolCommon common;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
CameDecoderStepReset = 0,
|
||||
CameDecoderStepFoundStartBit,
|
||||
CameDecoderStepSaveDuration,
|
||||
CameDecoderStepCheckDuration,
|
||||
} CameDecoderStep;
|
||||
|
||||
SubGhzProtocolCame* subghz_protocol_came_alloc() {
|
||||
SubGhzProtocolCame* instance = furi_alloc(sizeof(SubGhzProtocolCame));
|
||||
|
||||
instance->common.name = "CAME";
|
||||
instance->common.code_min_count_bit_for_found = 12;
|
||||
instance->common.te_short = 320;
|
||||
instance->common.te_long = 640;
|
||||
instance->common.te_delta = 150;
|
||||
instance->common.type_protocol = SubGhzProtocolCommonTypeStatic;
|
||||
instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_protocol_came_to_str;
|
||||
instance->common.to_save_string =
|
||||
(SubGhzProtocolCommonGetStrSave)subghz_protocol_came_to_save_str;
|
||||
instance->common.to_load_protocol_from_file =
|
||||
(SubGhzProtocolCommonLoadFromFile)subghz_protocol_came_to_load_protocol_from_file;
|
||||
instance->common.to_load_protocol =
|
||||
(SubGhzProtocolCommonLoadFromRAW)subghz_decoder_came_to_load_protocol;
|
||||
instance->common.get_upload_protocol =
|
||||
(SubGhzProtocolCommonEncoderGetUpLoad)subghz_protocol_came_send_key;
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void subghz_protocol_came_free(SubGhzProtocolCame* instance) {
|
||||
furi_assert(instance);
|
||||
free(instance);
|
||||
}
|
||||
|
||||
bool subghz_protocol_came_send_key(
|
||||
SubGhzProtocolCame* instance,
|
||||
SubGhzProtocolCommonEncoder* encoder) {
|
||||
furi_assert(instance);
|
||||
furi_assert(encoder);
|
||||
size_t index = 0;
|
||||
encoder->size_upload = (instance->common.code_last_count_bit * 2) + 2;
|
||||
if(encoder->size_upload > SUBGHZ_ENCODER_UPLOAD_MAX_SIZE) return false;
|
||||
//Send header
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(false, (uint32_t)instance->common.te_short * 36);
|
||||
//Send start bit
|
||||
encoder->upload[index++] = level_duration_make(true, (uint32_t)instance->common.te_short);
|
||||
//Send key data
|
||||
for(uint8_t i = instance->common.code_last_count_bit; i > 0; i--) {
|
||||
if(bit_read(instance->common.code_last_found, i - 1)) {
|
||||
//send bit 1
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(false, (uint32_t)instance->common.te_long);
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(true, (uint32_t)instance->common.te_short);
|
||||
} else {
|
||||
//send bit 0
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(false, (uint32_t)instance->common.te_short);
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(true, (uint32_t)instance->common.te_long);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void subghz_protocol_came_reset(SubGhzProtocolCame* instance) {
|
||||
instance->common.parser_step = CameDecoderStepReset;
|
||||
}
|
||||
|
||||
void subghz_protocol_came_parse(SubGhzProtocolCame* instance, bool level, uint32_t duration) {
|
||||
switch(instance->common.parser_step) {
|
||||
case CameDecoderStepReset:
|
||||
if((!level) && (DURATION_DIFF(duration, instance->common.te_short * 51) <
|
||||
instance->common.te_delta * 51)) { //Need protocol 36 te_short
|
||||
//Found header CAME
|
||||
instance->common.parser_step = CameDecoderStepFoundStartBit;
|
||||
} else {
|
||||
instance->common.parser_step = CameDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case CameDecoderStepFoundStartBit:
|
||||
if(!level) {
|
||||
break;
|
||||
} else if(DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta) {
|
||||
//Found start bit CAME
|
||||
instance->common.parser_step = CameDecoderStepSaveDuration;
|
||||
instance->common.code_found = 0;
|
||||
instance->common.code_count_bit = 0;
|
||||
} else {
|
||||
instance->common.parser_step = CameDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case CameDecoderStepSaveDuration:
|
||||
if(!level) { //save interval
|
||||
if(duration >= (instance->common.te_short * 4)) {
|
||||
instance->common.parser_step = CameDecoderStepFoundStartBit;
|
||||
if(instance->common.code_count_bit >=
|
||||
instance->common.code_min_count_bit_for_found) {
|
||||
instance->common.serial = 0x0;
|
||||
instance->common.btn = 0x0;
|
||||
|
||||
instance->common.code_last_found = instance->common.code_found;
|
||||
instance->common.code_last_count_bit = instance->common.code_count_bit;
|
||||
|
||||
if(instance->common.callback)
|
||||
instance->common.callback(
|
||||
(SubGhzProtocolCommon*)instance, instance->common.context);
|
||||
}
|
||||
break;
|
||||
}
|
||||
instance->common.te_last = duration;
|
||||
instance->common.parser_step = CameDecoderStepCheckDuration;
|
||||
} else {
|
||||
instance->common.parser_step = CameDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case CameDecoderStepCheckDuration:
|
||||
if(level) {
|
||||
if((DURATION_DIFF(instance->common.te_last, instance->common.te_short) <
|
||||
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 = CameDecoderStepSaveDuration;
|
||||
} else if(
|
||||
(DURATION_DIFF(instance->common.te_last, instance->common.te_long) <
|
||||
instance->common.te_delta) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta)) {
|
||||
subghz_protocol_common_add_bit(&instance->common, 1);
|
||||
instance->common.parser_step = CameDecoderStepSaveDuration;
|
||||
} else
|
||||
instance->common.parser_step = CameDecoderStepReset;
|
||||
} else {
|
||||
instance->common.parser_step = CameDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void subghz_protocol_came_to_str(SubGhzProtocolCame* instance, string_t output) {
|
||||
uint32_t code_found_lo = instance->common.code_last_found & 0x00000000ffffffff;
|
||||
|
||||
uint64_t code_found_reverse = subghz_protocol_common_reverse_key(
|
||||
instance->common.code_last_found, instance->common.code_last_count_bit);
|
||||
|
||||
uint32_t code_found_reverse_lo = code_found_reverse & 0x00000000ffffffff;
|
||||
|
||||
string_cat_printf(
|
||||
output,
|
||||
"%s %dbit\r\n"
|
||||
"Key:0x%08lX\r\n"
|
||||
"Yek:0x%08lX\r\n",
|
||||
instance->common.name,
|
||||
instance->common.code_last_count_bit,
|
||||
code_found_lo,
|
||||
code_found_reverse_lo);
|
||||
}
|
||||
|
||||
void subghz_protocol_came_to_save_str(SubGhzProtocolCame* instance, string_t output) {
|
||||
string_printf(
|
||||
output,
|
||||
"Protocol: %s\n"
|
||||
"Bit: %d\n"
|
||||
"Key: %08lX\n",
|
||||
instance->common.name,
|
||||
instance->common.code_last_count_bit,
|
||||
(uint32_t)(instance->common.code_last_found & 0x00000000ffffffff));
|
||||
}
|
||||
|
||||
bool subghz_protocol_came_to_load_protocol_from_file(
|
||||
FileWorker* file_worker,
|
||||
SubGhzProtocolCame* instance) {
|
||||
bool loaded = false;
|
||||
string_t temp_str;
|
||||
string_init(temp_str);
|
||||
int res = 0;
|
||||
int data = 0;
|
||||
|
||||
do {
|
||||
// Read and parse bit data from 2nd line
|
||||
if(!file_worker_read_until(file_worker, temp_str, '\n')) {
|
||||
break;
|
||||
}
|
||||
res = sscanf(string_get_cstr(temp_str), "Bit: %d\n", &data);
|
||||
if(res != 1) {
|
||||
break;
|
||||
}
|
||||
instance->common.code_last_count_bit = (uint8_t)data;
|
||||
|
||||
// Read and parse key data from 3nd line
|
||||
if(!file_worker_read_until(file_worker, temp_str, '\n')) {
|
||||
break;
|
||||
}
|
||||
uint32_t temp_key = 0;
|
||||
res = sscanf(string_get_cstr(temp_str), "Key: %08lX\n", &temp_key);
|
||||
if(res != 1) {
|
||||
break;
|
||||
}
|
||||
instance->common.code_last_found = (uint64_t)temp_key;
|
||||
|
||||
loaded = true;
|
||||
} while(0);
|
||||
|
||||
string_clear(temp_str);
|
||||
|
||||
return loaded;
|
||||
}
|
||||
|
||||
void subghz_decoder_came_to_load_protocol(SubGhzProtocolCame* instance, void* context) {
|
||||
furi_assert(context);
|
||||
furi_assert(instance);
|
||||
SubGhzProtocolCommonLoad* data = context;
|
||||
instance->common.code_last_found = data->code_found;
|
||||
instance->common.code_last_count_bit = data->code_count_bit;
|
||||
}
|
||||
#include "subghz_protocol_came.h"
|
||||
#include "subghz_protocol_common.h"
|
||||
|
||||
/*
|
||||
* Help
|
||||
* https://phreakerclub.com/447
|
||||
*
|
||||
*/
|
||||
|
||||
struct SubGhzProtocolCame {
|
||||
SubGhzProtocolCommon common;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
CameDecoderStepReset = 0,
|
||||
CameDecoderStepFoundStartBit,
|
||||
CameDecoderStepSaveDuration,
|
||||
CameDecoderStepCheckDuration,
|
||||
} CameDecoderStep;
|
||||
|
||||
SubGhzProtocolCame* subghz_protocol_came_alloc() {
|
||||
SubGhzProtocolCame* instance = furi_alloc(sizeof(SubGhzProtocolCame));
|
||||
|
||||
instance->common.name = "CAME";
|
||||
instance->common.code_min_count_bit_for_found = 12;
|
||||
instance->common.te_short = 320;
|
||||
instance->common.te_long = 640;
|
||||
instance->common.te_delta = 150;
|
||||
instance->common.type_protocol = SubGhzProtocolCommonTypeStatic;
|
||||
instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_protocol_came_to_str;
|
||||
instance->common.to_save_string =
|
||||
(SubGhzProtocolCommonGetStrSave)subghz_protocol_came_to_save_str;
|
||||
instance->common.to_load_protocol_from_file =
|
||||
(SubGhzProtocolCommonLoadFromFile)subghz_protocol_came_to_load_protocol_from_file;
|
||||
instance->common.to_load_protocol =
|
||||
(SubGhzProtocolCommonLoadFromRAW)subghz_decoder_came_to_load_protocol;
|
||||
instance->common.get_upload_protocol =
|
||||
(SubGhzProtocolCommonEncoderGetUpLoad)subghz_protocol_came_send_key;
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void subghz_protocol_came_free(SubGhzProtocolCame* instance) {
|
||||
furi_assert(instance);
|
||||
free(instance);
|
||||
}
|
||||
|
||||
bool subghz_protocol_came_send_key(
|
||||
SubGhzProtocolCame* instance,
|
||||
SubGhzProtocolCommonEncoder* encoder) {
|
||||
furi_assert(instance);
|
||||
furi_assert(encoder);
|
||||
size_t index = 0;
|
||||
encoder->size_upload = (instance->common.code_last_count_bit * 2) + 2;
|
||||
if(encoder->size_upload > SUBGHZ_ENCODER_UPLOAD_MAX_SIZE) return false;
|
||||
//Send header
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(false, (uint32_t)instance->common.te_short * 36);
|
||||
//Send start bit
|
||||
encoder->upload[index++] = level_duration_make(true, (uint32_t)instance->common.te_short);
|
||||
//Send key data
|
||||
for(uint8_t i = instance->common.code_last_count_bit; i > 0; i--) {
|
||||
if(bit_read(instance->common.code_last_found, i - 1)) {
|
||||
//send bit 1
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(false, (uint32_t)instance->common.te_long);
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(true, (uint32_t)instance->common.te_short);
|
||||
} else {
|
||||
//send bit 0
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(false, (uint32_t)instance->common.te_short);
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(true, (uint32_t)instance->common.te_long);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void subghz_protocol_came_reset(SubGhzProtocolCame* instance) {
|
||||
instance->common.parser_step = CameDecoderStepReset;
|
||||
}
|
||||
|
||||
void subghz_protocol_came_parse(SubGhzProtocolCame* instance, bool level, uint32_t duration) {
|
||||
switch(instance->common.parser_step) {
|
||||
case CameDecoderStepReset:
|
||||
if((!level) && (DURATION_DIFF(duration, instance->common.te_short * 51) <
|
||||
instance->common.te_delta * 51)) { //Need protocol 36 te_short
|
||||
//Found header CAME
|
||||
instance->common.parser_step = CameDecoderStepFoundStartBit;
|
||||
} else {
|
||||
instance->common.parser_step = CameDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case CameDecoderStepFoundStartBit:
|
||||
if(!level) {
|
||||
break;
|
||||
} else if(DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta) {
|
||||
//Found start bit CAME
|
||||
instance->common.parser_step = CameDecoderStepSaveDuration;
|
||||
instance->common.code_found = 0;
|
||||
instance->common.code_count_bit = 0;
|
||||
} else {
|
||||
instance->common.parser_step = CameDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case CameDecoderStepSaveDuration:
|
||||
if(!level) { //save interval
|
||||
if(duration >= (instance->common.te_short * 4)) {
|
||||
instance->common.parser_step = CameDecoderStepFoundStartBit;
|
||||
if(instance->common.code_count_bit >=
|
||||
instance->common.code_min_count_bit_for_found) {
|
||||
instance->common.serial = 0x0;
|
||||
instance->common.btn = 0x0;
|
||||
|
||||
instance->common.code_last_found = instance->common.code_found;
|
||||
instance->common.code_last_count_bit = instance->common.code_count_bit;
|
||||
|
||||
if(instance->common.callback)
|
||||
instance->common.callback(
|
||||
(SubGhzProtocolCommon*)instance, instance->common.context);
|
||||
}
|
||||
break;
|
||||
}
|
||||
instance->common.te_last = duration;
|
||||
instance->common.parser_step = CameDecoderStepCheckDuration;
|
||||
} else {
|
||||
instance->common.parser_step = CameDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case CameDecoderStepCheckDuration:
|
||||
if(level) {
|
||||
if((DURATION_DIFF(instance->common.te_last, instance->common.te_short) <
|
||||
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 = CameDecoderStepSaveDuration;
|
||||
} else if(
|
||||
(DURATION_DIFF(instance->common.te_last, instance->common.te_long) <
|
||||
instance->common.te_delta) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta)) {
|
||||
subghz_protocol_common_add_bit(&instance->common, 1);
|
||||
instance->common.parser_step = CameDecoderStepSaveDuration;
|
||||
} else
|
||||
instance->common.parser_step = CameDecoderStepReset;
|
||||
} else {
|
||||
instance->common.parser_step = CameDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void subghz_protocol_came_to_str(SubGhzProtocolCame* instance, string_t output) {
|
||||
uint32_t code_found_lo = instance->common.code_last_found & 0x00000000ffffffff;
|
||||
|
||||
uint64_t code_found_reverse = subghz_protocol_common_reverse_key(
|
||||
instance->common.code_last_found, instance->common.code_last_count_bit);
|
||||
|
||||
uint32_t code_found_reverse_lo = code_found_reverse & 0x00000000ffffffff;
|
||||
|
||||
string_cat_printf(
|
||||
output,
|
||||
"%s %dbit\r\n"
|
||||
"Key:0x%08lX\r\n"
|
||||
"Yek:0x%08lX\r\n",
|
||||
instance->common.name,
|
||||
instance->common.code_last_count_bit,
|
||||
code_found_lo,
|
||||
code_found_reverse_lo);
|
||||
}
|
||||
|
||||
void subghz_protocol_came_to_save_str(SubGhzProtocolCame* instance, string_t output) {
|
||||
string_printf(
|
||||
output,
|
||||
"Protocol: %s\n"
|
||||
"Bit: %d\n"
|
||||
"Key: %08lX\n",
|
||||
instance->common.name,
|
||||
instance->common.code_last_count_bit,
|
||||
(uint32_t)(instance->common.code_last_found & 0x00000000ffffffff));
|
||||
}
|
||||
|
||||
bool subghz_protocol_came_to_load_protocol_from_file(
|
||||
FileWorker* file_worker,
|
||||
SubGhzProtocolCame* instance) {
|
||||
bool loaded = false;
|
||||
string_t temp_str;
|
||||
string_init(temp_str);
|
||||
int res = 0;
|
||||
int data = 0;
|
||||
|
||||
do {
|
||||
// Read and parse bit data from 2nd line
|
||||
if(!file_worker_read_until(file_worker, temp_str, '\n')) {
|
||||
break;
|
||||
}
|
||||
res = sscanf(string_get_cstr(temp_str), "Bit: %d\n", &data);
|
||||
if(res != 1) {
|
||||
break;
|
||||
}
|
||||
instance->common.code_last_count_bit = (uint8_t)data;
|
||||
|
||||
// Read and parse key data from 3nd line
|
||||
if(!file_worker_read_until(file_worker, temp_str, '\n')) {
|
||||
break;
|
||||
}
|
||||
uint32_t temp_key = 0;
|
||||
res = sscanf(string_get_cstr(temp_str), "Key: %08lX\n", &temp_key);
|
||||
if(res != 1) {
|
||||
break;
|
||||
}
|
||||
instance->common.code_last_found = (uint64_t)temp_key;
|
||||
|
||||
loaded = true;
|
||||
} while(0);
|
||||
|
||||
string_clear(temp_str);
|
||||
|
||||
return loaded;
|
||||
}
|
||||
|
||||
void subghz_decoder_came_to_load_protocol(SubGhzProtocolCame* instance, void* context) {
|
||||
furi_assert(context);
|
||||
furi_assert(instance);
|
||||
SubGhzProtocolCommonLoad* data = context;
|
||||
instance->common.code_last_found = data->code_found;
|
||||
instance->common.code_last_count_bit = data->code_count_bit;
|
||||
}
|
||||
|
@@ -1,70 +1,70 @@
|
||||
#pragma once
|
||||
|
||||
#include "subghz_protocol_common.h"
|
||||
|
||||
typedef struct SubGhzProtocolCame SubGhzProtocolCame;
|
||||
|
||||
/** Allocate SubGhzProtocolCame
|
||||
*
|
||||
* @return SubGhzProtocolCame*
|
||||
*/
|
||||
SubGhzProtocolCame* subghz_protocol_came_alloc();
|
||||
|
||||
/** Free SubGhzProtocolCame
|
||||
*
|
||||
* @param instance
|
||||
*/
|
||||
void subghz_protocol_came_free(SubGhzProtocolCame* instance);
|
||||
|
||||
/** Get upload protocol
|
||||
*
|
||||
* @param instance - SubGhzProtocolCame instance
|
||||
* @param encoder - SubGhzProtocolCommonEncoder encoder
|
||||
* @return bool
|
||||
*/
|
||||
bool subghz_protocol_came_send_key(
|
||||
SubGhzProtocolCame* instance,
|
||||
SubGhzProtocolCommonEncoder* encoder);
|
||||
|
||||
/** Reset internal state
|
||||
* @param instance - SubGhzProtocolCame instance
|
||||
*/
|
||||
void subghz_protocol_came_reset(SubGhzProtocolCame* instance);
|
||||
|
||||
/** Parse accepted duration
|
||||
*
|
||||
* @param instance - SubGhzProtocolCame instance
|
||||
* @param data - LevelDuration level_duration
|
||||
*/
|
||||
void subghz_protocol_came_parse(SubGhzProtocolCame* instance, bool level, uint32_t duration);
|
||||
|
||||
/** Outputting information from the parser
|
||||
*
|
||||
* @param instance - SubGhzProtocolCame* instance
|
||||
* @param output - output string
|
||||
*/
|
||||
void subghz_protocol_came_to_str(SubGhzProtocolCame* instance, string_t output);
|
||||
|
||||
/** Get a string to save the protocol
|
||||
*
|
||||
* @param instance - SubGhzProtocolCame instance
|
||||
* @param output - the resulting string
|
||||
*/
|
||||
void subghz_protocol_came_to_save_str(SubGhzProtocolCame* instance, string_t output);
|
||||
|
||||
/** Loading protocol from file
|
||||
*
|
||||
* @param file_worker - FileWorker file_worker
|
||||
* @param instance - SubGhzProtocolCame instance
|
||||
* @return bool
|
||||
*/
|
||||
bool subghz_protocol_came_to_load_protocol_from_file(
|
||||
FileWorker* file_worker,
|
||||
SubGhzProtocolCame* instance);
|
||||
|
||||
/** Loading protocol from bin data
|
||||
*
|
||||
* @param instance - SubGhzProtocolCame instance
|
||||
* @param context - SubGhzProtocolCommonLoad context
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "subghz_protocol_common.h"
|
||||
|
||||
typedef struct SubGhzProtocolCame SubGhzProtocolCame;
|
||||
|
||||
/** Allocate SubGhzProtocolCame
|
||||
*
|
||||
* @return SubGhzProtocolCame*
|
||||
*/
|
||||
SubGhzProtocolCame* subghz_protocol_came_alloc();
|
||||
|
||||
/** Free SubGhzProtocolCame
|
||||
*
|
||||
* @param instance
|
||||
*/
|
||||
void subghz_protocol_came_free(SubGhzProtocolCame* instance);
|
||||
|
||||
/** Get upload protocol
|
||||
*
|
||||
* @param instance - SubGhzProtocolCame instance
|
||||
* @param encoder - SubGhzProtocolCommonEncoder encoder
|
||||
* @return bool
|
||||
*/
|
||||
bool subghz_protocol_came_send_key(
|
||||
SubGhzProtocolCame* instance,
|
||||
SubGhzProtocolCommonEncoder* encoder);
|
||||
|
||||
/** Reset internal state
|
||||
* @param instance - SubGhzProtocolCame instance
|
||||
*/
|
||||
void subghz_protocol_came_reset(SubGhzProtocolCame* instance);
|
||||
|
||||
/** Parse accepted duration
|
||||
*
|
||||
* @param instance - SubGhzProtocolCame instance
|
||||
* @param data - LevelDuration level_duration
|
||||
*/
|
||||
void subghz_protocol_came_parse(SubGhzProtocolCame* instance, bool level, uint32_t duration);
|
||||
|
||||
/** Outputting information from the parser
|
||||
*
|
||||
* @param instance - SubGhzProtocolCame* instance
|
||||
* @param output - output string
|
||||
*/
|
||||
void subghz_protocol_came_to_str(SubGhzProtocolCame* instance, string_t output);
|
||||
|
||||
/** Get a string to save the protocol
|
||||
*
|
||||
* @param instance - SubGhzProtocolCame instance
|
||||
* @param output - the resulting string
|
||||
*/
|
||||
void subghz_protocol_came_to_save_str(SubGhzProtocolCame* instance, string_t output);
|
||||
|
||||
/** Loading protocol from file
|
||||
*
|
||||
* @param file_worker - FileWorker file_worker
|
||||
* @param instance - SubGhzProtocolCame instance
|
||||
* @return bool
|
||||
*/
|
||||
bool subghz_protocol_came_to_load_protocol_from_file(
|
||||
FileWorker* file_worker,
|
||||
SubGhzProtocolCame* instance);
|
||||
|
||||
/** Loading protocol from bin data
|
||||
*
|
||||
* @param instance - SubGhzProtocolCame instance
|
||||
* @param context - SubGhzProtocolCommonLoad context
|
||||
*/
|
||||
void subghz_decoder_came_to_load_protocol(SubGhzProtocolCame* instance, void* context);
|
@@ -1,4 +1,4 @@
|
||||
|
||||
/*
|
||||
* https://phreakerclub.com/616
|
||||
*/
|
||||
|
||||
/*
|
||||
* https://phreakerclub.com/616
|
||||
*/
|
||||
|
@@ -1,139 +1,139 @@
|
||||
#include "subghz_protocol_common.h"
|
||||
#include <stdio.h>
|
||||
#include <lib/toolbox/hex.h>
|
||||
|
||||
|
||||
SubGhzProtocolCommonEncoder* subghz_protocol_encoder_common_alloc() {
|
||||
SubGhzProtocolCommonEncoder* instance = furi_alloc(sizeof(SubGhzProtocolCommonEncoder));
|
||||
instance->upload = furi_alloc(SUBGHZ_ENCODER_UPLOAD_MAX_SIZE * sizeof(LevelDuration));
|
||||
instance->start = true;
|
||||
instance->repeat = 10; //default number of repeat
|
||||
return instance;
|
||||
}
|
||||
|
||||
void subghz_protocol_encoder_common_free(SubGhzProtocolCommonEncoder* instance) {
|
||||
furi_assert(instance);
|
||||
free(instance->upload);
|
||||
free(instance);
|
||||
}
|
||||
|
||||
size_t subghz_encoder_common_get_repeat_left(SubGhzProtocolCommonEncoder* instance) {
|
||||
furi_assert(instance);
|
||||
return instance->repeat;
|
||||
}
|
||||
|
||||
LevelDuration subghz_protocol_encoder_common_yield(void* context) {
|
||||
SubGhzProtocolCommonEncoder* instance = context;
|
||||
|
||||
if(instance->repeat == 0){
|
||||
return level_duration_reset();
|
||||
}
|
||||
|
||||
LevelDuration ret = instance->upload[instance->front];
|
||||
|
||||
if(++instance->front == instance->size_upload) {
|
||||
instance->repeat--;
|
||||
instance->front = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void subghz_protocol_common_add_bit(SubGhzProtocolCommon *common, uint8_t bit){
|
||||
common->code_found = common->code_found << 1 | bit;
|
||||
common->code_count_bit++;
|
||||
}
|
||||
|
||||
bool subghz_protocol_common_check_interval(SubGhzProtocolCommon *common, uint32_t duration, uint16_t duration_check) {
|
||||
if ((duration_check >= (duration - common->te_delta))&&(duration_check <= (duration + common->te_delta))){
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t subghz_protocol_common_reverse_key(uint64_t key, uint8_t count_bit){
|
||||
uint64_t key_reverse=0;
|
||||
for(uint8_t i=0; i<count_bit; i++) {
|
||||
key_reverse=key_reverse<<1|bit_read(key,i);
|
||||
}
|
||||
return key_reverse;
|
||||
}
|
||||
|
||||
void subghz_protocol_common_set_callback(SubGhzProtocolCommon* common, SubGhzProtocolCommonCallback callback, void* context) {
|
||||
common->callback = callback;
|
||||
common->context = context;
|
||||
}
|
||||
|
||||
|
||||
void subghz_protocol_common_to_str(SubGhzProtocolCommon* instance, string_t output) {
|
||||
if (instance->to_string) {
|
||||
instance->to_string(instance, output);
|
||||
} else {
|
||||
uint32_t code_found_hi = instance->code_found >> 32;
|
||||
uint32_t code_found_lo = instance->code_found & 0x00000000ffffffff;
|
||||
|
||||
uint64_t code_found_reverse = subghz_protocol_common_reverse_key(instance->code_found, instance->code_count_bit);
|
||||
|
||||
uint32_t code_found_reverse_hi = code_found_reverse>>32;
|
||||
uint32_t code_found_reverse_lo = code_found_reverse&0x00000000ffffffff;
|
||||
|
||||
if (code_found_hi>0) {
|
||||
string_cat_printf(
|
||||
output,
|
||||
"Protocol %s, %d Bit\r\n"
|
||||
" KEY:0x%lX%08lX\r\n"
|
||||
" YEK:0x%lX%08lX\r\n"
|
||||
" SN:0x%05lX BTN:%02X\r\n",
|
||||
instance->name,
|
||||
instance->code_count_bit,
|
||||
code_found_hi,
|
||||
code_found_lo,
|
||||
code_found_reverse_hi,
|
||||
code_found_reverse_lo,
|
||||
instance->serial,
|
||||
instance->btn
|
||||
);
|
||||
} else {
|
||||
string_cat_printf(
|
||||
output,
|
||||
"Protocol %s, %d Bit\r\n"
|
||||
" KEY:0x%lX%lX\r\n"
|
||||
" YEK:0x%lX%lX\r\n"
|
||||
" SN:0x%05lX BTN:%02X\r\n",
|
||||
instance->name,
|
||||
instance->code_count_bit,
|
||||
code_found_hi,
|
||||
code_found_lo,
|
||||
code_found_reverse_hi,
|
||||
code_found_reverse_lo,
|
||||
instance->serial,
|
||||
instance->btn
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool subghz_protocol_common_read_hex(string_t str, uint8_t* buff, uint16_t len) {
|
||||
string_strim(str);
|
||||
uint8_t nibble_high = 0;
|
||||
uint8_t nibble_low = 0;
|
||||
bool parsed = true;
|
||||
|
||||
for(uint16_t i = 0; i < len; i++) {
|
||||
if(hex_char_to_hex_nibble(string_get_char(str, 0), &nibble_high) &&
|
||||
hex_char_to_hex_nibble(string_get_char(str, 1), &nibble_low)) {
|
||||
buff[i] = (nibble_high << 4) | nibble_low;
|
||||
if(string_size(str)>2){
|
||||
string_right(str, 2);
|
||||
}else if(i<len-1){
|
||||
parsed = false;
|
||||
break;
|
||||
};
|
||||
} else {
|
||||
parsed = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return parsed;
|
||||
}
|
||||
#include "subghz_protocol_common.h"
|
||||
#include <stdio.h>
|
||||
#include <lib/toolbox/hex.h>
|
||||
|
||||
|
||||
SubGhzProtocolCommonEncoder* subghz_protocol_encoder_common_alloc() {
|
||||
SubGhzProtocolCommonEncoder* instance = furi_alloc(sizeof(SubGhzProtocolCommonEncoder));
|
||||
instance->upload = furi_alloc(SUBGHZ_ENCODER_UPLOAD_MAX_SIZE * sizeof(LevelDuration));
|
||||
instance->start = true;
|
||||
instance->repeat = 10; //default number of repeat
|
||||
return instance;
|
||||
}
|
||||
|
||||
void subghz_protocol_encoder_common_free(SubGhzProtocolCommonEncoder* instance) {
|
||||
furi_assert(instance);
|
||||
free(instance->upload);
|
||||
free(instance);
|
||||
}
|
||||
|
||||
size_t subghz_encoder_common_get_repeat_left(SubGhzProtocolCommonEncoder* instance) {
|
||||
furi_assert(instance);
|
||||
return instance->repeat;
|
||||
}
|
||||
|
||||
LevelDuration subghz_protocol_encoder_common_yield(void* context) {
|
||||
SubGhzProtocolCommonEncoder* instance = context;
|
||||
|
||||
if(instance->repeat == 0){
|
||||
return level_duration_reset();
|
||||
}
|
||||
|
||||
LevelDuration ret = instance->upload[instance->front];
|
||||
|
||||
if(++instance->front == instance->size_upload) {
|
||||
instance->repeat--;
|
||||
instance->front = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void subghz_protocol_common_add_bit(SubGhzProtocolCommon *common, uint8_t bit){
|
||||
common->code_found = common->code_found << 1 | bit;
|
||||
common->code_count_bit++;
|
||||
}
|
||||
|
||||
bool subghz_protocol_common_check_interval(SubGhzProtocolCommon *common, uint32_t duration, uint16_t duration_check) {
|
||||
if ((duration_check >= (duration - common->te_delta))&&(duration_check <= (duration + common->te_delta))){
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t subghz_protocol_common_reverse_key(uint64_t key, uint8_t count_bit){
|
||||
uint64_t key_reverse=0;
|
||||
for(uint8_t i=0; i<count_bit; i++) {
|
||||
key_reverse=key_reverse<<1|bit_read(key,i);
|
||||
}
|
||||
return key_reverse;
|
||||
}
|
||||
|
||||
void subghz_protocol_common_set_callback(SubGhzProtocolCommon* common, SubGhzProtocolCommonCallback callback, void* context) {
|
||||
common->callback = callback;
|
||||
common->context = context;
|
||||
}
|
||||
|
||||
|
||||
void subghz_protocol_common_to_str(SubGhzProtocolCommon* instance, string_t output) {
|
||||
if (instance->to_string) {
|
||||
instance->to_string(instance, output);
|
||||
} else {
|
||||
uint32_t code_found_hi = instance->code_found >> 32;
|
||||
uint32_t code_found_lo = instance->code_found & 0x00000000ffffffff;
|
||||
|
||||
uint64_t code_found_reverse = subghz_protocol_common_reverse_key(instance->code_found, instance->code_count_bit);
|
||||
|
||||
uint32_t code_found_reverse_hi = code_found_reverse>>32;
|
||||
uint32_t code_found_reverse_lo = code_found_reverse&0x00000000ffffffff;
|
||||
|
||||
if (code_found_hi>0) {
|
||||
string_cat_printf(
|
||||
output,
|
||||
"Protocol %s, %d Bit\r\n"
|
||||
" KEY:0x%lX%08lX\r\n"
|
||||
" YEK:0x%lX%08lX\r\n"
|
||||
" SN:0x%05lX BTN:%02X\r\n",
|
||||
instance->name,
|
||||
instance->code_count_bit,
|
||||
code_found_hi,
|
||||
code_found_lo,
|
||||
code_found_reverse_hi,
|
||||
code_found_reverse_lo,
|
||||
instance->serial,
|
||||
instance->btn
|
||||
);
|
||||
} else {
|
||||
string_cat_printf(
|
||||
output,
|
||||
"Protocol %s, %d Bit\r\n"
|
||||
" KEY:0x%lX%lX\r\n"
|
||||
" YEK:0x%lX%lX\r\n"
|
||||
" SN:0x%05lX BTN:%02X\r\n",
|
||||
instance->name,
|
||||
instance->code_count_bit,
|
||||
code_found_hi,
|
||||
code_found_lo,
|
||||
code_found_reverse_hi,
|
||||
code_found_reverse_lo,
|
||||
instance->serial,
|
||||
instance->btn
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool subghz_protocol_common_read_hex(string_t str, uint8_t* buff, uint16_t len) {
|
||||
string_strim(str);
|
||||
uint8_t nibble_high = 0;
|
||||
uint8_t nibble_low = 0;
|
||||
bool parsed = true;
|
||||
|
||||
for(uint16_t i = 0; i < len; i++) {
|
||||
if(hex_char_to_hex_nibble(string_get_char(str, 0), &nibble_high) &&
|
||||
hex_char_to_hex_nibble(string_get_char(str, 1), &nibble_low)) {
|
||||
buff[i] = (nibble_high << 4) | nibble_low;
|
||||
if(string_size(str)>2){
|
||||
string_right(str, 2);
|
||||
}else if(i<len-1){
|
||||
parsed = false;
|
||||
break;
|
||||
};
|
||||
} else {
|
||||
parsed = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return parsed;
|
||||
}
|
||||
|
@@ -1,177 +1,177 @@
|
||||
#pragma once
|
||||
|
||||
#include <m-string.h>
|
||||
#include <furi-hal.h>
|
||||
#include <stdint.h>
|
||||
#include "file-worker.h"
|
||||
|
||||
#define bit_read(value, bit) (((value) >> (bit)) & 0x01)
|
||||
#define bit_set(value, bit) ((value) |= (1UL << (bit)))
|
||||
#define bit_clear(value, bit) ((value) &= ~(1UL << (bit)))
|
||||
#define bit_write(value, bit, bitvalue) (bitvalue ? bit_set(value, bit) : bit_clear(value, bit))
|
||||
|
||||
#define SUBGHZ_TX_PIN_HIGH()
|
||||
#define SUBGHZ_TX_PIN_LOW()
|
||||
#define DURATION_DIFF(x, y) ((x < y) ? (y - x) : (x - y))
|
||||
|
||||
#define SUBGHZ_APP_FOLDER "/any/subghz"
|
||||
#define SUBGHZ_APP_PATH_FOLDER "/any/subghz/saved"
|
||||
#define SUBGHZ_APP_EXTENSION ".sub"
|
||||
#define SUBGHZ_ENCODER_UPLOAD_MAX_SIZE 2048
|
||||
|
||||
typedef enum {
|
||||
SubGhzProtocolCommonTypeUnknown,
|
||||
SubGhzProtocolCommonTypeStatic,
|
||||
SubGhzProtocolCommonTypeDynamic,
|
||||
} SubGhzProtocolCommonType;
|
||||
|
||||
typedef struct SubGhzProtocolCommon SubGhzProtocolCommon;
|
||||
typedef struct SubGhzProtocolCommonEncoder SubGhzProtocolCommonEncoder;
|
||||
typedef struct SubGhzProtocolCommonLoad SubGhzProtocolCommonLoad;
|
||||
|
||||
typedef void (*SubGhzProtocolCommonCallback)(SubGhzProtocolCommon* parser, void* context);
|
||||
|
||||
typedef void (*SubGhzProtocolCommonToStr)(SubGhzProtocolCommon* instance, string_t output);
|
||||
|
||||
//Get string to save
|
||||
typedef void (*SubGhzProtocolCommonGetStrSave)(SubGhzProtocolCommon* instance, string_t output);
|
||||
|
||||
//Load protocol from file
|
||||
typedef bool (
|
||||
*SubGhzProtocolCommonLoadFromFile)(FileWorker* file_worker, SubGhzProtocolCommon* instance);
|
||||
//Load protocol
|
||||
typedef void (*SubGhzProtocolCommonLoadFromRAW)(SubGhzProtocolCommon* instance, void* context);
|
||||
//Get upload encoder protocol
|
||||
typedef bool (*SubGhzProtocolCommonEncoderGetUpLoad)(
|
||||
SubGhzProtocolCommon* instance,
|
||||
SubGhzProtocolCommonEncoder* encoder);
|
||||
|
||||
struct SubGhzProtocolCommon {
|
||||
const char* name;
|
||||
uint16_t te_long;
|
||||
uint16_t te_short;
|
||||
uint16_t te_delta;
|
||||
uint8_t code_count_bit;
|
||||
uint8_t code_last_count_bit;
|
||||
uint64_t code_found;
|
||||
uint64_t code_last_found;
|
||||
uint8_t code_min_count_bit_for_found;
|
||||
uint8_t btn;
|
||||
uint8_t header_count;
|
||||
SubGhzProtocolCommonType type_protocol;
|
||||
uint32_t te_last;
|
||||
uint32_t serial;
|
||||
uint32_t parser_step;
|
||||
uint16_t cnt;
|
||||
|
||||
/* Standard Callback for on rx complete event */
|
||||
SubGhzProtocolCommonCallback callback;
|
||||
void* context;
|
||||
|
||||
/* Dump To String */
|
||||
SubGhzProtocolCommonToStr to_string;
|
||||
/* Get string to save */
|
||||
SubGhzProtocolCommonGetStrSave to_save_string;
|
||||
/* Load protocol from file */
|
||||
SubGhzProtocolCommonLoadFromFile to_load_protocol_from_file;
|
||||
/* Load protocol from RAW data */
|
||||
SubGhzProtocolCommonLoadFromRAW to_load_protocol;
|
||||
/* Get upload encoder protocol */
|
||||
SubGhzProtocolCommonEncoderGetUpLoad get_upload_protocol;
|
||||
};
|
||||
|
||||
struct SubGhzProtocolCommonEncoder {
|
||||
bool start;
|
||||
size_t repeat;
|
||||
size_t front;
|
||||
size_t size_upload;
|
||||
LevelDuration* upload;
|
||||
};
|
||||
|
||||
struct SubGhzProtocolCommonLoad {
|
||||
uint64_t code_found;
|
||||
uint8_t code_count_bit;
|
||||
uint32_t param1;
|
||||
uint32_t param2;
|
||||
uint32_t param3;
|
||||
};
|
||||
|
||||
/** Allocate SubGhzProtocolCommonEncoder
|
||||
*
|
||||
* @return SubGhzProtocolCommonEncoder*
|
||||
*/
|
||||
SubGhzProtocolCommonEncoder* subghz_protocol_encoder_common_alloc();
|
||||
|
||||
/** Free SubGhzProtocolCommonEncoder
|
||||
*
|
||||
* @param instance
|
||||
*/
|
||||
void subghz_protocol_encoder_common_free(SubGhzProtocolCommonEncoder* instance);
|
||||
|
||||
/** Get count repeat left
|
||||
*
|
||||
* @param instance - SubGhzProtocolCommonEncoder instance
|
||||
* @return count repeat left
|
||||
*/
|
||||
size_t subghz_encoder_common_get_repeat_left(SubGhzProtocolCommonEncoder* instance);
|
||||
|
||||
/** Get LevelDuration this encoder step
|
||||
*
|
||||
* @param context - SubGhzProtocolCommonEncoder context
|
||||
* @return LevelDuration this step
|
||||
*/
|
||||
LevelDuration subghz_protocol_encoder_common_yield(void* context);
|
||||
|
||||
/** Add data bit to code_found
|
||||
*
|
||||
* @param common - SubGhzProtocolCommon common
|
||||
* @param bit - add bit
|
||||
*/
|
||||
void subghz_protocol_common_add_bit(SubGhzProtocolCommon* common, uint8_t bit);
|
||||
|
||||
/** Checking that the duration is included in the interval
|
||||
*
|
||||
* @param common - SubGhzProtocolCommon common
|
||||
* @param duration duration reference
|
||||
* @param duration_check duration checked
|
||||
* @return true on success
|
||||
*/
|
||||
bool subghz_protocol_common_check_interval(
|
||||
SubGhzProtocolCommon* common,
|
||||
uint32_t duration,
|
||||
uint16_t duration_check);
|
||||
|
||||
/** Bit-by-bit data mirroring
|
||||
*
|
||||
* @param key - data to mirror
|
||||
* @param count_bit number of data bits
|
||||
* @return mirrored data
|
||||
*/
|
||||
uint64_t subghz_protocol_common_reverse_key(uint64_t key, uint8_t count_bit);
|
||||
|
||||
/** Callback protocol
|
||||
*
|
||||
* @param instance - SubGhzProtocolCommon* instance
|
||||
* @param callback
|
||||
* @param context
|
||||
*/
|
||||
void subghz_protocol_common_set_callback(
|
||||
SubGhzProtocolCommon* instance,
|
||||
SubGhzProtocolCommonCallback callback,
|
||||
void* context);
|
||||
|
||||
/** outputting information from the parser
|
||||
*
|
||||
* @param instance - SubGhzProtocolCommon* instance
|
||||
* @param output - output string
|
||||
*/
|
||||
void subghz_protocol_common_to_str(SubGhzProtocolCommon* instance, string_t output);
|
||||
|
||||
/** Converting a string to a HEX array
|
||||
*
|
||||
* @param str - string data
|
||||
* @param buff - uint8_t* buff
|
||||
* @param len - size buff
|
||||
* @return bool
|
||||
*/
|
||||
bool subghz_protocol_common_read_hex(string_t str, uint8_t* buff, uint16_t len);
|
||||
#pragma once
|
||||
|
||||
#include <m-string.h>
|
||||
#include <furi-hal.h>
|
||||
#include <stdint.h>
|
||||
#include "file-worker.h"
|
||||
|
||||
#define bit_read(value, bit) (((value) >> (bit)) & 0x01)
|
||||
#define bit_set(value, bit) ((value) |= (1UL << (bit)))
|
||||
#define bit_clear(value, bit) ((value) &= ~(1UL << (bit)))
|
||||
#define bit_write(value, bit, bitvalue) (bitvalue ? bit_set(value, bit) : bit_clear(value, bit))
|
||||
|
||||
#define SUBGHZ_TX_PIN_HIGH()
|
||||
#define SUBGHZ_TX_PIN_LOW()
|
||||
#define DURATION_DIFF(x, y) ((x < y) ? (y - x) : (x - y))
|
||||
|
||||
#define SUBGHZ_APP_FOLDER "/any/subghz"
|
||||
#define SUBGHZ_APP_PATH_FOLDER "/any/subghz/saved"
|
||||
#define SUBGHZ_APP_EXTENSION ".sub"
|
||||
#define SUBGHZ_ENCODER_UPLOAD_MAX_SIZE 2048
|
||||
|
||||
typedef enum {
|
||||
SubGhzProtocolCommonTypeUnknown,
|
||||
SubGhzProtocolCommonTypeStatic,
|
||||
SubGhzProtocolCommonTypeDynamic,
|
||||
} SubGhzProtocolCommonType;
|
||||
|
||||
typedef struct SubGhzProtocolCommon SubGhzProtocolCommon;
|
||||
typedef struct SubGhzProtocolCommonEncoder SubGhzProtocolCommonEncoder;
|
||||
typedef struct SubGhzProtocolCommonLoad SubGhzProtocolCommonLoad;
|
||||
|
||||
typedef void (*SubGhzProtocolCommonCallback)(SubGhzProtocolCommon* parser, void* context);
|
||||
|
||||
typedef void (*SubGhzProtocolCommonToStr)(SubGhzProtocolCommon* instance, string_t output);
|
||||
|
||||
//Get string to save
|
||||
typedef void (*SubGhzProtocolCommonGetStrSave)(SubGhzProtocolCommon* instance, string_t output);
|
||||
|
||||
//Load protocol from file
|
||||
typedef bool (
|
||||
*SubGhzProtocolCommonLoadFromFile)(FileWorker* file_worker, SubGhzProtocolCommon* instance);
|
||||
//Load protocol
|
||||
typedef void (*SubGhzProtocolCommonLoadFromRAW)(SubGhzProtocolCommon* instance, void* context);
|
||||
//Get upload encoder protocol
|
||||
typedef bool (*SubGhzProtocolCommonEncoderGetUpLoad)(
|
||||
SubGhzProtocolCommon* instance,
|
||||
SubGhzProtocolCommonEncoder* encoder);
|
||||
|
||||
struct SubGhzProtocolCommon {
|
||||
const char* name;
|
||||
uint16_t te_long;
|
||||
uint16_t te_short;
|
||||
uint16_t te_delta;
|
||||
uint8_t code_count_bit;
|
||||
uint8_t code_last_count_bit;
|
||||
uint64_t code_found;
|
||||
uint64_t code_last_found;
|
||||
uint8_t code_min_count_bit_for_found;
|
||||
uint8_t btn;
|
||||
uint8_t header_count;
|
||||
SubGhzProtocolCommonType type_protocol;
|
||||
uint32_t te_last;
|
||||
uint32_t serial;
|
||||
uint32_t parser_step;
|
||||
uint16_t cnt;
|
||||
|
||||
/* Standard Callback for on rx complete event */
|
||||
SubGhzProtocolCommonCallback callback;
|
||||
void* context;
|
||||
|
||||
/* Dump To String */
|
||||
SubGhzProtocolCommonToStr to_string;
|
||||
/* Get string to save */
|
||||
SubGhzProtocolCommonGetStrSave to_save_string;
|
||||
/* Load protocol from file */
|
||||
SubGhzProtocolCommonLoadFromFile to_load_protocol_from_file;
|
||||
/* Load protocol from RAW data */
|
||||
SubGhzProtocolCommonLoadFromRAW to_load_protocol;
|
||||
/* Get upload encoder protocol */
|
||||
SubGhzProtocolCommonEncoderGetUpLoad get_upload_protocol;
|
||||
};
|
||||
|
||||
struct SubGhzProtocolCommonEncoder {
|
||||
bool start;
|
||||
size_t repeat;
|
||||
size_t front;
|
||||
size_t size_upload;
|
||||
LevelDuration* upload;
|
||||
};
|
||||
|
||||
struct SubGhzProtocolCommonLoad {
|
||||
uint64_t code_found;
|
||||
uint8_t code_count_bit;
|
||||
uint32_t param1;
|
||||
uint32_t param2;
|
||||
uint32_t param3;
|
||||
};
|
||||
|
||||
/** Allocate SubGhzProtocolCommonEncoder
|
||||
*
|
||||
* @return SubGhzProtocolCommonEncoder*
|
||||
*/
|
||||
SubGhzProtocolCommonEncoder* subghz_protocol_encoder_common_alloc();
|
||||
|
||||
/** Free SubGhzProtocolCommonEncoder
|
||||
*
|
||||
* @param instance
|
||||
*/
|
||||
void subghz_protocol_encoder_common_free(SubGhzProtocolCommonEncoder* instance);
|
||||
|
||||
/** Get count repeat left
|
||||
*
|
||||
* @param instance - SubGhzProtocolCommonEncoder instance
|
||||
* @return count repeat left
|
||||
*/
|
||||
size_t subghz_encoder_common_get_repeat_left(SubGhzProtocolCommonEncoder* instance);
|
||||
|
||||
/** Get LevelDuration this encoder step
|
||||
*
|
||||
* @param context - SubGhzProtocolCommonEncoder context
|
||||
* @return LevelDuration this step
|
||||
*/
|
||||
LevelDuration subghz_protocol_encoder_common_yield(void* context);
|
||||
|
||||
/** Add data bit to code_found
|
||||
*
|
||||
* @param common - SubGhzProtocolCommon common
|
||||
* @param bit - add bit
|
||||
*/
|
||||
void subghz_protocol_common_add_bit(SubGhzProtocolCommon* common, uint8_t bit);
|
||||
|
||||
/** Checking that the duration is included in the interval
|
||||
*
|
||||
* @param common - SubGhzProtocolCommon common
|
||||
* @param duration duration reference
|
||||
* @param duration_check duration checked
|
||||
* @return true on success
|
||||
*/
|
||||
bool subghz_protocol_common_check_interval(
|
||||
SubGhzProtocolCommon* common,
|
||||
uint32_t duration,
|
||||
uint16_t duration_check);
|
||||
|
||||
/** Bit-by-bit data mirroring
|
||||
*
|
||||
* @param key - data to mirror
|
||||
* @param count_bit number of data bits
|
||||
* @return mirrored data
|
||||
*/
|
||||
uint64_t subghz_protocol_common_reverse_key(uint64_t key, uint8_t count_bit);
|
||||
|
||||
/** Callback protocol
|
||||
*
|
||||
* @param instance - SubGhzProtocolCommon* instance
|
||||
* @param callback
|
||||
* @param context
|
||||
*/
|
||||
void subghz_protocol_common_set_callback(
|
||||
SubGhzProtocolCommon* instance,
|
||||
SubGhzProtocolCommonCallback callback,
|
||||
void* context);
|
||||
|
||||
/** outputting information from the parser
|
||||
*
|
||||
* @param instance - SubGhzProtocolCommon* instance
|
||||
* @param output - output string
|
||||
*/
|
||||
void subghz_protocol_common_to_str(SubGhzProtocolCommon* instance, string_t output);
|
||||
|
||||
/** Converting a string to a HEX array
|
||||
*
|
||||
* @param str - string data
|
||||
* @param buff - uint8_t* buff
|
||||
* @param len - size buff
|
||||
* @return bool
|
||||
*/
|
||||
bool subghz_protocol_common_read_hex(string_t str, uint8_t* buff, uint16_t len);
|
||||
|
@@ -1,191 +1,191 @@
|
||||
#include "subghz_protocol_faac_slh.h"
|
||||
|
||||
struct SubGhzProtocolFaacSLH {
|
||||
SubGhzProtocolCommon common;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
FaacSLHDecoderStepReset = 0,
|
||||
FaacSLHDecoderStepFoundPreambula,
|
||||
FaacSLHDecoderStepSaveDuration,
|
||||
FaacSLHDecoderStepCheckDuration,
|
||||
} FaacSLHDecoderStep;
|
||||
|
||||
SubGhzProtocolFaacSLH* subghz_protocol_faac_slh_alloc(void) {
|
||||
SubGhzProtocolFaacSLH* instance = furi_alloc(sizeof(SubGhzProtocolFaacSLH));
|
||||
|
||||
instance->common.name = "Faac SLH";
|
||||
instance->common.code_min_count_bit_for_found = 64;
|
||||
instance->common.te_short = 255;
|
||||
instance->common.te_long = 595;
|
||||
instance->common.te_delta = 100;
|
||||
instance->common.type_protocol = SubGhzProtocolCommonTypeDynamic;
|
||||
instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_protocol_faac_slh_to_str;
|
||||
instance->common.to_load_protocol =
|
||||
(SubGhzProtocolCommonLoadFromRAW)subghz_decoder_faac_slh_to_load_protocol;
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void subghz_protocol_faac_slh_free(SubGhzProtocolFaacSLH* instance) {
|
||||
furi_assert(instance);
|
||||
free(instance);
|
||||
}
|
||||
|
||||
/** Send bit
|
||||
*
|
||||
* @param instance - SubGhzProtocolFaacSLH instance
|
||||
* @param bit - bit
|
||||
*/
|
||||
void subghz_protocol_faac_slh_send_bit(SubGhzProtocolFaacSLH* instance, uint8_t bit) {
|
||||
if(bit) {
|
||||
//send bit 1
|
||||
SUBGHZ_TX_PIN_HIGH();
|
||||
delay_us(instance->common.te_long);
|
||||
SUBGHZ_TX_PIN_LOW();
|
||||
delay_us(instance->common.te_short);
|
||||
} else {
|
||||
//send bit 0
|
||||
SUBGHZ_TX_PIN_HIGH();
|
||||
delay_us(instance->common.te_short);
|
||||
SUBGHZ_TX_PIN_LOW();
|
||||
delay_us(instance->common.te_long);
|
||||
}
|
||||
}
|
||||
|
||||
void subghz_protocol_faac_slh_send_key(
|
||||
SubGhzProtocolFaacSLH* instance,
|
||||
uint64_t key,
|
||||
uint8_t bit,
|
||||
uint8_t repeat) {
|
||||
while(repeat--) {
|
||||
SUBGHZ_TX_PIN_HIGH();
|
||||
//Send header
|
||||
delay_us(instance->common.te_long * 2);
|
||||
SUBGHZ_TX_PIN_LOW();
|
||||
delay_us(instance->common.te_long * 2);
|
||||
//Send key data
|
||||
for(uint8_t i = bit; i > 0; i--) {
|
||||
subghz_protocol_faac_slh_send_bit(instance, bit_read(key, i - 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void subghz_protocol_faac_slh_reset(SubGhzProtocolFaacSLH* instance) {
|
||||
instance->common.parser_step = FaacSLHDecoderStepReset;
|
||||
}
|
||||
|
||||
/** Analysis of received data
|
||||
*
|
||||
* @param instance SubGhzProtocolFaacSLH instance
|
||||
*/
|
||||
void subghz_protocol_faac_slh_check_remote_controller(SubGhzProtocolFaacSLH* instance) {
|
||||
uint64_t code_found_reverse = subghz_protocol_common_reverse_key(
|
||||
instance->common.code_last_found, instance->common.code_last_count_bit);
|
||||
uint32_t code_fix = code_found_reverse & 0xFFFFFFFF;
|
||||
//uint32_t code_hop = (code_found_reverse >> 24) & 0xFFFFF;
|
||||
|
||||
instance->common.serial = code_fix & 0xFFFFFFF;
|
||||
instance->common.btn = (code_fix >> 28) & 0x0F;
|
||||
}
|
||||
|
||||
void subghz_protocol_faac_slh_parse(SubGhzProtocolFaacSLH* instance, bool level, uint32_t duration) {
|
||||
switch(instance->common.parser_step) {
|
||||
case FaacSLHDecoderStepReset:
|
||||
if((level) && (DURATION_DIFF(duration, instance->common.te_long * 2) <
|
||||
instance->common.te_delta * 3)) {
|
||||
instance->common.parser_step = FaacSLHDecoderStepFoundPreambula;
|
||||
} else {
|
||||
instance->common.parser_step = FaacSLHDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case FaacSLHDecoderStepFoundPreambula:
|
||||
if((!level) && (DURATION_DIFF(duration, instance->common.te_long * 2) <
|
||||
instance->common.te_delta * 3)) {
|
||||
//Found Preambula
|
||||
instance->common.parser_step = FaacSLHDecoderStepSaveDuration;
|
||||
instance->common.code_found = 0;
|
||||
instance->common.code_count_bit = 0;
|
||||
} else {
|
||||
instance->common.parser_step = FaacSLHDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case FaacSLHDecoderStepSaveDuration:
|
||||
if(level) {
|
||||
if(duration >= (instance->common.te_short * 3 + instance->common.te_delta)) {
|
||||
instance->common.parser_step = FaacSLHDecoderStepFoundPreambula;
|
||||
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_count_bit = instance->common.code_count_bit;
|
||||
if(instance->common.callback)
|
||||
instance->common.callback(
|
||||
(SubGhzProtocolCommon*)instance, instance->common.context);
|
||||
}
|
||||
instance->common.code_found = 0;
|
||||
instance->common.code_count_bit = 0;
|
||||
break;
|
||||
} else {
|
||||
instance->common.te_last = duration;
|
||||
instance->common.parser_step = FaacSLHDecoderStepCheckDuration;
|
||||
}
|
||||
|
||||
} else {
|
||||
instance->common.parser_step = FaacSLHDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case FaacSLHDecoderStepCheckDuration:
|
||||
if(!level) {
|
||||
if((DURATION_DIFF(instance->common.te_last, instance->common.te_short) <
|
||||
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 = FaacSLHDecoderStepSaveDuration;
|
||||
} else if(
|
||||
(DURATION_DIFF(instance->common.te_last, instance->common.te_long) <
|
||||
instance->common.te_delta) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta)) {
|
||||
subghz_protocol_common_add_bit(&instance->common, 1);
|
||||
instance->common.parser_step = FaacSLHDecoderStepSaveDuration;
|
||||
} else {
|
||||
instance->common.parser_step = FaacSLHDecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
instance->common.parser_step = FaacSLHDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void subghz_protocol_faac_slh_to_str(SubGhzProtocolFaacSLH* instance, string_t output) {
|
||||
subghz_protocol_faac_slh_check_remote_controller(instance);
|
||||
uint64_t code_found_reverse = subghz_protocol_common_reverse_key(
|
||||
instance->common.code_last_found, instance->common.code_last_count_bit);
|
||||
uint32_t code_fix = code_found_reverse & 0xFFFFFFFF;
|
||||
uint32_t code_hop = (code_found_reverse >> 32) & 0xFFFFFFFF;
|
||||
|
||||
string_cat_printf(
|
||||
output,
|
||||
"%s %dbit\r\n"
|
||||
"Key:0x%lX%08lX\r\n"
|
||||
"Fix:%08lX \r\n"
|
||||
"Hop:%08lX \r\n"
|
||||
"Sn:%07lX Btn:%lX\r\n",
|
||||
instance->common.name,
|
||||
instance->common.code_last_count_bit,
|
||||
(uint32_t)(instance->common.code_last_found >> 32),
|
||||
(uint32_t)instance->common.code_last_found,
|
||||
code_fix,
|
||||
code_hop,
|
||||
instance->common.serial,
|
||||
instance->common.btn);
|
||||
}
|
||||
|
||||
void subghz_decoder_faac_slh_to_load_protocol(SubGhzProtocolFaacSLH* instance, void* context) {
|
||||
furi_assert(context);
|
||||
furi_assert(instance);
|
||||
SubGhzProtocolCommonLoad* data = context;
|
||||
instance->common.code_last_found = data->code_found;
|
||||
instance->common.code_last_count_bit = data->code_count_bit;
|
||||
subghz_protocol_faac_slh_check_remote_controller(instance);
|
||||
#include "subghz_protocol_faac_slh.h"
|
||||
|
||||
struct SubGhzProtocolFaacSLH {
|
||||
SubGhzProtocolCommon common;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
FaacSLHDecoderStepReset = 0,
|
||||
FaacSLHDecoderStepFoundPreambula,
|
||||
FaacSLHDecoderStepSaveDuration,
|
||||
FaacSLHDecoderStepCheckDuration,
|
||||
} FaacSLHDecoderStep;
|
||||
|
||||
SubGhzProtocolFaacSLH* subghz_protocol_faac_slh_alloc(void) {
|
||||
SubGhzProtocolFaacSLH* instance = furi_alloc(sizeof(SubGhzProtocolFaacSLH));
|
||||
|
||||
instance->common.name = "Faac SLH";
|
||||
instance->common.code_min_count_bit_for_found = 64;
|
||||
instance->common.te_short = 255;
|
||||
instance->common.te_long = 595;
|
||||
instance->common.te_delta = 100;
|
||||
instance->common.type_protocol = SubGhzProtocolCommonTypeDynamic;
|
||||
instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_protocol_faac_slh_to_str;
|
||||
instance->common.to_load_protocol =
|
||||
(SubGhzProtocolCommonLoadFromRAW)subghz_decoder_faac_slh_to_load_protocol;
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void subghz_protocol_faac_slh_free(SubGhzProtocolFaacSLH* instance) {
|
||||
furi_assert(instance);
|
||||
free(instance);
|
||||
}
|
||||
|
||||
/** Send bit
|
||||
*
|
||||
* @param instance - SubGhzProtocolFaacSLH instance
|
||||
* @param bit - bit
|
||||
*/
|
||||
void subghz_protocol_faac_slh_send_bit(SubGhzProtocolFaacSLH* instance, uint8_t bit) {
|
||||
if(bit) {
|
||||
//send bit 1
|
||||
SUBGHZ_TX_PIN_HIGH();
|
||||
delay_us(instance->common.te_long);
|
||||
SUBGHZ_TX_PIN_LOW();
|
||||
delay_us(instance->common.te_short);
|
||||
} else {
|
||||
//send bit 0
|
||||
SUBGHZ_TX_PIN_HIGH();
|
||||
delay_us(instance->common.te_short);
|
||||
SUBGHZ_TX_PIN_LOW();
|
||||
delay_us(instance->common.te_long);
|
||||
}
|
||||
}
|
||||
|
||||
void subghz_protocol_faac_slh_send_key(
|
||||
SubGhzProtocolFaacSLH* instance,
|
||||
uint64_t key,
|
||||
uint8_t bit,
|
||||
uint8_t repeat) {
|
||||
while(repeat--) {
|
||||
SUBGHZ_TX_PIN_HIGH();
|
||||
//Send header
|
||||
delay_us(instance->common.te_long * 2);
|
||||
SUBGHZ_TX_PIN_LOW();
|
||||
delay_us(instance->common.te_long * 2);
|
||||
//Send key data
|
||||
for(uint8_t i = bit; i > 0; i--) {
|
||||
subghz_protocol_faac_slh_send_bit(instance, bit_read(key, i - 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void subghz_protocol_faac_slh_reset(SubGhzProtocolFaacSLH* instance) {
|
||||
instance->common.parser_step = FaacSLHDecoderStepReset;
|
||||
}
|
||||
|
||||
/** Analysis of received data
|
||||
*
|
||||
* @param instance SubGhzProtocolFaacSLH instance
|
||||
*/
|
||||
void subghz_protocol_faac_slh_check_remote_controller(SubGhzProtocolFaacSLH* instance) {
|
||||
uint64_t code_found_reverse = subghz_protocol_common_reverse_key(
|
||||
instance->common.code_last_found, instance->common.code_last_count_bit);
|
||||
uint32_t code_fix = code_found_reverse & 0xFFFFFFFF;
|
||||
//uint32_t code_hop = (code_found_reverse >> 24) & 0xFFFFF;
|
||||
|
||||
instance->common.serial = code_fix & 0xFFFFFFF;
|
||||
instance->common.btn = (code_fix >> 28) & 0x0F;
|
||||
}
|
||||
|
||||
void subghz_protocol_faac_slh_parse(SubGhzProtocolFaacSLH* instance, bool level, uint32_t duration) {
|
||||
switch(instance->common.parser_step) {
|
||||
case FaacSLHDecoderStepReset:
|
||||
if((level) && (DURATION_DIFF(duration, instance->common.te_long * 2) <
|
||||
instance->common.te_delta * 3)) {
|
||||
instance->common.parser_step = FaacSLHDecoderStepFoundPreambula;
|
||||
} else {
|
||||
instance->common.parser_step = FaacSLHDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case FaacSLHDecoderStepFoundPreambula:
|
||||
if((!level) && (DURATION_DIFF(duration, instance->common.te_long * 2) <
|
||||
instance->common.te_delta * 3)) {
|
||||
//Found Preambula
|
||||
instance->common.parser_step = FaacSLHDecoderStepSaveDuration;
|
||||
instance->common.code_found = 0;
|
||||
instance->common.code_count_bit = 0;
|
||||
} else {
|
||||
instance->common.parser_step = FaacSLHDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case FaacSLHDecoderStepSaveDuration:
|
||||
if(level) {
|
||||
if(duration >= (instance->common.te_short * 3 + instance->common.te_delta)) {
|
||||
instance->common.parser_step = FaacSLHDecoderStepFoundPreambula;
|
||||
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_count_bit = instance->common.code_count_bit;
|
||||
if(instance->common.callback)
|
||||
instance->common.callback(
|
||||
(SubGhzProtocolCommon*)instance, instance->common.context);
|
||||
}
|
||||
instance->common.code_found = 0;
|
||||
instance->common.code_count_bit = 0;
|
||||
break;
|
||||
} else {
|
||||
instance->common.te_last = duration;
|
||||
instance->common.parser_step = FaacSLHDecoderStepCheckDuration;
|
||||
}
|
||||
|
||||
} else {
|
||||
instance->common.parser_step = FaacSLHDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case FaacSLHDecoderStepCheckDuration:
|
||||
if(!level) {
|
||||
if((DURATION_DIFF(instance->common.te_last, instance->common.te_short) <
|
||||
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 = FaacSLHDecoderStepSaveDuration;
|
||||
} else if(
|
||||
(DURATION_DIFF(instance->common.te_last, instance->common.te_long) <
|
||||
instance->common.te_delta) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta)) {
|
||||
subghz_protocol_common_add_bit(&instance->common, 1);
|
||||
instance->common.parser_step = FaacSLHDecoderStepSaveDuration;
|
||||
} else {
|
||||
instance->common.parser_step = FaacSLHDecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
instance->common.parser_step = FaacSLHDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void subghz_protocol_faac_slh_to_str(SubGhzProtocolFaacSLH* instance, string_t output) {
|
||||
subghz_protocol_faac_slh_check_remote_controller(instance);
|
||||
uint64_t code_found_reverse = subghz_protocol_common_reverse_key(
|
||||
instance->common.code_last_found, instance->common.code_last_count_bit);
|
||||
uint32_t code_fix = code_found_reverse & 0xFFFFFFFF;
|
||||
uint32_t code_hop = (code_found_reverse >> 32) & 0xFFFFFFFF;
|
||||
|
||||
string_cat_printf(
|
||||
output,
|
||||
"%s %dbit\r\n"
|
||||
"Key:0x%lX%08lX\r\n"
|
||||
"Fix:%08lX \r\n"
|
||||
"Hop:%08lX \r\n"
|
||||
"Sn:%07lX Btn:%lX\r\n",
|
||||
instance->common.name,
|
||||
instance->common.code_last_count_bit,
|
||||
(uint32_t)(instance->common.code_last_found >> 32),
|
||||
(uint32_t)instance->common.code_last_found,
|
||||
code_fix,
|
||||
code_hop,
|
||||
instance->common.serial,
|
||||
instance->common.btn);
|
||||
}
|
||||
|
||||
void subghz_decoder_faac_slh_to_load_protocol(SubGhzProtocolFaacSLH* instance, void* context) {
|
||||
furi_assert(context);
|
||||
furi_assert(instance);
|
||||
SubGhzProtocolCommonLoad* data = context;
|
||||
instance->common.code_last_found = data->code_found;
|
||||
instance->common.code_last_count_bit = data->code_count_bit;
|
||||
subghz_protocol_faac_slh_check_remote_controller(instance);
|
||||
}
|
@@ -1,58 +1,58 @@
|
||||
#pragma once
|
||||
|
||||
#include "subghz_protocol_common.h"
|
||||
|
||||
typedef struct SubGhzProtocolFaacSLH SubGhzProtocolFaacSLH;
|
||||
|
||||
/** Allocate SubGhzProtocolFaacSLH
|
||||
*
|
||||
* @return SubGhzProtocolFaacSLH*
|
||||
*/
|
||||
SubGhzProtocolFaacSLH* subghz_protocol_faac_slh_alloc();
|
||||
|
||||
/** Free SubGhzProtocolFaacSLH
|
||||
*
|
||||
* @param instance
|
||||
*/
|
||||
void subghz_protocol_faac_slh_free(SubGhzProtocolFaacSLH* instance);
|
||||
|
||||
/** Sends the key on the air
|
||||
*
|
||||
* @param instance - SubGhzProtocolFaacSLH instance
|
||||
* @param key - key send
|
||||
* @param bit - count bit key
|
||||
* @param repeat - repeat send key
|
||||
*/
|
||||
void subghz_protocol_faac_slh_send_key(SubGhzProtocolFaacSLH* instance, uint64_t key, uint8_t bit, uint8_t repeat);
|
||||
|
||||
/** Reset internal state
|
||||
* @param instance - SubGhzProtocolFaacSLH instance
|
||||
*/
|
||||
void subghz_protocol_faac_slh_reset(SubGhzProtocolFaacSLH* instance);
|
||||
|
||||
/** Analysis of received data
|
||||
*
|
||||
* @param instance SubGhzProtocolFaacSLH instance
|
||||
*/
|
||||
void subghz_protocol_faac_slh_check_remote_controller(SubGhzProtocolFaacSLH* instance);
|
||||
|
||||
/** Parse accepted duration
|
||||
*
|
||||
* @param instance - SubGhzProtocolFaacSLH instance
|
||||
* @param data - LevelDuration level_duration
|
||||
*/
|
||||
void subghz_protocol_faac_slh_parse(SubGhzProtocolFaacSLH* instance, bool level, uint32_t duration);
|
||||
|
||||
/** Outputting information from the parser
|
||||
*
|
||||
* @param instance - SubGhzProtocolFaacSLH* instance
|
||||
* @param output - output string
|
||||
*/
|
||||
void subghz_protocol_faac_slh_to_str(SubGhzProtocolFaacSLH* instance, string_t output);
|
||||
|
||||
/** Loading protocol from bin data
|
||||
*
|
||||
* @param instance - SubGhzProtocolFaacSLH instance
|
||||
* @param context - SubGhzProtocolCommonLoad context
|
||||
*/
|
||||
void subghz_decoder_faac_slh_to_load_protocol(SubGhzProtocolFaacSLH* instance, void* context);
|
||||
#pragma once
|
||||
|
||||
#include "subghz_protocol_common.h"
|
||||
|
||||
typedef struct SubGhzProtocolFaacSLH SubGhzProtocolFaacSLH;
|
||||
|
||||
/** Allocate SubGhzProtocolFaacSLH
|
||||
*
|
||||
* @return SubGhzProtocolFaacSLH*
|
||||
*/
|
||||
SubGhzProtocolFaacSLH* subghz_protocol_faac_slh_alloc();
|
||||
|
||||
/** Free SubGhzProtocolFaacSLH
|
||||
*
|
||||
* @param instance
|
||||
*/
|
||||
void subghz_protocol_faac_slh_free(SubGhzProtocolFaacSLH* instance);
|
||||
|
||||
/** Sends the key on the air
|
||||
*
|
||||
* @param instance - SubGhzProtocolFaacSLH instance
|
||||
* @param key - key send
|
||||
* @param bit - count bit key
|
||||
* @param repeat - repeat send key
|
||||
*/
|
||||
void subghz_protocol_faac_slh_send_key(SubGhzProtocolFaacSLH* instance, uint64_t key, uint8_t bit, uint8_t repeat);
|
||||
|
||||
/** Reset internal state
|
||||
* @param instance - SubGhzProtocolFaacSLH instance
|
||||
*/
|
||||
void subghz_protocol_faac_slh_reset(SubGhzProtocolFaacSLH* instance);
|
||||
|
||||
/** Analysis of received data
|
||||
*
|
||||
* @param instance SubGhzProtocolFaacSLH instance
|
||||
*/
|
||||
void subghz_protocol_faac_slh_check_remote_controller(SubGhzProtocolFaacSLH* instance);
|
||||
|
||||
/** Parse accepted duration
|
||||
*
|
||||
* @param instance - SubGhzProtocolFaacSLH instance
|
||||
* @param data - LevelDuration level_duration
|
||||
*/
|
||||
void subghz_protocol_faac_slh_parse(SubGhzProtocolFaacSLH* instance, bool level, uint32_t duration);
|
||||
|
||||
/** Outputting information from the parser
|
||||
*
|
||||
* @param instance - SubGhzProtocolFaacSLH* instance
|
||||
* @param output - output string
|
||||
*/
|
||||
void subghz_protocol_faac_slh_to_str(SubGhzProtocolFaacSLH* instance, string_t output);
|
||||
|
||||
/** Loading protocol from bin data
|
||||
*
|
||||
* @param instance - SubGhzProtocolFaacSLH instance
|
||||
* @param context - SubGhzProtocolCommonLoad context
|
||||
*/
|
||||
void subghz_decoder_faac_slh_to_load_protocol(SubGhzProtocolFaacSLH* instance, void* context);
|
||||
|
@@ -1,230 +1,230 @@
|
||||
#include "subghz_protocol_gate_tx.h"
|
||||
|
||||
struct SubGhzProtocolGateTX {
|
||||
SubGhzProtocolCommon common;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
GateTXDecoderStepReset = 0,
|
||||
GateTXDecoderStepFoundStartBit,
|
||||
GateTXDecoderStepSaveDuration,
|
||||
GateTXDecoderStepCheckDuration,
|
||||
} GateTXDecoderStep;
|
||||
|
||||
SubGhzProtocolGateTX* subghz_protocol_gate_tx_alloc(void) {
|
||||
SubGhzProtocolGateTX* instance = furi_alloc(sizeof(SubGhzProtocolGateTX));
|
||||
|
||||
instance->common.name = "GateTX";
|
||||
instance->common.code_min_count_bit_for_found = 24;
|
||||
instance->common.te_short = 350;
|
||||
instance->common.te_long = 700;
|
||||
instance->common.te_delta = 100;
|
||||
instance->common.type_protocol = SubGhzProtocolCommonTypeStatic;
|
||||
instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_protocol_gate_tx_to_str;
|
||||
instance->common.to_save_string =
|
||||
(SubGhzProtocolCommonGetStrSave)subghz_protocol_gate_tx_to_save_str;
|
||||
instance->common.to_load_protocol_from_file =
|
||||
(SubGhzProtocolCommonLoadFromFile)subghz_protocol_gate_tx_to_load_protocol_from_file;
|
||||
instance->common.to_load_protocol =
|
||||
(SubGhzProtocolCommonLoadFromRAW)subghz_decoder_gate_tx_to_load_protocol;
|
||||
instance->common.get_upload_protocol =
|
||||
(SubGhzProtocolCommonEncoderGetUpLoad)subghz_protocol_gate_tx_send_key;
|
||||
return instance;
|
||||
}
|
||||
|
||||
void subghz_protocol_gate_tx_free(SubGhzProtocolGateTX* instance) {
|
||||
furi_assert(instance);
|
||||
free(instance);
|
||||
}
|
||||
|
||||
bool subghz_protocol_gate_tx_send_key(
|
||||
SubGhzProtocolGateTX* instance,
|
||||
SubGhzProtocolCommonEncoder* encoder) {
|
||||
furi_assert(instance);
|
||||
furi_assert(encoder);
|
||||
size_t index = 0;
|
||||
encoder->size_upload = (instance->common.code_last_count_bit * 2) + 2;
|
||||
if(encoder->size_upload > SUBGHZ_ENCODER_UPLOAD_MAX_SIZE) return false;
|
||||
//Send header
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(false, (uint32_t)instance->common.te_short * 49);
|
||||
//Send start bit
|
||||
encoder->upload[index++] = level_duration_make(true, (uint32_t)instance->common.te_long);
|
||||
//Send key data
|
||||
for(uint8_t i = instance->common.code_last_count_bit; i > 0; i--) {
|
||||
if(bit_read(instance->common.code_last_found, i - 1)) {
|
||||
//send bit 1
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(false, (uint32_t)instance->common.te_long);
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(true, (uint32_t)instance->common.te_short);
|
||||
} else {
|
||||
//send bit 0
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(false, (uint32_t)instance->common.te_short);
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(true, (uint32_t)instance->common.te_long);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void subghz_protocol_gate_tx_reset(SubGhzProtocolGateTX* instance) {
|
||||
instance->common.parser_step = GateTXDecoderStepReset;
|
||||
}
|
||||
|
||||
/** Analysis of received data
|
||||
*
|
||||
* @param instance SubGhzProtocolFaacSLH instance
|
||||
*/
|
||||
void subghz_protocol_gate_tx_check_remote_controller(SubGhzProtocolGateTX* instance) {
|
||||
uint32_t code_found_reverse = subghz_protocol_common_reverse_key(
|
||||
instance->common.code_last_found, instance->common.code_last_count_bit);
|
||||
|
||||
instance->common.serial = (code_found_reverse & 0xFF) << 12 |
|
||||
((code_found_reverse >> 8) & 0xFF) << 4 |
|
||||
((code_found_reverse >> 20) & 0x0F);
|
||||
instance->common.btn = ((code_found_reverse >> 16) & 0x0F);
|
||||
}
|
||||
|
||||
void subghz_protocol_gate_tx_parse(SubGhzProtocolGateTX* instance, bool level, uint32_t duration) {
|
||||
switch(instance->common.parser_step) {
|
||||
case GateTXDecoderStepReset:
|
||||
if((!level) && (DURATION_DIFF(duration, instance->common.te_short * 47) <
|
||||
instance->common.te_delta * 47)) {
|
||||
//Found Preambula
|
||||
instance->common.parser_step = GateTXDecoderStepFoundStartBit;
|
||||
} else {
|
||||
instance->common.parser_step = GateTXDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case GateTXDecoderStepFoundStartBit:
|
||||
if(level &&
|
||||
((DURATION_DIFF(duration, instance->common.te_long) < instance->common.te_delta * 3))) {
|
||||
//Found start bit
|
||||
instance->common.parser_step = GateTXDecoderStepSaveDuration;
|
||||
instance->common.code_found = 0;
|
||||
instance->common.code_count_bit = 0;
|
||||
} else {
|
||||
instance->common.parser_step = GateTXDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case GateTXDecoderStepSaveDuration:
|
||||
if(!level) {
|
||||
if(duration >= (instance->common.te_short * 10 + instance->common.te_delta)) {
|
||||
instance->common.parser_step = GateTXDecoderStepFoundStartBit;
|
||||
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_count_bit = instance->common.code_count_bit;
|
||||
|
||||
if(instance->common.callback)
|
||||
instance->common.callback(
|
||||
(SubGhzProtocolCommon*)instance, instance->common.context);
|
||||
}
|
||||
instance->common.code_found = 0;
|
||||
instance->common.code_count_bit = 0;
|
||||
break;
|
||||
} else {
|
||||
instance->common.te_last = duration;
|
||||
instance->common.parser_step = GateTXDecoderStepCheckDuration;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GateTXDecoderStepCheckDuration:
|
||||
if(level) {
|
||||
if((DURATION_DIFF(instance->common.te_last, instance->common.te_short) <
|
||||
instance->common.te_delta) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_long) <
|
||||
instance->common.te_delta * 3)) {
|
||||
subghz_protocol_common_add_bit(&instance->common, 0);
|
||||
instance->common.parser_step = GateTXDecoderStepSaveDuration;
|
||||
} else if(
|
||||
(DURATION_DIFF(instance->common.te_last, instance->common.te_long) <
|
||||
instance->common.te_delta * 3) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta)) {
|
||||
subghz_protocol_common_add_bit(&instance->common, 1);
|
||||
instance->common.parser_step = GateTXDecoderStepSaveDuration;
|
||||
} else {
|
||||
instance->common.parser_step = GateTXDecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
instance->common.parser_step = GateTXDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void subghz_protocol_gate_tx_to_str(SubGhzProtocolGateTX* instance, string_t output) {
|
||||
subghz_protocol_gate_tx_check_remote_controller(instance);
|
||||
string_cat_printf(
|
||||
output,
|
||||
"%s %dbit\r\n"
|
||||
"Key:%06lX\r\n"
|
||||
"Sn:%05lX Btn:%lX\r\n",
|
||||
instance->common.name,
|
||||
instance->common.code_last_count_bit,
|
||||
(uint32_t)(instance->common.code_last_found & 0xFFFFFF),
|
||||
instance->common.serial,
|
||||
instance->common.btn);
|
||||
}
|
||||
|
||||
void subghz_protocol_gate_tx_to_save_str(SubGhzProtocolGateTX* instance, string_t output) {
|
||||
string_printf(
|
||||
output,
|
||||
"Protocol: %s\n"
|
||||
"Bit: %d\n"
|
||||
"Key: %08lX\n",
|
||||
instance->common.name,
|
||||
instance->common.code_last_count_bit,
|
||||
(uint32_t)(instance->common.code_last_found & 0x00000000ffffffff));
|
||||
}
|
||||
|
||||
bool subghz_protocol_gate_tx_to_load_protocol_from_file(
|
||||
FileWorker* file_worker,
|
||||
SubGhzProtocolGateTX* instance) {
|
||||
bool loaded = false;
|
||||
string_t temp_str;
|
||||
string_init(temp_str);
|
||||
int res = 0;
|
||||
int data = 0;
|
||||
|
||||
do {
|
||||
// Read and parse bit data from 2nd line
|
||||
if(!file_worker_read_until(file_worker, temp_str, '\n')) {
|
||||
break;
|
||||
}
|
||||
res = sscanf(string_get_cstr(temp_str), "Bit: %d\n", &data);
|
||||
if(res != 1) {
|
||||
break;
|
||||
}
|
||||
instance->common.code_last_count_bit = (uint8_t)data;
|
||||
|
||||
// Read and parse key data from 3nd line
|
||||
if(!file_worker_read_until(file_worker, temp_str, '\n')) {
|
||||
break;
|
||||
}
|
||||
uint32_t temp_key = 0;
|
||||
res = sscanf(string_get_cstr(temp_str), "Key: %08lX\n", &temp_key);
|
||||
if(res != 1) {
|
||||
break;
|
||||
}
|
||||
instance->common.code_last_found = (uint64_t)temp_key;
|
||||
subghz_protocol_gate_tx_check_remote_controller(instance);
|
||||
|
||||
loaded = true;
|
||||
} while(0);
|
||||
|
||||
string_clear(temp_str);
|
||||
|
||||
return loaded;
|
||||
}
|
||||
|
||||
void subghz_decoder_gate_tx_to_load_protocol(SubGhzProtocolGateTX* instance, void* context) {
|
||||
furi_assert(context);
|
||||
furi_assert(instance);
|
||||
SubGhzProtocolCommonLoad* data = context;
|
||||
instance->common.code_last_found = data->code_found;
|
||||
instance->common.code_last_count_bit = data->code_count_bit;
|
||||
subghz_protocol_gate_tx_check_remote_controller(instance);
|
||||
#include "subghz_protocol_gate_tx.h"
|
||||
|
||||
struct SubGhzProtocolGateTX {
|
||||
SubGhzProtocolCommon common;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
GateTXDecoderStepReset = 0,
|
||||
GateTXDecoderStepFoundStartBit,
|
||||
GateTXDecoderStepSaveDuration,
|
||||
GateTXDecoderStepCheckDuration,
|
||||
} GateTXDecoderStep;
|
||||
|
||||
SubGhzProtocolGateTX* subghz_protocol_gate_tx_alloc(void) {
|
||||
SubGhzProtocolGateTX* instance = furi_alloc(sizeof(SubGhzProtocolGateTX));
|
||||
|
||||
instance->common.name = "GateTX";
|
||||
instance->common.code_min_count_bit_for_found = 24;
|
||||
instance->common.te_short = 350;
|
||||
instance->common.te_long = 700;
|
||||
instance->common.te_delta = 100;
|
||||
instance->common.type_protocol = SubGhzProtocolCommonTypeStatic;
|
||||
instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_protocol_gate_tx_to_str;
|
||||
instance->common.to_save_string =
|
||||
(SubGhzProtocolCommonGetStrSave)subghz_protocol_gate_tx_to_save_str;
|
||||
instance->common.to_load_protocol_from_file =
|
||||
(SubGhzProtocolCommonLoadFromFile)subghz_protocol_gate_tx_to_load_protocol_from_file;
|
||||
instance->common.to_load_protocol =
|
||||
(SubGhzProtocolCommonLoadFromRAW)subghz_decoder_gate_tx_to_load_protocol;
|
||||
instance->common.get_upload_protocol =
|
||||
(SubGhzProtocolCommonEncoderGetUpLoad)subghz_protocol_gate_tx_send_key;
|
||||
return instance;
|
||||
}
|
||||
|
||||
void subghz_protocol_gate_tx_free(SubGhzProtocolGateTX* instance) {
|
||||
furi_assert(instance);
|
||||
free(instance);
|
||||
}
|
||||
|
||||
bool subghz_protocol_gate_tx_send_key(
|
||||
SubGhzProtocolGateTX* instance,
|
||||
SubGhzProtocolCommonEncoder* encoder) {
|
||||
furi_assert(instance);
|
||||
furi_assert(encoder);
|
||||
size_t index = 0;
|
||||
encoder->size_upload = (instance->common.code_last_count_bit * 2) + 2;
|
||||
if(encoder->size_upload > SUBGHZ_ENCODER_UPLOAD_MAX_SIZE) return false;
|
||||
//Send header
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(false, (uint32_t)instance->common.te_short * 49);
|
||||
//Send start bit
|
||||
encoder->upload[index++] = level_duration_make(true, (uint32_t)instance->common.te_long);
|
||||
//Send key data
|
||||
for(uint8_t i = instance->common.code_last_count_bit; i > 0; i--) {
|
||||
if(bit_read(instance->common.code_last_found, i - 1)) {
|
||||
//send bit 1
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(false, (uint32_t)instance->common.te_long);
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(true, (uint32_t)instance->common.te_short);
|
||||
} else {
|
||||
//send bit 0
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(false, (uint32_t)instance->common.te_short);
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(true, (uint32_t)instance->common.te_long);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void subghz_protocol_gate_tx_reset(SubGhzProtocolGateTX* instance) {
|
||||
instance->common.parser_step = GateTXDecoderStepReset;
|
||||
}
|
||||
|
||||
/** Analysis of received data
|
||||
*
|
||||
* @param instance SubGhzProtocolFaacSLH instance
|
||||
*/
|
||||
void subghz_protocol_gate_tx_check_remote_controller(SubGhzProtocolGateTX* instance) {
|
||||
uint32_t code_found_reverse = subghz_protocol_common_reverse_key(
|
||||
instance->common.code_last_found, instance->common.code_last_count_bit);
|
||||
|
||||
instance->common.serial = (code_found_reverse & 0xFF) << 12 |
|
||||
((code_found_reverse >> 8) & 0xFF) << 4 |
|
||||
((code_found_reverse >> 20) & 0x0F);
|
||||
instance->common.btn = ((code_found_reverse >> 16) & 0x0F);
|
||||
}
|
||||
|
||||
void subghz_protocol_gate_tx_parse(SubGhzProtocolGateTX* instance, bool level, uint32_t duration) {
|
||||
switch(instance->common.parser_step) {
|
||||
case GateTXDecoderStepReset:
|
||||
if((!level) && (DURATION_DIFF(duration, instance->common.te_short * 47) <
|
||||
instance->common.te_delta * 47)) {
|
||||
//Found Preambula
|
||||
instance->common.parser_step = GateTXDecoderStepFoundStartBit;
|
||||
} else {
|
||||
instance->common.parser_step = GateTXDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case GateTXDecoderStepFoundStartBit:
|
||||
if(level &&
|
||||
((DURATION_DIFF(duration, instance->common.te_long) < instance->common.te_delta * 3))) {
|
||||
//Found start bit
|
||||
instance->common.parser_step = GateTXDecoderStepSaveDuration;
|
||||
instance->common.code_found = 0;
|
||||
instance->common.code_count_bit = 0;
|
||||
} else {
|
||||
instance->common.parser_step = GateTXDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case GateTXDecoderStepSaveDuration:
|
||||
if(!level) {
|
||||
if(duration >= (instance->common.te_short * 10 + instance->common.te_delta)) {
|
||||
instance->common.parser_step = GateTXDecoderStepFoundStartBit;
|
||||
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_count_bit = instance->common.code_count_bit;
|
||||
|
||||
if(instance->common.callback)
|
||||
instance->common.callback(
|
||||
(SubGhzProtocolCommon*)instance, instance->common.context);
|
||||
}
|
||||
instance->common.code_found = 0;
|
||||
instance->common.code_count_bit = 0;
|
||||
break;
|
||||
} else {
|
||||
instance->common.te_last = duration;
|
||||
instance->common.parser_step = GateTXDecoderStepCheckDuration;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GateTXDecoderStepCheckDuration:
|
||||
if(level) {
|
||||
if((DURATION_DIFF(instance->common.te_last, instance->common.te_short) <
|
||||
instance->common.te_delta) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_long) <
|
||||
instance->common.te_delta * 3)) {
|
||||
subghz_protocol_common_add_bit(&instance->common, 0);
|
||||
instance->common.parser_step = GateTXDecoderStepSaveDuration;
|
||||
} else if(
|
||||
(DURATION_DIFF(instance->common.te_last, instance->common.te_long) <
|
||||
instance->common.te_delta * 3) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta)) {
|
||||
subghz_protocol_common_add_bit(&instance->common, 1);
|
||||
instance->common.parser_step = GateTXDecoderStepSaveDuration;
|
||||
} else {
|
||||
instance->common.parser_step = GateTXDecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
instance->common.parser_step = GateTXDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void subghz_protocol_gate_tx_to_str(SubGhzProtocolGateTX* instance, string_t output) {
|
||||
subghz_protocol_gate_tx_check_remote_controller(instance);
|
||||
string_cat_printf(
|
||||
output,
|
||||
"%s %dbit\r\n"
|
||||
"Key:%06lX\r\n"
|
||||
"Sn:%05lX Btn:%lX\r\n",
|
||||
instance->common.name,
|
||||
instance->common.code_last_count_bit,
|
||||
(uint32_t)(instance->common.code_last_found & 0xFFFFFF),
|
||||
instance->common.serial,
|
||||
instance->common.btn);
|
||||
}
|
||||
|
||||
void subghz_protocol_gate_tx_to_save_str(SubGhzProtocolGateTX* instance, string_t output) {
|
||||
string_printf(
|
||||
output,
|
||||
"Protocol: %s\n"
|
||||
"Bit: %d\n"
|
||||
"Key: %08lX\n",
|
||||
instance->common.name,
|
||||
instance->common.code_last_count_bit,
|
||||
(uint32_t)(instance->common.code_last_found & 0x00000000ffffffff));
|
||||
}
|
||||
|
||||
bool subghz_protocol_gate_tx_to_load_protocol_from_file(
|
||||
FileWorker* file_worker,
|
||||
SubGhzProtocolGateTX* instance) {
|
||||
bool loaded = false;
|
||||
string_t temp_str;
|
||||
string_init(temp_str);
|
||||
int res = 0;
|
||||
int data = 0;
|
||||
|
||||
do {
|
||||
// Read and parse bit data from 2nd line
|
||||
if(!file_worker_read_until(file_worker, temp_str, '\n')) {
|
||||
break;
|
||||
}
|
||||
res = sscanf(string_get_cstr(temp_str), "Bit: %d\n", &data);
|
||||
if(res != 1) {
|
||||
break;
|
||||
}
|
||||
instance->common.code_last_count_bit = (uint8_t)data;
|
||||
|
||||
// Read and parse key data from 3nd line
|
||||
if(!file_worker_read_until(file_worker, temp_str, '\n')) {
|
||||
break;
|
||||
}
|
||||
uint32_t temp_key = 0;
|
||||
res = sscanf(string_get_cstr(temp_str), "Key: %08lX\n", &temp_key);
|
||||
if(res != 1) {
|
||||
break;
|
||||
}
|
||||
instance->common.code_last_found = (uint64_t)temp_key;
|
||||
subghz_protocol_gate_tx_check_remote_controller(instance);
|
||||
|
||||
loaded = true;
|
||||
} while(0);
|
||||
|
||||
string_clear(temp_str);
|
||||
|
||||
return loaded;
|
||||
}
|
||||
|
||||
void subghz_decoder_gate_tx_to_load_protocol(SubGhzProtocolGateTX* instance, void* context) {
|
||||
furi_assert(context);
|
||||
furi_assert(instance);
|
||||
SubGhzProtocolCommonLoad* data = context;
|
||||
instance->common.code_last_found = data->code_found;
|
||||
instance->common.code_last_count_bit = data->code_count_bit;
|
||||
subghz_protocol_gate_tx_check_remote_controller(instance);
|
||||
}
|
@@ -1,66 +1,66 @@
|
||||
#pragma once
|
||||
|
||||
#include "subghz_protocol_common.h"
|
||||
|
||||
typedef struct SubGhzProtocolGateTX SubGhzProtocolGateTX;
|
||||
|
||||
/** Allocate SubGhzProtocolGateTX
|
||||
*
|
||||
* @return SubGhzProtocolGateTX*
|
||||
*/
|
||||
SubGhzProtocolGateTX* subghz_protocol_gate_tx_alloc();
|
||||
|
||||
/** Free SubGhzProtocolGateTX
|
||||
*
|
||||
* @param instance
|
||||
*/
|
||||
void subghz_protocol_gate_tx_free(SubGhzProtocolGateTX* instance);
|
||||
|
||||
/** Get upload protocol
|
||||
*
|
||||
* @param instance - SubGhzProtocolGateTX instance
|
||||
* @param encoder - SubGhzProtocolCommonEncoder encoder
|
||||
* @return bool
|
||||
*/
|
||||
bool subghz_protocol_gate_tx_send_key(SubGhzProtocolGateTX* instance, SubGhzProtocolCommonEncoder* encoder);
|
||||
|
||||
/** Reset internal state
|
||||
* @param instance - SubGhzProtocolGateTX instance
|
||||
*/
|
||||
void subghz_protocol_gate_tx_reset(SubGhzProtocolGateTX* instance);
|
||||
|
||||
/** Parse accepted duration
|
||||
*
|
||||
* @param instance - SubGhzProtocolGateTX instance
|
||||
* @param data - LevelDuration level_duration
|
||||
*/
|
||||
void subghz_protocol_gate_tx_parse(SubGhzProtocolGateTX* instance, bool level, uint32_t duration);
|
||||
|
||||
/** Outputting information from the parser
|
||||
*
|
||||
* @param instance - SubGhzProtocolFaacSLH* instance
|
||||
* @param output - output string
|
||||
*/
|
||||
void subghz_protocol_gate_tx_to_str(SubGhzProtocolGateTX* instance, string_t output);
|
||||
|
||||
/** Get a string to save the protocol
|
||||
*
|
||||
* @param instance - SubGhzProtocolGateTX instance
|
||||
* @param output - the resulting string
|
||||
*/
|
||||
void subghz_protocol_gate_tx_to_save_str(SubGhzProtocolGateTX* instance, string_t output);
|
||||
|
||||
/** Loading protocol from file
|
||||
*
|
||||
* @param file_worker - FileWorker file_worker
|
||||
* @param instance - SubGhzProtocolGateTX instance
|
||||
* @return bool
|
||||
*/
|
||||
bool subghz_protocol_gate_tx_to_load_protocol_from_file(FileWorker* file_worker, SubGhzProtocolGateTX* instance);
|
||||
|
||||
/** Loading protocol from bin data
|
||||
*
|
||||
* @param instance - SubGhzProtocolGateTX instance
|
||||
* @param context - SubGhzProtocolCommonLoad context
|
||||
*/
|
||||
void subghz_decoder_gate_tx_to_load_protocol(SubGhzProtocolGateTX* instance, void* context);
|
||||
#pragma once
|
||||
|
||||
#include "subghz_protocol_common.h"
|
||||
|
||||
typedef struct SubGhzProtocolGateTX SubGhzProtocolGateTX;
|
||||
|
||||
/** Allocate SubGhzProtocolGateTX
|
||||
*
|
||||
* @return SubGhzProtocolGateTX*
|
||||
*/
|
||||
SubGhzProtocolGateTX* subghz_protocol_gate_tx_alloc();
|
||||
|
||||
/** Free SubGhzProtocolGateTX
|
||||
*
|
||||
* @param instance
|
||||
*/
|
||||
void subghz_protocol_gate_tx_free(SubGhzProtocolGateTX* instance);
|
||||
|
||||
/** Get upload protocol
|
||||
*
|
||||
* @param instance - SubGhzProtocolGateTX instance
|
||||
* @param encoder - SubGhzProtocolCommonEncoder encoder
|
||||
* @return bool
|
||||
*/
|
||||
bool subghz_protocol_gate_tx_send_key(SubGhzProtocolGateTX* instance, SubGhzProtocolCommonEncoder* encoder);
|
||||
|
||||
/** Reset internal state
|
||||
* @param instance - SubGhzProtocolGateTX instance
|
||||
*/
|
||||
void subghz_protocol_gate_tx_reset(SubGhzProtocolGateTX* instance);
|
||||
|
||||
/** Parse accepted duration
|
||||
*
|
||||
* @param instance - SubGhzProtocolGateTX instance
|
||||
* @param data - LevelDuration level_duration
|
||||
*/
|
||||
void subghz_protocol_gate_tx_parse(SubGhzProtocolGateTX* instance, bool level, uint32_t duration);
|
||||
|
||||
/** Outputting information from the parser
|
||||
*
|
||||
* @param instance - SubGhzProtocolFaacSLH* instance
|
||||
* @param output - output string
|
||||
*/
|
||||
void subghz_protocol_gate_tx_to_str(SubGhzProtocolGateTX* instance, string_t output);
|
||||
|
||||
/** Get a string to save the protocol
|
||||
*
|
||||
* @param instance - SubGhzProtocolGateTX instance
|
||||
* @param output - the resulting string
|
||||
*/
|
||||
void subghz_protocol_gate_tx_to_save_str(SubGhzProtocolGateTX* instance, string_t output);
|
||||
|
||||
/** Loading protocol from file
|
||||
*
|
||||
* @param file_worker - FileWorker file_worker
|
||||
* @param instance - SubGhzProtocolGateTX instance
|
||||
* @return bool
|
||||
*/
|
||||
bool subghz_protocol_gate_tx_to_load_protocol_from_file(FileWorker* file_worker, SubGhzProtocolGateTX* instance);
|
||||
|
||||
/** Loading protocol from bin data
|
||||
*
|
||||
* @param instance - SubGhzProtocolGateTX instance
|
||||
* @param context - SubGhzProtocolCommonLoad context
|
||||
*/
|
||||
void subghz_decoder_gate_tx_to_load_protocol(SubGhzProtocolGateTX* instance, void* context);
|
||||
|
@@ -1,191 +1,191 @@
|
||||
#include "subghz_protocol_ido.h"
|
||||
|
||||
struct SubGhzProtocolIDo {
|
||||
SubGhzProtocolCommon common;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
IDoDecoderStepReset = 0,
|
||||
IDoDecoderStepFoundPreambula,
|
||||
IDoDecoderStepSaveDuration,
|
||||
IDoDecoderStepCheckDuration,
|
||||
} IDoDecoderStep;
|
||||
|
||||
SubGhzProtocolIDo* subghz_protocol_ido_alloc(void) {
|
||||
SubGhzProtocolIDo* instance = furi_alloc(sizeof(SubGhzProtocolIDo));
|
||||
|
||||
instance->common.name = "iDo 117/111"; // PT4301-X";
|
||||
instance->common.code_min_count_bit_for_found = 48;
|
||||
instance->common.te_short = 450;
|
||||
instance->common.te_long = 1450;
|
||||
instance->common.te_delta = 150;
|
||||
instance->common.type_protocol = SubGhzProtocolCommonTypeDynamic;
|
||||
instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_protocol_ido_to_str;
|
||||
instance->common.to_load_protocol =
|
||||
(SubGhzProtocolCommonLoadFromRAW)subghz_decoder_ido_to_load_protocol;
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void subghz_protocol_ido_free(SubGhzProtocolIDo* instance) {
|
||||
furi_assert(instance);
|
||||
free(instance);
|
||||
}
|
||||
|
||||
/** Send bit
|
||||
*
|
||||
* @param instance - SubGhzProtocolIDo instance
|
||||
* @param bit - bit
|
||||
*/
|
||||
void subghz_protocol_ido_send_bit(SubGhzProtocolIDo* instance, uint8_t bit) {
|
||||
if(bit) {
|
||||
//send bit 1
|
||||
SUBGHZ_TX_PIN_HIGH();
|
||||
delay_us(instance->common.te_short);
|
||||
SUBGHZ_TX_PIN_LOW();
|
||||
delay_us(instance->common.te_short);
|
||||
} else {
|
||||
//send bit 0
|
||||
SUBGHZ_TX_PIN_HIGH();
|
||||
delay_us(instance->common.te_short);
|
||||
SUBGHZ_TX_PIN_LOW();
|
||||
delay_us(instance->common.te_long);
|
||||
}
|
||||
}
|
||||
|
||||
void subghz_protocol_ido_send_key(
|
||||
SubGhzProtocolIDo* instance,
|
||||
uint64_t key,
|
||||
uint8_t bit,
|
||||
uint8_t repeat) {
|
||||
while(repeat--) {
|
||||
SUBGHZ_TX_PIN_HIGH();
|
||||
//Send header
|
||||
delay_us(instance->common.te_short * 10);
|
||||
SUBGHZ_TX_PIN_LOW();
|
||||
delay_us(instance->common.te_short * 10);
|
||||
//Send key data
|
||||
for(uint8_t i = bit; i > 0; i--) {
|
||||
subghz_protocol_ido_send_bit(instance, bit_read(key, i - 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void subghz_protocol_ido_reset(SubGhzProtocolIDo* instance) {
|
||||
instance->common.parser_step = IDoDecoderStepReset;
|
||||
}
|
||||
|
||||
/** Analysis of received data
|
||||
*
|
||||
* @param instance SubGhzProtocolIDo instance
|
||||
*/
|
||||
void subghz_protocol_ido_check_remote_controller(SubGhzProtocolIDo* instance) {
|
||||
uint64_t code_found_reverse = subghz_protocol_common_reverse_key(
|
||||
instance->common.code_last_found, instance->common.code_last_count_bit);
|
||||
uint32_t code_fix = code_found_reverse & 0xFFFFFF;
|
||||
|
||||
instance->common.serial = code_fix & 0xFFFFF;
|
||||
instance->common.btn = (code_fix >> 20) & 0x0F;
|
||||
}
|
||||
|
||||
void subghz_protocol_ido_parse(SubGhzProtocolIDo* instance, bool level, uint32_t duration) {
|
||||
switch(instance->common.parser_step) {
|
||||
case IDoDecoderStepReset:
|
||||
if((level) && (DURATION_DIFF(duration, instance->common.te_short * 10) <
|
||||
instance->common.te_delta * 5)) {
|
||||
instance->common.parser_step = IDoDecoderStepFoundPreambula;
|
||||
} else {
|
||||
instance->common.parser_step = IDoDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case IDoDecoderStepFoundPreambula:
|
||||
if((!level) && (DURATION_DIFF(duration, instance->common.te_short * 10) <
|
||||
instance->common.te_delta * 5)) {
|
||||
//Found Preambula
|
||||
instance->common.parser_step = IDoDecoderStepSaveDuration;
|
||||
instance->common.code_found = 0;
|
||||
instance->common.code_count_bit = 0;
|
||||
} else {
|
||||
instance->common.parser_step = IDoDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case IDoDecoderStepSaveDuration:
|
||||
if(level) {
|
||||
if(duration >= (instance->common.te_short * 5 + instance->common.te_delta)) {
|
||||
instance->common.parser_step = IDoDecoderStepFoundPreambula;
|
||||
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_count_bit = instance->common.code_count_bit;
|
||||
if(instance->common.callback)
|
||||
instance->common.callback(
|
||||
(SubGhzProtocolCommon*)instance, instance->common.context);
|
||||
}
|
||||
instance->common.code_found = 0;
|
||||
instance->common.code_count_bit = 0;
|
||||
break;
|
||||
} else {
|
||||
instance->common.te_last = duration;
|
||||
instance->common.parser_step = IDoDecoderStepCheckDuration;
|
||||
}
|
||||
|
||||
} else {
|
||||
instance->common.parser_step = IDoDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case IDoDecoderStepCheckDuration:
|
||||
if(!level) {
|
||||
if((DURATION_DIFF(instance->common.te_last, instance->common.te_short) <
|
||||
instance->common.te_delta) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_long) <
|
||||
instance->common.te_delta * 3)) {
|
||||
subghz_protocol_common_add_bit(&instance->common, 0);
|
||||
instance->common.parser_step = IDoDecoderStepSaveDuration;
|
||||
} else if(
|
||||
(DURATION_DIFF(instance->common.te_last, instance->common.te_short) <
|
||||
instance->common.te_delta * 3) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta)) {
|
||||
subghz_protocol_common_add_bit(&instance->common, 1);
|
||||
instance->common.parser_step = IDoDecoderStepSaveDuration;
|
||||
} else {
|
||||
instance->common.parser_step = IDoDecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
instance->common.parser_step = IDoDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void subghz_protocol_ido_to_str(SubGhzProtocolIDo* instance, string_t output) {
|
||||
subghz_protocol_ido_check_remote_controller(instance);
|
||||
uint64_t code_found_reverse = subghz_protocol_common_reverse_key(
|
||||
instance->common.code_last_found, instance->common.code_last_count_bit);
|
||||
uint32_t code_fix = code_found_reverse & 0xFFFFFF;
|
||||
uint32_t code_hop = (code_found_reverse >> 24) & 0xFFFFFF;
|
||||
|
||||
string_cat_printf(
|
||||
output,
|
||||
"%s %dbit\r\n"
|
||||
"Key:0x%lX%08lX\r\n"
|
||||
"Fix:%06lX \r\n"
|
||||
"Hop:%06lX \r\n"
|
||||
"Sn:%05lX Btn:%lX\r\n",
|
||||
instance->common.name,
|
||||
instance->common.code_last_count_bit,
|
||||
(uint32_t)(instance->common.code_last_found >> 32),
|
||||
(uint32_t)instance->common.code_last_found,
|
||||
code_fix,
|
||||
code_hop,
|
||||
instance->common.serial,
|
||||
instance->common.btn);
|
||||
}
|
||||
|
||||
void subghz_decoder_ido_to_load_protocol(SubGhzProtocolIDo* instance, void* context) {
|
||||
furi_assert(context);
|
||||
furi_assert(instance);
|
||||
SubGhzProtocolCommonLoad* data = context;
|
||||
instance->common.code_last_found = data->code_found;
|
||||
instance->common.code_last_count_bit = data->code_count_bit;
|
||||
subghz_protocol_ido_check_remote_controller(instance);
|
||||
#include "subghz_protocol_ido.h"
|
||||
|
||||
struct SubGhzProtocolIDo {
|
||||
SubGhzProtocolCommon common;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
IDoDecoderStepReset = 0,
|
||||
IDoDecoderStepFoundPreambula,
|
||||
IDoDecoderStepSaveDuration,
|
||||
IDoDecoderStepCheckDuration,
|
||||
} IDoDecoderStep;
|
||||
|
||||
SubGhzProtocolIDo* subghz_protocol_ido_alloc(void) {
|
||||
SubGhzProtocolIDo* instance = furi_alloc(sizeof(SubGhzProtocolIDo));
|
||||
|
||||
instance->common.name = "iDo 117/111"; // PT4301-X";
|
||||
instance->common.code_min_count_bit_for_found = 48;
|
||||
instance->common.te_short = 450;
|
||||
instance->common.te_long = 1450;
|
||||
instance->common.te_delta = 150;
|
||||
instance->common.type_protocol = SubGhzProtocolCommonTypeDynamic;
|
||||
instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_protocol_ido_to_str;
|
||||
instance->common.to_load_protocol =
|
||||
(SubGhzProtocolCommonLoadFromRAW)subghz_decoder_ido_to_load_protocol;
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void subghz_protocol_ido_free(SubGhzProtocolIDo* instance) {
|
||||
furi_assert(instance);
|
||||
free(instance);
|
||||
}
|
||||
|
||||
/** Send bit
|
||||
*
|
||||
* @param instance - SubGhzProtocolIDo instance
|
||||
* @param bit - bit
|
||||
*/
|
||||
void subghz_protocol_ido_send_bit(SubGhzProtocolIDo* instance, uint8_t bit) {
|
||||
if(bit) {
|
||||
//send bit 1
|
||||
SUBGHZ_TX_PIN_HIGH();
|
||||
delay_us(instance->common.te_short);
|
||||
SUBGHZ_TX_PIN_LOW();
|
||||
delay_us(instance->common.te_short);
|
||||
} else {
|
||||
//send bit 0
|
||||
SUBGHZ_TX_PIN_HIGH();
|
||||
delay_us(instance->common.te_short);
|
||||
SUBGHZ_TX_PIN_LOW();
|
||||
delay_us(instance->common.te_long);
|
||||
}
|
||||
}
|
||||
|
||||
void subghz_protocol_ido_send_key(
|
||||
SubGhzProtocolIDo* instance,
|
||||
uint64_t key,
|
||||
uint8_t bit,
|
||||
uint8_t repeat) {
|
||||
while(repeat--) {
|
||||
SUBGHZ_TX_PIN_HIGH();
|
||||
//Send header
|
||||
delay_us(instance->common.te_short * 10);
|
||||
SUBGHZ_TX_PIN_LOW();
|
||||
delay_us(instance->common.te_short * 10);
|
||||
//Send key data
|
||||
for(uint8_t i = bit; i > 0; i--) {
|
||||
subghz_protocol_ido_send_bit(instance, bit_read(key, i - 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void subghz_protocol_ido_reset(SubGhzProtocolIDo* instance) {
|
||||
instance->common.parser_step = IDoDecoderStepReset;
|
||||
}
|
||||
|
||||
/** Analysis of received data
|
||||
*
|
||||
* @param instance SubGhzProtocolIDo instance
|
||||
*/
|
||||
void subghz_protocol_ido_check_remote_controller(SubGhzProtocolIDo* instance) {
|
||||
uint64_t code_found_reverse = subghz_protocol_common_reverse_key(
|
||||
instance->common.code_last_found, instance->common.code_last_count_bit);
|
||||
uint32_t code_fix = code_found_reverse & 0xFFFFFF;
|
||||
|
||||
instance->common.serial = code_fix & 0xFFFFF;
|
||||
instance->common.btn = (code_fix >> 20) & 0x0F;
|
||||
}
|
||||
|
||||
void subghz_protocol_ido_parse(SubGhzProtocolIDo* instance, bool level, uint32_t duration) {
|
||||
switch(instance->common.parser_step) {
|
||||
case IDoDecoderStepReset:
|
||||
if((level) && (DURATION_DIFF(duration, instance->common.te_short * 10) <
|
||||
instance->common.te_delta * 5)) {
|
||||
instance->common.parser_step = IDoDecoderStepFoundPreambula;
|
||||
} else {
|
||||
instance->common.parser_step = IDoDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case IDoDecoderStepFoundPreambula:
|
||||
if((!level) && (DURATION_DIFF(duration, instance->common.te_short * 10) <
|
||||
instance->common.te_delta * 5)) {
|
||||
//Found Preambula
|
||||
instance->common.parser_step = IDoDecoderStepSaveDuration;
|
||||
instance->common.code_found = 0;
|
||||
instance->common.code_count_bit = 0;
|
||||
} else {
|
||||
instance->common.parser_step = IDoDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case IDoDecoderStepSaveDuration:
|
||||
if(level) {
|
||||
if(duration >= (instance->common.te_short * 5 + instance->common.te_delta)) {
|
||||
instance->common.parser_step = IDoDecoderStepFoundPreambula;
|
||||
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_count_bit = instance->common.code_count_bit;
|
||||
if(instance->common.callback)
|
||||
instance->common.callback(
|
||||
(SubGhzProtocolCommon*)instance, instance->common.context);
|
||||
}
|
||||
instance->common.code_found = 0;
|
||||
instance->common.code_count_bit = 0;
|
||||
break;
|
||||
} else {
|
||||
instance->common.te_last = duration;
|
||||
instance->common.parser_step = IDoDecoderStepCheckDuration;
|
||||
}
|
||||
|
||||
} else {
|
||||
instance->common.parser_step = IDoDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case IDoDecoderStepCheckDuration:
|
||||
if(!level) {
|
||||
if((DURATION_DIFF(instance->common.te_last, instance->common.te_short) <
|
||||
instance->common.te_delta) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_long) <
|
||||
instance->common.te_delta * 3)) {
|
||||
subghz_protocol_common_add_bit(&instance->common, 0);
|
||||
instance->common.parser_step = IDoDecoderStepSaveDuration;
|
||||
} else if(
|
||||
(DURATION_DIFF(instance->common.te_last, instance->common.te_short) <
|
||||
instance->common.te_delta * 3) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta)) {
|
||||
subghz_protocol_common_add_bit(&instance->common, 1);
|
||||
instance->common.parser_step = IDoDecoderStepSaveDuration;
|
||||
} else {
|
||||
instance->common.parser_step = IDoDecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
instance->common.parser_step = IDoDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void subghz_protocol_ido_to_str(SubGhzProtocolIDo* instance, string_t output) {
|
||||
subghz_protocol_ido_check_remote_controller(instance);
|
||||
uint64_t code_found_reverse = subghz_protocol_common_reverse_key(
|
||||
instance->common.code_last_found, instance->common.code_last_count_bit);
|
||||
uint32_t code_fix = code_found_reverse & 0xFFFFFF;
|
||||
uint32_t code_hop = (code_found_reverse >> 24) & 0xFFFFFF;
|
||||
|
||||
string_cat_printf(
|
||||
output,
|
||||
"%s %dbit\r\n"
|
||||
"Key:0x%lX%08lX\r\n"
|
||||
"Fix:%06lX \r\n"
|
||||
"Hop:%06lX \r\n"
|
||||
"Sn:%05lX Btn:%lX\r\n",
|
||||
instance->common.name,
|
||||
instance->common.code_last_count_bit,
|
||||
(uint32_t)(instance->common.code_last_found >> 32),
|
||||
(uint32_t)instance->common.code_last_found,
|
||||
code_fix,
|
||||
code_hop,
|
||||
instance->common.serial,
|
||||
instance->common.btn);
|
||||
}
|
||||
|
||||
void subghz_decoder_ido_to_load_protocol(SubGhzProtocolIDo* instance, void* context) {
|
||||
furi_assert(context);
|
||||
furi_assert(instance);
|
||||
SubGhzProtocolCommonLoad* data = context;
|
||||
instance->common.code_last_found = data->code_found;
|
||||
instance->common.code_last_count_bit = data->code_count_bit;
|
||||
subghz_protocol_ido_check_remote_controller(instance);
|
||||
}
|
@@ -1,58 +1,58 @@
|
||||
#pragma once
|
||||
|
||||
#include "subghz_protocol_common.h"
|
||||
|
||||
typedef struct SubGhzProtocolIDo SubGhzProtocolIDo;
|
||||
|
||||
/** Allocate SubGhzProtocolIDo
|
||||
*
|
||||
* @return SubGhzProtocolIDo*
|
||||
*/
|
||||
SubGhzProtocolIDo* subghz_protocol_ido_alloc();
|
||||
|
||||
/** Free SubGhzProtocolIDo
|
||||
*
|
||||
* @param instance
|
||||
*/
|
||||
void subghz_protocol_ido_free(SubGhzProtocolIDo* instance);
|
||||
|
||||
/** Sends the key on the air
|
||||
*
|
||||
* @param instance - SubGhzProtocolIDo instance
|
||||
* @param key - key send
|
||||
* @param bit - count bit key
|
||||
* @param repeat - repeat send key
|
||||
*/
|
||||
void subghz_protocol_ido_send_key(SubGhzProtocolIDo* instance, uint64_t key, uint8_t bit, uint8_t repeat);
|
||||
|
||||
/** Reset internal state
|
||||
* @param instance - SubGhzProtocolIDo instance
|
||||
*/
|
||||
void subghz_protocol_ido_reset(SubGhzProtocolIDo* instance);
|
||||
|
||||
/** Analysis of received data
|
||||
*
|
||||
* @param instance SubGhzProtocolIDo instance
|
||||
*/
|
||||
void subghz_protocol_ido_check_remote_controller(SubGhzProtocolIDo* instance);
|
||||
|
||||
/** Parse accepted duration
|
||||
*
|
||||
* @param instance - SubGhzProtocolIDo instance
|
||||
* @param data - LevelDuration level_duration
|
||||
*/
|
||||
void subghz_protocol_ido_parse(SubGhzProtocolIDo* instance, bool level, uint32_t duration);
|
||||
|
||||
/** Outputting information from the parser
|
||||
*
|
||||
* @param instance - SubGhzProtocolIDo* instance
|
||||
* @param output - output string
|
||||
*/
|
||||
void subghz_protocol_ido_to_str(SubGhzProtocolIDo* instance, string_t output);
|
||||
|
||||
/** Loading protocol from bin data
|
||||
*
|
||||
* @param instance - SubGhzProtocolIDo instance
|
||||
* @param context - SubGhzProtocolCommonLoad context
|
||||
*/
|
||||
void subghz_decoder_ido_to_load_protocol(SubGhzProtocolIDo* instance, void* context);
|
||||
#pragma once
|
||||
|
||||
#include "subghz_protocol_common.h"
|
||||
|
||||
typedef struct SubGhzProtocolIDo SubGhzProtocolIDo;
|
||||
|
||||
/** Allocate SubGhzProtocolIDo
|
||||
*
|
||||
* @return SubGhzProtocolIDo*
|
||||
*/
|
||||
SubGhzProtocolIDo* subghz_protocol_ido_alloc();
|
||||
|
||||
/** Free SubGhzProtocolIDo
|
||||
*
|
||||
* @param instance
|
||||
*/
|
||||
void subghz_protocol_ido_free(SubGhzProtocolIDo* instance);
|
||||
|
||||
/** Sends the key on the air
|
||||
*
|
||||
* @param instance - SubGhzProtocolIDo instance
|
||||
* @param key - key send
|
||||
* @param bit - count bit key
|
||||
* @param repeat - repeat send key
|
||||
*/
|
||||
void subghz_protocol_ido_send_key(SubGhzProtocolIDo* instance, uint64_t key, uint8_t bit, uint8_t repeat);
|
||||
|
||||
/** Reset internal state
|
||||
* @param instance - SubGhzProtocolIDo instance
|
||||
*/
|
||||
void subghz_protocol_ido_reset(SubGhzProtocolIDo* instance);
|
||||
|
||||
/** Analysis of received data
|
||||
*
|
||||
* @param instance SubGhzProtocolIDo instance
|
||||
*/
|
||||
void subghz_protocol_ido_check_remote_controller(SubGhzProtocolIDo* instance);
|
||||
|
||||
/** Parse accepted duration
|
||||
*
|
||||
* @param instance - SubGhzProtocolIDo instance
|
||||
* @param data - LevelDuration level_duration
|
||||
*/
|
||||
void subghz_protocol_ido_parse(SubGhzProtocolIDo* instance, bool level, uint32_t duration);
|
||||
|
||||
/** Outputting information from the parser
|
||||
*
|
||||
* @param instance - SubGhzProtocolIDo* instance
|
||||
* @param output - output string
|
||||
*/
|
||||
void subghz_protocol_ido_to_str(SubGhzProtocolIDo* instance, string_t output);
|
||||
|
||||
/** Loading protocol from bin data
|
||||
*
|
||||
* @param instance - SubGhzProtocolIDo instance
|
||||
* @param context - SubGhzProtocolCommonLoad context
|
||||
*/
|
||||
void subghz_decoder_ido_to_load_protocol(SubGhzProtocolIDo* instance, void* context);
|
||||
|
@@ -1,486 +1,486 @@
|
||||
#include "subghz_protocol_keeloq.h"
|
||||
#include "subghz_protocol_keeloq_common.h"
|
||||
|
||||
#include "../subghz_keystore.h"
|
||||
|
||||
#include <furi.h>
|
||||
|
||||
#include <m-string.h>
|
||||
|
||||
struct SubGhzProtocolKeeloq {
|
||||
SubGhzProtocolCommon common;
|
||||
SubGhzKeystore* keystore;
|
||||
const char* manufacture_name;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
KeeloqDecoderStepReset = 0,
|
||||
KeeloqDecoderStepCheckPreambula,
|
||||
KeeloqDecoderStepSaveDuration,
|
||||
KeeloqDecoderStepCheckDuration,
|
||||
} KeeloqDecoderStep;
|
||||
|
||||
SubGhzProtocolKeeloq* subghz_protocol_keeloq_alloc(SubGhzKeystore* keystore) {
|
||||
SubGhzProtocolKeeloq* instance = furi_alloc(sizeof(SubGhzProtocolKeeloq));
|
||||
|
||||
instance->keystore = keystore;
|
||||
|
||||
instance->common.name = "KeeLoq";
|
||||
instance->common.code_min_count_bit_for_found = 64;
|
||||
instance->common.te_short = 400;
|
||||
instance->common.te_long = 800;
|
||||
instance->common.te_delta = 140;
|
||||
instance->common.type_protocol = SubGhzProtocolCommonTypeDynamic;
|
||||
instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_protocol_keeloq_to_str;
|
||||
instance->common.to_save_string =
|
||||
(SubGhzProtocolCommonGetStrSave)subghz_protocol_keeloq_to_save_str;
|
||||
instance->common.to_load_protocol_from_file =
|
||||
(SubGhzProtocolCommonLoadFromFile)subghz_protocol_keeloq_to_load_protocol_from_file;
|
||||
instance->common.to_load_protocol =
|
||||
(SubGhzProtocolCommonLoadFromRAW)subghz_decoder_keeloq_to_load_protocol;
|
||||
instance->common.get_upload_protocol =
|
||||
(SubGhzProtocolCommonEncoderGetUpLoad)subghz_protocol_keeloq_send_key;
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void subghz_protocol_keeloq_free(SubGhzProtocolKeeloq* instance) {
|
||||
furi_assert(instance);
|
||||
free(instance);
|
||||
}
|
||||
|
||||
/** Checking the accepted code against the database manafacture key
|
||||
*
|
||||
* @param instance SubGhzProtocolKeeloq instance
|
||||
* @param fix fix part of the parcel
|
||||
* @param hop hop encrypted part of the parcel
|
||||
* @return true on successful search
|
||||
*/
|
||||
uint8_t subghz_protocol_keeloq_check_remote_controller_selector(
|
||||
SubGhzProtocolKeeloq* instance,
|
||||
uint32_t fix,
|
||||
uint32_t hop) {
|
||||
uint16_t end_serial = (uint16_t)(fix & 0x3FF);
|
||||
uint8_t btn = (uint8_t)(fix >> 28);
|
||||
uint32_t decrypt = 0;
|
||||
uint64_t man_normal_learning;
|
||||
|
||||
for
|
||||
M_EACH(manufacture_code, *subghz_keystore_get_data(instance->keystore), SubGhzKeyArray_t) {
|
||||
switch(manufacture_code->type) {
|
||||
case KEELOQ_LEARNING_SIMPLE:
|
||||
//Simple Learning
|
||||
decrypt = subghz_protocol_keeloq_common_decrypt(hop, manufacture_code->key);
|
||||
if((decrypt >> 28 == btn) &&
|
||||
(((((uint16_t)(decrypt >> 16)) & 0x3FF) == end_serial) ||
|
||||
((((uint16_t)(decrypt >> 16)) & 0x3FF) == 0))) {
|
||||
instance->manufacture_name = string_get_cstr(manufacture_code->name);
|
||||
instance->common.cnt = decrypt & 0x0000FFFF;
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case KEELOQ_LEARNING_NORMAL:
|
||||
// Normal_Learning
|
||||
// https://phreakerclub.com/forum/showpost.php?p=43557&postcount=37
|
||||
man_normal_learning =
|
||||
subghz_protocol_keeloq_common_normal_learning(fix, manufacture_code->key);
|
||||
decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_normal_learning);
|
||||
if((decrypt >> 28 == btn) &&
|
||||
(((((uint16_t)(decrypt >> 16)) & 0x3FF) == end_serial) ||
|
||||
((((uint16_t)(decrypt >> 16)) & 0x3FF) == 0))) {
|
||||
instance->manufacture_name = string_get_cstr(manufacture_code->name);
|
||||
instance->common.cnt = decrypt & 0x0000FFFF;
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case KEELOQ_LEARNING_UNKNOWN:
|
||||
// Simple Learning
|
||||
decrypt = subghz_protocol_keeloq_common_decrypt(hop, manufacture_code->key);
|
||||
if((decrypt >> 28 == btn) &&
|
||||
(((((uint16_t)(decrypt >> 16)) & 0x3FF) == end_serial) ||
|
||||
((((uint16_t)(decrypt >> 16)) & 0x3FF) == 0))) {
|
||||
instance->manufacture_name = string_get_cstr(manufacture_code->name);
|
||||
instance->common.cnt = decrypt & 0x0000FFFF;
|
||||
return 1;
|
||||
}
|
||||
// Check for mirrored man
|
||||
uint64_t man_rev = 0;
|
||||
uint64_t man_rev_byte = 0;
|
||||
for(uint8_t i = 0; i < 64; i += 8) {
|
||||
man_rev_byte = (uint8_t)(manufacture_code->key >> i);
|
||||
man_rev = man_rev | man_rev_byte << (56 - i);
|
||||
}
|
||||
decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_rev);
|
||||
if((decrypt >> 28 == btn) &&
|
||||
(((((uint16_t)(decrypt >> 16)) & 0x3FF) == end_serial) ||
|
||||
((((uint16_t)(decrypt >> 16)) & 0x3FF) == 0))) {
|
||||
instance->manufacture_name = string_get_cstr(manufacture_code->name);
|
||||
instance->common.cnt = decrypt & 0x0000FFFF;
|
||||
return 1;
|
||||
}
|
||||
//###########################
|
||||
// Normal_Learning
|
||||
// https://phreakerclub.com/forum/showpost.php?p=43557&postcount=37
|
||||
man_normal_learning =
|
||||
subghz_protocol_keeloq_common_normal_learning(fix, manufacture_code->key);
|
||||
decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_normal_learning);
|
||||
if((decrypt >> 28 == btn) &&
|
||||
(((((uint16_t)(decrypt >> 16)) & 0x3FF) == end_serial) ||
|
||||
((((uint16_t)(decrypt >> 16)) & 0x3FF) == 0))) {
|
||||
instance->manufacture_name = string_get_cstr(manufacture_code->name);
|
||||
instance->common.cnt = decrypt & 0x0000FFFF;
|
||||
return 1;
|
||||
}
|
||||
// Check for mirrored man
|
||||
man_rev = 0;
|
||||
man_rev_byte = 0;
|
||||
for(uint8_t i = 0; i < 64; i += 8) {
|
||||
man_rev_byte = (uint8_t)(manufacture_code->key >> i);
|
||||
man_rev = man_rev | man_rev_byte << (56 - i);
|
||||
}
|
||||
man_normal_learning = subghz_protocol_keeloq_common_normal_learning(fix, man_rev);
|
||||
decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_normal_learning);
|
||||
if((decrypt >> 28 == btn) &&
|
||||
(((((uint16_t)(decrypt >> 16)) & 0x3FF) == end_serial) ||
|
||||
((((uint16_t)(decrypt >> 16)) & 0x3FF) == 0))) {
|
||||
instance->manufacture_name = string_get_cstr(manufacture_code->name);
|
||||
instance->common.cnt = decrypt & 0x0000FFFF;
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
instance->manufacture_name = "Unknown";
|
||||
instance->common.cnt = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Analysis of received data
|
||||
*
|
||||
* @param instance SubGhzProtocolKeeloq instance
|
||||
*/
|
||||
void subghz_protocol_keeloq_check_remote_controller(SubGhzProtocolKeeloq* instance) {
|
||||
uint64_t key = subghz_protocol_common_reverse_key(
|
||||
instance->common.code_last_found, instance->common.code_last_count_bit);
|
||||
uint32_t key_fix = key >> 32;
|
||||
uint32_t key_hop = key & 0x00000000ffffffff;
|
||||
// Check key AN-Motors
|
||||
if((key_hop >> 24) == ((key_hop >> 16) & 0x00ff) &&
|
||||
(key_fix >> 28) == ((key_hop >> 12) & 0x0f) && (key_hop & 0xFFF) == 0x404) {
|
||||
instance->manufacture_name = "AN-Motors";
|
||||
instance->common.cnt = key_hop >> 16;
|
||||
} else if((key_hop & 0xFFF) == (0x000) && (key_fix >> 28) == ((key_hop >> 12) & 0x0f)) {
|
||||
instance->manufacture_name = "HCS101";
|
||||
instance->common.cnt = key_hop >> 16;
|
||||
} else {
|
||||
subghz_protocol_keeloq_check_remote_controller_selector(instance, key_fix, key_hop);
|
||||
}
|
||||
instance->common.serial = key_fix & 0x0FFFFFFF;
|
||||
instance->common.btn = key_fix >> 28;
|
||||
}
|
||||
|
||||
const char* subghz_protocol_keeloq_find_and_get_manufacture_name(void* context) {
|
||||
SubGhzProtocolKeeloq* instance = context;
|
||||
subghz_protocol_keeloq_check_remote_controller(instance);
|
||||
return instance->manufacture_name;
|
||||
}
|
||||
|
||||
const char* subghz_protocol_keeloq_get_manufacture_name(void* context) {
|
||||
SubGhzProtocolKeeloq* instance = context;
|
||||
return instance->manufacture_name;
|
||||
}
|
||||
|
||||
bool subghz_protocol_keeloq_set_manufacture_name(void* context, const char* manufacture_name) {
|
||||
SubGhzProtocolKeeloq* instance = context;
|
||||
instance->manufacture_name = manufacture_name;
|
||||
int res = 0;
|
||||
for
|
||||
M_EACH(
|
||||
manufacture_code,
|
||||
*subghz_keystore_get_data(instance->keystore),
|
||||
SubGhzKeyArray_t) {
|
||||
res = strcmp(string_get_cstr(manufacture_code->name), instance->manufacture_name);
|
||||
if(res == 0) return true;
|
||||
}
|
||||
instance->manufacture_name = "Unknown";
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64_t subghz_protocol_keeloq_gen_key(void* context) {
|
||||
SubGhzProtocolKeeloq* instance = context;
|
||||
uint32_t fix = instance->common.btn << 28 | instance->common.serial;
|
||||
uint32_t decrypt = instance->common.btn << 28 | (instance->common.serial & 0x3FF) << 16 |
|
||||
instance->common.cnt;
|
||||
uint32_t hop = 0;
|
||||
uint64_t man_normal_learning = 0;
|
||||
int res = 0;
|
||||
|
||||
for
|
||||
M_EACH(manufacture_code, *subghz_keystore_get_data(instance->keystore), SubGhzKeyArray_t) {
|
||||
res = strcmp(string_get_cstr(manufacture_code->name), instance->manufacture_name);
|
||||
if(res == 0) {
|
||||
switch(manufacture_code->type) {
|
||||
case KEELOQ_LEARNING_SIMPLE:
|
||||
//Simple Learning
|
||||
hop = subghz_protocol_keeloq_common_encrypt(decrypt, manufacture_code->key);
|
||||
break;
|
||||
case KEELOQ_LEARNING_NORMAL:
|
||||
//Simple Learning
|
||||
man_normal_learning =
|
||||
subghz_protocol_keeloq_common_normal_learning(fix, manufacture_code->key);
|
||||
hop = subghz_protocol_keeloq_common_encrypt(decrypt, man_normal_learning);
|
||||
break;
|
||||
case KEELOQ_LEARNING_UNKNOWN:
|
||||
hop = 0; //todo
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
uint64_t yek = (uint64_t)fix << 32 | hop;
|
||||
return subghz_protocol_common_reverse_key(yek, instance->common.code_last_count_bit);
|
||||
}
|
||||
|
||||
bool subghz_protocol_keeloq_send_key(
|
||||
SubGhzProtocolKeeloq* instance,
|
||||
SubGhzProtocolCommonEncoder* encoder) {
|
||||
furi_assert(instance);
|
||||
furi_assert(encoder);
|
||||
|
||||
//gen new key
|
||||
instance->common.cnt++;
|
||||
instance->common.code_last_found = subghz_protocol_keeloq_gen_key(instance);
|
||||
if(instance->common.callback)
|
||||
instance->common.callback((SubGhzProtocolCommon*)instance, instance->common.context);
|
||||
|
||||
if(!strcmp(instance->manufacture_name, "Unknown")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t index = 0;
|
||||
encoder->size_upload = 11 * 2 + 2 + (instance->common.code_last_count_bit * 2) + 4;
|
||||
if(encoder->size_upload > SUBGHZ_ENCODER_UPLOAD_MAX_SIZE) return false;
|
||||
|
||||
//Send header
|
||||
for(uint8_t i = 11; i > 0; i--) {
|
||||
encoder->upload[index++] = level_duration_make(true, (uint32_t)instance->common.te_short);
|
||||
encoder->upload[index++] = level_duration_make(false, (uint32_t)instance->common.te_short);
|
||||
}
|
||||
encoder->upload[index++] = level_duration_make(true, (uint32_t)instance->common.te_short);
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(false, (uint32_t)instance->common.te_short * 10);
|
||||
|
||||
//Send key data
|
||||
for(uint8_t i = instance->common.code_last_count_bit; i > 0; i--) {
|
||||
if(bit_read(instance->common.code_last_found, i - 1)) {
|
||||
//send bit 1
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(true, (uint32_t)instance->common.te_short);
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(false, (uint32_t)instance->common.te_long);
|
||||
} else {
|
||||
//send bit 0
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(true, (uint32_t)instance->common.te_long);
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(false, (uint32_t)instance->common.te_short);
|
||||
}
|
||||
}
|
||||
// +send 2 status bit
|
||||
encoder->upload[index++] = level_duration_make(true, (uint32_t)instance->common.te_short);
|
||||
encoder->upload[index++] = level_duration_make(false, (uint32_t)instance->common.te_long);
|
||||
|
||||
//encoder->upload[index++] = level_duration_make(true, (uint32_t)instance->common.te_long);
|
||||
//encoder->upload[index++] = level_duration_make(false, (uint32_t)instance->common.te_short);
|
||||
|
||||
// send end
|
||||
encoder->upload[index++] = level_duration_make(true, (uint32_t)instance->common.te_short);
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(false, (uint32_t)instance->common.te_short * 40);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void subghz_protocol_keeloq_reset(SubGhzProtocolKeeloq* instance) {
|
||||
instance->common.parser_step = KeeloqDecoderStepReset;
|
||||
}
|
||||
|
||||
void subghz_protocol_keeloq_parse(SubGhzProtocolKeeloq* instance, bool level, uint32_t duration) {
|
||||
switch(instance->common.parser_step) {
|
||||
case KeeloqDecoderStepReset:
|
||||
if((level) &&
|
||||
DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta) {
|
||||
instance->common.parser_step = KeeloqDecoderStepCheckPreambula;
|
||||
instance->common.header_count++;
|
||||
} else {
|
||||
instance->common.parser_step = KeeloqDecoderStepReset;
|
||||
}
|
||||
|
||||
break;
|
||||
case KeeloqDecoderStepCheckPreambula:
|
||||
if((!level) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta)) {
|
||||
instance->common.parser_step = KeeloqDecoderStepReset;
|
||||
break;
|
||||
}
|
||||
if((instance->common.header_count > 2) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_short * 10) <
|
||||
instance->common.te_delta * 10)) {
|
||||
// Found header
|
||||
instance->common.parser_step = KeeloqDecoderStepSaveDuration;
|
||||
instance->common.code_found = 0;
|
||||
instance->common.code_count_bit = 0;
|
||||
} else {
|
||||
instance->common.parser_step = KeeloqDecoderStepReset;
|
||||
instance->common.header_count = 0;
|
||||
}
|
||||
break;
|
||||
case KeeloqDecoderStepSaveDuration:
|
||||
if(level) {
|
||||
instance->common.te_last = duration;
|
||||
instance->common.parser_step = KeeloqDecoderStepCheckDuration;
|
||||
}
|
||||
break;
|
||||
case KeeloqDecoderStepCheckDuration:
|
||||
if(!level) {
|
||||
if(duration >= (instance->common.te_short * 2 + instance->common.te_delta)) {
|
||||
// Found end TX
|
||||
instance->common.parser_step = KeeloqDecoderStepReset;
|
||||
if(instance->common.code_count_bit >=
|
||||
instance->common.code_min_count_bit_for_found) {
|
||||
if(instance->common.code_last_found != instance->common.code_found) {
|
||||
instance->common.code_last_found = instance->common.code_found;
|
||||
instance->common.code_last_count_bit = instance->common.code_count_bit;
|
||||
if(instance->common.callback)
|
||||
instance->common.callback(
|
||||
(SubGhzProtocolCommon*)instance, instance->common.context);
|
||||
}
|
||||
instance->common.code_found = 0;
|
||||
instance->common.code_count_bit = 0;
|
||||
instance->common.header_count = 0;
|
||||
}
|
||||
break;
|
||||
} else if(
|
||||
(DURATION_DIFF(instance->common.te_last, instance->common.te_short) <
|
||||
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 = KeeloqDecoderStepSaveDuration;
|
||||
} else if(
|
||||
(DURATION_DIFF(instance->common.te_last, instance->common.te_long) <
|
||||
instance->common.te_delta) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_short) < 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);
|
||||
}
|
||||
instance->common.parser_step = KeeloqDecoderStepSaveDuration;
|
||||
} else {
|
||||
instance->common.parser_step = KeeloqDecoderStepReset;
|
||||
instance->common.header_count = 0;
|
||||
}
|
||||
} else {
|
||||
instance->common.parser_step = KeeloqDecoderStepReset;
|
||||
instance->common.header_count = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void subghz_protocol_keeloq_to_str(SubGhzProtocolKeeloq* instance, string_t output) {
|
||||
subghz_protocol_keeloq_check_remote_controller(instance);
|
||||
uint32_t code_found_hi = instance->common.code_last_found >> 32;
|
||||
uint32_t code_found_lo = instance->common.code_last_found & 0x00000000ffffffff;
|
||||
|
||||
uint64_t code_found_reverse = subghz_protocol_common_reverse_key(
|
||||
instance->common.code_last_found, instance->common.code_last_count_bit);
|
||||
|
||||
uint32_t code_found_reverse_hi = code_found_reverse >> 32;
|
||||
uint32_t code_found_reverse_lo = code_found_reverse & 0x00000000ffffffff;
|
||||
string_cat_printf(
|
||||
output,
|
||||
"%s %dbit\r\n"
|
||||
"Key:%08lX%08lX\r\n"
|
||||
"Fix:0x%08lX Cnt:%04X\r\n"
|
||||
"Hop:0x%08lX Btn:%02lX\r\n"
|
||||
"MF:%s\r\n"
|
||||
"Sn:0x%07lX \r\n",
|
||||
instance->common.name,
|
||||
instance->common.code_last_count_bit,
|
||||
code_found_hi,
|
||||
code_found_lo,
|
||||
code_found_reverse_hi,
|
||||
instance->common.cnt,
|
||||
code_found_reverse_lo,
|
||||
instance->common.btn,
|
||||
instance->manufacture_name,
|
||||
instance->common.serial);
|
||||
}
|
||||
|
||||
void subghz_protocol_keeloq_to_save_str(SubGhzProtocolKeeloq* instance, string_t output) {
|
||||
string_printf(
|
||||
output,
|
||||
"Protocol: %s\n"
|
||||
"Bit: %d\n"
|
||||
"Key: %08lX%08lX\n",
|
||||
instance->common.name,
|
||||
instance->common.code_last_count_bit,
|
||||
(uint32_t)(instance->common.code_last_found >> 32),
|
||||
(uint32_t)(instance->common.code_last_found & 0xFFFFFFFF));
|
||||
}
|
||||
|
||||
bool subghz_protocol_keeloq_to_load_protocol_from_file(
|
||||
FileWorker* file_worker,
|
||||
SubGhzProtocolKeeloq* instance) {
|
||||
bool loaded = false;
|
||||
string_t temp_str;
|
||||
string_init(temp_str);
|
||||
int res = 0;
|
||||
int data = 0;
|
||||
|
||||
do {
|
||||
// Read and parse bit data from 2nd line
|
||||
if(!file_worker_read_until(file_worker, temp_str, '\n')) {
|
||||
break;
|
||||
}
|
||||
res = sscanf(string_get_cstr(temp_str), "Bit: %d\n", &data);
|
||||
if(res != 1) {
|
||||
break;
|
||||
}
|
||||
instance->common.code_last_count_bit = (uint8_t)data;
|
||||
|
||||
// Read and parse key data from 3nd line
|
||||
if(!file_worker_read_until(file_worker, temp_str, '\n')) {
|
||||
break;
|
||||
}
|
||||
// strlen("Key: ") = 5
|
||||
string_right(temp_str, 5);
|
||||
|
||||
uint8_t buf_key[8] = {0};
|
||||
if(!subghz_protocol_common_read_hex(temp_str, buf_key, 8)) {
|
||||
break;
|
||||
}
|
||||
|
||||
for(uint8_t i = 0; i < 8; i++) {
|
||||
instance->common.code_last_found = instance->common.code_last_found << 8 | buf_key[i];
|
||||
}
|
||||
loaded = true;
|
||||
} while(0);
|
||||
string_clear(temp_str);
|
||||
|
||||
return loaded;
|
||||
}
|
||||
|
||||
void subghz_decoder_keeloq_to_load_protocol(SubGhzProtocolKeeloq* instance, void* context) {
|
||||
furi_assert(context);
|
||||
furi_assert(instance);
|
||||
SubGhzProtocolCommonLoad* data = context;
|
||||
instance->common.code_last_found = data->code_found;
|
||||
instance->common.code_last_count_bit = data->code_count_bit;
|
||||
subghz_protocol_keeloq_check_remote_controller(instance);
|
||||
}
|
||||
#include "subghz_protocol_keeloq.h"
|
||||
#include "subghz_protocol_keeloq_common.h"
|
||||
|
||||
#include "../subghz_keystore.h"
|
||||
|
||||
#include <furi.h>
|
||||
|
||||
#include <m-string.h>
|
||||
|
||||
struct SubGhzProtocolKeeloq {
|
||||
SubGhzProtocolCommon common;
|
||||
SubGhzKeystore* keystore;
|
||||
const char* manufacture_name;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
KeeloqDecoderStepReset = 0,
|
||||
KeeloqDecoderStepCheckPreambula,
|
||||
KeeloqDecoderStepSaveDuration,
|
||||
KeeloqDecoderStepCheckDuration,
|
||||
} KeeloqDecoderStep;
|
||||
|
||||
SubGhzProtocolKeeloq* subghz_protocol_keeloq_alloc(SubGhzKeystore* keystore) {
|
||||
SubGhzProtocolKeeloq* instance = furi_alloc(sizeof(SubGhzProtocolKeeloq));
|
||||
|
||||
instance->keystore = keystore;
|
||||
|
||||
instance->common.name = "KeeLoq";
|
||||
instance->common.code_min_count_bit_for_found = 64;
|
||||
instance->common.te_short = 400;
|
||||
instance->common.te_long = 800;
|
||||
instance->common.te_delta = 140;
|
||||
instance->common.type_protocol = SubGhzProtocolCommonTypeDynamic;
|
||||
instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_protocol_keeloq_to_str;
|
||||
instance->common.to_save_string =
|
||||
(SubGhzProtocolCommonGetStrSave)subghz_protocol_keeloq_to_save_str;
|
||||
instance->common.to_load_protocol_from_file =
|
||||
(SubGhzProtocolCommonLoadFromFile)subghz_protocol_keeloq_to_load_protocol_from_file;
|
||||
instance->common.to_load_protocol =
|
||||
(SubGhzProtocolCommonLoadFromRAW)subghz_decoder_keeloq_to_load_protocol;
|
||||
instance->common.get_upload_protocol =
|
||||
(SubGhzProtocolCommonEncoderGetUpLoad)subghz_protocol_keeloq_send_key;
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void subghz_protocol_keeloq_free(SubGhzProtocolKeeloq* instance) {
|
||||
furi_assert(instance);
|
||||
free(instance);
|
||||
}
|
||||
|
||||
/** Checking the accepted code against the database manafacture key
|
||||
*
|
||||
* @param instance SubGhzProtocolKeeloq instance
|
||||
* @param fix fix part of the parcel
|
||||
* @param hop hop encrypted part of the parcel
|
||||
* @return true on successful search
|
||||
*/
|
||||
uint8_t subghz_protocol_keeloq_check_remote_controller_selector(
|
||||
SubGhzProtocolKeeloq* instance,
|
||||
uint32_t fix,
|
||||
uint32_t hop) {
|
||||
uint16_t end_serial = (uint16_t)(fix & 0x3FF);
|
||||
uint8_t btn = (uint8_t)(fix >> 28);
|
||||
uint32_t decrypt = 0;
|
||||
uint64_t man_normal_learning;
|
||||
|
||||
for
|
||||
M_EACH(manufacture_code, *subghz_keystore_get_data(instance->keystore), SubGhzKeyArray_t) {
|
||||
switch(manufacture_code->type) {
|
||||
case KEELOQ_LEARNING_SIMPLE:
|
||||
//Simple Learning
|
||||
decrypt = subghz_protocol_keeloq_common_decrypt(hop, manufacture_code->key);
|
||||
if((decrypt >> 28 == btn) &&
|
||||
(((((uint16_t)(decrypt >> 16)) & 0x3FF) == end_serial) ||
|
||||
((((uint16_t)(decrypt >> 16)) & 0x3FF) == 0))) {
|
||||
instance->manufacture_name = string_get_cstr(manufacture_code->name);
|
||||
instance->common.cnt = decrypt & 0x0000FFFF;
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case KEELOQ_LEARNING_NORMAL:
|
||||
// Normal_Learning
|
||||
// https://phreakerclub.com/forum/showpost.php?p=43557&postcount=37
|
||||
man_normal_learning =
|
||||
subghz_protocol_keeloq_common_normal_learning(fix, manufacture_code->key);
|
||||
decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_normal_learning);
|
||||
if((decrypt >> 28 == btn) &&
|
||||
(((((uint16_t)(decrypt >> 16)) & 0x3FF) == end_serial) ||
|
||||
((((uint16_t)(decrypt >> 16)) & 0x3FF) == 0))) {
|
||||
instance->manufacture_name = string_get_cstr(manufacture_code->name);
|
||||
instance->common.cnt = decrypt & 0x0000FFFF;
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case KEELOQ_LEARNING_UNKNOWN:
|
||||
// Simple Learning
|
||||
decrypt = subghz_protocol_keeloq_common_decrypt(hop, manufacture_code->key);
|
||||
if((decrypt >> 28 == btn) &&
|
||||
(((((uint16_t)(decrypt >> 16)) & 0x3FF) == end_serial) ||
|
||||
((((uint16_t)(decrypt >> 16)) & 0x3FF) == 0))) {
|
||||
instance->manufacture_name = string_get_cstr(manufacture_code->name);
|
||||
instance->common.cnt = decrypt & 0x0000FFFF;
|
||||
return 1;
|
||||
}
|
||||
// Check for mirrored man
|
||||
uint64_t man_rev = 0;
|
||||
uint64_t man_rev_byte = 0;
|
||||
for(uint8_t i = 0; i < 64; i += 8) {
|
||||
man_rev_byte = (uint8_t)(manufacture_code->key >> i);
|
||||
man_rev = man_rev | man_rev_byte << (56 - i);
|
||||
}
|
||||
decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_rev);
|
||||
if((decrypt >> 28 == btn) &&
|
||||
(((((uint16_t)(decrypt >> 16)) & 0x3FF) == end_serial) ||
|
||||
((((uint16_t)(decrypt >> 16)) & 0x3FF) == 0))) {
|
||||
instance->manufacture_name = string_get_cstr(manufacture_code->name);
|
||||
instance->common.cnt = decrypt & 0x0000FFFF;
|
||||
return 1;
|
||||
}
|
||||
//###########################
|
||||
// Normal_Learning
|
||||
// https://phreakerclub.com/forum/showpost.php?p=43557&postcount=37
|
||||
man_normal_learning =
|
||||
subghz_protocol_keeloq_common_normal_learning(fix, manufacture_code->key);
|
||||
decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_normal_learning);
|
||||
if((decrypt >> 28 == btn) &&
|
||||
(((((uint16_t)(decrypt >> 16)) & 0x3FF) == end_serial) ||
|
||||
((((uint16_t)(decrypt >> 16)) & 0x3FF) == 0))) {
|
||||
instance->manufacture_name = string_get_cstr(manufacture_code->name);
|
||||
instance->common.cnt = decrypt & 0x0000FFFF;
|
||||
return 1;
|
||||
}
|
||||
// Check for mirrored man
|
||||
man_rev = 0;
|
||||
man_rev_byte = 0;
|
||||
for(uint8_t i = 0; i < 64; i += 8) {
|
||||
man_rev_byte = (uint8_t)(manufacture_code->key >> i);
|
||||
man_rev = man_rev | man_rev_byte << (56 - i);
|
||||
}
|
||||
man_normal_learning = subghz_protocol_keeloq_common_normal_learning(fix, man_rev);
|
||||
decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_normal_learning);
|
||||
if((decrypt >> 28 == btn) &&
|
||||
(((((uint16_t)(decrypt >> 16)) & 0x3FF) == end_serial) ||
|
||||
((((uint16_t)(decrypt >> 16)) & 0x3FF) == 0))) {
|
||||
instance->manufacture_name = string_get_cstr(manufacture_code->name);
|
||||
instance->common.cnt = decrypt & 0x0000FFFF;
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
instance->manufacture_name = "Unknown";
|
||||
instance->common.cnt = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Analysis of received data
|
||||
*
|
||||
* @param instance SubGhzProtocolKeeloq instance
|
||||
*/
|
||||
void subghz_protocol_keeloq_check_remote_controller(SubGhzProtocolKeeloq* instance) {
|
||||
uint64_t key = subghz_protocol_common_reverse_key(
|
||||
instance->common.code_last_found, instance->common.code_last_count_bit);
|
||||
uint32_t key_fix = key >> 32;
|
||||
uint32_t key_hop = key & 0x00000000ffffffff;
|
||||
// Check key AN-Motors
|
||||
if((key_hop >> 24) == ((key_hop >> 16) & 0x00ff) &&
|
||||
(key_fix >> 28) == ((key_hop >> 12) & 0x0f) && (key_hop & 0xFFF) == 0x404) {
|
||||
instance->manufacture_name = "AN-Motors";
|
||||
instance->common.cnt = key_hop >> 16;
|
||||
} else if((key_hop & 0xFFF) == (0x000) && (key_fix >> 28) == ((key_hop >> 12) & 0x0f)) {
|
||||
instance->manufacture_name = "HCS101";
|
||||
instance->common.cnt = key_hop >> 16;
|
||||
} else {
|
||||
subghz_protocol_keeloq_check_remote_controller_selector(instance, key_fix, key_hop);
|
||||
}
|
||||
instance->common.serial = key_fix & 0x0FFFFFFF;
|
||||
instance->common.btn = key_fix >> 28;
|
||||
}
|
||||
|
||||
const char* subghz_protocol_keeloq_find_and_get_manufacture_name(void* context) {
|
||||
SubGhzProtocolKeeloq* instance = context;
|
||||
subghz_protocol_keeloq_check_remote_controller(instance);
|
||||
return instance->manufacture_name;
|
||||
}
|
||||
|
||||
const char* subghz_protocol_keeloq_get_manufacture_name(void* context) {
|
||||
SubGhzProtocolKeeloq* instance = context;
|
||||
return instance->manufacture_name;
|
||||
}
|
||||
|
||||
bool subghz_protocol_keeloq_set_manufacture_name(void* context, const char* manufacture_name) {
|
||||
SubGhzProtocolKeeloq* instance = context;
|
||||
instance->manufacture_name = manufacture_name;
|
||||
int res = 0;
|
||||
for
|
||||
M_EACH(
|
||||
manufacture_code,
|
||||
*subghz_keystore_get_data(instance->keystore),
|
||||
SubGhzKeyArray_t) {
|
||||
res = strcmp(string_get_cstr(manufacture_code->name), instance->manufacture_name);
|
||||
if(res == 0) return true;
|
||||
}
|
||||
instance->manufacture_name = "Unknown";
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64_t subghz_protocol_keeloq_gen_key(void* context) {
|
||||
SubGhzProtocolKeeloq* instance = context;
|
||||
uint32_t fix = instance->common.btn << 28 | instance->common.serial;
|
||||
uint32_t decrypt = instance->common.btn << 28 | (instance->common.serial & 0x3FF) << 16 |
|
||||
instance->common.cnt;
|
||||
uint32_t hop = 0;
|
||||
uint64_t man_normal_learning = 0;
|
||||
int res = 0;
|
||||
|
||||
for
|
||||
M_EACH(manufacture_code, *subghz_keystore_get_data(instance->keystore), SubGhzKeyArray_t) {
|
||||
res = strcmp(string_get_cstr(manufacture_code->name), instance->manufacture_name);
|
||||
if(res == 0) {
|
||||
switch(manufacture_code->type) {
|
||||
case KEELOQ_LEARNING_SIMPLE:
|
||||
//Simple Learning
|
||||
hop = subghz_protocol_keeloq_common_encrypt(decrypt, manufacture_code->key);
|
||||
break;
|
||||
case KEELOQ_LEARNING_NORMAL:
|
||||
//Simple Learning
|
||||
man_normal_learning =
|
||||
subghz_protocol_keeloq_common_normal_learning(fix, manufacture_code->key);
|
||||
hop = subghz_protocol_keeloq_common_encrypt(decrypt, man_normal_learning);
|
||||
break;
|
||||
case KEELOQ_LEARNING_UNKNOWN:
|
||||
hop = 0; //todo
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
uint64_t yek = (uint64_t)fix << 32 | hop;
|
||||
return subghz_protocol_common_reverse_key(yek, instance->common.code_last_count_bit);
|
||||
}
|
||||
|
||||
bool subghz_protocol_keeloq_send_key(
|
||||
SubGhzProtocolKeeloq* instance,
|
||||
SubGhzProtocolCommonEncoder* encoder) {
|
||||
furi_assert(instance);
|
||||
furi_assert(encoder);
|
||||
|
||||
//gen new key
|
||||
instance->common.cnt++;
|
||||
instance->common.code_last_found = subghz_protocol_keeloq_gen_key(instance);
|
||||
if(instance->common.callback)
|
||||
instance->common.callback((SubGhzProtocolCommon*)instance, instance->common.context);
|
||||
|
||||
if(!strcmp(instance->manufacture_name, "Unknown")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t index = 0;
|
||||
encoder->size_upload = 11 * 2 + 2 + (instance->common.code_last_count_bit * 2) + 4;
|
||||
if(encoder->size_upload > SUBGHZ_ENCODER_UPLOAD_MAX_SIZE) return false;
|
||||
|
||||
//Send header
|
||||
for(uint8_t i = 11; i > 0; i--) {
|
||||
encoder->upload[index++] = level_duration_make(true, (uint32_t)instance->common.te_short);
|
||||
encoder->upload[index++] = level_duration_make(false, (uint32_t)instance->common.te_short);
|
||||
}
|
||||
encoder->upload[index++] = level_duration_make(true, (uint32_t)instance->common.te_short);
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(false, (uint32_t)instance->common.te_short * 10);
|
||||
|
||||
//Send key data
|
||||
for(uint8_t i = instance->common.code_last_count_bit; i > 0; i--) {
|
||||
if(bit_read(instance->common.code_last_found, i - 1)) {
|
||||
//send bit 1
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(true, (uint32_t)instance->common.te_short);
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(false, (uint32_t)instance->common.te_long);
|
||||
} else {
|
||||
//send bit 0
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(true, (uint32_t)instance->common.te_long);
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(false, (uint32_t)instance->common.te_short);
|
||||
}
|
||||
}
|
||||
// +send 2 status bit
|
||||
encoder->upload[index++] = level_duration_make(true, (uint32_t)instance->common.te_short);
|
||||
encoder->upload[index++] = level_duration_make(false, (uint32_t)instance->common.te_long);
|
||||
|
||||
//encoder->upload[index++] = level_duration_make(true, (uint32_t)instance->common.te_long);
|
||||
//encoder->upload[index++] = level_duration_make(false, (uint32_t)instance->common.te_short);
|
||||
|
||||
// send end
|
||||
encoder->upload[index++] = level_duration_make(true, (uint32_t)instance->common.te_short);
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(false, (uint32_t)instance->common.te_short * 40);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void subghz_protocol_keeloq_reset(SubGhzProtocolKeeloq* instance) {
|
||||
instance->common.parser_step = KeeloqDecoderStepReset;
|
||||
}
|
||||
|
||||
void subghz_protocol_keeloq_parse(SubGhzProtocolKeeloq* instance, bool level, uint32_t duration) {
|
||||
switch(instance->common.parser_step) {
|
||||
case KeeloqDecoderStepReset:
|
||||
if((level) &&
|
||||
DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta) {
|
||||
instance->common.parser_step = KeeloqDecoderStepCheckPreambula;
|
||||
instance->common.header_count++;
|
||||
} else {
|
||||
instance->common.parser_step = KeeloqDecoderStepReset;
|
||||
}
|
||||
|
||||
break;
|
||||
case KeeloqDecoderStepCheckPreambula:
|
||||
if((!level) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta)) {
|
||||
instance->common.parser_step = KeeloqDecoderStepReset;
|
||||
break;
|
||||
}
|
||||
if((instance->common.header_count > 2) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_short * 10) <
|
||||
instance->common.te_delta * 10)) {
|
||||
// Found header
|
||||
instance->common.parser_step = KeeloqDecoderStepSaveDuration;
|
||||
instance->common.code_found = 0;
|
||||
instance->common.code_count_bit = 0;
|
||||
} else {
|
||||
instance->common.parser_step = KeeloqDecoderStepReset;
|
||||
instance->common.header_count = 0;
|
||||
}
|
||||
break;
|
||||
case KeeloqDecoderStepSaveDuration:
|
||||
if(level) {
|
||||
instance->common.te_last = duration;
|
||||
instance->common.parser_step = KeeloqDecoderStepCheckDuration;
|
||||
}
|
||||
break;
|
||||
case KeeloqDecoderStepCheckDuration:
|
||||
if(!level) {
|
||||
if(duration >= (instance->common.te_short * 2 + instance->common.te_delta)) {
|
||||
// Found end TX
|
||||
instance->common.parser_step = KeeloqDecoderStepReset;
|
||||
if(instance->common.code_count_bit >=
|
||||
instance->common.code_min_count_bit_for_found) {
|
||||
if(instance->common.code_last_found != instance->common.code_found) {
|
||||
instance->common.code_last_found = instance->common.code_found;
|
||||
instance->common.code_last_count_bit = instance->common.code_count_bit;
|
||||
if(instance->common.callback)
|
||||
instance->common.callback(
|
||||
(SubGhzProtocolCommon*)instance, instance->common.context);
|
||||
}
|
||||
instance->common.code_found = 0;
|
||||
instance->common.code_count_bit = 0;
|
||||
instance->common.header_count = 0;
|
||||
}
|
||||
break;
|
||||
} else if(
|
||||
(DURATION_DIFF(instance->common.te_last, instance->common.te_short) <
|
||||
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 = KeeloqDecoderStepSaveDuration;
|
||||
} else if(
|
||||
(DURATION_DIFF(instance->common.te_last, instance->common.te_long) <
|
||||
instance->common.te_delta) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_short) < 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);
|
||||
}
|
||||
instance->common.parser_step = KeeloqDecoderStepSaveDuration;
|
||||
} else {
|
||||
instance->common.parser_step = KeeloqDecoderStepReset;
|
||||
instance->common.header_count = 0;
|
||||
}
|
||||
} else {
|
||||
instance->common.parser_step = KeeloqDecoderStepReset;
|
||||
instance->common.header_count = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void subghz_protocol_keeloq_to_str(SubGhzProtocolKeeloq* instance, string_t output) {
|
||||
subghz_protocol_keeloq_check_remote_controller(instance);
|
||||
uint32_t code_found_hi = instance->common.code_last_found >> 32;
|
||||
uint32_t code_found_lo = instance->common.code_last_found & 0x00000000ffffffff;
|
||||
|
||||
uint64_t code_found_reverse = subghz_protocol_common_reverse_key(
|
||||
instance->common.code_last_found, instance->common.code_last_count_bit);
|
||||
|
||||
uint32_t code_found_reverse_hi = code_found_reverse >> 32;
|
||||
uint32_t code_found_reverse_lo = code_found_reverse & 0x00000000ffffffff;
|
||||
string_cat_printf(
|
||||
output,
|
||||
"%s %dbit\r\n"
|
||||
"Key:%08lX%08lX\r\n"
|
||||
"Fix:0x%08lX Cnt:%04X\r\n"
|
||||
"Hop:0x%08lX Btn:%02lX\r\n"
|
||||
"MF:%s\r\n"
|
||||
"Sn:0x%07lX \r\n",
|
||||
instance->common.name,
|
||||
instance->common.code_last_count_bit,
|
||||
code_found_hi,
|
||||
code_found_lo,
|
||||
code_found_reverse_hi,
|
||||
instance->common.cnt,
|
||||
code_found_reverse_lo,
|
||||
instance->common.btn,
|
||||
instance->manufacture_name,
|
||||
instance->common.serial);
|
||||
}
|
||||
|
||||
void subghz_protocol_keeloq_to_save_str(SubGhzProtocolKeeloq* instance, string_t output) {
|
||||
string_printf(
|
||||
output,
|
||||
"Protocol: %s\n"
|
||||
"Bit: %d\n"
|
||||
"Key: %08lX%08lX\n",
|
||||
instance->common.name,
|
||||
instance->common.code_last_count_bit,
|
||||
(uint32_t)(instance->common.code_last_found >> 32),
|
||||
(uint32_t)(instance->common.code_last_found & 0xFFFFFFFF));
|
||||
}
|
||||
|
||||
bool subghz_protocol_keeloq_to_load_protocol_from_file(
|
||||
FileWorker* file_worker,
|
||||
SubGhzProtocolKeeloq* instance) {
|
||||
bool loaded = false;
|
||||
string_t temp_str;
|
||||
string_init(temp_str);
|
||||
int res = 0;
|
||||
int data = 0;
|
||||
|
||||
do {
|
||||
// Read and parse bit data from 2nd line
|
||||
if(!file_worker_read_until(file_worker, temp_str, '\n')) {
|
||||
break;
|
||||
}
|
||||
res = sscanf(string_get_cstr(temp_str), "Bit: %d\n", &data);
|
||||
if(res != 1) {
|
||||
break;
|
||||
}
|
||||
instance->common.code_last_count_bit = (uint8_t)data;
|
||||
|
||||
// Read and parse key data from 3nd line
|
||||
if(!file_worker_read_until(file_worker, temp_str, '\n')) {
|
||||
break;
|
||||
}
|
||||
// strlen("Key: ") = 5
|
||||
string_right(temp_str, 5);
|
||||
|
||||
uint8_t buf_key[8] = {0};
|
||||
if(!subghz_protocol_common_read_hex(temp_str, buf_key, 8)) {
|
||||
break;
|
||||
}
|
||||
|
||||
for(uint8_t i = 0; i < 8; i++) {
|
||||
instance->common.code_last_found = instance->common.code_last_found << 8 | buf_key[i];
|
||||
}
|
||||
loaded = true;
|
||||
} while(0);
|
||||
string_clear(temp_str);
|
||||
|
||||
return loaded;
|
||||
}
|
||||
|
||||
void subghz_decoder_keeloq_to_load_protocol(SubGhzProtocolKeeloq* instance, void* context) {
|
||||
furi_assert(context);
|
||||
furi_assert(instance);
|
||||
SubGhzProtocolCommonLoad* data = context;
|
||||
instance->common.code_last_found = data->code_found;
|
||||
instance->common.code_last_count_bit = data->code_count_bit;
|
||||
subghz_protocol_keeloq_check_remote_controller(instance);
|
||||
}
|
||||
|
@@ -1,97 +1,97 @@
|
||||
#pragma once
|
||||
|
||||
#include "subghz_protocol_common.h"
|
||||
|
||||
typedef struct SubGhzKeystore SubGhzKeystore;
|
||||
|
||||
typedef struct SubGhzProtocolKeeloq SubGhzProtocolKeeloq;
|
||||
|
||||
/** Allocate SubGhzProtocolKeeloq
|
||||
*
|
||||
* @return SubGhzProtocolKeeloq*
|
||||
*/
|
||||
SubGhzProtocolKeeloq* subghz_protocol_keeloq_alloc(SubGhzKeystore* keystore);
|
||||
|
||||
/** Free SubGhzProtocolKeeloq
|
||||
*
|
||||
* @param instance
|
||||
*/
|
||||
void subghz_protocol_keeloq_free(SubGhzProtocolKeeloq* instance);
|
||||
|
||||
/** Find and get manufacture name
|
||||
*
|
||||
* @param context - SubGhzProtocolKeeloq context
|
||||
* @return name - char* manufacture name
|
||||
*/
|
||||
const char* subghz_protocol_keeloq_find_and_get_manufacture_name(void* context);
|
||||
|
||||
/** Get manufacture name
|
||||
*
|
||||
* @param context - SubGhzProtocolKeeloq context
|
||||
* @return name - char* manufacture name
|
||||
*/
|
||||
const char* subghz_protocol_keeloq_get_manufacture_name(void* context);
|
||||
|
||||
/** Set manufacture name
|
||||
*
|
||||
* @param manufacture_name - manufacture name
|
||||
* @param context - SubGhzProtocolKeeloq context
|
||||
* @return bool
|
||||
*/
|
||||
bool subghz_protocol_keeloq_set_manufacture_name(void* context, const char* manufacture_name);
|
||||
|
||||
/** Get key keeloq
|
||||
*
|
||||
* @param context - SubGhzProtocolKeeloq context
|
||||
* @return key
|
||||
*/
|
||||
uint64_t subghz_protocol_keeloq_gen_key(void* context);
|
||||
|
||||
/** Get upload protocol
|
||||
*
|
||||
* @param instance - SubGhzProtocolKeeloq instance
|
||||
* @param encoder - SubGhzProtocolCommonEncoder encoder
|
||||
* @return bool
|
||||
*/
|
||||
bool subghz_protocol_keeloq_send_key(SubGhzProtocolKeeloq* instance, SubGhzProtocolCommonEncoder* encoder);
|
||||
|
||||
/** Reset internal state
|
||||
* @param instance - SubGhzProtocolKeeloq instance
|
||||
*/
|
||||
void subghz_protocol_keeloq_reset(SubGhzProtocolKeeloq* instance);
|
||||
|
||||
/** Parse accepted duration
|
||||
*
|
||||
* @param instance - SubGhzProtocolKeeloq instance
|
||||
* @param data - LevelDuration level_duration
|
||||
*/
|
||||
void subghz_protocol_keeloq_parse(SubGhzProtocolKeeloq* instance, bool level, uint32_t duration);
|
||||
|
||||
/** Outputting information from the parser
|
||||
*
|
||||
* @param instance - SubGhzProtocolKeeloq* instance
|
||||
* @param output - output string
|
||||
*/
|
||||
void subghz_protocol_keeloq_to_str(SubGhzProtocolKeeloq* instance, string_t output);
|
||||
|
||||
/** Get a string to save the protocol
|
||||
*
|
||||
* @param instance - SubGhzProtocolKeeloq instance
|
||||
* @param output - the resulting string
|
||||
*/
|
||||
void subghz_protocol_keeloq_to_save_str(SubGhzProtocolKeeloq* instance, string_t output);
|
||||
|
||||
/** Loading protocol from file
|
||||
*
|
||||
* @param file_worker - FileWorker file_worker
|
||||
* @param instance - SubGhzProtocolKeeloq instance
|
||||
* @return bool
|
||||
*/
|
||||
bool subghz_protocol_keeloq_to_load_protocol_from_file(FileWorker* file_worker, SubGhzProtocolKeeloq* instance);
|
||||
|
||||
/** Loading protocol from bin data
|
||||
*
|
||||
* @param instance - SubGhzProtocolKeeloq instance
|
||||
* @param context - SubGhzProtocolCommonLoad context
|
||||
*/
|
||||
void subghz_decoder_keeloq_to_load_protocol(SubGhzProtocolKeeloq* instance, void* context);
|
||||
#pragma once
|
||||
|
||||
#include "subghz_protocol_common.h"
|
||||
|
||||
typedef struct SubGhzKeystore SubGhzKeystore;
|
||||
|
||||
typedef struct SubGhzProtocolKeeloq SubGhzProtocolKeeloq;
|
||||
|
||||
/** Allocate SubGhzProtocolKeeloq
|
||||
*
|
||||
* @return SubGhzProtocolKeeloq*
|
||||
*/
|
||||
SubGhzProtocolKeeloq* subghz_protocol_keeloq_alloc(SubGhzKeystore* keystore);
|
||||
|
||||
/** Free SubGhzProtocolKeeloq
|
||||
*
|
||||
* @param instance
|
||||
*/
|
||||
void subghz_protocol_keeloq_free(SubGhzProtocolKeeloq* instance);
|
||||
|
||||
/** Find and get manufacture name
|
||||
*
|
||||
* @param context - SubGhzProtocolKeeloq context
|
||||
* @return name - char* manufacture name
|
||||
*/
|
||||
const char* subghz_protocol_keeloq_find_and_get_manufacture_name(void* context);
|
||||
|
||||
/** Get manufacture name
|
||||
*
|
||||
* @param context - SubGhzProtocolKeeloq context
|
||||
* @return name - char* manufacture name
|
||||
*/
|
||||
const char* subghz_protocol_keeloq_get_manufacture_name(void* context);
|
||||
|
||||
/** Set manufacture name
|
||||
*
|
||||
* @param manufacture_name - manufacture name
|
||||
* @param context - SubGhzProtocolKeeloq context
|
||||
* @return bool
|
||||
*/
|
||||
bool subghz_protocol_keeloq_set_manufacture_name(void* context, const char* manufacture_name);
|
||||
|
||||
/** Get key keeloq
|
||||
*
|
||||
* @param context - SubGhzProtocolKeeloq context
|
||||
* @return key
|
||||
*/
|
||||
uint64_t subghz_protocol_keeloq_gen_key(void* context);
|
||||
|
||||
/** Get upload protocol
|
||||
*
|
||||
* @param instance - SubGhzProtocolKeeloq instance
|
||||
* @param encoder - SubGhzProtocolCommonEncoder encoder
|
||||
* @return bool
|
||||
*/
|
||||
bool subghz_protocol_keeloq_send_key(SubGhzProtocolKeeloq* instance, SubGhzProtocolCommonEncoder* encoder);
|
||||
|
||||
/** Reset internal state
|
||||
* @param instance - SubGhzProtocolKeeloq instance
|
||||
*/
|
||||
void subghz_protocol_keeloq_reset(SubGhzProtocolKeeloq* instance);
|
||||
|
||||
/** Parse accepted duration
|
||||
*
|
||||
* @param instance - SubGhzProtocolKeeloq instance
|
||||
* @param data - LevelDuration level_duration
|
||||
*/
|
||||
void subghz_protocol_keeloq_parse(SubGhzProtocolKeeloq* instance, bool level, uint32_t duration);
|
||||
|
||||
/** Outputting information from the parser
|
||||
*
|
||||
* @param instance - SubGhzProtocolKeeloq* instance
|
||||
* @param output - output string
|
||||
*/
|
||||
void subghz_protocol_keeloq_to_str(SubGhzProtocolKeeloq* instance, string_t output);
|
||||
|
||||
/** Get a string to save the protocol
|
||||
*
|
||||
* @param instance - SubGhzProtocolKeeloq instance
|
||||
* @param output - the resulting string
|
||||
*/
|
||||
void subghz_protocol_keeloq_to_save_str(SubGhzProtocolKeeloq* instance, string_t output);
|
||||
|
||||
/** Loading protocol from file
|
||||
*
|
||||
* @param file_worker - FileWorker file_worker
|
||||
* @param instance - SubGhzProtocolKeeloq instance
|
||||
* @return bool
|
||||
*/
|
||||
bool subghz_protocol_keeloq_to_load_protocol_from_file(FileWorker* file_worker, SubGhzProtocolKeeloq* instance);
|
||||
|
||||
/** Loading protocol from bin data
|
||||
*
|
||||
* @param instance - SubGhzProtocolKeeloq instance
|
||||
* @param context - SubGhzProtocolCommonLoad context
|
||||
*/
|
||||
void subghz_decoder_keeloq_to_load_protocol(SubGhzProtocolKeeloq* instance, void* context);
|
||||
|
@@ -1,49 +1,49 @@
|
||||
#include "subghz_protocol_keeloq_common.h"
|
||||
|
||||
#include <furi.h>
|
||||
|
||||
#include <m-string.h>
|
||||
#include <m-array.h>
|
||||
|
||||
/** Simple Learning Encrypt
|
||||
* @param data - 0xBSSSCCCC, B(4bit) key, S(10bit) serial&0x3FF, C(16bit) counter
|
||||
* @param key - manufacture (64bit)
|
||||
* @return keelog encrypt data
|
||||
*/
|
||||
inline uint32_t subghz_protocol_keeloq_common_encrypt(const uint32_t data, const uint64_t key) {
|
||||
uint32_t x = data, r;
|
||||
for (r = 0; r < 528; r++)
|
||||
x = (x>>1)^((bit(x,0)^bit(x,16)^(uint32_t)bit(key,r&63)^bit(KEELOQ_NLF,g5(x,1,9,20,26,31)))<<31);
|
||||
return x;
|
||||
}
|
||||
|
||||
/** Simple Learning Decrypt
|
||||
* @param data - keelog encrypt data
|
||||
* @param key - manufacture (64bit)
|
||||
* @return 0xBSSSCCCC, B(4bit) key, S(10bit) serial&0x3FF, C(16bit) counter
|
||||
*/
|
||||
inline uint32_t subghz_protocol_keeloq_common_decrypt(const uint32_t data, const uint64_t key) {
|
||||
uint32_t x = data, r;
|
||||
for (r = 0; r < 528; r++)
|
||||
x = (x<<1)^bit(x,31)^bit(x,15)^(uint32_t)bit(key,(15-r)&63)^bit(KEELOQ_NLF,g5(x,0,8,19,25,30));
|
||||
return x;
|
||||
}
|
||||
|
||||
/** Normal Learning
|
||||
* @param data - serial number (28bit)
|
||||
* @param key - manufacture (64bit)
|
||||
* @return manufacture for this serial number (64bit)
|
||||
*/
|
||||
inline uint64_t subghz_protocol_keeloq_common_normal_learning(uint32_t data, const uint64_t key){
|
||||
uint32_t k1,k2;
|
||||
|
||||
data&=0x0FFFFFFF;
|
||||
data|=0x20000000;
|
||||
k1=subghz_protocol_keeloq_common_decrypt(data, key);
|
||||
|
||||
data&=0x0FFFFFFF;
|
||||
data|=0x60000000;
|
||||
k2=subghz_protocol_keeloq_common_decrypt(data, key);
|
||||
|
||||
return ((uint64_t)k2<<32)| k1; // key - shifrovanoya
|
||||
}
|
||||
#include "subghz_protocol_keeloq_common.h"
|
||||
|
||||
#include <furi.h>
|
||||
|
||||
#include <m-string.h>
|
||||
#include <m-array.h>
|
||||
|
||||
/** Simple Learning Encrypt
|
||||
* @param data - 0xBSSSCCCC, B(4bit) key, S(10bit) serial&0x3FF, C(16bit) counter
|
||||
* @param key - manufacture (64bit)
|
||||
* @return keelog encrypt data
|
||||
*/
|
||||
inline uint32_t subghz_protocol_keeloq_common_encrypt(const uint32_t data, const uint64_t key) {
|
||||
uint32_t x = data, r;
|
||||
for (r = 0; r < 528; r++)
|
||||
x = (x>>1)^((bit(x,0)^bit(x,16)^(uint32_t)bit(key,r&63)^bit(KEELOQ_NLF,g5(x,1,9,20,26,31)))<<31);
|
||||
return x;
|
||||
}
|
||||
|
||||
/** Simple Learning Decrypt
|
||||
* @param data - keelog encrypt data
|
||||
* @param key - manufacture (64bit)
|
||||
* @return 0xBSSSCCCC, B(4bit) key, S(10bit) serial&0x3FF, C(16bit) counter
|
||||
*/
|
||||
inline uint32_t subghz_protocol_keeloq_common_decrypt(const uint32_t data, const uint64_t key) {
|
||||
uint32_t x = data, r;
|
||||
for (r = 0; r < 528; r++)
|
||||
x = (x<<1)^bit(x,31)^bit(x,15)^(uint32_t)bit(key,(15-r)&63)^bit(KEELOQ_NLF,g5(x,0,8,19,25,30));
|
||||
return x;
|
||||
}
|
||||
|
||||
/** Normal Learning
|
||||
* @param data - serial number (28bit)
|
||||
* @param key - manufacture (64bit)
|
||||
* @return manufacture for this serial number (64bit)
|
||||
*/
|
||||
inline uint64_t subghz_protocol_keeloq_common_normal_learning(uint32_t data, const uint64_t key){
|
||||
uint32_t k1,k2;
|
||||
|
||||
data&=0x0FFFFFFF;
|
||||
data|=0x20000000;
|
||||
k1=subghz_protocol_keeloq_common_decrypt(data, key);
|
||||
|
||||
data&=0x0FFFFFFF;
|
||||
data|=0x60000000;
|
||||
k2=subghz_protocol_keeloq_common_decrypt(data, key);
|
||||
|
||||
return ((uint64_t)k2<<32)| k1; // key - shifrovanoya
|
||||
}
|
||||
|
@@ -1,48 +1,48 @@
|
||||
#pragma once
|
||||
#include "subghz_protocol_common.h"
|
||||
#include "file-worker.h"
|
||||
|
||||
|
||||
#include <furi.h>
|
||||
|
||||
/*
|
||||
* Keeloq
|
||||
* https://ru.wikipedia.org/wiki/KeeLoq
|
||||
* https://phreakerclub.com/forum/showthread.php?t=1094
|
||||
*
|
||||
*/
|
||||
|
||||
#define KEELOQ_NLF 0x3A5C742E
|
||||
#define bit(x,n) (((x)>>(n))&1)
|
||||
#define g5(x,a,b,c,d,e) (bit(x,a)+bit(x,b)*2+bit(x,c)*4+bit(x,d)*8+bit(x,e)*16)
|
||||
|
||||
/*
|
||||
* KeeLoq learning types
|
||||
* https://phreakerclub.com/forum/showthread.php?t=67
|
||||
*/
|
||||
#define KEELOQ_LEARNING_UNKNOWN 0u
|
||||
#define KEELOQ_LEARNING_SIMPLE 1u
|
||||
#define KEELOQ_LEARNING_NORMAL 2u
|
||||
#define KEELOQ_LEARNING_SECURE 3u
|
||||
|
||||
|
||||
/** Simple Learning Encrypt
|
||||
* @param data - 0xBSSSCCCC, B(4bit) key, S(10bit) serial&0x3FF, C(16bit) counter
|
||||
* @param key - manufacture (64bit)
|
||||
* @return keelog encrypt data
|
||||
*/
|
||||
uint32_t subghz_protocol_keeloq_common_encrypt(const uint32_t data, const uint64_t key);
|
||||
|
||||
/** Simple Learning Decrypt
|
||||
* @param data - keelog encrypt data
|
||||
* @param key - manufacture (64bit)
|
||||
* @return 0xBSSSCCCC, B(4bit) key, S(10bit) serial&0x3FF, C(16bit) counter
|
||||
*/
|
||||
uint32_t subghz_protocol_keeloq_common_decrypt(const uint32_t data, const uint64_t key);
|
||||
|
||||
/** Normal Learning
|
||||
* @param data - serial number (28bit)
|
||||
* @param key - manufacture (64bit)
|
||||
* @return manufacture for this serial number (64bit)
|
||||
*/
|
||||
uint64_t subghz_protocol_keeloq_common_normal_learning(uint32_t data, const uint64_t key);
|
||||
#pragma once
|
||||
#include "subghz_protocol_common.h"
|
||||
#include "file-worker.h"
|
||||
|
||||
|
||||
#include <furi.h>
|
||||
|
||||
/*
|
||||
* Keeloq
|
||||
* https://ru.wikipedia.org/wiki/KeeLoq
|
||||
* https://phreakerclub.com/forum/showthread.php?t=1094
|
||||
*
|
||||
*/
|
||||
|
||||
#define KEELOQ_NLF 0x3A5C742E
|
||||
#define bit(x,n) (((x)>>(n))&1)
|
||||
#define g5(x,a,b,c,d,e) (bit(x,a)+bit(x,b)*2+bit(x,c)*4+bit(x,d)*8+bit(x,e)*16)
|
||||
|
||||
/*
|
||||
* KeeLoq learning types
|
||||
* https://phreakerclub.com/forum/showthread.php?t=67
|
||||
*/
|
||||
#define KEELOQ_LEARNING_UNKNOWN 0u
|
||||
#define KEELOQ_LEARNING_SIMPLE 1u
|
||||
#define KEELOQ_LEARNING_NORMAL 2u
|
||||
#define KEELOQ_LEARNING_SECURE 3u
|
||||
|
||||
|
||||
/** Simple Learning Encrypt
|
||||
* @param data - 0xBSSSCCCC, B(4bit) key, S(10bit) serial&0x3FF, C(16bit) counter
|
||||
* @param key - manufacture (64bit)
|
||||
* @return keelog encrypt data
|
||||
*/
|
||||
uint32_t subghz_protocol_keeloq_common_encrypt(const uint32_t data, const uint64_t key);
|
||||
|
||||
/** Simple Learning Decrypt
|
||||
* @param data - keelog encrypt data
|
||||
* @param key - manufacture (64bit)
|
||||
* @return 0xBSSSCCCC, B(4bit) key, S(10bit) serial&0x3FF, C(16bit) counter
|
||||
*/
|
||||
uint32_t subghz_protocol_keeloq_common_decrypt(const uint32_t data, const uint64_t key);
|
||||
|
||||
/** Normal Learning
|
||||
* @param data - serial number (28bit)
|
||||
* @param key - manufacture (64bit)
|
||||
* @return manufacture for this serial number (64bit)
|
||||
*/
|
||||
uint64_t subghz_protocol_keeloq_common_normal_learning(uint32_t data, const uint64_t key);
|
||||
|
@@ -1,285 +1,285 @@
|
||||
#include "subghz_protocol_nero_sketch.h"
|
||||
|
||||
struct SubGhzProtocolNeroSketch {
|
||||
SubGhzProtocolCommon common;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
NeroSketchDecoderStepReset = 0,
|
||||
NeroSketchDecoderStepCheckPreambula,
|
||||
NeroSketchDecoderStepSaveDuration,
|
||||
NeroSketchDecoderStepCheckDuration,
|
||||
} NeroSketchDecoderStep;
|
||||
|
||||
SubGhzProtocolNeroSketch* subghz_protocol_nero_sketch_alloc(void) {
|
||||
SubGhzProtocolNeroSketch* instance = furi_alloc(sizeof(SubGhzProtocolNeroSketch));
|
||||
|
||||
instance->common.name = "Nero Sketch";
|
||||
instance->common.code_min_count_bit_for_found = 40;
|
||||
instance->common.te_short = 330;
|
||||
instance->common.te_long = 660;
|
||||
instance->common.te_delta = 150;
|
||||
instance->common.type_protocol = SubGhzProtocolCommonTypeStatic;
|
||||
instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_protocol_nero_sketch_to_str;
|
||||
instance->common.to_save_string =
|
||||
(SubGhzProtocolCommonGetStrSave)subghz_protocol_nero_sketch_to_save_str;
|
||||
instance->common.to_load_protocol_from_file =
|
||||
(SubGhzProtocolCommonLoadFromFile)subghz_protocol_nero_sketch_to_load_protocol_from_file;
|
||||
instance->common.to_load_protocol =
|
||||
(SubGhzProtocolCommonLoadFromRAW)subghz_decoder_nero_sketch_to_load_protocol;
|
||||
instance->common.get_upload_protocol =
|
||||
(SubGhzProtocolCommonEncoderGetUpLoad)subghz_protocol_nero_sketch_send_key;
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void subghz_protocol_nero_sketch_free(SubGhzProtocolNeroSketch* instance) {
|
||||
furi_assert(instance);
|
||||
free(instance);
|
||||
}
|
||||
|
||||
bool subghz_protocol_nero_sketch_send_key(
|
||||
SubGhzProtocolNeroSketch* instance,
|
||||
SubGhzProtocolCommonEncoder* encoder) {
|
||||
furi_assert(instance);
|
||||
furi_assert(encoder);
|
||||
size_t index = 0;
|
||||
encoder->size_upload = 47 * 2 + 2 + (instance->common.code_last_count_bit * 2) + 2;
|
||||
if(encoder->size_upload > SUBGHZ_ENCODER_UPLOAD_MAX_SIZE) return false;
|
||||
|
||||
//Send header
|
||||
for(uint8_t i = 0; i < 47; i++) {
|
||||
encoder->upload[index++] = level_duration_make(true, (uint32_t)instance->common.te_short);
|
||||
encoder->upload[index++] = level_duration_make(false, (uint32_t)instance->common.te_short);
|
||||
}
|
||||
|
||||
//Send start bit
|
||||
encoder->upload[index++] = level_duration_make(true, (uint32_t)instance->common.te_short * 4);
|
||||
encoder->upload[index++] = level_duration_make(false, (uint32_t)instance->common.te_short);
|
||||
|
||||
//Send key data
|
||||
for(uint8_t i = instance->common.code_last_count_bit; i > 0; i--) {
|
||||
if(bit_read(instance->common.code_last_found, i - 1)) {
|
||||
//send bit 1
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(true, (uint32_t)instance->common.te_long);
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(false, (uint32_t)instance->common.te_short);
|
||||
} else {
|
||||
//send bit 0
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(true, (uint32_t)instance->common.te_short);
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(false, (uint32_t)instance->common.te_long);
|
||||
}
|
||||
}
|
||||
|
||||
//Send stop bit
|
||||
encoder->upload[index++] = level_duration_make(true, (uint32_t)instance->common.te_short * 3);
|
||||
encoder->upload[index++] = level_duration_make(false, (uint32_t)instance->common.te_short);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void subghz_protocol_nero_sketch_reset(SubGhzProtocolNeroSketch* instance) {
|
||||
instance->common.parser_step = NeroSketchDecoderStepReset;
|
||||
}
|
||||
|
||||
/** Analysis of received data
|
||||
*
|
||||
* @param instance SubGhzProtocolNeroSketch instance
|
||||
*/
|
||||
// void subghz_protocol_nero_sketch_check_remote_controller(SubGhzProtocolNeroSketch* instance) {
|
||||
// //пока не понятно с серийником, но код статический
|
||||
// // uint64_t code_found_reverse = subghz_protocol_common_reverse_key(instance->common.code_found, instance->common.code_count_bit);
|
||||
// // uint32_t code_fix = code_found_reverse & 0xFFFFFFFF;
|
||||
// // //uint32_t code_hop = (code_found_reverse >> 24) & 0xFFFFF;
|
||||
|
||||
// // instance->common.serial = code_fix & 0xFFFFFFF;
|
||||
// // instance->common.btn = (code_fix >> 28) & 0x0F;
|
||||
|
||||
// //if (instance->common.callback) instance->common.callback((SubGhzProtocolCommon*)instance, instance->common.context);
|
||||
|
||||
// }
|
||||
|
||||
void subghz_protocol_nero_sketch_parse(
|
||||
SubGhzProtocolNeroSketch* instance,
|
||||
bool level,
|
||||
uint32_t duration) {
|
||||
switch(instance->common.parser_step) {
|
||||
case NeroSketchDecoderStepReset:
|
||||
if((level) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta)) {
|
||||
instance->common.parser_step = NeroSketchDecoderStepCheckPreambula;
|
||||
instance->common.te_last = duration;
|
||||
instance->common.header_count = 0;
|
||||
} else {
|
||||
instance->common.parser_step = NeroSketchDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case NeroSketchDecoderStepCheckPreambula:
|
||||
if(level) {
|
||||
if((DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta) ||
|
||||
(DURATION_DIFF(duration, instance->common.te_short * 4) <
|
||||
instance->common.te_delta)) {
|
||||
instance->common.te_last = duration;
|
||||
} else {
|
||||
instance->common.parser_step = NeroSketchDecoderStepReset;
|
||||
}
|
||||
} else if(DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta) {
|
||||
if(DURATION_DIFF(instance->common.te_last, instance->common.te_short) <
|
||||
instance->common.te_delta) {
|
||||
// Found header
|
||||
instance->common.header_count++;
|
||||
break;
|
||||
} else if(
|
||||
DURATION_DIFF(instance->common.te_last, instance->common.te_short * 4) <
|
||||
instance->common.te_delta) {
|
||||
// Found start bit
|
||||
if(instance->common.header_count > 40) {
|
||||
instance->common.parser_step = NeroSketchDecoderStepSaveDuration;
|
||||
instance->common.code_found = 0;
|
||||
instance->common.code_count_bit = 0;
|
||||
} else {
|
||||
instance->common.parser_step = NeroSketchDecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
instance->common.parser_step = NeroSketchDecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
instance->common.parser_step = NeroSketchDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case NeroSketchDecoderStepSaveDuration:
|
||||
if(level) {
|
||||
if(duration >= (instance->common.te_short * 2 + instance->common.te_delta * 2)) {
|
||||
//Found stop bit
|
||||
instance->common.parser_step = NeroSketchDecoderStepReset;
|
||||
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_count_bit = instance->common.code_count_bit;
|
||||
if(instance->common.callback)
|
||||
instance->common.callback(
|
||||
(SubGhzProtocolCommon*)instance, instance->common.context);
|
||||
}
|
||||
instance->common.code_found = 0;
|
||||
instance->common.code_count_bit = 0;
|
||||
break;
|
||||
} else {
|
||||
instance->common.te_last = duration;
|
||||
instance->common.parser_step = NeroSketchDecoderStepCheckDuration;
|
||||
}
|
||||
|
||||
} else {
|
||||
instance->common.parser_step = NeroSketchDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case NeroSketchDecoderStepCheckDuration:
|
||||
if(!level) {
|
||||
if((DURATION_DIFF(instance->common.te_last, instance->common.te_short) <
|
||||
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 = NeroSketchDecoderStepSaveDuration;
|
||||
} else if(
|
||||
(DURATION_DIFF(instance->common.te_last, instance->common.te_long) <
|
||||
instance->common.te_delta) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta)) {
|
||||
subghz_protocol_common_add_bit(&instance->common, 1);
|
||||
instance->common.parser_step = NeroSketchDecoderStepSaveDuration;
|
||||
} else {
|
||||
instance->common.parser_step = NeroSketchDecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
instance->common.parser_step = NeroSketchDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void subghz_protocol_nero_sketch_to_str(SubGhzProtocolNeroSketch* instance, string_t output) {
|
||||
uint32_t code_found_hi = instance->common.code_last_found >> 32;
|
||||
uint32_t code_found_lo = instance->common.code_last_found & 0x00000000ffffffff;
|
||||
|
||||
uint64_t code_found_reverse = subghz_protocol_common_reverse_key(
|
||||
instance->common.code_last_found, instance->common.code_last_count_bit);
|
||||
|
||||
uint32_t code_found_reverse_hi = code_found_reverse >> 32;
|
||||
uint32_t code_found_reverse_lo = code_found_reverse & 0x00000000ffffffff;
|
||||
|
||||
string_cat_printf(
|
||||
output,
|
||||
"%s %dbit\r\n"
|
||||
"Key:0x%lX%08lX\r\n"
|
||||
"Yek:0x%lX%08lX\r\n",
|
||||
instance->common.name,
|
||||
instance->common.code_last_count_bit,
|
||||
code_found_hi,
|
||||
code_found_lo,
|
||||
code_found_reverse_hi,
|
||||
code_found_reverse_lo);
|
||||
}
|
||||
|
||||
void subghz_protocol_nero_sketch_to_save_str(SubGhzProtocolNeroSketch* instance, string_t output) {
|
||||
uint32_t code_found_hi = instance->common.code_last_found >> 32;
|
||||
uint32_t code_found_lo = instance->common.code_last_found & 0x00000000ffffffff;
|
||||
|
||||
string_printf(
|
||||
output,
|
||||
"Protocol: %s\n"
|
||||
"Bit: %d\n"
|
||||
"Key: %08lX%08lX\n",
|
||||
instance->common.name,
|
||||
instance->common.code_last_count_bit,
|
||||
code_found_hi,
|
||||
code_found_lo);
|
||||
}
|
||||
|
||||
bool subghz_protocol_nero_sketch_to_load_protocol_from_file(
|
||||
FileWorker* file_worker,
|
||||
SubGhzProtocolNeroSketch* instance) {
|
||||
bool loaded = false;
|
||||
string_t temp_str;
|
||||
string_init(temp_str);
|
||||
int res = 0;
|
||||
int data = 0;
|
||||
|
||||
do {
|
||||
// Read and parse bit data from 2nd line
|
||||
if(!file_worker_read_until(file_worker, temp_str, '\n')) {
|
||||
break;
|
||||
}
|
||||
res = sscanf(string_get_cstr(temp_str), "Bit: %d\n", &data);
|
||||
if(res != 1) {
|
||||
break;
|
||||
}
|
||||
instance->common.code_last_count_bit = (uint8_t)data;
|
||||
|
||||
// Read and parse key data from 3nd line
|
||||
if(!file_worker_read_until(file_worker, temp_str, '\n')) {
|
||||
break;
|
||||
}
|
||||
uint32_t temp_key_hi = 0;
|
||||
uint32_t temp_key_lo = 0;
|
||||
res = sscanf(string_get_cstr(temp_str), "Key: %08lX%08lX\n", &temp_key_hi, &temp_key_lo);
|
||||
if(res != 2) {
|
||||
break;
|
||||
}
|
||||
instance->common.code_last_found = (uint64_t)temp_key_hi << 32 | temp_key_lo;
|
||||
|
||||
loaded = true;
|
||||
} while(0);
|
||||
|
||||
string_clear(temp_str);
|
||||
|
||||
return loaded;
|
||||
}
|
||||
|
||||
void subghz_decoder_nero_sketch_to_load_protocol(SubGhzProtocolNeroSketch* instance, void* context) {
|
||||
furi_assert(context);
|
||||
furi_assert(instance);
|
||||
SubGhzProtocolCommonLoad* data = context;
|
||||
instance->common.code_last_found = data->code_found;
|
||||
instance->common.code_last_count_bit = data->code_count_bit;
|
||||
#include "subghz_protocol_nero_sketch.h"
|
||||
|
||||
struct SubGhzProtocolNeroSketch {
|
||||
SubGhzProtocolCommon common;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
NeroSketchDecoderStepReset = 0,
|
||||
NeroSketchDecoderStepCheckPreambula,
|
||||
NeroSketchDecoderStepSaveDuration,
|
||||
NeroSketchDecoderStepCheckDuration,
|
||||
} NeroSketchDecoderStep;
|
||||
|
||||
SubGhzProtocolNeroSketch* subghz_protocol_nero_sketch_alloc(void) {
|
||||
SubGhzProtocolNeroSketch* instance = furi_alloc(sizeof(SubGhzProtocolNeroSketch));
|
||||
|
||||
instance->common.name = "Nero Sketch";
|
||||
instance->common.code_min_count_bit_for_found = 40;
|
||||
instance->common.te_short = 330;
|
||||
instance->common.te_long = 660;
|
||||
instance->common.te_delta = 150;
|
||||
instance->common.type_protocol = SubGhzProtocolCommonTypeStatic;
|
||||
instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_protocol_nero_sketch_to_str;
|
||||
instance->common.to_save_string =
|
||||
(SubGhzProtocolCommonGetStrSave)subghz_protocol_nero_sketch_to_save_str;
|
||||
instance->common.to_load_protocol_from_file =
|
||||
(SubGhzProtocolCommonLoadFromFile)subghz_protocol_nero_sketch_to_load_protocol_from_file;
|
||||
instance->common.to_load_protocol =
|
||||
(SubGhzProtocolCommonLoadFromRAW)subghz_decoder_nero_sketch_to_load_protocol;
|
||||
instance->common.get_upload_protocol =
|
||||
(SubGhzProtocolCommonEncoderGetUpLoad)subghz_protocol_nero_sketch_send_key;
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void subghz_protocol_nero_sketch_free(SubGhzProtocolNeroSketch* instance) {
|
||||
furi_assert(instance);
|
||||
free(instance);
|
||||
}
|
||||
|
||||
bool subghz_protocol_nero_sketch_send_key(
|
||||
SubGhzProtocolNeroSketch* instance,
|
||||
SubGhzProtocolCommonEncoder* encoder) {
|
||||
furi_assert(instance);
|
||||
furi_assert(encoder);
|
||||
size_t index = 0;
|
||||
encoder->size_upload = 47 * 2 + 2 + (instance->common.code_last_count_bit * 2) + 2;
|
||||
if(encoder->size_upload > SUBGHZ_ENCODER_UPLOAD_MAX_SIZE) return false;
|
||||
|
||||
//Send header
|
||||
for(uint8_t i = 0; i < 47; i++) {
|
||||
encoder->upload[index++] = level_duration_make(true, (uint32_t)instance->common.te_short);
|
||||
encoder->upload[index++] = level_duration_make(false, (uint32_t)instance->common.te_short);
|
||||
}
|
||||
|
||||
//Send start bit
|
||||
encoder->upload[index++] = level_duration_make(true, (uint32_t)instance->common.te_short * 4);
|
||||
encoder->upload[index++] = level_duration_make(false, (uint32_t)instance->common.te_short);
|
||||
|
||||
//Send key data
|
||||
for(uint8_t i = instance->common.code_last_count_bit; i > 0; i--) {
|
||||
if(bit_read(instance->common.code_last_found, i - 1)) {
|
||||
//send bit 1
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(true, (uint32_t)instance->common.te_long);
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(false, (uint32_t)instance->common.te_short);
|
||||
} else {
|
||||
//send bit 0
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(true, (uint32_t)instance->common.te_short);
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(false, (uint32_t)instance->common.te_long);
|
||||
}
|
||||
}
|
||||
|
||||
//Send stop bit
|
||||
encoder->upload[index++] = level_duration_make(true, (uint32_t)instance->common.te_short * 3);
|
||||
encoder->upload[index++] = level_duration_make(false, (uint32_t)instance->common.te_short);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void subghz_protocol_nero_sketch_reset(SubGhzProtocolNeroSketch* instance) {
|
||||
instance->common.parser_step = NeroSketchDecoderStepReset;
|
||||
}
|
||||
|
||||
/** Analysis of received data
|
||||
*
|
||||
* @param instance SubGhzProtocolNeroSketch instance
|
||||
*/
|
||||
// void subghz_protocol_nero_sketch_check_remote_controller(SubGhzProtocolNeroSketch* instance) {
|
||||
// //пока не понятно с серийником, но код статический
|
||||
// // uint64_t code_found_reverse = subghz_protocol_common_reverse_key(instance->common.code_found, instance->common.code_count_bit);
|
||||
// // uint32_t code_fix = code_found_reverse & 0xFFFFFFFF;
|
||||
// // //uint32_t code_hop = (code_found_reverse >> 24) & 0xFFFFF;
|
||||
|
||||
// // instance->common.serial = code_fix & 0xFFFFFFF;
|
||||
// // instance->common.btn = (code_fix >> 28) & 0x0F;
|
||||
|
||||
// //if (instance->common.callback) instance->common.callback((SubGhzProtocolCommon*)instance, instance->common.context);
|
||||
|
||||
// }
|
||||
|
||||
void subghz_protocol_nero_sketch_parse(
|
||||
SubGhzProtocolNeroSketch* instance,
|
||||
bool level,
|
||||
uint32_t duration) {
|
||||
switch(instance->common.parser_step) {
|
||||
case NeroSketchDecoderStepReset:
|
||||
if((level) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta)) {
|
||||
instance->common.parser_step = NeroSketchDecoderStepCheckPreambula;
|
||||
instance->common.te_last = duration;
|
||||
instance->common.header_count = 0;
|
||||
} else {
|
||||
instance->common.parser_step = NeroSketchDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case NeroSketchDecoderStepCheckPreambula:
|
||||
if(level) {
|
||||
if((DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta) ||
|
||||
(DURATION_DIFF(duration, instance->common.te_short * 4) <
|
||||
instance->common.te_delta)) {
|
||||
instance->common.te_last = duration;
|
||||
} else {
|
||||
instance->common.parser_step = NeroSketchDecoderStepReset;
|
||||
}
|
||||
} else if(DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta) {
|
||||
if(DURATION_DIFF(instance->common.te_last, instance->common.te_short) <
|
||||
instance->common.te_delta) {
|
||||
// Found header
|
||||
instance->common.header_count++;
|
||||
break;
|
||||
} else if(
|
||||
DURATION_DIFF(instance->common.te_last, instance->common.te_short * 4) <
|
||||
instance->common.te_delta) {
|
||||
// Found start bit
|
||||
if(instance->common.header_count > 40) {
|
||||
instance->common.parser_step = NeroSketchDecoderStepSaveDuration;
|
||||
instance->common.code_found = 0;
|
||||
instance->common.code_count_bit = 0;
|
||||
} else {
|
||||
instance->common.parser_step = NeroSketchDecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
instance->common.parser_step = NeroSketchDecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
instance->common.parser_step = NeroSketchDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case NeroSketchDecoderStepSaveDuration:
|
||||
if(level) {
|
||||
if(duration >= (instance->common.te_short * 2 + instance->common.te_delta * 2)) {
|
||||
//Found stop bit
|
||||
instance->common.parser_step = NeroSketchDecoderStepReset;
|
||||
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_count_bit = instance->common.code_count_bit;
|
||||
if(instance->common.callback)
|
||||
instance->common.callback(
|
||||
(SubGhzProtocolCommon*)instance, instance->common.context);
|
||||
}
|
||||
instance->common.code_found = 0;
|
||||
instance->common.code_count_bit = 0;
|
||||
break;
|
||||
} else {
|
||||
instance->common.te_last = duration;
|
||||
instance->common.parser_step = NeroSketchDecoderStepCheckDuration;
|
||||
}
|
||||
|
||||
} else {
|
||||
instance->common.parser_step = NeroSketchDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case NeroSketchDecoderStepCheckDuration:
|
||||
if(!level) {
|
||||
if((DURATION_DIFF(instance->common.te_last, instance->common.te_short) <
|
||||
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 = NeroSketchDecoderStepSaveDuration;
|
||||
} else if(
|
||||
(DURATION_DIFF(instance->common.te_last, instance->common.te_long) <
|
||||
instance->common.te_delta) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta)) {
|
||||
subghz_protocol_common_add_bit(&instance->common, 1);
|
||||
instance->common.parser_step = NeroSketchDecoderStepSaveDuration;
|
||||
} else {
|
||||
instance->common.parser_step = NeroSketchDecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
instance->common.parser_step = NeroSketchDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void subghz_protocol_nero_sketch_to_str(SubGhzProtocolNeroSketch* instance, string_t output) {
|
||||
uint32_t code_found_hi = instance->common.code_last_found >> 32;
|
||||
uint32_t code_found_lo = instance->common.code_last_found & 0x00000000ffffffff;
|
||||
|
||||
uint64_t code_found_reverse = subghz_protocol_common_reverse_key(
|
||||
instance->common.code_last_found, instance->common.code_last_count_bit);
|
||||
|
||||
uint32_t code_found_reverse_hi = code_found_reverse >> 32;
|
||||
uint32_t code_found_reverse_lo = code_found_reverse & 0x00000000ffffffff;
|
||||
|
||||
string_cat_printf(
|
||||
output,
|
||||
"%s %dbit\r\n"
|
||||
"Key:0x%lX%08lX\r\n"
|
||||
"Yek:0x%lX%08lX\r\n",
|
||||
instance->common.name,
|
||||
instance->common.code_last_count_bit,
|
||||
code_found_hi,
|
||||
code_found_lo,
|
||||
code_found_reverse_hi,
|
||||
code_found_reverse_lo);
|
||||
}
|
||||
|
||||
void subghz_protocol_nero_sketch_to_save_str(SubGhzProtocolNeroSketch* instance, string_t output) {
|
||||
uint32_t code_found_hi = instance->common.code_last_found >> 32;
|
||||
uint32_t code_found_lo = instance->common.code_last_found & 0x00000000ffffffff;
|
||||
|
||||
string_printf(
|
||||
output,
|
||||
"Protocol: %s\n"
|
||||
"Bit: %d\n"
|
||||
"Key: %08lX%08lX\n",
|
||||
instance->common.name,
|
||||
instance->common.code_last_count_bit,
|
||||
code_found_hi,
|
||||
code_found_lo);
|
||||
}
|
||||
|
||||
bool subghz_protocol_nero_sketch_to_load_protocol_from_file(
|
||||
FileWorker* file_worker,
|
||||
SubGhzProtocolNeroSketch* instance) {
|
||||
bool loaded = false;
|
||||
string_t temp_str;
|
||||
string_init(temp_str);
|
||||
int res = 0;
|
||||
int data = 0;
|
||||
|
||||
do {
|
||||
// Read and parse bit data from 2nd line
|
||||
if(!file_worker_read_until(file_worker, temp_str, '\n')) {
|
||||
break;
|
||||
}
|
||||
res = sscanf(string_get_cstr(temp_str), "Bit: %d\n", &data);
|
||||
if(res != 1) {
|
||||
break;
|
||||
}
|
||||
instance->common.code_last_count_bit = (uint8_t)data;
|
||||
|
||||
// Read and parse key data from 3nd line
|
||||
if(!file_worker_read_until(file_worker, temp_str, '\n')) {
|
||||
break;
|
||||
}
|
||||
uint32_t temp_key_hi = 0;
|
||||
uint32_t temp_key_lo = 0;
|
||||
res = sscanf(string_get_cstr(temp_str), "Key: %08lX%08lX\n", &temp_key_hi, &temp_key_lo);
|
||||
if(res != 2) {
|
||||
break;
|
||||
}
|
||||
instance->common.code_last_found = (uint64_t)temp_key_hi << 32 | temp_key_lo;
|
||||
|
||||
loaded = true;
|
||||
} while(0);
|
||||
|
||||
string_clear(temp_str);
|
||||
|
||||
return loaded;
|
||||
}
|
||||
|
||||
void subghz_decoder_nero_sketch_to_load_protocol(SubGhzProtocolNeroSketch* instance, void* context) {
|
||||
furi_assert(context);
|
||||
furi_assert(instance);
|
||||
SubGhzProtocolCommonLoad* data = context;
|
||||
instance->common.code_last_found = data->code_found;
|
||||
instance->common.code_last_count_bit = data->code_count_bit;
|
||||
}
|
@@ -1,72 +1,72 @@
|
||||
#pragma once
|
||||
|
||||
#include "subghz_protocol_common.h"
|
||||
|
||||
typedef struct SubGhzProtocolNeroSketch SubGhzProtocolNeroSketch;
|
||||
|
||||
/** Allocate SubGhzProtocolNeroSketch
|
||||
*
|
||||
* @return SubGhzProtocolNeroSketch*
|
||||
*/
|
||||
SubGhzProtocolNeroSketch* subghz_protocol_nero_sketch_alloc();
|
||||
|
||||
/** Free SubGhzProtocolNeroSketch
|
||||
*
|
||||
* @param instance
|
||||
*/
|
||||
void subghz_protocol_nero_sketch_free(SubGhzProtocolNeroSketch* instance);
|
||||
|
||||
/** Get upload protocol
|
||||
*
|
||||
* @param instance - SubGhzProtocolNeroSketch instance
|
||||
* @param encoder - SubGhzProtocolCommonEncoder encoder
|
||||
* @return bool
|
||||
*/
|
||||
bool subghz_protocol_nero_sketch_send_key(SubGhzProtocolNeroSketch* instance, SubGhzProtocolCommonEncoder* encoder);
|
||||
|
||||
/** Reset internal state
|
||||
* @param instance - SubGhzProtocolNeroSketch instance
|
||||
*/
|
||||
void subghz_protocol_nero_sketch_reset(SubGhzProtocolNeroSketch* instance);
|
||||
|
||||
/** Analysis of received data
|
||||
*
|
||||
* @param instance SubGhzProtocolNeroSketch instance
|
||||
*/
|
||||
void subghz_protocol_nero_sketch_check_remote_controller(SubGhzProtocolNeroSketch* instance);
|
||||
|
||||
/** Parse accepted duration
|
||||
*
|
||||
* @param instance - SubGhzProtocolNeroSketch instance
|
||||
* @param data - LevelDuration level_duration
|
||||
*/
|
||||
void subghz_protocol_nero_sketch_parse(SubGhzProtocolNeroSketch* instance, bool level, uint32_t duration);
|
||||
|
||||
/** Outputting information from the parser
|
||||
*
|
||||
* @param instance - SubGhzProtocolNeroSketch* instance
|
||||
* @param output - output string
|
||||
*/
|
||||
void subghz_protocol_nero_sketch_to_str(SubGhzProtocolNeroSketch* instance, string_t output);
|
||||
|
||||
/** Get a string to save the protocol
|
||||
*
|
||||
* @param instance - SubGhzProtocolNeroSketch instance
|
||||
* @param output - the resulting string
|
||||
*/
|
||||
void subghz_protocol_nero_sketch_to_save_str(SubGhzProtocolNeroSketch* instance, string_t output);
|
||||
|
||||
/** Loading protocol from file
|
||||
*
|
||||
* @param file_worker - FileWorker file_worker
|
||||
* @param instance - SubGhzProtocolNeroSketch instance
|
||||
* @return bool
|
||||
*/
|
||||
bool subghz_protocol_nero_sketch_to_load_protocol_from_file(FileWorker* file_worker, SubGhzProtocolNeroSketch* instance);
|
||||
|
||||
/** Loading protocol from bin data
|
||||
*
|
||||
* @param instance - SubGhzProtocolNeroSketch instance
|
||||
* @param context - SubGhzProtocolCommonLoad context
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "subghz_protocol_common.h"
|
||||
|
||||
typedef struct SubGhzProtocolNeroSketch SubGhzProtocolNeroSketch;
|
||||
|
||||
/** Allocate SubGhzProtocolNeroSketch
|
||||
*
|
||||
* @return SubGhzProtocolNeroSketch*
|
||||
*/
|
||||
SubGhzProtocolNeroSketch* subghz_protocol_nero_sketch_alloc();
|
||||
|
||||
/** Free SubGhzProtocolNeroSketch
|
||||
*
|
||||
* @param instance
|
||||
*/
|
||||
void subghz_protocol_nero_sketch_free(SubGhzProtocolNeroSketch* instance);
|
||||
|
||||
/** Get upload protocol
|
||||
*
|
||||
* @param instance - SubGhzProtocolNeroSketch instance
|
||||
* @param encoder - SubGhzProtocolCommonEncoder encoder
|
||||
* @return bool
|
||||
*/
|
||||
bool subghz_protocol_nero_sketch_send_key(SubGhzProtocolNeroSketch* instance, SubGhzProtocolCommonEncoder* encoder);
|
||||
|
||||
/** Reset internal state
|
||||
* @param instance - SubGhzProtocolNeroSketch instance
|
||||
*/
|
||||
void subghz_protocol_nero_sketch_reset(SubGhzProtocolNeroSketch* instance);
|
||||
|
||||
/** Analysis of received data
|
||||
*
|
||||
* @param instance SubGhzProtocolNeroSketch instance
|
||||
*/
|
||||
void subghz_protocol_nero_sketch_check_remote_controller(SubGhzProtocolNeroSketch* instance);
|
||||
|
||||
/** Parse accepted duration
|
||||
*
|
||||
* @param instance - SubGhzProtocolNeroSketch instance
|
||||
* @param data - LevelDuration level_duration
|
||||
*/
|
||||
void subghz_protocol_nero_sketch_parse(SubGhzProtocolNeroSketch* instance, bool level, uint32_t duration);
|
||||
|
||||
/** Outputting information from the parser
|
||||
*
|
||||
* @param instance - SubGhzProtocolNeroSketch* instance
|
||||
* @param output - output string
|
||||
*/
|
||||
void subghz_protocol_nero_sketch_to_str(SubGhzProtocolNeroSketch* instance, string_t output);
|
||||
|
||||
/** Get a string to save the protocol
|
||||
*
|
||||
* @param instance - SubGhzProtocolNeroSketch instance
|
||||
* @param output - the resulting string
|
||||
*/
|
||||
void subghz_protocol_nero_sketch_to_save_str(SubGhzProtocolNeroSketch* instance, string_t output);
|
||||
|
||||
/** Loading protocol from file
|
||||
*
|
||||
* @param file_worker - FileWorker file_worker
|
||||
* @param instance - SubGhzProtocolNeroSketch instance
|
||||
* @return bool
|
||||
*/
|
||||
bool subghz_protocol_nero_sketch_to_load_protocol_from_file(FileWorker* file_worker, SubGhzProtocolNeroSketch* instance);
|
||||
|
||||
/** Loading protocol from bin data
|
||||
*
|
||||
* @param instance - SubGhzProtocolNeroSketch instance
|
||||
* @param context - SubGhzProtocolCommonLoad context
|
||||
*/
|
||||
void subghz_decoder_nero_sketch_to_load_protocol(SubGhzProtocolNeroSketch* instance, void* context);
|
@@ -1,227 +1,227 @@
|
||||
#include "subghz_protocol_nice_flo.h"
|
||||
|
||||
/*
|
||||
* Help
|
||||
* https://phreakerclub.com/447
|
||||
*
|
||||
*/
|
||||
|
||||
struct SubGhzProtocolNiceFlo {
|
||||
SubGhzProtocolCommon common;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
NiceFloDecoderStepReset = 0,
|
||||
NiceFloDecoderStepFoundStartBit,
|
||||
NiceFloDecoderStepSaveDuration,
|
||||
NiceFloDecoderStepCheckDuration,
|
||||
} NiceFloDecoderStep;
|
||||
|
||||
SubGhzProtocolNiceFlo* subghz_protocol_nice_flo_alloc() {
|
||||
SubGhzProtocolNiceFlo* instance = furi_alloc(sizeof(SubGhzProtocolNiceFlo));
|
||||
|
||||
instance->common.name = "Nice FLO";
|
||||
instance->common.code_min_count_bit_for_found = 12;
|
||||
instance->common.te_short = 700;
|
||||
instance->common.te_long = 1400;
|
||||
instance->common.te_delta = 200;
|
||||
instance->common.type_protocol = SubGhzProtocolCommonTypeStatic;
|
||||
instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_protocol_nice_flo_to_str;
|
||||
instance->common.to_save_string =
|
||||
(SubGhzProtocolCommonGetStrSave)subghz_protocol_nice_flo_to_save_str;
|
||||
instance->common.to_load_protocol_from_file =
|
||||
(SubGhzProtocolCommonLoadFromFile)subghz_protocol_nice_flo_to_load_protocol_from_file;
|
||||
instance->common.to_load_protocol =
|
||||
(SubGhzProtocolCommonLoadFromRAW)subghz_decoder_nice_flo_to_load_protocol;
|
||||
instance->common.get_upload_protocol =
|
||||
(SubGhzProtocolCommonEncoderGetUpLoad)subghz_protocol_nice_flo_send_key;
|
||||
return instance;
|
||||
}
|
||||
|
||||
void subghz_protocol_nice_flo_free(SubGhzProtocolNiceFlo* instance) {
|
||||
furi_assert(instance);
|
||||
free(instance);
|
||||
}
|
||||
|
||||
bool subghz_protocol_nice_flo_send_key(
|
||||
SubGhzProtocolNiceFlo* instance,
|
||||
SubGhzProtocolCommonEncoder* encoder) {
|
||||
furi_assert(instance);
|
||||
furi_assert(encoder);
|
||||
size_t index = 0;
|
||||
encoder->size_upload = (instance->common.code_last_count_bit * 2) + 2;
|
||||
if(encoder->size_upload > SUBGHZ_ENCODER_UPLOAD_MAX_SIZE) return false;
|
||||
//Send header
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(false, (uint32_t)instance->common.te_short * 36);
|
||||
//Send start bit
|
||||
encoder->upload[index++] = level_duration_make(true, (uint32_t)instance->common.te_short);
|
||||
//Send key data
|
||||
for(uint8_t i = instance->common.code_last_count_bit; i > 0; i--) {
|
||||
if(bit_read(instance->common.code_last_found, i - 1)) {
|
||||
//send bit 1
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(false, (uint32_t)instance->common.te_long);
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(true, (uint32_t)instance->common.te_short);
|
||||
} else {
|
||||
//send bit 0
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(false, (uint32_t)instance->common.te_short);
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(true, (uint32_t)instance->common.te_long);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void subghz_protocol_nice_flo_reset(SubGhzProtocolNiceFlo* instance) {
|
||||
instance->common.parser_step = NiceFloDecoderStepReset;
|
||||
}
|
||||
|
||||
void subghz_protocol_nice_flo_parse(SubGhzProtocolNiceFlo* instance, bool level, uint32_t duration) {
|
||||
switch(instance->common.parser_step) {
|
||||
case NiceFloDecoderStepReset:
|
||||
if((!level) && (DURATION_DIFF(duration, instance->common.te_short * 36) <
|
||||
instance->common.te_delta * 36)) {
|
||||
//Found header Nice Flo
|
||||
instance->common.parser_step = NiceFloDecoderStepFoundStartBit;
|
||||
} else {
|
||||
instance->common.parser_step = NiceFloDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case NiceFloDecoderStepFoundStartBit:
|
||||
if(!level) {
|
||||
break;
|
||||
} else if(DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta) {
|
||||
//Found start bit Nice Flo
|
||||
instance->common.parser_step = NiceFloDecoderStepSaveDuration;
|
||||
instance->common.code_found = 0;
|
||||
instance->common.code_count_bit = 0;
|
||||
} else {
|
||||
instance->common.parser_step = NiceFloDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case NiceFloDecoderStepSaveDuration:
|
||||
if(!level) { //save interval
|
||||
if(duration >= (instance->common.te_short * 4)) {
|
||||
instance->common.parser_step = NiceFloDecoderStepFoundStartBit;
|
||||
if(instance->common.code_count_bit >=
|
||||
instance->common.code_min_count_bit_for_found) {
|
||||
instance->common.serial = 0x0;
|
||||
instance->common.btn = 0x0;
|
||||
|
||||
instance->common.code_last_found = instance->common.code_found;
|
||||
instance->common.code_last_count_bit = instance->common.code_count_bit;
|
||||
if(instance->common.callback)
|
||||
instance->common.callback(
|
||||
(SubGhzProtocolCommon*)instance, instance->common.context);
|
||||
}
|
||||
break;
|
||||
}
|
||||
instance->common.te_last = duration;
|
||||
instance->common.parser_step = NiceFloDecoderStepCheckDuration;
|
||||
} else {
|
||||
instance->common.parser_step = NiceFloDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case NiceFloDecoderStepCheckDuration:
|
||||
if(level) {
|
||||
if((DURATION_DIFF(instance->common.te_last, instance->common.te_short) <
|
||||
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 = NiceFloDecoderStepSaveDuration;
|
||||
} else if(
|
||||
(DURATION_DIFF(instance->common.te_last, instance->common.te_long) <
|
||||
instance->common.te_delta) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta)) {
|
||||
subghz_protocol_common_add_bit(&instance->common, 1);
|
||||
instance->common.parser_step = NiceFloDecoderStepSaveDuration;
|
||||
} else
|
||||
instance->common.parser_step = NiceFloDecoderStepReset;
|
||||
} else {
|
||||
instance->common.parser_step = NiceFloDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void subghz_protocol_nice_flo_to_str(SubGhzProtocolNiceFlo* instance, string_t output) {
|
||||
uint32_t code_found_lo = instance->common.code_last_found & 0x00000000ffffffff;
|
||||
|
||||
uint64_t code_found_reverse = subghz_protocol_common_reverse_key(
|
||||
instance->common.code_last_found, instance->common.code_last_count_bit);
|
||||
|
||||
uint32_t code_found_reverse_lo = code_found_reverse & 0x00000000ffffffff;
|
||||
|
||||
string_cat_printf(
|
||||
output,
|
||||
"%s %dbit\r\n"
|
||||
"Key:0x%08lX\r\n"
|
||||
"Yek:0x%08lX\r\n",
|
||||
instance->common.name,
|
||||
instance->common.code_last_count_bit,
|
||||
code_found_lo,
|
||||
code_found_reverse_lo);
|
||||
}
|
||||
|
||||
void subghz_protocol_nice_flo_to_save_str(SubGhzProtocolNiceFlo* instance, string_t output) {
|
||||
string_printf(
|
||||
output,
|
||||
"Protocol: %s\n"
|
||||
"Bit: %d\n"
|
||||
"Key: %08lX\n",
|
||||
instance->common.name,
|
||||
instance->common.code_last_count_bit,
|
||||
(uint32_t)(instance->common.code_last_found & 0x00000000ffffffff));
|
||||
}
|
||||
|
||||
bool subghz_protocol_nice_flo_to_load_protocol_from_file(
|
||||
FileWorker* file_worker,
|
||||
SubGhzProtocolNiceFlo* instance) {
|
||||
bool loaded = false;
|
||||
string_t temp_str;
|
||||
string_init(temp_str);
|
||||
int res = 0;
|
||||
int data = 0;
|
||||
|
||||
do {
|
||||
// Read and parse bit data from 2nd line
|
||||
if(!file_worker_read_until(file_worker, temp_str, '\n')) {
|
||||
break;
|
||||
}
|
||||
res = sscanf(string_get_cstr(temp_str), "Bit: %d\n", &data);
|
||||
if(res != 1) {
|
||||
break;
|
||||
}
|
||||
instance->common.code_last_count_bit = (uint8_t)data;
|
||||
|
||||
// Read and parse key data from 3nd line
|
||||
if(!file_worker_read_until(file_worker, temp_str, '\n')) {
|
||||
break;
|
||||
}
|
||||
uint32_t temp_key = 0;
|
||||
res = sscanf(string_get_cstr(temp_str), "Key: %08lX\n", &temp_key);
|
||||
if(res != 1) {
|
||||
break;
|
||||
}
|
||||
instance->common.code_last_found = (uint64_t)temp_key;
|
||||
|
||||
loaded = true;
|
||||
} while(0);
|
||||
|
||||
string_clear(temp_str);
|
||||
|
||||
return loaded;
|
||||
}
|
||||
|
||||
void subghz_decoder_nice_flo_to_load_protocol(SubGhzProtocolNiceFlo* instance, void* context) {
|
||||
furi_assert(context);
|
||||
furi_assert(instance);
|
||||
SubGhzProtocolCommonLoad* data = context;
|
||||
instance->common.code_last_found = data->code_found;
|
||||
instance->common.code_last_count_bit = data->code_count_bit;
|
||||
instance->common.serial = 0x0;
|
||||
instance->common.btn = 0x0;
|
||||
#include "subghz_protocol_nice_flo.h"
|
||||
|
||||
/*
|
||||
* Help
|
||||
* https://phreakerclub.com/447
|
||||
*
|
||||
*/
|
||||
|
||||
struct SubGhzProtocolNiceFlo {
|
||||
SubGhzProtocolCommon common;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
NiceFloDecoderStepReset = 0,
|
||||
NiceFloDecoderStepFoundStartBit,
|
||||
NiceFloDecoderStepSaveDuration,
|
||||
NiceFloDecoderStepCheckDuration,
|
||||
} NiceFloDecoderStep;
|
||||
|
||||
SubGhzProtocolNiceFlo* subghz_protocol_nice_flo_alloc() {
|
||||
SubGhzProtocolNiceFlo* instance = furi_alloc(sizeof(SubGhzProtocolNiceFlo));
|
||||
|
||||
instance->common.name = "Nice FLO";
|
||||
instance->common.code_min_count_bit_for_found = 12;
|
||||
instance->common.te_short = 700;
|
||||
instance->common.te_long = 1400;
|
||||
instance->common.te_delta = 200;
|
||||
instance->common.type_protocol = SubGhzProtocolCommonTypeStatic;
|
||||
instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_protocol_nice_flo_to_str;
|
||||
instance->common.to_save_string =
|
||||
(SubGhzProtocolCommonGetStrSave)subghz_protocol_nice_flo_to_save_str;
|
||||
instance->common.to_load_protocol_from_file =
|
||||
(SubGhzProtocolCommonLoadFromFile)subghz_protocol_nice_flo_to_load_protocol_from_file;
|
||||
instance->common.to_load_protocol =
|
||||
(SubGhzProtocolCommonLoadFromRAW)subghz_decoder_nice_flo_to_load_protocol;
|
||||
instance->common.get_upload_protocol =
|
||||
(SubGhzProtocolCommonEncoderGetUpLoad)subghz_protocol_nice_flo_send_key;
|
||||
return instance;
|
||||
}
|
||||
|
||||
void subghz_protocol_nice_flo_free(SubGhzProtocolNiceFlo* instance) {
|
||||
furi_assert(instance);
|
||||
free(instance);
|
||||
}
|
||||
|
||||
bool subghz_protocol_nice_flo_send_key(
|
||||
SubGhzProtocolNiceFlo* instance,
|
||||
SubGhzProtocolCommonEncoder* encoder) {
|
||||
furi_assert(instance);
|
||||
furi_assert(encoder);
|
||||
size_t index = 0;
|
||||
encoder->size_upload = (instance->common.code_last_count_bit * 2) + 2;
|
||||
if(encoder->size_upload > SUBGHZ_ENCODER_UPLOAD_MAX_SIZE) return false;
|
||||
//Send header
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(false, (uint32_t)instance->common.te_short * 36);
|
||||
//Send start bit
|
||||
encoder->upload[index++] = level_duration_make(true, (uint32_t)instance->common.te_short);
|
||||
//Send key data
|
||||
for(uint8_t i = instance->common.code_last_count_bit; i > 0; i--) {
|
||||
if(bit_read(instance->common.code_last_found, i - 1)) {
|
||||
//send bit 1
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(false, (uint32_t)instance->common.te_long);
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(true, (uint32_t)instance->common.te_short);
|
||||
} else {
|
||||
//send bit 0
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(false, (uint32_t)instance->common.te_short);
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(true, (uint32_t)instance->common.te_long);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void subghz_protocol_nice_flo_reset(SubGhzProtocolNiceFlo* instance) {
|
||||
instance->common.parser_step = NiceFloDecoderStepReset;
|
||||
}
|
||||
|
||||
void subghz_protocol_nice_flo_parse(SubGhzProtocolNiceFlo* instance, bool level, uint32_t duration) {
|
||||
switch(instance->common.parser_step) {
|
||||
case NiceFloDecoderStepReset:
|
||||
if((!level) && (DURATION_DIFF(duration, instance->common.te_short * 36) <
|
||||
instance->common.te_delta * 36)) {
|
||||
//Found header Nice Flo
|
||||
instance->common.parser_step = NiceFloDecoderStepFoundStartBit;
|
||||
} else {
|
||||
instance->common.parser_step = NiceFloDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case NiceFloDecoderStepFoundStartBit:
|
||||
if(!level) {
|
||||
break;
|
||||
} else if(DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta) {
|
||||
//Found start bit Nice Flo
|
||||
instance->common.parser_step = NiceFloDecoderStepSaveDuration;
|
||||
instance->common.code_found = 0;
|
||||
instance->common.code_count_bit = 0;
|
||||
} else {
|
||||
instance->common.parser_step = NiceFloDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case NiceFloDecoderStepSaveDuration:
|
||||
if(!level) { //save interval
|
||||
if(duration >= (instance->common.te_short * 4)) {
|
||||
instance->common.parser_step = NiceFloDecoderStepFoundStartBit;
|
||||
if(instance->common.code_count_bit >=
|
||||
instance->common.code_min_count_bit_for_found) {
|
||||
instance->common.serial = 0x0;
|
||||
instance->common.btn = 0x0;
|
||||
|
||||
instance->common.code_last_found = instance->common.code_found;
|
||||
instance->common.code_last_count_bit = instance->common.code_count_bit;
|
||||
if(instance->common.callback)
|
||||
instance->common.callback(
|
||||
(SubGhzProtocolCommon*)instance, instance->common.context);
|
||||
}
|
||||
break;
|
||||
}
|
||||
instance->common.te_last = duration;
|
||||
instance->common.parser_step = NiceFloDecoderStepCheckDuration;
|
||||
} else {
|
||||
instance->common.parser_step = NiceFloDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case NiceFloDecoderStepCheckDuration:
|
||||
if(level) {
|
||||
if((DURATION_DIFF(instance->common.te_last, instance->common.te_short) <
|
||||
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 = NiceFloDecoderStepSaveDuration;
|
||||
} else if(
|
||||
(DURATION_DIFF(instance->common.te_last, instance->common.te_long) <
|
||||
instance->common.te_delta) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta)) {
|
||||
subghz_protocol_common_add_bit(&instance->common, 1);
|
||||
instance->common.parser_step = NiceFloDecoderStepSaveDuration;
|
||||
} else
|
||||
instance->common.parser_step = NiceFloDecoderStepReset;
|
||||
} else {
|
||||
instance->common.parser_step = NiceFloDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void subghz_protocol_nice_flo_to_str(SubGhzProtocolNiceFlo* instance, string_t output) {
|
||||
uint32_t code_found_lo = instance->common.code_last_found & 0x00000000ffffffff;
|
||||
|
||||
uint64_t code_found_reverse = subghz_protocol_common_reverse_key(
|
||||
instance->common.code_last_found, instance->common.code_last_count_bit);
|
||||
|
||||
uint32_t code_found_reverse_lo = code_found_reverse & 0x00000000ffffffff;
|
||||
|
||||
string_cat_printf(
|
||||
output,
|
||||
"%s %dbit\r\n"
|
||||
"Key:0x%08lX\r\n"
|
||||
"Yek:0x%08lX\r\n",
|
||||
instance->common.name,
|
||||
instance->common.code_last_count_bit,
|
||||
code_found_lo,
|
||||
code_found_reverse_lo);
|
||||
}
|
||||
|
||||
void subghz_protocol_nice_flo_to_save_str(SubGhzProtocolNiceFlo* instance, string_t output) {
|
||||
string_printf(
|
||||
output,
|
||||
"Protocol: %s\n"
|
||||
"Bit: %d\n"
|
||||
"Key: %08lX\n",
|
||||
instance->common.name,
|
||||
instance->common.code_last_count_bit,
|
||||
(uint32_t)(instance->common.code_last_found & 0x00000000ffffffff));
|
||||
}
|
||||
|
||||
bool subghz_protocol_nice_flo_to_load_protocol_from_file(
|
||||
FileWorker* file_worker,
|
||||
SubGhzProtocolNiceFlo* instance) {
|
||||
bool loaded = false;
|
||||
string_t temp_str;
|
||||
string_init(temp_str);
|
||||
int res = 0;
|
||||
int data = 0;
|
||||
|
||||
do {
|
||||
// Read and parse bit data from 2nd line
|
||||
if(!file_worker_read_until(file_worker, temp_str, '\n')) {
|
||||
break;
|
||||
}
|
||||
res = sscanf(string_get_cstr(temp_str), "Bit: %d\n", &data);
|
||||
if(res != 1) {
|
||||
break;
|
||||
}
|
||||
instance->common.code_last_count_bit = (uint8_t)data;
|
||||
|
||||
// Read and parse key data from 3nd line
|
||||
if(!file_worker_read_until(file_worker, temp_str, '\n')) {
|
||||
break;
|
||||
}
|
||||
uint32_t temp_key = 0;
|
||||
res = sscanf(string_get_cstr(temp_str), "Key: %08lX\n", &temp_key);
|
||||
if(res != 1) {
|
||||
break;
|
||||
}
|
||||
instance->common.code_last_found = (uint64_t)temp_key;
|
||||
|
||||
loaded = true;
|
||||
} while(0);
|
||||
|
||||
string_clear(temp_str);
|
||||
|
||||
return loaded;
|
||||
}
|
||||
|
||||
void subghz_decoder_nice_flo_to_load_protocol(SubGhzProtocolNiceFlo* instance, void* context) {
|
||||
furi_assert(context);
|
||||
furi_assert(instance);
|
||||
SubGhzProtocolCommonLoad* data = context;
|
||||
instance->common.code_last_found = data->code_found;
|
||||
instance->common.code_last_count_bit = data->code_count_bit;
|
||||
instance->common.serial = 0x0;
|
||||
instance->common.btn = 0x0;
|
||||
}
|
@@ -1,66 +1,66 @@
|
||||
#pragma once
|
||||
|
||||
#include "subghz_protocol_common.h"
|
||||
|
||||
typedef struct SubGhzProtocolNiceFlo SubGhzProtocolNiceFlo;
|
||||
|
||||
/** Allocate SubGhzProtocolNiceFlo
|
||||
*
|
||||
* @return SubGhzProtocolNiceFlo*
|
||||
*/
|
||||
SubGhzProtocolNiceFlo* subghz_protocol_nice_flo_alloc();
|
||||
|
||||
/** Free SubGhzProtocolNiceFlo
|
||||
*
|
||||
* @param instance
|
||||
*/
|
||||
void subghz_protocol_nice_flo_free(SubGhzProtocolNiceFlo* instance);
|
||||
|
||||
/** Get upload protocol
|
||||
*
|
||||
* @param instance - SubGhzProtocolNiceFlo instance
|
||||
* @param encoder - SubGhzProtocolCommonEncoder encoder
|
||||
* @return bool
|
||||
*/
|
||||
bool subghz_protocol_nice_flo_send_key(SubGhzProtocolNiceFlo* instance, SubGhzProtocolCommonEncoder* encoder);
|
||||
|
||||
/** Reset internal state
|
||||
* @param instance - SubGhzProtocolNiceFlo instance
|
||||
*/
|
||||
void subghz_protocol_nice_flo_reset(SubGhzProtocolNiceFlo* instance);
|
||||
|
||||
/** Parse accepted duration
|
||||
*
|
||||
* @param instance - SubGhzProtocolNiceFlo instance
|
||||
* @param data - LevelDuration level_duration
|
||||
*/
|
||||
void subghz_protocol_nice_flo_parse(SubGhzProtocolNiceFlo* instance, bool level, uint32_t duration);
|
||||
|
||||
/** Outputting information from the parser
|
||||
*
|
||||
* @param instance - SubGhzProtocolNiceFlo* instance
|
||||
* @param output - output string
|
||||
*/
|
||||
void subghz_protocol_nice_flo_to_str(SubGhzProtocolNiceFlo* instance, string_t output);
|
||||
|
||||
/** Get a string to save the protocol
|
||||
*
|
||||
* @param instance - SubGhzProtocolNiceFlo instance
|
||||
* @param output - the resulting string
|
||||
*/
|
||||
void subghz_protocol_nice_flo_to_save_str(SubGhzProtocolNiceFlo* instance, string_t output);
|
||||
|
||||
/** Loading protocol from file
|
||||
*
|
||||
* @param file_worker - FileWorker file_worker
|
||||
* @param instance - SubGhzProtocolNiceFlo instance
|
||||
* @return bool
|
||||
*/
|
||||
bool subghz_protocol_nice_flo_to_load_protocol_from_file(FileWorker* file_worker, SubGhzProtocolNiceFlo* instance);
|
||||
|
||||
/** Loading protocol from bin data
|
||||
*
|
||||
* @param instance - SubGhzProtocolNiceFlo instance
|
||||
* @param context - SubGhzProtocolCommonLoad context
|
||||
*/
|
||||
void subghz_decoder_nice_flo_to_load_protocol(SubGhzProtocolNiceFlo* instance, void* context);
|
||||
#pragma once
|
||||
|
||||
#include "subghz_protocol_common.h"
|
||||
|
||||
typedef struct SubGhzProtocolNiceFlo SubGhzProtocolNiceFlo;
|
||||
|
||||
/** Allocate SubGhzProtocolNiceFlo
|
||||
*
|
||||
* @return SubGhzProtocolNiceFlo*
|
||||
*/
|
||||
SubGhzProtocolNiceFlo* subghz_protocol_nice_flo_alloc();
|
||||
|
||||
/** Free SubGhzProtocolNiceFlo
|
||||
*
|
||||
* @param instance
|
||||
*/
|
||||
void subghz_protocol_nice_flo_free(SubGhzProtocolNiceFlo* instance);
|
||||
|
||||
/** Get upload protocol
|
||||
*
|
||||
* @param instance - SubGhzProtocolNiceFlo instance
|
||||
* @param encoder - SubGhzProtocolCommonEncoder encoder
|
||||
* @return bool
|
||||
*/
|
||||
bool subghz_protocol_nice_flo_send_key(SubGhzProtocolNiceFlo* instance, SubGhzProtocolCommonEncoder* encoder);
|
||||
|
||||
/** Reset internal state
|
||||
* @param instance - SubGhzProtocolNiceFlo instance
|
||||
*/
|
||||
void subghz_protocol_nice_flo_reset(SubGhzProtocolNiceFlo* instance);
|
||||
|
||||
/** Parse accepted duration
|
||||
*
|
||||
* @param instance - SubGhzProtocolNiceFlo instance
|
||||
* @param data - LevelDuration level_duration
|
||||
*/
|
||||
void subghz_protocol_nice_flo_parse(SubGhzProtocolNiceFlo* instance, bool level, uint32_t duration);
|
||||
|
||||
/** Outputting information from the parser
|
||||
*
|
||||
* @param instance - SubGhzProtocolNiceFlo* instance
|
||||
* @param output - output string
|
||||
*/
|
||||
void subghz_protocol_nice_flo_to_str(SubGhzProtocolNiceFlo* instance, string_t output);
|
||||
|
||||
/** Get a string to save the protocol
|
||||
*
|
||||
* @param instance - SubGhzProtocolNiceFlo instance
|
||||
* @param output - the resulting string
|
||||
*/
|
||||
void subghz_protocol_nice_flo_to_save_str(SubGhzProtocolNiceFlo* instance, string_t output);
|
||||
|
||||
/** Loading protocol from file
|
||||
*
|
||||
* @param file_worker - FileWorker file_worker
|
||||
* @param instance - SubGhzProtocolNiceFlo instance
|
||||
* @return bool
|
||||
*/
|
||||
bool subghz_protocol_nice_flo_to_load_protocol_from_file(FileWorker* file_worker, SubGhzProtocolNiceFlo* instance);
|
||||
|
||||
/** Loading protocol from bin data
|
||||
*
|
||||
* @param instance - SubGhzProtocolNiceFlo instance
|
||||
* @param context - SubGhzProtocolCommonLoad context
|
||||
*/
|
||||
void subghz_decoder_nice_flo_to_load_protocol(SubGhzProtocolNiceFlo* instance, void* context);
|
||||
|
@@ -1,267 +1,267 @@
|
||||
#include "subghz_protocol_nice_flor_s.h"
|
||||
|
||||
#include <furi.h>
|
||||
#include "file-worker.h"
|
||||
/*
|
||||
* https://phreakerclub.com/1615
|
||||
* https://phreakerclub.com/forum/showthread.php?t=2360
|
||||
* https://vrtp.ru/index.php?showtopic=27867
|
||||
*/
|
||||
|
||||
struct SubGhzProtocolNiceFlorS {
|
||||
SubGhzProtocolCommon common;
|
||||
const char* rainbow_table_file_name;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
NiceFlorSDecoderStepReset = 0,
|
||||
NiceFlorSDecoderStepCheckHeader,
|
||||
NiceFlorSDecoderStepFoundHeader,
|
||||
NiceFlorSDecoderStepSaveDuration,
|
||||
NiceFlorSDecoderStepCheckDuration,
|
||||
} NiceFlorSDecoderStep;
|
||||
|
||||
SubGhzProtocolNiceFlorS* subghz_protocol_nice_flor_s_alloc() {
|
||||
SubGhzProtocolNiceFlorS* instance = furi_alloc(sizeof(SubGhzProtocolNiceFlorS));
|
||||
|
||||
instance->common.name = "Nice FloR-S";
|
||||
instance->common.code_min_count_bit_for_found = 52;
|
||||
instance->common.te_short = 500;
|
||||
instance->common.te_long = 1000;
|
||||
instance->common.te_delta = 300;
|
||||
instance->common.type_protocol = SubGhzProtocolCommonTypeDynamic;
|
||||
instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_protocol_nice_flor_s_to_str;
|
||||
instance->common.to_load_protocol =
|
||||
(SubGhzProtocolCommonLoadFromRAW)subghz_decoder_nice_flor_s_to_load_protocol;
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void subghz_protocol_nice_flor_s_free(SubGhzProtocolNiceFlorS* instance) {
|
||||
furi_assert(instance);
|
||||
free(instance);
|
||||
}
|
||||
|
||||
void subghz_protocol_nice_flor_s_name_file(SubGhzProtocolNiceFlorS* instance, const char* name) {
|
||||
instance->rainbow_table_file_name = name;
|
||||
printf("Loading Nice FloR S rainbow table %s\r\n", name);
|
||||
}
|
||||
|
||||
/** Send bit
|
||||
*
|
||||
* @param instance - SubGhzProtocolNiceFlorS instance
|
||||
* @param bit - bit
|
||||
*/
|
||||
void subghz_protocol_nice_flor_s_send_bit(SubGhzProtocolNiceFlorS* instance, uint8_t bit) {
|
||||
if(bit) {
|
||||
//send bit 1
|
||||
SUBGHZ_TX_PIN_HIGH();
|
||||
delay_us(instance->common.te_long);
|
||||
SUBGHZ_TX_PIN_LOW();
|
||||
delay_us(instance->common.te_short);
|
||||
} else {
|
||||
//send bit 0
|
||||
SUBGHZ_TX_PIN_HIGH();
|
||||
delay_us(instance->common.te_short);
|
||||
SUBGHZ_TX_PIN_LOW();
|
||||
delay_us(instance->common.te_long);
|
||||
}
|
||||
}
|
||||
|
||||
void subghz_protocol_nice_flor_s_send_key(
|
||||
SubGhzProtocolNiceFlorS* instance,
|
||||
uint64_t key,
|
||||
uint8_t bit,
|
||||
uint8_t repeat) {
|
||||
while(repeat--) {
|
||||
//Send header
|
||||
SUBGHZ_TX_PIN_LOW();
|
||||
delay_us(instance->common.te_short * 34);
|
||||
//Send Start Bit
|
||||
SUBGHZ_TX_PIN_HIGH();
|
||||
delay_us(instance->common.te_short * 3);
|
||||
SUBGHZ_TX_PIN_LOW();
|
||||
delay_us(instance->common.te_short * 3);
|
||||
//Send key data
|
||||
for(uint8_t i = bit; i > 0; i--) {
|
||||
subghz_protocol_nice_flor_s_send_bit(instance, bit_read(key, i - 1));
|
||||
}
|
||||
//Send Stop Bit
|
||||
SUBGHZ_TX_PIN_HIGH();
|
||||
delay_us(instance->common.te_short * 3);
|
||||
SUBGHZ_TX_PIN_LOW();
|
||||
delay_us(instance->common.te_short * 3);
|
||||
}
|
||||
}
|
||||
|
||||
/** Read bytes from rainbow table
|
||||
*
|
||||
* @param instance - SubGhzProtocolNiceFlorS* instance
|
||||
* @param address - address byte
|
||||
* @return byte data
|
||||
*/
|
||||
uint8_t subghz_nice_flor_s_get_byte_in_file(SubGhzProtocolNiceFlorS* instance, uint32_t address) {
|
||||
if(!instance->rainbow_table_file_name) return 0;
|
||||
|
||||
uint8_t buffer = 0;
|
||||
FileWorker* file_worker = file_worker_alloc(true);
|
||||
if(file_worker_open(
|
||||
file_worker, instance->rainbow_table_file_name, FSAM_READ, FSOM_OPEN_EXISTING)) {
|
||||
file_worker_seek(file_worker, address, true);
|
||||
file_worker_read(file_worker, &buffer, 1);
|
||||
}
|
||||
file_worker_close(file_worker);
|
||||
file_worker_free(file_worker);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/** Decrypt protocol Nice Flor S
|
||||
*
|
||||
* @param instance - SubGhzProtocolNiceFlorS* instance
|
||||
*/
|
||||
void subghz_nice_flor_s_decoder_decrypt(SubGhzProtocolNiceFlorS* instance) {
|
||||
/*
|
||||
* Packet format Nice Flor-s: START-P0-P1-P2-P3-P4-P5-P6-P7-STOP
|
||||
* P0 (4-bit) - button positional code - 1:0x1, 2:0x2, 3:0x4, 4:0x8;
|
||||
* P1 (4-bit) - batch repetition number, calculated by the formula:
|
||||
* P1 = 0xF ^ P0 ^ n; where n changes from 1 to 15, then 0, and then in a circle
|
||||
* key 1: {0xF,0xC,0xD,0xA,0xB,0x8,0x9,0x6,0x7,0x4,0x5,0x2,0x3,0x0,0x1,0xE};
|
||||
* key 2: {0xC,0xF,0xE,0x9,0x8,0xB,0xA,0x5,0x4,0x7,0x6,0x1,0x0,0x3,0x2,0xD};
|
||||
* key 3: {0xA,0x9,0x8,0xF,0xE,0xD,0xC,0x3,0x2,0x1,0x0,0x7,0x6,0x5,0x4,0xB};
|
||||
* P2 (4-bit) - part of the serial number, P2 = (K ^ S3) & 0xF;
|
||||
* P3 (byte) - the major part of the encrypted index
|
||||
* P4 (byte) - the low-order part of the encrypted index
|
||||
* P5 (byte) - part of the serial number, P5 = K ^ S2;
|
||||
* P6 (byte) - part of the serial number, P6 = K ^ S1;
|
||||
* P7 (byte) - part of the serial number, P7 = K ^ S0;
|
||||
* K (byte) - depends on P3 and P4, K = Fk(P3, P4);
|
||||
* S3,S2,S1,S0 - serial number of the console 28 bit.
|
||||
*/
|
||||
|
||||
uint16_t p3p4 = (uint16_t)(instance->common.code_last_found >> 24);
|
||||
instance->common.cnt = subghz_nice_flor_s_get_byte_in_file(instance, p3p4 * 2) << 8 |
|
||||
subghz_nice_flor_s_get_byte_in_file(instance, p3p4 * 2 + 1);
|
||||
uint8_t k =
|
||||
(uint8_t)(p3p4 & 0x00FF) ^
|
||||
subghz_nice_flor_s_get_byte_in_file(instance, (0x20000 | (instance->common.cnt & 0x00ff)));
|
||||
|
||||
uint8_t s3 = ((uint8_t)(instance->common.code_last_found >> 40) ^ k) & 0x0f;
|
||||
uint8_t s2 = ((uint8_t)(instance->common.code_last_found >> 16) ^ k);
|
||||
uint8_t s1 = ((uint8_t)(instance->common.code_last_found >> 8) ^ k);
|
||||
uint8_t s0 = ((uint8_t)(instance->common.code_last_found) ^ k);
|
||||
instance->common.serial = s3 << 24 | s2 << 16 | s1 << 8 | s0;
|
||||
|
||||
instance->common.btn = (instance->common.code_last_found >> 48) & 0x0f;
|
||||
}
|
||||
|
||||
void subghz_protocol_nice_flor_s_reset(SubGhzProtocolNiceFlorS* instance) {
|
||||
instance->common.parser_step = NiceFlorSDecoderStepReset;
|
||||
}
|
||||
|
||||
void subghz_protocol_nice_flor_s_parse(
|
||||
SubGhzProtocolNiceFlorS* instance,
|
||||
bool level,
|
||||
uint32_t duration) {
|
||||
switch(instance->common.parser_step) {
|
||||
case NiceFlorSDecoderStepReset:
|
||||
if((!level) && (DURATION_DIFF(duration, instance->common.te_short * 38) <
|
||||
instance->common.te_delta * 38)) {
|
||||
//Found start header Nice Flor-S
|
||||
instance->common.parser_step = NiceFlorSDecoderStepCheckHeader;
|
||||
} else {
|
||||
instance->common.parser_step = NiceFlorSDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case NiceFlorSDecoderStepCheckHeader:
|
||||
if((level) && (DURATION_DIFF(duration, instance->common.te_short * 3) <
|
||||
instance->common.te_delta * 3)) {
|
||||
//Found next header Nice Flor-S
|
||||
instance->common.parser_step = NiceFlorSDecoderStepFoundHeader;
|
||||
} else {
|
||||
instance->common.parser_step = NiceFlorSDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case NiceFlorSDecoderStepFoundHeader:
|
||||
if((!level) && (DURATION_DIFF(duration, instance->common.te_short * 3) <
|
||||
instance->common.te_delta * 3)) {
|
||||
//Found header Nice Flor-S
|
||||
instance->common.parser_step = NiceFlorSDecoderStepSaveDuration;
|
||||
instance->common.code_found = 0;
|
||||
instance->common.code_count_bit = 0;
|
||||
} else {
|
||||
instance->common.parser_step = NiceFlorSDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case NiceFlorSDecoderStepSaveDuration:
|
||||
if(level) {
|
||||
if(DURATION_DIFF(duration, instance->common.te_short * 3) <
|
||||
instance->common.te_delta) {
|
||||
//Found STOP bit
|
||||
instance->common.parser_step = NiceFlorSDecoderStepReset;
|
||||
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_count_bit = instance->common.code_count_bit;
|
||||
if(instance->common.callback)
|
||||
instance->common.callback(
|
||||
(SubGhzProtocolCommon*)instance, instance->common.context);
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
//save interval
|
||||
instance->common.te_last = duration;
|
||||
instance->common.parser_step = NiceFlorSDecoderStepCheckDuration;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NiceFlorSDecoderStepCheckDuration:
|
||||
if(!level) {
|
||||
if((DURATION_DIFF(instance->common.te_last, instance->common.te_short) <
|
||||
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 = NiceFlorSDecoderStepSaveDuration;
|
||||
} else if(
|
||||
(DURATION_DIFF(instance->common.te_last, instance->common.te_long) <
|
||||
instance->common.te_delta) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta)) {
|
||||
subghz_protocol_common_add_bit(&instance->common, 1);
|
||||
instance->common.parser_step = NiceFlorSDecoderStepSaveDuration;
|
||||
} else
|
||||
instance->common.parser_step = NiceFlorSDecoderStepReset;
|
||||
} else {
|
||||
instance->common.parser_step = NiceFlorSDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void subghz_protocol_nice_flor_s_to_str(SubGhzProtocolNiceFlorS* instance, string_t output) {
|
||||
subghz_nice_flor_s_decoder_decrypt(instance);
|
||||
uint32_t code_found_hi = instance->common.code_last_found >> 32;
|
||||
uint32_t code_found_lo = instance->common.code_last_found & 0x00000000ffffffff;
|
||||
|
||||
string_cat_printf(
|
||||
output,
|
||||
"%s %dbit\r\n"
|
||||
"Key:0x%lX%08lX\r\n"
|
||||
"Sn:%05lX\r\n"
|
||||
"Cnt:%04X Btn:%02lX\r\n",
|
||||
instance->common.name,
|
||||
instance->common.code_last_count_bit,
|
||||
code_found_hi,
|
||||
code_found_lo,
|
||||
instance->common.serial,
|
||||
instance->common.cnt,
|
||||
instance->common.btn);
|
||||
}
|
||||
|
||||
void subghz_decoder_nice_flor_s_to_load_protocol(SubGhzProtocolNiceFlorS* instance, void* context) {
|
||||
furi_assert(context);
|
||||
furi_assert(instance);
|
||||
SubGhzProtocolCommonLoad* data = context;
|
||||
instance->common.code_last_found = data->code_found;
|
||||
instance->common.code_last_count_bit = data->code_count_bit;
|
||||
subghz_nice_flor_s_decoder_decrypt(instance);
|
||||
#include "subghz_protocol_nice_flor_s.h"
|
||||
|
||||
#include <furi.h>
|
||||
#include "file-worker.h"
|
||||
/*
|
||||
* https://phreakerclub.com/1615
|
||||
* https://phreakerclub.com/forum/showthread.php?t=2360
|
||||
* https://vrtp.ru/index.php?showtopic=27867
|
||||
*/
|
||||
|
||||
struct SubGhzProtocolNiceFlorS {
|
||||
SubGhzProtocolCommon common;
|
||||
const char* rainbow_table_file_name;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
NiceFlorSDecoderStepReset = 0,
|
||||
NiceFlorSDecoderStepCheckHeader,
|
||||
NiceFlorSDecoderStepFoundHeader,
|
||||
NiceFlorSDecoderStepSaveDuration,
|
||||
NiceFlorSDecoderStepCheckDuration,
|
||||
} NiceFlorSDecoderStep;
|
||||
|
||||
SubGhzProtocolNiceFlorS* subghz_protocol_nice_flor_s_alloc() {
|
||||
SubGhzProtocolNiceFlorS* instance = furi_alloc(sizeof(SubGhzProtocolNiceFlorS));
|
||||
|
||||
instance->common.name = "Nice FloR-S";
|
||||
instance->common.code_min_count_bit_for_found = 52;
|
||||
instance->common.te_short = 500;
|
||||
instance->common.te_long = 1000;
|
||||
instance->common.te_delta = 300;
|
||||
instance->common.type_protocol = SubGhzProtocolCommonTypeDynamic;
|
||||
instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_protocol_nice_flor_s_to_str;
|
||||
instance->common.to_load_protocol =
|
||||
(SubGhzProtocolCommonLoadFromRAW)subghz_decoder_nice_flor_s_to_load_protocol;
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void subghz_protocol_nice_flor_s_free(SubGhzProtocolNiceFlorS* instance) {
|
||||
furi_assert(instance);
|
||||
free(instance);
|
||||
}
|
||||
|
||||
void subghz_protocol_nice_flor_s_name_file(SubGhzProtocolNiceFlorS* instance, const char* name) {
|
||||
instance->rainbow_table_file_name = name;
|
||||
printf("Loading Nice FloR S rainbow table %s\r\n", name);
|
||||
}
|
||||
|
||||
/** Send bit
|
||||
*
|
||||
* @param instance - SubGhzProtocolNiceFlorS instance
|
||||
* @param bit - bit
|
||||
*/
|
||||
void subghz_protocol_nice_flor_s_send_bit(SubGhzProtocolNiceFlorS* instance, uint8_t bit) {
|
||||
if(bit) {
|
||||
//send bit 1
|
||||
SUBGHZ_TX_PIN_HIGH();
|
||||
delay_us(instance->common.te_long);
|
||||
SUBGHZ_TX_PIN_LOW();
|
||||
delay_us(instance->common.te_short);
|
||||
} else {
|
||||
//send bit 0
|
||||
SUBGHZ_TX_PIN_HIGH();
|
||||
delay_us(instance->common.te_short);
|
||||
SUBGHZ_TX_PIN_LOW();
|
||||
delay_us(instance->common.te_long);
|
||||
}
|
||||
}
|
||||
|
||||
void subghz_protocol_nice_flor_s_send_key(
|
||||
SubGhzProtocolNiceFlorS* instance,
|
||||
uint64_t key,
|
||||
uint8_t bit,
|
||||
uint8_t repeat) {
|
||||
while(repeat--) {
|
||||
//Send header
|
||||
SUBGHZ_TX_PIN_LOW();
|
||||
delay_us(instance->common.te_short * 34);
|
||||
//Send Start Bit
|
||||
SUBGHZ_TX_PIN_HIGH();
|
||||
delay_us(instance->common.te_short * 3);
|
||||
SUBGHZ_TX_PIN_LOW();
|
||||
delay_us(instance->common.te_short * 3);
|
||||
//Send key data
|
||||
for(uint8_t i = bit; i > 0; i--) {
|
||||
subghz_protocol_nice_flor_s_send_bit(instance, bit_read(key, i - 1));
|
||||
}
|
||||
//Send Stop Bit
|
||||
SUBGHZ_TX_PIN_HIGH();
|
||||
delay_us(instance->common.te_short * 3);
|
||||
SUBGHZ_TX_PIN_LOW();
|
||||
delay_us(instance->common.te_short * 3);
|
||||
}
|
||||
}
|
||||
|
||||
/** Read bytes from rainbow table
|
||||
*
|
||||
* @param instance - SubGhzProtocolNiceFlorS* instance
|
||||
* @param address - address byte
|
||||
* @return byte data
|
||||
*/
|
||||
uint8_t subghz_nice_flor_s_get_byte_in_file(SubGhzProtocolNiceFlorS* instance, uint32_t address) {
|
||||
if(!instance->rainbow_table_file_name) return 0;
|
||||
|
||||
uint8_t buffer = 0;
|
||||
FileWorker* file_worker = file_worker_alloc(true);
|
||||
if(file_worker_open(
|
||||
file_worker, instance->rainbow_table_file_name, FSAM_READ, FSOM_OPEN_EXISTING)) {
|
||||
file_worker_seek(file_worker, address, true);
|
||||
file_worker_read(file_worker, &buffer, 1);
|
||||
}
|
||||
file_worker_close(file_worker);
|
||||
file_worker_free(file_worker);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/** Decrypt protocol Nice Flor S
|
||||
*
|
||||
* @param instance - SubGhzProtocolNiceFlorS* instance
|
||||
*/
|
||||
void subghz_nice_flor_s_decoder_decrypt(SubGhzProtocolNiceFlorS* instance) {
|
||||
/*
|
||||
* Packet format Nice Flor-s: START-P0-P1-P2-P3-P4-P5-P6-P7-STOP
|
||||
* P0 (4-bit) - button positional code - 1:0x1, 2:0x2, 3:0x4, 4:0x8;
|
||||
* P1 (4-bit) - batch repetition number, calculated by the formula:
|
||||
* P1 = 0xF ^ P0 ^ n; where n changes from 1 to 15, then 0, and then in a circle
|
||||
* key 1: {0xF,0xC,0xD,0xA,0xB,0x8,0x9,0x6,0x7,0x4,0x5,0x2,0x3,0x0,0x1,0xE};
|
||||
* key 2: {0xC,0xF,0xE,0x9,0x8,0xB,0xA,0x5,0x4,0x7,0x6,0x1,0x0,0x3,0x2,0xD};
|
||||
* key 3: {0xA,0x9,0x8,0xF,0xE,0xD,0xC,0x3,0x2,0x1,0x0,0x7,0x6,0x5,0x4,0xB};
|
||||
* P2 (4-bit) - part of the serial number, P2 = (K ^ S3) & 0xF;
|
||||
* P3 (byte) - the major part of the encrypted index
|
||||
* P4 (byte) - the low-order part of the encrypted index
|
||||
* P5 (byte) - part of the serial number, P5 = K ^ S2;
|
||||
* P6 (byte) - part of the serial number, P6 = K ^ S1;
|
||||
* P7 (byte) - part of the serial number, P7 = K ^ S0;
|
||||
* K (byte) - depends on P3 and P4, K = Fk(P3, P4);
|
||||
* S3,S2,S1,S0 - serial number of the console 28 bit.
|
||||
*/
|
||||
|
||||
uint16_t p3p4 = (uint16_t)(instance->common.code_last_found >> 24);
|
||||
instance->common.cnt = subghz_nice_flor_s_get_byte_in_file(instance, p3p4 * 2) << 8 |
|
||||
subghz_nice_flor_s_get_byte_in_file(instance, p3p4 * 2 + 1);
|
||||
uint8_t k =
|
||||
(uint8_t)(p3p4 & 0x00FF) ^
|
||||
subghz_nice_flor_s_get_byte_in_file(instance, (0x20000 | (instance->common.cnt & 0x00ff)));
|
||||
|
||||
uint8_t s3 = ((uint8_t)(instance->common.code_last_found >> 40) ^ k) & 0x0f;
|
||||
uint8_t s2 = ((uint8_t)(instance->common.code_last_found >> 16) ^ k);
|
||||
uint8_t s1 = ((uint8_t)(instance->common.code_last_found >> 8) ^ k);
|
||||
uint8_t s0 = ((uint8_t)(instance->common.code_last_found) ^ k);
|
||||
instance->common.serial = s3 << 24 | s2 << 16 | s1 << 8 | s0;
|
||||
|
||||
instance->common.btn = (instance->common.code_last_found >> 48) & 0x0f;
|
||||
}
|
||||
|
||||
void subghz_protocol_nice_flor_s_reset(SubGhzProtocolNiceFlorS* instance) {
|
||||
instance->common.parser_step = NiceFlorSDecoderStepReset;
|
||||
}
|
||||
|
||||
void subghz_protocol_nice_flor_s_parse(
|
||||
SubGhzProtocolNiceFlorS* instance,
|
||||
bool level,
|
||||
uint32_t duration) {
|
||||
switch(instance->common.parser_step) {
|
||||
case NiceFlorSDecoderStepReset:
|
||||
if((!level) && (DURATION_DIFF(duration, instance->common.te_short * 38) <
|
||||
instance->common.te_delta * 38)) {
|
||||
//Found start header Nice Flor-S
|
||||
instance->common.parser_step = NiceFlorSDecoderStepCheckHeader;
|
||||
} else {
|
||||
instance->common.parser_step = NiceFlorSDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case NiceFlorSDecoderStepCheckHeader:
|
||||
if((level) && (DURATION_DIFF(duration, instance->common.te_short * 3) <
|
||||
instance->common.te_delta * 3)) {
|
||||
//Found next header Nice Flor-S
|
||||
instance->common.parser_step = NiceFlorSDecoderStepFoundHeader;
|
||||
} else {
|
||||
instance->common.parser_step = NiceFlorSDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case NiceFlorSDecoderStepFoundHeader:
|
||||
if((!level) && (DURATION_DIFF(duration, instance->common.te_short * 3) <
|
||||
instance->common.te_delta * 3)) {
|
||||
//Found header Nice Flor-S
|
||||
instance->common.parser_step = NiceFlorSDecoderStepSaveDuration;
|
||||
instance->common.code_found = 0;
|
||||
instance->common.code_count_bit = 0;
|
||||
} else {
|
||||
instance->common.parser_step = NiceFlorSDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case NiceFlorSDecoderStepSaveDuration:
|
||||
if(level) {
|
||||
if(DURATION_DIFF(duration, instance->common.te_short * 3) <
|
||||
instance->common.te_delta) {
|
||||
//Found STOP bit
|
||||
instance->common.parser_step = NiceFlorSDecoderStepReset;
|
||||
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_count_bit = instance->common.code_count_bit;
|
||||
if(instance->common.callback)
|
||||
instance->common.callback(
|
||||
(SubGhzProtocolCommon*)instance, instance->common.context);
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
//save interval
|
||||
instance->common.te_last = duration;
|
||||
instance->common.parser_step = NiceFlorSDecoderStepCheckDuration;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NiceFlorSDecoderStepCheckDuration:
|
||||
if(!level) {
|
||||
if((DURATION_DIFF(instance->common.te_last, instance->common.te_short) <
|
||||
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 = NiceFlorSDecoderStepSaveDuration;
|
||||
} else if(
|
||||
(DURATION_DIFF(instance->common.te_last, instance->common.te_long) <
|
||||
instance->common.te_delta) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta)) {
|
||||
subghz_protocol_common_add_bit(&instance->common, 1);
|
||||
instance->common.parser_step = NiceFlorSDecoderStepSaveDuration;
|
||||
} else
|
||||
instance->common.parser_step = NiceFlorSDecoderStepReset;
|
||||
} else {
|
||||
instance->common.parser_step = NiceFlorSDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void subghz_protocol_nice_flor_s_to_str(SubGhzProtocolNiceFlorS* instance, string_t output) {
|
||||
subghz_nice_flor_s_decoder_decrypt(instance);
|
||||
uint32_t code_found_hi = instance->common.code_last_found >> 32;
|
||||
uint32_t code_found_lo = instance->common.code_last_found & 0x00000000ffffffff;
|
||||
|
||||
string_cat_printf(
|
||||
output,
|
||||
"%s %dbit\r\n"
|
||||
"Key:0x%lX%08lX\r\n"
|
||||
"Sn:%05lX\r\n"
|
||||
"Cnt:%04X Btn:%02lX\r\n",
|
||||
instance->common.name,
|
||||
instance->common.code_last_count_bit,
|
||||
code_found_hi,
|
||||
code_found_lo,
|
||||
instance->common.serial,
|
||||
instance->common.cnt,
|
||||
instance->common.btn);
|
||||
}
|
||||
|
||||
void subghz_decoder_nice_flor_s_to_load_protocol(SubGhzProtocolNiceFlorS* instance, void* context) {
|
||||
furi_assert(context);
|
||||
furi_assert(instance);
|
||||
SubGhzProtocolCommonLoad* data = context;
|
||||
instance->common.code_last_found = data->code_found;
|
||||
instance->common.code_last_count_bit = data->code_count_bit;
|
||||
subghz_nice_flor_s_decoder_decrypt(instance);
|
||||
}
|
@@ -1,59 +1,59 @@
|
||||
#pragma once
|
||||
|
||||
#include "subghz_protocol_common.h"
|
||||
|
||||
typedef struct SubGhzProtocolNiceFlorS SubGhzProtocolNiceFlorS;
|
||||
|
||||
/** Allocate SubGhzProtocolNiceFlorS
|
||||
*
|
||||
* @return SubGhzProtocolNiceFlorS*
|
||||
*/
|
||||
SubGhzProtocolNiceFlorS* subghz_protocol_nice_flor_s_alloc();
|
||||
|
||||
/** Free SubGhzProtocolNiceFlorS
|
||||
*
|
||||
* @param instance
|
||||
*/
|
||||
void subghz_protocol_nice_flor_s_free(SubGhzProtocolNiceFlorS* instance);
|
||||
|
||||
/** File name rainbow table Nice Flor-S
|
||||
*
|
||||
* @param instance - SubGhzProtocolNiceFlorS instance
|
||||
* @param file_name - "path/file_name"
|
||||
*/
|
||||
void subghz_protocol_nice_flor_s_name_file(SubGhzProtocolNiceFlorS* instance, const char* name);
|
||||
|
||||
/** Sends the key on the air
|
||||
*
|
||||
* @param instance - SubGhzProtocolNiceFlorS instance
|
||||
* @param key - key send
|
||||
* @param bit - count bit key
|
||||
* @param repeat - repeat send key
|
||||
*/
|
||||
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 - LevelDuration level_duration
|
||||
*/
|
||||
void subghz_protocol_nice_flor_s_parse(SubGhzProtocolNiceFlorS* instance, bool level, uint32_t duration);
|
||||
|
||||
/** Outputting information from the parser
|
||||
*
|
||||
* @param instance - SubGhzProtocolNiceFlorS* instance
|
||||
* @param output - output string
|
||||
*/
|
||||
void subghz_protocol_nice_flor_s_to_str(SubGhzProtocolNiceFlorS* instance, string_t output);
|
||||
|
||||
/** Loading protocol from bin data
|
||||
*
|
||||
* @param instance - SubGhzProtocolNiceFlorS instance
|
||||
* @param context - SubGhzProtocolCommonLoad context
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "subghz_protocol_common.h"
|
||||
|
||||
typedef struct SubGhzProtocolNiceFlorS SubGhzProtocolNiceFlorS;
|
||||
|
||||
/** Allocate SubGhzProtocolNiceFlorS
|
||||
*
|
||||
* @return SubGhzProtocolNiceFlorS*
|
||||
*/
|
||||
SubGhzProtocolNiceFlorS* subghz_protocol_nice_flor_s_alloc();
|
||||
|
||||
/** Free SubGhzProtocolNiceFlorS
|
||||
*
|
||||
* @param instance
|
||||
*/
|
||||
void subghz_protocol_nice_flor_s_free(SubGhzProtocolNiceFlorS* instance);
|
||||
|
||||
/** File name rainbow table Nice Flor-S
|
||||
*
|
||||
* @param instance - SubGhzProtocolNiceFlorS instance
|
||||
* @param file_name - "path/file_name"
|
||||
*/
|
||||
void subghz_protocol_nice_flor_s_name_file(SubGhzProtocolNiceFlorS* instance, const char* name);
|
||||
|
||||
/** Sends the key on the air
|
||||
*
|
||||
* @param instance - SubGhzProtocolNiceFlorS instance
|
||||
* @param key - key send
|
||||
* @param bit - count bit key
|
||||
* @param repeat - repeat send key
|
||||
*/
|
||||
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 - LevelDuration level_duration
|
||||
*/
|
||||
void subghz_protocol_nice_flor_s_parse(SubGhzProtocolNiceFlorS* instance, bool level, uint32_t duration);
|
||||
|
||||
/** Outputting information from the parser
|
||||
*
|
||||
* @param instance - SubGhzProtocolNiceFlorS* instance
|
||||
* @param output - output string
|
||||
*/
|
||||
void subghz_protocol_nice_flor_s_to_str(SubGhzProtocolNiceFlorS* instance, string_t output);
|
||||
|
||||
/** Loading protocol from bin data
|
||||
*
|
||||
* @param instance - SubGhzProtocolNiceFlorS instance
|
||||
* @param context - SubGhzProtocolCommonLoad context
|
||||
*/
|
||||
void subghz_decoder_nice_flor_s_to_load_protocol(SubGhzProtocolNiceFlorS* instance, void* context);
|
@@ -1,369 +1,369 @@
|
||||
#include "subghz_protocol_princeton.h"
|
||||
/*
|
||||
* Help
|
||||
* https://phreakerclub.com/447
|
||||
*
|
||||
*/
|
||||
|
||||
#define SUBGHZ_PT_SHORT 400
|
||||
#define SUBGHZ_PT_LONG (SUBGHZ_PT_SHORT * 3)
|
||||
#define SUBGHZ_PT_GUARD (SUBGHZ_PT_SHORT * 30)
|
||||
#define SUBGHZ_PT_COUNT_KEY 5
|
||||
#define SUBGHZ_PT_TIMEOUT 320
|
||||
|
||||
struct SubGhzEncoderPrinceton {
|
||||
uint32_t key;
|
||||
uint16_t te;
|
||||
size_t repeat;
|
||||
size_t front;
|
||||
size_t count_key;
|
||||
uint32_t time_high;
|
||||
uint32_t time_low;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
PrincetonDecoderStepReset = 0,
|
||||
PrincetonDecoderStepSaveDuration,
|
||||
PrincetonDecoderStepCheckDuration,
|
||||
} PrincetonDecoderStep;
|
||||
|
||||
SubGhzEncoderPrinceton* subghz_encoder_princeton_alloc() {
|
||||
SubGhzEncoderPrinceton* instance = furi_alloc(sizeof(SubGhzEncoderPrinceton));
|
||||
return instance;
|
||||
}
|
||||
|
||||
void subghz_encoder_princeton_free(SubGhzEncoderPrinceton* instance) {
|
||||
furi_assert(instance);
|
||||
free(instance);
|
||||
}
|
||||
|
||||
void subghz_encoder_princeton_set_te(SubGhzEncoderPrinceton* instance, void* decoder) {
|
||||
SubGhzDecoderPrinceton* pricenton = decoder;
|
||||
if((pricenton->te) != 0) {
|
||||
instance->te = pricenton->te;
|
||||
} else {
|
||||
instance->te = SUBGHZ_PT_SHORT;
|
||||
}
|
||||
}
|
||||
|
||||
void subghz_encoder_princeton_set(SubGhzEncoderPrinceton* instance, uint32_t key, size_t repeat) {
|
||||
furi_assert(instance);
|
||||
instance->te = SUBGHZ_PT_SHORT;
|
||||
instance->key = key;
|
||||
instance->repeat = repeat + 1;
|
||||
instance->front = 48;
|
||||
instance->count_key = SUBGHZ_PT_COUNT_KEY + 7;
|
||||
instance->time_high = 0;
|
||||
instance->time_low = 0;
|
||||
}
|
||||
|
||||
size_t subghz_encoder_princeton_get_repeat_left(SubGhzEncoderPrinceton* instance) {
|
||||
furi_assert(instance);
|
||||
return instance->repeat;
|
||||
}
|
||||
|
||||
void subghz_encoder_princeton_print_log(void* context) {
|
||||
SubGhzEncoderPrinceton* instance = context;
|
||||
float duty_cycle =
|
||||
((float)instance->time_high / (instance->time_high + instance->time_low)) * 100;
|
||||
FURI_LOG_I(
|
||||
"EncoderPrinceton",
|
||||
"Radio ON=%dus, OFF=%dus, DutyCycle=%d,%d%%",
|
||||
instance->time_high,
|
||||
instance->time_low,
|
||||
(uint32_t)duty_cycle,
|
||||
(uint32_t)((duty_cycle - (uint32_t)duty_cycle) * 100));
|
||||
}
|
||||
|
||||
LevelDuration subghz_encoder_princeton_yield(void* context) {
|
||||
SubGhzEncoderPrinceton* instance = context;
|
||||
if(instance->repeat == 0) {
|
||||
subghz_encoder_princeton_print_log(instance);
|
||||
return level_duration_reset();
|
||||
}
|
||||
|
||||
size_t bit = instance->front / 2;
|
||||
bool level = !(instance->front % 2);
|
||||
|
||||
LevelDuration ret;
|
||||
if(bit < 24) {
|
||||
uint8_t byte = bit / 8;
|
||||
uint8_t bit_in_byte = bit % 8;
|
||||
bool value = (((uint8_t*)&instance->key)[2 - byte] >> (7 - bit_in_byte)) & 1;
|
||||
if(value) {
|
||||
ret = level_duration_make(level, level ? instance->te * 3 : instance->te);
|
||||
if(level)
|
||||
instance->time_high += instance->te * 3;
|
||||
else
|
||||
instance->time_low += instance->te;
|
||||
} else {
|
||||
ret = level_duration_make(level, level ? instance->te : instance->te * 3);
|
||||
if(level)
|
||||
instance->time_high += instance->te;
|
||||
else
|
||||
instance->time_low += instance->te * 3;
|
||||
}
|
||||
} else {
|
||||
if(--instance->count_key != 0) {
|
||||
ret = level_duration_make(level, level ? instance->te : instance->te * 30);
|
||||
if(level)
|
||||
instance->time_high += instance->te;
|
||||
else
|
||||
instance->time_low += instance->te * 30;
|
||||
} else {
|
||||
instance->count_key = SUBGHZ_PT_COUNT_KEY + 6;
|
||||
instance->front = 48;
|
||||
ret = level_duration_make(level, level ? instance->te : SUBGHZ_PT_TIMEOUT * 1000);
|
||||
if(level)
|
||||
instance->time_high += instance->te;
|
||||
else
|
||||
instance->time_low += SUBGHZ_PT_TIMEOUT * 1000;
|
||||
}
|
||||
}
|
||||
|
||||
instance->front++;
|
||||
if(instance->front == 50) {
|
||||
instance->repeat--;
|
||||
instance->front = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
SubGhzDecoderPrinceton* subghz_decoder_princeton_alloc(void) {
|
||||
SubGhzDecoderPrinceton* instance = furi_alloc(sizeof(SubGhzDecoderPrinceton));
|
||||
|
||||
instance->te = SUBGHZ_PT_SHORT;
|
||||
instance->common.name = "Princeton";
|
||||
instance->common.code_min_count_bit_for_found = 24;
|
||||
instance->common.te_short = SUBGHZ_PT_SHORT; //150;
|
||||
instance->common.te_long = SUBGHZ_PT_LONG; //450;
|
||||
instance->common.te_delta = 250; //50;
|
||||
instance->common.type_protocol = SubGhzProtocolCommonTypeStatic;
|
||||
instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_decoder_princeton_to_str;
|
||||
instance->common.to_save_string =
|
||||
(SubGhzProtocolCommonGetStrSave)subghz_decoder_princeton_to_save_str;
|
||||
instance->common.to_load_protocol_from_file =
|
||||
(SubGhzProtocolCommonLoadFromFile)subghz_decoder_princeton_to_load_protocol_from_file;
|
||||
instance->common.to_load_protocol =
|
||||
(SubGhzProtocolCommonLoadFromRAW)subghz_decoder_princeton_to_load_protocol;
|
||||
instance->common.get_upload_protocol =
|
||||
(SubGhzProtocolCommonEncoderGetUpLoad)subghz_protocol_princeton_send_key;
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void subghz_decoder_princeton_free(SubGhzDecoderPrinceton* instance) {
|
||||
furi_assert(instance);
|
||||
free(instance);
|
||||
}
|
||||
|
||||
uint16_t subghz_protocol_princeton_get_te(void* context) {
|
||||
SubGhzDecoderPrinceton* instance = context;
|
||||
return instance->te;
|
||||
}
|
||||
|
||||
bool subghz_protocol_princeton_send_key(
|
||||
SubGhzDecoderPrinceton* instance,
|
||||
SubGhzProtocolCommonEncoder* encoder) {
|
||||
furi_assert(instance);
|
||||
furi_assert(encoder);
|
||||
size_t index = 0;
|
||||
encoder->size_upload = (instance->common.code_last_count_bit * 2) + 2;
|
||||
if(encoder->size_upload > SUBGHZ_ENCODER_UPLOAD_MAX_SIZE) return false;
|
||||
|
||||
//Send key data
|
||||
for(uint8_t i = instance->common.code_last_count_bit; i > 0; i--) {
|
||||
if(bit_read(instance->common.code_last_found, i - 1)) {
|
||||
//send bit 1
|
||||
encoder->upload[index++] = level_duration_make(true, (uint32_t)instance->te * 3);
|
||||
encoder->upload[index++] = level_duration_make(false, (uint32_t)instance->te);
|
||||
} else {
|
||||
//send bit 0
|
||||
encoder->upload[index++] = level_duration_make(true, (uint32_t)instance->te);
|
||||
encoder->upload[index++] = level_duration_make(false, (uint32_t)instance->te * 3);
|
||||
}
|
||||
}
|
||||
|
||||
//Send Stop bit
|
||||
encoder->upload[index++] = level_duration_make(true, (uint32_t)instance->te);
|
||||
//Send PT_GUARD
|
||||
encoder->upload[index++] = level_duration_make(false, (uint32_t)instance->te * 30);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void subghz_decoder_princeton_reset(SubGhzDecoderPrinceton* instance) {
|
||||
instance->common.parser_step = PrincetonDecoderStepReset;
|
||||
}
|
||||
|
||||
void subghz_decoder_princeton_parse(
|
||||
SubGhzDecoderPrinceton* instance,
|
||||
bool level,
|
||||
uint32_t duration) {
|
||||
switch(instance->common.parser_step) {
|
||||
case PrincetonDecoderStepReset:
|
||||
if((!level) && (DURATION_DIFF(duration, instance->common.te_short * 36) <
|
||||
instance->common.te_delta * 36)) {
|
||||
//Found Preambula
|
||||
instance->common.parser_step = PrincetonDecoderStepSaveDuration;
|
||||
instance->common.code_found = 0;
|
||||
instance->common.code_count_bit = 0;
|
||||
instance->te = 0;
|
||||
} else {
|
||||
instance->common.parser_step = PrincetonDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case PrincetonDecoderStepSaveDuration:
|
||||
//save duration
|
||||
if(level) {
|
||||
instance->common.te_last = duration;
|
||||
instance->te += duration;
|
||||
instance->common.parser_step = PrincetonDecoderStepCheckDuration;
|
||||
}
|
||||
break;
|
||||
case PrincetonDecoderStepCheckDuration:
|
||||
if(!level) {
|
||||
if(duration >= (instance->common.te_short * 10 + instance->common.te_delta)) {
|
||||
instance->common.parser_step = PrincetonDecoderStepSaveDuration;
|
||||
if(instance->common.code_count_bit ==
|
||||
instance->common.code_min_count_bit_for_found) {
|
||||
instance->te /= (instance->common.code_count_bit * 4 + 1);
|
||||
|
||||
instance->common.code_last_found = instance->common.code_found;
|
||||
instance->common.code_last_count_bit = instance->common.code_count_bit;
|
||||
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;
|
||||
instance->te = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
instance->te += duration;
|
||||
|
||||
if((DURATION_DIFF(instance->common.te_last, instance->common.te_short) <
|
||||
instance->common.te_delta) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_long) <
|
||||
instance->common.te_delta * 3)) {
|
||||
subghz_protocol_common_add_bit(&instance->common, 0);
|
||||
instance->common.parser_step = PrincetonDecoderStepSaveDuration;
|
||||
} else if(
|
||||
(DURATION_DIFF(instance->common.te_last, instance->common.te_long) <
|
||||
instance->common.te_delta * 3) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta)) {
|
||||
subghz_protocol_common_add_bit(&instance->common, 1);
|
||||
instance->common.parser_step = PrincetonDecoderStepSaveDuration;
|
||||
} else {
|
||||
instance->common.parser_step = PrincetonDecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
instance->common.parser_step = PrincetonDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void subghz_decoder_princeton_to_str(SubGhzDecoderPrinceton* instance, string_t output) {
|
||||
uint32_t code_found_lo = instance->common.code_last_found & 0x00000000ffffffff;
|
||||
|
||||
uint64_t code_found_reverse = subghz_protocol_common_reverse_key(
|
||||
instance->common.code_last_found, instance->common.code_last_count_bit);
|
||||
|
||||
uint32_t code_found_reverse_lo = code_found_reverse & 0x00000000ffffffff;
|
||||
|
||||
string_cat_printf(
|
||||
output,
|
||||
"%s %dbit\r\n"
|
||||
"Key:0x%08lX\r\n"
|
||||
"Yek:0x%08lX\r\n"
|
||||
"Sn:0x%05lX BTN:%02X\r\n"
|
||||
"Te:%dus\r\n",
|
||||
instance->common.name,
|
||||
instance->common.code_last_count_bit,
|
||||
code_found_lo,
|
||||
code_found_reverse_lo,
|
||||
instance->common.serial,
|
||||
instance->common.btn,
|
||||
instance->te);
|
||||
}
|
||||
|
||||
void subghz_decoder_princeton_to_save_str(SubGhzDecoderPrinceton* instance, string_t output) {
|
||||
string_printf(
|
||||
output,
|
||||
"Protocol: %s\n"
|
||||
"Bit: %d\n"
|
||||
"Te: %d\n"
|
||||
"Key: %08lX\n",
|
||||
instance->common.name,
|
||||
instance->common.code_last_count_bit,
|
||||
instance->te,
|
||||
(uint32_t)(instance->common.code_last_found & 0x00000000ffffffff));
|
||||
}
|
||||
|
||||
bool subghz_decoder_princeton_to_load_protocol_from_file(
|
||||
FileWorker* file_worker,
|
||||
SubGhzDecoderPrinceton* instance) {
|
||||
bool loaded = false;
|
||||
string_t temp_str;
|
||||
string_init(temp_str);
|
||||
int res = 0;
|
||||
int data = 0;
|
||||
|
||||
do {
|
||||
// Read and parse bit data from 2nd line
|
||||
if(!file_worker_read_until(file_worker, temp_str, '\n')) {
|
||||
break;
|
||||
}
|
||||
res = sscanf(string_get_cstr(temp_str), "Bit: %d\n", &data);
|
||||
if(res != 1) {
|
||||
break;
|
||||
}
|
||||
instance->common.code_last_count_bit = (uint8_t)data;
|
||||
|
||||
// Read and parse te data from 3nd line
|
||||
if(!file_worker_read_until(file_worker, temp_str, '\n')) {
|
||||
break;
|
||||
}
|
||||
res = sscanf(string_get_cstr(temp_str), "Te: %d\n", &data);
|
||||
if(res != 1) {
|
||||
break;
|
||||
}
|
||||
instance->te = (uint16_t)data;
|
||||
|
||||
// Read and parse key data from 4nd line
|
||||
if(!file_worker_read_until(file_worker, temp_str, '\n')) {
|
||||
break;
|
||||
}
|
||||
uint32_t temp_key = 0;
|
||||
res = sscanf(string_get_cstr(temp_str), "Key: %08lX\n", &temp_key);
|
||||
if(res != 1) {
|
||||
break;
|
||||
}
|
||||
instance->common.code_last_found = (uint64_t)temp_key;
|
||||
instance->common.serial = instance->common.code_last_found >> 4;
|
||||
instance->common.btn = (uint8_t)instance->common.code_last_found & 0x00000F;
|
||||
|
||||
loaded = true;
|
||||
} while(0);
|
||||
|
||||
string_clear(temp_str);
|
||||
|
||||
return loaded;
|
||||
}
|
||||
|
||||
void subghz_decoder_princeton_to_load_protocol(SubGhzDecoderPrinceton* instance, void* context) {
|
||||
furi_assert(context);
|
||||
furi_assert(instance);
|
||||
SubGhzProtocolCommonLoad* data = context;
|
||||
instance->common.code_last_found = data->code_found;
|
||||
instance->common.code_last_count_bit = data->code_count_bit;
|
||||
instance->te = data->param1;
|
||||
instance->common.serial = instance->common.code_last_found >> 4;
|
||||
instance->common.btn = (uint8_t)instance->common.code_last_found & 0x00000F;
|
||||
}
|
||||
#include "subghz_protocol_princeton.h"
|
||||
/*
|
||||
* Help
|
||||
* https://phreakerclub.com/447
|
||||
*
|
||||
*/
|
||||
|
||||
#define SUBGHZ_PT_SHORT 400
|
||||
#define SUBGHZ_PT_LONG (SUBGHZ_PT_SHORT * 3)
|
||||
#define SUBGHZ_PT_GUARD (SUBGHZ_PT_SHORT * 30)
|
||||
#define SUBGHZ_PT_COUNT_KEY 5
|
||||
#define SUBGHZ_PT_TIMEOUT 320
|
||||
|
||||
struct SubGhzEncoderPrinceton {
|
||||
uint32_t key;
|
||||
uint16_t te;
|
||||
size_t repeat;
|
||||
size_t front;
|
||||
size_t count_key;
|
||||
uint32_t time_high;
|
||||
uint32_t time_low;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
PrincetonDecoderStepReset = 0,
|
||||
PrincetonDecoderStepSaveDuration,
|
||||
PrincetonDecoderStepCheckDuration,
|
||||
} PrincetonDecoderStep;
|
||||
|
||||
SubGhzEncoderPrinceton* subghz_encoder_princeton_alloc() {
|
||||
SubGhzEncoderPrinceton* instance = furi_alloc(sizeof(SubGhzEncoderPrinceton));
|
||||
return instance;
|
||||
}
|
||||
|
||||
void subghz_encoder_princeton_free(SubGhzEncoderPrinceton* instance) {
|
||||
furi_assert(instance);
|
||||
free(instance);
|
||||
}
|
||||
|
||||
void subghz_encoder_princeton_set_te(SubGhzEncoderPrinceton* instance, void* decoder) {
|
||||
SubGhzDecoderPrinceton* pricenton = decoder;
|
||||
if((pricenton->te) != 0) {
|
||||
instance->te = pricenton->te;
|
||||
} else {
|
||||
instance->te = SUBGHZ_PT_SHORT;
|
||||
}
|
||||
}
|
||||
|
||||
void subghz_encoder_princeton_set(SubGhzEncoderPrinceton* instance, uint32_t key, size_t repeat) {
|
||||
furi_assert(instance);
|
||||
instance->te = SUBGHZ_PT_SHORT;
|
||||
instance->key = key;
|
||||
instance->repeat = repeat + 1;
|
||||
instance->front = 48;
|
||||
instance->count_key = SUBGHZ_PT_COUNT_KEY + 7;
|
||||
instance->time_high = 0;
|
||||
instance->time_low = 0;
|
||||
}
|
||||
|
||||
size_t subghz_encoder_princeton_get_repeat_left(SubGhzEncoderPrinceton* instance) {
|
||||
furi_assert(instance);
|
||||
return instance->repeat;
|
||||
}
|
||||
|
||||
void subghz_encoder_princeton_print_log(void* context) {
|
||||
SubGhzEncoderPrinceton* instance = context;
|
||||
float duty_cycle =
|
||||
((float)instance->time_high / (instance->time_high + instance->time_low)) * 100;
|
||||
FURI_LOG_I(
|
||||
"EncoderPrinceton",
|
||||
"Radio ON=%dus, OFF=%dus, DutyCycle=%d,%d%%",
|
||||
instance->time_high,
|
||||
instance->time_low,
|
||||
(uint32_t)duty_cycle,
|
||||
(uint32_t)((duty_cycle - (uint32_t)duty_cycle) * 100));
|
||||
}
|
||||
|
||||
LevelDuration subghz_encoder_princeton_yield(void* context) {
|
||||
SubGhzEncoderPrinceton* instance = context;
|
||||
if(instance->repeat == 0) {
|
||||
subghz_encoder_princeton_print_log(instance);
|
||||
return level_duration_reset();
|
||||
}
|
||||
|
||||
size_t bit = instance->front / 2;
|
||||
bool level = !(instance->front % 2);
|
||||
|
||||
LevelDuration ret;
|
||||
if(bit < 24) {
|
||||
uint8_t byte = bit / 8;
|
||||
uint8_t bit_in_byte = bit % 8;
|
||||
bool value = (((uint8_t*)&instance->key)[2 - byte] >> (7 - bit_in_byte)) & 1;
|
||||
if(value) {
|
||||
ret = level_duration_make(level, level ? instance->te * 3 : instance->te);
|
||||
if(level)
|
||||
instance->time_high += instance->te * 3;
|
||||
else
|
||||
instance->time_low += instance->te;
|
||||
} else {
|
||||
ret = level_duration_make(level, level ? instance->te : instance->te * 3);
|
||||
if(level)
|
||||
instance->time_high += instance->te;
|
||||
else
|
||||
instance->time_low += instance->te * 3;
|
||||
}
|
||||
} else {
|
||||
if(--instance->count_key != 0) {
|
||||
ret = level_duration_make(level, level ? instance->te : instance->te * 30);
|
||||
if(level)
|
||||
instance->time_high += instance->te;
|
||||
else
|
||||
instance->time_low += instance->te * 30;
|
||||
} else {
|
||||
instance->count_key = SUBGHZ_PT_COUNT_KEY + 6;
|
||||
instance->front = 48;
|
||||
ret = level_duration_make(level, level ? instance->te : SUBGHZ_PT_TIMEOUT * 1000);
|
||||
if(level)
|
||||
instance->time_high += instance->te;
|
||||
else
|
||||
instance->time_low += SUBGHZ_PT_TIMEOUT * 1000;
|
||||
}
|
||||
}
|
||||
|
||||
instance->front++;
|
||||
if(instance->front == 50) {
|
||||
instance->repeat--;
|
||||
instance->front = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
SubGhzDecoderPrinceton* subghz_decoder_princeton_alloc(void) {
|
||||
SubGhzDecoderPrinceton* instance = furi_alloc(sizeof(SubGhzDecoderPrinceton));
|
||||
|
||||
instance->te = SUBGHZ_PT_SHORT;
|
||||
instance->common.name = "Princeton";
|
||||
instance->common.code_min_count_bit_for_found = 24;
|
||||
instance->common.te_short = SUBGHZ_PT_SHORT; //150;
|
||||
instance->common.te_long = SUBGHZ_PT_LONG; //450;
|
||||
instance->common.te_delta = 250; //50;
|
||||
instance->common.type_protocol = SubGhzProtocolCommonTypeStatic;
|
||||
instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_decoder_princeton_to_str;
|
||||
instance->common.to_save_string =
|
||||
(SubGhzProtocolCommonGetStrSave)subghz_decoder_princeton_to_save_str;
|
||||
instance->common.to_load_protocol_from_file =
|
||||
(SubGhzProtocolCommonLoadFromFile)subghz_decoder_princeton_to_load_protocol_from_file;
|
||||
instance->common.to_load_protocol =
|
||||
(SubGhzProtocolCommonLoadFromRAW)subghz_decoder_princeton_to_load_protocol;
|
||||
instance->common.get_upload_protocol =
|
||||
(SubGhzProtocolCommonEncoderGetUpLoad)subghz_protocol_princeton_send_key;
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void subghz_decoder_princeton_free(SubGhzDecoderPrinceton* instance) {
|
||||
furi_assert(instance);
|
||||
free(instance);
|
||||
}
|
||||
|
||||
uint16_t subghz_protocol_princeton_get_te(void* context) {
|
||||
SubGhzDecoderPrinceton* instance = context;
|
||||
return instance->te;
|
||||
}
|
||||
|
||||
bool subghz_protocol_princeton_send_key(
|
||||
SubGhzDecoderPrinceton* instance,
|
||||
SubGhzProtocolCommonEncoder* encoder) {
|
||||
furi_assert(instance);
|
||||
furi_assert(encoder);
|
||||
size_t index = 0;
|
||||
encoder->size_upload = (instance->common.code_last_count_bit * 2) + 2;
|
||||
if(encoder->size_upload > SUBGHZ_ENCODER_UPLOAD_MAX_SIZE) return false;
|
||||
|
||||
//Send key data
|
||||
for(uint8_t i = instance->common.code_last_count_bit; i > 0; i--) {
|
||||
if(bit_read(instance->common.code_last_found, i - 1)) {
|
||||
//send bit 1
|
||||
encoder->upload[index++] = level_duration_make(true, (uint32_t)instance->te * 3);
|
||||
encoder->upload[index++] = level_duration_make(false, (uint32_t)instance->te);
|
||||
} else {
|
||||
//send bit 0
|
||||
encoder->upload[index++] = level_duration_make(true, (uint32_t)instance->te);
|
||||
encoder->upload[index++] = level_duration_make(false, (uint32_t)instance->te * 3);
|
||||
}
|
||||
}
|
||||
|
||||
//Send Stop bit
|
||||
encoder->upload[index++] = level_duration_make(true, (uint32_t)instance->te);
|
||||
//Send PT_GUARD
|
||||
encoder->upload[index++] = level_duration_make(false, (uint32_t)instance->te * 30);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void subghz_decoder_princeton_reset(SubGhzDecoderPrinceton* instance) {
|
||||
instance->common.parser_step = PrincetonDecoderStepReset;
|
||||
}
|
||||
|
||||
void subghz_decoder_princeton_parse(
|
||||
SubGhzDecoderPrinceton* instance,
|
||||
bool level,
|
||||
uint32_t duration) {
|
||||
switch(instance->common.parser_step) {
|
||||
case PrincetonDecoderStepReset:
|
||||
if((!level) && (DURATION_DIFF(duration, instance->common.te_short * 36) <
|
||||
instance->common.te_delta * 36)) {
|
||||
//Found Preambula
|
||||
instance->common.parser_step = PrincetonDecoderStepSaveDuration;
|
||||
instance->common.code_found = 0;
|
||||
instance->common.code_count_bit = 0;
|
||||
instance->te = 0;
|
||||
} else {
|
||||
instance->common.parser_step = PrincetonDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case PrincetonDecoderStepSaveDuration:
|
||||
//save duration
|
||||
if(level) {
|
||||
instance->common.te_last = duration;
|
||||
instance->te += duration;
|
||||
instance->common.parser_step = PrincetonDecoderStepCheckDuration;
|
||||
}
|
||||
break;
|
||||
case PrincetonDecoderStepCheckDuration:
|
||||
if(!level) {
|
||||
if(duration >= (instance->common.te_short * 10 + instance->common.te_delta)) {
|
||||
instance->common.parser_step = PrincetonDecoderStepSaveDuration;
|
||||
if(instance->common.code_count_bit ==
|
||||
instance->common.code_min_count_bit_for_found) {
|
||||
instance->te /= (instance->common.code_count_bit * 4 + 1);
|
||||
|
||||
instance->common.code_last_found = instance->common.code_found;
|
||||
instance->common.code_last_count_bit = instance->common.code_count_bit;
|
||||
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;
|
||||
instance->te = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
instance->te += duration;
|
||||
|
||||
if((DURATION_DIFF(instance->common.te_last, instance->common.te_short) <
|
||||
instance->common.te_delta) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_long) <
|
||||
instance->common.te_delta * 3)) {
|
||||
subghz_protocol_common_add_bit(&instance->common, 0);
|
||||
instance->common.parser_step = PrincetonDecoderStepSaveDuration;
|
||||
} else if(
|
||||
(DURATION_DIFF(instance->common.te_last, instance->common.te_long) <
|
||||
instance->common.te_delta * 3) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta)) {
|
||||
subghz_protocol_common_add_bit(&instance->common, 1);
|
||||
instance->common.parser_step = PrincetonDecoderStepSaveDuration;
|
||||
} else {
|
||||
instance->common.parser_step = PrincetonDecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
instance->common.parser_step = PrincetonDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void subghz_decoder_princeton_to_str(SubGhzDecoderPrinceton* instance, string_t output) {
|
||||
uint32_t code_found_lo = instance->common.code_last_found & 0x00000000ffffffff;
|
||||
|
||||
uint64_t code_found_reverse = subghz_protocol_common_reverse_key(
|
||||
instance->common.code_last_found, instance->common.code_last_count_bit);
|
||||
|
||||
uint32_t code_found_reverse_lo = code_found_reverse & 0x00000000ffffffff;
|
||||
|
||||
string_cat_printf(
|
||||
output,
|
||||
"%s %dbit\r\n"
|
||||
"Key:0x%08lX\r\n"
|
||||
"Yek:0x%08lX\r\n"
|
||||
"Sn:0x%05lX BTN:%02X\r\n"
|
||||
"Te:%dus\r\n",
|
||||
instance->common.name,
|
||||
instance->common.code_last_count_bit,
|
||||
code_found_lo,
|
||||
code_found_reverse_lo,
|
||||
instance->common.serial,
|
||||
instance->common.btn,
|
||||
instance->te);
|
||||
}
|
||||
|
||||
void subghz_decoder_princeton_to_save_str(SubGhzDecoderPrinceton* instance, string_t output) {
|
||||
string_printf(
|
||||
output,
|
||||
"Protocol: %s\n"
|
||||
"Bit: %d\n"
|
||||
"Te: %d\n"
|
||||
"Key: %08lX\n",
|
||||
instance->common.name,
|
||||
instance->common.code_last_count_bit,
|
||||
instance->te,
|
||||
(uint32_t)(instance->common.code_last_found & 0x00000000ffffffff));
|
||||
}
|
||||
|
||||
bool subghz_decoder_princeton_to_load_protocol_from_file(
|
||||
FileWorker* file_worker,
|
||||
SubGhzDecoderPrinceton* instance) {
|
||||
bool loaded = false;
|
||||
string_t temp_str;
|
||||
string_init(temp_str);
|
||||
int res = 0;
|
||||
int data = 0;
|
||||
|
||||
do {
|
||||
// Read and parse bit data from 2nd line
|
||||
if(!file_worker_read_until(file_worker, temp_str, '\n')) {
|
||||
break;
|
||||
}
|
||||
res = sscanf(string_get_cstr(temp_str), "Bit: %d\n", &data);
|
||||
if(res != 1) {
|
||||
break;
|
||||
}
|
||||
instance->common.code_last_count_bit = (uint8_t)data;
|
||||
|
||||
// Read and parse te data from 3nd line
|
||||
if(!file_worker_read_until(file_worker, temp_str, '\n')) {
|
||||
break;
|
||||
}
|
||||
res = sscanf(string_get_cstr(temp_str), "Te: %d\n", &data);
|
||||
if(res != 1) {
|
||||
break;
|
||||
}
|
||||
instance->te = (uint16_t)data;
|
||||
|
||||
// Read and parse key data from 4nd line
|
||||
if(!file_worker_read_until(file_worker, temp_str, '\n')) {
|
||||
break;
|
||||
}
|
||||
uint32_t temp_key = 0;
|
||||
res = sscanf(string_get_cstr(temp_str), "Key: %08lX\n", &temp_key);
|
||||
if(res != 1) {
|
||||
break;
|
||||
}
|
||||
instance->common.code_last_found = (uint64_t)temp_key;
|
||||
instance->common.serial = instance->common.code_last_found >> 4;
|
||||
instance->common.btn = (uint8_t)instance->common.code_last_found & 0x00000F;
|
||||
|
||||
loaded = true;
|
||||
} while(0);
|
||||
|
||||
string_clear(temp_str);
|
||||
|
||||
return loaded;
|
||||
}
|
||||
|
||||
void subghz_decoder_princeton_to_load_protocol(SubGhzDecoderPrinceton* instance, void* context) {
|
||||
furi_assert(context);
|
||||
furi_assert(instance);
|
||||
SubGhzProtocolCommonLoad* data = context;
|
||||
instance->common.code_last_found = data->code_found;
|
||||
instance->common.code_last_count_bit = data->code_count_bit;
|
||||
instance->te = data->param1;
|
||||
instance->common.serial = instance->common.code_last_found >> 4;
|
||||
instance->common.btn = (uint8_t)instance->common.code_last_found & 0x00000F;
|
||||
}
|
||||
|
@@ -1,125 +1,125 @@
|
||||
#pragma once
|
||||
|
||||
#include "subghz_protocol_common.h"
|
||||
|
||||
struct SubGhzDecoderPrinceton {
|
||||
SubGhzProtocolCommon common;
|
||||
uint32_t te;
|
||||
};
|
||||
|
||||
/** SubGhzEncoderPrinceton anonymous type */
|
||||
typedef struct SubGhzEncoderPrinceton SubGhzEncoderPrinceton;
|
||||
|
||||
/** Allocate SubGhzEncoderPrinceton
|
||||
* @return pointer to SubGhzEncoderPrinceton instance
|
||||
*/
|
||||
SubGhzEncoderPrinceton* subghz_encoder_princeton_alloc();
|
||||
|
||||
/** Free SubGhzEncoderPrinceton instance
|
||||
* @param instance - SubGhzEncoderPrinceton instance
|
||||
*/
|
||||
void subghz_encoder_princeton_free(SubGhzEncoderPrinceton* instance);
|
||||
|
||||
/** Set new encoder params
|
||||
* @param instance - SubGhzEncoderPrinceton instance
|
||||
* @param key - 24bit key
|
||||
* @param repeat - how many times to repeat
|
||||
*/
|
||||
void subghz_encoder_princeton_set(SubGhzEncoderPrinceton* instance, uint32_t key, size_t repeat);
|
||||
|
||||
/** Get repeat count left
|
||||
* @param instance - SubGhzEncoderPrinceton instance
|
||||
* @return repeat count left
|
||||
*/
|
||||
size_t subghz_encoder_princeton_get_repeat_left(SubGhzEncoderPrinceton* instance);
|
||||
|
||||
/** Print encoder log
|
||||
* @param instance - SubGhzEncoderPrinceton instance
|
||||
*/
|
||||
void subghz_encoder_princeton_print_log(void* context);
|
||||
|
||||
/** Get level duration
|
||||
* @param instance - SubGhzEncoderPrinceton instance
|
||||
* @return level duration
|
||||
*/
|
||||
LevelDuration subghz_encoder_princeton_yield(void* context);
|
||||
|
||||
/** SubGhzDecoderPrinceton anonymous type */
|
||||
typedef struct SubGhzDecoderPrinceton SubGhzDecoderPrinceton;
|
||||
|
||||
void subghz_encoder_princeton_set_te(SubGhzEncoderPrinceton* instance, void* decoder);
|
||||
|
||||
/** Allocate SubGhzDecoderPrinceton
|
||||
*
|
||||
* @return SubGhzDecoderPrinceton*
|
||||
*/
|
||||
SubGhzDecoderPrinceton* subghz_decoder_princeton_alloc();
|
||||
|
||||
/** Free SubGhzDecoderPrinceton
|
||||
*
|
||||
* @param instance
|
||||
*/
|
||||
void subghz_decoder_princeton_free(SubGhzDecoderPrinceton* instance);
|
||||
|
||||
/** Get Te interval protocol
|
||||
*
|
||||
* @param context - SubGhzDecoderPrinceton context
|
||||
* @return Te interval (us)
|
||||
*/
|
||||
uint16_t subghz_protocol_princeton_get_te(void* context);
|
||||
|
||||
/** Get upload protocol
|
||||
*
|
||||
* @param instance - SubGhzDecoderPrinceton instance
|
||||
* @param encoder - SubGhzProtocolCommonEncoder encoder
|
||||
* @return bool
|
||||
*/
|
||||
bool subghz_protocol_princeton_send_key(
|
||||
SubGhzDecoderPrinceton* instance,
|
||||
SubGhzProtocolCommonEncoder* encoder);
|
||||
|
||||
/** Reset internal state
|
||||
* @param instance - SubGhzDecoderPrinceton instance
|
||||
*/
|
||||
void subghz_decoder_princeton_reset(SubGhzDecoderPrinceton* instance);
|
||||
|
||||
/** Parse accepted duration
|
||||
*
|
||||
* @param instance - SubGhzDecoderPrinceton instance
|
||||
* @param data - LevelDuration level_duration
|
||||
*/
|
||||
void subghz_decoder_princeton_parse(
|
||||
SubGhzDecoderPrinceton* instance,
|
||||
bool level,
|
||||
uint32_t duration);
|
||||
|
||||
/** Outputting information from the parser
|
||||
*
|
||||
* @param instance - SubGhzDecoderPrinceton* instance
|
||||
* @param output - output string
|
||||
*/
|
||||
void subghz_decoder_princeton_to_str(SubGhzDecoderPrinceton* instance, string_t output);
|
||||
|
||||
/** Get a string to save the protocol
|
||||
*
|
||||
* @param instance - SubGhzDecoderPrinceton instance
|
||||
* @param output - the resulting string
|
||||
*/
|
||||
void subghz_decoder_princeton_to_save_str(SubGhzDecoderPrinceton* instance, string_t output);
|
||||
|
||||
/** Loading protocol from file
|
||||
*
|
||||
* @param file_worker - FileWorker file_worker
|
||||
* @param instance - SubGhzDecoderPrinceton instance
|
||||
* @return bool
|
||||
*/
|
||||
bool subghz_decoder_princeton_to_load_protocol_from_file(FileWorker* file_worker, SubGhzDecoderPrinceton* instance);
|
||||
|
||||
/** Loading protocol from bin data
|
||||
*
|
||||
* @param instance - SubGhzDecoderPrinceton instance
|
||||
* @param context - SubGhzProtocolCommonLoad context
|
||||
*/
|
||||
void subghz_decoder_princeton_to_load_protocol(
|
||||
SubGhzDecoderPrinceton* instance,
|
||||
void* context) ;
|
||||
#pragma once
|
||||
|
||||
#include "subghz_protocol_common.h"
|
||||
|
||||
struct SubGhzDecoderPrinceton {
|
||||
SubGhzProtocolCommon common;
|
||||
uint32_t te;
|
||||
};
|
||||
|
||||
/** SubGhzEncoderPrinceton anonymous type */
|
||||
typedef struct SubGhzEncoderPrinceton SubGhzEncoderPrinceton;
|
||||
|
||||
/** Allocate SubGhzEncoderPrinceton
|
||||
* @return pointer to SubGhzEncoderPrinceton instance
|
||||
*/
|
||||
SubGhzEncoderPrinceton* subghz_encoder_princeton_alloc();
|
||||
|
||||
/** Free SubGhzEncoderPrinceton instance
|
||||
* @param instance - SubGhzEncoderPrinceton instance
|
||||
*/
|
||||
void subghz_encoder_princeton_free(SubGhzEncoderPrinceton* instance);
|
||||
|
||||
/** Set new encoder params
|
||||
* @param instance - SubGhzEncoderPrinceton instance
|
||||
* @param key - 24bit key
|
||||
* @param repeat - how many times to repeat
|
||||
*/
|
||||
void subghz_encoder_princeton_set(SubGhzEncoderPrinceton* instance, uint32_t key, size_t repeat);
|
||||
|
||||
/** Get repeat count left
|
||||
* @param instance - SubGhzEncoderPrinceton instance
|
||||
* @return repeat count left
|
||||
*/
|
||||
size_t subghz_encoder_princeton_get_repeat_left(SubGhzEncoderPrinceton* instance);
|
||||
|
||||
/** Print encoder log
|
||||
* @param instance - SubGhzEncoderPrinceton instance
|
||||
*/
|
||||
void subghz_encoder_princeton_print_log(void* context);
|
||||
|
||||
/** Get level duration
|
||||
* @param instance - SubGhzEncoderPrinceton instance
|
||||
* @return level duration
|
||||
*/
|
||||
LevelDuration subghz_encoder_princeton_yield(void* context);
|
||||
|
||||
/** SubGhzDecoderPrinceton anonymous type */
|
||||
typedef struct SubGhzDecoderPrinceton SubGhzDecoderPrinceton;
|
||||
|
||||
void subghz_encoder_princeton_set_te(SubGhzEncoderPrinceton* instance, void* decoder);
|
||||
|
||||
/** Allocate SubGhzDecoderPrinceton
|
||||
*
|
||||
* @return SubGhzDecoderPrinceton*
|
||||
*/
|
||||
SubGhzDecoderPrinceton* subghz_decoder_princeton_alloc();
|
||||
|
||||
/** Free SubGhzDecoderPrinceton
|
||||
*
|
||||
* @param instance
|
||||
*/
|
||||
void subghz_decoder_princeton_free(SubGhzDecoderPrinceton* instance);
|
||||
|
||||
/** Get Te interval protocol
|
||||
*
|
||||
* @param context - SubGhzDecoderPrinceton context
|
||||
* @return Te interval (us)
|
||||
*/
|
||||
uint16_t subghz_protocol_princeton_get_te(void* context);
|
||||
|
||||
/** Get upload protocol
|
||||
*
|
||||
* @param instance - SubGhzDecoderPrinceton instance
|
||||
* @param encoder - SubGhzProtocolCommonEncoder encoder
|
||||
* @return bool
|
||||
*/
|
||||
bool subghz_protocol_princeton_send_key(
|
||||
SubGhzDecoderPrinceton* instance,
|
||||
SubGhzProtocolCommonEncoder* encoder);
|
||||
|
||||
/** Reset internal state
|
||||
* @param instance - SubGhzDecoderPrinceton instance
|
||||
*/
|
||||
void subghz_decoder_princeton_reset(SubGhzDecoderPrinceton* instance);
|
||||
|
||||
/** Parse accepted duration
|
||||
*
|
||||
* @param instance - SubGhzDecoderPrinceton instance
|
||||
* @param data - LevelDuration level_duration
|
||||
*/
|
||||
void subghz_decoder_princeton_parse(
|
||||
SubGhzDecoderPrinceton* instance,
|
||||
bool level,
|
||||
uint32_t duration);
|
||||
|
||||
/** Outputting information from the parser
|
||||
*
|
||||
* @param instance - SubGhzDecoderPrinceton* instance
|
||||
* @param output - output string
|
||||
*/
|
||||
void subghz_decoder_princeton_to_str(SubGhzDecoderPrinceton* instance, string_t output);
|
||||
|
||||
/** Get a string to save the protocol
|
||||
*
|
||||
* @param instance - SubGhzDecoderPrinceton instance
|
||||
* @param output - the resulting string
|
||||
*/
|
||||
void subghz_decoder_princeton_to_save_str(SubGhzDecoderPrinceton* instance, string_t output);
|
||||
|
||||
/** Loading protocol from file
|
||||
*
|
||||
* @param file_worker - FileWorker file_worker
|
||||
* @param instance - SubGhzDecoderPrinceton instance
|
||||
* @return bool
|
||||
*/
|
||||
bool subghz_decoder_princeton_to_load_protocol_from_file(FileWorker* file_worker, SubGhzDecoderPrinceton* instance);
|
||||
|
||||
/** Loading protocol from bin data
|
||||
*
|
||||
* @param instance - SubGhzDecoderPrinceton instance
|
||||
* @param context - SubGhzProtocolCommonLoad context
|
||||
*/
|
||||
void subghz_decoder_princeton_to_load_protocol(
|
||||
SubGhzDecoderPrinceton* instance,
|
||||
void* context) ;
|
||||
|
@@ -1,342 +1,342 @@
|
||||
#include "subghz_protocol_star_line.h"
|
||||
#include "subghz_protocol_keeloq_common.h"
|
||||
|
||||
#include "../subghz_keystore.h"
|
||||
|
||||
#include <furi.h>
|
||||
|
||||
#include <m-string.h>
|
||||
#include <m-array.h>
|
||||
|
||||
struct SubGhzProtocolStarLine {
|
||||
SubGhzProtocolCommon common;
|
||||
SubGhzKeystore* keystore;
|
||||
const char* manufacture_name;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
StarLineDecoderStepReset = 0,
|
||||
StarLineDecoderStepCheckPreambula,
|
||||
StarLineDecoderStepSaveDuration,
|
||||
StarLineDecoderStepCheckDuration,
|
||||
} StarLineDecoderStep;
|
||||
|
||||
SubGhzProtocolStarLine* subghz_protocol_star_line_alloc(SubGhzKeystore* keystore) {
|
||||
SubGhzProtocolStarLine* instance = furi_alloc(sizeof(SubGhzProtocolStarLine));
|
||||
|
||||
instance->keystore = keystore;
|
||||
|
||||
instance->common.name = "Star Line";
|
||||
instance->common.code_min_count_bit_for_found = 64;
|
||||
instance->common.te_short = 250;
|
||||
instance->common.te_long = 500;
|
||||
instance->common.te_delta = 120;
|
||||
instance->common.type_protocol = SubGhzProtocolCommonTypeDynamic;
|
||||
instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_protocol_star_line_to_str;
|
||||
instance->common.to_load_protocol =
|
||||
(SubGhzProtocolCommonLoadFromRAW)subghz_decoder_star_line_to_load_protocol;
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void subghz_protocol_star_line_free(SubGhzProtocolStarLine* instance) {
|
||||
furi_assert(instance);
|
||||
free(instance);
|
||||
}
|
||||
|
||||
const char* subghz_protocol_star_line_find_and_get_manufacture_name(void* context) {
|
||||
SubGhzProtocolStarLine* instance = context;
|
||||
subghz_protocol_star_line_check_remote_controller(instance);
|
||||
return instance->manufacture_name;
|
||||
}
|
||||
|
||||
const char* subghz_protocol_star_line_get_manufacture_name(void* context) {
|
||||
SubGhzProtocolStarLine* instance = context;
|
||||
return instance->manufacture_name;
|
||||
}
|
||||
|
||||
/** Send bit
|
||||
*
|
||||
* @param instance - SubGhzProtocolStarLine instance
|
||||
* @param bit - bit
|
||||
*/
|
||||
void subghz_protocol_star_line_send_bit(SubGhzProtocolStarLine* instance, uint8_t bit) {
|
||||
if(bit) {
|
||||
//send bit 1
|
||||
SUBGHZ_TX_PIN_HIGH();
|
||||
delay_us(instance->common.te_long);
|
||||
SUBGHZ_TX_PIN_LOW();
|
||||
delay_us(instance->common.te_long);
|
||||
} else {
|
||||
//send bit 0
|
||||
SUBGHZ_TX_PIN_HIGH();
|
||||
delay_us(instance->common.te_short);
|
||||
SUBGHZ_TX_PIN_LOW();
|
||||
delay_us(instance->common.te_short);
|
||||
}
|
||||
}
|
||||
|
||||
void subghz_protocol_star_line_send_key(
|
||||
SubGhzProtocolStarLine* instance,
|
||||
uint64_t key,
|
||||
uint8_t bit,
|
||||
uint8_t repeat) {
|
||||
while(repeat--) {
|
||||
//Send header
|
||||
for(uint8_t i = 0; i < 6; i++) {
|
||||
SUBGHZ_TX_PIN_HIGH();
|
||||
delay_us(instance->common.te_long * 2);
|
||||
SUBGHZ_TX_PIN_LOW();
|
||||
delay_us(instance->common.te_long * 2);
|
||||
}
|
||||
//Send Start bit ??????????
|
||||
//Send key data
|
||||
for(uint8_t i = bit; i > 0; i--) {
|
||||
subghz_protocol_star_line_send_bit(instance, bit_read(key, i - 1));
|
||||
}
|
||||
//Send Stop bit ??????????
|
||||
}
|
||||
}
|
||||
|
||||
void subghz_protocol_star_line_reset(SubGhzProtocolStarLine* instance) {
|
||||
instance->common.parser_step = StarLineDecoderStepReset;
|
||||
}
|
||||
|
||||
/** Checking the accepted code against the database manafacture key
|
||||
*
|
||||
* @param instance SubGhzProtocolStarLine instance
|
||||
* @param fix fix part of the parcel
|
||||
* @param hop hop encrypted part of the parcel
|
||||
* @return true on successful search
|
||||
*/
|
||||
uint8_t subghz_protocol_star_line_check_remote_controller_selector(
|
||||
SubGhzProtocolStarLine* instance,
|
||||
uint32_t fix,
|
||||
uint32_t hop) {
|
||||
uint16_t end_serial = (uint16_t)(fix & 0xFF);
|
||||
uint8_t btn = (uint8_t)(fix >> 24);
|
||||
uint32_t decrypt = 0;
|
||||
uint64_t man_normal_learning;
|
||||
|
||||
for
|
||||
M_EACH(manufacture_code, *subghz_keystore_get_data(instance->keystore), SubGhzKeyArray_t) {
|
||||
switch(manufacture_code->type) {
|
||||
case KEELOQ_LEARNING_SIMPLE:
|
||||
//Simple Learning
|
||||
decrypt = subghz_protocol_keeloq_common_decrypt(hop, manufacture_code->key);
|
||||
if((decrypt >> 24 == btn) &&
|
||||
((((uint16_t)(decrypt >> 16)) & 0x00FF) == end_serial)) {
|
||||
instance->manufacture_name = string_get_cstr(manufacture_code->name);
|
||||
instance->common.cnt = decrypt & 0x0000FFFF;
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case KEELOQ_LEARNING_NORMAL:
|
||||
// Normal_Learning
|
||||
// https://phreakerclub.com/forum/showpost.php?p=43557&postcount=37
|
||||
man_normal_learning =
|
||||
subghz_protocol_keeloq_common_normal_learning(fix, manufacture_code->key);
|
||||
decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_normal_learning);
|
||||
if((decrypt >> 24 == btn) &&
|
||||
((((uint16_t)(decrypt >> 16)) & 0x00FF) == end_serial)) {
|
||||
instance->manufacture_name = string_get_cstr(manufacture_code->name);
|
||||
instance->common.cnt = decrypt & 0x0000FFFF;
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case KEELOQ_LEARNING_UNKNOWN:
|
||||
// Simple Learning
|
||||
decrypt = subghz_protocol_keeloq_common_decrypt(hop, manufacture_code->key);
|
||||
if((decrypt >> 24 == btn) &&
|
||||
((((uint16_t)(decrypt >> 16)) & 0x00FF) == end_serial)) {
|
||||
instance->manufacture_name = string_get_cstr(manufacture_code->name);
|
||||
instance->common.cnt = decrypt & 0x0000FFFF;
|
||||
return 1;
|
||||
}
|
||||
// Check for mirrored man
|
||||
uint64_t man_rev = 0;
|
||||
uint64_t man_rev_byte = 0;
|
||||
for(uint8_t i = 0; i < 64; i += 8) {
|
||||
man_rev_byte = (uint8_t)(manufacture_code->key >> i);
|
||||
man_rev = man_rev | man_rev_byte << (56 - i);
|
||||
}
|
||||
decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_rev);
|
||||
if((decrypt >> 24 == btn) &&
|
||||
((((uint16_t)(decrypt >> 16)) & 0x00FF) == end_serial)) {
|
||||
instance->manufacture_name = string_get_cstr(manufacture_code->name);
|
||||
instance->common.cnt = decrypt & 0x0000FFFF;
|
||||
return 1;
|
||||
}
|
||||
//###########################
|
||||
// Normal_Learning
|
||||
// https://phreakerclub.com/forum/showpost.php?p=43557&postcount=37
|
||||
man_normal_learning =
|
||||
subghz_protocol_keeloq_common_normal_learning(fix, manufacture_code->key);
|
||||
decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_normal_learning);
|
||||
if((decrypt >> 24 == btn) &&
|
||||
((((uint16_t)(decrypt >> 16)) & 0x00FF) == end_serial)) {
|
||||
instance->manufacture_name = string_get_cstr(manufacture_code->name);
|
||||
instance->common.cnt = decrypt & 0x0000FFFF;
|
||||
return 1;
|
||||
}
|
||||
// Check for mirrored man
|
||||
man_rev = 0;
|
||||
man_rev_byte = 0;
|
||||
for(uint8_t i = 0; i < 64; i += 8) {
|
||||
man_rev_byte = (uint8_t)(manufacture_code->key >> i);
|
||||
man_rev = man_rev | man_rev_byte << (56 - i);
|
||||
}
|
||||
man_normal_learning = subghz_protocol_keeloq_common_normal_learning(fix, man_rev);
|
||||
decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_normal_learning);
|
||||
if((decrypt >> 24 == btn) &&
|
||||
((((uint16_t)(decrypt >> 16)) & 0x00FF) == end_serial)) {
|
||||
instance->manufacture_name = string_get_cstr(manufacture_code->name);
|
||||
instance->common.cnt = decrypt & 0x0000FFFF;
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
instance->manufacture_name = "Unknown";
|
||||
instance->common.cnt = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Analysis of received data
|
||||
*
|
||||
* @param instance SubGhzProtocolStarLine instance
|
||||
*/
|
||||
void subghz_protocol_star_line_check_remote_controller(SubGhzProtocolStarLine* instance) {
|
||||
uint64_t key = subghz_protocol_common_reverse_key(
|
||||
instance->common.code_last_found, instance->common.code_last_count_bit);
|
||||
uint32_t key_fix = key >> 32;
|
||||
uint32_t key_hop = key & 0x00000000ffffffff;
|
||||
|
||||
subghz_protocol_star_line_check_remote_controller_selector(instance, key_fix, key_hop);
|
||||
|
||||
instance->common.serial = key_fix & 0x00FFFFFF;
|
||||
instance->common.btn = key_fix >> 24;
|
||||
}
|
||||
|
||||
void subghz_protocol_star_line_parse(
|
||||
SubGhzProtocolStarLine* instance,
|
||||
bool level,
|
||||
uint32_t duration) {
|
||||
switch(instance->common.parser_step) {
|
||||
case StarLineDecoderStepReset:
|
||||
if(level) {
|
||||
if(DURATION_DIFF(duration, instance->common.te_long * 2) <
|
||||
instance->common.te_delta * 2) {
|
||||
instance->common.parser_step = StarLineDecoderStepCheckPreambula;
|
||||
instance->common.header_count++;
|
||||
} else if(instance->common.header_count > 4) {
|
||||
instance->common.code_found = 0;
|
||||
instance->common.code_count_bit = 0;
|
||||
instance->common.te_last = duration;
|
||||
instance->common.parser_step = StarLineDecoderStepCheckDuration;
|
||||
}
|
||||
} else {
|
||||
instance->common.parser_step = StarLineDecoderStepReset;
|
||||
instance->common.header_count = 0;
|
||||
}
|
||||
break;
|
||||
case StarLineDecoderStepCheckPreambula:
|
||||
if((!level) && (DURATION_DIFF(duration, instance->common.te_long * 2) <
|
||||
instance->common.te_delta * 2)) {
|
||||
//Found Preambula
|
||||
instance->common.parser_step = StarLineDecoderStepReset;
|
||||
} else {
|
||||
instance->common.header_count = 0;
|
||||
instance->common.parser_step = StarLineDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case StarLineDecoderStepSaveDuration:
|
||||
if(level) {
|
||||
if(duration >= (instance->common.te_long + instance->common.te_delta)) {
|
||||
instance->common.parser_step = StarLineDecoderStepReset;
|
||||
if(instance->common.code_count_bit >=
|
||||
instance->common.code_min_count_bit_for_found) {
|
||||
if(instance->common.code_last_found != instance->common.code_found) {
|
||||
instance->common.code_last_found = instance->common.code_found;
|
||||
instance->common.code_last_count_bit = instance->common.code_count_bit;
|
||||
if(instance->common.callback)
|
||||
instance->common.callback(
|
||||
(SubGhzProtocolCommon*)instance, instance->common.context);
|
||||
}
|
||||
}
|
||||
instance->common.code_found = 0;
|
||||
instance->common.code_count_bit = 0;
|
||||
instance->common.header_count = 0;
|
||||
break;
|
||||
} else {
|
||||
instance->common.te_last = duration;
|
||||
instance->common.parser_step = StarLineDecoderStepCheckDuration;
|
||||
}
|
||||
|
||||
} else {
|
||||
instance->common.parser_step = StarLineDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case StarLineDecoderStepCheckDuration:
|
||||
if(!level) {
|
||||
if((DURATION_DIFF(instance->common.te_last, instance->common.te_short) <
|
||||
instance->common.te_delta) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta)) {
|
||||
subghz_protocol_common_add_bit(&instance->common, 0);
|
||||
instance->common.parser_step = StarLineDecoderStepSaveDuration;
|
||||
} else if(
|
||||
(DURATION_DIFF(instance->common.te_last, 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, 1);
|
||||
instance->common.parser_step = StarLineDecoderStepSaveDuration;
|
||||
} else {
|
||||
instance->common.parser_step = StarLineDecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
instance->common.parser_step = StarLineDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void subghz_protocol_star_line_to_str(SubGhzProtocolStarLine* instance, string_t output) {
|
||||
subghz_protocol_star_line_check_remote_controller(instance);
|
||||
uint32_t code_found_hi = instance->common.code_last_found >> 32;
|
||||
uint32_t code_found_lo = instance->common.code_last_found & 0x00000000ffffffff;
|
||||
|
||||
uint64_t code_found_reverse = subghz_protocol_common_reverse_key(
|
||||
instance->common.code_last_found, instance->common.code_last_count_bit);
|
||||
|
||||
uint32_t code_found_reverse_hi = code_found_reverse >> 32;
|
||||
uint32_t code_found_reverse_lo = code_found_reverse & 0x00000000ffffffff;
|
||||
string_cat_printf(
|
||||
output,
|
||||
"%s %dbit\r\n"
|
||||
"Key:%08lX%08lX\r\n"
|
||||
"Fix:0x%08lX Cnt:%04X\r\n"
|
||||
"Hop:0x%08lX Btn:%02lX\r\n"
|
||||
"MF:%s\r\n"
|
||||
"Sn:0x%07lX \r\n",
|
||||
instance->common.name,
|
||||
instance->common.code_last_count_bit,
|
||||
code_found_hi,
|
||||
code_found_lo,
|
||||
code_found_reverse_hi,
|
||||
instance->common.cnt,
|
||||
code_found_reverse_lo,
|
||||
instance->common.btn,
|
||||
instance->manufacture_name,
|
||||
instance->common.serial);
|
||||
}
|
||||
|
||||
void subghz_decoder_star_line_to_load_protocol(SubGhzProtocolStarLine* instance, void* context) {
|
||||
furi_assert(context);
|
||||
furi_assert(instance);
|
||||
SubGhzProtocolCommonLoad* data = context;
|
||||
instance->common.code_last_found = data->code_found;
|
||||
instance->common.code_last_count_bit = data->code_count_bit;
|
||||
subghz_protocol_star_line_check_remote_controller(instance);
|
||||
#include "subghz_protocol_star_line.h"
|
||||
#include "subghz_protocol_keeloq_common.h"
|
||||
|
||||
#include "../subghz_keystore.h"
|
||||
|
||||
#include <furi.h>
|
||||
|
||||
#include <m-string.h>
|
||||
#include <m-array.h>
|
||||
|
||||
struct SubGhzProtocolStarLine {
|
||||
SubGhzProtocolCommon common;
|
||||
SubGhzKeystore* keystore;
|
||||
const char* manufacture_name;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
StarLineDecoderStepReset = 0,
|
||||
StarLineDecoderStepCheckPreambula,
|
||||
StarLineDecoderStepSaveDuration,
|
||||
StarLineDecoderStepCheckDuration,
|
||||
} StarLineDecoderStep;
|
||||
|
||||
SubGhzProtocolStarLine* subghz_protocol_star_line_alloc(SubGhzKeystore* keystore) {
|
||||
SubGhzProtocolStarLine* instance = furi_alloc(sizeof(SubGhzProtocolStarLine));
|
||||
|
||||
instance->keystore = keystore;
|
||||
|
||||
instance->common.name = "Star Line";
|
||||
instance->common.code_min_count_bit_for_found = 64;
|
||||
instance->common.te_short = 250;
|
||||
instance->common.te_long = 500;
|
||||
instance->common.te_delta = 120;
|
||||
instance->common.type_protocol = SubGhzProtocolCommonTypeDynamic;
|
||||
instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_protocol_star_line_to_str;
|
||||
instance->common.to_load_protocol =
|
||||
(SubGhzProtocolCommonLoadFromRAW)subghz_decoder_star_line_to_load_protocol;
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void subghz_protocol_star_line_free(SubGhzProtocolStarLine* instance) {
|
||||
furi_assert(instance);
|
||||
free(instance);
|
||||
}
|
||||
|
||||
const char* subghz_protocol_star_line_find_and_get_manufacture_name(void* context) {
|
||||
SubGhzProtocolStarLine* instance = context;
|
||||
subghz_protocol_star_line_check_remote_controller(instance);
|
||||
return instance->manufacture_name;
|
||||
}
|
||||
|
||||
const char* subghz_protocol_star_line_get_manufacture_name(void* context) {
|
||||
SubGhzProtocolStarLine* instance = context;
|
||||
return instance->manufacture_name;
|
||||
}
|
||||
|
||||
/** Send bit
|
||||
*
|
||||
* @param instance - SubGhzProtocolStarLine instance
|
||||
* @param bit - bit
|
||||
*/
|
||||
void subghz_protocol_star_line_send_bit(SubGhzProtocolStarLine* instance, uint8_t bit) {
|
||||
if(bit) {
|
||||
//send bit 1
|
||||
SUBGHZ_TX_PIN_HIGH();
|
||||
delay_us(instance->common.te_long);
|
||||
SUBGHZ_TX_PIN_LOW();
|
||||
delay_us(instance->common.te_long);
|
||||
} else {
|
||||
//send bit 0
|
||||
SUBGHZ_TX_PIN_HIGH();
|
||||
delay_us(instance->common.te_short);
|
||||
SUBGHZ_TX_PIN_LOW();
|
||||
delay_us(instance->common.te_short);
|
||||
}
|
||||
}
|
||||
|
||||
void subghz_protocol_star_line_send_key(
|
||||
SubGhzProtocolStarLine* instance,
|
||||
uint64_t key,
|
||||
uint8_t bit,
|
||||
uint8_t repeat) {
|
||||
while(repeat--) {
|
||||
//Send header
|
||||
for(uint8_t i = 0; i < 6; i++) {
|
||||
SUBGHZ_TX_PIN_HIGH();
|
||||
delay_us(instance->common.te_long * 2);
|
||||
SUBGHZ_TX_PIN_LOW();
|
||||
delay_us(instance->common.te_long * 2);
|
||||
}
|
||||
//Send Start bit ??????????
|
||||
//Send key data
|
||||
for(uint8_t i = bit; i > 0; i--) {
|
||||
subghz_protocol_star_line_send_bit(instance, bit_read(key, i - 1));
|
||||
}
|
||||
//Send Stop bit ??????????
|
||||
}
|
||||
}
|
||||
|
||||
void subghz_protocol_star_line_reset(SubGhzProtocolStarLine* instance) {
|
||||
instance->common.parser_step = StarLineDecoderStepReset;
|
||||
}
|
||||
|
||||
/** Checking the accepted code against the database manafacture key
|
||||
*
|
||||
* @param instance SubGhzProtocolStarLine instance
|
||||
* @param fix fix part of the parcel
|
||||
* @param hop hop encrypted part of the parcel
|
||||
* @return true on successful search
|
||||
*/
|
||||
uint8_t subghz_protocol_star_line_check_remote_controller_selector(
|
||||
SubGhzProtocolStarLine* instance,
|
||||
uint32_t fix,
|
||||
uint32_t hop) {
|
||||
uint16_t end_serial = (uint16_t)(fix & 0xFF);
|
||||
uint8_t btn = (uint8_t)(fix >> 24);
|
||||
uint32_t decrypt = 0;
|
||||
uint64_t man_normal_learning;
|
||||
|
||||
for
|
||||
M_EACH(manufacture_code, *subghz_keystore_get_data(instance->keystore), SubGhzKeyArray_t) {
|
||||
switch(manufacture_code->type) {
|
||||
case KEELOQ_LEARNING_SIMPLE:
|
||||
//Simple Learning
|
||||
decrypt = subghz_protocol_keeloq_common_decrypt(hop, manufacture_code->key);
|
||||
if((decrypt >> 24 == btn) &&
|
||||
((((uint16_t)(decrypt >> 16)) & 0x00FF) == end_serial)) {
|
||||
instance->manufacture_name = string_get_cstr(manufacture_code->name);
|
||||
instance->common.cnt = decrypt & 0x0000FFFF;
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case KEELOQ_LEARNING_NORMAL:
|
||||
// Normal_Learning
|
||||
// https://phreakerclub.com/forum/showpost.php?p=43557&postcount=37
|
||||
man_normal_learning =
|
||||
subghz_protocol_keeloq_common_normal_learning(fix, manufacture_code->key);
|
||||
decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_normal_learning);
|
||||
if((decrypt >> 24 == btn) &&
|
||||
((((uint16_t)(decrypt >> 16)) & 0x00FF) == end_serial)) {
|
||||
instance->manufacture_name = string_get_cstr(manufacture_code->name);
|
||||
instance->common.cnt = decrypt & 0x0000FFFF;
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case KEELOQ_LEARNING_UNKNOWN:
|
||||
// Simple Learning
|
||||
decrypt = subghz_protocol_keeloq_common_decrypt(hop, manufacture_code->key);
|
||||
if((decrypt >> 24 == btn) &&
|
||||
((((uint16_t)(decrypt >> 16)) & 0x00FF) == end_serial)) {
|
||||
instance->manufacture_name = string_get_cstr(manufacture_code->name);
|
||||
instance->common.cnt = decrypt & 0x0000FFFF;
|
||||
return 1;
|
||||
}
|
||||
// Check for mirrored man
|
||||
uint64_t man_rev = 0;
|
||||
uint64_t man_rev_byte = 0;
|
||||
for(uint8_t i = 0; i < 64; i += 8) {
|
||||
man_rev_byte = (uint8_t)(manufacture_code->key >> i);
|
||||
man_rev = man_rev | man_rev_byte << (56 - i);
|
||||
}
|
||||
decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_rev);
|
||||
if((decrypt >> 24 == btn) &&
|
||||
((((uint16_t)(decrypt >> 16)) & 0x00FF) == end_serial)) {
|
||||
instance->manufacture_name = string_get_cstr(manufacture_code->name);
|
||||
instance->common.cnt = decrypt & 0x0000FFFF;
|
||||
return 1;
|
||||
}
|
||||
//###########################
|
||||
// Normal_Learning
|
||||
// https://phreakerclub.com/forum/showpost.php?p=43557&postcount=37
|
||||
man_normal_learning =
|
||||
subghz_protocol_keeloq_common_normal_learning(fix, manufacture_code->key);
|
||||
decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_normal_learning);
|
||||
if((decrypt >> 24 == btn) &&
|
||||
((((uint16_t)(decrypt >> 16)) & 0x00FF) == end_serial)) {
|
||||
instance->manufacture_name = string_get_cstr(manufacture_code->name);
|
||||
instance->common.cnt = decrypt & 0x0000FFFF;
|
||||
return 1;
|
||||
}
|
||||
// Check for mirrored man
|
||||
man_rev = 0;
|
||||
man_rev_byte = 0;
|
||||
for(uint8_t i = 0; i < 64; i += 8) {
|
||||
man_rev_byte = (uint8_t)(manufacture_code->key >> i);
|
||||
man_rev = man_rev | man_rev_byte << (56 - i);
|
||||
}
|
||||
man_normal_learning = subghz_protocol_keeloq_common_normal_learning(fix, man_rev);
|
||||
decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_normal_learning);
|
||||
if((decrypt >> 24 == btn) &&
|
||||
((((uint16_t)(decrypt >> 16)) & 0x00FF) == end_serial)) {
|
||||
instance->manufacture_name = string_get_cstr(manufacture_code->name);
|
||||
instance->common.cnt = decrypt & 0x0000FFFF;
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
instance->manufacture_name = "Unknown";
|
||||
instance->common.cnt = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Analysis of received data
|
||||
*
|
||||
* @param instance SubGhzProtocolStarLine instance
|
||||
*/
|
||||
void subghz_protocol_star_line_check_remote_controller(SubGhzProtocolStarLine* instance) {
|
||||
uint64_t key = subghz_protocol_common_reverse_key(
|
||||
instance->common.code_last_found, instance->common.code_last_count_bit);
|
||||
uint32_t key_fix = key >> 32;
|
||||
uint32_t key_hop = key & 0x00000000ffffffff;
|
||||
|
||||
subghz_protocol_star_line_check_remote_controller_selector(instance, key_fix, key_hop);
|
||||
|
||||
instance->common.serial = key_fix & 0x00FFFFFF;
|
||||
instance->common.btn = key_fix >> 24;
|
||||
}
|
||||
|
||||
void subghz_protocol_star_line_parse(
|
||||
SubGhzProtocolStarLine* instance,
|
||||
bool level,
|
||||
uint32_t duration) {
|
||||
switch(instance->common.parser_step) {
|
||||
case StarLineDecoderStepReset:
|
||||
if(level) {
|
||||
if(DURATION_DIFF(duration, instance->common.te_long * 2) <
|
||||
instance->common.te_delta * 2) {
|
||||
instance->common.parser_step = StarLineDecoderStepCheckPreambula;
|
||||
instance->common.header_count++;
|
||||
} else if(instance->common.header_count > 4) {
|
||||
instance->common.code_found = 0;
|
||||
instance->common.code_count_bit = 0;
|
||||
instance->common.te_last = duration;
|
||||
instance->common.parser_step = StarLineDecoderStepCheckDuration;
|
||||
}
|
||||
} else {
|
||||
instance->common.parser_step = StarLineDecoderStepReset;
|
||||
instance->common.header_count = 0;
|
||||
}
|
||||
break;
|
||||
case StarLineDecoderStepCheckPreambula:
|
||||
if((!level) && (DURATION_DIFF(duration, instance->common.te_long * 2) <
|
||||
instance->common.te_delta * 2)) {
|
||||
//Found Preambula
|
||||
instance->common.parser_step = StarLineDecoderStepReset;
|
||||
} else {
|
||||
instance->common.header_count = 0;
|
||||
instance->common.parser_step = StarLineDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case StarLineDecoderStepSaveDuration:
|
||||
if(level) {
|
||||
if(duration >= (instance->common.te_long + instance->common.te_delta)) {
|
||||
instance->common.parser_step = StarLineDecoderStepReset;
|
||||
if(instance->common.code_count_bit >=
|
||||
instance->common.code_min_count_bit_for_found) {
|
||||
if(instance->common.code_last_found != instance->common.code_found) {
|
||||
instance->common.code_last_found = instance->common.code_found;
|
||||
instance->common.code_last_count_bit = instance->common.code_count_bit;
|
||||
if(instance->common.callback)
|
||||
instance->common.callback(
|
||||
(SubGhzProtocolCommon*)instance, instance->common.context);
|
||||
}
|
||||
}
|
||||
instance->common.code_found = 0;
|
||||
instance->common.code_count_bit = 0;
|
||||
instance->common.header_count = 0;
|
||||
break;
|
||||
} else {
|
||||
instance->common.te_last = duration;
|
||||
instance->common.parser_step = StarLineDecoderStepCheckDuration;
|
||||
}
|
||||
|
||||
} else {
|
||||
instance->common.parser_step = StarLineDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case StarLineDecoderStepCheckDuration:
|
||||
if(!level) {
|
||||
if((DURATION_DIFF(instance->common.te_last, instance->common.te_short) <
|
||||
instance->common.te_delta) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta)) {
|
||||
subghz_protocol_common_add_bit(&instance->common, 0);
|
||||
instance->common.parser_step = StarLineDecoderStepSaveDuration;
|
||||
} else if(
|
||||
(DURATION_DIFF(instance->common.te_last, 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, 1);
|
||||
instance->common.parser_step = StarLineDecoderStepSaveDuration;
|
||||
} else {
|
||||
instance->common.parser_step = StarLineDecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
instance->common.parser_step = StarLineDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void subghz_protocol_star_line_to_str(SubGhzProtocolStarLine* instance, string_t output) {
|
||||
subghz_protocol_star_line_check_remote_controller(instance);
|
||||
uint32_t code_found_hi = instance->common.code_last_found >> 32;
|
||||
uint32_t code_found_lo = instance->common.code_last_found & 0x00000000ffffffff;
|
||||
|
||||
uint64_t code_found_reverse = subghz_protocol_common_reverse_key(
|
||||
instance->common.code_last_found, instance->common.code_last_count_bit);
|
||||
|
||||
uint32_t code_found_reverse_hi = code_found_reverse >> 32;
|
||||
uint32_t code_found_reverse_lo = code_found_reverse & 0x00000000ffffffff;
|
||||
string_cat_printf(
|
||||
output,
|
||||
"%s %dbit\r\n"
|
||||
"Key:%08lX%08lX\r\n"
|
||||
"Fix:0x%08lX Cnt:%04X\r\n"
|
||||
"Hop:0x%08lX Btn:%02lX\r\n"
|
||||
"MF:%s\r\n"
|
||||
"Sn:0x%07lX \r\n",
|
||||
instance->common.name,
|
||||
instance->common.code_last_count_bit,
|
||||
code_found_hi,
|
||||
code_found_lo,
|
||||
code_found_reverse_hi,
|
||||
instance->common.cnt,
|
||||
code_found_reverse_lo,
|
||||
instance->common.btn,
|
||||
instance->manufacture_name,
|
||||
instance->common.serial);
|
||||
}
|
||||
|
||||
void subghz_decoder_star_line_to_load_protocol(SubGhzProtocolStarLine* instance, void* context) {
|
||||
furi_assert(context);
|
||||
furi_assert(instance);
|
||||
SubGhzProtocolCommonLoad* data = context;
|
||||
instance->common.code_last_found = data->code_found;
|
||||
instance->common.code_last_count_bit = data->code_count_bit;
|
||||
subghz_protocol_star_line_check_remote_controller(instance);
|
||||
}
|
@@ -1,74 +1,74 @@
|
||||
#pragma once
|
||||
|
||||
#include "subghz_protocol_common.h"
|
||||
|
||||
typedef struct SubGhzKeystore SubGhzKeystore;
|
||||
|
||||
typedef struct SubGhzProtocolStarLine SubGhzProtocolStarLine;
|
||||
|
||||
/** Allocate SubGhzProtocolStarLine
|
||||
*
|
||||
* @return SubGhzProtocolStarLine*
|
||||
*/
|
||||
SubGhzProtocolStarLine* subghz_protocol_star_line_alloc(SubGhzKeystore* keystore);
|
||||
|
||||
/** Free SubGhzProtocolStarLine
|
||||
*
|
||||
* @param instance
|
||||
*/
|
||||
void subghz_protocol_star_line_free(SubGhzProtocolStarLine* instance);
|
||||
|
||||
/** Find and get manufacture name
|
||||
*
|
||||
* @param context - SubGhzProtocolStarLine context
|
||||
* @return name - char* manufacture name
|
||||
*/
|
||||
const char* subghz_protocol_star_line_find_and_get_manufacture_name(void* context);
|
||||
|
||||
/** Get manufacture name
|
||||
*
|
||||
* @param context - SubGhzProtocolStarLine context
|
||||
* @return name - char* manufacture name
|
||||
*/
|
||||
const char* subghz_protocol_star_line_get_manufacture_name(void* context);
|
||||
|
||||
/** Sends the key on the air
|
||||
*
|
||||
* @param instance - SubGhzProtocolStarLine instance
|
||||
* @param key - key send
|
||||
* @param bit - count bit key
|
||||
* @param repeat - repeat send key
|
||||
*/
|
||||
void subghz_protocol_star_line_send_key(SubGhzProtocolStarLine* instance, uint64_t key, uint8_t bit, uint8_t repeat);
|
||||
|
||||
/** Reset internal state
|
||||
* @param instance - SubGhzProtocolStarLine instance
|
||||
*/
|
||||
void subghz_protocol_star_line_reset(SubGhzProtocolStarLine* instance);
|
||||
|
||||
/** Analysis of received data
|
||||
*
|
||||
* @param instance SubGhzProtocolStarLine instance
|
||||
*/
|
||||
void subghz_protocol_star_line_check_remote_controller(SubGhzProtocolStarLine* instance);
|
||||
|
||||
/** Parse accepted duration
|
||||
*
|
||||
* @param instance - SubGhzProtocolStarLine instance
|
||||
* @param data - LevelDuration level_duration
|
||||
*/
|
||||
void subghz_protocol_star_line_parse(SubGhzProtocolStarLine* instance, bool level, uint32_t duration);
|
||||
|
||||
/** Outputting information from the parser
|
||||
*
|
||||
* @param instance - SubGhzProtocolStarLine* instance
|
||||
* @param output - output string
|
||||
*/
|
||||
void subghz_protocol_star_line_to_str(SubGhzProtocolStarLine* instance, string_t output);
|
||||
|
||||
/** Loading protocol from bin data
|
||||
*
|
||||
* @param instance - SubGhzDecoderPrinceton instance
|
||||
* @param context - SubGhzProtocolCommonLoad context
|
||||
*/
|
||||
void subghz_decoder_star_line_to_load_protocol(SubGhzProtocolStarLine* instance, void* context);
|
||||
#pragma once
|
||||
|
||||
#include "subghz_protocol_common.h"
|
||||
|
||||
typedef struct SubGhzKeystore SubGhzKeystore;
|
||||
|
||||
typedef struct SubGhzProtocolStarLine SubGhzProtocolStarLine;
|
||||
|
||||
/** Allocate SubGhzProtocolStarLine
|
||||
*
|
||||
* @return SubGhzProtocolStarLine*
|
||||
*/
|
||||
SubGhzProtocolStarLine* subghz_protocol_star_line_alloc(SubGhzKeystore* keystore);
|
||||
|
||||
/** Free SubGhzProtocolStarLine
|
||||
*
|
||||
* @param instance
|
||||
*/
|
||||
void subghz_protocol_star_line_free(SubGhzProtocolStarLine* instance);
|
||||
|
||||
/** Find and get manufacture name
|
||||
*
|
||||
* @param context - SubGhzProtocolStarLine context
|
||||
* @return name - char* manufacture name
|
||||
*/
|
||||
const char* subghz_protocol_star_line_find_and_get_manufacture_name(void* context);
|
||||
|
||||
/** Get manufacture name
|
||||
*
|
||||
* @param context - SubGhzProtocolStarLine context
|
||||
* @return name - char* manufacture name
|
||||
*/
|
||||
const char* subghz_protocol_star_line_get_manufacture_name(void* context);
|
||||
|
||||
/** Sends the key on the air
|
||||
*
|
||||
* @param instance - SubGhzProtocolStarLine instance
|
||||
* @param key - key send
|
||||
* @param bit - count bit key
|
||||
* @param repeat - repeat send key
|
||||
*/
|
||||
void subghz_protocol_star_line_send_key(SubGhzProtocolStarLine* instance, uint64_t key, uint8_t bit, uint8_t repeat);
|
||||
|
||||
/** Reset internal state
|
||||
* @param instance - SubGhzProtocolStarLine instance
|
||||
*/
|
||||
void subghz_protocol_star_line_reset(SubGhzProtocolStarLine* instance);
|
||||
|
||||
/** Analysis of received data
|
||||
*
|
||||
* @param instance SubGhzProtocolStarLine instance
|
||||
*/
|
||||
void subghz_protocol_star_line_check_remote_controller(SubGhzProtocolStarLine* instance);
|
||||
|
||||
/** Parse accepted duration
|
||||
*
|
||||
* @param instance - SubGhzProtocolStarLine instance
|
||||
* @param data - LevelDuration level_duration
|
||||
*/
|
||||
void subghz_protocol_star_line_parse(SubGhzProtocolStarLine* instance, bool level, uint32_t duration);
|
||||
|
||||
/** Outputting information from the parser
|
||||
*
|
||||
* @param instance - SubGhzProtocolStarLine* instance
|
||||
* @param output - output string
|
||||
*/
|
||||
void subghz_protocol_star_line_to_str(SubGhzProtocolStarLine* instance, string_t output);
|
||||
|
||||
/** Loading protocol from bin data
|
||||
*
|
||||
* @param instance - SubGhzDecoderPrinceton instance
|
||||
* @param context - SubGhzProtocolCommonLoad context
|
||||
*/
|
||||
void subghz_decoder_star_line_to_load_protocol(SubGhzProtocolStarLine* instance, void* context);
|
||||
|
Reference in New Issue
Block a user