From 99f08decb27dc1ab811014ac55070d128783c017 Mon Sep 17 00:00:00 2001 From: RogueMaster Date: Sun, 30 Oct 2022 19:15:47 -0400 Subject: [PATCH] BRING BACK GPIO --- ReadMe.md | 6 +- applications/main/gpio/gpio_app.c | 14 + applications/main/gpio/gpio_app_i.h | 6 + applications/main/gpio/gpio_custom_event.h | 2 + .../main/gpio/gpio_i2c_scanner_control.c | 23 ++ .../main/gpio/gpio_i2c_scanner_control.h | 21 ++ applications/main/gpio/gpio_i2c_sfp_control.c | 334 ++++++++++++++++++ applications/main/gpio/gpio_i2c_sfp_control.h | 32 ++ .../main/gpio/scenes/gpio_scene_config.h | 2 + .../main/gpio/scenes/gpio_scene_i2c_scanner.c | 36 ++ .../main/gpio/scenes/gpio_scene_i2c_sfp.c | 35 ++ .../main/gpio/scenes/gpio_scene_start.c | 17 +- .../main/gpio/views/gpio_i2c_scanner.c | 139 ++++++++ .../main/gpio/views/gpio_i2c_scanner.h | 20 ++ applications/main/gpio/views/gpio_i2c_sfp.c | 149 ++++++++ applications/main/gpio/views/gpio_i2c_sfp.h | 20 ++ 16 files changed, 852 insertions(+), 4 deletions(-) create mode 100644 applications/main/gpio/gpio_i2c_scanner_control.c create mode 100644 applications/main/gpio/gpio_i2c_scanner_control.h create mode 100644 applications/main/gpio/gpio_i2c_sfp_control.c create mode 100644 applications/main/gpio/gpio_i2c_sfp_control.h create mode 100644 applications/main/gpio/scenes/gpio_scene_i2c_scanner.c create mode 100644 applications/main/gpio/scenes/gpio_scene_i2c_sfp.c create mode 100644 applications/main/gpio/views/gpio_i2c_scanner.c create mode 100644 applications/main/gpio/views/gpio_i2c_scanner.h create mode 100644 applications/main/gpio/views/gpio_i2c_sfp.c create mode 100644 applications/main/gpio/views/gpio_i2c_sfp.h diff --git a/ReadMe.md b/ReadMe.md index 2357bb772..b156d165f 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -18,13 +18,13 @@ - Fixed icons for U2F and iButton. - Added source file from third party animations. - Restored animation building. +- Restored: [I²C-Scanner #1431 (By GitChris3004)](https://github.com/flipperdevices/flipperzero-firmware/pull/1431) +- Restored: GPIO: Feature to read EEPROM of SFP Modules using I2C [(By marcusju)](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/pull/198)
TO DO / REMOVED
- [Keynote BT plugin: long press on OK to switch between Space and Retur… #1729 (By coded-with-claws)] -- GPIO: Feature to read EEPROM of SFP Modules using I2C [(By marcusju)](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/pull/198) -- [I²C-Scanner #1431 (By GitChris3004)](https://github.com/flipperdevices/flipperzero-firmware/pull/1431) - Settings: Rename from App [(Thanks to E_Surge)](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/pull/259) - [Chip8 Emulator (By mega8bit)](https://github.com/mega8bit/flipperzero-firmware) Updated by ESurge. Add SD folder `chip8`, [Get GAMES HERE](https://johnearnest.github.io/chip8Archive/) (Needs Controls Programmed) `HIDDEN because its broken` [Last Version Before Removal](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/tree/ec49915e1c4e908d9a2b0d4425fd97526755e276/applications/plugins/chip8) - Lost To Faps: Settings: Favorite Game by holding UP on Desktop [Thanks to gotnull](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/pull/57) @@ -137,6 +137,8 @@ $ ./fbt plugin_dist - - Tetris, Snake, or Flappy Bird Score For EXP - - Zombiez for every 20 Zombie kills - Dolphin: SD dolphin manifest updated to weight animations differently +- GPIO: Feature to read EEPROM of SFP Modules using I2C [(By marcusju)](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/pull/198) +- GPIO: [I²C-Scanner #1431 (By GitChris3004)](https://github.com/flipperdevices/flipperzero-firmware/pull/1431) - iButton: [Fixed issue when loading iButton keys or U2F token from Archive app #382 (By ESurge)](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/pull/382) - Icon Decode/Encode [(Thanks to PixlEmly)](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/pull/55/files) - IR: Universal AC, Audio, Fans & Projectors from [Unleashed/Eng1n33r](https://github.com/DarkFlippers/unleashed-firmware) diff --git a/applications/main/gpio/gpio_app.c b/applications/main/gpio/gpio_app.c index b8afdc8ea..19e53f453 100644 --- a/applications/main/gpio/gpio_app.c +++ b/applications/main/gpio/gpio_app.c @@ -51,6 +51,16 @@ GpioApp* gpio_app_alloc() { view_dispatcher_add_view( app->view_dispatcher, GpioAppViewGpioTest, gpio_test_get_view(app->gpio_test)); + app->gpio_i2c_scanner = gpio_i2c_scanner_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, + GpioAppViewI2CScanner, + gpio_i2c_scanner_get_view(app->gpio_i2c_scanner)); + + app->gpio_i2c_sfp = gpio_i2c_sfp_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, GpioAppViewI2CSfp, gpio_i2c_sfp_get_view(app->gpio_i2c_sfp)); + app->widget = widget_alloc(); view_dispatcher_add_view( app->view_dispatcher, GpioAppViewUsbUartCloseRpc, widget_get_view(app->widget)); @@ -75,6 +85,8 @@ void gpio_app_free(GpioApp* app) { // Views view_dispatcher_remove_view(app->view_dispatcher, GpioAppViewVarItemList); view_dispatcher_remove_view(app->view_dispatcher, GpioAppViewGpioTest); + view_dispatcher_remove_view(app->view_dispatcher, GpioAppViewI2CScanner); + view_dispatcher_remove_view(app->view_dispatcher, GpioAppViewI2CSfp); view_dispatcher_remove_view(app->view_dispatcher, GpioAppViewUsbUart); view_dispatcher_remove_view(app->view_dispatcher, GpioAppViewUsbUartCfg); view_dispatcher_remove_view(app->view_dispatcher, GpioAppViewUsbUartCloseRpc); @@ -82,6 +94,8 @@ void gpio_app_free(GpioApp* app) { widget_free(app->widget); gpio_test_free(app->gpio_test); gpio_usb_uart_free(app->gpio_usb_uart); + gpio_i2c_scanner_free(app->gpio_i2c_scanner); + gpio_i2c_sfp_free(app->gpio_i2c_sfp); // View dispatcher view_dispatcher_free(app->view_dispatcher); diff --git a/applications/main/gpio/gpio_app_i.h b/applications/main/gpio/gpio_app_i.h index 85c5c332e..ee1d3fc9b 100644 --- a/applications/main/gpio/gpio_app_i.h +++ b/applications/main/gpio/gpio_app_i.h @@ -15,6 +15,8 @@ #include #include "views/gpio_test.h" #include "views/gpio_usb_uart.h" +#include "views/gpio_i2c_scanner.h" +#include "views/gpio_i2c_sfp.h" #include struct GpioApp { @@ -29,6 +31,8 @@ struct GpioApp { GpioTest* gpio_test; GpioUsbUart* gpio_usb_uart; UsbUartBridge* usb_uart_bridge; + GpioI2CScanner* gpio_i2c_scanner; + GpioI2CSfp* gpio_i2c_sfp; }; typedef enum { @@ -37,4 +41,6 @@ typedef enum { GpioAppViewUsbUart, GpioAppViewUsbUartCfg, GpioAppViewUsbUartCloseRpc, + GpioAppViewI2CScanner, + GpioAppViewI2CSfp } GpioAppView; diff --git a/applications/main/gpio/gpio_custom_event.h b/applications/main/gpio/gpio_custom_event.h index 2bf3e5a8b..02e24f753 100644 --- a/applications/main/gpio/gpio_custom_event.h +++ b/applications/main/gpio/gpio_custom_event.h @@ -5,6 +5,8 @@ typedef enum { GpioStartEventOtgOn, GpioStartEventManualControl, GpioStartEventUsbUart, + GpioStartEventI2CScanner, + GpioStartEventI2CSfp, GpioCustomEventErrorBack, diff --git a/applications/main/gpio/gpio_i2c_scanner_control.c b/applications/main/gpio/gpio_i2c_scanner_control.c new file mode 100644 index 000000000..bf3f1090d --- /dev/null +++ b/applications/main/gpio/gpio_i2c_scanner_control.c @@ -0,0 +1,23 @@ +#include "gpio_i2c_scanner_control.h" +#include + +void gpio_i2c_scanner_run_once(I2CScannerState* i2c_scanner_state) { + //Reset the number of items for rewriting the array + i2c_scanner_state->items = 0; + furi_hal_i2c_acquire(&furi_hal_i2c_handle_external); + + uint32_t response_timeout_ticks = furi_ms_to_ticks(5.f); + + //Addresses 0 to 7 are reserved and won't be scanned + for(int i = FIRST_NON_RESERVED_I2C_ADDRESS; i <= HIGHEST_I2C_ADDRESS; i++) { + if(furi_hal_i2c_is_device_ready( + &furi_hal_i2c_handle_external, + i << 1, + response_timeout_ticks)) { //Bitshift of 1 bit to convert 7-Bit Address into 8-Bit Address + i2c_scanner_state->responding_address[i2c_scanner_state->items] = i; + i2c_scanner_state->items++; + } + } + + furi_hal_i2c_release(&furi_hal_i2c_handle_external); +} diff --git a/applications/main/gpio/gpio_i2c_scanner_control.h b/applications/main/gpio/gpio_i2c_scanner_control.h new file mode 100644 index 000000000..011f8aa36 --- /dev/null +++ b/applications/main/gpio/gpio_i2c_scanner_control.h @@ -0,0 +1,21 @@ +#pragma once + +#include +#include + +#include + +#define FIRST_NON_RESERVED_I2C_ADDRESS 8 +#define HIGHEST_I2C_ADDRESS 127 +#define AVAILABLE_NONRESVERED_I2C_ADDRESSES 120 + +typedef struct { + uint8_t items; + uint8_t responding_address[AVAILABLE_NONRESVERED_I2C_ADDRESSES]; +} I2CScannerState; + +/** Scans the I2C-Bus (SDA: Pin 15, SCL: Pin 16) for available 7-Bit slave addresses. Saves the number of detected slaves and their addresses. + * + * @param i2c_scanner_state State including the detected addresses and the number of addresses saved. + */ +void gpio_i2c_scanner_run_once(I2CScannerState* st); diff --git a/applications/main/gpio/gpio_i2c_sfp_control.c b/applications/main/gpio/gpio_i2c_sfp_control.c new file mode 100644 index 000000000..d14ba1b8e --- /dev/null +++ b/applications/main/gpio/gpio_i2c_sfp_control.c @@ -0,0 +1,334 @@ +#include "gpio_i2c_sfp_control.h" +#include +#include + +// This is map mapping the connector type to the appropriate name. (see SFF-8024 Rev. 4.9, Table 4-3) +const char* sfp_connector_map[256] = { + "Unknown or unspecified", + "SC", + "Fibre Channel Style 1", + "Fibre Channel Style 2", + "BNC/TNC", + "Fibre Channel Coax", + "Fiber Jack", + "LC", + "MT-RJ", + "MU", + "SG", + "Optical Pigtail", + "MP0 1x12", + "MP 2x16", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "HSSDC II", + "Copper pigtail", + "RJ45", + "No seperable connector", + "MXC 2x16", + "CS optical connector", + "SN (prev. Mini CS)", + "MPO 2x12", + "MPO 1x16", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved"}; + +void str_part(uint8_t* data, char* buffer, int start, int len) { + int i; + for(i = start; i < start + len; i++) { + buffer[i - start] = data[i]; + } + buffer[i - start] = '\0'; +} + +/* +void print_part(uint8_t *data, char *ptype, char *prefix, int start, int len){ + printf("%s: ", prefix); + for (int i=start; ivendor, 20, 16); + str_part(sfp_data, i2c_sfp_state->rev, 56, 4); + str_part(sfp_data, i2c_sfp_state->pn, 40, 16); + str_part(sfp_data, i2c_sfp_state->sn, 68, 16); + str_part(sfp_data, i2c_sfp_state->dc, 84, 6); + + //Look up connector in table and copy to struct. + strcpy(i2c_sfp_state->connector, sfp_connector_map[sfp_data[2]]); + i2c_sfp_state->bitrate = sfp_data[12] * 100; + i2c_sfp_state->wavelength = sfp_data[60] * 256 + sfp_data[61]; + i2c_sfp_state->sm_reach = sfp_data[14]; + i2c_sfp_state->mm_reach_om3 = sfp_data[19] * 10; + } + furi_hal_i2c_release(&furi_hal_i2c_handle_external); +} diff --git a/applications/main/gpio/gpio_i2c_sfp_control.h b/applications/main/gpio/gpio_i2c_sfp_control.h new file mode 100644 index 000000000..7a9f4bcbe --- /dev/null +++ b/applications/main/gpio/gpio_i2c_sfp_control.h @@ -0,0 +1,32 @@ +#pragma once + +#include +#include + +#include + +#define FIRST_NON_RESERVED_I2C_ADDRESS 8 +#define HIGHEST_I2C_ADDRESS 127 +#define AVAILABLE_NONRESVERED_I2C_ADDRESSES 120 +#define SFP_I2C_ADDRESS 0x50 + +typedef struct { + char vendor[32]; + char oui[32]; + char rev[32]; + char pn[32]; + char sn[32]; + char dc[32]; + uint8_t type; + char connector[32]; + int wavelength; + int sm_reach; + int mm_reach_om3; + int bitrate; +} I2CSfpState; + +/** Reads data from a connected SFP on I2C-Bus (SDA: Pin 15, SCL: Pin 16). Saves data from SFP. + * + * @param i2c_sfp_state Data collected from SFP. + */ +void gpio_i2c_sfp_run_once(I2CSfpState* st); diff --git a/applications/main/gpio/scenes/gpio_scene_config.h b/applications/main/gpio/scenes/gpio_scene_config.h index 3406e42d3..faca22d8d 100644 --- a/applications/main/gpio/scenes/gpio_scene_config.h +++ b/applications/main/gpio/scenes/gpio_scene_config.h @@ -3,3 +3,5 @@ ADD_SCENE(gpio, test, Test) ADD_SCENE(gpio, usb_uart, UsbUart) ADD_SCENE(gpio, usb_uart_cfg, UsbUartCfg) ADD_SCENE(gpio, usb_uart_close_rpc, UsbUartCloseRpc) +ADD_SCENE(gpio, i2c_scanner, I2CScanner) +ADD_SCENE(gpio, i2c_sfp, I2CSfp) diff --git a/applications/main/gpio/scenes/gpio_scene_i2c_scanner.c b/applications/main/gpio/scenes/gpio_scene_i2c_scanner.c new file mode 100644 index 000000000..7b310debc --- /dev/null +++ b/applications/main/gpio/scenes/gpio_scene_i2c_scanner.c @@ -0,0 +1,36 @@ +#include "../gpio_app_i.h" +#include + +static I2CScannerState* i2c_scanner_state; + +void gpio_scene_i2c_scanner_ok_callback(InputType type, void* context) { + furi_assert(context); + GpioApp* app = context; + + if(type == InputTypeRelease) { + notification_message(app->notifications, &sequence_set_green_255); + gpio_i2c_scanner_run_once(i2c_scanner_state); + notification_message(app->notifications, &sequence_reset_green); + gpio_i2c_scanner_update_state(app->gpio_i2c_scanner, i2c_scanner_state); + } +} + +void gpio_scene_i2c_scanner_on_enter(void* context) { + GpioApp* app = context; + i2c_scanner_state = malloc(sizeof(I2CScannerState)); + + gpio_i2c_scanner_set_ok_callback( + app->gpio_i2c_scanner, gpio_scene_i2c_scanner_ok_callback, app); + view_dispatcher_switch_to_view(app->view_dispatcher, GpioAppViewI2CScanner); +} + +bool gpio_scene_i2c_scanner_on_event(void* context, SceneManagerEvent event) { + UNUSED(context); + UNUSED(event); + return false; +} + +void gpio_scene_i2c_scanner_on_exit(void* context) { + UNUSED(context); + free(i2c_scanner_state); +} diff --git a/applications/main/gpio/scenes/gpio_scene_i2c_sfp.c b/applications/main/gpio/scenes/gpio_scene_i2c_sfp.c new file mode 100644 index 000000000..49d0e8dd2 --- /dev/null +++ b/applications/main/gpio/scenes/gpio_scene_i2c_sfp.c @@ -0,0 +1,35 @@ +#include "../gpio_app_i.h" +#include + +static I2CSfpState* i2c_sfp_state; + +void gpio_scene_i2c_sfp_ok_callback(InputType type, void* context) { + furi_assert(context); + GpioApp* app = context; + + if(type == InputTypeRelease) { + notification_message(app->notifications, &sequence_set_green_255); + gpio_i2c_sfp_run_once(i2c_sfp_state); + notification_message(app->notifications, &sequence_reset_green); + gpio_i2c_sfp_update_state(app->gpio_i2c_sfp, i2c_sfp_state); + } +} + +void gpio_scene_i2c_sfp_on_enter(void* context) { + GpioApp* app = context; + i2c_sfp_state = malloc(sizeof(I2CSfpState)); + + gpio_i2c_sfp_set_ok_callback(app->gpio_i2c_sfp, gpio_scene_i2c_sfp_ok_callback, app); + view_dispatcher_switch_to_view(app->view_dispatcher, GpioAppViewI2CSfp); +} + +bool gpio_scene_i2c_sfp_on_event(void* context, SceneManagerEvent event) { + UNUSED(context); + UNUSED(event); + return false; +} + +void gpio_scene_i2c_sfp_on_exit(void* context) { + UNUSED(context); + free(i2c_sfp_state); +} diff --git a/applications/main/gpio/scenes/gpio_scene_start.c b/applications/main/gpio/scenes/gpio_scene_start.c index 729922949..08b77238f 100644 --- a/applications/main/gpio/scenes/gpio_scene_start.c +++ b/applications/main/gpio/scenes/gpio_scene_start.c @@ -1,12 +1,13 @@ #include "../gpio_app_i.h" #include "furi_hal_power.h" #include "furi_hal_usb.h" -#include enum GpioItem { GpioItemUsbUart, GpioItemTest, GpioItemOtg, + GpioItemI2CScanner, + GpioItemI2CSfp, }; enum GpioOtg { @@ -27,6 +28,10 @@ static void gpio_scene_start_var_list_enter_callback(void* context, uint32_t ind view_dispatcher_send_custom_event(app->view_dispatcher, GpioStartEventManualControl); } else if(index == GpioItemUsbUart) { view_dispatcher_send_custom_event(app->view_dispatcher, GpioStartEventUsbUart); + } else if(index == GpioItemI2CScanner) { + view_dispatcher_send_custom_event(app->view_dispatcher, GpioStartEventI2CScanner); + } else if(index == GpioItemI2CSfp) { + view_dispatcher_send_custom_event(app->view_dispatcher, GpioStartEventI2CSfp); } } @@ -68,6 +73,9 @@ void gpio_scene_start_on_enter(void* context) { variable_item_set_current_value_text(item, gpio_otg_text[GpioOtgOff]); } + variable_item_list_add(var_item_list, "I2C-Scanner", 0, NULL, NULL); + variable_item_list_add(var_item_list, "I2C-SFP", 0, NULL, NULL); + variable_item_list_set_selected_item( var_item_list, scene_manager_get_scene_state(app->scene_manager, GpioSceneStart)); @@ -86,10 +94,15 @@ bool gpio_scene_start_on_event(void* context, SceneManagerEvent event) { } else if(event.event == GpioStartEventManualControl) { scene_manager_set_scene_state(app->scene_manager, GpioSceneStart, GpioItemTest); scene_manager_next_scene(app->scene_manager, GpioSceneTest); + } else if(event.event == GpioStartEventI2CScanner) { + scene_manager_set_scene_state(app->scene_manager, GpioSceneStart, GpioItemI2CScanner); + scene_manager_next_scene(app->scene_manager, GpioSceneI2CScanner); + } else if(event.event == GpioStartEventI2CSfp) { + scene_manager_set_scene_state(app->scene_manager, GpioSceneStart, GpioItemI2CSfp); + scene_manager_next_scene(app->scene_manager, GpioSceneI2CSfp); } else if(event.event == GpioStartEventUsbUart) { scene_manager_set_scene_state(app->scene_manager, GpioSceneStart, GpioItemUsbUart); if(!furi_hal_usb_is_locked()) { - DOLPHIN_DEED(DolphinDeedGpioUartBridge); scene_manager_next_scene(app->scene_manager, GpioSceneUsbUart); } else { scene_manager_next_scene(app->scene_manager, GpioSceneUsbUartCloseRpc); diff --git a/applications/main/gpio/views/gpio_i2c_scanner.c b/applications/main/gpio/views/gpio_i2c_scanner.c new file mode 100644 index 000000000..3b207b6e3 --- /dev/null +++ b/applications/main/gpio/views/gpio_i2c_scanner.c @@ -0,0 +1,139 @@ +#include +#include "gpio_i2c_scanner.h" +#include "../gpio_item.h" + +#include + +struct GpioI2CScanner { + View* view; + GpioI2CScannerOkCallback callback; + void* context; +}; + +typedef struct { + uint8_t items; + uint8_t responding_address[AVAILABLE_NONRESVERED_I2C_ADDRESSES]; +} GpioI2CScannerModel; + +static bool gpio_i2c_scanner_process_ok(GpioI2CScanner* gpio_i2c_scanner, InputEvent* event); + +static void gpio_i2c_scanner_draw_callback(Canvas* canvas, void* _model) { + GpioI2CScannerModel* model = _model; + + char temp_str[25]; + elements_button_center(canvas, "Start scan"); + canvas_draw_line(canvas, 2, 10, 125, 10); + canvas_draw_line(canvas, 2, 52, 125, 52); + + canvas_set_font(canvas, FontPrimary); + canvas_draw_str(canvas, 2, 9, "I2C-Scanner"); + canvas_draw_str(canvas, 3, 25, "SDA:"); + canvas_draw_str(canvas, 3, 42, "SCL:"); + + canvas_set_font(canvas, FontSecondary); + snprintf(temp_str, 25, "Slaves: %u", model->items); + canvas_draw_str_aligned(canvas, 126, 8, AlignRight, AlignBottom, temp_str); + + canvas_draw_str(canvas, 29, 25, "Pin 15"); + canvas_draw_str(canvas, 29, 42, "Pin 16"); + + canvas_set_font(canvas, FontSecondary); + + char temp_str2[6]; + if(model->items > 0) { + snprintf(temp_str, 25, "Addr: "); + for(int i = 0; i < model->items; i++) { + snprintf(temp_str2, 6, "0x%x ", model->responding_address[i]); + strcat(temp_str, temp_str2); + + if(i == 1 || model->items == 1) { //Draw a maximum of two addresses in the first line + canvas_draw_str_aligned(canvas, 127, 24, AlignRight, AlignBottom, temp_str); + temp_str[0] = '\0'; + } else if( + i == 4 || (model->items - 1 == i && + i < 6)) { //Draw a maximum of three addresses in the second line + canvas_draw_str_aligned(canvas, 127, 36, AlignRight, AlignBottom, temp_str); + temp_str[0] = '\0'; + } else if(i == 7 || model->items - 1 == i) { //Draw a maximum of three addresses in the third line + canvas_draw_str_aligned(canvas, 127, 48, AlignRight, AlignBottom, temp_str); + break; + } + } + } +} + +static bool gpio_i2c_scanner_input_callback(InputEvent* event, void* context) { + furi_assert(context); + GpioI2CScanner* gpio_i2c_scanner = context; + bool consumed = false; + + if(event->key == InputKeyOk) { + consumed = gpio_i2c_scanner_process_ok(gpio_i2c_scanner, event); + } + + return consumed; +} + +static bool gpio_i2c_scanner_process_ok(GpioI2CScanner* gpio_i2c_scanner, InputEvent* event) { + bool consumed = false; + gpio_i2c_scanner->callback(event->type, gpio_i2c_scanner->context); + + return consumed; +} + +GpioI2CScanner* gpio_i2c_scanner_alloc() { + GpioI2CScanner* gpio_i2c_scanner = malloc(sizeof(GpioI2CScanner)); + + gpio_i2c_scanner->view = view_alloc(); + view_allocate_model(gpio_i2c_scanner->view, ViewModelTypeLocking, sizeof(GpioI2CScannerModel)); + view_set_context(gpio_i2c_scanner->view, gpio_i2c_scanner); + view_set_draw_callback(gpio_i2c_scanner->view, gpio_i2c_scanner_draw_callback); + view_set_input_callback(gpio_i2c_scanner->view, gpio_i2c_scanner_input_callback); + + return gpio_i2c_scanner; +} + +void gpio_i2c_scanner_free(GpioI2CScanner* gpio_i2c_scanner) { + furi_assert(gpio_i2c_scanner); + view_free(gpio_i2c_scanner->view); + free(gpio_i2c_scanner); +} + +View* gpio_i2c_scanner_get_view(GpioI2CScanner* gpio_i2c_scanner) { + furi_assert(gpio_i2c_scanner); + return gpio_i2c_scanner->view; +} + +void gpio_i2c_scanner_set_ok_callback( + GpioI2CScanner* gpio_i2c_scanner, + GpioI2CScannerOkCallback callback, + void* context) { + furi_assert(gpio_i2c_scanner); + furi_assert(callback); + with_view_model( + gpio_i2c_scanner->view, + GpioI2CScannerModel * model, + { + UNUSED(model); + gpio_i2c_scanner->callback = callback; + gpio_i2c_scanner->context = context; + }, + false); +} + +void gpio_i2c_scanner_update_state(GpioI2CScanner* instance, I2CScannerState* st) { + furi_assert(instance); + furi_assert(st); + + with_view_model( + instance->view, + GpioI2CScannerModel * model, + { + model->items = st->items; + + for(int i = 0; i < model->items; i++) { + model->responding_address[i] = st->responding_address[i]; + } + }, + true); +} diff --git a/applications/main/gpio/views/gpio_i2c_scanner.h b/applications/main/gpio/views/gpio_i2c_scanner.h new file mode 100644 index 000000000..52ebf3de3 --- /dev/null +++ b/applications/main/gpio/views/gpio_i2c_scanner.h @@ -0,0 +1,20 @@ +#pragma once + +#include +#include "../gpio_i2c_scanner_control.h" + +typedef struct GpioI2CScanner GpioI2CScanner; +typedef void (*GpioI2CScannerOkCallback)(InputType type, void* context); + +GpioI2CScanner* gpio_i2c_scanner_alloc(); + +void gpio_i2c_scanner_free(GpioI2CScanner* gpio_i2c_scanner); + +View* gpio_i2c_scanner_get_view(GpioI2CScanner* gpio_i2c_scanner); + +void gpio_i2c_scanner_set_ok_callback( + GpioI2CScanner* gpio_i2c_scanner, + GpioI2CScannerOkCallback callback, + void* context); + +void gpio_i2c_scanner_update_state(GpioI2CScanner* instance, I2CScannerState* st); diff --git a/applications/main/gpio/views/gpio_i2c_sfp.c b/applications/main/gpio/views/gpio_i2c_sfp.c new file mode 100644 index 000000000..695260ef2 --- /dev/null +++ b/applications/main/gpio/views/gpio_i2c_sfp.c @@ -0,0 +1,149 @@ +#include +#include "gpio_i2c_sfp.h" +#include "../gpio_item.h" + +#include + +struct GpioI2CSfp { + View* view; + GpioI2CSfpOkCallback callback; + void* context; +}; + +typedef struct { + char vendor[32]; + char oui[32]; + char rev[32]; + char pn[32]; + char sn[32]; + char dc[32]; + uint8_t type; + char connector[32]; + int wavelength; + int sm_reach; + int mm_reach_om3; + int bitrate; +} GpioI2CSfpModel; + +static bool gpio_i2c_sfp_process_ok(GpioI2CSfp* gpio_i2c_sfp, InputEvent* event); + +static void gpio_i2c_sfp_draw_callback(Canvas* canvas, void* _model) { + GpioI2CSfpModel* model = _model; + + // Temp String for formatting output + char temp_str[280]; + + canvas_set_font(canvas, FontSecondary); + elements_button_center(canvas, "Read"); + canvas_draw_str(canvas, 2, 63, "P15 SCL"); + canvas_draw_str(canvas, 92, 63, "P16 SDA"); + + snprintf(temp_str, 280, "Vendor: %s", model->vendor); + canvas_draw_str(canvas, 2, 9, temp_str); + + snprintf(temp_str, 280, "PN: %s", model->pn); + canvas_draw_str(canvas, 2, 19, temp_str); + + snprintf(temp_str, 280, "SN: %s", model->sn); + canvas_draw_str(canvas, 2, 29, temp_str); + + snprintf(temp_str, 280, "REV: %s", model->rev); + canvas_draw_str(canvas, 2, 39, temp_str); + + snprintf(temp_str, 280, "CON: %s", model->connector); + canvas_draw_str(canvas, 50, 39, temp_str); + + //Print Wavelength of Module + snprintf(temp_str, 280, "%u nm", model->wavelength); + canvas_draw_str(canvas, 2, 49, temp_str); + + // These values will be zero if not applicable.. + if(model->sm_reach != 0) { + snprintf(temp_str, 280, "%u km (SM)", model->sm_reach); + canvas_draw_str(canvas, 50, 49, temp_str); + } + if(model->mm_reach_om3 != 0) { + snprintf(temp_str, 280, "%u m (MM OM3)", model->mm_reach_om3); + canvas_draw_str(canvas, 50, 49, temp_str); + } +} + +static bool gpio_i2c_sfp_input_callback(InputEvent* event, void* context) { + furi_assert(context); + GpioI2CSfp* gpio_i2c_sfp = context; + bool consumed = false; + + if(event->key == InputKeyOk) { + consumed = gpio_i2c_sfp_process_ok(gpio_i2c_sfp, event); + } + + return consumed; +} + +static bool gpio_i2c_sfp_process_ok(GpioI2CSfp* gpio_i2c_sfp, InputEvent* event) { + bool consumed = false; + gpio_i2c_sfp->callback(event->type, gpio_i2c_sfp->context); + + return consumed; +} + +GpioI2CSfp* gpio_i2c_sfp_alloc() { + GpioI2CSfp* gpio_i2c_sfp = malloc(sizeof(GpioI2CSfp)); + + gpio_i2c_sfp->view = view_alloc(); + view_allocate_model(gpio_i2c_sfp->view, ViewModelTypeLocking, sizeof(GpioI2CSfpModel)); + view_set_context(gpio_i2c_sfp->view, gpio_i2c_sfp); + view_set_draw_callback(gpio_i2c_sfp->view, gpio_i2c_sfp_draw_callback); + view_set_input_callback(gpio_i2c_sfp->view, gpio_i2c_sfp_input_callback); + + return gpio_i2c_sfp; +} + +void gpio_i2c_sfp_free(GpioI2CSfp* gpio_i2c_sfp) { + furi_assert(gpio_i2c_sfp); + view_free(gpio_i2c_sfp->view); + free(gpio_i2c_sfp); +} + +View* gpio_i2c_sfp_get_view(GpioI2CSfp* gpio_i2c_sfp) { + furi_assert(gpio_i2c_sfp); + return gpio_i2c_sfp->view; +} + +void gpio_i2c_sfp_set_ok_callback( + GpioI2CSfp* gpio_i2c_sfp, + GpioI2CSfpOkCallback callback, + void* context) { + furi_assert(gpio_i2c_sfp); + furi_assert(callback); + with_view_model( + gpio_i2c_sfp->view, + GpioI2CSfpModel * model, + { + UNUSED(model); + gpio_i2c_sfp->callback = callback; + gpio_i2c_sfp->context = context; + }, + false); +} + +void gpio_i2c_sfp_update_state(GpioI2CSfp* instance, I2CSfpState* st) { + furi_assert(instance); + furi_assert(st); + + with_view_model( + instance->view, + GpioI2CSfpModel * model, + { + // Insert values into model... + strcpy(model->vendor, st->vendor); + strcpy(model->pn, st->pn); + strcpy(model->sn, st->sn); + strcpy(model->rev, st->rev); + strcpy(model->connector, st->connector); + model->wavelength = st->wavelength; + model->sm_reach = st->sm_reach; + model->mm_reach_om3 = st->mm_reach_om3; + }, + true); +} diff --git a/applications/main/gpio/views/gpio_i2c_sfp.h b/applications/main/gpio/views/gpio_i2c_sfp.h new file mode 100644 index 000000000..c57c143a4 --- /dev/null +++ b/applications/main/gpio/views/gpio_i2c_sfp.h @@ -0,0 +1,20 @@ +#pragma once + +#include +#include "../gpio_i2c_sfp_control.h" + +typedef struct GpioI2CSfp GpioI2CSfp; +typedef void (*GpioI2CSfpOkCallback)(InputType type, void* context); + +GpioI2CSfp* gpio_i2c_sfp_alloc(); + +void gpio_i2c_sfp_free(GpioI2CSfp* gpio_i2c_sfp); + +View* gpio_i2c_sfp_get_view(GpioI2CSfp* gpio_i2c_sfp); + +void gpio_i2c_sfp_set_ok_callback( + GpioI2CSfp* gpio_i2c_sfp, + GpioI2CSfpOkCallback callback, + void* context); + +void gpio_i2c_sfp_update_state(GpioI2CSfp* instance, I2CSfpState* st);