From 258286acb3147fb596f50d5d3fbd2f0e2b298ef5 Mon Sep 17 00:00:00 2001 From: RogueMaster Date: Fri, 11 Nov 2022 16:53:42 -0500 Subject: [PATCH] Badger2040 --- applications/plugins/badger2040/README.md | 1 + .../plugins/badger2040/application.fam | 15 ++ applications/plugins/badger2040/badger2040.c | 235 ++++++++++++++++++ applications/plugins/badger2040/badger2040.h | 11 + applications/plugins/badger2040/dap_link.png | Bin 0 -> 143 bytes 5 files changed, 262 insertions(+) create mode 100644 applications/plugins/badger2040/README.md create mode 100644 applications/plugins/badger2040/application.fam create mode 100644 applications/plugins/badger2040/badger2040.c create mode 100644 applications/plugins/badger2040/badger2040.h create mode 100644 applications/plugins/badger2040/dap_link.png diff --git a/applications/plugins/badger2040/README.md b/applications/plugins/badger2040/README.md new file mode 100644 index 000000000..a711df119 --- /dev/null +++ b/applications/plugins/badger2040/README.md @@ -0,0 +1 @@ +This is an extremely basic plugin for interacting with a [badger2040](https://shop.pimoroni.com/products/badger-2040). \ No newline at end of file diff --git a/applications/plugins/badger2040/application.fam b/applications/plugins/badger2040/application.fam new file mode 100644 index 000000000..274a98261 --- /dev/null +++ b/applications/plugins/badger2040/application.fam @@ -0,0 +1,15 @@ +App( + appid="Badger2040", + name="Badger2040", + apptype=FlipperAppType.EXTERNAL, + entry_point="badger2040_app", + cdefines=["APP_BADGER2040"], + requires=[ + "gui", + "dialogs", + ], + stack_size=1 * 1024, + order=30, + fap_icon="dap_link.png", + fap_category="NeedsTesting", +) \ No newline at end of file diff --git a/applications/plugins/badger2040/badger2040.c b/applications/plugins/badger2040/badger2040.c new file mode 100644 index 000000000..5cbed37ed --- /dev/null +++ b/applications/plugins/badger2040/badger2040.c @@ -0,0 +1,235 @@ +#include +#include +#include +#include +#include "badger2040.h" + +#define ADDRESS_QUESTION_X 5 +#define ADDRESS_QUESTION_Y 10 +#define DATA_X 5 +#define DATA_Y 20 +#define ERROR_X 5 +#define ERROR_Y 55 + +#define DEBUG true + +#define ERROR + +typedef enum { + EventTypeTick, + EventTypeKey, +} EventType; + +typedef enum { + BadgerGetAddress, + BadgerSend +} STATE; + +typedef struct { + EventType type; + InputEvent input; +} PluginEvent; + +typedef struct { + STATE state; + bool get_failed; + uint8_t address; + uint8_t data; + bool send_failed; +} PluginState; + +static void badger2040_state_init(PluginState* const plugin_state) { + plugin_state->state = BadgerGetAddress; + plugin_state->get_failed = false; + plugin_state->address = FIRST_NON_RESERVED_I2C_ADDRESS; + plugin_state->data = 0; + plugin_state->send_failed = false; +} + +static void render_callback(Canvas* const canvas, void* ctx) { + PluginState* plugin_state = acquire_mutex((ValueMutex*)ctx, 25); + if(plugin_state == NULL) { + return; + } + + canvas_set_color(canvas, ColorBlack); + + char str[32]; + + if (plugin_state->state == BadgerGetAddress) { + sprintf(str, "Selected Address: %d", plugin_state->address); + canvas_draw_str(canvas, ADDRESS_QUESTION_X, ADDRESS_QUESTION_Y, str); + + if (plugin_state->get_failed) { + strcpy(str, "Error! Device not found!"); + canvas_draw_str(canvas, ERROR_X, ERROR_Y, str); + } + } else if (plugin_state->state == BadgerSend) { + sprintf(str, "Sending to Address: %d", plugin_state->address); + canvas_draw_str(canvas, ADDRESS_QUESTION_X, ADDRESS_QUESTION_Y, str); + + sprintf(str, "Data: %d", plugin_state->data); + canvas_draw_str(canvas, DATA_X, DATA_Y, str); + + if (plugin_state->send_failed) { + strcpy(str, "Error! Unable to send data!"); + canvas_draw_str(canvas, ERROR_X, ERROR_Y, str); + } + } + + release_mutex((ValueMutex*)ctx, plugin_state); +} + +static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) { + furi_assert(event_queue); + + PluginEvent event = {.type = EventTypeKey, .input = *input_event}; + furi_message_queue_put(event_queue, &event, FuriWaitForever); +} + +bool device_exists(int address) { + if (DEBUG) return true; + + uint32_t response_timeout_ticks = furi_ms_to_ticks(5.f); + + return furi_hal_i2c_is_device_ready( + &furi_hal_i2c_handle_external, + address << 1, + response_timeout_ticks); +} + +bool sendData(uint8_t address, uint8_t data) { + if (DEBUG) return true; + + uint32_t response_timeout_ticks = furi_ms_to_ticks(5.f); + + return furi_hal_i2c_tx(&furi_hal_i2c_handle_external, address, &data, 1, response_timeout_ticks); +} + +int32_t badger2040_app(void* p) { + UNUSED(p); + + FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(PluginEvent)); + + PluginState* plugin_state = malloc(sizeof(PluginState)); + badger2040_state_init(plugin_state); + + ValueMutex state_mutex; + if(!init_mutex(&state_mutex, plugin_state, sizeof(PluginState))) { + FURI_LOG_E("badger2040", "cannot create mutex\r\n"); + free(plugin_state); + return 255; + } + + furi_hal_i2c_acquire(&furi_hal_i2c_handle_external); + + // Set system callbacks + ViewPort* view_port = view_port_alloc(); + view_port_draw_callback_set(view_port, render_callback, &state_mutex); + view_port_input_callback_set(view_port, input_callback, event_queue); + + // Open GUI and register view_port + Gui* gui = furi_record_open("gui"); + gui_add_view_port(gui, view_port, GuiLayerFullscreen); + + PluginEvent event; + for(bool processing = true; processing;) { + FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); + PluginState* plugin_state = (PluginState*)acquire_mutex_block(&state_mutex); + + if(event_status == FuriStatusOk) { + // press events + if(event.type == EventTypeKey) { + if((event.input.type == InputTypePress) || (event.input.type == InputTypeRepeat)) { + + // Reset failed status to clear display after key press + if (plugin_state->state == BadgerGetAddress) { + plugin_state->get_failed = false; + } else if (plugin_state->state == BadgerSend) { + plugin_state->send_failed = false; + } + + switch(event.input.key) { + case InputKeyUp: + if (plugin_state->state == BadgerGetAddress) { + uint8_t prevAddr = plugin_state->address; + + if (prevAddr == HIGHEST_I2C_ADDRESS) { + plugin_state->address = FIRST_NON_RESERVED_I2C_ADDRESS; + } else { + plugin_state->address = prevAddr + 1; + } + } else if (plugin_state->state == BadgerSend) { + uint8_t prevData = plugin_state->data; + + if (prevData == MAX_DATA) { + plugin_state->data = MIN_DATA; + } else { + plugin_state->data = prevData + 1; + } + } + break; + case InputKeyDown: + if (plugin_state->state == BadgerGetAddress) { + uint8_t prevAddr = plugin_state->address; + + if (prevAddr == FIRST_NON_RESERVED_I2C_ADDRESS) { + plugin_state->address = HIGHEST_I2C_ADDRESS; + } else { + plugin_state->address = prevAddr - 1; + } + } else if (plugin_state->state == BadgerSend) { + uint8_t prevData = plugin_state->data; + + if (prevData == MIN_DATA) { + plugin_state->data = MAX_DATA; + } else { + plugin_state->data = prevData - 1; + } + } + break; + case InputKeyRight: + break; + case InputKeyLeft: + break; + case InputKeyOk: + if (plugin_state->state == BadgerGetAddress) { + if (device_exists(plugin_state->address)) { + if (plugin_state->state == BadgerGetAddress) { + plugin_state->state = BadgerSend; + } + } else { + plugin_state->get_failed = true; + } + } else if (plugin_state->state == BadgerSend) { + if (!sendData) { + plugin_state->send_failed = true; + } + } + break; + case InputKeyBack: + processing = false; + break; + default: + break; + } + } + } + } else { + FURI_LOG_D("badger2040", "osMessageQueue: event timeout"); + // event timeout + } + + view_port_update(view_port); + release_mutex(&state_mutex, plugin_state); + } + + view_port_enabled_set(view_port, false); + gui_remove_view_port(gui, view_port); + furi_record_close("gui"); + view_port_free(view_port); + furi_hal_i2c_release(&furi_hal_i2c_handle_external); + furi_message_queue_free(event_queue); + + return 0; +} \ No newline at end of file diff --git a/applications/plugins/badger2040/badger2040.h b/applications/plugins/badger2040/badger2040.h new file mode 100644 index 000000000..d8d09db2b --- /dev/null +++ b/applications/plugins/badger2040/badger2040.h @@ -0,0 +1,11 @@ +#pragma once + +#define FIRST_NON_RESERVED_I2C_ADDRESS 8 +#define HIGHEST_I2C_ADDRESS 127 + +#define MIN_DATA 0 +#define MAX_DATA 255 + +#include +#include +#include \ No newline at end of file diff --git a/applications/plugins/badger2040/dap_link.png b/applications/plugins/badger2040/dap_link.png new file mode 100644 index 0000000000000000000000000000000000000000..2278ce2b61cf97e51720bafb2d07dae48d986560 GIT binary patch literal 143 zcmeAS@N?(olHy`uVBq!ia0vp^AT}2V8<6ZZI=>f4F%}28J29*~C-V}>@$__Y43U`H zI>D2R!GMF={pJ7tHnyBWw`O@WO=4vXnQOryxnPsm9sxmyCsV>A?tXRt_DY<&Wq)IO q>DB4a%~XFc{Gk)L^WR4G>Gvdb>|Y;BDpm&?%HZkh=d#Wzp$P!!VJ~6; literal 0 HcmV?d00001