diff --git a/interfaces/gpio_interface.h b/interfaces/gpio_interface.h index e3df6cd..36a3e31 100644 --- a/interfaces/gpio_interface.h +++ b/interfaces/gpio_interface.h @@ -10,11 +10,14 @@ class GpioInterface public: enum class direction {IN, OUT}; - virtual void set_direction(direction) = 0; + virtual void set_direction(direction, bool) = 0; virtual uint32_t get() = 0; virtual void set() = 0; virtual void clear() = 0; virtual void toggle() = 0; + + virtual void handle() = 0; + virtual uint32_t pin_number() = 0; }; } diff --git a/src/application/blinky/main.cc b/src/application/blinky/main.cc index 0a8ad6f..b7b3a6a 100644 --- a/src/application/blinky/main.cc +++ b/src/application/blinky/main.cc @@ -7,6 +7,7 @@ #include "platform/cm4/SystemTick.h" #include "platform/nrf52/gpio.h" +#include "platform/nrf52/gpiote.h" #include "platform/nrf52/InterruptHandler.h" #include "platform/nrf52/InterruptGuardian.h" @@ -15,6 +16,18 @@ using namespace pinetime::platform; using namespace pinetime::virtual_timer; +// IRQs +nrf52::InterruptGuardian nrf52::InterruptGuardian::instance; +cm4::InterruptGuardian cm4::InterruptGuardian::instance; + +// GPIO events +nrf52::Gpiote gpiote; + +// Timer +cm4::SystemTick system_tick; +VirtualTimerDistributor virtual_timer_distributor(system_tick.instance()); +pinetime::Delay delay; + enum { PIN_NUMBER_LED_1 = 17, PIN_NUMBER_LED_2 = 18, @@ -29,15 +42,6 @@ nrf52::Gpio led_3(PIN_NUMBER_LED_3); nrf52::Gpio led_4(PIN_NUMBER_LED_4); std::array leds = {&led_1, &led_2, &led_3, &led_4}; -// IRQs -nrf52::InterruptGuardian nrf52::InterruptGuardian::instance; -cm4::InterruptGuardian cm4::InterruptGuardian::instance; - -// Timer -cm4::SystemTick system_tick; -VirtualTimerDistributor virtual_timer_distributor(system_tick.instance()); -pinetime::Delay delay; - int main(void) { cm4::InterruptGuardian::enable_interrupts(); diff --git a/src/platform/nrf52/gpio.cc b/src/platform/nrf52/gpio.cc index 20e8a34..b3c04fe 100644 --- a/src/platform/nrf52/gpio.cc +++ b/src/platform/nrf52/gpio.cc @@ -1,22 +1,33 @@ -#include "platform/nrf52/gpio.h" - extern "C" { #include "nrf52.h" #include "nrf52_bitfields.h" NRF_GPIO_Type *const GPIO_REGS = reinterpret_cast(NRF_P0_BASE); + NRF_GPIOTE_Type *const GPIOTE_REGS = reinterpret_cast(NRF_GPIOTE_BASE); } +#include "platform/nrf52/gpiote.h" +#include "platform/nrf52/gpio.h" + using namespace pinetime::platform::nrf52; +Gpio::Gpio() + : pin(0) + , blocking(false) + , wait_for_event(false) +{ +} + Gpio::Gpio(uint32_t pin) - : pin_number(pin) + : pin(pin) + , blocking(false) + , wait_for_event(false) { this->set_direction(direction::OUT); this->clear(); } -void Gpio::set_direction(direction dir) +void Gpio::set_direction(direction dir, bool blocking_read) { uint32_t direct = GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos; uint32_t input = GPIO_PIN_CNF_INPUT_Disconnect << GPIO_PIN_CNF_INPUT_Pos; @@ -33,36 +44,60 @@ void Gpio::set_direction(direction dir) // GPIO_PIN_CNF_PULL_Pullup, ///< Pin pull-up resistor enabled. pull = GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos; drive = GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos; - sense = GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos; + sense = GPIO_PIN_CNF_SENSE_Low << GPIO_PIN_CNF_SENSE_Pos; + + gpiote.instance().register_handler(this); + + this->blocking = blocking_read; + + gpiote.instance().enable(); } - GPIO_REGS->PIN_CNF[pin_number] = direct | input | pull | drive | sense; + GPIO_REGS->PIN_CNF[pin] = direct | input | pull | drive | sense; } -void Gpio::set_pin_number(uint32_t pin) +void Gpio::pin_number(uint32_t pin) { - this->pin_number = pin; + this->pin = pin; +} + +uint32_t Gpio::pin_number() +{ + return this->pin; } uint32_t Gpio::get() { - uint32_t res = (GPIO_REGS->IN >> pin_number) & 1UL; + if(this->blocking) { + this->wait_for_event = true; + while(this->wait_for_event == true) { + // FIXME: Low Power + asm volatile("nop"); + } + } + uint32_t res = (GPIO_REGS->IN >> pin) & 1UL; + return res; } void Gpio::set() { - GPIO_REGS->OUTSET = 1UL << (this->pin_number); + GPIO_REGS->OUTSET = 1UL << (this->pin); } void Gpio::clear() { - GPIO_REGS->OUTCLR = 1UL << (this->pin_number); + GPIO_REGS->OUTCLR = 1UL << (this->pin); } void Gpio::toggle() { uint32_t state = GPIO_REGS->OUT; - GPIO_REGS->OUTSET = (~state & (1UL << (this->pin_number))); - GPIO_REGS->OUTCLR = (state & (1UL << (this->pin_number))); -} \ No newline at end of file + GPIO_REGS->OUTSET = (~state & (1UL << (this->pin))); + GPIO_REGS->OUTCLR = (state & (1UL << (this->pin))); +} + +void Gpio::handle() +{ + this->wait_for_event = false; +} diff --git a/src/platform/nrf52/gpio.h b/src/platform/nrf52/gpio.h index e16e536..0164571 100644 --- a/src/platform/nrf52/gpio.h +++ b/src/platform/nrf52/gpio.h @@ -3,22 +3,30 @@ #include "gpio_interface.h" +#include "platform/nrf52/InterruptHandler.h" + namespace pinetime::platform::nrf52 { class Gpio : public pinetime::interfaces::GpioInterface { - public: - inline Gpio() {} - Gpio(uint32_t); - void set_pin_number(uint32_t); - void set_direction(direction) override; - uint32_t get() override; - void set() override; - void clear() override; - void toggle() override; +public: + Gpio(); + Gpio(uint32_t); + void pin_number(uint32_t); + uint32_t pin_number() override; - private: - uint32_t pin_number; + void set_direction(direction, bool blocking_read=false) override; + uint32_t get() override; + void set() override; + void clear() override; + void toggle() override; + + void handle() override; + +private: + uint32_t pin; + bool blocking; + volatile bool wait_for_event; }; }