#include #include "platform/nrf52/InterruptHandler.h" #include "platform/nrf52/InterruptGuardian.h" #include "platform/nrf52/gpiote.h" extern "C" { #include "nrf52.h" #include "nrf52_bitfields.h" NRF_GPIOTE_Type *const GPIOTE_REGS = reinterpret_cast(NRF_GPIOTE_BASE); } using namespace pinetime::platform::nrf52; Gpiote::Gpiote() : InterruptHandler(InterruptGuardian::Nrf52IrqN::GPIOTE_IRQ) , num_registered(0) { for(auto it = this->gpiote_channels.begin(); it != this->gpiote_channels.end(); ++it) { *it = nullptr; } } void Gpiote::enable() { NVIC_SetPriority(GPIOTE_IRQn, 7); NVIC_EnableIRQ(GPIOTE_IRQn); } void Gpiote::disable() { NVIC_DisableIRQ(GPIOTE_IRQn); } void Gpiote::register_handler(pinetime::interfaces::GpioInterface *gpio) { if(num_registered == GPIOTE_CHANNELS) { //FIXME: Error notification return; } if(num_registered == 0) { this->enable(); } else { //check if gpio already registered for(auto it = this->gpiote_channels.begin(); it != this->gpiote_channels.end(); ++it) { if(*it == gpio) { return; } } } uint32_t i = 0; for(auto it = this->gpiote_channels.begin(); it != this->gpiote_channels.end(); ++it) { if(*it == nullptr) { *it = gpio; GPIOTE_REGS->INTENSET = GPIOTE_INTENSET_IN0_Msk; GPIOTE_REGS->CONFIG[i] = (GPIOTE_CONFIG_POLARITY_Toggle << GPIOTE_CONFIG_POLARITY_Pos) | ((gpio->pin_number()) << GPIOTE_CONFIG_PSEL_Pos) | (GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos); } i++; } } void Gpiote::handle() { for(uint32_t i = 0; i < GPIOTE_CHANNELS; ++i) { if(GPIOTE_REGS->EVENTS_IN[i] != 0) { GPIOTE_REGS->EVENTS_IN[i] = 0; pinetime::interfaces::GpioInterface *h = this->gpiote_channels[i]; assert(h != nullptr); h->handle(); } } }