Skip to content

Instantly share code, notes, and snippets.

@kammce
Created August 11, 2021 22:29
Show Gist options
  • Save kammce/f05692e9b50240744525b64c53b1a7c8 to your computer and use it in GitHub Desktop.
Save kammce/f05692e9b50240744525b64c53b1a7c8 to your computer and use it in GitHub Desktop.
#include <cinttypes>
#include <cstdio>
#include <functional>
namespace embed {
/// An empty settings structure used to indicate that a module or interface does
/// not have generic settings.
struct empty_settings {};
/// The basis class for all peripheral, device and system drivers in SJSU-Dev2.
template <class Settings = empty_settings> class module {
public:
void initialize() { module_initialize(); }
Settings &settings() { return m_settings; }
protected:
virtual void module_initialize() = 0;
Settings m_settings;
};
struct pin_settings {
enum class resistor {
none,
pull_down,
pull_up,
};
enum class trigger {
none = 0,
falling = 0,
rising = 1,
both = 2,
};
constexpr pin_settings &pull_up() {
resistor = resistor::pull_up;
return *this;
}
constexpr pin_settings &pull_Down() {
resistor = resistor::pull_down;
return *this;
}
constexpr pin_settings &floating() {
resistor = resistor::none;
return *this;
}
int function = -1;
bool open_drain = false;
resistor resistor = resistor::pull_up;
};
class gpio : public module<pin_settings> {
public:
enum class pin_direction {
input,
output,
};
enum class state {
low = 0,
high = 1,
};
enum class trigger {
falling = 0,
rising = 1,
both = 2,
};
virtual void direction(pin_direction p_direction) = 0;
virtual pin_direction direction() = 0;
virtual void level(state p_level) = 0;
virtual state level() = 0;
virtual void attach_interrupt(std::function<void(void)> p_callback,
trigger p_trigger) = 0;
virtual void detach_interrupt() = 0;
void high() { level(state::high); }
void low() { level(state::low); }
bool is_high() { return state::high == level(); }
bool is_low() { return state::low == level(); }
void output() { direction(pin_direction::output); }
void input() { direction(pin_direction::input); }
bool is_output() { return pin_direction::output == direction(); }
bool is_input() { return pin_direction::input == direction(); }
void on_falling_edge(std::function<void(void)> p_callback) {
attach_interrupt(p_callback, trigger::falling);
}
void on_rising_edge(std::function<void(void)> p_callback) {
attach_interrupt(p_callback, trigger::rising);
}
void on_both_edges(std::function<void(void)> p_callback) {
attach_interrupt(p_callback, trigger::both);
}
};
namespace lpc40xx {
class gpio : public embed::gpio {
public:
void module_initialize() override { printf("MODULE INITIALIZE!\n"); }
void direction(pin_direction p_direction) override {
m_direction = p_direction;
}
pin_direction direction() override { return m_direction; }
void level(state p_level) override { m_level = p_level; }
state level() override { return m_level; }
void attach_interrupt(std::function<void(void)> p_callback,
trigger p_trigger) {
m_callback = p_callback;
printf("ATTACHING INTERRUPT with %d!\n", static_cast<int>(p_trigger));
}
void detach_interrupt() { printf("DETACHING INTERRUPT!\n"); }
void manual_trigger() { m_callback(); }
private:
pin_direction m_direction = pin_direction::output;
state m_level = state::high;
std::function<void(void)> m_callback;
};
} // namespace lpc40xx
} // namespace embed
int main() {
embed::lpc40xx::gpio gpio;
gpio.settings().pull_up();
gpio.initialize();
gpio.output();
gpio.high();
printf("level = %d\n", static_cast<int>(gpio.level()));
gpio.low();
printf("level = %d\n", static_cast<int>(gpio.level()));
gpio.on_falling_edge([]() { puts("I'm a callback!\n"); });
gpio.manual_trigger();
printf("sizeof(std::function<void(void)>) == %zu\n",
sizeof(std::function<void(void)>));
printf("sizeof(gpio) == %zu\n", sizeof(gpio));
printf("sizeof(pin_settings) == %zu\n", sizeof(embed::pin_settings));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment