Skip to content

Commit 66a8aa7

Browse files
authored
Merge pull request #139 from GitChris3004/gpio_i2c_scanner
Gpio i2c scanner
2 parents 368d1a0 + c50b547 commit 66a8aa7

10 files changed

+253
-1
lines changed

applications/gpio/gpio_app.c

+6
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ GpioApp* gpio_app_alloc() {
5151
view_dispatcher_add_view(
5252
app->view_dispatcher, GpioAppViewGpioTest, gpio_test_get_view(app->gpio_test));
5353

54+
app->gpio_i2c_scanner = gpio_i2c_scanner_alloc();
55+
view_dispatcher_add_view(
56+
app->view_dispatcher, GpioAppViewI2CScanner, gpio_i2c_scanner_get_view(app->gpio_i2c_scanner));
57+
5458
app->widget = widget_alloc();
5559
view_dispatcher_add_view(
5660
app->view_dispatcher, GpioAppViewUsbUartCloseRpc, widget_get_view(app->widget));
@@ -75,13 +79,15 @@ void gpio_app_free(GpioApp* app) {
7579
// Views
7680
view_dispatcher_remove_view(app->view_dispatcher, GpioAppViewVarItemList);
7781
view_dispatcher_remove_view(app->view_dispatcher, GpioAppViewGpioTest);
82+
view_dispatcher_remove_view(app->view_dispatcher, GpioAppViewI2CScanner);
7883
view_dispatcher_remove_view(app->view_dispatcher, GpioAppViewUsbUart);
7984
view_dispatcher_remove_view(app->view_dispatcher, GpioAppViewUsbUartCfg);
8085
view_dispatcher_remove_view(app->view_dispatcher, GpioAppViewUsbUartCloseRpc);
8186
variable_item_list_free(app->var_item_list);
8287
widget_free(app->widget);
8388
gpio_test_free(app->gpio_test);
8489
gpio_usb_uart_free(app->gpio_usb_uart);
90+
gpio_i2c_scanner_free(app->gpio_i2c_scanner);
8591

8692
// View dispatcher
8793
view_dispatcher_free(app->view_dispatcher);

applications/gpio/gpio_app_i.h

+3
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <gui/modules/widget.h>
1616
#include "views/gpio_test.h"
1717
#include "views/gpio_usb_uart.h"
18+
#include "views/gpio_i2c_scanner.h"
1819

1920
struct GpioApp {
2021
Gui* gui;
@@ -27,6 +28,7 @@ struct GpioApp {
2728
GpioTest* gpio_test;
2829
GpioUsbUart* gpio_usb_uart;
2930
UsbUartBridge* usb_uart_bridge;
31+
GpioI2CScanner* gpio_i2c_scanner;
3032
};
3133

3234
typedef enum {
@@ -35,4 +37,5 @@ typedef enum {
3537
GpioAppViewUsbUart,
3638
GpioAppViewUsbUartCfg,
3739
GpioAppViewUsbUartCloseRpc,
40+
GpioAppViewI2CScanner,
3841
} GpioAppView;

applications/gpio/gpio_custom_event.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ typedef enum {
55
GpioStartEventOtgOn,
66
GpioStartEventManualControl,
77
GpioStartEventUsbUart,
8-
8+
GpioStartEventI2CScanner,
9+
910
GpioCustomEventErrorBack,
1011

1112
GpioUsbUartEventConfig,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#include "gpio_i2c_scanner_control.h"
2+
#include <furi_hal_delay.h>
3+
4+
5+
void gpio_i2c_scanner_run_once(I2CScannerState* i2c_scanner_state) {
6+
//Reset the number of items for rewriting the array
7+
i2c_scanner_state->items = 0;
8+
furi_hal_i2c_acquire(&furi_hal_i2c_handle_external);
9+
10+
uint32_t response_timeout_ticks = furi_hal_ms_to_ticks(5.f);
11+
12+
//Addresses 0 to 7 are reserved and won't be scanned
13+
for(int i = FIRST_NON_RESERVED_I2C_ADDRESS; i<=HIGHEST_I2C_ADDRESS; i++) {
14+
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
15+
i2c_scanner_state->responding_address[i2c_scanner_state->items] = i;
16+
i2c_scanner_state->items++;
17+
}
18+
}
19+
20+
furi_hal_i2c_release(&furi_hal_i2c_handle_external);
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#pragma once
2+
3+
#include <stdint.h>
4+
#include <stdbool.h>
5+
6+
#include <furi_hal_i2c.h>
7+
8+
#define FIRST_NON_RESERVED_I2C_ADDRESS 8
9+
#define HIGHEST_I2C_ADDRESS 127
10+
#define AVAILABLE_NONRESVERED_I2C_ADDRESSES 120
11+
12+
typedef struct {
13+
uint8_t items;
14+
uint8_t responding_address[AVAILABLE_NONRESVERED_I2C_ADDRESSES];
15+
} I2CScannerState;
16+
17+
/** 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.
18+
*
19+
* @param i2c_scanner_state State including the detected addresses and the number of addresses saved.
20+
*/
21+
void gpio_i2c_scanner_run_once(I2CScannerState* st);

applications/gpio/scenes/gpio_scene_config.h

+1
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ ADD_SCENE(gpio, test, Test)
33
ADD_SCENE(gpio, usb_uart, UsbUart)
44
ADD_SCENE(gpio, usb_uart_cfg, UsbUartCfg)
55
ADD_SCENE(gpio, usb_uart_close_rpc, UsbUartCloseRpc)
6+
ADD_SCENE(gpio, i2c_scanner, I2CScanner)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#include "../gpio_app_i.h"
2+
#include <furi_hal_gpio.h>
3+
4+
static I2CScannerState* i2c_scanner_state;
5+
6+
7+
void gpio_scene_i2c_scanner_ok_callback(InputType type, void* context) {
8+
furi_assert(context);
9+
GpioApp* app = context;
10+
11+
if(type == InputTypeRelease) {
12+
notification_message(app->notifications, &sequence_set_green_255);
13+
gpio_i2c_scanner_run_once(i2c_scanner_state);
14+
notification_message(app->notifications, &sequence_reset_green);
15+
gpio_i2c_scanner_update_state(app->gpio_i2c_scanner, i2c_scanner_state);
16+
}
17+
}
18+
19+
void gpio_scene_i2c_scanner_on_enter(void* context) {
20+
GpioApp* app = context;
21+
i2c_scanner_state = malloc(sizeof(I2CScannerState));
22+
23+
gpio_i2c_scanner_set_ok_callback(app->gpio_i2c_scanner, gpio_scene_i2c_scanner_ok_callback, app);
24+
view_dispatcher_switch_to_view(app->view_dispatcher, GpioAppViewI2CScanner);
25+
}
26+
27+
bool gpio_scene_i2c_scanner_on_event(void* context, SceneManagerEvent event) {
28+
UNUSED(context);
29+
UNUSED(event);
30+
return false;
31+
}
32+
33+
void gpio_scene_i2c_scanner_on_exit(void* context) {
34+
UNUSED(context);
35+
free(i2c_scanner_state);
36+
}

applications/gpio/scenes/gpio_scene_start.c

+8
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ enum GpioItem {
66
GpioItemUsbUart,
77
GpioItemTest,
88
GpioItemOtg,
9+
GpioItemI2CScanner,
910
};
1011

1112
enum GpioOtg {
@@ -26,6 +27,8 @@ static void gpio_scene_start_var_list_enter_callback(void* context, uint32_t ind
2627
view_dispatcher_send_custom_event(app->view_dispatcher, GpioStartEventManualControl);
2728
} else if(index == GpioItemUsbUart) {
2829
view_dispatcher_send_custom_event(app->view_dispatcher, GpioStartEventUsbUart);
30+
} else if(index == GpioItemI2CScanner) {
31+
view_dispatcher_send_custom_event(app->view_dispatcher, GpioStartEventI2CScanner);
2932
}
3033
}
3134

@@ -66,6 +69,8 @@ void gpio_scene_start_on_enter(void* context) {
6669
variable_item_set_current_value_index(item, GpioOtgOff);
6770
variable_item_set_current_value_text(item, gpio_otg_text[GpioOtgOff]);
6871
}
72+
73+
variable_item_list_add(var_item_list, "I2C-Scanner", 0, NULL, NULL);
6974

7075
variable_item_list_set_selected_item(
7176
var_item_list, scene_manager_get_scene_state(app->scene_manager, GpioSceneStart));
@@ -85,6 +90,9 @@ bool gpio_scene_start_on_event(void* context, SceneManagerEvent event) {
8590
} else if(event.event == GpioStartEventManualControl) {
8691
scene_manager_set_scene_state(app->scene_manager, GpioSceneStart, GpioItemTest);
8792
scene_manager_next_scene(app->scene_manager, GpioSceneTest);
93+
} else if(event.event == GpioStartEventI2CScanner) {
94+
scene_manager_set_scene_state(app->scene_manager, GpioSceneStart, GpioItemI2CScanner);
95+
scene_manager_next_scene(app->scene_manager, GpioSceneI2CScanner);
8896
} else if(event.event == GpioStartEventUsbUart) {
8997
scene_manager_set_scene_state(app->scene_manager, GpioSceneStart, GpioItemUsbUart);
9098
if(!furi_hal_usb_is_locked()) {
+136
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
#include <gui/elements.h>
2+
#include "gpio_i2c_scanner.h"
3+
#include "../gpio_item.h"
4+
5+
#include <string.h>
6+
7+
8+
struct GpioI2CScanner {
9+
View* view;
10+
GpioI2CScannerOkCallback callback;
11+
void* context;
12+
};
13+
14+
typedef struct {
15+
uint8_t items;
16+
uint8_t responding_address[AVAILABLE_NONRESVERED_I2C_ADDRESSES];
17+
} GpioI2CScannerModel;
18+
19+
static bool gpio_i2c_scanner_process_ok(GpioI2CScanner* gpio_i2c_scanner, InputEvent* event);
20+
21+
static void gpio_i2c_scanner_draw_callback(Canvas* canvas, void* _model) {
22+
GpioI2CScannerModel* model = _model;
23+
24+
char temp_str[25];
25+
elements_button_center(canvas, "Start scan");
26+
canvas_draw_line(canvas, 2, 10, 125, 10);
27+
canvas_draw_line(canvas, 2, 52, 125, 52);
28+
29+
canvas_set_font(canvas, FontPrimary);
30+
canvas_draw_str(canvas, 2, 9, "I2C-Scanner");
31+
canvas_draw_str(canvas, 3, 25, "SDA:");
32+
canvas_draw_str(canvas, 3, 42, "SCL:");
33+
34+
canvas_set_font(canvas, FontSecondary);
35+
snprintf(temp_str, 25, "Slaves: %u", model->items);
36+
canvas_draw_str_aligned(canvas, 126, 8, AlignRight, AlignBottom, temp_str);
37+
38+
canvas_draw_str(canvas, 29, 25, "Pin 15");
39+
canvas_draw_str(canvas, 29, 42, "Pin 16");
40+
41+
canvas_set_font(canvas, FontSecondary);
42+
43+
char temp_str2[6];
44+
if(model->items > 0) {
45+
snprintf(temp_str, 25, "Addr: " );
46+
for(int i = 0; i< model->items; i++){
47+
snprintf(temp_str2, 6, "0x%x ", model->responding_address[i]);
48+
strcat (temp_str, temp_str2);
49+
50+
if(i == 1 || model->items == 1) { //Draw a maximum of two addresses in the first line
51+
canvas_draw_str_aligned(canvas, 127, 24, AlignRight, AlignBottom, temp_str);
52+
temp_str[0] = '\0';
53+
}
54+
else if(i == 4 || (model->items-1 == i && i<6 )) { //Draw a maximum of three addresses in the second line
55+
canvas_draw_str_aligned(canvas, 127, 36, AlignRight, AlignBottom, temp_str);
56+
temp_str[0] = '\0';
57+
}
58+
else if(i == 7 || model->items-1 == i) { //Draw a maximum of three addresses in the third line
59+
canvas_draw_str_aligned(canvas, 127, 48, AlignRight, AlignBottom, temp_str);
60+
break;
61+
}
62+
}
63+
}
64+
}
65+
66+
static bool gpio_i2c_scanner_input_callback(InputEvent* event, void* context) {
67+
furi_assert(context);
68+
GpioI2CScanner* gpio_i2c_scanner = context;
69+
bool consumed = false;
70+
71+
if(event->key == InputKeyOk) {
72+
consumed = gpio_i2c_scanner_process_ok(gpio_i2c_scanner, event);
73+
}
74+
75+
return consumed;
76+
}
77+
78+
static bool gpio_i2c_scanner_process_ok(GpioI2CScanner* gpio_i2c_scanner, InputEvent* event) {
79+
bool consumed = false;
80+
gpio_i2c_scanner->callback(event->type, gpio_i2c_scanner->context);
81+
82+
return consumed;
83+
}
84+
85+
GpioI2CScanner* gpio_i2c_scanner_alloc() {
86+
GpioI2CScanner* gpio_i2c_scanner = malloc(sizeof(GpioI2CScanner));
87+
88+
gpio_i2c_scanner->view = view_alloc();
89+
view_allocate_model(gpio_i2c_scanner->view, ViewModelTypeLocking, sizeof(GpioI2CScannerModel));
90+
view_set_context(gpio_i2c_scanner->view, gpio_i2c_scanner);
91+
view_set_draw_callback(gpio_i2c_scanner->view, gpio_i2c_scanner_draw_callback);
92+
view_set_input_callback(gpio_i2c_scanner->view, gpio_i2c_scanner_input_callback);
93+
94+
return gpio_i2c_scanner;
95+
}
96+
97+
void gpio_i2c_scanner_free(GpioI2CScanner* gpio_i2c_scanner) {
98+
furi_assert(gpio_i2c_scanner);
99+
view_free(gpio_i2c_scanner->view);
100+
free(gpio_i2c_scanner);
101+
}
102+
103+
View* gpio_i2c_scanner_get_view(GpioI2CScanner* gpio_i2c_scanner) {
104+
furi_assert(gpio_i2c_scanner);
105+
return gpio_i2c_scanner->view;
106+
}
107+
108+
void gpio_i2c_scanner_set_ok_callback(GpioI2CScanner* gpio_i2c_scanner, GpioI2CScannerOkCallback callback, void* context) {
109+
furi_assert(gpio_i2c_scanner);
110+
furi_assert(callback);
111+
with_view_model(
112+
gpio_i2c_scanner->view, (GpioI2CScannerModel * model) {
113+
UNUSED(model);
114+
gpio_i2c_scanner->callback = callback;
115+
gpio_i2c_scanner->context = context;
116+
return false;
117+
});
118+
}
119+
120+
void gpio_i2c_scanner_update_state(GpioI2CScanner* instance, I2CScannerState* st) {
121+
furi_assert(instance);
122+
furi_assert(st);
123+
124+
with_view_model(
125+
instance->view, (GpioI2CScannerModel * model) {
126+
model->items = st->items;
127+
128+
for(int i =0; i<model->items; i++) {
129+
model->responding_address[i] = st->responding_address[i];
130+
}
131+
132+
return true;
133+
});
134+
}
135+
136+
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#pragma once
2+
3+
#include <gui/view.h>
4+
#include "../gpio_i2c_scanner_control.h"
5+
6+
7+
typedef struct GpioI2CScanner GpioI2CScanner;
8+
typedef void (*GpioI2CScannerOkCallback)(InputType type, void* context);
9+
10+
GpioI2CScanner* gpio_i2c_scanner_alloc();
11+
12+
void gpio_i2c_scanner_free(GpioI2CScanner* gpio_i2c_scanner);
13+
14+
View* gpio_i2c_scanner_get_view(GpioI2CScanner* gpio_i2c_scanner);
15+
16+
void gpio_i2c_scanner_set_ok_callback(GpioI2CScanner* gpio_i2c_scanner, GpioI2CScannerOkCallback callback, void* context);
17+
18+
void gpio_i2c_scanner_update_state(GpioI2CScanner* instance, I2CScannerState* st);
19+

0 commit comments

Comments
 (0)