mirror of
https://github.com/usatiuk/cardboy.git
synced 2025-10-28 15:17:48 +01:00
some firmware updates (fuel gauge and port extender)
This commit is contained in:
@@ -21,7 +21,7 @@ public:
|
||||
private:
|
||||
static inline i2c_device_config_t _dev_cfg = {
|
||||
.dev_addr_length = I2C_ADDR_BIT_LEN_7,
|
||||
.device_address = 0x70,
|
||||
.device_address = 0x36,
|
||||
.scl_speed_hz = 100000,
|
||||
};
|
||||
|
||||
|
||||
@@ -9,14 +9,14 @@
|
||||
#include "freertos/task.h"
|
||||
|
||||
typedef enum {
|
||||
L1 = 1 << 1,
|
||||
L2 = 1 << 6,
|
||||
L3 = 1 << 0,
|
||||
L4 = 1 << 7,
|
||||
R1 = 1 << 5,
|
||||
R2 = 1 << 2,
|
||||
R3 = 1 << 4,
|
||||
R4 = 1 << 3,
|
||||
BTN_START = 1 << 1,
|
||||
BTN_DOWN = 1 << 6,
|
||||
BTN_SELECT = 1 << 0,
|
||||
BTN_LEFT = 1 << 7,
|
||||
BTN_UP = 1 << 5,
|
||||
BTN_B = 1 << 2,
|
||||
BTN_RIGHT = 1 << 4,
|
||||
BTN_A = 1 << 3,
|
||||
} btn_num;
|
||||
|
||||
class Buttons {
|
||||
|
||||
@@ -7,10 +7,11 @@
|
||||
#define I2C_SCL GPIO_NUM_8
|
||||
#define I2C_SDA GPIO_NUM_9
|
||||
|
||||
#define SPI_MOSI GPIO_NUM_5
|
||||
#define SPI_MISO GPIO_NUM_0
|
||||
#define SPI_SCK GPIO_NUM_4
|
||||
#define SPI_DISP_CS GPIO_NUM_11
|
||||
#define SPI_MOSI GPIO_NUM_5
|
||||
#define SPI_MISO GPIO_NUM_0
|
||||
#define SPI_SCK GPIO_NUM_4
|
||||
#define SPI_DISP_CS GPIO_NUM_24
|
||||
#define SPI_DISP_DISP GPIO_NUM_11
|
||||
|
||||
#define SPI_BUS SPI2_HOST
|
||||
|
||||
@@ -20,10 +21,6 @@
|
||||
#define PWR_INT GPIO_NUM_10
|
||||
#define PWR_KILL GPIO_NUM_12
|
||||
|
||||
#define SHR_OUT GPIO_NUM_23
|
||||
#define SHR_CLK GPIO_NUM_3
|
||||
#define SHR_SH GPIO_NUM_2
|
||||
|
||||
#define DIRECT_BTN GPIO_NUM_1
|
||||
#define EXP_INT GPIO_NUM_1
|
||||
|
||||
#endif
|
||||
|
||||
@@ -20,25 +20,78 @@ BatMon& BatMon::get() {
|
||||
|
||||
static void start_pooler(void* arg) { static_cast<BatMon*>(arg)->pooler(); }
|
||||
|
||||
void WriteRegister(uint8_t reg, uint16_t value) {
|
||||
uint8_t buf2[3];
|
||||
buf2[0] = reg;
|
||||
buf2[1] = value & 0xFF;
|
||||
buf2[2] = value >> 8;
|
||||
ESP_ERROR_CHECK(i2c_master_transmit(dev_handle, buf2, sizeof(buf2), -1));
|
||||
}
|
||||
|
||||
uint16_t ReadRegister(uint8_t reg) {
|
||||
uint16_t buffer;
|
||||
ESP_ERROR_CHECK(
|
||||
i2c_master_transmit_receive(dev_handle, ®, sizeof(reg), reinterpret_cast<uint8_t*>(&buffer), 2, -1));
|
||||
return buffer;
|
||||
}
|
||||
void WriteAndVerifyRegister(char RegisterAddress, int RegisterValueToWrite) {
|
||||
int attempt = 0;
|
||||
uint16_t RegisterValueRead;
|
||||
do {
|
||||
WriteRegister(RegisterAddress, RegisterValueToWrite);
|
||||
vTaskDelay(1 / portTICK_PERIOD_MS);
|
||||
RegisterValueRead = ReadRegister(RegisterAddress);
|
||||
} while (RegisterValueToWrite != RegisterValueRead && attempt++ < 3);
|
||||
}
|
||||
|
||||
static constexpr float RSense = 0.1; // 100mOhm
|
||||
static constexpr uint16_t DesignCapMah = 180; // 100mOhm
|
||||
|
||||
constexpr float mahToCap(float mah) { return mah * (1000.0 / 5.0) * RSense; }
|
||||
constexpr float capToMah(uint16_t cap) { return cap * (5.0 / 1000.0) / RSense; }
|
||||
constexpr float regToCurrent(uint16_t reg) {
|
||||
return static_cast<float>(static_cast<int16_t>(reg)) * 0.0015625f / RSense; // Convert to mA
|
||||
}
|
||||
constexpr uint16_t currentToReg(float current) { return static_cast<uint16_t>(current * RSense / 0.0015625f); }
|
||||
constexpr float regToVoltage(uint16_t reg) {
|
||||
return reg * 0.078125f * 0.001f; // Convert to volts
|
||||
}
|
||||
constexpr uint16_t voltageToReg(float voltage) {
|
||||
return static_cast<uint16_t>(voltage / (0.078125f * 0.001f)); // Convert to register value
|
||||
}
|
||||
static constexpr uint16_t DesignCap = mahToCap(DesignCapMah);
|
||||
static constexpr uint16_t IchgTerm = currentToReg(25);
|
||||
static constexpr uint16_t VEmpty = 0xA561; // (3.3V/3.88V)
|
||||
static constexpr uint16_t dQAcc = (DesignCap / 32);
|
||||
|
||||
BatMon::BatMon() {
|
||||
ESP_ERROR_CHECK(i2c_master_bus_add_device(I2cGlobal::get().get_bus_handle(), &_dev_cfg, &dev_handle));
|
||||
|
||||
uint8_t reg = 1;
|
||||
uint8_t buffer;
|
||||
uint8_t buf2[2];
|
||||
|
||||
ESP_ERROR_CHECK(
|
||||
i2c_master_transmit_receive(dev_handle, ®, sizeof(reg), reinterpret_cast<uint8_t*>(&buffer), 1, -1));
|
||||
if (buffer & (1 << 4)) // POR reset
|
||||
bool StatusPOR = ReadRegister(0x00) & 0x0002;
|
||||
if (StatusPOR) // POR reset
|
||||
{
|
||||
printf("Gas gauge reset!\n");
|
||||
buf2[0] = 1;
|
||||
buf2[1] = 0 << 4;
|
||||
ESP_ERROR_CHECK(i2c_master_transmit(dev_handle, buf2, sizeof(buf2), -1));
|
||||
while (ReadRegister(0x3D) & 1)
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||
|
||||
buf2[0] = 0;
|
||||
buf2[1] = 1 << 4 | 1 << 2; // 10 bit adc
|
||||
ESP_ERROR_CHECK(i2c_master_transmit(dev_handle, buf2, sizeof(buf2), -1));
|
||||
uint16_t HibCFG = ReadRegister(0xBA); // Store original HibCFG value
|
||||
WriteRegister(0x60, 0x90); // Exit Hibernate Mode step 1
|
||||
WriteRegister(0xBA, 0x0); // Exit Hibernate Mode step 2
|
||||
WriteRegister(0x60, 0x0); // Exit Hibernate Mode step 3
|
||||
WriteRegister(0x18, DesignCap); // Write DesignCap
|
||||
WriteRegister(0x45, DesignCap / 32); // Write dQAcc
|
||||
WriteRegister(0x1E, IchgTerm); // Write IchgTerm
|
||||
WriteRegister(0x3A, VEmpty); // Write VEmpty
|
||||
WriteRegister(0x46, dQAcc * 44138 / DesignCap); // Write dPAcc
|
||||
WriteRegister(0xDB, 0x8000); // Write ModelCFG
|
||||
|
||||
// Poll ModelCFG.Refresh(highest bit), proceed to Step 4 when ModelCFG.Refresh = 0.
|
||||
while (ReadRegister(0xDB) & 0x8000)
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS); // 10ms wait loop. Do not continue until ModelCFG.Refresh == 0.
|
||||
WriteRegister(0xBA, HibCFG); // Restore Original HibCFG value
|
||||
|
||||
uint16_t Status = ReadRegister(0x00); // Read Status
|
||||
WriteAndVerifyRegister(0x00, Status & 0xFFFD); // Write and Verify Status with POR bit cleared
|
||||
}
|
||||
|
||||
xTaskCreate(&start_pooler, "BatMon", 2048, this, tskIDLE_PRIORITY, &_pooler_task);
|
||||
@@ -48,27 +101,9 @@ void BatMon::pooler() {
|
||||
while (true) {
|
||||
uint8_t reg = 8;
|
||||
uint16_t buffer;
|
||||
ESP_ERROR_CHECK(
|
||||
i2c_master_transmit_receive(dev_handle, ®, sizeof(reg), reinterpret_cast<uint8_t*>(&buffer), 2, -1));
|
||||
float voltage = buffer;
|
||||
voltage *= 2.44f;
|
||||
voltage /= 1000;
|
||||
_voltage = voltage;
|
||||
reg = 2;
|
||||
ESP_ERROR_CHECK(
|
||||
i2c_master_transmit_receive(dev_handle, ®, sizeof(reg), reinterpret_cast<uint8_t*>(&buffer), 2, -1));
|
||||
float charge = *reinterpret_cast<int16_t*>(&buffer);
|
||||
charge *= 6.70f;
|
||||
charge /= 50;
|
||||
_charge = charge;
|
||||
reg = 6;
|
||||
ESP_ERROR_CHECK(
|
||||
i2c_master_transmit_receive(dev_handle, ®, sizeof(reg), reinterpret_cast<uint8_t*>(&buffer), 2, -1));
|
||||
float current = static_cast<int16_t>(buffer << 2);
|
||||
current *= 11.77f;
|
||||
current /= 50;
|
||||
current /= 4;
|
||||
_current = current;
|
||||
_charge = capToMah(ReadRegister(0x05));
|
||||
_current = regToCurrent(ReadRegister(0x0B));
|
||||
_voltage = regToVoltage(ReadRegister(0x09));
|
||||
PowerHelper::get().delay(10000, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,14 @@
|
||||
#include "freertos/task.h"
|
||||
|
||||
#include "config.hpp"
|
||||
#include "i2c_global.hpp"
|
||||
|
||||
static i2c_master_dev_handle_t dev_handle;
|
||||
static inline i2c_device_config_t dev_cfg = {
|
||||
.dev_addr_length = I2C_ADDR_BIT_LEN_7,
|
||||
.device_address = 0x20,
|
||||
.scl_speed_hz = 100000,
|
||||
};
|
||||
|
||||
Buttons& Buttons::get() {
|
||||
static Buttons buttons;
|
||||
@@ -22,14 +30,15 @@ Buttons& Buttons::get() {
|
||||
static void start_pooler(void* arg) { static_cast<Buttons*>(arg)->pooler(); }
|
||||
|
||||
Buttons::Buttons() {
|
||||
ESP_ERROR_CHECK(gpio_reset_pin(SHR_OUT));
|
||||
ESP_ERROR_CHECK(gpio_reset_pin(SHR_CLK));
|
||||
ESP_ERROR_CHECK(gpio_reset_pin(SHR_SH));
|
||||
ESP_ERROR_CHECK(gpio_set_direction(SHR_OUT, GPIO_MODE_INPUT));
|
||||
ESP_ERROR_CHECK(gpio_set_pull_mode(SHR_OUT, GPIO_FLOATING));
|
||||
ESP_ERROR_CHECK(gpio_set_direction(SHR_SH, GPIO_MODE_OUTPUT));
|
||||
ESP_ERROR_CHECK(gpio_set_direction(SHR_CLK, GPIO_MODE_OUTPUT));
|
||||
ESP_ERROR_CHECK(i2c_master_bus_add_device(I2cGlobal::get().get_bus_handle(), &dev_cfg, &dev_handle));
|
||||
uint8_t buf2[2];
|
||||
|
||||
// Config
|
||||
buf2[0] = 6;
|
||||
buf2[1] = 0xFF;
|
||||
ESP_ERROR_CHECK(i2c_master_transmit(dev_handle, buf2, sizeof(buf2), -1));
|
||||
buf2[0] = 7;
|
||||
ESP_ERROR_CHECK(i2c_master_transmit(dev_handle, buf2, sizeof(buf2), -1));
|
||||
xTaskCreate(&start_pooler, "ButtonsPooler", 2048, this, 1, &_pooler_task);
|
||||
}
|
||||
|
||||
@@ -42,18 +51,12 @@ static void delay(unsigned long long loop) {
|
||||
|
||||
void Buttons::pooler() {
|
||||
while (true) {
|
||||
ESP_ERROR_CHECK(gpio_set_level(SHR_SH, 0));
|
||||
ESP_ERROR_CHECK(gpio_set_level(SHR_SH, 1));
|
||||
|
||||
uint8_t new_val = 0;
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
ESP_ERROR_CHECK(gpio_set_level(SHR_CLK, 0));
|
||||
new_val |= gpio_get_level(SHR_OUT) << i;
|
||||
ESP_ERROR_CHECK(gpio_set_level(SHR_CLK, 1));
|
||||
}
|
||||
_current = new_val;
|
||||
PowerHelper::get().delay(10000, 100);
|
||||
uint8_t reg = 0;
|
||||
uint8_t buffer;
|
||||
ESP_ERROR_CHECK(
|
||||
i2c_master_transmit_receive(dev_handle, ®, sizeof(reg), reinterpret_cast<uint8_t*>(&buffer), 1, -1));
|
||||
_current = buffer;
|
||||
PowerHelper::get().delay(10000, 200);
|
||||
}
|
||||
}
|
||||
uint8_t Buttons::get_pressed() { return _current; }
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include <driver/gpio.h>
|
||||
#include "driver/spi_master.h"
|
||||
|
||||
// This solution is attributed to Rich Schroeppel in the Programming Hacks section
|
||||
@@ -28,7 +29,14 @@ SMD& SMD::get() {
|
||||
return smd;
|
||||
}
|
||||
|
||||
SMD::SMD() { spi_bus_add_device(SPI_BUS, &_devcfg, &_spi); }
|
||||
SMD::SMD() {
|
||||
spi_bus_add_device(SPI_BUS, &_devcfg, &_spi);
|
||||
ESP_ERROR_CHECK(gpio_reset_pin(SPI_DISP_DISP));
|
||||
|
||||
ESP_ERROR_CHECK(gpio_set_direction(SPI_DISP_DISP, GPIO_MODE_OUTPUT));
|
||||
ESP_ERROR_CHECK(gpio_set_level(SPI_DISP_DISP, 1));
|
||||
ESP_ERROR_CHECK(gpio_hold_en(SPI_DISP_DISP));
|
||||
}
|
||||
|
||||
void SMD::clear() {
|
||||
std::array<uint8_t, 2> buf{};
|
||||
|
||||
@@ -39,7 +39,7 @@ FbTty tty;
|
||||
extern "C" void app_main() {
|
||||
esp_pm_config_t pm_config = {
|
||||
.max_freq_mhz = CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ, .min_freq_mhz = 16, .light_sleep_enable = true};
|
||||
ESP_ERROR_CHECK(esp_pm_configure(&pm_config));
|
||||
// ESP_ERROR_CHECK(esp_pm_configure(&pm_config));
|
||||
printf("Hello world!\n");
|
||||
// TODO: Where to put that?
|
||||
ESP_ERROR_CHECK(esp_sleep_enable_gpio_wakeup());
|
||||
@@ -74,13 +74,13 @@ extern "C" void app_main() {
|
||||
tty.reset();
|
||||
|
||||
uint8_t pressed = Buttons::get().get_pressed();
|
||||
if (pressed & L3)
|
||||
if (pressed & BTN_LEFT)
|
||||
rx -= 5;
|
||||
if (pressed & L4)
|
||||
if (pressed & BTN_DOWN)
|
||||
ry += 5;
|
||||
if (pressed & R3)
|
||||
if (pressed & BTN_UP)
|
||||
ry -= 5;
|
||||
if (pressed & R4)
|
||||
if (pressed & BTN_RIGHT)
|
||||
rx += 5;
|
||||
|
||||
if (pressed == 0 && !PowerHelper::get().is_slow())
|
||||
@@ -99,6 +99,8 @@ extern "C" void app_main() {
|
||||
tty.fmt("{:.1f}mA {:.1f}V {:.1f}mAh {}", BatMon::get().get_current(), BatMon::get().get_voltage(),
|
||||
BatMon::get().get_charge(), slow ? "S" : "");
|
||||
|
||||
tty.fmt("Buttons: {:08b}", pressed);
|
||||
|
||||
if (rx < 30)
|
||||
rx = 30;
|
||||
if (rx > 370)
|
||||
|
||||
@@ -17,6 +17,7 @@ PowerHelper& PowerHelper::get() {
|
||||
}
|
||||
bool PowerHelper::is_slow() const { return _slow; }
|
||||
void PowerHelper::set_slow(bool slow) {
|
||||
return;
|
||||
_slow = slow;
|
||||
if (_slow) {
|
||||
xEventGroupClearBits(_event_group, 1);
|
||||
@@ -41,13 +42,13 @@ void PowerHelper::reset_slow_isr() {
|
||||
static void wakeup(void* arg) { static_cast<PowerHelper*>(arg)->reset_slow_isr(); }
|
||||
|
||||
PowerHelper::PowerHelper() : _event_group(xEventGroupCreate()) {
|
||||
ESP_ERROR_CHECK(gpio_reset_pin(DIRECT_BTN));
|
||||
ESP_ERROR_CHECK(gpio_set_direction(DIRECT_BTN, GPIO_MODE_INPUT));
|
||||
ESP_ERROR_CHECK(gpio_set_pull_mode(DIRECT_BTN, GPIO_FLOATING));
|
||||
ESP_ERROR_CHECK(gpio_set_intr_type(DIRECT_BTN, GPIO_INTR_HIGH_LEVEL));
|
||||
ESP_ERROR_CHECK(gpio_wakeup_enable(DIRECT_BTN, GPIO_INTR_HIGH_LEVEL));
|
||||
// ESP_ERROR_CHECK(gpio_reset_pin(EXP_INT));
|
||||
// ESP_ERROR_CHECK(gpio_set_direction(EXP_INT, GPIO_MODE_INPUT));
|
||||
// ESP_ERROR_CHECK(gpio_set_pull_mode(EXP_INT, GPIO_FLOATING));
|
||||
// ESP_ERROR_CHECK(gpio_set_intr_type(EXP_INT, GPIO_INTR_HIGH_LEVEL));
|
||||
// ESP_ERROR_CHECK(gpio_wakeup_enable(EXP_INT, GPIO_INTR_HIGH_LEVEL));
|
||||
// ESP_ERROR_CHECK(gpio_install_isr_service(0));
|
||||
// gpio_isr_handler_add(DIRECT_BTN, wakeup, this);
|
||||
// gpio_isr_handler_add(EXP_INT, wakeup, this);
|
||||
|
||||
set_slow(false);
|
||||
}
|
||||
@@ -67,4 +68,6 @@ void PowerHelper::delay(int slow_ms, int normal_ms) {
|
||||
vTaskDelay(normal_ms / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
void PowerHelper::install_isr() { gpio_isr_handler_add(DIRECT_BTN, wakeup, this); }
|
||||
void PowerHelper::install_isr() {
|
||||
// gpio_isr_handler_add(EXP_INT, wakeup, this);
|
||||
}
|
||||
|
||||
@@ -21,18 +21,18 @@ static void IRAM_ATTR shutdown(void* arg) {
|
||||
}
|
||||
|
||||
Shutdowner::Shutdowner() {
|
||||
ESP_ERROR_CHECK(gpio_reset_pin(PWR_INT));
|
||||
ESP_ERROR_CHECK(gpio_reset_pin(PWR_KILL));
|
||||
|
||||
ESP_ERROR_CHECK(gpio_set_direction(PWR_INT, GPIO_MODE_INPUT));
|
||||
ESP_ERROR_CHECK(gpio_set_direction(PWR_KILL, GPIO_MODE_OUTPUT));
|
||||
ESP_ERROR_CHECK(gpio_set_level(PWR_KILL, 1));
|
||||
ESP_ERROR_CHECK(gpio_hold_en(PWR_KILL));
|
||||
|
||||
ESP_ERROR_CHECK(gpio_reset_pin(PWR_INT));
|
||||
ESP_ERROR_CHECK(gpio_set_direction(PWR_INT, GPIO_MODE_INPUT));
|
||||
ESP_ERROR_CHECK(gpio_set_pull_mode(PWR_INT, GPIO_FLOATING));
|
||||
ESP_ERROR_CHECK(gpio_set_intr_type(PWR_INT, GPIO_INTR_LOW_LEVEL));
|
||||
// ESP_ERROR_CHECK(esp_sleep_enable_gpio_wakeup());
|
||||
ESP_ERROR_CHECK(gpio_wakeup_enable(PWR_INT, GPIO_INTR_LOW_LEVEL));
|
||||
// ESP_ERROR_CHECK(gpio_install_isr_service(0));
|
||||
ESP_ERROR_CHECK(gpio_hold_en(PWR_KILL));
|
||||
// gpio_isr_handler_add(PWR_INT, shutdown, nullptr);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user