summaryrefslogtreecommitdiff
path: root/src/drivers
diff options
context:
space:
mode:
authorjacqueline <me@jacqueline.id.au>2023-08-18 15:40:24 +1000
committerjacqueline <me@jacqueline.id.au>2023-08-18 15:40:24 +1000
commitcad70605401e8fa30811e8c68a0cc5c014438942 (patch)
tree42307c27b01ce80b1e9038dea6dca2d4aa94eae1 /src/drivers
parent697ec3c5843c66253f73572c26b9b4885680d56c (diff)
downloadtangara-fw-cad70605401e8fa30811e8c68a0cc5c014438942.tar.gz
Add interrupts for samd changes
Diffstat (limited to 'src/drivers')
-rw-r--r--src/drivers/gpios.cpp15
-rw-r--r--src/drivers/include/gpios.hpp5
-rw-r--r--src/drivers/include/samd.hpp22
-rw-r--r--src/drivers/samd.cpp67
4 files changed, 81 insertions, 28 deletions
diff --git a/src/drivers/gpios.cpp b/src/drivers/gpios.cpp
index f6293697..412c091f 100644
--- a/src/drivers/gpios.cpp
+++ b/src/drivers/gpios.cpp
@@ -58,7 +58,9 @@ constexpr std::pair<uint8_t, uint8_t> unpack(uint16_t ba) {
return std::pair((uint8_t)ba, (uint8_t)(ba >> 8));
}
-void interrupt_isr(void* arg) {
+SemaphoreHandle_t Gpios::sReadPending;
+
+static void interrupt_isr(void* arg) {
SemaphoreHandle_t sem = reinterpret_cast<SemaphoreHandle_t>(arg);
xSemaphoreGive(sem);
}
@@ -73,10 +75,7 @@ auto Gpios::Create() -> Gpios* {
return instance;
}
-Gpios::Gpios()
- : ports_(pack(kPortADefault, kPortBDefault)),
- inputs_(0),
- read_pending_(xSemaphoreCreateBinary()) {
+Gpios::Gpios() : ports_(pack(kPortADefault, kPortBDefault)), inputs_(0) {
gpio_config_t config{
.pin_bit_mask = static_cast<uint64_t>(1) << GPIO_NUM_34,
.mode = GPIO_MODE_INPUT,
@@ -87,6 +86,7 @@ Gpios::Gpios()
gpio_config(&config);
gpio_install_isr_service(ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_SHARED |
ESP_INTR_FLAG_IRAM);
+ gpio_isr_handler_add(GPIO_NUM_34, &interrupt_isr, sReadPending);
}
Gpios::~Gpios() {
@@ -141,8 +141,9 @@ auto Gpios::Read() -> bool {
return true;
}
-auto Gpios::InstallReadPendingISR() -> void {
- gpio_isr_handler_add(GPIO_NUM_34, &interrupt_isr, read_pending_);
+auto Gpios::CreateReadPending() -> SemaphoreHandle_t {
+ sReadPending = xSemaphoreCreateBinary();
+ return sReadPending;
}
} // namespace drivers
diff --git a/src/drivers/include/gpios.hpp b/src/drivers/include/gpios.hpp
index 5ac475bf..fe330e3b 100644
--- a/src/drivers/include/gpios.hpp
+++ b/src/drivers/include/gpios.hpp
@@ -107,8 +107,7 @@ class Gpios : public IGpios {
*/
auto Read(void) -> bool;
- auto InstallReadPendingISR() -> void;
- auto IsReadPending() -> SemaphoreHandle_t { return read_pending_; }
+ static auto CreateReadPending() -> SemaphoreHandle_t;
// Not copyable or movable. There should usually only ever be once instance
// of this class, and that instance will likely have a static lifetime.
@@ -121,7 +120,7 @@ class Gpios : public IGpios {
std::atomic<uint16_t> ports_;
std::atomic<uint16_t> inputs_;
- SemaphoreHandle_t read_pending_;
+ static SemaphoreHandle_t sReadPending;
};
} // namespace drivers
diff --git a/src/drivers/include/samd.hpp b/src/drivers/include/samd.hpp
index 1560b590..4a31a577 100644
--- a/src/drivers/include/samd.hpp
+++ b/src/drivers/include/samd.hpp
@@ -8,6 +8,9 @@
#include <optional>
+#include "freertos/FreeRTOS.h"
+#include "freertos/semphr.h"
+
namespace drivers {
class Samd {
@@ -32,7 +35,8 @@ class Samd {
kFullCharge,
};
- auto ReadChargeStatus() -> std::optional<ChargeStatus>;
+ auto GetChargeStatus() -> std::optional<ChargeStatus>;
+ auto UpdateChargeStatus() -> void;
enum class UsbStatus {
// There is no compatible usb host attached.
@@ -44,9 +48,23 @@ class Samd {
kAttachedMounted,
};
- auto ReadUsbStatus() -> UsbStatus;
+ auto GetUsbStatus() -> UsbStatus;
+ auto UpdateUsbStatus() -> void;
auto ResetToFlashSamd() -> void;
+
+ static auto CreateReadPending() -> SemaphoreHandle_t;
+
+ // Not copyable or movable. There should usually only ever be once instance
+ // of this class, and that instance will likely have a static lifetime.
+ Samd(const Samd&) = delete;
+ Samd& operator=(const Samd&) = delete;
+
+ private:
+ std::optional<ChargeStatus> charge_status_;
+ UsbStatus usb_status_;
+
+ static SemaphoreHandle_t sReadPending;
};
} // namespace drivers
diff --git a/src/drivers/samd.cpp b/src/drivers/samd.cpp
index e7bfbb6b..455e9ce5 100644
--- a/src/drivers/samd.cpp
+++ b/src/drivers/samd.cpp
@@ -26,7 +26,24 @@ static const char kTag[] = "SAMD";
namespace drivers {
+SemaphoreHandle_t Samd::sReadPending;
+
+static void interrupt_isr(void* arg) {
+ SemaphoreHandle_t sem = reinterpret_cast<SemaphoreHandle_t>(arg);
+ xSemaphoreGive(sem);
+}
+
Samd::Samd() {
+ gpio_config_t config{
+ .pin_bit_mask = static_cast<uint64_t>(1) << GPIO_NUM_35,
+ .mode = GPIO_MODE_INPUT,
+ .pull_up_en = GPIO_PULLUP_ENABLE,
+ .pull_down_en = GPIO_PULLDOWN_DISABLE,
+ .intr_type = GPIO_INTR_NEGEDGE,
+ };
+ gpio_config(&config);
+ gpio_isr_handler_add(GPIO_NUM_35, &interrupt_isr, sReadPending);
+
// Being able to interface with the SAMD properly is critical. To ensure we
// will be able to, we begin by checking the I2C protocol version is
// compatible, and throw if it's not.
@@ -41,10 +58,17 @@ Samd::Samd() {
.stop();
ESP_ERROR_CHECK(transaction.Execute());
ESP_LOGI(kTag, "samd firmware rev: %u", raw_res);
+
+ UpdateChargeStatus();
+ UpdateUsbStatus();
}
Samd::~Samd() {}
-auto Samd::ReadChargeStatus() -> std::optional<ChargeStatus> {
+auto Samd::GetChargeStatus() -> std::optional<ChargeStatus> {
+ return charge_status_;
+}
+
+auto Samd::UpdateChargeStatus() -> void {
uint8_t raw_res;
I2CTransaction transaction;
transaction.start()
@@ -54,31 +78,39 @@ auto Samd::ReadChargeStatus() -> std::optional<ChargeStatus> {
.write_addr(kAddress, I2C_MASTER_READ)
.read(&raw_res, I2C_MASTER_NACK)
.stop();
- ESP_LOGI(kTag, "checking charge status");
ESP_ERROR_CHECK(transaction.Execute());
- ESP_LOGI(kTag, "raw charge status: 0x%x", raw_res);
uint8_t usb_state = raw_res & 0b11;
uint8_t charge_state = (raw_res >> 2) & 0b111;
switch (charge_state) {
case 0b000:
case 0b011:
- return ChargeStatus::kNoBattery;
+ charge_status_ = ChargeStatus::kNoBattery;
+ break;
case 0b001:
- return usb_state == 1 ? ChargeStatus::kChargingRegular
- : ChargeStatus::kChargingFast;
+ charge_status_ = usb_state == 1 ? ChargeStatus::kChargingRegular
+ : ChargeStatus::kChargingFast;
+ break;
case 0b010:
- return ChargeStatus::kFullCharge;
+ charge_status_ = ChargeStatus::kFullCharge;
+ break;
case 0b100:
- return ChargeStatus::kBatteryCritical;
+ charge_status_ = ChargeStatus::kBatteryCritical;
+ break;
case 0b101:
- return ChargeStatus::kDischarging;
+ charge_status_ = ChargeStatus::kDischarging;
+ break;
default:
- return {};
+ charge_status_ = {};
+ break;
}
}
-auto Samd::ReadUsbStatus() -> UsbStatus {
+auto Samd::GetUsbStatus() -> UsbStatus {
+ return usb_status_;
+}
+
+auto Samd::UpdateUsbStatus() -> void {
uint8_t raw_res;
I2CTransaction transaction;
transaction.start()
@@ -88,15 +120,13 @@ auto Samd::ReadUsbStatus() -> UsbStatus {
.write_addr(kAddress, I2C_MASTER_READ)
.read(&raw_res, I2C_MASTER_NACK)
.stop();
- ESP_LOGI(kTag, "checking usb status");
ESP_ERROR_CHECK(transaction.Execute());
- ESP_LOGI(kTag, "raw usb status: 0x%x", raw_res);
if (!(raw_res & 0b1)) {
- return UsbStatus::kDetached;
+ usb_status_ = UsbStatus::kDetached;
}
- return (raw_res & 0b10) ? UsbStatus::kAttachedMounted
- : UsbStatus::kAttachedIdle;
+ usb_status_ =
+ (raw_res & 0b10) ? UsbStatus::kAttachedMounted : UsbStatus::kAttachedIdle;
}
auto Samd::ResetToFlashSamd() -> void {
@@ -108,4 +138,9 @@ auto Samd::ResetToFlashSamd() -> void {
ESP_ERROR_CHECK(transaction.Execute());
}
+auto Samd::CreateReadPending() -> SemaphoreHandle_t {
+ sReadPending = xSemaphoreCreateBinary();
+ return sReadPending;
+}
+
} // namespace drivers