narf52/src/platform/nrf52/gpiote.cc
2020-04-26 08:34:37 +02:00

78 lines
2.0 KiB
C++

#include <cassert>
#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_Type *>(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();
}
}
}