drop useless file and some useless line

This commit is contained in:
yocvito
2023-01-27 11:56:29 +01:00
parent a88053964e
commit a6daa2a20d
60 changed files with 1822 additions and 4867 deletions

View File

@@ -95,7 +95,6 @@ BadBleApp* bad_ble_app_alloc(char* arg) {
view_dispatcher_set_navigation_event_callback( view_dispatcher_set_navigation_event_callback(
app->view_dispatcher, bad_ble_app_back_event_callback); app->view_dispatcher, bad_ble_app_back_event_callback);
Bt* bt = furi_record_open(RECORD_BT); Bt* bt = furi_record_open(RECORD_BT);
app->bt = bt; app->bt = bt;
const char* adv_name = bt_get_profile_adv_name(bt); const char* adv_name = bt_get_profile_adv_name(bt);

View File

@@ -45,7 +45,6 @@ struct BadBleApp {
uint8_t mac[BAD_BLE_MAC_ADDRESS_LEN]; uint8_t mac[BAD_BLE_MAC_ADDRESS_LEN];
char name[BAD_BLE_ADV_NAME_MAX_LEN + 1]; char name[BAD_BLE_ADV_NAME_MAX_LEN + 1];
BadBleAppError error; BadBleAppError error;
FuriString* file_path; FuriString* file_path;
FuriString* keyboard_layout; FuriString* keyboard_layout;

View File

@@ -30,7 +30,6 @@ typedef enum {
WorkerEvtDisconnect = (1 << 3), WorkerEvtDisconnect = (1 << 3),
} WorkerEvtFlags; } WorkerEvtFlags;
typedef enum { typedef enum {
LevelRssi122_100, LevelRssi122_100,
LevelRssi99_80, LevelRssi99_80,
@@ -41,6 +40,9 @@ typedef enum {
LevelRssiError = 0xFF, LevelRssiError = 0xFF,
} LevelRssiRange; } LevelRssiRange;
/**
* Delays for waiting between HID key press and key release
*/
const uint8_t bt_hid_delays[LevelRssiNum] = { const uint8_t bt_hid_delays[LevelRssiNum] = {
30, // LevelRssi122_100 30, // LevelRssi122_100
25, // LevelRssi99_80 25, // LevelRssi99_80
@@ -162,11 +164,9 @@ static const uint8_t numpad_keys[10] = {
uint8_t bt_timeout = 0; uint8_t bt_timeout = 0;
static LevelRssiRange bt_remote_rssi_range(Bt* bt) { static LevelRssiRange bt_remote_rssi_range(Bt* bt) {
BtRssi rssi_data = {0}; BtRssi rssi_data = {0};
if (!bt_remote_rssi(bt, &rssi_data)) if(!bt_remote_rssi(bt, &rssi_data)) return LevelRssiError;
return LevelRssiError;
if(rssi_data.rssi <= 39) if(rssi_data.rssi <= 39)
return LevelRssi39_0; return LevelRssi39_0;
@@ -183,7 +183,6 @@ static LevelRssiRange bt_remote_rssi_range(Bt *bt) {
} }
static inline void update_bt_timeout(Bt* bt) { static inline void update_bt_timeout(Bt* bt) {
LevelRssiRange r = bt_remote_rssi_range(bt); LevelRssiRange r = bt_remote_rssi_range(bt);
if(r < LevelRssiNum) { if(r < LevelRssiNum) {
bt_timeout = bt_hid_delays[r]; bt_timeout = bt_hid_delays[r];
@@ -330,8 +329,6 @@ static int32_t
return SCRIPT_STATE_NEXT_LINE; // Skip empty lines return SCRIPT_STATE_NEXT_LINE; // Skip empty lines
} }
FURI_LOG_D(WORKER_TAG, "line:%s", line_tmp);
// General commands // General commands
if(strncmp(line_tmp, ducky_cmd_comment, strlen(ducky_cmd_comment)) == 0) { if(strncmp(line_tmp, ducky_cmd_comment, strlen(ducky_cmd_comment)) == 0) {
// REM - comment line // REM - comment line
@@ -426,7 +423,6 @@ static int32_t
line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1]; line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1];
key |= ducky_get_keycode(bad_ble, line_tmp, true); key |= ducky_get_keycode(bad_ble, line_tmp, true);
} }
FURI_LOG_I(WORKER_TAG, "Special key pressed %x\r\n", key);
furi_hal_bt_hid_kb_press(key); furi_hal_bt_hid_kb_press(key);
furi_delay_ms(bt_timeout); furi_delay_ms(bt_timeout);
@@ -559,9 +555,9 @@ static int32_t bad_ble_worker(void* context) {
BadBleWorkerState worker_state = BadBleStateInit; BadBleWorkerState worker_state = BadBleStateInit;
int32_t delay_val = 0; int32_t delay_val = 0;
// BLE HID init
bt_timeout = bt_hid_delays[LevelRssi39_0]; bt_timeout = bt_hid_delays[LevelRssi39_0];
// init ble hid
bt_disconnect(bad_ble->bt); bt_disconnect(bad_ble->bt);
// Wait 2nd core to update nvm storage // Wait 2nd core to update nvm storage
@@ -569,10 +565,6 @@ static int32_t bad_ble_worker(void* context) {
bt_keys_storage_set_storage_path(bad_ble->bt, HID_BT_KEYS_STORAGE_PATH); bt_keys_storage_set_storage_path(bad_ble->bt, HID_BT_KEYS_STORAGE_PATH);
bt_set_profile_adv_name(bad_ble->bt, "Keyboard K99");
//furi_hal_bt_set_profile_adv_name("Keyboard K99", FuriHalBtProfileHidKeyboard);
if(!bt_set_profile(bad_ble->bt, BtProfileHidKeyboard)) { if(!bt_set_profile(bad_ble->bt, BtProfileHidKeyboard)) {
FURI_LOG_E(TAG, "Failed to switch to HID profile"); FURI_LOG_E(TAG, "Failed to switch to HID profile");
return -1; return -1;
@@ -727,7 +719,7 @@ static int32_t bad_ble_worker(void* context) {
} }
update_bt_timeout(bad_ble->bt); update_bt_timeout(bad_ble->bt);
FURI_LOG_I(WORKER_TAG, "BLE Key timeout : %u", bt_timeout); FURI_LOG_D(WORKER_TAG, "BLE Key timeout : %u", bt_timeout);
} }
// release all keys // release all keys

View File

@@ -33,8 +33,7 @@ bool bad_ble_scene_config_name_on_event(void* context, SceneManagerEvent event)
if(event.event == BadBleAppCustomEventTextEditResult) { if(event.event == BadBleAppCustomEventTextEditResult) {
bt_set_profile_adv_name(bad_ble->bt, bad_ble->name); bt_set_profile_adv_name(bad_ble->bt, bad_ble->name);
} }
scene_manager_previous_scene( scene_manager_previous_scene(bad_ble->scene_manager);
bad_ble->scene_manager);
} }
return consumed; return consumed;
} }

View File

@@ -38,8 +38,7 @@ static void gpio_scene_start_var_list_enter_callback(void* context, uint32_t ind
} }
} }
static void static void gpio_scene_start_var_list_change_callback(VariableItem* item) {
gpio_scene_start_var_list_change_callback(VariableItem* item) {
GpioApp* app = variable_item_get_context(item); GpioApp* app = variable_item_get_context(item);
uint8_t index = variable_item_get_current_value_index(item); uint8_t index = variable_item_get_current_value_index(item);

View File

@@ -486,8 +486,7 @@ int32_t dap_link_app(void* p) {
if(furi_hal_usb_is_locked()) { if(furi_hal_usb_is_locked()) {
DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS); DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS);
DialogMessage* message = dialog_message_alloc(); DialogMessage* message = dialog_message_alloc();
dialog_message_set_header( dialog_message_set_header(message, "Connection\nis active!", 3, 2, AlignLeft, AlignTop);
message, "Connection\nis active!", 3, 2, AlignLeft, AlignTop);
dialog_message_set_text( dialog_message_set_text(
message, message,
"Disconnect from\nPC or phone to\nuse this function.", "Disconnect from\nPC or phone to\nuse this function.",

View File

@@ -467,7 +467,6 @@ int32_t dice_app(void* p) {
return 255; return 255;
} }
ViewPort* view_port = view_port_alloc(); ViewPort* view_port = view_port_alloc();
view_port_draw_callback_set(view_port, dice_render_callback, plugin_state); view_port_draw_callback_set(view_port, dice_render_callback, plugin_state);
view_port_input_callback_set(view_port, dice_input_callback, plugin_state->event_queue); view_port_input_callback_set(view_port, dice_input_callback, plugin_state->event_queue);

View File

@@ -73,19 +73,24 @@ int32_t orgasmotron_app(void* p) {
processing = false; processing = false;
//break; //break;
} }
if(event.key == InputKeyOk && (event.type == InputTypePress || event.type == InputTypeRelease)) { if(event.key == InputKeyOk &&
(event.type == InputTypePress || event.type == InputTypeRelease)) {
plugin_state->mode = 0; plugin_state->mode = 0;
} }
if(event.key == InputKeyLeft && (event.type == InputTypePress || event.type == InputTypeRelease)) { if(event.key == InputKeyLeft &&
(event.type == InputTypePress || event.type == InputTypeRelease)) {
plugin_state->mode = 1; plugin_state->mode = 1;
} }
if(event.key == InputKeyRight && (event.type == InputTypePress || event.type == InputTypeRelease)) { if(event.key == InputKeyRight &&
(event.type == InputTypePress || event.type == InputTypeRelease)) {
plugin_state->mode = 3; plugin_state->mode = 3;
} }
if(event.key == InputKeyUp && (event.type == InputTypePress || event.type == InputTypeRelease)) { if(event.key == InputKeyUp &&
(event.type == InputTypePress || event.type == InputTypeRelease)) {
plugin_state->mode = 2; plugin_state->mode = 2;
} }
if(event.key == InputKeyDown && (event.type == InputTypePress || event.type == InputTypeRelease)) { if(event.key == InputKeyDown &&
(event.type == InputTypePress || event.type == InputTypeRelease)) {
plugin_state->mode = 4; plugin_state->mode = 4;
} }
} }

View File

@@ -51,14 +51,25 @@ static void render_callback(Canvas *const canvas, void *ctx) {
/* Call who is in charge right now. */ /* Call who is in charge right now. */
switch(app->current_view) { switch(app->current_view) {
case ViewRawPulses: render_view_raw_pulses(canvas,app); break; case ViewRawPulses:
case ViewInfo: render_view_info(canvas,app); break; render_view_raw_pulses(canvas, app);
break;
case ViewInfo:
render_view_info(canvas, app);
break;
case ViewFrequencySettings: case ViewFrequencySettings:
case ViewModulationSettings: case ViewModulationSettings:
render_view_settings(canvas,app); break; render_view_settings(canvas, app);
case ViewDirectSampling: render_view_direct_sampling(canvas,app); break; break;
case ViewBuildMessage: render_view_build_message(canvas,app); break; case ViewDirectSampling:
default: furi_crash(TAG "Invalid view selected"); break; render_view_direct_sampling(canvas, app);
break;
case ViewBuildMessage:
render_view_build_message(canvas, app);
break;
default:
furi_crash(TAG "Invalid view selected");
break;
} }
/* Draw the alert box if set. */ /* Draw the alert box if set. */
@@ -67,8 +78,7 @@ static void render_callback(Canvas *const canvas, void *ctx) {
/* Here all we do is putting the events into the queue that will be handled /* 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. */ * in the while() loop of the app entry point function. */
static void input_callback(InputEvent* input_event, void* ctx) static void input_callback(InputEvent* input_event, void* ctx) {
{
ProtoViewApp* app = ctx; ProtoViewApp* app = ctx;
furi_message_queue_put(app->event_queue, input_event, FuriWaitForever); furi_message_queue_put(app->event_queue, input_event, FuriWaitForever);
} }
@@ -176,13 +186,10 @@ ProtoViewApp* protoview_app_alloc() {
app->txrx->environment = subghz_environment_alloc(); app->txrx->environment = subghz_environment_alloc();
subghz_environment_set_protocol_registry( subghz_environment_set_protocol_registry(
app->txrx->environment, (void*)&protoview_protocol_registry); app->txrx->environment, (void*)&protoview_protocol_registry);
app->txrx->receiver = app->txrx->receiver = subghz_receiver_alloc_init(app->txrx->environment);
subghz_receiver_alloc_init(app->txrx->environment); subghz_receiver_set_filter(app->txrx->receiver, SubGhzProtocolFlag_Decodable);
subghz_receiver_set_filter(app->txrx->receiver,
SubGhzProtocolFlag_Decodable);
subghz_worker_set_overrun_callback( subghz_worker_set_overrun_callback(
app->txrx->worker, app->txrx->worker, (SubGhzWorkerOverrunCallback)subghz_receiver_reset);
(SubGhzWorkerOverrunCallback)subghz_receiver_reset);
subghz_worker_set_pair_callback( subghz_worker_set_pair_callback(
app->txrx->worker, (SubGhzWorkerPairCallback)subghz_receiver_decode); app->txrx->worker, (SubGhzWorkerPairCallback)subghz_receiver_decode);
subghz_worker_set_context(app->txrx->worker, app->txrx->receiver); subghz_worker_set_context(app->txrx->worker, app->txrx->receiver);
@@ -292,14 +299,12 @@ int32_t protoview_app_entry(void* p) {
while(app->running) { while(app->running) {
FuriStatus qstat = furi_message_queue_get(app->event_queue, &input, 100); FuriStatus qstat = furi_message_queue_get(app->event_queue, &input, 100);
if(qstat == FuriStatusOk) { if(qstat == FuriStatusOk) {
if (DEBUG_MSG) FURI_LOG_E(TAG, "Main Loop - Input: type %d key %u", if(DEBUG_MSG)
input.type, input.key); FURI_LOG_E(TAG, "Main Loop - Input: type %d key %u", input.type, input.key);
/* Handle navigation here. Then handle view-specific inputs /* Handle navigation here. Then handle view-specific inputs
* in the view specific handling function. */ * in the view specific handling function. */
if (input.type == InputTypeShort && if(input.type == InputTypeShort && input.key == InputKeyBack) {
input.key == InputKeyBack)
{
if(app->current_view != ViewRawPulses) { if(app->current_view != ViewRawPulses) {
/* If this is not the main app view, go there. */ /* If this is not the main app view, go there. */
app_switch_view(app, ViewRawPulses); app_switch_view(app, ViewRawPulses);
@@ -308,20 +313,16 @@ int32_t protoview_app_entry(void* p) {
* they needs to long press to really quit. */ * they needs to long press to really quit. */
ui_show_alert(app, "Long press to exit", 1000); ui_show_alert(app, "Long press to exit", 1000);
} }
} else if (input.type == InputTypeLong && } else if(input.type == InputTypeLong && input.key == InputKeyBack) {
input.key == InputKeyBack)
{
app->running = 0; app->running = 0;
} else if (input.type == InputTypeShort && } else if(
input.key == InputKeyRight && input.type == InputTypeShort && input.key == InputKeyRight &&
ui_get_current_subview(app) == 0) ui_get_current_subview(app) == 0) {
{
/* Go to the next view. */ /* Go to the next view. */
app_switch_view(app, ViewGoNext); app_switch_view(app, ViewGoNext);
} else if (input.type == InputTypeShort && } else if(
input.key == InputKeyLeft && input.type == InputTypeShort && input.key == InputKeyLeft &&
ui_get_current_subview(app) == 0) ui_get_current_subview(app) == 0) {
{
/* Go to the previous view. */ /* Go to the previous view. */
app_switch_view(app, ViewGoPrev); app_switch_view(app, ViewGoPrev);
} else { } else {
@@ -344,14 +345,17 @@ int32_t protoview_app_entry(void* p) {
case ViewBuildMessage: case ViewBuildMessage:
process_input_build_message(app, input); process_input_build_message(app, input);
break; break;
default: furi_crash(TAG "Invalid view selected"); break; default:
furi_crash(TAG "Invalid view selected");
break;
} }
} }
} else { } else {
/* Useful to understand if the app is still alive when it /* Useful to understand if the app is still alive when it
* does not respond because of bugs. */ * does not respond because of bugs. */
if(DEBUG_MSG) { if(DEBUG_MSG) {
static int c = 0; c++; static int c = 0;
c++;
if(!(c % 20)) FURI_LOG_E(TAG, "Loop timeout"); if(!(c % 20)) FURI_LOG_E(TAG, "Loop timeout");
} }
} }
@@ -368,11 +372,11 @@ int32_t protoview_app_entry(void* p) {
* otherwise when the user presses back on the keyboard to * otherwise when the user presses back on the keyboard to
* abort, the dispatcher will not stop. */ * abort, the dispatcher will not stop. */
view_dispatcher_set_navigation_event_callback( view_dispatcher_set_navigation_event_callback(
app->view_dispatcher, app->view_dispatcher, keyboard_view_dispatcher_navigation_callback);
keyboard_view_dispatcher_navigation_callback);
app->text_input = text_input_alloc(); app->text_input = text_input_alloc();
view_dispatcher_set_event_callback_context(app->view_dispatcher, app); view_dispatcher_set_event_callback_context(app->view_dispatcher, app);
view_dispatcher_add_view(app->view_dispatcher, 0, text_input_get_view(app->text_input)); view_dispatcher_add_view(
app->view_dispatcher, 0, text_input_get_view(app->text_input));
view_dispatcher_switch_to_view(app->view_dispatcher, 0); view_dispatcher_switch_to_view(app->view_dispatcher, 0);
/* Setup the text input view. The different parameters are set /* Setup the text input view. The different parameters are set
@@ -388,7 +392,8 @@ int32_t protoview_app_entry(void* p) {
false); false);
/* Run the dispatcher with the keyboard. */ /* Run the dispatcher with the keyboard. */
view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); view_dispatcher_attach_to_gui(
app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen);
view_dispatcher_run(app->view_dispatcher); view_dispatcher_run(app->view_dispatcher);
/* Undo all it: remove the view from the dispatcher, free it /* Undo all it: remove the view from the dispatcher, free it
@@ -416,4 +421,3 @@ int32_t protoview_app_entry(void* p) {
protoview_app_free(app); protoview_app_free(app);
return 0; return 0;
} }

View File

@@ -254,13 +254,38 @@ void reset_current_signal(ProtoViewApp *app);
void scan_for_signal(ProtoViewApp* app, RawSamplesBuffer* source); void scan_for_signal(ProtoViewApp* app, RawSamplesBuffer* source);
bool bitmap_get(uint8_t* b, uint32_t blen, uint32_t bitpos); 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(uint8_t* b, uint32_t blen, uint32_t bitpos, bool val);
void bitmap_copy(uint8_t *d, uint32_t dlen, uint32_t doff, uint8_t *s, uint32_t slen, uint32_t soff, uint32_t count); void bitmap_copy(
uint8_t* d,
uint32_t dlen,
uint32_t doff,
uint8_t* s,
uint32_t slen,
uint32_t soff,
uint32_t count);
void bitmap_set_pattern(uint8_t* b, uint32_t blen, uint32_t off, const char* pat); void bitmap_set_pattern(uint8_t* b, uint32_t blen, uint32_t off, const char* pat);
void bitmap_reverse_bytes_bits(uint8_t* p, uint32_t len); void bitmap_reverse_bytes_bits(uint8_t* p, uint32_t len);
bool bitmap_match_bits(uint8_t* b, uint32_t blen, uint32_t bitpos, const char* bits); 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 bitmap_seek_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); uint8_t* b,
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 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 init_msg_info(ProtoViewMsgInfo* i, ProtoViewApp* app); void init_msg_info(ProtoViewMsgInfo* i, ProtoViewApp* app);
void free_msg_info(ProtoViewMsgInfo* i); void free_msg_info(ProtoViewMsgInfo* i);
@@ -290,13 +315,22 @@ void adjust_raw_view_scale(ProtoViewApp *app, uint32_t short_pulse_dur);
int ui_get_current_subview(ProtoViewApp* app); int ui_get_current_subview(ProtoViewApp* app);
void ui_show_available_subviews(Canvas* canvas, ProtoViewApp* app, int last_subview); void ui_show_available_subviews(Canvas* canvas, ProtoViewApp* app, int last_subview);
bool ui_process_subview_updown(ProtoViewApp* app, InputEvent input, int last_subview); bool ui_process_subview_updown(ProtoViewApp* app, InputEvent input, int last_subview);
void ui_show_keyboard(ProtoViewApp *app, char *buffer, uint32_t buflen, void ui_show_keyboard(
ProtoViewApp* app,
char* buffer,
uint32_t buflen,
void (*done_callback)(void*)); void (*done_callback)(void*));
void ui_dismiss_keyboard(ProtoViewApp* app); void ui_dismiss_keyboard(ProtoViewApp* app);
void ui_show_alert(ProtoViewApp* app, const char* text, uint32_t ttl); void ui_show_alert(ProtoViewApp* app, const char* text, uint32_t ttl);
void ui_dismiss_alert(ProtoViewApp* app); void ui_dismiss_alert(ProtoViewApp* app);
void ui_draw_alert_if_needed(Canvas* canvas, ProtoViewApp* app); void ui_draw_alert_if_needed(Canvas* canvas, ProtoViewApp* app);
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);
/* fields.c */ /* fields.c */
void fieldset_free(ProtoViewFieldSet* fs); void fieldset_free(ProtoViewFieldSet* fs);
@@ -306,8 +340,16 @@ void fieldset_add_uint(ProtoViewFieldSet *fs, const char *name, uint64_t uval, u
void fieldset_add_hex(ProtoViewFieldSet* fs, const char* name, uint64_t uval, uint8_t bits); void fieldset_add_hex(ProtoViewFieldSet* fs, const char* name, uint64_t uval, uint8_t bits);
void fieldset_add_bin(ProtoViewFieldSet* fs, const char* name, uint64_t uval, uint8_t bits); void fieldset_add_bin(ProtoViewFieldSet* fs, const char* name, uint64_t uval, uint8_t bits);
void fieldset_add_str(ProtoViewFieldSet* fs, const char* name, const char* s); void fieldset_add_str(ProtoViewFieldSet* fs, const char* name, const char* s);
void fieldset_add_bytes(ProtoViewFieldSet *fs, const char *name, const uint8_t *bytes, uint32_t count); void fieldset_add_bytes(
void fieldset_add_float(ProtoViewFieldSet *fs, const char *name, float val, uint32_t digits_after_dot); ProtoViewFieldSet* fs,
const char* name,
const uint8_t* bytes,
uint32_t count);
void fieldset_add_float(
ProtoViewFieldSet* fs,
const char* name,
float val,
uint32_t digits_after_dot);
const char* field_get_type_name(ProtoViewField* f); const char* field_get_type_name(ProtoViewField* f);
int field_to_string(char* buf, size_t len, ProtoViewField* f); int field_to_string(char* buf, size_t len, ProtoViewField* f);
bool field_set_from_string(ProtoViewField* f, char* buf, size_t len); bool field_set_from_string(ProtoViewField* f, char* buf, size_t len);

View File

@@ -13,14 +13,16 @@ void raw_sampling_worker_start(ProtoViewApp *app);
void raw_sampling_worker_stop(ProtoViewApp* app); void raw_sampling_worker_stop(ProtoViewApp* app);
ProtoViewModulation ProtoViewModulations[] = { ProtoViewModulation ProtoViewModulations[] = {
{"OOK 650Khz", "FuriHalSubGhzPresetOok650Async", {"OOK 650Khz", "FuriHalSubGhzPresetOok650Async", FuriHalSubGhzPresetOok650Async, NULL},
FuriHalSubGhzPresetOok650Async, NULL}, {"OOK 270Khz", "FuriHalSubGhzPresetOok270Async", FuriHalSubGhzPresetOok270Async, NULL},
{"OOK 270Khz", "FuriHalSubGhzPresetOok270Async", {"2FSK 2.38Khz",
FuriHalSubGhzPresetOok270Async, NULL}, "FuriHalSubGhzPreset2FSKDev238Async",
{"2FSK 2.38Khz", "FuriHalSubGhzPreset2FSKDev238Async", FuriHalSubGhzPreset2FSKDev238Async,
FuriHalSubGhzPreset2FSKDev238Async, NULL}, NULL},
{"2FSK 47.6Khz", "FuriHalSubGhzPreset2FSKDev476Async", {"2FSK 47.6Khz",
FuriHalSubGhzPreset2FSKDev476Async, NULL}, "FuriHalSubGhzPreset2FSKDev476Async",
FuriHalSubGhzPreset2FSKDev476Async,
NULL},
{"TPMS 1 (FSK)", NULL, 0, (uint8_t*)protoview_subghz_tpms1_fsk_async_regs}, {"TPMS 1 (FSK)", NULL, 0, (uint8_t*)protoview_subghz_tpms1_fsk_async_regs},
{"TPMS 2 (OOK)", NULL, 0, (uint8_t*)protoview_subghz_tpms2_ook_async_regs}, {"TPMS 2 (OOK)", NULL, 0, (uint8_t*)protoview_subghz_tpms2_ook_async_regs},
{"TPMS 3 (FSK)", NULL, 0, (uint8_t*)protoview_subghz_tpms3_fsk_async_regs}, {"TPMS 3 (FSK)", NULL, 0, (uint8_t*)protoview_subghz_tpms3_fsk_async_regs},
@@ -45,11 +47,9 @@ void radio_begin(ProtoViewApp* app) {
* the modulation "custom" field is NULL, or a custom preset we * the modulation "custom" field is NULL, or a custom preset we
* defined in custom_presets.h. */ * defined in custom_presets.h. */
if(ProtoViewModulations[app->modulation].custom == NULL) { if(ProtoViewModulations[app->modulation].custom == NULL) {
furi_hal_subghz_load_preset( furi_hal_subghz_load_preset(ProtoViewModulations[app->modulation].preset);
ProtoViewModulations[app->modulation].preset);
} else { } else {
furi_hal_subghz_load_custom_preset( furi_hal_subghz_load_custom_preset(ProtoViewModulations[app->modulation].custom);
ProtoViewModulations[app->modulation].custom);
} }
furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow);
app->txrx->txrx_state = TxRxStateIDLE; app->txrx->txrx_state = TxRxStateIDLE;
@@ -73,9 +73,7 @@ uint32_t radio_rx(ProtoViewApp* app) {
furi_hal_subghz_flush_rx(); furi_hal_subghz_flush_rx();
furi_hal_subghz_rx(); furi_hal_subghz_rx();
if(!app->txrx->debug_timer_sampling) { if(!app->txrx->debug_timer_sampling) {
furi_hal_subghz_start_async_rx(subghz_worker_rx_callback, app->txrx->worker);
furi_hal_subghz_start_async_rx(subghz_worker_rx_callback,
app->txrx->worker);
subghz_worker_start(app->txrx->worker); subghz_worker_start(app->txrx->worker);
} else { } else {
raw_sampling_worker_start(app); raw_sampling_worker_start(app);

View File

@@ -3,8 +3,7 @@
/* CRC8 with the specified initialization value 'init' and /* CRC8 with the specified initialization value 'init' and
* polynomial 'poly'. */ * 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; uint8_t crc = init;
size_t i, j; size_t i, j;
for(i = 0; i < len; i++) { for(i = 0; i < len; i++) {

View File

@@ -76,7 +76,8 @@ static uint8_t protoview_subghz_tpms1_fsk_async_regs[][2] = {
// // Modem Configuration // // Modem Configuration
{CC1101_MDMCFG0, 0x00}, {CC1101_MDMCFG0, 0x00},
{CC1101_MDMCFG1, 0x02}, {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_MDMCFG3, 0x93}, // Data rate is 20kBaud
{CC1101_MDMCFG4, 0x59}, // Rx bandwidth filter is 325 kHz {CC1101_MDMCFG4, 0x59}, // Rx bandwidth filter is 325 kHz
{CC1101_DEVIATN, 0x41}, // Deviation 28.56 kHz {CC1101_DEVIATN, 0x41}, // Deviation 28.56 kHz
@@ -106,8 +107,10 @@ static uint8_t protoview_subghz_tpms1_fsk_async_regs[][2] = {
{0, 0}, {0, 0},
/* CC1101 2FSK PATABLE. */ /* CC1101 2FSK PATABLE. */
{0xC0, 0}, {0,0}, {0,0}, {0,0} {0xC0, 0},
}; {0, 0},
{0, 0},
{0, 0}};
/* This is like the default Flipper OOK 640Khz bandwidth preset, but /* This is like the default Flipper OOK 640Khz bandwidth preset, but
* the bandwidth is changed to 10kBaud to accomodate TPMS frequency. */ * the bandwidth is changed to 10kBaud to accomodate TPMS frequency. */
@@ -156,8 +159,10 @@ static const uint8_t protoview_subghz_tpms2_ook_async_regs[][2] = {
{0, 0}, {0, 0},
/* CC1101 OOK PATABLE. */ /* CC1101 OOK PATABLE. */
{0, 0xC0}, {0,0}, {0,0}, {0,0} {0, 0xC0},
}; {0, 0},
{0, 0},
{0, 0}};
/* 40 KBaud, 2FSK, 28 kHz deviation, 270 Khz bandwidth filter. */ /* 40 KBaud, 2FSK, 28 kHz deviation, 270 Khz bandwidth filter. */
static uint8_t protoview_subghz_tpms3_fsk_async_regs[][2] = { static uint8_t protoview_subghz_tpms3_fsk_async_regs[][2] = {
@@ -174,7 +179,8 @@ static uint8_t protoview_subghz_tpms3_fsk_async_regs[][2] = {
// // Modem Configuration // // Modem Configuration
{CC1101_MDMCFG0, 0x00}, {CC1101_MDMCFG0, 0x00},
{CC1101_MDMCFG1, 0x02}, {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_MDMCFG3, 0x93}, // Data rate is 40kBaud
{CC1101_MDMCFG4, 0x6A}, // 6 = BW filter 270kHz, A = Data rate exp {CC1101_MDMCFG4, 0x6A}, // 6 = BW filter 270kHz, A = Data rate exp
{CC1101_DEVIATN, 0x41}, // Deviation 28kHz {CC1101_DEVIATN, 0x41}, // Deviation 28kHz
@@ -204,8 +210,10 @@ static uint8_t protoview_subghz_tpms3_fsk_async_regs[][2] = {
{0, 0}, {0, 0},
/* CC1101 2FSK PATABLE. */ /* CC1101 2FSK PATABLE. */
{0xC0, 0}, {0,0}, {0,0}, {0,0} {0xC0, 0},
}; {0, 0},
{0, 0},
{0, 0}};
/* FSK 19k dev, 325 Khz filter, 20kBaud. Works well with Toyota. */ /* FSK 19k dev, 325 Khz filter, 20kBaud. Works well with Toyota. */
static uint8_t protoview_subghz_tpms4_fsk_async_regs[][2] = { static uint8_t protoview_subghz_tpms4_fsk_async_regs[][2] = {
@@ -250,6 +258,7 @@ static uint8_t protoview_subghz_tpms4_fsk_async_regs[][2] = {
{0, 0}, {0, 0},
/* CC1101 2FSK PATABLE. */ /* CC1101 2FSK PATABLE. */
{0xC0, 0}, {0,0}, {0,0}, {0,0} {0xC0, 0},
}; {0, 0},
{0, 0},
{0, 0}};

View File

@@ -26,8 +26,7 @@ typedef struct SubGhzProtocolDecoderprotoview {
void* subghz_protocol_decoder_protoview_alloc(SubGhzEnvironment* environment) { void* subghz_protocol_decoder_protoview_alloc(SubGhzEnvironment* environment) {
UNUSED(environment); UNUSED(environment);
SubGhzProtocolDecoderprotoview* instance = SubGhzProtocolDecoderprotoview* instance = malloc(sizeof(SubGhzProtocolDecoderprotoview));
malloc(sizeof(SubGhzProtocolDecoderprotoview));
instance->base.protocol = &subghz_protocol_protoview; instance->base.protocol = &subghz_protocol_protoview;
return instance; return instance;
} }
@@ -66,8 +65,7 @@ uint8_t subghz_protocol_decoder_protoview_get_hash_data(void* context) {
bool subghz_protocol_decoder_protoview_serialize( bool subghz_protocol_decoder_protoview_serialize(
void* context, void* context,
FlipperFormat* flipper_format, FlipperFormat* flipper_format,
SubGhzRadioPreset* preset) SubGhzRadioPreset* preset) {
{
UNUSED(context); UNUSED(context);
UNUSED(flipper_format); UNUSED(flipper_format);
UNUSED(preset); UNUSED(preset);
@@ -75,15 +73,13 @@ bool subghz_protocol_decoder_protoview_serialize(
} }
/* Not used. */ /* 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(context);
UNUSED(flipper_format); UNUSED(flipper_format);
return false; 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_assert(context);
furi_string_cat_printf(output, "Protoview"); furi_string_cat_printf(output, "Protoview");
} }
@@ -116,5 +112,4 @@ const SubGhzProtocol* protoview_protocol_registry_items[] = {
const SubGhzProtocolRegistry protoview_protocol_registry = { const SubGhzProtocolRegistry protoview_protocol_registry = {
.items = protoview_protocol_registry_items, .items = protoview_protocol_registry_items,
.size = COUNT_OF(protoview_protocol_registry_items) .size = COUNT_OF(protoview_protocol_registry_items)};
};

View File

@@ -18,9 +18,14 @@ static ProtoViewField *field_new(ProtoViewFieldType type, const char *name) {
* current type. Name and type are not touched. */ * current type. Name and type are not touched. */
static void field_free_aux_data(ProtoViewField* f) { static void field_free_aux_data(ProtoViewField* f) {
switch(f->type) { switch(f->type) {
case FieldTypeStr: free(f->str); break; case FieldTypeStr:
case FieldTypeBytes: free(f->bytes); break; free(f->str);
default: break; // Nothing to free for other types. break;
case FieldTypeBytes:
free(f->bytes);
break;
default:
break; // Nothing to free for other types.
} }
} }
@@ -34,13 +39,20 @@ static void field_free(ProtoViewField *f) {
/* Return the type of the field as string. */ /* Return the type of the field as string. */
const char* field_get_type_name(ProtoViewField* f) { const char* field_get_type_name(ProtoViewField* f) {
switch(f->type) { switch(f->type) {
case FieldTypeStr: return "str"; case FieldTypeStr:
case FieldTypeSignedInt: return "int"; return "str";
case FieldTypeUnsignedInt: return "uint"; case FieldTypeSignedInt:
case FieldTypeBinary: return "bin"; return "int";
case FieldTypeHex: return "hex"; case FieldTypeUnsignedInt:
case FieldTypeBytes: return "bytes"; return "uint";
case FieldTypeFloat: return "float"; case FieldTypeBinary:
return "bin";
case FieldTypeHex:
return "hex";
case FieldTypeBytes:
return "bytes";
case FieldTypeFloat:
return "float";
} }
return "unknown"; return "unknown";
} }
@@ -54,8 +66,7 @@ int field_to_string(char *buf, size_t len, ProtoViewField *f) {
return snprintf(buf, len, "%lld", (long long)f->value); return snprintf(buf, len, "%lld", (long long)f->value);
case FieldTypeUnsignedInt: case FieldTypeUnsignedInt:
return snprintf(buf, len, "%llu", (unsigned long long)f->uvalue); return snprintf(buf, len, "%llu", (unsigned long long)f->uvalue);
case FieldTypeBinary: case FieldTypeBinary: {
{
uint64_t test_bit = (1 << (f->len - 1)); uint64_t test_bit = (1 << (f->len - 1));
uint64_t idx = 0; uint64_t idx = 0;
while(idx < len - 1 && test_bit) { while(idx < len - 1 && test_bit) {
@@ -69,14 +80,11 @@ int field_to_string(char *buf, size_t len, ProtoViewField *f) {
return snprintf(buf, len, "%*llX", (int)(f->len + 7) / 8, f->uvalue); return snprintf(buf, len, "%*llX", (int)(f->len + 7) / 8, f->uvalue);
case FieldTypeFloat: case FieldTypeFloat:
return snprintf(buf, len, "%.*f", (int)f->len, (double)f->fvalue); return snprintf(buf, len, "%.*f", (int)f->len, (double)f->fvalue);
case FieldTypeBytes: case FieldTypeBytes: {
{
uint64_t idx = 0; uint64_t idx = 0;
while(idx < len - 1 && idx < f->len) { while(idx < len - 1 && idx < f->len) {
const char* charset = "0123456789ABCDEF"; const char* charset = "0123456789ABCDEF";
uint32_t nibble = idx & 1 ? uint32_t nibble = idx & 1 ? (f->bytes[idx / 2] & 0xf) : (f->bytes[idx / 2] >> 4);
(f->bytes[idx/2] & 0xf) :
(f->bytes[idx/2] >> 4);
buf[idx++] = charset[nibble]; buf[idx++] = charset[nibble];
} }
buf[idx] = 0; buf[idx] = 0;
@@ -118,52 +126,50 @@ bool field_set_from_string(ProtoViewField *f, char *buf, size_t len) {
if(!sscanf(buf, "%llu", &uval)) return false; if(!sscanf(buf, "%llu", &uval)) return false;
f->uvalue = uval; f->uvalue = uval;
break; break;
case FieldTypeBinary: case FieldTypeBinary: {
{
uint64_t bit_to_set = (1 << (len - 1)); uint64_t bit_to_set = (1 << (len - 1));
uint64_t idx = 0; uint64_t idx = 0;
uval = 0; uval = 0;
while(buf[idx]) { while(buf[idx]) {
if (buf[idx] == '1') uval |= bit_to_set; if(buf[idx] == '1')
else if (buf[idx] != '0') return false; uval |= bit_to_set;
else if(buf[idx] != '0')
return false;
bit_to_set >>= 1; bit_to_set >>= 1;
idx++; idx++;
} }
f->uvalue = uval; f->uvalue = uval;
} } break;
break;
case FieldTypeHex: case FieldTypeHex:
if (!sscanf(buf,"%llx",&uval) && if(!sscanf(buf, "%llx", &uval) && !sscanf(buf, "%llX", &uval)) return false;
!sscanf(buf,"%llX",&uval)) return false;
f->uvalue = uval; f->uvalue = uval;
break; break;
case FieldTypeFloat: case FieldTypeFloat:
if(!sscanf(buf, "%f", &fval)) return false; if(!sscanf(buf, "%f", &fval)) return false;
f->fvalue = fval; f->fvalue = fval;
break; break;
case FieldTypeBytes: case FieldTypeBytes: {
{
if(len > f->len) return false; if(len > f->len) return false;
uint64_t idx = 0; uint64_t idx = 0;
while(buf[idx]) { while(buf[idx]) {
uint8_t nibble = 0; uint8_t nibble = 0;
char c = toupper(buf[idx]); char c = toupper(buf[idx]);
if (c >= '0' && c <= '9') nibble = c-'0'; if(c >= '0' && c <= '9')
else if (c >= 'A' && c <= 'F') nibble = 10+(c-'A'); nibble = c - '0';
else return false; else if(c >= 'A' && c <= 'F')
nibble = 10 + (c - 'A');
else
return false;
if(idx & 1) { if(idx & 1) {
f->bytes[idx/2] = f->bytes[idx / 2] = (f->bytes[idx / 2] & 0xF0) | nibble;
(f->bytes[idx/2] & 0xF0) | nibble;
} else { } else {
f->bytes[idx/2] = f->bytes[idx / 2] = (f->bytes[idx / 2] & 0x0F) | (nibble << 4);
(f->bytes[idx/2] & 0x0F) | (nibble<<4);
} }
idx++; idx++;
} }
buf[idx] = 0; buf[idx] = 0;
} } break;
break;
} }
return true; return true;
} }
@@ -201,7 +207,8 @@ void field_set_from_field(ProtoViewField *dst, ProtoViewField *src) {
* action is performed. */ * action is performed. */
bool field_incr_value(ProtoViewField* f, int incr) { bool field_incr_value(ProtoViewField* f, int incr) {
switch(f->type) { switch(f->type) {
case FieldTypeStr: return false; case FieldTypeStr:
return false;
case FieldTypeSignedInt: { case FieldTypeSignedInt: {
/* Wrap around depending on the number of bits (f->len) /* Wrap around depending on the number of bits (f->len)
* the integer was declared to have. */ * the integer was declared to have. */
@@ -231,8 +238,7 @@ bool field_incr_value(ProtoViewField *f, int incr) {
// For bytes we only support single unit increments. // For bytes we only support single unit increments.
if(incr != -1 && incr != 1) return false; if(incr != -1 && incr != 1) return false;
for(int j = f->len - 1; j >= 0; j--) { for(int j = f->len - 1; j >= 0; j--) {
uint8_t nibble = (j&1) ? (f->bytes[j/2] & 0x0F) : uint8_t nibble = (j & 1) ? (f->bytes[j / 2] & 0x0F) : ((f->bytes[j / 2] & 0xF0) >> 4);
((f->bytes[j/2] & 0xF0) >> 4);
nibble += incr; nibble += incr;
nibble &= 0x0F; nibble &= 0x0F;
@@ -241,9 +247,7 @@ bool field_incr_value(ProtoViewField *f, int incr) {
((f->bytes[j / 2] & 0x0F) | (nibble << 4)); ((f->bytes[j / 2] & 0x0F) | (nibble << 4));
/* Propagate the operation on overflow of this nibble. */ /* Propagate the operation on overflow of this nibble. */
if ((incr == 1 && nibble == 0) || if((incr == 1 && nibble == 0) || (incr == -1 && nibble == 0xf)) {
(incr == -1 && nibble == 0xf))
{
continue; continue;
} }
break; // Otherwise stop the loop here. break; // Otherwise stop the loop here.
@@ -254,11 +258,9 @@ bool field_incr_value(ProtoViewField *f, int incr) {
return true; return true;
} }
/* Free a field set and its contained fields. */ /* Free a field set and its contained fields. */
void fieldset_free(ProtoViewFieldSet* fs) { void fieldset_free(ProtoViewFieldSet* fs) {
for (uint32_t j = 0; j < fs->numfields; j++) for(uint32_t j = 0; j < fs->numfields; j++) field_free(fs->fields[j]);
field_free(fs->fields[j]);
free(fs->fields); free(fs->fields);
free(fs); free(fs);
} }
@@ -322,7 +324,11 @@ void fieldset_add_str(ProtoViewFieldSet *fs, const char *name, const char *s) {
/* Allocate and append a bytes field. Note that 'count' is specified in /* Allocate and append a bytes field. Note that 'count' is specified in
* nibbles (bytes*2). */ * nibbles (bytes*2). */
void fieldset_add_bytes(ProtoViewFieldSet *fs, const char *name, const uint8_t *bytes, uint32_t count_nibbles) { void fieldset_add_bytes(
ProtoViewFieldSet* fs,
const char* name,
const uint8_t* bytes,
uint32_t count_nibbles) {
uint32_t numbytes = (count_nibbles + count_nibbles % 2) / 2; uint32_t numbytes = (count_nibbles + count_nibbles % 2) / 2;
ProtoViewField* f = field_new(FieldTypeBytes, name); ProtoViewField* f = field_new(FieldTypeBytes, name);
f->bytes = malloc(numbytes); f->bytes = malloc(numbytes);
@@ -332,7 +338,11 @@ void fieldset_add_bytes(ProtoViewFieldSet *fs, const char *name, const uint8_t *
} }
/* Allocate and append a float field. */ /* Allocate and append a float field. */
void fieldset_add_float(ProtoViewFieldSet *fs, const char *name, float val, uint32_t digits_after_dot) { void fieldset_add_float(
ProtoViewFieldSet* fs,
const char* name,
float val,
uint32_t digits_after_dot) {
ProtoViewField* f = field_new(FieldTypeFloat, name); ProtoViewField* f = field_new(FieldTypeFloat, name);
f->fvalue = val; f->fvalue = val;
f->len = digits_after_dot; f->len = digits_after_dot;
@@ -342,16 +352,12 @@ void fieldset_add_float(ProtoViewFieldSet *fs, const char *name, float val, uint
/* For each field of the destination filedset 'dst', look for a matching /* For each field of the destination filedset 'dst', look for a matching
* field name/type in the source fieldset 'src', and if one is found copy * field name/type in the source fieldset 'src', and if one is found copy
* its value into the 'dst' field. */ * its value into the 'dst' field. */
void fieldset_copy_matching_fields(ProtoViewFieldSet *dst, void fieldset_copy_matching_fields(ProtoViewFieldSet* dst, ProtoViewFieldSet* src) {
ProtoViewFieldSet *src)
{
for(uint32_t j = 0; j < dst->numfields; j++) { for(uint32_t j = 0; j < dst->numfields; j++) {
for(uint32_t i = 0; i < src->numfields; i++) { for(uint32_t i = 0; i < src->numfields; i++) {
if(dst->fields[j]->type == src->fields[i]->type && if(dst->fields[j]->type == src->fields[i]->type &&
!strcmp(dst->fields[j]->name,src->fields[i]->name)) !strcmp(dst->fields[j]->name, src->fields[i]->name)) {
{ field_set_from_field(dst->fields[j], src->fields[i]);
field_set_from_field(dst->fields[j],
src->fields[i]);
} }
} }
} }

View File

@@ -31,8 +31,7 @@ static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoView
off += strlen(sync_patterns[j]) - 1; off += strlen(sync_patterns[j]) - 1;
uint8_t d[3]; /* 24 bits of data. */ uint8_t d[3]; /* 24 bits of data. */
uint32_t decoded = uint32_t decoded = convert_from_line_code(d, sizeof(d), bits, numbytes, off, "1000", "1110");
convert_from_line_code(d,sizeof(d),bits,numbytes,off,"1000","1110");
if(DEBUG_MSG) FURI_LOG_E(TAG, "B4B1 decoded: %lu", decoded); if(DEBUG_MSG) FURI_LOG_E(TAG, "B4B1 decoded: %lu", decoded);
if(decoded < 24) return false; if(decoded < 24) return false;
@@ -54,8 +53,7 @@ static void get_fields(ProtoViewFieldSet *fieldset) {
} }
/* Create a signal. */ /* Create a signal. */
static void build_message(RawSamplesBuffer *samples, ProtoViewFieldSet *fs) static void build_message(RawSamplesBuffer* samples, ProtoViewFieldSet* fs) {
{
uint32_t te = 334; // Short pulse duration in microseconds. uint32_t te = 334; // Short pulse duration in microseconds.
// Sync: 1 te pulse, 31 te gap. // Sync: 1 te pulse, 31 te gap.
@@ -84,5 +82,4 @@ ProtoViewDecoder B4B1Decoder = {
.name = "PT/SC remote", .name = "PT/SC remote",
.decode = decode, .decode = decode,
.get_fields = get_fields, .get_fields = get_fields,
.build_message = build_message .build_message = build_message};
};

View File

@@ -25,11 +25,11 @@
#include "../app.h" #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) {
/* In the sync pattern, we require the 12 high/low pulses and at least /* 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 * half the gap we expect (5 pulses times, one is the final zero in the
* 24 symbols high/low sequence, then other 4). */ * 24 symbols high/low sequence, then other 4). */
const char *sync_pattern = "101010101010101010101010" "0000"; const char* sync_pattern = "101010101010101010101010"
"0000";
uint8_t sync_len = 24 + 4; uint8_t sync_len = 24 + 4;
if(numbits - sync_len + sync_len < 3 * 66) return false; if(numbits - sync_len + sync_len < 3 * 66) return false;
uint32_t off = bitmap_seek_bits(bits, numbytes, 0, numbits, sync_pattern); uint32_t off = bitmap_seek_bits(bits, numbytes, 0, numbits, sync_pattern);
@@ -42,17 +42,15 @@ static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoView
* symbols of gap, to avoid missing the signal for a matter of wrong * symbols of gap, to avoid missing the signal for a matter of wrong
* timing. */ * timing. */
uint8_t gap_len = 0; uint8_t gap_len = 0;
while(gap_len <= 7 && bitmap_get(bits,numbytes,off+gap_len) == 0) while(gap_len <= 7 && bitmap_get(bits, numbytes, off + gap_len) == 0) gap_len++;
gap_len++;
if(gap_len < 3 || gap_len > 7) return false; if(gap_len < 3 || gap_len > 7) return false;
off += gap_len; off += gap_len;
FURI_LOG_E(TAG, "Keeloq preamble+sync found"); FURI_LOG_E(TAG, "Keeloq preamble+sync found");
uint8_t raw[9] = {0}; uint8_t raw[9] = {0};
uint32_t decoded = uint32_t decoded = convert_from_line_code(
convert_from_line_code(raw,sizeof(raw),bits,numbytes,off, raw, sizeof(raw), bits, numbytes, off, "110", "100"); /* Pulse width modulation. */
"110","100"); /* Pulse width modulation. */
FURI_LOG_E(TAG, "Keeloq decoded bits: %lu", decoded); FURI_LOG_E(TAG, "Keeloq decoded bits: %lu", decoded);
if(decoded < 66) return false; /* Require the full 66 bits. */ if(decoded < 66) return false; /* Require the full 66 bits. */
@@ -83,8 +81,7 @@ static void get_fields(ProtoViewFieldSet *fieldset) {
fieldset_add_bin(fieldset, "always one", 1, 1); fieldset_add_bin(fieldset, "always one", 1, 1);
} }
static void build_message(RawSamplesBuffer *samples, ProtoViewFieldSet *fieldset) static void build_message(RawSamplesBuffer* samples, ProtoViewFieldSet* fieldset) {
{
uint32_t te = 380; // Short pulse duration in microseconds. uint32_t te = 380; // Short pulse duration in microseconds.
// Sync: 12 pairs of pulse/gap + 9 times gap // Sync: 12 pairs of pulse/gap + 9 times gap
@@ -117,9 +114,5 @@ static void build_message(RawSamplesBuffer *samples, ProtoViewFieldSet *fieldset
} }
} }
ProtoViewDecoder KeeloqDecoder = { ProtoViewDecoder KeeloqDecoder =
.name = "Keeloq", {.name = "Keeloq", .decode = decode, .get_fields = get_fields, .build_message = build_message};
.decode = decode,
.get_fields = get_fields,
.build_message = build_message
};

View File

@@ -8,7 +8,10 @@
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) {
if(numbits < 32) return false; if(numbits < 32) return false;
const char *sync_pattern = "01100110" "01100110" "10010110" "10010110"; const char* sync_pattern = "01100110"
"01100110"
"10010110"
"10010110";
uint64_t off = bitmap_seek_bits(bits, numbytes, 0, numbits, sync_pattern); uint64_t off = bitmap_seek_bits(bits, numbytes, 0, numbits, sync_pattern);
if(off == BITMAP_SEEK_NOT_FOUND) return false; if(off == BITMAP_SEEK_NOT_FOUND) return false;
FURI_LOG_E(TAG, "Oregon2 preamble+sync found"); FURI_LOG_E(TAG, "Oregon2 preamble+sync found");
@@ -28,29 +31,44 @@ static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoView
uint8_t deviceid[2]; uint8_t deviceid[2];
for(int j = 0; j < 64; j += 4) { for(int j = 0; j < 64; j += 4) {
uint8_t nib[1]; uint8_t nib[1];
nib[0] = (bitmap_get(buffer,8,j+0) | nib[0] =
bitmap_get(buffer,8,j+1) << 1 | (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 + 2) << 2 | bitmap_get(buffer, 8, j + 3) << 3);
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]); 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)); raw[j / 8] |= nib[0] << (4 - (j % 4));
switch(j / 4) { switch(j / 4) {
case 1: deviceid[0] |= nib[0]; break; case 1:
case 0: deviceid[0] |= nib[0] << 4; break; deviceid[0] |= nib[0];
case 3: deviceid[1] |= nib[0]; break; break;
case 2: deviceid[1] |= nib[0] << 4; break; case 0:
case 10: temp[0] = nib[0]; break; 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. */ /* Fixme: take the temperature sign from nibble 11. */
case 9: temp[1] = nib[0]; break; case 9:
case 8: temp[2] = nib[0]; break; temp[1] = nib[0];
case 13: hum[0] = nib[0]; break; break;
case 12: hum[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;
} }
} }
float tempval = ((temp[0]-'0')*10) + float tempval = ((temp[0] - '0') * 10) + (temp[1] - '0') + ((float)(temp[2] - '0') * 0.1);
(temp[1]-'0') +
((float)(temp[2]-'0')*0.1);
int humval = (hum[0] - '0') * 10 + (hum[1] - '0'); int humval = (hum[0] - '0') * 10 + (hum[1] - '0');
fieldset_add_bytes(info->fieldset, "Sensor ID", deviceid, 4); fieldset_add_bytes(info->fieldset, "Sensor ID", deviceid, 4);
@@ -59,9 +77,5 @@ static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoView
return true; return true;
} }
ProtoViewDecoder Oregon2Decoder = { ProtoViewDecoder Oregon2Decoder =
.name = "Oregon2", {.name = "Oregon2", .decode = decode, .get_fields = NULL, .build_message = NULL};
.decode = decode,
.get_fields = NULL,
.build_message = NULL
};

View File

@@ -8,7 +8,6 @@
#include "../../app.h" #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 /* 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 * is more likely to happen if we don't pretend to receive from the
* very start of the message. */ * very start of the message. */
@@ -24,9 +23,8 @@ static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoView
off += sync_len; /* Skip preamble + sync. */ off += sync_len; /* Skip preamble + sync. */
uint8_t raw[10]; uint8_t raw[10];
uint32_t decoded = uint32_t decoded = convert_from_line_code(
convert_from_line_code(raw,sizeof(raw),bits,numbytes,off, raw, sizeof(raw), bits, numbytes, off, "01", "10"); /* Manchester. */
"01","10"); /* Manchester. */
FURI_LOG_E(TAG, "Citroen TPMS decoded bits: %lu", decoded); 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. */
@@ -53,9 +51,5 @@ static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoView
return true; return true;
} }
ProtoViewDecoder CitroenTPMSDecoder = { ProtoViewDecoder CitroenTPMSDecoder =
.name = "Citroen TPMS", {.name = "Citroen TPMS", .decode = decode, .get_fields = NULL, .build_message = NULL};
.decode = decode,
.get_fields = NULL,
.build_message = NULL
};

View File

@@ -11,8 +11,8 @@
#include "../../app.h" #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"
const char *sync_pattern = "010101010101" "0110"; "0110";
uint8_t sync_len = 12 + 4; /* We just use 12 preamble symbols + sync. */ uint8_t sync_len = 12 + 4; /* We just use 12 preamble symbols + sync. */
if(numbits - sync_len < 8 * 8) return false; if(numbits - sync_len < 8 * 8) return false;
@@ -24,9 +24,8 @@ static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoView
off += sync_len; /* Skip preamble and sync. */ off += sync_len; /* Skip preamble and sync. */
uint8_t raw[8]; uint8_t raw[8];
uint32_t decoded = uint32_t decoded = convert_from_line_code(
convert_from_line_code(raw,sizeof(raw),bits,numbytes,off, raw, sizeof(raw), bits, numbytes, off, "01", "10"); /* Manchester. */
"01","10"); /* Manchester. */
FURI_LOG_E(TAG, "Ford TPMS decoded bits: %lu", decoded); 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. */
@@ -55,9 +54,5 @@ static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoView
return true; return true;
} }
ProtoViewDecoder FordTPMSDecoder = { ProtoViewDecoder FordTPMSDecoder =
.name = "Ford TPMS", {.name = "Ford TPMS", .decode = decode, .get_fields = NULL, .build_message = NULL};
.decode = decode,
.get_fields = NULL,
.build_message = NULL
};

View File

@@ -23,7 +23,6 @@ static const char *test_vector =
"0110010101010101"; // CRC8 with (poly 7, initialization 0). "0110010101010101"; // CRC8 with (poly 7, initialization 0).
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) {
if(USE_TEST_VECTOR) { /* Test vector to check that decoding works. */ if(USE_TEST_VECTOR) { /* Test vector to check that decoding works. */
bitmap_set_pattern(bits, numbytes, 0, test_vector); bitmap_set_pattern(bits, numbytes, 0, test_vector);
numbits = strlen(test_vector); numbits = strlen(test_vector);
@@ -40,9 +39,8 @@ static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoView
off += 20; /* Skip preamble. */ off += 20; /* Skip preamble. */
uint8_t raw[9]; uint8_t raw[9];
uint32_t decoded = uint32_t decoded = convert_from_line_code(
convert_from_line_code(raw,sizeof(raw),bits,numbytes,off, raw, sizeof(raw), bits, numbytes, off, "01", "10"); /* Manchester. */
"01","10"); /* Manchester. */
FURI_LOG_E(TAG, "Renault TPMS decoded bits: %lu", decoded); FURI_LOG_E(TAG, "Renault TPMS decoded bits: %lu", decoded);
if(decoded < 8 * 9) return false; /* Require the full 9 bytes. */ if(decoded < 8 * 9) return false; /* Require the full 9 bytes. */
@@ -76,8 +74,7 @@ static void get_fields(ProtoViewFieldSet *fieldset) {
} }
/* Create a Renault TPMS signal, according to the fields provided. */ /* Create a Renault TPMS signal, according to the fields provided. */
static void build_message(RawSamplesBuffer *samples, ProtoViewFieldSet *fieldset) static void build_message(RawSamplesBuffer* samples, ProtoViewFieldSet* fieldset) {
{
uint32_t te = 50; // Short pulse duration in microseconds. uint32_t te = 50; // Short pulse duration in microseconds.
// Preamble + sync // Preamble + sync
@@ -116,5 +113,4 @@ ProtoViewDecoder RenaultTPMSDecoder = {
.name = "Renault TPMS", .name = "Renault TPMS",
.decode = decode, .decode = decode,
.get_fields = get_fields, .get_fields = get_fields,
.build_message = build_message .build_message = build_message};
};

View File

@@ -11,10 +11,10 @@
#include "../../app.h" #include "../../app.h"
#define USE_TEST_VECTOR 0 #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) { 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. */ if(USE_TEST_VECTOR) { /* Test vector to check that decoding works. */
bitmap_set_pattern(bits, numbytes, 0, test_vector); bitmap_set_pattern(bits, numbytes, 0, test_vector);
numbits = strlen(test_vector); numbits = strlen(test_vector);
@@ -22,7 +22,8 @@ static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoView
if(numbits < 64) return false; /* Preamble + data. */ if(numbits < 64) return false; /* Preamble + data. */
const char *sync_pattern = "1111010101" "01011010"; const char* sync_pattern = "1111010101"
"01011010";
uint64_t off = bitmap_seek_bits(bits, numbytes, 0, numbits, sync_pattern); uint64_t off = bitmap_seek_bits(bits, numbytes, 0, numbits, sync_pattern);
if(off == BITMAP_SEEK_NOT_FOUND) return false; if(off == BITMAP_SEEK_NOT_FOUND) return false;
FURI_LOG_E(TAG, "Schrader TPMS gap+preamble found"); FURI_LOG_E(TAG, "Schrader TPMS gap+preamble found");
@@ -34,9 +35,8 @@ static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoView
uint8_t raw[8]; uint8_t raw[8];
uint8_t id[4]; uint8_t id[4];
uint32_t decoded = uint32_t decoded = convert_from_line_code(
convert_from_line_code(raw,sizeof(raw),bits,numbytes,off, raw, sizeof(raw), bits, numbytes, off, "01", "10"); /* Manchester code. */
"01","10"); /* Manchester code. */
FURI_LOG_E(TAG, "Schrader TPMS decoded bits: %lu", decoded); 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. */
@@ -63,9 +63,5 @@ static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoView
return true; return true;
} }
ProtoViewDecoder SchraderTPMSDecoder = { ProtoViewDecoder SchraderTPMSDecoder =
.name = "Schrader TPMS", {.name = "Schrader TPMS", .decode = decode, .get_fields = NULL, .build_message = NULL};
.decode = decode,
.get_fields = NULL,
.build_message = NULL
};

View File

@@ -16,8 +16,8 @@
#include "../../app.h" #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"
const char *sync_pattern = "010101010101" "01100101"; "01100101";
uint8_t sync_len = 12 + 8; /* We just use 12 preamble symbols + sync. */ uint8_t sync_len = 12 + 8; /* We just use 12 preamble symbols + sync. */
if(numbits - sync_len + 8 < 8 * 10) return false; if(numbits - sync_len + 8 < 8 * 10) return false;
@@ -29,9 +29,8 @@ static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoView
off += sync_len - 8; /* Skip preamble, not sync that is part of the data. */ off += sync_len - 8; /* Skip preamble, not sync that is part of the data. */
uint8_t raw[10]; uint8_t raw[10];
uint32_t decoded = uint32_t decoded = convert_from_line_code(
convert_from_line_code(raw,sizeof(raw),bits,numbytes,off, raw, sizeof(raw), bits, numbytes, off, "01", "10"); /* Manchester code. */
"01","10"); /* Manchester code. */
FURI_LOG_E(TAG, "Schrader EG53MA4 TPMS decoded bits: %lu", decoded); FURI_LOG_E(TAG, "Schrader EG53MA4 TPMS decoded bits: %lu", decoded);
if(decoded < 10 * 8) return false; /* Require the full 10 bytes. */ if(decoded < 10 * 8) return false; /* Require the full 10 bytes. */
@@ -56,9 +55,5 @@ static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoView
return true; return true;
} }
ProtoViewDecoder SchraderEG53MA4TPMSDecoder = { ProtoViewDecoder SchraderEG53MA4TPMSDecoder =
.name = "Schrader EG53MA4 TPMS", {.name = "Schrader EG53MA4 TPMS", .decode = decode, .get_fields = NULL, .build_message = NULL};
.decode = decode,
.get_fields = NULL,
.build_message = NULL
};

View File

@@ -25,17 +25,11 @@
#include "../../app.h" #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) {
if(numbits - 6 < 64 * 2)
if (numbits-6 < 64*2) return false; /* Ask for 64 bit of data (each bit return false; /* Ask for 64 bit of data (each bit
is two symbols in the bitmap). */ is two symbols in the bitmap). */
char *sync[] = { char* sync[] = {"00111100", "001111100", "00111101", "001111101", NULL};
"00111100",
"001111100",
"00111101",
"001111101",
NULL
};
int j; int j;
uint32_t off = 0; uint32_t off = 0;
@@ -52,8 +46,7 @@ static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoView
FURI_LOG_E(TAG, "Toyota TPMS sync[%s] found", sync[j]); FURI_LOG_E(TAG, "Toyota TPMS sync[%s] found", sync[j]);
uint8_t raw[9]; uint8_t raw[9];
uint32_t decoded = uint32_t decoded = convert_from_diff_manchester(raw, sizeof(raw), bits, numbytes, off, true);
convert_from_diff_manchester(raw,sizeof(raw),bits,numbytes,off,true);
FURI_LOG_E(TAG, "Toyota TPMS decoded bits: %lu", decoded); FURI_LOG_E(TAG, "Toyota TPMS decoded bits: %lu", decoded);
if(decoded < 8 * 9) return false; /* Require the full 8 bytes. */ if(decoded < 8 * 9) return false; /* Require the full 8 bytes. */
@@ -81,9 +74,5 @@ static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoView
return true; return true;
} }
ProtoViewDecoder ToyotaTPMSDecoder = { ProtoViewDecoder ToyotaTPMSDecoder =
.name = "Toyota TPMS", {.name = "Toyota TPMS", .decode = decode, .get_fields = NULL, .build_message = NULL};
.decode = decode,
.get_fields = NULL,
.build_message = NULL
};

View File

@@ -59,9 +59,7 @@ void raw_samples_add(RawSamplesBuffer *s, bool level, uint32_t dur) {
void raw_samples_add_or_update(RawSamplesBuffer* s, bool level, uint32_t dur) { void raw_samples_add_or_update(RawSamplesBuffer* s, bool level, uint32_t dur) {
furi_mutex_acquire(s->mutex, FuriWaitForever); furi_mutex_acquire(s->mutex, FuriWaitForever);
uint32_t previdx = (s->idx - 1) % RAW_SAMPLES_NUM; uint32_t previdx = (s->idx - 1) % RAW_SAMPLES_NUM;
if (s->samples[previdx].level == level && if(s->samples[previdx].level == level && s->samples[previdx].dur != 0) {
s->samples[previdx].dur != 0)
{
/* Update the last sample: it has the same level. */ /* Update the last sample: it has the same level. */
s->samples[previdx].dur += dur; s->samples[previdx].dur += dur;
} else { } else {
@@ -75,8 +73,7 @@ void raw_samples_add_or_update(RawSamplesBuffer *s, bool level, uint32_t dur) {
/* Get the sample from the buffer. It is possible to use out of range indexes /* 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. */ * 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) void raw_samples_get(RawSamplesBuffer* s, uint32_t idx, bool* level, uint32_t* dur) {
{
furi_mutex_acquire(s->mutex, FuriWaitForever); furi_mutex_acquire(s->mutex, FuriWaitForever);
idx = (s->idx + idx) % RAW_SAMPLES_NUM; idx = (s->idx + idx) % RAW_SAMPLES_NUM;
*level = s->samples[idx].level; *level = s->samples[idx].level;

View File

@@ -4,7 +4,8 @@
/* Our circular buffer of raw samples, used in order to display /* Our circular buffer of raw samples, used in order to display
* the signal. */ * 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 of the index quite often to normalize inside
the range, and division is slow. */ the range, and division is slow. */
typedef struct RawSamplesBuffer { typedef struct RawSamplesBuffer {

View File

@@ -102,9 +102,7 @@ uint32_t search_coherent_signal(RawSamplesBuffer *s, uint32_t idx) {
for(int level = 0; level < 2; level++) { for(int level = 0; level < 2; level++) {
if(classes[j].dur[level] == 0) continue; if(classes[j].dur[level] == 0) continue;
if(classes[j].count[level] < 3) continue; if(classes[j].count[level] < 3) continue;
if (short_dur[level] == 0 || if(short_dur[level] == 0 || short_dur[level] > classes[j].dur[level]) {
short_dur[level] > classes[j].dur[level])
{
short_dur[level] = classes[j].dur[level]; short_dur[level] = classes[j].dur[level];
} }
} }
@@ -129,15 +127,10 @@ void notify_signal_detected(ProtoViewApp *app, bool decoded) {
&message_delay_50, &message_delay_50,
&message_green_0, &message_green_0,
&message_vibro_off, &message_vibro_off,
NULL NULL};
};
static const NotificationSequence unknown_seq = { static const NotificationSequence unknown_seq = {
&message_red_255, &message_red_255, &message_delay_50, &message_red_0, NULL};
&message_delay_50,
&message_red_0,
NULL
};
if(decoded) if(decoded)
notification_message(app->notification, &decoded_seq); notification_message(app->notification, &decoded_seq);
@@ -186,17 +179,19 @@ void scan_for_signal(ProtoViewApp *app, RawSamplesBuffer *source) {
/* Accept this signal as the new signal if either it's longer /* Accept this signal as the new signal if either it's longer
* than the previous undecoded one, or the previous one was * than the previous undecoded one, or the previous one was
* unknown and this is decoded. */ * unknown and this is decoded. */
if ((thislen > app->signal_bestlen && app->signal_decoded == false) if((thislen > app->signal_bestlen && app->signal_decoded == false) ||
|| (app->signal_decoded == false && decoded)) (app->signal_decoded == false && decoded)) {
{
free_msg_info(app->msg_info); free_msg_info(app->msg_info);
app->msg_info = info; app->msg_info = info;
app->signal_bestlen = thislen; app->signal_bestlen = thislen;
app->signal_decoded = decoded; app->signal_decoded = decoded;
raw_samples_copy(DetectedSamples, copy); raw_samples_copy(DetectedSamples, copy);
raw_samples_center(DetectedSamples, i); raw_samples_center(DetectedSamples, i);
FURI_LOG_E(TAG, "===> Displayed sample updated (%d samples %lu us)", FURI_LOG_E(
(int)thislen, DetectedSamples->short_pulse_dur); TAG,
"===> Displayed sample updated (%d samples %lu us)",
(int)thislen,
DetectedSamples->short_pulse_dur);
adjust_raw_view_scale(app, DetectedSamples->short_pulse_dur); adjust_raw_view_scale(app, DetectedSamples->short_pulse_dur);
notify_signal_detected(app, decoded); notify_signal_detected(app, decoded);
@@ -250,10 +245,14 @@ bool bitmap_get(uint8_t *b, uint32_t blen, uint32_t bitpos) {
* bitmap 'd' of 'dlen' total bytes. The bits are copied starting from * bitmap 'd' of 'dlen' total bytes. The bits are copied starting from
* offset 'soff' of the source bitmap to the offset 'doff' of the * offset 'soff' of the source bitmap to the offset 'doff' of the
* destination bitmap. */ * destination bitmap. */
void bitmap_copy(uint8_t *d, uint32_t dlen, uint32_t doff, void bitmap_copy(
uint8_t *s, uint32_t slen, uint32_t soff, uint8_t* d,
uint32_t count) uint32_t dlen,
{ uint32_t doff,
uint8_t* s,
uint32_t slen,
uint32_t soff,
uint32_t count) {
/* If we are byte-aligned in both source and destination, use a fast /* If we are byte-aligned in both source and destination, use a fast
* path for the number of bytes we can consume this way. */ * path for the number of bytes we can consume this way. */
if((doff & 7) == 0 && (soff & 7) == 0) { if((doff & 7) == 0 && (soff & 7) == 0) {
@@ -321,8 +320,7 @@ void bitmap_copy(uint8_t *d, uint32_t dlen, uint32_t doff,
uint32_t didx = doff / 8; uint32_t didx = doff / 8;
uint32_t sidx = soff / 8; uint32_t sidx = soff / 8;
while(count > 8 && didx < dlen && sidx < slen) { while(count > 8 && didx < dlen && sidx < slen) {
d[didx] = ((s[sidx] << skew) | d[didx] = ((s[sidx] << skew) | (s[sidx + 1] >> (8 - skew)));
(s[sidx+1] >> (8-skew)));
sidx++; sidx++;
didx++; didx++;
soff += 8; soff += 8;
@@ -375,7 +373,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 * 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 * for the kind of patterns we search we'll have a lot of early stops so
* we use a vanilla approach. */ * 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 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 endpos = startpos + blen * 8;
uint32_t end2 = startpos + maxbits; uint32_t end2 = startpos + maxbits;
if(end2 < endpos) endpos = end2; if(end2 < endpos) endpos = end2;
@@ -426,7 +429,13 @@ void bitmap_set_pattern(uint8_t *b, uint32_t blen, uint32_t off, const char *pat
* bits set into the buffer 'b'. The 'rate' argument, in microseconds, is * bits set into the buffer 'b'. The 'rate' argument, in microseconds, is
* the detected short-pulse duration. We expect the line code to be * the detected short-pulse duration. We expect the line code to be
* meaningful when interpreted at multiples of 'rate'. */ * 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) { 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. */ if(rate == 0) return 0; /* We can't perform the conversion. */
uint32_t bitpos = 0; uint32_t bitpos = 0;
for(uint32_t j = 0; j < count; j++) { for(uint32_t j = 0; j < count; j++) {
@@ -443,8 +452,7 @@ uint32_t convert_signal_to_bits(uint8_t *b, uint32_t blen, RawSamplesBuffer *s,
if(numbits > 1024) numbits = 1024; if(numbits > 1024) numbits = 1024;
if(0) /* Super verbose, so not under the DEBUG_MSG define. */ if(0) /* Super verbose, so not under the DEBUG_MSG define. */
FURI_LOG_E(TAG, "%lu converted into %lu (%d) bits", FURI_LOG_E(TAG, "%lu converted into %lu (%d) bits", dur, numbits, (int)level);
dur,numbits,(int)level);
/* If the signal is too short, let's claim it an interference /* If the signal is too short, let's claim it an interference
* and ignore it completely. */ * and ignore it completely. */
@@ -467,8 +475,14 @@ uint32_t convert_signal_to_bits(uint8_t *b, uint32_t blen, RawSamplesBuffer *s,
* specified in bytes by the caller, via the 'len' parameters). * specified in bytes by the caller, via the 'len' parameters).
* *
* The decoding starts at the specified offset (in bits) 'off'. */ * 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. */ uint32_t decoded = 0; /* Number of bits extracted. */
len *= 8; /* Convert bytes to bits. */ len *= 8; /* Convert bytes to bits. */
while(off < len) { while(off < len) {
@@ -494,8 +508,13 @@ 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. * in differential codings the next bits depend on the previous one.
* *
* Parameters and return values are like convert_from_line_code(). */ * 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; uint32_t decoded = 0;
len *= 8; /* Conver to bits. */ len *= 8; /* Conver to bits. */
for(uint32_t j = off; j < len; j += 2) { for(uint32_t j = off; j < len; j += 2) {
@@ -532,8 +551,7 @@ ProtoViewDecoder *Decoders[] = {
&CitroenTPMSDecoder, /* Citroen TPMS. */ &CitroenTPMSDecoder, /* Citroen TPMS. */
&FordTPMSDecoder, /* Ford TPMS. */ &FordTPMSDecoder, /* Ford TPMS. */
&KeeloqDecoder, /* Keeloq remote. */ &KeeloqDecoder, /* Keeloq remote. */
NULL NULL};
};
/* Free the message info and allocated data. */ /* Free the message info and allocated data. */
void free_msg_info(ProtoViewMsgInfo* i) { void free_msg_info(ProtoViewMsgInfo* i) {
@@ -566,7 +584,13 @@ bool decode_signal(RawSamplesBuffer *s, uint64_t len, ProtoViewMsgInfo *info) {
uint32_t after_samples = 100; uint32_t after_samples = 100;
uint8_t* bitmap = malloc(bitmap_size); 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); 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. */ if(DEBUG_MSG) { /* Useful for debugging purposes. Don't remove. */
char* str = malloc(1024); char* str = malloc(1024);
@@ -587,8 +611,7 @@ bool decode_signal(RawSamplesBuffer *s, uint64_t len, ProtoViewMsgInfo *info) {
uint32_t start_time = furi_get_tick(); 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; uint32_t delta = furi_get_tick() - start_time;
FURI_LOG_E(TAG, "Decoder %s took %lu ms", FURI_LOG_E(TAG, "Decoder %s took %lu ms", Decoders[j]->name, (unsigned long)delta);
Decoders[j]->name, (unsigned long)delta);
if(decoded) { if(decoded) {
info->decoder = Decoders[j]; info->decoder = Decoders[j];
break; break;
@@ -607,8 +630,13 @@ bool decode_signal(RawSamplesBuffer *s, uint64_t len, ProtoViewMsgInfo *info) {
if(info->pulses_count) { if(info->pulses_count) {
info->bits_bytes = (info->pulses_count + 7) / 8; // Round to full byte. info->bits_bytes = (info->pulses_count + 7) / 8; // Round to full byte.
info->bits = malloc(info->bits_bytes); info->bits = malloc(info->bits_bytes);
bitmap_copy(info->bits,info->bits_bytes,0, bitmap_copy(
bitmap,bitmap_size,info->start_off, info->bits,
info->bits_bytes,
0,
bitmap,
bitmap_size,
info->start_off,
info->pulses_count); info->pulses_count);
} }
} }

View File

@@ -28,7 +28,8 @@ bool save_signal(ProtoViewApp *app, const char *filename) {
FuriString* file_content = furi_string_alloc(); FuriString* file_content = furi_string_alloc();
const char* preset_id = ProtoViewModulations[app->modulation].id; const char* preset_id = ProtoViewModulations[app->modulation].id;
furi_string_printf(file_content, furi_string_printf(
file_content,
"Filetype: Flipper SubGhz RAW File\n" "Filetype: Flipper SubGhz RAW File\n"
"Version: 1\n" "Version: 1\n"
"Frequency: %ld\n" "Frequency: %ld\n"
@@ -40,12 +41,12 @@ bool save_signal(ProtoViewApp *app, const char *filename) {
if(preset_id == NULL) { if(preset_id == NULL) {
FuriString* custom = furi_string_alloc(); FuriString* custom = furi_string_alloc();
uint8_t* regs = ProtoViewModulations[app->modulation].custom; uint8_t* regs = ProtoViewModulations[app->modulation].custom;
furi_string_printf(custom, furi_string_printf(
custom,
"Custom_preset_module: CC1101\n" "Custom_preset_module: CC1101\n"
"Custom_preset_data: "); "Custom_preset_data: ");
for(int j = 0; regs[j]; j += 2) { for(int j = 0; regs[j]; j += 2) {
furi_string_cat_printf(custom, "%02X %02X ", furi_string_cat_printf(custom, "%02X %02X ", (int)regs[j], (int)regs[j + 1]);
(int)regs[j], (int)regs[j+1]);
} }
size_t len = furi_string_size(file_content); size_t len = furi_string_size(file_content);
furi_string_set_char(custom, len - 1, '\n'); furi_string_set_char(custom, len - 1, '\n');
@@ -54,16 +55,14 @@ bool save_signal(ProtoViewApp *app, const char *filename) {
} }
/* We always save raw files. */ /* We always save raw files. */
furi_string_cat_printf(file_content, furi_string_cat_printf(
file_content,
"Protocol: RAW\n" "Protocol: RAW\n"
"RAW_Data: -10000\n"); // Start with 10 ms of gap "RAW_Data: -10000\n"); // Start with 10 ms of gap
/* Write header. */ /* Write header. */
size_t len = furi_string_size(file_content); size_t len = furi_string_size(file_content);
if (stream_write(stream, if(stream_write(stream, (uint8_t*)furi_string_get_cstr(file_content), len) != len) {
(uint8_t*) furi_string_get_cstr(file_content), len)
!= len)
{
FURI_LOG_W(TAG, "Short write to file"); FURI_LOG_W(TAG, "Short write to file");
success = false; success = false;
goto write_err; goto write_err;
@@ -82,9 +81,7 @@ bool save_signal(ProtoViewApp *app, const char *filename) {
uint32_t te_times = 1; uint32_t te_times = 1;
idx++; idx++;
/* Count the duration of the current pulse/gap. */ /* Count the duration of the current pulse/gap. */
while(idx < i->pulses_count && while(idx < i->pulses_count && bitmap_get(i->bits, i->bits_bytes, idx) == level) {
bitmap_get(i->bits,i->bits_bytes,idx) == level)
{
te_times++; te_times++;
idx++; idx++;
} }
@@ -96,8 +93,7 @@ bool save_signal(ProtoViewApp *app, const char *filename) {
/* Emit the sample. If this is the first sample of the line, /* Emit the sample. If this is the first sample of the line,
* also emit the RAW_Data: field. */ * also emit the RAW_Data: field. */
if (this_line_samples == 0) if(this_line_samples == 0) furi_string_cat_printf(file_content, "RAW_Data: ");
furi_string_cat_printf(file_content,"RAW_Data: ");
furi_string_cat_printf(file_content, "%d ", (int)dur); furi_string_cat_printf(file_content, "%d ", (int)dur);
this_line_samples++; this_line_samples++;
@@ -114,10 +110,8 @@ bool save_signal(ProtoViewApp *app, const char *filename) {
size_t len = furi_string_size(file_content); size_t len = furi_string_size(file_content);
furi_string_set_char(file_content, len - 1, '\n'); furi_string_set_char(file_content, len - 1, '\n');
if (stream_write(stream, if(stream_write(stream, (uint8_t*)furi_string_get_cstr(file_content), len) !=
(uint8_t*) furi_string_get_cstr(file_content), len) {
len) != len)
{
FURI_LOG_W(TAG, "Short write to file"); FURI_LOG_W(TAG, "Short write to file");
success = false; success = false;
goto write_err; goto write_err;

View File

@@ -17,12 +17,9 @@ int ui_get_current_subview(ProtoViewApp *app) {
/* Called by view rendering callback that has subviews, to show small triangles /* Called by view rendering callback that has subviews, to show small triangles
* facing down/up if there are other subviews the user can access with up * facing down/up if there are other subviews the user can access with up
* and down. */ * and down. */
void ui_show_available_subviews(Canvas *canvas, ProtoViewApp *app, void ui_show_available_subviews(Canvas* canvas, ProtoViewApp* app, int last_subview) {
int last_subview)
{
int subview = ui_get_current_subview(app); int subview = ui_get_current_subview(app);
if (subview != 0) if(subview != 0) canvas_draw_triangle(canvas, 120, 5, 8, 5, CanvasDirectionBottomToTop);
canvas_draw_triangle(canvas,120,5,8,5,CanvasDirectionBottomToTop);
if(subview != last_subview - 1) if(subview != last_subview - 1)
canvas_draw_triangle(canvas, 120, 59, 8, 5, CanvasDirectionTopToBottom); canvas_draw_triangle(canvas, 120, 59, 8, 5, CanvasDirectionTopToBottom);
} }
@@ -34,12 +31,10 @@ bool ui_process_subview_updown(ProtoViewApp *app, InputEvent input, int last_sub
int subview = ui_get_current_subview(app); int subview = ui_get_current_subview(app);
if(input.type == InputTypePress) { if(input.type == InputTypePress) {
if(input.key == InputKeyUp) { if(input.key == InputKeyUp) {
if (subview != 0) if(subview != 0) app->current_subview[app->current_view]--;
app->current_subview[app->current_view]--;
return true; return true;
} else if(input.key == InputKeyDown) { } else if(input.key == InputKeyDown) {
if (subview != last_subview-1) if(subview != last_subview - 1) app->current_subview[app->current_view]++;
app->current_subview[app->current_view]++;
return true; return true;
} }
} }
@@ -62,9 +57,11 @@ bool ui_process_subview_updown(ProtoViewApp *app, InputEvent input, int last_sub
* *
* Note: if the buffer is not a null-termined zero string, what it contains will * Note: if the buffer is not a null-termined zero string, what it contains will
* be used as initial input for the user. */ * be used as initial input for the user. */
void ui_show_keyboard(ProtoViewApp *app, char *buffer, uint32_t buflen, void ui_show_keyboard(
void (*done_callback)(void*)) ProtoViewApp* app,
{ char* buffer,
uint32_t buflen,
void (*done_callback)(void*)) {
app->show_text_input = true; app->show_text_input = true;
app->text_input_buffer = buffer; app->text_input_buffer = buffer;
app->text_input_buffer_len = buflen; app->text_input_buffer_len = buflen;
@@ -110,36 +107,38 @@ void ui_draw_alert_if_needed(Canvas *canvas, ProtoViewApp *app) {
uint8_t text_y = 32 + 4; uint8_t text_y = 32 + 4;
uint8_t padding = 3; uint8_t padding = 3;
canvas_set_color(canvas, ColorBlack); canvas_set_color(canvas, ColorBlack);
canvas_draw_box(canvas,text_x-padding,text_y-padding-h,w+padding*2,h+padding*2); canvas_draw_box(
canvas, text_x - padding, text_y - padding - h, w + padding * 2, h + padding * 2);
canvas_set_color(canvas, ColorWhite); canvas_set_color(canvas, ColorWhite);
canvas_draw_box(canvas,text_x-padding+1,text_y-padding-h+1,w+padding*2-2,h+padding*2-2); canvas_draw_box(
canvas,
text_x - padding + 1,
text_y - padding - h + 1,
w + padding * 2 - 2,
h + padding * 2 - 2);
canvas_set_color(canvas, ColorBlack); canvas_set_color(canvas, ColorBlack);
canvas_draw_str(canvas, text_x, text_y, app->alert_text); canvas_draw_str(canvas, text_x, text_y, app->alert_text);
} }
/* =========================== Canvas extensions ============================ */ /* =========================== Canvas extensions ============================ */
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 { struct {
uint8_t x; uint8_t y; uint8_t x;
} dir[8] = { uint8_t y;
{-1,-1}, } dir[8] = {{-1, -1}, {0, -1}, {1, -1}, {1, 0}, {1, 1}, {0, 1}, {-1, 1}, {-1, 0}};
{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 /* Rotate in all the directions writing the same string to create a
* border, then write the actual string in the other color in the * border, then write the actual string in the other color in the
* middle. */ * middle. */
canvas_set_color(canvas, border_color); canvas_set_color(canvas, border_color);
for (int j = 0; j < 8; j++) for(int j = 0; j < 8; j++) canvas_draw_str(canvas, x + dir[j].x, y + dir[j].y, str);
canvas_draw_str(canvas,x+dir[j].x,y+dir[j].y,str);
canvas_set_color(canvas, text_color); 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); canvas_set_color(canvas, ColorBlack);

View File

@@ -26,8 +26,7 @@ static void select_next_decoder(ProtoViewApp *app) {
BuildViewPrivData* privdata = app->view_privdata; BuildViewPrivData* privdata = app->view_privdata;
do { do {
privdata->cur_decoder++; privdata->cur_decoder++;
if (Decoders[privdata->cur_decoder] == NULL) if(Decoders[privdata->cur_decoder] == NULL) privdata->cur_decoder = 0;
privdata->cur_decoder = 0;
} while(Decoders[privdata->cur_decoder]->get_fields == NULL); } while(Decoders[privdata->cur_decoder]->get_fields == NULL);
} }
@@ -53,8 +52,8 @@ static void render_view_select_decoder(Canvas *const canvas, ProtoViewApp *app)
canvas_draw_str(canvas, 0, 19, "up/down: select, ok: choose"); canvas_draw_str(canvas, 0, 19, "up/down: select, ok: choose");
canvas_set_font(canvas, FontPrimary); canvas_set_font(canvas, FontPrimary);
canvas_draw_str_aligned(canvas,64,38,AlignCenter,AlignCenter, canvas_draw_str_aligned(
Decoders[privdata->cur_decoder]->name); canvas, 64, 38, AlignCenter, AlignCenter, Decoders[privdata->cur_decoder]->name);
} }
/* Render the view that allows the user to populate the fields needed /* Render the view that allows the user to populate the fields needed
@@ -62,8 +61,12 @@ static void render_view_select_decoder(Canvas *const canvas, ProtoViewApp *app)
static void render_view_set_fields(Canvas* const canvas, ProtoViewApp* app) { static void render_view_set_fields(Canvas* const canvas, ProtoViewApp* app) {
BuildViewPrivData* privdata = app->view_privdata; BuildViewPrivData* privdata = app->view_privdata;
char buf[32]; char buf[32];
snprintf(buf,sizeof(buf), "%s field %d/%d", snprintf(
privdata->decoder->name, (int)privdata->cur_field+1, buf,
sizeof(buf),
"%s field %d/%d",
privdata->decoder->name,
(int)privdata->cur_field + 1,
(int)privdata->fieldset->numfields); (int)privdata->fieldset->numfields);
canvas_set_color(canvas, ColorBlack); canvas_set_color(canvas, ColorBlack);
canvas_draw_box(canvas, 0, 0, 128, 21); canvas_draw_box(canvas, 0, 0, 128, 21);
@@ -76,8 +79,8 @@ static void render_view_set_fields(Canvas *const canvas, ProtoViewApp *app) {
/* Write the field name, type, current content. */ /* Write the field name, type, current content. */
canvas_set_color(canvas, ColorBlack); canvas_set_color(canvas, ColorBlack);
ProtoViewField* field = privdata->fieldset->fields[privdata->cur_field]; ProtoViewField* field = privdata->fieldset->fields[privdata->cur_field];
snprintf(buf,sizeof(buf), "%s %s:%d", field->name, snprintf(
field_get_type_name(field), (int)field->len); buf, sizeof(buf), "%s %s:%d", field->name, field_get_type_name(field), (int)field->len);
buf[0] = toupper(buf[0]); buf[0] = toupper(buf[0]);
canvas_set_font(canvas, FontPrimary); canvas_set_font(canvas, FontPrimary);
canvas_draw_str_aligned(canvas, 64, 30, AlignCenter, AlignCenter, buf); canvas_draw_str_aligned(canvas, 64, 30, AlignCenter, AlignCenter, buf);
@@ -116,11 +119,8 @@ static void process_input_select_decoder(ProtoViewApp *app, InputEvent input) {
* same decoder the user selected, let's populate the * same decoder the user selected, let's populate the
* defaults with the current values. So the user will * defaults with the current values. So the user will
* actaully edit the current message. */ * actaully edit the current message. */
if (app->signal_decoded && if(app->signal_decoded && app->msg_info->decoder == privdata->decoder) {
app->msg_info->decoder == privdata->decoder) fieldset_copy_matching_fields(privdata->fieldset, app->msg_info->fieldset);
{
fieldset_copy_matching_fields(privdata->fieldset,
app->msg_info->fieldset);
} }
/* Now we use the subview system in order to protect the /* Now we use the subview system in order to protect the
@@ -143,9 +143,10 @@ static void text_input_done_callback(void* context) {
ProtoViewApp* app = context; ProtoViewApp* app = context;
BuildViewPrivData* privdata = app->view_privdata; BuildViewPrivData* privdata = app->view_privdata;
if (field_set_from_string(privdata->fieldset->fields[privdata->cur_field], if(field_set_from_string(
privdata->user_value, strlen(privdata->user_value)) == false) privdata->fieldset->fields[privdata->cur_field],
{ privdata->user_value,
strlen(privdata->user_value)) == false) {
ui_show_alert(app, "Invalid value", 1500); ui_show_alert(app, "Invalid value", 1500);
} }
@@ -175,12 +176,9 @@ static void process_input_set_fields(ProtoViewApp *app, InputEvent input) {
if(input.type == InputTypeShort && input.key == InputKeyOk) { if(input.type == InputTypeShort && input.key == InputKeyOk) {
/* Show the keyboard to let the user type the new /* Show the keyboard to let the user type the new
* value. */ * value. */
if (privdata->user_value == NULL) if(privdata->user_value == NULL) privdata->user_value = malloc(USER_VALUE_LEN);
privdata->user_value = malloc(USER_VALUE_LEN); field_to_string(privdata->user_value, USER_VALUE_LEN, fs->fields[privdata->cur_field]);
field_to_string(privdata->user_value, USER_VALUE_LEN, ui_show_keyboard(app, privdata->user_value, USER_VALUE_LEN, text_input_done_callback);
fs->fields[privdata->cur_field]);
ui_show_keyboard(app, privdata->user_value, USER_VALUE_LEN,
text_input_done_callback);
} else if(input.type == InputTypeShort && input.key == InputKeyDown) { } else if(input.type == InputTypeShort && input.key == InputKeyDown) {
privdata->cur_field = (privdata->cur_field + 1) % fs->numfields; privdata->cur_field = (privdata->cur_field + 1) % fs->numfields;
} else if(input.type == InputTypeShort && input.key == InputKeyUp) { } else if(input.type == InputTypeShort && input.key == InputKeyUp) {
@@ -236,12 +234,9 @@ void view_enter_build_message(ProtoViewApp *app) {
// However if there is currently a decoded message, and the // However if there is currently a decoded message, and the
// decoder of such message supports message building, let's // decoder of such message supports message building, let's
// select it. // select it.
if (app->signal_decoded && if(app->signal_decoded && app->msg_info->decoder->get_fields &&
app->msg_info->decoder->get_fields && app->msg_info->decoder->build_message) {
app->msg_info->decoder->build_message) while(Decoders[privdata->cur_decoder] != app->msg_info->decoder) select_next_decoder(app);
{
while(Decoders[privdata->cur_decoder] != app->msg_info->decoder)
select_next_decoder(app);
} }
} }

View File

@@ -27,12 +27,13 @@ void render_view_direct_sampling(Canvas *const canvas, ProtoViewApp *app) {
/* Busy loop: this is a terrible approach as it blocks /* Busy loop: this is a terrible approach as it blocks
* everything else, but for now it's the best we can do * everything else, but for now it's the best we can do
* to obtain direct data with some spacing. */ * 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_set_font(canvas, FontSecondary);
canvas_draw_str_with_border(canvas,36,60,"Direct sampling", canvas_draw_str_with_border(canvas, 36, 60, "Direct sampling", ColorWhite, ColorBlack);
ColorWhite,ColorBlack);
} }
/* Handle input */ /* Handle input */
@@ -45,9 +46,7 @@ void process_input_direct_sampling(ProtoViewApp *app, InputEvent input) {
/* Enter view. Stop the subghz thread to prevent access as we read /* Enter view. Stop the subghz thread to prevent access as we read
* the CC1101 data directly. */ * the CC1101 data directly. */
void view_enter_direct_sampling(ProtoViewApp* app) { void view_enter_direct_sampling(ProtoViewApp* app) {
if (app->txrx->txrx_state == TxRxStateRx && if(app->txrx->txrx_state == TxRxStateRx && !app->txrx->debug_timer_sampling) {
!app->txrx->debug_timer_sampling)
{
subghz_worker_stop(app->txrx->worker); subghz_worker_stop(app->txrx->worker);
} else { } else {
raw_sampling_worker_stop(app); raw_sampling_worker_stop(app);
@@ -56,9 +55,7 @@ void view_enter_direct_sampling(ProtoViewApp *app) {
/* Exit view. Restore the subghz thread. */ /* Exit view. Restore the subghz thread. */
void view_exit_direct_sampling(ProtoViewApp* app) { void view_exit_direct_sampling(ProtoViewApp* app) {
if (app->txrx->txrx_state == TxRxStateRx && if(app->txrx->txrx_state == TxRxStateRx && !app->txrx->debug_timer_sampling) {
!app->txrx->debug_timer_sampling)
{
subghz_worker_start(app->txrx->worker); subghz_worker_start(app->txrx->worker);
} else { } else {
raw_sampling_worker_start(app); raw_sampling_worker_start(app);

View File

@@ -27,9 +27,7 @@ typedef struct {
} InfoViewPrivData; } InfoViewPrivData;
/* Draw the text label and value of the specified info field at x,y. */ /* Draw the text label and value of the specified info field at x,y. */
static void render_info_field(Canvas *const canvas, static void render_info_field(Canvas* const canvas, ProtoViewField* f, uint8_t x, uint8_t y) {
ProtoViewField *f, uint8_t x, uint8_t y)
{
char buf[64]; char buf[64];
char strval[32]; char strval[32];
@@ -43,8 +41,8 @@ static void render_info_field(Canvas *const canvas,
#define INFO_LINES_PER_PAGE 5 #define INFO_LINES_PER_PAGE 5
static void render_subview_main(Canvas* const canvas, ProtoViewApp* app) { static void render_subview_main(Canvas* const canvas, ProtoViewApp* app) {
InfoViewPrivData* privdata = app->view_privdata; InfoViewPrivData* privdata = app->view_privdata;
uint8_t pages = (app->msg_info->fieldset->numfields uint8_t pages =
+(INFO_LINES_PER_PAGE-1)) / INFO_LINES_PER_PAGE; (app->msg_info->fieldset->numfields + (INFO_LINES_PER_PAGE - 1)) / INFO_LINES_PER_PAGE;
privdata->cur_info_page %= pages; privdata->cur_info_page %= pages;
uint8_t current_page = privdata->cur_info_page; uint8_t current_page = privdata->cur_info_page;
char buf[32]; char buf[32];
@@ -54,8 +52,8 @@ static void render_subview_main(Canvas *const canvas, ProtoViewApp *app) {
uint8_t y = 8, lineheight = 10; uint8_t y = 8, lineheight = 10;
if(pages > 1) { if(pages > 1) {
snprintf(buf,sizeof(buf),"%s %u/%u", app->msg_info->decoder->name, snprintf(
current_page+1, pages); buf, sizeof(buf), "%s %u/%u", app->msg_info->decoder->name, current_page + 1, pages);
canvas_draw_str(canvas, 0, y, buf); canvas_draw_str(canvas, 0, y, buf);
} else { } else {
canvas_draw_str(canvas, 0, y, app->msg_info->decoder->name); canvas_draw_str(canvas, 0, y, app->msg_info->decoder->name);
@@ -75,10 +73,14 @@ static void render_subview_main(Canvas *const canvas, ProtoViewApp *app) {
* something better ASAP. */ * something better ASAP. */
y = 37; y = 37;
lineheight = 7; lineheight = 7;
canvas_draw_str(canvas, 119, y, "s"); y += lineheight; canvas_draw_str(canvas, 119, y, "s");
canvas_draw_str(canvas, 119, y, "a"); y += lineheight; y += lineheight;
canvas_draw_str(canvas, 119, y, "v"); y += lineheight; canvas_draw_str(canvas, 119, y, "a");
canvas_draw_str(canvas, 119, y, "e"); y += lineheight; y += lineheight;
canvas_draw_str(canvas, 119, y, "v");
y += lineheight;
canvas_draw_str(canvas, 119, y, "e");
y += lineheight;
} }
/* Render view with save option. */ /* Render view with save option. */
@@ -96,8 +98,7 @@ static void render_subview_save(Canvas *const canvas, ProtoViewApp *app) {
bool prevbit = false; bool prevbit = false;
for(uint8_t y = bitheight + 12; y <= rows * rowheight; y += rowheight) { for(uint8_t y = bitheight + 12; y <= rows * rowheight; y += rowheight) {
for(uint8_t x = 0; x < 128; x += 4) { for(uint8_t x = 0; x < 128; x += 4) {
bool bit = bitmap_get(app->msg_info->bits, bool bit = bitmap_get(app->msg_info->bits, app->msg_info->bits_bytes, idx);
app->msg_info->bits_bytes,idx);
uint8_t prevy = y + prevbit * (bitheight * -1) - 1; uint8_t prevy = y + prevbit * (bitheight * -1) - 1;
uint8_t thisy = y + bit * (bitheight * -1) - 1; uint8_t thisy = y + bit * (bitheight * -1) - 1;
canvas_draw_line(canvas, x, prevy, x, thisy); canvas_draw_line(canvas, x, prevy, x, thisy);
@@ -127,8 +128,12 @@ void render_view_info(Canvas *const canvas, ProtoViewApp *app) {
ui_show_available_subviews(canvas, app, SubViewInfoLast); ui_show_available_subviews(canvas, app, SubViewInfoLast);
switch(app->current_subview[app->current_view]) { switch(app->current_subview[app->current_view]) {
case SubViewInfoMain: render_subview_main(canvas,app); break; case SubViewInfoMain:
case SubViewInfoSave: render_subview_save(canvas,app); break; render_subview_main(canvas, app);
break;
case SubViewInfoSave:
render_subview_save(canvas, app);
break;
} }
} }
@@ -138,8 +143,8 @@ static void text_input_done_callback(void* context) {
ProtoViewApp* app = context; ProtoViewApp* app = context;
InfoViewPrivData* privdata = app->view_privdata; InfoViewPrivData* privdata = app->view_privdata;
FuriString *save_path = furi_string_alloc_printf( FuriString* save_path =
"%s/%s.sub", EXT_PATH("subghz"), privdata->filename); furi_string_alloc_printf("%s/%s.sub", EXT_PATH("subghz"), privdata->filename);
save_signal(app, furi_string_get_cstr(save_path)); save_signal(app, furi_string_get_cstr(save_path));
furi_string_free(save_path); furi_string_free(save_path);
@@ -231,9 +236,8 @@ LevelDuration radio_tx_feed_data(void *ctx) {
/* Let's see how many consecutive bits we have with the same /* Let's see how many consecutive bits we have with the same
* level. */ * level. */
for(j = 0; ss->curpos + j < ss->app->msg_info->pulses_count; j++) { for(j = 0; ss->curpos + j < ss->app->msg_info->pulses_count; j++) {
uint32_t l = bitmap_get(ss->app->msg_info->bits, uint32_t l =
ss->app->msg_info->bits_bytes, bitmap_get(ss->app->msg_info->bits, ss->app->msg_info->bits_bytes, ss->curpos + j);
ss->curpos+j);
if(j == 0) { if(j == 0) {
/* At the first bit of this sequence, we store the /* At the first bit of this sequence, we store the
* level of the sequence. */ * level of the sequence. */
@@ -251,8 +255,7 @@ LevelDuration radio_tx_feed_data(void *ctx) {
/* If this was the last set of bits, change the state to /* If this was the last set of bits, change the state to
* send the final gap. */ * send the final gap. */
if (ss->curpos >= ss->app->msg_info->pulses_count) if(ss->curpos >= ss->app->msg_info->pulses_count) ss->state = SendSignalSendEndGap;
ss->state = SendSignalSendEndGap;
return level_duration_make(level, dur); return level_duration_make(level, dur);
} }
@@ -277,8 +280,7 @@ void notify_signal_sent(ProtoViewApp *app) {
&message_sound_off, &message_sound_off,
&message_vibro_off, &message_vibro_off,
&message_blue_0, &message_blue_0,
NULL NULL};
};
notification_message(app->notification, &sent_seq); notification_message(app->notification, &sent_seq);
} }
@@ -286,8 +288,7 @@ void notify_signal_sent(ProtoViewApp *app) {
void process_input_info(ProtoViewApp* app, InputEvent input) { void process_input_info(ProtoViewApp* app, InputEvent input) {
/* If we don't have a decoded signal, we don't allow to go up/down /* If we don't have a decoded signal, we don't allow to go up/down
* in the subviews: they are only useful when a loaded signal. */ * in the subviews: they are only useful when a loaded signal. */
if (app->signal_decoded && if(app->signal_decoded && ui_process_subview_updown(app, input, SubViewInfoLast)) return;
ui_process_subview_updown(app,input,SubViewInfoLast)) return;
InfoViewPrivData* privdata = app->view_privdata; InfoViewPrivData* privdata = app->view_privdata;
int subview = ui_get_current_subview(app); int subview = ui_get_current_subview(app);
@@ -306,17 +307,13 @@ void process_input_info(ProtoViewApp *app, InputEvent input) {
if(input.type == InputTypePress && input.key == InputKeyRight) { if(input.type == InputTypePress && input.key == InputKeyRight) {
privdata->signal_display_start_row++; privdata->signal_display_start_row++;
} else if(input.type == InputTypePress && input.key == InputKeyLeft) { } else if(input.type == InputTypePress && input.key == InputKeyLeft) {
if (privdata->signal_display_start_row != 0) if(privdata->signal_display_start_row != 0) privdata->signal_display_start_row--;
privdata->signal_display_start_row--; } else if(input.type == InputTypeLong && input.key == InputKeyOk) {
} else if (input.type == InputTypeLong && input.key == InputKeyOk)
{
// We have have the buffer already allocated, in case the // We have have the buffer already allocated, in case the
// user aborted with BACK a previous saving. // user aborted with BACK a previous saving.
if (privdata->filename == NULL) if(privdata->filename == NULL) privdata->filename = malloc(SAVE_FILENAME_LEN);
privdata->filename = malloc(SAVE_FILENAME_LEN);
set_signal_random_filename(app, privdata->filename, SAVE_FILENAME_LEN); set_signal_random_filename(app, privdata->filename, SAVE_FILENAME_LEN);
ui_show_keyboard(app, privdata->filename, SAVE_FILENAME_LEN, ui_show_keyboard(app, privdata->filename, SAVE_FILENAME_LEN, text_input_done_callback);
text_input_done_callback);
} else if(input.type == InputTypeShort && input.key == InputKeyOk) { } else if(input.type == InputTypeShort && input.key == InputKeyOk) {
SendSignalCtx send_state; SendSignalCtx send_state;
send_signal_init(&send_state, app); send_signal_init(&send_state, app);

View File

@@ -32,9 +32,7 @@ void render_signal(ProtoViewApp *app, Canvas *const canvas, RawSamplesBuffer *bu
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. */ /* Write a small triangle under the last sample detected. */
if (app->signal_bestlen != 0 && if(app->signal_bestlen != 0 && sample_num + start_idx == app->signal_bestlen + 1) {
sample_num+start_idx == app->signal_bestlen+1)
{
canvas_draw_dot(canvas, x, y + 2); canvas_draw_dot(canvas, x, y + 2);
canvas_draw_dot(canvas, x - 1, y + 3); canvas_draw_dot(canvas, x - 1, y + 3);
canvas_draw_dot(canvas, x, y + 3); canvas_draw_dot(canvas, x, y + 3);
@@ -59,13 +57,13 @@ void render_view_raw_pulses(Canvas *const canvas, ProtoViewApp *app) {
/* Show signal information. */ /* Show signal information. */
char buf[64]; char buf[64];
snprintf(buf,sizeof(buf),"%luus", snprintf(buf, sizeof(buf), "%luus", (unsigned long)DetectedSamples->short_pulse_dur);
(unsigned long)DetectedSamples->short_pulse_dur);
canvas_set_font(canvas, FontSecondary); canvas_set_font(canvas, FontSecondary);
canvas_draw_str_with_border(canvas, 97, 63, buf, ColorWhite, ColorBlack); 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_set_font(canvas, FontPrimary);
canvas_draw_str_with_border(canvas, 1, 61, app->msg_info->decoder->name, ColorWhite, ColorBlack); canvas_draw_str_with_border(
canvas, 1, 61, app->msg_info->decoder->name, ColorWhite, ColorBlack);
} }
} }
@@ -75,8 +73,10 @@ void process_input_raw_pulses(ProtoViewApp *app, InputEvent input) {
/* Handle panning of the signal window. Long pressing /* Handle panning of the signal window. Long pressing
* right will show successive samples, long pressing left * right will show successive samples, long pressing left
* previous samples. */ * previous samples. */
if (input.key == InputKeyRight) app->signal_offset++; if(input.key == InputKeyRight)
else if (input.key == InputKeyLeft) app->signal_offset--; app->signal_offset++;
else if(input.key == InputKeyLeft)
app->signal_offset--;
} else if(input.type == InputTypeLong) { } else if(input.type == InputTypeLong) {
if(input.key == InputKeyOk) { if(input.key == InputKeyOk) {
/* Reset the current sample to capture the next. */ /* Reset the current sample to capture the next. */

View File

@@ -55,9 +55,7 @@ void process_input_settings(ProtoViewApp *app, InputEvent input) {
app->txrx->debug_timer_sampling = !app->txrx->debug_timer_sampling; app->txrx->debug_timer_sampling = !app->txrx->debug_timer_sampling;
radio_begin(app); radio_begin(app);
radio_rx(app); radio_rx(app);
} else if (input.type == InputTypePress && } else if(input.type == InputTypePress && (input.key != InputKeyDown || input.key != InputKeyUp)) {
(input.key != InputKeyDown || input.key != InputKeyUp))
{
/* Handle up and down to change frequency or modulation. */ /* 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 curidx = 0, i;
@@ -108,7 +106,11 @@ void process_input_settings(ProtoViewApp *app, InputEvent input) {
* we need to restart the radio with the right frequency and modulation. */ * we need to restart the radio with the right frequency and modulation. */
void view_exit_settings(ProtoViewApp* app) { void view_exit_settings(ProtoViewApp* app) {
if(app->txrx->freq_mod_changed) { if(app->txrx->freq_mod_changed) {
FURI_LOG_E(TAG, "Setting view, setting frequency/modulation to %lu %s", app->frequency, ProtoViewModulations[app->modulation].name); FURI_LOG_E(
TAG,
"Setting view, setting frequency/modulation to %lu %s",
app->frequency,
ProtoViewModulations[app->modulation].name);
radio_rx_end(app); radio_rx_end(app);
radio_begin(app); radio_begin(app);
radio_rx(app); radio_rx(app);

View File

@@ -13,7 +13,6 @@
#define STATE_FILE_VERSION 2 #define STATE_FILE_VERSION 2
#define TAMA_SAVE_PATH EXT_PATH("tama_p1/save.bin") #define TAMA_SAVE_PATH EXT_PATH("tama_p1/save.bin")
typedef struct { typedef struct {
FuriThread* thread; FuriThread* thread;
hal_t hal; hal_t hal;

View File

@@ -53,7 +53,6 @@ static void tama_p1_draw_callback(Canvas* const canvas, void* cb_ctx) {
uint16_t lcd_icon_spacing_horiz = uint16_t lcd_icon_spacing_horiz =
(lcd_matrix_scaled_width - (4 * TAMA_LCD_ICON_SIZE)) / 3 + TAMA_LCD_ICON_SIZE; (lcd_matrix_scaled_width - (4 * TAMA_LCD_ICON_SIZE)) / 3 + TAMA_LCD_ICON_SIZE;
uint16_t y = lcd_matrix_top; uint16_t y = lcd_matrix_top;
for(uint8_t row = 0; row < 16; ++row) { for(uint8_t row = 0; row < 16; ++row) {
uint16_t x = lcd_matrix_left; uint16_t x = lcd_matrix_left;
@@ -124,7 +123,6 @@ static void tama_p1_load_state() {
Storage* storage = furi_record_open(RECORD_STORAGE); Storage* storage = furi_record_open(RECORD_STORAGE);
File* file = storage_file_alloc(storage); File* file = storage_file_alloc(storage);
if(storage_file_open(file, TAMA_SAVE_PATH, FSAM_READ, FSOM_OPEN_EXISTING)) { if(storage_file_open(file, TAMA_SAVE_PATH, FSAM_READ, FSOM_OPEN_EXISTING)) {
storage_file_read(file, &buf, 4); storage_file_read(file, &buf, 4);
if(buf[0] != (uint8_t)STATE_FILE_MAGIC[0] || buf[1] != (uint8_t)STATE_FILE_MAGIC[1] || if(buf[0] != (uint8_t)STATE_FILE_MAGIC[0] || buf[1] != (uint8_t)STATE_FILE_MAGIC[1] ||
buf[2] != (uint8_t)STATE_FILE_MAGIC[2] || buf[3] != (uint8_t)STATE_FILE_MAGIC[3]) { buf[2] != (uint8_t)STATE_FILE_MAGIC[2] || buf[3] != (uint8_t)STATE_FILE_MAGIC[3]) {
@@ -168,10 +166,12 @@ static void tama_p1_load_state() {
*(state->tick_counter) = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); *(state->tick_counter) = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
storage_file_read(file, &buf, 4); storage_file_read(file, &buf, 4);
*(state->clk_timer_timestamp) = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); *(state->clk_timer_timestamp) = buf[0] | (buf[1] << 8) | (buf[2] << 16) |
(buf[3] << 24);
storage_file_read(file, &buf, 4); storage_file_read(file, &buf, 4);
*(state->prog_timer_timestamp) = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); *(state->prog_timer_timestamp) = buf[0] | (buf[1] << 8) | (buf[2] << 16) |
(buf[3] << 24);
storage_file_read(file, &buf, 1); storage_file_read(file, &buf, 1);
*(state->prog_timer_enabled) = buf[0] & 0x1; *(state->prog_timer_enabled) = buf[0] & 0x1;
@@ -220,9 +220,7 @@ static void tama_p1_load_state() {
furi_record_close(RECORD_STORAGE); furi_record_close(RECORD_STORAGE);
} }
static void tama_p1_save_state() { static void tama_p1_save_state() {
// Saving state // Saving state
FURI_LOG_D(TAG, "Saving Gamestate"); FURI_LOG_D(TAG, "Saving Gamestate");
uint8_t buf[4]; uint8_t buf[4];
@@ -333,7 +331,6 @@ static void tama_p1_save_state() {
FURI_LOG_D(TAG, "Finished Writing %lu", offset); FURI_LOG_D(TAG, "Finished Writing %lu", offset);
} }
static int32_t tama_p1_worker(void* context) { static int32_t tama_p1_worker(void* context) {
bool running = true; bool running = true;
FuriMutex* mutex = context; FuriMutex* mutex = context;
@@ -358,8 +355,6 @@ static int32_t tama_p1_worker(void* context) {
return 0; return 0;
} }
static void tama_p1_init(TamaApp* const ctx) { static void tama_p1_init(TamaApp* const ctx) {
g_ctx = ctx; g_ctx = ctx;
memset(ctx, 0, sizeof(TamaApp)); memset(ctx, 0, sizeof(TamaApp));

View File

@@ -435,8 +435,7 @@ bool bt_remote_rssi(Bt *bt, BtRssi *rssi) {
uint8_t rssi_val; uint8_t rssi_val;
uint32_t since = furi_hal_bt_get_conn_rssi(&rssi_val); uint32_t since = furi_hal_bt_get_conn_rssi(&rssi_val);
if (since == 0) if(since == 0) return false;
return false;
rssi->rssi = rssi_val; rssi->rssi = rssi_val;
rssi->since = since; rssi->since = since;

View File

@@ -28,7 +28,6 @@ typedef struct {
uint32_t since; uint32_t since;
} BtRssi; } BtRssi;
typedef void (*BtStatusChangedCallback)(BtStatus status, void* context); typedef void (*BtStatusChangedCallback)(BtStatus status, void* context);
/** Change BLE Profile /** Change BLE Profile
@@ -41,7 +40,6 @@ typedef void (*BtStatusChangedCallback)(BtStatus status, void* context);
*/ */
bool bt_set_profile(Bt* bt, BtProfile profile); bool bt_set_profile(Bt* bt, BtProfile profile);
void bt_set_profile_adv_name(Bt* bt, const char* fmt, ...); void bt_set_profile_adv_name(Bt* bt, const char* fmt, ...);
const char* bt_get_profile_adv_name(Bt* bt); const char* bt_get_profile_adv_name(Bt* bt);
@@ -50,7 +48,6 @@ const uint8_t *bt_get_profile_mac_address(Bt *bt);
bool bt_remote_rssi(Bt* bt, BtRssi* rssi); bool bt_remote_rssi(Bt* bt, BtRssi* rssi);
/** Disconnect from Central /** Disconnect from Central
* *
* @param bt Bt instance * @param bt Bt instance

View File

@@ -145,7 +145,8 @@ void animation_manager_check_blocking_process(AnimationManager* animation_manage
const StorageAnimationManifestInfo* manifest_info = const StorageAnimationManifestInfo* manifest_info =
animation_storage_get_meta(animation_manager->current_animation); animation_storage_get_meta(animation_manager->current_animation);
bool valid = animation_manager_is_valid_idle_animation(manifest_info, &stats, XTREME_SETTINGS()->unlock_anims); bool valid = animation_manager_is_valid_idle_animation(
manifest_info, &stats, XTREME_SETTINGS()->unlock_anims);
if(!valid) { if(!valid) {
animation_manager_start_new_idle(animation_manager); animation_manager_start_new_idle(animation_manager);
@@ -201,8 +202,10 @@ static void animation_manager_start_new_idle(AnimationManager* animation_manager
animation_storage_get_bubble_animation(animation_manager->current_animation); animation_storage_get_bubble_animation(animation_manager->current_animation);
animation_manager->state = AnimationManagerStateIdle; animation_manager->state = AnimationManagerStateIdle;
XtremeSettings* xtreme_settings = XTREME_SETTINGS(); XtremeSettings* xtreme_settings = XTREME_SETTINGS();
int32_t duration = (xtreme_settings->cycle_anims == 0) ? (bubble_animation->duration) : (xtreme_settings->cycle_anims); int32_t duration = (xtreme_settings->cycle_anims == 0) ? (bubble_animation->duration) :
furi_timer_start(animation_manager->idle_animation_timer, (duration > 0) ? (duration * 1000) : 0); (xtreme_settings->cycle_anims);
furi_timer_start(
animation_manager->idle_animation_timer, (duration > 0) ? (duration * 1000) : 0);
} }
static bool animation_manager_check_blocking(AnimationManager* animation_manager) { static bool animation_manager_check_blocking(AnimationManager* animation_manager) {
@@ -371,7 +374,8 @@ static StorageAnimation*
animation_manager_select_idle_animation(AnimationManager* animation_manager) { animation_manager_select_idle_animation(AnimationManager* animation_manager) {
const char* old_animation_name = NULL; const char* old_animation_name = NULL;
if(animation_manager->current_animation) { if(animation_manager->current_animation) {
old_animation_name = animation_storage_get_meta(animation_manager->current_animation)->name; old_animation_name =
animation_storage_get_meta(animation_manager->current_animation)->name;
} }
StorageAnimationList_t animation_list; StorageAnimationList_t animation_list;
@@ -512,7 +516,8 @@ void animation_manager_load_and_continue_animation(AnimationManager* animation_m
furi_record_close(RECORD_DOLPHIN); furi_record_close(RECORD_DOLPHIN);
const StorageAnimationManifestInfo* manifest_info = const StorageAnimationManifestInfo* manifest_info =
animation_storage_get_meta(restore_animation); animation_storage_get_meta(restore_animation);
bool valid = animation_manager_is_valid_idle_animation(manifest_info, &stats, XTREME_SETTINGS()->unlock_anims); bool valid = animation_manager_is_valid_idle_animation(
manifest_info, &stats, XTREME_SETTINGS()->unlock_anims);
if(valid) { if(valid) {
animation_manager_replace_current_animation( animation_manager_replace_current_animation(
animation_manager, restore_animation); animation_manager, restore_animation);
@@ -523,12 +528,16 @@ void animation_manager_load_and_continue_animation(AnimationManager* animation_m
animation_manager->idle_animation_timer, animation_manager->idle_animation_timer,
animation_manager->freezed_animation_time_left); animation_manager->freezed_animation_time_left);
} else { } else {
const BubbleAnimation* bubble_animation = animation_storage_get_bubble_animation( const BubbleAnimation* bubble_animation =
animation_storage_get_bubble_animation(
animation_manager->current_animation); animation_manager->current_animation);
XtremeSettings* xtreme_settings = XTREME_SETTINGS(); XtremeSettings* xtreme_settings = XTREME_SETTINGS();
int32_t duration = (xtreme_settings->cycle_anims == 0) ? (bubble_animation->duration) : (xtreme_settings->cycle_anims); int32_t duration = (xtreme_settings->cycle_anims == 0) ?
(bubble_animation->duration) :
(xtreme_settings->cycle_anims);
furi_timer_start( furi_timer_start(
animation_manager->idle_animation_timer, (duration > 0) ? (duration * 1000) : 0); animation_manager->idle_animation_timer,
(duration > 0) ? (duration * 1000) : 0);
} }
} }
} else { } else {

View File

@@ -58,7 +58,8 @@ void animation_handler_select_manifest() {
furi_string_printf(manifest, "%s/manifest.txt", furi_string_get_cstr(anim_dir)); furi_string_printf(manifest, "%s/manifest.txt", furi_string_get_cstr(anim_dir));
} }
strlcpy(ANIMATION_DIR, furi_string_get_cstr(anim_dir), sizeof(ANIMATION_DIR)); strlcpy(ANIMATION_DIR, furi_string_get_cstr(anim_dir), sizeof(ANIMATION_DIR));
strlcpy(ANIMATION_MANIFEST_FILE, furi_string_get_cstr(manifest), sizeof(ANIMATION_MANIFEST_FILE)); strlcpy(
ANIMATION_MANIFEST_FILE, furi_string_get_cstr(manifest), sizeof(ANIMATION_MANIFEST_FILE));
furi_string_free(manifest); furi_string_free(manifest);
furi_string_free(anim_dir); furi_string_free(anim_dir);
} }

View File

@@ -15,9 +15,10 @@
#define DOLPHIN_STATE_HEADER_MAGIC 0xD0 #define DOLPHIN_STATE_HEADER_MAGIC 0xD0
#define DOLPHIN_STATE_HEADER_VERSION 0x01 #define DOLPHIN_STATE_HEADER_VERSION 0x01
const int DOLPHIN_LEVELS[DOLPHIN_LEVEL_COUNT] = {100, 200, 300, 450, 600, 750, 950, 1150, 1350, 1600, const int DOLPHIN_LEVELS[DOLPHIN_LEVEL_COUNT] = {100, 200, 300, 450, 600, 750, 950, 1150,
1850, 2100, 2400, 2700, 3000, 3350, 3700, 4050, 4450, 4850, 1350, 1600, 1850, 2100, 2400, 2700, 3000, 3350,
5250, 5700, 6150, 6600, 7100, 7600, 8100, 8650, 9200}; 3700, 4050, 4450, 4850, 5250, 5700, 6150, 6600,
7100, 7600, 8100, 8650, 9200};
#define BUTTHURT_MAX 14 #define BUTTHURT_MAX 14
#define BUTTHURT_MIN 0 #define BUTTHURT_MIN 0

View File

@@ -145,8 +145,7 @@ void power_draw_battery_callback(Canvas* canvas, void* context) {
if(power->state == PowerStateCharging) { if(power->state == PowerStateCharging) {
canvas_set_bitmap_mode(canvas, 1); canvas_set_bitmap_mode(canvas, 1);
// TODO: replace -1 magic for uint8_t with re-framing // TODO: replace -1 magic for uint8_t with re-framing
if(battery_style == BatteryStylePercent || if(battery_style == BatteryStylePercent || battery_style == BatteryStyleBarPercent) {
battery_style == BatteryStyleBarPercent) {
canvas_set_color(canvas, ColorBlack); canvas_set_color(canvas, ColorBlack);
canvas_draw_box(canvas, 1, 1, 22, 6); canvas_draw_box(canvas, 1, 1, 22, 6);
canvas_draw_icon(canvas, 2, -1, &I_Charging_lightning_9x10); canvas_draw_icon(canvas, 2, -1, &I_Charging_lightning_9x10);

View File

@@ -298,7 +298,6 @@ const AboutDialogScreen about_screens[] = {
const int about_screens_count = sizeof(about_screens) / sizeof(AboutDialogScreen); const int about_screens_count = sizeof(about_screens) / sizeof(AboutDialogScreen);
int32_t about_settings_app(void* p) { int32_t about_settings_app(void* p) {
bool battery_info = false; bool battery_info = false;
if(p && strlen(p) && !strcmp(p, "batt")) { if(p && strlen(p) && !strcmp(p, "batt")) {
@@ -324,24 +323,19 @@ int32_t about_settings_app(void* p) {
DialogMessageButton screen_result; DialogMessageButton screen_result;
// draw empty screen to prevent menu flickering // draw empty screen to prevent menu flickering
view_dispatcher_add_view( view_dispatcher_add_view(view_dispatcher, battery_info_index, battery_view);
view_dispatcher, battery_info_index, battery_view);
view_dispatcher_add_view( view_dispatcher_add_view(
view_dispatcher, empty_screen_index, empty_screen_get_view(empty_screen)); view_dispatcher, empty_screen_index, empty_screen_get_view(empty_screen));
view_dispatcher_attach_to_gui(view_dispatcher, gui, ViewDispatcherTypeFullscreen); view_dispatcher_attach_to_gui(view_dispatcher, gui, ViewDispatcherTypeFullscreen);
screen_index = -1 + !battery_info; screen_index = -1 + !battery_info;
while(screen_index > -2) { while(screen_index > -2) {
if(screen_index == -1) { if(screen_index == -1) {
if(!battery_info) { if(!battery_info) {
break; break;
} }
with_view_model( with_view_model(
battery_view, battery_view, PowerInfo * model, { power_get_info(power, model); }, true);
PowerInfo * model,
{ power_get_info(power, model); },
true);
view_dispatcher_switch_to_view(view_dispatcher, battery_info_index); view_dispatcher_switch_to_view(view_dispatcher, battery_info_index);
furi_semaphore_acquire(semaphore, 2000); furi_semaphore_acquire(semaphore, 2000);
} else { } else {
@@ -360,7 +354,6 @@ int32_t about_settings_app(void* p) {
screen_index = -2; screen_index = -2;
} }
} }
} }
dialog_message_free(message); dialog_message_free(message);

View File

@@ -15,8 +15,12 @@ static void xtreme_settings_scene_start_base_graphics_changed(VariableItem* item
static void xtreme_settings_scene_start_asset_pack_changed(VariableItem* item) { static void xtreme_settings_scene_start_asset_pack_changed(VariableItem* item) {
XtremeSettingsApp* app = variable_item_get_context(item); XtremeSettingsApp* app = variable_item_get_context(item);
uint8_t index = variable_item_get_current_value_index(item); uint8_t index = variable_item_get_current_value_index(item);
variable_item_set_current_value_text(item, index == 0 ? "OFF" : *asset_packs_get(app->asset_packs, index - 1)); variable_item_set_current_value_text(
strlcpy(XTREME_SETTINGS()->asset_pack, index == 0 ? "" : *asset_packs_get(app->asset_packs, index - 1), MAX_PACK_NAME_LEN); item, index == 0 ? "OFF" : *asset_packs_get(app->asset_packs, index - 1));
strlcpy(
XTREME_SETTINGS()->asset_pack,
index == 0 ? "" : *asset_packs_get(app->asset_packs, index - 1),
MAX_PACK_NAME_LEN);
app->settings_changed = true; app->settings_changed = true;
app->assets_changed = true; app->assets_changed = true;
} }
@@ -33,8 +37,20 @@ static void xtreme_settings_scene_start_anim_speed_changed(VariableItem* item) {
app->settings_changed = true; app->settings_changed = true;
} }
const char* const cycle_anims_names[] = const char* const cycle_anims_names[] = {
{"OFF", "Meta.txt", "30 S", "1 M", "5 M", "10 M", "15 M", "30 M", "1 H", "2 H", "6 H", "12 H", "24 H"}; "OFF",
"Meta.txt",
"30 S",
"1 M",
"5 M",
"10 M",
"15 M",
"30 M",
"1 H",
"2 H",
"6 H",
"12 H",
"24 H"};
const int32_t cycle_anims_values[COUNT_OF(cycle_anims_names)] = const int32_t cycle_anims_values[COUNT_OF(cycle_anims_names)] =
{-1, 0, 30, 60, 300, 600, 900, 1800, 3600, 7200, 21600, 43200, 86400}; {-1, 0, 30, 60, 300, 600, 900, 1800, 3600, 7200, 21600, 43200, 86400};
static void xtreme_settings_scene_start_cycle_anims_changed(VariableItem* item) { static void xtreme_settings_scene_start_cycle_anims_changed(VariableItem* item) {
@@ -62,8 +78,7 @@ const int32_t battery_style_values[COUNT_OF(battery_style_names)] = {
BatteryStyleInvertedPercent, BatteryStyleInvertedPercent,
BatteryStyleRetro3, BatteryStyleRetro3,
BatteryStyleRetro5, BatteryStyleRetro5,
BatteryStyleBarPercent BatteryStyleBarPercent};
};
static void xtreme_settings_scene_start_battery_style_changed(VariableItem* item) { static void xtreme_settings_scene_start_battery_style_changed(VariableItem* item) {
XtremeSettingsApp* app = variable_item_get_context(item); XtremeSettingsApp* app = variable_item_get_context(item);
uint8_t index = variable_item_get_current_value_index(item); uint8_t index = variable_item_get_current_value_index(item);
@@ -112,7 +127,8 @@ void xtreme_settings_scene_start_on_enter(void* context) {
app->subghz_extend = false; app->subghz_extend = false;
app->subghz_bypass = false; app->subghz_bypass = false;
if(flipper_format_file_open_existing(subghz_range, "/ext/subghz/assets/extend_range.txt")) { if(flipper_format_file_open_existing(subghz_range, "/ext/subghz/assets/extend_range.txt")) {
flipper_format_read_bool(subghz_range, "use_ext_range_at_own_risk", &app->subghz_extend, 1); flipper_format_read_bool(
subghz_range, "use_ext_range_at_own_risk", &app->subghz_extend, 1);
flipper_format_read_bool(subghz_range, "ignore_default_tx_region", &app->subghz_bypass, 1); flipper_format_read_bool(subghz_range, "ignore_default_tx_region", &app->subghz_bypass, 1);
} }
flipper_format_free(subghz_range); flipper_format_free(subghz_range);
@@ -130,7 +146,8 @@ void xtreme_settings_scene_start_on_enter(void* context) {
char* copy = malloc(MAX_PACK_NAME_LEN); char* copy = malloc(MAX_PACK_NAME_LEN);
strlcpy(copy, name, MAX_PACK_NAME_LEN); strlcpy(copy, name, MAX_PACK_NAME_LEN);
asset_packs_push_back(app->asset_packs, copy); asset_packs_push_back(app->asset_packs, copy);
if (strcmp(name, xtreme_settings->asset_pack) == 0) current_pack = asset_packs_size(app->asset_packs); if(strcmp(name, xtreme_settings->asset_pack) == 0)
current_pack = asset_packs_size(app->asset_packs);
} }
} }
} while(false); } while(false);
@@ -139,11 +156,7 @@ void xtreme_settings_scene_start_on_enter(void* context) {
furi_record_close(RECORD_STORAGE); furi_record_close(RECORD_STORAGE);
item = variable_item_list_add( item = variable_item_list_add(
var_item_list, var_item_list, "Base Graphics", 2, xtreme_settings_scene_start_base_graphics_changed, app);
"Base Graphics",
2,
xtreme_settings_scene_start_base_graphics_changed,
app);
variable_item_set_current_value_index(item, xtreme_settings->nsfw_mode); variable_item_set_current_value_index(item, xtreme_settings->nsfw_mode);
variable_item_set_current_value_text(item, xtreme_settings->nsfw_mode ? "NSFW" : "SFW"); variable_item_set_current_value_text(item, xtreme_settings->nsfw_mode ? "NSFW" : "SFW");
@@ -154,7 +167,8 @@ void xtreme_settings_scene_start_on_enter(void* context) {
xtreme_settings_scene_start_asset_pack_changed, xtreme_settings_scene_start_asset_pack_changed,
app); app);
variable_item_set_current_value_index(item, current_pack); variable_item_set_current_value_index(item, current_pack);
variable_item_set_current_value_text(item, current_pack == 0 ? "OFF" : *asset_packs_get(app->asset_packs, current_pack - 1)); variable_item_set_current_value_text(
item, current_pack == 0 ? "OFF" : *asset_packs_get(app->asset_packs, current_pack - 1));
item = variable_item_list_add( item = variable_item_list_add(
var_item_list, var_item_list,
@@ -179,11 +193,7 @@ void xtreme_settings_scene_start_on_enter(void* context) {
variable_item_set_current_value_text(item, cycle_anims_names[value_index]); variable_item_set_current_value_text(item, cycle_anims_names[value_index]);
item = variable_item_list_add( item = variable_item_list_add(
var_item_list, var_item_list, "Unlock Anims", 2, xtreme_settings_scene_start_unlock_anims_changed, app);
"Unlock Anims",
2,
xtreme_settings_scene_start_unlock_anims_changed,
app);
variable_item_set_current_value_index(item, xtreme_settings->unlock_anims); variable_item_set_current_value_index(item, xtreme_settings->unlock_anims);
variable_item_set_current_value_text(item, xtreme_settings->unlock_anims ? "ON" : "OFF"); variable_item_set_current_value_text(item, xtreme_settings->unlock_anims ? "ON" : "OFF");
@@ -210,30 +220,18 @@ void xtreme_settings_scene_start_on_enter(void* context) {
variable_item_set_current_value_text(item, level_str); variable_item_set_current_value_text(item, level_str);
item = variable_item_list_add( item = variable_item_list_add(
var_item_list, var_item_list, "SubGHz Extend", 2, xtreme_settings_scene_start_subghz_extend_changed, app);
"SubGHz Extend",
2,
xtreme_settings_scene_start_subghz_extend_changed,
app);
variable_item_set_current_value_index(item, app->subghz_extend); variable_item_set_current_value_index(item, app->subghz_extend);
variable_item_set_current_value_text(item, app->subghz_extend ? "ON" : "OFF"); variable_item_set_current_value_text(item, app->subghz_extend ? "ON" : "OFF");
item = variable_item_list_add( item = variable_item_list_add(
var_item_list, var_item_list, "SubGHz Bypass", 2, xtreme_settings_scene_start_subghz_bypass_changed, app);
"SubGHz Bypass",
2,
xtreme_settings_scene_start_subghz_bypass_changed,
app);
variable_item_set_current_value_index(item, app->subghz_bypass); variable_item_set_current_value_index(item, app->subghz_bypass);
variable_item_set_current_value_text(item, app->subghz_bypass ? "ON" : "OFF"); variable_item_set_current_value_text(item, app->subghz_bypass ? "ON" : "OFF");
FuriString* version_tag = furi_string_alloc_printf("%s %s", version_get_gitbranchnum(NULL), version_get_builddate(NULL)); FuriString* version_tag = furi_string_alloc_printf(
item = variable_item_list_add( "%s %s", version_get_gitbranchnum(NULL), version_get_builddate(NULL));
var_item_list, item = variable_item_list_add(var_item_list, furi_string_get_cstr(version_tag), 0, NULL, app);
furi_string_get_cstr(version_tag),
0,
NULL,
app);
view_dispatcher_switch_to_view(app->view_dispatcher, XtremeSettingsAppViewVarItemList); view_dispatcher_switch_to_view(app->view_dispatcher, XtremeSettingsAppViewVarItemList);
} }

View File

@@ -45,7 +45,8 @@ void XTREME_ASSETS_LOAD() {
xtreme_assets->I_DolphinMafia_115x62 = &I_DolphinMafia_115x62_sfw; xtreme_assets->I_DolphinMafia_115x62 = &I_DolphinMafia_115x62_sfw;
xtreme_assets->I_DolphinNice_96x59 = &I_DolphinNice_96x59_sfw; xtreme_assets->I_DolphinNice_96x59 = &I_DolphinNice_96x59_sfw;
xtreme_assets->I_DolphinWait_61x59 = &I_DolphinWait_61x59_sfw; xtreme_assets->I_DolphinWait_61x59 = &I_DolphinWait_61x59_sfw;
xtreme_assets->I_iButtonDolphinVerySuccess_108x52 = &I_iButtonDolphinVerySuccess_108x52_sfw; xtreme_assets->I_iButtonDolphinVerySuccess_108x52 =
&I_iButtonDolphinVerySuccess_108x52_sfw;
xtreme_assets->I_DolphinReadingSuccess_59x63 = &I_DolphinReadingSuccess_59x63_sfw; xtreme_assets->I_DolphinReadingSuccess_59x63 = &I_DolphinReadingSuccess_59x63_sfw;
xtreme_assets->I_NFC_dolphin_emulation_47x61 = &I_NFC_dolphin_emulation_47x61_sfw; xtreme_assets->I_NFC_dolphin_emulation_47x61 = &I_NFC_dolphin_emulation_47x61_sfw;
xtreme_assets->I_passport_bad_46x49 = &I_passport_bad1_46x49_sfw; xtreme_assets->I_passport_bad_46x49 = &I_passport_bad1_46x49_sfw;
@@ -69,29 +70,92 @@ void XTREME_ASSETS_LOAD() {
const char* pack = xtreme_settings->asset_pack; const char* pack = xtreme_settings->asset_pack;
furi_string_printf(path, PACKS_DIR "/%s", pack); furi_string_printf(path, PACKS_DIR "/%s", pack);
Storage* storage = furi_record_open(RECORD_STORAGE); Storage* storage = furi_record_open(RECORD_STORAGE);
if (storage_common_stat(storage, furi_string_get_cstr(path), &info) == FSE_OK && info.flags & FSF_DIRECTORY) { if(storage_common_stat(storage, furi_string_get_cstr(path), &info) == FSE_OK &&
info.flags & FSF_DIRECTORY) {
File* file = storage_file_alloc(storage); File* file = storage_file_alloc(storage);
swap_bmx_icon(&xtreme_assets->I_BLE_Pairing_128x64, pack, "BLE/BLE_Pairing_128x64.bmx", path, file); swap_bmx_icon(
swap_bmx_icon(&xtreme_assets->I_DolphinCommon_56x48, pack, "Dolphin/DolphinCommon_56x48.bmx", path, file); &xtreme_assets->I_BLE_Pairing_128x64, pack, "BLE/BLE_Pairing_128x64.bmx", path, file);
swap_bmx_icon(&xtreme_assets->I_DolphinMafia_115x62, pack, "iButton/DolphinMafia_115x62.bmx", path, file); swap_bmx_icon(
swap_bmx_icon(&xtreme_assets->I_DolphinNice_96x59, pack, "iButton/DolphinNice_96x59.bmx", path, file); &xtreme_assets->I_DolphinCommon_56x48,
swap_bmx_icon(&xtreme_assets->I_DolphinWait_61x59, pack, "iButton/DolphinWait_61x59.bmx", path, file); pack,
swap_bmx_icon(&xtreme_assets->I_iButtonDolphinVerySuccess_108x52, pack, "iButton/iButtonDolphinVerySuccess_108x52.bmx", path, file); "Dolphin/DolphinCommon_56x48.bmx",
swap_bmx_icon(&xtreme_assets->I_DolphinReadingSuccess_59x63, pack, "Infrared/DolphinReadingSuccess_59x63.bmx", path, file); path,
swap_bmx_icon(&xtreme_assets->I_NFC_dolphin_emulation_47x61, pack, "NFC/NFC_dolphin_emulation_47x61.bmx", path, file); file);
swap_bmx_icon(&xtreme_assets->I_passport_bad_46x49, pack, "Passport/passport_bad_46x49.bmx", path, file); swap_bmx_icon(
&xtreme_assets->I_DolphinMafia_115x62,
pack,
"iButton/DolphinMafia_115x62.bmx",
path,
file);
swap_bmx_icon(
&xtreme_assets->I_DolphinNice_96x59, pack, "iButton/DolphinNice_96x59.bmx", path, file);
swap_bmx_icon(
&xtreme_assets->I_DolphinWait_61x59, pack, "iButton/DolphinWait_61x59.bmx", path, file);
swap_bmx_icon(
&xtreme_assets->I_iButtonDolphinVerySuccess_108x52,
pack,
"iButton/iButtonDolphinVerySuccess_108x52.bmx",
path,
file);
swap_bmx_icon(
&xtreme_assets->I_DolphinReadingSuccess_59x63,
pack,
"Infrared/DolphinReadingSuccess_59x63.bmx",
path,
file);
swap_bmx_icon(
&xtreme_assets->I_NFC_dolphin_emulation_47x61,
pack,
"NFC/NFC_dolphin_emulation_47x61.bmx",
path,
file);
swap_bmx_icon(
&xtreme_assets->I_passport_bad_46x49,
pack,
"Passport/passport_bad_46x49.bmx",
path,
file);
swap_bmx_icon(&xtreme_assets->I_passport_DB, pack, "Passport/passport_DB.bmx", path, file); swap_bmx_icon(&xtreme_assets->I_passport_DB, pack, "Passport/passport_DB.bmx", path, file);
swap_bmx_icon(&xtreme_assets->I_passport_happy_46x49, pack, "Passport/passport_happy_46x49.bmx", path, file); swap_bmx_icon(
swap_bmx_icon(&xtreme_assets->I_passport_okay_46x49, pack, "Passport/passport_okay_46x49.bmx", path, file); &xtreme_assets->I_passport_happy_46x49,
swap_bmx_icon(&xtreme_assets->I_RFIDDolphinReceive_97x61, pack, "RFID/RFIDDolphinReceive_97x61.bmx", path, file); pack,
swap_bmx_icon(&xtreme_assets->I_RFIDDolphinSend_97x61, pack, "RFID/RFIDDolphinSend_97x61.bmx", path, file); "Passport/passport_happy_46x49.bmx",
swap_bmx_icon(&xtreme_assets->I_RFIDDolphinSuccess_108x57, pack, "RFID/RFIDDolphinSuccess_108x57.bmx", path, file); path,
swap_bmx_icon(&xtreme_assets->I_Cry_dolph_55x52, pack, "Settings/Cry_dolph_55x52.bmx", path, file); file);
swap_bmx_icon(&xtreme_assets->I_Scanning_123x52, pack, "SubGhz/Scanning_123x52.bmx", path, file); swap_bmx_icon(
&xtreme_assets->I_passport_okay_46x49,
pack,
"Passport/passport_okay_46x49.bmx",
path,
file);
swap_bmx_icon(
&xtreme_assets->I_RFIDDolphinReceive_97x61,
pack,
"RFID/RFIDDolphinReceive_97x61.bmx",
path,
file);
swap_bmx_icon(
&xtreme_assets->I_RFIDDolphinSend_97x61,
pack,
"RFID/RFIDDolphinSend_97x61.bmx",
path,
file);
swap_bmx_icon(
&xtreme_assets->I_RFIDDolphinSuccess_108x57,
pack,
"RFID/RFIDDolphinSuccess_108x57.bmx",
path,
file);
swap_bmx_icon(
&xtreme_assets->I_Cry_dolph_55x52, pack, "Settings/Cry_dolph_55x52.bmx", path, file);
swap_bmx_icon(
&xtreme_assets->I_Scanning_123x52, pack, "SubGhz/Scanning_123x52.bmx", path, file);
swap_bmx_icon(&xtreme_assets->I_Auth_62x31, pack, "U2F/Auth_62x31.bmx", path, file); swap_bmx_icon(&xtreme_assets->I_Auth_62x31, pack, "U2F/Auth_62x31.bmx", path, file);
swap_bmx_icon(&xtreme_assets->I_Connect_me_62x31, pack, "U2F/Connect_me_62x31.bmx", path, file); swap_bmx_icon(
swap_bmx_icon(&xtreme_assets->I_Connected_62x31, pack, "U2F/Connected_62x31.bmx", path, file); &xtreme_assets->I_Connect_me_62x31, pack, "U2F/Connect_me_62x31.bmx", path, file);
swap_bmx_icon(
&xtreme_assets->I_Connected_62x31, pack, "U2F/Connected_62x31.bmx", path, file);
swap_bmx_icon(&xtreme_assets->I_Error_62x31, pack, "U2F/Error_62x31.bmx", path, file); swap_bmx_icon(&xtreme_assets->I_Error_62x31, pack, "U2F/Error_62x31.bmx", path, file);
storage_file_free(file); storage_file_free(file);
@@ -100,7 +164,12 @@ void XTREME_ASSETS_LOAD() {
furi_string_free(path); furi_string_free(path);
} }
void swap_bmx_icon(const Icon** replace, const char* pack, const char* name, FuriString* path, File* file) { void swap_bmx_icon(
const Icon** replace,
const char* pack,
const char* name,
FuriString* path,
File* file) {
furi_string_printf(path, PACKS_DIR "/%s/Icons/%s", pack, name); furi_string_printf(path, PACKS_DIR "/%s/Icons/%s", pack, name);
if(storage_file_open(file, furi_string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) { if(storage_file_open(file, furi_string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) {
uint64_t size = storage_file_size(file) - 8; uint64_t size = storage_file_size(file) - 8;

View File

@@ -34,6 +34,11 @@ XtremeAssets* XTREME_ASSETS();
void XTREME_ASSETS_LOAD(); void XTREME_ASSETS_LOAD();
void swap_bmx_icon(const Icon** replace, const char* base, const char* name, FuriString* path, File* file); void swap_bmx_icon(
const Icon** replace,
const char* base,
const char* name,
FuriString* path,
File* file);
void free_bmx_icon(Icon* icon); void free_bmx_icon(Icon* icon);

View File

@@ -13,7 +13,11 @@ bool XTREME_SETTINGS_LOAD() {
if(xtreme_settings == NULL) { if(xtreme_settings == NULL) {
xtreme_settings = malloc(sizeof(XtremeSettings)); xtreme_settings = malloc(sizeof(XtremeSettings));
bool loaded = saved_struct_load( bool loaded = saved_struct_load(
XTREME_SETTINGS_PATH, xtreme_settings, sizeof(XtremeSettings), XTREME_SETTINGS_MAGIC, XTREME_SETTINGS_VERSION); XTREME_SETTINGS_PATH,
xtreme_settings,
sizeof(XtremeSettings),
XTREME_SETTINGS_MAGIC,
XTREME_SETTINGS_VERSION);
if(!loaded) { if(!loaded) {
memset(xtreme_settings, 0, sizeof(XtremeSettings)); memset(xtreme_settings, 0, sizeof(XtremeSettings));
loaded = XTREME_SETTINGS_SAVE(); loaded = XTREME_SETTINGS_SAVE();
@@ -28,5 +32,9 @@ bool XTREME_SETTINGS_SAVE() {
XTREME_SETTINGS_LOAD(); XTREME_SETTINGS_LOAD();
} }
return saved_struct_save( return saved_struct_save(
XTREME_SETTINGS_PATH, xtreme_settings, sizeof(XtremeSettings), XTREME_SETTINGS_MAGIC, XTREME_SETTINGS_VERSION); XTREME_SETTINGS_PATH,
xtreme_settings,
sizeof(XtremeSettings),
XTREME_SETTINGS_MAGIC,
XTREME_SETTINGS_VERSION);
} }

View File

@@ -31,8 +31,10 @@ static bool xtreme_settings_back_event_callback(void* context) {
Storage* storage = furi_record_open(RECORD_STORAGE); Storage* storage = furi_record_open(RECORD_STORAGE);
FlipperFormat* subghz_range = flipper_format_file_alloc(storage); FlipperFormat* subghz_range = flipper_format_file_alloc(storage);
if(flipper_format_file_open_existing(subghz_range, "/ext/subghz/assets/extend_range.txt")) { if(flipper_format_file_open_existing(subghz_range, "/ext/subghz/assets/extend_range.txt")) {
flipper_format_insert_or_update_bool(subghz_range, "use_ext_range_at_own_risk", &app->subghz_extend, 1); flipper_format_insert_or_update_bool(
flipper_format_insert_or_update_bool(subghz_range, "ignore_default_tx_region", &app->subghz_bypass, 1); subghz_range, "use_ext_range_at_own_risk", &app->subghz_extend, 1);
flipper_format_insert_or_update_bool(
subghz_range, "ignore_default_tx_region", &app->subghz_bypass, 1);
} }
flipper_format_free(subghz_range); flipper_format_free(subghz_range);
furi_record_close(RECORD_STORAGE); furi_record_close(RECORD_STORAGE);
@@ -81,9 +83,7 @@ XtremeSettingsApp* xtreme_settings_app_alloc() {
app->popup = popup_alloc(); app->popup = popup_alloc();
view_dispatcher_add_view( view_dispatcher_add_view(
app->view_dispatcher, app->view_dispatcher, XtremeSettingsAppViewPopup, popup_get_view(app->popup));
XtremeSettingsAppViewPopup,
popup_get_view(app->popup));
// Set first scene // Set first scene
scene_manager_next_scene(app->scene_manager, XtremeSettingsAppSceneStart); scene_manager_next_scene(app->scene_manager, XtremeSettingsAppSceneStart);

View File

@@ -166,7 +166,6 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification(void* pckt) {
gap->connection_params.slave_latency = event->Conn_Latency; gap->connection_params.slave_latency = event->Conn_Latency;
gap->connection_params.supervisor_timeout = event->Supervision_Timeout; gap->connection_params.supervisor_timeout = event->Supervision_Timeout;
// Stop advertising as connection completed // Stop advertising as connection completed
furi_timer_stop(gap->advertise_timer); furi_timer_stop(gap->advertise_timer);
@@ -504,9 +503,15 @@ bool gap_init(GapConfig* config, GapEventCallback on_event_cb, void* context) {
// Initialization of GATT & GAP layer // Initialization of GATT & GAP layer
gap->service.adv_name = config->adv_name; gap->service.adv_name = config->adv_name;
FURI_LOG_I(TAG, "Advertising name: %s", &(gap->service.adv_name[1])); FURI_LOG_I(TAG, "Advertising name: %s", &(gap->service.adv_name[1]));
FURI_LOG_I(TAG, "MAC @ : %02X:%02X:%02X:%02X:%02X:%02X", FURI_LOG_I(
config->mac_address[0], config->mac_address[1], config->mac_address[2], TAG,
config->mac_address[3], config->mac_address[4], config->mac_address[5]); "MAC @ : %02X:%02X:%02X:%02X:%02X:%02X",
config->mac_address[0],
config->mac_address[1],
config->mac_address[2],
config->mac_address[3],
config->mac_address[4],
config->mac_address[5]);
gap_init_svc(gap); gap_init_svc(gap);
// Initialization of the BLE Services // Initialization of the BLE Services
SVCCTL_Init(); SVCCTL_Init();
@@ -543,10 +548,7 @@ uint32_t gap_get_remote_conn_rssi(int8_t *rssi) {
fetch_rssi(); fetch_rssi();
*rssi = gap->conn_rssi; *rssi = gap->conn_rssi;
FURI_LOG_D(TAG, "RSSI: %d", *rssi); if(gap->time_rssi_sample) return furi_get_tick() - gap->time_rssi_sample;
if (gap->time_rssi_sample)
return furi_get_tick() - gap->time_rssi_sample;
} }
return 0; return 0;
} }

View File

@@ -430,12 +430,10 @@ float furi_hal_bt_get_rssi() {
* *
*/ */
uint32_t furi_hal_bt_get_conn_rssi(uint8_t* rssi) { uint32_t furi_hal_bt_get_conn_rssi(uint8_t* rssi) {
int8_t ret_rssi = 0; int8_t ret_rssi = 0;
uint32_t since = gap_get_remote_conn_rssi(&ret_rssi); uint32_t since = gap_get_remote_conn_rssi(&ret_rssi);
if (ret_rssi == 127 || since == 0) if(ret_rssi == 127 || since == 0) return 0;
return 0;
*rssi = (uint8_t)abs(ret_rssi); *rssi = (uint8_t)abs(ret_rssi);
@@ -474,7 +472,9 @@ void furi_hal_bt_set_profile_adv_name(
furi_assert(name); furi_assert(name);
memcpy( memcpy(
&(profile_config[profile].config.adv_name[1]), name, FURI_HAL_VERSION_DEVICE_NAME_LENGTH-1); &(profile_config[profile].config.adv_name[1]),
name,
FURI_HAL_VERSION_DEVICE_NAME_LENGTH - 1);
} }
const char* furi_hal_bt_get_profile_adv_name(FuriHalBtProfile profile) { const char* furi_hal_bt_get_profile_adv_name(FuriHalBtProfile profile) {

View File

@@ -199,8 +199,7 @@ bool furi_hal_bt_hid_kb_press(uint16_t button) {
bool furi_hal_bt_hid_kb_free_slots(uint8_t n_empty_slots) { bool furi_hal_bt_hid_kb_free_slots(uint8_t n_empty_slots) {
furi_assert(kb_report); furi_assert(kb_report);
for(uint8_t i = 0; n_empty_slots > 0 && i < FURI_HAL_BT_HID_KB_MAX_KEYS; i++) { for(uint8_t i = 0; n_empty_slots > 0 && i < FURI_HAL_BT_HID_KB_MAX_KEYS; i++) {
if(kb_report->key[i] == 0) if(kb_report->key[i] == 0) n_empty_slots--;
n_empty_slots--;
} }
return (n_empty_slots == 0); return (n_empty_slots == 0);
} }

View File

@@ -228,7 +228,9 @@ bool furi_hal_bt_ensure_c2_mode(BleGlueC2Mode mode);
* @param[in] profile profile type * @param[in] profile profile type
* @param[in] name new adv name * @param[in] name new adv name
*/ */
void furi_hal_bt_set_profile_adv_name(FuriHalBtProfile profile, const char name[FURI_HAL_VERSION_DEVICE_NAME_LENGTH-1]); void furi_hal_bt_set_profile_adv_name(
FuriHalBtProfile profile,
const char name[FURI_HAL_VERSION_DEVICE_NAME_LENGTH - 1]);
const char* furi_hal_bt_get_profile_adv_name(FuriHalBtProfile profile); const char* furi_hal_bt_get_profile_adv_name(FuriHalBtProfile profile);
@@ -236,7 +238,9 @@ const char *furi_hal_bt_get_profile_adv_name(FuriHalBtProfile profile);
* @param[in] profile profile type * @param[in] profile profile type
* @param[in] mac new mac address * @param[in] mac new mac address
*/ */
void furi_hal_bt_set_profile_mac_addr(FuriHalBtProfile profile, const uint8_t mac_addr[GAP_MAC_ADDR_SIZE]); void furi_hal_bt_set_profile_mac_addr(
FuriHalBtProfile profile,
const uint8_t mac_addr[GAP_MAC_ADDR_SIZE]);
const uint8_t* furi_hal_bt_get_profile_mac_addr(FuriHalBtProfile profile); const uint8_t* furi_hal_bt_get_profile_mac_addr(FuriHalBtProfile profile);

File diff suppressed because it is too large Load Diff