io.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. /*******************************************************************************
  2. * IO Driver for IdeasX
  3. * Author: curiousmuch
  4. * Description: HAL layer for IdeasX v0.3.X encoders
  5. * This lib has a couple functions
  6. * 1) Provide SW interface for encoder hardware for the following functions:
  7. * reset, shutdown, enable / disable assistive switches
  8. * 2) Provide the ability to attach custom ISR to assistive switch inputs
  9. and INTR pin on LSM6DS3.
  10. * Todo:
  11. *******************************************************************************/
  12. #include "hal/io.h"
  13. // debounce timers
  14. static Encoder_Timer_t encoder_timer;
  15. void ICACHE_FLASH_ATTR Encoder_InitIO(uint32_t debounce_delay, switch_function_t
  16. switch_a_cb, switch_function_t switch_b_cb, switch_function_t imu_cb)
  17. {
  18. ETS_GPIO_INTR_DISABLE();
  19. gpio_init();
  20. // setup as GPIO pins
  21. PIN_FUNC_SELECT(LDO_SHUTDOWN_MUX, LDO_SHUTDOWN_FUNC);
  22. PIN_FUNC_SELECT(SWITCH_A_MUX, SWITCH_A_FUNC);
  23. PIN_FUNC_SELECT(SWITCH_B_MUX, SWITCH_B_FUNC);
  24. PIN_FUNC_SELECT(STATUS_LED_MUX, STATUS_LED_FUNC);
  25. // setup GPIO states
  26. gpio_output_set(BIT(LDO_SHUTDOWN), BIT(STATUS_LED), (BIT(LDO_SHUTDOWN)|BIT(STATUS_LED)), (BIT(SWITCH_A)|BIT(SWITCH_B)));
  27. // attach interrupts to switchs
  28. gpio_pin_intr_state_set(GPIO_ID_PIN(SWTICH_A), GPIO_PIN_INTR_ANYEDGE);
  29. gpio_pin_intr_state_set(GPIO_ID_PIN(SWITCH_B), GPIO_PIN_INTR_ANYEDGE);
  30. os_timer_disarm(&encoder_timer.switch_a);
  31. os_timer_disarm(&encoder_timer.switch_b);
  32. os_timer_setfn(&timerA, (os_timer_func_t *)switchA_debounce, NULL);
  33. os_timer_setfn(&timerB, (os_timer_func_t *)switchB_debounce, NULL);
  34. ETS_GPIO_INTR_ENABLE();
  35. return;
  36. }
  37. void ICACHE_FLASH_ATTR Encoder_EnableAdaptiveSwitches(void)
  38. {
  39. gpio_pin_intr_state_set(GPIO_ID_PIN(SWTICH_A), GPIO_PIN_INTR_ANYEDGE);
  40. gpio_pin_intr_state_set(GPIO_ID_PIN(SWITCH_B), GPIO_PIN_INTR_ANYEDGE);
  41. }
  42. void ICACHE_FLASH_ATTR Encoder_DisableAdaptiveSwitches(void)
  43. {
  44. gpio_pin_intr_state_set(GPIO_ID_PIN(SWTICH_A), GPIO_PIN_INTR_DISABLE);
  45. gpio_pin_intr_state_set(GPIO_ID_PIN(SWITCH_B), GPIO_PIN_INTR_DISABLE);
  46. }
  47. void ICACHE_FLASH_ATTR Encoder_ShutDown(void)
  48. {
  49. GPIO_OUTPUT_SET(LDO_SHUTDOWN, 0);
  50. }
  51. void ICACHE_FLASH_ATTR Encoder_Restart(void)
  52. {
  53. return;
  54. }
  55. void ICACHE_FLASH_ATTR Encoder_GPIO_Handler(void)
  56. {
  57. uint8_t i;
  58. uint32_t gpio_status = GPIO_REG_READ(GPIO_STATUS_ADDRESS); // read interupt status of pins
  59. uint32_t gpio_states = GPIO_REG_READ(GPIO_IN_ADDRESS); // read pin status
  60. ETS_GPIO_INTR_DISABLE(); // disable GPIO interrupts
  61. for (i=0;i<GPIO_PIN_COUNT;i++)
  62. {
  63. if (BIT(i) & gpio_status)
  64. {
  65. gpio_pin_intr_state_set(GPIO_ID_PIN(i), GPIO_PIN_INTR_DISABLE); // disable interrupt for pin
  66. GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, gpio_status & BIT(i)); // clear interrupt status
  67. #if MODULE_IO_DEBUG
  68. os_printf("GPIO: Pin %d Interrupt\r\n", i);
  69. #endif
  70. switch(i)
  71. {
  72. case PBA: {
  73. //os_printf("I'm here!\r\n");
  74. if (sysCfg.module_state.connected == true) // if module is connected to Wi-Fi
  75. {
  76. uint8_t fifoFlags;
  77. fifoFlags = lsm6ds3_fifo_getFlags();
  78. os_printf("LSM6DS3: FIFO Flags %x\r\n", fifoFlags);
  79. if (fifoFlags & (LSM6DS3_FIFO_OVER_RUN | LSM6DS3_FIFO_FULL ) )
  80. {
  81. os_printf("LSM6DS3: FIFO Full / Overrun\r\n");
  82. lsm6ds3_reset();
  83. os_printf("LSM6DS3: Reset IMU\r\n");
  84. gpio_pin_intr_state_set(GPIO_ID_PIN(i), GPIO_PIN_INTR_ANYEDGE); // re-enable pin interrupt
  85. // shutdown LSM6DS3
  86. // set error flag in health message
  87. }
  88. else if (fifoFlags & LSM6DS3_FIFO_THRESHOLD)
  89. {
  90. os_printf("LSM6DS3: FIFO Threshold\r\n");
  91. publish_fifo_dump();
  92. gpio_pin_intr_state_set(GPIO_ID_PIN(i), GPIO_PIN_INTR_ANYEDGE); // re-enable pin interrupt
  93. }
  94. else if (fifoFlags & LSM6DS3_FIFO_EMPTY)
  95. {
  96. os_printf("LSM6DS3: FIFO Empty\r\n");
  97. gpio_pin_intr_state_set(GPIO_ID_PIN(i), GPIO_PIN_INTR_ANYEDGE); // re-enable pin interrupt
  98. }
  99. else
  100. {
  101. os_timer_arm(&pba_timer, DEBOUNCEDELAY, 0); // arm SW timer
  102. }
  103. }
  104. else if (sysCfg.module_state.connected == false && sysCfg.module_state.asleep == true)
  105. {
  106. sysCfg.module_state.asleep = false; // indicate module is now awake
  107. /*
  108. * MODULE NEEDS TO WAKE FROM SLEEP HERE IF PLACED TO SLEEP BY WI-FI PROCESS
  109. */
  110. lsm6ds3_read_motion(); // clear LSM6DS3 interrupt
  111. start_wifi_process(); // start Wi-Fi process
  112. gpio_pin_intr_state_set(GPIO_ID_PIN(i), GPIO_PIN_INTR_ANYEDGE); // re-enable pin interrupt
  113. }
  114. else
  115. {
  116. //os_printf("WHY ARE WE HERE!!!!\r\n");
  117. lsm6ds3_read_motion();
  118. gpio_pin_intr_state_set(GPIO_ID_PIN(i), GPIO_PIN_INTR_ANYEDGE); // re-enable pin interrupt
  119. }
  120. break;
  121. }
  122. case PBB: {
  123. if (sysCfg.module_state.connected == true) // if module is connected to Wi-Fi
  124. {
  125. os_timer_arm(&pbb_timer, DEBOUNCEDELAY, 0); // arm SW timer
  126. }
  127. else if (sysCfg.module_state.searching == false && sysCfg.module_state.connected == false && sysCfg.module_state.asleep == true)
  128. {
  129. sysCfg.module_state.asleep = false; // indicate module is now awake
  130. /*
  131. * MODULE NEEDS TO WAKE FROM SLEEP HERE IF PLACED TO SLEEP BY WI-FI PROCESS
  132. */
  133. start_wifi_process(); // start Wi-Fi process
  134. gpio_pin_intr_state_set(GPIO_ID_PIN(i), GPIO_PIN_INTR_ANYEDGE); // re-enable pin interrupt
  135. }
  136. break;
  137. }
  138. default: {
  139. #if MODULE_IO_DEBUG
  140. os_printf("Help! Unknown Interrupt: %d\r\n", gpio_status);
  141. #endif
  142. }
  143. }
  144. }
  145. }
  146. /*
  147. NOTE: This is slightly a hack. When the start_wifi_process function is called, it will disable I/O interrupts to insure
  148. it is not called multiple times and schedule a Wi-Fi scan. The functions returns before the scan is started the following
  149. line is called and therefore the LSM6DS3 is free to trigger the ISR multiple times on any motion. This line prevents this.
  150. This could also be stopped by setting the INTS to INT2 when the first INT is called.
  151. */
  152. if (sysCfg.module_state.searching == false)
  153. {
  154. ETS_GPIO_INTR_ENABLE();
  155. os_printf("MODULE IO: I re-enabled interrupts..bitch.\r\n");
  156. }
  157. }
  158. static void ICACHE_FLASH_ATTR switchA_debounce(void)
  159. {
  160. ETS_GPIO_INTR_DISABLE();
  161. uint32_t gpio_states = GPIO_REG_READ(GPIO_IN_ADDRESS);
  162. //publish_button_state(gpio_states);
  163. gpio_pin_intr_state_set(GPIO_ID_PIN(SWITCH_A), GPIO_PIN_INTR_ANYEDGE);
  164. os_timer_disarm(&timerA);
  165. ETS_GPIO_INTR_ENABLE();
  166. }
  167. static void ICACHE_FLASH_ATTR switchB_debounce(void)
  168. {
  169. ETS_GPIO_INTR_DISABLE();
  170. uint32_t gpio_states = GPIO_REG_READ(GPIO_IN_ADDRESS);
  171. //publish_button_state(gpio_states);
  172. gpio_pin_intr_state_set(GPIO_ID_PIN(SWITCH_B), GPIO_PIN_INTR_ANYEDGE);
  173. os_timer_disarm(&timerB);
  174. ETS_GPIO_INTR_ENABLE();
  175. }