mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-04-24 03:29:57 -07:00
BRING BACK GPIO
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -5,6 +5,8 @@ typedef enum {
|
||||
GpioStartEventOtgOn,
|
||||
GpioStartEventManualControl,
|
||||
GpioStartEventUsbUart,
|
||||
GpioStartEventI2CScanner,
|
||||
GpioStartEventI2CSfp,
|
||||
|
||||
GpioCustomEventErrorBack,
|
||||
|
||||
|
||||
23
applications/main/gpio/gpio_i2c_scanner_control.c
Normal file
23
applications/main/gpio/gpio_i2c_scanner_control.c
Normal 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);
|
||||
}
|
||||
21
applications/main/gpio/gpio_i2c_scanner_control.h
Normal file
21
applications/main/gpio/gpio_i2c_scanner_control.h
Normal 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);
|
||||
334
applications/main/gpio/gpio_i2c_sfp_control.c
Normal file
334
applications/main/gpio/gpio_i2c_sfp_control.c
Normal 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);
|
||||
}
|
||||
32
applications/main/gpio/gpio_i2c_sfp_control.h
Normal file
32
applications/main/gpio/gpio_i2c_sfp_control.h
Normal 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);
|
||||
@@ -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)
|
||||
|
||||
36
applications/main/gpio/scenes/gpio_scene_i2c_scanner.c
Normal file
36
applications/main/gpio/scenes/gpio_scene_i2c_scanner.c
Normal 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);
|
||||
}
|
||||
35
applications/main/gpio/scenes/gpio_scene_i2c_sfp.c
Normal file
35
applications/main/gpio/scenes/gpio_scene_i2c_sfp.c
Normal 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);
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
139
applications/main/gpio/views/gpio_i2c_scanner.c
Normal file
139
applications/main/gpio/views/gpio_i2c_scanner.c
Normal 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);
|
||||
}
|
||||
20
applications/main/gpio/views/gpio_i2c_scanner.h
Normal file
20
applications/main/gpio/views/gpio_i2c_scanner.h
Normal 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);
|
||||
149
applications/main/gpio/views/gpio_i2c_sfp.c
Normal file
149
applications/main/gpio/views/gpio_i2c_sfp.c
Normal 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);
|
||||
}
|
||||
20
applications/main/gpio/views/gpio_i2c_sfp.h
Normal file
20
applications/main/gpio/views/gpio_i2c_sfp.h
Normal 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);
|
||||
Reference in New Issue
Block a user