diff options
Diffstat (limited to 'src/drivers/samd.cpp')
| -rw-r--r-- | src/drivers/samd.cpp | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/src/drivers/samd.cpp b/src/drivers/samd.cpp new file mode 100644 index 00000000..3b275c47 --- /dev/null +++ b/src/drivers/samd.cpp @@ -0,0 +1,109 @@ +#include "samd.hpp" +#include <stdint.h> +#include <optional> + +#include "esp_err.h" +#include "esp_log.h" +#include "hal/i2c_types.h" +#include "i2c.hpp" + +enum Registers { + kRegisterVersion = 0, + kRegisterCharge = 1, + kRegisterUsbMsc = 2, + kRegisterFlashing = 3, +}; + +static const uint8_t kAddress = 0x45; +static const char kTag[] = "SAMD"; + +namespace drivers { + +Samd::Samd() { + // 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. + uint8_t raw_res = 0; + I2CTransaction transaction; + transaction.start() + .write_addr(kAddress, I2C_MASTER_WRITE) + .write_ack(kRegisterVersion) + .write_addr(kAddress, I2C_MASTER_READ) + .read(&raw_res, I2C_MASTER_NACK) + .stop(); + ESP_LOGI(kTag, "checking samd firmware rev"); + ESP_ERROR_CHECK(transaction.Execute()); + ESP_LOGI(kTag, "samd firmware: %u", raw_res); +} +Samd::~Samd() {} + +auto Samd::ReadChargeStatus() -> std::optional<ChargeStatus> { + uint8_t raw_res; + I2CTransaction transaction; + transaction.start() + .write_addr(kAddress, I2C_MASTER_WRITE) + .write_ack(kRegisterCharge) + .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: %x", raw_res); + + uint8_t usb_state = raw_res & 0b11; + uint8_t charge_state = (raw_res >> 2) & 0b111; + switch (charge_state) { + case 0: + return ChargeStatus::kNoBattery; + case 1: + return usb_state == 1 ? ChargeStatus::kChargingRegular + : ChargeStatus::kChargingFast; + case 2: + return ChargeStatus::kFullCharge; + case 4: + return ChargeStatus::kBatteryCritical; + case 5: + return ChargeStatus::kDischarging; + case 3: + // Fall-through. + default: + return {}; + } +} + +auto Samd::WriteAllowUsbMsc(bool is_allowed) -> void { + I2CTransaction transaction; + transaction.start() + .write_addr(kAddress, I2C_MASTER_WRITE) + .write_ack(kRegisterUsbMsc, is_allowed) + .stop(); + ESP_ERROR_CHECK(transaction.Execute()); +} + +auto Samd::ReadUsbMscStatus() -> UsbMscStatus { + return UsbMscStatus::kDetached; +} + +auto Samd::ReadFlashingEnabled() -> bool { + uint8_t raw_res; + I2CTransaction transaction; + transaction.start() + .write_addr(kAddress, I2C_MASTER_WRITE) + .write_ack(kRegisterVersion) + .write_addr(kAddress, I2C_MASTER_READ) + .read(&raw_res, I2C_MASTER_NACK) + .stop(); + ESP_ERROR_CHECK(transaction.Execute()); + return raw_res; +} + +auto Samd::WriteFlashingEnabled(bool is_enabled) -> void { + I2CTransaction transaction; + transaction.start() + .write_addr(kAddress, I2C_MASTER_WRITE) + .write_ack(kRegisterFlashing, is_enabled) + .stop(); + ESP_ERROR_CHECK(transaction.Execute()); +} + +} // namespace drivers |
