From d0ee981fd463324337ba0ce590e5d58730a062d9 Mon Sep 17 00:00:00 2001 From: VerstreuteSeele Date: Wed, 11 Jan 2023 18:57:42 +0100 Subject: [PATCH 01/60] V38 passed QC testing --- fbt_options.py | 2 +- scripts/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fbt_options.py b/fbt_options.py index a54f2595f..9174b9552 100644 --- a/fbt_options.py +++ b/fbt_options.py @@ -14,7 +14,7 @@ DEBUG = 0 # Suffix to add to files when building distribution # If OS environment has DIST_SUFFIX set, it will be used instead -DIST_SUFFIX = "XFW-0037_01072023" +DIST_SUFFIX = "XFW-0038_01112023" # Coprocessor firmware COPRO_OB_DATA = "scripts/ob.data" diff --git a/scripts/version.py b/scripts/version.py index 74c2f4a04..f46eee068 100644 --- a/scripts/version.py +++ b/scripts/version.py @@ -14,7 +14,7 @@ class GitVersion: self.gitlist = [("commit", "rev-parse --short HEAD"), ("branch", "rev-parse --abbrev-ref") , ("branch_num", "rev-list -count HEAD")] def get_version_info(self): - commit = branch = branch_num = "XFW-0037" + commit = branch = branch_num = "XFW-0038" # We dont use an `or` in commands that we expect to fail. It will serve no function. # We also dont try;exept an entire block of code. This is bad practise. We only try the single part that we expect to fail! From ea0b5488ad0f295406dbdc1d6b511e873a0ddc29 Mon Sep 17 00:00:00 2001 From: jbohack Date: Wed, 11 Jan 2023 19:15:06 -0500 Subject: [PATCH 02/60] u2f over nfc https://github.com/flipperdevices/flipperzero-firmware/pull/1755 from @devsnek may need more testing --- applications/main/nfc/nfc_cli.c | 2 +- applications/main/u2f/scenes/u2f_scene_main.c | 2 + applications/main/u2f/u2f.c | 127 ++++++++---- applications/main/u2f/u2f.h | 10 +- applications/main/u2f/u2f_app_i.h | 2 + applications/main/u2f/u2f_hid.c | 7 +- applications/main/u2f/u2f_nfc.c | 187 ++++++++++++++++++ applications/main/u2f/u2f_nfc.h | 17 ++ firmware/targets/f7/api_symbols.csv | 4 +- firmware/targets/f7/furi_hal/furi_hal_nfc.c | 20 +- .../targets/furi_hal_include/furi_hal_nfc.h | 6 +- lib/nfc/nfc_worker.c | 4 +- scripts/flipper/assets/icon.py | 5 +- 13 files changed, 327 insertions(+), 66 deletions(-) create mode 100644 applications/main/u2f/u2f_nfc.c create mode 100644 applications/main/u2f/u2f_nfc.h diff --git a/applications/main/nfc/nfc_cli.c b/applications/main/nfc/nfc_cli.c index a6475ca68..c21e491e6 100644 --- a/applications/main/nfc/nfc_cli.c +++ b/applications/main/nfc/nfc_cli.c @@ -67,7 +67,7 @@ static void nfc_cli_emulate(Cli* cli, FuriString* args) { }; while(!cli_cmd_interrupt_received(cli)) { - if(furi_hal_nfc_listen(params.uid, params.uid_len, params.atqa, params.sak, false, 100)) { + if (furi_hal_nfc_listen(¶ms, false, 100)) { printf("Reader detected\r\n"); furi_hal_nfc_sleep(); } diff --git a/applications/main/u2f/scenes/u2f_scene_main.c b/applications/main/u2f/scenes/u2f_scene_main.c index af7f1159b..abf78c841 100644 --- a/applications/main/u2f/scenes/u2f_scene_main.c +++ b/applications/main/u2f/scenes/u2f_scene_main.c @@ -101,6 +101,7 @@ void u2f_scene_main_on_enter(void* context) { if(app->u2f_ready == true) { u2f_set_event_callback(app->u2f_instance, u2f_scene_main_event_callback, app); app->u2f_hid = u2f_hid_start(app->u2f_instance); + app->u2f_nfc = u2f_nfc_start(app->u2f_instance); u2f_view_set_ok_callback(app->u2f_view, u2f_scene_main_ok_callback, app); } else { u2f_free(app->u2f_instance); @@ -117,6 +118,7 @@ void u2f_scene_main_on_exit(void* context) { furi_timer_free(app->timer); if(app->u2f_ready == true) { u2f_hid_stop(app->u2f_hid); + u2f_nfc_stop(app->u2f_nfc); u2f_free(app->u2f_instance); } } diff --git a/applications/main/u2f/u2f.c b/applications/main/u2f/u2f.c index 767733ce6..f4197dd74 100644 --- a/applications/main/u2f/u2f.c +++ b/applications/main/u2f/u2f.c @@ -16,6 +16,7 @@ #define U2F_CMD_REGISTER 0x01 #define U2F_CMD_AUTHENTICATE 0x02 #define U2F_CMD_VERSION 0x03 +#define U2F_CMD_APPLET_SELECTION 0xA4 typedef enum { U2fCheckOnly = 0x07, // "check-only" - only check key handle, don't send auth response @@ -37,11 +38,6 @@ typedef struct { } __attribute__((packed)) U2fKeyHandle; typedef struct { - uint8_t cla; - uint8_t ins; - uint8_t p1; - uint8_t p2; - uint8_t len[3]; uint8_t challenge[32]; uint8_t app_id[32]; } __attribute__((packed)) U2fRegisterReq; @@ -54,11 +50,6 @@ typedef struct { } __attribute__((packed)) U2fRegisterResp; typedef struct { - uint8_t cla; - uint8_t ins; - uint8_t p1; - uint8_t p2; - uint8_t len[3]; uint8_t challenge[32]; uint8_t app_id[32]; U2fKeyHandle key_handle; @@ -72,10 +63,14 @@ typedef struct { static const uint8_t ver_str[] = {"U2F_V2"}; +// NFC applet selection fields +static const uint8_t rid_ac_ax[] = { 0xA0, 0x00, 0x00, 0x06, 0x47, 0x2F, 0x00, 0x01 }; + static const uint8_t state_no_error[] = {0x90, 0x00}; static const uint8_t state_not_supported[] = {0x6D, 0x00}; static const uint8_t state_user_missing[] = {0x69, 0x85}; static const uint8_t state_wrong_data[] = {0x6A, 0x80}; +static const uint8_t state_app_not_found[] = { 0x6A, 0x82 }; struct U2fData { uint8_t device_key[32]; @@ -88,6 +83,17 @@ struct U2fData { void* context; }; +static void* apdu_command_data(U2fApduCommand* cmd) { + // Short encoding is a single byte. + // Extended length encoding is 0 byte followed by MSB and LSB bytes. + if (cmd->len[0] == 0) { + return cmd->len + 3; + } + else { + return cmd->len + 1; + } +} + static int u2f_uecc_random(uint8_t* dest, unsigned size) { furi_hal_random_fill_buf(dest, size); return 1; @@ -178,9 +184,10 @@ static uint8_t u2f_der_encode_signature(uint8_t* der, uint8_t* sig) { return len; } -static uint16_t u2f_register(U2fData* U2F, uint8_t* buf) { - U2fRegisterReq* req = (U2fRegisterReq*)buf; - U2fRegisterResp* resp = (U2fRegisterResp*)buf; +static uint16_t u2f_register(U2fData* U2F, const uint8_t* in_buf, uint8_t* out_buf) { + U2fApduCommand* cmd = (U2fApduCommand*)in_buf; + U2fRegisterReq* req = apdu_command_data(cmd); + U2fRegisterResp* resp = (U2fRegisterResp*)out_buf; U2fKeyHandle handle; uint8_t private[32]; U2fPubKey pub_key; @@ -190,13 +197,13 @@ static uint16_t u2f_register(U2fData* U2F, uint8_t* buf) { if(u2f_data_check(false) == false) { U2F->ready = false; if(U2F->callback != NULL) U2F->callback(U2fNotifyError, U2F->context); - memcpy(&buf[0], state_not_supported, 2); + memcpy(&out_buf[0], state_not_supported, 2); return 2; } if(U2F->callback != NULL) U2F->callback(U2fNotifyRegister, U2F->context); if(U2F->user_present == false) { - memcpy(&buf[0], state_user_missing, 2); + memcpy(&out_buf[0], state_user_missing, 2); return 2; } U2F->user_present = false; @@ -247,9 +254,10 @@ static uint16_t u2f_register(U2fData* U2F, uint8_t* buf) { return (sizeof(U2fRegisterResp) + cert_len + signature_len + 2); } -static uint16_t u2f_authenticate(U2fData* U2F, uint8_t* buf) { - U2fAuthReq* req = (U2fAuthReq*)buf; - U2fAuthResp* resp = (U2fAuthResp*)buf; +static uint16_t u2f_authenticate(U2fData* U2F, const uint8_t* in_buf, uint8_t* out_buf) { + U2fApduCommand* cmd = (U2fApduCommand*)in_buf; + U2fAuthReq* req = apdu_command_data(cmd); + U2fAuthResp* resp = (U2fAuthResp*)out_buf; uint8_t priv_key[32]; uint8_t mac_control[32]; hmac_sha256_context hmac_ctx; @@ -262,7 +270,7 @@ static uint16_t u2f_authenticate(U2fData* U2F, uint8_t* buf) { if(u2f_data_check(false) == false) { U2F->ready = false; if(U2F->callback != NULL) U2F->callback(U2fNotifyError, U2F->context); - memcpy(&buf[0], state_not_supported, 2); + memcpy(&out_buf[0], state_not_supported, 2); return 2; } @@ -270,8 +278,8 @@ static uint16_t u2f_authenticate(U2fData* U2F, uint8_t* buf) { if(U2F->user_present == true) { flags |= 1; } else { - if(req->p1 == U2fEnforce) { - memcpy(&buf[0], state_user_missing, 2); + if (cmd->p1 == U2fEnforce) { + memcpy(&out_buf[0], state_user_missing, 2); return 2; } } @@ -302,12 +310,12 @@ static uint16_t u2f_authenticate(U2fData* U2F, uint8_t* buf) { if(memcmp(req->key_handle.hash, mac_control, 32) != 0) { FURI_LOG_W(TAG, "Wrong handle!"); - memcpy(&buf[0], state_wrong_data, 2); + memcpy(&out_buf[0], state_wrong_data, 2); return 2; } - if(req->p1 == U2fCheckOnly) { // Check-only: don't need to send full response - memcpy(&buf[0], state_user_missing, 2); + if (cmd->p1 == U2fCheckOnly) { // Check-only: don't need to send full response + memcpy(&out_buf[0], state_user_missing, 2); return 2; } @@ -327,36 +335,69 @@ static uint16_t u2f_authenticate(U2fData* U2F, uint8_t* buf) { return (sizeof(U2fAuthResp) + signature_len + 2); } -uint16_t u2f_msg_parse(U2fData* U2F, uint8_t* buf, uint16_t len) { +uint16_t u2f_applet_selection(const uint8_t* in_buf, uint8_t* out_buf) { + U2fApduCommand* cmd = (U2fApduCommand*)in_buf; + uint8_t* data = apdu_command_data(cmd); + + FURI_LOG_D( + TAG, + "len=%d %02x%02x%02x%02x%02x%02x%02x%02x", + cmd->len[0], + data[0], + data[1], + data[2], + data[3], + data[4], + data[5], + data[6], + data[7]); + + if (cmd->len[0] != 8 || memcmp(rid_ac_ax, data, 8) != 0) { + memcpy(&out_buf[0], state_app_not_found, 2); + return 2; + } + + memcpy(&out_buf[0], ver_str, 6); + memcpy(&out_buf[6], state_no_error, 2); + return 8; +} + +uint16_t u2f_msg_parse(U2fData* U2F, const uint8_t* in_buf, uint16_t in_len, uint8_t* out_buf) { furi_assert(U2F); - if(!U2F->ready) return 0; - if((buf[0] != 0x00) && (len < 5)) return 0; - if(buf[1] == U2F_CMD_REGISTER) { // Register request - return u2f_register(U2F, buf); - - } else if(buf[1] == U2F_CMD_AUTHENTICATE) { // Authenticate request - return u2f_authenticate(U2F, buf); - - } else if(buf[1] == U2F_CMD_VERSION) { // Get U2F version string - memcpy(&buf[0], ver_str, 6); - memcpy(&buf[6], state_no_error, 2); + if (!U2F->ready) return 0; + if ((in_buf[0] != 0x00) && (in_len < 5)) return 0; + FURI_LOG_D(TAG, "ins=0x%02x", in_buf[1]); + if (in_buf[1] == U2F_CMD_REGISTER) { // Register request + return u2f_register(U2F, in_buf, out_buf); + } + else if (in_buf[1] == U2F_CMD_AUTHENTICATE) { // Authenticate request + return u2f_authenticate(U2F, in_buf, out_buf); + } + else if (in_buf[1] == U2F_CMD_VERSION) { // Get U2F version string + memcpy(&out_buf[0], ver_str, 6); + memcpy(&out_buf[6], state_no_error, 2); return 8; - } else { - memcpy(&buf[0], state_not_supported, 2); + } + else if (in_buf[1] == U2F_CMD_APPLET_SELECTION) { + return u2f_applet_selection(in_buf, out_buf); + } + else { + memcpy(&out_buf[0], state_not_supported, 2); return 2; } return 0; } void u2f_wink(U2fData* U2F) { - if(U2F->callback != NULL) U2F->callback(U2fNotifyWink, U2F->context); + if (U2F->callback != NULL) U2F->callback(U2fNotifyWink, U2F->context); } void u2f_set_state(U2fData* U2F, uint8_t state) { - if(state == 0) { - if(U2F->callback != NULL) U2F->callback(U2fNotifyDisconnect, U2F->context); - } else { - if(U2F->callback != NULL) U2F->callback(U2fNotifyConnect, U2F->context); + if (state == 0) { + if (U2F->callback != NULL) U2F->callback(U2fNotifyDisconnect, U2F->context); + } + else { + if (U2F->callback != NULL) U2F->callback(U2fNotifyConnect, U2F->context); } U2F->user_present = false; } diff --git a/applications/main/u2f/u2f.h b/applications/main/u2f/u2f.h index dcd7c3ff2..e7508dfa5 100644 --- a/applications/main/u2f/u2f.h +++ b/applications/main/u2f/u2f.h @@ -6,6 +6,14 @@ extern "C" { #include +typedef struct { + uint8_t cla; + uint8_t ins; + uint8_t p1; + uint8_t p2; + uint8_t len[]; +} __attribute__((packed)) U2fApduCommand; + typedef enum { U2fNotifyRegister, U2fNotifyAuth, @@ -30,7 +38,7 @@ void u2f_set_event_callback(U2fData* instance, U2fEvtCallback callback, void* co void u2f_confirm_user_present(U2fData* instance); -uint16_t u2f_msg_parse(U2fData* instance, uint8_t* buf, uint16_t len); +uint16_t u2f_msg_parse(U2fData* instance, const uint8_t* in_buf, uint16_t len, uint8_t* out_buf); void u2f_wink(U2fData* instance); diff --git a/applications/main/u2f/u2f_app_i.h b/applications/main/u2f/u2f_app_i.h index 2896684c3..cfaf3a929 100644 --- a/applications/main/u2f/u2f_app_i.h +++ b/applications/main/u2f/u2f_app_i.h @@ -13,6 +13,7 @@ #include #include #include "views/u2f_view.h" +#include "u2f_nfc.h" #include "u2f_hid.h" #include "u2f.h" @@ -54,6 +55,7 @@ struct U2fApp { Widget* widget; FuriTimer* timer; U2fHid* u2f_hid; + U2fNfc* u2f_nfc; U2fView* u2f_view; U2fData* u2f_instance; GpioCustomEvent event_cur; diff --git a/applications/main/u2f/u2f_hid.c b/applications/main/u2f/u2f_hid.c index 9b625c1f3..4ca49a3bb 100644 --- a/applications/main/u2f/u2f_hid.c +++ b/applications/main/u2f/u2f_hid.c @@ -140,8 +140,11 @@ static bool u2f_hid_parse_request(U2fHid* u2f_hid) { } else if(u2f_hid->packet.cmd == U2F_HID_MSG) { // MSG - U2F message if((u2f_hid->lock == true) && (u2f_hid->packet.cid != u2f_hid->lock_cid)) return false; - uint16_t resp_len = - u2f_msg_parse(u2f_hid->u2f_instance, u2f_hid->packet.payload, u2f_hid->packet.len); + uint16_t resp_len = u2f_msg_parse( + u2f_hid->u2f_instance, + u2f_hid->packet.payload, + u2f_hid->packet.len, + u2f_hid->packet.payload); if(resp_len > 0) { u2f_hid->packet.len = resp_len; u2f_hid_send_response(u2f_hid); diff --git a/applications/main/u2f/u2f_nfc.c b/applications/main/u2f/u2f_nfc.c new file mode 100644 index 000000000..9ee97ad2a --- /dev/null +++ b/applications/main/u2f/u2f_nfc.c @@ -0,0 +1,187 @@ +#include "u2f_nfc.h" +#include "furi_hal.h" +#include "u2f.h" + +#define TAG "U2F_NFC" + +typedef enum { + WorkerEvtReserved = (1 << 0), + WorkerEvtStop = (1 << 1), +} WorkerEvtFlags; + +struct U2fNfc { + FuriThread* thread; + U2fData* u2f_instance; + uint8_t payload[65535]; + uint16_t payload_len; + uint16_t payload_cursor; +}; + +static uint16_t +u2f_callback(U2fNfc* u2f_nfc, const uint8_t* buff_rx, uint16_t buff_rx_len, uint8_t* buff_tx) { + U2fApduCommand* cmd = (U2fApduCommand*)buff_rx; + if (cmd->ins == 0xC0) { + if (u2f_nfc->payload_len == 0) { + FURI_LOG_E(TAG, "requested block but not chaining"); + buff_tx[0] = 0x69; + buff_tx[1] = 0x00; + return 2; + } + + FURI_LOG_T(TAG, "continued chaining %d/%d", u2f_nfc->payload_cursor, u2f_nfc->payload_len); + + uint16_t max_resp_len = cmd->len[0]; + if (max_resp_len == 0) { + max_resp_len = 256; + } + + uint16_t remaining_len = (u2f_nfc->payload_len - 2) - u2f_nfc->payload_cursor; + if (remaining_len > max_resp_len) { + memcpy(buff_tx, &u2f_nfc->payload[u2f_nfc->payload_cursor], max_resp_len); + remaining_len -= max_resp_len; + buff_tx[max_resp_len] = 0x61; + if (remaining_len >= 256) { + buff_tx[max_resp_len + 1] = 0x00; + } + else { + buff_tx[max_resp_len + 1] = remaining_len; + } + u2f_nfc->payload_cursor += max_resp_len; + return max_resp_len + 2; + } + else { + memcpy( + buff_tx, + &u2f_nfc->payload[u2f_nfc->payload_cursor], + u2f_nfc->payload_len - u2f_nfc->payload_cursor); + u2f_nfc->payload_len = 0; + return remaining_len; + } + } + + // Presence is implied by touching the NFC devices. + u2f_confirm_user_present(u2f_nfc->u2f_instance); + + u2f_nfc->payload_len = + u2f_msg_parse(u2f_nfc->u2f_instance, buff_rx, buff_rx_len, u2f_nfc->payload); + + // If this is extended format, send entire response at once + if (cmd->len[0] == 0) { + FURI_LOG_T(TAG, "single extended response"); + memcpy(&buff_tx, u2f_nfc->payload, u2f_nfc->payload_len); + uint16_t len = u2f_nfc->payload_len; + u2f_nfc->payload_len = 0; + return len; + } + + // Otherwise, we need to do chaining. + uint16_t max_resp_len = 256; + + // If this message happens to be less than the chaining size, send it all at once. + if ((u2f_nfc->payload_len - 2) <= max_resp_len) { + FURI_LOG_T(TAG, "single short response"); + memcpy(buff_tx, u2f_nfc->payload, u2f_nfc->payload_len); + uint16_t len = u2f_nfc->payload_len; + u2f_nfc->payload_len = 0; + return len; + } + else { + memcpy(buff_tx, u2f_nfc->payload, max_resp_len); + buff_tx[max_resp_len] = 0x61; + uint16_t remaining_len = (u2f_nfc->payload_len - 2) - max_resp_len; + if (remaining_len >= max_resp_len) { + buff_tx[max_resp_len + 1] = 0x00; + } + else { + buff_tx[max_resp_len + 1] = remaining_len; + } + u2f_nfc->payload_cursor = max_resp_len; + FURI_LOG_T( + TAG, "started u2f chaining %d/%d", u2f_nfc->payload_cursor, u2f_nfc->payload_len); + return max_resp_len + 2; + } +} + +static int32_t u2f_nfc_worker(void* context) { + U2fNfc* u2f_nfc = context; + FURI_LOG_D(TAG, "Init"); + while (furi_hal_nfc_is_busy()) { + furi_delay_ms(10); + } + FuriHalNfcDevData params = { + // TODO: Randomize this or something? + .uid = {0xCF, 0x72, 0xd4, 0x40}, + .uid_len = 4, + .atqa = {0x00, 0x04}, + .sak = 0x20, + .type = FuriHalNfcTypeA, + .interface = FuriHalNfcInterfaceIsoDep, + }; + + furi_hal_nfc_exit_sleep(); + + FURI_LOG_D(TAG, "Start"); + + while (1) { + uint32_t flags = furi_thread_flags_wait(WorkerEvtStop, FuriFlagWaitAny, 10); + if (flags != FuriFlagErrorTimeout) { + furi_check((flags & FuriFlagError) == 0); + if (flags & WorkerEvtStop) break; + } + if (!furi_hal_nfc_listen(¶ms, false, 200)) { + FURI_LOG_T(TAG, "wtf"); + continue; + } + FuriHalNfcTxRxContext tx_rx = {}; + tx_rx.tx_bits = 0; + tx_rx.tx_rx_type = FuriHalNfcTxRxTypeDefault; + if (!furi_hal_nfc_tx_rx(&tx_rx, 300)) continue; + if (tx_rx.rx_bits == 0) continue; + u2f_nfc->payload_len = 0; + u2f_nfc->payload_cursor = 0; + while (true) { + uint16_t payload_len = + u2f_callback(u2f_nfc, tx_rx.rx_data, tx_rx.rx_bits / 8, tx_rx.tx_data); + tx_rx.rx_bits = 0; + FURI_LOG_T(TAG, "payload_len=%d", payload_len); + if (payload_len == 0) { + break; + } + else { + tx_rx.tx_bits = payload_len * 8; + tx_rx.tx_rx_type = FuriHalNfcTxRxTypeDefault; + if (!furi_hal_nfc_tx_rx(&tx_rx, 300)) break; + if (tx_rx.rx_bits == 0) break; + } + } + } + + FURI_LOG_D(TAG, "Cleanup"); + furi_hal_nfc_sleep(); + FURI_LOG_D(TAG, "End"); + return 0; +} + +U2fNfc* u2f_nfc_start(U2fData* u2f_inst) { + U2fNfc* u2f_nfc = malloc(sizeof(U2fNfc)); + u2f_nfc->u2f_instance = u2f_inst; + u2f_nfc->payload_len = 0; + u2f_nfc->payload_cursor = 0; + + u2f_nfc->thread = furi_thread_alloc(); + furi_thread_set_name(u2f_nfc->thread, "U2fNFCWorker"); + furi_thread_set_stack_size(u2f_nfc->thread, 4096); + furi_thread_set_context(u2f_nfc->thread, u2f_nfc); + furi_thread_set_callback(u2f_nfc->thread, u2f_nfc_worker); + furi_thread_start(u2f_nfc->thread); + + return u2f_nfc; +} + +void u2f_nfc_stop(U2fNfc* u2f_nfc) { + furi_assert(u2f_nfc); + furi_thread_flags_set(furi_thread_get_id(u2f_nfc->thread), WorkerEvtStop); + furi_thread_join(u2f_nfc->thread); + furi_thread_free(u2f_nfc->thread); + free(u2f_nfc); +} diff --git a/applications/main/u2f/u2f_nfc.h b/applications/main/u2f/u2f_nfc.h new file mode 100644 index 000000000..c3018f601 --- /dev/null +++ b/applications/main/u2f/u2f_nfc.h @@ -0,0 +1,17 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "u2f.h" + + typedef struct U2fNfc U2fNfc; + + U2fNfc* u2f_nfc_start(U2fData* u2f_inst); + + void u2f_nfc_stop(U2fNfc* u2f_hid); + +#ifdef __cplusplus +} +#endif diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index 9e38f6970..1874b664b 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,12.0,, +Version,+,13.0,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -1198,7 +1198,7 @@ Function,+,furi_hal_nfc_field_on,void, Function,-,furi_hal_nfc_init,void, Function,+,furi_hal_nfc_is_busy,_Bool, Function,+,furi_hal_nfc_is_init,_Bool, -Function,+,furi_hal_nfc_listen,_Bool,"uint8_t*, uint8_t, uint8_t*, uint8_t, _Bool, uint32_t" +Function,+,furi_hal_nfc_listen,_Bool,"FuriHalNfcDevData*, _Bool, uint32_t" Function,+,furi_hal_nfc_listen_rx,_Bool,"FuriHalNfcTxRxContext*, uint32_t" Function,+,furi_hal_nfc_listen_sleep,void, Function,+,furi_hal_nfc_listen_start,void,FuriHalNfcDevData* diff --git a/firmware/targets/f7/furi_hal/furi_hal_nfc.c b/firmware/targets/f7/furi_hal/furi_hal_nfc.c index 6381d1a91..0923378db 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_nfc.c +++ b/firmware/targets/f7/furi_hal/furi_hal_nfc.c @@ -206,10 +206,7 @@ bool furi_hal_nfc_activate_nfca(uint32_t timeout, uint32_t* cuid) { } bool furi_hal_nfc_listen( - uint8_t* uid, - uint8_t uid_len, - uint8_t* atqa, - uint8_t sak, + FuriHalNfcDevData* nfc_data, bool activate_after_sak, uint32_t timeout) { rfalNfcState state = rfalNfcGetState(); @@ -232,16 +229,19 @@ bool furi_hal_nfc_listen( .notifyCb = NULL, .activate_after_sak = activate_after_sak, }; - if(FURI_BIT(sak, 5)) { + if (nfc_data->interface == FuriHalNfcInterfaceIsoDep) { + params.compMode = RFAL_COMPLIANCE_MODE_ISO; + } + else if (FURI_BIT(nfc_data->sak, 5)) { params.compMode = RFAL_COMPLIANCE_MODE_EMV; } else { params.compMode = RFAL_COMPLIANCE_MODE_NFC; } - params.lmConfigPA.nfcidLen = uid_len; - memcpy(params.lmConfigPA.nfcid, uid, uid_len); - params.lmConfigPA.SENS_RES[0] = atqa[0]; - params.lmConfigPA.SENS_RES[1] = atqa[1]; - params.lmConfigPA.SEL_RES = sak; + params.lmConfigPA.nfcidLen = nfc_data->uid_len; + memcpy(params.lmConfigPA.nfcid, nfc_data->uid, nfc_data->uid_len); + params.lmConfigPA.SENS_RES[0] = nfc_data->atqa[0]; + params.lmConfigPA.SENS_RES[1] = nfc_data->atqa[1]; + params.lmConfigPA.SEL_RES = nfc_data->sak; rfalNfcDiscover(¶ms); // Disable EMD suppression. diff --git a/firmware/targets/furi_hal_include/furi_hal_nfc.h b/firmware/targets/furi_hal_include/furi_hal_nfc.h index d3f6de602..79207ea71 100644 --- a/firmware/targets/furi_hal_include/furi_hal_nfc.h +++ b/firmware/targets/furi_hal_include/furi_hal_nfc.h @@ -154,6 +154,7 @@ bool furi_hal_nfc_activate_nfca(uint32_t timeout, uint32_t* cuid); /** NFC listen * * @param uid pointer to uid buffer + * @param nfc_data pointer to FuriHalNfcDevData * @param uid_len uid length * @param atqa pointer to atqa * @param sak sak @@ -163,10 +164,7 @@ bool furi_hal_nfc_activate_nfca(uint32_t timeout, uint32_t* cuid); * @return true on success */ bool furi_hal_nfc_listen( - uint8_t* uid, - uint8_t uid_len, - uint8_t* atqa, - uint8_t sak, + FuriHalNfcDevData* nfc_data, bool activate_after_sak, uint32_t timeout); diff --git a/lib/nfc/nfc_worker.c b/lib/nfc/nfc_worker.c index 4138bf033..de7e99cf2 100644 --- a/lib/nfc/nfc_worker.c +++ b/lib/nfc/nfc_worker.c @@ -776,7 +776,7 @@ void nfc_worker_emulate_uid(NfcWorker* nfc_worker) { // Need to save ATS to support ISO-14443A-4 emulation while(nfc_worker->state == NfcWorkerStateUidEmulate) { - if(furi_hal_nfc_listen(data->uid, data->uid_len, data->atqa, data->sak, false, 100)) { + if (furi_hal_nfc_listen(data, false, 100)) { if(furi_hal_nfc_tx_rx(&tx_rx, 100)) { reader_data->size = tx_rx.rx_bits / 8; if(reader_data->size > 0) { @@ -834,7 +834,7 @@ void nfc_worker_emulate_apdu(NfcWorker* nfc_worker) { } while(nfc_worker->state == NfcWorkerStateEmulateApdu) { //-V1044 - if(furi_hal_nfc_listen(params.uid, params.uid_len, params.atqa, params.sak, false, 300)) { + if (furi_hal_nfc_listen(¶ms, false, 300)) { FURI_LOG_D(TAG, "POS terminal detected"); if(emv_card_emulation(&tx_rx)) { FURI_LOG_D(TAG, "EMV card emulated"); diff --git a/scripts/flipper/assets/icon.py b/scripts/flipper/assets/icon.py index ed85b024e..c31eab0b7 100644 --- a/scripts/flipper/assets/icon.py +++ b/scripts/flipper/assets/icon.py @@ -60,7 +60,10 @@ class ImageTools: with Image.open(file) as im: with io.BytesIO() as output: bw = im.convert("1") - bw = ImageOps.invert(bw) + try: + bw = ImageOps.invert(bw) + except OSError: + bw = bw.point(lambda x: 255 - x) bw.save(output, format="XBM") return output.getvalue() From ff7c3742c093c78365b322bc451e723d189eaaec Mon Sep 17 00:00:00 2001 From: jbohack Date: Thu, 12 Jan 2023 09:48:32 -0500 Subject: [PATCH 03/60] fixed level up animations not properly being displayed --- applications/services/desktop/animations/animation_manager.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/applications/services/desktop/animations/animation_manager.c b/applications/services/desktop/animations/animation_manager.c index 041ef2d11..3bc568d6a 100644 --- a/applications/services/desktop/animations/animation_manager.c +++ b/applications/services/desktop/animations/animation_manager.c @@ -557,8 +557,6 @@ static void animation_manager_switch_to_one_shot_view(AnimationManager* animatio view_stack_remove_view(animation_manager->view_stack, prev_view); view_stack_add_view(animation_manager->view_stack, next_view); if (settings->sfw_mode) { - one_shot_view_start_animation(animation_manager->one_shot_view, &A_Levelup1_128x64); - }else { if (stats.level <= 20) { one_shot_view_start_animation(animation_manager->one_shot_view, &A_Levelup1_128x64_sfw); } @@ -568,6 +566,8 @@ static void animation_manager_switch_to_one_shot_view(AnimationManager* animatio else { furi_assert(0); } + }else { + one_shot_view_start_animation(animation_manager->one_shot_view, &A_Levelup1_128x64); } free(settings); } From 5dbb39eb05b2a492379556c7dc0dfa81a398c196 Mon Sep 17 00:00:00 2001 From: jbohack Date: Thu, 12 Jan 2023 11:15:46 -0500 Subject: [PATCH 04/60] updated authenticator (totp) --- applications/plugins/totp/cli/cli.c | 19 ++++++-- applications/plugins/totp/cli/cli.h | 10 ++++- applications/plugins/totp/cli/cli_helpers.c | 41 ++++++++++++++++++ applications/plugins/totp/cli/cli_helpers.h | 17 +++++++- .../plugins/totp/cli/commands/add/add.c | 43 +++---------------- .../plugins/totp/cli/commands/help/help.c | 3 ++ .../plugins/totp/cli/commands/reset/reset.c | 37 ++++++++++++++++ .../plugins/totp/cli/commands/reset/reset.h | 10 +++++ .../plugins/totp/services/config/config.c | 8 +++- .../plugins/totp/services/config/config.h | 7 ++- applications/plugins/totp/totp_app.c | 10 +++-- applications/plugins/totp/types/event_type.h | 5 +-- applications/plugins/totp/types/token_info.c | 2 +- .../scenes/app_settings/totp_app_settings.c | 2 +- 14 files changed, 158 insertions(+), 56 deletions(-) create mode 100644 applications/plugins/totp/cli/commands/reset/reset.c create mode 100644 applications/plugins/totp/cli/commands/reset/reset.h diff --git a/applications/plugins/totp/cli/cli.c b/applications/plugins/totp/cli/cli.c index e61c67206..8f4708f4d 100644 --- a/applications/plugins/totp/cli/cli.c +++ b/applications/plugins/totp/cli/cli.c @@ -11,6 +11,7 @@ #include "commands/move/move.h" #include "commands/pin/pin.h" #include "commands/notification/notification.h" +#include "commands/reset/reset.h" static void totp_cli_print_unknown_command(const FuriString* unknown_command) { TOTP_CLI_PRINTF( @@ -20,7 +21,8 @@ static void totp_cli_print_unknown_command(const FuriString* unknown_command) { } static void totp_cli_handler(Cli* cli, FuriString* args, void* context) { - PluginState* plugin_state = (PluginState*)context; + TotpCliContext* cli_context = context; + PluginState* plugin_state = cli_context->plugin_state; FuriString* cmd = furi_string_alloc(); @@ -55,6 +57,8 @@ static void totp_cli_handler(Cli* cli, FuriString* args, void* context) { totp_cli_command_pin_handle(plugin_state, args, cli); } else if(furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_NOTIFICATION) == 0) { totp_cli_command_notification_handle(plugin_state, args, cli); + } else if(furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_RESET) == 0) { + totp_cli_command_reset_handle(cli, cli_context->event_queue); } else { totp_cli_print_unknown_command(cmd); } @@ -62,15 +66,22 @@ static void totp_cli_handler(Cli* cli, FuriString* args, void* context) { furi_string_free(cmd); } -void totp_cli_register_command_handler(PluginState* plugin_state) { +TotpCliContext* + totp_cli_register_command_handler(PluginState* plugin_state, FuriMessageQueue* event_queue) { Cli* cli = furi_record_open(RECORD_CLI); + TotpCliContext* context = malloc(sizeof(TotpCliContext)); + furi_check(context != NULL); + context->plugin_state = plugin_state; + context->event_queue = event_queue; cli_add_command( - cli, TOTP_CLI_COMMAND_NAME, CliCommandFlagParallelSafe, totp_cli_handler, plugin_state); + cli, TOTP_CLI_COMMAND_NAME, CliCommandFlagParallelSafe, totp_cli_handler, context); furi_record_close(RECORD_CLI); + return context; } -void totp_cli_unregister_command_handler() { +void totp_cli_unregister_command_handler(TotpCliContext* context) { Cli* cli = furi_record_open(RECORD_CLI); cli_delete_command(cli, TOTP_CLI_COMMAND_NAME); furi_record_close(RECORD_CLI); + free(context); } \ No newline at end of file diff --git a/applications/plugins/totp/cli/cli.h b/applications/plugins/totp/cli/cli.h index 3eb18172c..2e4b92db8 100644 --- a/applications/plugins/totp/cli/cli.h +++ b/applications/plugins/totp/cli/cli.h @@ -3,5 +3,11 @@ #include #include "../types/plugin_state.h" -void totp_cli_register_command_handler(PluginState* plugin_state); -void totp_cli_unregister_command_handler(); \ No newline at end of file +typedef struct { + PluginState* plugin_state; + FuriMessageQueue* event_queue; +} TotpCliContext; + +TotpCliContext* + totp_cli_register_command_handler(PluginState* plugin_state, FuriMessageQueue* event_queue); +void totp_cli_unregister_command_handler(TotpCliContext* context); \ No newline at end of file diff --git a/applications/plugins/totp/cli/cli_helpers.c b/applications/plugins/totp/cli/cli_helpers.c index 0bea6fd90..984637164 100644 --- a/applications/plugins/totp/cli/cli_helpers.c +++ b/applications/plugins/totp/cli/cli_helpers.c @@ -1,5 +1,6 @@ #include "cli_helpers.h" #include +#include "../types/plugin_event.h" bool totp_cli_ensure_authenticated(const PluginState* plugin_state, Cli* cli) { if(plugin_state->current_scene == TotpSceneAuthentication) { @@ -17,5 +18,45 @@ bool totp_cli_ensure_authenticated(const PluginState* plugin_state, Cli* cli) { } } + return true; +} + +void totp_cli_force_close_app(FuriMessageQueue* event_queue) { + PluginEvent event = {.type = EventForceCloseApp}; + furi_message_queue_put(event_queue, &event, FuriWaitForever); +} + +bool totp_cli_read_line(Cli* cli, FuriString* out_str, bool mask_user_input) { + uint8_t c; + while(cli_read(cli, &c, 1) == 1) { + if(c == CliSymbolAsciiEsc) { + // Some keys generating escape-sequences + // We need to ignore them as we care about alpha-numerics only + uint8_t c2; + cli_read_timeout(cli, &c2, 1, 0); + cli_read_timeout(cli, &c2, 1, 0); + } else if(c == CliSymbolAsciiETX) { + cli_nl(); + return false; + } else if((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) { + if(mask_user_input) { + putc('*', stdout); + } else { + putc(c, stdout); + } + fflush(stdout); + furi_string_push_back(out_str, c); + } else if(c == CliSymbolAsciiBackspace || c == CliSymbolAsciiDel) { + size_t out_str_size = furi_string_size(out_str); + if(out_str_size > 0) { + TOTP_CLI_DELETE_LAST_CHAR(); + furi_string_left(out_str, out_str_size - 1); + } + } else if(c == CliSymbolAsciiCR) { + cli_nl(); + break; + } + } + return true; } \ No newline at end of file diff --git a/applications/plugins/totp/cli/cli_helpers.h b/applications/plugins/totp/cli/cli_helpers.h index ae6fe6e0c..5027d7027 100644 --- a/applications/plugins/totp/cli/cli_helpers.h +++ b/applications/plugins/totp/cli/cli_helpers.h @@ -45,7 +45,22 @@ * @brief Checks whether user is authenticated and entered correct PIN. * If user is not authenticated it prompts user to enter correct PIN to authenticate. * @param plugin_state application state - * @param cli reference to the firmware CLI subsystem + * @param cli pointer to the firmware CLI subsystem * @return \c true if user is already authenticated or successfully authenticated; \c false otherwise */ bool totp_cli_ensure_authenticated(const PluginState* plugin_state, Cli* cli); + +/** + * @brief Forces application to be instantly closed + * @param event_queue main app queue + */ +void totp_cli_force_close_app(FuriMessageQueue* event_queue); + +/** + * @brief Reads line of characters from console + * @param cli pointer to the firmware CLI subsystem + * @param out_str pointer to an output string to put read line to + * @param mask_user_input whether to mask input characters in console or not + * @return \c true if line successfully read and confirmed; \c false otherwise + */ +bool totp_cli_read_line(Cli* cli, FuriString* out_str, bool mask_user_input); diff --git a/applications/plugins/totp/cli/commands/add/add.c b/applications/plugins/totp/cli/commands/add/add.c index e037546e2..ba36a973a 100644 --- a/applications/plugins/totp/cli/commands/add/add.c +++ b/applications/plugins/totp/cli/commands/add/add.c @@ -76,43 +76,6 @@ static void furi_string_secure_free(FuriString* str) { furi_string_free(str); } -static bool totp_cli_read_secret(Cli* cli, FuriString* out_str, bool mask_user_input) { - uint8_t c; - while(cli_read(cli, &c, 1) == 1) { - if(c == CliSymbolAsciiEsc) { - // Some keys generating escape-sequences - // We need to ignore them as we care about alpha-numerics only - uint8_t c2; - cli_read_timeout(cli, &c2, 1, 0); - cli_read_timeout(cli, &c2, 1, 0); - } else if(c == CliSymbolAsciiETX) { - TOTP_CLI_DELETE_CURRENT_LINE(); - TOTP_CLI_PRINTF("Cancelled by user\r\n"); - return false; - } else if((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) { - if(mask_user_input) { - putc('*', stdout); - } else { - putc(c, stdout); - } - fflush(stdout); - furi_string_push_back(out_str, c); - } else if(c == CliSymbolAsciiBackspace || c == CliSymbolAsciiDel) { - size_t out_str_size = furi_string_size(out_str); - if(out_str_size > 0) { - TOTP_CLI_DELETE_LAST_CHAR(); - furi_string_left(out_str, out_str_size - 1); - } - } else if(c == CliSymbolAsciiCR) { - cli_nl(); - break; - } - } - - TOTP_CLI_DELETE_LAST_LINE(); - return true; -} - void totp_cli_command_add_handle(PluginState* plugin_state, FuriString* args, Cli* cli) { FuriString* temp_str = furi_string_alloc(); TokenInfo* token_info = token_info_alloc(); @@ -178,13 +141,17 @@ void totp_cli_command_add_handle(PluginState* plugin_state, FuriString* args, Cl // Reading token secret furi_string_reset(temp_str); TOTP_CLI_PRINTF("Enter token secret and confirm with [ENTER]\r\n"); - if(!totp_cli_read_secret(cli, temp_str, mask_user_input) || + if(!totp_cli_read_line(cli, temp_str, mask_user_input) || !totp_cli_ensure_authenticated(plugin_state, cli)) { + TOTP_CLI_DELETE_LAST_LINE(); + TOTP_CLI_PRINTF("Cancelled by user\r\n"); furi_string_secure_free(temp_str); token_info_free(token_info); return; } + TOTP_CLI_DELETE_LAST_LINE(); + if(!token_info_set_secret( token_info, furi_string_get_cstr(temp_str), diff --git a/applications/plugins/totp/cli/commands/help/help.c b/applications/plugins/totp/cli/commands/help/help.c index 419964880..104b39e47 100644 --- a/applications/plugins/totp/cli/commands/help/help.c +++ b/applications/plugins/totp/cli/commands/help/help.c @@ -7,6 +7,7 @@ #include "../move/move.h" #include "../pin/pin.h" #include "../notification/notification.h" +#include "../reset/reset.h" void totp_cli_command_help_docopt_commands() { TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_HELP ", " TOTP_CLI_COMMAND_HELP_ALT @@ -29,6 +30,7 @@ void totp_cli_command_help_handle() { totp_cli_command_move_docopt_usage(); totp_cli_command_pin_docopt_usage(); totp_cli_command_notification_docopt_usage(); + totp_cli_command_reset_docopt_usage(); cli_nl(); TOTP_CLI_PRINTF("Commands:\r\n"); totp_cli_command_help_docopt_commands(); @@ -39,6 +41,7 @@ void totp_cli_command_help_handle() { totp_cli_command_move_docopt_commands(); totp_cli_command_pin_docopt_commands(); totp_cli_command_notification_docopt_commands(); + totp_cli_command_reset_docopt_commands(); cli_nl(); TOTP_CLI_PRINTF("Arguments:\r\n"); totp_cli_command_add_docopt_arguments(); diff --git a/applications/plugins/totp/cli/commands/reset/reset.c b/applications/plugins/totp/cli/commands/reset/reset.c new file mode 100644 index 000000000..3f20dc8ad --- /dev/null +++ b/applications/plugins/totp/cli/commands/reset/reset.c @@ -0,0 +1,37 @@ +#include "reset.h" + +#include +#include +#include "../../cli_helpers.h" +#include "../../../services/config/config.h" + +#define TOTP_CLI_RESET_CONFIRMATION_KEYWORD "YES" + +void totp_cli_command_reset_docopt_commands() { + TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_RESET + " Reset application to default settings\r\n"); +} + +void totp_cli_command_reset_docopt_usage() { + TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_NAME " " TOTP_CLI_COMMAND_RESET "\r\n"); +} + +void totp_cli_command_reset_handle(Cli* cli, FuriMessageQueue* event_queue) { + TOTP_CLI_PRINTF( + "As a result of reset all the settings and tokens will be permanently lost.\r\n"); + TOTP_CLI_PRINTF("Do you really want to reset application?\r\n"); + TOTP_CLI_PRINTF("Type \"" TOTP_CLI_RESET_CONFIRMATION_KEYWORD + "\" and hit to confirm:\r\n"); + FuriString* temp_str = furi_string_alloc(); + bool is_confirmed = totp_cli_read_line(cli, temp_str, false) && + furi_string_cmpi_str(temp_str, TOTP_CLI_RESET_CONFIRMATION_KEYWORD) == 0; + furi_string_free(temp_str); + if(is_confirmed) { + totp_config_file_reset(); + TOTP_CLI_PRINTF("Application has been successfully reset to default.\r\n"); + TOTP_CLI_PRINTF("Now application will be closed to apply all the changes.\r\n"); + totp_cli_force_close_app(event_queue); + } else { + TOTP_CLI_PRINTF("Action was not confirmed by user\r\n"); + } +} \ No newline at end of file diff --git a/applications/plugins/totp/cli/commands/reset/reset.h b/applications/plugins/totp/cli/commands/reset/reset.h new file mode 100644 index 000000000..7c879e13e --- /dev/null +++ b/applications/plugins/totp/cli/commands/reset/reset.h @@ -0,0 +1,10 @@ +#pragma once + +#include +#include "../../../types/plugin_state.h" + +#define TOTP_CLI_COMMAND_RESET "reset" + +void totp_cli_command_reset_handle(Cli* cli, FuriMessageQueue* event_queue); +void totp_cli_command_reset_docopt_commands(); +void totp_cli_command_reset_docopt_usage(); \ No newline at end of file diff --git a/applications/plugins/totp/services/config/config.c b/applications/plugins/totp/services/config/config.c index 799db79b8..4b2090d55 100644 --- a/applications/plugins/totp/services/config/config.c +++ b/applications/plugins/totp/services/config/config.c @@ -730,4 +730,10 @@ TotpConfigFileUpdateResult totp_close_storage(); return update_result; -} \ No newline at end of file +} + +void totp_config_file_reset() { + Storage* storage = totp_open_storage(); + storage_simply_remove(storage, CONFIG_FILE_PATH); + totp_close_storage(); +} diff --git a/applications/plugins/totp/services/config/config.h b/applications/plugins/totp/services/config/config.h index bb48105f7..c630810a6 100644 --- a/applications/plugins/totp/services/config/config.h +++ b/applications/plugins/totp/services/config/config.h @@ -116,4 +116,9 @@ TotpConfigFileUpdateResult totp_config_file_update_user_settings(const PluginSta * @return Config file update result */ TotpConfigFileUpdateResult - totp_config_file_update_crypto_signatures(const PluginState* plugin_state); \ No newline at end of file + totp_config_file_update_crypto_signatures(const PluginState* plugin_state); + +/** + * @brief Reset all the settings to default + */ +void totp_config_file_reset(); \ No newline at end of file diff --git a/applications/plugins/totp/totp_app.c b/applications/plugins/totp/totp_app.c index 93acf8e4d..f10837814 100644 --- a/applications/plugins/totp/totp_app.c +++ b/applications/plugins/totp/totp_app.c @@ -143,7 +143,7 @@ int32_t totp_app() { return 255; } - totp_cli_register_command_handler(plugin_state); + TotpCliContext* cli_context = totp_cli_register_command_handler(plugin_state, event_queue); totp_scene_director_init_scenes(plugin_state); if(!totp_activate_initial_scene(plugin_state)) { FURI_LOG_E(LOGGING_TAG, "An error ocurred during activating initial scene\r\n"); @@ -172,7 +172,11 @@ int32_t totp_app() { last_user_interaction_time = furi_get_tick(); } - processing = totp_scene_director_handle_event(&event, plugin_state_m); + if(event.type == EventForceCloseApp) { + processing = false; + } else { + processing = totp_scene_director_handle_event(&event, plugin_state_m); + } } else if( plugin_state_m->pin_set && plugin_state_m->current_scene != TotpSceneAuthentication && furi_get_tick() - last_user_interaction_time > IDLE_TIMEOUT) { @@ -183,7 +187,7 @@ int32_t totp_app() { release_mutex(&state_mutex, plugin_state_m); } - totp_cli_unregister_command_handler(); + totp_cli_unregister_command_handler(cli_context); totp_scene_director_deactivate_active_scene(plugin_state); totp_scene_director_dispose(plugin_state); diff --git a/applications/plugins/totp/types/event_type.h b/applications/plugins/totp/types/event_type.h index 4fe916872..7bdf6981f 100644 --- a/applications/plugins/totp/types/event_type.h +++ b/applications/plugins/totp/types/event_type.h @@ -3,7 +3,4 @@ typedef uint8_t EventType; -enum EventTypes { - EventTypeTick, - EventTypeKey, -}; +enum EventTypes { EventTypeTick, EventTypeKey, EventForceCloseApp }; diff --git a/applications/plugins/totp/types/token_info.c b/applications/plugins/totp/types/token_info.c index a5e12ac4c..b43293788 100644 --- a/applications/plugins/totp/types/token_info.c +++ b/applications/plugins/totp/types/token_info.c @@ -28,7 +28,7 @@ bool token_info_set_secret( size_t token_secret_length, const uint8_t* iv) { if(token_secret_length == 0) return false; - + uint8_t* plain_secret = malloc(token_secret_length); furi_check(plain_secret != NULL); int plain_secret_length = diff --git a/applications/plugins/totp/ui/scenes/app_settings/totp_app_settings.c b/applications/plugins/totp/ui/scenes/app_settings/totp_app_settings.c index 5ff6b4cd7..fa4ba5411 100644 --- a/applications/plugins/totp/ui/scenes/app_settings/totp_app_settings.c +++ b/applications/plugins/totp/ui/scenes/app_settings/totp_app_settings.c @@ -247,4 +247,4 @@ void totp_scene_app_settings_deactivate(PluginState* plugin_state) { void totp_scene_app_settings_free(const PluginState* plugin_state) { UNUSED(plugin_state); -} \ No newline at end of file +} From f6abce51caa1d3cf89782955363e69cef3258329 Mon Sep 17 00:00:00 2001 From: jbohack Date: Thu, 12 Jan 2023 11:42:04 -0500 Subject: [PATCH 05/60] changed duration of sfw animations 3600-->360 cycles more frequent --- assets/dolphin/external/sfw/L1_Boxing_128x64/meta.txt | 2 +- assets/dolphin/external/sfw/L1_Cry_128x64/meta.txt | 2 +- assets/dolphin/external/sfw/L1_Furippa1_128x64/meta.txt | 2 +- assets/dolphin/external/sfw/L1_Happy_holidays_128x64/meta.txt | 2 +- assets/dolphin/external/sfw/L1_Laptop_128x51/meta.txt | 2 +- assets/dolphin/external/sfw/L1_Leaving_sad_128x64/meta.txt | 2 +- assets/dolphin/external/sfw/L1_Mad_fist_128x64/meta.txt | 2 +- assets/dolphin/external/sfw/L1_Mods_128x64/meta.txt | 2 +- assets/dolphin/external/sfw/L1_Painting_128x64/meta.txt | 2 +- assets/dolphin/external/sfw/L1_Read_books_128x64/meta.txt | 2 +- assets/dolphin/external/sfw/L1_Recording_128x51/meta.txt | 2 +- assets/dolphin/external/sfw/L1_Sleep_128x64/meta.txt | 2 +- assets/dolphin/external/sfw/L1_Sleigh_ride_128x64/meta.txt | 2 +- assets/dolphin/external/sfw/L1_Waves_128x50/meta.txt | 2 +- assets/dolphin/external/sfw/L2_Furippa2_128x64/meta.txt | 2 +- assets/dolphin/external/sfw/L2_Hacking_pc_128x64/meta.txt | 2 +- assets/dolphin/external/sfw/L2_Soldering_128x64/meta.txt | 2 +- assets/dolphin/external/sfw/L2_Wake_up_128x64/meta.txt | 2 +- assets/dolphin/external/sfw/L3_Furippa3_128x64/meta.txt | 2 +- assets/dolphin/external/sfw/L3_Hijack_radio_128x64/meta.txt | 2 +- assets/dolphin/external/sfw/L3_Lab_research_128x54/meta.txt | 2 +- assets/resources/dolphin/sfw/L1_Boxing_128x64/meta.txt | 2 +- assets/resources/dolphin/sfw/L1_Cry_128x64/meta.txt | 2 +- assets/resources/dolphin/sfw/L1_Furippa1_128x64/meta.txt | 2 +- assets/resources/dolphin/sfw/L1_Happy_holidays_128x64/meta.txt | 2 +- assets/resources/dolphin/sfw/L1_Laptop_128x51/meta.txt | 2 +- assets/resources/dolphin/sfw/L1_Leaving_sad_128x64/meta.txt | 2 +- assets/resources/dolphin/sfw/L1_Mad_fist_128x64/meta.txt | 2 +- assets/resources/dolphin/sfw/L1_Mods_128x64/meta.txt | 2 +- assets/resources/dolphin/sfw/L1_Painting_128x64/meta.txt | 2 +- assets/resources/dolphin/sfw/L1_Read_books_128x64/meta.txt | 2 +- assets/resources/dolphin/sfw/L1_Recording_128x51/meta.txt | 2 +- assets/resources/dolphin/sfw/L1_Sleep_128x64/meta.txt | 2 +- assets/resources/dolphin/sfw/L1_Sleigh_ride_128x64/meta.txt | 2 +- assets/resources/dolphin/sfw/L1_Waves_128x50/meta.txt | 2 +- assets/resources/dolphin/sfw/L2_Furippa2_128x64/meta.txt | 2 +- assets/resources/dolphin/sfw/L2_Hacking_pc_128x64/meta.txt | 2 +- assets/resources/dolphin/sfw/L2_Soldering_128x64/meta.txt | 2 +- assets/resources/dolphin/sfw/L2_Wake_up_128x64/meta.txt | 2 +- assets/resources/dolphin/sfw/L3_Furippa3_128x64/meta.txt | 2 +- assets/resources/dolphin/sfw/L3_Hijack_radio_128x64/meta.txt | 2 +- assets/resources/dolphin/sfw/L3_Lab_research_128x54/meta.txt | 2 +- 42 files changed, 42 insertions(+), 42 deletions(-) diff --git a/assets/dolphin/external/sfw/L1_Boxing_128x64/meta.txt b/assets/dolphin/external/sfw/L1_Boxing_128x64/meta.txt index c66998e7d..ec5127b8a 100644 --- a/assets/dolphin/external/sfw/L1_Boxing_128x64/meta.txt +++ b/assets/dolphin/external/sfw/L1_Boxing_128x64/meta.txt @@ -8,7 +8,7 @@ Active frames: 7 Frames order: 0 1 2 1 3 1 2 3 1 4 5 6 5 6 5 4 Active cycles: 1 Frame rate: 2 -Duration: 3600 +Duration: 360 Active cooldown: 7 Bubble slots: 2 diff --git a/assets/dolphin/external/sfw/L1_Cry_128x64/meta.txt b/assets/dolphin/external/sfw/L1_Cry_128x64/meta.txt index e96c8d7c6..ea0bf89d0 100644 --- a/assets/dolphin/external/sfw/L1_Cry_128x64/meta.txt +++ b/assets/dolphin/external/sfw/L1_Cry_128x64/meta.txt @@ -8,7 +8,7 @@ Active frames: 4 Frames order: 0 1 2 3 4 2 3 4 5 6 7 6 Active cycles: 2 Frame rate: 2 -Duration: 3600 +Duration: 360 Active cooldown: 7 Bubble slots: 2 diff --git a/assets/dolphin/external/sfw/L1_Furippa1_128x64/meta.txt b/assets/dolphin/external/sfw/L1_Furippa1_128x64/meta.txt index c21027e49..8b01676f5 100644 --- a/assets/dolphin/external/sfw/L1_Furippa1_128x64/meta.txt +++ b/assets/dolphin/external/sfw/L1_Furippa1_128x64/meta.txt @@ -8,7 +8,7 @@ Active frames: 11 Frames order: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 Active cycles: 1 Frame rate: 2 -Duration: 3600 +Duration: 360 Active cooldown: 7 Bubble slots: 0 diff --git a/assets/dolphin/external/sfw/L1_Happy_holidays_128x64/meta.txt b/assets/dolphin/external/sfw/L1_Happy_holidays_128x64/meta.txt index a2c733397..ad883525e 100644 --- a/assets/dolphin/external/sfw/L1_Happy_holidays_128x64/meta.txt +++ b/assets/dolphin/external/sfw/L1_Happy_holidays_128x64/meta.txt @@ -8,7 +8,7 @@ Active frames: 18 Frames order: 0 1 2 1 0 1 2 1 0 1 2 3 4 5 6 5 4 7 2 8 9 10 11 10 9 10 11 12 Active cycles: 1 Frame rate: 2 -Duration: 3600 +Duration: 360 Active cooldown: 7 Bubble slots: 1 diff --git a/assets/dolphin/external/sfw/L1_Laptop_128x51/meta.txt b/assets/dolphin/external/sfw/L1_Laptop_128x51/meta.txt index 90cdc5ce9..0c3edb057 100644 --- a/assets/dolphin/external/sfw/L1_Laptop_128x51/meta.txt +++ b/assets/dolphin/external/sfw/L1_Laptop_128x51/meta.txt @@ -8,7 +8,7 @@ Active frames: 2 Frames order: 0 1 2 3 4 5 6 7 Active cycles: 4 Frame rate: 2 -Duration: 3600 +Duration: 360 Active cooldown: 7 Bubble slots: 1 diff --git a/assets/dolphin/external/sfw/L1_Leaving_sad_128x64/meta.txt b/assets/dolphin/external/sfw/L1_Leaving_sad_128x64/meta.txt index 876003079..fbf7c67fc 100644 --- a/assets/dolphin/external/sfw/L1_Leaving_sad_128x64/meta.txt +++ b/assets/dolphin/external/sfw/L1_Leaving_sad_128x64/meta.txt @@ -8,7 +8,7 @@ Active frames: 42 Frames order: 0 1 2 1 3 4 5 6 7 8 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 10 11 12 4 3 Active cycles: 1 Frame rate: 2 -Duration: 3600 +Duration: 360 Active cooldown: 7 Bubble slots: 1 diff --git a/assets/dolphin/external/sfw/L1_Mad_fist_128x64/meta.txt b/assets/dolphin/external/sfw/L1_Mad_fist_128x64/meta.txt index 93e59e49b..56f380747 100644 --- a/assets/dolphin/external/sfw/L1_Mad_fist_128x64/meta.txt +++ b/assets/dolphin/external/sfw/L1_Mad_fist_128x64/meta.txt @@ -8,7 +8,7 @@ Active frames: 13 Frames order: 0 1 0 1 2 3 4 5 6 7 8 9 10 11 12 13 12 13 12 13 Active cycles: 1 Frame rate: 2 -Duration: 3600 +Duration: 360 Active cooldown: 7 Bubble slots: 1 diff --git a/assets/dolphin/external/sfw/L1_Mods_128x64/meta.txt b/assets/dolphin/external/sfw/L1_Mods_128x64/meta.txt index 0225c7e55..255fda738 100644 --- a/assets/dolphin/external/sfw/L1_Mods_128x64/meta.txt +++ b/assets/dolphin/external/sfw/L1_Mods_128x64/meta.txt @@ -8,7 +8,7 @@ Active frames: 18 Frames order: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 Active cycles: 1 Frame rate: 2 -Duration: 3600 +Duration: 360 Active cooldown: 7 Bubble slots: 0 \ No newline at end of file diff --git a/assets/dolphin/external/sfw/L1_Painting_128x64/meta.txt b/assets/dolphin/external/sfw/L1_Painting_128x64/meta.txt index 6964b479b..3676efdfe 100644 --- a/assets/dolphin/external/sfw/L1_Painting_128x64/meta.txt +++ b/assets/dolphin/external/sfw/L1_Painting_128x64/meta.txt @@ -8,7 +8,7 @@ Active frames: 13 Frames order: 0 1 2 3 4 5 2 3 4 10 6 7 8 7 8 7 8 7 8 9 10 11 Active cycles: 1 Frame rate: 2 -Duration: 3600 +Duration: 360 Active cooldown: 7 Bubble slots: 1 diff --git a/assets/dolphin/external/sfw/L1_Read_books_128x64/meta.txt b/assets/dolphin/external/sfw/L1_Read_books_128x64/meta.txt index 7432507ce..750c043d0 100644 --- a/assets/dolphin/external/sfw/L1_Read_books_128x64/meta.txt +++ b/assets/dolphin/external/sfw/L1_Read_books_128x64/meta.txt @@ -8,7 +8,7 @@ Active frames: 2 Frames order: 0 1 0 2 3 3 4 0 1 5 6 1 1 7 8 Active cycles: 2 Frame rate: 2 -Duration: 3600 +Duration: 360 Active cooldown: 5 Bubble slots: 1 diff --git a/assets/dolphin/external/sfw/L1_Recording_128x51/meta.txt b/assets/dolphin/external/sfw/L1_Recording_128x51/meta.txt index de37d5b2e..dc79b1645 100644 --- a/assets/dolphin/external/sfw/L1_Recording_128x51/meta.txt +++ b/assets/dolphin/external/sfw/L1_Recording_128x51/meta.txt @@ -8,7 +8,7 @@ Active frames: 6 Frames order: 0 1 2 3 4 5 6 7 8 9 10 11 Active cycles: 1 Frame rate: 2 -Duration: 3600 +Duration: 360 Active cooldown: 5 Bubble slots: 0 diff --git a/assets/dolphin/external/sfw/L1_Sleep_128x64/meta.txt b/assets/dolphin/external/sfw/L1_Sleep_128x64/meta.txt index 7960b0653..eea23b69c 100644 --- a/assets/dolphin/external/sfw/L1_Sleep_128x64/meta.txt +++ b/assets/dolphin/external/sfw/L1_Sleep_128x64/meta.txt @@ -8,7 +8,7 @@ Active frames: 4 Frames order: 0 1 2 3 2 3 Active cycles: 2 Frame rate: 2 -Duration: 3600 +Duration: 360 Active cooldown: 5 Bubble slots: 2 diff --git a/assets/dolphin/external/sfw/L1_Sleigh_ride_128x64/meta.txt b/assets/dolphin/external/sfw/L1_Sleigh_ride_128x64/meta.txt index 3e31e1d69..eed81079d 100644 --- a/assets/dolphin/external/sfw/L1_Sleigh_ride_128x64/meta.txt +++ b/assets/dolphin/external/sfw/L1_Sleigh_ride_128x64/meta.txt @@ -8,7 +8,7 @@ Active frames: 19 Frames order: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 Active cycles: 1 Frame rate: 2 -Duration: 3600 +Duration: 360 Active cooldown: 7 Bubble slots: 1 diff --git a/assets/dolphin/external/sfw/L1_Waves_128x50/meta.txt b/assets/dolphin/external/sfw/L1_Waves_128x50/meta.txt index c2f63b4c7..f86579634 100644 --- a/assets/dolphin/external/sfw/L1_Waves_128x50/meta.txt +++ b/assets/dolphin/external/sfw/L1_Waves_128x50/meta.txt @@ -8,7 +8,7 @@ Active frames: 4 Frames order: 0 1 2 3 2 3 Active cycles: 2 Frame rate: 2 -Duration: 3600 +Duration: 360 Active cooldown: 5 Bubble slots: 3 diff --git a/assets/dolphin/external/sfw/L2_Furippa2_128x64/meta.txt b/assets/dolphin/external/sfw/L2_Furippa2_128x64/meta.txt index c21027e49..8b01676f5 100644 --- a/assets/dolphin/external/sfw/L2_Furippa2_128x64/meta.txt +++ b/assets/dolphin/external/sfw/L2_Furippa2_128x64/meta.txt @@ -8,7 +8,7 @@ Active frames: 11 Frames order: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 Active cycles: 1 Frame rate: 2 -Duration: 3600 +Duration: 360 Active cooldown: 7 Bubble slots: 0 diff --git a/assets/dolphin/external/sfw/L2_Hacking_pc_128x64/meta.txt b/assets/dolphin/external/sfw/L2_Hacking_pc_128x64/meta.txt index 8ad8d42a3..a47eae2a9 100644 --- a/assets/dolphin/external/sfw/L2_Hacking_pc_128x64/meta.txt +++ b/assets/dolphin/external/sfw/L2_Hacking_pc_128x64/meta.txt @@ -8,7 +8,7 @@ Active frames: 2 Frames order: 0 1 2 3 4 Active cycles: 4 Frame rate: 2 -Duration: 3600 +Duration: 360 Active cooldown: 7 Bubble slots: 1 diff --git a/assets/dolphin/external/sfw/L2_Soldering_128x64/meta.txt b/assets/dolphin/external/sfw/L2_Soldering_128x64/meta.txt index b705bf623..f47cfe047 100644 --- a/assets/dolphin/external/sfw/L2_Soldering_128x64/meta.txt +++ b/assets/dolphin/external/sfw/L2_Soldering_128x64/meta.txt @@ -8,7 +8,7 @@ Active frames: 5 Frames order: 0 1 2 3 4 5 6 7 8 9 10 9 10 9 Active cycles: 1 Frame rate: 2 -Duration: 3600 +Duration: 360 Active cooldown: 7 Bubble slots: 1 diff --git a/assets/dolphin/external/sfw/L2_Wake_up_128x64/meta.txt b/assets/dolphin/external/sfw/L2_Wake_up_128x64/meta.txt index 06c710f03..c91bda1fc 100644 --- a/assets/dolphin/external/sfw/L2_Wake_up_128x64/meta.txt +++ b/assets/dolphin/external/sfw/L2_Wake_up_128x64/meta.txt @@ -8,7 +8,7 @@ Active frames: 18 Frames order: 0 1 0 1 0 1 0 2 3 4 0 5 6 7 8 9 10 11 10 12 13 14 15 16 17 18 19 20 Active cycles: 1 Frame rate: 2 -Duration: 3600 +Duration: 360 Active cooldown: 7 Bubble slots: 0 \ No newline at end of file diff --git a/assets/dolphin/external/sfw/L3_Furippa3_128x64/meta.txt b/assets/dolphin/external/sfw/L3_Furippa3_128x64/meta.txt index c21027e49..8b01676f5 100644 --- a/assets/dolphin/external/sfw/L3_Furippa3_128x64/meta.txt +++ b/assets/dolphin/external/sfw/L3_Furippa3_128x64/meta.txt @@ -8,7 +8,7 @@ Active frames: 11 Frames order: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 Active cycles: 1 Frame rate: 2 -Duration: 3600 +Duration: 360 Active cooldown: 7 Bubble slots: 0 diff --git a/assets/dolphin/external/sfw/L3_Hijack_radio_128x64/meta.txt b/assets/dolphin/external/sfw/L3_Hijack_radio_128x64/meta.txt index 1d415b4b8..8af34cdc5 100644 --- a/assets/dolphin/external/sfw/L3_Hijack_radio_128x64/meta.txt +++ b/assets/dolphin/external/sfw/L3_Hijack_radio_128x64/meta.txt @@ -8,7 +8,7 @@ Active frames: 8 Frames order: 0 1 2 3 4 5 4 6 7 8 9 10 11 12 11 13 Active cycles: 1 Frame rate: 2 -Duration: 3600 +Duration: 360 Active cooldown: 7 Bubble slots: 0 diff --git a/assets/dolphin/external/sfw/L3_Lab_research_128x54/meta.txt b/assets/dolphin/external/sfw/L3_Lab_research_128x54/meta.txt index e83a8b436..efb2f9cd5 100644 --- a/assets/dolphin/external/sfw/L3_Lab_research_128x54/meta.txt +++ b/assets/dolphin/external/sfw/L3_Lab_research_128x54/meta.txt @@ -8,7 +8,7 @@ Active frames: 8 Frames order: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 Active cycles: 1 Frame rate: 2 -Duration: 3600 +Duration: 360 Active cooldown: 7 Bubble slots: 1 diff --git a/assets/resources/dolphin/sfw/L1_Boxing_128x64/meta.txt b/assets/resources/dolphin/sfw/L1_Boxing_128x64/meta.txt index c66998e7d..ec5127b8a 100644 --- a/assets/resources/dolphin/sfw/L1_Boxing_128x64/meta.txt +++ b/assets/resources/dolphin/sfw/L1_Boxing_128x64/meta.txt @@ -8,7 +8,7 @@ Active frames: 7 Frames order: 0 1 2 1 3 1 2 3 1 4 5 6 5 6 5 4 Active cycles: 1 Frame rate: 2 -Duration: 3600 +Duration: 360 Active cooldown: 7 Bubble slots: 2 diff --git a/assets/resources/dolphin/sfw/L1_Cry_128x64/meta.txt b/assets/resources/dolphin/sfw/L1_Cry_128x64/meta.txt index 1b7d13dd8..43b4603d4 100644 --- a/assets/resources/dolphin/sfw/L1_Cry_128x64/meta.txt +++ b/assets/resources/dolphin/sfw/L1_Cry_128x64/meta.txt @@ -8,7 +8,7 @@ Active frames: 4 Frames order: 0 1 2 3 4 2 3 4 5 6 7 6 Active cycles: 2 Frame rate: 2 -Duration: 3600 +Duration: 360 Active cooldown: 7 Bubble slots: 2 diff --git a/assets/resources/dolphin/sfw/L1_Furippa1_128x64/meta.txt b/assets/resources/dolphin/sfw/L1_Furippa1_128x64/meta.txt index c21027e49..8b01676f5 100644 --- a/assets/resources/dolphin/sfw/L1_Furippa1_128x64/meta.txt +++ b/assets/resources/dolphin/sfw/L1_Furippa1_128x64/meta.txt @@ -8,7 +8,7 @@ Active frames: 11 Frames order: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 Active cycles: 1 Frame rate: 2 -Duration: 3600 +Duration: 360 Active cooldown: 7 Bubble slots: 0 diff --git a/assets/resources/dolphin/sfw/L1_Happy_holidays_128x64/meta.txt b/assets/resources/dolphin/sfw/L1_Happy_holidays_128x64/meta.txt index 6c50a40ed..d99fe14b9 100644 --- a/assets/resources/dolphin/sfw/L1_Happy_holidays_128x64/meta.txt +++ b/assets/resources/dolphin/sfw/L1_Happy_holidays_128x64/meta.txt @@ -8,7 +8,7 @@ Active frames: 18 Frames order: 0 1 2 1 0 1 2 1 0 1 2 3 4 5 6 5 4 7 2 8 9 10 11 10 9 10 11 12 Active cycles: 1 Frame rate: 2 -Duration: 3600 +Duration: 360 Active cooldown: 7 Bubble slots: 1 diff --git a/assets/resources/dolphin/sfw/L1_Laptop_128x51/meta.txt b/assets/resources/dolphin/sfw/L1_Laptop_128x51/meta.txt index 90cdc5ce9..0c3edb057 100644 --- a/assets/resources/dolphin/sfw/L1_Laptop_128x51/meta.txt +++ b/assets/resources/dolphin/sfw/L1_Laptop_128x51/meta.txt @@ -8,7 +8,7 @@ Active frames: 2 Frames order: 0 1 2 3 4 5 6 7 Active cycles: 4 Frame rate: 2 -Duration: 3600 +Duration: 360 Active cooldown: 7 Bubble slots: 1 diff --git a/assets/resources/dolphin/sfw/L1_Leaving_sad_128x64/meta.txt b/assets/resources/dolphin/sfw/L1_Leaving_sad_128x64/meta.txt index 876003079..fbf7c67fc 100644 --- a/assets/resources/dolphin/sfw/L1_Leaving_sad_128x64/meta.txt +++ b/assets/resources/dolphin/sfw/L1_Leaving_sad_128x64/meta.txt @@ -8,7 +8,7 @@ Active frames: 42 Frames order: 0 1 2 1 3 4 5 6 7 8 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 10 11 12 4 3 Active cycles: 1 Frame rate: 2 -Duration: 3600 +Duration: 360 Active cooldown: 7 Bubble slots: 1 diff --git a/assets/resources/dolphin/sfw/L1_Mad_fist_128x64/meta.txt b/assets/resources/dolphin/sfw/L1_Mad_fist_128x64/meta.txt index 93e59e49b..56f380747 100644 --- a/assets/resources/dolphin/sfw/L1_Mad_fist_128x64/meta.txt +++ b/assets/resources/dolphin/sfw/L1_Mad_fist_128x64/meta.txt @@ -8,7 +8,7 @@ Active frames: 13 Frames order: 0 1 0 1 2 3 4 5 6 7 8 9 10 11 12 13 12 13 12 13 Active cycles: 1 Frame rate: 2 -Duration: 3600 +Duration: 360 Active cooldown: 7 Bubble slots: 1 diff --git a/assets/resources/dolphin/sfw/L1_Mods_128x64/meta.txt b/assets/resources/dolphin/sfw/L1_Mods_128x64/meta.txt index c9c35ee41..40dc021bf 100644 --- a/assets/resources/dolphin/sfw/L1_Mods_128x64/meta.txt +++ b/assets/resources/dolphin/sfw/L1_Mods_128x64/meta.txt @@ -8,7 +8,7 @@ Active frames: 18 Frames order: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 Active cycles: 1 Frame rate: 2 -Duration: 3600 +Duration: 360 Active cooldown: 7 Bubble slots: 0 diff --git a/assets/resources/dolphin/sfw/L1_Painting_128x64/meta.txt b/assets/resources/dolphin/sfw/L1_Painting_128x64/meta.txt index e5f5fc0a6..b0b88fbbd 100644 --- a/assets/resources/dolphin/sfw/L1_Painting_128x64/meta.txt +++ b/assets/resources/dolphin/sfw/L1_Painting_128x64/meta.txt @@ -8,7 +8,7 @@ Active frames: 13 Frames order: 0 1 2 3 4 5 2 3 4 10 6 7 8 7 8 7 8 7 8 9 10 11 Active cycles: 1 Frame rate: 2 -Duration: 3600 +Duration: 360 Active cooldown: 7 Bubble slots: 1 diff --git a/assets/resources/dolphin/sfw/L1_Read_books_128x64/meta.txt b/assets/resources/dolphin/sfw/L1_Read_books_128x64/meta.txt index 7432507ce..750c043d0 100644 --- a/assets/resources/dolphin/sfw/L1_Read_books_128x64/meta.txt +++ b/assets/resources/dolphin/sfw/L1_Read_books_128x64/meta.txt @@ -8,7 +8,7 @@ Active frames: 2 Frames order: 0 1 0 2 3 3 4 0 1 5 6 1 1 7 8 Active cycles: 2 Frame rate: 2 -Duration: 3600 +Duration: 360 Active cooldown: 5 Bubble slots: 1 diff --git a/assets/resources/dolphin/sfw/L1_Recording_128x51/meta.txt b/assets/resources/dolphin/sfw/L1_Recording_128x51/meta.txt index de37d5b2e..dc79b1645 100644 --- a/assets/resources/dolphin/sfw/L1_Recording_128x51/meta.txt +++ b/assets/resources/dolphin/sfw/L1_Recording_128x51/meta.txt @@ -8,7 +8,7 @@ Active frames: 6 Frames order: 0 1 2 3 4 5 6 7 8 9 10 11 Active cycles: 1 Frame rate: 2 -Duration: 3600 +Duration: 360 Active cooldown: 5 Bubble slots: 0 diff --git a/assets/resources/dolphin/sfw/L1_Sleep_128x64/meta.txt b/assets/resources/dolphin/sfw/L1_Sleep_128x64/meta.txt index ffd845e8c..589f46294 100644 --- a/assets/resources/dolphin/sfw/L1_Sleep_128x64/meta.txt +++ b/assets/resources/dolphin/sfw/L1_Sleep_128x64/meta.txt @@ -8,7 +8,7 @@ Active frames: 4 Frames order: 0 1 2 3 2 3 Active cycles: 2 Frame rate: 2 -Duration: 3600 +Duration: 360 Active cooldown: 5 Bubble slots: 2 diff --git a/assets/resources/dolphin/sfw/L1_Sleigh_ride_128x64/meta.txt b/assets/resources/dolphin/sfw/L1_Sleigh_ride_128x64/meta.txt index 3e31e1d69..eed81079d 100644 --- a/assets/resources/dolphin/sfw/L1_Sleigh_ride_128x64/meta.txt +++ b/assets/resources/dolphin/sfw/L1_Sleigh_ride_128x64/meta.txt @@ -8,7 +8,7 @@ Active frames: 19 Frames order: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 Active cycles: 1 Frame rate: 2 -Duration: 3600 +Duration: 360 Active cooldown: 7 Bubble slots: 1 diff --git a/assets/resources/dolphin/sfw/L1_Waves_128x50/meta.txt b/assets/resources/dolphin/sfw/L1_Waves_128x50/meta.txt index 376447af7..edc7ebe99 100644 --- a/assets/resources/dolphin/sfw/L1_Waves_128x50/meta.txt +++ b/assets/resources/dolphin/sfw/L1_Waves_128x50/meta.txt @@ -8,7 +8,7 @@ Active frames: 4 Frames order: 0 1 2 3 2 3 Active cycles: 2 Frame rate: 2 -Duration: 3600 +Duration: 360 Active cooldown: 5 Bubble slots: 3 diff --git a/assets/resources/dolphin/sfw/L2_Furippa2_128x64/meta.txt b/assets/resources/dolphin/sfw/L2_Furippa2_128x64/meta.txt index c21027e49..8b01676f5 100644 --- a/assets/resources/dolphin/sfw/L2_Furippa2_128x64/meta.txt +++ b/assets/resources/dolphin/sfw/L2_Furippa2_128x64/meta.txt @@ -8,7 +8,7 @@ Active frames: 11 Frames order: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 Active cycles: 1 Frame rate: 2 -Duration: 3600 +Duration: 360 Active cooldown: 7 Bubble slots: 0 diff --git a/assets/resources/dolphin/sfw/L2_Hacking_pc_128x64/meta.txt b/assets/resources/dolphin/sfw/L2_Hacking_pc_128x64/meta.txt index 8ad8d42a3..a47eae2a9 100644 --- a/assets/resources/dolphin/sfw/L2_Hacking_pc_128x64/meta.txt +++ b/assets/resources/dolphin/sfw/L2_Hacking_pc_128x64/meta.txt @@ -8,7 +8,7 @@ Active frames: 2 Frames order: 0 1 2 3 4 Active cycles: 4 Frame rate: 2 -Duration: 3600 +Duration: 360 Active cooldown: 7 Bubble slots: 1 diff --git a/assets/resources/dolphin/sfw/L2_Soldering_128x64/meta.txt b/assets/resources/dolphin/sfw/L2_Soldering_128x64/meta.txt index b705bf623..f47cfe047 100644 --- a/assets/resources/dolphin/sfw/L2_Soldering_128x64/meta.txt +++ b/assets/resources/dolphin/sfw/L2_Soldering_128x64/meta.txt @@ -8,7 +8,7 @@ Active frames: 5 Frames order: 0 1 2 3 4 5 6 7 8 9 10 9 10 9 Active cycles: 1 Frame rate: 2 -Duration: 3600 +Duration: 360 Active cooldown: 7 Bubble slots: 1 diff --git a/assets/resources/dolphin/sfw/L2_Wake_up_128x64/meta.txt b/assets/resources/dolphin/sfw/L2_Wake_up_128x64/meta.txt index 8ae3b093d..08de0bbc0 100644 --- a/assets/resources/dolphin/sfw/L2_Wake_up_128x64/meta.txt +++ b/assets/resources/dolphin/sfw/L2_Wake_up_128x64/meta.txt @@ -8,7 +8,7 @@ Active frames: 18 Frames order: 0 1 0 1 0 1 0 2 3 4 0 5 6 7 8 9 10 11 10 12 13 14 15 16 17 18 19 20 Active cycles: 1 Frame rate: 2 -Duration: 3600 +Duration: 360 Active cooldown: 7 Bubble slots: 0 diff --git a/assets/resources/dolphin/sfw/L3_Furippa3_128x64/meta.txt b/assets/resources/dolphin/sfw/L3_Furippa3_128x64/meta.txt index c21027e49..8b01676f5 100644 --- a/assets/resources/dolphin/sfw/L3_Furippa3_128x64/meta.txt +++ b/assets/resources/dolphin/sfw/L3_Furippa3_128x64/meta.txt @@ -8,7 +8,7 @@ Active frames: 11 Frames order: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 Active cycles: 1 Frame rate: 2 -Duration: 3600 +Duration: 360 Active cooldown: 7 Bubble slots: 0 diff --git a/assets/resources/dolphin/sfw/L3_Hijack_radio_128x64/meta.txt b/assets/resources/dolphin/sfw/L3_Hijack_radio_128x64/meta.txt index 1d415b4b8..8af34cdc5 100644 --- a/assets/resources/dolphin/sfw/L3_Hijack_radio_128x64/meta.txt +++ b/assets/resources/dolphin/sfw/L3_Hijack_radio_128x64/meta.txt @@ -8,7 +8,7 @@ Active frames: 8 Frames order: 0 1 2 3 4 5 4 6 7 8 9 10 11 12 11 13 Active cycles: 1 Frame rate: 2 -Duration: 3600 +Duration: 360 Active cooldown: 7 Bubble slots: 0 diff --git a/assets/resources/dolphin/sfw/L3_Lab_research_128x54/meta.txt b/assets/resources/dolphin/sfw/L3_Lab_research_128x54/meta.txt index e83a8b436..efb2f9cd5 100644 --- a/assets/resources/dolphin/sfw/L3_Lab_research_128x54/meta.txt +++ b/assets/resources/dolphin/sfw/L3_Lab_research_128x54/meta.txt @@ -8,7 +8,7 @@ Active frames: 8 Frames order: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 Active cycles: 1 Frame rate: 2 -Duration: 3600 +Duration: 360 Active cooldown: 7 Bubble slots: 1 From 53ba8beeee1f52ce7d5177586d2a53b0829f5d02 Mon Sep 17 00:00:00 2001 From: VerstreuteSeele Date: Thu, 12 Jan 2023 22:25:53 +0100 Subject: [PATCH 06/60] Create FlipperPlaylist.py --- scripts/FlipperPlaylist.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 scripts/FlipperPlaylist.py diff --git a/scripts/FlipperPlaylist.py b/scripts/FlipperPlaylist.py new file mode 100644 index 000000000..b77fcbb8b --- /dev/null +++ b/scripts/FlipperPlaylist.py @@ -0,0 +1,21 @@ +# Flipper Zero SUB-GHZ Playlist Generator +import os + + +def windows(): + folder_path = str(input("Enter the path for the folder: ")) + playlist_name = str(input("Enter a name for the playlist: ")) + playlist_file = open((r"C:\Users\\fisch\\Downloads\\" + playlist_name.lower() + ".txt"), "w") + playlist_file.write("# " + playlist_name + "\n") + for root, dirs, files in os.walk(folder_path, topdown=True): + for file in files: + if file.endswith(".sub"): + file_path = os.path.join(root, file) + file_path = file_path.replace("\\", "/") + file_path = file_path.replace("E:", "ext") + playlist_file.write(f"sub: {file_path}\n") + playlist_file.close() + print("Done!") + + +windows() \ No newline at end of file From 8cf961382bc3ec648fc095dbf6b0ba97fd7f6fe4 Mon Sep 17 00:00:00 2001 From: VerstreuteSeele Date: Fri, 13 Jan 2023 13:48:40 +0100 Subject: [PATCH 07/60] Optimized playlist creator --- scripts/FlipperPlaylist.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/scripts/FlipperPlaylist.py b/scripts/FlipperPlaylist.py index b77fcbb8b..90d0a4899 100644 --- a/scripts/FlipperPlaylist.py +++ b/scripts/FlipperPlaylist.py @@ -1,21 +1,22 @@ # Flipper Zero SUB-GHZ Playlist Generator import os +from easygui import fileopenbox, diropenbox - -def windows(): - folder_path = str(input("Enter the path for the folder: ")) +def main(): + folder_path = diropenbox("Select the folder with Subghz files", "Subghz selector") + output_path = diropenbox("Select your output location", "Output location") playlist_name = str(input("Enter a name for the playlist: ")) - playlist_file = open((r"C:\Users\\fisch\\Downloads\\" + playlist_name.lower() + ".txt"), "w") + playlist_file = open((output_path + playlist_name.lower() + ".txt"), "w") playlist_file.write("# " + playlist_name + "\n") for root, dirs, files in os.walk(folder_path, topdown=True): for file in files: if file.endswith(".sub"): file_path = os.path.join(root, file) file_path = file_path.replace("\\", "/") - file_path = file_path.replace("E:", "ext") + file_path = file_path.replace(f"{folder_path.split(':')[0]}:", "ext") playlist_file.write(f"sub: {file_path}\n") playlist_file.close() print("Done!") - -windows() \ No newline at end of file +if __name__ == '__main__': + main() \ No newline at end of file From 332abdacbb1756cc9145f16586e656a05e160510 Mon Sep 17 00:00:00 2001 From: VerstreuteSeele Date: Fri, 13 Jan 2023 13:51:05 +0100 Subject: [PATCH 08/60] Automating import install for playlist script --- scripts/FlipperPlaylist.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/scripts/FlipperPlaylist.py b/scripts/FlipperPlaylist.py index 90d0a4899..1ff7f8532 100644 --- a/scripts/FlipperPlaylist.py +++ b/scripts/FlipperPlaylist.py @@ -1,6 +1,11 @@ # Flipper Zero SUB-GHZ Playlist Generator import os -from easygui import fileopenbox, diropenbox +import pip +try: + from easygui import fileopenbox, diropenbox +except ImportError: + pip.main(['Install'], "easygui") + from easygui import fileopenbox, diropenbox def main(): folder_path = diropenbox("Select the folder with Subghz files", "Subghz selector") From 75e9de12b065bd5e572b8b9232c8b9670c8e6f91 Mon Sep 17 00:00:00 2001 From: Georgii Surkov <37121527+gsurkov@users.noreply.github.com> Date: Fri, 13 Jan 2023 16:50:19 +0300 Subject: [PATCH 09/60] [FL-3078] Per protocol signal repeat count (#2293) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Better Infrared protocol file structure * Rename InfraredProtocolSpec to InfraredProtocolVariant * Slightly better names * Add repeat count field to protocol variant description * Repeat the signal the appropriate number of times when brute-forcing * Repeat the signal the appropriate number of times when sending via worker * Better signal count logic in infrared_transmit * Better variable names * Convert some raw signals to messages in tv.ir Co-authored-by: あく --- assets/resources/infrared/assets/tv.ir | 814 +++++++++--------- firmware/targets/f7/api_symbols.csv | 3 +- .../common/infrared_common_decoder.c | 9 +- .../common/infrared_common_encoder.c | 11 +- .../common/infrared_common_protocol_defs.c | 140 --- lib/infrared/encoder_decoder/infrared.c | 63 +- lib/infrared/encoder_decoder/infrared.h | 10 + lib/infrared/encoder_decoder/infrared_i.h | 5 +- .../infrared_protocol_defs_i.h | 320 ------- .../kaseikyo/infrared_decoder_kaseikyo.c | 10 +- .../kaseikyo/infrared_encoder_kaseikyo.c | 8 +- .../kaseikyo/infrared_kaseikyo_spec.c | 17 - .../kaseikyo/infrared_protocol_kaseikyo.c | 40 + .../kaseikyo/infrared_protocol_kaseikyo.h | 31 + .../kaseikyo/infrared_protocol_kaseikyo_i.h | 30 + .../nec/infrared_decoder_nec.c | 11 +- .../nec/infrared_encoder_nec.c | 11 +- .../encoder_decoder/nec/infrared_nec_spec.c | 47 - .../nec/infrared_protocol_nec.c | 74 ++ .../nec/infrared_protocol_nec.h | 30 + .../nec/infrared_protocol_nec_i.h | 29 + .../rc5/infrared_decoder_rc5.c | 13 +- .../rc5/infrared_encoder_rc5.c | 12 +- .../rc5/infrared_protocol_rc5.c | 49 ++ .../rc5/infrared_protocol_rc5.h | 38 + .../rc5/infrared_protocol_rc5_i.h | 20 + .../encoder_decoder/rc5/infrared_rc5_spec.c | 27 - .../rc6/infrared_decoder_rc6.c | 13 +- .../rc6/infrared_encoder_rc6.c | 12 +- .../rc6/infrared_protocol_rc6.c | 39 + .../rc6/infrared_protocol_rc6.h | 37 + .../rc6/infrared_protocol_rc6_i.h | 28 + .../encoder_decoder/rc6/infrared_rc6_spec.c | 17 - .../samsung/infrared_decoder_samsung.c | 10 +- .../samsung/infrared_encoder_samsung.c | 10 +- .../samsung/infrared_protocol_samsung.c | 40 + .../samsung/infrared_protocol_samsung.h | 31 + .../samsung/infrared_protocol_samsung_i.h | 35 + .../samsung/infrared_samsung_spec.c | 17 - .../sirc/infrared_decoder_sirc.c | 11 +- .../sirc/infrared_encoder_sirc.c | 9 +- .../sirc/infrared_protocol_sirc.c | 64 ++ .../sirc/infrared_protocol_sirc.h | 37 + .../sirc/infrared_protocol_sirc_i.h | 26 + .../encoder_decoder/sirc/infrared_sirc_spec.c | 37 - lib/infrared/worker/infrared_transmit.c | 3 +- lib/infrared/worker/infrared_worker.c | 52 +- 47 files changed, 1220 insertions(+), 1180 deletions(-) mode change 100755 => 100644 assets/resources/infrared/assets/tv.ir delete mode 100644 lib/infrared/encoder_decoder/common/infrared_common_protocol_defs.c delete mode 100644 lib/infrared/encoder_decoder/infrared_protocol_defs_i.h delete mode 100644 lib/infrared/encoder_decoder/kaseikyo/infrared_kaseikyo_spec.c create mode 100644 lib/infrared/encoder_decoder/kaseikyo/infrared_protocol_kaseikyo.c create mode 100644 lib/infrared/encoder_decoder/kaseikyo/infrared_protocol_kaseikyo.h create mode 100644 lib/infrared/encoder_decoder/kaseikyo/infrared_protocol_kaseikyo_i.h delete mode 100644 lib/infrared/encoder_decoder/nec/infrared_nec_spec.c create mode 100644 lib/infrared/encoder_decoder/nec/infrared_protocol_nec.c create mode 100644 lib/infrared/encoder_decoder/nec/infrared_protocol_nec.h create mode 100644 lib/infrared/encoder_decoder/nec/infrared_protocol_nec_i.h create mode 100644 lib/infrared/encoder_decoder/rc5/infrared_protocol_rc5.c create mode 100644 lib/infrared/encoder_decoder/rc5/infrared_protocol_rc5.h create mode 100644 lib/infrared/encoder_decoder/rc5/infrared_protocol_rc5_i.h delete mode 100644 lib/infrared/encoder_decoder/rc5/infrared_rc5_spec.c create mode 100644 lib/infrared/encoder_decoder/rc6/infrared_protocol_rc6.c create mode 100644 lib/infrared/encoder_decoder/rc6/infrared_protocol_rc6.h create mode 100644 lib/infrared/encoder_decoder/rc6/infrared_protocol_rc6_i.h delete mode 100644 lib/infrared/encoder_decoder/rc6/infrared_rc6_spec.c create mode 100644 lib/infrared/encoder_decoder/samsung/infrared_protocol_samsung.c create mode 100644 lib/infrared/encoder_decoder/samsung/infrared_protocol_samsung.h create mode 100644 lib/infrared/encoder_decoder/samsung/infrared_protocol_samsung_i.h delete mode 100644 lib/infrared/encoder_decoder/samsung/infrared_samsung_spec.c create mode 100644 lib/infrared/encoder_decoder/sirc/infrared_protocol_sirc.c create mode 100644 lib/infrared/encoder_decoder/sirc/infrared_protocol_sirc.h create mode 100644 lib/infrared/encoder_decoder/sirc/infrared_protocol_sirc_i.h delete mode 100644 lib/infrared/encoder_decoder/sirc/infrared_sirc_spec.c diff --git a/assets/resources/infrared/assets/tv.ir b/assets/resources/infrared/assets/tv.ir old mode 100755 new mode 100644 index cc5b0360e..b45171cb1 --- a/assets/resources/infrared/assets/tv.ir +++ b/assets/resources/infrared/assets/tv.ir @@ -47,85 +47,85 @@ name: Mute type: parsed protocol: NEC address: 08 00 00 00 -command: 0b 00 00 00 +command: 0B 00 00 00 # name: Power type: parsed protocol: NECext -address: 00 df 00 00 -command: 1c 00 00 00 +address: 00 DF 00 00 +command: 1C 00 00 00 # name: Vol_up type: parsed protocol: NECext -address: 00 df 00 00 -command: 4b 00 00 00 +address: 00 DF 00 00 +command: 4B 00 00 00 # name: Vol_dn type: parsed protocol: NECext -address: 00 df 00 00 -command: 4f 00 00 00 +address: 00 DF 00 00 +command: 4F 00 00 00 # name: Ch_next type: parsed protocol: NECext -address: 00 df 00 00 +address: 00 DF 00 00 command: 09 00 00 00 # name: Ch_prev type: parsed protocol: NECext -address: 00 df 00 00 +address: 00 DF 00 00 command: 05 00 00 00 # name: Mute type: parsed protocol: NECext -address: 00 df 00 00 +address: 00 DF 00 00 command: 08 00 00 00 # name: Power type: parsed protocol: Samsung32 -address: 0e 00 00 00 -command: 0c 00 00 00 +address: 0E 00 00 00 +command: 0C 00 00 00 # name: Mute type: parsed protocol: Samsung32 -address: 0e 00 00 00 -command: 0d 00 00 00 +address: 0E 00 00 00 +command: 0D 00 00 00 # name: Vol_up type: parsed protocol: Samsung32 -address: 0e 00 00 00 +address: 0E 00 00 00 command: 14 00 00 00 # name: Vol_dn type: parsed protocol: Samsung32 -address: 0e 00 00 00 +address: 0E 00 00 00 command: 15 00 00 00 # name: Ch_next type: parsed protocol: Samsung32 -address: 0e 00 00 00 +address: 0E 00 00 00 command: 12 00 00 00 # name: Ch_prev type: parsed protocol: Samsung32 -address: 0e 00 00 00 +address: 0E 00 00 00 command: 13 00 00 00 # name: Power type: parsed protocol: RC6 address: 00 00 00 00 -command: 0c 00 00 00 +command: 0C 00 00 00 # name: Power type: parsed @@ -190,19 +190,19 @@ command: 63 00 00 00 name: Power type: parsed protocol: NEC -address: aa 00 00 00 -command: 1c 00 00 00 +address: AA 00 00 00 +command: 1C 00 00 00 # name: Power type: parsed protocol: NEC address: 38 00 00 00 -command: 1c 00 00 00 +command: 1C 00 00 00 # name: Power type: parsed protocol: NECext -address: 83 7a 00 00 +address: 83 7A 00 00 command: 08 00 00 00 # name: Power @@ -215,7 +215,7 @@ name: Power type: parsed protocol: NECext address: 18 18 00 00 -command: c0 00 00 00 +command: C0 00 00 00 # name: Power type: parsed @@ -226,8 +226,8 @@ command: 10 00 00 00 name: Power type: parsed protocol: NEC -address: aa 00 00 00 -command: c5 00 00 00 +address: AA 00 00 00 +command: C5 00 00 00 # name: Power type: parsed @@ -250,8 +250,8 @@ command: 08 00 00 00 name: Power type: parsed protocol: NECext -address: 80 6f 00 00 -command: 0a 00 00 00 +address: 80 6F 00 00 +command: 0A 00 00 00 # name: Power type: parsed @@ -262,19 +262,19 @@ command: 00 00 00 00 name: Power type: parsed protocol: NECext -address: 80 7b 00 00 +address: 80 7B 00 00 command: 13 00 00 00 # name: Power type: parsed protocol: Samsung32 -address: 0e 00 00 00 +address: 0E 00 00 00 command: 14 00 00 00 # name: Power type: parsed protocol: NECext -address: 80 7e 00 00 +address: 80 7E 00 00 command: 18 00 00 00 # name: Power @@ -287,25 +287,25 @@ name: Power type: parsed protocol: NECext address: 80 75 00 00 -command: 0a 00 00 00 +command: 0A 00 00 00 # name: Power type: parsed protocol: NECext address: 80 57 00 00 -command: 0a 00 00 00 +command: 0A 00 00 00 # name: Power type: parsed protocol: Samsung32 -address: 0b 00 00 00 -command: 0a 00 00 00 +address: 0B 00 00 00 +command: 0A 00 00 00 # name: Power type: parsed protocol: NEC -address: aa 00 00 00 -command: 1b 00 00 00 +address: AA 00 00 00 +command: 1B 00 00 00 # name: Power type: parsed @@ -323,7 +323,7 @@ name: Power type: parsed protocol: Samsung32 address: 08 00 00 00 -command: 0f 00 00 00 +command: 0F 00 00 00 # name: Power type: parsed @@ -340,626 +340,626 @@ command: 01 00 00 00 name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 634 2571 505 519 479 519 479 518 480 518 480 518 480 518 480 517 481 547 481 517 481 20040 590 2555 501 1007 999 997 510 548 480 486 512 486 512 486 542 485 513 516 482 116758 593 2552 504 1004 992 1004 514 514 514 483 515 513 485 483 545 482 516 482 516 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 525 1955 449 1999 476 4545 446 4544 478 2032 443 2006 469 2011 444 4577 445 4545 447 4574 448 2002 473 4547 444 34913 447 2032 443 2007 478 4542 449 4541 471 2039 446 2004 471 2008 447 4574 448 4543 448 4572 450 2030 445 4545 446 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 2445 582 1221 603 548 602 1191 609 572 602 1191 609 542 607 544 631 1172 603 568 606 545 605 566 608 543 26263 2414 611 1192 607 544 606 1197 602 569 606 1197 602 539 611 540 635 1168 606 565 610 541 608 563 587 564 +type: parsed +protocol: SIRC +address: 01 00 00 00 +command: 15 00 00 00 +# +name: Power +type: parsed +protocol: Kaseikyo +address: 80 02 20 00 +command: D0 03 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 -data: 3461 1802 439 452 444 1283 469 448 438 453 443 447 439 452 444 419 497 448 438 425 471 419 467 451 445 445 441 450 446 1281 471 420 466 425 471 446 440 424 472 445 461 456 440 451 445 445 441 450 446 1281 471 447 439 451 445 419 467 423 473 445 441 422 494 450 436 428 468 1259 493 425 471 1256 496 1259 472 1281 471 1285 467 423 473 417 469 1286 466 452 444 1283 469 1285 467 1261 491 1263 468 423 493 1260 471 74142 3578 1713 467 423 473 1281 471 420 466 452 444 419 467 424 472 418 488 429 467 451 445 445 441 450 446 444 442 449 437 1290 472 446 440 423 473 445 441 449 467 396 490 428 468 449 447 444 442 448 438 1289 473 445 441 450 446 444 442 449 437 426 470 421 495 422 464 426 470 1257 495 450 446 1254 488 1267 464 1290 472 1282 470 421 465 453 443 1284 468 450 446 1281 471 1283 469 1259 493 1261 470 448 468 1258 473 -# -name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 389 1737 280 796 253 744 295 754 274 775 274 776 273 1827 271 1828 270 805 254 1820 278 796 253 797 252 745 294 1806 302 773 245 48942 305 1821 277 798 251 746 303 747 271 778 271 1829 279 796 253 796 253 1821 277 798 251 1823 275 1824 274 1825 273 802 247 1827 271 42824 381 1745 272 804 245 752 297 753 275 773 276 774 275 1825 273 1826 272 803 246 1828 270 805 254 795 244 753 296 1804 294 781 247 48939 379 1746 271 804 245 779 270 753 275 774 275 1825 273 802 247 802 247 1827 271 804 245 1829 279 1820 278 1821 277 798 251 1823 275 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 562 1721 561 594 557 597 564 617 513 615 536 618 543 1715 566 1716 566 1692 559 594 567 588 563 618 543 611 540 615 536 618 543 1715 556 623 538 617 534 621 530 624 516 638 513 642 509 1722 560 620 541 1717 565 1692 559 1724 568 1715 556 1701 560 1723 559 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 8436 4189 538 1563 566 1559 539 510 559 543 516 507 542 560 509 540 509 567 512 1586 512 1562 567 1559 539 536 533 1566 542 507 562 513 536 540 509 22102 647 1478 559 1568 540 508 541 535 534 515 534 568 511 538 511 539 540 1585 513 1560 559 1567 541 534 535 1564 534 515 534 568 511 538 511 22125 644 1482 565 1561 537 511 538 564 515 508 541 535 534 541 508 516 563 1588 510 1563 556 1570 538 510 559 1567 541 534 515 535 534 541 508 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 929 825 1711 934 797 930 791 909 822 932 789 938 793 934 797 930 791 1719 899 856 1711 907 824 90848 923 830 1706 912 819 908 823 931 790 910 822 933 788 912 819 935 796 1714 904 850 1707 939 792 +type: parsed +protocol: RC5 +address: 00 00 00 00 +command: 0C 00 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 448 2031 444 2005 480 4540 452 4539 473 2037 438 2011 474 2006 449 4571 451 4539 453 4568 444 2036 449 4541 451 34906 527 1953 451 1998 477 4543 449 4542 480 2030 445 2004 471 2009 446 4575 447 4543 449 4572 450 1999 476 4545 446 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 9021 4496 567 1664 567 1690 561 567 533 1698 563 1667 564 1693 568 1663 568 586 534 567 563 565 535 594 536 591 539 589 531 571 539 563 567 1690 541 560 560 594 536 592 538 564 536 1695 566 1664 567 1690 561 1670 561 1696 555 1675 566 562 558 596 514 562 568 559 561 594 536 565 535 593 537 591 539 1665 566 1692 559 1671 560 1697 564 1666 565 1666 565 1693 558 1672 569 23181 9013 4504 569 1689 542 1689 562 565 535 1697 564 1666 646 1610 560 1672 559 595 535 593 537 590 510 566 564 590 540 588 532 596 514 588 542 1689 542 560 560 594 536 592 538 590 510 1694 567 1664 567 1690 561 1669 562 1695 556 1675 566 561 559 596 514 588 542 585 535 593 537 591 509 593 537 591 539 1665 566 1692 559 1671 560 1697 564 1667 564 1667 564 1693 558 1672 569 +type: parsed +protocol: NEC42 +address: 7B 00 00 00 +command: 00 00 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 8041 3979 513 536 482 515 513 1559 509 515 514 1560 508 515 514 509 509 514 484 4000 533 1566 512 537 481 1566 512 537 481 1566 512 537 481 516 513 537 481 24150 8044 3977 505 518 510 539 479 1567 511 512 506 1568 510 539 479 543 485 538 480 3977 536 1564 514 534 484 1563 515 508 510 1563 515 508 510 540 489 534 484 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 383 2027 295 2112 271 2138 266 890 271 887 294 926 235 2114 300 887 274 915 236 2145 269 887 274 884 297 923 238 920 241 917 264 895 266 26573 384 2026 296 2111 273 2136 268 889 272 886 295 924 237 2113 301 886 275 914 237 2144 270 886 275 914 267 921 240 919 242 916 265 924 237 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 177 8474 175 5510 174 8476 173 8477 177 8504 171 5515 175 8476 178 8472 177 8473 176 5541 174 8476 173 45583 171 8481 178 5507 177 8473 176 8474 175 8506 173 5512 172 8478 176 8475 174 8476 178 5538 177 8474 175 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 8044 3976 506 517 511 1563 505 517 511 538 480 517 511 538 460 563 455 568 460 3993 530 545 483 1564 514 1559 509 1564 514 509 509 540 488 535 483 513 505 24150 8043 3978 514 509 509 1564 514 509 509 540 478 519 509 540 458 565 464 559 459 3994 529 546 482 1565 513 1560 508 1565 513 510 508 541 487 536 482 541 477 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 558 2942 450 10021 482 2989 484 10015 447 3024 449 10021 472 3100 485 2986 477 2994 500 2999 475 2996 477 2994 479 2992 482 3018 476 2995 479 6464 484 36270 477 3023 450 10020 473 2999 485 10014 448 3022 452 10019 474 3098 478 2994 480 2991 503 2996 477 2994 480 2992 482 2990 484 3015 479 2992 481 6462 485 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 587 2407 476 1062 965 547 482 547 451 577 452 546 452 22108 590 2404 479 1060 967 1028 510 519 509 548 480 487 511 120791 645 2411 472 1066 961 1065 483 515 514 514 504 493 515 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 172 7439 171 7441 169 7443 177 7434 176 7462 178 4887 176 4916 177 4914 169 7469 171 4920 174 4918 175 55174 176 7436 174 7437 173 7439 171 7440 175 7463 172 4894 174 4917 171 4921 172 7465 175 4916 178 4914 169 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 589 2556 500 524 474 554 454 544 454 543 455 543 455 543 455 543 445 583 446 552 446 20046 584 2561 505 1033 485 514 963 518 480 1032 516 512 476 522 506 491 507 522 476 116758 586 2560 506 1033 484 513 964 548 450 1031 507 522 476 521 507 490 508 521 477 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 586 2407 476 1063 964 578 450 548 450 547 481 517 481 577 451 546 452 546 472 556 452 545 453 575 453 514 484 544 484 543 455 14954 510 2483 481 1058 480 548 959 552 446 1067 481 516 512 546 482 515 992 1003 535 493 515 543 486 513 475 522 506 552 446 111671 589 2405 478 1061 477 551 967 514 484 1059 479 549 479 548 480 517 990 1036 512 516 482 546 483 515 503 525 483 544 454 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 8444 4180 537 1564 565 1560 538 1561 557 1568 540 1559 539 536 533 542 517 559 510 1563 535 1564 565 1561 537 512 567 1558 540 535 534 1566 542 1557 562 23122 564 1562 557 1569 539 1560 538 1587 542 1558 540 534 535 515 534 541 538 1587 511 1563 566 1560 538 536 533 1567 541 534 515 1585 533 1566 542 23166 561 1565 564 1561 537 1563 535 1590 539 1561 537 538 541 534 515 535 534 1564 534 1566 563 1563 535 540 539 1560 538 511 538 1588 541 1559 539 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 527 1923 481 1998 477 4543 449 4542 470 2040 445 2004 471 2009 446 4575 447 4543 449 4572 450 1999 476 2034 441 34899 524 1956 448 2001 474 4546 446 4545 477 2033 442 2007 478 2002 443 4578 444 4546 445 4575 447 2003 472 2037 448 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 533 1356 437 3474 427 3483 429 3455 436 1454 430 1459 405 28168 510 1379 434 3477 434 3476 425 3459 432 1457 427 1462 402 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 921 833 1714 932 789 938 793 934 797 903 818 909 822 905 816 938 793 1716 902 853 1714 905 816 90856 922 805 1742 931 790 937 794 933 788 939 792 935 796 930 791 937 794 1715 903 825 1742 904 817 +type: parsed +protocol: RC5 +address: 00 00 00 00 +command: 0C 00 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 179 7433 177 4915 178 7434 175 7436 174 7464 176 7435 175 4916 177 4915 173 4918 170 4922 171 4920 173 55174 175 7437 173 4919 174 7437 173 7439 171 7467 173 7438 172 4920 173 4919 174 4917 176 4915 178 4914 169 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 169 6731 176 6748 169 6730 177 6748 169 6755 172 4427 177 4447 178 6721 175 6749 178 4446 168 4456 169 54704 176 6723 174 6750 177 6723 173 6750 177 6747 170 4429 175 4449 176 6723 174 6751 176 4448 177 4447 178 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 3506 3494 876 830 840 2576 847 2568 844 862 819 2570 842 864 816 863 818 2570 842 836 844 2572 840 866 815 865 815 2573 839 867 813 866 814 2573 850 857 813 2575 847 2568 844 834 847 2569 843 835 845 2571 872 2571 842 32654 3512 3488 872 834 847 2570 842 2573 839 867 814 2574 849 858 822 857 813 2575 848 859 821 2566 846 832 848 860 821 2567 845 833 848 860 820 2568 844 834 847 2569 843 2572 840 838 843 2574 849 829 841 2575 868 2575 837 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 560 2939 453 10018 475 2996 477 10022 450 3021 452 10018 475 3097 478 6464 483 6460 477 6466 502 6469 479 2993 480 2990 484 36274 564 2936 456 10015 478 2993 481 10020 534 2936 456 10014 479 3093 482 6461 476 6466 482 6461 476 6495 473 2999 485 2986 477 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 10726 41047 10727 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 1617 4604 1559 1537 1560 1537 1560 4661 1533 33422 1613 4607 1566 1530 1556 1540 1536 4685 1539 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 174 4972 177 4910 173 4944 170 6988 174 6984 177 6951 175 6983 174 14269 177 4969 175 4912 176 4941 178 6979 172 6986 175 6953 178 6980 171 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 174 7067 176 10544 1055 719 1053 739 1054 738 953 822 1052 2566 169 3435 171 3431 175 3446 170 3432 174 3446 170 3432 174 3428 178 3442 174 3429 177 3425 171 39320 2323 4900 178 10543 1056 719 1053 739 1054 738 953 821 1053 2566 169 3435 171 3431 175 3445 171 3432 174 3446 170 3432 174 3428 178 3442 174 3428 178 3425 171 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 3506 3492 868 839 841 2575 848 858 822 2566 846 832 848 859 821 858 812 2576 847 860 820 2567 845 833 847 860 821 2568 844 862 818 2570 842 864 817 2571 841 2574 849 2567 845 861 820 2568 845 834 847 2570 873 2570 842 34395 3503 3496 874 833 847 2568 845 834 847 2570 842 864 816 835 846 862 819 2569 843 835 846 2571 841 865 816 864 816 2571 841 837 844 2573 850 857 813 2575 848 2567 845 2570 842 864 816 2572 840 838 842 2574 869 2574 838 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 170 8479 170 5516 178 8472 177 8474 175 8506 173 5513 171 8479 175 8476 178 8472 177 5540 175 8475 174 45584 177 8473 176 5509 175 8476 173 8477 176 8504 170 5516 178 8472 177 8474 175 8476 173 5543 172 8479 170 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 178 4969 170 6958 173 4944 175 6983 173 6956 174 6984 177 6980 171 16308 180 4966 173 6955 176 4941 172 6985 176 6982 169 6960 176 6982 174 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 585 2409 474 550 478 550 448 1033 994 1063 485 512 506 79916 585 2410 473 551 477 550 448 1034 993 1033 515 543 475 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 1192 1012 6649 26844 1192 1013 6648 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 3134 6105 6263 82963 3134 6105 6263 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 588 1511 567 1533 565 589 531 597 513 589 541 587 533 1565 533 569 541 1533 565 562 568 1531 537 1537 561 593 537 591 539 1507 561 1539 569 22152 586 1513 565 1535 563 590 540 562 538 564 566 588 542 1557 531 597 513 1534 564 590 540 1533 535 1539 559 568 562 592 538 1509 569 1531 567 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 923 831 1715 903 818 936 795 932 789 938 793 934 797 1713 1740 932 789 911 821 934 798 930 791 90853 928 799 1737 935 796 931 790 937 795 932 789 938 793 1717 1736 936 796 932 789 911 820 934 798 +type: parsed +protocol: RC5 +address: 00 00 00 00 +command: 20 00 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 689 1461 566 1534 564 589 531 597 513 1534 564 564 566 1533 535 620 510 1537 561 592 538 1535 543 1531 567 587 533 595 535 1511 567 1533 565 22161 588 1512 566 1534 564 564 556 598 512 1535 563 565 565 1534 534 594 536 1538 560 593 537 1536 542 1532 566 587 543 585 535 1511 567 1534 564 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 588 2558 498 526 482 515 483 546 452 545 453 545 453 545 453 545 453 544 474 554 444 20047 583 2562 504 519 479 519 479 1003 515 483 1024 548 450 1001 995 1001 506 116771 593 2552 504 520 478 551 447 1004 513 514 993 549 449 1002 994 1002 516 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 587 2559 507 517 481 517 481 547 451 516 482 546 452 546 452 546 452 545 473 525 483 20038 592 2553 503 521 477 552 446 521 477 1004 514 515 992 1034 483 514 484 513 485 116769 593 2552 504 520 478 550 448 520 478 1003 515 514 993 1032 486 513 475 522 476 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 4558 4576 558 596 565 97881 4554 4579 565 589 562 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 1039 7202 958 4713 981 4713 961 7255 956 4739 955 16077 1038 7204 956 4714 980 4715 959 7256 954 4741 954 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 506 2638 510 516 482 516 482 546 452 546 452 545 453 545 453 545 453 575 443 554 444 20048 592 2554 502 1036 481 517 481 517 511 516 482 516 961 1035 513 515 483 514 484 116757 594 2552 504 1034 484 514 484 514 504 524 484 513 964 1032 506 522 476 492 506 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 170 7441 169 4924 174 7437 193 7444 171 7441 174 4918 170 7441 174 4917 171 7440 195 7443 172 7439 171 55187 174 7437 173 4919 175 7437 173 7438 172 7466 175 4891 172 7439 171 4921 172 7439 171 7441 174 7464 171 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 179 4967 172 4915 178 6980 171 4945 169 4948 176 4912 176 4941 178 16307 176 4969 175 4912 176 6982 174 4942 171 4945 169 4919 174 4943 176 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 1042 793 898 883 869 858 924 884 878 877 875 879 873 855 928 1717 901 854 1794 878 894 887 875 1716 902 89114 985 798 903 878 874 880 902 852 900 855 897 857 905 876 896 1722 906 849 1789 883 899 855 897 1721 897 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 170 8480 169 8481 178 8472 177 8474 175 8476 173 5513 176 8474 175 8476 173 8507 178 5509 175 8505 174 45558 175 8476 173 8476 173 8477 172 8478 171 8480 169 5517 177 8473 176 8474 175 8506 174 5512 172 8509 171 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 628 2577 499 528 480 545 453 544 454 544 454 544 454 544 454 543 455 543 475 553 445 20047 593 2553 503 521 477 551 447 1004 514 515 992 519 479 1003 515 513 485 543 455 116768 585 2561 505 519 479 519 479 1002 516 513 994 548 450 1001 506 522 476 521 477 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 8987 4505 568 586 534 594 536 591 509 567 563 591 539 563 567 587 513 1692 559 1672 559 1698 563 590 510 592 538 590 540 1664 567 1690 561 593 507 1699 562 1668 563 1694 567 1663 568 586 534 568 562 592 508 595 535 1695 536 592 538 1693 558 595 515 1690 561 593 517 585 535 567 563 39551 8994 4497 566 589 541 560 560 594 516 586 534 594 536 592 538 590 510 1695 566 1664 567 1690 561 593 507 595 535 566 564 1667 564 1693 558 596 534 1670 561 1670 561 1696 565 1666 565 589 541 587 533 595 515 587 533 1697 534 568 562 1695 556 572 538 1693 568 559 541 588 542 585 535 +type: parsed +protocol: NECext +address: 80 63 00 00 +command: 0F 15 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 80 64 00 00 +command: 49 08 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 -data: 8987 4504 569 559 561 593 537 565 535 567 563 591 539 588 532 597 513 1691 560 568 562 592 508 1697 564 589 511 565 565 1692 559 1672 559 569 561 1669 562 566 564 564 566 1665 566 588 542 586 534 1670 561 567 563 565 535 593 537 591 539 1692 539 589 541 586 534 594 536 592 508 40679 8987 4504 569 585 535 593 537 591 509 566 564 591 539 588 532 596 514 1691 560 594 536 592 508 1697 564 589 511 591 539 1692 559 1671 560 594 536 1669 562 592 538 590 540 1664 567 587 543 585 535 1670 561 593 537 565 535 593 537 591 539 1691 540 588 542 586 534 594 536 592 508 -# -name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 298 1828 270 804 245 1829 279 1820 278 797 252 771 278 1822 276 1824 274 800 249 1825 273 802 247 776 252 771 278 1822 276 799 250 48931 388 1737 280 796 253 1821 277 1822 276 798 251 1823 275 800 249 774 275 1825 273 776 273 1801 297 1828 270 1829 279 796 253 1821 277 42813 301 1825 273 801 248 1826 272 1827 271 804 245 805 244 1830 278 1821 277 798 251 1823 275 799 250 774 244 779 280 1820 278 796 253 48926 382 1744 354 696 271 1828 270 1829 279 796 253 1821 277 797 252 746 303 1823 275 774 275 1799 299 1826 272 1827 271 804 245 1829 279 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 177 5508 176 5539 176 8475 174 5542 173 8478 171 5545 170 8481 168 8482 177 8473 176 5541 174 8476 173 45573 169 5517 177 5538 177 8473 176 5541 174 8476 173 5544 171 8479 170 8481 178 8472 177 5540 175 8475 174 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 175 8474 175 8475 174 8477 172 8478 171 8480 169 8481 178 5538 177 5510 174 5542 173 5543 172 5544 171 45575 177 8472 177 8474 175 8476 173 8477 172 8478 171 8481 178 5507 177 5539 176 5540 175 5542 173 5543 172 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 8050 3971 511 1562 516 1558 510 539 490 1557 511 1563 515 533 485 538 490 533 485 3983 530 1569 509 1564 514 1559 509 1565 513 1560 508 515 513 536 482 541 488 24152 8042 3979 514 1560 508 1565 513 510 508 1565 513 1560 508 515 513 536 482 541 488 3980 533 1567 511 1562 516 1557 511 1563 515 1558 510 539 489 534 484 539 490 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 175 8475 174 5512 177 8473 176 8475 174 8506 179 5508 176 8474 175 8475 174 8477 172 5544 171 8480 169 45587 176 8475 174 5511 173 8477 177 8473 176 8504 170 5516 178 8472 177 8473 176 8475 174 5542 173 8478 171 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 176 7436 174 7438 172 7439 171 7441 174 7463 172 7440 170 4921 172 4919 174 4917 176 4916 177 4914 174 55176 175 7437 173 7439 191 7446 174 7438 177 7434 176 7435 175 4917 176 4915 179 4914 174 4917 171 4946 178 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 176 7435 175 4917 177 7435 175 7436 189 7449 176 7435 175 7437 173 4918 175 7436 174 4918 175 4916 178 55171 175 7436 174 4918 170 7441 174 7438 177 7460 170 7441 174 7438 177 4914 174 7437 178 4914 169 4922 171 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 8049 3973 509 1564 514 509 509 1564 514 535 483 1564 514 535 483 540 489 535 483 3980 533 1566 512 537 481 1566 512 511 507 1566 512 537 481 542 486 511 507 24149 8045 3976 516 1558 510 512 516 1557 511 512 516 1558 510 512 516 507 511 512 506 3984 539 1560 508 515 513 1560 508 541 488 1560 508 541 488 536 482 514 504 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 366 202 867 527 170 130516 343 227 863 529 168 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 176 5992 176 1372 176 1320 177 1345 172 1349 179 1370 178 1317 175 4444 176 1346 171 1351 177 1345 172 1349 179 1344 174 5963 175 65574 172 5995 178 1344 174 1348 175 1347 175 1347 170 1378 170 1325 172 4447 178 1344 173 1349 169 1353 175 1347 170 1351 177 5961 177 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 497 1478 488 511 467 1482 494 531 447 1477 499 501 466 533 445 530 468 507 471 529 438 12857 488 1485 491 509 469 1481 495 529 448 1476 490 510 468 532 445 529 469 480 498 502 465 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 982 6313 961 2662 903 2718 929 2719 907 6363 900 2722 904 6365 909 6361 903 6368 906 2742 905 46364 989 6307 906 2716 911 2712 925 2723 903 6367 907 2715 901 6369 905 6365 909 6361 903 2745 902 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 599 257 975 317 177 130649 308 228 974 319 175 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 176 4969 170 6958 173 6985 177 6981 171 6958 178 6980 177 6981 170 16308 180 4966 173 6955 176 6982 169 6988 174 6956 175 6983 173 6984 172 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 178 5990 173 1349 174 1348 175 1348 174 4444 176 1346 171 1351 177 4416 178 1344 173 1348 169 1353 175 1347 170 1351 177 9048 177 65573 173 5995 173 1348 175 1348 174 1347 176 4444 171 1351 177 1345 173 4421 173 1348 169 1352 176 1347 170 1351 177 1345 172 9053 177 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 174 4972 177 4910 173 6985 177 4940 174 6984 178 6951 175 6983 174 14269 177 4968 176 4912 176 6981 175 4941 173 6985 177 6953 178 6979 172 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 1318 225 177 130305 1609 231 171 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 585 2410 473 1065 962 581 447 519 479 580 448 549 449 579 449 518 480 548 480 517 481 517 481 577 451 516 482 576 452 545 453 14955 510 2483 481 1058 480 549 969 543 445 1037 511 547 481 546 482 516 482 545 484 545 483 514 484 544 963 1063 485 543 445 111612 626 2427 557 954 513 512 995 547 451 1031 507 521 508 551 477 520 478 550 478 549 479 488 510 548 969 1057 481 517 481 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 203 272 1215 302 171 130229 1423 275 178 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 176 7436 174 7438 192 7446 174 7437 178 7434 176 7435 175 4917 176 4915 178 4913 175 4917 197 7440 175 55130 286 7377 177 7435 175 7437 173 7438 172 7466 174 7411 178 4913 170 4921 172 4919 174 4918 175 7436 174 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 175 7437 173 4918 170 7441 174 7437 178 7460 170 7441 179 7433 177 4915 178 4913 170 4922 171 4920 173 55124 291 7372 172 4921 172 7439 171 7441 174 7463 172 7440 170 7442 178 4913 170 4922 171 4920 173 4918 175 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 172 8477 172 8478 171 8480 169 5516 179 8502 178 5509 175 8475 174 8476 173 8479 170 5545 170 8480 169 45588 176 8473 176 8474 175 8476 173 5513 177 8504 171 5515 174 8476 178 8472 177 8473 176 5541 174 8476 173 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 177 7436 174 4918 175 7436 174 4918 175 7462 178 4887 176 4916 177 4914 174 4917 171 4921 172 4919 175 55184 175 7435 175 4918 175 7436 174 4918 175 7462 178 4914 174 4917 171 4920 173 4919 174 4917 176 4915 178 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 508 2484 480 1060 967 544 485 544 454 574 454 543 455 573 445 553 445 522 506 552 446 552 446 551 477 551 447 581 447 520 478 550 478 15908 626 2427 476 1062 476 522 995 547 451 1061 477 520 508 550 478 519 479 519 999 1058 959 1037 990 582 446 1035 483 111666 590 2404 479 1059 479 549 968 543 455 1027 511 548 480 517 511 486 512 546 961 1065 962 1034 993 579 449 1032 486 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 175 8475 174 8475 174 8477 172 8478 171 8480 169 5517 178 8473 175 8475 179 8501 173 5513 176 8505 169 45562 179 8472 177 8473 176 8474 175 8476 173 8478 171 5515 174 8476 178 8473 176 8505 174 5512 172 8508 171 120769 178 93377 175 7437 173 4919 174 7437 173 7439 171 7467 173 7439 171 7441 174 4918 170 4921 172 7439 171 7467 173 55167 171 7440 170 4922 171 7440 195 7443 172 7439 171 7441 174 7438 177 4915 173 4918 195 7442 173 7439 170 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 295 1805 273 776 242 1808 270 754 244 1806 272 777 241 758 270 754 264 760 268 756 272 14149 297 1802 266 784 244 1805 263 762 246 1803 265 785 244 780 248 751 267 758 271 753 265 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 535 1723 569 585 566 615 536 619 542 586 565 616 535 1722 539 615 536 1721 561 620 541 587 564 617 534 621 540 588 563 618 543 1714 537 617 534 621 540 615 536 618 543 612 539 615 536 1722 560 594 567 1717 534 1723 569 1714 557 1700 643 1639 643 1641 559 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 502 2521 504 521 997 545 453 575 453 545 453 575 454 22097 591 2433 511 513 994 1062 476 552 476 522 476 552 476 120839 628 2455 509 515 992 1064 484 513 505 493 515 543 475 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 591 2404 479 1060 967 1029 509 519 509 549 479 518 480 79926 585 2408 556 956 989 1033 515 544 484 543 475 522 476 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 586 2560 506 518 480 548 450 548 450 517 481 517 481 517 481 547 451 546 482 516 482 20040 590 2556 500 1038 480 518 969 543 455 543 475 1006 511 517 481 517 511 486 481 116778 584 2561 505 1033 485 513 964 548 450 548 480 1001 506 522 476 522 506 521 446 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 917 206 175 186 170 21561 170 2280 175 2274 502 1929 174 2276 169 5178 170 2261 173 3724 498 1932 171 2279 176 2273 172 3709 172 2277 178 3720 171 17223 177 7619 174 2275 170 2279 176 2256 168 2280 175 5172 176 2256 168 3729 173 2276 179 2253 171 2278 177 3703 178 2271 174 3724 177 17251 170 7627 177 2272 173 2276 169 2263 171 2277 178 5169 169 2262 172 3726 175 2256 168 2280 175 2274 171 3710 171 2278 177 3720 171 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 565 233 653 313 170 130328 752 235 233 107 229 398 177 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 586 2439 505 549 968 1027 511 517 511 517 481 547 481 21583 584 2439 505 520 997 1059 479 549 479 518 480 548 480 120894 593 2432 501 522 995 1061 477 521 507 520 478 550 478 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 558 8032 474 8115 503 8116 482 8108 480 8141 477 5239 476 8114 504 8115 483 8107 481 5236 509 8111 477 45290 554 8036 481 8108 510 8110 478 8112 476 8145 473 5243 482 8107 511 8109 479 8111 477 5240 505 8115 473 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 173 7438 172 4920 173 7438 172 4920 173 7465 175 4890 173 7439 171 4920 173 4919 174 4917 176 4915 178 55179 170 7441 169 4924 174 7437 178 4913 175 7463 172 4893 170 7441 174 4918 170 4922 171 4920 173 4918 175 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 225 745 222 774 193 778 200 797 175 769 193 777 201 771 196 774 224 747 220 776 202 769 198 248 220 252 196 250 218 253 225 746 221 250 198 248 220 252 226 246 222 223 225 248 220 252 216 229 219 253 225 247 221 277 176 243 220 279 189 230 228 244 224 248 220 252 196 250 218 253 215 257 201 770 197 799 189 257 201 271 197 37716 222 749 218 778 200 771 196 801 172 772 200 771 196 774 193 777 221 750 217 780 197 773 194 251 217 255 193 279 199 273 195 749 218 254 194 252 226 245 223 275 178 242 221 277 201 245 193 253 225 247 221 250 218 254 194 252 226 272 196 223 225 248 220 251 217 255 193 253 225 247 221 251 197 773 194 803 174 297 176 244 219 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 3503 2655 197 642 876 2568 844 834 846 833 848 860 821 831 839 2576 847 2569 843 2572 841 2574 849 858 823 857 813 866 815 865 815 2572 841 2575 848 2568 844 2570 842 836 844 863 818 834 847 861 820 2568 845 2571 872 2571 842 32651 3505 3495 875 2567 845 861 820 832 849 859 811 840 840 2576 847 2568 844 2571 842 2574 849 830 840 867 814 838 842 865 815 2572 840 2575 848 2568 845 2571 841 865 815 864 817 834 846 861 819 2569 843 2572 871 2572 840 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 347 677 219 252 196 276 202 742 225 798 174 770 192 778 200 771 196 775 223 748 219 777 200 770 197 249 219 253 195 251 227 271 197 747 220 252 216 229 219 253 225 273 195 277 176 244 219 253 215 230 228 244 224 248 220 252 196 250 218 280 198 247 201 245 223 249 219 253 195 251 227 245 223 248 200 797 175 795 198 248 200 246 222 37666 344 678 228 245 223 222 226 771 196 800 198 747 220 750 217 753 224 773 194 776 202 769 198 799 173 246 227 245 223 249 199 247 221 749 218 280 198 247 201 245 223 249 219 253 195 251 227 244 224 248 200 272 196 250 218 254 194 252 226 245 223 249 199 274 194 251 227 245 193 253 225 273 195 251 217 753 225 746 221 251 197 275 193 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 174 7437 173 7440 174 7437 178 7433 177 7461 169 7442 178 4914 174 4917 171 4921 172 4919 174 7463 177 55163 177 7435 174 7437 173 7438 172 7440 175 7463 172 7413 176 4915 178 4913 175 4917 171 4920 174 7438 172 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 8042 3979 513 510 508 541 487 1559 509 515 513 1560 508 515 513 510 508 541 477 3981 532 1568 510 1563 515 1558 510 1564 514 1559 509 514 514 535 483 540 488 24151 8042 3979 513 536 482 541 487 1560 508 541 488 1560 508 541 487 536 482 541 477 3980 533 1566 512 1561 507 1566 512 1562 516 1557 511 538 491 533 485 538 490 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 8989 4501 562 1696 565 1665 566 562 568 586 514 588 542 586 534 594 536 1667 564 591 539 1692 539 563 567 1690 561 1669 562 1669 562 1696 565 562 538 564 566 588 542 586 534 1670 561 568 562 592 538 590 510 592 538 590 540 561 539 563 567 561 569 585 535 593 507 595 535 593 537 39547 8987 4504 569 1689 562 1668 563 591 539 589 511 591 539 589 541 561 559 1671 560 568 562 1695 536 592 538 1693 558 1673 568 1663 568 1689 562 592 508 594 536 592 538 590 540 1664 567 561 569 559 561 567 543 585 535 593 537 591 509 593 537 591 539 589 541 587 513 589 541 587 533 +type: parsed +protocol: NECext +address: 83 7A 00 00 +command: 08 00 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 8988 4504 640 487 562 592 538 590 510 592 538 590 540 588 532 596 514 614 516 1689 562 1668 563 1695 536 1695 566 1664 567 1690 612 1618 643 1430 801 1613 648 481 558 570 540 589 541 587 533 595 535 592 508 594 536 592 538 1667 564 1693 558 1672 569 1688 563 1668 644 1586 563 1694 567 40630 8994 2265 557 96833 8987 2273 538 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 173 7439 171 4922 172 7439 171 4921 172 7466 174 4917 176 4915 173 4918 170 7441 174 7438 192 7445 175 55181 174 7437 173 4918 175 7437 173 4919 175 7463 177 4888 175 4917 176 4915 178 7460 170 7440 175 7437 178 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 1636 4610 1563 1533 1584 7760 1561 28769 1641 4606 1557 1539 1588 7757 1564 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 590 2404 479 1059 968 575 454 544 454 574 454 543 455 543 475 522 476 552 476 552 446 551 447 581 448 520 478 581 447 519 479 549 479 15967 587 2407 476 1062 476 522 995 547 451 1030 508 520 509 550 478 519 479 519 998 1028 999 1057 481 547 960 1066 482 111641 587 2407 476 1063 485 513 994 547 451 1031 507 551 477 551 477 520 478 550 968 1059 968 1027 511 548 959 1036 512 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 588 2406 477 1061 966 577 451 516 482 545 483 545 453 575 443 524 484 514 504 554 454 543 455 543 475 553 445 583 445 521 477 582 446 15969 585 2409 474 1065 483 514 993 549 449 1033 515 543 475 553 475 522 476 552 965 1030 997 576 452 1029 998 1028 479 111668 587 2407 475 1063 485 543 964 517 481 1031 507 552 476 551 477 520 478 550 968 1028 999 574 454 1027 990 1036 481 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 174 7439 196 7441 174 7437 173 7439 171 7441 174 7438 177 7460 170 7442 178 7433 177 4915 173 4918 170 55186 174 7438 172 7440 170 7441 174 7438 177 7461 169 7416 173 7464 176 7435 175 7437 173 4918 175 4917 176 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 173 7438 172 7441 174 7438 177 7434 176 7462 168 7443 177 7435 175 4917 176 4915 173 7438 177 4941 173 55166 174 7438 197 7441 174 7437 173 7439 171 7441 174 7438 177 7460 170 4922 171 4893 195 7443 172 4920 173 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 175 7436 179 4913 175 4917 171 4920 173 4945 169 4896 177 7435 175 7436 174 7464 176 4916 177 4914 169 55180 170 7441 169 4924 169 4922 171 4920 173 4919 174 4917 176 7435 175 7463 177 7434 176 4916 177 4914 174 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 927 827 1709 936 796 932 789 938 793 1717 1736 936 795 932 789 1721 927 827 1709 909 822 90851 898 829 1738 934 798 930 791 936 796 1715 1738 934 797 930 791 1719 899 828 1739 934 797 +type: parsed +protocol: RC5 +address: 02 00 00 00 +command: 0C 00 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 176 5991 177 1372 176 1320 177 1344 173 1349 174 1374 169 1327 170 4449 176 1346 171 1351 177 1345 172 1349 168 1353 175 5963 175 65573 173 5995 178 1344 174 1348 175 1348 174 1347 170 1378 170 1325 172 4447 178 1344 174 1349 169 1353 175 1347 170 1352 176 5961 177 # name: Power type: parsed protocol: NEC address: 71 00 00 00 -command: 4a 00 00 00 +command: 4A 00 00 00 # name: Power type: parsed @@ -982,26 +982,26 @@ command: 01 00 00 00 name: Power type: parsed protocol: NECext -address: 50 ad 00 00 +address: 50 AD 00 00 command: 00 00 00 00 # name: Power type: parsed protocol: NECext -address: 50 ad 00 00 +address: 50 AD 00 00 command: 02 00 00 00 # name: Power type: parsed protocol: NEC address: 50 00 00 00 -command: 3f 00 00 00 +command: 3F 00 00 00 # name: Power type: parsed protocol: Samsung32 address: 06 00 00 00 -command: 0f 00 00 00 +command: 0F 00 00 00 # name: Power type: parsed @@ -1013,13 +1013,13 @@ name: Power type: parsed protocol: Samsung32 address: 08 00 00 00 -command: 0b 00 00 00 +command: 0B 00 00 00 # name: Power type: parsed protocol: NECext address: 83 55 00 00 -command: c2 00 00 00 +command: C2 00 00 00 # name: Power type: parsed @@ -1030,20 +1030,20 @@ command: 51 00 00 00 name: Power type: parsed protocol: NECext -address: 00 bd 00 00 +address: 00 BD 00 00 command: 01 00 00 00 # name: Power type: parsed protocol: Samsung32 address: 00 00 00 00 -command: 0f 00 00 00 +command: 0F 00 00 00 # name: Power type: parsed protocol: Samsung32 address: 16 00 00 00 -command: 0f 00 00 00 +command: 0F 00 00 00 # name: Power type: parsed @@ -1064,561 +1064,561 @@ address: 86 02 00 00 command: 49 00 00 00 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 2383 609 1214 600 612 580 1213 608 614 583 1210 605 607 586 616 611 1192 599 613 608 614 579 613 615 607 26670 2387 601 1212 600 612 589 1214 603 609 586 1217 595 607 594 618 606 1187 602 610 609 613 588 614 610 612 +type: parsed +protocol: SIRC +address: 01 00 00 00 +command: 15 00 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 178 7761 176 11308 546 957 540 1958 538 970 537 1955 541 962 545 1953 543 964 543 962 545 957 540 970 548 960 547 1945 541 1950 546 965 542 1953 543 962 545 1945 540 970 537 1958 538 7881 172 7744 172 11318 536 971 536 1956 540 963 534 1964 542 966 541 1951 535 968 539 971 536 971 536 969 538 964 533 1965 541 1954 542 963 534 1956 540 971 536 1959 537 968 539 1951 535 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 3444 1767 413 486 420 1343 419 478 418 485 411 490 416 479 417 489 417 482 414 485 421 482 414 483 413 490 416 485 411 1343 419 487 419 480 416 483 413 490 416 482 414 488 418 483 413 483 413 492 414 1345 417 482 414 489 417 480 416 487 419 482 414 481 415 491 415 484 412 1347 415 488 418 1338 414 1348 414 1347 415 1340 412 494 412 487 419 1340 412 491 415 1341 421 1341 421 1340 412 1343 419 487 419 1339 413 74311 3445 1753 437 461 445 1316 446 456 440 455 441 465 441 458 438 461 445 458 438 460 436 466 440 461 445 451 445 460 446 1313 439 460 446 457 439 459 437 465 441 460 446 450 436 469 437 462 444 456 440 1322 440 457 439 464 442 459 437 459 437 468 438 461 445 455 441 462 444 1312 440 463 443 1317 445 1310 442 1323 439 1320 442 457 439 464 442 1315 437 466 440 1320 442 1313 439 1326 446 1313 439 460 446 1317 445 +type: parsed +protocol: Kaseikyo +address: 80 02 20 00 +command: D0 03 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 278 1845 274 808 271 806 273 812 278 805 275 805 274 1840 279 1844 275 809 281 1836 272 806 274 812 278 805 274 1842 277 802 277 44956 279 1842 277 804 275 802 277 808 271 811 279 1838 281 798 271 814 276 1844 275 806 273 1841 278 1845 274 1846 273 808 271 1843 276 44959 275 1845 274 807 272 805 275 811 279 804 275 805 274 1839 280 1844 275 808 271 1845 274 805 274 811 279 804 275 1841 278 801 278 44955 280 1841 278 802 277 801 278 807 272 810 280 1837 271 807 272 813 277 1843 276 805 274 1839 280 1843 276 1845 274 807 272 1842 277 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 881 909 1750 928 875 927 876 921 872 929 874 927 876 918 875 930 873 1815 874 924 1745 937 876 88694 880 922 1747 933 880 914 879 926 877 922 871 927 876 927 876 920 873 1818 871 929 1740 934 879 +type: parsed +protocol: RC5 +address: 00 00 00 00 +command: 0C 00 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 509 1717 504 629 512 631 510 627 504 633 508 633 508 1713 508 1719 512 1713 508 625 505 637 504 633 508 629 512 629 512 623 508 1719 512 626 505 628 513 631 510 627 514 623 507 632 509 1713 508 632 509 1716 505 1715 506 1724 507 1716 505 1719 512 1715 506 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 506 493 505 4059 505 5051 501 506 502 4065 499 511 497 4063 501 5058 504 504 504 4060 504 5052 500 507 501 4066 498 5056 506 5042 500 515 503 119614 504 505 503 4065 499 5051 501 511 497 4069 505 499 499 4072 502 5050 502 506 502 4066 498 5053 499 512 506 4060 504 5044 498 5061 501 508 500 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 8887 4470 532 1738 513 1708 533 1708 533 577 533 576 534 569 531 582 538 1705 536 571 539 1707 534 571 539 571 539 570 540 1699 532 581 539 568 532 575 535 576 534 571 539 571 539 569 541 1698 533 1717 534 1708 533 1710 531 1716 535 1706 535 1711 540 1705 536 567 533 580 540 567 533 39042 8915 2231 530 94849 8917 2256 535 +type: parsed +protocol: NECext +address: 87 22 00 00 +command: E0 1F 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 8313 4161 515 1574 514 1571 507 569 510 562 507 563 506 562 507 568 511 562 507 1580 508 1577 511 1582 506 567 513 1575 513 554 505 571 509 564 505 22604 513 1573 505 1589 509 563 506 564 505 562 507 569 511 562 507 563 506 1579 509 1584 514 1576 512 558 511 1574 514 562 507 565 515 556 513 22593 514 1581 507 1583 505 564 505 563 506 570 510 563 506 564 505 562 507 1586 512 1578 510 1577 511 557 512 1581 507 566 514 556 513 555 514 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 8735 4383 558 573 557 550 560 568 562 544 566 1722 560 540 560 1732 560 544 566 1719 563 1701 560 1723 559 1704 557 574 556 1699 562 574 556 1703 559 1727 565 1698 563 1721 561 546 564 1723 559 541 559 577 564 541 559 571 560 548 562 565 566 1697 565 567 564 1693 558 1733 559 1701 560 39926 8754 2247 565 92341 8758 2243 589 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 3298 3336 821 2506 825 881 820 2505 826 2529 823 856 825 2524 817 866 825 2528 813 2513 818 888 813 862 819 887 814 865 826 2522 820 864 827 2526 815 861 820 887 814 2510 821 885 816 863 818 2531 821 2512 819 2559 793 32401 3298 3349 818 2507 824 882 819 2509 822 2527 814 868 823 2530 821 855 826 2531 821 2504 827 879 822 857 824 875 816 867 824 2529 823 854 827 2530 821 853 817 889 822 2506 825 873 818 866 825 2527 814 2513 818 2564 788 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 8840 4439 532 566 534 566 534 1668 532 1674 536 1669 531 562 538 566 534 563 537 1667 533 567 533 563 537 563 537 562 538 1662 538 1671 529 568 532 565 535 566 534 1668 532 1674 536 1669 531 562 538 1672 528 1675 536 1668 532 1675 535 559 531 1676 534 565 535 558 532 1678 532 565 535 562 538 563 537 1665 535 565 535 1670 530 1669 531 572 538 1666 534 1669 531 1676 534 22777 8858 4447 535 92577 8858 4413 538 +type: parsed +protocol: NEC42 +address: 1C 01 00 00 +command: 12 00 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 289 2112 261 2109 295 2101 262 918 294 912 259 915 297 2098 265 916 296 909 262 2107 297 905 266 913 289 918 263 910 292 909 262 918 294 24789 263 2106 298 2098 265 2110 294 913 258 916 296 905 266 2108 296 911 260 914 288 2107 266 914 298 908 263 911 291 910 261 919 293 913 258 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 8898 4453 569 578 573 577 574 571 570 1745 567 1747 565 1743 569 583 568 579 572 1740 572 1744 568 1742 570 579 572 576 575 568 573 1746 566 1746 566 580 571 1745 567 577 574 576 575 1739 573 569 572 581 570 577 574 1738 574 576 575 1735 567 1748 574 574 567 1742 570 1748 574 1737 575 41005 8876 2261 571 93850 8898 2264 568 +type: parsed +protocol: NEC +address: 38 00 00 00 +command: 12 00 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 3215 1637 410 430 405 439 406 1242 408 435 410 1242 408 428 407 440 405 435 410 1240 410 1243 407 431 404 440 405 437 408 1238 402 1254 406 434 401 439 406 438 407 431 404 440 405 437 408 428 407 439 406 434 401 439 406 438 407 1241 409 434 401 441 404 432 403 444 401 1249 401 439 406 438 407 1241 409 434 401 441 404 433 402 444 401 1249 401 439 406 1248 402 436 409 434 401 441 404 433 402 444 401 439 406 45471 3239 1614 403 435 400 444 401 1250 400 437 408 1248 402 438 407 433 402 442 403 1245 405 1248 423 420 405 431 404 443 402 1248 402 1248 422 421 404 435 400 443 402 440 405 431 404 443 402 438 407 433 402 442 403 435 400 443 402 1250 400 436 399 447 408 432 403 438 407 1246 404 434 401 443 402 1250 400 436 399 447 408 432 403 437 408 1246 404 434 401 1253 407 434 401 436 399 447 408 432 403 437 408 436 399 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 7928 3948 504 515 503 518 500 1583 505 516 502 1584 504 510 508 516 502 516 502 3952 510 1579 509 507 501 1587 501 519 510 1571 507 518 500 517 501 517 501 23073 7931 3943 509 514 504 515 503 1578 500 524 505 1580 508 510 508 514 504 511 507 3951 511 1576 502 513 505 1586 502 515 503 1582 506 515 503 513 505 516 502 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 8837 4464 538 610 531 619 532 613 538 1748 534 1750 532 611 540 613 538 609 532 615 536 614 537 608 533 1753 539 1745 537 606 535 618 533 614 537 609 532 619 532 613 538 611 540 609 532 611 540 1748 534 1749 533 1750 532 1754 538 1743 539 1747 535 1750 532 1747 535 618 533 613 538 44105 8864 2224 537 93399 8912 2202 538 +type: parsed +protocol: NECext +address: 18 18 00 00 +command: C0 3F 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 492 4975 496 4993 498 498 500 4056 498 504 494 4055 499 4963 497 532 496 4031 492 4996 495 502 496 4060 494 4972 499 4990 491 506 492 4063 491 511 497 4052 492 4970 490 539 500 4027 496 103358 500 4961 500 4995 496 505 493 4056 498 499 499 4057 497 4969 491 533 496 4026 497 4997 494 508 490 4059 495 4967 494 5001 490 511 497 4053 491 505 493 4063 491 4975 496 528 490 4032 491 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 2357 610 1183 592 1191 614 1179 595 1188 618 584 613 1180 593 588 613 1190 612 590 605 587 613 589 605 587 25398 2355 623 1180 591 1181 627 1186 589 1183 618 584 616 1187 587 584 614 1189 615 587 605 587 615 587 609 593 +type: parsed +protocol: SIRC +address: 01 00 00 00 +command: 2F 00 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 3425 3482 848 2607 846 2639 845 2608 846 2639 845 2612 852 2624 850 2613 851 911 851 885 847 919 843 891 851 915 847 890 852 907 845 897 845 917 845 891 851 915 847 887 845 2639 845 2612 852 2625 849 2613 851 2630 844 34282 3455 3478 852 2601 852 2633 851 2605 848 2629 845 2617 847 2633 851 2604 849 917 845 890 852 913 849 889 843 915 847 896 846 916 846 890 852 914 848 885 847 919 843 895 847 2630 844 2617 847 2634 850 2605 848 2636 848 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 500 500 498 4066 498 5058 504 502 506 4061 503 508 500 4060 504 5055 497 5055 497 511 497 4071 503 5047 505 507 501 4065 499 5049 503 512 496 124314 501 508 500 4067 507 5043 499 513 505 4060 504 501 497 4073 501 5052 500 5052 500 512 496 4066 498 5058 504 506 502 4058 506 5053 499 509 499 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 176 7763 174 8817 169 10842 544 1955 541 967 540 1952 544 959 538 972 546 962 545 1947 538 1952 544 967 540 1955 541 964 543 1947 539 972 546 1949 547 7873 170 7746 170 10350 175 11811 543 960 537 1961 535 972 535 970 537 965 542 1956 540 1956 540 965 542 1947 539 973 534 1960 536 969 538 1952 534 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 2570 2682 1189 1208 1186 2665 1186 1217 1187 2668 1183 1215 1179 2671 1190 2695 1186 1187 1187 2692 1179 2671 1190 1213 1181 1193 1191 1207 1187 2663 1188 1215 1179 2676 1185 46941 2563 2685 1186 1191 1183 2698 1184 1188 1186 2691 1180 1197 1187 2694 1187 2666 1185 1210 1184 2674 1187 2695 1186 1185 1189 1206 1188 1189 1185 2696 1186 1186 1187 2689 1182 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 873 916 1773 906 877 925 878 919 874 928 875 925 878 1806 1770 914 879 1809 870 928 1772 88684 870 926 1774 908 875 926 877 917 876 929 874 925 878 1809 1777 905 877 1808 871 930 1770 +type: parsed +protocol: RC5 +address: 00 00 00 00 +command: 26 00 00 00 +# +name: Power +type: parsed +protocol: RC5 +address: 00 00 00 00 +command: 0C 00 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 -data: 874 906 877 912 1767 904 879 908 874 918 875 915 878 907 875 920 873 1795 874 914 1775 897 875 88704 879 914 868 922 1767 897 875 919 874 915 878 911 872 920 873 914 879 1792 877 914 1775 889 873 -# -name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 3325 1560 406 444 401 453 402 1226 404 449 406 1226 404 443 402 454 401 449 406 1224 406 1228 402 446 409 444 401 451 404 1223 407 1230 410 440 405 445 410 443 402 446 409 444 401 451 404 442 403 453 402 448 407 443 402 451 404 1224 406 448 407 444 401 445 410 446 409 1221 409 442 403 1231 409 439 406 1227 403 450 405 441 404 452 403 1227 403 448 407 446 409 439 406 447 408 444 401 445 400 456 410 440 405 52348 3320 1553 403 445 400 454 401 1230 400 447 408 1228 402 449 406 444 401 452 403 1225 405 1229 431 421 404 442 403 454 401 1229 401 1229 431 423 402 446 399 455 400 451 404 442 403 453 402 448 407 443 402 451 404 444 401 452 403 1229 401 445 400 457 398 451 404 446 399 1235 405 443 402 1232 408 444 401 1225 405 452 403 447 398 452 403 1231 399 449 406 447 408 443 402 444 401 456 399 450 405 445 400 453 402 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 990 915 980 909 986 924 981 2829 981 934 981 2823 987 923 982 2828 982 933 982 906 989 33895 989 907 988 927 988 900 985 2841 979 915 980 2851 980 909 986 2840 980 914 981 934 981 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 821 5754 848 2490 841 2492 819 2524 817 5726 845 2492 839 5727 844 5757 845 5727 854 2483 848 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 5092 1621 406 2599 406 2598 407 2605 1653 1616 411 2619 1609 1606 1654 1618 409 2623 382 2600 405 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 8879 4446 566 1747 565 584 567 1744 568 581 570 1744 568 574 567 586 565 582 569 578 563 1753 570 575 566 1749 563 585 566 1743 569 1749 563 1748 564 582 569 1747 565 580 571 578 573 1741 571 572 569 584 567 580 571 1741 571 578 573 1738 564 1751 572 577 564 1744 568 1750 572 1740 572 41007 8906 2257 565 93855 8872 2265 567 +type: parsed +protocol: NEC +address: 15 00 00 00 +command: 12 00 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 1144 1010 6795 26754 1151 997 6798 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 1144 1009 1120 1006 1143 1991 1116 26758 1146 1006 1123 1003 1146 1988 1119 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 170 46238 169 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 8906 4165 572 1672 569 1678 563 640 572 637 565 643 569 633 569 643 569 1674 567 639 563 1684 567 637 565 1681 570 1675 566 1673 568 1681 570 636 566 640 572 637 565 639 563 1684 567 640 572 630 572 640 572 634 568 1675 566 1681 570 1670 571 638 564 1681 570 1669 572 1678 563 1680 571 40485 8898 2252 570 85621 8955 2194 567 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 446 1191 449 1194 446 1195 445 1204 446 1200 1316 459 447 1193 447 1202 448 1197 443 1201 449 1191 449 34491 443 1204 446 1197 443 1198 442 1207 443 1202 1314 436 440 1201 449 1199 441 1205 445 1198 442 1199 441 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 4268 4327 522 1593 516 1603 516 1597 522 519 520 520 519 515 514 531 518 520 519 519 520 521 518 519 520 1597 522 1595 514 1597 522 1599 520 1595 514 524 515 1604 515 521 518 523 516 524 515 519 520 525 514 524 515 1599 520 522 517 1596 513 1605 514 1602 517 1595 514 1607 522 1592 516 40481 8748 2187 523 93986 8721 2189 521 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 247 3006 244 153 178 1007 251 117 637 597 381 678 218 156 175 529 382 679 217 157 174 24963 247 3038 252 117 219 994 249 119 217 483 250 117 173 531 278 779 173 167 169 569 383 679 217 156 175 126538 246 3039 251 118 218 995 247 120 195 504 249 118 172 532 277 780 172 168 178 560 382 680 216 157 174 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 8872 4454 568 579 572 578 573 572 569 581 570 1744 568 575 566 587 564 582 569 1743 569 1747 565 1745 567 1748 564 584 567 1741 571 1747 565 1747 565 1747 565 1751 571 1739 563 1752 570 578 563 1745 567 1751 572 1741 571 575 566 585 566 578 573 577 564 1750 573 571 570 583 568 579 572 41007 8905 2258 574 93846 8871 2266 566 +type: parsed +protocol: NEC +address: 10 00 00 00 +command: EF 00 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 4278 4318 521 517 522 520 519 517 522 520 519 521 518 516 513 531 518 520 519 1595 514 1605 514 1599 520 1598 521 1595 513 1598 521 1600 519 1596 513 1602 517 1601 518 1595 514 1604 515 525 514 520 519 526 513 525 514 524 515 527 522 513 516 526 513 1603 516 1595 514 1607 522 1593 516 40481 8749 2186 524 93985 8722 2189 521 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 2746 8423 2744 19607 2746 19601 2742 8431 2745 8424 2742 19608 2745 8419 2747 19608 2745 19607 2746 8422 2744 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 170 6683 174 4889 175 10382 372 849 821 2498 176 10378 264 2479 842 2492 839 2475 846 2483 838 2481 840 2495 836 2477 844 845 846 37009 172 6681 176 4888 175 10381 373 848 924 2395 844 2490 174 10383 248 2492 172 10386 245 2495 169 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 8898 4453 569 578 573 577 574 1737 565 584 567 582 569 574 567 1751 572 1741 571 1741 571 1744 568 576 575 1741 571 1743 569 1739 573 579 572 575 566 581 570 580 571 574 567 1748 575 1739 573 570 571 582 569 578 573 1739 573 1742 570 1740 572 577 574 575 566 1742 570 1749 574 1738 574 41006 8875 2262 570 93850 8907 2256 566 +type: parsed +protocol: NEC +address: C4 00 00 00 +command: 18 00 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 37 00 00 00 +command: 12 00 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 -data: 8872 4454 568 1745 567 1749 563 1746 566 584 567 1747 565 1743 569 583 568 579 572 575 566 584 567 578 563 1752 571 578 563 580 571 1747 565 1747 565 581 570 1746 566 578 573 577 564 1751 572 571 570 583 568 579 572 1740 572 578 563 1747 565 1750 573 576 565 1743 569 1749 563 1749 563 41017 8906 2257 565 93855 8872 2265 567 -# -name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 179 2644 178 8174 170 2646 176 8181 173 2648 174 8177 177 2640 172 5419 174 5413 170 2649 173 2644 178 2646 176 2646 176 5409 174 28831 174 2651 171 8183 171 2648 174 8174 170 2655 177 8177 177 2642 170 5412 171 5420 173 2649 173 2646 176 2640 172 2653 169 5419 174 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 174 2648 174 8178 176 2640 171 8185 169 2653 169 8182 172 2645 177 2647 557 2264 558 5027 174 5410 173 5418 175 5413 170 28837 168 2649 173 8184 170 2652 170 8181 173 2643 169 8188 176 2646 176 2643 168 2648 174 5417 176 5411 172 5413 170 5413 170 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 178 706 266 139 268 137 173 173 198 234 178 126768 175 299 169 86 275 130 267 138 172 230 177 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 554 1922 584 3809 582 3782 578 3821 580 1920 555 1941 544 1922 574 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 476 1470 465 3479 474 3469 474 3477 475 1467 468 1471 474 27473 472 1474 472 3475 467 3478 475 3468 474 1471 475 1468 467 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 301 2188 236 2169 235 2205 230 1009 234 1070 183 1064 179 2198 206 1046 207 1069 173 2207 207 1042 211 1062 201 1043 210 1032 231 1005 237 1039 234 1006 236 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 8872 4453 570 1744 568 582 569 1741 571 1744 568 580 571 1738 564 1754 569 578 563 584 567 1749 563 581 570 580 571 1743 569 573 568 585 566 1746 566 580 571 580 571 1739 563 586 565 1749 563 579 572 582 569 577 564 1748 564 1752 571 574 567 1748 564 584 567 1742 570 1748 564 1747 565 41015 8898 2265 567 93853 8875 2262 570 +type: parsed +protocol: NEC +address: 6D 00 00 00 +command: 14 00 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 20 00 00 00 +command: 11 00 00 00 +# +name: Power +type: parsed +protocol: NEC +address: A0 00 00 00 +command: 0B 00 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 28 00 00 00 +command: 0B 00 00 00 +# +name: Power +type: parsed +protocol: NEC +address: FF 00 00 00 +command: 3F 00 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 -data: 8904 4446 576 572 569 581 570 575 566 584 567 582 569 1739 573 579 572 575 566 1746 566 1750 572 1738 574 1741 571 1742 570 573 568 1750 572 1740 572 1740 572 578 573 572 569 581 570 1744 568 574 567 586 575 572 569 578 573 1742 570 1740 572 1743 569 579 572 1737 565 1753 570 1743 569 41010 8881 2257 565 93855 8903 2259 573 -# -name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 8878 4448 564 584 567 583 568 577 564 586 565 584 567 1741 571 582 569 1743 569 1743 569 1746 566 1744 568 1747 565 1749 563 579 572 1747 565 581 570 1743 569 1746 566 578 573 1743 569 579 572 571 570 583 568 579 572 575 566 584 567 1743 569 581 570 1744 568 1740 572 1746 566 1746 566 41013 8898 2264 568 93853 8872 2265 567 -# -name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 8900 4450 572 575 566 585 566 578 573 1743 569 579 572 1736 566 587 574 572 569 1743 569 1747 565 1745 567 582 569 1745 567 575 566 1753 570 1742 570 1742 570 1746 566 578 573 1742 570 578 573 570 571 582 569 578 573 574 567 583 568 1742 570 579 572 1742 570 1738 574 1744 568 1744 568 41012 8871 2266 566 93855 8903 2258 574 -# -name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 8872 4454 568 1745 567 1749 563 1747 565 1750 562 1752 571 1737 565 1754 568 1743 569 578 563 587 564 581 570 580 571 577 564 579 572 581 570 576 565 1748 564 1751 572 1739 563 1752 571 1743 569 1739 563 590 571 575 566 581 570 580 571 574 567 583 568 580 571 572 569 1750 562 1749 563 41017 8905 2257 575 93846 8871 2266 566 -# -name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 176 7764 173 11361 544 1951 545 1948 176 8815 171 2319 177 2322 174 2321 175 2318 178 2313 173 18281 170 7746 170 11369 536 1954 542 1957 539 969 538 1954 542 1949 536 1962 534 1960 174 2320 176 2315 170 2328 178 2317 168 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 172 23035 176 2267 178 2285 170 2270 175 2288 177 11602 222 2218 216 2246 173 183 173 935 221 218 174 864 221 1250 171 1310 223 2219 216 2247 218 1244 223 216 176 869 170 1296 217 2239 216 1254 223 216 176 866 219 9127 169 7642 173 2284 171 2273 172 2290 175 2263 171 10143 178 10623 222 1245 222 217 175 1843 220 2226 219 1264 223 1237 174 183 178 952 219 2222 223 216 176 866 219 1249 172 9190 173 7637 178 2266 169 2286 169 2280 175 2284 171 10125 175 10622 224 215 177 868 216 2228 217 2238 171 1299 224 215 177 865 174 183 173 934 222 216 176 1848 215 1247 220 1265 222 762 170 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 7410 1482 382 2742 375 2747 380 2751 1630 1535 400 2724 1657 1529 1629 1538 407 2720 407 2716 401 2722 4125 1549 376 2751 376 2748 379 2744 1626 1541 405 2723 1658 1530 1628 1531 404 2726 401 2726 401 2723 4124 1542 383 2747 380 2747 380 2745 1626 1534 401 2729 1652 1539 1629 1532 403 2719 408 2722 405 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 4277 4319 520 518 521 521 518 518 521 1597 522 1594 515 1597 522 1599 520 1594 515 1600 519 1600 519 1594 515 526 513 527 522 512 517 528 521 517 522 516 513 1605 514 522 517 525 514 525 514 521 518 526 513 525 514 1600 519 523 516 1597 522 1596 513 1603 516 1595 514 1607 522 1593 516 40481 8749 2186 524 93986 8721 2188 522 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 1325 431 445 1199 1317 455 441 1207 443 1202 1294 457 449 1190 440 1209 441 1205 445 1198 1318 454 442 93237 1320 434 442 1201 1325 448 448 1200 440 1205 1291 460 446 1193 447 1202 448 1198 442 1201 1325 447 449 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 8876 4450 572 575 566 585 566 578 573 577 564 585 566 577 564 589 572 574 567 1745 567 1749 563 1747 565 1750 562 1751 571 1737 565 1754 569 1743 569 1743 569 1747 565 579 572 1743 569 579 572 571 570 583 568 579 572 575 566 584 567 1743 569 581 570 1744 568 1740 572 1746 566 1746 566 41013 8898 2265 567 93853 8873 2264 568 +type: parsed +protocol: NEC +address: 00 00 00 00 +command: 0B 00 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 300 1791 297 744 295 743 296 751 298 745 294 747 302 736 293 1837 271 745 294 747 302 1793 295 752 297 1802 296 1801 297 742 297 1806 302 31592 296 1801 297 742 297 749 300 744 295 745 294 745 294 752 297 1829 269 746 293 745 294 1809 300 744 295 1802 296 1799 299 748 301 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 178 2003 177 2899 177 1996 174 2908 168 2910 177 2000 170 2004 176 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 8898 4173 564 642 570 1677 564 1677 564 645 567 640 572 631 571 641 571 635 567 639 563 1683 568 1673 568 641 571 636 566 637 565 647 565 641 571 634 568 642 570 1671 570 639 563 1682 569 632 570 643 569 636 566 1677 564 1683 568 636 566 1680 571 636 566 1674 567 1682 569 1674 567 40489 8904 2246 566 85626 8902 2248 564 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 8897 4454 569 578 573 1743 569 576 565 1750 572 576 575 1733 569 584 567 1745 567 1745 567 583 568 1742 570 579 572 1742 570 573 568 1750 573 574 567 580 571 580 571 573 568 582 569 580 571 572 569 584 567 1744 568 1744 568 1748 575 1735 567 1749 574 1740 572 1736 566 1752 571 576 575 41005 8878 2259 563 93858 8901 2260 572 +type: parsed +protocol: NEC +address: AA 00 00 00 +command: 80 00 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 51 00 00 00 +command: 08 00 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 -data: 8880 4446 566 1747 565 585 566 578 573 577 564 1750 573 571 570 1748 564 582 569 578 573 1743 569 1741 571 1744 568 580 571 1737 565 588 563 1749 563 583 568 582 569 576 565 1750 573 576 565 578 573 580 571 576 565 1747 565 1751 571 1738 564 586 565 1749 563 1745 567 1751 572 1741 571 41008 8905 2258 574 93846 8871 2266 566 -# -name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 3892 3856 525 978 529 977 530 969 528 977 530 974 523 975 532 1924 531 971 526 1924 531 975 532 1916 529 976 531 1921 524 1947 508 1925 530 1920 525 1926 529 1925 530 970 527 1927 528 976 531 1915 530 978 529 1921 1033 9201 3871 3867 524 977 530 975 522 981 526 972 525 983 524 978 529 1921 524 982 525 1923 532 973 524 1928 527 971 526 1931 524 1950 505 1922 523 1931 524 1924 531 1923 532 972 525 1922 523 985 533 1918 527 975 532 1922 1032 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 8900 4451 571 576 575 1742 570 1739 573 1742 570 578 573 1736 566 1752 570 576 575 1737 575 575 566 579 572 578 573 1741 571 571 570 583 568 1745 567 579 572 578 573 1738 574 575 566 1748 575 568 573 581 570 576 575 1737 565 1751 572 573 568 1747 576 573 568 1741 571 1747 565 1747 565 41014 8878 2260 562 93858 8901 2261 571 +type: parsed +protocol: NEC +address: 6E 00 00 00 +command: 14 00 00 00 +# +name: Power +type: parsed +protocol: RC5 +address: 07 00 00 00 +command: 0C 00 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 -data: 875 904 1745 924 879 913 880 1786 873 919 874 917 1742 922 871 1802 877 912 1747 921 872 88714 880 907 1742 930 873 917 876 1788 871 924 879 910 1749 919 874 1798 871 916 1743 928 875 -# -name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 4758 1543 403 2731 407 2726 402 2739 1601 1514 401 2760 1580 1530 1577 1540 406 2758 400 2708 1602 1535 400 2740 408 2729 409 2726 401 2731 1599 1520 405 2758 1572 1540 1578 1532 403 2737 431 2706 1604 1535 411 2722 405 2734 403 2734 404 2731 1599 1512 403 2764 1576 1539 1578 1533 402 2730 428 2712 1608 1534 402 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 8873 4453 570 578 563 1753 570 575 566 1749 563 585 566 1742 570 583 568 1744 568 1744 568 582 569 1741 571 578 573 1741 571 572 569 1749 563 583 568 1745 567 1748 564 1746 566 583 568 581 570 1738 564 589 572 1740 572 574 567 584 567 577 564 1752 571 1743 569 573 568 1751 572 575 566 41014 8900 2263 569 93851 8878 2259 563 +type: parsed +protocol: NEC +address: AA 00 00 00 +command: A7 00 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 171 313 176 798 337 133 600 232 170 126777 176 65 169 496 176 200 609 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 500 527 491 4033 500 4986 495 510 498 4054 500 499 499 4048 496 4974 497 530 499 4026 497 4989 492 513 495 4057 497 4967 493 4992 499 506 492 4060 494 505 493 4054 500 98563 497 529 500 4025 498 4988 493 512 496 4056 498 501 497 4050 493 4976 495 532 497 4028 495 4991 500 505 493 4059 495 4969 491 4994 497 508 490 4062 492 507 491 4056 498 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 879 901 871 1796 1770 903 869 917 876 916 877 913 880 906 877 918 875 914 879 1788 1768 1784 875 87826 871 921 872 1797 1769 897 875 919 874 915 878 910 873 920 873 914 879 913 870 1800 1776 1767 871 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 874 905 1774 894 878 914 879 908 875 917 876 915 878 907 876 919 874 1793 876 913 1777 895 878 88703 872 920 1769 901 872 913 870 925 878 910 873 916 877 916 877 910 873 1798 871 919 1770 894 878 +type: parsed +protocol: RC5 +address: 00 00 00 00 +command: 0C 00 00 00 +# +name: Power +type: parsed +protocol: Kaseikyo +address: 90 02 20 00 +command: D0 03 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 -data: 3339 1714 415 445 420 1283 418 440 415 448 418 444 422 435 420 446 420 440 415 445 421 443 412 445 421 443 412 449 416 1279 412 455 421 439 416 443 412 452 414 444 411 452 414 1287 414 442 413 453 413 1287 414 446 419 444 422 437 418 445 421 441 414 442 413 452 414 447 419 1281 420 443 412 1285 416 1287 414 1287 414 1282 419 447 419 441 414 1286 415 448 418 1280 421 1282 419 443 412 1283 418 448 418 1283 418 73871 3336 1694 414 444 411 1291 410 452 414 442 413 453 413 448 418 442 413 450 416 443 412 450 416 447 419 437 418 448 418 1282 419 441 414 449 417 442 413 449 417 446 420 436 419 1287 414 446 420 440 415 1288 413 445 410 453 413 449 417 439 416 450 416 445 421 439 416 447 419 1279 412 451 415 1287 414 1282 419 1287 414 1285 416 444 411 453 413 1285 416 447 419 1283 418 1278 413 453 413 1287 414 446 419 1284 417 -# -name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 4411 4332 558 1660 561 596 565 612 559 597 564 617 565 585 566 620 561 591 560 620 561 595 566 611 560 597 564 1653 558 592 559 627 565 589 562 617 564 1630 560 617 564 592 559 22591 4439 4322 558 1639 561 618 563 590 561 622 560 592 559 624 557 597 564 612 559 600 561 618 563 590 561 622 559 1628 562 621 561 594 567 609 562 597 564 1652 559 595 566 617 564 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 3444 1767 413 487 419 1274 417 481 415 1277 414 488 418 1267 414 492 414 1276 415 484 412 1282 419 478 418 1275 416 1276 415 480 416 1280 421 479 417 1272 419 1275 416 1272 419 1274 417 484 412 484 412 493 413 1277 414 485 421 1273 418 479 417 486 420 1271 420 476 420 486 420 479 417 482 414 1280 411 1276 415 488 418 1273 418 478 418 488 418 481 415 1275 416 487 419 478 418 485 411 1280 421 475 421 1275 416 1273 418 69071 3439 1759 441 456 440 1253 438 463 443 1243 438 468 438 1251 440 460 446 1247 444 454 442 1251 440 461 445 1241 440 1256 445 455 441 1248 443 461 445 1242 439 1254 447 1245 446 1240 441 465 441 458 438 462 444 1249 442 456 440 1252 439 463 443 452 444 1252 439 461 445 454 442 461 445 452 444 1249 442 1250 441 454 442 1254 437 463 443 456 440 463 443 1245 446 456 440 462 444 451 445 1251 440 460 436 1253 438 1256 445 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 8705 4317 583 682 581 688 585 678 585 1721 581 1722 580 681 582 690 583 682 581 1721 581 1725 587 1713 579 689 584 683 580 1718 584 1724 588 1714 588 677 586 683 580 683 580 1726 586 680 583 678 585 687 586 679 584 1718 584 1721 581 1719 583 685 588 1716 586 1713 579 1729 583 1719 583 41145 8706 2217 585 94686 8705 2217 584 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 8888 4470 532 576 534 576 534 571 539 572 538 1706 535 568 532 581 529 578 532 1711 530 581 529 1711 530 1717 534 574 536 1703 538 575 535 572 538 1705 536 1711 530 1711 530 1716 535 1709 532 571 529 585 535 571 529 579 531 579 531 574 536 574 536 573 537 1701 530 1720 531 1712 529 39045 8912 2261 540 94838 8911 2235 536 +type: parsed +protocol: NECext +address: 10 2D 00 00 +command: 1F E0 00 00 +# +name: Power +type: parsed +protocol: RC5 +address: 05 00 00 00 +command: 0C 00 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 -data: 874 915 1774 904 879 923 870 1816 1770 1800 1776 904 879 1805 874 931 1769 909 874 88698 876 927 1773 904 879 922 871 1819 1767 1796 1770 914 879 1809 870 928 1772 910 873 -# -name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 178 7753 174 2308 178 2284 171 2316 170 2298 177 10228 174 10724 223 1256 221 217 175 1868 169 2293 172 1327 216 1263 178 1316 217 2245 220 218 174 887 218 1261 170 10707 174 7752 175 2296 169 2314 171 2293 172 2307 179 10216 176 6265 174 10729 219 1258 219 1272 215 1268 173 2310 221 1255 222 217 175 877 172 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 532 1692 559 561 529 574 567 559 531 566 564 555 535 1694 557 568 532 1691 560 560 530 573 557 568 532 565 565 555 535 567 563 1688 533 564 567 554 536 567 563 562 538 558 562 558 532 1697 565 561 539 1683 558 1689 532 1697 564 1687 534 1689 562 1684 537 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 874 915 1774 904 879 923 870 927 876 1814 876 925 1775 900 872 1821 879 920 1769 909 874 88702 871 926 1774 907 876 925 878 917 876 1817 873 927 1773 905 878 1813 876 921 1769 912 871 +type: parsed +protocol: RC5 +address: 03 00 00 00 +command: 0C 00 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 12 FF 00 00 +command: 0E F1 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 -data: 8884 4474 538 569 531 1716 535 570 530 580 530 1715 536 567 533 580 530 577 533 1710 531 1715 536 1705 536 1710 531 1714 537 1702 529 1720 531 1712 529 578 532 1715 536 1705 536 1710 531 577 533 570 530 584 536 571 529 1714 537 573 537 568 532 578 532 1713 538 1701 530 1719 532 1711 530 39044 8913 2260 531 94848 8907 2239 532 -# -name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 446 1694 455 1706 453 1705 424 628 452 597 452 622 458 1673 456 625 455 594 455 1706 454 590 459 621 459 591 458 616 453 591 458 622 539 22750 459 1675 454 1733 427 1712 427 622 458 588 451 622 458 1681 458 618 451 595 454 1705 455 598 451 625 454 592 457 616 453 598 451 626 535 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 3429 3445 875 2555 868 875 867 871 871 2560 873 868 874 2551 872 874 868 871 871 869 873 870 872 865 867 2565 868 873 869 2556 867 2567 866 874 868 2560 873 870 872 2555 868 2564 869 2586 847 2577 846 2589 844 870 872 32983 3470 3430 869 2559 874 868 874 867 875 2550 873 873 869 2559 874 865 867 877 875 862 870 873 869 872 870 2555 868 877 875 2554 869 2559 874 869 873 2554 869 873 869 2562 871 2553 870 2590 843 2586 847 2581 842 876 866 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 8873 4452 571 1743 569 580 571 574 567 583 568 1746 566 1742 570 1748 564 582 569 578 563 1753 570 1740 572 1743 569 579 572 571 570 583 568 1744 568 579 572 578 573 572 569 1746 566 582 569 574 567 586 565 582 569 1743 569 1746 566 1744 568 581 570 1745 567 1741 571 1747 565 1746 566 41014 8898 2264 568 93853 8874 2263 569 +type: parsed +protocol: NEC +address: 71 00 00 00 +command: 08 00 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 83 00 00 00 +command: FF 00 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 -data: 8902 4448 574 1739 573 1742 570 575 566 584 567 581 570 573 568 585 566 1746 566 580 571 580 571 1739 573 1742 570 1743 569 1739 573 1745 567 579 572 1741 571 1744 568 1742 570 1745 567 1747 565 1743 569 1749 573 1739 573 573 568 583 568 576 575 575 566 583 568 575 566 587 574 572 569 41011 8871 2266 566 93854 8902 2260 572 -# -name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 4275 4320 519 520 519 523 516 520 519 1599 520 520 519 515 524 521 518 520 519 1595 524 1595 524 1588 520 521 518 1599 520 1591 517 1603 516 1599 520 1595 524 1594 525 1588 521 1597 522 518 521 513 526 519 520 518 521 517 522 520 519 517 522 519 520 1597 522 1589 519 1601 518 1597 522 40475 8724 2186 514 93995 8752 2183 516 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 10380 4892 599 620 592 605 597 620 592 604 598 623 589 2081 598 627 595 2080 599 2101 598 2105 574 2099 590 2088 591 2111 599 591 590 2116 594 599 593 626 596 2082 597 619 593 2086 593 626 596 594 598 627 595 598 594 2106 593 604 598 2100 589 607 595 2107 593 2079 590 2116 594 2082 750 41149 8722 2109 590 94682 8727 2104 596 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 8879 4446 566 1747 565 1751 571 573 568 582 569 580 571 571 570 584 567 1744 568 579 572 578 573 1737 565 1751 572 1742 570 1738 564 1754 568 578 573 574 567 584 567 577 564 1752 571 577 564 580 571 582 569 577 564 1748 564 1752 571 1739 563 587 564 1750 572 1736 566 1752 571 1742 570 41009 8903 2260 572 93848 8880 2257 565 +type: parsed +protocol: NEC +address: 83 00 00 00 +command: 08 00 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 4271 4324 515 1600 519 1600 519 1594 515 1603 516 1601 518 1593 516 1605 514 1601 518 520 519 522 517 520 519 522 517 523 516 518 521 523 516 522 517 1598 521 1597 522 1591 518 1600 519 521 518 516 523 522 517 521 518 520 519 523 516 520 519 522 517 1599 520 1591 518 1603 516 1599 520 40477 8753 2183 516 93993 8724 2185 515 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 7847 3931 470 1448 467 495 472 1443 472 490 467 1451 464 491 466 499 468 491 466 4413 467 1455 470 486 471 1449 466 495 472 1441 464 501 466 492 465 494 463 22093 7851 3934 467 1454 471 490 467 1446 469 496 471 1446 469 489 468 494 473 484 473 4410 470 1449 466 489 468 1455 470 489 468 1449 466 496 471 486 471 490 467 # name: Power @@ -1656,20 +1656,20 @@ type: parsed protocol: RC5 address: 01 00 00 00 command: 21 00 00 00 -# +# # Model: VIZIO name: Mute type: parsed protocol: NEC address: 04 00 00 00 command: 09 00 00 00 -# +# name: Vol_up type: parsed protocol: NEC address: 04 00 00 00 command: 02 00 00 00 -# +# name: Vol_dn type: parsed protocol: NEC diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index ac7d1a0c5..3d7bd7cd2 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,11.6,, +Version,+,11.7,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -1630,6 +1630,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* diff --git a/lib/infrared/encoder_decoder/common/infrared_common_decoder.c b/lib/infrared/encoder_decoder/common/infrared_common_decoder.c index 8acb6751b..d67b204f5 100644 --- a/lib/infrared/encoder_decoder/common/infrared_common_decoder.c +++ b/lib/infrared/encoder_decoder/common/infrared_common_decoder.c @@ -1,11 +1,8 @@ +#include "infrared_common_i.h" + +#include #include #include -#include "infrared.h" -#include "infrared_common_i.h" -#include -#include -#include "infrared_i.h" -#include static void infrared_common_decoder_reset_state(InfraredCommonDecoder* decoder); diff --git a/lib/infrared/encoder_decoder/common/infrared_common_encoder.c b/lib/infrared/encoder_decoder/common/infrared_common_encoder.c index 9c774617e..f145a585a 100644 --- a/lib/infrared/encoder_decoder/common/infrared_common_encoder.c +++ b/lib/infrared/encoder_decoder/common/infrared_common_encoder.c @@ -1,10 +1,9 @@ -#include -#include "infrared.h" #include "infrared_common_i.h" -#include -#include -#include "infrared_i.h" -#include + +#include +#include +#include +#include static InfraredStatus infrared_common_encode_bits(InfraredCommonEncoder* encoder, uint32_t* duration, bool* level) { diff --git a/lib/infrared/encoder_decoder/common/infrared_common_protocol_defs.c b/lib/infrared/encoder_decoder/common/infrared_common_protocol_defs.c deleted file mode 100644 index 3dd26e9d8..000000000 --- a/lib/infrared/encoder_decoder/common/infrared_common_protocol_defs.c +++ /dev/null @@ -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, -}; diff --git a/lib/infrared/encoder_decoder/infrared.c b/lib/infrared/encoder_decoder/infrared.c index 2c5ef0fff..fcfc5da2b 100644 --- a/lib/infrared/encoder_decoder/infrared.c +++ b/lib/infrared/encoder_decoder/infrared.c @@ -1,13 +1,16 @@ #include "infrared.h" -#include -#include "common/infrared_common_i.h" -#include "infrared_protocol_defs_i.h" -#include -#include + #include -#include -#include "infrared_i.h" -#include +#include +#include +#include + +#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; } diff --git a/lib/infrared/encoder_decoder/infrared.h b/lib/infrared/encoder_decoder/infrared.h index 2c76645ff..3ab46cbbf 100644 --- a/lib/infrared/encoder_decoder/infrared.h +++ b/lib/infrared/encoder_decoder/infrared.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #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 diff --git a/lib/infrared/encoder_decoder/infrared_i.h b/lib/infrared/encoder_decoder/infrared_i.h index 3a645cede..3efc41cd6 100644 --- a/lib/infrared/encoder_decoder/infrared_i.h +++ b/lib/infrared/encoder_decoder/infrared_i.h @@ -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*); diff --git a/lib/infrared/encoder_decoder/infrared_protocol_defs_i.h b/lib/infrared/encoder_decoder/infrared_protocol_defs_i.h deleted file mode 100644 index 6146f7b4e..000000000 --- a/lib/infrared/encoder_decoder/infrared_protocol_defs_i.h +++ /dev/null @@ -1,320 +0,0 @@ -#pragma once - -#include -#include -#include -#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; diff --git a/lib/infrared/encoder_decoder/kaseikyo/infrared_decoder_kaseikyo.c b/lib/infrared/encoder_decoder/kaseikyo/infrared_decoder_kaseikyo.c index b8db81d7e..e85a89652 100644 --- a/lib/infrared/encoder_decoder/kaseikyo/infrared_decoder_kaseikyo.c +++ b/lib/infrared/encoder_decoder/kaseikyo/infrared_decoder_kaseikyo.c @@ -1,9 +1,5 @@ -#include "infrared.h" -#include "infrared_protocol_defs_i.h" -#include -#include -#include -#include "../infrared_i.h" +#include "infrared_protocol_kaseikyo_i.h" +#include 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) { diff --git a/lib/infrared/encoder_decoder/kaseikyo/infrared_encoder_kaseikyo.c b/lib/infrared/encoder_decoder/kaseikyo/infrared_encoder_kaseikyo.c index 5814c7255..618fc3bab 100644 --- a/lib/infrared/encoder_decoder/kaseikyo/infrared_encoder_kaseikyo.c +++ b/lib/infrared/encoder_decoder/kaseikyo/infrared_encoder_kaseikyo.c @@ -1,9 +1,5 @@ +#include "infrared_protocol_kaseikyo_i.h" #include -#include "common/infrared_common_i.h" -#include -#include "../infrared_i.h" -#include "infrared_protocol_defs_i.h" -#include 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) { diff --git a/lib/infrared/encoder_decoder/kaseikyo/infrared_kaseikyo_spec.c b/lib/infrared/encoder_decoder/kaseikyo/infrared_kaseikyo_spec.c deleted file mode 100644 index 87c86c7b3..000000000 --- a/lib/infrared/encoder_decoder/kaseikyo/infrared_kaseikyo_spec.c +++ /dev/null @@ -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; -} diff --git a/lib/infrared/encoder_decoder/kaseikyo/infrared_protocol_kaseikyo.c b/lib/infrared/encoder_decoder/kaseikyo/infrared_protocol_kaseikyo.c new file mode 100644 index 000000000..0c61be3bf --- /dev/null +++ b/lib/infrared/encoder_decoder/kaseikyo/infrared_protocol_kaseikyo.c @@ -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; +} diff --git a/lib/infrared/encoder_decoder/kaseikyo/infrared_protocol_kaseikyo.h b/lib/infrared/encoder_decoder/kaseikyo/infrared_protocol_kaseikyo.h new file mode 100644 index 000000000..61ff0ca1c --- /dev/null +++ b/lib/infrared/encoder_decoder/kaseikyo/infrared_protocol_kaseikyo.h @@ -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); diff --git a/lib/infrared/encoder_decoder/kaseikyo/infrared_protocol_kaseikyo_i.h b/lib/infrared/encoder_decoder/kaseikyo/infrared_protocol_kaseikyo_i.h new file mode 100644 index 000000000..bee116c4d --- /dev/null +++ b/lib/infrared/encoder_decoder/kaseikyo/infrared_protocol_kaseikyo_i.h @@ -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); diff --git a/lib/infrared/encoder_decoder/nec/infrared_decoder_nec.c b/lib/infrared/encoder_decoder/nec/infrared_decoder_nec.c index 3ad14a7ab..91384d702 100644 --- a/lib/infrared/encoder_decoder/nec/infrared_decoder_nec.c +++ b/lib/infrared/encoder_decoder/nec/infrared_decoder_nec.c @@ -1,10 +1,5 @@ -#include "common/infrared_common_i.h" -#include "infrared.h" -#include "infrared_protocol_defs_i.h" -#include -#include -#include -#include "../infrared_i.h" +#include "infrared_protocol_nec_i.h" +#include 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) { diff --git a/lib/infrared/encoder_decoder/nec/infrared_encoder_nec.c b/lib/infrared/encoder_decoder/nec/infrared_encoder_nec.c index d0039c330..87f815142 100644 --- a/lib/infrared/encoder_decoder/nec/infrared_encoder_nec.c +++ b/lib/infrared/encoder_decoder/nec/infrared_encoder_nec.c @@ -1,10 +1,7 @@ +#include "infrared_protocol_nec_i.h" + +#include #include -#include "infrared.h" -#include "common/infrared_common_i.h" -#include -#include "../infrared_i.h" -#include "infrared_protocol_defs_i.h" -#include 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) { diff --git a/lib/infrared/encoder_decoder/nec/infrared_nec_spec.c b/lib/infrared/encoder_decoder/nec/infrared_nec_spec.c deleted file mode 100644 index 16cab8b5f..000000000 --- a/lib/infrared/encoder_decoder/nec/infrared_nec_spec.c +++ /dev/null @@ -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; -} diff --git a/lib/infrared/encoder_decoder/nec/infrared_protocol_nec.c b/lib/infrared/encoder_decoder/nec/infrared_protocol_nec.c new file mode 100644 index 000000000..3444f78b6 --- /dev/null +++ b/lib/infrared/encoder_decoder/nec/infrared_protocol_nec.c @@ -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; +} diff --git a/lib/infrared/encoder_decoder/nec/infrared_protocol_nec.h b/lib/infrared/encoder_decoder/nec/infrared_protocol_nec.h new file mode 100644 index 000000000..559e31fda --- /dev/null +++ b/lib/infrared/encoder_decoder/nec/infrared_protocol_nec.h @@ -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); diff --git a/lib/infrared/encoder_decoder/nec/infrared_protocol_nec_i.h b/lib/infrared/encoder_decoder/nec/infrared_protocol_nec_i.h new file mode 100644 index 000000000..05df1f474 --- /dev/null +++ b/lib/infrared/encoder_decoder/nec/infrared_protocol_nec_i.h @@ -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); diff --git a/lib/infrared/encoder_decoder/rc5/infrared_decoder_rc5.c b/lib/infrared/encoder_decoder/rc5/infrared_decoder_rc5.c index 6b4a7c2e3..1b2f2f301 100644 --- a/lib/infrared/encoder_decoder/rc5/infrared_decoder_rc5.c +++ b/lib/infrared/encoder_decoder/rc5/infrared_decoder_rc5.c @@ -1,10 +1,7 @@ -#include "infrared.h" -#include -#include -#include -#include -#include "../infrared_i.h" -#include "../infrared_protocol_defs_i.h" +#include "infrared_protocol_rc5_i.h" + +#include +#include 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; } diff --git a/lib/infrared/encoder_decoder/rc5/infrared_encoder_rc5.c b/lib/infrared/encoder_decoder/rc5/infrared_encoder_rc5.c index 7b55cdc44..df47fb7c4 100644 --- a/lib/infrared/encoder_decoder/rc5/infrared_encoder_rc5.c +++ b/lib/infrared/encoder_decoder/rc5/infrared_encoder_rc5.c @@ -1,9 +1,7 @@ -#include -#include "infrared.h" -#include "common/infrared_common_i.h" -#include "infrared_protocol_defs_i.h" -#include -#include "../infrared_i.h" +#include "infrared_protocol_rc5_i.h" + +#include +#include 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; } diff --git a/lib/infrared/encoder_decoder/rc5/infrared_protocol_rc5.c b/lib/infrared/encoder_decoder/rc5/infrared_protocol_rc5.c new file mode 100644 index 000000000..bc7e299fd --- /dev/null +++ b/lib/infrared/encoder_decoder/rc5/infrared_protocol_rc5.c @@ -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; +} diff --git a/lib/infrared/encoder_decoder/rc5/infrared_protocol_rc5.h b/lib/infrared/encoder_decoder/rc5/infrared_protocol_rc5.h new file mode 100644 index 000000000..9dd5802a9 --- /dev/null +++ b/lib/infrared/encoder_decoder/rc5/infrared_protocol_rc5.h @@ -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); diff --git a/lib/infrared/encoder_decoder/rc5/infrared_protocol_rc5_i.h b/lib/infrared/encoder_decoder/rc5/infrared_protocol_rc5_i.h new file mode 100644 index 000000000..b906c369e --- /dev/null +++ b/lib/infrared/encoder_decoder/rc5/infrared_protocol_rc5_i.h @@ -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); diff --git a/lib/infrared/encoder_decoder/rc5/infrared_rc5_spec.c b/lib/infrared/encoder_decoder/rc5/infrared_rc5_spec.c deleted file mode 100644 index 25ea230ef..000000000 --- a/lib/infrared/encoder_decoder/rc5/infrared_rc5_spec.c +++ /dev/null @@ -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; -} diff --git a/lib/infrared/encoder_decoder/rc6/infrared_decoder_rc6.c b/lib/infrared/encoder_decoder/rc6/infrared_decoder_rc6.c index 13d3e5364..b70f7ceb8 100644 --- a/lib/infrared/encoder_decoder/rc6/infrared_decoder_rc6.c +++ b/lib/infrared/encoder_decoder/rc6/infrared_decoder_rc6.c @@ -1,10 +1,7 @@ -#include "infrared.h" -#include -#include -#include -#include -#include "../infrared_i.h" -#include "../infrared_protocol_defs_i.h" +#include "infrared_protocol_rc6_i.h" + +#include +#include 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; } diff --git a/lib/infrared/encoder_decoder/rc6/infrared_encoder_rc6.c b/lib/infrared/encoder_decoder/rc6/infrared_encoder_rc6.c index f1240b17a..d13a204ea 100644 --- a/lib/infrared/encoder_decoder/rc6/infrared_encoder_rc6.c +++ b/lib/infrared/encoder_decoder/rc6/infrared_encoder_rc6.c @@ -1,9 +1,7 @@ -#include -#include "infrared.h" -#include "common/infrared_common_i.h" -#include "infrared_protocol_defs_i.h" -#include -#include "../infrared_i.h" +#include "infrared_protocol_rc6_i.h" + +#include +#include 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; } diff --git a/lib/infrared/encoder_decoder/rc6/infrared_protocol_rc6.c b/lib/infrared/encoder_decoder/rc6/infrared_protocol_rc6.c new file mode 100644 index 000000000..40a187d85 --- /dev/null +++ b/lib/infrared/encoder_decoder/rc6/infrared_protocol_rc6.c @@ -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; +} diff --git a/lib/infrared/encoder_decoder/rc6/infrared_protocol_rc6.h b/lib/infrared/encoder_decoder/rc6/infrared_protocol_rc6.h new file mode 100644 index 000000000..f0b163411 --- /dev/null +++ b/lib/infrared/encoder_decoder/rc6/infrared_protocol_rc6.h @@ -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); diff --git a/lib/infrared/encoder_decoder/rc6/infrared_protocol_rc6_i.h b/lib/infrared/encoder_decoder/rc6/infrared_protocol_rc6_i.h new file mode 100644 index 000000000..06aa2a6a5 --- /dev/null +++ b/lib/infrared/encoder_decoder/rc6/infrared_protocol_rc6_i.h @@ -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); diff --git a/lib/infrared/encoder_decoder/rc6/infrared_rc6_spec.c b/lib/infrared/encoder_decoder/rc6/infrared_rc6_spec.c deleted file mode 100644 index 9e0ba7462..000000000 --- a/lib/infrared/encoder_decoder/rc6/infrared_rc6_spec.c +++ /dev/null @@ -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; -} diff --git a/lib/infrared/encoder_decoder/samsung/infrared_decoder_samsung.c b/lib/infrared/encoder_decoder/samsung/infrared_decoder_samsung.c index e8cd3b05c..32881d3c9 100644 --- a/lib/infrared/encoder_decoder/samsung/infrared_decoder_samsung.c +++ b/lib/infrared/encoder_decoder/samsung/infrared_decoder_samsung.c @@ -1,9 +1,5 @@ -#include "infrared.h" -#include "infrared_protocol_defs_i.h" -#include -#include -#include -#include "../infrared_i.h" +#include "infrared_protocol_samsung_i.h" +#include 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) { diff --git a/lib/infrared/encoder_decoder/samsung/infrared_encoder_samsung.c b/lib/infrared/encoder_decoder/samsung/infrared_encoder_samsung.c index 75b037f00..3aed50656 100644 --- a/lib/infrared/encoder_decoder/samsung/infrared_encoder_samsung.c +++ b/lib/infrared/encoder_decoder/samsung/infrared_encoder_samsung.c @@ -1,9 +1,7 @@ +#include "infrared_protocol_samsung_i.h" + #include -#include "common/infrared_common_i.h" -#include -#include "../infrared_i.h" -#include "infrared_protocol_defs_i.h" -#include +#include 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) { diff --git a/lib/infrared/encoder_decoder/samsung/infrared_protocol_samsung.c b/lib/infrared/encoder_decoder/samsung/infrared_protocol_samsung.c new file mode 100644 index 000000000..ca78726ac --- /dev/null +++ b/lib/infrared/encoder_decoder/samsung/infrared_protocol_samsung.c @@ -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; +} diff --git a/lib/infrared/encoder_decoder/samsung/infrared_protocol_samsung.h b/lib/infrared/encoder_decoder/samsung/infrared_protocol_samsung.h new file mode 100644 index 000000000..9abcb2e3e --- /dev/null +++ b/lib/infrared/encoder_decoder/samsung/infrared_protocol_samsung.h @@ -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); diff --git a/lib/infrared/encoder_decoder/samsung/infrared_protocol_samsung_i.h b/lib/infrared/encoder_decoder/samsung/infrared_protocol_samsung_i.h new file mode 100644 index 000000000..b85384942 --- /dev/null +++ b/lib/infrared/encoder_decoder/samsung/infrared_protocol_samsung_i.h @@ -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; diff --git a/lib/infrared/encoder_decoder/samsung/infrared_samsung_spec.c b/lib/infrared/encoder_decoder/samsung/infrared_samsung_spec.c deleted file mode 100644 index f4cbf699e..000000000 --- a/lib/infrared/encoder_decoder/samsung/infrared_samsung_spec.c +++ /dev/null @@ -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; -} diff --git a/lib/infrared/encoder_decoder/sirc/infrared_decoder_sirc.c b/lib/infrared/encoder_decoder/sirc/infrared_decoder_sirc.c index 45f06c942..fc18a183c 100644 --- a/lib/infrared/encoder_decoder/sirc/infrared_decoder_sirc.c +++ b/lib/infrared/encoder_decoder/sirc/infrared_decoder_sirc.c @@ -1,10 +1,5 @@ -#include "common/infrared_common_i.h" -#include "infrared.h" -#include "infrared_protocol_defs_i.h" -#include -#include -#include -#include "../infrared_i.h" +#include "infrared_protocol_sirc_i.h" +#include 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) { diff --git a/lib/infrared/encoder_decoder/sirc/infrared_encoder_sirc.c b/lib/infrared/encoder_decoder/sirc/infrared_encoder_sirc.c index 2c2bda1af..6adf2235c 100644 --- a/lib/infrared/encoder_decoder/sirc/infrared_encoder_sirc.c +++ b/lib/infrared/encoder_decoder/sirc/infrared_encoder_sirc.c @@ -1,10 +1,5 @@ +#include "infrared_protocol_sirc_i.h" #include -#include "infrared.h" -#include "common/infrared_common_i.h" -#include -#include "../infrared_i.h" -#include "infrared_protocol_defs_i.h" -#include 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) { diff --git a/lib/infrared/encoder_decoder/sirc/infrared_protocol_sirc.c b/lib/infrared/encoder_decoder/sirc/infrared_protocol_sirc.c new file mode 100644 index 000000000..b527fba98 --- /dev/null +++ b/lib/infrared/encoder_decoder/sirc/infrared_protocol_sirc.c @@ -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; +} diff --git a/lib/infrared/encoder_decoder/sirc/infrared_protocol_sirc.h b/lib/infrared/encoder_decoder/sirc/infrared_protocol_sirc.h new file mode 100644 index 000000000..0c3bcd8a2 --- /dev/null +++ b/lib/infrared/encoder_decoder/sirc/infrared_protocol_sirc.h @@ -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); diff --git a/lib/infrared/encoder_decoder/sirc/infrared_protocol_sirc_i.h b/lib/infrared/encoder_decoder/sirc/infrared_protocol_sirc_i.h new file mode 100644 index 000000000..e38be9bc8 --- /dev/null +++ b/lib/infrared/encoder_decoder/sirc/infrared_protocol_sirc_i.h @@ -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); diff --git a/lib/infrared/encoder_decoder/sirc/infrared_sirc_spec.c b/lib/infrared/encoder_decoder/sirc/infrared_sirc_spec.c deleted file mode 100644 index 9bf35908e..000000000 --- a/lib/infrared/encoder_decoder/sirc/infrared_sirc_spec.c +++ /dev/null @@ -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; -} diff --git a/lib/infrared/worker/infrared_transmit.c b/lib/infrared/worker/infrared_transmit.c index 1a5083019..113fb6324 100644 --- a/lib/infrared/worker/infrared_transmit.c +++ b/lib/infrared/worker/infrared_transmit.c @@ -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); diff --git a/lib/infrared/worker/infrared_worker.c b/lib/infrared/worker/infrared_worker.c index 033dba525..5add1413e 100644 --- a/lib/infrared/worker/infrared_worker.c +++ b/lib/infrared/worker/infrared_worker.c @@ -1,13 +1,10 @@ +#include "infrared_worker.h" + +#include +#include + #include #include -#include "sys/_stdint.h" -#include "infrared_worker.h" -#include -#include -#include -#include -#include -#include #include @@ -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); From 073fb3861ac310c07bdbbb3fd12fc37fe8d9799c Mon Sep 17 00:00:00 2001 From: gid9798 <30450294+gid9798@users.noreply.github.com> Date: Fri, 13 Jan 2023 17:11:12 +0300 Subject: [PATCH 10/60] Add the ability to turn pages in infrared (#2271) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: あく --- .../services/gui/modules/button_menu.c | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/applications/services/gui/modules/button_menu.c b/applications/services/gui/modules/button_menu.c index 60bd160c5..427a3e1ae 100644 --- a/applications/services/gui/modules/button_menu.c +++ b/applications/services/gui/modules/button_menu.c @@ -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; } From 6015afe36894d67a74d911671a4deee8f1b64bb3 Mon Sep 17 00:00:00 2001 From: jbohack Date: Fri, 13 Jan 2023 10:02:14 -0500 Subject: [PATCH 11/60] updated protoview and fixed array count issue arrays start at 0 and citroen_tpms was trying to read 0-10 meaning 11 full bytes rather than actually 10 (0-9). --- applications/plugins/protoview/README.md | 32 ++++++- applications/plugins/protoview/TODO | 28 +++---- applications/plugins/protoview/app.c | 48 ++++++++--- applications/plugins/protoview/app.h | 23 ++++++ applications/plugins/protoview/app_subghz.c | 78 ++++++++++++++++-- .../plugins/protoview/application.fam | 2 +- .../plugins/protoview/binaries/protoview.fap | Bin 21208 -> 28520 bytes .../plugins/protoview/binaries/update.sh | 4 + applications/plugins/protoview/crc.c | 20 +++++ .../plugins/protoview/custom_presets.h | 62 +++++++++++++- .../protoview/{proto.c => data_feed.c} | 0 .../plugins/protoview/images/protoview_1.jpg | Bin 0 -> 66885 bytes .../plugins/protoview/images/protoview_2.jpg | Bin 0 -> 64574 bytes .../plugins/protoview/protocols/b4b1.c | 2 +- .../protoview/protocols/citroen_tpms.c | 60 ++++++++++++++ .../plugins/protoview/protocols/ford_tpms.c | 64 ++++++++++++++ .../protoview/protocols/renault_tpms.c | 25 +++--- .../protoview/protocols/schrader_tpms.c | 65 +++++++++++++++ .../plugins/protoview/protocols/toyota_tpms.c | 77 +++++++++++++++++ applications/plugins/protoview/signal.c | 72 ++++++++++++---- .../plugins/protoview/view_direct_sampling.c | 35 ++++++-- applications/plugins/protoview/view_info.c | 21 ++--- .../plugins/protoview/view_settings.c | 34 ++++++-- 23 files changed, 663 insertions(+), 89 deletions(-) create mode 100644 applications/plugins/protoview/binaries/update.sh create mode 100644 applications/plugins/protoview/crc.c rename applications/plugins/protoview/{proto.c => data_feed.c} (100%) create mode 100644 applications/plugins/protoview/images/protoview_1.jpg create mode 100644 applications/plugins/protoview/images/protoview_2.jpg create mode 100644 applications/plugins/protoview/protocols/citroen_tpms.c create mode 100644 applications/plugins/protoview/protocols/ford_tpms.c create mode 100644 applications/plugins/protoview/protocols/schrader_tpms.c create mode 100644 applications/plugins/protoview/protocols/toyota_tpms.c diff --git a/applications/plugins/protoview/README.md b/applications/plugins/protoview/README.md index 4b8a3c3a0..8359c073d 100644 --- a/applications/plugins/protoview/README.md +++ b/applications/plugins/protoview/README.md @@ -6,11 +6,24 @@ the car keys), the curious person is left wondering what the device is sending at all. Using ProtoView she or he can visualize the high and low pulses like in the example image below (showing a Volkswagen key in 2FSK): -![ProtoView screenshot](/images/ProtoViewSignal.jpg) +![ProtoView screenshot raw signal](/images/protoview_1.jpg) This is often enough to make an initial idea about the encoding used and if the selected modulation is correct. +Other than that, ProtoView is able to decode a few interesting protocols: + +* TPMS sensors: Renault, Toyota, Schrader, Citroen, Ford. +* Oregon thermometer protocol 2. +* PTxxxx/SCxxxx based remotes. +* ... more will be implemented soon, hopefully. Send PRs :) + +![ProtoView screenshot Renault TPMS data](/images/protoview_2.jpg) + +The app implements a framework that makes adding and experimenting with new +protocols very simple. Check the `protocols` directory to see how the +API works. + The secondary goal of ProtoView is to provide a somewhat-documented application for the Flipper (even if ProtoView is a pretty atypical application: doesn't make use of the standard widgets and other abstractions provded by the framework). Many apps dealing with the *subghz subsystem* (the Flipper @@ -40,7 +53,7 @@ encodings are somewhat self-clocked, so they tend to have just two or three classes of pulse lengths. However often pulses of the same theoretical -length have slightly different lenghts in the case of high and low level +length have slightly different lengths in the case of high and low level (RF on or off), so we classify them separately for robustness. # Usage @@ -55,6 +68,10 @@ Under the detected sequence, you will see a small triangle marking a specific sample. This mark means that the sequence looked coherent up to that point, and starting from there it could be just noise. +If the protocol is decoded, the bottom-left corner of the screen +will show the name of the protocol, and going in the next screen +with the right arrow will show information about the decoded signal. + In the bottom-right corner the application displays an amount of time in microseconds. This is the average length of the shortest pulse length detected among the three classes. Usually the *data rate* of the protocol @@ -67,7 +84,8 @@ Things to investigate: * Many cheap remotes (gate openers, remotes, ...) are on the 433.92Mhz or nearby and use OOK modulation. * Weather stations are often too in the 433.92Mhz OOK. -* For car keys, try 443.92 OOK650 and 868.35 Mhz in OOK or 2FSK. +* For car keys, try 433.92 OOK650 and 868.35 Mhz in OOK or 2FSK. +* For TPMS try 433.92 in TPMS modulation (FSK optimized for these signals). # Installing the app from source @@ -101,3 +119,11 @@ The code is released under the BSD license. # Disclaimer This application is only provided as an educational tool. The author is not liable in case the application is used to reverse engineer protocols protected by IP or for any other illegal purpose. + +# Credits + +A big thank you to the RTL433 author, [Benjamin Larsson](https://github.com/merbanan). I used the code and tools he developed in many ways: +* To capture TPMS data with rtl433 and save to a file, to later play the IQ files and speedup the development. +* As a sourve of documentation for protocols. +* As an awesome way to visualize and understand protocols, via [these great web tools](https://triq.org/). +* To have tons of fun with RTLSDR in general, now and in the past. diff --git a/applications/plugins/protoview/TODO b/applications/plugins/protoview/TODO index 0003ccd38..feb7b0743 100644 --- a/applications/plugins/protoview/TODO +++ b/applications/plugins/protoview/TODO @@ -1,20 +1,14 @@ Core improvements ================= -- Detection of non Manchester and non RZ encoded signals. Not sure if there are any signals that are not self clocked widely used in RF. Note that the current approach already detects encodings using short high + long low and long high + short low to encode 0 and 1. In addition to the current classifier, it is possible to add one that checks for a sequence of pulses that are all multiples of some base length. This should detect, for instance, even NRZ encodings where 1 and 0 are just clocked as they are. - -- Views on-enter on-exit. - -Features -======== - -- Help screen (with press ok for next page). -- Detect the line code used and try to decode the message as hex dump. -- Pressing right/left you browse different modes: - * Current best signal pulse classes. - * Raw square wave display. Central button freezes and resumes (toggle). When frozen we display "paused" (inverted) on the low part of the screen. - -Screens sequence (user can navigate with <- and ->): - - (default) -[settings] <> [freq] <> [pulses view] <> [raw square view] <> [signal info] +- Decoders should declare the short pulse duration range, so that + only matching decoders will be called. This may also be useful for + modulations. If a signal is only OOK, does not make much sense to + call it for samples obtained in FSK. +- More protocols, especially TPMS and other stuff not supported right now + by the Flipper. +- CC1101 synchronous mode with protocol hopping? +- Protocols decoded can register actions, for instance to generate + sub files with modified signal and so forth. +- Optimize memory usage storing raw samples in a bitfield: 15 bits + duration, 1 bit level. diff --git a/applications/plugins/protoview/app.c b/applications/plugins/protoview/app.c index 4e6b2ff3e..ea4e366b8 100644 --- a/applications/plugins/protoview/app.c +++ b/applications/plugins/protoview/app.c @@ -89,6 +89,12 @@ static void app_switch_view(ProtoViewApp *app, SwitchViewDirection dir) { /* Call the enter/exit view callbacks if needed. */ if (old == ViewDirectSampling) view_exit_direct_sampling(app); if (new == ViewDirectSampling) view_enter_direct_sampling(app); + /* The frequency/modulation settings are actually a single view: + * as long as the user stays between the two modes of this view we + * don't need to call the exit-view callback. */ + if ((old == ViewFrequencySettings && new != ViewModulationSettings) || + (old == ViewModulationSettings && new != ViewFrequencySettings)) + view_exit_settings(app); } /* Allocate the application state and initialize a number of stuff. @@ -112,9 +118,11 @@ ProtoViewApp* protoview_app_alloc() { gui_add_view_port(app->gui, app->view_port, GuiLayerFullscreen); app->event_queue = furi_message_queue_alloc(8, sizeof(InputEvent)); app->current_view = ViewRawPulses; + app->direct_sampling_enabled = false; // Signal found and visualization defaults app->signal_bestlen = 0; + app->signal_last_scan_idx = 0; app->signal_decoded = false; app->us_scale = PROTOVIEW_RAW_VIEW_DEFAULT_SCALE; app->signal_offset = 0; @@ -123,20 +131,24 @@ ProtoViewApp* protoview_app_alloc() { app->txrx = malloc(sizeof(ProtoViewTxRx)); /* Setup rx worker and environment. */ + app->txrx->freq_mod_changed = false; + app->txrx->debug_timer_sampling = false; + app->txrx->last_g0_change_time = DWT->CYCCNT; + app->txrx->last_g0_value = false; app->txrx->worker = subghz_worker_alloc(); - #ifdef PROTOVIEW_DISABLE_SUBGHZ_FILTER app->txrx->worker->filter_running = 0; #endif - app->txrx->environment = subghz_environment_alloc(); subghz_environment_set_protocol_registry( app->txrx->environment, (void*)&protoview_protocol_registry); - app->txrx->receiver = subghz_receiver_alloc_init(app->txrx->environment); - - subghz_receiver_set_filter(app->txrx->receiver, SubGhzProtocolFlag_Decodable); + app->txrx->receiver = + subghz_receiver_alloc_init(app->txrx->environment); + subghz_receiver_set_filter(app->txrx->receiver, + SubGhzProtocolFlag_Decodable); subghz_worker_set_overrun_callback( - app->txrx->worker, (SubGhzWorkerOverrunCallback)subghz_receiver_reset); + app->txrx->worker, + (SubGhzWorkerOverrunCallback)subghz_receiver_reset); subghz_worker_set_pair_callback( app->txrx->worker, (SubGhzWorkerPairCallback)subghz_receiver_decode); subghz_worker_set_context(app->txrx->worker, app->txrx->receiver); @@ -171,9 +183,11 @@ void protoview_app_free(ProtoViewApp *app) { subghz_setting_free(app->setting); // Worker stuff. - subghz_receiver_free(app->txrx->receiver); - subghz_environment_free(app->txrx->environment); - subghz_worker_free(app->txrx->worker); + if (!app->txrx->debug_timer_sampling) { + subghz_receiver_free(app->txrx->receiver); + subghz_environment_free(app->txrx->environment); + subghz_worker_free(app->txrx->worker); + } free(app->txrx); // Raw samples buffers. @@ -189,6 +203,20 @@ void protoview_app_free(ProtoViewApp *app) { * function is to scan for signals and set DetectedSamples. */ static void timer_callback(void *ctx) { ProtoViewApp *app = ctx; + uint32_t delta, lastidx = app->signal_last_scan_idx; + + /* scan_for_signal(), called by this function, deals with a + * circular buffer. To never miss anything, even if a signal spawns + * cross-boundaries, it is enough if we scan each time the buffer fills + * for 50% more compared to the last scan. Thanks to this check we + * can avoid scanning too many times to just find the same data. */ + if (lastidx < RawSamples->idx) { + delta = RawSamples->idx - lastidx; + } else { + delta = RawSamples->total - lastidx + RawSamples->idx; + } + if (delta < RawSamples->total/2) return; + app->signal_last_scan_idx = RawSamples->idx; scan_for_signal(app); } @@ -198,7 +226,7 @@ int32_t protoview_app_entry(void* p) { /* Create a timer. We do data analysis in the callback. */ FuriTimer *timer = furi_timer_alloc(timer_callback, FuriTimerTypePeriodic, app); - furi_timer_start(timer, furi_kernel_get_tick_frequency() / 4); + furi_timer_start(timer, furi_kernel_get_tick_frequency() / 8); /* Start listening to signals immediately. */ radio_begin(app); diff --git a/applications/plugins/protoview/app.h b/applications/plugins/protoview/app.h index 4ad0a9196..71b06bf9a 100644 --- a/applications/plugins/protoview/app.h +++ b/applications/plugins/protoview/app.h @@ -65,10 +65,21 @@ extern ProtoViewModulation ProtoViewModulations[]; /* In app_subghz.c */ * It receives data and we get our protocol "feed" callback called * with the level (1 or 0) and duration. */ struct ProtoViewTxRx { + bool freq_mod_changed; /* The user changed frequency and/or modulation + from the interface. There is to restart the + radio with the right parameters. */ SubGhzWorker* worker; /* Our background worker. */ SubGhzEnvironment* environment; SubGhzReceiver* receiver; TxRxState txrx_state; /* Receiving, idle or sleeping? */ + + /* Timer sampling mode state. */ + bool debug_timer_sampling; /* Read data from GDO0 in a busy loop. Only + for testing. */ + uint32_t last_g0_change_time; /* Last high->low (or reverse) switch. */ + bool last_g0_value; /* Current value (high or low): we are + checking the duration in the timer + handler. */ }; typedef struct ProtoViewTxRx ProtoViewTxRx; @@ -85,6 +96,7 @@ typedef struct ProtoViewMsgInfo { char info1[PROTOVIEW_MSG_STR_LEN]; /* Protocol specific info line 1. */ char info2[PROTOVIEW_MSG_STR_LEN]; /* Protocol specific info line 2. */ char info3[PROTOVIEW_MSG_STR_LEN]; /* Protocol specific info line 3. */ + char info4[PROTOVIEW_MSG_STR_LEN]; /* Protocol specific info line 4. */ uint64_t len; /* Bits consumed from the stream. */ } ProtoViewMsgInfo; @@ -103,8 +115,12 @@ struct ProtoViewApp { /* Generic app state. */ int running; /* Once false exists the app. */ uint32_t signal_bestlen; /* Longest coherent signal observed so far. */ + uint32_t signal_last_scan_idx; /* Index of the buffer last time we + performed the scan. */ bool signal_decoded; /* Was the current signal decoded? */ ProtoViewMsgInfo signal_info; /* Decoded message, if signal_decoded true. */ + bool direct_sampling_enabled; /* This special view needs an explicit + acknowledge to work. */ /* Raw view apps state. */ uint32_t us_scale; /* microseconds per pixel. */ @@ -136,6 +152,8 @@ uint32_t radio_rx(ProtoViewApp* app); void radio_idle(ProtoViewApp* app); void radio_rx_end(ProtoViewApp* app); void radio_sleep(ProtoViewApp* app); +void raw_sampling_worker_start(ProtoViewApp *app); +void raw_sampling_worker_stop(ProtoViewApp *app); /* signal.c */ uint32_t duration_delta(uint32_t a, uint32_t b); @@ -148,6 +166,7 @@ void bitmap_invert_bytes_bits(uint8_t *p, uint32_t len); bool bitmap_match_bits(uint8_t *b, uint32_t blen, uint32_t bitpos, const char *bits); uint32_t bitmap_seek_bits(uint8_t *b, uint32_t blen, uint32_t startpos, uint32_t maxbits, const char *bits); uint32_t convert_from_line_code(uint8_t *buf, uint64_t buflen, uint8_t *bits, uint32_t len, uint32_t offset, const char *zero_pattern, const char *one_pattern); +uint32_t convert_from_diff_manchester(uint8_t *buf, uint64_t buflen, uint8_t *bits, uint32_t len, uint32_t off, bool previous); /* view_*.c */ void render_view_raw_pulses(Canvas *const canvas, ProtoViewApp *app); @@ -160,6 +179,10 @@ void render_view_direct_sampling(Canvas *const canvas, ProtoViewApp *app); void process_input_direct_sampling(ProtoViewApp *app, InputEvent input); void view_enter_direct_sampling(ProtoViewApp *app); void view_exit_direct_sampling(ProtoViewApp *app); +void view_exit_settings(ProtoViewApp *app); /* ui.c */ void canvas_draw_str_with_border(Canvas* canvas, uint8_t x, uint8_t y, const char* str, Color text_color, Color border_color); + +/* crc.c */ +uint8_t crc8(const uint8_t *data, size_t len, uint8_t init, uint8_t poly); diff --git a/applications/plugins/protoview/app_subghz.c b/applications/plugins/protoview/app_subghz.c index 2bb87af7a..30e0c817f 100644 --- a/applications/plugins/protoview/app_subghz.c +++ b/applications/plugins/protoview/app_subghz.c @@ -5,6 +5,12 @@ #include "custom_presets.h" #include +#include +#include +#include + +void raw_sampling_worker_start(ProtoViewApp *app); +void raw_sampling_worker_stop(ProtoViewApp *app); ProtoViewModulation ProtoViewModulations[] = { {"OOK 650Khz", FuriHalSubGhzPresetOok650Async, NULL}, @@ -15,6 +21,7 @@ ProtoViewModulation ProtoViewModulations[] = { {"GFSK", FuriHalSubGhzPresetGFSK9_99KbAsync, NULL}, {"TPMS 1 (FSK)", 0, (uint8_t*)protoview_subghz_tpms1_async_regs}, {"TPMS 2 (FSK)", 0, (uint8_t*)protoview_subghz_tpms2_async_regs}, + {"TPMS 3 (FSK)", 0, (uint8_t*)protoview_subghz_tpms3_async_regs}, {NULL, 0, NULL} /* End of list sentinel. */ }; @@ -53,9 +60,14 @@ uint32_t radio_rx(ProtoViewApp* app) { furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); furi_hal_subghz_flush_rx(); furi_hal_subghz_rx(); + if (!app->txrx->debug_timer_sampling) { - furi_hal_subghz_start_async_rx(subghz_worker_rx_callback, app->txrx->worker); - subghz_worker_start(app->txrx->worker); + furi_hal_subghz_start_async_rx(subghz_worker_rx_callback, + app->txrx->worker); + subghz_worker_start(app->txrx->worker); + } else { + raw_sampling_worker_start(app); + } app->txrx->txrx_state = TxRxStateRx; return value; } @@ -64,9 +76,13 @@ uint32_t radio_rx(ProtoViewApp* app) { void radio_rx_end(ProtoViewApp* app) { furi_assert(app); if (app->txrx->txrx_state == TxRxStateRx) { - if(subghz_worker_is_running(app->txrx->worker)) { - subghz_worker_stop(app->txrx->worker); - furi_hal_subghz_stop_async_rx(); + if (!app->txrx->debug_timer_sampling) { + if(subghz_worker_is_running(app->txrx->worker)) { + subghz_worker_stop(app->txrx->worker); + furi_hal_subghz_stop_async_rx(); + } + } else { + raw_sampling_worker_stop(app); } } furi_hal_subghz_idle(); @@ -84,3 +100,55 @@ void radio_sleep(ProtoViewApp* app) { furi_hal_subghz_sleep(); app->txrx->txrx_state = TxRxStateSleep; } + +/* ============================= Raw sampling mode ============================= + * This is a special mode that uses a high frequency timer to sample the + * CC1101 pin directly. It's useful for debugging purposes when we want + * to get the raw data from the chip and completely bypass the subghz + * Flipper system. + * ===========================================================================*/ + +void protoview_timer_isr(void *ctx) { + ProtoViewApp *app = ctx; + + bool level = furi_hal_gpio_read(&gpio_cc1101_g0); + if (app->txrx->last_g0_value != level) { + uint32_t now = DWT->CYCCNT; + uint32_t dur = now - app->txrx->last_g0_change_time; + dur /= furi_hal_cortex_instructions_per_microsecond(); + if (dur > 15000) dur = 15000; + raw_samples_add(RawSamples, app->txrx->last_g0_value, dur); + app->txrx->last_g0_value = level; + app->txrx->last_g0_change_time = now; + } + LL_TIM_ClearFlag_UPDATE(TIM2); +} + +void raw_sampling_worker_start(ProtoViewApp *app) { + UNUSED(app); + + LL_TIM_InitTypeDef tim_init = { + .Prescaler = 63, /* CPU frequency is ~64Mhz. */ + .CounterMode = LL_TIM_COUNTERMODE_UP, + .Autoreload = 5, /* Sample every 5 us */ + }; + + LL_TIM_Init(TIM2, &tim_init); + LL_TIM_SetClockSource(TIM2, LL_TIM_CLOCKSOURCE_INTERNAL); + LL_TIM_DisableCounter(TIM2); + LL_TIM_SetCounter(TIM2, 0); + furi_hal_interrupt_set_isr(FuriHalInterruptIdTIM2, protoview_timer_isr, app); + LL_TIM_EnableIT_UPDATE(TIM2); + LL_TIM_EnableCounter(TIM2); + FURI_LOG_E(TAG, "Timer enabled"); +} + +void raw_sampling_worker_stop(ProtoViewApp *app) { + UNUSED(app); + FURI_CRITICAL_ENTER(); + LL_TIM_DisableCounter(TIM2); + LL_TIM_DisableIT_UPDATE(TIM2); + furi_hal_interrupt_set_isr(FuriHalInterruptIdTIM2, NULL, NULL); + LL_TIM_DeInit(TIM2); + FURI_CRITICAL_EXIT(); +} diff --git a/applications/plugins/protoview/application.fam b/applications/plugins/protoview/application.fam index df2a77261..6cd31372e 100644 --- a/applications/plugins/protoview/application.fam +++ b/applications/plugins/protoview/application.fam @@ -1,6 +1,6 @@ App( appid="protoview", - name="Protocols visualizer", + name="ProtoView", apptype=FlipperAppType.EXTERNAL, entry_point="protoview_app_entry", cdefines=["APP_PROTOVIEW"], diff --git a/applications/plugins/protoview/binaries/protoview.fap b/applications/plugins/protoview/binaries/protoview.fap index f5a03056e172efab800adfb989d987ce2e3b849e..696dc523ef6e43d610df9cfaf14e5264774c7da2 100644 GIT binary patch literal 28520 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 R5&C@QHuz926Hv?d{{cGVrR4ws delta 10526 zcmaJ`eOwgRxjr+yz=DvVpdcU&y9kS@SphA6HTX3kXo4TL#F}(%jahE}AZlA;XqL97 z*Cw_XGnm*`TN=qNX_6a^+G=~P^v3p@)}(7<8%#{(*Cbv1#dslVGD&Q5pJ(PQtn){Y z&OYZk?>pzb=RNQFn8U!EO5YPodv?mqn}wAk4F|msc@}jx2;U24S3uETj|#21Mrf}_ zZ3Q7ZVj193JiU^i0-ncnN%E%;?M^LGW{gh}VsWw%6~GcaE0B+WmZGc%&pau+gP3Am zPJ1(aUDl*2Le%1Ez{AuCOtrIO8}f7TwBy-_hp88M7SDj>_e@gy*o!F_2Nz6vPks0Y zJqh|vdY(R~UKkm=@Xo&dXibvdGxXW5p~wX@eRoyeVqMiPgw51%_twm)cN;V6U555K z^)cm9u_xIpe97Gvi+9!}=q|n7Qthp&nZhRO`uCeffgDx6TD@hzIWbtiz;ii$($UMc z4}Eaiv)zBW!I>chte2EQv#2-R|uC<3m;(-oCr|-gmYtWT^(@hzo z6k4ND?&=vl&U`ZRW|TP(a#x}kOszK&Ipf}OdExVD$#X;j^&F?6%}4sRN;K)#E79f3 z`s`qLO$B}{pb=bKv6xs5(pMIl>nQAzNX^EjiF-Xi<_E56M;P_Qw#To ze8~Hne2cSX&WoJaD*I6=J5-2Vut~%3NwZJvFwZySBd_=ltkv{pt8?t2n?Ev{s>jY{ zyNuoADvZu?zHsvq;jf6e^<2Cw3WK2>AiFaj7_@%J*D~L4<%Q1|3^rwf`S6sd)W4-xhb- zt7l;6ma|dc_KagLX8X3Bj=G=9xR@w3oxc9VFr$}$H_YhOUn6Gr_7))LYs$S} zDf2}9`UEgd&%>|K+&#_5bL-L;t6G{>O8;o8o^AX-+m~O79yH>KPjve|>({Se=Ry$X z+_WuDd|o|NKK^mVSeToxo(~wSa(&8HV|%Vw$%blHc%S7D;lBk#6u~fC!{nbFu??FX z$wt#>QO+UZiZQM(3ua}(^}?5RV0I`8 zzrsHVo3ld+$n&`v6(`Wa%sf^UtAxHzj&QCb{!xjMo}agz3ic+^T;n;Cs;LmG^{yc1 zuN6dXjPQe$T`*I7IkWBZl_>WdydMiQC7xbE3DQcp@tgd774TYq@ghs>h<4DUyBE8m z;ep+my)LVk4RLdadOPPU=c;p1AD;9h!uR~zUh{0A&D4xV1=Eye#y1P5l+{L3hLn`# zAtia#wU4*fFRDK0dMa&bl)6|~_TIXrv&Qwa3AfBR_v>rhH&+;cDX2)}YSHuV-)>f3 zQ7Ze5v0908*qEz*Zxk(+>A+b{UEn#=?G=S1>lQYf+aJV6lc~R9R<+%JwXNZT>EC?{ z8%@GBvEmgowMsGEm7-(wpyHaOL%yuaFnndoRO5s%tE{xH6j4$Nd;EGSELf^9(M7*f zSyI0OJIs}X7tHRSzMAjo7tCFTQsfKg)QyAw1+%gJRE?POdgRVyS#_gP!l_)P^VhE@ z^k4({56_V1@(fk0o}r-P8EO-*c6GP%h%grDqv{gyMgrP=XE>;O;MG%cUhYDd&w^jV z<4%Y(;nDx9MWyy#8vP3vl8!vHCUBeY8{$=u^R8G)0?N z7ruZ#8C&YN^*=%ONz;M(?pGc&wSXwAIMaTp+dEHB8uE)G=wDy^@21v%!R&0Grk^u~ z;A&W^7ctA32MoBRe}&=G$JdRw{IU&xF}6?4bEWy8HGVX4cA_7~pK>F>#~FhY5iP@A z5n}Mj&wJeZZZyB(P?|0Z3ot(uhWsuM##hrP3~zUP%-X=H-;OCs7z(*&K~K}i8K0FD z7?b^Zvy$uD3PZXFZ+=Z5W4(8@Ca)xdITdTD5e96K9{f&^`jiU`pW4%0V|4oSl!$TM zA63p8Pn6D8G~=z(DeATaW6Y$_7n}{O^Yvo4dM_G5WGfYn@2H)hjl8jW(%5h$P+pdG zuH2ha_VT%(}ELO-9-tbF;6B2O1yQR5f^Uk@#ifxB^L)Vd?gCe3 z-SV*M3kU;CexSUr9KlzP9>8(1OtWTy{mUJyy6F~_@@yb{I2{DeN2{AAqa+dY<;eWx zmrM0v6DL3G`tJNO5oP+7s3<%#zaPz~2EKYsnRf7#53VGBk}*2i#J!L;{U*A)RDUn3 zl)ZE&`PjYr??;uHgVA;q2Xi0Rj|$kRj#|9T^lD<#hi6cYHtU!Y==tQz`>s#MxM;+W zqspY7GoEA0><^<0@~_F5I0}ypCSYU9Pto9@g?K{3xNXY&hvo#_O5wD?zxo%LCX8iM zD-wZXTEO_>wAGK4`;ENHJ|lg4bxOmQ&D%DwYP$QIsBgNSs;{Wm)^FaTt!!Aj!swkI zNa7-|h_9gSQbU{Zb=RFj7(btJi}CR1?l9a{OTxQg3zMnX$TO^!@LnvNYSm#EXCu!Y zi^-2X{#&UEnb^3`K|WEIFO&)`lE*+z8XNpe|Db{IdHm8({|j9<>0uU;3%Mt9GvG>JK6ncbjU+-9Q7N&ottJwP}_~=VrLv@mHXm2 z?dp!>l=nLL$QjzUBjS(`jPS5EfSstsPWH;u64w!C+Z?<-j?*A>q(aM)?y<5uFsc^C zaq0(#xs0HlTt%#84`7Fb|INY8IL-zFS@Lx>$ObCoIOW^oIOQ!d&gIDJ43|GE*%f%= zIORLzI4kIgl=tg;l=!h$zolj3N z?wXe$jvdvwZ?m`||HgX#1vhdYR_tW!uW`uNXfe4WrpK~CuAPe<{4Rlyn^>a4*YFUz z!H!lF!~?)sV)<@7$r!+0z%i;Kx?@5hwt>DkV(Opu1k3;_;_?_^WAISPn@f2_`mU+%w z7Q7BV4}?)l?vneh-9VDa7~X&F9+x`!Ob4%b@a5o7;PJ}(!*@9pz6GuzHe02_kHGi9 z8hV2UJ>$^lCFb{GuqNfNgFlFeVMP4_u$;9_dz}xUJKRT?s#5{+>a`2gODT~>_0}lBC@NZ#= zx}^LtxB~qu$$K68Z-H~8&>$a;_7aAtFy70B7xj06#}ez?H^Re~8=e{|u=sHYe+8UJ_3d&<`oZHHyzJ0d z@qMuf22aL2G$1qfy#Y=GO2O?}fc1w8(^0^^)?O%FVwvNGkb}2^j|7n-9(2g}fXBzs zPr=9IFttt^^lVJu7^=$(p9A{{0~qtyKujvlO~t1HjI*B6YLdtT{}yW7CTsJ7KY=;A zP>#nm@c3nLE_f`l`?uZ5!{Vzb;EEH(!)2`HMg_6Q!Jh=5hNHte*+!?#hdfKH1oGTk>Q z2=Tmw_c{1Q@H2598H?%Mh59%e9D#gJZ<$#3LVQRWdm5^YHyYL$^~-|B$z`R+=ayF+ zfB#~x@$~W)M%s#Zl#RymFZkW-x7>ZVp|AXlk@JO*jq+91#sjM!JyiU~sfw|wvDp}E z%rT1ZIBle@&N8Z3e|G5hFWs*gjmy)GFRw~4K3LObJagx(ja$F|m3ukw}tx&k$m!B0R)?^qlw{ zB9r*P=sEEttggfkoNS0NoR>f9ui-hYL+Z2G9f{}gJ`oF1y2MQ4CwM>13|`D5_F*xR zyoiXk-A~L@#AIS2z7~m(<13MfLt+&XgFc6NR)}iiuQ2C{Z^EO*-@&8A^Ei+Y_hHc_ zev0vLWTrq7YluT|DRBZ0iNqtgS0yGZVgvCgTuM~nQsN)&+bH!EF8;{>idZ6E65=|M zUk^C-u!C;mlkf=fpYRCr|1kdP%)ADd5{nQ_#7E%~;zUJgM7XYqcmf`gd@}JL@CXq@ zP)S5XEm$d3k0M%$6NP9azK=^j;?tP3#CI`gi31q_c4jgZ(LqE7dnN88A}BkFg^K7R z9>x_05eD@Tp?{e8b4+968LZ#L1K5X%Fzh7p5!_7?6BTiqi1#AIaDpPvG6NU(Nx>ko z8!jcn1H3ik?cyBb+ZbbF7KVuUEQW}95`VuT{?xt{qy9;$$4fBsOd{Unofr8wU|9Vn zTqXs)+)}T=GNJ~>49_9BYa$ZNN{|SSM z80*PIRLEN>#>Ot>^^TYL^O~L{!Mz z9`$2HH4zo{5@Fy;iKmDd!qY_bI6_3soR#uEiRUHu6XD6XiPtgyydB~ad5VahoF@Jq zK}dw+S>k^o2#H+?LgGaPArZm*Hj$o_c!@X&&k;|+b3_SzR??F|?_-|td zYkmuHFIJ{JAlCeJB6ubd4P;BqBfgAsEWdm&n+R9t5yxP`A|As%8xaleC0;|&5>Zbl z5$|^q!)U0RnP;#@=L5$oB2WNCc_k4qR1smw9LcLCE+pc;TH-;xPy8){RmxWq(NH7t zJt5X;HU^2PcOB5$|3fT*OEwS@_07Zqc!r3Tv4w~=zm@nFmQ>hd>*Y3e+>T +#include + +/* CRC8 with the specified initialization value 'init' and + * polynomial 'poly'. */ +uint8_t crc8(const uint8_t *data, size_t len, uint8_t init, uint8_t poly) +{ + uint8_t crc = init; + size_t i, j; + for (i = 0; i < len; i++) { + crc ^= data[i]; + for (j = 0; j < 8; j++) { + if ((crc & 0x80) != 0) + crc = (uint8_t)((crc << 1) ^ poly); + else + crc <<= 1; + } + } + return crc; +} diff --git a/applications/plugins/protoview/custom_presets.h b/applications/plugins/protoview/custom_presets.h index d34446f48..38fca0e31 100644 --- a/applications/plugins/protoview/custom_presets.h +++ b/applications/plugins/protoview/custom_presets.h @@ -11,7 +11,7 @@ * * ((256+MDMCFG3)*(2^MDMCFG4:0..3bits)) / 2^28 * 26000000. * - * For instance for the default values of MDMCFG3 (34) and MDMCFG4 (12): + * For instance for the default values of MDMCFG3[0..3] (34) and MDMCFG4 (12): * * ((256+34)*(2^12))/(2^28)*26000000 = 115051.2688000000, that is 115KBaud * @@ -38,6 +38,23 @@ * d 82 khz * e 68 khz * f 58 khz + * + * FSK deviation is controlled by the DEVIATION register. In Ruby: + * + * dev = (26000000.0/2**17)*(8+(deviation&7))*(2**(deviation>>4&7)) + * + * deviation&7 (last three bits) is the deviation mantissa, while + * deviation>>4&7 (bits 6,5,4) are the exponent. + * + * Deviations values according to certain configuration of DEVIATION: + * + * 0x04 -> 2.380371 kHz + * 0x24 -> 9.521484 kHz + * 0x34 -> 19.042969 Khz + * 0x40 -> 25.390625 Khz + * 0x43 -> 34.912109 Khz + * 0x45 -> 41.259765 Khz + * 0x47 -> 47.607422 kHz */ /* 20 KBaud, 2FSK, 28.56 kHz deviation, 325 Khz bandwidth filter. */ @@ -130,3 +147,46 @@ static uint8_t protoview_subghz_tpms2_async_regs[][2] = { {0, 0}, }; +/* Parameters that should work well for the TPMS PVM C210 sensor. */ +static uint8_t protoview_subghz_tpms3_async_regs[][2] = { + /* GPIO GD0 */ + {CC1101_IOCFG0, 0x0D}, // GD0 as async serial data output/input + + /* Frequency Synthesizer Control */ + {CC1101_FSCTRL1, 0x06}, // IF = (26*10^6) / (2^10) * 0x06 = 152343.75Hz + + /* Packet engine */ + {CC1101_PKTCTRL0, 0x32}, // Async, continious, no whitening + {CC1101_PKTCTRL1, 0x04}, + + // // Modem Configuration + {CC1101_MDMCFG0, 0x00}, + {CC1101_MDMCFG1, 0x02}, // 2 is the channel spacing exponet: not used + {CC1101_MDMCFG2, 0x10}, // GFSK without any other check + {CC1101_MDMCFG3, 0x93}, // Data rate is 20kBaud + {CC1101_MDMCFG4, 0x59}, // Rx bandwidth filter is 325 kHz + {CC1101_DEVIATN, 0x34}, // Deviation 19.04 Khz, works well with TPMS + + /* Main Radio Control State Machine */ + {CC1101_MCSM0, 0x18}, // Autocalibrate on idle-to-rx/tx, PO_TIMEOUT is 64 cycles(149-155us) + + /* Frequency Offset Compensation Configuration */ + {CC1101_FOCCFG, + 0x16}, // no frequency offset compensation, POST_K same as PRE_K, PRE_K is 4K, GATE is off + + /* Automatic Gain Control */ + {CC1101_AGCCTRL0, 0x80}, + {CC1101_AGCCTRL1, 0x58}, + {CC1101_AGCCTRL2, 0x87}, + + /* Wake on radio and timeouts control */ + {CC1101_WORCTRL, 0xFB}, // WOR_RES is 2^15 periods (0.91 - 0.94 s) 16.5 - 17.2 hours + + /* Frontend configuration */ + {CC1101_FREND0, 0x10}, // Adjusts current TX LO buffer + {CC1101_FREND1, 0x56}, + + /* End */ + {0, 0}, +}; + diff --git a/applications/plugins/protoview/proto.c b/applications/plugins/protoview/data_feed.c similarity index 100% rename from applications/plugins/protoview/proto.c rename to applications/plugins/protoview/data_feed.c diff --git a/applications/plugins/protoview/images/protoview_1.jpg b/applications/plugins/protoview/images/protoview_1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..10d9d6ec551f678fb8064ae8310dabd64d69b9c1 GIT binary patch literal 66885 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 a#@^hs?BdY5iuF7vE49l|^XuYYZ~hy2+QilX literal 0 HcmV?d00001 diff --git a/applications/plugins/protoview/images/protoview_2.jpg b/applications/plugins/protoview/images/protoview_2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2560297707d0d2a38e5f4e5a4cf64ee4f0ab64ec GIT binary patch literal 64574 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 literal 0 HcmV?d00001 diff --git a/applications/plugins/protoview/protocols/b4b1.c b/applications/plugins/protoview/protocols/b4b1.c index 6977c0eb3..2bed2ac32 100644 --- a/applications/plugins/protoview/protocols/b4b1.c +++ b/applications/plugins/protoview/protocols/b4b1.c @@ -1,7 +1,7 @@ /* PT/SC remotes. Usually 443.92 Mhz OOK. * * This line code is used in many remotes such as Princeton chips - * named PT, Silian Microelectronics SC5262 and others. + * named PT2262, Silian Microelectronics SC5262 and others. * Basically every 4 pulsee represent a bit, where 1000 means 0, and * 1110 means 1. Usually we can read 24 bits of data. * In this specific implementation we check for a prelude that is diff --git a/applications/plugins/protoview/protocols/citroen_tpms.c b/applications/plugins/protoview/protocols/citroen_tpms.c new file mode 100644 index 000000000..14d824e50 --- /dev/null +++ b/applications/plugins/protoview/protocols/citroen_tpms.c @@ -0,0 +1,60 @@ +/* Citroen TPMS. Usually 443.92 Mhz FSK. + * + * Preamble of ~14 high/low 52 us pulses + * Sync of high 100us pulse then 50us low + * Then Manchester bits, 10 bytes total. + * Simple XOR checksum. */ + +#include "../app.h" + +static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo *info) { + + /* We consider a preamble of 17 symbols. They are more, but the decoding + * is more likely to happen if we don't pretend to receive from the + * very start of the message. */ + uint32_t sync_len = 17; + const char *sync_pattern = "10101010101010110"; + if (numbits-sync_len < 8*10) return false; /* Expect 10 bytes. */ + + uint64_t off = bitmap_seek_bits(bits,numbytes,0,numbits,sync_pattern); + if (off == BITMAP_SEEK_NOT_FOUND) return false; + FURI_LOG_E(TAG, "Renault TPMS preamble+sync found"); + + off += sync_len; /* Skip preamble + sync. */ + + uint8_t raw[10]; + uint32_t decoded = + convert_from_line_code(raw,sizeof(raw),bits,numbytes,off, + "01","10"); /* Manchester. */ + FURI_LOG_E(TAG, "Citroen TPMS decoded bits: %lu", decoded); + + if (decoded < 8*10) return false; /* Require the full 10 bytes. */ + + /* Check the CRC. It's a simple XOR of bytes 1-9, the first byte + * is not included. The meaning of the first byte is unknown and + * we don't display it. */ + uint8_t crc = 0; + for (int j = 1; j < 10; j++) crc ^= raw[j]; + if (crc != 0) return false; /* Require sane checksum. */ + + int repeat = raw[5] & 0xf; + float kpa = (float)raw[6]*1.364; + int temp = raw[7]-50; + int battery = raw[8]; /* This may be the battery. It's not clear. */ + + snprintf(info->name,sizeof(info->name),"%s","Citroen TPMS"); + snprintf(info->raw,sizeof(info->raw), + "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", + raw[0],raw[1],raw[2],raw[3],raw[4],raw[5], + raw[6],raw[7],raw[8],raw[9]); + snprintf(info->info1,sizeof(info->info1),"Tire ID %02X%02X%02X%02X", + raw[1],raw[2],raw[3],raw[4]); + snprintf(info->info2,sizeof(info->info2),"Pressure %.2f kpa", (double)kpa); + snprintf(info->info3,sizeof(info->info3),"Temperature %d C", temp); + snprintf(info->info4,sizeof(info->info4),"Repeat %d, Bat %d", repeat, battery); + return true; +} + +ProtoViewDecoder CitroenTPMSDecoder = { + "Citroen TPMS", decode +}; diff --git a/applications/plugins/protoview/protocols/ford_tpms.c b/applications/plugins/protoview/protocols/ford_tpms.c new file mode 100644 index 000000000..2cab0ea91 --- /dev/null +++ b/applications/plugins/protoview/protocols/ford_tpms.c @@ -0,0 +1,64 @@ +/* Ford tires TPMS. Usually 443.92 Mhz FSK (in Europe). + * + * 52 us short pules + * Preamble: 0101010101010101010101010101 + * Sync: 0110 (that is 52 us gap + 104 us pulse + 52 us gap) + * Data: 8 bytes Manchester encoded + * 01 = zero + * 10 = one + */ + +#include "../app.h" + +static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo *info) { + + const char *sync_pattern = "010101010101" "0110"; + uint8_t sync_len = 12+4; /* We just use 12 preamble symbols + sync. */ + if (numbits-sync_len < 8*8) return false; + + uint64_t off = bitmap_seek_bits(bits,numbytes,0,numbits,sync_pattern); + if (off == BITMAP_SEEK_NOT_FOUND) return false; + FURI_LOG_E(TAG, "Fort TPMS preamble+sync found"); + + off += sync_len; /* Skip preamble and sync. */ + + uint8_t raw[8]; + uint32_t decoded = + convert_from_line_code(raw,sizeof(raw),bits,numbytes,off, + "01","10"); /* Manchester. */ + FURI_LOG_E(TAG, "Ford TPMS decoded bits: %lu", decoded); + + if (decoded < 8*8) return false; /* Require the full 8 bytes. */ + + /* CRC is just the sum of the first 7 bytes MOD 256. */ + uint8_t crc = 0; + for (int j = 0; j < 7; j++) crc += raw[j]; + if (crc != raw[7]) return false; /* Require sane CRC. */ + + float psi = 0.25 * (((raw[6]&0x20)<<3)|raw[4]); + + /* Temperature apperas to be valid only if the most significant + * bit of the value is not set. Otherwise its meaning is unknown. + * Likely useful to alternatively send temperature or other info. */ + int temp = raw[5] & 0x80 ? 0 : raw[5]-56; + int flags = raw[5] & 0x7f; + int car_moving = (raw[6] & 0x44) == 0x44; + + snprintf(info->name,sizeof(info->name),"%s","Ford TPMS"); + snprintf(info->raw,sizeof(info->raw),"%02X%02X%02X%02X%02X%02X%02X%02X", + raw[0],raw[1],raw[2],raw[3],raw[4],raw[5], + raw[6],raw[7]); + snprintf(info->info1,sizeof(info->info1),"Tire ID %02X%02X%02X%02X", + raw[0],raw[1],raw[2],raw[3]); + snprintf(info->info2,sizeof(info->info2),"Pressure %.2f psi", (double)psi); + if (temp) + snprintf(info->info3,sizeof(info->info3),"Temperature %d C", temp); + else + snprintf(info->info3,sizeof(info->info3),"Flags %d", flags); + snprintf(info->info4,sizeof(info->info4),"Moving %s", car_moving ? "yes" : "no"); + return true; +} + +ProtoViewDecoder FordTPMSDecoder = { + "Ford TPMS", decode +}; diff --git a/applications/plugins/protoview/protocols/renault_tpms.c b/applications/plugins/protoview/protocols/renault_tpms.c index 3022a5d4e..1f8ea0711 100644 --- a/applications/plugins/protoview/protocols/renault_tpms.c +++ b/applications/plugins/protoview/protocols/renault_tpms.c @@ -1,16 +1,16 @@ /* Renault tires TPMS. Usually 443.92 Mhz FSK. * - * Preamble + marshal-encoded bits. 9 Bytes in total if we don't - * count the preamble. */ + * Preamble + sync + Manchester bits. ~48us short pulse. + * 9 Bytes in total not counting the preamble. */ #include "../app.h" #define USE_TEST_VECTOR 0 static const char *test_vector = - "10101010" "10101010" "10101010" "10101001" // Preamble + sync. + "...01010101010101010110" // Preamble + sync - /* The following is marshal encoded, so each two characters are - * actaully one bit. 01 = 1, 10 = 0. */ + /* The following is Marshal encoded, so each two characters are + * actaully one bit. 01 = 0, 10 = 1. */ "010110010110" // Flags. "10011001101010011001" // Pressure, multiply by 0.75 to obtain kpa. // 244 kpa here. @@ -29,22 +29,23 @@ static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoView numbits = strlen(test_vector); } - if (numbits < 13*8) return false; + if (numbits-12 < 9*8) return false; - const char *sync_pattern = "10101010" "10101010" "10101010" "10101001"; + const char *sync_pattern = "01010101010101010110"; uint64_t off = bitmap_seek_bits(bits,numbytes,0,numbits,sync_pattern); if (off == BITMAP_SEEK_NOT_FOUND) return false; FURI_LOG_E(TAG, "Renault TPMS preamble+sync found"); - off += 32; /* Skip preamble. */ + off += 20; /* Skip preamble. */ uint8_t raw[9]; uint32_t decoded = convert_from_line_code(raw,sizeof(raw),bits,numbytes,off, - "10","01"); /* Manchester. */ + "01","10"); /* Manchester. */ FURI_LOG_E(TAG, "Renault TPMS decoded bits: %lu", decoded); if (decoded < 8*9) return false; /* Require the full 9 bytes. */ + if (crc8(raw,8,0,7) != raw[8]) return false; /* Require sane CRC. */ float kpa = 0.75 *((uint32_t)((raw[0]&3)<<8) | raw[1]); int temp = raw[2]-30; @@ -53,8 +54,10 @@ static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoView snprintf(info->raw,sizeof(info->raw),"%02X%02X%02X%02X%02X%02X%02X%02X%02X", raw[0],raw[1],raw[2],raw[3],raw[4],raw[5], raw[6],raw[7],raw[8]); - snprintf(info->info1,sizeof(info->info1),"Pressure %.2f kpa", (double)kpa); - snprintf(info->info2,sizeof(info->info2),"Temperature %d C", temp); + snprintf(info->info1,sizeof(info->info1),"Tire ID %02X%02X%02X", + raw[3],raw[4],raw[5]); + snprintf(info->info2,sizeof(info->info2),"Pressure %.2f kpa", (double)kpa); + snprintf(info->info3,sizeof(info->info3),"Temperature %d C", temp); return true; } diff --git a/applications/plugins/protoview/protocols/schrader_tpms.c b/applications/plugins/protoview/protocols/schrader_tpms.c new file mode 100644 index 000000000..ebf3d6004 --- /dev/null +++ b/applications/plugins/protoview/protocols/schrader_tpms.c @@ -0,0 +1,65 @@ +/* Schrader TPMS. Usually 443.92 Mhz OOK, 120us pulse len. + * + * 500us high pulse + Preamble + Manchester coded bits where: + * 1 = 10 + * 0 = 01 + * + * 60 bits of data total (first 4 nibbles is the preamble, 0xF). + * + * Used in FIAT-Chrysler, Mercedes, ... */ + +#include "../app.h" + +#define USE_TEST_VECTOR 0 +static const char *test_vector = "000000111101010101011010010110010110101001010110100110011001100101010101011010100110100110011010101010101010101010101010101010101010101010101010"; + +static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo *info) { + + if (USE_TEST_VECTOR) { /* Test vector to check that decoding works. */ + bitmap_set_pattern(bits,numbytes,test_vector); + numbits = strlen(test_vector); + } + + if (numbits < 64) return false; /* Preamble + data. */ + + const char *sync_pattern = "1111010101" "01011010"; + uint64_t off = bitmap_seek_bits(bits,numbytes,0,numbits,sync_pattern); + if (off == BITMAP_SEEK_NOT_FOUND) return false; + FURI_LOG_E(TAG, "Schrader TPMS gap+preamble found"); + + off += 10; /* Skip just the long pulse and the first 3 bits of sync, so + that we have the first byte of data with the sync nibble + 0011 = 0x3. */ + + uint8_t raw[8]; + uint32_t decoded = + convert_from_line_code(raw,sizeof(raw),bits,numbytes,off, + "01","10"); /* Manchester code. */ + FURI_LOG_E(TAG, "Schrader TPMS decoded bits: %lu", decoded); + + if (decoded < 64) return false; /* Require the full 8 bytes. */ + + raw[0] |= 0xf0; // Fix the preamble nibble for checksum computation. + uint8_t cksum = crc8(raw,sizeof(raw)-1,0xf0,0x7); + if (cksum != raw[7]) { + FURI_LOG_E(TAG, "Schrader TPMS checksum mismatch"); + return false; + } + + float kpa = (float)raw[5]*2.5; + int temp = raw[6]-50; + + snprintf(info->name,sizeof(info->name),"%s","Schrader TPMS"); + snprintf(info->raw,sizeof(info->raw),"%02X%02X%02X%02X%02X%02X%02X%02X", + raw[0],raw[1],raw[2],raw[3],raw[4],raw[5], + raw[6],raw[7]); + snprintf(info->info1,sizeof(info->info1),"Tire ID %01X%02X%02X%02X", + raw[1]&7,raw[2],raw[3],raw[4]); /* Only 28 bits of ID, not 32. */ + snprintf(info->info2,sizeof(info->info2),"Pressure %.2f kpa", (double)kpa); + snprintf(info->info3,sizeof(info->info3),"Temperature %d C", temp); + return true; +} + +ProtoViewDecoder SchraderTPMSDecoder = { + "Schrader TPMS", decode +}; diff --git a/applications/plugins/protoview/protocols/toyota_tpms.c b/applications/plugins/protoview/protocols/toyota_tpms.c new file mode 100644 index 000000000..b870c2f33 --- /dev/null +++ b/applications/plugins/protoview/protocols/toyota_tpms.c @@ -0,0 +1,77 @@ +/* Toyota tires TPMS. Usually 443.92 Mhz FSK (In Europe). + * + * Preamble + sync + 64 bits of data. ~48us short pulse length. + * + * The preamble + sync is something like: + * + * 10101010101 (preamble) + 001111[1] (sync) + * + * Note: the final [1] means that sometimes it is four 1s, sometimes + * five, depending on the short pulse length detection and the exact + * duration of the high long pulse. After the sync, a differential + * Manchester encoded payload follows. However the Flipper's CC1101 + * often can't decode correctly the initial alternating pattern 101010101, + * so what we do is to seek just the sync, that is "001111" or "0011111", + * however we now that it must be followed by one differenitally encoded + * bit, so we can use also the first bit of data to force a more robust + * detection, and look for one of the following: + * + * [001111]00 + * [0011111]00 + * [001111]01 + * [0011111]01 + */ + +#include "../app.h" + +static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo *info) { + + if (numbits-6 < 64*2) return false; /* Ask for 64 bit of data (each bit + is two symbols in the bitmap). */ + + char *sync[] = { + "00111100", + "001111100", + "00111101", + "001111101", + NULL + }; + + int j; + uint32_t off = 0; + for (j = 0; sync[j]; j++) { + off = bitmap_seek_bits(bits,numbytes,0,numbits,sync[j]); + if (off != BITMAP_SEEK_NOT_FOUND) { + off += strlen(sync[j])-2; + break; + } + } + if (off == BITMAP_SEEK_NOT_FOUND) return false; + + FURI_LOG_E(TAG, "Toyota TPMS sync[%s] found", sync[j]); + + uint8_t raw[9]; + uint32_t decoded = + convert_from_diff_manchester(raw,sizeof(raw),bits,numbytes,off,true); + FURI_LOG_E(TAG, "Toyota TPMS decoded bits: %lu", decoded); + + if (decoded < 8*9) return false; /* Require the full 8 bytes. */ + if (crc8(raw,8,0x80,7) != raw[8]) return false; /* Require sane CRC. */ + + float kpa = (float)((raw[4]&0x7f)<<1 | raw[5]>>7) * 0.25 - 7; + int temp = ((raw[5]&0x7f)<<1 | raw[6]>>7) - 40; + + snprintf(info->name,sizeof(info->name),"%s","Toyota TPMS"); + snprintf(info->raw,sizeof(info->raw),"%02X%02X%02X%02X%02X%02X%02X%02X%02X", + raw[0],raw[1],raw[2],raw[3],raw[4],raw[5], + raw[6],raw[7],raw[8]); + snprintf(info->info1,sizeof(info->info1),"Tire ID %02X%02X%02X%02X", + raw[0],raw[1],raw[2],raw[3]); + snprintf(info->info1,sizeof(info->info1),"Pressure %.2f psi", (double)kpa); + snprintf(info->info2,sizeof(info->info2),"Temperature %d C", temp); + return true; +} + +ProtoViewDecoder ToyotaTPMSDecoder = { + "Toyota TPMS", decode +}; diff --git a/applications/plugins/protoview/signal.c b/applications/plugins/protoview/signal.c index 2ff632811..5a1c6c99b 100644 --- a/applications/plugins/protoview/signal.c +++ b/applications/plugins/protoview/signal.c @@ -53,6 +53,7 @@ uint32_t search_coherent_signal(RawSamplesBuffer *s, uint32_t idx) { bool level; uint32_t dur; raw_samples_get(s, j, &level, &dur); + if (dur < minlen || dur > maxlen) break; /* return. */ /* Let's see if it matches a class we already have or if we @@ -70,7 +71,7 @@ uint32_t search_coherent_signal(RawSamplesBuffer *s, uint32_t idx) { /* Is the difference in duration between this signal and * the class we are inspecting less than a given percentage? * If so, accept this signal. */ - if (delta < classavg/8) { /* 100%/8 = 12%. */ + if (delta < classavg/5) { /* 100%/5 = 20%. */ /* It is useful to compute the average of the class * we are observing. We know how many samples we got so * far, so we can recompute the average easily. @@ -130,9 +131,9 @@ void scan_for_signal(ProtoViewApp *app) { /* Try to seek on data that looks to have a regular high low high low * pattern. */ - uint32_t minlen = 13; /* Min run of coherent samples. Up to - 12 samples it's very easy to mistake - noise for signal. */ + uint32_t minlen = 18; /* Min run of coherent samples. With less + than a few samples it's very easy to + mistake noise for signal. */ ProtoViewMsgInfo *info = malloc(sizeof(ProtoViewMsgInfo)); uint32_t i = 0; @@ -152,18 +153,25 @@ void scan_for_signal(ProtoViewApp *app) { the signal in the loop. */ /* Accept this signal as the new signal if either it's longer - * than the previous one, or the previous one was unknown and - * this is decoded. */ - if (thislen > app->signal_bestlen || - (app->signal_decoded == false && decoded)) + * than the previous undecoded one, or the previous one was + * unknown and this is decoded. */ + if ((thislen > app->signal_bestlen && app->signal_decoded == false) + || (app->signal_decoded == false && decoded)) { app->signal_info = *info; app->signal_bestlen = thislen; app->signal_decoded = decoded; raw_samples_copy(DetectedSamples,copy); raw_samples_center(DetectedSamples,i); - FURI_LOG_E(TAG, "Displayed sample updated (%d samples %lu us)", + FURI_LOG_E(TAG, "===> Displayed sample updated (%d samples %lu us)", (int)thislen, DetectedSamples->short_pulse_dur); + + /* Adjust raw view scale if the signal has an high + * data rate. */ + if (DetectedSamples->short_pulse_dur < 75) + app->us_scale = 10; + else if (DetectedSamples->short_pulse_dur < 145) + app->us_scale = 30; } } i += thislen ? thislen : 1; @@ -317,11 +325,9 @@ uint32_t convert_signal_to_bits(uint8_t *b, uint32_t blen, RawSamplesBuffer *s, /* This function converts the line code used to the final data representation. * The representation is put inside 'buf', for up to 'buflen' bytes of total - * data. For instance in order to convert manchester I can use "10" and "01" - * as zero and one patterns. It is possible to use "?" inside patterns in - * order to skip certain bits. For instance certain devices encode data twice, - * with each bit encoded in manchester encoding and then in its reversed - * representation. In such a case I could use "10??" and "01??". + * data. For instance in order to convert manchester you can use "10" and "01" + * as zero and one patterns. However this function does not handle differential + * encodings. See below for convert_from_diff_manchester(). * * The function returns the number of bits converted. It will stop as soon * as it finds a pattern that does not match zero or one patterns, or when @@ -350,17 +356,46 @@ uint32_t convert_from_line_code(uint8_t *buf, uint64_t buflen, uint8_t *bits, ui return decoded; } +/* Convert the differential Manchester code to bits. This is similar to + * convert_from_line_code() but specific for Manchester. The user must + * supply the value of the previous symbol before this stream, since + * in differential codings the next bits depend on the previous one. + * + * Parameters and return values are like convert_from_line_code(). */ +uint32_t convert_from_diff_manchester(uint8_t *buf, uint64_t buflen, uint8_t *bits, uint32_t len, uint32_t off, bool previous) +{ + uint32_t decoded = 0; + len *= 8; /* Conver to bits. */ + for (uint32_t j = off; j < len; j += 2) { + bool b0 = bitmap_get(bits,len,j); + bool b1 = bitmap_get(bits,len,j+1); + if (b0 == previous) break; /* Each new bit must switch value. */ + bitmap_set(buf,buflen,decoded++,b0 == b1); + previous = b1; + if (decoded/8 == buflen) break; /* No space left on target buffer. */ + } + return decoded; +} + /* Supported protocols go here, with the relevant implementation inside * protocols/.c */ extern ProtoViewDecoder Oregon2Decoder; extern ProtoViewDecoder B4B1Decoder; extern ProtoViewDecoder RenaultTPMSDecoder; +extern ProtoViewDecoder ToyotaTPMSDecoder; +extern ProtoViewDecoder SchraderTPMSDecoder; +extern ProtoViewDecoder CitroenTPMSDecoder; +extern ProtoViewDecoder FordTPMSDecoder; ProtoViewDecoder *Decoders[] = { &Oregon2Decoder, /* Oregon sensors v2.1 protocol. */ &B4B1Decoder, /* PT, SC, ... 24 bits remotes. */ &RenaultTPMSDecoder, /* Renault TPMS. */ + &ToyotaTPMSDecoder, /* Toyota TPMS. */ + &SchraderTPMSDecoder, /* Schrader TPMS. */ + &CitroenTPMSDecoder, /* Citroen TPMS. */ + &FordTPMSDecoder, /* Ford TPMS. */ NULL }; @@ -378,12 +413,13 @@ bool decode_signal(RawSamplesBuffer *s, uint64_t len, ProtoViewMsgInfo *info) { uint32_t bitmap_bits_size = 4096*8; uint32_t bitmap_size = bitmap_bits_size/8; - /* We call the decoders with an offset a few bits before the actual + /* We call the decoders with an offset a few samples before the actual * signal detected and for a len of a few bits after its end. */ - uint32_t before_after_bits = 2; + uint32_t before_samples = 20; + uint32_t after_samples = 100; uint8_t *bitmap = malloc(bitmap_size); - uint32_t bits = convert_signal_to_bits(bitmap,bitmap_size,s,-before_after_bits,len+before_after_bits*2,s->short_pulse_dur); + uint32_t bits = convert_signal_to_bits(bitmap,bitmap_size,s,-before_samples,len+before_samples+after_samples,s->short_pulse_dur); if (DEBUG_MSG) { /* Useful for debugging purposes. Don't remove. */ char *str = malloc(1024); @@ -413,7 +449,7 @@ bool decode_signal(RawSamplesBuffer *s, uint64_t len, ProtoViewMsgInfo *info) { if (!decoded) { FURI_LOG_E(TAG, "No decoding possible"); } else { - FURI_LOG_E(TAG, "Decoded %s, raw=%s info=[%s,%s,%s]", info->name, info->raw, info->info1, info->info2, info->info3); + FURI_LOG_E(TAG, "Decoded %s, raw=%s info=[%s,%s,%s,%s]", info->name, info->raw, info->info1, info->info2, info->info3, info->info4); } free(bitmap); return decoded; diff --git a/applications/plugins/protoview/view_direct_sampling.c b/applications/plugins/protoview/view_direct_sampling.c index a287dc14a..251a289b8 100644 --- a/applications/plugins/protoview/view_direct_sampling.c +++ b/applications/plugins/protoview/view_direct_sampling.c @@ -8,7 +8,18 @@ /* Read directly from the G0 CC1101 pin, and draw a black or white * dot depending on the level. */ void render_view_direct_sampling(Canvas *const canvas, ProtoViewApp *app) { - UNUSED(app); + if (!app->direct_sampling_enabled) { + canvas_set_font(canvas, FontSecondary); + canvas_draw_str(canvas,2,9,"Direct sampling is a special"); + canvas_draw_str(canvas,2,18,"mode that displays the signal"); + canvas_draw_str(canvas,2,27,"captured in real time. Like in"); + canvas_draw_str(canvas,2,36,"a old CRT TV. It's very slow."); + canvas_draw_str(canvas,2,45,"Can crash your Flipper."); + canvas_set_font(canvas, FontPrimary); + canvas_draw_str(canvas,14,60,"To enable press OK"); + return; + } + for (int y = 0; y < 64; y++) { for (int x = 0; x < 128; x++) { bool level = furi_hal_gpio_read(&gpio_cc1101_g0); @@ -16,31 +27,41 @@ void render_view_direct_sampling(Canvas *const canvas, ProtoViewApp *app) { /* Busy loop: this is a terrible approach as it blocks * everything else, but for now it's the best we can do * to obtain direct data with some spacing. */ - uint32_t x = 500; while(x--); + uint32_t x = 250; while(x--); } } canvas_set_font(canvas, FontSecondary); - canvas_draw_str_with_border(canvas,40,60,"Direct sampling", + canvas_draw_str_with_border(canvas,36,60,"Direct sampling", ColorWhite,ColorBlack); } /* Handle input */ void process_input_direct_sampling(ProtoViewApp *app, InputEvent input) { - UNUSED(app); - UNUSED(input); + if (input.type == InputTypePress && input.key == InputKeyOk) { + app->direct_sampling_enabled = !app->direct_sampling_enabled; + } } /* Enter view. Stop the subghz thread to prevent access as we read * the CC1101 data directly. */ void view_enter_direct_sampling(ProtoViewApp *app) { - if (app->txrx->txrx_state == TxRxStateRx) { + if (app->txrx->txrx_state == TxRxStateRx && + !app->txrx->debug_timer_sampling) + { subghz_worker_stop(app->txrx->worker); + } else { + raw_sampling_worker_stop(app); } } /* Exit view. Restore the subghz thread. */ void view_exit_direct_sampling(ProtoViewApp *app) { - if (app->txrx->txrx_state == TxRxStateRx) { + if (app->txrx->txrx_state == TxRxStateRx && + !app->txrx->debug_timer_sampling) + { subghz_worker_start(app->txrx->worker); + } else { + raw_sampling_worker_start(app); } + app->direct_sampling_enabled = false; } diff --git a/applications/plugins/protoview/view_info.c b/applications/plugins/protoview/view_info.c index fff9c836e..775c8abc2 100644 --- a/applications/plugins/protoview/view_info.c +++ b/applications/plugins/protoview/view_info.c @@ -25,17 +25,18 @@ void render_view_info(Canvas *const canvas, ProtoViewApp *app) { canvas_draw_str(canvas, 0, y, buf); y += lineheight; } - canvas_draw_str(canvas, 0, y, app->signal_info.info1); - y += lineheight; - canvas_draw_str(canvas, 0, y, app->signal_info.info2); - y += lineheight; - canvas_draw_str(canvas, 0, y, app->signal_info.info3); - y += lineheight; + canvas_draw_str(canvas, 0, y, app->signal_info.info1); y += lineheight; + canvas_draw_str(canvas, 0, y, app->signal_info.info2); y += lineheight; + canvas_draw_str(canvas, 0, y, app->signal_info.info3); y += lineheight; + canvas_draw_str(canvas, 0, y, app->signal_info.info4); y += lineheight; } -/* Handle input for the settings view. */ +/* Handle input for the info view. */ void process_input_info(ProtoViewApp *app, InputEvent input) { - UNUSED(app); - UNUSED(input); - return; + if (input.type == InputTypeShort) { + if (input.key == InputKeyOk) { + /* Reset the current sample to capture the next. */ + reset_current_signal(app); + } + } } diff --git a/applications/plugins/protoview/view_settings.c b/applications/plugins/protoview/view_settings.c index 22ac5ef0f..1e2dce226 100644 --- a/applications/plugins/protoview/view_settings.c +++ b/applications/plugins/protoview/view_settings.c @@ -20,6 +20,9 @@ void render_view_settings(Canvas *const canvas, ProtoViewApp *app) { canvas_set_font(canvas, FontSecondary); canvas_draw_str(canvas,10,61,"Use up and down to modify"); + if (app->txrx->debug_timer_sampling) + canvas_draw_str(canvas,3,52,"(DEBUG timer sampling is ON)"); + /* Show frequency. We can use big numbers font since it's just a number. */ if (app->current_view == ViewFrequencySettings) { char buf[16]; @@ -40,6 +43,18 @@ void process_input_settings(ProtoViewApp *app, InputEvent input) { * modulation. */ app->frequency = subghz_setting_get_default_frequency(app->setting); app->modulation = 0; + } else if (0 && input.type == InputTypeLong && input.key == InputKeyDown) { + /* Long pressing to down switches between normal and debug + * timer sampling mode. NOTE: this feature is disabled for users, + * only useful for devs (if useful at all). */ + + /* We have to stop the previous sampling system. */ + radio_rx_end(app); + + /* Then switch mode and start the new one. */ + app->txrx->debug_timer_sampling = !app->txrx->debug_timer_sampling; + radio_begin(app); + radio_rx(app); } else if (input.type == InputTypePress && (input.key != InputKeyDown || input.key != InputKeyUp)) { @@ -85,9 +100,18 @@ void process_input_settings(ProtoViewApp *app, InputEvent input) { return; } - /* Apply changes. */ - FURI_LOG_E(TAG, "Setting view, setting frequency/modulation to %lu %s", app->frequency, ProtoViewModulations[app->modulation].name); - radio_rx_end(app); - radio_begin(app); - radio_rx(app); + /* Apply changes when switching to other views. */ + app->txrx->freq_mod_changed = true; +} + +/* When the user switches to some other view, if they changed the parameters + * we need to restart the radio with the right frequency and modulation. */ +void view_exit_settings(ProtoViewApp *app) { + if (app->txrx->freq_mod_changed) { + FURI_LOG_E(TAG, "Setting view, setting frequency/modulation to %lu %s", app->frequency, ProtoViewModulations[app->modulation].name); + radio_rx_end(app); + radio_begin(app); + radio_rx(app); + app->txrx->freq_mod_changed = false; + } } From a9d955546554549882bce561b8fef172ab49bcb6 Mon Sep 17 00:00:00 2001 From: jbohack Date: Fri, 13 Jan 2023 13:36:50 -0500 Subject: [PATCH 12/60] sfw added for sd card unmount --- .../scenes/storage_settings_scene_unmounted.c | 11 ++++++++++- assets/icons/Dolphin/DolphinCommon_56x48_sfw.png | Bin 0 -> 1416 bytes 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 assets/icons/Dolphin/DolphinCommon_56x48_sfw.png diff --git a/applications/settings/storage_settings/scenes/storage_settings_scene_unmounted.c b/applications/settings/storage_settings/scenes/storage_settings_scene_unmounted.c index 486f07603..db7382eb0 100644 --- a/applications/settings/storage_settings/scenes/storage_settings_scene_unmounted.c +++ b/applications/settings/storage_settings/scenes/storage_settings_scene_unmounted.c @@ -1,4 +1,5 @@ #include "../storage_settings.h" +#include "../../desktop_settings/desktop_settings_app.h" static void storage_settings_scene_unmounted_dialog_callback(DialogExResult result, void* context) { @@ -11,9 +12,16 @@ void storage_settings_scene_unmounted_on_enter(void* context) { StorageSettings* app = context; FS_Error error = storage_sd_unmount(app->fs_api); DialogEx* dialog_ex = app->dialog_ex; + DesktopSettings* settings = malloc(sizeof(DesktopSettings)); + DESKTOP_SETTINGS_LOAD(settings); dialog_ex_set_center_button_text(dialog_ex, "OK"); - dialog_ex_set_icon(dialog_ex, 72, 17, &I_DolphinCommon_56x48); + if (settings->sfw_mode) { + dialog_ex_set_icon(dialog_ex, 72, 17, &I_DolphinCommon_56x48_sfw); + } + else { + dialog_ex_set_icon(dialog_ex, 72, 17, &I_DolphinCommon_56x48); + } if(error == FSE_OK) { dialog_ex_set_header(dialog_ex, "SD Card Unmounted", 64, 3, AlignCenter, AlignTop); @@ -29,6 +37,7 @@ void storage_settings_scene_unmounted_on_enter(void* context) { dialog_ex_set_result_callback(dialog_ex, storage_settings_scene_unmounted_dialog_callback); view_dispatcher_switch_to_view(app->view_dispatcher, StorageSettingsViewDialogEx); + free(settings); } bool storage_settings_scene_unmounted_on_event(void* context, SceneManagerEvent event) { diff --git a/assets/icons/Dolphin/DolphinCommon_56x48_sfw.png b/assets/icons/Dolphin/DolphinCommon_56x48_sfw.png new file mode 100644 index 0000000000000000000000000000000000000000..089aaed83507431993a76ca25d32fdd9664c1c84 GIT binary patch literal 1416 zcmaJ>eNYr-7(dh;KXS5&nWVIBjS_NizYg|x=Pr^vz*7zxJO|P-dw2IeZq?gec9-rD zoPZchQ_6}yP{Slc4I!!28K==nodOJ_nsCY-(wOq2uZbLx!rlYU{KIi)_Wj!D_j`WN z^FGgREXdEDF)ewT&1Re7Tj(uBvlG44lnH3;I%IzsO|z`*Vr!`uv?9QOwgs{#Ld+Ki zC9n_zxxBOkx@@+IwMwAaD)#3Ik`}gun2kLe))Crfb7e+#AgzHGCc+X$b>qJuIf`S7 z?8b}I{ghw#z>uiaLknQh@LJUrqHcVYS3v97F^OZN zCe|7^J|?QzUx0Zu17e(=CM1fYFpjtLk|a4~$g}e?hGH0!VoBOT&<=s(1ct%J9~?O} z$)jW_dkX9yTX~%W*i_IM%0{ z7EmP^_pKn`<5>E(SixgJU};7`)7Hidp&+DLnizsebUk}_-GfgbN^il9b`v)f+ z{o5Zry)d<7`fHQ^uw_;+x>mcPw0&8iW69x{k92O{Q}`yFdH=5d$pbf49w1&NS)G+vhr6y}5TMsofQirRDUmKilk5=(KGouJ{H9hW=$X zgi;)vI!jl!_4H3jD(?Jz=8By|i47I&tKA1y9{nfp;_|FxKBDNWp{hN9hJ1nU?z%J6 z?>UxyzWvO}Pgc~rCZ#5%Eq+_hNS~bBdiGlT&f%%e`hHjSySR2=JuK2^+%;$R3#Wz~ z=e_mfqW23bPa0fhe)HdE5+GelU&!jS3ckUZOQ)CC5?mo zo=tzG_4|RuvPUO|mhCwA>y)1c%SWC%a4?a-x|J*?ch~+n=R7o@>p6J2dE=$stKZmK z-xoTRwET2^Wu)&1U7!Ebw!!D?x`xwQX3pMnrRwCT?`4GHt4&?|cIiI{_^XYp-np>6 xE^lPSXzOYCC4X`6tl@OB1M5_S7jml-Y~(TPp{aTIejNKZ`m*!Atyxdk{0EAy49frj literal 0 HcmV?d00001 From ed9cad46abedbf335f6cfee7a5b9796db823aaf7 Mon Sep 17 00:00:00 2001 From: VerstreuteSeele Date: Sat, 14 Jan 2023 01:08:12 +0100 Subject: [PATCH 13/60] Update api_symbols.csv --- firmware/targets/f7/api_symbols.csv | 1 + 1 file changed, 1 insertion(+) diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index 1874b664b..35fd8015d 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1659,6 +1659,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* From e79ade605d6247d2220b5a22dffb7a6a9e84659a Mon Sep 17 00:00:00 2001 From: VerstreuteSeele Date: Sat, 14 Jan 2023 01:10:00 +0100 Subject: [PATCH 14/60] Update subghz_cli.c --- applications/main/subghz/subghz_cli.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/applications/main/subghz/subghz_cli.c b/applications/main/subghz/subghz_cli.c index 684733c2b..6072be694 100644 --- a/applications/main/subghz/subghz_cli.c +++ b/applications/main/subghz/subghz_cli.c @@ -766,7 +766,7 @@ void subghz_on_system_start() { Cli* cli = furi_record_open(RECORD_CLI); cli_add_command(cli, "subghz", CliCommandFlagDefault, subghz_cli_command, NULL); - + cli_add_command(cli, "chat", CliCommandFlagDefault, subghz_cli_command_chat, NULL); furi_record_close(RECORD_CLI); #else UNUSED(subghz_cli_command); From 9fb6ad2e26451fca222f261c63e358d2626533ce Mon Sep 17 00:00:00 2001 From: VerstreuteSeele Date: Sat, 14 Jan 2023 03:11:20 +0100 Subject: [PATCH 15/60] Chat update --- applications/main/subghz/subghz_cli.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/applications/main/subghz/subghz_cli.c b/applications/main/subghz/subghz_cli.c index 6072be694..7422b6fb9 100644 --- a/applications/main/subghz/subghz_cli.c +++ b/applications/main/subghz/subghz_cli.c @@ -387,7 +387,7 @@ void subghz_cli_command_decode_raw(Cli* cli, FuriString* args, void* context) { } printf( - "Listening at \033[0;33m%s\033[0m.\r\n\r\nPress CTRL+C to stop\r\n\r\n", + "Listening at %s.\r\n\r\nPress CTRL+C to stop\r\n\r\n", furi_string_get_cstr(file_name)); LevelDuration level_duration; @@ -521,7 +521,8 @@ static void subghz_cli_command_encrypt_raw(Cli* cli, FuriString* args) { furi_string_free(source); } -static void subghz_cli_command_chat(Cli* cli, FuriString* args) { +static void subghz_cli_command_chat(Cli* cli, FuriString* args, void* context) { + UNUSED(context); uint32_t frequency = 433920000; if(furi_string_size(args)) { @@ -577,7 +578,7 @@ static void subghz_cli_command_chat(Cli* cli, FuriString* args) { NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION); - furi_string_printf(name, "\033[0;33m%s\033[0m: ", furi_hal_version_get_name_ptr()); + furi_string_printf(name, "%s: ", furi_hal_version_get_name_ptr()); furi_string_set(input, name); printf("%s", furi_string_get_cstr(input)); fflush(stdout); @@ -660,7 +661,7 @@ static void subghz_cli_command_chat(Cli* cli, FuriString* args) { case SubGhzChatEventUserEntrance: furi_string_printf( sysmsg, - "\033[0;34m%s joined chat.\033[0m\r\n", + "%s joined chat.\r\n", furi_hal_version_get_name_ptr()); subghz_chat_worker_write( subghz_chat, @@ -669,7 +670,7 @@ static void subghz_cli_command_chat(Cli* cli, FuriString* args) { break; case SubGhzChatEventUserExit: furi_string_printf( - sysmsg, "\033[0;31m%s left chat.\033[0m\r\n", furi_hal_version_get_name_ptr()); + sysmsg, "%s left chat.\r\n", furi_hal_version_get_name_ptr()); subghz_chat_worker_write( subghz_chat, (uint8_t*)furi_string_get_cstr(sysmsg), @@ -714,7 +715,7 @@ static void subghz_cli_command(Cli* cli, FuriString* args, void* context) { } if(furi_string_cmp_str(cmd, "chat") == 0) { - subghz_cli_command_chat(cli, args); + subghz_cli_command_chat(cli, args, NULL); break; } @@ -766,9 +767,11 @@ void subghz_on_system_start() { Cli* cli = furi_record_open(RECORD_CLI); cli_add_command(cli, "subghz", CliCommandFlagDefault, subghz_cli_command, NULL); + cli_add_command(cli, "chat", CliCommandFlagDefault, subghz_cli_command_chat, NULL); + furi_record_close(RECORD_CLI); #else UNUSED(subghz_cli_command); #endif -} +} \ No newline at end of file From 98778401fef7f45f2c1ef055fe8b4c93b41051ba Mon Sep 17 00:00:00 2001 From: VerstreuteSeele Date: Sat, 14 Jan 2023 03:14:33 +0100 Subject: [PATCH 16/60] Update FlipperPlaylist.py --- scripts/FlipperPlaylist.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/FlipperPlaylist.py b/scripts/FlipperPlaylist.py index 1ff7f8532..4a688f2fb 100644 --- a/scripts/FlipperPlaylist.py +++ b/scripts/FlipperPlaylist.py @@ -2,10 +2,10 @@ import os import pip try: - from easygui import fileopenbox, diropenbox + from easygui import diropenbox except ImportError: pip.main(['Install'], "easygui") - from easygui import fileopenbox, diropenbox + from easygui import diropenbox def main(): folder_path = diropenbox("Select the folder with Subghz files", "Subghz selector") From d6962e3b3d76d004190a145f29c0f4bb9b7ef94d Mon Sep 17 00:00:00 2001 From: VerstreuteSeele Date: Sat, 14 Jan 2023 03:52:04 +0100 Subject: [PATCH 17/60] trollage --- applications/main/subghz/subghz_cli.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/applications/main/subghz/subghz_cli.c b/applications/main/subghz/subghz_cli.c index 7422b6fb9..d2c999a8d 100644 --- a/applications/main/subghz/subghz_cli.c +++ b/applications/main/subghz/subghz_cli.c @@ -767,7 +767,7 @@ void subghz_on_system_start() { Cli* cli = furi_record_open(RECORD_CLI); cli_add_command(cli, "subghz", CliCommandFlagDefault, subghz_cli_command, NULL); - + // psst RM... i know you dont care much about errors, but if you ever see this... incompatible pointer type :3 cli_add_command(cli, "chat", CliCommandFlagDefault, subghz_cli_command_chat, NULL); furi_record_close(RECORD_CLI); From f0df3ff827278625a0b2e4466b8d596ce374a309 Mon Sep 17 00:00:00 2001 From: VerstreuteSeele Date: Sat, 14 Jan 2023 05:44:07 +0100 Subject: [PATCH 18/60] Browser now opening to browser --- applications/main/archive/helpers/archive_browser.c | 4 ++-- applications/main/archive/helpers/archive_browser.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/applications/main/archive/helpers/archive_browser.c b/applications/main/archive/helpers/archive_browser.c index 1cf7be854..7d3c753c3 100644 --- a/applications/main/archive/helpers/archive_browser.c +++ b/applications/main/archive/helpers/archive_browser.c @@ -139,7 +139,7 @@ void archive_update_focus(ArchiveBrowserView* browser, const char* target) { archive_get_items(browser, furi_string_get_cstr(browser->path)); if(!archive_file_get_array_size(browser) && archive_is_home(browser)) { - archive_switch_tab(browser, TAB_RIGHT); + archive_switch_tab(browser, TAB_LEFT); } else { with_view_model( browser->view, @@ -206,7 +206,7 @@ void archive_file_array_rm_selected(ArchiveBrowserView* browser) { false); if((items_cnt == 0) && (archive_is_home(browser))) { - archive_switch_tab(browser, TAB_RIGHT); + archive_switch_tab(browser, TAB_LEFT); } archive_update_offset(browser); diff --git a/applications/main/archive/helpers/archive_browser.h b/applications/main/archive/helpers/archive_browser.h index 09ffea1f9..5b13e98da 100644 --- a/applications/main/archive/helpers/archive_browser.h +++ b/applications/main/archive/helpers/archive_browser.h @@ -3,7 +3,7 @@ #include "../archive_i.h" #include -#define TAB_RIGHT InputKeyRight // Default tab switch direction +#define TAB_LEFT InputKeyLeft // Default tab switch direction #define TAB_DEFAULT ArchiveTabFavorites // Start tab #define FILE_LIST_BUF_LEN 50 From dda9ffdce2a249182c064614c910f612d0fb10e2 Mon Sep 17 00:00:00 2001 From: VerstreuteSeele Date: Sat, 14 Jan 2023 07:19:26 +0100 Subject: [PATCH 19/60] Thanks, PVC --- firmware/targets/f7/furi_hal/furi_hal_subghz.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/targets/f7/furi_hal/furi_hal_subghz.c b/firmware/targets/f7/furi_hal/furi_hal_subghz.c index 74f9d334f..fdeb5c742 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_subghz.c +++ b/firmware/targets/f7/furi_hal/furi_hal_subghz.c @@ -354,7 +354,7 @@ bool furi_hal_subghz_is_tx_allowed(uint32_t value) { !(value >= 915000000 && value <= 928000000)) { } else { if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { - if((value >= 304100000 && value <= 321950000) && + if(value <= 321950000 && ((furi_hal_subghz.preset == FuriHalSubGhzPresetOok270Async) || (furi_hal_subghz.preset == FuriHalSubGhzPresetOok650Async))) { furi_hal_subghz_load_patable(furi_hal_subghz_preset_ook_async_patable_au); From 7385a28ddd9a4ffc66f3c53976a1460dea484d7f Mon Sep 17 00:00:00 2001 From: VerstreuteSeele Date: Sat, 14 Jan 2023 08:01:52 +0100 Subject: [PATCH 20/60] Remove unused code --- applications/services/desktop/desktop.c | 16 ---------- applications/services/desktop/desktop_i.h | 1 - applications/services/gui/gui.c | 36 +---------------------- 3 files changed, 1 insertion(+), 52 deletions(-) diff --git a/applications/services/desktop/desktop.c b/applications/services/desktop/desktop.c index 5575537de..0e7f3caba 100644 --- a/applications/services/desktop/desktop.c +++ b/applications/services/desktop/desktop.c @@ -39,12 +39,6 @@ static void desktop_lock_icon_draw_callback(Canvas* canvas, void* context) { canvas_draw_icon(canvas, 0, 0, &I_Lock_8x8); } -static void desktop_sfw_mode_icon_draw_callback(Canvas* canvas, void* context) { - UNUSED(context); - furi_assert(canvas); - canvas_draw_icon(canvas, 0, 0, &I_GameMode_11x8); -} - static bool desktop_custom_event_callback(void* context, uint32_t event) { furi_assert(context); Desktop* desktop = (Desktop*)context; @@ -149,7 +143,6 @@ void desktop_unlock(Desktop* desktop) { } void desktop_set_sfw_mode_state(Desktop* desktop, bool enabled) { - view_port_enabled_set(desktop->sfw_mode_icon_viewport, enabled); desktop->settings.sfw_mode = enabled; DESKTOP_SETTINGS_SAVE(&desktop->settings); animation_manager_new_idle_process(desktop->animation_manager); @@ -238,14 +231,6 @@ Desktop* desktop_alloc() { view_port_enabled_set(desktop->lock_icon_viewport, false); gui_add_view_port(desktop->gui, desktop->lock_icon_viewport, GuiLayerStatusBarLeft); - // Dummy mode icon - desktop->sfw_mode_icon_viewport = view_port_alloc(); - view_port_set_width(desktop->sfw_mode_icon_viewport, icon_get_width(&I_GameMode_11x8)); - view_port_draw_callback_set( - desktop->sfw_mode_icon_viewport, desktop_sfw_mode_icon_draw_callback, desktop); - view_port_enabled_set(desktop->sfw_mode_icon_viewport, false); - gui_add_view_port(desktop->gui, desktop->sfw_mode_icon_viewport, GuiLayerStatusBarLeft); - // Special case: autostart application is already running desktop->loader = furi_record_open(RECORD_LOADER); if (loader_is_locked(desktop->loader) && @@ -342,7 +327,6 @@ int32_t desktop_srv(void* p) { DESKTOP_SETTINGS_SAVE(&desktop->settings); } - view_port_enabled_set(desktop->sfw_mode_icon_viewport, desktop->settings.sfw_mode); desktop_main_set_sfw_mode_state(desktop->main_view, desktop->settings.sfw_mode); scene_manager_next_scene(desktop->scene_manager, DesktopSceneMain); diff --git a/applications/services/desktop/desktop_i.h b/applications/services/desktop/desktop_i.h index b6de6bfd5..007c50f36 100644 --- a/applications/services/desktop/desktop_i.h +++ b/applications/services/desktop/desktop_i.h @@ -58,7 +58,6 @@ struct Desktop { DesktopViewPinInput* pin_input_view; ViewPort* lock_icon_viewport; - ViewPort* sfw_mode_icon_viewport; AnimationManager* animation_manager; diff --git a/applications/services/gui/gui.c b/applications/services/gui/gui.c index 060fa844b..7ef6ef2a9 100644 --- a/applications/services/gui/gui.c +++ b/applications/services/gui/gui.c @@ -116,41 +116,7 @@ static void gui_redraw_status_bar(Gui* gui, bool need_attention) { canvas_height(gui->canvas) - 4); } - // Left side - x = 2; - ViewPortArray_it(it, gui->layers[GuiLayerStatusBarLeft]); - while(!ViewPortArray_end_p(it) && (right_used + left_used) < GUI_STATUS_BAR_WIDTH) { - ViewPort* view_port = *ViewPortArray_ref(it); - if(view_port_is_enabled(view_port)) { - width = view_port_get_width(view_port); - if(!width) width = 8; - // Prepare work area background - canvas_frame_set( - gui->canvas, - x - 1, - // SASQUACH SAYS : This is the white box behind the left bar, move it 64 to hide it - GUI_STATUS_BAR_Y + 64, - width + 2, - GUI_STATUS_BAR_WORKAREA_HEIGHT + 2); - canvas_set_color(gui->canvas, ColorWhite); - canvas_draw_box( - gui->canvas, 0, 0, canvas_width(gui->canvas), canvas_height(gui->canvas)); - canvas_set_color(gui->canvas, ColorBlack); - // ViewPort draw - canvas_frame_set( - // SASQUACH SAYS : This is where you move the Icons for the left bar, 64 to hide it - gui->canvas, - x, - GUI_STATUS_BAR_Y + 64, - width, - GUI_STATUS_BAR_WORKAREA_HEIGHT); - view_port_draw(view_port, gui->canvas); - // Recalculate next position - left_used += (width + 2); - x += (width + 2); - } - ViewPortArray_next(it); - } + // Extra notification if(need_attention) { width = icon_get_width(&I_Hidden_window_9x8); From 905bb23fdf0e59d54d2daf29b4ebb444ab8f9e2c Mon Sep 17 00:00:00 2001 From: VerstreuteSeele Date: Sat, 14 Jan 2023 08:44:32 +0100 Subject: [PATCH 21/60] Formatting & New updated IR --- .../main/archive/helpers/archive_browser.c | 8 +- .../main/bad_usb/scenes/bad_usb_scene_error.c | 5 +- .../main/bad_usb/views/bad_usb_view.c | 15 +- .../scenes/ibutton_scene_delete_success.c | 5 +- .../main/ibutton/scenes/ibutton_scene_read.c | 5 +- .../scenes/ibutton_scene_save_success.c | 5 +- .../scenes/ibutton_scene_write_success.c | 5 +- .../scenes/infrared_scene_edit_rename_done.c | 5 +- .../scenes/infrared_scene_learn_done.c | 10 +- .../scenes/infrared_scene_learn_success.c | 5 +- .../infrared/scenes/infrared_scene_start.c | 1 - .../lfrfid/scenes/lfrfid_scene_clear_t5577.c | 10 +- .../scenes/lfrfid_scene_delete_success.c | 5 +- .../main/lfrfid/scenes/lfrfid_scene_emulate.c | 5 +- .../lfrfid/scenes/lfrfid_scene_raw_read.c | 5 +- .../main/lfrfid/scenes/lfrfid_scene_rpc.c | 5 +- .../lfrfid/scenes/lfrfid_scene_save_success.c | 5 +- .../main/lfrfid/scenes/lfrfid_scene_write.c | 5 +- .../scenes/lfrfid_scene_write_success.c | 5 +- applications/main/nfc/nfc_cli.c | 2 +- .../nfc/scenes/nfc_scene_delete_success.c | 5 +- .../main/nfc/scenes/nfc_scene_emulate_uid.c | 5 +- .../nfc/scenes/nfc_scene_mf_classic_emulate.c | 5 +- .../nfc_scene_mf_classic_update_success.c | 5 +- .../nfc_scene_mf_classic_write_success.c | 5 +- .../scenes/nfc_scene_mf_ultralight_emulate.c | 5 +- .../main/nfc/scenes/nfc_scene_passport_auth.c | 2 +- .../main/nfc/scenes/nfc_scene_passport_date.c | 1 - .../nfc/scenes/nfc_scene_restore_original.c | 5 +- applications/main/nfc/scenes/nfc_scene_rpc.c | 5 +- .../main/nfc/scenes/nfc_scene_save_success.c | 5 +- applications/main/sub_playlist/playlist.c | 3 +- .../scenes/subghz_scene_delete_success.c | 5 +- .../main/subghz/scenes/subghz_scene_rpc.c | 5 +- .../subghz/scenes/subghz_scene_save_success.c | 5 +- applications/main/subghz/subghz_cli.c | 10 +- applications/main/subghz/views/receiver.c | 10 +- .../main/u2f/scenes/u2f_scene_error.c | 5 +- applications/main/u2f/u2f.c | 44 +- applications/main/u2f/u2f_nfc.c | 55 +- applications/main/u2f/u2f_nfc.h | 6 +- applications/main/u2f/views/u2f_view.c | 78 +- applications/plugins/arkanoid/arkanoid_game.c | 2 +- applications/plugins/asteroids/app.c | 409 +++--- applications/plugins/cli_bridge/cligui_main.c | 6 +- .../plugins/cli_bridge/console_output.c | 1 - .../plugins/cli_bridge/internal_defs.h | 1 - applications/plugins/dap_link/dap_link.c | 8 +- .../views/pocsag_pager_receiver.c | 10 +- applications/plugins/pong/flipper_pong.c | 229 ++-- applications/plugins/protoview/app.c | 124 +- applications/plugins/protoview/app.h | 121 +- applications/plugins/protoview/app_buffer.c | 39 +- applications/plugins/protoview/app_buffer.h | 21 +- applications/plugins/protoview/app_subghz.c | 38 +- applications/plugins/protoview/crc.c | 9 +- .../plugins/protoview/custom_presets.h | 7 +- applications/plugins/protoview/data_feed.c | 17 +- .../plugins/protoview/protocols/b4b1.c | 35 +- .../protoview/protocols/citroen_tpms.c | 64 +- .../plugins/protoview/protocols/ford_tpms.c | 70 +- .../plugins/protoview/protocols/oregon2.c | 98 +- .../protoview/protocols/renault_tpms.c | 67 +- .../protoview/protocols/schrader_tpms.c | 69 +- .../plugins/protoview/protocols/toyota_tpms.c | 73 +- applications/plugins/protoview/signal.c | 283 ++-- applications/plugins/protoview/ui.c | 28 +- .../plugins/protoview/view_direct_sampling.c | 45 +- applications/plugins/protoview/view_info.c | 28 +- .../plugins/protoview/view_raw_signal.c | 57 +- .../plugins/protoview/view_settings.c | 74 +- applications/plugins/qrcode/qrcode.c | 649 +++++---- applications/plugins/qrcode/qrcode.h | 54 +- applications/plugins/qrcode/qrcode_app.c | 272 ++-- applications/plugins/solitaire/solitaire.c | 3 +- .../plugins/unitemp/views/General_view.c | 5 +- applications/plugins/usb_hid_autofire/tools.c | 18 +- applications/plugins/usb_hid_autofire/tools.h | 4 +- .../usb_hid_autofire/usb_hid_autofire.c | 26 +- .../views/weather_station_receiver.c | 10 +- .../wii_ec_anal/_image_tool/_convert.c | 234 ++-- .../wii_ec_anal/_image_tool/_convert_images.c | 206 ++- .../wii_ec_anal/_image_tool/_convert_images.h | 66 +- .../wii_ec_anal/_image_tool/_convert_test.c | 82 +- applications/plugins/wii_ec_anal/bc_logging.h | 54 +- applications/plugins/wii_ec_anal/err.h | 91 +- applications/plugins/wii_ec_anal/gfx/images.c | 206 ++- applications/plugins/wii_ec_anal/gfx/images.h | 228 ++-- .../plugins/wii_ec_anal/gfx/img_3x5_0.c | 4 +- .../plugins/wii_ec_anal/gfx/img_3x5_1.c | 4 +- .../plugins/wii_ec_anal/gfx/img_3x5_2.c | 4 +- .../plugins/wii_ec_anal/gfx/img_3x5_3.c | 4 +- .../plugins/wii_ec_anal/gfx/img_3x5_4.c | 4 +- .../plugins/wii_ec_anal/gfx/img_3x5_5.c | 4 +- .../plugins/wii_ec_anal/gfx/img_3x5_6.c | 4 +- .../plugins/wii_ec_anal/gfx/img_3x5_7.c | 4 +- .../plugins/wii_ec_anal/gfx/img_3x5_8.c | 4 +- .../plugins/wii_ec_anal/gfx/img_3x5_9.c | 4 +- .../plugins/wii_ec_anal/gfx/img_3x5_v.c | 4 +- .../plugins/wii_ec_anal/gfx/img_5x7_0.c | 4 +- .../plugins/wii_ec_anal/gfx/img_5x7_1.c | 4 +- .../plugins/wii_ec_anal/gfx/img_5x7_2.c | 4 +- .../plugins/wii_ec_anal/gfx/img_5x7_3.c | 4 +- .../plugins/wii_ec_anal/gfx/img_5x7_4.c | 4 +- .../plugins/wii_ec_anal/gfx/img_5x7_5.c | 4 +- .../plugins/wii_ec_anal/gfx/img_5x7_6.c | 4 +- .../plugins/wii_ec_anal/gfx/img_5x7_7.c | 4 +- .../plugins/wii_ec_anal/gfx/img_5x7_8.c | 4 +- .../plugins/wii_ec_anal/gfx/img_5x7_9.c | 4 +- .../plugins/wii_ec_anal/gfx/img_5x7_A.c | 4 +- .../plugins/wii_ec_anal/gfx/img_5x7_B.c | 4 +- .../plugins/wii_ec_anal/gfx/img_5x7_C.c | 4 +- .../plugins/wii_ec_anal/gfx/img_5x7_D.c | 4 +- .../plugins/wii_ec_anal/gfx/img_5x7_E.c | 4 +- .../plugins/wii_ec_anal/gfx/img_5x7_F.c | 4 +- .../plugins/wii_ec_anal/gfx/img_6x8_0.c | 4 +- .../plugins/wii_ec_anal/gfx/img_6x8_1.c | 4 +- .../plugins/wii_ec_anal/gfx/img_6x8_2.c | 4 +- .../plugins/wii_ec_anal/gfx/img_6x8_3.c | 4 +- .../plugins/wii_ec_anal/gfx/img_6x8_4.c | 4 +- .../plugins/wii_ec_anal/gfx/img_6x8_5.c | 4 +- .../plugins/wii_ec_anal/gfx/img_6x8_6.c | 4 +- .../plugins/wii_ec_anal/gfx/img_6x8_7.c | 4 +- .../plugins/wii_ec_anal/gfx/img_6x8_8.c | 4 +- .../plugins/wii_ec_anal/gfx/img_6x8_9.c | 4 +- .../plugins/wii_ec_anal/gfx/img_6x8_A.c | 4 +- .../plugins/wii_ec_anal/gfx/img_6x8_B.c | 4 +- .../plugins/wii_ec_anal/gfx/img_6x8_C.c | 4 +- .../plugins/wii_ec_anal/gfx/img_6x8_D.c | 4 +- .../plugins/wii_ec_anal/gfx/img_6x8_E.c | 4 +- .../plugins/wii_ec_anal/gfx/img_6x8_F.c | 4 +- .../plugins/wii_ec_anal/gfx/img_6x8_G.c | 4 +- .../plugins/wii_ec_anal/gfx/img_6x8_X.c | 4 +- .../plugins/wii_ec_anal/gfx/img_6x8_Y.c | 4 +- .../plugins/wii_ec_anal/gfx/img_6x8_Z.c | 4 +- .../plugins/wii_ec_anal/gfx/img_6x8_d_.c | 4 +- .../plugins/wii_ec_anal/gfx/img_6x8_n_.c | 4 +- .../plugins/wii_ec_anal/gfx/img_6x8_v_.c | 4 +- .../plugins/wii_ec_anal/gfx/img_RIP.c | 118 +- .../plugins/wii_ec_anal/gfx/img_cc_Cable.c | 14 +- .../plugins/wii_ec_anal/gfx/img_cc_Joy.c | 10 +- .../plugins/wii_ec_anal/gfx/img_cc_Main.c | 80 +- .../plugins/wii_ec_anal/gfx/img_cc_btn_A1.c | 4 +- .../plugins/wii_ec_anal/gfx/img_cc_btn_B1.c | 4 +- .../plugins/wii_ec_anal/gfx/img_cc_btn_X1.c | 4 +- .../plugins/wii_ec_anal/gfx/img_cc_btn_Y1.c | 4 +- .../plugins/wii_ec_anal/gfx/img_cc_pad_LR1.c | 4 +- .../plugins/wii_ec_anal/gfx/img_cc_pad_UD1.c | 4 +- .../plugins/wii_ec_anal/gfx/img_cc_trg_L1.c | 10 +- .../plugins/wii_ec_anal/gfx/img_cc_trg_L2.c | 22 +- .../plugins/wii_ec_anal/gfx/img_cc_trg_L3.c | 10 +- .../plugins/wii_ec_anal/gfx/img_cc_trg_L4.c | 18 +- .../plugins/wii_ec_anal/gfx/img_cc_trg_R1.c | 10 +- .../plugins/wii_ec_anal/gfx/img_cc_trg_R2.c | 10 +- .../plugins/wii_ec_anal/gfx/img_cc_trg_R3.c | 10 +- .../plugins/wii_ec_anal/gfx/img_cc_trg_R4.c | 21 +- .../plugins/wii_ec_anal/gfx/img_csLogo_FULL.c | 84 +- .../wii_ec_anal/gfx/img_csLogo_Small.c | 10 +- .../plugins/wii_ec_anal/gfx/img_ecp_SCL.c | 10 +- .../plugins/wii_ec_anal/gfx/img_ecp_SDA.c | 8 +- .../plugins/wii_ec_anal/gfx/img_ecp_port.c | 48 +- .../plugins/wii_ec_anal/gfx/img_key_Back.c | 5 +- .../plugins/wii_ec_anal/gfx/img_key_D.c | 5 +- .../plugins/wii_ec_anal/gfx/img_key_L.c | 5 +- .../plugins/wii_ec_anal/gfx/img_key_OK.c | 5 +- .../plugins/wii_ec_anal/gfx/img_key_OKi.c | 5 +- .../plugins/wii_ec_anal/gfx/img_key_R.c | 5 +- .../plugins/wii_ec_anal/gfx/img_key_U.c | 5 +- .../plugins/wii_ec_anal/gfx/img_key_Ui.c | 5 +- .../plugins/wii_ec_anal/i2c_workaround.h | 128 +- applications/plugins/wii_ec_anal/wii_anal.c | 765 +++++------ applications/plugins/wii_ec_anal/wii_anal.h | 118 +- .../plugins/wii_ec_anal/wii_anal_ec.c | 182 +-- .../plugins/wii_ec_anal/wii_anal_ec.h | 12 +- .../plugins/wii_ec_anal/wii_anal_keys.c | 416 +++--- .../plugins/wii_ec_anal/wii_anal_keys.h | 18 +- .../plugins/wii_ec_anal/wii_anal_lcd.c | 323 +++-- .../plugins/wii_ec_anal/wii_anal_lcd.h | 58 +- .../plugins/wii_ec_anal/wii_anal_ver.h | 10 +- applications/plugins/wii_ec_anal/wii_ec.c | 400 +++--- applications/plugins/wii_ec_anal/wii_ec.h | 210 ++- .../plugins/wii_ec_anal/wii_ec_classic.c | 575 ++++---- .../plugins/wii_ec_anal/wii_ec_classic.h | 69 +- .../plugins/wii_ec_anal/wii_ec_macros.h | 150 ++- .../plugins/wii_ec_anal/wii_ec_nunchuck.c | 715 +++++----- .../plugins/wii_ec_anal/wii_ec_nunchuck.h | 53 +- .../plugins/wii_ec_anal/wii_ec_udraw.c | 160 +-- .../plugins/wii_ec_anal/wii_ec_udraw.h | 20 +- applications/plugins/wii_ec_anal/wii_i2c.c | 364 +++-- applications/plugins/wii_ec_anal/wii_i2c.h | 24 +- applications/services/bt/bt_service/bt.c | 10 +- .../desktop/animations/animation_manager.c | 20 +- .../desktop/animations/animation_storage.c | 16 +- applications/services/desktop/desktop.c | 48 +- .../desktop/scenes/desktop_scene_fault.c | 6 +- .../desktop/views/desktop_view_lock_menu.c | 5 +- .../services/dolphin/helpers/dolphin_state.c | 14 +- applications/services/gui/gui.c | 1 - .../services/namechangersrv/namechangersrv.c | 86 +- .../services/power/power_service/power.c | 5 +- applications/settings/about/about.c | 9 +- .../bt_settings_scene_forget_dev_success.c | 5 +- .../desktop_settings_scene_pin_disable.c | 5 +- .../scenes/desktop_settings_scene_start.c | 13 +- .../settings/dolphin_passport/passport.c | 31 +- .../scenes/power_settings_scene_power_off.c | 13 +- .../scenes/storage_settings_scene_unmounted.c | 5 +- assets/resources/infrared/assets/ac.ir | 164 ++- assets/resources/infrared/assets/audio.ir | 1196 ++++++++--------- assets/resources/infrared/assets/fans.ir | 87 +- .../resources/infrared/assets/projectors.ir | 145 +- assets/resources/infrared/assets/tv.ir | 247 ++-- firmware/targets/f7/furi_hal/furi_hal_nfc.c | 10 +- .../targets/furi_hal_include/furi_hal_nfc.h | 5 +- lib/nfc/nfc_worker.c | 4 +- lib/subghz/protocols/protocol_items.c | 24 +- 216 files changed, 6455 insertions(+), 5877 deletions(-) diff --git a/applications/main/archive/helpers/archive_browser.c b/applications/main/archive/helpers/archive_browser.c index 7d3c753c3..f579a2beb 100644 --- a/applications/main/archive/helpers/archive_browser.c +++ b/applications/main/archive/helpers/archive_browser.c @@ -64,7 +64,13 @@ static void archive_add_file_item(browser, is_folder, furi_string_get_cstr(item_path)); } else { with_view_model( - browser->view, ArchiveBrowserViewModel * model, { files_array_sort(model->files); model->list_loading = false; }, true); + browser->view, + ArchiveBrowserViewModel * model, + { + files_array_sort(model->files); + model->list_loading = false; + }, + true); } } diff --git a/applications/main/bad_usb/scenes/bad_usb_scene_error.c b/applications/main/bad_usb/scenes/bad_usb_scene_error.c index feff466fa..8a50a2df8 100644 --- a/applications/main/bad_usb/scenes/bad_usb_scene_error.c +++ b/applications/main/bad_usb/scenes/bad_usb_scene_error.c @@ -34,7 +34,7 @@ void bad_usb_scene_error_on_enter(void* context) { app->widget, GuiButtonTypeLeft, "Back", bad_usb_scene_error_event_callback, app); } else if(app->error == BadUsbAppErrorCloseRpc) { widget_add_icon_element(app->widget, 78, 0, &I_ActiveConnection_50x64); - if (settings->sfw_mode) { + if(settings->sfw_mode) { widget_add_string_multiline_element( app->widget, 3, 2, AlignLeft, AlignTop, FontPrimary, "Connection\nis active!"); widget_add_string_multiline_element( @@ -45,8 +45,7 @@ void bad_usb_scene_error_on_enter(void* context) { AlignTop, FontSecondary, "Disconnect from\nPC or phone to\nuse this function."); - } - else { + } else { widget_add_string_multiline_element( app->widget, 3, 2, AlignLeft, AlignTop, FontPrimary, "I am not\na whore!"); widget_add_string_multiline_element( diff --git a/applications/main/bad_usb/views/bad_usb_view.c b/applications/main/bad_usb/views/bad_usb_view.c index 26b6ed27d..b700bc023 100644 --- a/applications/main/bad_usb/views/bad_usb_view.c +++ b/applications/main/bad_usb/views/bad_usb_view.c @@ -50,10 +50,9 @@ static void bad_usb_draw_callback(Canvas* canvas, void* _model) { if((model->state.state == BadUsbStateIdle) || (model->state.state == BadUsbStateDone) || (model->state.state == BadUsbStateNotConnected)) { - if (settings->sfw_mode) { + if(settings->sfw_mode) { elements_button_center(canvas, "Start"); - } - else { + } else { elements_button_center(canvas, "Cum"); } } else if((model->state.state == BadUsbStateRunning) || (model->state.state == BadUsbStateDelay)) { @@ -70,21 +69,19 @@ static void bad_usb_draw_callback(Canvas* canvas, void* _model) { if(model->state.state == BadUsbStateNotConnected) { canvas_draw_icon(canvas, 4, 26, &I_Clock_18x18); canvas_set_font(canvas, FontPrimary); - if (settings->sfw_mode) { + if(settings->sfw_mode) { canvas_draw_str_aligned(canvas, 127, 31, AlignRight, AlignBottom, "Connect to"); canvas_draw_str_aligned(canvas, 127, 43, AlignRight, AlignBottom, "a device"); - } - else { + } else { canvas_draw_str_aligned(canvas, 127, 31, AlignRight, AlignBottom, "Plug me"); canvas_draw_str_aligned(canvas, 127, 43, AlignRight, AlignBottom, "in, Daddy"); } } else if(model->state.state == BadUsbStateWillRun) { canvas_draw_icon(canvas, 4, 26, &I_Clock_18x18); canvas_set_font(canvas, FontPrimary); - if (settings->sfw_mode) { + if(settings->sfw_mode) { canvas_draw_str_aligned(canvas, 127, 31, AlignRight, AlignBottom, "Will run"); - } - else { + } else { canvas_draw_str_aligned(canvas, 127, 31, AlignRight, AlignBottom, "Will cum"); } canvas_draw_str_aligned(canvas, 127, 43, AlignRight, AlignBottom, "on connect"); diff --git a/applications/main/ibutton/scenes/ibutton_scene_delete_success.c b/applications/main/ibutton/scenes/ibutton_scene_delete_success.c index 0af4b19a6..f543ceeb2 100644 --- a/applications/main/ibutton/scenes/ibutton_scene_delete_success.c +++ b/applications/main/ibutton/scenes/ibutton_scene_delete_success.c @@ -12,10 +12,9 @@ void ibutton_scene_delete_success_on_enter(void* context) { DesktopSettings* settings = malloc(sizeof(DesktopSettings)); DESKTOP_SETTINGS_LOAD(settings); - if (settings->sfw_mode) { + if(settings->sfw_mode) { popup_set_icon(popup, 0, 2, &I_DolphinMafia_115x62_sfw); - } - else { + } else { popup_set_icon(popup, 0, 2, &I_DolphinMafia_115x62); } popup_set_header(popup, "Deleted", 83, 19, AlignLeft, AlignBottom); diff --git a/applications/main/ibutton/scenes/ibutton_scene_read.c b/applications/main/ibutton/scenes/ibutton_scene_read.c index b574b643b..4dbbed352 100644 --- a/applications/main/ibutton/scenes/ibutton_scene_read.c +++ b/applications/main/ibutton/scenes/ibutton_scene_read.c @@ -17,10 +17,9 @@ void ibutton_scene_read_on_enter(void* context) { popup_set_header(popup, "iButton", 95, 26, AlignCenter, AlignBottom); popup_set_text(popup, "Waiting\nfor key ...", 95, 30, AlignCenter, AlignTop); - if (settings->sfw_mode) { + if(settings->sfw_mode) { popup_set_icon(popup, 0, 5, &I_DolphinWait_61x59_sfw); - } - else { + } else { popup_set_icon(popup, 0, 5, &I_DolphinWait_61x59); } diff --git a/applications/main/ibutton/scenes/ibutton_scene_save_success.c b/applications/main/ibutton/scenes/ibutton_scene_save_success.c index ad673faba..02c6abe2b 100644 --- a/applications/main/ibutton/scenes/ibutton_scene_save_success.c +++ b/applications/main/ibutton/scenes/ibutton_scene_save_success.c @@ -12,10 +12,9 @@ void ibutton_scene_save_success_on_enter(void* context) { DesktopSettings* settings = malloc(sizeof(DesktopSettings)); DESKTOP_SETTINGS_LOAD(settings); - if (settings->sfw_mode) { + if(settings->sfw_mode) { popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59_sfw); - } - else { + } else { popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59); } popup_set_header(popup, "Saved!", 5, 7, AlignLeft, AlignTop); diff --git a/applications/main/ibutton/scenes/ibutton_scene_write_success.c b/applications/main/ibutton/scenes/ibutton_scene_write_success.c index 291140506..3d461018c 100644 --- a/applications/main/ibutton/scenes/ibutton_scene_write_success.c +++ b/applications/main/ibutton/scenes/ibutton_scene_write_success.c @@ -13,10 +13,9 @@ void ibutton_scene_write_success_on_enter(void* context) { DesktopSettings* settings = malloc(sizeof(DesktopSettings)); DESKTOP_SETTINGS_LOAD(settings); - if (settings->sfw_mode) { + if(settings->sfw_mode) { popup_set_icon(popup, 0, 12, &I_iButtonDolphinVerySuccess_108x52_sfw); - } - else { + } else { popup_set_icon(popup, 0, 12, &I_iButtonDolphinVerySuccess_108x52); } popup_set_text(popup, "Successfully written!", 40, 12, AlignLeft, AlignBottom); diff --git a/applications/main/infrared/scenes/infrared_scene_edit_rename_done.c b/applications/main/infrared/scenes/infrared_scene_edit_rename_done.c index 5142a181f..056c97db6 100644 --- a/applications/main/infrared/scenes/infrared_scene_edit_rename_done.c +++ b/applications/main/infrared/scenes/infrared_scene_edit_rename_done.c @@ -7,10 +7,9 @@ void infrared_scene_edit_rename_done_on_enter(void* context) { DesktopSettings* settings = malloc(sizeof(DesktopSettings)); DESKTOP_SETTINGS_LOAD(settings); - if (settings->sfw_mode) { + if(settings->sfw_mode) { popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59_sfw); - } - else { + } else { popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59); } popup_set_header(popup, "Saved!", 5, 7, AlignLeft, AlignTop); diff --git a/applications/main/infrared/scenes/infrared_scene_learn_done.c b/applications/main/infrared/scenes/infrared_scene_learn_done.c index ace9bb250..a66445efe 100644 --- a/applications/main/infrared/scenes/infrared_scene_learn_done.c +++ b/applications/main/infrared/scenes/infrared_scene_learn_done.c @@ -7,16 +7,14 @@ void infrared_scene_learn_done_on_enter(void* context) { DesktopSettings* settings = malloc(sizeof(DesktopSettings)); DESKTOP_SETTINGS_LOAD(settings); - if (settings->sfw_mode) { + if(settings->sfw_mode) { popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59_sfw); - if (infrared->app_state.is_learning_new_remote) { + if(infrared->app_state.is_learning_new_remote) { popup_set_header(popup, "New remote\ncreated!", 0, 0, AlignLeft, AlignTop); - } - else { + } else { popup_set_header(popup, "Saved!", 5, 7, AlignLeft, AlignTop); } - } - else { + } else { popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59); } diff --git a/applications/main/infrared/scenes/infrared_scene_learn_success.c b/applications/main/infrared/scenes/infrared_scene_learn_success.c index ed9d8ce6e..82ced17c2 100644 --- a/applications/main/infrared/scenes/infrared_scene_learn_success.c +++ b/applications/main/infrared/scenes/infrared_scene_learn_success.c @@ -50,10 +50,9 @@ void infrared_scene_learn_success_on_enter(void* context) { dialog_ex_set_left_button_text(dialog_ex, "Retry"); dialog_ex_set_right_button_text(dialog_ex, "Save"); dialog_ex_set_center_button_text(dialog_ex, "Send"); - if (settings->sfw_mode) { + if(settings->sfw_mode) { dialog_ex_set_icon(dialog_ex, 0, 1, &I_DolphinReadingSuccess_59x63_sfw); - } - else { + } else { dialog_ex_set_icon(dialog_ex, 0, 1, &I_DolphinReadingSuccess_59x63); } dialog_ex_set_result_callback(dialog_ex, infrared_scene_learn_success_dialog_result_callback); diff --git a/applications/main/infrared/scenes/infrared_scene_start.c b/applications/main/infrared/scenes/infrared_scene_start.c index 79826ede9..4d13d6e0e 100644 --- a/applications/main/infrared/scenes/infrared_scene_start.c +++ b/applications/main/infrared/scenes/infrared_scene_start.c @@ -71,7 +71,6 @@ bool infrared_scene_start_on_event(void* context, SceneManagerEvent event) { } 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( diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_clear_t5577.c b/applications/main/lfrfid/scenes/lfrfid_scene_clear_t5577.c index a95eed7db..565655080 100644 --- a/applications/main/lfrfid/scenes/lfrfid_scene_clear_t5577.c +++ b/applications/main/lfrfid/scenes/lfrfid_scene_clear_t5577.c @@ -45,10 +45,9 @@ static void lfrfid_clear_t5577_password_and_config_to_EM(LfRfid* app) { writer_initialize(t55xxtiming); popup_set_header(popup, "Removing\npassword", 90, 36, AlignCenter, AlignCenter); - if (settings->sfw_mode) { + if(settings->sfw_mode) { popup_set_icon(popup, 0, 3, &I_RFIDDolphinSend_97x61_sfw); - } - else { + } else { popup_set_icon(popup, 0, 3, &I_RFIDDolphinSend_97x61); } popup_set_text(popup, curr_buf, 90, 56, AlignCenter, AlignCenter); @@ -81,10 +80,9 @@ void lfrfid_scene_clear_t5577_on_enter(void* context) { notification_message(app->notifications, &sequence_success); popup_set_header(popup, "Done!", 94, 10, AlignCenter, AlignTop); - if (settings->sfw_mode) { + if(settings->sfw_mode) { popup_set_icon(popup, 0, 7, &I_RFIDDolphinSuccess_108x57_sfw); - } - else { + } else { popup_set_icon(popup, 0, 7, &I_RFIDDolphinSuccess_108x57); } popup_set_context(popup, app); diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_delete_success.c b/applications/main/lfrfid/scenes/lfrfid_scene_delete_success.c index 9b49614b2..94e5a684e 100644 --- a/applications/main/lfrfid/scenes/lfrfid_scene_delete_success.c +++ b/applications/main/lfrfid/scenes/lfrfid_scene_delete_success.c @@ -7,10 +7,9 @@ void lfrfid_scene_delete_success_on_enter(void* context) { DesktopSettings* settings = malloc(sizeof(DesktopSettings)); DESKTOP_SETTINGS_LOAD(settings); - if (settings->sfw_mode) { + if(settings->sfw_mode) { popup_set_icon(popup, 0, 2, &I_DolphinMafia_115x62_sfw); - } - else { + } else { popup_set_icon(popup, 0, 2, &I_DolphinMafia_115x62); } popup_set_header(popup, "Deleted", 83, 19, AlignLeft, AlignBottom); diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_emulate.c b/applications/main/lfrfid/scenes/lfrfid_scene_emulate.c index a0e9b8609..4bc3ceb22 100644 --- a/applications/main/lfrfid/scenes/lfrfid_scene_emulate.c +++ b/applications/main/lfrfid/scenes/lfrfid_scene_emulate.c @@ -19,10 +19,9 @@ void lfrfid_scene_emulate_on_enter(void* context) { AlignCenter, AlignTop); } - if (settings->sfw_mode) { + if(settings->sfw_mode) { popup_set_icon(popup, 0, 3, &I_RFIDDolphinSend_97x61_sfw); - } - else { + } else { popup_set_icon(popup, 0, 3, &I_RFIDDolphinSend_97x61); } diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_raw_read.c b/applications/main/lfrfid/scenes/lfrfid_scene_raw_read.c index 1d6a63f91..b8da7e04c 100644 --- a/applications/main/lfrfid/scenes/lfrfid_scene_raw_read.c +++ b/applications/main/lfrfid/scenes/lfrfid_scene_raw_read.c @@ -35,10 +35,9 @@ void lfrfid_scene_raw_read_on_enter(void* context) { LfRfidReadRawState* state = malloc(sizeof(LfRfidReadRawState)); scene_manager_set_scene_state(app->scene_manager, LfRfidSceneRawRead, (uint32_t)state); state->string_file_name = furi_string_alloc(); - if (settings->sfw_mode) { + if(settings->sfw_mode) { popup_set_icon(popup, 0, 3, &I_RFIDDolphinReceive_97x61_sfw); - } - else { + } else { popup_set_icon(popup, 0, 3, &I_RFIDDolphinReceive_97x61); } view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewPopup); diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_rpc.c b/applications/main/lfrfid/scenes/lfrfid_scene_rpc.c index a7161e069..4b0f52d49 100644 --- a/applications/main/lfrfid/scenes/lfrfid_scene_rpc.c +++ b/applications/main/lfrfid/scenes/lfrfid_scene_rpc.c @@ -9,10 +9,9 @@ void lfrfid_scene_rpc_on_enter(void* context) { popup_set_header(popup, "LF RFID", 89, 42, AlignCenter, AlignBottom); popup_set_text(popup, "RPC mode", 89, 44, AlignCenter, AlignTop); - if (settings->sfw_mode) { + if(settings->sfw_mode) { popup_set_icon(popup, 0, 12, &I_RFIDDolphinSend_97x61_sfw); - } - else { + } else { popup_set_icon(popup, 0, 12, &I_RFIDDolphinSend_97x61); } diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_save_success.c b/applications/main/lfrfid/scenes/lfrfid_scene_save_success.c index 4646fde49..5521bb0f7 100644 --- a/applications/main/lfrfid/scenes/lfrfid_scene_save_success.c +++ b/applications/main/lfrfid/scenes/lfrfid_scene_save_success.c @@ -9,10 +9,9 @@ void lfrfid_scene_save_success_on_enter(void* context) { // Clear state of data enter scene scene_manager_set_scene_state(app->scene_manager, LfRfidSceneSaveData, 0); - if (settings->sfw_mode) { + if(settings->sfw_mode) { popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59_sfw); - } - else { + } else { popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59); } popup_set_header(popup, "Saved!", 5, 7, AlignLeft, AlignTop); diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_write.c b/applications/main/lfrfid/scenes/lfrfid_scene_write.c index f4bd8f45a..549e2f9a3 100644 --- a/applications/main/lfrfid/scenes/lfrfid_scene_write.c +++ b/applications/main/lfrfid/scenes/lfrfid_scene_write.c @@ -36,10 +36,9 @@ void lfrfid_scene_write_on_enter(void* context) { AlignCenter, AlignTop); } - if (settings->sfw_mode) { + if(settings->sfw_mode) { popup_set_icon(popup, 0, 3, &I_RFIDDolphinSend_97x61_sfw); - } - else { + } else { popup_set_icon(popup, 0, 3, &I_RFIDDolphinSend_97x61); } diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_write_success.c b/applications/main/lfrfid/scenes/lfrfid_scene_write_success.c index 6ba138879..27552f417 100644 --- a/applications/main/lfrfid/scenes/lfrfid_scene_write_success.c +++ b/applications/main/lfrfid/scenes/lfrfid_scene_write_success.c @@ -8,10 +8,9 @@ void lfrfid_scene_write_success_on_enter(void* context) { DESKTOP_SETTINGS_LOAD(settings); popup_set_header(popup, "Successfully\nwritten!", 94, 3, AlignCenter, AlignTop); - if (settings->sfw_mode) { + if(settings->sfw_mode) { popup_set_icon(popup, 0, 6, &I_RFIDDolphinSuccess_108x57_sfw); - } - else { + } else { popup_set_icon(popup, 0, 6, &I_RFIDDolphinSuccess_108x57); } popup_set_context(popup, app); diff --git a/applications/main/nfc/nfc_cli.c b/applications/main/nfc/nfc_cli.c index c21e491e6..b2b85f6d3 100644 --- a/applications/main/nfc/nfc_cli.c +++ b/applications/main/nfc/nfc_cli.c @@ -67,7 +67,7 @@ static void nfc_cli_emulate(Cli* cli, FuriString* args) { }; while(!cli_cmd_interrupt_received(cli)) { - if (furi_hal_nfc_listen(¶ms, false, 100)) { + if(furi_hal_nfc_listen(¶ms, false, 100)) { printf("Reader detected\r\n"); furi_hal_nfc_sleep(); } diff --git a/applications/main/nfc/scenes/nfc_scene_delete_success.c b/applications/main/nfc/scenes/nfc_scene_delete_success.c index faa7fd7bb..5da15f91f 100644 --- a/applications/main/nfc/scenes/nfc_scene_delete_success.c +++ b/applications/main/nfc/scenes/nfc_scene_delete_success.c @@ -13,10 +13,9 @@ void nfc_scene_delete_success_on_enter(void* context) { // Setup view Popup* popup = nfc->popup; - if (settings->sfw_mode) { + if(settings->sfw_mode) { popup_set_icon(popup, 0, 2, &I_DolphinMafia_115x62_sfw); - } - else { + } else { popup_set_icon(popup, 0, 2, &I_DolphinMafia_115x62); } popup_set_header(popup, "Deleted", 83, 19, AlignLeft, AlignBottom); diff --git a/applications/main/nfc/scenes/nfc_scene_emulate_uid.c b/applications/main/nfc/scenes/nfc_scene_emulate_uid.c index eec43c92c..e935ad18c 100644 --- a/applications/main/nfc/scenes/nfc_scene_emulate_uid.c +++ b/applications/main/nfc/scenes/nfc_scene_emulate_uid.c @@ -40,10 +40,9 @@ static void nfc_scene_emulate_uid_widget_config(Nfc* nfc, bool data_received) { DesktopSettings* settings = malloc(sizeof(DesktopSettings)); DESKTOP_SETTINGS_LOAD(settings); - if (settings->sfw_mode) { + if(settings->sfw_mode) { widget_add_icon_element(widget, 0, 3, &I_NFC_dolphin_emulation_47x61_sfw); - } - else { + } else { widget_add_icon_element(widget, 0, 3, &I_NFC_dolphin_emulation_47x61); } widget_add_string_element(widget, 57, 13, AlignLeft, AlignTop, FontPrimary, "Emulating UID"); diff --git a/applications/main/nfc/scenes/nfc_scene_mf_classic_emulate.c b/applications/main/nfc/scenes/nfc_scene_mf_classic_emulate.c index 0fa624ad9..3a0b597e9 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_classic_emulate.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_classic_emulate.c @@ -26,10 +26,9 @@ void nfc_scene_mf_classic_emulate_on_enter(void* context) { } else { nfc_text_store_set(nfc, "MIFARE\nClassic"); } - if (settings->sfw_mode) { + if(settings->sfw_mode) { popup_set_icon(popup, 0, 3, &I_NFC_dolphin_emulation_47x61_sfw); - } - else { + } else { popup_set_icon(popup, 0, 3, &I_NFC_dolphin_emulation_47x61); } popup_set_text(popup, nfc->text_store, 90, 28, AlignCenter, AlignTop); diff --git a/applications/main/nfc/scenes/nfc_scene_mf_classic_update_success.c b/applications/main/nfc/scenes/nfc_scene_mf_classic_update_success.c index a76a758b6..9bd354c85 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_classic_update_success.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_classic_update_success.c @@ -16,10 +16,9 @@ void nfc_scene_mf_classic_update_success_on_enter(void* context) { notification_message(nfc->notifications, &sequence_success); Popup* popup = nfc->popup; - if (settings->sfw_mode) { + if(settings->sfw_mode) { popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59_sfw); - } - else { + } else { popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59); } popup_set_header(popup, "Updated!", 11, 20, AlignLeft, AlignBottom); diff --git a/applications/main/nfc/scenes/nfc_scene_mf_classic_write_success.c b/applications/main/nfc/scenes/nfc_scene_mf_classic_write_success.c index e425d8c3a..25656c072 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_classic_write_success.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_classic_write_success.c @@ -16,10 +16,9 @@ void nfc_scene_mf_classic_write_success_on_enter(void* context) { notification_message(nfc->notifications, &sequence_success); Popup* popup = nfc->popup; - if (settings->sfw_mode) { + if(settings->sfw_mode) { popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59_sfw); - } - else { + } else { popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59); } popup_set_header(popup, "Successfully\nwritten", 13, 22, AlignLeft, AlignBottom); diff --git a/applications/main/nfc/scenes/nfc_scene_mf_ultralight_emulate.c b/applications/main/nfc/scenes/nfc_scene_mf_ultralight_emulate.c index 4dc35c68d..e46609c08 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_ultralight_emulate.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_ultralight_emulate.c @@ -114,10 +114,9 @@ void nfc_scene_mf_ultralight_emulate_on_enter(void* context) { } else { nfc_text_store_set(nfc, "MIFARE\nNTAG"); } - if (settings->sfw_mode) { + if(settings->sfw_mode) { popup_set_icon(popup, 0, 3, &I_NFC_dolphin_emulation_47x61_sfw); - } - else { + } else { popup_set_icon(popup, 0, 3, &I_NFC_dolphin_emulation_47x61); } popup_set_text(popup, nfc->text_store, 90, 28, AlignCenter, AlignTop); diff --git a/applications/main/nfc/scenes/nfc_scene_passport_auth.c b/applications/main/nfc/scenes/nfc_scene_passport_auth.c index c90c38233..7bb13e1a1 100644 --- a/applications/main/nfc/scenes/nfc_scene_passport_auth.c +++ b/applications/main/nfc/scenes/nfc_scene_passport_auth.c @@ -107,7 +107,7 @@ void nfc_scene_passport_auth_on_enter(void* context) { item = variable_item_list_add(variable_item_list, "Document Nr.", 1, NULL, NULL); strncpy(temp_str, mrtd_data->auth.doc_number, temp_str_size); - temp_str[temp_str_size -1] = '\x00'; + temp_str[temp_str_size - 1] = '\x00'; if(strlen(temp_str) > 8) { temp_str[8] = '.'; temp_str[9] = '.'; diff --git a/applications/main/nfc/scenes/nfc_scene_passport_date.c b/applications/main/nfc/scenes/nfc_scene_passport_date.c index 6655bdd59..4594721df 100644 --- a/applications/main/nfc/scenes/nfc_scene_passport_date.c +++ b/applications/main/nfc/scenes/nfc_scene_passport_date.c @@ -31,7 +31,6 @@ void nfc_scene_passport_date_on_enter(void* context) { date_value.month = 0; date_value.day = 0; - switch(date_type) { case NFC_PASSPORT_DATE_BIRTH: text_input_set_header_text(text_input, "Birth Date"); diff --git a/applications/main/nfc/scenes/nfc_scene_restore_original.c b/applications/main/nfc/scenes/nfc_scene_restore_original.c index 3709008fd..b87c2f790 100644 --- a/applications/main/nfc/scenes/nfc_scene_restore_original.c +++ b/applications/main/nfc/scenes/nfc_scene_restore_original.c @@ -13,10 +13,9 @@ void nfc_scene_restore_original_on_enter(void* context) { // Setup view Popup* popup = nfc->popup; - if (settings->sfw_mode) { + if(settings->sfw_mode) { popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59_sfw); - } - else { + } else { popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59); } popup_set_header(popup, "Original file\nrestored", 13, 22, AlignLeft, AlignBottom); diff --git a/applications/main/nfc/scenes/nfc_scene_rpc.c b/applications/main/nfc/scenes/nfc_scene_rpc.c index edf63faf4..9bd55577d 100644 --- a/applications/main/nfc/scenes/nfc_scene_rpc.c +++ b/applications/main/nfc/scenes/nfc_scene_rpc.c @@ -10,10 +10,9 @@ void nfc_scene_rpc_on_enter(void* context) { popup_set_header(popup, "NFC", 89, 42, AlignCenter, AlignBottom); popup_set_text(popup, "RPC mode", 89, 44, AlignCenter, AlignTop); - if (settings->sfw_mode) { + if(settings->sfw_mode) { popup_set_icon(popup, 0, 12, &I_NFC_dolphin_emulation_47x61_sfw); - } - else { + } else { popup_set_icon(popup, 0, 12, &I_NFC_dolphin_emulation_47x61); } diff --git a/applications/main/nfc/scenes/nfc_scene_save_success.c b/applications/main/nfc/scenes/nfc_scene_save_success.c index 67dd4a6dd..58b7d1bf4 100644 --- a/applications/main/nfc/scenes/nfc_scene_save_success.c +++ b/applications/main/nfc/scenes/nfc_scene_save_success.c @@ -13,10 +13,9 @@ void nfc_scene_save_success_on_enter(void* context) { // Setup view Popup* popup = nfc->popup; - if (settings->sfw_mode) { + if(settings->sfw_mode) { popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59_sfw); - } - else { + } else { popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59); } popup_set_header(popup, "Saved!", 13, 22, AlignLeft, AlignBottom); diff --git a/applications/main/sub_playlist/playlist.c b/applications/main/sub_playlist/playlist.c index b11dae31e..7bf433d09 100644 --- a/applications/main/sub_playlist/playlist.c +++ b/applications/main/sub_playlist/playlist.c @@ -683,7 +683,8 @@ int32_t playlist_app(void* p) { dialog_file_browser_set_basic_options(&browser_options, PLAYLIST_EXT, &I_sub1_10px); browser_options.base_path = PLAYLIST_FOLDER; - bool res = dialog_file_browser_show(dialogs, app->file_path, app->file_path, &browser_options); + bool res = + dialog_file_browser_show(dialogs, app->file_path, app->file_path, &browser_options); furi_record_close(RECORD_DIALOGS); // check if a file was selected diff --git a/applications/main/subghz/scenes/subghz_scene_delete_success.c b/applications/main/subghz/scenes/subghz_scene_delete_success.c index e10d28a21..e30eda785 100644 --- a/applications/main/subghz/scenes/subghz_scene_delete_success.c +++ b/applications/main/subghz/scenes/subghz_scene_delete_success.c @@ -15,10 +15,9 @@ void subghz_scene_delete_success_on_enter(void* context) { // Setup view Popup* popup = subghz->popup; - if (settings->sfw_mode) { + if(settings->sfw_mode) { popup_set_icon(popup, 0, 2, &I_DolphinMafia_115x62_sfw); - } - else { + } else { popup_set_icon(popup, 0, 2, &I_DolphinMafia_115x62); } popup_set_header(popup, "Deleted", 83, 19, AlignLeft, AlignBottom); diff --git a/applications/main/subghz/scenes/subghz_scene_rpc.c b/applications/main/subghz/scenes/subghz_scene_rpc.c index e78e7fa71..12a5787ad 100644 --- a/applications/main/subghz/scenes/subghz_scene_rpc.c +++ b/applications/main/subghz/scenes/subghz_scene_rpc.c @@ -16,10 +16,9 @@ void subghz_scene_rpc_on_enter(void* context) { popup_set_header(popup, "Sub-GHz", 89, 42, AlignCenter, AlignBottom); popup_set_text(popup, "RPC mode", 89, 44, AlignCenter, AlignTop); - if (settings->sfw_mode) { + if(settings->sfw_mode) { popup_set_icon(popup, 0, 12, &I_RFIDDolphinSend_97x61_sfw); - } - else { + } else { popup_set_icon(popup, 0, 12, &I_RFIDDolphinSend_97x61); } diff --git a/applications/main/subghz/scenes/subghz_scene_save_success.c b/applications/main/subghz/scenes/subghz_scene_save_success.c index 4f36a0938..76e30d088 100644 --- a/applications/main/subghz/scenes/subghz_scene_save_success.c +++ b/applications/main/subghz/scenes/subghz_scene_save_success.c @@ -14,10 +14,9 @@ void subghz_scene_save_success_on_enter(void* context) { // Setup view Popup* popup = subghz->popup; - if (settings->sfw_mode) { + if(settings->sfw_mode) { popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59_sfw); - } - else { + } else { popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59); } popup_set_header(popup, "Saved!", 13, 22, AlignLeft, AlignBottom); diff --git a/applications/main/subghz/subghz_cli.c b/applications/main/subghz/subghz_cli.c index d2c999a8d..ed1648083 100644 --- a/applications/main/subghz/subghz_cli.c +++ b/applications/main/subghz/subghz_cli.c @@ -659,18 +659,14 @@ static void subghz_cli_command_chat(Cli* cli, FuriString* args, void* context) { notification_message(notification, &sequence_single_vibro); break; case SubGhzChatEventUserEntrance: - furi_string_printf( - sysmsg, - "%s joined chat.\r\n", - furi_hal_version_get_name_ptr()); + furi_string_printf(sysmsg, "%s joined chat.\r\n", furi_hal_version_get_name_ptr()); subghz_chat_worker_write( subghz_chat, (uint8_t*)furi_string_get_cstr(sysmsg), strlen(furi_string_get_cstr(sysmsg))); break; case SubGhzChatEventUserExit: - furi_string_printf( - sysmsg, "%s left chat.\r\n", furi_hal_version_get_name_ptr()); + furi_string_printf(sysmsg, "%s left chat.\r\n", furi_hal_version_get_name_ptr()); subghz_chat_worker_write( subghz_chat, (uint8_t*)furi_string_get_cstr(sysmsg), @@ -768,7 +764,7 @@ void subghz_on_system_start() { cli_add_command(cli, "subghz", CliCommandFlagDefault, subghz_cli_command, NULL); // psst RM... i know you dont care much about errors, but if you ever see this... incompatible pointer type :3 - cli_add_command(cli, "chat", CliCommandFlagDefault, subghz_cli_command_chat, NULL); + cli_add_command(cli, "chat", CliCommandFlagDefault, subghz_cli_command_chat, NULL); furi_record_close(RECORD_CLI); #else diff --git a/applications/main/subghz/views/receiver.c b/applications/main/subghz/views/receiver.c index 77f4d2074..637ca8632 100644 --- a/applications/main/subghz/views/receiver.c +++ b/applications/main/subghz/views/receiver.c @@ -234,10 +234,9 @@ void subghz_view_receiver_draw(Canvas* canvas, SubGhzViewReceiverModel* model) { if(model->history_item == 0) { if(model->mode == SubGhzViewReceiverModeLive) { - if (settings->sfw_mode) { + if(settings->sfw_mode) { canvas_draw_icon(canvas, 0, 0, &I_Scanning_123x52_sfw); - } - else { + } else { canvas_draw_icon(canvas, 0, 0, &I_Scanning_123x52); } canvas_set_font(canvas, FontPrimary); @@ -245,10 +244,9 @@ void subghz_view_receiver_draw(Canvas* canvas, SubGhzViewReceiverModel* model) { canvas_draw_line(canvas, 46, 51, 125, 51); canvas_set_font(canvas, FontSecondary); } else { - if (settings->sfw_mode) { + if(settings->sfw_mode) { canvas_draw_icon(canvas, 0, 0, &I_Scanning_123x52_sfw); - } - else { + } else { canvas_draw_icon(canvas, 0, 0, &I_Scanning_123x52); } canvas_set_font(canvas, FontPrimary); diff --git a/applications/main/u2f/scenes/u2f_scene_error.c b/applications/main/u2f/scenes/u2f_scene_error.c index 20b7be952..a4cfd3819 100644 --- a/applications/main/u2f/scenes/u2f_scene_error.c +++ b/applications/main/u2f/scenes/u2f_scene_error.c @@ -29,7 +29,7 @@ void u2f_scene_error_on_enter(void* context) { app->widget, GuiButtonTypeLeft, "Back", u2f_scene_error_event_callback, app); } else if(app->error == U2fAppErrorCloseRpc) { widget_add_icon_element(app->widget, 78, 0, &I_ActiveConnection_50x64); - if (settings->sfw_mode) { + if(settings->sfw_mode) { widget_add_string_multiline_element( app->widget, 3, 2, AlignLeft, AlignTop, FontPrimary, "Connection\nis active!"); widget_add_string_multiline_element( @@ -40,8 +40,7 @@ void u2f_scene_error_on_enter(void* context) { AlignTop, FontSecondary, "Disconnect from\nPC or phone to\nuse this function."); - } - else { + } else { widget_add_string_multiline_element( app->widget, 3, 2, AlignLeft, AlignTop, FontPrimary, "I am not\na whore!"); widget_add_string_multiline_element( diff --git a/applications/main/u2f/u2f.c b/applications/main/u2f/u2f.c index f4197dd74..ff90329c5 100644 --- a/applications/main/u2f/u2f.c +++ b/applications/main/u2f/u2f.c @@ -64,13 +64,13 @@ typedef struct { static const uint8_t ver_str[] = {"U2F_V2"}; // NFC applet selection fields -static const uint8_t rid_ac_ax[] = { 0xA0, 0x00, 0x00, 0x06, 0x47, 0x2F, 0x00, 0x01 }; +static const uint8_t rid_ac_ax[] = {0xA0, 0x00, 0x00, 0x06, 0x47, 0x2F, 0x00, 0x01}; static const uint8_t state_no_error[] = {0x90, 0x00}; static const uint8_t state_not_supported[] = {0x6D, 0x00}; static const uint8_t state_user_missing[] = {0x69, 0x85}; static const uint8_t state_wrong_data[] = {0x6A, 0x80}; -static const uint8_t state_app_not_found[] = { 0x6A, 0x82 }; +static const uint8_t state_app_not_found[] = {0x6A, 0x82}; struct U2fData { uint8_t device_key[32]; @@ -86,10 +86,9 @@ struct U2fData { static void* apdu_command_data(U2fApduCommand* cmd) { // Short encoding is a single byte. // Extended length encoding is 0 byte followed by MSB and LSB bytes. - if (cmd->len[0] == 0) { + if(cmd->len[0] == 0) { return cmd->len + 3; - } - else { + } else { return cmd->len + 1; } } @@ -278,7 +277,7 @@ static uint16_t u2f_authenticate(U2fData* U2F, const uint8_t* in_buf, uint8_t* o if(U2F->user_present == true) { flags |= 1; } else { - if (cmd->p1 == U2fEnforce) { + if(cmd->p1 == U2fEnforce) { memcpy(&out_buf[0], state_user_missing, 2); return 2; } @@ -314,7 +313,7 @@ static uint16_t u2f_authenticate(U2fData* U2F, const uint8_t* in_buf, uint8_t* o return 2; } - if (cmd->p1 == U2fCheckOnly) { // Check-only: don't need to send full response + if(cmd->p1 == U2fCheckOnly) { // Check-only: don't need to send full response memcpy(&out_buf[0], state_user_missing, 2); return 2; } @@ -352,7 +351,7 @@ uint16_t u2f_applet_selection(const uint8_t* in_buf, uint8_t* out_buf) { data[6], data[7]); - if (cmd->len[0] != 8 || memcmp(rid_ac_ax, data, 8) != 0) { + if(cmd->len[0] != 8 || memcmp(rid_ac_ax, data, 8) != 0) { memcpy(&out_buf[0], state_app_not_found, 2); return 2; } @@ -364,24 +363,20 @@ uint16_t u2f_applet_selection(const uint8_t* in_buf, uint8_t* out_buf) { uint16_t u2f_msg_parse(U2fData* U2F, const uint8_t* in_buf, uint16_t in_len, uint8_t* out_buf) { furi_assert(U2F); - if (!U2F->ready) return 0; - if ((in_buf[0] != 0x00) && (in_len < 5)) return 0; + if(!U2F->ready) return 0; + if((in_buf[0] != 0x00) && (in_len < 5)) return 0; FURI_LOG_D(TAG, "ins=0x%02x", in_buf[1]); - if (in_buf[1] == U2F_CMD_REGISTER) { // Register request + if(in_buf[1] == U2F_CMD_REGISTER) { // Register request return u2f_register(U2F, in_buf, out_buf); - } - else if (in_buf[1] == U2F_CMD_AUTHENTICATE) { // Authenticate request + } else if(in_buf[1] == U2F_CMD_AUTHENTICATE) { // Authenticate request return u2f_authenticate(U2F, in_buf, out_buf); - } - else if (in_buf[1] == U2F_CMD_VERSION) { // Get U2F version string + } else if(in_buf[1] == U2F_CMD_VERSION) { // Get U2F version string memcpy(&out_buf[0], ver_str, 6); memcpy(&out_buf[6], state_no_error, 2); return 8; - } - else if (in_buf[1] == U2F_CMD_APPLET_SELECTION) { + } else if(in_buf[1] == U2F_CMD_APPLET_SELECTION) { return u2f_applet_selection(in_buf, out_buf); - } - else { + } else { memcpy(&out_buf[0], state_not_supported, 2); return 2; } @@ -389,15 +384,14 @@ uint16_t u2f_msg_parse(U2fData* U2F, const uint8_t* in_buf, uint16_t in_len, uin } void u2f_wink(U2fData* U2F) { - if (U2F->callback != NULL) U2F->callback(U2fNotifyWink, U2F->context); + if(U2F->callback != NULL) U2F->callback(U2fNotifyWink, U2F->context); } void u2f_set_state(U2fData* U2F, uint8_t state) { - if (state == 0) { - if (U2F->callback != NULL) U2F->callback(U2fNotifyDisconnect, U2F->context); - } - else { - if (U2F->callback != NULL) U2F->callback(U2fNotifyConnect, U2F->context); + if(state == 0) { + if(U2F->callback != NULL) U2F->callback(U2fNotifyDisconnect, U2F->context); + } else { + if(U2F->callback != NULL) U2F->callback(U2fNotifyConnect, U2F->context); } U2F->user_present = false; } diff --git a/applications/main/u2f/u2f_nfc.c b/applications/main/u2f/u2f_nfc.c index 9ee97ad2a..8c0439982 100644 --- a/applications/main/u2f/u2f_nfc.c +++ b/applications/main/u2f/u2f_nfc.c @@ -18,10 +18,10 @@ struct U2fNfc { }; static uint16_t -u2f_callback(U2fNfc* u2f_nfc, const uint8_t* buff_rx, uint16_t buff_rx_len, uint8_t* buff_tx) { + u2f_callback(U2fNfc* u2f_nfc, const uint8_t* buff_rx, uint16_t buff_rx_len, uint8_t* buff_tx) { U2fApduCommand* cmd = (U2fApduCommand*)buff_rx; - if (cmd->ins == 0xC0) { - if (u2f_nfc->payload_len == 0) { + if(cmd->ins == 0xC0) { + if(u2f_nfc->payload_len == 0) { FURI_LOG_E(TAG, "requested block but not chaining"); buff_tx[0] = 0x69; buff_tx[1] = 0x00; @@ -31,25 +31,23 @@ u2f_callback(U2fNfc* u2f_nfc, const uint8_t* buff_rx, uint16_t buff_rx_len, uint FURI_LOG_T(TAG, "continued chaining %d/%d", u2f_nfc->payload_cursor, u2f_nfc->payload_len); uint16_t max_resp_len = cmd->len[0]; - if (max_resp_len == 0) { + if(max_resp_len == 0) { max_resp_len = 256; } uint16_t remaining_len = (u2f_nfc->payload_len - 2) - u2f_nfc->payload_cursor; - if (remaining_len > max_resp_len) { + if(remaining_len > max_resp_len) { memcpy(buff_tx, &u2f_nfc->payload[u2f_nfc->payload_cursor], max_resp_len); remaining_len -= max_resp_len; buff_tx[max_resp_len] = 0x61; - if (remaining_len >= 256) { + if(remaining_len >= 256) { buff_tx[max_resp_len + 1] = 0x00; - } - else { + } else { buff_tx[max_resp_len + 1] = remaining_len; } u2f_nfc->payload_cursor += max_resp_len; return max_resp_len + 2; - } - else { + } else { memcpy( buff_tx, &u2f_nfc->payload[u2f_nfc->payload_cursor], @@ -66,7 +64,7 @@ u2f_callback(U2fNfc* u2f_nfc, const uint8_t* buff_rx, uint16_t buff_rx_len, uint u2f_msg_parse(u2f_nfc->u2f_instance, buff_rx, buff_rx_len, u2f_nfc->payload); // If this is extended format, send entire response at once - if (cmd->len[0] == 0) { + if(cmd->len[0] == 0) { FURI_LOG_T(TAG, "single extended response"); memcpy(&buff_tx, u2f_nfc->payload, u2f_nfc->payload_len); uint16_t len = u2f_nfc->payload_len; @@ -78,21 +76,19 @@ u2f_callback(U2fNfc* u2f_nfc, const uint8_t* buff_rx, uint16_t buff_rx_len, uint uint16_t max_resp_len = 256; // If this message happens to be less than the chaining size, send it all at once. - if ((u2f_nfc->payload_len - 2) <= max_resp_len) { + if((u2f_nfc->payload_len - 2) <= max_resp_len) { FURI_LOG_T(TAG, "single short response"); memcpy(buff_tx, u2f_nfc->payload, u2f_nfc->payload_len); uint16_t len = u2f_nfc->payload_len; u2f_nfc->payload_len = 0; return len; - } - else { + } else { memcpy(buff_tx, u2f_nfc->payload, max_resp_len); buff_tx[max_resp_len] = 0x61; uint16_t remaining_len = (u2f_nfc->payload_len - 2) - max_resp_len; - if (remaining_len >= max_resp_len) { + if(remaining_len >= max_resp_len) { buff_tx[max_resp_len + 1] = 0x00; - } - else { + } else { buff_tx[max_resp_len + 1] = remaining_len; } u2f_nfc->payload_cursor = max_resp_len; @@ -105,7 +101,7 @@ u2f_callback(U2fNfc* u2f_nfc, const uint8_t* buff_rx, uint16_t buff_rx_len, uint static int32_t u2f_nfc_worker(void* context) { U2fNfc* u2f_nfc = context; FURI_LOG_D(TAG, "Init"); - while (furi_hal_nfc_is_busy()) { + while(furi_hal_nfc_is_busy()) { furi_delay_ms(10); } FuriHalNfcDevData params = { @@ -122,36 +118,35 @@ static int32_t u2f_nfc_worker(void* context) { FURI_LOG_D(TAG, "Start"); - while (1) { + while(1) { uint32_t flags = furi_thread_flags_wait(WorkerEvtStop, FuriFlagWaitAny, 10); - if (flags != FuriFlagErrorTimeout) { + if(flags != FuriFlagErrorTimeout) { furi_check((flags & FuriFlagError) == 0); - if (flags & WorkerEvtStop) break; + if(flags & WorkerEvtStop) break; } - if (!furi_hal_nfc_listen(¶ms, false, 200)) { + if(!furi_hal_nfc_listen(¶ms, false, 200)) { FURI_LOG_T(TAG, "wtf"); continue; } FuriHalNfcTxRxContext tx_rx = {}; tx_rx.tx_bits = 0; tx_rx.tx_rx_type = FuriHalNfcTxRxTypeDefault; - if (!furi_hal_nfc_tx_rx(&tx_rx, 300)) continue; - if (tx_rx.rx_bits == 0) continue; + if(!furi_hal_nfc_tx_rx(&tx_rx, 300)) continue; + if(tx_rx.rx_bits == 0) continue; u2f_nfc->payload_len = 0; u2f_nfc->payload_cursor = 0; - while (true) { + while(true) { uint16_t payload_len = u2f_callback(u2f_nfc, tx_rx.rx_data, tx_rx.rx_bits / 8, tx_rx.tx_data); tx_rx.rx_bits = 0; FURI_LOG_T(TAG, "payload_len=%d", payload_len); - if (payload_len == 0) { + if(payload_len == 0) { break; - } - else { + } else { tx_rx.tx_bits = payload_len * 8; tx_rx.tx_rx_type = FuriHalNfcTxRxTypeDefault; - if (!furi_hal_nfc_tx_rx(&tx_rx, 300)) break; - if (tx_rx.rx_bits == 0) break; + if(!furi_hal_nfc_tx_rx(&tx_rx, 300)) break; + if(tx_rx.rx_bits == 0) break; } } } diff --git a/applications/main/u2f/u2f_nfc.h b/applications/main/u2f/u2f_nfc.h index c3018f601..3ac9186f7 100644 --- a/applications/main/u2f/u2f_nfc.h +++ b/applications/main/u2f/u2f_nfc.h @@ -6,11 +6,11 @@ extern "C" { #include "u2f.h" - typedef struct U2fNfc U2fNfc; +typedef struct U2fNfc U2fNfc; - U2fNfc* u2f_nfc_start(U2fData* u2f_inst); +U2fNfc* u2f_nfc_start(U2fData* u2f_inst); - void u2f_nfc_stop(U2fNfc* u2f_hid); +void u2f_nfc_stop(U2fNfc* u2f_hid); #ifdef __cplusplus } diff --git a/applications/main/u2f/views/u2f_view.c b/applications/main/u2f/views/u2f_view.c index af55ea7ce..77b6a288e 100644 --- a/applications/main/u2f/views/u2f_view.c +++ b/applications/main/u2f/views/u2f_view.c @@ -18,70 +18,66 @@ static void u2f_view_draw_callback(Canvas* canvas, void* _model) { DesktopSettings* settings = malloc(sizeof(DesktopSettings)); DESKTOP_SETTINGS_LOAD(settings); - canvas_draw_icon(canvas, 8, 14, &I_Drive_112x35); canvas_set_font(canvas, FontSecondary); - if (model->display_msg == U2fMsgNotConnected) { - if (settings->sfw_mode) { + if(model->display_msg == U2fMsgNotConnected) { + if(settings->sfw_mode) { canvas_draw_icon(canvas, 22, 15, &I_Connect_me_62x31_sfw); - canvas_draw_str_aligned(canvas, 128 / 2, 3, AlignCenter, AlignTop, "Connect to a device"); - } - else { + canvas_draw_str_aligned( + canvas, 128 / 2, 3, AlignCenter, AlignTop, "Connect to a device"); + } else { canvas_draw_icon(canvas, 22, 15, &I_Connect_me_62x31); - canvas_draw_str_aligned(canvas, 128 / 2, 3, AlignCenter, AlignTop, "Plug me in d-daddy"); + canvas_draw_str_aligned( + canvas, 128 / 2, 3, AlignCenter, AlignTop, "Plug me in d-daddy"); } - } - else if (model->display_msg == U2fMsgIdle) { - if (settings->sfw_mode) { + } else if(model->display_msg == U2fMsgIdle) { + if(settings->sfw_mode) { canvas_draw_icon(canvas, 22, 15, &I_Connected_62x31_sfw); canvas_draw_str_aligned(canvas, 128 / 2, 3, AlignCenter, AlignTop, "Connected!"); - } - else { + } else { canvas_draw_icon(canvas, 22, 15, &I_Connected_62x31); canvas_draw_str_aligned(canvas, 128 / 2, 3, AlignCenter, AlignTop, "Connected!"); } - } - else if (model->display_msg == U2fMsgRegister) { - if (settings->sfw_mode) { + } else if(model->display_msg == U2fMsgRegister) { + if(settings->sfw_mode) { elements_button_center(canvas, "OK"); canvas_draw_icon(canvas, 22, 15, &I_Auth_62x31_sfw); - canvas_draw_str_aligned(canvas, 128 / 2, 3, AlignCenter, AlignTop, "Press OK to register"); - } - else { + canvas_draw_str_aligned( + canvas, 128 / 2, 3, AlignCenter, AlignTop, "Press OK to register"); + } else { elements_button_center(canvas, "CUM"); canvas_draw_icon(canvas, 22, 15, &I_Auth_62x31); - canvas_draw_str_aligned(canvas, 128 / 2, 3, AlignCenter, AlignTop, "Press CUM to register"); + canvas_draw_str_aligned( + canvas, 128 / 2, 3, AlignCenter, AlignTop, "Press CUM to register"); } - } - else if (model->display_msg == U2fMsgAuth) { - if (settings->sfw_mode) { + } else if(model->display_msg == U2fMsgAuth) { + if(settings->sfw_mode) { elements_button_center(canvas, "OK"); canvas_draw_icon(canvas, 22, 15, &I_Auth_62x31_sfw); - canvas_draw_str_aligned(canvas, 128 / 2, 3, AlignCenter, AlignTop, "Press OK to authenticate"); - } - else { + canvas_draw_str_aligned( + canvas, 128 / 2, 3, AlignCenter, AlignTop, "Press OK to authenticate"); + } else { elements_button_center(canvas, "CUM"); canvas_draw_icon(canvas, 22, 15, &I_Auth_62x31); - canvas_draw_str_aligned(canvas, 128 / 2, 3, AlignCenter, AlignTop, "Press CUM to authenticate"); + canvas_draw_str_aligned( + canvas, 128 / 2, 3, AlignCenter, AlignTop, "Press CUM to authenticate"); } - } - else if (model->display_msg == U2fMsgSuccess) { - if (settings->sfw_mode) { + } else if(model->display_msg == U2fMsgSuccess) { + if(settings->sfw_mode) { canvas_draw_icon(canvas, 22, 15, &I_Connected_62x31_sfw); - canvas_draw_str_aligned(canvas, 128 / 2, 3, AlignCenter, AlignTop, "Authentication successful!"); - } - else { + canvas_draw_str_aligned( + canvas, 128 / 2, 3, AlignCenter, AlignTop, "Authentication successful!"); + } else { canvas_draw_icon(canvas, 22, 15, &I_Connected_62x31); canvas_draw_str_aligned(canvas, 128 / 2, 3, AlignCenter, AlignTop, "Cum released~"); } - } - else if (model->display_msg == U2fMsgError) { - if (settings->sfw_mode) { + } else if(model->display_msg == U2fMsgError) { + if(settings->sfw_mode) { canvas_draw_icon(canvas, 22, 15, &I_Error_62x31_sfw); - canvas_draw_str_aligned(canvas, 128 / 2, 3, AlignCenter, AlignTop, "Certificate error"); - } - else { + canvas_draw_str_aligned( + canvas, 128 / 2, 3, AlignCenter, AlignTop, "Certificate error"); + } else { canvas_draw_icon(canvas, 22, 15, &I_Error_62x31); canvas_draw_str_aligned(canvas, 128 / 2, 3, AlignCenter, AlignTop, "Unable to cum"); } @@ -94,10 +90,10 @@ static bool u2f_view_input_callback(InputEvent* event, void* context) { U2fView* u2f = context; bool consumed = false; - if (event->type == InputTypeShort) { - if (event->key == InputKeyOk) { + if(event->type == InputTypeShort) { + if(event->key == InputKeyOk) { consumed = true; - if (u2f->callback != NULL) u2f->callback(InputTypeShort, u2f->context); + if(u2f->callback != NULL) u2f->callback(InputTypeShort, u2f->context); } } diff --git a/applications/plugins/arkanoid/arkanoid_game.c b/applications/plugins/arkanoid/arkanoid_game.c index 2e859afe8..af9976c98 100644 --- a/applications/plugins/arkanoid/arkanoid_game.c +++ b/applications/plugins/arkanoid/arkanoid_game.c @@ -277,7 +277,7 @@ void reset_level(Canvas* canvas, ArkanoidState* arkanoid_state) { arkanoid_state->brickCount = 0; arkanoid_state->ball_state.released = false; arkanoid_state->gameStarted = false; - + // Reset all brick hit states for(unsigned int row = 0; row < arkanoid_state->ROWS; row++) { for(unsigned int column = 0; column < arkanoid_state->COLUMNS; column++) { diff --git a/applications/plugins/asteroids/app.c b/applications/plugins/asteroids/app.c index 1a3945fd7..07be54c3d 100644 --- a/applications/plugins/asteroids/app.c +++ b/applications/plugins/asteroids/app.c @@ -32,42 +32,42 @@ /* ============================ Data structures ============================= */ typedef struct Ship { - float x, /* Ship x position. */ - y, /* Ship y position. */ - vx, /* x velocity. */ - vy, /* y velocity. */ - rot; /* Current rotation. 2*PI full rotation. */ + float x, /* Ship x position. */ + y, /* Ship y position. */ + vx, /* x velocity. */ + vy, /* y velocity. */ + rot; /* Current rotation. 2*PI full rotation. */ } Ship; typedef struct Bullet { - float x, y, vx, vy; /* Fields like in ship. */ - uint32_t ttl; /* Time to live, in ticks. */ + float x, y, vx, vy; /* Fields like in ship. */ + uint32_t ttl; /* Time to live, in ticks. */ } Bullet; typedef struct Asteroid { - float x, y, vx, vy, rot, /* Fields like ship. */ - rot_speed, /* Angular velocity (rot speed and sense). */ - size; /* Asteroid size. */ - uint8_t shape_seed; /* Seed to give random shape. */ + float x, y, vx, vy, rot, /* Fields like ship. */ + rot_speed, /* Angular velocity (rot speed and sense). */ + size; /* Asteroid size. */ + uint8_t shape_seed; /* Seed to give random shape. */ } Asteroid; -#define MAXBUL 10 /* Max bullets on the screen. */ -#define MAXAST 32 /* Max asteroids on the screen. */ +#define MAXBUL 10 /* Max bullets on the screen. */ +#define MAXAST 32 /* Max asteroids on the screen. */ #define SHIP_HIT_ANIMATION_LEN 15 typedef struct AsteroidsApp { /* GUI */ - Gui *gui; - ViewPort *view_port; /* We just use a raw viewport and we render + Gui* gui; + ViewPort* view_port; /* We just use a raw viewport and we render everything into the low level canvas. */ - FuriMessageQueue *event_queue; /* Key press events go here. */ + FuriMessageQueue* event_queue; /* Key press events go here. */ /* Game state. */ - int running; /* Once false exists the app. */ - bool gameover; /* Game over status. */ - uint32_t ticks; /* Game ticks. Increments at each refresh. */ - uint32_t score; /* Game score. */ - uint32_t lives; /* Number of lives in the current game. */ - uint32_t ship_hit; /* When non zero, the ship was hit by an asteroid + int running; /* Once false exists the app. */ + bool gameover; /* Game over status. */ + uint32_t ticks; /* Game ticks. Increments at each refresh. */ + uint32_t score; /* Game score. */ + uint32_t lives; /* Number of lives in the current game. */ + uint32_t ship_hit; /* When non zero, the ship was hit by an asteroid and we need to show an animation as long as its value is non-zero (and decrease it's value at each tick of animation). */ @@ -76,26 +76,26 @@ typedef struct AsteroidsApp { struct Ship ship; /* Bullets state. */ - struct Bullet bullets[MAXBUL]; /* Each bullet state. */ - int bullets_num; /* Active bullets. */ - uint32_t last_bullet_tick; /* Tick the last bullet was fired. */ + struct Bullet bullets[MAXBUL]; /* Each bullet state. */ + int bullets_num; /* Active bullets. */ + uint32_t last_bullet_tick; /* Tick the last bullet was fired. */ /* Asteroids state. */ - Asteroid asteroids[MAXAST]; /* Each asteroid state. */ - int asteroids_num; /* Active asteroids. */ + Asteroid asteroids[MAXAST]; /* Each asteroid state. */ + int asteroids_num; /* Active asteroids. */ uint32_t pressed[InputKeyMAX]; /* pressed[id] is true if pressed. Each array item contains the time in milliseconds the key was pressed. */ - bool fire; /* Short press detected: fire a bullet. */ + bool fire; /* Short press detected: fire a bullet. */ } AsteroidsApp; /* ============================== Prototypes ================================ */ // Only functions called before their definition are here. -void restart_game_after_gameover(AsteroidsApp *app); -uint32_t key_pressed_time(AsteroidsApp *app, InputKey key); +void restart_game_after_gameover(AsteroidsApp* app); +uint32_t key_pressed_time(AsteroidsApp* app, InputKey key); /* ============================ 2D drawing ================================== */ @@ -110,29 +110,21 @@ typedef struct Poly { } Poly; /* Define the polygons we use. */ -Poly ShipPoly = { - {-3, 0, 3}, - {-3, 6, -3}, - 3 -}; +Poly ShipPoly = {{-3, 0, 3}, {-3, 6, -3}, 3}; -Poly ShipFirePoly = { - {-1.5, 0, 1.5}, - {-3, -6, -3}, - 3 -}; +Poly ShipFirePoly = {{-1.5, 0, 1.5}, {-3, -6, -3}, 3}; /* Rotate the point of the polygon 'poly' and store the new rotated * polygon in 'rot'. The polygon is rotated by an angle 'a', with * center at 0,0. */ -void rotate_poly(Poly *rot, Poly *poly, float a) { +void rotate_poly(Poly* rot, Poly* poly, float a) { /* We want to compute sin(a) and cos(a) only one time * for every point to rotate. It's a slow operation. */ float sin_a = (float)sin(a); float cos_a = (float)cos(a); - for (uint32_t j = 0; j < poly->points; j++) { - rot->x[j] = poly->x[j]*cos_a - poly->y[j]*sin_a; - rot->y[j] = poly->y[j]*cos_a + poly->x[j]*sin_a; + for(uint32_t j = 0; j < poly->points; j++) { + rot->x[j] = poly->x[j] * cos_a - poly->y[j] * sin_a; + rot->y[j] = poly->y[j] * cos_a + poly->x[j] * sin_a; } rot->points = poly->points; } @@ -140,36 +132,34 @@ void rotate_poly(Poly *rot, Poly *poly, float a) { /* This is an 8 bit LFSR we use to generate a predictable and fast * pseudorandom sequence of numbers, to give a different shape to * each asteroid. */ -void lfsr_next(unsigned char *prev) { +void lfsr_next(unsigned char* prev) { unsigned char lsb = *prev & 1; *prev = *prev >> 1; - if (lsb == 1) *prev ^= 0b11000111; - *prev ^= *prev<<7; /* Mix things a bit more. */ + if(lsb == 1) *prev ^= 0b11000111; + *prev ^= *prev << 7; /* Mix things a bit more. */ } /* Render the polygon 'poly' at x,y, rotated by the specified angle. */ -void draw_poly(Canvas *const canvas, Poly *poly, uint8_t x, uint8_t y, float a) -{ +void draw_poly(Canvas* const canvas, Poly* poly, uint8_t x, uint8_t y, float a) { Poly rot; - rotate_poly(&rot,poly,a); + rotate_poly(&rot, poly, a); canvas_set_color(canvas, ColorBlack); - for (uint32_t j = 0; j < rot.points; j++) { + for(uint32_t j = 0; j < rot.points; j++) { uint32_t a = j; - uint32_t b = j+1; - if (b == rot.points) b = 0; - canvas_draw_line(canvas,x+rot.x[a],y+rot.y[a], - x+rot.x[b],y+rot.y[b]); + uint32_t b = j + 1; + if(b == rot.points) b = 0; + canvas_draw_line(canvas, x + rot.x[a], y + rot.y[a], x + rot.x[b], y + rot.y[b]); } } /* A bullet is just a + pixels pattern. A single pixel is not * visible enough. */ -void draw_bullet(Canvas *const canvas, Bullet *b) { - canvas_draw_dot(canvas,b->x-1,b->y); - canvas_draw_dot(canvas,b->x+1,b->y); - canvas_draw_dot(canvas,b->x,b->y); - canvas_draw_dot(canvas,b->x,b->y-1); - canvas_draw_dot(canvas,b->x,b->y+1); +void draw_bullet(Canvas* const canvas, Bullet* b) { + canvas_draw_dot(canvas, b->x - 1, b->y); + canvas_draw_dot(canvas, b->x + 1, b->y); + canvas_draw_dot(canvas, b->x, b->y); + canvas_draw_dot(canvas, b->x, b->y - 1); + canvas_draw_dot(canvas, b->x, b->y + 1); } /* Draw an asteroid. The asteroid shapes is computed on the fly and @@ -177,15 +167,15 @@ void draw_bullet(Canvas *const canvas, Bullet *b) { * the shape, we use an initial fixed shape that we resize according * to the asteroid size, perturbed according to the asteroid shape * seed, and finally draw it rotated of the right amount. */ -void draw_asteroid(Canvas *const canvas, Asteroid *ast) { +void draw_asteroid(Canvas* const canvas, Asteroid* ast) { Poly ap; /* Start with what is kinda of a circle. Note that this could be * stored into a template and copied here, to avoid computing * sin() / cos(). But the Flipper can handle it without problems. */ uint8_t r = ast->shape_seed; - for (int j = 0; j < 8; j++) { - float a = (PI*2)/8*j; + for(int j = 0; j < 8; j++) { + float a = (PI * 2) / 8 * j; /* Before generating the point, to make the shape unique generate * a random factor between .7 and 1.3 to scale the distance from @@ -193,75 +183,73 @@ void draw_asteroid(Canvas *const canvas, Asteroid *ast) { * that remains always the same, so we use a predictable PRNG * implemented by an 8 bit shift register. */ lfsr_next(&r); - float scaling = .7+((float)r/255*.6); + float scaling = .7 + ((float)r / 255 * .6); ap.x[j] = (float)sin(a) * ast->size * scaling; ap.y[j] = (float)cos(a) * ast->size * scaling; } ap.points = 8; - draw_poly(canvas,&ap,ast->x,ast->y,ast->rot); + draw_poly(canvas, &ap, ast->x, ast->y, ast->rot); } /* Draw small ships in the top-right part of the screen, one for * each left live. */ -void draw_left_lives(Canvas *const canvas, AsteroidsApp *app) { +void draw_left_lives(Canvas* const canvas, AsteroidsApp* app) { int lives = app->lives; - int x = SCREEN_XRES-5; + int x = SCREEN_XRES - 5; - Poly mini_ship = { - {-2, 0, 2}, - {-2, 4, -2}, - 3 - }; + Poly mini_ship = {{-2, 0, 2}, {-2, 4, -2}, 3}; while(lives--) { - draw_poly(canvas,&mini_ship,x,6,PI); + draw_poly(canvas, &mini_ship, x, 6, PI); x -= 6; } } /* Given the current position, update it according to the velocity and * wrap it back to the other side if the object went over the screen. */ -void update_pos_by_velocity(float *x, float *y, float vx, float vy) { +void update_pos_by_velocity(float* x, float* y, float vx, float vy) { /* Return back from one side to the other of the screen. */ *x += vx; *y += vy; - if (*x >= SCREEN_XRES) *x = 0; - else if (*x < 0) *x = SCREEN_XRES-1; - if (*y >= SCREEN_YRES) *y = 0; - else if (*y < 0) *y = SCREEN_YRES-1; + if(*x >= SCREEN_XRES) + *x = 0; + else if(*x < 0) + *x = SCREEN_XRES - 1; + if(*y >= SCREEN_YRES) + *y = 0; + else if(*y < 0) + *y = SCREEN_YRES - 1; } /* Render the current game screen. */ -void render_callback(Canvas *const canvas, void *ctx) { - AsteroidsApp *app = ctx; +void render_callback(Canvas* const canvas, void* ctx) { + AsteroidsApp* app = ctx; /* Clear screen. */ canvas_set_color(canvas, ColorWhite); - canvas_draw_box(canvas, 0, 0, SCREEN_XRES-1, SCREEN_YRES-1); + canvas_draw_box(canvas, 0, 0, SCREEN_XRES - 1, SCREEN_YRES - 1); /* Draw score. */ canvas_set_color(canvas, ColorBlack); canvas_set_font(canvas, FontSecondary); char score[32]; - snprintf(score,sizeof(score),"%lu",app->score); + snprintf(score, sizeof(score), "%lu", app->score); canvas_draw_str(canvas, 0, 8, score); /* Draw left ships. */ - draw_left_lives(canvas,app); + draw_left_lives(canvas, app); /* Draw ship, asteroids, bullets. */ - draw_poly(canvas,&ShipPoly,app->ship.x,app->ship.y,app->ship.rot); - if (key_pressed_time(app,InputKeyOk) > SHIP_ACCELERATION_KEYPRESS_TIME) - draw_poly(canvas,&ShipFirePoly,app->ship.x,app->ship.y,app->ship.rot); + draw_poly(canvas, &ShipPoly, app->ship.x, app->ship.y, app->ship.rot); + if(key_pressed_time(app, InputKeyOk) > SHIP_ACCELERATION_KEYPRESS_TIME) + draw_poly(canvas, &ShipFirePoly, app->ship.x, app->ship.y, app->ship.rot); - for (int j = 0; j < app->bullets_num; j++) - draw_bullet(canvas,&app->bullets[j]); + for(int j = 0; j < app->bullets_num; j++) draw_bullet(canvas, &app->bullets[j]); - for (int j = 0; j < app->asteroids_num; j++) - draw_asteroid(canvas,&app->asteroids[j]); + for(int j = 0; j < app->asteroids_num; j++) draw_asteroid(canvas, &app->asteroids[j]); /* Game over text. */ - if (app->gameover) { + if(app->gameover) { canvas_set_color(canvas, ColorBlack); canvas_set_font(canvas, FontPrimary); canvas_draw_str(canvas, 28, 35, "GAME OVER"); @@ -273,9 +261,9 @@ void render_callback(Canvas *const canvas, void *ctx) { /* ============================ Game logic ================================== */ float distance(float x1, float y1, float x2, float y2) { - float dx = x1-x2; - float dy = y1-y2; - return sqrt(dx*dx+dy*dy); + float dx = x1 - x2; + float dy = y1 - y2; + return sqrt(dx * dx + dy * dy); } /* Detect a collision between the object at x1,y1 of radius r1 and @@ -289,10 +277,7 @@ float distance(float x1, float y1, float x2, float y2) { * spheres (this is why this function only takes the radius). This * is, after all, kinda accurate for asteroids, for bullets, and * even for the ship "core" itself. */ -bool objects_are_colliding(float x1, float y1, float r1, - float x2, float y2, float r2, - float factor) -{ +bool objects_are_colliding(float x1, float y1, float r1, float x2, float y2, float r2, float factor) { /* The objects are colliding if the distance between object 1 and 2 * is smaller than the sum of the two radiuses r1 and r2. * So it would be like: sqrt((x1-x2)^2+(y1-y2)^2) < r1+r2. @@ -301,24 +286,24 @@ bool objects_are_colliding(float x1, float y1, float r1, * the comparison like this: * * (x1-x2)^2+(y1-y2)^2 < (r1+r2)^2. */ - float dx = (x1-x2)*factor; - float dy = (y1-y2)*factor; - float rsum = r1+r2; - return dx*dx+dy*dy < rsum*rsum; + float dx = (x1 - x2) * factor; + float dy = (y1 - y2) * factor; + float rsum = r1 + r2; + return dx * dx + dy * dy < rsum * rsum; } /* Create a new bullet headed in the same direction of the ship. */ -void ship_fire_bullet(AsteroidsApp *app) { - if (app->bullets_num == MAXBUL) return; - Bullet *b = &app->bullets[app->bullets_num]; +void ship_fire_bullet(AsteroidsApp* app) { + if(app->bullets_num == MAXBUL) return; + Bullet* b = &app->bullets[app->bullets_num]; b->x = app->ship.x; b->y = app->ship.y; b->vx = -sin(app->ship.rot); b->vy = cos(app->ship.rot); /* Ship should fire from its head, not in the middle. */ - b->x += b->vx*5; - b->y += b->vy*5; + b->x += b->vx * 5; + b->y += b->vy * 5; /* Give the bullet some velocity (for now the vector is just * normalized to 1). */ @@ -336,68 +321,68 @@ void ship_fire_bullet(AsteroidsApp *app) { } /* Remove the specified bullet by id (index in the array). */ -void remove_bullet(AsteroidsApp *app, int bid) { +void remove_bullet(AsteroidsApp* app, int bid) { /* Replace the top bullet with the empty space left * by the removal of this bullet. This way we always take the * array dense, which is an advantage when looping. */ int n = --app->bullets_num; - if (n && bid != n) app->bullets[bid] = app->bullets[n]; + if(n && bid != n) app->bullets[bid] = app->bullets[n]; } /* Create a new asteroid, away from the ship. Return the * pointer to the asteroid object, so that the caller can change * certain things of the asteroid if needed. */ -Asteroid *add_asteroid(AsteroidsApp *app) { - if (app->asteroids_num == MAXAST) return NULL; - float size = 4+rand()%15; +Asteroid* add_asteroid(AsteroidsApp* app) { + if(app->asteroids_num == MAXAST) return NULL; + float size = 4 + rand() % 15; float min_distance = 20; - float x,y; + float x, y; do { x = rand() % SCREEN_XRES; y = rand() % SCREEN_YRES; - } while(distance(app->ship.x,app->ship.y,x,y) < min_distance+size); - Asteroid *a = &app->asteroids[app->asteroids_num++]; + } while(distance(app->ship.x, app->ship.y, x, y) < min_distance + size); + Asteroid* a = &app->asteroids[app->asteroids_num++]; a->x = x; a->y = y; - a->vx = 2*(-.5 + ((float)rand()/RAND_MAX)); - a->vy = 2*(-.5 + ((float)rand()/RAND_MAX)); + a->vx = 2 * (-.5 + ((float)rand() / RAND_MAX)); + a->vy = 2 * (-.5 + ((float)rand() / RAND_MAX)); a->size = size; a->rot = 0; - a->rot_speed = ((float)rand()/RAND_MAX)/10; - if (app->ticks & 1) a->rot_speed = -(a->rot_speed); + a->rot_speed = ((float)rand() / RAND_MAX) / 10; + if(app->ticks & 1) a->rot_speed = -(a->rot_speed); a->shape_seed = rand() & 255; return a; } /* Remove the specified asteroid by id (index in the array). */ -void remove_asteroid(AsteroidsApp *app, int id) { +void remove_asteroid(AsteroidsApp* app, int id) { /* Replace the top asteroid with the empty space left * by the removal of this one. This way we always take the * array dense, which is an advantage when looping. */ int n = --app->asteroids_num; - if (n && id != n) app->asteroids[id] = app->asteroids[n]; + if(n && id != n) app->asteroids[id] = app->asteroids[n]; } /* Called when an asteroid was reached by a bullet. The asteroid * hit is the one with the specified 'id'. */ -void asteroid_was_hit(AsteroidsApp *app, int id) { +void asteroid_was_hit(AsteroidsApp* app, int id) { float sizelimit = 6; // Smaller than that, they disappear in one shot. - Asteroid *a = &app->asteroids[id]; + Asteroid* a = &app->asteroids[id]; /* Asteroid is large enough to break into fragments. */ float size = a->size; float x = a->x, y = a->y; - remove_asteroid(app,id); - if (size > sizelimit) { + remove_asteroid(app, id); + if(size > sizelimit) { int max_fragments = size / sizelimit; - int fragments = 2+rand()%max_fragments; - float newsize = size/fragments; - if (newsize < 2) newsize = 2; - for (int j = 0; j < fragments; j++) { + int fragments = 2 + rand() % max_fragments; + float newsize = size / fragments; + if(newsize < 2) newsize = 2; + for(int j = 0; j < fragments; j++) { a = add_asteroid(app); - if (a == NULL) break; // Too many asteroids on screen. - a->x = x + -(size/2) + rand() % (int)newsize; - a->y = y + -(size/2) + rand() % (int)newsize; + if(a == NULL) break; // Too many asteroids on screen. + a->x = x + -(size / 2) + rand() % (int)newsize; + a->y = y + -(size / 2) + rand() % (int)newsize; a->size = newsize; } } else { @@ -407,18 +392,19 @@ void asteroid_was_hit(AsteroidsApp *app, int id) { /* Set game over state. When in game-over mode, the game displays a * game over text with a background of many asteroids floating around. */ -void game_over(AsteroidsApp *app) { +void game_over(AsteroidsApp* app) { restart_game_after_gameover(app); app->gameover = true; int asteroids = 8; - while(asteroids-- && add_asteroid(app) != NULL); + while(asteroids-- && add_asteroid(app) != NULL) + ; } /* Function called when a collision between the asteroid and the * ship is detected. */ -void ship_was_hit(AsteroidsApp *app) { +void ship_was_hit(AsteroidsApp* app) { app->ship_hit = SHIP_HIT_ANIMATION_LEN; - if (app->lives) { + if(app->lives) { app->lives--; } else { game_over(app); @@ -427,10 +413,10 @@ void ship_was_hit(AsteroidsApp *app) { /* Restart game after the ship is hit. Will reset the ship position, bullets * and asteroids to restart the game. */ -void restart_game(AsteroidsApp *app) { +void restart_game(AsteroidsApp* app) { app->ship.x = SCREEN_XRES / 2; app->ship.y = SCREEN_YRES / 2; - app->ship.rot = PI; /* Start headed towards top. */ + app->ship.rot = PI; /* Start headed towards top. */ app->ship.vx = 0; app->ship.vy = 0; app->bullets_num = 0; @@ -440,22 +426,22 @@ void restart_game(AsteroidsApp *app) { /* Called after game over to restart the game. This function * also calls restart_game(). */ -void restart_game_after_gameover(AsteroidsApp *app) { +void restart_game_after_gameover(AsteroidsApp* app) { app->gameover = false; app->ticks = 0; app->score = 0; app->ship_hit = 0; - app->lives = GAME_START_LIVES-1; /* -1 to account for current one. */ + app->lives = GAME_START_LIVES - 1; /* -1 to account for current one. */ restart_game(app); } /* Move bullets. */ -void update_bullets_position(AsteroidsApp *app) { - for (int j = 0; j < app->bullets_num; j++) { - update_pos_by_velocity(&app->bullets[j].x,&app->bullets[j].y, - app->bullets[j].vx,app->bullets[j].vy); - if (--app->bullets[j].ttl == 0) { - remove_bullet(app,j); +void update_bullets_position(AsteroidsApp* app) { + for(int j = 0; j < app->bullets_num; j++) { + update_pos_by_velocity( + &app->bullets[j].x, &app->bullets[j].y, app->bullets[j].vx, app->bullets[j].vy); + if(--app->bullets[j].ttl == 0) { + remove_bullet(app, j); j--; /* Process this bullet index again: the removal will fill it with the top bullet to take the array dense. */ } @@ -463,28 +449,28 @@ void update_bullets_position(AsteroidsApp *app) { } /* Move asteroids. */ -void update_asteroids_position(AsteroidsApp *app) { - for (int j = 0; j < app->asteroids_num; j++) { - update_pos_by_velocity(&app->asteroids[j].x,&app->asteroids[j].y, - app->asteroids[j].vx,app->asteroids[j].vy); +void update_asteroids_position(AsteroidsApp* app) { + for(int j = 0; j < app->asteroids_num; j++) { + update_pos_by_velocity( + &app->asteroids[j].x, &app->asteroids[j].y, app->asteroids[j].vx, app->asteroids[j].vy); app->asteroids[j].rot += app->asteroids[j].rot_speed; - if (app->asteroids[j].rot < 0) app->asteroids[j].rot = 2*PI; - else if (app->asteroids[j].rot > 2*PI) app->asteroids[j].rot = 0; + if(app->asteroids[j].rot < 0) + app->asteroids[j].rot = 2 * PI; + else if(app->asteroids[j].rot > 2 * PI) + app->asteroids[j].rot = 0; } } /* Collision detection and game state update based on collisions. */ -void detect_collisions(AsteroidsApp *app) { +void detect_collisions(AsteroidsApp* app) { /* Detect collision between bullet and asteroid. */ - for (int j = 0; j < app->bullets_num; j++) { - Bullet *b = &app->bullets[j]; - for (int i = 0; i < app->asteroids_num; i++) { - Asteroid *a = &app->asteroids[i]; - if (objects_are_colliding(a->x, a->y, a->size, - b->x, b->y, 1.5, 1)) - { - asteroid_was_hit(app,i); - remove_bullet(app,j); + for(int j = 0; j < app->bullets_num; j++) { + Bullet* b = &app->bullets[j]; + for(int i = 0; i < app->asteroids_num; i++) { + Asteroid* a = &app->asteroids[i]; + if(objects_are_colliding(a->x, a->y, a->size, b->x, b->y, 1.5, 1)) { + asteroid_was_hit(app, i); + remove_bullet(app, j); /* The bullet no longer exist. Break the loop. * However we want to start processing from the * same bullet index, since now it is used by @@ -496,11 +482,9 @@ void detect_collisions(AsteroidsApp *app) { } /* Detect collision between ship and asteroid. */ - for (int j = 0; j < app->asteroids_num; j++) { - Asteroid *a = &app->asteroids[j]; - if (objects_are_colliding(a->x, a->y, a->size, - app->ship.x, app->ship.y, 4, 1)) - { + for(int j = 0; j < app->asteroids_num; j++) { + Asteroid* a = &app->asteroids[j]; + if(objects_are_colliding(a->x, a->y, a->size, app->ship.x, app->ship.y, 4, 1)) { ship_was_hit(app); break; } @@ -513,26 +497,26 @@ void detect_collisions(AsteroidsApp *app) { * on velocity. Detect collisions. Update the score and so forth. * * Each time this function is called, app->tick is incremented. */ -void game_tick(void *ctx) { - AsteroidsApp *app = ctx; +void game_tick(void* ctx) { + AsteroidsApp* app = ctx; /* There are two special screens: * * 1. Ship was hit, we frozen the game as long as ship_hit isn't zero * again, and show an animation of a rotating ship. */ - if (app->ship_hit) { + if(app->ship_hit) { app->ship.rot += 0.5; app->ship_hit--; view_port_update(app->view_port); - if (app->ship_hit == 0) { + if(app->ship_hit == 0) { restart_game(app); } return; - } else if (app->gameover) { - /* 2. Game over. We need to update only background asteroids. In this + } else if(app->gameover) { + /* 2. Game over. We need to update only background asteroids. In this * state the game just displays a GAME OVER text with the floating * asteroids in background. */ - if (key_pressed_time(app,InputKeyOk) > 100) { + if(key_pressed_time(app, InputKeyOk) > 100) { restart_game_after_gameover(app); } update_asteroids_position(app); @@ -541,12 +525,12 @@ void game_tick(void *ctx) { } /* Handle key presses. */ - if (app->pressed[InputKeyLeft]) app->ship.rot -= .35; - if (app->pressed[InputKeyRight]) app->ship.rot += .35; - if (key_pressed_time(app,InputKeyOk) > SHIP_ACCELERATION_KEYPRESS_TIME) { - app->ship.vx -= 0.5*(float)sin(app->ship.rot); - app->ship.vy += 0.5*(float)cos(app->ship.rot); - } else if (app->pressed[InputKeyDown]) { + if(app->pressed[InputKeyLeft]) app->ship.rot -= .35; + if(app->pressed[InputKeyRight]) app->ship.rot += .35; + if(key_pressed_time(app, InputKeyOk) > SHIP_ACCELERATION_KEYPRESS_TIME) { + app->ship.vx -= 0.5 * (float)sin(app->ship.rot); + app->ship.vy += 0.5 * (float)cos(app->ship.rot); + } else if(app->pressed[InputKeyDown]) { app->ship.vx *= 0.75; app->ship.vy *= 0.75; } @@ -554,10 +538,10 @@ void game_tick(void *ctx) { /* Fire a bullet if needed. app->fire is set in * asteroids_update_keypress_state() since depends on exact * pressure timing. */ - if (app->fire) { + if(app->fire) { uint32_t bullet_min_period = 200; // In milliseconds uint32_t now = furi_get_tick(); - if (now - app->last_bullet_tick >= bullet_min_period) { + if(now - app->last_bullet_tick >= bullet_min_period) { ship_fire_bullet(app); app->last_bullet_tick = now; } @@ -565,7 +549,7 @@ void game_tick(void *ctx) { } /* Update positions and detect collisions. */ - update_pos_by_velocity(&app->ship.x,&app->ship.y,app->ship.vx,app->ship.vy); + update_pos_by_velocity(&app->ship.x, &app->ship.y, app->ship.vx, app->ship.vy); update_bullets_position(app); update_asteroids_position(app); detect_collisions(app); @@ -573,9 +557,7 @@ void game_tick(void *ctx) { /* From time to time, create a new asteroid. The more asteroids * already on the screen, the smaller probability of creating * a new one. */ - if (app->asteroids_num == 0 || - (random() % 5000) < (30/(1+app->asteroids_num))) - { + if(app->asteroids_num == 0 || (random() % 5000) < (30 / (1 + app->asteroids_num))) { add_asteroid(app); } @@ -587,16 +569,15 @@ void game_tick(void *ctx) { /* Here all we do is putting the events into the queue that will be handled * in the while() loop of the app entry point function. */ -void input_callback(InputEvent* input_event, void* ctx) -{ - AsteroidsApp *app = ctx; - furi_message_queue_put(app->event_queue,input_event,FuriWaitForever); +void input_callback(InputEvent* input_event, void* ctx) { + AsteroidsApp* app = ctx; + furi_message_queue_put(app->event_queue, input_event, FuriWaitForever); } /* Allocate the application state and initialize a number of stuff. * This is called in the entry point to create the application state. */ AsteroidsApp* asteroids_app_alloc() { - AsteroidsApp *app = malloc(sizeof(AsteroidsApp)); + AsteroidsApp* app = malloc(sizeof(AsteroidsApp)); app->gui = furi_record_open(RECORD_GUI); app->view_port = view_port_alloc(); @@ -605,16 +586,16 @@ AsteroidsApp* asteroids_app_alloc() { gui_add_view_port(app->gui, app->view_port, GuiLayerFullscreen); app->event_queue = furi_message_queue_alloc(8, sizeof(InputEvent)); - app->running = 1; /* Turns 0 when back is pressed. */ + app->running = 1; /* Turns 0 when back is pressed. */ restart_game_after_gameover(app); - memset(app->pressed,0,sizeof(app->pressed)); + memset(app->pressed, 0, sizeof(app->pressed)); return app; } /* Free what the application allocated. It is not clear to me if the * Flipper OS, once the application exits, will be able to reclaim space * even if we forget to free something here. */ -void asteroids_app_free(AsteroidsApp *app) { +void asteroids_app_free(AsteroidsApp* app) { furi_assert(app); // View related. @@ -630,28 +611,27 @@ void asteroids_app_free(AsteroidsApp *app) { /* Return the time in milliseconds the specified key is continuously * pressed. Or 0 if it is not pressed. */ -uint32_t key_pressed_time(AsteroidsApp *app, InputKey key) { - return app->pressed[key] == 0 ? 0 : - furi_get_tick() - app->pressed[key]; +uint32_t key_pressed_time(AsteroidsApp* app, InputKey key) { + return app->pressed[key] == 0 ? 0 : furi_get_tick() - app->pressed[key]; } /* Handle keys interaction. */ -void asteroids_update_keypress_state(AsteroidsApp *app, InputEvent input) { - if (input.type == InputTypePress) { +void asteroids_update_keypress_state(AsteroidsApp* app, InputEvent input) { + if(input.type == InputTypePress) { app->pressed[input.key] = furi_get_tick(); - } else if (input.type == InputTypeRelease) { - uint32_t dur = key_pressed_time(app,input.key); + } else if(input.type == InputTypeRelease) { + uint32_t dur = key_pressed_time(app, input.key); app->pressed[input.key] = 0; - if (dur < 200 && input.key == InputKeyOk) app->fire = true; + if(dur < 200 && input.key == InputKeyOk) app->fire = true; } } int32_t asteroids_app_entry(void* p) { UNUSED(p); - AsteroidsApp *app = asteroids_app_alloc(); + AsteroidsApp* app = asteroids_app_alloc(); /* Create a timer. We do data analysis in the callback. */ - FuriTimer *timer = furi_timer_alloc(game_tick, FuriTimerTypePeriodic, app); + FuriTimer* timer = furi_timer_alloc(game_tick, FuriTimerTypePeriodic, app); furi_timer_start(timer, furi_kernel_get_tick_frequency() / 10); /* This is the main event loop: here we get the events that are pushed @@ -660,25 +640,24 @@ int32_t asteroids_app_entry(void* p) { InputEvent input; while(app->running) { FuriStatus qstat = furi_message_queue_get(app->event_queue, &input, 100); - if (qstat == FuriStatusOk) { - if (DEBUG_MSG) FURI_LOG_E(TAG, "Main Loop - Input: type %d key %u", - input.type, input.key); + if(qstat == FuriStatusOk) { + if(DEBUG_MSG) + FURI_LOG_E(TAG, "Main Loop - Input: type %d key %u", input.type, input.key); /* Handle navigation here. Then handle view-specific inputs * in the view specific handling function. */ - if (input.type == InputTypeShort && - input.key == InputKeyBack) - { + if(input.type == InputTypeShort && input.key == InputKeyBack) { app->running = 0; } else { - asteroids_update_keypress_state(app,input); + asteroids_update_keypress_state(app, input); } } else { /* Useful to understand if the app is still alive when it * does not respond because of bugs. */ - if (DEBUG_MSG) { - static int c = 0; c++; - if (!(c % 20)) FURI_LOG_E(TAG, "Loop timeout"); + if(DEBUG_MSG) { + static int c = 0; + c++; + if(!(c % 20)) FURI_LOG_E(TAG, "Loop timeout"); } } } diff --git a/applications/plugins/cli_bridge/cligui_main.c b/applications/plugins/cli_bridge/cligui_main.c index afda14683..137b4a08b 100644 --- a/applications/plugins/cli_bridge/cligui_main.c +++ b/applications/plugins/cli_bridge/cligui_main.c @@ -24,14 +24,14 @@ static void cligui_tick_event_cb(void* context) { furi_string_push_back(app->text_box_store, c); } } - if (available > 0) { + if(available > 0) { text_box_set_text(app->text_box, furi_string_get_cstr(app->text_box_store)); } // Set input header stuff size_t len = furi_string_size(app->text_box_store); size_t idx = len - 2; - while (idx > 0) { - if (furi_string_get_char(app->text_box_store, idx) == '\n') { + while(idx > 0) { + if(furi_string_get_char(app->text_box_store, idx) == '\n') { idx++; break; } diff --git a/applications/plugins/cli_bridge/console_output.c b/applications/plugins/cli_bridge/console_output.c index 933ee8431..71603ec13 100644 --- a/applications/plugins/cli_bridge/console_output.c +++ b/applications/plugins/cli_bridge/console_output.c @@ -9,5 +9,4 @@ void console_output_input_handler(CliguiApp* app, InputEvent* event) { char eot = 0x03; furi_stream_buffer_send(app->data->streams.app_tx, &eot, 1, FuriWaitForever); } - } \ No newline at end of file diff --git a/applications/plugins/cli_bridge/internal_defs.h b/applications/plugins/cli_bridge/internal_defs.h index cdb5f2fa9..9840d008b 100644 --- a/applications/plugins/cli_bridge/internal_defs.h +++ b/applications/plugins/cli_bridge/internal_defs.h @@ -88,7 +88,6 @@ typedef struct { void* pubsub; } Loader_internal; - typedef struct { CliCallback callback; void* context; diff --git a/applications/plugins/dap_link/dap_link.c b/applications/plugins/dap_link/dap_link.c index 510540588..15f3ce771 100644 --- a/applications/plugins/dap_link/dap_link.c +++ b/applications/plugins/dap_link/dap_link.c @@ -490,8 +490,9 @@ int32_t dap_link_app(void* p) { if(furi_hal_usb_is_locked()) { DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS); DialogMessage* message = dialog_message_alloc(); - if (settings->sfw_mode) { - dialog_message_set_header(message, "Connection\nis active!", 3, 2, AlignLeft, AlignTop); + if(settings->sfw_mode) { + dialog_message_set_header( + message, "Connection\nis active!", 3, 2, AlignLeft, AlignTop); dialog_message_set_text( message, "Disconnect from\nPC or phone to\nuse this function.", @@ -499,8 +500,7 @@ int32_t dap_link_app(void* p) { 30, AlignLeft, AlignTop); - } - else { + } else { dialog_message_set_header(message, "I am not\na whore!", 3, 2, AlignLeft, AlignTop); dialog_message_set_text( message, diff --git a/applications/plugins/pocsag_pager/views/pocsag_pager_receiver.c b/applications/plugins/pocsag_pager/views/pocsag_pager_receiver.c index 760fcd0fc..c452e5fe9 100644 --- a/applications/plugins/pocsag_pager/views/pocsag_pager_receiver.c +++ b/applications/plugins/pocsag_pager/views/pocsag_pager_receiver.c @@ -209,10 +209,9 @@ void pcsg_view_receiver_draw(Canvas* canvas, PCSGReceiverModel* model) { canvas_set_color(canvas, ColorBlack); if(model->history_item == 0) { - if (settings->sfw_mode) { + if(settings->sfw_mode) { canvas_draw_icon(canvas, 0, 0, &I_Scanning_123x52_sfw); - } - else { + } else { canvas_draw_icon(canvas, 0, 0, &I_Scanning_123x52); } canvas_set_font(canvas, FontPrimary); @@ -236,10 +235,9 @@ void pcsg_view_receiver_draw(Canvas* canvas, PCSGReceiverModel* model) { canvas_draw_icon(canvas, 65, 42, &I_Pin_back_arrow_10x8); canvas_draw_icon(canvas, 80, 42, &I_Pin_back_arrow_10x8); canvas_draw_icon(canvas, 95, 42, &I_Pin_back_arrow_10x8); - if (settings->sfw_mode) { + if(settings->sfw_mode) { canvas_draw_icon(canvas, 16, 13, &I_WarningDolphin_45x42_sfw); - } - else { + } else { canvas_draw_icon(canvas, 16, 13, &I_WarningDolphin_45x42); } canvas_draw_dot(canvas, 17, 61); diff --git a/applications/plugins/pong/flipper_pong.c b/applications/plugins/pong/flipper_pong.c index 2af3e6df4..0e80e6ff3 100644 --- a/applications/plugins/pong/flipper_pong.c +++ b/applications/plugins/pong/flipper_pong.c @@ -28,34 +28,39 @@ typedef struct { InputEvent input; } EventApp; -typedef struct Players -{ - uint8_t player1_X,player1_Y,player2_X,player2_Y; - uint16_t player1_score,player2_score; - uint8_t ball_X,ball_Y,ball_X_speed,ball_Y_speed,ball_X_direction,ball_Y_direction; +typedef struct Players { + uint8_t player1_X, player1_Y, player2_X, player2_Y; + uint16_t player1_score, player2_score; + uint8_t ball_X, ball_Y, ball_X_speed, ball_Y_speed, ball_X_direction, ball_Y_direction; } Players; -static void draw_callback(Canvas* canvas, void* ctx) -{ +static void draw_callback(Canvas* canvas, void* ctx) { UNUSED(ctx); Players* playersMutex = (Players*)acquire_mutex_block((ValueMutex*)ctx); canvas_draw_frame(canvas, 0, 0, 128, 64); - canvas_draw_box(canvas, playersMutex->player1_X, playersMutex->player1_Y, PAD_SIZE_X, PAD_SIZE_Y); - canvas_draw_box(canvas, playersMutex->player2_X, playersMutex->player2_Y, PAD_SIZE_X, PAD_SIZE_Y); + canvas_draw_box( + canvas, playersMutex->player1_X, playersMutex->player1_Y, PAD_SIZE_X, PAD_SIZE_Y); + canvas_draw_box( + canvas, playersMutex->player2_X, playersMutex->player2_Y, PAD_SIZE_X, PAD_SIZE_Y); canvas_draw_box(canvas, playersMutex->ball_X, playersMutex->ball_Y, BALL_SIZE, BALL_SIZE); canvas_set_font(canvas, FontPrimary); canvas_set_font_direction(canvas, CanvasDirectionBottomToTop); char buffer[16]; - snprintf(buffer, sizeof(buffer), "%u - %u", playersMutex->player1_score, playersMutex->player2_score); - canvas_draw_str_aligned(canvas, SCREEN_SIZE_X/2+15, SCREEN_SIZE_Y/2+2, AlignCenter, AlignTop, buffer); + snprintf( + buffer, + sizeof(buffer), + "%u - %u", + playersMutex->player1_score, + playersMutex->player2_score); + canvas_draw_str_aligned( + canvas, SCREEN_SIZE_X / 2 + 15, SCREEN_SIZE_Y / 2 + 2, AlignCenter, AlignTop, buffer); release_mutex((ValueMutex*)ctx, playersMutex); } -static void input_callback(InputEvent* input_event, void* ctx) -{ +static void input_callback(InputEvent* input_event, void* ctx) { furi_assert(ctx); FuriMessageQueue* event_queue = ctx; EventApp event = {.type = EventTypeInput, .input = *input_event}; @@ -69,48 +74,44 @@ static void clock_tick(void* ctx) { furi_message_queue_put(queue, &event, 0); } -bool insidePad(uint8_t x, uint8_t y, uint8_t playerX, uint8_t playerY) -{ - if (x >= playerX && x <= playerX+PAD_SIZE_X && y >= playerY && y <= playerY+PAD_SIZE_Y) return true; +bool insidePad(uint8_t x, uint8_t y, uint8_t playerX, uint8_t playerY) { + if(x >= playerX && x <= playerX + PAD_SIZE_X && y >= playerY && y <= playerY + PAD_SIZE_Y) + return true; return false; } -uint8_t changeSpeed() -{ +uint8_t changeSpeed() { uint8_t randomuint8[1]; - while(1) - { - furi_hal_random_fill_buf(randomuint8,1); - randomuint8[0] &= 0b00000011; - if (randomuint8[0] >= 1) break; + while(1) { + furi_hal_random_fill_buf(randomuint8, 1); + randomuint8[0] &= 0b00000011; + if(randomuint8[0] >= 1) break; } return randomuint8[0]; } -uint8_t changeDirection() -{ +uint8_t changeDirection() { uint8_t randomuint8[1]; - furi_hal_random_fill_buf(randomuint8,1); + furi_hal_random_fill_buf(randomuint8, 1); randomuint8[0] &= 0b1; - return randomuint8[0]; + return randomuint8[0]; } -int32_t flipper_pong_app() -{ +int32_t flipper_pong_app() { EventApp event; FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(EventApp)); Players players; - players.player1_X = SCREEN_SIZE_X-PAD_SIZE_X-1; - players.player1_Y = SCREEN_SIZE_Y/2 - PAD_SIZE_Y/2; + players.player1_X = SCREEN_SIZE_X - PAD_SIZE_X - 1; + players.player1_Y = SCREEN_SIZE_Y / 2 - PAD_SIZE_Y / 2; players.player1_score = 0; players.player2_X = 1; - players.player2_Y = SCREEN_SIZE_Y/2 - PAD_SIZE_Y/2; + players.player2_Y = SCREEN_SIZE_Y / 2 - PAD_SIZE_Y / 2; players.player2_score = 0; - players.ball_X = SCREEN_SIZE_X/2 - BALL_SIZE/2; - players.ball_Y = SCREEN_SIZE_Y/2 - BALL_SIZE/2; + players.ball_X = SCREEN_SIZE_X / 2 - BALL_SIZE / 2; + players.ball_Y = SCREEN_SIZE_Y / 2 - BALL_SIZE / 2; players.ball_X_speed = 1; players.ball_Y_speed = 1; players.ball_X_direction = changeDirection(); @@ -127,112 +128,110 @@ int32_t flipper_pong_app() gui_add_view_port(gui, view_port, GuiLayerFullscreen); FuriTimer* timer = furi_timer_alloc(clock_tick, FuriTimerTypePeriodic, event_queue); - furi_timer_start(timer, 1000/FPS); + furi_timer_start(timer, 1000 / FPS); - while(1) - { + while(1) { FuriStatus event_status = furi_message_queue_get(event_queue, &event, FuriWaitForever); Players* playersMutex = (Players*)acquire_mutex_block(&state_mutex); - if (event_status == FuriStatusOk) - { - if(event.type == EventTypeInput) - { - if(event.input.key == InputKeyBack) - { + if(event_status == FuriStatusOk) { + if(event.type == EventTypeInput) { + if(event.input.key == InputKeyBack) { release_mutex(&state_mutex, playersMutex); break; + } else if(event.input.key == InputKeyUp) { + if(playersMutex->player1_Y >= 1 + PLAYER1_PAD_SPEED) + playersMutex->player1_Y -= PLAYER1_PAD_SPEED; + else + playersMutex->player1_Y = 1; + } else if(event.input.key == InputKeyDown) { + if(playersMutex->player1_Y <= + SCREEN_SIZE_Y - PAD_SIZE_Y - PLAYER1_PAD_SPEED - 1) + playersMutex->player1_Y += PLAYER1_PAD_SPEED; + else + playersMutex->player1_Y = SCREEN_SIZE_Y - PAD_SIZE_Y - 1; } - else if(event.input.key == InputKeyUp) - { - if (playersMutex->player1_Y >= 1+PLAYER1_PAD_SPEED) playersMutex->player1_Y -= PLAYER1_PAD_SPEED; - else playersMutex->player1_Y = 1; - } - else if(event.input.key == InputKeyDown) - { - if (playersMutex->player1_Y <= SCREEN_SIZE_Y - PAD_SIZE_Y - PLAYER1_PAD_SPEED -1) playersMutex->player1_Y += PLAYER1_PAD_SPEED; - else playersMutex->player1_Y = SCREEN_SIZE_Y - PAD_SIZE_Y - 1; - } - } - else if (event.type == ClockEventTypeTick) - { - - if (playersMutex->ball_X + BALL_SIZE/2 <= SCREEN_SIZE_X*0.35 && playersMutex->ball_X_direction == 0) - { - if (playersMutex->ball_Y + BALL_SIZE/2 < playersMutex->player2_Y + PAD_SIZE_Y/2) - { - if (playersMutex->player2_Y >= 1+PLAYER2_PAD_SPEED) playersMutex->player2_Y -= PLAYER2_PAD_SPEED; - else playersMutex->player2_Y= 1; - } - else if (playersMutex->ball_Y + BALL_SIZE/2 > playersMutex->player2_Y + PAD_SIZE_Y/2) - { - if (playersMutex->player2_Y <= SCREEN_SIZE_Y - PAD_SIZE_Y - PLAYER2_PAD_SPEED -1) playersMutex->player2_Y += PLAYER2_PAD_SPEED; - else playersMutex->player2_Y = SCREEN_SIZE_Y - PAD_SIZE_Y - 1; + } else if(event.type == ClockEventTypeTick) { + if(playersMutex->ball_X + BALL_SIZE / 2 <= SCREEN_SIZE_X * 0.35 && + playersMutex->ball_X_direction == 0) { + if(playersMutex->ball_Y + BALL_SIZE / 2 < + playersMutex->player2_Y + PAD_SIZE_Y / 2) { + if(playersMutex->player2_Y >= 1 + PLAYER2_PAD_SPEED) + playersMutex->player2_Y -= PLAYER2_PAD_SPEED; + else + playersMutex->player2_Y = 1; + } else if( + playersMutex->ball_Y + BALL_SIZE / 2 > + playersMutex->player2_Y + PAD_SIZE_Y / 2) { + if(playersMutex->player2_Y <= + SCREEN_SIZE_Y - PAD_SIZE_Y - PLAYER2_PAD_SPEED - 1) + playersMutex->player2_Y += PLAYER2_PAD_SPEED; + else + playersMutex->player2_Y = SCREEN_SIZE_Y - PAD_SIZE_Y - 1; } } - uint8_t ball_corner_X[4] = {playersMutex->ball_X, playersMutex->ball_X + BALL_SIZE, playersMutex->ball_X + BALL_SIZE, playersMutex->ball_X}; - uint8_t ball_corner_Y[4] = {playersMutex->ball_Y, playersMutex->ball_Y, playersMutex->ball_Y + BALL_SIZE, playersMutex->ball_Y + BALL_SIZE}; + uint8_t ball_corner_X[4] = { + playersMutex->ball_X, + playersMutex->ball_X + BALL_SIZE, + playersMutex->ball_X + BALL_SIZE, + playersMutex->ball_X}; + uint8_t ball_corner_Y[4] = { + playersMutex->ball_Y, + playersMutex->ball_Y, + playersMutex->ball_Y + BALL_SIZE, + playersMutex->ball_Y + BALL_SIZE}; bool insidePlayer1 = false, insidePlayer2 = false; - for (int i=0;i<4;i++) - { - if (insidePad(ball_corner_X[i], ball_corner_Y[i], playersMutex->player1_X, playersMutex->player1_Y) == true) - { + for(int i = 0; i < 4; i++) { + if(insidePad( + ball_corner_X[i], + ball_corner_Y[i], + playersMutex->player1_X, + playersMutex->player1_Y) == true) { insidePlayer1 = true; break; } - if (insidePad(ball_corner_X[i], ball_corner_Y[i], playersMutex->player2_X, playersMutex->player2_Y) == true) - { + if(insidePad( + ball_corner_X[i], + ball_corner_Y[i], + playersMutex->player2_X, + playersMutex->player2_Y) == true) { insidePlayer2 = true; break; } } - if (insidePlayer1 == true) - { + if(insidePlayer1 == true) { playersMutex->ball_X_direction = 0; playersMutex->ball_X -= playersMutex->ball_X_speed; playersMutex->ball_X_speed = changeSpeed(); playersMutex->ball_Y_speed = changeSpeed(); - } - else if (insidePlayer2 == true) - { + } else if(insidePlayer2 == true) { playersMutex->ball_X_direction = 1; playersMutex->ball_X += playersMutex->ball_X_speed; playersMutex->ball_X_speed = changeSpeed(); playersMutex->ball_Y_speed = changeSpeed(); - } - else - { - if (playersMutex->ball_X_direction == 1) - { - - if (playersMutex->ball_X <= SCREEN_SIZE_X - BALL_SIZE - 1 - playersMutex->ball_X_speed) - { + } else { + if(playersMutex->ball_X_direction == 1) { + if(playersMutex->ball_X <= + SCREEN_SIZE_X - BALL_SIZE - 1 - playersMutex->ball_X_speed) { playersMutex->ball_X += playersMutex->ball_X_speed; - } - else - { - playersMutex->ball_X = SCREEN_SIZE_X/2 - BALL_SIZE/2; - playersMutex->ball_Y = SCREEN_SIZE_Y/2 - BALL_SIZE/2; + } else { + playersMutex->ball_X = SCREEN_SIZE_X / 2 - BALL_SIZE / 2; + playersMutex->ball_Y = SCREEN_SIZE_Y / 2 - BALL_SIZE / 2; playersMutex->ball_X_speed = 1; playersMutex->ball_Y_speed = 1; playersMutex->ball_X_direction = 0; playersMutex->player2_score++; } - } - else - { - if (playersMutex->ball_X >= 1 + playersMutex->ball_X_speed) - { + } else { + if(playersMutex->ball_X >= 1 + playersMutex->ball_X_speed) { playersMutex->ball_X -= playersMutex->ball_X_speed; - } - else - { - playersMutex->ball_X = SCREEN_SIZE_X/2 - BALL_SIZE/2; - playersMutex->ball_Y = SCREEN_SIZE_Y/2 - BALL_SIZE/2; + } else { + playersMutex->ball_X = SCREEN_SIZE_X / 2 - BALL_SIZE / 2; + playersMutex->ball_Y = SCREEN_SIZE_Y / 2 - BALL_SIZE / 2; playersMutex->ball_X_speed = 1; playersMutex->ball_Y_speed = 1; playersMutex->ball_X_direction = 1; @@ -241,28 +240,20 @@ int32_t flipper_pong_app() } } - if (playersMutex->ball_Y_direction == 1) - { - if (playersMutex->ball_Y <= SCREEN_SIZE_Y - BALL_SIZE - 1 - playersMutex->ball_Y_speed) - { + if(playersMutex->ball_Y_direction == 1) { + if(playersMutex->ball_Y <= + SCREEN_SIZE_Y - BALL_SIZE - 1 - playersMutex->ball_Y_speed) { playersMutex->ball_Y += playersMutex->ball_Y_speed; - } - else - { + } else { playersMutex->ball_Y = SCREEN_SIZE_Y - BALL_SIZE - 1; playersMutex->ball_X_speed = changeSpeed(); playersMutex->ball_Y_speed = changeSpeed(); playersMutex->ball_Y_direction = 0; } - } - else - { - if (playersMutex->ball_Y >= 1 + playersMutex->ball_Y_speed) - { + } else { + if(playersMutex->ball_Y >= 1 + playersMutex->ball_Y_speed) { playersMutex->ball_Y -= playersMutex->ball_Y_speed; - } - else - { + } else { playersMutex->ball_Y = 1; playersMutex->ball_X_speed = changeSpeed(); playersMutex->ball_Y_speed = changeSpeed(); diff --git a/applications/plugins/protoview/app.c b/applications/plugins/protoview/app.c index ea4e366b8..3f9c7ced1 100644 --- a/applications/plugins/protoview/app.c +++ b/applications/plugins/protoview/app.c @@ -40,8 +40,8 @@ extern const SubGhzProtocolRegistry protoview_protocol_registry; /* The callback actually just passes the control to the actual active * view callback, after setting up basic stuff like cleaning the screen * and setting color to black. */ -static void render_callback(Canvas *const canvas, void *ctx) { - ProtoViewApp *app = ctx; +static void render_callback(Canvas* const canvas, void* ctx) { + ProtoViewApp* app = ctx; /* Clear screen. */ canvas_set_color(canvas, ColorWhite); @@ -51,56 +51,63 @@ static void render_callback(Canvas *const canvas, void *ctx) { /* Call who is in charge right now. */ switch(app->current_view) { - case ViewRawPulses: render_view_raw_pulses(canvas,app); break; - case ViewInfo: render_view_info(canvas,app); break; + case ViewRawPulses: + render_view_raw_pulses(canvas, app); + break; + case ViewInfo: + render_view_info(canvas, app); + break; case ViewFrequencySettings: case ViewModulationSettings: - render_view_settings(canvas,app); break; - case ViewDirectSampling: render_view_direct_sampling(canvas,app); break; - case ViewLast: furi_crash(TAG " ViewLast selected"); break; + render_view_settings(canvas, app); + break; + case ViewDirectSampling: + render_view_direct_sampling(canvas, app); + break; + case ViewLast: + furi_crash(TAG " ViewLast selected"); + break; } } /* Here all we do is putting the events into the queue that will be handled * in the while() loop of the app entry point function. */ -static void input_callback(InputEvent* input_event, void* ctx) -{ - ProtoViewApp *app = ctx; - furi_message_queue_put(app->event_queue,input_event,FuriWaitForever); +static void input_callback(InputEvent* input_event, void* ctx) { + ProtoViewApp* app = ctx; + furi_message_queue_put(app->event_queue, input_event, FuriWaitForever); } - /* Called to switch view (when left/right is pressed). Handles * changing the current view ID and calling the enter/exit view * callbacks if needed. */ -static void app_switch_view(ProtoViewApp *app, SwitchViewDirection dir) { +static void app_switch_view(ProtoViewApp* app, SwitchViewDirection dir) { ProtoViewCurrentView old = app->current_view; - if (dir == AppNextView) { + if(dir == AppNextView) { app->current_view++; - if (app->current_view == ViewLast) app->current_view = 0; - } else if (dir == AppPrevView) { - if (app->current_view == 0) - app->current_view = ViewLast-1; + if(app->current_view == ViewLast) app->current_view = 0; + } else if(dir == AppPrevView) { + if(app->current_view == 0) + app->current_view = ViewLast - 1; else app->current_view--; } ProtoViewCurrentView new = app->current_view; /* Call the enter/exit view callbacks if needed. */ - if (old == ViewDirectSampling) view_exit_direct_sampling(app); - if (new == ViewDirectSampling) view_enter_direct_sampling(app); + if(old == ViewDirectSampling) view_exit_direct_sampling(app); + if(new == ViewDirectSampling) view_enter_direct_sampling(app); /* The frequency/modulation settings are actually a single view: * as long as the user stays between the two modes of this view we * don't need to call the exit-view callback. */ - if ((old == ViewFrequencySettings && new != ViewModulationSettings) || - (old == ViewModulationSettings && new != ViewFrequencySettings)) + if((old == ViewFrequencySettings && new != ViewModulationSettings) || + (old == ViewModulationSettings && new != ViewFrequencySettings)) view_exit_settings(app); } /* Allocate the application state and initialize a number of stuff. * This is called in the entry point to create the application state. */ ProtoViewApp* protoview_app_alloc() { - ProtoViewApp *app = malloc(sizeof(ProtoViewApp)); + ProtoViewApp* app = malloc(sizeof(ProtoViewApp)); // Init shared data structures RawSamples = raw_samples_alloc(); @@ -142,17 +149,14 @@ ProtoViewApp* protoview_app_alloc() { app->txrx->environment = subghz_environment_alloc(); subghz_environment_set_protocol_registry( app->txrx->environment, (void*)&protoview_protocol_registry); - app->txrx->receiver = - subghz_receiver_alloc_init(app->txrx->environment); - subghz_receiver_set_filter(app->txrx->receiver, - SubGhzProtocolFlag_Decodable); + app->txrx->receiver = subghz_receiver_alloc_init(app->txrx->environment); + subghz_receiver_set_filter(app->txrx->receiver, SubGhzProtocolFlag_Decodable); subghz_worker_set_overrun_callback( - app->txrx->worker, - (SubGhzWorkerOverrunCallback)subghz_receiver_reset); + app->txrx->worker, (SubGhzWorkerOverrunCallback)subghz_receiver_reset); subghz_worker_set_pair_callback( app->txrx->worker, (SubGhzWorkerPairCallback)subghz_receiver_decode); subghz_worker_set_context(app->txrx->worker, app->txrx->receiver); - + app->frequency = subghz_setting_get_default_frequency(app->setting); app->modulation = 0; /* Defaults to ProtoViewModulations[0]. */ @@ -165,7 +169,7 @@ ProtoViewApp* protoview_app_alloc() { /* Free what the application allocated. It is not clear to me if the * Flipper OS, once the application exits, will be able to reclaim space * even if we forget to free something here. */ -void protoview_app_free(ProtoViewApp *app) { +void protoview_app_free(ProtoViewApp* app) { furi_assert(app); // Put CC1101 on sleep. @@ -183,7 +187,7 @@ void protoview_app_free(ProtoViewApp *app) { subghz_setting_free(app->setting); // Worker stuff. - if (!app->txrx->debug_timer_sampling) { + if(!app->txrx->debug_timer_sampling) { subghz_receiver_free(app->txrx->receiver); subghz_environment_free(app->txrx->environment); subghz_worker_free(app->txrx->worker); @@ -201,8 +205,8 @@ void protoview_app_free(ProtoViewApp *app) { /* Called periodically. Do signal processing here. Data we process here * will be later displayed by the render callback. The side effect of this * function is to scan for signals and set DetectedSamples. */ -static void timer_callback(void *ctx) { - ProtoViewApp *app = ctx; +static void timer_callback(void* ctx) { + ProtoViewApp* app = ctx; uint32_t delta, lastidx = app->signal_last_scan_idx; /* scan_for_signal(), called by this function, deals with a @@ -210,22 +214,22 @@ static void timer_callback(void *ctx) { * cross-boundaries, it is enough if we scan each time the buffer fills * for 50% more compared to the last scan. Thanks to this check we * can avoid scanning too many times to just find the same data. */ - if (lastidx < RawSamples->idx) { + if(lastidx < RawSamples->idx) { delta = RawSamples->idx - lastidx; } else { delta = RawSamples->total - lastidx + RawSamples->idx; } - if (delta < RawSamples->total/2) return; + if(delta < RawSamples->total / 2) return; app->signal_last_scan_idx = RawSamples->idx; scan_for_signal(app); } int32_t protoview_app_entry(void* p) { UNUSED(p); - ProtoViewApp *app = protoview_app_alloc(); + ProtoViewApp* app = protoview_app_alloc(); /* Create a timer. We do data analysis in the callback. */ - FuriTimer *timer = furi_timer_alloc(timer_callback, FuriTimerTypePeriodic, app); + FuriTimer* timer = furi_timer_alloc(timer_callback, FuriTimerTypePeriodic, app); furi_timer_start(timer, furi_kernel_get_tick_frequency() / 8); /* Start listening to signals immediately. */ @@ -240,60 +244,57 @@ int32_t protoview_app_entry(void* p) { InputEvent input; while(app->running) { FuriStatus qstat = furi_message_queue_get(app->event_queue, &input, 100); - if (qstat == FuriStatusOk) { - if (DEBUG_MSG) FURI_LOG_E(TAG, "Main Loop - Input: type %d key %u", - input.type, input.key); + if(qstat == FuriStatusOk) { + if(DEBUG_MSG) + FURI_LOG_E(TAG, "Main Loop - Input: type %d key %u", input.type, input.key); /* Handle navigation here. Then handle view-specific inputs * in the view specific handling function. */ - if (input.type == InputTypeShort && - input.key == InputKeyBack) - { + if(input.type == InputTypeShort && input.key == InputKeyBack) { /* Exit the app. */ app->running = 0; - } else if (input.type == InputTypeShort && - input.key == InputKeyRight) - { + } else if(input.type == InputTypeShort && input.key == InputKeyRight) { /* Go to the next view. */ - app_switch_view(app,AppNextView); - } else if (input.type == InputTypeShort && - input.key == InputKeyLeft) - { + app_switch_view(app, AppNextView); + } else if(input.type == InputTypeShort && input.key == InputKeyLeft) { /* Go to the previous view. */ - app_switch_view(app,AppPrevView); + app_switch_view(app, AppPrevView); } else { /* This is where we pass the control to the currently * active view input processing. */ switch(app->current_view) { case ViewRawPulses: - process_input_raw_pulses(app,input); + process_input_raw_pulses(app, input); break; case ViewInfo: - process_input_info(app,input); + process_input_info(app, input); break; case ViewFrequencySettings: case ViewModulationSettings: - process_input_settings(app,input); + process_input_settings(app, input); break; case ViewDirectSampling: - process_input_direct_sampling(app,input); + process_input_direct_sampling(app, input); + break; + case ViewLast: + furi_crash(TAG " ViewLast selected"); break; - case ViewLast: furi_crash(TAG " ViewLast selected"); break; } } } else { /* Useful to understand if the app is still alive when it * does not respond because of bugs. */ - if (DEBUG_MSG) { - static int c = 0; c++; - if (!(c % 20)) FURI_LOG_E(TAG, "Loop timeout"); + if(DEBUG_MSG) { + static int c = 0; + c++; + if(!(c % 20)) FURI_LOG_E(TAG, "Loop timeout"); } } view_port_update(app->view_port); } /* App no longer running. Shut down and free. */ - if (app->txrx->txrx_state == TxRxStateRx) { + if(app->txrx->txrx_state == TxRxStateRx) { FURI_LOG_E(TAG, "Putting CC1101 to sleep before exiting."); radio_rx_end(app); radio_sleep(app); @@ -303,4 +304,3 @@ int32_t protoview_app_entry(void* p) { protoview_app_free(app); return 0; } - diff --git a/applications/plugins/protoview/app.h b/applications/plugins/protoview/app.h index 71b06bf9a..735515cd9 100644 --- a/applications/plugins/protoview/app.h +++ b/applications/plugins/protoview/app.h @@ -48,15 +48,12 @@ typedef enum { } ProtoViewCurrentView; /* Used by app_switch_view() */ -typedef enum { - AppNextView, - AppPrevView -} SwitchViewDirection; +typedef enum { AppNextView, AppPrevView } SwitchViewDirection; typedef struct { - const char *name; + const char* name; FuriHalSubGhzPreset preset; - uint8_t *custom; + uint8_t* custom; } ProtoViewModulation; extern ProtoViewModulation ProtoViewModulations[]; /* In app_subghz.c */ @@ -65,19 +62,19 @@ extern ProtoViewModulation ProtoViewModulations[]; /* In app_subghz.c */ * It receives data and we get our protocol "feed" callback called * with the level (1 or 0) and duration. */ struct ProtoViewTxRx { - bool freq_mod_changed; /* The user changed frequency and/or modulation + bool freq_mod_changed; /* The user changed frequency and/or modulation from the interface. There is to restart the radio with the right parameters. */ - SubGhzWorker* worker; /* Our background worker. */ + SubGhzWorker* worker; /* Our background worker. */ SubGhzEnvironment* environment; SubGhzReceiver* receiver; TxRxState txrx_state; /* Receiving, idle or sleeping? */ /* Timer sampling mode state. */ - bool debug_timer_sampling; /* Read data from GDO0 in a busy loop. Only + bool debug_timer_sampling; /* Read data from GDO0 in a busy loop. Only for testing. */ uint32_t last_g0_change_time; /* Last high->low (or reverse) switch. */ - bool last_g0_value; /* Current value (high or low): we are + bool last_g0_value; /* Current value (high or low): we are checking the duration in the timer handler. */ }; @@ -97,43 +94,43 @@ typedef struct ProtoViewMsgInfo { char info2[PROTOVIEW_MSG_STR_LEN]; /* Protocol specific info line 2. */ char info3[PROTOVIEW_MSG_STR_LEN]; /* Protocol specific info line 3. */ char info4[PROTOVIEW_MSG_STR_LEN]; /* Protocol specific info line 4. */ - uint64_t len; /* Bits consumed from the stream. */ + uint64_t len; /* Bits consumed from the stream. */ } ProtoViewMsgInfo; struct ProtoViewApp { /* GUI */ - Gui *gui; - ViewPort *view_port; /* We just use a raw viewport and we render + Gui* gui; + ViewPort* view_port; /* We just use a raw viewport and we render everything into the low level canvas. */ - ProtoViewCurrentView current_view; /* Active view ID. */ - FuriMessageQueue *event_queue; /* Keypress events go here. */ + ProtoViewCurrentView current_view; /* Active view ID. */ + FuriMessageQueue* event_queue; /* Keypress events go here. */ /* Radio related. */ - ProtoViewTxRx *txrx; /* Radio state. */ - SubGhzSetting *setting; /* A list of valid frequencies. */ + ProtoViewTxRx* txrx; /* Radio state. */ + SubGhzSetting* setting; /* A list of valid frequencies. */ /* Generic app state. */ - int running; /* Once false exists the app. */ + int running; /* Once false exists the app. */ uint32_t signal_bestlen; /* Longest coherent signal observed so far. */ uint32_t signal_last_scan_idx; /* Index of the buffer last time we performed the scan. */ - bool signal_decoded; /* Was the current signal decoded? */ + bool signal_decoded; /* Was the current signal decoded? */ ProtoViewMsgInfo signal_info; /* Decoded message, if signal_decoded true. */ bool direct_sampling_enabled; /* This special view needs an explicit acknowledge to work. */ /* Raw view apps state. */ - uint32_t us_scale; /* microseconds per pixel. */ - uint32_t signal_offset; /* Long press left/right panning in raw view. */ + uint32_t us_scale; /* microseconds per pixel. */ + uint32_t signal_offset; /* Long press left/right panning in raw view. */ /* Configuration view app state. */ - uint32_t frequency; /* Current frequency. */ - uint8_t modulation; /* Current modulation ID, array index in the + uint32_t frequency; /* Current frequency. */ + uint8_t modulation; /* Current modulation ID, array index in the ProtoViewModulations table. */ }; typedef struct ProtoViewDecoder { - const char *name; /* Protocol name. */ + const char* name; /* Protocol name. */ /* The decode function takes a buffer that is actually a bitmap, with * high and low levels represented as 0 and 1. The number of high/low * pulses represented by the bitmap is passed as the 'numbits' argument, @@ -141,7 +138,7 @@ typedef struct ProtoViewDecoder { * 'bits'. So 'numbytes' is mainly useful to pass as argument to other * functions that perform bit extraction with bound checking, such as * bitmap_get() and so forth. */ - bool (*decode)(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo *info); + bool (*decode)(uint8_t* bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo* info); } ProtoViewDecoder; extern RawSamplesBuffer *RawSamples, *DetectedSamples; @@ -152,37 +149,61 @@ uint32_t radio_rx(ProtoViewApp* app); void radio_idle(ProtoViewApp* app); void radio_rx_end(ProtoViewApp* app); void radio_sleep(ProtoViewApp* app); -void raw_sampling_worker_start(ProtoViewApp *app); -void raw_sampling_worker_stop(ProtoViewApp *app); +void raw_sampling_worker_start(ProtoViewApp* app); +void raw_sampling_worker_stop(ProtoViewApp* app); /* signal.c */ uint32_t duration_delta(uint32_t a, uint32_t b); -void reset_current_signal(ProtoViewApp *app); -void scan_for_signal(ProtoViewApp *app); -bool bitmap_get(uint8_t *b, uint32_t blen, uint32_t bitpos); -void bitmap_set(uint8_t *b, uint32_t blen, uint32_t bitpos, bool val); -void bitmap_set_pattern(uint8_t *b, uint32_t blen, const char *pat); -void bitmap_invert_bytes_bits(uint8_t *p, uint32_t len); -bool bitmap_match_bits(uint8_t *b, uint32_t blen, uint32_t bitpos, const char *bits); -uint32_t bitmap_seek_bits(uint8_t *b, uint32_t blen, uint32_t startpos, uint32_t maxbits, const char *bits); -uint32_t convert_from_line_code(uint8_t *buf, uint64_t buflen, uint8_t *bits, uint32_t len, uint32_t offset, const char *zero_pattern, const char *one_pattern); -uint32_t convert_from_diff_manchester(uint8_t *buf, uint64_t buflen, uint8_t *bits, uint32_t len, uint32_t off, bool previous); +void reset_current_signal(ProtoViewApp* app); +void scan_for_signal(ProtoViewApp* app); +bool bitmap_get(uint8_t* b, uint32_t blen, uint32_t bitpos); +void bitmap_set(uint8_t* b, uint32_t blen, uint32_t bitpos, bool val); +void bitmap_set_pattern(uint8_t* b, uint32_t blen, const char* pat); +void bitmap_invert_bytes_bits(uint8_t* p, uint32_t len); +bool bitmap_match_bits(uint8_t* b, uint32_t blen, uint32_t bitpos, const char* bits); +uint32_t bitmap_seek_bits( + uint8_t* b, + uint32_t blen, + uint32_t startpos, + uint32_t maxbits, + const char* bits); +uint32_t convert_from_line_code( + uint8_t* buf, + uint64_t buflen, + uint8_t* bits, + uint32_t len, + uint32_t offset, + const char* zero_pattern, + const char* one_pattern); +uint32_t convert_from_diff_manchester( + uint8_t* buf, + uint64_t buflen, + uint8_t* bits, + uint32_t len, + uint32_t off, + bool previous); /* view_*.c */ -void render_view_raw_pulses(Canvas *const canvas, ProtoViewApp *app); -void process_input_raw_pulses(ProtoViewApp *app, InputEvent input); -void render_view_settings(Canvas *const canvas, ProtoViewApp *app); -void process_input_settings(ProtoViewApp *app, InputEvent input); -void render_view_info(Canvas *const canvas, ProtoViewApp *app); -void process_input_info(ProtoViewApp *app, InputEvent input); -void render_view_direct_sampling(Canvas *const canvas, ProtoViewApp *app); -void process_input_direct_sampling(ProtoViewApp *app, InputEvent input); -void view_enter_direct_sampling(ProtoViewApp *app); -void view_exit_direct_sampling(ProtoViewApp *app); -void view_exit_settings(ProtoViewApp *app); +void render_view_raw_pulses(Canvas* const canvas, ProtoViewApp* app); +void process_input_raw_pulses(ProtoViewApp* app, InputEvent input); +void render_view_settings(Canvas* const canvas, ProtoViewApp* app); +void process_input_settings(ProtoViewApp* app, InputEvent input); +void render_view_info(Canvas* const canvas, ProtoViewApp* app); +void process_input_info(ProtoViewApp* app, InputEvent input); +void render_view_direct_sampling(Canvas* const canvas, ProtoViewApp* app); +void process_input_direct_sampling(ProtoViewApp* app, InputEvent input); +void view_enter_direct_sampling(ProtoViewApp* app); +void view_exit_direct_sampling(ProtoViewApp* app); +void view_exit_settings(ProtoViewApp* app); /* ui.c */ -void canvas_draw_str_with_border(Canvas* canvas, uint8_t x, uint8_t y, const char* str, Color text_color, Color border_color); +void canvas_draw_str_with_border( + Canvas* canvas, + uint8_t x, + uint8_t y, + const char* str, + Color text_color, + Color border_color); /* crc.c */ -uint8_t crc8(const uint8_t *data, size_t len, uint8_t init, uint8_t poly); +uint8_t crc8(const uint8_t* data, size_t len, uint8_t init, uint8_t poly); diff --git a/applications/plugins/protoview/app_buffer.c b/applications/plugins/protoview/app_buffer.c index df2e7074e..3954587a4 100644 --- a/applications/plugins/protoview/app_buffer.c +++ b/applications/plugins/protoview/app_buffer.c @@ -8,15 +8,15 @@ #include "app_buffer.h" /* Allocate and initialize a samples buffer. */ -RawSamplesBuffer *raw_samples_alloc(void) { - RawSamplesBuffer *buf = malloc(sizeof(*buf)); +RawSamplesBuffer* raw_samples_alloc(void) { + RawSamplesBuffer* buf = malloc(sizeof(*buf)); buf->mutex = furi_mutex_alloc(FuriMutexTypeNormal); raw_samples_reset(buf); return buf; } /* Free a sample buffer. Should be called when the mutex is released. */ -void raw_samples_free(RawSamplesBuffer *s) { +void raw_samples_free(RawSamplesBuffer* s) { furi_mutex_free(s->mutex); free(s); } @@ -24,36 +24,35 @@ void raw_samples_free(RawSamplesBuffer *s) { /* This just set all the samples to zero and also resets the internal * index. There is no need to call it after raw_samples_alloc(), but only * when one wants to reset the whole buffer of samples. */ -void raw_samples_reset(RawSamplesBuffer *s) { - furi_mutex_acquire(s->mutex,FuriWaitForever); +void raw_samples_reset(RawSamplesBuffer* s) { + furi_mutex_acquire(s->mutex, FuriWaitForever); s->total = RAW_SAMPLES_NUM; s->idx = 0; s->short_pulse_dur = 0; - memset(s->level,0,sizeof(s->level)); - memset(s->dur,0,sizeof(s->dur)); + memset(s->level, 0, sizeof(s->level)); + memset(s->dur, 0, sizeof(s->dur)); furi_mutex_release(s->mutex); } /* Set the raw sample internal index so that what is currently at * offset 'offset', will appear to be at 0 index. */ -void raw_samples_center(RawSamplesBuffer *s, uint32_t offset) { - s->idx = (s->idx+offset) % RAW_SAMPLES_NUM; +void raw_samples_center(RawSamplesBuffer* s, uint32_t offset) { + s->idx = (s->idx + offset) % RAW_SAMPLES_NUM; } /* Add the specified sample in the circular buffer. */ -void raw_samples_add(RawSamplesBuffer *s, bool level, uint32_t dur) { - furi_mutex_acquire(s->mutex,FuriWaitForever); +void raw_samples_add(RawSamplesBuffer* s, bool level, uint32_t dur) { + furi_mutex_acquire(s->mutex, FuriWaitForever); s->level[s->idx] = level; s->dur[s->idx] = dur; - s->idx = (s->idx+1) % RAW_SAMPLES_NUM; + s->idx = (s->idx + 1) % RAW_SAMPLES_NUM; furi_mutex_release(s->mutex); } /* Get the sample from the buffer. It is possible to use out of range indexes * as 'idx' because the modulo operation will rewind back from the start. */ -void raw_samples_get(RawSamplesBuffer *s, uint32_t idx, bool *level, uint32_t *dur) -{ - furi_mutex_acquire(s->mutex,FuriWaitForever); +void raw_samples_get(RawSamplesBuffer* s, uint32_t idx, bool* level, uint32_t* dur) { + furi_mutex_acquire(s->mutex, FuriWaitForever); idx = (s->idx + idx) % RAW_SAMPLES_NUM; *level = s->level[idx]; *dur = s->dur[idx]; @@ -61,13 +60,13 @@ void raw_samples_get(RawSamplesBuffer *s, uint32_t idx, bool *level, uint32_t *d } /* Copy one buffer to the other, including current index. */ -void raw_samples_copy(RawSamplesBuffer *dst, RawSamplesBuffer *src) { - furi_mutex_acquire(src->mutex,FuriWaitForever); - furi_mutex_acquire(dst->mutex,FuriWaitForever); +void raw_samples_copy(RawSamplesBuffer* dst, RawSamplesBuffer* src) { + furi_mutex_acquire(src->mutex, FuriWaitForever); + furi_mutex_acquire(dst->mutex, FuriWaitForever); dst->idx = src->idx; dst->short_pulse_dur = src->short_pulse_dur; - memcpy(dst->level,src->level,sizeof(dst->level)); - memcpy(dst->dur,src->dur,sizeof(dst->dur)); + memcpy(dst->level, src->level, sizeof(dst->level)); + memcpy(dst->dur, src->dur, sizeof(dst->dur)); furi_mutex_release(src->mutex); furi_mutex_release(dst->mutex); } diff --git a/applications/plugins/protoview/app_buffer.h b/applications/plugins/protoview/app_buffer.h index 5d997d02e..4448464ae 100644 --- a/applications/plugins/protoview/app_buffer.h +++ b/applications/plugins/protoview/app_buffer.h @@ -4,15 +4,16 @@ /* Our circular buffer of raw samples, used in order to display * the signal. */ -#define RAW_SAMPLES_NUM 2048 /* Use a power of two: we take the modulo +#define RAW_SAMPLES_NUM \ + 2048 /* Use a power of two: we take the modulo of the index quite often to normalize inside the range, and division is slow. */ typedef struct RawSamplesBuffer { - FuriMutex *mutex; + FuriMutex* mutex; uint8_t level[RAW_SAMPLES_NUM]; uint32_t dur[RAW_SAMPLES_NUM]; - uint32_t idx; /* Current idx (next to write). */ + uint32_t idx; /* Current idx (next to write). */ uint32_t total; /* Total samples: same as RAW_SAMPLES_NUM, we provide this field for a cleaner interface with the user, but we always use RAW_SAMPLES_NUM when taking the modulo so @@ -21,10 +22,10 @@ typedef struct RawSamplesBuffer { uint32_t short_pulse_dur; /* Duration of the shortest pulse. */ } RawSamplesBuffer; -RawSamplesBuffer *raw_samples_alloc(void); -void raw_samples_reset(RawSamplesBuffer *s); -void raw_samples_center(RawSamplesBuffer *s, uint32_t offset); -void raw_samples_add(RawSamplesBuffer *s, bool level, uint32_t dur); -void raw_samples_get(RawSamplesBuffer *s, uint32_t idx, bool *level, uint32_t *dur); -void raw_samples_copy(RawSamplesBuffer *dst, RawSamplesBuffer *src); -void raw_samples_free(RawSamplesBuffer *s); +RawSamplesBuffer* raw_samples_alloc(void); +void raw_samples_reset(RawSamplesBuffer* s); +void raw_samples_center(RawSamplesBuffer* s, uint32_t offset); +void raw_samples_add(RawSamplesBuffer* s, bool level, uint32_t dur); +void raw_samples_get(RawSamplesBuffer* s, uint32_t idx, bool* level, uint32_t* dur); +void raw_samples_copy(RawSamplesBuffer* dst, RawSamplesBuffer* src); +void raw_samples_free(RawSamplesBuffer* s); diff --git a/applications/plugins/protoview/app_subghz.c b/applications/plugins/protoview/app_subghz.c index 30e0c817f..40c7dcfa2 100644 --- a/applications/plugins/protoview/app_subghz.c +++ b/applications/plugins/protoview/app_subghz.c @@ -9,8 +9,8 @@ #include #include -void raw_sampling_worker_start(ProtoViewApp *app); -void raw_sampling_worker_stop(ProtoViewApp *app); +void raw_sampling_worker_start(ProtoViewApp* app); +void raw_sampling_worker_stop(ProtoViewApp* app); ProtoViewModulation ProtoViewModulations[] = { {"OOK 650Khz", FuriHalSubGhzPresetOok650Async, NULL}, @@ -37,7 +37,7 @@ void radio_begin(ProtoViewApp* app) { /* The CC1101 preset can be either one of the standard presets, if * the modulation "custom" field is NULL, or a custom preset we * defined in custom_presets.h. */ - if (ProtoViewModulations[app->modulation].custom == NULL) + if(ProtoViewModulations[app->modulation].custom == NULL) furi_hal_subghz_load_preset(ProtoViewModulations[app->modulation].preset); else furi_hal_subghz_load_custom_preset(ProtoViewModulations[app->modulation].custom); @@ -49,10 +49,10 @@ void radio_begin(ProtoViewApp* app) { uint32_t radio_rx(ProtoViewApp* app) { furi_assert(app); if(!furi_hal_subghz_is_frequency_valid(app->frequency)) { - furi_crash(TAG" Incorrect RX frequency."); + furi_crash(TAG " Incorrect RX frequency."); } - if (app->txrx->txrx_state == TxRxStateRx) return app->frequency; + if(app->txrx->txrx_state == TxRxStateRx) return app->frequency; furi_hal_subghz_idle(); /* Put it into idle state in case it is sleeping. */ uint32_t value = furi_hal_subghz_set_frequency_and_path(app->frequency); @@ -60,10 +60,8 @@ uint32_t radio_rx(ProtoViewApp* app) { furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); furi_hal_subghz_flush_rx(); furi_hal_subghz_rx(); - if (!app->txrx->debug_timer_sampling) { - - furi_hal_subghz_start_async_rx(subghz_worker_rx_callback, - app->txrx->worker); + if(!app->txrx->debug_timer_sampling) { + furi_hal_subghz_start_async_rx(subghz_worker_rx_callback, app->txrx->worker); subghz_worker_start(app->txrx->worker); } else { raw_sampling_worker_start(app); @@ -75,8 +73,8 @@ uint32_t radio_rx(ProtoViewApp* app) { /* Stop subghz worker (if active), put radio on idle state. */ void radio_rx_end(ProtoViewApp* app) { furi_assert(app); - if (app->txrx->txrx_state == TxRxStateRx) { - if (!app->txrx->debug_timer_sampling) { + if(app->txrx->txrx_state == TxRxStateRx) { + if(!app->txrx->debug_timer_sampling) { if(subghz_worker_is_running(app->txrx->worker)) { subghz_worker_stop(app->txrx->worker); furi_hal_subghz_stop_async_rx(); @@ -92,7 +90,7 @@ void radio_rx_end(ProtoViewApp* app) { /* Put radio on sleep. */ void radio_sleep(ProtoViewApp* app) { furi_assert(app); - if (app->txrx->txrx_state == TxRxStateRx) { + if(app->txrx->txrx_state == TxRxStateRx) { /* We can't go from having an active RX worker to sleeping. * Stop the RX subsystems first. */ radio_rx_end(app); @@ -108,15 +106,15 @@ void radio_sleep(ProtoViewApp* app) { * Flipper system. * ===========================================================================*/ -void protoview_timer_isr(void *ctx) { - ProtoViewApp *app = ctx; +void protoview_timer_isr(void* ctx) { + ProtoViewApp* app = ctx; bool level = furi_hal_gpio_read(&gpio_cc1101_g0); - if (app->txrx->last_g0_value != level) { + if(app->txrx->last_g0_value != level) { uint32_t now = DWT->CYCCNT; uint32_t dur = now - app->txrx->last_g0_change_time; dur /= furi_hal_cortex_instructions_per_microsecond(); - if (dur > 15000) dur = 15000; + if(dur > 15000) dur = 15000; raw_samples_add(RawSamples, app->txrx->last_g0_value, dur); app->txrx->last_g0_value = level; app->txrx->last_g0_change_time = now; @@ -124,13 +122,13 @@ void protoview_timer_isr(void *ctx) { LL_TIM_ClearFlag_UPDATE(TIM2); } -void raw_sampling_worker_start(ProtoViewApp *app) { +void raw_sampling_worker_start(ProtoViewApp* app) { UNUSED(app); LL_TIM_InitTypeDef tim_init = { - .Prescaler = 63, /* CPU frequency is ~64Mhz. */ + .Prescaler = 63, /* CPU frequency is ~64Mhz. */ .CounterMode = LL_TIM_COUNTERMODE_UP, - .Autoreload = 5, /* Sample every 5 us */ + .Autoreload = 5, /* Sample every 5 us */ }; LL_TIM_Init(TIM2, &tim_init); @@ -143,7 +141,7 @@ void raw_sampling_worker_start(ProtoViewApp *app) { FURI_LOG_E(TAG, "Timer enabled"); } -void raw_sampling_worker_stop(ProtoViewApp *app) { +void raw_sampling_worker_stop(ProtoViewApp* app) { UNUSED(app); FURI_CRITICAL_ENTER(); LL_TIM_DisableCounter(TIM2); diff --git a/applications/plugins/protoview/crc.c b/applications/plugins/protoview/crc.c index 38a809e10..94d482972 100644 --- a/applications/plugins/protoview/crc.c +++ b/applications/plugins/protoview/crc.c @@ -3,14 +3,13 @@ /* CRC8 with the specified initialization value 'init' and * polynomial 'poly'. */ -uint8_t crc8(const uint8_t *data, size_t len, uint8_t init, uint8_t poly) -{ +uint8_t crc8(const uint8_t* data, size_t len, uint8_t init, uint8_t poly) { uint8_t crc = init; size_t i, j; - for (i = 0; i < len; i++) { + for(i = 0; i < len; i++) { crc ^= data[i]; - for (j = 0; j < 8; j++) { - if ((crc & 0x80) != 0) + for(j = 0; j < 8; j++) { + if((crc & 0x80) != 0) crc = (uint8_t)((crc << 1) ^ poly); else crc <<= 1; diff --git a/applications/plugins/protoview/custom_presets.h b/applications/plugins/protoview/custom_presets.h index 38fca0e31..804c4e629 100644 --- a/applications/plugins/protoview/custom_presets.h +++ b/applications/plugins/protoview/custom_presets.h @@ -72,7 +72,8 @@ static uint8_t protoview_subghz_tpms1_async_regs[][2] = { // // Modem Configuration {CC1101_MDMCFG0, 0x00}, {CC1101_MDMCFG1, 0x02}, - {CC1101_MDMCFG2, 0x04}, // Format 2-FSK/FM, No preamble/sync, Disable (current optimized). Other code reading TPMS uses GFSK, but should be the same when in RX mode. + {CC1101_MDMCFG2, + 0x04}, // Format 2-FSK/FM, No preamble/sync, Disable (current optimized). Other code reading TPMS uses GFSK, but should be the same when in RX mode. {CC1101_MDMCFG3, 0x93}, // Data rate is 20kBaud {CC1101_MDMCFG4, 0x59}, // Rx bandwidth filter is 325 kHz {CC1101_DEVIATN, 0x41}, // Deviation 28.56 kHz @@ -117,7 +118,8 @@ static uint8_t protoview_subghz_tpms2_async_regs[][2] = { // // Modem Configuration {CC1101_MDMCFG0, 0x00}, {CC1101_MDMCFG1, 0x02}, - {CC1101_MDMCFG2, 0x04}, // Format 2-FSK/FM, No preamble/sync, Disable (current optimized). Other code reading TPMS uses GFSK, but should be the same when in RX mode. + {CC1101_MDMCFG2, + 0x04}, // Format 2-FSK/FM, No preamble/sync, Disable (current optimized). Other code reading TPMS uses GFSK, but should be the same when in RX mode. {CC1101_MDMCFG3, 0x93}, // Data rate is 40kBaud {CC1101_MDMCFG4, 0x6A}, // 6 = BW filter 270kHz, A = Data rate exp {CC1101_DEVIATN, 0x41}, // Deviation 19.042 kHz @@ -189,4 +191,3 @@ static uint8_t protoview_subghz_tpms3_async_regs[][2] = { /* End */ {0, 0}, }; - diff --git a/applications/plugins/protoview/data_feed.c b/applications/plugins/protoview/data_feed.c index c3387fc4c..686bd356e 100644 --- a/applications/plugins/protoview/data_feed.c +++ b/applications/plugins/protoview/data_feed.c @@ -14,7 +14,7 @@ const SubGhzProtocol subghz_protocol_protoview; /* The feed() method puts data in the RawSamples global (protected by * a mutex). */ -extern RawSamplesBuffer *RawSamples; +extern RawSamplesBuffer* RawSamples; /* This is totally dummy: we just define the decoder base for the async * system to work but we don't really use it if not to collect raw @@ -26,8 +26,7 @@ typedef struct SubGhzProtocolDecoderprotoview { void* subghz_protocol_decoder_protoview_alloc(SubGhzEnvironment* environment) { UNUSED(environment); - SubGhzProtocolDecoderprotoview* instance = - malloc(sizeof(SubGhzProtocolDecoderprotoview)); + SubGhzProtocolDecoderprotoview* instance = malloc(sizeof(SubGhzProtocolDecoderprotoview)); instance->base.protocol = &subghz_protocol_protoview; return instance; } @@ -66,8 +65,7 @@ uint8_t subghz_protocol_decoder_protoview_get_hash_data(void* context) { bool subghz_protocol_decoder_protoview_serialize( void* context, FlipperFormat* flipper_format, - SubGhzRadioPreset* preset) -{ + SubGhzRadioPreset* preset) { UNUSED(context); UNUSED(flipper_format); UNUSED(preset); @@ -75,15 +73,13 @@ bool subghz_protocol_decoder_protoview_serialize( } /* Not used. */ -bool subghz_protocol_decoder_protoview_deserialize(void* context, FlipperFormat* flipper_format) -{ +bool subghz_protocol_decoder_protoview_deserialize(void* context, FlipperFormat* flipper_format) { UNUSED(context); UNUSED(flipper_format); return false; } -void subhz_protocol_decoder_protoview_get_string(void* context, FuriString* output) -{ +void subhz_protocol_decoder_protoview_get_string(void* context, FuriString* output) { furi_assert(context); furi_string_cat_printf(output, "Protoview"); } @@ -116,5 +112,4 @@ const SubGhzProtocol* protoview_protocol_registry_items[] = { const SubGhzProtocolRegistry protoview_protocol_registry = { .items = protoview_protocol_registry_items, - .size = COUNT_OF(protoview_protocol_registry_items) -}; + .size = COUNT_OF(protoview_protocol_registry_items)}; diff --git a/applications/plugins/protoview/protocols/b4b1.c b/applications/plugins/protoview/protocols/b4b1.c index 2bed2ac32..234b0158e 100644 --- a/applications/plugins/protoview/protocols/b4b1.c +++ b/applications/plugins/protoview/protocols/b4b1.c @@ -9,9 +9,9 @@ #include "../app.h" -static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo *info) { - if (numbits < 30) return false; - const char *sync_patterns[3] = { +static bool decode(uint8_t* bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo* info) { + if(numbits < 30) return false; + const char* sync_patterns[3] = { "10000000000000000000000000000001", /* 30 zero bits. */ "100000000000000000000000000000001", /* 31 zero bits. */ "1000000000000000000000000000000001", /* 32 zero bits. */ @@ -19,26 +19,23 @@ static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoView uint32_t off; int j; - for (j = 0; j < 3; j++) { - off = bitmap_seek_bits(bits,numbytes,0,numbits,sync_patterns[j]); - if (off != BITMAP_SEEK_NOT_FOUND) break; + for(j = 0; j < 3; j++) { + off = bitmap_seek_bits(bits, numbytes, 0, numbits, sync_patterns[j]); + if(off != BITMAP_SEEK_NOT_FOUND) break; } - if (off == BITMAP_SEEK_NOT_FOUND) return false; - if (DEBUG_MSG) FURI_LOG_E(TAG, "B4B1 preamble at: %lu",off); - off += strlen(sync_patterns[j])-1; + if(off == BITMAP_SEEK_NOT_FOUND) return false; + if(DEBUG_MSG) FURI_LOG_E(TAG, "B4B1 preamble at: %lu", off); + off += strlen(sync_patterns[j]) - 1; uint8_t d[3]; /* 24 bits of data. */ - uint32_t decoded = - convert_from_line_code(d,sizeof(d),bits,numbytes,off,"1000","1110"); + uint32_t decoded = convert_from_line_code(d, sizeof(d), bits, numbytes, off, "1000", "1110"); - if (DEBUG_MSG) FURI_LOG_E(TAG, "B4B1 decoded: %lu",decoded); - if (decoded != 24) return false; - snprintf(info->name,PROTOVIEW_MSG_STR_LEN,"PT/SC remote"); - snprintf(info->raw,PROTOVIEW_MSG_STR_LEN,"%02X%02X%02X",d[0],d[1],d[2]); - info->len = off+(4*24); + if(DEBUG_MSG) FURI_LOG_E(TAG, "B4B1 decoded: %lu", decoded); + if(decoded != 24) return false; + snprintf(info->name, PROTOVIEW_MSG_STR_LEN, "PT/SC remote"); + snprintf(info->raw, PROTOVIEW_MSG_STR_LEN, "%02X%02X%02X", d[0], d[1], d[2]); + info->len = off + (4 * 24); return true; } -ProtoViewDecoder B4B1Decoder = { - "B4B1", decode -}; +ProtoViewDecoder B4B1Decoder = {"B4B1", decode}; diff --git a/applications/plugins/protoview/protocols/citroen_tpms.c b/applications/plugins/protoview/protocols/citroen_tpms.c index 14d824e50..8831c22f4 100644 --- a/applications/plugins/protoview/protocols/citroen_tpms.c +++ b/applications/plugins/protoview/protocols/citroen_tpms.c @@ -7,54 +7,66 @@ #include "../app.h" -static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo *info) { - +static bool decode(uint8_t* bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo* info) { /* We consider a preamble of 17 symbols. They are more, but the decoding * is more likely to happen if we don't pretend to receive from the * very start of the message. */ uint32_t sync_len = 17; - const char *sync_pattern = "10101010101010110"; - if (numbits-sync_len < 8*10) return false; /* Expect 10 bytes. */ + const char* sync_pattern = "10101010101010110"; + if(numbits - sync_len < 8 * 10) return false; /* Expect 10 bytes. */ - uint64_t off = bitmap_seek_bits(bits,numbytes,0,numbits,sync_pattern); - if (off == BITMAP_SEEK_NOT_FOUND) return false; + uint64_t off = bitmap_seek_bits(bits, numbytes, 0, numbits, sync_pattern); + if(off == BITMAP_SEEK_NOT_FOUND) return false; FURI_LOG_E(TAG, "Renault TPMS preamble+sync found"); off += sync_len; /* Skip preamble + sync. */ uint8_t raw[10]; - uint32_t decoded = - convert_from_line_code(raw,sizeof(raw),bits,numbytes,off, - "01","10"); /* Manchester. */ + uint32_t decoded = convert_from_line_code( + raw, sizeof(raw), bits, numbytes, off, "01", "10"); /* Manchester. */ FURI_LOG_E(TAG, "Citroen TPMS decoded bits: %lu", decoded); - if (decoded < 8*10) return false; /* Require the full 10 bytes. */ + if(decoded < 8 * 10) return false; /* Require the full 10 bytes. */ /* Check the CRC. It's a simple XOR of bytes 1-9, the first byte * is not included. The meaning of the first byte is unknown and * we don't display it. */ uint8_t crc = 0; - for (int j = 1; j < 10; j++) crc ^= raw[j]; - if (crc != 0) return false; /* Require sane checksum. */ + for(int j = 1; j < 10; j++) crc ^= raw[j]; + if(crc != 0) return false; /* Require sane checksum. */ int repeat = raw[5] & 0xf; - float kpa = (float)raw[6]*1.364; - int temp = raw[7]-50; + float kpa = (float)raw[6] * 1.364; + int temp = raw[7] - 50; int battery = raw[8]; /* This may be the battery. It's not clear. */ - snprintf(info->name,sizeof(info->name),"%s","Citroen TPMS"); - snprintf(info->raw,sizeof(info->raw), + snprintf(info->name, sizeof(info->name), "%s", "Citroen TPMS"); + snprintf( + info->raw, + sizeof(info->raw), "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", - raw[0],raw[1],raw[2],raw[3],raw[4],raw[5], - raw[6],raw[7],raw[8],raw[9]); - snprintf(info->info1,sizeof(info->info1),"Tire ID %02X%02X%02X%02X", - raw[1],raw[2],raw[3],raw[4]); - snprintf(info->info2,sizeof(info->info2),"Pressure %.2f kpa", (double)kpa); - snprintf(info->info3,sizeof(info->info3),"Temperature %d C", temp); - snprintf(info->info4,sizeof(info->info4),"Repeat %d, Bat %d", repeat, battery); + raw[0], + raw[1], + raw[2], + raw[3], + raw[4], + raw[5], + raw[6], + raw[7], + raw[8], + raw[9]); + snprintf( + info->info1, + sizeof(info->info1), + "Tire ID %02X%02X%02X%02X", + raw[1], + raw[2], + raw[3], + raw[4]); + snprintf(info->info2, sizeof(info->info2), "Pressure %.2f kpa", (double)kpa); + snprintf(info->info3, sizeof(info->info3), "Temperature %d C", temp); + snprintf(info->info4, sizeof(info->info4), "Repeat %d, Bat %d", repeat, battery); return true; } -ProtoViewDecoder CitroenTPMSDecoder = { - "Citroen TPMS", decode -}; +ProtoViewDecoder CitroenTPMSDecoder = {"Citroen TPMS", decode}; diff --git a/applications/plugins/protoview/protocols/ford_tpms.c b/applications/plugins/protoview/protocols/ford_tpms.c index 2cab0ea91..9d3e66ff8 100644 --- a/applications/plugins/protoview/protocols/ford_tpms.c +++ b/applications/plugins/protoview/protocols/ford_tpms.c @@ -10,55 +10,67 @@ #include "../app.h" -static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo *info) { +static bool decode(uint8_t* bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo* info) { + const char* sync_pattern = "010101010101" + "0110"; + uint8_t sync_len = 12 + 4; /* We just use 12 preamble symbols + sync. */ + if(numbits - sync_len < 8 * 8) return false; - const char *sync_pattern = "010101010101" "0110"; - uint8_t sync_len = 12+4; /* We just use 12 preamble symbols + sync. */ - if (numbits-sync_len < 8*8) return false; - - uint64_t off = bitmap_seek_bits(bits,numbytes,0,numbits,sync_pattern); - if (off == BITMAP_SEEK_NOT_FOUND) return false; + uint64_t off = bitmap_seek_bits(bits, numbytes, 0, numbits, sync_pattern); + if(off == BITMAP_SEEK_NOT_FOUND) return false; FURI_LOG_E(TAG, "Fort TPMS preamble+sync found"); off += sync_len; /* Skip preamble and sync. */ uint8_t raw[8]; - uint32_t decoded = - convert_from_line_code(raw,sizeof(raw),bits,numbytes,off, - "01","10"); /* Manchester. */ + uint32_t decoded = convert_from_line_code( + raw, sizeof(raw), bits, numbytes, off, "01", "10"); /* Manchester. */ FURI_LOG_E(TAG, "Ford TPMS decoded bits: %lu", decoded); - if (decoded < 8*8) return false; /* Require the full 8 bytes. */ + if(decoded < 8 * 8) return false; /* Require the full 8 bytes. */ /* CRC is just the sum of the first 7 bytes MOD 256. */ uint8_t crc = 0; - for (int j = 0; j < 7; j++) crc += raw[j]; - if (crc != raw[7]) return false; /* Require sane CRC. */ + for(int j = 0; j < 7; j++) crc += raw[j]; + if(crc != raw[7]) return false; /* Require sane CRC. */ - float psi = 0.25 * (((raw[6]&0x20)<<3)|raw[4]); + float psi = 0.25 * (((raw[6] & 0x20) << 3) | raw[4]); /* Temperature apperas to be valid only if the most significant * bit of the value is not set. Otherwise its meaning is unknown. * Likely useful to alternatively send temperature or other info. */ - int temp = raw[5] & 0x80 ? 0 : raw[5]-56; + int temp = raw[5] & 0x80 ? 0 : raw[5] - 56; int flags = raw[5] & 0x7f; int car_moving = (raw[6] & 0x44) == 0x44; - snprintf(info->name,sizeof(info->name),"%s","Ford TPMS"); - snprintf(info->raw,sizeof(info->raw),"%02X%02X%02X%02X%02X%02X%02X%02X", - raw[0],raw[1],raw[2],raw[3],raw[4],raw[5], - raw[6],raw[7]); - snprintf(info->info1,sizeof(info->info1),"Tire ID %02X%02X%02X%02X", - raw[0],raw[1],raw[2],raw[3]); - snprintf(info->info2,sizeof(info->info2),"Pressure %.2f psi", (double)psi); - if (temp) - snprintf(info->info3,sizeof(info->info3),"Temperature %d C", temp); + snprintf(info->name, sizeof(info->name), "%s", "Ford TPMS"); + snprintf( + info->raw, + sizeof(info->raw), + "%02X%02X%02X%02X%02X%02X%02X%02X", + raw[0], + raw[1], + raw[2], + raw[3], + raw[4], + raw[5], + raw[6], + raw[7]); + snprintf( + info->info1, + sizeof(info->info1), + "Tire ID %02X%02X%02X%02X", + raw[0], + raw[1], + raw[2], + raw[3]); + snprintf(info->info2, sizeof(info->info2), "Pressure %.2f psi", (double)psi); + if(temp) + snprintf(info->info3, sizeof(info->info3), "Temperature %d C", temp); else - snprintf(info->info3,sizeof(info->info3),"Flags %d", flags); - snprintf(info->info4,sizeof(info->info4),"Moving %s", car_moving ? "yes" : "no"); + snprintf(info->info3, sizeof(info->info3), "Flags %d", flags); + snprintf(info->info4, sizeof(info->info4), "Moving %s", car_moving ? "yes" : "no"); return true; } -ProtoViewDecoder FordTPMSDecoder = { - "Ford TPMS", decode -}; +ProtoViewDecoder FordTPMSDecoder = {"Ford TPMS", decode}; diff --git a/applications/plugins/protoview/protocols/oregon2.c b/applications/plugins/protoview/protocols/oregon2.c index 3aa57c72d..fbb87d3be 100644 --- a/applications/plugins/protoview/protocols/oregon2.c +++ b/applications/plugins/protoview/protocols/oregon2.c @@ -6,60 +6,84 @@ #include "../app.h" -static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo *info) { - if (numbits < 32) return false; - const char *sync_pattern = "01100110" "01100110" "10010110" "10010110"; - uint64_t off = bitmap_seek_bits(bits,numbytes,0,numbits,sync_pattern); - if (off == BITMAP_SEEK_NOT_FOUND) return false; +static bool decode(uint8_t* bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo* info) { + if(numbits < 32) return false; + const char* sync_pattern = "01100110" + "01100110" + "10010110" + "10010110"; + uint64_t off = bitmap_seek_bits(bits, numbytes, 0, numbits, sync_pattern); + if(off == BITMAP_SEEK_NOT_FOUND) return false; FURI_LOG_E(TAG, "Oregon2 preamble+sync found"); off += 32; /* Skip preamble. */ uint8_t buffer[8], raw[8] = {0}; uint32_t decoded = - convert_from_line_code(buffer,sizeof(buffer),bits,numbytes,off,"1001","0110"); + convert_from_line_code(buffer, sizeof(buffer), bits, numbytes, off, "1001", "0110"); FURI_LOG_E(TAG, "Oregon2 decoded bits: %lu", decoded); - if (decoded < 11*4) return false; /* Minimum len to extract some data. */ + if(decoded < 11 * 4) return false; /* Minimum len to extract some data. */ char temp[3] = {0}, deviceid[2] = {0}, hum[2] = {0}; - for (int j = 0; j < 64; j += 4) { + for(int j = 0; j < 64; j += 4) { uint8_t nib[1]; - nib[0] = (bitmap_get(buffer,8,j+0) | - bitmap_get(buffer,8,j+1) << 1 | - bitmap_get(buffer,8,j+2) << 2 | - bitmap_get(buffer,8,j+3) << 3); - if (DEBUG_MSG) FURI_LOG_E(TAG, "Not inverted nibble[%d]: %x", j/4, (unsigned int)nib[0]); - raw[j/8] |= nib[0] << (4-(j%4)); - switch(j/4) { - case 1: deviceid[0] |= nib[0]; break; - case 0: deviceid[0] |= nib[0] << 4; break; - case 3: deviceid[1] |= nib[0]; break; - case 2: deviceid[1] |= nib[0] << 4; break; - case 10: temp[0] = nib[0]; break; + nib[0] = + (bitmap_get(buffer, 8, j + 0) | bitmap_get(buffer, 8, j + 1) << 1 | + bitmap_get(buffer, 8, j + 2) << 2 | bitmap_get(buffer, 8, j + 3) << 3); + if(DEBUG_MSG) FURI_LOG_E(TAG, "Not inverted nibble[%d]: %x", j / 4, (unsigned int)nib[0]); + raw[j / 8] |= nib[0] << (4 - (j % 4)); + switch(j / 4) { + case 1: + deviceid[0] |= nib[0]; + break; + case 0: + deviceid[0] |= nib[0] << 4; + break; + case 3: + deviceid[1] |= nib[0]; + break; + case 2: + deviceid[1] |= nib[0] << 4; + break; + case 10: + temp[0] = nib[0]; + break; /* Fixme: take the temperature sign from nibble 11. */ - case 9: temp[1] = nib[0]; break; - case 8: temp[2] = nib[0]; break; - case 13: hum[0] = nib[0]; break; - case 12: hum[1] = nib[0]; break; + case 9: + temp[1] = nib[0]; + break; + case 8: + temp[2] = nib[0]; + break; + case 13: + hum[0] = nib[0]; + break; + case 12: + hum[1] = nib[0]; + break; } } - snprintf(info->name,sizeof(info->name),"%s","Oregon v2.1"); + snprintf(info->name, sizeof(info->name), "%s", "Oregon v2.1"); /* The following line crashes the Flipper because of broken * snprintf() implementation. */ - snprintf(info->raw,sizeof(info->raw),"%02X%02X%02X%02X%02X%02X%02X%02X", - raw[0],raw[1],raw[2],raw[3],raw[4],raw[5], - raw[6],raw[7]); - snprintf(info->info1,sizeof(info->info1),"Sensor ID %02X%02X", - deviceid[0], deviceid[1]); - snprintf(info->info2,sizeof(info->info2),"Temperature %d%d.%d", - temp[0],temp[1],temp[2]); - snprintf(info->info3,sizeof(info->info3),"Humidity %d%d", - hum[0],hum[1]); + snprintf( + info->raw, + sizeof(info->raw), + "%02X%02X%02X%02X%02X%02X%02X%02X", + raw[0], + raw[1], + raw[2], + raw[3], + raw[4], + raw[5], + raw[6], + raw[7]); + snprintf(info->info1, sizeof(info->info1), "Sensor ID %02X%02X", deviceid[0], deviceid[1]); + snprintf(info->info2, sizeof(info->info2), "Temperature %d%d.%d", temp[0], temp[1], temp[2]); + snprintf(info->info3, sizeof(info->info3), "Humidity %d%d", hum[0], hum[1]); return true; } -ProtoViewDecoder Oregon2Decoder = { - "Oregon2", decode -}; +ProtoViewDecoder Oregon2Decoder = {"Oregon2", decode}; diff --git a/applications/plugins/protoview/protocols/renault_tpms.c b/applications/plugins/protoview/protocols/renault_tpms.c index 1f8ea0711..b876d2731 100644 --- a/applications/plugins/protoview/protocols/renault_tpms.c +++ b/applications/plugins/protoview/protocols/renault_tpms.c @@ -6,61 +6,66 @@ #include "../app.h" #define USE_TEST_VECTOR 0 -static const char *test_vector = +static const char* test_vector = "...01010101010101010110" // Preamble + sync /* The following is Marshal encoded, so each two characters are * actaully one bit. 01 = 0, 10 = 1. */ "010110010110" // Flags. "10011001101010011001" // Pressure, multiply by 0.75 to obtain kpa. - // 244 kpa here. - "1010010110011010" // Temperature, subtract 30 to obtain celsius. 22C here. + // 244 kpa here. + "1010010110011010" // Temperature, subtract 30 to obtain celsius. 22C here. "1001010101101001" "0101100110010101" - "1001010101100110" // Tire ID. 0x7AD779 here. + "1001010101100110" // Tire ID. 0x7AD779 here. "0101010101010101" - "0101010101010101" // Two FF bytes (usually). Unknown. + "0101010101010101" // Two FF bytes (usually). Unknown. "0110010101010101"; // CRC8 with (poly 7, initialization 0). -static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo *info) { - - if (USE_TEST_VECTOR) { /* Test vector to check that decoding works. */ - bitmap_set_pattern(bits,numbytes,test_vector); +static bool decode(uint8_t* bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo* info) { + if(USE_TEST_VECTOR) { /* Test vector to check that decoding works. */ + bitmap_set_pattern(bits, numbytes, test_vector); numbits = strlen(test_vector); } - if (numbits-12 < 9*8) return false; + if(numbits - 12 < 9 * 8) return false; - const char *sync_pattern = "01010101010101010110"; - uint64_t off = bitmap_seek_bits(bits,numbytes,0,numbits,sync_pattern); - if (off == BITMAP_SEEK_NOT_FOUND) return false; + const char* sync_pattern = "01010101010101010110"; + uint64_t off = bitmap_seek_bits(bits, numbytes, 0, numbits, sync_pattern); + if(off == BITMAP_SEEK_NOT_FOUND) return false; FURI_LOG_E(TAG, "Renault TPMS preamble+sync found"); off += 20; /* Skip preamble. */ uint8_t raw[9]; - uint32_t decoded = - convert_from_line_code(raw,sizeof(raw),bits,numbytes,off, - "01","10"); /* Manchester. */ + uint32_t decoded = convert_from_line_code( + raw, sizeof(raw), bits, numbytes, off, "01", "10"); /* Manchester. */ FURI_LOG_E(TAG, "Renault TPMS decoded bits: %lu", decoded); - if (decoded < 8*9) return false; /* Require the full 9 bytes. */ - if (crc8(raw,8,0,7) != raw[8]) return false; /* Require sane CRC. */ + if(decoded < 8 * 9) return false; /* Require the full 9 bytes. */ + if(crc8(raw, 8, 0, 7) != raw[8]) return false; /* Require sane CRC. */ - float kpa = 0.75 *((uint32_t)((raw[0]&3)<<8) | raw[1]); - int temp = raw[2]-30; + float kpa = 0.75 * ((uint32_t)((raw[0] & 3) << 8) | raw[1]); + int temp = raw[2] - 30; - snprintf(info->name,sizeof(info->name),"%s","Renault TPMS"); - snprintf(info->raw,sizeof(info->raw),"%02X%02X%02X%02X%02X%02X%02X%02X%02X", - raw[0],raw[1],raw[2],raw[3],raw[4],raw[5], - raw[6],raw[7],raw[8]); - snprintf(info->info1,sizeof(info->info1),"Tire ID %02X%02X%02X", - raw[3],raw[4],raw[5]); - snprintf(info->info2,sizeof(info->info2),"Pressure %.2f kpa", (double)kpa); - snprintf(info->info3,sizeof(info->info3),"Temperature %d C", temp); + snprintf(info->name, sizeof(info->name), "%s", "Renault TPMS"); + snprintf( + info->raw, + sizeof(info->raw), + "%02X%02X%02X%02X%02X%02X%02X%02X%02X", + raw[0], + raw[1], + raw[2], + raw[3], + raw[4], + raw[5], + raw[6], + raw[7], + raw[8]); + snprintf(info->info1, sizeof(info->info1), "Tire ID %02X%02X%02X", raw[3], raw[4], raw[5]); + snprintf(info->info2, sizeof(info->info2), "Pressure %.2f kpa", (double)kpa); + snprintf(info->info3, sizeof(info->info3), "Temperature %d C", temp); return true; } -ProtoViewDecoder RenaultTPMSDecoder = { - "Renault TPMS", decode -}; +ProtoViewDecoder RenaultTPMSDecoder = {"Renault TPMS", decode}; diff --git a/applications/plugins/protoview/protocols/schrader_tpms.c b/applications/plugins/protoview/protocols/schrader_tpms.c index ebf3d6004..cb2cf52c4 100644 --- a/applications/plugins/protoview/protocols/schrader_tpms.c +++ b/applications/plugins/protoview/protocols/schrader_tpms.c @@ -11,20 +11,21 @@ #include "../app.h" #define USE_TEST_VECTOR 0 -static const char *test_vector = "000000111101010101011010010110010110101001010110100110011001100101010101011010100110100110011010101010101010101010101010101010101010101010101010"; +static const char* test_vector = + "000000111101010101011010010110010110101001010110100110011001100101010101011010100110100110011010101010101010101010101010101010101010101010101010"; -static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo *info) { - - if (USE_TEST_VECTOR) { /* Test vector to check that decoding works. */ - bitmap_set_pattern(bits,numbytes,test_vector); +static bool decode(uint8_t* bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo* info) { + if(USE_TEST_VECTOR) { /* Test vector to check that decoding works. */ + bitmap_set_pattern(bits, numbytes, test_vector); numbits = strlen(test_vector); } - if (numbits < 64) return false; /* Preamble + data. */ + if(numbits < 64) return false; /* Preamble + data. */ - const char *sync_pattern = "1111010101" "01011010"; - uint64_t off = bitmap_seek_bits(bits,numbytes,0,numbits,sync_pattern); - if (off == BITMAP_SEEK_NOT_FOUND) return false; + const char* sync_pattern = "1111010101" + "01011010"; + uint64_t off = bitmap_seek_bits(bits, numbytes, 0, numbits, sync_pattern); + if(off == BITMAP_SEEK_NOT_FOUND) return false; FURI_LOG_E(TAG, "Schrader TPMS gap+preamble found"); off += 10; /* Skip just the long pulse and the first 3 bits of sync, so @@ -32,34 +33,46 @@ static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoView 0011 = 0x3. */ uint8_t raw[8]; - uint32_t decoded = - convert_from_line_code(raw,sizeof(raw),bits,numbytes,off, - "01","10"); /* Manchester code. */ + uint32_t decoded = convert_from_line_code( + raw, sizeof(raw), bits, numbytes, off, "01", "10"); /* Manchester code. */ FURI_LOG_E(TAG, "Schrader TPMS decoded bits: %lu", decoded); - if (decoded < 64) return false; /* Require the full 8 bytes. */ + if(decoded < 64) return false; /* Require the full 8 bytes. */ raw[0] |= 0xf0; // Fix the preamble nibble for checksum computation. - uint8_t cksum = crc8(raw,sizeof(raw)-1,0xf0,0x7); - if (cksum != raw[7]) { + uint8_t cksum = crc8(raw, sizeof(raw) - 1, 0xf0, 0x7); + if(cksum != raw[7]) { FURI_LOG_E(TAG, "Schrader TPMS checksum mismatch"); return false; } - float kpa = (float)raw[5]*2.5; - int temp = raw[6]-50; + float kpa = (float)raw[5] * 2.5; + int temp = raw[6] - 50; - snprintf(info->name,sizeof(info->name),"%s","Schrader TPMS"); - snprintf(info->raw,sizeof(info->raw),"%02X%02X%02X%02X%02X%02X%02X%02X", - raw[0],raw[1],raw[2],raw[3],raw[4],raw[5], - raw[6],raw[7]); - snprintf(info->info1,sizeof(info->info1),"Tire ID %01X%02X%02X%02X", - raw[1]&7,raw[2],raw[3],raw[4]); /* Only 28 bits of ID, not 32. */ - snprintf(info->info2,sizeof(info->info2),"Pressure %.2f kpa", (double)kpa); - snprintf(info->info3,sizeof(info->info3),"Temperature %d C", temp); + snprintf(info->name, sizeof(info->name), "%s", "Schrader TPMS"); + snprintf( + info->raw, + sizeof(info->raw), + "%02X%02X%02X%02X%02X%02X%02X%02X", + raw[0], + raw[1], + raw[2], + raw[3], + raw[4], + raw[5], + raw[6], + raw[7]); + snprintf( + info->info1, + sizeof(info->info1), + "Tire ID %01X%02X%02X%02X", + raw[1] & 7, + raw[2], + raw[3], + raw[4]); /* Only 28 bits of ID, not 32. */ + snprintf(info->info2, sizeof(info->info2), "Pressure %.2f kpa", (double)kpa); + snprintf(info->info3, sizeof(info->info3), "Temperature %d C", temp); return true; } -ProtoViewDecoder SchraderTPMSDecoder = { - "Schrader TPMS", decode -}; +ProtoViewDecoder SchraderTPMSDecoder = {"Schrader TPMS", decode}; diff --git a/applications/plugins/protoview/protocols/toyota_tpms.c b/applications/plugins/protoview/protocols/toyota_tpms.c index b870c2f33..4e2376b96 100644 --- a/applications/plugins/protoview/protocols/toyota_tpms.c +++ b/applications/plugins/protoview/protocols/toyota_tpms.c @@ -24,54 +24,61 @@ #include "../app.h" -static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo *info) { - - if (numbits-6 < 64*2) return false; /* Ask for 64 bit of data (each bit +static bool decode(uint8_t* bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo* info) { + if(numbits - 6 < 64 * 2) + return false; /* Ask for 64 bit of data (each bit is two symbols in the bitmap). */ - char *sync[] = { - "00111100", - "001111100", - "00111101", - "001111101", - NULL - }; + char* sync[] = {"00111100", "001111100", "00111101", "001111101", NULL}; int j; uint32_t off = 0; - for (j = 0; sync[j]; j++) { - off = bitmap_seek_bits(bits,numbytes,0,numbits,sync[j]); - if (off != BITMAP_SEEK_NOT_FOUND) { - off += strlen(sync[j])-2; + for(j = 0; sync[j]; j++) { + off = bitmap_seek_bits(bits, numbytes, 0, numbits, sync[j]); + if(off != BITMAP_SEEK_NOT_FOUND) { + off += strlen(sync[j]) - 2; break; - } + } } - if (off == BITMAP_SEEK_NOT_FOUND) return false; + if(off == BITMAP_SEEK_NOT_FOUND) return false; FURI_LOG_E(TAG, "Toyota TPMS sync[%s] found", sync[j]); uint8_t raw[9]; - uint32_t decoded = - convert_from_diff_manchester(raw,sizeof(raw),bits,numbytes,off,true); + uint32_t decoded = convert_from_diff_manchester(raw, sizeof(raw), bits, numbytes, off, true); FURI_LOG_E(TAG, "Toyota TPMS decoded bits: %lu", decoded); - if (decoded < 8*9) return false; /* Require the full 8 bytes. */ - if (crc8(raw,8,0x80,7) != raw[8]) return false; /* Require sane CRC. */ + if(decoded < 8 * 9) return false; /* Require the full 8 bytes. */ + if(crc8(raw, 8, 0x80, 7) != raw[8]) return false; /* Require sane CRC. */ - float kpa = (float)((raw[4]&0x7f)<<1 | raw[5]>>7) * 0.25 - 7; - int temp = ((raw[5]&0x7f)<<1 | raw[6]>>7) - 40; + float kpa = (float)((raw[4] & 0x7f) << 1 | raw[5] >> 7) * 0.25 - 7; + int temp = ((raw[5] & 0x7f) << 1 | raw[6] >> 7) - 40; - snprintf(info->name,sizeof(info->name),"%s","Toyota TPMS"); - snprintf(info->raw,sizeof(info->raw),"%02X%02X%02X%02X%02X%02X%02X%02X%02X", - raw[0],raw[1],raw[2],raw[3],raw[4],raw[5], - raw[6],raw[7],raw[8]); - snprintf(info->info1,sizeof(info->info1),"Tire ID %02X%02X%02X%02X", - raw[0],raw[1],raw[2],raw[3]); - snprintf(info->info1,sizeof(info->info1),"Pressure %.2f psi", (double)kpa); - snprintf(info->info2,sizeof(info->info2),"Temperature %d C", temp); + snprintf(info->name, sizeof(info->name), "%s", "Toyota TPMS"); + snprintf( + info->raw, + sizeof(info->raw), + "%02X%02X%02X%02X%02X%02X%02X%02X%02X", + raw[0], + raw[1], + raw[2], + raw[3], + raw[4], + raw[5], + raw[6], + raw[7], + raw[8]); + snprintf( + info->info1, + sizeof(info->info1), + "Tire ID %02X%02X%02X%02X", + raw[0], + raw[1], + raw[2], + raw[3]); + snprintf(info->info1, sizeof(info->info1), "Pressure %.2f psi", (double)kpa); + snprintf(info->info2, sizeof(info->info2), "Temperature %d C", temp); return true; } -ProtoViewDecoder ToyotaTPMSDecoder = { - "Toyota TPMS", decode -}; +ProtoViewDecoder ToyotaTPMSDecoder = {"Toyota TPMS", decode}; diff --git a/applications/plugins/protoview/signal.c b/applications/plugins/protoview/signal.c index 5a1c6c99b..a06ec1d74 100644 --- a/applications/plugins/protoview/signal.c +++ b/applications/plugins/protoview/signal.c @@ -3,8 +3,8 @@ #include "app.h" -bool decode_signal(RawSamplesBuffer *s, uint64_t len, ProtoViewMsgInfo *info); -void initialize_msg_info(ProtoViewMsgInfo *i); +bool decode_signal(RawSamplesBuffer* s, uint64_t len, ProtoViewMsgInfo* info); +void initialize_msg_info(ProtoViewMsgInfo* i); /* ============================================================================= * Raw signal detection @@ -17,7 +17,7 @@ uint32_t duration_delta(uint32_t a, uint32_t b) { } /* Reset the current signal, so that a new one can be detected. */ -void reset_current_signal(ProtoViewApp *app) { +void reset_current_signal(ProtoViewApp* app) { app->signal_bestlen = 0; app->signal_offset = 0; app->signal_decoded = false; @@ -38,47 +38,47 @@ void reset_current_signal(ProtoViewApp *app) { * For instance Oregon2 sensors, in the case of protocol 2.1 will send * pulses of ~400us (RF on) VS ~580us (RF off). */ #define SEARCH_CLASSES 3 -uint32_t search_coherent_signal(RawSamplesBuffer *s, uint32_t idx) { +uint32_t search_coherent_signal(RawSamplesBuffer* s, uint32_t idx) { struct { - uint32_t dur[2]; /* dur[0] = low, dur[1] = high */ - uint32_t count[2]; /* Associated observed frequency. */ + uint32_t dur[2]; /* dur[0] = low, dur[1] = high */ + uint32_t count[2]; /* Associated observed frequency. */ } classes[SEARCH_CLASSES]; - memset(classes,0,sizeof(classes)); + memset(classes, 0, sizeof(classes)); uint32_t minlen = 30, maxlen = 4000; /* Depends on data rate, here we allow for high and low. */ uint32_t len = 0; /* Observed len of coherent samples. */ s->short_pulse_dur = 0; - for (uint32_t j = idx; j < idx+500; j++) { + for(uint32_t j = idx; j < idx + 500; j++) { bool level; uint32_t dur; raw_samples_get(s, j, &level, &dur); - if (dur < minlen || dur > maxlen) break; /* return. */ + if(dur < minlen || dur > maxlen) break; /* return. */ /* Let's see if it matches a class we already have or if we * can populate a new (yet empty) class. */ uint32_t k; - for (k = 0; k < SEARCH_CLASSES; k++) { - if (classes[k].count[level] == 0) { + for(k = 0; k < SEARCH_CLASSES; k++) { + if(classes[k].count[level] == 0) { classes[k].dur[level] = dur; classes[k].count[level] = 1; break; /* Sample accepted. */ } else { uint32_t classavg = classes[k].dur[level]; uint32_t count = classes[k].count[level]; - uint32_t delta = duration_delta(dur,classavg); + uint32_t delta = duration_delta(dur, classavg); /* Is the difference in duration between this signal and * the class we are inspecting less than a given percentage? * If so, accept this signal. */ - if (delta < classavg/5) { /* 100%/5 = 20%. */ + if(delta < classavg / 5) { /* 100%/5 = 20%. */ /* It is useful to compute the average of the class * we are observing. We know how many samples we got so * far, so we can recompute the average easily. * By always having a better estimate of the pulse len * we can avoid missing next samples in case the first * observed samples are too off. */ - classavg = ((classavg * count) + dur) / (count+1); + classavg = ((classavg * count) + dur) / (count + 1); classes[k].dur[level] = classavg; classes[k].count[level]++; break; /* Sample accepted. */ @@ -86,7 +86,7 @@ uint32_t search_coherent_signal(RawSamplesBuffer *s, uint32_t idx) { } } - if (k == SEARCH_CLASSES) break; /* No match, return. */ + if(k == SEARCH_CLASSES) break; /* No match, return. */ /* If we are here, we accepted this sample. Try with the next * one. */ @@ -96,14 +96,12 @@ uint32_t search_coherent_signal(RawSamplesBuffer *s, uint32_t idx) { /* Update the buffer setting the shortest pulse we found * among the three classes. This will be used when scaling * for visualization. */ - uint32_t short_dur[2] = {0,0}; - for (int j = 0; j < SEARCH_CLASSES; j++) { - for (int level = 0; level < 2; level++) { - if (classes[j].dur[level] == 0) continue; - if (classes[j].count[level] < 3) continue; - if (short_dur[level] == 0 || - short_dur[level] > classes[j].dur[level]) - { + uint32_t short_dur[2] = {0, 0}; + for(int j = 0; j < SEARCH_CLASSES; j++) { + for(int level = 0; level < 2; level++) { + if(classes[j].dur[level] == 0) continue; + if(classes[j].count[level] < 3) continue; + if(short_dur[level] == 0 || short_dur[level] > classes[j].dur[level]) { short_dur[level] = classes[j].dur[level]; } } @@ -112,9 +110,9 @@ uint32_t search_coherent_signal(RawSamplesBuffer *s, uint32_t idx) { /* Use the average between high and low short pulses duration. * Often they are a bit different, and using the average is more robust * when we do decoding sampling at short_pulse_dur intervals. */ - if (short_dur[0] == 0) short_dur[0] = short_dur[1]; - if (short_dur[1] == 0) short_dur[1] = short_dur[0]; - s->short_pulse_dur = (short_dur[0]+short_dur[1])/2; + if(short_dur[0] == 0) short_dur[0] = short_dur[1]; + if(short_dur[1] == 0) short_dur[1] = short_dur[0]; + s->short_pulse_dur = (short_dur[0] + short_dur[1]) / 2; return len; } @@ -123,54 +121,56 @@ uint32_t search_coherent_signal(RawSamplesBuffer *s, uint32_t idx) { * in order to find a coherent signal. If a signal that does not appear to * be just noise is found, it is set in DetectedSamples global signal * buffer, that is what is rendered on the screen. */ -void scan_for_signal(ProtoViewApp *app) { +void scan_for_signal(ProtoViewApp* app) { /* We need to work on a copy: the RawSamples buffer is populated * by the background thread receiving data. */ - RawSamplesBuffer *copy = raw_samples_alloc(); - raw_samples_copy(copy,RawSamples); + RawSamplesBuffer* copy = raw_samples_alloc(); + raw_samples_copy(copy, RawSamples); /* Try to seek on data that looks to have a regular high low high low * pattern. */ - uint32_t minlen = 18; /* Min run of coherent samples. With less + uint32_t minlen = 18; /* Min run of coherent samples. With less than a few samples it's very easy to mistake noise for signal. */ - ProtoViewMsgInfo *info = malloc(sizeof(ProtoViewMsgInfo)); + ProtoViewMsgInfo* info = malloc(sizeof(ProtoViewMsgInfo)); uint32_t i = 0; - while (i < copy->total-1) { - uint32_t thislen = search_coherent_signal(copy,i); + while(i < copy->total - 1) { + uint32_t thislen = search_coherent_signal(copy, i); /* For messages that are long enough, attempt decoding. */ - if (thislen > minlen) { + if(thislen > minlen) { initialize_msg_info(info); uint32_t saved_idx = copy->idx; /* Save index, see later. */ /* decode_signal() expects the detected signal to start * from index .*/ - raw_samples_center(copy,i); - bool decoded = decode_signal(copy,thislen,info); + raw_samples_center(copy, i); + bool decoded = decode_signal(copy, thislen, info); copy->idx = saved_idx; /* Restore the index as we are scanning the signal in the loop. */ /* Accept this signal as the new signal if either it's longer * than the previous undecoded one, or the previous one was * unknown and this is decoded. */ - if ((thislen > app->signal_bestlen && app->signal_decoded == false) - || (app->signal_decoded == false && decoded)) - { + if((thislen > app->signal_bestlen && app->signal_decoded == false) || + (app->signal_decoded == false && decoded)) { app->signal_info = *info; app->signal_bestlen = thislen; app->signal_decoded = decoded; - raw_samples_copy(DetectedSamples,copy); - raw_samples_center(DetectedSamples,i); - FURI_LOG_E(TAG, "===> Displayed sample updated (%d samples %lu us)", - (int)thislen, DetectedSamples->short_pulse_dur); + raw_samples_copy(DetectedSamples, copy); + raw_samples_center(DetectedSamples, i); + FURI_LOG_E( + TAG, + "===> Displayed sample updated (%d samples %lu us)", + (int)thislen, + DetectedSamples->short_pulse_dur); /* Adjust raw view scale if the signal has an high * data rate. */ - if (DetectedSamples->short_pulse_dur < 75) + if(DetectedSamples->short_pulse_dur < 75) app->us_scale = 10; - else if (DetectedSamples->short_pulse_dur < 145) + else if(DetectedSamples->short_pulse_dur < 145) app->us_scale = 30; } } @@ -196,43 +196,43 @@ void scan_for_signal(ProtoViewApp *app) { /* Set the 'bitpos' bit to value 'val', in the specified bitmap * 'b' of len 'blen'. * Out of range bits will silently be discarded. */ -void bitmap_set(uint8_t *b, uint32_t blen, uint32_t bitpos, bool val) { - uint32_t byte = bitpos/8; - uint32_t bit = 7-(bitpos&7); - if (byte >= blen) return; - if (val) - b[byte] |= 1<= blen) return; + if(val) + b[byte] |= 1 << bit; else - b[byte] &= ~(1<= blen) return 0; - return (b[byte] & (1<= blen) return 0; + return (b[byte] & (1 << bit)) != 0; } /* We decode bits assuming the first bit we receive is the LSB * (see bitmap_set/get functions). Many devices send data * encoded in the reverse way. */ -void bitmap_invert_bytes_bits(uint8_t *p, uint32_t len) { - for (uint32_t j = 0; j < len*8; j += 8) { +void bitmap_invert_bytes_bits(uint8_t* p, uint32_t len) { + for(uint32_t j = 0; j < len * 8; j += 8) { bool bits[8]; - for (int i = 0; i < 8; i++) bits[i] = bitmap_get(p,len,j+i); - for (int i = 0; i < 8; i++) bitmap_set(p,len,j+i,bits[7-i]); + for(int i = 0; i < 8; i++) bits[i] = bitmap_get(p, len, j + i); + for(int i = 0; i < 8; i++) bitmap_set(p, len, j + i, bits[7 - i]); } } /* Return true if the specified sequence of bits, provided as a string in the * form "11010110..." is found in the 'b' bitmap of 'blen' bits at 'bitpos' * position. */ -bool bitmap_match_bits(uint8_t *b, uint32_t blen, uint32_t bitpos, const char *bits) { - for (size_t j = 0; bits[j]; j++) { +bool bitmap_match_bits(uint8_t* b, uint32_t blen, uint32_t bitpos, const char* bits) { + for(size_t j = 0; bits[j]; j++) { bool expected = (bits[j] == '1') ? true : false; - if (bitmap_get(b,blen,bitpos+j) != expected) return false; + if(bitmap_get(b, blen, bitpos + j) != expected) return false; } return true; } @@ -245,12 +245,17 @@ bool bitmap_match_bits(uint8_t *b, uint32_t blen, uint32_t bitpos, const char *b * Note: there are better algorithms, such as Boyer-Moore. Here we hope that * for the kind of patterns we search we'll have a lot of early stops so * we use a vanilla approach. */ -uint32_t bitmap_seek_bits(uint8_t *b, uint32_t blen, uint32_t startpos, uint32_t maxbits, const char *bits) { - uint32_t endpos = startpos+blen*8; - uint32_t end2 = startpos+maxbits; - if (end2 < endpos) endpos = end2; - for (uint32_t j = startpos; j < endpos; j++) - if (bitmap_match_bits(b,blen,j,bits)) return j; +uint32_t bitmap_seek_bits( + uint8_t* b, + uint32_t blen, + uint32_t startpos, + uint32_t maxbits, + const char* bits) { + uint32_t endpos = startpos + blen * 8; + uint32_t end2 = startpos + maxbits; + if(end2 < endpos) endpos = end2; + for(uint32_t j = startpos; j < endpos; j++) + if(bitmap_match_bits(b, blen, j, bits)) return j; return BITMAP_SEEK_NOT_FOUND; } @@ -259,10 +264,10 @@ uint32_t bitmap_seek_bits(uint8_t *b, uint32_t blen, uint32_t startpos, uint32_t * This function is useful in order to set the test vectors in the protocol * decoders, to see if the decoding works regardless of the fact we are able * to actually receive a given signal. */ -void bitmap_set_pattern(uint8_t *b, uint32_t blen, const char *pat) { +void bitmap_set_pattern(uint8_t* b, uint32_t blen, const char* pat) { uint32_t i = 0; while(pat[i]) { - bitmap_set(b,blen,i,pat[i] == '1'); + bitmap_set(b, blen, i, pat[i] == '1'); i++; } } @@ -294,31 +299,36 @@ void bitmap_set_pattern(uint8_t *b, uint32_t blen, const char *pat) { * bits set into the buffer 'b'. The 'rate' argument, in microseconds, is * the detected short-pulse duration. We expect the line code to be * meaningful when interpreted at multiples of 'rate'. */ -uint32_t convert_signal_to_bits(uint8_t *b, uint32_t blen, RawSamplesBuffer *s, uint32_t idx, uint32_t count, uint32_t rate) { - if (rate == 0) return 0; /* We can't perform the conversion. */ +uint32_t convert_signal_to_bits( + uint8_t* b, + uint32_t blen, + RawSamplesBuffer* s, + uint32_t idx, + uint32_t count, + uint32_t rate) { + if(rate == 0) return 0; /* We can't perform the conversion. */ uint32_t bitpos = 0; - for (uint32_t j = 0; j < count; j++) { + for(uint32_t j = 0; j < count; j++) { uint32_t dur; bool level; - raw_samples_get(s, j+idx, &level, &dur); + raw_samples_get(s, j + idx, &level, &dur); uint32_t numbits = dur / rate; /* full bits that surely fit. */ - uint32_t rest = dur % rate; /* How much we are left with. */ - if (rest > rate/2) numbits++; /* There is another one. */ + uint32_t rest = dur % rate; /* How much we are left with. */ + if(rest > rate / 2) numbits++; /* There is another one. */ /* Limit how much a single sample can spawn. There are likely no * protocols doing such long pulses when the rate is low. */ - if (numbits > 1024) numbits = 1024; + if(numbits > 1024) numbits = 1024; - if (0) /* Super verbose, so not under the DEBUG_MSG define. */ - FURI_LOG_E(TAG, "%lu converted into %lu (%d) bits", - dur,numbits,(int)level); + if(0) /* Super verbose, so not under the DEBUG_MSG define. */ + FURI_LOG_E(TAG, "%lu converted into %lu (%d) bits", dur, numbits, (int)level); /* If the signal is too short, let's claim it an interference * and ignore it completely. */ - if (numbits == 0) continue; + if(numbits == 0) continue; - while(numbits--) bitmap_set(b,blen,bitpos++,level); + while(numbits--) bitmap_set(b, blen, bitpos++, level); } return bitpos; } @@ -335,23 +345,29 @@ uint32_t convert_signal_to_bits(uint8_t *b, uint32_t blen, RawSamplesBuffer *s, * specified in bytes by the caller, via the 'len' parameters). * * The decoding starts at the specified offset (in bits) 'off'. */ -uint32_t convert_from_line_code(uint8_t *buf, uint64_t buflen, uint8_t *bits, uint32_t len, uint32_t off, const char *zero_pattern, const char *one_pattern) -{ +uint32_t convert_from_line_code( + uint8_t* buf, + uint64_t buflen, + uint8_t* bits, + uint32_t len, + uint32_t off, + const char* zero_pattern, + const char* one_pattern) { uint32_t decoded = 0; /* Number of bits extracted. */ len *= 8; /* Convert bytes to bits. */ while(off < len) { bool bitval; - if (bitmap_match_bits(bits,len,off,zero_pattern)) { + if(bitmap_match_bits(bits, len, off, zero_pattern)) { bitval = false; off += strlen(zero_pattern); - } else if (bitmap_match_bits(bits,len,off,one_pattern)) { + } else if(bitmap_match_bits(bits, len, off, one_pattern)) { bitval = true; off += strlen(one_pattern); } else { break; } - bitmap_set(buf,buflen,decoded++,bitval); - if (decoded/8 == buflen) break; /* No space left on target buffer. */ + bitmap_set(buf, buflen, decoded++, bitval); + if(decoded / 8 == buflen) break; /* No space left on target buffer. */ } return decoded; } @@ -362,17 +378,22 @@ uint32_t convert_from_line_code(uint8_t *buf, uint64_t buflen, uint8_t *bits, ui * in differential codings the next bits depend on the previous one. * * Parameters and return values are like convert_from_line_code(). */ -uint32_t convert_from_diff_manchester(uint8_t *buf, uint64_t buflen, uint8_t *bits, uint32_t len, uint32_t off, bool previous) -{ +uint32_t convert_from_diff_manchester( + uint8_t* buf, + uint64_t buflen, + uint8_t* bits, + uint32_t len, + uint32_t off, + bool previous) { uint32_t decoded = 0; len *= 8; /* Conver to bits. */ - for (uint32_t j = off; j < len; j += 2) { - bool b0 = bitmap_get(bits,len,j); - bool b1 = bitmap_get(bits,len,j+1); - if (b0 == previous) break; /* Each new bit must switch value. */ - bitmap_set(buf,buflen,decoded++,b0 == b1); + for(uint32_t j = off; j < len; j += 2) { + bool b0 = bitmap_get(bits, len, j); + bool b1 = bitmap_get(bits, len, j + 1); + if(b0 == previous) break; /* Each new bit must switch value. */ + bitmap_set(buf, buflen, decoded++, b0 == b1); previous = b1; - if (decoded/8 == buflen) break; /* No space left on target buffer. */ + if(decoded / 8 == buflen) break; /* No space left on target buffer. */ } return decoded; } @@ -388,44 +409,49 @@ extern ProtoViewDecoder SchraderTPMSDecoder; extern ProtoViewDecoder CitroenTPMSDecoder; extern ProtoViewDecoder FordTPMSDecoder; -ProtoViewDecoder *Decoders[] = { - &Oregon2Decoder, /* Oregon sensors v2.1 protocol. */ - &B4B1Decoder, /* PT, SC, ... 24 bits remotes. */ - &RenaultTPMSDecoder, /* Renault TPMS. */ - &ToyotaTPMSDecoder, /* Toyota TPMS. */ - &SchraderTPMSDecoder, /* Schrader TPMS. */ - &CitroenTPMSDecoder, /* Citroen TPMS. */ - &FordTPMSDecoder, /* Ford TPMS. */ - NULL -}; +ProtoViewDecoder* Decoders[] = { + &Oregon2Decoder, /* Oregon sensors v2.1 protocol. */ + &B4B1Decoder, /* PT, SC, ... 24 bits remotes. */ + &RenaultTPMSDecoder, /* Renault TPMS. */ + &ToyotaTPMSDecoder, /* Toyota TPMS. */ + &SchraderTPMSDecoder, /* Schrader TPMS. */ + &CitroenTPMSDecoder, /* Citroen TPMS. */ + &FordTPMSDecoder, /* Ford TPMS. */ + NULL}; /* Reset the message info structure before passing it to the decoding * functions. */ -void initialize_msg_info(ProtoViewMsgInfo *i) { - memset(i,0,sizeof(ProtoViewMsgInfo)); +void initialize_msg_info(ProtoViewMsgInfo* i) { + memset(i, 0, sizeof(ProtoViewMsgInfo)); } /* This function is called when a new signal is detected. It converts it * to a bitstream, and the calls the protocol specific functions for * decoding. If the signal was decoded correctly by some protocol, true * is returned. Otherwise false is returned. */ -bool decode_signal(RawSamplesBuffer *s, uint64_t len, ProtoViewMsgInfo *info) { - uint32_t bitmap_bits_size = 4096*8; - uint32_t bitmap_size = bitmap_bits_size/8; +bool decode_signal(RawSamplesBuffer* s, uint64_t len, ProtoViewMsgInfo* info) { + uint32_t bitmap_bits_size = 4096 * 8; + uint32_t bitmap_size = bitmap_bits_size / 8; /* We call the decoders with an offset a few samples before the actual * signal detected and for a len of a few bits after its end. */ uint32_t before_samples = 20; uint32_t after_samples = 100; - uint8_t *bitmap = malloc(bitmap_size); - uint32_t bits = convert_signal_to_bits(bitmap,bitmap_size,s,-before_samples,len+before_samples+after_samples,s->short_pulse_dur); + uint8_t* bitmap = malloc(bitmap_size); + uint32_t bits = convert_signal_to_bits( + bitmap, + bitmap_size, + s, + -before_samples, + len + before_samples + after_samples, + s->short_pulse_dur); - if (DEBUG_MSG) { /* Useful for debugging purposes. Don't remove. */ - char *str = malloc(1024); + if(DEBUG_MSG) { /* Useful for debugging purposes. Don't remove. */ + char* str = malloc(1024); uint32_t j; - for (j = 0; j < bits && j < 1023; j++) { - str[j] = bitmap_get(bitmap,bitmap_size,j) ? '1' : '0'; + for(j = 0; j < bits && j < 1023; j++) { + str[j] = bitmap_get(bitmap, bitmap_size, j) ? '1' : '0'; } str[j] = 0; FURI_LOG_E(TAG, "%lu bits sampled: %s", bits, str); @@ -438,18 +464,25 @@ bool decode_signal(RawSamplesBuffer *s, uint64_t len, ProtoViewMsgInfo *info) { bool decoded = false; while(Decoders[j]) { uint32_t start_time = furi_get_tick(); - decoded = Decoders[j]->decode(bitmap,bitmap_size,bits,info); + decoded = Decoders[j]->decode(bitmap, bitmap_size, bits, info); uint32_t delta = furi_get_tick() - start_time; - FURI_LOG_E(TAG, "Decoder %s took %lu ms", - Decoders[j]->name, (unsigned long)delta); - if (decoded) break; + FURI_LOG_E(TAG, "Decoder %s took %lu ms", Decoders[j]->name, (unsigned long)delta); + if(decoded) break; j++; } - if (!decoded) { + if(!decoded) { FURI_LOG_E(TAG, "No decoding possible"); } else { - FURI_LOG_E(TAG, "Decoded %s, raw=%s info=[%s,%s,%s,%s]", info->name, info->raw, info->info1, info->info2, info->info3, info->info4); + FURI_LOG_E( + TAG, + "Decoded %s, raw=%s info=[%s,%s,%s,%s]", + info->name, + info->raw, + info->info1, + info->info2, + info->info3, + info->info4); } free(bitmap); return decoded; diff --git a/applications/plugins/protoview/ui.c b/applications/plugins/protoview/ui.c index e22e4d57e..2a974756b 100644 --- a/applications/plugins/protoview/ui.c +++ b/applications/plugins/protoview/ui.c @@ -3,28 +3,24 @@ #include "app.h" -void canvas_draw_str_with_border(Canvas* canvas, uint8_t x, uint8_t y, const char* str, Color text_color, Color border_color) -{ +void canvas_draw_str_with_border( + Canvas* canvas, + uint8_t x, + uint8_t y, + const char* str, + Color text_color, + Color border_color) { struct { - uint8_t x; uint8_t y; - } dir[8] = { - {-1,-1}, - {0,-1}, - {1,-1}, - {1,0}, - {1,1}, - {0,1}, - {-1,1}, - {-1,0} - }; + uint8_t x; + uint8_t y; + } dir[8] = {{-1, -1}, {0, -1}, {1, -1}, {1, 0}, {1, 1}, {0, 1}, {-1, 1}, {-1, 0}}; /* Rotate in all the directions writing the same string to create a * border, then write the actual string in the other color in the * middle. */ canvas_set_color(canvas, border_color); - for (int j = 0; j < 8; j++) - canvas_draw_str(canvas,x+dir[j].x,y+dir[j].y,str); + for(int j = 0; j < 8; j++) canvas_draw_str(canvas, x + dir[j].x, y + dir[j].y, str); canvas_set_color(canvas, text_color); - canvas_draw_str(canvas,x,y,str); + canvas_draw_str(canvas, x, y, str); canvas_set_color(canvas, ColorBlack); } diff --git a/applications/plugins/protoview/view_direct_sampling.c b/applications/plugins/protoview/view_direct_sampling.c index 251a289b8..1ab90f096 100644 --- a/applications/plugins/protoview/view_direct_sampling.c +++ b/applications/plugins/protoview/view_direct_sampling.c @@ -7,47 +7,46 @@ /* Read directly from the G0 CC1101 pin, and draw a black or white * dot depending on the level. */ -void render_view_direct_sampling(Canvas *const canvas, ProtoViewApp *app) { - if (!app->direct_sampling_enabled) { +void render_view_direct_sampling(Canvas* const canvas, ProtoViewApp* app) { + if(!app->direct_sampling_enabled) { canvas_set_font(canvas, FontSecondary); - canvas_draw_str(canvas,2,9,"Direct sampling is a special"); - canvas_draw_str(canvas,2,18,"mode that displays the signal"); - canvas_draw_str(canvas,2,27,"captured in real time. Like in"); - canvas_draw_str(canvas,2,36,"a old CRT TV. It's very slow."); - canvas_draw_str(canvas,2,45,"Can crash your Flipper."); + canvas_draw_str(canvas, 2, 9, "Direct sampling is a special"); + canvas_draw_str(canvas, 2, 18, "mode that displays the signal"); + canvas_draw_str(canvas, 2, 27, "captured in real time. Like in"); + canvas_draw_str(canvas, 2, 36, "a old CRT TV. It's very slow."); + canvas_draw_str(canvas, 2, 45, "Can crash your Flipper."); canvas_set_font(canvas, FontPrimary); - canvas_draw_str(canvas,14,60,"To enable press OK"); + canvas_draw_str(canvas, 14, 60, "To enable press OK"); return; } - for (int y = 0; y < 64; y++) { - for (int x = 0; x < 128; x++) { + for(int y = 0; y < 64; y++) { + for(int x = 0; x < 128; x++) { bool level = furi_hal_gpio_read(&gpio_cc1101_g0); - if (level) canvas_draw_dot(canvas,x,y); + if(level) canvas_draw_dot(canvas, x, y); /* Busy loop: this is a terrible approach as it blocks * everything else, but for now it's the best we can do * to obtain direct data with some spacing. */ - uint32_t x = 250; while(x--); + uint32_t x = 250; + while(x--) + ; } } canvas_set_font(canvas, FontSecondary); - canvas_draw_str_with_border(canvas,36,60,"Direct sampling", - ColorWhite,ColorBlack); + canvas_draw_str_with_border(canvas, 36, 60, "Direct sampling", ColorWhite, ColorBlack); } /* Handle input */ -void process_input_direct_sampling(ProtoViewApp *app, InputEvent input) { - if (input.type == InputTypePress && input.key == InputKeyOk) { +void process_input_direct_sampling(ProtoViewApp* app, InputEvent input) { + if(input.type == InputTypePress && input.key == InputKeyOk) { app->direct_sampling_enabled = !app->direct_sampling_enabled; } } /* Enter view. Stop the subghz thread to prevent access as we read * the CC1101 data directly. */ -void view_enter_direct_sampling(ProtoViewApp *app) { - if (app->txrx->txrx_state == TxRxStateRx && - !app->txrx->debug_timer_sampling) - { +void view_enter_direct_sampling(ProtoViewApp* app) { + if(app->txrx->txrx_state == TxRxStateRx && !app->txrx->debug_timer_sampling) { subghz_worker_stop(app->txrx->worker); } else { raw_sampling_worker_stop(app); @@ -55,10 +54,8 @@ void view_enter_direct_sampling(ProtoViewApp *app) { } /* Exit view. Restore the subghz thread. */ -void view_exit_direct_sampling(ProtoViewApp *app) { - if (app->txrx->txrx_state == TxRxStateRx && - !app->txrx->debug_timer_sampling) - { +void view_exit_direct_sampling(ProtoViewApp* app) { + if(app->txrx->txrx_state == TxRxStateRx && !app->txrx->debug_timer_sampling) { subghz_worker_start(app->txrx->worker); } else { raw_sampling_worker_start(app); diff --git a/applications/plugins/protoview/view_info.c b/applications/plugins/protoview/view_info.c index 775c8abc2..aeca36668 100644 --- a/applications/plugins/protoview/view_info.c +++ b/applications/plugins/protoview/view_info.c @@ -4,10 +4,10 @@ #include "app.h" /* Renders the view with the detected message information. */ -void render_view_info(Canvas *const canvas, ProtoViewApp *app) { - if (app->signal_decoded == false) { +void render_view_info(Canvas* const canvas, ProtoViewApp* app) { + if(app->signal_decoded == false) { canvas_set_font(canvas, FontSecondary); - canvas_draw_str(canvas, 30,36,"No signal decoded"); + canvas_draw_str(canvas, 30, 36, "No signal decoded"); return; } @@ -20,21 +20,25 @@ void render_view_info(Canvas *const canvas, ProtoViewApp *app) { /* Info fields. */ char buf[128]; canvas_set_font(canvas, FontSecondary); - if (app->signal_info.raw[0]) { - snprintf(buf,sizeof(buf),"Raw: %s", app->signal_info.raw); + if(app->signal_info.raw[0]) { + snprintf(buf, sizeof(buf), "Raw: %s", app->signal_info.raw); canvas_draw_str(canvas, 0, y, buf); y += lineheight; } - canvas_draw_str(canvas, 0, y, app->signal_info.info1); y += lineheight; - canvas_draw_str(canvas, 0, y, app->signal_info.info2); y += lineheight; - canvas_draw_str(canvas, 0, y, app->signal_info.info3); y += lineheight; - canvas_draw_str(canvas, 0, y, app->signal_info.info4); y += lineheight; + canvas_draw_str(canvas, 0, y, app->signal_info.info1); + y += lineheight; + canvas_draw_str(canvas, 0, y, app->signal_info.info2); + y += lineheight; + canvas_draw_str(canvas, 0, y, app->signal_info.info3); + y += lineheight; + canvas_draw_str(canvas, 0, y, app->signal_info.info4); + y += lineheight; } /* Handle input for the info view. */ -void process_input_info(ProtoViewApp *app, InputEvent input) { - if (input.type == InputTypeShort) { - if (input.key == InputKeyOk) { +void process_input_info(ProtoViewApp* app, InputEvent input) { + if(input.type == InputTypeShort) { + if(input.key == InputKeyOk) { /* Reset the current sample to capture the next. */ reset_current_signal(app); } diff --git a/applications/plugins/protoview/view_raw_signal.c b/applications/plugins/protoview/view_raw_signal.c index 58d23e8ee..c20e3a69d 100644 --- a/applications/plugins/protoview/view_raw_signal.c +++ b/applications/plugins/protoview/view_raw_signal.c @@ -12,7 +12,7 @@ * * The 'idx' argument is the first sample to render in the circular * buffer. */ -void render_signal(ProtoViewApp *app, Canvas *const canvas, RawSamplesBuffer *buf, uint32_t idx) { +void render_signal(ProtoViewApp* app, Canvas* const canvas, RawSamplesBuffer* buf, uint32_t idx) { canvas_set_color(canvas, ColorBlack); int rows = 8; @@ -20,31 +20,29 @@ void render_signal(ProtoViewApp *app, Canvas *const canvas, RawSamplesBuffer *bu uint32_t start_idx = idx; bool level = 0; uint32_t dur = 0, sample_num = 0; - for (int row = 0; row < rows ; row++) { - for (int x = 0; x < 128; x++) { - int y = 3 + row*8; - if (dur < time_per_pixel/2) { + for(int row = 0; row < rows; row++) { + for(int x = 0; x < 128; x++) { + int y = 3 + row * 8; + if(dur < time_per_pixel / 2) { /* Get more data. */ raw_samples_get(buf, idx++, &level, &dur); sample_num++; } - canvas_draw_line(canvas, x,y,x,y-(level*3)); + canvas_draw_line(canvas, x, y, x, y - (level * 3)); /* Write a small triangle under the last sample detected. */ - if (app->signal_bestlen != 0 && - sample_num+start_idx == app->signal_bestlen+1) - { - canvas_draw_dot(canvas,x,y+2); - canvas_draw_dot(canvas,x-1,y+3); - canvas_draw_dot(canvas,x,y+3); - canvas_draw_dot(canvas,x+1,y+3); + if(app->signal_bestlen != 0 && sample_num + start_idx == app->signal_bestlen + 1) { + canvas_draw_dot(canvas, x, y + 2); + canvas_draw_dot(canvas, x - 1, y + 3); + canvas_draw_dot(canvas, x, y + 3); + canvas_draw_dot(canvas, x + 1, y + 3); sample_num++; /* Make sure we don't mark the next, too. */ } /* Remove from the current level duration the time we * just plot. */ - if (dur > time_per_pixel) + if(dur > time_per_pixel) dur -= time_per_pixel; else dur = 0; @@ -53,45 +51,46 @@ void render_signal(ProtoViewApp *app, Canvas *const canvas, RawSamplesBuffer *bu } /* Raw pulses rendering. This is our default view. */ -void render_view_raw_pulses(Canvas *const canvas, ProtoViewApp *app) { +void render_view_raw_pulses(Canvas* const canvas, ProtoViewApp* app) { /* Show signal. */ render_signal(app, canvas, DetectedSamples, app->signal_offset); /* Show signal information. */ char buf[64]; - snprintf(buf,sizeof(buf),"%luus", - (unsigned long)DetectedSamples->short_pulse_dur); + snprintf(buf, sizeof(buf), "%luus", (unsigned long)DetectedSamples->short_pulse_dur); canvas_set_font(canvas, FontSecondary); canvas_draw_str_with_border(canvas, 97, 63, buf, ColorWhite, ColorBlack); - if (app->signal_decoded) { + if(app->signal_decoded) { canvas_set_font(canvas, FontPrimary); canvas_draw_str_with_border(canvas, 1, 61, app->signal_info.name, ColorWhite, ColorBlack); } } /* Handle input for the raw pulses view. */ -void process_input_raw_pulses(ProtoViewApp *app, InputEvent input) { - if (input.type == InputTypeRepeat) { +void process_input_raw_pulses(ProtoViewApp* app, InputEvent input) { + if(input.type == InputTypeRepeat) { /* Handle panning of the signal window. Long pressing * right will show successive samples, long pressing left * previous samples. */ - if (input.key == InputKeyRight) app->signal_offset++; - else if (input.key == InputKeyLeft) app->signal_offset--; - else if (input.key == InputKeyOk) { + if(input.key == InputKeyRight) + app->signal_offset++; + else if(input.key == InputKeyLeft) + app->signal_offset--; + else if(input.key == InputKeyOk) { app->signal_offset = 0; app->us_scale = PROTOVIEW_RAW_VIEW_DEFAULT_SCALE; } - } else if (input.type == InputTypeShort) { - if (input.key == InputKeyOk) { + } else if(input.type == InputTypeShort) { + if(input.key == InputKeyOk) { /* Reset the current sample to capture the next. */ reset_current_signal(app); - } else if (input.key == InputKeyDown) { + } else if(input.key == InputKeyDown) { /* Rescaling. The set becomes finer under 50us per pixel. */ uint32_t scale_step = app->us_scale >= 50 ? 50 : 10; - if (app->us_scale < 500) app->us_scale += scale_step; - } else if (input.key == InputKeyUp) { + if(app->us_scale < 500) app->us_scale += scale_step; + } else if(input.key == InputKeyUp) { uint32_t scale_step = app->us_scale > 50 ? 50 : 10; - if (app->us_scale > 10) app->us_scale -= scale_step; + if(app->us_scale > 10) app->us_scale -= scale_step; } } } diff --git a/applications/plugins/protoview/view_settings.c b/applications/plugins/protoview/view_settings.c index 1e2dce226..09abf5a2a 100644 --- a/applications/plugins/protoview/view_settings.c +++ b/applications/plugins/protoview/view_settings.c @@ -6,30 +6,30 @@ /* Renders a single view with frequency and modulation setting. However * this are logically two different views, and only one of the settings * will be highlighted. */ -void render_view_settings(Canvas *const canvas, ProtoViewApp *app) { +void render_view_settings(Canvas* const canvas, ProtoViewApp* app) { canvas_set_font(canvas, FontPrimary); - if (app->current_view == ViewFrequencySettings) - canvas_draw_str_with_border(canvas,1,10,"Frequency",ColorWhite,ColorBlack); + if(app->current_view == ViewFrequencySettings) + canvas_draw_str_with_border(canvas, 1, 10, "Frequency", ColorWhite, ColorBlack); else - canvas_draw_str(canvas,1,10,"Frequency"); + canvas_draw_str(canvas, 1, 10, "Frequency"); - if (app->current_view == ViewModulationSettings) - canvas_draw_str_with_border(canvas,70,10,"Modulation",ColorWhite,ColorBlack); + if(app->current_view == ViewModulationSettings) + canvas_draw_str_with_border(canvas, 70, 10, "Modulation", ColorWhite, ColorBlack); else - canvas_draw_str(canvas,70,10,"Modulation"); + canvas_draw_str(canvas, 70, 10, "Modulation"); canvas_set_font(canvas, FontSecondary); - canvas_draw_str(canvas,10,61,"Use up and down to modify"); + canvas_draw_str(canvas, 10, 61, "Use up and down to modify"); - if (app->txrx->debug_timer_sampling) - canvas_draw_str(canvas,3,52,"(DEBUG timer sampling is ON)"); + if(app->txrx->debug_timer_sampling) + canvas_draw_str(canvas, 3, 52, "(DEBUG timer sampling is ON)"); /* Show frequency. We can use big numbers font since it's just a number. */ - if (app->current_view == ViewFrequencySettings) { + if(app->current_view == ViewFrequencySettings) { char buf[16]; - snprintf(buf,sizeof(buf),"%.2f",(double)app->frequency/1000000); + snprintf(buf, sizeof(buf), "%.2f", (double)app->frequency / 1000000); canvas_set_font(canvas, FontBigNumbers); canvas_draw_str(canvas, 30, 40, buf); - } else if (app->current_view == ViewModulationSettings) { + } else if(app->current_view == ViewModulationSettings) { int current = app->modulation; canvas_set_font(canvas, FontPrimary); canvas_draw_str(canvas, 33, 39, ProtoViewModulations[current].name); @@ -37,13 +37,13 @@ void render_view_settings(Canvas *const canvas, ProtoViewApp *app) { } /* Handle input for the settings view. */ -void process_input_settings(ProtoViewApp *app, InputEvent input) { - if (input.type == InputTypeLong && input.key == InputKeyOk) { +void process_input_settings(ProtoViewApp* app, InputEvent input) { + if(input.type == InputTypeLong && input.key == InputKeyOk) { /* Long pressing to OK sets the default frequency and * modulation. */ app->frequency = subghz_setting_get_default_frequency(app->setting); app->modulation = 0; - } else if (0 && input.type == InputTypeLong && input.key == InputKeyDown) { + } else if(0 && input.type == InputTypeLong && input.key == InputKeyDown) { /* Long pressing to down switches between normal and debug * timer sampling mode. NOTE: this feature is disabled for users, * only useful for devs (if useful at all). */ @@ -55,42 +55,40 @@ void process_input_settings(ProtoViewApp *app, InputEvent input) { app->txrx->debug_timer_sampling = !app->txrx->debug_timer_sampling; radio_begin(app); radio_rx(app); - } else if (input.type == InputTypePress && - (input.key != InputKeyDown || input.key != InputKeyUp)) - { + } else if(input.type == InputTypePress && (input.key != InputKeyDown || input.key != InputKeyUp)) { /* Handle up and down to change frequency or modulation. */ - if (app->current_view == ViewFrequencySettings) { + if(app->current_view == ViewFrequencySettings) { size_t curidx = 0, i; size_t count = subghz_setting_get_frequency_count(app->setting); /* Scan the list of frequencies to check for the index of the * currently set frequency. */ for(i = 0; i < count; i++) { - uint32_t freq = subghz_setting_get_frequency(app->setting,i); - if (freq == app->frequency) { + uint32_t freq = subghz_setting_get_frequency(app->setting, i); + if(freq == app->frequency) { curidx = i; break; } } - if (i == count) return; /* Should never happen. */ + if(i == count) return; /* Should never happen. */ - if (input.key == InputKeyUp) { - curidx = curidx == 0 ? count-1 : curidx-1; - } else if (input.key == InputKeyDown) { - curidx = (curidx+1) % count; + if(input.key == InputKeyUp) { + curidx = curidx == 0 ? count - 1 : curidx - 1; + } else if(input.key == InputKeyDown) { + curidx = (curidx + 1) % count; } else { return; } - app->frequency = subghz_setting_get_frequency(app->setting,curidx); - } else if (app->current_view == ViewModulationSettings) { + app->frequency = subghz_setting_get_frequency(app->setting, curidx); + } else if(app->current_view == ViewModulationSettings) { uint32_t count = 0; uint32_t modid = app->modulation; while(ProtoViewModulations[count].name != NULL) count++; - if (input.key == InputKeyUp) { - modid = modid == 0 ? count-1 : modid-1; - } else if (input.key == InputKeyDown) { - modid = (modid+1) % count; + if(input.key == InputKeyUp) { + modid = modid == 0 ? count - 1 : modid - 1; + } else if(input.key == InputKeyDown) { + modid = (modid + 1) % count; } else { return; } @@ -106,9 +104,13 @@ void process_input_settings(ProtoViewApp *app, InputEvent input) { /* When the user switches to some other view, if they changed the parameters * we need to restart the radio with the right frequency and modulation. */ -void view_exit_settings(ProtoViewApp *app) { - if (app->txrx->freq_mod_changed) { - FURI_LOG_E(TAG, "Setting view, setting frequency/modulation to %lu %s", app->frequency, ProtoViewModulations[app->modulation].name); +void view_exit_settings(ProtoViewApp* app) { + if(app->txrx->freq_mod_changed) { + FURI_LOG_E( + TAG, + "Setting view, setting frequency/modulation to %lu %s", + app->frequency, + ProtoViewModulations[app->modulation].name); radio_rx_end(app); radio_begin(app); radio_rx(app); diff --git a/applications/plugins/qrcode/qrcode.c b/applications/plugins/qrcode/qrcode.c index c36285a17..aed1869cf 100644 --- a/applications/plugins/qrcode/qrcode.c +++ b/applications/plugins/qrcode/qrcode.c @@ -42,40 +42,84 @@ static const uint16_t NUM_ERROR_CORRECTION_CODEWORDS[4][40] = { // 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level - { 10, 16, 26, 36, 48, 64, 72, 88, 110, 130, 150, 176, 198, 216, 240, 280, 308, 338, 364, 416, 442, 476, 504, 560, 588, 644, 700, 728, 784, 812, 868, 924, 980, 1036, 1064, 1120, 1204, 1260, 1316, 1372}, // Medium - { 7, 10, 15, 20, 26, 36, 40, 48, 60, 72, 80, 96, 104, 120, 132, 144, 168, 180, 196, 224, 224, 252, 270, 300, 312, 336, 360, 390, 420, 450, 480, 510, 540, 570, 570, 600, 630, 660, 720, 750}, // Low - { 17, 28, 44, 64, 88, 112, 130, 156, 192, 224, 264, 308, 352, 384, 432, 480, 532, 588, 650, 700, 750, 816, 900, 960, 1050, 1110, 1200, 1260, 1350, 1440, 1530, 1620, 1710, 1800, 1890, 1980, 2100, 2220, 2310, 2430}, // High - { 13, 22, 36, 52, 72, 96, 108, 132, 160, 192, 224, 260, 288, 320, 360, 408, 448, 504, 546, 600, 644, 690, 750, 810, 870, 952, 1020, 1050, 1140, 1200, 1290, 1350, 1440, 1530, 1590, 1680, 1770, 1860, 1950, 2040}, // Quartile + {10, 16, 26, 36, 48, 64, 72, 88, 110, 130, 150, 176, 198, 216, + 240, 280, 308, 338, 364, 416, 442, 476, 504, 560, 588, 644, 700, 728, + 784, 812, 868, 924, 980, 1036, 1064, 1120, 1204, 1260, 1316, 1372}, // Medium + {7, 10, 15, 20, 26, 36, 40, 48, 60, 72, 80, 96, 104, 120, + 132, 144, 168, 180, 196, 224, 224, 252, 270, 300, 312, 336, 360, 390, + 420, 450, 480, 510, 540, 570, 570, 600, 630, 660, 720, 750}, // Low + {17, 28, 44, 64, 88, 112, 130, 156, 192, 224, 264, 308, 352, 384, + 432, 480, 532, 588, 650, 700, 750, 816, 900, 960, 1050, 1110, 1200, 1260, + 1350, 1440, 1530, 1620, 1710, 1800, 1890, 1980, 2100, 2220, 2310, 2430}, // High + {13, 22, 36, 52, 72, 96, 108, 132, 160, 192, 224, 260, 288, 320, + 360, 408, 448, 504, 546, 600, 644, 690, 750, 810, 870, 952, 1020, 1050, + 1140, 1200, 1290, 1350, 1440, 1530, 1590, 1680, 1770, 1860, 1950, 2040}, // Quartile }; static const uint8_t NUM_ERROR_CORRECTION_BLOCKS[4][40] = { // Version: (note that index 0 is for padding, and is set to an illegal value) // 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level - { 1, 1, 1, 2, 2, 4, 4, 4, 5, 5, 5, 8, 9, 9, 10, 10, 11, 13, 14, 16, 17, 17, 18, 20, 21, 23, 25, 26, 28, 29, 31, 33, 35, 37, 38, 40, 43, 45, 47, 49}, // Medium - { 1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 4, 4, 4, 4, 6, 6, 6, 6, 7, 8, 8, 9, 9, 10, 12, 12, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 24, 25}, // Low - { 1, 1, 2, 4, 4, 4, 5, 6, 8, 8, 11, 11, 16, 16, 18, 16, 19, 21, 25, 25, 25, 34, 30, 32, 35, 37, 40, 42, 45, 48, 51, 54, 57, 60, 63, 66, 70, 74, 77, 81}, // High - { 1, 1, 2, 2, 4, 4, 6, 6, 8, 8, 8, 10, 12, 16, 12, 17, 16, 18, 21, 20, 23, 23, 25, 27, 29, 34, 34, 35, 38, 40, 43, 45, 48, 51, 53, 56, 59, 62, 65, 68}, // Quartile + {1, 1, 1, 2, 2, 4, 4, 4, 5, 5, 5, 8, 9, 9, 10, 10, 11, 13, 14, 16, + 17, 17, 18, 20, 21, 23, 25, 26, 28, 29, 31, 33, 35, 37, 38, 40, 43, 45, 47, 49}, // Medium + {1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 4, 4, 4, 4, 6, 6, 6, 6, 7, 8, + 8, 9, 9, 10, 12, 12, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 24, 25}, // Low + {1, 1, 2, 4, 4, 4, 5, 6, 8, 8, 11, 11, 16, 16, 18, 16, 19, 21, 25, 25, + 25, 34, 30, 32, 35, 37, 40, 42, 45, 48, 51, 54, 57, 60, 63, 66, 70, 74, 77, 81}, // High + {1, 1, 2, 2, 4, 4, 6, 6, 8, 8, 8, 10, 12, 16, 12, 17, 16, 18, 21, 20, + 23, 23, 25, 27, 29, 34, 34, 35, 38, 40, 43, 45, 48, 51, 53, 56, 59, 62, 65, 68}, // Quartile }; static const uint16_t NUM_RAW_DATA_MODULES[40] = { // 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, - 208, 359, 567, 807, 1079, 1383, 1568, 1936, 2336, 2768, 3232, 3728, 4256, 4651, 5243, 5867, 6523, + 208, + 359, + 567, + 807, + 1079, + 1383, + 1568, + 1936, + 2336, + 2768, + 3232, + 3728, + 4256, + 4651, + 5243, + 5867, + 6523, // 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 7211, 7931, 8683, 9252, 10068, 10916, 11796, 12708, 13652, 14628, 15371, 16411, 17483, 18587, + 7211, + 7931, + 8683, + 9252, + 10068, + 10916, + 11796, + 12708, + 13652, + 14628, + 15371, + 16411, + 17483, + 18587, // 32, 33, 34, 35, 36, 37, 38, 39, 40 - 19723, 20891, 22091, 23008, 24272, 25568, 26896, 28256, 29648 -}; + 19723, + 20891, + 22091, + 23008, + 24272, + 25568, + 26896, + 28256, + 29648}; // @TODO: Put other LOCK_VERSIONS here #elif LOCK_VERSION == 3 -static const int16_t NUM_ERROR_CORRECTION_CODEWORDS[4] = { - 26, 15, 44, 36 -}; +static const int16_t NUM_ERROR_CORRECTION_CODEWORDS[4] = {26, 15, 44, 36}; -static const int8_t NUM_ERROR_CORRECTION_BLOCKS[4] = { - 1, 1, 2, 2 -}; +static const int8_t NUM_ERROR_CORRECTION_BLOCKS[4] = {1, 1, 2, 2}; static const uint16_t NUM_RAW_DATA_MODULES = 567; @@ -85,9 +129,10 @@ static const uint16_t NUM_RAW_DATA_MODULES = 567; #endif - static int max(int a, int b) { - if (a > b) { return a; } + if(a > b) { + return a; + } return b; } @@ -98,44 +143,57 @@ static int abs(int value) { } */ - static int8_t getAlphanumeric(char c) { - - if (c >= '0' && c <= '9') { return (c - '0'); } - if (c >= 'A' && c <= 'Z') { return (c - 'A' + 10); } - - switch (c) { - case ' ': return 36; - case '$': return 37; - case '%': return 38; - case '*': return 39; - case '+': return 40; - case '-': return 41; - case '.': return 42; - case '/': return 43; - case ':': return 44; + if(c >= '0' && c <= '9') { + return (c - '0'); } - + if(c >= 'A' && c <= 'Z') { + return (c - 'A' + 10); + } + + switch(c) { + case ' ': + return 36; + case '$': + return 37; + case '%': + return 38; + case '*': + return 39; + case '+': + return 40; + case '-': + return 41; + case '.': + return 42; + case '/': + return 43; + case ':': + return 44; + } + return -1; } -static bool isAlphanumeric(const char *text, uint16_t length) { - while (length != 0) { - if (getAlphanumeric(text[--length]) == -1) { return false; } +static bool isAlphanumeric(const char* text, uint16_t length) { + while(length != 0) { + if(getAlphanumeric(text[--length]) == -1) { + return false; + } } return true; } - -static bool isNumeric(const char *text, uint16_t length) { - while (length != 0) { +static bool isNumeric(const char* text, uint16_t length) { + while(length != 0) { char c = text[--length]; - if (c < '0' || c > '9') { return false; } + if(c < '0' || c > '9') { + return false; + } } return true; } - // We store the following tightly packed (less 8) in modeInfo // <=9 <=26 <= 40 // NUMERIC ( 10, 12, 14); @@ -145,26 +203,31 @@ static char getModeBits(uint8_t version, uint8_t mode) { // Note: We use 15 instead of 16; since 15 doesn't exist and we cannot store 16 (8 + 8) in 3 bits // hex(int("".join(reversed([('00' + bin(x - 8)[2:])[-3:] for x in [10, 9, 8, 12, 11, 15, 14, 13, 15]])), 2)) unsigned int modeInfo = 0x7bbb80a; - + #if LOCK_VERSION == 0 || LOCK_VERSION > 9 - if (version > 9) { modeInfo >>= 9; } + if(version > 9) { + modeInfo >>= 9; + } #endif - + #if LOCK_VERSION == 0 || LOCK_VERSION > 26 - if (version > 26) { modeInfo >>= 9; } + if(version > 26) { + modeInfo >>= 9; + } #endif - + char result = 8 + ((modeInfo >> (3 * mode)) & 0x07); - if (result == 15) { result = 16; } - + if(result == 15) { + result = 16; + } + return result; } - typedef struct BitBucket { uint32_t bitOffsetOrWidth; uint16_t capacityBytes; - uint8_t *data; + uint8_t* data; } BitBucket; /* @@ -186,15 +249,15 @@ static uint16_t bb_getBufferSizeBytes(uint32_t bits) { return ((bits + 7) / 8); } -static void bb_initBuffer(BitBucket *bitBuffer, uint8_t *data, int32_t capacityBytes) { +static void bb_initBuffer(BitBucket* bitBuffer, uint8_t* data, int32_t capacityBytes) { bitBuffer->bitOffsetOrWidth = 0; bitBuffer->capacityBytes = capacityBytes; bitBuffer->data = data; - + memset(data, 0, bitBuffer->capacityBytes); } -static void bb_initGrid(BitBucket *bitGrid, uint8_t *data, uint8_t size) { +static void bb_initGrid(BitBucket* bitGrid, uint8_t* data, uint8_t size) { bitGrid->bitOffsetOrWidth = size; bitGrid->capacityBytes = bb_getGridSizeBytes(size); bitGrid->data = data; @@ -202,9 +265,9 @@ static void bb_initGrid(BitBucket *bitGrid, uint8_t *data, uint8_t size) { memset(data, 0, bitGrid->capacityBytes); } -static void bb_appendBits(BitBucket *bitBuffer, uint32_t val, uint8_t length) { +static void bb_appendBits(BitBucket* bitBuffer, uint32_t val, uint8_t length) { uint32_t offset = bitBuffer->bitOffsetOrWidth; - for (int8_t i = length - 1; i >= 0; i--, offset++) { + for(int8_t i = length - 1; i >= 0; i--, offset++) { bitBuffer->data[offset >> 3] |= ((val >> i) & 1) << (7 - (offset & 7)); } bitBuffer->bitOffsetOrWidth = offset; @@ -216,74 +279,92 @@ void bb_setBits(BitBucket *bitBuffer, uint32_t val, int offset, uint8_t length) } } */ -static void bb_setBit(BitBucket *bitGrid, uint8_t x, uint8_t y, bool on) { +static void bb_setBit(BitBucket* bitGrid, uint8_t x, uint8_t y, bool on) { uint32_t offset = y * bitGrid->bitOffsetOrWidth + x; uint8_t mask = 1 << (7 - (offset & 0x07)); - if (on) { + if(on) { bitGrid->data[offset >> 3] |= mask; } else { bitGrid->data[offset >> 3] &= ~mask; } } -static void bb_invertBit(BitBucket *bitGrid, uint8_t x, uint8_t y, bool invert) { +static void bb_invertBit(BitBucket* bitGrid, uint8_t x, uint8_t y, bool invert) { uint32_t offset = y * bitGrid->bitOffsetOrWidth + x; uint8_t mask = 1 << (7 - (offset & 0x07)); bool on = ((bitGrid->data[offset >> 3] & (1 << (7 - (offset & 0x07)))) != 0); - if (on ^ invert) { + if(on ^ invert) { bitGrid->data[offset >> 3] |= mask; } else { bitGrid->data[offset >> 3] &= ~mask; } } -static bool bb_getBit(BitBucket *bitGrid, uint8_t x, uint8_t y) { +static bool bb_getBit(BitBucket* bitGrid, uint8_t x, uint8_t y) { uint32_t offset = y * bitGrid->bitOffsetOrWidth + x; return (bitGrid->data[offset >> 3] & (1 << (7 - (offset & 0x07)))) != 0; } - // XORs the data modules in this QR Code with the given mask pattern. Due to XOR's mathematical // properties, calling applyMask(m) twice with the same value is equivalent to no change at all. // This means it is possible to apply a mask, undo it, and try another mask. Note that a final // well-formed QR Code symbol needs exactly one mask applied (not zero, not two, etc.). -static void applyMask(BitBucket *modules, BitBucket *isFunction, uint8_t mask) { +static void applyMask(BitBucket* modules, BitBucket* isFunction, uint8_t mask) { uint8_t size = modules->bitOffsetOrWidth; - - for (uint8_t y = 0; y < size; y++) { - for (uint8_t x = 0; x < size; x++) { - if (bb_getBit(isFunction, x, y)) { continue; } - + + for(uint8_t y = 0; y < size; y++) { + for(uint8_t x = 0; x < size; x++) { + if(bb_getBit(isFunction, x, y)) { + continue; + } + bool invert = 0; - switch (mask) { - case 0: invert = (x + y) % 2 == 0; break; - case 1: invert = y % 2 == 0; break; - case 2: invert = x % 3 == 0; break; - case 3: invert = (x + y) % 3 == 0; break; - case 4: invert = (x / 3 + y / 2) % 2 == 0; break; - case 5: invert = x * y % 2 + x * y % 3 == 0; break; - case 6: invert = (x * y % 2 + x * y % 3) % 2 == 0; break; - case 7: invert = ((x + y) % 2 + x * y % 3) % 2 == 0; break; + switch(mask) { + case 0: + invert = (x + y) % 2 == 0; + break; + case 1: + invert = y % 2 == 0; + break; + case 2: + invert = x % 3 == 0; + break; + case 3: + invert = (x + y) % 3 == 0; + break; + case 4: + invert = (x / 3 + y / 2) % 2 == 0; + break; + case 5: + invert = x * y % 2 + x * y % 3 == 0; + break; + case 6: + invert = (x * y % 2 + x * y % 3) % 2 == 0; + break; + case 7: + invert = ((x + y) % 2 + x * y % 3) % 2 == 0; + break; } bb_invertBit(modules, x, y, invert); } } } -static void setFunctionModule(BitBucket *modules, BitBucket *isFunction, uint8_t x, uint8_t y, bool on) { +static void + setFunctionModule(BitBucket* modules, BitBucket* isFunction, uint8_t x, uint8_t y, bool on) { bb_setBit(modules, x, y, on); bb_setBit(isFunction, x, y, true); } // Draws a 9*9 finder pattern including the border separator, with the center module at (x, y). -static void drawFinderPattern(BitBucket *modules, BitBucket *isFunction, uint8_t x, uint8_t y) { +static void drawFinderPattern(BitBucket* modules, BitBucket* isFunction, uint8_t x, uint8_t y) { uint8_t size = modules->bitOffsetOrWidth; - for (int8_t i = -4; i <= 4; i++) { - for (int8_t j = -4; j <= 4; j++) { - uint8_t dist = max(abs(i), abs(j)); // Chebyshev/infinity norm + for(int8_t i = -4; i <= 4; i++) { + for(int8_t j = -4; j <= 4; j++) { + uint8_t dist = max(abs(i), abs(j)); // Chebyshev/infinity norm int16_t xx = x + j, yy = y + i; - if (0 <= xx && xx < size && 0 <= yy && yy < size) { + if(0 <= xx && xx < size && 0 <= yy && yy < size) { setFunctionModule(modules, isFunction, xx, yy, dist != 2 && dist != 4); } } @@ -291,9 +372,9 @@ static void drawFinderPattern(BitBucket *modules, BitBucket *isFunction, uint8_t } // Draws a 5*5 alignment pattern, with the center module at (x, y). -static void drawAlignmentPattern(BitBucket *modules, BitBucket *isFunction, uint8_t x, uint8_t y) { - for (int8_t i = -2; i <= 2; i++) { - for (int8_t j = -2; j <= 2; j++) { +static void drawAlignmentPattern(BitBucket* modules, BitBucket* isFunction, uint8_t x, uint8_t y) { + for(int8_t i = -2; i <= 2; i++) { + for(int8_t j = -2; j <= 2; j++) { setFunctionModule(modules, isFunction, x + j, y + i, max(abs(i), abs(j)) != 1); } } @@ -301,157 +382,159 @@ static void drawAlignmentPattern(BitBucket *modules, BitBucket *isFunction, uint // Draws two copies of the format bits (with its own error correction code) // based on the given mask and this object's error correction level field. -static void drawFormatBits(BitBucket *modules, BitBucket *isFunction, uint8_t ecc, uint8_t mask) { - +static void drawFormatBits(BitBucket* modules, BitBucket* isFunction, uint8_t ecc, uint8_t mask) { uint8_t size = modules->bitOffsetOrWidth; // Calculate error correction code and pack bits - uint32_t data = ecc << 3 | mask; // errCorrLvl is uint2, mask is uint3 + uint32_t data = ecc << 3 | mask; // errCorrLvl is uint2, mask is uint3 uint32_t rem = data; - for (int i = 0; i < 10; i++) { + for(int i = 0; i < 10; i++) { rem = (rem << 1) ^ ((rem >> 9) * 0x537); } - + data = data << 10 | rem; - data ^= 0x5412; // uint15 - + data ^= 0x5412; // uint15 + // Draw first copy - for (uint8_t i = 0; i <= 5; i++) { + for(uint8_t i = 0; i <= 5; i++) { setFunctionModule(modules, isFunction, 8, i, ((data >> i) & 1) != 0); } - + setFunctionModule(modules, isFunction, 8, 7, ((data >> 6) & 1) != 0); setFunctionModule(modules, isFunction, 8, 8, ((data >> 7) & 1) != 0); setFunctionModule(modules, isFunction, 7, 8, ((data >> 8) & 1) != 0); - - for (int8_t i = 9; i < 15; i++) { + + for(int8_t i = 9; i < 15; i++) { setFunctionModule(modules, isFunction, 14 - i, 8, ((data >> i) & 1) != 0); } - + // Draw second copy - for (int8_t i = 0; i <= 7; i++) { + for(int8_t i = 0; i <= 7; i++) { setFunctionModule(modules, isFunction, size - 1 - i, 8, ((data >> i) & 1) != 0); } - - for (int8_t i = 8; i < 15; i++) { + + for(int8_t i = 8; i < 15; i++) { setFunctionModule(modules, isFunction, 8, size - 15 + i, ((data >> i) & 1) != 0); } - + setFunctionModule(modules, isFunction, 8, size - 8, true); } - // Draws two copies of the version bits (with its own error correction code), // based on this object's version field (which only has an effect for 7 <= version <= 40). -static void drawVersion(BitBucket *modules, BitBucket *isFunction, uint8_t version) { - +static void drawVersion(BitBucket* modules, BitBucket* isFunction, uint8_t version) { int8_t size = modules->bitOffsetOrWidth; #if LOCK_VERSION != 0 && LOCK_VERSION < 7 return; - + #else - if (version < 7) { return; } - + if(version < 7) { + return; + } + // Calculate error correction code and pack bits - uint32_t rem = version; // version is uint6, in the range [7, 40] - for (uint8_t i = 0; i < 12; i++) { + uint32_t rem = version; // version is uint6, in the range [7, 40] + for(uint8_t i = 0; i < 12; i++) { rem = (rem << 1) ^ ((rem >> 11) * 0x1F25); } - - uint32_t data = version << 12 | rem; // uint18 - + + uint32_t data = version << 12 | rem; // uint18 + // Draw two copies - for (uint8_t i = 0; i < 18; i++) { + for(uint8_t i = 0; i < 18; i++) { bool bit = ((data >> i) & 1) != 0; uint8_t a = size - 11 + i % 3, b = i / 3; setFunctionModule(modules, isFunction, a, b, bit); setFunctionModule(modules, isFunction, b, a, bit); } - + #endif } -static void drawFunctionPatterns(BitBucket *modules, BitBucket *isFunction, uint8_t version, uint8_t ecc) { - +static void + drawFunctionPatterns(BitBucket* modules, BitBucket* isFunction, uint8_t version, uint8_t ecc) { uint8_t size = modules->bitOffsetOrWidth; // Draw the horizontal and vertical timing patterns - for (uint8_t i = 0; i < size; i++) { + for(uint8_t i = 0; i < size; i++) { setFunctionModule(modules, isFunction, 6, i, i % 2 == 0); setFunctionModule(modules, isFunction, i, 6, i % 2 == 0); } - + // Draw 3 finder patterns (all corners except bottom right; overwrites some timing modules) drawFinderPattern(modules, isFunction, 3, 3); drawFinderPattern(modules, isFunction, size - 4, 3); drawFinderPattern(modules, isFunction, 3, size - 4); - + #if LOCK_VERSION == 0 || LOCK_VERSION > 1 - if (version > 1) { - + if(version > 1) { // Draw the numerous alignment patterns - + uint8_t alignCount = version / 7 + 2; uint8_t step; - if (version != 32) { - step = (version * 4 + alignCount * 2 + 1) / (2 * alignCount - 2) * 2; // ceil((size - 13) / (2*numAlign - 2)) * 2 + if(version != 32) { + step = (version * 4 + alignCount * 2 + 1) / (2 * alignCount - 2) * + 2; // ceil((size - 13) / (2*numAlign - 2)) * 2 } else { // C-C-C-Combo breaker! step = 26; } - + uint8_t alignPositionIndex = alignCount - 1; uint8_t alignPosition[alignCount]; - + alignPosition[0] = 6; - + uint8_t size = version * 4 + 17; - for (uint8_t i = 0, pos = size - 7; i < alignCount - 1; i++, pos -= step) { + for(uint8_t i = 0, pos = size - 7; i < alignCount - 1; i++, pos -= step) { alignPosition[alignPositionIndex--] = pos; } - - for (uint8_t i = 0; i < alignCount; i++) { - for (uint8_t j = 0; j < alignCount; j++) { - if ((i == 0 && j == 0) || (i == 0 && j == alignCount - 1) || (i == alignCount - 1 && j == 0)) { - continue; // Skip the three finder corners + + for(uint8_t i = 0; i < alignCount; i++) { + for(uint8_t j = 0; j < alignCount; j++) { + if((i == 0 && j == 0) || (i == 0 && j == alignCount - 1) || + (i == alignCount - 1 && j == 0)) { + continue; // Skip the three finder corners } else { drawAlignmentPattern(modules, isFunction, alignPosition[i], alignPosition[j]); } } } } - + #endif - + // Draw configuration data - drawFormatBits(modules, isFunction, ecc, 0); // Dummy mask value; overwritten later in the constructor + drawFormatBits( + modules, isFunction, ecc, 0); // Dummy mask value; overwritten later in the constructor drawVersion(modules, isFunction, version); } - // Draws the given sequence of 8-bit codewords (data and error correction) onto the entire // data area of this QR Code symbol. Function modules need to be marked off before this is called. -static void drawCodewords(BitBucket *modules, BitBucket *isFunction, BitBucket *codewords) { - +static void drawCodewords(BitBucket* modules, BitBucket* isFunction, BitBucket* codewords) { uint32_t bitLength = codewords->bitOffsetOrWidth; - uint8_t *data = codewords->data; - + uint8_t* data = codewords->data; + uint8_t size = modules->bitOffsetOrWidth; - + // Bit index into the data uint32_t i = 0; - + // Do the funny zigzag scan - for (int16_t right = size - 1; right >= 1; right -= 2) { // Index of right column in each column pair - if (right == 6) { right = 5; } - - for (uint8_t vert = 0; vert < size; vert++) { // Vertical counter - for (int j = 0; j < 2; j++) { - uint8_t x = right - j; // Actual x coordinate + for(int16_t right = size - 1; right >= 1; + right -= 2) { // Index of right column in each column pair + if(right == 6) { + right = 5; + } + + for(uint8_t vert = 0; vert < size; vert++) { // Vertical counter + for(int j = 0; j < 2; j++) { + uint8_t x = right - j; // Actual x coordinate bool upwards = ((right & 2) == 0) ^ (x < 6); - uint8_t y = upwards ? size - 1 - vert : vert; // Actual y coordinate - if (!bb_getBit(isFunction, x, y) && i < bitLength) { + uint8_t y = upwards ? size - 1 - vert : vert; // Actual y coordinate + if(!bb_getBit(isFunction, x, y) && i < bitLength) { bb_setBit(modules, x, y, ((data[i >> 3] >> (7 - (i & 7))) & 1) != 0); i++; } @@ -462,73 +545,70 @@ static void drawCodewords(BitBucket *modules, BitBucket *isFunction, BitBucket * } } - - -#define PENALTY_N1 3 -#define PENALTY_N2 3 -#define PENALTY_N3 40 -#define PENALTY_N4 10 +#define PENALTY_N1 3 +#define PENALTY_N2 3 +#define PENALTY_N3 40 +#define PENALTY_N4 10 // Calculates and returns the penalty score based on state of this QR Code's current modules. // This is used by the automatic mask choice algorithm to find the mask pattern that yields the lowest score. // @TODO: This can be optimized by working with the bytes instead of bits. -static uint32_t getPenaltyScore(BitBucket *modules) { +static uint32_t getPenaltyScore(BitBucket* modules) { uint32_t result = 0; - + uint8_t size = modules->bitOffsetOrWidth; - + // Adjacent modules in row having same color - for (uint8_t y = 0; y < size; y++) { - + for(uint8_t y = 0; y < size; y++) { bool colorX = bb_getBit(modules, 0, y); - for (uint8_t x = 1, runX = 1; x < size; x++) { + for(uint8_t x = 1, runX = 1; x < size; x++) { bool cx = bb_getBit(modules, x, y); - if (cx != colorX) { + if(cx != colorX) { colorX = cx; runX = 1; - + } else { runX++; - if (runX == 5) { + if(runX == 5) { result += PENALTY_N1; - } else if (runX > 5) { + } else if(runX > 5) { result++; } } } } - + // Adjacent modules in column having same color - for (uint8_t x = 0; x < size; x++) { + for(uint8_t x = 0; x < size; x++) { bool colorY = bb_getBit(modules, x, 0); - for (uint8_t y = 1, runY = 1; y < size; y++) { + for(uint8_t y = 1, runY = 1; y < size; y++) { bool cy = bb_getBit(modules, x, y); - if (cy != colorY) { + if(cy != colorY) { colorY = cy; runY = 1; } else { runY++; - if (runY == 5) { + if(runY == 5) { result += PENALTY_N1; - } else if (runY > 5) { + } else if(runY > 5) { result++; } } } } - + uint16_t black = 0; - for (uint8_t y = 0; y < size; y++) { + for(uint8_t y = 0; y < size; y++) { uint16_t bitsRow = 0, bitsCol = 0; - for (uint8_t x = 0; x < size; x++) { + for(uint8_t x = 0; x < size; x++) { bool color = bb_getBit(modules, x, y); // 2*2 blocks of modules having same color - if (x > 0 && y > 0) { + if(x > 0 && y > 0) { bool colorUL = bb_getBit(modules, x - 1, y - 1); bool colorUR = bb_getBit(modules, x, y - 1); bool colorL = bb_getBit(modules, x - 1, y); - if (color == colorUL && color == colorUR && color == colorL) { + if(color == colorUL && color == colorUR && color == colorL) { result += PENALTY_N2; } } @@ -538,146 +618,154 @@ static uint32_t getPenaltyScore(BitBucket *modules) { bitsCol = ((bitsCol << 1) & 0x7FF) | bb_getBit(modules, y, x); // Needs 11 bits accumulated - if (x >= 10) { - if (bitsRow == 0x05D || bitsRow == 0x5D0) { + if(x >= 10) { + if(bitsRow == 0x05D || bitsRow == 0x5D0) { result += PENALTY_N3; } - if (bitsCol == 0x05D || bitsCol == 0x5D0) { + if(bitsCol == 0x05D || bitsCol == 0x5D0) { result += PENALTY_N3; } } // Balance of black and white modules - if (color) { black++; } + if(color) { + black++; + } } } // Find smallest k such that (45-5k)% <= dark/total <= (55+5k)% uint16_t total = size * size; - for (uint16_t k = 0; black * 20 < (9 - k) * total || black * 20 > (11 + k) * total; k++) { + for(uint16_t k = 0; black * 20 < (9 - k) * total || black * 20 > (11 + k) * total; k++) { result += PENALTY_N4; } - + return result; } - static uint8_t rs_multiply(uint8_t x, uint8_t y) { // Russian peasant multiplication // See: https://en.wikipedia.org/wiki/Ancient_Egyptian_multiplication uint16_t z = 0; - for (int8_t i = 7; i >= 0; i--) { + for(int8_t i = 7; i >= 0; i--) { z = (z << 1) ^ ((z >> 7) * 0x11D); z ^= ((y >> i) & 1) * x; } return z; } -static void rs_init(uint8_t degree, uint8_t *coeff) { +static void rs_init(uint8_t degree, uint8_t* coeff) { memset(coeff, 0, degree); coeff[degree - 1] = 1; - + // Compute the product polynomial (x - r^0) * (x - r^1) * (x - r^2) * ... * (x - r^{degree-1}), // drop the highest term, and store the rest of the coefficients in order of descending powers. // Note that r = 0x02, which is a generator element of this field GF(2^8/0x11D). uint16_t root = 1; - for (uint8_t i = 0; i < degree; i++) { + for(uint8_t i = 0; i < degree; i++) { // Multiply the current product by (x - r^i) - for (uint8_t j = 0; j < degree; j++) { + for(uint8_t j = 0; j < degree; j++) { coeff[j] = rs_multiply(coeff[j], root); - if (j + 1 < degree) { + if(j + 1 < degree) { coeff[j] ^= coeff[j + 1]; } } - root = (root << 1) ^ ((root >> 7) * 0x11D); // Multiply by 0x02 mod GF(2^8/0x11D) + root = (root << 1) ^ ((root >> 7) * 0x11D); // Multiply by 0x02 mod GF(2^8/0x11D) } } -static void rs_getRemainder(uint8_t degree, uint8_t *coeff, uint8_t *data, uint8_t length, uint8_t *result, uint8_t stride) { +static void rs_getRemainder( + uint8_t degree, + uint8_t* coeff, + uint8_t* data, + uint8_t length, + uint8_t* result, + uint8_t stride) { // Compute the remainder by performing polynomial division - + //for (uint8_t i = 0; i < degree; i++) { result[] = 0; } //memset(result, 0, degree); - - for (uint8_t i = 0; i < length; i++) { + + for(uint8_t i = 0; i < length; i++) { uint8_t factor = data[i] ^ result[0]; - for (uint8_t j = 1; j < degree; j++) { + for(uint8_t j = 1; j < degree; j++) { result[(j - 1) * stride] = result[j * stride]; } result[(degree - 1) * stride] = 0; - - for (uint8_t j = 0; j < degree; j++) { + + for(uint8_t j = 0; j < degree; j++) { result[j * stride] ^= rs_multiply(coeff[j], factor); } } } - - -static int8_t encodeDataCodewords(BitBucket *dataCodewords, const uint8_t *text, uint16_t length, uint8_t version) { +static int8_t encodeDataCodewords( + BitBucket* dataCodewords, + const uint8_t* text, + uint16_t length, + uint8_t version) { int8_t mode = MODE_BYTE; - - if (isNumeric((char*)text, length)) { + + if(isNumeric((char*)text, length)) { mode = MODE_NUMERIC; bb_appendBits(dataCodewords, 1 << MODE_NUMERIC, 4); bb_appendBits(dataCodewords, length, getModeBits(version, MODE_NUMERIC)); uint16_t accumData = 0; uint8_t accumCount = 0; - for (uint16_t i = 0; i < length; i++) { + for(uint16_t i = 0; i < length; i++) { accumData = accumData * 10 + ((char)(text[i]) - '0'); accumCount++; - if (accumCount == 3) { + if(accumCount == 3) { bb_appendBits(dataCodewords, accumData, 10); accumData = 0; accumCount = 0; } } - + // 1 or 2 digits remaining - if (accumCount > 0) { + if(accumCount > 0) { bb_appendBits(dataCodewords, accumData, accumCount * 3 + 1); } - - } else if (isAlphanumeric((char*)text, length)) { + + } else if(isAlphanumeric((char*)text, length)) { mode = MODE_ALPHANUMERIC; bb_appendBits(dataCodewords, 1 << MODE_ALPHANUMERIC, 4); bb_appendBits(dataCodewords, length, getModeBits(version, MODE_ALPHANUMERIC)); uint16_t accumData = 0; uint8_t accumCount = 0; - for (uint16_t i = 0; i < length; i++) { + for(uint16_t i = 0; i < length; i++) { accumData = accumData * 45 + getAlphanumeric((char)(text[i])); accumCount++; - if (accumCount == 2) { + if(accumCount == 2) { bb_appendBits(dataCodewords, accumData, 11); accumData = 0; accumCount = 0; } } - + // 1 character remaining - if (accumCount > 0) { + if(accumCount > 0) { bb_appendBits(dataCodewords, accumData, 6); } - + } else { bb_appendBits(dataCodewords, 1 << MODE_BYTE, 4); bb_appendBits(dataCodewords, length, getModeBits(version, MODE_BYTE)); - for (uint16_t i = 0; i < length; i++) { + for(uint16_t i = 0; i < length; i++) { bb_appendBits(dataCodewords, (char)(text[i]), 8); } } - + //bb_setBits(dataCodewords, length, 4, getModeBits(version, mode)); - + return mode; } -static void performErrorCorrection(uint8_t version, uint8_t ecc, BitBucket *data) { - +static void performErrorCorrection(uint8_t version, uint8_t ecc, BitBucket* data) { // See: http://www.thonky.com/qr-code-tutorial/structure-final-message - + #if LOCK_VERSION == 0 uint8_t numBlocks = NUM_ERROR_CORRECTION_BLOCKS[ecc][version - 1]; uint16_t totalEcc = NUM_ERROR_CORRECTION_CODEWORDS[ecc][version - 1]; @@ -687,63 +775,68 @@ static void performErrorCorrection(uint8_t version, uint8_t ecc, BitBucket *data uint16_t totalEcc = NUM_ERROR_CORRECTION_CODEWORDS[ecc]; uint16_t moduleCount = NUM_RAW_DATA_MODULES; #endif - + uint8_t blockEccLen = totalEcc / numBlocks; uint8_t numShortBlocks = numBlocks - moduleCount / 8 % numBlocks; uint8_t shortBlockLen = moduleCount / 8 / numBlocks; - + uint8_t shortDataBlockLen = shortBlockLen - blockEccLen; - + uint8_t result[data->capacityBytes]; memset(result, 0, sizeof(result)); - + uint8_t coeff[blockEccLen]; rs_init(blockEccLen, coeff); - + uint16_t offset = 0; - uint8_t *dataBytes = data->data; - - + uint8_t* dataBytes = data->data; + // Interleave all short blocks - for (uint8_t i = 0; i < shortDataBlockLen; i++) { + for(uint8_t i = 0; i < shortDataBlockLen; i++) { uint16_t index = i; uint8_t stride = shortDataBlockLen; - for (uint8_t blockNum = 0; blockNum < numBlocks; blockNum++) { + for(uint8_t blockNum = 0; blockNum < numBlocks; blockNum++) { result[offset++] = dataBytes[index]; - + #if LOCK_VERSION == 0 || LOCK_VERSION >= 5 - if (blockNum == numShortBlocks) { stride++; } + if(blockNum == numShortBlocks) { + stride++; + } #endif index += stride; } } - + // Version less than 5 only have short blocks #if LOCK_VERSION == 0 || LOCK_VERSION >= 5 { // Interleave long blocks uint16_t index = shortDataBlockLen * (numShortBlocks + 1); uint8_t stride = shortDataBlockLen; - for (uint8_t blockNum = 0; blockNum < numBlocks - numShortBlocks; blockNum++) { + for(uint8_t blockNum = 0; blockNum < numBlocks - numShortBlocks; blockNum++) { result[offset++] = dataBytes[index]; - - if (blockNum == 0) { stride++; } + + if(blockNum == 0) { + stride++; + } index += stride; } } #endif - + // Add all ecc blocks, interleaved uint8_t blockSize = shortDataBlockLen; - for (uint8_t blockNum = 0; blockNum < numBlocks; blockNum++) { - + for(uint8_t blockNum = 0; blockNum < numBlocks; blockNum++) { #if LOCK_VERSION == 0 || LOCK_VERSION >= 5 - if (blockNum == numShortBlocks) { blockSize++; } + if(blockNum == numShortBlocks) { + blockSize++; + } #endif - rs_getRemainder(blockEccLen, coeff, dataBytes, blockSize, &result[offset + blockNum], numBlocks); + rs_getRemainder( + blockEccLen, coeff, dataBytes, blockSize, &result[offset + blockNum], numBlocks); dataBytes += blockSize; } - + memcpy(data->data, result, data->capacityBytes); data->bitOffsetOrWidth = moduleCount; } @@ -752,94 +845,110 @@ static void performErrorCorrection(uint8_t version, uint8_t ecc, BitBucket *data // The format bits can be determined by ECC_FORMAT_BITS >> (2 * ecc) static const uint8_t ECC_FORMAT_BITS = (0x02 << 6) | (0x03 << 4) | (0x00 << 2) | (0x01 << 0); - uint16_t qrcode_getBufferSize(uint8_t version) { return bb_getGridSizeBytes(4 * version + 17); } // @TODO: Return error if data is too big. -int8_t qrcode_initBytes(QRCode *qrcode, uint8_t *modules, uint8_t version, uint8_t ecc, uint8_t *data, uint16_t length) { +int8_t qrcode_initBytes( + QRCode* qrcode, + uint8_t* modules, + uint8_t version, + uint8_t ecc, + uint8_t* data, + uint16_t length) { uint8_t size = version * 4 + 17; qrcode->version = version; qrcode->size = size; qrcode->ecc = ecc; qrcode->modules = modules; - + uint8_t eccFormatBits = (ECC_FORMAT_BITS >> (2 * ecc)) & 0x03; - + #if LOCK_VERSION == 0 uint16_t moduleCount = NUM_RAW_DATA_MODULES[version - 1]; - uint16_t dataCapacity = moduleCount / 8 - NUM_ERROR_CORRECTION_CODEWORDS[eccFormatBits][version - 1]; + uint16_t dataCapacity = + moduleCount / 8 - NUM_ERROR_CORRECTION_CODEWORDS[eccFormatBits][version - 1]; #else version = LOCK_VERSION; uint16_t moduleCount = NUM_RAW_DATA_MODULES; uint16_t dataCapacity = moduleCount / 8 - NUM_ERROR_CORRECTION_CODEWORDS[eccFormatBits]; #endif - + struct BitBucket codewords; uint8_t codewordBytes[bb_getBufferSizeBytes(moduleCount)]; bb_initBuffer(&codewords, codewordBytes, (int32_t)sizeof(codewordBytes)); - + // Place the data code words into the buffer int8_t mode = encodeDataCodewords(&codewords, data, length, version); - - if (mode < 0) { return -1; } + + if(mode < 0) { + return -1; + } qrcode->mode = mode; - + // Add terminator and pad up to a byte if applicable uint32_t padding = (dataCapacity * 8) - codewords.bitOffsetOrWidth; - if (padding > 4) { padding = 4; } + if(padding > 4) { + padding = 4; + } bb_appendBits(&codewords, 0, padding); bb_appendBits(&codewords, 0, (8 - codewords.bitOffsetOrWidth % 8) % 8); // Pad with alternate bytes until data capacity is reached - for (uint8_t padByte = 0xEC; codewords.bitOffsetOrWidth < (dataCapacity * 8); padByte ^= 0xEC ^ 0x11) { + for(uint8_t padByte = 0xEC; codewords.bitOffsetOrWidth < (dataCapacity * 8); + padByte ^= 0xEC ^ 0x11) { bb_appendBits(&codewords, padByte, 8); } BitBucket modulesGrid; bb_initGrid(&modulesGrid, modules, size); - + BitBucket isFunctionGrid; uint8_t isFunctionGridBytes[bb_getGridSizeBytes(size)]; bb_initGrid(&isFunctionGrid, isFunctionGridBytes, size); - + // Draw function patterns, draw all codewords, do masking drawFunctionPatterns(&modulesGrid, &isFunctionGrid, version, eccFormatBits); performErrorCorrection(version, eccFormatBits, &codewords); drawCodewords(&modulesGrid, &isFunctionGrid, &codewords); - + // Find the best (lowest penalty) mask uint8_t mask = 0; int32_t minPenalty = INT32_MAX; - for (uint8_t i = 0; i < 8; i++) { + for(uint8_t i = 0; i < 8; i++) { drawFormatBits(&modulesGrid, &isFunctionGrid, eccFormatBits, i); applyMask(&modulesGrid, &isFunctionGrid, i); int penalty = getPenaltyScore(&modulesGrid); - if (penalty < minPenalty) { + if(penalty < minPenalty) { mask = i; minPenalty = penalty; } - applyMask(&modulesGrid, &isFunctionGrid, i); // Undoes the mask due to XOR + applyMask(&modulesGrid, &isFunctionGrid, i); // Undoes the mask due to XOR } - + qrcode->mask = mask; - + // Overwrite old format bits drawFormatBits(&modulesGrid, &isFunctionGrid, eccFormatBits, mask); - + // Apply the final choice of mask applyMask(&modulesGrid, &isFunctionGrid, mask); return 0; } -int8_t qrcode_initText(QRCode *qrcode, uint8_t *modules, uint8_t version, uint8_t ecc, const char *data) { +int8_t qrcode_initText( + QRCode* qrcode, + uint8_t* modules, + uint8_t version, + uint8_t ecc, + const char* data) { return qrcode_initBytes(qrcode, modules, version, ecc, (uint8_t*)data, strlen(data)); } -bool qrcode_getModule(QRCode *qrcode, uint8_t x, uint8_t y) { - if (x >= qrcode->size || y >= qrcode->size) { +bool qrcode_getModule(QRCode* qrcode, uint8_t x, uint8_t y) { + if(x >= qrcode->size || y >= qrcode->size) { return false; } diff --git a/applications/plugins/qrcode/qrcode.h b/applications/plugins/qrcode/qrcode.h index 6e8bf1c36..12f2d9ab3 100644 --- a/applications/plugins/qrcode/qrcode.h +++ b/applications/plugins/qrcode/qrcode.h @@ -33,7 +33,6 @@ * See: https://github.com/nayuki/QR-Code-generator/tree/master/cpp */ - #ifndef __QRCODE_H_ #define __QRCODE_H_ @@ -46,55 +45,56 @@ #include #include - // QR Code Format Encoding -#define MODE_NUMERIC 0 -#define MODE_ALPHANUMERIC 1 -#define MODE_BYTE 2 - +#define MODE_NUMERIC 0 +#define MODE_ALPHANUMERIC 1 +#define MODE_BYTE 2 // Error Correction Code Levels -#define ECC_LOW 0 -#define ECC_MEDIUM 1 -#define ECC_QUARTILE 2 -#define ECC_HIGH 3 - +#define ECC_LOW 0 +#define ECC_MEDIUM 1 +#define ECC_QUARTILE 2 +#define ECC_HIGH 3 // If set to non-zero, this library can ONLY produce QR codes at that version // This saves a lot of dynamic memory, as the codeword tables are skipped #ifndef LOCK_VERSION -#define LOCK_VERSION 0 +#define LOCK_VERSION 0 #endif - typedef struct QRCode { uint8_t version; uint8_t size; uint8_t ecc; uint8_t mode; uint8_t mask; - uint8_t *modules; + uint8_t* modules; } QRCode; - #ifdef __cplusplus -extern "C"{ -#endif /* __cplusplus */ - - +extern "C" { +#endif /* __cplusplus */ uint16_t qrcode_getBufferSize(uint8_t version); -int8_t qrcode_initText(QRCode *qrcode, uint8_t *modules, uint8_t version, uint8_t ecc, const char *data); -int8_t qrcode_initBytes(QRCode *qrcode, uint8_t *modules, uint8_t version, uint8_t ecc, uint8_t *data, uint16_t length); - -bool qrcode_getModule(QRCode *qrcode, uint8_t x, uint8_t y); - +int8_t qrcode_initText( + QRCode* qrcode, + uint8_t* modules, + uint8_t version, + uint8_t ecc, + const char* data); +int8_t qrcode_initBytes( + QRCode* qrcode, + uint8_t* modules, + uint8_t version, + uint8_t ecc, + uint8_t* data, + uint16_t length); +bool qrcode_getModule(QRCode* qrcode, uint8_t x, uint8_t y); #ifdef __cplusplus } -#endif /* __cplusplus */ +#endif /* __cplusplus */ - -#endif /* __QRCODE_H_ */ +#endif /* __QRCODE_H_ */ diff --git a/applications/plugins/qrcode/qrcode_app.c b/applications/plugins/qrcode/qrcode_app.c index 8a4d36783..056f04eb9 100644 --- a/applications/plugins/qrcode/qrcode_app.c +++ b/applications/plugins/qrcode/qrcode_app.c @@ -28,22 +28,22 @@ static const uint16_t MAX_LENGTH[3][4][MAX_QRCODE_VERSION] = { // Numeric {41, 77, 127, 187, 255, 322, 370, 461, 552, 652, 772}, // Low {34, 63, 101, 149, 202, 255, 293, 365, 432, 513, 604}, // Medium - {27, 48, 77, 111, 144, 178, 207, 259, 312, 364, 427}, // Quartile - {17, 34, 58, 82, 106, 139, 154, 202, 235, 288, 331}, // High + {27, 48, 77, 111, 144, 178, 207, 259, 312, 364, 427}, // Quartile + {17, 34, 58, 82, 106, 139, 154, 202, 235, 288, 331}, // High }, { // Alphanumeric {25, 47, 77, 114, 154, 195, 224, 279, 335, 395, 468}, // Low - {20, 38, 61, 90, 122, 154, 178, 221, 262, 311, 366}, // Medium - {16, 29, 47, 67, 87, 108, 125, 157, 189, 221, 259}, // Quartile - {10, 20, 35, 50, 64, 84, 93, 122, 143, 174, 200}, // High + {20, 38, 61, 90, 122, 154, 178, 221, 262, 311, 366}, // Medium + {16, 29, 47, 67, 87, 108, 125, 157, 189, 221, 259}, // Quartile + {10, 20, 35, 50, 64, 84, 93, 122, 143, 174, 200}, // High }, { // Binary {17, 32, 53, 78, 106, 134, 154, 192, 230, 271, 321}, // Low - {14, 26, 42, 62, 84, 106, 122, 152, 180, 213, 251}, // Medium - {11, 20, 32, 46, 60, 74, 86, 108, 130, 151, 177}, // Quartile - {7, 14, 24, 34, 44, 58, 64, 84, 98, 119, 137}, // High + {14, 26, 42, 62, 84, 106, 122, 152, 180, 213, 251}, // Medium + {11, 20, 32, 46, 60, 74, 86, 108, 130, 151, 177}, // Quartile + {7, 14, 24, 34, 44, 58, 64, 84, 98, 119, 137}, // High }, }; @@ -72,12 +72,17 @@ typedef struct { * @returns a character corresponding to the ecc level */ static char get_ecc_char(uint8_t ecc) { - switch (ecc) { - case 0: return 'L'; - case 1: return 'M'; - case 2: return 'Q'; - case 3: return 'H'; - default: return '?'; + switch(ecc) { + case 0: + return 'L'; + case 1: + return 'M'; + case 2: + return 'Q'; + case 3: + return 'H'; + default: + return '?'; } } @@ -86,12 +91,17 @@ static char get_ecc_char(uint8_t ecc) { * @returns a character corresponding to the mode */ static char get_mode_char(uint8_t mode) { - switch (mode) { - case 0: return 'N'; - case 1: return 'A'; - case 2: return 'B'; - case 3: return 'K'; - default: return '?'; + switch(mode) { + case 0: + return 'N'; + case 1: + return 'A'; + case 2: + return 'B'; + case 3: + return 'K'; + default: + return '?'; } } @@ -114,68 +124,108 @@ static void render_callback(Canvas* canvas, void* ctx) { uint8_t font_height = canvas_current_font_height(canvas); uint8_t width = canvas_width(canvas); uint8_t height = canvas_height(canvas); - if (instance->loading) { - canvas_draw_str_aligned(canvas, width / 2, height / 2, AlignCenter, AlignCenter, "Loading..."); - } else if (instance->qrcode) { + if(instance->loading) { + canvas_draw_str_aligned( + canvas, width / 2, height / 2, AlignCenter, AlignCenter, "Loading..."); + } else if(instance->qrcode) { uint8_t size = instance->qrcode->size; uint8_t pixel_size = height / size; uint8_t top = (height - pixel_size * size) / 2; uint8_t left = ((instance->show_stats ? 65 : width) - pixel_size * size) / 2; - for (uint8_t y = 0; y < size; y++) { - for (uint8_t x = 0; x < size; x++) { - if (qrcode_getModule(instance->qrcode, x, y)) { - if (pixel_size == 1) { + for(uint8_t y = 0; y < size; y++) { + for(uint8_t x = 0; x < size; x++) { + if(qrcode_getModule(instance->qrcode, x, y)) { + if(pixel_size == 1) { canvas_draw_dot(canvas, left + x * pixel_size, top + y * pixel_size); } else { - canvas_draw_box(canvas, left + x * pixel_size, top + y * pixel_size, pixel_size, pixel_size); + canvas_draw_box( + canvas, + left + x * pixel_size, + top + y * pixel_size, + pixel_size, + pixel_size); } } } } - if (instance->show_stats) { + if(instance->show_stats) { top = 10; left = 66; FuriString* str = furi_string_alloc(); - if (!instance->edit || instance->selected_idx == 0) { + if(!instance->edit || instance->selected_idx == 0) { furi_string_printf(str, "Ver: %i", instance->set_version); canvas_draw_str(canvas, left + 5, top + font_height, furi_string_get_cstr(str)); - if (instance->selected_idx == 0) { - canvas_draw_triangle(canvas, left, top + font_height / 2, font_height - 4, 4, CanvasDirectionLeftToRight); + if(instance->selected_idx == 0) { + canvas_draw_triangle( + canvas, + left, + top + font_height / 2, + font_height - 4, + 4, + CanvasDirectionLeftToRight); } - if (instance->edit) { + if(instance->edit) { uint8_t arrow_left = left + 5 + canvas_string_width(canvas, "Ver: 8") / 2; - canvas_draw_triangle(canvas, arrow_left, top, font_height - 4, 4, CanvasDirectionBottomToTop); - canvas_draw_triangle(canvas, arrow_left, top + font_height + 1, font_height - 4, 4, CanvasDirectionTopToBottom); + canvas_draw_triangle( + canvas, arrow_left, top, font_height - 4, 4, CanvasDirectionBottomToTop); + canvas_draw_triangle( + canvas, + arrow_left, + top + font_height + 1, + font_height - 4, + 4, + CanvasDirectionTopToBottom); } } - if (!instance->edit || instance->selected_idx == 1) { + if(!instance->edit || instance->selected_idx == 1) { furi_string_printf(str, "ECC: %c", get_ecc_char(instance->set_ecc)); - canvas_draw_str(canvas, left + 5, 2 * font_height + top + 2, furi_string_get_cstr(str)); - if (instance->selected_idx == 1) { - canvas_draw_triangle(canvas, left, 3 * font_height / 2 + top + 2, font_height - 4, 4, CanvasDirectionLeftToRight); + canvas_draw_str( + canvas, left + 5, 2 * font_height + top + 2, furi_string_get_cstr(str)); + if(instance->selected_idx == 1) { + canvas_draw_triangle( + canvas, + left, + 3 * font_height / 2 + top + 2, + font_height - 4, + 4, + CanvasDirectionLeftToRight); } - if (instance->edit) { + if(instance->edit) { uint8_t arrow_left = left + 5 + canvas_string_width(canvas, "ECC: H") / 2; - canvas_draw_triangle(canvas, arrow_left, font_height + top + 2, font_height - 4, 4, CanvasDirectionBottomToTop); - canvas_draw_triangle(canvas, arrow_left, 2 * font_height + top + 3, font_height - 4, 4, CanvasDirectionTopToBottom); + canvas_draw_triangle( + canvas, + arrow_left, + font_height + top + 2, + font_height - 4, + 4, + CanvasDirectionBottomToTop); + canvas_draw_triangle( + canvas, + arrow_left, + 2 * font_height + top + 3, + font_height - 4, + 4, + CanvasDirectionTopToBottom); } } - if (!instance->edit) { + if(!instance->edit) { furi_string_printf(str, "Mod: %c", get_mode_char(instance->qrcode->mode)); - canvas_draw_str(canvas, left + 5, 3 * font_height + top + 4, furi_string_get_cstr(str)); + canvas_draw_str( + canvas, left + 5, 3 * font_height + top + 4, furi_string_get_cstr(str)); } furi_string_free(str); } } else { uint8_t margin = (height - font_height * 2) / 3; - canvas_draw_str_aligned(canvas, width / 2, margin, AlignCenter, AlignTop, "Could not load qrcode."); - if (instance->too_long) { + canvas_draw_str_aligned( + canvas, width / 2, margin, AlignCenter, AlignTop, "Could not load qrcode."); + if(instance->too_long) { canvas_set_font(canvas, FontSecondary); canvas_draw_str(canvas, width / 2, margin * 2 + font_height, "Message is too long."); } @@ -192,7 +242,7 @@ static void render_callback(Canvas* canvas, void* ctx) { static void input_callback(InputEvent* input_event, void* ctx) { furi_assert(input_event); furi_assert(ctx); - if (input_event->type == InputTypeShort) { + if(input_event->type == InputTypeShort) { QRCodeApp* instance = ctx; furi_message_queue_put(instance->input_queue, input_event, 0); } @@ -205,9 +255,9 @@ static void input_callback(InputEvent* input_event, void* ctx) { */ static bool is_numeric(const char* str, uint16_t len) { furi_assert(str); - while (len > 0) { + while(len > 0) { char c = str[--len]; - if (c < '0' || c > '9') return false; + if(c < '0' || c > '9') return false; } return true; } @@ -219,19 +269,12 @@ static bool is_numeric(const char* str, uint16_t len) { */ static bool is_alphanumeric(const char* str, uint16_t len) { furi_assert(str); - while (len > 0) { + while(len > 0) { char c = str[--len]; - if (c >= '0' && c <= '9') continue; - if (c >= 'A' && c <= 'Z') continue; - if (c == ' ' - || c == '$' - || c == '%' - || c == '*' - || c == '+' - || c == '-' - || c == '.' - || c == '/' - || c == ':') + if(c >= '0' && c <= '9') continue; + if(c >= 'A' && c <= 'Z') continue; + if(c == ' ' || c == '$' || c == '%' || c == '*' || c == '+' || c == '-' || c == '.' || + c == '/' || c == ':') continue; return false; } @@ -277,8 +320,9 @@ static bool rebuild_qrcode(QRCodeApp* instance, uint8_t version, uint8_t ecc) { uint16_t len = strlen(cstr); instance->qrcode = qrcode_alloc(version); - int8_t res = qrcode_initBytes(instance->qrcode, instance->qrcode->modules, version, ecc, (uint8_t*)cstr, len); - if (res != 0) { + int8_t res = qrcode_initBytes( + instance->qrcode, instance->qrcode->modules, version, ecc, (uint8_t*)cstr, len); + if(res != 0) { FURI_LOG_E(TAG, "Could not create qrcode"); qrcode_free(instance->qrcode); @@ -300,11 +344,11 @@ static bool qrcode_load_string(QRCodeApp* instance, FuriString* str) { furi_assert(str); furi_check(furi_mutex_acquire(instance->mutex, FuriWaitForever) == FuriStatusOk); - if (instance->message) { + if(instance->message) { furi_string_free(instance->message); instance->message = NULL; } - if (instance->qrcode) { + if(instance->qrcode) { qrcode_free(instance->qrcode); instance->qrcode = NULL; } @@ -319,15 +363,17 @@ static bool qrcode_load_string(QRCodeApp* instance, FuriString* str) { uint16_t len = strlen(cstr); instance->message = furi_string_alloc_set(str); - if (!instance->message) { + if(!instance->message) { FURI_LOG_E(TAG, "Could not allocate message"); break; } // figure out the qrcode "mode" uint8_t mode = MODE_BYTE; - if (is_numeric(cstr, len)) mode = MODE_NUMERIC; - else if (is_alphanumeric(cstr, len)) mode = MODE_ALPHANUMERIC; + if(is_numeric(cstr, len)) + mode = MODE_NUMERIC; + else if(is_alphanumeric(cstr, len)) + mode = MODE_ALPHANUMERIC; // Figure out the smallest qrcode version that'll fit all of the data - // we prefer the smallest version to maximize the pixel size of each @@ -336,11 +382,11 @@ static bool qrcode_load_string(QRCodeApp* instance, FuriString* str) { // number, so we'll add one later. uint8_t ecc = ECC_LOW; uint8_t version = 0; - while (version < MAX_QRCODE_VERSION && MAX_LENGTH[mode][ecc][version] < len) { + while(version < MAX_QRCODE_VERSION && MAX_LENGTH[mode][ecc][version] < len) { version++; } - if (version == MAX_QRCODE_VERSION) { + if(version == MAX_QRCODE_VERSION) { instance->too_long = true; break; } @@ -350,13 +396,13 @@ static bool qrcode_load_string(QRCodeApp* instance, FuriString* str) { // above that ECC_LOW (0) works... don't forget to add one to that // version number... ecc = ECC_HIGH; - while (MAX_LENGTH[mode][ecc][version] < len) { + while(MAX_LENGTH[mode][ecc][version] < len) { ecc--; } version++; // Build the qrcode - if (!rebuild_qrcode(instance, version, ecc)) { + if(!rebuild_qrcode(instance, version, ecc)) { furi_string_free(instance->message); instance->message = NULL; break; @@ -365,7 +411,7 @@ static bool qrcode_load_string(QRCodeApp* instance, FuriString* str) { instance->min_version = instance->set_version = version; instance->max_ecc_at_min_version = instance->set_ecc = ecc; result = true; - } while (false); + } while(false); instance->loading = false; @@ -391,27 +437,26 @@ static bool qrcode_load_file(QRCodeApp* instance, const char* file_path) { FlipperFormat* file = flipper_format_file_alloc(storage); do { - if (!flipper_format_file_open_existing(file, file_path)) break; + if(!flipper_format_file_open_existing(file, file_path)) break; uint32_t version = 0; - if (!flipper_format_read_header(file, temp_str, &version)) break; - if (furi_string_cmp_str(temp_str, QRCODE_FILETYPE) - || version != QRCODE_FILE_VERSION) { + if(!flipper_format_read_header(file, temp_str, &version)) break; + if(furi_string_cmp_str(temp_str, QRCODE_FILETYPE) || version != QRCODE_FILE_VERSION) { FURI_LOG_E(TAG, "Incorrect file format or version"); break; } - if (!flipper_format_read_string(file, "Message", temp_str)) { + if(!flipper_format_read_string(file, "Message", temp_str)) { FURI_LOG_E(TAG, "Message is missing"); break; } - if (!qrcode_load_string(instance, temp_str)) { + if(!qrcode_load_string(instance, temp_str)) { break; } result = true; - } while (false); + } while(false); furi_record_close(RECORD_STORAGE); flipper_format_free(file); @@ -454,8 +499,8 @@ static QRCodeApp* qrcode_app_alloc() { * @param qrcode_app The app to free */ static void qrcode_app_free(QRCodeApp* instance) { - if (instance->message) furi_string_free(instance->message); - if (instance->qrcode) qrcode_free(instance->qrcode); + if(instance->message) furi_string_free(instance->message); + if(instance->qrcode) qrcode_free(instance->qrcode); gui_remove_view_port(instance->gui, instance->view_port); furi_record_close(RECORD_GUI); @@ -475,14 +520,14 @@ int32_t qrcode_app(void* p) { FuriString* file_path = furi_string_alloc(); do { - if (p && strlen(p)) { + if(p && strlen(p)) { furi_string_set(file_path, (const char*)p); } else { furi_string_set(file_path, QRCODE_FOLDER); DialogsFileBrowserOptions browser_options; dialog_file_browser_set_basic_options( - &browser_options, QRCODE_EXTENSION, &I_qrcode_10px); + &browser_options, QRCODE_EXTENSION, &I_qrcode_10px); browser_options.hide_ext = true; browser_options.base_path = QRCODE_FOLDER; @@ -490,26 +535,27 @@ int32_t qrcode_app(void* p) { bool res = dialog_file_browser_show(dialogs, file_path, file_path, &browser_options); furi_record_close(RECORD_DIALOGS); - if (!res) { + if(!res) { FURI_LOG_E(TAG, "No file selected"); break; } } - if (!qrcode_load_file(instance, furi_string_get_cstr(file_path))) { + if(!qrcode_load_file(instance, furi_string_get_cstr(file_path))) { FURI_LOG_E(TAG, "Unable to load file"); } InputEvent input; - while (furi_message_queue_get(instance->input_queue, &input, FuriWaitForever) == FuriStatusOk) { + while(furi_message_queue_get(instance->input_queue, &input, FuriWaitForever) == + FuriStatusOk) { furi_check(furi_mutex_acquire(instance->mutex, FuriWaitForever) == FuriStatusOk); - if (input.key == InputKeyBack) { - if (instance->message) { + if(input.key == InputKeyBack) { + if(instance->message) { furi_string_free(instance->message); instance->message = NULL; } - if (instance->qrcode) { + if(instance->qrcode) { qrcode_free(instance->qrcode); instance->qrcode = NULL; } @@ -517,43 +563,49 @@ int32_t qrcode_app(void* p) { instance->edit = false; furi_mutex_release(instance->mutex); break; - } else if (input.key == InputKeyRight) { + } else if(input.key == InputKeyRight) { instance->show_stats = true; - } else if (input.key == InputKeyLeft) { + } else if(input.key == InputKeyLeft) { instance->show_stats = false; - } else if (instance->show_stats && !instance->loading && instance->qrcode) { - if (input.key == InputKeyUp) { - if (!instance->edit) { + } else if(instance->show_stats && !instance->loading && instance->qrcode) { + if(input.key == InputKeyUp) { + if(!instance->edit) { instance->selected_idx = MAX(0, instance->selected_idx - 1); } else { - if (instance->selected_idx == 0 && instance->set_version < MAX_QRCODE_VERSION) { + if(instance->selected_idx == 0 && + instance->set_version < MAX_QRCODE_VERSION) { instance->set_version++; - } else if (instance->selected_idx == 1) { - uint8_t max_ecc = instance->set_version == instance->min_version ? instance->max_ecc_at_min_version : ECC_HIGH; - if (instance->set_ecc < max_ecc) { + } else if(instance->selected_idx == 1) { + uint8_t max_ecc = instance->set_version == instance->min_version ? + instance->max_ecc_at_min_version : + ECC_HIGH; + if(instance->set_ecc < max_ecc) { instance->set_ecc++; } } } - } else if (input.key == InputKeyDown) { - if (!instance->edit) { + } else if(input.key == InputKeyDown) { + if(!instance->edit) { instance->selected_idx = MIN(1, instance->selected_idx + 1); } else { - if (instance->selected_idx == 0 && instance->set_version > instance->min_version) { + if(instance->selected_idx == 0 && + instance->set_version > instance->min_version) { instance->set_version--; - if (instance->set_version == instance->min_version) { - instance->set_ecc = MAX(instance->set_ecc, instance->max_ecc_at_min_version); + if(instance->set_version == instance->min_version) { + instance->set_ecc = + MAX(instance->set_ecc, instance->max_ecc_at_min_version); } - } else if (instance->selected_idx == 1 && instance->set_ecc > 0) { + } else if(instance->selected_idx == 1 && instance->set_ecc > 0) { instance->set_ecc--; } } - } else if (input.key == InputKeyOk) { - if (instance->edit && (instance->set_version != instance->qrcode->version || instance->set_ecc != instance->qrcode->ecc)) { + } else if(input.key == InputKeyOk) { + if(instance->edit && (instance->set_version != instance->qrcode->version || + instance->set_ecc != instance->qrcode->ecc)) { QRCode* qrcode = instance->qrcode; instance->loading = true; - if (rebuild_qrcode(instance, instance->set_version, instance->set_ecc)) { + if(rebuild_qrcode(instance, instance->set_version, instance->set_ecc)) { qrcode_free(qrcode); } else { FURI_LOG_E(TAG, "Could not rebuild qrcode"); @@ -572,12 +624,12 @@ int32_t qrcode_app(void* p) { view_port_update(instance->view_port); } - if (p && strlen(p)) { + if(p && strlen(p)) { // if started with an arg, exit instead // of looping back to the browser break; } - } while (true); + } while(true); furi_string_free(file_path); qrcode_app_free(instance); diff --git a/applications/plugins/solitaire/solitaire.c b/applications/plugins/solitaire/solitaire.c index b099e77a1..8893b3986 100644 --- a/applications/plugins/solitaire/solitaire.c +++ b/applications/plugins/solitaire/solitaire.c @@ -255,8 +255,7 @@ bool place_on_top(Card* where, Card what) { int8_t b_letter = (int8_t)what.character; if(a_letter == 12) a_letter = -1; if(b_letter == 12) b_letter = -1; - if(where->disabled && b_letter!=-1) - return false; + if(where->disabled && b_letter != -1) return false; if((a_letter + 1) == b_letter) { where->disabled = what.disabled; where->pip = what.pip; diff --git a/applications/plugins/unitemp/views/General_view.c b/applications/plugins/unitemp/views/General_view.c index b48349bdd..02e416fb2 100644 --- a/applications/plugins/unitemp/views/General_view.c +++ b/applications/plugins/unitemp/views/General_view.c @@ -172,10 +172,9 @@ static void _draw_singleSensor(Canvas* canvas, Sensor* sensor, const uint8_t pos static void _draw_view_noSensors(Canvas* canvas) { DesktopSettings* settings = malloc(sizeof(DesktopSettings)); DESKTOP_SETTINGS_LOAD(settings); - if (settings->sfw_mode) { + if(settings->sfw_mode) { canvas_draw_icon(canvas, 7, 17, &I_sherlok_53x45_sfw); - } - else { + } else { canvas_draw_icon(canvas, 7, 17, &I_sherlok_53x45); } //Рисование рамки diff --git a/applications/plugins/usb_hid_autofire/tools.c b/applications/plugins/usb_hid_autofire/tools.c index 2b452b55b..566d00564 100644 --- a/applications/plugins/usb_hid_autofire/tools.c +++ b/applications/plugins/usb_hid_autofire/tools.c @@ -5,8 +5,7 @@ void strrev(char* arr, int start, int end) { char temp; - if (start >= end) - return; + if(start >= end) return; temp = *(arr + start); *(arr + start) = *(arr + end); @@ -17,33 +16,28 @@ void strrev(char* arr, int start, int end) { strrev(arr, start, end); } -char *itoa(int number, char *arr, int base) -{ +char* itoa(int number, char* arr, int base) { int i = 0, r, negative = 0; - if (number == 0) - { + if(number == 0) { arr[i] = '0'; arr[i + 1] = '\0'; return arr; } - if (number < 0 && base == 10) - { + if(number < 0 && base == 10) { number *= -1; negative = 1; } - while (number != 0) - { + while(number != 0) { r = number % base; arr[i] = (r > 9) ? (r - 10) + 'a' : r + '0'; i++; number /= base; } - if (negative) - { + if(negative) { arr[i] = '-'; i++; } diff --git a/applications/plugins/usb_hid_autofire/tools.h b/applications/plugins/usb_hid_autofire/tools.h index 9c71ea6ca..7e5226514 100644 --- a/applications/plugins/usb_hid_autofire/tools.h +++ b/applications/plugins/usb_hid_autofire/tools.h @@ -1,7 +1,7 @@ #ifndef FLIPPERZERO_FIRMWARE_TOOLS_H #define FLIPPERZERO_FIRMWARE_TOOLS_H -void strrev(char *arr, int start, int end); -char *itoa(int number, char *arr, int base); +void strrev(char* arr, int start, int end); +char* itoa(int number, char* arr, int base); #endif //FLIPPERZERO_FIRMWARE_TOOLS_H diff --git a/applications/plugins/usb_hid_autofire/usb_hid_autofire.c b/applications/plugins/usb_hid_autofire/usb_hid_autofire.c index 1333ba94a..cf8077ae7 100644 --- a/applications/plugins/usb_hid_autofire/usb_hid_autofire.c +++ b/applications/plugins/usb_hid_autofire/usb_hid_autofire.c @@ -88,19 +88,19 @@ int32_t usb_hid_autofire_app(void* p) { } switch(event.input.key) { - case InputKeyOk: - btn_left_autofire = !btn_left_autofire; - break; - case InputKeyLeft: - if(autofire_delay > 0) { - autofire_delay -= 10; - } - break; - case InputKeyRight: - autofire_delay += 10; - break; - default: - break; + case InputKeyOk: + btn_left_autofire = !btn_left_autofire; + break; + case InputKeyLeft: + if(autofire_delay > 0) { + autofire_delay -= 10; + } + break; + case InputKeyRight: + autofire_delay += 10; + break; + default: + break; } } } diff --git a/applications/plugins/weather_station/views/weather_station_receiver.c b/applications/plugins/weather_station/views/weather_station_receiver.c index 89dbc7a0a..cfcdac9fb 100644 --- a/applications/plugins/weather_station/views/weather_station_receiver.c +++ b/applications/plugins/weather_station/views/weather_station_receiver.c @@ -205,10 +205,9 @@ void ws_view_receiver_draw(Canvas* canvas, WSReceiverModel* model) { canvas_set_color(canvas, ColorBlack); if(model->history_item == 0) { - if (settings->sfw_mode) { + if(settings->sfw_mode) { canvas_draw_icon(canvas, 0, 0, &I_Scanning_123x52_sfw); - } - else { + } else { canvas_draw_icon(canvas, 0, 0, &I_Scanning_123x52); } canvas_set_font(canvas, FontPrimary); @@ -232,10 +231,9 @@ void ws_view_receiver_draw(Canvas* canvas, WSReceiverModel* model) { canvas_draw_icon(canvas, 65, 42, &I_Pin_back_arrow_10x8); canvas_draw_icon(canvas, 80, 42, &I_Pin_back_arrow_10x8); canvas_draw_icon(canvas, 95, 42, &I_Pin_back_arrow_10x8); - if (settings->sfw_mode) { + if(settings->sfw_mode) { canvas_draw_icon(canvas, 16, 13, &I_WarningDolphin_45x42_sfw); - } - else { + } else { canvas_draw_icon(canvas, 16, 13, &I_WarningDolphin_45x42); } canvas_draw_dot(canvas, 17, 61); diff --git a/applications/plugins/wii_ec_anal/_image_tool/_convert.c b/applications/plugins/wii_ec_anal/_image_tool/_convert.c index 267985e8d..57deeb083 100644 --- a/applications/plugins/wii_ec_anal/_image_tool/_convert.c +++ b/applications/plugins/wii_ec_anal/_image_tool/_convert.c @@ -3,136 +3,146 @@ #include #include -int main (int argc, char* argv[]) -{ - const unsigned char* pp = NULL; - uint32_t pix = 0; - int bit = 0; +int main(int argc, char* argv[]) { + const unsigned char* pp = NULL; + uint32_t pix = 0; + int bit = 0; - uint8_t b = 0; - uint8_t bcnt = 0; + uint8_t b = 0; + uint8_t bcnt = 0; - unsigned int lcnt = 0; - static const int lmax = 16; // max hex values per line + unsigned int lcnt = 0; + static const int lmax = 16; // max hex values per line - uint8_t* buf = NULL; - uint8_t* bp = NULL; - unsigned int blen = 0; + uint8_t* buf = NULL; + uint8_t* bp = NULL; + unsigned int blen = 0; - uint8_t* cmp = NULL; - uint8_t* cp = NULL; - unsigned int clen = 0; - uint8_t ctag = 0xFF; - uint32_t tag[256] = {0}; - uint32_t tmax = UINT32_MAX; + uint8_t* cmp = NULL; + uint8_t* cp = NULL; + unsigned int clen = 0; + uint8_t ctag = 0xFF; + uint32_t tag[256] = {0}; + uint32_t tmax = UINT32_MAX; - unsigned int x, y, z; + unsigned int x, y, z; - const char* name = argv[1]; - FILE* fh = fopen(argv[2], "wb"); + const char* name = argv[1]; + FILE* fh = fopen(argv[2], "wb"); - uint32_t white = 0xFF; + uint32_t white = 0xFF; - int rv = 0; // assume success + int rv = 0; // assume success - // allocate buffers - blen = ((img.w * img.h) +0x7) >>3; - bp = (buf = calloc(blen +1, 1)); - cp = (cmp = calloc(blen +4, 1)); + // allocate buffers + blen = ((img.w * img.h) + 0x7) >> 3; + bp = (buf = calloc(blen + 1, 1)); + cp = (cmp = calloc(blen + 4, 1)); - // sanity check - if (!fh || !buf || !cmp) { - printf("! fopen() or malloc() fail.\n"); - rv = 255; - goto bail; - } + // sanity check + if(!fh || !buf || !cmp) { + printf("! fopen() or malloc() fail.\n"); + rv = 255; + goto bail; + } - // Find white value - for (x = 1; x < img.bpp; x++) - white = (white << 8) | 0xFF ; + // Find white value + for(x = 1; x < img.bpp; x++) white = (white << 8) | 0xFF; - // build bit pattern - // create the comment as we go - for (pp = img.b, y = 0; y < img.h; y++) { - fprintf(fh, "// "); - for (x = 0; x < img.w; x++) { - // read pixel - for (pix = 0, z = 0; z < img.bpp; pix = (pix << 8) | *pp++, z++) ; - // get bit and draw - if (pix < white) { - b = (b << 1) | 1; - fprintf(fh, "##"); - } else { - b <<= 1; - fprintf(fh, ".."); - } - // got byte - if ((++bcnt) == 8) { - *bp++ = b; - tag[b]++; - bcnt = (b = 0); - } - } - fprintf(fh, "\n"); - } - fprintf(fh, "\n"); - // padding - if (bcnt) { - b <<= (bcnt = 8 - bcnt); - *bp++ = b; - tag[b]++; - } - // Kill the compression - *bp = ~bp[-1]; // https://youtube.com/clip/Ugkx-JZIr16hETy7hz_H6yIdKPtxVe8C5w_V + // build bit pattern + // create the comment as we go + for(pp = img.b, y = 0; y < img.h; y++) { + fprintf(fh, "// "); + for(x = 0; x < img.w; x++) { + // read pixel + for(pix = 0, z = 0; z < img.bpp; pix = (pix << 8) | *pp++, z++) + ; + // get bit and draw + if(pix < white) { + b = (b << 1) | 1; + fprintf(fh, "##"); + } else { + b <<= 1; + fprintf(fh, ".."); + } + // got byte + if((++bcnt) == 8) { + *bp++ = b; + tag[b]++; + bcnt = (b = 0); + } + } + fprintf(fh, "\n"); + } + fprintf(fh, "\n"); + // padding + if(bcnt) { + b <<= (bcnt = 8 - bcnt); + *bp++ = b; + tag[b]++; + } + // Kill the compression + *bp = ~bp[-1]; // https://youtube.com/clip/Ugkx-JZIr16hETy7hz_H6yIdKPtxVe8C5w_V - // Byte run length compression - // Find a good tag - for (x = 0; tmax && (x < 256); x++) { - if (tag[x] < tmax) { - tmax = tag[x]; - ctag = x; - } - } + // Byte run length compression + // Find a good tag + for(x = 0; tmax && (x < 256); x++) { + if(tag[x] < tmax) { + tmax = tag[x]; + ctag = x; + } + } - // compress the data - for (bp = buf, x = 0; (clen < blen) && (x < blen); x++) { - // need at least 4 the same to be worth it - // must compress tag (if it occurs) - if ((bp[x] == bp[x+1]) && (bp[x] == bp[x+2]) && (bp[x] == bp[x+3]) || (bp[x] == ctag)) { - for (y = 1; (y < 255) && (bp[x] == bp[x+y]); y++) ; - *cp++ = ctag; // tag - *cp++ = y; // length - *cp++ = bp[x]; // byte - x += y -1; - clen += 3; - } else { - *cp++ = bp[x]; - clen++; - } - } + // compress the data + for(bp = buf, x = 0; (clen < blen) && (x < blen); x++) { + // need at least 4 the same to be worth it + // must compress tag (if it occurs) + if((bp[x] == bp[x + 1]) && (bp[x] == bp[x + 2]) && (bp[x] == bp[x + 3]) || + (bp[x] == ctag)) { + for(y = 1; (y < 255) && (bp[x] == bp[x + y]); y++) + ; + *cp++ = ctag; // tag + *cp++ = y; // length + *cp++ = bp[x]; // byte + x += y - 1; + clen += 3; + } else { + *cp++ = bp[x]; + clen++; + } + } - // create struct - fprintf(fh, "#include \"images.h\"\n\n"); - fprintf(fh, "const image_t img_%s = { %d, %d, ", name, img.w, img.h); + // create struct + fprintf(fh, "#include \"images.h\"\n\n"); + fprintf(fh, "const image_t img_%s = { %d, %d, ", name, img.w, img.h); - if (clen < blen) { // dump compressed? - fprintf(fh, "true, %d, 0x%02X, { // orig:%d, comp:%.2f%%\n\t", - clen, ctag, blen, 100.0-((clen*100.0)/blen)); - for (x = 0; x < clen; x++) - if (x == clen -1) fprintf(fh, "0x%02X\n}};\n", cmp[x]) ; - else fprintf(fh, "0x%02X%s", cmp[x], (!((x+1)%16)) ? ",\n\t" : ", ") ; + if(clen < blen) { // dump compressed? + fprintf( + fh, + "true, %d, 0x%02X, { // orig:%d, comp:%.2f%%\n\t", + clen, + ctag, + blen, + 100.0 - ((clen * 100.0) / blen)); + for(x = 0; x < clen; x++) + if(x == clen - 1) + fprintf(fh, "0x%02X\n}};\n", cmp[x]); + else + fprintf(fh, "0x%02X%s", cmp[x], (!((x + 1) % 16)) ? ",\n\t" : ", "); - } else { // dump UNcompressed - fprintf(fh, "false, %d, 0, {\n\t", blen); - for (x = 0; x < blen; x++) - if (x == blen -1) fprintf(fh, "0x%02X\n}};\n", buf[x]) ; - else fprintf(fh, "0x%02X%s", buf[x], (!((x+1)%16)) ? ",\n\t" : ", ") ; - } + } else { // dump UNcompressed + fprintf(fh, "false, %d, 0, {\n\t", blen); + for(x = 0; x < blen; x++) + if(x == blen - 1) + fprintf(fh, "0x%02X\n}};\n", buf[x]); + else + fprintf(fh, "0x%02X%s", buf[x], (!((x + 1) % 16)) ? ",\n\t" : ", "); + } bail: - if (fh) fclose(fh) ; - if (buf) free(buf) ; - if (cmp) free(cmp) ; + if(fh) fclose(fh); + if(buf) free(buf); + if(cmp) free(cmp); - return rv; + return rv; } diff --git a/applications/plugins/wii_ec_anal/_image_tool/_convert_images.c b/applications/plugins/wii_ec_anal/_image_tool/_convert_images.c index 57046e9a3..e8ab899f7 100644 --- a/applications/plugins/wii_ec_anal/_image_tool/_convert_images.c +++ b/applications/plugins/wii_ec_anal/_image_tool/_convert_images.c @@ -1,55 +1,49 @@ -#include // GUI (screen/keyboard) API +#include // GUI (screen/keyboard) API -#include "images.h" +#include "images.h" //----------------------------------------------------------------------------- ---------------------------------------- -static Canvas* _canvas; -static uint8_t _tlx; -static uint8_t _tly; +static Canvas* _canvas; +static uint8_t _tlx; +static uint8_t _tly; -static uint8_t _x; -static uint8_t _y; +static uint8_t _x; +static uint8_t _y; -static const image_t* _img; +static const image_t* _img; -static bool _blk; -static Color _set; -static Color _clr; +static bool _blk; +static Color _set; +static Color _clr; //+============================================================================ -static -void _showByteSet (const uint8_t b) -{ - for (uint8_t m = 0x80; m; m >>= 1) { - if (b & m) // plot only SET bits - canvas_draw_dot(_canvas, (_tlx +_x), (_tly +_y)) ; - if ( ((++_x) == _img->w) && !(_x = 0) && ((++_y) == _img->h) ) break ; - } +static void _showByteSet(const uint8_t b) { + for(uint8_t m = 0x80; m; m >>= 1) { + if(b & m) // plot only SET bits + canvas_draw_dot(_canvas, (_tlx + _x), (_tly + _y)); + if(((++_x) == _img->w) && !(_x = 0) && ((++_y) == _img->h)) break; + } } //+============================================================================ -static -void _showByteClr (const uint8_t b) -{ - for (uint8_t m = 0x80; m; m >>= 1) { - if (!(b & m)) // plot only CLR bits - canvas_draw_dot(_canvas, (_tlx +_x), (_tly +_y)) ; - if ( ((++_x) == _img->w) && !(_x = 0) && ((++_y) == _img->h) ) break ; - } +static void _showByteClr(const uint8_t b) { + for(uint8_t m = 0x80; m; m >>= 1) { + if(!(b & m)) // plot only CLR bits + canvas_draw_dot(_canvas, (_tlx + _x), (_tly + _y)); + if(((++_x) == _img->w) && !(_x = 0) && ((++_y) == _img->h)) break; + } } //+============================================================================ -static -void _showByteAll (const uint8_t b) -{ - for (uint8_t m = 0x80; m; m >>= 1) { - if ((!!(b & m)) ^ _blk) { // Change colour only when required - canvas_set_color(_canvas, ((b & m) ? _set : _clr)); - _blk = !_blk; - } - canvas_draw_dot(_canvas, (_tlx +_x), (_tly +_y)) ; - if ( ((++_x) == _img->w) && !(_x = 0) && ((++_y) == _img->h) ) break ; - } +static void _showByteAll(const uint8_t b) { + for(uint8_t m = 0x80; m; m >>= 1) { + if((!!(b & m)) ^ _blk) { // Change colour only when required + canvas_set_color(_canvas, ((b & m) ? _set : _clr)); + _blk = !_blk; + } + canvas_draw_dot(_canvas, (_tlx + _x), (_tly + _y)); + if(((++_x) == _img->w) && !(_x = 0) && ((++_y) == _img->h)) break; + } } //+============================================================================ @@ -61,81 +55,83 @@ void _showByteAll (const uint8_t b) // SHOW_ALL - plot all images pixels as they are // SHOW_ALL_INV - plot all images pixels inverted // -void show (Canvas* const canvas, const uint8_t tlx, const uint8_t tly, - const image_t* img, const showMode_t mode) -{ - void(*fnShow)(const uint8_t) = NULL; +void show( + Canvas* const canvas, + const uint8_t tlx, + const uint8_t tly, + const image_t* img, + const showMode_t mode) { + void (*fnShow)(const uint8_t) = NULL; - const uint8_t* bp = img->data; + const uint8_t* bp = img->data; - // code size optimisation - switch (mode & SHOW_INV_) { - case SHOW_NRM_: - _set = ColorBlack; - _clr = ColorWhite; - break; + // code size optimisation + switch(mode & SHOW_INV_) { + case SHOW_NRM_: + _set = ColorBlack; + _clr = ColorWhite; + break; - case SHOW_INV_: - _set = ColorWhite; - _clr = ColorBlack; - break; + case SHOW_INV_: + _set = ColorWhite; + _clr = ColorBlack; + break; - case SHOW_BLK_: - canvas_set_color(canvas, ColorBlack); - break; + case SHOW_BLK_: + canvas_set_color(canvas, ColorBlack); + break; - case SHOW_WHT_: - canvas_set_color(canvas, ColorWhite); - break; + case SHOW_WHT_: + canvas_set_color(canvas, ColorWhite); + break; + } + switch(mode & SHOW_INV_) { + case SHOW_NRM_: + case SHOW_INV_: + fnShow = _showByteAll; + canvas_set_color(canvas, ColorWhite); + _blk = 0; + break; - } - switch (mode & SHOW_INV_) { - case SHOW_NRM_: - case SHOW_INV_: - fnShow = _showByteAll; - canvas_set_color(canvas, ColorWhite); - _blk = 0; - break; + case SHOW_BLK_: + case SHOW_WHT_: + switch(mode & SHOW_ALL_) { + case SHOW_SET_: + fnShow = _showByteSet; + break; + case SHOW_CLR_: + fnShow = _showByteClr; + break; + } + break; + } + furi_check(fnShow); - case SHOW_BLK_: - case SHOW_WHT_: - switch (mode & SHOW_ALL_) { - case SHOW_SET_: - fnShow = _showByteSet; - break; - case SHOW_CLR_: - fnShow = _showByteClr; - break; - } - break; - } - furi_check(fnShow); + // I want nested functions! + _canvas = canvas; + _img = img; + _tlx = tlx; + _tly = tly; + _x = 0; + _y = 0; - // I want nested functions! - _canvas = canvas; - _img = img; - _tlx = tlx; - _tly = tly; - _x = 0; - _y = 0; + // Compressed + if(img->c) { + for(unsigned int i = 0; i < img->len; i++, bp++) { + // Compressed data? {tag, length, value} + if(*bp == img->tag) { + for(uint16_t c = 0; c < bp[1]; c++) fnShow(bp[2]); + bp += 3 - 1; + i += 3 - 1; - // Compressed - if (img->c) { - for (unsigned int i = 0; i < img->len; i++, bp++) { - // Compressed data? {tag, length, value} - if (*bp == img->tag) { - for (uint16_t c = 0; c < bp[1]; c++) fnShow(bp[2]) ; - bp += 3 -1; - i += 3 -1; + // Uncompressed byte + } else { + fnShow(*bp); + } + } - // Uncompressed byte - } else { - fnShow(*bp); - } - } - - // Not compressed - } else { - for (unsigned int i = 0; i < img->len; i++, bp++) fnShow(*bp) ; - } + // Not compressed + } else { + for(unsigned int i = 0; i < img->len; i++, bp++) fnShow(*bp); + } } diff --git a/applications/plugins/wii_ec_anal/_image_tool/_convert_images.h b/applications/plugins/wii_ec_anal/_image_tool/_convert_images.h index bfc44568e..1743cb409 100644 --- a/applications/plugins/wii_ec_anal/_image_tool/_convert_images.h +++ b/applications/plugins/wii_ec_anal/_image_tool/_convert_images.h @@ -1,53 +1,53 @@ -#ifndef IMAGES_H_ -#define IMAGES_H_ +#ifndef IMAGES_H_ +#define IMAGES_H_ #include #include //----------------------------------------------------------------------------- ---------------------------------------- -typedef - enum showMode { - // {INV:--:WHT:BLK::--:--:CLR:SET} - SHOW_SET_ = 0x01, - SHOW_CLR_ = 0x02, - SHOW_ALL_ = SHOW_SET_ | SHOW_CLR_, +typedef enum showMode { + // {INV:--:WHT:BLK::--:--:CLR:SET} + SHOW_SET_ = 0x01, + SHOW_CLR_ = 0x02, + SHOW_ALL_ = SHOW_SET_ | SHOW_CLR_, - SHOW_BLK_ = 0x10, - SHOW_WHT_ = 0x20, - SHOW_NRM_ = 0x00, - SHOW_INV_ = SHOW_BLK_ | SHOW_WHT_, + SHOW_BLK_ = 0x10, + SHOW_WHT_ = 0x20, + SHOW_NRM_ = 0x00, + SHOW_INV_ = SHOW_BLK_ | SHOW_WHT_, - SHOW_SET_BLK = SHOW_SET_ | SHOW_BLK_, - SHOW_SET_WHT = SHOW_SET_ | SHOW_WHT_, + SHOW_SET_BLK = SHOW_SET_ | SHOW_BLK_, + SHOW_SET_WHT = SHOW_SET_ | SHOW_WHT_, - SHOW_CLR_BLK = SHOW_CLR_ | SHOW_BLK_, - SHOW_CLR_WHT = SHOW_CLR_ | SHOW_WHT_, + SHOW_CLR_BLK = SHOW_CLR_ | SHOW_BLK_, + SHOW_CLR_WHT = SHOW_CLR_ | SHOW_WHT_, - SHOW_ALL = SHOW_ALL_ | SHOW_NRM_, - SHOW_ALL_INV = SHOW_ALL_ | SHOW_INV_, - } -showMode_t; + SHOW_ALL = SHOW_ALL_ | SHOW_NRM_, + SHOW_ALL_INV = SHOW_ALL_ | SHOW_INV_, +} showMode_t; //----------------------------------------------------------------------------- ---------------------------------------- -typedef - struct image { - uint8_t w; // width - uint8_t h; // height - bool c; // compressed? - uint16_t len; // image data length - uint8_t tag; // rle tag - uint8_t data[]; // image data - } -image_t; +typedef struct image { + uint8_t w; // width + uint8_t h; // height + bool c; // compressed? + uint16_t len; // image data length + uint8_t tag; // rle tag + uint8_t data[]; // image data +} image_t; //----------------------------------------------------------------------------- ---------------------------------------- //[TAG] //----------------------------------------------------------------------------- ---------------------------------------- #ifndef IMGTEST -# include - void show (Canvas* const canvas, const uint8_t tlx, const uint8_t tly, - const image_t* img, const showMode_t mode) ; +#include +void show( + Canvas* const canvas, + const uint8_t tlx, + const uint8_t tly, + const image_t* img, + const showMode_t mode); #endif #endif //IMAGES_H_ diff --git a/applications/plugins/wii_ec_anal/_image_tool/_convert_test.c b/applications/plugins/wii_ec_anal/_image_tool/_convert_test.c index 4bdb531d5..fdc2ee946 100644 --- a/applications/plugins/wii_ec_anal/_image_tool/_convert_test.c +++ b/applications/plugins/wii_ec_anal/_image_tool/_convert_test.c @@ -1,59 +1,59 @@ -#include -#include +#include +#include -#include "images.h" +#include "images.h" //----------------------------------------------------------------------------- // This will be the plot function out of your graphics library // -#define PLOT(x,y,c) do { \ - printf("%s", (c ? "#" : ".")); \ - if (x == img->w -1) printf("\n") ; \ -}while(0) +#define PLOT(x, y, c) \ + do { \ + printf("%s", (c ? "#" : ".")); \ + if(x == img->w - 1) printf("\n"); \ + } while(0) //+============================================================================ // The pain we endure to avoid code duplication cleanly // -#define PLOTBYTE(b) do { \ - for (uint8_t m = 0x80; m; m>>=1) { \ - PLOT(x,y, (b & m)); \ - if ( ((++x) == img->w) && !(x = 0) && ((++y) == img->h) ) break ; \ - } \ -}while(0) +#define PLOTBYTE(b) \ + do { \ + for(uint8_t m = 0x80; m; m >>= 1) { \ + PLOT(x, y, (b & m)); \ + if(((++x) == img->w) && !(x = 0) && ((++y) == img->h)) break; \ + } \ + } while(0) -void show (const image_t* img) -{ - // Some variables - const uint8_t* bp = img->data; - unsigned int x = 0; - unsigned int y = 0; +void show(const image_t* img) { + // Some variables + const uint8_t* bp = img->data; + unsigned int x = 0; + unsigned int y = 0; - // Compressed - if (img->c) { - for (unsigned int i = 0; i < img->len; i++, bp++) { - // Compressed data? {tag, length, value} - if (*bp == img->tag) { - for (uint16_t c = 0; c < bp[1]; c++) PLOTBYTE(bp[2]) ; - bp += 3 -1; - i += 3 -1; + // Compressed + if(img->c) { + for(unsigned int i = 0; i < img->len; i++, bp++) { + // Compressed data? {tag, length, value} + if(*bp == img->tag) { + for(uint16_t c = 0; c < bp[1]; c++) PLOTBYTE(bp[2]); + bp += 3 - 1; + i += 3 - 1; - // Uncompressed byte - } else { - PLOTBYTE(*bp); - } - } + // Uncompressed byte + } else { + PLOTBYTE(*bp); + } + } - // Not compressed - } else { - for (unsigned int i = 0; i < img->len; i++, bp++) PLOTBYTE(*bp) ; - } + // Not compressed + } else { + for(unsigned int i = 0; i < img->len; i++, bp++) PLOTBYTE(*bp); + } } -#undef PLOTBYTE +#undef PLOTBYTE //+============================================================================ -int main (void) -{ - show(&img_zzz); - return 0; +int main(void) { + show(&img_zzz); + return 0; } diff --git a/applications/plugins/wii_ec_anal/bc_logging.h b/applications/plugins/wii_ec_anal/bc_logging.h index d9bb48c92..73dda80bd 100644 --- a/applications/plugins/wii_ec_anal/bc_logging.h +++ b/applications/plugins/wii_ec_anal/bc_logging.h @@ -1,13 +1,13 @@ -#ifndef BC_LOGGING_H_ -#define BC_LOGGING_H_ +#ifndef BC_LOGGING_H_ +#define BC_LOGGING_H_ #include -#include "err.h" // appName +#include "err.h" // appName //! WARNING: There is a bug in Furi such that if you crank LOG_LEVEL up to 6=TRACE //! AND you have menu->settings->system->logLevel = trace //! THEN this program will cause the FZ to crash when the plugin exits! -#define LOG_LEVEL 4 +#define LOG_LEVEL 4 //----------------------------------------------------------------------------- ---------------------------------------- // The FlipperZero Settings->System menu allows you to set the logging level at RUN-time @@ -27,44 +27,44 @@ // The FlipperZero Settings->System menu allows you to set the logging level at RUN-time // This lets you limit it at COMPILE-time #ifndef LOG_LEVEL -# define LOG_LEVEL 6 // default = full logging +#define LOG_LEVEL 6 // default = full logging #endif -#if (LOG_LEVEL < 2) -# undef FURI_LOG_E -# define FURI_LOG_E(tag, fmt, ...) +#if(LOG_LEVEL < 2) +#undef FURI_LOG_E +#define FURI_LOG_E(tag, fmt, ...) #endif -#if (LOG_LEVEL < 3) -# undef FURI_LOG_W -# define FURI_LOG_W(tag, fmt, ...) +#if(LOG_LEVEL < 3) +#undef FURI_LOG_W +#define FURI_LOG_W(tag, fmt, ...) #endif -#if (LOG_LEVEL < 4) -# undef FURI_LOG_I -# define FURI_LOG_I(tag, fmt, ...) +#if(LOG_LEVEL < 4) +#undef FURI_LOG_I +#define FURI_LOG_I(tag, fmt, ...) #endif -#if (LOG_LEVEL < 5) -# undef FURI_LOG_D -# define FURI_LOG_D(tag, fmt, ...) +#if(LOG_LEVEL < 5) +#undef FURI_LOG_D +#define FURI_LOG_D(tag, fmt, ...) #endif -#if (LOG_LEVEL < 6) -# undef FURI_LOG_T -# define FURI_LOG_T(tag, fmt, ...) +#if(LOG_LEVEL < 6) +#undef FURI_LOG_T +#define FURI_LOG_T(tag, fmt, ...) #endif //---------------------------------------------------------- // Logging helper macros // -#define ERROR(fmt, ...) FURI_LOG_E(appName, fmt __VA_OPT__(,) __VA_ARGS__) -#define WARN(fmt, ...) FURI_LOG_W(appName, fmt __VA_OPT__(,) __VA_ARGS__) -#define INFO(fmt, ...) FURI_LOG_I(appName, fmt __VA_OPT__(,) __VA_ARGS__) -#define DEBUG(fmt, ...) FURI_LOG_D(appName, fmt __VA_OPT__(,) __VA_ARGS__) -#define TRACE(fmt, ...) FURI_LOG_T(appName, fmt __VA_OPT__(,) __VA_ARGS__) +#define ERROR(fmt, ...) FURI_LOG_E(appName, fmt __VA_OPT__(, ) __VA_ARGS__) +#define WARN(fmt, ...) FURI_LOG_W(appName, fmt __VA_OPT__(, ) __VA_ARGS__) +#define INFO(fmt, ...) FURI_LOG_I(appName, fmt __VA_OPT__(, ) __VA_ARGS__) +#define DEBUG(fmt, ...) FURI_LOG_D(appName, fmt __VA_OPT__(, ) __VA_ARGS__) +#define TRACE(fmt, ...) FURI_LOG_T(appName, fmt __VA_OPT__(, ) __VA_ARGS__) -#define ENTER TRACE("(+) %s", __func__) -#define LEAVE TRACE("(-) %s", __func__) +#define ENTER TRACE("(+) %s", __func__) +#define LEAVE TRACE("(-) %s", __func__) #endif //BC_LOGGING_H_ diff --git a/applications/plugins/wii_ec_anal/err.h b/applications/plugins/wii_ec_anal/err.h index 9398a3fb8..5a25c93f8 100644 --- a/applications/plugins/wii_ec_anal/err.h +++ b/applications/plugins/wii_ec_anal/err.h @@ -1,11 +1,11 @@ // Avoid circular/nested/mulitple inclusion -#ifndef ERR_H_ -#define ERR_H_ +#ifndef ERR_H_ +#define ERR_H_ //----------------------------------------------------------------------------- ---------------------------------------- // Application name // -static const char* const appName = "Wii_i2c"; //$ Name used in log files +static const char* const appName = "Wii_i2c"; //$ Name used in log files //----------------------------------------------------------------------------- ---------------------------------------- // Error codes and messages @@ -13,57 +13,60 @@ static const char* const appName = "Wii_i2c"; //$ Name used in log files // You should only ever (need to) edit this list // ...Watch out for extraneous whitespace after the terminating backslashes -#define FOREACH_ES(esPrial) \ - /* The first line MUST define 'ERR_OK = 0' */ \ - esPrial( 0, ERR_OK , "OK (no error)") \ -\ - esPrial( 1, ERR_MALLOC_QUEUE , "malloc() fail - queue") \ - esPrial( 2, ERR_MALLOC_STATE , "malloc() fail - state") \ - esPrial( 3, ERR_MALLOC_TEXT , "malloc() fail - text") \ - esPrial( 4, ERR_MALLOC_VIEW , "malloc() fail - viewport") \ - esPrial( 5, ERR_NO_MUTEX , "Cannot create mutex") \ - esPrial( 6, ERR_NO_GUI , "Cannot open GUI") \ - esPrial( 7, ERR_NO_TIMER , "Cannot create timer") \ - esPrial( 8, ERR_NO_NOTIFY , "Cannot acquire notifications handle") \ -\ - esPrial(10, ERR_MUTEX_BLOCK , "Mutex block failed") \ - esPrial(11, ERR_MUTEX_RELEASE , "Mutex release failed") \ -\ - esPrial(20, ERR_QUEUE_RTOS , "queue - Undefined RTOS error") \ - esPrial(21, DEBUG_QUEUE_TIMEOUT, "queue - Timeout") \ - esPrial(22, ERR_QUEUE_RESOURCE , "queue - Resource not available") \ - esPrial(23, ERR_QUEUE_BADPRM , "queue - Bad parameter") \ - esPrial(24, ERR_QUEUE_NOMEM , "queue - Out of memory") \ - esPrial(25, ERR_QUEUE_ISR , "queue - Banned in ISR") \ - esPrial(26, ERR_QUEUE_UNK , "queue - Unknown") \ -\ - esPrial(30, WARN_SCAN_START , "Scan - Already started") \ - esPrial(31, WARN_SCAN_STOP , "Scan - Already stopped") \ - esPrial(32, ERR_TIMER_START , "Scan - Cannot start timer") \ - esPrial(33, ERR_TIMER_STOP , "Scan - Cannot stop timer") \ -//[EOT] +#define FOREACH_ES(esPrial) \ + /* The first line MUST define 'ERR_OK = 0' */ \ + esPrial(0, ERR_OK, "OK (no error)") \ + \ + esPrial(1, ERR_MALLOC_QUEUE, "malloc() fail - queue") esPrial( \ + 2, \ + ERR_MALLOC_STATE, \ + "malloc() fail - state") esPrial(3, ERR_MALLOC_TEXT, "malloc() fail - text") \ + esPrial(4, ERR_MALLOC_VIEW, "malloc() fail - viewport") esPrial( \ + 5, ERR_NO_MUTEX, "Cannot create mutex") esPrial(6, ERR_NO_GUI, "Cannot open GUI") \ + esPrial(7, ERR_NO_TIMER, "Cannot create timer") esPrial( \ + 8, ERR_NO_NOTIFY, "Cannot acquire notifications handle") \ + \ + esPrial(10, ERR_MUTEX_BLOCK, "Mutex block failed") esPrial( \ + 11, ERR_MUTEX_RELEASE, "Mutex release failed") \ + \ + esPrial(20, ERR_QUEUE_RTOS, "queue - Undefined RTOS error") \ + esPrial(21, DEBUG_QUEUE_TIMEOUT, "queue - Timeout") esPrial( \ + 22, ERR_QUEUE_RESOURCE, "queue - Resource not available") \ + esPrial(23, ERR_QUEUE_BADPRM, "queue - Bad parameter") esPrial( \ + 24, ERR_QUEUE_NOMEM, "queue - Out of memory") \ + esPrial(25, ERR_QUEUE_ISR, "queue - Banned in ISR") esPrial( \ + 26, ERR_QUEUE_UNK, "queue - Unknown") \ + \ + esPrial(30, WARN_SCAN_START, "Scan - Already started") \ + esPrial(31, WARN_SCAN_STOP, "Scan - Already stopped") \ + esPrial( \ + 32, \ + ERR_TIMER_START, \ + "Scan - Cannot start timer") \ + esPrial( \ + 33, \ + ERR_TIMER_STOP, \ + "Scan - Cannot stop timer") //[EOT] // Declare list extraction macros -#define ES_ENUM(num, ename, string) ename = num, -#define ES_STRING(num, ename, string) string"\r\n", +#define ES_ENUM(num, ename, string) ename = num, +#define ES_STRING(num, ename, string) string "\r\n", // Build the enum -typedef - enum err { FOREACH_ES(ES_ENUM) } -err_t ; +typedef enum err { FOREACH_ES(ES_ENUM) } err_t; // You need to '#define ERR_C_' in precisely ONE source file #ifdef ERR_C_ - // Build the string list - const char* const wii_errs[] = { FOREACH_ES(ES_STRING) }; +// Build the string list +const char* const wii_errs[] = {FOREACH_ES(ES_STRING)}; #else - // Give access to string list - extern const char* const wii_errs[]; +// Give access to string list +extern const char* const wii_errs[]; #endif // This is a header file, clean up -#undef ES_ENUM -#undef ES_STRING -#undef FOREACH_ES +#undef ES_ENUM +#undef ES_STRING +#undef FOREACH_ES #endif // ERR_H_ diff --git a/applications/plugins/wii_ec_anal/gfx/images.c b/applications/plugins/wii_ec_anal/gfx/images.c index 57046e9a3..e8ab899f7 100644 --- a/applications/plugins/wii_ec_anal/gfx/images.c +++ b/applications/plugins/wii_ec_anal/gfx/images.c @@ -1,55 +1,49 @@ -#include // GUI (screen/keyboard) API +#include // GUI (screen/keyboard) API -#include "images.h" +#include "images.h" //----------------------------------------------------------------------------- ---------------------------------------- -static Canvas* _canvas; -static uint8_t _tlx; -static uint8_t _tly; +static Canvas* _canvas; +static uint8_t _tlx; +static uint8_t _tly; -static uint8_t _x; -static uint8_t _y; +static uint8_t _x; +static uint8_t _y; -static const image_t* _img; +static const image_t* _img; -static bool _blk; -static Color _set; -static Color _clr; +static bool _blk; +static Color _set; +static Color _clr; //+============================================================================ -static -void _showByteSet (const uint8_t b) -{ - for (uint8_t m = 0x80; m; m >>= 1) { - if (b & m) // plot only SET bits - canvas_draw_dot(_canvas, (_tlx +_x), (_tly +_y)) ; - if ( ((++_x) == _img->w) && !(_x = 0) && ((++_y) == _img->h) ) break ; - } +static void _showByteSet(const uint8_t b) { + for(uint8_t m = 0x80; m; m >>= 1) { + if(b & m) // plot only SET bits + canvas_draw_dot(_canvas, (_tlx + _x), (_tly + _y)); + if(((++_x) == _img->w) && !(_x = 0) && ((++_y) == _img->h)) break; + } } //+============================================================================ -static -void _showByteClr (const uint8_t b) -{ - for (uint8_t m = 0x80; m; m >>= 1) { - if (!(b & m)) // plot only CLR bits - canvas_draw_dot(_canvas, (_tlx +_x), (_tly +_y)) ; - if ( ((++_x) == _img->w) && !(_x = 0) && ((++_y) == _img->h) ) break ; - } +static void _showByteClr(const uint8_t b) { + for(uint8_t m = 0x80; m; m >>= 1) { + if(!(b & m)) // plot only CLR bits + canvas_draw_dot(_canvas, (_tlx + _x), (_tly + _y)); + if(((++_x) == _img->w) && !(_x = 0) && ((++_y) == _img->h)) break; + } } //+============================================================================ -static -void _showByteAll (const uint8_t b) -{ - for (uint8_t m = 0x80; m; m >>= 1) { - if ((!!(b & m)) ^ _blk) { // Change colour only when required - canvas_set_color(_canvas, ((b & m) ? _set : _clr)); - _blk = !_blk; - } - canvas_draw_dot(_canvas, (_tlx +_x), (_tly +_y)) ; - if ( ((++_x) == _img->w) && !(_x = 0) && ((++_y) == _img->h) ) break ; - } +static void _showByteAll(const uint8_t b) { + for(uint8_t m = 0x80; m; m >>= 1) { + if((!!(b & m)) ^ _blk) { // Change colour only when required + canvas_set_color(_canvas, ((b & m) ? _set : _clr)); + _blk = !_blk; + } + canvas_draw_dot(_canvas, (_tlx + _x), (_tly + _y)); + if(((++_x) == _img->w) && !(_x = 0) && ((++_y) == _img->h)) break; + } } //+============================================================================ @@ -61,81 +55,83 @@ void _showByteAll (const uint8_t b) // SHOW_ALL - plot all images pixels as they are // SHOW_ALL_INV - plot all images pixels inverted // -void show (Canvas* const canvas, const uint8_t tlx, const uint8_t tly, - const image_t* img, const showMode_t mode) -{ - void(*fnShow)(const uint8_t) = NULL; +void show( + Canvas* const canvas, + const uint8_t tlx, + const uint8_t tly, + const image_t* img, + const showMode_t mode) { + void (*fnShow)(const uint8_t) = NULL; - const uint8_t* bp = img->data; + const uint8_t* bp = img->data; - // code size optimisation - switch (mode & SHOW_INV_) { - case SHOW_NRM_: - _set = ColorBlack; - _clr = ColorWhite; - break; + // code size optimisation + switch(mode & SHOW_INV_) { + case SHOW_NRM_: + _set = ColorBlack; + _clr = ColorWhite; + break; - case SHOW_INV_: - _set = ColorWhite; - _clr = ColorBlack; - break; + case SHOW_INV_: + _set = ColorWhite; + _clr = ColorBlack; + break; - case SHOW_BLK_: - canvas_set_color(canvas, ColorBlack); - break; + case SHOW_BLK_: + canvas_set_color(canvas, ColorBlack); + break; - case SHOW_WHT_: - canvas_set_color(canvas, ColorWhite); - break; + case SHOW_WHT_: + canvas_set_color(canvas, ColorWhite); + break; + } + switch(mode & SHOW_INV_) { + case SHOW_NRM_: + case SHOW_INV_: + fnShow = _showByteAll; + canvas_set_color(canvas, ColorWhite); + _blk = 0; + break; - } - switch (mode & SHOW_INV_) { - case SHOW_NRM_: - case SHOW_INV_: - fnShow = _showByteAll; - canvas_set_color(canvas, ColorWhite); - _blk = 0; - break; + case SHOW_BLK_: + case SHOW_WHT_: + switch(mode & SHOW_ALL_) { + case SHOW_SET_: + fnShow = _showByteSet; + break; + case SHOW_CLR_: + fnShow = _showByteClr; + break; + } + break; + } + furi_check(fnShow); - case SHOW_BLK_: - case SHOW_WHT_: - switch (mode & SHOW_ALL_) { - case SHOW_SET_: - fnShow = _showByteSet; - break; - case SHOW_CLR_: - fnShow = _showByteClr; - break; - } - break; - } - furi_check(fnShow); + // I want nested functions! + _canvas = canvas; + _img = img; + _tlx = tlx; + _tly = tly; + _x = 0; + _y = 0; - // I want nested functions! - _canvas = canvas; - _img = img; - _tlx = tlx; - _tly = tly; - _x = 0; - _y = 0; + // Compressed + if(img->c) { + for(unsigned int i = 0; i < img->len; i++, bp++) { + // Compressed data? {tag, length, value} + if(*bp == img->tag) { + for(uint16_t c = 0; c < bp[1]; c++) fnShow(bp[2]); + bp += 3 - 1; + i += 3 - 1; - // Compressed - if (img->c) { - for (unsigned int i = 0; i < img->len; i++, bp++) { - // Compressed data? {tag, length, value} - if (*bp == img->tag) { - for (uint16_t c = 0; c < bp[1]; c++) fnShow(bp[2]) ; - bp += 3 -1; - i += 3 -1; + // Uncompressed byte + } else { + fnShow(*bp); + } + } - // Uncompressed byte - } else { - fnShow(*bp); - } - } - - // Not compressed - } else { - for (unsigned int i = 0; i < img->len; i++, bp++) fnShow(*bp) ; - } + // Not compressed + } else { + for(unsigned int i = 0; i < img->len; i++, bp++) fnShow(*bp); + } } diff --git a/applications/plugins/wii_ec_anal/gfx/images.h b/applications/plugins/wii_ec_anal/gfx/images.h index 87f2b89b7..d21909176 100644 --- a/applications/plugins/wii_ec_anal/gfx/images.h +++ b/applications/plugins/wii_ec_anal/gfx/images.h @@ -1,134 +1,134 @@ -#ifndef IMAGES_H_ -#define IMAGES_H_ +#ifndef IMAGES_H_ +#define IMAGES_H_ #include #include //----------------------------------------------------------------------------- ---------------------------------------- -typedef - enum showMode { - // {INV:--:WHT:BLK::--:--:CLR:SET} - SHOW_SET_ = 0x01, - SHOW_CLR_ = 0x02, - SHOW_ALL_ = SHOW_SET_ | SHOW_CLR_, +typedef enum showMode { + // {INV:--:WHT:BLK::--:--:CLR:SET} + SHOW_SET_ = 0x01, + SHOW_CLR_ = 0x02, + SHOW_ALL_ = SHOW_SET_ | SHOW_CLR_, - SHOW_BLK_ = 0x10, - SHOW_WHT_ = 0x20, - SHOW_NRM_ = 0x00, - SHOW_INV_ = SHOW_BLK_ | SHOW_WHT_, + SHOW_BLK_ = 0x10, + SHOW_WHT_ = 0x20, + SHOW_NRM_ = 0x00, + SHOW_INV_ = SHOW_BLK_ | SHOW_WHT_, - SHOW_SET_BLK = SHOW_SET_ | SHOW_BLK_, - SHOW_SET_WHT = SHOW_SET_ | SHOW_WHT_, + SHOW_SET_BLK = SHOW_SET_ | SHOW_BLK_, + SHOW_SET_WHT = SHOW_SET_ | SHOW_WHT_, - SHOW_CLR_BLK = SHOW_CLR_ | SHOW_BLK_, - SHOW_CLR_WHT = SHOW_CLR_ | SHOW_WHT_, + SHOW_CLR_BLK = SHOW_CLR_ | SHOW_BLK_, + SHOW_CLR_WHT = SHOW_CLR_ | SHOW_WHT_, - SHOW_ALL = SHOW_ALL_ | SHOW_NRM_, - SHOW_ALL_INV = SHOW_ALL_ | SHOW_INV_, - } -showMode_t; + SHOW_ALL = SHOW_ALL_ | SHOW_NRM_, + SHOW_ALL_INV = SHOW_ALL_ | SHOW_INV_, +} showMode_t; //----------------------------------------------------------------------------- ---------------------------------------- -typedef - struct image { - uint8_t w; // width - uint8_t h; // height - bool c; // compressed? - uint16_t len; // image data length - uint8_t tag; // rle tag - uint8_t data[]; // image data - } -image_t; +typedef struct image { + uint8_t w; // width + uint8_t h; // height + bool c; // compressed? + uint16_t len; // image data length + uint8_t tag; // rle tag + uint8_t data[]; // image data +} image_t; //----------------------------------------------------------------------------- ---------------------------------------- //[TAG] -extern const image_t img_csLogo_Small; -extern const image_t img_3x5_v; -extern const image_t img_3x5_9; -extern const image_t img_3x5_8; -extern const image_t img_3x5_7; -extern const image_t img_3x5_6; -extern const image_t img_3x5_5; -extern const image_t img_3x5_4; -extern const image_t img_3x5_3; -extern const image_t img_3x5_2; -extern const image_t img_3x5_1; -extern const image_t img_3x5_0; -extern const image_t img_key_Ui; -extern const image_t img_key_OKi; -extern const image_t img_RIP; -extern const image_t img_cc_trg_R4; -extern const image_t img_cc_trg_R3; -extern const image_t img_cc_trg_R2; -extern const image_t img_cc_trg_R1; -extern const image_t img_cc_trg_L4; -extern const image_t img_cc_trg_L3; -extern const image_t img_cc_trg_L2; -extern const image_t img_cc_trg_L1; -extern const image_t img_cc_Joy; -extern const image_t img_cc_Main; -extern const image_t img_cc_Cable; -extern const image_t img_key_Back; -extern const image_t img_key_OK; -extern const image_t img_6x8_Z; -extern const image_t img_6x8_Y; -extern const image_t img_6x8_X; -extern const image_t img_key_U; -extern const image_t img_key_D; -extern const image_t img_csLogo_FULL; -extern const image_t img_6x8_7; -extern const image_t img_key_R; -extern const image_t img_key_L; -extern const image_t img_5x7_7; -extern const image_t img_5x7_F; -extern const image_t img_5x7_E; -extern const image_t img_5x7_D; -extern const image_t img_5x7_C; -extern const image_t img_5x7_B; -extern const image_t img_5x7_A; -extern const image_t img_5x7_9; -extern const image_t img_5x7_8; -extern const image_t img_5x7_6; -extern const image_t img_5x7_5; -extern const image_t img_5x7_4; -extern const image_t img_5x7_3; -extern const image_t img_5x7_2; -extern const image_t img_5x7_1; -extern const image_t img_5x7_0; -extern const image_t img_6x8_v; -extern const image_t img_6x8_n; -extern const image_t img_6x8_G; -extern const image_t img_6x8_F; -extern const image_t img_6x8_E; -extern const image_t img_6x8_d; -extern const image_t img_6x8_C; -extern const image_t img_6x8_B; -extern const image_t img_6x8_A; -extern const image_t img_6x8_9; -extern const image_t img_6x8_8; -extern const image_t img_6x8_6; -extern const image_t img_6x8_5; -extern const image_t img_6x8_4; -extern const image_t img_6x8_3; -extern const image_t img_6x8_2; -extern const image_t img_6x8_1; -extern const image_t img_6x8_0; -extern const image_t img_ecp_SDA; -extern const image_t img_ecp_SCL; -extern const image_t img_ecp_port; -extern const image_t img_cc_pad_UD1; -extern const image_t img_cc_pad_LR1; -extern const image_t img_cc_btn_Y1; -extern const image_t img_cc_btn_X1; -extern const image_t img_cc_btn_B1; -extern const image_t img_cc_btn_A1; -extern const image_t img_6x8_D; +extern const image_t img_csLogo_Small; +extern const image_t img_3x5_v; +extern const image_t img_3x5_9; +extern const image_t img_3x5_8; +extern const image_t img_3x5_7; +extern const image_t img_3x5_6; +extern const image_t img_3x5_5; +extern const image_t img_3x5_4; +extern const image_t img_3x5_3; +extern const image_t img_3x5_2; +extern const image_t img_3x5_1; +extern const image_t img_3x5_0; +extern const image_t img_key_Ui; +extern const image_t img_key_OKi; +extern const image_t img_RIP; +extern const image_t img_cc_trg_R4; +extern const image_t img_cc_trg_R3; +extern const image_t img_cc_trg_R2; +extern const image_t img_cc_trg_R1; +extern const image_t img_cc_trg_L4; +extern const image_t img_cc_trg_L3; +extern const image_t img_cc_trg_L2; +extern const image_t img_cc_trg_L1; +extern const image_t img_cc_Joy; +extern const image_t img_cc_Main; +extern const image_t img_cc_Cable; +extern const image_t img_key_Back; +extern const image_t img_key_OK; +extern const image_t img_6x8_Z; +extern const image_t img_6x8_Y; +extern const image_t img_6x8_X; +extern const image_t img_key_U; +extern const image_t img_key_D; +extern const image_t img_csLogo_FULL; +extern const image_t img_6x8_7; +extern const image_t img_key_R; +extern const image_t img_key_L; +extern const image_t img_5x7_7; +extern const image_t img_5x7_F; +extern const image_t img_5x7_E; +extern const image_t img_5x7_D; +extern const image_t img_5x7_C; +extern const image_t img_5x7_B; +extern const image_t img_5x7_A; +extern const image_t img_5x7_9; +extern const image_t img_5x7_8; +extern const image_t img_5x7_6; +extern const image_t img_5x7_5; +extern const image_t img_5x7_4; +extern const image_t img_5x7_3; +extern const image_t img_5x7_2; +extern const image_t img_5x7_1; +extern const image_t img_5x7_0; +extern const image_t img_6x8_v; +extern const image_t img_6x8_n; +extern const image_t img_6x8_G; +extern const image_t img_6x8_F; +extern const image_t img_6x8_E; +extern const image_t img_6x8_d; +extern const image_t img_6x8_C; +extern const image_t img_6x8_B; +extern const image_t img_6x8_A; +extern const image_t img_6x8_9; +extern const image_t img_6x8_8; +extern const image_t img_6x8_6; +extern const image_t img_6x8_5; +extern const image_t img_6x8_4; +extern const image_t img_6x8_3; +extern const image_t img_6x8_2; +extern const image_t img_6x8_1; +extern const image_t img_6x8_0; +extern const image_t img_ecp_SDA; +extern const image_t img_ecp_SCL; +extern const image_t img_ecp_port; +extern const image_t img_cc_pad_UD1; +extern const image_t img_cc_pad_LR1; +extern const image_t img_cc_btn_Y1; +extern const image_t img_cc_btn_X1; +extern const image_t img_cc_btn_B1; +extern const image_t img_cc_btn_A1; +extern const image_t img_6x8_D; //----------------------------------------------------------------------------- ---------------------------------------- #ifndef IMGTEST -# include - void show (Canvas* const canvas, const uint8_t tlx, const uint8_t tly, - const image_t* img, const showMode_t mode) ; +#include +void show( + Canvas* const canvas, + const uint8_t tlx, + const uint8_t tly, + const image_t* img, + const showMode_t mode); #endif #endif //IMAGES_H_ diff --git a/applications/plugins/wii_ec_anal/gfx/img_3x5_0.c b/applications/plugins/wii_ec_anal/gfx/img_3x5_0.c index 975d98d35..8fc8e0e14 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_3x5_0.c +++ b/applications/plugins/wii_ec_anal/gfx/img_3x5_0.c @@ -6,6 +6,4 @@ #include "images.h" -const image_t img_3x5_0 = { 3, 5, false, 2, 0, { - 0xF6, 0xDE -}}; +const image_t img_3x5_0 = {3, 5, false, 2, 0, {0xF6, 0xDE}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_3x5_1.c b/applications/plugins/wii_ec_anal/gfx/img_3x5_1.c index 0d9dc3fe4..8b7d4cf80 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_3x5_1.c +++ b/applications/plugins/wii_ec_anal/gfx/img_3x5_1.c @@ -6,6 +6,4 @@ #include "images.h" -const image_t img_3x5_1 = { 3, 5, false, 2, 0, { - 0xC9, 0x2E -}}; +const image_t img_3x5_1 = {3, 5, false, 2, 0, {0xC9, 0x2E}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_3x5_2.c b/applications/plugins/wii_ec_anal/gfx/img_3x5_2.c index d98bf4e93..89a81c75e 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_3x5_2.c +++ b/applications/plugins/wii_ec_anal/gfx/img_3x5_2.c @@ -6,6 +6,4 @@ #include "images.h" -const image_t img_3x5_2 = { 3, 5, false, 2, 0, { - 0xE7, 0xCE -}}; +const image_t img_3x5_2 = {3, 5, false, 2, 0, {0xE7, 0xCE}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_3x5_3.c b/applications/plugins/wii_ec_anal/gfx/img_3x5_3.c index 8d08ed1b6..97ff0478a 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_3x5_3.c +++ b/applications/plugins/wii_ec_anal/gfx/img_3x5_3.c @@ -6,6 +6,4 @@ #include "images.h" -const image_t img_3x5_3 = { 3, 5, false, 2, 0, { - 0xE5, 0x9E -}}; +const image_t img_3x5_3 = {3, 5, false, 2, 0, {0xE5, 0x9E}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_3x5_4.c b/applications/plugins/wii_ec_anal/gfx/img_3x5_4.c index 795e9b76f..2bbd9ef42 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_3x5_4.c +++ b/applications/plugins/wii_ec_anal/gfx/img_3x5_4.c @@ -6,6 +6,4 @@ #include "images.h" -const image_t img_3x5_4 = { 3, 5, false, 2, 0, { - 0x97, 0x92 -}}; +const image_t img_3x5_4 = {3, 5, false, 2, 0, {0x97, 0x92}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_3x5_5.c b/applications/plugins/wii_ec_anal/gfx/img_3x5_5.c index 377853507..e0466f37a 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_3x5_5.c +++ b/applications/plugins/wii_ec_anal/gfx/img_3x5_5.c @@ -6,6 +6,4 @@ #include "images.h" -const image_t img_3x5_5 = { 3, 5, false, 2, 0, { - 0xF3, 0x9E -}}; +const image_t img_3x5_5 = {3, 5, false, 2, 0, {0xF3, 0x9E}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_3x5_6.c b/applications/plugins/wii_ec_anal/gfx/img_3x5_6.c index d3af64071..1b62caf72 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_3x5_6.c +++ b/applications/plugins/wii_ec_anal/gfx/img_3x5_6.c @@ -6,6 +6,4 @@ #include "images.h" -const image_t img_3x5_6 = { 3, 5, false, 2, 0, { - 0xD3, 0xDE -}}; +const image_t img_3x5_6 = {3, 5, false, 2, 0, {0xD3, 0xDE}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_3x5_7.c b/applications/plugins/wii_ec_anal/gfx/img_3x5_7.c index 2c3b1e0b9..acfe57cf8 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_3x5_7.c +++ b/applications/plugins/wii_ec_anal/gfx/img_3x5_7.c @@ -6,6 +6,4 @@ #include "images.h" -const image_t img_3x5_7 = { 3, 5, false, 2, 0, { - 0xE5, 0x24 -}}; +const image_t img_3x5_7 = {3, 5, false, 2, 0, {0xE5, 0x24}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_3x5_8.c b/applications/plugins/wii_ec_anal/gfx/img_3x5_8.c index 5cb6d3354..31f32af52 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_3x5_8.c +++ b/applications/plugins/wii_ec_anal/gfx/img_3x5_8.c @@ -6,6 +6,4 @@ #include "images.h" -const image_t img_3x5_8 = { 3, 5, false, 2, 0, { - 0xF7, 0xDE -}}; +const image_t img_3x5_8 = {3, 5, false, 2, 0, {0xF7, 0xDE}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_3x5_9.c b/applications/plugins/wii_ec_anal/gfx/img_3x5_9.c index ee5e82b87..4b1ba1e09 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_3x5_9.c +++ b/applications/plugins/wii_ec_anal/gfx/img_3x5_9.c @@ -6,6 +6,4 @@ #include "images.h" -const image_t img_3x5_9 = { 3, 5, false, 2, 0, { - 0xF7, 0x96 -}}; +const image_t img_3x5_9 = {3, 5, false, 2, 0, {0xF7, 0x96}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_3x5_v.c b/applications/plugins/wii_ec_anal/gfx/img_3x5_v.c index dcf3f631d..2282e1697 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_3x5_v.c +++ b/applications/plugins/wii_ec_anal/gfx/img_3x5_v.c @@ -6,6 +6,4 @@ #include "images.h" -const image_t img_3x5_v = { 3, 5, false, 2, 0, { - 0x02, 0xD4 -}}; +const image_t img_3x5_v = {3, 5, false, 2, 0, {0x02, 0xD4}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_5x7_0.c b/applications/plugins/wii_ec_anal/gfx/img_5x7_0.c index c59852f19..7ae2186b3 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_5x7_0.c +++ b/applications/plugins/wii_ec_anal/gfx/img_5x7_0.c @@ -8,6 +8,4 @@ #include "images.h" -const image_t img_5x7_0 = { 5, 7, false, 5, 0, { - 0x74, 0x67, 0x5C, 0xC5, 0xC0 -}}; +const image_t img_5x7_0 = {5, 7, false, 5, 0, {0x74, 0x67, 0x5C, 0xC5, 0xC0}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_5x7_1.c b/applications/plugins/wii_ec_anal/gfx/img_5x7_1.c index 4bd08f89c..c1a9cec74 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_5x7_1.c +++ b/applications/plugins/wii_ec_anal/gfx/img_5x7_1.c @@ -8,6 +8,4 @@ #include "images.h" -const image_t img_5x7_1 = { 5, 7, false, 5, 0, { - 0x65, 0x08, 0x42, 0x13, 0xE0 -}}; +const image_t img_5x7_1 = {5, 7, false, 5, 0, {0x65, 0x08, 0x42, 0x13, 0xE0}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_5x7_2.c b/applications/plugins/wii_ec_anal/gfx/img_5x7_2.c index 1270393f7..7fab90010 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_5x7_2.c +++ b/applications/plugins/wii_ec_anal/gfx/img_5x7_2.c @@ -8,6 +8,4 @@ #include "images.h" -const image_t img_5x7_2 = { 5, 7, false, 5, 0, { - 0x74, 0x42, 0x22, 0x23, 0xE0 -}}; +const image_t img_5x7_2 = {5, 7, false, 5, 0, {0x74, 0x42, 0x22, 0x23, 0xE0}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_5x7_3.c b/applications/plugins/wii_ec_anal/gfx/img_5x7_3.c index e26bac523..2099bf795 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_5x7_3.c +++ b/applications/plugins/wii_ec_anal/gfx/img_5x7_3.c @@ -8,6 +8,4 @@ #include "images.h" -const image_t img_5x7_3 = { 5, 7, false, 5, 0, { - 0x74, 0x42, 0x60, 0xC5, 0xC0 -}}; +const image_t img_5x7_3 = {5, 7, false, 5, 0, {0x74, 0x42, 0x60, 0xC5, 0xC0}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_5x7_4.c b/applications/plugins/wii_ec_anal/gfx/img_5x7_4.c index e0dc5687f..1eee4f07d 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_5x7_4.c +++ b/applications/plugins/wii_ec_anal/gfx/img_5x7_4.c @@ -8,6 +8,4 @@ #include "images.h" -const image_t img_5x7_4 = { 5, 7, false, 5, 0, { - 0x84, 0x25, 0x2F, 0x88, 0x40 -}}; +const image_t img_5x7_4 = {5, 7, false, 5, 0, {0x84, 0x25, 0x2F, 0x88, 0x40}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_5x7_5.c b/applications/plugins/wii_ec_anal/gfx/img_5x7_5.c index 81747376f..be1e54681 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_5x7_5.c +++ b/applications/plugins/wii_ec_anal/gfx/img_5x7_5.c @@ -8,6 +8,4 @@ #include "images.h" -const image_t img_5x7_5 = { 5, 7, false, 5, 0, { - 0xFC, 0x21, 0xE0, 0x87, 0xC0 -}}; +const image_t img_5x7_5 = {5, 7, false, 5, 0, {0xFC, 0x21, 0xE0, 0x87, 0xC0}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_5x7_6.c b/applications/plugins/wii_ec_anal/gfx/img_5x7_6.c index 455c874dc..da155c1b5 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_5x7_6.c +++ b/applications/plugins/wii_ec_anal/gfx/img_5x7_6.c @@ -8,6 +8,4 @@ #include "images.h" -const image_t img_5x7_6 = { 5, 7, false, 5, 0, { - 0x74, 0x21, 0xE8, 0xC5, 0xC0 -}}; +const image_t img_5x7_6 = {5, 7, false, 5, 0, {0x74, 0x21, 0xE8, 0xC5, 0xC0}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_5x7_7.c b/applications/plugins/wii_ec_anal/gfx/img_5x7_7.c index 73e813a21..fde7e8ea2 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_5x7_7.c +++ b/applications/plugins/wii_ec_anal/gfx/img_5x7_7.c @@ -8,6 +8,4 @@ #include "images.h" -const image_t img_5x7_7 = { 5, 7, false, 5, 0, { - 0xF8, 0x44, 0x22, 0x10, 0x80 -}}; +const image_t img_5x7_7 = {5, 7, false, 5, 0, {0xF8, 0x44, 0x22, 0x10, 0x80}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_5x7_8.c b/applications/plugins/wii_ec_anal/gfx/img_5x7_8.c index 0f04a48bf..aff178282 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_5x7_8.c +++ b/applications/plugins/wii_ec_anal/gfx/img_5x7_8.c @@ -8,6 +8,4 @@ #include "images.h" -const image_t img_5x7_8 = { 5, 7, false, 5, 0, { - 0x74, 0x62, 0xE8, 0xC5, 0xC0 -}}; +const image_t img_5x7_8 = {5, 7, false, 5, 0, {0x74, 0x62, 0xE8, 0xC5, 0xC0}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_5x7_9.c b/applications/plugins/wii_ec_anal/gfx/img_5x7_9.c index 2b1e978c6..2417c57e8 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_5x7_9.c +++ b/applications/plugins/wii_ec_anal/gfx/img_5x7_9.c @@ -8,6 +8,4 @@ #include "images.h" -const image_t img_5x7_9 = { 5, 7, false, 5, 0, { - 0x74, 0x62, 0xF0, 0x85, 0xC0 -}}; +const image_t img_5x7_9 = {5, 7, false, 5, 0, {0x74, 0x62, 0xF0, 0x85, 0xC0}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_5x7_A.c b/applications/plugins/wii_ec_anal/gfx/img_5x7_A.c index a6b049f01..910c034a2 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_5x7_A.c +++ b/applications/plugins/wii_ec_anal/gfx/img_5x7_A.c @@ -8,6 +8,4 @@ #include "images.h" -const image_t img_5x7_A = { 5, 7, false, 5, 0, { - 0x74, 0x63, 0xF8, 0xC6, 0x20 -}}; +const image_t img_5x7_A = {5, 7, false, 5, 0, {0x74, 0x63, 0xF8, 0xC6, 0x20}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_5x7_B.c b/applications/plugins/wii_ec_anal/gfx/img_5x7_B.c index 06b36599c..93808fee2 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_5x7_B.c +++ b/applications/plugins/wii_ec_anal/gfx/img_5x7_B.c @@ -8,6 +8,4 @@ #include "images.h" -const image_t img_5x7_B = { 5, 7, false, 5, 0, { - 0xF4, 0x63, 0x68, 0xC7, 0xC0 -}}; +const image_t img_5x7_B = {5, 7, false, 5, 0, {0xF4, 0x63, 0x68, 0xC7, 0xC0}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_5x7_C.c b/applications/plugins/wii_ec_anal/gfx/img_5x7_C.c index c058d09a9..1438eaf44 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_5x7_C.c +++ b/applications/plugins/wii_ec_anal/gfx/img_5x7_C.c @@ -8,6 +8,4 @@ #include "images.h" -const image_t img_5x7_C = { 5, 7, false, 5, 0, { - 0x74, 0x61, 0x08, 0x45, 0xC0 -}}; +const image_t img_5x7_C = {5, 7, false, 5, 0, {0x74, 0x61, 0x08, 0x45, 0xC0}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_5x7_D.c b/applications/plugins/wii_ec_anal/gfx/img_5x7_D.c index 3425e3648..9c6b590ee 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_5x7_D.c +++ b/applications/plugins/wii_ec_anal/gfx/img_5x7_D.c @@ -8,6 +8,4 @@ #include "images.h" -const image_t img_5x7_D = { 5, 7, false, 5, 0, { - 0x75, 0x4A, 0x52, 0xD5, 0xC0 -}}; +const image_t img_5x7_D = {5, 7, false, 5, 0, {0x75, 0x4A, 0x52, 0xD5, 0xC0}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_5x7_E.c b/applications/plugins/wii_ec_anal/gfx/img_5x7_E.c index c7bbc301a..bc15fb240 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_5x7_E.c +++ b/applications/plugins/wii_ec_anal/gfx/img_5x7_E.c @@ -8,6 +8,4 @@ #include "images.h" -const image_t img_5x7_E = { 5, 7, false, 5, 0, { - 0xFC, 0x21, 0xC8, 0x43, 0xE0 -}}; +const image_t img_5x7_E = {5, 7, false, 5, 0, {0xFC, 0x21, 0xC8, 0x43, 0xE0}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_5x7_F.c b/applications/plugins/wii_ec_anal/gfx/img_5x7_F.c index 440c37eae..e4ad0db69 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_5x7_F.c +++ b/applications/plugins/wii_ec_anal/gfx/img_5x7_F.c @@ -8,6 +8,4 @@ #include "images.h" -const image_t img_5x7_F = { 5, 7, false, 5, 0, { - 0xFC, 0x21, 0xC8, 0x42, 0x00 -}}; +const image_t img_5x7_F = {5, 7, false, 5, 0, {0xFC, 0x21, 0xC8, 0x42, 0x00}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_6x8_0.c b/applications/plugins/wii_ec_anal/gfx/img_6x8_0.c index b8b4c7d9a..952cf34d8 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_6x8_0.c +++ b/applications/plugins/wii_ec_anal/gfx/img_6x8_0.c @@ -9,6 +9,4 @@ #include "images.h" -const image_t img_6x8_0 = { 6, 8, false, 6, 0, { - 0x7B, 0xFC, 0xF3, 0xCF, 0x3F, 0xDE -}}; +const image_t img_6x8_0 = {6, 8, false, 6, 0, {0x7B, 0xFC, 0xF3, 0xCF, 0x3F, 0xDE}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_6x8_1.c b/applications/plugins/wii_ec_anal/gfx/img_6x8_1.c index 91e2b2cfa..846a6876c 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_6x8_1.c +++ b/applications/plugins/wii_ec_anal/gfx/img_6x8_1.c @@ -9,6 +9,4 @@ #include "images.h" -const image_t img_6x8_1 = { 6, 8, false, 6, 0, { - 0x73, 0xC3, 0x0C, 0x30, 0xCF, 0xFF -}}; +const image_t img_6x8_1 = {6, 8, false, 6, 0, {0x73, 0xC3, 0x0C, 0x30, 0xCF, 0xFF}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_6x8_2.c b/applications/plugins/wii_ec_anal/gfx/img_6x8_2.c index 7d24c64d6..4534bb67c 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_6x8_2.c +++ b/applications/plugins/wii_ec_anal/gfx/img_6x8_2.c @@ -9,6 +9,4 @@ #include "images.h" -const image_t img_6x8_2 = { 6, 8, false, 6, 0, { - 0x7B, 0xF0, 0xC7, 0x31, 0x8F, 0xFF -}}; +const image_t img_6x8_2 = {6, 8, false, 6, 0, {0x7B, 0xF0, 0xC7, 0x31, 0x8F, 0xFF}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_6x8_3.c b/applications/plugins/wii_ec_anal/gfx/img_6x8_3.c index 3a8f9f211..7e79eb03a 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_6x8_3.c +++ b/applications/plugins/wii_ec_anal/gfx/img_6x8_3.c @@ -9,6 +9,4 @@ #include "images.h" -const image_t img_6x8_3 = { 6, 8, false, 6, 0, { - 0x7B, 0xF0, 0xCF, 0x3C, 0x3F, 0xDE -}}; +const image_t img_6x8_3 = {6, 8, false, 6, 0, {0x7B, 0xF0, 0xCF, 0x3C, 0x3F, 0xDE}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_6x8_4.c b/applications/plugins/wii_ec_anal/gfx/img_6x8_4.c index c5ae9efef..324b036ce 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_6x8_4.c +++ b/applications/plugins/wii_ec_anal/gfx/img_6x8_4.c @@ -9,6 +9,4 @@ #include "images.h" -const image_t img_6x8_4 = { 6, 8, false, 6, 0, { - 0xC3, 0x0D, 0xB6, 0xFF, 0xF1, 0x86 -}}; +const image_t img_6x8_4 = {6, 8, false, 6, 0, {0xC3, 0x0D, 0xB6, 0xFF, 0xF1, 0x86}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_6x8_5.c b/applications/plugins/wii_ec_anal/gfx/img_6x8_5.c index 787e39ea6..cdfda5f2b 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_6x8_5.c +++ b/applications/plugins/wii_ec_anal/gfx/img_6x8_5.c @@ -9,6 +9,4 @@ #include "images.h" -const image_t img_6x8_5 = { 6, 8, false, 6, 0, { - 0xFF, 0xFC, 0x3E, 0xFC, 0x3F, 0xFE -}}; +const image_t img_6x8_5 = {6, 8, false, 6, 0, {0xFF, 0xFC, 0x3E, 0xFC, 0x3F, 0xFE}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_6x8_6.c b/applications/plugins/wii_ec_anal/gfx/img_6x8_6.c index 8f07f1bfc..781a060f1 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_6x8_6.c +++ b/applications/plugins/wii_ec_anal/gfx/img_6x8_6.c @@ -9,6 +9,4 @@ #include "images.h" -const image_t img_6x8_6 = { 6, 8, false, 6, 0, { - 0x7B, 0xEC, 0x3E, 0xFF, 0x3F, 0xDE -}}; +const image_t img_6x8_6 = {6, 8, false, 6, 0, {0x7B, 0xEC, 0x3E, 0xFF, 0x3F, 0xDE}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_6x8_7.c b/applications/plugins/wii_ec_anal/gfx/img_6x8_7.c index cad50c65d..fec5f4bf4 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_6x8_7.c +++ b/applications/plugins/wii_ec_anal/gfx/img_6x8_7.c @@ -9,6 +9,4 @@ #include "images.h" -const image_t img_6x8_7 = { 6, 8, false, 6, 0, { - 0xFF, 0xF0, 0xC6, 0x18, 0xC3, 0x0C -}}; +const image_t img_6x8_7 = {6, 8, false, 6, 0, {0xFF, 0xF0, 0xC6, 0x18, 0xC3, 0x0C}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_6x8_8.c b/applications/plugins/wii_ec_anal/gfx/img_6x8_8.c index a38b2110d..a5b21c375 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_6x8_8.c +++ b/applications/plugins/wii_ec_anal/gfx/img_6x8_8.c @@ -9,6 +9,4 @@ #include "images.h" -const image_t img_6x8_8 = { 6, 8, false, 6, 0, { - 0x7B, 0xFC, 0xDE, 0xFF, 0x3F, 0xDE -}}; +const image_t img_6x8_8 = {6, 8, false, 6, 0, {0x7B, 0xFC, 0xDE, 0xFF, 0x3F, 0xDE}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_6x8_9.c b/applications/plugins/wii_ec_anal/gfx/img_6x8_9.c index b740c7f90..f7707c0df 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_6x8_9.c +++ b/applications/plugins/wii_ec_anal/gfx/img_6x8_9.c @@ -9,6 +9,4 @@ #include "images.h" -const image_t img_6x8_9 = { 6, 8, false, 6, 0, { - 0x7B, 0xFC, 0xFF, 0x7C, 0x37, 0xDE -}}; +const image_t img_6x8_9 = {6, 8, false, 6, 0, {0x7B, 0xFC, 0xFF, 0x7C, 0x37, 0xDE}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_6x8_A.c b/applications/plugins/wii_ec_anal/gfx/img_6x8_A.c index fa3aed598..1bb65c902 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_6x8_A.c +++ b/applications/plugins/wii_ec_anal/gfx/img_6x8_A.c @@ -9,6 +9,4 @@ #include "images.h" -const image_t img_6x8_A = { 6, 8, false, 6, 0, { - 0x7B, 0xFC, 0xF3, 0xFF, 0xFC, 0xF3 -}}; +const image_t img_6x8_A = {6, 8, false, 6, 0, {0x7B, 0xFC, 0xF3, 0xFF, 0xFC, 0xF3}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_6x8_B.c b/applications/plugins/wii_ec_anal/gfx/img_6x8_B.c index 14c1e28c6..00e012d53 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_6x8_B.c +++ b/applications/plugins/wii_ec_anal/gfx/img_6x8_B.c @@ -9,6 +9,4 @@ #include "images.h" -const image_t img_6x8_B = { 6, 8, false, 6, 0, { - 0xFB, 0xFC, 0xFE, 0xFB, 0x3F, 0xFE -}}; +const image_t img_6x8_B = {6, 8, false, 6, 0, {0xFB, 0xFC, 0xFE, 0xFB, 0x3F, 0xFE}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_6x8_C.c b/applications/plugins/wii_ec_anal/gfx/img_6x8_C.c index 6d8f7aa32..694901009 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_6x8_C.c +++ b/applications/plugins/wii_ec_anal/gfx/img_6x8_C.c @@ -9,6 +9,4 @@ #include "images.h" -const image_t img_6x8_C = { 6, 8, false, 6, 0, { - 0x7F, 0xFC, 0x30, 0xC3, 0x0F, 0xDF -}}; +const image_t img_6x8_C = {6, 8, false, 6, 0, {0x7F, 0xFC, 0x30, 0xC3, 0x0F, 0xDF}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_6x8_D.c b/applications/plugins/wii_ec_anal/gfx/img_6x8_D.c index 474e4a235..a95e760eb 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_6x8_D.c +++ b/applications/plugins/wii_ec_anal/gfx/img_6x8_D.c @@ -9,6 +9,4 @@ #include "images.h" -const image_t img_6x8_D = { 6, 8, false, 6, 0, { - 0xFB, 0xF6, 0xDB, 0x6D, 0xBF, 0xFE -}}; +const image_t img_6x8_D = {6, 8, false, 6, 0, {0xFB, 0xF6, 0xDB, 0x6D, 0xBF, 0xFE}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_6x8_E.c b/applications/plugins/wii_ec_anal/gfx/img_6x8_E.c index 00f2cb559..f49503f00 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_6x8_E.c +++ b/applications/plugins/wii_ec_anal/gfx/img_6x8_E.c @@ -9,6 +9,4 @@ #include "images.h" -const image_t img_6x8_E = { 6, 8, false, 6, 0, { - 0xFF, 0xFC, 0x3C, 0xF3, 0x0F, 0xFF -}}; +const image_t img_6x8_E = {6, 8, false, 6, 0, {0xFF, 0xFC, 0x3C, 0xF3, 0x0F, 0xFF}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_6x8_F.c b/applications/plugins/wii_ec_anal/gfx/img_6x8_F.c index 8958a0419..0037b2544 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_6x8_F.c +++ b/applications/plugins/wii_ec_anal/gfx/img_6x8_F.c @@ -9,6 +9,4 @@ #include "images.h" -const image_t img_6x8_F = { 6, 8, false, 6, 0, { - 0xFF, 0xFC, 0x3C, 0xF3, 0x0C, 0x30 -}}; +const image_t img_6x8_F = {6, 8, false, 6, 0, {0xFF, 0xFC, 0x3C, 0xF3, 0x0C, 0x30}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_6x8_G.c b/applications/plugins/wii_ec_anal/gfx/img_6x8_G.c index f5e8f03f4..f30bc9952 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_6x8_G.c +++ b/applications/plugins/wii_ec_anal/gfx/img_6x8_G.c @@ -9,6 +9,4 @@ #include "images.h" -const image_t img_6x8_G = { 6, 8, false, 6, 0, { - 0x7F, 0xFC, 0x30, 0xDF, 0x3F, 0xDF -}}; +const image_t img_6x8_G = {6, 8, false, 6, 0, {0x7F, 0xFC, 0x30, 0xDF, 0x3F, 0xDF}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_6x8_X.c b/applications/plugins/wii_ec_anal/gfx/img_6x8_X.c index 7b162baf3..4735e82a1 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_6x8_X.c +++ b/applications/plugins/wii_ec_anal/gfx/img_6x8_X.c @@ -9,6 +9,4 @@ #include "images.h" -const image_t img_6x8_X = { 6, 8, false, 6, 0, { - 0xCF, 0x36, 0x8E, 0x71, 0x6C, 0xF3 -}}; +const image_t img_6x8_X = {6, 8, false, 6, 0, {0xCF, 0x36, 0x8E, 0x71, 0x6C, 0xF3}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_6x8_Y.c b/applications/plugins/wii_ec_anal/gfx/img_6x8_Y.c index b39392948..508e786bd 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_6x8_Y.c +++ b/applications/plugins/wii_ec_anal/gfx/img_6x8_Y.c @@ -9,6 +9,4 @@ #include "images.h" -const image_t img_6x8_Y = { 6, 8, false, 6, 0, { - 0xCF, 0x3C, 0xF3, 0x78, 0xC3, 0x0C -}}; +const image_t img_6x8_Y = {6, 8, false, 6, 0, {0xCF, 0x3C, 0xF3, 0x78, 0xC3, 0x0C}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_6x8_Z.c b/applications/plugins/wii_ec_anal/gfx/img_6x8_Z.c index 9904d08b4..c42d560ac 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_6x8_Z.c +++ b/applications/plugins/wii_ec_anal/gfx/img_6x8_Z.c @@ -9,6 +9,4 @@ #include "images.h" -const image_t img_6x8_Z = { 6, 8, false, 6, 0, { - 0xFF, 0xF0, 0xC6, 0x31, 0x8F, 0xFF -}}; +const image_t img_6x8_Z = {6, 8, false, 6, 0, {0xFF, 0xF0, 0xC6, 0x31, 0x8F, 0xFF}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_6x8_d_.c b/applications/plugins/wii_ec_anal/gfx/img_6x8_d_.c index 2a00713fd..1f8123a6c 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_6x8_d_.c +++ b/applications/plugins/wii_ec_anal/gfx/img_6x8_d_.c @@ -9,6 +9,4 @@ #include "images.h" -const image_t img_6x8_d = { 6, 8, false, 6, 0, { - 0x0C, 0x30, 0xDF, 0xFF, 0x3F, 0xDF -}}; +const image_t img_6x8_d = {6, 8, false, 6, 0, {0x0C, 0x30, 0xDF, 0xFF, 0x3F, 0xDF}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_6x8_n_.c b/applications/plugins/wii_ec_anal/gfx/img_6x8_n_.c index 086bdd2de..15d403d28 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_6x8_n_.c +++ b/applications/plugins/wii_ec_anal/gfx/img_6x8_n_.c @@ -9,6 +9,4 @@ #include "images.h" -const image_t img_6x8_n = { 6, 8, false, 6, 0, { - 0x00, 0x07, 0xBF, 0xCF, 0x3C, 0xF3 -}}; +const image_t img_6x8_n = {6, 8, false, 6, 0, {0x00, 0x07, 0xBF, 0xCF, 0x3C, 0xF3}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_6x8_v_.c b/applications/plugins/wii_ec_anal/gfx/img_6x8_v_.c index c897aadff..1229701a1 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_6x8_v_.c +++ b/applications/plugins/wii_ec_anal/gfx/img_6x8_v_.c @@ -9,6 +9,4 @@ #include "images.h" -const image_t img_6x8_v = { 6, 8, false, 6, 0, { - 0x00, 0x08, 0x73, 0xCF, 0xF7, 0x8C -}}; +const image_t img_6x8_v = {6, 8, false, 6, 0, {0x00, 0x08, 0x73, 0xCF, 0xF7, 0x8C}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_RIP.c b/applications/plugins/wii_ec_anal/gfx/img_RIP.c index 55cb7bfc2..c20877ef0 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_RIP.c +++ b/applications/plugins/wii_ec_anal/gfx/img_RIP.c @@ -65,58 +65,66 @@ #include "images.h" -const image_t img_RIP = { 128, 64, true, 837, 0x06, { // orig:1024, comp:18.26% - 0x06, 0x20, 0xFF, 0xC0, 0x06, 0x0E, 0x00, 0x03, 0xD4, 0x06, 0x0E, 0x00, 0x2B, 0xC8, 0x01, 0xFC, - 0x1E, 0x1F, 0xF0, 0x00, 0xFE, 0x20, 0x8F, 0xE3, 0xF8, 0xFE, 0x3F, 0x80, 0x13, 0xD4, 0x01, 0xFC, - 0x0E, 0x0F, 0xF0, 0x00, 0xFE, 0x71, 0xCF, 0xE3, 0xF8, 0xFE, 0x3F, 0x80, 0x2B, 0xC0, 0x00, 0x0E, - 0x0A, 0x00, 0x38, 0x01, 0x87, 0x71, 0xD8, 0x77, 0x1C, 0x07, 0x71, 0xC0, 0x03, 0xC0, 0x03, 0x8E, - 0x0A, 0x0E, 0x28, 0x01, 0xC5, 0x51, 0x5C, 0x77, 0x1D, 0xC7, 0x71, 0x40, 0x03, 0xC0, 0x03, 0x8A, - 0x0A, 0x0E, 0x28, 0x01, 0x47, 0x51, 0x5C, 0x55, 0x15, 0xC5, 0x51, 0x40, 0x03, 0xC0, 0x02, 0x8A, - 0x0A, 0x0A, 0x28, 0x01, 0x40, 0x51, 0x54, 0x55, 0x15, 0x45, 0x51, 0x40, 0x03, 0xC0, 0x02, 0x8A, - 0x0A, 0x0A, 0x28, 0x01, 0x40, 0x51, 0x54, 0x55, 0x15, 0x45, 0x51, 0xC0, 0x03, 0xC0, 0x02, 0x8E, - 0x0A, 0x0A, 0x38, 0x01, 0x40, 0x51, 0x54, 0x75, 0x55, 0x47, 0x50, 0x00, 0x03, 0xC0, 0x02, 0xF8, - 0x0A, 0x0B, 0xE0, 0x01, 0x40, 0x71, 0xD7, 0xC5, 0x15, 0x7C, 0x50, 0x00, 0x03, 0xC0, 0x02, 0xF8, - 0x0A, 0x0B, 0xE0, 0x01, 0x40, 0x3F, 0x97, 0xC5, 0x15, 0x7C, 0x57, 0x80, 0x03, 0xC0, 0x02, 0x9C, - 0x0A, 0x0A, 0x00, 0x01, 0x40, 0x1B, 0x14, 0x75, 0x55, 0x4E, 0x57, 0xC0, 0x03, 0xC0, 0x02, 0x94, - 0x0A, 0x0A, 0x00, 0x01, 0x40, 0x0A, 0x14, 0x55, 0x15, 0x4A, 0x51, 0x40, 0x03, 0xC0, 0x02, 0x94, - 0x0A, 0x0A, 0x00, 0x01, 0x40, 0x0A, 0x14, 0x55, 0x15, 0x4A, 0x51, 0x40, 0x03, 0xC0, 0x02, 0x94, - 0x0A, 0x0A, 0x00, 0x01, 0xC7, 0x0A, 0x14, 0x55, 0x15, 0x4A, 0x71, 0x40, 0x03, 0xC0, 0x02, 0x94, - 0x0A, 0x0A, 0x00, 0x01, 0xC5, 0x0A, 0x1C, 0x77, 0x1D, 0x4A, 0x71, 0x40, 0x03, 0xC0, 0x02, 0x94, - 0x0A, 0x0A, 0x00, 0x01, 0x87, 0x0E, 0x1C, 0x77, 0x1D, 0x4A, 0x61, 0xC0, 0x03, 0xC0, 0x03, 0x9C, - 0xCE, 0xCE, 0xC0, 0x00, 0xFE, 0x0E, 0x0F, 0xE3, 0xF9, 0xCE, 0x3F, 0x80, 0x03, 0xC0, 0x03, 0x8E, - 0xDE, 0xDE, 0xC0, 0x00, 0xFE, 0x1F, 0x0F, 0xE3, 0xF9, 0xC7, 0x3F, 0x80, 0x03, 0xC0, 0x06, 0x0E, - 0x00, 0x03, 0xC0, 0x06, 0x0E, 0x00, 0x03, 0xC0, 0x06, 0x0A, 0x00, 0x01, 0x8C, 0x07, 0xF0, 0x03, - 0xC0, 0x06, 0x07, 0x00, 0x04, 0x00, 0x00, 0x02, 0x52, 0x18, 0x0C, 0x03, 0xC1, 0xD5, 0xC7, 0x57, - 0x77, 0x6D, 0xC4, 0x5D, 0x2B, 0x8E, 0xE0, 0x03, 0x5A, 0x20, 0x02, 0x03, 0xC0, 0x95, 0x04, 0x54, - 0x24, 0x55, 0x04, 0x55, 0xA1, 0x0A, 0x80, 0x01, 0x8C, 0x47, 0xC1, 0x03, 0xC0, 0x9D, 0x87, 0x27, - 0x26, 0x55, 0xC5, 0x55, 0x61, 0x0C, 0xC0, 0x00, 0x50, 0x88, 0x21, 0x03, 0xC0, 0x95, 0x01, 0x21, - 0x24, 0x44, 0x45, 0x55, 0x21, 0x0A, 0x80, 0x00, 0x20, 0x90, 0x11, 0x03, 0xC0, 0x95, 0xC7, 0x27, - 0x27, 0x45, 0xC6, 0xDD, 0x21, 0x0E, 0xE0, 0x00, 0x70, 0x91, 0x91, 0x03, 0xC0, 0x06, 0x0B, 0x00, - 0x88, 0x92, 0x51, 0x03, 0xC0, 0x06, 0x0A, 0x00, 0x01, 0x08, 0x92, 0x91, 0x03, 0xC0, 0x06, 0x0A, - 0x00, 0x01, 0x08, 0x92, 0x11, 0x03, 0xC1, 0xD5, 0xC7, 0x76, 0xDC, 0x45, 0xDD, 0x5D, 0x5C, 0x57, - 0x50, 0x00, 0x87, 0x11, 0xE2, 0x03, 0xC0, 0x95, 0x04, 0x55, 0x50, 0x44, 0x89, 0x55, 0x48, 0x55, - 0x50, 0x00, 0x80, 0x88, 0x03, 0x03, 0xC0, 0x9D, 0x87, 0x75, 0x58, 0x54, 0x89, 0xD5, 0x48, 0x25, - 0x50, 0x00, 0x40, 0x7C, 0x04, 0x83, 0xC0, 0x95, 0x01, 0x54, 0x50, 0x54, 0x89, 0x55, 0x48, 0x25, - 0x50, 0x00, 0x40, 0x07, 0xF8, 0x43, 0xC0, 0x95, 0xC7, 0x54, 0x5C, 0x6D, 0xC9, 0x5D, 0xC8, 0x27, - 0x70, 0x00, 0x30, 0x00, 0x00, 0x43, 0xC0, 0x06, 0x0B, 0x00, 0x0F, 0xFF, 0xFF, 0x83, 0xC0, 0x06, - 0x0E, 0x00, 0x03, 0xC0, 0x06, 0x0E, 0x00, 0x03, 0xC0, 0x00, 0x07, 0xC7, 0xF1, 0xFC, 0x7F, 0x00, - 0x03, 0xF8, 0xFE, 0x3F, 0x8F, 0xE0, 0x00, 0x03, 0xC0, 0x00, 0x07, 0xC7, 0xF1, 0xFC, 0x7F, 0x00, - 0x03, 0xF8, 0xFE, 0x3F, 0x8F, 0xE0, 0x00, 0x03, 0xC0, 0x00, 0x05, 0x4E, 0x3B, 0x8E, 0xE3, 0x80, - 0x07, 0x1D, 0xC7, 0x71, 0xDC, 0x70, 0x00, 0x03, 0xC0, 0x00, 0x01, 0x4E, 0x3A, 0x8E, 0xE3, 0x80, - 0x05, 0x15, 0xC7, 0x51, 0x54, 0x50, 0x00, 0x03, 0xC0, 0x00, 0x01, 0x4A, 0x2B, 0x8A, 0xA2, 0x80, - 0x07, 0x15, 0x45, 0x71, 0x5C, 0x50, 0x00, 0x03, 0xC0, 0x00, 0x01, 0x4A, 0x28, 0x0A, 0xA2, 0x80, - 0x00, 0x15, 0x45, 0x01, 0x40, 0x50, 0x00, 0x03, 0xC0, 0x00, 0x01, 0x4A, 0x28, 0x0A, 0xA6, 0x80, - 0x00, 0x15, 0x4D, 0x01, 0x40, 0x50, 0x00, 0x03, 0xC0, 0x00, 0x01, 0x4E, 0x28, 0x0E, 0xA6, 0x80, - 0x00, 0x1D, 0x4D, 0x01, 0xC0, 0x70, 0x00, 0x03, 0xC0, 0x00, 0x01, 0xC3, 0xE8, 0x0E, 0xAA, 0x9F, - 0xE1, 0xF9, 0x55, 0x1F, 0x87, 0xE0, 0x00, 0x03, 0xC0, 0x00, 0x01, 0xC3, 0xE8, 0x38, 0xAA, 0x90, - 0x23, 0xF1, 0x55, 0x3F, 0x0F, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x01, 0x40, 0x28, 0x38, 0xB2, 0x9F, - 0xE7, 0x01, 0x65, 0x70, 0x1C, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x01, 0x40, 0x28, 0x28, 0xB2, 0x80, - 0x05, 0x01, 0x65, 0x50, 0x14, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x01, 0x40, 0x28, 0x28, 0xA2, 0x80, - 0x05, 0x01, 0x45, 0x50, 0x14, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x01, 0x40, 0x28, 0x28, 0xA2, 0x80, - 0x05, 0x01, 0x45, 0x50, 0x14, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x01, 0x40, 0x38, 0x28, 0xE3, 0x80, - 0x05, 0x01, 0xC7, 0x50, 0x14, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x01, 0x40, 0x38, 0x28, 0xE3, 0x80, - 0x05, 0x0D, 0xC7, 0x50, 0xD4, 0x30, 0x00, 0x03, 0xD4, 0x00, 0x07, 0xF3, 0xF0, 0x38, 0x7F, 0x00, - 0x07, 0xFC, 0xFE, 0x7F, 0xDF, 0xF0, 0x00, 0x2B, 0xC8, 0x00, 0x0F, 0xFB, 0xF0, 0x38, 0x7F, 0x00, - 0x07, 0xFC, 0xFE, 0x7F, 0xDF, 0xF0, 0x00, 0x13, 0xD4, 0x06, 0x0E, 0x00, 0x2B, 0xC0, 0x06, 0x0E, - 0x00, 0x03, 0x06, 0x20, 0xFF -}}; +const image_t img_RIP = { + 128, + 64, + true, + 837, + 0x06, + {// orig:1024, comp:18.26% + 0x06, 0x20, 0xFF, 0xC0, 0x06, 0x0E, 0x00, 0x03, 0xD4, 0x06, 0x0E, 0x00, 0x2B, 0xC8, 0x01, + 0xFC, 0x1E, 0x1F, 0xF0, 0x00, 0xFE, 0x20, 0x8F, 0xE3, 0xF8, 0xFE, 0x3F, 0x80, 0x13, 0xD4, + 0x01, 0xFC, 0x0E, 0x0F, 0xF0, 0x00, 0xFE, 0x71, 0xCF, 0xE3, 0xF8, 0xFE, 0x3F, 0x80, 0x2B, + 0xC0, 0x00, 0x0E, 0x0A, 0x00, 0x38, 0x01, 0x87, 0x71, 0xD8, 0x77, 0x1C, 0x07, 0x71, 0xC0, + 0x03, 0xC0, 0x03, 0x8E, 0x0A, 0x0E, 0x28, 0x01, 0xC5, 0x51, 0x5C, 0x77, 0x1D, 0xC7, 0x71, + 0x40, 0x03, 0xC0, 0x03, 0x8A, 0x0A, 0x0E, 0x28, 0x01, 0x47, 0x51, 0x5C, 0x55, 0x15, 0xC5, + 0x51, 0x40, 0x03, 0xC0, 0x02, 0x8A, 0x0A, 0x0A, 0x28, 0x01, 0x40, 0x51, 0x54, 0x55, 0x15, + 0x45, 0x51, 0x40, 0x03, 0xC0, 0x02, 0x8A, 0x0A, 0x0A, 0x28, 0x01, 0x40, 0x51, 0x54, 0x55, + 0x15, 0x45, 0x51, 0xC0, 0x03, 0xC0, 0x02, 0x8E, 0x0A, 0x0A, 0x38, 0x01, 0x40, 0x51, 0x54, + 0x75, 0x55, 0x47, 0x50, 0x00, 0x03, 0xC0, 0x02, 0xF8, 0x0A, 0x0B, 0xE0, 0x01, 0x40, 0x71, + 0xD7, 0xC5, 0x15, 0x7C, 0x50, 0x00, 0x03, 0xC0, 0x02, 0xF8, 0x0A, 0x0B, 0xE0, 0x01, 0x40, + 0x3F, 0x97, 0xC5, 0x15, 0x7C, 0x57, 0x80, 0x03, 0xC0, 0x02, 0x9C, 0x0A, 0x0A, 0x00, 0x01, + 0x40, 0x1B, 0x14, 0x75, 0x55, 0x4E, 0x57, 0xC0, 0x03, 0xC0, 0x02, 0x94, 0x0A, 0x0A, 0x00, + 0x01, 0x40, 0x0A, 0x14, 0x55, 0x15, 0x4A, 0x51, 0x40, 0x03, 0xC0, 0x02, 0x94, 0x0A, 0x0A, + 0x00, 0x01, 0x40, 0x0A, 0x14, 0x55, 0x15, 0x4A, 0x51, 0x40, 0x03, 0xC0, 0x02, 0x94, 0x0A, + 0x0A, 0x00, 0x01, 0xC7, 0x0A, 0x14, 0x55, 0x15, 0x4A, 0x71, 0x40, 0x03, 0xC0, 0x02, 0x94, + 0x0A, 0x0A, 0x00, 0x01, 0xC5, 0x0A, 0x1C, 0x77, 0x1D, 0x4A, 0x71, 0x40, 0x03, 0xC0, 0x02, + 0x94, 0x0A, 0x0A, 0x00, 0x01, 0x87, 0x0E, 0x1C, 0x77, 0x1D, 0x4A, 0x61, 0xC0, 0x03, 0xC0, + 0x03, 0x9C, 0xCE, 0xCE, 0xC0, 0x00, 0xFE, 0x0E, 0x0F, 0xE3, 0xF9, 0xCE, 0x3F, 0x80, 0x03, + 0xC0, 0x03, 0x8E, 0xDE, 0xDE, 0xC0, 0x00, 0xFE, 0x1F, 0x0F, 0xE3, 0xF9, 0xC7, 0x3F, 0x80, + 0x03, 0xC0, 0x06, 0x0E, 0x00, 0x03, 0xC0, 0x06, 0x0E, 0x00, 0x03, 0xC0, 0x06, 0x0A, 0x00, + 0x01, 0x8C, 0x07, 0xF0, 0x03, 0xC0, 0x06, 0x07, 0x00, 0x04, 0x00, 0x00, 0x02, 0x52, 0x18, + 0x0C, 0x03, 0xC1, 0xD5, 0xC7, 0x57, 0x77, 0x6D, 0xC4, 0x5D, 0x2B, 0x8E, 0xE0, 0x03, 0x5A, + 0x20, 0x02, 0x03, 0xC0, 0x95, 0x04, 0x54, 0x24, 0x55, 0x04, 0x55, 0xA1, 0x0A, 0x80, 0x01, + 0x8C, 0x47, 0xC1, 0x03, 0xC0, 0x9D, 0x87, 0x27, 0x26, 0x55, 0xC5, 0x55, 0x61, 0x0C, 0xC0, + 0x00, 0x50, 0x88, 0x21, 0x03, 0xC0, 0x95, 0x01, 0x21, 0x24, 0x44, 0x45, 0x55, 0x21, 0x0A, + 0x80, 0x00, 0x20, 0x90, 0x11, 0x03, 0xC0, 0x95, 0xC7, 0x27, 0x27, 0x45, 0xC6, 0xDD, 0x21, + 0x0E, 0xE0, 0x00, 0x70, 0x91, 0x91, 0x03, 0xC0, 0x06, 0x0B, 0x00, 0x88, 0x92, 0x51, 0x03, + 0xC0, 0x06, 0x0A, 0x00, 0x01, 0x08, 0x92, 0x91, 0x03, 0xC0, 0x06, 0x0A, 0x00, 0x01, 0x08, + 0x92, 0x11, 0x03, 0xC1, 0xD5, 0xC7, 0x76, 0xDC, 0x45, 0xDD, 0x5D, 0x5C, 0x57, 0x50, 0x00, + 0x87, 0x11, 0xE2, 0x03, 0xC0, 0x95, 0x04, 0x55, 0x50, 0x44, 0x89, 0x55, 0x48, 0x55, 0x50, + 0x00, 0x80, 0x88, 0x03, 0x03, 0xC0, 0x9D, 0x87, 0x75, 0x58, 0x54, 0x89, 0xD5, 0x48, 0x25, + 0x50, 0x00, 0x40, 0x7C, 0x04, 0x83, 0xC0, 0x95, 0x01, 0x54, 0x50, 0x54, 0x89, 0x55, 0x48, + 0x25, 0x50, 0x00, 0x40, 0x07, 0xF8, 0x43, 0xC0, 0x95, 0xC7, 0x54, 0x5C, 0x6D, 0xC9, 0x5D, + 0xC8, 0x27, 0x70, 0x00, 0x30, 0x00, 0x00, 0x43, 0xC0, 0x06, 0x0B, 0x00, 0x0F, 0xFF, 0xFF, + 0x83, 0xC0, 0x06, 0x0E, 0x00, 0x03, 0xC0, 0x06, 0x0E, 0x00, 0x03, 0xC0, 0x00, 0x07, 0xC7, + 0xF1, 0xFC, 0x7F, 0x00, 0x03, 0xF8, 0xFE, 0x3F, 0x8F, 0xE0, 0x00, 0x03, 0xC0, 0x00, 0x07, + 0xC7, 0xF1, 0xFC, 0x7F, 0x00, 0x03, 0xF8, 0xFE, 0x3F, 0x8F, 0xE0, 0x00, 0x03, 0xC0, 0x00, + 0x05, 0x4E, 0x3B, 0x8E, 0xE3, 0x80, 0x07, 0x1D, 0xC7, 0x71, 0xDC, 0x70, 0x00, 0x03, 0xC0, + 0x00, 0x01, 0x4E, 0x3A, 0x8E, 0xE3, 0x80, 0x05, 0x15, 0xC7, 0x51, 0x54, 0x50, 0x00, 0x03, + 0xC0, 0x00, 0x01, 0x4A, 0x2B, 0x8A, 0xA2, 0x80, 0x07, 0x15, 0x45, 0x71, 0x5C, 0x50, 0x00, + 0x03, 0xC0, 0x00, 0x01, 0x4A, 0x28, 0x0A, 0xA2, 0x80, 0x00, 0x15, 0x45, 0x01, 0x40, 0x50, + 0x00, 0x03, 0xC0, 0x00, 0x01, 0x4A, 0x28, 0x0A, 0xA6, 0x80, 0x00, 0x15, 0x4D, 0x01, 0x40, + 0x50, 0x00, 0x03, 0xC0, 0x00, 0x01, 0x4E, 0x28, 0x0E, 0xA6, 0x80, 0x00, 0x1D, 0x4D, 0x01, + 0xC0, 0x70, 0x00, 0x03, 0xC0, 0x00, 0x01, 0xC3, 0xE8, 0x0E, 0xAA, 0x9F, 0xE1, 0xF9, 0x55, + 0x1F, 0x87, 0xE0, 0x00, 0x03, 0xC0, 0x00, 0x01, 0xC3, 0xE8, 0x38, 0xAA, 0x90, 0x23, 0xF1, + 0x55, 0x3F, 0x0F, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x01, 0x40, 0x28, 0x38, 0xB2, 0x9F, 0xE7, + 0x01, 0x65, 0x70, 0x1C, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x01, 0x40, 0x28, 0x28, 0xB2, 0x80, + 0x05, 0x01, 0x65, 0x50, 0x14, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x01, 0x40, 0x28, 0x28, 0xA2, + 0x80, 0x05, 0x01, 0x45, 0x50, 0x14, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x01, 0x40, 0x28, 0x28, + 0xA2, 0x80, 0x05, 0x01, 0x45, 0x50, 0x14, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x01, 0x40, 0x38, + 0x28, 0xE3, 0x80, 0x05, 0x01, 0xC7, 0x50, 0x14, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x01, 0x40, + 0x38, 0x28, 0xE3, 0x80, 0x05, 0x0D, 0xC7, 0x50, 0xD4, 0x30, 0x00, 0x03, 0xD4, 0x00, 0x07, + 0xF3, 0xF0, 0x38, 0x7F, 0x00, 0x07, 0xFC, 0xFE, 0x7F, 0xDF, 0xF0, 0x00, 0x2B, 0xC8, 0x00, + 0x0F, 0xFB, 0xF0, 0x38, 0x7F, 0x00, 0x07, 0xFC, 0xFE, 0x7F, 0xDF, 0xF0, 0x00, 0x13, 0xD4, + 0x06, 0x0E, 0x00, 0x2B, 0xC0, 0x06, 0x0E, 0x00, 0x03, 0x06, 0x20, 0xFF}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_cc_Cable.c b/applications/plugins/wii_ec_anal/gfx/img_cc_Cable.c index 2fc6b5f23..f4ac26173 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_cc_Cable.c +++ b/applications/plugins/wii_ec_anal/gfx/img_cc_Cable.c @@ -12,6 +12,14 @@ #include "images.h" -const image_t img_cc_Cable = { 4, 11, true, 4, 0x00, { // orig:6, comp:33.33% - 0x00, 0x05, 0xDB, 0xD0 -}}; +const image_t img_cc_Cable = { + 4, + 11, + true, + 4, + 0x00, + {// orig:6, comp:33.33% + 0x00, + 0x05, + 0xDB, + 0xD0}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_cc_Joy.c b/applications/plugins/wii_ec_anal/gfx/img_cc_Joy.c index dd189cb7e..5054103b3 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_cc_Joy.c +++ b/applications/plugins/wii_ec_anal/gfx/img_cc_Joy.c @@ -18,8 +18,8 @@ #include "images.h" -const image_t img_cc_Joy = { 17, 17, false, 37, 0, { - 0x00, 0x80, 0x01, 0xF0, 0x0F, 0xDF, 0x87, 0x01, 0xC3, 0x00, 0x61, 0x00, 0x11, 0x80, 0x0C, 0xC0, - 0x06, 0xC0, 0x01, 0xB0, 0x01, 0x98, 0x00, 0xC4, 0x00, 0x43, 0x00, 0x61, 0xC0, 0x70, 0xFD, 0xF8, - 0x07, 0xC0, 0x00, 0x80, 0x00 -}}; +const image_t img_cc_Joy = {17, 17, false, 37, 0, {0x00, 0x80, 0x01, 0xF0, 0x0F, 0xDF, 0x87, 0x01, + 0xC3, 0x00, 0x61, 0x00, 0x11, 0x80, 0x0C, 0xC0, + 0x06, 0xC0, 0x01, 0xB0, 0x01, 0x98, 0x00, 0xC4, + 0x00, 0x43, 0x00, 0x61, 0xC0, 0x70, 0xFD, 0xF8, + 0x07, 0xC0, 0x00, 0x80, 0x00}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_cc_Main.c b/applications/plugins/wii_ec_anal/gfx/img_cc_Main.c index 8e7bd5ed9..b29a9ab57 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_cc_Main.c +++ b/applications/plugins/wii_ec_anal/gfx/img_cc_Main.c @@ -54,39 +54,47 @@ #include "images.h" -const image_t img_cc_Main = { 116, 53, true, 542, 0x05, { // orig:769, comp:29.52% - 0x00, 0x00, 0x00, 0x7F, 0xC0, 0x05, 0x05, 0x00, 0x3F, 0xE0, 0x05, 0x04, 0x00, 0x01, 0xF8, 0x04, - 0x0F, 0x80, 0x00, 0x00, 0x1F, 0x02, 0x01, 0xF8, 0x05, 0x04, 0x00, 0x60, 0x00, 0x41, 0x04, 0x00, - 0x60, 0x02, 0x08, 0x20, 0x00, 0x60, 0x00, 0x00, 0x00, 0x08, 0x00, 0x07, 0xF0, 0x7F, 0xFF, 0xFF, - 0xE0, 0xFE, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x41, 0x04, 0x00, 0x60, 0x02, 0x08, - 0x20, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x50, 0x03, 0xFC, 0x10, 0x40, 0x06, 0x00, 0x20, 0x83, 0xFC, - 0x00, 0xA0, 0x00, 0x00, 0x09, 0x0F, 0xC0, 0x00, 0xF8, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x3F, 0x09, - 0x00, 0x00, 0x01, 0x1F, 0x05, 0x09, 0x00, 0x0F, 0x88, 0x00, 0x00, 0x20, 0x05, 0x0A, 0xFF, 0xF0, - 0x40, 0x00, 0x04, 0x78, 0x05, 0x09, 0x00, 0x01, 0xE2, 0x00, 0x00, 0x9C, 0x05, 0x0A, 0x00, 0x03, - 0x90, 0x00, 0x13, 0x05, 0x0B, 0x00, 0x0C, 0x80, 0x03, 0xE0, 0x05, 0x0B, 0x00, 0x7C, 0x00, 0x38, - 0x05, 0x05, 0x00, 0xC6, 0xD8, 0x05, 0x04, 0x00, 0x01, 0xC0, 0x07, 0x00, 0x1F, 0xF0, 0x00, 0x00, - 0x0D, 0x60, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x60, 0x01, 0xFF, 0x00, 0x00, 0x00, 0xD6, - 0xD8, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x60, 0x0C, 0x00, 0x18, 0x30, 0x00, 0x00, 0x0D, 0x6D, 0x80, - 0x00, 0x00, 0x31, 0x80, 0x03, 0x01, 0xC0, 0x01, 0x83, 0x00, 0x00, 0x00, 0x6C, 0xD8, 0x00, 0x00, - 0x06, 0x0C, 0x00, 0x38, 0x18, 0x00, 0x19, 0x30, 0x05, 0x07, 0x00, 0xCA, 0x60, 0x01, 0x81, 0x00, - 0x01, 0x93, 0x05, 0x07, 0x00, 0x0C, 0x46, 0x00, 0x0C, 0x30, 0x00, 0x19, 0x30, 0x05, 0x07, 0x00, - 0xCA, 0x60, 0x00, 0xC2, 0x00, 0xFF, 0x83, 0xFE, 0x05, 0x05, 0x00, 0x07, 0x06, 0x0C, 0x1C, 0x04, - 0x60, 0x0F, 0xF8, 0x3F, 0xE0, 0x05, 0x05, 0x00, 0xF8, 0x31, 0x83, 0xE0, 0x64, 0x00, 0xC0, 0x00, - 0x06, 0x00, 0x0F, 0x0F, 0x0F, 0x00, 0x18, 0xC1, 0xF0, 0x63, 0x02, 0x40, 0x0C, 0x00, 0x00, 0x60, - 0x01, 0x99, 0x99, 0x98, 0x03, 0x06, 0x0E, 0x0C, 0x98, 0x2C, 0x00, 0xCE, 0x00, 0xE6, 0x00, 0x10, - 0x90, 0x90, 0x80, 0x65, 0x30, 0x01, 0x94, 0xC3, 0x80, 0x0C, 0x00, 0x00, 0x60, 0x01, 0x09, 0x09, - 0x08, 0x06, 0x73, 0x00, 0x19, 0xCC, 0x18, 0x00, 0xC0, 0x00, 0x06, 0x00, 0x19, 0x99, 0x99, 0x80, - 0x61, 0x30, 0x01, 0x94, 0xC1, 0x80, 0x0F, 0xF8, 0x3F, 0xE0, 0x00, 0xF0, 0xF0, 0xF0, 0x03, 0x26, - 0x0E, 0x0C, 0x18, 0x18, 0x00, 0xFF, 0x83, 0xFE, 0x05, 0x05, 0x00, 0x18, 0xC1, 0xF0, 0x63, 0x01, - 0x80, 0x00, 0x19, 0x30, 0x05, 0x06, 0x00, 0xF8, 0x31, 0x83, 0xE0, 0x18, 0x00, 0x01, 0x93, 0x05, - 0x06, 0x00, 0x07, 0x06, 0x8C, 0x1C, 0x01, 0x80, 0x00, 0x19, 0x30, 0x05, 0x07, 0x00, 0xC8, 0x60, - 0x00, 0x18, 0x00, 0x01, 0x83, 0x05, 0x07, 0x00, 0x0C, 0xC6, 0x00, 0x01, 0x80, 0x00, 0x18, 0x30, - 0x05, 0x07, 0x00, 0xCA, 0x60, 0x00, 0x1C, 0x00, 0x01, 0xFF, 0x05, 0x07, 0x00, 0x06, 0x6C, 0x00, - 0x03, 0x40, 0x00, 0x1F, 0xF0, 0x05, 0x07, 0x00, 0x31, 0x80, 0x00, 0x24, 0x05, 0x0A, 0x00, 0x01, - 0xF0, 0x00, 0x02, 0x60, 0x05, 0x0A, 0x00, 0x0E, 0x00, 0x00, 0x62, 0x05, 0x0D, 0x00, 0x04, 0x20, - 0x05, 0x0D, 0x00, 0x43, 0x05, 0x0D, 0x00, 0x0C, 0x10, 0x05, 0x0D, 0x00, 0x81, 0x80, 0x05, 0x0C, - 0x00, 0x18, 0x0C, 0x05, 0x0C, 0x00, 0x03, 0x00, 0x60, 0x05, 0x0C, 0x00, 0x60, 0x03, 0x05, 0x0C, - 0x00, 0x0C, 0x00, 0x18, 0x05, 0x0B, 0x00, 0x01, 0x80, 0x00, 0xE0, 0x05, 0x0B, 0x00, 0x70, 0x00, - 0x03, 0x05, 0x0B, 0x00, 0x0C, 0x00, 0x00, 0x1C, 0x05, 0x0A, 0x00, 0x03, 0x80, 0x00, 0x00, 0x78, - 0x05, 0x09, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x00, 0x05, 0x0A, 0xFF, 0xF0, 0x00, 0x00 -}}; +const image_t img_cc_Main = { + 116, + 53, + true, + 542, + 0x05, + {// orig:769, comp:29.52% + 0x00, 0x00, 0x00, 0x7F, 0xC0, 0x05, 0x05, 0x00, 0x3F, 0xE0, 0x05, 0x04, 0x00, 0x01, 0xF8, + 0x04, 0x0F, 0x80, 0x00, 0x00, 0x1F, 0x02, 0x01, 0xF8, 0x05, 0x04, 0x00, 0x60, 0x00, 0x41, + 0x04, 0x00, 0x60, 0x02, 0x08, 0x20, 0x00, 0x60, 0x00, 0x00, 0x00, 0x08, 0x00, 0x07, 0xF0, + 0x7F, 0xFF, 0xFF, 0xE0, 0xFE, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x41, 0x04, + 0x00, 0x60, 0x02, 0x08, 0x20, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x50, 0x03, 0xFC, 0x10, 0x40, + 0x06, 0x00, 0x20, 0x83, 0xFC, 0x00, 0xA0, 0x00, 0x00, 0x09, 0x0F, 0xC0, 0x00, 0xF8, 0x00, + 0x00, 0x01, 0xF0, 0x00, 0x3F, 0x09, 0x00, 0x00, 0x01, 0x1F, 0x05, 0x09, 0x00, 0x0F, 0x88, + 0x00, 0x00, 0x20, 0x05, 0x0A, 0xFF, 0xF0, 0x40, 0x00, 0x04, 0x78, 0x05, 0x09, 0x00, 0x01, + 0xE2, 0x00, 0x00, 0x9C, 0x05, 0x0A, 0x00, 0x03, 0x90, 0x00, 0x13, 0x05, 0x0B, 0x00, 0x0C, + 0x80, 0x03, 0xE0, 0x05, 0x0B, 0x00, 0x7C, 0x00, 0x38, 0x05, 0x05, 0x00, 0xC6, 0xD8, 0x05, + 0x04, 0x00, 0x01, 0xC0, 0x07, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x0D, 0x60, 0x00, 0x00, 0x00, + 0x0E, 0x00, 0x0E, 0x00, 0x60, 0x01, 0xFF, 0x00, 0x00, 0x00, 0xD6, 0xD8, 0x00, 0x00, 0x01, + 0xF0, 0x00, 0x60, 0x0C, 0x00, 0x18, 0x30, 0x00, 0x00, 0x0D, 0x6D, 0x80, 0x00, 0x00, 0x31, + 0x80, 0x03, 0x01, 0xC0, 0x01, 0x83, 0x00, 0x00, 0x00, 0x6C, 0xD8, 0x00, 0x00, 0x06, 0x0C, + 0x00, 0x38, 0x18, 0x00, 0x19, 0x30, 0x05, 0x07, 0x00, 0xCA, 0x60, 0x01, 0x81, 0x00, 0x01, + 0x93, 0x05, 0x07, 0x00, 0x0C, 0x46, 0x00, 0x0C, 0x30, 0x00, 0x19, 0x30, 0x05, 0x07, 0x00, + 0xCA, 0x60, 0x00, 0xC2, 0x00, 0xFF, 0x83, 0xFE, 0x05, 0x05, 0x00, 0x07, 0x06, 0x0C, 0x1C, + 0x04, 0x60, 0x0F, 0xF8, 0x3F, 0xE0, 0x05, 0x05, 0x00, 0xF8, 0x31, 0x83, 0xE0, 0x64, 0x00, + 0xC0, 0x00, 0x06, 0x00, 0x0F, 0x0F, 0x0F, 0x00, 0x18, 0xC1, 0xF0, 0x63, 0x02, 0x40, 0x0C, + 0x00, 0x00, 0x60, 0x01, 0x99, 0x99, 0x98, 0x03, 0x06, 0x0E, 0x0C, 0x98, 0x2C, 0x00, 0xCE, + 0x00, 0xE6, 0x00, 0x10, 0x90, 0x90, 0x80, 0x65, 0x30, 0x01, 0x94, 0xC3, 0x80, 0x0C, 0x00, + 0x00, 0x60, 0x01, 0x09, 0x09, 0x08, 0x06, 0x73, 0x00, 0x19, 0xCC, 0x18, 0x00, 0xC0, 0x00, + 0x06, 0x00, 0x19, 0x99, 0x99, 0x80, 0x61, 0x30, 0x01, 0x94, 0xC1, 0x80, 0x0F, 0xF8, 0x3F, + 0xE0, 0x00, 0xF0, 0xF0, 0xF0, 0x03, 0x26, 0x0E, 0x0C, 0x18, 0x18, 0x00, 0xFF, 0x83, 0xFE, + 0x05, 0x05, 0x00, 0x18, 0xC1, 0xF0, 0x63, 0x01, 0x80, 0x00, 0x19, 0x30, 0x05, 0x06, 0x00, + 0xF8, 0x31, 0x83, 0xE0, 0x18, 0x00, 0x01, 0x93, 0x05, 0x06, 0x00, 0x07, 0x06, 0x8C, 0x1C, + 0x01, 0x80, 0x00, 0x19, 0x30, 0x05, 0x07, 0x00, 0xC8, 0x60, 0x00, 0x18, 0x00, 0x01, 0x83, + 0x05, 0x07, 0x00, 0x0C, 0xC6, 0x00, 0x01, 0x80, 0x00, 0x18, 0x30, 0x05, 0x07, 0x00, 0xCA, + 0x60, 0x00, 0x1C, 0x00, 0x01, 0xFF, 0x05, 0x07, 0x00, 0x06, 0x6C, 0x00, 0x03, 0x40, 0x00, + 0x1F, 0xF0, 0x05, 0x07, 0x00, 0x31, 0x80, 0x00, 0x24, 0x05, 0x0A, 0x00, 0x01, 0xF0, 0x00, + 0x02, 0x60, 0x05, 0x0A, 0x00, 0x0E, 0x00, 0x00, 0x62, 0x05, 0x0D, 0x00, 0x04, 0x20, 0x05, + 0x0D, 0x00, 0x43, 0x05, 0x0D, 0x00, 0x0C, 0x10, 0x05, 0x0D, 0x00, 0x81, 0x80, 0x05, 0x0C, + 0x00, 0x18, 0x0C, 0x05, 0x0C, 0x00, 0x03, 0x00, 0x60, 0x05, 0x0C, 0x00, 0x60, 0x03, 0x05, + 0x0C, 0x00, 0x0C, 0x00, 0x18, 0x05, 0x0B, 0x00, 0x01, 0x80, 0x00, 0xE0, 0x05, 0x0B, 0x00, + 0x70, 0x00, 0x03, 0x05, 0x0B, 0x00, 0x0C, 0x00, 0x00, 0x1C, 0x05, 0x0A, 0x00, 0x03, 0x80, + 0x00, 0x00, 0x78, 0x05, 0x09, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x00, 0x05, 0x0A, 0xFF, 0xF0, + 0x00, 0x00}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_cc_btn_A1.c b/applications/plugins/wii_ec_anal/gfx/img_cc_btn_A1.c index 4d54cbf22..0889b2a08 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_cc_btn_A1.c +++ b/applications/plugins/wii_ec_anal/gfx/img_cc_btn_A1.c @@ -8,6 +8,4 @@ #include "images.h" -const image_t img_cc_btn_A1 = { 7, 7, false, 7, 0, { - 0xFF, 0xDF, 0x5E, 0x3D, 0x7F, 0xFF, 0x80 -}}; +const image_t img_cc_btn_A1 = {7, 7, false, 7, 0, {0xFF, 0xDF, 0x5E, 0x3D, 0x7F, 0xFF, 0x80}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_cc_btn_B1.c b/applications/plugins/wii_ec_anal/gfx/img_cc_btn_B1.c index 89d357282..bbf5fba1a 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_cc_btn_B1.c +++ b/applications/plugins/wii_ec_anal/gfx/img_cc_btn_B1.c @@ -8,6 +8,4 @@ #include "images.h" -const image_t img_cc_btn_B1 = { 7, 7, false, 7, 0, { - 0xFF, 0xBF, 0x7E, 0x7D, 0x7C, 0xFF, 0x80 -}}; +const image_t img_cc_btn_B1 = {7, 7, false, 7, 0, {0xFF, 0xBF, 0x7E, 0x7D, 0x7C, 0xFF, 0x80}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_cc_btn_X1.c b/applications/plugins/wii_ec_anal/gfx/img_cc_btn_X1.c index a1e7f2876..2352ba695 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_cc_btn_X1.c +++ b/applications/plugins/wii_ec_anal/gfx/img_cc_btn_X1.c @@ -8,6 +8,4 @@ #include "images.h" -const image_t img_cc_btn_X1 = { 7, 7, false, 7, 0, { - 0xFF, 0xFF, 0x5F, 0x7D, 0x7F, 0xFF, 0x80 -}}; +const image_t img_cc_btn_X1 = {7, 7, false, 7, 0, {0xFF, 0xFF, 0x5F, 0x7D, 0x7F, 0xFF, 0x80}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_cc_btn_Y1.c b/applications/plugins/wii_ec_anal/gfx/img_cc_btn_Y1.c index 01f66b4c7..d7192e3e7 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_cc_btn_Y1.c +++ b/applications/plugins/wii_ec_anal/gfx/img_cc_btn_Y1.c @@ -8,6 +8,4 @@ #include "images.h" -const image_t img_cc_btn_Y1 = { 7, 7, false, 7, 0, { - 0xFF, 0xFF, 0x5E, 0x3F, 0x7D, 0xFF, 0x80 -}}; +const image_t img_cc_btn_Y1 = {7, 7, false, 7, 0, {0xFF, 0xFF, 0x5E, 0x3F, 0x7D, 0xFF, 0x80}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_cc_pad_LR1.c b/applications/plugins/wii_ec_anal/gfx/img_cc_pad_LR1.c index 698fcfdd6..300ed5eee 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_cc_pad_LR1.c +++ b/applications/plugins/wii_ec_anal/gfx/img_cc_pad_LR1.c @@ -6,6 +6,4 @@ #include "images.h" -const image_t img_cc_pad_LR1 = { 7, 5, false, 5, 0, { - 0xFF, 0xFF, 0x1F, 0xFF, 0xE0 -}}; +const image_t img_cc_pad_LR1 = {7, 5, false, 5, 0, {0xFF, 0xFF, 0x1F, 0xFF, 0xE0}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_cc_pad_UD1.c b/applications/plugins/wii_ec_anal/gfx/img_cc_pad_UD1.c index b7d104ee4..feb32d283 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_cc_pad_UD1.c +++ b/applications/plugins/wii_ec_anal/gfx/img_cc_pad_UD1.c @@ -8,6 +8,4 @@ #include "images.h" -const image_t img_cc_pad_UD1 = { 5, 7, false, 5, 0, { - 0xFF, 0xF7, 0xBD, 0xFF, 0xE0 -}}; +const image_t img_cc_pad_UD1 = {5, 7, false, 5, 0, {0xFF, 0xF7, 0xBD, 0xFF, 0xE0}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_cc_trg_L1.c b/applications/plugins/wii_ec_anal/gfx/img_cc_trg_L1.c index cf4d7159b..c70e35334 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_cc_trg_L1.c +++ b/applications/plugins/wii_ec_anal/gfx/img_cc_trg_L1.c @@ -7,6 +7,10 @@ #include "images.h" -const image_t img_cc_trg_L1 = { 17, 6, false, 13, 0, { - 0x1F, 0xC9, 0x34, 0x92, 0x64, 0x92, 0x54, 0x92, 0x44, 0x93, 0xFC, 0xFE, 0x00 -}}; +const image_t img_cc_trg_L1 = { + 17, + 6, + false, + 13, + 0, + {0x1F, 0xC9, 0x34, 0x92, 0x64, 0x92, 0x54, 0x92, 0x44, 0x93, 0xFC, 0xFE, 0x00}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_cc_trg_L2.c b/applications/plugins/wii_ec_anal/gfx/img_cc_trg_L2.c index 9e61a64cc..47561ab98 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_cc_trg_L2.c +++ b/applications/plugins/wii_ec_anal/gfx/img_cc_trg_L2.c @@ -7,6 +7,22 @@ #include "images.h" -const image_t img_cc_trg_L2 = { 17, 6, true, 12, 0x01, { // orig:13, comp:7.69% - 0x1F, 0xD5, 0x35, 0x55, 0x75, 0x01, 0x04, 0x55, 0x57, 0xFD, 0x7E, 0x00 -}}; +const image_t img_cc_trg_L2 = { + 17, + 6, + true, + 12, + 0x01, + {// orig:13, comp:7.69% + 0x1F, + 0xD5, + 0x35, + 0x55, + 0x75, + 0x01, + 0x04, + 0x55, + 0x57, + 0xFD, + 0x7E, + 0x00}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_cc_trg_L3.c b/applications/plugins/wii_ec_anal/gfx/img_cc_trg_L3.c index 1b06de5ee..0b51bed35 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_cc_trg_L3.c +++ b/applications/plugins/wii_ec_anal/gfx/img_cc_trg_L3.c @@ -7,6 +7,10 @@ #include "images.h" -const image_t img_cc_trg_L3 = { 17, 6, false, 13, 0, { - 0x1F, 0xB6, 0xBB, 0x6D, 0xBB, 0x6D, 0xBB, 0x6D, 0xBB, 0x6F, 0xFB, 0x7E, 0x00 -}}; +const image_t img_cc_trg_L3 = { + 17, + 6, + false, + 13, + 0, + {0x1F, 0xB6, 0xBB, 0x6D, 0xBB, 0x6D, 0xBB, 0x6D, 0xBB, 0x6F, 0xFB, 0x7E, 0x00}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_cc_trg_L4.c b/applications/plugins/wii_ec_anal/gfx/img_cc_trg_L4.c index 12f877ab1..062caca77 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_cc_trg_L4.c +++ b/applications/plugins/wii_ec_anal/gfx/img_cc_trg_L4.c @@ -7,6 +7,18 @@ #include "images.h" -const image_t img_cc_trg_L4 = { 17, 6, true, 8, 0x01, { // orig:13, comp:38.46% - 0x1F, 0xFF, 0xBF, 0x01, 0x08, 0xFF, 0xFE, 0x00 -}}; +const image_t img_cc_trg_L4 = { + 17, + 6, + true, + 8, + 0x01, + {// orig:13, comp:38.46% + 0x1F, + 0xFF, + 0xBF, + 0x01, + 0x08, + 0xFF, + 0xFE, + 0x00}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_cc_trg_R1.c b/applications/plugins/wii_ec_anal/gfx/img_cc_trg_R1.c index a196c0fe1..6f08886d3 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_cc_trg_R1.c +++ b/applications/plugins/wii_ec_anal/gfx/img_cc_trg_R1.c @@ -7,6 +7,10 @@ #include "images.h" -const image_t img_cc_trg_R1 = { 17, 6, false, 13, 0, { - 0x49, 0xFC, 0x49, 0x25, 0x92, 0x49, 0x24, 0x92, 0x5F, 0xE4, 0x90, 0x0F, 0xE4 -}}; +const image_t img_cc_trg_R1 = { + 17, + 6, + false, + 13, + 0, + {0x49, 0xFC, 0x49, 0x25, 0x92, 0x49, 0x24, 0x92, 0x5F, 0xE4, 0x90, 0x0F, 0xE4}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_cc_trg_R2.c b/applications/plugins/wii_ec_anal/gfx/img_cc_trg_R2.c index ea5458f39..d85e45761 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_cc_trg_R2.c +++ b/applications/plugins/wii_ec_anal/gfx/img_cc_trg_R2.c @@ -7,6 +7,10 @@ #include "images.h" -const image_t img_cc_trg_R2 = { 17, 6, false, 13, 0, { - 0x55, 0xFC, 0x55, 0x55, 0x95, 0x55, 0x75, 0x55, 0x5F, 0xF5, 0x50, 0x0F, 0xD4 -}}; +const image_t img_cc_trg_R2 = { + 17, + 6, + false, + 13, + 0, + {0x55, 0xFC, 0x55, 0x55, 0x95, 0x55, 0x75, 0x55, 0x5F, 0xF5, 0x50, 0x0F, 0xD4}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_cc_trg_R3.c b/applications/plugins/wii_ec_anal/gfx/img_cc_trg_R3.c index 94cf02bf0..082d160e2 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_cc_trg_R3.c +++ b/applications/plugins/wii_ec_anal/gfx/img_cc_trg_R3.c @@ -7,6 +7,10 @@ #include "images.h" -const image_t img_cc_trg_R3 = { 17, 6, false, 13, 0, { - 0xB6, 0xFC, 0x36, 0xDB, 0xAD, 0xB6, 0xFB, 0x6D, 0xBF, 0xFB, 0x68, 0x0F, 0xD8 -}}; +const image_t img_cc_trg_R3 = { + 17, + 6, + false, + 13, + 0, + {0xB6, 0xFC, 0x36, 0xDB, 0xAD, 0xB6, 0xFB, 0x6D, 0xBF, 0xFB, 0x68, 0x0F, 0xD8}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_cc_trg_R4.c b/applications/plugins/wii_ec_anal/gfx/img_cc_trg_R4.c index c90fbe20b..0395058b8 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_cc_trg_R4.c +++ b/applications/plugins/wii_ec_anal/gfx/img_cc_trg_R4.c @@ -7,6 +7,21 @@ #include "images.h" -const image_t img_cc_trg_R4 = { 17, 6, true, 11, 0x00, { // orig:13, comp:15.38% - 0xFF, 0xFC, 0x7F, 0xFF, 0xBF, 0x00, 0x05, 0xFF, 0xF8, 0x0F, 0xFC -}}; +const image_t img_cc_trg_R4 = { + 17, + 6, + true, + 11, + 0x00, + {// orig:13, comp:15.38% + 0xFF, + 0xFC, + 0x7F, + 0xFF, + 0xBF, + 0x00, + 0x05, + 0xFF, + 0xF8, + 0x0F, + 0xFC}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_csLogo_FULL.c b/applications/plugins/wii_ec_anal/gfx/img_csLogo_FULL.c index 97f09ac17..a8c030fa2 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_csLogo_FULL.c +++ b/applications/plugins/wii_ec_anal/gfx/img_csLogo_FULL.c @@ -41,41 +41,49 @@ #include "images.h" -const image_t img_csLogo_FULL = { 124, 40, true, 571, 0x0B, { // orig:620, comp:7.90% - 0x3F, 0xFF, 0xFE, 0x10, 0x43, 0xF8, 0x7F, 0x0F, 0xE1, 0xFC, 0x0B, 0x05, 0x00, 0x03, 0xFF, 0xFF, - 0xE3, 0x8E, 0x3F, 0x87, 0xF0, 0xFE, 0x1F, 0xC0, 0x0B, 0x05, 0x00, 0xFC, 0x00, 0x07, 0x38, 0xE6, - 0x1C, 0xE3, 0x80, 0x73, 0x8E, 0x03, 0xBB, 0x80, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x52, 0x8A, 0x71, - 0xCE, 0x39, 0xC7, 0x38, 0xA0, 0x22, 0x10, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x05, 0x28, 0xA7, 0x14, - 0xA2, 0x9C, 0x52, 0x8A, 0x03, 0x39, 0x00, 0x00, 0x00, 0x0C, 0xC0, 0x00, 0x52, 0x8A, 0x51, 0x4A, - 0x29, 0x45, 0x28, 0xA0, 0x20, 0x90, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x07, 0x28, 0xA5, 0x14, 0xA2, - 0x94, 0x52, 0x8E, 0x03, 0xB9, 0x40, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x02, 0x8A, 0x51, 0xCA, 0xA9, - 0x47, 0x28, 0x0B, 0x06, 0x00, 0xCC, 0x00, 0x00, 0x38, 0xE5, 0xF0, 0xA2, 0x97, 0xC2, 0x80, 0x06, - 0xEE, 0x80, 0x00, 0x00, 0x0E, 0xC3, 0x00, 0x01, 0xFC, 0x5F, 0x0A, 0x29, 0x7C, 0x2B, 0xC0, 0x2A, - 0xAA, 0x00, 0x00, 0x00, 0xDC, 0x30, 0x00, 0x0D, 0x85, 0x1C, 0xAA, 0x94, 0xE2, 0xBE, 0x02, 0xEE, - 0xE0, 0x00, 0x00, 0x0E, 0xC0, 0x30, 0x00, 0x50, 0x51, 0x4A, 0x29, 0x4A, 0x28, 0xA0, 0x22, 0xA2, - 0x00, 0x00, 0x00, 0xDC, 0x04, 0x80, 0x05, 0x05, 0x14, 0xA2, 0x94, 0xA2, 0x8A, 0x07, 0x2E, 0x20, - 0x00, 0x08, 0x0E, 0xC0, 0x48, 0x00, 0x50, 0x51, 0x4A, 0x29, 0x4A, 0x38, 0xA0, 0x00, 0x00, 0x00, - 0x01, 0x40, 0xDC, 0x03, 0x00, 0x05, 0x07, 0x1C, 0xE3, 0x94, 0xA3, 0x8A, 0x0B, 0x04, 0x00, 0xE2, - 0x0C, 0xC0, 0x00, 0x00, 0x70, 0x71, 0xCE, 0x39, 0x4A, 0x30, 0xE0, 0x00, 0x00, 0x00, 0x0C, 0x90, - 0xCC, 0x00, 0x00, 0x07, 0x03, 0xF8, 0x7F, 0x1C, 0xE1, 0xFC, 0x0B, 0x04, 0x00, 0x94, 0x8C, 0xC0, - 0x00, 0x00, 0xF8, 0x3F, 0x87, 0xF1, 0xC7, 0x1F, 0xC0, 0x00, 0x00, 0x00, 0x72, 0x24, 0xCC, 0x0B, - 0x0C, 0x00, 0x06, 0x15, 0x2C, 0xC0, 0x0B, 0x0C, 0x00, 0x48, 0x89, 0xCC, 0x00, 0xFE, 0x10, 0x43, - 0xF8, 0xFF, 0x8F, 0xE1, 0xFC, 0x3F, 0x80, 0x00, 0x39, 0x05, 0x3C, 0xC0, 0x0F, 0xE3, 0x8E, 0x3F, - 0x8F, 0xF8, 0xFE, 0x1F, 0xC3, 0xF8, 0x00, 0x03, 0x22, 0x27, 0xDC, 0x01, 0x87, 0x38, 0xE6, 0x1C, - 0xDD, 0x99, 0xF3, 0xFE, 0x61, 0xC0, 0x00, 0x21, 0x50, 0xFE, 0xC0, 0x1C, 0x52, 0x8A, 0x71, 0x41, - 0x41, 0xC0, 0x3A, 0xE7, 0x14, 0x00, 0x1C, 0x88, 0x9E, 0xDC, 0x01, 0x45, 0x28, 0xA5, 0x14, 0x14, - 0x14, 0x02, 0xAA, 0x51, 0x40, 0x01, 0x94, 0x13, 0xEE, 0xC0, 0x14, 0x52, 0x8A, 0x51, 0x41, 0x41, - 0x40, 0x2A, 0xA5, 0x14, 0x00, 0x12, 0x22, 0x7F, 0xDC, 0x01, 0x47, 0x28, 0xA5, 0x1C, 0x14, 0x14, - 0x02, 0xAA, 0x51, 0xC0, 0x0E, 0x05, 0x0F, 0x3E, 0xC0, 0x1C, 0x02, 0x8A, 0x70, 0x01, 0x41, 0x4E, - 0x2A, 0xA7, 0x00, 0x00, 0xC0, 0x09, 0xF0, 0xCC, 0x00, 0xFC, 0x38, 0xE3, 0xF0, 0x14, 0x17, 0x82, - 0xAA, 0x3F, 0x00, 0x09, 0x01, 0x3F, 0x8F, 0xC0, 0x03, 0xE1, 0xFC, 0x0F, 0x81, 0x41, 0x78, 0x2A, - 0xA0, 0xF8, 0x01, 0x28, 0x27, 0x98, 0xFC, 0x00, 0x07, 0x0D, 0x80, 0x1C, 0x14, 0x14, 0xE2, 0xAA, - 0x01, 0xC0, 0x28, 0x40, 0xF8, 0x0C, 0xC0, 0x1C, 0x50, 0x50, 0x71, 0x41, 0x41, 0x40, 0x28, 0xA7, - 0x14, 0x03, 0x02, 0x9F, 0xC0, 0xFC, 0x01, 0x45, 0x05, 0x05, 0x14, 0x14, 0x14, 0x02, 0xAA, 0x51, - 0x40, 0x32, 0x13, 0xCC, 0x0F, 0xC1, 0x94, 0x50, 0x50, 0x51, 0x41, 0x41, 0x40, 0x28, 0xA5, 0x14, - 0x01, 0xF2, 0x7C, 0x00, 0xFC, 0x19, 0x47, 0x05, 0x05, 0x1C, 0x14, 0x1C, 0x02, 0x8A, 0x51, 0xC0, - 0x0E, 0x0F, 0xE0, 0x0F, 0xC1, 0x9C, 0x30, 0x70, 0x70, 0xC1, 0x41, 0x9F, 0x28, 0xA7, 0x0C, 0x00, - 0x61, 0xE6, 0x00, 0x3F, 0xF8, 0xFE, 0x07, 0x03, 0xF8, 0x1C, 0x0F, 0xE3, 0x8E, 0x3F, 0x80, 0x03, - 0xBE, 0x00, 0x03, 0xFF, 0x8F, 0xE0, 0xF8, 0x3F, 0x81, 0xC0, 0xFE, 0x38, 0xE3, 0xF8, 0x00, 0x1F, - 0xF0, 0x0B, 0x0E, 0x00, 0xF3, 0x0B, 0x0E, 0x00, 0x06, 0x00, 0x00 -}}; +const image_t img_csLogo_FULL = { + 124, + 40, + true, + 571, + 0x0B, + {// orig:620, comp:7.90% + 0x3F, 0xFF, 0xFE, 0x10, 0x43, 0xF8, 0x7F, 0x0F, 0xE1, 0xFC, 0x0B, 0x05, 0x00, 0x03, 0xFF, + 0xFF, 0xE3, 0x8E, 0x3F, 0x87, 0xF0, 0xFE, 0x1F, 0xC0, 0x0B, 0x05, 0x00, 0xFC, 0x00, 0x07, + 0x38, 0xE6, 0x1C, 0xE3, 0x80, 0x73, 0x8E, 0x03, 0xBB, 0x80, 0x00, 0x00, 0x0F, 0xC0, 0x00, + 0x52, 0x8A, 0x71, 0xCE, 0x39, 0xC7, 0x38, 0xA0, 0x22, 0x10, 0x00, 0x00, 0x00, 0xFC, 0x00, + 0x05, 0x28, 0xA7, 0x14, 0xA2, 0x9C, 0x52, 0x8A, 0x03, 0x39, 0x00, 0x00, 0x00, 0x0C, 0xC0, + 0x00, 0x52, 0x8A, 0x51, 0x4A, 0x29, 0x45, 0x28, 0xA0, 0x20, 0x90, 0x00, 0x00, 0x00, 0xFC, + 0x00, 0x07, 0x28, 0xA5, 0x14, 0xA2, 0x94, 0x52, 0x8E, 0x03, 0xB9, 0x40, 0x00, 0x00, 0x0F, + 0xC0, 0x00, 0x02, 0x8A, 0x51, 0xCA, 0xA9, 0x47, 0x28, 0x0B, 0x06, 0x00, 0xCC, 0x00, 0x00, + 0x38, 0xE5, 0xF0, 0xA2, 0x97, 0xC2, 0x80, 0x06, 0xEE, 0x80, 0x00, 0x00, 0x0E, 0xC3, 0x00, + 0x01, 0xFC, 0x5F, 0x0A, 0x29, 0x7C, 0x2B, 0xC0, 0x2A, 0xAA, 0x00, 0x00, 0x00, 0xDC, 0x30, + 0x00, 0x0D, 0x85, 0x1C, 0xAA, 0x94, 0xE2, 0xBE, 0x02, 0xEE, 0xE0, 0x00, 0x00, 0x0E, 0xC0, + 0x30, 0x00, 0x50, 0x51, 0x4A, 0x29, 0x4A, 0x28, 0xA0, 0x22, 0xA2, 0x00, 0x00, 0x00, 0xDC, + 0x04, 0x80, 0x05, 0x05, 0x14, 0xA2, 0x94, 0xA2, 0x8A, 0x07, 0x2E, 0x20, 0x00, 0x08, 0x0E, + 0xC0, 0x48, 0x00, 0x50, 0x51, 0x4A, 0x29, 0x4A, 0x38, 0xA0, 0x00, 0x00, 0x00, 0x01, 0x40, + 0xDC, 0x03, 0x00, 0x05, 0x07, 0x1C, 0xE3, 0x94, 0xA3, 0x8A, 0x0B, 0x04, 0x00, 0xE2, 0x0C, + 0xC0, 0x00, 0x00, 0x70, 0x71, 0xCE, 0x39, 0x4A, 0x30, 0xE0, 0x00, 0x00, 0x00, 0x0C, 0x90, + 0xCC, 0x00, 0x00, 0x07, 0x03, 0xF8, 0x7F, 0x1C, 0xE1, 0xFC, 0x0B, 0x04, 0x00, 0x94, 0x8C, + 0xC0, 0x00, 0x00, 0xF8, 0x3F, 0x87, 0xF1, 0xC7, 0x1F, 0xC0, 0x00, 0x00, 0x00, 0x72, 0x24, + 0xCC, 0x0B, 0x0C, 0x00, 0x06, 0x15, 0x2C, 0xC0, 0x0B, 0x0C, 0x00, 0x48, 0x89, 0xCC, 0x00, + 0xFE, 0x10, 0x43, 0xF8, 0xFF, 0x8F, 0xE1, 0xFC, 0x3F, 0x80, 0x00, 0x39, 0x05, 0x3C, 0xC0, + 0x0F, 0xE3, 0x8E, 0x3F, 0x8F, 0xF8, 0xFE, 0x1F, 0xC3, 0xF8, 0x00, 0x03, 0x22, 0x27, 0xDC, + 0x01, 0x87, 0x38, 0xE6, 0x1C, 0xDD, 0x99, 0xF3, 0xFE, 0x61, 0xC0, 0x00, 0x21, 0x50, 0xFE, + 0xC0, 0x1C, 0x52, 0x8A, 0x71, 0x41, 0x41, 0xC0, 0x3A, 0xE7, 0x14, 0x00, 0x1C, 0x88, 0x9E, + 0xDC, 0x01, 0x45, 0x28, 0xA5, 0x14, 0x14, 0x14, 0x02, 0xAA, 0x51, 0x40, 0x01, 0x94, 0x13, + 0xEE, 0xC0, 0x14, 0x52, 0x8A, 0x51, 0x41, 0x41, 0x40, 0x2A, 0xA5, 0x14, 0x00, 0x12, 0x22, + 0x7F, 0xDC, 0x01, 0x47, 0x28, 0xA5, 0x1C, 0x14, 0x14, 0x02, 0xAA, 0x51, 0xC0, 0x0E, 0x05, + 0x0F, 0x3E, 0xC0, 0x1C, 0x02, 0x8A, 0x70, 0x01, 0x41, 0x4E, 0x2A, 0xA7, 0x00, 0x00, 0xC0, + 0x09, 0xF0, 0xCC, 0x00, 0xFC, 0x38, 0xE3, 0xF0, 0x14, 0x17, 0x82, 0xAA, 0x3F, 0x00, 0x09, + 0x01, 0x3F, 0x8F, 0xC0, 0x03, 0xE1, 0xFC, 0x0F, 0x81, 0x41, 0x78, 0x2A, 0xA0, 0xF8, 0x01, + 0x28, 0x27, 0x98, 0xFC, 0x00, 0x07, 0x0D, 0x80, 0x1C, 0x14, 0x14, 0xE2, 0xAA, 0x01, 0xC0, + 0x28, 0x40, 0xF8, 0x0C, 0xC0, 0x1C, 0x50, 0x50, 0x71, 0x41, 0x41, 0x40, 0x28, 0xA7, 0x14, + 0x03, 0x02, 0x9F, 0xC0, 0xFC, 0x01, 0x45, 0x05, 0x05, 0x14, 0x14, 0x14, 0x02, 0xAA, 0x51, + 0x40, 0x32, 0x13, 0xCC, 0x0F, 0xC1, 0x94, 0x50, 0x50, 0x51, 0x41, 0x41, 0x40, 0x28, 0xA5, + 0x14, 0x01, 0xF2, 0x7C, 0x00, 0xFC, 0x19, 0x47, 0x05, 0x05, 0x1C, 0x14, 0x1C, 0x02, 0x8A, + 0x51, 0xC0, 0x0E, 0x0F, 0xE0, 0x0F, 0xC1, 0x9C, 0x30, 0x70, 0x70, 0xC1, 0x41, 0x9F, 0x28, + 0xA7, 0x0C, 0x00, 0x61, 0xE6, 0x00, 0x3F, 0xF8, 0xFE, 0x07, 0x03, 0xF8, 0x1C, 0x0F, 0xE3, + 0x8E, 0x3F, 0x80, 0x03, 0xBE, 0x00, 0x03, 0xFF, 0x8F, 0xE0, 0xF8, 0x3F, 0x81, 0xC0, 0xFE, + 0x38, 0xE3, 0xF8, 0x00, 0x1F, 0xF0, 0x0B, 0x0E, 0x00, 0xF3, 0x0B, 0x0E, 0x00, 0x06, 0x00, + 0x00}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_csLogo_Small.c b/applications/plugins/wii_ec_anal/gfx/img_csLogo_Small.c index 5cd2f613f..71debc2ff 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_csLogo_Small.c +++ b/applications/plugins/wii_ec_anal/gfx/img_csLogo_Small.c @@ -13,6 +13,10 @@ #include "images.h" -const image_t img_csLogo_Small = { 9, 12, false, 14, 0, { - 0xFF, 0xFF, 0xF0, 0x78, 0x3D, 0x06, 0x3F, 0x13, 0x88, 0xC7, 0xE0, 0x7D, 0x3E, 0xF0 -}}; +const image_t img_csLogo_Small = { + 9, + 12, + false, + 14, + 0, + {0xFF, 0xFF, 0xF0, 0x78, 0x3D, 0x06, 0x3F, 0x13, 0x88, 0xC7, 0xE0, 0x7D, 0x3E, 0xF0}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_ecp_SCL.c b/applications/plugins/wii_ec_anal/gfx/img_ecp_SCL.c index 533b79c7b..e3622a626 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_ecp_SCL.c +++ b/applications/plugins/wii_ec_anal/gfx/img_ecp_SCL.c @@ -8,6 +8,10 @@ #include "images.h" -const image_t img_ecp_SCL = { 16, 7, false, 14, 0, { - 0x3F, 0x8F, 0x3F, 0x8F, 0x31, 0x8C, 0x31, 0x8C, 0x31, 0x8C, 0xF1, 0xFC, 0xF1, 0xFC -}}; +const image_t img_ecp_SCL = { + 16, + 7, + false, + 14, + 0, + {0x3F, 0x8F, 0x3F, 0x8F, 0x31, 0x8C, 0x31, 0x8C, 0x31, 0x8C, 0xF1, 0xFC, 0xF1, 0xFC}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_ecp_SDA.c b/applications/plugins/wii_ec_anal/gfx/img_ecp_SDA.c index 7384fc87c..5ce0cbec4 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_ecp_SDA.c +++ b/applications/plugins/wii_ec_anal/gfx/img_ecp_SDA.c @@ -13,7 +13,7 @@ #include "images.h" -const image_t img_ecp_SDA = { 17, 12, false, 26, 0, { - 0x10, 0x00, 0x18, 0x00, 0x18, 0x00, 0x1F, 0xFC, 0x0F, 0xFE, 0x43, 0x00, 0x30, 0xC0, 0x0C, 0x27, - 0xFF, 0x03, 0xFF, 0x80, 0x01, 0x80, 0x01, 0x80, 0x00, 0x80 -}}; +const image_t img_ecp_SDA = {17, 12, false, 26, 0, {0x10, 0x00, 0x18, 0x00, 0x18, 0x00, 0x1F, + 0xFC, 0x0F, 0xFE, 0x43, 0x00, 0x30, 0xC0, + 0x0C, 0x27, 0xFF, 0x03, 0xFF, 0x80, 0x01, + 0x80, 0x01, 0x80, 0x00, 0x80}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_ecp_port.c b/applications/plugins/wii_ec_anal/gfx/img_ecp_port.c index 942f0c593..60f535458 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_ecp_port.c +++ b/applications/plugins/wii_ec_anal/gfx/img_ecp_port.c @@ -43,24 +43,30 @@ #include "images.h" -const image_t img_ecp_port = { 69, 42, true, 290, 0x04, { // orig:363, comp:20.11% - 0x00, 0x2A, 0x04, 0x06, 0xAA, 0xA8, 0x02, 0x04, 0x07, 0xAA, 0x80, 0x2A, 0x04, 0x07, 0xAA, 0x02, - 0x04, 0x07, 0xAA, 0xA0, 0x2A, 0x04, 0x07, 0xAA, 0x82, 0x04, 0x07, 0xAA, 0xA8, 0x2A, 0x04, 0x07, - 0xAA, 0xA3, 0x04, 0x07, 0xFF, 0xAA, 0x1F, 0x04, 0x06, 0xFF, 0xFE, 0xA8, 0xC0, 0x04, 0x06, 0x00, - 0x6A, 0x86, 0x04, 0x06, 0x00, 0x03, 0xAA, 0x30, 0x04, 0x06, 0x00, 0x1A, 0xA1, 0x80, 0x04, 0x06, - 0x00, 0xEA, 0x8C, 0x04, 0x06, 0x00, 0x06, 0xA8, 0x61, 0x04, 0x05, 0xFF, 0xFC, 0x3A, 0xA3, 0x0F, - 0x04, 0x05, 0xFF, 0xE1, 0xAA, 0x18, 0x61, 0x83, 0x0C, 0x18, 0x60, 0xC3, 0x0E, 0xA8, 0xC3, 0x0C, - 0x18, 0x60, 0xC3, 0x06, 0x18, 0x6A, 0x86, 0x18, 0x7F, 0xC3, 0xFE, 0x1F, 0xF0, 0xC3, 0xAA, 0x30, - 0xC3, 0xFE, 0x1F, 0xF0, 0xFF, 0x86, 0x1A, 0xA1, 0x86, 0x04, 0x05, 0x00, 0x30, 0xEA, 0xBC, 0x30, - 0x04, 0x04, 0x00, 0x01, 0x86, 0xFB, 0xE1, 0x80, 0x04, 0x04, 0x00, 0x0C, 0x3F, 0xFF, 0x0C, 0x04, - 0x05, 0x00, 0x61, 0xBE, 0x78, 0x60, 0x04, 0x04, 0x00, 0x03, 0x0F, 0xF8, 0xC3, 0x0F, 0xF8, 0x00, - 0x03, 0xFE, 0x18, 0x6A, 0x86, 0x18, 0x7F, 0xC0, 0x00, 0x1F, 0xF0, 0xC3, 0xAA, 0x30, 0xC3, 0x06, - 0x1F, 0xF0, 0xC1, 0x86, 0x1A, 0xA1, 0x86, 0x18, 0x30, 0x80, 0x86, 0x0C, 0x30, 0xEA, 0x8C, 0x3F, - 0x04, 0x05, 0xFF, 0x86, 0xA8, 0x61, 0x04, 0x05, 0xFF, 0xFC, 0x3A, 0xA3, 0x04, 0x06, 0x00, 0x01, - 0xAA, 0x18, 0x04, 0x06, 0x00, 0x0E, 0xA8, 0xC0, 0x04, 0x06, 0x00, 0x6A, 0x86, 0x00, 0x00, 0x7F, - 0xFF, 0xF0, 0x00, 0x03, 0xAA, 0x30, 0x00, 0x03, 0xFF, 0xFF, 0x80, 0x00, 0x1A, 0xA1, 0x80, 0x00, - 0x1A, 0xA0, 0x0C, 0x00, 0x00, 0xEA, 0x0C, 0x00, 0x00, 0xEA, 0x00, 0x60, 0x00, 0x06, 0xA0, 0x60, - 0x00, 0x06, 0xA0, 0x03, 0x00, 0x00, 0x3A, 0x03, 0x00, 0x00, 0x3A, 0x00, 0x18, 0x00, 0x01, 0xA0, - 0x1F, 0xFF, 0xFF, 0xA0, 0x00, 0xFF, 0xFF, 0xFE, 0x00, 0xFF, 0xFF, 0xFE, 0x00, 0x07, 0xFF, 0xFF, - 0xE0, 0x00 -}}; +const image_t img_ecp_port = { + 69, + 42, + true, + 290, + 0x04, + {// orig:363, comp:20.11% + 0x00, 0x2A, 0x04, 0x06, 0xAA, 0xA8, 0x02, 0x04, 0x07, 0xAA, 0x80, 0x2A, 0x04, 0x07, 0xAA, + 0x02, 0x04, 0x07, 0xAA, 0xA0, 0x2A, 0x04, 0x07, 0xAA, 0x82, 0x04, 0x07, 0xAA, 0xA8, 0x2A, + 0x04, 0x07, 0xAA, 0xA3, 0x04, 0x07, 0xFF, 0xAA, 0x1F, 0x04, 0x06, 0xFF, 0xFE, 0xA8, 0xC0, + 0x04, 0x06, 0x00, 0x6A, 0x86, 0x04, 0x06, 0x00, 0x03, 0xAA, 0x30, 0x04, 0x06, 0x00, 0x1A, + 0xA1, 0x80, 0x04, 0x06, 0x00, 0xEA, 0x8C, 0x04, 0x06, 0x00, 0x06, 0xA8, 0x61, 0x04, 0x05, + 0xFF, 0xFC, 0x3A, 0xA3, 0x0F, 0x04, 0x05, 0xFF, 0xE1, 0xAA, 0x18, 0x61, 0x83, 0x0C, 0x18, + 0x60, 0xC3, 0x0E, 0xA8, 0xC3, 0x0C, 0x18, 0x60, 0xC3, 0x06, 0x18, 0x6A, 0x86, 0x18, 0x7F, + 0xC3, 0xFE, 0x1F, 0xF0, 0xC3, 0xAA, 0x30, 0xC3, 0xFE, 0x1F, 0xF0, 0xFF, 0x86, 0x1A, 0xA1, + 0x86, 0x04, 0x05, 0x00, 0x30, 0xEA, 0xBC, 0x30, 0x04, 0x04, 0x00, 0x01, 0x86, 0xFB, 0xE1, + 0x80, 0x04, 0x04, 0x00, 0x0C, 0x3F, 0xFF, 0x0C, 0x04, 0x05, 0x00, 0x61, 0xBE, 0x78, 0x60, + 0x04, 0x04, 0x00, 0x03, 0x0F, 0xF8, 0xC3, 0x0F, 0xF8, 0x00, 0x03, 0xFE, 0x18, 0x6A, 0x86, + 0x18, 0x7F, 0xC0, 0x00, 0x1F, 0xF0, 0xC3, 0xAA, 0x30, 0xC3, 0x06, 0x1F, 0xF0, 0xC1, 0x86, + 0x1A, 0xA1, 0x86, 0x18, 0x30, 0x80, 0x86, 0x0C, 0x30, 0xEA, 0x8C, 0x3F, 0x04, 0x05, 0xFF, + 0x86, 0xA8, 0x61, 0x04, 0x05, 0xFF, 0xFC, 0x3A, 0xA3, 0x04, 0x06, 0x00, 0x01, 0xAA, 0x18, + 0x04, 0x06, 0x00, 0x0E, 0xA8, 0xC0, 0x04, 0x06, 0x00, 0x6A, 0x86, 0x00, 0x00, 0x7F, 0xFF, + 0xF0, 0x00, 0x03, 0xAA, 0x30, 0x00, 0x03, 0xFF, 0xFF, 0x80, 0x00, 0x1A, 0xA1, 0x80, 0x00, + 0x1A, 0xA0, 0x0C, 0x00, 0x00, 0xEA, 0x0C, 0x00, 0x00, 0xEA, 0x00, 0x60, 0x00, 0x06, 0xA0, + 0x60, 0x00, 0x06, 0xA0, 0x03, 0x00, 0x00, 0x3A, 0x03, 0x00, 0x00, 0x3A, 0x00, 0x18, 0x00, + 0x01, 0xA0, 0x1F, 0xFF, 0xFF, 0xA0, 0x00, 0xFF, 0xFF, 0xFE, 0x00, 0xFF, 0xFF, 0xFE, 0x00, + 0x07, 0xFF, 0xFF, 0xE0, 0x00}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_key_Back.c b/applications/plugins/wii_ec_anal/gfx/img_key_Back.c index d13bcf7f2..23c17fe2b 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_key_Back.c +++ b/applications/plugins/wii_ec_anal/gfx/img_key_Back.c @@ -10,6 +10,5 @@ #include "images.h" -const image_t img_key_Back = { 9, 9, false, 11, 0, { - 0x7F, 0x7F, 0xFB, 0xF8, 0x7E, 0xDF, 0xEF, 0xCF, 0xFF, 0x3F, 0x00 -}}; +const image_t img_key_Back = + {9, 9, false, 11, 0, {0x7F, 0x7F, 0xFB, 0xF8, 0x7E, 0xDF, 0xEF, 0xCF, 0xFF, 0x3F, 0x00}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_key_D.c b/applications/plugins/wii_ec_anal/gfx/img_key_D.c index 8d182427c..689b9148c 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_key_D.c +++ b/applications/plugins/wii_ec_anal/gfx/img_key_D.c @@ -9,6 +9,5 @@ #include "images.h" -const image_t img_key_D = { 9, 8, false, 9, 0, { - 0x7F, 0x7F, 0xFF, 0xF8, 0x3E, 0x3F, 0xBF, 0xFE, 0xFE -}}; +const image_t img_key_D = + {9, 8, false, 9, 0, {0x7F, 0x7F, 0xFF, 0xF8, 0x3E, 0x3F, 0xBF, 0xFE, 0xFE}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_key_L.c b/applications/plugins/wii_ec_anal/gfx/img_key_L.c index 1fc5556b1..a5fca1a21 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_key_L.c +++ b/applications/plugins/wii_ec_anal/gfx/img_key_L.c @@ -10,6 +10,5 @@ #include "images.h" -const image_t img_key_L = { 8, 9, false, 9, 0, { - 0x7E, 0xFF, 0xF7, 0xE7, 0xC7, 0xE7, 0xF7, 0xFF, 0x7E -}}; +const image_t img_key_L = + {8, 9, false, 9, 0, {0x7E, 0xFF, 0xF7, 0xE7, 0xC7, 0xE7, 0xF7, 0xFF, 0x7E}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_key_OK.c b/applications/plugins/wii_ec_anal/gfx/img_key_OK.c index ef64128f8..926d91c2e 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_key_OK.c +++ b/applications/plugins/wii_ec_anal/gfx/img_key_OK.c @@ -10,6 +10,5 @@ #include "images.h" -const image_t img_key_OK = { 9, 9, false, 11, 0, { - 0x7F, 0x7F, 0xF8, 0xF8, 0x3C, 0x1E, 0x0F, 0x8F, 0xFF, 0x3F, 0x00 -}}; +const image_t img_key_OK = + {9, 9, false, 11, 0, {0x7F, 0x7F, 0xF8, 0xF8, 0x3C, 0x1E, 0x0F, 0x8F, 0xFF, 0x3F, 0x00}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_key_OKi.c b/applications/plugins/wii_ec_anal/gfx/img_key_OKi.c index 595f2f431..aa6f9e692 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_key_OKi.c +++ b/applications/plugins/wii_ec_anal/gfx/img_key_OKi.c @@ -10,6 +10,5 @@ #include "images.h" -const image_t img_key_OKi = { 9, 9, false, 11, 0, { - 0x7F, 0x60, 0xE7, 0x37, 0xDB, 0xED, 0xF6, 0x73, 0x83, 0x7F, 0x00 -}}; +const image_t img_key_OKi = + {9, 9, false, 11, 0, {0x7F, 0x60, 0xE7, 0x37, 0xDB, 0xED, 0xF6, 0x73, 0x83, 0x7F, 0x00}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_key_R.c b/applications/plugins/wii_ec_anal/gfx/img_key_R.c index 87cc385bc..8b97c7b48 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_key_R.c +++ b/applications/plugins/wii_ec_anal/gfx/img_key_R.c @@ -10,6 +10,5 @@ #include "images.h" -const image_t img_key_R = { 8, 9, false, 9, 0, { - 0x7E, 0xFF, 0xEF, 0xE7, 0xE3, 0xE7, 0xEF, 0xFF, 0x7E -}}; +const image_t img_key_R = + {8, 9, false, 9, 0, {0x7E, 0xFF, 0xEF, 0xE7, 0xE3, 0xE7, 0xEF, 0xFF, 0x7E}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_key_U.c b/applications/plugins/wii_ec_anal/gfx/img_key_U.c index aca5bb62a..65f4cd9e0 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_key_U.c +++ b/applications/plugins/wii_ec_anal/gfx/img_key_U.c @@ -9,6 +9,5 @@ #include "images.h" -const image_t img_key_U = { 9, 8, false, 9, 0, { - 0x7F, 0x7F, 0xFD, 0xFC, 0x7C, 0x1F, 0xFF, 0xFE, 0xFE -}}; +const image_t img_key_U = + {9, 8, false, 9, 0, {0x7F, 0x7F, 0xFD, 0xFC, 0x7C, 0x1F, 0xFF, 0xFE, 0xFE}}; diff --git a/applications/plugins/wii_ec_anal/gfx/img_key_Ui.c b/applications/plugins/wii_ec_anal/gfx/img_key_Ui.c index b740780ad..30c60c66e 100644 --- a/applications/plugins/wii_ec_anal/gfx/img_key_Ui.c +++ b/applications/plugins/wii_ec_anal/gfx/img_key_Ui.c @@ -9,6 +9,5 @@ #include "images.h" -const image_t img_key_Ui = { 9, 8, false, 9, 0, { - 0x7F, 0x60, 0xE2, 0x33, 0x9B, 0xEC, 0x07, 0x06, 0xFE -}}; +const image_t img_key_Ui = + {9, 8, false, 9, 0, {0x7F, 0x60, 0xE2, 0x33, 0x9B, 0xEC, 0x07, 0x06, 0xFE}}; diff --git a/applications/plugins/wii_ec_anal/i2c_workaround.h b/applications/plugins/wii_ec_anal/i2c_workaround.h index de1dbba54..b24efaf48 100644 --- a/applications/plugins/wii_ec_anal/i2c_workaround.h +++ b/applications/plugins/wii_ec_anal/i2c_workaround.h @@ -40,62 +40,70 @@ void furi_hal_i2c_release (FuriHalI2cBusHandle* handle) */ -#ifndef I2C_WORKAROUND_H_ -#define I2C_WORKAROUND_H_ +#ifndef I2C_WORKAROUND_H_ +#define I2C_WORKAROUND_H_ -#include +#include #define ENABLE_WORKAROUND 1 #if ENABLE_WORKAROUND == 1 - //+============================================================================ ======================================== - static inline - bool furi_hal_Wi2c_is_device_ready (FuriHalI2cBusHandle* const bus, const uint8_t addr, const uint32_t tmo) - { - furi_hal_i2c_acquire(bus); - bool rv = furi_hal_i2c_is_device_ready(bus, addr, tmo); - furi_hal_i2c_release(bus); - return rv; - } +//+============================================================================ ======================================== +static inline bool furi_hal_Wi2c_is_device_ready( + FuriHalI2cBusHandle* const bus, + const uint8_t addr, + const uint32_t tmo) { + furi_hal_i2c_acquire(bus); + bool rv = furi_hal_i2c_is_device_ready(bus, addr, tmo); + furi_hal_i2c_release(bus); + return rv; +} - //+============================================================================ - static inline - bool furi_hal_Wi2c_tx ( FuriHalI2cBusHandle* const bus, const uint8_t addr, - const void* buf, const size_t len, const uint32_t tmo ) - { - furi_hal_i2c_acquire(bus); - bool rv = furi_hal_i2c_tx(bus, addr, buf, len, tmo); - furi_hal_i2c_release(bus); - return rv; - } +//+============================================================================ +static inline bool furi_hal_Wi2c_tx( + FuriHalI2cBusHandle* const bus, + const uint8_t addr, + const void* buf, + const size_t len, + const uint32_t tmo) { + furi_hal_i2c_acquire(bus); + bool rv = furi_hal_i2c_tx(bus, addr, buf, len, tmo); + furi_hal_i2c_release(bus); + return rv; +} - //+============================================================================ - static inline - bool furi_hal_Wi2c_rx ( FuriHalI2cBusHandle* const bus, const uint8_t addr, - void* buf, const size_t len, const uint32_t tmo ) - { - furi_hal_i2c_acquire(bus); - bool rv = furi_hal_i2c_rx(bus, addr, buf, len, tmo); - furi_hal_i2c_release(bus); - return rv; - } +//+============================================================================ +static inline bool furi_hal_Wi2c_rx( + FuriHalI2cBusHandle* const bus, + const uint8_t addr, + void* buf, + const size_t len, + const uint32_t tmo) { + furi_hal_i2c_acquire(bus); + bool rv = furi_hal_i2c_rx(bus, addr, buf, len, tmo); + furi_hal_i2c_release(bus); + return rv; +} - //+============================================================================ - static inline - bool furi_hal_Wi2c_trx ( FuriHalI2cBusHandle* const bus, const uint8_t addr, - const void* tx, const size_t txlen, - void* rx, const size_t rxlen, const uint32_t tmo ) - { - bool rv = furi_hal_Wi2c_tx(bus, addr, tx, txlen, tmo); - if (rv) rv = furi_hal_Wi2c_rx(bus, addr, rx, rxlen, tmo); - return rv; - } +//+============================================================================ +static inline bool furi_hal_Wi2c_trx( + FuriHalI2cBusHandle* const bus, + const uint8_t addr, + const void* tx, + const size_t txlen, + void* rx, + const size_t rxlen, + const uint32_t tmo) { + bool rv = furi_hal_Wi2c_tx(bus, addr, tx, txlen, tmo); + if(rv) rv = furi_hal_Wi2c_rx(bus, addr, rx, rxlen, tmo); + return rv; +} - //----------------------------------------------------------------------------- ---------------------------------------- -# define furi_hal_i2c_is_device_ready(...) furi_hal_Wi2c_is_device_ready(__VA_ARGS__) -# define furi_hal_i2c_tx(...) furi_hal_Wi2c_tx(__VA_ARGS__) -# define furi_hal_i2c_rx(...) furi_hal_Wi2c_rx(__VA_ARGS__) -# define furi_hal_i2c_trx(...) furi_hal_Wi2c_trx(__VA_ARGS__) +//----------------------------------------------------------------------------- ---------------------------------------- +#define furi_hal_i2c_is_device_ready(...) furi_hal_Wi2c_is_device_ready(__VA_ARGS__) +#define furi_hal_i2c_tx(...) furi_hal_Wi2c_tx(__VA_ARGS__) +#define furi_hal_i2c_rx(...) furi_hal_Wi2c_rx(__VA_ARGS__) +#define furi_hal_i2c_trx(...) furi_hal_Wi2c_trx(__VA_ARGS__) #endif //ENABLE_WORKAROUND @@ -103,17 +111,21 @@ void furi_hal_i2c_release (FuriHalI2cBusHandle* handle) // Some devices take a moment to respond to read requests // The puts a delay between the address being set and the data being read // -static inline -bool furi_hal_i2c_trxd ( FuriHalI2cBusHandle* const bus, const uint8_t addr, - const void* tx, const size_t txlen, - void* rx, const size_t rxlen, const uint32_t tmo, const uint32_t us ) -{ - bool rv = furi_hal_i2c_tx(bus, addr, tx, txlen, tmo); - if (rv) { - furi_delay_us(us); - rv = furi_hal_i2c_rx(bus, addr, rx, rxlen, tmo); - } - return rv; +static inline bool furi_hal_i2c_trxd( + FuriHalI2cBusHandle* const bus, + const uint8_t addr, + const void* tx, + const size_t txlen, + void* rx, + const size_t rxlen, + const uint32_t tmo, + const uint32_t us) { + bool rv = furi_hal_i2c_tx(bus, addr, tx, txlen, tmo); + if(rv) { + furi_delay_us(us); + rv = furi_hal_i2c_rx(bus, addr, rx, rxlen, tmo); + } + return rv; } #endif //I2C_WORKAROUND_H_ diff --git a/applications/plugins/wii_ec_anal/wii_anal.c b/applications/plugins/wii_ec_anal/wii_anal.c index fdf718b63..f0af1c9c5 100644 --- a/applications/plugins/wii_ec_anal/wii_anal.c +++ b/applications/plugins/wii_ec_anal/wii_anal.c @@ -3,34 +3,34 @@ // // System libs -#include // malloc -#include // uint32_t -#include // __VA_ARGS__ -#include -#include +#include // malloc +#include // uint32_t +#include // __VA_ARGS__ +#include +#include // FlipperZero libs -#include // Core API -#include // GUI (screen/keyboard) API -#include // GUI Input extensions -#include +#include // Core API +#include // GUI (screen/keyboard) API +#include // GUI Input extensions +#include // Do this first! #define ERR_C_ // Do this in precisely ONE file -#include "err.h" // Error numbers & messages +#include "err.h" // Error numbers & messages -#include "bc_logging.h" +#include "bc_logging.h" // Local headers -#include "wii_anal.h" // Various enums and struct declarations -#include "wii_i2c.h" // Wii i2c functions -#include "wii_ec.h" // Wii Extension Controller functions (eg. draw) -#include "wii_anal_keys.h" // key mappings -#include "gfx/images.h" // Images -#include "wii_anal_lcd.h" // Drawing functions -#include "wii_anal_ec.h" // Wii controller events +#include "wii_anal.h" // Various enums and struct declarations +#include "wii_i2c.h" // Wii i2c functions +#include "wii_ec.h" // Wii Extension Controller functions (eg. draw) +#include "wii_anal_keys.h" // key mappings +#include "gfx/images.h" // Images +#include "wii_anal_lcd.h" // Drawing functions +#include "wii_anal_ec.h" // Wii controller events -#include "wii_anal_ver.h" // Version number +#include "wii_anal_ver.h" // Version number //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // OOOOO // SSSSS CCCCC AAA L L BBBB AAA CCCC K K SSSSS @@ -44,48 +44,42 @@ // OS Callback : Timer tick // We register this function to be called when the OS signals a timer 'tick' event // -static -void cbTimer (FuriMessageQueue* queue) -{ - ENTER; - furi_assert(queue); +static void cbTimer(FuriMessageQueue* queue) { + ENTER; + furi_assert(queue); - eventMsg_t message = {.id = EVID_TICK}; - furi_message_queue_put(queue, &message, 0); + eventMsg_t message = {.id = EVID_TICK}; + furi_message_queue_put(queue, &message, 0); - LEAVE; - return; + LEAVE; + return; } //+============================================================================ ======================================== // OS Callback : Keypress // We register this function to be called when the OS detects a keypress // -static -void cbInput (InputEvent* event, FuriMessageQueue* queue) -{ - ENTER; - furi_assert(queue); - furi_assert(event); +static void cbInput(InputEvent* event, FuriMessageQueue* queue) { + ENTER; + furi_assert(queue); + furi_assert(event); - // Put an "input" event message on the message queue - eventMsg_t message = {.id = EVID_KEY, .input = *event}; - furi_message_queue_put(queue, &message, FuriWaitForever); + // Put an "input" event message on the message queue + eventMsg_t message = {.id = EVID_KEY, .input = *event}; + furi_message_queue_put(queue, &message, FuriWaitForever); - LEAVE; - return; + LEAVE; + return; } //+============================================================================ // Show version number // -static -void showVer (Canvas* const canvas) -{ - show(canvas, 0,59, &img_3x5_v, SHOW_SET_BLK); - show(canvas, 4,59, VER_MAJ, SHOW_SET_BLK); - canvas_draw_frame(canvas, 8,62, 2,2); - show(canvas, 11,59, VER_MIN, SHOW_SET_BLK); +static void showVer(Canvas* const canvas) { + show(canvas, 0, 59, &img_3x5_v, SHOW_SET_BLK); + show(canvas, 4, 59, VER_MAJ, SHOW_SET_BLK); + canvas_draw_frame(canvas, 8, 62, 2, 2); + show(canvas, 11, 59, VER_MIN, SHOW_SET_BLK); } //+============================================================================ @@ -95,105 +89,103 @@ void showVer (Canvas* const canvas) // We actually instruct the OS to perform this request, after we update the interface // I guess it's possible that this instruction may able be issued by other threads !? // -static -void cbDraw (Canvas* const canvas, void* ctx) -{ - ENTER; - furi_assert(canvas); - furi_assert(ctx); +static void cbDraw(Canvas* const canvas, void* ctx) { + ENTER; + furi_assert(canvas); + furi_assert(ctx); - state_t* state = NULL; + state_t* state = NULL; - // Try to acquire the mutex for the plugin state variables, timeout = 25mS - if ( !(state = (state_t*)acquire_mutex((ValueMutex*)ctx, 25)) ) return ; + // Try to acquire the mutex for the plugin state variables, timeout = 25mS + if(!(state = (state_t*)acquire_mutex((ValueMutex*)ctx, 25))) return; - switch (state->scene) { - //--------------------------------------------------------------------- - case SCENE_SPLASH: - show(canvas, 2,0, &img_csLogo_FULL, SHOW_SET_BLK); + switch(state->scene) { + //--------------------------------------------------------------------- + case SCENE_SPLASH: + show(canvas, 2, 0, &img_csLogo_FULL, SHOW_SET_BLK); - canvas_set_font(canvas, FontSecondary); - canvas_draw_str_aligned(canvas, 64,43, AlignCenter, AlignTop, "Wii Extension Controller"); - canvas_draw_str_aligned(canvas, 64,55, AlignCenter, AlignTop, "Protocol Analyser"); + canvas_set_font(canvas, FontSecondary); + canvas_draw_str_aligned(canvas, 64, 43, AlignCenter, AlignTop, "Wii Extension Controller"); + canvas_draw_str_aligned(canvas, 64, 55, AlignCenter, AlignTop, "Protocol Analyser"); - showVer(canvas); + showVer(canvas); - break; + break; - //--------------------------------------------------------------------- - case SCENE_RIP: - show(canvas, 0,0, &img_RIP, SHOW_SET_BLK); - break; + //--------------------------------------------------------------------- + case SCENE_RIP: + show(canvas, 0, 0, &img_RIP, SHOW_SET_BLK); + break; - //--------------------------------------------------------------------- - case SCENE_WAIT: -# define xo 2 + //--------------------------------------------------------------------- + case SCENE_WAIT: +#define xo 2 - show(canvas, 3+xo,10, &img_ecp_port, SHOW_SET_BLK); + show(canvas, 3 + xo, 10, &img_ecp_port, SHOW_SET_BLK); - BOX_TL(22+xo, 6, 82+xo,23); // 3v3 - BOX_TL(48+xo,21, 82+xo,23); // C1 - BOX_BL(22+xo,41, 82+xo,58); // C0 - BOX_BL(48+xo,41, 82+xo,44); // Gnd + BOX_TL(22 + xo, 6, 82 + xo, 23); // 3v3 + BOX_TL(48 + xo, 21, 82 + xo, 23); // C1 + BOX_BL(22 + xo, 41, 82 + xo, 58); // C0 + BOX_BL(48 + xo, 41, 82 + xo, 44); // Gnd - show(canvas, 90+xo, 3, &img_6x8_3, SHOW_SET_BLK); // 3v3 - show(canvas, 97+xo, 3, &img_6x8_v, SHOW_SET_BLK); - show(canvas, 104+xo, 3, &img_6x8_3, SHOW_SET_BLK); + show(canvas, 90 + xo, 3, &img_6x8_3, SHOW_SET_BLK); // 3v3 + show(canvas, 97 + xo, 3, &img_6x8_v, SHOW_SET_BLK); + show(canvas, 104 + xo, 3, &img_6x8_3, SHOW_SET_BLK); - show(canvas, 90+xo,18, &img_6x8_C, SHOW_SET_BLK); // C1 <-> - show(canvas, 98+xo,18, &img_6x8_1, SHOW_SET_BLK); - show(canvas, 107+xo,16, &img_ecp_SDA, SHOW_SET_BLK); + show(canvas, 90 + xo, 18, &img_6x8_C, SHOW_SET_BLK); // C1 <-> + show(canvas, 98 + xo, 18, &img_6x8_1, SHOW_SET_BLK); + show(canvas, 107 + xo, 16, &img_ecp_SDA, SHOW_SET_BLK); - show(canvas, 90+xo,40, &img_6x8_G, SHOW_SET_BLK); // Gnd - show(canvas, 97+xo,40, &img_6x8_n, SHOW_SET_BLK); - show(canvas, 104+xo,40, &img_6x8_d, SHOW_SET_BLK); + show(canvas, 90 + xo, 40, &img_6x8_G, SHOW_SET_BLK); // Gnd + show(canvas, 97 + xo, 40, &img_6x8_n, SHOW_SET_BLK); + show(canvas, 104 + xo, 40, &img_6x8_d, SHOW_SET_BLK); - show(canvas, 90+xo,54, &img_6x8_C, SHOW_SET_BLK); // C0 _-_- - show(canvas, 98+xo,54, &img_6x8_0, SHOW_SET_BLK); - show(canvas, 108+xo,54, &img_ecp_SCL, SHOW_SET_BLK); + show(canvas, 90 + xo, 54, &img_6x8_C, SHOW_SET_BLK); // C0 _-_- + show(canvas, 98 + xo, 54, &img_6x8_0, SHOW_SET_BLK); + show(canvas, 108 + xo, 54, &img_ecp_SCL, SHOW_SET_BLK); - show(canvas, 0,0, &img_csLogo_Small, SHOW_SET_BLK); - showVer(canvas); + show(canvas, 0, 0, &img_csLogo_Small, SHOW_SET_BLK); + showVer(canvas); -# undef xo - break; +#undef xo + break; - //--------------------------------------------------------------------- - case SCENE_DEBUG: - canvas_set_font(canvas, FontSecondary); + //--------------------------------------------------------------------- + case SCENE_DEBUG: + canvas_set_font(canvas, FontSecondary); - show(canvas, 0,0, &img_key_U, SHOW_SET_BLK); - canvas_draw_str_aligned(canvas, 11, 0, AlignLeft, AlignTop, "Initialise Perhipheral"); + show(canvas, 0, 0, &img_key_U, SHOW_SET_BLK); + canvas_draw_str_aligned(canvas, 11, 0, AlignLeft, AlignTop, "Initialise Perhipheral"); - show(canvas, 0,11, &img_key_OK, SHOW_SET_BLK); - canvas_draw_str_aligned(canvas, 11,11, AlignLeft, AlignTop, "Read values [see log]"); + show(canvas, 0, 11, &img_key_OK, SHOW_SET_BLK); + canvas_draw_str_aligned(canvas, 11, 11, AlignLeft, AlignTop, "Read values [see log]"); - show(canvas, 0,23, &img_key_D, SHOW_SET_BLK); - canvas_draw_str_aligned(canvas, 11,22, AlignLeft, AlignTop, "Restart Scanner"); + show(canvas, 0, 23, &img_key_D, SHOW_SET_BLK); + canvas_draw_str_aligned(canvas, 11, 22, AlignLeft, AlignTop, "Restart Scanner"); - show(canvas, 0,33, &img_key_Back, SHOW_SET_BLK); - canvas_draw_str_aligned(canvas, 11,33, AlignLeft, AlignTop, "Exit"); + show(canvas, 0, 33, &img_key_Back, SHOW_SET_BLK); + canvas_draw_str_aligned(canvas, 11, 33, AlignLeft, AlignTop, "Exit"); - break ; + break; - //--------------------------------------------------------------------- - default: - if (state->ec.pidx >= PID_ERROR) { - ERROR("%s : bad PID = %d", __func__, state->ec.pidx); - } else { - if ((state->scene == SCENE_DUMP) || !ecId[state->ec.pidx].show) - ecId[PID_UNKNOWN].show(canvas, state); - else - ecId[state->ec.pidx].show(canvas, state); - } - break; - } + //--------------------------------------------------------------------- + default: + if(state->ec.pidx >= PID_ERROR) { + ERROR("%s : bad PID = %d", __func__, state->ec.pidx); + } else { + if((state->scene == SCENE_DUMP) || !ecId[state->ec.pidx].show) + ecId[PID_UNKNOWN].show(canvas, state); + else + ecId[state->ec.pidx].show(canvas, state); + } + break; + } - // Release the mutex - release_mutex((ValueMutex*)ctx, state); + // Release the mutex + release_mutex((ValueMutex*)ctx, state); - LEAVE; - return; + LEAVE; + return; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -207,56 +199,54 @@ void cbDraw (Canvas* const canvas, void* ctx) //+============================================================================ ======================================== // Initialise plugin state variables // -static inline -bool stateInit (state_t* const state) -{ - ENTER; - furi_assert(state); +static inline bool stateInit(state_t* const state) { + ENTER; + furi_assert(state); - bool rv = true; // assume success + bool rv = true; // assume success - // Enable the main loop - state->run = true; + // Enable the main loop + state->run = true; - // Timer - state->timerEn = false; - state->timer = NULL; - state->timerHz = furi_kernel_get_tick_frequency(); - state->fps = 30; + // Timer + state->timerEn = false; + state->timer = NULL; + state->timerHz = furi_kernel_get_tick_frequency(); + state->fps = 30; - // Scene - state->scene = SCENE_SPLASH; - state->scenePrev = SCENE_NONE; - state->scenePegg = SCENE_NONE; + // Scene + state->scene = SCENE_SPLASH; + state->scenePrev = SCENE_NONE; + state->scenePegg = SCENE_NONE; - state->hold = 0; // show hold meters (-1=lowest, 0=current, +1=highest} - state->calib = CAL_TRACK; - state->pause = false; // animation running - state->apause = false; // auto-pause animation + state->hold = 0; // show hold meters (-1=lowest, 0=current, +1=highest} + state->calib = CAL_TRACK; + state->pause = false; // animation running + state->apause = false; // auto-pause animation - // Notifications - state->notify = NULL; + // Notifications + state->notify = NULL; - // Perhipheral - state->ec.init = false; - state->ec.pidx = PID_UNKNOWN; - state->ec.sid = ecId[state->ec.pidx].name; + // Perhipheral + state->ec.init = false; + state->ec.pidx = PID_UNKNOWN; + state->ec.sid = ecId[state->ec.pidx].name; - // Controller data - memset(state->ec.pid, 0xC5, PID_LEN); // Cyborg 5ystems - memset(state->ec.calF, 0xC5, CAL_LEN); - memset(state->ec.joy, 0xC5, JOY_LEN); + // Controller data + memset(state->ec.pid, 0xC5, PID_LEN); // Cyborg 5ystems + memset(state->ec.calF, 0xC5, CAL_LEN); + memset(state->ec.joy, 0xC5, JOY_LEN); - // Encryption details - state->ec.encrypt = false; - memset(state->ec.encKey, 0x00, ENC_LEN); + // Encryption details + state->ec.encrypt = false; + memset(state->ec.encKey, 0x00, ENC_LEN); - // Seed the PRNG - // CYCCNT --> lib/STM32CubeWB/Drivers/CMSIS/Include/core_cm7.h -// srand(DWT->CYCCNT); + // Seed the PRNG + // CYCCNT --> lib/STM32CubeWB/Drivers/CMSIS/Include/core_cm7.h + // srand(DWT->CYCCNT); - LEAVE; - return rv; + LEAVE; + return rv; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -270,271 +260,284 @@ bool stateInit (state_t* const state) //+============================================================================ ======================================== // Enable/Disable scanning // -void timerEn (state_t* state, bool on) -{ - ENTER; - furi_assert(state); +void timerEn(state_t* state, bool on) { + ENTER; + furi_assert(state); - // ENable scanning - if (on) { - if (state->timerEn) { - WARN(wii_errs[WARN_SCAN_START]); - } else { - // Set the timer to fire at 'fps' times/second - if (furi_timer_start(state->timer, state->timerHz/state->fps) == FuriStatusOk) { - state->timerEn = true; - INFO("%s : monitor started", __func__); - } else { - ERROR(wii_errs[ERR_TIMER_START]); - } - } + // ENable scanning + if(on) { + if(state->timerEn) { + WARN(wii_errs[WARN_SCAN_START]); + } else { + // Set the timer to fire at 'fps' times/second + if(furi_timer_start(state->timer, state->timerHz / state->fps) == FuriStatusOk) { + state->timerEn = true; + INFO("%s : monitor started", __func__); + } else { + ERROR(wii_errs[ERR_TIMER_START]); + } + } - // DISable scanning - } else { - if (!state->timerEn) { - WARN(wii_errs[WARN_SCAN_STOP]); - } else { - // Stop the timer - if (furi_timer_stop(state->timer) == FuriStatusOk) { - state->timerEn = false; - INFO("%s : monitor stopped", __func__); - } else { - ERROR(wii_errs[ERR_TIMER_STOP]); - } - } - } + // DISable scanning + } else { + if(!state->timerEn) { + WARN(wii_errs[WARN_SCAN_STOP]); + } else { + // Stop the timer + if(furi_timer_stop(state->timer) == FuriStatusOk) { + state->timerEn = false; + INFO("%s : monitor stopped", __func__); + } else { + ERROR(wii_errs[ERR_TIMER_STOP]); + } + } + } - LEAVE; - return; + LEAVE; + return; } //+============================================================================ ======================================== // Plugin entry point // -int32_t wii_ec_anal (void) -{ - ENTER; +int32_t wii_ec_anal(void) { + ENTER; - // ===== Variables ===== - err_t error = 0; // assume success - Gui* gui = NULL; - ViewPort* vpp = NULL; - state_t* state = NULL; - ValueMutex mutex = {0}; - FuriMessageQueue* queue = NULL; - const uint32_t queueSz = 20; // maximum messages in queue - uint32_t tmo = (3.5f *1000); // timeout splash screen after N seconds + // ===== Variables ===== + err_t error = 0; // assume success + Gui* gui = NULL; + ViewPort* vpp = NULL; + state_t* state = NULL; + ValueMutex mutex = {0}; + FuriMessageQueue* queue = NULL; + const uint32_t queueSz = 20; // maximum messages in queue + uint32_t tmo = (3.5f * 1000); // timeout splash screen after N seconds - // The queue will contain plugin event-messages - // --> local - eventMsg_t msg = {0}; + // The queue will contain plugin event-messages + // --> local + eventMsg_t msg = {0}; - INFO("BEGIN"); + INFO("BEGIN"); - // ===== Message queue ===== - // 1. Create a message queue (for up to 8 (keyboard) event messages) - if ( !(queue = furi_message_queue_alloc(queueSz, sizeof(msg))) ) { - ERROR(wii_errs[(error = ERR_MALLOC_QUEUE)]); - goto bail; - } + // ===== Message queue ===== + // 1. Create a message queue (for up to 8 (keyboard) event messages) + if(!(queue = furi_message_queue_alloc(queueSz, sizeof(msg)))) { + ERROR(wii_errs[(error = ERR_MALLOC_QUEUE)]); + goto bail; + } - // ===== Create GUI Interface ===== - // 2. Create a GUI interface - if ( !(gui = furi_record_open("gui")) ) { - ERROR(wii_errs[(error = ERR_NO_GUI)]); - goto bail; - } + // ===== Create GUI Interface ===== + // 2. Create a GUI interface + if(!(gui = furi_record_open("gui"))) { + ERROR(wii_errs[(error = ERR_NO_GUI)]); + goto bail; + } - // ===== Plugin state variables ===== - // 3. Allocate space on the heap for the plugin state variables - if ( !(state = malloc(sizeof(state_t))) ) { - ERROR(wii_errs[(error = ERR_MALLOC_STATE)]); - goto bail; - } - // 4. Initialise the plugin state variables - if (!stateInit(state)) { - // error message(s) is/are output by stateInit() - error = 15; - goto bail; - } - // 5. Create a mutex for (reading/writing) the plugin state variables - if (!init_mutex(&mutex, state, sizeof(state))) { - ERROR(wii_errs[(error = ERR_NO_MUTEX)]); - goto bail; - } + // ===== Plugin state variables ===== + // 3. Allocate space on the heap for the plugin state variables + if(!(state = malloc(sizeof(state_t)))) { + ERROR(wii_errs[(error = ERR_MALLOC_STATE)]); + goto bail; + } + // 4. Initialise the plugin state variables + if(!stateInit(state)) { + // error message(s) is/are output by stateInit() + error = 15; + goto bail; + } + // 5. Create a mutex for (reading/writing) the plugin state variables + if(!init_mutex(&mutex, state, sizeof(state))) { + ERROR(wii_errs[(error = ERR_NO_MUTEX)]); + goto bail; + } - // ===== Viewport ===== - // 6. Allocate space on the heap for the viewport - if ( !(vpp = view_port_alloc()) ) { - ERROR(wii_errs[(error = ERR_MALLOC_VIEW)]); - goto bail; - } - // 7a. Register a callback for input events - view_port_input_callback_set(vpp, cbInput, queue); - // 7b. Register a callback for draw events - view_port_draw_callback_set(vpp, cbDraw, &mutex); + // ===== Viewport ===== + // 6. Allocate space on the heap for the viewport + if(!(vpp = view_port_alloc())) { + ERROR(wii_errs[(error = ERR_MALLOC_VIEW)]); + goto bail; + } + // 7a. Register a callback for input events + view_port_input_callback_set(vpp, cbInput, queue); + // 7b. Register a callback for draw events + view_port_draw_callback_set(vpp, cbDraw, &mutex); - // ===== Start GUI Interface ===== - // 8. Attach the viewport to the GUI - gui_add_view_port(gui, vpp, GuiLayerFullscreen); + // ===== Start GUI Interface ===== + // 8. Attach the viewport to the GUI + gui_add_view_port(gui, vpp, GuiLayerFullscreen); - // ===== Timer ===== - // 9. Allocate a timer - if ( !(state->timer = furi_timer_alloc(cbTimer, FuriTimerTypePeriodic, queue)) ) { - ERROR(wii_errs[(error = ERR_NO_TIMER)]); - goto bail; - } + // ===== Timer ===== + // 9. Allocate a timer + if(!(state->timer = furi_timer_alloc(cbTimer, FuriTimerTypePeriodic, queue))) { + ERROR(wii_errs[(error = ERR_NO_TIMER)]); + goto bail; + } - // === System Notifications === - // 10. Acquire a handle for the system notification queue - if ( !(state->notify = furi_record_open(RECORD_NOTIFICATION)) ) { - ERROR(wii_errs[(error = ERR_NO_NOTIFY)]); - goto bail; - } - patBacklight(state); // Turn on the backlight [qv. remote FAP launch] + // === System Notifications === + // 10. Acquire a handle for the system notification queue + if(!(state->notify = furi_record_open(RECORD_NOTIFICATION))) { + ERROR(wii_errs[(error = ERR_NO_NOTIFY)]); + goto bail; + } + patBacklight(state); // Turn on the backlight [qv. remote FAP launch] - INFO("INITIALISED"); + INFO("INITIALISED"); - // ==================== Main event loop ==================== + // ==================== Main event loop ==================== - if (state->run) do { - bool redraw = false; - FuriStatus status = FuriStatusErrorTimeout; + if(state->run) do { + bool redraw = false; + FuriStatus status = FuriStatusErrorTimeout; - // Wait for a message -// while ((status = furi_message_queue_get(queue, &msg, tmo)) == FuriStatusErrorTimeout) ; - status = furi_message_queue_get(queue, &msg, tmo); + // Wait for a message + // while ((status = furi_message_queue_get(queue, &msg, tmo)) == FuriStatusErrorTimeout) ; + status = furi_message_queue_get(queue, &msg, tmo); - // Clear splash screen - if ( (state->scene == SCENE_SPLASH) && (state->scenePrev == SCENE_NONE) && // Initial splash - ( (status == FuriStatusErrorTimeout) || // timeout - ((msg.id == EVID_KEY) && (msg.input.type == InputTypeShort)) ) // or key-short - ) { - tmo = 60 *1000; // increase message-wait timeout to 60secs - timerEn(state, true); // start scanning the i2c bus - status = FuriStatusOk; // pass status check - msg.id = EVID_NONE; // valid msg ID - sceneSet(state, SCENE_WAIT); // move to wait screen - } + // Clear splash screen + if((state->scene == SCENE_SPLASH) && + (state->scenePrev == SCENE_NONE) && // Initial splash + ((status == FuriStatusErrorTimeout) || // timeout + ((msg.id == EVID_KEY) && (msg.input.type == InputTypeShort))) // or key-short + ) { + tmo = 60 * 1000; // increase message-wait timeout to 60secs + timerEn(state, true); // start scanning the i2c bus + status = FuriStatusOk; // pass status check + msg.id = EVID_NONE; // valid msg ID + sceneSet(state, SCENE_WAIT); // move to wait screen + } - // Check for queue errors - if (status != FuriStatusOk) { - switch (status) { - case FuriStatusErrorTimeout: DEBUG(wii_errs[DEBUG_QUEUE_TIMEOUT]); continue ; - case FuriStatusError: ERROR(wii_errs[(error = ERR_QUEUE_RTOS)]); goto bail ; - case FuriStatusErrorResource: ERROR(wii_errs[(error = ERR_QUEUE_RESOURCE)]); goto bail ; - case FuriStatusErrorParameter: ERROR(wii_errs[(error = ERR_QUEUE_BADPRM)]); goto bail ; - case FuriStatusErrorNoMemory: ERROR(wii_errs[(error = ERR_QUEUE_NOMEM)]); goto bail ; - case FuriStatusErrorISR: ERROR(wii_errs[(error = ERR_QUEUE_ISR)]); goto bail ; - default: ERROR(wii_errs[(error = ERR_QUEUE_UNK)]); goto bail ; - } - } - // Read successful + // Check for queue errors + if(status != FuriStatusOk) { + switch(status) { + case FuriStatusErrorTimeout: + DEBUG(wii_errs[DEBUG_QUEUE_TIMEOUT]); + continue; + case FuriStatusError: + ERROR(wii_errs[(error = ERR_QUEUE_RTOS)]); + goto bail; + case FuriStatusErrorResource: + ERROR(wii_errs[(error = ERR_QUEUE_RESOURCE)]); + goto bail; + case FuriStatusErrorParameter: + ERROR(wii_errs[(error = ERR_QUEUE_BADPRM)]); + goto bail; + case FuriStatusErrorNoMemory: + ERROR(wii_errs[(error = ERR_QUEUE_NOMEM)]); + goto bail; + case FuriStatusErrorISR: + ERROR(wii_errs[(error = ERR_QUEUE_ISR)]); + goto bail; + default: + ERROR(wii_errs[(error = ERR_QUEUE_UNK)]); + goto bail; + } + } + // Read successful - // *** Try to lock the plugin state variables *** - if ( !(state = (state_t*)acquire_mutex_block(&mutex)) ) { - ERROR(wii_errs[(error = ERR_MUTEX_BLOCK)]); - goto bail; - } + // *** Try to lock the plugin state variables *** + if(!(state = (state_t*)acquire_mutex_block(&mutex))) { + ERROR(wii_errs[(error = ERR_MUTEX_BLOCK)]); + goto bail; + } - // *** Handle events *** - switch (msg.id) { - //--------------------------------------------- - case EVID_TICK: // Timer events - //! I would prefer to have ecPoll() called by cbTimer() - //! ...but how does cbTimer() get the required access to the state variables? Namely: 'state->ec' - //! So, for now, the timer pushes a message to call ecPoll() - //! which, in turn, will push WIIEC event meesages! - ecPoll(&state->ec, queue); - break; + // *** Handle events *** + switch(msg.id) { + //--------------------------------------------- + case EVID_TICK: // Timer events + //! I would prefer to have ecPoll() called by cbTimer() + //! ...but how does cbTimer() get the required access to the state variables? Namely: 'state->ec' + //! So, for now, the timer pushes a message to call ecPoll() + //! which, in turn, will push WIIEC event meesages! + ecPoll(&state->ec, queue); + break; - //--------------------------------------------- - case EVID_WIIEC: // WiiMote Perhipheral - if (evWiiEC(&msg, state)) redraw = true ; - break; + //--------------------------------------------- + case EVID_WIIEC: // WiiMote Perhipheral + if(evWiiEC(&msg, state)) redraw = true; + break; - //--------------------------------------------- - case EVID_KEY: // Key events - patBacklight(state); - if (evKey(&msg, state)) redraw = true; - break; + //--------------------------------------------- + case EVID_KEY: // Key events + patBacklight(state); + if(evKey(&msg, state)) redraw = true; + break; - //--------------------------------------------- - case EVID_NONE: - break; + //--------------------------------------------- + case EVID_NONE: + break; - //--------------------------------------------- - default: // Unknown event - WARN("Unknown message.ID [%d]", msg.id); - break; - } + //--------------------------------------------- + default: // Unknown event + WARN("Unknown message.ID [%d]", msg.id); + break; + } - // *** Update the GUI screen via the viewport *** - if (redraw) view_port_update(vpp) ; + // *** Update the GUI screen via the viewport *** + if(redraw) view_port_update(vpp); - // *** Try to release the plugin state variables *** - if ( !release_mutex(&mutex, state) ) { - ERROR(wii_errs[(error = ERR_MUTEX_RELEASE)]); - goto bail; - } - } while (state->run); + // *** Try to release the plugin state variables *** + if(!release_mutex(&mutex, state)) { + ERROR(wii_errs[(error = ERR_MUTEX_RELEASE)]); + goto bail; + } + } while(state->run); - // ===== Game Over ===== - INFO("USER EXIT"); + // ===== Game Over ===== + INFO("USER EXIT"); bail: - // 10. Release system notification queue - if (state->notify) { - furi_record_close(RECORD_NOTIFICATION); - state->notify = NULL; - } + // 10. Release system notification queue + if(state->notify) { + furi_record_close(RECORD_NOTIFICATION); + state->notify = NULL; + } - // 9. Stop the timer - if (state->timer) { - (void)furi_timer_stop(state->timer); - furi_timer_free(state->timer); - state->timer = NULL; - state->timerEn = false; - } + // 9. Stop the timer + if(state->timer) { + (void)furi_timer_stop(state->timer); + furi_timer_free(state->timer); + state->timer = NULL; + state->timerEn = false; + } - // 8. Detach the viewport - gui_remove_view_port(gui, vpp); + // 8. Detach the viewport + gui_remove_view_port(gui, vpp); - // 7. No need to unreqgister the callbacks - // ...they will go when the viewport is destroyed + // 7. No need to unreqgister the callbacks + // ...they will go when the viewport is destroyed - // 6. Destroy the viewport - if (vpp) { - view_port_enabled_set(vpp, false); - view_port_free(vpp); - vpp = NULL; - } + // 6. Destroy the viewport + if(vpp) { + view_port_enabled_set(vpp, false); + view_port_free(vpp); + vpp = NULL; + } - // 5. Free the mutex - if (mutex.mutex) { - delete_mutex(&mutex); - mutex.mutex = NULL; - } + // 5. Free the mutex + if(mutex.mutex) { + delete_mutex(&mutex); + mutex.mutex = NULL; + } - // 4. Free up state pointer(s) - // none + // 4. Free up state pointer(s) + // none - // 3. Free the plugin state variables - if (state) { - free(state); - state = NULL; - } + // 3. Free the plugin state variables + if(state) { + free(state); + state = NULL; + } - // 2. Close the GUI - furi_record_close("gui"); + // 2. Close the GUI + furi_record_close("gui"); - // 1. Destroy the message queue - if (queue) { - furi_message_queue_free(queue); - queue = NULL; - } + // 1. Destroy the message queue + if(queue) { + furi_message_queue_free(queue); + queue = NULL; + } - INFO("CLEAN EXIT ... Exit code: %d", error); - LEAVE; - return (int32_t)error; + INFO("CLEAN EXIT ... Exit code: %d", error); + LEAVE; + return (int32_t)error; } diff --git a/applications/plugins/wii_ec_anal/wii_anal.h b/applications/plugins/wii_ec_anal/wii_anal.h index ac7ffddb1..3aae61fdc 100644 --- a/applications/plugins/wii_ec_anal/wii_anal.h +++ b/applications/plugins/wii_ec_anal/wii_anal.h @@ -1,97 +1,89 @@ -#ifndef WII_ANAL_H_ -#define WII_ANAL_H_ +#ifndef WII_ANAL_H_ +#define WII_ANAL_H_ -#include // Core API -#include // GUI Input extensions -#include +#include // Core API +#include // GUI Input extensions +#include //----------------------------------------------------------------------------- ---------------------------------------- // GUI scenes // -typedef - enum scene { - SCENE_NONE = 0, - SCENE_SPLASH = 1, - SCENE_RIP = 2, - SCENE_WAIT = 3, - SCENE_DEBUG = 4, - SCENE_DUMP = 5, - SCENE_CLASSIC = 6, - SCENE_CLASSIC_N = 7, - SCENE_NUNCHUCK = 8, - SCENE_NUNCHUCK_ACC = 9, - } -scene_t; +typedef enum scene { + SCENE_NONE = 0, + SCENE_SPLASH = 1, + SCENE_RIP = 2, + SCENE_WAIT = 3, + SCENE_DEBUG = 4, + SCENE_DUMP = 5, + SCENE_CLASSIC = 6, + SCENE_CLASSIC_N = 7, + SCENE_NUNCHUCK = 8, + SCENE_NUNCHUCK_ACC = 9, +} scene_t; //----------------------------------------------------------------------------- ---------------------------------------- -#include "wii_i2c.h" -#include "wii_ec.h" +#include "wii_i2c.h" +#include "wii_ec.h" //----------------------------------------------------------------------------- ---------------------------------------- // A list of event IDs handled by this plugin // -typedef - enum eventID { - EVID_NONE, - EVID_UNKNOWN, +typedef enum eventID { + EVID_NONE, + EVID_UNKNOWN, - // A full list of events can be found with: `grep -r --color "void.*set_.*_callback" applications/gui/*` - // ...A free gift to you from the makers of well written code that conforms to a good coding standard - EVID_KEY, // keypad - EVID_TICK, // tick - EVID_WIIEC, // wii extension controller - } -eventID_t; + // A full list of events can be found with: `grep -r --color "void.*set_.*_callback" applications/gui/*` + // ...A free gift to you from the makers of well written code that conforms to a good coding standard + EVID_KEY, // keypad + EVID_TICK, // tick + EVID_WIIEC, // wii extension controller +} eventID_t; //----------------------------------------------------------------------------- ---------------------------------------- // An item in the event message-queue // -typedef - struct eventMsg { - eventID_t id; - union { - InputEvent input; // --> applications/input/input.h - wiiEcEvent_t wiiEc; // --> local - }; - } -eventMsg_t; +typedef struct eventMsg { + eventID_t id; + union { + InputEvent input; // --> applications/input/input.h + wiiEcEvent_t wiiEc; // --> local + }; +} eventMsg_t; //----------------------------------------------------------------------------- ---------------------------------------- // State variables for this plugin // An instance of this is allocated on the heap, and the pointer is passed back to the OS // Access to this memory is controlled by mutex // -typedef - struct state { - bool run; // true : plugin is running +typedef struct state { + bool run; // true : plugin is running - bool timerEn; // controller scanning enabled - FuriTimer* timer; // the timer - uint32_t timerHz; // system ticks per second - int fps; // poll/refresh [frames]-per-second + bool timerEn; // controller scanning enabled + FuriTimer* timer; // the timer + uint32_t timerHz; // system ticks per second + int fps; // poll/refresh [frames]-per-second - int cnvW; // canvas width - int cnvH; // canvas height - scene_t scene; // current scene - scene_t scenePrev; // previous scene - scene_t scenePegg; // previous scene for easter eggs - int flash; // flash counter (flashing icons) + int cnvW; // canvas width + int cnvH; // canvas height + scene_t scene; // current scene + scene_t scenePrev; // previous scene + scene_t scenePegg; // previous scene for easter eggs + int flash; // flash counter (flashing icons) - int hold; // hold type: {-1=tough-peak, 0=none, +1=peak-hold} - ecCalib_t calib; // Software calibration mode + int hold; // hold type: {-1=tough-peak, 0=none, +1=peak-hold} + ecCalib_t calib; // Software calibration mode - bool pause; // Accelerometer animation pause - bool apause; // Accelerometer animation auto-pause + bool pause; // Accelerometer animation pause + bool apause; // Accelerometer animation auto-pause - NotificationApp* notify; // OS nitifcation queue (for patting the backlight watchdog timer) + NotificationApp* notify; // OS nitifcation queue (for patting the backlight watchdog timer) - wiiEC_t ec; // Extension Controller details - } -state_t; + wiiEC_t ec; // Extension Controller details +} state_t; //============================================================================= ======================================== // Function prototypes // -void timerEn (state_t* state, bool on) ; +void timerEn(state_t* state, bool on); #endif //WII_ANAL_H_ diff --git a/applications/plugins/wii_ec_anal/wii_anal_ec.c b/applications/plugins/wii_ec_anal/wii_anal_ec.c index 0bfa47362..dab167bc0 100644 --- a/applications/plugins/wii_ec_anal/wii_anal_ec.c +++ b/applications/plugins/wii_ec_anal/wii_anal_ec.c @@ -1,97 +1,115 @@ -#include -#include +#include +#include -#include "wii_anal.h" -#include "wii_anal_lcd.h" -#include "wii_anal_keys.h" +#include "wii_anal.h" +#include "wii_anal_lcd.h" +#include "wii_anal_keys.h" //+============================================================================ ======================================== // Handle Wii Extension Controller events // -bool evWiiEC (const eventMsg_t* const msg, state_t* const state) -{ - bool redraw = false; +bool evWiiEC(const eventMsg_t* const msg, state_t* const state) { + bool redraw = false; -# if LOG_LEVEL >= 4 - { - const char* s = NULL; - switch (msg->wiiEc.type) { - case WIIEC_NONE: s = "Error"; break ; - case WIIEC_CONN: s = "Connect"; break ; - case WIIEC_DISCONN: s = "Disconnect"; break ; - case WIIEC_PRESS: s = "Press"; break ; - case WIIEC_RELEASE: s = "Release"; break ; - case WIIEC_ANALOG: s = "Analog"; break ; - case WIIEC_ACCEL: s = "Accel"; break ; - default: s = "Bug"; break ; - } - INFO("WIIP : %s '%c' = %d", s, (isprint((int)msg->wiiEc.in) ? msg->wiiEc.in : '_'), msg->wiiEc.val); - if ((msg->wiiEc.type == WIIEC_CONN) || (msg->wiiEc.type == WIIEC_DISCONN)) - INFO("...%d=\"%s\"", msg->wiiEc.val, ecId[msg->wiiEc.val].name); - } -# endif - - switch (msg->wiiEc.type) { - case WIIEC_CONN: - patBacklight(state); - state->hold = 0; - state->calib = CAL_TRACK; - sceneSet(state, ecId[msg->wiiEc.val].scene); - redraw = true ; - -#if 1 // Workaround for Classic Controller Pro, which shows 00's for Factory Calibration Data!? - if (state->ec.pidx == PID_CLASSIC_PRO) { - // Simulate a Long-OK keypress, to start Software Calibration mode - eventMsg_t msg = { -// .id = EVID_KEY, - .input.type = InputTypeLong, - .input.key = InputKeyOk - }; - key_calib(&msg, state); - } +#if LOG_LEVEL >= 4 + { + const char* s = NULL; + switch(msg->wiiEc.type) { + case WIIEC_NONE: + s = "Error"; + break; + case WIIEC_CONN: + s = "Connect"; + break; + case WIIEC_DISCONN: + s = "Disconnect"; + break; + case WIIEC_PRESS: + s = "Press"; + break; + case WIIEC_RELEASE: + s = "Release"; + break; + case WIIEC_ANALOG: + s = "Analog"; + break; + case WIIEC_ACCEL: + s = "Accel"; + break; + default: + s = "Bug"; + break; + } + INFO( + "WIIP : %s '%c' = %d", + s, + (isprint((int)msg->wiiEc.in) ? msg->wiiEc.in : '_'), + msg->wiiEc.val); + if((msg->wiiEc.type == WIIEC_CONN) || (msg->wiiEc.type == WIIEC_DISCONN)) + INFO("...%d=\"%s\"", msg->wiiEc.val, ecId[msg->wiiEc.val].name); + } #endif - break; - case WIIEC_DISCONN: - patBacklight(state); - sceneSet(state, SCENE_WAIT); - redraw = true; - break; + switch(msg->wiiEc.type) { + case WIIEC_CONN: + patBacklight(state); + state->hold = 0; + state->calib = CAL_TRACK; + sceneSet(state, ecId[msg->wiiEc.val].scene); + redraw = true; - case WIIEC_PRESS: - if (state->scene == SCENE_NUNCHUCK_ACC) switch (msg->wiiEc.in) { - case 'z': // un-pause - state->pause = !state->pause; - break; - case 'c': // toggle auto-pause - state->pause = false; - state->apause = !state->apause; - break; - default: break ; - } - -#if 1 //! factory calibration method not known for classic triggers - this will set the digital switch point - if ((state->ec.pidx == PID_CLASSIC) || (state->ec.pidx == PID_CLASSIC_PRO)) { - if (msg->wiiEc.in == 'l') state->ec.calS.classic[2].trgZL = msg->wiiEc.val ; - if (msg->wiiEc.in == 'r') state->ec.calS.classic[2].trgZR = msg->wiiEc.val ; - } +#if 1 // Workaround for Classic Controller Pro, which shows 00's for Factory Calibration Data!? + if(state->ec.pidx == PID_CLASSIC_PRO) { + // Simulate a Long-OK keypress, to start Software Calibration mode + eventMsg_t msg = {// .id = EVID_KEY, + .input.type = InputTypeLong, + .input.key = InputKeyOk}; + key_calib(&msg, state); + } #endif - __attribute__ ((fallthrough)); + break; - case WIIEC_RELEASE: - patBacklight(state); - redraw = true; - break; + case WIIEC_DISCONN: + patBacklight(state); + sceneSet(state, SCENE_WAIT); + redraw = true; + break; - case WIIEC_ANALOG: - case WIIEC_ACCEL: - ecCalibrate(&state->ec, state->calib); - redraw = true; - break; + case WIIEC_PRESS: + if(state->scene == SCENE_NUNCHUCK_ACC) switch(msg->wiiEc.in) { + case 'z': // un-pause + state->pause = !state->pause; + break; + case 'c': // toggle auto-pause + state->pause = false; + state->apause = !state->apause; + break; + default: + break; + } - default: - break; - } +#if 1 //! factory calibration method not known for classic triggers - this will set the digital switch point + if((state->ec.pidx == PID_CLASSIC) || (state->ec.pidx == PID_CLASSIC_PRO)) { + if(msg->wiiEc.in == 'l') state->ec.calS.classic[2].trgZL = msg->wiiEc.val; + if(msg->wiiEc.in == 'r') state->ec.calS.classic[2].trgZR = msg->wiiEc.val; + } +#endif + __attribute__((fallthrough)); - return redraw; + case WIIEC_RELEASE: + patBacklight(state); + redraw = true; + break; + + case WIIEC_ANALOG: + case WIIEC_ACCEL: + ecCalibrate(&state->ec, state->calib); + redraw = true; + break; + + default: + break; + } + + return redraw; } diff --git a/applications/plugins/wii_ec_anal/wii_anal_ec.h b/applications/plugins/wii_ec_anal/wii_anal_ec.h index 886b60281..eec6b523c 100644 --- a/applications/plugins/wii_ec_anal/wii_anal_ec.h +++ b/applications/plugins/wii_ec_anal/wii_anal_ec.h @@ -1,14 +1,14 @@ -#ifndef WII_ANAL_EC_H_ -#define WII_ANAL_EC_H_ +#ifndef WII_ANAL_EC_H_ +#define WII_ANAL_EC_H_ -#include +#include //============================================================================= ======================================== // Function prototypes // -typedef struct eventMsg eventMsg_t ; -typedef struct state state_t ; +typedef struct eventMsg eventMsg_t; +typedef struct state state_t; -bool evWiiEC (const eventMsg_t* const msg, state_t* const state) ; +bool evWiiEC(const eventMsg_t* const msg, state_t* const state); #endif //WII_ANAL_EC_H_ diff --git a/applications/plugins/wii_ec_anal/wii_anal_keys.c b/applications/plugins/wii_ec_anal/wii_anal_keys.c index 3d2fae14a..2a446efb6 100644 --- a/applications/plugins/wii_ec_anal/wii_anal_keys.c +++ b/applications/plugins/wii_ec_anal/wii_anal_keys.c @@ -1,40 +1,35 @@ -#include +#include -#include "bc_logging.h" +#include "bc_logging.h" -#include "wii_anal.h" +#include "wii_anal.h" //+============================================================================ ======================================== // Stop Calibration mode // -static -void calStop (state_t* const state) -{ - state->hold = 0; // stop calibration mode - state->calib &= ~(CAL_RANGE | CAL_NOTJOY); // ... +static void calStop(state_t* const state) { + state->hold = 0; // stop calibration mode + state->calib &= ~(CAL_RANGE | CAL_NOTJOY); // ... } //+============================================================================ ======================================== // Change to another scene // -void sceneSet (state_t* const state, const scene_t scene) -{ - calStop(state); // Stop software calibration - state->scenePrev = state->scene; // Remember where we came from - state->scene = scene; // Go to new scene - INFO("Scene : %d -> %d", state->scenePrev, state->scene); +void sceneSet(state_t* const state, const scene_t scene) { + calStop(state); // Stop software calibration + state->scenePrev = state->scene; // Remember where we came from + state->scene = scene; // Go to new scene + INFO("Scene : %d -> %d", state->scenePrev, state->scene); } //+============================================================================ ======================================== // Change to an easter egg scene // -static -void sceneSetEgg (state_t* const state, const scene_t scene) -{ - calStop(state); // Stop software calibration - state->scenePegg = state->scene; // Remember where we came from - state->scene = scene; // Go to new scene - INFO("Scene* : %d => %d", state->scenePegg, state->scene); +static void sceneSetEgg(state_t* const state, const scene_t scene) { + calStop(state); // Stop software calibration + state->scenePegg = state->scene; // Remember where we came from + state->scene = scene; // Go to new scene + INFO("Scene* : %d => %d", state->scenePegg, state->scene); } //+============================================================================ ======================================== @@ -42,256 +37,265 @@ void sceneSetEgg (state_t* const state, const scene_t scene) // Enabling peak-hold on screen with no peak meters will have no effect // So, to avoid code duplication... // -bool key_calib (const eventMsg_t* const msg, state_t* const state) -{ - int used = false; // assume key is NOT-handled +bool key_calib(const eventMsg_t* const msg, state_t* const state) { + int used = false; // assume key is NOT-handled - switch (msg->input.type) { - case InputTypeShort: //# input.key) { - case InputKeyUp: //# hold = (state->hold == +1) ? 0 : +1 ; // toggle peak hold - used = true; - break; + switch(msg->input.type) { + case InputTypeShort: //# input.key) { + case InputKeyUp: //# hold = (state->hold == +1) ? 0 : +1; // toggle peak hold + used = true; + break; - case InputKeyDown: //# hold = (state->hold == -1) ? 0 : -1 ; // toggle trough hold - used = true; - break; + case InputKeyDown: //# hold = (state->hold == -1) ? 0 : -1; // toggle trough hold + used = true; + break; - case InputKeyOk: //# calib & CAL_RANGE) calStop(state) ; // STOP softare calibration - else ecCalibrate(&state->ec, CAL_CENTRE) ; // perform centre calibration - used = true; - break; + case InputKeyOk: //# calib & CAL_RANGE) + calStop(state); // STOP softare calibration + else + ecCalibrate(&state->ec, CAL_CENTRE); // perform centre calibration + used = true; + break; - default: break ; - } - break; + default: + break; + } + break; - case InputTypeLong: //# >! After INPUT_LONG_PRESS interval, asynch to InputTypeRelease - switch (msg->input.key) { - case InputKeyOk: //# >O [ LONG-OK ] - ecCalibrate(&state->ec, CAL_RESET | CAL_CENTRE); // START software calibration - state->hold = 0; - state->calib |= CAL_RANGE; - state->flash = 8; // start with flash ON - used = true; - break; + case InputTypeLong: //# >! After INPUT_LONG_PRESS interval, asynch to InputTypeRelease + switch(msg->input.key) { + case InputKeyOk: //# >O [ LONG-OK ] + ecCalibrate(&state->ec, CAL_RESET | CAL_CENTRE); // START software calibration + state->hold = 0; + state->calib |= CAL_RANGE; + state->flash = 8; // start with flash ON + used = true; + break; - default: break ; - } - break; + default: + break; + } + break; - default: break ; - } + default: + break; + } - return used; + return used; } //+============================================================================ ======================================== // WAIT screen // -static inline -bool wait_key (const eventMsg_t* const msg, state_t* const state) -{ - int used = false; // assume key is NOT-handled +static inline bool wait_key(const eventMsg_t* const msg, state_t* const state) { + int used = false; // assume key is NOT-handled - if (msg->input.type == InputTypeShort) { - switch (msg->input.key) { - case InputKeyLeft: //# input.type == InputTypeShort) { + switch(msg->input.key) { + case InputKeyLeft: //# run = false; - used = true; - break; + case InputKeyBack: //# run = false; + used = true; + break; - default: break ; - } - } + default: + break; + } + } - return used; + return used; } //+============================================================================ ======================================== // DEBUG screen // -static inline -bool debug_key (const eventMsg_t* const msg, state_t* const state) -{ - int used = false; // assume key is NOT-handled +static inline bool debug_key(const eventMsg_t* const msg, state_t* const state) { + int used = false; // assume key is NOT-handled - switch (msg->input.type) { - case InputTypeShort: //# input.key) { - case InputKeyUp: { //# ec, NULL); // Initialise the controller //! NULL = no encryption - (void)init; // in case INFO is optimised out - INFO("%s : %s", __func__, (init ? "init OK" : "init fail")); - used = true; - break; - } + switch(msg->input.type) { + case InputTypeShort: //# input.key) { + case InputKeyUp: { //# ec, NULL); // Initialise the controller //! NULL = no encryption + (void)init; // in case INFO is optimised out + INFO("%s : %s", __func__, (init ? "init OK" : "init fail")); + used = true; + break; + } - case InputKeyOk: //# ec) == 0) { // Read the controller - INFO( "%s : joy: {%02X,%02X,%02X,%02X,%02X,%02X}", __func__, - state->ec.joy[0], state->ec.joy[1], state->ec.joy[2], - state->ec.joy[3], state->ec.joy[4], state->ec.joy[5] ); - } - used = true; - break; + case InputKeyOk: //# ec) == 0) { // Read the controller + INFO( + "%s : joy: {%02X,%02X,%02X,%02X,%02X,%02X}", + __func__, + state->ec.joy[0], + state->ec.joy[1], + state->ec.joy[2], + state->ec.joy[3], + state->ec.joy[4], + state->ec.joy[5]); + } + used = true; + break; - case InputKeyDown: //# scenePrev); - used = true; - break; + case InputKeyDown: //# scenePrev); + used = true; + break; - case InputKeyBack: //# run = false; - used = true; - break; + case InputKeyBack: //# run = false; + used = true; + break; - default: break ; //# input.key == InputKeyBack) && (state->scenePrev == SCENE_NONE)) state->run = false ; +static inline bool splash_key(const eventMsg_t* const msg, state_t* const state) { + // Back key on the initial SPLASH screen (this will catch the InputKeyPress) + if((msg->input.key == InputKeyBack) && (state->scenePrev == SCENE_NONE)) state->run = false; - // ANY-other-KEY press - if (msg->input.type == InputTypeShort) { - timerEn(state, true); // Restart the timer - state->scene = state->scenePegg; - } + // ANY-other-KEY press + if(msg->input.type == InputTypeShort) { + timerEn(state, true); // Restart the timer + state->scene = state->scenePegg; + } - return true; + return true; } - //+============================================================================ ======================================== // "_pre" allows the plugin to use the key before the active scene gets a chance // -static inline -bool key_pre (const eventMsg_t* const msg, state_t* const state) -{ - (void)msg; - (void)state; +static inline bool key_pre(const eventMsg_t* const msg, state_t* const state) { + (void)msg; + (void)state; - return false; + return false; } //+============================================================================ ======================================== // "_post" allows the plugin to use a key if it was not used by the active scene // -static inline -bool key_post (const eventMsg_t* const msg, state_t* const state) -{ - int used = false; // assume key is NOT-handled +static inline bool key_post(const eventMsg_t* const msg, state_t* const state) { + int used = false; // assume key is NOT-handled - if (msg->input.key == InputKeyBack) { - if (msg->input.type == InputTypeShort) { //# ec.init = false; // reset/disconnect the controller - sceneSet(state, SCENE_WAIT); - used = true; + if(msg->input.key == InputKeyBack) { + if(msg->input.type == InputTypeShort) { //# ec.init = false; // reset/disconnect the controller + sceneSet(state, SCENE_WAIT); + used = true; - } else if (msg->input.type == InputTypeLong) { //# >B [LONG-BACK] - state->run = false; // Signal the plugin to exit - used = true; - } - } + } else if(msg->input.type == InputTypeLong) { //# >B [LONG-BACK] + state->run = false; // Signal the plugin to exit + used = true; + } + } - // Easter eggs - switch (state->scene) { - case SCENE_SPLASH: // Scenes that do NOT offer Easter eggs - case SCENE_RIP: - case SCENE_DEBUG: - break; - default: - if (msg->input.type == InputTypeLong) { - switch (msg->input.key) { - case InputKeyDown: //# >D [LONG-DOWN] - timerEn(state, false); // Stop the timer - sceneSetEgg(state, SCENE_DEBUG); - used = true; - break; + // Easter eggs + switch(state->scene) { + case SCENE_SPLASH: // Scenes that do NOT offer Easter eggs + case SCENE_RIP: + case SCENE_DEBUG: + break; + default: + if(msg->input.type == InputTypeLong) { + switch(msg->input.key) { + case InputKeyDown: //# >D [LONG-DOWN] + timerEn(state, false); // Stop the timer + sceneSetEgg(state, SCENE_DEBUG); + used = true; + break; - case InputKeyLeft: //# >L [ LONG-LEFT ] - timerEn(state, false); // Stop the timer - sceneSetEgg(state, SCENE_SPLASH); - used = true; - break; + case InputKeyLeft: //# >L [ LONG-LEFT ] + timerEn(state, false); // Stop the timer + sceneSetEgg(state, SCENE_SPLASH); + used = true; + break; - case InputKeyUp: //# >U [ LONG-UP ] - timerEn(state, false); // Stop the timer - sceneSetEgg(state, SCENE_RIP); - used = true; - break; + case InputKeyUp: //# >U [ LONG-UP ] + timerEn(state, false); // Stop the timer + sceneSetEgg(state, SCENE_RIP); + used = true; + break; - default: break ; - } - } - break; - } + default: + break; + } + } + break; + } - return used; + return used; } //+============================================================================ ======================================== // Handle a key press event // -bool evKey (const eventMsg_t* const msg, state_t* const state) -{ - furi_assert(msg); - furi_assert(state); +bool evKey(const eventMsg_t* const msg, state_t* const state) { + furi_assert(msg); + furi_assert(state); - bool used = key_pre(msg, state); + bool used = key_pre(msg, state); - if (!used) switch (state->scene) { - case SCENE_SPLASH: //... - case SCENE_RIP: used = splash_key(msg, state); break ; + if(!used) switch(state->scene) { + case SCENE_SPLASH: //... + case SCENE_RIP: + used = splash_key(msg, state); + break; - case SCENE_WAIT: used = wait_key(msg, state); break ; - case SCENE_DEBUG: used = debug_key(msg, state); break ; + case SCENE_WAIT: + used = wait_key(msg, state); + break; + case SCENE_DEBUG: + used = debug_key(msg, state); + break; - default: - if (state->ec.pidx >= PID_ERROR) { - ERROR("%s : bad PID = %d", __func__, state->ec.pidx); - } else { - if ((state->scene == SCENE_DUMP) || !ecId[state->ec.pidx].keys) - ecId[PID_UNKNOWN].keys(msg, state); - else - ecId[state->ec.pidx].keys(msg, state); - } - break; + default: + if(state->ec.pidx >= PID_ERROR) { + ERROR("%s : bad PID = %d", __func__, state->ec.pidx); + } else { + if((state->scene == SCENE_DUMP) || !ecId[state->ec.pidx].keys) + ecId[PID_UNKNOWN].keys(msg, state); + else + ecId[state->ec.pidx].keys(msg, state); + } + break; - case SCENE_NONE: break; - } + case SCENE_NONE: + break; + } - if (!used) used = key_post(msg, state) ; + if(!used) used = key_post(msg, state); - return used; + return used; } - diff --git a/applications/plugins/wii_ec_anal/wii_anal_keys.h b/applications/plugins/wii_ec_anal/wii_anal_keys.h index 0ebbd5e8e..c10fcd1ef 100644 --- a/applications/plugins/wii_ec_anal/wii_anal_keys.h +++ b/applications/plugins/wii_ec_anal/wii_anal_keys.h @@ -1,16 +1,16 @@ -#ifndef WII_ANAL_KEYS_H_ -#define WII_ANAL_KEYS_H_ +#ifndef WII_ANAL_KEYS_H_ +#define WII_ANAL_KEYS_H_ //============================================================================= ======================================== // Function prototypes // -#include // bool -typedef struct eventMsg eventMsg_t ; -typedef struct state state_t ; -typedef enum scene scene_t ; +#include // bool +typedef struct eventMsg eventMsg_t; +typedef struct state state_t; +typedef enum scene scene_t; -void sceneSet (state_t* const state, const scene_t scene) ; -bool key_calib (const eventMsg_t* const msg, state_t* const state) ; -bool evKey (const eventMsg_t* const msg, state_t* const state) ; +void sceneSet(state_t* const state, const scene_t scene); +bool key_calib(const eventMsg_t* const msg, state_t* const state); +bool evKey(const eventMsg_t* const msg, state_t* const state); #endif //WII_ANAL_KEYS_H_ diff --git a/applications/plugins/wii_ec_anal/wii_anal_lcd.c b/applications/plugins/wii_ec_anal/wii_anal_lcd.c index d031bc120..921a3708e 100644 --- a/applications/plugins/wii_ec_anal/wii_anal_lcd.c +++ b/applications/plugins/wii_ec_anal/wii_anal_lcd.c @@ -1,17 +1,45 @@ -#include "wii_anal.h" -#include "gfx/images.h" // Images +#include "wii_anal.h" +#include "gfx/images.h" // Images //----------------------------------------------------------------------------- ---------------------------------------- // A couple of monospaced hex fonts // -const image_t* img_6x8[16] = { - &img_6x8_0, &img_6x8_1, &img_6x8_2, &img_6x8_3, &img_6x8_4, &img_6x8_5, &img_6x8_6, &img_6x8_7, - &img_6x8_8, &img_6x8_9, &img_6x8_A, &img_6x8_B, &img_6x8_C, &img_6x8_D, &img_6x8_E, &img_6x8_F, +const image_t* img_6x8[16] = { + &img_6x8_0, + &img_6x8_1, + &img_6x8_2, + &img_6x8_3, + &img_6x8_4, + &img_6x8_5, + &img_6x8_6, + &img_6x8_7, + &img_6x8_8, + &img_6x8_9, + &img_6x8_A, + &img_6x8_B, + &img_6x8_C, + &img_6x8_D, + &img_6x8_E, + &img_6x8_F, }; -const image_t* img_5x7[16] = { - &img_5x7_0, &img_5x7_1, &img_5x7_2, &img_5x7_3, &img_5x7_4, &img_5x7_5, &img_5x7_6, &img_5x7_7, - &img_5x7_8, &img_5x7_9, &img_5x7_A, &img_5x7_B, &img_5x7_C, &img_5x7_D, &img_5x7_E, &img_5x7_F, +const image_t* img_5x7[16] = { + &img_5x7_0, + &img_5x7_1, + &img_5x7_2, + &img_5x7_3, + &img_5x7_4, + &img_5x7_5, + &img_5x7_6, + &img_5x7_7, + &img_5x7_8, + &img_5x7_9, + &img_5x7_A, + &img_5x7_B, + &img_5x7_C, + &img_5x7_D, + &img_5x7_E, + &img_5x7_F, }; //+============================================================================ ======================================== @@ -30,66 +58,71 @@ const image_t* img_5x7[16] = { // // Do this ONCE ... at plugin quit // furi_record_close(RECORD_NOTIFICATION); // } -void patBacklight (state_t* state) -{ - notification_message(state->notify, &sequence_display_backlight_on); +void patBacklight(state_t* state) { + notification_message(state->notify, &sequence_display_backlight_on); } //============================================================================= ======================================== // Show a hex number in an inverted box (for ananlogue readings) // -void showHex ( Canvas* const canvas, uint8_t x, uint8_t y, - const uint32_t val, const uint8_t cnt, const int b ) -{ - canvas_set_color(canvas, ColorBlack); - canvas_draw_box(canvas, x++,y++, 1 +(cnt *(6 +1)), 10); +void showHex( + Canvas* const canvas, + uint8_t x, + uint8_t y, + const uint32_t val, + const uint8_t cnt, + const int b) { + canvas_set_color(canvas, ColorBlack); + canvas_draw_box(canvas, x++, y++, 1 + (cnt * (6 + 1)), 10); - // thicken border - if (b == 2) canvas_draw_frame(canvas, x-2,y-2, 1 +(cnt *(6 +1))+2, 10+2); + // thicken border + if(b == 2) canvas_draw_frame(canvas, x - 2, y - 2, 1 + (cnt * (6 + 1)) + 2, 10 + 2); - for (int i = (cnt -1) *4; i >= 0; i -= 4, x += 6+1) - show(canvas, x,y, img_6x8[(val >>i) &0xF], SHOW_SET_WHT) ; + for(int i = (cnt - 1) * 4; i >= 0; i -= 4, x += 6 + 1) + show(canvas, x, y, img_6x8[(val >> i) & 0xF], SHOW_SET_WHT); } //============================================================================= ======================================== // Show the up/down "peak hold" controls in the bottom right // -void showPeakHold (state_t* const state, Canvas* const canvas, const int hold) -{ - switch (hold) { - case 0: - show(canvas, 119,51, &img_key_U, SHOW_CLR_BLK); - show(canvas, 119,56, &img_key_D, SHOW_CLR_BLK); - break; - case +1: - canvas_set_color(canvas, ColorBlack); - canvas_draw_box(canvas, 120,52, 7,6); - show(canvas, 119,51, &img_key_U, SHOW_CLR_WHT); - show(canvas, 119,56, &img_key_D, SHOW_CLR_BLK); - break; - case -1: - show(canvas, 119,51, &img_key_U, SHOW_CLR_BLK); - canvas_draw_box(canvas, 120,57, 7,6); - show(canvas, 119,56, &img_key_D, SHOW_CLR_WHT); - break; - default: - break; - } - canvas_set_color(canvas, ColorBlack); - canvas_draw_frame(canvas, 119,51, 9,13); +void showPeakHold(state_t* const state, Canvas* const canvas, const int hold) { + switch(hold) { + case 0: + show(canvas, 119, 51, &img_key_U, SHOW_CLR_BLK); + show(canvas, 119, 56, &img_key_D, SHOW_CLR_BLK); + break; + case +1: + canvas_set_color(canvas, ColorBlack); + canvas_draw_box(canvas, 120, 52, 7, 6); + show(canvas, 119, 51, &img_key_U, SHOW_CLR_WHT); + show(canvas, 119, 56, &img_key_D, SHOW_CLR_BLK); + break; + case -1: + show(canvas, 119, 51, &img_key_U, SHOW_CLR_BLK); + canvas_draw_box(canvas, 120, 57, 7, 6); + show(canvas, 119, 56, &img_key_D, SHOW_CLR_WHT); + break; + default: + break; + } + canvas_set_color(canvas, ColorBlack); + canvas_draw_frame(canvas, 119, 51, 9, 13); - // calibration indicator - show( canvas, 108,55, - ((state->calib & CAL_RANGE) && (++state->flash &8)) ? &img_key_OKi : &img_key_OK, - SHOW_SET_BLK ); + // calibration indicator + show( + canvas, + 108, + 55, + ((state->calib & CAL_RANGE) && (++state->flash & 8)) ? &img_key_OKi : &img_key_OK, + SHOW_SET_BLK); } //============================================================================= ======================================== -// This code performs a FULL calibration on the device EVERY time it draws a joystick +// This code performs a FULL calibration on the device EVERY time it draws a joystick //...This is NOT a good way forward for anything other than a test tool. // // Realistically you would do all the maths when the controller is connected -// or, if you prefer (and it IS a good thing), have a "calibrate controller" menu option +// or, if you prefer (and it IS a good thing), have a "calibrate controller" menu option // ...and then just use a lookup table, or trivial formual // // THIS algorithm chops the joystick in to one of 9 zones @@ -97,12 +130,12 @@ void showPeakHold (state_t* const state, Canvas* const canvas, const int hold // FullLeft and FullRight have a deadzone of N [qv. xDead] ..a total of N+1 positions // Middle has a deadzone of N EACH WAY ...a total of 2N+1 positions // -// If the remaining range does not divide evenly in to three zones, +// If the remaining range does not divide evenly in to three zones, // the first remainder is added to zone3, // and the second remainder (if there is one) is added to zone2 // ...giving finer control near the centre of the joystick // -// The value of the deadzone is based on the number of bits in the +// The value of the deadzone is based on the number of bits in the // joystcik {x,y} values - the larger the range, the larger the deadzone. // // 03 15 29 @@ -118,106 +151,132 @@ void showPeakHold (state_t* const state, Canvas* const canvas, const int hold // Turn and object - this is probably good enough // Start slowly & pick up speed - how about a log or sine curve? // -void showJoy ( Canvas* const canvas, const uint8_t x, const uint8_t y, // x,y is the CENTRE of the Joystick - const uint8_t xMin, const uint8_t xMid, const uint8_t xMax, - const uint8_t yMin, const uint8_t yMid, const uint8_t yMax, - const uint8_t xPos, const uint8_t yPos, const uint8_t bits ) -{ - int xOff = 0; // final offset of joystick hat image - int yOff = 0; +void showJoy( + Canvas* const canvas, + const uint8_t x, + const uint8_t y, // x,y is the CENTRE of the Joystick + const uint8_t xMin, + const uint8_t xMid, + const uint8_t xMax, + const uint8_t yMin, + const uint8_t yMid, + const uint8_t yMax, + const uint8_t xPos, + const uint8_t yPos, + const uint8_t bits) { + int xOff = 0; // final offset of joystick hat image + int yOff = 0; - int xDead = (bits < 7) ? (1<<0) : (1<<3); // dead zone (centre & limits) - int yDead = xDead; + int xDead = (bits < 7) ? (1 << 0) : (1 << 3); // dead zone (centre & limits) + int yDead = xDead; - // This code is NOT optimised ...and it's still barely readable! - if ((xPos >= (xMid -xDead)) && (xPos <= (xMid +xDead))) xOff = 0 ; // centre [most likely] - else if (xPos <= (xMin +xDead)) xOff = -4 ; // full left - else if (xPos >= (xMax -xDead)) xOff = +4 ; // full right - else if (xPos < (xMid -xDead)) { // part left - // very much hard-coded for 3 interim positions - int lo = (xMin +xDead) +1; // lowest position - int hi = (xMid -xDead) -1; // highest position + // This code is NOT optimised ...and it's still barely readable! + if((xPos >= (xMid - xDead)) && (xPos <= (xMid + xDead))) + xOff = 0; // centre [most likely] + else if(xPos <= (xMin + xDead)) + xOff = -4; // full left + else if(xPos >= (xMax - xDead)) + xOff = +4; // full right + else if(xPos < (xMid - xDead)) { // part left + // very much hard-coded for 3 interim positions + int lo = (xMin + xDead) + 1; // lowest position + int hi = (xMid - xDead) - 1; // highest position - // this is the only duplicated bit of code - int range = (hi -lo) +1; // range covered - int div = range /3; // each division (base amount, eg. 17/3==5) - int rem = range -(div *3); // remainder (ie. range%3) + // this is the only duplicated bit of code + int range = (hi - lo) + 1; // range covered + int div = range / 3; // each division (base amount, eg. 17/3==5) + int rem = range - (div * 3); // remainder (ie. range%3) -// int hi1 = hi; // lowest value for zone #-1 -// int lo1 = hi1 -div +1; // highest value for zone #-1 -// int hi2 = lo1 -1; // lowest value for zone #-2 -// int lo2 = hi2 -div +1 -(rem==2); // highest value for zone #-2 expand out remainder -// int hi3 = lo2 -1; // lowest value for zone #-3 -// int lo3 = hi3 -div +1 -(rem>=1); // highest value for zone #-3 expand out remainder + // int hi1 = hi; // lowest value for zone #-1 + // int lo1 = hi1 -div +1; // highest value for zone #-1 + // int hi2 = lo1 -1; // lowest value for zone #-2 + // int lo2 = hi2 -div +1 -(rem==2); // highest value for zone #-2 expand out remainder + // int hi3 = lo2 -1; // lowest value for zone #-3 + // int lo3 = hi3 -div +1 -(rem>=1); // highest value for zone #-3 expand out remainder - int lo1 = hi -div +1; // (in brevity) - int hi3 = hi -div -div -(rem==2); // ... + int lo1 = hi - div + 1; // (in brevity) + int hi3 = hi - div - div - (rem == 2); // ... - if (xPos <= hi3) xOff = -3 ; // zone #-3 - else if (xPos >= lo1) xOff = -1 ; // zone #-1 - else xOff = -2 ; // zone #-2 + if(xPos <= hi3) + xOff = -3; // zone #-3 + else if(xPos >= lo1) + xOff = -1; // zone #-1 + else + xOff = -2; // zone #-2 - } else /*if (xPos > (xMid +xDead))*/ { // part right - // very much hard-coded for 3 interim positions - int lo = (xMid +xDead) +1; // lowest position - int hi = (xMax -xDead) -1; // highest position + } else /*if (xPos > (xMid +xDead))*/ { // part right + // very much hard-coded for 3 interim positions + int lo = (xMid + xDead) + 1; // lowest position + int hi = (xMax - xDead) - 1; // highest position - int range = (hi -lo) +1; // range covered - int div = range /3; // each division (base amount, eg. 17/3==5) - int rem = range -(div *3); // remainder (ie. range%3) + int range = (hi - lo) + 1; // range covered + int div = range / 3; // each division (base amount, eg. 17/3==5) + int rem = range - (div * 3); // remainder (ie. range%3) -// int lo1 = lo; // lowest value for zone #+1 -// int hi1 = lo +div -1; // highest value for zone #+1 -// int lo2 = hi1 +1; // lowest value for zone #+2 -// int hi2 = lo2 +div -1 +(rem==2); // highest value for zone #+2 expand out remainder -// int lo3 = hi2 +1; // lowest value for zone #+3 -// int hi3 = lo3 +div -1 +(rem>=1); // highest value for zone #+3 expand out remainder + // int lo1 = lo; // lowest value for zone #+1 + // int hi1 = lo +div -1; // highest value for zone #+1 + // int lo2 = hi1 +1; // lowest value for zone #+2 + // int hi2 = lo2 +div -1 +(rem==2); // highest value for zone #+2 expand out remainder + // int lo3 = hi2 +1; // lowest value for zone #+3 + // int hi3 = lo3 +div -1 +(rem>=1); // highest value for zone #+3 expand out remainder - int hi1 = lo +div -1; // (in brevity) - int lo3 = lo +div +div +(rem==2); // ... + int hi1 = lo + div - 1; // (in brevity) + int lo3 = lo + div + div + (rem == 2); // ... - if (xPos <= hi1) xOff = 1 ; // zone #1 - else if (xPos >= lo3) xOff = 3 ; // zone #3 - else xOff = 2 ; // zone #2 - } + if(xPos <= hi1) + xOff = 1; // zone #1 + else if(xPos >= lo3) + xOff = 3; // zone #3 + else + xOff = 2; // zone #2 + } - // All this to print a 3x3 square (in the right place) - LOL! - if ((yPos >= (yMid -yDead)) && (yPos <= (yMid +yDead))) yOff = 0 ; // centre [most likely] - else if (yPos <= (yMin +yDead)) yOff = +4 ; // full down - else if (yPos >= (yMax -yDead)) yOff = -4 ; // full up - else if (yPos < (yMid -yDead)) { // part down - int lo = (yMin +yDead) +1; // lowest position - int hi = (yMid -yDead) -1; // highest position + // All this to print a 3x3 square (in the right place) - LOL! + if((yPos >= (yMid - yDead)) && (yPos <= (yMid + yDead))) + yOff = 0; // centre [most likely] + else if(yPos <= (yMin + yDead)) + yOff = +4; // full down + else if(yPos >= (yMax - yDead)) + yOff = -4; // full up + else if(yPos < (yMid - yDead)) { // part down + int lo = (yMin + yDead) + 1; // lowest position + int hi = (yMid - yDead) - 1; // highest position - int range = (hi -lo) +1; // range covered - int div = range /3; // each division (base amount, eg. 17/3==5) - int rem = range -(div *3); // remainder (ie. range%3) + int range = (hi - lo) + 1; // range covered + int div = range / 3; // each division (base amount, eg. 17/3==5) + int rem = range - (div * 3); // remainder (ie. range%3) - int lo1 = hi -div +1; // (in brevity) - int hi3 = hi -div -div -(rem==2); // ... + int lo1 = hi - div + 1; // (in brevity) + int hi3 = hi - div - div - (rem == 2); // ... - if (yPos <= hi3) yOff = +3 ; // zone #3 - else if (yPos >= lo1) yOff = +1 ; // zone #1 - else yOff = +2 ; // zone #2 + if(yPos <= hi3) + yOff = +3; // zone #3 + else if(yPos >= lo1) + yOff = +1; // zone #1 + else + yOff = +2; // zone #2 - } else /*if (yPos > (yMid +yDead))*/ { // part up - int lo = (yMid +yDead) +1; // lowest position - int hi = (yMax -yDead) -1; // highest position + } else /*if (yPos > (yMid +yDead))*/ { // part up + int lo = (yMid + yDead) + 1; // lowest position + int hi = (yMax - yDead) - 1; // highest position - int range = (hi -lo) +1; // range covered - int div = range /3; // each division (base amount, eg. 17/3==5) - int rem = range -(div *3); // remainder (ie. range%3) + int range = (hi - lo) + 1; // range covered + int div = range / 3; // each division (base amount, eg. 17/3==5) + int rem = range - (div * 3); // remainder (ie. range%3) - int hi1 = lo +div -1; // (in brevity) - int lo3 = lo +div +div +(rem==2); // ... + int hi1 = lo + div - 1; // (in brevity) + int lo3 = lo + div + div + (rem == 2); // ... - if (yPos <= hi1) yOff = -1 ; // zone #-1 - else if (yPos >= lo3) yOff = -3 ; // zone #-3 - else yOff = -2 ; // zone #-2 - } + if(yPos <= hi1) + yOff = -1; // zone #-1 + else if(yPos >= lo3) + yOff = -3; // zone #-3 + else + yOff = -2; // zone #-2 + } - show(canvas, x-(img_cc_Joy.w/2),y-(img_cc_Joy.h/2), &img_cc_Joy, SHOW_SET_BLK); + show(canvas, x - (img_cc_Joy.w / 2), y - (img_cc_Joy.h / 2), &img_cc_Joy, SHOW_SET_BLK); - // All ^that^ for v-this-v - LOL!! - canvas_draw_box(canvas, (x-1)+xOff,(y-1)+yOff, 3,3); + // All ^that^ for v-this-v - LOL!! + canvas_draw_box(canvas, (x - 1) + xOff, (y - 1) + yOff, 3, 3); } diff --git a/applications/plugins/wii_ec_anal/wii_anal_lcd.h b/applications/plugins/wii_ec_anal/wii_anal_lcd.h index 5258c4de1..e52a3adc6 100644 --- a/applications/plugins/wii_ec_anal/wii_anal_lcd.h +++ b/applications/plugins/wii_ec_anal/wii_anal_lcd.h @@ -1,43 +1,57 @@ -#ifndef WII_ANAL_LCD_H_ -#define WII_ANAL_LCD_H_ +#ifndef WII_ANAL_LCD_H_ +#define WII_ANAL_LCD_H_ //----------------------------------------------------------------------------- ---------------------------------------- // A couple of monospaced hex fonts // #include "gfx/images.h" -extern const image_t* img_6x8[]; -extern const image_t* img_5x7[]; +extern const image_t* img_6x8[]; +extern const image_t* img_5x7[]; //============================================================================= ======================================== // macros to draw only two sides of a box // these are used for drawing the wires on the WAIT screen // -#define BOX_TL(x1,y1,x2,y2) do { \ - canvas_draw_frame(canvas, x1,y1, x2-x1+1,2); \ - canvas_draw_frame(canvas, x1,y1+2, 2,y2-y1+1-2); \ -}while(0) - -#define BOX_BL(x1,y1,x2,y2) do { \ - canvas_draw_frame(canvas, x1,y2-1, x2-x1+1,2); \ - canvas_draw_frame(canvas, x1,y1, 2,y2-y1+1-2); \ -}while(0) +#define BOX_TL(x1, y1, x2, y2) \ + do { \ + canvas_draw_frame(canvas, x1, y1, x2 - x1 + 1, 2); \ + canvas_draw_frame(canvas, x1, y1 + 2, 2, y2 - y1 + 1 - 2); \ + } while(0) +#define BOX_BL(x1, y1, x2, y2) \ + do { \ + canvas_draw_frame(canvas, x1, y2 - 1, x2 - x1 + 1, 2); \ + canvas_draw_frame(canvas, x1, y1, 2, y2 - y1 + 1 - 2); \ + } while(0) //============================================================================= ======================================== // Function prototypes // -void patBacklight (state_t* state) ; +void patBacklight(state_t* state); -void showHex ( Canvas* const canvas, uint8_t x, uint8_t y, - const uint32_t val, const uint8_t cnt, const int b ) ; +void showHex( + Canvas* const canvas, + uint8_t x, + uint8_t y, + const uint32_t val, + const uint8_t cnt, + const int b); -void showPeakHold (state_t* const state, Canvas* const canvas, const int hold) ; - -void showJoy ( Canvas* const canvas, const uint8_t x, const uint8_t y, // x,y is the CENTRE of the Joystick - const uint8_t xMin, const uint8_t xMid, const uint8_t xMax, - const uint8_t yMin, const uint8_t yMid, const uint8_t yMax, - const uint8_t xPos, const uint8_t yPos, const uint8_t bits ) ; +void showPeakHold(state_t* const state, Canvas* const canvas, const int hold); +void showJoy( + Canvas* const canvas, + const uint8_t x, + const uint8_t y, // x,y is the CENTRE of the Joystick + const uint8_t xMin, + const uint8_t xMid, + const uint8_t xMax, + const uint8_t yMin, + const uint8_t yMid, + const uint8_t yMax, + const uint8_t xPos, + const uint8_t yPos, + const uint8_t bits); #endif //WII_ANAL_LCD_H_ diff --git a/applications/plugins/wii_ec_anal/wii_anal_ver.h b/applications/plugins/wii_ec_anal/wii_anal_ver.h index 88ed17d19..3f2c8c0e6 100644 --- a/applications/plugins/wii_ec_anal/wii_anal_ver.h +++ b/applications/plugins/wii_ec_anal/wii_anal_ver.h @@ -1,9 +1,9 @@ -#ifndef WII_ANAL_VER_H_ -#define WII_ANAL_VER_H_ +#ifndef WII_ANAL_VER_H_ +#define WII_ANAL_VER_H_ -#include "gfx/images.h" +#include "gfx/images.h" -#define VER_MAJ &img_3x5_1 -#define VER_MIN &img_3x5_0 +#define VER_MAJ &img_3x5_1 +#define VER_MIN &img_3x5_0 #endif //WII_ANAL_VER_H_ diff --git a/applications/plugins/wii_ec_anal/wii_ec.c b/applications/plugins/wii_ec_anal/wii_ec.c index 93b17c67c..00dcbf922 100644 --- a/applications/plugins/wii_ec_anal/wii_ec.c +++ b/applications/plugins/wii_ec_anal/wii_ec.c @@ -1,220 +1,298 @@ -#include -#include // Core API +#include +#include // Core API -#include "wii_anal.h" -#include "wii_i2c.h" -#include "wii_ec.h" -#include "bc_logging.h" +#include "wii_anal.h" +#include "wii_i2c.h" +#include "wii_ec.h" +#include "bc_logging.h" -#include "gfx/images.h" // Images -#include "wii_anal_lcd.h" // Drawing functions -#include "wii_anal_keys.h" // key mappings +#include "gfx/images.h" // Images +#include "wii_anal_lcd.h" // Drawing functions +#include "wii_anal_keys.h" // key mappings //----------------------------------------------------------------------------- ---------------------------------------- // List of known perhipherals // // More perhipheral ID codes here: https://wiibrew.org/wiki/Wiimote/Extension_Controllers#The_New_Way // -const ecId_t ecId[PID_CNT] = { - [PID_UNKNOWN ] = { {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, "Unknown Perhipheral", SCENE_DUMP, - NULL, NULL, NULL, NULL, ec_show, ec_key}, +const ecId_t ecId[PID_CNT] = { + [PID_UNKNOWN] = + {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + "Unknown Perhipheral", + SCENE_DUMP, + NULL, + NULL, + NULL, + NULL, + ec_show, + ec_key}, - // If you're wise, ONLY edit this bit - [PID_NUNCHUCK ] = { {0x00, 0x00, 0xA4, 0x20, 0x00, 0x00}, "Nunchuck", SCENE_NUNCHUCK, - NULL, nunchuck_decode, nunchuck_msg, nunchuck_calib, nunchuck_show, nunchuck_key }, + // If you're wise, ONLY edit this bit + [PID_NUNCHUCK] = + {{0x00, 0x00, 0xA4, 0x20, 0x00, 0x00}, + "Nunchuck", + SCENE_NUNCHUCK, + NULL, + nunchuck_decode, + nunchuck_msg, + nunchuck_calib, + nunchuck_show, + nunchuck_key}, - [PID_NUNCHUCK_R2] = { {0xFF, 0x00, 0xA4, 0x20, 0x00, 0x00}, "Nunchuck (rev2)", SCENE_NUNCHUCK, - NULL, nunchuck_decode, nunchuck_msg, nunchuck_calib, nunchuck_show, nunchuck_key }, + [PID_NUNCHUCK_R2] = + {{0xFF, 0x00, 0xA4, 0x20, 0x00, 0x00}, + "Nunchuck (rev2)", + SCENE_NUNCHUCK, + NULL, + nunchuck_decode, + nunchuck_msg, + nunchuck_calib, + nunchuck_show, + nunchuck_key}, - [PID_CLASSIC ] = { {0x00, 0x00, 0xA4, 0x20, 0x01, 0x01}, "Classic Controller", SCENE_CLASSIC, - NULL, classic_decode, classic_msg, classic_calib, classic_show, classic_key }, + [PID_CLASSIC] = + {{0x00, 0x00, 0xA4, 0x20, 0x01, 0x01}, + "Classic Controller", + SCENE_CLASSIC, + NULL, + classic_decode, + classic_msg, + classic_calib, + classic_show, + classic_key}, - [PID_CLASSIC_PRO] = { {0x01, 0x00, 0xA4, 0x20, 0x01, 0x01}, "Classic Controller Pro", SCENE_CLASSIC, - NULL, classic_decode, classic_msg, classic_calib, classic_show, classic_key }, + [PID_CLASSIC_PRO] = + {{0x01, 0x00, 0xA4, 0x20, 0x01, 0x01}, + "Classic Controller Pro", + SCENE_CLASSIC, + NULL, + classic_decode, + classic_msg, + classic_calib, + classic_show, + classic_key}, - [PID_BALANCE ] = { {0x00, 0x00, 0xA4, 0x20, 0x04, 0x02}, "Balance Board", SCENE_DUMP, - NULL, NULL, NULL, NULL, NULL, NULL }, + [PID_BALANCE] = + {{0x00, 0x00, 0xA4, 0x20, 0x04, 0x02}, + "Balance Board", + SCENE_DUMP, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL}, - [PID_GH_GUITAR ] = { {0x00, 0x00, 0xA4, 0x20, 0x01, 0x03}, "Guitar Hero Guitar", SCENE_DUMP, - NULL, NULL, NULL, NULL, NULL, NULL }, + [PID_GH_GUITAR] = + {{0x00, 0x00, 0xA4, 0x20, 0x01, 0x03}, + "Guitar Hero Guitar", + SCENE_DUMP, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL}, - [PID_GH_DRUMS ] = { {0x01, 0x00, 0xA4, 0x20, 0x01, 0x03}, "Guitar Hero World Tour Drums", SCENE_DUMP, - NULL, NULL, NULL, NULL, NULL, NULL }, + [PID_GH_DRUMS] = + {{0x01, 0x00, 0xA4, 0x20, 0x01, 0x03}, + "Guitar Hero World Tour Drums", + SCENE_DUMP, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL}, - [PID_TURNTABLE ] = { {0x03, 0x00, 0xA4, 0x20, 0x01, 0x03}, "DJ Hero Turntable", SCENE_DUMP, - NULL, NULL, NULL, NULL, NULL, NULL }, + [PID_TURNTABLE] = + {{0x03, 0x00, 0xA4, 0x20, 0x01, 0x03}, + "DJ Hero Turntable", + SCENE_DUMP, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL}, - [PID_TAIKO_DRUMS] = { {0x00, 0x00, 0xA4, 0x20, 0x01, 0x11}, "Taiko Drum Controller)", SCENE_DUMP, - NULL, NULL, NULL, NULL, NULL, NULL }, // Taiko no Tatsujin TaTaCon (Drum controller) + [PID_TAIKO_DRUMS] = + {{0x00, 0x00, 0xA4, 0x20, 0x01, 0x11}, + "Taiko Drum Controller)", + SCENE_DUMP, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL}, // Taiko no Tatsujin TaTaCon (Drum controller) - [PID_UDRAW ] = { {0xFF, 0x00, 0xA4, 0x20, 0x00, 0x13}, "uDraw Tablet", SCENE_DUMP, - udraw_init, NULL, NULL, NULL, NULL, NULL }, //! same as drawsome? - // ----- + [PID_UDRAW] = + {{0xFF, 0x00, 0xA4, 0x20, 0x00, 0x13}, + "uDraw Tablet", + SCENE_DUMP, + udraw_init, + NULL, + NULL, + NULL, + NULL, + NULL}, //! same as drawsome? + // ----- - [PID_ERROR ] = { {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, "Read Error", SCENE_NONE, - NULL, NULL, NULL, NULL, NULL, NULL }, + [PID_ERROR] = + {{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, + "Read Error", + SCENE_NONE, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL}, - [PID_NULL ] = { {0}, NULL, SCENE_NONE, NULL, NULL, NULL, NULL, NULL, NULL } // last entry + [PID_NULL] = {{0}, NULL, SCENE_NONE, NULL, NULL, NULL, NULL, NULL, NULL} // last entry }; //+============================================================================ ======================================== -void ecDecode (wiiEC_t* pec) -{ - if (ecId[pec->pidx].decode) ecId[pec->pidx].decode(pec) ; +void ecDecode(wiiEC_t* pec) { + if(ecId[pec->pidx].decode) ecId[pec->pidx].decode(pec); } //+============================================================================ ======================================== -void ecCalibrate (wiiEC_t* const pec, ecCalib_t c) -{ - if (ecId[pec->pidx].calib) ecId[pec->pidx].calib(pec, c) ; +void ecCalibrate(wiiEC_t* const pec, ecCalib_t c) { + if(ecId[pec->pidx].calib) ecId[pec->pidx].calib(pec, c); } //+============================================================================ ======================================== -void ecPoll (wiiEC_t* const pec, FuriMessageQueue* const queue) -{ - ENTER; - furi_assert(queue); +void ecPoll(wiiEC_t* const pec, FuriMessageQueue* const queue) { + ENTER; + furi_assert(queue); - if (!pec->init) { - // Attempt to initialise - if (ecInit(pec, NULL)) { //! need a way to auto-start with encryption enabled - eventMsg_t msg = { - .id = EVID_WIIEC, - .wiiEc = { - .type = WIIEC_CONN, - .in = '<', - .val = pec->pidx - } - }; - furi_message_queue_put(queue, &msg, 0); - } + if(!pec->init) { + // Attempt to initialise + if(ecInit(pec, NULL)) { //! need a way to auto-start with encryption enabled + eventMsg_t msg = { + .id = EVID_WIIEC, .wiiEc = {.type = WIIEC_CONN, .in = '<', .val = pec->pidx}}; + furi_message_queue_put(queue, &msg, 0); + } - } else { - // Attempt to read - switch (ecRead(pec)) { - case 2: { // device gone - eventMsg_t msg = { - .id = EVID_WIIEC, - .wiiEc = { - .type = WIIEC_DISCONN, - .in = '>', - .val = pec->pidx - } - }; - furi_message_queue_put(queue, &msg, 0); - break; - } + } else { + // Attempt to read + switch(ecRead(pec)) { + case 2: { // device gone + eventMsg_t msg = { + .id = EVID_WIIEC, .wiiEc = {.type = WIIEC_DISCONN, .in = '>', .val = pec->pidx}}; + furi_message_queue_put(queue, &msg, 0); + break; + } - case 0: { // read OK - void (*fn)(wiiEC_t*, FuriMessageQueue*) = ecId[pec->pidx].check; - if (fn) fn(pec, queue); - break; - } + case 0: { // read OK + void (*fn)(wiiEC_t*, FuriMessageQueue*) = ecId[pec->pidx].check; + if(fn) fn(pec, queue); + break; + } - case 3: // read fail - // this is probably temporary just ignore it - break; + case 3: // read fail + // this is probably temporary just ignore it + break; - default: // bug: unknown - case 1: // bug: not initialised - should never happen - ERROR("%s : read bug", __func__); - break; - } - } + default: // bug: unknown + case 1: // bug: not initialised - should never happen + ERROR("%s : read bug", __func__); + break; + } + } - LEAVE; - return; + LEAVE; + return; } //+============================================================================ ======================================== // This is the screen drawn for an unknown controller // It is also available by pressing LEFT (at least once) on a "known controller" screen // -void ec_show (Canvas* const canvas, state_t* const state) -{ - wiiEC_t* pec = &state->ec; - int h = 11; // line height - int x = 1; // (initial) offset for bits - int y = -h; // previous y value - int yb = 0; // y for bit patterns - int c2 = 17; // column 2 +void ec_show(Canvas* const canvas, state_t* const state) { + wiiEC_t* pec = &state->ec; + int h = 11; // line height + int x = 1; // (initial) offset for bits + int y = -h; // previous y value + int yb = 0; // y for bit patterns + int c2 = 17; // column 2 - // Headings - canvas_set_font(canvas, FontSecondary); - canvas_set_color(canvas, ColorBlack); + // Headings + canvas_set_font(canvas, FontSecondary); + canvas_set_color(canvas, ColorBlack); - canvas_draw_str_aligned(canvas, 0 ,0, AlignLeft, AlignTop, "SID:"); - canvas_draw_str_aligned(canvas, c2,0, AlignLeft, AlignTop, pec->sid); + canvas_draw_str_aligned(canvas, 0, 0, AlignLeft, AlignTop, "SID:"); + canvas_draw_str_aligned(canvas, c2, 0, AlignLeft, AlignTop, pec->sid); - canvas_draw_str_aligned(canvas, 0 ,11, AlignLeft, AlignTop, "PID:"); - canvas_draw_str_aligned(canvas, 0 ,22, AlignLeft, AlignTop, "Cal:"); + canvas_draw_str_aligned(canvas, 0, 11, AlignLeft, AlignTop, "PID:"); + canvas_draw_str_aligned(canvas, 0, 22, AlignLeft, AlignTop, "Cal:"); - // PID - x = c2; - for (int i = 0; i < 6; i++) { - show(canvas, x,11, img_5x7[pec->pid[i]>>4], SHOW_SET_BLK); - x += 5+1; - show(canvas, x,11, img_5x7[pec->pid[i]&0xF], SHOW_SET_BLK); - x += 5+1+2; - } + // PID + x = c2; + for(int i = 0; i < 6; i++) { + show(canvas, x, 11, img_5x7[pec->pid[i] >> 4], SHOW_SET_BLK); + x += 5 + 1; + show(canvas, x, 11, img_5x7[pec->pid[i] & 0xF], SHOW_SET_BLK); + x += 5 + 1 + 2; + } - // Calibrations data - y = 11; - for (int j = 0; j <= 8; j += 8) { - x = c2; - y += 11; - for (int i = 0; i < 8; i++) { - show(canvas, x,y, img_5x7[pec->calF[i+j]>>4], SHOW_SET_BLK); - x += 5+1; - show(canvas, x,y, img_5x7[pec->calF[i+j]&0xF], SHOW_SET_BLK); - x += 5+1+2; - } - } + // Calibrations data + y = 11; + for(int j = 0; j <= 8; j += 8) { + x = c2; + y += 11; + for(int i = 0; i < 8; i++) { + show(canvas, x, y, img_5x7[pec->calF[i + j] >> 4], SHOW_SET_BLK); + x += 5 + 1; + show(canvas, x, y, img_5x7[pec->calF[i + j] & 0xF], SHOW_SET_BLK); + x += 5 + 1 + 2; + } + } - // Reading - x = 1; - y++; - yb = (y+=h) +h +2; + // Reading + x = 1; + y++; + yb = (y += h) + h + 2; - canvas_draw_line(canvas, x,y-1, x,yb+4); - x += 2; + canvas_draw_line(canvas, x, y - 1, x, yb + 4); + x += 2; - for (int i = 0; i < JOY_LEN; i++) { - show(canvas, x+ 1,y, img_6x8[pec->joy[i]>>4], SHOW_SET_BLK); - show(canvas, x+11,y, img_6x8[pec->joy[i]&0xF], SHOW_SET_BLK); + for(int i = 0; i < JOY_LEN; i++) { + show(canvas, x + 1, y, img_6x8[pec->joy[i] >> 4], SHOW_SET_BLK); + show(canvas, x + 11, y, img_6x8[pec->joy[i] & 0xF], SHOW_SET_BLK); - // bits - for (int m = 0x80; m; m >>= 1) { - x += 2 * !!(m & 0x08) ; // nybble step - canvas_draw_box(canvas, x,yb +(2*!(pec->joy[i] & m)), 2,2) ; - x += 2; // bit step - } + // bits + for(int m = 0x80; m; m >>= 1) { + x += 2 * !!(m & 0x08); // nybble step + canvas_draw_box(canvas, x, yb + (2 * !(pec->joy[i] & m)), 2, 2); + x += 2; // bit step + } - // byte step - x += 1; - canvas_draw_line(canvas, x,y-1, x,yb+4); - x += 2; - } + // byte step + x += 1; + canvas_draw_line(canvas, x, y - 1, x, yb + 4); + x += 2; + } - // Scene navigation - if (state->scenePrev != SCENE_WAIT) - show(canvas, 120,0, &img_key_R, SHOW_SET_BLK); + // Scene navigation + if(state->scenePrev != SCENE_WAIT) show(canvas, 120, 0, &img_key_R, SHOW_SET_BLK); } //+============================================================================ ======================================== -// The DUMP screen is +// The DUMP screen is // -bool ec_key (const eventMsg_t* const msg, state_t* const state) -{ - int used = false; // assume key is NOT-handled +bool ec_key(const eventMsg_t* const msg, state_t* const state) { + int used = false; // assume key is NOT-handled - if (state->scenePrev != SCENE_WAIT) { - //# input.type == InputTypeShort) && (msg->input.key == InputKeyRight)) { - sceneSet(state, state->scenePrev); - used = true; - } - } + if(state->scenePrev != SCENE_WAIT) { + //# input.type == InputTypeShort) && (msg->input.key == InputKeyRight)) { + sceneSet(state, state->scenePrev); + used = true; + } + } - return used; + return used; } diff --git a/applications/plugins/wii_ec_anal/wii_ec.h b/applications/plugins/wii_ec_anal/wii_ec.h index e8745ba13..a28453740 100644 --- a/applications/plugins/wii_ec_anal/wii_ec.h +++ b/applications/plugins/wii_ec_anal/wii_ec.h @@ -1,158 +1,142 @@ -#ifndef WII_EC_H_ -#define WII_EC_H_ +#ifndef WII_EC_H_ +#define WII_EC_H_ -#include +#include -#include +#include -#include "wii_ec_nunchuck.h" -#include "wii_ec_classic.h" -#include "wii_ec_udraw.h" +#include "wii_ec_nunchuck.h" +#include "wii_ec_classic.h" +#include "wii_ec_udraw.h" //----------------------------------------------------------------------------- ---------------------------------------- // Crypto key (PSK), base register : {0x40..0x4F}[2][8] -#define ENC_LEN (2*8) +#define ENC_LEN (2 * 8) // Controller State data, base register : {0x00..0x05}[6] -#define JOY_LEN (6) +#define JOY_LEN (6) // Calibration data, base register : {0x20..0x2F}[16] -#define CAL_LEN (16) +#define CAL_LEN (16) // Controller ID, base register : {0xFA..0xFF}[6] -#define PID_LEN (6) +#define PID_LEN (6) //----------------------------------------------------------------------------- ---------------------------------------- // Perhipheral specific parameters union // -typedef - union ecDec { - ecDecNunchuck_t nunchuck; - ecDecClassic_t classic; - } -ecDec_t; +typedef union ecDec { + ecDecNunchuck_t nunchuck; + ecDecClassic_t classic; +} ecDec_t; //----------------------------------------------------------------------------- -typedef - union ecCal { - // 0=lowest seen ; 1=min ; 2=mid ; 3=max ; 4=highest seen - ecCalNunchuck_t nunchuck[5]; - ecCalClassic_t classic[5]; - } -ecCal_t; +typedef union ecCal { + // 0=lowest seen ; 1=min ; 2=mid ; 3=max ; 4=highest seen + ecCalNunchuck_t nunchuck[5]; + ecCalClassic_t classic[5]; +} ecCal_t; //----------------------------------------------------------------------------- ---------------------------------------- // Wii Extension Controller events // -typedef - enum wiiEcEventType { - WIIEC_NONE, - WIIEC_CONN, // Connect - WIIEC_DISCONN, // Disconnect - WIIEC_PRESS, // Press button - WIIEC_RELEASE, // Release button - WIIEC_ANALOG, // Analogue change (Joystick/Trigger) - WIIEC_ACCEL, // Accelerometer change - } -wiiEcEventType_t; +typedef enum wiiEcEventType { + WIIEC_NONE, + WIIEC_CONN, // Connect + WIIEC_DISCONN, // Disconnect + WIIEC_PRESS, // Press button + WIIEC_RELEASE, // Release button + WIIEC_ANALOG, // Analogue change (Joystick/Trigger) + WIIEC_ACCEL, // Accelerometer change +} wiiEcEventType_t; //----------------------------------------------------------------------------- -typedef - struct wiiEcEvent { - wiiEcEventType_t type; // event type - char in; // input (see device specific options) - uint32_t val; // new value - meaningless for digital button presses - } -wiiEcEvent_t; +typedef struct wiiEcEvent { + wiiEcEventType_t type; // event type + char in; // input (see device specific options) + uint32_t val; // new value - meaningless for digital button presses +} wiiEcEvent_t; //----------------------------------------------------------------------------- ---------------------------------------- // Known perhipheral types // -typedef - enum ecPid { - PID_UNKNOWN = 0, - PID_FIRST = 1, - PID_NUNCHUCK = PID_FIRST, +typedef enum ecPid { + PID_UNKNOWN = 0, + PID_FIRST = 1, + PID_NUNCHUCK = PID_FIRST, - // If you're wise, ONLY edit this section - PID_NUNCHUCK_R2, - PID_CLASSIC, - PID_CLASSIC_PRO, - PID_BALANCE, - PID_GH_GUITAR, - PID_GH_DRUMS, - PID_TURNTABLE, - PID_TAIKO_DRUMS, - PID_UDRAW, //! same as drawsome? - // ----- + // If you're wise, ONLY edit this section + PID_NUNCHUCK_R2, + PID_CLASSIC, + PID_CLASSIC_PRO, + PID_BALANCE, + PID_GH_GUITAR, + PID_GH_DRUMS, + PID_TURNTABLE, + PID_TAIKO_DRUMS, + PID_UDRAW, //! same as drawsome? + // ----- - PID_ERROR, - PID_NULL, - PID_CNT, - } -ecPid_t; + PID_ERROR, + PID_NULL, + PID_CNT, +} ecPid_t; //----------------------------------------------------------------------------- // Calibration strategies // -typedef - enum ecCalib { - CAL_FACTORY = 0x01, // (re)set to factory defaults - CAL_TRACK = 0x02, // track maximum and minimum values seen - CAL_RESET = 0x04, // initialise ready for software calibration - CAL_RANGE = 0x08, // perform software calibration step - CAL_CENTRE = 0x10, // reset centre point of joystick - CAL_NOTJOY = 0x20, // do NOT calibrate the joystick - } -ecCalib_t; +typedef enum ecCalib { + CAL_FACTORY = 0x01, // (re)set to factory defaults + CAL_TRACK = 0x02, // track maximum and minimum values seen + CAL_RESET = 0x04, // initialise ready for software calibration + CAL_RANGE = 0x08, // perform software calibration step + CAL_CENTRE = 0x10, // reset centre point of joystick + CAL_NOTJOY = 0x20, // do NOT calibrate the joystick +} ecCalib_t; //----------------------------------------------------------------------------- // ecId table entry // -typedef - struct ecId { - uint8_t id[6]; // 6 byte ID string returned by Extension Controller - char* name; // Friendly name - scene_t scene; // Default scene - bool (*init)(wiiEC_t*); // Additional initialisation code - void (*decode)(wiiEC_t*); // Decode function - void (*check)(wiiEC_t*, FuriMessageQueue*); // check (for action) function - void (*calib)(wiiEC_t*, ecCalib_t); // calibrate analogue controllers [SOFTWARE] - void (*show)(Canvas* const, state_t* const); // Draw scene - bool (*keys)(const eventMsg_t* const, state_t* const); // Interpret keys - } -ecId_t; +typedef struct ecId { + uint8_t id[6]; // 6 byte ID string returned by Extension Controller + char* name; // Friendly name + scene_t scene; // Default scene + bool (*init)(wiiEC_t*); // Additional initialisation code + void (*decode)(wiiEC_t*); // Decode function + void (*check)(wiiEC_t*, FuriMessageQueue*); // check (for action) function + void (*calib)(wiiEC_t*, ecCalib_t); // calibrate analogue controllers [SOFTWARE] + void (*show)(Canvas* const, state_t* const); // Draw scene + bool (*keys)(const eventMsg_t* const, state_t* const); // Interpret keys +} ecId_t; //----------------------------------------------------------------------------- // List of known perhipherals // // More perhipheral ID codes here: https://wiibrew.org/wiki/Wiimote/Extension_Controllers#The_New_Way // -extern const ecId_t ecId[PID_CNT] ; +extern const ecId_t ecId[PID_CNT]; //----------------------------------------------------------------------------- ---------------------------------------- // Data pertaining to a single Perhipheral instance // -typedef - struct wiiEC { - // Perhipheral state - bool init; // Initialised? +typedef struct wiiEC { + // Perhipheral state + bool init; // Initialised? - uint8_t pid[PID_LEN]; // PID string - eg. {0x00, 0x00, 0xA4, 0x20, 0x00, 0x00} - ecPid_t pidx; // Index in to ecId table - const char* sid; // just for convenience + uint8_t pid[PID_LEN]; // PID string - eg. {0x00, 0x00, 0xA4, 0x20, 0x00, 0x00} + ecPid_t pidx; // Index in to ecId table + const char* sid; // just for convenience - bool encrypt; // encryption enabled? - uint8_t encKey[ENC_LEN]; // encryption key + bool encrypt; // encryption enabled? + uint8_t encKey[ENC_LEN]; // encryption key - uint8_t calF[CAL_LEN]; // factory calibration data (not software) - uint8_t joy[JOY_LEN]; // Perhipheral raw data + uint8_t calF[CAL_LEN]; // factory calibration data (not software) + uint8_t joy[JOY_LEN]; // Perhipheral raw data - ecDec_t dec[2]; // device specific decode (two, so we can spot changes) - int decN; // which decode set is most recent {0, 1} - ecCal_t calS; // software calibration data - } -wiiEC_t; + ecDec_t dec[2]; // device specific decode (two, so we can spot changes) + int decN; // which decode set is most recent {0, 1} + ecCal_t calS; // software calibration data +} wiiEC_t; //----------------------------------------------------------------------------- ---------------------------------------- // Function prototypes @@ -161,17 +145,17 @@ wiiEC_t; // top level check() function will handle connect/disconnect messages // -#include // Canvas -typedef struct wiiEC wiiEC_t ; -typedef enum ecCalib ecCalib_t ; -typedef struct state state_t ; -typedef struct eventMsg eventMsg_t ; +#include // Canvas +typedef struct wiiEC wiiEC_t; +typedef enum ecCalib ecCalib_t; +typedef struct state state_t; +typedef struct eventMsg eventMsg_t; -void ecDecode (wiiEC_t* const pec) ; -void ecPoll (wiiEC_t* const pec, FuriMessageQueue* const queue) ; -void ecCalibrate (wiiEC_t* const pec, ecCalib_t c) ; +void ecDecode(wiiEC_t* const pec); +void ecPoll(wiiEC_t* const pec, FuriMessageQueue* const queue); +void ecCalibrate(wiiEC_t* const pec, ecCalib_t c); -void ec_show ( Canvas* const canvas, state_t* const state) ; -bool ec_key (const eventMsg_t* const msg, state_t* const state) ; +void ec_show(Canvas* const canvas, state_t* const state); +bool ec_key(const eventMsg_t* const msg, state_t* const state); #endif //WII_EC_H_ diff --git a/applications/plugins/wii_ec_anal/wii_ec_classic.c b/applications/plugins/wii_ec_anal/wii_ec_classic.c index 91393ba07..5bd3398ca 100644 --- a/applications/plugins/wii_ec_anal/wii_ec_classic.c +++ b/applications/plugins/wii_ec_anal/wii_ec_classic.c @@ -1,17 +1,17 @@ -#include -#include // Core API +#include +#include // Core API -#include "wii_anal.h" -#include "wii_ec.h" -#include "bc_logging.h" +#include "wii_anal.h" +#include "wii_ec.h" +#include "bc_logging.h" //#include "gfx/images.h" // Images -#include "wii_anal_lcd.h" // Drawing functions -#include "wii_anal_keys.h" // key mappings +#include "wii_anal_lcd.h" // Drawing functions +#include "wii_anal_keys.h" // key mappings // ** If you want to see what this source code looks like with all the MACROs expanded // ** grep -v '#include ' wii_i2c_classic.c | gcc -E -o /dev/stdout -xc - -# include "wii_ec_macros.h" +#include "wii_ec_macros.h" //----------------------------------------------------------------------------- ---------------------------------------- // Classic Controller ... Classic Controller Pro is electronically the same @@ -36,102 +36,115 @@ // ...And yes, the left-joystick has an extra 'bit' of precision! // ...Also: trgZ{L|R} WILL continue to increase after btnZ{L|R} has gone active // -void classic_decode (wiiEC_t* const pec) -{ - ecDecClassic_t* p = &pec->dec[(pec->decN = !pec->decN)].classic; - uint8_t* joy = pec->joy; +void classic_decode(wiiEC_t* const pec) { + ecDecClassic_t* p = &pec->dec[(pec->decN = !pec->decN)].classic; + uint8_t* joy = pec->joy; - p->trgZL = ((joy[2] >>2) &0x18) | ((joy[3] >>5) &0x07); // {5} - p->btnZL = !(joy[4] & 0x20); // !{1} + p->trgZL = ((joy[2] >> 2) & 0x18) | ((joy[3] >> 5) & 0x07); // {5} + p->btnZL = !(joy[4] & 0x20); // !{1} - p->trgZR = joy[3] & 0x1F; // {5} - p->btnZR = !(joy[4] & 0x02); // !{1} + p->trgZR = joy[3] & 0x1F; // {5} + p->btnZR = !(joy[4] & 0x02); // !{1} - p->btnL = !(joy[5] & 0x80); // !{1} - p->btnR = !(joy[5] & 0x04); // !{1} + p->btnL = !(joy[5] & 0x80); // !{1} + p->btnR = !(joy[5] & 0x04); // !{1} - p->padU = !(joy[5] & 0x01); // !{1} - p->padD = !(joy[4] & 0x40); // !{1} - p->padL = !(joy[5] & 0x02); // !{1} - p->padR = !(joy[4] & 0x80); // !{1} + p->padU = !(joy[5] & 0x01); // !{1} + p->padD = !(joy[4] & 0x40); // !{1} + p->padL = !(joy[5] & 0x02); // !{1} + p->padR = !(joy[4] & 0x80); // !{1} - p->btnM = !(joy[4] & 0x10); // !{1} - p->btnH = !(joy[4] & 0x08); // !{1} - p->btnP = !(joy[4] & 0x04); // !{1} + p->btnM = !(joy[4] & 0x10); // !{1} + p->btnH = !(joy[4] & 0x08); // !{1} + p->btnP = !(joy[4] & 0x04); // !{1} - p->btnX = !(joy[5] & 0x08); // !{1} - p->btnY = !(joy[5] & 0x20); // !{1} + p->btnX = !(joy[5] & 0x08); // !{1} + p->btnY = !(joy[5] & 0x20); // !{1} - p->btnA = !(joy[5] & 0x10); // !{1} - p->btnB = !(joy[5] & 0x40); // !{1} + p->btnA = !(joy[5] & 0x10); // !{1} + p->btnB = !(joy[5] & 0x40); // !{1} - p->joyLX = joy[0] & 0x3F; // {6} - p->joyLY = joy[1] & 0x3F; // {6} + p->joyLX = joy[0] & 0x3F; // {6} + p->joyLY = joy[1] & 0x3F; // {6} - p->joyRX = ((joy[0] >>3) &0x18) | ((joy[1] >>5) &0x06) | ((joy[2] >>7) &0x01); // {5} - p->joyRY = joy[2] & 0x1F; // {5} + p->joyRX = ((joy[0] >> 3) & 0x18) | ((joy[1] >> 5) & 0x06) | ((joy[2] >> 7) & 0x01); // {5} + p->joyRY = joy[2] & 0x1F; // {5} - DEBUG( ">%d> ZL{%02X}%c, L:%c, R:%c, ZR{%02X}%c", pec->decN, - p->trgZL, (p->btnZL ? '#' : '.'), - (p->btnL ? '#' : '.'), - (p->btnR ? '#' : '.'), - p->trgZR, (p->btnZR ? '#' : '.') - ); - DEBUG( ">%d> D:{%c,%c,%c,%c}, H:{%c,%c,%c}, B:{%c,%c,%c,%c}", pec->decN, - (p->padU ? 'U' : '.'), (p->padD ? 'D' : '.'), (p->padL ? 'L' : '.'), (p->padR ? 'R' : '.'), - (p->btnM ? '-' : '.'), (p->btnH ? 'H' : '.'), (p->btnP ? '+' : '.'), - (p->btnX ? 'X' : '.'), (p->btnY ? 'Y' : '.'), (p->btnA ? 'A' : '.'), (p->btnB ? 'B' : '.') - ); - DEBUG( ">%d> JoyL{x:%02X, y:%02X}, JoyR{x:%02X, y:%02X}", pec->decN, - p->joyLX, p->joyLY, p->joyRX, p->joyRY - ); + DEBUG( + ">%d> ZL{%02X}%c, L:%c, R:%c, ZR{%02X}%c", + pec->decN, + p->trgZL, + (p->btnZL ? '#' : '.'), + (p->btnL ? '#' : '.'), + (p->btnR ? '#' : '.'), + p->trgZR, + (p->btnZR ? '#' : '.')); + DEBUG( + ">%d> D:{%c,%c,%c,%c}, H:{%c,%c,%c}, B:{%c,%c,%c,%c}", + pec->decN, + (p->padU ? 'U' : '.'), + (p->padD ? 'D' : '.'), + (p->padL ? 'L' : '.'), + (p->padR ? 'R' : '.'), + (p->btnM ? '-' : '.'), + (p->btnH ? 'H' : '.'), + (p->btnP ? '+' : '.'), + (p->btnX ? 'X' : '.'), + (p->btnY ? 'Y' : '.'), + (p->btnA ? 'A' : '.'), + (p->btnB ? 'B' : '.')); + DEBUG( + ">%d> JoyL{x:%02X, y:%02X}, JoyR{x:%02X, y:%02X}", + pec->decN, + p->joyLX, + p->joyLY, + p->joyRX, + p->joyRY); } //+============================================================================ ======================================== // Give each button a unique character identifier // -void classic_msg (wiiEC_t* const pec, FuriMessageQueue* const queue) -{ - ecDecClassic_t* new = &pec->dec[pec->decN].classic; - ecDecClassic_t* old = &pec->dec[!pec->decN].classic; +void classic_msg(wiiEC_t* const pec, FuriMessageQueue* const queue) { + ecDecClassic_t* new = &pec->dec[pec->decN].classic; + ecDecClassic_t* old = &pec->dec[!pec->decN].classic; - eventMsg_t msg = { - .id = EVID_WIIEC, - .wiiEc = { - .type = WIIEC_NONE, - .in = ' ', - .val = 0, - } - }; + eventMsg_t msg = { + .id = EVID_WIIEC, + .wiiEc = { + .type = WIIEC_NONE, + .in = ' ', + .val = 0, + }}; - ANALOG(trgZL, 'l'); // FIVE bit value - ANABTN(btnZL, trgZL, 'l'); + ANALOG(trgZL, 'l'); // FIVE bit value + ANABTN(btnZL, trgZL, 'l'); - BUTTON(btnL, 'L'); - BUTTON(btnR, 'R'); + BUTTON(btnL, 'L'); + BUTTON(btnR, 'R'); - ANALOG(trgZR, 'r'); // FIVE bit value - ANABTN(btnZR, trgZR, 'r'); + ANALOG(trgZR, 'r'); // FIVE bit value + ANABTN(btnZR, trgZR, 'r'); - BUTTON(padU, 'W'); - BUTTON(padL, 'A'); - BUTTON(padD, 'S'); - BUTTON(padR, 'D'); + BUTTON(padU, 'W'); + BUTTON(padL, 'A'); + BUTTON(padD, 'S'); + BUTTON(padR, 'D'); - BUTTON(btnM, '-'); - BUTTON(btnH, 'h'); - BUTTON(btnP, '+'); + BUTTON(btnM, '-'); + BUTTON(btnH, 'h'); + BUTTON(btnP, '+'); - BUTTON(btnX, 'x'); - BUTTON(btnY, 'y'); - BUTTON(btnA, 'a'); - BUTTON(btnB, 'b'); + BUTTON(btnX, 'x'); + BUTTON(btnY, 'y'); + BUTTON(btnA, 'a'); + BUTTON(btnB, 'b'); - ANALOG(joyLX, 'x'); // SIX bit values - ANALOG(joyLY, 'y'); + ANALOG(joyLX, 'x'); // SIX bit values + ANALOG(joyLY, 'y'); - ANALOG(joyRX, 'X'); // FIVE bit values - ANALOG(joyRY, 'Y'); + ANALOG(joyRX, 'X'); // FIVE bit values + ANALOG(joyRY, 'Y'); } //+============================================================================ ======================================== @@ -144,255 +157,283 @@ void classic_msg (wiiEC_t* const pec, FuriMessageQueue* const queue) // 9..11 right analog stick Y axis {maximum, minimum, center} ... JoyR is 5bits, so >>3 to compare to readings // 12..15 somehow describe the shoulder {5bit} button values!? // -void classic_calib (wiiEC_t* const pec, ecCalib_t c) -{ - ecDecClassic_t* src = &pec->dec[pec->decN].classic; // from input - ecCalClassic_t* dst = pec->calS.classic; // to calibration data +void classic_calib(wiiEC_t* const pec, ecCalib_t c) { + ecDecClassic_t* src = &pec->dec[pec->decN].classic; // from input + ecCalClassic_t* dst = pec->calS.classic; // to calibration data - if (c & CAL_RESET) { // initialise ready for software calibration - // LO is set to the MAXIMUM value (so it can be reduced) - // HI is set to ZERO (so it can be increased) - RESET_LO_HI(trgZL, 5); // 5bit value - RESET_LO_HI(trgZR, 5); // 5bit value + if(c & CAL_RESET) { // initialise ready for software calibration + // LO is set to the MAXIMUM value (so it can be reduced) + // HI is set to ZERO (so it can be increased) + RESET_LO_HI(trgZL, 5); // 5bit value + RESET_LO_HI(trgZR, 5); // 5bit value - RESET_LO_MID_HI(joyLX, 6); // 6bit value - RESET_LO_MID_HI(joyLY, 6); // 6bit value + RESET_LO_MID_HI(joyLX, 6); // 6bit value + RESET_LO_MID_HI(joyLY, 6); // 6bit value - RESET_LO_MID_HI(joyRX, 5); // 5bit value - RESET_LO_MID_HI(joyRY, 5); // 5bit value - } - if (c & CAL_FACTORY) { // (re)set to factory defaults -//! strategy for factory calibration for classic controller [pro] triggers is (currently) unknown -//! FACTORY_LO( trgZL, pec->calF[12..15]); -//! FACTORY_MID(trgZL, pec->calF[12..15]); -//! FACTORY_HI( trgZL, pec->calF[12..15]); + RESET_LO_MID_HI(joyRX, 5); // 5bit value + RESET_LO_MID_HI(joyRY, 5); // 5bit value + } + if(c & CAL_FACTORY) { // (re)set to factory defaults + //! strategy for factory calibration for classic controller [pro] triggers is (currently) unknown + //! FACTORY_LO( trgZL, pec->calF[12..15]); + //! FACTORY_MID(trgZL, pec->calF[12..15]); + //! FACTORY_HI( trgZL, pec->calF[12..15]); -//! FACTORY_LO( trgZR, pec->calF[12..15]); -//! FACTORY_MID(trgZR, pec->calF[12..15]); -//! FACTORY_HI( trgZR, pec->calF[12..15]); + //! FACTORY_LO( trgZR, pec->calF[12..15]); + //! FACTORY_MID(trgZR, pec->calF[12..15]); + //! FACTORY_HI( trgZR, pec->calF[12..15]); #if 1 - FACTORY_LO(trgZL, 0x03); - FACTORY_LO(trgZR, 0x03); + FACTORY_LO(trgZL, 0x03); + FACTORY_LO(trgZR, 0x03); - FACTORY_MID(trgZL, 0x1B); //! these will be set every time the digital switch changes to ON - FACTORY_MID(trgZR, 0x1B); + FACTORY_MID(trgZL, 0x1B); //! these will be set every time the digital switch changes to ON + FACTORY_MID(trgZR, 0x1B); #endif - FACTORY_LO( joyLX, pec->calF[ 1] >>2); - FACTORY_MID(joyLX, pec->calF[ 2] >>2); - FACTORY_HI( joyLX, pec->calF[ 0] >>2); + FACTORY_LO(joyLX, pec->calF[1] >> 2); + FACTORY_MID(joyLX, pec->calF[2] >> 2); + FACTORY_HI(joyLX, pec->calF[0] >> 2); - FACTORY_LO( joyLY, pec->calF[ 4] >>2); - FACTORY_MID(joyLY, pec->calF[ 5] >>2); - FACTORY_HI( joyLY, pec->calF[ 3] >>2); + FACTORY_LO(joyLY, pec->calF[4] >> 2); + FACTORY_MID(joyLY, pec->calF[5] >> 2); + FACTORY_HI(joyLY, pec->calF[3] >> 2); - FACTORY_LO( joyRX, pec->calF[ 7] >>3); - FACTORY_MID(joyRX, pec->calF[ 8] >>3); - FACTORY_HI( joyRX, pec->calF[ 6] >>3); + FACTORY_LO(joyRX, pec->calF[7] >> 3); + FACTORY_MID(joyRX, pec->calF[8] >> 3); + FACTORY_HI(joyRX, pec->calF[6] >> 3); - FACTORY_LO( joyRY, pec->calF[10] >>3); - FACTORY_MID(joyRY, pec->calF[11] >>3); - FACTORY_HI( joyRY, pec->calF[ 9] >>3); - } - if (c & CAL_TRACK) { // track maximum and minimum values seen - TRACK_LO_HI(trgZL); - TRACK_LO_HI(trgZR); + FACTORY_LO(joyRY, pec->calF[10] >> 3); + FACTORY_MID(joyRY, pec->calF[11] >> 3); + FACTORY_HI(joyRY, pec->calF[9] >> 3); + } + if(c & CAL_TRACK) { // track maximum and minimum values seen + TRACK_LO_HI(trgZL); + TRACK_LO_HI(trgZR); - TRACK_LO_HI(joyLX); - TRACK_LO_HI(joyLY); + TRACK_LO_HI(joyLX); + TRACK_LO_HI(joyLY); - TRACK_LO_HI(joyRX); - TRACK_LO_HI(joyRY); - } - if (c & CAL_RANGE) { // perform software calibration step - RANGE_LO_HI(trgZL); - RANGE_LO_HI(trgZR); + TRACK_LO_HI(joyRX); + TRACK_LO_HI(joyRY); + } + if(c & CAL_RANGE) { // perform software calibration step + RANGE_LO_HI(trgZL); + RANGE_LO_HI(trgZR); - RANGE_LO_HI(joyLX); - RANGE_LO_HI(joyLY); + RANGE_LO_HI(joyLX); + RANGE_LO_HI(joyLY); - RANGE_LO_HI(joyRX); - RANGE_LO_HI(joyRY); - } - if (c & CAL_CENTRE) { // reset centre point of joystick - CENTRE(joyLX); - CENTRE(joyLY); + RANGE_LO_HI(joyRX); + RANGE_LO_HI(joyRY); + } + if(c & CAL_CENTRE) { // reset centre point of joystick + CENTRE(joyLX); + CENTRE(joyLY); - CENTRE(joyRX); - CENTRE(joyRY); - } + CENTRE(joyRX); + CENTRE(joyRY); + } } //+============================================================================ ======================================== // bits that are common to both screens // -static -void classic_show_ (Canvas* const canvas, state_t* const state) -{ - ecDecClassic_t* d = &state->ec.dec[state->ec.decN].classic; - ecCalClassic_t* js = state->ec.calS.classic; +static void classic_show_(Canvas* const canvas, state_t* const state) { + ecDecClassic_t* d = &state->ec.dec[state->ec.decN].classic; + ecCalClassic_t* js = state->ec.calS.classic; - static const int dead = 1; // trigger deadzone - const image_t* img = NULL; // trigger image + static const int dead = 1; // trigger deadzone + const image_t* img = NULL; // trigger image - show(canvas, 6, 0, &img_cc_Main , SHOW_SET_BLK); - show(canvas, 62,53, &img_cc_Cable, SHOW_SET_BLK); + show(canvas, 6, 0, &img_cc_Main, SHOW_SET_BLK); + show(canvas, 62, 53, &img_cc_Cable, SHOW_SET_BLK); - // classic triggers - if (d->trgZL >= js[2].trgZL ) img = &img_cc_trg_L4; - else if (d->trgZL <= js[1].trgZL +dead) img = NULL; - else { - // copied from the joystick calibration code - int lo = js[1].trgZL +dead +1; - int hi = js[2].trgZL -1; - int range = hi -lo +1; - int div = range /3; // each division (base amount, eg. 17/3==5) - int rem = range -(div *3); // remainder (ie. range%3) - int hi1 = lo +div -1; // (in brevity) - int lo3 = lo +div +div +(rem==2); // ... + // classic triggers + if(d->trgZL >= js[2].trgZL) + img = &img_cc_trg_L4; + else if(d->trgZL <= js[1].trgZL + dead) + img = NULL; + else { + // copied from the joystick calibration code + int lo = js[1].trgZL + dead + 1; + int hi = js[2].trgZL - 1; + int range = hi - lo + 1; + int div = range / 3; // each division (base amount, eg. 17/3==5) + int rem = range - (div * 3); // remainder (ie. range%3) + int hi1 = lo + div - 1; // (in brevity) + int lo3 = lo + div + div + (rem == 2); // ... - if (d->trgZL <= hi1) img = &img_cc_trg_L1 ; // zone #1 - else if (d->trgZL >= lo3) img = &img_cc_trg_L3 ; // zone #3 - else img = &img_cc_trg_L2 ; // zone #2 - } - if (img) show(canvas, 22,1, img, SHOW_SET_BLK) ; + if(d->trgZL <= hi1) + img = &img_cc_trg_L1; // zone #1 + else if(d->trgZL >= lo3) + img = &img_cc_trg_L3; // zone #3 + else + img = &img_cc_trg_L2; // zone #2 + } + if(img) show(canvas, 22, 1, img, SHOW_SET_BLK); - if (d->trgZR >= js[2].trgZR ) img = &img_cc_trg_R4; - else if (d->trgZR <= js[1].trgZR +dead) img = NULL; - else { - // copied from the joystick calibration code - int lo = js[1].trgZR +dead +1; - int hi = js[2].trgZR -1; - int range = hi -lo +1; - int div = range /3; // each division (base amount, eg. 17/3==5) - int rem = range -(div *3); // remainder (ie. range%3) - int hi1 = lo +div -1; // (in brevity) - int lo3 = lo +div +div +(rem==2); // ... + if(d->trgZR >= js[2].trgZR) + img = &img_cc_trg_R4; + else if(d->trgZR <= js[1].trgZR + dead) + img = NULL; + else { + // copied from the joystick calibration code + int lo = js[1].trgZR + dead + 1; + int hi = js[2].trgZR - 1; + int range = hi - lo + 1; + int div = range / 3; // each division (base amount, eg. 17/3==5) + int rem = range - (div * 3); // remainder (ie. range%3) + int hi1 = lo + div - 1; // (in brevity) + int lo3 = lo + div + div + (rem == 2); // ... - if (d->trgZR <= hi1) img = &img_cc_trg_R1 ; // zone #1 - else if (d->trgZR >= lo3) img = &img_cc_trg_R3 ; // zone #3 - else img = &img_cc_trg_R2 ; // zone #2 - } - if (img) show(canvas, 89,1, img, SHOW_SET_BLK) ; + if(d->trgZR <= hi1) + img = &img_cc_trg_R1; // zone #1 + else if(d->trgZR >= lo3) + img = &img_cc_trg_R3; // zone #3 + else + img = &img_cc_trg_R2; // zone #2 + } + if(img) show(canvas, 89, 1, img, SHOW_SET_BLK); - if (d->padU ) show(canvas, 27,16, &img_cc_pad_UD1, SHOW_ALL) ; - if (d->padL ) show(canvas, 20,23, &img_cc_pad_LR1, SHOW_ALL) ; - if (d->padD ) show(canvas, 27,28, &img_cc_pad_UD1, SHOW_ALL) ; - if (d->padR ) show(canvas, 32,23, &img_cc_pad_LR1, SHOW_ALL) ; + if(d->padU) show(canvas, 27, 16, &img_cc_pad_UD1, SHOW_ALL); + if(d->padL) show(canvas, 20, 23, &img_cc_pad_LR1, SHOW_ALL); + if(d->padD) show(canvas, 27, 28, &img_cc_pad_UD1, SHOW_ALL); + if(d->padR) show(canvas, 32, 23, &img_cc_pad_LR1, SHOW_ALL); - if (d->btnX ) show(canvas, 96,16, &img_cc_btn_X1, SHOW_ALL) ; - if (d->btnY ) show(canvas, 85,23, &img_cc_btn_Y1, SHOW_ALL) ; - if (d->btnA ) show(canvas, 107,23, &img_cc_btn_A1, SHOW_ALL) ; - if (d->btnB ) show(canvas, 96,30, &img_cc_btn_B1, SHOW_ALL) ; + if(d->btnX) show(canvas, 96, 16, &img_cc_btn_X1, SHOW_ALL); + if(d->btnY) show(canvas, 85, 23, &img_cc_btn_Y1, SHOW_ALL); + if(d->btnA) show(canvas, 107, 23, &img_cc_btn_A1, SHOW_ALL); + if(d->btnB) show(canvas, 96, 30, &img_cc_btn_B1, SHOW_ALL); - canvas_set_color(canvas, ColorBlack); - if (d->btnL ) canvas_draw_box(canvas, 46,2, 5,4) ; - if (d->btnR ) canvas_draw_box(canvas, 77,2, 5,4) ; + canvas_set_color(canvas, ColorBlack); + if(d->btnL) canvas_draw_box(canvas, 46, 2, 5, 4); + if(d->btnR) canvas_draw_box(canvas, 77, 2, 5, 4); - if (d->btnM ) canvas_draw_box(canvas, 54,24, 4,4) ; - if (d->btnH ) canvas_draw_box(canvas, 62,24, 4,4) ; - if (d->btnP ) canvas_draw_box(canvas, 70,24, 4,4) ; + if(d->btnM) canvas_draw_box(canvas, 54, 24, 4, 4); + if(d->btnH) canvas_draw_box(canvas, 62, 24, 4, 4); + if(d->btnP) canvas_draw_box(canvas, 70, 24, 4, 4); - // Show joysticks - showJoy(canvas, 48,42, js[1].joyLX,js[2].joyLX, js[3].joyLX, - js[1].joyLY,js[2].joyLY, js[3].joyLY, d->joyLX,d->joyLY, 6); - showJoy(canvas, 78,42, js[1].joyRX,js[2].joyRX, js[3].joyRX, - js[1].joyRY,js[2].joyRY, js[3].joyRY, d->joyRX,d->joyRY, 5); + // Show joysticks + showJoy( + canvas, + 48, + 42, + js[1].joyLX, + js[2].joyLX, + js[3].joyLX, + js[1].joyLY, + js[2].joyLY, + js[3].joyLY, + d->joyLX, + d->joyLY, + 6); + showJoy( + canvas, + 78, + 42, + js[1].joyRX, + js[2].joyRX, + js[3].joyRX, + js[1].joyRY, + js[2].joyRY, + js[3].joyRY, + d->joyRX, + d->joyRY, + 5); - show(canvas, 0,55, &img_key_L, SHOW_SET_BLK); + show(canvas, 0, 55, &img_key_L, SHOW_SET_BLK); } //+============================================================================ ======================================== -static -void classic_showN (Canvas* const canvas, state_t* const state) -{ - ecCalClassic_t* c = (state->hold) ? &state->ec.calS.classic[(state->hold < 0) ? 0 : 4] - : (ecCalClassic_t*)(&state->ec.dec[state->ec.decN].classic) ; //! danger +static void classic_showN(Canvas* const canvas, state_t* const state) { + ecCalClassic_t* c = (state->hold) ? + &state->ec.calS.classic[(state->hold < 0) ? 0 : 4] : + (ecCalClassic_t*)(&state->ec.dec[state->ec.decN].classic); //! danger - classic_show_(canvas, state); + classic_show_(canvas, state); - showHex(canvas, 0, 0, c->trgZL, 2,1); // 5bits - showHex(canvas, 113, 0, c->trgZR, 2,1); // 5bits + showHex(canvas, 0, 0, c->trgZL, 2, 1); // 5bits + showHex(canvas, 113, 0, c->trgZR, 2, 1); // 5bits - showHex(canvas, 24,41, c->joyLX, 2,1); // 6bits - showHex(canvas, 41,54, c->joyLY, 2,1); // 6bits + showHex(canvas, 24, 41, c->joyLX, 2, 1); // 6bits + showHex(canvas, 41, 54, c->joyLY, 2, 1); // 6bits - showHex(canvas, 88,41, c->joyRX, 2,1); // 5bits - showHex(canvas, 71,54, c->joyRY, 2,1); // 5bits + showHex(canvas, 88, 41, c->joyRX, 2, 1); // 5bits + showHex(canvas, 71, 54, c->joyRY, 2, 1); // 5bits - showPeakHold(state, canvas, state->hold); // peak keys + showPeakHold(state, canvas, state->hold); // peak keys } //+============================================================================ ======================================== -void classic_show (Canvas* const canvas, state_t* const state) -{ - // Classic controllers have TWO scenes - if (state->scene == SCENE_CLASSIC_N) return classic_showN(canvas, state) ; +void classic_show(Canvas* const canvas, state_t* const state) { + // Classic controllers have TWO scenes + if(state->scene == SCENE_CLASSIC_N) return classic_showN(canvas, state); - // Default scene - classic_show_(canvas, state); - show(canvas, 9,55, &img_key_R, SHOW_SET_BLK); + // Default scene + classic_show_(canvas, state); + show(canvas, 9, 55, &img_key_R, SHOW_SET_BLK); - show( canvas, 119,55, - ((state->calib & CAL_RANGE) && (++state->flash &8)) ? &img_key_OKi : &img_key_OK, - SHOW_SET_BLK ); + show( + canvas, + 119, + 55, + ((state->calib & CAL_RANGE) && (++state->flash & 8)) ? &img_key_OKi : &img_key_OK, + SHOW_SET_BLK); } //+============================================================================ ======================================== -static -bool classic_keyN (const eventMsg_t* const msg, state_t* const state) -{ - int used = false; // assume key is NOT-handled +static bool classic_keyN(const eventMsg_t* const msg, state_t* const state) { + int used = false; // assume key is NOT-handled - if ((msg->input.type == InputTypeShort) && (msg->input.key == InputKeyLeft)) { - sceneSet(state, SCENE_CLASSIC); - used = true; - } + if((msg->input.type == InputTypeShort) && (msg->input.key == InputKeyLeft)) { + sceneSet(state, SCENE_CLASSIC); + used = true; + } - // Calibration keys - if (!used) used = key_calib(msg, state) ; + // Calibration keys + if(!used) used = key_calib(msg, state); - return used; + return used; } //+============================================================================ ======================================== -bool classic_key (const eventMsg_t* const msg, state_t* const state) -{ - // Classic controllers have TWO scenes - if (state->scene == SCENE_CLASSIC_N) return classic_keyN(msg, state) ; +bool classic_key(const eventMsg_t* const msg, state_t* const state) { + // Classic controllers have TWO scenes + if(state->scene == SCENE_CLASSIC_N) return classic_keyN(msg, state); - // Default scene - int used = false; // assume key is NOT-handled + // Default scene + int used = false; // assume key is NOT-handled - switch (msg->input.type) { - case InputTypeShort: //# input.key) { - case InputKeyUp: //# input.type) { + case InputTypeShort: //# input.key) { + case InputKeyUp: //# -#include +#include +#include //----------------------------------------------------------------------------- ---------------------------------------- // Classic Controller ... Classic Controller Pro is electronically the same @@ -25,60 +25,55 @@ //----------------------------------------------------------------------------- ---------------------------------------- // Controllers which have calibration must have their calibratable controls here //! Is there a better way to get the start of the decode struct to match the calibration struct ? -#define CLASSIC_ANALOGUE \ - uint8_t trgZL, trgZR; /* ANA{l, l} lowercase=trigger 5bit values {5} */ \ - uint8_t joyLX, joyLY; /* ANA{x, y} left=lowercase 6bit values {6}<-- */ \ - uint8_t joyRX, joyRY; /* ANA{X, Y} 5bit values {5} */ +#define CLASSIC_ANALOGUE \ + uint8_t trgZL, trgZR; /* ANA{l, l} lowercase=trigger 5bit values {5} */ \ + uint8_t joyLX, joyLY; /* ANA{x, y} left=lowercase 6bit values {6}<-- */ \ + uint8_t joyRX, joyRY; /* ANA{X, Y} 5bit values {5} */ //----------------------------------------------------------------------------- // Calibratable controls // -typedef - struct ecCalClassic - { - CLASSIC_ANALOGUE - } -ecCalClassic_t; +typedef struct ecCalClassic { + CLASSIC_ANALOGUE +} ecCalClassic_t; //----------------------------------------------------------------------------- // All controls // -typedef - struct ecDecClassic - { - CLASSIC_ANALOGUE // MUST be first +typedef struct ecDecClassic { + CLASSIC_ANALOGUE // MUST be first - // Digital controls - bool btnZL, btnZR; // BTN{l, l} + // Digital controls + bool btnZL, + btnZR; // BTN{l, l} - bool btnL, btnR; // BTN{L, R} upperrcase=shoulder + bool btnL, btnR; // BTN{L, R} upperrcase=shoulder - bool padU, padL, padD, padR; // BTN{W, A, S, D} + bool padU, padL, padD, padR; // BTN{W, A, S, D} - bool btnM, btnH, btnP; // BTN{-, h, +} + bool btnM, btnH, btnP; // BTN{-, h, +} - bool btnX, btnY; // BTN{x, y} - bool btnA, btnB; // BTN{a, b} + bool btnX, btnY; // BTN{x, y} + bool btnA, btnB; // BTN{a, b} - } -ecDecClassic_t; +} ecDecClassic_t; #undef CLASSIC_ANALOGUE //============================================================================= ======================================== // Function prototypes // -#include // Canvas -typedef struct wiiEC wiiEC_t ; -typedef enum ecCalib ecCalib_t ; -typedef struct state state_t ; -typedef struct eventMsg eventMsg_t ; +#include // Canvas +typedef struct wiiEC wiiEC_t; +typedef enum ecCalib ecCalib_t; +typedef struct state state_t; +typedef struct eventMsg eventMsg_t; -void classic_decode (wiiEC_t* const pec) ; -void classic_msg (wiiEC_t* const pec, FuriMessageQueue* const queue) ; -void classic_calib (wiiEC_t* const pec, ecCalib_t c) ; +void classic_decode(wiiEC_t* const pec); +void classic_msg(wiiEC_t* const pec, FuriMessageQueue* const queue); +void classic_calib(wiiEC_t* const pec, ecCalib_t c); -void classic_show (Canvas* const canvas, state_t* const state) ; -bool classic_key (const eventMsg_t* const msg, state_t* const state) ; +void classic_show(Canvas* const canvas, state_t* const state); +bool classic_key(const eventMsg_t* const msg, state_t* const state); #endif //WII_EC_CLASSIC_H_ diff --git a/applications/plugins/wii_ec_anal/wii_ec_macros.h b/applications/plugins/wii_ec_anal/wii_ec_macros.h index 33daf944d..00ab9825b 100644 --- a/applications/plugins/wii_ec_anal/wii_ec_macros.h +++ b/applications/plugins/wii_ec_anal/wii_ec_macros.h @@ -9,49 +9,53 @@ // //if (furi_message_queue_get_count(queue) > 18) WARN("queue high %d", furi_message_queue_get_count(queue)); -#define MSGQ(lbl) do { \ - msg.wiiEc.in = lbl; \ - furi_message_queue_put(queue, &msg, 0); \ -}while(0) - +#define MSGQ(lbl) \ + do { \ + msg.wiiEc.in = lbl; \ + furi_message_queue_put(queue, &msg, 0); \ + } while(0) // A 'standard' "button" is an independent SPST switch // Eg. Nunchuck 'Z' button // The "value" will always be 0 -#define BUTTON(btn,lbl) do { \ - if (new->btn != old->btn) { \ - msg.wiiEc.type = (new->btn) ? WIIEC_PRESS : WIIEC_RELEASE; \ - msg.wiiEc.val = 0; \ - MSGQ(lbl); \ - } \ -}while(0) +#define BUTTON(btn, lbl) \ + do { \ + if(new->btn != old->btn) { \ + msg.wiiEc.type = (new->btn) ? WIIEC_PRESS : WIIEC_RELEASE; \ + msg.wiiEc.val = 0; \ + MSGQ(lbl); \ + } \ + } while(0) // An "analogue button" is an SPST coupled with an ananlogue 'switch' // Eg. The "bottom out" switches on the triggers of the classic controller // The "value" will be the value of the associated analogue controller -#define ANABTN(btn,ana,lbl) do { \ - if (new->btn != old->btn) { \ - msg.wiiEc.type = (new->btn) ? WIIEC_PRESS : WIIEC_RELEASE; \ - msg.wiiEc.val = new->ana; \ - MSGQ(lbl); \ - } \ -}while(0) +#define ANABTN(btn, ana, lbl) \ + do { \ + if(new->btn != old->btn) { \ + msg.wiiEc.type = (new->btn) ? WIIEC_PRESS : WIIEC_RELEASE; \ + msg.wiiEc.val = new->ana; \ + MSGQ(lbl); \ + } \ + } while(0) -#define ANALOG(ana,lbl) do { \ - if (new->ana != old->ana) { \ - msg.wiiEc.type = WIIEC_ANALOG; \ - msg.wiiEc.val = new->ana; \ - MSGQ(lbl); \ - } \ -}while(0) +#define ANALOG(ana, lbl) \ + do { \ + if(new->ana != old->ana) { \ + msg.wiiEc.type = WIIEC_ANALOG; \ + msg.wiiEc.val = new->ana; \ + MSGQ(lbl); \ + } \ + } while(0) -#define ACCEL(acc,lbl) do { \ - if (new->acc != old->acc) { \ - msg.wiiEc.type = WIIEC_ACCEL; \ - msg.wiiEc.val = new->acc; \ - MSGQ(lbl); \ - } \ -}while(0) +#define ACCEL(acc, lbl) \ + do { \ + if(new->acc != old->acc) { \ + msg.wiiEc.type = WIIEC_ACCEL; \ + msg.wiiEc.val = new->acc; \ + MSGQ(lbl); \ + } \ + } while(0) //----------------------------------------------------------------------------- ---------------------------------------- // CALIBRATION MACROS @@ -61,24 +65,74 @@ // // ... v=variable, n=number // -#define FACTORY_LO(v,n) do{ (dst[1]. v) = n; }while(0) -#define FACTORY_MID(v,n) do{ (dst[2]. v) = n; }while(0) -#define FACTORY_HI(v,n) do{ (dst[3]. v) = n; }while(0) +#define FACTORY_LO(v, n) \ + do { \ + (dst[1].v) = n; \ + } while(0) +#define FACTORY_MID(v, n) \ + do { \ + (dst[2].v) = n; \ + } while(0) +#define FACTORY_HI(v, n) \ + do { \ + (dst[3].v) = n; \ + } while(0) -#define TRACK_LO(v) do{ if ((src-> v) < (dst[0]. v)) (dst[0]. v) = (src-> v); }while(0) -#define TRACK_HI(v) do{ if ((src-> v) > (dst[4]. v)) (dst[4]. v) = (src-> v); }while(0) -#define TRACK_LO_HI(v) do{ TRACK_LO(v); TRACK_HI(v); }while(0) +#define TRACK_LO(v) \ + do { \ + if((src->v) < (dst[0].v)) (dst[0].v) = (src->v); \ + } while(0) +#define TRACK_HI(v) \ + do { \ + if((src->v) > (dst[4].v)) (dst[4].v) = (src->v); \ + } while(0) +#define TRACK_LO_HI(v) \ + do { \ + TRACK_LO(v); \ + TRACK_HI(v); \ + } while(0) -#define RESET_LO(v,b) do{ (dst[0]. v) = (dst[1]. v) = ((1<<(b))-1); }while(0) -#define RESET_HI(v) do{ (dst[4]. v) = (dst[3]. v) = 0; }while(0) -#define RESET_MID(v) do{ (dst[2]. v) = (src-> v); }while(0) -#define RESET_LO_HI(v,b) do{ RESET_LO(v,b); RESET_HI(v); }while(0) -#define RESET_LO_MID_HI(v,b) do{ RESET_LO(v,b); RESET_MID(v); RESET_HI(v); }while(0) +#define RESET_LO(v, b) \ + do { \ + (dst[0].v) = (dst[1].v) = ((1 << (b)) - 1); \ + } while(0) +#define RESET_HI(v) \ + do { \ + (dst[4].v) = (dst[3].v) = 0; \ + } while(0) +#define RESET_MID(v) \ + do { \ + (dst[2].v) = (src->v); \ + } while(0) +#define RESET_LO_HI(v, b) \ + do { \ + RESET_LO(v, b); \ + RESET_HI(v); \ + } while(0) +#define RESET_LO_MID_HI(v, b) \ + do { \ + RESET_LO(v, b); \ + RESET_MID(v); \ + RESET_HI(v); \ + } while(0) -#define RANGE_LO(v) do{ if ((src-> v) < (dst[1]. v)) (dst[1]. v) = (src-> v); }while(0) -#define RANGE_HI(v) do{ if ((src-> v) > (dst[3]. v)) (dst[3]. v) = (src-> v); }while(0) -#define RANGE_LO_HI(v) do{ RANGE_LO(v); RANGE_HI(v); }while(0) +#define RANGE_LO(v) \ + do { \ + if((src->v) < (dst[1].v)) (dst[1].v) = (src->v); \ + } while(0) +#define RANGE_HI(v) \ + do { \ + if((src->v) > (dst[3].v)) (dst[3].v) = (src->v); \ + } while(0) +#define RANGE_LO_HI(v) \ + do { \ + RANGE_LO(v); \ + RANGE_HI(v); \ + } while(0) -#define CENTRE(v) do{ (dst[2]. v) = (src-> v); } while(0) +#define CENTRE(v) \ + do { \ + (dst[2].v) = (src->v); \ + } while(0) #endif //WII_EC_MACROS_H_ diff --git a/applications/plugins/wii_ec_anal/wii_ec_nunchuck.c b/applications/plugins/wii_ec_anal/wii_ec_nunchuck.c index 81c32a243..d88d535b6 100644 --- a/applications/plugins/wii_ec_anal/wii_ec_nunchuck.c +++ b/applications/plugins/wii_ec_anal/wii_ec_nunchuck.c @@ -1,142 +1,144 @@ -#include -#include // Core API +#include +#include // Core API -#include "wii_anal.h" -#include "wii_i2c.h" -#include "bc_logging.h" +#include "wii_anal.h" +#include "wii_i2c.h" +#include "bc_logging.h" -#include "gfx/images.h" // Images -#include "wii_anal_lcd.h" // Drawing functions -#include "wii_anal_keys.h" // key mappings +#include "gfx/images.h" // Images +#include "wii_anal_lcd.h" // Drawing functions +#include "wii_anal_keys.h" // key mappings // ** If you want to see what this source code looks like with all the MACROs expanded // ** grep -v '#include ' wii_ec_nunchuck.c | gcc -E -o /dev/stdout -xc - -# include "wii_ec_macros.h" +#include "wii_ec_macros.h" //+============================================================================ ======================================== // Standard Nunchuck : 2 buttons, 1 analogue joystick, 1 3-axis accelerometer -// -void nunchuck_decode (wiiEC_t* const pec) -{ - ecDecNunchuck_t* p = &pec->dec[(pec->decN = !pec->decN)].nunchuck; - uint8_t* joy = pec->joy; +// +void nunchuck_decode(wiiEC_t* const pec) { + ecDecNunchuck_t* p = &pec->dec[(pec->decN = !pec->decN)].nunchuck; + uint8_t* joy = pec->joy; - p->btnC = !(joy[5] & 0x02); // !{1} - p->btnZ = !(joy[5] & 0x01); // !{1} + p->btnC = !(joy[5] & 0x02); // !{1} + p->btnZ = !(joy[5] & 0x01); // !{1} - p->joyX = joy[0]; // {8} - p->joyY = joy[1]; // {8} + p->joyX = joy[0]; // {8} + p->joyY = joy[1]; // {8} - p->accX = ((uint16_t)joy[2] << 2) | ((joy[5] >>2) & 0x03); // {10} - p->accY = ((uint16_t)joy[3] << 2) | ((joy[5] >>4) & 0x03); // {10} - p->accZ = ((uint16_t)joy[4] << 2) | ((joy[5] >>6) & 0x03); // {10} + p->accX = ((uint16_t)joy[2] << 2) | ((joy[5] >> 2) & 0x03); // {10} + p->accY = ((uint16_t)joy[3] << 2) | ((joy[5] >> 4) & 0x03); // {10} + p->accZ = ((uint16_t)joy[4] << 2) | ((joy[5] >> 6) & 0x03); // {10} - DEBUG(">%d> C:%c, Z:%c, Joy{x:%02X, y:%02X}, Acc{x:%03X, y:%03X, z:%03X}", pec->decN, - (p->btnC ? '#' : '.'), (p->btnZ ? '#' : '.'), - p->joyX, p->joyY, p->accX, p->accY, p->accZ - ); + DEBUG( + ">%d> C:%c, Z:%c, Joy{x:%02X, y:%02X}, Acc{x:%03X, y:%03X, z:%03X}", + pec->decN, + (p->btnC ? '#' : '.'), + (p->btnZ ? '#' : '.'), + p->joyX, + p->joyY, + p->accX, + p->accY, + p->accZ); } //+============================================================================ ======================================== // Give each button a unique character identifier // -void nunchuck_msg (wiiEC_t* const pec, FuriMessageQueue* const queue) -{ - ecDecNunchuck_t* new = &pec->dec[pec->decN].nunchuck; - ecDecNunchuck_t* old = &pec->dec[!pec->decN].nunchuck; +void nunchuck_msg(wiiEC_t* const pec, FuriMessageQueue* const queue) { + ecDecNunchuck_t* new = &pec->dec[pec->decN].nunchuck; + ecDecNunchuck_t* old = &pec->dec[!pec->decN].nunchuck; - eventMsg_t msg = { - .id = EVID_WIIEC, - .wiiEc = { - .type = WIIEC_NONE, - .in = ' ', - .val = 0, - } - }; + eventMsg_t msg = { + .id = EVID_WIIEC, + .wiiEc = { + .type = WIIEC_NONE, + .in = ' ', + .val = 0, + }}; - BUTTON(btnC, 'c'); - BUTTON(btnZ, 'z'); + BUTTON(btnC, 'c'); + BUTTON(btnZ, 'z'); - ANALOG(joyX, 'x'); - ANALOG(joyY, 'y'); + ANALOG(joyX, 'x'); + ANALOG(joyY, 'y'); - ACCEL(accX, 'x'); - ACCEL(accY, 'y'); - ACCEL(accZ, 'z'); + ACCEL(accX, 'x'); + ACCEL(accY, 'y'); + ACCEL(accZ, 'z'); } //+============================================================================ ======================================== // https://www.hackster.io/infusion/using-a-wii-nunchuk-with-arduino-597254#toc-5--read-actual-calibration-data-from-the-device-14 // -void nunchuck_calib (wiiEC_t* const pec, ecCalib_t c) -{ - ecDecNunchuck_t* src = &pec->dec[pec->decN].nunchuck; // from input - ecCalNunchuck_t* dst = pec->calS.nunchuck; // to calibration data +void nunchuck_calib(wiiEC_t* const pec, ecCalib_t c) { + ecDecNunchuck_t* src = &pec->dec[pec->decN].nunchuck; // from input + ecCalNunchuck_t* dst = pec->calS.nunchuck; // to calibration data - if (c & CAL_RESET) { // initialise ready for software calibration - // LO is set to the MAXIMUM value (so it can be reduced) - // HI is set to ZERO (so it can be increased) - RESET_LO_HI(accX, 10); // 10bit value - RESET_LO_HI(accY, 10); // 10bit value - RESET_LO_HI(accZ, 10); // 10bit value + if(c & CAL_RESET) { // initialise ready for software calibration + // LO is set to the MAXIMUM value (so it can be reduced) + // HI is set to ZERO (so it can be increased) + RESET_LO_HI(accX, 10); // 10bit value + RESET_LO_HI(accY, 10); // 10bit value + RESET_LO_HI(accZ, 10); // 10bit value - RESET_LO_HI(joyX, 8); // 8bit value - RESET_LO_HI(joyY, 8); // 8bit value - } - if (c & CAL_FACTORY) { // (re)set to factory defaults - //! "[4] LSB of Zero value of X,Y,Z axes" ...helpful! - //! ...Well, my test nunchuck has bits set in the bottom 6 bits, so let's guess ;) + RESET_LO_HI(joyX, 8); // 8bit value + RESET_LO_HI(joyY, 8); // 8bit value + } + if(c & CAL_FACTORY) { // (re)set to factory defaults + //! "[4] LSB of Zero value of X,Y,Z axes" ...helpful! + //! ...Well, my test nunchuck has bits set in the bottom 6 bits, so let's guess ;) - // No value available - annecdotal tests suggest 8 is reasonable - FACTORY_LO( accX, 8); - FACTORY_LO( accY, 8); - FACTORY_LO( accZ, 8); + // No value available - annecdotal tests suggest 8 is reasonable + FACTORY_LO(accX, 8); + FACTORY_LO(accY, 8); + FACTORY_LO(accZ, 8); - // @ 0G - FACTORY_MID( accX, ((pec->calF[0] <<2) | ((pec->calF[3] >>4) &0x3)) ) ; - FACTORY_MID( accY, ((pec->calF[1] <<2) | ((pec->calF[3] >>2) &0x3)) ) ; - FACTORY_MID( accZ, ((pec->calF[2] <<2) | ((pec->calF[3] ) &0x3)) ) ; + // @ 0G + FACTORY_MID(accX, ((pec->calF[0] << 2) | ((pec->calF[3] >> 4) & 0x3))); + FACTORY_MID(accY, ((pec->calF[1] << 2) | ((pec->calF[3] >> 2) & 0x3))); + FACTORY_MID(accZ, ((pec->calF[2] << 2) | ((pec->calF[3]) & 0x3))); - // @ 1G - FACTORY_HI( accX, ((pec->calF[4] <<2) | ((pec->calF[7] >>4) &0x3)) ) ; - FACTORY_HI( accY, ((pec->calF[5] <<2) | ((pec->calF[7] >>2) &0x3)) ) ; - FACTORY_HI( accZ, ((pec->calF[6] <<2) | ((pec->calF[7] ) &0x3)) ) ; + // @ 1G + FACTORY_HI(accX, ((pec->calF[4] << 2) | ((pec->calF[7] >> 4) & 0x3))); + FACTORY_HI(accY, ((pec->calF[5] << 2) | ((pec->calF[7] >> 2) & 0x3))); + FACTORY_HI(accZ, ((pec->calF[6] << 2) | ((pec->calF[7]) & 0x3))); - // Joysticks - FACTORY_LO( joyX, pec->calF[ 9] ) ; - FACTORY_MID(joyX, pec->calF[10] ) ; - FACTORY_HI( joyX, pec->calF[ 8] ) ; + // Joysticks + FACTORY_LO(joyX, pec->calF[9]); + FACTORY_MID(joyX, pec->calF[10]); + FACTORY_HI(joyX, pec->calF[8]); - FACTORY_LO( joyY, pec->calF[12] ) ; - FACTORY_MID(joyY, pec->calF[13] ) ; - FACTORY_HI( joyY, pec->calF[11] ) ; - } - if (c & CAL_TRACK) { // track maximum and minimum values seen - TRACK_LO_HI(accX); - TRACK_LO_HI(accY); - TRACK_LO_HI(accZ); + FACTORY_LO(joyY, pec->calF[12]); + FACTORY_MID(joyY, pec->calF[13]); + FACTORY_HI(joyY, pec->calF[11]); + } + if(c & CAL_TRACK) { // track maximum and minimum values seen + TRACK_LO_HI(accX); + TRACK_LO_HI(accY); + TRACK_LO_HI(accZ); - TRACK_LO_HI(joyX); - TRACK_LO_HI(joyY); - } - if (c & CAL_RANGE) { // perform software calibration step - RANGE_LO_HI(accX); - RANGE_LO_HI(accY); - RANGE_LO_HI(accZ); + TRACK_LO_HI(joyX); + TRACK_LO_HI(joyY); + } + if(c & CAL_RANGE) { // perform software calibration step + RANGE_LO_HI(accX); + RANGE_LO_HI(accY); + RANGE_LO_HI(accZ); - if (!(c & CAL_NOTJOY)) { // double negative! - RANGE_LO_HI(joyX); - RANGE_LO_HI(joyY); - } - } - if (c & CAL_CENTRE) { // reset centre point of joystick - CENTRE(accX); - CENTRE(accY); - CENTRE(accZ); + if(!(c & CAL_NOTJOY)) { // double negative! + RANGE_LO_HI(joyX); + RANGE_LO_HI(joyY); + } + } + if(c & CAL_CENTRE) { // reset centre point of joystick + CENTRE(accX); + CENTRE(accY); + CENTRE(accZ); - CENTRE(joyX); - CENTRE(joyY); - } + CENTRE(joyX); + CENTRE(joyY); + } } //============================================================================= ======================================== @@ -152,308 +154,323 @@ void nunchuck_calib (wiiEC_t* const pec, ecCalib_t c) // // EG. Move left will effect X ; turn left will effect Y & Z // -#define aw 110 // axis width -#define ah 15 // height {0......7......14} -#define am 7 // midpoint { 7 } -#define ar 7 // range {1234567 1234567} +#define aw 110 // axis width +#define ah 15 // height {0......7......14} +#define am 7 // midpoint { 7 } +#define ar 7 // range {1234567 1234567} enum { - ACC_X = 0, - ACC_Y = 1, - ACC_Z = 2, - ACC_CNT = 3, - ACC_1 = ACC_X, // first - ACC_N = ACC_Z, // last + ACC_X = 0, + ACC_Y = 1, + ACC_Z = 2, + ACC_CNT = 3, + ACC_1 = ACC_X, // first + ACC_N = ACC_Z, // last }; //+============================================================================ -static -void nunchuck_showAcc (Canvas* const canvas, state_t* const state) -{ - ecDecNunchuck_t* d = &state->ec.dec[state->ec.decN].nunchuck; - ecCalNunchuck_t* lo = &state->ec.calS.nunchuck[1]; - ecCalNunchuck_t* mid = &state->ec.calS.nunchuck[2]; - ecCalNunchuck_t* hi = &state->ec.calS.nunchuck[3]; +static void nunchuck_showAcc(Canvas* const canvas, state_t* const state) { + ecDecNunchuck_t* d = &state->ec.dec[state->ec.decN].nunchuck; + ecCalNunchuck_t* lo = &state->ec.calS.nunchuck[1]; + ecCalNunchuck_t* mid = &state->ec.calS.nunchuck[2]; + ecCalNunchuck_t* hi = &state->ec.calS.nunchuck[3]; - int y[ACC_CNT] = {0, 0+(ah+4), 0+((ah+4)*2)}; - int x = 10; + int y[ACC_CNT] = {0, 0 + (ah + 4), 0 + ((ah + 4) * 2)}; + int x = 10; - static uint16_t v[ACC_CNT][aw] = {0}; -// static uint16_t tv[ACC_CNT][aw] = {0}; + static uint16_t v[ACC_CNT][aw] = {0}; + // static uint16_t tv[ACC_CNT][aw] = {0}; - static uint16_t idx = 0; - static uint16_t cnt = aw -1; + static uint16_t idx = 0; + static uint16_t cnt = aw - 1; - // Only record when scanner NOT-paused - if (!state->pause) { - uint16_t dead = (1<<5); + // Only record when scanner NOT-paused + if(!state->pause) { + uint16_t dead = (1 << 5); - // Find axes y-offsets - for (int a = ACC_1; a <= ACC_N; a++) { - uint16_t* dp = NULL; // data value (current reading) - uint16_t* lp = NULL; // lo value - uint16_t* mp = NULL; // mid value - uint16_t* hp = NULL; // hi value - uint16_t* vp = NULL; // value (result) + // Find axes y-offsets + for(int a = ACC_1; a <= ACC_N; a++) { + uint16_t* dp = NULL; // data value (current reading) + uint16_t* lp = NULL; // lo value + uint16_t* mp = NULL; // mid value + uint16_t* hp = NULL; // hi value + uint16_t* vp = NULL; // value (result) - switch (a) { - case ACC_X: - dp = & d->accX; // data (input) - lp = & lo->accX; // low \. - mp = &mid->accX; // mid > calibration - hp = & hi->accX; // high / - vp = &v[ ACC_X][idx]; // value (where to store the result) - break; - case ACC_Y: - dp = & d->accY; - lp = & lo->accY; - mp = &mid->accY; - hp = & hi->accY; - vp = &v[ ACC_Y][idx]; - break; - case ACC_Z: - dp = & d->accZ; - lp = & lo->accZ; - mp = &mid->accZ; - hp = & hi->accZ; - vp = &v[ ACC_Z][idx]; - break; - default: break ; - } + switch(a) { + case ACC_X: + dp = &d->accX; // data (input) + lp = &lo->accX; // low \. + mp = &mid->accX; // mid > calibration + hp = &hi->accX; // high / + vp = &v[ACC_X][idx]; // value (where to store the result) + break; + case ACC_Y: + dp = &d->accY; + lp = &lo->accY; + mp = &mid->accY; + hp = &hi->accY; + vp = &v[ACC_Y][idx]; + break; + case ACC_Z: + dp = &d->accZ; + lp = &lo->accZ; + mp = &mid->accZ; + hp = &hi->accZ; + vp = &v[ACC_Z][idx]; + break; + default: + break; + } - // Again - qv. the joysick calibration: - // This is not the "right way" to do this, it is just "one way" to do it - // ...mid point and extreme zones have a deadzone - // ...the rest is evenly divided by the amount of space on the graph - if ((*dp >= (*mp -dead)) && (*dp <= (*mp +dead))) *vp = ar ; - else if (*dp >= (*hp -dead)) *vp = ah-1 ; - else if (*dp <= (*lp +dead)) *vp = 0 ; - else if (*dp < *mp) { - uint16_t min = ((*lp +dead) +1); - uint16_t max = ((*mp -dead) -1); - float range = (max -min) +1; - float m = range /(ar-1); // 6 evenly(/fairly) divided zones - *vp = ((int)((*dp -min) /m)) +1; + // Again - qv. the joysick calibration: + // This is not the "right way" to do this, it is just "one way" to do it + // ...mid point and extreme zones have a deadzone + // ...the rest is evenly divided by the amount of space on the graph + if((*dp >= (*mp - dead)) && (*dp <= (*mp + dead))) + *vp = ar; + else if(*dp >= (*hp - dead)) + *vp = ah - 1; + else if(*dp <= (*lp + dead)) + *vp = 0; + else if(*dp < *mp) { + uint16_t min = ((*lp + dead) + 1); + uint16_t max = ((*mp - dead) - 1); + float range = (max - min) + 1; + float m = range / (ar - 1); // 6 evenly(/fairly) divided zones + *vp = ((int)((*dp - min) / m)) + 1; - } else {//if (*dp > *mp) - uint16_t min = ((*mp +dead) +1); - uint16_t max = ((*hp -dead) -1); - float range = (max -min) +1; - float m = range /(ar-1); // 6 evenly(/fairly) divided zones - *vp = ((int)((*dp -min) /m)) +1 +ar; - } - } + } else { //if (*dp > *mp) + uint16_t min = ((*mp + dead) + 1); + uint16_t max = ((*hp - dead) - 1); + float range = (max - min) + 1; + float m = range / (ar - 1); // 6 evenly(/fairly) divided zones + *vp = ((int)((*dp - min) / m)) + 1 + ar; + } + } -//! If we decide to offer "export to CSV" -//! I suggest we keep a second array of true-values, rather than do all the maths every time -//! Also - the data will need to me moved to the 'state' table - so a.n.other function can save it off -// tv[ACC_X][idx] = d->accX; -// tv[ACC_Y][idx] = d->accY; -// tv[ACC_Z][idx] = d->accZ; + //! If we decide to offer "export to CSV" + //! I suggest we keep a second array of true-values, rather than do all the maths every time + //! Also - the data will need to me moved to the 'state' table - so a.n.other function can save it off + // tv[ACC_X][idx] = d->accX; + // tv[ACC_Y][idx] = d->accY; + // tv[ACC_Z][idx] = d->accZ; - // Prepare for the next datapoint - if (++idx >= aw) idx = 0 ; - if (cnt) cnt-- ; - } + // Prepare for the next datapoint + if(++idx >= aw) idx = 0; + if(cnt) cnt--; + } - // Auto-pause - if (state->apause && !idx) state->pause = true ; + // Auto-pause + if(state->apause && !idx) state->pause = true; - // *** Draw axes *** - show(canvas, 0,y[ACC_X] +((ah -img_6x8_X.h) /2), &img_6x8_X, SHOW_SET_BLK); - show(canvas, 0,y[ACC_Y] +((ah -img_6x8_Y.h) /2), &img_6x8_Y, SHOW_SET_BLK); - show(canvas, 0,y[ACC_Z] +((ah -img_6x8_Z.h) /2), &img_6x8_Z, SHOW_SET_BLK); + // *** Draw axes *** + show(canvas, 0, y[ACC_X] + ((ah - img_6x8_X.h) / 2), &img_6x8_X, SHOW_SET_BLK); + show(canvas, 0, y[ACC_Y] + ((ah - img_6x8_Y.h) / 2), &img_6x8_Y, SHOW_SET_BLK); + show(canvas, 0, y[ACC_Z] + ((ah - img_6x8_Z.h) / 2), &img_6x8_Z, SHOW_SET_BLK); - canvas_set_color(canvas, ColorBlack); - for (int a = ACC_1; a <= ACC_N; a++) { - canvas_draw_line(canvas, x-1,y[a] , x -1,y[a]+ah); - canvas_draw_line(canvas, x ,y[a]+ah, x+aw-1,y[a]+ah); + canvas_set_color(canvas, ColorBlack); + for(int a = ACC_1; a <= ACC_N; a++) { + canvas_draw_line(canvas, x - 1, y[a], x - 1, y[a] + ah); + canvas_draw_line(canvas, x, y[a] + ah, x + aw - 1, y[a] + ah); - // Mid & Peak lines - for (int i = 1; i < aw; i += 3) { - canvas_draw_dot(canvas, x+i,y[a]); - canvas_draw_dot(canvas, x+i,y[a] +(ah /2)); - } - } + // Mid & Peak lines + for(int i = 1; i < aw; i += 3) { + canvas_draw_dot(canvas, x + i, y[a]); + canvas_draw_dot(canvas, x + i, y[a] + (ah / 2)); + } + } - // Data (wiper display - see notes.txt for scrolling algorithm) - int end = idx ? idx : aw; - for (int a = ACC_1; a <= ACC_N; a++) { - canvas_draw_dot(canvas, x,y[a]+v[a][idx]); - for (int i = 1; i < end; i++) - canvas_draw_line(canvas, x+i,y[a]+v[a][i-1] , x+i,y[a]+v[a][i]); - if (!state->apause) - for (int i = end+10; i < aw -cnt; i++) - canvas_draw_line(canvas, x+i,y[a]+v[a][i-1] , x+i,y[a]+v[a][i]); - } - // Wipe bar - if (end < aw) canvas_draw_line(canvas, x+end,y[0], x+end,y[2]+ah-1); - if (++end < aw) canvas_draw_line(canvas, x+end,y[0], x+end,y[2]+ah-1); - if (++end < aw) canvas_draw_line(canvas, x+end,y[0], x+end,y[2]+ah-1); + // Data (wiper display - see notes.txt for scrolling algorithm) + int end = idx ? idx : aw; + for(int a = ACC_1; a <= ACC_N; a++) { + canvas_draw_dot(canvas, x, y[a] + v[a][idx]); + for(int i = 1; i < end; i++) + canvas_draw_line(canvas, x + i, y[a] + v[a][i - 1], x + i, y[a] + v[a][i]); + if(!state->apause) + for(int i = end + 10; i < aw - cnt; i++) + canvas_draw_line(canvas, x + i, y[a] + v[a][i - 1], x + i, y[a] + v[a][i]); + } + // Wipe bar + if(end < aw) canvas_draw_line(canvas, x + end, y[0], x + end, y[2] + ah - 1); + if(++end < aw) canvas_draw_line(canvas, x + end, y[0], x + end, y[2] + ah - 1); + if(++end < aw) canvas_draw_line(canvas, x + end, y[0], x + end, y[2] + ah - 1); - // *** Mode buttons *** - show(canvas, 0,55, &img_key_L, SHOW_SET_BLK); // mode key + // *** Mode buttons *** + show(canvas, 0, 55, &img_key_L, SHOW_SET_BLK); // mode key - if ((state->calib & CAL_RANGE) || state->pause) state->flash++ ; + if((state->calib & CAL_RANGE) || state->pause) state->flash++; - // -pause- ...yeah, this got a little out of hand! LOL! - if (state->pause || state->apause) { - if (state->pause && state->apause && !idx) { - if (state->flash &8) { - show(canvas, 108,56, &img_key_U, SHOW_SET_BLK); - } else { - show(canvas, 108,56, &img_key_Ui, SHOW_SET_BLK); - canvas_draw_line(canvas, x+aw,y[0], x+aw,y[2]+ah-1); - } - } else { - show(canvas, 108,56, &img_key_Ui, SHOW_SET_BLK); - } - } else { - show(canvas, 108,56, &img_key_U, SHOW_SET_BLK); // pause - } + // -pause- ...yeah, this got a little out of hand! LOL! + if(state->pause || state->apause) { + if(state->pause && state->apause && !idx) { + if(state->flash & 8) { + show(canvas, 108, 56, &img_key_U, SHOW_SET_BLK); + } else { + show(canvas, 108, 56, &img_key_Ui, SHOW_SET_BLK); + canvas_draw_line(canvas, x + aw, y[0], x + aw, y[2] + ah - 1); + } + } else { + show(canvas, 108, 56, &img_key_Ui, SHOW_SET_BLK); + } + } else { + show(canvas, 108, 56, &img_key_U, SHOW_SET_BLK); // pause + } - // -calibration- - if (state->calib & CAL_RANGE) { - show(canvas, 119,55, (state->flash &8) ? &img_key_OKi : &img_key_OK, SHOW_SET_BLK); - } else { - show(canvas, 119,55, &img_key_OK, SHOW_SET_BLK); - } + // -calibration- + if(state->calib & CAL_RANGE) { + show(canvas, 119, 55, (state->flash & 8) ? &img_key_OKi : &img_key_OK, SHOW_SET_BLK); + } else { + show(canvas, 119, 55, &img_key_OK, SHOW_SET_BLK); + } } -# undef aw -# undef ah -# undef am -# undef ar +#undef aw +#undef ah +#undef am +#undef ar //+============================================================================ ======================================== // Default nunchuck screen // -void nunchuck_show (Canvas* const canvas, state_t* const state) -{ - // Nunchucks have TWO scenes - if (state->scene == SCENE_NUNCHUCK_ACC) return nunchuck_showAcc(canvas, state) ; +void nunchuck_show(Canvas* const canvas, state_t* const state) { + // Nunchucks have TWO scenes + if(state->scene == SCENE_NUNCHUCK_ACC) return nunchuck_showAcc(canvas, state); - // Default scene - ecDecNunchuck_t* d = &state->ec.dec[state->ec.decN].nunchuck; - ecCalNunchuck_t* c = (state->hold) ? &state->ec.calS.nunchuck[(state->hold < 0) ? 0 : 4] - : (ecCalNunchuck_t*)d ; //! danger will robinson! - ecCalNunchuck_t* js = state->ec.calS.nunchuck; + // Default scene + ecDecNunchuck_t* d = &state->ec.dec[state->ec.decN].nunchuck; + ecCalNunchuck_t* c = (state->hold) ? &state->ec.calS.nunchuck[(state->hold < 0) ? 0 : 4] : + (ecCalNunchuck_t*)d; //! danger will robinson! + ecCalNunchuck_t* js = state->ec.calS.nunchuck; - // X, Y, Z - show(canvas, 42,0, &img_6x8_X, SHOW_SET_BLK); - show(canvas, 73,0, &img_6x8_Y, SHOW_SET_BLK); - show(canvas, 104,0, &img_6x8_Z, SHOW_SET_BLK); + // X, Y, Z + show(canvas, 42, 0, &img_6x8_X, SHOW_SET_BLK); + show(canvas, 73, 0, &img_6x8_Y, SHOW_SET_BLK); + show(canvas, 104, 0, &img_6x8_Z, SHOW_SET_BLK); - canvas_draw_str_aligned(canvas, 0,14, AlignLeft, AlignTop, "Accel"); - canvas_draw_str_aligned(canvas, 0,28, AlignLeft, AlignTop, "Joy"); + canvas_draw_str_aligned(canvas, 0, 14, AlignLeft, AlignTop, "Accel"); + canvas_draw_str_aligned(canvas, 0, 28, AlignLeft, AlignTop, "Joy"); - // accel values - showHex(canvas, 34,12, c->accX, 3,2); - showHex(canvas, 65,12, c->accY, 3,2); - showHex(canvas, 96,12, c->accZ, 3,2); - // Joy values - showHex(canvas, 38,27, c->joyX, 2,2); - showHex(canvas, 69,27, c->joyY, 2,2); + // accel values + showHex(canvas, 34, 12, c->accX, 3, 2); + showHex(canvas, 65, 12, c->accY, 3, 2); + showHex(canvas, 96, 12, c->accZ, 3, 2); + // Joy values + showHex(canvas, 38, 27, c->joyX, 2, 2); + showHex(canvas, 69, 27, c->joyY, 2, 2); - showJoy(canvas, 103,32, js[1].joyX, js[2].joyX, js[3].joyX, - js[1].joyY, js[2].joyY, js[3].joyY, d->joyX,d->joyY, 8); + showJoy( + canvas, + 103, + 32, + js[1].joyX, + js[2].joyX, + js[3].joyX, + js[1].joyY, + js[2].joyY, + js[3].joyY, + d->joyX, + d->joyY, + 8); - // buttons - canvas_set_color(canvas, ColorBlack); - canvas_draw_str_aligned(canvas, 0,44, AlignLeft, AlignTop, "Button"); + // buttons + canvas_set_color(canvas, ColorBlack); + canvas_draw_str_aligned(canvas, 0, 44, AlignLeft, AlignTop, "Button"); - if (!d->btnC) { - canvas_draw_rframe(canvas, 36,42, 18,12, 6); - show(canvas, 42,44, &img_6x8_C, SHOW_SET_BLK); - } else { - canvas_draw_rbox(canvas, 36,42, 18,12, 6); - show(canvas, 42,44, &img_6x8_C, SHOW_SET_WHT); - canvas_set_color(canvas, ColorBlack); - } + if(!d->btnC) { + canvas_draw_rframe(canvas, 36, 42, 18, 12, 6); + show(canvas, 42, 44, &img_6x8_C, SHOW_SET_BLK); + } else { + canvas_draw_rbox(canvas, 36, 42, 18, 12, 6); + show(canvas, 42, 44, &img_6x8_C, SHOW_SET_WHT); + canvas_set_color(canvas, ColorBlack); + } - if (!d->btnZ) { - canvas_draw_rframe(canvas, 64,40, 24,16, 2); - show(canvas, 73,44, &img_6x8_Z, SHOW_SET_BLK); - } else { - canvas_draw_rbox(canvas, 64,40, 24,16, 2); - show(canvas, 73,44, &img_6x8_Z, SHOW_SET_WHT); - } + if(!d->btnZ) { + canvas_draw_rframe(canvas, 64, 40, 24, 16, 2); + show(canvas, 73, 44, &img_6x8_Z, SHOW_SET_BLK); + } else { + canvas_draw_rbox(canvas, 64, 40, 24, 16, 2); + show(canvas, 73, 44, &img_6x8_Z, SHOW_SET_WHT); + } - // Navigation - showPeakHold(state, canvas, state->hold); // peak keys - show(canvas, 0,55, &img_key_L, SHOW_SET_BLK); // mode keys - show(canvas, 9,55, &img_key_R, SHOW_SET_BLK); + // Navigation + showPeakHold(state, canvas, state->hold); // peak keys + show(canvas, 0, 55, &img_key_L, SHOW_SET_BLK); // mode keys + show(canvas, 9, 55, &img_key_R, SHOW_SET_BLK); } //+============================================================================ ======================================== -static -bool nunchuck_keyAcc (const eventMsg_t* const msg, state_t* const state) -{ - int used = false; // assume key is NOT-handled +static bool nunchuck_keyAcc(const eventMsg_t* const msg, state_t* const state) { + int used = false; // assume key is NOT-handled - switch (msg->input.type) { - case InputTypeShort: //# input.key) { - case InputKeyDown: //# input.type) { + case InputTypeShort: //# input.key) { + case InputKeyDown: //# pause) state->pause = false ; // Paused? Restart - else state->apause = !state->apause ; // No? toggle auto-pause - used = true; - break; + case InputKeyUp: //# pause) + state->pause = false; // Paused? Restart + else + state->apause = !state->apause; // No? toggle auto-pause + used = true; + break; - case InputKeyLeft: //# calib &= ~CAL_NOTJOY; // DO calibrate joystick in NUNCHUCK mode - used = true; - break; + case InputKeyLeft: //# calib &= ~CAL_NOTJOY; // DO calibrate joystick in NUNCHUCK mode + used = true; + break; - default: break ; //# scene == SCENE_NUNCHUCK_ACC) return nunchuck_keyAcc(msg, state) ; +bool nunchuck_key(const eventMsg_t* const msg, state_t* const state) { + // Nunchucks have TWO scenes + if(state->scene == SCENE_NUNCHUCK_ACC) return nunchuck_keyAcc(msg, state); - // Default scene - int used = false; // assume key is NOT-handled + // Default scene + int used = false; // assume key is NOT-handled - switch (msg->input.type) { - case InputTypeShort: //# input.key) { - case InputKeyLeft: //# input.type) { + case InputTypeShort: //# input.key) { + case InputKeyLeft: //# calib |= CAL_NOTJOY; // do NOT calibrate joystick in _ACC mode - used = true; - break; - default: break ; //# calib |= CAL_NOTJOY; // do NOT calibrate joystick in _ACC mode + used = true; + break; + default: + break; //# -#include +#include +#include //----------------------------------------------------------------------------- // Controllers which have calibration must have their calibratable controls here //! Is there a better way to get the start of the decode struct to match the calibration struct ? #define NUNCHUCK_ANALOGUE \ - uint8_t joyX, joyY; \ - uint16_t accX, accY, accZ; + uint8_t joyX, joyY; \ + uint16_t accX, accY, accZ; //----------------------------------------------------------------------------- // Calibratable controls // -typedef - struct ecCalNunchuck { - NUNCHUCK_ANALOGUE - } -ecCalNunchuck_t; +typedef struct ecCalNunchuck { + NUNCHUCK_ANALOGUE +} ecCalNunchuck_t; //----------------------------------------------------------------------------- // All controls // -typedef - struct ecDecNunchuck { - NUNCHUCK_ANALOGUE // MUST be first +typedef struct ecDecNunchuck { + NUNCHUCK_ANALOGUE // MUST be first - // Digital controls - bool btnC, btnZ; // BTN{c, z} - } -ecDecNunchuck_t; + // Digital controls + bool btnC, + btnZ; // BTN{c, z} +} ecDecNunchuck_t; #undef NUNCHUCK_ANALOGUE //============================================================================= // Function prototypes // -#include // Canvas -typedef struct wiiEC wiiEC_t ; -typedef enum ecCalib ecCalib_t ; -typedef struct state state_t ; -typedef struct eventMsg eventMsg_t ; +#include // Canvas +typedef struct wiiEC wiiEC_t; +typedef enum ecCalib ecCalib_t; +typedef struct state state_t; +typedef struct eventMsg eventMsg_t; -void nunchuck_decode (wiiEC_t* const pec) ; -void nunchuck_msg (wiiEC_t* const pec, FuriMessageQueue* const queue) ; -void nunchuck_calib (wiiEC_t* const pec, ecCalib_t c) ; +void nunchuck_decode(wiiEC_t* const pec); +void nunchuck_msg(wiiEC_t* const pec, FuriMessageQueue* const queue); +void nunchuck_calib(wiiEC_t* const pec, ecCalib_t c); -void nunchuck_show (Canvas* const canvas, state_t* const state) ; -bool nunchuck_key (const eventMsg_t* const msg, state_t* const state) ; +void nunchuck_show(Canvas* const canvas, state_t* const state); +bool nunchuck_key(const eventMsg_t* const msg, state_t* const state); #endif //WII_EC_NUNCHUCK_H_ diff --git a/applications/plugins/wii_ec_anal/wii_ec_udraw.c b/applications/plugins/wii_ec_anal/wii_ec_udraw.c index babbc92ab..82987b205 100644 --- a/applications/plugins/wii_ec_anal/wii_ec_udraw.c +++ b/applications/plugins/wii_ec_anal/wii_ec_udraw.c @@ -1,16 +1,16 @@ //! udraw support is NOT written - this is just notes about the init function -#include -#include // Core API +#include +#include // Core API -#include "wii_anal.h" -#include "wii_ec.h" -#include "bc_logging.h" +#include "wii_anal.h" +#include "wii_ec.h" +#include "bc_logging.h" -#include "i2c_workaround.h" //! temporary workaround for a bug in furi i2c [see header] +#include "i2c_workaround.h" //! temporary workaround for a bug in furi i2c [see header] // ** If you want to see what this source code looks like with all the MACROs expanded // ** grep -v '#include ' wii_ec_udraw.c | gcc -E -o /dev/stdout -xc - -# include "wii_ec_macros.h" +#include "wii_ec_macros.h" //+============================================================================ ======================================== // https://github.com/madhephaestus/WiiChuck/blob/master/src/Drawsome.cpp#L3 @@ -27,13 +27,12 @@ // read 6 bytes starting from 0x00 (#3) // read 6 bytes starting from 0x00 (#4) // -bool udraw_init (wiiEC_t* const pec) -{ - ENTER; - bool rv = true; +bool udraw_init(wiiEC_t* const pec) { + ENTER; + bool rv = true; -(void)pec; -/* + (void)pec; + /* //! this is the Drawsome code, NOT the uDraw code !! static const uint8_t reg[9] = {0x20, 0x28, 0x30, 0x38, 0x00, 0x00, 0xFB, 0x00, 0x00}; // 0..8 const uint8_t* p = reg; @@ -72,74 +71,79 @@ fail: done: */ - LEAVE; - return rv; + LEAVE; + return rv; } //+============================================================================ ======================================== -bool udraw_key (const eventMsg_t* const msg, state_t* const state) -{ -(void)state; - bool run = true; +bool udraw_key(const eventMsg_t* const msg, state_t* const state) { + (void)state; + bool run = true; - switch (msg->input.type) { - case InputTypeShort: //# input.key) { - case InputKeyUp: //# ! After INPUT_LONG_PRESS interval, asynch to InputTypeRelease - switch (msg->input.key) { - case InputKeyUp: //# >U [ LONG-UP ] - case InputKeyDown: //# >D [ LONG-DOWN ] - case InputKeyLeft: //# >L [ LONG-LEFT ] - case InputKeyRight: //# >R [ LONG-RIGHT ] - case InputKeyOk: //# >O [ LONG-OK ] - case InputKeyBack: //# >B [ LONG-BACK ] - default: break ; //# >? - } - break; - case InputTypePress: //# +! After debounce - switch (msg->input.key) { - case InputKeyUp: //# +U [ SHORT-UP ] - case InputKeyDown: //# +D [ SHORT-DOWN ] - case InputKeyLeft: //# +L [ SHORT-LEFT ] - case InputKeyRight: //# +R [ SHORT-RIGHT ] - case InputKeyOk: //# +O [ SHORT-OK ] - case InputKeyBack: //# +B [ SHORT-BACK ] - default: break ; //# +? - } - break; - case InputTypeRepeat: //# *! With INPUT_REPEATE_PRESS period after InputTypeLong event - switch (msg->input.key) { - case InputKeyUp: //# *U [ REPEAT-UP ] - case InputKeyDown: //# *D [ REPEAT-DOWN ] - case InputKeyLeft: //# *L [ REPEAT-LEFT ] - case InputKeyRight: //# *R [ REPEAT-RIGHT ] - case InputKeyOk: //# *O [ REPEAT-OK ] - case InputKeyBack: //# *B [ REPEAT-BACK ] - default: break ; //# *? - } - break; - case InputTypeRelease: //# -! After debounce - switch (msg->input.key) { - case InputKeyUp: //# -U [ RELEASE-UP ] - case InputKeyDown: //# -D [ RELEASE-DOWN ] - case InputKeyLeft: //# -L [ RELEASE-LEFT ] - case InputKeyRight: //# -R [ RELEASE-RIGHT ] - case InputKeyOk: //# -O [ RELEASE-OK ] - case InputKeyBack: //# -B [ RELEASE-BACK ] - default: break ; //# -? - } - break; - default: return true ; - } + switch(msg->input.type) { + case InputTypeShort: //# input.key) { + case InputKeyUp: //# ! After INPUT_LONG_PRESS interval, asynch to InputTypeRelease + switch(msg->input.key) { + case InputKeyUp: //# >U [ LONG-UP ] + case InputKeyDown: //# >D [ LONG-DOWN ] + case InputKeyLeft: //# >L [ LONG-LEFT ] + case InputKeyRight: //# >R [ LONG-RIGHT ] + case InputKeyOk: //# >O [ LONG-OK ] + case InputKeyBack: //# >B [ LONG-BACK ] + default: + break; //# >? + } + break; + case InputTypePress: //# +! After debounce + switch(msg->input.key) { + case InputKeyUp: //# +U [ SHORT-UP ] + case InputKeyDown: //# +D [ SHORT-DOWN ] + case InputKeyLeft: //# +L [ SHORT-LEFT ] + case InputKeyRight: //# +R [ SHORT-RIGHT ] + case InputKeyOk: //# +O [ SHORT-OK ] + case InputKeyBack: //# +B [ SHORT-BACK ] + default: + break; //# +? + } + break; + case InputTypeRepeat: //# *! With INPUT_REPEATE_PRESS period after InputTypeLong event + switch(msg->input.key) { + case InputKeyUp: //# *U [ REPEAT-UP ] + case InputKeyDown: //# *D [ REPEAT-DOWN ] + case InputKeyLeft: //# *L [ REPEAT-LEFT ] + case InputKeyRight: //# *R [ REPEAT-RIGHT ] + case InputKeyOk: //# *O [ REPEAT-OK ] + case InputKeyBack: //# *B [ REPEAT-BACK ] + default: + break; //# *? + } + break; + case InputTypeRelease: //# -! After debounce + switch(msg->input.key) { + case InputKeyUp: //# -U [ RELEASE-UP ] + case InputKeyDown: //# -D [ RELEASE-DOWN ] + case InputKeyLeft: //# -L [ RELEASE-LEFT ] + case InputKeyRight: //# -R [ RELEASE-RIGHT ] + case InputKeyOk: //# -O [ RELEASE-OK ] + case InputKeyBack: //# -B [ RELEASE-BACK ] + default: + break; //# -? + } + break; + default: + return true; + } - return run; + return run; } diff --git a/applications/plugins/wii_ec_anal/wii_ec_udraw.h b/applications/plugins/wii_ec_anal/wii_ec_udraw.h index 1721894e5..9283fd95d 100644 --- a/applications/plugins/wii_ec_anal/wii_ec_udraw.h +++ b/applications/plugins/wii_ec_anal/wii_ec_udraw.h @@ -1,18 +1,18 @@ -#ifndef WII_EC_UDRAW_H_ -#define WII_EC_UDRAW_H_ +#ifndef WII_EC_UDRAW_H_ +#define WII_EC_UDRAW_H_ -#include -#include +#include +#include //============================================================================= ======================================= // Function prototypes // -typedef struct wiiEC wiiEC_t ; -typedef enum ecCalib ecCalib_t ; -typedef struct eventMsg eventMsg_t ; -typedef struct state state_t ; +typedef struct wiiEC wiiEC_t; +typedef enum ecCalib ecCalib_t; +typedef struct eventMsg eventMsg_t; +typedef struct state state_t; -bool udraw_init (wiiEC_t* const pec) ; -bool udraw_key (const eventMsg_t* const msg, state_t* const state) ; +bool udraw_init(wiiEC_t* const pec); +bool udraw_key(const eventMsg_t* const msg, state_t* const state); #endif //WII_EC_UDRAW_H_ diff --git a/applications/plugins/wii_ec_anal/wii_i2c.c b/applications/plugins/wii_ec_anal/wii_i2c.c index 90fe22163..f5d6840d9 100644 --- a/applications/plugins/wii_ec_anal/wii_i2c.c +++ b/applications/plugins/wii_ec_anal/wii_i2c.c @@ -17,103 +17,98 @@ // 0xFA..0xFF ( 6 bytes) ... [r] Perhipheral ID //----------------------------------------------------------------------------- ---------------------------------------- -#include -#include -#include +#include +#include +#include -#include -#include -#include +#include +#include +#include -#include "i2c_workaround.h" //! temporary workaround for a bug in furi i2c [see header] +#include "i2c_workaround.h" //! temporary workaround for a bug in furi i2c [see header] -#include "wii_anal.h" -#include "wii_i2c.h" -#include "wii_ec.h" +#include "wii_anal.h" +#include "wii_i2c.h" +#include "wii_ec.h" -#include "bc_logging.h" +#include "bc_logging.h" //----------------------------------------------------------------------------- ---------------------------------------- // Wii Extension Controller i2c Bus address -static const uint8_t ec_i2cAddr = 0x52; +static const uint8_t ec_i2cAddr = 0x52; // Initialise for UNencrypted comms -static const uint8_t regInit1 = 0xF0; -static const uint8_t regInit2 = 0xFB; -static const uint8_t cmdInit1[] = {regInit1, 0x55}; -static const uint8_t cmdInit2[] = {regInit2, 0x00}; +static const uint8_t regInit1 = 0xF0; +static const uint8_t regInit2 = 0xFB; +static const uint8_t cmdInit1[] = {regInit1, 0x55}; +static const uint8_t cmdInit2[] = {regInit2, 0x00}; // Initialise for ENcrypted comms -static const uint8_t regInitEnc = 0x40; -static const uint8_t cmdInitEnc[] = {regInitEnc, 0x00}; +static const uint8_t regInitEnc = 0x40; +static const uint8_t cmdInitEnc[] = {regInitEnc, 0x00}; // Crypto key (PSK), base register : {0x40..0x4F}[2][8] -static const uint8_t regEnc = 0x40; // ENC_LEN +static const uint8_t regEnc = 0x40; // ENC_LEN // Controller State data, base register : {0x00..0x05}[6] -static const uint8_t regJoy = 0x00; // JOY_LEN +static const uint8_t regJoy = 0x00; // JOY_LEN // Calibration data, base register : {0x20..0x2F}[16] -static const uint8_t regCal = 0x20; // CAL_LEN +static const uint8_t regCal = 0x20; // CAL_LEN // Controller ID, base register : {0xFA..0xFF}[6] -static const uint8_t regPid = 0xFA; // PID_LEN +static const uint8_t regPid = 0xFA; // PID_LEN //+============================================================================ ======================================== // Hexdump a buffer to the logfile // #if LOG_LEVEL >= 4 // INFO -static -void dump (const uint8_t* buf, const unsigned int len, const char* id) -{ - // snprintf() would be useful! - char s[128] = {0}; - char* p = NULL; +static void dump(const uint8_t* buf, const unsigned int len, const char* id) { + // snprintf() would be useful! + char s[128] = {0}; + char* p = NULL; - strcpy(s, id); - p = s +strlen(s); - *p++ = ':'; - *p++ = ' '; - *p++ = '{'; + strcpy(s, id); + p = s + strlen(s); + *p++ = ':'; + *p++ = ' '; + *p++ = '{'; - for (unsigned int i = 0; i < len; i++) { - uint8_t hi = (buf[i] &0xF0) >>4; - uint8_t lo = (buf[i] &0x0F); + for(unsigned int i = 0; i < len; i++) { + uint8_t hi = (buf[i] & 0xF0) >> 4; + uint8_t lo = (buf[i] & 0x0F); - hi = hi + ((hi > 9) ? ('A' -10) : '0'); - lo = lo + ((lo > 9) ? ('A' -10) : '0'); + hi = hi + ((hi > 9) ? ('A' - 10) : '0'); + lo = lo + ((lo > 9) ? ('A' - 10) : '0'); - *p++ = (char)hi; - *p++ = (char)lo; - *p++ = ','; - } - *p = '\0'; - *--p = '}'; - INFO(s); + *p++ = (char)hi; + *p++ = (char)lo; + *p++ = ','; + } + *p = '\0'; + *--p = '}'; + INFO(s); } #else -# define dump(...) +#define dump(...) #endif //+============================================================================ ======================================== // //! -W-A-R-N-I-N-G- : THIS ENCRYPTION CODE SHOULD NEVER BE REQUIRED ... AS SUCH, I'VE NEVER TESTED IT // -static -void decrypt (uint8_t* buf, const uint8_t* encKey, const uint8_t reg, unsigned int len) -{ -#if 1 // Use standard algorithm - // decrypted_byte = (encrypted_byte XOR encKey[1][address%8]) + encKey[2][address%8] - for (uint8_t* p = buf; p < buf+len; p++) - *p = (*p ^ encKey[(reg +(p -buf)) %8]) + encKey[8 +((reg +(p -buf)) %8)]; +static void decrypt(uint8_t* buf, const uint8_t* encKey, const uint8_t reg, unsigned int len) { +#if 1 // Use standard algorithm + // decrypted_byte = (encrypted_byte XOR encKey[1][address%8]) + encKey[2][address%8] + for(uint8_t* p = buf; p < buf + len; p++) + *p = (*p ^ encKey[(reg + (p - buf)) % 8]) + encKey[8 + ((reg + (p - buf)) % 8)]; -#else //! This is (I think) a shortcut for an all-zero key [not tested] - (void)encKey; - (void)reg; - for (uint8_t* p = buf; p < buf+len; p++) - *p = (*p ^ 0x17) + 0x17; +#else //! This is (I think) a shortcut for an all-zero key [not tested] + (void)encKey; + (void)reg; + for(uint8_t* p = buf; p < buf + len; p++) *p = (*p ^ 0x17) + 0x17; #endif } @@ -123,38 +118,38 @@ void decrypt (uint8_t* buf, const uint8_t* encKey, const uint8_t reg, unsign // // Returns: {0:OK, >0:Error} // -int ecRead (wiiEC_t* pec) -{ - ENTER; - int rv = 0; // assume success +int ecRead(wiiEC_t* pec) { + ENTER; + int rv = 0; // assume success - if (!pec->init) { - WARN("%s : device not initialised", __func__); - rv = 1; - goto bail; - } + if(!pec->init) { + WARN("%s : device not initialised", __func__); + rv = 1; + goto bail; + } - if (!furi_hal_i2c_is_device_ready(i2cBus,i2cAddr, i2cTimeout)) { - INFO("%s : device disconnected", __func__); - pec->init = false; - rv = 2; - goto bail; - } + if(!furi_hal_i2c_is_device_ready(i2cBus, i2cAddr, i2cTimeout)) { + INFO("%s : device disconnected", __func__); + pec->init = false; + rv = 2; + goto bail; + } - if (!furi_hal_i2c_trxd(i2cBus,i2cAddr, ®Joy,1, pec->joy,JOY_LEN, i2cTimeout,i2cReadWait)) { - ERROR("%s : trxd fail", __func__); - rv = 3; - goto bail; - } + if(!furi_hal_i2c_trxd( + i2cBus, i2cAddr, ®Joy, 1, pec->joy, JOY_LEN, i2cTimeout, i2cReadWait)) { + ERROR("%s : trxd fail", __func__); + rv = 3; + goto bail; + } - if (pec->encrypt) decrypt(pec->joy, pec->encKey, regJoy, JOY_LEN) ; + if(pec->encrypt) decrypt(pec->joy, pec->encKey, regJoy, JOY_LEN); - // Decode the readings (according to Controller type) - ecDecode(pec); + // Decode the readings (according to Controller type) + ecDecode(pec); bail: - LEAVE; - return rv; + LEAVE; + return rv; } //+============================================================================ ======================================== @@ -162,148 +157,145 @@ bail: // //! To disable encryption, pass a NULL encryption key <-- this is currently ALWAYS the case // -bool ecInit (wiiEC_t* pec, const uint8_t* encKey) -{ - ENTER; +bool ecInit(wiiEC_t* pec, const uint8_t* encKey) { + ENTER; - bool rv = false; // assume failure + bool rv = false; // assume failure -#if 0 //! i2c workaround +#if 0 //! i2c workaround //! I think this is done during OS startup - long before the plugin starts furi_hal_i2c_init(); #endif -#if 0 //! i2c workaround +#if 0 //! i2c workaround // May become relevant when the i2c issues are resolved // Take control of the i2c bus [which returns void !?] // --> firmware/targets/f7/furi_hal/furi_hal_i2c.c furi_hal_i2c_acquire(i2cBus); #endif - pec->init = false; // assume failure + pec->init = false; // assume failure - // === See if the device is alive === - if (!furi_hal_i2c_is_device_ready(i2cBus,i2cAddr, i2cTimeout)) { - TRACE("%s : waiting for device", __func__); - goto bail; - } - INFO("%s : device connected", __func__); + // === See if the device is alive === + if(!furi_hal_i2c_is_device_ready(i2cBus, i2cAddr, i2cTimeout)) { + TRACE("%s : waiting for device", __func__); + goto bail; + } + INFO("%s : device connected", __func__); - // === Initialise the device === - pec->init = false; // This goes true AFTER the (optional) controller-specific init code + // === Initialise the device === + pec->init = false; // This goes true AFTER the (optional) controller-specific init code - // === Start the Extension Controller === - if (encKey) { //! start in encrypted mode + // === Start the Extension Controller === + if(encKey) { //! start in encrypted mode - //! todo - should this happen here, or AFTER we've got the ID ? + //! todo - should this happen here, or AFTER we've got the ID ? - } else { + } else { + if(!furi_hal_i2c_tx(i2cBus, i2cAddr, cmdInit1, sizeof(cmdInit1), i2cTimeout)) { + ERROR("%s : init fail (dec1)", __func__); + goto bail; + } + TRACE("%s : init OK1", __func__); - if ( !furi_hal_i2c_tx(i2cBus,i2cAddr, cmdInit1,sizeof(cmdInit1), i2cTimeout) ) { - ERROR("%s : init fail (dec1)", __func__); - goto bail; - } - TRACE("%s : init OK1", __func__); + if(!furi_hal_i2c_tx(i2cBus, i2cAddr, cmdInit2, sizeof(cmdInit2), i2cTimeout)) { + ERROR("%s : init fail (dec2)", __func__); + goto bail; + } + TRACE("%s : init OK2", __func__); + } - if ( !furi_hal_i2c_tx(i2cBus,i2cAddr, cmdInit2,sizeof(cmdInit2), i2cTimeout) ) { - ERROR("%s : init fail (dec2)", __func__); - goto bail; - } - TRACE("%s : init OK2", __func__); - } + // === Retrieve the Extension Controller ID === + if(!furi_hal_i2c_trx(i2cBus, i2cAddr, ®Pid, 1, pec->pid, PID_LEN, i2cTimeout)) { + ERROR("%s : T(R)x fail (pid)", __func__); + goto bail; + } + if(pec->encrypt) decrypt(pec->joy, pec->encKey, regJoy, JOY_LEN); + dump(pec->pid, PID_LEN, "pid"); // debug INFO - // === Retrieve the Extension Controller ID === - if (!furi_hal_i2c_trx(i2cBus,i2cAddr, ®Pid,1, pec->pid,PID_LEN, i2cTimeout)) { - ERROR("%s : T(R)x fail (pid)", __func__); - goto bail; - } - if (pec->encrypt) decrypt(pec->joy, pec->encKey, regJoy, JOY_LEN); - dump(pec->pid, PID_LEN, "pid"); // debug INFO + // Find the StringID in the lookup table + for(pec->pidx = PID_FIRST; pec->pidx < PID_ERROR; pec->pidx++) + if(memcmp(pec->pid, ecId[pec->pidx].id, PID_LEN) == 0) break; + if(pec->pidx == PID_ERROR) pec->pidx = PID_UNKNOWN; + pec->sid = ecId[pec->pidx].name; + INFO("sid: %s", pec->sid); - // Find the StringID in the lookup table - for (pec->pidx = PID_FIRST; pec->pidx < PID_ERROR; pec->pidx++) - if (memcmp(pec->pid, ecId[pec->pidx].id, PID_LEN) == 0) break ; - if (pec->pidx == PID_ERROR) pec->pidx = PID_UNKNOWN ; - pec->sid = ecId[pec->pidx].name; - INFO("sid: %s", pec->sid); + // === (optionally) Enable encryption === + if(!encKey) { + pec->encrypt = false; - // === (optionally) Enable encryption === - if (!encKey) { - pec->encrypt = false; + } else { // Controller WILL encrypt ALL tranmissions + //! this encryption code fails - should it be done earlier? + //! as it is probably never of any use, I'm kinda loathed to spend time on it + //! https://github.com/madhephaestus/WiiChuck/blob/master/src/Accessory.cpp#L138 + uint8_t encTx[1 + ENC_LEN] = {0}; + uint8_t* ep = encTx; - } else { // Controller WILL encrypt ALL tranmissions -//! this encryption code fails - should it be done earlier? -//! as it is probably never of any use, I'm kinda loathed to spend time on it -//! https://github.com/madhephaestus/WiiChuck/blob/master/src/Accessory.cpp#L138 - uint8_t encTx[1+ENC_LEN] = {0}; - uint8_t* ep = encTx; + pec->encrypt = true; - pec->encrypt = true; + // ** Start the Controller in ENcrytped mode + if(!furi_hal_i2c_tx(i2cBus, i2cAddr, cmdInitEnc, sizeof(cmdInitEnc), i2cTimeout)) { + ERROR("%s : init fail (enc)", __func__); + goto bail; + } - // ** Start the Controller in ENcrytped mode - if ( !furi_hal_i2c_tx(i2cBus,i2cAddr, cmdInitEnc,sizeof(cmdInitEnc), i2cTimeout) ) { - ERROR("%s : init fail (enc)", __func__); - goto bail; - } + // Copy the (symmetric) encryption key to the controller state table + if(pec->encKey != encKey) memcpy(pec->encKey, encKey, ENC_LEN); - // Copy the (symmetric) encryption key to the controller state table - if (pec->encKey != encKey) - memcpy(pec->encKey, encKey, ENC_LEN); + // Build the encryption key packet + *ep++ = regEnc; + memcpy(ep, pec->encKey, ENC_LEN); - // Build the encryption key packet - *ep++ = regEnc; - memcpy(ep, pec->encKey, ENC_LEN); + // ** Send encryption key (PSK) + if(!furi_hal_i2c_tx(i2cBus, i2cAddr, encTx, (1 + ENC_LEN), i2cTimeout)) { + ERROR("%s : key fail", __func__); + goto bail; + } - // ** Send encryption key (PSK) - if ( !furi_hal_i2c_tx(i2cBus,i2cAddr, encTx,(1+ENC_LEN), i2cTimeout) ) { - ERROR("%s : key fail", __func__); - goto bail; - } + TRACE("%s : init OK (enc)", __func__); + } - TRACE("%s : init OK (enc)", __func__); - } + // === Some devices [eg. Drawsome/uDraw] require additional init code === + if(ecId[pec->init].init && (ecId[pec->init].init(pec) == false)) goto bail; + pec->init = true; - // === Some devices [eg. Drawsome/uDraw] require additional init code === - if ( ecId[pec->init].init && (ecId[pec->init].init(pec) == false) ) goto bail ; - pec->init = true; + // === Read calibration data === + if(!furi_hal_i2c_trx(i2cBus, i2cAddr, ®Cal, 1, pec->calF, CAL_LEN, i2cTimeout)) { + ERROR("%s : trx fail (cal)", __func__); + goto bail; + } + if(pec->encrypt) decrypt(pec->joy, pec->encKey, regJoy, JOY_LEN); + dump(pec->calF, CAL_LEN, "cal"); - // === Read calibration data === - if (!furi_hal_i2c_trx(i2cBus,i2cAddr, ®Cal,1, pec->calF,CAL_LEN, i2cTimeout)) { - ERROR("%s : trx fail (cal)", __func__); - goto bail; - } - if (pec->encrypt) decrypt(pec->joy, pec->encKey, regJoy, JOY_LEN); - dump(pec->calF, CAL_LEN, "cal"); + ecCalibrate(pec, CAL_RESET | CAL_FACTORY); // Load factory default calibration - ecCalibrate(pec, CAL_RESET | CAL_FACTORY); // Load factory default calibration + // === Initialise decode buffers === + pec->decN = 0; // read in to decode[1] (yes, N=0 -> read in to dec[1]) + switch(ecRead(pec)) { + case 0: // read OK + memcpy(&pec->dec[0], &pec->dec[1], sizeof(pec->dec[0])); + dump(pec->joy, JOY_LEN, "joy"); + break; - // === Initialise decode buffers === - pec->decN = 0; // read in to decode[1] (yes, N=0 -> read in to dec[1]) - switch (ecRead(pec)) { - case 0: // read OK - memcpy(&pec->dec[0], &pec->dec[1], sizeof(pec->dec[0])); - dump(pec->joy, JOY_LEN, "joy"); - break; + default: // bug: unknown + case 1: // bug: not initialised - should never happen + ERROR("%s : read bug", __func__); + break; - default: // bug: unknown - case 1: // bug: not initialised - should never happen - ERROR("%s : read bug", __func__); - break; + case 2: // device gone + case 3: // read fail + // Logging done by ecRead() + pec->init = false; + goto bail; + } - case 2: // device gone - case 3: // read fail - // Logging done by ecRead() - pec->init = false; - goto bail; - } - - rv = true; // yay :) + rv = true; // yay :) bail: #if 0 //! i2c workaround furi_hal_i2c_release(i2cBus); #endif - LEAVE; - return rv; + LEAVE; + return rv; } diff --git a/applications/plugins/wii_ec_anal/wii_i2c.h b/applications/plugins/wii_ec_anal/wii_i2c.h index 18cb5ee9b..efebefcf9 100644 --- a/applications/plugins/wii_ec_anal/wii_i2c.h +++ b/applications/plugins/wii_ec_anal/wii_i2c.h @@ -1,7 +1,7 @@ -#ifndef WII_I2C_H_ -#define WII_I2C_H_ +#ifndef WII_I2C_H_ +#define WII_I2C_H_ -#include +#include //#include "wii_ec.h" @@ -14,11 +14,11 @@ // // After the (special) START "bit"... // the first 8bits (byte) of i2c data are the 7bit i2c Address, -// FOLLOWED by 1bit to signify a READ or WRITE {0=write, 1=read} +// FOLLOWED by 1bit to signify a READ or WRITE {0=write, 1=read} // The data is transmitted BIG-Endian, IE. MSb first [human readable] // So the address actually lives in the TOP (MSb's) of the first "byte", (with bit0 being used as the read/write flag) // -// The read() and write() functions on the FZ will set the LSb appropriately, +// The read() and write() functions on the FZ will set the LSb appropriately, // BUT they do NOT shift the address left to make room for it! // So the address you give to read/write() MUST be given as (7bitAddress << 1) // @@ -26,17 +26,17 @@ // // firmware/targets/f7/furi_hal/furi_hal_i2c_types.h -#define i2cBus (&furi_hal_i2c_handle_external) // FZ external i2c bus -#define i2cAddr (ec_i2cAddr << 1) -#define i2cTimeout (3) // in mS -#define i2cReadWait (300) //! 300uS: how low can we take this? +#define i2cBus (&furi_hal_i2c_handle_external) // FZ external i2c bus +#define i2cAddr (ec_i2cAddr << 1) +#define i2cTimeout (3) // in mS +#define i2cReadWait (300) //! 300uS: how low can we take this? //----------------------------------------------------------------------------- ---------------------------------------- // public functions // -typedef struct wiiEC wiiEC_t ; +typedef struct wiiEC wiiEC_t; -bool ecInit (wiiEC_t* const pec, const uint8_t* encKey) ; -int ecRead (wiiEC_t* const pec) ; +bool ecInit(wiiEC_t* const pec, const uint8_t* encKey); +int ecRead(wiiEC_t* const pec); #endif //WII_I2C_H_ diff --git a/applications/services/bt/bt_service/bt.c b/applications/services/bt/bt_service/bt.c index b1be44214..e341544b3 100644 --- a/applications/services/bt/bt_service/bt.c +++ b/applications/services/bt/bt_service/bt.c @@ -38,10 +38,9 @@ static void bt_pin_code_view_port_draw_callback(Canvas* canvas, void* context) { char pin_code_info[24]; DesktopSettings* settings = malloc(sizeof(DesktopSettings)); DESKTOP_SETTINGS_LOAD(settings); - if (settings->sfw_mode) { + if(settings->sfw_mode) { canvas_draw_icon(canvas, 0, 0, &I_BLE_Pairing_128x64_sfw); - } - else { + } else { canvas_draw_icon(canvas, 0, 0, &I_BLE_Pairing_128x64); } snprintf(pin_code_info, sizeof(pin_code_info), "Pairing code\n%06lu", bt->pin_code); @@ -89,10 +88,9 @@ static bool bt_pin_code_verify_event_handler(Bt* bt, uint32_t pin) { notification_message(bt->notification, &sequence_display_backlight_on); FuriString* pin_str; - if (settings->sfw_mode) { + if(settings->sfw_mode) { dialog_message_set_icon(bt->dialog_message, &I_BLE_Pairing_128x64_sfw, 0, 0); - } - else { + } else { dialog_message_set_icon(bt->dialog_message, &I_BLE_Pairing_128x64, 0, 0); } pin_str = furi_string_alloc_printf("Verify code\n%06lu", pin); diff --git a/applications/services/desktop/animations/animation_manager.c b/applications/services/desktop/animations/animation_manager.c index 3bc568d6a..9f6df386c 100644 --- a/applications/services/desktop/animations/animation_manager.c +++ b/applications/services/desktop/animations/animation_manager.c @@ -365,7 +365,7 @@ static bool animation_manager_is_valid_idle_animation( static StorageAnimation* animation_manager_select_idle_animation(AnimationManager* animation_manager) { UNUSED(animation_manager); - + StorageAnimationList_t animation_list; StorageAnimationList_init(animation_list); animation_storage_fill_animation_list(&animation_list); @@ -556,17 +556,17 @@ static void animation_manager_switch_to_one_shot_view(AnimationManager* animatio View* next_view = one_shot_view_get_view(animation_manager->one_shot_view); view_stack_remove_view(animation_manager->view_stack, prev_view); view_stack_add_view(animation_manager->view_stack, next_view); - if (settings->sfw_mode) { - if (stats.level <= 20) { - one_shot_view_start_animation(animation_manager->one_shot_view, &A_Levelup1_128x64_sfw); - } - else if (stats.level >= 21) { - one_shot_view_start_animation(animation_manager->one_shot_view, &A_Levelup2_128x64_sfw); - } - else { + if(settings->sfw_mode) { + if(stats.level <= 20) { + one_shot_view_start_animation( + animation_manager->one_shot_view, &A_Levelup1_128x64_sfw); + } else if(stats.level >= 21) { + one_shot_view_start_animation( + animation_manager->one_shot_view, &A_Levelup2_128x64_sfw); + } else { furi_assert(0); } - }else { + } else { one_shot_view_start_animation(animation_manager->one_shot_view, &A_Levelup1_128x64); } free(settings); diff --git a/applications/services/desktop/animations/animation_storage.c b/applications/services/desktop/animations/animation_storage.c index 410da1290..c1dcdffc3 100644 --- a/applications/services/desktop/animations/animation_storage.c +++ b/applications/services/desktop/animations/animation_storage.c @@ -27,20 +27,18 @@ static void animation_storage_free_frames(BubbleAnimation* animation); static void animation_storage_free_animation(BubbleAnimation** storage_animation); static BubbleAnimation* animation_storage_load_animation(const char* name); -void animation_handler_beta() -{ +void animation_handler_beta() { DesktopSettings* settings = malloc(sizeof(DesktopSettings)); DESKTOP_SETTINGS_LOAD(settings); - if (settings->sfw_mode) { - snprintf(ANIMATION_MANIFEST_FILE, sizeof(ANIMATION_DIR), "%s", ANIMATION_DIR); + if(settings->sfw_mode) { + snprintf(ANIMATION_MANIFEST_FILE, sizeof(ANIMATION_DIR), "%s", ANIMATION_DIR); FURI_LOG_I(TAG, "SFW Manifest selected"); - strcat(ANIMATION_MANIFEST_FILE,"/sfw/manifest.txt"); - } - else { - snprintf(ANIMATION_MANIFEST_FILE, sizeof(ANIMATION_DIR), "%s", ANIMATION_DIR); + strcat(ANIMATION_MANIFEST_FILE, "/sfw/manifest.txt"); + } else { + snprintf(ANIMATION_MANIFEST_FILE, sizeof(ANIMATION_DIR), "%s", ANIMATION_DIR); FURI_LOG_I(TAG, "NSFW Manifest selected"); - strcat(ANIMATION_MANIFEST_FILE,"/nsfw/manifest.txt"); + strcat(ANIMATION_MANIFEST_FILE, "/nsfw/manifest.txt"); } free(settings); } diff --git a/applications/services/desktop/desktop.c b/applications/services/desktop/desktop.c index 0e7f3caba..e43e6e6e0 100644 --- a/applications/services/desktop/desktop.c +++ b/applications/services/desktop/desktop.c @@ -26,10 +26,9 @@ static void desktop_loader_callback(const void* message, void* context) { Desktop* desktop = context; const LoaderEvent* event = message; - if (event->type == LoaderEventTypeApplicationStarted) { + if(event->type == LoaderEventTypeApplicationStarted) { view_dispatcher_send_custom_event(desktop->view_dispatcher, DesktopGlobalBeforeAppStarted); - } - else if (event->type == LoaderEventTypeApplicationStopped) { + } else if(event->type == LoaderEventTypeApplicationStopped) { view_dispatcher_send_custom_event(desktop->view_dispatcher, DesktopGlobalAfterAppFinished); } } @@ -43,7 +42,7 @@ static bool desktop_custom_event_callback(void* context, uint32_t event) { furi_assert(context); Desktop* desktop = (Desktop*)context; - switch (event) { + switch(event) { case DesktopGlobalBeforeAppStarted: animation_manager_unload_and_stall_animation(desktop->animation_manager); desktop_auto_lock_inhibit(desktop); @@ -56,12 +55,11 @@ static bool desktop_custom_event_callback(void* context, uint32_t event) { desktop_auto_lock_arm(desktop); return true; case DesktopGlobalAutoLock: - if (!loader_is_locked(desktop->loader)) { - if (desktop->settings.pin_code.length > 0) { + if(!loader_is_locked(desktop->loader)) { + if(desktop->settings.pin_code.length > 0) { desktop_pin_lock(&desktop->settings); desktop_lock(desktop); - } - else { + } else { desktop_lock(desktop); } } @@ -88,7 +86,7 @@ static void desktop_input_event_callback(const void* value, void* context) { furi_assert(context); const InputEvent* event = value; Desktop* desktop = context; - if (event->type == InputTypePress) { + if(event->type == InputTypePress) { desktop_start_auto_lock_timer(desktop); } } @@ -109,7 +107,7 @@ static void desktop_stop_auto_lock_timer(Desktop* desktop) { } static void desktop_auto_lock_arm(Desktop* desktop) { - if (desktop->settings.auto_lock_delay_ms) { + if(desktop->settings.auto_lock_delay_ms) { desktop->input_events_subscription = furi_pubsub_subscribe( desktop->input_events_pubsub, desktop_input_event_callback, desktop); desktop_start_auto_lock_timer(desktop); @@ -118,7 +116,7 @@ static void desktop_auto_lock_arm(Desktop* desktop) { static void desktop_auto_lock_inhibit(Desktop* desktop) { desktop_stop_auto_lock_timer(desktop); - if (desktop->input_events_subscription) { + if(desktop->input_events_subscription) { furi_pubsub_unsubscribe(desktop->input_events_pubsub, desktop->input_events_subscription); desktop->input_events_subscription = NULL; } @@ -233,8 +231,8 @@ Desktop* desktop_alloc() { // Special case: autostart application is already running desktop->loader = furi_record_open(RECORD_LOADER); - if (loader_is_locked(desktop->loader) && - animation_manager_is_animation_loaded(desktop->animation_manager)) { + if(loader_is_locked(desktop->loader) && + animation_manager_is_animation_loaded(desktop->animation_manager)) { animation_manager_unload_and_stall_animation(desktop->animation_manager); } @@ -257,7 +255,7 @@ void desktop_free(Desktop* desktop) { furi_pubsub_unsubscribe( loader_get_pubsub(desktop->loader), desktop->app_start_stop_subscription); - if (desktop->input_events_subscription) { + if(desktop->input_events_subscription) { furi_pubsub_unsubscribe(desktop->input_events_pubsub, desktop->input_events_subscription); desktop->input_events_subscription = NULL; } @@ -313,16 +311,13 @@ static bool desktop_check_file_flag(const char* flag_path) { int32_t desktop_srv(void* p) { UNUSED(p); - if (furi_hal_rtc_get_boot_mode() != FuriHalRtcBootModeNormal) - { + if(furi_hal_rtc_get_boot_mode() != FuriHalRtcBootModeNormal) { FURI_LOG_W("Desktop", "Desktop load skipped. Device is in special startup mode."); - } - else - { + } else { Desktop* desktop = desktop_alloc(); bool loaded = DESKTOP_SETTINGS_LOAD(&desktop->settings); - if (!loaded) { + if(!loaded) { memset(&desktop->settings, 0, sizeof(desktop->settings)); DESKTOP_SETTINGS_SAVE(&desktop->settings); } @@ -333,24 +328,23 @@ int32_t desktop_srv(void* p) { desktop_pin_lock_init(&desktop->settings); - if (!desktop_pin_lock_is_locked()) { - if (!loader_is_locked(desktop->loader)) { + if(!desktop_pin_lock_is_locked()) { + if(!loader_is_locked(desktop->loader)) { desktop_auto_lock_arm(desktop); } - } - else { + } else { desktop_lock(desktop); } - if (desktop_check_file_flag(SLIDESHOW_FS_PATH)) { + if(desktop_check_file_flag(SLIDESHOW_FS_PATH)) { scene_manager_next_scene(desktop->scene_manager, DesktopSceneSlideshow); } - if (!furi_hal_version_do_i_belong_here()) { + if(!furi_hal_version_do_i_belong_here()) { scene_manager_next_scene(desktop->scene_manager, DesktopSceneHwMismatch); } - if (furi_hal_rtc_get_fault_data()) { + if(furi_hal_rtc_get_fault_data()) { scene_manager_next_scene(desktop->scene_manager, DesktopSceneFault); } diff --git a/applications/services/desktop/scenes/desktop_scene_fault.c b/applications/services/desktop/scenes/desktop_scene_fault.c index 38151e6b9..79dedbe59 100644 --- a/applications/services/desktop/scenes/desktop_scene_fault.c +++ b/applications/services/desktop/scenes/desktop_scene_fault.c @@ -18,7 +18,7 @@ void desktop_scene_fault_on_enter(void* context) { Popup* popup = desktop->hw_mismatch_popup; popup_set_context(popup, desktop); - if (settings->sfw_mode) { + if(settings->sfw_mode) { popup_set_header( popup, "Flipper crashed\n but has been rebooted", @@ -26,8 +26,7 @@ void desktop_scene_fault_on_enter(void* context) { 14 + STATUS_BAR_Y_SHIFT, AlignCenter, AlignCenter); - } - else { + } else { popup_set_header( popup, "Slut passed out\n but is now back", @@ -37,7 +36,6 @@ void desktop_scene_fault_on_enter(void* context) { AlignCenter); } - char* message = (char*)furi_hal_rtc_get_fault_data(); popup_set_text(popup, message, 60, 37 + STATUS_BAR_Y_SHIFT, AlignCenter, AlignCenter); popup_set_callback(popup, desktop_scene_fault_callback); diff --git a/applications/services/desktop/views/desktop_view_lock_menu.c b/applications/services/desktop/views/desktop_view_lock_menu.c index 77eedcb8c..698c26505 100644 --- a/applications/services/desktop/views/desktop_view_lock_menu.c +++ b/applications/services/desktop/views/desktop_view_lock_menu.c @@ -38,10 +38,7 @@ void desktop_lock_menu_set_pin_state(DesktopLockMenuView* lock_menu, bool pin_is void desktop_lock_menu_set_sfw_mode_state(DesktopLockMenuView* lock_menu, bool sfw_mode) { with_view_model( - lock_menu->view, - DesktopLockMenuViewModel * model, - { model->sfw_mode = sfw_mode; }, - true); + lock_menu->view, DesktopLockMenuViewModel * model, { model->sfw_mode = sfw_mode; }, true); } void desktop_lock_menu_set_idx(DesktopLockMenuView* lock_menu, uint8_t idx) { diff --git a/applications/services/dolphin/helpers/dolphin_state.c b/applications/services/dolphin/helpers/dolphin_state.c index eb34e87ea..eaf270bbe 100644 --- a/applications/services/dolphin/helpers/dolphin_state.c +++ b/applications/services/dolphin/helpers/dolphin_state.c @@ -82,8 +82,8 @@ uint64_t dolphin_state_timestamp() { } bool dolphin_state_is_levelup(int icounter) { - for (int i = 0; i<30; ++i) { - if ((icounter == level_array[i])) { + for(int i = 0; i < 30; ++i) { + if((icounter == level_array[i])) { return true; } }; @@ -91,12 +91,12 @@ bool dolphin_state_is_levelup(int icounter) { } uint8_t dolphin_get_level(int icounter) { -for (int i = 0; i < 29; ++i) { - if (icounter <= level_array[i]) { - return i + 1; + for(int i = 0; i < 29; ++i) { + if(icounter <= level_array[i]) { + return i + 1; + } } -} -return 30; + return 30; } uint32_t dolphin_state_xp_above_last_levelup(int icounter) { diff --git a/applications/services/gui/gui.c b/applications/services/gui/gui.c index 7ef6ef2a9..37839c789 100644 --- a/applications/services/gui/gui.c +++ b/applications/services/gui/gui.c @@ -116,7 +116,6 @@ static void gui_redraw_status_bar(Gui* gui, bool need_attention) { canvas_height(gui->canvas) - 4); } - // Extra notification if(need_attention) { width = icon_get_width(&I_Hidden_window_9x8); diff --git a/applications/services/namechangersrv/namechangersrv.c b/applications/services/namechangersrv/namechangersrv.c index 3e63c9120..e62b39c01 100644 --- a/applications/services/namechangersrv/namechangersrv.c +++ b/applications/services/namechangersrv/namechangersrv.c @@ -4,12 +4,9 @@ #include void namechanger_on_system_start() { - if (furi_hal_rtc_get_boot_mode() != FuriHalRtcBootModeNormal) - { + if(furi_hal_rtc_get_boot_mode() != FuriHalRtcBootModeNormal) { FURI_LOG_W(TAG, "NameChangerSRV load skipped. Device is in special startup mode."); - } - else - { + } else { Storage* storage = furi_record_open(RECORD_STORAGE); FlipperFormat* file = flipper_format_file_alloc(storage); @@ -25,36 +22,36 @@ void namechanger_on_system_start() { data = furi_string_alloc(); do { - if (!flipper_format_file_open_existing(file, furi_string_get_cstr(filepath))) { + if(!flipper_format_file_open_existing(file, furi_string_get_cstr(filepath))) { break; } // header uint32_t version; - if (!flipper_format_read_header(file, data, &version)) { + if(!flipper_format_read_header(file, data, &version)) { break; } - if (furi_string_cmp_str(data, furi_string_get_cstr(NAMEHEADER)) != 0) { + if(furi_string_cmp_str(data, furi_string_get_cstr(NAMEHEADER)) != 0) { break; } - if (version != 1) { + if(version != 1) { break; } // get Name - if (!flipper_format_read_string(file, "Name", data)) { + if(!flipper_format_read_string(file, "Name", data)) { break; } result = true; - } while (false); + } while(false); flipper_format_free(file); - if (!result) { + if(!result) { //file not good - write new one FlipperFormat* file = flipper_format_file_alloc(storage); @@ -62,49 +59,49 @@ void namechanger_on_system_start() { do { // Open file for write - if (!flipper_format_file_open_always(file, furi_string_get_cstr(filepath))) { + if(!flipper_format_file_open_always(file, furi_string_get_cstr(filepath))) { break; } // Write header - if (!flipper_format_write_header_cstr(file, furi_string_get_cstr(NAMEHEADER), 1)) { + if(!flipper_format_write_header_cstr(file, furi_string_get_cstr(NAMEHEADER), 1)) { break; } // Write comments - if (!flipper_format_write_comment_cstr( - file, - "Changing the value below will change your FlipperZero device name.")) { + if(!flipper_format_write_comment_cstr( + file, + "Changing the value below will change your FlipperZero device name.")) { break; } - if (!flipper_format_write_comment_cstr( - file, - "Note: This is limited to 8 characters using the following: a-z, A-Z, 0-9, and _")) { + if(!flipper_format_write_comment_cstr( + file, + "Note: This is limited to 8 characters using the following: a-z, A-Z, 0-9, and _")) { break; } - if (!flipper_format_write_comment_cstr( - file, "It can contain other characters but use at your own risk.")) { + if(!flipper_format_write_comment_cstr( + file, "It can contain other characters but use at your own risk.")) { break; } //Write name - if (!flipper_format_write_string_cstr(file, "Name", furi_hal_version_get_name_ptr())) { + if(!flipper_format_write_string_cstr( + file, "Name", furi_hal_version_get_name_ptr())) { break; } res = true; - } while (false); + } while(false); flipper_format_free(file); - if (!res) { + if(!res) { FURI_LOG_E(TAG, "Save failed."); } - } - else { - if (!furi_string_size(data)) { + } else { + if(!furi_string_size(data)) { //Empty file - get default name and write to file. FlipperFormat* file = flipper_format_file_alloc(storage); @@ -112,50 +109,49 @@ void namechanger_on_system_start() { do { // Open file for write - if (!flipper_format_file_open_always(file, furi_string_get_cstr(filepath))) { + if(!flipper_format_file_open_always(file, furi_string_get_cstr(filepath))) { break; } // Write header - if (!flipper_format_write_header_cstr( - file, furi_string_get_cstr(NAMEHEADER), 1)) { + if(!flipper_format_write_header_cstr( + file, furi_string_get_cstr(NAMEHEADER), 1)) { break; } // Write comments - if (!flipper_format_write_comment_cstr( - file, - "Changing the value below will change your FlipperZero device name.")) { + if(!flipper_format_write_comment_cstr( + file, + "Changing the value below will change your FlipperZero device name.")) { break; } - if (!flipper_format_write_comment_cstr( - file, - "Note: This is limited to 8 characters using the following: a-z, A-Z, 0-9, and _")) { + if(!flipper_format_write_comment_cstr( + file, + "Note: This is limited to 8 characters using the following: a-z, A-Z, 0-9, and _")) { break; } - if (!flipper_format_write_comment_cstr( - file, "It cannot contain any other characters.")) { + if(!flipper_format_write_comment_cstr( + file, "It cannot contain any other characters.")) { break; } //Write name - if (!flipper_format_write_string_cstr( - file, "Name", furi_hal_version_get_name_ptr())) { + if(!flipper_format_write_string_cstr( + file, "Name", furi_hal_version_get_name_ptr())) { break; } res = true; - } while (false); + } while(false); flipper_format_free(file); - if (!res) { + if(!res) { FURI_LOG_E(TAG, "Save failed."); } - } - else { + } else { char newdata[9]; snprintf(newdata, 9, "%s", furi_string_get_cstr(data)); //set name from file diff --git a/applications/services/power/power_service/power.c b/applications/services/power/power_service/power.c index d891968c7..92aefbe75 100644 --- a/applications/services/power/power_service/power.c +++ b/applications/services/power/power_service/power.c @@ -62,8 +62,9 @@ void power_draw_battery_callback(Canvas* canvas, void* context) { } 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); + (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; diff --git a/applications/settings/about/about.c b/applications/settings/about/about.c index 25e8b8fdb..17c734a20 100644 --- a/applications/settings/about/about.c +++ b/applications/settings/about/about.c @@ -136,7 +136,13 @@ static DialogMessageButton fw_version_screen(DialogsApp* dialogs, DialogMessage* } dialog_message_set_header(message, "Firmware Info:", 0, 0, AlignLeft, AlignTop); - dialog_message_set_text(message, "XFW - Xtreme Firmware\nGithub.com/ClaraCrazy/Flipper-Xtreme", 0, 13, AlignLeft, AlignTop); + dialog_message_set_text( + message, + "XFW - Xtreme Firmware\nGithub.com/ClaraCrazy/Flipper-Xtreme", + 0, + 13, + AlignLeft, + AlignTop); result = dialog_message_show(dialogs, message); dialog_message_set_text(message, NULL, 0, 0, AlignLeft, AlignTop); dialog_message_set_header(message, NULL, 0, 0, AlignLeft, AlignTop); @@ -154,7 +160,6 @@ const AboutDialogScreen about_screens[] = { compliance_screen, address_screen}; - const size_t about_screens_count = sizeof(about_screens) / sizeof(AboutDialogScreen); int32_t about_settings_app(void* p) { diff --git a/applications/settings/bt_settings_app/scenes/bt_settings_scene_forget_dev_success.c b/applications/settings/bt_settings_app/scenes/bt_settings_scene_forget_dev_success.c index 1a3914f3c..79651a976 100644 --- a/applications/settings/bt_settings_app/scenes/bt_settings_scene_forget_dev_success.c +++ b/applications/settings/bt_settings_app/scenes/bt_settings_scene_forget_dev_success.c @@ -13,10 +13,9 @@ void bt_settings_scene_forget_dev_success_on_enter(void* context) { DesktopSettings* settings = malloc(sizeof(DesktopSettings)); DESKTOP_SETTINGS_LOAD(settings); - if (settings->sfw_mode) { + if(settings->sfw_mode) { popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59_sfw); - } - else { + } else { popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59); } popup_set_header(popup, "Done", 14, 15, AlignLeft, AlignTop); diff --git a/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_disable.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_disable.c index c8a383acd..4b183251b 100644 --- a/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_disable.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_disable.c @@ -26,10 +26,9 @@ void desktop_settings_scene_pin_disable_on_enter(void* context) { popup_set_context(app->popup, app); popup_set_callback(app->popup, pin_disable_back_callback); - if (settings->sfw_mode) { + if(settings->sfw_mode) { popup_set_icon(app->popup, 0, 2, &I_DolphinMafia_115x62_sfw); - } - else { + } else { popup_set_icon(app->popup, 0, 2, &I_DolphinMafia_115x62); } popup_set_header(app->popup, "PIN\nDeleted!", 95, 9, AlignCenter, AlignCenter); diff --git a/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c index da4140aa1..9901740b6 100644 --- a/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c @@ -27,22 +27,15 @@ const uint32_t auto_lock_delay_value[AUTO_LOCK_DELAY_COUNT] = {0, 10000, 15000, 30000, 60000, 90000, 120000, 300000, 600000}; #define BATTERY_VIEW_COUNT 6 -const char* const battery_view_count_text[BATTERY_VIEW_COUNT] = { - "Bar", - "%", - "Inv. %", - "Retro 3", - "Retro 5", - "Bar %" -}; +const char* const battery_view_count_text[BATTERY_VIEW_COUNT] = + {"Bar", "%", "Inv. %", "Retro 3", "Retro 5", "Bar %"}; 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 -}; + DISPLAY_BATTERY_BAR_PERCENT}; uint8_t origBattDisp_value = 0; diff --git a/applications/settings/dolphin_passport/passport.c b/applications/settings/dolphin_passport/passport.c index f8be24397..7d5a500ea 100644 --- a/applications/settings/dolphin_passport/passport.c +++ b/applications/settings/dolphin_passport/passport.c @@ -12,15 +12,27 @@ #define MOODS_TOTAL 3 #define BUTTHURT_MAX 3 -static const Icon* const portrait_happy_sfw[BUTTHURT_MAX] = {&I_passport_happy1_46x49_sfw, &I_passport_happy2_46x49_sfw, &I_passport_happy3_46x49_sfw}; -static const Icon* const portrait_ok_sfw[BUTTHURT_MAX] = {&I_passport_okay1_46x49_sfw, &I_passport_okay2_46x49_sfw, &I_passport_okay3_46x49_sfw}; -static const Icon* const portrait_bad_sfw[BUTTHURT_MAX] = {&I_passport_bad1_46x49_sfw, &I_passport_bad2_46x49_sfw, &I_passport_bad3_46x49_sfw}; +static const Icon* const portrait_happy_sfw[BUTTHURT_MAX] = { + &I_passport_happy1_46x49_sfw, + &I_passport_happy2_46x49_sfw, + &I_passport_happy3_46x49_sfw}; +static const Icon* const portrait_ok_sfw[BUTTHURT_MAX] = { + &I_passport_okay1_46x49_sfw, + &I_passport_okay2_46x49_sfw, + &I_passport_okay3_46x49_sfw}; +static const Icon* const portrait_bad_sfw[BUTTHURT_MAX] = { + &I_passport_bad1_46x49_sfw, + &I_passport_bad2_46x49_sfw, + &I_passport_bad3_46x49_sfw}; static const Icon* const portrait_happy[BUTTHURT_MAX] = {&I_flipper}; static const Icon* const portrait_ok[BUTTHURT_MAX] = {&I_flipper}; static const Icon* const portrait_bad[BUTTHURT_MAX] = {&I_flipper}; -static const Icon* const* portraits_sfw[MOODS_TOTAL] = {portrait_happy_sfw, portrait_ok_sfw, portrait_bad_sfw}; +static const Icon* const* portraits_sfw[MOODS_TOTAL] = { + portrait_happy_sfw, + portrait_ok_sfw, + portrait_bad_sfw}; static const Icon* const* portraits[MOODS_TOTAL] = {portrait_happy, portrait_ok, portrait_bad}; // static const Icon* const* portraits[MOODS_TOTAL] = {portrait_happy}; @@ -65,7 +77,6 @@ static void render_callback(Canvas* canvas, void* ctx) { mood = 2; snprintf(mood_str, 20, "Status: Desperate"); } - } uint32_t xp_progress = 0; uint32_t xp_to_levelup = dolphin_state_xp_to_levelup(stats->icounter); @@ -79,20 +90,18 @@ static void render_callback(Canvas* canvas, void* ctx) { } // multipass - if (settings->sfw_mode) { + if(settings->sfw_mode) { canvas_draw_icon(canvas, 0, 0, &I_passport_DB_sfw); - } - else { + } else { canvas_draw_icon(canvas, 0, 0, &I_passport_DB); } // portrait furi_assert((stats->level > 0) && (stats->level <= 30)); uint16_t tmpLvl = 0; - if (settings->sfw_mode) { + if(settings->sfw_mode) { canvas_draw_icon(canvas, 11, 2, portraits_sfw[mood][tmpLvl]); - } - else { + } else { canvas_draw_icon(canvas, 11, 2, portraits[mood][tmpLvl]); } diff --git a/applications/settings/power_settings_app/scenes/power_settings_scene_power_off.c b/applications/settings/power_settings_app/scenes/power_settings_scene_power_off.c index f20f1a5bf..43d429692 100644 --- a/applications/settings/power_settings_app/scenes/power_settings_scene_power_off.c +++ b/applications/settings/power_settings_app/scenes/power_settings_scene_power_off.c @@ -15,14 +15,15 @@ void power_settings_scene_power_off_on_enter(void* context) { DESKTOP_SETTINGS_LOAD(settings); dialog_ex_set_header(dialog, "Turn Off Device?", 64, 2, AlignCenter, AlignTop); - if (settings->sfw_mode) { - dialog_ex_set_text(dialog, " I will be\nwaiting for\n you here", 78, 16, AlignLeft, AlignTop); + if(settings->sfw_mode) { + dialog_ex_set_text( + dialog, " I will be\nwaiting for\n you here", 78, 16, AlignLeft, AlignTop); dialog_ex_set_icon(dialog, 21, 13, &I_Cry_dolph_55x52_sfw); - } - else { - dialog_ex_set_text(dialog, " I will be\nwaiting for\n you master", 78, 16, AlignLeft, AlignTop); + } else { + dialog_ex_set_text( + dialog, " I will be\nwaiting for\n you master", 78, 16, AlignLeft, AlignTop); dialog_ex_set_icon(dialog, 21, 13, &I_Cry_dolph_55x52); - } + } dialog_ex_set_left_button_text(dialog, "Back"); dialog_ex_set_right_button_text(dialog, "OFF"); dialog_ex_set_result_callback(dialog, power_settings_scene_power_off_dialog_callback); diff --git a/applications/settings/storage_settings/scenes/storage_settings_scene_unmounted.c b/applications/settings/storage_settings/scenes/storage_settings_scene_unmounted.c index db7382eb0..4d8f81f9e 100644 --- a/applications/settings/storage_settings/scenes/storage_settings_scene_unmounted.c +++ b/applications/settings/storage_settings/scenes/storage_settings_scene_unmounted.c @@ -16,10 +16,9 @@ void storage_settings_scene_unmounted_on_enter(void* context) { DESKTOP_SETTINGS_LOAD(settings); dialog_ex_set_center_button_text(dialog_ex, "OK"); - if (settings->sfw_mode) { + if(settings->sfw_mode) { dialog_ex_set_icon(dialog_ex, 72, 17, &I_DolphinCommon_56x48_sfw); - } - else { + } else { dialog_ex_set_icon(dialog_ex, 72, 17, &I_DolphinCommon_56x48); } diff --git a/assets/resources/infrared/assets/ac.ir b/assets/resources/infrared/assets/ac.ir index bce1031d6..20a72e0ca 100644 --- a/assets/resources/infrared/assets/ac.ir +++ b/assets/resources/infrared/assets/ac.ir @@ -1,7 +1,37 @@ Filetype: IR library file Version: 1 -# Last Updated 20th Dec, 2022 -# Last Checked 21th Dec, 2022 +# 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 @@ -112,7 +142,7 @@ type: raw frequency: 38000 duty_cycle: 0.330000 data: 473 397 473 397 473 397 472 371 472 397 473 25350 3523 1697 449 1292 449 422 474 397 473 397 473 1267 473 372 470 401 468 402 468 402 441 1300 441 402 468 1272 469 1272 469 402 468 1273 468 1273 468 1272 469 1273 468 1273 468 403 440 402 468 1273 468 402 468 402 468 375 468 402 468 402 468 402 441 402 468 402 468 402 468 376 467 1273 468 402 468 1273 468 402 468 402 441 402 468 1273 468 1273 468 402 468 403 467 376 467 403 467 403 467 376 467 403 467 403 467 403 440 403 467 403 467 403 467 376 467 403 467 403 467 403 440 1302 439 1302 439 1302 439 404 466 1274 467 403 467 1274 467 1275 466 34905 3520 1705 469 1273 468 402 441 402 468 402 468 1273 468 402 468 376 467 402 468 402 468 1273 468 402 441 1300 441 1300 441 403 467 1273 468 1273 468 1273 468 1273 468 1273 468 403 467 402 468 1273 468 376 467 402 468 402 468 402 441 403 467 403 468 402 441 403 467 403 467 403 467 376 467 1274 467 403 467 403 467 403 440 403 467 1274 467 403 467 403 467 376 467 1274 467 1274 467 1274 467 1274 467 403 467 404 466 1274 467 1274 467 404 439 1302 439 1302 439 404 466 404 466 404 439 1302 439 1302 439 404 466 1275 466 404 466 1275 466 404 466 1275 466 34906 3519 1705 468 1273 468 376 467 402 468 402 468 1273 468 402 441 402 468 402 468 402 468 1273 468 376 467 1273 468 1273 468 402 468 1273 468 1273 468 1273 468 1273 468 1273 468 402 468 376 467 1273 468 402 468 402 468 403 440 403 467 403 467 403 467 376 467 403 467 403 467 403 440 403 467 403 468 402 468 376 467 403 467 403 467 403 440 403 467 403 467 403 440 403 467 1274 467 1274 467 1274 467 403 467 404 466 376 467 1274 467 1275 466 404 466 1275 466 1275 466 404 466 404 439 404 466 404 467 404 466 377 466 404 466 404 466 404 439 404 466 404 466 405 438 405 465 404 466 405 465 1276 465 1299 442 378 465 406 464 405 465 406 437 405 465 428 442 428 442 401 442 428 442 428 442 428 415 429 441 428 442 429 414 429 441 429 441 428 442 401 442 1300 441 1299 442 429 441 429 441 429 414 429 441 429 441 429 441 402 441 429 441 429 441 429 414 1327 414 1327 414 429 441 429 441 429 441 402 441 429 441 429 441 402 441 429 441 429 441 429 414 429 441 429 441 429 441 402 441 429 441 429 441 429 414 1328 413 430 441 429 441 429 441 402 441 429 441 1300 441 1301 440 429 441 402 441 430 440 430 440 430 413 430 441 429 441 1301 440 430 440 403 440 430 440 430 440 430 413 430 440 430 440 430 440 1301 440 1301 440 1301 440 403 440 430 440 430 440 403 440 1301 440 -# +# name: TEMP- type: raw frequency: 38000 @@ -1440,115 +1470,75 @@ type: raw frequency: 38000 duty_cycle: 0.330000 data: 3821 1901 456 507 456 1424 430 490 484 1425 429 475 488 1420 434 471 482 1427 437 467 486 1420 434 486 457 1416 459 1432 432 487 456 1436 439 480 483 1425 439 1425 460 1420 455 1419 435 485 457 472 491 1417 458 1407 437 483 459 487 456 474 458 487 466 1432 432 471 461 485 457 472 491 1415 460 1378 466 480 483 1424 430 474 458 487 466 1424 461 1419 456 1426 438 465 457 489 464 466 456 489 464 1426 438 481 461 484 437 493 460 1429 435 482 460 485 458 1440 435 484 458 1438 437 467 465 480 462 467 465 481 461 468 464 481 461 469 463 481 461 468 485 1424 430 1434 462 1418 457 1425 439 465 457 489 464 465 457 489 464 466 456 490 463 467 465 480 463 467 465 480 463 467 486 1422 432 471 461 485 457 472 460 485 457 472 460 485 457 472 460 486 456 488 434 497 456 473 459 486 456 488 465 1414 461 1393 482 1423 462 1419 435 469 463 482 460 469 463 482 460 1436 439 1425 439 480 483 +# +name: POWER +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 6149 7347 601 535 573 560 602 505 602 480 597 509 600 534 599 487 593 541 591 568 569 539 568 490 594 539 570 513 568 540 570 566 570 540 568 543 594 540 569 566 543 515 594 540 569 514 567 542 570 514 568 543 594 540 569 490 592 542 570 514 568 541 570 541 542 541 569 567 570 515 567 542 570 515 567 542 570 568 568 516 570 568 570 542 568 542 570 515 569 542 570 568 568 517 569 541 569 517 569 568 570 515 568 570 569 569 543 542 569 569 569 516 569 542 570 543 568 1640 570 516 568 543 570 569 543 1613 569 516 568 1613 570 569 543 570 569 542 543 543 569 543 542 544 569 516 569 544 570 543 570 570 570 543 543 544 569 1615 569 571 569 570 568 519 569 1615 569 544 569 1615 568 572 569 571 542 1642 569 571 568 1617 569 1642 542 1642 569 1589 568 545 569 1590 569 518 568 1617 569 545 568 7372 568 +# +name: MODE +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 6145 7375 572 534 598 535 574 532 576 507 598 507 601 508 599 484 595 565 569 567 568 541 566 541 567 543 567 513 569 540 569 568 568 513 569 567 569 541 568 513 568 568 569 542 568 540 568 543 568 569 567 541 568 543 568 542 541 541 569 542 567 515 569 542 568 514 568 572 567 570 567 515 569 571 567 514 569 544 567 569 568 542 568 1641 566 543 541 595 568 546 567 515 568 573 566 571 566 517 568 572 567 515 568 571 542 543 568 571 567 569 541 519 568 569 516 570 569 1639 541 518 568 570 515 544 568 1666 542 518 568 1666 542 543 568 571 542 516 568 571 542 517 567 598 542 517 568 572 542 544 567 572 542 517 569 571 542 1615 568 1669 542 544 568 572 542 1615 568 599 542 1615 567 572 542 518 569 1642 515 571 542 1615 569 598 542 518 569 598 543 1670 514 1644 542 1616 567 1670 542 545 568 7374 567 +# High +name: TEMP+ +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 6143 7350 600 533 572 507 573 532 575 508 597 507 600 535 572 510 569 539 569 593 542 541 566 540 568 569 541 513 569 540 568 542 567 513 568 570 567 594 542 569 540 541 568 567 542 513 568 571 567 544 564 542 567 569 542 514 569 568 568 568 542 514 567 570 542 514 568 569 569 568 542 514 570 568 542 514 568 570 542 595 515 542 568 1664 542 514 568 1639 542 595 515 569 542 595 543 542 568 597 542 596 542 542 568 597 543 596 540 518 569 596 542 542 568 571 542 1612 568 1640 541 516 568 571 542 596 515 1640 542 516 568 1641 542 596 516 570 542 516 569 571 542 517 568 571 542 516 569 598 543 597 515 571 542 517 568 571 543 1614 568 1642 542 517 569 571 542 1615 569 598 542 1615 568 571 542 544 569 1669 542 518 568 1668 542 1619 565 571 540 1643 543 1668 516 1643 541 1616 567 1670 542 545 568 7371 568 +# Low +name: TEMP- +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 6144 7375 572 534 572 533 574 559 575 507 598 507 600 508 598 484 595 539 568 567 568 513 568 540 568 541 567 513 567 542 568 541 541 540 568 568 568 514 593 515 569 541 568 540 568 543 567 542 567 515 568 569 567 514 569 567 569 542 568 514 568 569 569 542 567 515 569 569 568 515 567 543 567 542 567 516 569 543 567 515 568 543 568 1610 568 569 542 1612 540 542 568 544 566 516 568 596 542 516 567 572 567 596 541 517 568 569 542 543 567 597 542 597 540 518 568 1667 541 1587 567 570 541 544 567 598 541 1587 567 1641 540 1614 567 598 540 598 541 519 566 571 541 519 567 598 541 518 567 572 541 545 566 573 541 519 566 573 541 1617 565 1670 541 545 541 572 541 1642 541 599 541 1642 540 600 541 571 542 1671 539 545 541 1671 540 1617 566 600 540 1642 541 1643 541 1642 540 1644 540 545 541 1643 514 7370 566 +# +name: TIMER +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 6199 7295 628 530 604 504 601 480 573 534 600 482 596 537 570 538 595 541 593 540 568 541 569 567 568 566 568 518 590 1636 569 540 568 1582 566 569 569 540 568 514 569 541 569 567 542 541 569 567 570 514 567 569 568 541 568 515 568 541 569 1610 568 541 569 541 568 516 568 1636 569 515 567 542 569 515 568 542 569 541 568 516 569 541 570 1611 567 543 569 568 568 517 569 1637 569 516 568 542 569 542 568 569 570 569 569 542 568 543 570 516 567 544 569 543 568 543 570 1639 542 1639 568 542 568 518 568 542 569 1588 569 1639 543 1613 569 570 568 517 569 543 543 543 569 570 569 544 569 543 570 517 569 570 569 517 568 572 569 544 568 1642 569 1615 567 571 569 517 569 1642 569 518 567 1616 569 517 569 544 569 1616 568 571 569 1616 568 571 569 1616 568 571 569 1616 568 1642 569 1616 568 1642 568 545 569 7371 568 # -# Model: Sharp AH-X9VEW. Doesn't have heat function. -name: Dh +name: POWER type: raw frequency: 38000 duty_cycle: 0.330000 -data: 307 125509 3831 1867 489 482 491 1392 461 468 485 1397 456 489 464 1411 463 466 487 1397 456 488 465 1390 463 482 481 1402 462 1402 483 471 461 1412 462 468 485 1400 464 1401 484 1397 488 1395 458 471 461 485 457 1408 487 1393 460 485 457 473 459 486 456 474 489 1394 459 471 461 485 457 473 459 488 465 466 455 490 463 467 465 480 462 468 464 482 460 470 483 1399 465 464 457 488 465 465 488 1393 460 484 458 471 461 485 457 1415 459 1405 511 408 482 489 464 466 487 1377 456 489 464 481 461 469 463 482 460 470 462 483 459 470 462 484 458 472 460 485 457 473 459 487 455 474 489 1395 458 471 461 485 457 472 460 486 456 473 459 486 456 474 458 487 455 474 458 488 465 466 487 1396 457 487 434 496 457 488 433 496 457 489 432 497 466 479 432 498 465 480 431 499 464 482 439 490 463 482 460 1394 491 1389 485 1395 490 1392 461 468 464 482 460 469 484 1399 465 1399 465 480 462 483 491 77962 300 +data: 1299 412 1270 412 426 1225 1299 412 1244 438 399 1279 400 1254 451 1253 426 1253 426 1253 426 1254 1268 7130 1266 416 1266 416 421 1258 1267 416 1267 416 422 1258 421 1258 422 1258 421 1259 421 1258 422 1258 1266 7132 1266 417 1266 417 421 1259 1266 417 1266 417 421 1259 421 1259 421 1259 421 1259 421 1259 421 1259 1266 7133 1265 417 1266 417 421 1259 1266 418 1266 417 422 1259 421 1260 420 1259 421 1259 421 1259 420 1259 1266 7133 1265 418 1266 418 421 1260 1265 418 1266 418 421 1260 420 1260 420 1260 420 1260 420 1260 420 1260 1266 7135 1265 418 1266 419 420 1260 1266 419 1266 419 420 1261 420 1261 420 1261 420 1261 420 1261 420 1261 1265 7137 1264 420 1265 420 419 1262 1266 420 1265 420 420 1262 420 1262 419 1262 420 1262 419 1262 419 1262 1265 7139 1264 421 1265 421 419 1263 1265 421 1265 421 418 1264 418 1264 418 1263 419 1264 417 1264 418 1264 1264 7142 1263 423 1263 422 418 1288 1241 446 1240 446 394 1288 394 1289 393 1288 394 1288 394 1288 394 1288 1241 7168 1240 446 1241 446 394 1289 1241 447 1241 447 394 1289 394 1289 394 1289 394 1289 394 1289 394 1289 1241 7171 1239 447 1240 447 393 1290 1240 447 1241 447 393 1290 393 1290 393 1290 393 1290 393 1290 393 1290 1241 7174 1239 447 1241 448 392 1291 1240 448 1241 448 393 1291 393 1292 392 1292 392 1291 393 1292 392 1291 1240 7177 1239 449 1240 449 392 1292 1240 449 1240 449 392 1293 392 1293 392 1292 392 1293 391 1293 392 1293 1239 7179 1239 450 1239 450 391 1294 1239 450 1240 451 391 1294 391 1294 391 1295 390 1294 391 1295 390 1294 1239 7184 1237 452 1238 475 367 1319 1215 476 1215 476 366 1320 366 1320 366 1320 365 1320 365 1320 366 1320 1215 7211 1213 476 1190 501 366 1321 1215 477 1214 477 365 1322 364 1321 365 1322 364 1321 365 1321 365 1322 1213 7214 1213 478 1213 478 364 1322 1189 503 1189 503 364 1323 339 1348 338 1348 364 1323 363 1324 362 1323 1213 7218 1187 528 1164 529 313 1374 1163 529 1164 529 313 1375 313 1375 312 1375 312 1374 313 1374 313 1375 1163 7271 1162 530 1163 530 312 1376 1163 531 1162 530 312 1377 311 1378 310 1402 285 1378 310 1402 285 1403 1136 7300 1136 557 1136 557 285 1404 1136 558 1136 559 283 1404 285 1431 257 1405 284 1431 257 1431 257 1431 1109 7330 1108 585 1109 586 256 1432 1109 586 1109 638 177 1486 222 1468 221 1468 221 1468 221 1467 221 1495 1055 7413 1028 666 1029 2500 885 # -name: Cool_hi +name: SWING type: raw frequency: 38000 duty_cycle: 0.330000 -data: 345 2685 478 1170 176 29680 3832 1891 465 481 482 1400 464 465 488 1395 458 470 483 1396 457 487 466 1406 458 471 492 1389 464 481 461 1411 463 1408 456 489 464 1407 457 473 490 1392 482 1383 481 1399 486 1396 458 462 459 497 456 1409 486 1394 459 459 483 473 459 487 455 474 489 1392 461 468 464 481 461 469 463 483 459 471 482 1398 487 1379 464 481 461 485 457 1416 458 487 466 1407 457 472 460 460 482 474 489 1393 460 469 463 483 459 471 461 485 457 1408 456 488 465 481 461 469 484 1381 462 483 459 486 456 473 459 487 455 474 458 487 455 475 457 489 464 467 465 481 461 1410 485 1380 484 1397 488 1392 461 483 459 471 461 485 457 473 459 486 456 474 458 488 454 476 456 490 463 467 465 481 461 1411 464 481 440 491 462 484 437 492 461 485 436 494 459 487 434 495 458 488 433 497 456 489 432 498 486 450 482 1408 467 1389 485 1394 480 1384 459 486 456 489 464 466 487 1393 460 485 457 1415 459 1406 510 +data: 1333 359 1331 358 482 1200 1279 411 1279 411 430 1255 430 1256 1279 411 430 1257 428 1257 428 1258 452 7993 1276 390 1300 415 402 1285 1276 415 1276 416 425 1262 425 1262 1275 417 425 1262 425 1262 425 1262 424 8000 1274 417 1275 417 425 1262 1276 417 1276 417 425 1263 424 1263 1275 417 425 1263 424 1263 425 1263 424 8003 1274 417 1276 417 425 1263 1275 418 1276 417 425 1263 425 1263 1276 417 425 1263 425 1263 425 1263 425 8006 1275 418 1276 418 425 1264 1276 418 1276 418 425 1264 425 1264 1276 418 425 1264 425 1264 425 1264 424 8009 1276 418 1276 418 425 1265 1276 418 1277 419 424 1265 425 1265 1276 419 424 1265 424 1265 425 1265 424 8013 1275 419 1277 419 424 1266 1276 419 1277 419 425 1266 424 1266 1276 419 424 1266 424 1266 424 1266 424 8016 1276 419 1277 420 424 1267 1276 420 1277 420 424 1267 424 1267 1276 420 424 1267 424 1267 424 1267 424 8019 1276 420 1277 420 424 1267 1277 420 1277 421 423 1268 423 1268 1277 421 423 1268 424 1268 423 1268 423 8023 1275 421 1276 421 423 1268 1277 421 1277 421 424 1269 423 1269 1277 422 423 1269 423 1269 423 1269 423 8025 1276 422 1276 422 423 1270 1276 422 1277 422 423 1270 422 1270 1277 422 423 1271 422 1271 421 1271 422 8029 1275 423 1276 423 422 1271 1276 423 1276 447 398 1273 421 1273 1275 424 421 1296 397 1296 397 1296 397 8056 1252 447 1253 447 398 1296 1252 448 1253 448 398 1296 398 1296 1252 448 398 1297 397 1296 398 1296 398 8059 1252 448 1253 448 398 1297 1252 448 1253 448 398 1297 397 1297 1252 449 397 1298 397 1297 397 1297 397 8062 1252 449 1253 449 397 1298 1252 449 1253 449 397 1298 397 1298 1253 450 396 1298 397 1298 397 1298 397 8065 1252 449 1252 450 397 1299 1252 450 1253 450 396 1299 397 1299 1253 450 396 1299 397 1299 396 1299 396 8069 1251 450 1253 450 396 1300 1252 450 1253 451 396 1300 396 1300 1253 451 396 1301 396 1300 396 1301 395 8072 1251 451 1253 451 396 1301 1252 452 1252 452 395 1302 395 1302 1227 477 395 1302 395 1302 394 1302 395 8076 1251 452 1227 478 394 1302 1252 453 1227 478 370 1328 369 1328 1251 454 394 1304 369 1329 369 1329 369 8129 1201 503 1202 503 344 1353 1202 503 1203 503 345 1354 344 1354 1202 504 344 1354 345 1354 344 1354 344 8132 1201 503 1202 504 344 1354 1202 504 1202 504 344 1355 344 1355 1202 504 344 1355 344 1355 344 1355 344 8135 1201 504 1202 505 343 1355 1202 505 1202 505 343 1357 343 1357 1201 506 343 1358 342 1383 316 1383 316 8166 1173 533 1174 559 288 1412 1147 560 1148 561 287 1439 261 1440 1120 588 260 1441 259 1467 227 1474 225 # -name: Cool_lo +name: TIMER type: raw frequency: 38000 duty_cycle: 0.330000 -data: 181 11813 3819 1899 457 488 486 1421 433 472 491 1416 438 481 461 1417 437 482 492 1416 437 467 486 1419 435 485 457 1439 435 1403 461 483 480 1408 435 484 490 1416 438 1401 484 1395 490 1392 461 467 465 480 462 1427 458 1396 457 486 456 473 459 486 456 472 481 1426 438 466 466 480 462 467 465 480 462 467 465 479 463 1426 438 481 461 484 458 1438 436 1409 486 1378 465 480 462 483 459 471 482 1425 428 475 457 487 455 474 458 487 455 1434 430 489 464 481 461 468 485 1404 439 480 462 483 459 470 462 483 459 469 463 482 460 470 462 483 459 470 462 483 459 1437 458 1381 483 1395 490 1390 463 481 461 469 463 482 460 468 464 481 461 468 464 481 461 469 463 482 460 469 463 481 461 1434 430 474 458 486 456 473 459 486 456 473 459 486 456 473 459 486 456 473 459 485 457 472 460 485 489 449 462 1434 461 1378 486 1393 481 1397 519 400 479 476 456 489 464 1431 433 486 435 495 458 487 487 +data: 1275 413 1305 384 457 1226 1308 385 1329 385 430 1228 457 1228 457 1229 1304 411 429 1257 428 1258 427 7993 1275 416 1275 416 425 1262 1274 416 1275 417 425 1262 425 1262 425 1261 1276 416 426 1262 424 1262 425 7999 1274 417 1275 417 425 1262 1276 417 1276 417 425 1263 424 1262 425 1262 1276 417 425 1263 425 1263 424 8003 1274 417 1276 417 425 1263 1275 417 1277 417 425 1263 425 1263 425 1263 1276 418 425 1264 424 1263 425 8006 1276 418 1276 418 425 1263 1277 418 1277 418 425 1264 425 1264 425 1264 1276 418 425 1264 425 1264 425 8010 1276 418 1276 418 425 1264 1277 418 1277 418 425 1265 425 1265 424 1265 1276 418 425 1265 425 1265 425 8012 1276 418 1277 418 425 1265 1277 419 1277 419 425 1266 424 1266 424 1266 1277 419 425 1266 424 1266 424 8016 1276 419 1277 419 425 1266 1277 419 1278 419 425 1267 424 1266 425 1267 1277 420 424 1267 424 1267 424 8020 1275 420 1277 420 424 1267 1277 420 1277 420 424 1268 424 1268 423 1267 1277 420 424 1268 424 1268 424 8023 1276 420 1277 421 424 1268 1277 421 1277 421 424 1269 423 1269 423 1268 1278 421 423 1269 424 1269 423 8026 1276 421 1277 422 423 1269 1277 422 1277 422 423 1270 423 1270 423 1270 1276 422 423 1270 423 1271 422 8029 1276 423 1276 447 398 1272 1276 446 1254 447 399 1295 398 1272 422 1295 1252 447 398 1295 398 1295 398 8056 1252 447 1252 447 398 1296 1252 447 1253 447 399 1296 398 1296 398 1296 1253 448 398 1296 398 1296 398 8059 1252 447 1253 447 399 1296 1253 448 1253 448 398 1297 397 1297 398 1297 1253 448 398 1297 398 1297 397 8062 1252 448 1253 448 398 1297 1253 448 1254 448 398 1298 397 1298 397 1298 1253 449 397 1298 397 1298 397 8065 1252 449 1253 449 397 1298 1253 449 1254 449 398 1299 397 1299 397 1299 1253 449 398 1299 397 1299 397 8069 1252 450 1252 450 397 1299 1253 450 1254 450 397 1300 396 1300 396 1300 1252 450 397 1300 397 1300 396 8072 1252 450 1253 451 396 1300 1253 451 1253 451 396 1301 396 1301 396 1301 1253 451 396 1301 396 1301 396 8075 1251 452 1252 452 396 1301 1253 452 1253 452 395 1303 395 1303 394 1302 1254 453 395 1303 395 1303 395 8081 1250 477 1228 455 393 1304 1252 478 1227 478 370 1329 369 1329 369 1328 1228 478 370 1329 369 1329 369 8107 1227 478 1227 478 370 1329 1227 479 1227 479 369 1329 370 1329 370 1329 1227 479 369 1330 369 1330 369 8111 1225 479 1227 479 369 1330 1227 479 1228 480 368 1331 368 1331 368 1331 1227 480 368 1332 367 1332 367 8114 1225 480 1227 481 367 1332 1226 506 1201 507 342 1358 317 1383 342 1358 1200 507 317 1384 316 1384 316 8168 1174 532 1175 532 316 1384 1175 533 1175 533 315 1385 315 1385 315 1384 1175 533 315 1386 315 1385 315 8171 1174 534 1174 559 289 1387 1174 559 1149 560 289 1413 288 1412 289 1413 1148 560 289 1413 288 1413 288 8203 1147 561 1148 562 287 1414 1148 562 1147 588 260 1416 286 1441 260 1440 1122 588 260 1442 260 1442 260 8232 1120 589 1120 615 228 1474 1095 616 1094 642 182 1494 226 1476 226 1503 1067 643 181 3224 182 8314 1066 671 1039 2427 986 # -name: Off +name: POWER type: raw frequency: 38000 duty_cycle: 0.330000 -data: 3826 1866 490 481 482 1382 461 484 490 1392 461 467 486 1396 457 471 482 1400 464 479 463 1390 463 481 482 1399 465 1398 518 401 510 1379 464 480 483 1398 456 1408 487 1392 482 1399 517 386 483 487 466 1399 486 1392 461 483 459 470 462 482 460 469 484 1397 456 473 459 459 483 472 460 484 458 471 461 483 459 1411 463 480 462 467 486 1377 487 1392 482 1396 457 486 456 472 460 486 456 473 480 1400 464 465 456 488 454 475 488 1393 460 468 464 480 462 467 486 1395 458 470 462 483 459 485 436 493 460 469 463 481 461 486 435 500 463 463 458 486 456 1397 488 1390 484 1394 480 1400 464 465 456 488 465 464 457 487 455 474 458 487 455 473 459 485 457 472 460 485 457 472 481 1399 517 401 458 497 456 473 459 485 457 487 434 495 458 471 461 484 458 488 433 502 430 507 435 500 432 498 455 1409 486 1392 482 1399 454 1409 455 488 465 480 462 467 465 480 462 1408 456 473 459 486 488 -# -# Model: Electrolux ESV09CRO-B21. Doesn't have heat function. -name: Dh -type: raw -frequency: 38000 -duty_cycle: 0.330000 -data: 3092 3057 3092 4438 579 1675 545 534 576 1650 571 535 575 531 569 1656 575 1652 579 527 573 533 577 1648 572 1655 576 1651 580 526 573 532 578 1647 573 532 578 1647 573 1654 577 529 571 535 575 530 570 535 575 529 571 534 576 529 571 534 576 528 571 534 576 528 572 533 577 528 572 533 577 527 573 1651 580 526 573 532 578 527 572 532 568 537 573 531 568 536 574 1650 571 535 575 531 569 536 574 530 569 535 575 529 571 534 576 529 571 533 577 528 572 533 577 527 572 532 568 536 574 531 569 1655 576 530 570 535 575 530 570 535 575 529 571 534 576 528 572 533 577 527 573 532 578 527 572 531 569 536 574 531 569 535 575 530 570 534 576 529 571 534 576 528 571 533 577 527 573 532 567 537 573 531 569 536 574 530 570 535 575 529 571 534 576 528 571 533 577 527 572 532 578 526 573 531 569 536 574 530 570 535 575 529 571 534 576 528 572 533 577 1646 574 532 578 1646 574 1652 579 527 572 533 577 1647 573 1653 578 1675 545 534 576 1649 571 +data: 3110 1566 525 1084 497 356 471 1085 497 356 472 356 471 1085 497 356 470 357 474 1084 498 356 471 356 471 356 471 356 471 356 496 357 470 357 473 1061 520 357 470 1063 519 357 470 1064 518 1064 518 357 470 357 471 # -name: Cool_hi +name: TIMER type: raw frequency: 38000 duty_cycle: 0.330000 -data: 315 101050 3094 3056 3093 4437 580 1648 572 534 576 1649 582 525 574 530 580 1646 574 1653 578 529 570 534 576 529 571 534 576 529 570 1655 576 1651 580 527 572 532 578 1647 573 1654 577 1651 580 526 573 531 579 526 573 531 579 526 573 531 579 526 573 531 579 526 573 531 579 525 574 531 579 525 574 531 579 1646 574 532 578 526 573 531 579 526 573 531 579 526 573 1652 579 527 572 1653 578 528 571 534 576 528 571 533 577 528 571 533 577 528 572 533 577 528 572 532 578 527 572 532 578 527 572 532 578 526 573 1652 579 527 572 532 578 527 572 532 578 527 572 532 578 526 573 531 579 526 573 531 579 526 573 531 579 525 574 530 580 525 574 530 580 525 574 530 580 524 575 529 581 524 575 529 571 534 576 528 571 533 577 528 571 533 577 528 571 533 577 527 572 532 578 527 572 532 578 526 573 531 579 526 573 531 579 525 574 531 579 525 574 530 580 525 574 1650 581 525 574 1651 580 1647 573 533 577 527 572 1653 578 528 572 1654 577 1650 581 1646 574 71637 254 +data: 3128 1546 549 1032 549 356 471 1033 549 357 470 356 445 1085 496 356 471 357 498 1059 523 1059 522 1059 522 1061 520 356 470 357 470 357 470 357 474 1064 518 1065 517 357 470 357 471 357 470 357 470 1064 517 357 471 # -name: Cool_lo +name: TEMP+ type: raw frequency: 38000 duty_cycle: 0.330000 -data: 284 19161 3098 3053 3096 4435 572 1656 575 532 578 1648 572 534 576 530 570 1682 549 1652 579 527 572 534 576 1649 571 1656 575 1652 579 1649 571 1656 575 531 579 527 572 1653 578 1649 571 1656 575 531 579 527 572 532 578 527 572 533 577 527 572 533 577 527 573 532 578 527 572 532 578 527 573 532 578 527 572 1652 579 527 572 533 577 528 571 533 577 528 571 533 577 1648 572 533 577 1649 571 535 575 530 569 536 574 531 569 536 574 530 569 536 574 530 570 535 575 530 570 535 575 530 569 535 575 530 569 535 575 1649 571 535 575 531 568 536 574 531 568 536 574 531 568 536 574 531 569 536 574 530 569 536 574 530 569 535 575 530 569 535 575 530 569 535 575 530 570 535 575 529 570 534 576 529 570 534 576 529 570 534 576 528 571 534 576 528 571 534 576 528 571 534 576 528 571 534 576 528 571 533 577 528 571 533 577 528 572 533 577 528 571 533 577 528 572 1652 579 527 572 1653 578 529 570 534 576 529 570 535 575 529 570 1654 577 1677 554 1673 547 +data: 3107 1568 549 1034 524 356 471 1056 549 357 471 357 471 1031 525 356 471 358 473 1083 498 356 471 1083 498 356 494 357 471 357 469 357 470 358 472 1063 518 357 470 357 470 1064 518 1063 519 1064 517 357 470 357 471 # -name: Off +name: TEMP- type: raw frequency: 38000 duty_cycle: 0.330000 -data: 3093 3058 3090 4441 576 1652 579 528 571 1654 577 531 579 526 573 1652 579 1649 582 525 574 1652 579 528 571 1654 577 1651 580 527 572 533 577 528 571 533 577 1649 582 1646 574 1653 578 529 581 525 574 530 580 525 574 530 580 525 574 531 579 526 573 531 579 526 573 531 579 526 573 531 579 526 573 531 579 526 573 531 579 526 573 531 579 526 573 532 578 1647 573 533 577 1648 572 535 575 530 569 535 575 530 580 525 574 531 579 525 574 531 579 526 573 531 579 526 573 531 579 526 573 531 579 526 573 1651 580 527 572 533 577 528 571 533 577 528 571 533 577 528 571 533 577 528 571 534 576 528 571 534 576 529 570 534 576 529 570 534 576 529 570 534 576 529 570 534 576 529 570 534 576 529 570 534 576 529 570 534 576 529 570 534 576 529 570 534 576 529 570 534 576 529 570 534 576 529 570 534 576 529 570 534 576 529 570 534 576 529 570 534 576 1649 582 525 574 1650 581 1647 573 1654 577 1651 580 1647 573 1654 577 531 579 1646 574 1653 578 -# -# Model: Daikin FTE35KV1. Doesn't have heat function. -name: Dh -type: raw -frequency: 38000 -duty_cycle: 0.330000 -data: 5045 2158 335 1768 358 690 357 723 335 716 331 1771 355 694 364 686 361 720 327 723 335 1767 359 690 357 1775 362 1770 356 692 366 1767 359 1772 354 1777 360 1771 355 1776 361 687 360 690 357 1776 361 687 360 690 357 693 365 716 331 719 328 692 366 1767 359 1772 354 1777 360 1771 355 1776 361 687 360 1773 364 1767 360 689 358 692 366 685 362 688 359 721 326 724 334 717 330 720 327 723 335 715 332 718 329 721 326 1777 360 1771 355 1776 361 1770 356 692 366 715 332 718 329 721 326 29460 5042 2161 332 1770 356 692 366 685 362 688 359 1774 363 685 362 688 359 721 326 694 364 1769 357 691 367 1767 360 1771 355 693 365 1769 358 1773 364 1768 359 1772 365 1766 361 688 359 691 367 1767 360 689 358 692 366 684 363 717 330 720 327 693 365 686 361 689 358 722 336 684 363 1770 357 1774 363 686 361 689 358 1774 363 686 361 1771 356 1776 361 1770 357 692 366 685 362 688 359 690 357 1776 361 687 360 690 357 1776 361 688 359 691 356 694 364 716 331 689 358 1775 362 686 361 689 358 692 366 685 362 688 359 691 356 724 334 716 331 689 358 722 336 685 362 688 359 721 326 693 365 716 331 689 358 692 366 684 363 718 329 690 357 693 365 716 331 689 358 722 336 1767 360 689 358 1774 363 686 361 1771 356 693 365 686 361 689 358 722 336 684 363 717 330 720 327 1776 361 687 360 690 357 693 365 716 331 1771 355 693 365 686 361 1772 355 1776 361 688 359 1773 364 1768 359 -# -name: Cool_hi -type: raw -frequency: 38000 -duty_cycle: 0.330000 -data: 5038 2165 328 1772 365 686 361 689 358 692 366 1765 362 719 328 692 366 684 363 717 330 1771 366 684 363 1768 359 1774 363 686 361 1771 355 1776 361 1770 357 1775 362 1769 358 691 356 694 364 1767 360 691 356 694 364 686 361 689 358 692 366 685 362 1769 358 1775 362 1769 358 1774 363 1768 359 690 357 1776 361 1770 357 692 366 684 363 687 360 690 357 693 365 686 361 689 358 692 366 684 363 687 360 690 357 693 365 1766 361 1773 364 1767 360 1772 355 694 364 686 361 689 358 692 366 25151 319 3980 5041 2131 362 1769 358 693 365 686 361 689 358 1772 365 686 361 689 358 692 366 684 363 1768 359 692 366 1765 361 1772 354 694 364 1769 358 1774 363 1768 359 1773 364 1767 359 719 328 692 366 1796 331 719 328 692 366 685 362 688 359 691 356 694 364 686 361 689 358 692 366 685 362 1768 359 1775 362 686 361 689 358 1773 364 686 361 1770 357 1777 360 1771 355 693 365 686 361 689 358 1772 365 1769 358 690 357 694 364 1767 360 691 356 694 364 686 361 689 358 723 335 1766 361 690 357 693 365 685 362 688 359 691 356 694 364 687 360 690 357 693 365 685 362 688 359 691 356 694 364 687 360 690 357 693 365 685 362 688 359 691 367 684 363 687 360 1771 366 684 363 687 360 690 357 693 365 1767 360 690 357 1804 333 687 360 690 357 693 365 686 361 689 358 692 366 685 362 1768 359 692 366 685 362 688 359 690 357 1774 363 688 359 691 356 1774 363 1770 356 1775 362 1769 358 691 356 -# -name: Cool_lo -type: raw -frequency: 38000 -duty_cycle: 0.330000 -data: 301 132136 5036 2167 337 1766 361 689 358 692 366 684 363 1770 357 692 366 684 363 718 329 690 357 1776 361 687 360 1773 364 1767 360 689 358 1775 362 1769 357 1774 363 1768 359 1773 364 684 363 718 329 1773 364 684 363 718 329 691 356 694 364 716 331 719 328 1775 362 1769 358 1774 363 1768 359 1772 365 714 333 1770 357 1774 363 716 331 719 328 722 336 715 332 718 329 721 326 724 334 716 331 719 328 722 336 715 332 718 329 1773 364 1767 360 1772 354 1777 360 719 328 721 326 725 333 717 330 29455 5036 2139 354 1777 360 688 359 691 367 714 333 1770 356 692 366 684 363 687 360 690 357 1776 361 688 359 1773 364 1768 359 689 358 1775 362 1769 357 1774 363 1768 359 1773 364 684 363 687 360 1773 364 685 362 688 359 691 356 694 364 686 361 689 358 692 366 685 362 688 359 691 356 1777 360 1771 355 693 365 685 362 1771 355 693 365 1768 359 1773 364 1767 360 689 358 692 366 685 362 1771 355 1775 362 687 360 690 357 1775 362 687 360 690 357 693 365 716 331 689 358 1774 363 686 361 689 358 692 366 685 362 688 359 691 356 694 364 686 361 689 358 692 366 685 362 688 359 691 356 694 364 686 361 689 358 692 366 685 362 1771 355 693 365 1768 358 1773 364 684 363 687 360 690 357 693 365 1768 359 690 357 1776 361 688 359 691 356 694 364 686 361 689 358 692 366 685 362 1770 356 693 365 685 362 688 359 691 356 1777 360 1771 355 693 365 686 361 689 358 692 366 685 362 1770 356 -# -name: Off -type: raw -frequency: 38000 -duty_cycle: 0.330000 -data: 5043 2132 361 1770 356 723 335 715 332 718 329 1774 363 715 332 719 328 722 336 714 333 1770 356 722 336 1767 360 1772 354 724 334 1769 357 1774 363 1768 358 1773 364 1767 359 720 327 723 335 1768 359 720 327 723 335 716 331 719 328 722 336 714 333 1770 356 1774 363 1769 357 1773 364 1767 360 720 327 1775 362 1769 357 721 326 725 333 717 330 720 327 723 335 716 331 719 328 722 336 714 333 717 330 720 327 723 335 1768 359 1773 364 1767 360 1772 354 724 334 717 330 720 327 723 335 29451 5041 2134 359 1772 354 724 334 717 330 720 327 1775 362 717 330 720 327 723 335 715 332 1771 355 723 335 1768 358 1773 364 715 332 1770 357 1775 362 1769 357 1774 363 1768 359 720 327 723 335 1768 359 720 327 724 334 716 331 719 328 722 336 715 332 718 329 720 327 723 335 716 331 1771 355 1776 361 718 329 721 326 1776 361 718 329 1773 364 1767 360 720 327 723 335 715 332 718 329 1774 363 1768 359 720 327 723 335 1768 358 721 326 724 334 716 331 719 328 722 336 1767 360 719 328 722 336 715 332 718 329 721 326 724 334 717 330 720 327 723 335 715 332 719 328 722 325 725 333 717 330 720 327 723 335 716 331 719 328 1774 363 716 331 1771 355 1776 361 718 329 721 326 724 334 717 330 1772 365 714 333 1770 356 722 336 715 332 718 329 721 326 724 334 717 330 719 328 1775 362 717 330 720 327 723 335 715 332 718 329 1774 363 715 332 718 329 721 326 725 333 717 330 1772 365 -# -# Model: Dyson Purifier Hot+Cool -name: Off -type: raw -frequency: 38000 -duty_cycle: 0.330000 -data: 2309 665 781 672 803 672 803 695 832 643 833 1355 804 694 836 640 781 695 804 1409 778 697 777 702 797 678 798 677 799 678 799 701 803 674 802 1412 801 674 801 674 801 674 802 674 801 51317 2284 670 775 1413 802 51252 2283 670 801 1412 775 51275 2258 673 798 1414 802 51248 2284 670 802 1412 774 51246 2259 695 775 1413 801 -# -name: Heat_hi -type: raw -frequency: 38000 -duty_cycle: 0.330000 -data: 2316 610 806 671 781 695 806 695 781 695 782 1405 782 694 808 694 780 693 808 1381 779 697 802 1412 776 1438 800 1437 776 1438 775 700 775 1412 776 700 801 701 775 700 776 1438 776 700 776 51695 2258 695 776 1437 776 51248 2258 672 798 1439 776 51240 2258 670 801 1436 776 -# -name: Heat_lo -type: raw -frequency: 38000 -duty_cycle: 0.330000 -data: 2342 612 781 695 805 668 810 666 810 665 811 1402 811 666 811 692 781 670 781 1432 781 696 778 1436 802 1412 802 1412 802 1413 801 1412 802 1412 801 1412 777 1411 776 1463 776 1412 800 1414 801 51041 2257 697 802 1411 777 51240 2283 671 776 1437 801 51209 2255 672 799 1412 801 -# -name: Cool_hi -type: raw -frequency: 38000 -duty_cycle: 0.330000 -data: 2317 637 832 644 830 669 805 670 805 672 803 1411 803 673 802 674 802 673 803 1411 803 674 801 1411 802 675 775 1415 800 701 774 1440 801 1412 775 702 799 1414 774 1413 801 701 801 675 800 51681 2257 695 803 1411 801 51226 2283 671 799 1412 803 51246 2257 696 803 1411 775 51255 2282 668 803 1410 802 51243 2258 695 802 1387 798 -# -name: Cool_lo -type: raw -frequency: 38000 -duty_cycle: 0.330000 -data: 2315 618 853 643 832 644 834 641 833 643 833 1356 805 695 835 640 808 667 809 1404 808 668 806 1409 803 674 801 1412 802 1388 799 677 799 701 775 701 801 1389 799 677 799 676 800 1439 802 51426 2283 671 800 1412 802 51251 2258 697 801 1387 800 51248 2283 669 802 1411 802 51230 2258 696 799 1387 801 51225 2283 670 801 1411 801 51200 2280 695 775 1411 802 51227 2258 696 802 1411 775 51204 2281 669 801 1411 800 -# -name: Dh -type: raw -frequency: 38000 -duty_cycle: 0.330000 -data: 2320 634 837 637 838 637 838 640 835 642 832 1378 836 645 826 670 809 667 808 1406 806 672 803 674 802 1412 802 1412 800 676 801 675 802 1412 802 674 802 1413 801 1412 801 1413 802 1412 802 50937 2285 671 801 1411 802 51225 2280 696 775 1412 801 51212 2283 671 775 1412 802 +data: 3110 1567 551 1031 550 356 471 1032 550 356 471 356 445 1084 497 355 472 357 497 356 472 1058 523 1058 523 356 471 356 470 357 469 357 470 357 474 357 470 1063 519 357 470 1063 518 1063 519 1063 518 357 470 357 471 diff --git a/assets/resources/infrared/assets/audio.ir b/assets/resources/infrared/assets/audio.ir index f39a8c3b4..5a0b18658 100644 --- a/assets/resources/infrared/assets/audio.ir +++ b/assets/resources/infrared/assets/audio.ir @@ -1,309 +1,176 @@ Filetype: IR library file Version: 1 -# Last Checked 20th Dec, 2022 -# Model: NoName Unknown Audio remote -name: Play +# Last Updated 13th Jan, 2023 +# Last Checked 13th Jan, 2023 +# +name: POWER type: parsed protocol: NEC -address: 00 00 00 00 -command: 43 00 00 00 -# -name: Vol_up +address: 77 00 00 00 +command: F1 00 00 00 +# +name: MUTE type: parsed protocol: NEC -address: 00 00 00 00 -command: 15 00 00 00 -# -name: Vol_dn +address: 77 00 00 00 +command: F3 00 00 00 +# +name: VOL+ type: parsed protocol: NEC -address: 00 00 00 00 -command: 07 00 00 00 -# -name: Next +address: 77 00 00 00 +command: FB 00 00 00 +# +name: VOL- type: parsed protocol: NEC -address: 00 00 00 00 -command: 40 00 00 00 -# -name: Prev +address: 77 00 00 00 +command: FC 00 00 00 +# +name: POWER type: parsed protocol: NEC -address: 00 00 00 00 -command: 44 00 00 00 -# -# Model: Western Digital Unknown -name: Power -type: parsed -protocol: NECext -address: 84 79 00 00 -command: 12 ED 00 00 -# -name: Play -type: parsed -protocol: NECext -address: 84 79 00 00 -command: 0A F5 00 00 -# -name: Vol_up -type: parsed -protocol: NECext -address: 84 79 00 00 -command: 05 FA 00 00 -# -name: Vol_dn -type: parsed -protocol: NECext -address: 84 79 00 00 -command: 00 FF 00 00 -# -name: Next -type: parsed -protocol: NECext -address: 84 79 00 00 -command: 01 FE 00 00 -# -name: Prev -type: parsed -protocol: NECext -address: 84 79 00 00 -command: 02 FD 00 00 -# -# Model: Yamaha RAV15 -name: Play -type: parsed -protocol: NEC -address: 00 00 00 00 -command: 43 00 00 00 -# -name: Vol_up -type: parsed -protocol: NEC -address: 00 00 00 00 -command: 15 00 00 00 -# -name: Vol_dn -type: parsed -protocol: NEC -address: 00 00 00 00 -command: 07 00 00 00 -# -name: Next -type: parsed -protocol: NEC -address: 00 00 00 00 -command: 40 00 00 00 -# -name: Prev -type: parsed -protocol: NEC -address: 00 00 00 00 -command: 44 00 00 00 -# -# Model: Yamaha RX-V375 -name: Power -type: parsed -protocol: NEC -address: 7E 00 00 00 -command: 2A 00 00 00 -# -name: Vol_up -type: parsed -protocol: NEC -address: 7A 00 00 00 +address: 80 00 00 00 command: 1A 00 00 00 -# -name: Mute -type: parsed -protocol: NEC -address: 7A 00 00 00 -command: 1C 00 00 00 -# -name: Vol_dn -type: parsed -protocol: NEC -address: 7A 00 00 00 -command: 1B 00 00 00 -# -# Model: SVEN HT-415 -name: Power -type: parsed -protocol: NEC -address: 41 00 00 00 -command: 42 00 00 00 -# -name: Vol_up -type: parsed -protocol: NEC -address: 41 00 00 00 -command: 0B 00 00 00 -# -name: Vol_dn -type: parsed -protocol: NEC -address: 41 00 00 00 -command: 1B 00 00 00 -# -name: Mute -type: parsed -protocol: NEC -address: 41 00 00 00 -command: 56 00 00 00 -# -# Model: HUAYU AKB74475490 -name: Power -type: parsed -protocol: NEC -address: 04 00 00 00 -command: 08 00 00 00 -# -name: Play -type: parsed -protocol: NEC -address: 04 00 00 00 -command: B0 00 00 00 -# -name: Pause -type: parsed -protocol: NEC -address: 04 00 00 00 -command: BA 00 00 00 -# -name: Vol_up -type: parsed -protocol: NEC -address: 04 00 00 00 -command: 02 00 00 00 -# -name: Vol_dn -type: parsed -protocol: NEC -address: 04 00 00 00 -command: 03 00 00 00 -# -name: Prev -type: parsed -protocol: NEC -address: 04 00 00 00 -command: 8F 00 00 00 -# -name: Next -type: parsed -protocol: NEC -address: 04 00 00 00 -command: 8E 00 00 00 -# -name: Mute -type: parsed -protocol: NEC -address: 04 00 00 00 -command: 09 00 00 00 -# -# Model: Samsung HW-K450 Soundbar # -name: Power -type: raw -frequency: 38000 -duty_cycle: 0.330000 -data: 4637 4376 612 419 584 420 584 420 583 421 582 1427 531 1477 531 472 532 472 557 1452 556 1451 557 1451 557 1452 556 447 557 448 556 449 555 449 555 4453 554 450 554 450 554 451 553 450 554 451 553 451 553 451 553 450 554 1455 553 1454 554 1454 554 451 553 1454 554 1454 554 1455 553 1454 554 451 553 450 554 450 554 1455 553 55439 4554 4458 555 449 555 449 555 450 554 450 554 1455 553 1454 554 451 553 450 554 1454 554 1454 554 1454 554 1455 553 450 554 451 553 451 553 451 553 4453 554 451 553 451 552 451 553 451 553 451 553 451 553 451 553 451 553 1455 553 1455 553 1455 553 451 553 1455 553 1455 553 1455 553 1455 553 451 553 451 552 451 553 1455 553 -# -name: Play -type: raw -frequency: 38000 -duty_cycle: 0.330000 -data: 4636 4380 612 392 612 394 610 394 610 419 583 1399 557 1452 556 473 556 448 556 1428 581 1453 555 1453 555 1453 555 449 555 450 554 451 553 452 552 4457 551 452 552 452 552 452 552 452 552 452 552 1457 551 452 552 1457 551 452 552 452 552 453 551 1457 552 1457 551 452 552 1457 551 452 552 1457 551 1457 551 1457 552 452 552 55450 4551 4461 553 451 553 452 552 452 552 452 552 1456 552 1456 552 452 552 452 552 1456 552 1456 552 1456 552 1456 552 452 552 452 552 453 551 453 551 4456 551 453 551 453 551 453 551 453 551 453 551 1457 551 453 551 1457 552 453 551 454 550 454 550 1457 552 1457 551 454 550 1457 551 454 550 1458 551 1457 551 1458 550 454 550 -# -name: Vol_up -type: raw -frequency: 38000 -duty_cycle: 0.330000 -data: 4640 4405 583 420 583 421 582 421 583 422 581 1427 531 1478 530 473 531 472 557 1452 557 1452 556 1452 556 1452 556 448 556 448 556 449 555 450 554 4454 554 451 553 451 553 451 553 451 553 1455 554 1455 553 1455 553 451 553 1455 553 1456 553 1456 553 451 553 451 553 451 553 451 554 1455 554 451 553 452 553 451 553 1456 553 55447 4556 4458 555 449 555 450 554 450 554 450 554 1455 553 1455 553 451 553 451 553 1455 553 1455 553 1455 553 1455 553 451 553 451 553 451 553 451 553 4454 553 451 553 450 554 451 553 450 554 1455 553 1455 553 1455 553 451 553 1455 553 1455 553 1455 553 451 553 451 553 451 553 450 554 1455 553 451 553 451 553 451 553 1455 553 -# -name: Vol_dn -type: raw -frequency: 38000 -duty_cycle: 0.330000 -data: 4636 4378 613 393 611 392 612 393 611 393 557 1451 558 1450 610 420 583 421 557 1427 581 1452 556 1452 556 1452 556 448 555 449 555 450 554 450 554 4455 553 451 553 451 553 451 553 451 553 451 553 451 553 452 552 1456 553 1456 552 1456 553 1456 552 451 553 1456 553 1456 552 1456 553 451 553 451 553 452 552 451 553 1456 552 55452 4553 4461 553 450 554 451 553 451 553 451 553 1456 553 1456 552 451 553 451 553 1456 552 1455 553 1455 553 1455 553 451 553 451 553 451 553 451 553 4456 552 451 553 451 553 451 553 451 553 451 553 451 553 451 553 1456 552 1455 553 1455 553 1455 553 451 553 1455 553 1456 552 1456 552 451 553 451 553 451 553 451 553 1456 552 -# -name: Prev -type: raw -frequency: 38000 -duty_cycle: 0.330000 -data: 255 113623 4638 4378 613 391 612 392 559 446 558 446 558 1477 531 1477 532 472 532 472 532 1476 532 1476 532 1476 532 1477 531 473 555 449 555 449 555 450 554 4455 554 450 554 450 554 450 554 450 554 1455 554 1455 554 450 554 1455 554 450 555 450 554 450 554 1455 554 451 553 451 553 1455 554 450 554 1455 554 1456 553 1455 554 450 554 -# -name: Next -type: raw -frequency: 38000 -duty_cycle: 0.330000 -data: 4557 4430 611 392 610 394 559 445 559 446 558 1451 558 1477 531 448 556 472 532 1476 532 1477 532 1477 531 1477 531 473 556 449 555 449 555 450 554 4454 554 450 554 450 554 450 554 450 555 450 554 450 554 1455 554 1455 554 450 554 450 554 450 554 1455 554 1455 554 1455 553 451 553 450 554 1455 554 1455 554 1455 554 450 554 55458 4555 4459 554 450 554 450 554 450 554 450 554 1455 553 1455 553 450 554 450 554 1455 553 1455 553 1455 553 1455 553 450 554 450 554 450 554 450 554 4454 554 450 554 450 554 450 554 451 553 450 554 450 554 1455 553 1455 553 451 553 450 554 450 554 1455 553 1455 553 1455 553 450 554 451 553 1455 554 1455 553 1455 553 450 554 -# -name: Mute -type: raw -frequency: 38000 -duty_cycle: 0.330000 -data: 4639 4406 586 418 585 393 559 447 557 447 557 1477 532 1477 532 472 532 472 532 1476 533 1476 532 1476 532 1476 532 473 555 449 555 449 555 449 555 4455 554 450 554 450 554 450 554 450 554 1455 554 450 554 450 554 450 554 1455 554 1455 553 1455 553 450 554 450 554 1455 554 1455 554 1455 554 450 554 450 554 450 554 1455 554 55454 4557 4458 555 449 555 449 555 450 554 450 554 1455 554 1455 553 450 554 450 554 1455 554 1455 554 1454 554 1455 554 450 554 450 554 450 555 450 554 4455 553 450 554 450 554 450 554 450 554 1455 554 450 554 450 554 450 554 1455 554 1455 554 1455 553 450 554 450 554 1455 554 1455 553 1455 554 450 554 450 554 450 554 1455 554 -# -# Model: Edifier R1850DB -name: Power +name: POWER type: parsed protocol: NECext address: 10 E7 00 00 command: 46 B9 00 00 -# -name: Play +# +name: VOL+ type: parsed protocol: NECext address: 10 E7 00 00 -command: 5E A1 00 00 -# -name: Vol_up +command: 06 F9 00 00 +# +name: VOL- type: parsed protocol: NECext address: 10 E7 00 00 -command: 05 FA 00 00 -# -name: Vol_dn -type: parsed -protocol: NECext -address: 10 E7 00 00 -command: 49 B6 00 00 -# -name: Next -type: parsed -protocol: NECext -address: 10 E7 00 00 -command: 02 FD 00 00 -# -name: Prev -type: parsed -protocol: NECext -address: 10 E7 00 00 -command: 1E E1 00 00 -# -name: Mute +command: 47 B8 00 00 +# +name: MUTE type: parsed protocol: NECext address: 10 E7 00 00 command: 41 BE 00 00 -# +# +name: POWER +type: parsed +protocol: RC5 +address: 10 00 00 00 +command: 0C 00 00 00 +# +name: MUTE +type: parsed +protocol: RC5 +address: 10 00 00 00 +command: 0D 00 00 00 +# +name: VOL+ +type: parsed +protocol: RC5 +address: 10 00 00 00 +command: 10 00 00 00 +# +name: VOL- +type: parsed +protocol: RC5 +address: 10 00 00 00 +command: 11 00 00 00 +# +name: POWER +type: parsed +protocol: NEC +address: 00 00 00 00 +command: 40 00 00 00 +# +name: VOL+ +type: parsed +protocol: NEC +address: 00 00 00 00 +command: 41 00 00 00 +# +name: VOL- +type: parsed +protocol: NEC +address: 00 00 00 00 +command: 45 00 00 00 +# +name: MUTE +type: parsed +protocol: NEC +address: 00 00 00 00 +command: 48 00 00 00 +# +name: POWER +type: parsed +protocol: NECext +address: 2D D3 00 00 +command: 12 ED 00 00 +# +name: VOL+ +type: parsed +protocol: NECext +address: 2D D3 00 00 +command: 11 EE 00 00 +# +name: VOL- +type: parsed +protocol: NECext +address: 2D D3 00 00 +command: 10 EF 00 00 +# +name: MUTE +type: parsed +protocol: NECext +address: 2D D3 00 00 +command: 13 EC 00 00 +# +name: POWER +type: parsed +protocol: SIRC15 +address: 44 00 00 00 +command: 15 00 00 00 +# +name: VOL+ +type: parsed +protocol: SIRC15 +address: 44 00 00 00 +command: 12 00 00 00 +# +name: VOL- +type: parsed +protocol: SIRC15 +address: 44 00 00 00 +command: 13 00 00 00 +# +name: MUTE +type: parsed +protocol: SIRC15 +address: 44 00 00 00 +command: 14 00 00 00 +# name: POWER type: parsed protocol: NECext address: 02 A0 00 00 command: 80 7F 00 00 -# +# name: VOL+ type: parsed protocol: NECext address: 02 A0 00 00 command: AA 55 00 00 -# +# name: VOL- type: parsed protocol: NECext address: 02 A0 00 00 command: 6A 95 00 00 -# +# name: MUTE type: parsed protocol: NECext @@ -333,7 +200,7 @@ type: parsed protocol: NEC address: 04 00 00 00 command: 06 00 00 00 -# +# name: POWER type: parsed protocol: NECext @@ -357,25 +224,25 @@ type: parsed protocol: NECext address: 29 A1 00 00 command: 9F 60 00 00 -# +# name: POWER type: parsed protocol: NEC address: 7A 00 00 00 command: 1F 00 00 00 -# +# name: POWER type: parsed protocol: NEC address: 00 00 00 00 command: 1C 00 00 00 -# +# name: MUTE type: parsed protocol: NEC address: 00 00 00 00 command: 0B 00 00 00 -# +# name: VOL+ type: parsed protocol: NEC @@ -387,49 +254,49 @@ type: parsed protocol: NEC address: 00 00 00 00 command: 05 00 00 00 -# +# name: VOL+ type: raw frequency: 38000 duty_cycle: 0.330000 data: 4617 4406 584 448 557 448 557 449 556 449 555 1430 580 1432 577 452 552 454 550 1460 549 1462 548 1462 549 1462 548 457 548 457 548 457 548 457 548 4463 548 457 548 457 548 457 548 458 548 1462 548 1462 548 1462 548 457 548 1463 547 1462 548 1462 548 458 547 458 548 458 548 458 547 1463 547 458 547 458 547 458 548 1463 547 55451 4606 4440 549 457 548 457 548 457 548 457 548 1462 548 1462 548 457 548 457 548 1462 548 1461 549 1462 548 1462 548 457 548 457 548 457 548 457 548 4462 548 457 548 457 548 457 548 457 548 1462 548 1462 548 1462 548 457 548 1462 548 1462 548 1462 547 457 548 458 547 458 547 458 547 1462 548 458 547 458 547 458 547 1462 548 -# +# name: VOL- type: raw frequency: 38000 duty_cycle: 0.330000 data: 4614 4408 583 449 555 450 555 451 553 451 554 1432 577 1434 576 453 551 454 550 1460 549 1461 549 1461 549 1461 549 457 548 457 548 457 548 457 548 4461 548 457 548 457 548 457 548 457 548 457 548 457 548 457 548 1462 548 1461 549 1461 549 1461 548 457 548 1462 549 1461 549 1461 548 457 548 457 548 457 548 458 547 1462 548 55443 4606 4440 549 456 549 456 549 456 549 456 549 1461 549 1461 549 457 548 457 548 1461 549 1461 549 1461 549 1461 549 456 549 457 548 457 548 457 548 4461 549 456 549 457 548 457 548 457 548 457 548 457 548 457 548 1462 548 1461 549 1461 549 1461 548 457 548 1461 549 1461 549 1461 549 457 548 457 548 458 547 457 548 1462 548 -# +# name: POWER type: raw frequency: 38000 duty_cycle: 0.330000 data: 4588 4435 556 477 556 449 555 450 555 451 554 1428 582 1429 581 451 553 452 552 1457 552 1458 551 1461 548 1463 547 458 547 458 547 458 547 458 547 4464 547 458 547 458 547 458 547 458 548 458 547 458 547 458 548 458 547 1463 547 1463 547 1464 546 459 547 1464 546 1464 546 1463 547 1464 546 459 546 459 546 459 546 1464 547 55456 4581 4468 546 458 547 458 547 458 547 458 547 1463 547 1463 547 458 547 459 547 1463 547 1464 546 1464 546 1464 547 459 546 459 546 459 546 459 547 4465 546 459 546 459 546 459 546 459 546 459 547 459 546 459 546 459 546 1464 546 1464 546 1465 546 460 545 1465 545 1465 545 1465 546 1465 546 460 545 460 546 460 545 1466 544 -# +# name: POWER type: parsed protocol: NECext address: 3F 5C 00 00 command: 18 E7 00 00 -# +# name: VOL+ type: parsed protocol: NECext address: 3F 5C 00 00 command: 55 AA 00 00 -# +# name: VOL- type: parsed protocol: NECext address: 3F 5C 00 00 command: 59 A6 00 00 -# +# name: MUTE type: parsed protocol: NECext address: 3F 5C 00 00 command: 15 EA 00 00 -# +# name: MUTE type: parsed protocol: NECext @@ -453,25 +320,25 @@ type: parsed protocol: NECext address: 00 FB 00 00 command: 0A F5 00 00 -# +# name: VOL+ type: parsed protocol: NECext address: 80 D9 00 00 command: 8A 75 00 00 -# +# name: VOL- type: parsed protocol: NECext address: 80 D9 00 00 command: 88 77 00 00 -# +# name: MUTE type: parsed protocol: NECext address: 80 D9 00 00 command: 8C 73 00 00 -# +# name: POWER type: parsed protocol: NECext @@ -495,13 +362,13 @@ type: parsed protocol: NECext address: 78 0E 00 00 command: 18 E7 00 00 -# +# name: VOL+ type: parsed protocol: NEC address: 20 00 00 00 command: 14 00 00 00 -# +# name: VOL- type: parsed protocol: NEC @@ -514,1579 +381,1501 @@ type: parsed protocol: RC5 address: 10 00 00 00 command: 0E 00 00 00 -# +# name: VOL- type: parsed protocol: NECext address: 10 E7 00 00 command: 0C F3 00 00 -# +# name: VOL+ type: parsed protocol: NECext address: 10 E7 00 00 command: 09 F6 00 00 -# +# name: POWER type: raw frequency: 38000 duty_cycle: 0.330000 data: 3309 1906 410 1178 411 1177 412 416 435 445 406 448 414 440 411 1150 439 415 436 1178 411 1177 412 442 409 444 407 1181 408 419 432 1182 407 420 442 1146 433 448 414 440 411 442 409 444 407 446 416 438 413 441 410 443 408 419 432 1182 407 446 405 422 440 414 437 416 435 445 406 1181 408 446 405 448 414 440 411 442 409 418 433 446 416 438 413 1175 414 413 438 1176 413 414 437 443 408 419 432 421 441 413 438 42493 3308 3343 355 43011 3309 3316 382 43009 3310 3314 384 43007 3303 3347 361 -# +# name: VOL+ type: raw frequency: 38000 duty_cycle: 0.330000 data: 3307 1879 437 1177 412 1176 413 415 436 417 434 446 405 448 414 1174 415 412 439 1149 440 1147 442 438 413 440 411 1177 412 441 410 1178 411 442 409 1179 410 417 434 419 432 448 414 440 411 442 409 444 407 446 416 438 413 441 410 1151 438 415 436 444 407 446 416 412 439 414 437 1177 412 1176 413 414 437 416 435 1152 437 1177 412 416 435 444 407 446 416 1146 433 421 441 1173 406 422 440 413 438 442 409 444 407 40133 3308 3341 357 42862 3301 3347 361 42859 3304 3319 379 -# +# name: VOL- type: raw frequency: 38000 duty_cycle: 0.330000 data: 3310 1876 440 1174 415 1173 405 422 440 414 437 443 408 445 406 1182 407 420 442 1173 406 1182 407 420 442 412 439 1175 414 440 411 1150 439 415 436 1152 437 416 435 419 432 447 415 440 411 442 409 418 433 420 442 438 413 440 411 1177 412 415 436 418 433 420 442 438 413 441 410 1151 438 1150 439 415 436 1178 411 1150 439 1149 440 414 437 417 434 445 406 1155 434 420 442 438 413 1175 414 413 438 442 409 444 407 39503 3303 3320 388 42857 3304 3319 379 42867 3305 3317 381 -# +# name: MUTE type: raw frequency: 38000 duty_cycle: 0.330000 data: 3305 1907 409 1178 411 1177 412 442 409 418 433 447 415 439 412 1176 413 441 410 1177 412 1176 413 441 410 443 408 1180 409 445 406 1181 408 446 416 1172 406 448 413 440 411 442 409 445 406 447 414 439 412 442 409 444 407 447 414 1173 405 449 413 441 410 443 408 446 405 448 413 1174 415 440 411 442 409 1178 411 1177 412 1177 412 442 409 444 407 447 415 439 412 441 410 444 407 1180 409 445 406 448 414 440 411 41125 3303 3347 360 42906 3308 3315 382 -# +# name: MUTE type: parsed protocol: NECext address: BA A0 00 00 command: 01 FE 00 00 -# +# name: POWER -type: raw -frequency: 38000 -duty_cycle: 0.330000 -data: 3469 1719 450 447 423 1293 447 451 419 452 418 454 416 455 425 446 424 447 423 449 421 450 420 451 419 452 418 454 416 1300 450 447 423 449 421 450 420 451 419 453 417 454 416 455 425 1291 449 449 421 1295 445 452 418 454 416 1300 450 1292 448 1295 445 453 417 454 426 445 425 1291 449 449 421 1295 445 1297 453 1289 451 1292 448 450 420 452 418 1298 452 445 425 446 424 448 422 449 420 450 420 452 418 1298 452 74868 3471 1717 453 445 425 1291 449 449 421 451 419 452 418 453 417 455 425 446 424 447 423 448 422 449 421 451 419 452 418 1298 452 445 425 447 423 448 422 449 421 451 419 452 418 454 416 1300 450 447 423 1293 447 451 419 453 417 1299 451 1291 449 1293 447 451 419 453 417 454 426 1290 450 447 423 1293 447 1296 444 1299 451 1291 449 449 421 450 420 1296 444 454 426 445 425 446 424 448 422 449 421 450 420 1296 444 74877 3472 1716 443 455 425 1291 449 448 422 450 420 451 419 453 417 454 426 445 425 446 424 447 423 449 421 450 420 451 419 1298 452 445 425 446 424 448 422 449 421 450 420 452 418 453 417 1299 451 447 423 1293 447 451 419 452 418 1298 452 1290 450 1293 447 451 419 452 418 454 416 1300 450 447 423 1293 447 1296 444 1299 451 1291 449 449 421 450 420 1296 444 454 426 445 425 446 424 447 423 449 421 450 420 1296 444 -# +type: parsed +protocol: Kaseikyo +address: AC 02 20 00 +command: D1 03 00 00 +# name: VOL+ -type: raw -frequency: 38000 -duty_cycle: 0.330000 -data: 3472 1743 416 455 425 1317 422 449 420 451 418 453 416 454 426 445 424 447 422 448 421 450 419 452 417 453 416 455 425 1317 422 449 420 450 419 452 417 454 415 455 425 446 423 448 421 1320 419 452 417 1325 425 447 422 448 421 450 419 452 417 453 416 455 425 446 423 448 421 449 420 451 418 452 417 454 415 456 424 1317 422 449 420 451 418 453 416 455 425 446 423 447 422 449 420 450 419 452 417 1324 426 74911 3469 1746 423 448 421 1321 418 453 416 455 425 446 423 447 422 449 420 450 419 452 417 454 415 455 425 446 423 448 421 1320 419 452 417 454 426 445 424 447 422 448 421 450 419 452 417 1324 426 446 423 1291 448 450 419 452 417 454 415 455 425 446 423 448 421 450 419 451 418 453 416 454 426 446 423 447 422 449 420 1294 445 453 416 455 425 446 423 448 421 449 420 451 418 453 416 454 426 445 424 1290 449 -# +type: parsed +protocol: Kaseikyo +address: A0 02 20 00 +command: 00 02 00 00 +# name: VOL- -type: raw -frequency: 38000 -duty_cycle: 0.330000 -data: 3473 1742 417 454 426 1317 422 448 421 450 419 452 417 453 416 455 425 446 423 447 422 449 420 451 418 452 417 454 415 1326 424 448 421 449 420 451 418 453 416 454 426 445 425 447 422 1320 419 452 417 1324 426 446 423 447 422 449 420 450 419 452 417 454 415 455 425 446 423 1319 420 451 418 453 416 454 426 445 424 1318 421 450 419 452 417 1324 426 446 423 447 422 449 420 451 418 452 417 454 415 1326 424 74913 3467 1748 421 450 419 1323 416 455 425 446 423 447 422 449 420 451 418 452 417 454 415 455 425 446 423 448 421 449 420 1322 417 454 426 445 424 447 422 448 421 450 419 452 417 453 416 1326 424 447 422 1320 419 452 417 454 415 455 425 446 423 448 421 450 419 451 418 453 416 1325 425 447 422 448 421 450 419 452 417 1324 426 446 423 447 422 1320 419 452 417 454 415 455 425 446 423 448 421 450 419 1322 417 -# +type: parsed +protocol: Kaseikyo +address: A0 02 20 00 +command: 10 02 00 00 +# name: MUTE -type: raw -frequency: 38000 -duty_cycle: 0.330000 -data: 3473 1716 453 445 425 1291 448 422 447 424 446 453 416 427 453 446 423 420 449 449 420 423 446 425 444 454 426 418 451 1291 448 423 446 452 417 454 415 428 452 446 423 421 448 422 447 1296 443 455 425 1290 449 449 420 423 446 425 444 427 453 445 424 420 449 449 420 423 446 425 444 1298 452 419 450 448 421 1294 445 1298 452 446 423 448 421 449 420 1296 443 427 453 445 424 1292 447 423 446 452 417 1299 451 74922 3472 1717 452 446 423 1292 447 451 418 452 417 454 426 445 424 447 423 449 420 450 419 452 417 454 415 455 425 446 424 1293 446 451 418 453 416 455 425 446 423 447 422 449 420 451 418 1297 453 445 424 1292 447 450 419 452 417 454 415 455 425 446 423 448 421 450 419 451 418 453 416 1300 450 448 421 449 420 1296 443 1299 451 447 422 449 420 450 419 1297 442 455 425 447 422 1293 446 451 418 453 416 1300 450 -# +type: parsed +protocol: Kaseikyo +address: A0 02 20 00 +command: 20 03 00 00 +# name: POWER type: parsed protocol: NEC address: 01 00 00 00 command: 02 00 00 00 -# +# name: VOL+ type: parsed protocol: NEC address: 01 00 00 00 command: 01 00 00 00 -# +# name: VOL- type: parsed protocol: NEC address: 01 00 00 00 command: 0B 00 00 00 -# +# name: MUTE type: parsed protocol: NEC address: 01 00 00 00 command: 06 00 00 00 -# +# name: POWER type: raw frequency: 38000 duty_cycle: 0.330000 data: 9150 4435 643 1608 643 468 644 469 642 364 749 468 643 447 665 449 663 469 643 452 660 470 642 450 662 442 670 449 662 469 643 1579 672 1608 642 1580 671 1609 641 1607 643 1578 672 1607 643 1608 642 1606 644 1606 644 1606 644 1607 643 1576 675 1579 671 1605 674 438 645 466 673 438 646 466 674 437 673 439 672 439 673 438 646 1604 673 1577 673 1578 673 1577 674 1577 673 23799 9095 4485 616 -# +# name: VOL+ type: parsed protocol: NEC42 address: 01 00 00 00 command: 0C 00 00 00 -# +# name: VOL- type: raw frequency: 38000 duty_cycle: 0.330000 data: 9151 4434 644 1608 643 376 737 379 733 446 666 449 663 468 644 469 643 468 644 468 644 468 644 447 665 448 664 468 644 450 662 1608 643 1607 644 1576 676 1607 644 1608 643 1578 674 1608 643 1577 674 1579 672 1607 643 1608 643 1607 644 1607 644 1608 643 448 664 1608 643 448 664 468 644 469 643 380 732 468 644 469 643 1607 644 468 644 1608 643 1608 644 1609 643 1608 643 23837 9152 4434 642 -# +# name: POWER type: raw frequency: 38000 duty_cycle: 0.330000 data: 8968 4344 670 460 670 460 670 1566 669 462 668 486 643 487 642 489 641 1595 640 490 640 491 640 1596 640 491 640 1596 640 1596 640 1596 640 491 640 1596 640 1596 640 1596 640 1596 640 1596 640 1596 640 1596 640 1622 640 491 640 491 640 491 640 491 640 491 640 491 640 491 640 491 639 -# +# name: POWER type: parsed protocol: SIRC address: 10 00 00 00 command: 2E 00 00 00 -# +# name: POWER type: parsed protocol: NECext address: 00 FD 00 00 command: 01 FE 00 00 -# +# name: MUTE type: parsed protocol: NECext address: 00 FD 00 00 command: 03 FC 00 00 -# +# name: VOL+ type: parsed protocol: NECext address: 00 FD 00 00 command: 09 F6 00 00 -# +# name: VOL- type: parsed protocol: NECext address: 00 FD 00 00 command: 07 F8 00 00 -# +# name: POWER type: raw frequency: 38000 duty_cycle: 0.330000 data: 1042 1461 540 1460 541 1460 541 1460 541 1459 542 1459 542 454 536 460 540 456 544 452 538 458 542 454 546 450 540 456 544 1457 544 1456 545 1448 542 50531 1041 1462 539 1462 539 1461 540 1461 540 1460 541 1460 541 455 545 451 539 457 543 480 510 459 541 481 519 451 539 457 543 1457 543 1457 544 1449 541 50515 1037 1467 544 1456 545 1456 545 1455 546 1455 535 1465 536 486 514 483 517 479 511 485 515 481 509 487 513 483 517 478 512 1462 539 1462 539 1454 536 50537 1035 1467 544 1457 544 1457 544 1456 545 1456 544 1456 545 477 513 483 517 479 511 486 514 481 519 477 513 484 516 479 511 1464 536 1463 538 1455 546 -# +# name: POWER type: raw frequency: 38000 duty_cycle: 0.330000 data: 1010 1491 509 1490 510 1488 512 487 513 487 513 1486 514 1485 515 484 516 1483 517 482 518 482 518 1481 509 1489 511 488 512 487 513 1486 514 484 516 50963 1011 1489 511 1488 512 1487 513 485 515 486 514 1485 515 1484 516 484 516 1483 517 482 518 482 518 1481 509 1489 511 489 511 489 511 1487 513 486 514 50986 1008 1492 518 1480 510 1488 512 487 513 487 513 1486 514 1484 516 484 516 1483 517 482 518 481 519 1480 510 1488 512 487 513 487 513 1486 514 484 516 50972 1012 1488 512 1486 514 1484 516 483 517 483 517 1482 518 1480 510 489 511 1487 513 486 514 486 514 1485 515 1483 517 483 517 483 517 1481 509 490 510 50976 1008 1491 509 1489 511 1487 513 485 515 485 515 1484 516 1481 509 491 509 1489 511 488 512 488 512 1487 513 1485 515 484 516 484 516 1483 517 481 509 -# +# name: POWER type: raw frequency: 38000 duty_cycle: 0.330000 data: 1011 1479 517 477 516 481 512 1480 516 1473 513 482 511 485 518 1473 513 482 511 1481 515 1474 512 482 511 485 518 1473 513 1477 509 486 517 1473 513 50728 1014 1475 511 484 509 487 516 1475 511 1479 517 477 516 480 513 1478 508 487 516 1475 511 1479 517 478 514 480 513 1479 517 1473 513 508 484 1479 517 50725 1016 1473 513 481 512 484 519 1473 513 1477 509 485 518 478 515 1476 510 485 518 1473 513 1477 509 486 517 478 515 1476 510 1480 516 479 514 1476 510 50735 1069 1421 513 481 512 484 509 1483 513 1477 509 486 517 479 514 1477 509 486 517 1474 512 1479 507 488 515 480 513 1479 507 1483 513 482 511 1479 517 50733 1011 1478 508 513 490 506 486 1478 508 1483 513 508 485 511 482 1482 514 508 485 1480 516 1473 513 508 485 511 482 1483 513 1477 509 512 491 1473 513 50735 1008 1480 516 479 514 508 485 1480 516 1474 512 509 484 486 517 1472 514 508 485 1480 516 1474 512 509 484 512 481 1482 514 1477 509 512 491 1472 514 50738 1006 1509 487 508 485 486 507 1509 487 1503 483 513 490 505 488 1502 484 512 491 1473 513 1503 483 512 491 505 488 1476 510 1507 489 506 487 1503 483 -# +# name: MUTE type: raw frequency: 38000 duty_cycle: 0.330000 data: 1010 1479 517 1474 512 509 484 512 491 505 488 507 486 510 483 512 491 505 488 508 485 1505 491 1474 512 1478 508 1483 513 1477 509 1482 514 1475 511 50713 1005 1483 513 1475 511 511 482 513 490 505 488 507 486 483 510 511 482 487 516 505 488 1501 485 1478 508 1483 513 1476 510 1479 507 1483 513 1474 512 50707 1012 1501 485 1479 506 513 490 505 488 507 486 509 484 511 482 487 516 505 488 508 485 1504 482 1482 514 1476 592 1396 590 1400 513 1476 510 1478 508 50715 1015 1473 513 1476 510 484 508 513 490 504 489 480 513 508 485 483 510 511 482 488 515 1473 513 1477 509 1480 516 1474 512 1477 591 1397 516 1472 514 -# +# name: VOL+ type: raw frequency: 38000 duty_cycle: 0.330000 data: 1041 1462 538 1462 538 485 515 481 519 478 512 484 516 1458 542 1458 542 1459 541 481 519 1481 519 1455 545 1482 518 1456 544 479 511 486 514 474 516 50532 1039 1464 536 1490 510 487 513 483 517 480 510 486 514 1460 540 1486 514 1460 540 483 517 1457 543 1484 516 1458 542 1458 542 481 519 477 513 476 513 50534 1036 1467 543 1457 543 480 509 460 540 483 517 479 511 1463 537 1463 537 1464 536 486 514 1487 513 1461 539 1461 539 1462 538 484 516 481 519 469 510 -# +# name: VOL- type: raw frequency: 38000 duty_cycle: 0.330000 data: 1042 1461 539 457 543 1458 542 1458 542 1458 542 1458 542 454 536 461 539 457 543 1457 543 453 537 460 540 456 544 452 538 1463 537 1463 537 1456 544 50530 1065 1438 572 424 566 1434 566 1435 565 1435 565 1436 544 452 537 459 572 424 545 1456 544 451 539 458 542 454 536 460 540 1461 539 1461 539 1454 536 50538 1036 1467 543 452 537 1464 536 1464 536 1464 536 1465 545 450 540 456 544 452 537 1464 536 460 540 455 545 452 538 458 542 1459 541 1460 540 1452 538 -# +# name: VOL+ type: raw frequency: 38000 duty_cycle: 0.330000 data: 1044 1456 544 455 545 455 534 1464 536 1462 538 1460 540 1458 542 1456 544 1455 545 1453 537 1461 539 460 540 459 541 459 561 437 542 457 543 456 544 50915 1016 1483 517 482 518 482 518 1481 509 1489 511 1487 513 1486 514 1485 515 1483 517 1482 508 1490 510 489 511 488 512 487 513 487 513 486 514 485 515 50956 1047 1452 538 462 538 462 538 1461 539 1460 540 1458 542 1457 543 1456 544 1454 546 1453 547 1451 539 461 539 460 540 460 540 459 541 459 541 457 543 -# +# name: VOL- type: raw frequency: 38000 duty_cycle: 0.330000 data: 1017 1484 516 1482 518 481 519 1480 510 1489 511 1487 513 1486 514 1485 515 1483 517 482 518 1480 510 490 510 489 511 489 511 488 512 488 512 486 514 50956 1015 1486 514 1484 516 484 516 1483 517 1482 518 1480 510 1489 511 1488 512 1486 514 486 514 1485 515 484 516 484 516 483 517 483 517 482 518 481 509 50960 1011 1488 512 1486 514 486 514 1485 515 1483 517 1482 518 1480 510 1488 512 1486 514 486 514 1484 516 483 517 483 517 482 518 481 519 481 508 489 511 50961 1040 1461 539 1459 541 459 541 1458 542 1456 544 1455 545 1454 546 1452 538 1460 540 460 540 1458 542 457 543 456 544 456 544 455 545 455 545 453 547 -# +# name: VOL+ type: raw frequency: 38000 duty_cycle: 0.330000 data: 1006 1485 511 1479 517 1473 513 509 484 511 482 514 489 506 487 508 485 511 482 513 490 505 488 1477 509 1481 515 1475 511 1480 516 1474 512 1477 509 50734 1007 1483 513 1477 509 1482 514 507 486 509 484 511 492 503 490 506 487 508 485 510 483 513 490 1474 512 1479 517 1473 513 1477 509 1481 515 1474 512 50729 1012 1477 509 1481 515 1474 512 509 484 512 491 504 489 506 487 508 485 511 482 513 490 506 487 1477 509 1481 515 1475 511 1479 517 1473 513 1476 510 -# +# name: VOL- type: raw frequency: 38000 duty_cycle: 0.330000 data: 1012 1503 483 514 489 1475 511 483 510 486 517 478 515 481 512 483 510 486 517 1473 513 508 485 1480 516 1475 511 1479 507 1483 513 1477 509 1480 588 50646 1012 1476 510 512 491 1473 513 508 485 485 508 488 515 480 513 482 511 512 481 1482 514 482 511 1480 516 1473 513 1478 508 1482 514 1476 510 1479 590 50651 1007 1507 489 507 485 1478 508 514 489 506 487 509 484 485 508 488 515 506 487 1503 483 513 490 1474 512 1478 508 1483 513 1477 509 1481 515 1473 513 50721 1009 1505 491 478 515 1475 511 510 483 486 517 478 515 507 486 483 510 512 491 1472 514 508 485 1505 491 1473 513 1477 509 1481 587 1403 510 1478 508 50733 1008 1506 490 479 514 1477 509 512 481 514 489 506 487 508 485 484 509 513 490 1473 513 509 483 1481 515 1474 512 1479 507 1482 514 1476 510 1478 590 50642 1006 1508 488 508 485 1478 508 487 516 479 514 481 512 510 483 486 517 504 489 1474 512 510 483 1482 514 1475 511 1479 507 1483 513 1477 509 1480 516 -# +# name: POWER type: parsed protocol: NEC address: 20 00 00 00 command: 09 00 00 00 -# +# name: MUTE type: parsed protocol: NEC address: 20 00 00 00 command: 1F 00 00 00 -# +# name: VOL+ type: parsed protocol: NEC address: 20 00 00 00 command: 0E 00 00 00 -# +# name: VOL- type: parsed protocol: NEC address: 20 00 00 00 command: 1A 00 00 00 -# +# name: VOL+ type: parsed protocol: NEC address: 20 00 00 00 command: 02 00 00 00 -# +# name: VOL- type: parsed protocol: NEC address: 20 00 00 00 command: 05 00 00 00 -# +# name: POWER type: parsed protocol: NEC address: 20 00 00 00 command: 0C 00 00 00 -# +# name: MUTE type: parsed protocol: NEC address: 20 00 00 00 command: 08 00 00 00 -# +# name: POWER type: parsed protocol: NEC address: 00 00 00 00 command: 12 00 00 00 -# +# name: MUTE type: parsed protocol: NEC address: 00 00 00 00 command: 1E 00 00 00 -# +# name: VOL+ type: parsed protocol: NEC address: 00 00 00 00 command: 03 00 00 00 -# +# name: VOL- type: parsed protocol: NEC address: 00 00 00 00 command: 01 00 00 00 -# +# name: VOL+ type: parsed protocol: NEC address: 00 00 00 00 command: 1F 00 00 00 -# +# name: VOL- type: parsed protocol: NEC address: 00 00 00 00 command: 09 00 00 00 -# +# name: POWER type: parsed protocol: NECext address: 10 E7 00 00 command: 01 FE 00 00 -# +# name: MUTE type: parsed protocol: NECext address: 10 E7 00 00 command: 00 FF 00 00 -# +# name: MUTE type: parsed protocol: NECext address: 10 E7 00 00 command: 2B D4 00 00 -# +# name: MUTE type: parsed protocol: NECext address: 78 0E 00 00 command: 09 F6 00 00 -# +# name: VOL+ type: parsed protocol: NECext address: 78 0E 00 00 command: 01 FE 00 00 -# +# name: VOL- type: parsed protocol: NECext address: 78 0E 00 00 command: 02 FD 00 00 -# +# name: VOL- type: parsed protocol: NEC address: 00 00 00 00 command: 06 00 00 00 -# +# name: POWER type: parsed protocol: NEC address: 02 00 00 00 command: 0A 00 00 00 -# +# name: MUTE type: parsed protocol: NEC address: 02 00 00 00 command: 0D 00 00 00 -# +# name: VOL+ type: parsed protocol: NEC address: 02 00 00 00 command: 1C 00 00 00 -# +# name: VOL- type: parsed protocol: NEC address: 02 00 00 00 command: 07 00 00 00 -# +# name: VOL+ type: parsed protocol: NEC address: 00 00 00 00 command: 14 00 00 00 -# +# name: VOL- type: parsed protocol: NEC address: 00 00 00 00 command: 08 00 00 00 -# +# name: VOL+ type: parsed protocol: NECext address: 86 FF 00 00 command: 14 EB 00 00 -# +# name: VOL- type: parsed protocol: NECext address: 86 FF 00 00 command: 13 EC 00 00 -# +# name: POWER type: parsed protocol: NECext address: 86 FF 00 00 command: 1B E4 00 00 -# +# name: MUTE type: parsed protocol: NECext address: 86 FF 00 00 command: 2A D5 00 00 -# +# name: POWER type: parsed protocol: NEC address: 00 00 00 00 command: 07 00 00 00 -# +# name: MUTE type: parsed protocol: NEC address: 00 00 00 00 command: 00 00 00 00 -# +# name: MUTE type: parsed protocol: NECext address: 40 AF 00 00 command: 19 E6 00 00 -# +# name: VOL+ type: parsed protocol: NECext address: 02 BD 00 00 command: 26 D9 00 00 -# +# name: VOL- type: parsed protocol: NECext address: 02 BD 00 00 command: 28 D7 00 00 -# +# name: POWER type: parsed protocol: NECext address: 02 BD 00 00 command: 53 AC 00 00 -# +# name: MUTE type: parsed protocol: NECext address: 02 BD 00 00 command: AD 52 00 00 -# +# name: POWER type: parsed protocol: SIRC address: 10 00 00 00 command: 2F 00 00 00 -# +# name: VOL+ type: parsed protocol: SIRC address: 10 00 00 00 command: 12 00 00 00 -# +# name: VOL- type: parsed protocol: SIRC address: 10 00 00 00 command: 13 00 00 00 -# +# name: POWER type: parsed protocol: NECext address: 85 23 00 00 command: 99 66 00 00 -# +# name: MUTE type: parsed protocol: NECext address: 85 23 00 00 command: 97 68 00 00 -# +# name: VOL+ type: parsed protocol: NECext address: 85 23 00 00 command: 57 A8 00 00 -# +# name: VOL- type: parsed protocol: NECext address: 85 23 00 00 command: 47 B8 00 00 -# +# name: POWER type: parsed protocol: NEC address: 08 00 00 00 command: 10 00 00 00 -# +# name: MUTE type: parsed protocol: NEC address: 08 00 00 00 command: 16 00 00 00 -# +# name: VOL+ type: parsed protocol: NECext address: 86 FF 00 00 command: 21 DE 00 00 -# +# name: VOL- type: parsed protocol: NECext address: 86 FF 00 00 command: 2B D4 00 00 -# +# name: VOL+ type: parsed protocol: NECext address: BA 4B 00 00 command: 03 FC 00 00 -# +# name: VOL- type: parsed protocol: NECext address: BA 4B 00 00 command: 02 FD 00 00 -# +# name: VOL+ type: parsed protocol: NECext address: BA A0 00 00 command: 03 FC 00 00 -# +# name: VOL- type: parsed protocol: NECext address: BA A0 00 00 command: 02 FD 00 00 -# +# name: VOL+ type: raw frequency: 38000 duty_cycle: 0.330000 data: 1014 1477 517 478 514 509 483 487 515 480 512 484 508 488 514 1479 515 1476 508 1483 511 1481 513 1478 516 1475 509 1482 512 1479 515 480 512 483 509 50775 1014 1477 517 504 488 508 484 513 489 506 486 510 482 514 488 1478 516 1475 509 1483 511 1480 514 1477 517 1474 510 1482 512 1478 516 505 487 509 483 50770 1009 1481 513 508 484 512 490 506 486 510 482 514 488 508 484 1481 513 1478 516 1475 509 1483 511 1480 514 1477 517 1475 509 1482 512 509 483 513 489 -# +# name: VOL- type: raw frequency: 38000 duty_cycle: 0.330000 data: 1010 1508 486 509 483 513 489 507 485 512 490 505 487 510 482 1509 485 511 491 1501 483 1509 485 1507 487 1504 490 1502 482 1509 485 511 491 1500 484 50779 1010 1506 488 508 484 512 490 505 487 509 483 513 489 506 486 1506 488 507 485 1506 488 1503 481 1510 484 1508 486 1505 489 1503 481 514 488 1503 491 -# +# name: POWER type: parsed protocol: NECext address: BA A0 00 00 command: 4C B3 00 00 -# +# name: MUTE type: parsed protocol: NECext address: BA A0 00 00 command: 01 FD 00 00 -# +# name: POWER type: raw frequency: 38000 duty_cycle: 0.330000 data: 1004 1513 481 515 487 1478 516 505 487 510 482 1484 510 1481 513 508 484 512 490 1475 509 513 489 1477 507 1484 510 511 481 515 487 1479 515 1474 510 50774 1005 1484 510 513 489 1476 508 513 489 508 484 1482 512 1479 515 506 486 511 481 1483 511 512 490 1475 509 1483 511 510 482 515 487 1504 490 1475 509 50777 1013 1503 491 506 486 1505 489 507 485 512 490 1501 483 1508 486 510 482 514 488 1503 481 515 487 1504 490 1500 484 512 490 506 486 1506 488 1502 482 -# +# name: MUTE type: raw frequency: 38000 duty_cycle: 0.330000 data: 1014 1477 507 514 488 508 484 512 490 505 487 509 483 513 489 507 485 1480 514 1477 517 1475 509 1483 511 1480 514 1477 517 1475 509 1482 512 508 484 50774 1004 1486 508 513 489 507 485 511 491 504 488 508 484 513 489 505 487 1479 515 1476 508 1484 510 1481 513 1478 516 1475 509 1482 512 1480 514 507 485 50771 1007 1507 487 509 483 513 489 507 485 511 481 515 487 508 484 513 489 1502 482 1483 511 1481 513 1479 515 1476 508 1484 510 1481 513 1478 516 506 486 -# +# name: POWER type: parsed protocol: NECext address: BA 4B 00 00 command: 4C B3 00 00 -# +# name: MUTE type: parsed protocol: NECext address: BA 4B 00 00 command: 01 FE 00 00 -# +# name: VOL+ type: parsed protocol: NECext address: 83 22 00 00 command: 0A F5 00 00 -# +# name: VOL- type: parsed protocol: NECext address: 83 22 00 00 command: 01 FE 00 00 -# +# name: VOL+ type: parsed protocol: NEC address: 35 00 00 00 command: 45 00 00 00 -# +# name: VOL- type: parsed protocol: NEC address: 35 00 00 00 command: 1B 00 00 00 -# +# name: POWER type: parsed protocol: NEC address: 35 00 00 00 command: 09 00 00 00 -# +# name: MUTE type: parsed protocol: NEC address: 35 00 00 00 command: 51 00 00 00 -# +# name: POWER type: parsed protocol: NECext address: 83 22 00 00 command: 08 F7 00 00 -# +# name: VOL+ type: parsed protocol: NECext address: 0A 1D 00 00 command: 08 F7 00 00 -# +# name: VOL- type: parsed protocol: NECext address: 0A 1D 00 00 command: 0A F5 00 00 -# +# name: MUTE type: parsed protocol: NECext address: 0A 1D 00 00 command: 03 FC 00 00 -# +# name: POWER type: parsed protocol: NECext address: 0A 1D 00 00 command: 01 FE 00 00 -# +# name: VOL+ type: parsed protocol: NEC address: 20 00 00 00 command: 06 00 00 00 -# +# name: VOL- type: parsed protocol: NEC address: 20 00 00 00 command: 07 00 00 00 -# +# name: MUTE type: parsed protocol: NEC address: 20 00 00 00 command: 1E 00 00 00 -# +# name: MUTE type: parsed protocol: NEC address: 80 00 00 00 command: 01 00 00 00 -# +# name: VOL+ type: parsed protocol: NEC address: 80 00 00 00 command: 03 00 00 00 -# +# name: VOL- type: parsed protocol: NEC address: 80 00 00 00 command: 06 00 00 00 -# +# name: VOL+ type: parsed protocol: Samsung32 address: 2C 00 00 00 command: 17 00 00 00 -# +# name: VOL- type: parsed protocol: Samsung32 address: 2C 00 00 00 command: 16 00 00 00 -# +# name: VOL+ type: parsed protocol: NECext address: 83 22 00 00 command: 16 E9 00 00 -# +# name: VOL- type: parsed protocol: NECext address: 83 22 00 00 command: 0F F0 00 00 -# +# name: POWER type: parsed protocol: NECext address: 83 22 00 00 command: 0C F3 00 00 -# +# name: MUTE type: parsed protocol: NECext address: 83 22 00 00 command: 15 EA 00 00 -# -name: VOL+ -type: raw -frequency: 38000 -duty_cycle: 0.330000 -data: 3492 1750 416 454 425 1313 424 446 422 447 421 448 420 450 418 451 417 452 416 453 415 455 424 445 423 446 422 447 421 1290 447 450 418 451 417 452 416 453 415 455 424 445 423 447 421 1290 447 422 446 1319 418 452 416 426 442 454 425 445 423 446 422 447 421 421 447 449 419 450 418 451 417 452 416 453 415 454 425 1314 423 446 422 447 421 448 420 449 419 450 418 451 417 452 416 454 425 444 424 1315 422 74926 3488 1754 422 447 421 1317 420 422 446 451 417 452 416 453 415 454 425 444 424 445 423 446 422 447 421 448 420 449 419 1292 445 452 416 453 415 454 425 445 423 446 422 447 421 448 420 1318 419 450 418 1293 444 453 415 454 425 445 423 446 422 447 421 448 420 449 419 450 418 451 417 452 416 453 415 455 424 445 423 1315 422 448 420 449 419 450 418 424 444 452 416 453 415 454 425 445 423 446 422 1289 448 -# -name: VOL- -type: raw -frequency: 38000 -duty_cycle: 0.330000 -data: 3486 1756 420 449 419 1291 446 424 444 452 416 453 415 454 425 444 424 445 423 446 422 446 422 447 421 448 420 449 419 1319 418 452 416 453 415 426 453 444 424 445 423 446 422 447 421 1290 447 422 446 1319 418 451 417 452 416 454 425 444 424 445 423 446 422 447 421 420 448 1317 420 449 419 450 418 452 416 453 415 1322 425 417 451 445 423 1315 422 447 421 448 420 449 419 450 418 451 417 452 416 1322 415 74922 3492 1722 444 452 416 1321 416 426 453 444 424 445 423 446 422 447 421 447 421 448 420 449 419 450 418 451 417 452 416 1294 443 453 415 454 425 445 423 445 423 446 422 447 421 448 420 1317 420 450 418 1319 418 451 417 425 443 453 415 454 425 444 424 418 450 446 422 447 421 1317 420 449 419 450 418 451 417 452 416 1322 425 444 424 445 423 1315 422 420 448 448 420 448 420 422 446 450 418 451 417 1321 416 -# +# name: POWER -type: raw -frequency: 38000 -duty_cycle: 0.330000 -data: 3491 1751 415 454 425 1314 423 446 422 448 420 449 419 450 418 451 417 452 416 453 415 454 425 445 423 446 422 447 421 1317 420 449 419 451 417 452 416 453 415 454 425 444 424 445 423 1316 421 448 420 1318 419 451 417 452 416 453 415 454 425 445 423 446 422 447 421 448 420 1318 419 451 417 1321 416 1322 425 1313 424 1314 423 419 449 447 421 1290 447 450 418 1320 417 1321 416 1322 425 444 424 445 423 1288 449 74914 3491 1751 415 427 452 1314 423 446 422 447 421 448 420 449 419 450 418 451 417 452 416 453 415 454 425 445 423 446 422 1316 421 449 419 450 418 451 417 452 416 453 415 454 425 445 423 1315 422 448 420 1318 419 451 417 452 416 453 415 454 425 445 423 446 422 447 421 448 420 1318 419 451 417 1321 416 1322 415 1295 452 1286 451 446 422 447 421 1317 420 450 418 1320 417 1321 416 1295 442 454 425 445 423 1315 422 74905 3491 1752 424 445 423 1315 422 447 421 448 420 422 446 451 417 452 416 453 415 454 425 445 423 446 422 447 421 448 420 1318 419 451 417 452 416 453 415 454 425 445 423 446 422 447 421 1317 420 450 418 1293 444 452 416 454 425 444 424 446 422 447 421 448 420 449 419 450 418 1320 417 453 415 1323 424 1314 423 1315 422 1288 449 448 420 450 418 1293 444 453 415 1323 424 1313 424 1314 423 447 421 448 420 1318 419 -# -name: MUTE -type: raw -frequency: 38000 -duty_cycle: 0.330000 -data: 3486 1728 448 448 420 1318 419 423 445 451 417 452 416 454 425 444 424 445 423 446 422 447 421 448 420 421 447 449 419 1319 418 451 417 453 415 453 426 444 424 445 423 446 422 447 421 1317 420 449 419 1319 418 451 417 452 416 453 415 454 425 445 423 446 422 447 421 447 421 421 447 1291 446 423 445 425 443 1322 415 1322 425 444 424 445 423 446 422 1289 448 448 420 422 446 1292 445 451 417 452 416 1322 415 74924 3486 1755 421 447 421 1317 420 449 419 450 418 451 417 452 416 453 415 454 425 417 451 445 423 446 422 420 448 448 420 1317 420 450 418 451 417 452 416 426 442 427 452 444 424 445 423 1315 422 447 421 1317 420 449 419 450 418 451 417 425 443 453 415 454 425 444 424 418 450 446 422 1315 422 448 420 421 447 1291 446 1319 418 451 417 452 416 454 414 1323 424 445 423 419 449 1316 421 422 446 450 418 1293 444 74912 3487 1755 421 448 420 1290 447 423 445 451 417 452 416 453 415 454 425 445 423 446 422 446 422 447 421 421 447 449 419 1319 418 452 416 426 442 454 425 444 424 445 423 446 422 447 421 1290 447 449 419 1319 418 452 416 452 416 453 415 427 451 445 423 446 422 447 421 448 420 449 419 1319 418 424 444 452 416 1322 415 1323 424 444 424 445 423 446 422 1317 420 449 419 423 445 1320 417 453 415 427 452 1313 424 -# +type: parsed +protocol: Kaseikyo +address: A0 02 20 00 +command: D0 03 00 00 +# name: POWER type: parsed protocol: NECext address: C8 91 00 00 command: 00 FF 00 00 -# +# name: MUTE type: parsed protocol: NECext address: C8 91 00 00 command: 20 DF 00 00 -# +# name: VOL+ type: parsed protocol: NECext address: C8 91 00 00 command: 1E E1 00 00 -# +# name: VOL- type: parsed protocol: NECext address: C8 91 00 00 command: 1F E0 00 00 -# +# name: VOL+ type: parsed protocol: RC6 address: 10 00 00 00 command: 10 00 00 00 -# +# name: VOL- type: parsed protocol: RC6 address: 10 00 00 00 command: 11 00 00 00 -# +# name: POWER type: parsed protocol: RC6 address: 10 00 00 00 command: 0C 00 00 00 -# +# name: VOL+ type: raw frequency: 38000 duty_cycle: 0.330000 data: 4559 4461 546 490 515 495 521 490 515 495 489 1484 516 1482 550 486 519 491 493 1480 520 1478 522 1477 523 1475 546 490 515 495 521 490 515 495 489 4493 545 491 525 486 519 491 514 496 488 1484 516 1483 517 1481 551 486 488 1485 515 1483 517 1482 550 486 519 491 525 486 519 491 493 1479 542 494 522 489 516 467 517 1482 550 -# +# name: VOL- type: raw frequency: 38000 duty_cycle: 0.330000 data: 4550 4469 548 462 543 467 549 461 544 466 518 1481 520 1479 542 468 548 462 522 1477 523 1476 514 1485 515 1483 549 461 544 466 550 461 544 466 518 4491 547 463 542 468 548 462 543 467 549 462 543 467 549 461 523 1476 514 1485 515 1484 516 1482 550 461 513 1486 514 1485 515 1483 549 461 544 466 550 461 544 493 491 1481 540 -# +# name: VOL+ type: raw frequency: 38000 duty_cycle: 0.330000 data: 4496 4442 513 503 488 502 489 501 490 500 491 1505 487 1508 484 505 486 504 487 1508 484 1511 492 1503 489 1499 514 484 486 504 487 502 489 501 490 4449 517 499 492 499 492 497 483 507 484 1511 492 1504 488 1499 514 483 487 1509 483 1512 491 1504 488 503 488 501 490 500 491 499 492 1504 488 501 490 500 491 492 509 1494 488 55126 4496 4446 541 482 488 502 489 501 490 500 491 1505 487 1508 484 505 486 504 487 1508 484 1503 510 1493 489 1480 512 504 487 503 488 502 489 500 491 4449 517 498 493 497 483 507 484 505 486 1502 511 1492 490 1504 488 502 489 1507 485 1509 483 1512 491 473 518 498 493 496 484 505 486 1510 483 499 512 484 486 504 487 1508 484 -# +# name: VOL- type: raw frequency: 38000 duty_cycle: 0.330000 data: 4492 4434 510 505 486 505 486 504 487 503 488 1481 511 1484 518 499 492 498 493 1476 516 1479 513 1483 519 1469 596 402 516 500 491 499 492 498 493 4447 518 498 493 497 483 507 484 506 485 504 487 503 488 494 517 1485 486 1483 519 1476 516 1480 512 504 486 1508 484 1486 517 1479 565 425 513 502 488 501 490 492 509 1467 515 -# +# name: VOL+ type: raw frequency: 38000 duty_cycle: 0.330000 data: 4500 4436 516 504 486 510 490 505 485 510 490 1500 491 1474 517 505 485 484 516 1501 490 1501 490 1501 490 1501 490 505 485 511 489 506 484 485 515 4449 513 482 508 513 487 508 482 514 486 1504 487 1504 487 1504 487 482 508 1509 482 1509 492 1499 492 504 486 509 491 504 486 509 491 1500 491 504 486 510 490 478 512 1505 486 55017 4492 4444 508 512 488 508 482 513 487 508 482 1508 483 1482 509 513 487 508 482 1509 482 1509 482 1483 508 1483 508 513 487 508 482 514 486 509 481 4457 515 506 484 511 489 506 484 511 489 1501 490 1475 516 1501 490 506 484 1480 511 1507 484 1480 511 511 489 506 484 512 488 507 483 1507 484 512 488 507 483 512 488 1503 488 -# +# name: VOL- type: raw frequency: 38000 duty_cycle: 0.330000 data: 4493 4443 509 512 488 507 483 512 488 507 483 1482 509 1482 509 512 488 507 483 1482 509 1482 509 1482 509 1482 509 512 488 507 483 513 487 508 482 4457 516 505 485 510 490 505 485 510 490 505 485 511 489 505 485 1480 511 1480 511 1480 511 1481 510 484 516 1476 515 1476 515 1476 515 481 509 486 514 481 509 486 514 1476 515 55014 4498 4438 514 482 508 487 513 482 508 488 512 1477 514 1477 514 482 508 487 513 1477 514 1477 514 1477 514 1477 514 482 518 477 513 482 518 477 513 4451 511 485 515 479 511 485 515 480 510 485 515 480 510 485 515 1475 516 1475 516 1476 515 1476 515 480 510 1481 510 1481 510 1481 510 486 514 481 509 486 514 481 509 1482 509 -# +# name: VOL+ type: raw frequency: 38000 duty_cycle: 0.330000 data: 4524 4473 512 516 491 511 486 516 491 511 496 1482 522 1482 522 506 491 512 495 1483 521 1483 521 1483 521 1483 521 506 491 512 495 507 490 512 495 4475 521 507 490 513 494 508 489 513 494 1484 520 1484 520 1483 521 507 490 1488 516 1488 516 1488 516 511 496 506 491 511 496 506 491 1488 516 511 496 506 491 512 495 1483 521 55356 4533 4463 512 516 491 511 486 516 491 511 496 1507 487 1492 512 515 492 510 487 1492 512 1492 512 1491 513 1491 513 515 492 510 487 515 492 510 487 4484 512 516 491 511 496 506 491 512 495 1483 521 1482 522 1482 522 506 491 1488 516 1487 517 1487 517 511 496 506 491 512 495 506 491 1488 516 512 495 507 490 512 495 1483 521 -# +# name: VOL- type: raw frequency: 38000 duty_cycle: 0.330000 data: 4533 4464 521 507 490 512 495 507 490 513 494 1484 520 1484 520 508 489 513 494 1484 520 1484 520 1483 521 1483 521 506 491 511 496 506 491 512 495 4475 521 507 490 512 495 507 490 513 494 508 489 513 494 508 489 1490 514 1490 514 1490 514 1490 514 514 493 1485 519 1485 519 1485 519 509 488 515 492 510 487 516 491 1487 517 55369 4531 4465 520 508 489 514 493 509 488 515 492 1486 518 1486 518 509 488 514 493 1486 518 1485 519 1485 519 1485 519 509 488 514 493 509 488 515 492 4478 518 511 486 516 491 511 496 506 491 512 495 507 490 512 495 1483 521 1483 521 1483 521 1483 521 507 490 1488 516 1488 516 1488 516 512 495 507 490 513 494 508 489 1490 514 -# +# name: POWER type: raw frequency: 38000 duty_cycle: 0.330000 data: 4530 4465 521 507 490 513 494 507 490 513 494 1509 496 1483 521 506 491 512 495 1508 486 1492 512 1492 513 1491 513 514 493 509 488 514 493 509 488 4483 513 514 493 509 488 515 492 510 487 515 492 510 487 515 492 510 487 1517 488 1491 513 1490 515 513 494 1510 494 1484 520 1483 521 1483 521 506 491 512 495 506 491 1487 517 55357 4528 4468 518 510 487 515 492 510 487 515 492 1512 493 1485 519 509 488 514 493 1510 494 1483 522 1483 521 1482 512 516 491 511 486 516 491 511 486 4484 512 516 491 511 486 516 491 511 486 516 491 511 486 516 491 511 496 1507 487 1491 513 1491 514 514 493 1510 495 1484 521 1483 522 1483 522 506 491 511 486 516 491 1513 491 -# +# name: POWER type: raw frequency: 38000 duty_cycle: 0.330000 data: 4495 4440 512 509 491 504 486 509 491 504 486 1478 513 1479 512 509 491 504 486 1478 513 1479 512 1479 512 1479 512 509 491 504 486 509 491 504 486 4452 511 511 489 506 484 511 489 506 484 511 489 506 484 511 489 506 484 1480 511 1480 511 1480 511 510 491 1500 491 1475 516 1475 516 1475 516 504 486 510 490 505 485 1479 512 55017 4497 4439 513 507 483 513 487 507 483 513 487 1476 515 1477 514 507 483 513 487 1476 515 1476 515 1477 514 1477 514 481 509 512 488 507 483 512 488 4451 512 509 491 504 486 509 491 504 486 483 517 504 486 509 492 504 486 1504 487 1504 487 1478 513 508 482 1509 482 1509 482 1509 482 1483 508 513 487 508 482 513 487 1504 487 -# +# name: MUTE type: raw frequency: 38000 duty_cycle: 0.330000 data: 4501 4435 517 504 486 510 490 505 485 510 490 1475 516 1475 516 506 484 511 489 1476 515 1476 515 1476 515 1477 514 507 483 512 488 507 483 513 487 4451 511 510 490 479 511 484 516 506 484 1481 510 511 489 506 484 511 489 1476 515 1476 515 1477 514 507 483 512 488 1477 514 1477 514 1478 513 508 482 513 487 508 482 1484 517 55011 4496 4440 512 509 491 478 512 483 517 504 486 1480 511 1480 511 484 516 505 485 1480 511 1480 511 1481 510 1481 510 484 516 506 484 511 489 506 484 4455 517 504 486 509 491 504 486 483 517 1474 517 505 485 510 490 505 485 1480 511 1480 511 1481 510 511 489 480 510 1481 510 1481 510 1482 509 485 515 507 483 512 488 1477 514 -# +# name: POWER type: parsed protocol: Samsung32 address: 2C 00 00 00 command: 1E 00 00 00 -# +# name: MUTE type: parsed protocol: Samsung32 address: 2C 00 00 00 command: 1F 00 00 00 -# +# name: POWER type: raw frequency: 38000 duty_cycle: 0.330000 data: 4504 4432 511 509 492 504 486 509 492 504 486 1478 514 1477 515 507 484 512 489 1476 516 1475 517 1475 517 1474 518 503 487 509 492 503 487 508 493 4446 508 513 488 507 483 512 489 507 483 512 489 506 484 511 490 506 484 1481 511 1480 512 1479 513 509 492 1473 519 1473 519 1472 509 1482 510 511 490 506 484 511 490 1475 517 54985 4498 4437 517 504 486 509 492 504 486 509 492 1473 519 1472 509 512 489 506 484 1481 511 1480 512 1480 512 1479 513 508 493 502 488 507 483 512 489 4449 516 506 485 511 490 505 485 510 491 505 485 510 491 504 486 509 492 1473 519 1473 508 1483 561 434 515 1476 516 1475 517 1474 518 1473 519 502 488 507 483 512 489 1476 516 -# +# name: MUTE type: raw frequency: 38000 duty_cycle: 0.330000 data: 4531 4406 516 478 512 484 538 457 544 452 538 1453 518 1473 519 476 546 450 540 1451 509 1482 510 1481 511 1480 512 483 539 457 544 452 538 457 544 4420 513 482 540 456 545 450 540 455 546 1445 547 449 541 454 536 458 543 1449 543 1449 543 1448 544 451 539 456 545 1445 547 1445 547 1444 537 458 543 453 537 457 544 1448 544 54957 4495 4440 514 481 520 477 513 482 519 476 514 1476 516 1475 517 478 512 484 517 1474 518 1473 519 1472 520 1471 521 474 516 479 511 484 517 479 511 4452 512 509 492 503 487 508 493 503 487 1477 515 507 483 512 489 506 484 1481 511 1481 511 1480 512 509 492 503 487 1478 514 1478 514 1477 515 506 484 511 490 505 485 1480 512 -# +# name: POWER type: raw frequency: 38000 duty_cycle: 0.330000 data: 4551 4468 549 461 544 493 523 460 545 466 518 1480 520 1479 542 468 548 489 495 1477 523 1475 515 1484 516 1483 549 461 544 493 523 487 518 466 518 4490 548 462 543 493 523 488 517 466 550 461 544 466 550 460 545 465 519 1480 520 1478 522 1477 544 465 519 1480 520 1479 521 1477 523 1476 545 464 541 496 520 490 494 1479 542 55901 4554 4465 542 494 522 489 516 494 522 488 496 1477 523 1476 545 490 515 495 489 1484 516 1483 517 1481 519 1479 542 494 522 489 516 494 522 488 496 4487 541 495 521 490 515 495 521 489 516 494 522 488 517 493 523 488 496 1476 525 1475 515 1483 549 488 496 1476 524 1475 515 1484 516 1482 550 486 519 491 525 486 488 1485 547 55897 4548 4470 548 462 543 468 548 462 543 467 517 1482 518 1480 541 469 547 490 494 1478 575 1423 515 1485 515 1483 549 461 544 466 550 461 544 466 518 4491 547 462 543 467 549 462 543 467 549 461 544 466 539 497 519 492 492 1480 520 1478 522 1477 544 465 519 1480 520 1479 521 1477 513 1486 546 464 541 469 547 464 520 1478 543 -# +# name: MUTE type: raw frequency: 38000 duty_cycle: 0.330000 data: 4553 4467 550 459 546 464 541 469 547 464 520 1479 521 1477 544 492 524 486 498 1475 515 1484 516 1482 518 1481 540 496 520 490 515 495 521 490 494 4488 550 486 519 491 525 486 519 491 493 1479 542 494 522 489 516 494 490 1482 518 1481 519 1480 541 494 522 489 495 1478 522 1476 514 1485 547 489 516 494 522 489 495 1477 544 -# +# name: POWER type: raw frequency: 38000 duty_cycle: 0.330000 data: 4555 4483 516 516 488 519 495 512 492 515 489 1525 493 1519 489 518 496 511 493 1521 487 1525 493 1520 488 1524 494 513 491 517 487 520 494 514 490 4501 519 513 491 516 488 520 494 513 491 517 487 521 493 514 490 518 486 1527 491 1522 496 1517 491 516 488 1525 493 1520 488 1525 493 1520 488 519 495 512 492 516 488 1525 493 -# +# name: VOL+ type: parsed protocol: RC5 address: 13 00 00 00 command: 0D 00 00 00 -# +# name: VOL- type: parsed protocol: RC5 address: 13 00 00 00 command: 0E 00 00 00 -# +# name: POWER type: parsed protocol: RC5 address: 13 00 00 00 command: 0B 00 00 00 -# +# name: MUTE type: parsed protocol: RC5 address: 13 00 00 00 command: 0C 00 00 00 -# +# name: VOL+ type: parsed protocol: SIRC address: 01 00 00 00 command: 12 00 00 00 -# +# name: VOL- type: parsed protocol: SIRC address: 01 00 00 00 command: 13 00 00 00 -# +# name: VOL+ type: raw frequency: 38000 duty_cycle: 0.330000 data: 4552 4468 574 436 566 444 568 442 570 441 540 1458 546 1453 572 439 573 437 544 1455 539 1460 544 1456 548 1450 575 436 566 444 568 442 570 440 541 4468 594 416 565 445 567 443 569 441 540 1459 545 1453 541 1459 566 444 547 1452 542 1457 547 1452 593 417 564 446 566 444 568 442 539 1460 565 446 566 444 568 442 539 1460 565 55957 4581 4437 543 467 545 466 546 464 538 472 519 1480 514 1485 540 471 541 469 512 1486 518 1481 513 1486 518 1481 575 436 566 444 568 442 570 440 541 4468 543 468 544 465 547 464 538 472 519 1480 514 1485 519 1479 546 465 516 1483 511 1488 516 1483 542 468 544 466 546 464 538 473 519 1480 545 466 546 464 538 472 519 1480 545 -# +# name: VOL- type: raw frequency: 38000 duty_cycle: 0.330000 data: 4546 4473 538 473 539 470 542 469 543 467 514 1484 520 1479 545 465 547 463 518 1481 513 1486 518 1481 513 1487 538 472 540 470 542 469 543 466 515 4495 546 463 539 472 540 470 542 468 544 466 546 491 521 462 519 1480 513 1485 519 1480 514 1486 539 472 519 1479 515 1484 520 1479 546 464 548 463 539 471 541 469 512 1487 548 -# +# name: POWER type: raw frequency: 38000 duty_cycle: 0.330000 data: 4549 4469 542 468 544 467 545 465 537 473 519 1481 513 1485 540 471 541 469 512 1487 517 1482 512 1487 517 1482 543 467 545 465 547 463 539 472 519 4489 543 468 544 466 546 464 538 473 539 470 542 468 544 466 546 465 516 1482 512 1487 517 1482 543 468 513 1485 519 1480 514 1485 519 1480 545 465 547 463 539 472 520 1479 546 55899 4549 4470 541 469 574 436 566 445 546 463 549 1450 513 1486 539 471 572 438 543 1456 548 1451 543 1456 548 1451 574 436 566 445 567 443 569 441 540 4469 573 437 575 435 567 443 569 441 571 439 573 437 565 445 567 443 549 1451 543 1456 548 1451 574 436 545 1454 540 1459 545 1454 540 1459 566 444 568 442 570 440 541 1458 567 55878 4580 4439 572 439 573 437 565 445 567 443 548 1451 543 1456 569 441 571 439 542 1457 547 1452 542 1457 547 1452 573 437 575 435 567 443 569 442 539 4469 573 438 574 436 566 444 568 442 570 440 572 438 574 436 566 444 547 1452 542 1457 547 1452 573 437 544 1455 539 1460 544 1455 539 1460 575 435 567 444 568 442 539 1459 566 55879 4578 4442 569 441 571 439 573 437 575 435 546 1453 541 1458 567 444 568 441 540 1459 545 1454 540 1459 545 1454 571 439 573 437 575 435 567 444 548 4461 571 440 572 438 574 436 566 444 568 442 570 440 572 438 574 436 545 1454 540 1459 545 1454 571 439 542 1457 547 1452 542 1457 547 1452 573 437 575 435 567 444 547 1451 574 55871 4554 4465 546 464 538 473 539 471 541 469 512 1487 517 1481 544 467 545 465 516 1483 511 1488 516 1483 511 1488 547 463 539 472 540 470 542 468 513 4496 546 464 538 472 540 470 542 468 544 466 546 464 538 473 539 471 510 1488 516 1483 511 1488 547 463 518 1481 513 1486 518 1481 513 1486 539 472 540 470 542 467 514 1485 540 -# +# name: MUTE type: raw frequency: 38000 duty_cycle: 0.330000 data: 4555 4465 546 464 538 472 540 470 542 468 513 1486 518 1481 544 467 545 465 516 1483 511 1488 516 1483 511 1488 537 473 539 472 540 470 542 468 513 4496 546 464 538 473 539 471 541 469 512 1487 538 472 540 470 542 469 512 1486 518 1481 544 1455 570 441 571 439 542 1457 547 1452 542 1457 568 442 570 440 572 438 543 1456 569 55920 4555 4464 547 464 538 472 540 470 542 468 513 1486 518 1481 544 466 546 464 517 1482 512 1487 517 1482 512 1487 538 473 539 471 541 469 543 467 514 4495 547 463 539 472 540 470 542 468 513 1486 539 471 541 469 543 467 514 1485 519 1479 515 1485 540 470 542 468 513 1486 518 1481 513 1486 539 471 541 469 543 467 514 1485 540 -# +# name: POWER type: parsed protocol: SIRC15 address: 10 00 00 00 command: 15 00 00 00 -# +# name: POWER type: parsed protocol: SIRC address: 01 00 00 00 command: 15 00 00 00 -# +# name: MUTE type: parsed protocol: SIRC address: 01 00 00 00 command: 14 00 00 00 -# +# name: POWER type: parsed protocol: SIRC address: 10 00 00 00 command: 15 00 00 00 -# +# name: POWER type: parsed protocol: SIRC15 address: 30 00 00 00 command: 15 00 00 00 -# +# name: MUTE type: parsed protocol: SIRC15 address: 30 00 00 00 command: 14 00 00 00 -# +# name: POWER type: parsed protocol: NECext address: 86 FF 00 00 command: 1C E3 00 00 -# +# name: MUTE type: parsed protocol: NECext address: 86 FF 00 00 command: 1D E2 00 00 -# +# name: VOL+ type: parsed protocol: NEC address: 80 00 00 00 command: 0D 00 00 00 -# +# name: VOL- type: parsed protocol: NEC address: 80 00 00 00 command: 08 00 00 00 -# +# name: POWER type: parsed protocol: NEC address: 80 00 00 00 command: 12 00 00 00 -# +# name: MUTE type: parsed protocol: NEC address: 80 00 00 00 command: 1E 00 00 00 -# +# name: POWER type: parsed protocol: NECext address: EF 01 00 00 command: 25 DA 00 00 -# +# name: VOL- type: parsed protocol: NECext address: EF 01 00 00 command: 14 EB 00 00 -# +# name: VOL+ type: parsed protocol: NECext address: EF 01 00 00 command: 13 EC 00 00 -# +# name: MUTE type: parsed protocol: NECext address: EF 01 00 00 command: 28 D7 00 00 -# -name: POWER -type: parsed -protocol: NEC -address: 00 00 00 00 -command: 40 00 00 00 -# -name: VOL+ -type: parsed -protocol: NEC -address: 00 00 00 00 -command: 41 00 00 00 -# -name: VOL- -type: parsed -protocol: NEC -address: 00 00 00 00 -command: 45 00 00 00 -# -name: MUTE -type: parsed -protocol: NEC -address: 00 00 00 00 -command: 48 00 00 00 -# +# name: VOL+ type: raw frequency: 38000 duty_cycle: 0.330000 data: 1048 580 597 1165 596 582 595 1167 594 875 599 578 599 1455 593 585 592 1171 600 577 600 576 601 13191 1042 586 591 1170 601 576 601 1161 600 869 595 582 595 1459 599 578 599 1163 598 580 597 579 598 13195 1048 580 597 1165 596 581 596 1167 594 875 599 578 599 1456 592 585 592 1171 600 577 600 577 600 13192 1052 576 601 1162 599 578 599 1163 598 871 593 584 593 1462 596 581 596 1166 595 582 595 582 595 -# +# name: VOL- type: raw frequency: 38000 duty_cycle: 0.330000 data: 1048 553 624 1138 623 554 623 1139 622 848 626 551 626 1427 621 556 652 1403 655 522 655 814 650 12579 1050 552 656 1106 624 553 624 1138 623 847 627 550 627 1427 621 556 621 1434 624 553 624 845 619 12612 1079 523 623 1139 622 555 622 1139 622 848 626 550 627 1427 621 556 621 1434 624 553 624 845 619 12613 1047 556 621 1141 620 556 621 1141 620 850 624 552 625 1429 619 558 619 1435 623 554 623 846 628 12600 1050 552 625 1137 624 553 624 1137 624 846 618 558 619 1435 623 554 623 1431 627 550 627 842 622 12609 1051 551 626 1136 625 551 626 1136 625 844 620 557 620 1434 624 554 623 1431 627 550 627 843 621 -# +# name: POWER type: raw frequency: 38000 duty_cycle: 0.330000 data: 1073 528 649 1114 647 530 647 1116 645 825 649 527 650 1405 653 1402 625 552 646 1409 649 1113 648 11417 1077 524 653 1110 651 526 651 1112 649 820 654 523 654 1400 648 1407 651 526 651 1404 654 1109 652 11414 1079 523 654 1109 652 524 653 1111 650 819 624 554 654 1401 647 1408 650 529 648 1406 652 1111 650 11416 1077 525 652 1110 651 526 651 1112 649 820 654 523 654 1401 647 1408 650 528 649 1405 622 1141 651 11414 1080 521 646 1116 624 553 645 1117 654 816 648 529 648 1406 652 1403 655 523 644 1410 648 1114 647 11418 1075 526 651 1111 650 527 650 1112 649 820 623 554 654 1400 648 1407 651 526 651 1403 655 1107 654 -# +# name: MUTE type: raw frequency: 38000 duty_cycle: 0.330000 data: 1051 550 627 1135 626 551 626 1136 625 845 619 850 624 553 675 794 629 842 622 555 622 555 622 13780 1047 555 622 1140 621 557 620 1141 620 850 624 845 619 558 619 850 624 846 618 559 618 559 618 13782 1045 558 619 1143 618 559 618 1144 627 842 622 847 627 550 627 842 622 848 626 551 626 551 626 13774 1053 549 618 1144 627 550 627 1135 626 843 621 849 625 551 626 844 620 850 624 553 624 552 625 13776 1051 551 626 1137 624 553 624 1138 623 846 618 851 623 554 623 846 628 841 623 554 623 554 623 13776 1051 551 626 1136 625 552 625 1137 624 845 619 850 624 553 624 846 618 852 622 555 622 554 623 13778 1049 554 623 1139 622 555 622 1140 621 849 625 844 620 557 620 850 624 846 618 559 618 558 619 -# +# name: POWER type: parsed protocol: NEC address: 78 00 00 00 command: CC 00 00 00 -# +# name: MUTE type: parsed protocol: NEC address: 78 00 00 00 command: 9C 00 00 00 -# +# name: POWER type: parsed protocol: NEC address: 7E 00 00 00 command: 2A 00 00 00 -# +# name: MUTE type: parsed protocol: NEC address: 7A 00 00 00 command: 1C 00 00 00 -# +# name: POWER type: raw frequency: 38000 duty_cycle: 0.330000 data: 274 789 254 1792 275 814 250 787 246 816 248 1798 279 784 249 813 251 785 248 788 245 1827 281 1791 275 1825 272 790 253 783 250 43886 277 786 278 1795 272 791 252 783 281 782 251 785 269 1804 273 1800 277 1822 275 1798 279 783 270 766 277 759 274 1825 272 1800 277 43886 277 759 274 1825 272 764 279 756 277 786 278 1795 282 781 272 763 280 755 278 785 279 1794 273 1827 270 1802 275 761 272 791 273 43888 276 761 272 1800 277 786 278 758 275 760 273 790 274 1799 278 1821 276 1796 281 1792 275 788 276 760 273 789 275 1798 279 1794 273 43889 278 785 248 1825 272 790 253 782 272 764 279 1793 274 790 274 761 282 781 273 763 280 1793 273 1825 272 1800 277 813 220 789 275 -# +# name: POWER type: raw frequency: 38000 duty_cycle: 0.330000 data: 270 793 250 1795 272 818 246 791 252 809 244 766 277 1795 282 781 272 790 253 809 224 1822 275 1797 280 1820 277 785 248 788 245 43889 273 790 274 1799 278 785 248 788 276 787 246 1826 271 792 251 1794 273 1827 270 1802 275 788 245 791 273 790 253 1819 278 1794 273 43889 274 789 254 1818 269 767 276 786 247 789 275 788 245 1827 270 792 251 785 248 814 250 1796 281 1819 248 1825 272 790 253 783 271 43889 245 791 273 1799 278 786 278 784 249 787 246 1827 281 781 252 1821 276 1796 281 1792 274 814 250 786 247 789 244 1829 279 1793 274 43888 275 815 218 1828 280 783 250 786 278 785 248 788 245 1827 280 782 251 785 268 794 249 1797 280 1819 278 1794 272 791 252 810 254 -# +# name: VOL+ type: raw frequency: 38000 duty_cycle: 0.330000 data: 277 759 274 1799 278 784 280 783 250 812 242 1804 273 816 227 808 246 791 252 1819 248 1825 273 1826 251 1822 276 786 247 789 244 43888 274 815 249 1797 280 783 250 812 252 784 249 813 241 1805 272 1827 250 1822 275 787 246 816 217 819 255 807 226 1820 278 1795 272 43888 273 789 254 1817 270 793 251 785 248 814 250 1795 282 807 247 790 253 783 250 1822 276 1796 281 1818 249 1824 274 814 229 807 247 -# +# name: VOL- type: raw frequency: 38000 duty_cycle: 0.330000 data: 275 762 271 1800 277 786 278 784 249 813 241 795 248 1824 253 784 270 792 251 1821 246 1826 272 1801 276 1823 275 762 271 790 243 43889 274 789 275 1797 280 783 250 812 252 784 249 1823 275 762 271 1827 250 1822 276 787 246 816 217 818 246 790 253 1819 268 1804 273 43886 277 786 247 1825 273 764 280 783 250 811 253 784 249 1822 276 761 272 816 228 1819 279 1794 273 1826 251 1821 277 786 247 815 249 -# +# name: MUTE type: raw frequency: 38000 duty_cycle: 0.330000 data: 275 762 271 1800 277 786 278 784 249 813 241 795 248 814 219 817 247 789 254 1818 249 1824 274 1798 279 1820 278 759 274 788 245 43887 274 789 275 1798 279 783 250 812 252 784 249 1823 274 1798 279 1820 247 1826 271 765 278 809 224 812 252 784 249 1823 275 1798 279 43880 281 782 251 1821 277 760 273 789 244 818 246 790 253 808 246 791 252 809 224 1822 275 1797 280 1819 248 1825 273 790 253 808 246 -# +# name: POWER -type: raw -frequency: 39105 -duty_cycle: 0.330000 -data: 5396 53113 8899 4450 563 1662 563 1662 563 1662 563 563 563 563 563 563 563 563 563 1662 563 563 563 563 563 1662 563 1662 563 1662 563 1662 563 1662 563 563 563 563 563 563 563 563 563 563 563 563 563 563 563 563 563 1662 563 1662 563 1662 563 1662 563 1662 563 1662 563 1662 563 1662 563 563 563 38358 8899 2225 563 95052 -# +type: parsed +protocol: NECext +address: 87 7C 00 00 +command: 80 7F 00 00 +# name: VOL+ -type: raw -frequency: 39105 -duty_cycle: 0.330000 -data: 5472 53216 8899 4450 563 1662 563 1662 563 1662 563 563 563 563 563 563 563 563 563 1662 563 563 563 563 563 1662 563 1662 563 1662 563 1662 563 1662 563 563 563 563 563 563 563 563 563 1662 563 563 563 563 563 563 563 1662 563 1662 563 1662 563 1662 563 563 563 1662 563 1662 563 1662 563 563 563 38358 8899 2199 563 95052 -# +type: parsed +protocol: NECext +address: 87 7C 00 00 +command: 88 77 00 00 +# name: VOL- -type: raw -frequency: 39105 -duty_cycle: 0.330000 -data: 5472 53344 8899 4424 563 1662 563 1662 563 1662 563 563 563 563 563 563 563 563 563 1662 563 563 563 563 563 1662 563 1662 563 1662 563 1662 563 1662 563 563 563 563 563 563 563 1662 563 1662 563 563 563 563 563 563 563 1662 563 1662 563 1662 563 563 563 563 563 1662 563 1662 563 1662 563 563 563 38358 8899 2225 563 95052 -# +type: parsed +protocol: NECext +address: 87 7C 00 00 +command: 8C 73 00 00 +# name: MUTE -type: raw -frequency: 39105 -duty_cycle: 0.330000 -data: 5498 53523 8899 4450 563 1662 563 1662 563 1662 563 563 563 563 563 563 563 563 563 1662 563 563 563 563 563 1662 563 1662 563 1662 563 1662 563 1662 563 563 563 563 563 563 563 1662 563 563 563 1662 563 563 563 563 563 1662 563 1662 563 1662 563 563 563 1662 563 563 563 1662 563 1662 563 563 563 38358 8899 2199 563 95052 -# +type: parsed +protocol: NECext +address: 87 7C 00 00 +command: 94 6B 00 00 +# name: POWER type: parsed protocol: NECext address: D2 6C 00 00 command: CB 34 00 00 -# +# name: VOL+ type: parsed protocol: NECext address: D2 6D 00 00 command: 02 FD 00 00 -# +# name: VOL- type: parsed protocol: NECext address: D2 6D 00 00 command: 03 FC 00 00 -# +# name: MUTE type: parsed protocol: NECext address: D2 6D 00 00 command: 05 FA 00 00 -# +# name: POWER type: parsed protocol: NECext address: D2 03 00 00 command: 04 FB 00 00 -# +# name: VOL+ type: parsed protocol: NECext address: D2 03 00 00 command: 02 FD 00 00 -# +# name: VOL- type: parsed protocol: NECext address: D2 03 00 00 command: 03 FC 00 00 -# +# name: MUTE type: parsed protocol: NECext address: D2 03 00 00 command: 05 FA 00 00 -# +# name: POWER type: parsed protocol: RC5 address: 14 00 00 00 command: 0C 00 00 00 -# +# name: VOL- type: parsed protocol: RC5 address: 14 00 00 00 command: 11 00 00 00 -# +# name: VOL+ type: parsed protocol: RC5 address: 14 00 00 00 command: 10 00 00 00 -# -name: MUTE -type: parsed -protocol: RC5 -address: 10 00 00 00 -command: 0D 00 00 00 -# -name: VOL+ -type: parsed -protocol: RC5 -address: 10 00 00 00 -command: 10 00 00 00 -# -name: VOL- -type: parsed -protocol: RC5 -address: 10 00 00 00 -command: 11 00 00 00 -# +# name: POWER type: parsed protocol: SIRC15 address: 10 00 00 00 command: 60 00 00 00 -# +# name: VOL+ type: parsed protocol: SIRC15 address: 30 00 00 00 command: 12 00 00 00 -# +# name: VOL- type: parsed protocol: SIRC15 address: 30 00 00 00 command: 13 00 00 00 -# +# name: VOL+ type: parsed protocol: SIRC15 address: 10 00 00 00 command: 12 00 00 00 -# +# name: VOL- type: parsed protocol: SIRC15 address: 10 00 00 00 command: 13 00 00 00 -# +# name: POWER type: parsed protocol: NECext address: 7E 81 00 00 command: 2A D4 00 00 -# +# name: MUTE type: parsed protocol: NECext address: 7A 85 00 00 command: 1C E2 00 00 -# +# name: POWER type: parsed protocol: NEC address: 78 00 00 00 command: 0F 00 00 00 -# +# name: POWER type: parsed protocol: NEC address: 78 00 00 00 command: 4F 00 00 00 -# +# name: VOL+ type: parsed protocol: NEC address: 7A 00 00 00 command: 1A 00 00 00 -# +# name: VOL- type: parsed protocol: NEC address: 7A 00 00 00 command: 1B 00 00 00 -# +# name: VOL+ type: parsed protocol: NECext address: 7A 85 00 00 command: 1A E4 00 00 -# +# name: VOL- type: parsed protocol: NECext address: 7A 85 00 00 command: 1B E5 00 00 -# +# name: VOL+ type: parsed protocol: NEC address: 78 00 00 00 command: 1E 00 00 00 -# +# name: VOL- type: parsed protocol: NEC address: 78 00 00 00 command: 1F 00 00 00 -# +# name: MUTE type: parsed protocol: RC5X address: 0A 00 00 00 command: 2F 00 00 00 -# +# name: VOL- type: parsed protocol: NEC address: 00 00 00 00 command: 15 00 00 00 -# +# name: POWER type: raw frequency: 38000 duty_cycle: 0.330000 data: 8437 4188 538 1565 539 1565 539 513 544 508 538 513 544 1559 545 507 539 1564 540 1564 540 1563 541 1563 541 511 546 1557 547 505 542 511 546 505 542 20497 597 1507 545 1559 545 507 539 512 545 507 539 1564 540 512 545 1558 546 1558 546 1558 546 1557 547 505 542 1562 542 510 547 505 542 510 547 20492 540 1564 540 1564 540 512 545 506 540 511 546 1558 546 505 542 1562 542 1562 542 1562 542 1561 543 509 548 1555 538 514 543 509 537 514 543 20495 547 1558 546 1557 547 505 541 511 546 505 542 1562 542 510 547 1556 548 1556 548 1556 548 1556 537 514 543 1560 544 508 538 514 543 508 538 20501 541 1562 542 1562 542 510 547 505 541 510 547 1556 548 504 543 1561 543 1561 543 1560 544 1560 544 508 538 1565 539 513 544 507 539 513 544 20494 548 1556 548 1556 548 504 543 509 548 504 543 1560 544 508 539 1565 539 1565 539 1564 540 1564 540 512 545 1559 545 506 540 512 545 506 540 20499 543 1560 544 1560 544 508 539 513 544 508 538 1564 540 512 545 1559 545 1558 546 1558 546 1558 546 506 541 1563 541 510 547 505 542 510 547 -# +# name: VOL+ type: raw frequency: 38000 duty_cycle: 0.330000 data: 8430 4194 542 1562 542 1562 542 510 547 505 541 510 547 1556 548 504 542 1561 543 509 548 1556 548 1556 548 1556 548 1556 548 504 542 509 537 514 543 20496 545 1559 545 1559 545 507 539 512 545 507 539 1564 540 512 545 1559 545 507 539 1564 540 1564 540 1563 541 1563 541 511 546 506 540 511 546 20494 546 1557 547 1557 547 505 541 510 547 505 541 1562 542 510 547 1556 548 505 541 1562 542 1562 542 1561 543 1561 543 509 548 504 542 509 537 20501 540 1565 539 1565 539 512 545 507 539 512 545 1559 545 507 539 1564 540 512 545 1559 545 1558 546 1558 546 1558 546 506 540 511 546 506 540 20498 543 1562 542 1562 542 510 547 505 541 510 547 1557 547 505 541 1562 542 509 548 1556 548 1556 548 1556 548 1556 548 504 542 509 548 504 542 20497 543 1560 544 1560 544 508 538 513 544 508 538 1565 539 513 544 1560 544 508 538 1565 539 1565 539 1565 539 1564 540 513 544 507 539 512 545 20495 545 1558 546 1558 546 506 540 511 546 506 540 1563 541 511 546 1558 546 506 540 1563 541 1563 541 1563 541 1562 542 510 547 505 541 510 547 20493 548 1556 548 1556 548 504 542 509 548 504 542 1561 543 509 537 1566 538 514 543 1560 544 1560 544 1560 544 1560 544 508 538 513 544 508 538 20501 539 1564 540 1564 540 512 545 507 539 512 545 1559 545 507 539 1564 540 512 545 1559 545 1558 546 1558 546 1558 546 506 540 511 546 506 540 -# +# name: VOL- type: raw frequency: 38000 duty_cycle: 0.330000 data: 8434 4191 545 1559 545 1559 545 534 512 513 544 507 539 1564 540 538 519 1559 545 1558 546 1558 546 1558 546 1558 546 1558 546 533 513 511 546 506 540 19446 547 1557 547 1557 547 532 514 511 546 532 514 1562 593 459 546 1557 547 1557 547 1557 547 1557 547 1557 547 1557 547 531 515 510 547 505 541 19446 548 1556 548 1556 548 530 516 509 548 504 543 1561 543 535 512 1566 538 1565 539 1565 539 1565 539 1565 539 1565 539 540 517 509 537 514 543 19444 539 1565 539 1565 539 513 544 508 538 513 544 1559 545 534 512 1564 540 1564 540 1564 540 1564 540 1564 540 1564 540 539 518 507 539 513 544 19442 541 1563 541 1563 541 538 519 507 539 512 545 1558 546 506 540 1563 541 1563 541 1563 541 1563 541 1563 541 1562 542 537 520 505 541 511 546 19440 595 1509 543 1561 543 536 521 504 542 509 548 1555 538 540 517 1560 544 1560 544 1560 544 1560 544 1560 544 1560 544 534 512 513 544 508 538 19448 546 1559 545 1559 545 533 513 512 545 507 539 1563 541 538 519 1558 546 1558 546 1558 546 1557 547 1558 546 1558 546 533 513 512 545 506 540 19447 546 1557 547 1557 547 532 514 511 546 506 540 1562 542 537 520 1557 547 1557 547 1557 547 1557 547 1557 547 1557 547 505 542 510 547 505 541 19445 548 1556 548 1556 548 531 515 510 547 504 542 1561 543 536 521 1555 538 1566 538 1566 538 1566 538 1566 538 1565 539 514 543 509 537 514 543 -# +# name: MUTE type: raw frequency: 38000 duty_cycle: 0.330000 data: 8435 4189 547 1557 547 1557 547 505 541 510 547 505 541 1562 542 510 547 1557 547 505 541 510 547 1557 546 1557 547 1557 547 505 541 510 547 505 541 21550 547 1558 545 1558 546 506 540 511 546 506 540 1563 541 511 546 1558 545 506 540 511 546 1558 546 1558 546 1558 546 506 540 511 546 506 540 21551 546 1558 546 1558 546 506 540 512 545 506 540 1563 540 512 545 1558 546 506 540 512 545 1558 546 1558 546 1558 546 506 540 512 545 506 540 21551 546 1559 545 1559 545 507 539 512 545 507 539 1564 539 512 545 1559 545 507 539 512 545 1559 545 1559 545 1559 545 507 539 512 545 507 539 21552 545 1559 545 1559 545 507 539 513 544 507 539 1564 540 512 545 1559 545 507 539 512 545 1559 545 1559 545 1559 545 507 539 512 545 507 539 21552 545 1559 545 1559 545 507 539 513 544 507 539 1565 538 513 544 1559 545 507 539 513 544 1559 545 1559 544 1559 545 534 512 513 544 507 539 21553 544 1560 544 1560 544 534 512 513 544 508 538 1565 539 539 518 1560 544 534 512 513 544 1560 544 1560 544 1560 544 534 512 513 544 508 538 -# +# name: POWER type: parsed protocol: NEC address: 20 00 00 00 command: 41 00 00 00 -# +# name: VOL+ type: parsed protocol: NEC address: 20 00 00 00 command: 42 00 00 00 -# +# name: VOL- type: parsed protocol: NEC address: 20 00 00 00 command: 43 00 00 00 -# +# name: MUTE type: parsed protocol: NEC address: 20 00 00 00 command: 1B 00 00 00 -# +# name: VOL+ type: raw frequency: 38000 duty_cycle: 0.330000 data: 8498 4205 651 1471 576 530 550 1572 547 535 545 536 544 1578 541 540 550 1572 547 535 545 1576 543 539 541 1580 549 1572 547 534 546 1576 543 539 541 540 550 1571 548 533 547 1574 545 537 543 539 541 541 549 532 548 1574 545 536 544 1578 541 540 550 1571 548 1572 547 1574 545 1576 543 26533 8497 4203 653 1468 569 538 542 1579 550 531 549 533 547 1573 546 535 545 1576 543 538 542 1579 550 531 549 1571 548 1573 546 536 544 1576 543 539 541 540 550 1571 548 533 547 1574 545 536 544 538 542 540 550 530 550 1572 547 534 546 1575 544 537 543 1578 541 1579 550 1570 549 1572 547 26524 8496 4207 576 1570 549 533 547 1574 545 537 543 539 541 1580 549 532 548 1573 546 536 544 1577 542 539 551 1570 549 1572 547 534 546 1575 544 538 542 540 550 1571 548 534 546 1575 544 538 542 540 550 531 549 533 547 1575 544 537 543 1579 550 531 549 1571 548 1572 547 1574 545 1576 543 26529 8491 4211 573 1573 546 535 545 1576 543 539 551 530 550 1571 548 533 547 1574 545 536 544 1578 541 540 550 1570 549 1572 547 534 546 1575 544 538 542 539 541 1580 549 532 548 1572 547 535 545 537 543 539 541 540 550 1571 548 533 547 1574 545 537 543 1578 541 1579 550 1571 548 1574 545 26522 8498 4202 571 1574 545 537 543 1578 541 541 549 532 548 1573 546 534 546 1575 544 537 543 1577 542 540 550 1570 549 1571 548 533 547 1574 545 537 543 538 542 1579 550 531 549 1572 547 534 546 536 544 537 543 538 542 1579 550 531 549 1572 547 535 545 1575 544 1577 542 1579 550 1571 548 26522 8498 4203 570 1575 544 537 543 1578 541 541 549 532 548 1573 546 535 545 1575 544 538 542 1579 550 531 549 1571 548 1572 547 535 545 1575 544 538 542 539 541 1580 549 532 548 1572 547 534 546 536 544 537 543 539 541 1579 550 531 549 1571 548 533 547 1573 546 1574 545 1575 544 1577 542 -# +# name: VOL- type: raw frequency: 38000 duty_cycle: 0.330000 data: 8490 4211 573 1573 546 535 545 1576 543 539 541 540 550 1571 548 532 548 1573 546 535 545 1576 543 539 541 1579 550 1571 548 533 547 1574 545 536 544 1576 543 1578 541 540 550 1570 549 533 547 534 546 536 544 537 543 539 541 540 550 1570 549 532 548 1572 547 1573 546 1574 545 1576 543 26528 8492 4208 648 1475 572 534 546 1575 544 537 543 539 541 1580 549 532 548 1573 546 535 545 1576 543 538 542 1579 550 1571 548 533 547 1575 544 537 543 1577 542 1579 550 532 548 1573 546 535 545 537 543 539 541 541 549 532 548 533 547 1575 544 537 543 1578 541 1579 550 1571 548 1573 546 26523 8496 4203 622 1499 569 537 543 1578 541 541 549 532 548 1572 547 534 546 1574 545 537 543 1578 541 540 550 1570 549 1571 548 534 546 1575 544 538 542 1578 541 1580 549 532 548 1573 546 536 544 538 542 540 550 532 548 533 547 535 545 1576 543 539 541 1579 550 1571 548 1573 546 1574 545 26521 8498 4201 572 1573 546 536 544 1577 542 540 550 531 549 1571 548 533 547 1573 546 536 544 1576 543 539 541 1579 550 1570 549 532 548 1573 546 535 545 1576 543 1578 541 540 550 1571 548 533 547 535 545 537 543 538 542 540 550 531 549 1572 547 534 546 1575 544 1576 543 1577 542 1579 550 26522 8498 4203 570 1575 544 538 542 1579 550 532 548 533 547 1575 544 537 543 1578 541 540 550 1570 549 533 547 1573 546 1575 544 537 543 1578 541 540 550 1571 548 1573 546 536 544 1578 551 531 549 533 547 535 545 537 543 539 541 540 550 1571 548 533 547 1575 544 1576 543 1578 541 1580 549 26521 8498 4203 570 1576 543 538 542 1580 549 532 548 533 547 1574 545 536 544 1577 542 540 550 1570 549 533 547 1573 546 1575 544 538 542 1579 550 531 549 1571 548 1573 546 536 544 1576 543 539 551 531 549 532 548 534 546 536 544 538 542 1579 550 531 549 1572 547 1573 546 1574 545 1576 543 -# +# name: POWER type: raw frequency: 38000 duty_cycle: 0.330000 data: 8500 4203 653 1468 569 538 542 1579 550 532 548 534 546 1575 544 536 544 1578 541 540 550 1572 547 534 546 1575 544 1577 542 539 541 1580 550 532 548 534 546 535 545 1576 543 1577 542 1579 551 532 548 534 546 536 544 1577 542 1578 552 531 549 533 547 534 546 1574 545 1575 544 1577 542 26533 8492 4211 573 1573 546 535 545 1576 543 539 551 530 550 1571 548 533 547 1574 545 536 544 1577 542 540 550 1570 549 1572 547 534 546 1576 543 539 541 541 549 532 548 1573 546 1574 545 1576 543 539 551 531 549 533 547 1573 546 1576 543 539 541 541 549 532 548 1573 546 1574 545 1576 543 26532 8493 4209 575 1571 548 533 547 1575 544 537 543 539 541 1580 550 531 549 1572 547 534 546 1576 543 538 542 1579 551 1570 549 532 548 1574 545 537 543 538 542 540 550 1570 549 1572 547 1575 544 537 543 539 541 540 550 1571 548 1573 546 536 544 538 542 539 551 1570 549 1572 547 1574 545 26530 8496 4207 567 1579 551 531 549 1572 547 535 545 536 544 1576 543 538 542 1579 551 530 550 1571 548 534 546 1574 545 1576 543 538 542 1579 551 532 548 533 547 534 546 1576 543 1577 542 1579 551 532 548 534 546 535 545 1576 543 1578 541 540 550 532 548 533 547 1574 545 1575 544 1577 542 26531 8495 4210 574 1571 548 534 546 1575 544 538 542 539 551 1569 550 531 549 1572 547 535 545 1576 543 539 541 1579 550 1571 548 534 546 1575 544 538 542 540 550 531 549 1572 547 1549 570 1551 568 539 551 531 549 532 548 1573 546 1550 569 538 542 540 550 531 549 1571 548 1548 571 1550 569 -# +# name: POWER type: parsed protocol: NECext address: 00 EF 00 00 command: 1C E3 00 00 -# +# name: VOL+ type: parsed protocol: NECext address: 00 EF 00 00 command: 00 FF 00 00 -# +# name: VOL- type: parsed protocol: NECext address: 00 EF 00 00 command: 04 FB 00 00 -# +# name: POWER type: parsed protocol: NEC42 address: 6E 00 00 00 command: 00 00 00 00 -# +# name: VOL+ type: parsed protocol: NEC42 address: 6E 00 00 00 command: 4D 00 00 00 -# +# name: VOL- type: parsed protocol: NEC42 address: 6E 00 00 00 command: 4E 00 00 00 -# +# name: POWER type: parsed protocol: NEC42 address: 6E 00 00 00 command: 0E 00 00 00 -# +# name: POWER type: raw frequency: 38000 duty_cycle: 0.330000 data: 8441 4184 542 1562 541 1562 542 511 546 506 540 511 546 1557 546 506 540 1563 541 1563 540 1563 541 512 545 507 539 512 545 507 539 512 545 507 539 22605 538 1565 539 1565 538 514 543 509 537 514 543 1560 543 509 548 1555 548 1556 548 1556 547 504 542 510 547 505 541 510 547 505 541 510 547 22597 546 1559 544 1559 545 507 539 513 544 507 539 1564 539 513 544 1559 544 1559 545 545 508 549 513 508 538 513 544 508 538 513 544 22601 542 1562 542 1561 543 510 547 505 541 510 547 1557 547 505 541 1562 542 1562 542 1562 542 510 547 505 541 510 547 505 541 511 546 505 541 22603 540 1564 539 1565 538 513 544 508 538 513 544 1560 544 508 538 1565 538 1565 538 1566 537 514 543 509 548 504 542 509 548 504 542 509 548 22597 546 1558 546 1558 546 506 540 512 545 507 539 1564 540 512 545 1559 545 1559 544 1559 544 507 539 513 544 508 538 513 544 508 538 513 544 22600 543 1561 542 1562 542 510 547 505 541 510 547 1557 547 505 541 1562 541 1563 540 1563 541 511 546 506 540 511 546 506 540 511 546 506 540 22604 539 1565 538 1566 537 514 543 509 548 504 542 1561 543 509 548 1556 548 1556 548 1556 547 504 542 510 547 505 541 510 547 505 541 510 547 22598 545 1559 544 1559 545 507 539 512 545 507 539 1564 540 512 545 1559 544 1559 545 1559 545 508 538 513 544 508 538 513 544 508 538 513 544 22601 542 1562 542 1562 542 511 546 505 541 511 546 1557 546 506 540 1563 541 1563 540 1563 541 511 546 506 540 511 546 506 540 512 545 506 540 22604 539 1565 538 1566 537 514 543 509 548 504 542 1561 543 509 548 1556 547 1556 547 1556 548 504 542 510 547 505 541 510 547 505 541 510 547 -# +# name: POWER type: parsed protocol: SIRC address: 10 00 00 00 command: 60 00 00 00 -# +# name: VOL- type: parsed protocol: NEC address: 08 00 00 00 command: 0E 00 00 00 -# +# name: VOL+ type: parsed protocol: NEC address: 08 00 00 00 command: 1A 00 00 00 -# +# name: VOL+ type: parsed protocol: NEC address: 00 00 00 00 command: 57 00 00 00 -# -name: VOL+ -type: parsed -protocol: NECext -address: 10 E7 00 00 -command: 06 F9 00 00 -# -name: VOL- -type: parsed -protocol: NECext -address: 10 E7 00 00 -command: 47 B8 00 00 -# -name: MUTE -type: parsed -protocol: NECext -address: 10 E7 00 00 -command: 41 BE 00 00 -# +# name: VOL+ type: parsed protocol: NEC address: 4D 00 00 00 command: 04 00 00 00 -# +# name: VOL- type: parsed protocol: NEC address: 4D 00 00 00 command: 05 00 00 00 -# +# name: VOL+ type: parsed protocol: NEC address: 4D 00 00 00 command: 02 00 00 00 -# +# name: VOL- type: parsed protocol: NEC address: 4D 00 00 00 command: 03 00 00 00 -# +# name: POWER type: parsed protocol: NEC address: 4D 00 00 00 command: 00 00 00 00 -# +# name: VOL+ type: parsed protocol: NEC address: 00 00 00 00 command: 19 00 00 00 -# +# name: VOL- type: parsed protocol: NEC address: 00 00 00 00 command: 16 00 00 00 -# +# name: MUTE type: parsed protocol: NEC address: 00 00 00 00 command: 44 00 00 00 -# +# name: VOL+ type: parsed protocol: NECext address: 12 36 00 00 command: 0A F5 00 00 -# +# name: VOL- type: parsed protocol: NECext address: 12 36 00 00 command: 0B F4 00 00 -# +# name: MUTE type: parsed protocol: NECext address: 12 36 00 00 command: 09 F6 00 00 -# +# name: POWER type: parsed protocol: NECext @@ -2099,4 +1888,117 @@ type: parsed protocol: RC5 address: 10 00 00 00 command: 0F 00 00 00 -# +# +name: POWER +type: parsed +protocol: NEC +address: 00 00 00 00 +command: 02 00 00 00 +# +name: VOL+ +type: parsed +protocol: NEC +address: 00 00 00 00 +command: 0A 00 00 00 +# +name: VOL- +type: parsed +protocol: NEC +address: 00 00 00 00 +command: 0E 00 00 00 +# +name: POWER +type: parsed +protocol: SIRC +address: 0F 00 00 00 +command: 15 00 00 00 +# +name: Power +type: parsed +protocol: Samsung32 +address: 10 00 00 00 +command: 1E 00 00 00 +# +name: VOL+ +type: parsed +protocol: Samsung32 +address: 10 00 00 00 +command: 17 00 00 00 +# +name: VOL- +type: parsed +protocol: Samsung32 +address: 10 00 00 00 +command: 16 00 00 00 +# +name: MUTE +type: parsed +protocol: Samsung32 +address: 10 00 00 00 +command: 1F 00 00 00 +# +name: POWER +type: parsed +protocol: Kaseikyo +address: 51 54 32 01 +command: 03 00 00 00 +# +name: VOL+ +type: parsed +protocol: Kaseikyo +address: 51 54 32 01 +command: 04 00 00 00 +# +name: VOL- +type: parsed +protocol: Kaseikyo +address: 51 54 32 01 +command: 05 00 00 00 +# +name: MUTE +type: parsed +protocol: Kaseikyo +address: 51 54 32 01 +command: 06 00 00 00 +# +name: POWER +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 4567 4454 549 481 522 481 523 480 498 506 498 1509 499 1509 523 480 499 505 523 1484 523 1484 523 1485 521 1487 520 484 519 485 519 485 519 471 519 4488 518 485 519 485 518 485 519 485 518 485 519 485 519 485 519 485 519 1489 519 1489 518 1489 518 485 519 1489 518 1490 518 1490 517 1490 518 486 518 486 518 486 518 1490 518 +# +name: VOL+ +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 4571 4453 552 478 525 478 526 478 500 504 500 1507 501 1506 526 478 525 477 526 1481 526 1481 526 1482 524 1483 523 481 522 482 521 481 522 468 522 4484 521 482 521 482 521 482 522 481 522 1486 521 1486 521 1486 521 482 521 1486 522 1486 522 1486 522 482 522 482 522 482 522 482 522 1486 522 483 521 482 521 483 521 1487 521 55474 4547 4477 524 479 524 480 524 480 523 480 523 1485 523 1484 524 481 523 481 523 1485 523 1485 522 1485 523 1485 523 480 524 480 524 481 523 467 524 4484 523 481 523 481 523 481 523 481 523 1485 523 1485 523 1485 523 481 523 1485 523 1485 523 1485 523 481 523 481 523 481 523 481 523 1485 523 481 523 481 523 481 523 1486 522 +# +name: VOL- +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 4572 4453 552 456 548 479 524 479 500 504 500 1482 526 1482 551 478 526 478 525 1483 524 1484 523 1486 521 1487 521 483 521 483 521 483 521 470 520 4487 521 483 521 483 521 483 521 483 521 483 521 483 521 483 521 1488 520 1488 520 1488 520 1488 520 483 521 1488 520 1488 520 1488 520 483 521 483 521 483 521 483 521 1488 520 55457 4565 4483 521 483 521 483 521 483 521 483 520 1488 520 1487 521 483 521 483 520 1488 520 1488 520 1488 520 1488 520 483 520 484 520 484 520 470 521 4487 520 484 520 483 520 484 520 484 520 484 520 484 519 484 520 1488 520 1488 520 1488 519 1488 520 484 520 1488 520 1488 520 1488 520 484 520 484 520 484 520 484 520 1489 519 +# +name: MUTE +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 4573 4451 552 477 527 478 526 477 526 478 501 1507 501 1506 502 502 527 477 526 1481 527 1481 527 1481 526 1482 525 479 524 480 523 481 523 468 523 4485 522 481 522 482 522 482 522 482 522 1486 522 482 521 482 522 482 522 1486 522 1486 522 1486 522 482 522 482 521 1487 521 1487 521 1487 521 482 521 483 521 483 521 1487 521 55462 4547 4474 524 478 525 479 524 480 523 480 523 1484 523 1484 523 480 523 480 523 1484 523 1484 524 1484 523 1485 522 480 523 480 524 480 523 467 523 4484 522 480 524 481 523 481 523 481 523 1485 523 481 522 481 523 481 523 1485 522 1485 523 1485 523 481 523 481 522 1485 522 1485 522 1485 523 481 522 481 522 481 523 1485 523 +# +name: VOL- +type: parsed +protocol: NECext +address: 10 E7 00 00 +command: 49 B6 00 00 +# +name: VOL+ +type: parsed +protocol: NECext +address: 10 E7 00 00 +command: 05 FA 00 00 +# +name: MUTE +type: parsed +protocol: NEC +address: 20 00 00 00 +command: 50 00 00 00 diff --git a/assets/resources/infrared/assets/fans.ir b/assets/resources/infrared/assets/fans.ir index 8b3310fb6..b2c683cba 100644 --- a/assets/resources/infrared/assets/fans.ir +++ b/assets/resources/infrared/assets/fans.ir @@ -1,7 +1,7 @@ Filetype: IR library file Version: 1 -# Last Updated 21th Dec, 2022 -# Last Checked 26th Dec, 2022 +# Last Updated 13th Jan, 2023 +# Last Checked 13th Jan, 2023 # name: POWER type: raw @@ -1203,4 +1203,87 @@ type: raw frequency: 38000 duty_cycle: 0.330000 data: 1366 388 1295 387 446 1164 1368 387 1296 387 448 1164 518 1164 493 1189 517 1165 492 1189 493 1189 493 7851 1365 387 1270 388 446 1190 1365 387 1295 387 447 1192 490 1193 489 1193 489 1194 488 1194 488 1193 489 7855 1337 386 1296 386 448 1193 1338 386 1296 386 448 1193 489 1193 489 1193 489 1193 489 1193 489 1193 489 7855 1337 386 1297 386 448 1194 1337 386 1296 386 448 1194 488 1194 488 1194 488 1194 488 1194 488 1194 488 8160 1336 387 1296 387 447 1194 1337 387 1296 386 448 1194 488 1194 488 1194 488 1194 488 1194 488 1194 488 7855 1336 386 1297 387 447 1195 1336 386 1297 386 448 1195 486 1195 487 1195 487 1195 487 1196 486 1196 486 7881 1310 387 1272 397 436 1245 1286 397 1285 397 436 1246 436 1246 436 1247 435 1247 435 1248 434 1248 434 7934 1259 424 1259 424 408 1274 1258 424 1259 424 408 1274 408 1274 408 1274 408 1274 408 1274 408 1274 408 8239 1258 425 1258 424 408 1274 1258 424 1258 425 407 1273 408 1273 409 1273 408 1273 408 1274 408 1273 408 7907 1283 424 1258 424 409 1248 1283 399 1283 400 433 1247 434 1247 434 1247 434 1247 434 1247 434 1247 434 7905 1282 424 1258 425 407 1273 1257 425 1257 425 407 1273 407 1274 407 1274 407 1274 407 1275 406 1275 406 7958 1230 478 1204 478 353 1328 1204 478 1204 453 378 1327 353 1328 353 1302 379 1301 380 1301 380 1300 381 +# +name: POWER +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 1341 337 1339 338 496 1178 1395 305 1316 337 1339 338 496 1178 526 1151 526 1151 1366 335 1341 335 498 7888 1338 338 1337 339 495 1182 1336 340 1336 340 1336 340 494 1182 494 1182 494 1183 1336 340 1336 340 494 7892 1336 340 1336 340 494 1183 1336 340 1336 340 1336 340 494 1183 494 1183 494 1183 1335 341 1335 340 494 7893 1335 341 1335 341 493 1183 1336 341 1335 341 1335 341 493 1183 493 1183 494 1183 1335 341 1335 341 493 7893 1335 341 1335 341 493 1184 1334 341 1335 341 1335 341 493 1184 493 1184 493 1184 1335 341 1335 342 492 7894 1334 342 1334 342 492 1184 1334 342 1334 341 1335 342 492 1184 493 1184 492 1185 1334 342 1334 342 492 7894 1334 342 1334 342 492 1185 1333 343 1333 342 1334 342 492 1185 492 1185 492 1185 1333 343 1333 343 491 7895 1333 343 1333 343 491 1185 1333 343 1333 344 1332 344 490 1186 490 1186 491 1186 1333 344 1332 344 490 7897 1331 368 1308 368 466 1211 1308 368 1308 368 1308 368 466 1211 465 1211 466 1211 1307 368 1308 369 465 7921 1307 368 1308 368 466 1211 1308 368 1308 369 1307 368 466 1211 466 1211 465 1211 1308 369 1307 369 465 7921 1307 369 1307 369 465 1212 1307 369 1307 369 1307 369 465 1212 465 1212 465 1212 1307 369 1307 369 465 7922 1306 370 1306 370 464 1212 1307 370 1306 370 1306 370 464 1212 464 1213 464 1212 1306 370 1306 370 464 7922 1306 370 1306 371 463 1213 1306 370 1306 371 1305 371 463 1213 439 1238 439 1238 1305 371 1305 371 462 7924 1280 396 1280 396 438 1238 1281 396 1280 396 1280 396 438 1239 437 1239 438 1239 1280 396 1280 397 437 7949 1279 397 1279 397 437 1240 1279 398 1278 422 1254 422 412 1265 411 1265 412 1265 1254 422 1254 422 412 7974 1254 422 1254 422 412 1265 1254 423 1253 423 1253 449 384 1293 383 1293 383 1294 1225 451 1225 452 382 8056 1171 505 1171 532 188 1463 1169 # +name: MODE +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 1349 364 1321 363 490 1219 1324 364 1294 389 463 1245 1324 363 462 1219 491 1221 462 1223 461 1226 484 8019 1292 393 1292 420 433 1252 1292 393 1292 420 433 1252 1292 393 460 1252 433 1252 460 1226 459 1252 433 8021 1317 393 1292 394 459 1226 1318 393 1292 394 458 1226 1318 394 432 1253 459 1226 459 1253 432 1253 459 +# +name: TEMP+ +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 1355 364 1348 363 462 1189 1355 363 1322 389 436 1245 492 1192 1351 389 436 1221 490 1197 487 1249 434 8019 1319 393 1292 393 459 1252 1292 393 1292 393 459 1252 432 1252 1292 393 459 1252 433 1252 433 1252 460 8020 1291 393 1292 420 432 1252 1292 393 1292 420 432 1253 459 1226 1291 420 432 1253 459 1226 459 1252 432 +# +name: TEMP- +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 1354 363 1322 363 489 1219 1325 364 1295 389 463 1245 464 1219 466 1219 1324 416 435 1223 461 1249 461 8019 1292 393 1318 393 432 1252 1292 393 1318 393 433 1252 460 1225 460 1252 1292 393 460 1225 459 1252 433 8020 1318 393 1292 393 459 1253 1291 393 1291 394 459 1253 431 1253 432 1253 1291 420 432 1253 432 1253 458 +# +name: TIMER +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 1376 337 1348 363 462 1219 1325 390 1295 388 1322 363 490 1218 466 1219 465 1220 490 1222 1319 369 1316 7187 1292 393 1292 393 460 1252 1292 370 1315 393 1292 420 433 1252 433 1252 460 1252 433 1252 1292 393 1292 7188 1291 393 1318 393 433 1252 1292 393 1319 393 1291 393 460 1226 459 1252 432 1253 459 1225 1319 393 1292 +# +name: POWER +type: parsed +protocol: NECext +address: 00 F3 00 00 +command: 91 6E 00 00 +# +name: TIMER +type: parsed +protocol: NECext +address: 00 F3 00 00 +command: 96 69 00 00 +# +name: POWER +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9253 4427 684 486 656 486 656 486 682 461 681 1573 680 1575 678 464 677 491 651 1604 650 1604 650 1604 650 1604 650 491 651 491 651 1604 650 1604 651 491 651 491 651 1604 650 1604 650 491 651 491 651 491 652 1604 650 1604 651 1604 650 491 651 491 652 1604 650 1604 650 1604 651 491 651 39948 9250 2183 651 +# +name: SPEED+ +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9226 4450 657 484 657 484 658 484 657 485 657 1596 658 1597 681 487 653 488 653 1602 652 1602 652 1602 652 1602 652 490 652 490 652 1602 652 1602 652 490 652 490 652 490 652 1603 652 490 652 490 652 490 652 1602 652 1602 652 1602 653 1602 652 490 652 1602 652 1602 652 1602 653 489 653 39949 9250 2179 653 +# OSC +name: ROTATE +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9231 4449 657 484 658 483 659 483 659 483 659 1595 659 1595 659 485 681 461 680 1601 652 1602 653 1601 653 1601 653 488 654 488 654 1602 653 1601 653 488 654 488 654 1602 653 1602 652 1602 652 488 654 488 654 1602 653 1601 653 1602 652 488 654 488 654 488 654 1602 652 1602 653 488 654 39978 9229 2174 654 96468 9259 2146 679 +# +name: TIMER +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9384 4452 658 485 657 484 658 484 659 485 657 1597 658 1597 682 487 655 488 654 1603 652 1603 653 1603 653 1604 653 491 653 491 653 1603 653 1603 653 1603 653 491 653 1604 652 490 654 1603 652 490 653 490 653 1603 652 490 653 1603 652 490 653 1603 652 490 653 1603 652 1603 652 490 653 39953 9263 2181 652 +# +name: POWER +type: parsed +protocol: NEC +address: 01 00 00 00 +command: 83 00 00 00 +# +name: SPEED+ +type: parsed +protocol: NEC +address: 01 00 00 00 +command: 87 00 00 00 +# +name: TIMER +type: parsed +protocol: NEC +address: 01 00 00 00 +command: 8B 00 00 00 diff --git a/assets/resources/infrared/assets/projectors.ir b/assets/resources/infrared/assets/projectors.ir index f30ee402a..db90997a7 100644 --- a/assets/resources/infrared/assets/projectors.ir +++ b/assets/resources/infrared/assets/projectors.ir @@ -1,7 +1,7 @@ Filetype: IR library file Version: 1 -# Last Updated 26th Dec, 2022 -# Last Checked 26th Dec, 2022 +# Last Updated 13th Jan, 2023 +# Last Checked 13th Jan, 2023 # # ON name: POWER @@ -10,7 +10,7 @@ frequency: 38000 duty_cycle: 0.330000 data: 310 27591 171 27662 241 27731 307 27575 107 27749 306 27551 130 55520 243 27614 217 55584 129 27743 119 27756 115 27747 163 27712 308 27502 243 27650 217 27732 175 27693 167 27698 166 27689 171 27622 215 27712 133 27658 216 27716 129 27732 162 27698 305 27571 131 27753 310 27570 170 27707 162 27707 175 10960 9194 4518 618 542 618 543 725 434 672 1623 671 1647 646 514 592 568 592 568 592 1702 592 568 592 567 593 1702 592 568 618 1676 618 1676 618 1676 618 543 617 543 617 543 617 1677 617 544 616 544 616 544 616 544 616 1678 616 1678 616 1678 616 544 616 1678 616 1679 615 1678 616 1678 616 40239 9196 2250 617 # -name: VOL + +name: VOL+ type: parsed protocol: NEC address: 08 00 00 00 @@ -592,7 +592,7 @@ type: raw frequency: 38000 duty_cycle: 0.330000 data: 3523 1701 472 426 444 1269 472 426 444 426 442 429 443 427 443 426 444 426 444 426 443 427 442 429 440 430 439 432 438 1304 437 433 437 432 438 432 438 433 437 433 437 433 437 433 437 433 437 433 437 1304 437 433 437 433 437 433 437 1304 437 433 437 433 437 1304 437 433 437 434 436 433 437 434 436 434 436 434 436 433 437 433 437 434 436 1304 437 1305 436 1305 436 1305 436 1305 436 1305 436 434 436 434 436 1305 436 1305 436 1305 436 434 436 1305 436 1305 436 1306 435 1306 435 74393 3515 1736 437 433 437 1304 437 433 437 433 437 433 437 433 437 433 437 433 437 433 437 434 436 433 437 434 436 434 436 1304 437 434 436 434 436 434 436 434 436 434 436 434 436 434 436 434 436 434 436 1305 436 434 436 434 436 434 436 1305 436 434 436 434 436 1306 435 435 435 435 435 435 435 435 435 435 435 435 435 435 435 436 434 435 435 1307 434 1331 410 1307 434 1307 434 1330 411 1307 434 460 410 460 410 1331 410 1331 410 1331 410 460 410 1331 410 1331 410 1331 410 1331 410 74393 3515 1736 437 433 437 1304 437 433 437 433 437 433 437 433 437 433 437 433 437 433 437 434 436 434 436 433 437 433 437 1304 437 434 436 434 436 434 437 434 436 434 436 434 436 434 436 434 436 434 436 1305 436 434 436 434 436 434 436 1305 436 435 435 434 436 1305 436 434 436 435 435 435 435 435 435 435 435 435 435 435 435 435 435 435 435 1307 434 1306 435 1307 434 1307 434 1307 434 1331 410 460 410 460 410 1331 410 1331 410 1331 410 460 410 1331 410 1331 410 1331 410 1331 410 74393 3515 1736 437 433 437 1304 437 433 437 433 437 433 437 433 437 433 437 433 437 433 437 433 437 433 437 434 436 433 437 1304 437 433 437 434 436 434 436 434 436 434 436 434 436 434 436 434 436 434 437 1305 436 434 436 434 436 434 436 1305 436 434 436 434 436 1306 435 435 435 435 435 435 435 435 435 435 435 435 435 435 435 435 435 435 435 1307 434 1330 411 1330 411 1330 411 1330 411 1330 411 460 410 460 410 1331 410 1331 410 1331 410 460 410 1331 410 1331 410 1331 410 1331 410 -# Standby/Off +# OFF name: POWER type: raw frequency: 38000 @@ -641,3 +641,140 @@ protocol: NEC address: 02 00 00 00 command: 18 00 00 00 # +name: POWER +type: parsed +protocol: NECext +address: B8 57 00 00 +command: 0C F3 00 00 +# +name: MUTE +type: parsed +protocol: NECext +address: B8 57 00 00 +command: 0D F2 00 00 +# +name: VOL- +type: parsed +protocol: NECext +address: B8 57 00 00 +command: 1E E1 00 00 +# +name: VOL+ +type: parsed +protocol: NECext +address: B8 57 00 00 +command: 1F E0 00 00 +# +name: POWER +type: parsed +protocol: NEC +address: 32 00 00 00 +command: 81 00 00 00 +# +name: VOL- +type: parsed +protocol: NEC +address: 32 00 00 00 +command: 8F 00 00 00 +# +name: VOL+ +type: parsed +protocol: NEC +address: 32 00 00 00 +command: 8C 00 00 00 +# +name: MUTE +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9066 4428 608 507 609 1622 609 507 609 507 609 1623 608 1623 609 507 609 506 610 1623 609 507 609 1622 610 1623 608 507 609 506 610 1622 609 1623 609 506 610 1622 610 506 610 1623 637 478 690 425 638 478 637 1594 637 1594 664 451 636 1594 610 506 610 1621 611 1621 610 1621 610 505 611 40183 9065 2156 637 95953 9037 2185 608 +# +name: POWER +type: parsed +protocol: NEC +address: 00 00 00 00 +command: A8 00 00 00 +# +name: MUTE +type: parsed +protocol: NEC +address: 00 00 00 00 +command: 88 00 00 00 +# +name: VOL- +type: parsed +protocol: NEC +address: 00 00 00 00 +command: 9C 00 00 00 +# +name: VOL+ +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 diff --git a/assets/resources/infrared/assets/tv.ir b/assets/resources/infrared/assets/tv.ir index a4df4d4c4..6126a6239 100644 --- a/assets/resources/infrared/assets/tv.ir +++ b/assets/resources/infrared/assets/tv.ir @@ -1,7 +1,115 @@ Filetype: IR library file Version: 1 -# Last Updated 20th Dec, 2022 -# Last Checked 26th Dec, 2022 +# Last Updated 13th Jan, 2023 +# Last Checked 13th Jan, 2023 +# +name: POWER +type: parsed +protocol: SIRC +address: 01 00 00 00 +command: 15 00 00 00 +# +name: VOL+ +type: parsed +protocol: SIRC +address: 01 00 00 00 +command: 12 00 00 00 +# +name: VOL- +type: parsed +protocol: SIRC +address: 01 00 00 00 +command: 13 00 00 00 +# +name: CH+ +type: parsed +protocol: SIRC +address: 01 00 00 00 +command: 10 00 00 00 +# +name: CH- +type: parsed +protocol: SIRC +address: 01 00 00 00 +command: 11 00 00 00 +# +name: MUTE +type: parsed +protocol: SIRC +address: 01 00 00 00 +command: 14 00 00 00 +# +name: POWER +type: parsed +protocol: NEC +address: 40 00 00 00 +command: 0B 00 00 00 +# +name: CH+ +type: parsed +protocol: NEC +address: 40 00 00 00 +command: 11 00 00 00 +# +name: CH- +type: parsed +protocol: NEC +address: 40 00 00 00 +command: 10 00 00 00 +# +name: VOL+ +type: parsed +protocol: NEC +address: 40 00 00 00 +command: 13 00 00 00 +# +name: VOL- +type: parsed +protocol: NEC +address: 40 00 00 00 +command: 12 00 00 00 +# +name: MUTE +type: parsed +protocol: NEC +address: 40 00 00 00 +command: 14 00 00 00 +# +name: POWER +type: parsed +protocol: Kaseikyo +address: 80 02 20 00 +command: D0 03 00 00 +# +name: VOL+ +type: parsed +protocol: Kaseikyo +address: 80 02 20 00 +command: 00 02 00 00 +# +name: VOL- +type: parsed +protocol: Kaseikyo +address: 80 02 20 00 +command: 10 02 00 00 +# +name: MUTE +type: parsed +protocol: Kaseikyo +address: 80 02 20 00 +command: 20 03 00 00 +# +name: CH+ +type: parsed +protocol: Kaseikyo +address: 80 02 20 00 +command: 40 03 00 00 +# +name: CH- +type: parsed +protocol: Kaseikyo +address: 80 02 20 00 +command: 50 03 00 00 # name: POWER type: parsed @@ -51,42 +159,6 @@ protocol: NECext address: 00 7F 00 00 command: 18 E7 00 00 # -name: POWER -type: parsed -protocol: Kaseikyo -address: 80 02 20 00 -command: D0 03 00 00 -# -name: MUTE -type: parsed -protocol: Kaseikyo -address: 80 02 20 00 -command: 20 03 00 00 -# -name: VOL+ -type: parsed -protocol: Kaseikyo -address: 80 02 20 00 -command: 00 02 00 00 -# -name: VOL- -type: parsed -protocol: Kaseikyo -address: 80 02 20 00 -command: 10 02 00 00 -# -name: CH+ -type: parsed -protocol: Kaseikyo -address: 80 02 20 00 -command: 40 03 00 00 -# -name: CH- -type: parsed -protocol: Kaseikyo -address: 80 02 20 00 -command: 50 03 00 00 -# name: MUTE type: parsed protocol: NECext @@ -283,12 +355,6 @@ command: E9 16 00 00 name: POWER type: parsed protocol: SIRC -address: 01 00 00 00 -command: 15 00 00 00 -# -name: POWER -type: parsed -protocol: SIRC address: 10 00 00 00 command: 15 00 00 00 # @@ -420,12 +486,6 @@ command: 17 00 00 00 # name: POWER type: parsed -protocol: NEC -address: 40 00 00 00 -command: 12 00 00 00 -# -name: POWER -type: parsed protocol: NECext address: 31 49 00 00 command: 63 00 00 00 @@ -1083,61 +1143,19 @@ type: parsed protocol: RC6 address: 00 00 00 00 command: 0D 00 00 00 -# +# Samsung Standby name: POWER type: parsed protocol: Samsung32 address: 07 00 00 00 command: E0 00 00 00 -# -name: VOL- -type: parsed -protocol: Samsung32 -address: 07 00 00 00 -command: 23 00 00 00 -# -name: CH- -type: parsed -protocol: Samsung32 -address: 07 00 00 00 -command: 13 00 00 00 -# +# Samsung Power Off name: POWER type: parsed protocol: Samsung32 address: 07 00 00 00 command: 98 00 00 00 # -name: VOL+ -type: parsed -protocol: SIRC -address: 01 00 00 00 -command: 12 00 00 00 -# -name: VOL- -type: parsed -protocol: SIRC -address: 01 00 00 00 -command: 13 00 00 00 -# -name: CH+ -type: parsed -protocol: SIRC -address: 01 00 00 00 -command: 10 00 00 00 -# -name: CH- -type: parsed -protocol: SIRC -address: 01 00 00 00 -command: 11 00 00 00 -# -name: MUTE -type: parsed -protocol: SIRC -address: 01 00 00 00 -command: 14 00 00 00 -# name: POWER type: parsed protocol: SIRC @@ -1192,12 +1210,6 @@ protocol: NEC address: 40 00 00 00 command: 1E 00 00 00 # -name: MUTE -type: parsed -protocol: NEC -address: 40 00 00 00 -command: 10 00 00 00 -# name: CH+ type: parsed protocol: NEC @@ -1773,4 +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 diff --git a/firmware/targets/f7/furi_hal/furi_hal_nfc.c b/firmware/targets/f7/furi_hal/furi_hal_nfc.c index 0923378db..5e851254d 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_nfc.c +++ b/firmware/targets/f7/furi_hal/furi_hal_nfc.c @@ -205,10 +205,7 @@ bool furi_hal_nfc_activate_nfca(uint32_t timeout, uint32_t* cuid) { return true; } -bool furi_hal_nfc_listen( - FuriHalNfcDevData* nfc_data, - bool activate_after_sak, - uint32_t timeout) { +bool furi_hal_nfc_listen(FuriHalNfcDevData* nfc_data, bool activate_after_sak, uint32_t timeout) { rfalNfcState state = rfalNfcGetState(); if(state == RFAL_NFC_STATE_NOTINIT) { rfalNfcInitialize(); @@ -229,10 +226,9 @@ bool furi_hal_nfc_listen( .notifyCb = NULL, .activate_after_sak = activate_after_sak, }; - if (nfc_data->interface == FuriHalNfcInterfaceIsoDep) { + if(nfc_data->interface == FuriHalNfcInterfaceIsoDep) { params.compMode = RFAL_COMPLIANCE_MODE_ISO; - } - else if (FURI_BIT(nfc_data->sak, 5)) { + } else if(FURI_BIT(nfc_data->sak, 5)) { params.compMode = RFAL_COMPLIANCE_MODE_EMV; } else { params.compMode = RFAL_COMPLIANCE_MODE_NFC; diff --git a/firmware/targets/furi_hal_include/furi_hal_nfc.h b/firmware/targets/furi_hal_include/furi_hal_nfc.h index 79207ea71..06cd46ba4 100644 --- a/firmware/targets/furi_hal_include/furi_hal_nfc.h +++ b/firmware/targets/furi_hal_include/furi_hal_nfc.h @@ -163,10 +163,7 @@ bool furi_hal_nfc_activate_nfca(uint32_t timeout, uint32_t* cuid); * * @return true on success */ -bool furi_hal_nfc_listen( - FuriHalNfcDevData* nfc_data, - bool activate_after_sak, - uint32_t timeout); +bool furi_hal_nfc_listen(FuriHalNfcDevData* nfc_data, bool activate_after_sak, uint32_t timeout); /** Start Target Listen mode * @note RFAL free implementation diff --git a/lib/nfc/nfc_worker.c b/lib/nfc/nfc_worker.c index de7e99cf2..a67c64c3c 100644 --- a/lib/nfc/nfc_worker.c +++ b/lib/nfc/nfc_worker.c @@ -776,7 +776,7 @@ void nfc_worker_emulate_uid(NfcWorker* nfc_worker) { // Need to save ATS to support ISO-14443A-4 emulation while(nfc_worker->state == NfcWorkerStateUidEmulate) { - if (furi_hal_nfc_listen(data, false, 100)) { + if(furi_hal_nfc_listen(data, false, 100)) { if(furi_hal_nfc_tx_rx(&tx_rx, 100)) { reader_data->size = tx_rx.rx_bits / 8; if(reader_data->size > 0) { @@ -834,7 +834,7 @@ void nfc_worker_emulate_apdu(NfcWorker* nfc_worker) { } while(nfc_worker->state == NfcWorkerStateEmulateApdu) { //-V1044 - if (furi_hal_nfc_listen(¶ms, false, 300)) { + if(furi_hal_nfc_listen(¶ms, false, 300)) { FURI_LOG_D(TAG, "POS terminal detected"); if(emv_card_emulation(&tx_rx)) { FURI_LOG_D(TAG, "EMV card emulated"); diff --git a/lib/subghz/protocols/protocol_items.c b/lib/subghz/protocols/protocol_items.c index 5d708c468..5f733d6bd 100644 --- a/lib/subghz/protocols/protocol_items.c +++ b/lib/subghz/protocols/protocol_items.c @@ -1,18 +1,18 @@ #include "protocol_items.h" const SubGhzProtocol* subghz_protocol_registry_items[] = { - &subghz_protocol_gate_tx, &subghz_protocol_keeloq, &subghz_protocol_star_line, - &subghz_protocol_nice_flo, &subghz_protocol_came, &subghz_protocol_faac_slh, - &subghz_protocol_nice_flor_s, &subghz_protocol_came_twee, &subghz_protocol_came_atomo, - &subghz_protocol_nero_sketch, &subghz_protocol_ido, &subghz_protocol_kia, - &subghz_protocol_hormann, &subghz_protocol_nero_radio, &subghz_protocol_somfy_telis, - &subghz_protocol_somfy_keytis, &subghz_protocol_scher_khan, &subghz_protocol_princeton, - &subghz_protocol_raw, &subghz_protocol_linear, &subghz_protocol_secplus_v2, - &subghz_protocol_secplus_v1, &subghz_protocol_megacode, &subghz_protocol_holtek, - &subghz_protocol_chamb_code, &subghz_protocol_power_smart, &subghz_protocol_marantec, - &subghz_protocol_bett, &subghz_protocol_doitrand, &subghz_protocol_phoenix_v2, - &subghz_protocol_honeywell_wdb, &subghz_protocol_magellan, &subghz_protocol_intertechno_v3, - &subghz_protocol_clemsa, &subghz_protocol_ansonic, &subghz_protocol_pocsag, + &subghz_protocol_gate_tx, &subghz_protocol_keeloq, &subghz_protocol_star_line, + &subghz_protocol_nice_flo, &subghz_protocol_came, &subghz_protocol_faac_slh, + &subghz_protocol_nice_flor_s, &subghz_protocol_came_twee, &subghz_protocol_came_atomo, + &subghz_protocol_nero_sketch, &subghz_protocol_ido, &subghz_protocol_kia, + &subghz_protocol_hormann, &subghz_protocol_nero_radio, &subghz_protocol_somfy_telis, + &subghz_protocol_somfy_keytis, &subghz_protocol_scher_khan, &subghz_protocol_princeton, + &subghz_protocol_raw, &subghz_protocol_linear, &subghz_protocol_secplus_v2, + &subghz_protocol_secplus_v1, &subghz_protocol_megacode, &subghz_protocol_holtek, + &subghz_protocol_chamb_code, &subghz_protocol_power_smart, &subghz_protocol_marantec, + &subghz_protocol_bett, &subghz_protocol_doitrand, &subghz_protocol_phoenix_v2, + &subghz_protocol_honeywell_wdb, &subghz_protocol_magellan, &subghz_protocol_intertechno_v3, + &subghz_protocol_clemsa, &subghz_protocol_ansonic, &subghz_protocol_pocsag, &subghz_protocol_smc5326, &subghz_protocol_holtek_th12x, }; From 49dabee42fd48c9dc29eca822768c405fb9e9a66 Mon Sep 17 00:00:00 2001 From: VerstreuteSeele Date: Sat, 14 Jan 2023 09:00:41 +0100 Subject: [PATCH 22/60] Revert NFC u2f --- applications/main/nfc/nfc_cli.c | 2 +- applications/main/u2f/scenes/u2f_scene_main.c | 2 - applications/main/u2f/u2f.c | 107 ++++------ applications/main/u2f/u2f.h | 10 +- applications/main/u2f/u2f_app_i.h | 2 - applications/main/u2f/u2f_hid.c | 7 +- applications/main/u2f/u2f_nfc.c | 182 ------------------ applications/main/u2f/u2f_nfc.h | 17 -- firmware/targets/f7/api_symbols.csv | 4 +- firmware/targets/f7/furi_hal/furi_hal_nfc.c | 22 ++- .../targets/furi_hal_include/furi_hal_nfc.h | 9 +- lib/nfc/nfc_worker.c | 4 +- scripts/flipper/assets/icon.py | 5 +- 13 files changed, 65 insertions(+), 308 deletions(-) delete mode 100644 applications/main/u2f/u2f_nfc.c delete mode 100644 applications/main/u2f/u2f_nfc.h diff --git a/applications/main/nfc/nfc_cli.c b/applications/main/nfc/nfc_cli.c index b2b85f6d3..a6475ca68 100644 --- a/applications/main/nfc/nfc_cli.c +++ b/applications/main/nfc/nfc_cli.c @@ -67,7 +67,7 @@ static void nfc_cli_emulate(Cli* cli, FuriString* args) { }; while(!cli_cmd_interrupt_received(cli)) { - if(furi_hal_nfc_listen(¶ms, false, 100)) { + if(furi_hal_nfc_listen(params.uid, params.uid_len, params.atqa, params.sak, false, 100)) { printf("Reader detected\r\n"); furi_hal_nfc_sleep(); } diff --git a/applications/main/u2f/scenes/u2f_scene_main.c b/applications/main/u2f/scenes/u2f_scene_main.c index abf78c841..af7f1159b 100644 --- a/applications/main/u2f/scenes/u2f_scene_main.c +++ b/applications/main/u2f/scenes/u2f_scene_main.c @@ -101,7 +101,6 @@ void u2f_scene_main_on_enter(void* context) { if(app->u2f_ready == true) { u2f_set_event_callback(app->u2f_instance, u2f_scene_main_event_callback, app); app->u2f_hid = u2f_hid_start(app->u2f_instance); - app->u2f_nfc = u2f_nfc_start(app->u2f_instance); u2f_view_set_ok_callback(app->u2f_view, u2f_scene_main_ok_callback, app); } else { u2f_free(app->u2f_instance); @@ -118,7 +117,6 @@ void u2f_scene_main_on_exit(void* context) { furi_timer_free(app->timer); if(app->u2f_ready == true) { u2f_hid_stop(app->u2f_hid); - u2f_nfc_stop(app->u2f_nfc); u2f_free(app->u2f_instance); } } diff --git a/applications/main/u2f/u2f.c b/applications/main/u2f/u2f.c index ff90329c5..767733ce6 100644 --- a/applications/main/u2f/u2f.c +++ b/applications/main/u2f/u2f.c @@ -16,7 +16,6 @@ #define U2F_CMD_REGISTER 0x01 #define U2F_CMD_AUTHENTICATE 0x02 #define U2F_CMD_VERSION 0x03 -#define U2F_CMD_APPLET_SELECTION 0xA4 typedef enum { U2fCheckOnly = 0x07, // "check-only" - only check key handle, don't send auth response @@ -38,6 +37,11 @@ typedef struct { } __attribute__((packed)) U2fKeyHandle; typedef struct { + uint8_t cla; + uint8_t ins; + uint8_t p1; + uint8_t p2; + uint8_t len[3]; uint8_t challenge[32]; uint8_t app_id[32]; } __attribute__((packed)) U2fRegisterReq; @@ -50,6 +54,11 @@ typedef struct { } __attribute__((packed)) U2fRegisterResp; typedef struct { + uint8_t cla; + uint8_t ins; + uint8_t p1; + uint8_t p2; + uint8_t len[3]; uint8_t challenge[32]; uint8_t app_id[32]; U2fKeyHandle key_handle; @@ -63,14 +72,10 @@ typedef struct { static const uint8_t ver_str[] = {"U2F_V2"}; -// NFC applet selection fields -static const uint8_t rid_ac_ax[] = {0xA0, 0x00, 0x00, 0x06, 0x47, 0x2F, 0x00, 0x01}; - static const uint8_t state_no_error[] = {0x90, 0x00}; static const uint8_t state_not_supported[] = {0x6D, 0x00}; static const uint8_t state_user_missing[] = {0x69, 0x85}; static const uint8_t state_wrong_data[] = {0x6A, 0x80}; -static const uint8_t state_app_not_found[] = {0x6A, 0x82}; struct U2fData { uint8_t device_key[32]; @@ -83,16 +88,6 @@ struct U2fData { void* context; }; -static void* apdu_command_data(U2fApduCommand* cmd) { - // Short encoding is a single byte. - // Extended length encoding is 0 byte followed by MSB and LSB bytes. - if(cmd->len[0] == 0) { - return cmd->len + 3; - } else { - return cmd->len + 1; - } -} - static int u2f_uecc_random(uint8_t* dest, unsigned size) { furi_hal_random_fill_buf(dest, size); return 1; @@ -183,10 +178,9 @@ static uint8_t u2f_der_encode_signature(uint8_t* der, uint8_t* sig) { return len; } -static uint16_t u2f_register(U2fData* U2F, const uint8_t* in_buf, uint8_t* out_buf) { - U2fApduCommand* cmd = (U2fApduCommand*)in_buf; - U2fRegisterReq* req = apdu_command_data(cmd); - U2fRegisterResp* resp = (U2fRegisterResp*)out_buf; +static uint16_t u2f_register(U2fData* U2F, uint8_t* buf) { + U2fRegisterReq* req = (U2fRegisterReq*)buf; + U2fRegisterResp* resp = (U2fRegisterResp*)buf; U2fKeyHandle handle; uint8_t private[32]; U2fPubKey pub_key; @@ -196,13 +190,13 @@ static uint16_t u2f_register(U2fData* U2F, const uint8_t* in_buf, uint8_t* out_b if(u2f_data_check(false) == false) { U2F->ready = false; if(U2F->callback != NULL) U2F->callback(U2fNotifyError, U2F->context); - memcpy(&out_buf[0], state_not_supported, 2); + memcpy(&buf[0], state_not_supported, 2); return 2; } if(U2F->callback != NULL) U2F->callback(U2fNotifyRegister, U2F->context); if(U2F->user_present == false) { - memcpy(&out_buf[0], state_user_missing, 2); + memcpy(&buf[0], state_user_missing, 2); return 2; } U2F->user_present = false; @@ -253,10 +247,9 @@ static uint16_t u2f_register(U2fData* U2F, const uint8_t* in_buf, uint8_t* out_b return (sizeof(U2fRegisterResp) + cert_len + signature_len + 2); } -static uint16_t u2f_authenticate(U2fData* U2F, const uint8_t* in_buf, uint8_t* out_buf) { - U2fApduCommand* cmd = (U2fApduCommand*)in_buf; - U2fAuthReq* req = apdu_command_data(cmd); - U2fAuthResp* resp = (U2fAuthResp*)out_buf; +static uint16_t u2f_authenticate(U2fData* U2F, uint8_t* buf) { + U2fAuthReq* req = (U2fAuthReq*)buf; + U2fAuthResp* resp = (U2fAuthResp*)buf; uint8_t priv_key[32]; uint8_t mac_control[32]; hmac_sha256_context hmac_ctx; @@ -269,7 +262,7 @@ static uint16_t u2f_authenticate(U2fData* U2F, const uint8_t* in_buf, uint8_t* o if(u2f_data_check(false) == false) { U2F->ready = false; if(U2F->callback != NULL) U2F->callback(U2fNotifyError, U2F->context); - memcpy(&out_buf[0], state_not_supported, 2); + memcpy(&buf[0], state_not_supported, 2); return 2; } @@ -277,8 +270,8 @@ static uint16_t u2f_authenticate(U2fData* U2F, const uint8_t* in_buf, uint8_t* o if(U2F->user_present == true) { flags |= 1; } else { - if(cmd->p1 == U2fEnforce) { - memcpy(&out_buf[0], state_user_missing, 2); + if(req->p1 == U2fEnforce) { + memcpy(&buf[0], state_user_missing, 2); return 2; } } @@ -309,12 +302,12 @@ static uint16_t u2f_authenticate(U2fData* U2F, const uint8_t* in_buf, uint8_t* o if(memcmp(req->key_handle.hash, mac_control, 32) != 0) { FURI_LOG_W(TAG, "Wrong handle!"); - memcpy(&out_buf[0], state_wrong_data, 2); + memcpy(&buf[0], state_wrong_data, 2); return 2; } - if(cmd->p1 == U2fCheckOnly) { // Check-only: don't need to send full response - memcpy(&out_buf[0], state_user_missing, 2); + if(req->p1 == U2fCheckOnly) { // Check-only: don't need to send full response + memcpy(&buf[0], state_user_missing, 2); return 2; } @@ -334,50 +327,22 @@ static uint16_t u2f_authenticate(U2fData* U2F, const uint8_t* in_buf, uint8_t* o return (sizeof(U2fAuthResp) + signature_len + 2); } -uint16_t u2f_applet_selection(const uint8_t* in_buf, uint8_t* out_buf) { - U2fApduCommand* cmd = (U2fApduCommand*)in_buf; - uint8_t* data = apdu_command_data(cmd); - - FURI_LOG_D( - TAG, - "len=%d %02x%02x%02x%02x%02x%02x%02x%02x", - cmd->len[0], - data[0], - data[1], - data[2], - data[3], - data[4], - data[5], - data[6], - data[7]); - - if(cmd->len[0] != 8 || memcmp(rid_ac_ax, data, 8) != 0) { - memcpy(&out_buf[0], state_app_not_found, 2); - return 2; - } - - memcpy(&out_buf[0], ver_str, 6); - memcpy(&out_buf[6], state_no_error, 2); - return 8; -} - -uint16_t u2f_msg_parse(U2fData* U2F, const uint8_t* in_buf, uint16_t in_len, uint8_t* out_buf) { +uint16_t u2f_msg_parse(U2fData* U2F, uint8_t* buf, uint16_t len) { furi_assert(U2F); if(!U2F->ready) return 0; - if((in_buf[0] != 0x00) && (in_len < 5)) return 0; - FURI_LOG_D(TAG, "ins=0x%02x", in_buf[1]); - if(in_buf[1] == U2F_CMD_REGISTER) { // Register request - return u2f_register(U2F, in_buf, out_buf); - } else if(in_buf[1] == U2F_CMD_AUTHENTICATE) { // Authenticate request - return u2f_authenticate(U2F, in_buf, out_buf); - } else if(in_buf[1] == U2F_CMD_VERSION) { // Get U2F version string - memcpy(&out_buf[0], ver_str, 6); - memcpy(&out_buf[6], state_no_error, 2); + if((buf[0] != 0x00) && (len < 5)) return 0; + if(buf[1] == U2F_CMD_REGISTER) { // Register request + return u2f_register(U2F, buf); + + } else if(buf[1] == U2F_CMD_AUTHENTICATE) { // Authenticate request + return u2f_authenticate(U2F, buf); + + } else if(buf[1] == U2F_CMD_VERSION) { // Get U2F version string + memcpy(&buf[0], ver_str, 6); + memcpy(&buf[6], state_no_error, 2); return 8; - } else if(in_buf[1] == U2F_CMD_APPLET_SELECTION) { - return u2f_applet_selection(in_buf, out_buf); } else { - memcpy(&out_buf[0], state_not_supported, 2); + memcpy(&buf[0], state_not_supported, 2); return 2; } return 0; diff --git a/applications/main/u2f/u2f.h b/applications/main/u2f/u2f.h index e7508dfa5..dcd7c3ff2 100644 --- a/applications/main/u2f/u2f.h +++ b/applications/main/u2f/u2f.h @@ -6,14 +6,6 @@ extern "C" { #include -typedef struct { - uint8_t cla; - uint8_t ins; - uint8_t p1; - uint8_t p2; - uint8_t len[]; -} __attribute__((packed)) U2fApduCommand; - typedef enum { U2fNotifyRegister, U2fNotifyAuth, @@ -38,7 +30,7 @@ void u2f_set_event_callback(U2fData* instance, U2fEvtCallback callback, void* co void u2f_confirm_user_present(U2fData* instance); -uint16_t u2f_msg_parse(U2fData* instance, const uint8_t* in_buf, uint16_t len, uint8_t* out_buf); +uint16_t u2f_msg_parse(U2fData* instance, uint8_t* buf, uint16_t len); void u2f_wink(U2fData* instance); diff --git a/applications/main/u2f/u2f_app_i.h b/applications/main/u2f/u2f_app_i.h index cfaf3a929..2896684c3 100644 --- a/applications/main/u2f/u2f_app_i.h +++ b/applications/main/u2f/u2f_app_i.h @@ -13,7 +13,6 @@ #include #include #include "views/u2f_view.h" -#include "u2f_nfc.h" #include "u2f_hid.h" #include "u2f.h" @@ -55,7 +54,6 @@ struct U2fApp { Widget* widget; FuriTimer* timer; U2fHid* u2f_hid; - U2fNfc* u2f_nfc; U2fView* u2f_view; U2fData* u2f_instance; GpioCustomEvent event_cur; diff --git a/applications/main/u2f/u2f_hid.c b/applications/main/u2f/u2f_hid.c index 4ca49a3bb..9b625c1f3 100644 --- a/applications/main/u2f/u2f_hid.c +++ b/applications/main/u2f/u2f_hid.c @@ -140,11 +140,8 @@ static bool u2f_hid_parse_request(U2fHid* u2f_hid) { } else if(u2f_hid->packet.cmd == U2F_HID_MSG) { // MSG - U2F message if((u2f_hid->lock == true) && (u2f_hid->packet.cid != u2f_hid->lock_cid)) return false; - uint16_t resp_len = u2f_msg_parse( - u2f_hid->u2f_instance, - u2f_hid->packet.payload, - u2f_hid->packet.len, - u2f_hid->packet.payload); + uint16_t resp_len = + u2f_msg_parse(u2f_hid->u2f_instance, u2f_hid->packet.payload, u2f_hid->packet.len); if(resp_len > 0) { u2f_hid->packet.len = resp_len; u2f_hid_send_response(u2f_hid); diff --git a/applications/main/u2f/u2f_nfc.c b/applications/main/u2f/u2f_nfc.c deleted file mode 100644 index 8c0439982..000000000 --- a/applications/main/u2f/u2f_nfc.c +++ /dev/null @@ -1,182 +0,0 @@ -#include "u2f_nfc.h" -#include "furi_hal.h" -#include "u2f.h" - -#define TAG "U2F_NFC" - -typedef enum { - WorkerEvtReserved = (1 << 0), - WorkerEvtStop = (1 << 1), -} WorkerEvtFlags; - -struct U2fNfc { - FuriThread* thread; - U2fData* u2f_instance; - uint8_t payload[65535]; - uint16_t payload_len; - uint16_t payload_cursor; -}; - -static uint16_t - u2f_callback(U2fNfc* u2f_nfc, const uint8_t* buff_rx, uint16_t buff_rx_len, uint8_t* buff_tx) { - U2fApduCommand* cmd = (U2fApduCommand*)buff_rx; - if(cmd->ins == 0xC0) { - if(u2f_nfc->payload_len == 0) { - FURI_LOG_E(TAG, "requested block but not chaining"); - buff_tx[0] = 0x69; - buff_tx[1] = 0x00; - return 2; - } - - FURI_LOG_T(TAG, "continued chaining %d/%d", u2f_nfc->payload_cursor, u2f_nfc->payload_len); - - uint16_t max_resp_len = cmd->len[0]; - if(max_resp_len == 0) { - max_resp_len = 256; - } - - uint16_t remaining_len = (u2f_nfc->payload_len - 2) - u2f_nfc->payload_cursor; - if(remaining_len > max_resp_len) { - memcpy(buff_tx, &u2f_nfc->payload[u2f_nfc->payload_cursor], max_resp_len); - remaining_len -= max_resp_len; - buff_tx[max_resp_len] = 0x61; - if(remaining_len >= 256) { - buff_tx[max_resp_len + 1] = 0x00; - } else { - buff_tx[max_resp_len + 1] = remaining_len; - } - u2f_nfc->payload_cursor += max_resp_len; - return max_resp_len + 2; - } else { - memcpy( - buff_tx, - &u2f_nfc->payload[u2f_nfc->payload_cursor], - u2f_nfc->payload_len - u2f_nfc->payload_cursor); - u2f_nfc->payload_len = 0; - return remaining_len; - } - } - - // Presence is implied by touching the NFC devices. - u2f_confirm_user_present(u2f_nfc->u2f_instance); - - u2f_nfc->payload_len = - u2f_msg_parse(u2f_nfc->u2f_instance, buff_rx, buff_rx_len, u2f_nfc->payload); - - // If this is extended format, send entire response at once - if(cmd->len[0] == 0) { - FURI_LOG_T(TAG, "single extended response"); - memcpy(&buff_tx, u2f_nfc->payload, u2f_nfc->payload_len); - uint16_t len = u2f_nfc->payload_len; - u2f_nfc->payload_len = 0; - return len; - } - - // Otherwise, we need to do chaining. - uint16_t max_resp_len = 256; - - // If this message happens to be less than the chaining size, send it all at once. - if((u2f_nfc->payload_len - 2) <= max_resp_len) { - FURI_LOG_T(TAG, "single short response"); - memcpy(buff_tx, u2f_nfc->payload, u2f_nfc->payload_len); - uint16_t len = u2f_nfc->payload_len; - u2f_nfc->payload_len = 0; - return len; - } else { - memcpy(buff_tx, u2f_nfc->payload, max_resp_len); - buff_tx[max_resp_len] = 0x61; - uint16_t remaining_len = (u2f_nfc->payload_len - 2) - max_resp_len; - if(remaining_len >= max_resp_len) { - buff_tx[max_resp_len + 1] = 0x00; - } else { - buff_tx[max_resp_len + 1] = remaining_len; - } - u2f_nfc->payload_cursor = max_resp_len; - FURI_LOG_T( - TAG, "started u2f chaining %d/%d", u2f_nfc->payload_cursor, u2f_nfc->payload_len); - return max_resp_len + 2; - } -} - -static int32_t u2f_nfc_worker(void* context) { - U2fNfc* u2f_nfc = context; - FURI_LOG_D(TAG, "Init"); - while(furi_hal_nfc_is_busy()) { - furi_delay_ms(10); - } - FuriHalNfcDevData params = { - // TODO: Randomize this or something? - .uid = {0xCF, 0x72, 0xd4, 0x40}, - .uid_len = 4, - .atqa = {0x00, 0x04}, - .sak = 0x20, - .type = FuriHalNfcTypeA, - .interface = FuriHalNfcInterfaceIsoDep, - }; - - furi_hal_nfc_exit_sleep(); - - FURI_LOG_D(TAG, "Start"); - - while(1) { - uint32_t flags = furi_thread_flags_wait(WorkerEvtStop, FuriFlagWaitAny, 10); - if(flags != FuriFlagErrorTimeout) { - furi_check((flags & FuriFlagError) == 0); - if(flags & WorkerEvtStop) break; - } - if(!furi_hal_nfc_listen(¶ms, false, 200)) { - FURI_LOG_T(TAG, "wtf"); - continue; - } - FuriHalNfcTxRxContext tx_rx = {}; - tx_rx.tx_bits = 0; - tx_rx.tx_rx_type = FuriHalNfcTxRxTypeDefault; - if(!furi_hal_nfc_tx_rx(&tx_rx, 300)) continue; - if(tx_rx.rx_bits == 0) continue; - u2f_nfc->payload_len = 0; - u2f_nfc->payload_cursor = 0; - while(true) { - uint16_t payload_len = - u2f_callback(u2f_nfc, tx_rx.rx_data, tx_rx.rx_bits / 8, tx_rx.tx_data); - tx_rx.rx_bits = 0; - FURI_LOG_T(TAG, "payload_len=%d", payload_len); - if(payload_len == 0) { - break; - } else { - tx_rx.tx_bits = payload_len * 8; - tx_rx.tx_rx_type = FuriHalNfcTxRxTypeDefault; - if(!furi_hal_nfc_tx_rx(&tx_rx, 300)) break; - if(tx_rx.rx_bits == 0) break; - } - } - } - - FURI_LOG_D(TAG, "Cleanup"); - furi_hal_nfc_sleep(); - FURI_LOG_D(TAG, "End"); - return 0; -} - -U2fNfc* u2f_nfc_start(U2fData* u2f_inst) { - U2fNfc* u2f_nfc = malloc(sizeof(U2fNfc)); - u2f_nfc->u2f_instance = u2f_inst; - u2f_nfc->payload_len = 0; - u2f_nfc->payload_cursor = 0; - - u2f_nfc->thread = furi_thread_alloc(); - furi_thread_set_name(u2f_nfc->thread, "U2fNFCWorker"); - furi_thread_set_stack_size(u2f_nfc->thread, 4096); - furi_thread_set_context(u2f_nfc->thread, u2f_nfc); - furi_thread_set_callback(u2f_nfc->thread, u2f_nfc_worker); - furi_thread_start(u2f_nfc->thread); - - return u2f_nfc; -} - -void u2f_nfc_stop(U2fNfc* u2f_nfc) { - furi_assert(u2f_nfc); - furi_thread_flags_set(furi_thread_get_id(u2f_nfc->thread), WorkerEvtStop); - furi_thread_join(u2f_nfc->thread); - furi_thread_free(u2f_nfc->thread); - free(u2f_nfc); -} diff --git a/applications/main/u2f/u2f_nfc.h b/applications/main/u2f/u2f_nfc.h deleted file mode 100644 index 3ac9186f7..000000000 --- a/applications/main/u2f/u2f_nfc.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -#include "u2f.h" - -typedef struct U2fNfc U2fNfc; - -U2fNfc* u2f_nfc_start(U2fData* u2f_inst); - -void u2f_nfc_stop(U2fNfc* u2f_hid); - -#ifdef __cplusplus -} -#endif diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index 35fd8015d..d04c22bc9 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,13.0,, +Version,+,12.0,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -1198,7 +1198,7 @@ Function,+,furi_hal_nfc_field_on,void, Function,-,furi_hal_nfc_init,void, Function,+,furi_hal_nfc_is_busy,_Bool, Function,+,furi_hal_nfc_is_init,_Bool, -Function,+,furi_hal_nfc_listen,_Bool,"FuriHalNfcDevData*, _Bool, uint32_t" +Function,+,furi_hal_nfc_listen,_Bool,"uint8_t*, uint8_t, uint8_t*, uint8_t, _Bool, uint32_t" Function,+,furi_hal_nfc_listen_rx,_Bool,"FuriHalNfcTxRxContext*, uint32_t" Function,+,furi_hal_nfc_listen_sleep,void, Function,+,furi_hal_nfc_listen_start,void,FuriHalNfcDevData* diff --git a/firmware/targets/f7/furi_hal/furi_hal_nfc.c b/firmware/targets/f7/furi_hal/furi_hal_nfc.c index 5e851254d..6381d1a91 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_nfc.c +++ b/firmware/targets/f7/furi_hal/furi_hal_nfc.c @@ -205,7 +205,13 @@ bool furi_hal_nfc_activate_nfca(uint32_t timeout, uint32_t* cuid) { return true; } -bool furi_hal_nfc_listen(FuriHalNfcDevData* nfc_data, bool activate_after_sak, uint32_t timeout) { +bool furi_hal_nfc_listen( + uint8_t* uid, + uint8_t uid_len, + uint8_t* atqa, + uint8_t sak, + bool activate_after_sak, + uint32_t timeout) { rfalNfcState state = rfalNfcGetState(); if(state == RFAL_NFC_STATE_NOTINIT) { rfalNfcInitialize(); @@ -226,18 +232,16 @@ bool furi_hal_nfc_listen(FuriHalNfcDevData* nfc_data, bool activate_after_sak, u .notifyCb = NULL, .activate_after_sak = activate_after_sak, }; - if(nfc_data->interface == FuriHalNfcInterfaceIsoDep) { - params.compMode = RFAL_COMPLIANCE_MODE_ISO; - } else if(FURI_BIT(nfc_data->sak, 5)) { + if(FURI_BIT(sak, 5)) { params.compMode = RFAL_COMPLIANCE_MODE_EMV; } else { params.compMode = RFAL_COMPLIANCE_MODE_NFC; } - params.lmConfigPA.nfcidLen = nfc_data->uid_len; - memcpy(params.lmConfigPA.nfcid, nfc_data->uid, nfc_data->uid_len); - params.lmConfigPA.SENS_RES[0] = nfc_data->atqa[0]; - params.lmConfigPA.SENS_RES[1] = nfc_data->atqa[1]; - params.lmConfigPA.SEL_RES = nfc_data->sak; + params.lmConfigPA.nfcidLen = uid_len; + memcpy(params.lmConfigPA.nfcid, uid, uid_len); + params.lmConfigPA.SENS_RES[0] = atqa[0]; + params.lmConfigPA.SENS_RES[1] = atqa[1]; + params.lmConfigPA.SEL_RES = sak; rfalNfcDiscover(¶ms); // Disable EMD suppression. diff --git a/firmware/targets/furi_hal_include/furi_hal_nfc.h b/firmware/targets/furi_hal_include/furi_hal_nfc.h index 06cd46ba4..d3f6de602 100644 --- a/firmware/targets/furi_hal_include/furi_hal_nfc.h +++ b/firmware/targets/furi_hal_include/furi_hal_nfc.h @@ -154,7 +154,6 @@ bool furi_hal_nfc_activate_nfca(uint32_t timeout, uint32_t* cuid); /** NFC listen * * @param uid pointer to uid buffer - * @param nfc_data pointer to FuriHalNfcDevData * @param uid_len uid length * @param atqa pointer to atqa * @param sak sak @@ -163,7 +162,13 @@ bool furi_hal_nfc_activate_nfca(uint32_t timeout, uint32_t* cuid); * * @return true on success */ -bool furi_hal_nfc_listen(FuriHalNfcDevData* nfc_data, bool activate_after_sak, uint32_t timeout); +bool furi_hal_nfc_listen( + uint8_t* uid, + uint8_t uid_len, + uint8_t* atqa, + uint8_t sak, + bool activate_after_sak, + uint32_t timeout); /** Start Target Listen mode * @note RFAL free implementation diff --git a/lib/nfc/nfc_worker.c b/lib/nfc/nfc_worker.c index a67c64c3c..4138bf033 100644 --- a/lib/nfc/nfc_worker.c +++ b/lib/nfc/nfc_worker.c @@ -776,7 +776,7 @@ void nfc_worker_emulate_uid(NfcWorker* nfc_worker) { // Need to save ATS to support ISO-14443A-4 emulation while(nfc_worker->state == NfcWorkerStateUidEmulate) { - if(furi_hal_nfc_listen(data, false, 100)) { + if(furi_hal_nfc_listen(data->uid, data->uid_len, data->atqa, data->sak, false, 100)) { if(furi_hal_nfc_tx_rx(&tx_rx, 100)) { reader_data->size = tx_rx.rx_bits / 8; if(reader_data->size > 0) { @@ -834,7 +834,7 @@ void nfc_worker_emulate_apdu(NfcWorker* nfc_worker) { } while(nfc_worker->state == NfcWorkerStateEmulateApdu) { //-V1044 - if(furi_hal_nfc_listen(¶ms, false, 300)) { + if(furi_hal_nfc_listen(params.uid, params.uid_len, params.atqa, params.sak, false, 300)) { FURI_LOG_D(TAG, "POS terminal detected"); if(emv_card_emulation(&tx_rx)) { FURI_LOG_D(TAG, "EMV card emulated"); diff --git a/scripts/flipper/assets/icon.py b/scripts/flipper/assets/icon.py index c31eab0b7..ed85b024e 100644 --- a/scripts/flipper/assets/icon.py +++ b/scripts/flipper/assets/icon.py @@ -60,10 +60,7 @@ class ImageTools: with Image.open(file) as im: with io.BytesIO() as output: bw = im.convert("1") - try: - bw = ImageOps.invert(bw) - except OSError: - bw = bw.point(lambda x: 255 - x) + bw = ImageOps.invert(bw) bw.save(output, format="XBM") return output.getvalue() From 4e1dc9216c78691e8d7d1da7068eb1c75be9b1c4 Mon Sep 17 00:00:00 2001 From: Willy-JL Date: Sat, 14 Jan 2023 17:19:24 +0000 Subject: [PATCH 23/60] XP bar progress to next level, not overall --- applications/services/dolphin/helpers/dolphin_state.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/applications/services/dolphin/helpers/dolphin_state.c b/applications/services/dolphin/helpers/dolphin_state.c index eaf270bbe..cd2bd9cd7 100644 --- a/applications/services/dolphin/helpers/dolphin_state.c +++ b/applications/services/dolphin/helpers/dolphin_state.c @@ -100,11 +100,9 @@ uint8_t dolphin_get_level(int icounter) { } uint32_t dolphin_state_xp_above_last_levelup(int icounter) { - if(level_array[0] > icounter) { - for(int i = 1; i < 29; ++i) { - if(icounter <= level_array[i]) { - return level_array[i] - icounter + 1; - } + for(int i = 1; i < 29; ++i) { + if (icounter <= level_array[i]) { + return icounter - level_array[i - 1]; } } return icounter; From a1fac3eb956f23d555147e57fd441fded1ba0533 Mon Sep 17 00:00:00 2001 From: Willy-JL Date: Sat, 14 Jan 2023 17:49:39 +0000 Subject: [PATCH 24/60] Use pathlib for assets, fix build on linux --- scripts/assets.py | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/scripts/assets.py b/scripts/assets.py index 7f086afd7..930783141 100755 --- a/scripts/assets.py +++ b/scripts/assets.py @@ -4,8 +4,8 @@ from flipper.app import App from flipper.assets.icon import file2image import os -import sys import shutil +import pathlib ICONS_SUPPORTED_FORMATS = ["png"] @@ -27,13 +27,13 @@ ICONS_TEMPLATE_C_ICONS = "const Icon {name} = {{.width={width},.height={height}, valid_dirs = list() # This will not stay, dont worry! This is temp code until we got time to rewrite this all -we_are_here = "\\".join(os.path.abspath(__file__).split("\\")[:-2]) -dolphin_external = os.path.join(we_are_here, r"assets\dolphin\external/") -potential_directories = [d for d in os.listdir(dolphin_external) if os.path.isdir(os.path.join(dolphin_external, d))] # Get all animation directories +root_dir = pathlib.Path(__file__).absolute().parent.parent +dolphin_external = root_dir / "assets/dolphin/external/" +potential_directories = [item for item in dolphin_external.iterdir() if item.is_dir()] # Get all animation directories -for i in potential_directories: # loop through all of them - if os.path.exists(os.path.join(dolphin_external, f"{i}\manifest.txt")): # check if they contain a manifest.txt TODO: This code should be moved to wherever manifest.txt files are validated! - valid_dirs.append(os.path.join(dolphin_external, f"{i}")) # append valid directory to list +for directory in potential_directories: # loop through all of them + if (directory / "manifest.txt").exists(): # check if they contain a manifest.txt TODO: This code should be moved to wherever manifest.txt files are validated! + valid_dirs.append(directory) # append valid directory to list class Main(App): def init(self): @@ -259,10 +259,9 @@ class Main(App): # This will not stay, dont worry! This is temp code until we got time to rewrite this all global valid_dirs # access our global variable - for i in valid_dirs: # We can copy the manifest for all of the valid dirs! - i = i.split("/")[-1] - shutil.copyfile(fr"assets\dolphin\external\{i}\manifest.txt", fr"assets\resources\dolphin\{i}\manifest.txt") - os.remove(r"assets\resources\dolphin\manifest.txt") + for valid_dir in valid_dirs: # We can copy the manifest for all of the valid dirs! + shutil.copyfile(valid_dir / "manifest.txt", root_dir / f"assets/resources/dolphin/{valid_dir.name}/manifest.txt") + (root_dir / "assets/resources/dolphin/manifest.txt").unlink() self.logger.info(f"Complete") @@ -292,7 +291,7 @@ class Main(App): self.logger.info(f"Processing Dolphin sources") dolphin = Dolphin() self.logger.info(f"Loading data") - if not "dolphin\external" in str(self.args.input_directory): # AHEM... oopsie. This script apparently just loads all assets, not only external assets, lol. + if not f"dolphin{os.sep}external" in str(self.args.input_directory): # AHEM... oopsie. This script apparently just loads all assets, not only external assets, lol. dolphin.load([self.args.input_directory]) else: dolphin.load(valid_dirs) From 3e0eac000d9d22a764528f3a5816714dd1945850 Mon Sep 17 00:00:00 2001 From: VerstreuteSeele Date: Sat, 14 Jan 2023 20:49:40 +0100 Subject: [PATCH 25/60] Why is this still here? --- assets/resources/infrared/ir_remote/Roku.txt | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 assets/resources/infrared/ir_remote/Roku.txt diff --git a/assets/resources/infrared/ir_remote/Roku.txt b/assets/resources/infrared/ir_remote/Roku.txt deleted file mode 100644 index d9778d3ec..000000000 --- a/assets/resources/infrared/ir_remote/Roku.txt +++ /dev/null @@ -1,12 +0,0 @@ -REMOTE: /ext/infrared/Roku.ir -UP: Up -DOWN: Down -LEFT: Left -RIGHT: Right -OK: Ok -BACK: Back -UPHOLD: V_up -DOWNHOLD: V_down -LEFTHOLD: Play -RIGHTHOLD: Home -OKHOLD: Power \ No newline at end of file From e0544541b13f58be0ea90866a34daf1795218eab Mon Sep 17 00:00:00 2001 From: Willy-JL Date: Sat, 14 Jan 2023 21:05:59 +0000 Subject: [PATCH 26/60] Add passport switch between total and level stats --- .../settings/dolphin_passport/passport.c | 50 +++++++++++++++---- 1 file changed, 41 insertions(+), 9 deletions(-) diff --git a/applications/settings/dolphin_passport/passport.c b/applications/settings/dolphin_passport/passport.c index 7d5a500ea..6de7c3502 100644 --- a/applications/settings/dolphin_passport/passport.c +++ b/applications/settings/dolphin_passport/passport.c @@ -36,16 +36,29 @@ static const Icon* const* portraits_sfw[MOODS_TOTAL] = { static const Icon* const* portraits[MOODS_TOTAL] = {portrait_happy, portrait_ok, portrait_bad}; // static const Icon* const* portraits[MOODS_TOTAL] = {portrait_happy}; -static void input_callback(InputEvent* input, void* ctx) { - FuriSemaphore* semaphore = ctx; +typedef struct { + FuriSemaphore* semaphore; + DolphinStats* stats; + ViewPort* view_port; + bool progress_total; +} PassportContext; + +static void input_callback(InputEvent* input, void* _ctx) { + PassportContext* ctx = _ctx; + + if((input->type == InputTypeShort) && (input->key == InputKeyOk)) { + ctx->progress_total = !ctx->progress_total; + view_port_update(ctx->view_port); + } if((input->type == InputTypeShort) && (input->key == InputKeyBack)) { - furi_semaphore_release(semaphore); + furi_semaphore_release(ctx->semaphore); } } -static void render_callback(Canvas* canvas, void* ctx) { - DolphinStats* stats = ctx; +static void render_callback(Canvas* canvas, void* _ctx) { + PassportContext* ctx = _ctx; + DolphinStats* stats = ctx->stats; DesktopSettings* settings = malloc(sizeof(DesktopSettings)); DESKTOP_SETTINGS_LOAD(settings); @@ -82,11 +95,16 @@ static void render_callback(Canvas* canvas, void* ctx) { uint32_t xp_to_levelup = dolphin_state_xp_to_levelup(stats->icounter); uint32_t xp_above_last_levelup = dolphin_state_xp_above_last_levelup(stats->icounter); uint32_t xp_for_current_level = xp_to_levelup + xp_above_last_levelup; + uint32_t xp_next_level = stats->icounter + xp_to_levelup; if(stats->level == 30) { xp_progress = 0; } else { - xp_progress = xp_to_levelup * 64 / xp_for_current_level; + if (ctx->progress_total) { + xp_progress = stats->icounter * 64 / xp_next_level; + } else { + xp_progress = xp_to_levelup * 64 / xp_for_current_level; + } } // multipass @@ -107,7 +125,11 @@ static void render_callback(Canvas* canvas, void* ctx) { const char* my_name = furi_hal_version_get_name_ptr(); snprintf(level_str, 12, "Level: %hu", stats->level); - snprintf(xp_str, 12, "%lu/%lu", xp_above_last_levelup, xp_for_current_level); + if (ctx->progress_total) { + snprintf(xp_str, 12, "%lu/%lu", stats->icounter, xp_next_level); + } else { + snprintf(xp_str, 12, "%lu/%lu", xp_above_last_levelup, xp_for_current_level); + } canvas_set_font(canvas, FontSecondary); canvas_draw_str(canvas, 58, 10, my_name ? my_name : "Unknown"); canvas_draw_str(canvas, 58, 22, mood_str); @@ -121,6 +143,10 @@ static void render_callback(Canvas* canvas, void* ctx) { canvas_set_color(canvas, ColorWhite); canvas_draw_box(canvas, 123 - xp_progress, 45, xp_progress + 1, 5); canvas_set_color(canvas, ColorBlack); + + canvas_draw_icon(canvas, 52, 51, &I_Ok_btn_9x9); + canvas_draw_str(canvas, ctx->progress_total ? 37 : 36, 59, ctx->progress_total ? "Lvl" : "Tot"); + free(settings); } @@ -133,9 +159,14 @@ int32_t passport_app(void* p) { Dolphin* dolphin = furi_record_open(RECORD_DOLPHIN); DolphinStats stats = dolphin_stats(dolphin); + PassportContext* ctx = malloc(sizeof(PassportContext)); + ctx->stats = &stats; + ctx->view_port = view_port; + ctx->semaphore = semaphore; + ctx->progress_total = false; furi_record_close(RECORD_DOLPHIN); - view_port_draw_callback_set(view_port, render_callback, &stats); - view_port_input_callback_set(view_port, input_callback, semaphore); + view_port_draw_callback_set(view_port, render_callback, ctx); + view_port_input_callback_set(view_port, input_callback, ctx); Gui* gui = furi_record_open(RECORD_GUI); gui_add_view_port(gui, view_port, GuiLayerFullscreen); view_port_update(view_port); @@ -146,6 +177,7 @@ int32_t passport_app(void* p) { view_port_free(view_port); furi_record_close(RECORD_GUI); furi_semaphore_free(semaphore); + free(ctx); return 0; } From ee404fb3f1ca726e5493ebb82b0e84d3e4dd166e Mon Sep 17 00:00:00 2001 From: VerstreuteSeele Date: Sat, 14 Jan 2023 22:53:44 +0100 Subject: [PATCH 27/60] no more manifest pathing --- assets/dolphin/external/nsfw/manifest.txt | 62 +++++++++---------- .../external/nsfw/no_lvl_up_manifest.txt | 62 +++++++++---------- assets/dolphin/external/sfw/manifest.txt | 42 ++++++------- 3 files changed, 83 insertions(+), 83 deletions(-) diff --git a/assets/dolphin/external/nsfw/manifest.txt b/assets/dolphin/external/nsfw/manifest.txt index c9cba41d4..55697afe5 100644 --- a/assets/dolphin/external/nsfw/manifest.txt +++ b/assets/dolphin/external/nsfw/manifest.txt @@ -1,217 +1,217 @@ Filetype: Flipper Animation Manifest Version: 1 -Name: nsfw/lvl_1 +Name: lvl_1 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 7 -Name: nsfw/lvl_2 +Name: lvl_2 Min butthurt: 0 Max butthurt: 14 Min level: 2 Max level: 30 Weight: 7 -Name: nsfw/lvl_3 +Name: lvl_3 Min butthurt: 0 Max butthurt: 14 Min level: 3 Max level: 30 Weight: 7 -Name: nsfw/lvl_4 +Name: lvl_4 Min butthurt: 0 Max butthurt: 14 Min level: 4 Max level: 30 Weight: 7 -Name: nsfw/lvl_5 +Name: lvl_5 Min butthurt: 0 Max butthurt: 14 Min level: 5 Max level: 30 Weight: 7 -Name: nsfw/lvl_6 +Name: lvl_6 Min butthurt: 0 Max butthurt: 14 Min level: 6 Max level: 30 Weight: 7 -Name: nsfw/lvl_7 +Name: lvl_7 Min butthurt: 0 Max butthurt: 14 Min level: 7 Max level: 30 Weight: 7 -Name: nsfw/lvl_8 +Name: lvl_8 Min butthurt: 0 Max butthurt: 14 Min level: 8 Max level: 30 Weight: 7 -Name: nsfw/lvl_9 +Name: lvl_9 Min butthurt: 0 Max butthurt: 14 Min level: 9 Max level: 30 Weight: 7 -Name: nsfw/lvl_10 +Name: lvl_10 Min butthurt: 0 Max butthurt: 14 Min level: 10 Max level: 30 Weight: 7 -Name: nsfw/lvl_11 +Name: lvl_11 Min butthurt: 0 Max butthurt: 14 Min level: 11 Max level: 30 Weight: 9 -Name: nsfw/PaxGod_TikTok_Marketing +Name: PaxGod_TikTok_Marketing Min butthurt: 0 Max butthurt: 14 Min level: 11 Max level: 30 Weight: 3 -Name: nsfw/lvl_12 +Name: lvl_12 Min butthurt: 0 Max butthurt: 14 Min level: 12 Max level: 30 Weight: 7 -Name: nsfw/lvl_13 +Name: lvl_13 Min butthurt: 0 Max butthurt: 14 Min level: 13 Max level: 30 Weight: 7 -Name: nsfw/lvl_14 +Name: lvl_14 Min butthurt: 0 Max butthurt: 14 Min level: 14 Max level: 30 Weight: 7 -Name: nsfw/lvl_15 +Name: lvl_15 Min butthurt: 0 Max butthurt: 14 Min level: 15 Max level: 30 Weight: 7 -Name: nsfw/lvl_16 +Name: lvl_16 Min butthurt: 0 Max butthurt: 14 Min level: 16 Max level: 30 Weight: 7 -Name: nsfw/lvl_17 +Name: lvl_17 Min butthurt: 0 Max butthurt: 14 Min level: 17 Max level: 30 Weight: 7 -Name: nsfw/lvl_18 +Name: lvl_18 Min butthurt: 0 Max butthurt: 14 Min level: 18 Max level: 30 Weight: 7 -Name: nsfw/lvl_19 +Name: lvl_19 Min butthurt: 0 Max butthurt: 14 Min level: 19 Max level: 30 Weight: 7 -Name: nsfw/lvl_20 +Name: lvl_20 Min butthurt: 0 Max butthurt: 14 Min level: 20 Max level: 30 Weight: 7 -Name: nsfw/lvl_21 +Name: lvl_21 Min butthurt: 0 Max butthurt: 14 Min level: 21 Max level: 30 Weight: 9 -Name: nsfw/lvl_22 +Name: lvl_22 Min butthurt: 0 Max butthurt: 14 Min level: 22 Max level: 30 Weight: 7 -Name: nsfw/lvl_23 +Name: lvl_23 Min butthurt: 0 Max butthurt: 14 Min level: 23 Max level: 30 Weight: 7 -Name: nsfw/lvl_24 +Name: lvl_24 Min butthurt: 0 Max butthurt: 14 Min level: 24 Max level: 30 Weight: 7 -Name: nsfw/lvl_25 +Name: lvl_25 Min butthurt: 0 Max butthurt: 14 Min level: 25 Max level: 30 Weight: 7 -Name: nsfw/lvl_26 +Name: lvl_26 Min butthurt: 0 Max butthurt: 14 Min level: 26 Max level: 30 Weight: 7 -Name: nsfw/lvl_27 +Name: lvl_27 Min butthurt: 0 Max butthurt: 14 Min level: 27 Max level: 30 Weight: 7 -Name: nsfw/lvl_28 +Name: lvl_28 Min butthurt: 0 Max butthurt: 14 Min level: 28 Max level: 30 Weight: 7 -Name: nsfw/lvl_29 +Name: lvl_29 Min butthurt: 0 Max butthurt: 14 Min level: 29 Max level: 30 Weight: 7 -Name: nsfw/lvl_30 +Name: lvl_30 Min butthurt: 0 Max butthurt: 14 Min level: 30 diff --git a/assets/dolphin/external/nsfw/no_lvl_up_manifest.txt b/assets/dolphin/external/nsfw/no_lvl_up_manifest.txt index 2027b1c9f..923efb65e 100644 --- a/assets/dolphin/external/nsfw/no_lvl_up_manifest.txt +++ b/assets/dolphin/external/nsfw/no_lvl_up_manifest.txt @@ -1,217 +1,217 @@ Filetype: Flipper Animation Manifest Version: 1 -Name: nsfw/lvl_1 +Name: lvl_1 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 7 -Name: nsfw/lvl_2 +Name: lvl_2 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 7 -Name: nsfw/lvl_3 +Name: lvl_3 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 7 -Name: nsfw/lvl_4 +Name: lvl_4 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 7 -Name: nsfw/lvl_5 +Name: lvl_5 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 7 -Name: nsfw/lvl_6 +Name: lvl_6 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 7 -Name: nsfw/lvl_7 +Name: lvl_7 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 7 -Name: nsfw/lvl_8 +Name: lvl_8 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 7 -Name: nsfw/lvl_9 +Name: lvl_9 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 7 -Name: nsfw/lvl_10 +Name: lvl_10 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 7 -Name: nsfw/lvl_11 +Name: lvl_11 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 9 -Name: nsfw/PaxGod_TikTok_Marketing +Name: PaxGod_TikTok_Marketing Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 3 -Name: nsfw/lvl_12 +Name: lvl_12 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 7 -Name: nsfw/lvl_13 +Name: lvl_13 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 7 -Name: nsfw/lvl_14 +Name: lvl_14 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 7 -Name: nsfw/lvl_15 +Name: lvl_15 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 7 -Name: nsfw/lvl_16 +Name: lvl_16 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 7 -Name: nsfw/lvl_17 +Name: lvl_17 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 7 -Name: nsfw/lvl_18 +Name: lvl_18 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 7 -Name: nsfw/lvl_19 +Name: lvl_19 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 7 -Name: nsfw/lvl_20 +Name: lvl_20 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 7 -Name: nsfw/lvl_21 +Name: lvl_21 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 9 -Name: nsfw/lvl_22 +Name: lvl_22 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 7 -Name: nsfw/lvl_23 +Name: lvl_23 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 7 -Name: nsfw/lvl_24 +Name: lvl_24 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 7 -Name: nsfw/lvl_25 +Name: lvl_25 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 7 -Name: nsfw/lvl_26 +Name: lvl_26 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 7 -Name: nsfw/lvl_27 +Name: lvl_27 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 7 -Name: nsfw/lvl_28 +Name: lvl_28 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 7 -Name: nsfw/lvl_29 +Name: lvl_29 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 7 -Name: nsfw/lvl_30 +Name: lvl_30 Min butthurt: 0 Max butthurt: 14 Min level: 1 diff --git a/assets/dolphin/external/sfw/manifest.txt b/assets/dolphin/external/sfw/manifest.txt index 070277350..48911f9a1 100644 --- a/assets/dolphin/external/sfw/manifest.txt +++ b/assets/dolphin/external/sfw/manifest.txt @@ -1,147 +1,147 @@ Filetype: Flipper Animation Manifest Version: 1 -Name: sfw/L1_Waves_128x50 +Name: L1_Waves_128x50 Min butthurt: 0 Max butthurt: 5 Min level: 1 Max level: 30 Weight: 3 -Name: sfw/L1_Laptop_128x51 +Name: L1_Laptop_128x51 Min butthurt: 0 Max butthurt: 7 Min level: 1 Max level: 30 Weight: 3 -Name: sfw/L1_Sleep_128x64 +Name: L1_Sleep_128x64 Min butthurt: 0 Max butthurt: 10 Min level: 1 Max level: 30 Weight: 3 -Name: sfw/L1_Recording_128x51 +Name: L1_Recording_128x51 Min butthurt: 0 Max butthurt: 8 Min level: 1 Max level: 30 Weight: 3 -Name: sfw/L1_Furippa1_128x64 +Name: L1_Furippa1_128x64 Min butthurt: 0 Max butthurt: 6 Min level: 1 Max level: 30 Weight: 3 -Name: sfw/L1_Happy_holidays_128x64 +Name: L1_Happy_holidays_128x64 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 4 -Name: sfw/L1_Read_books_128x64 +Name: L1_Read_books_128x64 Min butthurt: 0 Max butthurt: 8 Min level: 1 Max level: 30 Weight: 3 -Name: sfw/L1_Cry_128x64 +Name: L1_Cry_128x64 Min butthurt: 8 Max butthurt: 13 Min level: 1 Max level: 30 Weight: 3 -Name: sfw/L1_Boxing_128x64 +Name: L1_Boxing_128x64 Min butthurt: 10 Max butthurt: 13 Min level: 1 Max level: 30 Weight: 3 -Name: sfw/L1_Mad_fist_128x64 +Name: L1_Mad_fist_128x64 Min butthurt: 9 Max butthurt: 13 Min level: 1 Max level: 30 Weight: 3 -Name: sfw/L1_Mods_128x64 +Name: L1_Mods_128x64 Min butthurt: 0 Max butthurt: 9 Min level: 1 Max level: 30 Weight: 4 -Name: sfw/L1_Painting_128x64 +Name: L1_Painting_128x64 Min butthurt: 0 Max butthurt: 7 Min level: 1 Max level: 30 Weight: 3 -Name: sfw/L1_Leaving_sad_128x64 +Name: L1_Leaving_sad_128x64 Min butthurt: 14 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 3 -Name: sfw/L2_Wake_up_128x64 +Name: L2_Wake_up_128x64 Min butthurt: 0 Max butthurt: 12 Min level: 1 Max level: 30 Weight: 4 -Name: sfw/L2_Furippa2_128x64 +Name: L2_Furippa2_128x64 Min butthurt: 0 Max butthurt: 6 Min level: 1 Max level: 30 Weight: 3 -Name: sfw/L2_Hacking_pc_128x64 +Name: L2_Hacking_pc_128x64 Min butthurt: 0 Max butthurt: 8 Min level: 1 Max level: 30 Weight: 3 -Name: sfw/L2_Soldering_128x64 +Name: L2_Soldering_128x64 Min butthurt: 0 Max butthurt: 10 Min level: 1 Max level: 30 Weight: 3 -Name: sfw/L3_Furippa3_128x64 +Name: L3_Furippa3_128x64 Min butthurt: 0 Max butthurt: 6 Min level: 1 Max level: 30 Weight: 3 -Name: sfw/L3_Hijack_radio_128x64 +Name: L3_Hijack_radio_128x64 Min butthurt: 0 Max butthurt: 8 Min level: 1 Max level: 30 Weight: 3 -Name: sfw/L3_Lab_research_128x54 +Name: L3_Lab_research_128x54 Min butthurt: 0 Max butthurt: 10 Min level: 1 Max level: 30 Weight: 3 -Name: sfw/L1_Sleigh_ride_128x64 +Name: L1_Sleigh_ride_128x64 Min butthurt: 0 Max butthurt: 14 Min level: 1 From b01fe0645270085354c25d7bc9ebb493fdf47407 Mon Sep 17 00:00:00 2001 From: VerstreuteSeele Date: Sat, 14 Jan 2023 22:56:08 +0100 Subject: [PATCH 28/60] personal preference on tot-xp switch default --- applications/settings/dolphin_passport/passport.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/applications/settings/dolphin_passport/passport.c b/applications/settings/dolphin_passport/passport.c index 6de7c3502..35c3191f7 100644 --- a/applications/settings/dolphin_passport/passport.c +++ b/applications/settings/dolphin_passport/passport.c @@ -163,7 +163,7 @@ int32_t passport_app(void* p) { ctx->stats = &stats; ctx->view_port = view_port; ctx->semaphore = semaphore; - ctx->progress_total = false; + ctx->progress_total = true; furi_record_close(RECORD_DOLPHIN); view_port_draw_callback_set(view_port, render_callback, ctx); view_port_input_callback_set(view_port, input_callback, ctx); From 51e1665b01367f1defec508b11ecf129a4364ce6 Mon Sep 17 00:00:00 2001 From: VerstreuteSeele Date: Sat, 14 Jan 2023 22:57:47 +0100 Subject: [PATCH 29/60] Revert "no more manifest pathing" This reverts commit ee404fb3f1ca726e5493ebb82b0e84d3e4dd166e. --- assets/dolphin/external/nsfw/manifest.txt | 62 +++++++++---------- .../external/nsfw/no_lvl_up_manifest.txt | 62 +++++++++---------- assets/dolphin/external/sfw/manifest.txt | 42 ++++++------- 3 files changed, 83 insertions(+), 83 deletions(-) diff --git a/assets/dolphin/external/nsfw/manifest.txt b/assets/dolphin/external/nsfw/manifest.txt index 55697afe5..c9cba41d4 100644 --- a/assets/dolphin/external/nsfw/manifest.txt +++ b/assets/dolphin/external/nsfw/manifest.txt @@ -1,217 +1,217 @@ Filetype: Flipper Animation Manifest Version: 1 -Name: lvl_1 +Name: nsfw/lvl_1 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 7 -Name: lvl_2 +Name: nsfw/lvl_2 Min butthurt: 0 Max butthurt: 14 Min level: 2 Max level: 30 Weight: 7 -Name: lvl_3 +Name: nsfw/lvl_3 Min butthurt: 0 Max butthurt: 14 Min level: 3 Max level: 30 Weight: 7 -Name: lvl_4 +Name: nsfw/lvl_4 Min butthurt: 0 Max butthurt: 14 Min level: 4 Max level: 30 Weight: 7 -Name: lvl_5 +Name: nsfw/lvl_5 Min butthurt: 0 Max butthurt: 14 Min level: 5 Max level: 30 Weight: 7 -Name: lvl_6 +Name: nsfw/lvl_6 Min butthurt: 0 Max butthurt: 14 Min level: 6 Max level: 30 Weight: 7 -Name: lvl_7 +Name: nsfw/lvl_7 Min butthurt: 0 Max butthurt: 14 Min level: 7 Max level: 30 Weight: 7 -Name: lvl_8 +Name: nsfw/lvl_8 Min butthurt: 0 Max butthurt: 14 Min level: 8 Max level: 30 Weight: 7 -Name: lvl_9 +Name: nsfw/lvl_9 Min butthurt: 0 Max butthurt: 14 Min level: 9 Max level: 30 Weight: 7 -Name: lvl_10 +Name: nsfw/lvl_10 Min butthurt: 0 Max butthurt: 14 Min level: 10 Max level: 30 Weight: 7 -Name: lvl_11 +Name: nsfw/lvl_11 Min butthurt: 0 Max butthurt: 14 Min level: 11 Max level: 30 Weight: 9 -Name: PaxGod_TikTok_Marketing +Name: nsfw/PaxGod_TikTok_Marketing Min butthurt: 0 Max butthurt: 14 Min level: 11 Max level: 30 Weight: 3 -Name: lvl_12 +Name: nsfw/lvl_12 Min butthurt: 0 Max butthurt: 14 Min level: 12 Max level: 30 Weight: 7 -Name: lvl_13 +Name: nsfw/lvl_13 Min butthurt: 0 Max butthurt: 14 Min level: 13 Max level: 30 Weight: 7 -Name: lvl_14 +Name: nsfw/lvl_14 Min butthurt: 0 Max butthurt: 14 Min level: 14 Max level: 30 Weight: 7 -Name: lvl_15 +Name: nsfw/lvl_15 Min butthurt: 0 Max butthurt: 14 Min level: 15 Max level: 30 Weight: 7 -Name: lvl_16 +Name: nsfw/lvl_16 Min butthurt: 0 Max butthurt: 14 Min level: 16 Max level: 30 Weight: 7 -Name: lvl_17 +Name: nsfw/lvl_17 Min butthurt: 0 Max butthurt: 14 Min level: 17 Max level: 30 Weight: 7 -Name: lvl_18 +Name: nsfw/lvl_18 Min butthurt: 0 Max butthurt: 14 Min level: 18 Max level: 30 Weight: 7 -Name: lvl_19 +Name: nsfw/lvl_19 Min butthurt: 0 Max butthurt: 14 Min level: 19 Max level: 30 Weight: 7 -Name: lvl_20 +Name: nsfw/lvl_20 Min butthurt: 0 Max butthurt: 14 Min level: 20 Max level: 30 Weight: 7 -Name: lvl_21 +Name: nsfw/lvl_21 Min butthurt: 0 Max butthurt: 14 Min level: 21 Max level: 30 Weight: 9 -Name: lvl_22 +Name: nsfw/lvl_22 Min butthurt: 0 Max butthurt: 14 Min level: 22 Max level: 30 Weight: 7 -Name: lvl_23 +Name: nsfw/lvl_23 Min butthurt: 0 Max butthurt: 14 Min level: 23 Max level: 30 Weight: 7 -Name: lvl_24 +Name: nsfw/lvl_24 Min butthurt: 0 Max butthurt: 14 Min level: 24 Max level: 30 Weight: 7 -Name: lvl_25 +Name: nsfw/lvl_25 Min butthurt: 0 Max butthurt: 14 Min level: 25 Max level: 30 Weight: 7 -Name: lvl_26 +Name: nsfw/lvl_26 Min butthurt: 0 Max butthurt: 14 Min level: 26 Max level: 30 Weight: 7 -Name: lvl_27 +Name: nsfw/lvl_27 Min butthurt: 0 Max butthurt: 14 Min level: 27 Max level: 30 Weight: 7 -Name: lvl_28 +Name: nsfw/lvl_28 Min butthurt: 0 Max butthurt: 14 Min level: 28 Max level: 30 Weight: 7 -Name: lvl_29 +Name: nsfw/lvl_29 Min butthurt: 0 Max butthurt: 14 Min level: 29 Max level: 30 Weight: 7 -Name: lvl_30 +Name: nsfw/lvl_30 Min butthurt: 0 Max butthurt: 14 Min level: 30 diff --git a/assets/dolphin/external/nsfw/no_lvl_up_manifest.txt b/assets/dolphin/external/nsfw/no_lvl_up_manifest.txt index 923efb65e..2027b1c9f 100644 --- a/assets/dolphin/external/nsfw/no_lvl_up_manifest.txt +++ b/assets/dolphin/external/nsfw/no_lvl_up_manifest.txt @@ -1,217 +1,217 @@ Filetype: Flipper Animation Manifest Version: 1 -Name: lvl_1 +Name: nsfw/lvl_1 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 7 -Name: lvl_2 +Name: nsfw/lvl_2 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 7 -Name: lvl_3 +Name: nsfw/lvl_3 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 7 -Name: lvl_4 +Name: nsfw/lvl_4 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 7 -Name: lvl_5 +Name: nsfw/lvl_5 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 7 -Name: lvl_6 +Name: nsfw/lvl_6 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 7 -Name: lvl_7 +Name: nsfw/lvl_7 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 7 -Name: lvl_8 +Name: nsfw/lvl_8 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 7 -Name: lvl_9 +Name: nsfw/lvl_9 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 7 -Name: lvl_10 +Name: nsfw/lvl_10 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 7 -Name: lvl_11 +Name: nsfw/lvl_11 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 9 -Name: PaxGod_TikTok_Marketing +Name: nsfw/PaxGod_TikTok_Marketing Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 3 -Name: lvl_12 +Name: nsfw/lvl_12 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 7 -Name: lvl_13 +Name: nsfw/lvl_13 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 7 -Name: lvl_14 +Name: nsfw/lvl_14 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 7 -Name: lvl_15 +Name: nsfw/lvl_15 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 7 -Name: lvl_16 +Name: nsfw/lvl_16 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 7 -Name: lvl_17 +Name: nsfw/lvl_17 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 7 -Name: lvl_18 +Name: nsfw/lvl_18 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 7 -Name: lvl_19 +Name: nsfw/lvl_19 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 7 -Name: lvl_20 +Name: nsfw/lvl_20 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 7 -Name: lvl_21 +Name: nsfw/lvl_21 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 9 -Name: lvl_22 +Name: nsfw/lvl_22 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 7 -Name: lvl_23 +Name: nsfw/lvl_23 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 7 -Name: lvl_24 +Name: nsfw/lvl_24 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 7 -Name: lvl_25 +Name: nsfw/lvl_25 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 7 -Name: lvl_26 +Name: nsfw/lvl_26 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 7 -Name: lvl_27 +Name: nsfw/lvl_27 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 7 -Name: lvl_28 +Name: nsfw/lvl_28 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 7 -Name: lvl_29 +Name: nsfw/lvl_29 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 7 -Name: lvl_30 +Name: nsfw/lvl_30 Min butthurt: 0 Max butthurt: 14 Min level: 1 diff --git a/assets/dolphin/external/sfw/manifest.txt b/assets/dolphin/external/sfw/manifest.txt index 48911f9a1..070277350 100644 --- a/assets/dolphin/external/sfw/manifest.txt +++ b/assets/dolphin/external/sfw/manifest.txt @@ -1,147 +1,147 @@ Filetype: Flipper Animation Manifest Version: 1 -Name: L1_Waves_128x50 +Name: sfw/L1_Waves_128x50 Min butthurt: 0 Max butthurt: 5 Min level: 1 Max level: 30 Weight: 3 -Name: L1_Laptop_128x51 +Name: sfw/L1_Laptop_128x51 Min butthurt: 0 Max butthurt: 7 Min level: 1 Max level: 30 Weight: 3 -Name: L1_Sleep_128x64 +Name: sfw/L1_Sleep_128x64 Min butthurt: 0 Max butthurt: 10 Min level: 1 Max level: 30 Weight: 3 -Name: L1_Recording_128x51 +Name: sfw/L1_Recording_128x51 Min butthurt: 0 Max butthurt: 8 Min level: 1 Max level: 30 Weight: 3 -Name: L1_Furippa1_128x64 +Name: sfw/L1_Furippa1_128x64 Min butthurt: 0 Max butthurt: 6 Min level: 1 Max level: 30 Weight: 3 -Name: L1_Happy_holidays_128x64 +Name: sfw/L1_Happy_holidays_128x64 Min butthurt: 0 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 4 -Name: L1_Read_books_128x64 +Name: sfw/L1_Read_books_128x64 Min butthurt: 0 Max butthurt: 8 Min level: 1 Max level: 30 Weight: 3 -Name: L1_Cry_128x64 +Name: sfw/L1_Cry_128x64 Min butthurt: 8 Max butthurt: 13 Min level: 1 Max level: 30 Weight: 3 -Name: L1_Boxing_128x64 +Name: sfw/L1_Boxing_128x64 Min butthurt: 10 Max butthurt: 13 Min level: 1 Max level: 30 Weight: 3 -Name: L1_Mad_fist_128x64 +Name: sfw/L1_Mad_fist_128x64 Min butthurt: 9 Max butthurt: 13 Min level: 1 Max level: 30 Weight: 3 -Name: L1_Mods_128x64 +Name: sfw/L1_Mods_128x64 Min butthurt: 0 Max butthurt: 9 Min level: 1 Max level: 30 Weight: 4 -Name: L1_Painting_128x64 +Name: sfw/L1_Painting_128x64 Min butthurt: 0 Max butthurt: 7 Min level: 1 Max level: 30 Weight: 3 -Name: L1_Leaving_sad_128x64 +Name: sfw/L1_Leaving_sad_128x64 Min butthurt: 14 Max butthurt: 14 Min level: 1 Max level: 30 Weight: 3 -Name: L2_Wake_up_128x64 +Name: sfw/L2_Wake_up_128x64 Min butthurt: 0 Max butthurt: 12 Min level: 1 Max level: 30 Weight: 4 -Name: L2_Furippa2_128x64 +Name: sfw/L2_Furippa2_128x64 Min butthurt: 0 Max butthurt: 6 Min level: 1 Max level: 30 Weight: 3 -Name: L2_Hacking_pc_128x64 +Name: sfw/L2_Hacking_pc_128x64 Min butthurt: 0 Max butthurt: 8 Min level: 1 Max level: 30 Weight: 3 -Name: L2_Soldering_128x64 +Name: sfw/L2_Soldering_128x64 Min butthurt: 0 Max butthurt: 10 Min level: 1 Max level: 30 Weight: 3 -Name: L3_Furippa3_128x64 +Name: sfw/L3_Furippa3_128x64 Min butthurt: 0 Max butthurt: 6 Min level: 1 Max level: 30 Weight: 3 -Name: L3_Hijack_radio_128x64 +Name: sfw/L3_Hijack_radio_128x64 Min butthurt: 0 Max butthurt: 8 Min level: 1 Max level: 30 Weight: 3 -Name: L3_Lab_research_128x54 +Name: sfw/L3_Lab_research_128x54 Min butthurt: 0 Max butthurt: 10 Min level: 1 Max level: 30 Weight: 3 -Name: L1_Sleigh_ride_128x64 +Name: sfw/L1_Sleigh_ride_128x64 Min butthurt: 0 Max butthurt: 14 Min level: 1 From 1d58823c54538456d25f45ad8927aa5ec623c20a Mon Sep 17 00:00:00 2001 From: VerstreuteSeele Date: Sat, 14 Jan 2023 23:54:50 +0100 Subject: [PATCH 30/60] maybe just keep it as is, was better --- applications/settings/dolphin_passport/passport.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/applications/settings/dolphin_passport/passport.c b/applications/settings/dolphin_passport/passport.c index 35c3191f7..6de7c3502 100644 --- a/applications/settings/dolphin_passport/passport.c +++ b/applications/settings/dolphin_passport/passport.c @@ -163,7 +163,7 @@ int32_t passport_app(void* p) { ctx->stats = &stats; ctx->view_port = view_port; ctx->semaphore = semaphore; - ctx->progress_total = true; + ctx->progress_total = false; furi_record_close(RECORD_DOLPHIN); view_port_draw_callback_set(view_port, render_callback, ctx); view_port_input_callback_set(view_port, input_callback, ctx); From f375a60555901d331deb017b9919a3cec6dfbf32 Mon Sep 17 00:00:00 2001 From: VerstreuteSeele Date: Sun, 15 Jan 2023 01:12:25 +0100 Subject: [PATCH 31/60] Fix Assets --- .../main/lfrfid/scenes/lfrfid_scene_extra_actions.c | 2 +- .../main/nfc/scenes/nfc_scene_emulate_nfcv.c | 12 +++++++++++- .../nfc/scenes/nfc_scene_mf_ultralight_emulate.c | 11 ++++++++++- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_extra_actions.c b/applications/main/lfrfid/scenes/lfrfid_scene_extra_actions.c index efa319c1e..b1130d191 100644 --- a/applications/main/lfrfid/scenes/lfrfid_scene_extra_actions.c +++ b/applications/main/lfrfid/scenes/lfrfid_scene_extra_actions.c @@ -20,7 +20,7 @@ void lfrfid_scene_extra_actions_on_enter(void* context) { submenu_add_item( submenu, - "Read ASK (FDX,Regular)", + "Read ASK (Animal, FDX)", SubmenuIndexASK, lfrfid_scene_extra_actions_submenu_callback, app); diff --git a/applications/main/nfc/scenes/nfc_scene_emulate_nfcv.c b/applications/main/nfc/scenes/nfc_scene_emulate_nfcv.c index e6fc60d86..d9d3db9da 100644 --- a/applications/main/nfc/scenes/nfc_scene_emulate_nfcv.c +++ b/applications/main/nfc/scenes/nfc_scene_emulate_nfcv.c @@ -1,4 +1,5 @@ #include "../nfc_i.h" +#include "../../../settings/desktop_settings/desktop_settings_app.h" #define NFC_SCENE_EMULATE_NFCV_LOG_SIZE_MAX (100) @@ -37,7 +38,15 @@ static void nfc_scene_emulate_nfcv_widget_config(Nfc* nfc, bool data_received) { FuriString* info_str; info_str = furi_string_alloc(); - widget_add_icon_element(widget, 0, 3, &I_RFIDDolphinSend_97x61); + DesktopSettings* settings = malloc(sizeof(DesktopSettings)); + DESKTOP_SETTINGS_LOAD(settings); + + if(settings->sfw_mode) { + widget_add_icon_element(widget, 0, 3, &I_RFIDDolphinSend_97x61_sfw); + } else { + widget_add_icon_element(widget, 0, 3, &I_RFIDDolphinSend_97x61); + } + widget_add_string_element( widget, 89, 32, AlignCenter, AlignTop, FontPrimary, "Emulating NfcV"); if(strcmp(nfc->dev->dev_name, "")) { @@ -55,6 +64,7 @@ static void nfc_scene_emulate_nfcv_widget_config(Nfc* nfc, bool data_received) { widget_add_button_element( widget, GuiButtonTypeCenter, "Log", nfc_scene_emulate_nfcv_widget_callback, nfc); } + free(settings); } void nfc_scene_emulate_nfcv_on_enter(void* context) { diff --git a/applications/main/nfc/scenes/nfc_scene_mf_ultralight_emulate.c b/applications/main/nfc/scenes/nfc_scene_mf_ultralight_emulate.c index e46609c08..7e8a899a4 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_ultralight_emulate.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_ultralight_emulate.c @@ -66,7 +66,15 @@ void nfc_scene_mf_ultralight_emulate_widget_config(Nfc* nfc, bool auth_attempted FuriString* info_str; info_str = furi_string_alloc(); - widget_add_icon_element(widget, 0, 3, &I_RFIDDolphinSend_97x61); + DesktopSettings* settings = malloc(sizeof(DesktopSettings)); + DESKTOP_SETTINGS_LOAD(settings); + + if(settings->sfw_mode) { + widget_add_icon_element(widget, 0, 3, &I_NFC_dolphin_emulation_47x61_sfw); + } else { + widget_add_icon_element(widget, 0, 3, &I_NFC_dolphin_emulation_47x61); + } + if(strcmp(nfc->dev->dev_name, "")) { furi_string_printf(info_str, "Emulating\n%s", nfc->dev->dev_name); } else { @@ -84,6 +92,7 @@ void nfc_scene_mf_ultralight_emulate_widget_config(Nfc* nfc, bool auth_attempted nfc_scene_mf_ultralight_emulate_widget_callback, nfc); } + free(settings); } void nfc_scene_mf_ultralight_emulate_on_enter(void* context) { From a642bed2fc84926ddcf7378ccf08e1dfffff36ae Mon Sep 17 00:00:00 2001 From: VerstreuteSeele Date: Sun, 15 Jan 2023 22:35:36 +0100 Subject: [PATCH 32/60] scons fuckery --- scripts/version.py | 10 +++++++++- site_scons/commandline.scons | 7 ++++++- site_scons/environ.scons | 3 ++- site_scons/extapps.scons | 16 +--------------- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/scripts/version.py b/scripts/version.py index f46eee068..a32b272aa 100644 --- a/scripts/version.py +++ b/scripts/version.py @@ -40,7 +40,15 @@ class GitVersion: os.environ.get("CUSTOM_FLIPPER_NAME", None) or "" ) - + + force_no_dirty = ( + os.environ.get("FORCE_NO_DIRTY", None) + or "" + ) + + if (force_no_dirty != ""): + dirty = False + if (custom_fz_name != "") and (len(custom_fz_name) <= 8) and (custom_fz_name.isalnum()) and (custom_fz_name.isascii()): return { "GIT_COMMIT": commit, diff --git a/site_scons/commandline.scons b/site_scons/commandline.scons index 3e6859b4e..00781db31 100644 --- a/site_scons/commandline.scons +++ b/site_scons/commandline.scons @@ -106,6 +106,11 @@ vars.AddVariables( "Replaces OTP flipper name with custom string of 8 chars", "", ), + ( + "FORCE_NO_DIRTY", + "Force disable dirty status of the build", + "", + ), ( "COPRO_CUBE_VERSION", "Cube version", @@ -242,4 +247,4 @@ vars.AddVariables( ), ) -Return("vars") +Return("vars") \ No newline at end of file diff --git a/site_scons/environ.scons b/site_scons/environ.scons index 128a667f1..ab60d4e71 100644 --- a/site_scons/environ.scons +++ b/site_scons/environ.scons @@ -21,6 +21,7 @@ variables_to_forward = [ "WORKFLOW_BRANCH_OR_TAG", "DIST_SUFFIX", "CUSTOM_FLIPPER_NAME", + "FORCE_NO_DIRTY", # Python & other tools "HOME", "APPDATA", @@ -87,4 +88,4 @@ SetOption("max_drift", 1) wrap_tempfile(coreenv, "LINKCOM") wrap_tempfile(coreenv, "ARCOM") -Return("coreenv") +Return("coreenv") \ No newline at end of file diff --git a/site_scons/extapps.scons b/site_scons/extapps.scons index 5f6b1393f..6b6735705 100644 --- a/site_scons/extapps.scons +++ b/site_scons/extapps.scons @@ -1,4 +1,3 @@ -import os from dataclasses import dataclass, field from SCons.Node import NodeList from SCons.Warnings import warn, WarningOnByDefault @@ -110,25 +109,12 @@ if appsrc := appenv.subst("$APPSRC"): app_artifacts = appenv.GetExtAppFromPath(appsrc) appenv.PhonyTarget( "launch_app", - '${PYTHON3} "${APP_RUN_SCRIPT}" --launch "${SOURCE}" --fap_dst_dir "/ext/apps/${FAP_CATEGORY}"', + '${PYTHON3} "${APP_RUN_SCRIPT}" "${SOURCE}" --fap_dst_dir "/ext/apps/${FAP_CATEGORY}"', source=app_artifacts.compact, FAP_CATEGORY=app_artifacts.app.fap_category, ) appenv.Alias("launch_app", app_artifacts.validator) -appenv.PhonyTarget( - "faps_copy", - os.linesep.join( - [ - '${PYTHON3} "${APP_RUN_SCRIPT}"' - f' "{app_artifact.compact[0].rstr()}"' - f' --fap_dst_dir "/ext/apps/{app_artifact.app.fap_category}"' - for app_artifact in appenv["EXT_APPS"].values() - ] - ), - source=["faps"], -) - # SDK management sdk_origin_path = "${BUILD_DIR}/sdk_origin" From fe20da6a2a43045b0234e9a5b8dc8778660485b9 Mon Sep 17 00:00:00 2001 From: VerstreuteSeele Date: Mon, 16 Jan 2023 01:01:17 +0100 Subject: [PATCH 33/60] Update gui.c --- applications/services/gui/gui.c | 1 - 1 file changed, 1 deletion(-) diff --git a/applications/services/gui/gui.c b/applications/services/gui/gui.c index 37839c789..4d4ef33a2 100644 --- a/applications/services/gui/gui.c +++ b/applications/services/gui/gui.c @@ -137,7 +137,6 @@ static void gui_redraw_status_bar(Gui* gui, bool need_attention) { left_used += (width + 2); x += (width + 2); } - // Draw frame around icons on the left } static bool gui_redraw_window(Gui* gui) { From 88252eaa20a0bf86ac8dcbc9bf3947606998b68f Mon Sep 17 00:00:00 2001 From: Willy-JL Date: Sun, 15 Jan 2023 23:56:29 +0000 Subject: [PATCH 34/60] Remove ugly box --- applications/services/gui/gui.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/applications/services/gui/gui.c b/applications/services/gui/gui.c index 37839c789..f6978ff4d 100644 --- a/applications/services/gui/gui.c +++ b/applications/services/gui/gui.c @@ -86,9 +86,9 @@ static void gui_redraw_status_bar(Gui* gui, bool need_attention) { GUI_STATUS_BAR_Y + 1, width + 2, GUI_STATUS_BAR_WORKAREA_HEIGHT + 2); - canvas_set_color(gui->canvas, ColorWhite); - canvas_draw_box( - gui->canvas, 0, 0, canvas_width(gui->canvas), canvas_height(gui->canvas)); + // canvas_set_color(gui->canvas, ColorWhite); + // canvas_draw_box( + // gui->canvas, 0, 0, canvas_width(gui->canvas), canvas_height(gui->canvas)); canvas_set_color(gui->canvas, ColorBlack); // ViewPort draw canvas_frame_set( @@ -105,15 +105,15 @@ static void gui_redraw_status_bar(Gui* gui, bool need_attention) { GUI_STATUS_BAR_Y, right_used + 2, GUI_STATUS_BAR_HEIGHT); - canvas_set_color(gui->canvas, ColorBlack); - canvas_draw_rframe( - gui->canvas, 0, 0, canvas_width(gui->canvas), canvas_height(gui->canvas) - 1, 1); - canvas_draw_line( - gui->canvas, - canvas_width(gui->canvas) - 1, - 2, - canvas_width(gui->canvas) - 1, - canvas_height(gui->canvas) - 4); + // canvas_set_color(gui->canvas, ColorBlack); + // canvas_draw_rframe( + // gui->canvas, 0, 0, canvas_width(gui->canvas), canvas_height(gui->canvas) - 1, 1); + // canvas_draw_line( + // gui->canvas, + // canvas_width(gui->canvas) - 1, + // 2, + // canvas_width(gui->canvas) - 1, + // canvas_height(gui->canvas) - 4); } // Extra notification From 5802ea951def42b193438e45cb373684862c905f Mon Sep 17 00:00:00 2001 From: Willy-JL Date: Sun, 15 Jan 2023 23:57:18 +0000 Subject: [PATCH 35/60] Add tiny battery border for readability --- .../services/power/power_service/power.c | 11 +++++++++-- assets/icons/StatusBar/Battery_25x8.png | Bin 0 -> 5992 bytes assets/icons/StatusBar/Battery_26x8.png | Bin 313 -> 0 bytes 3 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 assets/icons/StatusBar/Battery_25x8.png delete mode 100644 assets/icons/StatusBar/Battery_26x8.png diff --git a/applications/services/power/power_service/power.c b/applications/services/power/power_service/power.c index 92aefbe75..76be01806 100644 --- a/applications/services/power/power_service/power.c +++ b/applications/services/power/power_service/power.c @@ -9,7 +9,14 @@ void power_draw_battery_callback(Canvas* canvas, void* context) { furi_assert(context); Power* power = context; - canvas_draw_icon(canvas, 0, 0, &I_Battery_26x8); + canvas_draw_icon(canvas, 0, 0, &I_Battery_25x8); + canvas_set_color(canvas, ColorWhite); + canvas_draw_box(canvas, -1, 0, 1, 8); + canvas_draw_box(canvas, 0, -1, 24, 1); + canvas_draw_box(canvas, 0, 8, 24, 1); + canvas_draw_box(canvas, 25, 1, 2, 6); + canvas_set_color(canvas, ColorBlack); + canvas_draw_box(canvas, 25, 2, 1, 4); if(power->info.gauge_is_ok) { char batteryPercentile[4]; @@ -168,7 +175,7 @@ void power_draw_battery_callback(Canvas* canvas, void* context) { static ViewPort* power_battery_view_port_alloc(Power* power) { ViewPort* battery_view_port = view_port_alloc(); - view_port_set_width(battery_view_port, icon_get_width(&I_Battery_26x8)); + view_port_set_width(battery_view_port, icon_get_width(&I_Battery_25x8)); view_port_draw_callback_set(battery_view_port, power_draw_battery_callback, power); gui_add_view_port(power->gui, battery_view_port, GuiLayerStatusBarRight); return battery_view_port; diff --git a/assets/icons/StatusBar/Battery_25x8.png b/assets/icons/StatusBar/Battery_25x8.png new file mode 100644 index 0000000000000000000000000000000000000000..03187dc1f3c0b270b387b402c8f312b1970cb721 GIT binary patch literal 5992 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 literal 0 HcmV?d00001 diff --git a/assets/icons/StatusBar/Battery_26x8.png b/assets/icons/StatusBar/Battery_26x8.png deleted file mode 100644 index 5fc1b0cd6d93a694ee460f7253bac4fa368285c2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 313 zcmeAS@N?(olHy`uVBq!ia0vp^Qb5eX#0(^7S+So5QY`6?zK#qG8~eHcB(ehe3dtTp zz6=aiY77hwEes65fIC7!;n>`$46IoXB1>;0Aig%mtp978y+ zCkybhHVLq?v9l>8v|MBih+^pFYgpao>z40R2Rbqy^;3@ofnEv-xpwG9lc3=G7b1=gZy$jwj5OsmAyU~B}@5No`9Do_K1 Mr>mdKI;Vst0P~nnl>h($ From bebb8a47ac5b8dc357a53d79f93cee152d91049b Mon Sep 17 00:00:00 2001 From: VerstreuteSeele Date: Mon, 16 Jan 2023 03:07:02 +0100 Subject: [PATCH 36/60] fix submenu in vertical --- applications/services/gui/modules/submenu.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/applications/services/gui/modules/submenu.c b/applications/services/gui/modules/submenu.c index 72626c587..88c1c55d4 100644 --- a/applications/services/gui/modules/submenu.c +++ b/applications/services/gui/modules/submenu.c @@ -1,4 +1,5 @@ #include "submenu.h" +#include #include #include @@ -63,7 +64,12 @@ static void submenu_view_draw_callback(Canvas* canvas, void* _model) { SubmenuModel* model = _model; const uint8_t item_height = 16; - const uint8_t item_width = 123; + uint8_t item_width = 123; + + if(canvas->orientation == CanvasOrientationVertical || + canvas->orientation == CanvasOrientationVerticalFlip) { + item_width = 60; + } canvas_clear(canvas); From 280b83c32dec021a42168a9c59940e8d283023f0 Mon Sep 17 00:00:00 2001 From: VerstreuteSeele Date: Mon, 16 Jan 2023 03:09:40 +0100 Subject: [PATCH 37/60] Add Mifare Mini, fix char type & fix sector reads in edge-cases --- firmware/targets/f7/api_symbols.csv | 4 ++-- lib/nfc/helpers/nfc_generators.c | 22 ++++++++++++++++++++++ lib/nfc/nfc_device.c | 18 ++++++++++++++---- lib/nfc/nfc_types.c | 4 +++- lib/nfc/protocols/mifare_classic.c | 29 ++++++++++++++++++++--------- lib/nfc/protocols/mifare_classic.h | 4 +++- 6 files changed, 64 insertions(+), 17 deletions(-) diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index d04c22bc9..8f47b6e31 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,12.0,, +Version,+,12.1,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -1913,7 +1913,7 @@ Function,-,mf_classic_dict_is_key_present,_Bool,"MfClassicDict*, uint8_t*" Function,-,mf_classic_dict_is_key_present_str,_Bool,"MfClassicDict*, FuriString*" Function,-,mf_classic_dict_rewind,_Bool,MfClassicDict* Function,-,mf_classic_emulator,_Bool,"MfClassicEmulator*, FuriHalNfcTxRxContext*" -Function,-,mf_classic_get_classic_type,MfClassicType,"int8_t, uint8_t, uint8_t" +Function,-,mf_classic_get_classic_type,MfClassicType,"uint8_t, uint8_t, uint8_t" Function,-,mf_classic_get_read_sectors_and_keys,void,"MfClassicData*, uint8_t*, uint8_t*" Function,-,mf_classic_get_sector_by_block,uint8_t,uint8_t Function,-,mf_classic_get_sector_trailer_block_num_by_sector,uint8_t,uint8_t diff --git a/lib/nfc/helpers/nfc_generators.c b/lib/nfc/helpers/nfc_generators.c index 769b9c7b6..590ff4d50 100644 --- a/lib/nfc/helpers/nfc_generators.c +++ b/lib/nfc/helpers/nfc_generators.c @@ -352,11 +352,27 @@ void nfc_generate_mf_classic(NfcDeviceData* data, uint8_t uid_len, MfClassicType } // Set SAK to 08 data->nfc_data.sak = 0x08; + } else if(type == MfClassicTypeMini) { + // Set every block to 0xFF + for(uint16_t i = 1; i < MF_MINI_TOTAL_SECTORS_NUM * 4; i += 1) { + if(mf_classic_is_sector_trailer(i)) { + nfc_generate_mf_classic_sector_trailer(mfc, i); + } else { + memset(&mfc->block[i].value, 0xFF, 16); + } + mf_classic_set_block_read(mfc, i, &mfc->block[i]); + } + // Set SAK to 09 + data->nfc_data.sak = 0x09; } mfc->type = type; } +static void nfc_generate_mf_mini(NfcDeviceData* data) { + nfc_generate_mf_classic(data, 4, MfClassicTypeMini); +} + static void nfc_generate_mf_classic_1k_4b_uid(NfcDeviceData* data) { nfc_generate_mf_classic(data, 4, MfClassicType1k); } @@ -438,6 +454,11 @@ static const NfcGenerator ntag_i2c_plus_2k_generator = { .generator_func = nfc_generate_ntag_i2c_plus_2k, }; +static const NfcGenerator mifare_mini_generator = { + .name = "Mifare Mini", + .generator_func = nfc_generate_mf_mini, +}; + static const NfcGenerator mifare_classic_1k_4b_uid_generator = { .name = "Mifare Classic 1k 4byte UID", .generator_func = nfc_generate_mf_classic_1k_4b_uid, @@ -472,6 +493,7 @@ const NfcGenerator* const nfc_generators[] = { &ntag_i2c_2k_generator, &ntag_i2c_plus_1k_generator, &ntag_i2c_plus_2k_generator, + &mifare_mini_generator, &mifare_classic_1k_4b_uid_generator, &mifare_classic_1k_7b_uid_generator, &mifare_classic_4k_4b_uid_generator, diff --git a/lib/nfc/nfc_device.c b/lib/nfc/nfc_device.c index 2a47ba1fd..df7688ed1 100644 --- a/lib/nfc/nfc_device.c +++ b/lib/nfc/nfc_device.c @@ -1055,7 +1055,10 @@ static bool nfc_device_save_mifare_classic_data(FlipperFormat* file, NfcDevice* do { if(!flipper_format_write_comment_cstr(file, "Mifare Classic specific data")) break; - if(data->type == MfClassicType1k) { + if(data->type == MfClassicTypeMini) { + if(!flipper_format_write_string_cstr(file, "Mifare Classic type", "MINI")) break; + blocks = 20; + } else if(data->type == MfClassicType1k) { if(!flipper_format_write_string_cstr(file, "Mifare Classic type", "1K")) break; blocks = 64; } else if(data->type == MfClassicType4k) { @@ -1153,7 +1156,10 @@ static bool nfc_device_load_mifare_classic_data(FlipperFormat* file, NfcDevice* do { // Read Mifare Classic type if(!flipper_format_read_string(file, "Mifare Classic type", temp_str)) break; - if(!furi_string_cmp(temp_str, "1K")) { + if(!furi_string_cmp(temp_str, "MINI")) { + data->type = MfClassicTypeMini; + data_blocks = 20; + } else if(!furi_string_cmp(temp_str, "1K")) { data->type = MfClassicType1k; data_blocks = 64; } else if(!furi_string_cmp(temp_str, "4K")) { @@ -1228,7 +1234,9 @@ static bool nfc_device_save_mifare_classic_keys(NfcDevice* dev) { if(!flipper_format_file_open_always(file, furi_string_get_cstr(temp_str))) break; if(!flipper_format_write_header_cstr(file, nfc_keys_file_header, nfc_keys_file_version)) break; - if(data->type == MfClassicType1k) { + if(data->type == MfClassicTypeMini) { + if(!flipper_format_write_string_cstr(file, "Mifare Classic type", "MINI")) break; + } else if(data->type == MfClassicType1k) { if(!flipper_format_write_string_cstr(file, "Mifare Classic type", "1K")) break; } else if(data->type == MfClassicType4k) { if(!flipper_format_write_string_cstr(file, "Mifare Classic type", "4K")) break; @@ -1278,7 +1286,9 @@ bool nfc_device_load_key_cache(NfcDevice* dev) { if(furi_string_cmp_str(temp_str, nfc_keys_file_header)) break; if(version != nfc_keys_file_version) break; if(!flipper_format_read_string(file, "Mifare Classic type", temp_str)) break; - if(!furi_string_cmp(temp_str, "1K")) { + if(!furi_string_cmp(temp_str, "MINI")) { + data->type = MfClassicTypeMini; + } else if(!furi_string_cmp(temp_str, "1K")) { data->type = MfClassicType1k; } else if(!furi_string_cmp(temp_str, "4K")) { data->type = MfClassicType4k; diff --git a/lib/nfc/nfc_types.c b/lib/nfc/nfc_types.c index 427628769..02ca85580 100644 --- a/lib/nfc/nfc_types.c +++ b/lib/nfc/nfc_types.c @@ -55,7 +55,9 @@ const char* nfc_mf_ul_type(MfUltralightType type, bool full_name) { } const char* nfc_mf_classic_type(MfClassicType type) { - if(type == MfClassicType1k) { + if(type == MfClassicTypeMini) { + return "Mifare Mini 0.3K"; + } else if(type == MfClassicType1k) { return "Mifare Classic 1K"; } else if(type == MfClassicType4k) { return "Mifare Classic 4K"; diff --git a/lib/nfc/protocols/mifare_classic.c b/lib/nfc/protocols/mifare_classic.c index a22617ef7..5fda122ab 100644 --- a/lib/nfc/protocols/mifare_classic.c +++ b/lib/nfc/protocols/mifare_classic.c @@ -13,7 +13,9 @@ #define MF_CLASSIC_WRITE_BLOCK_CMD (0xA0) const char* mf_classic_get_type_str(MfClassicType type) { - if(type == MfClassicType1k) { + if(type == MfClassicTypeMini) { + return "MIFARE Mini 0.3K"; + } else if(type == MfClassicType1k) { return "MIFARE Classic 1K"; } else if(type == MfClassicType4k) { return "MIFARE Classic 4K"; @@ -73,7 +75,9 @@ MfClassicSectorTrailer* } uint8_t mf_classic_get_total_sectors_num(MfClassicType type) { - if(type == MfClassicType1k) { + if(type == MfClassicTypeMini) { + return MF_MINI_TOTAL_SECTORS_NUM; + } else if(type == MfClassicType1k) { return MF_CLASSIC_1K_TOTAL_SECTORS_NUM; } else if(type == MfClassicType4k) { return MF_CLASSIC_4K_TOTAL_SECTORS_NUM; @@ -83,7 +87,9 @@ uint8_t mf_classic_get_total_sectors_num(MfClassicType type) { } uint16_t mf_classic_get_total_block_num(MfClassicType type) { - if(type == MfClassicType1k) { + if(type == MfClassicTypeMini) { + return 20; + } else if(type == MfClassicType1k) { return 64; } else if(type == MfClassicType4k) { return 256; @@ -361,10 +367,14 @@ bool mf_classic_check_card_type(uint8_t ATQA0, uint8_t ATQA1, uint8_t SAK) { } } -MfClassicType mf_classic_get_classic_type(int8_t ATQA0, uint8_t ATQA1, uint8_t SAK) { +MfClassicType mf_classic_get_classic_type(uint8_t ATQA0, uint8_t ATQA1, uint8_t SAK) { UNUSED(ATQA1); - if((ATQA0 == 0x44 || ATQA0 == 0x04) && (SAK == 0x08 || SAK == 0x88 || SAK == 0x09)) { - return MfClassicType1k; + if((ATQA0 == 0x44 || ATQA0 == 0x04)) { + if((SAK == 0x08 || SAK == 0x88)) { + return MfClassicType1k; + } else if(SAK == 0x09) { + return MfClassicTypeMini; + } } else if((ATQA0 == 0x01) && (ATQA1 == 0x0F) && (SAK == 0x01)) { //skylanders support return MfClassicType1k; @@ -589,13 +599,14 @@ void mf_classic_read_sector(FuriHalNfcTxRxContext* tx_rx, MfClassicData* data, u if(!key_a_found) break; FURI_LOG_D(TAG, "Try to read blocks with key A"); key = nfc_util_bytes2num(sec_tr->key_a, sizeof(sec_tr->key_a)); - if(!mf_classic_auth(tx_rx, start_block, key, MfClassicKeyA, &crypto, false, 0)) break; for(size_t i = start_block; i < start_block + total_blocks; i++) { if(!mf_classic_is_block_read(data, i)) { + if(!mf_classic_auth(tx_rx, i, key, MfClassicKeyA, &crypto, false, 0)) continue; if(mf_classic_read_block(tx_rx, &crypto, i, &block_tmp)) { mf_classic_set_block_read(data, i, &block_tmp); blocks_read++; } + furi_hal_nfc_sleep(); } else { blocks_read++; } @@ -607,14 +618,14 @@ void mf_classic_read_sector(FuriHalNfcTxRxContext* tx_rx, MfClassicData* data, u if(!key_b_found) break; FURI_LOG_D(TAG, "Try to read blocks with key B"); key = nfc_util_bytes2num(sec_tr->key_b, sizeof(sec_tr->key_b)); - furi_hal_nfc_sleep(); - if(!mf_classic_auth(tx_rx, start_block, key, MfClassicKeyB, &crypto, false, 0)) break; for(size_t i = start_block; i < start_block + total_blocks; i++) { if(!mf_classic_is_block_read(data, i)) { + if(!mf_classic_auth(tx_rx, i, key, MfClassicKeyB, &crypto, false, 0)) continue; if(mf_classic_read_block(tx_rx, &crypto, i, &block_tmp)) { mf_classic_set_block_read(data, i, &block_tmp); blocks_read++; } + furi_hal_nfc_sleep(); } else { blocks_read++; } diff --git a/lib/nfc/protocols/mifare_classic.h b/lib/nfc/protocols/mifare_classic.h index 74beceb62..ac5701ecf 100644 --- a/lib/nfc/protocols/mifare_classic.h +++ b/lib/nfc/protocols/mifare_classic.h @@ -8,6 +8,7 @@ #define MF_CLASSIC_TOTAL_BLOCKS_MAX (256) #define MF_CLASSIC_1K_TOTAL_SECTORS_NUM (16) #define MF_CLASSIC_4K_TOTAL_SECTORS_NUM (40) +#define MF_MINI_TOTAL_SECTORS_NUM (5) #define MF_CLASSIC_SECTORS_MAX (40) #define MF_CLASSIC_BLOCKS_IN_SECTOR_MAX (16) @@ -18,6 +19,7 @@ #define MF_CLASSIC_ACCESS_BYTES_SIZE (4) typedef enum { + MfClassicTypeMini, MfClassicType1k, MfClassicType4k, } MfClassicType; @@ -94,7 +96,7 @@ const char* mf_classic_get_type_str(MfClassicType type); bool mf_classic_check_card_type(uint8_t ATQA0, uint8_t ATQA1, uint8_t SAK); -MfClassicType mf_classic_get_classic_type(int8_t ATQA0, uint8_t ATQA1, uint8_t SAK); +MfClassicType mf_classic_get_classic_type(uint8_t ATQA0, uint8_t ATQA1, uint8_t SAK); uint8_t mf_classic_get_total_sectors_num(MfClassicType type); From fdb255a39e63dea5beae834987c98af15daa6cf1 Mon Sep 17 00:00:00 2001 From: VerstreuteSeele Date: Mon, 16 Jan 2023 03:10:05 +0100 Subject: [PATCH 38/60] Add CRC verification for paradox protocol cards --- lib/lfrfid/protocols/protocol_paradox.c | 45 ++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/lib/lfrfid/protocols/protocol_paradox.c b/lib/lfrfid/protocols/protocol_paradox.c index 7e029f1de..26c9b55dc 100644 --- a/lib/lfrfid/protocols/protocol_paradox.c +++ b/lib/lfrfid/protocols/protocol_paradox.c @@ -136,17 +136,45 @@ LevelDuration protocol_paradox_encoder_yield(ProtocolParadox* protocol) { return level_duration_make(level, duration); }; +static uint8_t protocol_paradox_calculate_checksum(uint8_t fc, uint16_t card_id) { + uint8_t card_hi = (card_id >> 8) & 0xff; + uint8_t card_lo = card_id & 0xff; + + uint8_t arr[5] = {0, 0, fc, card_hi, card_lo}; + + uint8_t manchester[9]; + + bit_lib_push_bit(manchester, 9, false); + bit_lib_push_bit(manchester, 9, false); + bit_lib_push_bit(manchester, 9, false); + bit_lib_push_bit(manchester, 9, false); + + for(uint8_t i = 6; i < 40; i += 1) { + if(bit_lib_get_bit(arr, i) == 0b1) { + bit_lib_push_bit(manchester, 9, true); + bit_lib_push_bit(manchester, 9, false); + } else { + bit_lib_push_bit(manchester, 9, false); + bit_lib_push_bit(manchester, 9, true); + } + } + + uint8_t output = bit_lib_crc8(manchester, 9, 0x31, 0x00, true, true, 0x06); + + return output; +} + void protocol_paradox_render_data(ProtocolParadox* protocol, FuriString* result) { uint8_t* decoded_data = protocol->data; uint8_t fc = bit_lib_get_bits(decoded_data, 10, 8); uint16_t card_id = bit_lib_get_bits_16(decoded_data, 18, 16); + uint8_t card_crc = bit_lib_get_bits_16(decoded_data, 34, 8); + uint8_t calc_crc = protocol_paradox_calculate_checksum(fc, card_id); furi_string_cat_printf(result, "Facility: %u\r\n", fc); furi_string_cat_printf(result, "Card: %u\r\n", card_id); - furi_string_cat_printf(result, "Data: "); - for(size_t i = 0; i < PARADOX_DECODED_DATA_SIZE; i++) { - furi_string_cat_printf(result, "%02X", decoded_data[i]); - } + furi_string_cat_printf(result, "CRC: %u Calc CRC: %u\r\n", card_crc, calc_crc); + if(card_crc != calc_crc) furi_string_cat_printf(result, "CRC Mismatch, Invalid Card!\r\n"); }; void protocol_paradox_render_brief_data(ProtocolParadox* protocol, FuriString* result) { @@ -154,8 +182,15 @@ void protocol_paradox_render_brief_data(ProtocolParadox* protocol, FuriString* r uint8_t fc = bit_lib_get_bits(decoded_data, 10, 8); uint16_t card_id = bit_lib_get_bits_16(decoded_data, 18, 16); + uint8_t card_crc = bit_lib_get_bits_16(decoded_data, 34, 8); + uint8_t calc_crc = protocol_paradox_calculate_checksum(fc, card_id); - furi_string_cat_printf(result, "FC: %03u, Card: %05u", fc, card_id); + furi_string_cat_printf(result, "FC: %03u, Card: %05u\r\n", fc, card_id); + if(calc_crc == card_crc) { + furi_string_cat_printf(result, "CRC : %03u", card_crc); + } else { + furi_string_cat_printf(result, "Card is Invalid!"); + } }; bool protocol_paradox_write_data(ProtocolParadox* protocol, void* data) { From 3da5655411af81077544503ed2525146f1caa6e6 Mon Sep 17 00:00:00 2001 From: VerstreuteSeele Date: Mon, 16 Jan 2023 03:14:31 +0100 Subject: [PATCH 39/60] Fix RAW subghz write --- lib/subghz/protocols/raw.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/subghz/protocols/raw.c b/lib/subghz/protocols/raw.c index 61a7442aa..393d7f360 100644 --- a/lib/subghz/protocols/raw.c +++ b/lib/subghz/protocols/raw.c @@ -170,6 +170,7 @@ bool subghz_protocol_raw_save_to_file_init( instance->upload_raw = malloc(SUBGHZ_DOWNLOAD_MAX_SIZE * sizeof(int32_t)); instance->file_is_open = RAWFileIsOpenWrite; instance->sample_write = 0; + instance->last_level = false; instance->pause = false; init = true; } while(0); From 8b5f24978cc18571578d010afeddf6c9bb950fae Mon Sep 17 00:00:00 2001 From: VerstreuteSeele Date: Mon, 16 Jan 2023 03:23:25 +0100 Subject: [PATCH 40/60] Short duration filter setting --- firmware/targets/f7/api_symbols.csv | 3 ++- lib/subghz/subghz_worker.c | 36 ++++++++++++++--------------- lib/subghz/subghz_worker.h | 9 ++++++++ 3 files changed, 28 insertions(+), 20 deletions(-) diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index 8f47b6e31..aaeb0b8a7 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,12.1,, +Version,+,12.2,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -3190,6 +3190,7 @@ Function,+,subghz_worker_free,void,SubGhzWorker* Function,+,subghz_worker_is_running,_Bool,SubGhzWorker* Function,+,subghz_worker_rx_callback,void,"_Bool, uint32_t, void*" Function,+,subghz_worker_set_context,void,"SubGhzWorker*, void*" +Function,+,subghz_worker_set_filter,void,"SubGhzWorker*, uint16_t" Function,+,subghz_worker_set_overrun_callback,void,"SubGhzWorker*, SubGhzWorkerOverrunCallback" Function,+,subghz_worker_set_pair_callback,void,"SubGhzWorker*, SubGhzWorkerPairCallback" Function,+,subghz_worker_start,void,SubGhzWorker* diff --git a/lib/subghz/subghz_worker.c b/lib/subghz/subghz_worker.c index 35e399885..50b5aba51 100644 --- a/lib/subghz/subghz_worker.c +++ b/lib/subghz/subghz_worker.c @@ -12,7 +12,6 @@ struct SubGhzWorker { volatile bool overrun; LevelDuration filter_level_duration; - bool filter_running; uint16_t filter_duration; SubGhzWorkerOverrunCallback overrun_callback; @@ -59,24 +58,19 @@ static int32_t subghz_worker_thread_callback(void* context) { bool level = level_duration_get_level(level_duration); uint32_t duration = level_duration_get_duration(level_duration); - if(instance->filter_running) { - if((duration < instance->filter_duration) || - (instance->filter_level_duration.level == level)) { - instance->filter_level_duration.duration += duration; + if((duration < instance->filter_duration) || + (instance->filter_level_duration.level == level)) { + instance->filter_level_duration.duration += duration; - } else if(instance->filter_level_duration.level != level) { - if(instance->pair_callback) - instance->pair_callback( - instance->context, - instance->filter_level_duration.level, - instance->filter_level_duration.duration); - - instance->filter_level_duration.duration = duration; - instance->filter_level_duration.level = level; - } - } else { + } else if(instance->filter_level_duration.level != level) { if(instance->pair_callback) - instance->pair_callback(instance->context, level, duration); + instance->pair_callback( + instance->context, + instance->filter_level_duration.level, + instance->filter_level_duration.duration); + + instance->filter_level_duration.duration = duration; + instance->filter_level_duration.level = level; } } } @@ -94,8 +88,7 @@ SubGhzWorker* subghz_worker_alloc() { instance->stream = furi_stream_buffer_alloc(sizeof(LevelDuration) * 4096, sizeof(LevelDuration)); - //setting filter - instance->filter_running = true; + //setting default filter in us instance->filter_duration = 30; return instance; @@ -149,3 +142,8 @@ bool subghz_worker_is_running(SubGhzWorker* instance) { furi_assert(instance); return instance->running; } + +void subghz_worker_set_filter(SubGhzWorker* instance, uint16_t timeout) { + furi_assert(instance); + instance->filter_duration = timeout; +} \ No newline at end of file diff --git a/lib/subghz/subghz_worker.h b/lib/subghz/subghz_worker.h index f85b1fdc7..220c6aeb5 100644 --- a/lib/subghz/subghz_worker.h +++ b/lib/subghz/subghz_worker.h @@ -67,6 +67,15 @@ void subghz_worker_stop(SubGhzWorker* instance); */ bool subghz_worker_is_running(SubGhzWorker* instance); +/** + * Short duration filter setting. + * glues short durations into 1. The default setting is 30 us, if set to 0 the filter will be disabled + * @param instance Pointer to a SubGhzWorker instance + * @param timeout time in us + */ +void subghz_worker_set_filter(SubGhzWorker* instance, uint16_t timeout); + + #ifdef __cplusplus } #endif From 948b9523080bb4406bb69ad779d0fd80a82d28de Mon Sep 17 00:00:00 2001 From: VerstreuteSeele Date: Mon, 16 Jan 2023 03:25:53 +0100 Subject: [PATCH 41/60] PVS Studio acknowledgement --- ReadMe.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ReadMe.md b/ReadMe.md index b28b14c20..fdd4b3bf0 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -148,5 +148,12 @@ $ ./fbt resources icons dolphin_ext

+---- +## SAST Tools + +This helps us a lot, thanks for the free license for this project! + +[PVS-Studio](https://pvs-studio.com/en/pvs-studio/?utm_source=github&utm_medium=organic&utm_campaign=open_source) - static analyzer for C, C++, C#, and Java code. + ----

"What we do for ourselves dies with us. What we do for others and the world remains and is immortal.” ― Albert Pike

From 35befd07c4fa92890de3629aa07c68bd6b964518 Mon Sep 17 00:00:00 2001 From: VerstreuteSeele Date: Mon, 16 Jan 2023 04:29:26 +0100 Subject: [PATCH 42/60] Remove "Flipper" from BT name + formatting --- applications/services/dolphin/helpers/dolphin_state.c | 2 +- applications/settings/dolphin_passport/passport.c | 7 ++++--- firmware/targets/f7/furi_hal/furi_hal_version.c | 7 +++++-- lib/subghz/subghz_worker.h | 1 - 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/applications/services/dolphin/helpers/dolphin_state.c b/applications/services/dolphin/helpers/dolphin_state.c index cd2bd9cd7..e0e5dbe60 100644 --- a/applications/services/dolphin/helpers/dolphin_state.c +++ b/applications/services/dolphin/helpers/dolphin_state.c @@ -101,7 +101,7 @@ uint8_t dolphin_get_level(int icounter) { uint32_t dolphin_state_xp_above_last_levelup(int icounter) { for(int i = 1; i < 29; ++i) { - if (icounter <= level_array[i]) { + if(icounter <= level_array[i]) { return icounter - level_array[i - 1]; } } diff --git a/applications/settings/dolphin_passport/passport.c b/applications/settings/dolphin_passport/passport.c index 6de7c3502..914f7ef0e 100644 --- a/applications/settings/dolphin_passport/passport.c +++ b/applications/settings/dolphin_passport/passport.c @@ -100,7 +100,7 @@ static void render_callback(Canvas* canvas, void* _ctx) { if(stats->level == 30) { xp_progress = 0; } else { - if (ctx->progress_total) { + if(ctx->progress_total) { xp_progress = stats->icounter * 64 / xp_next_level; } else { xp_progress = xp_to_levelup * 64 / xp_for_current_level; @@ -125,7 +125,7 @@ static void render_callback(Canvas* canvas, void* _ctx) { const char* my_name = furi_hal_version_get_name_ptr(); snprintf(level_str, 12, "Level: %hu", stats->level); - if (ctx->progress_total) { + if(ctx->progress_total) { snprintf(xp_str, 12, "%lu/%lu", stats->icounter, xp_next_level); } else { snprintf(xp_str, 12, "%lu/%lu", xp_above_last_levelup, xp_for_current_level); @@ -145,7 +145,8 @@ static void render_callback(Canvas* canvas, void* _ctx) { canvas_set_color(canvas, ColorBlack); canvas_draw_icon(canvas, 52, 51, &I_Ok_btn_9x9); - canvas_draw_str(canvas, ctx->progress_total ? 37 : 36, 59, ctx->progress_total ? "Lvl" : "Tot"); + canvas_draw_str( + canvas, ctx->progress_total ? 37 : 36, 59, ctx->progress_total ? "Lvl" : "Tot"); free(settings); } diff --git a/firmware/targets/f7/furi_hal/furi_hal_version.c b/firmware/targets/f7/furi_hal/furi_hal_version.c index e59cbd040..418dda10a 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_version.c +++ b/firmware/targets/f7/furi_hal/furi_hal_version.c @@ -94,7 +94,10 @@ void furi_hal_version_set_custom_name(const char* name) { if((name != NULL) && ((strlen(name) >= 1) && (strlen(name) <= 8))) { strlcpy(furi_hal_version.name, name, FURI_HAL_VERSION_ARRAY_NAME_LENGTH); snprintf( - furi_hal_version.device_name, FURI_HAL_VERSION_DEVICE_NAME_LENGTH, "xFlipper %s", name); + furi_hal_version.device_name, + FURI_HAL_VERSION_DEVICE_NAME_LENGTH, + "x%s", // Someone tell me why that X is needed + name); furi_hal_version.device_name[0] = AD_TYPE_COMPLETE_LOCAL_NAME; } @@ -106,7 +109,7 @@ static void furi_hal_version_set_name(const char* name) { snprintf( furi_hal_version.device_name, FURI_HAL_VERSION_DEVICE_NAME_LENGTH, - "xFlipper %s", + "x%s", // Someone tell me why that X is needed furi_hal_version.name); } else { snprintf(furi_hal_version.device_name, FURI_HAL_VERSION_DEVICE_NAME_LENGTH, "xFlipper"); diff --git a/lib/subghz/subghz_worker.h b/lib/subghz/subghz_worker.h index 220c6aeb5..657278f50 100644 --- a/lib/subghz/subghz_worker.h +++ b/lib/subghz/subghz_worker.h @@ -75,7 +75,6 @@ bool subghz_worker_is_running(SubGhzWorker* instance); */ void subghz_worker_set_filter(SubGhzWorker* instance, uint16_t timeout); - #ifdef __cplusplus } #endif From debd850ccd8f3c372afb5d6c3e7726403d5b722b Mon Sep 17 00:00:00 2001 From: jbohack Date: Sun, 15 Jan 2023 22:54:39 -0500 Subject: [PATCH 43/60] updated protoview --- applications/plugins/protoview/README.md | 3 +- applications/plugins/protoview/app.c | 124 ++++---- applications/plugins/protoview/app.h | 121 +++---- applications/plugins/protoview/app_buffer.c | 45 ++- applications/plugins/protoview/app_buffer.h | 28 +- applications/plugins/protoview/app_subghz.c | 45 +-- applications/plugins/protoview/crc.c | 9 +- .../plugins/protoview/custom_presets.h | 77 ++++- applications/plugins/protoview/data_feed.c | 17 +- .../plugins/protoview/protocols/b4b1.c | 35 +- .../protoview/protocols/citroen_tpms.c | 72 ----- .../plugins/protoview/protocols/ford_tpms.c | 76 ----- .../plugins/protoview/protocols/keeloq.c | 87 +++++ .../plugins/protoview/protocols/oregon2.c | 98 +++--- .../plugins/protoview/protocols/oregon2.txt | 6 - .../protoview/protocols/renault_tpms.c | 71 ----- .../protoview/protocols/schrader_tpms.c | 78 ----- .../plugins/protoview/protocols/toyota_tpms.c | 84 ----- .../protoview/protocols/tpms/citroen.c | 60 ++++ .../plugins/protoview/protocols/tpms/ford.c | 64 ++++ .../protoview/protocols/tpms/renault.c | 66 ++++ .../protoview/protocols/tpms/schrader.c | 65 ++++ .../protocols/tpms/schrader_eg53ma4.c | 63 ++++ .../plugins/protoview/protocols/tpms/toyota.c | 77 +++++ applications/plugins/protoview/signal.c | 298 ++++++++---------- applications/plugins/protoview/ui.c | 28 +- .../plugins/protoview/view_direct_sampling.c | 45 +-- applications/plugins/protoview/view_info.c | 28 +- .../plugins/protoview/view_raw_signal.c | 57 ++-- .../plugins/protoview/view_settings.c | 74 +++-- 30 files changed, 1046 insertions(+), 955 deletions(-) delete mode 100644 applications/plugins/protoview/protocols/citroen_tpms.c delete mode 100644 applications/plugins/protoview/protocols/ford_tpms.c create mode 100644 applications/plugins/protoview/protocols/keeloq.c delete mode 100644 applications/plugins/protoview/protocols/oregon2.txt delete mode 100644 applications/plugins/protoview/protocols/renault_tpms.c delete mode 100644 applications/plugins/protoview/protocols/schrader_tpms.c delete mode 100644 applications/plugins/protoview/protocols/toyota_tpms.c create mode 100644 applications/plugins/protoview/protocols/tpms/citroen.c create mode 100644 applications/plugins/protoview/protocols/tpms/ford.c create mode 100644 applications/plugins/protoview/protocols/tpms/renault.c create mode 100644 applications/plugins/protoview/protocols/tpms/schrader.c create mode 100644 applications/plugins/protoview/protocols/tpms/schrader_eg53ma4.c create mode 100644 applications/plugins/protoview/protocols/tpms/toyota.c diff --git a/applications/plugins/protoview/README.md b/applications/plugins/protoview/README.md index 8359c073d..a12aec979 100644 --- a/applications/plugins/protoview/README.md +++ b/applications/plugins/protoview/README.md @@ -14,8 +14,9 @@ and if the selected modulation is correct. Other than that, ProtoView is able to decode a few interesting protocols: * TPMS sensors: Renault, Toyota, Schrader, Citroen, Ford. +* Microchip HSC200/300/301 Keeloq protocol. * Oregon thermometer protocol 2. -* PTxxxx/SCxxxx based remotes. +* PT2262, SC5262 based remotes. * ... more will be implemented soon, hopefully. Send PRs :) ![ProtoView screenshot Renault TPMS data](/images/protoview_2.jpg) diff --git a/applications/plugins/protoview/app.c b/applications/plugins/protoview/app.c index 3f9c7ced1..ea4e366b8 100644 --- a/applications/plugins/protoview/app.c +++ b/applications/plugins/protoview/app.c @@ -40,8 +40,8 @@ extern const SubGhzProtocolRegistry protoview_protocol_registry; /* The callback actually just passes the control to the actual active * view callback, after setting up basic stuff like cleaning the screen * and setting color to black. */ -static void render_callback(Canvas* const canvas, void* ctx) { - ProtoViewApp* app = ctx; +static void render_callback(Canvas *const canvas, void *ctx) { + ProtoViewApp *app = ctx; /* Clear screen. */ canvas_set_color(canvas, ColorWhite); @@ -51,63 +51,56 @@ static void render_callback(Canvas* const canvas, void* ctx) { /* Call who is in charge right now. */ switch(app->current_view) { - case ViewRawPulses: - render_view_raw_pulses(canvas, app); - break; - case ViewInfo: - render_view_info(canvas, app); - break; + case ViewRawPulses: render_view_raw_pulses(canvas,app); break; + case ViewInfo: render_view_info(canvas,app); break; case ViewFrequencySettings: case ViewModulationSettings: - render_view_settings(canvas, app); - break; - case ViewDirectSampling: - render_view_direct_sampling(canvas, app); - break; - case ViewLast: - furi_crash(TAG " ViewLast selected"); - break; + render_view_settings(canvas,app); break; + case ViewDirectSampling: render_view_direct_sampling(canvas,app); break; + case ViewLast: furi_crash(TAG " ViewLast selected"); break; } } /* Here all we do is putting the events into the queue that will be handled * in the while() loop of the app entry point function. */ -static void input_callback(InputEvent* input_event, void* ctx) { - ProtoViewApp* app = ctx; - furi_message_queue_put(app->event_queue, input_event, FuriWaitForever); +static void input_callback(InputEvent* input_event, void* ctx) +{ + ProtoViewApp *app = ctx; + furi_message_queue_put(app->event_queue,input_event,FuriWaitForever); } + /* Called to switch view (when left/right is pressed). Handles * changing the current view ID and calling the enter/exit view * callbacks if needed. */ -static void app_switch_view(ProtoViewApp* app, SwitchViewDirection dir) { +static void app_switch_view(ProtoViewApp *app, SwitchViewDirection dir) { ProtoViewCurrentView old = app->current_view; - if(dir == AppNextView) { + if (dir == AppNextView) { app->current_view++; - if(app->current_view == ViewLast) app->current_view = 0; - } else if(dir == AppPrevView) { - if(app->current_view == 0) - app->current_view = ViewLast - 1; + if (app->current_view == ViewLast) app->current_view = 0; + } else if (dir == AppPrevView) { + if (app->current_view == 0) + app->current_view = ViewLast-1; else app->current_view--; } ProtoViewCurrentView new = app->current_view; /* Call the enter/exit view callbacks if needed. */ - if(old == ViewDirectSampling) view_exit_direct_sampling(app); - if(new == ViewDirectSampling) view_enter_direct_sampling(app); + if (old == ViewDirectSampling) view_exit_direct_sampling(app); + if (new == ViewDirectSampling) view_enter_direct_sampling(app); /* The frequency/modulation settings are actually a single view: * as long as the user stays between the two modes of this view we * don't need to call the exit-view callback. */ - if((old == ViewFrequencySettings && new != ViewModulationSettings) || - (old == ViewModulationSettings && new != ViewFrequencySettings)) + if ((old == ViewFrequencySettings && new != ViewModulationSettings) || + (old == ViewModulationSettings && new != ViewFrequencySettings)) view_exit_settings(app); } /* Allocate the application state and initialize a number of stuff. * This is called in the entry point to create the application state. */ ProtoViewApp* protoview_app_alloc() { - ProtoViewApp* app = malloc(sizeof(ProtoViewApp)); + ProtoViewApp *app = malloc(sizeof(ProtoViewApp)); // Init shared data structures RawSamples = raw_samples_alloc(); @@ -149,14 +142,17 @@ ProtoViewApp* protoview_app_alloc() { app->txrx->environment = subghz_environment_alloc(); subghz_environment_set_protocol_registry( app->txrx->environment, (void*)&protoview_protocol_registry); - app->txrx->receiver = subghz_receiver_alloc_init(app->txrx->environment); - subghz_receiver_set_filter(app->txrx->receiver, SubGhzProtocolFlag_Decodable); + app->txrx->receiver = + subghz_receiver_alloc_init(app->txrx->environment); + subghz_receiver_set_filter(app->txrx->receiver, + SubGhzProtocolFlag_Decodable); subghz_worker_set_overrun_callback( - app->txrx->worker, (SubGhzWorkerOverrunCallback)subghz_receiver_reset); + app->txrx->worker, + (SubGhzWorkerOverrunCallback)subghz_receiver_reset); subghz_worker_set_pair_callback( app->txrx->worker, (SubGhzWorkerPairCallback)subghz_receiver_decode); subghz_worker_set_context(app->txrx->worker, app->txrx->receiver); - + app->frequency = subghz_setting_get_default_frequency(app->setting); app->modulation = 0; /* Defaults to ProtoViewModulations[0]. */ @@ -169,7 +165,7 @@ ProtoViewApp* protoview_app_alloc() { /* Free what the application allocated. It is not clear to me if the * Flipper OS, once the application exits, will be able to reclaim space * even if we forget to free something here. */ -void protoview_app_free(ProtoViewApp* app) { +void protoview_app_free(ProtoViewApp *app) { furi_assert(app); // Put CC1101 on sleep. @@ -187,7 +183,7 @@ void protoview_app_free(ProtoViewApp* app) { subghz_setting_free(app->setting); // Worker stuff. - if(!app->txrx->debug_timer_sampling) { + if (!app->txrx->debug_timer_sampling) { subghz_receiver_free(app->txrx->receiver); subghz_environment_free(app->txrx->environment); subghz_worker_free(app->txrx->worker); @@ -205,8 +201,8 @@ void protoview_app_free(ProtoViewApp* app) { /* Called periodically. Do signal processing here. Data we process here * will be later displayed by the render callback. The side effect of this * function is to scan for signals and set DetectedSamples. */ -static void timer_callback(void* ctx) { - ProtoViewApp* app = ctx; +static void timer_callback(void *ctx) { + ProtoViewApp *app = ctx; uint32_t delta, lastidx = app->signal_last_scan_idx; /* scan_for_signal(), called by this function, deals with a @@ -214,22 +210,22 @@ static void timer_callback(void* ctx) { * cross-boundaries, it is enough if we scan each time the buffer fills * for 50% more compared to the last scan. Thanks to this check we * can avoid scanning too many times to just find the same data. */ - if(lastidx < RawSamples->idx) { + if (lastidx < RawSamples->idx) { delta = RawSamples->idx - lastidx; } else { delta = RawSamples->total - lastidx + RawSamples->idx; } - if(delta < RawSamples->total / 2) return; + if (delta < RawSamples->total/2) return; app->signal_last_scan_idx = RawSamples->idx; scan_for_signal(app); } int32_t protoview_app_entry(void* p) { UNUSED(p); - ProtoViewApp* app = protoview_app_alloc(); + ProtoViewApp *app = protoview_app_alloc(); /* Create a timer. We do data analysis in the callback. */ - FuriTimer* timer = furi_timer_alloc(timer_callback, FuriTimerTypePeriodic, app); + FuriTimer *timer = furi_timer_alloc(timer_callback, FuriTimerTypePeriodic, app); furi_timer_start(timer, furi_kernel_get_tick_frequency() / 8); /* Start listening to signals immediately. */ @@ -244,57 +240,60 @@ int32_t protoview_app_entry(void* p) { InputEvent input; while(app->running) { FuriStatus qstat = furi_message_queue_get(app->event_queue, &input, 100); - if(qstat == FuriStatusOk) { - if(DEBUG_MSG) - FURI_LOG_E(TAG, "Main Loop - Input: type %d key %u", input.type, input.key); + if (qstat == FuriStatusOk) { + if (DEBUG_MSG) FURI_LOG_E(TAG, "Main Loop - Input: type %d key %u", + input.type, input.key); /* Handle navigation here. Then handle view-specific inputs * in the view specific handling function. */ - if(input.type == InputTypeShort && input.key == InputKeyBack) { + if (input.type == InputTypeShort && + input.key == InputKeyBack) + { /* Exit the app. */ app->running = 0; - } else if(input.type == InputTypeShort && input.key == InputKeyRight) { + } else if (input.type == InputTypeShort && + input.key == InputKeyRight) + { /* Go to the next view. */ - app_switch_view(app, AppNextView); - } else if(input.type == InputTypeShort && input.key == InputKeyLeft) { + app_switch_view(app,AppNextView); + } else if (input.type == InputTypeShort && + input.key == InputKeyLeft) + { /* Go to the previous view. */ - app_switch_view(app, AppPrevView); + app_switch_view(app,AppPrevView); } else { /* This is where we pass the control to the currently * active view input processing. */ switch(app->current_view) { case ViewRawPulses: - process_input_raw_pulses(app, input); + process_input_raw_pulses(app,input); break; case ViewInfo: - process_input_info(app, input); + process_input_info(app,input); break; case ViewFrequencySettings: case ViewModulationSettings: - process_input_settings(app, input); + process_input_settings(app,input); break; case ViewDirectSampling: - process_input_direct_sampling(app, input); - break; - case ViewLast: - furi_crash(TAG " ViewLast selected"); + process_input_direct_sampling(app,input); break; + case ViewLast: furi_crash(TAG " ViewLast selected"); break; } } } else { /* Useful to understand if the app is still alive when it * does not respond because of bugs. */ - if(DEBUG_MSG) { - static int c = 0; - c++; - if(!(c % 20)) FURI_LOG_E(TAG, "Loop timeout"); + if (DEBUG_MSG) { + static int c = 0; c++; + if (!(c % 20)) FURI_LOG_E(TAG, "Loop timeout"); } } view_port_update(app->view_port); } /* App no longer running. Shut down and free. */ - if(app->txrx->txrx_state == TxRxStateRx) { + if (app->txrx->txrx_state == TxRxStateRx) { FURI_LOG_E(TAG, "Putting CC1101 to sleep before exiting."); radio_rx_end(app); radio_sleep(app); @@ -304,3 +303,4 @@ int32_t protoview_app_entry(void* p) { protoview_app_free(app); return 0; } + diff --git a/applications/plugins/protoview/app.h b/applications/plugins/protoview/app.h index 735515cd9..52b0bff5b 100644 --- a/applications/plugins/protoview/app.h +++ b/applications/plugins/protoview/app.h @@ -48,12 +48,15 @@ typedef enum { } ProtoViewCurrentView; /* Used by app_switch_view() */ -typedef enum { AppNextView, AppPrevView } SwitchViewDirection; +typedef enum { + AppNextView, + AppPrevView +} SwitchViewDirection; typedef struct { - const char* name; + const char *name; FuriHalSubGhzPreset preset; - uint8_t* custom; + uint8_t *custom; } ProtoViewModulation; extern ProtoViewModulation ProtoViewModulations[]; /* In app_subghz.c */ @@ -62,19 +65,19 @@ extern ProtoViewModulation ProtoViewModulations[]; /* In app_subghz.c */ * It receives data and we get our protocol "feed" callback called * with the level (1 or 0) and duration. */ struct ProtoViewTxRx { - bool freq_mod_changed; /* The user changed frequency and/or modulation + bool freq_mod_changed; /* The user changed frequency and/or modulation from the interface. There is to restart the radio with the right parameters. */ - SubGhzWorker* worker; /* Our background worker. */ + SubGhzWorker* worker; /* Our background worker. */ SubGhzEnvironment* environment; SubGhzReceiver* receiver; TxRxState txrx_state; /* Receiving, idle or sleeping? */ /* Timer sampling mode state. */ - bool debug_timer_sampling; /* Read data from GDO0 in a busy loop. Only + bool debug_timer_sampling; /* Read data from GDO0 in a busy loop. Only for testing. */ uint32_t last_g0_change_time; /* Last high->low (or reverse) switch. */ - bool last_g0_value; /* Current value (high or low): we are + bool last_g0_value; /* Current value (high or low): we are checking the duration in the timer handler. */ }; @@ -94,43 +97,43 @@ typedef struct ProtoViewMsgInfo { char info2[PROTOVIEW_MSG_STR_LEN]; /* Protocol specific info line 2. */ char info3[PROTOVIEW_MSG_STR_LEN]; /* Protocol specific info line 3. */ char info4[PROTOVIEW_MSG_STR_LEN]; /* Protocol specific info line 4. */ - uint64_t len; /* Bits consumed from the stream. */ + uint64_t len; /* Bits consumed from the stream. */ } ProtoViewMsgInfo; struct ProtoViewApp { /* GUI */ - Gui* gui; - ViewPort* view_port; /* We just use a raw viewport and we render + Gui *gui; + ViewPort *view_port; /* We just use a raw viewport and we render everything into the low level canvas. */ - ProtoViewCurrentView current_view; /* Active view ID. */ - FuriMessageQueue* event_queue; /* Keypress events go here. */ + ProtoViewCurrentView current_view; /* Active view ID. */ + FuriMessageQueue *event_queue; /* Keypress events go here. */ /* Radio related. */ - ProtoViewTxRx* txrx; /* Radio state. */ - SubGhzSetting* setting; /* A list of valid frequencies. */ + ProtoViewTxRx *txrx; /* Radio state. */ + SubGhzSetting *setting; /* A list of valid frequencies. */ /* Generic app state. */ - int running; /* Once false exists the app. */ + int running; /* Once false exists the app. */ uint32_t signal_bestlen; /* Longest coherent signal observed so far. */ uint32_t signal_last_scan_idx; /* Index of the buffer last time we performed the scan. */ - bool signal_decoded; /* Was the current signal decoded? */ + bool signal_decoded; /* Was the current signal decoded? */ ProtoViewMsgInfo signal_info; /* Decoded message, if signal_decoded true. */ bool direct_sampling_enabled; /* This special view needs an explicit acknowledge to work. */ /* Raw view apps state. */ - uint32_t us_scale; /* microseconds per pixel. */ - uint32_t signal_offset; /* Long press left/right panning in raw view. */ + uint32_t us_scale; /* microseconds per pixel. */ + uint32_t signal_offset; /* Long press left/right panning in raw view. */ /* Configuration view app state. */ - uint32_t frequency; /* Current frequency. */ - uint8_t modulation; /* Current modulation ID, array index in the + uint32_t frequency; /* Current frequency. */ + uint8_t modulation; /* Current modulation ID, array index in the ProtoViewModulations table. */ }; typedef struct ProtoViewDecoder { - const char* name; /* Protocol name. */ + const char *name; /* Protocol name. */ /* The decode function takes a buffer that is actually a bitmap, with * high and low levels represented as 0 and 1. The number of high/low * pulses represented by the bitmap is passed as the 'numbits' argument, @@ -138,7 +141,7 @@ typedef struct ProtoViewDecoder { * 'bits'. So 'numbytes' is mainly useful to pass as argument to other * functions that perform bit extraction with bound checking, such as * bitmap_get() and so forth. */ - bool (*decode)(uint8_t* bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo* info); + bool (*decode)(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo *info); } ProtoViewDecoder; extern RawSamplesBuffer *RawSamples, *DetectedSamples; @@ -149,61 +152,37 @@ uint32_t radio_rx(ProtoViewApp* app); void radio_idle(ProtoViewApp* app); void radio_rx_end(ProtoViewApp* app); void radio_sleep(ProtoViewApp* app); -void raw_sampling_worker_start(ProtoViewApp* app); -void raw_sampling_worker_stop(ProtoViewApp* app); +void raw_sampling_worker_start(ProtoViewApp *app); +void raw_sampling_worker_stop(ProtoViewApp *app); /* signal.c */ uint32_t duration_delta(uint32_t a, uint32_t b); -void reset_current_signal(ProtoViewApp* app); -void scan_for_signal(ProtoViewApp* app); -bool bitmap_get(uint8_t* b, uint32_t blen, uint32_t bitpos); -void bitmap_set(uint8_t* b, uint32_t blen, uint32_t bitpos, bool val); -void bitmap_set_pattern(uint8_t* b, uint32_t blen, const char* pat); -void bitmap_invert_bytes_bits(uint8_t* p, uint32_t len); -bool bitmap_match_bits(uint8_t* b, uint32_t blen, uint32_t bitpos, const char* bits); -uint32_t bitmap_seek_bits( - uint8_t* b, - uint32_t blen, - uint32_t startpos, - uint32_t maxbits, - const char* bits); -uint32_t convert_from_line_code( - uint8_t* buf, - uint64_t buflen, - uint8_t* bits, - uint32_t len, - uint32_t offset, - const char* zero_pattern, - const char* one_pattern); -uint32_t convert_from_diff_manchester( - uint8_t* buf, - uint64_t buflen, - uint8_t* bits, - uint32_t len, - uint32_t off, - bool previous); +void reset_current_signal(ProtoViewApp *app); +void scan_for_signal(ProtoViewApp *app); +bool bitmap_get(uint8_t *b, uint32_t blen, uint32_t bitpos); +void bitmap_set(uint8_t *b, uint32_t blen, uint32_t bitpos, bool val); +void bitmap_set_pattern(uint8_t *b, uint32_t blen, const char *pat); +void bitmap_reverse_bytes(uint8_t *p, uint32_t len); +bool bitmap_match_bits(uint8_t *b, uint32_t blen, uint32_t bitpos, const char *bits); +uint32_t bitmap_seek_bits(uint8_t *b, uint32_t blen, uint32_t startpos, uint32_t maxbits, const char *bits); +uint32_t convert_from_line_code(uint8_t *buf, uint64_t buflen, uint8_t *bits, uint32_t len, uint32_t offset, const char *zero_pattern, const char *one_pattern); +uint32_t convert_from_diff_manchester(uint8_t *buf, uint64_t buflen, uint8_t *bits, uint32_t len, uint32_t off, bool previous); /* view_*.c */ -void render_view_raw_pulses(Canvas* const canvas, ProtoViewApp* app); -void process_input_raw_pulses(ProtoViewApp* app, InputEvent input); -void render_view_settings(Canvas* const canvas, ProtoViewApp* app); -void process_input_settings(ProtoViewApp* app, InputEvent input); -void render_view_info(Canvas* const canvas, ProtoViewApp* app); -void process_input_info(ProtoViewApp* app, InputEvent input); -void render_view_direct_sampling(Canvas* const canvas, ProtoViewApp* app); -void process_input_direct_sampling(ProtoViewApp* app, InputEvent input); -void view_enter_direct_sampling(ProtoViewApp* app); -void view_exit_direct_sampling(ProtoViewApp* app); -void view_exit_settings(ProtoViewApp* app); +void render_view_raw_pulses(Canvas *const canvas, ProtoViewApp *app); +void process_input_raw_pulses(ProtoViewApp *app, InputEvent input); +void render_view_settings(Canvas *const canvas, ProtoViewApp *app); +void process_input_settings(ProtoViewApp *app, InputEvent input); +void render_view_info(Canvas *const canvas, ProtoViewApp *app); +void process_input_info(ProtoViewApp *app, InputEvent input); +void render_view_direct_sampling(Canvas *const canvas, ProtoViewApp *app); +void process_input_direct_sampling(ProtoViewApp *app, InputEvent input); +void view_enter_direct_sampling(ProtoViewApp *app); +void view_exit_direct_sampling(ProtoViewApp *app); +void view_exit_settings(ProtoViewApp *app); /* ui.c */ -void canvas_draw_str_with_border( - Canvas* canvas, - uint8_t x, - uint8_t y, - const char* str, - Color text_color, - Color border_color); +void canvas_draw_str_with_border(Canvas* canvas, uint8_t x, uint8_t y, const char* str, Color text_color, Color border_color); /* crc.c */ -uint8_t crc8(const uint8_t* data, size_t len, uint8_t init, uint8_t poly); +uint8_t crc8(const uint8_t *data, size_t len, uint8_t init, uint8_t poly); diff --git a/applications/plugins/protoview/app_buffer.c b/applications/plugins/protoview/app_buffer.c index 3954587a4..7c069fd91 100644 --- a/applications/plugins/protoview/app_buffer.c +++ b/applications/plugins/protoview/app_buffer.c @@ -8,15 +8,15 @@ #include "app_buffer.h" /* Allocate and initialize a samples buffer. */ -RawSamplesBuffer* raw_samples_alloc(void) { - RawSamplesBuffer* buf = malloc(sizeof(*buf)); +RawSamplesBuffer *raw_samples_alloc(void) { + RawSamplesBuffer *buf = malloc(sizeof(*buf)); buf->mutex = furi_mutex_alloc(FuriMutexTypeNormal); raw_samples_reset(buf); return buf; } /* Free a sample buffer. Should be called when the mutex is released. */ -void raw_samples_free(RawSamplesBuffer* s) { +void raw_samples_free(RawSamplesBuffer *s) { furi_mutex_free(s->mutex); free(s); } @@ -24,49 +24,48 @@ void raw_samples_free(RawSamplesBuffer* s) { /* This just set all the samples to zero and also resets the internal * index. There is no need to call it after raw_samples_alloc(), but only * when one wants to reset the whole buffer of samples. */ -void raw_samples_reset(RawSamplesBuffer* s) { - furi_mutex_acquire(s->mutex, FuriWaitForever); +void raw_samples_reset(RawSamplesBuffer *s) { + furi_mutex_acquire(s->mutex,FuriWaitForever); s->total = RAW_SAMPLES_NUM; s->idx = 0; s->short_pulse_dur = 0; - memset(s->level, 0, sizeof(s->level)); - memset(s->dur, 0, sizeof(s->dur)); + memset(s->samples,0,sizeof(s->samples)); furi_mutex_release(s->mutex); } /* Set the raw sample internal index so that what is currently at * offset 'offset', will appear to be at 0 index. */ -void raw_samples_center(RawSamplesBuffer* s, uint32_t offset) { - s->idx = (s->idx + offset) % RAW_SAMPLES_NUM; +void raw_samples_center(RawSamplesBuffer *s, uint32_t offset) { + s->idx = (s->idx+offset) % RAW_SAMPLES_NUM; } /* Add the specified sample in the circular buffer. */ -void raw_samples_add(RawSamplesBuffer* s, bool level, uint32_t dur) { - furi_mutex_acquire(s->mutex, FuriWaitForever); - s->level[s->idx] = level; - s->dur[s->idx] = dur; - s->idx = (s->idx + 1) % RAW_SAMPLES_NUM; +void raw_samples_add(RawSamplesBuffer *s, bool level, uint32_t dur) { + furi_mutex_acquire(s->mutex,FuriWaitForever); + s->samples[s->idx].level = level; + s->samples[s->idx].dur = dur; + s->idx = (s->idx+1) % RAW_SAMPLES_NUM; furi_mutex_release(s->mutex); } /* Get the sample from the buffer. It is possible to use out of range indexes * as 'idx' because the modulo operation will rewind back from the start. */ -void raw_samples_get(RawSamplesBuffer* s, uint32_t idx, bool* level, uint32_t* dur) { - furi_mutex_acquire(s->mutex, FuriWaitForever); +void raw_samples_get(RawSamplesBuffer *s, uint32_t idx, bool *level, uint32_t *dur) +{ + furi_mutex_acquire(s->mutex,FuriWaitForever); idx = (s->idx + idx) % RAW_SAMPLES_NUM; - *level = s->level[idx]; - *dur = s->dur[idx]; + *level = s->samples[idx].level; + *dur = s->samples[idx].dur; furi_mutex_release(s->mutex); } /* Copy one buffer to the other, including current index. */ -void raw_samples_copy(RawSamplesBuffer* dst, RawSamplesBuffer* src) { - furi_mutex_acquire(src->mutex, FuriWaitForever); - furi_mutex_acquire(dst->mutex, FuriWaitForever); +void raw_samples_copy(RawSamplesBuffer *dst, RawSamplesBuffer *src) { + furi_mutex_acquire(src->mutex,FuriWaitForever); + furi_mutex_acquire(dst->mutex,FuriWaitForever); dst->idx = src->idx; dst->short_pulse_dur = src->short_pulse_dur; - memcpy(dst->level, src->level, sizeof(dst->level)); - memcpy(dst->dur, src->dur, sizeof(dst->dur)); + memcpy(dst->samples,src->samples,sizeof(dst->samples)); furi_mutex_release(src->mutex); furi_mutex_release(dst->mutex); } diff --git a/applications/plugins/protoview/app_buffer.h b/applications/plugins/protoview/app_buffer.h index 4448464ae..3a34d50f8 100644 --- a/applications/plugins/protoview/app_buffer.h +++ b/applications/plugins/protoview/app_buffer.h @@ -4,16 +4,16 @@ /* Our circular buffer of raw samples, used in order to display * the signal. */ -#define RAW_SAMPLES_NUM \ - 2048 /* Use a power of two: we take the modulo +#define RAW_SAMPLES_NUM 2048 /* Use a power of two: we take the modulo of the index quite often to normalize inside the range, and division is slow. */ - typedef struct RawSamplesBuffer { - FuriMutex* mutex; - uint8_t level[RAW_SAMPLES_NUM]; - uint32_t dur[RAW_SAMPLES_NUM]; - uint32_t idx; /* Current idx (next to write). */ + FuriMutex *mutex; + struct { + uint16_t level:1; + uint16_t dur:15; + } samples[RAW_SAMPLES_NUM]; + uint32_t idx; /* Current idx (next to write). */ uint32_t total; /* Total samples: same as RAW_SAMPLES_NUM, we provide this field for a cleaner interface with the user, but we always use RAW_SAMPLES_NUM when taking the modulo so @@ -22,10 +22,10 @@ typedef struct RawSamplesBuffer { uint32_t short_pulse_dur; /* Duration of the shortest pulse. */ } RawSamplesBuffer; -RawSamplesBuffer* raw_samples_alloc(void); -void raw_samples_reset(RawSamplesBuffer* s); -void raw_samples_center(RawSamplesBuffer* s, uint32_t offset); -void raw_samples_add(RawSamplesBuffer* s, bool level, uint32_t dur); -void raw_samples_get(RawSamplesBuffer* s, uint32_t idx, bool* level, uint32_t* dur); -void raw_samples_copy(RawSamplesBuffer* dst, RawSamplesBuffer* src); -void raw_samples_free(RawSamplesBuffer* s); +RawSamplesBuffer *raw_samples_alloc(void); +void raw_samples_reset(RawSamplesBuffer *s); +void raw_samples_center(RawSamplesBuffer *s, uint32_t offset); +void raw_samples_add(RawSamplesBuffer *s, bool level, uint32_t dur); +void raw_samples_get(RawSamplesBuffer *s, uint32_t idx, bool *level, uint32_t *dur); +void raw_samples_copy(RawSamplesBuffer *dst, RawSamplesBuffer *src); +void raw_samples_free(RawSamplesBuffer *s); diff --git a/applications/plugins/protoview/app_subghz.c b/applications/plugins/protoview/app_subghz.c index 40c7dcfa2..ec7724b13 100644 --- a/applications/plugins/protoview/app_subghz.c +++ b/applications/plugins/protoview/app_subghz.c @@ -9,8 +9,8 @@ #include #include -void raw_sampling_worker_start(ProtoViewApp* app); -void raw_sampling_worker_stop(ProtoViewApp* app); +void raw_sampling_worker_start(ProtoViewApp *app); +void raw_sampling_worker_stop(ProtoViewApp *app); ProtoViewModulation ProtoViewModulations[] = { {"OOK 650Khz", FuriHalSubGhzPresetOok650Async, NULL}, @@ -19,9 +19,10 @@ ProtoViewModulation ProtoViewModulations[] = { {"2FSK 47.6Khz", FuriHalSubGhzPreset2FSKDev476Async, NULL}, {"MSK", FuriHalSubGhzPresetMSK99_97KbAsync, NULL}, {"GFSK", FuriHalSubGhzPresetGFSK9_99KbAsync, NULL}, - {"TPMS 1 (FSK)", 0, (uint8_t*)protoview_subghz_tpms1_async_regs}, - {"TPMS 2 (FSK)", 0, (uint8_t*)protoview_subghz_tpms2_async_regs}, - {"TPMS 3 (FSK)", 0, (uint8_t*)protoview_subghz_tpms3_async_regs}, + {"TPMS 1 (FSK)", 0, (uint8_t*)protoview_subghz_tpms1_fsk_async_regs}, + {"TPMS 2 (OOK)", 0, (uint8_t*)protoview_subghz_tpms2_ook_async_regs}, + {"TPMS 3 (FSK)", 0, (uint8_t*)protoview_subghz_tpms3_fsk_async_regs}, + {"TPMS 4 (FSK)", 0, (uint8_t*)protoview_subghz_tpms4_fsk_async_regs}, {NULL, 0, NULL} /* End of list sentinel. */ }; @@ -37,7 +38,7 @@ void radio_begin(ProtoViewApp* app) { /* The CC1101 preset can be either one of the standard presets, if * the modulation "custom" field is NULL, or a custom preset we * defined in custom_presets.h. */ - if(ProtoViewModulations[app->modulation].custom == NULL) + if (ProtoViewModulations[app->modulation].custom == NULL) furi_hal_subghz_load_preset(ProtoViewModulations[app->modulation].preset); else furi_hal_subghz_load_custom_preset(ProtoViewModulations[app->modulation].custom); @@ -49,10 +50,10 @@ void radio_begin(ProtoViewApp* app) { uint32_t radio_rx(ProtoViewApp* app) { furi_assert(app); if(!furi_hal_subghz_is_frequency_valid(app->frequency)) { - furi_crash(TAG " Incorrect RX frequency."); + furi_crash(TAG" Incorrect RX frequency."); } - if(app->txrx->txrx_state == TxRxStateRx) return app->frequency; + if (app->txrx->txrx_state == TxRxStateRx) return app->frequency; furi_hal_subghz_idle(); /* Put it into idle state in case it is sleeping. */ uint32_t value = furi_hal_subghz_set_frequency_and_path(app->frequency); @@ -60,8 +61,10 @@ uint32_t radio_rx(ProtoViewApp* app) { furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); furi_hal_subghz_flush_rx(); furi_hal_subghz_rx(); - if(!app->txrx->debug_timer_sampling) { - furi_hal_subghz_start_async_rx(subghz_worker_rx_callback, app->txrx->worker); + if (!app->txrx->debug_timer_sampling) { + + furi_hal_subghz_start_async_rx(subghz_worker_rx_callback, + app->txrx->worker); subghz_worker_start(app->txrx->worker); } else { raw_sampling_worker_start(app); @@ -73,8 +76,8 @@ uint32_t radio_rx(ProtoViewApp* app) { /* Stop subghz worker (if active), put radio on idle state. */ void radio_rx_end(ProtoViewApp* app) { furi_assert(app); - if(app->txrx->txrx_state == TxRxStateRx) { - if(!app->txrx->debug_timer_sampling) { + if (app->txrx->txrx_state == TxRxStateRx) { + if (!app->txrx->debug_timer_sampling) { if(subghz_worker_is_running(app->txrx->worker)) { subghz_worker_stop(app->txrx->worker); furi_hal_subghz_stop_async_rx(); @@ -90,7 +93,7 @@ void radio_rx_end(ProtoViewApp* app) { /* Put radio on sleep. */ void radio_sleep(ProtoViewApp* app) { furi_assert(app); - if(app->txrx->txrx_state == TxRxStateRx) { + if (app->txrx->txrx_state == TxRxStateRx) { /* We can't go from having an active RX worker to sleeping. * Stop the RX subsystems first. */ radio_rx_end(app); @@ -106,15 +109,15 @@ void radio_sleep(ProtoViewApp* app) { * Flipper system. * ===========================================================================*/ -void protoview_timer_isr(void* ctx) { - ProtoViewApp* app = ctx; +void protoview_timer_isr(void *ctx) { + ProtoViewApp *app = ctx; bool level = furi_hal_gpio_read(&gpio_cc1101_g0); - if(app->txrx->last_g0_value != level) { + if (app->txrx->last_g0_value != level) { uint32_t now = DWT->CYCCNT; uint32_t dur = now - app->txrx->last_g0_change_time; dur /= furi_hal_cortex_instructions_per_microsecond(); - if(dur > 15000) dur = 15000; + if (dur > 15000) dur = 15000; raw_samples_add(RawSamples, app->txrx->last_g0_value, dur); app->txrx->last_g0_value = level; app->txrx->last_g0_change_time = now; @@ -122,13 +125,13 @@ void protoview_timer_isr(void* ctx) { LL_TIM_ClearFlag_UPDATE(TIM2); } -void raw_sampling_worker_start(ProtoViewApp* app) { +void raw_sampling_worker_start(ProtoViewApp *app) { UNUSED(app); LL_TIM_InitTypeDef tim_init = { - .Prescaler = 63, /* CPU frequency is ~64Mhz. */ + .Prescaler = 63, /* CPU frequency is ~64Mhz. */ .CounterMode = LL_TIM_COUNTERMODE_UP, - .Autoreload = 5, /* Sample every 5 us */ + .Autoreload = 5, /* Sample every 5 us */ }; LL_TIM_Init(TIM2, &tim_init); @@ -141,7 +144,7 @@ void raw_sampling_worker_start(ProtoViewApp* app) { FURI_LOG_E(TAG, "Timer enabled"); } -void raw_sampling_worker_stop(ProtoViewApp* app) { +void raw_sampling_worker_stop(ProtoViewApp *app) { UNUSED(app); FURI_CRITICAL_ENTER(); LL_TIM_DisableCounter(TIM2); diff --git a/applications/plugins/protoview/crc.c b/applications/plugins/protoview/crc.c index 94d482972..38a809e10 100644 --- a/applications/plugins/protoview/crc.c +++ b/applications/plugins/protoview/crc.c @@ -3,13 +3,14 @@ /* CRC8 with the specified initialization value 'init' and * polynomial 'poly'. */ -uint8_t crc8(const uint8_t* data, size_t len, uint8_t init, uint8_t poly) { +uint8_t crc8(const uint8_t *data, size_t len, uint8_t init, uint8_t poly) +{ uint8_t crc = init; size_t i, j; - for(i = 0; i < len; i++) { + for (i = 0; i < len; i++) { crc ^= data[i]; - for(j = 0; j < 8; j++) { - if((crc & 0x80) != 0) + for (j = 0; j < 8; j++) { + if ((crc & 0x80) != 0) crc = (uint8_t)((crc << 1) ^ poly); else crc <<= 1; diff --git a/applications/plugins/protoview/custom_presets.h b/applications/plugins/protoview/custom_presets.h index 804c4e629..713827d22 100644 --- a/applications/plugins/protoview/custom_presets.h +++ b/applications/plugins/protoview/custom_presets.h @@ -1,8 +1,8 @@ #include -/* This is how to configure registers MDMCFG3 and MDMCFG4. +/* ========================== DATA RATE SETTINGS =============================== * - * Data rate kBaud setting: + * This is how to configure registers MDMCFG3 and MDMCFG4. * * MDMCFG3 is the data rate mantissa, the exponent is in MDMCFG4, * last 4 bits of the register. @@ -15,6 +15,8 @@ * * ((256+34)*(2^12))/(2^28)*26000000 = 115051.2688000000, that is 115KBaud * + * ============================ BANDWIDTH FILTER =============================== + * * Bandwidth filter setting: * * BW filter as just 16 possibilities depending on how the first nibble @@ -39,6 +41,8 @@ * e 68 khz * f 58 khz * + * ============================== FSK DEVIATION ================================ + * * FSK deviation is controlled by the DEVIATION register. In Ruby: * * dev = (26000000.0/2**17)*(8+(deviation&7))*(2**(deviation>>4&7)) @@ -58,7 +62,7 @@ */ /* 20 KBaud, 2FSK, 28.56 kHz deviation, 325 Khz bandwidth filter. */ -static uint8_t protoview_subghz_tpms1_async_regs[][2] = { +static uint8_t protoview_subghz_tpms1_fsk_async_regs[][2] = { /* GPIO GD0 */ {CC1101_IOCFG0, 0x0D}, // GD0 as async serial data output/input @@ -72,8 +76,7 @@ static uint8_t protoview_subghz_tpms1_async_regs[][2] = { // // Modem Configuration {CC1101_MDMCFG0, 0x00}, {CC1101_MDMCFG1, 0x02}, - {CC1101_MDMCFG2, - 0x04}, // Format 2-FSK/FM, No preamble/sync, Disable (current optimized). Other code reading TPMS uses GFSK, but should be the same when in RX mode. + {CC1101_MDMCFG2, 0x04}, // Format 2-FSK/FM, No preamble/sync, Disable (current optimized). Other code reading TPMS uses GFSK, but should be the same when in RX mode. {CC1101_MDMCFG3, 0x93}, // Data rate is 20kBaud {CC1101_MDMCFG4, 0x59}, // Rx bandwidth filter is 325 kHz {CC1101_DEVIATN, 0x41}, // Deviation 28.56 kHz @@ -103,8 +106,55 @@ static uint8_t protoview_subghz_tpms1_async_regs[][2] = { {0, 0}, }; -/* 40 KBaud, 2FSK, 19 kHz deviation, 102 Khz bandwidth filter. */ -static uint8_t protoview_subghz_tpms2_async_regs[][2] = { +/* This is like the default Flipper OOK 640Khz bandwidth preset, but + * the bandwidth is changed to 10kBaud to accomodate TPMS frequency. */ +static const uint8_t protoview_subghz_tpms2_ook_async_regs[][2] = { + /* GPIO GD0 */ + {CC1101_IOCFG0, 0x0D}, // GD0 as async serial data output/input + + /* FIFO and internals */ + {CC1101_FIFOTHR, 0x07}, // The only important bit is ADC_RETENTION + + /* Packet engine */ + {CC1101_PKTCTRL0, 0x32}, // Async, continious, no whitening + + /* Frequency Synthesizer Control */ + {CC1101_FSCTRL1, 0x06}, // IF = (26*10^6) / (2^10) * 0x06 = 152343.75Hz + + // Modem Configuration + {CC1101_MDMCFG0, 0x00}, // Channel spacing is 25kHz + {CC1101_MDMCFG1, 0x00}, // Channel spacing is 25kHz + {CC1101_MDMCFG2, 0x30}, // Format ASK/OOK, No preamble/sync + {CC1101_MDMCFG3, 0x93}, // Data rate is 10kBaud + {CC1101_MDMCFG4, 0x18}, // Rx BW filter is 650.000kHz + + /* Main Radio Control State Machine */ + {CC1101_MCSM0, 0x18}, // Autocalibrate on idle-to-rx/tx, PO_TIMEOUT is 64 cycles(149-155us) + + /* Frequency Offset Compensation Configuration */ + {CC1101_FOCCFG, + 0x18}, // no frequency offset compensation, POST_K same as PRE_K, PRE_K is 4K, GATE is off + + /* Automatic Gain Control */ + {CC1101_AGCCTRL0, + 0x91}, // 10 - Medium hysteresis, medium asymmetric dead zone, medium gain ; 01 - 16 samples agc; 00 - Normal AGC, 01 - 8dB boundary + {CC1101_AGCCTRL1, + 0x0}, // 0; 0 - LNA 2 gain is decreased to minimum before decreasing LNA gain; 00 - Relative carrier sense threshold disabled; 0000 - RSSI to MAIN_TARGET + {CC1101_AGCCTRL2, 0x07}, // 00 - DVGA all; 000 - MAX LNA+LNA2; 111 - MAIN_TARGET 42 dB + + /* Wake on radio and timeouts control */ + {CC1101_WORCTRL, 0xFB}, // WOR_RES is 2^15 periods (0.91 - 0.94 s) 16.5 - 17.2 hours + + /* Frontend configuration */ + {CC1101_FREND0, 0x11}, // Adjusts current TX LO buffer + high is PATABLE[1] + {CC1101_FREND1, 0xB6}, // + + /* End */ + {0, 0}, +}; + +/* 40 KBaud, 2FSK, 28 kHz deviation, 270 Khz bandwidth filter. */ +static uint8_t protoview_subghz_tpms3_fsk_async_regs[][2] = { /* GPIO GD0 */ {CC1101_IOCFG0, 0x0D}, // GD0 as async serial data output/input @@ -118,11 +168,10 @@ static uint8_t protoview_subghz_tpms2_async_regs[][2] = { // // Modem Configuration {CC1101_MDMCFG0, 0x00}, {CC1101_MDMCFG1, 0x02}, - {CC1101_MDMCFG2, - 0x04}, // Format 2-FSK/FM, No preamble/sync, Disable (current optimized). Other code reading TPMS uses GFSK, but should be the same when in RX mode. + {CC1101_MDMCFG2, 0x04}, // Format 2-FSK/FM, No preamble/sync, Disable (current optimized). Other code reading TPMS uses GFSK, but should be the same when in RX mode. {CC1101_MDMCFG3, 0x93}, // Data rate is 40kBaud {CC1101_MDMCFG4, 0x6A}, // 6 = BW filter 270kHz, A = Data rate exp - {CC1101_DEVIATN, 0x41}, // Deviation 19.042 kHz + {CC1101_DEVIATN, 0x41}, // Deviation 28kHz /* Main Radio Control State Machine */ {CC1101_MCSM0, 0x18}, // Autocalibrate on idle-to-rx/tx, PO_TIMEOUT is 64 cycles(149-155us) @@ -149,8 +198,8 @@ static uint8_t protoview_subghz_tpms2_async_regs[][2] = { {0, 0}, }; -/* Parameters that should work well for the TPMS PVM C210 sensor. */ -static uint8_t protoview_subghz_tpms3_async_regs[][2] = { +/* FSK 19k dev, 325 Khz filter, 20kBaud. Works well with Toyota. */ +static uint8_t protoview_subghz_tpms4_fsk_async_regs[][2] = { /* GPIO GD0 */ {CC1101_IOCFG0, 0x0D}, // GD0 as async serial data output/input @@ -167,7 +216,7 @@ static uint8_t protoview_subghz_tpms3_async_regs[][2] = { {CC1101_MDMCFG2, 0x10}, // GFSK without any other check {CC1101_MDMCFG3, 0x93}, // Data rate is 20kBaud {CC1101_MDMCFG4, 0x59}, // Rx bandwidth filter is 325 kHz - {CC1101_DEVIATN, 0x34}, // Deviation 19.04 Khz, works well with TPMS + {CC1101_DEVIATN, 0x34}, // Deviation 19.04 Khz. /* Main Radio Control State Machine */ {CC1101_MCSM0, 0x18}, // Autocalibrate on idle-to-rx/tx, PO_TIMEOUT is 64 cycles(149-155us) @@ -191,3 +240,5 @@ static uint8_t protoview_subghz_tpms3_async_regs[][2] = { /* End */ {0, 0}, }; + + diff --git a/applications/plugins/protoview/data_feed.c b/applications/plugins/protoview/data_feed.c index 686bd356e..c3387fc4c 100644 --- a/applications/plugins/protoview/data_feed.c +++ b/applications/plugins/protoview/data_feed.c @@ -14,7 +14,7 @@ const SubGhzProtocol subghz_protocol_protoview; /* The feed() method puts data in the RawSamples global (protected by * a mutex). */ -extern RawSamplesBuffer* RawSamples; +extern RawSamplesBuffer *RawSamples; /* This is totally dummy: we just define the decoder base for the async * system to work but we don't really use it if not to collect raw @@ -26,7 +26,8 @@ typedef struct SubGhzProtocolDecoderprotoview { void* subghz_protocol_decoder_protoview_alloc(SubGhzEnvironment* environment) { UNUSED(environment); - SubGhzProtocolDecoderprotoview* instance = malloc(sizeof(SubGhzProtocolDecoderprotoview)); + SubGhzProtocolDecoderprotoview* instance = + malloc(sizeof(SubGhzProtocolDecoderprotoview)); instance->base.protocol = &subghz_protocol_protoview; return instance; } @@ -65,7 +66,8 @@ uint8_t subghz_protocol_decoder_protoview_get_hash_data(void* context) { bool subghz_protocol_decoder_protoview_serialize( void* context, FlipperFormat* flipper_format, - SubGhzRadioPreset* preset) { + SubGhzRadioPreset* preset) +{ UNUSED(context); UNUSED(flipper_format); UNUSED(preset); @@ -73,13 +75,15 @@ bool subghz_protocol_decoder_protoview_serialize( } /* Not used. */ -bool subghz_protocol_decoder_protoview_deserialize(void* context, FlipperFormat* flipper_format) { +bool subghz_protocol_decoder_protoview_deserialize(void* context, FlipperFormat* flipper_format) +{ UNUSED(context); UNUSED(flipper_format); return false; } -void subhz_protocol_decoder_protoview_get_string(void* context, FuriString* output) { +void subhz_protocol_decoder_protoview_get_string(void* context, FuriString* output) +{ furi_assert(context); furi_string_cat_printf(output, "Protoview"); } @@ -112,4 +116,5 @@ const SubGhzProtocol* protoview_protocol_registry_items[] = { const SubGhzProtocolRegistry protoview_protocol_registry = { .items = protoview_protocol_registry_items, - .size = COUNT_OF(protoview_protocol_registry_items)}; + .size = COUNT_OF(protoview_protocol_registry_items) +}; diff --git a/applications/plugins/protoview/protocols/b4b1.c b/applications/plugins/protoview/protocols/b4b1.c index 234b0158e..2bed2ac32 100644 --- a/applications/plugins/protoview/protocols/b4b1.c +++ b/applications/plugins/protoview/protocols/b4b1.c @@ -9,9 +9,9 @@ #include "../app.h" -static bool decode(uint8_t* bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo* info) { - if(numbits < 30) return false; - const char* sync_patterns[3] = { +static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo *info) { + if (numbits < 30) return false; + const char *sync_patterns[3] = { "10000000000000000000000000000001", /* 30 zero bits. */ "100000000000000000000000000000001", /* 31 zero bits. */ "1000000000000000000000000000000001", /* 32 zero bits. */ @@ -19,23 +19,26 @@ static bool decode(uint8_t* bits, uint32_t numbytes, uint32_t numbits, ProtoView uint32_t off; int j; - for(j = 0; j < 3; j++) { - off = bitmap_seek_bits(bits, numbytes, 0, numbits, sync_patterns[j]); - if(off != BITMAP_SEEK_NOT_FOUND) break; + for (j = 0; j < 3; j++) { + off = bitmap_seek_bits(bits,numbytes,0,numbits,sync_patterns[j]); + if (off != BITMAP_SEEK_NOT_FOUND) break; } - if(off == BITMAP_SEEK_NOT_FOUND) return false; - if(DEBUG_MSG) FURI_LOG_E(TAG, "B4B1 preamble at: %lu", off); - off += strlen(sync_patterns[j]) - 1; + if (off == BITMAP_SEEK_NOT_FOUND) return false; + if (DEBUG_MSG) FURI_LOG_E(TAG, "B4B1 preamble at: %lu",off); + off += strlen(sync_patterns[j])-1; uint8_t d[3]; /* 24 bits of data. */ - uint32_t decoded = convert_from_line_code(d, sizeof(d), bits, numbytes, off, "1000", "1110"); + uint32_t decoded = + convert_from_line_code(d,sizeof(d),bits,numbytes,off,"1000","1110"); - if(DEBUG_MSG) FURI_LOG_E(TAG, "B4B1 decoded: %lu", decoded); - if(decoded != 24) return false; - snprintf(info->name, PROTOVIEW_MSG_STR_LEN, "PT/SC remote"); - snprintf(info->raw, PROTOVIEW_MSG_STR_LEN, "%02X%02X%02X", d[0], d[1], d[2]); - info->len = off + (4 * 24); + if (DEBUG_MSG) FURI_LOG_E(TAG, "B4B1 decoded: %lu",decoded); + if (decoded != 24) return false; + snprintf(info->name,PROTOVIEW_MSG_STR_LEN,"PT/SC remote"); + snprintf(info->raw,PROTOVIEW_MSG_STR_LEN,"%02X%02X%02X",d[0],d[1],d[2]); + info->len = off+(4*24); return true; } -ProtoViewDecoder B4B1Decoder = {"B4B1", decode}; +ProtoViewDecoder B4B1Decoder = { + "B4B1", decode +}; diff --git a/applications/plugins/protoview/protocols/citroen_tpms.c b/applications/plugins/protoview/protocols/citroen_tpms.c deleted file mode 100644 index 8831c22f4..000000000 --- a/applications/plugins/protoview/protocols/citroen_tpms.c +++ /dev/null @@ -1,72 +0,0 @@ -/* Citroen TPMS. Usually 443.92 Mhz FSK. - * - * Preamble of ~14 high/low 52 us pulses - * Sync of high 100us pulse then 50us low - * Then Manchester bits, 10 bytes total. - * Simple XOR checksum. */ - -#include "../app.h" - -static bool decode(uint8_t* bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo* info) { - /* We consider a preamble of 17 symbols. They are more, but the decoding - * is more likely to happen if we don't pretend to receive from the - * very start of the message. */ - uint32_t sync_len = 17; - const char* sync_pattern = "10101010101010110"; - if(numbits - sync_len < 8 * 10) return false; /* Expect 10 bytes. */ - - uint64_t off = bitmap_seek_bits(bits, numbytes, 0, numbits, sync_pattern); - if(off == BITMAP_SEEK_NOT_FOUND) return false; - FURI_LOG_E(TAG, "Renault TPMS preamble+sync found"); - - off += sync_len; /* Skip preamble + sync. */ - - uint8_t raw[10]; - uint32_t decoded = convert_from_line_code( - raw, sizeof(raw), bits, numbytes, off, "01", "10"); /* Manchester. */ - FURI_LOG_E(TAG, "Citroen TPMS decoded bits: %lu", decoded); - - if(decoded < 8 * 10) return false; /* Require the full 10 bytes. */ - - /* Check the CRC. It's a simple XOR of bytes 1-9, the first byte - * is not included. The meaning of the first byte is unknown and - * we don't display it. */ - uint8_t crc = 0; - for(int j = 1; j < 10; j++) crc ^= raw[j]; - if(crc != 0) return false; /* Require sane checksum. */ - - int repeat = raw[5] & 0xf; - float kpa = (float)raw[6] * 1.364; - int temp = raw[7] - 50; - int battery = raw[8]; /* This may be the battery. It's not clear. */ - - snprintf(info->name, sizeof(info->name), "%s", "Citroen TPMS"); - snprintf( - info->raw, - sizeof(info->raw), - "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", - raw[0], - raw[1], - raw[2], - raw[3], - raw[4], - raw[5], - raw[6], - raw[7], - raw[8], - raw[9]); - snprintf( - info->info1, - sizeof(info->info1), - "Tire ID %02X%02X%02X%02X", - raw[1], - raw[2], - raw[3], - raw[4]); - snprintf(info->info2, sizeof(info->info2), "Pressure %.2f kpa", (double)kpa); - snprintf(info->info3, sizeof(info->info3), "Temperature %d C", temp); - snprintf(info->info4, sizeof(info->info4), "Repeat %d, Bat %d", repeat, battery); - return true; -} - -ProtoViewDecoder CitroenTPMSDecoder = {"Citroen TPMS", decode}; diff --git a/applications/plugins/protoview/protocols/ford_tpms.c b/applications/plugins/protoview/protocols/ford_tpms.c deleted file mode 100644 index 9d3e66ff8..000000000 --- a/applications/plugins/protoview/protocols/ford_tpms.c +++ /dev/null @@ -1,76 +0,0 @@ -/* Ford tires TPMS. Usually 443.92 Mhz FSK (in Europe). - * - * 52 us short pules - * Preamble: 0101010101010101010101010101 - * Sync: 0110 (that is 52 us gap + 104 us pulse + 52 us gap) - * Data: 8 bytes Manchester encoded - * 01 = zero - * 10 = one - */ - -#include "../app.h" - -static bool decode(uint8_t* bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo* info) { - const char* sync_pattern = "010101010101" - "0110"; - uint8_t sync_len = 12 + 4; /* We just use 12 preamble symbols + sync. */ - if(numbits - sync_len < 8 * 8) return false; - - uint64_t off = bitmap_seek_bits(bits, numbytes, 0, numbits, sync_pattern); - if(off == BITMAP_SEEK_NOT_FOUND) return false; - FURI_LOG_E(TAG, "Fort TPMS preamble+sync found"); - - off += sync_len; /* Skip preamble and sync. */ - - uint8_t raw[8]; - uint32_t decoded = convert_from_line_code( - raw, sizeof(raw), bits, numbytes, off, "01", "10"); /* Manchester. */ - FURI_LOG_E(TAG, "Ford TPMS decoded bits: %lu", decoded); - - if(decoded < 8 * 8) return false; /* Require the full 8 bytes. */ - - /* CRC is just the sum of the first 7 bytes MOD 256. */ - uint8_t crc = 0; - for(int j = 0; j < 7; j++) crc += raw[j]; - if(crc != raw[7]) return false; /* Require sane CRC. */ - - float psi = 0.25 * (((raw[6] & 0x20) << 3) | raw[4]); - - /* Temperature apperas to be valid only if the most significant - * bit of the value is not set. Otherwise its meaning is unknown. - * Likely useful to alternatively send temperature or other info. */ - int temp = raw[5] & 0x80 ? 0 : raw[5] - 56; - int flags = raw[5] & 0x7f; - int car_moving = (raw[6] & 0x44) == 0x44; - - snprintf(info->name, sizeof(info->name), "%s", "Ford TPMS"); - snprintf( - info->raw, - sizeof(info->raw), - "%02X%02X%02X%02X%02X%02X%02X%02X", - raw[0], - raw[1], - raw[2], - raw[3], - raw[4], - raw[5], - raw[6], - raw[7]); - snprintf( - info->info1, - sizeof(info->info1), - "Tire ID %02X%02X%02X%02X", - raw[0], - raw[1], - raw[2], - raw[3]); - snprintf(info->info2, sizeof(info->info2), "Pressure %.2f psi", (double)psi); - if(temp) - snprintf(info->info3, sizeof(info->info3), "Temperature %d C", temp); - else - snprintf(info->info3, sizeof(info->info3), "Flags %d", flags); - snprintf(info->info4, sizeof(info->info4), "Moving %s", car_moving ? "yes" : "no"); - return true; -} - -ProtoViewDecoder FordTPMSDecoder = {"Ford TPMS", decode}; diff --git a/applications/plugins/protoview/protocols/keeloq.c b/applications/plugins/protoview/protocols/keeloq.c new file mode 100644 index 000000000..cf0b7682f --- /dev/null +++ b/applications/plugins/protoview/protocols/keeloq.c @@ -0,0 +1,87 @@ +/* Microchip HCS200/HCS300/HSC301 KeeLoq, rolling code remotes. + * + * Usually 443.92 Mhz OOK, ~200us or ~400us pulse len, depending + * on the configuration. + * + * Preamble: 12 pairs of alternating pulse/gap. + * Sync: long gap of around 10 times the duration of the short-pulse. + * Data: pulse width encoded data. Each bit takes three cycles: + * + * 0 = 110 + * 1 = 100 + * + * There are a total of 66 bits transmitted. + * 0..31: 32 bits of encrypted rolling code. + * 32..59: Remote ID, 28 bits + * 60..63: Buttons pressed + * 64..64: Low battery if set + * 65..65: Always set to 1 + * + * Bits in bytes are inverted: least significant bit is first. + * For some reason there is no checksum whatsoever, so we only decode + * if we find everything well formed. + */ + +#include "../app.h" + +static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo *info) { + + /* In the sync pattern, we require the 12 high/low pulses and at least + * half the gap we expect (5 pulses times, one is the final zero in the + * 24 symbols high/low sequence, then other 4). */ + const char *sync_pattern = "101010101010101010101010" "0000"; + uint8_t sync_len = 24+4; + if (numbits-sync_len+sync_len < 3*66) return false; + uint64_t off = bitmap_seek_bits(bits,numbytes,0,numbits,sync_pattern); + if (off == BITMAP_SEEK_NOT_FOUND) return false; + off += sync_len; + + /* Now there is half the gap left, but we allow from 3 to 7, instead of 5 + * symbols of gap, to avoid missing the signal for a matter of wrong + * timing. */ + uint8_t gap_len = 0; + while(gap_len <= 7 && bitmap_get(bits,numbytes,off+gap_len) == 0) + gap_len++; + if (gap_len < 3 || gap_len > 7) return false; + + off += gap_len; + FURI_LOG_E(TAG, "Keeloq preamble+sync found"); + + uint8_t raw[9] = {0}; + uint32_t decoded = + convert_from_line_code(raw,sizeof(raw),bits,numbytes,off, + "110","100"); /* Pulse width modulation. */ + FURI_LOG_E(TAG, "Keeloq decoded bits: %lu", decoded); + + if (decoded < 66) return false; /* Require the full 66 bits. */ + bitmap_reverse_bytes(raw,sizeof(raw)); /* Keeloq is LSB first. */ + + int buttons = raw[7]>>4; + int s3 = (buttons&1) != 0; + int s0 = (buttons&2) != 0; + int s1 = (buttons&4) != 0; + int s2 = (buttons&8) != 0; + + int remote_id = ((raw[7]&0x0f) << 24) | + (raw[6] << 16) | + (raw[5] << 8) | + (raw[4] << 0); + int lowbat = raw[8]&0x80; + + snprintf(info->name,sizeof(info->name),"%s","Keeloq remote"); + snprintf(info->raw,sizeof(info->raw),"%02X%02X%02X%02X%02X%02X%02X%02X%02X", + raw[0],raw[1],raw[2],raw[3],raw[4],raw[5], + raw[6],raw[7],raw[8]); + snprintf(info->info1,sizeof(info->info1),"Encrpyted %02X%02X%02X%02X", + raw[3],raw[2],raw[1],raw[0]); + snprintf(info->info2,sizeof(info->info2),"ID %08X", remote_id); + snprintf(info->info3,sizeof(info->info3),"s0-s3: %d%d%d%d", + s0,s1,s2,s3); + snprintf(info->info4,sizeof(info->info4),"Low battery? %s", + lowbat ? "yes" : "no"); + return true; +} + +ProtoViewDecoder KeeloqDecoder = { + "Keeloq", decode +}; diff --git a/applications/plugins/protoview/protocols/oregon2.c b/applications/plugins/protoview/protocols/oregon2.c index fbb87d3be..3aa57c72d 100644 --- a/applications/plugins/protoview/protocols/oregon2.c +++ b/applications/plugins/protoview/protocols/oregon2.c @@ -6,84 +6,60 @@ #include "../app.h" -static bool decode(uint8_t* bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo* info) { - if(numbits < 32) return false; - const char* sync_pattern = "01100110" - "01100110" - "10010110" - "10010110"; - uint64_t off = bitmap_seek_bits(bits, numbytes, 0, numbits, sync_pattern); - if(off == BITMAP_SEEK_NOT_FOUND) return false; +static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo *info) { + if (numbits < 32) return false; + const char *sync_pattern = "01100110" "01100110" "10010110" "10010110"; + uint64_t off = bitmap_seek_bits(bits,numbytes,0,numbits,sync_pattern); + if (off == BITMAP_SEEK_NOT_FOUND) return false; FURI_LOG_E(TAG, "Oregon2 preamble+sync found"); off += 32; /* Skip preamble. */ uint8_t buffer[8], raw[8] = {0}; uint32_t decoded = - convert_from_line_code(buffer, sizeof(buffer), bits, numbytes, off, "1001", "0110"); + convert_from_line_code(buffer,sizeof(buffer),bits,numbytes,off,"1001","0110"); FURI_LOG_E(TAG, "Oregon2 decoded bits: %lu", decoded); - if(decoded < 11 * 4) return false; /* Minimum len to extract some data. */ + if (decoded < 11*4) return false; /* Minimum len to extract some data. */ char temp[3] = {0}, deviceid[2] = {0}, hum[2] = {0}; - for(int j = 0; j < 64; j += 4) { + for (int j = 0; j < 64; j += 4) { uint8_t nib[1]; - nib[0] = - (bitmap_get(buffer, 8, j + 0) | bitmap_get(buffer, 8, j + 1) << 1 | - bitmap_get(buffer, 8, j + 2) << 2 | bitmap_get(buffer, 8, j + 3) << 3); - if(DEBUG_MSG) FURI_LOG_E(TAG, "Not inverted nibble[%d]: %x", j / 4, (unsigned int)nib[0]); - raw[j / 8] |= nib[0] << (4 - (j % 4)); - switch(j / 4) { - case 1: - deviceid[0] |= nib[0]; - break; - case 0: - deviceid[0] |= nib[0] << 4; - break; - case 3: - deviceid[1] |= nib[0]; - break; - case 2: - deviceid[1] |= nib[0] << 4; - break; - case 10: - temp[0] = nib[0]; - break; + nib[0] = (bitmap_get(buffer,8,j+0) | + bitmap_get(buffer,8,j+1) << 1 | + bitmap_get(buffer,8,j+2) << 2 | + bitmap_get(buffer,8,j+3) << 3); + if (DEBUG_MSG) FURI_LOG_E(TAG, "Not inverted nibble[%d]: %x", j/4, (unsigned int)nib[0]); + raw[j/8] |= nib[0] << (4-(j%4)); + switch(j/4) { + case 1: deviceid[0] |= nib[0]; break; + case 0: deviceid[0] |= nib[0] << 4; break; + case 3: deviceid[1] |= nib[0]; break; + case 2: deviceid[1] |= nib[0] << 4; break; + case 10: temp[0] = nib[0]; break; /* Fixme: take the temperature sign from nibble 11. */ - case 9: - temp[1] = nib[0]; - break; - case 8: - temp[2] = nib[0]; - break; - case 13: - hum[0] = nib[0]; - break; - case 12: - hum[1] = nib[0]; - break; + case 9: temp[1] = nib[0]; break; + case 8: temp[2] = nib[0]; break; + case 13: hum[0] = nib[0]; break; + case 12: hum[1] = nib[0]; break; } } - snprintf(info->name, sizeof(info->name), "%s", "Oregon v2.1"); + snprintf(info->name,sizeof(info->name),"%s","Oregon v2.1"); /* The following line crashes the Flipper because of broken * snprintf() implementation. */ - snprintf( - info->raw, - sizeof(info->raw), - "%02X%02X%02X%02X%02X%02X%02X%02X", - raw[0], - raw[1], - raw[2], - raw[3], - raw[4], - raw[5], - raw[6], - raw[7]); - snprintf(info->info1, sizeof(info->info1), "Sensor ID %02X%02X", deviceid[0], deviceid[1]); - snprintf(info->info2, sizeof(info->info2), "Temperature %d%d.%d", temp[0], temp[1], temp[2]); - snprintf(info->info3, sizeof(info->info3), "Humidity %d%d", hum[0], hum[1]); + snprintf(info->raw,sizeof(info->raw),"%02X%02X%02X%02X%02X%02X%02X%02X", + raw[0],raw[1],raw[2],raw[3],raw[4],raw[5], + raw[6],raw[7]); + snprintf(info->info1,sizeof(info->info1),"Sensor ID %02X%02X", + deviceid[0], deviceid[1]); + snprintf(info->info2,sizeof(info->info2),"Temperature %d%d.%d", + temp[0],temp[1],temp[2]); + snprintf(info->info3,sizeof(info->info3),"Humidity %d%d", + hum[0],hum[1]); return true; } -ProtoViewDecoder Oregon2Decoder = {"Oregon2", decode}; +ProtoViewDecoder Oregon2Decoder = { + "Oregon2", decode +}; diff --git a/applications/plugins/protoview/protocols/oregon2.txt b/applications/plugins/protoview/protocols/oregon2.txt deleted file mode 100644 index 362631431..000000000 --- a/applications/plugins/protoview/protocols/oregon2.txt +++ /dev/null @@ -1,6 +0,0 @@ -11001100110011001100110011001100110011001100110011001100110 (Preamble) -10 01 01 10 10 01 01 10 (Sync) -01 10 10 01 10 01 10 01 01 10 10 01 01 10 01 10 10 01 01 10 10 01 10 01 10 01 10 01 10 01 10 01 01 10 10 01 10 01 10 01 01 10 01 10 01 10 01 10 01 10 01 10 10 01 01 10 01 10 10 01 10 01 10 01 10 01 10 01 01 10 10 01 10 01 01 10 01 10 10 01 01 10 10 01 10 01 10 01 10 01 10 01 10 01 11 0 - -We need to seek the following bytes: 01100110 01100110 10010110 10010110 - 0x66 0x66 96 96 diff --git a/applications/plugins/protoview/protocols/renault_tpms.c b/applications/plugins/protoview/protocols/renault_tpms.c deleted file mode 100644 index b876d2731..000000000 --- a/applications/plugins/protoview/protocols/renault_tpms.c +++ /dev/null @@ -1,71 +0,0 @@ -/* Renault tires TPMS. Usually 443.92 Mhz FSK. - * - * Preamble + sync + Manchester bits. ~48us short pulse. - * 9 Bytes in total not counting the preamble. */ - -#include "../app.h" - -#define USE_TEST_VECTOR 0 -static const char* test_vector = - "...01010101010101010110" // Preamble + sync - - /* The following is Marshal encoded, so each two characters are - * actaully one bit. 01 = 0, 10 = 1. */ - "010110010110" // Flags. - "10011001101010011001" // Pressure, multiply by 0.75 to obtain kpa. - // 244 kpa here. - "1010010110011010" // Temperature, subtract 30 to obtain celsius. 22C here. - "1001010101101001" - "0101100110010101" - "1001010101100110" // Tire ID. 0x7AD779 here. - "0101010101010101" - "0101010101010101" // Two FF bytes (usually). Unknown. - "0110010101010101"; // CRC8 with (poly 7, initialization 0). - -static bool decode(uint8_t* bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo* info) { - if(USE_TEST_VECTOR) { /* Test vector to check that decoding works. */ - bitmap_set_pattern(bits, numbytes, test_vector); - numbits = strlen(test_vector); - } - - if(numbits - 12 < 9 * 8) return false; - - const char* sync_pattern = "01010101010101010110"; - uint64_t off = bitmap_seek_bits(bits, numbytes, 0, numbits, sync_pattern); - if(off == BITMAP_SEEK_NOT_FOUND) return false; - FURI_LOG_E(TAG, "Renault TPMS preamble+sync found"); - - off += 20; /* Skip preamble. */ - - uint8_t raw[9]; - uint32_t decoded = convert_from_line_code( - raw, sizeof(raw), bits, numbytes, off, "01", "10"); /* Manchester. */ - FURI_LOG_E(TAG, "Renault TPMS decoded bits: %lu", decoded); - - if(decoded < 8 * 9) return false; /* Require the full 9 bytes. */ - if(crc8(raw, 8, 0, 7) != raw[8]) return false; /* Require sane CRC. */ - - float kpa = 0.75 * ((uint32_t)((raw[0] & 3) << 8) | raw[1]); - int temp = raw[2] - 30; - - snprintf(info->name, sizeof(info->name), "%s", "Renault TPMS"); - snprintf( - info->raw, - sizeof(info->raw), - "%02X%02X%02X%02X%02X%02X%02X%02X%02X", - raw[0], - raw[1], - raw[2], - raw[3], - raw[4], - raw[5], - raw[6], - raw[7], - raw[8]); - snprintf(info->info1, sizeof(info->info1), "Tire ID %02X%02X%02X", raw[3], raw[4], raw[5]); - snprintf(info->info2, sizeof(info->info2), "Pressure %.2f kpa", (double)kpa); - snprintf(info->info3, sizeof(info->info3), "Temperature %d C", temp); - return true; -} - -ProtoViewDecoder RenaultTPMSDecoder = {"Renault TPMS", decode}; diff --git a/applications/plugins/protoview/protocols/schrader_tpms.c b/applications/plugins/protoview/protocols/schrader_tpms.c deleted file mode 100644 index cb2cf52c4..000000000 --- a/applications/plugins/protoview/protocols/schrader_tpms.c +++ /dev/null @@ -1,78 +0,0 @@ -/* Schrader TPMS. Usually 443.92 Mhz OOK, 120us pulse len. - * - * 500us high pulse + Preamble + Manchester coded bits where: - * 1 = 10 - * 0 = 01 - * - * 60 bits of data total (first 4 nibbles is the preamble, 0xF). - * - * Used in FIAT-Chrysler, Mercedes, ... */ - -#include "../app.h" - -#define USE_TEST_VECTOR 0 -static const char* test_vector = - "000000111101010101011010010110010110101001010110100110011001100101010101011010100110100110011010101010101010101010101010101010101010101010101010"; - -static bool decode(uint8_t* bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo* info) { - if(USE_TEST_VECTOR) { /* Test vector to check that decoding works. */ - bitmap_set_pattern(bits, numbytes, test_vector); - numbits = strlen(test_vector); - } - - if(numbits < 64) return false; /* Preamble + data. */ - - const char* sync_pattern = "1111010101" - "01011010"; - uint64_t off = bitmap_seek_bits(bits, numbytes, 0, numbits, sync_pattern); - if(off == BITMAP_SEEK_NOT_FOUND) return false; - FURI_LOG_E(TAG, "Schrader TPMS gap+preamble found"); - - off += 10; /* Skip just the long pulse and the first 3 bits of sync, so - that we have the first byte of data with the sync nibble - 0011 = 0x3. */ - - uint8_t raw[8]; - uint32_t decoded = convert_from_line_code( - raw, sizeof(raw), bits, numbytes, off, "01", "10"); /* Manchester code. */ - FURI_LOG_E(TAG, "Schrader TPMS decoded bits: %lu", decoded); - - if(decoded < 64) return false; /* Require the full 8 bytes. */ - - raw[0] |= 0xf0; // Fix the preamble nibble for checksum computation. - uint8_t cksum = crc8(raw, sizeof(raw) - 1, 0xf0, 0x7); - if(cksum != raw[7]) { - FURI_LOG_E(TAG, "Schrader TPMS checksum mismatch"); - return false; - } - - float kpa = (float)raw[5] * 2.5; - int temp = raw[6] - 50; - - snprintf(info->name, sizeof(info->name), "%s", "Schrader TPMS"); - snprintf( - info->raw, - sizeof(info->raw), - "%02X%02X%02X%02X%02X%02X%02X%02X", - raw[0], - raw[1], - raw[2], - raw[3], - raw[4], - raw[5], - raw[6], - raw[7]); - snprintf( - info->info1, - sizeof(info->info1), - "Tire ID %01X%02X%02X%02X", - raw[1] & 7, - raw[2], - raw[3], - raw[4]); /* Only 28 bits of ID, not 32. */ - snprintf(info->info2, sizeof(info->info2), "Pressure %.2f kpa", (double)kpa); - snprintf(info->info3, sizeof(info->info3), "Temperature %d C", temp); - return true; -} - -ProtoViewDecoder SchraderTPMSDecoder = {"Schrader TPMS", decode}; diff --git a/applications/plugins/protoview/protocols/toyota_tpms.c b/applications/plugins/protoview/protocols/toyota_tpms.c deleted file mode 100644 index 4e2376b96..000000000 --- a/applications/plugins/protoview/protocols/toyota_tpms.c +++ /dev/null @@ -1,84 +0,0 @@ -/* Toyota tires TPMS. Usually 443.92 Mhz FSK (In Europe). - * - * Preamble + sync + 64 bits of data. ~48us short pulse length. - * - * The preamble + sync is something like: - * - * 10101010101 (preamble) + 001111[1] (sync) - * - * Note: the final [1] means that sometimes it is four 1s, sometimes - * five, depending on the short pulse length detection and the exact - * duration of the high long pulse. After the sync, a differential - * Manchester encoded payload follows. However the Flipper's CC1101 - * often can't decode correctly the initial alternating pattern 101010101, - * so what we do is to seek just the sync, that is "001111" or "0011111", - * however we now that it must be followed by one differenitally encoded - * bit, so we can use also the first bit of data to force a more robust - * detection, and look for one of the following: - * - * [001111]00 - * [0011111]00 - * [001111]01 - * [0011111]01 - */ - -#include "../app.h" - -static bool decode(uint8_t* bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo* info) { - if(numbits - 6 < 64 * 2) - return false; /* Ask for 64 bit of data (each bit - is two symbols in the bitmap). */ - - char* sync[] = {"00111100", "001111100", "00111101", "001111101", NULL}; - - int j; - uint32_t off = 0; - for(j = 0; sync[j]; j++) { - off = bitmap_seek_bits(bits, numbytes, 0, numbits, sync[j]); - if(off != BITMAP_SEEK_NOT_FOUND) { - off += strlen(sync[j]) - 2; - break; - } - } - if(off == BITMAP_SEEK_NOT_FOUND) return false; - - FURI_LOG_E(TAG, "Toyota TPMS sync[%s] found", sync[j]); - - uint8_t raw[9]; - uint32_t decoded = convert_from_diff_manchester(raw, sizeof(raw), bits, numbytes, off, true); - FURI_LOG_E(TAG, "Toyota TPMS decoded bits: %lu", decoded); - - if(decoded < 8 * 9) return false; /* Require the full 8 bytes. */ - if(crc8(raw, 8, 0x80, 7) != raw[8]) return false; /* Require sane CRC. */ - - float kpa = (float)((raw[4] & 0x7f) << 1 | raw[5] >> 7) * 0.25 - 7; - int temp = ((raw[5] & 0x7f) << 1 | raw[6] >> 7) - 40; - - snprintf(info->name, sizeof(info->name), "%s", "Toyota TPMS"); - snprintf( - info->raw, - sizeof(info->raw), - "%02X%02X%02X%02X%02X%02X%02X%02X%02X", - raw[0], - raw[1], - raw[2], - raw[3], - raw[4], - raw[5], - raw[6], - raw[7], - raw[8]); - snprintf( - info->info1, - sizeof(info->info1), - "Tire ID %02X%02X%02X%02X", - raw[0], - raw[1], - raw[2], - raw[3]); - snprintf(info->info1, sizeof(info->info1), "Pressure %.2f psi", (double)kpa); - snprintf(info->info2, sizeof(info->info2), "Temperature %d C", temp); - return true; -} - -ProtoViewDecoder ToyotaTPMSDecoder = {"Toyota TPMS", decode}; diff --git a/applications/plugins/protoview/protocols/tpms/citroen.c b/applications/plugins/protoview/protocols/tpms/citroen.c new file mode 100644 index 000000000..809dc0a25 --- /dev/null +++ b/applications/plugins/protoview/protocols/tpms/citroen.c @@ -0,0 +1,60 @@ +/* Citroen TPMS. Usually 443.92 Mhz FSK. + * + * Preamble of ~14 high/low 52 us pulses + * Sync of high 100us pulse then 50us low + * Then Manchester bits, 10 bytes total. + * Simple XOR checksum. */ + +#include "../../app.h" + +static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo *info) { + + /* We consider a preamble of 17 symbols. They are more, but the decoding + * is more likely to happen if we don't pretend to receive from the + * very start of the message. */ + uint32_t sync_len = 17; + const char *sync_pattern = "10101010101010110"; + if (numbits-sync_len < 8*10) return false; /* Expect 10 bytes. */ + + uint64_t off = bitmap_seek_bits(bits,numbytes,0,numbits,sync_pattern); + if (off == BITMAP_SEEK_NOT_FOUND) return false; + FURI_LOG_E(TAG, "Renault TPMS preamble+sync found"); + + off += sync_len; /* Skip preamble + sync. */ + + uint8_t raw[10]; + uint32_t decoded = + convert_from_line_code(raw,sizeof(raw),bits,numbytes,off, + "01","10"); /* Manchester. */ + FURI_LOG_E(TAG, "Citroen TPMS decoded bits: %lu", decoded); + + if (decoded < 8*10) return false; /* Require the full 10 bytes. */ + + /* Check the CRC. It's a simple XOR of bytes 1-9, the first byte + * is not included. The meaning of the first byte is unknown and + * we don't display it. */ + uint8_t crc = 0; + for (int j = 1; j < 10; j++) crc ^= raw[j]; + if (crc != 0) return false; /* Require sane checksum. */ + + int repeat = raw[5] & 0xf; + float kpa = (float)raw[6]*1.364; + int temp = raw[7]-50; + int battery = raw[8]; /* This may be the battery. It's not clear. */ + + snprintf(info->name,sizeof(info->name),"%s","Citroen TPMS"); + snprintf(info->raw,sizeof(info->raw), + "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", + raw[0],raw[1],raw[2],raw[3],raw[4],raw[5], + raw[6],raw[7],raw[8],raw[9]); + snprintf(info->info1,sizeof(info->info1),"Tire ID %02X%02X%02X%02X", + raw[1],raw[2],raw[3],raw[4]); + snprintf(info->info2,sizeof(info->info2),"Pressure %.2f kpa", (double)kpa); + snprintf(info->info3,sizeof(info->info3),"Temperature %d C", temp); + snprintf(info->info4,sizeof(info->info4),"Repeat %d, Bat %d", repeat, battery); + return true; +} + +ProtoViewDecoder CitroenTPMSDecoder = { + "Citroen TPMS", decode +}; diff --git a/applications/plugins/protoview/protocols/tpms/ford.c b/applications/plugins/protoview/protocols/tpms/ford.c new file mode 100644 index 000000000..a9c687075 --- /dev/null +++ b/applications/plugins/protoview/protocols/tpms/ford.c @@ -0,0 +1,64 @@ +/* Ford tires TPMS. Usually 443.92 Mhz FSK (in Europe). + * + * 52 us short pules + * Preamble: 0101010101010101010101010101 + * Sync: 0110 (that is 52 us gap + 104 us pulse + 52 us gap) + * Data: 8 bytes Manchester encoded + * 01 = zero + * 10 = one + */ + +#include "../../app.h" + +static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo *info) { + + const char *sync_pattern = "010101010101" "0110"; + uint8_t sync_len = 12+4; /* We just use 12 preamble symbols + sync. */ + if (numbits-sync_len < 8*8) return false; + + uint64_t off = bitmap_seek_bits(bits,numbytes,0,numbits,sync_pattern); + if (off == BITMAP_SEEK_NOT_FOUND) return false; + FURI_LOG_E(TAG, "Fort TPMS preamble+sync found"); + + off += sync_len; /* Skip preamble and sync. */ + + uint8_t raw[8]; + uint32_t decoded = + convert_from_line_code(raw,sizeof(raw),bits,numbytes,off, + "01","10"); /* Manchester. */ + FURI_LOG_E(TAG, "Ford TPMS decoded bits: %lu", decoded); + + if (decoded < 8*8) return false; /* Require the full 8 bytes. */ + + /* CRC is just the sum of the first 7 bytes MOD 256. */ + uint8_t crc = 0; + for (int j = 0; j < 7; j++) crc += raw[j]; + if (crc != raw[7]) return false; /* Require sane CRC. */ + + float psi = 0.25 * (((raw[6]&0x20)<<3)|raw[4]); + + /* Temperature apperas to be valid only if the most significant + * bit of the value is not set. Otherwise its meaning is unknown. + * Likely useful to alternatively send temperature or other info. */ + int temp = raw[5] & 0x80 ? 0 : raw[5]-56; + int flags = raw[5] & 0x7f; + int car_moving = (raw[6] & 0x44) == 0x44; + + snprintf(info->name,sizeof(info->name),"%s","Ford TPMS"); + snprintf(info->raw,sizeof(info->raw),"%02X%02X%02X%02X%02X%02X%02X%02X", + raw[0],raw[1],raw[2],raw[3],raw[4],raw[5], + raw[6],raw[7]); + snprintf(info->info1,sizeof(info->info1),"Tire ID %02X%02X%02X%02X", + raw[0],raw[1],raw[2],raw[3]); + snprintf(info->info2,sizeof(info->info2),"Pressure %.2f psi", (double)psi); + if (temp) + snprintf(info->info3,sizeof(info->info3),"Temperature %d C", temp); + else + snprintf(info->info3,sizeof(info->info3),"Flags %d", flags); + snprintf(info->info4,sizeof(info->info4),"Moving %s", car_moving ? "yes" : "no"); + return true; +} + +ProtoViewDecoder FordTPMSDecoder = { + "Ford TPMS", decode +}; diff --git a/applications/plugins/protoview/protocols/tpms/renault.c b/applications/plugins/protoview/protocols/tpms/renault.c new file mode 100644 index 000000000..4bbe55e42 --- /dev/null +++ b/applications/plugins/protoview/protocols/tpms/renault.c @@ -0,0 +1,66 @@ +/* Renault tires TPMS. Usually 443.92 Mhz FSK. + * + * Preamble + sync + Manchester bits. ~48us short pulse. + * 9 Bytes in total not counting the preamble. */ + +#include "../../app.h" + +#define USE_TEST_VECTOR 0 +static const char *test_vector = + "...01010101010101010110" // Preamble + sync + + /* The following is Marshal encoded, so each two characters are + * actaully one bit. 01 = 0, 10 = 1. */ + "010110010110" // Flags. + "10011001101010011001" // Pressure, multiply by 0.75 to obtain kpa. + // 244 kpa here. + "1010010110011010" // Temperature, subtract 30 to obtain celsius. 22C here. + "1001010101101001" + "0101100110010101" + "1001010101100110" // Tire ID. 0x7AD779 here. + "0101010101010101" + "0101010101010101" // Two FF bytes (usually). Unknown. + "0110010101010101"; // CRC8 with (poly 7, initialization 0). + +static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo *info) { + + if (USE_TEST_VECTOR) { /* Test vector to check that decoding works. */ + bitmap_set_pattern(bits,numbytes,test_vector); + numbits = strlen(test_vector); + } + + if (numbits-12 < 9*8) return false; + + const char *sync_pattern = "01010101010101010110"; + uint64_t off = bitmap_seek_bits(bits,numbytes,0,numbits,sync_pattern); + if (off == BITMAP_SEEK_NOT_FOUND) return false; + FURI_LOG_E(TAG, "Renault TPMS preamble+sync found"); + + off += 20; /* Skip preamble. */ + + uint8_t raw[9]; + uint32_t decoded = + convert_from_line_code(raw,sizeof(raw),bits,numbytes,off, + "01","10"); /* Manchester. */ + FURI_LOG_E(TAG, "Renault TPMS decoded bits: %lu", decoded); + + if (decoded < 8*9) return false; /* Require the full 9 bytes. */ + if (crc8(raw,8,0,7) != raw[8]) return false; /* Require sane CRC. */ + + float kpa = 0.75 *((uint32_t)((raw[0]&3)<<8) | raw[1]); + int temp = raw[2]-30; + + snprintf(info->name,sizeof(info->name),"%s","Renault TPMS"); + snprintf(info->raw,sizeof(info->raw),"%02X%02X%02X%02X%02X%02X%02X%02X%02X", + raw[0],raw[1],raw[2],raw[3],raw[4],raw[5], + raw[6],raw[7],raw[8]); + snprintf(info->info1,sizeof(info->info1),"Tire ID %02X%02X%02X", + raw[3],raw[4],raw[5]); + snprintf(info->info2,sizeof(info->info2),"Pressure %.2f kpa", (double)kpa); + snprintf(info->info3,sizeof(info->info3),"Temperature %d C", temp); + return true; +} + +ProtoViewDecoder RenaultTPMSDecoder = { + "Renault TPMS", decode +}; diff --git a/applications/plugins/protoview/protocols/tpms/schrader.c b/applications/plugins/protoview/protocols/tpms/schrader.c new file mode 100644 index 000000000..ab65a92d3 --- /dev/null +++ b/applications/plugins/protoview/protocols/tpms/schrader.c @@ -0,0 +1,65 @@ +/* Schrader TPMS. Usually 443.92 Mhz OOK, 120us pulse len. + * + * 500us high pulse + Preamble + Manchester coded bits where: + * 1 = 10 + * 0 = 01 + * + * 60 bits of data total (first 4 nibbles is the preamble, 0xF). + * + * Used in FIAT-Chrysler, Mercedes, ... */ + +#include "../../app.h" + +#define USE_TEST_VECTOR 0 +static const char *test_vector = "000000111101010101011010010110010110101001010110100110011001100101010101011010100110100110011010101010101010101010101010101010101010101010101010"; + +static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo *info) { + + if (USE_TEST_VECTOR) { /* Test vector to check that decoding works. */ + bitmap_set_pattern(bits,numbytes,test_vector); + numbits = strlen(test_vector); + } + + if (numbits < 64) return false; /* Preamble + data. */ + + const char *sync_pattern = "1111010101" "01011010"; + uint64_t off = bitmap_seek_bits(bits,numbytes,0,numbits,sync_pattern); + if (off == BITMAP_SEEK_NOT_FOUND) return false; + FURI_LOG_E(TAG, "Schrader TPMS gap+preamble found"); + + off += 10; /* Skip just the long pulse and the first 3 bits of sync, so + that we have the first byte of data with the sync nibble + 0011 = 0x3. */ + + uint8_t raw[8]; + uint32_t decoded = + convert_from_line_code(raw,sizeof(raw),bits,numbytes,off, + "01","10"); /* Manchester code. */ + FURI_LOG_E(TAG, "Schrader TPMS decoded bits: %lu", decoded); + + if (decoded < 64) return false; /* Require the full 8 bytes. */ + + raw[0] |= 0xf0; // Fix the preamble nibble for checksum computation. + uint8_t cksum = crc8(raw,sizeof(raw)-1,0xf0,0x7); + if (cksum != raw[7]) { + FURI_LOG_E(TAG, "Schrader TPMS checksum mismatch"); + return false; + } + + float kpa = (float)raw[5]*2.5; + int temp = raw[6]-50; + + snprintf(info->name,sizeof(info->name),"%s","Schrader TPMS"); + snprintf(info->raw,sizeof(info->raw),"%02X%02X%02X%02X%02X%02X%02X%02X", + raw[0],raw[1],raw[2],raw[3],raw[4],raw[5], + raw[6],raw[7]); + snprintf(info->info1,sizeof(info->info1),"Tire ID %01X%02X%02X%02X", + raw[1]&7,raw[2],raw[3],raw[4]); /* Only 28 bits of ID, not 32. */ + snprintf(info->info2,sizeof(info->info2),"Pressure %.2f kpa", (double)kpa); + snprintf(info->info3,sizeof(info->info3),"Temperature %d C", temp); + return true; +} + +ProtoViewDecoder SchraderTPMSDecoder = { + "Schrader TPMS", decode +}; diff --git a/applications/plugins/protoview/protocols/tpms/schrader_eg53ma4.c b/applications/plugins/protoview/protocols/tpms/schrader_eg53ma4.c new file mode 100644 index 000000000..6fce40d64 --- /dev/null +++ b/applications/plugins/protoview/protocols/tpms/schrader_eg53ma4.c @@ -0,0 +1,63 @@ +/* Schrader variant EG53MA4 TPMS. + * Usually 443.92 Mhz OOK, 100us pulse len. + * + * Preamble: alternating pulse/gap, 100us. + * Sync (as pulses and gaps): "01100101", already part of the data stream + * (first nibble) corresponding to 0x4 + * + * A total of 10 bytes payload, Manchester encoded. + * + * 0 = 01 + * 1 = 10 + * + * Used in certain Open cars and others. + */ + +#include "../../app.h" + +static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo *info) { + + const char *sync_pattern = "010101010101" "01100101"; + uint8_t sync_len = 12+8; /* We just use 12 preamble symbols + sync. */ + if (numbits-sync_len+8 < 8*10) return false; + + uint64_t off = bitmap_seek_bits(bits,numbytes,0,numbits,sync_pattern); + if (off == BITMAP_SEEK_NOT_FOUND) return false; + FURI_LOG_E(TAG, "Schrader EG53MA4 TPMS preamble+sync found"); + + off += sync_len-8; /* Skip preamble, not sync that is part of the data. */ + + uint8_t raw[10]; + uint32_t decoded = + convert_from_line_code(raw,sizeof(raw),bits,numbytes,off, + "01","10"); /* Manchester code. */ + FURI_LOG_E(TAG, "Schrader EG53MA4 TPMS decoded bits: %lu", decoded); + + if (decoded < 10*8) return false; /* Require the full 10 bytes. */ + + /* CRC is just all bytes added mod 256. */ + uint8_t crc = 0; + for (int j = 0; j < 9; j++) crc += raw[j]; + if (crc != raw[9]) return false; /* Require sane CRC. */ + + /* To convert the raw pressure to kPa, RTL433 uses 2.5, but is likely + * wrong. Searching on Google for users experimenting with the value + * reported, the value appears to be 2.75. */ + float kpa = (float)raw[7]*2.75; + int temp_f = raw[8]; + int temp_c = (temp_f-32)*5/9; /* Convert Fahrenheit to Celsius. */ + + snprintf(info->name,sizeof(info->name),"%s","Schrader EG53MA4 TPMS"); + snprintf(info->raw,sizeof(info->raw),"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", + raw[0],raw[1],raw[2],raw[3],raw[4],raw[5], + raw[6],raw[7],raw[8],raw[9]); + snprintf(info->info1,sizeof(info->info1),"Tire ID %02X%02X%02X", + raw[4],raw[5],raw[6]); /* Only 28 bits of ID, not 32. */ + snprintf(info->info2,sizeof(info->info2),"Pressure %.2f kpa", (double)kpa); + snprintf(info->info3,sizeof(info->info3),"Temperature %d C", temp_c); + return true; +} + +ProtoViewDecoder SchraderEG53MA4TPMSDecoder = { + "Schrader EG53MA4 TPMS", decode +}; diff --git a/applications/plugins/protoview/protocols/tpms/toyota.c b/applications/plugins/protoview/protocols/tpms/toyota.c new file mode 100644 index 000000000..b27353739 --- /dev/null +++ b/applications/plugins/protoview/protocols/tpms/toyota.c @@ -0,0 +1,77 @@ +/* Toyota tires TPMS. Usually 443.92 Mhz FSK (In Europe). + * + * Preamble + sync + 64 bits of data. ~48us short pulse length. + * + * The preamble + sync is something like: + * + * 10101010101 (preamble) + 001111[1] (sync) + * + * Note: the final [1] means that sometimes it is four 1s, sometimes + * five, depending on the short pulse length detection and the exact + * duration of the high long pulse. After the sync, a differential + * Manchester encoded payload follows. However the Flipper's CC1101 + * often can't decode correctly the initial alternating pattern 101010101, + * so what we do is to seek just the sync, that is "001111" or "0011111", + * however we now that it must be followed by one differenitally encoded + * bit, so we can use also the first symbol of data to force a more robust + * detection, and look for one of the following: + * + * [001111]00 + * [0011111]00 + * [001111]01 + * [0011111]01 + */ + +#include "../../app.h" + +static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo *info) { + + if (numbits-6 < 64*2) return false; /* Ask for 64 bit of data (each bit + is two symbols in the bitmap). */ + + char *sync[] = { + "00111100", + "001111100", + "00111101", + "001111101", + NULL + }; + + int j; + uint32_t off = 0; + for (j = 0; sync[j]; j++) { + off = bitmap_seek_bits(bits,numbytes,0,numbits,sync[j]); + if (off != BITMAP_SEEK_NOT_FOUND) { + off += strlen(sync[j])-2; + break; + } + } + if (off == BITMAP_SEEK_NOT_FOUND) return false; + + FURI_LOG_E(TAG, "Toyota TPMS sync[%s] found", sync[j]); + + uint8_t raw[9]; + uint32_t decoded = + convert_from_diff_manchester(raw,sizeof(raw),bits,numbytes,off,true); + FURI_LOG_E(TAG, "Toyota TPMS decoded bits: %lu", decoded); + + if (decoded < 8*9) return false; /* Require the full 8 bytes. */ + if (crc8(raw,8,0x80,7) != raw[8]) return false; /* Require sane CRC. */ + + float kpa = (float)((raw[4]&0x7f)<<1 | raw[5]>>7) * 0.25 - 7; + int temp = ((raw[5]&0x7f)<<1 | raw[6]>>7) - 40; + + snprintf(info->name,sizeof(info->name),"%s","Toyota TPMS"); + snprintf(info->raw,sizeof(info->raw),"%02X%02X%02X%02X%02X%02X%02X%02X%02X", + raw[0],raw[1],raw[2],raw[3],raw[4],raw[5], + raw[6],raw[7],raw[8]); + snprintf(info->info1,sizeof(info->info1),"Tire ID %02X%02X%02X%02X", + raw[0],raw[1],raw[2],raw[3]); + snprintf(info->info1,sizeof(info->info1),"Pressure %.2f psi", (double)kpa); + snprintf(info->info2,sizeof(info->info2),"Temperature %d C", temp); + return true; +} + +ProtoViewDecoder ToyotaTPMSDecoder = { + "Toyota TPMS", decode +}; diff --git a/applications/plugins/protoview/signal.c b/applications/plugins/protoview/signal.c index a06ec1d74..06e2197c2 100644 --- a/applications/plugins/protoview/signal.c +++ b/applications/plugins/protoview/signal.c @@ -3,8 +3,8 @@ #include "app.h" -bool decode_signal(RawSamplesBuffer* s, uint64_t len, ProtoViewMsgInfo* info); -void initialize_msg_info(ProtoViewMsgInfo* i); +bool decode_signal(RawSamplesBuffer *s, uint64_t len, ProtoViewMsgInfo *info); +void initialize_msg_info(ProtoViewMsgInfo *i); /* ============================================================================= * Raw signal detection @@ -17,7 +17,7 @@ uint32_t duration_delta(uint32_t a, uint32_t b) { } /* Reset the current signal, so that a new one can be detected. */ -void reset_current_signal(ProtoViewApp* app) { +void reset_current_signal(ProtoViewApp *app) { app->signal_bestlen = 0; app->signal_offset = 0; app->signal_decoded = false; @@ -38,47 +38,47 @@ void reset_current_signal(ProtoViewApp* app) { * For instance Oregon2 sensors, in the case of protocol 2.1 will send * pulses of ~400us (RF on) VS ~580us (RF off). */ #define SEARCH_CLASSES 3 -uint32_t search_coherent_signal(RawSamplesBuffer* s, uint32_t idx) { +uint32_t search_coherent_signal(RawSamplesBuffer *s, uint32_t idx) { struct { - uint32_t dur[2]; /* dur[0] = low, dur[1] = high */ - uint32_t count[2]; /* Associated observed frequency. */ + uint32_t dur[2]; /* dur[0] = low, dur[1] = high */ + uint32_t count[2]; /* Associated observed frequency. */ } classes[SEARCH_CLASSES]; - memset(classes, 0, sizeof(classes)); + memset(classes,0,sizeof(classes)); uint32_t minlen = 30, maxlen = 4000; /* Depends on data rate, here we allow for high and low. */ uint32_t len = 0; /* Observed len of coherent samples. */ s->short_pulse_dur = 0; - for(uint32_t j = idx; j < idx + 500; j++) { + for (uint32_t j = idx; j < idx+500; j++) { bool level; uint32_t dur; raw_samples_get(s, j, &level, &dur); - if(dur < minlen || dur > maxlen) break; /* return. */ + if (dur < minlen || dur > maxlen) break; /* return. */ /* Let's see if it matches a class we already have or if we * can populate a new (yet empty) class. */ uint32_t k; - for(k = 0; k < SEARCH_CLASSES; k++) { - if(classes[k].count[level] == 0) { + for (k = 0; k < SEARCH_CLASSES; k++) { + if (classes[k].count[level] == 0) { classes[k].dur[level] = dur; classes[k].count[level] = 1; break; /* Sample accepted. */ } else { uint32_t classavg = classes[k].dur[level]; uint32_t count = classes[k].count[level]; - uint32_t delta = duration_delta(dur, classavg); + uint32_t delta = duration_delta(dur,classavg); /* Is the difference in duration between this signal and * the class we are inspecting less than a given percentage? * If so, accept this signal. */ - if(delta < classavg / 5) { /* 100%/5 = 20%. */ + if (delta < classavg/5) { /* 100%/5 = 20%. */ /* It is useful to compute the average of the class * we are observing. We know how many samples we got so * far, so we can recompute the average easily. * By always having a better estimate of the pulse len * we can avoid missing next samples in case the first * observed samples are too off. */ - classavg = ((classavg * count) + dur) / (count + 1); + classavg = ((classavg * count) + dur) / (count+1); classes[k].dur[level] = classavg; classes[k].count[level]++; break; /* Sample accepted. */ @@ -86,7 +86,7 @@ uint32_t search_coherent_signal(RawSamplesBuffer* s, uint32_t idx) { } } - if(k == SEARCH_CLASSES) break; /* No match, return. */ + if (k == SEARCH_CLASSES) break; /* No match, return. */ /* If we are here, we accepted this sample. Try with the next * one. */ @@ -96,12 +96,14 @@ uint32_t search_coherent_signal(RawSamplesBuffer* s, uint32_t idx) { /* Update the buffer setting the shortest pulse we found * among the three classes. This will be used when scaling * for visualization. */ - uint32_t short_dur[2] = {0, 0}; - for(int j = 0; j < SEARCH_CLASSES; j++) { - for(int level = 0; level < 2; level++) { - if(classes[j].dur[level] == 0) continue; - if(classes[j].count[level] < 3) continue; - if(short_dur[level] == 0 || short_dur[level] > classes[j].dur[level]) { + uint32_t short_dur[2] = {0,0}; + for (int j = 0; j < SEARCH_CLASSES; j++) { + for (int level = 0; level < 2; level++) { + if (classes[j].dur[level] == 0) continue; + if (classes[j].count[level] < 3) continue; + if (short_dur[level] == 0 || + short_dur[level] > classes[j].dur[level]) + { short_dur[level] = classes[j].dur[level]; } } @@ -110,9 +112,9 @@ uint32_t search_coherent_signal(RawSamplesBuffer* s, uint32_t idx) { /* Use the average between high and low short pulses duration. * Often they are a bit different, and using the average is more robust * when we do decoding sampling at short_pulse_dur intervals. */ - if(short_dur[0] == 0) short_dur[0] = short_dur[1]; - if(short_dur[1] == 0) short_dur[1] = short_dur[0]; - s->short_pulse_dur = (short_dur[0] + short_dur[1]) / 2; + if (short_dur[0] == 0) short_dur[0] = short_dur[1]; + if (short_dur[1] == 0) short_dur[1] = short_dur[0]; + s->short_pulse_dur = (short_dur[0]+short_dur[1])/2; return len; } @@ -121,56 +123,54 @@ uint32_t search_coherent_signal(RawSamplesBuffer* s, uint32_t idx) { * in order to find a coherent signal. If a signal that does not appear to * be just noise is found, it is set in DetectedSamples global signal * buffer, that is what is rendered on the screen. */ -void scan_for_signal(ProtoViewApp* app) { +void scan_for_signal(ProtoViewApp *app) { /* We need to work on a copy: the RawSamples buffer is populated * by the background thread receiving data. */ - RawSamplesBuffer* copy = raw_samples_alloc(); - raw_samples_copy(copy, RawSamples); + RawSamplesBuffer *copy = raw_samples_alloc(); + raw_samples_copy(copy,RawSamples); /* Try to seek on data that looks to have a regular high low high low * pattern. */ - uint32_t minlen = 18; /* Min run of coherent samples. With less + uint32_t minlen = 18; /* Min run of coherent samples. With less than a few samples it's very easy to mistake noise for signal. */ - ProtoViewMsgInfo* info = malloc(sizeof(ProtoViewMsgInfo)); + ProtoViewMsgInfo *info = malloc(sizeof(ProtoViewMsgInfo)); uint32_t i = 0; - while(i < copy->total - 1) { - uint32_t thislen = search_coherent_signal(copy, i); + while (i < copy->total-1) { + uint32_t thislen = search_coherent_signal(copy,i); /* For messages that are long enough, attempt decoding. */ - if(thislen > minlen) { + if (thislen > minlen) { initialize_msg_info(info); uint32_t saved_idx = copy->idx; /* Save index, see later. */ /* decode_signal() expects the detected signal to start * from index .*/ - raw_samples_center(copy, i); - bool decoded = decode_signal(copy, thislen, info); + raw_samples_center(copy,i); + bool decoded = decode_signal(copy,thislen,info); copy->idx = saved_idx; /* Restore the index as we are scanning the signal in the loop. */ /* Accept this signal as the new signal if either it's longer * than the previous undecoded one, or the previous one was * unknown and this is decoded. */ - if((thislen > app->signal_bestlen && app->signal_decoded == false) || - (app->signal_decoded == false && decoded)) { + if ((thislen > app->signal_bestlen && app->signal_decoded == false) + || (app->signal_decoded == false && decoded)) + { app->signal_info = *info; app->signal_bestlen = thislen; app->signal_decoded = decoded; - raw_samples_copy(DetectedSamples, copy); - raw_samples_center(DetectedSamples, i); - FURI_LOG_E( - TAG, - "===> Displayed sample updated (%d samples %lu us)", - (int)thislen, - DetectedSamples->short_pulse_dur); + raw_samples_copy(DetectedSamples,copy); + raw_samples_center(DetectedSamples,i); + FURI_LOG_E(TAG, "===> Displayed sample updated (%d samples %lu us)", + (int)thislen, DetectedSamples->short_pulse_dur); /* Adjust raw view scale if the signal has an high * data rate. */ - if(DetectedSamples->short_pulse_dur < 75) + if (DetectedSamples->short_pulse_dur < 75) app->us_scale = 10; - else if(DetectedSamples->short_pulse_dur < 145) + else if (DetectedSamples->short_pulse_dur < 145) app->us_scale = 30; } } @@ -196,43 +196,48 @@ void scan_for_signal(ProtoViewApp* app) { /* Set the 'bitpos' bit to value 'val', in the specified bitmap * 'b' of len 'blen'. * Out of range bits will silently be discarded. */ -void bitmap_set(uint8_t* b, uint32_t blen, uint32_t bitpos, bool val) { - uint32_t byte = bitpos / 8; - uint32_t bit = 7 - (bitpos & 7); - if(byte >= blen) return; - if(val) - b[byte] |= 1 << bit; +void bitmap_set(uint8_t *b, uint32_t blen, uint32_t bitpos, bool val) { + uint32_t byte = bitpos/8; + uint32_t bit = 7-(bitpos&7); + if (byte >= blen) return; + if (val) + b[byte] |= 1<= blen) return 0; - return (b[byte] & (1 << bit)) != 0; +bool bitmap_get(uint8_t *b, uint32_t blen, uint32_t bitpos) { + uint32_t byte = bitpos/8; + uint32_t bit = 7-(bitpos&7); + if (byte >= blen) return 0; + return (b[byte] & (1< 56781234 */ + b = (b&0xf0)>>4 | (b&0x0f)<<4; + /* Step 2: swap adjacent pairs : 56781234 -> 78563412 */ + b = (b&0xcc)>>2 | (b&0x33)<<2; + /* Step 3: swap adjacent bits : 78563412 -> 87654321 */ + b = (b&0xaa)>>1 | (b&0x55)<<1; + p[j] = b; } } /* Return true if the specified sequence of bits, provided as a string in the * form "11010110..." is found in the 'b' bitmap of 'blen' bits at 'bitpos' * position. */ -bool bitmap_match_bits(uint8_t* b, uint32_t blen, uint32_t bitpos, const char* bits) { - for(size_t j = 0; bits[j]; j++) { +bool bitmap_match_bits(uint8_t *b, uint32_t blen, uint32_t bitpos, const char *bits) { + for (size_t j = 0; bits[j]; j++) { bool expected = (bits[j] == '1') ? true : false; - if(bitmap_get(b, blen, bitpos + j) != expected) return false; + if (bitmap_get(b,blen,bitpos+j) != expected) return false; } return true; } @@ -245,17 +250,12 @@ bool bitmap_match_bits(uint8_t* b, uint32_t blen, uint32_t bitpos, const char* b * Note: there are better algorithms, such as Boyer-Moore. Here we hope that * for the kind of patterns we search we'll have a lot of early stops so * we use a vanilla approach. */ -uint32_t bitmap_seek_bits( - uint8_t* b, - uint32_t blen, - uint32_t startpos, - uint32_t maxbits, - const char* bits) { - uint32_t endpos = startpos + blen * 8; - uint32_t end2 = startpos + maxbits; - if(end2 < endpos) endpos = end2; - for(uint32_t j = startpos; j < endpos; j++) - if(bitmap_match_bits(b, blen, j, bits)) return j; +uint32_t bitmap_seek_bits(uint8_t *b, uint32_t blen, uint32_t startpos, uint32_t maxbits, const char *bits) { + uint32_t endpos = startpos+blen*8; + uint32_t end2 = startpos+maxbits; + if (end2 < endpos) endpos = end2; + for (uint32_t j = startpos; j < endpos; j++) + if (bitmap_match_bits(b,blen,j,bits)) return j; return BITMAP_SEEK_NOT_FOUND; } @@ -264,10 +264,10 @@ uint32_t bitmap_seek_bits( * This function is useful in order to set the test vectors in the protocol * decoders, to see if the decoding works regardless of the fact we are able * to actually receive a given signal. */ -void bitmap_set_pattern(uint8_t* b, uint32_t blen, const char* pat) { +void bitmap_set_pattern(uint8_t *b, uint32_t blen, const char *pat) { uint32_t i = 0; while(pat[i]) { - bitmap_set(b, blen, i, pat[i] == '1'); + bitmap_set(b,blen,i,pat[i] == '1'); i++; } } @@ -299,36 +299,31 @@ void bitmap_set_pattern(uint8_t* b, uint32_t blen, const char* pat) { * bits set into the buffer 'b'. The 'rate' argument, in microseconds, is * the detected short-pulse duration. We expect the line code to be * meaningful when interpreted at multiples of 'rate'. */ -uint32_t convert_signal_to_bits( - uint8_t* b, - uint32_t blen, - RawSamplesBuffer* s, - uint32_t idx, - uint32_t count, - uint32_t rate) { - if(rate == 0) return 0; /* We can't perform the conversion. */ +uint32_t convert_signal_to_bits(uint8_t *b, uint32_t blen, RawSamplesBuffer *s, uint32_t idx, uint32_t count, uint32_t rate) { + if (rate == 0) return 0; /* We can't perform the conversion. */ uint32_t bitpos = 0; - for(uint32_t j = 0; j < count; j++) { + for (uint32_t j = 0; j < count; j++) { uint32_t dur; bool level; - raw_samples_get(s, j + idx, &level, &dur); + raw_samples_get(s, j+idx, &level, &dur); uint32_t numbits = dur / rate; /* full bits that surely fit. */ - uint32_t rest = dur % rate; /* How much we are left with. */ - if(rest > rate / 2) numbits++; /* There is another one. */ + uint32_t rest = dur % rate; /* How much we are left with. */ + if (rest > rate/2) numbits++; /* There is another one. */ /* Limit how much a single sample can spawn. There are likely no * protocols doing such long pulses when the rate is low. */ - if(numbits > 1024) numbits = 1024; + if (numbits > 1024) numbits = 1024; - if(0) /* Super verbose, so not under the DEBUG_MSG define. */ - FURI_LOG_E(TAG, "%lu converted into %lu (%d) bits", dur, numbits, (int)level); + if (0) /* Super verbose, so not under the DEBUG_MSG define. */ + FURI_LOG_E(TAG, "%lu converted into %lu (%d) bits", + dur,numbits,(int)level); /* If the signal is too short, let's claim it an interference * and ignore it completely. */ - if(numbits == 0) continue; + if (numbits == 0) continue; - while(numbits--) bitmap_set(b, blen, bitpos++, level); + while(numbits--) bitmap_set(b,blen,bitpos++,level); } return bitpos; } @@ -345,29 +340,23 @@ uint32_t convert_signal_to_bits( * specified in bytes by the caller, via the 'len' parameters). * * The decoding starts at the specified offset (in bits) 'off'. */ -uint32_t convert_from_line_code( - uint8_t* buf, - uint64_t buflen, - uint8_t* bits, - uint32_t len, - uint32_t off, - const char* zero_pattern, - const char* one_pattern) { +uint32_t convert_from_line_code(uint8_t *buf, uint64_t buflen, uint8_t *bits, uint32_t len, uint32_t off, const char *zero_pattern, const char *one_pattern) +{ uint32_t decoded = 0; /* Number of bits extracted. */ len *= 8; /* Convert bytes to bits. */ while(off < len) { bool bitval; - if(bitmap_match_bits(bits, len, off, zero_pattern)) { + if (bitmap_match_bits(bits,len,off,zero_pattern)) { bitval = false; off += strlen(zero_pattern); - } else if(bitmap_match_bits(bits, len, off, one_pattern)) { + } else if (bitmap_match_bits(bits,len,off,one_pattern)) { bitval = true; off += strlen(one_pattern); } else { break; } - bitmap_set(buf, buflen, decoded++, bitval); - if(decoded / 8 == buflen) break; /* No space left on target buffer. */ + bitmap_set(buf,buflen,decoded++,bitval); + if (decoded/8 == buflen) break; /* No space left on target buffer. */ } return decoded; } @@ -378,22 +367,17 @@ uint32_t convert_from_line_code( * in differential codings the next bits depend on the previous one. * * Parameters and return values are like convert_from_line_code(). */ -uint32_t convert_from_diff_manchester( - uint8_t* buf, - uint64_t buflen, - uint8_t* bits, - uint32_t len, - uint32_t off, - bool previous) { +uint32_t convert_from_diff_manchester(uint8_t *buf, uint64_t buflen, uint8_t *bits, uint32_t len, uint32_t off, bool previous) +{ uint32_t decoded = 0; len *= 8; /* Conver to bits. */ - for(uint32_t j = off; j < len; j += 2) { - bool b0 = bitmap_get(bits, len, j); - bool b1 = bitmap_get(bits, len, j + 1); - if(b0 == previous) break; /* Each new bit must switch value. */ - bitmap_set(buf, buflen, decoded++, b0 == b1); + for (uint32_t j = off; j < len; j += 2) { + bool b0 = bitmap_get(bits,len,j); + bool b1 = bitmap_get(bits,len,j+1); + if (b0 == previous) break; /* Each new bit must switch value. */ + bitmap_set(buf,buflen,decoded++,b0 == b1); previous = b1; - if(decoded / 8 == buflen) break; /* No space left on target buffer. */ + if (decoded/8 == buflen) break; /* No space left on target buffer. */ } return decoded; } @@ -406,52 +390,51 @@ extern ProtoViewDecoder B4B1Decoder; extern ProtoViewDecoder RenaultTPMSDecoder; extern ProtoViewDecoder ToyotaTPMSDecoder; extern ProtoViewDecoder SchraderTPMSDecoder; +extern ProtoViewDecoder SchraderEG53MA4TPMSDecoder; extern ProtoViewDecoder CitroenTPMSDecoder; extern ProtoViewDecoder FordTPMSDecoder; +extern ProtoViewDecoder KeeloqDecoder; -ProtoViewDecoder* Decoders[] = { - &Oregon2Decoder, /* Oregon sensors v2.1 protocol. */ - &B4B1Decoder, /* PT, SC, ... 24 bits remotes. */ - &RenaultTPMSDecoder, /* Renault TPMS. */ - &ToyotaTPMSDecoder, /* Toyota TPMS. */ - &SchraderTPMSDecoder, /* Schrader TPMS. */ - &CitroenTPMSDecoder, /* Citroen TPMS. */ - &FordTPMSDecoder, /* Ford TPMS. */ - NULL}; +ProtoViewDecoder *Decoders[] = { + &Oregon2Decoder, /* Oregon sensors v2.1 protocol. */ + &B4B1Decoder, /* PT, SC, ... 24 bits remotes. */ + &RenaultTPMSDecoder, /* Renault TPMS. */ + &ToyotaTPMSDecoder, /* Toyota TPMS. */ + &SchraderTPMSDecoder, /* Schrader TPMS. */ + &SchraderEG53MA4TPMSDecoder, /* Schrader EG53MA4 TPMS. */ + &CitroenTPMSDecoder, /* Citroen TPMS. */ + &FordTPMSDecoder, /* Ford TPMS. */ + &KeeloqDecoder, /* Keeloq remote. */ + NULL +}; /* Reset the message info structure before passing it to the decoding * functions. */ -void initialize_msg_info(ProtoViewMsgInfo* i) { - memset(i, 0, sizeof(ProtoViewMsgInfo)); +void initialize_msg_info(ProtoViewMsgInfo *i) { + memset(i,0,sizeof(ProtoViewMsgInfo)); } /* This function is called when a new signal is detected. It converts it * to a bitstream, and the calls the protocol specific functions for * decoding. If the signal was decoded correctly by some protocol, true * is returned. Otherwise false is returned. */ -bool decode_signal(RawSamplesBuffer* s, uint64_t len, ProtoViewMsgInfo* info) { - uint32_t bitmap_bits_size = 4096 * 8; - uint32_t bitmap_size = bitmap_bits_size / 8; +bool decode_signal(RawSamplesBuffer *s, uint64_t len, ProtoViewMsgInfo *info) { + uint32_t bitmap_bits_size = 4096*8; + uint32_t bitmap_size = bitmap_bits_size/8; /* We call the decoders with an offset a few samples before the actual * signal detected and for a len of a few bits after its end. */ uint32_t before_samples = 20; uint32_t after_samples = 100; - uint8_t* bitmap = malloc(bitmap_size); - uint32_t bits = convert_signal_to_bits( - bitmap, - bitmap_size, - s, - -before_samples, - len + before_samples + after_samples, - s->short_pulse_dur); + uint8_t *bitmap = malloc(bitmap_size); + uint32_t bits = convert_signal_to_bits(bitmap,bitmap_size,s,-before_samples,len+before_samples+after_samples,s->short_pulse_dur); - if(DEBUG_MSG) { /* Useful for debugging purposes. Don't remove. */ - char* str = malloc(1024); + if (DEBUG_MSG) { /* Useful for debugging purposes. Don't remove. */ + char *str = malloc(1024); uint32_t j; - for(j = 0; j < bits && j < 1023; j++) { - str[j] = bitmap_get(bitmap, bitmap_size, j) ? '1' : '0'; + for (j = 0; j < bits && j < 1023; j++) { + str[j] = bitmap_get(bitmap,bitmap_size,j) ? '1' : '0'; } str[j] = 0; FURI_LOG_E(TAG, "%lu bits sampled: %s", bits, str); @@ -464,25 +447,18 @@ bool decode_signal(RawSamplesBuffer* s, uint64_t len, ProtoViewMsgInfo* info) { bool decoded = false; while(Decoders[j]) { uint32_t start_time = furi_get_tick(); - decoded = Decoders[j]->decode(bitmap, bitmap_size, bits, info); + decoded = Decoders[j]->decode(bitmap,bitmap_size,bits,info); uint32_t delta = furi_get_tick() - start_time; - FURI_LOG_E(TAG, "Decoder %s took %lu ms", Decoders[j]->name, (unsigned long)delta); - if(decoded) break; + FURI_LOG_E(TAG, "Decoder %s took %lu ms", + Decoders[j]->name, (unsigned long)delta); + if (decoded) break; j++; } - if(!decoded) { + if (!decoded) { FURI_LOG_E(TAG, "No decoding possible"); } else { - FURI_LOG_E( - TAG, - "Decoded %s, raw=%s info=[%s,%s,%s,%s]", - info->name, - info->raw, - info->info1, - info->info2, - info->info3, - info->info4); + FURI_LOG_E(TAG, "Decoded %s, raw=%s info=[%s,%s,%s,%s]", info->name, info->raw, info->info1, info->info2, info->info3, info->info4); } free(bitmap); return decoded; diff --git a/applications/plugins/protoview/ui.c b/applications/plugins/protoview/ui.c index 2a974756b..e22e4d57e 100644 --- a/applications/plugins/protoview/ui.c +++ b/applications/plugins/protoview/ui.c @@ -3,24 +3,28 @@ #include "app.h" -void canvas_draw_str_with_border( - Canvas* canvas, - uint8_t x, - uint8_t y, - const char* str, - Color text_color, - Color border_color) { +void canvas_draw_str_with_border(Canvas* canvas, uint8_t x, uint8_t y, const char* str, Color text_color, Color border_color) +{ struct { - uint8_t x; - uint8_t y; - } dir[8] = {{-1, -1}, {0, -1}, {1, -1}, {1, 0}, {1, 1}, {0, 1}, {-1, 1}, {-1, 0}}; + uint8_t x; uint8_t y; + } dir[8] = { + {-1,-1}, + {0,-1}, + {1,-1}, + {1,0}, + {1,1}, + {0,1}, + {-1,1}, + {-1,0} + }; /* Rotate in all the directions writing the same string to create a * border, then write the actual string in the other color in the * middle. */ canvas_set_color(canvas, border_color); - for(int j = 0; j < 8; j++) canvas_draw_str(canvas, x + dir[j].x, y + dir[j].y, str); + for (int j = 0; j < 8; j++) + canvas_draw_str(canvas,x+dir[j].x,y+dir[j].y,str); canvas_set_color(canvas, text_color); - canvas_draw_str(canvas, x, y, str); + canvas_draw_str(canvas,x,y,str); canvas_set_color(canvas, ColorBlack); } diff --git a/applications/plugins/protoview/view_direct_sampling.c b/applications/plugins/protoview/view_direct_sampling.c index 1ab90f096..251a289b8 100644 --- a/applications/plugins/protoview/view_direct_sampling.c +++ b/applications/plugins/protoview/view_direct_sampling.c @@ -7,46 +7,47 @@ /* Read directly from the G0 CC1101 pin, and draw a black or white * dot depending on the level. */ -void render_view_direct_sampling(Canvas* const canvas, ProtoViewApp* app) { - if(!app->direct_sampling_enabled) { +void render_view_direct_sampling(Canvas *const canvas, ProtoViewApp *app) { + if (!app->direct_sampling_enabled) { canvas_set_font(canvas, FontSecondary); - canvas_draw_str(canvas, 2, 9, "Direct sampling is a special"); - canvas_draw_str(canvas, 2, 18, "mode that displays the signal"); - canvas_draw_str(canvas, 2, 27, "captured in real time. Like in"); - canvas_draw_str(canvas, 2, 36, "a old CRT TV. It's very slow."); - canvas_draw_str(canvas, 2, 45, "Can crash your Flipper."); + canvas_draw_str(canvas,2,9,"Direct sampling is a special"); + canvas_draw_str(canvas,2,18,"mode that displays the signal"); + canvas_draw_str(canvas,2,27,"captured in real time. Like in"); + canvas_draw_str(canvas,2,36,"a old CRT TV. It's very slow."); + canvas_draw_str(canvas,2,45,"Can crash your Flipper."); canvas_set_font(canvas, FontPrimary); - canvas_draw_str(canvas, 14, 60, "To enable press OK"); + canvas_draw_str(canvas,14,60,"To enable press OK"); return; } - for(int y = 0; y < 64; y++) { - for(int x = 0; x < 128; x++) { + for (int y = 0; y < 64; y++) { + for (int x = 0; x < 128; x++) { bool level = furi_hal_gpio_read(&gpio_cc1101_g0); - if(level) canvas_draw_dot(canvas, x, y); + if (level) canvas_draw_dot(canvas,x,y); /* Busy loop: this is a terrible approach as it blocks * everything else, but for now it's the best we can do * to obtain direct data with some spacing. */ - uint32_t x = 250; - while(x--) - ; + uint32_t x = 250; while(x--); } } canvas_set_font(canvas, FontSecondary); - canvas_draw_str_with_border(canvas, 36, 60, "Direct sampling", ColorWhite, ColorBlack); + canvas_draw_str_with_border(canvas,36,60,"Direct sampling", + ColorWhite,ColorBlack); } /* Handle input */ -void process_input_direct_sampling(ProtoViewApp* app, InputEvent input) { - if(input.type == InputTypePress && input.key == InputKeyOk) { +void process_input_direct_sampling(ProtoViewApp *app, InputEvent input) { + if (input.type == InputTypePress && input.key == InputKeyOk) { app->direct_sampling_enabled = !app->direct_sampling_enabled; } } /* Enter view. Stop the subghz thread to prevent access as we read * the CC1101 data directly. */ -void view_enter_direct_sampling(ProtoViewApp* app) { - if(app->txrx->txrx_state == TxRxStateRx && !app->txrx->debug_timer_sampling) { +void view_enter_direct_sampling(ProtoViewApp *app) { + if (app->txrx->txrx_state == TxRxStateRx && + !app->txrx->debug_timer_sampling) + { subghz_worker_stop(app->txrx->worker); } else { raw_sampling_worker_stop(app); @@ -54,8 +55,10 @@ void view_enter_direct_sampling(ProtoViewApp* app) { } /* Exit view. Restore the subghz thread. */ -void view_exit_direct_sampling(ProtoViewApp* app) { - if(app->txrx->txrx_state == TxRxStateRx && !app->txrx->debug_timer_sampling) { +void view_exit_direct_sampling(ProtoViewApp *app) { + if (app->txrx->txrx_state == TxRxStateRx && + !app->txrx->debug_timer_sampling) + { subghz_worker_start(app->txrx->worker); } else { raw_sampling_worker_start(app); diff --git a/applications/plugins/protoview/view_info.c b/applications/plugins/protoview/view_info.c index aeca36668..775c8abc2 100644 --- a/applications/plugins/protoview/view_info.c +++ b/applications/plugins/protoview/view_info.c @@ -4,10 +4,10 @@ #include "app.h" /* Renders the view with the detected message information. */ -void render_view_info(Canvas* const canvas, ProtoViewApp* app) { - if(app->signal_decoded == false) { +void render_view_info(Canvas *const canvas, ProtoViewApp *app) { + if (app->signal_decoded == false) { canvas_set_font(canvas, FontSecondary); - canvas_draw_str(canvas, 30, 36, "No signal decoded"); + canvas_draw_str(canvas, 30,36,"No signal decoded"); return; } @@ -20,25 +20,21 @@ void render_view_info(Canvas* const canvas, ProtoViewApp* app) { /* Info fields. */ char buf[128]; canvas_set_font(canvas, FontSecondary); - if(app->signal_info.raw[0]) { - snprintf(buf, sizeof(buf), "Raw: %s", app->signal_info.raw); + if (app->signal_info.raw[0]) { + snprintf(buf,sizeof(buf),"Raw: %s", app->signal_info.raw); canvas_draw_str(canvas, 0, y, buf); y += lineheight; } - canvas_draw_str(canvas, 0, y, app->signal_info.info1); - y += lineheight; - canvas_draw_str(canvas, 0, y, app->signal_info.info2); - y += lineheight; - canvas_draw_str(canvas, 0, y, app->signal_info.info3); - y += lineheight; - canvas_draw_str(canvas, 0, y, app->signal_info.info4); - y += lineheight; + canvas_draw_str(canvas, 0, y, app->signal_info.info1); y += lineheight; + canvas_draw_str(canvas, 0, y, app->signal_info.info2); y += lineheight; + canvas_draw_str(canvas, 0, y, app->signal_info.info3); y += lineheight; + canvas_draw_str(canvas, 0, y, app->signal_info.info4); y += lineheight; } /* Handle input for the info view. */ -void process_input_info(ProtoViewApp* app, InputEvent input) { - if(input.type == InputTypeShort) { - if(input.key == InputKeyOk) { +void process_input_info(ProtoViewApp *app, InputEvent input) { + if (input.type == InputTypeShort) { + if (input.key == InputKeyOk) { /* Reset the current sample to capture the next. */ reset_current_signal(app); } diff --git a/applications/plugins/protoview/view_raw_signal.c b/applications/plugins/protoview/view_raw_signal.c index c20e3a69d..58d23e8ee 100644 --- a/applications/plugins/protoview/view_raw_signal.c +++ b/applications/plugins/protoview/view_raw_signal.c @@ -12,7 +12,7 @@ * * The 'idx' argument is the first sample to render in the circular * buffer. */ -void render_signal(ProtoViewApp* app, Canvas* const canvas, RawSamplesBuffer* buf, uint32_t idx) { +void render_signal(ProtoViewApp *app, Canvas *const canvas, RawSamplesBuffer *buf, uint32_t idx) { canvas_set_color(canvas, ColorBlack); int rows = 8; @@ -20,29 +20,31 @@ void render_signal(ProtoViewApp* app, Canvas* const canvas, RawSamplesBuffer* bu uint32_t start_idx = idx; bool level = 0; uint32_t dur = 0, sample_num = 0; - for(int row = 0; row < rows; row++) { - for(int x = 0; x < 128; x++) { - int y = 3 + row * 8; - if(dur < time_per_pixel / 2) { + for (int row = 0; row < rows ; row++) { + for (int x = 0; x < 128; x++) { + int y = 3 + row*8; + if (dur < time_per_pixel/2) { /* Get more data. */ raw_samples_get(buf, idx++, &level, &dur); sample_num++; } - canvas_draw_line(canvas, x, y, x, y - (level * 3)); + canvas_draw_line(canvas, x,y,x,y-(level*3)); /* Write a small triangle under the last sample detected. */ - if(app->signal_bestlen != 0 && sample_num + start_idx == app->signal_bestlen + 1) { - canvas_draw_dot(canvas, x, y + 2); - canvas_draw_dot(canvas, x - 1, y + 3); - canvas_draw_dot(canvas, x, y + 3); - canvas_draw_dot(canvas, x + 1, y + 3); + if (app->signal_bestlen != 0 && + sample_num+start_idx == app->signal_bestlen+1) + { + canvas_draw_dot(canvas,x,y+2); + canvas_draw_dot(canvas,x-1,y+3); + canvas_draw_dot(canvas,x,y+3); + canvas_draw_dot(canvas,x+1,y+3); sample_num++; /* Make sure we don't mark the next, too. */ } /* Remove from the current level duration the time we * just plot. */ - if(dur > time_per_pixel) + if (dur > time_per_pixel) dur -= time_per_pixel; else dur = 0; @@ -51,46 +53,45 @@ void render_signal(ProtoViewApp* app, Canvas* const canvas, RawSamplesBuffer* bu } /* Raw pulses rendering. This is our default view. */ -void render_view_raw_pulses(Canvas* const canvas, ProtoViewApp* app) { +void render_view_raw_pulses(Canvas *const canvas, ProtoViewApp *app) { /* Show signal. */ render_signal(app, canvas, DetectedSamples, app->signal_offset); /* Show signal information. */ char buf[64]; - snprintf(buf, sizeof(buf), "%luus", (unsigned long)DetectedSamples->short_pulse_dur); + snprintf(buf,sizeof(buf),"%luus", + (unsigned long)DetectedSamples->short_pulse_dur); canvas_set_font(canvas, FontSecondary); canvas_draw_str_with_border(canvas, 97, 63, buf, ColorWhite, ColorBlack); - if(app->signal_decoded) { + if (app->signal_decoded) { canvas_set_font(canvas, FontPrimary); canvas_draw_str_with_border(canvas, 1, 61, app->signal_info.name, ColorWhite, ColorBlack); } } /* Handle input for the raw pulses view. */ -void process_input_raw_pulses(ProtoViewApp* app, InputEvent input) { - if(input.type == InputTypeRepeat) { +void process_input_raw_pulses(ProtoViewApp *app, InputEvent input) { + if (input.type == InputTypeRepeat) { /* Handle panning of the signal window. Long pressing * right will show successive samples, long pressing left * previous samples. */ - if(input.key == InputKeyRight) - app->signal_offset++; - else if(input.key == InputKeyLeft) - app->signal_offset--; - else if(input.key == InputKeyOk) { + if (input.key == InputKeyRight) app->signal_offset++; + else if (input.key == InputKeyLeft) app->signal_offset--; + else if (input.key == InputKeyOk) { app->signal_offset = 0; app->us_scale = PROTOVIEW_RAW_VIEW_DEFAULT_SCALE; } - } else if(input.type == InputTypeShort) { - if(input.key == InputKeyOk) { + } else if (input.type == InputTypeShort) { + if (input.key == InputKeyOk) { /* Reset the current sample to capture the next. */ reset_current_signal(app); - } else if(input.key == InputKeyDown) { + } else if (input.key == InputKeyDown) { /* Rescaling. The set becomes finer under 50us per pixel. */ uint32_t scale_step = app->us_scale >= 50 ? 50 : 10; - if(app->us_scale < 500) app->us_scale += scale_step; - } else if(input.key == InputKeyUp) { + if (app->us_scale < 500) app->us_scale += scale_step; + } else if (input.key == InputKeyUp) { uint32_t scale_step = app->us_scale > 50 ? 50 : 10; - if(app->us_scale > 10) app->us_scale -= scale_step; + if (app->us_scale > 10) app->us_scale -= scale_step; } } } diff --git a/applications/plugins/protoview/view_settings.c b/applications/plugins/protoview/view_settings.c index 09abf5a2a..1e2dce226 100644 --- a/applications/plugins/protoview/view_settings.c +++ b/applications/plugins/protoview/view_settings.c @@ -6,30 +6,30 @@ /* Renders a single view with frequency and modulation setting. However * this are logically two different views, and only one of the settings * will be highlighted. */ -void render_view_settings(Canvas* const canvas, ProtoViewApp* app) { +void render_view_settings(Canvas *const canvas, ProtoViewApp *app) { canvas_set_font(canvas, FontPrimary); - if(app->current_view == ViewFrequencySettings) - canvas_draw_str_with_border(canvas, 1, 10, "Frequency", ColorWhite, ColorBlack); + if (app->current_view == ViewFrequencySettings) + canvas_draw_str_with_border(canvas,1,10,"Frequency",ColorWhite,ColorBlack); else - canvas_draw_str(canvas, 1, 10, "Frequency"); + canvas_draw_str(canvas,1,10,"Frequency"); - if(app->current_view == ViewModulationSettings) - canvas_draw_str_with_border(canvas, 70, 10, "Modulation", ColorWhite, ColorBlack); + if (app->current_view == ViewModulationSettings) + canvas_draw_str_with_border(canvas,70,10,"Modulation",ColorWhite,ColorBlack); else - canvas_draw_str(canvas, 70, 10, "Modulation"); + canvas_draw_str(canvas,70,10,"Modulation"); canvas_set_font(canvas, FontSecondary); - canvas_draw_str(canvas, 10, 61, "Use up and down to modify"); + canvas_draw_str(canvas,10,61,"Use up and down to modify"); - if(app->txrx->debug_timer_sampling) - canvas_draw_str(canvas, 3, 52, "(DEBUG timer sampling is ON)"); + if (app->txrx->debug_timer_sampling) + canvas_draw_str(canvas,3,52,"(DEBUG timer sampling is ON)"); /* Show frequency. We can use big numbers font since it's just a number. */ - if(app->current_view == ViewFrequencySettings) { + if (app->current_view == ViewFrequencySettings) { char buf[16]; - snprintf(buf, sizeof(buf), "%.2f", (double)app->frequency / 1000000); + snprintf(buf,sizeof(buf),"%.2f",(double)app->frequency/1000000); canvas_set_font(canvas, FontBigNumbers); canvas_draw_str(canvas, 30, 40, buf); - } else if(app->current_view == ViewModulationSettings) { + } else if (app->current_view == ViewModulationSettings) { int current = app->modulation; canvas_set_font(canvas, FontPrimary); canvas_draw_str(canvas, 33, 39, ProtoViewModulations[current].name); @@ -37,13 +37,13 @@ void render_view_settings(Canvas* const canvas, ProtoViewApp* app) { } /* Handle input for the settings view. */ -void process_input_settings(ProtoViewApp* app, InputEvent input) { - if(input.type == InputTypeLong && input.key == InputKeyOk) { +void process_input_settings(ProtoViewApp *app, InputEvent input) { + if (input.type == InputTypeLong && input.key == InputKeyOk) { /* Long pressing to OK sets the default frequency and * modulation. */ app->frequency = subghz_setting_get_default_frequency(app->setting); app->modulation = 0; - } else if(0 && input.type == InputTypeLong && input.key == InputKeyDown) { + } else if (0 && input.type == InputTypeLong && input.key == InputKeyDown) { /* Long pressing to down switches between normal and debug * timer sampling mode. NOTE: this feature is disabled for users, * only useful for devs (if useful at all). */ @@ -55,40 +55,42 @@ void process_input_settings(ProtoViewApp* app, InputEvent input) { app->txrx->debug_timer_sampling = !app->txrx->debug_timer_sampling; radio_begin(app); radio_rx(app); - } else if(input.type == InputTypePress && (input.key != InputKeyDown || input.key != InputKeyUp)) { + } else if (input.type == InputTypePress && + (input.key != InputKeyDown || input.key != InputKeyUp)) + { /* Handle up and down to change frequency or modulation. */ - if(app->current_view == ViewFrequencySettings) { + if (app->current_view == ViewFrequencySettings) { size_t curidx = 0, i; size_t count = subghz_setting_get_frequency_count(app->setting); /* Scan the list of frequencies to check for the index of the * currently set frequency. */ for(i = 0; i < count; i++) { - uint32_t freq = subghz_setting_get_frequency(app->setting, i); - if(freq == app->frequency) { + uint32_t freq = subghz_setting_get_frequency(app->setting,i); + if (freq == app->frequency) { curidx = i; break; } } - if(i == count) return; /* Should never happen. */ + if (i == count) return; /* Should never happen. */ - if(input.key == InputKeyUp) { - curidx = curidx == 0 ? count - 1 : curidx - 1; - } else if(input.key == InputKeyDown) { - curidx = (curidx + 1) % count; + if (input.key == InputKeyUp) { + curidx = curidx == 0 ? count-1 : curidx-1; + } else if (input.key == InputKeyDown) { + curidx = (curidx+1) % count; } else { return; } - app->frequency = subghz_setting_get_frequency(app->setting, curidx); - } else if(app->current_view == ViewModulationSettings) { + app->frequency = subghz_setting_get_frequency(app->setting,curidx); + } else if (app->current_view == ViewModulationSettings) { uint32_t count = 0; uint32_t modid = app->modulation; while(ProtoViewModulations[count].name != NULL) count++; - if(input.key == InputKeyUp) { - modid = modid == 0 ? count - 1 : modid - 1; - } else if(input.key == InputKeyDown) { - modid = (modid + 1) % count; + if (input.key == InputKeyUp) { + modid = modid == 0 ? count-1 : modid-1; + } else if (input.key == InputKeyDown) { + modid = (modid+1) % count; } else { return; } @@ -104,13 +106,9 @@ void process_input_settings(ProtoViewApp* app, InputEvent input) { /* When the user switches to some other view, if they changed the parameters * we need to restart the radio with the right frequency and modulation. */ -void view_exit_settings(ProtoViewApp* app) { - if(app->txrx->freq_mod_changed) { - FURI_LOG_E( - TAG, - "Setting view, setting frequency/modulation to %lu %s", - app->frequency, - ProtoViewModulations[app->modulation].name); +void view_exit_settings(ProtoViewApp *app) { + if (app->txrx->freq_mod_changed) { + FURI_LOG_E(TAG, "Setting view, setting frequency/modulation to %lu %s", app->frequency, ProtoViewModulations[app->modulation].name); radio_rx_end(app); radio_begin(app); radio_rx(app); From cd2da151f4a63da400d05a9a7bdc81b47aab5a17 Mon Sep 17 00:00:00 2001 From: VerstreuteSeele Date: Mon, 16 Jan 2023 05:37:32 +0100 Subject: [PATCH 44/60] Update furi_hal_bt.c --- firmware/targets/f7/furi_hal/furi_hal_bt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/firmware/targets/f7/furi_hal/furi_hal_bt.c b/firmware/targets/f7/furi_hal/furi_hal_bt.c index 0857fe4ee..d42f4b7f9 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_bt.c +++ b/firmware/targets/f7/furi_hal/furi_hal_bt.c @@ -218,8 +218,8 @@ bool furi_hal_bt_start_app(FuriHalBtProfile profile, GapEventCallback event_cb, } else if(profile == FuriHalBtProfileHidKeyboard) { // Change MAC address for HID profile config->mac_address[2]++; - // Change name Flipper -> Control - const char* clicker_str = "Control"; + // Change name Flipper -> BLE Remote + const char* clicker_str = "BLE Remote"; memcpy(&config->adv_name[1], clicker_str, strlen(clicker_str)); } if(!gap_init(config, event_cb, context)) { From 87582441c2b5d6b40b9176dd51d5244cc67e6d2e Mon Sep 17 00:00:00 2001 From: jbohack Date: Sun, 15 Jan 2023 23:42:54 -0500 Subject: [PATCH 45/60] added 446 MHz to frequency list --- assets/resources/subghz/assets/setting_user.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/assets/resources/subghz/assets/setting_user.txt b/assets/resources/subghz/assets/setting_user.txt index 0926f6bd7..06a699a6c 100644 --- a/assets/resources/subghz/assets/setting_user.txt +++ b/assets/resources/subghz/assets/setting_user.txt @@ -49,6 +49,7 @@ Frequency: 434620000 Frequency: 434775000 Frequency: 438900000 Frequency: 440175000 +Frequency: 446000000 Frequency: 464000000 Frequency: 779000000 Frequency: 868350000 From a7217088978ffb0f6115f42cbec5d791feffc5bb Mon Sep 17 00:00:00 2001 From: VerstreuteSeele Date: Mon, 16 Jan 2023 05:45:51 +0100 Subject: [PATCH 46/60] Update furi_hal_bt.c --- firmware/targets/f7/furi_hal/furi_hal_bt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/firmware/targets/f7/furi_hal/furi_hal_bt.c b/firmware/targets/f7/furi_hal/furi_hal_bt.c index d42f4b7f9..4e10b90d7 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_bt.c +++ b/firmware/targets/f7/furi_hal/furi_hal_bt.c @@ -218,8 +218,8 @@ bool furi_hal_bt_start_app(FuriHalBtProfile profile, GapEventCallback event_cb, } else if(profile == FuriHalBtProfileHidKeyboard) { // Change MAC address for HID profile config->mac_address[2]++; - // Change name Flipper -> BLE Remote - const char* clicker_str = "BLE Remote"; + // Change name Flipper -> Flipper Remote + const char* clicker_str = "Flipper Remote"; memcpy(&config->adv_name[1], clicker_str, strlen(clicker_str)); } if(!gap_init(config, event_cb, context)) { From 333cf4dadc57e1bb5c65fb5b91869669d5a0afb0 Mon Sep 17 00:00:00 2001 From: VerstreuteSeele Date: Mon, 16 Jan 2023 06:19:04 +0100 Subject: [PATCH 47/60] Update text_input.c --- applications/services/gui/modules/text_input.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/applications/services/gui/modules/text_input.c b/applications/services/gui/modules/text_input.c index 32607e884..9004304cb 100644 --- a/applications/services/gui/modules/text_input.c +++ b/applications/services/gui/modules/text_input.c @@ -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(islower(letter)) { + } else if(isalpha(letter)) { return (letter - 0x20); } else { return letter; @@ -309,9 +309,7 @@ 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); - bool toogle_case = text_length == 0; - if(shift) toogle_case = !toogle_case; - if(toogle_case) { + if(shift) { selected = char_to_uppercase(selected); } @@ -331,6 +329,9 @@ 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; } @@ -567,4 +568,4 @@ void* text_input_get_validator_callback_context(TextInput* text_input) { void text_input_set_header_text(TextInput* text_input, const char* text) { with_view_model( text_input->view, TextInputModel * model, { model->header = text; }, true); -} +} \ No newline at end of file From 9e1a6a6d2ec4a340b2fc0dceda86116044044070 Mon Sep 17 00:00:00 2001 From: Eric Betts Date: Mon, 16 Jan 2023 01:36:59 -0800 Subject: [PATCH 48/60] relocate R_ARM_CALL (#2305) --- lib/flipper_application/elf/elf_file.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/flipper_application/elf/elf_file.c b/lib/flipper_application/elf/elf_file.c index bf98650a2..64d5755ef 100644 --- a/lib/flipper_application/elf/elf_file.c +++ b/lib/flipper_application/elf/elf_file.c @@ -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( From 64b8e3ddb798944ecd2eaac3b682fa7a6fbccec1 Mon Sep 17 00:00:00 2001 From: Willy-JL Date: Mon, 16 Jan 2023 16:51:25 +0000 Subject: [PATCH 49/60] Fix xp bar --- .../settings/dolphin_passport/passport.c | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/applications/settings/dolphin_passport/passport.c b/applications/settings/dolphin_passport/passport.c index 914f7ef0e..b6c94d2c1 100644 --- a/applications/settings/dolphin_passport/passport.c +++ b/applications/settings/dolphin_passport/passport.c @@ -92,19 +92,20 @@ static void render_callback(Canvas* canvas, void* _ctx) { } } uint32_t xp_progress = 0; - uint32_t xp_to_levelup = dolphin_state_xp_to_levelup(stats->icounter); + uint32_t xp_need = dolphin_state_xp_to_levelup(stats->icounter); uint32_t xp_above_last_levelup = dolphin_state_xp_above_last_levelup(stats->icounter); - uint32_t xp_for_current_level = xp_to_levelup + xp_above_last_levelup; - uint32_t xp_next_level = stats->icounter + xp_to_levelup; + uint32_t xp_levelup = 0; + if (ctx->progress_total) { + xp_levelup = xp_need + stats->icounter; + } else { + xp_levelup = xp_need + xp_above_last_levelup; + } + uint32_t xp_have = xp_levelup - xp_need; if(stats->level == 30) { xp_progress = 0; } else { - if(ctx->progress_total) { - xp_progress = stats->icounter * 64 / xp_next_level; - } else { - xp_progress = xp_to_levelup * 64 / xp_for_current_level; - } + xp_progress = xp_need * 64 / xp_levelup; } // multipass @@ -125,11 +126,7 @@ static void render_callback(Canvas* canvas, void* _ctx) { const char* my_name = furi_hal_version_get_name_ptr(); snprintf(level_str, 12, "Level: %hu", stats->level); - if(ctx->progress_total) { - snprintf(xp_str, 12, "%lu/%lu", stats->icounter, xp_next_level); - } else { - snprintf(xp_str, 12, "%lu/%lu", xp_above_last_levelup, xp_for_current_level); - } + snprintf(xp_str, 12, "%lu/%lu", xp_have, xp_levelup); canvas_set_font(canvas, FontSecondary); canvas_draw_str(canvas, 58, 10, my_name ? my_name : "Unknown"); canvas_draw_str(canvas, 58, 22, mood_str); From cf2a1265db2baed3fd13f1d0fb9abff852f90308 Mon Sep 17 00:00:00 2001 From: Willy-JL Date: Mon, 16 Jan 2023 19:18:28 +0000 Subject: [PATCH 50/60] Add a cycle animations setting --- .../desktop/animations/animation_manager.c | 5 +++- .../services/desktop/desktop_settings.h | 1 + .../scenes/desktop_settings_scene_start.c | 28 +++++++++++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/applications/services/desktop/animations/animation_manager.c b/applications/services/desktop/animations/animation_manager.c index 9f6df386c..f76c45383 100644 --- a/applications/services/desktop/animations/animation_manager.c +++ b/applications/services/desktop/animations/animation_manager.c @@ -118,9 +118,12 @@ static void animation_manager_check_blocking_callback(const void* message, void* static void animation_manager_timer_callback(void* context) { furi_assert(context); AnimationManager* animation_manager = context; - if(animation_manager->new_idle_callback) { + DesktopSettings* settings = malloc(sizeof(DesktopSettings)); + DESKTOP_SETTINGS_LOAD(settings); + if(!settings->dont_cycle_animations && animation_manager->new_idle_callback) { animation_manager->new_idle_callback(animation_manager->context); } + free(settings); } static void animation_manager_interact_callback(void* context) { diff --git a/applications/services/desktop/desktop_settings.h b/applications/services/desktop/desktop_settings.h index 55d8640f5..c8be1d6b6 100644 --- a/applications/services/desktop/desktop_settings.h +++ b/applications/services/desktop/desktop_settings.h @@ -64,4 +64,5 @@ typedef struct { uint8_t displayBatteryPercentage; bool is_sfwmode; uint8_t sfw_mode; + uint8_t dont_cycle_animations; } DesktopSettings; diff --git a/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c index 9901740b6..6e64fe80d 100644 --- a/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c @@ -39,6 +39,14 @@ const uint32_t displayBatteryPercentage_value[BATTERY_VIEW_COUNT] = { uint8_t origBattDisp_value = 0; +#define CYCLE_ANIMATIONS_COUNT 2 +const char* const cycle_animations_text[CYCLE_ANIMATIONS_COUNT] = { + "ON", + "OFF", +}; +const uint32_t cycle_animations_value[CYCLE_ANIMATIONS_COUNT] = + {0, 1}; + static void desktop_settings_scene_start_var_list_enter_callback(void* context, uint32_t index) { DesktopSettingsApp* app = context; view_dispatcher_send_custom_event(app->view_dispatcher, index); @@ -60,6 +68,14 @@ static void desktop_settings_scene_start_battery_view_changed(VariableItem* item app->settings.displayBatteryPercentage = index; } +static void desktop_settings_scene_start_cycle_animations_changed(VariableItem* item) { + DesktopSettingsApp* app = variable_item_get_context(item); + uint8_t index = variable_item_get_current_value_index(item); + + variable_item_set_current_value_text(item, cycle_animations_text[index]); + app->settings.dont_cycle_animations = auto_lock_delay_value[index]; +} + void desktop_settings_scene_start_on_enter(void* context) { DesktopSettingsApp* app = context; VariableItemList* variable_item_list = app->variable_item_list; @@ -102,6 +118,18 @@ void desktop_settings_scene_start_on_enter(void* context) { variable_item_set_current_value_index(item, value_index); variable_item_set_current_value_text(item, battery_view_count_text[value_index]); + item = variable_item_list_add( + variable_item_list, + "Cycle animations", + CYCLE_ANIMATIONS_COUNT, + desktop_settings_scene_start_cycle_animations_changed, + app); + + value_index = value_index_uint32( + app->settings.dont_cycle_animations, cycle_animations_value, CYCLE_ANIMATIONS_COUNT); + variable_item_set_current_value_index(item, value_index); + variable_item_set_current_value_text(item, cycle_animations_text[value_index]); + variable_item_list_set_enter_callback( variable_item_list, desktop_settings_scene_start_var_list_enter_callback, app); view_dispatcher_switch_to_view(app->view_dispatcher, DesktopSettingsAppViewVarItemList); From f2c19216380d40ade04fe5918ebb41e2ad205b99 Mon Sep 17 00:00:00 2001 From: Willy-JL Date: Mon, 16 Jan 2023 20:02:40 +0000 Subject: [PATCH 51/60] Change cycle anims setting to control anim length --- .../desktop/animations/animation_manager.c | 15 +++++++------ applications/services/desktop/desktop.c | 4 ++++ .../services/desktop/desktop_settings.h | 2 +- .../scenes/desktop_settings_scene_start.c | 21 +++++++++++++------ 4 files changed, 29 insertions(+), 13 deletions(-) diff --git a/applications/services/desktop/animations/animation_manager.c b/applications/services/desktop/animations/animation_manager.c index f76c45383..cadd50ded 100644 --- a/applications/services/desktop/animations/animation_manager.c +++ b/applications/services/desktop/animations/animation_manager.c @@ -118,12 +118,9 @@ static void animation_manager_check_blocking_callback(const void* message, void* static void animation_manager_timer_callback(void* context) { furi_assert(context); AnimationManager* animation_manager = context; - DesktopSettings* settings = malloc(sizeof(DesktopSettings)); - DESKTOP_SETTINGS_LOAD(settings); - if(!settings->dont_cycle_animations && animation_manager->new_idle_callback) { + if(animation_manager->new_idle_callback) { animation_manager->new_idle_callback(animation_manager->context); } - free(settings); } static void animation_manager_interact_callback(void* context) { @@ -203,7 +200,10 @@ static void animation_manager_start_new_idle(AnimationManager* animation_manager const BubbleAnimation* bubble_animation = animation_storage_get_bubble_animation(animation_manager->current_animation); animation_manager->state = AnimationManagerStateIdle; - furi_timer_start(animation_manager->idle_animation_timer, bubble_animation->duration * 1000); + DesktopSettings* settings = malloc(sizeof(DesktopSettings)); + DESKTOP_SETTINGS_LOAD(settings); + furi_timer_start(animation_manager->idle_animation_timer, (settings->cycle_animations_s - 1) * 1000); + free(settings); } static bool animation_manager_check_blocking(AnimationManager* animation_manager) { @@ -513,8 +513,11 @@ void animation_manager_load_and_continue_animation(AnimationManager* animation_m } else { const BubbleAnimation* animation = animation_storage_get_bubble_animation( animation_manager->current_animation); + DesktopSettings* settings = malloc(sizeof(DesktopSettings)); + DESKTOP_SETTINGS_LOAD(settings); furi_timer_start( - animation_manager->idle_animation_timer, animation->duration * 1000); + animation_manager->idle_animation_timer, (settings->cycle_animations_s - 1) * 1000); + free(settings); } } } else { diff --git a/applications/services/desktop/desktop.c b/applications/services/desktop/desktop.c index e43e6e6e0..b0f3eac34 100644 --- a/applications/services/desktop/desktop.c +++ b/applications/services/desktop/desktop.c @@ -322,6 +322,10 @@ int32_t desktop_srv(void* p) { DESKTOP_SETTINGS_SAVE(&desktop->settings); } + if(!desktop->settings.cycle_animations_s) { + desktop->settings.cycle_animations_s = 3601; + } + desktop_main_set_sfw_mode_state(desktop->main_view, desktop->settings.sfw_mode); scene_manager_next_scene(desktop->scene_manager, DesktopSceneMain); diff --git a/applications/services/desktop/desktop_settings.h b/applications/services/desktop/desktop_settings.h index c8be1d6b6..dd9231b39 100644 --- a/applications/services/desktop/desktop_settings.h +++ b/applications/services/desktop/desktop_settings.h @@ -64,5 +64,5 @@ typedef struct { uint8_t displayBatteryPercentage; bool is_sfwmode; uint8_t sfw_mode; - uint8_t dont_cycle_animations; + uint8_t cycle_animations_s; } DesktopSettings; diff --git a/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c index 6e64fe80d..b158384e0 100644 --- a/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c @@ -39,13 +39,22 @@ const uint32_t displayBatteryPercentage_value[BATTERY_VIEW_COUNT] = { uint8_t origBattDisp_value = 0; -#define CYCLE_ANIMATIONS_COUNT 2 +#define CYCLE_ANIMATIONS_COUNT 10 const char* const cycle_animations_text[CYCLE_ANIMATIONS_COUNT] = { - "ON", "OFF", + "5 M", + "10 M", + "15 M", + "30 M", + "1 H", + "2 H", + "6 H", + "12 H", + "24 H", }; +// Values are offset by 1 so that 0 is not a valid value and desktop.c can detect this to set a default value (3601 / 1 H) const uint32_t cycle_animations_value[CYCLE_ANIMATIONS_COUNT] = - {0, 1}; + {1, 301, 601, 901, 1801, 3601, 7201, 21601, 43201, 86401}; static void desktop_settings_scene_start_var_list_enter_callback(void* context, uint32_t index) { DesktopSettingsApp* app = context; @@ -73,7 +82,7 @@ static void desktop_settings_scene_start_cycle_animations_changed(VariableItem* uint8_t index = variable_item_get_current_value_index(item); variable_item_set_current_value_text(item, cycle_animations_text[index]); - app->settings.dont_cycle_animations = auto_lock_delay_value[index]; + app->settings.cycle_animations_s = cycle_animations_value[index]; } void desktop_settings_scene_start_on_enter(void* context) { @@ -120,13 +129,13 @@ void desktop_settings_scene_start_on_enter(void* context) { item = variable_item_list_add( variable_item_list, - "Cycle animations", + "Cycle Animations", CYCLE_ANIMATIONS_COUNT, desktop_settings_scene_start_cycle_animations_changed, app); value_index = value_index_uint32( - app->settings.dont_cycle_animations, cycle_animations_value, CYCLE_ANIMATIONS_COUNT); + app->settings.cycle_animations_s, cycle_animations_value, CYCLE_ANIMATIONS_COUNT); variable_item_set_current_value_index(item, value_index); variable_item_set_current_value_text(item, cycle_animations_text[value_index]); From 2566106a56db87d58739d707b279731cd9ec2654 Mon Sep 17 00:00:00 2001 From: Willy-JL Date: Mon, 16 Jan 2023 20:16:38 +0000 Subject: [PATCH 52/60] Fix cycle anims setting --- .../services/desktop/animations/animation_manager.c | 8 ++++---- applications/services/desktop/desktop.c | 1 + applications/services/desktop/desktop_settings.h | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/applications/services/desktop/animations/animation_manager.c b/applications/services/desktop/animations/animation_manager.c index cadd50ded..37cd4fd53 100644 --- a/applications/services/desktop/animations/animation_manager.c +++ b/applications/services/desktop/animations/animation_manager.c @@ -197,8 +197,8 @@ static void animation_manager_start_new_idle(AnimationManager* animation_manager StorageAnimation* new_animation = animation_manager_select_idle_animation(animation_manager); animation_manager_replace_current_animation(animation_manager, new_animation); - const BubbleAnimation* bubble_animation = - animation_storage_get_bubble_animation(animation_manager->current_animation); + // const BubbleAnimation* bubble_animation = + // animation_storage_get_bubble_animation(animation_manager->current_animation); animation_manager->state = AnimationManagerStateIdle; DesktopSettings* settings = malloc(sizeof(DesktopSettings)); DESKTOP_SETTINGS_LOAD(settings); @@ -511,8 +511,8 @@ void animation_manager_load_and_continue_animation(AnimationManager* animation_m animation_manager->idle_animation_timer, animation_manager->freezed_animation_time_left); } else { - const BubbleAnimation* animation = animation_storage_get_bubble_animation( - animation_manager->current_animation); + // const BubbleAnimation* animation = animation_storage_get_bubble_animation( + // animation_manager->current_animation); DesktopSettings* settings = malloc(sizeof(DesktopSettings)); DESKTOP_SETTINGS_LOAD(settings); furi_timer_start( diff --git a/applications/services/desktop/desktop.c b/applications/services/desktop/desktop.c index b0f3eac34..719ed3018 100644 --- a/applications/services/desktop/desktop.c +++ b/applications/services/desktop/desktop.c @@ -324,6 +324,7 @@ int32_t desktop_srv(void* p) { if(!desktop->settings.cycle_animations_s) { desktop->settings.cycle_animations_s = 3601; + DESKTOP_SETTINGS_SAVE(&desktop->settings); } desktop_main_set_sfw_mode_state(desktop->main_view, desktop->settings.sfw_mode); diff --git a/applications/services/desktop/desktop_settings.h b/applications/services/desktop/desktop_settings.h index dd9231b39..35299a295 100644 --- a/applications/services/desktop/desktop_settings.h +++ b/applications/services/desktop/desktop_settings.h @@ -64,5 +64,5 @@ typedef struct { uint8_t displayBatteryPercentage; bool is_sfwmode; uint8_t sfw_mode; - uint8_t cycle_animations_s; + uint32_t cycle_animations_s; } DesktopSettings; From affaab7db751381fe8b10431c0856d25bfcbf1b0 Mon Sep 17 00:00:00 2001 From: VerstreuteSeele Date: Tue, 17 Jan 2023 00:28:45 +0100 Subject: [PATCH 53/60] Rename Cli-Gui Bridge to "CLI (subghz chat)" --- applications/plugins/cli_bridge/application.fam | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/applications/plugins/cli_bridge/application.fam b/applications/plugins/cli_bridge/application.fam index c9baa5254..60cd9648d 100644 --- a/applications/plugins/cli_bridge/application.fam +++ b/applications/plugins/cli_bridge/application.fam @@ -1,6 +1,6 @@ App( appid="cli_gui", - name="CLI-GUI Bridge", + name="CLI (subghz chat)", apptype=FlipperAppType.EXTERNAL, entry_point="cligui_main", requires=["gui","cli"], From b7a452900a7794623aff0ac2ed7266fe3aaa8ca2 Mon Sep 17 00:00:00 2001 From: VerstreuteSeele Date: Tue, 17 Jan 2023 01:57:23 +0100 Subject: [PATCH 54/60] fix slight display issue --- .../desktop_settings/scenes/desktop_settings_scene_start.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c index b158384e0..89a344563 100644 --- a/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c @@ -129,7 +129,7 @@ void desktop_settings_scene_start_on_enter(void* context) { item = variable_item_list_add( variable_item_list, - "Cycle Animations", + "Cycle Animation", CYCLE_ANIMATIONS_COUNT, desktop_settings_scene_start_cycle_animations_changed, app); From 968c1c815fa7e817d2fc219fb361c6e77b1748c6 Mon Sep 17 00:00:00 2001 From: Willy-JL Date: Tue, 17 Jan 2023 01:19:45 +0000 Subject: [PATCH 55/60] Add value_index_int32 --- lib/toolbox/value_index.c | 11 +++++++++++ lib/toolbox/value_index.h | 13 +++++++++++++ 2 files changed, 24 insertions(+) diff --git a/lib/toolbox/value_index.c b/lib/toolbox/value_index.c index e0745e434..87bf990f3 100644 --- a/lib/toolbox/value_index.c +++ b/lib/toolbox/value_index.c @@ -1,5 +1,16 @@ #include "value_index.h" +uint8_t value_index_int32(const int32_t value, const int32_t values[], uint8_t values_count) { + uint8_t index = 0; + for(uint8_t i = 0; i < values_count; i++) { + if(value == values[i]) { + index = i; + break; + } + } + return index; +} + uint8_t value_index_uint32(const uint32_t value, const uint32_t values[], uint8_t values_count) { int64_t last_value = INT64_MIN; uint8_t index = 0; diff --git a/lib/toolbox/value_index.h b/lib/toolbox/value_index.h index 9459292a7..23d53ca21 100644 --- a/lib/toolbox/value_index.h +++ b/lib/toolbox/value_index.h @@ -7,6 +7,19 @@ extern "C" { #endif +/** Get the index of a int32_t array element which is equal to the given value. + * + * Returned index corresponds to the first element found. + * If no suitable elements were found, the function returns 0. + * + * @param value value to be searched. + * @param values pointer to the array to perform the search in. + * @param values_count array size. + * + * @return value's index. + */ +uint8_t value_index_int32(const int32_t value, const int32_t values[], uint8_t values_count); + /** Get the index of a uint32_t array element which is closest to the given value. * * Returned index corresponds to the first element found. From a8725999c7a6cfd2faab323b02bc7e0bd61a70e5 Mon Sep 17 00:00:00 2001 From: Willy-JL Date: Tue, 17 Jan 2023 01:21:24 +0000 Subject: [PATCH 56/60] Update api symbols --- firmware/targets/f7/api_symbols.csv | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index aaeb0b8a7..ac33c40f2 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,12.2,, +Version,v,12.3,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -4410,6 +4410,7 @@ Function,+,validator_is_file_callback,_Bool,"const char*, FuriString*, void*" Function,+,validator_is_file_free,void,ValidatorIsFile* Function,+,value_index_bool,uint8_t,"const _Bool, const _Bool[], uint8_t" Function,+,value_index_float,uint8_t,"const float, const float[], uint8_t" +Function,?,value_index_int32,uint8_t,"const int32_t, const int32_t[], uint8_t" Function,+,value_index_uint32,uint8_t,"const uint32_t, const uint32_t[], uint8_t" Function,+,variable_item_get_context,void*,VariableItem* Function,+,variable_item_get_current_value_index,uint8_t,VariableItem* From 01b1ea123b7124680a59ccb906f7cd4a754012e6 Mon Sep 17 00:00:00 2001 From: Willy-JL Date: Tue, 17 Jan 2023 01:22:19 +0000 Subject: [PATCH 57/60] Add anim cycle 30s, 1m and manifest --- .../desktop/animations/animation_manager.c | 14 +++++----- applications/services/desktop/desktop.c | 4 +-- .../services/desktop/desktop_settings.h | 2 +- .../scenes/desktop_settings_scene_start.c | 27 ++++++++++--------- 4 files changed, 26 insertions(+), 21 deletions(-) diff --git a/applications/services/desktop/animations/animation_manager.c b/applications/services/desktop/animations/animation_manager.c index 37cd4fd53..d3d85be43 100644 --- a/applications/services/desktop/animations/animation_manager.c +++ b/applications/services/desktop/animations/animation_manager.c @@ -197,12 +197,13 @@ static void animation_manager_start_new_idle(AnimationManager* animation_manager StorageAnimation* new_animation = animation_manager_select_idle_animation(animation_manager); animation_manager_replace_current_animation(animation_manager, new_animation); - // const BubbleAnimation* bubble_animation = - // animation_storage_get_bubble_animation(animation_manager->current_animation); + const BubbleAnimation* bubble_animation = + animation_storage_get_bubble_animation(animation_manager->current_animation); animation_manager->state = AnimationManagerStateIdle; DesktopSettings* settings = malloc(sizeof(DesktopSettings)); DESKTOP_SETTINGS_LOAD(settings); - furi_timer_start(animation_manager->idle_animation_timer, (settings->cycle_animations_s - 1) * 1000); + int32_t duration_s = settings->cycle_animation_s == -1 ? bubble_animation->duration : (settings->cycle_animation_s - 1); + furi_timer_start(animation_manager->idle_animation_timer, duration_s * 1000); free(settings); } @@ -511,12 +512,13 @@ void animation_manager_load_and_continue_animation(AnimationManager* animation_m animation_manager->idle_animation_timer, animation_manager->freezed_animation_time_left); } else { - // const BubbleAnimation* animation = animation_storage_get_bubble_animation( - // animation_manager->current_animation); + const BubbleAnimation* animation = animation_storage_get_bubble_animation( + animation_manager->current_animation); DesktopSettings* settings = malloc(sizeof(DesktopSettings)); DESKTOP_SETTINGS_LOAD(settings); + int32_t duration_s = settings->cycle_animation_s == -1 ? animation->duration : (settings->cycle_animation_s - 1); furi_timer_start( - animation_manager->idle_animation_timer, (settings->cycle_animations_s - 1) * 1000); + animation_manager->idle_animation_timer, duration_s * 1000); free(settings); } } diff --git a/applications/services/desktop/desktop.c b/applications/services/desktop/desktop.c index 719ed3018..fbd483826 100644 --- a/applications/services/desktop/desktop.c +++ b/applications/services/desktop/desktop.c @@ -322,8 +322,8 @@ int32_t desktop_srv(void* p) { DESKTOP_SETTINGS_SAVE(&desktop->settings); } - if(!desktop->settings.cycle_animations_s) { - desktop->settings.cycle_animations_s = 3601; + if(!desktop->settings.cycle_animation_s) { + desktop->settings.cycle_animation_s = 3601; DESKTOP_SETTINGS_SAVE(&desktop->settings); } diff --git a/applications/services/desktop/desktop_settings.h b/applications/services/desktop/desktop_settings.h index 35299a295..5e97f7647 100644 --- a/applications/services/desktop/desktop_settings.h +++ b/applications/services/desktop/desktop_settings.h @@ -64,5 +64,5 @@ typedef struct { uint8_t displayBatteryPercentage; bool is_sfwmode; uint8_t sfw_mode; - uint32_t cycle_animations_s; + int32_t cycle_animation_s; } DesktopSettings; diff --git a/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c index 89a344563..b97c2a4a2 100644 --- a/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c @@ -39,9 +39,12 @@ const uint32_t displayBatteryPercentage_value[BATTERY_VIEW_COUNT] = { uint8_t origBattDisp_value = 0; -#define CYCLE_ANIMATIONS_COUNT 10 -const char* const cycle_animations_text[CYCLE_ANIMATIONS_COUNT] = { +#define CYCLE_ANIMATION_COUNT 13 +const char* const cycle_animation_text[CYCLE_ANIMATION_COUNT] = { "OFF", + "Manifest", + "30 S", + "1 M", "5 M", "10 M", "15 M", @@ -53,8 +56,8 @@ const char* const cycle_animations_text[CYCLE_ANIMATIONS_COUNT] = { "24 H", }; // Values are offset by 1 so that 0 is not a valid value and desktop.c can detect this to set a default value (3601 / 1 H) -const uint32_t cycle_animations_value[CYCLE_ANIMATIONS_COUNT] = - {1, 301, 601, 901, 1801, 3601, 7201, 21601, 43201, 86401}; +const int32_t cycle_animation_value[CYCLE_ANIMATION_COUNT] = + {1, -1, 31, 61, 301, 601, 901, 1801, 3601, 7201, 21601, 43201, 86401}; static void desktop_settings_scene_start_var_list_enter_callback(void* context, uint32_t index) { DesktopSettingsApp* app = context; @@ -77,12 +80,12 @@ static void desktop_settings_scene_start_battery_view_changed(VariableItem* item app->settings.displayBatteryPercentage = index; } -static void desktop_settings_scene_start_cycle_animations_changed(VariableItem* item) { +static void desktop_settings_scene_start_cycle_animation_changed(VariableItem* item) { DesktopSettingsApp* app = variable_item_get_context(item); uint8_t index = variable_item_get_current_value_index(item); - variable_item_set_current_value_text(item, cycle_animations_text[index]); - app->settings.cycle_animations_s = cycle_animations_value[index]; + variable_item_set_current_value_text(item, cycle_animation_text[index]); + app->settings.cycle_animation_s = cycle_animation_value[index]; } void desktop_settings_scene_start_on_enter(void* context) { @@ -130,14 +133,14 @@ void desktop_settings_scene_start_on_enter(void* context) { item = variable_item_list_add( variable_item_list, "Cycle Animation", - CYCLE_ANIMATIONS_COUNT, - desktop_settings_scene_start_cycle_animations_changed, + CYCLE_ANIMATION_COUNT, + desktop_settings_scene_start_cycle_animation_changed, app); - value_index = value_index_uint32( - app->settings.cycle_animations_s, cycle_animations_value, CYCLE_ANIMATIONS_COUNT); + value_index = value_index_int32( + app->settings.cycle_animation_s, cycle_animation_value, CYCLE_ANIMATION_COUNT); variable_item_set_current_value_index(item, value_index); - variable_item_set_current_value_text(item, cycle_animations_text[value_index]); + variable_item_set_current_value_text(item, cycle_animation_text[value_index]); variable_item_list_set_enter_callback( variable_item_list, desktop_settings_scene_start_var_list_enter_callback, app); From dac53ab09bb0028fc509186cffd93261c613483d Mon Sep 17 00:00:00 2001 From: Willy-JL Date: Tue, 17 Jan 2023 01:24:32 +0000 Subject: [PATCH 58/60] Fix symbols --- firmware/targets/f7/api_symbols.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index ac33c40f2..a644e6711 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,v,12.3,, +Version,+,12.3,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, From 47914681594ff5fbcb405241e1fe58fed2f8b5bc Mon Sep 17 00:00:00 2001 From: Willy-JL Date: Tue, 17 Jan 2023 01:27:20 +0000 Subject: [PATCH 59/60] Use default anim cycle duration --- applications/services/desktop/desktop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/applications/services/desktop/desktop.c b/applications/services/desktop/desktop.c index fbd483826..78ff9bdab 100644 --- a/applications/services/desktop/desktop.c +++ b/applications/services/desktop/desktop.c @@ -323,7 +323,7 @@ int32_t desktop_srv(void* p) { } if(!desktop->settings.cycle_animation_s) { - desktop->settings.cycle_animation_s = 3601; + desktop->settings.cycle_animation_s = -1; DESKTOP_SETTINGS_SAVE(&desktop->settings); } From a095cc894f7c6f145f4abe83ea85cd6fd0c2380e Mon Sep 17 00:00:00 2001 From: VerstreuteSeele Date: Tue, 17 Jan 2023 05:36:09 +0100 Subject: [PATCH 60/60] V39 passed QC testing --- fbt_options.py | 2 +- firmware/targets/f7/api_symbols.csv | 2 +- scripts/version.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/fbt_options.py b/fbt_options.py index 9174b9552..0458ea03b 100644 --- a/fbt_options.py +++ b/fbt_options.py @@ -14,7 +14,7 @@ DEBUG = 0 # Suffix to add to files when building distribution # If OS environment has DIST_SUFFIX set, it will be used instead -DIST_SUFFIX = "XFW-0038_01112023" +DIST_SUFFIX = "XFW-0039_01172023" # Coprocessor firmware COPRO_OB_DATA = "scripts/ob.data" diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index a644e6711..42ea150df 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -4410,7 +4410,7 @@ Function,+,validator_is_file_callback,_Bool,"const char*, FuriString*, void*" Function,+,validator_is_file_free,void,ValidatorIsFile* Function,+,value_index_bool,uint8_t,"const _Bool, const _Bool[], uint8_t" Function,+,value_index_float,uint8_t,"const float, const float[], uint8_t" -Function,?,value_index_int32,uint8_t,"const int32_t, const int32_t[], uint8_t" +Function,+,value_index_int32,uint8_t,"const int32_t, const int32_t[], uint8_t" Function,+,value_index_uint32,uint8_t,"const uint32_t, const uint32_t[], uint8_t" Function,+,variable_item_get_context,void*,VariableItem* Function,+,variable_item_get_current_value_index,uint8_t,VariableItem* diff --git a/scripts/version.py b/scripts/version.py index a32b272aa..8f3ff0cf5 100644 --- a/scripts/version.py +++ b/scripts/version.py @@ -14,7 +14,7 @@ class GitVersion: self.gitlist = [("commit", "rev-parse --short HEAD"), ("branch", "rev-parse --abbrev-ref") , ("branch_num", "rev-list -count HEAD")] def get_version_info(self): - commit = branch = branch_num = "XFW-0038" + commit = branch = branch_num = "XFW-0039" # We dont use an `or` in commands that we expect to fail. It will serve no function. # We also dont try;exept an entire block of code. This is bad practise. We only try the single part that we expect to fail!