i2csniffer.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. #include "i2csniffer.h"
  2. void clear_sniffer_buffers(i2cSniffer* i2c_sniffer) {
  3. furi_assert(i2c_sniffer);
  4. for(uint8_t i = 0; i < MAX_RECORDS; i++) {
  5. for(uint8_t j = 0; j < MAX_MESSAGE_SIZE; j++) {
  6. i2c_sniffer->frames[i].ack[j] = false;
  7. i2c_sniffer->frames[i].data[j] = 0;
  8. }
  9. i2c_sniffer->frames[i].bit_index = 0;
  10. i2c_sniffer->frames[i].data_index = 0;
  11. }
  12. i2c_sniffer->frame_index = 0;
  13. i2c_sniffer->state = I2C_BUS_FREE;
  14. i2c_sniffer->first = true;
  15. }
  16. void start_interrupts(i2cSniffer* i2c_sniffer) {
  17. furi_assert(i2c_sniffer);
  18. furi_hal_gpio_init(pinSCL, GpioModeInterruptRise, GpioPullNo, GpioSpeedHigh);
  19. furi_hal_gpio_add_int_callback(pinSCL, SCLcallback, i2c_sniffer);
  20. // Add Rise and Fall Interrupt on SDA pin
  21. furi_hal_gpio_init(pinSDA, GpioModeInterruptRiseFall, GpioPullNo, GpioSpeedHigh);
  22. furi_hal_gpio_add_int_callback(pinSDA, SDAcallback, i2c_sniffer);
  23. }
  24. void stop_interrupts() {
  25. furi_hal_gpio_remove_int_callback(pinSCL);
  26. furi_hal_gpio_remove_int_callback(pinSDA);
  27. // Reset GPIO pins to default state
  28. furi_hal_gpio_init(pinSCL, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
  29. furi_hal_gpio_init(pinSDA, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
  30. }
  31. // Called on Fallin/Rising SDA
  32. // Used to monitor i2c bus state
  33. void SDAcallback(void* _i2c_sniffer) {
  34. i2cSniffer* i2c_sniffer = _i2c_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(i2c_sniffer->state == I2C_BUS_STARTED) {
  41. if(furi_hal_gpio_read(pinSDA) == true) {
  42. i2c_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. i2c_sniffer->state = I2C_BUS_STARTED;
  48. if(i2c_sniffer->first) {
  49. i2c_sniffer->first = false;
  50. return;
  51. }
  52. i2c_sniffer->frame_index++;
  53. if(i2c_sniffer->frame_index >= MAX_RECORDS) {
  54. clear_sniffer_buffers(i2c_sniffer);
  55. }
  56. }
  57. return;
  58. }
  59. // Called on Rising SCL
  60. // Used to read bus datas
  61. void SCLcallback(void* _i2c_sniffer) {
  62. i2cSniffer* i2c_sniffer = _i2c_sniffer;
  63. if(i2c_sniffer->state == I2C_BUS_FREE) {
  64. return;
  65. }
  66. uint8_t frame = i2c_sniffer->frame_index;
  67. uint8_t bit = i2c_sniffer->frames[frame].bit_index;
  68. uint8_t data_idx = i2c_sniffer->frames[frame].data_index;
  69. if(bit < 8) {
  70. i2c_sniffer->frames[frame].data[data_idx] <<= 1;
  71. i2c_sniffer->frames[frame].data[data_idx] |= (int)furi_hal_gpio_read(pinSDA);
  72. i2c_sniffer->frames[frame].bit_index++;
  73. } else {
  74. i2c_sniffer->frames[frame].ack[data_idx] = !furi_hal_gpio_read(pinSDA);
  75. i2c_sniffer->frames[frame].data_index++;
  76. i2c_sniffer->frames[frame].bit_index = 0;
  77. }
  78. }
  79. i2cSniffer* i2c_sniffer_alloc() {
  80. i2cSniffer* i2c_sniffer = malloc(sizeof(i2cSniffer));
  81. i2c_sniffer->started = false;
  82. i2c_sniffer->row_index = 0;
  83. i2c_sniffer->menu_index = 0;
  84. clear_sniffer_buffers(i2c_sniffer);
  85. return i2c_sniffer;
  86. }
  87. void i2c_sniffer_free(i2cSniffer* i2c_sniffer) {
  88. furi_assert(i2c_sniffer);
  89. if(i2c_sniffer->started) {
  90. stop_interrupts();
  91. }
  92. free(i2c_sniffer);
  93. }