[FL-140] Core api dynamic records (#296)
* SYSTEM: tickless mode with deep sleep. * Move FreeRTOS ticks to lptim2 * API: move all sumbodules init routines to one place. Timebase: working lptim2 at tick source. * API Timebase: lp-timer routines, timer access safe zones prediction and synchronization. FreeRTOS: adjust configuration for tickless mode. * NFC: support for tickless mode. * API Timebase: improve tick error handling in IRQ. Apploader: use insomnia mode to run applications. * BLE: prevent sleep while core2 starting * HAL: nap while in insomnia mode * init records work * try to implement record delete * tests and flapp * flapp subsystem * new core functions to get app stat, simplify core code * fix thread termination * add strdup to core * fix tests * Refactoring: remove all unusued parts, update API usage, aggreagate API sources and headers, new record storage * Refactoring: update furi record api usage, cleanup code * Fix broken merge for freertos apps * Core, Target: fix compilation warnings * Drop firmware target local * HAL Timebase, Power, Clock: semaphore guarded access to clock and power modes, better sleep mode. * SD-Filesystem: wait for all deps to arrive before adding widget. Core, BLE: disable debug dump to serial. * delete old app example-ipc * delete old app fatfs list * fix strobe app, add input header * delete old display driver * comment old app qr-code * fix sd-card test, add forced widget update * remove unused new core test * increase heap to 128k * comment and assert old core tests * fix syntax Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
This commit is contained in:
parent
6c4983c6b6
commit
8f9b2513ff
4
.github/CODEOWNERS
vendored
4
.github/CODEOWNERS
vendored
@ -19,10 +19,6 @@ firmware/targets/f4/api-hal/api-hal-boot.c @skotopes
|
||||
|
||||
debug/** @skotopes
|
||||
|
||||
# local target
|
||||
|
||||
firmware/targets/local/** @glitchcore
|
||||
|
||||
# BLE
|
||||
|
||||
firmware/targets/f4/ble-glue/** @skotopes
|
||||
|
10
.github/workflows/ci.yml
vendored
10
.github/workflows/ci.yml
vendored
@ -32,16 +32,6 @@ jobs:
|
||||
with:
|
||||
run: /syntax_check.sh
|
||||
|
||||
- name: Build local testing firmware in docker
|
||||
uses: ./.github/actions/docker
|
||||
with:
|
||||
run: make -C firmware TARGET=local
|
||||
|
||||
- name: Run local tests
|
||||
uses: ./.github/actions/docker
|
||||
with:
|
||||
run: make -C firmware TARGET=local APP_TEST=1 run
|
||||
|
||||
- name: Build F4 bootloader in docker
|
||||
uses: ./.github/actions/docker
|
||||
with:
|
||||
|
@ -25,14 +25,7 @@ Flipper Zero's firmware consists of two components: Bootloader and main firmware
|
||||
|
||||
## Build from source
|
||||
|
||||
You can run firmware locally (with HAL stub):
|
||||
|
||||
* `docker-compose exec dev make -C firmware TARGET=local APP_TEST=1 run` for running tests
|
||||
* `docker-compose exec dev make -C firmware TARGET=local APP_*=1 run` for running examples (see `applications/applications.mk` for list of applications/examples)
|
||||
|
||||
Or on your flipper:
|
||||
|
||||
`docker-compose exec dev make -C firmware TARGET=f4 APP_*=1 flash` for build and flash dev board (see `applications/applications.mk` for list of applications/examples)
|
||||
`docker-compose exec dev make -C firmware TARGET=f4 APP_RELEASE=1 flash` for build and flash dev board (see `applications/applications.mk` for list of applications/examples)
|
||||
|
||||
# Links
|
||||
* Task tracker: [Jira](https://flipperzero.atlassian.net/)
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "flipper_v2.h"
|
||||
#include <furi.h>
|
||||
#include <cli/cli.h>
|
||||
#include <gui/gui.h>
|
||||
#include "menu/menu.h"
|
||||
@ -8,14 +8,15 @@
|
||||
#include <api-hal.h>
|
||||
|
||||
typedef struct {
|
||||
FuriApp* handler;
|
||||
osThreadAttr_t app_thread_attr;
|
||||
osThreadId_t app_thread_id;
|
||||
Widget* widget;
|
||||
const FlipperStartupApp* current_app;
|
||||
const FuriApplication* current_app;
|
||||
} AppLoaderState;
|
||||
|
||||
typedef struct {
|
||||
AppLoaderState* state;
|
||||
const FlipperStartupApp* app;
|
||||
const FuriApplication* app;
|
||||
} AppLoaderContext;
|
||||
|
||||
// TODO add mutex for contex
|
||||
@ -36,7 +37,7 @@ static void input_callback(InputEvent* input_event, void* _ctx) {
|
||||
AppLoaderState* ctx = (AppLoaderState*)_ctx;
|
||||
|
||||
if(input_event->state && input_event->input == InputBack) {
|
||||
furiac_kill(ctx->handler);
|
||||
osThreadTerminate(ctx->app_thread_id);
|
||||
widget_enabled_set(ctx->widget, false);
|
||||
api_hal_timebase_insomnia_exit();
|
||||
}
|
||||
@ -54,7 +55,16 @@ static void handle_menu(void* _ctx) {
|
||||
api_hal_timebase_insomnia_enter();
|
||||
|
||||
ctx->state->current_app = ctx->app;
|
||||
ctx->state->handler = furiac_start(ctx->app->app, ctx->app->name, NULL);
|
||||
ctx->state->app_thread_attr.name = ctx->app->name;
|
||||
ctx->state->app_thread_attr.attr_bits = osThreadDetached;
|
||||
ctx->state->app_thread_attr.cb_mem = NULL;
|
||||
ctx->state->app_thread_attr.cb_size = 0;
|
||||
ctx->state->app_thread_attr.stack_mem = NULL;
|
||||
ctx->state->app_thread_attr.stack_size = 1024;
|
||||
ctx->state->app_thread_attr.priority = osPriorityNormal;
|
||||
ctx->state->app_thread_attr.tz_module = 0;
|
||||
ctx->state->app_thread_attr.reserved = 0;
|
||||
ctx->state->app_thread_id = osThreadNew(ctx->app->app, NULL, &ctx->state->app_thread_attr);
|
||||
}
|
||||
|
||||
static void handle_cli(string_t args, void* _ctx) {
|
||||
@ -65,13 +75,22 @@ static void handle_cli(string_t args, void* _ctx) {
|
||||
cli_print("Starting furi application\r\n");
|
||||
|
||||
ctx->state->current_app = ctx->app;
|
||||
ctx->state->handler = furiac_start(ctx->app->app, ctx->app->name, NULL);
|
||||
ctx->state->app_thread_attr.name = ctx->app->name;
|
||||
ctx->state->app_thread_attr.attr_bits = osThreadDetached;
|
||||
ctx->state->app_thread_attr.cb_mem = NULL;
|
||||
ctx->state->app_thread_attr.cb_size = 0;
|
||||
ctx->state->app_thread_attr.stack_mem = NULL;
|
||||
ctx->state->app_thread_attr.stack_size = 1024;
|
||||
ctx->state->app_thread_attr.priority = osPriorityNormal;
|
||||
ctx->state->app_thread_attr.tz_module = 0;
|
||||
ctx->state->app_thread_attr.reserved = 0;
|
||||
ctx->state->app_thread_id = osThreadNew(ctx->app->app, NULL, &ctx->state->app_thread_attr);
|
||||
|
||||
cli_print("Press any key to kill application");
|
||||
|
||||
char c;
|
||||
cli_read(&c, 1);
|
||||
furiac_kill(ctx->state->handler);
|
||||
osThreadTerminate(ctx->state->app_thread_id);
|
||||
}
|
||||
|
||||
void app_loader(void* p) {
|
||||
@ -79,37 +98,23 @@ void app_loader(void* p) {
|
||||
furi_check(self_id);
|
||||
|
||||
AppLoaderState state;
|
||||
state.handler = NULL;
|
||||
state.app_thread_id = NULL;
|
||||
|
||||
state.widget = widget_alloc();
|
||||
widget_enabled_set(state.widget, false);
|
||||
widget_draw_callback_set(state.widget, render_callback, &state);
|
||||
widget_input_callback_set(state.widget, input_callback, &state);
|
||||
|
||||
ValueMutex* menu_mutex = furi_open("menu");
|
||||
if(menu_mutex == NULL) {
|
||||
printf("menu is not available\n");
|
||||
furiac_exit(NULL);
|
||||
}
|
||||
ValueMutex* menu_mutex = furi_record_open("menu");
|
||||
Cli* cli = furi_record_open("cli");
|
||||
Gui* gui = furi_record_open("gui");
|
||||
|
||||
Cli* cli = furi_open("cli");
|
||||
|
||||
// Open GUI and register widget
|
||||
Gui* gui = furi_open("gui");
|
||||
if(gui == NULL) {
|
||||
printf("gui is not available\n");
|
||||
furiac_exit(NULL);
|
||||
}
|
||||
gui_add_widget(gui, state.widget, GuiLayerFullscreen);
|
||||
|
||||
// FURI startup
|
||||
const size_t flipper_app_count = sizeof(FLIPPER_APPS) / sizeof(FLIPPER_APPS[0]);
|
||||
const size_t flipper_plugins_count = sizeof(FLIPPER_PLUGINS) / sizeof(FLIPPER_PLUGINS[0]);
|
||||
|
||||
// Main menu
|
||||
with_value_mutex(
|
||||
menu_mutex, (Menu * menu) {
|
||||
for(size_t i = 0; i < flipper_app_count; i++) {
|
||||
for(size_t i = 0; i < FLIPPER_APPS_size(); i++) {
|
||||
AppLoaderContext* ctx = furi_alloc(sizeof(AppLoaderContext));
|
||||
ctx->state = &state;
|
||||
ctx->app = &FLIPPER_APPS[i];
|
||||
@ -123,13 +128,11 @@ void app_loader(void* p) {
|
||||
ctx));
|
||||
|
||||
// Add cli command
|
||||
if(cli) {
|
||||
string_t cli_name;
|
||||
string_init_set_str(cli_name, "app_");
|
||||
string_cat_str(cli_name, FLIPPER_APPS[i].name);
|
||||
cli_add_command(cli, string_get_cstr(cli_name), handle_cli, ctx);
|
||||
string_clear(cli_name);
|
||||
}
|
||||
string_t cli_name;
|
||||
string_init_set_str(cli_name, "app_");
|
||||
string_cat_str(cli_name, FLIPPER_APPS[i].name);
|
||||
cli_add_command(cli, string_get_cstr(cli_name), handle_cli, ctx);
|
||||
string_clear(cli_name);
|
||||
}
|
||||
});
|
||||
|
||||
@ -157,7 +160,7 @@ void app_loader(void* p) {
|
||||
MenuItem* menu_plugins =
|
||||
menu_item_alloc_menu("Plugins", assets_icons_get(A_Plugins_14));
|
||||
|
||||
for(size_t i = 0; i < flipper_plugins_count; i++) {
|
||||
for(size_t i = 0; i < FLIPPER_PLUGINS_size(); i++) {
|
||||
AppLoaderContext* ctx = furi_alloc(sizeof(AppLoaderContext));
|
||||
ctx->state = &state;
|
||||
ctx->app = &FLIPPER_PLUGINS[i];
|
||||
@ -171,13 +174,11 @@ void app_loader(void* p) {
|
||||
ctx));
|
||||
|
||||
// Add cli command
|
||||
if(cli) {
|
||||
string_t cli_name;
|
||||
string_init_set_str(cli_name, "app_");
|
||||
string_cat_str(cli_name, FLIPPER_PLUGINS[i].name);
|
||||
cli_add_command(cli, string_get_cstr(cli_name), handle_cli, ctx);
|
||||
string_clear(cli_name);
|
||||
}
|
||||
string_t cli_name;
|
||||
string_init_set_str(cli_name, "app_");
|
||||
string_cat_str(cli_name, FLIPPER_PLUGINS[i].name);
|
||||
cli_add_command(cli, string_get_cstr(cli_name), handle_cli, ctx);
|
||||
string_clear(cli_name);
|
||||
}
|
||||
|
||||
menu_item_add(menu, menu_plugins);
|
||||
@ -186,4 +187,4 @@ void app_loader(void* p) {
|
||||
printf("[app loader] start\n");
|
||||
|
||||
osThreadSuspend(self_id);
|
||||
}
|
||||
}
|
||||
|
220
applications/applications.c
Normal file
220
applications/applications.c
Normal file
@ -0,0 +1,220 @@
|
||||
#include "applications.h"
|
||||
|
||||
#ifdef APP_TEST
|
||||
void flipper_test_app(void* p);
|
||||
#endif
|
||||
|
||||
void application_blink(void* p);
|
||||
void application_uart_write(void* p);
|
||||
void application_ipc_display(void* p);
|
||||
void application_ipc_widget(void* p);
|
||||
void application_input_dump(void* p);
|
||||
void display_u8g2(void* p);
|
||||
void u8g2_example(void* p);
|
||||
void input_task(void* p);
|
||||
void menu_task(void* p);
|
||||
void coreglitch_demo_0(void* p);
|
||||
void u8g2_qrcode(void* p);
|
||||
void fatfs_list(void* p);
|
||||
void gui_task(void* p);
|
||||
void backlight_control(void* p);
|
||||
void irda(void* p);
|
||||
void app_loader(void* p);
|
||||
void cc1101_workaround(void* p);
|
||||
void lf_rfid_workaround(void* p);
|
||||
void nfc_task(void* p);
|
||||
void dolphin_task(void* p);
|
||||
void power_task(void* p);
|
||||
void bt_task(void* p);
|
||||
void sd_card_test(void* p);
|
||||
void application_vibro(void* p);
|
||||
void app_gpio_test(void* p);
|
||||
void app_ibutton(void* p);
|
||||
void cli_task(void* p);
|
||||
void music_player(void* p);
|
||||
void sdnfc(void* p);
|
||||
void floopper_bloopper(void* p);
|
||||
void sd_filesystem(void* p);
|
||||
|
||||
const FuriApplication FLIPPER_SERVICES[] = {
|
||||
#ifdef APP_DISPLAY
|
||||
{.app = display_u8g2, .name = "display_u8g2", .icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_CLI
|
||||
{.app = cli_task, .name = "cli_task", .icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_EXAMPLE_BLINK
|
||||
{.app = application_blink, .name = "blink", .icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_INPUT
|
||||
{.app = input_task, .name = "input_task", .icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_EXAMPLE_INPUT_DUMP
|
||||
{.app = application_input_dump, .name = "input dump", .icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_GUI
|
||||
{.app = backlight_control, .name = "backlight_control", .icon = A_Plugins_14},
|
||||
{.app = gui_task, .name = "gui_task", .icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_MENU
|
||||
{.app = menu_task, .name = "menu_task", .icon = A_Plugins_14},
|
||||
{.app = app_loader, .name = "app_loader", .icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_SD_FILESYSTEM
|
||||
{.app = sd_filesystem, .name = "sd_filesystem", .icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_DOLPHIN
|
||||
{.app = dolphin_task, .name = "dolphin_task", .icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_POWER
|
||||
{.app = power_task, .name = "power_task", .icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_BT
|
||||
{.app = bt_task, .name = "bt_task", .icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_CC1101
|
||||
{.app = cc1101_workaround, .name = "cc1101 workaround", .icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_LF_RFID
|
||||
{.app = lf_rfid_workaround, .name = "lf rfid workaround", .icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_IRDA
|
||||
{.app = irda, .name = "irda", .icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_NFC
|
||||
{.app = nfc_task, .name = "nfc_task", .icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_TEST
|
||||
{.app = flipper_test_app, .name = "test app", .icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_EXAMPLE_IPC
|
||||
{.app = application_ipc_display, .name = "ipc display", .icon = A_Plugins_14},
|
||||
{.app = application_ipc_widget, .name = "ipc widget", .icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_EXAMPLE_QRCODE
|
||||
{.app = u8g2_qrcode, .name = "u8g2_qrcode", .icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_EXAMPLE_FATFS
|
||||
{.app = fatfs_list, .name = "fatfs_list", .icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_EXAMPLE_DISPLAY
|
||||
{.app = u8g2_example, .name = "u8g2_example", .icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_SPEAKER_DEMO
|
||||
{.app = coreglitch_demo_0, .name = "coreglitch_demo_0", .icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_SD_TEST
|
||||
{.app = sd_card_test, .name = "sd_card_test", .icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_MUSIC_PLAYER
|
||||
{.app = music_player, .name = "music player", .icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_IBUTTON
|
||||
{.app = app_ibutton, .name = "ibutton", .icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_GPIO_DEMO
|
||||
{.app = app_gpio_test, .name = "gpio test", .icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_FLOOPPER_BLOOPPER
|
||||
{.app = floopper_bloopper, .name = "Floopper Bloopper", .icon = A_Games_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_SDNFC
|
||||
{.app = sdnfc, .name = "sdnfc", .icon = A_Plugins_14},
|
||||
#endif
|
||||
};
|
||||
|
||||
size_t FLIPPER_SERVICES_size() {
|
||||
return sizeof(FLIPPER_SERVICES) / sizeof(FuriApplication);
|
||||
}
|
||||
|
||||
// Main menu APP
|
||||
const FuriApplication FLIPPER_APPS[] = {
|
||||
#ifdef BUILD_CC1101
|
||||
{.app = cc1101_workaround, .name = "Sub-1 GHz", .icon = A_Sub1ghz_14},
|
||||
#endif
|
||||
|
||||
#ifdef BUILD_LF_RFID
|
||||
{.app = lf_rfid_workaround, .name = "125 kHz RFID", .icon = A_125khz_14},
|
||||
#endif
|
||||
|
||||
#ifdef BUILD_IRDA
|
||||
{.app = irda, .name = "Infrared", .icon = A_Infrared_14},
|
||||
#endif
|
||||
|
||||
#ifdef BUILD_IBUTTON
|
||||
{.app = app_ibutton, .name = "iButton", .icon = A_iButton_14},
|
||||
#endif
|
||||
|
||||
#ifdef BUILD_GPIO_DEMO
|
||||
{.app = app_gpio_test, .name = "GPIO", .icon = A_GPIO_14},
|
||||
#endif
|
||||
};
|
||||
|
||||
size_t FLIPPER_APPS_size() {
|
||||
return sizeof(FLIPPER_APPS) / sizeof(FuriApplication);
|
||||
}
|
||||
|
||||
// Plugin menu
|
||||
const FuriApplication FLIPPER_PLUGINS[] = {
|
||||
#ifdef BUILD_EXAMPLE_BLINK
|
||||
{.app = application_blink, .name = "blink", .icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef BUILD_EXAMPLE_INPUT_DUMP
|
||||
{.app = application_input_dump, .name = "input dump", .icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef BUILD_SPEAKER_DEMO
|
||||
{.app = coreglitch_demo_0, .name = "coreglitch_demo_0", .icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef BUILD_SD_TEST
|
||||
{.app = sd_card_test, .name = "sd_card_test", .icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef BUILD_VIBRO_DEMO
|
||||
{.app = application_vibro, .name = "application_vibro", .icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef BUILD_MUSIC_PLAYER
|
||||
{.app = music_player, .name = "music player", .icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef BUILD_FLOOPPER_BLOOPPER
|
||||
{.app = floopper_bloopper, .name = "Floopper Bloopper", .icon = A_Games_14},
|
||||
#endif
|
||||
|
||||
#ifdef BUILD_SDNFC
|
||||
{.app = sdnfc, .name = "sdnfc", .icon = A_Plugins_14},
|
||||
#endif
|
||||
};
|
||||
|
||||
size_t FLIPPER_PLUGINS_size() {
|
||||
return sizeof(FLIPPER_PLUGINS) / sizeof(FuriApplication);
|
||||
}
|
@ -1,296 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include "flipper.h"
|
||||
#include <furi.h>
|
||||
#include <assets_icons.h>
|
||||
|
||||
#ifdef APP_TEST
|
||||
void flipper_test_app(void* p);
|
||||
#endif
|
||||
typedef void (*FlipperApplication)(void*);
|
||||
|
||||
void application_blink(void* p);
|
||||
void application_uart_write(void* p);
|
||||
void application_ipc_display(void* p);
|
||||
void application_ipc_widget(void* p);
|
||||
void application_input_dump(void* p);
|
||||
typedef struct {
|
||||
const FlipperApplication app;
|
||||
const char* name;
|
||||
const IconName icon;
|
||||
} FuriApplication;
|
||||
|
||||
void display_u8g2(void* p);
|
||||
extern const FuriApplication FLIPPER_SERVICES[];
|
||||
size_t FLIPPER_SERVICES_size();
|
||||
|
||||
void u8g2_example(void* p);
|
||||
extern const FuriApplication FLIPPER_APPS[];
|
||||
size_t FLIPPER_APPS_size();
|
||||
|
||||
void input_task(void* p);
|
||||
void menu_task(void* p);
|
||||
|
||||
void coreglitch_demo_0(void* p);
|
||||
|
||||
void u8g2_qrcode(void* p);
|
||||
void fatfs_list(void* p);
|
||||
void gui_task(void* p);
|
||||
void backlight_control(void* p);
|
||||
void irda(void* p);
|
||||
void app_loader(void* p);
|
||||
void cc1101_workaround(void* p);
|
||||
void lf_rfid_workaround(void* p);
|
||||
void nfc_task(void* p);
|
||||
void dolphin_task(void* p);
|
||||
void power_task(void* p);
|
||||
void bt_task(void* p);
|
||||
void sd_card_test(void* p);
|
||||
void application_vibro(void* p);
|
||||
void app_gpio_test(void* p);
|
||||
void app_ibutton(void* p);
|
||||
void cli_task(void* p);
|
||||
void music_player(void* p);
|
||||
void sdnfc(void* p);
|
||||
void floopper_bloopper(void* p);
|
||||
void sd_filesystem(void* p);
|
||||
|
||||
const FlipperStartupApp FLIPPER_STARTUP[] = {
|
||||
#ifdef APP_DISPLAY
|
||||
{.app = display_u8g2, .name = "display_u8g2", .libs = {0}, .icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_CLI
|
||||
{.app = cli_task, .name = "cli_task", .libs = {0}, .icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_EXAMPLE_BLINK
|
||||
{.app = application_blink,
|
||||
.name = "blink",
|
||||
.libs = {1, FURI_LIB{"input_task"}},
|
||||
.icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_INPUT
|
||||
{.app = input_task, .name = "input_task", .libs = {0}, .icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_EXAMPLE_INPUT_DUMP
|
||||
{.app = application_input_dump,
|
||||
.name = "input dump",
|
||||
.libs = {1, FURI_LIB{"input_task"}},
|
||||
.icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_GUI
|
||||
{.app = backlight_control,
|
||||
.name = "backlight_control",
|
||||
.libs = {1, FURI_LIB{"input_task"}},
|
||||
.icon = A_Plugins_14},
|
||||
{.app = gui_task, .name = "gui_task", .libs = {0}, .icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_MENU
|
||||
{.app = menu_task,
|
||||
.name = "menu_task",
|
||||
.libs = {1, FURI_LIB{"gui_task"}},
|
||||
.icon = A_Plugins_14},
|
||||
{.app = app_loader,
|
||||
.name = "app_loader",
|
||||
.libs = {2, FURI_LIB{"menu_task", "cli_task"}},
|
||||
.icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_SD_FILESYSTEM
|
||||
{.app = sd_filesystem,
|
||||
.name = "sd_filesystem",
|
||||
.libs = {1, FURI_LIB{"menu_task"}},
|
||||
.icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_DOLPHIN
|
||||
{.app = dolphin_task,
|
||||
.name = "dolphin_task",
|
||||
.libs = {1, FURI_LIB{"menu_task"}},
|
||||
.icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_POWER
|
||||
{.app = power_task,
|
||||
.name = "power_task",
|
||||
.libs = {2, FURI_LIB{"cli_task", "gui_task"}},
|
||||
.icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_BT
|
||||
{.app = bt_task, .name = "bt_task", .libs = {1, FURI_LIB{"cli_task"}}, .icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_CC1101
|
||||
{.app = cc1101_workaround,
|
||||
.name = "cc1101 workaround",
|
||||
.libs = {1, FURI_LIB{"gui_task"}},
|
||||
.icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_LF_RFID
|
||||
{.app = lf_rfid_workaround,
|
||||
.name = "lf rfid workaround",
|
||||
.libs = {1, FURI_LIB{"gui_task"}},
|
||||
.icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_IRDA
|
||||
{.app = irda, .name = "irda", .libs = {1, FURI_LIB{"gui_task"}}, .icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_NFC
|
||||
{.app = nfc_task, .name = "nfc_task", .libs = {1, FURI_LIB{"menu_task"}}, .icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_TEST
|
||||
{.app = flipper_test_app, .name = "test app", .libs = {0}, .icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_EXAMPLE_IPC
|
||||
{.app = application_ipc_display, .name = "ipc display", .libs = {0}, .icon = A_Plugins_14},
|
||||
{.app = application_ipc_widget, .name = "ipc widget", .libs = {0}, .icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_EXAMPLE_QRCODE
|
||||
{.app = u8g2_qrcode,
|
||||
.name = "u8g2_qrcode",
|
||||
.libs = {1, FURI_LIB{"display_u8g2"}},
|
||||
.icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_EXAMPLE_FATFS
|
||||
{.app = fatfs_list,
|
||||
.name = "fatfs_list",
|
||||
.libs = {2, FURI_LIB{"display_u8g2", "input_task"}},
|
||||
.icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_EXAMPLE_DISPLAY
|
||||
{.app = u8g2_example,
|
||||
.name = "u8g2_example",
|
||||
.libs = {1, FURI_LIB{"display_u8g2"}},
|
||||
.icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_SPEAKER_DEMO
|
||||
{.app = coreglitch_demo_0, .name = "coreglitch_demo_0", .libs = {0}, .icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_SD_TEST
|
||||
{.app = sd_card_test,
|
||||
.name = "sd_card_test",
|
||||
.libs = {2, FURI_LIB{"gui_task", "sd_filesystem"}},
|
||||
.icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_MUSIC_PLAYER
|
||||
{.app = music_player,
|
||||
.name = "music player",
|
||||
.libs = {1, FURI_LIB{"gui_task"}},
|
||||
.icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_IBUTTON
|
||||
{.app = app_ibutton,
|
||||
.name = "ibutton",
|
||||
.libs = {1, FURI_LIB{"gui_task"}},
|
||||
.icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_GPIO_DEMO
|
||||
{.app = app_gpio_test,
|
||||
.name = "gpio test",
|
||||
.libs = {1, FURI_LIB{"gui_task"}},
|
||||
.icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_FLOOPPER_BLOOPPER
|
||||
{.app = floopper_bloopper,
|
||||
.name = "Floopper Bloopper",
|
||||
.libs = {1, FURI_LIB{"gui_task"}},
|
||||
.icon = A_Games_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_SDNFC
|
||||
{.app = sdnfc, .name = "sdnfc", .libs = {1, FURI_LIB{"gui_task"}}, .icon = A_Plugins_14},
|
||||
#endif
|
||||
};
|
||||
|
||||
// Main menu APP
|
||||
const FlipperStartupApp FLIPPER_APPS[] = {
|
||||
#ifdef BUILD_CC1101
|
||||
{.app = cc1101_workaround,
|
||||
.name = "Sub-1 GHz",
|
||||
.libs = {1, FURI_LIB{"gui_task"}},
|
||||
.icon = A_Sub1ghz_14},
|
||||
#endif
|
||||
|
||||
#ifdef BUILD_LF_RFID
|
||||
{.app = lf_rfid_workaround,
|
||||
.name = "125 kHz RFID",
|
||||
.libs = {1, FURI_LIB{"gui_task"}},
|
||||
.icon = A_125khz_14},
|
||||
#endif
|
||||
|
||||
#ifdef BUILD_IRDA
|
||||
{.app = irda, .name = "Infrared", .libs = {1, FURI_LIB{"gui_task"}}, .icon = A_Infrared_14},
|
||||
#endif
|
||||
|
||||
#ifdef BUILD_IBUTTON
|
||||
{.app = app_ibutton,
|
||||
.name = "iButton",
|
||||
.libs = {1, FURI_LIB{"gui_task"}},
|
||||
.icon = A_iButton_14},
|
||||
#endif
|
||||
|
||||
#ifdef BUILD_GPIO_DEMO
|
||||
{.app = app_gpio_test, .name = "GPIO", .libs = {1, FURI_LIB{"gui_task"}}, .icon = A_GPIO_14},
|
||||
#endif
|
||||
};
|
||||
|
||||
// Plugin menu
|
||||
const FlipperStartupApp FLIPPER_PLUGINS[] = {
|
||||
#ifdef BUILD_EXAMPLE_BLINK
|
||||
{.app = application_blink,
|
||||
.name = "blink",
|
||||
.libs = {1, FURI_LIB{"input_task"}},
|
||||
.icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef BUILD_EXAMPLE_INPUT_DUMP
|
||||
{.app = application_input_dump,
|
||||
.name = "input dump",
|
||||
.libs = {1, FURI_LIB{"input_task"}},
|
||||
.icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef BUILD_SPEAKER_DEMO
|
||||
{.app = coreglitch_demo_0, .name = "coreglitch_demo_0", .libs = {0}, .icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef BUILD_SD_TEST
|
||||
{.app = sd_card_test,
|
||||
.name = "sd_card_test",
|
||||
.libs = {2, FURI_LIB{"gui_task", "sd_filesystem"}},
|
||||
.icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef BUILD_VIBRO_DEMO
|
||||
{.app = application_vibro,
|
||||
.name = "application_vibro",
|
||||
.libs = {1, FURI_LIB{"input_task"}},
|
||||
.icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef BUILD_MUSIC_PLAYER
|
||||
{.app = music_player,
|
||||
.name = "music player",
|
||||
.libs = {1, FURI_LIB{"gui_task"}},
|
||||
.icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef BUILD_FLOOPPER_BLOOPPER
|
||||
{.app = floopper_bloopper,
|
||||
.name = "Floopper Bloopper",
|
||||
.libs = {1, FURI_LIB{"gui_task"}},
|
||||
.icon = A_Games_14},
|
||||
#endif
|
||||
|
||||
#ifdef BUILD_SDNFC
|
||||
{.app = sdnfc, .name = "sdnfc", .libs = {1, FURI_LIB{"gui_task"}}, .icon = A_Plugins_14},
|
||||
#endif
|
||||
};
|
||||
extern const FuriApplication FLIPPER_PLUGINS[];
|
||||
size_t FLIPPER_PLUGINS_size();
|
||||
|
@ -2,6 +2,7 @@ APP_DIR = $(PROJECT_ROOT)/applications
|
||||
LIB_DIR = $(PROJECT_ROOT)/lib
|
||||
|
||||
CFLAGS += -I$(APP_DIR)
|
||||
C_SOURCES += $(APP_DIR)/applications.c
|
||||
|
||||
# Use APP_* for autostart app
|
||||
# Use BUILD_* for add app to build
|
||||
|
@ -1,11 +1,12 @@
|
||||
#include "flipper_v2.h"
|
||||
#include <furi.h>
|
||||
|
||||
#define BACKLIGHT_TIME 10000
|
||||
#define BACKLIGHT_FLAG_ACTIVITY 0x00000001U
|
||||
|
||||
static void event_cb(const void* value, void* ctx) {
|
||||
xSemaphoreGive((SemaphoreHandle_t*)ctx);
|
||||
osThreadFlagsSet((osThreadId_t)ctx, BACKLIGHT_FLAG_ACTIVITY);
|
||||
}
|
||||
|
||||
const uint32_t BACKLIGHT_TIME = 10000;
|
||||
|
||||
void backlight_control(void* p) {
|
||||
// TODO open record
|
||||
const GpioPin* backlight_record = &backlight_gpio;
|
||||
@ -14,20 +15,14 @@ void backlight_control(void* p) {
|
||||
gpio_init(backlight_record, GpioModeOutputPushPull);
|
||||
gpio_write(backlight_record, true);
|
||||
|
||||
StaticSemaphore_t event_descriptor;
|
||||
SemaphoreHandle_t update = xSemaphoreCreateCountingStatic(255, 0, &event_descriptor);
|
||||
|
||||
// open record
|
||||
PubSub* event_record = furi_open("input_events");
|
||||
furi_check(event_record);
|
||||
subscribe_pubsub(event_record, event_cb, (void*)update);
|
||||
|
||||
// we ready to work
|
||||
furiac_ready();
|
||||
PubSub* event_record = furi_record_open("input_events");
|
||||
subscribe_pubsub(event_record, event_cb, (void*)osThreadGetId());
|
||||
|
||||
while(1) {
|
||||
// wait for event
|
||||
if(xSemaphoreTake(update, BACKLIGHT_TIME) == pdTRUE) {
|
||||
if(osThreadFlagsWait(BACKLIGHT_FLAG_ACTIVITY, osFlagsWaitAny, BACKLIGHT_TIME) ==
|
||||
BACKLIGHT_FLAG_ACTIVITY) {
|
||||
gpio_write(backlight_record, true);
|
||||
} else {
|
||||
gpio_write(backlight_record, false);
|
||||
|
@ -2,16 +2,23 @@
|
||||
|
||||
Bt* bt_alloc() {
|
||||
Bt* bt = furi_alloc(sizeof(Bt));
|
||||
bt->cli = furi_open("cli");
|
||||
|
||||
bt->cli = furi_record_open("cli");
|
||||
cli_add_command(bt->cli, "bt_info", bt_cli_info, bt);
|
||||
bt->gui = furi_record_open("gui");
|
||||
bt->menu = furi_record_open("menu");
|
||||
|
||||
bt->statusbar_icon = assets_icons_get(I_Bluetooth_5x8);
|
||||
bt->statusbar_widget = widget_alloc();
|
||||
widget_set_width(bt->statusbar_widget, icon_get_width(bt->statusbar_icon));
|
||||
widget_draw_callback_set(bt->statusbar_widget, bt_draw_statusbar_callback, bt);
|
||||
widget_enabled_set(bt->statusbar_widget, false);
|
||||
gui_add_widget(bt->gui, bt->statusbar_widget, GuiLayerStatusBarLeft);
|
||||
|
||||
bt->menu_icon = assets_icons_get(A_Bluetooth_14);
|
||||
bt->menu_item = menu_item_alloc_menu("Bluetooth", bt->menu_icon);
|
||||
with_value_mutex(
|
||||
bt->menu, (Menu * menu) { menu_item_add(menu, bt->menu_item); });
|
||||
|
||||
return bt;
|
||||
}
|
||||
@ -33,23 +40,7 @@ void bt_cli_info(string_t args, void* context) {
|
||||
void bt_task() {
|
||||
Bt* bt = bt_alloc();
|
||||
|
||||
if(bt->cli) {
|
||||
cli_add_command(bt->cli, "bt_info", bt_cli_info, bt);
|
||||
}
|
||||
|
||||
// TODO: add ValueMutex(bt) to "bt" record
|
||||
if(!furi_create("bt", bt)) {
|
||||
printf("[bt_task] unable to create bt record\n");
|
||||
furiac_exit(NULL);
|
||||
}
|
||||
|
||||
Gui* gui = furi_open("gui");
|
||||
gui_add_widget(gui, bt->statusbar_widget, GuiLayerStatusBarLeft);
|
||||
|
||||
with_value_mutex(
|
||||
furi_open("menu"), (Menu * menu) { menu_item_add(menu, bt->menu_item); });
|
||||
|
||||
furiac_ready();
|
||||
furi_record_create("bt", bt);
|
||||
|
||||
api_hal_bt_init();
|
||||
|
||||
|
@ -2,10 +2,9 @@
|
||||
|
||||
#include "bt.h"
|
||||
|
||||
#include <cli/cli.h>
|
||||
#include <furi.h>
|
||||
|
||||
#include <flipper.h>
|
||||
#include <flipper_v2.h>
|
||||
#include <cli/cli.h>
|
||||
|
||||
#include <gui/gui.h>
|
||||
#include <gui/widget.h>
|
||||
@ -15,6 +14,8 @@
|
||||
|
||||
typedef struct {
|
||||
Cli* cli;
|
||||
Gui* gui;
|
||||
ValueMutex* menu;
|
||||
// Status bar
|
||||
Icon* statusbar_icon;
|
||||
Widget* statusbar_widget;
|
||||
@ -26,3 +27,7 @@ typedef struct {
|
||||
Bt* bt_alloc();
|
||||
|
||||
void bt_draw_statusbar_callback(Canvas* canvas, void* context);
|
||||
|
||||
void bt_cli_info(string_t args, void* context);
|
||||
|
||||
void bt_draw_statusbar_callback(Canvas* canvas, void* context);
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "flipper.h"
|
||||
|
||||
#include "cc1101-workaround/cc1101.h"
|
||||
#include "cc1101.h"
|
||||
#include <furi.h>
|
||||
#include <gui/gui.h>
|
||||
#include <input/input.h>
|
||||
|
||||
extern "C" void cli_print(const char* str);
|
||||
|
||||
@ -335,7 +336,7 @@ static void render_callback(Canvas* canvas, void* ctx) {
|
||||
}
|
||||
|
||||
static void input_callback(InputEvent* input_event, void* ctx) {
|
||||
osMessageQueueId_t event_queue = (QueueHandle_t)ctx;
|
||||
osMessageQueueId_t event_queue = ctx;
|
||||
|
||||
AppEvent event;
|
||||
event.type = EventTypeKey;
|
||||
@ -370,7 +371,7 @@ extern "C" void cc1101_workaround(void* p) {
|
||||
widget_input_callback_set(widget, input_callback, event_queue);
|
||||
|
||||
// Open GUI and register widget
|
||||
Gui* gui = (Gui*)furi_open("gui");
|
||||
Gui* gui = (Gui*)furi_record_open("gui");
|
||||
if(gui == NULL) {
|
||||
printf("[cc1101] gui is not available\n");
|
||||
furiac_exit(NULL);
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "flipper_v2.h"
|
||||
#include <furi.h>
|
||||
#include "cc1101-workaround/cc1101.h"
|
||||
#include "spi.h"
|
||||
#include <math.h>
|
||||
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "flipper_v2.h"
|
||||
#include <furi.h>
|
||||
|
||||
#define F_OSC 26e6
|
||||
|
||||
|
@ -1,8 +1,6 @@
|
||||
#include "cli_i.h"
|
||||
#include "cli_commands.h"
|
||||
|
||||
#include <api-hal-vcp.h>
|
||||
|
||||
Cli* cli_alloc() {
|
||||
Cli* cli = furi_alloc(sizeof(Cli));
|
||||
CliCommandDict_init(cli->commands);
|
||||
@ -175,12 +173,7 @@ void cli_task(void* p) {
|
||||
// Init basic cli commands
|
||||
cli_commands_init(cli);
|
||||
|
||||
if(!furi_create("cli", cli)) {
|
||||
printf("[cli_task] cannot create the cli record\n");
|
||||
furiac_exit(NULL);
|
||||
}
|
||||
|
||||
furiac_ready();
|
||||
furi_record_create("cli", cli);
|
||||
|
||||
while(1) {
|
||||
cli_process_input(cli);
|
||||
|
@ -2,8 +2,7 @@
|
||||
|
||||
#include "cli.h"
|
||||
|
||||
#include <flipper.h>
|
||||
#include <flipper_v2.h>
|
||||
#include <furi.h>
|
||||
|
||||
#include <m-dict.h>
|
||||
|
||||
|
@ -1,12 +1,10 @@
|
||||
#include "flipper.h"
|
||||
#include <furi.h>
|
||||
#include "u8g2/u8g2.h"
|
||||
|
||||
extern TIM_HandleTypeDef SPEAKER_TIM;
|
||||
|
||||
void coreglitch_demo_0(void* p) {
|
||||
FuriRecordSubscriber* log = get_default_log();
|
||||
|
||||
fuprintf(log, "coreglitch demo!\n");
|
||||
printf("coreglitch demo!\n");
|
||||
|
||||
float notes[] = {
|
||||
0.0,
|
||||
|
@ -1,195 +0,0 @@
|
||||
#include "u8g2/u8g2.h"
|
||||
#include "flipper.h"
|
||||
#include "main.h"
|
||||
|
||||
extern SPI_HandleTypeDef SPI_D;
|
||||
|
||||
// TODO: fix log
|
||||
#ifdef DEBUG
|
||||
#undef DEBUG
|
||||
#endif
|
||||
|
||||
// TODO rewrite u8g2 to pass thread-local context in this handlers
|
||||
|
||||
static uint8_t
|
||||
u8g2_gpio_and_delay_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* arg_ptr) {
|
||||
switch(msg) {
|
||||
//Initialize SPI peripheral
|
||||
case U8X8_MSG_GPIO_AND_DELAY_INIT:
|
||||
/* HAL initialization contains all what we need so we can skip this part. */
|
||||
break;
|
||||
|
||||
//Function which implements a delay, arg_int contains the amount of ms
|
||||
case U8X8_MSG_DELAY_MILLI:
|
||||
osDelay(arg_int);
|
||||
break;
|
||||
|
||||
//Function which delays 10us
|
||||
case U8X8_MSG_DELAY_10MICRO:
|
||||
delay_us(10);
|
||||
break;
|
||||
|
||||
//Function which delays 100ns
|
||||
case U8X8_MSG_DELAY_100NANO:
|
||||
asm("nop");
|
||||
break;
|
||||
|
||||
// Function to define the logic level of the RESET line
|
||||
case U8X8_MSG_GPIO_RESET:
|
||||
#ifdef DEBUG
|
||||
fuprintf(log, "[u8g2] rst %d\n", arg_int);
|
||||
#endif
|
||||
|
||||
// TODO change it to FuriRecord pin
|
||||
HAL_GPIO_WritePin(
|
||||
DISPLAY_RST_GPIO_Port, DISPLAY_RST_Pin, arg_int ? GPIO_PIN_SET : GPIO_PIN_RESET);
|
||||
break;
|
||||
|
||||
default:
|
||||
#ifdef DEBUG
|
||||
fufuprintf(log, "[u8g2] unknown io %d\n", msg);
|
||||
#endif
|
||||
|
||||
return 0; //A message was received which is not implemented, return 0 to indicate an error
|
||||
}
|
||||
|
||||
return 1; // command processed successfully.
|
||||
}
|
||||
|
||||
static uint8_t u8x8_hw_spi_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* arg_ptr) {
|
||||
switch(msg) {
|
||||
case U8X8_MSG_BYTE_SEND:
|
||||
#ifdef DEBUG
|
||||
fuprintf(log, "[u8g2] send %d bytes %02X\n", arg_int, ((uint8_t*)arg_ptr)[0]);
|
||||
#endif
|
||||
|
||||
// TODO change it to FuriRecord SPI
|
||||
HAL_SPI_Transmit(&SPI_D, (uint8_t*)arg_ptr, arg_int, 10000);
|
||||
break;
|
||||
|
||||
case U8X8_MSG_BYTE_SET_DC:
|
||||
#ifdef DEBUG
|
||||
fuprintf(log, "[u8g2] dc %d\n", arg_int);
|
||||
#endif
|
||||
|
||||
// TODO change it to FuriRecord pin
|
||||
HAL_GPIO_WritePin(
|
||||
DISPLAY_DI_GPIO_Port, DISPLAY_DI_Pin, arg_int ? GPIO_PIN_SET : GPIO_PIN_RESET);
|
||||
break;
|
||||
|
||||
case U8X8_MSG_BYTE_INIT:
|
||||
#ifdef DEBUG
|
||||
fuprintf(log, "[u8g2] init\n");
|
||||
#endif
|
||||
|
||||
// TODO change it to FuriRecord pin
|
||||
HAL_GPIO_WritePin(DISPLAY_CS_GPIO_Port, DISPLAY_CS_Pin, GPIO_PIN_RESET);
|
||||
break;
|
||||
|
||||
case U8X8_MSG_BYTE_START_TRANSFER:
|
||||
#ifdef DEBUG
|
||||
fuprintf(log, "[u8g2] start\n");
|
||||
#endif
|
||||
|
||||
// TODO change it to FuriRecord pin
|
||||
HAL_GPIO_WritePin(DISPLAY_CS_GPIO_Port, DISPLAY_CS_Pin, GPIO_PIN_RESET);
|
||||
asm("nop");
|
||||
break;
|
||||
|
||||
case U8X8_MSG_BYTE_END_TRANSFER:
|
||||
#ifdef DEBUG
|
||||
fuprintf(log, "[u8g2] end\n");
|
||||
#endif
|
||||
|
||||
asm("nop");
|
||||
// TODO change it to FuriRecord pin
|
||||
HAL_GPIO_WritePin(DISPLAY_CS_GPIO_Port, DISPLAY_CS_Pin, GPIO_PIN_SET);
|
||||
break;
|
||||
|
||||
default:
|
||||
#ifdef DEBUG
|
||||
fuprintf(log, "[u8g2] unknown xfer %d\n", msg);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
SemaphoreHandle_t update; // queue to pass events from callback to app thread
|
||||
FuriRecordSubscriber* log; // app logger
|
||||
} DisplayCtx;
|
||||
|
||||
static void handle_fb_change(const void* fb, size_t fb_size, void* raw_ctx) {
|
||||
DisplayCtx* ctx = (DisplayCtx*)raw_ctx; // make right type
|
||||
|
||||
// fuprintf(ctx->log, "[display_u8g2] change fb\n");
|
||||
|
||||
// send update to app thread
|
||||
xSemaphoreGive(ctx->update);
|
||||
}
|
||||
|
||||
void display_u8g2(void* p) {
|
||||
FuriRecordSubscriber* log = get_default_log();
|
||||
|
||||
// TODO we need different app to contol backlight
|
||||
HAL_GPIO_WritePin(DISPLAY_BACKLIGHT_GPIO_Port, DISPLAY_BACKLIGHT_Pin, GPIO_PIN_SET);
|
||||
|
||||
u8g2_t _u8g2;
|
||||
u8g2_Setup_st7565_erc12864_alt_f(
|
||||
&_u8g2, U8G2_R0, u8x8_hw_spi_stm32, u8g2_gpio_and_delay_stm32);
|
||||
u8g2_InitDisplay(
|
||||
&_u8g2); // send init sequence to the display, display is in sleep mode after this
|
||||
u8g2_SetContrast(&_u8g2, 36);
|
||||
|
||||
if(!furi_create_deprecated("u8g2_fb", (void*)&_u8g2, sizeof(_u8g2))) {
|
||||
fuprintf(log, "[display_u8g2] cannot create fb record\n");
|
||||
furiac_exit(NULL);
|
||||
}
|
||||
|
||||
StaticSemaphore_t event_descriptor;
|
||||
// create stack-based counting semaphore
|
||||
SemaphoreHandle_t update = xSemaphoreCreateCountingStatic(255, 0, &event_descriptor);
|
||||
|
||||
if(update == NULL) {
|
||||
fuprintf(log, "[display_u8g2] cannot create update semaphore\n");
|
||||
furiac_exit(NULL);
|
||||
}
|
||||
|
||||
// save log and event queue in context structure
|
||||
DisplayCtx ctx = {.update = update, .log = log};
|
||||
|
||||
// subscribe to record. ctx will be passed to handle_fb_change
|
||||
FuriRecordSubscriber* fb_record =
|
||||
furi_open_deprecated("u8g2_fb", false, false, handle_fb_change, NULL, &ctx);
|
||||
|
||||
if(fb_record == NULL) {
|
||||
fuprintf(log, "[display] cannot open fb record\n");
|
||||
furiac_exit(NULL);
|
||||
}
|
||||
|
||||
u8g2_t* u8g2 = (u8g2_t*)furi_take(fb_record);
|
||||
u8g2_SetPowerSave(u8g2, 0); // wake up display
|
||||
u8g2_SendBuffer(u8g2);
|
||||
furi_give(fb_record);
|
||||
|
||||
// we ready to work
|
||||
furiac_ready();
|
||||
|
||||
while(1) {
|
||||
// wait for event
|
||||
if(xSemaphoreTake(update, 10000) == pdTRUE) {
|
||||
HAL_GPIO_WritePin(DISPLAY_BACKLIGHT_GPIO_Port, DISPLAY_BACKLIGHT_Pin, GPIO_PIN_SET);
|
||||
|
||||
u8g2_t* u8g2 = (u8g2_t*)furi_take(fb_record);
|
||||
u8g2_SetPowerSave(u8g2, 0); // wake up display
|
||||
u8g2_SendBuffer(u8g2);
|
||||
furi_give(fb_record);
|
||||
} else {
|
||||
// TODO we need different app to contol backlight
|
||||
HAL_GPIO_WritePin(DISPLAY_BACKLIGHT_GPIO_Port, DISPLAY_BACKLIGHT_Pin, GPIO_PIN_RESET);
|
||||
}
|
||||
}
|
||||
}
|
@ -67,8 +67,7 @@ Dolphin* dolphin_alloc() {
|
||||
// State
|
||||
dolphin->state = dolphin_state_alloc();
|
||||
// Menu
|
||||
dolphin->menu_vm = furi_open("menu");
|
||||
furi_check(dolphin->menu_vm);
|
||||
dolphin->menu_vm = furi_record_open("menu");
|
||||
// GUI
|
||||
dolphin->idle_view_dispatcher = view_dispatcher_alloc();
|
||||
// First start View
|
||||
@ -125,7 +124,7 @@ void dolphin_deed(Dolphin* dolphin, DolphinDeed deed) {
|
||||
void dolphin_task() {
|
||||
Dolphin* dolphin = dolphin_alloc();
|
||||
|
||||
Gui* gui = furi_open("gui");
|
||||
Gui* gui = furi_record_open("gui");
|
||||
view_dispatcher_attach_to_gui(dolphin->idle_view_dispatcher, gui, ViewDispatcherTypeWindow);
|
||||
if(dolphin_state_load(dolphin->state)) {
|
||||
view_dispatcher_switch_to_view(dolphin->idle_view_dispatcher, DolphinViewIdleMain);
|
||||
@ -138,12 +137,7 @@ void dolphin_task() {
|
||||
model->butthurt = dolphin_state_get_butthurt(dolphin->state);
|
||||
});
|
||||
|
||||
if(!furi_create("dolphin", dolphin)) {
|
||||
printf("[dolphin_task] cannot create the dolphin record\n");
|
||||
furiac_exit(NULL);
|
||||
}
|
||||
|
||||
furiac_ready();
|
||||
furi_record_create("dolphin", dolphin);
|
||||
|
||||
DolphinEvent event;
|
||||
while(1) {
|
||||
|
@ -4,7 +4,7 @@
|
||||
#include "dolphin_state.h"
|
||||
#include "dolphin_views.h"
|
||||
|
||||
#include <flipper_v2.h>
|
||||
#include <furi.h>
|
||||
|
||||
#include <gui/gui.h>
|
||||
#include <gui/view_dispatcher.h>
|
||||
|
@ -1,6 +1,5 @@
|
||||
#include "dolphin_state.h"
|
||||
#include <api-hal-flash.h>
|
||||
#include <flipper_v2.h>
|
||||
#include <furi.h>
|
||||
|
||||
typedef struct {
|
||||
uint8_t magic;
|
||||
|
@ -3,7 +3,8 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <gui/canvas.h>
|
||||
#include <flipper_v2.h>
|
||||
#include <input/input.h>
|
||||
#include <furi.h>
|
||||
|
||||
// Idle scree
|
||||
typedef enum {
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "flipper_v2.h"
|
||||
#include <furi.h>
|
||||
|
||||
void rgb_set(
|
||||
bool r,
|
||||
|
@ -1,155 +0,0 @@
|
||||
#include "u8g2/u8g2.h"
|
||||
#include "fatfs/ff.h"
|
||||
#include "flipper_v2.h"
|
||||
#include <stdio.h>
|
||||
|
||||
extern uint8_t BSP_SD_Init();
|
||||
|
||||
// TODO currently we have small stack, so it will be static
|
||||
FuriRecordSubscriber* furi_log;
|
||||
#define STR_BUFFER_SIZE 128
|
||||
char str_buffer[STR_BUFFER_SIZE];
|
||||
uint8_t line_current = 0;
|
||||
uint16_t line_position = 0;
|
||||
|
||||
// TODO this should be in the target driver
|
||||
FATFS SD_FatFs;
|
||||
char SD_Path[4];
|
||||
|
||||
typedef enum {
|
||||
EventTypeStart,
|
||||
EventTypeKey,
|
||||
} AppEventType;
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
InputEvent input;
|
||||
} value;
|
||||
AppEventType type;
|
||||
} AppEvent;
|
||||
|
||||
static void event_cb(const void* value, void* ctx) {
|
||||
QueueHandle_t event_queue = (QueueHandle_t)ctx;
|
||||
|
||||
AppEvent event;
|
||||
event.type = EventTypeKey;
|
||||
event.value.input = *(InputEvent*)value;
|
||||
xQueueSend(event_queue, (void*)&event, 0);
|
||||
}
|
||||
|
||||
void fatfs_list(void* p) {
|
||||
const uint8_t line_size = 10;
|
||||
const uint8_t lines_on_display = 6;
|
||||
|
||||
uint8_t bsp_result;
|
||||
FRESULT result;
|
||||
DIR dir;
|
||||
FILINFO fno;
|
||||
AppEvent event;
|
||||
|
||||
QueueHandle_t event_queue = xQueueCreate(2, sizeof(AppEvent));
|
||||
|
||||
furi_log = get_default_log();
|
||||
fuprintf(furi_log, "[fatfs_list] app start\n");
|
||||
fuprintf(furi_log, "[fatfs_list] wait for sd insert\n");
|
||||
|
||||
while(!hal_gpio_read_sd_detect()) {
|
||||
delay(100);
|
||||
}
|
||||
|
||||
fuprintf(furi_log, "[fatfs_list] sd inserted\n");
|
||||
|
||||
FuriRecordSubscriber* fb_record =
|
||||
furi_open_deprecated("u8g2_fb", false, false, NULL, NULL, NULL);
|
||||
if(fb_record == NULL) {
|
||||
fuprintf(furi_log, "[fatfs_list] cannot create fb record\n");
|
||||
furiac_exit(NULL);
|
||||
}
|
||||
|
||||
PubSub* event_record = furi_open("input_events");
|
||||
if(event_record == NULL) {
|
||||
fuprintf(furi_log, "[fatfs_list] cannot open input_events record\n");
|
||||
furiac_exit(NULL);
|
||||
}
|
||||
PubSubItem* subscription = subscribe_pubsub(event_record, event_cb, event_queue);
|
||||
if(subscription == NULL) {
|
||||
fuprintf(furi_log, "[fatfs_list] cannot register input_events callback\n");
|
||||
furiac_exit(NULL);
|
||||
}
|
||||
|
||||
bsp_result = BSP_SD_Init();
|
||||
|
||||
if(bsp_result != 0) {
|
||||
fuprintf(furi_log, "[fatfs_list] SD card init error\n");
|
||||
furiac_exit(NULL);
|
||||
}
|
||||
|
||||
result = f_mount(&SD_FatFs, (TCHAR const*)SD_Path, 1);
|
||||
|
||||
if(result != FR_OK) {
|
||||
fuprintf(furi_log, "[fatfs_list] SD card mount error\n");
|
||||
furiac_exit(NULL);
|
||||
}
|
||||
|
||||
// ok, now we can work with sd card
|
||||
|
||||
// send start event
|
||||
event.type = EventTypeStart;
|
||||
xQueueSend(event_queue, (void*)&event, 0);
|
||||
|
||||
while(1) {
|
||||
if(xQueueReceive(event_queue, (void*)&event, portMAX_DELAY)) {
|
||||
// process buttons event
|
||||
if(event.type == EventTypeKey) {
|
||||
// button pressed
|
||||
if(event.value.input.state == true) {
|
||||
if(event.value.input.input == InputUp && line_position > 0) {
|
||||
line_position--;
|
||||
}
|
||||
if(event.value.input.input == InputDown) {
|
||||
line_position++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
line_current = 1;
|
||||
|
||||
// open root dir
|
||||
result = f_opendir(&dir, "");
|
||||
|
||||
while(1) {
|
||||
// read a directory item
|
||||
result = f_readdir(&dir, &fno);
|
||||
|
||||
if(result != FR_OK) {
|
||||
// cannot read dir
|
||||
break;
|
||||
}
|
||||
|
||||
if(fno.fname[0] == 0) {
|
||||
// Break on end of dir
|
||||
break;
|
||||
}
|
||||
|
||||
// draw files on display
|
||||
if(line_current > line_position &&
|
||||
line_current <= (line_position + lines_on_display)) {
|
||||
if(fno.fattrib & AM_DIR) {
|
||||
snprintf(str_buffer, STR_BUFFER_SIZE, "DIR %s\n", fno.fname);
|
||||
} else {
|
||||
snprintf(str_buffer, STR_BUFFER_SIZE, "FIL %s\n", fno.fname);
|
||||
}
|
||||
fuprintf(furi_log, str_buffer);
|
||||
}
|
||||
|
||||
line_current++;
|
||||
}
|
||||
|
||||
result = f_closedir(&dir);
|
||||
|
||||
furi_commit(fb_record);
|
||||
}
|
||||
}
|
||||
|
||||
furiac_exit(NULL);
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
#include "flipper_v2.h"
|
||||
#include <furi.h>
|
||||
#include <stdio.h>
|
||||
#include <input/input.h>
|
||||
|
||||
typedef union {
|
||||
unsigned int packed;
|
||||
@ -21,12 +22,10 @@ static void event_cb(const void* value, void* ctx) {
|
||||
|
||||
void application_input_dump(void* p) {
|
||||
// open record
|
||||
ValueManager* state_record = furi_open("input_state");
|
||||
furi_check(state_record);
|
||||
ValueManager* state_record = furi_record_open("input_state");
|
||||
subscribe_pubsub(&state_record->pubsub, state_cb, NULL);
|
||||
|
||||
PubSub* event_record = furi_open("input_events");
|
||||
furi_check(event_record);
|
||||
PubSub* event_record = furi_record_open("input_events");
|
||||
subscribe_pubsub(event_record, event_cb, NULL);
|
||||
|
||||
printf("Example app [input dump]\n");
|
||||
|
@ -1,155 +0,0 @@
|
||||
#include "flipper.h"
|
||||
#include <string.h>
|
||||
|
||||
#define FB_WIDTH 10
|
||||
#define FB_HEIGHT 3
|
||||
#define FB_SIZE (FB_WIDTH * FB_HEIGHT)
|
||||
|
||||
// context structure used for pass some object from app thread to callback
|
||||
typedef struct {
|
||||
SemaphoreHandle_t events; // queue to pass events from callback to app thread
|
||||
FuriRecordSubscriber* log; // app logger
|
||||
} IpcCtx;
|
||||
|
||||
static void handle_fb_change(const void* fb, size_t fb_size, void* raw_ctx) {
|
||||
IpcCtx* ctx = (IpcCtx*)raw_ctx; // make right type
|
||||
|
||||
fuprintf(ctx->log, "[cb] framebuffer updated\n");
|
||||
|
||||
// send event to app thread
|
||||
xSemaphoreGive(ctx->events);
|
||||
|
||||
// Attention! Please, do not make blocking operation like IO and waits inside callback
|
||||
// Remember that callback execute in calling thread/context
|
||||
}
|
||||
|
||||
static void print_fb(char* fb, FuriRecordSubscriber* log) {
|
||||
if(fb == NULL) return;
|
||||
|
||||
/* draw framebuffer like this:
|
||||
+==========+
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
+==========+
|
||||
*/
|
||||
|
||||
char row_buffer[FB_WIDTH + 1];
|
||||
row_buffer[FB_WIDTH] = '\0';
|
||||
|
||||
// FB layout is hardcoded here
|
||||
fuprintf(log, "+==========+\n");
|
||||
for(uint8_t i = 0; i < FB_HEIGHT; i++) {
|
||||
strncpy(row_buffer, &fb[FB_WIDTH * i], FB_WIDTH);
|
||||
fuprintf(log, "|%s|\n", row_buffer);
|
||||
}
|
||||
fuprintf(log, "+==========+\n");
|
||||
}
|
||||
|
||||
void application_ipc_display(void* p) {
|
||||
// get logger
|
||||
FuriRecordSubscriber* log = get_default_log();
|
||||
|
||||
// create ASCII "framebuffer"
|
||||
// FB_WIDTH x FB_HEIGHT char buffer
|
||||
char _framebuffer[FB_SIZE];
|
||||
|
||||
// init framebuffer by spaces
|
||||
for(size_t i = 0; i < FB_SIZE; i++) {
|
||||
_framebuffer[i] = ' ';
|
||||
}
|
||||
|
||||
// create record
|
||||
if(!furi_create_deprecated("test_fb", (void*)_framebuffer, FB_SIZE)) {
|
||||
fuprintf(log, "[display] cannot create fb record\n");
|
||||
furiac_exit(NULL);
|
||||
}
|
||||
|
||||
StaticSemaphore_t event_descriptor;
|
||||
// create stack-based counting semaphore
|
||||
SemaphoreHandle_t events = xSemaphoreCreateCountingStatic(255, 0, &event_descriptor);
|
||||
|
||||
if(events == NULL) {
|
||||
fuprintf(log, "[display] cannot create event semaphore\n");
|
||||
furiac_exit(NULL);
|
||||
}
|
||||
|
||||
// save log and event queue in context structure
|
||||
IpcCtx ctx = {.events = events, .log = log};
|
||||
|
||||
// subscribe to record. ctx will be passed to handle_fb_change
|
||||
FuriRecordSubscriber* fb_record =
|
||||
furi_open_deprecated("test_fb", false, false, handle_fb_change, NULL, &ctx);
|
||||
|
||||
if(fb_record == NULL) {
|
||||
fuprintf(log, "[display] cannot open fb record\n");
|
||||
furiac_exit(NULL);
|
||||
}
|
||||
|
||||
#ifdef HW_DISPLAY
|
||||
// on Flipper target -- open screen
|
||||
|
||||
// draw border
|
||||
|
||||
#else
|
||||
// on Local target -- print "blank screen"
|
||||
{
|
||||
void* fb = furi_take(fb_record);
|
||||
print_fb((char*)fb, log);
|
||||
furi_give(fb_record);
|
||||
}
|
||||
#endif
|
||||
|
||||
while(1) {
|
||||
// wait for event
|
||||
if(xSemaphoreTake(events, portMAX_DELAY) == pdTRUE) {
|
||||
fuprintf(log, "[display] get fb update\n\n");
|
||||
|
||||
#ifdef HW_DISPLAY
|
||||
// on Flipper target draw the screen
|
||||
#else
|
||||
// on local target just print
|
||||
{
|
||||
void* fb = furi_take(fb_record);
|
||||
print_fb((char*)fb, log);
|
||||
furi_give(fb_record);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Widget application
|
||||
void application_ipc_widget(void* p) {
|
||||
FuriRecordSubscriber* log = get_default_log();
|
||||
|
||||
// open record
|
||||
FuriRecordSubscriber* fb_record =
|
||||
furi_open_deprecated("test_fb", false, false, NULL, NULL, NULL);
|
||||
|
||||
if(fb_record == NULL) {
|
||||
fuprintf(log, "[widget] cannot create fb record\n");
|
||||
furiac_exit(NULL);
|
||||
}
|
||||
|
||||
uint8_t counter = 0;
|
||||
|
||||
while(1) {
|
||||
delay(120);
|
||||
|
||||
// write some ascii demo here: '#'' symbol run on overall screen
|
||||
char* fb = (char*)furi_take(fb_record);
|
||||
|
||||
if(fb == NULL) furiac_exit(NULL);
|
||||
|
||||
for(size_t i = 0; i < FB_SIZE; i++) {
|
||||
fb[i] = ' ';
|
||||
}
|
||||
|
||||
fb[counter % FB_SIZE] = '#';
|
||||
|
||||
furi_commit(fb_record);
|
||||
|
||||
counter++;
|
||||
}
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
#include "flipper_v2.h"
|
||||
#include <furi.h>
|
||||
#include <input.h>
|
||||
|
||||
static void event_cb(const void* value, void* ctx) {
|
||||
const InputEvent* event = value;
|
||||
@ -38,8 +39,7 @@ void application_strobe(void* p) {
|
||||
ValueMutex delay_mutex;
|
||||
init_mutex(&delay_mutex, &delay_time_holder, sizeof(delay_time_holder));
|
||||
|
||||
PubSub* event_record = furi_open("input_events");
|
||||
furi_check(event_record);
|
||||
PubSub* event_record = furi_record_open("input_events");
|
||||
subscribe_pubsub(event_record, event_cb, &delay_mutex);
|
||||
|
||||
while(1) {
|
||||
|
@ -1,32 +1,14 @@
|
||||
#include "u8g2/u8g2.h"
|
||||
#include "flipper.h"
|
||||
#include <furi.h>
|
||||
|
||||
void u8g2_example(void* p) {
|
||||
FuriRecordSubscriber* log = get_default_log();
|
||||
|
||||
// open record
|
||||
FuriRecordSubscriber* fb_record =
|
||||
furi_open_deprecated("u8g2_fb", false, false, NULL, NULL, NULL);
|
||||
u8g2_t* fb = furi_record_open("u8g2_fb");
|
||||
u8g2_SetFont(fb, u8g2_font_6x10_mf);
|
||||
u8g2_SetDrawColor(fb, 1);
|
||||
u8g2_SetFontMode(fb, 1);
|
||||
u8g2_DrawStr(fb, 2, 12, "hello world!");
|
||||
furi_record_close("u8g2_fb");
|
||||
|
||||
if(fb_record == NULL) {
|
||||
fuprintf(log, "[widget] cannot create fb record\n");
|
||||
furiac_exit(NULL);
|
||||
}
|
||||
|
||||
while(1) {
|
||||
u8g2_t* fb = furi_take(fb_record);
|
||||
if(fb != NULL) {
|
||||
u8g2_SetFont(fb, u8g2_font_6x10_mf);
|
||||
u8g2_SetDrawColor(fb, 1);
|
||||
u8g2_SetFontMode(fb, 1);
|
||||
u8g2_DrawStr(fb, 2, 12, "hello world!");
|
||||
}
|
||||
furi_commit(fb_record);
|
||||
|
||||
if(fb != NULL) {
|
||||
furiac_exit(NULL);
|
||||
}
|
||||
|
||||
delay(1);
|
||||
}
|
||||
furiac_exit(NULL);
|
||||
}
|
@ -1,6 +1,9 @@
|
||||
#include "u8g2/u8g2.h"
|
||||
#include "qrcode/qrcode.h"
|
||||
#include "flipper.h"
|
||||
#include <furi.h>
|
||||
|
||||
/*
|
||||
TODO: rework with new app api
|
||||
|
||||
void u8g2_DrawPixelSize(u8g2_t* u8g2, uint8_t x, uint8_t y, uint8_t size) {
|
||||
for(uint8_t px = 0; px < size; px++) {
|
||||
@ -11,8 +14,6 @@ void u8g2_DrawPixelSize(u8g2_t* u8g2, uint8_t x, uint8_t y, uint8_t size) {
|
||||
}
|
||||
|
||||
void u8g2_qrcode(void* p) {
|
||||
FuriRecordSubscriber* log = get_default_log();
|
||||
|
||||
// open record
|
||||
FuriRecordSubscriber* fb_record =
|
||||
furi_open_deprecated("u8g2_fb", false, false, NULL, NULL, NULL);
|
||||
@ -36,7 +37,7 @@ void u8g2_qrcode(void* p) {
|
||||
qrcode_initText(&qrcode, qrcodeBytes, qr_version, qr_error_correction, "HELLO FLIPPER");
|
||||
|
||||
if(fb_record == NULL) {
|
||||
fuprintf(log, "[widget] cannot create fb record\n");
|
||||
printf("[widget] cannot create fb record\n");
|
||||
furiac_exit(NULL);
|
||||
}
|
||||
|
||||
@ -69,4 +70,5 @@ void u8g2_qrcode(void* p) {
|
||||
|
||||
delay(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
@ -1,7 +1,5 @@
|
||||
#include "flipper.h"
|
||||
#include <furi.h>
|
||||
#include <string.h>
|
||||
#include "log.h"
|
||||
#include "flipper_v2.h"
|
||||
|
||||
void application_uart_write(void* p) {
|
||||
// Red led for showing progress
|
||||
@ -11,12 +9,9 @@ void application_uart_write(void* p) {
|
||||
|
||||
gpio_init(led_record, GpioModeOutputOpenDrain);
|
||||
|
||||
// get_default_log open "tty" record
|
||||
FuriRecordSubscriber* log = get_default_log();
|
||||
|
||||
// create buffer
|
||||
const char test_string[] = "test\n";
|
||||
furi_write(log, test_string, strlen(test_string));
|
||||
printf(test_string);
|
||||
|
||||
// for example, create counter and show its value
|
||||
uint8_t counter = 0;
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "flipper_v2.h"
|
||||
#include <furi.h>
|
||||
#include <input/input.h>
|
||||
|
||||
typedef struct {
|
||||
GpioPin* led;
|
||||
@ -24,7 +25,7 @@ void application_vibro(void* p) {
|
||||
gpio_write(ctx.vibro, false);
|
||||
|
||||
// subscribe on buttons
|
||||
PubSub* event_record = furi_open("input_events");
|
||||
PubSub* event_record = furi_record_open("input_events");
|
||||
furi_check(event_record);
|
||||
subscribe_pubsub(event_record, button_handler, &ctx);
|
||||
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 25a2cc076c3162aad721e0d92009cfa7b9100c7a
|
||||
Subproject commit 621044255a8be4d2c3f342e2b22178a342ccbfe8
|
@ -1,4 +1,6 @@
|
||||
#include "flipper_v2.h"
|
||||
#include <furi.h>
|
||||
#include <gui/gui.h>
|
||||
#include <input/input.h>
|
||||
|
||||
typedef struct {
|
||||
const char* name;
|
||||
@ -47,7 +49,7 @@ static void render_callback(Canvas* canvas, void* ctx) {
|
||||
}
|
||||
|
||||
static void input_callback(InputEvent* input_event, void* ctx) {
|
||||
osMessageQueueId_t event_queue = (QueueHandle_t)ctx;
|
||||
osMessageQueueId_t event_queue = ctx;
|
||||
|
||||
AppEvent event;
|
||||
event.type = EventTypeKey;
|
||||
@ -74,11 +76,7 @@ void app_gpio_test(void* p) {
|
||||
widget_input_callback_set(widget, input_callback, event_queue);
|
||||
|
||||
// Open GUI and register widget
|
||||
Gui* gui = (Gui*)furi_open("gui");
|
||||
if(gui == NULL) {
|
||||
printf("[gpio-tester] gui is not available\n");
|
||||
furiac_exit(NULL);
|
||||
}
|
||||
Gui* gui = furi_record_open("gui");
|
||||
gui_add_widget(gui, widget, GuiLayerFullscreen);
|
||||
|
||||
// configure pin
|
||||
|
@ -1,8 +1,7 @@
|
||||
#include "canvas_i.h"
|
||||
#include "icon_i.h"
|
||||
|
||||
#include <flipper.h>
|
||||
#include <flipper_v2.h>
|
||||
#include <furi.h>
|
||||
|
||||
struct Canvas {
|
||||
u8g2_t fb;
|
||||
|
@ -5,6 +5,10 @@
|
||||
#include <gui/icon.h>
|
||||
#include <assets_icons_i.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
ColorWhite = 0x00,
|
||||
ColorBlack = 0x01,
|
||||
@ -91,3 +95,7 @@ void canvas_draw_line(Canvas* canvas, uint8_t x1, uint8_t y1, uint8_t x2, uint8_
|
||||
* Draw glyph
|
||||
*/
|
||||
void canvas_draw_glyph(Canvas* canvas, uint8_t x, uint8_t y, uint16_t ch);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -3,6 +3,10 @@
|
||||
#include <stdint.h>
|
||||
#include "canvas.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Draw scrollbar on canvas.
|
||||
* width 3px, height equal to canvas height
|
||||
@ -17,3 +21,7 @@ void elements_scrollbar(Canvas* canvas, uint8_t pos, uint8_t total);
|
||||
* @param width, height - frame width and height
|
||||
*/
|
||||
void elements_frame(Canvas* canvas, uint8_t x, uint8_t y, uint8_t width, uint8_t height);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -1,8 +1,7 @@
|
||||
#include "gui.h"
|
||||
#include "gui_i.h"
|
||||
|
||||
#include <flipper.h>
|
||||
#include <flipper_v2.h>
|
||||
#include <furi.h>
|
||||
#include <m-array.h>
|
||||
#include <stdio.h>
|
||||
|
||||
@ -207,13 +206,9 @@ Gui* gui_alloc() {
|
||||
|
||||
void gui_task(void* p) {
|
||||
Gui* gui = gui_alloc();
|
||||
// Create FURI record
|
||||
if(!furi_create("gui", gui)) {
|
||||
printf("[gui_task] cannot create the gui record\n");
|
||||
furiac_exit(NULL);
|
||||
}
|
||||
|
||||
furiac_ready();
|
||||
// Create FURI record
|
||||
furi_record_create("gui", gui);
|
||||
|
||||
// Forever dispatch
|
||||
while(1) {
|
||||
|
@ -3,6 +3,10 @@
|
||||
#include "widget.h"
|
||||
#include "canvas.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define GUI_DISPLAY_WIDTH 128
|
||||
#define GUI_DISPLAY_HEIGHT 64
|
||||
|
||||
@ -40,3 +44,7 @@ void gui_add_widget(Gui* gui, Widget* widget, GuiLayer layer);
|
||||
* @remarks thread safe
|
||||
*/
|
||||
void gui_remove_widget(Gui* gui, Widget* widget);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -1,6 +1,6 @@
|
||||
#include "gui_event.h"
|
||||
|
||||
#include <flipper_v2.h>
|
||||
#include <furi.h>
|
||||
|
||||
#define GUI_EVENT_MQUEUE_SIZE 8
|
||||
|
||||
@ -45,7 +45,7 @@ GuiEvent* gui_event_alloc() {
|
||||
// osTimerStart(gui_event->timer, 1024 / 4);
|
||||
|
||||
// Input
|
||||
gui_event->input_event_record = furi_open("input_events");
|
||||
gui_event->input_event_record = furi_record_open("input_events");
|
||||
furi_check(gui_event->input_event_record != NULL);
|
||||
subscribe_pubsub(gui_event->input_event_record, gui_event_input_events_callback, gui_event);
|
||||
|
||||
|
@ -3,6 +3,10 @@
|
||||
#include <stdint.h>
|
||||
#include <input/input.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
GuiMessageTypeRedraw = 0x00,
|
||||
GuiMessageTypeInput = 0x01,
|
||||
@ -23,3 +27,7 @@ void gui_event_free(GuiEvent* gui_event);
|
||||
void gui_event_messsage_send(GuiEvent* gui_event, GuiMessage* message);
|
||||
|
||||
GuiMessage gui_event_message_next(GuiEvent* gui_event);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -1,8 +1,6 @@
|
||||
#include "icon_i.h"
|
||||
|
||||
#include <cmsis_os2.h>
|
||||
#include <flipper.h>
|
||||
#include <flipper_v2.h>
|
||||
#include <furi.h>
|
||||
|
||||
Icon* icon_alloc(const IconData* data) {
|
||||
Icon* icon = furi_alloc(sizeof(Icon));
|
||||
|
@ -3,6 +3,10 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct IconData IconData;
|
||||
typedef struct Icon Icon;
|
||||
|
||||
@ -41,3 +45,7 @@ void icon_start_animation(Icon* icon);
|
||||
* Stop icon animation
|
||||
*/
|
||||
void icon_stop_animation(Icon* icon);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -1,5 +1,5 @@
|
||||
#include "u8g2/u8g2.h"
|
||||
#include "flipper.h"
|
||||
#include <furi.h>
|
||||
#include <main.h>
|
||||
|
||||
extern SPI_HandleTypeDef SPI_D;
|
||||
@ -34,7 +34,7 @@ uint8_t u8g2_gpio_and_delay_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, vo
|
||||
// Function to define the logic level of the RESET line
|
||||
case U8X8_MSG_GPIO_RESET:
|
||||
#ifdef DEBUG
|
||||
fuprintf(log, "[u8g2] rst %d\n", arg_int);
|
||||
printf("[u8g2] rst %d\n", arg_int);
|
||||
#endif
|
||||
|
||||
// TODO change it to FuriRecord pin
|
||||
@ -44,7 +44,7 @@ uint8_t u8g2_gpio_and_delay_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, vo
|
||||
|
||||
default:
|
||||
#ifdef DEBUG
|
||||
fufuprintf(log, "[u8g2] unknown io %d\n", msg);
|
||||
printf("[u8g2] unknown io %d\n", msg);
|
||||
#endif
|
||||
|
||||
return 0; //A message was received which is not implemented, return 0 to indicate an error
|
||||
@ -57,7 +57,7 @@ uint8_t u8x8_hw_spi_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* arg_
|
||||
switch(msg) {
|
||||
case U8X8_MSG_BYTE_SEND:
|
||||
#ifdef DEBUG
|
||||
fuprintf(log, "[u8g2] send %d bytes %02X\n", arg_int, ((uint8_t*)arg_ptr)[0]);
|
||||
printf("[u8g2] send %d bytes %02X\n", arg_int, ((uint8_t*)arg_ptr)[0]);
|
||||
#endif
|
||||
|
||||
// TODO change it to FuriRecord SPI
|
||||
@ -66,7 +66,7 @@ uint8_t u8x8_hw_spi_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* arg_
|
||||
|
||||
case U8X8_MSG_BYTE_SET_DC:
|
||||
#ifdef DEBUG
|
||||
fuprintf(log, "[u8g2] dc %d\n", arg_int);
|
||||
printf("[u8g2] dc %d\n", arg_int);
|
||||
#endif
|
||||
|
||||
// TODO change it to FuriRecord pin
|
||||
@ -76,7 +76,7 @@ uint8_t u8x8_hw_spi_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* arg_
|
||||
|
||||
case U8X8_MSG_BYTE_INIT:
|
||||
#ifdef DEBUG
|
||||
fuprintf(log, "[u8g2] init\n");
|
||||
printf("[u8g2] init\n");
|
||||
#endif
|
||||
|
||||
// TODO change it to FuriRecord pin
|
||||
@ -85,7 +85,7 @@ uint8_t u8x8_hw_spi_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* arg_
|
||||
|
||||
case U8X8_MSG_BYTE_START_TRANSFER:
|
||||
#ifdef DEBUG
|
||||
fuprintf(log, "[u8g2] start\n");
|
||||
printf("[u8g2] start\n");
|
||||
#endif
|
||||
|
||||
// TODO: SPI manager
|
||||
@ -98,7 +98,7 @@ uint8_t u8x8_hw_spi_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* arg_
|
||||
|
||||
case U8X8_MSG_BYTE_END_TRANSFER:
|
||||
#ifdef DEBUG
|
||||
fuprintf(log, "[u8g2] end\n");
|
||||
printf("[u8g2] end\n");
|
||||
#endif
|
||||
|
||||
asm("nop");
|
||||
@ -112,7 +112,7 @@ uint8_t u8x8_hw_spi_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* arg_
|
||||
|
||||
default:
|
||||
#ifdef DEBUG
|
||||
fuprintf(log, "[u8g2] unknown xfer %d\n", msg);
|
||||
printf("[u8g2] unknown xfer %d\n", msg);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
@ -3,6 +3,10 @@
|
||||
#include <input/input.h>
|
||||
#include "canvas.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Hides drawing widget */
|
||||
#define VIEW_NONE 0xFFFFFFFF
|
||||
/* Ignore navigation event */
|
||||
@ -127,3 +131,7 @@ void view_commit_model(View* view);
|
||||
({ void __fn__ function_body __fn__; })(p); \
|
||||
view_commit_model(view); \
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -3,6 +3,10 @@
|
||||
#include "view.h"
|
||||
#include "gui.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ViewDispatcher widget placement */
|
||||
typedef enum {
|
||||
ViewDispatcherTypeNone, /* Special layer for internal use only */
|
||||
@ -43,3 +47,7 @@ void view_dispatcher_attach_to_gui(
|
||||
ViewDispatcher* view_dispatcher,
|
||||
Gui* gui,
|
||||
ViewDispatcherType type);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
#include "view_dispatcher.h"
|
||||
#include "view_i.h"
|
||||
#include <flipper_v2.h>
|
||||
#include <furi.h>
|
||||
#include <m-dict.h>
|
||||
|
||||
DICT_DEF2(ViewDict, uint32_t, M_DEFAULT_OPLIST, View*, M_PTR_OPLIST)
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
#include "view.h"
|
||||
#include "view_dispatcher_i.h"
|
||||
#include <flipper_v2.h>
|
||||
#include <furi.h>
|
||||
|
||||
typedef struct {
|
||||
void* data;
|
||||
|
@ -1,8 +1,6 @@
|
||||
#include "widget_i.h"
|
||||
|
||||
#include <cmsis_os.h>
|
||||
#include <flipper.h>
|
||||
#include <flipper_v2.h>
|
||||
#include <furi.h>
|
||||
|
||||
#include "gui.h"
|
||||
#include "gui_i.h"
|
||||
@ -73,8 +71,6 @@ void widget_update(Widget* widget) {
|
||||
|
||||
void widget_gui_set(Widget* widget, Gui* gui) {
|
||||
furi_assert(widget);
|
||||
furi_assert(gui);
|
||||
|
||||
widget->gui = gui;
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,10 @@
|
||||
#include <input/input.h>
|
||||
#include "canvas.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct Widget Widget;
|
||||
|
||||
/*
|
||||
@ -65,3 +69,7 @@ void widget_input_callback_set(Widget* widget, WidgetInputCallback callback, voi
|
||||
* Rendering will happen later after GUI system process signal.
|
||||
*/
|
||||
void widget_update(Widget* widget);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -32,7 +32,7 @@ void AppiButton::run() {
|
||||
printf("[ibutton] bye!\n");
|
||||
// TODO remove all widgets create by app
|
||||
widget_enabled_set(widget, false);
|
||||
furiac_exit(NULL);
|
||||
osThreadExit();
|
||||
}
|
||||
|
||||
if(event.value.input.state && event.value.input.input == InputLeft) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
#include <input/input.h>
|
||||
#include <stdio.h>
|
||||
#include <flipper_v2.h>
|
||||
#include <furi.h>
|
||||
|
||||
#ifdef APP_NFC
|
||||
void nfc_isr(void);
|
||||
@ -35,18 +35,10 @@ void input_task(void* p) {
|
||||
furiac_exit(NULL);
|
||||
}
|
||||
|
||||
if(!furi_create("input_state", &input_state_record)) {
|
||||
printf("[input_task] cannot create the input_state record\n");
|
||||
furiac_exit(NULL);
|
||||
}
|
||||
|
||||
if(!furi_create("input_events", &input_events_record)) {
|
||||
printf("[input_task] cannot create the input_events record\n");
|
||||
furiac_exit(NULL);
|
||||
}
|
||||
furi_record_create("input_state", &input_state_record);
|
||||
furi_record_create("input_events", &input_events_record);
|
||||
|
||||
// we ready to work
|
||||
furiac_ready();
|
||||
initialized = true;
|
||||
|
||||
// Force state update
|
||||
|
@ -1,6 +1,5 @@
|
||||
#pragma once
|
||||
#include "flipper.h"
|
||||
#include "flipper_v2.h"
|
||||
#include <furi.h>
|
||||
#include "irda-decoder-nec.h"
|
||||
#include "irda-decoder-types.h"
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include "flipper.h"
|
||||
#include "flipper_v2.h"
|
||||
#include <furi.h>
|
||||
#include <gui/gui.h>
|
||||
#include <input/input.h>
|
||||
|
||||
#include "irda_nec.h"
|
||||
#include "irda_samsung.h"
|
||||
#include "irda_protocols.h"
|
||||
@ -185,7 +187,7 @@ static void render_callback(Canvas* canvas, void* ctx) {
|
||||
}
|
||||
|
||||
static void input_callback(InputEvent* input_event, void* ctx) {
|
||||
osMessageQueueId_t event_queue = (QueueHandle_t)ctx;
|
||||
osMessageQueueId_t event_queue = ctx;
|
||||
|
||||
AppEvent event;
|
||||
event.type = EventTypeKey;
|
||||
@ -271,11 +273,7 @@ void irda(void* p) {
|
||||
widget_input_callback_set(widget, input_callback, event_queue);
|
||||
|
||||
// Open GUI and register widget
|
||||
Gui* gui = (Gui*)furi_open("gui");
|
||||
if(gui == NULL) {
|
||||
printf("gui is not available\n");
|
||||
furiac_exit(NULL);
|
||||
}
|
||||
Gui* gui = furi_record_open("gui");
|
||||
gui_add_widget(gui, widget, GuiLayerFullscreen);
|
||||
|
||||
// Red LED
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "flipper.h"
|
||||
#include <furi.h>
|
||||
#include "irda_nec.h"
|
||||
#include "irda_protocols.h"
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
#pragma once
|
||||
#include "flipper.h"
|
||||
#include <furi.h>
|
||||
|
||||
void ir_nec_send(uint16_t addr, uint8_t data);
|
@ -1,4 +1,4 @@
|
||||
#include "flipper.h"
|
||||
#include <furi.h>
|
||||
#include "irda_samsung.h"
|
||||
#include "irda_protocols.h"
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
#pragma once
|
||||
#include "flipper.h"
|
||||
#include <furi.h>
|
||||
|
||||
void ir_samsung_send(uint16_t addr, uint16_t data);
|
@ -1,4 +1,4 @@
|
||||
#include "flipper_v2.h"
|
||||
#include <furi.h>
|
||||
|
||||
void prepare_data(uint32_t ID, uint32_t VENDOR, uint8_t* data) {
|
||||
uint8_t value[10];
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "flipper_v2.h"
|
||||
#include <furi.h>
|
||||
#include <gui/gui.h>
|
||||
|
||||
typedef enum { EventTypeTick, EventTypeKey, EventTypeRx } EventType;
|
||||
|
||||
@ -45,7 +46,7 @@ static void render_callback(Canvas* canvas, void* ctx) {
|
||||
}
|
||||
|
||||
static void input_callback(InputEvent* input_event, void* ctx) {
|
||||
osMessageQueueId_t event_queue = (QueueHandle_t)ctx;
|
||||
osMessageQueueId_t event_queue = ctx;
|
||||
|
||||
AppEvent event;
|
||||
event.type = EventTypeKey;
|
||||
@ -67,7 +68,7 @@ void comparator_trigger_callback(void* hcomp, void* comp_ctx) {
|
||||
|
||||
// gpio_write(&debug_0, true);
|
||||
|
||||
osMessageQueueId_t event_queue = (QueueHandle_t)comp_ctx;
|
||||
osMessageQueueId_t event_queue = comp_ctx;
|
||||
|
||||
AppEvent event;
|
||||
event.type = EventTypeRx;
|
||||
@ -202,11 +203,7 @@ void lf_rfid_workaround(void* p) {
|
||||
widget_input_callback_set(widget, input_callback, event_queue);
|
||||
|
||||
// Open GUI and register widget
|
||||
Gui* gui = (Gui*)furi_open("gui");
|
||||
if(gui == NULL) {
|
||||
printf("gui is not available\n");
|
||||
furiac_exit(NULL);
|
||||
}
|
||||
Gui* gui = furi_record_open("gui");
|
||||
gui_add_widget(gui, widget, GuiLayerFullscreen);
|
||||
|
||||
AppEvent event;
|
||||
|
@ -1,9 +1,8 @@
|
||||
#include "menu.h"
|
||||
#include <cmsis_os.h>
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <flipper_v2.h>
|
||||
#include <furi.h>
|
||||
#include <gui/gui.h>
|
||||
#include <gui/elements.h>
|
||||
|
||||
@ -42,8 +41,7 @@ ValueMutex* menu_init() {
|
||||
menu->widget = widget_alloc();
|
||||
|
||||
// Open GUI and register fullscreen widget
|
||||
Gui* gui = furi_open("gui");
|
||||
furi_check(gui);
|
||||
Gui* gui = furi_record_open("gui");
|
||||
gui_add_widget(gui, menu->widget, GuiLayerFullscreen);
|
||||
|
||||
widget_enabled_set(menu->widget, false);
|
||||
@ -237,12 +235,7 @@ void menu_task(void* p) {
|
||||
release_mutex(menu_mutex, menu);
|
||||
}
|
||||
|
||||
if(!furi_create("menu", menu_mutex)) {
|
||||
printf("[menu_task] cannot create the menu record\n");
|
||||
furiac_exit(NULL);
|
||||
}
|
||||
|
||||
furiac_ready();
|
||||
furi_record_create("menu", menu_mutex);
|
||||
|
||||
while(1) {
|
||||
MenuMessage m = menu_event_next(menu_event);
|
||||
|
@ -1,11 +1,9 @@
|
||||
#include "menu_event.h"
|
||||
|
||||
#include <cmsis_os.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <flipper.h>
|
||||
#include <flipper_v2.h>
|
||||
#include <furi.h>
|
||||
|
||||
#define MENU_MESSAGE_MQUEUE_SIZE 8
|
||||
|
||||
|
@ -1,8 +1,7 @@
|
||||
#include "menu_item.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <flipper.h>
|
||||
#include <flipper_v2.h>
|
||||
#include <furi.h>
|
||||
|
||||
struct MenuItem {
|
||||
MenuItemType type;
|
||||
|
@ -1,4 +1,6 @@
|
||||
#include "flipper_v2.h"
|
||||
#include <furi.h>
|
||||
#include <gui/gui.h>
|
||||
#include <input/input.h>
|
||||
|
||||
// TODO float note freq
|
||||
typedef enum {
|
||||
@ -302,7 +304,7 @@ static void render_callback(Canvas* canvas, void* ctx) {
|
||||
}
|
||||
|
||||
static void input_callback(InputEvent* input_event, void* ctx) {
|
||||
osMessageQueueId_t event_queue = (QueueHandle_t)ctx;
|
||||
osMessageQueueId_t event_queue = ctx;
|
||||
|
||||
MusicDemoEvent event;
|
||||
event.type = EventTypeKey;
|
||||
@ -376,15 +378,11 @@ void music_player(void* p) {
|
||||
widget_input_callback_set(widget, input_callback, event_queue);
|
||||
|
||||
// Open GUI and register widget
|
||||
Gui* gui = (Gui*)furi_open("gui");
|
||||
if(gui == NULL) {
|
||||
printf("gui is not available\n");
|
||||
furiac_exit(NULL);
|
||||
}
|
||||
Gui* gui = furi_record_open("gui");
|
||||
gui_add_widget(gui, widget, GuiLayerFullscreen);
|
||||
|
||||
// open input record
|
||||
PubSub* input_events_record = furi_open("input_events");
|
||||
PubSub* input_events_record = furi_record_open("input_events");
|
||||
// prepare "do nothing" event
|
||||
InputEvent input_event = {InputRight, true};
|
||||
|
||||
|
@ -16,8 +16,7 @@ Nfc* nfc_alloc() {
|
||||
nfc->worker = nfc_worker_alloc(nfc->message_queue);
|
||||
|
||||
nfc->icon = assets_icons_get(A_NFC_14);
|
||||
nfc->menu_vm = furi_open("menu");
|
||||
furi_check(nfc->menu_vm);
|
||||
nfc->menu_vm = furi_record_open("menu");
|
||||
|
||||
nfc->menu = menu_item_alloc_menu("NFC", nfc->icon);
|
||||
menu_item_subitem_add(
|
||||
@ -102,18 +101,13 @@ void nfc_start(Nfc* nfc, NfcView view_id, NfcWorkerState worker_state) {
|
||||
void nfc_task(void* p) {
|
||||
Nfc* nfc = nfc_alloc();
|
||||
|
||||
Gui* gui = furi_open("gui");
|
||||
Gui* gui = furi_record_open("gui");
|
||||
view_dispatcher_attach_to_gui(nfc->view_dispatcher, gui, ViewDispatcherTypeFullscreen);
|
||||
|
||||
with_value_mutex(
|
||||
nfc->menu_vm, (Menu * menu) { menu_item_add(menu, nfc->menu); });
|
||||
|
||||
if(!furi_create("nfc", nfc)) {
|
||||
printf("[nfc_task] cannot create nfc record\n");
|
||||
furiac_exit(NULL);
|
||||
}
|
||||
|
||||
furiac_ready();
|
||||
furi_record_create("nfc", nfc);
|
||||
|
||||
NfcMessage message;
|
||||
while(1) {
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include "nfc_views.h"
|
||||
#include "nfc_worker.h"
|
||||
|
||||
#include <flipper_v2.h>
|
||||
#include <furi.h>
|
||||
|
||||
#include <gui/gui.h>
|
||||
#include <gui/view.h>
|
||||
|
@ -3,7 +3,7 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <gui/canvas.h>
|
||||
#include <flipper_v2.h>
|
||||
#include <furi.h>
|
||||
|
||||
#include "nfc_types.h"
|
||||
|
||||
|
@ -3,8 +3,7 @@
|
||||
#include "nfc_types.h"
|
||||
#include "nfc_worker.h"
|
||||
|
||||
#include <flipper_v2.h>
|
||||
#include <cmsis_os2.h>
|
||||
#include <furi.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <rfal_analogConfig.h>
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include "power.h"
|
||||
#include "power_views.h"
|
||||
|
||||
#include <flipper_v2.h>
|
||||
#include <furi.h>
|
||||
|
||||
#include <menu/menu.h>
|
||||
#include <menu/menu_item.h>
|
||||
@ -12,8 +12,8 @@
|
||||
#include <gui/view_dispatcher.h>
|
||||
|
||||
#include <assets_icons.h>
|
||||
#include <api-hal-power.h>
|
||||
#include <cli/cli.h>
|
||||
#include <stm32wbxx.h>
|
||||
|
||||
struct Power {
|
||||
ViewDispatcher* view_dispatcher;
|
||||
@ -47,6 +47,10 @@ void power_draw_battery_callback(Canvas* canvas, void* context) {
|
||||
});
|
||||
}
|
||||
|
||||
uint32_t power_info_back_callback(void* context) {
|
||||
return VIEW_NONE;
|
||||
}
|
||||
|
||||
void power_menu_off_callback(void* context) {
|
||||
api_hal_power_off();
|
||||
}
|
||||
@ -71,10 +75,9 @@ void power_menu_info_callback(void* context) {
|
||||
Power* power_alloc() {
|
||||
Power* power = furi_alloc(sizeof(Power));
|
||||
|
||||
power->menu_vm = furi_open("menu");
|
||||
furi_check(power->menu_vm);
|
||||
power->menu_vm = furi_record_open("menu");
|
||||
|
||||
power->cli = furi_open("cli");
|
||||
power->cli = furi_record_open("cli");
|
||||
|
||||
power->menu = menu_item_alloc_menu("Power", NULL);
|
||||
menu_item_subitem_add(
|
||||
@ -163,7 +166,7 @@ void power_task(void* p) {
|
||||
cli_add_command(power->cli, "power_otg_off", power_cli_otg_off, power);
|
||||
}
|
||||
|
||||
Gui* gui = furi_open("gui");
|
||||
Gui* gui = furi_record_open("gui");
|
||||
gui_add_widget(gui, power->usb_widget, GuiLayerStatusBarLeft);
|
||||
gui_add_widget(gui, power->battery_widget, GuiLayerStatusBarRight);
|
||||
view_dispatcher_attach_to_gui(power->view_dispatcher, gui, ViewDispatcherTypeFullscreen);
|
||||
@ -171,14 +174,9 @@ void power_task(void* p) {
|
||||
with_value_mutex(
|
||||
power->menu_vm, (Menu * menu) { menu_item_add(menu, power->menu); });
|
||||
|
||||
if(!furi_create("power", power)) {
|
||||
printf("[power_task] unable to create power record\n");
|
||||
furiac_exit(NULL);
|
||||
}
|
||||
|
||||
api_hal_power_init();
|
||||
|
||||
furiac_ready();
|
||||
furi_record_create("power", power);
|
||||
|
||||
while(1) {
|
||||
with_view_model(
|
||||
|
@ -2,8 +2,8 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <furi.h>
|
||||
#include <gui/canvas.h>
|
||||
#include <flipper_v2.h>
|
||||
#include <gui/view.h>
|
||||
|
||||
typedef enum { PowerViewInfo } PowerView;
|
||||
@ -24,8 +24,4 @@ typedef struct {
|
||||
uint8_t charge;
|
||||
} PowerInfoModel;
|
||||
|
||||
static uint32_t power_info_back_callback(void* context) {
|
||||
return VIEW_NONE;
|
||||
}
|
||||
|
||||
void power_info_draw_callback(Canvas* canvas, void* context);
|
||||
|
@ -104,23 +104,21 @@ void SdTest::run() {
|
||||
|
||||
app_ready();
|
||||
|
||||
fs_api = static_cast<FS_Api*>(furi_open("sdcard"));
|
||||
fs_api = static_cast<FS_Api*>(furi_record_open("sdcard"));
|
||||
|
||||
if(fs_api == NULL) {
|
||||
set_error({"cannot get sdcard api"});
|
||||
exit();
|
||||
}
|
||||
|
||||
Cli* cli = static_cast<Cli*>(furi_open("cli"));
|
||||
Cli* cli = static_cast<Cli*>(furi_record_open("cli"));
|
||||
|
||||
if(cli != NULL) {
|
||||
// read_benchmark and write_benchmark signatures are same. so we must use tags
|
||||
auto cli_read_cb = cbc::obtain_connector<0>(this, &SdTest::cli_read_benchmark);
|
||||
cli_add_command(cli, "sd_read_test", cli_read_cb, this);
|
||||
// read_benchmark and write_benchmark signatures are same. so we must use tags
|
||||
auto cli_read_cb = cbc::obtain_connector<0>(this, &SdTest::cli_read_benchmark);
|
||||
cli_add_command(cli, "sd_read_test", cli_read_cb, this);
|
||||
|
||||
auto cli_write_cb = cbc::obtain_connector<1>(this, &SdTest::cli_write_benchmark);
|
||||
cli_add_command(cli, "sd_write_test", cli_write_cb, this);
|
||||
}
|
||||
auto cli_write_cb = cbc::obtain_connector<1>(this, &SdTest::cli_write_benchmark);
|
||||
cli_add_command(cli, "sd_write_test", cli_write_cb, this);
|
||||
|
||||
detect_sd_card();
|
||||
get_sd_card_info();
|
||||
@ -893,6 +891,7 @@ template <class T> void SdTest::set_text(std::initializer_list<T> list) {
|
||||
|
||||
printf("------------------------\n");
|
||||
release_state();
|
||||
update_gui();
|
||||
}
|
||||
|
||||
// render app
|
||||
|
@ -480,22 +480,19 @@ void sd_filesystem(void* p) {
|
||||
SdApp* sd_app = sd_app_alloc();
|
||||
FS_Api* fs_api = fs_api_alloc();
|
||||
|
||||
Gui* gui = furi_open("gui");
|
||||
Gui* gui = furi_record_open("gui");
|
||||
Cli* cli = furi_record_open("cli");
|
||||
ValueMutex* menu_vm = furi_record_open("menu");
|
||||
|
||||
gui_add_widget(gui, sd_app->widget, GuiLayerFullscreen);
|
||||
gui_add_widget(gui, sd_app->icon.widget, GuiLayerStatusBarLeft);
|
||||
|
||||
Cli* cli = furi_open("cli");
|
||||
|
||||
if(cli != NULL) {
|
||||
cli_add_command(cli, "sd_status", cli_sd_status, sd_app);
|
||||
cli_add_command(cli, "sd_format", cli_sd_format, sd_app);
|
||||
cli_add_command(cli, "sd_info", cli_sd_info, sd_app);
|
||||
}
|
||||
cli_add_command(cli, "sd_status", cli_sd_status, sd_app);
|
||||
cli_add_command(cli, "sd_format", cli_sd_format, sd_app);
|
||||
cli_add_command(cli, "sd_info", cli_sd_info, sd_app);
|
||||
|
||||
// add api record
|
||||
if(!furi_create("sdcard", fs_api)) {
|
||||
furiac_exit(NULL);
|
||||
}
|
||||
furi_record_create("sdcard", fs_api);
|
||||
|
||||
// init menu
|
||||
// TODO menu icon
|
||||
@ -510,15 +507,15 @@ void sd_filesystem(void* p) {
|
||||
menu_item, menu_item_alloc_function("Eject", NULL, app_sd_eject_callback, sd_app));
|
||||
|
||||
// add item to menu
|
||||
ValueMutex* menu_vm = furi_open("menu");
|
||||
furi_check(menu_vm);
|
||||
with_value_mutex(
|
||||
menu_vm, (Menu * menu) { menu_item_add(menu, menu_item); });
|
||||
|
||||
furiac_ready();
|
||||
|
||||
printf("[sd_filesystem] start\n");
|
||||
|
||||
// add api record
|
||||
furi_record_create("sdcard", fs_api);
|
||||
|
||||
// sd card cycle
|
||||
bool sd_was_present = true;
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
#pragma once
|
||||
#include "flipper.h"
|
||||
#include "flipper_v2.h"
|
||||
|
||||
#include <furi.h>
|
||||
#include <gui/gui.h>
|
||||
#include <input/input.h>
|
||||
|
||||
#define SD_FS_MAX_FILES _FS_LOCK
|
||||
#define SD_STATE_LINES_COUNT 6
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "flipper_v2.h"
|
||||
#include <furi.h>
|
||||
|
||||
typedef enum {
|
||||
EventTypeTick,
|
||||
@ -54,7 +54,7 @@ void template_app(void* p) {
|
||||
widget_input_callback_set(widget, input_callback, event_queue);
|
||||
|
||||
// Open GUI and register widget
|
||||
Gui* gui = (Gui*)furi_open("gui");
|
||||
Gui* gui = furi_record_open("gui");
|
||||
if(gui == NULL) {
|
||||
printf("gui is not available\n");
|
||||
furiac_exit(NULL);
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "flipper_v2.h"
|
||||
#include <furi.h>
|
||||
#include "minunit.h"
|
||||
|
||||
static void furi_concurent_app(void* p) {
|
||||
@ -10,7 +10,9 @@ static void furi_concurent_app(void* p) {
|
||||
}
|
||||
|
||||
void test_furi_event() {
|
||||
Event event;
|
||||
mu_assert(false, "please reimplement or delete test");
|
||||
|
||||
/*Event event;
|
||||
|
||||
mu_check(init_event(&event));
|
||||
|
||||
@ -27,5 +29,5 @@ void test_furi_event() {
|
||||
// The event should not be signalled once it's processed
|
||||
mu_check(!wait_event_with_timeout(&event, 100));
|
||||
|
||||
mu_check(delete_event(&event));
|
||||
mu_check(delete_event(&event));*/
|
||||
}
|
||||
|
@ -1,8 +1,6 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "flipper_v2.h"
|
||||
#include "log.h"
|
||||
|
||||
#include <furi.h>
|
||||
#include "minunit.h"
|
||||
|
||||
const uint32_t context_value = 0xdeadbeef;
|
||||
|
@ -1,16 +1,14 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "flipper.h"
|
||||
#include "flipper_v2.h"
|
||||
#include "log.h"
|
||||
#include <furi.h>
|
||||
#include "minunit.h"
|
||||
|
||||
void test_furi_create_open() {
|
||||
// 1. Create record
|
||||
uint8_t test_data = 0;
|
||||
mu_check(furi_create("test/holding", (void*)&test_data));
|
||||
furi_record_create("test/holding", (void*)&test_data);
|
||||
|
||||
// 2. Open it
|
||||
void* record = furi_open("test/holding");
|
||||
void* record = furi_record_open("test/holding");
|
||||
mu_assert_pointers_eq(record, &test_data);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "flipper_v2.h"
|
||||
#include <furi.h>
|
||||
#include "minunit.h"
|
||||
#include <stdint.h>
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "flipper_v2.h"
|
||||
#include "log.h"
|
||||
#include <furi.h>
|
||||
|
||||
#include "minunit.h"
|
||||
|
||||
@ -88,6 +87,8 @@ void furi_concurent_app(void* p) {
|
||||
}
|
||||
|
||||
void test_furi_concurrent_access() {
|
||||
mu_assert(false, "please reimplement or delete test");
|
||||
/*
|
||||
// 1. Create holding record
|
||||
ConcurrentValue value = {.a = 0, .b = 0};
|
||||
ValueMutex mutex;
|
||||
@ -123,4 +124,5 @@ void test_furi_concurrent_access() {
|
||||
mu_assert_int_eq(value.a, value.b);
|
||||
|
||||
mu_check(delete_mutex(&mutex));
|
||||
*/
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "flipper.h"
|
||||
#include "log.h"
|
||||
#include <furi.h>
|
||||
|
||||
/*
|
||||
Test: creating and killing task
|
||||
@ -24,6 +23,8 @@ void create_kill_app(void* p) {
|
||||
}
|
||||
|
||||
bool test_furi_ac_create_kill() {
|
||||
mu_assert(false, "please reimplement or delete test");
|
||||
/*
|
||||
uint8_t counter = 0;
|
||||
|
||||
uint8_t value_a = counter;
|
||||
@ -56,6 +57,7 @@ bool test_furi_ac_create_kill() {
|
||||
}
|
||||
|
||||
return true;
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1,6 +1,5 @@
|
||||
#include <stdio.h>
|
||||
#include "flipper.h"
|
||||
#include "log.h"
|
||||
#include <furi.h>
|
||||
#include "minunit_vars.h"
|
||||
#include "minunit.h"
|
||||
|
||||
|
@ -1,7 +1,5 @@
|
||||
#include <stdio.h>
|
||||
#include "flipper.h"
|
||||
#include "flipper_v2.h"
|
||||
#include "log.h"
|
||||
#include <furi.h>
|
||||
|
||||
// #include "flipper-core.h" TODO: Rust build disabled
|
||||
|
||||
|
@ -1,47 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "flipper.h"
|
||||
|
||||
// == Flipper Application control (flapp) ==
|
||||
|
||||
typedef FlappHandler uint32_t; // TODO
|
||||
|
||||
/*
|
||||
simply starts application. It call `app` entrypoint with `param` passed as argument
|
||||
Useful for daemon applications and pop-up.
|
||||
*/
|
||||
FlappHandler* flapp_start(void(app*)(void*), char* name, void* param);
|
||||
|
||||
/*
|
||||
swtich to other application.
|
||||
System **stop current app**, call `app` entrypoint with `param` passed
|
||||
as argument and save current application entrypoint to `prev` field in
|
||||
current application registry. Useful for UI or "active" application.
|
||||
*/
|
||||
FlappHandler* flapp_switch(void(app*)(void*), char* name, void* param);
|
||||
|
||||
/*
|
||||
Exit application
|
||||
stop current application (stop thread and clear application's stack),
|
||||
start application from `prev` entry in current application registry,
|
||||
cleanup current application registry.
|
||||
*/
|
||||
void flapp_exit(void* param);
|
||||
|
||||
/*
|
||||
stop specified `app` without returning to `prev` application.
|
||||
*/
|
||||
bool flapp_kill(FlappHandler* app);
|
||||
|
||||
/*
|
||||
If case one app depend on other, notify that app is ready.
|
||||
*/
|
||||
void flapp_ready();
|
||||
|
||||
/*
|
||||
Register on-exit callback.
|
||||
It called before app will be killed.
|
||||
Not recommended to use in user scenario, only for system purpose
|
||||
(unregister callbacks, release mutexes, etc.)
|
||||
*/
|
||||
bool flapp_on_exit(void(cb*)(void*), void* ctx);
|
@ -1,14 +0,0 @@
|
||||
#include "furi.h"
|
||||
#include "furi-deprecated.h"
|
||||
|
||||
bool furi_create(const char* name, void* ptr) {
|
||||
return furi_create_deprecated(name, ptr, sizeof(size_t));
|
||||
}
|
||||
|
||||
void* furi_open(const char* name) {
|
||||
FuriRecordSubscriber* record = furi_open_deprecated(name, false, false, NULL, NULL, NULL);
|
||||
void* res = furi_take(record);
|
||||
furi_give(record);
|
||||
|
||||
return res;
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "flipper.h"
|
||||
|
||||
/*
|
||||
== Flipper universal registry implementation (FURI) ==
|
||||
|
||||
## Requirements
|
||||
|
||||
* start daemon app
|
||||
* kill app
|
||||
* start child thread (kill when parent app was killed)
|
||||
* switch between UI apps
|
||||
*/
|
||||
|
||||
/*
|
||||
Create record.
|
||||
creates new record in registry and store pointer into it
|
||||
*/
|
||||
bool furi_create(const char* name, void* ptr);
|
||||
|
||||
/*
|
||||
Open record.
|
||||
get stored pointer by its name
|
||||
*/
|
||||
void* furi_open(const char* name);
|
@ -1,4 +1,6 @@
|
||||
#include "api-gpio.h"
|
||||
#include <cmsis_os2.h>
|
||||
#include <furi/record.h>
|
||||
|
||||
osMutexId_t gpioInitMutex;
|
||||
|
||||
@ -37,7 +39,7 @@ void gpio_disable(GpioDisableRecord* gpio_record) {
|
||||
|
||||
// get GPIO record
|
||||
ValueMutex* gpio_open_mutex(const char* name) {
|
||||
ValueMutex* gpio_mutex = (ValueMutex*)furi_open(name);
|
||||
ValueMutex* gpio_mutex = (ValueMutex*)furi_record_open(name);
|
||||
|
||||
// TODO disable gpio on app exit
|
||||
//if(gpio_mutex != NULL) flapp_on_exit(gpio_disable, gpio_mutex);
|
||||
@ -48,6 +50,6 @@ ValueMutex* gpio_open_mutex(const char* name) {
|
||||
// get GPIO record and acquire mutex
|
||||
GpioPin* gpio_open(const char* name) {
|
||||
ValueMutex* gpio_mutex = gpio_open_mutex(name);
|
||||
GpioPin* gpio_pin = acquire_mutex(gpio_mutex, FLIPPER_HELPER_TIMEOUT);
|
||||
GpioPin* gpio_pin = acquire_mutex(gpio_mutex, osWaitForever);
|
||||
return gpio_pin;
|
||||
}
|
@ -1,7 +1,11 @@
|
||||
#pragma once
|
||||
#include "flipper.h"
|
||||
#include "flipper_v2.h"
|
||||
|
||||
#include "api-hal-gpio.h"
|
||||
#include <furi/valuemutex.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
ValueMutex* gpio_mutex;
|
||||
@ -38,4 +42,8 @@ void gpio_disable(GpioDisableRecord* gpio_record);
|
||||
ValueMutex* gpio_open_mutex(const char* name);
|
||||
|
||||
// get GPIO record and acquire mutex
|
||||
GpioPin* gpio_open(const char* name);
|
||||
GpioPin* gpio_open(const char* name);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -1,5 +1,8 @@
|
||||
#include "api-interrupt-mgr.h"
|
||||
|
||||
#include <m-list.h>
|
||||
#include <cmsis_os2.h>
|
||||
|
||||
LIST_DEF(list_interrupt, InterruptCallbackItem, M_POD_OPLIST);
|
||||
list_interrupt_t interrupts;
|
||||
osMutexId_t interrupt_list_mutex;
|
||||
|
@ -1,5 +1,10 @@
|
||||
#pragma once
|
||||
#include "flipper_v2.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void (*InterruptCallback)(void*, void*);
|
||||
|
||||
@ -18,4 +23,8 @@ typedef struct {
|
||||
bool api_interrupt_init();
|
||||
void api_interrupt_add(InterruptCallback callback, InterruptType type, void* context);
|
||||
void api_interrupt_remove(InterruptCallback callback);
|
||||
void api_interrupt_call(InterruptType type, void* hw);
|
||||
void api_interrupt_call(InterruptType type, void* hw);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -1,4 +1,8 @@
|
||||
#include "flipper_v2.h"
|
||||
#include <furi.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
struct used for handling SPI info.
|
||||
@ -133,4 +137,8 @@ void cc1101_example() {
|
||||
}
|
||||
}
|
||||
```
|
||||
*/
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
48
core/app.cpp
48
core/app.cpp
@ -1,48 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include "flipper.h"
|
||||
#include "flipper_v2.h"
|
||||
|
||||
extern "C" {
|
||||
#include "log.h"
|
||||
#include "applications.h"
|
||||
#include "tty_uart.h"
|
||||
}
|
||||
|
||||
// for testing purpose
|
||||
uint32_t exitcode = 0;
|
||||
extern "C" void set_exitcode(uint32_t _exitcode) {
|
||||
exitcode = _exitcode;
|
||||
}
|
||||
|
||||
extern "C" int app() {
|
||||
init_flipper_api();
|
||||
register_tty_uart();
|
||||
|
||||
FuriRecordSubscriber* log = get_default_log();
|
||||
fuprintf(log, "\n=== Welcome to Flipper Zero! ===\n\n");
|
||||
|
||||
// FURI startup
|
||||
const size_t flipper_app_count = sizeof(FLIPPER_STARTUP) / sizeof(FLIPPER_STARTUP[0]);
|
||||
FuriApp* handlers[flipper_app_count];
|
||||
|
||||
for(size_t i = 0; i < flipper_app_count; i++) {
|
||||
// TODO create a dependency tree and run tasks in the desired order
|
||||
furiac_wait_libs(&FLIPPER_STARTUP[i].libs);
|
||||
handlers[i] = furiac_start(FLIPPER_STARTUP[i].app, FLIPPER_STARTUP[i].name, NULL);
|
||||
}
|
||||
|
||||
bool is_alive = false;
|
||||
do {
|
||||
is_alive = false;
|
||||
for(size_t i = 0; i < flipper_app_count; i++) {
|
||||
if(handlers[i]->handler != NULL) {
|
||||
is_alive = true;
|
||||
}
|
||||
}
|
||||
delay(500);
|
||||
} while(is_alive);
|
||||
|
||||
fuprintf(log, "\n=== Bye from Flipper Zero! ===\n\n");
|
||||
|
||||
return (int)exitcode;
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
CORE_DIR = $(PROJECT_ROOT)/core
|
||||
|
||||
CFLAGS += -I$(CORE_DIR)
|
||||
CFLAGS += -I$(CORE_DIR) -D_GNU_SOURCE
|
||||
ASM_SOURCES += $(wildcard $(CORE_DIR)/*.s)
|
||||
C_SOURCES += $(wildcard $(CORE_DIR)/*.c)
|
||||
C_SOURCES += $(wildcard $(CORE_DIR)/api-basic/*.c)
|
||||
C_SOURCES += $(wildcard $(CORE_DIR)/furi/*.c)
|
||||
C_SOURCES += $(wildcard $(CORE_DIR)/api-hal/*.c)
|
||||
CPP_SOURCES += $(wildcard $(CORE_DIR)/*.cpp)
|
||||
|
@ -1,24 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "api-hal.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "main.h"
|
||||
#include "cmsis_os.h"
|
||||
#include "furi-deprecated.h"
|
||||
|
||||
#include "log.h"
|
||||
#include "input/input.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
void set_exitcode(uint32_t _exitcode);
|
||||
|
||||
#define FURI_LIB (const char*[])
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -1,16 +0,0 @@
|
||||
#pragma once
|
||||
#include "stdint.h"
|
||||
|
||||
// Arduino defines
|
||||
#define pinMode gpio_init
|
||||
#define digitalWrite gpio_write
|
||||
#define digitalRead gpio_read
|
||||
#define delayMicroseconds delay_us
|
||||
#define delay osDelay
|
||||
|
||||
#define OUTPUT GpioModeOutputPushPull
|
||||
#define INPUT GpioModeInput
|
||||
#define LOW false
|
||||
#define HIGH true
|
||||
|
||||
typedef uint8_t byte;
|
@ -1,19 +0,0 @@
|
||||
#include "flipper_v2.h"
|
||||
|
||||
bool init_flipper_api(void) {
|
||||
bool no_errors = true;
|
||||
|
||||
if(!furi_init()) {
|
||||
no_errors = false;
|
||||
}
|
||||
|
||||
if(!gpio_api_init()) {
|
||||
no_errors = false;
|
||||
}
|
||||
|
||||
if(!api_interrupt_init()) {
|
||||
no_errors = false;
|
||||
}
|
||||
|
||||
return no_errors;
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "flipper.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "api-basic/furi.h"
|
||||
//#include "api-basic/flapp.h"
|
||||
#include "cmsis_os2.h"
|
||||
#include "api-basic/valuemutex.h"
|
||||
#include "api-basic/pubsub.h"
|
||||
#include "api-basic/value-expanders.h"
|
||||
#include "api-basic/event.h"
|
||||
|
||||
#include "api-basic/memmgr.h"
|
||||
#include "api-basic/check.h"
|
||||
|
||||
#include "api-hal/api-gpio.h"
|
||||
#include "api-hal/api-interrupt-mgr.h"
|
||||
#include "api-hal-resources.h"
|
||||
|
||||
#include "gui/gui.h"
|
||||
|
||||
// tmeout for helper functions
|
||||
#define FLIPPER_HELPER_TIMEOUT 10
|
||||
|
||||
bool init_flipper_api(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -1,295 +0,0 @@
|
||||
#include "furi-deprecated.h"
|
||||
#include <string.h>
|
||||
|
||||
// TODO: this file contains printf, that not implemented on uC target
|
||||
|
||||
#ifdef FURI_DEBUG
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#define MAX_RECORD_COUNT 32
|
||||
|
||||
static FuriRecord records[MAX_RECORD_COUNT];
|
||||
static size_t current_buffer_idx = 0;
|
||||
osMutexId_t furi_core_mutex;
|
||||
|
||||
bool furi_init(void) {
|
||||
furi_core_mutex = osMutexNew(NULL);
|
||||
if(furi_core_mutex == NULL) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// find record pointer by name
|
||||
static FuriRecord* find_record(const char* name) {
|
||||
if(name == NULL) return NULL;
|
||||
|
||||
FuriRecord* res = NULL;
|
||||
for(size_t i = 0; i < MAX_RECORD_COUNT; i++) {
|
||||
if(records[i].name != NULL && strcmp(name, records[i].name) == 0) {
|
||||
res = &records[i];
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
// TODO: change open-create to only open
|
||||
bool furi_create_deprecated(const char* name, void* value, size_t size) {
|
||||
#ifdef FURI_DEBUG
|
||||
printf("[FURI] creating %s record\n", name);
|
||||
#endif
|
||||
|
||||
// acquire mutex to prevent simultaneous write to record with same index
|
||||
if(osMutexAcquire(furi_core_mutex, osWaitForever) != osOK) {
|
||||
return false;
|
||||
}
|
||||
|
||||
FuriRecord* record = find_record(name);
|
||||
|
||||
if(record != NULL) {
|
||||
#ifdef FURI_DEBUG
|
||||
printf("[FURI] record already exist\n");
|
||||
#endif
|
||||
|
||||
record->value = value;
|
||||
record->size = size;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// record not exist, create new
|
||||
|
||||
if(current_buffer_idx >= MAX_RECORD_COUNT) {
|
||||
// max record count exceed
|
||||
#ifdef FURI_DEBUG
|
||||
printf("[FURI] create: max record count exceed\n");
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
records[current_buffer_idx].mute_counter = 0;
|
||||
records[current_buffer_idx].mutex =
|
||||
xSemaphoreCreateMutexStatic(&records[current_buffer_idx].mutex_buffer);
|
||||
records[current_buffer_idx].value = value;
|
||||
records[current_buffer_idx].size = size;
|
||||
records[current_buffer_idx].name = name;
|
||||
|
||||
for(size_t i = 0; i < MAX_RECORD_SUBSCRIBERS; i++) {
|
||||
records[current_buffer_idx].subscribers[i].allocated = false;
|
||||
records[current_buffer_idx].subscribers[i].ctx = NULL;
|
||||
}
|
||||
|
||||
current_buffer_idx++;
|
||||
|
||||
osMutexRelease(furi_core_mutex);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
FuriRecordSubscriber* furi_open_deprecated(
|
||||
const char* name,
|
||||
bool solo,
|
||||
bool no_mute,
|
||||
FlipperRecordCallback value_callback,
|
||||
FlipperRecordStateCallback state_callback,
|
||||
void* ctx) {
|
||||
#ifdef FURI_DEBUG
|
||||
printf("[FURI] opening %s record\n", name);
|
||||
#endif
|
||||
|
||||
// get furi record by name
|
||||
FuriRecord* record = find_record(name);
|
||||
|
||||
if(record == NULL) {
|
||||
// cannot find record
|
||||
#ifdef FURI_DEBUG
|
||||
printf("[FURI] cannot find record %s\n", name);
|
||||
#endif
|
||||
|
||||
// create record if not exist
|
||||
if(!furi_create_deprecated(name, NULL, 0)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
record = find_record(name);
|
||||
|
||||
if(record == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// allocate subscriber
|
||||
FuriRecordSubscriber* subscriber = NULL;
|
||||
|
||||
for(size_t i = 0; i < MAX_RECORD_SUBSCRIBERS; i++) {
|
||||
if(!record->subscribers[i].allocated) {
|
||||
subscriber = &record->subscribers[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(subscriber == NULL) {
|
||||
// cannot add subscriber (full)
|
||||
#ifdef FURI_DEBUG
|
||||
printf("[FURI] open: cannot add subscriber (full)\n");
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// increase mute_counter
|
||||
if(solo) {
|
||||
record->mute_counter++;
|
||||
}
|
||||
|
||||
// set all parameters
|
||||
subscriber->allocated = true;
|
||||
subscriber->mute_counter = record->mute_counter;
|
||||
subscriber->no_mute = no_mute;
|
||||
subscriber->cb = value_callback;
|
||||
subscriber->state_cb = state_callback;
|
||||
subscriber->record = record;
|
||||
subscriber->ctx = ctx;
|
||||
|
||||
// register record in application
|
||||
FuriApp* current_task = find_task(xTaskGetCurrentTaskHandle());
|
||||
|
||||
if(current_task != NULL) {
|
||||
current_task->records[current_task->records_count] = record;
|
||||
current_task->records_count++;
|
||||
} else {
|
||||
#ifdef FURI_DEBUG
|
||||
printf("[FURI] open: no current task\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
return subscriber;
|
||||
}
|
||||
|
||||
void furi_close(FuriRecordSubscriber* handler) {
|
||||
#ifdef FURI_DEBUG
|
||||
printf("[FURI] closing %s record\n", handler->record->name);
|
||||
#endif
|
||||
|
||||
// deallocate subscriber
|
||||
handler->allocated = false;
|
||||
|
||||
// set mute counter to next max value
|
||||
uint8_t max_mute_counter = 0;
|
||||
for(size_t i = 0; i < MAX_RECORD_SUBSCRIBERS; i++) {
|
||||
if(handler->record->subscribers[i].allocated) {
|
||||
if(handler->record->subscribers[i].mute_counter > max_mute_counter) {
|
||||
max_mute_counter = handler->record->subscribers[i].mute_counter;
|
||||
}
|
||||
}
|
||||
}
|
||||
handler->record->mute_counter = max_mute_counter;
|
||||
}
|
||||
|
||||
static void furi_notify(FuriRecordSubscriber* handler, const void* value, size_t size) {
|
||||
for(size_t i = 0; i < MAX_RECORD_SUBSCRIBERS; i++) {
|
||||
if(handler->record->subscribers[i].allocated) {
|
||||
if(handler->record->subscribers[i].cb != NULL) {
|
||||
handler->record->subscribers[i].cb(
|
||||
value, size, handler->record->subscribers[i].ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void* furi_take(FuriRecordSubscriber* handler) {
|
||||
if(handler == NULL || handler->record == NULL) return NULL;
|
||||
|
||||
if(xSemaphoreTake(handler->record->mutex, portMAX_DELAY) == pdTRUE) {
|
||||
return handler->record->value;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void furi_give(FuriRecordSubscriber* handler) {
|
||||
if(handler == NULL || handler->record == NULL) return;
|
||||
|
||||
xSemaphoreGive(handler->record->mutex);
|
||||
}
|
||||
|
||||
void furi_commit(FuriRecordSubscriber* handler) {
|
||||
if(handler == NULL || handler->record == NULL) return;
|
||||
|
||||
furi_notify(handler, handler->record->value, handler->record->size);
|
||||
furi_give(handler);
|
||||
}
|
||||
|
||||
bool furi_read(FuriRecordSubscriber* handler, void* value, size_t size) {
|
||||
#ifdef FURI_DEBUG
|
||||
printf("[FURI] read from %s\n", handler->record->name);
|
||||
#endif
|
||||
|
||||
if(handler == NULL || handler->record == NULL || value == NULL) return false;
|
||||
|
||||
if(size > handler->record->size) return false;
|
||||
|
||||
// return false if read from pipe
|
||||
if(handler->record->value == NULL) return false;
|
||||
|
||||
furi_take(handler);
|
||||
memcpy(value, handler->record->value, size);
|
||||
furi_notify(handler, value, size);
|
||||
furi_give(handler);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool furi_write(FuriRecordSubscriber* handler, const void* value, size_t size) {
|
||||
#ifdef FURI_DEBUG
|
||||
printf("[FURI] write to %s\n", handler->record->name);
|
||||
#endif
|
||||
|
||||
if(handler == NULL || handler->record == NULL || value == NULL) {
|
||||
#ifdef FURI_DEBUG
|
||||
printf(
|
||||
"[FURI] write: null param %x %x\n",
|
||||
(uint32_t)(size_t)handler,
|
||||
(uint32_t)(size_t)value);
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// check if closed
|
||||
if(!handler->allocated) {
|
||||
#ifdef FURI_DEBUG
|
||||
printf("[FURI] write: handler closed\n");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
if(handler->record->value != NULL && size > handler->record->size) {
|
||||
#ifdef FURI_DEBUG
|
||||
printf("[FURI] write: wrong size %d\n", (uint32_t)size);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
// check mute
|
||||
if(handler->record->mute_counter != handler->mute_counter && !handler->no_mute) {
|
||||
#ifdef FURI_DEBUG
|
||||
printf("[FURI] write: muted\n");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
furi_take(handler);
|
||||
if(handler->record->value != NULL) {
|
||||
// real write to value
|
||||
memcpy(handler->record->value, value, size);
|
||||
|
||||
// notify subscribers
|
||||
furi_notify(handler, handler->record->value, handler->record->size);
|
||||
} else {
|
||||
furi_notify(handler, value, size);
|
||||
}
|
||||
furi_give(handler);
|
||||
|
||||
return true;
|
||||
}
|
@ -1,207 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "cmsis_os.h"
|
||||
|
||||
#ifdef HAVE_FREERTOS
|
||||
#include <semphr.h>
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "assets_icons.h"
|
||||
|
||||
#define MAX_TASK_RECORDS 8
|
||||
#define MAX_RECORD_SUBSCRIBERS 8
|
||||
|
||||
inline static void* furi_alloc(size_t size) {
|
||||
void* p = malloc(size);
|
||||
assert(p);
|
||||
return memset(p, 0, size);
|
||||
}
|
||||
|
||||
/// application is just a function
|
||||
typedef void (*FlipperApplication)(void*);
|
||||
|
||||
/// pointer to value callback function
|
||||
typedef void (*FlipperRecordCallback)(const void*, size_t, void*);
|
||||
|
||||
typedef enum {
|
||||
FlipperRecordStateMute, ///< record open and mute this handler
|
||||
FlipperRecordStateUnmute, ///< record unmuted
|
||||
FlipperRecordStateDeleted ///< record owner halt
|
||||
} FlipperRecordState;
|
||||
|
||||
/// pointer to state callback function
|
||||
typedef void (*FlipperRecordStateCallback)(FlipperRecordState, void*);
|
||||
|
||||
struct _FuriRecord;
|
||||
|
||||
typedef struct {
|
||||
bool allocated;
|
||||
FlipperRecordCallback cb; ///< value cb
|
||||
FlipperRecordStateCallback state_cb; ///< state cb
|
||||
uint8_t mute_counter; ///< see "wiki/FURI#mute-algorithm"
|
||||
bool no_mute;
|
||||
struct _FuriRecord* record; ///< parent record
|
||||
void* ctx;
|
||||
} FuriRecordSubscriber;
|
||||
|
||||
/// FURI record handler
|
||||
struct _FuriRecord {
|
||||
const char* name;
|
||||
void* value;
|
||||
size_t size;
|
||||
StaticSemaphore_t mutex_buffer;
|
||||
SemaphoreHandle_t mutex;
|
||||
uint8_t mute_counter;
|
||||
FuriRecordSubscriber subscribers[MAX_RECORD_SUBSCRIBERS];
|
||||
};
|
||||
|
||||
typedef struct _FuriRecord FuriRecord;
|
||||
|
||||
/// store info about active task
|
||||
typedef struct {
|
||||
const char* name;
|
||||
FlipperApplication application;
|
||||
const char* prev_name;
|
||||
FlipperApplication prev;
|
||||
TaskHandle_t handler;
|
||||
uint8_t records_count; ///< count of records which task open
|
||||
FuriRecord* records[MAX_TASK_RECORDS]; ///< list of records which task open
|
||||
|
||||
bool ready;
|
||||
} FuriApp;
|
||||
|
||||
// application dependency info
|
||||
typedef struct {
|
||||
uint8_t count;
|
||||
const char** name;
|
||||
} FlipperAppLibrary;
|
||||
|
||||
// application startup info
|
||||
typedef struct {
|
||||
FlipperApplication app;
|
||||
const char* name;
|
||||
FlipperAppLibrary libs;
|
||||
IconName icon;
|
||||
} FlipperStartupApp;
|
||||
|
||||
// Init core
|
||||
bool furi_init(void);
|
||||
|
||||
/*!
|
||||
Simply starts application.
|
||||
It call app entrypoint with param passed as argument.
|
||||
Useful for daemon applications and pop-up.
|
||||
*/
|
||||
FuriApp* furiac_start(FlipperApplication app, const char* name, void* param);
|
||||
|
||||
/*!
|
||||
Swtich to other application.
|
||||
FURI stop current app, call app entrypoint with param passed as
|
||||
argument and save current application entrypoint to prev field
|
||||
in current application registry.
|
||||
Useful for UI or "active" application.
|
||||
*/
|
||||
void furiac_switch(FlipperApplication app, char* name, void* param);
|
||||
|
||||
/*!
|
||||
Stop current application
|
||||
(stop thread and clear application's stack), start application
|
||||
from prev entry in current application registry, cleanup current
|
||||
application registry.
|
||||
*/
|
||||
void furiac_exit(void* param);
|
||||
|
||||
/*!
|
||||
Mark application as prepared and ready to perform actions
|
||||
*/
|
||||
void furiac_ready();
|
||||
|
||||
/*
|
||||
Wait for the libraries we depend on
|
||||
*/
|
||||
void furiac_wait_libs(const FlipperAppLibrary* libs);
|
||||
|
||||
/*!
|
||||
Stop specified app without returning to prev application.
|
||||
*/
|
||||
bool furiac_kill(FuriApp* app);
|
||||
|
||||
// find task pointer by handle
|
||||
FuriApp* find_task(TaskHandle_t handler);
|
||||
|
||||
/*!
|
||||
Creates named FURI record.
|
||||
\param[in] name you can open this record anywhere
|
||||
\param[in] value pointer to data.
|
||||
\param[in] size size of data.
|
||||
If NULL, create FURI Pipe (only callbacks management, no data/mutex)
|
||||
|
||||
Returns false if registry have not enough memory for creating.
|
||||
*/
|
||||
bool furi_create_deprecated(const char* name, void* value, size_t size);
|
||||
|
||||
/*!
|
||||
Opens existing FURI record by name.
|
||||
Returns NULL if record does not exist.
|
||||
\param[in] solo if true another applications handlers set into "muted" state.
|
||||
When appication has exited or record has closed, all handlers is unmuted.
|
||||
It may be useful for concurrently acces to resources like framebuffer or beeper.
|
||||
\param[in] no_mute if true, another applications cannot mute this handler.
|
||||
*/
|
||||
FuriRecordSubscriber* furi_open_deprecated(
|
||||
const char* name,
|
||||
bool solo,
|
||||
bool no_mute,
|
||||
FlipperRecordCallback value_callback,
|
||||
FlipperRecordStateCallback state_callback,
|
||||
void* ctx);
|
||||
|
||||
/*!
|
||||
|
||||
*/
|
||||
void furi_close(FuriRecordSubscriber* handler);
|
||||
|
||||
/*!
|
||||
read message from record.
|
||||
Returns true if success, false otherwise (closed/non-existent record)
|
||||
Also return false if you try to read from FURI pipe
|
||||
|
||||
TODO: enum return value with execution status
|
||||
*/
|
||||
bool furi_read(FuriRecordSubscriber* record, void* data, size_t size);
|
||||
|
||||
/*!
|
||||
write message to record.
|
||||
Returns true if success, false otherwise (closed/non-existent record or muted).
|
||||
|
||||
TODO: enum return value with execution status
|
||||
*/
|
||||
bool furi_write(FuriRecordSubscriber* record, const void* data, size_t size);
|
||||
|
||||
/*!
|
||||
lock value mutex.
|
||||
It can be useful if records contain pointer to buffer which you want to change.
|
||||
You must call furi_give after operation on data and
|
||||
you shouldn't block executing between take and give calls
|
||||
|
||||
Returns pointer to data, NULL if closed/non-existent record or muted
|
||||
|
||||
TODO: enum return value with execution status
|
||||
*/
|
||||
void* furi_take(FuriRecordSubscriber* record);
|
||||
|
||||
/*!
|
||||
unlock value mutex.
|
||||
*/
|
||||
void furi_give(FuriRecordSubscriber* record);
|
||||
|
||||
/*!
|
||||
unlock value mutex and notify subscribers that data is chaned.
|
||||
*/
|
||||
void furi_commit(FuriRecordSubscriber* handler);
|
36
core/furi.c
Normal file
36
core/furi.c
Normal file
@ -0,0 +1,36 @@
|
||||
#include "furi.h"
|
||||
#include <applications.h>
|
||||
|
||||
// for testing purpose
|
||||
uint32_t exitcode = 0;
|
||||
|
||||
void set_exitcode(uint32_t _exitcode) {
|
||||
exitcode = _exitcode;
|
||||
}
|
||||
|
||||
void furi_init() {
|
||||
gpio_api_init();
|
||||
api_interrupt_init();
|
||||
furi_record_init();
|
||||
furi_stdglue_init();
|
||||
}
|
||||
|
||||
int systemd() {
|
||||
furi_init();
|
||||
|
||||
// FURI startup
|
||||
for(size_t i = 0; i < FLIPPER_SERVICES_size(); i++) {
|
||||
osThreadAttr_t* attr = furi_alloc(sizeof(osThreadAttr_t));
|
||||
attr->name = FLIPPER_SERVICES[i].name;
|
||||
attr->stack_size = 1024;
|
||||
osThreadNew(FLIPPER_SERVICES[i].app, NULL, attr);
|
||||
}
|
||||
|
||||
while(1) {
|
||||
osThreadSuspend(osThreadGetId());
|
||||
}
|
||||
|
||||
printf("\n=== Bye from Flipper Zero! ===\n\n");
|
||||
|
||||
return (int)exitcode;
|
||||
}
|
28
core/furi.h
Normal file
28
core/furi.h
Normal file
@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include <cmsis_os2.h>
|
||||
|
||||
#include <furi/check.h>
|
||||
#include <furi/event.h>
|
||||
#include <furi/memmgr.h>
|
||||
#include <furi/pubsub.h>
|
||||
#include <furi/record.h>
|
||||
#include <furi/stdglue.h>
|
||||
#include <furi/value-expanders.h>
|
||||
#include <furi/valuemutex.h>
|
||||
|
||||
#include <api-hal/api-gpio.h>
|
||||
#include <api-hal/api-interrupt-mgr.h>
|
||||
|
||||
#include <api-hal.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define furiac_exit(ptr) osThreadExit()
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -1,5 +1,6 @@
|
||||
#include "check.h"
|
||||
#include "api-hal-task.h"
|
||||
#include <stdio.h>
|
||||
|
||||
void __furi_abort(void);
|
||||
|
||||
@ -22,20 +23,21 @@ void __furi_check_debug(const char* file, int line, const char* function, const
|
||||
if(task_is_isr_context()) {
|
||||
printf(" in [ISR] context");
|
||||
} else {
|
||||
FuriApp* app = find_task(xTaskGetCurrentTaskHandle());
|
||||
// FuriApp* app = find_task(xTaskGetCurrentTaskHandle());
|
||||
|
||||
if(app == NULL) {
|
||||
printf(", in [main] context");
|
||||
} else {
|
||||
printf(", in [%s] app context", app->name);
|
||||
}
|
||||
// if(app == NULL) {
|
||||
// printf(", in [main] context");
|
||||
// } else {
|
||||
// printf(", in [%s] app context", app->name);
|
||||
// }
|
||||
}
|
||||
|
||||
__furi_abort();
|
||||
}
|
||||
|
||||
void __furi_abort(void) {
|
||||
taskDISABLE_INTERRUPTS();
|
||||
__disable_irq();
|
||||
asm("bkpt 1");
|
||||
while(1) {
|
||||
}
|
||||
}
|
@ -1,6 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "flipper.h"
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Find how to how get function's pretty name
|
||||
#ifndef __FURI_CHECK_FUNC
|
||||
@ -38,4 +40,8 @@
|
||||
// !NDEBUG
|
||||
|
||||
void __furi_check(void);
|
||||
void __furi_check_debug(const char* file, int line, const char* function, const char* condition);
|
||||
void __furi_check_debug(const char* file, int line, const char* function, const char* condition);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user