Skip to content

Commit 373f199

Browse files
committed
Merge branch 'gpio'
2 parents ea30140 + bcd241a commit 373f199

File tree

2 files changed

+97
-59
lines changed

2 files changed

+97
-59
lines changed

Application/Inc/GPIO.hpp

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#ifndef APPLICATION_INC_GPIO
22
#define APPLICATION_INC_GPIO
33

4+
#include "StateMachine.hpp"
45
#include "main.h"
56

67
/**
@@ -12,27 +13,41 @@
1213
class CustomGPIO {
1314
public:
1415
CustomGPIO();
15-
CustomGPIO(uint16_t);
16+
CustomGPIO(uint16_t PollPeriod);
1617
virtual ~CustomGPIO();
17-
void setPort(GPIO_TypeDef *, uint16_t);
18-
19-
void on();
20-
void off();
21-
void toggle();
18+
void setPort(GPIO_TypeDef *Port, uint16_t Pin);
2219

20+
// Public Methods
21+
void on();
22+
void off();
23+
void toggle();
2324
bool getStatus();
25+
void scheduler();
2426

25-
void schedulerLowActive();
26-
void schedulerHighActive();
27+
// Hardware Data
28+
private:
29+
GPIO_TypeDef *port;
30+
uint16_t pin;
2731

32+
// State Machine
33+
public:
34+
enum class State { ON, OFF, LOW_INACTIVE, LOW_SETTLING, LOW_ACTIVE, HIGH_INACTIVE, HIGH_SETTLING, HIGH_ACTIVE };
35+
enum class Event { ON, OFF, TOGGLE, POLL };
36+
SM<CustomGPIO>::StateMachine gpio_sm;
37+
38+
// Action and Guard
2839
private:
29-
GPIO_TypeDef *m_port;
30-
uint16_t m_pin;
40+
Action actionOn();
41+
Action actionOff();
42+
Action actionToggle();
43+
44+
Guard guardLowSense();
45+
Guard guardHighSense();
46+
Guard guardStable();
3147

32-
uint16_t m_roll_period{100};
33-
uint16_t m_roll_timer{0};
34-
bool m_stable{true};
35-
bool m_pressed{false};
48+
// State Machine Data
49+
uint16_t roll_period{100};
50+
uint16_t roll_timer{0};
3651
};
3752

3853
#endif /* APPLICATION_INC_GPIO */

Application/Src/GPIO.cpp

Lines changed: 68 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -2,74 +2,97 @@
22

33
/// @brief Default constructor for CustomGPIO.
44
/// Initializes rollover period and state variables.
5-
CustomGPIO::CustomGPIO() {}
5+
CustomGPIO::CustomGPIO() {
6+
// State Machine
7+
// clang-format off
8+
gpio_sm = {
9+
State::OFF,
10+
{ // Entry definition: (TargetState, GuardFunction, ActionFunction, Injection)
11+
{ State::OFF, {}, actionOff(), {} },
12+
{ State::LOW_INACTIVE, {}, {}, {} },
13+
{ State::HIGH_INACTIVE, {}, {}, {} },
14+
},
15+
{ // Transition definition: (CurrentState, Event, NextState, GuardFunction, ActionFunction, Injection)
16+
{ State::ON, Event::OFF, State::OFF, {}, actionOff(), {} },
17+
{ State::OFF, Event::ON, State::ON, {}, actionOn(), {} },
18+
{ State::ON, Event::TOGGLE, State::OFF, {}, actionToggle(), {} },
19+
{ State::OFF, Event::TOGGLE, State::ON, {}, actionToggle(), {} },
20+
{ State::LOW_INACTIVE, Event::POLL, State::LOW_SETTLING, guardLowSense(), {}, {} },
21+
{ State::LOW_SETTLING, Event::POLL, State::LOW_ACTIVE, guardStable(), {}, {} },
22+
{ State::LOW_ACTIVE, Event::POLL, State::LOW_INACTIVE, {}, guardHighSense(), {} },
23+
{ State::HIGH_INACTIVE, Event::POLL, State::HIGH_SETTLING, guardHighSense(), {}, {} },
24+
{ State::HIGH_SETTLING, Event::POLL, State::HIGH_ACTIVE, guardStable(), {}, {} },
25+
{ State::HIGH_ACTIVE, Event::POLL, State::HIGH_INACTIVE, {}, guardLowSense(), {} },
26+
}
27+
};
28+
// clang-format on
29+
}
630

731
/// @brief Constructor with custom debounce period.
832
/// @param value Number of ticks for stable state detection.
9-
CustomGPIO::CustomGPIO(uint16_t value) { m_roll_period = value; }
33+
CustomGPIO::CustomGPIO(uint16_t PollPeriod) { roll_period = PollPeriod; }
1034

1135
/// @brief Destructor for CustomGPIO.
1236
CustomGPIO::~CustomGPIO() {}
1337

1438
/// @brief Configure the GPIO port and pin for this instance.
1539
/// @param port Pointer to the GPIO port (e.g., GPIOA).
1640
/// @param pin GPIO pin identifier (e.g., GPIO_PIN_0).
17-
void CustomGPIO::setPort(GPIO_TypeDef *port, uint16_t pin) {
18-
m_port = port;
19-
m_pin = pin;
41+
void CustomGPIO::setPort(GPIO_TypeDef *Port, uint16_t Pin) {
42+
port = Port;
43+
pin = Pin;
2044
}
2145

2246
/// @brief Set the GPIO pin to a high logic level.
23-
void CustomGPIO::on() { HAL_GPIO_WritePin(m_port, m_pin, GPIO_PIN_SET); }
47+
void CustomGPIO::on() { gpio_sm.triggerEvent(Event::ON); }
2448

2549
/// @brief Set the GPIO pin to a low logic level.
26-
void CustomGPIO::off() { HAL_GPIO_WritePin(m_port, m_pin, GPIO_PIN_RESET); }
50+
void CustomGPIO::off() { gpio_sm.triggerEvent(Event::OFF); }
2751

2852
/// @brief Toggle the current state of the GPIO pin.
29-
void CustomGPIO::toggle() { HAL_GPIO_TogglePin(m_port, m_pin); }
53+
void CustomGPIO::toggle() { gpio_sm.triggerEvent(Event::TOGGLE); }
3054

31-
/// @brief Debounce scheduler for active-low inputs.
32-
/// Monitors pin for stable falling-edge and marks press event.
33-
/// @note Call periodically to update internal status.
34-
void CustomGPIO::schedulerLowActive() {
35-
if (m_stable) {
36-
if (!HAL_GPIO_ReadPin(m_port, m_pin))
37-
m_stable = false;
38-
else
39-
m_roll_timer = 0;
55+
bool CustomGPIO::getStatus() {
56+
if (gpio_sm.currentState == State::ON) {
57+
return true;
58+
} else if (gpio_sm.currentState == State::LOW_ACTIVE) {
59+
return true;
60+
} else if (gpio_sm.currentState == State::HIGH_ACTIVE) {
61+
return true;
4062
}
63+
return false;
64+
}
4165

42-
else if (HAL_GPIO_ReadPin(m_port, m_pin) || ++m_roll_timer > m_roll_period) {
43-
m_stable = true;
44-
m_pressed = true;
45-
m_roll_timer = m_roll_period * 0.8;
46-
}
66+
/// @brief Scheduler for state-driven GPIO updates.
67+
void CustomGPIO::scheduler() { gpio_sm.triggerEvent(Event::POLL); }
68+
69+
Action CustomGPIO::actionOn() {
70+
return [this]() { HAL_GPIO_WritePin(port, pin, GPIO_PIN_SET); };
4771
}
4872

49-
/// @brief Debounce scheduler for active-high inputs.
50-
/// Monitors pin for stable rising-edge and marks press event.
51-
/// @note Call periodically to update internal status.
52-
void CustomGPIO::schedulerHighActive() {
53-
if (m_stable) {
54-
if (HAL_GPIO_ReadPin(m_port, m_pin))
55-
m_stable = false;
56-
else
57-
m_roll_timer = 0;
58-
}
73+
Action CustomGPIO::actionOff() {
74+
return [this]() { HAL_GPIO_WritePin(port, pin, GPIO_PIN_RESET); };
75+
}
5976

60-
else if (!HAL_GPIO_ReadPin(m_port, m_pin) || ++m_roll_timer > m_roll_period) {
61-
m_stable = true;
62-
m_pressed = true;
63-
m_roll_timer = m_roll_period * 0.8;
64-
}
77+
Action CustomGPIO::actionToggle() {
78+
return [this]() { HAL_GPIO_TogglePin(port, pin); };
6579
}
6680

67-
/// @brief Retrieve and clear the press event flag.
68-
/// @return true if a press event was detected since last call; false otherwise.
69-
bool CustomGPIO::getStatus() {
70-
if (m_pressed) {
71-
m_pressed = !m_pressed;
72-
return true;
73-
} else
74-
return false;
81+
Guard CustomGPIO::guardLowSense() {
82+
return [this]() { return !HAL_GPIO_ReadPin(port, pin); };
83+
}
84+
85+
Guard CustomGPIO::guardHighSense() {
86+
return [this]() { return HAL_GPIO_ReadPin(port, pin); };
87+
}
88+
89+
Guard CustomGPIO::guardStable() {
90+
return [this]() {
91+
if (roll_timer++ > roll_period) {
92+
roll_timer = 0;
93+
return true;
94+
} else {
95+
return false;
96+
}
97+
};
7598
}

0 commit comments

Comments
 (0)