diff --git a/applications/applications.c b/applications/applications.c index 9e19ea5d8..a4e81a88d 100644 --- a/applications/applications.c +++ b/applications/applications.c @@ -21,6 +21,7 @@ extern int32_t accessor_app(void* p); extern int32_t archive_app(void* p); extern int32_t bad_usb_app(void* p); extern int32_t u2f_app(void* p); +extern int32_t wav_player_app(void* p); extern int32_t uart_echo_app(void* p); extern int32_t blink_test_app(void* p); extern int32_t bt_debug_app(void* p); @@ -38,6 +39,8 @@ extern int32_t passport_app(void* p); extern int32_t scened_app(void* p); extern int32_t storage_test_app(void* p); extern int32_t subghz_app(void* p); +extern int32_t jukebox_app(void *p); +extern int32_t universal_rf_remote_app(void *p); extern int32_t usb_mouse_app(void* p); extern int32_t usb_test_app(void* p); extern int32_t vibro_test_app(void* p); @@ -49,7 +52,11 @@ extern int32_t text_box_test_app(void* p); extern int32_t music_player_app(void* p); extern int32_t snake_game_app(void* p); extern int32_t tetris_game_app(void *p); +extern int32_t clock_app(void *p); +// extern int32_t floopper_bloopper(void* p); +// extern int32_t raycast_game_app(void* p); extern int32_t spectrum_analyzer_app(void* p); +extern int32_t flappy_game_app(void* p); // On system start hooks declaration extern void bt_on_system_start(); @@ -207,6 +214,14 @@ const size_t FLIPPER_SYSTEM_APPS_COUNT = COUNT_OF(FLIPPER_SYSTEM_APPS); // Main menu APP const FlipperApplication FLIPPER_APPS[] = { +#ifdef APP_CLOCK + {.app = clock_app, + .name = "Clock", + .stack_size = 2048, + .icon = &A_Clock_14, + .flags = FlipperApplicationFlagDefault}, +#endif + #ifdef APP_SUBGHZ {.app = subghz_app, .name = "Sub-GHz", @@ -270,7 +285,6 @@ const FlipperApplication FLIPPER_APPS[] = { .icon = &A_U2F_14, .flags = FlipperApplicationFlagDefault}, #endif - }; const size_t FLIPPER_APPS_COUNT = COUNT_OF(FLIPPER_APPS); @@ -336,11 +350,27 @@ const FlipperApplication FLIPPER_PLUGINS[] = { .flags = FlipperApplicationFlagDefault}, #endif +#ifdef APP_FLAPPY_GAME + {.app = flappy_game_app, + .name = "Flipper Flappy Bird", + .stack_size = 1024, + .icon = &A_Plugins_14 + }, +#endif + +#ifdef APP_JUKEBOX + {.app = jukebox_app, + .name = "Jukebox", + .stack_size = 2048, + .icon = &A_UniversalRemote_14, + .flags = FlipperApplicationFlagDefault}, +#endif + #ifdef APP_MUSIC_PLAYER {.app = music_player_app, .name = "Music Player", .stack_size = 2048, - .icon = &A_Plugins_14, + .icon = &A_MusicPlayer_14, .flags = FlipperApplicationFlagDefault}, #endif @@ -352,20 +382,44 @@ const FlipperApplication FLIPPER_PLUGINS[] = { .flags = FlipperApplicationFlagDefault}, #endif -#ifdef APP_TETRIS_GAME - {.app = tetris_game_app, - .name = "Tetris Game", - .stack_size = 1024, - .icon = NULL}, +#ifdef APP_SPECTRUM_ANALYZER + {.app = spectrum_analyzer_app, + .name = "Spectrum Analyzer", + .stack_size = 1024, + .icon = &A_Plugins_14, + .flags = FlipperApplicationFlagDefault}, #endif -#ifdef APP_SPECTRUM_ANALYZER - {.app = spectrum_analyzer_app, - .name = "Spectrum Analyzer", - .stack_size = 1024, - .icon = &A_Plugins_14, +#ifdef APP_TETRIS_GAME + {.app = tetris_game_app, .name = "Tetris Game", .stack_size = 1024, .icon = NULL}, +#endif + +#ifdef APP_UNIVERSALRF + {.app = universal_rf_remote_app, + .name = "Universal SubGHz", + .stack_size = 2048, + .icon = &A_UniversalRemote_14, .flags = FlipperApplicationFlagDefault}, #endif + + {.app = wav_player_app, + .name = "Wav Player", + .stack_size = 4096, + .icon = &A_MusicPlayer_14, + .flags = FlipperApplicationFlagDefault}, + +// #ifdef APP_RAYCAST_GAME +// {.app = raycast_game_app, .name = "Raycast Game", .stack_size = 4096, .icon = NULL}, +// #endif + +// #ifdef FLOOPPER_BLOOPPER +// {.app = floopper_bloopper, +// .name = "Floopper Bloopper", +// .stack_size = 1024, +// .icon = &A_Plugins_14, +// .flags = FlipperApplicationFlagDefault}, +// #endif + }; const size_t FLIPPER_PLUGINS_COUNT = COUNT_OF(FLIPPER_PLUGINS); diff --git a/applications/applications.mk b/applications/applications.mk index 4ae0a87ad..1e5a22cbb 100644 --- a/applications/applications.mk +++ b/applications/applications.mk @@ -40,6 +40,8 @@ APP_INFRARED = 1 APP_LF_RFID = 1 APP_NFC = 1 APP_SUBGHZ = 1 +APP_UNIVERSALRF = 1 +APP_JUKEBOX = 1 APP_ABOUT = 1 APP_PASSPORT = 1 APP_UPDATER = 1 @@ -48,7 +50,11 @@ APP_UPDATER = 1 APP_MUSIC_PLAYER = 1 APP_SNAKE_GAME = 1 APP_TETRIS_GAME = 1 +# APP_RAYCAST_GAME = 1 +APP_CLOCK = 1 APP_SPECTRUM_ANALYZER = 1 +APP_FLAPPY_GAME = 1 + # Debug APP_ACCESSOR = 1 @@ -106,6 +112,19 @@ SRV_GUI = 1 SRV_CLI = 1 endif +APP_UNIVERSALRF ?= 0 +ifeq ($(APP_UNIVERSALRF), 1) +CFLAGS += -DAPP_UNIVERSALRF +SRV_GUI = 1 +SRV_CLI = 1 +endif + +APP_JUKEBOX ?= 0 +ifeq ($(APP_JUKEBOX), 1) +CFLAGS += -DAPP_JUKEBOX +SRV_GUI = 1 +SRV_CLI = 1 +endif APP_ABOUT ?= 0 ifeq ($(APP_ABOUT), 1) @@ -230,21 +249,40 @@ CFLAGS += -DAPP_MUSIC_PLAYER SRV_GUI = 1 endif +APP_FLAPPY_GAME ?= 0 +ifeq ($(APP_FLAPPY_GAME), 1) +CFLAGS += -DAPP_FLAPPY_GAME +SRV_GUI = 1 +endif + APP_SNAKE_GAME ?= 0 ifeq ($(APP_SNAKE_GAME), 1) CFLAGS += -DAPP_SNAKE_GAME SRV_GUI = 1 endif +APP_SPECTRUM_ANALYZER ?= 0 +ifeq ($(APP_SPECTRUM_ANALYZER), 1) +CFLAGS += -DAPP_SPECTRUM_ANALYZER +SRV_GUI = 1 +endif + APP_TETRIS_GAME ?= 0 ifeq ($(APP_TETRIS_GAME), 1) CFLAGS += -DAPP_TETRIS_GAME SRV_GUI = 1 endif -APP_SPECTRUM_ANALYZER ?= 0 -ifeq ($(APP_SPECTRUM_ANALYZER), 1) -CFLAGS += -DAPP_SPECTRUM_ANALYZER +# APP_RAYCAST_GAME ?= 0 +# ifeq ($(APP_RAYCAST_GAME), 1) +# CFLAGS += -DAPP_RAYCAST_GAME +# SRV_GUI = 1 +# endif + + +APP_CLOCK ?= 0 +ifeq ($(APP_CLOCK), 1) +CFLAGS += -DAPP_CLOCK SRV_GUI = 1 endif diff --git a/applications/clock_app/clock_app.c b/applications/clock_app/clock_app.c new file mode 100644 index 000000000..de4f3d0c0 --- /dev/null +++ b/applications/clock_app/clock_app.c @@ -0,0 +1,278 @@ +#include +#include +#include +#include +#include +#include +#include + +#define TAG "Clock" + +bool timerStarted=false; +int timerSecs=0; +int songSelect=0; + +typedef enum { + EventTypeTick, + EventTypeKey, +} EventType; + +typedef struct { + EventType type; + InputEvent input; +} PluginEvent; + +typedef struct { + FuriHalRtcDateTime datetime; +} ClockState; + +static void clock_input_callback(InputEvent* input_event, osMessageQueueId_t event_queue) { + furi_assert(event_queue); + PluginEvent event = {.type = EventTypeKey, .input = *input_event}; + osMessageQueuePut(event_queue, &event, 0, osWaitForever); +} + +static void clock_render_callback(Canvas* const canvas, void* ctx) { + canvas_clear(canvas); + canvas_set_color(canvas, ColorBlack); + ClockState* state = (ClockState*)acquire_mutex((ValueMutex*)ctx, 25); + char strings[3][20]; + int curMin = (timerSecs/60); + int curSec = timerSecs-(curMin *60); + sprintf(strings[0], "%.4d-%.2d-%.2d", state->datetime.year, state->datetime.month, state->datetime.day); + sprintf(strings[1], "%.2d:%.2d:%.2d", state->datetime.hour, state->datetime.minute, state->datetime.second); + sprintf(strings[2], "%.2d:%.2d", curMin , curSec); + release_mutex((ValueMutex*)ctx, state); + canvas_set_font(canvas, FontBigNumbers); + canvas_draw_str_aligned(canvas, 64, 8, AlignCenter, AlignCenter, strings[1]); + canvas_set_font(canvas, FontSecondary); + canvas_draw_str_aligned(canvas, 64, 20, AlignCenter, AlignTop, strings[0]); + // elements_button_left(canvas, "Alarms"); + // elements_button_right(canvas, "Settings"); + // elements_button_center(canvas, "Reset"); + canvas_set_font(canvas, FontBigNumbers); + canvas_draw_str_aligned(canvas, 64, 32, AlignCenter, AlignTop, strings[2]); + canvas_set_font(canvas, FontSecondary); + if(timerStarted) { + elements_button_center(canvas, "Stop"); + } else { + elements_button_center(canvas, "Start"); + } + if(songSelect==0) { + elements_button_right(canvas, "S:OFF"); + } else if(songSelect==1) { + elements_button_right(canvas, "S:PoRa"); + } else if(songSelect==2) { + elements_button_right(canvas, "S:Mario"); + } +} + +static void clock_state_init(ClockState* const state) { + furi_hal_rtc_get_datetime(&state->datetime); +} + +const NotificationSequence clock_alert_silent = { + &message_force_vibro_setting_on, &message_vibro_on, &message_red_255, &message_green_255, &message_blue_255, &message_display_backlight_on, + &message_vibro_off, &message_display_backlight_off, &message_delay_50, &message_display_backlight_on, NULL, +}; +const NotificationSequence clock_alert_pr1 = { + &message_force_speaker_volume_setting_1f, + &message_force_vibro_setting_on, &message_vibro_on, &message_red_255, &message_green_255, &message_blue_255, &message_display_backlight_on, + &message_note_g5, &message_delay_100, &message_delay_100, &message_delay_50, &message_sound_off, + &message_vibro_off, &message_display_backlight_off, &message_delay_50, &message_display_backlight_on, + &message_note_g5, &message_delay_100, &message_delay_100, &message_delay_50, &message_sound_off, NULL, +}; +const NotificationSequence clock_alert_pr2 = { + &message_force_speaker_volume_setting_1f, + &message_force_vibro_setting_on, &message_vibro_on, + &message_note_fs5, &message_delay_100, &message_delay_100, &message_sound_off, + &message_display_backlight_off, &message_vibro_off, &message_delay_50, + &message_note_g5, &message_delay_100, &message_delay_100, &message_sound_off, + &message_display_backlight_on, &message_delay_50, + &message_note_a5, &message_delay_100, &message_delay_100, &message_sound_off, NULL, +}; +const NotificationSequence clock_alert_pr3 = { + &message_force_speaker_volume_setting_1f, + &message_display_backlight_off, + &message_note_g5, &message_delay_100, &message_delay_100, &message_sound_off, + &message_delay_50, &message_red_255, &message_green_255, &message_blue_255, &message_display_backlight_on, &message_delay_100, NULL, +}; +const NotificationSequence clock_alert_mario1 = { + &message_force_speaker_volume_setting_1f, + &message_force_vibro_setting_on, &message_vibro_on, &message_red_255, &message_green_255, &message_blue_255, &message_display_backlight_on, + &message_note_e5, &message_delay_100, &message_delay_100, &message_delay_50, &message_sound_off, + &message_note_e5, &message_delay_100, &message_delay_100, &message_delay_50, &message_sound_off, + &message_vibro_off, &message_display_backlight_off, &message_delay_100, &message_display_backlight_on, &message_delay_100, + &message_note_e5, &message_delay_100, &message_delay_100, &message_delay_50, &message_sound_off, NULL, +}; +const NotificationSequence clock_alert_mario2 = { + &message_force_speaker_volume_setting_1f, + &message_force_vibro_setting_on, &message_vibro_on, &message_display_backlight_off, &message_delay_100, &message_display_backlight_on, &message_delay_100, + &message_note_c5, &message_delay_100, &message_delay_100, &message_sound_off, + &message_display_backlight_off, &message_vibro_off, &message_delay_50, + &message_note_e5, &message_delay_100, &message_delay_100, &message_sound_off, + &message_display_backlight_on, NULL, +}; +const NotificationSequence clock_alert_mario3 = { + &message_force_speaker_volume_setting_1f, + &message_display_backlight_off, + &message_note_g5, &message_delay_100, &message_delay_100, &message_delay_100, &message_delay_100, &message_sound_off, + &message_delay_50, &message_red_255, &message_green_255, &message_blue_255, &message_display_backlight_on, &message_delay_100, + &message_note_g4, &message_delay_100, &message_delay_100, &message_delay_100, &message_delay_100, &message_sound_off, + NULL, +}; +const NotificationSequence clock_alert_perMin = { + &message_force_speaker_volume_setting_1f, + &message_note_g5, &message_delay_100, &message_delay_50, &message_sound_off, + &message_delay_10, + &message_note_g4, &message_delay_50, &message_delay_10, &message_delay_10, &message_sound_off, + NULL, +}; +const NotificationSequence clock_alert_startStop = { + &message_force_speaker_volume_setting_1f, + &message_note_d6, &message_delay_100, &message_delay_10, &message_delay_10, &message_sound_off, NULL, +}; + +// Runs every 1000ms by default +static void clock_tick(void* ctx) { + furi_assert(ctx); + osMessageQueueId_t event_queue = ctx; + PluginEvent event = {.type = EventTypeTick}; + if(timerStarted) { + timerSecs=timerSecs+1; + if(timerSecs%60==0) { + NotificationApp* notification = furi_record_open("notification"); + notification_message(notification, &clock_alert_perMin); + furi_record_close("notification"); + } + if(songSelect==1 ) { + if(timerSecs==80) { + NotificationApp* notification = furi_record_open("notification"); + notification_message(notification, &clock_alert_pr1); + furi_record_close("notification"); + } + if(timerSecs==81) { + NotificationApp* notification = furi_record_open("notification"); + notification_message(notification, &clock_alert_pr2); + furi_record_close("notification"); + } + if(timerSecs==82) { + NotificationApp* notification = furi_record_open("notification"); + notification_message(notification, &clock_alert_pr3); + furi_record_close("notification"); + } + } else if(songSelect==2 ) { + if(timerSecs==80) { + NotificationApp* notification = furi_record_open("notification"); + notification_message(notification, &clock_alert_mario1); + furi_record_close("notification"); + } + if(timerSecs==81) { + NotificationApp* notification = furi_record_open("notification"); + notification_message(notification, &clock_alert_mario2); + furi_record_close("notification"); + } + if(timerSecs==82) { + NotificationApp* notification = furi_record_open("notification"); + notification_message(notification, &clock_alert_mario3); + furi_record_close("notification"); + } + } else { + if(timerSecs==80) { + NotificationApp* notification = furi_record_open("notification"); + notification_message(notification, &clock_alert_silent); + furi_record_close("notification"); + } + } + } + // It's OK to loose this event if system overloaded + osMessageQueuePut(event_queue, &event, 0, 0); +} + +int32_t clock_app(void* p) { + UNUSED(p); + timerStarted=false; + timerSecs=0; + songSelect=0; + osMessageQueueId_t event_queue = osMessageQueueNew(8, sizeof(PluginEvent), NULL); + ClockState* plugin_state = malloc(sizeof(ClockState)); + clock_state_init(plugin_state); + ValueMutex state_mutex; + if (!init_mutex(&state_mutex, plugin_state, sizeof(ClockState))) { + FURI_LOG_E(TAG, "cannot create mutex\r\n"); + free(plugin_state); + return 255; + } + // Set system callbacks + ViewPort* view_port = view_port_alloc(); + view_port_draw_callback_set(view_port, clock_render_callback, &state_mutex); + view_port_input_callback_set(view_port, clock_input_callback, event_queue); + osTimerId_t timer = osTimerNew(clock_tick, osTimerPeriodic, event_queue, NULL); + osTimerStart(timer, osKernelGetTickFreq()); + // Open GUI and register view_port + Gui* gui = furi_record_open("gui"); + gui_add_view_port(gui, view_port, GuiLayerFullscreen); + // Main loop + PluginEvent event; + for (bool processing = true; processing;) { + osStatus_t event_status = osMessageQueueGet(event_queue, &event, NULL, 100); + ClockState* plugin_state = (ClockState*)acquire_mutex_block(&state_mutex); + if (event_status == osOK) { + // press events + if (event.type == EventTypeKey) { + if (event.input.type == InputTypeShort || event.input.type == InputTypeRepeat) { + switch(event.input.key) { + case InputKeyUp: + if(timerStarted) timerSecs=timerSecs+5; + break; + case InputKeyDown: + if(timerStarted) timerSecs=timerSecs-5; + break; + case InputKeyRight: + if(songSelect==0) { + songSelect=1; + } else if(songSelect==1) { + songSelect=2; + } else { + songSelect=0; + } + break; + case InputKeyLeft: + break; + case InputKeyOk: + if(songSelect==1 || songSelect==2) { + NotificationApp* notification = furi_record_open("notification"); + notification_message(notification, &clock_alert_startStop); + furi_record_close("notification"); + } + if(timerStarted) { + timerStarted=false; + timerSecs=0; + } else { + timerStarted=true; + } + break; + case InputKeyBack: + // Exit the plugin + processing = false; + break; + } + } + } else if(event.type == EventTypeTick) { + furi_hal_rtc_get_datetime(&plugin_state->datetime); + } + } else { + FURI_LOG_D(TAG, "osMessageQueue: event timeout"); + // event timeout + } + view_port_update(view_port); + release_mutex(&state_mutex, plugin_state); + } + osTimerDelete(timer); + view_port_enabled_set(view_port, false); + gui_remove_view_port(gui, view_port); + furi_record_close("gui"); + view_port_free(view_port); + osMessageQueueDelete(event_queue); + return 0; +} diff --git a/applications/flappy_bird/bird.h b/applications/flappy_bird/bird.h new file mode 100644 index 000000000..339c8056a --- /dev/null +++ b/applications/flappy_bird/bird.h @@ -0,0 +1,54 @@ +#include + +uint8_t bird_array[3][15][11] = { + { + {0,0,0,0,0,0,1,1,0,0,0}, + {0,0,0,0,0,1,0,0,1,0,0}, + {0,0,0,0,0,1,0,0,0,1,0}, + {0,0,1,1,1,1,0,0,0,1,0}, + {0,1,0,0,0,1,0,0,0,1,0}, + {0,1,0,0,0,0,1,0,1,0,1}, + {1,0,0,0,0,0,0,1,0,0,1}, + {1,0,1,1,1,0,0,1,0,0,1}, + {1,1,0,0,0,0,1,0,1,0,1}, + {1,0,0,0,0,1,0,1,0,1,0}, + {1,0,0,0,0,1,0,1,0,1,0}, + {0,1,0,1,1,1,0,1,0,1,0}, + {0,0,1,0,0,1,0,1,0,1,0}, + {0,0,0,1,1,1,0,1,0,1,0}, + {0,0,0,0,0,0,1,1,1,0,0}, + }, { + {0,0,0,0,0,1,1,0,0,0,0}, + {0,0,0,0,1,0,0,1,0,0,0}, + {0,0,0,0,1,0,0,0,1,0,0}, + {0,0,1,1,1,0,0,0,1,0,0}, + {0,1,0,0,1,0,0,0,1,1,0}, + {0,1,0,0,0,1,0,1,0,0,1}, + {1,0,0,0,0,0,1,0,0,0,1}, + {1,0,1,1,1,0,0,1,0,0,1}, + {1,1,0,0,0,0,1,0,1,0,1}, + {1,0,0,0,0,1,0,1,0,1,0}, + {1,0,0,0,0,1,0,1,0,1,0}, + {0,1,0,1,1,1,0,1,0,1,0}, + {0,0,1,0,0,1,0,1,0,1,0}, + {0,0,0,1,1,1,0,1,0,1,0}, + {0,0,0,0,0,0,1,1,1,0,0}, + }, { + {0,0,0,0,1,1,0,0,0,0,0}, + {0,0,0,1,0,0,1,0,0,0,0}, + {0,0,0,1,0,0,0,1,1,0,0}, + {0,0,1,1,0,0,0,1,0,1,0}, + {0,1,0,1,0,0,0,1,0,1,0}, + {0,1,0,0,1,0,1,0,0,0,1}, + {1,0,0,0,0,1,0,0,0,0,1}, + {1,0,1,1,1,0,0,1,0,0,1}, + {1,1,0,0,0,0,1,0,1,0,1}, + {1,0,0,0,0,1,0,1,0,1,0}, + {1,0,0,0,0,1,0,1,0,1,0}, + {0,1,0,1,1,1,0,1,0,1,0}, + {0,0,1,0,0,1,0,1,0,1,0}, + {0,0,0,1,1,1,0,1,0,1,0}, + {0,0,0,0,0,0,1,1,1,0,0}, + } +}; + \ No newline at end of file diff --git a/applications/flappy_bird/flappy_bird.c b/applications/flappy_bird/flappy_bird.c new file mode 100644 index 000000000..602ccc851 --- /dev/null +++ b/applications/flappy_bird/flappy_bird.c @@ -0,0 +1,256 @@ +#include +#include +#include +#include + +#include "bird.h" + +#define TAG "Flappy" + +#define FLAPPY_BIRD_HEIGHT 15 +#define FLAPPY_BIRD_WIDTH 10 + +#define FLAPPY_PILAR_MAX 6 +#define FLAPPY_PILAR_DIST 45 + +#define FLAPPY_GAB_HEIGHT 25 +#define FLAPPY_GAB_WIDTH 5 + +#define FLAPPY_GRAVITY_JUMP -1.1 +#define FLAPPY_GRAVITY_TICK 0.10 + +#define FLIPPER_LCD_WIDTH 128 +#define FLIPPER_LCD_HEIGHT 64 + +typedef enum { + EventTypeTick, + EventTypeKey, +} EventType; + +typedef struct { + int x; + int y; +} POINT; + +typedef struct { + float gravity; + POINT point; +}BIRD; + +typedef struct { + POINT point; + int height; + int visible; + int passed; +} PILAR; + +typedef struct { + BIRD bird; + + int points; + int pilars_count; + PILAR pilars[FLAPPY_PILAR_MAX]; +} GameState; + +typedef struct { + EventType type; + InputEvent input; +} GameEvent; + +typedef enum { + DirectionUp, + DirectionRight, + DirectionDown, + DirectionLeft, +} Direction; + +static void flappy_game_random_pilar(GameState* const game_state) { + PILAR pilar; + + pilar.visible = 1; + pilar.height = random() % (FLIPPER_LCD_HEIGHT - FLAPPY_GAB_HEIGHT) + 1; + pilar.point.y = 0; + pilar.point.x = FLIPPER_LCD_WIDTH + FLAPPY_GAB_WIDTH + 1; + + game_state->pilars_count++; + game_state->pilars[game_state->pilars_count % FLAPPY_PILAR_MAX] = pilar; +} + +static void flappy_game_tick(GameState* const game_state) { + game_state->bird.gravity += FLAPPY_GRAVITY_TICK; + game_state->bird.point.y += game_state->bird.gravity; + + // Checking the location of the last respawned pilar. + PILAR * pilar = &game_state->pilars[game_state->pilars_count % FLAPPY_PILAR_MAX]; + if (pilar->point.x == (FLIPPER_LCD_WIDTH - FLAPPY_PILAR_DIST)) + flappy_game_random_pilar(game_state); + + // Updating the position/status of the pilars (visiblity, posotion, game points) + for (int i = 0; i < FLAPPY_PILAR_MAX; i++) { + PILAR * pilar = &game_state->pilars[i]; + pilar->point.x--; + + if (pilar != NULL && pilar->visible && pilar->point.x > 0) { + if (game_state->bird.point.x >= pilar->point.x + FLAPPY_GAB_WIDTH && + pilar->passed == 0) { + pilar->passed = 1; + game_state->points++; + } + if (pilar->point.x < -FLAPPY_PILAR_DIST) + pilar->visible = 0; + } + } +} + +static void flappy_game_flap(GameState* const game_state) { + game_state->bird.gravity = FLAPPY_GRAVITY_JUMP; +} + +static void flappy_game_state_init(GameState* const game_state) { + BIRD bird; + bird.gravity = 0.0f; + bird.point.x = 5; + bird.point.y = 32; + + game_state->bird = bird; + game_state->pilars_count = 0; + memset(game_state->pilars, 0, sizeof(game_state->pilars)); + + flappy_game_random_pilar(game_state); +} + +static void flappy_game_render_callback(Canvas* const canvas, void* ctx) { + const GameState* game_state = acquire_mutex((ValueMutex*)ctx, 25); + if(game_state == NULL) { + return; + } + + canvas_draw_frame(canvas, 0, 0, 128, 64); + + // Pilars + for (int i = 0; i < FLAPPY_PILAR_MAX; i++) { + const PILAR * pilar = &game_state->pilars[i]; + if (pilar != NULL && pilar->visible) { + canvas_draw_dot(canvas, pilar->point.x, pilar->point.y + 10); + canvas_draw_frame(canvas, pilar->point.x, pilar->point.y, + FLAPPY_GAB_WIDTH, pilar->height); + + canvas_draw_frame(canvas, pilar->point.x, pilar->point.y + pilar->height + FLAPPY_GAB_HEIGHT, + FLAPPY_GAB_WIDTH, FLIPPER_LCD_HEIGHT - pilar->height - FLAPPY_GAB_HEIGHT); + } + } + + // Flappy + for (int h = 0; h < FLAPPY_BIRD_HEIGHT; h++) { + for (int w = 0; w < FLAPPY_BIRD_WIDTH; w++) { + // Switch animation + int bird = 0; + if (game_state->bird.gravity < -0.5) + bird = 1; + else + bird = 2; + + // Draw bird pixels + if (bird_array[bird][h][w] == 1) { + int x = game_state->bird.point.x + h; + int y = game_state->bird.point.y + w; + + canvas_draw_dot(canvas, x, y); + } + } + } + + release_mutex((ValueMutex*)ctx, game_state); +} + + +static void flappy_game_input_callback(InputEvent* input_event, osMessageQueueId_t event_queue) { + furi_assert(event_queue); + + GameEvent event = {.type = EventTypeKey, .input = *input_event}; + osMessageQueuePut(event_queue, &event, 0, osWaitForever); +} + +static void flappy_game_update_timer_callback(osMessageQueueId_t event_queue) { + furi_assert(event_queue); + + GameEvent event = {.type = EventTypeTick}; + osMessageQueuePut(event_queue, &event, 0, 0); +} + +int32_t flappy_game_app(void* p) { + osMessageQueueId_t event_queue = osMessageQueueNew(8, sizeof(GameEvent), NULL); + + GameState* game_state = malloc(sizeof(GameState)); + flappy_game_state_init(game_state); + + ValueMutex state_mutex; + if (!init_mutex(&state_mutex, game_state, sizeof(GameState))) { + FURI_LOG_E(TAG, "cannot create mutex\r\n"); + free(game_state); + return 255; + } + + // Set system callbacks + ViewPort* view_port = view_port_alloc(); + view_port_draw_callback_set(view_port, flappy_game_render_callback, &state_mutex); + view_port_input_callback_set(view_port, flappy_game_input_callback, event_queue); + + osTimerId_t timer = + osTimerNew(flappy_game_update_timer_callback, osTimerPeriodic, event_queue, NULL); + osTimerStart(timer, osKernelGetTickFreq() / 22); + + // Open GUI and register view_port + Gui* gui = furi_record_open("gui"); + gui_add_view_port(gui, view_port, GuiLayerFullscreen); + + GameEvent event; + for(bool processing = true; processing;) { + osStatus_t event_status = osMessageQueueGet(event_queue, &event, NULL, 100); + GameState* game_state = (GameState*)acquire_mutex_block(&state_mutex); + + if(event_status == osOK) { + // press events + if(event.type == EventTypeKey) { + if(event.input.type == InputTypePress) { + switch(event.input.key) { + case InputKeyUp: + game_state->bird.point.y--; + break; + case InputKeyDown: + game_state->bird.point.y++; + break; + case InputKeyRight: + game_state->bird.point.x++; + break; + case InputKeyLeft: + game_state->bird.point.x--; + break; + case InputKeyOk: + flappy_game_flap(game_state); + break; + case InputKeyBack: + processing = false; + break; + } + } + } else if(event.type == EventTypeTick) { + flappy_game_tick(game_state); + } + } else { + FURI_LOG_D(TAG, "osMessageQueue: event timeout"); + // event timeout + } + + view_port_update(view_port); + release_mutex(&state_mutex, game_state); + } + + view_port_enabled_set(view_port, false); + gui_remove_view_port(gui, view_port); + furi_record_close("gui"); + view_port_free(view_port); + osMessageQueueDelete(event_queue); + + return 0; +} \ No newline at end of file diff --git a/applications/jukebox/jukebox.c b/applications/jukebox/jukebox.c new file mode 100644 index 000000000..17bfa89d6 --- /dev/null +++ b/applications/jukebox/jukebox.c @@ -0,0 +1,303 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TAG "JukeBox" + +typedef struct { + bool press[5]; +} RemoteAppState; + +static void jukebox_reset_state(RemoteAppState* state) { + state->press[0] = 0; + state->press[1] = 0; + state->press[2] = 0; + state->press[3] = 0; + state->press[4] = 0; +} +static string_t up_file; +static string_t down_file; +static string_t left_file; +static string_t right_file; +static string_t ok_file; + +static char* subString(char* someString, int n) { + char* new = malloc(sizeof(char) * n + 1); + strncpy(new, someString, n); + new[n] = '\0'; + return new; +} + +static char* file_stub(const char* file_name) { + string_t filename; + string_init(filename); + // string_init(file_name); + path_extract_filename_no_ext(file_name, filename); + + return subString((char*)string_get_cstr(filename), 8); +} + +static void jukebox_send_signal(uint32_t frequency, string_t signal, string_t protocol) { + uint32_t repeat = 1; + frequency = frequency ? frequency : 433920000; + FURI_LOG_D(TAG, "file to send: %s", string_get_cstr(signal)); + + if(strlen(string_get_cstr(signal)) < 10) { + return; + } + + string_t flipper_format_string; + if(strcmp(string_get_cstr(protocol), "RAW") == 0) { + string_init_printf(flipper_format_string, "File_name: %s", string_get_cstr(signal)); + } else { + return; + } + + FlipperFormat* flipper_format = flipper_format_string_alloc(); + Stream* stream = flipper_format_get_raw_stream(flipper_format); + stream_clean(stream); + stream_write_cstring(stream, string_get_cstr(flipper_format_string)); + + SubGhzEnvironment* environment = subghz_environment_alloc(); + + SubGhzTransmitter* transmitter = + subghz_transmitter_alloc_init(environment, string_get_cstr(protocol)); + subghz_transmitter_deserialize(transmitter, flipper_format); + + furi_hal_subghz_reset(); + furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok270Async); + furi_hal_subghz_set_frequency_and_path(frequency); + FURI_LOG_D( + TAG, "Transmitting at %lu, repeat %lu. Press CTRL+C to stop\r\n", frequency, repeat); + + furi_hal_power_suppress_charge_enter(); + furi_hal_subghz_start_async_tx(subghz_transmitter_yield, transmitter); + + while(!(furi_hal_subghz_is_async_tx_complete())) { + FURI_LOG_D(TAG, "."); + fflush(stdout); + osDelay(333); + } + furi_hal_subghz_stop_async_tx(); + furi_hal_subghz_sleep(); + + furi_hal_power_suppress_charge_exit(); + + flipper_format_free(flipper_format); + subghz_transmitter_free(transmitter); + subghz_environment_free(environment); +} + +static void jukebox_render_callback(Canvas* canvas, void* ctx) { + RemoteAppState* state = (RemoteAppState*)acquire_mutex((ValueMutex*)ctx, 25); + canvas_clear(canvas); + char strings[5][20]; + string_t signal; + string_init(signal); + sprintf(strings[0], "Ok: %s", file_stub(string_get_cstr(ok_file))); + sprintf(strings[1], "L: %s", file_stub(string_get_cstr(left_file))); + sprintf(strings[2], "R: %s", file_stub(string_get_cstr(right_file))); + sprintf(strings[3], "U: %s", file_stub(string_get_cstr(up_file))); + sprintf(strings[4], "D: %s", file_stub(string_get_cstr(down_file))); + + canvas_set_font(canvas, FontPrimary); + canvas_draw_str(canvas, 0, 10, "Univeral Remote"); + + canvas_set_font(canvas, FontSecondary); + canvas_draw_str(canvas, 0, 24, strings[1]); + canvas_draw_str(canvas, 85, 24, strings[2]); + canvas_draw_str(canvas, 0, 36, strings[3]); + canvas_draw_str(canvas, 85, 36, strings[4]); + canvas_draw_str(canvas, 0, 48, strings[0]); + // canvas_draw_circle(canvas, 100, 26, 25); + + if(state->press[0]) { + string_cat_printf(signal, "%s", string_get_cstr(right_file)); + } + + else if(state->press[1]) { + string_cat_printf(signal, "%s", string_get_cstr(left_file)); + + } else if(state->press[2]) { + string_cat_printf(signal, "%s", string_get_cstr(up_file)); + + } else if(state->press[3]) { + string_cat_printf(signal, "%s", string_get_cstr(down_file)); + + } + + else if(state->press[4]) { + string_cat_printf(signal, "%s", string_get_cstr(ok_file)); + } + FURI_LOG_D(TAG, "signal = %s", string_get_cstr(signal)); + + if(strlen(string_get_cstr(signal)) > 12) { + string_t file_name; + string_init(file_name); + string_t protocol; + string_init(protocol); + string_set(file_name, string_get_cstr(signal)); + Storage* storage = furi_record_open("storage"); + FlipperFormat* fff_data_file = flipper_format_file_alloc(storage); + uint32_t frequency_str; + flipper_format_file_open_existing(fff_data_file, string_get_cstr(file_name)); + flipper_format_read_uint32(fff_data_file, "Frequency", (uint32_t*)&frequency_str, 1); + if(!flipper_format_read_string(fff_data_file, "Protocol", protocol)) { + FURI_LOG_D(TAG, "Could not read Protocol"); + string_set(protocol, "RAW"); + } + flipper_format_free(fff_data_file); + furi_record_close("storage"); + FURI_LOG_D(TAG, "%lu", frequency_str); + jukebox_send_signal(frequency_str, signal, protocol); + } + + canvas_draw_str(canvas, 10, 63, "[back] - skip, hold to exit"); + + release_mutex((ValueMutex*)ctx, state); +} + +static void jukebox_input_callback(InputEvent* input_event, void* ctx) { + osMessageQueueId_t event_queue = ctx; + osMessageQueuePut(event_queue, input_event, 0, osWaitForever); +} + +int32_t jukebox_app(void* p) { + UNUSED(p); + osMessageQueueId_t event_queue = osMessageQueueNew(32, sizeof(InputEvent), NULL); + furi_check(event_queue); + string_init(up_file); + string_init(down_file); + string_init(left_file); + string_init(right_file); + string_init(ok_file); + + string_t file_name; + string_init(file_name); + string_set(file_name, "/ext/subghz/assets/touchtunes_map"); + Storage* storage = furi_record_open("storage"); + FlipperFormat* fff_data_file = flipper_format_file_alloc(storage); + if(!flipper_format_file_open_existing(fff_data_file, string_get_cstr(file_name))) { + FURI_LOG_D(TAG, "Could not open file %s", string_get_cstr(file_name)); + } + + if(!flipper_format_read_string(fff_data_file, "UP", up_file)) { + FURI_LOG_D(TAG, "Could not read UP string"); + } + if(!flipper_format_read_string(fff_data_file, "DOWN", down_file)) { + FURI_LOG_D(TAG, "Could not read DOWN string"); + } + if(!flipper_format_read_string(fff_data_file, "LEFT", left_file)) { + FURI_LOG_D(TAG, "Could not read LEFT string"); + } + if(!flipper_format_read_string(fff_data_file, "RIGHT", right_file)) { + FURI_LOG_D(TAG, "Could not read RIGHT string"); + } + if(!flipper_format_read_string(fff_data_file, "OK", ok_file)) { + FURI_LOG_D(TAG, "Could not read OK string"); + } + flipper_format_free(fff_data_file); + furi_record_close("storage"); + FURI_LOG_I( + TAG, + "%s %s %s %s %s ", + string_get_cstr(up_file), + string_get_cstr(down_file), + string_get_cstr(left_file), + string_get_cstr(right_file), + string_get_cstr(ok_file)); + + RemoteAppState _state = {{false, false, false, false, false}}; + + ValueMutex state_mutex; + if(!init_mutex(&state_mutex, &_state, sizeof(RemoteAppState))) { + FURI_LOG_D(TAG, "cannot create mutex"); + return 0; + } + + ViewPort* view_port = view_port_alloc(); + + view_port_draw_callback_set(view_port, jukebox_render_callback, &state_mutex); + view_port_input_callback_set(view_port, jukebox_input_callback, event_queue); + + // Open GUI and register view_port + Gui* gui = furi_record_open("gui"); + gui_add_view_port(gui, view_port, GuiLayerFullscreen); + + InputEvent event; + while(osMessageQueueGet(event_queue, &event, NULL, osWaitForever) == osOK) { + RemoteAppState* state = (RemoteAppState*)acquire_mutex_block(&state_mutex); + FURI_LOG_D( + TAG, + "key: %s type: %s", + input_get_key_name(event.key), + input_get_type_name(event.type)); + + if(event.key == InputKeyRight) { + if(event.type == InputTypePress) { + state->press[0] = true; + } else if(event.type == InputTypeRelease) { + state->press[0] = false; + } else if(event.type == InputTypeShort) { + state->press[0] = false; + } + } else if(event.key == InputKeyLeft) { + if(event.type == InputTypePress) { + state->press[1] = true; + } else if(event.type == InputTypeRelease) { + state->press[1] = false; + } else if(event.type == InputTypeShort) { + state->press[1] = false; + } + } else if(event.key == InputKeyUp) { + if(event.type == InputTypePress) { + state->press[2] = true; + } else if(event.type == InputTypeRelease) { + state->press[2] = false; + } else if(event.type == InputTypeShort) { + state->press[2] = false; + } + } else if(event.key == InputKeyDown) { + if(event.type == InputTypePress) { + state->press[3] = true; + } else if(event.type == InputTypeRelease) { + state->press[3] = false; + } else if(event.type == InputTypeShort) { + state->press[3] = false; + } + } else if(event.key == InputKeyOk) { + if(event.type == InputTypePress) { + state->press[4] = true; + } else if(event.type == InputTypeRelease) { + state->press[4] = false; + } else if(event.type == InputTypeShort) { + state->press[4] = false; + } + } else if(event.key == InputKeyBack) { + if(event.type == InputTypeLong) { + release_mutex(&state_mutex, state); + break; + } else if(event.type == InputTypeShort) { + jukebox_reset_state(state); + } + } + release_mutex(&state_mutex, state); + view_port_update(view_port); + } + + // remove & free all stuff created by app + gui_remove_view_port(gui, view_port); + view_port_free(view_port); + osMessageQueueDelete(event_queue); + delete_mutex(&state_mutex); + + furi_record_close("gui"); + + return 0; +} \ No newline at end of file diff --git a/applications/notification/notification_settings_app.c b/applications/notification/notification_settings_app.c index bcb1b6a27..8254473fe 100644 --- a/applications/notification/notification_settings_app.c +++ b/applications/notification/notification_settings_app.c @@ -46,16 +46,17 @@ const char* const volume_text[VOLUME_COUNT] = { }; const float volume_value[VOLUME_COUNT] = {0.0f, 0.25f, 0.5f, 0.75f, 1.0f}; -#define DELAY_COUNT 6 +#define DELAY_COUNT 7 const char* const delay_text[DELAY_COUNT] = { "1s", "5s", "15s", "30s", "60s", + "90s", "120s", }; -const uint32_t delay_value[DELAY_COUNT] = {1000, 5000, 15000, 30000, 60000, 120000}; +const uint32_t delay_value[DELAY_COUNT] = {1000, 5000, 15000, 30000, 60000, 90000, 120000}; #define VIBRO_COUNT 2 const char* const vibro_text[VIBRO_COUNT] = { diff --git a/applications/snake_game/snake_game.c b/applications/snake_game/snake_game.c index bb9e207de..b07210ee5 100644 --- a/applications/snake_game/snake_game.c +++ b/applications/snake_game/snake_game.c @@ -2,6 +2,8 @@ #include #include #include +#include +#include typedef struct { // +-----x @@ -298,6 +300,11 @@ static void snake_game_process_game_step(SnakeState* const snake_state) { bool eatFruit = (next_step.x == snake_state->fruit.x) && (next_step.y == snake_state->fruit.y); if(eatFruit) { + NotificationApp* notification = furi_record_open("notification"); + notification_message(notification, &sequence_single_vibro); + notification_message(notification, &sequence_blink_white_100); + furi_record_close("notification"); + snake_state->len++; if(snake_state->len >= MAX_SNAKE_LEN) { snake_state->state = GameStateGameOver; diff --git a/applications/spectrum_analyzer/spectrum_analyzer.c b/applications/spectrum_analyzer/spectrum_analyzer.c index e3f557791..5d9ec2531 100644 --- a/applications/spectrum_analyzer/spectrum_analyzer.c +++ b/applications/spectrum_analyzer/spectrum_analyzer.c @@ -20,7 +20,7 @@ typedef struct { uint32_t channel0_frequency; uint32_t spacing; - double max_rssi; + float max_rssi; uint8_t max_rssi_dec; uint8_t max_rssi_channel; uint8_t channel_ss[NUM_CHANNELS]; @@ -135,7 +135,7 @@ static void spectrum_analyzer_render_callback(Canvas* const canvas, void* ctx) { temp_str, 36, "Peak: %3.2f Mhz %3.1f dbm", - ((double)(model->channel0_frequency + (model->max_rssi_channel * model->spacing)) / + ((float)(model->channel0_frequency + (model->max_rssi_channel * model->spacing)) / 1000000), model->max_rssi); canvas_draw_str_aligned(canvas, 127, 0, AlignRight, AlignTop, temp_str); @@ -156,7 +156,7 @@ static void spectrum_analyzer_input_callback(InputEvent* input_event, void* ctx) static void spectrum_analyzer_worker_callback( void* channel_ss, - double max_rssi, + float max_rssi, uint8_t max_rssi_dec, uint8_t max_rssi_channel, void* context) { diff --git a/applications/spectrum_analyzer/spectrum_analyzer_worker.c b/applications/spectrum_analyzer/spectrum_analyzer_worker.c index 2b98bae7b..9bf3c1085 100644 --- a/applications/spectrum_analyzer/spectrum_analyzer_worker.c +++ b/applications/spectrum_analyzer/spectrum_analyzer_worker.c @@ -16,7 +16,7 @@ struct SpectrumAnalyzerWorker { uint32_t channel0_frequency; uint32_t spacing; uint8_t width; - double max_rssi; + float max_rssi; uint8_t max_rssi_dec; uint8_t max_rssi_channel; diff --git a/applications/spectrum_analyzer/spectrum_analyzer_worker.h b/applications/spectrum_analyzer/spectrum_analyzer_worker.h index 1f5002359..ca051dacc 100644 --- a/applications/spectrum_analyzer/spectrum_analyzer_worker.h +++ b/applications/spectrum_analyzer/spectrum_analyzer_worker.h @@ -4,7 +4,7 @@ typedef void (*SpectrumAnalyzerWorkerCallback)( void* chan_table, - double max_rssi, + float max_rssi, uint8_t max_rssi_dec, uint8_t max_rssi_channel, void* context); diff --git a/applications/subghz/scenes/subghz_scene_read_raw.c b/applications/subghz/scenes/subghz_scene_read_raw.c index 767f09248..6914bdb31 100644 --- a/applications/subghz/scenes/subghz_scene_read_raw.c +++ b/applications/subghz/scenes/subghz_scene_read_raw.c @@ -1,10 +1,12 @@ +#include +#include #include "../subghz_i.h" #include "../views/subghz_read_raw.h" #include #include #include -#define RAW_FILE_NAME "Raw_signal_" +#define RAW_FILE_NAME "R_" #define TAG "SubGhzSceneReadRAW" bool subghz_scene_read_raw_update_filename(SubGhz* subghz) { @@ -237,8 +239,17 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) { string_t temp_str; string_init(temp_str); + + FuriHalRtcDateTime datetime; + furi_hal_rtc_get_datetime(&datetime); + char strings[1][25]; + sprintf(strings[0], "%s%.4d%.2d%.2d%.2d%.2d", "R" + , datetime.year, datetime.month, datetime.day + , datetime.hour, datetime.minute + ); + string_printf( - temp_str, "%s/%s%s", SUBGHZ_RAW_FOLDER, RAW_FILE_NAME, SUBGHZ_APP_EXTENSION); + temp_str, "%s/%s%s", SUBGHZ_RAW_FOLDER, strings[0], SUBGHZ_APP_EXTENSION); subghz_protocol_raw_gen_fff_data(subghz->txrx->fff_data, string_get_cstr(temp_str)); string_clear(temp_str); @@ -259,9 +270,17 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) { scene_manager_next_scene(subghz->scene_manager, SubGhzSceneNeedSaving); } else { //subghz_get_preset_name(subghz, subghz->error_str); + FuriHalRtcDateTime datetime; + furi_hal_rtc_get_datetime(&datetime); + char strings[1][25]; + sprintf(strings[0], "%s%.4d%.2d%.2d%.2d%.2d", "R" + , datetime.year, datetime.month, datetime.day + , datetime.hour, datetime.minute + ); + if(subghz_protocol_raw_save_to_file_init( (SubGhzProtocolDecoderRAW*)subghz->txrx->decoder_result, - RAW_FILE_NAME, + strings[0], subghz->txrx->frequency, subghz->txrx->preset)) { DOLPHIN_DEED(DolphinDeedSubGhzRawRec); diff --git a/applications/subghz/subghz_setting.c b/applications/subghz/subghz_setting.c index 4d40d49ee..f5d3da5d4 100644 --- a/applications/subghz/subghz_setting.c +++ b/applications/subghz/subghz_setting.c @@ -19,25 +19,36 @@ typedef enum { static const uint32_t subghz_frequencies[] = { /* 300 - 348 */ 300000000, + 302757000, /* FCC ID N6U303NTX */ 303875000, - 304250000, + 304250000, /* Ceiling Fan - Harbor Breeze*/ + 310000000, + 313850000, /* 2007 Honda Key */ 315000000, 318000000, + 348000000, + 387000000, /* 387 - 464 */ 390000000, 418000000, 433075000, /* LPD433 first */ + 433220000, /* 2016-2020 Honda */ 433420000, + 433889000, /* ROGUE? */ + 433920000, /* LPD433 mid */ 434420000, 434775000, /* LPD433 last channels */ 438900000, + 464000000, /* 779 - 928 */ + 779000000, 868350000, 915000000, 925000000, + 928000000, 0, }; static const uint32_t subghz_hopper_frequencies[] = { diff --git a/applications/tetris_game/tetris_game.c b/applications/tetris_game/tetris_game.c index 222728114..8bfdd741c 100644 --- a/applications/tetris_game/tetris_game.c +++ b/applications/tetris_game/tetris_game.c @@ -269,7 +269,7 @@ static void tetris_game_update_timer_callback(osMessageQueueId_t event_queue) { int32_t tetris_game_app(void* p) { - UNUSED(p); + (void)p; srand(DWT->CYCCNT); osMessageQueueId_t event_queue = osMessageQueueNew(8, sizeof(TetrisEvent), NULL); @@ -402,4 +402,4 @@ int32_t tetris_game_app(void* p) { free(tetris_state); return 0; -} +} \ No newline at end of file diff --git a/applications/universal_rf/universal_rf.c b/applications/universal_rf/universal_rf.c new file mode 100644 index 000000000..d37c38350 --- /dev/null +++ b/applications/universal_rf/universal_rf.c @@ -0,0 +1,303 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TAG "UniveralRFRemote" + +typedef struct { + bool press[5]; +} RemoteAppState; + +static void remote_reset_state(RemoteAppState* state) { + state->press[0] = 0; + state->press[1] = 0; + state->press[2] = 0; + state->press[3] = 0; + state->press[4] = 0; +} +static string_t up_file; +static string_t down_file; +static string_t left_file; +static string_t right_file; +static string_t ok_file; + +static char* subString(char* someString, int n) { + char* new = malloc(sizeof(char) * n + 1); + strncpy(new, someString, n); + new[n] = '\0'; + return new; +} + +static char* file_stub(const char* file_name) { + string_t filename; + string_init(filename); + // string_init(file_name); + path_extract_filename_no_ext(file_name, filename); + + return subString((char*)string_get_cstr(filename), 8); +} + +static void remote_send_signal(uint32_t frequency, string_t signal, string_t protocol) { + uint32_t repeat = 1; + frequency = frequency ? frequency : 433920000; + FURI_LOG_D(TAG, "file to send: %s", string_get_cstr(signal)); + + if(strlen(string_get_cstr(signal)) < 10) { + return; + } + + string_t flipper_format_string; + if(strcmp(string_get_cstr(protocol), "RAW") == 0) { + string_init_printf(flipper_format_string, "File_name: %s", string_get_cstr(signal)); + } else { + return; + } + + FlipperFormat* flipper_format = flipper_format_string_alloc(); + Stream* stream = flipper_format_get_raw_stream(flipper_format); + stream_clean(stream); + stream_write_cstring(stream, string_get_cstr(flipper_format_string)); + + SubGhzEnvironment* environment = subghz_environment_alloc(); + + SubGhzTransmitter* transmitter = + subghz_transmitter_alloc_init(environment, string_get_cstr(protocol)); + subghz_transmitter_deserialize(transmitter, flipper_format); + + furi_hal_subghz_reset(); + furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok270Async); + furi_hal_subghz_set_frequency_and_path(frequency); + FURI_LOG_D( + TAG, "Transmitting at %lu, repeat %lu. Press CTRL+C to stop\r\n", frequency, repeat); + + furi_hal_power_suppress_charge_enter(); + furi_hal_subghz_start_async_tx(subghz_transmitter_yield, transmitter); + + while(!(furi_hal_subghz_is_async_tx_complete())) { + FURI_LOG_D(TAG, "."); + fflush(stdout); + osDelay(333); + } + furi_hal_subghz_stop_async_tx(); + furi_hal_subghz_sleep(); + + furi_hal_power_suppress_charge_exit(); + + flipper_format_free(flipper_format); + subghz_transmitter_free(transmitter); + subghz_environment_free(environment); +} + +static void remote_render_callback(Canvas* canvas, void* ctx) { + RemoteAppState* state = (RemoteAppState*)acquire_mutex((ValueMutex*)ctx, 25); + canvas_clear(canvas); + char strings[5][20]; + string_t signal; + string_init(signal); + sprintf(strings[0], "Ok: %s", file_stub(string_get_cstr(ok_file))); + sprintf(strings[1], "L: %s", file_stub(string_get_cstr(left_file))); + sprintf(strings[2], "R: %s", file_stub(string_get_cstr(right_file))); + sprintf(strings[3], "U: %s", file_stub(string_get_cstr(up_file))); + sprintf(strings[4], "D: %s", file_stub(string_get_cstr(down_file))); + + canvas_set_font(canvas, FontPrimary); + canvas_draw_str(canvas, 0, 10, "Univeral Remote"); + + canvas_set_font(canvas, FontSecondary); + canvas_draw_str(canvas, 0, 24, strings[1]); + canvas_draw_str(canvas, 85, 24, strings[2]); + canvas_draw_str(canvas, 0, 36, strings[3]); + canvas_draw_str(canvas, 85, 36, strings[4]); + canvas_draw_str(canvas, 0, 48, strings[0]); + // canvas_draw_circle(canvas, 100, 26, 25); + + if(state->press[0]) { + string_cat_printf(signal, "%s", string_get_cstr(right_file)); + } + + else if(state->press[1]) { + string_cat_printf(signal, "%s", string_get_cstr(left_file)); + + } else if(state->press[2]) { + string_cat_printf(signal, "%s", string_get_cstr(up_file)); + + } else if(state->press[3]) { + string_cat_printf(signal, "%s", string_get_cstr(down_file)); + + } + + else if(state->press[4]) { + string_cat_printf(signal, "%s", string_get_cstr(ok_file)); + } + FURI_LOG_D(TAG, "signal = %s", string_get_cstr(signal)); + + if(strlen(string_get_cstr(signal)) > 12) { + string_t file_name; + string_init(file_name); + string_t protocol; + string_init(protocol); + string_set(file_name, string_get_cstr(signal)); + Storage* storage = furi_record_open("storage"); + FlipperFormat* fff_data_file = flipper_format_file_alloc(storage); + uint32_t frequency_str; + flipper_format_file_open_existing(fff_data_file, string_get_cstr(file_name)); + flipper_format_read_uint32(fff_data_file, "Frequency", (uint32_t*)&frequency_str, 1); + if(!flipper_format_read_string(fff_data_file, "Protocol", protocol)) { + FURI_LOG_D(TAG, "Could not read Protocol"); + string_set(protocol, "RAW"); + } + flipper_format_free(fff_data_file); + furi_record_close("storage"); + FURI_LOG_D(TAG, "%lu", frequency_str); + remote_send_signal(frequency_str, signal, protocol); + } + + canvas_draw_str(canvas, 10, 63, "[back] - skip, hold to exit"); + + release_mutex((ValueMutex*)ctx, state); +} + +static void remote_input_callback(InputEvent* input_event, void* ctx) { + osMessageQueueId_t event_queue = ctx; + osMessageQueuePut(event_queue, input_event, 0, osWaitForever); +} + +int32_t universal_rf_remote_app(void* p) { + UNUSED(p); + osMessageQueueId_t event_queue = osMessageQueueNew(32, sizeof(InputEvent), NULL); + furi_check(event_queue); + string_init(up_file); + string_init(down_file); + string_init(left_file); + string_init(right_file); + string_init(ok_file); + + string_t file_name; + string_init(file_name); + string_set(file_name, "/ext/subghz/assets/universal_rf_map"); + Storage* storage = furi_record_open("storage"); + FlipperFormat* fff_data_file = flipper_format_file_alloc(storage); + if(!flipper_format_file_open_existing(fff_data_file, string_get_cstr(file_name))) { + FURI_LOG_D(TAG, "Could not open file %s", string_get_cstr(file_name)); + } + + if(!flipper_format_read_string(fff_data_file, "UP", up_file)) { + FURI_LOG_D(TAG, "Could not read UP string"); + } + if(!flipper_format_read_string(fff_data_file, "DOWN", down_file)) { + FURI_LOG_D(TAG, "Could not read DOWN string"); + } + if(!flipper_format_read_string(fff_data_file, "LEFT", left_file)) { + FURI_LOG_D(TAG, "Could not read LEFT string"); + } + if(!flipper_format_read_string(fff_data_file, "RIGHT", right_file)) { + FURI_LOG_D(TAG, "Could not read RIGHT string"); + } + if(!flipper_format_read_string(fff_data_file, "OK", ok_file)) { + FURI_LOG_D(TAG, "Could not read OK string"); + } + flipper_format_free(fff_data_file); + furi_record_close("storage"); + FURI_LOG_I( + TAG, + "%s %s %s %s %s ", + string_get_cstr(up_file), + string_get_cstr(down_file), + string_get_cstr(left_file), + string_get_cstr(right_file), + string_get_cstr(ok_file)); + + RemoteAppState _state = {{false, false, false, false, false}}; + + ValueMutex state_mutex; + if(!init_mutex(&state_mutex, &_state, sizeof(RemoteAppState))) { + FURI_LOG_D(TAG, "cannot create mutex"); + return 0; + } + + ViewPort* view_port = view_port_alloc(); + + view_port_draw_callback_set(view_port, remote_render_callback, &state_mutex); + view_port_input_callback_set(view_port, remote_input_callback, event_queue); + + // Open GUI and register view_port + Gui* gui = furi_record_open("gui"); + gui_add_view_port(gui, view_port, GuiLayerFullscreen); + + InputEvent event; + while(osMessageQueueGet(event_queue, &event, NULL, osWaitForever) == osOK) { + RemoteAppState* state = (RemoteAppState*)acquire_mutex_block(&state_mutex); + FURI_LOG_D( + TAG, + "key: %s type: %s", + input_get_key_name(event.key), + input_get_type_name(event.type)); + + if(event.key == InputKeyRight) { + if(event.type == InputTypePress) { + state->press[0] = true; + } else if(event.type == InputTypeRelease) { + state->press[0] = false; + } else if(event.type == InputTypeShort) { + state->press[0] = false; + } + } else if(event.key == InputKeyLeft) { + if(event.type == InputTypePress) { + state->press[1] = true; + } else if(event.type == InputTypeRelease) { + state->press[1] = false; + } else if(event.type == InputTypeShort) { + state->press[1] = false; + } + } else if(event.key == InputKeyUp) { + if(event.type == InputTypePress) { + state->press[2] = true; + } else if(event.type == InputTypeRelease) { + state->press[2] = false; + } else if(event.type == InputTypeShort) { + state->press[2] = false; + } + } else if(event.key == InputKeyDown) { + if(event.type == InputTypePress) { + state->press[3] = true; + } else if(event.type == InputTypeRelease) { + state->press[3] = false; + } else if(event.type == InputTypeShort) { + state->press[3] = false; + } + } else if(event.key == InputKeyOk) { + if(event.type == InputTypePress) { + state->press[4] = true; + } else if(event.type == InputTypeRelease) { + state->press[4] = false; + } else if(event.type == InputTypeShort) { + state->press[4] = false; + } + } else if(event.key == InputKeyBack) { + if(event.type == InputTypeLong) { + release_mutex(&state_mutex, state); + break; + } else if(event.type == InputTypeShort) { + remote_reset_state(state); + } + } + release_mutex(&state_mutex, state); + view_port_update(view_port); + } + + // remove & free all stuff created by app + gui_remove_view_port(gui, view_port); + view_port_free(view_port); + osMessageQueueDelete(event_queue); + delete_mutex(&state_mutex); + + furi_record_close("gui"); + + return 0; +} diff --git a/applications/wav_player/wav_parser.c b/applications/wav_player/wav_parser.c new file mode 100644 index 000000000..c2897706c --- /dev/null +++ b/applications/wav_player/wav_parser.c @@ -0,0 +1,84 @@ +#include "wav_parser.h" + +#define TAG "WavParser" + +const char* format_text(FormatTag tag) { + switch(tag) { + case FormatTagPCM: + return "PCM"; + case FormatTagIEEE_FLOAT: + return "IEEE FLOAT"; + default: + return "Unknown"; + } +}; + +struct WavParser { + WavHeaderChunk header; + WavFormatChunk format; + WavDataChunk data; + size_t wav_data_start; + size_t wav_data_end; +}; + +WavParser* wav_parser_alloc() { + return malloc(sizeof(WavParser)); +} + +void wav_parser_free(WavParser* parser) { + free(parser); +} + +bool wav_parser_parse(WavParser* parser, Stream* stream) { + stream_read(stream, (uint8_t*)&parser->header, sizeof(WavHeaderChunk)); + stream_read(stream, (uint8_t*)&parser->format, sizeof(WavFormatChunk)); + stream_read(stream, (uint8_t*)&parser->data, sizeof(WavDataChunk)); + + if(memcmp(parser->header.riff, "RIFF", 4) != 0 || + memcmp(parser->header.wave, "WAVE", 4) != 0) { + FURI_LOG_E(TAG, "WAV: wrong header"); + return false; + } + + if(memcmp(parser->format.fmt, "fmt ", 4) != 0) { + FURI_LOG_E(TAG, "WAV: wrong format"); + return false; + } + + if(parser->format.tag != FormatTagPCM || memcmp(parser->data.data, "data", 4) != 0) { + FURI_LOG_E( + TAG, + "WAV: non-PCM format %u, next '%lu'", + parser->format.tag, + (uint32_t)parser->data.data); + return false; + } + + FURI_LOG_I( + TAG, + "Format tag: %s, ch: %u, smplrate: %lu, bps: %lu, bits: %u", + format_text(parser->format.tag), + parser->format.channels, + parser->format.sample_rate, + parser->format.byte_per_sec, + parser->format.bits_per_sample); + + parser->wav_data_start = stream_tell(stream); + parser->wav_data_end = parser->wav_data_start + parser->data.size; + + FURI_LOG_I(TAG, "data: %u - %u", parser->wav_data_start, parser->wav_data_end); + + return true; +} + +size_t wav_parser_get_data_start(WavParser* parser) { + return parser->wav_data_start; +} + +size_t wav_parser_get_data_end(WavParser* parser) { + return parser->wav_data_end; +} + +size_t wav_parser_get_data_len(WavParser* parser) { + return parser->wav_data_end - parser->wav_data_start; +} diff --git a/applications/wav_player/wav_parser.h b/applications/wav_player/wav_parser.h new file mode 100644 index 000000000..f50c48b3f --- /dev/null +++ b/applications/wav_player/wav_parser.h @@ -0,0 +1,51 @@ +#pragma once +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + FormatTagPCM = 0x0001, + FormatTagIEEE_FLOAT = 0x0003, +} FormatTag; + +typedef struct { + uint8_t riff[4]; + uint32_t size; + uint8_t wave[4]; +} WavHeaderChunk; + +typedef struct { + uint8_t fmt[4]; + uint32_t size; + uint16_t tag; + uint16_t channels; + uint32_t sample_rate; + uint32_t byte_per_sec; + uint16_t block_align; + uint16_t bits_per_sample; +} WavFormatChunk; + +typedef struct { + uint8_t data[4]; + uint32_t size; +} WavDataChunk; + +typedef struct WavParser WavParser; + +WavParser* wav_parser_alloc(); + +void wav_parser_free(WavParser* parser); + +bool wav_parser_parse(WavParser* parser, Stream* stream); + +size_t wav_parser_get_data_start(WavParser* parser); + +size_t wav_parser_get_data_end(WavParser* parser); + +size_t wav_parser_get_data_len(WavParser* parser); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/applications/wav_player/wav_player.c b/applications/wav_player/wav_player.c new file mode 100644 index 000000000..e86acf5b2 --- /dev/null +++ b/applications/wav_player/wav_player.c @@ -0,0 +1,303 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "wav_player_hal.h" +#include "wav_parser.h" +#include "wav_player_view.h" + +#define TAG "WavPlayer" + +static bool open_wav_stream(Storage* storage, Stream* stream) { + DialogsApp* dialogs = furi_record_open("dialogs"); + bool result = false; + size_t name_size = 255; + char* name_buffer = malloc(name_size); + string_t path; + string_init(path); + + bool ret = + dialog_file_select_show(dialogs, "/ext/wav_player", ".wav", name_buffer, name_size, NULL); + furi_record_close("dialogs"); + + if(ret) { + string_printf(path, "%s/%s.%s", "/ext/wav_player", name_buffer, "wav"); + if(!file_stream_open(stream, string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) { + FURI_LOG_E(TAG, "Cannot open file \"%s\"", string_get_cstr(path)); + } else { + result = true; + } + } + + string_clear(path); + free(name_buffer); + return result; +} + +typedef enum { + WavPlayerEventHalfTransfer, + WavPlayerEventFullTransfer, + WavPlayerEventCtrlVolUp, + WavPlayerEventCtrlVolDn, + WavPlayerEventCtrlMoveL, + WavPlayerEventCtrlMoveR, + WavPlayerEventCtrlOk, + WavPlayerEventCtrlBack, +} WavPlayerEventType; + +typedef struct { + WavPlayerEventType type; +} WavPlayerEvent; + +static void wav_player_dma_isr(void* ctx) { + osMessageQueueId_t event_queue = ctx; + + // half of transfer + if(LL_DMA_IsActiveFlag_HT1(DMA1)) { + LL_DMA_ClearFlag_HT1(DMA1); + // fill first half of buffer + WavPlayerEvent event = {.type = WavPlayerEventHalfTransfer}; + osMessageQueuePut(event_queue, &event, 0, 0); + } + + // transfer complete + if(LL_DMA_IsActiveFlag_TC1(DMA1)) { + LL_DMA_ClearFlag_TC1(DMA1); + // fill second half of buffer + WavPlayerEvent event = {.type = WavPlayerEventFullTransfer}; + osMessageQueuePut(event_queue, &event, 0, 0); + } +} + +typedef struct { + Storage* storage; + Stream* stream; + WavParser* parser; + uint16_t* sample_buffer; + uint8_t* tmp_buffer; + + size_t samples_count_half; + size_t samples_count; + + osMessageQueueId_t queue; + + float volume; + bool play; + + WavPlayerView* view; + ViewDispatcher* view_dispatcher; + Gui* gui; + NotificationApp* notification; +} WavPlayerApp; + +static WavPlayerApp* app_alloc() { + WavPlayerApp* app = malloc(sizeof(WavPlayerApp)); + app->samples_count_half = 1024 * 4; + app->samples_count = app->samples_count_half * 2; + app->storage = furi_record_open("storage"); + app->stream = file_stream_alloc(app->storage); + app->parser = wav_parser_alloc(); + app->sample_buffer = malloc(sizeof(uint16_t) * app->samples_count); + app->tmp_buffer = malloc(sizeof(uint8_t) * app->samples_count); + app->queue = osMessageQueueNew(10, sizeof(WavPlayerEvent), NULL); + + app->volume = 10.0f; + app->play = true; + + app->gui = furi_record_open("gui"); + app->view_dispatcher = view_dispatcher_alloc(); + app->view = wav_player_view_alloc(); + + view_dispatcher_add_view(app->view_dispatcher, 0, wav_player_view_get_view(app->view)); + view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); + view_dispatcher_switch_to_view(app->view_dispatcher, 0); + + app->notification = furi_record_open("notification"); + notification_message(app->notification, &sequence_display_backlight_enforce_on); + + return app; +} + +static void app_free(WavPlayerApp* app) { + view_dispatcher_remove_view(app->view_dispatcher, 0); + view_dispatcher_free(app->view_dispatcher); + wav_player_view_free(app->view); + furi_record_close("gui"); + + osMessageQueueDelete(app->queue); + free(app->tmp_buffer); + free(app->sample_buffer); + wav_parser_free(app->parser); + stream_free(app->stream); + furi_record_close("storage"); + + notification_message(app->notification, &sequence_display_backlight_enforce_auto); + furi_record_close("notification"); + free(app); +} + +// TODO: that works only with 8-bit 2ch audio +static bool fill_data(WavPlayerApp* app, size_t index) { + uint16_t* sample_buffer_start = &app->sample_buffer[index]; + size_t count = stream_read(app->stream, app->tmp_buffer, app->samples_count); + + for(size_t i = count; i < app->samples_count; i++) { + app->tmp_buffer[i] = 0; + } + + for(size_t i = 0; i < app->samples_count; i += 2) { + float data = app->tmp_buffer[i]; + data -= UINT8_MAX / 2; // to signed + data /= UINT8_MAX / 2; // scale -1..1 + + data *= app->volume; // volume + data = tanhf(data); // hyperbolic tangent limiter + + data *= UINT8_MAX / 2; // scale -128..127 + data += UINT8_MAX / 2; // to unsigned + + if(data < 0) { + data = 0; + } + + if(data > 255) { + data = 255; + } + + sample_buffer_start[i / 2] = data; + } + + wav_player_view_set_data(app->view, sample_buffer_start, app->samples_count_half); + + return count != app->samples_count; +} + +static void ctrl_callback(WavPlayerCtrl ctrl, void* ctx) { + osMessageQueueId_t event_queue = ctx; + WavPlayerEvent event; + + switch(ctrl) { + case WavPlayerCtrlVolUp: + event.type = WavPlayerEventCtrlVolUp; + osMessageQueuePut(event_queue, &event, 0, 0); + break; + case WavPlayerCtrlVolDn: + event.type = WavPlayerEventCtrlVolDn; + osMessageQueuePut(event_queue, &event, 0, 0); + break; + case WavPlayerCtrlMoveL: + event.type = WavPlayerEventCtrlMoveL; + osMessageQueuePut(event_queue, &event, 0, 0); + break; + case WavPlayerCtrlMoveR: + event.type = WavPlayerEventCtrlMoveR; + osMessageQueuePut(event_queue, &event, 0, 0); + break; + case WavPlayerCtrlOk: + event.type = WavPlayerEventCtrlOk; + osMessageQueuePut(event_queue, &event, 0, 0); + break; + case WavPlayerCtrlBack: + event.type = WavPlayerEventCtrlBack; + osMessageQueuePut(event_queue, &event, 0, 0); + break; + default: + break; + } +} + +static void app_run(WavPlayerApp* app) { + if(!open_wav_stream(app->storage, app->stream)) return; + if(!wav_parser_parse(app->parser, app->stream)) return; + + wav_player_view_set_volume(app->view, app->volume); + wav_player_view_set_start(app->view, wav_parser_get_data_start(app->parser)); + wav_player_view_set_current(app->view, stream_tell(app->stream)); + wav_player_view_set_end(app->view, wav_parser_get_data_end(app->parser)); + wav_player_view_set_play(app->view, app->play); + + wav_player_view_set_context(app->view, app->queue); + wav_player_view_set_ctrl_callback(app->view, ctrl_callback); + + bool eof = fill_data(app, 0); + eof = fill_data(app, app->samples_count_half); + + wav_player_speaker_init(); + wav_player_dma_init((uint32_t)app->sample_buffer, app->samples_count); + + furi_hal_interrupt_set_isr(FuriHalInterruptIdDma1Ch1, wav_player_dma_isr, app->queue); + + wav_player_dma_start(); + wav_player_speaker_start(); + + WavPlayerEvent event; + + while(1) { + if(osMessageQueueGet(app->queue, &event, NULL, osWaitForever) == osOK) { + if(event.type == WavPlayerEventHalfTransfer) { + eof = fill_data(app, 0); + wav_player_view_set_current(app->view, stream_tell(app->stream)); + if(eof) { + stream_seek( + app->stream, + wav_parser_get_data_start(app->parser), + StreamOffsetFromStart); + } + + } else if(event.type == WavPlayerEventFullTransfer) { + eof = fill_data(app, app->samples_count_half); + wav_player_view_set_current(app->view, stream_tell(app->stream)); + if(eof) { + stream_seek( + app->stream, + wav_parser_get_data_start(app->parser), + StreamOffsetFromStart); + } + } else if(event.type == WavPlayerEventCtrlVolUp) { + if(app->volume < 9.9) app->volume += 0.2; + wav_player_view_set_volume(app->view, app->volume); + } else if(event.type == WavPlayerEventCtrlVolDn) { + if(app->volume > 0.01) app->volume -= 0.2; + wav_player_view_set_volume(app->view, app->volume); + } else if(event.type == WavPlayerEventCtrlMoveL) { + int32_t seek = stream_tell(app->stream) - wav_parser_get_data_start(app->parser); + seek = MIN(seek, wav_parser_get_data_len(app->parser) / 100); + stream_seek(app->stream, -seek, StreamOffsetFromCurrent); + wav_player_view_set_current(app->view, stream_tell(app->stream)); + } else if(event.type == WavPlayerEventCtrlMoveR) { + int32_t seek = wav_parser_get_data_end(app->parser) - stream_tell(app->stream); + seek = MIN(seek, wav_parser_get_data_len(app->parser) / 100); + stream_seek(app->stream, seek, StreamOffsetFromCurrent); + wav_player_view_set_current(app->view, stream_tell(app->stream)); + } else if(event.type == WavPlayerEventCtrlOk) { + app->play = !app->play; + wav_player_view_set_play(app->view, app->play); + + if(!app->play) { + wav_player_speaker_stop(); + } else { + wav_player_speaker_start(); + } + } else if(event.type == WavPlayerEventCtrlBack) { + break; + } + } + } + + wav_player_speaker_stop(); + wav_player_dma_stop(); + + furi_hal_interrupt_set_isr(FuriHalInterruptIdDma1Ch1, NULL, NULL); +} + +int32_t wav_player_app(void* p) { + WavPlayerApp* app = app_alloc(); + app_run(app); + app_free(app); + return 0; +} \ No newline at end of file diff --git a/applications/wav_player/wav_player_hal.c b/applications/wav_player/wav_player_hal.c new file mode 100644 index 000000000..ad0c019be --- /dev/null +++ b/applications/wav_player/wav_player_hal.c @@ -0,0 +1,58 @@ +#include "wav_player_hal.h" +#include +#include + +#define FURI_HAL_SPEAKER_TIMER TIM16 +#define FURI_HAL_SPEAKER_CHANNEL LL_TIM_CHANNEL_CH1 +#define DMA_INSTANCE DMA1, LL_DMA_CHANNEL_1 + +void wav_player_speaker_init() { + LL_TIM_InitTypeDef TIM_InitStruct = {0}; + TIM_InitStruct.Prescaler = 4; + TIM_InitStruct.Autoreload = 255; + LL_TIM_Init(FURI_HAL_SPEAKER_TIMER, &TIM_InitStruct); + + LL_TIM_OC_InitTypeDef TIM_OC_InitStruct = {0}; + TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_PWM1; + TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_ENABLE; + TIM_OC_InitStruct.CompareValue = 127; + LL_TIM_OC_Init(FURI_HAL_SPEAKER_TIMER, FURI_HAL_SPEAKER_CHANNEL, &TIM_OC_InitStruct); +} + +void wav_player_speaker_start() { + LL_TIM_EnableAllOutputs(FURI_HAL_SPEAKER_TIMER); + LL_TIM_EnableCounter(FURI_HAL_SPEAKER_TIMER); +} + +void wav_player_speaker_stop() { + LL_TIM_DisableAllOutputs(FURI_HAL_SPEAKER_TIMER); + LL_TIM_DisableCounter(FURI_HAL_SPEAKER_TIMER); +} + +void wav_player_dma_init(uint32_t address, size_t size) { + uint32_t dma_dst = (uint32_t) & (FURI_HAL_SPEAKER_TIMER->CCR1); + + LL_DMA_ConfigAddresses(DMA_INSTANCE, address, dma_dst, LL_DMA_DIRECTION_MEMORY_TO_PERIPH); + LL_DMA_SetDataLength(DMA_INSTANCE, size); + + LL_DMA_SetPeriphRequest(DMA_INSTANCE, LL_DMAMUX_REQ_TIM16_UP); + LL_DMA_SetDataTransferDirection(DMA_INSTANCE, LL_DMA_DIRECTION_MEMORY_TO_PERIPH); + LL_DMA_SetChannelPriorityLevel(DMA_INSTANCE, LL_DMA_PRIORITY_VERYHIGH); + LL_DMA_SetMode(DMA_INSTANCE, LL_DMA_MODE_CIRCULAR); + LL_DMA_SetPeriphIncMode(DMA_INSTANCE, LL_DMA_PERIPH_NOINCREMENT); + LL_DMA_SetMemoryIncMode(DMA_INSTANCE, LL_DMA_MEMORY_INCREMENT); + LL_DMA_SetPeriphSize(DMA_INSTANCE, LL_DMA_PDATAALIGN_HALFWORD); + LL_DMA_SetMemorySize(DMA_INSTANCE, LL_DMA_MDATAALIGN_HALFWORD); + + LL_DMA_EnableIT_TC(DMA_INSTANCE); + LL_DMA_EnableIT_HT(DMA_INSTANCE); +} + +void wav_player_dma_start() { + LL_DMA_EnableChannel(DMA_INSTANCE); + LL_TIM_EnableDMAReq_UPDATE(FURI_HAL_SPEAKER_TIMER); +} + +void wav_player_dma_stop() { + LL_DMA_DisableChannel(DMA_INSTANCE); +} \ No newline at end of file diff --git a/applications/wav_player/wav_player_hal.h b/applications/wav_player/wav_player_hal.h new file mode 100644 index 000000000..124f51406 --- /dev/null +++ b/applications/wav_player/wav_player_hal.h @@ -0,0 +1,23 @@ +#pragma once +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void wav_player_speaker_init(); + +void wav_player_speaker_start(); + +void wav_player_speaker_stop(); + +void wav_player_dma_init(uint32_t address, size_t size); + +void wav_player_dma_start(); + +void wav_player_dma_stop(); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/applications/wav_player/wav_player_view.c b/applications/wav_player/wav_player_view.c new file mode 100644 index 000000000..8068bf351 --- /dev/null +++ b/applications/wav_player/wav_player_view.c @@ -0,0 +1,214 @@ +#include "wav_player_view.h" + +#define DATA_COUNT 116 + +struct WavPlayerView { + View* view; + WavPlayerCtrlCallback callback; + void* context; +}; + +typedef struct { + bool play; + float volume; + size_t start; + size_t end; + size_t current; + uint8_t data[DATA_COUNT]; +} WavPlayerViewModel; + +float map(float x, float in_min, float in_max, float out_min, float out_max) { + return (x - in_min) * (out_max - out_min + 1) / (in_max - in_min + 1) + out_min; +} + +static void wav_player_view_draw_callback(Canvas* canvas, void* _model) { + WavPlayerViewModel* model = _model; + + canvas_clear(canvas); + canvas_set_color(canvas, ColorBlack); + uint8_t x_pos = 0; + uint8_t y_pos = 0; + + // volume + x_pos = 124; + y_pos = 0; + const float volume = (64 / 10.0f) * model->volume; + canvas_draw_frame(canvas, x_pos, y_pos, 4, 64); + canvas_draw_box(canvas, x_pos, y_pos + (64 - volume), 4, volume); + + // play / pause + x_pos = 58; + y_pos = 55; + if(model->play) { + canvas_draw_line(canvas, x_pos, y_pos, x_pos + 8, y_pos + 4); + canvas_draw_line(canvas, x_pos, y_pos + 8, x_pos + 8, y_pos + 4); + canvas_draw_line(canvas, x_pos, y_pos + 8, x_pos, y_pos); + } else { + canvas_draw_box(canvas, x_pos, y_pos, 3, 9); + canvas_draw_box(canvas, x_pos + 4, y_pos, 3, 9); + } + + x_pos = 78; + y_pos = 55; + canvas_draw_line(canvas, x_pos, y_pos, x_pos + 4, y_pos + 4); + canvas_draw_line(canvas, x_pos, y_pos + 8, x_pos + 4, y_pos + 4); + canvas_draw_line(canvas, x_pos, y_pos + 8, x_pos, y_pos); + + x_pos = 82; + y_pos = 55; + canvas_draw_line(canvas, x_pos, y_pos, x_pos + 4, y_pos + 4); + canvas_draw_line(canvas, x_pos, y_pos + 8, x_pos + 4, y_pos + 4); + canvas_draw_line(canvas, x_pos, y_pos + 8, x_pos, y_pos); + + x_pos = 40; + y_pos = 55; + canvas_draw_line(canvas, x_pos, y_pos, x_pos - 4, y_pos + 4); + canvas_draw_line(canvas, x_pos, y_pos + 8, x_pos - 4, y_pos + 4); + canvas_draw_line(canvas, x_pos, y_pos + 8, x_pos, y_pos); + + x_pos = 44; + y_pos = 55; + canvas_draw_line(canvas, x_pos, y_pos, x_pos - 4, y_pos + 4); + canvas_draw_line(canvas, x_pos, y_pos + 8, x_pos - 4, y_pos + 4); + canvas_draw_line(canvas, x_pos, y_pos + 8, x_pos, y_pos); + + // len + x_pos = 4; + y_pos = 47; + const uint8_t play_len = 116; + uint8_t play_pos = map(model->current, model->start, model->end, 0, play_len - 4); + + canvas_draw_frame(canvas, x_pos, y_pos, play_len, 4); + canvas_draw_box(canvas, x_pos + play_pos, y_pos - 2, 4, 8); + canvas_draw_box(canvas, x_pos, y_pos, play_pos, 4); + + // osc + x_pos = 4; + y_pos = 0; + for(size_t i = 1; i < DATA_COUNT; i++) { + canvas_draw_line(canvas, x_pos + i - 1, model->data[i - 1], x_pos + i, model->data[i]); + } +} + +static bool wav_player_view_input_callback(InputEvent* event, void* context) { + WavPlayerView* wav_player_view = context; + bool consumed = false; + + if(wav_player_view->callback) { + if(event->type == InputTypeShort || event->type == InputTypeRepeat) { + if(event->key == InputKeyUp) { + wav_player_view->callback(WavPlayerCtrlVolUp, wav_player_view->context); + consumed = true; + } else if(event->key == InputKeyDown) { + wav_player_view->callback(WavPlayerCtrlVolDn, wav_player_view->context); + consumed = true; + } else if(event->key == InputKeyLeft) { + wav_player_view->callback(WavPlayerCtrlMoveL, wav_player_view->context); + consumed = true; + } else if(event->key == InputKeyRight) { + wav_player_view->callback(WavPlayerCtrlMoveR, wav_player_view->context); + consumed = true; + } else if(event->key == InputKeyOk) { + wav_player_view->callback(WavPlayerCtrlOk, wav_player_view->context); + consumed = true; + } else if(event->key == InputKeyBack) { + wav_player_view->callback(WavPlayerCtrlBack, wav_player_view->context); + consumed = true; + } + } + } + + return consumed; +} + +WavPlayerView* wav_player_view_alloc() { + WavPlayerView* wav_view = malloc(sizeof(WavPlayerView)); + wav_view->view = view_alloc(); + view_set_context(wav_view->view, wav_view); + view_allocate_model(wav_view->view, ViewModelTypeLocking, sizeof(WavPlayerViewModel)); + view_set_draw_callback(wav_view->view, wav_player_view_draw_callback); + view_set_input_callback(wav_view->view, wav_player_view_input_callback); + + return wav_view; +} + +void wav_player_view_free(WavPlayerView* wav_view) { + furi_assert(wav_view); + view_free(wav_view->view); + free(wav_view); +} + +View* wav_player_view_get_view(WavPlayerView* wav_view) { + furi_assert(wav_view); + return wav_view->view; +} + +void wav_player_view_set_volume(WavPlayerView* wav_view, float volume) { + furi_assert(wav_view); + with_view_model( + wav_view->view, (WavPlayerViewModel * model) { + model->volume = volume; + return true; + }); +} + +void wav_player_view_set_start(WavPlayerView* wav_view, size_t start) { + furi_assert(wav_view); + with_view_model( + wav_view->view, (WavPlayerViewModel * model) { + model->start = start; + return true; + }); +} + +void wav_player_view_set_end(WavPlayerView* wav_view, size_t end) { + furi_assert(wav_view); + with_view_model( + wav_view->view, (WavPlayerViewModel * model) { + model->end = end; + return true; + }); +} + +void wav_player_view_set_current(WavPlayerView* wav_view, size_t current) { + furi_assert(wav_view); + with_view_model( + wav_view->view, (WavPlayerViewModel * model) { + model->current = current; + return true; + }); +} + +void wav_player_view_set_play(WavPlayerView* wav_view, bool play) { + furi_assert(wav_view); + with_view_model( + wav_view->view, (WavPlayerViewModel * model) { + model->play = play; + return true; + }); +} + +void wav_player_view_set_data(WavPlayerView* wav_view, uint16_t* data, size_t data_count) { + furi_assert(wav_view); + with_view_model( + wav_view->view, (WavPlayerViewModel * model) { + size_t inc = (data_count / DATA_COUNT) - 1; + + for(size_t i = 0; i < DATA_COUNT; i++) { + model->data[i] = *data / 6; + if(model->data[i] > 42) model->data[i] = 42; + data += inc; + } + return true; + }); +} + +void wav_player_view_set_ctrl_callback(WavPlayerView* wav_view, WavPlayerCtrlCallback callback) { + furi_assert(wav_view); + wav_view->callback = callback; +} + +void wav_player_view_set_context(WavPlayerView* wav_view, void* context) { + furi_assert(wav_view); + wav_view->context = context; +} \ No newline at end of file diff --git a/applications/wav_player/wav_player_view.h b/applications/wav_player/wav_player_view.h new file mode 100644 index 000000000..246aeaf3e --- /dev/null +++ b/applications/wav_player/wav_player_view.h @@ -0,0 +1,45 @@ +#pragma once +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct WavPlayerView WavPlayerView; + +typedef enum { + WavPlayerCtrlVolUp, + WavPlayerCtrlVolDn, + WavPlayerCtrlMoveL, + WavPlayerCtrlMoveR, + WavPlayerCtrlOk, + WavPlayerCtrlBack, +} WavPlayerCtrl; + +typedef void (*WavPlayerCtrlCallback)(WavPlayerCtrl ctrl, void* context); + +WavPlayerView* wav_player_view_alloc(); + +void wav_player_view_free(WavPlayerView* wav_view); + +View* wav_player_view_get_view(WavPlayerView* wav_view); + +void wav_player_view_set_volume(WavPlayerView* wav_view, float volume); + +void wav_player_view_set_start(WavPlayerView* wav_view, size_t start); + +void wav_player_view_set_end(WavPlayerView* wav_view, size_t end); + +void wav_player_view_set_current(WavPlayerView* wav_view, size_t current); + +void wav_player_view_set_play(WavPlayerView* wav_view, bool play); + +void wav_player_view_set_data(WavPlayerView* wav_view, uint16_t* data, size_t data_count); + +void wav_player_view_set_ctrl_callback(WavPlayerView* wav_view, WavPlayerCtrlCallback callback); + +void wav_player_view_set_context(WavPlayerView* wav_view, void* context); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/assets/compiled/assets_icons.c b/assets/compiled/assets_icons.c index 709fab457..566a22fd4 100644 --- a/assets/compiled/assets_icons.c +++ b/assets/compiled/assets_icons.c @@ -328,6 +328,16 @@ const uint8_t _A_Bluetooth_14_4[] = {0x00,0x10,0x00,0x30,0x00,0x51,0x00,0x92,0x0 const uint8_t _A_Bluetooth_14_5[] = {0x00,0x10,0x00,0x30,0x00,0x51,0x00,0x92,0x00,0x94,0x04,0x58,0x08,0x30,0x09,0x30,0x09,0x58,0x08,0x94,0x04,0x92,0x00,0x51,0x00,0x30,0x00,0x10,0x00,}; const uint8_t* const _A_Bluetooth_14[] = {_A_Bluetooth_14_0,_A_Bluetooth_14_1,_A_Bluetooth_14_2,_A_Bluetooth_14_3,_A_Bluetooth_14_4,_A_Bluetooth_14_5}; +const uint8_t _A_Clock_14_0[] = {0x00,0xF0,0x01,0x0E,0x0E,0x47,0x1C,0x03,0x18,0x49,0x12,0x41,0x10,0x41,0x10,0x01,0x10,0x09,0x12,0x02,0x08,0x46,0x0C,0x0E,0x0E,0xF6,0x0D,0x02,0x08,}; +const uint8_t _A_Clock_14_1[] = {0x00,0xF0,0x01,0x0E,0x0E,0x47,0x1C,0x03,0x18,0x09,0x13,0x81,0x10,0x41,0x10,0x01,0x10,0x09,0x12,0x02,0x08,0x46,0x0C,0x0E,0x0E,0xF6,0x0D,0x02,0x08,}; +const uint8_t _A_Clock_14_2[] = {0x00,0xF0,0x01,0x0E,0x0E,0x47,0x1C,0x03,0x18,0x09,0x12,0x01,0x10,0xC1,0x11,0x01,0x10,0x09,0x12,0x02,0x08,0x46,0x0C,0x0E,0x0E,0xF6,0x0D,0x02,0x08,}; +const uint8_t _A_Clock_14_3[] = {0x00,0xF0,0x01,0x0E,0x0E,0x47,0x1C,0x03,0x18,0x09,0x12,0x01,0x10,0x41,0x10,0x81,0x10,0x09,0x13,0x02,0x08,0x46,0x0C,0x0E,0x0E,0xF6,0x0D,0x02,0x08,}; +const uint8_t _A_Clock_14_4[] = {0x00,0xF0,0x01,0x0E,0x0E,0x47,0x1C,0x03,0x18,0x09,0x12,0x01,0x10,0x41,0x10,0x41,0x10,0x49,0x12,0x02,0x08,0x46,0x0C,0x0E,0x0E,0xF6,0x0D,0x02,0x08,}; +const uint8_t _A_Clock_14_5[] = {0x00,0xF0,0x01,0x0E,0x0E,0x47,0x1C,0x03,0x18,0x09,0x12,0x01,0x10,0x41,0x10,0x21,0x10,0x19,0x12,0x02,0x08,0x46,0x0C,0x0E,0x0E,0xF6,0x0D,0x02,0x08,}; +const uint8_t _A_Clock_14_6[] = {0x00,0xF0,0x01,0x0E,0x0E,0x47,0x1C,0x03,0x18,0x09,0x12,0x01,0x10,0x71,0x10,0x01,0x10,0x09,0x12,0x02,0x08,0x46,0x0C,0x0E,0x0E,0xF6,0x0D,0x02,0x08,}; +const uint8_t _A_Clock_14_7[] = {0x00,0xF0,0x01,0x0E,0x0E,0x47,0x1C,0x03,0x18,0x19,0x12,0x21,0x10,0x41,0x10,0x01,0x10,0x09,0x12,0x02,0x08,0x46,0x0C,0x0E,0x0E,0xF6,0x0D,0x02,0x08,}; +const uint8_t* const _A_Clock_14[] = {_A_Clock_14_0,_A_Clock_14_1,_A_Clock_14_2,_A_Clock_14_3,_A_Clock_14_4,_A_Clock_14_5,_A_Clock_14_6,_A_Clock_14_7}; + const uint8_t _A_Debug_14_0[] = {0x00,0x20,0x01,0xC1,0x20,0x22,0x11,0x24,0x09,0xD9,0x26,0x16,0x1A,0xD8,0x06,0xD8,0x06,0xD6,0x1A,0x19,0x26,0xE4,0x09,0xC2,0x10,0x01,0x20,0x00,0x00,}; const uint8_t _A_Debug_14_1[] = {0x00,0x20,0x01,0xC0,0x00,0x22,0x11,0x25,0x29,0xD8,0x06,0x16,0x1A,0xD9,0x26,0xD8,0x06,0xD4,0x0A,0x12,0x12,0xEA,0x15,0xC5,0x28,0x02,0x10,0x02,0x10,}; const uint8_t _A_Debug_14_2[] = {0x00,0x20,0x01,0xC0,0x00,0x20,0x01,0x24,0x09,0xDA,0x16,0x11,0x22,0xDC,0x0E,0xDA,0x16,0xD9,0x26,0x14,0x0A,0xF2,0x13,0xD1,0x22,0x08,0x04,0x06,0x18,}; @@ -375,6 +385,13 @@ const uint8_t _A_Infrared_14_4[] = {0x01,0x00,0x0e,0x00,0x00,0x5f,0x82,0x02,0x05 const uint8_t _A_Infrared_14_5[] = {0x01,0x00,0x15,0x00,0x00,0x2f,0xc2,0x07,0x08,0x82,0x01,0x47,0xc1,0x01,0x05,0x98,0x14,0x41,0xa3,0xf8,0x83,0x80,0x47,0xff,0x3f,}; const uint8_t* const _A_Infrared_14[] = {_A_Infrared_14_0,_A_Infrared_14_1,_A_Infrared_14_2,_A_Infrared_14_3,_A_Infrared_14_4,_A_Infrared_14_5}; +const uint8_t _A_MusicPlayer_14_0[] = {0x01,0x00,0x17,0x00,0x00,0x1e,0x02,0x01,0xc0,0x80,0xf0,0x20,0x74,0x08,0x15,0x02,0x00,0x01,0x3b,0x84,0x02,0xf0,0x01,0x29,0x80,0x5c,0x80,}; +const uint8_t _A_MusicPlayer_14_1[] = {0x01,0x00,0x16,0x00,0x80,0x41,0x20,0x10,0xe8,0x04,0x7a,0x01,0x12,0x80,0x40,0x80,0x27,0x80,0x81,0xf0,0x00,0x25,0x80,0x80,0x86,0x94,}; +const uint8_t _A_MusicPlayer_14_2[] = {0x01,0x00,0x13,0x00,0x00,0x34,0x82,0x03,0x30,0x81,0xcc,0x20,0x51,0x08,0x00,0x05,0x63,0x90,0x08,0xf0,0x04,0xa1,0x80,}; +const uint8_t _A_MusicPlayer_14_3[] = {0x01,0x00,0x16,0x00,0x82,0x40,0x21,0xd0,0x08,0xf4,0x02,0x25,0x00,0x81,0x00,0x52,0x07,0x20,0x81,0xcc,0x00,0x23,0x01,0x90,0x06,0xd4,}; +const uint8_t _A_MusicPlayer_14_4[] = {0x01,0x00,0x15,0x00,0x00,0x2c,0x82,0x01,0x70,0x80,0x7c,0x20,0x19,0x08,0x04,0x40,0x02,0x91,0xc8,0x04,0x78,0x02,0x50,0xc8,0x00,}; +const uint8_t* const _A_MusicPlayer_14[] = {_A_MusicPlayer_14_0,_A_MusicPlayer_14_1,_A_MusicPlayer_14_2,_A_MusicPlayer_14_3,_A_MusicPlayer_14_4}; + const uint8_t _A_NFC_14_0[] = {0x00,0x00,0x08,0x00,0x10,0x00,0x12,0x00,0x22,0x42,0x24,0x87,0x24,0x8D,0x24,0x99,0x24,0xF1,0x24,0x62,0x24,0x00,0x22,0x00,0x12,0x00,0x10,0x00,0x08,}; const uint8_t _A_NFC_14_1[] = {0x01,0x00,0x1a,0x00,0x80,0x42,0x20,0x11,0x00,0x09,0x48,0x28,0x52,0x0c,0x3c,0x83,0x1b,0x20,0xcc,0xc8,0x3e,0x32,0x0b,0x14,0x80,0x1a,0x21,0x34,0x84,0x00,}; const uint8_t _A_NFC_14_2[] = {0x01,0x00,0x10,0x00,0x00,0x3d,0x0a,0x01,0x87,0x80,0x63,0x60,0x19,0x98,0x07,0xc6,0x01,0x62,0x09,0xc0,}; @@ -441,6 +458,38 @@ const uint8_t _A_U2F_14_2[] = {0x00,0xE0,0x01,0x10,0x02,0x08,0x04,0x08,0x04,0x08 const uint8_t _A_U2F_14_3[] = {0x00,0x00,0x00,0xE0,0x01,0x10,0x02,0x08,0x04,0x08,0x04,0xFE,0x1F,0x01,0x20,0xD5,0x2D,0x55,0x25,0x15,0x2D,0x95,0x24,0xDD,0x25,0x01,0x20,0xFE,0x1F,}; const uint8_t* const _A_U2F_14[] = {_A_U2F_14_0,_A_U2F_14_1,_A_U2F_14_2,_A_U2F_14_3}; +const uint8_t _A_UniversalRemote_14_0[] = {0x00,0x60,0x01,0xF8,0x07,0xF8,0x07,0x08,0x04,0x18,0x02,0x08,0x04,0x04,0x08,0x0C,0x0C,0x18,0x04,0x10,0x02,0x98,0x06,0xF8,0x07,0xF8,0x07,0x80,0x01,}; +const uint8_t _A_UniversalRemote_14_1[] = {0x00,0x60,0x01,0xF8,0x07,0xF8,0x07,0x08,0x04,0x18,0x02,0x08,0x04,0x04,0x08,0x0C,0x0C,0x18,0x04,0x10,0x02,0x98,0x06,0xF8,0x07,0xF8,0x07,0x80,0x01,}; +const uint8_t _A_UniversalRemote_14_2[] = {0x00,0x60,0x01,0xF8,0x07,0xF8,0x07,0x08,0x04,0x18,0x02,0x08,0x04,0x04,0x08,0x0C,0x0C,0x18,0x04,0x10,0x02,0x98,0x06,0xF8,0x07,0xF8,0x07,0x80,0x01,}; +const uint8_t _A_UniversalRemote_14_3[] = {0x01,0x00,0x1a,0x00,0xd0,0x40,0x7f,0x10,0x70,0x08,0xc2,0x20,0x91,0x08,0x10,0x0c,0x60,0x90,0x88,0x64,0x32,0x30,0x09,0x2c,0xc4,0x18,0x26,0x78,0x08,0x08,}; +const uint8_t _A_UniversalRemote_14_4[] = {0x00,0x40,0x01,0xF8,0x07,0xF8,0x07,0x18,0x04,0x10,0x06,0x08,0x04,0x0C,0x0C,0x08,0x04,0x18,0x02,0x10,0x06,0xD8,0x06,0xF8,0x07,0xF8,0x07,0x00,0x00,}; +const uint8_t _A_UniversalRemote_14_5[] = {0x00,0x00,0x00,0xF0,0x07,0xF8,0x07,0x18,0x04,0x18,0x06,0x10,0x02,0x08,0x04,0x08,0x04,0x10,0x02,0x18,0x06,0xD8,0x06,0xF8,0x07,0xF0,0x03,0x00,0x00,}; +const uint8_t _A_UniversalRemote_14_6[] = {0x00,0x00,0x01,0xF0,0x03,0xF8,0x07,0x18,0x04,0x10,0x02,0x18,0x04,0x0C,0x0C,0x08,0x04,0x18,0x02,0x10,0x02,0xF8,0x06,0xF8,0x07,0xF0,0x07,0x00,0x00,}; +const uint8_t _A_UniversalRemote_14_7[] = {0x00,0x00,0x00,0xF8,0x07,0xF8,0x07,0x00,0x04,0x10,0x04,0x08,0x04,0x0C,0x0C,0x0C,0x0C,0x18,0x04,0x00,0x04,0xD8,0x06,0xF8,0x07,0xF0,0x03,0x00,0x00,}; +const uint8_t _A_UniversalRemote_14_8[] = {0x00,0x00,0x00,0xF0,0x07,0xF8,0x07,0x18,0x04,0x08,0x04,0x0C,0x0C,0x0A,0x1C,0x0E,0x18,0x08,0x0C,0x48,0x00,0xD8,0x06,0xF8,0x07,0xF0,0x03,0x40,0x00,}; +const uint8_t _A_UniversalRemote_14_9[] = {0x00,0x20,0x02,0xF8,0x07,0xF8,0x07,0x08,0x04,0x00,0x04,0x0C,0x0C,0x0B,0x34,0x0E,0x1C,0x0C,0x0C,0xE0,0x01,0xD8,0x06,0xF8,0x07,0xF8,0x07,0x00,0x00,}; +const uint8_t _A_UniversalRemote_14_10[] = {0x00,0xA0,0x02,0xF8,0x07,0xF8,0x07,0x00,0x04,0x08,0x00,0x0C,0x0C,0x0B,0x34,0x0A,0x14,0x0C,0x0C,0xF0,0x01,0x98,0x05,0xF8,0x07,0xF8,0x07,0x40,0x00,}; +const uint8_t _A_UniversalRemote_14_11[] = {0x00,0xA0,0x01,0xF8,0x07,0xF8,0x07,0x00,0x00,0x00,0x00,0x0E,0x0C,0x0A,0x34,0x0B,0x14,0x0C,0x0C,0xE0,0x01,0x98,0x05,0xF8,0x07,0xD8,0x07,0x60,0x00,}; +const uint8_t _A_UniversalRemote_14_12[] = {0x00,0xA0,0x02,0xF8,0x07,0xF8,0x07,0x00,0x04,0x04,0x00,0x0C,0x0C,0x0A,0x14,0x0A,0x1C,0x0C,0x0C,0xE0,0x01,0x98,0x05,0xF8,0x07,0xD8,0x07,0x60,0x00,}; +const uint8_t _A_UniversalRemote_14_13[] = {0x00,0x60,0x02,0xF8,0x07,0xF8,0x07,0x00,0x04,0x04,0x08,0x0C,0x0C,0x0A,0x34,0x0A,0x14,0x0C,0x0C,0xE8,0x05,0x98,0x05,0xF8,0x07,0xF8,0x07,0x80,0x00,}; +const uint8_t _A_UniversalRemote_14_14[] = {0x00,0x60,0x02,0xF8,0x07,0xF8,0x07,0x00,0x04,0x04,0x08,0x0C,0x0C,0x0A,0x34,0x0A,0x14,0x0C,0x0C,0xE8,0x05,0x98,0x05,0xF8,0x07,0xF8,0x07,0x80,0x00,}; +const uint8_t _A_UniversalRemote_14_15[] = {0x00,0x60,0x02,0xF8,0x07,0xF8,0x07,0x00,0x04,0x04,0x08,0x0C,0x0C,0x0A,0x34,0x0A,0x14,0x0C,0x0C,0xE8,0x05,0x98,0x05,0xF8,0x07,0xF8,0x07,0x80,0x00,}; +const uint8_t _A_UniversalRemote_14_16[] = {0x00,0x60,0x02,0xF8,0x07,0xF8,0x07,0x00,0x04,0x04,0x08,0x0C,0x0C,0x0A,0x34,0x0A,0x14,0x0C,0x0C,0xE8,0x05,0x98,0x05,0xF8,0x07,0xF8,0x07,0x80,0x00,}; +const uint8_t _A_UniversalRemote_14_17[] = {0x00,0xA0,0x01,0xF8,0x07,0xF8,0x07,0x00,0x00,0x04,0x08,0x0C,0x0C,0x0A,0x14,0x0A,0x1C,0x0C,0x0C,0xE0,0x01,0x98,0x06,0xF8,0x07,0xD8,0x07,0x60,0x00,}; +const uint8_t _A_UniversalRemote_14_18[] = {0x00,0x20,0x02,0xF8,0x07,0xF8,0x07,0x08,0x04,0x08,0x04,0x0E,0x0C,0x0A,0x34,0x0B,0x14,0x0C,0x0C,0xE4,0x03,0xD8,0x06,0xF8,0x07,0xF8,0x07,0x00,0x00,}; +const uint8_t _A_UniversalRemote_14_19[] = {0x00,0x00,0x00,0xF0,0x07,0xF8,0x07,0x18,0x04,0x04,0x08,0x0E,0x1C,0x0B,0x34,0x0A,0x14,0x0C,0x0C,0xE0,0x03,0xF8,0x06,0xF8,0x07,0xF0,0x07,0x00,0x00,}; +const uint8_t _A_UniversalRemote_14_20[] = {0x00,0x00,0x01,0xF0,0x03,0xF8,0x07,0x18,0x04,0x04,0x00,0x0C,0x0C,0x0B,0x34,0x0B,0x34,0x0C,0x0C,0xE0,0x05,0xF8,0x06,0xF8,0x07,0xF0,0x03,0x00,0x00,}; +const uint8_t _A_UniversalRemote_14_21[] = {0x00,0x00,0x00,0xF8,0x07,0xF8,0x07,0x10,0x00,0x08,0x04,0x0C,0x0C,0x0C,0x0C,0x0E,0x0C,0x08,0x04,0x88,0x04,0xF0,0x02,0xF8,0x07,0xF0,0x03,0x00,0x00,}; +const uint8_t _A_UniversalRemote_14_22[] = {0x00,0x00,0x00,0xF8,0x07,0xF8,0x07,0x00,0x00,0x18,0x04,0x08,0x04,0x0C,0x0C,0x08,0x04,0x08,0x04,0x00,0x04,0xD8,0x02,0xF8,0x07,0xF0,0x03,0x00,0x00,}; +const uint8_t _A_UniversalRemote_14_23[] = {0x01,0x00,0x14,0x00,0xa0,0x40,0x7f,0x10,0x70,0x08,0x81,0xc6,0x21,0x02,0x84,0x41,0x00,0x2a,0x09,0x1e,0xc4,0x18,0x26,0xa0,}; +const uint8_t _A_UniversalRemote_14_24[] = {0x01,0x00,0x17,0x00,0x90,0x40,0xbf,0x10,0x70,0x08,0xc2,0x20,0x91,0x08,0x14,0x62,0x0c,0x05,0x10,0x3a,0xe6,0x20,0xa1,0x33,0xa0,0x40,0x00,}; +const uint8_t _A_UniversalRemote_14_25[] = {0x01,0x00,0x1a,0x00,0xb0,0x40,0x7f,0x10,0x70,0x08,0xc2,0x20,0x91,0x88,0x34,0x62,0x04,0x05,0x10,0x39,0x40,0xa2,0x10,0x6c,0xc4,0x14,0x26,0x78,0x08,0x00,}; +const uint8_t _A_UniversalRemote_14_26[] = {0x00,0x60,0x01,0xF8,0x07,0xF8,0x07,0x08,0x04,0x10,0x06,0x08,0x04,0x0C,0x0C,0x08,0x04,0x18,0x02,0x10,0x06,0x98,0x04,0xF8,0x07,0xF8,0x07,0x80,0x02,}; +const uint8_t _A_UniversalRemote_14_27[] = {0x00,0x60,0x01,0xF8,0x07,0xF8,0x07,0x08,0x04,0x18,0x02,0x08,0x04,0x04,0x08,0x0C,0x0C,0x18,0x04,0x10,0x02,0x98,0x06,0xF8,0x07,0xF8,0x07,0x80,0x01,}; +const uint8_t _A_UniversalRemote_14_28[] = {0x00,0x60,0x01,0xF8,0x07,0xF8,0x07,0x08,0x04,0x18,0x02,0x08,0x04,0x04,0x08,0x0C,0x0C,0x18,0x04,0x10,0x02,0x98,0x06,0xF8,0x07,0xF8,0x07,0x80,0x01,}; +const uint8_t _A_UniversalRemote_14_29[] = {0x00,0x60,0x01,0xF8,0x07,0xF8,0x07,0x08,0x04,0x18,0x02,0x08,0x04,0x04,0x08,0x0C,0x0C,0x18,0x04,0x10,0x02,0x98,0x06,0xF8,0x07,0xF8,0x07,0x80,0x01,}; +const uint8_t* const _A_UniversalRemote_14[] = {_A_UniversalRemote_14_0,_A_UniversalRemote_14_1,_A_UniversalRemote_14_2,_A_UniversalRemote_14_3,_A_UniversalRemote_14_4,_A_UniversalRemote_14_5,_A_UniversalRemote_14_6,_A_UniversalRemote_14_7,_A_UniversalRemote_14_8,_A_UniversalRemote_14_9,_A_UniversalRemote_14_10,_A_UniversalRemote_14_11,_A_UniversalRemote_14_12,_A_UniversalRemote_14_13,_A_UniversalRemote_14_14,_A_UniversalRemote_14_15,_A_UniversalRemote_14_16,_A_UniversalRemote_14_17,_A_UniversalRemote_14_18,_A_UniversalRemote_14_19,_A_UniversalRemote_14_20,_A_UniversalRemote_14_21,_A_UniversalRemote_14_22,_A_UniversalRemote_14_23,_A_UniversalRemote_14_24,_A_UniversalRemote_14_25,_A_UniversalRemote_14_26,_A_UniversalRemote_14_27,_A_UniversalRemote_14_28,_A_UniversalRemote_14_29}; + const uint8_t _A_iButton_14_0[] = {0x00,0x00,0x1C,0x00,0x3E,0x00,0x35,0x80,0x3A,0x78,0x15,0x84,0x0A,0x32,0x05,0x49,0x02,0x85,0x02,0x85,0x02,0x49,0x02,0x32,0x01,0x84,0x00,0x78,0x00,}; const uint8_t _A_iButton_14_1[] = {0x00,0x00,0x00,0x00,0x38,0x00,0x26,0x80,0x21,0xE0,0x10,0x38,0x0D,0x6C,0x03,0x56,0x01,0x2B,0x01,0x97,0x00,0x4D,0x00,0x21,0x00,0x1E,0x00,0x00,0x00,}; const uint8_t _A_iButton_14_2[] = {0x01,0x00,0x1a,0x00,0x00,0x24,0xc2,0x01,0x2c,0x80,0x48,0xfb,0x11,0x89,0x64,0x1b,0x2d,0x01,0xa5,0xc0,0x24,0xb0,0x08,0x94,0x02,0x13,0x00,0x83,0x85,0x88,}; @@ -760,11 +809,13 @@ const Icon I_KeySave_24x11 = {.width=24,.height=11,.frame_count=1,.frame_rate=0, const Icon A_125khz_14 = {.width=14,.height=14,.frame_count=4,.frame_rate=3,.frames=_A_125khz_14}; const Icon A_BadUsb_14 = {.width=14,.height=14,.frame_count=11,.frame_rate=3,.frames=_A_BadUsb_14}; const Icon A_Bluetooth_14 = {.width=14,.height=14,.frame_count=6,.frame_rate=3,.frames=_A_Bluetooth_14}; +const Icon A_Clock_14 = {.width=14,.height=14,.frame_count=8,.frame_rate=3,.frames=_A_Clock_14}; const Icon A_Debug_14 = {.width=14,.height=14,.frame_count=4,.frame_rate=3,.frames=_A_Debug_14}; const Icon A_FileManager_14 = {.width=14,.height=14,.frame_count=10,.frame_rate=3,.frames=_A_FileManager_14}; const Icon A_GPIO_14 = {.width=14,.height=14,.frame_count=8,.frame_rate=3,.frames=_A_GPIO_14}; const Icon A_Games_14 = {.width=14,.height=14,.frame_count=9,.frame_rate=3,.frames=_A_Games_14}; const Icon A_Infrared_14 = {.width=14,.height=14,.frame_count=6,.frame_rate=3,.frames=_A_Infrared_14}; +const Icon A_MusicPlayer_14 = {.width=14,.height=14,.frame_count=5,.frame_rate=3,.frames=_A_MusicPlayer_14}; const Icon A_NFC_14 = {.width=14,.height=14,.frame_count=4,.frame_rate=3,.frames=_A_NFC_14}; const Icon A_Passport_14 = {.width=14,.height=14,.frame_count=10,.frame_rate=3,.frames=_A_Passport_14}; const Icon A_Plugins_14 = {.width=14,.height=14,.frame_count=9,.frame_rate=3,.frames=_A_Plugins_14}; @@ -773,6 +824,7 @@ const Icon A_Settings_14 = {.width=14,.height=14,.frame_count=10,.frame_rate=3,. const Icon A_Sub1ghz_14 = {.width=14,.height=14,.frame_count=6,.frame_rate=3,.frames=_A_Sub1ghz_14}; const Icon A_Tamagotchi_14 = {.width=14,.height=14,.frame_count=6,.frame_rate=3,.frames=_A_Tamagotchi_14}; const Icon A_U2F_14 = {.width=14,.height=14,.frame_count=4,.frame_rate=3,.frames=_A_U2F_14}; +const Icon A_UniversalRemote_14 = {.width=14,.height=14,.frame_count=30,.frame_rate=3,.frames=_A_UniversalRemote_14}; const Icon A_iButton_14 = {.width=14,.height=14,.frame_count=7,.frame_rate=3,.frames=_A_iButton_14}; const Icon I_Detailed_chip_17x13 = {.width=17,.height=13,.frame_count=1,.frame_rate=0,.frames=_I_Detailed_chip_17x13}; const Icon I_Medium_chip_22x21 = {.width=22,.height=21,.frame_count=1,.frame_rate=0,.frames=_I_Medium_chip_22x21}; diff --git a/assets/compiled/assets_icons.h b/assets/compiled/assets_icons.h index 12ddb78e9..94de03f1b 100644 --- a/assets/compiled/assets_icons.h +++ b/assets/compiled/assets_icons.h @@ -95,11 +95,13 @@ extern const Icon I_KeySave_24x11; extern const Icon A_125khz_14; extern const Icon A_BadUsb_14; extern const Icon A_Bluetooth_14; +extern const Icon A_Clock_14; extern const Icon A_Debug_14; extern const Icon A_FileManager_14; extern const Icon A_GPIO_14; extern const Icon A_Games_14; extern const Icon A_Infrared_14; +extern const Icon A_MusicPlayer_14; extern const Icon A_NFC_14; extern const Icon A_Passport_14; extern const Icon A_Plugins_14; @@ -108,6 +110,7 @@ extern const Icon A_Settings_14; extern const Icon A_Sub1ghz_14; extern const Icon A_Tamagotchi_14; extern const Icon A_U2F_14; +extern const Icon A_UniversalRemote_14; extern const Icon A_iButton_14; extern const Icon I_Detailed_chip_17x13; extern const Icon I_Medium_chip_22x21; diff --git a/assets/icons/MainMenu/Clock_14/frame_01.png b/assets/icons/MainMenu/Clock_14/frame_01.png new file mode 100644 index 000000000..80193281a Binary files /dev/null and b/assets/icons/MainMenu/Clock_14/frame_01.png differ diff --git a/assets/icons/MainMenu/Clock_14/frame_02.png b/assets/icons/MainMenu/Clock_14/frame_02.png new file mode 100644 index 000000000..7eb0f8bef Binary files /dev/null and b/assets/icons/MainMenu/Clock_14/frame_02.png differ diff --git a/assets/icons/MainMenu/Clock_14/frame_03.png b/assets/icons/MainMenu/Clock_14/frame_03.png new file mode 100644 index 000000000..5d4e6243b Binary files /dev/null and b/assets/icons/MainMenu/Clock_14/frame_03.png differ diff --git a/assets/icons/MainMenu/Clock_14/frame_04.png b/assets/icons/MainMenu/Clock_14/frame_04.png new file mode 100644 index 000000000..8578a5a73 Binary files /dev/null and b/assets/icons/MainMenu/Clock_14/frame_04.png differ diff --git a/assets/icons/MainMenu/Clock_14/frame_05.png b/assets/icons/MainMenu/Clock_14/frame_05.png new file mode 100644 index 000000000..9c50fe469 Binary files /dev/null and b/assets/icons/MainMenu/Clock_14/frame_05.png differ diff --git a/assets/icons/MainMenu/Clock_14/frame_06.png b/assets/icons/MainMenu/Clock_14/frame_06.png new file mode 100644 index 000000000..4fe0f2c63 Binary files /dev/null and b/assets/icons/MainMenu/Clock_14/frame_06.png differ diff --git a/assets/icons/MainMenu/Clock_14/frame_07.png b/assets/icons/MainMenu/Clock_14/frame_07.png new file mode 100644 index 000000000..8ff61ba2e Binary files /dev/null and b/assets/icons/MainMenu/Clock_14/frame_07.png differ diff --git a/assets/icons/MainMenu/Clock_14/frame_08.png b/assets/icons/MainMenu/Clock_14/frame_08.png new file mode 100644 index 000000000..baffdaa70 Binary files /dev/null and b/assets/icons/MainMenu/Clock_14/frame_08.png differ diff --git a/assets/icons/MainMenu/Clock_14/frame_rate b/assets/icons/MainMenu/Clock_14/frame_rate new file mode 100644 index 000000000..00750edc0 --- /dev/null +++ b/assets/icons/MainMenu/Clock_14/frame_rate @@ -0,0 +1 @@ +3 diff --git a/assets/icons/MainMenu/MusicPlayer_14/frame_0.png b/assets/icons/MainMenu/MusicPlayer_14/frame_0.png new file mode 100644 index 000000000..9b20ba849 Binary files /dev/null and b/assets/icons/MainMenu/MusicPlayer_14/frame_0.png differ diff --git a/assets/icons/MainMenu/MusicPlayer_14/frame_1.png b/assets/icons/MainMenu/MusicPlayer_14/frame_1.png new file mode 100644 index 000000000..781d353be Binary files /dev/null and b/assets/icons/MainMenu/MusicPlayer_14/frame_1.png differ diff --git a/assets/icons/MainMenu/MusicPlayer_14/frame_2.png b/assets/icons/MainMenu/MusicPlayer_14/frame_2.png new file mode 100644 index 000000000..9a3099dbd Binary files /dev/null and b/assets/icons/MainMenu/MusicPlayer_14/frame_2.png differ diff --git a/assets/icons/MainMenu/MusicPlayer_14/frame_3.png b/assets/icons/MainMenu/MusicPlayer_14/frame_3.png new file mode 100644 index 000000000..13ddc3eee Binary files /dev/null and b/assets/icons/MainMenu/MusicPlayer_14/frame_3.png differ diff --git a/assets/icons/MainMenu/MusicPlayer_14/frame_4.png b/assets/icons/MainMenu/MusicPlayer_14/frame_4.png new file mode 100644 index 000000000..5ae831e64 Binary files /dev/null and b/assets/icons/MainMenu/MusicPlayer_14/frame_4.png differ diff --git a/assets/icons/MainMenu/MusicPlayer_14/frame_rate b/assets/icons/MainMenu/MusicPlayer_14/frame_rate new file mode 100644 index 000000000..e440e5c84 --- /dev/null +++ b/assets/icons/MainMenu/MusicPlayer_14/frame_rate @@ -0,0 +1 @@ +3 \ No newline at end of file diff --git a/assets/icons/MainMenu/UniversalRemote_14/frame_00_delay-0.04s.png b/assets/icons/MainMenu/UniversalRemote_14/frame_00_delay-0.04s.png new file mode 100644 index 000000000..d6c97146d Binary files /dev/null and b/assets/icons/MainMenu/UniversalRemote_14/frame_00_delay-0.04s.png differ diff --git a/assets/icons/MainMenu/UniversalRemote_14/frame_01_delay-0.04s.png b/assets/icons/MainMenu/UniversalRemote_14/frame_01_delay-0.04s.png new file mode 100644 index 000000000..479fbd58b Binary files /dev/null and b/assets/icons/MainMenu/UniversalRemote_14/frame_01_delay-0.04s.png differ diff --git a/assets/icons/MainMenu/UniversalRemote_14/frame_02_delay-0.04s.png b/assets/icons/MainMenu/UniversalRemote_14/frame_02_delay-0.04s.png new file mode 100644 index 000000000..479fbd58b Binary files /dev/null and b/assets/icons/MainMenu/UniversalRemote_14/frame_02_delay-0.04s.png differ diff --git a/assets/icons/MainMenu/UniversalRemote_14/frame_03_delay-0.04s.png b/assets/icons/MainMenu/UniversalRemote_14/frame_03_delay-0.04s.png new file mode 100644 index 000000000..1ece97a6f Binary files /dev/null and b/assets/icons/MainMenu/UniversalRemote_14/frame_03_delay-0.04s.png differ diff --git a/assets/icons/MainMenu/UniversalRemote_14/frame_04_delay-0.04s.png b/assets/icons/MainMenu/UniversalRemote_14/frame_04_delay-0.04s.png new file mode 100644 index 000000000..d85fa6ebc Binary files /dev/null and b/assets/icons/MainMenu/UniversalRemote_14/frame_04_delay-0.04s.png differ diff --git a/assets/icons/MainMenu/UniversalRemote_14/frame_05_delay-0.04s.png b/assets/icons/MainMenu/UniversalRemote_14/frame_05_delay-0.04s.png new file mode 100644 index 000000000..1f5ff11cb Binary files /dev/null and b/assets/icons/MainMenu/UniversalRemote_14/frame_05_delay-0.04s.png differ diff --git a/assets/icons/MainMenu/UniversalRemote_14/frame_06_delay-0.04s.png b/assets/icons/MainMenu/UniversalRemote_14/frame_06_delay-0.04s.png new file mode 100644 index 000000000..8fbf8625c Binary files /dev/null and b/assets/icons/MainMenu/UniversalRemote_14/frame_06_delay-0.04s.png differ diff --git a/assets/icons/MainMenu/UniversalRemote_14/frame_07_delay-0.04s.png b/assets/icons/MainMenu/UniversalRemote_14/frame_07_delay-0.04s.png new file mode 100644 index 000000000..0472780e4 Binary files /dev/null and b/assets/icons/MainMenu/UniversalRemote_14/frame_07_delay-0.04s.png differ diff --git a/assets/icons/MainMenu/UniversalRemote_14/frame_08_delay-0.04s.png b/assets/icons/MainMenu/UniversalRemote_14/frame_08_delay-0.04s.png new file mode 100644 index 000000000..f3724bbde Binary files /dev/null and b/assets/icons/MainMenu/UniversalRemote_14/frame_08_delay-0.04s.png differ diff --git a/assets/icons/MainMenu/UniversalRemote_14/frame_09_delay-0.04s.png b/assets/icons/MainMenu/UniversalRemote_14/frame_09_delay-0.04s.png new file mode 100644 index 000000000..ff34450d9 Binary files /dev/null and b/assets/icons/MainMenu/UniversalRemote_14/frame_09_delay-0.04s.png differ diff --git a/assets/icons/MainMenu/UniversalRemote_14/frame_10_delay-0.04s.png b/assets/icons/MainMenu/UniversalRemote_14/frame_10_delay-0.04s.png new file mode 100644 index 000000000..2b61340cb Binary files /dev/null and b/assets/icons/MainMenu/UniversalRemote_14/frame_10_delay-0.04s.png differ diff --git a/assets/icons/MainMenu/UniversalRemote_14/frame_11_delay-0.04s.png b/assets/icons/MainMenu/UniversalRemote_14/frame_11_delay-0.04s.png new file mode 100644 index 000000000..9420c763f Binary files /dev/null and b/assets/icons/MainMenu/UniversalRemote_14/frame_11_delay-0.04s.png differ diff --git a/assets/icons/MainMenu/UniversalRemote_14/frame_12_delay-0.04s.png b/assets/icons/MainMenu/UniversalRemote_14/frame_12_delay-0.04s.png new file mode 100644 index 000000000..66a096a64 Binary files /dev/null and b/assets/icons/MainMenu/UniversalRemote_14/frame_12_delay-0.04s.png differ diff --git a/assets/icons/MainMenu/UniversalRemote_14/frame_13_delay-0.04s.png b/assets/icons/MainMenu/UniversalRemote_14/frame_13_delay-0.04s.png new file mode 100644 index 000000000..e9527fa83 Binary files /dev/null and b/assets/icons/MainMenu/UniversalRemote_14/frame_13_delay-0.04s.png differ diff --git a/assets/icons/MainMenu/UniversalRemote_14/frame_14_delay-0.04s.png b/assets/icons/MainMenu/UniversalRemote_14/frame_14_delay-0.04s.png new file mode 100644 index 000000000..e9527fa83 Binary files /dev/null and b/assets/icons/MainMenu/UniversalRemote_14/frame_14_delay-0.04s.png differ diff --git a/assets/icons/MainMenu/UniversalRemote_14/frame_15_delay-0.04s.png b/assets/icons/MainMenu/UniversalRemote_14/frame_15_delay-0.04s.png new file mode 100644 index 000000000..e9527fa83 Binary files /dev/null and b/assets/icons/MainMenu/UniversalRemote_14/frame_15_delay-0.04s.png differ diff --git a/assets/icons/MainMenu/UniversalRemote_14/frame_16_delay-0.04s.png b/assets/icons/MainMenu/UniversalRemote_14/frame_16_delay-0.04s.png new file mode 100644 index 000000000..e9527fa83 Binary files /dev/null and b/assets/icons/MainMenu/UniversalRemote_14/frame_16_delay-0.04s.png differ diff --git a/assets/icons/MainMenu/UniversalRemote_14/frame_17_delay-0.04s.png b/assets/icons/MainMenu/UniversalRemote_14/frame_17_delay-0.04s.png new file mode 100644 index 000000000..ff4374596 Binary files /dev/null and b/assets/icons/MainMenu/UniversalRemote_14/frame_17_delay-0.04s.png differ diff --git a/assets/icons/MainMenu/UniversalRemote_14/frame_18_delay-0.04s.png b/assets/icons/MainMenu/UniversalRemote_14/frame_18_delay-0.04s.png new file mode 100644 index 000000000..2109273f0 Binary files /dev/null and b/assets/icons/MainMenu/UniversalRemote_14/frame_18_delay-0.04s.png differ diff --git a/assets/icons/MainMenu/UniversalRemote_14/frame_19_delay-0.04s.png b/assets/icons/MainMenu/UniversalRemote_14/frame_19_delay-0.04s.png new file mode 100644 index 000000000..0c7e9eaa9 Binary files /dev/null and b/assets/icons/MainMenu/UniversalRemote_14/frame_19_delay-0.04s.png differ diff --git a/assets/icons/MainMenu/UniversalRemote_14/frame_20_delay-0.04s.png b/assets/icons/MainMenu/UniversalRemote_14/frame_20_delay-0.04s.png new file mode 100644 index 000000000..4c283af6c Binary files /dev/null and b/assets/icons/MainMenu/UniversalRemote_14/frame_20_delay-0.04s.png differ diff --git a/assets/icons/MainMenu/UniversalRemote_14/frame_21_delay-0.04s.png b/assets/icons/MainMenu/UniversalRemote_14/frame_21_delay-0.04s.png new file mode 100644 index 000000000..750aec162 Binary files /dev/null and b/assets/icons/MainMenu/UniversalRemote_14/frame_21_delay-0.04s.png differ diff --git a/assets/icons/MainMenu/UniversalRemote_14/frame_22_delay-0.04s.png b/assets/icons/MainMenu/UniversalRemote_14/frame_22_delay-0.04s.png new file mode 100644 index 000000000..42fda5096 Binary files /dev/null and b/assets/icons/MainMenu/UniversalRemote_14/frame_22_delay-0.04s.png differ diff --git a/assets/icons/MainMenu/UniversalRemote_14/frame_23_delay-0.04s.png b/assets/icons/MainMenu/UniversalRemote_14/frame_23_delay-0.04s.png new file mode 100644 index 000000000..17007aad5 Binary files /dev/null and b/assets/icons/MainMenu/UniversalRemote_14/frame_23_delay-0.04s.png differ diff --git a/assets/icons/MainMenu/UniversalRemote_14/frame_24_delay-0.04s.png b/assets/icons/MainMenu/UniversalRemote_14/frame_24_delay-0.04s.png new file mode 100644 index 000000000..4c03a8101 Binary files /dev/null and b/assets/icons/MainMenu/UniversalRemote_14/frame_24_delay-0.04s.png differ diff --git a/assets/icons/MainMenu/UniversalRemote_14/frame_25_delay-0.04s.png b/assets/icons/MainMenu/UniversalRemote_14/frame_25_delay-0.04s.png new file mode 100644 index 000000000..334498adc Binary files /dev/null and b/assets/icons/MainMenu/UniversalRemote_14/frame_25_delay-0.04s.png differ diff --git a/assets/icons/MainMenu/UniversalRemote_14/frame_26_delay-0.04s.png b/assets/icons/MainMenu/UniversalRemote_14/frame_26_delay-0.04s.png new file mode 100644 index 000000000..b203dc302 Binary files /dev/null and b/assets/icons/MainMenu/UniversalRemote_14/frame_26_delay-0.04s.png differ diff --git a/assets/icons/MainMenu/UniversalRemote_14/frame_27_delay-0.04s.png b/assets/icons/MainMenu/UniversalRemote_14/frame_27_delay-0.04s.png new file mode 100644 index 000000000..3e17c6c76 Binary files /dev/null and b/assets/icons/MainMenu/UniversalRemote_14/frame_27_delay-0.04s.png differ diff --git a/assets/icons/MainMenu/UniversalRemote_14/frame_28_delay-0.04s.png b/assets/icons/MainMenu/UniversalRemote_14/frame_28_delay-0.04s.png new file mode 100644 index 000000000..479fbd58b Binary files /dev/null and b/assets/icons/MainMenu/UniversalRemote_14/frame_28_delay-0.04s.png differ diff --git a/assets/icons/MainMenu/UniversalRemote_14/frame_29_delay-0.04s.png b/assets/icons/MainMenu/UniversalRemote_14/frame_29_delay-0.04s.png new file mode 100644 index 000000000..479fbd58b Binary files /dev/null and b/assets/icons/MainMenu/UniversalRemote_14/frame_29_delay-0.04s.png differ diff --git a/assets/icons/MainMenu/UniversalRemote_14/frame_rate b/assets/icons/MainMenu/UniversalRemote_14/frame_rate new file mode 100644 index 000000000..e440e5c84 --- /dev/null +++ b/assets/icons/MainMenu/UniversalRemote_14/frame_rate @@ -0,0 +1 @@ +3 \ No newline at end of file diff --git a/assets/resources/subghz/assets/setting_frequency_analyzer_user b/assets/resources/subghz/assets/setting_frequency_analyzer_user index 2c03a4022..ee75a2c83 100644 --- a/assets/resources/subghz/assets/setting_frequency_analyzer_user +++ b/assets/resources/subghz/assets/setting_frequency_analyzer_user @@ -2,18 +2,30 @@ Filetype: Flipper SubGhz Setting File Version: 1 Frequency_default: 433920000 Frequency: 300000000 +Frequency: 302757000 Frequency: 303875000 Frequency: 304250000 +Frequency: 310000000 +Frequency: 312000000 +Frequency: 313850000 +Frequency: 314000000 Frequency: 315000000 Frequency: 318000000 +Frequency: 348000000 +Frequency: 387000000 Frequency: 390000000 Frequency: 418000000 Frequency: 433075000 +Frequency: 433220000 Frequency: 433420000 +Frequency: 433889000 Frequency: 433920000 Frequency: 434420000 Frequency: 434775000 Frequency: 438900000 +Frequency: 464000000 +Frequency: 779000000 Frequency: 868350000 Frequency: 915000000 Frequency: 925000000 +Frequency: 928000000 diff --git a/assets/resources/subghz/assets/setting_user b/assets/resources/subghz/assets/setting_user index 11bd984dc..e3039e560 100644 --- a/assets/resources/subghz/assets/setting_user +++ b/assets/resources/subghz/assets/setting_user @@ -2,23 +2,37 @@ Filetype: Flipper SubGhz Setting File Version: 1 Frequency_default: 433920000 Frequency: 300000000 +Frequency: 302757000 Frequency: 303875000 Frequency: 304250000 +Frequency: 310000000 +Frequency: 312000000 +Frequency: 313850000 +Frequency: 314000000 Frequency: 315000000 Frequency: 318000000 +Frequency: 348000000 +Frequency: 387000000 Frequency: 390000000 Frequency: 418000000 Frequency: 433075000 +Frequency: 433220000 Frequency: 433420000 +Frequency: 433889000 Frequency: 433920000 Frequency: 434420000 Frequency: 434775000 Frequency: 438900000 +Frequency: 464000000 +Frequency: 779000000 Frequency: 868350000 Frequency: 915000000 Frequency: 925000000 +Frequency: 928000000 +Hopper_frequency: 312000000 +Hopper_frequency: 314000000 Hopper_frequency: 315000000 Hopper_frequency: 318000000 Hopper_frequency: 390000000 Hopper_frequency: 433920000 -Hopper_frequency: 868350000 +Hopper_frequency: 868350000 \ No newline at end of file diff --git a/assets/resources/subghz/assets/touchtunes_map b/assets/resources/subghz/assets/touchtunes_map new file mode 100644 index 000000000..2e2c6ff81 --- /dev/null +++ b/assets/resources/subghz/assets/touchtunes_map @@ -0,0 +1,7 @@ +Filetype: Flipper SubGhz RAW File +Version: 1 +UP: /any/subghz/touchtunes/brute/P2.sub +DOWN: /any/subghz/touchtunes/brute/Pause.sub +LEFT: /any/subghz/touchtunes/brute/Pwr.sub +RIGHT: /any/subghz/touchtunes/brute/P1.sub +OK: /any/subghz/touchtunes/brute/OK.sub \ No newline at end of file diff --git a/assets/resources/subghz/assets/universal_rf_map b/assets/resources/subghz/assets/universal_rf_map new file mode 100644 index 000000000..986ff9c35 --- /dev/null +++ b/assets/resources/subghz/assets/universal_rf_map @@ -0,0 +1,7 @@ +Filetype: Flipper SubGhz RAW File +Version: 1 +UP: /any/subghz/Vehicles/Tesla/Tesla_charge_door_AM270.sub +DOWN: /any/subghz/DoorbellFM.sub +LEFT: /any/subghz/Vehicles/Tesla/Tesla_charge_door_AM650.sub +RIGHT: /any/subghz/Doorbell1.sub +OK: /any/subghz/handicap_push_door.sub \ No newline at end of file diff --git a/firmware/targets/f7/target.mk b/firmware/targets/f7/target.mk index 8e58a71c9..4b019cae8 100644 --- a/firmware/targets/f7/target.mk +++ b/firmware/targets/f7/target.mk @@ -19,9 +19,8 @@ endif MCU_FLAGS = -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard # Warnings configuration -CFLAGS += -Wall -Wextra -Wredundant-decls -Wdouble-promotion +CFLAGS += $(MCU_FLAGS) -DSTM32WB55xx -Wall -fdata-sections -ffunction-sections -CFLAGS += $(MCU_FLAGS) -DSTM32WB55xx -fdata-sections -ffunction-sections -fsingle-precision-constant LDFLAGS += $(MCU_FLAGS) -specs=nosys.specs -specs=nano.specs CPPFLAGS += -fno-rtti -fno-use-cxa-atexit -fno-exceptions diff --git a/lib/toolbox/random_name.c b/lib/toolbox/random_name.c index b581bb979..cf2f8d7fb 100644 --- a/lib/toolbox/random_name.c +++ b/lib/toolbox/random_name.c @@ -3,40 +3,17 @@ #include #include #include +#include void set_random_name(char* name, uint8_t max_name_size) { - static bool rand_generator_inited = false; - - if(!rand_generator_inited) { - srand(DWT->CYCCNT); - rand_generator_inited = true; - } - const char* prefix[] = { - "ancient", - "hollow", - "strange", - "disappeared", - "unknown", - "unthinkable", - "unnamable", - "nameless", - "my", - }; - - const char* suffix[] = { - "door", - "entrance", - "doorway", - "entry", - "portal", - "entree", - "opening", - "crack", - }; - uint8_t prefix_i = rand() % COUNT_OF(prefix); - uint8_t suffix_i = rand() % COUNT_OF(suffix); - - sniprintf(name, max_name_size, "%s_%s", prefix[prefix_i], suffix[suffix_i]); + FuriHalRtcDateTime datetime; + furi_hal_rtc_get_datetime(&datetime); + char strings[1][25]; + sprintf(strings[0], "%s%.4d%.2d%.2d%.2d%.2d", "s" + , datetime.year, datetime.month, datetime.day + , datetime.hour, datetime.minute + ); + sniprintf(name, max_name_size, "%s", strings[0]); // Set first symbol to upper case name[0] = name[0] - 0x20; }