mirror of
https://github.com/DarkFlippers/unleashed-firmware
synced 2024-11-27 15:00:46 +00:00
Merge branch 'dev' into somfy_encoder_new
This commit is contained in:
commit
27826f95ca
100 changed files with 2948 additions and 3468 deletions
|
@ -1 +1 @@
|
|||
--rules-config .pvsconfig -e lib/fatfs -e lib/fnv1a-hash -e lib/FreeRTOS-Kernel -e lib/heatshrink -e lib/libusb_stm32 -e lib/littlefs -e lib/mbedtls -e lib/micro-ecc -e lib/microtar -e lib/mlib -e lib/qrcode -e lib/ST25RFAL002 -e lib/STM32CubeWB -e lib/u8g2 -e lib/nanopb -e */arm-none-eabi/* -e applications/plugins/dap_link/lib/free-dap
|
||||
--ignore-ccache -C gccarm --rules-config .pvsconfig -e lib/fatfs -e lib/fnv1a-hash -e lib/FreeRTOS-Kernel -e lib/heatshrink -e lib/libusb_stm32 -e lib/littlefs -e lib/mbedtls -e lib/micro-ecc -e lib/microtar -e lib/mlib -e lib/qrcode -e lib/ST25RFAL002 -e lib/STM32CubeWB -e lib/u8g2 -e lib/nanopb -e */arm-none-eabi/* -e applications/plugins/dap_link/lib/free-dap
|
||||
|
|
22
.vscode/example/tasks.json
vendored
22
.vscode/example/tasks.json
vendored
|
@ -105,6 +105,12 @@
|
|||
"type": "shell",
|
||||
"command": "./fbt COMPACT=1 DEBUG=0 FORCE=1 flash_usb_full"
|
||||
},
|
||||
{
|
||||
"label": "[Debug] Create PVS-Studio report",
|
||||
"group": "build",
|
||||
"type": "shell",
|
||||
"command": "./fbt firmware_pvs"
|
||||
},
|
||||
{
|
||||
"label": "[Debug] Build FAPs",
|
||||
"group": "build",
|
||||
|
@ -138,6 +144,18 @@
|
|||
"Serial Console"
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "[Debug] Build and upload all FAPs to Flipper over USB",
|
||||
"group": "build",
|
||||
"type": "shell",
|
||||
"command": "./fbt fap_deploy"
|
||||
},
|
||||
{
|
||||
"label": "[Release] Build and upload all FAPs to Flipper over USB",
|
||||
"group": "build",
|
||||
"type": "shell",
|
||||
"command": "./fbt COMPACT=1 DEBUG=0 fap_deploy"
|
||||
},
|
||||
{
|
||||
// Press Ctrl+] to quit
|
||||
"label": "Serial Console",
|
||||
|
@ -145,7 +163,7 @@
|
|||
"command": "./fbt cli",
|
||||
"group": "none",
|
||||
"isBackground": true,
|
||||
"options": {
|
||||
"options": {
|
||||
"env": {
|
||||
"FBT_NO_SYNC": "0"
|
||||
}
|
||||
|
@ -162,4 +180,4 @@
|
|||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
17
SConstruct
17
SConstruct
|
@ -148,9 +148,12 @@ fap_dist = [
|
|||
for app_artifact in firmware_env["FW_EXTAPPS"].applications.values()
|
||||
),
|
||||
),
|
||||
distenv.Install(
|
||||
f"#/dist/{dist_dir}/apps",
|
||||
"#/assets/resources/apps",
|
||||
*(
|
||||
distenv.Install(
|
||||
f"#/dist/{dist_dir}/apps/{app_artifact.app.fap_category}",
|
||||
app_artifact.compact[0],
|
||||
)
|
||||
for app_artifact in firmware_env["FW_EXTAPPS"].applications.values()
|
||||
),
|
||||
]
|
||||
Depends(
|
||||
|
@ -165,6 +168,14 @@ Alias("fap_dist", fap_dist)
|
|||
|
||||
distenv.Depends(firmware_env["FW_RESOURCES"], firmware_env["FW_EXTAPPS"].resources_dist)
|
||||
|
||||
# Copy all faps to device
|
||||
|
||||
fap_deploy = distenv.PhonyTarget(
|
||||
"fap_deploy",
|
||||
"${PYTHON3} ${ROOT_DIR}/scripts/storage.py send ${SOURCE} /ext/apps",
|
||||
source=Dir("#/assets/resources/apps"),
|
||||
)
|
||||
|
||||
|
||||
# Target for bundling core2 package for qFlipper
|
||||
copro_dist = distenv.CoproBuilder(
|
||||
|
|
|
@ -31,7 +31,8 @@ void AccessorApp::run(void) {
|
|||
onewire_host_stop(onewire_host);
|
||||
}
|
||||
|
||||
AccessorApp::AccessorApp() {
|
||||
AccessorApp::AccessorApp()
|
||||
: text_store{0} {
|
||||
notification = static_cast<NotificationApp*>(furi_record_open(RECORD_NOTIFICATION));
|
||||
onewire_host = onewire_host_alloc();
|
||||
furi_hal_power_enable_otg();
|
||||
|
|
|
@ -171,9 +171,6 @@ bool WIEGAND::DoWiegandConversion() {
|
|||
return true;
|
||||
} else {
|
||||
_lastWiegand = sysTick;
|
||||
_bitCount = 0;
|
||||
_cardTemp = 0;
|
||||
_cardTempHigh = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,8 +2,11 @@
|
|||
|
||||
#include <gui/canvas.h>
|
||||
#include <gui/elements.h>
|
||||
|
||||
#include <lib/toolbox/float_tools.h>
|
||||
#include <m-array.h>
|
||||
#include <furi.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdint.h>
|
||||
|
||||
struct BtTestParam {
|
||||
|
@ -98,16 +101,16 @@ static void bt_test_draw_callback(Canvas* canvas, void* _model) {
|
|||
elements_scrollbar(canvas, model->position, BtTestParamArray_size(model->params));
|
||||
canvas_draw_str(canvas, 6, 60, model->message);
|
||||
if(model->state == BtTestStateStarted) {
|
||||
if(model->rssi != 0.0f) {
|
||||
if(!float_is_equal(model->rssi, 0.0f)) {
|
||||
snprintf(info_str, sizeof(info_str), "RSSI:%3.1f dB", (double)model->rssi);
|
||||
canvas_draw_str_aligned(canvas, 124, 60, AlignRight, AlignBottom, info_str);
|
||||
}
|
||||
} else if(model->state == BtTestStateStopped) {
|
||||
if(model->packets_num_rx) {
|
||||
snprintf(info_str, sizeof(info_str), "%ld pack rcv", model->packets_num_rx);
|
||||
snprintf(info_str, sizeof(info_str), "%" PRIu32 " pack rcv", model->packets_num_rx);
|
||||
canvas_draw_str_aligned(canvas, 124, 60, AlignRight, AlignBottom, info_str);
|
||||
} else if(model->packets_num_tx) {
|
||||
snprintf(info_str, sizeof(info_str), "%ld pack sent", model->packets_num_tx);
|
||||
snprintf(info_str, sizeof(info_str), "%" PRIu32 " pack sent", model->packets_num_tx);
|
||||
canvas_draw_str_aligned(canvas, 124, 60, AlignRight, AlignBottom, info_str);
|
||||
}
|
||||
}
|
||||
|
@ -153,7 +156,7 @@ static bool bt_test_input_callback(InputEvent* event, void* context) {
|
|||
}
|
||||
|
||||
void bt_test_process_up(BtTest* bt_test) {
|
||||
with_view_model(
|
||||
with_view_model( // -V658
|
||||
bt_test->view,
|
||||
BtTestModel * model,
|
||||
{
|
||||
|
|
|
@ -48,7 +48,7 @@ FileBrowserApp* file_browser_app_alloc(char* arg) {
|
|||
|
||||
app->file_path = furi_string_alloc();
|
||||
app->file_browser = file_browser_alloc(app->file_path);
|
||||
file_browser_configure(app->file_browser, "*", NULL, true, &I_badusb_10px, true);
|
||||
file_browser_configure(app->file_browser, "*", NULL, true, false, &I_badusb_10px, true);
|
||||
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher, FileBrowserAppViewStart, widget_get_view(app->widget));
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
#include <lib/subghz/subghz_keystore.h>
|
||||
#include <lib/subghz/subghz_file_encoder_worker.h>
|
||||
#include <lib/subghz/protocols/protocol_items.h>
|
||||
#include <lib/subghz/helpers/subghz_config_preset_custom.h>
|
||||
#include <flipper_format/flipper_format_i.h>
|
||||
|
||||
#define TAG "SubGhz TEST"
|
||||
|
@ -204,132 +203,6 @@ static bool subghz_encoder_test(const char* path) {
|
|||
return subghz_test_decoder_count ? true : false;
|
||||
}
|
||||
|
||||
static bool subghz_custom_preset_test(void) {
|
||||
static const uint8_t preset_data[][2] = {
|
||||
{CC1101_MDMCFG0, 0},
|
||||
{CC1101_MDMCFG1, 0},
|
||||
{CC1101_MDMCFG2, 0},
|
||||
{CC1101_MDMCFG3, 0},
|
||||
{CC1101_MDMCFG4, 0},
|
||||
};
|
||||
|
||||
static uint8_t test_data[sizeof(preset_data)] = {0};
|
||||
memcpy(test_data, preset_data, sizeof(preset_data));
|
||||
|
||||
uint8_t* test_data_ptr = &test_data[0];
|
||||
|
||||
{ // CHEKING BANDWIDTH SET
|
||||
for(uint32_t i = 0; i < CH_BANDWIDTH_NUM; ++i) {
|
||||
uint8_t bw_value = subghz_preset_custom_bandwidth_values[i];
|
||||
|
||||
bool result =
|
||||
subghz_preset_custom_set_bandwidth(test_data_ptr, sizeof(test_data), bw_value);
|
||||
if(!result) {
|
||||
FURI_LOG_E(TAG, "Failed to set BW value: %hhu", bw_value);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t get_bw_value =
|
||||
subghz_preset_custom_get_bandwidth(test_data_ptr, sizeof(test_data));
|
||||
if(get_bw_value != bw_value) {
|
||||
FURI_LOG_E(
|
||||
TAG,
|
||||
"BW value from preset: %hhu is not equal expected value: %hhu",
|
||||
get_bw_value,
|
||||
bw_value);
|
||||
return false;
|
||||
}
|
||||
|
||||
FURI_LOG_T(TAG, "Bandwidth check OK: %hhu", bw_value);
|
||||
}
|
||||
}
|
||||
|
||||
{ // CHEKING MACHESTER SET
|
||||
bool result =
|
||||
subghz_preset_custom_set_machester_enable(test_data_ptr, sizeof(test_data), false);
|
||||
if(!result) {
|
||||
FURI_LOG_E(TAG, "Failed to set manchester enable flag");
|
||||
return false;
|
||||
}
|
||||
bool flag = subghz_preset_custom_get_machester_enable(test_data_ptr, sizeof(test_data));
|
||||
if(flag != false) {
|
||||
FURI_LOG_E(TAG, "Manchester disable flag setup failed!");
|
||||
return false;
|
||||
}
|
||||
|
||||
subghz_preset_custom_set_machester_enable(test_data_ptr, sizeof(test_data), true);
|
||||
flag = subghz_preset_custom_get_machester_enable(test_data_ptr, sizeof(test_data));
|
||||
if(flag != true) {
|
||||
FURI_LOG_E(TAG, "Manchester enable flag setup failed!");
|
||||
return false;
|
||||
}
|
||||
|
||||
FURI_LOG_T(TAG, "Manchester flag check OK");
|
||||
}
|
||||
{ // CHEKING DATARATE SET
|
||||
const float datarateRoughMax = 1600000.0f; // bauds
|
||||
const float datarateRoughStep = 5000.0f;
|
||||
|
||||
const float datarateFineMax = 30000.0f;
|
||||
const float datarateFineStep = 50.0f;
|
||||
|
||||
bool result = false;
|
||||
char datarate_set_str[16] = {0};
|
||||
char datarate_get_str[16] = {0};
|
||||
|
||||
float datarate_set = datarateRoughMax;
|
||||
float datarate_get = -1.0f;
|
||||
while(datarate_set > 0) {
|
||||
subghz_preset_custom_printf_datarate(
|
||||
datarate_set, datarate_set_str, sizeof(datarate_set_str));
|
||||
|
||||
result =
|
||||
subghz_preset_custom_set_datarate(test_data_ptr, sizeof(test_data), datarate_set);
|
||||
if(!result) {
|
||||
FURI_LOG_E(TAG, "Failed to set datarate: %s!", datarate_set_str);
|
||||
return false;
|
||||
}
|
||||
|
||||
datarate_get = subghz_preset_custom_get_datarate(test_data_ptr, sizeof(test_data));
|
||||
subghz_preset_custom_printf_datarate(
|
||||
datarate_get, datarate_get_str, sizeof(datarate_get_str));
|
||||
|
||||
if(datarate_get < 0) {
|
||||
FURI_LOG_E(TAG, "Failed to get datarate!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(datarate_set > datarateFineMax) {
|
||||
result = fabsf(datarate_get - datarate_set) <= datarateRoughStep;
|
||||
datarate_set -= datarateRoughStep;
|
||||
} else {
|
||||
result = fabsf(datarate_get - datarate_set) <= datarateFineStep;
|
||||
datarate_set -= datarateFineStep;
|
||||
}
|
||||
|
||||
if(result) {
|
||||
FURI_LOG_T(
|
||||
TAG,
|
||||
"Datarate check OK: Set: %s - Get: %s",
|
||||
datarate_set_str,
|
||||
datarate_get_str);
|
||||
} else {
|
||||
FURI_LOG_E(
|
||||
TAG,
|
||||
"Datarate check failed!: %s is way to diff %s! DRATE_E: %hhu DRATE_M: %hhu",
|
||||
datarate_set_str,
|
||||
datarate_get_str,
|
||||
test_data[4 * 2 + 1] & 0b00001111,
|
||||
test_data[3 * 2 + 1]);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FURI_LOG_I(TAG, "Sub GHz custom preset test: OK");
|
||||
return true;
|
||||
}
|
||||
|
||||
MU_TEST(subghz_keystore_test) {
|
||||
mu_assert(
|
||||
subghz_environment_load_keystore(environment_handler, KEYSTORE_DIR_NAME),
|
||||
|
@ -874,10 +747,6 @@ MU_TEST(subghz_random_test) {
|
|||
mu_assert(subghz_decode_random_test(TEST_RANDOM_DIR_NAME), "Random test error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST(subghz_preset_test) {
|
||||
mu_assert(subghz_custom_preset_test(), "Custom preset logic error\r\n");
|
||||
}
|
||||
|
||||
MU_TEST_SUITE(subghz) {
|
||||
subghz_test_init();
|
||||
MU_RUN_TEST(subghz_keystore_test);
|
||||
|
@ -948,16 +817,7 @@ MU_TEST_SUITE(subghz) {
|
|||
subghz_test_deinit();
|
||||
}
|
||||
|
||||
MU_TEST_SUITE(subghz_app) {
|
||||
MU_RUN_TEST(subghz_preset_test);
|
||||
}
|
||||
|
||||
int run_minunit_test_subghz() {
|
||||
MU_RUN_SUITE(subghz);
|
||||
return MU_EXIT_CODE;
|
||||
}
|
||||
|
||||
int run_minunit_test_subghz_app() {
|
||||
MU_RUN_SUITE(subghz_app);
|
||||
return MU_EXIT_CODE;
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
#include <notification/notification_messages.h>
|
||||
#include <cli/cli.h>
|
||||
#include <loader/loader.h>
|
||||
#include <lib/toolbox/args.h>
|
||||
|
||||
#define TAG "UnitTests"
|
||||
|
||||
|
@ -20,7 +19,6 @@ int run_minunit_test_flipper_format_string();
|
|||
int run_minunit_test_stream();
|
||||
int run_minunit_test_storage();
|
||||
int run_minunit_test_subghz();
|
||||
int run_minunit_test_subghz_app();
|
||||
int run_minunit_test_dirwalk();
|
||||
int run_minunit_test_power();
|
||||
int run_minunit_test_protocol_dict();
|
||||
|
@ -49,7 +47,6 @@ const UnitTest unit_tests[] = {
|
|||
{.name = "flipper_format_string", .entry = run_minunit_test_flipper_format_string},
|
||||
{.name = "rpc", .entry = run_minunit_test_rpc},
|
||||
{.name = "subghz", .entry = run_minunit_test_subghz},
|
||||
{.name = "subghz_app", .entry = run_minunit_test_subghz_app},
|
||||
{.name = "infrared", .entry = run_minunit_test_infrared},
|
||||
{.name = "nfc", .entry = run_minunit_test_nfc},
|
||||
{.name = "power", .entry = run_minunit_test_power},
|
||||
|
@ -76,72 +73,6 @@ void minunit_print_fail(const char* str) {
|
|||
printf(FURI_LOG_CLR_E "%s\r\n" FURI_LOG_CLR_RESET, str);
|
||||
}
|
||||
|
||||
void unit_tests_cli_logs_puts(const char* str) {
|
||||
printf(str);
|
||||
}
|
||||
|
||||
// by default there is no output from unit tests
|
||||
// you have to enable them with this function
|
||||
void unit_tests_cli_enable_logs(FuriLogLevel logLevel) {
|
||||
furi_log_init();
|
||||
furi_log_set_level(logLevel);
|
||||
furi_log_set_puts(unit_tests_cli_logs_puts);
|
||||
}
|
||||
|
||||
void unit_tests_cli_print_help() {
|
||||
printf(
|
||||
"Usage:\r\n"
|
||||
" unit_tests [log level] [test_suit_name]\r\n"
|
||||
" Arguments:\r\n"
|
||||
" [log level]: optional, enables printing output from FURI_LOG_* macro in unit_tests\r\n"
|
||||
" [test_suit_name]: a specific test suit to run. If not specified runs all tests\r\n"
|
||||
" Warning: supports only 1 test suit to launch\r\n"
|
||||
" Example:\r\n"
|
||||
" unit_tests - run ALL tests wihtout log printing\r\n"
|
||||
" unit_tests bt - run bt tests wihtout log printing\r\n"
|
||||
" unit_tests log debug subghz - run subghz tests with logs at debug level abd above\r\n\r\n"
|
||||
" unit_tests help [?]\r\n"
|
||||
" prints this help\r\n");
|
||||
}
|
||||
|
||||
bool unit_tests_cli_parse_log_level(FuriString* args) {
|
||||
bool result = true;
|
||||
FuriString* level = furi_string_alloc();
|
||||
if(args_read_string_and_trim(args, level)) {
|
||||
if(furi_string_cmpi_str(level, "default") == 0) {
|
||||
unit_tests_cli_enable_logs(FuriLogLevelDefault);
|
||||
} else if(furi_string_cmpi_str(level, "none") == 0) {
|
||||
unit_tests_cli_enable_logs(FuriLogLevelNone);
|
||||
} else if(furi_string_cmpi_str(level, "error") == 0) {
|
||||
unit_tests_cli_enable_logs(FuriLogLevelError);
|
||||
} else if(furi_string_cmpi_str(level, "warn") == 0) {
|
||||
unit_tests_cli_enable_logs(FuriLogLevelWarn);
|
||||
} else if(furi_string_cmpi_str(level, "info") == 0) {
|
||||
unit_tests_cli_enable_logs(FuriLogLevelInfo);
|
||||
} else if(furi_string_cmpi_str(level, "debug") == 0) {
|
||||
unit_tests_cli_enable_logs(FuriLogLevelDebug);
|
||||
} else if(furi_string_cmpi_str(level, "trace") == 0) {
|
||||
unit_tests_cli_enable_logs(FuriLogLevelTrace);
|
||||
} else {
|
||||
printf("Error: Invalid log level: %s\r\n", furi_string_get_cstr(level));
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
furi_string_free(level);
|
||||
return result;
|
||||
}
|
||||
|
||||
FuriString* unit_tests_cli_parse_test_suit(FuriString* args) {
|
||||
FuriString* test_suit = furi_string_alloc();
|
||||
|
||||
if(!args_read_string_and_trim(args, test_suit)) {
|
||||
furi_string_free(test_suit);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return test_suit;
|
||||
}
|
||||
|
||||
void unit_tests_cli(Cli* cli, FuriString* args, void* context) {
|
||||
UNUSED(cli);
|
||||
UNUSED(args);
|
||||
|
@ -151,34 +82,6 @@ void unit_tests_cli(Cli* cli, FuriString* args, void* context) {
|
|||
minunit_fail = 0;
|
||||
minunit_status = 0;
|
||||
|
||||
if(furi_string_cmp_str(args, "help") == 0 || furi_string_cmp_str(args, "?") == 0) {
|
||||
unit_tests_cli_print_help();
|
||||
return;
|
||||
}
|
||||
|
||||
FuriString* test_suit_to_run = NULL;
|
||||
|
||||
if(furi_string_size(args)) {
|
||||
FuriString* arg = furi_string_alloc();
|
||||
if(args_read_string_and_trim(args, arg)) {
|
||||
if(furi_string_cmp_str(arg, "log") == 0) {
|
||||
// read next argument - log level, if fail - show help and return
|
||||
if(!unit_tests_cli_parse_log_level(args)) {
|
||||
unit_tests_cli_print_help();
|
||||
furi_string_free(arg);
|
||||
return;
|
||||
}
|
||||
|
||||
// next argument might be test suit
|
||||
test_suit_to_run = unit_tests_cli_parse_test_suit(args);
|
||||
} else {
|
||||
// if first argument wasn't log - it was exact test suit to run
|
||||
test_suit_to_run = unit_tests_cli_parse_test_suit(arg);
|
||||
}
|
||||
}
|
||||
furi_string_free(arg);
|
||||
}
|
||||
|
||||
Loader* loader = furi_record_open(RECORD_LOADER);
|
||||
NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION);
|
||||
|
||||
|
@ -197,8 +100,8 @@ void unit_tests_cli(Cli* cli, FuriString* args, void* context) {
|
|||
break;
|
||||
}
|
||||
|
||||
if(test_suit_to_run) {
|
||||
if(furi_string_cmp_str(test_suit_to_run, unit_tests[i].name) == 0) {
|
||||
if(furi_string_size(args)) {
|
||||
if(furi_string_cmp_str(args, unit_tests[i].name) == 0) {
|
||||
unit_tests[i].entry();
|
||||
} else {
|
||||
printf("Skipping %s\r\n", unit_tests[i].name);
|
||||
|
@ -231,10 +134,6 @@ void unit_tests_cli(Cli* cli, FuriString* args, void* context) {
|
|||
}
|
||||
}
|
||||
|
||||
if(test_suit_to_run) {
|
||||
furi_string_free(test_suit_to_run);
|
||||
}
|
||||
|
||||
furi_record_close(RECORD_NOTIFICATION);
|
||||
furi_record_close(RECORD_LOADER);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
App(
|
||||
appid="sample_apps",
|
||||
name="Sample apps bundle",
|
||||
appid="example_apps",
|
||||
name="Example apps bundle",
|
||||
apptype=FlipperAppType.METAPACKAGE,
|
||||
)
|
||||
|
|
|
@ -75,8 +75,8 @@ static const DuckyKey ducky_keys[] = {
|
|||
{"BREAK", HID_KEYBOARD_PAUSE},
|
||||
{"PAUSE", HID_KEYBOARD_PAUSE},
|
||||
{"CAPSLOCK", HID_KEYBOARD_CAPS_LOCK},
|
||||
{"DELETE", HID_KEYBOARD_DELETE},
|
||||
{"BACKSPACE", HID_KEYPAD_BACKSPACE},
|
||||
{"DELETE", HID_KEYBOARD_DELETE_FORWARD},
|
||||
{"BACKSPACE", HID_KEYBOARD_DELETE},
|
||||
{"END", HID_KEYBOARD_END},
|
||||
{"ESC", HID_KEYBOARD_ESCAPE},
|
||||
{"ESCAPE", HID_KEYBOARD_ESCAPE},
|
||||
|
|
|
@ -39,11 +39,12 @@ static void clock_render_callback(Canvas* const canvas, void* ctx) {
|
|||
} else {
|
||||
bool pm = curr_dt.hour > 12;
|
||||
bool pm12 = curr_dt.hour >= 12;
|
||||
bool am12 = curr_dt.hour == 0;
|
||||
snprintf(
|
||||
time_string,
|
||||
TIME_LEN,
|
||||
CLOCK_TIME_FORMAT,
|
||||
pm ? curr_dt.hour - 12 : curr_dt.hour,
|
||||
pm ? curr_dt.hour - 12 : (am12 ? 12 : curr_dt.hour),
|
||||
curr_dt.minute,
|
||||
curr_dt.second);
|
||||
|
||||
|
@ -237,4 +238,4 @@ int32_t clock_app(void* p) {
|
|||
free(plugin_state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,9 +14,12 @@ static const char* uart_ch[] = {"13,14", "15,16"};
|
|||
static const char* flow_pins[] = {"None", "2,3", "6,7", "16,15"};
|
||||
static const char* baudrate_mode[] = {"Host"};
|
||||
static const uint32_t baudrate_list[] = {
|
||||
1200,
|
||||
2400,
|
||||
4800,
|
||||
9600,
|
||||
19200,
|
||||
28800,
|
||||
38400,
|
||||
57600,
|
||||
115200,
|
||||
|
|
|
@ -295,6 +295,6 @@ void infrared_signal_transmit(InfraredSignal* signal) {
|
|||
raw_signal->duty_cycle);
|
||||
} else {
|
||||
InfraredMessage* message = &signal->payload.message;
|
||||
infrared_send(message, 2);
|
||||
infrared_send(message, 1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
enum SubmenuIndex {
|
||||
SubmenuIndexUniversalRemotes,
|
||||
SubmenuIndexLearnNewRemote,
|
||||
SubmenuIndexLearnNewRemoteRaw,
|
||||
SubmenuIndexSavedRemotes,
|
||||
SubmenuIndexDebug
|
||||
};
|
||||
|
@ -37,6 +38,12 @@ void infrared_scene_start_on_enter(void* context) {
|
|||
infrared);
|
||||
|
||||
if(infrared->app_state.is_debug_enabled) {
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Learn New Remote RAW",
|
||||
SubmenuIndexLearnNewRemoteRaw,
|
||||
infrared_scene_start_submenu_callback,
|
||||
infrared);
|
||||
submenu_add_item(
|
||||
submenu, "Debug", SubmenuIndexDebug, infrared_scene_start_submenu_callback, infrared);
|
||||
}
|
||||
|
@ -61,7 +68,15 @@ bool infrared_scene_start_on_event(void* context, SceneManagerEvent event) {
|
|||
if(submenu_index == SubmenuIndexUniversalRemotes) {
|
||||
scene_manager_next_scene(scene_manager, InfraredSceneUniversal);
|
||||
consumed = true;
|
||||
} else if(submenu_index == SubmenuIndexLearnNewRemote) {
|
||||
} else if(
|
||||
submenu_index == SubmenuIndexLearnNewRemote ||
|
||||
submenu_index == SubmenuIndexLearnNewRemoteRaw) {
|
||||
|
||||
// enable automatic signal decoding if "Learn New Remote"
|
||||
// disable automatic signal decoding if "Learn New Remote (RAW)"
|
||||
infrared_worker_rx_enable_signal_decoding(
|
||||
infrared->worker, submenu_index == SubmenuIndexLearnNewRemote);
|
||||
|
||||
infrared->app_state.is_learning_new_remote = true;
|
||||
scene_manager_next_scene(scene_manager, InfraredSceneLearn);
|
||||
consumed = true;
|
||||
|
|
|
@ -50,7 +50,6 @@ typedef enum {
|
|||
SubGhzCustomEventSceneAnalyzerLock,
|
||||
SubGhzCustomEventSceneAnalyzerUnlock,
|
||||
SubGhzCustomEventSceneSettingLock,
|
||||
SubGhzCustomEventSceneSettingError,
|
||||
|
||||
SubGhzCustomEventSceneExit,
|
||||
SubGhzCustomEventSceneStay,
|
||||
|
|
|
@ -45,35 +45,6 @@ const float raw_theshold_rssi_value[RAW_THRESHOLD_RSSI_COUNT] = {
|
|||
-40.0f,
|
||||
};
|
||||
|
||||
#define BANDWIDTH_COUNT 16
|
||||
const char* const bandwidth_labels[BANDWIDTH_COUNT] = {
|
||||
"58 kHz",
|
||||
"68 kHz",
|
||||
"81 kHz",
|
||||
"102 kHz",
|
||||
"116 kHz",
|
||||
"135 kHz",
|
||||
"162 kHz",
|
||||
"203 kHz",
|
||||
"232 kHz",
|
||||
"270 kHz",
|
||||
"325 kHz",
|
||||
"406 kHz",
|
||||
"464 kHz",
|
||||
"541 kHz",
|
||||
"650 kHz",
|
||||
"812 kHz",
|
||||
};
|
||||
|
||||
// Bandwidths values are ordered from F (58kHz) to 0 (812kHz)
|
||||
#define BANDWIDTH_INDEX(value) ((uint8_t)15 - ((uint8_t)(value >> 4) & 0x0F))
|
||||
|
||||
#define MANCHESTER_FLAG_COUNT 2
|
||||
const char* const manchester_flag_text[MANCHESTER_FLAG_COUNT] = {
|
||||
"OFF",
|
||||
"ON",
|
||||
};
|
||||
|
||||
#define HOPPING_COUNT 2
|
||||
const char* const hopping_text[HOPPING_COUNT] = {
|
||||
"OFF",
|
||||
|
@ -128,18 +99,6 @@ const uint32_t speaker_value[SPEAKER_COUNT] = {
|
|||
SubGhzSpeakerStateEnable,
|
||||
};
|
||||
|
||||
// Allow advanced edit only on specific preset
|
||||
bool subghz_scene_receiver_config_can_edit_current_preset(SubGhz* subghz) {
|
||||
SubGhzRadioPreset* preset = subghz->txrx->preset;
|
||||
|
||||
bool preset_name_allow_edit =
|
||||
!strcmp(furi_string_get_cstr(preset->name), ADVANCED_AM_PRESET_NAME) ||
|
||||
!strcmp(furi_string_get_cstr(preset->name), "CUSTOM");
|
||||
|
||||
return preset && preset_name_allow_edit &&
|
||||
subghz_preset_custom_is_ook_modulation(preset->data, preset->data_size);
|
||||
}
|
||||
|
||||
uint8_t subghz_scene_receiver_config_next_frequency(const uint32_t value, void* context) {
|
||||
furi_assert(context);
|
||||
SubGhz* subghz = context;
|
||||
|
@ -170,52 +129,6 @@ uint8_t subghz_scene_receiver_config_next_preset(const char* preset_name, void*
|
|||
return index;
|
||||
}
|
||||
|
||||
// Advanced settings of preset may change if preset was changed.
|
||||
// In that case - update values
|
||||
static void subghz_scene_receiver_config_update_advanced(SubGhz* subghz) {
|
||||
uint8_t value_index;
|
||||
|
||||
if(subghz->variable_item_bandwidth) {
|
||||
value_index = BANDWIDTH_INDEX(subghz->txrx->raw_bandwidth);
|
||||
variable_item_set_current_value_index(subghz->variable_item_bandwidth, value_index);
|
||||
variable_item_set_current_value_text(
|
||||
subghz->variable_item_bandwidth, bandwidth_labels[value_index]);
|
||||
}
|
||||
|
||||
if(subghz->variable_item_datarate) {
|
||||
variable_item_set_current_value_index(subghz->variable_item_datarate, 0);
|
||||
|
||||
char datarate_str[16] = {0};
|
||||
subghz_preset_custom_printf_datarate(
|
||||
subghz->txrx->raw_datarate, datarate_str, sizeof(datarate_str));
|
||||
variable_item_set_current_value_text(subghz->variable_item_datarate, datarate_str);
|
||||
}
|
||||
|
||||
if(subghz->variable_item_manchester) {
|
||||
value_index = subghz->txrx->raw_manchester_enabled ? 1 : 0;
|
||||
|
||||
variable_item_set_current_value_index(subghz->variable_item_manchester, value_index);
|
||||
variable_item_set_current_value_text(
|
||||
subghz->variable_item_manchester, manchester_flag_text[value_index]);
|
||||
}
|
||||
}
|
||||
|
||||
// Apply advanced configuration to advanced am preset
|
||||
static void subghz_scene_receiver_config_apply_advanced(SubGhz* subghz) {
|
||||
if(subghz_scene_receiver_config_can_edit_current_preset(subghz)) {
|
||||
SubGhzRadioPreset* preset = subghz->txrx->preset;
|
||||
|
||||
subghz_preset_custom_set_bandwidth(
|
||||
preset->data, preset->data_size, subghz->txrx->raw_bandwidth);
|
||||
|
||||
subghz_preset_custom_set_machester_enable(
|
||||
preset->data, preset->data_size, subghz->txrx->raw_manchester_enabled);
|
||||
|
||||
subghz_preset_custom_set_datarate(
|
||||
preset->data, preset->data_size, subghz->txrx->raw_datarate);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t subghz_scene_receiver_config_hopper_value_index(
|
||||
const uint32_t value,
|
||||
const uint32_t values[],
|
||||
|
@ -301,8 +214,6 @@ static void subghz_scene_receiver_config_set_preset(VariableItem* item) {
|
|||
subghz->txrx->preset->frequency,
|
||||
subghz_setting_get_preset_data(subghz->setting, index),
|
||||
subghz_setting_get_preset_data_size(subghz->setting, index));
|
||||
|
||||
subghz_scene_receiver_config_update_advanced(subghz);
|
||||
}
|
||||
|
||||
static void subghz_scene_receiver_config_set_rssi_threshold(VariableItem* item) {
|
||||
|
@ -396,107 +307,6 @@ static void subghz_scene_receiver_config_set_raw_threshold_rssi(VariableItem* it
|
|||
subghz->txrx->raw_threshold_rssi = raw_theshold_rssi_value[index];
|
||||
}
|
||||
|
||||
static void subghz_scene_receiver_config_set_raw_ook_bandwidth(VariableItem* item) {
|
||||
SubGhz* subghz = variable_item_get_context(item);
|
||||
if(subghz_scene_receiver_config_can_edit_current_preset(subghz)) {
|
||||
// update bandwidth value from selected index
|
||||
uint8_t index = variable_item_get_current_value_index(item);
|
||||
subghz->txrx->raw_bandwidth = subghz_preset_custom_bandwidth_values[index];
|
||||
|
||||
subghz_scene_receiver_config_update_advanced(subghz);
|
||||
} else {
|
||||
furi_string_set(
|
||||
subghz->error_str, "Read-only\nsetting!\nUse '" ADVANCED_AM_PRESET_NAME "'\npreset.");
|
||||
view_dispatcher_send_custom_event(
|
||||
subghz->view_dispatcher, SubGhzCustomEventSceneSettingError);
|
||||
}
|
||||
}
|
||||
|
||||
static void subghz_scene_receiver_config_set_manchester_flag(VariableItem* item) {
|
||||
SubGhz* subghz = variable_item_get_context(item);
|
||||
if(subghz_scene_receiver_config_can_edit_current_preset(subghz)) {
|
||||
// update enable flag from view
|
||||
uint8_t index = variable_item_get_current_value_index(item);
|
||||
subghz->txrx->raw_manchester_enabled = index == 0 ? false : true;
|
||||
|
||||
subghz_scene_receiver_config_update_advanced(subghz);
|
||||
} else {
|
||||
furi_string_set(
|
||||
subghz->error_str, "Read-only\nsetting!\nUse '" ADVANCED_AM_PRESET_NAME "'\npreset.");
|
||||
view_dispatcher_send_custom_event(
|
||||
subghz->view_dispatcher, SubGhzCustomEventSceneSettingError);
|
||||
}
|
||||
}
|
||||
|
||||
static void subghz_scene_receiver_config_datarate_input_callback(void* context) {
|
||||
furi_assert(context);
|
||||
SubGhz* subghz = context;
|
||||
|
||||
float value = atoff(subghz->datarate_input_str);
|
||||
if(value != 0 && value > 0) {
|
||||
subghz->txrx->raw_datarate = value;
|
||||
subghz_scene_receiver_config_update_advanced(subghz);
|
||||
}
|
||||
|
||||
// show list view
|
||||
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdVariableItemList);
|
||||
}
|
||||
|
||||
static bool subghz_scene_receiver_config_datarate_input_validate(
|
||||
const char* text,
|
||||
FuriString* error,
|
||||
void* context) {
|
||||
UNUSED(context);
|
||||
|
||||
float value = atoff(text);
|
||||
if(value == 0) {
|
||||
furi_string_printf(error, "Cannot parse\r\nvalue");
|
||||
} else if(value < 0) {
|
||||
furi_string_printf(error, "Value\r\nshould be\r\ngreater\r\nthan 0");
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void subghz_scene_receiver_config_show_datarate_input(SubGhz* subghz) {
|
||||
TextInput* text_input = subghz->text_input;
|
||||
|
||||
snprintf(
|
||||
subghz->datarate_input_str,
|
||||
sizeof(subghz->datarate_input_str),
|
||||
"%.2f",
|
||||
(double)subghz->txrx->raw_datarate);
|
||||
|
||||
text_input_set_header_text(text_input, "Datarate bauds (not kBauds)");
|
||||
text_input_set_result_callback(
|
||||
text_input,
|
||||
subghz_scene_receiver_config_datarate_input_callback,
|
||||
subghz,
|
||||
subghz->datarate_input_str,
|
||||
sizeof(subghz->datarate_input_str),
|
||||
false);
|
||||
|
||||
text_input_set_validator(
|
||||
text_input, subghz_scene_receiver_config_datarate_input_validate, NULL);
|
||||
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdTextInput);
|
||||
}
|
||||
|
||||
static void subghz_scene_receiver_config_set_datarate(VariableItem* item) {
|
||||
SubGhz* subghz = variable_item_get_context(item);
|
||||
if(subghz_scene_receiver_config_can_edit_current_preset(subghz)) {
|
||||
// reset value index in order to show '>' symbol always
|
||||
variable_item_set_current_value_index(item, 0);
|
||||
subghz_scene_receiver_config_show_datarate_input(subghz);
|
||||
} else {
|
||||
furi_string_set(
|
||||
subghz->error_str, "Read-only\nsetting!\nUse '" ADVANCED_AM_PRESET_NAME "'\npreset.");
|
||||
view_dispatcher_send_custom_event(
|
||||
subghz->view_dispatcher, SubGhzCustomEventSceneSettingError);
|
||||
}
|
||||
}
|
||||
|
||||
static void subghz_scene_receiver_config_var_list_enter_callback(void* context, uint32_t index) {
|
||||
furi_assert(context);
|
||||
SubGhz* subghz = context;
|
||||
|
@ -627,33 +437,6 @@ void subghz_scene_receiver_config_on_enter(void* context) {
|
|||
subghz->txrx->raw_threshold_rssi, raw_theshold_rssi_value, RAW_THRESHOLD_RSSI_COUNT);
|
||||
variable_item_set_current_value_index(item, value_index);
|
||||
variable_item_set_current_value_text(item, raw_theshold_rssi_text[value_index]);
|
||||
|
||||
// Advanced MODEM settings. RW only for ADVANCED_AM_PRESET_NAME
|
||||
// Bandwidth
|
||||
subghz->variable_item_bandwidth = variable_item_list_add(
|
||||
subghz->variable_item_list,
|
||||
"Bandwidth:",
|
||||
BANDWIDTH_COUNT,
|
||||
subghz_scene_receiver_config_set_raw_ook_bandwidth,
|
||||
subghz);
|
||||
|
||||
// Data rate (editable via OK click)
|
||||
subghz->variable_item_datarate = variable_item_list_add(
|
||||
subghz->variable_item_list,
|
||||
"Data rate:",
|
||||
2,
|
||||
subghz_scene_receiver_config_set_datarate,
|
||||
subghz);
|
||||
|
||||
// Manchester codec flag
|
||||
subghz->variable_item_manchester = variable_item_list_add(
|
||||
subghz->variable_item_list,
|
||||
"Manch. Enc.:",
|
||||
MANCHESTER_FLAG_COUNT,
|
||||
subghz_scene_receiver_config_set_manchester_flag,
|
||||
subghz);
|
||||
|
||||
subghz_scene_receiver_config_update_advanced(subghz);
|
||||
}
|
||||
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdVariableItemList);
|
||||
}
|
||||
|
@ -667,11 +450,6 @@ bool subghz_scene_receiver_config_on_event(void* context, SceneManagerEvent even
|
|||
subghz->lock = SubGhzLockOn;
|
||||
scene_manager_previous_scene(subghz->scene_manager);
|
||||
consumed = true;
|
||||
} else if(event.event == SubGhzCustomEventSceneSettingError) {
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowErrorSub);
|
||||
scene_manager_set_scene_state(
|
||||
subghz->scene_manager, SubGhzSceneShowErrorSub, event.event);
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
return consumed;
|
||||
|
@ -679,16 +457,6 @@ bool subghz_scene_receiver_config_on_event(void* context, SceneManagerEvent even
|
|||
|
||||
void subghz_scene_receiver_config_on_exit(void* context) {
|
||||
SubGhz* subghz = context;
|
||||
|
||||
// reset UI variable list items (next scene may be not RAW config)
|
||||
subghz->variable_item_bandwidth = NULL;
|
||||
subghz->variable_item_datarate = NULL;
|
||||
subghz->variable_item_manchester = NULL;
|
||||
text_input_set_validator(subghz->text_input, NULL, NULL);
|
||||
|
||||
// apply advanced preset variables (if applicable)
|
||||
subghz_scene_receiver_config_apply_advanced(subghz);
|
||||
|
||||
variable_item_list_set_selected_item(subghz->variable_item_list, 0);
|
||||
variable_item_list_reset(subghz->variable_item_list);
|
||||
subghz_last_settings_save(subghz->last_settings);
|
||||
|
|
|
@ -26,16 +26,8 @@ bool subghz_scene_show_error_sub_on_event(void* context, SceneManagerEvent event
|
|||
SubGhz* subghz = context;
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == SubGhzCustomEventSceneShowErrorSub) {
|
||||
if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneShowErrorSub) ==
|
||||
SubGhzCustomEventSceneSettingError) {
|
||||
scene_manager_set_scene_state(
|
||||
subghz->scene_manager, SubGhzSceneReadRAW, SubGhzCustomEventManagerSet);
|
||||
scene_manager_search_and_switch_to_previous_scene(
|
||||
subghz->scene_manager, SubGhzSceneReceiverConfig);
|
||||
} else {
|
||||
scene_manager_search_and_switch_to_previous_scene(
|
||||
subghz->scene_manager, SubGhzSceneStart);
|
||||
}
|
||||
scene_manager_search_and_switch_to_previous_scene(
|
||||
subghz->scene_manager, SubGhzSceneStart);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,25 +12,6 @@ enum SubmenuIndex {
|
|||
SubmenuIndexReadRAW,
|
||||
};
|
||||
|
||||
void subghz_scene_start_remove_advanced_preset(SubGhz* subghz) {
|
||||
// delete operation is harmless
|
||||
subghz_setting_delete_custom_preset(subghz->setting, ADVANCED_AM_PRESET_NAME);
|
||||
}
|
||||
|
||||
void subghz_scene_start_load_advanced_preset(SubGhz* subghz) {
|
||||
for(uint8_t i = 0; i < subghz_setting_get_preset_count(subghz->setting); i++) {
|
||||
if(!strcmp(subghz_setting_get_preset_name(subghz->setting, i), ADVANCED_AM_PRESET_NAME)) {
|
||||
return; // already exists
|
||||
}
|
||||
}
|
||||
|
||||
// Load custom advanced AM preset with configurable CFGMDM settings
|
||||
FlipperFormat* advanced_am_preset = subghz_preset_custom_advanced_am_preset_alloc();
|
||||
subghz_setting_load_custom_preset(
|
||||
subghz->setting, ADVANCED_AM_PRESET_NAME, advanced_am_preset);
|
||||
flipper_format_free(advanced_am_preset);
|
||||
}
|
||||
|
||||
void subghz_scene_start_submenu_callback(void* context, uint32_t index) {
|
||||
SubGhz* subghz = context;
|
||||
view_dispatcher_send_custom_event(subghz->view_dispatcher, index);
|
||||
|
@ -92,14 +73,12 @@ bool subghz_scene_start_on_event(void* context, SceneManagerEvent event) {
|
|||
return true;
|
||||
} else if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == SubmenuIndexReadRAW) {
|
||||
subghz_scene_start_load_advanced_preset(subghz);
|
||||
scene_manager_set_scene_state(
|
||||
subghz->scene_manager, SubGhzSceneStart, SubmenuIndexReadRAW);
|
||||
subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE;
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReadRAW);
|
||||
return true;
|
||||
} else if(event.event == SubmenuIndexRead) {
|
||||
subghz_scene_start_remove_advanced_preset(subghz);
|
||||
scene_manager_set_scene_state(
|
||||
subghz->scene_manager, SubGhzSceneStart, SubmenuIndexRead);
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReceiver);
|
||||
|
|
|
@ -30,12 +30,6 @@ void subghz_preset_init(
|
|||
subghz->txrx->preset->frequency = frequency;
|
||||
subghz->txrx->preset->data = preset_data;
|
||||
subghz->txrx->preset->data_size = preset_data_size;
|
||||
|
||||
subghz->txrx->raw_bandwidth =
|
||||
subghz_preset_custom_get_bandwidth(preset_data, preset_data_size);
|
||||
subghz->txrx->raw_manchester_enabled =
|
||||
subghz_preset_custom_get_machester_enable(preset_data, preset_data_size);
|
||||
subghz->txrx->raw_datarate = subghz_preset_custom_get_datarate(preset_data, preset_data_size);
|
||||
}
|
||||
|
||||
bool subghz_set_preset(SubGhz* subghz, const char* preset) {
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
#include "helpers/subghz_types.h"
|
||||
#include "helpers/subghz_error_type.h"
|
||||
#include <lib/subghz/types.h>
|
||||
#include <lib/subghz/helpers/subghz_config_preset_custom.h>
|
||||
#include "subghz.h"
|
||||
#include "views/receiver.h"
|
||||
#include "views/transmitter.h"
|
||||
|
@ -79,13 +78,6 @@ struct SubGhzTxRx {
|
|||
|
||||
float raw_threshold_rssi;
|
||||
uint8_t raw_threshold_rssi_low_count;
|
||||
|
||||
// one of the 16 possible bandwidth values
|
||||
uint8_t raw_bandwidth;
|
||||
// datarate in bauds
|
||||
float raw_datarate;
|
||||
// flag if manchester encoding/decoding enabled
|
||||
bool raw_manchester_enabled;
|
||||
};
|
||||
|
||||
typedef struct SubGhzTxRx SubGhzTxRx;
|
||||
|
@ -114,13 +106,6 @@ struct SubGhz {
|
|||
SubGhzViewTransmitter* subghz_transmitter;
|
||||
VariableItemList* variable_item_list;
|
||||
|
||||
// Advanced config items
|
||||
VariableItem* variable_item_bandwidth; // specific config list view item: bandwidth
|
||||
VariableItem* variable_item_datarate; // specific config list view item: data rate
|
||||
VariableItem* variable_item_manchester; // specific config list view item: manchester enc flag
|
||||
// Advanced config strings
|
||||
char datarate_input_str[16];
|
||||
|
||||
SubGhzFrequencyAnalyzer* subghz_frequency_analyzer;
|
||||
SubGhzReadRAW* subghz_read_raw;
|
||||
bool raw_send_only;
|
||||
|
|
|
@ -36,6 +36,13 @@
|
|||
#define MIN_PIN_SIZE 4
|
||||
#define MAX_APP_LENGTH 128
|
||||
|
||||
#define DISPLAY_BATTERY_BAR 0
|
||||
#define DISPLAY_BATTERY_PERCENT 1
|
||||
#define DISPLAY_BATTERY_INVERTED_PERCENT 2
|
||||
#define DISPLAY_BATTERY_RETRO_3 3
|
||||
#define DISPLAY_BATTERY_RETRO_5 4
|
||||
#define DISPLAY_BATTERY_BAR_PERCENT 5
|
||||
|
||||
#define FAP_LOADER_APP_NAME "Applications"
|
||||
|
||||
typedef struct {
|
||||
|
|
|
@ -56,7 +56,7 @@ static bool desktop_view_slideshow_input(InputEvent* event, void* context) {
|
|||
instance->callback(DesktopSlideshowCompleted, instance->context);
|
||||
}
|
||||
update_view = true;
|
||||
} else if(event->key == InputKeyOk) {
|
||||
} else if(event->key == InputKeyOk && instance->timer) {
|
||||
if(event->type == InputTypePress) {
|
||||
furi_timer_start(instance->timer, DESKTOP_SLIDESHOW_POWEROFF_SHORT);
|
||||
} else if(event->type == InputTypeRelease) {
|
||||
|
|
|
@ -178,6 +178,47 @@ static void button_menu_process_down(ButtonMenu* button_menu) {
|
|||
true);
|
||||
}
|
||||
|
||||
static void button_menu_process_right(ButtonMenu* button_menu) {
|
||||
furi_assert(button_menu);
|
||||
|
||||
with_view_model(
|
||||
button_menu->view,
|
||||
ButtonMenuModel * model,
|
||||
{
|
||||
if(ButtonMenuItemArray_size(model->items) > BUTTONS_PER_SCREEN) {
|
||||
size_t position_candidate = model->position + BUTTONS_PER_SCREEN;
|
||||
position_candidate -= position_candidate % BUTTONS_PER_SCREEN;
|
||||
if(position_candidate < (ButtonMenuItemArray_size(model->items))) {
|
||||
model->position = position_candidate;
|
||||
} else {
|
||||
model->position = 0;
|
||||
}
|
||||
}
|
||||
},
|
||||
true);
|
||||
}
|
||||
|
||||
static void button_menu_process_left(ButtonMenu* button_menu) {
|
||||
furi_assert(button_menu);
|
||||
|
||||
with_view_model(
|
||||
button_menu->view,
|
||||
ButtonMenuModel * model,
|
||||
{
|
||||
if(ButtonMenuItemArray_size(model->items) > BUTTONS_PER_SCREEN) {
|
||||
size_t position_candidate;
|
||||
if(model->position < BUTTONS_PER_SCREEN) {
|
||||
position_candidate = (ButtonMenuItemArray_size(model->items) - 1);
|
||||
} else {
|
||||
position_candidate = model->position - BUTTONS_PER_SCREEN;
|
||||
};
|
||||
position_candidate -= position_candidate % BUTTONS_PER_SCREEN;
|
||||
model->position = position_candidate;
|
||||
}
|
||||
},
|
||||
true);
|
||||
}
|
||||
|
||||
static void button_menu_process_ok(ButtonMenu* button_menu, InputType type) {
|
||||
furi_assert(button_menu);
|
||||
|
||||
|
@ -239,6 +280,14 @@ static bool button_menu_view_input_callback(InputEvent* event, void* context) {
|
|||
consumed = true;
|
||||
button_menu_process_down(button_menu);
|
||||
break;
|
||||
case InputKeyRight:
|
||||
consumed = true;
|
||||
button_menu_process_right(button_menu);
|
||||
break;
|
||||
case InputKeyLeft:
|
||||
consumed = true;
|
||||
button_menu_process_left(button_menu);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ typedef struct {
|
|||
TextInputValidatorCallback validator_callback;
|
||||
void* validator_callback_context;
|
||||
FuriString* validator_text;
|
||||
bool valadator_message_visible;
|
||||
bool validator_message_visible;
|
||||
} TextInputModel;
|
||||
|
||||
static const uint8_t keyboard_origin_x = 1;
|
||||
|
@ -138,7 +138,7 @@ static bool char_is_lowercase(char letter) {
|
|||
static char char_to_uppercase(const char letter) {
|
||||
if(letter == '_') {
|
||||
return 0x20;
|
||||
} else if(isalpha(letter)) {
|
||||
} else if(islower(letter)) {
|
||||
return (letter - 0x20);
|
||||
} else {
|
||||
return letter;
|
||||
|
@ -254,7 +254,7 @@ static void text_input_view_draw_callback(Canvas* canvas, void* _model) {
|
|||
}
|
||||
}
|
||||
}
|
||||
if(model->valadator_message_visible) {
|
||||
if(model->validator_message_visible) {
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
canvas_draw_box(canvas, 8, 10, 110, 48);
|
||||
|
@ -309,7 +309,9 @@ static void text_input_handle_ok(TextInput* text_input, TextInputModel* model, b
|
|||
char selected = get_selected_char(model);
|
||||
size_t text_length = strlen(model->text_buffer);
|
||||
|
||||
if(shift) {
|
||||
bool toogle_case = text_length == 0;
|
||||
if(shift) toogle_case = !toogle_case;
|
||||
if(toogle_case) {
|
||||
selected = char_to_uppercase(selected);
|
||||
}
|
||||
|
||||
|
@ -317,7 +319,7 @@ static void text_input_handle_ok(TextInput* text_input, TextInputModel* model, b
|
|||
if(model->validator_callback &&
|
||||
(!model->validator_callback(
|
||||
model->text_buffer, model->validator_text, model->validator_callback_context))) {
|
||||
model->valadator_message_visible = true;
|
||||
model->validator_message_visible = true;
|
||||
furi_timer_start(text_input->timer, furi_kernel_get_tick_frequency() * 4);
|
||||
} else if(model->callback != 0 && text_length > 0) {
|
||||
model->callback(model->callback_context);
|
||||
|
@ -329,9 +331,6 @@ static void text_input_handle_ok(TextInput* text_input, TextInputModel* model, b
|
|||
text_length = 0;
|
||||
}
|
||||
if(text_length < (model->text_buffer_size - 1)) {
|
||||
if(text_length == 0 && char_is_lowercase(selected)) {
|
||||
selected = char_to_uppercase(selected);
|
||||
}
|
||||
model->text_buffer[text_length] = selected;
|
||||
model->text_buffer[text_length + 1] = 0;
|
||||
}
|
||||
|
@ -349,8 +348,8 @@ static bool text_input_view_input_callback(InputEvent* event, void* context) {
|
|||
TextInputModel* model = view_get_model(text_input->view);
|
||||
|
||||
if((!(event->type == InputTypePress) && !(event->type == InputTypeRelease)) &&
|
||||
model->valadator_message_visible) {
|
||||
model->valadator_message_visible = false;
|
||||
model->validator_message_visible) {
|
||||
model->validator_message_visible = false;
|
||||
consumed = true;
|
||||
} else if(event->type == InputTypeShort) {
|
||||
consumed = true;
|
||||
|
@ -436,7 +435,7 @@ void text_input_timer_callback(void* context) {
|
|||
with_view_model(
|
||||
text_input->view,
|
||||
TextInputModel * model,
|
||||
{ model->valadator_message_visible = false; },
|
||||
{ model->validator_message_visible = false; },
|
||||
true);
|
||||
}
|
||||
|
||||
|
@ -496,7 +495,7 @@ void text_input_reset(TextInput* text_input) {
|
|||
model->validator_callback = NULL;
|
||||
model->validator_callback_context = NULL;
|
||||
furi_string_reset(model->validator_text);
|
||||
model->valadator_message_visible = false;
|
||||
model->validator_message_visible = false;
|
||||
},
|
||||
true);
|
||||
}
|
||||
|
|
|
@ -91,7 +91,7 @@ void widget_add_string_element(
|
|||
* @param[in] text Formatted text. The following formats are available:
|
||||
* "\e#Bold text\e#" - bold font is used
|
||||
* "\e*Monospaced text\e*" - monospaced font is used
|
||||
* "\e#Inversed text\e#" - white text on black background
|
||||
* "\e!Inversed text\e!" - white text on black background
|
||||
* @param strip_to_dots Strip text to ... if does not fit to width
|
||||
*/
|
||||
void widget_add_text_box_element(
|
||||
|
|
|
@ -19,7 +19,7 @@ extern "C" {
|
|||
typedef enum {
|
||||
InputTypePress, /**< Press event, emitted after debounce */
|
||||
InputTypeRelease, /**< Release event, emitted after debounce */
|
||||
InputTypeShort, /**< Short event, emitted after InputTypeRelease done withing INPUT_LONG_PRESS interval */
|
||||
InputTypeShort, /**< Short event, emitted after InputTypeRelease done within INPUT_LONG_PRESS interval */
|
||||
InputTypeLong, /**< Long event, emitted after INPUT_LONG_PRESS_COUNTS interval, asynchronous to InputTypeRelease */
|
||||
InputTypeRepeat, /**< Repeat event, emitted with INPUT_LONG_PRESS_COUNTS period after InputTypeLong event */
|
||||
InputTypeMAX, /**< Special value for exceptional */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#include "power_i.h"
|
||||
#include "desktop/desktop_settings.h"
|
||||
#include "power_i.h"
|
||||
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
|
@ -14,7 +14,7 @@ void power_draw_battery_callback(Canvas* canvas, void* context) {
|
|||
if(power->info.gauge_is_ok) {
|
||||
char batteryPercentile[4];
|
||||
snprintf(batteryPercentile, sizeof(batteryPercentile), "%d", power->info.charge);
|
||||
if((power->displayBatteryPercentage == 1) &&
|
||||
if((power->displayBatteryPercentage == DISPLAY_BATTERY_PERCENT) &&
|
||||
(power->state !=
|
||||
PowerStateCharging)) { //if display battery percentage, black background white text
|
||||
canvas_set_font(canvas, FontBatteryPercent);
|
||||
|
@ -23,14 +23,14 @@ void power_draw_battery_callback(Canvas* canvas, void* context) {
|
|||
canvas_set_color(canvas, ColorWhite);
|
||||
canvas_draw_str_aligned(canvas, 11, 4, AlignCenter, AlignCenter, batteryPercentile);
|
||||
} else if(
|
||||
(power->displayBatteryPercentage == 2) &&
|
||||
(power->displayBatteryPercentage == DISPLAY_BATTERY_INVERTED_PERCENT) &&
|
||||
(power->state !=
|
||||
PowerStateCharging)) { //if display inverted percentage, white background black text
|
||||
canvas_set_font(canvas, FontBatteryPercent);
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
canvas_draw_str_aligned(canvas, 11, 4, AlignCenter, AlignCenter, batteryPercentile);
|
||||
} else if(
|
||||
(power->displayBatteryPercentage == 3) &&
|
||||
(power->displayBatteryPercentage == DISPLAY_BATTERY_RETRO_3) &&
|
||||
(power->state != PowerStateCharging)) { //Retro style segmented display, 3 parts
|
||||
if(power->info.charge > 25) {
|
||||
canvas_draw_box(canvas, 2, 2, 6, 4);
|
||||
|
@ -42,7 +42,7 @@ void power_draw_battery_callback(Canvas* canvas, void* context) {
|
|||
canvas_draw_box(canvas, 16, 2, 6, 4);
|
||||
}
|
||||
} else if(
|
||||
(power->displayBatteryPercentage == 4) &&
|
||||
(power->displayBatteryPercentage == DISPLAY_BATTERY_RETRO_5) &&
|
||||
(power->state != PowerStateCharging)) { //Retro style segmented display, 5 parts
|
||||
if(power->info.charge > 10) {
|
||||
canvas_draw_box(canvas, 2, 2, 3, 4);
|
||||
|
@ -59,6 +59,58 @@ void power_draw_battery_callback(Canvas* canvas, void* context) {
|
|||
if(power->info.charge > 90) {
|
||||
canvas_draw_box(canvas, 18, 2, 3, 4);
|
||||
}
|
||||
} else if(
|
||||
(power->displayBatteryPercentage == DISPLAY_BATTERY_BAR_PERCENT) &&
|
||||
(power->state != PowerStateCharging) && // Default bar display with percentage
|
||||
(power->info.voltage_battery_charging >= 4.2)) { // not looking nice with low voltage indicator
|
||||
canvas_set_font(canvas, FontBatteryPercent);
|
||||
|
||||
// align charge dispaly value with digits to draw
|
||||
uint8_t bar_charge = power->info.charge;
|
||||
if(bar_charge > 23 && bar_charge < 38) {
|
||||
bar_charge = 23;
|
||||
} else if(bar_charge >= 38 && bar_charge < 62) {
|
||||
bar_charge = 50;
|
||||
} else if(bar_charge >= 62 && bar_charge < 74) {
|
||||
bar_charge = 74;
|
||||
}
|
||||
|
||||
// drawing digits
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
canvas_draw_box(canvas, 1, 1, (bar_charge * 22) / 100, 6);
|
||||
if(bar_charge < 38) { // both digits are black
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
canvas_draw_str_aligned(
|
||||
canvas, 11, 4, AlignCenter, AlignCenter, batteryPercentile);
|
||||
} else if(bar_charge >= 38 && bar_charge < 74) { // first digit is white
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
|
||||
// first
|
||||
char batteryPercentileFirstDigit[2];
|
||||
snprintf(
|
||||
batteryPercentileFirstDigit,
|
||||
sizeof(batteryPercentileFirstDigit),
|
||||
"%c",
|
||||
batteryPercentile[0]);
|
||||
canvas_draw_str_aligned(
|
||||
canvas, 9, 4, AlignCenter, AlignCenter, batteryPercentileFirstDigit);
|
||||
|
||||
// second
|
||||
char batteryPercentileSecondDigit[2];
|
||||
snprintf(
|
||||
batteryPercentileSecondDigit,
|
||||
sizeof(batteryPercentileSecondDigit),
|
||||
"%c",
|
||||
batteryPercentile[1]);
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
canvas_draw_str_aligned(
|
||||
canvas, 15, 4, AlignCenter, AlignCenter, batteryPercentileSecondDigit);
|
||||
} else { // charge >= 74, both digits are white
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
canvas_draw_str_aligned(
|
||||
canvas, 11, 4, AlignCenter, AlignCenter, batteryPercentile);
|
||||
}
|
||||
|
||||
} else { //default bar display, added here to serve as fallback/default behaviour.
|
||||
canvas_draw_box(canvas, 2, 2, (power->info.charge + 4) / 5, 4);
|
||||
}
|
||||
|
@ -82,7 +134,7 @@ void power_draw_battery_callback(Canvas* canvas, void* context) {
|
|||
if(power->state == PowerStateCharging) {
|
||||
canvas_set_bitmap_mode(canvas, 1);
|
||||
// TODO: replace -1 magic for uint8_t with re-framing
|
||||
if(power->displayBatteryPercentage == 1) {
|
||||
if(power->displayBatteryPercentage == DISPLAY_BATTERY_PERCENT) {
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
canvas_draw_box(canvas, 1, 1, 22, 6);
|
||||
canvas_draw_icon(canvas, 2, -1, &I_Charging_lightning_9x10);
|
||||
|
@ -91,7 +143,7 @@ void power_draw_battery_callback(Canvas* canvas, void* context) {
|
|||
canvas_set_font(canvas, FontBatteryPercent);
|
||||
canvas_draw_str_aligned(
|
||||
canvas, 16, 4, AlignCenter, AlignCenter, batteryPercentile);
|
||||
} else if(power->displayBatteryPercentage == 2) {
|
||||
} else if(power->displayBatteryPercentage == DISPLAY_BATTERY_INVERTED_PERCENT) {
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
canvas_draw_box(canvas, 1, 1, 22, 6);
|
||||
canvas_draw_icon(canvas, 2, -1, &I_Charging_lightning_9x10);
|
||||
|
@ -100,6 +152,64 @@ void power_draw_battery_callback(Canvas* canvas, void* context) {
|
|||
canvas_set_font(canvas, FontBatteryPercent);
|
||||
canvas_draw_str_aligned(
|
||||
canvas, 16, 4, AlignCenter, AlignCenter, batteryPercentile);
|
||||
} else if(power->displayBatteryPercentage == DISPLAY_BATTERY_BAR_PERCENT) {
|
||||
|
||||
// clean-up default charging bar display
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
canvas_draw_box(canvas, 1, 1, 22, 6);
|
||||
|
||||
// align charge dispaly value with digits to draw
|
||||
uint8_t bar_charge = power->info.charge;
|
||||
|
||||
if(bar_charge > 48 && bar_charge < 63) {
|
||||
bar_charge = 48;
|
||||
} else if(bar_charge >= 63 && bar_charge < 84) {
|
||||
bar_charge = 75;
|
||||
} else if(bar_charge >= 84 && bar_charge < 96) {
|
||||
bar_charge = 96;
|
||||
}
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
canvas_draw_box(canvas, 1, 1, (bar_charge * 22) / 100, 6);
|
||||
|
||||
// drawing charge icon
|
||||
canvas_draw_icon(canvas, 2, -1, &I_Charging_lightning_9x10);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
canvas_draw_icon(canvas, 2, -1, &I_Charging_lightning_mask_9x10);
|
||||
|
||||
// drawing digits
|
||||
canvas_set_font(canvas, FontBatteryPercent);
|
||||
if(bar_charge < 64) { // both digits are black
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
canvas_draw_str_aligned(
|
||||
canvas, 16, 4, AlignCenter, AlignCenter, batteryPercentile);
|
||||
} else if(bar_charge >= 64 && bar_charge < 84) { // first digit is white
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
|
||||
// first
|
||||
char batteryPercentileFirstDigit[2];
|
||||
snprintf(
|
||||
batteryPercentileFirstDigit,
|
||||
sizeof(batteryPercentileFirstDigit),
|
||||
"%c",
|
||||
batteryPercentile[0]);
|
||||
canvas_draw_str_aligned(
|
||||
canvas, 14, 4, AlignCenter, AlignCenter, batteryPercentileFirstDigit);
|
||||
|
||||
// second
|
||||
char batteryPercentileSecondDigit[2];
|
||||
snprintf(
|
||||
batteryPercentileSecondDigit,
|
||||
sizeof(batteryPercentileSecondDigit),
|
||||
"%c",
|
||||
batteryPercentile[1]);
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
canvas_draw_str_aligned(
|
||||
canvas, 20, 4, AlignCenter, AlignCenter, batteryPercentileSecondDigit);
|
||||
} else { // charge >= 84, both digits are white
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
canvas_draw_str_aligned(
|
||||
canvas, 16, 4, AlignCenter, AlignCenter, batteryPercentile);
|
||||
}
|
||||
} else {
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
canvas_draw_icon(canvas, 8, -1, &I_Charging_lightning_mask_9x10);
|
||||
|
|
|
@ -26,7 +26,7 @@ const char* const auto_lock_delay_text[AUTO_LOCK_DELAY_COUNT] = {
|
|||
const uint32_t auto_lock_delay_value[AUTO_LOCK_DELAY_COUNT] =
|
||||
{0, 10000, 15000, 30000, 60000, 90000, 120000, 300000, 600000};
|
||||
|
||||
#define BATTERY_VIEW_COUNT 5
|
||||
#define BATTERY_VIEW_COUNT 6
|
||||
|
||||
const char* const battery_view_count_text[BATTERY_VIEW_COUNT] = {
|
||||
"Bar",
|
||||
|
@ -34,9 +34,17 @@ const char* const battery_view_count_text[BATTERY_VIEW_COUNT] = {
|
|||
"Inv. %",
|
||||
"Retro 3",
|
||||
"Retro 5",
|
||||
"Bar %"
|
||||
};
|
||||
|
||||
const uint32_t displayBatteryPercentage_value[BATTERY_VIEW_COUNT] = {0, 1, 2, 3, 4};
|
||||
const uint32_t displayBatteryPercentage_value[BATTERY_VIEW_COUNT] = {
|
||||
DISPLAY_BATTERY_BAR,
|
||||
DISPLAY_BATTERY_PERCENT,
|
||||
DISPLAY_BATTERY_INVERTED_PERCENT,
|
||||
DISPLAY_BATTERY_RETRO_3,
|
||||
DISPLAY_BATTERY_RETRO_5,
|
||||
DISPLAY_BATTERY_BAR_PERCENT
|
||||
};
|
||||
|
||||
static void desktop_settings_scene_start_var_list_enter_callback(void* context, uint32_t index) {
|
||||
DesktopSettingsApp* app = context;
|
||||
|
|
|
@ -54,13 +54,14 @@ assetsenv.Alias("proto_ver", proto_ver)
|
|||
|
||||
# Gather everything into a static lib
|
||||
assets_parts = (icons, proto, dolphin_blocking, dolphin_internal, proto_ver)
|
||||
env.Replace(FW_ASSETS_HEADERS=assets_parts)
|
||||
|
||||
assetslib = assetsenv.Library("${FW_LIB_NAME}", assets_parts)
|
||||
assetsenv.Install("${LIB_DIST_DIR}", assetslib)
|
||||
|
||||
|
||||
# Resources for SD card
|
||||
|
||||
env.SetDefault(FW_RESOURCES=None)
|
||||
if assetsenv["IS_BASE_FIRMWARE"]:
|
||||
# External dolphin animations
|
||||
dolphin_external = assetsenv.DolphinExtBuilder(
|
||||
|
@ -92,8 +93,7 @@ if assetsenv["IS_BASE_FIRMWARE"]:
|
|||
)
|
||||
|
||||
# Exporting resources node to external environment
|
||||
env["FW_ASSETS_HEADERS"] = assets_parts
|
||||
env["FW_RESOURCES"] = resources
|
||||
env.Replace(FW_RESOURCES=resources)
|
||||
assetsenv.Alias("resources", resources)
|
||||
|
||||
Return("assetslib")
|
||||
|
|
|
@ -79,7 +79,7 @@ STRING Flipper Zero BadUSB feature is compatible with USB Rubber Ducky script fo
|
|||
ENTER
|
||||
STRING More information about script syntax can be found here:
|
||||
ENTER
|
||||
STRING https://github.com/hak5darren/USB-Rubber-Ducky/wiki/Duckyscript
|
||||
STRING https://github.com/flipperdevices/flipperzero-firmware/blob/dev/documentation/file_formats/BadUsbScriptFormat.md
|
||||
ENTER
|
||||
|
||||
STRING EOF
|
||||
|
|
|
@ -80,5 +80,5 @@ STRING Flipper Zero BadUSB feature is compatible with USB Rubber Ducky script fo
|
|||
ENTER
|
||||
STRING More information about script syntax can be found here:
|
||||
ENTER
|
||||
STRING https://github.com/hak5darren/USB-Rubber-Ducky/wiki/Duckyscript
|
||||
STRING https://github.com/flipperdevices/flipperzero-firmware/blob/dev/documentation/file_formats/BadUsbScriptFormat.md
|
||||
ENTER
|
||||
|
|
|
@ -1,7 +1,37 @@
|
|||
Filetype: IR library file
|
||||
Version: 1
|
||||
# Last Updated 7th Jan, 2023
|
||||
# Last Checked 7th Jan, 2023
|
||||
# Last Updated 13th Jan, 2023
|
||||
# Last Checked 13th Jan, 2023
|
||||
#
|
||||
name: POWER
|
||||
type: raw
|
||||
frequency: 38000
|
||||
duty_cycle: 0.330000
|
||||
data: 8714 4338 579 538 551 540 549 542 557 1613 555 1615 553 538 551 540 549 1619 549 1620 558 1612 556 1614 554 1617 551 540 559 1611 557 1612 556 531 558 1613 555 536 553 538 551 1620 558 1612 556 535 554 537 552 535 554 537 552 1618 550 1620 558 533 556 536 553 1617 551 1617 551 1608 549
|
||||
#
|
||||
name: MODE
|
||||
type: raw
|
||||
frequency: 38000
|
||||
duty_cycle: 0.330000
|
||||
data: 8710 4341 576 541 558 533 556 535 554 1616 552 1618 550 542 557 533 556 1612 556 1614 554 1616 552 1618 550 1621 557 534 555 1615 553 1616 552 536 553 538 551 541 558 533 556 1613 555 537 552 539 550 541 558 528 550 1619 559 1610 557 1612 556 536 553 1616 552 1618 550 1619 559 1598 559
|
||||
#
|
||||
name: TIMER
|
||||
type: raw
|
||||
frequency: 38000
|
||||
duty_cycle: 0.330000
|
||||
data: 8717 4334 583 534 555 537 552 539 550 1620 558 1611 557 535 554 536 553 1615 553 1617 551 1619 559 1611 557 1613 555 537 552 1617 551 1619 559 528 550 541 558 1612 556 535 554 1616 552 1619 549 543 556 534 555 532 557 1614 554 537 552 1619 559 533 556 535 554 1616 552 1617 551 1608 549
|
||||
#
|
||||
name: TEMP+
|
||||
type: raw
|
||||
frequency: 38000
|
||||
duty_cycle: 0.330000
|
||||
data: 8714 4337 580 538 551 540 559 533 556 1613 555 1615 553 539 550 541 558 1608 560 1611 557 1587 581 1590 578 1593 575 542 557 1613 555 1614 554 534 555 1615 553 539 550 1620 558 534 555 536 553 539 550 541 558 529 549 541 558 1612 556 536 553 1617 551 1619 559 1611 557 1613 555 1603 554
|
||||
#
|
||||
name: TEMP-
|
||||
type: raw
|
||||
frequency: 38000
|
||||
duty_cycle: 0.330000
|
||||
data: 8711 4341 576 541 558 534 555 536 553 1616 552 1618 549 542 557 533 556 1611 557 1613 555 1614 554 1616 552 1619 559 532 557 1613 555 1614 554 533 556 1614 554 538 551 541 558 1611 557 535 554 537 552 539 550 537 552 540 549 1620 558 1612 556 536 553 1617 550 1619 559 1610 558 1601 556
|
||||
#
|
||||
# POWER_ON
|
||||
name: POWER
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,7 +1,7 @@
|
|||
Filetype: IR library file
|
||||
Version: 1
|
||||
# Last Updated 7th Jan, 2023
|
||||
# Last Checked 7th Jan, 2023
|
||||
# Last Updated 13th Jan, 2023
|
||||
# Last Checked 13th Jan, 2023
|
||||
#
|
||||
name: POWER
|
||||
type: raw
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
Filetype: IR library file
|
||||
Version: 1
|
||||
# Last Updated 5th Jan, 2023
|
||||
# Last Checked 7th Jan, 2023
|
||||
# Last Updated 13th Jan, 2023
|
||||
# Last Checked 13th Jan, 2023
|
||||
#
|
||||
# ON
|
||||
name: POWER
|
||||
|
@ -712,3 +712,69 @@ type: parsed
|
|||
protocol: NEC
|
||||
address: 00 00 00 00
|
||||
command: 8C 00 00 00
|
||||
#
|
||||
name: POWER
|
||||
type: parsed
|
||||
protocol: NECext
|
||||
address: 87 45 00 00
|
||||
command: 17 E8 00 00
|
||||
#
|
||||
name: VOL+
|
||||
type: raw
|
||||
frequency: 38000
|
||||
duty_cycle: 0.330000
|
||||
data: 9064 4354 666 1559 666 1562 662 1586 638 475 636 477 635 477 635 478 635 1590 635 1591 634 478 635 1591 634 478 634 478 635 478 634 1591 635 478 634 1591 634 478 635 478 634 478 635 1591 634 478 634 1591 635 478 634 478 634 1591 634 1591 635 1591 634 478 635 1591 634 478 634 1591 635 40957 9035 2144 634 95483 9047 2155 632 95484 9048 2153 633
|
||||
#
|
||||
name: VOL-
|
||||
type: parsed
|
||||
protocol: NECext
|
||||
address: 87 45 00 00
|
||||
command: 50 AF 00 00
|
||||
#
|
||||
name: MUTE
|
||||
type: raw
|
||||
frequency: 38000
|
||||
duty_cycle: 0.330000
|
||||
data: 9034 4385 638 1587 664 1562 663 1587 637 476 635 478 634 478 635 478 635 1591 634 1591 634 478 635 1591 635 478 634 478 635 478 635 1591 635 478 634 478 634 1591 634 478 635 479 634 1591 635 478 634 1591 635 478 634 1592 634 478 634 1591 635 1591 635 478 634 1592 634 478 634 1591 634 40958 9033 2144 635
|
||||
#
|
||||
name: POWER
|
||||
type: parsed
|
||||
protocol: NECext
|
||||
address: FF FF 00 00
|
||||
command: E8 17 00 00
|
||||
#
|
||||
name: VOL+
|
||||
type: parsed
|
||||
protocol: NECext
|
||||
address: FF FF 00 00
|
||||
command: BD 42 00 00
|
||||
#
|
||||
name: VOL-
|
||||
type: parsed
|
||||
protocol: NECext
|
||||
address: FF FF 00 00
|
||||
command: F2 0D 00 00
|
||||
#
|
||||
name: POWER
|
||||
type: parsed
|
||||
protocol: Kaseikyo
|
||||
address: 41 54 32 00
|
||||
command: 05 00 00 00
|
||||
#
|
||||
name: VOL+
|
||||
type: parsed
|
||||
protocol: Kaseikyo
|
||||
address: 41 54 32 00
|
||||
command: 70 01 00 00
|
||||
#
|
||||
name: VOL-
|
||||
type: parsed
|
||||
protocol: Kaseikyo
|
||||
address: 41 54 32 00
|
||||
command: 71 01 00 00
|
||||
#
|
||||
name: POWER
|
||||
type: parsed
|
||||
protocol: NEC
|
||||
address: 31 00 00 00
|
||||
command: 81 00 00 00
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
Filetype: IR library file
|
||||
Version: 1
|
||||
# Last Updated 7th Jan, 2023
|
||||
# Last Checked 7th Jan, 2023
|
||||
# Last Updated 13th Jan, 2023
|
||||
# Last Checked 13th Jan, 2023
|
||||
#
|
||||
name: POWER
|
||||
type: parsed
|
||||
|
@ -1785,3 +1785,39 @@ type: parsed
|
|||
protocol: NEC
|
||||
address: 00 00 00 00
|
||||
command: 33 00 00 00
|
||||
#
|
||||
name: POWER
|
||||
type: parsed
|
||||
protocol: NEC
|
||||
address: 28 00 00 00
|
||||
command: 0B 00 00 00
|
||||
#
|
||||
name: CH+
|
||||
type: parsed
|
||||
protocol: NEC
|
||||
address: 28 00 00 00
|
||||
command: 0C 00 00 00
|
||||
#
|
||||
name: CH-
|
||||
type: parsed
|
||||
protocol: NEC
|
||||
address: 28 00 00 00
|
||||
command: 0D 00 00 00
|
||||
#
|
||||
name: VOL+
|
||||
type: parsed
|
||||
protocol: NEC
|
||||
address: 28 00 00 00
|
||||
command: 0E 00 00 00
|
||||
#
|
||||
name: VOL-
|
||||
type: parsed
|
||||
protocol: NEC
|
||||
address: 28 00 00 00
|
||||
command: 0F 00 00 00
|
||||
#
|
||||
name: MUTE
|
||||
type: parsed
|
||||
protocol: NEC
|
||||
address: 28 00 00 00
|
||||
command: 10 00 00 00
|
||||
|
|
|
@ -56,6 +56,7 @@ To run cleanup (think of `make clean`) for specified targets, add the `-c` optio
|
|||
- `get_stlink` - output serial numbers for attached STLink probes. Used for specifying an adapter with `OPENOCD_ADAPTER_SERIAL=...`.
|
||||
- `lint`, `format` - run clang-format on the C source code to check and reformat it according to the `.clang-format` specs.
|
||||
- `lint_py`, `format_py` - run [black](https://black.readthedocs.io/en/stable/index.html) on the Python source code, build system files & application manifests.
|
||||
- `firmware_pvs` - generate a PVS Studio report for the firmware. Requires PVS Studio to be availabe on your system's `PATH`.
|
||||
- `cli` - start a Flipper CLI session over USB.
|
||||
|
||||
### Firmware targets
|
||||
|
|
|
@ -15,6 +15,7 @@ env = ENV.Clone(
|
|||
("compilation_db", {"COMPILATIONDB_COMSTR": "\tCDB\t${TARGET}"}),
|
||||
"fwbin",
|
||||
"fbt_apps",
|
||||
"pvsstudio",
|
||||
],
|
||||
COMPILATIONDB_USE_ABSPATH=False,
|
||||
BUILD_DIR=fw_build_meta["build_dir"],
|
||||
|
@ -69,6 +70,8 @@ env = ENV.Clone(
|
|||
],
|
||||
},
|
||||
},
|
||||
SDK_APISYMS=None,
|
||||
_APP_ICONS=None,
|
||||
)
|
||||
|
||||
|
||||
|
@ -128,9 +131,6 @@ if extra_int_apps := GetOption("extra_int_apps"):
|
|||
fwenv.Append(APPS=extra_int_apps.split(","))
|
||||
|
||||
|
||||
if fwenv["FAP_EXAMPLES"]:
|
||||
fwenv.Append(APPDIRS=[("applications/examples", False)])
|
||||
|
||||
for app_dir, _ in env["APPDIRS"]:
|
||||
app_dir_node = env.Dir("#").Dir(app_dir)
|
||||
|
||||
|
@ -273,6 +273,24 @@ Precious(fwcdb)
|
|||
NoClean(fwcdb)
|
||||
Alias(fwenv["FIRMWARE_BUILD_CFG"] + "_cdb", fwcdb)
|
||||
|
||||
pvscheck = fwenv.PVSCheck("pvsreport.log", fwcdb)
|
||||
Depends(
|
||||
pvscheck,
|
||||
[
|
||||
fwenv["FW_VERSION_JSON"],
|
||||
fwenv["FW_ASSETS_HEADERS"],
|
||||
fwenv["SDK_APISYMS"],
|
||||
fwenv["_APP_ICONS"],
|
||||
],
|
||||
)
|
||||
Alias(fwenv["FIRMWARE_BUILD_CFG"] + "_pvscheck", pvscheck)
|
||||
AlwaysBuild(pvscheck)
|
||||
Precious(pvscheck)
|
||||
|
||||
pvsreport = fwenv.PVSReport(None, pvscheck, REPORT_DIR=Dir("pvsreport"))
|
||||
Alias(fwenv["FIRMWARE_BUILD_CFG"] + "_pvs", pvsreport)
|
||||
AlwaysBuild(pvsreport)
|
||||
|
||||
# If current configuration was explicitly requested, generate compilation database
|
||||
# and link its directory as build/latest
|
||||
if should_gen_cdb_and_link_dir(fwenv, BUILD_TARGETS):
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
entry,status,name,type,params
|
||||
Version,+,11.8,,
|
||||
Version,+,11.7,,
|
||||
Header,+,applications/services/bt/bt_service/bt.h,,
|
||||
Header,+,applications/services/cli/cli.h,,
|
||||
Header,+,applications/services/cli/cli_vcp.h,,
|
||||
|
@ -1649,6 +1649,7 @@ Function,+,infrared_get_protocol_by_name,InfraredProtocol,const char*
|
|||
Function,+,infrared_get_protocol_command_length,uint8_t,InfraredProtocol
|
||||
Function,+,infrared_get_protocol_duty_cycle,float,InfraredProtocol
|
||||
Function,+,infrared_get_protocol_frequency,uint32_t,InfraredProtocol
|
||||
Function,+,infrared_get_protocol_min_repeat_count,size_t,InfraredProtocol
|
||||
Function,+,infrared_get_protocol_name,const char*,InfraredProtocol
|
||||
Function,+,infrared_is_protocol_valid,_Bool,InfraredProtocol
|
||||
Function,+,infrared_reset_decoder,void,InfraredDecoderHandler*
|
||||
|
|
|
|
@ -93,7 +93,11 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
#ifndef FURI_BIT_CLEAR
|
||||
#define FURI_BIT_CLEAR(x, n) ((x) &= ~(1UL << (n)))
|
||||
#define FURI_BIT_CLEAR(x, n) \
|
||||
({ \
|
||||
__typeof__(x) _x = (1); \
|
||||
(x) &= ~(_x << (n)); \
|
||||
})
|
||||
#endif
|
||||
|
||||
#define FURI_SW_MEMBARRIER() asm volatile("" : : : "memory")
|
||||
|
|
|
@ -315,6 +315,7 @@ static bool elf_relocate_symbol(ELFFile* elf, Elf32_Addr relAddr, int type, Elf3
|
|||
FURI_LOG_D(TAG, " R_ARM_ABS32 relocated is 0x%08X", (unsigned int)*((uint32_t*)relAddr));
|
||||
break;
|
||||
case R_ARM_THM_PC22:
|
||||
case R_ARM_CALL:
|
||||
case R_ARM_THM_JUMP24:
|
||||
elf_relocate_jmp_call(elf, relAddr, type, symAddr);
|
||||
FURI_LOG_D(
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
#include "infrared_common_i.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <core/check.h>
|
||||
#include <core/common_defines.h>
|
||||
#include "infrared.h"
|
||||
#include "infrared_common_i.h"
|
||||
#include <stdbool.h>
|
||||
#include <furi.h>
|
||||
#include "infrared_i.h"
|
||||
#include <stdint.h>
|
||||
|
||||
static void infrared_common_decoder_reset_state(InfraredCommonDecoder* decoder);
|
||||
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
#include <core/check.h>
|
||||
#include "infrared.h"
|
||||
#include "infrared_common_i.h"
|
||||
#include <stdbool.h>
|
||||
#include <furi.h>
|
||||
#include "infrared_i.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <core/check.h>
|
||||
#include <core/common_defines.h>
|
||||
|
||||
static InfraredStatus
|
||||
infrared_common_encode_bits(InfraredCommonEncoder* encoder, uint32_t* duration, bool* level) {
|
||||
|
|
|
@ -1,140 +0,0 @@
|
|||
#include "infrared_common_i.h"
|
||||
#include "infrared_protocol_defs_i.h"
|
||||
|
||||
const InfraredCommonProtocolSpec protocol_nec = {
|
||||
.timings =
|
||||
{
|
||||
.preamble_mark = INFRARED_NEC_PREAMBLE_MARK,
|
||||
.preamble_space = INFRARED_NEC_PREAMBLE_SPACE,
|
||||
.bit1_mark = INFRARED_NEC_BIT1_MARK,
|
||||
.bit1_space = INFRARED_NEC_BIT1_SPACE,
|
||||
.bit0_mark = INFRARED_NEC_BIT0_MARK,
|
||||
.bit0_space = INFRARED_NEC_BIT0_SPACE,
|
||||
.preamble_tolerance = INFRARED_NEC_PREAMBLE_TOLERANCE,
|
||||
.bit_tolerance = INFRARED_NEC_BIT_TOLERANCE,
|
||||
.silence_time = INFRARED_NEC_SILENCE,
|
||||
.min_split_time = INFRARED_NEC_MIN_SPLIT_TIME,
|
||||
},
|
||||
.databit_len[0] = 42,
|
||||
.databit_len[1] = 32,
|
||||
.no_stop_bit = false,
|
||||
.decode = infrared_common_decode_pdwm,
|
||||
.encode = infrared_common_encode_pdwm,
|
||||
.interpret = infrared_decoder_nec_interpret,
|
||||
.decode_repeat = infrared_decoder_nec_decode_repeat,
|
||||
.encode_repeat = infrared_encoder_nec_encode_repeat,
|
||||
};
|
||||
|
||||
const InfraredCommonProtocolSpec protocol_samsung32 = {
|
||||
.timings =
|
||||
{
|
||||
.preamble_mark = INFRARED_SAMSUNG_PREAMBLE_MARK,
|
||||
.preamble_space = INFRARED_SAMSUNG_PREAMBLE_SPACE,
|
||||
.bit1_mark = INFRARED_SAMSUNG_BIT1_MARK,
|
||||
.bit1_space = INFRARED_SAMSUNG_BIT1_SPACE,
|
||||
.bit0_mark = INFRARED_SAMSUNG_BIT0_MARK,
|
||||
.bit0_space = INFRARED_SAMSUNG_BIT0_SPACE,
|
||||
.preamble_tolerance = INFRARED_SAMSUNG_PREAMBLE_TOLERANCE,
|
||||
.bit_tolerance = INFRARED_SAMSUNG_BIT_TOLERANCE,
|
||||
.silence_time = INFRARED_SAMSUNG_SILENCE,
|
||||
.min_split_time = INFRARED_SAMSUNG_MIN_SPLIT_TIME,
|
||||
},
|
||||
.databit_len[0] = 32,
|
||||
.no_stop_bit = false,
|
||||
.decode = infrared_common_decode_pdwm,
|
||||
.encode = infrared_common_encode_pdwm,
|
||||
.interpret = infrared_decoder_samsung32_interpret,
|
||||
.decode_repeat = infrared_decoder_samsung32_decode_repeat,
|
||||
.encode_repeat = infrared_encoder_samsung32_encode_repeat,
|
||||
};
|
||||
|
||||
const InfraredCommonProtocolSpec protocol_rc6 = {
|
||||
.timings =
|
||||
{
|
||||
.preamble_mark = INFRARED_RC6_PREAMBLE_MARK,
|
||||
.preamble_space = INFRARED_RC6_PREAMBLE_SPACE,
|
||||
.bit1_mark = INFRARED_RC6_BIT,
|
||||
.preamble_tolerance = INFRARED_RC6_PREAMBLE_TOLERANCE,
|
||||
.bit_tolerance = INFRARED_RC6_BIT_TOLERANCE,
|
||||
.silence_time = INFRARED_RC6_SILENCE,
|
||||
.min_split_time = INFRARED_RC6_MIN_SPLIT_TIME,
|
||||
},
|
||||
.databit_len[0] =
|
||||
1 + 3 + 1 + 8 +
|
||||
8, // start_bit + 3 mode bits, + 1 toggle bit (x2 timing) + 8 address + 8 command
|
||||
.manchester_start_from_space = false,
|
||||
.decode = infrared_decoder_rc6_decode_manchester,
|
||||
.encode = infrared_encoder_rc6_encode_manchester,
|
||||
.interpret = infrared_decoder_rc6_interpret,
|
||||
.decode_repeat = NULL,
|
||||
.encode_repeat = NULL,
|
||||
};
|
||||
|
||||
const InfraredCommonProtocolSpec protocol_rc5 = {
|
||||
.timings =
|
||||
{
|
||||
.preamble_mark = 0,
|
||||
.preamble_space = 0,
|
||||
.bit1_mark = INFRARED_RC5_BIT,
|
||||
.preamble_tolerance = 0,
|
||||
.bit_tolerance = INFRARED_RC5_BIT_TOLERANCE,
|
||||
.silence_time = INFRARED_RC5_SILENCE,
|
||||
.min_split_time = INFRARED_RC5_MIN_SPLIT_TIME,
|
||||
},
|
||||
.databit_len[0] = 1 + 1 + 1 + 5 +
|
||||
6, // start_bit + start_bit/command_bit + toggle_bit + 5 address + 6 command
|
||||
.manchester_start_from_space = true,
|
||||
.decode = infrared_common_decode_manchester,
|
||||
.encode = infrared_common_encode_manchester,
|
||||
.interpret = infrared_decoder_rc5_interpret,
|
||||
.decode_repeat = NULL,
|
||||
.encode_repeat = NULL,
|
||||
};
|
||||
|
||||
const InfraredCommonProtocolSpec protocol_sirc = {
|
||||
.timings =
|
||||
{
|
||||
.preamble_mark = INFRARED_SIRC_PREAMBLE_MARK,
|
||||
.preamble_space = INFRARED_SIRC_PREAMBLE_SPACE,
|
||||
.bit1_mark = INFRARED_SIRC_BIT1_MARK,
|
||||
.bit1_space = INFRARED_SIRC_BIT1_SPACE,
|
||||
.bit0_mark = INFRARED_SIRC_BIT0_MARK,
|
||||
.bit0_space = INFRARED_SIRC_BIT0_SPACE,
|
||||
.preamble_tolerance = INFRARED_SIRC_PREAMBLE_TOLERANCE,
|
||||
.bit_tolerance = INFRARED_SIRC_BIT_TOLERANCE,
|
||||
.silence_time = INFRARED_SIRC_SILENCE,
|
||||
.min_split_time = INFRARED_SIRC_MIN_SPLIT_TIME,
|
||||
},
|
||||
.databit_len[0] = 20,
|
||||
.databit_len[1] = 15,
|
||||
.databit_len[2] = 12,
|
||||
.no_stop_bit = true,
|
||||
.decode = infrared_common_decode_pdwm,
|
||||
.encode = infrared_common_encode_pdwm,
|
||||
.interpret = infrared_decoder_sirc_interpret,
|
||||
.decode_repeat = NULL,
|
||||
.encode_repeat = infrared_encoder_sirc_encode_repeat,
|
||||
};
|
||||
|
||||
const InfraredCommonProtocolSpec protocol_kaseikyo = {
|
||||
.timings =
|
||||
{
|
||||
.preamble_mark = INFRARED_KASEIKYO_PREAMBLE_MARK,
|
||||
.preamble_space = INFRARED_KASEIKYO_PREAMBLE_SPACE,
|
||||
.bit1_mark = INFRARED_KASEIKYO_BIT1_MARK,
|
||||
.bit1_space = INFRARED_KASEIKYO_BIT1_SPACE,
|
||||
.bit0_mark = INFRARED_KASEIKYO_BIT0_MARK,
|
||||
.bit0_space = INFRARED_KASEIKYO_BIT0_SPACE,
|
||||
.preamble_tolerance = INFRARED_KASEIKYO_PREAMBLE_TOLERANCE,
|
||||
.bit_tolerance = INFRARED_KASEIKYO_BIT_TOLERANCE,
|
||||
.silence_time = INFRARED_KASEIKYO_SILENCE,
|
||||
.min_split_time = INFRARED_KASEIKYO_MIN_SPLIT_TIME,
|
||||
},
|
||||
.databit_len[0] = 48,
|
||||
.no_stop_bit = false,
|
||||
.decode = infrared_common_decode_pdwm,
|
||||
.encode = infrared_common_encode_pdwm,
|
||||
.interpret = infrared_decoder_kaseikyo_interpret,
|
||||
.decode_repeat = NULL,
|
||||
.encode_repeat = NULL,
|
||||
};
|
|
@ -1,13 +1,16 @@
|
|||
#include "infrared.h"
|
||||
#include <core/check.h>
|
||||
#include "common/infrared_common_i.h"
|
||||
#include "infrared_protocol_defs_i.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <furi.h>
|
||||
#include "infrared_i.h"
|
||||
#include <furi_hal_infrared.h>
|
||||
#include <string.h>
|
||||
#include <core/check.h>
|
||||
#include <core/common_defines.h>
|
||||
|
||||
#include "nec/infrared_protocol_nec.h"
|
||||
#include "samsung/infrared_protocol_samsung.h"
|
||||
#include "rc5/infrared_protocol_rc5.h"
|
||||
#include "rc6/infrared_protocol_rc6.h"
|
||||
#include "sirc/infrared_protocol_sirc.h"
|
||||
#include "kaseikyo/infrared_protocol_kaseikyo.h"
|
||||
|
||||
typedef struct {
|
||||
InfraredAlloc alloc;
|
||||
|
@ -36,7 +39,7 @@ struct InfraredEncoderHandler {
|
|||
typedef struct {
|
||||
InfraredEncoders encoder;
|
||||
InfraredDecoders decoder;
|
||||
InfraredGetProtocolSpec get_protocol_spec;
|
||||
InfraredGetProtocolVariant get_protocol_variant;
|
||||
} InfraredEncoderDecoder;
|
||||
|
||||
static const InfraredEncoderDecoder infrared_encoder_decoder[] = {
|
||||
|
@ -52,7 +55,7 @@ static const InfraredEncoderDecoder infrared_encoder_decoder[] = {
|
|||
.encode = infrared_encoder_nec_encode,
|
||||
.reset = infrared_encoder_nec_reset,
|
||||
.free = infrared_encoder_nec_free},
|
||||
.get_protocol_spec = infrared_nec_get_spec,
|
||||
.get_protocol_variant = infrared_protocol_nec_get_variant,
|
||||
},
|
||||
{
|
||||
.decoder =
|
||||
|
@ -66,7 +69,7 @@ static const InfraredEncoderDecoder infrared_encoder_decoder[] = {
|
|||
.encode = infrared_encoder_samsung32_encode,
|
||||
.reset = infrared_encoder_samsung32_reset,
|
||||
.free = infrared_encoder_samsung32_free},
|
||||
.get_protocol_spec = infrared_samsung32_get_spec,
|
||||
.get_protocol_variant = infrared_protocol_samsung32_get_variant,
|
||||
},
|
||||
{
|
||||
.decoder =
|
||||
|
@ -80,7 +83,7 @@ static const InfraredEncoderDecoder infrared_encoder_decoder[] = {
|
|||
.encode = infrared_encoder_rc5_encode,
|
||||
.reset = infrared_encoder_rc5_reset,
|
||||
.free = infrared_encoder_rc5_free},
|
||||
.get_protocol_spec = infrared_rc5_get_spec,
|
||||
.get_protocol_variant = infrared_protocol_rc5_get_variant,
|
||||
},
|
||||
{
|
||||
.decoder =
|
||||
|
@ -94,7 +97,7 @@ static const InfraredEncoderDecoder infrared_encoder_decoder[] = {
|
|||
.encode = infrared_encoder_rc6_encode,
|
||||
.reset = infrared_encoder_rc6_reset,
|
||||
.free = infrared_encoder_rc6_free},
|
||||
.get_protocol_spec = infrared_rc6_get_spec,
|
||||
.get_protocol_variant = infrared_protocol_rc6_get_variant,
|
||||
},
|
||||
{
|
||||
.decoder =
|
||||
|
@ -108,7 +111,7 @@ static const InfraredEncoderDecoder infrared_encoder_decoder[] = {
|
|||
.encode = infrared_encoder_sirc_encode,
|
||||
.reset = infrared_encoder_sirc_reset,
|
||||
.free = infrared_encoder_sirc_free},
|
||||
.get_protocol_spec = infrared_sirc_get_spec,
|
||||
.get_protocol_variant = infrared_protocol_sirc_get_variant,
|
||||
},
|
||||
{
|
||||
.decoder =
|
||||
|
@ -122,13 +125,12 @@ static const InfraredEncoderDecoder infrared_encoder_decoder[] = {
|
|||
.encode = infrared_encoder_kaseikyo_encode,
|
||||
.reset = infrared_encoder_kaseikyo_reset,
|
||||
.free = infrared_encoder_kaseikyo_free},
|
||||
.get_protocol_spec = infrared_kaseikyo_get_spec,
|
||||
.get_protocol_variant = infrared_protocol_kaseikyo_get_variant,
|
||||
},
|
||||
};
|
||||
|
||||
static int infrared_find_index_by_protocol(InfraredProtocol protocol);
|
||||
static const InfraredProtocolSpecification*
|
||||
infrared_get_spec_by_protocol(InfraredProtocol protocol);
|
||||
static const InfraredProtocolVariant* infrared_get_variant_by_protocol(InfraredProtocol protocol);
|
||||
|
||||
const InfraredMessage*
|
||||
infrared_decode(InfraredDecoderHandler* handler, bool level, uint32_t duration) {
|
||||
|
@ -224,7 +226,7 @@ void infrared_free_encoder(InfraredEncoderHandler* handler) {
|
|||
|
||||
static int infrared_find_index_by_protocol(InfraredProtocol protocol) {
|
||||
for(size_t i = 0; i < COUNT_OF(infrared_encoder_decoder); ++i) {
|
||||
if(infrared_encoder_decoder[i].get_protocol_spec(protocol)) {
|
||||
if(infrared_encoder_decoder[i].get_protocol_variant(protocol)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
@ -282,34 +284,37 @@ InfraredProtocol infrared_get_protocol_by_name(const char* protocol_name) {
|
|||
return InfraredProtocolUnknown;
|
||||
}
|
||||
|
||||
static const InfraredProtocolSpecification*
|
||||
infrared_get_spec_by_protocol(InfraredProtocol protocol) {
|
||||
static const InfraredProtocolVariant* infrared_get_variant_by_protocol(InfraredProtocol protocol) {
|
||||
int index = infrared_find_index_by_protocol(protocol);
|
||||
const InfraredProtocolSpecification* spec = NULL;
|
||||
const InfraredProtocolVariant* variant = NULL;
|
||||
if(index >= 0) {
|
||||
spec = infrared_encoder_decoder[index].get_protocol_spec(protocol);
|
||||
variant = infrared_encoder_decoder[index].get_protocol_variant(protocol);
|
||||
}
|
||||
|
||||
furi_assert(spec);
|
||||
return spec;
|
||||
furi_assert(variant);
|
||||
return variant;
|
||||
}
|
||||
|
||||
const char* infrared_get_protocol_name(InfraredProtocol protocol) {
|
||||
return infrared_get_spec_by_protocol(protocol)->name;
|
||||
return infrared_get_variant_by_protocol(protocol)->name;
|
||||
}
|
||||
|
||||
uint8_t infrared_get_protocol_address_length(InfraredProtocol protocol) {
|
||||
return infrared_get_spec_by_protocol(protocol)->address_length;
|
||||
return infrared_get_variant_by_protocol(protocol)->address_length;
|
||||
}
|
||||
|
||||
uint8_t infrared_get_protocol_command_length(InfraredProtocol protocol) {
|
||||
return infrared_get_spec_by_protocol(protocol)->command_length;
|
||||
return infrared_get_variant_by_protocol(protocol)->command_length;
|
||||
}
|
||||
|
||||
uint32_t infrared_get_protocol_frequency(InfraredProtocol protocol) {
|
||||
return infrared_get_spec_by_protocol(protocol)->frequency;
|
||||
return infrared_get_variant_by_protocol(protocol)->frequency;
|
||||
}
|
||||
|
||||
float infrared_get_protocol_duty_cycle(InfraredProtocol protocol) {
|
||||
return infrared_get_spec_by_protocol(protocol)->duty_cycle;
|
||||
return infrared_get_variant_by_protocol(protocol)->duty_cycle;
|
||||
}
|
||||
|
||||
size_t infrared_get_protocol_min_repeat_count(InfraredProtocol protocol) {
|
||||
return infrared_get_variant_by_protocol(protocol)->repeat_count;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -201,6 +202,15 @@ uint32_t infrared_get_protocol_frequency(InfraredProtocol protocol);
|
|||
*/
|
||||
float infrared_get_protocol_duty_cycle(InfraredProtocol protocol);
|
||||
|
||||
/**
|
||||
* Get the minimum count of signal repeats for the selected protocol
|
||||
*
|
||||
* \param[in] protocol - protocol to get the repeat count from
|
||||
*
|
||||
* \return repeat count
|
||||
*/
|
||||
size_t infrared_get_protocol_min_repeat_count(InfraredProtocol protocol);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -22,9 +22,10 @@ typedef struct {
|
|||
uint8_t command_length;
|
||||
uint32_t frequency;
|
||||
float duty_cycle;
|
||||
} InfraredProtocolSpecification;
|
||||
size_t repeat_count;
|
||||
} InfraredProtocolVariant;
|
||||
|
||||
typedef const InfraredProtocolSpecification* (*InfraredGetProtocolSpec)(InfraredProtocol protocol);
|
||||
typedef const InfraredProtocolVariant* (*InfraredGetProtocolVariant)(InfraredProtocol protocol);
|
||||
|
||||
typedef void* (*InfraredAlloc)(void);
|
||||
typedef void (*InfraredFree)(void*);
|
||||
|
|
|
@ -1,320 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "infrared.h"
|
||||
#include "common/infrared_common_i.h"
|
||||
|
||||
/***************************************************************************************************
|
||||
* NEC protocol description
|
||||
* https://radioparty.ru/manuals/encyclopedia/213-ircontrol?start=1
|
||||
****************************************************************************************************
|
||||
* Preamble Preamble Pulse Distance/Width Pause Preamble Preamble Stop
|
||||
* mark space Modulation up to period repeat repeat bit
|
||||
* mark space
|
||||
*
|
||||
* 9000 4500 32 bit + stop bit ...110000 9000 2250
|
||||
* __________ _ _ _ _ _ _ _ _ _ _ _ _ _ ___________ _
|
||||
* ____ __________ _ _ _ __ __ __ _ _ __ __ _ _ ________________ ____________ ___
|
||||
*
|
||||
***************************************************************************************************/
|
||||
|
||||
#define INFRARED_NEC_PREAMBLE_MARK 9000
|
||||
#define INFRARED_NEC_PREAMBLE_SPACE 4500
|
||||
#define INFRARED_NEC_BIT1_MARK 560
|
||||
#define INFRARED_NEC_BIT1_SPACE 1690
|
||||
#define INFRARED_NEC_BIT0_MARK 560
|
||||
#define INFRARED_NEC_BIT0_SPACE 560
|
||||
#define INFRARED_NEC_REPEAT_PERIOD 110000
|
||||
#define INFRARED_NEC_SILENCE INFRARED_NEC_REPEAT_PERIOD
|
||||
#define INFRARED_NEC_MIN_SPLIT_TIME INFRARED_NEC_REPEAT_PAUSE_MIN
|
||||
#define INFRARED_NEC_REPEAT_PAUSE_MIN 4000
|
||||
#define INFRARED_NEC_REPEAT_PAUSE_MAX 150000
|
||||
#define INFRARED_NEC_REPEAT_MARK 9000
|
||||
#define INFRARED_NEC_REPEAT_SPACE 2250
|
||||
#define INFRARED_NEC_PREAMBLE_TOLERANCE 200 // us
|
||||
#define INFRARED_NEC_BIT_TOLERANCE 120 // us
|
||||
|
||||
void* infrared_decoder_nec_alloc(void);
|
||||
void infrared_decoder_nec_reset(void* decoder);
|
||||
void infrared_decoder_nec_free(void* decoder);
|
||||
InfraredMessage* infrared_decoder_nec_check_ready(void* decoder);
|
||||
InfraredMessage* infrared_decoder_nec_decode(void* decoder, bool level, uint32_t duration);
|
||||
void* infrared_encoder_nec_alloc(void);
|
||||
InfraredStatus infrared_encoder_nec_encode(void* encoder_ptr, uint32_t* duration, bool* level);
|
||||
void infrared_encoder_nec_reset(void* encoder_ptr, const InfraredMessage* message);
|
||||
void infrared_encoder_nec_free(void* encoder_ptr);
|
||||
bool infrared_decoder_nec_interpret(InfraredCommonDecoder* decoder);
|
||||
InfraredStatus infrared_decoder_nec_decode_repeat(InfraredCommonDecoder* decoder);
|
||||
InfraredStatus infrared_encoder_nec_encode_repeat(
|
||||
InfraredCommonEncoder* encoder,
|
||||
uint32_t* duration,
|
||||
bool* level);
|
||||
const InfraredProtocolSpecification* infrared_nec_get_spec(InfraredProtocol protocol);
|
||||
|
||||
extern const InfraredCommonProtocolSpec protocol_nec;
|
||||
|
||||
/***************************************************************************************************
|
||||
* SAMSUNG32 protocol description
|
||||
* https://www.mikrocontroller.net/articles/IRMP_-_english#SAMSUNG
|
||||
****************************************************************************************************
|
||||
* Preamble Preamble Pulse Distance/Width Pause Preamble Preamble Bit1 Stop
|
||||
* mark space Modulation repeat repeat bit
|
||||
* mark space
|
||||
*
|
||||
* 4500 4500 32 bit + stop bit 40000/100000 4500 4500
|
||||
* __________ _ _ _ _ _ _ _ _ _ _ _ ___________ _ _
|
||||
* _ __________ __ _ __ __ __ _ _ __ __ _ ________________ ____________ ____ ___
|
||||
*
|
||||
***************************************************************************************************/
|
||||
|
||||
#define INFRARED_SAMSUNG_PREAMBLE_MARK 4500
|
||||
#define INFRARED_SAMSUNG_PREAMBLE_SPACE 4500
|
||||
#define INFRARED_SAMSUNG_BIT1_MARK 550
|
||||
#define INFRARED_SAMSUNG_BIT1_SPACE 1650
|
||||
#define INFRARED_SAMSUNG_BIT0_MARK 550
|
||||
#define INFRARED_SAMSUNG_BIT0_SPACE 550
|
||||
#define INFRARED_SAMSUNG_REPEAT_PAUSE_MIN 30000
|
||||
#define INFRARED_SAMSUNG_REPEAT_PAUSE1 46000
|
||||
#define INFRARED_SAMSUNG_REPEAT_PAUSE2 97000
|
||||
/* Samsung silence have to be greater than REPEAT MAX
|
||||
* otherwise there can be problems during unit tests parsing
|
||||
* of some data. Real tolerances we don't know, but in real life
|
||||
* silence time should be greater than max repeat time. This is
|
||||
* because of similar preambule timings for repeat and first messages. */
|
||||
#define INFRARED_SAMSUNG_MIN_SPLIT_TIME 5000
|
||||
#define INFRARED_SAMSUNG_SILENCE 145000
|
||||
#define INFRARED_SAMSUNG_REPEAT_PAUSE_MAX 140000
|
||||
#define INFRARED_SAMSUNG_REPEAT_MARK 4500
|
||||
#define INFRARED_SAMSUNG_REPEAT_SPACE 4500
|
||||
#define INFRARED_SAMSUNG_PREAMBLE_TOLERANCE 200 // us
|
||||
#define INFRARED_SAMSUNG_BIT_TOLERANCE 120 // us
|
||||
|
||||
void* infrared_decoder_samsung32_alloc(void);
|
||||
void infrared_decoder_samsung32_reset(void* decoder);
|
||||
void infrared_decoder_samsung32_free(void* decoder);
|
||||
InfraredMessage* infrared_decoder_samsung32_check_ready(void* ctx);
|
||||
InfraredMessage* infrared_decoder_samsung32_decode(void* decoder, bool level, uint32_t duration);
|
||||
InfraredStatus
|
||||
infrared_encoder_samsung32_encode(void* encoder_ptr, uint32_t* duration, bool* level);
|
||||
void infrared_encoder_samsung32_reset(void* encoder_ptr, const InfraredMessage* message);
|
||||
void* infrared_encoder_samsung32_alloc(void);
|
||||
void infrared_encoder_samsung32_free(void* encoder_ptr);
|
||||
bool infrared_decoder_samsung32_interpret(InfraredCommonDecoder* decoder);
|
||||
InfraredStatus infrared_decoder_samsung32_decode_repeat(InfraredCommonDecoder* decoder);
|
||||
InfraredStatus infrared_encoder_samsung32_encode_repeat(
|
||||
InfraredCommonEncoder* encoder,
|
||||
uint32_t* duration,
|
||||
bool* level);
|
||||
const InfraredProtocolSpecification* infrared_samsung32_get_spec(InfraredProtocol protocol);
|
||||
|
||||
extern const InfraredCommonProtocolSpec protocol_samsung32;
|
||||
|
||||
/***************************************************************************************************
|
||||
* RC6 protocol description
|
||||
* https://www.mikrocontroller.net/articles/IRMP_-_english#RC6_.2B_RC6A
|
||||
****************************************************************************************************
|
||||
* Preamble Manchester/biphase Silence
|
||||
* mark/space Modulation
|
||||
*
|
||||
* 2666 889 444/888 - bit (x2 for toggle bit) 2666
|
||||
*
|
||||
* ________ __ __ __ __ ____ __ __ __ __ __ __ __ __
|
||||
* _ _________ ____ __ __ ____ __ __ __ __ __ __ __ __ _______________
|
||||
* | 1 | 0 | 0 | 0 | 0 | ... | ... | |
|
||||
* s m2 m1 m0 T address (MSB) command (MSB)
|
||||
*
|
||||
* s - start bit (always 1)
|
||||
* m0-2 - mode (000 for RC6)
|
||||
* T - toggle bit, twice longer
|
||||
* address - 8 bit
|
||||
* command - 8 bit
|
||||
***************************************************************************************************/
|
||||
|
||||
#define INFRARED_RC6_CARRIER_FREQUENCY 36000
|
||||
#define INFRARED_RC6_DUTY_CYCLE 0.33
|
||||
|
||||
#define INFRARED_RC6_PREAMBLE_MARK 2666
|
||||
#define INFRARED_RC6_PREAMBLE_SPACE 889
|
||||
#define INFRARED_RC6_BIT 444 // half of time-quant for 1 bit
|
||||
#define INFRARED_RC6_PREAMBLE_TOLERANCE 200 // us
|
||||
#define INFRARED_RC6_BIT_TOLERANCE 120 // us
|
||||
/* protocol allows 2700 silence, but it is hard to send 1 message without repeat */
|
||||
#define INFRARED_RC6_SILENCE (2700 * 10)
|
||||
#define INFRARED_RC6_MIN_SPLIT_TIME 2700
|
||||
|
||||
void* infrared_decoder_rc6_alloc(void);
|
||||
void infrared_decoder_rc6_reset(void* decoder);
|
||||
void infrared_decoder_rc6_free(void* decoder);
|
||||
InfraredMessage* infrared_decoder_rc6_check_ready(void* ctx);
|
||||
InfraredMessage* infrared_decoder_rc6_decode(void* decoder, bool level, uint32_t duration);
|
||||
void* infrared_encoder_rc6_alloc(void);
|
||||
void infrared_encoder_rc6_reset(void* encoder_ptr, const InfraredMessage* message);
|
||||
void infrared_encoder_rc6_free(void* decoder);
|
||||
InfraredStatus infrared_encoder_rc6_encode(void* encoder_ptr, uint32_t* duration, bool* polarity);
|
||||
bool infrared_decoder_rc6_interpret(InfraredCommonDecoder* decoder);
|
||||
InfraredStatus infrared_decoder_rc6_decode_manchester(
|
||||
InfraredCommonDecoder* decoder,
|
||||
bool level,
|
||||
uint32_t timing);
|
||||
InfraredStatus infrared_encoder_rc6_encode_manchester(
|
||||
InfraredCommonEncoder* encoder_ptr,
|
||||
uint32_t* duration,
|
||||
bool* polarity);
|
||||
const InfraredProtocolSpecification* infrared_rc6_get_spec(InfraredProtocol protocol);
|
||||
|
||||
extern const InfraredCommonProtocolSpec protocol_rc6;
|
||||
|
||||
/***************************************************************************************************
|
||||
* RC5 protocol description
|
||||
* https://www.mikrocontroller.net/articles/IRMP_-_english#RC5_.2B_RC5X
|
||||
****************************************************************************************************
|
||||
* Manchester/biphase
|
||||
* Modulation
|
||||
*
|
||||
* 888/1776 - bit (x2 for toggle bit)
|
||||
*
|
||||
* __ ____ __ __ __ __ __ __ __ __
|
||||
* __ __ ____ __ __ __ __ __ __ __ _
|
||||
* | 1 | 1 | 0 | ... | ... |
|
||||
* s si T address (MSB) command (MSB)
|
||||
*
|
||||
* Note: manchester starts from space timing, so it have to be handled properly
|
||||
* s - start bit (always 1)
|
||||
* si - RC5: start bit (always 1), RC5X - 7-th bit of address (in our case always 0)
|
||||
* T - toggle bit, change it's value every button press
|
||||
* address - 5 bit
|
||||
* command - 6/7 bit
|
||||
***************************************************************************************************/
|
||||
|
||||
#define INFRARED_RC5_CARRIER_FREQUENCY 36000
|
||||
#define INFRARED_RC5_DUTY_CYCLE 0.33
|
||||
|
||||
#define INFRARED_RC5_PREAMBLE_MARK 0
|
||||
#define INFRARED_RC5_PREAMBLE_SPACE 0
|
||||
#define INFRARED_RC5_BIT 888 // half of time-quant for 1 bit
|
||||
#define INFRARED_RC5_PREAMBLE_TOLERANCE 200 // us
|
||||
#define INFRARED_RC5_BIT_TOLERANCE 120 // us
|
||||
/* protocol allows 2700 silence, but it is hard to send 1 message without repeat */
|
||||
#define INFRARED_RC5_SILENCE (2700 * 10)
|
||||
#define INFRARED_RC5_MIN_SPLIT_TIME 2700
|
||||
|
||||
void* infrared_decoder_rc5_alloc(void);
|
||||
void infrared_decoder_rc5_reset(void* decoder);
|
||||
void infrared_decoder_rc5_free(void* decoder);
|
||||
InfraredMessage* infrared_decoder_rc5_check_ready(void* ctx);
|
||||
InfraredMessage* infrared_decoder_rc5_decode(void* decoder, bool level, uint32_t duration);
|
||||
void* infrared_encoder_rc5_alloc(void);
|
||||
void infrared_encoder_rc5_reset(void* encoder_ptr, const InfraredMessage* message);
|
||||
void infrared_encoder_rc5_free(void* decoder);
|
||||
InfraredStatus infrared_encoder_rc5_encode(void* encoder_ptr, uint32_t* duration, bool* polarity);
|
||||
bool infrared_decoder_rc5_interpret(InfraredCommonDecoder* decoder);
|
||||
const InfraredProtocolSpecification* infrared_rc5_get_spec(InfraredProtocol protocol);
|
||||
|
||||
extern const InfraredCommonProtocolSpec protocol_rc5;
|
||||
|
||||
/***************************************************************************************************
|
||||
* Sony SIRC protocol description
|
||||
* https://www.sbprojects.net/knowledge/ir/sirc.php
|
||||
* http://picprojects.org.uk/
|
||||
****************************************************************************************************
|
||||
* Preamble Preamble Pulse Width Modulation Pause Entirely repeat
|
||||
* mark space up to period message..
|
||||
*
|
||||
* 2400 600 12/15/20 bits (600,1200) ...45000 2400 600
|
||||
* __________ _ _ _ _ _ _ _ _ _ _ _ _ _ __________ _ _
|
||||
* ____ __________ _ _ _ __ __ __ _ _ __ __ _ _ ____________________ __________ _
|
||||
* | command | address |
|
||||
* SIRC | 7b LSB | 5b LSB |
|
||||
* SIRC15 | 7b LSB | 8b LSB |
|
||||
* SIRC20 | 7b LSB | 13b LSB |
|
||||
*
|
||||
* No way to determine either next message is repeat or not,
|
||||
* so recognize only fact message received. Sony remotes always send at least 3 messages.
|
||||
* Assume 8 last extended bits for SIRC20 are address bits.
|
||||
***************************************************************************************************/
|
||||
|
||||
#define INFRARED_SIRC_CARRIER_FREQUENCY 40000
|
||||
#define INFRARED_SIRC_DUTY_CYCLE 0.33
|
||||
#define INFRARED_SIRC_PREAMBLE_MARK 2400
|
||||
#define INFRARED_SIRC_PREAMBLE_SPACE 600
|
||||
#define INFRARED_SIRC_BIT1_MARK 1200
|
||||
#define INFRARED_SIRC_BIT1_SPACE 600
|
||||
#define INFRARED_SIRC_BIT0_MARK 600
|
||||
#define INFRARED_SIRC_BIT0_SPACE 600
|
||||
#define INFRARED_SIRC_PREAMBLE_TOLERANCE 200 // us
|
||||
#define INFRARED_SIRC_BIT_TOLERANCE 120 // us
|
||||
#define INFRARED_SIRC_SILENCE 10000
|
||||
#define INFRARED_SIRC_MIN_SPLIT_TIME (INFRARED_SIRC_SILENCE - 1000)
|
||||
#define INFRARED_SIRC_REPEAT_PERIOD 45000
|
||||
|
||||
void* infrared_decoder_sirc_alloc(void);
|
||||
void infrared_decoder_sirc_reset(void* decoder);
|
||||
InfraredMessage* infrared_decoder_sirc_check_ready(void* decoder);
|
||||
uint32_t infrared_decoder_sirc_get_timeout(void* decoder);
|
||||
void infrared_decoder_sirc_free(void* decoder);
|
||||
InfraredMessage* infrared_decoder_sirc_decode(void* decoder, bool level, uint32_t duration);
|
||||
void* infrared_encoder_sirc_alloc(void);
|
||||
void infrared_encoder_sirc_reset(void* encoder_ptr, const InfraredMessage* message);
|
||||
void infrared_encoder_sirc_free(void* decoder);
|
||||
InfraredStatus infrared_encoder_sirc_encode(void* encoder_ptr, uint32_t* duration, bool* polarity);
|
||||
bool infrared_decoder_sirc_interpret(InfraredCommonDecoder* decoder);
|
||||
const InfraredProtocolSpecification* infrared_sirc_get_spec(InfraredProtocol protocol);
|
||||
InfraredStatus infrared_encoder_sirc_encode_repeat(
|
||||
InfraredCommonEncoder* encoder,
|
||||
uint32_t* duration,
|
||||
bool* level);
|
||||
|
||||
extern const InfraredCommonProtocolSpec protocol_sirc;
|
||||
|
||||
/***************************************************************************************************
|
||||
* Kaseikyo protocol description
|
||||
* https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/ir_Kaseikyo.hpp
|
||||
****************************************************************************************************
|
||||
* Preamble Preamble Pulse Distance/Width Pause Preamble Preamble
|
||||
* mark space Modulation up to period repeat repeat
|
||||
* mark space
|
||||
*
|
||||
* 3360 1665 48 bit ...130000 3456 1728
|
||||
* __________ _ _ _ _ _ _ _ _ _ _ _ _ _ ___________
|
||||
* ____ __________ _ _ _ __ __ __ _ _ __ __ _ _ ________________ ___________
|
||||
*
|
||||
***************************************************************************************************/
|
||||
|
||||
#define INFRARED_KASEIKYO_UNIT 432
|
||||
#define INFRARED_KASEIKYO_PREAMBLE_MARK (8 * INFRARED_KASEIKYO_UNIT)
|
||||
#define INFRARED_KASEIKYO_PREAMBLE_SPACE (4 * INFRARED_KASEIKYO_UNIT)
|
||||
#define INFRARED_KASEIKYO_BIT1_MARK INFRARED_KASEIKYO_UNIT
|
||||
#define INFRARED_KASEIKYO_BIT1_SPACE (3 * INFRARED_KASEIKYO_UNIT)
|
||||
#define INFRARED_KASEIKYO_BIT0_MARK INFRARED_KASEIKYO_UNIT
|
||||
#define INFRARED_KASEIKYO_BIT0_SPACE INFRARED_KASEIKYO_UNIT
|
||||
#define INFRARED_KASEIKYO_REPEAT_PERIOD 130000
|
||||
#define INFRARED_KASEIKYO_SILENCE INFRARED_KASEIKYO_REPEAT_PERIOD
|
||||
#define INFRARED_KASEIKYO_MIN_SPLIT_TIME INFRARED_KASEIKYO_REPEAT_PAUSE_MIN
|
||||
#define INFRARED_KASEIKYO_REPEAT_PAUSE_MIN 4000
|
||||
#define INFRARED_KASEIKYO_REPEAT_PAUSE_MAX 150000
|
||||
#define INFRARED_KASEIKYO_REPEAT_MARK INFRARED_KASEIKYO_PREAMBLE_MARK
|
||||
#define INFRARED_KASEIKYO_REPEAT_SPACE (INFRARED_KASEIKYO_REPEAT_PERIOD - 56000)
|
||||
#define INFRARED_KASEIKYO_PREAMBLE_TOLERANCE 200 // us
|
||||
#define INFRARED_KASEIKYO_BIT_TOLERANCE 120 // us
|
||||
|
||||
void* infrared_decoder_kaseikyo_alloc(void);
|
||||
void infrared_decoder_kaseikyo_reset(void* decoder);
|
||||
void infrared_decoder_kaseikyo_free(void* decoder);
|
||||
InfraredMessage* infrared_decoder_kaseikyo_check_ready(void* decoder);
|
||||
InfraredMessage* infrared_decoder_kaseikyo_decode(void* decoder, bool level, uint32_t duration);
|
||||
void* infrared_encoder_kaseikyo_alloc(void);
|
||||
InfraredStatus
|
||||
infrared_encoder_kaseikyo_encode(void* encoder_ptr, uint32_t* duration, bool* level);
|
||||
void infrared_encoder_kaseikyo_reset(void* encoder_ptr, const InfraredMessage* message);
|
||||
void infrared_encoder_kaseikyo_free(void* encoder_ptr);
|
||||
bool infrared_decoder_kaseikyo_interpret(InfraredCommonDecoder* decoder);
|
||||
InfraredStatus infrared_decoder_kaseikyo_decode_repeat(InfraredCommonDecoder* decoder);
|
||||
InfraredStatus infrared_encoder_kaseikyo_encode_repeat(
|
||||
InfraredCommonEncoder* encoder,
|
||||
uint32_t* duration,
|
||||
bool* level);
|
||||
const InfraredProtocolSpecification* infrared_kaseikyo_get_spec(InfraredProtocol protocol);
|
||||
|
||||
extern const InfraredCommonProtocolSpec protocol_kaseikyo;
|
|
@ -1,9 +1,5 @@
|
|||
#include "infrared.h"
|
||||
#include "infrared_protocol_defs_i.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <furi.h>
|
||||
#include "../infrared_i.h"
|
||||
#include "infrared_protocol_kaseikyo_i.h"
|
||||
#include <core/check.h>
|
||||
|
||||
InfraredMessage* infrared_decoder_kaseikyo_check_ready(void* ctx) {
|
||||
return infrared_common_decoder_check_ready(ctx);
|
||||
|
@ -38,7 +34,7 @@ bool infrared_decoder_kaseikyo_interpret(InfraredCommonDecoder* decoder) {
|
|||
}
|
||||
|
||||
void* infrared_decoder_kaseikyo_alloc(void) {
|
||||
return infrared_common_decoder_alloc(&protocol_kaseikyo);
|
||||
return infrared_common_decoder_alloc(&infrared_protocol_kaseikyo);
|
||||
}
|
||||
|
||||
InfraredMessage* infrared_decoder_kaseikyo_decode(void* decoder, bool level, uint32_t duration) {
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
#include "infrared_protocol_kaseikyo_i.h"
|
||||
#include <core/check.h>
|
||||
#include "common/infrared_common_i.h"
|
||||
#include <stdint.h>
|
||||
#include "../infrared_i.h"
|
||||
#include "infrared_protocol_defs_i.h"
|
||||
#include <furi.h>
|
||||
|
||||
void infrared_encoder_kaseikyo_reset(void* encoder_ptr, const InfraredMessage* message) {
|
||||
furi_assert(encoder_ptr);
|
||||
|
@ -32,7 +28,7 @@ void infrared_encoder_kaseikyo_reset(void* encoder_ptr, const InfraredMessage* m
|
|||
}
|
||||
|
||||
void* infrared_encoder_kaseikyo_alloc(void) {
|
||||
return infrared_common_encoder_alloc(&protocol_kaseikyo);
|
||||
return infrared_common_encoder_alloc(&infrared_protocol_kaseikyo);
|
||||
}
|
||||
|
||||
void infrared_encoder_kaseikyo_free(void* encoder_ptr) {
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
#include "../infrared_i.h"
|
||||
#include "infrared_protocol_defs_i.h"
|
||||
|
||||
static const InfraredProtocolSpecification infrared_kaseikyo_protocol_specification = {
|
||||
.name = "Kaseikyo",
|
||||
.address_length = 26,
|
||||
.command_length = 10,
|
||||
.frequency = INFRARED_COMMON_CARRIER_FREQUENCY,
|
||||
.duty_cycle = INFRARED_COMMON_DUTY_CYCLE,
|
||||
};
|
||||
|
||||
const InfraredProtocolSpecification* infrared_kaseikyo_get_spec(InfraredProtocol protocol) {
|
||||
if(protocol == InfraredProtocolKaseikyo)
|
||||
return &infrared_kaseikyo_protocol_specification;
|
||||
else
|
||||
return NULL;
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
#include "infrared_protocol_kaseikyo_i.h"
|
||||
|
||||
const InfraredCommonProtocolSpec infrared_protocol_kaseikyo = {
|
||||
.timings =
|
||||
{
|
||||
.preamble_mark = INFRARED_KASEIKYO_PREAMBLE_MARK,
|
||||
.preamble_space = INFRARED_KASEIKYO_PREAMBLE_SPACE,
|
||||
.bit1_mark = INFRARED_KASEIKYO_BIT1_MARK,
|
||||
.bit1_space = INFRARED_KASEIKYO_BIT1_SPACE,
|
||||
.bit0_mark = INFRARED_KASEIKYO_BIT0_MARK,
|
||||
.bit0_space = INFRARED_KASEIKYO_BIT0_SPACE,
|
||||
.preamble_tolerance = INFRARED_KASEIKYO_PREAMBLE_TOLERANCE,
|
||||
.bit_tolerance = INFRARED_KASEIKYO_BIT_TOLERANCE,
|
||||
.silence_time = INFRARED_KASEIKYO_SILENCE,
|
||||
.min_split_time = INFRARED_KASEIKYO_MIN_SPLIT_TIME,
|
||||
},
|
||||
.databit_len[0] = 48,
|
||||
.no_stop_bit = false,
|
||||
.decode = infrared_common_decode_pdwm,
|
||||
.encode = infrared_common_encode_pdwm,
|
||||
.interpret = infrared_decoder_kaseikyo_interpret,
|
||||
.decode_repeat = NULL,
|
||||
.encode_repeat = NULL,
|
||||
};
|
||||
|
||||
static const InfraredProtocolVariant infrared_protocol_variant_kaseikyo = {
|
||||
.name = "Kaseikyo",
|
||||
.address_length = 26,
|
||||
.command_length = 10,
|
||||
.frequency = INFRARED_COMMON_CARRIER_FREQUENCY,
|
||||
.duty_cycle = INFRARED_COMMON_DUTY_CYCLE,
|
||||
.repeat_count = INFRARED_KASEIKYO_REPEAT_COUNT_MIN,
|
||||
};
|
||||
|
||||
const InfraredProtocolVariant* infrared_protocol_kaseikyo_get_variant(InfraredProtocol protocol) {
|
||||
if(protocol == InfraredProtocolKaseikyo)
|
||||
return &infrared_protocol_variant_kaseikyo;
|
||||
else
|
||||
return NULL;
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
#pragma once
|
||||
|
||||
#include "../infrared_i.h"
|
||||
|
||||
/***************************************************************************************************
|
||||
* Kaseikyo protocol description
|
||||
* https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/ir_Kaseikyo.hpp
|
||||
****************************************************************************************************
|
||||
* Preamble Preamble Pulse Distance/Width Pause Preamble Preamble
|
||||
* mark space Modulation up to period repeat repeat
|
||||
* mark space
|
||||
*
|
||||
* 3360 1665 48 bit ...130000 3456 1728
|
||||
* __________ _ _ _ _ _ _ _ _ _ _ _ _ _ ___________
|
||||
* ____ __________ _ _ _ __ __ __ _ _ __ __ _ _ ________________ ___________
|
||||
*
|
||||
***************************************************************************************************/
|
||||
|
||||
void* infrared_decoder_kaseikyo_alloc(void);
|
||||
void infrared_decoder_kaseikyo_reset(void* decoder);
|
||||
void infrared_decoder_kaseikyo_free(void* decoder);
|
||||
InfraredMessage* infrared_decoder_kaseikyo_check_ready(void* decoder);
|
||||
InfraredMessage* infrared_decoder_kaseikyo_decode(void* decoder, bool level, uint32_t duration);
|
||||
|
||||
void* infrared_encoder_kaseikyo_alloc(void);
|
||||
InfraredStatus
|
||||
infrared_encoder_kaseikyo_encode(void* encoder_ptr, uint32_t* duration, bool* level);
|
||||
void infrared_encoder_kaseikyo_reset(void* encoder_ptr, const InfraredMessage* message);
|
||||
void infrared_encoder_kaseikyo_free(void* encoder_ptr);
|
||||
|
||||
const InfraredProtocolVariant* infrared_protocol_kaseikyo_get_variant(InfraredProtocol protocol);
|
|
@ -0,0 +1,30 @@
|
|||
#pragma once
|
||||
|
||||
#include "../common/infrared_common_i.h"
|
||||
|
||||
#define INFRARED_KASEIKYO_UNIT 432
|
||||
#define INFRARED_KASEIKYO_PREAMBLE_MARK (8 * INFRARED_KASEIKYO_UNIT)
|
||||
#define INFRARED_KASEIKYO_PREAMBLE_SPACE (4 * INFRARED_KASEIKYO_UNIT)
|
||||
#define INFRARED_KASEIKYO_BIT1_MARK INFRARED_KASEIKYO_UNIT
|
||||
#define INFRARED_KASEIKYO_BIT1_SPACE (3 * INFRARED_KASEIKYO_UNIT)
|
||||
#define INFRARED_KASEIKYO_BIT0_MARK INFRARED_KASEIKYO_UNIT
|
||||
#define INFRARED_KASEIKYO_BIT0_SPACE INFRARED_KASEIKYO_UNIT
|
||||
#define INFRARED_KASEIKYO_REPEAT_PERIOD 130000
|
||||
#define INFRARED_KASEIKYO_SILENCE INFRARED_KASEIKYO_REPEAT_PERIOD
|
||||
#define INFRARED_KASEIKYO_MIN_SPLIT_TIME INFRARED_KASEIKYO_REPEAT_PAUSE_MIN
|
||||
#define INFRARED_KASEIKYO_REPEAT_PAUSE_MIN 4000
|
||||
#define INFRARED_KASEIKYO_REPEAT_PAUSE_MAX 150000
|
||||
#define INFRARED_KASEIKYO_REPEAT_COUNT_MIN 1
|
||||
#define INFRARED_KASEIKYO_REPEAT_MARK INFRARED_KASEIKYO_PREAMBLE_MARK
|
||||
#define INFRARED_KASEIKYO_REPEAT_SPACE (INFRARED_KASEIKYO_REPEAT_PERIOD - 56000)
|
||||
#define INFRARED_KASEIKYO_PREAMBLE_TOLERANCE 200 // us
|
||||
#define INFRARED_KASEIKYO_BIT_TOLERANCE 120 // us
|
||||
|
||||
extern const InfraredCommonProtocolSpec infrared_protocol_kaseikyo;
|
||||
|
||||
bool infrared_decoder_kaseikyo_interpret(InfraredCommonDecoder* decoder);
|
||||
InfraredStatus infrared_decoder_kaseikyo_decode_repeat(InfraredCommonDecoder* decoder);
|
||||
InfraredStatus infrared_encoder_kaseikyo_encode_repeat(
|
||||
InfraredCommonEncoder* encoder,
|
||||
uint32_t* duration,
|
||||
bool* level);
|
|
@ -1,10 +1,5 @@
|
|||
#include "common/infrared_common_i.h"
|
||||
#include "infrared.h"
|
||||
#include "infrared_protocol_defs_i.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <furi.h>
|
||||
#include "../infrared_i.h"
|
||||
#include "infrared_protocol_nec_i.h"
|
||||
#include <core/check.h>
|
||||
|
||||
InfraredMessage* infrared_decoder_nec_check_ready(void* ctx) {
|
||||
return infrared_common_decoder_check_ready(ctx);
|
||||
|
@ -86,7 +81,7 @@ InfraredStatus infrared_decoder_nec_decode_repeat(InfraredCommonDecoder* decoder
|
|||
}
|
||||
|
||||
void* infrared_decoder_nec_alloc(void) {
|
||||
return infrared_common_decoder_alloc(&protocol_nec);
|
||||
return infrared_common_decoder_alloc(&infrared_protocol_nec);
|
||||
}
|
||||
|
||||
InfraredMessage* infrared_decoder_nec_decode(void* decoder, bool level, uint32_t duration) {
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
#include "infrared_protocol_nec_i.h"
|
||||
|
||||
#include <core/core_defines.h>
|
||||
#include <core/check.h>
|
||||
#include "infrared.h"
|
||||
#include "common/infrared_common_i.h"
|
||||
#include <stdint.h>
|
||||
#include "../infrared_i.h"
|
||||
#include "infrared_protocol_defs_i.h"
|
||||
#include <furi.h>
|
||||
|
||||
static const uint32_t repeat_timings[] = {
|
||||
INFRARED_NEC_REPEAT_PERIOD - INFRARED_NEC_REPEAT_MARK - INFRARED_NEC_REPEAT_SPACE -
|
||||
|
@ -81,7 +78,7 @@ InfraredStatus infrared_encoder_nec_encode_repeat(
|
|||
}
|
||||
|
||||
void* infrared_encoder_nec_alloc(void) {
|
||||
return infrared_common_encoder_alloc(&protocol_nec);
|
||||
return infrared_common_encoder_alloc(&infrared_protocol_nec);
|
||||
}
|
||||
|
||||
void infrared_encoder_nec_free(void* encoder_ptr) {
|
||||
|
|
|
@ -1,47 +0,0 @@
|
|||
#include "../infrared_i.h"
|
||||
#include "infrared_protocol_defs_i.h"
|
||||
|
||||
static const InfraredProtocolSpecification infrared_nec_protocol_specification = {
|
||||
.name = "NEC",
|
||||
.address_length = 8,
|
||||
.command_length = 8,
|
||||
.frequency = INFRARED_COMMON_CARRIER_FREQUENCY,
|
||||
.duty_cycle = INFRARED_COMMON_DUTY_CYCLE,
|
||||
};
|
||||
|
||||
static const InfraredProtocolSpecification infrared_necext_protocol_specification = {
|
||||
.name = "NECext",
|
||||
.address_length = 16,
|
||||
.command_length = 16,
|
||||
.frequency = INFRARED_COMMON_CARRIER_FREQUENCY,
|
||||
.duty_cycle = INFRARED_COMMON_DUTY_CYCLE,
|
||||
};
|
||||
|
||||
static const InfraredProtocolSpecification infrared_nec42_protocol_specification = {
|
||||
.name = "NEC42",
|
||||
.address_length = 13,
|
||||
.command_length = 8,
|
||||
.frequency = INFRARED_COMMON_CARRIER_FREQUENCY,
|
||||
.duty_cycle = INFRARED_COMMON_DUTY_CYCLE,
|
||||
};
|
||||
|
||||
static const InfraredProtocolSpecification infrared_nec42ext_protocol_specification = {
|
||||
.name = "NEC42ext",
|
||||
.address_length = 26,
|
||||
.command_length = 16,
|
||||
.frequency = INFRARED_COMMON_CARRIER_FREQUENCY,
|
||||
.duty_cycle = INFRARED_COMMON_DUTY_CYCLE,
|
||||
};
|
||||
|
||||
const InfraredProtocolSpecification* infrared_nec_get_spec(InfraredProtocol protocol) {
|
||||
if(protocol == InfraredProtocolNEC)
|
||||
return &infrared_nec_protocol_specification;
|
||||
else if(protocol == InfraredProtocolNECext)
|
||||
return &infrared_necext_protocol_specification;
|
||||
else if(protocol == InfraredProtocolNEC42)
|
||||
return &infrared_nec42_protocol_specification;
|
||||
else if(protocol == InfraredProtocolNEC42ext)
|
||||
return &infrared_nec42ext_protocol_specification;
|
||||
else
|
||||
return NULL;
|
||||
}
|
74
lib/infrared/encoder_decoder/nec/infrared_protocol_nec.c
Normal file
74
lib/infrared/encoder_decoder/nec/infrared_protocol_nec.c
Normal file
|
@ -0,0 +1,74 @@
|
|||
#include "infrared_protocol_nec_i.h"
|
||||
|
||||
const InfraredCommonProtocolSpec infrared_protocol_nec = {
|
||||
.timings =
|
||||
{
|
||||
.preamble_mark = INFRARED_NEC_PREAMBLE_MARK,
|
||||
.preamble_space = INFRARED_NEC_PREAMBLE_SPACE,
|
||||
.bit1_mark = INFRARED_NEC_BIT1_MARK,
|
||||
.bit1_space = INFRARED_NEC_BIT1_SPACE,
|
||||
.bit0_mark = INFRARED_NEC_BIT0_MARK,
|
||||
.bit0_space = INFRARED_NEC_BIT0_SPACE,
|
||||
.preamble_tolerance = INFRARED_NEC_PREAMBLE_TOLERANCE,
|
||||
.bit_tolerance = INFRARED_NEC_BIT_TOLERANCE,
|
||||
.silence_time = INFRARED_NEC_SILENCE,
|
||||
.min_split_time = INFRARED_NEC_MIN_SPLIT_TIME,
|
||||
},
|
||||
.databit_len[0] = 42,
|
||||
.databit_len[1] = 32,
|
||||
.no_stop_bit = false,
|
||||
.decode = infrared_common_decode_pdwm,
|
||||
.encode = infrared_common_encode_pdwm,
|
||||
.interpret = infrared_decoder_nec_interpret,
|
||||
.decode_repeat = infrared_decoder_nec_decode_repeat,
|
||||
.encode_repeat = infrared_encoder_nec_encode_repeat,
|
||||
};
|
||||
|
||||
static const InfraredProtocolVariant infrared_protocol_variant_nec = {
|
||||
.name = "NEC",
|
||||
.address_length = 8,
|
||||
.command_length = 8,
|
||||
.frequency = INFRARED_COMMON_CARRIER_FREQUENCY,
|
||||
.duty_cycle = INFRARED_COMMON_DUTY_CYCLE,
|
||||
.repeat_count = INFRARED_NEC_REPEAT_COUNT_MIN,
|
||||
};
|
||||
|
||||
static const InfraredProtocolVariant infrared_protocol_variant_necext = {
|
||||
.name = "NECext",
|
||||
.address_length = 16,
|
||||
.command_length = 16,
|
||||
.frequency = INFRARED_COMMON_CARRIER_FREQUENCY,
|
||||
.duty_cycle = INFRARED_COMMON_DUTY_CYCLE,
|
||||
.repeat_count = INFRARED_NEC_REPEAT_COUNT_MIN,
|
||||
};
|
||||
|
||||
static const InfraredProtocolVariant infrared_protocol_variant_nec42 = {
|
||||
.name = "NEC42",
|
||||
.address_length = 13,
|
||||
.command_length = 8,
|
||||
.frequency = INFRARED_COMMON_CARRIER_FREQUENCY,
|
||||
.duty_cycle = INFRARED_COMMON_DUTY_CYCLE,
|
||||
.repeat_count = INFRARED_NEC_REPEAT_COUNT_MIN,
|
||||
};
|
||||
|
||||
static const InfraredProtocolVariant infrared_protocol_variant_nec42ext = {
|
||||
.name = "NEC42ext",
|
||||
.address_length = 26,
|
||||
.command_length = 16,
|
||||
.frequency = INFRARED_COMMON_CARRIER_FREQUENCY,
|
||||
.duty_cycle = INFRARED_COMMON_DUTY_CYCLE,
|
||||
.repeat_count = INFRARED_NEC_REPEAT_COUNT_MIN,
|
||||
};
|
||||
|
||||
const InfraredProtocolVariant* infrared_protocol_nec_get_variant(InfraredProtocol protocol) {
|
||||
if(protocol == InfraredProtocolNEC)
|
||||
return &infrared_protocol_variant_nec;
|
||||
else if(protocol == InfraredProtocolNECext)
|
||||
return &infrared_protocol_variant_necext;
|
||||
else if(protocol == InfraredProtocolNEC42)
|
||||
return &infrared_protocol_variant_nec42;
|
||||
else if(protocol == InfraredProtocolNEC42ext)
|
||||
return &infrared_protocol_variant_nec42ext;
|
||||
else
|
||||
return NULL;
|
||||
}
|
30
lib/infrared/encoder_decoder/nec/infrared_protocol_nec.h
Normal file
30
lib/infrared/encoder_decoder/nec/infrared_protocol_nec.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
#pragma once
|
||||
|
||||
#include "../infrared_i.h"
|
||||
|
||||
/***************************************************************************************************
|
||||
* NEC protocol description
|
||||
* https://radioparty.ru/manuals/encyclopedia/213-ircontrol?start=1
|
||||
****************************************************************************************************
|
||||
* Preamble Preamble Pulse Distance/Width Pause Preamble Preamble Stop
|
||||
* mark space Modulation up to period repeat repeat bit
|
||||
* mark space
|
||||
*
|
||||
* 9000 4500 32 bit + stop bit ...110000 9000 2250
|
||||
* __________ _ _ _ _ _ _ _ _ _ _ _ _ _ ___________ _
|
||||
* ____ __________ _ _ _ __ __ __ _ _ __ __ _ _ ________________ ____________ ___
|
||||
*
|
||||
***************************************************************************************************/
|
||||
|
||||
void* infrared_decoder_nec_alloc(void);
|
||||
void infrared_decoder_nec_reset(void* decoder);
|
||||
void infrared_decoder_nec_free(void* decoder);
|
||||
InfraredMessage* infrared_decoder_nec_check_ready(void* decoder);
|
||||
InfraredMessage* infrared_decoder_nec_decode(void* decoder, bool level, uint32_t duration);
|
||||
|
||||
void* infrared_encoder_nec_alloc(void);
|
||||
InfraredStatus infrared_encoder_nec_encode(void* encoder_ptr, uint32_t* duration, bool* level);
|
||||
void infrared_encoder_nec_reset(void* encoder_ptr, const InfraredMessage* message);
|
||||
void infrared_encoder_nec_free(void* encoder_ptr);
|
||||
|
||||
const InfraredProtocolVariant* infrared_protocol_nec_get_variant(InfraredProtocol protocol);
|
29
lib/infrared/encoder_decoder/nec/infrared_protocol_nec_i.h
Normal file
29
lib/infrared/encoder_decoder/nec/infrared_protocol_nec_i.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
#pragma once
|
||||
|
||||
#include "../common/infrared_common_i.h"
|
||||
|
||||
#define INFRARED_NEC_PREAMBLE_MARK 9000
|
||||
#define INFRARED_NEC_PREAMBLE_SPACE 4500
|
||||
#define INFRARED_NEC_BIT1_MARK 560
|
||||
#define INFRARED_NEC_BIT1_SPACE 1690
|
||||
#define INFRARED_NEC_BIT0_MARK 560
|
||||
#define INFRARED_NEC_BIT0_SPACE 560
|
||||
#define INFRARED_NEC_REPEAT_PERIOD 110000
|
||||
#define INFRARED_NEC_SILENCE INFRARED_NEC_REPEAT_PERIOD
|
||||
#define INFRARED_NEC_MIN_SPLIT_TIME INFRARED_NEC_REPEAT_PAUSE_MIN
|
||||
#define INFRARED_NEC_REPEAT_PAUSE_MIN 4000
|
||||
#define INFRARED_NEC_REPEAT_PAUSE_MAX 150000
|
||||
#define INFRARED_NEC_REPEAT_COUNT_MIN 1
|
||||
#define INFRARED_NEC_REPEAT_MARK 9000
|
||||
#define INFRARED_NEC_REPEAT_SPACE 2250
|
||||
#define INFRARED_NEC_PREAMBLE_TOLERANCE 200 // us
|
||||
#define INFRARED_NEC_BIT_TOLERANCE 120 // us
|
||||
|
||||
extern const InfraredCommonProtocolSpec infrared_protocol_nec;
|
||||
|
||||
bool infrared_decoder_nec_interpret(InfraredCommonDecoder* decoder);
|
||||
InfraredStatus infrared_decoder_nec_decode_repeat(InfraredCommonDecoder* decoder);
|
||||
InfraredStatus infrared_encoder_nec_encode_repeat(
|
||||
InfraredCommonEncoder* encoder,
|
||||
uint32_t* duration,
|
||||
bool* level);
|
|
@ -1,10 +1,7 @@
|
|||
#include "infrared.h"
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <furi.h>
|
||||
#include "../infrared_i.h"
|
||||
#include "../infrared_protocol_defs_i.h"
|
||||
#include "infrared_protocol_rc5_i.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <core/check.h>
|
||||
|
||||
typedef struct {
|
||||
InfraredCommonDecoder* common_decoder;
|
||||
|
@ -60,7 +57,7 @@ bool infrared_decoder_rc5_interpret(InfraredCommonDecoder* decoder) {
|
|||
void* infrared_decoder_rc5_alloc(void) {
|
||||
InfraredRc5Decoder* decoder = malloc(sizeof(InfraredRc5Decoder));
|
||||
decoder->toggle = false;
|
||||
decoder->common_decoder = infrared_common_decoder_alloc(&protocol_rc5);
|
||||
decoder->common_decoder = infrared_common_decoder_alloc(&infrared_protocol_rc5);
|
||||
decoder->common_decoder->context = decoder;
|
||||
return decoder;
|
||||
}
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
#include <core/memmgr.h>
|
||||
#include "infrared.h"
|
||||
#include "common/infrared_common_i.h"
|
||||
#include "infrared_protocol_defs_i.h"
|
||||
#include <stdint.h>
|
||||
#include "../infrared_i.h"
|
||||
#include "infrared_protocol_rc5_i.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <core/check.h>
|
||||
|
||||
typedef struct InfraredEncoderRC5 {
|
||||
InfraredCommonEncoder* common_encoder;
|
||||
|
@ -41,7 +39,7 @@ InfraredStatus infrared_encoder_rc5_encode(void* encoder_ptr, uint32_t* duration
|
|||
|
||||
void* infrared_encoder_rc5_alloc(void) {
|
||||
InfraredEncoderRC5* encoder = malloc(sizeof(InfraredEncoderRC5));
|
||||
encoder->common_encoder = infrared_common_encoder_alloc(&protocol_rc5);
|
||||
encoder->common_encoder = infrared_common_encoder_alloc(&infrared_protocol_rc5);
|
||||
encoder->toggle_bit = false;
|
||||
return encoder;
|
||||
}
|
||||
|
|
49
lib/infrared/encoder_decoder/rc5/infrared_protocol_rc5.c
Normal file
49
lib/infrared/encoder_decoder/rc5/infrared_protocol_rc5.c
Normal file
|
@ -0,0 +1,49 @@
|
|||
#include "infrared_protocol_rc5_i.h"
|
||||
|
||||
const InfraredCommonProtocolSpec infrared_protocol_rc5 = {
|
||||
.timings =
|
||||
{
|
||||
.preamble_mark = 0,
|
||||
.preamble_space = 0,
|
||||
.bit1_mark = INFRARED_RC5_BIT,
|
||||
.preamble_tolerance = 0,
|
||||
.bit_tolerance = INFRARED_RC5_BIT_TOLERANCE,
|
||||
.silence_time = INFRARED_RC5_SILENCE,
|
||||
.min_split_time = INFRARED_RC5_MIN_SPLIT_TIME,
|
||||
},
|
||||
.databit_len[0] = 1 + 1 + 1 + 5 +
|
||||
6, // start_bit + start_bit/command_bit + toggle_bit + 5 address + 6 command
|
||||
.manchester_start_from_space = true,
|
||||
.decode = infrared_common_decode_manchester,
|
||||
.encode = infrared_common_encode_manchester,
|
||||
.interpret = infrared_decoder_rc5_interpret,
|
||||
.decode_repeat = NULL,
|
||||
.encode_repeat = NULL,
|
||||
};
|
||||
|
||||
static const InfraredProtocolVariant infrared_protocol_variant_rc5 = {
|
||||
.name = "RC5",
|
||||
.address_length = 5,
|
||||
.command_length = 6,
|
||||
.frequency = INFRARED_RC5_CARRIER_FREQUENCY,
|
||||
.duty_cycle = INFRARED_RC5_DUTY_CYCLE,
|
||||
.repeat_count = INFRARED_RC5_REPEAT_COUNT_MIN,
|
||||
};
|
||||
|
||||
static const InfraredProtocolVariant infrared_protocol_variant_rc5x = {
|
||||
.name = "RC5X",
|
||||
.address_length = 5,
|
||||
.command_length = 7,
|
||||
.frequency = INFRARED_RC5_CARRIER_FREQUENCY,
|
||||
.duty_cycle = INFRARED_RC5_DUTY_CYCLE,
|
||||
.repeat_count = INFRARED_RC5_REPEAT_COUNT_MIN,
|
||||
};
|
||||
|
||||
const InfraredProtocolVariant* infrared_protocol_rc5_get_variant(InfraredProtocol protocol) {
|
||||
if(protocol == InfraredProtocolRC5)
|
||||
return &infrared_protocol_variant_rc5;
|
||||
else if(protocol == InfraredProtocolRC5X)
|
||||
return &infrared_protocol_variant_rc5x;
|
||||
else
|
||||
return NULL;
|
||||
}
|
38
lib/infrared/encoder_decoder/rc5/infrared_protocol_rc5.h
Normal file
38
lib/infrared/encoder_decoder/rc5/infrared_protocol_rc5.h
Normal file
|
@ -0,0 +1,38 @@
|
|||
#pragma once
|
||||
|
||||
#include "../infrared_i.h"
|
||||
|
||||
/***************************************************************************************************
|
||||
* RC5 protocol description
|
||||
* https://www.mikrocontroller.net/articles/IRMP_-_english#RC5_.2B_RC5X
|
||||
****************************************************************************************************
|
||||
* Manchester/biphase
|
||||
* Modulation
|
||||
*
|
||||
* 888/1776 - bit (x2 for toggle bit)
|
||||
*
|
||||
* __ ____ __ __ __ __ __ __ __ __
|
||||
* __ __ ____ __ __ __ __ __ __ __ _
|
||||
* | 1 | 1 | 0 | ... | ... |
|
||||
* s si T address (MSB) command (MSB)
|
||||
*
|
||||
* Note: manchester starts from space timing, so it have to be handled properly
|
||||
* s - start bit (always 1)
|
||||
* si - RC5: start bit (always 1), RC5X - 7-th bit of address (in our case always 0)
|
||||
* T - toggle bit, change it's value every button press
|
||||
* address - 5 bit
|
||||
* command - 6/7 bit
|
||||
***************************************************************************************************/
|
||||
|
||||
void* infrared_decoder_rc5_alloc(void);
|
||||
void infrared_decoder_rc5_reset(void* decoder);
|
||||
void infrared_decoder_rc5_free(void* decoder);
|
||||
InfraredMessage* infrared_decoder_rc5_check_ready(void* ctx);
|
||||
InfraredMessage* infrared_decoder_rc5_decode(void* decoder, bool level, uint32_t duration);
|
||||
|
||||
void* infrared_encoder_rc5_alloc(void);
|
||||
void infrared_encoder_rc5_reset(void* encoder_ptr, const InfraredMessage* message);
|
||||
void infrared_encoder_rc5_free(void* decoder);
|
||||
InfraredStatus infrared_encoder_rc5_encode(void* encoder_ptr, uint32_t* duration, bool* polarity);
|
||||
|
||||
const InfraredProtocolVariant* infrared_protocol_rc5_get_variant(InfraredProtocol protocol);
|
20
lib/infrared/encoder_decoder/rc5/infrared_protocol_rc5_i.h
Normal file
20
lib/infrared/encoder_decoder/rc5/infrared_protocol_rc5_i.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
#pragma once
|
||||
|
||||
#include "../common/infrared_common_i.h"
|
||||
|
||||
#define INFRARED_RC5_CARRIER_FREQUENCY 36000
|
||||
#define INFRARED_RC5_DUTY_CYCLE 0.33
|
||||
|
||||
#define INFRARED_RC5_PREAMBLE_MARK 0
|
||||
#define INFRARED_RC5_PREAMBLE_SPACE 0
|
||||
#define INFRARED_RC5_BIT 888 // half of time-quant for 1 bit
|
||||
#define INFRARED_RC5_PREAMBLE_TOLERANCE 200 // us
|
||||
#define INFRARED_RC5_BIT_TOLERANCE 120 // us
|
||||
/* protocol allows 2700 silence, but it is hard to send 1 message without repeat */
|
||||
#define INFRARED_RC5_SILENCE (2700 * 10)
|
||||
#define INFRARED_RC5_MIN_SPLIT_TIME 2700
|
||||
#define INFRARED_RC5_REPEAT_COUNT_MIN 1
|
||||
|
||||
extern const InfraredCommonProtocolSpec infrared_protocol_rc5;
|
||||
|
||||
bool infrared_decoder_rc5_interpret(InfraredCommonDecoder* decoder);
|
|
@ -1,27 +0,0 @@
|
|||
#include "../infrared_i.h"
|
||||
#include "infrared_protocol_defs_i.h"
|
||||
|
||||
static const InfraredProtocolSpecification infrared_rc5_protocol_specification = {
|
||||
.name = "RC5",
|
||||
.address_length = 5,
|
||||
.command_length = 6,
|
||||
.frequency = INFRARED_RC5_CARRIER_FREQUENCY,
|
||||
.duty_cycle = INFRARED_RC5_DUTY_CYCLE,
|
||||
};
|
||||
|
||||
static const InfraredProtocolSpecification infrared_rc5x_protocol_specification = {
|
||||
.name = "RC5X",
|
||||
.address_length = 5,
|
||||
.command_length = 7,
|
||||
.frequency = INFRARED_RC5_CARRIER_FREQUENCY,
|
||||
.duty_cycle = INFRARED_RC5_DUTY_CYCLE,
|
||||
};
|
||||
|
||||
const InfraredProtocolSpecification* infrared_rc5_get_spec(InfraredProtocol protocol) {
|
||||
if(protocol == InfraredProtocolRC5)
|
||||
return &infrared_rc5_protocol_specification;
|
||||
else if(protocol == InfraredProtocolRC5X)
|
||||
return &infrared_rc5x_protocol_specification;
|
||||
else
|
||||
return NULL;
|
||||
}
|
|
@ -1,10 +1,7 @@
|
|||
#include "infrared.h"
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <furi.h>
|
||||
#include "../infrared_i.h"
|
||||
#include "../infrared_protocol_defs_i.h"
|
||||
#include "infrared_protocol_rc6_i.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <core/check.h>
|
||||
|
||||
typedef struct {
|
||||
InfraredCommonDecoder* common_decoder;
|
||||
|
@ -93,7 +90,7 @@ InfraredStatus infrared_decoder_rc6_decode_manchester(
|
|||
void* infrared_decoder_rc6_alloc(void) {
|
||||
InfraredRc6Decoder* decoder = malloc(sizeof(InfraredRc6Decoder));
|
||||
decoder->toggle = false;
|
||||
decoder->common_decoder = infrared_common_decoder_alloc(&protocol_rc6);
|
||||
decoder->common_decoder = infrared_common_decoder_alloc(&infrared_protocol_rc6);
|
||||
decoder->common_decoder->context = decoder;
|
||||
return decoder;
|
||||
}
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
#include <core/memmgr.h>
|
||||
#include "infrared.h"
|
||||
#include "common/infrared_common_i.h"
|
||||
#include "infrared_protocol_defs_i.h"
|
||||
#include <stdint.h>
|
||||
#include "../infrared_i.h"
|
||||
#include "infrared_protocol_rc6_i.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <core/check.h>
|
||||
|
||||
typedef struct InfraredEncoderRC6 {
|
||||
InfraredCommonEncoder* common_encoder;
|
||||
|
@ -35,7 +33,7 @@ InfraredStatus infrared_encoder_rc6_encode(void* encoder_ptr, uint32_t* duration
|
|||
|
||||
void* infrared_encoder_rc6_alloc(void) {
|
||||
InfraredEncoderRC6* encoder = malloc(sizeof(InfraredEncoderRC6));
|
||||
encoder->common_encoder = infrared_common_encoder_alloc(&protocol_rc6);
|
||||
encoder->common_encoder = infrared_common_encoder_alloc(&infrared_protocol_rc6);
|
||||
encoder->toggle_bit = false;
|
||||
return encoder;
|
||||
}
|
||||
|
|
39
lib/infrared/encoder_decoder/rc6/infrared_protocol_rc6.c
Normal file
39
lib/infrared/encoder_decoder/rc6/infrared_protocol_rc6.c
Normal file
|
@ -0,0 +1,39 @@
|
|||
#include "infrared_protocol_rc6_i.h"
|
||||
|
||||
const InfraredCommonProtocolSpec infrared_protocol_rc6 = {
|
||||
.timings =
|
||||
{
|
||||
.preamble_mark = INFRARED_RC6_PREAMBLE_MARK,
|
||||
.preamble_space = INFRARED_RC6_PREAMBLE_SPACE,
|
||||
.bit1_mark = INFRARED_RC6_BIT,
|
||||
.preamble_tolerance = INFRARED_RC6_PREAMBLE_TOLERANCE,
|
||||
.bit_tolerance = INFRARED_RC6_BIT_TOLERANCE,
|
||||
.silence_time = INFRARED_RC6_SILENCE,
|
||||
.min_split_time = INFRARED_RC6_MIN_SPLIT_TIME,
|
||||
},
|
||||
.databit_len[0] =
|
||||
1 + 3 + 1 + 8 +
|
||||
8, // start_bit + 3 mode bits, + 1 toggle bit (x2 timing) + 8 address + 8 command
|
||||
.manchester_start_from_space = false,
|
||||
.decode = infrared_decoder_rc6_decode_manchester,
|
||||
.encode = infrared_encoder_rc6_encode_manchester,
|
||||
.interpret = infrared_decoder_rc6_interpret,
|
||||
.decode_repeat = NULL,
|
||||
.encode_repeat = NULL,
|
||||
};
|
||||
|
||||
static const InfraredProtocolVariant infrared_protocol_variant_rc6 = {
|
||||
.name = "RC6",
|
||||
.address_length = 8,
|
||||
.command_length = 8,
|
||||
.frequency = INFRARED_RC6_CARRIER_FREQUENCY,
|
||||
.duty_cycle = INFRARED_RC6_DUTY_CYCLE,
|
||||
.repeat_count = INFRARED_RC6_REPEAT_COUNT_MIN,
|
||||
};
|
||||
|
||||
const InfraredProtocolVariant* infrared_protocol_rc6_get_variant(InfraredProtocol protocol) {
|
||||
if(protocol == InfraredProtocolRC6)
|
||||
return &infrared_protocol_variant_rc6;
|
||||
else
|
||||
return NULL;
|
||||
}
|
37
lib/infrared/encoder_decoder/rc6/infrared_protocol_rc6.h
Normal file
37
lib/infrared/encoder_decoder/rc6/infrared_protocol_rc6.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
#pragma once
|
||||
|
||||
#include "../infrared_i.h"
|
||||
|
||||
/***************************************************************************************************
|
||||
* RC6 protocol description
|
||||
* https://www.mikrocontroller.net/articles/IRMP_-_english#RC6_.2B_RC6A
|
||||
****************************************************************************************************
|
||||
* Preamble Manchester/biphase Silence
|
||||
* mark/space Modulation
|
||||
*
|
||||
* 2666 889 444/888 - bit (x2 for toggle bit) 2666
|
||||
*
|
||||
* ________ __ __ __ __ ____ __ __ __ __ __ __ __ __
|
||||
* _ _________ ____ __ __ ____ __ __ __ __ __ __ __ __ _______________
|
||||
* | 1 | 0 | 0 | 0 | 0 | ... | ... | |
|
||||
* s m2 m1 m0 T address (MSB) command (MSB)
|
||||
*
|
||||
* s - start bit (always 1)
|
||||
* m0-2 - mode (000 for RC6)
|
||||
* T - toggle bit, twice longer
|
||||
* address - 8 bit
|
||||
* command - 8 bit
|
||||
***************************************************************************************************/
|
||||
|
||||
void* infrared_decoder_rc6_alloc(void);
|
||||
void infrared_decoder_rc6_reset(void* decoder);
|
||||
void infrared_decoder_rc6_free(void* decoder);
|
||||
InfraredMessage* infrared_decoder_rc6_check_ready(void* ctx);
|
||||
InfraredMessage* infrared_decoder_rc6_decode(void* decoder, bool level, uint32_t duration);
|
||||
|
||||
void* infrared_encoder_rc6_alloc(void);
|
||||
void infrared_encoder_rc6_reset(void* encoder_ptr, const InfraredMessage* message);
|
||||
void infrared_encoder_rc6_free(void* decoder);
|
||||
InfraredStatus infrared_encoder_rc6_encode(void* encoder_ptr, uint32_t* duration, bool* polarity);
|
||||
|
||||
const InfraredProtocolVariant* infrared_protocol_rc6_get_variant(InfraredProtocol protocol);
|
28
lib/infrared/encoder_decoder/rc6/infrared_protocol_rc6_i.h
Normal file
28
lib/infrared/encoder_decoder/rc6/infrared_protocol_rc6_i.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
#pragma once
|
||||
|
||||
#include "../common/infrared_common_i.h"
|
||||
|
||||
#define INFRARED_RC6_CARRIER_FREQUENCY 36000
|
||||
#define INFRARED_RC6_DUTY_CYCLE 0.33
|
||||
|
||||
#define INFRARED_RC6_PREAMBLE_MARK 2666
|
||||
#define INFRARED_RC6_PREAMBLE_SPACE 889
|
||||
#define INFRARED_RC6_BIT 444 // half of time-quant for 1 bit
|
||||
#define INFRARED_RC6_PREAMBLE_TOLERANCE 200 // us
|
||||
#define INFRARED_RC6_BIT_TOLERANCE 120 // us
|
||||
/* protocol allows 2700 silence, but it is hard to send 1 message without repeat */
|
||||
#define INFRARED_RC6_SILENCE (2700 * 10)
|
||||
#define INFRARED_RC6_MIN_SPLIT_TIME 2700
|
||||
#define INFRARED_RC6_REPEAT_COUNT_MIN 1
|
||||
|
||||
extern const InfraredCommonProtocolSpec infrared_protocol_rc6;
|
||||
|
||||
bool infrared_decoder_rc6_interpret(InfraredCommonDecoder* decoder);
|
||||
InfraredStatus infrared_decoder_rc6_decode_manchester(
|
||||
InfraredCommonDecoder* decoder,
|
||||
bool level,
|
||||
uint32_t timing);
|
||||
InfraredStatus infrared_encoder_rc6_encode_manchester(
|
||||
InfraredCommonEncoder* encoder_ptr,
|
||||
uint32_t* duration,
|
||||
bool* polarity);
|
|
@ -1,17 +0,0 @@
|
|||
#include "../infrared_i.h"
|
||||
#include "infrared_protocol_defs_i.h"
|
||||
|
||||
static const InfraredProtocolSpecification infrared_rc6_protocol_specification = {
|
||||
.name = "RC6",
|
||||
.address_length = 8,
|
||||
.command_length = 8,
|
||||
.frequency = INFRARED_RC6_CARRIER_FREQUENCY,
|
||||
.duty_cycle = INFRARED_RC6_DUTY_CYCLE,
|
||||
};
|
||||
|
||||
const InfraredProtocolSpecification* infrared_rc6_get_spec(InfraredProtocol protocol) {
|
||||
if(protocol == InfraredProtocolRC6)
|
||||
return &infrared_rc6_protocol_specification;
|
||||
else
|
||||
return NULL;
|
||||
}
|
|
@ -1,9 +1,5 @@
|
|||
#include "infrared.h"
|
||||
#include "infrared_protocol_defs_i.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <furi.h>
|
||||
#include "../infrared_i.h"
|
||||
#include "infrared_protocol_samsung_i.h"
|
||||
#include <core/check.h>
|
||||
|
||||
InfraredMessage* infrared_decoder_samsung32_check_ready(void* ctx) {
|
||||
return infrared_common_decoder_check_ready(ctx);
|
||||
|
@ -57,7 +53,7 @@ InfraredStatus infrared_decoder_samsung32_decode_repeat(InfraredCommonDecoder* d
|
|||
}
|
||||
|
||||
void* infrared_decoder_samsung32_alloc(void) {
|
||||
return infrared_common_decoder_alloc(&protocol_samsung32);
|
||||
return infrared_common_decoder_alloc(&infrared_protocol_samsung32);
|
||||
}
|
||||
|
||||
InfraredMessage* infrared_decoder_samsung32_decode(void* decoder, bool level, uint32_t duration) {
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
#include "infrared_protocol_samsung_i.h"
|
||||
|
||||
#include <core/check.h>
|
||||
#include "common/infrared_common_i.h"
|
||||
#include <stdint.h>
|
||||
#include "../infrared_i.h"
|
||||
#include "infrared_protocol_defs_i.h"
|
||||
#include <furi.h>
|
||||
#include <core/common_defines.h>
|
||||
|
||||
static const uint32_t repeat_timings[] = {
|
||||
INFRARED_SAMSUNG_REPEAT_PAUSE2,
|
||||
|
@ -58,7 +56,7 @@ InfraredStatus infrared_encoder_samsung32_encode_repeat(
|
|||
}
|
||||
|
||||
void* infrared_encoder_samsung32_alloc(void) {
|
||||
return infrared_common_encoder_alloc(&protocol_samsung32);
|
||||
return infrared_common_encoder_alloc(&infrared_protocol_samsung32);
|
||||
}
|
||||
|
||||
void infrared_encoder_samsung32_free(void* encoder_ptr) {
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
#include "infrared_protocol_samsung_i.h"
|
||||
|
||||
const InfraredCommonProtocolSpec infrared_protocol_samsung32 = {
|
||||
.timings =
|
||||
{
|
||||
.preamble_mark = INFRARED_SAMSUNG_PREAMBLE_MARK,
|
||||
.preamble_space = INFRARED_SAMSUNG_PREAMBLE_SPACE,
|
||||
.bit1_mark = INFRARED_SAMSUNG_BIT1_MARK,
|
||||
.bit1_space = INFRARED_SAMSUNG_BIT1_SPACE,
|
||||
.bit0_mark = INFRARED_SAMSUNG_BIT0_MARK,
|
||||
.bit0_space = INFRARED_SAMSUNG_BIT0_SPACE,
|
||||
.preamble_tolerance = INFRARED_SAMSUNG_PREAMBLE_TOLERANCE,
|
||||
.bit_tolerance = INFRARED_SAMSUNG_BIT_TOLERANCE,
|
||||
.silence_time = INFRARED_SAMSUNG_SILENCE,
|
||||
.min_split_time = INFRARED_SAMSUNG_MIN_SPLIT_TIME,
|
||||
},
|
||||
.databit_len[0] = 32,
|
||||
.no_stop_bit = false,
|
||||
.decode = infrared_common_decode_pdwm,
|
||||
.encode = infrared_common_encode_pdwm,
|
||||
.interpret = infrared_decoder_samsung32_interpret,
|
||||
.decode_repeat = infrared_decoder_samsung32_decode_repeat,
|
||||
.encode_repeat = infrared_encoder_samsung32_encode_repeat,
|
||||
};
|
||||
|
||||
static const InfraredProtocolVariant infrared_protocol_variant_samsung32 = {
|
||||
.name = "Samsung32",
|
||||
.address_length = 8,
|
||||
.command_length = 8,
|
||||
.frequency = INFRARED_COMMON_CARRIER_FREQUENCY,
|
||||
.duty_cycle = INFRARED_COMMON_DUTY_CYCLE,
|
||||
.repeat_count = INFRARED_SAMSUNG_REPEAT_COUNT_MIN,
|
||||
};
|
||||
|
||||
const InfraredProtocolVariant* infrared_protocol_samsung32_get_variant(InfraredProtocol protocol) {
|
||||
if(protocol == InfraredProtocolSamsung32)
|
||||
return &infrared_protocol_variant_samsung32;
|
||||
else
|
||||
return NULL;
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
#pragma once
|
||||
|
||||
#include "../infrared_i.h"
|
||||
|
||||
/***************************************************************************************************
|
||||
* SAMSUNG32 protocol description
|
||||
* https://www.mikrocontroller.net/articles/IRMP_-_english#SAMSUNG
|
||||
****************************************************************************************************
|
||||
* Preamble Preamble Pulse Distance/Width Pause Preamble Preamble Bit1 Stop
|
||||
* mark space Modulation repeat repeat bit
|
||||
* mark space
|
||||
*
|
||||
* 4500 4500 32 bit + stop bit 40000/100000 4500 4500
|
||||
* __________ _ _ _ _ _ _ _ _ _ _ _ ___________ _ _
|
||||
* _ __________ __ _ __ __ __ _ _ __ __ _ ________________ ____________ ____ ___
|
||||
*
|
||||
***************************************************************************************************/
|
||||
|
||||
void* infrared_decoder_samsung32_alloc(void);
|
||||
void infrared_decoder_samsung32_reset(void* decoder);
|
||||
void infrared_decoder_samsung32_free(void* decoder);
|
||||
InfraredMessage* infrared_decoder_samsung32_check_ready(void* ctx);
|
||||
InfraredMessage* infrared_decoder_samsung32_decode(void* decoder, bool level, uint32_t duration);
|
||||
|
||||
InfraredStatus
|
||||
infrared_encoder_samsung32_encode(void* encoder_ptr, uint32_t* duration, bool* level);
|
||||
void infrared_encoder_samsung32_reset(void* encoder_ptr, const InfraredMessage* message);
|
||||
void* infrared_encoder_samsung32_alloc(void);
|
||||
void infrared_encoder_samsung32_free(void* encoder_ptr);
|
||||
|
||||
const InfraredProtocolVariant* infrared_protocol_samsung32_get_variant(InfraredProtocol protocol);
|
|
@ -0,0 +1,35 @@
|
|||
#pragma once
|
||||
|
||||
#include "../common/infrared_common_i.h"
|
||||
|
||||
#define INFRARED_SAMSUNG_PREAMBLE_MARK 4500
|
||||
#define INFRARED_SAMSUNG_PREAMBLE_SPACE 4500
|
||||
#define INFRARED_SAMSUNG_BIT1_MARK 550
|
||||
#define INFRARED_SAMSUNG_BIT1_SPACE 1650
|
||||
#define INFRARED_SAMSUNG_BIT0_MARK 550
|
||||
#define INFRARED_SAMSUNG_BIT0_SPACE 550
|
||||
#define INFRARED_SAMSUNG_REPEAT_PAUSE_MIN 30000
|
||||
#define INFRARED_SAMSUNG_REPEAT_PAUSE_MAX 140000
|
||||
#define INFRARED_SAMSUNG_REPEAT_PAUSE1 46000
|
||||
#define INFRARED_SAMSUNG_REPEAT_PAUSE2 97000
|
||||
#define INFRARED_SAMSUNG_REPEAT_COUNT_MIN 1
|
||||
/* Samsung silence have to be greater than REPEAT MAX
|
||||
* otherwise there can be problems during unit tests parsing
|
||||
* of some data. Real tolerances we don't know, but in real life
|
||||
* silence time should be greater than max repeat time. This is
|
||||
* because of similar preambule timings for repeat and first messages. */
|
||||
#define INFRARED_SAMSUNG_MIN_SPLIT_TIME 5000
|
||||
#define INFRARED_SAMSUNG_SILENCE 145000
|
||||
#define INFRARED_SAMSUNG_REPEAT_MARK 4500
|
||||
#define INFRARED_SAMSUNG_REPEAT_SPACE 4500
|
||||
#define INFRARED_SAMSUNG_PREAMBLE_TOLERANCE 200 // us
|
||||
#define INFRARED_SAMSUNG_BIT_TOLERANCE 120 // us
|
||||
|
||||
bool infrared_decoder_samsung32_interpret(InfraredCommonDecoder* decoder);
|
||||
InfraredStatus infrared_decoder_samsung32_decode_repeat(InfraredCommonDecoder* decoder);
|
||||
InfraredStatus infrared_encoder_samsung32_encode_repeat(
|
||||
InfraredCommonEncoder* encoder,
|
||||
uint32_t* duration,
|
||||
bool* level);
|
||||
|
||||
extern const InfraredCommonProtocolSpec infrared_protocol_samsung32;
|
|
@ -1,17 +0,0 @@
|
|||
#include "../infrared_i.h"
|
||||
#include "infrared_protocol_defs_i.h"
|
||||
|
||||
static const InfraredProtocolSpecification infrared_samsung32_protocol_specification = {
|
||||
.name = "Samsung32",
|
||||
.address_length = 8,
|
||||
.command_length = 8,
|
||||
.frequency = INFRARED_COMMON_CARRIER_FREQUENCY,
|
||||
.duty_cycle = INFRARED_COMMON_DUTY_CYCLE,
|
||||
};
|
||||
|
||||
const InfraredProtocolSpecification* infrared_samsung32_get_spec(InfraredProtocol protocol) {
|
||||
if(protocol == InfraredProtocolSamsung32)
|
||||
return &infrared_samsung32_protocol_specification;
|
||||
else
|
||||
return NULL;
|
||||
}
|
|
@ -1,10 +1,5 @@
|
|||
#include "common/infrared_common_i.h"
|
||||
#include "infrared.h"
|
||||
#include "infrared_protocol_defs_i.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <furi.h>
|
||||
#include "../infrared_i.h"
|
||||
#include "infrared_protocol_sirc_i.h"
|
||||
#include <core/check.h>
|
||||
|
||||
InfraredMessage* infrared_decoder_sirc_check_ready(void* ctx) {
|
||||
return infrared_common_decoder_check_ready(ctx);
|
||||
|
@ -44,7 +39,7 @@ bool infrared_decoder_sirc_interpret(InfraredCommonDecoder* decoder) {
|
|||
}
|
||||
|
||||
void* infrared_decoder_sirc_alloc(void) {
|
||||
return infrared_common_decoder_alloc(&protocol_sirc);
|
||||
return infrared_common_decoder_alloc(&infrared_protocol_sirc);
|
||||
}
|
||||
|
||||
InfraredMessage* infrared_decoder_sirc_decode(void* decoder, bool level, uint32_t duration) {
|
||||
|
|
|
@ -1,10 +1,5 @@
|
|||
#include "infrared_protocol_sirc_i.h"
|
||||
#include <core/check.h>
|
||||
#include "infrared.h"
|
||||
#include "common/infrared_common_i.h"
|
||||
#include <stdint.h>
|
||||
#include "../infrared_i.h"
|
||||
#include "infrared_protocol_defs_i.h"
|
||||
#include <furi.h>
|
||||
|
||||
void infrared_encoder_sirc_reset(void* encoder_ptr, const InfraredMessage* message) {
|
||||
furi_assert(encoder_ptr);
|
||||
|
@ -53,7 +48,7 @@ InfraredStatus infrared_encoder_sirc_encode_repeat(
|
|||
}
|
||||
|
||||
void* infrared_encoder_sirc_alloc(void) {
|
||||
return infrared_common_encoder_alloc(&protocol_sirc);
|
||||
return infrared_common_encoder_alloc(&infrared_protocol_sirc);
|
||||
}
|
||||
|
||||
void infrared_encoder_sirc_free(void* encoder_ptr) {
|
||||
|
|
64
lib/infrared/encoder_decoder/sirc/infrared_protocol_sirc.c
Normal file
64
lib/infrared/encoder_decoder/sirc/infrared_protocol_sirc.c
Normal file
|
@ -0,0 +1,64 @@
|
|||
#include "infrared_protocol_sirc_i.h"
|
||||
|
||||
const InfraredCommonProtocolSpec infrared_protocol_sirc = {
|
||||
.timings =
|
||||
{
|
||||
.preamble_mark = INFRARED_SIRC_PREAMBLE_MARK,
|
||||
.preamble_space = INFRARED_SIRC_PREAMBLE_SPACE,
|
||||
.bit1_mark = INFRARED_SIRC_BIT1_MARK,
|
||||
.bit1_space = INFRARED_SIRC_BIT1_SPACE,
|
||||
.bit0_mark = INFRARED_SIRC_BIT0_MARK,
|
||||
.bit0_space = INFRARED_SIRC_BIT0_SPACE,
|
||||
.preamble_tolerance = INFRARED_SIRC_PREAMBLE_TOLERANCE,
|
||||
.bit_tolerance = INFRARED_SIRC_BIT_TOLERANCE,
|
||||
.silence_time = INFRARED_SIRC_SILENCE,
|
||||
.min_split_time = INFRARED_SIRC_MIN_SPLIT_TIME,
|
||||
},
|
||||
.databit_len[0] = 20,
|
||||
.databit_len[1] = 15,
|
||||
.databit_len[2] = 12,
|
||||
.no_stop_bit = true,
|
||||
.decode = infrared_common_decode_pdwm,
|
||||
.encode = infrared_common_encode_pdwm,
|
||||
.interpret = infrared_decoder_sirc_interpret,
|
||||
.decode_repeat = NULL,
|
||||
.encode_repeat = infrared_encoder_sirc_encode_repeat,
|
||||
};
|
||||
|
||||
static const InfraredProtocolVariant infrared_protocol_variant_sirc = {
|
||||
.name = "SIRC",
|
||||
.address_length = 5,
|
||||
.command_length = 7,
|
||||
.frequency = INFRARED_SIRC_CARRIER_FREQUENCY,
|
||||
.duty_cycle = INFRARED_SIRC_DUTY_CYCLE,
|
||||
.repeat_count = INFRARED_SIRC_REPEAT_COUNT_MIN,
|
||||
};
|
||||
|
||||
static const InfraredProtocolVariant infrared_protocol_variant_sirc15 = {
|
||||
.name = "SIRC15",
|
||||
.address_length = 8,
|
||||
.command_length = 7,
|
||||
.frequency = INFRARED_SIRC_CARRIER_FREQUENCY,
|
||||
.duty_cycle = INFRARED_SIRC_DUTY_CYCLE,
|
||||
.repeat_count = INFRARED_SIRC_REPEAT_COUNT_MIN,
|
||||
};
|
||||
|
||||
static const InfraredProtocolVariant infrared_protocol_variant_sirc20 = {
|
||||
.name = "SIRC20",
|
||||
.address_length = 13,
|
||||
.command_length = 7,
|
||||
.frequency = INFRARED_SIRC_CARRIER_FREQUENCY,
|
||||
.duty_cycle = INFRARED_SIRC_DUTY_CYCLE,
|
||||
.repeat_count = INFRARED_SIRC_REPEAT_COUNT_MIN,
|
||||
};
|
||||
|
||||
const InfraredProtocolVariant* infrared_protocol_sirc_get_variant(InfraredProtocol protocol) {
|
||||
if(protocol == InfraredProtocolSIRC)
|
||||
return &infrared_protocol_variant_sirc;
|
||||
else if(protocol == InfraredProtocolSIRC15)
|
||||
return &infrared_protocol_variant_sirc15;
|
||||
else if(protocol == InfraredProtocolSIRC20)
|
||||
return &infrared_protocol_variant_sirc20;
|
||||
else
|
||||
return NULL;
|
||||
}
|
37
lib/infrared/encoder_decoder/sirc/infrared_protocol_sirc.h
Normal file
37
lib/infrared/encoder_decoder/sirc/infrared_protocol_sirc.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
#pragma once
|
||||
|
||||
#include "../infrared_i.h"
|
||||
|
||||
/***************************************************************************************************
|
||||
* Sony SIRC protocol description
|
||||
* https://www.sbprojects.net/knowledge/ir/sirc.php
|
||||
* http://picprojects.org.uk/
|
||||
****************************************************************************************************
|
||||
* Preamble Preamble Pulse Width Modulation Pause Entirely repeat
|
||||
* mark space up to period message..
|
||||
*
|
||||
* 2400 600 12/15/20 bits (600,1200) ...45000 2400 600
|
||||
* __________ _ _ _ _ _ _ _ _ _ _ _ _ _ __________ _ _
|
||||
* ____ __________ _ _ _ __ __ __ _ _ __ __ _ _ ____________________ __________ _
|
||||
* | command | address |
|
||||
* SIRC | 7b LSB | 5b LSB |
|
||||
* SIRC15 | 7b LSB | 8b LSB |
|
||||
* SIRC20 | 7b LSB | 13b LSB |
|
||||
*
|
||||
* No way to determine either next message is repeat or not,
|
||||
* so recognize only fact message received. Sony remotes always send at least 3 messages.
|
||||
* Assume 8 last extended bits for SIRC20 are address bits.
|
||||
***************************************************************************************************/
|
||||
|
||||
void* infrared_decoder_sirc_alloc(void);
|
||||
void infrared_decoder_sirc_reset(void* decoder);
|
||||
InfraredMessage* infrared_decoder_sirc_check_ready(void* decoder);
|
||||
void infrared_decoder_sirc_free(void* decoder);
|
||||
InfraredMessage* infrared_decoder_sirc_decode(void* decoder, bool level, uint32_t duration);
|
||||
|
||||
void* infrared_encoder_sirc_alloc(void);
|
||||
void infrared_encoder_sirc_reset(void* encoder_ptr, const InfraredMessage* message);
|
||||
void infrared_encoder_sirc_free(void* decoder);
|
||||
InfraredStatus infrared_encoder_sirc_encode(void* encoder_ptr, uint32_t* duration, bool* polarity);
|
||||
|
||||
const InfraredProtocolVariant* infrared_protocol_sirc_get_variant(InfraredProtocol protocol);
|
26
lib/infrared/encoder_decoder/sirc/infrared_protocol_sirc_i.h
Normal file
26
lib/infrared/encoder_decoder/sirc/infrared_protocol_sirc_i.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
#pragma once
|
||||
|
||||
#include "../common/infrared_common_i.h"
|
||||
|
||||
#define INFRARED_SIRC_CARRIER_FREQUENCY 40000
|
||||
#define INFRARED_SIRC_DUTY_CYCLE 0.33
|
||||
#define INFRARED_SIRC_PREAMBLE_MARK 2400
|
||||
#define INFRARED_SIRC_PREAMBLE_SPACE 600
|
||||
#define INFRARED_SIRC_BIT1_MARK 1200
|
||||
#define INFRARED_SIRC_BIT1_SPACE 600
|
||||
#define INFRARED_SIRC_BIT0_MARK 600
|
||||
#define INFRARED_SIRC_BIT0_SPACE 600
|
||||
#define INFRARED_SIRC_PREAMBLE_TOLERANCE 200 // us
|
||||
#define INFRARED_SIRC_BIT_TOLERANCE 120 // us
|
||||
#define INFRARED_SIRC_SILENCE 10000
|
||||
#define INFRARED_SIRC_MIN_SPLIT_TIME (INFRARED_SIRC_SILENCE - 1000)
|
||||
#define INFRARED_SIRC_REPEAT_PERIOD 45000
|
||||
#define INFRARED_SIRC_REPEAT_COUNT_MIN 3
|
||||
|
||||
extern const InfraredCommonProtocolSpec infrared_protocol_sirc;
|
||||
|
||||
bool infrared_decoder_sirc_interpret(InfraredCommonDecoder* decoder);
|
||||
InfraredStatus infrared_encoder_sirc_encode_repeat(
|
||||
InfraredCommonEncoder* encoder,
|
||||
uint32_t* duration,
|
||||
bool* level);
|
|
@ -1,37 +0,0 @@
|
|||
#include "../infrared_i.h"
|
||||
#include "infrared_protocol_defs_i.h"
|
||||
|
||||
static const InfraredProtocolSpecification infrared_sirc_protocol_specification = {
|
||||
.name = "SIRC",
|
||||
.address_length = 5,
|
||||
.command_length = 7,
|
||||
.frequency = INFRARED_SIRC_CARRIER_FREQUENCY,
|
||||
.duty_cycle = INFRARED_SIRC_DUTY_CYCLE,
|
||||
};
|
||||
|
||||
static const InfraredProtocolSpecification infrared_sirc15_protocol_specification = {
|
||||
.name = "SIRC15",
|
||||
.address_length = 8,
|
||||
.command_length = 7,
|
||||
.frequency = INFRARED_SIRC_CARRIER_FREQUENCY,
|
||||
.duty_cycle = INFRARED_SIRC_DUTY_CYCLE,
|
||||
};
|
||||
|
||||
static const InfraredProtocolSpecification infrared_sirc20_protocol_specification = {
|
||||
.name = "SIRC20",
|
||||
.address_length = 13,
|
||||
.command_length = 7,
|
||||
.frequency = INFRARED_SIRC_CARRIER_FREQUENCY,
|
||||
.duty_cycle = INFRARED_SIRC_DUTY_CYCLE,
|
||||
};
|
||||
|
||||
const InfraredProtocolSpecification* infrared_sirc_get_spec(InfraredProtocol protocol) {
|
||||
if(protocol == InfraredProtocolSIRC)
|
||||
return &infrared_sirc_protocol_specification;
|
||||
else if(protocol == InfraredProtocolSIRC15)
|
||||
return &infrared_sirc15_protocol_specification;
|
||||
else if(protocol == InfraredProtocolSIRC20)
|
||||
return &infrared_sirc20_protocol_specification;
|
||||
else
|
||||
return NULL;
|
||||
}
|
|
@ -101,7 +101,8 @@ void infrared_send(const InfraredMessage* message, int times) {
|
|||
|
||||
InfraredEncoderHandler* handler = infrared_alloc_encoder();
|
||||
infrared_reset_encoder(handler, message);
|
||||
infrared_tx_number_of_transmissions = times;
|
||||
infrared_tx_number_of_transmissions =
|
||||
MAX((int)infrared_get_protocol_min_repeat_count(message->protocol), times);
|
||||
|
||||
uint32_t frequency = infrared_get_protocol_frequency(message->protocol);
|
||||
float duty_cycle = infrared_get_protocol_duty_cycle(message->protocol);
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
#include "infrared_worker.h"
|
||||
|
||||
#include <furi_hal_infrared.h>
|
||||
#include <float_tools.h>
|
||||
|
||||
#include <core/check.h>
|
||||
#include <core/common_defines.h>
|
||||
#include "sys/_stdint.h"
|
||||
#include "infrared_worker.h"
|
||||
#include <infrared.h>
|
||||
#include <furi_hal_infrared.h>
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
#include <furi.h>
|
||||
#include <float_tools.h>
|
||||
|
||||
#include <notification/notification_messages.h>
|
||||
|
||||
|
@ -471,18 +468,23 @@ static int32_t infrared_worker_tx_thread(void* thread_context) {
|
|||
furi_assert(instance->state == InfraredWorkerStateStartTx);
|
||||
furi_assert(thread_context);
|
||||
|
||||
size_t repeats_left =
|
||||
instance->signal.decoded ?
|
||||
infrared_get_protocol_min_repeat_count(instance->signal.message.protocol) :
|
||||
1;
|
||||
uint32_t events = 0;
|
||||
bool new_data_available = true;
|
||||
bool exit = false;
|
||||
|
||||
exit = !infrared_get_new_signal(instance);
|
||||
furi_assert(!exit);
|
||||
bool exit_pending = false;
|
||||
|
||||
while(!exit) {
|
||||
bool running = infrared_get_new_signal(instance);
|
||||
furi_assert(running);
|
||||
|
||||
while(running) {
|
||||
switch(instance->state) {
|
||||
case InfraredWorkerStateStartTx:
|
||||
--repeats_left; /* The first message does not result in TX_MESSAGE_SENT event for some reason */
|
||||
instance->tx.need_reinitialization = false;
|
||||
new_data_available = infrared_worker_tx_fill_buffer(instance);
|
||||
const bool new_data_available = infrared_worker_tx_fill_buffer(instance);
|
||||
furi_hal_infrared_async_tx_start(instance->tx.frequency, instance->tx.duty_cycle);
|
||||
|
||||
if(!new_data_available) {
|
||||
|
@ -496,7 +498,7 @@ static int32_t infrared_worker_tx_thread(void* thread_context) {
|
|||
break;
|
||||
case InfraredWorkerStateStopTx:
|
||||
furi_hal_infrared_async_tx_stop();
|
||||
exit = true;
|
||||
running = false;
|
||||
break;
|
||||
case InfraredWorkerStateWaitTxEnd:
|
||||
furi_hal_infrared_async_tx_wait_termination();
|
||||
|
@ -504,18 +506,18 @@ static int32_t infrared_worker_tx_thread(void* thread_context) {
|
|||
|
||||
events = furi_thread_flags_get();
|
||||
if(events & INFRARED_WORKER_EXIT) {
|
||||
exit = true;
|
||||
running = false;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
case InfraredWorkerStateRunTx:
|
||||
events = furi_thread_flags_wait(INFRARED_WORKER_ALL_TX_EVENTS, 0, FuriWaitForever);
|
||||
events = furi_thread_flags_wait(
|
||||
INFRARED_WORKER_ALL_TX_EVENTS, FuriFlagWaitAny, FuriWaitForever);
|
||||
furi_check(events & INFRARED_WORKER_ALL_TX_EVENTS); /* at least one caught */
|
||||
|
||||
if(events & INFRARED_WORKER_EXIT) {
|
||||
instance->state = InfraredWorkerStateStopTx;
|
||||
break;
|
||||
exit_pending = true;
|
||||
}
|
||||
|
||||
if(events & INFRARED_WORKER_TX_FILL_BUFFER) {
|
||||
|
@ -527,9 +529,19 @@ static int32_t infrared_worker_tx_thread(void* thread_context) {
|
|||
}
|
||||
|
||||
if(events & INFRARED_WORKER_TX_MESSAGE_SENT) {
|
||||
if(instance->tx.message_sent_callback)
|
||||
if(repeats_left > 0) {
|
||||
--repeats_left;
|
||||
}
|
||||
|
||||
if(instance->tx.message_sent_callback) {
|
||||
instance->tx.message_sent_callback(instance->tx.message_sent_context);
|
||||
}
|
||||
}
|
||||
|
||||
if(exit_pending && repeats_left == 0) {
|
||||
instance->state = InfraredWorkerStateStopTx;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
furi_assert(0);
|
||||
|
|
|
@ -244,7 +244,7 @@ LevelDuration protocol_fdx_b_encoder_yield(ProtocolFDXB* protocol) {
|
|||
static uint64_t protocol_fdx_b_get_national_code(const uint8_t* data) {
|
||||
uint64_t national_code = bit_lib_get_bits_32(data, 0, 32);
|
||||
national_code = national_code << 32;
|
||||
national_code |= bit_lib_get_bits_32(data, 32, 6) << (32 - 6);
|
||||
national_code |= (uint64_t)bit_lib_get_bits_32(data, 32, 6) << (32 - 6);
|
||||
bit_lib_reverse_bits((uint8_t*)&national_code, 0, 64);
|
||||
return national_code;
|
||||
}
|
||||
|
|
|
@ -5,8 +5,16 @@
|
|||
#include <stddef.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_set(value, bit) \
|
||||
({ \
|
||||
__typeof__(value) _one = (1); \
|
||||
(value) |= (_one << (bit)); \
|
||||
})
|
||||
#define bit_clear(value, bit) \
|
||||
({ \
|
||||
__typeof__(value) _one = (1); \
|
||||
(value) &= ~(_one << (bit)); \
|
||||
})
|
||||
#define bit_write(value, bit, bitvalue) (bitvalue ? bit_set(value, bit) : bit_clear(value, bit))
|
||||
#define DURATION_DIFF(x, y) (((x) < (y)) ? ((y) - (x)) : ((x) - (y)))
|
||||
|
||||
|
|
|
@ -1,326 +0,0 @@
|
|||
#include "subghz_config_preset_custom.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <core/log.h>
|
||||
#include <core/core_defines.h> // UNUSED()
|
||||
#include <core/check.h> // furi_assert()
|
||||
#include <math.h> // log2(), floor()
|
||||
|
||||
#include <flipper_format/flipper_format.h>
|
||||
|
||||
// https://www.ti.com/lit/ds/symlink/cc1101.pdf?ts=1671943815135
|
||||
// page 35.
|
||||
// 12 Data Rate Programming
|
||||
//
|
||||
#define DATARATE_FUNC_CHIP_FOSC 26000000.0 /* 26MHz */
|
||||
#define DATARATE_FUNC_DIVIDER (1 << 28) /* 2 pow 28 */
|
||||
#define DATARATE_FUNC_MULTIPLIER \
|
||||
(DATARATE_FUNC_CHIP_FOSC / DATARATE_FUNC_DIVIDER) /* should be 0.09685754 */
|
||||
|
||||
#define DATARATE_EXP_FORMULA_DIVISIBLE (1 << 20) /* 2 pow 20 */
|
||||
#define DATARATE_EXP_FORMULA_MULTIPLIER \
|
||||
(DATARATE_EXP_FORMULA_DIVISIBLE / DATARATE_FUNC_CHIP_FOSC) /* should be 0.04032984 */
|
||||
|
||||
#define DATARATE_MNT_FORMULA_DIVISIBLE (1 << 28) /* 2 pow 28 */
|
||||
#define DATARATE_MNT_FORMULA_MULTIPLIER \
|
||||
(DATARATE_MNT_FORMULA_DIVISIBLE / DATARATE_FUNC_CHIP_FOSC) /* should be 10.3244406 */
|
||||
//
|
||||
|
||||
#define SUGHZ_CONFIG_TAG "SubGHz_Config"
|
||||
|
||||
uint8_t furi_hal_subghz_preset_ook_custom_async_regs[PRESET_OOK_CUSTOM_ADVANCED_AM_SIZE] = {0};
|
||||
|
||||
/** Check if cursom preset is AM (OOK) modulation
|
||||
*
|
||||
* This will check MOD_FORMAT bits in CC1101_MDMCFG2 register
|
||||
* If preset data doesn have this register - will return false.
|
||||
* This function will not fail in any case
|
||||
*
|
||||
* @param preset_data Custom preset data (registers and patable)
|
||||
* @param data_len Data length
|
||||
*/
|
||||
bool subghz_preset_custom_is_ook_modulation(const uint8_t* preset_data, uint8_t data_len) {
|
||||
if(preset_data != NULL) {
|
||||
for(uint8_t i = 2; i <= data_len; i += 2) {
|
||||
if(preset_data[i - 2] == CC1101_MDMCFG2) {
|
||||
return (preset_data[i - 1] & 0b01110000) == 0x30;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Get bandwidth value from preset data.
|
||||
*
|
||||
* This will get HIGHER bits in CC1101_MDMCFG4 register
|
||||
* If CC1101_MDMCFG4 is not found in preset data - will return
|
||||
* CH_BANDWIDTH_INVALID (0xFF)
|
||||
* If there is ANY low 4 bits in returned value - the value is invalid
|
||||
*
|
||||
* @param preset_data Custom preset data (registers and patable)
|
||||
* @param data_len Data length
|
||||
*/
|
||||
uint8_t subghz_preset_custom_get_bandwidth(const uint8_t* preset_data, uint8_t data_len) {
|
||||
if(preset_data != NULL) {
|
||||
for(uint8_t i = 2; i <= data_len; i += 2) {
|
||||
if(preset_data[i - 2] == CC1101_MDMCFG4) {
|
||||
return (preset_data[i - 1] & 0b11110000);
|
||||
}
|
||||
}
|
||||
}
|
||||
return CH_BANDWIDTH_INVALID;
|
||||
}
|
||||
|
||||
/** Set bandwidth value to preset data.
|
||||
*
|
||||
* This will set HIGHER bits in CC1101_MDMCFG4 register
|
||||
* If CC1101_MDMCFG4 is not found in preset data - will do nothing and return false
|
||||
* If there are ANY low 4 bits in provided value - they will be ignored
|
||||
*
|
||||
* @param preset_data Custom preset data (registers and patable)
|
||||
* @param data_len Data length
|
||||
* @param value New bandwidth value. See macros definition for possible values
|
||||
*/
|
||||
bool subghz_preset_custom_set_bandwidth(uint8_t* preset_data, uint8_t data_len, uint8_t value) {
|
||||
if(preset_data != NULL) {
|
||||
for(uint8_t i = 2; i <= data_len; i += 2) {
|
||||
if(preset_data[i - 2] == CC1101_MDMCFG4) {
|
||||
preset_data[i - 1] = (preset_data[i - 1] & 0b00001111) | (0b11110000 & value);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Get data rate value from preset data.
|
||||
*
|
||||
* This will get DRATE_M and DRATE_E bits from CC1101_MDMCFG3 and CC1101_MDMCFG4 registers
|
||||
* and calculate the value for 26MHz chip oscillator by formula from datasheet.
|
||||
*
|
||||
* If CC1101_MDMCFG[3:4] are not found in preset data - will return `-1`
|
||||
*
|
||||
* @param preset_data Custom preset data (registers and patable)
|
||||
* @param data_len Data length
|
||||
*/
|
||||
float subghz_preset_custom_get_datarate(const uint8_t* preset_data, uint8_t data_len) {
|
||||
if(preset_data != NULL) {
|
||||
uint8_t mantissa = 0xFF;
|
||||
uint8_t exponent = 0xFF; // Invalid, only 4 lower bits are singificant
|
||||
|
||||
uint8_t step = 0;
|
||||
|
||||
for(uint8_t i = 2; i <= data_len && step < 2; i += 2) {
|
||||
if(preset_data[i - 2] == CC1101_MDMCFG4) {
|
||||
exponent = preset_data[i - 1] & 0b00001111;
|
||||
step++;
|
||||
} else if(preset_data[i - 2] == CC1101_MDMCFG3) {
|
||||
mantissa = preset_data[i - 1];
|
||||
step++;
|
||||
}
|
||||
}
|
||||
|
||||
if(step == 2) {
|
||||
return (float)((256 + mantissa) * (1 << exponent) * DATARATE_FUNC_MULTIPLIER);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** Set data rate value to preset data.
|
||||
*
|
||||
* This will update DRATE_M and DRATE_E bits from CC1101_MDMCFG3 and CC1101_MDMCFG4 registers
|
||||
* with calculated values for 26MHz chip oscillator by formula from datasheet.
|
||||
*
|
||||
* If CC1101_MDMCFG[3:4] are not found in preset data - will return false
|
||||
*
|
||||
* @param preset_data Custom preset data (registers and patable)
|
||||
* @param data_len Data length
|
||||
* @param value value in kBaud
|
||||
*/
|
||||
bool subghz_preset_custom_set_datarate(uint8_t* preset_data, uint8_t data_len, float value) {
|
||||
if(preset_data != NULL) {
|
||||
uint8_t* pMantissa = NULL;
|
||||
uint8_t* pExponent = NULL;
|
||||
|
||||
uint8_t step = 0;
|
||||
for(uint8_t i = 2; i <= data_len && step < 2; i += 2) {
|
||||
if(preset_data[i - 2] == CC1101_MDMCFG4) {
|
||||
pExponent = &preset_data[i - 1];
|
||||
step++;
|
||||
} else if(preset_data[i - 2] == CC1101_MDMCFG3) {
|
||||
pMantissa = &preset_data[i - 1];
|
||||
step++;
|
||||
}
|
||||
}
|
||||
|
||||
// Has both registers in data - calculate values
|
||||
if(step == 2) {
|
||||
// │ value * 2^20 │
|
||||
// DRATE_E = │log2(──────────────)│
|
||||
// └ Fosc ┘
|
||||
|
||||
double exponent = floor(log2(value * DATARATE_EXP_FORMULA_MULTIPLIER));
|
||||
uint8_t datarate_e = (uint8_t)exponent;
|
||||
|
||||
// value * 2^28
|
||||
// DRATE_M = (────────────────────) - 256
|
||||
// Fosc * 2^DRATE_E
|
||||
double mantissa =
|
||||
floor((value * DATARATE_MNT_FORMULA_MULTIPLIER) / (1 << datarate_e) + 0.5) - 256;
|
||||
|
||||
// If DRATE_M is rounded to the nearest integer and becomes 256, increment DRATE_E and use DRATE_M = 0.
|
||||
if(mantissa >= 256) {
|
||||
mantissa = 0;
|
||||
datarate_e += 1;
|
||||
}
|
||||
uint8_t datarate_m = (uint8_t)mantissa;
|
||||
|
||||
*pExponent = (*pExponent & 0b11110000) | (datarate_e & 0b00001111);
|
||||
*pMantissa = datarate_m;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Print datarate value to string
|
||||
*
|
||||
* This is just convenience function
|
||||
*
|
||||
* @param datarate datarate obtained from `subghz_preset_custom_get_datarate` function
|
||||
* @param string Target print buffer
|
||||
* @param size Target print buffer size
|
||||
*/
|
||||
void subghz_preset_custom_printf_datarate(float datarate, char* string, uint8_t size) {
|
||||
float kBaudRate = datarate / 1000.0f;
|
||||
snprintf(
|
||||
string,
|
||||
size,
|
||||
"%lu.%02lu kBd",
|
||||
(uint32_t)(kBaudRate), // decimal part
|
||||
(uint32_t)((kBaudRate - (uint32_t)kBaudRate) * 100) // fractional part multiplied by 100
|
||||
);
|
||||
}
|
||||
|
||||
/** Get Manchester encoding/decoding flag value from preset data.
|
||||
*
|
||||
* This will get MANCHESTER_EN (3-rd) bit in CC1101_MDMCFG2 register
|
||||
* If CC1101_MDMCFG2 is not found in preset data - will return false
|
||||
*
|
||||
* @param preset_data Custom preset data (registers and patable)
|
||||
* @param data_len Data length
|
||||
*/
|
||||
bool subghz_preset_custom_get_machester_enable(const uint8_t* preset_data, uint8_t data_len) {
|
||||
if(preset_data != NULL) {
|
||||
for(uint8_t i = 2; i <= data_len; i += 2) {
|
||||
if(preset_data[i - 2] == CC1101_MDMCFG2) {
|
||||
return (preset_data[i - 1] & 0b00001000);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Set Manchester encoding/decoding flag value to preset data.
|
||||
*
|
||||
* This will set MANCHESTER_EN (3-rd) bit in CC1101_MDMCFG2 register
|
||||
* If CC1101_MDMCFG2 is not found in preset data - will return false
|
||||
*
|
||||
* @param preset_data Custom preset data (registers and patable)
|
||||
* @param data_len Data length
|
||||
*/
|
||||
bool subghz_preset_custom_set_machester_enable(uint8_t* preset_data, uint8_t data_len, bool value) {
|
||||
if(preset_data != NULL) {
|
||||
for(uint8_t i = 2; i <= data_len; i += 2) {
|
||||
if(preset_data[i - 2] == CC1101_MDMCFG2) {
|
||||
preset_data[i - 1] = (preset_data[i - 1] & 0b11110111) | (0b00001000 * value);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize custom preset data
|
||||
*/
|
||||
void subghz_preset_custom_init_advanced_am_preset() {
|
||||
FURI_LOG_D(SUGHZ_CONFIG_TAG, "Initializing AM preset with custom Modem configuration");
|
||||
|
||||
if(furi_hal_subghz_preset_ook_custom_async_regs[0]) {
|
||||
// already initialized
|
||||
FURI_LOG_D(SUGHZ_CONFIG_TAG, "Already initialized");
|
||||
return;
|
||||
}
|
||||
|
||||
// Copy default AM270 preset
|
||||
memcpy(
|
||||
&furi_hal_subghz_preset_ook_custom_async_regs,
|
||||
&furi_hal_subghz_preset_ook_270khz_async_regs,
|
||||
sizeof(furi_hal_subghz_preset_ook_270khz_async_regs));
|
||||
|
||||
const uint8_t ModemConfigStart = 4;
|
||||
|
||||
#if FURI_DEBUG
|
||||
const uint8_t ModemConfigEnd = ModemConfigStart + MODEM_CONFIG_REGISTERS_COUNT;
|
||||
for(uint8_t i = ModemConfigStart; i < ModemConfigEnd; ++i) {
|
||||
// Check we'll overwrite correct settings
|
||||
furi_assert(
|
||||
furi_hal_subghz_preset_ook_custom_async_regs[i * 2 + 0] ==
|
||||
furi_hal_subghz_custom_modulation_regs[i - ModemConfigStart][0]);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Copy CUSTOM Modem preset
|
||||
memcpy(
|
||||
&furi_hal_subghz_preset_ook_custom_async_regs[ModemConfigStart * 2],
|
||||
&furi_hal_subghz_custom_modulation_regs,
|
||||
sizeof(furi_hal_subghz_custom_modulation_regs));
|
||||
|
||||
// Copy default AM270 patable
|
||||
memcpy(
|
||||
&furi_hal_subghz_preset_ook_custom_async_regs[sizeof(
|
||||
furi_hal_subghz_preset_ook_270khz_async_regs)],
|
||||
&furi_hal_subghz_preset_ook_async_patable,
|
||||
sizeof(furi_hal_subghz_preset_ook_async_patable));
|
||||
|
||||
// Here at the end we should have
|
||||
// <AM270 bytes> <CFGMDM regs> <AM270 bytes> 00 00 <AM270 patable>
|
||||
|
||||
#if FURI_DEBUG
|
||||
FURI_LOG_D(SUGHZ_CONFIG_TAG, "Custom OOK preset created");
|
||||
|
||||
for(uint8_t i = 0; i < PRESET_OOK_CUSTOM_ADVANCED_AM_SIZE; i += 2) {
|
||||
FURI_LOG_D(
|
||||
SUGHZ_CONFIG_TAG,
|
||||
"Register: 0x%hhX, Value: 0x%hhX",
|
||||
furi_hal_subghz_preset_ook_custom_async_regs[i * 2 + 0],
|
||||
furi_hal_subghz_preset_ook_custom_async_regs[i * 2 + 1]);
|
||||
}
|
||||
#endif
|
||||
|
||||
FURI_LOG_D(SUGHZ_CONFIG_TAG, "Done");
|
||||
}
|
||||
|
||||
/**
|
||||
* Create subghz preset file with custom am preset
|
||||
* this is used for preset initialization if subghz app
|
||||
*/
|
||||
FlipperFormat* subghz_preset_custom_advanced_am_preset_alloc() {
|
||||
FlipperFormat* advanced_am_preset = flipper_format_string_alloc();
|
||||
|
||||
subghz_preset_custom_init_advanced_am_preset();
|
||||
|
||||
flipper_format_write_hex(
|
||||
advanced_am_preset,
|
||||
(const char*)"Custom_preset_data",
|
||||
(const uint8_t*)&furi_hal_subghz_preset_ook_custom_async_regs[0],
|
||||
sizeof(furi_hal_subghz_preset_ook_custom_async_regs));
|
||||
|
||||
flipper_format_rewind(advanced_am_preset);
|
||||
|
||||
return advanced_am_preset;
|
||||
}
|
|
@ -1,193 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <furi_hal_subghz_configs.h>
|
||||
#include <string.h> /* memcpy() */
|
||||
|
||||
#define ADVANCED_AM_PRESET_NAME "AM*"
|
||||
|
||||
// Awailable bandwidth values
|
||||
// Setup in MDMCFG4 register
|
||||
#define CH_BANDWIDTH_058 0b11110000
|
||||
#define CH_BANDWIDTH_068 0b11100000
|
||||
#define CH_BANDWIDTH_081 0b11010000
|
||||
#define CH_BANDWIDTH_102 0b11000000
|
||||
|
||||
#define CH_BANDWIDTH_116 0b10110000
|
||||
#define CH_BANDWIDTH_135 0b10100000
|
||||
#define CH_BANDWIDTH_162 0b10010000
|
||||
#define CH_BANDWIDTH_203 0b10000000
|
||||
|
||||
#define CH_BANDWIDTH_232 0b01110000
|
||||
#define CH_BANDWIDTH_270 0b01100000
|
||||
#define CH_BANDWIDTH_325 0b01010000
|
||||
#define CH_BANDWIDTH_406 0b01000000
|
||||
|
||||
#define CH_BANDWIDTH_464 0b00110000
|
||||
#define CH_BANDWIDTH_541 0b00100000
|
||||
#define CH_BANDWIDTH_650 0b00010000
|
||||
#define CH_BANDWIDTH_812 0b00000000
|
||||
|
||||
#define CH_BANDWIDTH_INVALID 0xFF
|
||||
|
||||
static const uint8_t subghz_preset_custom_bandwidth_values[] = {
|
||||
CH_BANDWIDTH_058,
|
||||
CH_BANDWIDTH_068,
|
||||
CH_BANDWIDTH_081,
|
||||
CH_BANDWIDTH_102,
|
||||
|
||||
CH_BANDWIDTH_116,
|
||||
CH_BANDWIDTH_135,
|
||||
CH_BANDWIDTH_162,
|
||||
CH_BANDWIDTH_203,
|
||||
|
||||
CH_BANDWIDTH_232,
|
||||
CH_BANDWIDTH_270,
|
||||
CH_BANDWIDTH_325,
|
||||
CH_BANDWIDTH_406,
|
||||
|
||||
CH_BANDWIDTH_464,
|
||||
CH_BANDWIDTH_541,
|
||||
CH_BANDWIDTH_650,
|
||||
CH_BANDWIDTH_812,
|
||||
};
|
||||
#define CH_BANDWIDTH_NUM (sizeof(subghz_preset_custom_bandwidth_values) / sizeof(uint8_t))
|
||||
|
||||
#define DATARATE_EXPONENT_3_79_kBaud 0b00000111 // 7
|
||||
#define DATARATE_MANTISSA_3_79_kBaud 0x32
|
||||
|
||||
#define CHANNEL_SPACING_25_EXPONENT 0b00000000 /* last bit */
|
||||
#define CHANNEL_SPACING_25_MANTISSA 0x00
|
||||
|
||||
#define MODEM_CONFIG_REGISTERS_COUNT 5
|
||||
#define PRESET_OOK_CUSTOM_ADVANCED_AM_SIZE \
|
||||
sizeof(furi_hal_subghz_preset_ook_270khz_async_regs) + \
|
||||
sizeof(furi_hal_subghz_preset_ook_async_patable)
|
||||
|
||||
extern uint8_t furi_hal_subghz_preset_ook_custom_async_regs[PRESET_OOK_CUSTOM_ADVANCED_AM_SIZE];
|
||||
|
||||
static const uint8_t furi_hal_subghz_custom_modulation_regs[MODEM_CONFIG_REGISTERS_COUNT][2] = {
|
||||
// Channel spacing is 25kHz, no Forward Error Correction, 2 preamble bytes (will be ignored)
|
||||
{CC1101_MDMCFG0, CHANNEL_SPACING_25_MANTISSA},
|
||||
{CC1101_MDMCFG1, 0x00 | CHANNEL_SPACING_25_EXPONENT},
|
||||
|
||||
// [0:2] SYNC_MODE = 00 // No preamble/sync
|
||||
// [3:3] MANCHESTER_EN = 0 // Disable
|
||||
// [4:6] MOD_FORMAT = 03 // Format ASK/OOK
|
||||
// [7:7] DEM_DCFILT_OFF = 0 // Enable
|
||||
{CC1101_MDMCFG2, 0x30},
|
||||
|
||||
// 3.79 kBaud data rate (mantissa in 3rd register)
|
||||
{CC1101_MDMCFG3, DATARATE_MANTISSA_3_79_kBaud},
|
||||
|
||||
// 270.8333 kHz Rx BW filer (hi) and 3.79 kBaud data rate (exponent in 4th register)
|
||||
{CC1101_MDMCFG4, DATARATE_EXPONENT_3_79_kBaud | CH_BANDWIDTH_270},
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Check if cursom preset is AM (OOK) modulation
|
||||
*
|
||||
* This will check MOD_FORMAT bits in CC1101_MDMCFG2 register
|
||||
* If preset data doesn have this register - will return false.
|
||||
* This function will not fail in any case
|
||||
*
|
||||
* @param preset_data Custom preset data (registers and patable)
|
||||
* @param data_len Data length
|
||||
*/
|
||||
bool subghz_preset_custom_is_ook_modulation(const uint8_t* preset_data, uint8_t data_len);
|
||||
|
||||
/** Get bandwidth value from preset data.
|
||||
*
|
||||
* This will get HIGHER bits in CC1101_MDMCFG4 register
|
||||
* If CC1101_MDMCFG4 is not found in preset data - will return
|
||||
* CH_BANDWIDTH_INVALID (0xFF)
|
||||
* If there is ANY low 4 bits in returned value - the value is invalid
|
||||
*
|
||||
* @param preset_data Custom preset data (registers and patable)
|
||||
* @param data_len Data length
|
||||
*/
|
||||
uint8_t subghz_preset_custom_get_bandwidth(const uint8_t* preset_data, uint8_t data_len);
|
||||
|
||||
/** Set bandwidth value to preset data.
|
||||
*
|
||||
* This will set HIGHER bits in CC1101_MDMCFG4 register
|
||||
* If CC1101_MDMCFG4 is not found in preset data - will do nothing and return false
|
||||
* If there are ANY low 4 bits in provided value - they will be ignored
|
||||
*
|
||||
* @param preset_data Custom preset data (registers and patable)
|
||||
* @param data_len Data length
|
||||
* @param value New bandwidth value. See macros definition for possible values
|
||||
*/
|
||||
bool subghz_preset_custom_set_bandwidth(uint8_t* preset_data, uint8_t data_len, uint8_t value);
|
||||
|
||||
/** Get data rate value from preset data.
|
||||
*
|
||||
* This will get DRATE_M and DRATE_E bits from CC1101_MDMCFG3 and CC1101_MDMCFG4 registers
|
||||
* and calculate the value for 26MHz chip oscillator by formula from datasheet.
|
||||
*
|
||||
* If CC1101_MDMCFG[3:4] are not found in preset data - will return `-1`
|
||||
*
|
||||
* @param preset_data Custom preset data (registers and patable)
|
||||
* @param data_len Data length
|
||||
*/
|
||||
float subghz_preset_custom_get_datarate(const uint8_t* preset_data, uint8_t data_len);
|
||||
|
||||
/** Set data rate value to preset data.
|
||||
*
|
||||
* This will update DRATE_M and DRATE_E bits from CC1101_MDMCFG3 and CC1101_MDMCFG4 registers
|
||||
* with calculated values for 26MHz chip oscillator by formula from datasheet.
|
||||
*
|
||||
* If CC1101_MDMCFG[3:4] are not found in preset data - will return false
|
||||
*
|
||||
* @param preset_data Custom preset data (registers and patable)
|
||||
* @param data_len Data length
|
||||
* @param value value in kBaud
|
||||
*/
|
||||
bool subghz_preset_custom_set_datarate(uint8_t* preset_data, uint8_t data_len, float value);
|
||||
|
||||
/** Print datarate value to string
|
||||
*
|
||||
* This is just conviniece function
|
||||
*
|
||||
* @param datarate datarate obtained from `subghz_preset_custom_get_datarate` function
|
||||
* @param string Target print buffer
|
||||
* @param size Target print buffer size
|
||||
*/
|
||||
void subghz_preset_custom_printf_datarate(float datarate, char* string, uint8_t size);
|
||||
|
||||
/** Get Manchester encoding/decoding flag value from preset data.
|
||||
*
|
||||
* This will get MANCHESTER_EN (3-rd) bit in CC1101_MDMCFG2 register
|
||||
* If CC1101_MDMCFG2 is not found in preset data - will return false
|
||||
*
|
||||
* @param preset_data Custom preset data (registers and patable)
|
||||
* @param data_len Data length
|
||||
*/
|
||||
bool subghz_preset_custom_get_machester_enable(const uint8_t* preset_data, uint8_t data_len);
|
||||
|
||||
/** Set Manchester encoding/decoding flag value to preset data.
|
||||
*
|
||||
* This will set MANCHESTER_EN (3-rd) bit in CC1101_MDMCFG2 register
|
||||
* If CC1101_MDMCFG2 is not found in preset data - will return false
|
||||
*
|
||||
* @param preset_data Custom preset data (registers and patable)
|
||||
* @param data_len Data length
|
||||
*/
|
||||
bool subghz_preset_custom_set_machester_enable(uint8_t* preset_data, uint8_t data_len, bool value);
|
||||
|
||||
/**
|
||||
* Initialize advanced am custom preset
|
||||
*/
|
||||
void subghz_preset_custom_init_advanced_am_preset();
|
||||
|
||||
/**
|
||||
* Create subghz preset file with custom am preset
|
||||
* this is used for preset initialization if subghz app
|
||||
*/
|
||||
struct FlipperFormat* subghz_preset_custom_advanced_am_preset_alloc();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -280,9 +280,9 @@ static bool subghz_protocol_chamb_code_to_bit(uint64_t* data, uint8_t size) {
|
|||
uint64_t data_tmp = data[0];
|
||||
uint64_t data_res = 0;
|
||||
for(uint8_t i = 0; i < size; i++) {
|
||||
if((data_tmp & 0xF) == CHAMBERLAIN_CODE_BIT_0) {
|
||||
if((data_tmp & 0xFll) == CHAMBERLAIN_CODE_BIT_0) {
|
||||
bit_write(data_res, i, 0);
|
||||
} else if((data_tmp & 0xF) == CHAMBERLAIN_CODE_BIT_1) {
|
||||
} else if((data_tmp & 0xFll) == CHAMBERLAIN_CODE_BIT_1) {
|
||||
bit_write(data_res, i, 1);
|
||||
} else {
|
||||
return false;
|
||||
|
|
|
@ -224,7 +224,7 @@ static bool subghz_protocol_secplus_v1_encode(SubGhzProtocolEncoderSecPlus_v1* i
|
|||
instance->generic.data &= 0xFFFFFFFF00000000;
|
||||
instance->generic.data |= rolling;
|
||||
|
||||
if(rolling > 0xFFFFFFFF) {
|
||||
if(rolling == 0xFFFFFFFF) {
|
||||
rolling = 0xE6000000;
|
||||
}
|
||||
if(fixed > 0xCFD41B90) {
|
||||
|
|
|
@ -7,7 +7,7 @@ from SCons.Node import NodeList
|
|||
import SCons.Warnings
|
||||
|
||||
from fbt.elfmanifest import assemble_manifest_data
|
||||
from fbt.appmanifest import FlipperApplication, FlipperManifestException
|
||||
from fbt.appmanifest import FlipperApplication, FlipperManifestException, FlipperAppType
|
||||
from fbt.sdk.cache import SdkCache
|
||||
from fbt.util import extract_abs_dir_path
|
||||
|
||||
|
@ -32,6 +32,7 @@ def BuildAppElf(env, app):
|
|||
ext_apps_work_dir = env.subst("$EXT_APPS_WORK_DIR")
|
||||
app_work_dir = os.path.join(ext_apps_work_dir, app.appid)
|
||||
|
||||
env.SetDefault(_APP_ICONS=[])
|
||||
env.VariantDir(app_work_dir, app._appdir, duplicate=False)
|
||||
|
||||
app_env = env.Clone(FAP_SRC_DIR=app._appdir, FAP_WORK_DIR=app_work_dir)
|
||||
|
@ -63,6 +64,7 @@ def BuildAppElf(env, app):
|
|||
icon_bundle_name=f"{app.fap_icon_assets_symbol if app.fap_icon_assets_symbol else app.appid }_icons",
|
||||
)
|
||||
app_env.Alias("_fap_icons", fap_icons)
|
||||
env.Append(_APP_ICONS=[fap_icons])
|
||||
|
||||
private_libs = []
|
||||
|
||||
|
@ -232,11 +234,18 @@ def GetExtAppFromPath(env, app_dir):
|
|||
return app_artifacts
|
||||
|
||||
|
||||
def fap_dist_emitter(target, source, env):
|
||||
def resources_fap_dist_emitter(target, source, env):
|
||||
target_dir = target[0]
|
||||
|
||||
target = []
|
||||
for _, app_artifacts in env["EXT_APPS"].items():
|
||||
# We don't deploy example apps & debug tools with SD card resources
|
||||
if (
|
||||
app_artifacts.app.apptype == FlipperAppType.DEBUG
|
||||
or app_artifacts.app.fap_category == "Examples"
|
||||
):
|
||||
continue
|
||||
|
||||
source.extend(app_artifacts.compact)
|
||||
target.append(
|
||||
target_dir.Dir(app_artifacts.app.fap_category).File(
|
||||
|
@ -247,7 +256,7 @@ def fap_dist_emitter(target, source, env):
|
|||
return (target, source)
|
||||
|
||||
|
||||
def fap_dist_action(target, source, env):
|
||||
def resources_fap_dist_action(target, source, env):
|
||||
# FIXME
|
||||
target_dir = env.Dir("#/assets/resources/apps")
|
||||
|
||||
|
@ -280,10 +289,10 @@ def generate(env, **kw):
|
|||
BUILDERS={
|
||||
"FapDist": Builder(
|
||||
action=Action(
|
||||
fap_dist_action,
|
||||
resources_fap_dist_action,
|
||||
"$FAPDISTCOMSTR",
|
||||
),
|
||||
emitter=fap_dist_emitter,
|
||||
emitter=resources_fap_dist_emitter,
|
||||
),
|
||||
"EmbedAppMetadata": Builder(
|
||||
action=[
|
||||
|
|
|
@ -11,6 +11,8 @@ Building:
|
|||
Build all FAP apps
|
||||
fap_{APPID}, launch_app APPSRC={APPID}:
|
||||
Build FAP app with appid={APPID}; upload & start it over USB
|
||||
fap_deploy:
|
||||
Build and upload all FAP apps over USB
|
||||
|
||||
Flashing & debugging:
|
||||
flash, flash_blackmagic, jflash:
|
||||
|
@ -29,6 +31,8 @@ Other:
|
|||
run linters
|
||||
format, format_py:
|
||||
run code formatters
|
||||
firmware_pvs:
|
||||
generate a PVS-Studio report
|
||||
|
||||
For more targets & info, see documentation/fbt.md
|
||||
"""
|
||||
|
|
106
scripts/fbt_tools/pvsstudio.py
Normal file
106
scripts/fbt_tools/pvsstudio.py
Normal file
|
@ -0,0 +1,106 @@
|
|||
from SCons.Builder import Builder
|
||||
from SCons.Action import Action
|
||||
from SCons.Script import Delete, Mkdir, GetBuildFailures
|
||||
import multiprocessing
|
||||
import webbrowser
|
||||
import atexit
|
||||
import sys
|
||||
import subprocess
|
||||
|
||||
__no_browser = False
|
||||
|
||||
|
||||
def _set_browser_action(target, source, env):
|
||||
if env["PVSNOBROWSER"]:
|
||||
global __no_browser
|
||||
__no_browser = True
|
||||
|
||||
|
||||
def emit_pvsreport(target, source, env):
|
||||
target_dir = env["REPORT_DIR"]
|
||||
if env["PLATFORM"] == "win32":
|
||||
# Report generator on Windows emits to a subfolder of given output folder
|
||||
target_dir = target_dir.Dir("fullhtml")
|
||||
return [target_dir.File("index.html")], source
|
||||
|
||||
|
||||
def atexist_handler():
|
||||
global __no_browser
|
||||
if __no_browser:
|
||||
return
|
||||
|
||||
for bf in GetBuildFailures():
|
||||
if bf.node.exists and bf.node.name.endswith(".html"):
|
||||
# macOS
|
||||
if sys.platform == "darwin":
|
||||
subprocess.run(["open", bf.node.abspath])
|
||||
else:
|
||||
webbrowser.open(bf.node.abspath)
|
||||
break
|
||||
|
||||
|
||||
def generate(env):
|
||||
env.SetDefault(
|
||||
PVSNCORES=multiprocessing.cpu_count(),
|
||||
PVSOPTIONS=[
|
||||
"@.pvsoptions",
|
||||
"-j${PVSNCORES}",
|
||||
# "--incremental", # kinda broken on PVS side
|
||||
],
|
||||
PVSCONVOPTIONS=[
|
||||
"-a",
|
||||
"GA:1,2,3",
|
||||
"-t",
|
||||
"fullhtml",
|
||||
"--indicate-warnings",
|
||||
],
|
||||
)
|
||||
|
||||
if env["PLATFORM"] == "win32":
|
||||
env.SetDefault(
|
||||
PVSCHECKBIN="CompilerCommandsAnalyzer.exe",
|
||||
PVSCONVBIN="PlogConverter.exe",
|
||||
)
|
||||
else:
|
||||
env.SetDefault(
|
||||
PVSCHECKBIN="pvs-studio-analyzer",
|
||||
PVSCONVBIN="plog-converter",
|
||||
)
|
||||
|
||||
if not env["VERBOSE"]:
|
||||
env.SetDefault(
|
||||
PVSCHECKCOMSTR="\tPVS\t${TARGET}",
|
||||
PVSCONVCOMSTR="\tPVSREP\t${TARGET}",
|
||||
)
|
||||
|
||||
env.Append(
|
||||
BUILDERS={
|
||||
"PVSCheck": Builder(
|
||||
action=Action(
|
||||
'${PVSCHECKBIN} analyze ${PVSOPTIONS} -f "${SOURCE}" -o "${TARGET}"',
|
||||
"${PVSCHECKCOMSTR}",
|
||||
),
|
||||
suffix=".log",
|
||||
src_suffix=".json",
|
||||
),
|
||||
"PVSReport": Builder(
|
||||
action=Action(
|
||||
[
|
||||
Delete("${TARGET.dir}"),
|
||||
# PlogConverter.exe and plog-converter have different behavior
|
||||
Mkdir("${TARGET.dir}") if env["PLATFORM"] == "win32" else None,
|
||||
Action(_set_browser_action, None),
|
||||
'${PVSCONVBIN} ${PVSCONVOPTIONS} "${SOURCE}" -o "${REPORT_DIR}"',
|
||||
],
|
||||
"${PVSCONVCOMSTR}",
|
||||
),
|
||||
emitter=emit_pvsreport,
|
||||
src_suffix=".log",
|
||||
),
|
||||
}
|
||||
)
|
||||
atexit.register(atexist_handler)
|
||||
|
||||
|
||||
def exists(env):
|
||||
return True
|
|
@ -15,6 +15,13 @@ import serial.tools.list_ports as list_ports
|
|||
class Main(App):
|
||||
def init(self):
|
||||
self.parser.add_argument("-p", "--port", help="CDC Port", default="auto")
|
||||
self.parser.add_argument(
|
||||
"-n",
|
||||
"--no-launch",
|
||||
dest="launch_app",
|
||||
action="store_false",
|
||||
help="Don't launch app",
|
||||
)
|
||||
|
||||
self.parser.add_argument("fap_src_path", help="App file to upload")
|
||||
self.parser.add_argument(
|
||||
|
@ -84,11 +91,14 @@ class Main(App):
|
|||
self.logger.error(f"Error: upload failed: {storage.last_error}")
|
||||
return -3
|
||||
|
||||
storage.send_and_wait_eol(f'loader open "Applications" {fap_dst_path}\r')
|
||||
result = storage.read.until(storage.CLI_EOL)
|
||||
if len(result):
|
||||
self.logger.error(f"Unexpected response: {result.decode('ascii')}")
|
||||
return -4
|
||||
if self.args.launch_app:
|
||||
storage.send_and_wait_eol(
|
||||
f'loader open "Applications" {fap_dst_path}\r'
|
||||
)
|
||||
result = storage.read.until(storage.CLI_EOL)
|
||||
if len(result):
|
||||
self.logger.error(f"Unexpected response: {result.decode('ascii')}")
|
||||
return -4
|
||||
|
||||
return 0
|
||||
finally:
|
||||
|
|
|
@ -43,9 +43,11 @@ fbtenv_restore_env()
|
|||
|
||||
PYTHONNOUSERSITE="$SAVED_PYTHONNOUSERSITE";
|
||||
PYTHONPATH="$SAVED_PYTHONPATH";
|
||||
PYTHONHOME="$SAVED_PYTHONHOME";
|
||||
|
||||
unset SAVED_PYTHONNOUSERSITE;
|
||||
unset SAVED_PYTHONPATH;
|
||||
unset SAVED_PYTHONHOME;
|
||||
|
||||
unset SCRIPT_PATH;
|
||||
unset FBT_TOOLCHAIN_VERSION;
|
||||
|
@ -69,7 +71,7 @@ fbtenv_check_sourced()
|
|||
return 1;
|
||||
}
|
||||
|
||||
fbtenv_chck_many_source()
|
||||
fbtenv_check_if_sourced_multiple_times()
|
||||
{
|
||||
if ! echo "${PS1:-""}" | grep -qF "[fbt]"; then
|
||||
if ! echo "${PROMPT:-""}" | grep -qF "[fbt]"; then
|
||||
|
@ -285,7 +287,7 @@ fbtenv_main()
|
|||
fbtenv_restore_env;
|
||||
return 0;
|
||||
fi
|
||||
fbtenv_chck_many_source; # many source it's just a warning
|
||||
fbtenv_check_if_sourced_multiple_times; # many source it's just a warning
|
||||
fbtenv_check_script_path || return 1;
|
||||
fbtenv_check_download_toolchain || return 1;
|
||||
fbtenv_set_shell_prompt;
|
||||
|
@ -293,12 +295,14 @@ fbtenv_main()
|
|||
PATH="$TOOLCHAIN_ARCH_DIR/bin:$PATH";
|
||||
PATH="$TOOLCHAIN_ARCH_DIR/protobuf/bin:$PATH";
|
||||
PATH="$TOOLCHAIN_ARCH_DIR/openocd/bin:$PATH";
|
||||
|
||||
|
||||
SAVED_PYTHONNOUSERSITE="${PYTHONNOUSERSITE:-""}";
|
||||
SAVED_PYTHONPATH="${PYTHONPATH:-""}";
|
||||
SAVED_PYTHONHOME="${PYTHONHOME:-""}";
|
||||
|
||||
PYTHONNOUSERSITE=1;
|
||||
PYTHONPATH=;
|
||||
PYTHONHOME=;
|
||||
}
|
||||
|
||||
fbtenv_main "${1:-""}";
|
||||
|
|
|
@ -81,16 +81,6 @@ vars.AddVariables(
|
|||
"7",
|
||||
],
|
||||
),
|
||||
BoolVariable(
|
||||
"DEBUG_TOOLS",
|
||||
help="Enable debug tools to be built",
|
||||
default=False,
|
||||
),
|
||||
BoolVariable(
|
||||
"FAP_EXAMPLES",
|
||||
help="Enable example applications to be built",
|
||||
default=False,
|
||||
),
|
||||
(
|
||||
"DIST_SUFFIX",
|
||||
"Suffix for binaries in build output for dist targets",
|
||||
|
@ -242,9 +232,15 @@ vars.AddVariables(
|
|||
("applications/system", False),
|
||||
("applications/debug", False),
|
||||
("applications/plugins", False),
|
||||
("applications/examples", False),
|
||||
("applications_user", False),
|
||||
],
|
||||
),
|
||||
BoolVariable(
|
||||
"PVSNOBROWSER",
|
||||
help="Don't open browser after generating error repots",
|
||||
default=False,
|
||||
),
|
||||
)
|
||||
|
||||
Return("vars")
|
||||
|
|
|
@ -65,9 +65,8 @@ class FlipperExtAppBuildArtifacts:
|
|||
apps_to_build_as_faps = [
|
||||
FlipperAppType.PLUGIN,
|
||||
FlipperAppType.EXTERNAL,
|
||||
FlipperAppType.DEBUG,
|
||||
]
|
||||
if appenv["DEBUG_TOOLS"]:
|
||||
apps_to_build_as_faps.append(FlipperAppType.DEBUG)
|
||||
|
||||
known_extapps = [
|
||||
app
|
||||
|
@ -143,6 +142,11 @@ sdk_apisyms = appenv.SDKSymGenerator(
|
|||
"${BUILD_DIR}/assets/compiled/symbols.h", appenv["SDK_DEFINITION"]
|
||||
)
|
||||
Alias("api_syms", sdk_apisyms)
|
||||
ENV.Replace(
|
||||
SDK_APISYMS=sdk_apisyms,
|
||||
_APP_ICONS=appenv["_APP_ICONS"],
|
||||
)
|
||||
|
||||
|
||||
if appenv["FORCE"]:
|
||||
appenv.AlwaysBuild(sdk_source, sdk_tree, sdk_apicheck, sdk_apisyms)
|
||||
|
|
Loading…
Reference in a new issue