Skip to content

Commit 33601d5

Browse files
committed
Updated GPIO Event Controller to handle both ports
1 parent ded541d commit 33601d5

File tree

4 files changed

+39
-21
lines changed

4 files changed

+39
-21
lines changed

include/hal/gpio_event_controller.hpp

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,16 @@ namespace edge::aidan {
66

77
extern "C" void GPIOTE_IRQHandler();
88

9-
static constexpr uint8_t GPIO_PINS = 32;
9+
static constexpr uint8_t MAX_GPIO_CALLBACKS = 32;
1010

1111
// TODO: Add a controller for other GPIOTE events (channels)?
1212
class GPIOEventController {
1313
public:
14+
enum class Port { ZERO, ONE };
1415
using GPIOEventCallback = etl::delegate<void(nrf_gpio_pin_sense_t, int)>;
1516

1617
private:
17-
etl::array<etl::optional<GPIOEventCallback>, GPIO_PINS> callbacks{etl::nullopt};
18+
etl::unordered_map<int, GPIOEventCallback, MAX_GPIO_CALLBACKS> callbacks{};
1819

1920
void handle_gpiote_port_event() const;
2021
GPIOEventController();
@@ -24,14 +25,15 @@ class GPIOEventController {
2425

2526
static GPIOEventController& get();
2627

27-
// GPIOEventController& operator=(const GPIOEventController&) = delete;
28-
// GPIOEventController& operator=(GPIOEventController&&) = delete;
29-
// GPIOEventController(const GPIOEventController&) = delete;
30-
// GPIOEventController(GPIOEventController&&) = delete;
28+
GPIOEventController& operator=(const GPIOEventController&) = delete;
29+
GPIOEventController& operator=(GPIOEventController&&) = delete;
30+
GPIOEventController(const GPIOEventController&) = delete;
31+
GPIOEventController(GPIOEventController&&) = delete;
3132

3233
// TODO/idea, what if we instead made this a factory?
3334
void set_gpio_callback(
34-
uint32_t pin, PinPullMode pin_resistance, GPIOEventCallback callback
35+
uint32_t pin, PinPullMode pin_resistance, GPIOEventCallback callback,
36+
PinSense sense = PinSense::HIGH
3537
);
3638

3739
void clear_gpio_callback(uint32_t pin);

include/hal/hal_enums.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ enum class PinPullMode {
99
NONE = NRF_GPIO_PIN_NOPULL
1010
};
1111

12+
enum class PinSense { HIGH, LOW };
13+
1214
nrf_gpio_pin_pull_t to_nrf_gpio_pin_pull(PinPullMode mode);
15+
nrf_gpio_pin_sense_t to_nrf_gpio_pin_sense(PinSense sense);
1316

1417
} // namespace edge::aidan

src/hal/gpio_event_controller.cpp

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "hal/gpio_event_controller.hpp"
22

33
#include "hal/hal_enums.hpp"
4+
#include "microbit_v2.h"
45
#include "nrf_gpio.h"
56

67
#include <nrf_gpiote.h>
@@ -11,14 +12,13 @@ namespace edge::aidan {
1112

1213
// TODO: expose pullup, polarity, etc
1314
void GPIOEventController::set_gpio_callback(
14-
uint32_t pin, PinPullMode pin_resistance, GPIOEventCallback callback
15+
uint32_t pin, PinPullMode pin_resistance, GPIOEventCallback callback, PinSense sense
1516
)
1617
{
1718
callbacks[pin] = callback;
1819

19-
// TODO: start high/lwo based on resistance type
2020
nrf_gpio_cfg_sense_input(
21-
pin, to_nrf_gpio_pin_pull(pin_resistance), NRF_GPIO_PIN_SENSE_HIGH
21+
pin, to_nrf_gpio_pin_pull(pin_resistance), to_nrf_gpio_pin_sense(sense)
2222
);
2323
}
2424

@@ -30,7 +30,9 @@ GPIOEventController& GPIOEventController::get()
3030

3131
void GPIOEventController::clear_gpio_callback(uint32_t pin)
3232
{
33-
callbacks[pin] = etl::nullopt;
33+
if (auto it = callbacks.find(pin); it != callbacks.end()) {
34+
callbacks.erase(it);
35+
}
3436
nrf_gpio_cfg_sense_input(pin, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_NOSENSE);
3537
}
3638

@@ -50,12 +52,11 @@ GPIOEventController::~GPIOEventController()
5052

5153
void GPIOEventController::handle_gpiote_port_event() const
5254
{
53-
auto latch = NRF_GPIO->LATCH;
54-
55-
for (uint32_t pin = 0; pin < GPIO_PINS; pin++) {
56-
if (!(latch & (1UL << pin))) {
55+
for (auto& [pin, callback] : callbacks) {
56+
if (!nrf_gpio_pin_latch_get(pin))
5757
continue;
58-
}
58+
59+
nrf_gpio_pin_latch_clear(pin);
5960

6061
uint32_t pin_state = nrf_gpio_pin_read(pin);
6162
auto state =
@@ -64,12 +65,12 @@ void GPIOEventController::handle_gpiote_port_event() const
6465
(pin_state != 0) ? NRF_GPIO_PIN_SENSE_LOW : NRF_GPIO_PIN_SENSE_HIGH;
6566
nrf_gpio_cfg_sense_input(pin, nrf_gpio_pin_pull_get(pin), opposite_state);
6667

67-
auto callback = GPIOEventController::get().callbacks[pin];
68-
if (callback) {
69-
callback.value()(state, pin);
70-
}
68+
callback(state, pin);
7169
}
72-
NRF_GPIO->LATCH = latch;
70+
71+
// Ensure all pins cleared, even if no handler set
72+
NRF_P0->LATCH = NRF_P0->LATCH;
73+
NRF_P1->LATCH = NRF_P1->LATCH;
7374
}
7475

7576
extern "C" {

src/hal/hal_enums.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,16 @@ nrf_gpio_pin_pull_t to_nrf_gpio_pin_pull(PinPullMode mode)
1616
panic("Invalid pull mode");
1717
}
1818
}
19+
20+
nrf_gpio_pin_sense_t to_nrf_gpio_pin_sense(PinSense sense)
21+
{
22+
switch (sense) {
23+
case PinSense::LOW:
24+
return NRF_GPIO_PIN_SENSE_LOW;
25+
case PinSense::HIGH:
26+
return NRF_GPIO_PIN_SENSE_HIGH;
27+
default:
28+
panic("Invalid pin sense");
29+
}
30+
}
1931
} // namespace edge::aidan

0 commit comments

Comments
 (0)