This commit is contained in:
r3df0xx 2022-05-17 15:54:09 +03:00
parent 2c5fc9ea44
commit 7fbf49d377
76 changed files with 2239 additions and 63 deletions

View File

@ -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);

View File

@ -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

View File

@ -0,0 +1,278 @@
#include <furi.h>
#include <furi_hal.h>
#include <gui/elements.h>
#include <gui/gui.h>
#include <input/input.h>
#include <notification/notification.h>
#include <notification/notification_messages.h>
#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;
}

View File

@ -0,0 +1,54 @@
#include <furi.h>
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},
}
};

View File

@ -0,0 +1,256 @@
#include <furi.h>
#include <gui/gui.h>
#include <input/input.h>
#include <stdlib.h>
#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;
}

View File

@ -0,0 +1,303 @@
#include <furi.h>
#include <gui/gui.h>
#include <input/input.h>
#include <flipper_format/flipper_format_i.h>
#include <string.h>
#include <lib/subghz/receiver.h>
#include <lib/subghz/transmitter.h>
#include <lib/subghz/subghz_file_encoder_worker.h>
#include <lib/toolbox/path.h>
#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;
}

View File

@ -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] = {

View File

@ -2,6 +2,8 @@
#include <gui/gui.h>
#include <input/input.h>
#include <stdlib.h>
#include <notification/notification.h>
#include <notification/notification_messages.h>
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;

View File

@ -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) {

View File

@ -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;

View File

@ -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);

View File

@ -1,10 +1,12 @@
#include <furi.h>
#include <furi_hal.h>
#include "../subghz_i.h"
#include "../views/subghz_read_raw.h"
#include <dolphin/dolphin.h>
#include <lib/subghz/protocols/raw.h>
#include <lib/toolbox/path.h>
#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);

View File

@ -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[] = {

View File

@ -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;
}
}

View File

@ -0,0 +1,303 @@
#include <furi.h>
#include <gui/gui.h>
#include <input/input.h>
#include <flipper_format/flipper_format_i.h>
#include <string.h>
#include <lib/subghz/receiver.h>
#include <lib/subghz/transmitter.h>
#include <lib/subghz/subghz_file_encoder_worker.h>
#include <lib/toolbox/path.h>
#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;
}

View File

@ -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;
}

View File

@ -0,0 +1,51 @@
#pragma once
#include <toolbox/stream/stream.h>
#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

View File

@ -0,0 +1,303 @@
#include <furi.h>
#include <furi_hal.h>
#include <cli/cli.h>
#include <gui/gui.h>
#include <stm32wbxx_ll_dma.h>
#include <dialogs/dialogs.h>
#include <notification/notification_messages.h>
#include <gui/view_dispatcher.h>
#include <toolbox/stream/file_stream.h>
#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;
}

View File

@ -0,0 +1,58 @@
#include "wav_player_hal.h"
#include <stm32wbxx_ll_tim.h>
#include <stm32wbxx_ll_dma.h>
#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);
}

View File

@ -0,0 +1,23 @@
#pragma once
#include <stdint.h>
#include <stddef.h>
#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

View File

@ -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;
}

View File

@ -0,0 +1,45 @@
#pragma once
#include <gui/view.h>
#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

View File

@ -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};

View File

@ -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;

Binary file not shown.

After

Width:  |  Height:  |  Size: 173 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 176 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 172 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 B

View File

@ -0,0 +1 @@
3

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 B

View File

@ -0,0 +1 @@
3

Binary file not shown.

After

Width:  |  Height:  |  Size: 470 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 411 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 411 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 411 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 401 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 397 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 400 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 404 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 414 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 427 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 427 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 426 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 431 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 424 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 424 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 424 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 424 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 426 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 418 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 419 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 425 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 415 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 405 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 394 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 401 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 401 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 404 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 410 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 411 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 411 B

View File

@ -0,0 +1 @@
3

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -3,40 +3,17 @@
#include <stdlib.h>
#include <stdbool.h>
#include <furi.h>
#include <furi_hal.h>
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;
}