|
| 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 | +} |
0 commit comments