BRING BACK GPIO

This commit is contained in:
RogueMaster
2022-10-30 19:15:47 -04:00
parent e300e9c0a9
commit 99f08decb2
16 changed files with 852 additions and 4 deletions

View File

@@ -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)
<details>
<summary><B>TO DO / REMOVED</b></summary><br/>
- [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)

View File

@@ -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);

View File

@@ -15,6 +15,8 @@
#include <gui/modules/widget.h>
#include "views/gpio_test.h"
#include "views/gpio_usb_uart.h"
#include "views/gpio_i2c_scanner.h"
#include "views/gpio_i2c_sfp.h"
#include <assets_icons.h>
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;

View File

@@ -5,6 +5,8 @@ typedef enum {
GpioStartEventOtgOn,
GpioStartEventManualControl,
GpioStartEventUsbUart,
GpioStartEventI2CScanner,
GpioStartEventI2CSfp,
GpioCustomEventErrorBack,

View File

@@ -0,0 +1,23 @@
#include "gpio_i2c_scanner_control.h"
#include <furi.h>
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);
}

View File

@@ -0,0 +1,21 @@
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include <furi_hal_i2c.h>
#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);

View File

@@ -0,0 +1,334 @@
#include "gpio_i2c_sfp_control.h"
#include <furi_hal.h>
#include <string.h>
// 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; i<start+len; i++){
printf(ptype, data[i]);
}
printf("\n");
}
*/
void gpio_i2c_sfp_run_once(I2CSfpState* i2c_sfp_state) {
furi_hal_i2c_acquire(&furi_hal_i2c_handle_external);
// Allocate buffer for SFP Data
uint8_t sfp_data[255];
uint32_t response_timeout_ticks = furi_ms_to_ticks(5.f);
// Check for SFP Module on I2C Bus
if(furi_hal_i2c_is_device_ready(
&furi_hal_i2c_handle_external, SFP_I2C_ADDRESS << 1, response_timeout_ticks)) {
for(uint8_t i = 0; i <= 254; i++) {
uint8_t data = 0;
// Read data from register
furi_hal_i2c_read_reg_8(
&furi_hal_i2c_handle_external,
SFP_I2C_ADDRESS << 1,
i,
&data,
response_timeout_ticks);
// Save data
sfp_data[i] = data;
}
/*
print_part(sfp_data, "%c", "Vendor", 20, 16);
print_part(sfp_data, "%02X", "OUI", 37, 3);
print_part(sfp_data, "%c", "Rev", 56, 4);
print_part(sfp_data, "%c", "PN", 40, 16);
print_part(sfp_data, "%c", "SN", 68, 16);
print_part(sfp_data, "%c", "DC", 84, 6);
printf("Typ: 0x%02X\r\n", sfp_data[0]);
printf("Connector: 0x%02X\r\n", sfp_data[2]);
printf("Bitrate: %u MBd\r\n", sfp_data[12]*100);
printf("Wavelength: %u nm\r\n", sfp_data[60] * 256 + sfp_data[61]);
printf(" %-6s %-6s %-6s %-6s %-6s\r\n", "SM", "OM1", "OM2", "OM3", "OM4");
printf("Max length: %3u km %4u m %4u m %4u m %4u m\r\n", sfp_data[14], sfp_data[17]*10, sfp_data[16]*10, sfp_data[19]*10, sfp_data[18]*10);
*/
str_part(sfp_data, i2c_sfp_state->vendor, 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);
}

View File

@@ -0,0 +1,32 @@
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include <furi_hal_i2c.h>
#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);

View File

@@ -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)

View File

@@ -0,0 +1,36 @@
#include "../gpio_app_i.h"
#include <furi_hal_gpio.h>
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);
}

View File

@@ -0,0 +1,35 @@
#include "../gpio_app_i.h"
#include <furi_hal_gpio.h>
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);
}

View File

@@ -1,12 +1,13 @@
#include "../gpio_app_i.h"
#include "furi_hal_power.h"
#include "furi_hal_usb.h"
#include <dolphin/dolphin.h>
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);

View File

@@ -0,0 +1,139 @@
#include <gui/elements.h>
#include "gpio_i2c_scanner.h"
#include "../gpio_item.h"
#include <string.h>
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);
}

View File

@@ -0,0 +1,20 @@
#pragma once
#include <gui/view.h>
#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);

View File

@@ -0,0 +1,149 @@
#include <gui/elements.h>
#include "gpio_i2c_sfp.h"
#include "../gpio_item.h"
#include <string.h>
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);
}

View File

@@ -0,0 +1,20 @@
#pragma once
#include <gui/view.h>
#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);