i2csniffer.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  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. }
  28. // Called on Fallin/Rising SDA
  29. // Used to monitor i2c bus state
  30. void SDAcallback(void* _i2c_sniffer) {
  31. i2cSniffer* i2c_sniffer = _i2c_sniffer;
  32. // SCL is low maybe cclock strecching
  33. if(furi_hal_gpio_read(pinSCL) == false) {
  34. return;
  35. }
  36. // Check for stop condition: SDA rising while SCL is High
  37. if(i2c_sniffer->state == I2C_BUS_STARTED) {
  38. if(furi_hal_gpio_read(pinSDA) == true) {
  39. i2c_sniffer->state = I2C_BUS_FREE;
  40. }
  41. }
  42. // Check for start condition: SDA falling while SCL is high
  43. else if(furi_hal_gpio_read(pinSDA) == false) {
  44. i2c_sniffer->state = I2C_BUS_STARTED;
  45. if(i2c_sniffer->first) {
  46. i2c_sniffer->first = false;
  47. return;
  48. }
  49. i2c_sniffer->frame_index++;
  50. if(i2c_sniffer->frame_index >= MAX_RECORDS) {
  51. clear_sniffer_buffers(i2c_sniffer);
  52. }
  53. }
  54. return;
  55. }
  56. // Called on Rising SCL
  57. // Used to read bus datas
  58. void SCLcallback(void* _i2c_sniffer) {
  59. i2cSniffer* i2c_sniffer = _i2c_sniffer;
  60. if(i2c_sniffer->state == I2C_BUS_FREE) {
  61. return;
  62. }
  63. uint8_t frame = i2c_sniffer->frame_index;
  64. uint8_t bit = i2c_sniffer->frames[frame].bit_index;
  65. uint8_t data_idx = i2c_sniffer->frames[frame].data_index;
  66. if(bit < 8) {
  67. i2c_sniffer->frames[frame].data[data_idx] <<= 1;
  68. i2c_sniffer->frames[frame].data[data_idx] |= (int)furi_hal_gpio_read(pinSDA);
  69. i2c_sniffer->frames[frame].bit_index++;
  70. } else {
  71. i2c_sniffer->frames[frame].ack[data_idx] = !furi_hal_gpio_read(pinSDA);
  72. i2c_sniffer->frames[frame].data_index++;
  73. i2c_sniffer->frames[frame].bit_index = 0;
  74. }
  75. }
  76. i2cSniffer* i2c_sniffer_alloc() {
  77. i2cSniffer* i2c_sniffer = malloc(sizeof(i2cSniffer));
  78. i2c_sniffer->started = false;
  79. clear_sniffer_buffers(i2c_sniffer);
  80. return i2c_sniffer;
  81. }
  82. void i2c_sniffer_free(i2cSniffer* i2c_sniffer) {
  83. furi_assert(i2c_sniffer);
  84. if(i2c_sniffer->started) {
  85. stop_interrupts();
  86. }
  87. free(i2c_sniffer);
  88. }