Rename Boards/ to Devices/ (#414)
This commit is contained in:
committed by
GitHub
parent
c7c9618f48
commit
c1ff024657
@@ -0,0 +1,54 @@
|
||||
#include "CardputerEncoder.h"
|
||||
|
||||
void CardputerEncoder::readCallback(lv_indev_t* indev, lv_indev_data_t* data) {
|
||||
CardputerEncoder* self = static_cast<CardputerEncoder*>(lv_indev_get_user_data(indev));
|
||||
|
||||
self->keyboard.updateKeyList();
|
||||
|
||||
data->state = LV_INDEV_STATE_RELEASED;
|
||||
|
||||
if (self->keyboard.keyList().size() != self->lastKeyNum) {
|
||||
// If key pressed
|
||||
if (self->keyboard.keyList().size() != 0) {
|
||||
// Update states and values
|
||||
self->keyboard.updateKeysState();
|
||||
if (self->keyboard.keysState().fn) {
|
||||
if (self->keyboard.keysState().enter) {
|
||||
data->key = LV_KEY_ENTER;
|
||||
data->state = LV_INDEV_STATE_PRESSED;
|
||||
} else {
|
||||
for (auto& i : self->keyboard.keysState().values) {
|
||||
if (i == ';') { // Up
|
||||
data->enc_diff = -1;
|
||||
} else if (i == '.') { // Down
|
||||
data->enc_diff = 1;
|
||||
}
|
||||
break; // We only care about the first value
|
||||
}
|
||||
}
|
||||
}
|
||||
self->lastKeyNum = self->keyboard.keyList().size();
|
||||
} else {
|
||||
self->lastKeyNum = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CardputerEncoder::startLvgl(lv_display_t* display) {
|
||||
keyboard.init();
|
||||
|
||||
lvglDevice = lv_indev_create();
|
||||
lv_indev_set_type(lvglDevice, LV_INDEV_TYPE_ENCODER);
|
||||
lv_indev_set_read_cb(lvglDevice, &readCallback);
|
||||
lv_indev_set_display(lvglDevice, display);
|
||||
lv_indev_set_user_data(lvglDevice, this);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CardputerEncoder::stopLvgl() {
|
||||
lv_indev_delete(lvglDevice);
|
||||
lvglDevice = nullptr;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <Tactility/hal/encoder/EncoderDevice.h>
|
||||
|
||||
#include "keyboard/keyboard.h"
|
||||
|
||||
/**
|
||||
* Wrapper around the keyboard that uses the following buttons to simulate an encoder:
|
||||
* - Up
|
||||
* - Down
|
||||
* - ok (fn + enter)
|
||||
*/
|
||||
class CardputerEncoder final : public tt::hal::encoder::EncoderDevice {
|
||||
KEYBOARD::Keyboard keyboard;
|
||||
int lastKeyNum = 0;
|
||||
lv_indev_t* _Nullable lvglDevice = nullptr;
|
||||
|
||||
static void readCallback(lv_indev_t* indev, lv_indev_data_t* data);
|
||||
|
||||
public:
|
||||
|
||||
std::string getName() const override { return "Cardputer Encoder"; }
|
||||
std::string getDescription() const override { return "Cardputer keyboard up/down acting as encoder"; }
|
||||
|
||||
bool startLvgl(lv_display_t* display) override;
|
||||
bool stopLvgl() override;
|
||||
|
||||
lv_indev_t* _Nullable getLvglIndev() override { return lvglDevice; }
|
||||
};
|
||||
@@ -0,0 +1,102 @@
|
||||
#include "CardputerKeyboard.h"
|
||||
|
||||
#include <Tactility/Log.h>
|
||||
|
||||
constexpr auto* TAG = "Keyboard";
|
||||
|
||||
bool CardputerKeyboard::startLvgl(lv_display_t* display) {
|
||||
keyboard.init();
|
||||
|
||||
lvglDevice = lv_indev_create();
|
||||
lv_indev_set_type(lvglDevice, LV_INDEV_TYPE_KEYPAD);
|
||||
lv_indev_set_read_cb(lvglDevice, &readCallback);
|
||||
lv_indev_set_display(lvglDevice, display);
|
||||
lv_indev_set_user_data(lvglDevice, this);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CardputerKeyboard::stopLvgl() {
|
||||
lv_indev_delete(lvglDevice);
|
||||
lvglDevice = nullptr;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CardputerKeyboard::readCallback(lv_indev_t* indev, lv_indev_data_t* data) {
|
||||
CardputerKeyboard* self = static_cast<CardputerKeyboard*>(lv_indev_get_user_data(indev));
|
||||
|
||||
data->key = 0;
|
||||
data->state = LV_INDEV_STATE_RELEASED;
|
||||
|
||||
self->keyboard.updateKeyList();
|
||||
|
||||
if (self->keyboard.keyList().size() != self->lastKeyNum) {
|
||||
// If key pressed
|
||||
if (self->keyboard.keyList().size() != 0) {
|
||||
// Update states and values
|
||||
self->keyboard.updateKeysState();
|
||||
if (!self->keyboard.keysState().fn) {
|
||||
if (self->keyboard.keysState().enter) {
|
||||
data->key = LV_KEY_ENTER;
|
||||
data->state = LV_INDEV_STATE_PRESSED;
|
||||
} else if (self->keyboard.keysState().space) {
|
||||
data->key = ' ';
|
||||
data->state = LV_INDEV_STATE_PRESSED;
|
||||
} else if (self->keyboard.keysState().del) {
|
||||
data->key = LV_KEY_BACKSPACE;
|
||||
data->state = LV_INDEV_STATE_PRESSED;
|
||||
} else {
|
||||
// Normal chars
|
||||
for (auto& i : self->keyboard.keysState().values) {
|
||||
data->key = i;
|
||||
data->state = LV_INDEV_STATE_PRESSED;
|
||||
break; // We only support 1 keypress for now
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (self->keyboard.keysState().del) {
|
||||
TT_LOG_I(TAG, "del");
|
||||
data->key = LV_KEY_DEL;
|
||||
data->state = LV_INDEV_STATE_PRESSED;
|
||||
} else {
|
||||
for (auto& i : self->keyboard.keysState().values) {
|
||||
if (i == ';') { // Up
|
||||
/*
|
||||
* WARNING:
|
||||
* lv_switch picks up on this and toggles it, while the CardputerEncoder uses it for scrolling.
|
||||
* We disable the keypress so the encoder can work properly.
|
||||
*/
|
||||
// TODO: Can we detect the active widget and ignore it in case it's a switch?
|
||||
// data->key = LV_KEY_UP;
|
||||
// data->state = LV_INDEV_STATE_PRESSED;
|
||||
} else if (i == '.') { // Down
|
||||
/*
|
||||
* WARNING:
|
||||
* lv_switch picks up on this and toggles it, while the CardputerEncoder uses it for scrolling.
|
||||
* We disable the keypress so the encoder can work properly.
|
||||
*/
|
||||
// TODO: Can we detect the active widget and ignore it in case it's a switch?
|
||||
// data->key = LV_KEY_DOWN;
|
||||
// data->state = LV_INDEV_STATE_PRESSED;
|
||||
} else if (i == ',') { // Left
|
||||
data->key = LV_KEY_LEFT;
|
||||
data->state = LV_INDEV_STATE_PRESSED;
|
||||
} else if (i == '/') { // Right
|
||||
data->key = LV_KEY_RIGHT;
|
||||
data->state = LV_INDEV_STATE_PRESSED;
|
||||
} else if (i == '`') { // Escape
|
||||
data->key = LV_KEY_ESC;
|
||||
data->state = LV_INDEV_STATE_PRESSED;
|
||||
}
|
||||
|
||||
break; // We only support 1 keypress for now
|
||||
}
|
||||
}
|
||||
}
|
||||
self->lastKeyNum = self->keyboard.keyList().size();
|
||||
} else {
|
||||
self->lastKeyNum = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include <Tactility/Thread.h>
|
||||
#include <Tactility/hal/keyboard/KeyboardDevice.h>
|
||||
|
||||
#include "keyboard/keyboard.h"
|
||||
|
||||
class CardputerKeyboard : public tt::hal::keyboard::KeyboardDevice {
|
||||
KEYBOARD::Keyboard keyboard;
|
||||
int lastKeyNum = 0;
|
||||
lv_indev_t* _Nullable lvglDevice = nullptr;
|
||||
|
||||
static void readCallback(lv_indev_t* indev, lv_indev_data_t* data);
|
||||
|
||||
public:
|
||||
|
||||
std::string getName() const override { return "Cardputer Keyboard"; }
|
||||
std::string getDescription() const override { return "Cardputer internal keyboard"; }
|
||||
|
||||
bool startLvgl(lv_display_t* display) override;
|
||||
bool stopLvgl() override;
|
||||
|
||||
bool isAttached() const override { return true; }
|
||||
|
||||
lv_indev_t* _Nullable getLvglIndev() override { return lvglDevice; }
|
||||
};
|
||||
@@ -0,0 +1,85 @@
|
||||
#include "CardputerPower.h"
|
||||
|
||||
#include <Tactility/Log.h>
|
||||
#include <driver/adc.h>
|
||||
|
||||
constexpr auto* TAG = "CardputerPower";
|
||||
|
||||
bool CardputerPower::adcInitCalibration() {
|
||||
bool calibrated = false;
|
||||
|
||||
esp_err_t efuse_read_result = esp_adc_cal_check_efuse(ESP_ADC_CAL_VAL_EFUSE_TP_FIT);
|
||||
if (efuse_read_result == ESP_ERR_NOT_SUPPORTED) {
|
||||
TT_LOG_W(TAG, "Calibration scheme not supported, skip software calibration");
|
||||
} else if (efuse_read_result == ESP_ERR_INVALID_VERSION) {
|
||||
TT_LOG_W(TAG, "eFuse not burnt, skip software calibration");
|
||||
} else if (efuse_read_result == ESP_OK) {
|
||||
calibrated = true;
|
||||
TT_LOG_I(TAG, "Calibration success");
|
||||
esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_11, static_cast<adc_bits_width_t>(ADC_WIDTH_BIT_DEFAULT), 0, &adcCharacteristics);
|
||||
} else {
|
||||
TT_LOG_W(TAG, "eFuse read failed, skipping calibration");
|
||||
}
|
||||
|
||||
return calibrated;
|
||||
}
|
||||
|
||||
uint32_t CardputerPower::adcReadValue() const {
|
||||
int adc_raw = adc1_get_raw(ADC1_CHANNEL_9);
|
||||
TT_LOG_D(TAG, "Raw data: %d", adc_raw);
|
||||
float voltage;
|
||||
if (calibrated) {
|
||||
voltage = esp_adc_cal_raw_to_voltage(adc_raw, &adcCharacteristics);
|
||||
TT_LOG_D(TAG, "Calibrated data: %d mV", voltage);
|
||||
} else {
|
||||
voltage = 0.0f;
|
||||
}
|
||||
return voltage;
|
||||
}
|
||||
|
||||
bool CardputerPower::ensureInitialized() {
|
||||
if (!initialized) {
|
||||
calibrated = adcInitCalibration();
|
||||
|
||||
if (adc1_config_width(static_cast<adc_bits_width_t>(ADC_WIDTH_BIT_DEFAULT)) != ESP_OK) {
|
||||
TT_LOG_E(TAG, "ADC1 config width failed");
|
||||
return false;
|
||||
}
|
||||
if (adc1_config_channel_atten(ADC1_CHANNEL_9, ADC_ATTEN_DB_11) != ESP_OK) {
|
||||
TT_LOG_E(TAG, "ADC1 config attenuation failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CardputerPower::supportsMetric(MetricType type) const {
|
||||
switch (type) {
|
||||
using enum MetricType;
|
||||
case BatteryVoltage:
|
||||
case ChargeLevel:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool CardputerPower::getMetric(MetricType type, MetricData& data) {
|
||||
if (!ensureInitialized()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case MetricType::BatteryVoltage:
|
||||
data.valueAsUint32 = adcReadValue() * 2;
|
||||
return true;
|
||||
case MetricType::ChargeLevel:
|
||||
data.valueAsUint8 = chargeFromAdcVoltage.estimateCharge(adcReadValue() * 2);
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <Tactility/hal/power/PowerDevice.h>
|
||||
#include <ChargeFromVoltage.h>
|
||||
#include <esp_adc_cal.h>
|
||||
#include <string>
|
||||
|
||||
using tt::hal::power::PowerDevice;
|
||||
|
||||
class CardputerPower final : public PowerDevice {
|
||||
|
||||
ChargeFromVoltage chargeFromAdcVoltage = ChargeFromVoltage(3.3f, 4.2f);
|
||||
bool initialized = false;
|
||||
esp_adc_cal_characteristics_t adcCharacteristics;
|
||||
bool calibrated = false;
|
||||
|
||||
bool adcInitCalibration();
|
||||
uint32_t adcReadValue() const;
|
||||
|
||||
bool ensureInitialized();
|
||||
|
||||
public:
|
||||
|
||||
std::string getName() const override { return "Cardputer Power"; }
|
||||
std::string getDescription() const override { return "Power measurement via ADC"; }
|
||||
|
||||
bool supportsMetric(MetricType type) const override;
|
||||
bool getMetric(MetricType type, MetricData& data) override;
|
||||
};
|
||||
@@ -0,0 +1,32 @@
|
||||
#include "Display.h"
|
||||
|
||||
#include <PwmBacklight.h>
|
||||
#include <St7789Display.h>
|
||||
|
||||
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay() {
|
||||
St7789Display::Configuration panel_configuration = {
|
||||
.horizontalResolution = LCD_HORIZONTAL_RESOLUTION,
|
||||
.verticalResolution = LCD_VERTICAL_RESOLUTION,
|
||||
.gapX = 53, // Should be 52 according to https://github.com/m5stack/M5GFX/blob/master/src/M5GFX.cpp but this leaves a gap at the bottom
|
||||
.gapY = 40,
|
||||
.swapXY = true,
|
||||
.mirrorX = true,
|
||||
.mirrorY = false,
|
||||
.invertColor = true,
|
||||
.bufferSize = LCD_BUFFER_SIZE,
|
||||
.touch = nullptr,
|
||||
.backlightDutyFunction = driver::pwmbacklight::setBacklightDuty,
|
||||
.resetPin = LCD_PIN_RESET,
|
||||
.lvglSwapBytes = false
|
||||
};
|
||||
|
||||
auto spi_configuration = std::make_shared<St7789Display::SpiConfiguration>(St7789Display::SpiConfiguration {
|
||||
.spiHostDevice = LCD_SPI_HOST,
|
||||
.csPin = LCD_PIN_CS,
|
||||
.dcPin = LCD_PIN_DC,
|
||||
.pixelClockFrequency = 62'500'000,
|
||||
.transactionQueueDepth = 10
|
||||
});
|
||||
|
||||
return std::make_shared<St7789Display>(panel_configuration, spi_configuration);
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <Tactility/hal/display/DisplayDevice.h>
|
||||
#include <memory>
|
||||
#include <driver/gpio.h>
|
||||
#include <driver/spi_common.h>
|
||||
|
||||
constexpr auto LCD_SPI_HOST = SPI2_HOST;
|
||||
constexpr auto LCD_PIN_CS = GPIO_NUM_37;
|
||||
constexpr auto LCD_PIN_DC = GPIO_NUM_34; // RS
|
||||
constexpr auto LCD_PIN_RESET = GPIO_NUM_33;
|
||||
constexpr auto LCD_PIN_BACKLIGHT = GPIO_NUM_38;
|
||||
constexpr auto LCD_HORIZONTAL_RESOLUTION = 240;
|
||||
constexpr auto LCD_VERTICAL_RESOLUTION = 135;
|
||||
constexpr auto LCD_BUFFER_HEIGHT = LCD_VERTICAL_RESOLUTION / 10;
|
||||
constexpr auto LCD_BUFFER_SIZE = LCD_HORIZONTAL_RESOLUTION * LCD_BUFFER_HEIGHT;
|
||||
constexpr auto LCD_SPI_TRANSFER_SIZE_LIMIT = LCD_BUFFER_SIZE * LV_COLOR_DEPTH / 8;
|
||||
|
||||
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay();
|
||||
@@ -0,0 +1,25 @@
|
||||
#include "SdCard.h"
|
||||
|
||||
#include <Tactility/hal/sdcard/SpiSdCardDevice.h>
|
||||
|
||||
constexpr auto SDCARD_PIN_CS = GPIO_NUM_12;
|
||||
constexpr auto LCD_PIN_CS = GPIO_NUM_37;
|
||||
|
||||
using tt::hal::sdcard::SpiSdCardDevice;
|
||||
|
||||
std::shared_ptr<SdCardDevice> createSdCard() {
|
||||
auto configuration = std::make_unique<SpiSdCardDevice::Config>(
|
||||
SDCARD_PIN_CS,
|
||||
GPIO_NUM_NC,
|
||||
GPIO_NUM_NC,
|
||||
GPIO_NUM_NC,
|
||||
SdCardDevice::MountBehaviour::AtBoot,
|
||||
tt::hal::spi::getLock(SPI3_HOST),
|
||||
std::vector { LCD_PIN_CS },
|
||||
SPI3_HOST
|
||||
);
|
||||
|
||||
return std::make_shared<SpiSdCardDevice>(
|
||||
std::move(configuration)
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <Tactility/hal/sdcard/SdCardDevice.h>
|
||||
#include <memory>
|
||||
|
||||
using tt::hal::sdcard::SdCardDevice;
|
||||
|
||||
std::shared_ptr<SdCardDevice> createSdCard();
|
||||
Reference in New Issue
Block a user