]> git.earman.xyz Git - sensor-watch.git/commitdiff
port external interrupts to gossamer framework
authorjoeycastillo <joeycastillo@utexas.edu>
Wed, 18 Sep 2024 19:29:31 +0000 (15:29 -0400)
committerjoeycastillo <joeycastillo@utexas.edu>
Wed, 18 Sep 2024 19:29:31 +0000 (15:29 -0400)
Makefile
app.c
watch-library/hardware/watch/watch_extint.c
watch-library/shared/watch/watch.h
watch-library/shared/watch/watch_extint.h

index db2a0417f4a65c2f7d080804bddf6f61a7cc5b78..54fb26bfb3fa60ea20be6d5672065d20a77621d7 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -29,6 +29,7 @@ INCLUDES += \
 
 # Add your source files here.
 SRCS += \
+  ./watch-library/hardware/watch/watch_extint.c \
   ./watch-library/hardware/watch/watch_gpio.c \
   ./watch-library/hardware/watch/watch_rtc.c \
   ./watch-library/hardware/watch/watch_tcc.c \
diff --git a/app.c b/app.c
index 0ba7a4442ed02dd4b4b8516d35fff9909c9662c9..9daf3fb9cb6979cb90e1ee8752c4b47960d75e65 100644 (file)
--- a/app.c
+++ b/app.c
@@ -4,22 +4,25 @@
 #include "delay.h"
 
 void app_init(void) {
-    _watch_rtc_init();
 }
 
 void app_setup(void) {
     watch_enable_leds();
-    watch_rtc_register_periodic_callback(NULL, 1);
+    watch_enable_external_interrupts();
+    watch_register_interrupt_callback(HAL_GPIO_BTN_LIGHT_pin(), NULL, INTERRUPT_TRIGGER_FALLING);
+    watch_register_interrupt_callback(HAL_GPIO_BTN_MODE_pin(), NULL, INTERRUPT_TRIGGER_FALLING);
+    watch_register_interrupt_callback(HAL_GPIO_BTN_ALARM_pin(), NULL, INTERRUPT_TRIGGER_FALLING);
 }
 
 bool app_loop(void) {
-    watch_date_time date_time = watch_rtc_get_date_time();
+    static bool on = false;
 
-    if (date_time.unit.second % 2 == 0) {
-        watch_set_led_red();
+    if (on) {
+        watch_set_led_off();
     } else {
-        watch_set_led_green();
+        watch_set_led_yellow();
     }
+    on = !on;
 
     return true;
 }
\ No newline at end of file
index 13e8eaa3b7f3198555228f5a3bcc8ad0ecc75a43..9a77d2b56702efaaaaafd299f28ccb9b7c480bec 100644 (file)
  * SOFTWARE.
  */
 
+#include <stdio.h>
 #include "watch_extint.h"
+#include "watch_gpio.h"
+#include "eic.h"
+
+watch_cb_t eic_callbacks[16] = { NULL };
+
+void watch_eic_callback(uint8_t channel);
 
 void watch_enable_external_interrupts(void) {
-    // Configure EIC to use GCLK3 (the 32.768 kHz crystal)
-    hri_gclk_write_PCHCTRL_reg(GCLK, EIC_GCLK_ID, GCLK_PCHCTRL_GEN_GCLK3_Val | (1 << GCLK_PCHCTRL_CHEN_Pos));
-    // Enable AHB clock for the EIC
-    hri_mclk_set_APBAMASK_EIC_bit(MCLK);
-    // call HAL's external interrupt init function
-    ext_irq_init();
+    eic_init();
+    eic_configure_callback(watch_eic_callback);
+    eic_enable();
 }
 
 void watch_disable_external_interrupts(void) {
-    ext_irq_deinit();
-    hri_mclk_clear_APBAMASK_EIC_bit(MCLK);
+    eic_disable();
 }
 
-void watch_register_interrupt_callback(const uint8_t pin, ext_irq_cb_t callback, watch_interrupt_trigger trigger) {
-    uint8_t config_index;
-    uint8_t sense_pos;
-    switch (pin) {
-        case A0:
-            // for EIC channels 8-15, we need to set the SENSE value in CONFIG[1]
-            config_index = (WATCH_A0_EIC_CHANNEL > 7) ? 1 : 0;
-            // either way the index in CONFIG[n] must be 0-7
-            sense_pos = 4 * (WATCH_A0_EIC_CHANNEL % 8);
-            break;
-        case A1:
-            config_index = (WATCH_A1_EIC_CHANNEL > 7) ? 1 : 0;
-            sense_pos = 4 * (WATCH_A1_EIC_CHANNEL % 8);
-            break;
-        case A2:
-            config_index = (WATCH_A2_EIC_CHANNEL > 7) ? 1 : 0;
-            sense_pos = 4 * (WATCH_A2_EIC_CHANNEL % 8);
-            break;
-        case A3:
-            config_index = (WATCH_A3_EIC_CHANNEL > 7) ? 1 : 0;
-            sense_pos = 4 * (WATCH_A3_EIC_CHANNEL % 8);
-            break;
-        case A4:
-            config_index = (WATCH_A4_EIC_CHANNEL > 7) ? 1 : 0;
-            sense_pos = 4 * (WATCH_A4_EIC_CHANNEL % 8);
-            break;
-        case BTN_ALARM:
-            config_index = (WATCH_BTN_ALARM_EIC_CHANNEL > 7) ? 1 : 0;
-            sense_pos = 4 * (WATCH_BTN_ALARM_EIC_CHANNEL % 8);
-            break;
-        case BTN_LIGHT:
-            config_index = (WATCH_BTN_LIGHT_EIC_CHANNEL > 7) ? 1 : 0;
-            sense_pos = 4 * (WATCH_BTN_LIGHT_EIC_CHANNEL % 8);
-            break;
-        case BTN_MODE:
-            config_index = (WATCH_BTN_MODE_EIC_CHANNEL > 7) ? 1 : 0;
-            sense_pos = 4 * (WATCH_BTN_MODE_EIC_CHANNEL % 8);
-            break;
-        default:
-            return;
-    }
+void watch_register_interrupt_callback(const uint8_t pin, watch_cb_t callback, eic_interrupt_trigger trigger) {
+    watch_enable_digital_input(pin);
 
-    gpio_set_pin_direction(pin, GPIO_DIRECTION_IN);
+    // check if this is a button pin
+    if (pin == HAL_GPIO_BTN_LIGHT_pin() || pin == HAL_GPIO_BTN_MODE_pin() || pin == HAL_GPIO_BTN_ALARM_pin()) {
+        // if so, enable the pull-down resistor
+        watch_enable_pull_down(pin);
+    }
 
-    // EIC configuration register is enable-protected, so we have to disable it first...
-    if (hri_eic_get_CTRLA_reg(EIC, EIC_CTRLA_ENABLE)) {
-        hri_eic_clear_CTRLA_ENABLE_bit(EIC);
-        // ...and wait for it to synchronize.
-        hri_eic_wait_for_sync(EIC, EIC_SYNCBUSY_ENABLE);
+    int8_t channel = eic_configure_pin(pin, trigger);
+    if (channel >= 0 && channel < 16) {
+        printf("Configured port %d pin %d on channel %d\n", pin >> 5, pin & 0x1F, channel);
+        eic_enable_interrupt(pin);
+        eic_callbacks[channel] = callback;
     }
-    // now update the configuration...
-    hri_eic_config_reg_t config = EIC->CONFIG[config_index].reg;
-    config &= ~(7 << sense_pos);
-    config |= trigger << (sense_pos);
-    hri_eic_write_CONFIG_reg(EIC, config_index, config);
-    // ...set the pin mode...
-    gpio_set_pin_function(pin, GPIO_PIN_FUNCTION_A);
-    if (pin == BTN_ALARM || pin == BTN_LIGHT || pin == BTN_MODE) gpio_set_pin_pull_mode(pin, GPIO_PULL_DOWN);
-    // ...and re-enable the EIC
-    hri_eic_set_CTRLA_ENABLE_bit(EIC);
+}
 
-    ext_irq_register(pin, callback);
+void watch_eic_callback(uint8_t channel) {
+    if (eic_callbacks[channel] != NULL) {
+        eic_callbacks[channel]();
+    }
 }
index ecff19272bbed1fd9e70cdcf501322b8a898b2a6..59a89efa8047748758e5eba6f0742c416b5e5b8e 100644 (file)
@@ -63,7 +63,7 @@ typedef void (*watch_cb_t)(void);
 
 #include "watch_rtc.h"
 // #include "watch_slcd.h"
-// #include "watch_extint.h"
+#include "watch_extint.h"
 #include "watch_tcc.h"
 // #include "watch_adc.h"
 #include "watch_gpio.h"
index 84194e9a68270e7290d4fc45bb0e8d4cf215621d..df8ffaae1b9468ceafd92874a9bbb3b829d73ec8 100644 (file)
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  * SOFTWARE.
  */
-#ifndef _WATCH_EXTINT_H_INCLUDED
-#define _WATCH_EXTINT_H_INCLUDED
+
+#pragma once
+
 ////< @file watch_extint.h
 
 #include "watch.h"
-#include "hal_ext_irq.h"
+#include "eic.h"
 
 /** @addtogroup buttons Buttons & External Interrupts
   * @brief This section covers functions related to the three buttons: Light, Mode and Alarm, as well as
   */
 /// @{
 
-///@brief An enum defining the types of interrupt trigger you wish to scan for.
-typedef enum watch_interrupt_trigger {
-    INTERRUPT_TRIGGER_NONE = 0,
-    INTERRUPT_TRIGGER_RISING,
-    INTERRUPT_TRIGGER_FALLING,
-    INTERRUPT_TRIGGER_BOTH,
-} watch_interrupt_trigger;
-
 /// @brief Enables the external interrupt controller.
 void watch_enable_external_interrupts(void);
 
@@ -62,7 +55,7 @@ void watch_disable_external_interrupts(void);
   *          want to detect both rising and falling conditions (i.e. button down and button up), use
   *          INTERRUPT_TRIGGER_BOTH and use watch_get_pin_level to check the pin level in your callback
   *          to determine which condition caused the interrupt.
-  * @param pin One of BTN_LIGHT, BTN_MODE, BTN_ALARM, A0, A1, A3 or A4. If the pin parameter matches one of
+  * @param pin One of BTN_LIGHT, BTN_MODE, BTN_ALARM, A0, A1, A2, A3 or A4. If the pin parameter matches one of
   *            the three button pins, this function will also enable an internal pull-down resistor. If
   *            the pin parameter is A0-A4, you are responsible for setting any required pull configuration
   *            using watch_enable_pull_up or watch_enable_pull_down.
@@ -70,11 +63,8 @@ void watch_disable_external_interrupts(void);
   * @param trigger The condition on which you wish to trigger: rising, falling or both.
   * @note Pins A2 and A4 can also generate interrupts via the watch_register_extwake_callback function, which
   *       will allow them to trigger even when the watch is in deep sleep mode.
-  * @warning As of now, A2 is not usable via the watch_register_interrupt_callback function. To enable an
-  *          external interrupt on pin A2, use the watch_register_extwake_callback function. This issue will be
-  *          addressed in a future revision of the watch library.
+  * @warning Pin A2 shares an interrupt channel with the Alarm button; use caution when configuring both.
   */
-void watch_register_interrupt_callback(const uint8_t pin, ext_irq_cb_t callback, watch_interrupt_trigger trigger);
+void watch_register_interrupt_callback(const uint8_t pin, watch_cb_t callback, eic_interrupt_trigger trigger);
 
 /// @}
-#endif