port external interrupts to gossamer framework
This commit is contained in:
parent
f5435d468d
commit
ac88e2de8c
1
Makefile
1
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 \
|
||||
|
||||
15
app.c
15
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;
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -21,12 +21,13 @@
|
||||
* 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
|
||||
@ -40,14 +41,6 @@
|
||||
*/
|
||||
/// @{
|
||||
|
||||
///@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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user