Skip to content

Commit 2870da3

Browse files
committed
One tool, one file
1 parent ce5510d commit 2870da3

File tree

4 files changed

+205
-175
lines changed

4 files changed

+205
-175
lines changed

i2csniffer.c

+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
#include "i2csniffer.h"
2+
3+
void clearSnifferBuffers(i2csniffer* sniffer) {
4+
for(uint8_t i = 0; i < MAX_RECORDS; i++) {
5+
for(uint8_t j = 0; j < MAX_MESSAGE_SIZE; j++) {
6+
sniffer->frames[i].ack[j] = false;
7+
sniffer->frames[i].data[j] = 0;
8+
}
9+
sniffer->frames[i].bit_index = 0;
10+
sniffer->frames[i].data_index = 0;
11+
}
12+
sniffer->frame_index = 0;
13+
sniffer->state = I2C_BUS_FREE;
14+
sniffer->first = true;
15+
}
16+
17+
void start_interrupts(i2csniffer* sniffer) {
18+
furi_hal_gpio_init(pinSCL, GpioModeInterruptRise, GpioPullNo, GpioSpeedHigh);
19+
furi_hal_gpio_add_int_callback(pinSCL, SCLcallback, sniffer);
20+
21+
// Add Rise and Fall Interrupt on SDA pin
22+
furi_hal_gpio_init(pinSDA, GpioModeInterruptRiseFall, GpioPullNo, GpioSpeedHigh);
23+
furi_hal_gpio_add_int_callback(pinSDA, SDAcallback, sniffer);
24+
}
25+
26+
void stop_interrupts() {
27+
furi_hal_gpio_remove_int_callback(pinSCL);
28+
furi_hal_gpio_remove_int_callback(pinSDA);
29+
}
30+
31+
// Called on Fallin/Rising SDA
32+
// Used to monitor i2c bus state
33+
void SDAcallback(void* _sniffer) {
34+
i2csniffer* sniffer = _sniffer;
35+
// SCL is low maybe cclock strecching
36+
if(furi_hal_gpio_read(pinSCL) == false) {
37+
return;
38+
}
39+
// Check for stop condition: SDA rising while SCL is High
40+
if(sniffer->state == I2C_BUS_STARTED) {
41+
if(furi_hal_gpio_read(pinSDA) == true) {
42+
sniffer->state = I2C_BUS_FREE;
43+
}
44+
}
45+
// Check for start condition: SDA falling while SCL is high
46+
else if(furi_hal_gpio_read(pinSDA) == false) {
47+
sniffer->state = I2C_BUS_STARTED;
48+
if(sniffer->first) {
49+
sniffer->first = false;
50+
return;
51+
}
52+
sniffer->frame_index++;
53+
if(sniffer->frame_index >= MAX_RECORDS) {
54+
clearSnifferBuffers(sniffer);
55+
}
56+
}
57+
return;
58+
}
59+
60+
// Called on Rising SCL
61+
// Used to read bus datas
62+
void SCLcallback(void* _sniffer) {
63+
i2csniffer* sniffer = _sniffer;
64+
if(sniffer->state == I2C_BUS_FREE) {
65+
return;
66+
}
67+
uint8_t frame = sniffer->frame_index;
68+
uint8_t bit = sniffer->frames[frame].bit_index;
69+
uint8_t data_idx = sniffer->frames[frame].data_index;
70+
if(bit < 8) {
71+
sniffer->frames[frame].data[data_idx] <<= 1;
72+
sniffer->frames[frame].data[data_idx] |= (int)furi_hal_gpio_read(pinSDA);
73+
sniffer->frames[frame].bit_index++;
74+
} else {
75+
sniffer->frames[frame].ack[data_idx] = !furi_hal_gpio_read(pinSDA);
76+
sniffer->frames[frame].data_index++;
77+
sniffer->frames[frame].bit_index = 0;
78+
}
79+
}

i2csniffer.h

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#pragma once
2+
3+
#include <furi.h>
4+
#include <furi_hal.h>
5+
6+
// I2C Pins
7+
#define pinSCL &gpio_ext_pc0
8+
#define pinSDA &gpio_ext_pc1
9+
10+
// Bus States
11+
typedef enum { I2C_BUS_FREE, I2C_BUS_STARTED } i2cBusStates;
12+
13+
// Max read size of i2c frame by message
14+
// Arbitraly defined
15+
// They're not real limit to maximum frames send
16+
#define MAX_MESSAGE_SIZE 128
17+
18+
// Nb of records
19+
#define MAX_RECORDS 32
20+
21+
/// @brief Struct used to store our reads
22+
typedef struct {
23+
uint8_t data[MAX_MESSAGE_SIZE];
24+
bool ack[MAX_MESSAGE_SIZE];
25+
uint8_t bit_index;
26+
uint8_t data_index;
27+
} i2cFrame;
28+
29+
typedef struct {
30+
bool started;
31+
bool first;
32+
i2cBusStates state;
33+
i2cFrame frames[MAX_RECORDS];
34+
uint8_t frame_index;
35+
uint8_t menu_index;
36+
} i2csniffer;
37+
38+
void clearSnifferBuffers(i2csniffer* sniffer);
39+
void start_interrupts(i2csniffer* sniffer);
40+
void stop_interrupts();
41+
void SDAcallback(void* _sniffer);
42+
void SCLcallback(void* _sniffer);

0 commit comments

Comments
 (0)