123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211 |
- /*******************************************************************************
- * IO Driver for IdeasX
- * Author: curiousmuch
- * Description: HAL layer for IdeasX v0.3.X encoders
- * This lib has a couple functions
- * 1) Provide SW interface for encoder hardware for the following functions:
- * reset, shutdown, enable / disable assistive switches
- * 2) Provide the ability to attach custom ISR to assistive switch inputs
- and INTR pin on LSM6DS3.
- * Todo:
- *******************************************************************************/
- #include "hal/io.h"
- // debounce timers
- static Encoder_Timer_t encoder_timer;
- void ICACHE_FLASH_ATTR Encoder_InitIO(uint32_t debounce_delay, switch_function_t
- switch_a_cb, switch_function_t switch_b_cb, switch_function_t imu_cb)
- {
- ETS_GPIO_INTR_DISABLE();
- gpio_init();
- // setup as GPIO pins
- PIN_FUNC_SELECT(LDO_SHUTDOWN_MUX, LDO_SHUTDOWN_FUNC);
- PIN_FUNC_SELECT(SWITCH_A_MUX, SWITCH_A_FUNC);
- PIN_FUNC_SELECT(SWITCH_B_MUX, SWITCH_B_FUNC);
- PIN_FUNC_SELECT(STATUS_LED_MUX, STATUS_LED_FUNC);
- // setup GPIO states
- gpio_output_set(BIT(LDO_SHUTDOWN), BIT(STATUS_LED), (BIT(LDO_SHUTDOWN)|BIT(STATUS_LED)), (BIT(SWITCH_A)|BIT(SWITCH_B)));
- // attach interrupts to switchs
- gpio_pin_intr_state_set(GPIO_ID_PIN(SWTICH_A), GPIO_PIN_INTR_ANYEDGE);
- gpio_pin_intr_state_set(GPIO_ID_PIN(SWITCH_B), GPIO_PIN_INTR_ANYEDGE);
- os_timer_disarm(&encoder_timer.switch_a);
- os_timer_disarm(&encoder_timer.switch_b);
- os_timer_setfn(&timerA, (os_timer_func_t *)switchA_debounce, NULL);
- os_timer_setfn(&timerB, (os_timer_func_t *)switchB_debounce, NULL);
- ETS_GPIO_INTR_ENABLE();
- return;
- }
- void ICACHE_FLASH_ATTR Encoder_EnableAdaptiveSwitches(void)
- {
- gpio_pin_intr_state_set(GPIO_ID_PIN(SWTICH_A), GPIO_PIN_INTR_ANYEDGE);
- gpio_pin_intr_state_set(GPIO_ID_PIN(SWITCH_B), GPIO_PIN_INTR_ANYEDGE);
- }
- void ICACHE_FLASH_ATTR Encoder_DisableAdaptiveSwitches(void)
- {
- gpio_pin_intr_state_set(GPIO_ID_PIN(SWTICH_A), GPIO_PIN_INTR_DISABLE);
- gpio_pin_intr_state_set(GPIO_ID_PIN(SWITCH_B), GPIO_PIN_INTR_DISABLE);
- }
- void ICACHE_FLASH_ATTR Encoder_ShutDown(void)
- {
- GPIO_OUTPUT_SET(LDO_SHUTDOWN, 0);
- }
- void ICACHE_FLASH_ATTR Encoder_Restart(void)
- {
- return;
- }
- void ICACHE_FLASH_ATTR Encoder_GPIO_Handler(void)
- {
- uint8_t i;
- uint32_t gpio_status = GPIO_REG_READ(GPIO_STATUS_ADDRESS); // read interupt status of pins
- uint32_t gpio_states = GPIO_REG_READ(GPIO_IN_ADDRESS); // read pin status
- ETS_GPIO_INTR_DISABLE(); // disable GPIO interrupts
- for (i=0;i<GPIO_PIN_COUNT;i++)
- {
- if (BIT(i) & gpio_status)
- {
- gpio_pin_intr_state_set(GPIO_ID_PIN(i), GPIO_PIN_INTR_DISABLE); // disable interrupt for pin
- GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, gpio_status & BIT(i)); // clear interrupt status
- #if MODULE_IO_DEBUG
- os_printf("GPIO: Pin %d Interrupt\r\n", i);
- #endif
- switch(i)
- {
- case PBA: {
- //os_printf("I'm here!\r\n");
- if (sysCfg.module_state.connected == true) // if module is connected to Wi-Fi
- {
- uint8_t fifoFlags;
- fifoFlags = lsm6ds3_fifo_getFlags();
- os_printf("LSM6DS3: FIFO Flags %x\r\n", fifoFlags);
- if (fifoFlags & (LSM6DS3_FIFO_OVER_RUN | LSM6DS3_FIFO_FULL ) )
- {
- os_printf("LSM6DS3: FIFO Full / Overrun\r\n");
- lsm6ds3_reset();
- os_printf("LSM6DS3: Reset IMU\r\n");
- gpio_pin_intr_state_set(GPIO_ID_PIN(i), GPIO_PIN_INTR_ANYEDGE); // re-enable pin interrupt
- // shutdown LSM6DS3
- // set error flag in health message
- }
- else if (fifoFlags & LSM6DS3_FIFO_THRESHOLD)
- {
- os_printf("LSM6DS3: FIFO Threshold\r\n");
- publish_fifo_dump();
- gpio_pin_intr_state_set(GPIO_ID_PIN(i), GPIO_PIN_INTR_ANYEDGE); // re-enable pin interrupt
- }
- else if (fifoFlags & LSM6DS3_FIFO_EMPTY)
- {
- os_printf("LSM6DS3: FIFO Empty\r\n");
- gpio_pin_intr_state_set(GPIO_ID_PIN(i), GPIO_PIN_INTR_ANYEDGE); // re-enable pin interrupt
- }
- else
- {
- os_timer_arm(&pba_timer, DEBOUNCEDELAY, 0); // arm SW timer
- }
- }
- else if (sysCfg.module_state.connected == false && sysCfg.module_state.asleep == true)
- {
- sysCfg.module_state.asleep = false; // indicate module is now awake
- /*
- * MODULE NEEDS TO WAKE FROM SLEEP HERE IF PLACED TO SLEEP BY WI-FI PROCESS
- */
- lsm6ds3_read_motion(); // clear LSM6DS3 interrupt
- start_wifi_process(); // start Wi-Fi process
- gpio_pin_intr_state_set(GPIO_ID_PIN(i), GPIO_PIN_INTR_ANYEDGE); // re-enable pin interrupt
- }
- else
- {
- //os_printf("WHY ARE WE HERE!!!!\r\n");
- lsm6ds3_read_motion();
- gpio_pin_intr_state_set(GPIO_ID_PIN(i), GPIO_PIN_INTR_ANYEDGE); // re-enable pin interrupt
- }
- break;
- }
- case PBB: {
- if (sysCfg.module_state.connected == true) // if module is connected to Wi-Fi
- {
- os_timer_arm(&pbb_timer, DEBOUNCEDELAY, 0); // arm SW timer
- }
- else if (sysCfg.module_state.searching == false && sysCfg.module_state.connected == false && sysCfg.module_state.asleep == true)
- {
- sysCfg.module_state.asleep = false; // indicate module is now awake
- /*
- * MODULE NEEDS TO WAKE FROM SLEEP HERE IF PLACED TO SLEEP BY WI-FI PROCESS
- */
- start_wifi_process(); // start Wi-Fi process
- gpio_pin_intr_state_set(GPIO_ID_PIN(i), GPIO_PIN_INTR_ANYEDGE); // re-enable pin interrupt
- }
- break;
- }
- default: {
- #if MODULE_IO_DEBUG
- os_printf("Help! Unknown Interrupt: %d\r\n", gpio_status);
- #endif
- }
- }
- }
- }
- /*
- NOTE: This is slightly a hack. When the start_wifi_process function is called, it will disable I/O interrupts to insure
- it is not called multiple times and schedule a Wi-Fi scan. The functions returns before the scan is started the following
- line is called and therefore the LSM6DS3 is free to trigger the ISR multiple times on any motion. This line prevents this.
- This could also be stopped by setting the INTS to INT2 when the first INT is called.
- */
- if (sysCfg.module_state.searching == false)
- {
- ETS_GPIO_INTR_ENABLE();
- os_printf("MODULE IO: I re-enabled interrupts..bitch.\r\n");
- }
- }
- static void ICACHE_FLASH_ATTR switchA_debounce(void)
- {
- ETS_GPIO_INTR_DISABLE();
- uint32_t gpio_states = GPIO_REG_READ(GPIO_IN_ADDRESS);
- //publish_button_state(gpio_states);
- gpio_pin_intr_state_set(GPIO_ID_PIN(SWITCH_A), GPIO_PIN_INTR_ANYEDGE);
- os_timer_disarm(&timerA);
- ETS_GPIO_INTR_ENABLE();
- }
- static void ICACHE_FLASH_ATTR switchB_debounce(void)
- {
- ETS_GPIO_INTR_DISABLE();
- uint32_t gpio_states = GPIO_REG_READ(GPIO_IN_ADDRESS);
- //publish_button_state(gpio_states);
- gpio_pin_intr_state_set(GPIO_ID_PIN(SWITCH_B), GPIO_PIN_INTR_ANYEDGE);
- os_timer_disarm(&timerB);
- ETS_GPIO_INTR_ENABLE();
- }
|