mirror of
https://github.com/DarkFlippers/unleashed-firmware
synced 2024-11-27 06:50:21 +00:00
[FL-1884] GPIO application (#732)
* gpio: rename gpio application * bq25896: add reading OTG config * furi-hal-power: add is_otg_enabled API * gpio: introduce new GPIO app, add OTG enable / disable * variable-item-list: add enter callback * gpio: add output test view and scene * gpio app: fix GpioItemTester -> GpioItemTest Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
parent
7a89791b2b
commit
638f276308
22 changed files with 574 additions and 155 deletions
|
@ -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
|
||||
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -1,148 +0,0 @@
|
|||
#include <furi.h>
|
||||
#include <furi-hal.h>
|
||||
|
||||
#include <gui/gui.h>
|
||||
#include <notification/notification-messages.h>
|
||||
|
||||
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;
|
||||
}
|
76
applications/gpio/gpio_app.c
Executable file
76
applications/gpio/gpio_app.c
Executable file
|
@ -0,0 +1,76 @@
|
|||
#include "gpio_app_i.h"
|
||||
|
||||
#include <furi.h>
|
||||
#include <furi-hal.h>
|
||||
|
||||
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;
|
||||
}
|
11
applications/gpio/gpio_app.h
Normal file
11
applications/gpio/gpio_app.h
Normal file
|
@ -0,0 +1,11 @@
|
|||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct GpioApp GpioApp;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
28
applications/gpio/gpio_app_i.h
Normal file
28
applications/gpio/gpio_app_i.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
#pragma once
|
||||
|
||||
#include "gpio_app.h"
|
||||
#include "gpio_item.h"
|
||||
#include "scenes/gpio_scene.h"
|
||||
|
||||
#include <gui/gui.h>
|
||||
#include <gui/view_dispatcher.h>
|
||||
#include <gui/scene_manager.h>
|
||||
#include <notification/notification-messages.h>
|
||||
|
||||
#include <gui/modules/variable-item-list.h>
|
||||
#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;
|
51
applications/gpio/gpio_item.c
Normal file
51
applications/gpio/gpio_item.c
Normal file
|
@ -0,0 +1,51 @@
|
|||
#include "gpio_item.h"
|
||||
|
||||
#include <furi-hal-resources.h>
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
15
applications/gpio/gpio_item.h
Normal file
15
applications/gpio/gpio_item.h
Normal file
|
@ -0,0 +1,15 @@
|
|||
#pragma once
|
||||
|
||||
#include <furi-hal-gpio.h>
|
||||
|
||||
#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);
|
30
applications/gpio/scenes/gpio_scene.c
Normal file
30
applications/gpio/scenes/gpio_scene.c
Normal file
|
@ -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,
|
||||
};
|
29
applications/gpio/scenes/gpio_scene.h
Normal file
29
applications/gpio/scenes/gpio_scene.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
#pragma once
|
||||
|
||||
#include <gui/scene_manager.h>
|
||||
|
||||
// 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
|
2
applications/gpio/scenes/gpio_scene_config.h
Normal file
2
applications/gpio/scenes/gpio_scene_config.h
Normal file
|
@ -0,0 +1,2 @@
|
|||
ADD_SCENE(gpio, start, Start)
|
||||
ADD_SCENE(gpio, test, Test)
|
92
applications/gpio/scenes/gpio_scene_start.c
Executable file
92
applications/gpio/scenes/gpio_scene_start.c
Executable file
|
@ -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);
|
||||
}
|
27
applications/gpio/scenes/gpio_scene_test.c
Normal file
27
applications/gpio/scenes/gpio_scene_test.c
Normal file
|
@ -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);
|
||||
}
|
130
applications/gpio/views/gpio_test.c
Executable file
130
applications/gpio/views/gpio_test.c
Executable file
|
@ -0,0 +1,130 @@
|
|||
#include "gpio_test.h"
|
||||
#include "../gpio_item.h"
|
||||
|
||||
#include <gui/elements.h>
|
||||
|
||||
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;
|
||||
});
|
||||
}
|
14
applications/gpio/views/gpio_test.h
Executable file
14
applications/gpio/views/gpio_test.h
Executable file
|
@ -0,0 +1,14 @@
|
|||
#pragma once
|
||||
|
||||
#include <gui/view.h>
|
||||
|
||||
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);
|
29
applications/gui/modules/variable-item-list.c
Normal file → Executable file
29
applications/gui/modules/variable-item-list.c
Normal file → Executable file
|
@ -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;
|
||||
}
|
||||
|
|
14
applications/gui/modules/variable-item-list.h
Normal file → Executable file
14
applications/gui/modules/variable-item-list.h
Normal file → Executable file
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
Loading…
Reference in a new issue