From ec28b36a447e1a78f2512cc8f3fe579c7ad191d2 Mon Sep 17 00:00:00 2001 From: jacqueline Date: Fri, 30 Jun 2023 21:01:25 +1000 Subject: gpio expander pin change -> event! --- src/drivers/include/gpios.hpp | 128 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 src/drivers/include/gpios.hpp (limited to 'src/drivers/include') diff --git a/src/drivers/include/gpios.hpp b/src/drivers/include/gpios.hpp new file mode 100644 index 00000000..32bbacf4 --- /dev/null +++ b/src/drivers/include/gpios.hpp @@ -0,0 +1,128 @@ +/* + * Copyright 2023 jacqueline + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#pragma once + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "driver/i2c.h" +#include "esp_check.h" +#include "esp_err.h" +#include "esp_log.h" +#include "freertos/FreeRTOS.h" + +namespace drivers { + +/** + * Wrapper for interfacing with the PCA8575 GPIO expander. Includes basic + * low-level pin setting methods, as well as higher level convenience functions + * for reading, writing, and atomically interacting with the SPI chip select + * pins. + * + * Each method of this class can be called safely from any thread, and all + * updates are guaranteed to be atomic. Any access to chip select related pins + * should be done whilst holding `cs_lock` (preferably via the helper methods). + */ +class IGpios { + public: + virtual ~IGpios() {} + + /* Maps each pin of the expander to its number in a `pack`ed uint16. */ + enum class Pin { + // Port A + kSdMuxSwitch = 0, + kSdMuxDisable = 1, + kKeyUp = 2, + kKeyDown = 3, + kKeyLock = 4, + kDisplayEnable = 5, + // 6 is unused + kSdPowerDisable = 7, + + // Port B + kPhoneDetect = 8, + kAmplifierEnable = 9, + kSdCardDetect = 10, + // 11 through 15 are unused + }; + + /* Nicer value names for use with kSdMuxSwitch. */ + enum SdController { + SD_MUX_ESP = 0, + SD_MUX_SAMD = 1, + }; + + /* + * Sets a single specific pin to the given value. `true` corresponds to + * HIGH, and `false` corresponds to LOW. + * + * This function will block until the pin has changed level. + */ + virtual auto WriteSync(Pin, bool) -> bool = 0; + + /* + * Returns the most recently cached value of the given pin. + */ + virtual auto Get(Pin) const -> bool = 0; +}; + +class Gpios : public IGpios { + public: + static auto Create() -> Gpios*; + ~Gpios(); + + /* + * Sets a single specific pin to the given value. `true` corresponds to + * HIGH, and `false` corresponds to LOW. + * + * Calls to this method will be buffered in memory until a call to `Write()` + * is made. + */ + auto WriteSync(Pin, bool) -> bool override; + + virtual auto WriteBuffered(Pin, bool) -> void; + + /** + * Sets the ports on the GPIO expander to the values currently represented + * in `ports`. + */ + auto Flush(void) -> bool; + + auto Get(Pin) const -> bool override; + + /** + * Reads from the GPIO expander, populating `inputs` with the most recent + * values. + */ + auto Read(void) -> bool; + + auto listener() -> std::function* { return listener_; } + + auto set_listener(std::function* l) -> void { listener_ = l; } + + // Not copyable or movable. There should usually only ever be once instance + // of this class, and that instance will likely have a static lifetime. + Gpios(const Gpios&) = delete; + Gpios& operator=(const Gpios&) = delete; + + private: + Gpios(); + + std::atomic ports_; + std::atomic inputs_; + + std::function* listener_; +}; + +} // namespace drivers -- cgit v1.2.3