diff --git a/applications/applications.c b/applications/applications.c index 9c014450..f16d1fde 100755 --- a/applications/applications.c +++ b/applications/applications.c @@ -20,7 +20,7 @@ extern int32_t accessor_app(void* p); extern int32_t archive_app(void* p); extern int32_t blink_test_app(void* p); extern int32_t flipper_test_app(void* p); -extern int32_t gpio_test_app(void* p); +extern int32_t gpio_app(void* p); extern int32_t ibutton_app(void* p); extern int32_t irda_app(void* p); extern int32_t irda_monitor_app(void* p); @@ -132,8 +132,8 @@ const FlipperApplication FLIPPER_APPS[] = { {.app = ibutton_app, .name = "iButton", .stack_size = 2048, .icon = &A_iButton_14}, #endif -#ifdef APP_GPIO_TEST - {.app = gpio_test_app, .name = "GPIO", .stack_size = 1024, .icon = &A_GPIO_14}, +#ifdef APP_GPIO + {.app = gpio_app, .name = "GPIO", .stack_size = 1024, .icon = &A_GPIO_14}, #endif }; diff --git a/applications/applications.mk b/applications/applications.mk index 191a5427..2d6820b5 100644 --- a/applications/applications.mk +++ b/applications/applications.mk @@ -24,7 +24,7 @@ SRV_STORAGE = 1 # Apps SRV_DESKTOP = 1 APP_ARCHIVE = 1 -APP_GPIO_TEST = 1 +APP_GPIO = 1 APP_IBUTTON = 1 APP_IRDA = 1 APP_LF_RFID = 1 @@ -135,9 +135,9 @@ SRV_GUI = 1 endif -APP_GPIO_TEST ?= 0 -ifeq ($(APP_GPIO_TEST), 1) -CFLAGS += -DAPP_GPIO_TEST +APP_GPIO ?= 0 +ifeq ($(APP_GPIO), 1) +CFLAGS += -DAPP_GPIO SRV_GUI = 1 endif diff --git a/applications/gpio-tester/gpio-tester.c b/applications/gpio-tester/gpio-tester.c deleted file mode 100644 index e994ad73..00000000 --- a/applications/gpio-tester/gpio-tester.c +++ /dev/null @@ -1,148 +0,0 @@ -#include -#include - -#include -#include - -typedef struct { - const char* name; - const GpioPin* pin; -} GpioItem; - -static const GpioItem GPIO_PINS[] = { - {"1.2: PA7", &gpio_ext_pa7}, - {"1.3: PA6", &gpio_ext_pa6}, - {"1.4: PA4", &gpio_ext_pa4}, - {"1.5: PB3", &gpio_ext_pb3}, - {"1.6: PB2", &gpio_ext_pb2}, - {"1.7: PC3", &gpio_ext_pc3}, - {"2.7: PC1", &gpio_ext_pc1}, - {"2.8: PC0", &gpio_ext_pc0}, - {"*.*: ALL", NULL}, -}; - -static const size_t GPIO_PINS_COUNT = sizeof(GPIO_PINS) / sizeof(GPIO_PINS[0]); - -typedef struct { - osMessageQueueId_t input_queue; - uint8_t gpio_index; - ViewPort* view_port; - Gui* gui; - NotificationApp* notification; -} GpioTest; - -static void gpio_test_render_callback(Canvas* canvas, void* ctx) { - GpioTest* gpio_test = ctx; - - canvas_clear(canvas); - canvas_set_color(canvas, ColorBlack); - canvas_set_font(canvas, FontPrimary); - canvas_draw_str(canvas, 2, 10, "GPIO Control"); - canvas_set_font(canvas, FontSecondary); - canvas_draw_str(canvas, 2, 25, GPIO_PINS[gpio_test->gpio_index].name); -} - -static void gpio_test_input_callback(InputEvent* input_event, void* ctx) { - GpioTest* gpio_test = ctx; - - osMessageQueuePut(gpio_test->input_queue, input_event, 0, 0); -} - -static void gpio_test_configure_pins(GpioMode mode) { - for(size_t i = 0; i < GPIO_PINS_COUNT; i++) { - if(!GPIO_PINS[i].pin) continue; - hal_gpio_write(GPIO_PINS[i].pin, false); - hal_gpio_init(GPIO_PINS[i].pin, mode, GpioPullNo, GpioSpeedVeryHigh); - } -} - -static void gpio_test_set_pin(uint8_t index, bool level) { - if(GPIO_PINS[index].pin) { - hal_gpio_write(GPIO_PINS[index].pin, level); - } else { - for(size_t i = 0; i < GPIO_PINS_COUNT; i++) { - if(!GPIO_PINS[i].pin) continue; - hal_gpio_write(GPIO_PINS[i].pin, level); - } - } -} - -GpioTest* gpio_test_alloc() { - GpioTest* instance = furi_alloc(sizeof(GpioTest)); - - gpio_test_configure_pins(GpioModeOutputPushPull); - - instance->input_queue = osMessageQueueNew(8, sizeof(InputEvent), NULL); - furi_check(instance->input_queue); - - instance->view_port = view_port_alloc(); - view_port_draw_callback_set(instance->view_port, gpio_test_render_callback, instance); - view_port_input_callback_set(instance->view_port, gpio_test_input_callback, instance); - - instance->gui = furi_record_open("gui"); - gui_add_view_port(instance->gui, instance->view_port, GuiLayerFullscreen); - - instance->notification = furi_record_open("notification"); - - return instance; -} - -void gpio_test_free(GpioTest* instance) { - furi_assert(instance); - - furi_record_close("notification"); - - view_port_enabled_set(instance->view_port, false); - gui_remove_view_port(instance->gui, instance->view_port); - furi_record_close("gui"); - - view_port_free(instance->view_port); - - osMessageQueueDelete(instance->input_queue); - - gpio_test_configure_pins(GpioModeAnalog); - - free(instance); -} - -int32_t gpio_test_app(void* p) { - GpioTest* gpio_test = gpio_test_alloc(); - - InputEvent event; - while(osMessageQueueGet(gpio_test->input_queue, &event, NULL, osWaitForever) == osOK) { - if(event.type == InputTypeShort) { - if(event.key == InputKeyBack) { - notification_message(gpio_test->notification, &sequence_reset_green); - break; - } - - if(event.key == InputKeyRight) { - if(gpio_test->gpio_index < (GPIO_PINS_COUNT - 1)) { - gpio_test->gpio_index++; - } - } - - if(event.key == InputKeyLeft) { - if(gpio_test->gpio_index > 0) { - gpio_test->gpio_index--; - } - } - } else { - if(event.key == InputKeyOk) { - if(event.type == InputTypePress) { - gpio_test_set_pin(gpio_test->gpio_index, true); - notification_message(gpio_test->notification, &sequence_set_green_255); - } else if(event.type == InputTypeRelease) { - gpio_test_set_pin(gpio_test->gpio_index, false); - notification_message(gpio_test->notification, &sequence_reset_green); - } - } - } - - view_port_update(gpio_test->view_port); - } - - gpio_test_free(gpio_test); - - return 0; -} diff --git a/applications/gpio/gpio_app.c b/applications/gpio/gpio_app.c new file mode 100755 index 00000000..32d92af0 --- /dev/null +++ b/applications/gpio/gpio_app.c @@ -0,0 +1,76 @@ +#include "gpio_app_i.h" + +#include +#include + +static bool gpio_app_custom_event_callback(void* context, uint32_t event) { + furi_assert(context); + GpioApp* app = context; + return scene_manager_handle_custom_event(app->scene_manager, event); +} + +static bool gpio_app_back_event_callback(void* context) { + furi_assert(context); + GpioApp* app = context; + return scene_manager_handle_back_event(app->scene_manager); +} + +GpioApp* gpio_app_alloc() { + GpioApp* app = furi_alloc(sizeof(GpioApp)); + + app->gui = furi_record_open("gui"); + app->notifications = furi_record_open("notification"); + + app->view_dispatcher = view_dispatcher_alloc(); + app->scene_manager = scene_manager_alloc(&gpio_scene_handlers, app); + view_dispatcher_enable_queue(app->view_dispatcher); + view_dispatcher_set_event_callback_context(app->view_dispatcher, app); + + view_dispatcher_set_custom_event_callback( + app->view_dispatcher, gpio_app_custom_event_callback); + view_dispatcher_set_navigation_event_callback( + app->view_dispatcher, gpio_app_back_event_callback); + + view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); + + app->var_item_list = variable_item_list_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, + GpioAppViewVarItemList, + variable_item_list_get_view(app->var_item_list)); + app->gpio_test = gpio_test_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, GpioAppViewGpioTest, gpio_test_get_view(app->gpio_test)); + + scene_manager_next_scene(app->scene_manager, GpioSceneStart); + + return app; +} + +void gpio_app_free(GpioApp* app) { + furi_assert(app); + + // Views + view_dispatcher_remove_view(app->view_dispatcher, GpioAppViewVarItemList); + variable_item_list_free(app->var_item_list); + view_dispatcher_remove_view(app->view_dispatcher, GpioAppViewGpioTest); + gpio_test_free(app->gpio_test); + // View dispatcher + view_dispatcher_free(app->view_dispatcher); + scene_manager_free(app->scene_manager); + // Close records + furi_record_close("gui"); + furi_record_close("notification"); + + free(app); +} + +int32_t gpio_app(void* p) { + GpioApp* gpio_app = gpio_app_alloc(); + + view_dispatcher_run(gpio_app->view_dispatcher); + + gpio_app_free(gpio_app); + + return 0; +} diff --git a/applications/gpio/gpio_app.h b/applications/gpio/gpio_app.h new file mode 100644 index 00000000..156ddc92 --- /dev/null +++ b/applications/gpio/gpio_app.h @@ -0,0 +1,11 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct GpioApp GpioApp; + +#ifdef __cplusplus +} +#endif diff --git a/applications/gpio/gpio_app_i.h b/applications/gpio/gpio_app_i.h new file mode 100644 index 00000000..590bedc3 --- /dev/null +++ b/applications/gpio/gpio_app_i.h @@ -0,0 +1,28 @@ +#pragma once + +#include "gpio_app.h" +#include "gpio_item.h" +#include "scenes/gpio_scene.h" + +#include +#include +#include +#include + +#include +#include "views/gpio_test.h" + +struct GpioApp { + Gui* gui; + ViewDispatcher* view_dispatcher; + SceneManager* scene_manager; + NotificationApp* notifications; + + VariableItemList* var_item_list; + GpioTest* gpio_test; +}; + +typedef enum { + GpioAppViewVarItemList, + GpioAppViewGpioTest, +} GpioAppView; diff --git a/applications/gpio/gpio_item.c b/applications/gpio/gpio_item.c new file mode 100644 index 00000000..96823ece --- /dev/null +++ b/applications/gpio/gpio_item.c @@ -0,0 +1,51 @@ +#include "gpio_item.h" + +#include + +typedef struct { + const char* name; + const GpioPin* pin; +} GpioItem; + +static const GpioItem gpio_item[GPIO_ITEM_COUNT] = { + {"1.2: PA7", &gpio_ext_pa7}, + {"1.3: PA6", &gpio_ext_pa6}, + {"1.4: PA4", &gpio_ext_pa4}, + {"1.5: PB3", &gpio_ext_pb3}, + {"1.6: PB2", &gpio_ext_pb2}, + {"1.7: PC3", &gpio_ext_pc3}, + {"2.7: PC1", &gpio_ext_pc1}, + {"2.8: PC0", &gpio_ext_pc0}, +}; + +void gpio_item_configure_pin(uint8_t index, GpioMode mode) { + furi_assert(index < GPIO_ITEM_COUNT); + hal_gpio_write(gpio_item[index].pin, false); + hal_gpio_init(gpio_item[index].pin, mode, GpioPullNo, GpioSpeedVeryHigh); +} + +void gpio_item_configure_all_pins(GpioMode mode) { + for(uint8_t i = 0; i < GPIO_ITEM_COUNT; i++) { + gpio_item_configure_pin(i, mode); + } +} + +void gpio_item_set_pin(uint8_t index, bool level) { + furi_assert(index < GPIO_ITEM_COUNT); + hal_gpio_write(gpio_item[index].pin, level); +} + +void gpio_item_set_all_pins(bool level) { + for(uint8_t i = 0; i < GPIO_ITEM_COUNT; i++) { + gpio_item_set_pin(i, level); + } +} + +const char* gpio_item_get_pin_name(uint8_t index) { + furi_assert(index < GPIO_ITEM_COUNT + 1); + if(index == GPIO_ITEM_COUNT) { + return "ALL"; + } else { + return gpio_item[index].name; + } +} diff --git a/applications/gpio/gpio_item.h b/applications/gpio/gpio_item.h new file mode 100644 index 00000000..25675729 --- /dev/null +++ b/applications/gpio/gpio_item.h @@ -0,0 +1,15 @@ +#pragma once + +#include + +#define GPIO_ITEM_COUNT 8 + +void gpio_item_configure_pin(uint8_t index, GpioMode mode); + +void gpio_item_configure_all_pins(GpioMode mode); + +void gpio_item_set_pin(uint8_t index, bool level); + +void gpio_item_set_all_pins(bool level); + +const char* gpio_item_get_pin_name(uint8_t index); diff --git a/applications/gpio/scenes/gpio_scene.c b/applications/gpio/scenes/gpio_scene.c new file mode 100644 index 00000000..d5aa4cbe --- /dev/null +++ b/applications/gpio/scenes/gpio_scene.c @@ -0,0 +1,30 @@ +#include "gpio_scene.h" + +// Generate scene on_enter handlers array +#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter, +void (*const gpio_scene_on_enter_handlers[])(void*) = { +#include "gpio_scene_config.h" +}; +#undef ADD_SCENE + +// Generate scene on_event handlers array +#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event, +bool (*const gpio_scene_on_event_handlers[])(void* context, SceneManagerEvent event) = { +#include "gpio_scene_config.h" +}; +#undef ADD_SCENE + +// Generate scene on_exit handlers array +#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit, +void (*const gpio_scene_on_exit_handlers[])(void* context) = { +#include "gpio_scene_config.h" +}; +#undef ADD_SCENE + +// Initialize scene handlers configuration structure +const SceneManagerHandlers gpio_scene_handlers = { + .on_enter_handlers = gpio_scene_on_enter_handlers, + .on_event_handlers = gpio_scene_on_event_handlers, + .on_exit_handlers = gpio_scene_on_exit_handlers, + .scene_num = GpioSceneNum, +}; diff --git a/applications/gpio/scenes/gpio_scene.h b/applications/gpio/scenes/gpio_scene.h new file mode 100644 index 00000000..15556c8d --- /dev/null +++ b/applications/gpio/scenes/gpio_scene.h @@ -0,0 +1,29 @@ +#pragma once + +#include + +// Generate scene id and total number +#define ADD_SCENE(prefix, name, id) GpioScene##id, +typedef enum { +#include "gpio_scene_config.h" + GpioSceneNum, +} GpioScene; +#undef ADD_SCENE + +extern const SceneManagerHandlers gpio_scene_handlers; + +// Generate scene on_enter handlers declaration +#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*); +#include "gpio_scene_config.h" +#undef ADD_SCENE + +// Generate scene on_event handlers declaration +#define ADD_SCENE(prefix, name, id) \ + bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event); +#include "gpio_scene_config.h" +#undef ADD_SCENE + +// Generate scene on_exit handlers declaration +#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context); +#include "gpio_scene_config.h" +#undef ADD_SCENE diff --git a/applications/gpio/scenes/gpio_scene_config.h b/applications/gpio/scenes/gpio_scene_config.h new file mode 100644 index 00000000..5f7f78ba --- /dev/null +++ b/applications/gpio/scenes/gpio_scene_config.h @@ -0,0 +1,2 @@ +ADD_SCENE(gpio, start, Start) +ADD_SCENE(gpio, test, Test) diff --git a/applications/gpio/scenes/gpio_scene_start.c b/applications/gpio/scenes/gpio_scene_start.c new file mode 100755 index 00000000..946d8e1b --- /dev/null +++ b/applications/gpio/scenes/gpio_scene_start.c @@ -0,0 +1,92 @@ +#include "../gpio_app_i.h" +#include "furi-hal-power.h" + +#define GPIO_SCENE_START_CUSTOM_EVENT_OTG_OFF (0UL) +#define GPIO_SCENE_START_CUSTOM_EVENT_OTG_ON (1UL) +#define GPIO_SCENE_START_CUSTOM_EVENT_TEST (2UL) + +enum GpioItem { + GpioItemOtg, + GpioItemTest, +}; + +enum GpioOtg { + GpioOtgOff, + GpioOtgOn, + GpioOtgSettingsNum, +}; + +const char* const gpio_otg_text[GpioOtgSettingsNum] = { + "Off", + "On", +}; + +static void gpio_scene_start_var_list_enter_callback(void* context, uint32_t index) { + furi_assert(context); + GpioApp* app = context; + if(index == GpioItemTest) { + view_dispatcher_send_custom_event( + app->view_dispatcher, GPIO_SCENE_START_CUSTOM_EVENT_TEST); + } +} + +static void gpio_scene_start_var_list_change_callback(VariableItem* item) { + GpioApp* app = variable_item_get_context(item); + uint8_t index = variable_item_get_current_value_index(item); + + variable_item_set_current_value_text(item, gpio_otg_text[index]); + if(index == GpioOtgOff) { + view_dispatcher_send_custom_event( + app->view_dispatcher, GPIO_SCENE_START_CUSTOM_EVENT_OTG_OFF); + } else if(index == GpioOtgOn) { + view_dispatcher_send_custom_event( + app->view_dispatcher, GPIO_SCENE_START_CUSTOM_EVENT_OTG_ON); + } +} + +void gpio_scene_start_on_enter(void* context) { + GpioApp* app = context; + VariableItemList* var_item_list = app->var_item_list; + + VariableItem* item; + variable_item_list_set_enter_callback( + var_item_list, gpio_scene_start_var_list_enter_callback, app); + item = variable_item_list_add( + var_item_list, + "5V on GPIO", + GpioOtgSettingsNum, + gpio_scene_start_var_list_change_callback, + app); + if(furi_hal_power_is_otg_enabled()) { + variable_item_set_current_value_index(item, GpioOtgOn); + variable_item_set_current_value_text(item, gpio_otg_text[GpioOtgOn]); + } else { + variable_item_set_current_value_index(item, GpioOtgOff); + variable_item_set_current_value_text(item, gpio_otg_text[GpioOtgOff]); + } + variable_item_list_add(var_item_list, "GPIO tester", 0, NULL, NULL); + + view_dispatcher_switch_to_view(app->view_dispatcher, GpioAppViewVarItemList); +} + +bool gpio_scene_start_on_event(void* context, SceneManagerEvent event) { + GpioApp* app = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == GPIO_SCENE_START_CUSTOM_EVENT_OTG_ON) { + furi_hal_power_enable_otg(); + } else if(event.event == GPIO_SCENE_START_CUSTOM_EVENT_OTG_OFF) { + furi_hal_power_disable_otg(); + } else if(event.event == GPIO_SCENE_START_CUSTOM_EVENT_TEST) { + scene_manager_next_scene(app->scene_manager, GpioSceneTest); + } + consumed = true; + } + return consumed; +} + +void gpio_scene_start_on_exit(void* context) { + GpioApp* app = context; + variable_item_list_clean(app->var_item_list); +} diff --git a/applications/gpio/scenes/gpio_scene_test.c b/applications/gpio/scenes/gpio_scene_test.c new file mode 100644 index 00000000..009e2ff4 --- /dev/null +++ b/applications/gpio/scenes/gpio_scene_test.c @@ -0,0 +1,27 @@ +#include "../gpio_app_i.h" + +void gpio_scene_test_ok_callback(InputType type, void* context) { + furi_assert(context); + GpioApp* app = context; + + if(type == InputTypePress) { + notification_message(app->notifications, &sequence_set_green_255); + } else if(type == InputTypeRelease) { + notification_message(app->notifications, &sequence_reset_green); + } +} + +void gpio_scene_test_on_enter(void* context) { + GpioApp* app = context; + gpio_item_configure_all_pins(GpioModeOutputPushPull); + gpio_test_set_ok_callback(app->gpio_test, gpio_scene_test_ok_callback, app); + view_dispatcher_switch_to_view(app->view_dispatcher, GpioAppViewGpioTest); +} + +bool gpio_scene_test_on_event(void* context, SceneManagerEvent event) { + return false; +} + +void gpio_scene_test_on_exit(void* context) { + gpio_item_configure_all_pins(GpioModeAnalog); +} diff --git a/applications/gpio/views/gpio_test.c b/applications/gpio/views/gpio_test.c new file mode 100755 index 00000000..62f3426e --- /dev/null +++ b/applications/gpio/views/gpio_test.c @@ -0,0 +1,130 @@ +#include "gpio_test.h" +#include "../gpio_item.h" + +#include + +struct GpioTest { + View* view; + GpioTestOkCallback callback; + void* context; +}; + +typedef struct { + uint8_t pin_idx; +} GpioTestModel; + +static bool gpio_test_process_left(GpioTest* gpio_test); +static bool gpio_test_process_right(GpioTest* gpio_test); +static bool gpio_test_process_ok(GpioTest* gpio_test, InputEvent* event); + +static void gpio_test_draw_callback(Canvas* canvas, void* _model) { + GpioTestModel* model = _model; + canvas_set_font(canvas, FontPrimary); + elements_multiline_text_aligned(canvas, 64, 2, AlignCenter, AlignTop, "Gpio Output mode test"); + canvas_set_font(canvas, FontSecondary); + elements_multiline_text_aligned( + canvas, 64, 16, AlignCenter, AlignTop, "Press < or > to change pin"); + elements_multiline_text_aligned( + canvas, 64, 32, AlignCenter, AlignTop, gpio_item_get_pin_name(model->pin_idx)); +} + +static bool gpio_test_input_callback(InputEvent* event, void* context) { + furi_assert(context); + GpioTest* gpio_test = context; + bool consumed = false; + + if(event->type == InputTypeShort) { + if(event->key == InputKeyRight) { + consumed = gpio_test_process_right(gpio_test); + } else if(event->key == InputKeyLeft) { + consumed = gpio_test_process_left(gpio_test); + } + } else if(event->key == InputKeyOk) { + consumed = gpio_test_process_ok(gpio_test, event); + } + + return consumed; +} + +static bool gpio_test_process_left(GpioTest* gpio_test) { + with_view_model( + gpio_test->view, (GpioTestModel * model) { + if(model->pin_idx) { + model->pin_idx--; + } + return true; + }); + return true; +} + +static bool gpio_test_process_right(GpioTest* gpio_test) { + with_view_model( + gpio_test->view, (GpioTestModel * model) { + if(model->pin_idx < GPIO_ITEM_COUNT) { + model->pin_idx++; + } + return true; + }); + return true; +} + +static bool gpio_test_process_ok(GpioTest* gpio_test, InputEvent* event) { + bool consumed = false; + + with_view_model( + gpio_test->view, (GpioTestModel * model) { + if(event->type == InputTypePress) { + if(model->pin_idx < GPIO_ITEM_COUNT) { + gpio_item_set_pin(model->pin_idx, true); + } else { + gpio_item_set_all_pins(true); + } + consumed = true; + } else if(event->type == InputTypeRelease) { + if(model->pin_idx < GPIO_ITEM_COUNT) { + gpio_item_set_pin(model->pin_idx, false); + } else { + gpio_item_set_all_pins(false); + } + consumed = true; + } + gpio_test->callback(event->type, gpio_test->context); + return true; + }); + + return consumed; +} + +GpioTest* gpio_test_alloc() { + GpioTest* gpio_test = furi_alloc(sizeof(GpioTest)); + + gpio_test->view = view_alloc(); + view_allocate_model(gpio_test->view, ViewModelTypeLocking, sizeof(GpioTestModel)); + view_set_context(gpio_test->view, gpio_test); + view_set_draw_callback(gpio_test->view, gpio_test_draw_callback); + view_set_input_callback(gpio_test->view, gpio_test_input_callback); + + return gpio_test; +} + +void gpio_test_free(GpioTest* gpio_test) { + furi_assert(gpio_test); + view_free(gpio_test->view); + free(gpio_test); +} + +View* gpio_test_get_view(GpioTest* gpio_test) { + furi_assert(gpio_test); + return gpio_test->view; +} + +void gpio_test_set_ok_callback(GpioTest* gpio_test, GpioTestOkCallback callback, void* context) { + furi_assert(gpio_test); + furi_assert(callback); + with_view_model( + gpio_test->view, (GpioTestModel * model) { + gpio_test->callback = callback; + gpio_test->context = context; + return false; + }); +} diff --git a/applications/gpio/views/gpio_test.h b/applications/gpio/views/gpio_test.h new file mode 100755 index 00000000..5cbd11e8 --- /dev/null +++ b/applications/gpio/views/gpio_test.h @@ -0,0 +1,14 @@ +#pragma once + +#include + +typedef struct GpioTest GpioTest; +typedef void (*GpioTestOkCallback)(InputType type, void* context); + +GpioTest* gpio_test_alloc(); + +void gpio_test_free(GpioTest* gpio_test); + +View* gpio_test_get_view(GpioTest* gpio_test); + +void gpio_test_set_ok_callback(GpioTest* gpio_test, GpioTestOkCallback callback, void* context); diff --git a/applications/gui/modules/variable-item-list.c b/applications/gui/modules/variable-item-list.c old mode 100644 new mode 100755 index 1879353f..fccfd84a --- a/applications/gui/modules/variable-item-list.c +++ b/applications/gui/modules/variable-item-list.c @@ -18,6 +18,8 @@ ARRAY_DEF(VariableItemArray, VariableItem, M_POD_OPLIST); struct VariableItemList { View* view; + VariableItemListEnterCallback callback; + void* context; }; typedef struct { @@ -30,6 +32,7 @@ static void variable_item_list_process_up(VariableItemList* variable_item_list); static void variable_item_list_process_down(VariableItemList* variable_item_list); static void variable_item_list_process_left(VariableItemList* variable_item_list); static void variable_item_list_process_right(VariableItemList* variable_item_list); +static void variable_item_list_process_ok(VariableItemList* variable_item_list); static void variable_item_list_draw_callback(Canvas* canvas, void* _model) { VariableItemListModel* model = _model; @@ -104,6 +107,9 @@ static bool variable_item_list_input_callback(InputEvent* event, void* context) consumed = true; variable_item_list_process_right(variable_item_list); break; + case InputKeyOk: + variable_item_list_process_ok(variable_item_list); + break; default: break; } @@ -198,6 +204,16 @@ void variable_item_list_process_right(VariableItemList* variable_item_list) { }); } +void variable_item_list_process_ok(VariableItemList* variable_item_list) { + with_view_model( + variable_item_list->view, (VariableItemListModel * model) { + if(variable_item_list->callback) { + variable_item_list->callback(variable_item_list->context, model->position); + } + return false; + }); +} + VariableItemList* variable_item_list_alloc() { VariableItemList* variable_item_list = furi_alloc(sizeof(VariableItemList)); variable_item_list->view = view_alloc(); @@ -280,6 +296,19 @@ VariableItem* variable_item_list_add( return item; } +void variable_item_list_set_enter_callback( + VariableItemList* variable_item_list, + VariableItemListEnterCallback callback, + void* context) { + furi_assert(callback); + with_view_model( + variable_item_list->view, (VariableItemListModel * model) { + variable_item_list->callback = callback; + variable_item_list->context = context; + return false; + }); +} + void variable_item_set_current_value_index(VariableItem* item, uint8_t current_value_index) { item->current_value_index = current_value_index; } diff --git a/applications/gui/modules/variable-item-list.h b/applications/gui/modules/variable-item-list.h old mode 100644 new mode 100755 index 8844b419..a70ded39 --- a/applications/gui/modules/variable-item-list.h +++ b/applications/gui/modules/variable-item-list.h @@ -8,6 +8,7 @@ extern "C" { typedef struct VariableItemList VariableItemList; typedef struct VariableItem VariableItem; typedef void (*VariableItemChangeCallback)(VariableItem* item); +typedef void (*VariableItemListEnterCallback)(void* context, uint32_t index); /** Allocate and initialize VariableItemList * @return VariableItemList* @@ -19,6 +20,9 @@ VariableItemList* variable_item_list_alloc(); */ void variable_item_list_free(VariableItemList* variable_item_list); +/** Clear all elements from list + * @param variable_item_list VariableItemList instance + */ void variable_item_list_clean(VariableItemList* variable_item_list); View* variable_item_list_get_view(VariableItemList* variable_item_list); @@ -38,6 +42,16 @@ VariableItem* variable_item_list_add( VariableItemChangeCallback change_callback, void* context); +/** Set enter callback + * @param variable_item_list VariableItemList instance + * @param calback VariableItemListEnterCallback instance + * @param context pointer to context + */ +void variable_item_list_set_enter_callback( + VariableItemList* variable_item_list, + VariableItemListEnterCallback callback, + void* context); + /** Set item current selected index * @param item VariableItem* instance * @param current_value_index diff --git a/firmware/targets/f6/furi-hal/furi-hal-power.c b/firmware/targets/f6/furi-hal/furi-hal-power.c index 4dd0127f..afc430ab 100644 --- a/firmware/targets/f6/furi-hal/furi-hal-power.c +++ b/firmware/targets/f6/furi-hal/furi-hal-power.c @@ -180,6 +180,10 @@ void furi_hal_power_disable_otg() { bq25896_disable_otg(); } +bool furi_hal_power_is_otg_enabled() { + return bq25896_is_otg_enabled(); +} + uint32_t furi_hal_power_get_battery_remaining_capacity() { return bq27220_get_remaining_capacity(); } diff --git a/firmware/targets/f7/furi-hal/furi-hal-power.c b/firmware/targets/f7/furi-hal/furi-hal-power.c index 4dd0127f..afc430ab 100644 --- a/firmware/targets/f7/furi-hal/furi-hal-power.c +++ b/firmware/targets/f7/furi-hal/furi-hal-power.c @@ -180,6 +180,10 @@ void furi_hal_power_disable_otg() { bq25896_disable_otg(); } +bool furi_hal_power_is_otg_enabled() { + return bq25896_is_otg_enabled(); +} + uint32_t furi_hal_power_get_battery_remaining_capacity() { return bq27220_get_remaining_capacity(); } diff --git a/firmware/targets/furi-hal-include/furi-hal-power.h b/firmware/targets/furi-hal-include/furi-hal-power.h index aeb6c201..3514e8d6 100644 --- a/firmware/targets/furi-hal-include/furi-hal-power.h +++ b/firmware/targets/furi-hal-include/furi-hal-power.h @@ -69,6 +69,9 @@ void furi_hal_power_enable_otg(); /** OTG disable */ void furi_hal_power_disable_otg(); +/** Get OTG status */ +bool furi_hal_power_is_otg_enabled(); + /** Get remaining battery battery capacity in mAh */ uint32_t furi_hal_power_get_battery_remaining_capacity(); diff --git a/lib/drivers/bq25896.c b/lib/drivers/bq25896.c index bcafcb6a..e767179f 100644 --- a/lib/drivers/bq25896.c +++ b/lib/drivers/bq25896.c @@ -101,6 +101,11 @@ void bq25896_disable_otg() { bq25896_write_reg(0x03, (uint8_t*)&bq25896_regs.r03); } +bool bq25896_is_otg_enabled() { + bq25896_read_reg(0x03, (uint8_t*)&bq25896_regs.r03); + return bq25896_regs.r03.OTG_CONFIG; +} + uint16_t bq25896_get_vbus_voltage() { bq25896_read_reg(0x11, (uint8_t*)&bq25896_regs.r11); if(bq25896_regs.r11.VBUS_GD) { diff --git a/lib/drivers/bq25896.h b/lib/drivers/bq25896.h index ee5ad09b..e60fb247 100644 --- a/lib/drivers/bq25896.h +++ b/lib/drivers/bq25896.h @@ -18,6 +18,9 @@ void bq25896_enable_otg(); /** Disable otg */ void bq25896_disable_otg(); +/** Is otg enabled */ +bool bq25896_is_otg_enabled(); + /** Get VBUS Voltage in mV */ uint16_t bq25896_get_vbus_voltage();