port external interrupts to gossamer framework

This commit is contained in:
joeycastillo
2024-09-18 15:29:31 -04:00
parent f5435d468d
commit ac88e2de8c
5 changed files with 47 additions and 91 deletions

View File

@@ -22,82 +22,44 @@
* 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);
// 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);
}
gpio_set_pin_direction(pin, GPIO_DIRECTION_IN);
// 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;
}
}
void watch_eic_callback(uint8_t channel) {
if (eic_callbacks[channel] != NULL) {
eic_callbacks[channel]();
}
// 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);
}