mirror of
https://github.com/usatiuk/cardboy.git
synced 2025-10-28 23:27:49 +01:00
some basic stuff
This commit is contained in:
@@ -1,3 +1,9 @@
|
||||
idf_component_register(SRCS "hello_world_main.c"
|
||||
PRIV_REQUIRES spi_flash
|
||||
INCLUDE_DIRS "")
|
||||
idf_component_register(SRCS
|
||||
src/hello_world_main.cpp
|
||||
src/display.cpp
|
||||
src/bat_mon.cpp
|
||||
src/spi_global.cpp
|
||||
src/i2c_global.cpp
|
||||
src/disp_tools.cpp
|
||||
PRIV_REQUIRES spi_flash esp_driver_i2c driver
|
||||
INCLUDE_DIRS "include")
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: CC0-1.0
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_chip_info.h"
|
||||
#include "esp_flash.h"
|
||||
#include "esp_system.h"
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
printf("Hello world!\n");
|
||||
|
||||
/* Print chip information */
|
||||
esp_chip_info_t chip_info;
|
||||
uint32_t flash_size;
|
||||
esp_chip_info(&chip_info);
|
||||
printf("This is %s chip with %d CPU core(s), %s%s%s%s, ",
|
||||
CONFIG_IDF_TARGET,
|
||||
chip_info.cores,
|
||||
(chip_info.features & CHIP_FEATURE_WIFI_BGN) ? "WiFi/" : "",
|
||||
(chip_info.features & CHIP_FEATURE_BT) ? "BT" : "",
|
||||
(chip_info.features & CHIP_FEATURE_BLE) ? "BLE" : "",
|
||||
(chip_info.features & CHIP_FEATURE_IEEE802154) ? ", 802.15.4 (Zigbee/Thread)" : "");
|
||||
|
||||
unsigned major_rev = chip_info.revision / 100;
|
||||
unsigned minor_rev = chip_info.revision % 100;
|
||||
printf("silicon revision v%d.%d, ", major_rev, minor_rev);
|
||||
if(esp_flash_get_size(NULL, &flash_size) != ESP_OK) {
|
||||
printf("Get flash size failed");
|
||||
return;
|
||||
}
|
||||
|
||||
printf("%" PRIu32 "MB %s flash\n", flash_size / (uint32_t)(1024 * 1024),
|
||||
(chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" : "external");
|
||||
|
||||
printf("Minimum free heap size: %" PRIu32 " bytes\n", esp_get_minimum_free_heap_size());
|
||||
|
||||
for (int i = 10; i >= 0; i--) {
|
||||
printf("Restarting in %d seconds...\n", i);
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
printf("Restarting now.\n");
|
||||
fflush(stdout);
|
||||
esp_restart();
|
||||
}
|
||||
25
Firmware/main/include/bat_mon.hpp
Normal file
25
Firmware/main/include/bat_mon.hpp
Normal file
@@ -0,0 +1,25 @@
|
||||
//
|
||||
// Created by Stepan Usatiuk on 02.03.2025.
|
||||
//
|
||||
|
||||
#ifndef CB_BAT_MON_HPP
|
||||
#define CB_BAT_MON_HPP
|
||||
|
||||
#include "config.hpp"
|
||||
|
||||
#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,
|
||||
};
|
||||
|
||||
void init();
|
||||
float get_voltage();
|
||||
float get_charge();
|
||||
float get_current();
|
||||
}; // namespace BatMon
|
||||
|
||||
#endif // CB_BAT_MON_HPP
|
||||
20
Firmware/main/include/config.hpp
Normal file
20
Firmware/main/include/config.hpp
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef CB_CONFIG_HPP
|
||||
#define CB_CONFIG_HPP
|
||||
|
||||
#include "soc/gpio_num.h"
|
||||
#include "hal/spi_types.h"
|
||||
|
||||
#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_BUS SPI2_HOST
|
||||
|
||||
#define DISP_WIDTH 400
|
||||
#define DISP_HEIGHT 240
|
||||
|
||||
#endif
|
||||
22
Firmware/main/include/disp_tools.hpp
Normal file
22
Firmware/main/include/disp_tools.hpp
Normal file
@@ -0,0 +1,22 @@
|
||||
//
|
||||
// Created by Stepan Usatiuk on 02.03.2025.
|
||||
//
|
||||
|
||||
#ifndef CB_DISP_TOOLS_HPP
|
||||
#define CB_DISP_TOOLS_HPP
|
||||
|
||||
|
||||
namespace disp_tools {
|
||||
void clear();
|
||||
bool get_pixel(int x, int y);
|
||||
void set_pixel(int x, int y);
|
||||
void reset_pixel(int x, int y);
|
||||
void draw_rectangle(int x1, int y1, int x2, int y2);
|
||||
void draw_line(int x1, int y1, int x2, int y2);
|
||||
void draw_circle(int x, int y, int r);
|
||||
void draw_to_display();
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif //DISP_TOOLS_HPP
|
||||
34
Firmware/main/include/display.hpp
Normal file
34
Firmware/main/include/display.hpp
Normal file
@@ -0,0 +1,34 @@
|
||||
//
|
||||
// Created by Stepan Usatiuk on 02.03.2025.
|
||||
//
|
||||
|
||||
#ifndef CB_DISPLAY_HPP
|
||||
#define CB_DISPLAY_HPP
|
||||
|
||||
#include "config.hpp"
|
||||
|
||||
#include "driver/spi_master.h"
|
||||
|
||||
#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
|
||||
};
|
||||
|
||||
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
|
||||
26
Firmware/main/include/i2c_global.hpp
Normal file
26
Firmware/main/include/i2c_global.hpp
Normal file
@@ -0,0 +1,26 @@
|
||||
//
|
||||
// Created by Stepan Usatiuk on 02.03.2025.
|
||||
//
|
||||
|
||||
#ifndef CB_I2C_GLOBAL_HPP
|
||||
#define CB_I2C_GLOBAL_HPP
|
||||
|
||||
#include "config.hpp"
|
||||
|
||||
#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();
|
||||
}; // namespace i2c_global
|
||||
|
||||
|
||||
#endif // CB_I2C_GLOBAL_HPP
|
||||
24
Firmware/main/include/spi_global.hpp
Normal file
24
Firmware/main/include/spi_global.hpp
Normal file
@@ -0,0 +1,24 @@
|
||||
//
|
||||
// Created by Stepan Usatiuk on 02.03.2025.
|
||||
//
|
||||
|
||||
#ifndef CB_SPI_GLOBAL_HPP
|
||||
#define CB_SPI_GLOBAL_HPP
|
||||
|
||||
#include "config.hpp"
|
||||
|
||||
#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};
|
||||
|
||||
void init();
|
||||
}; // namespace spi_global
|
||||
|
||||
|
||||
#endif // CB_SPI_GLOBAL_HPP
|
||||
47
Firmware/main/src/bat_mon.cpp
Normal file
47
Firmware/main/src/bat_mon.cpp
Normal file
@@ -0,0 +1,47 @@
|
||||
//
|
||||
// Created by Stepan Usatiuk on 02.03.2025.
|
||||
//
|
||||
|
||||
#include "bat_mon.hpp"
|
||||
|
||||
#include "i2c_global.hpp"
|
||||
|
||||
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)); }
|
||||
float BatMon::get_voltage() {
|
||||
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;
|
||||
|
||||
return voltage;
|
||||
}
|
||||
float BatMon::get_charge() {
|
||||
uint8_t reg = 2;
|
||||
uint16_t buffer;
|
||||
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;
|
||||
return charge;
|
||||
}
|
||||
float BatMon::get_current() {
|
||||
uint8_t reg = 6;
|
||||
uint16_t buffer;
|
||||
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;
|
||||
|
||||
return current;
|
||||
}
|
||||
74
Firmware/main/src/disp_tools.cpp
Normal file
74
Firmware/main/src/disp_tools.cpp
Normal file
@@ -0,0 +1,74 @@
|
||||
//
|
||||
// Created by Stepan Usatiuk on 02.03.2025.
|
||||
//
|
||||
|
||||
#include "disp_tools.hpp"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include <display.hpp>
|
||||
|
||||
using namespace disp_tools;
|
||||
|
||||
static SMD::disp_frame_t disp_frame;
|
||||
|
||||
void disp_tools::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) {
|
||||
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) {
|
||||
int dx = x2 - x1;
|
||||
int dy = y2 - y1;
|
||||
int a = 0, b = 0, diff = 0;
|
||||
|
||||
if (dx == 0) {
|
||||
while (dy != 0) {
|
||||
set_pixel(x1, y1 + dy);
|
||||
dy += (dy > 0) ? -1 : 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (dy == 0) {
|
||||
while (dx != 0) {
|
||||
set_pixel(x1 + dx, y1);
|
||||
dx += (dx > 0) ? -1 : 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
while (std::abs(a) <= std::abs(dx) && std::abs(b) <= std::abs(dy)) {
|
||||
set_pixel(x1 + a, y1 + b);
|
||||
if (diff < 0) {
|
||||
a += (dx > 0) ? 1 : -1;
|
||||
diff += std::abs(dy);
|
||||
} else {
|
||||
b += (dy > 0) ? 1 : -1;
|
||||
diff -= std::abs(dx);
|
||||
}
|
||||
}
|
||||
}
|
||||
void disp_tools::draw_circle(int x, int y, int r) {
|
||||
if (r > 181)
|
||||
return;
|
||||
int dy = -r;
|
||||
while (dy <= r) {
|
||||
int dx = static_cast<int>(std::sqrt(r * r - dy * dy));
|
||||
draw_line(x - dx, y + dy, x + dx, y + dy);
|
||||
dy++;
|
||||
}
|
||||
}
|
||||
void disp_tools::draw_to_display() { SMD::draw(disp_frame); }
|
||||
78
Firmware/main/src/display.cpp
Normal file
78
Firmware/main/src/display.cpp
Normal file
@@ -0,0 +1,78 @@
|
||||
//
|
||||
// Created by Stepan Usatiuk on 02.03.2025.
|
||||
//
|
||||
|
||||
#include "display.hpp"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "driver/spi_master.h"
|
||||
|
||||
using namespace SMD;
|
||||
|
||||
spi_device_interface_config_t devcfg = {
|
||||
.command_bits = 0,
|
||||
.address_bits = 0,
|
||||
.mode = 0, // SPI mode 0
|
||||
.clock_speed_hz = 4 * 1000 * 1000, // Clock out at 10 MHz
|
||||
.spics_io_num = SPI_DISP_CS, // CS pin
|
||||
.flags = SPI_DEVICE_POSITIVE_CS,
|
||||
.queue_size = 1, // 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 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, kLineBytes> data{};
|
||||
for (int i = 0; i < DISP_WIDTH; i++) {
|
||||
data[i / 8] = data[i / 8] | (line[i] << (i % 8));
|
||||
}
|
||||
for (int i = 0; i < kLineBytes; i++) {
|
||||
data[i] = reverse_bits3(data[i]);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
void SMD::init() { spi_bus_add_device(SPI_BUS, &devcfg, &spi); }
|
||||
|
||||
void SMD::clear() {
|
||||
std::array<uint8_t, 2> buf{};
|
||||
buf[0] = 0b00100000;
|
||||
spi_transaction_t t{};
|
||||
|
||||
t.tx_buffer = buf.data();
|
||||
t.length = buf.size() * 8;
|
||||
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;
|
||||
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[1] = reverse_bits3(i + 1);
|
||||
|
||||
auto prepared = prep_line(frame.at(i));
|
||||
memcpy(buf.data() + 2, prepared.data(), kLineBytes);
|
||||
|
||||
buf[2 + kLineBytes] = 0;
|
||||
buf[2 + kLineBytes + 1] = 0;
|
||||
|
||||
ESP_ERROR_CHECK(spi_device_transmit(spi, &t));
|
||||
}
|
||||
}
|
||||
53
Firmware/main/src/hello_world_main.cpp
Normal file
53
Firmware/main/src/hello_world_main.cpp
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: CC0-1.0
|
||||
*/
|
||||
|
||||
#include <cstdint>
|
||||
#include <disp_tools.hpp>
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include "esp_chip_info.h"
|
||||
#include "esp_flash.h"
|
||||
#include "esp_system.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#include "display.hpp"
|
||||
|
||||
#include "bat_mon.hpp"
|
||||
#include "driver/i2c_master.h"
|
||||
#include "driver/spi_master.h"
|
||||
#include "i2c_global.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <spi_global.hpp>
|
||||
#include <string>
|
||||
|
||||
|
||||
extern "C" void app_main() {
|
||||
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();
|
||||
|
||||
for (int i = 10; i >= 0; i--) {
|
||||
// SMD::clear();
|
||||
printf("Voltage: %f\n", BatMon::get_voltage());
|
||||
printf("Current: %f\n", BatMon::get_current());
|
||||
printf("Charge: %f\n", BatMon::get_charge());
|
||||
printf("Restarting in %d seconds...\n", i);
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
printf("Restarting now.\n");
|
||||
fflush(stdout);
|
||||
esp_restart();
|
||||
}
|
||||
11
Firmware/main/src/i2c_global.cpp
Normal file
11
Firmware/main/src/i2c_global.cpp
Normal file
@@ -0,0 +1,11 @@
|
||||
//
|
||||
// Created by Stepan Usatiuk on 02.03.2025.
|
||||
//
|
||||
|
||||
#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)); }
|
||||
|
||||
i2c_master_bus_handle_t& i2c_global::get_bus_handle() { return bus_handle; }
|
||||
7
Firmware/main/src/spi_global.cpp
Normal file
7
Firmware/main/src/spi_global.cpp
Normal file
@@ -0,0 +1,7 @@
|
||||
//
|
||||
// Created by Stepan Usatiuk on 02.03.2025.
|
||||
//
|
||||
|
||||
#include "spi_global.hpp"
|
||||
|
||||
void spi_global::init() { ESP_ERROR_CHECK(spi_bus_initialize(SPI_BUS, &buscfg, SPI_DMA_CH_AUTO)); }
|
||||
Reference in New Issue
Block a user