use real classes

This commit is contained in:
2025-03-02 22:23:04 +01:00
parent b86fcbd570
commit f7d751e7dc
12 changed files with 138 additions and 102 deletions

View File

@@ -9,17 +9,21 @@
#include "driver/i2c_master.h"
namespace BatMon {
static inline i2c_device_config_t dev_cfg = {
.dev_addr_length = I2C_ADDR_BIT_LEN_7,
.device_address = 0x70,
.scl_speed_hz = 100000,
class BatMon {
public:
static BatMon& get();
float get_voltage();
float get_charge();
float get_current();
private:
static inline i2c_device_config_t _dev_cfg = {
.dev_addr_length = I2C_ADDR_BIT_LEN_7,
.device_address = 0x70,
.scl_speed_hz = 100000,
};
BatMon();
};
void init();
float get_voltage();
float get_charge();
float get_current();
}; // namespace BatMon
#endif // CB_BAT_MON_HPP

View File

@@ -4,9 +4,13 @@
#ifndef CB_DISP_TOOLS_HPP
#define CB_DISP_TOOLS_HPP
#include <display.hpp>
namespace disp_tools {
class DispTools {
public:
static DispTools& get();
void clear();
bool get_pixel(int x, int y);
void set_pixel(int x, int y);
@@ -15,8 +19,10 @@ namespace disp_tools {
void draw_line(int x1, int y1, int x2, int y2);
void draw_circle(int x, int y, int r);
void draw_to_display();
private:
SMD::disp_frame_t disp_frame;
};
#endif //DISP_TOOLS_HPP
#endif // DISP_TOOLS_HPP

View File

@@ -12,23 +12,33 @@
#include <array>
#include <bitset>
namespace SMD {
static inline spi_device_interface_config_t devcfg = {
.mode = 0, // SPI mode 0
.clock_speed_hz = 10 * 1000 * 1000, // Clock out at 10 MHz
.spics_io_num = SPI_DISP_CS, // CS pin
.flags = SPI_DEVICE_POSITIVE_CS,
.queue_size = 7, // We want to be able to queue 7 transactions at a time
// .pre_cb = lcd_spi_pre_transfer_callback, //Specify pre-transfer callback to handle D/C line
class SMD {
public:
using disp_line_t = std::bitset<400>;
using disp_frame_t = std::array<disp_line_t, 240>;
static SMD& get();
void clear();
void draw(const disp_frame_t& frame);
private:
SMD();
static inline spi_device_interface_config_t _devcfg = {
.mode = 0, // SPI mode 0
.clock_speed_hz = 10 * 1000 * 1000, // Clock out at 10 MHz
.spics_io_num = SPI_DISP_CS, // CS pin
.flags = SPI_DEVICE_POSITIVE_CS,
.queue_size = 7, // We want to be able to queue 7 transactions at a time
// .pre_cb = lcd_spi_pre_transfer_callback, //Specify pre-transfer callback to handle D/C line
};
static constexpr size_t kLineBytes = DISP_WIDTH / 8;
spi_device_handle_t _spi;
bool _vcom = false;
static constexpr size_t kLineData = (kLineBytes + 4);
std::array<uint8_t, kLineData> buf{};
std::array<uint8_t, kLineBytes> prep_line(const SMD::disp_line_t& line);
};
using disp_line_t = std::bitset<400>;
using disp_frame_t = std::array<disp_line_t, 240>;
static constexpr size_t kLineBytes = DISP_WIDTH / 8;
void init();
void clear();
void draw(const disp_frame_t& frame);
} // namespace SMD
#endif // DISPLAY_HPP

View File

@@ -9,17 +9,22 @@
#include "driver/i2c_master.h"
namespace i2c_global {
static inline i2c_master_bus_config_t i2c_mst_config = {
.i2c_port = 0,
.sda_io_num = I2C_SDA,
.scl_io_num = I2C_SCL,
.clk_source = I2C_CLK_SRC_DEFAULT,
.glitch_ignore_cnt = 7,
.flags = {.enable_internal_pullup = false, .allow_pd = true},
};
void init();
i2c_master_bus_handle_t& get_bus_handle();
class I2cGlobal {
public:
static I2cGlobal& get();
i2c_master_bus_handle_t& get_bus_handle();
private:
I2cGlobal();
static inline i2c_master_bus_config_t _i2c_mst_config = {
.i2c_port = 0,
.sda_io_num = I2C_SDA,
.scl_io_num = I2C_SCL,
.clk_source = I2C_CLK_SRC_DEFAULT,
.glitch_ignore_cnt = 7,
.flags = {.enable_internal_pullup = false, .allow_pd = true},
};
i2c_master_bus_handle_t _bus_handle;
}; // namespace i2c_global

View File

@@ -9,15 +9,19 @@
#include "driver/spi_master.h"
namespace spi_global {
static inline spi_bus_config_t buscfg = {.mosi_io_num = SPI_MOSI,
.miso_io_num = SPI_MISO,
.sclk_io_num = SPI_SCK,
.quadwp_io_num = -1,
.quadhd_io_num = -1,
.max_transfer_sz = 400 * 240 * 2};
class SpiGlobal {
public:
static SpiGlobal& get();
private:
SpiGlobal();
static inline spi_bus_config_t _buscfg = {.mosi_io_num = SPI_MOSI,
.miso_io_num = SPI_MISO,
.sclk_io_num = SPI_SCK,
.quadwp_io_num = -1,
.quadhd_io_num = -1,
.max_transfer_sz = 400 * 240 * 2};
void init();
}; // namespace spi_global

View File

@@ -8,18 +8,20 @@
static i2c_master_dev_handle_t dev_handle;
void BatMon::init() { ESP_ERROR_CHECK(i2c_master_bus_add_device(i2c_global::get_bus_handle(), &dev_cfg, &dev_handle)); }
BatMon& BatMon::get() {
static BatMon bat_mon;
return bat_mon;
}
BatMon::BatMon() { ESP_ERROR_CHECK(i2c_master_bus_add_device(I2cGlobal::get().get_bus_handle(), &_dev_cfg, &dev_handle)); }
float BatMon::get_voltage() {
uint8_t reg = 8;
uint16_t buffer;
ESP_ERROR_CHECK(
i2c_master_transmit_receive(dev_handle, &reg, sizeof(reg), reinterpret_cast<uint8_t*>(&buffer), 2, -1));
float voltage = buffer;
voltage *= 2.44f;
voltage /= 1000;
return voltage;
}
float BatMon::get_charge() {
@@ -37,11 +39,9 @@ float BatMon::get_current() {
uint16_t buffer;
ESP_ERROR_CHECK(
i2c_master_transmit_receive(dev_handle, &reg, sizeof(reg), reinterpret_cast<uint8_t*>(&buffer), 2, -1));
float current = static_cast<int16_t>(buffer << 2);
current *= 11.77f;
current /= 50;
current /= 4;
return current;
}

View File

@@ -8,28 +8,29 @@
#include <display.hpp>
using namespace disp_tools;
DispTools& DispTools::get() {
static DispTools disp_tools;
return disp_tools;
}
static SMD::disp_frame_t disp_frame;
void disp_tools::clear() {
void DispTools::clear() {
for (int y = 0; y < DISP_HEIGHT; y++) {
for (int x = 0; x < DISP_WIDTH; x++) {
disp_frame[y][x] = 1;
}
}
}
bool disp_tools::get_pixel(int x, int y) { return disp_frame[y][x]; }
void disp_tools::reset_pixel(int x, int y) { disp_frame[y][x] = true; }
void disp_tools::set_pixel(int x, int y) { disp_frame[y][x] = false; }
void disp_tools::draw_rectangle(int x1, int y1, int x2, int y2) {
bool DispTools::get_pixel(int x, int y) { return disp_frame[y][x]; }
void DispTools::reset_pixel(int x, int y) { disp_frame[y][x] = true; }
void DispTools::set_pixel(int x, int y) { disp_frame[y][x] = false; }
void DispTools::draw_rectangle(int x1, int y1, int x2, int y2) {
int dy = y2 - y1;
while (std::abs(dy) > 0) {
draw_line(x1, y1 + dy, x2, y1 + dy);
dy += (dy > 0) ? -1 : 1;
}
}
void disp_tools::draw_line(int x1, int y1, int x2, int y2) {
void DispTools::draw_line(int x1, int y1, int x2, int y2) {
int dx = x2 - x1;
int dy = y2 - y1;
int a = 0, b = 0, diff = 0;
@@ -61,7 +62,7 @@ void disp_tools::draw_line(int x1, int y1, int x2, int y2) {
}
}
}
void disp_tools::draw_circle(int x, int y, int r) {
void DispTools::draw_circle(int x, int y, int r) {
if (r > 181)
return;
int dy = -r;
@@ -71,4 +72,4 @@ void disp_tools::draw_circle(int x, int y, int r) {
dy++;
}
}
void disp_tools::draw_to_display() { SMD::draw(disp_frame); }
void DispTools::draw_to_display() { SMD::get().draw(disp_frame); }

View File

@@ -13,9 +13,9 @@ void FbTty::draw_char(int col, int row) {
for (int y = 0; y < 16; y++) {
bool color = fonts_Terminess_Powerline[_buf[col][row]][y] & (1 << (8 - x));
if (color)
disp_tools::set_pixel(col * 8 + x, row * 16 + y);
DispTools::get().set_pixel(col * 8 + x, row * 16 + y);
else
disp_tools::reset_pixel(col * 8 + x, row * 16 + y);
DispTools::get().reset_pixel(col * 8 + x, row * 16 + y);
}
}
}

View File

@@ -8,8 +8,6 @@
#include "driver/spi_master.h"
using namespace SMD;
spi_device_interface_config_t devcfg = {
.command_bits = 0,
.address_bits = 0,
@@ -21,13 +19,12 @@ spi_device_interface_config_t devcfg = {
// .pre_cb = lcd_spi_pre_transfer_callback, //Specify pre-transfer callback to handle D/C line
};
static spi_device_handle_t spi;
// This solution is attributed to Rich Schroeppel in the Programming Hacks section
// TODO: Why does the device flag not work?
unsigned char reverse_bits3(unsigned char b) { return (b * 0x0202020202ULL & 0x010884422010ULL) % 0x3ff; }
std::array<uint8_t, kLineBytes> prep_line(const SMD::disp_line_t& line) {
std::array<uint8_t, SMD::kLineBytes> SMD::prep_line(const SMD::disp_line_t& line) {
std::array<uint8_t, kLineBytes> data{};
for (int i = 0; i < DISP_WIDTH; i++) {
data[i / 8] = data[i / 8] | (line[i] << (i % 8));
@@ -38,7 +35,13 @@ std::array<uint8_t, kLineBytes> prep_line(const SMD::disp_line_t& line) {
return data;
}
void SMD::init() { spi_bus_add_device(SPI_BUS, &devcfg, &spi); }
SMD& SMD::get() {
static SMD smd;
return smd;
}
SMD::SMD() { spi_bus_add_device(SPI_BUS, &_devcfg, &_spi); }
void SMD::clear() {
std::array<uint8_t, 2> buf{};
@@ -47,24 +50,18 @@ void SMD::clear() {
t.tx_buffer = buf.data();
t.length = buf.size() * 8;
ESP_ERROR_CHECK(spi_device_transmit(spi, &t));
ESP_ERROR_CHECK(spi_device_transmit(_spi, &t));
}
bool vcom = false;
constexpr size_t kLineData = (kLineBytes + 4);
std::array<uint8_t, kLineData> buf{};
void SMD::draw(const disp_frame_t& frame) {
vcom = !vcom;
_vcom = !_vcom;
for (uint8_t i = 0; i < DISP_HEIGHT; i++) {
spi_transaction_t t{};
t.tx_buffer = buf.data();
t.length = buf.size() * 8;
buf[0] = 0b10000000 | (vcom << 6);
buf[0] = 0b10000000 | (_vcom << 6);
buf[1] = reverse_bits3(i + 1);
auto prepared = prep_line(frame.at(i));
@@ -73,6 +70,6 @@ void SMD::draw(const disp_frame_t& frame) {
buf[2 + kLineBytes] = 0;
buf[2 + kLineBytes + 1] = 0;
ESP_ERROR_CHECK(spi_device_transmit(spi, &t));
ESP_ERROR_CHECK(spi_device_transmit(_spi, &t));
}
}

View File

@@ -35,28 +35,28 @@ extern "C" void app_main() {
// .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));
printf("Hello world!\n");
i2c_global::init();
BatMon::init();
spi_global::init();
SMD::init();
SMD::clear();
disp_tools::clear();
disp_tools::draw_line(0, 0, 400, 240);
disp_tools::draw_circle(100, 100, 20);
disp_tools::draw_to_display();
I2cGlobal::get();
BatMon::get();
SpiGlobal::get();
SMD::get();
SMD::get().clear();
DispTools::get().clear();
DispTools::get().draw_line(0, 0, 400, 240);
DispTools::get().draw_circle(100, 100, 20);
DispTools::get().draw_to_display();
tty.putstr("Hello\nworld!");
disp_tools::draw_to_display();
DispTools::get().draw_to_display();
while (true) {
// SMD::clear();
// printf("Voltage: %f\n", BatMon::get_voltage());
tty.fmt("Current: {}\n", BatMon::get_current());
tty.fmt("Voltage: {}\n", BatMon::get_voltage());
tty.fmt("Current: {}\n", BatMon::get().get_current());
tty.fmt("Voltage: {}\n", BatMon::get().get_voltage());
// printf("Current: %f\n", BatMon::get_current());
// printf("Charge: %f\n", BatMon::get_charge());
tty.fmt("Charge: {}\n", BatMon::get_charge());
tty.fmt("Charge: {}\n", BatMon::get().get_charge());
// printf("Restarting in %d seconds...\n", i);
disp_tools::draw_to_display();
DispTools::get().draw_to_display();
vTaskDelay(2000 / portTICK_PERIOD_MS);
}
// printf("Restarting now.\n");

View File

@@ -4,8 +4,12 @@
#include "i2c_global.hpp"
static i2c_master_bus_handle_t bus_handle;
void i2c_global::init() { ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_mst_config, &bus_handle)); }
I2cGlobal& I2cGlobal::get() {
static I2cGlobal i2cGlobal;
return i2cGlobal;
}
i2c_master_bus_handle_t& i2c_global::get_bus_handle() { return bus_handle; }
I2cGlobal::I2cGlobal() { ESP_ERROR_CHECK(i2c_new_master_bus(&_i2c_mst_config, &_bus_handle)); }
i2c_master_bus_handle_t& I2cGlobal::get_bus_handle() { return _bus_handle; }

View File

@@ -4,4 +4,9 @@
#include "spi_global.hpp"
void spi_global::init() { ESP_ERROR_CHECK(spi_bus_initialize(SPI_BUS, &buscfg, SPI_DMA_CH_AUTO)); }
SpiGlobal& SpiGlobal::get() {
static SpiGlobal SpiGlobal;
return SpiGlobal;
}
SpiGlobal::SpiGlobal() { ESP_ERROR_CHECK(spi_bus_initialize(SPI_BUS, &_buscfg, SPI_DMA_CH_AUTO)); }