i2csniffer.c 2.5 KB

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