Files
TTGO_TWatch_Library/src/LilyGoLib.cpp
2023-11-22 19:18:39 +01:00

601 lines
16 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* @file LilyGoLib.cpp
* @author Lewis He (lewishe@outlook.com)
* @license MIT
* @copyright Copyright (c) 2023 Shenzhen Xinyuan Electronic Technology Co., Ltd
* @date 2023-04-28
*
*/
#include "LilyGoLib.h"
#ifdef USING_TWATCH_S3
SPIClass radioBus = SPIClass(HSPI);
#endif
void deviceScan(TwoWire *_port, Stream *stream)
{
uint8_t err, addr;
int nDevices = 0;
for (addr = 1; addr < 127; addr++) {
_port->beginTransmission(addr);
err = _port->endTransmission();
if (err == 0) {
stream->print("I2C device found at address 0x");
if (addr < 16)
stream->print("0");
stream->print(addr, HEX);
stream->println(" !");
nDevices++;
} else if (err == 4) {
stream->print("Unknow error at address 0x");
if (addr < 16)
stream->print("0");
stream->println(addr, HEX);
}
}
if (nDevices == 0)
stream->println("No I2C devices found\n");
else
stream->println("Done\n");
}
LilyGoLib::LilyGoLib()
#ifdef USING_TWATCH_S3
: SX1262(new Module(BOARD_RADIO_SS,
BOARD_RADIO_DI01,
BOARD_RADIO_RST,
BOARD_RADIO_BUSY,
radioBus))
#endif
{
//Default use SX1262
}
LilyGoLib::~LilyGoLib()
{
}
void LilyGoLib::log_println(const char *message)
{
if (stream) {
stream->println(message);
}
}
bool LilyGoLib::begin(Stream *stream)
{
bool res;
#ifdef LILYGO_LIB_DEBUG
this->stream = &Serial;
#else
this->stream = stream;
#endif
pinMode(BOARD_TOUCH_INT, INPUT);
Wire.begin(BOARD_I2C_SDA, BOARD_I2C_SCL);
if (stream) {
deviceScan(&Wire, stream);
}
Wire1.begin(BOARD_TOUCH_SDA, BOARD_TOUCH_SCL);
if (stream) {
deviceScan(&Wire1, stream);
}
log_println("Init PMU");
if (!beginPower()) {
log_println("Failed to find PMU - check your wiring!");
return false;
} else {
log_println("Initializing PMU succeeded");
}
log_println("Init LEDC");
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)
ledcAttach(BOARD_TFT_BL, LEDC_BACKLIGHT_FREQ, LEDC_BACKLIGHT_BIT_WIDTH);
#else
ledcSetup(LEDC_BACKLIGHT_CHANNEL, LEDC_BACKLIGHT_FREQ, LEDC_BACKLIGHT_BIT_WIDTH);
ledcAttachPin(BOARD_TFT_BL, LEDC_BACKLIGHT_CHANNEL);
#endif
log_println("Init TFT");
TFT_eSPI::init();
setRotation(2);
setTextDatum(MC_DATUM);
setTextFont(2);
log_println("Init SPIFFS");
if (!SPIFFS.begin()) {
fillScreen(TFT_BLACK);
setBrightness(50);
drawString("Format SPIFFS...", 120, 120);
SPIFFS.format();
}
fillScreen(TFT_BLACK);
drawString("Hello T-Watch", 120, 120);
setBrightness(50);
log_println("Init Touch");
res = TouchDrvFT6X36::init(Wire1, BOARD_TOUCH_SDA, BOARD_TOUCH_SCL);
if (!res) {
log_println("Failed to find FT6X36 - check your wiring!");
} else {
log_println("Initializing FT6X36 succeeded");
interruptTrigger(); //enable Interrupt
}
log_println("Init BMA423");
res = SensorBMA423::init(Wire);
if (!res) {
log_println("Failed to find BMA423 - check your wiring!");
} else {
log_println("Initializing BMA423 succeeded");
setReampAxes(REMAP_BOTTOM_LAYER_TOP_RIGHT_CORNER);
setStepCounterWatermark(1);
}
log_println("Init PCF8563 RTC");
res = SensorPCF8563::init(Wire);
if (!res) {
log_println("Failed to find PCF8563 - check your wiring!");
} else {
log_println("Initializing PCF8563 succeeded");
disableCLK(); //Disable clock output Conserve Backup Battery Current Consumption
hwClockRead(); //Synchronize RTC clock to system clock
}
log_println("Init DRV2605");
res = SensorDRV2605::init(Wire);
if (!res) {
log_println("Failed to find DRV2605 - check your wiring!");
} else {
log_println("Initializing DRV2605 succeeded");
SensorDRV2605::selectLibrary(1);
SensorDRV2605::setMode(DRV2605_MODE_INTTRIG);
SensorDRV2605::useERM();
SensorDRV2605::setWaveform(0, 15); // play effect
SensorDRV2605::setWaveform(1, 0); // end waveform
SensorDRV2605::run();
}
#ifdef USING_TWATCH_S3
log_println("Init Radio");
radioBus.begin(BOARD_RADIO_SCK,
BOARD_RADIO_MISO,
BOARD_RADIO_MOSI);
//Using default params433Mhz,bw:125k,sf:9,cr:7,syncword:18,txpower:10
if (SX1262::begin() == RADIOLIB_ERR_NONE) {
log_println("Initializing Radio succeeded");
} else {
log_println("Failed to find Radio - check your wiring!");
}
#endif
beginCore();
delay(1000);
return true;
}
void LilyGoLib::beginCore()
{
// https://docs.espressif.com/projects/esp-idf/zh_CN/v4.4.4/esp32s3/api-reference/peripherals/temp_sensor.html
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5,0,0)
temp_sensor_config_t temp_sensor = {
.dac_offset = TSENS_DAC_L2,
.clk_div = 6,
};
temp_sensor_set_config(temp_sensor);
temp_sensor_start();
#else
// https://docs.espressif.com/projects/esp-idf/zh_CN/v5.0.1/esp32s3/api-reference/peripherals/temp_sensor.html
static temperature_sensor_config_t temp_sensor_config = TEMPERATURE_SENSOR_CONFIG_DEFAULT(10, 50);
temperature_sensor_install(&temp_sensor_config, &temp_sensor);
temperature_sensor_enable(temp_sensor);
#endif
}
void LilyGoLib::attachPMU(void(*cb)(void))
{
pinMode(BOARD_PMU_INT, INPUT_PULLUP);
attachInterrupt(BOARD_PMU_INT, cb, FALLING);
}
void LilyGoLib::attachBMA(void(*cb)(void))
{
pinMode(BOARD_BMA423_INT1, INPUT_PULLUP);
attachInterrupt(BOARD_BMA423_INT1, cb, RISING);
}
void LilyGoLib::attachRTC(void(*cb)(void))
{
pinMode(BOARD_RTC_INT_PIN, INPUT_PULLUP);
attachInterrupt(BOARD_RTC_INT_PIN, cb, RISING);
}
uint16_t LilyGoLib::readBMA()
{
return SensorBMA423::readIrqStatus();
}
uint64_t LilyGoLib::readPMU()
{
#ifdef USING_TWATCH_S3
return XPowersAXP2101::getIrqStatus();
#else
return XPowersAXP202::getIrqStatus();
#endif
}
void LilyGoLib::clearPMU()
{
#ifdef USING_TWATCH_S3
XPowersAXP2101::clearIrqStatus();
#else
XPowersAXP202::clearIrqStatus();
#endif
}
bool LilyGoLib::readRTC()
{
return digitalRead(BOARD_RTC_INT_PIN) == LOW;
}
float LilyGoLib::readAccelTemp()
{
return SensorBMA423::getTemperature(SensorBMA423::TEMP_DEG);
}
float LilyGoLib::readCoreTemp()
{
float tsens_value;
// https://docs.espressif.com/projects/esp-idf/zh_CN/v4.4.4/esp32s3/api-reference/peripherals/temp_sensor.html
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5,0,0)
temp_sensor_read_celsius(&tsens_value);
#else
// https://docs.espressif.com/projects/esp-idf/zh_CN/v5.0.1/esp32s3/api-reference/peripherals/temp_sensor.html
temperature_sensor_get_celsius(temp_sensor, &tsens_value);
#endif
return tsens_value;
}
bool LilyGoLib::getTouched()
{
return digitalRead(BOARD_TOUCH_INT) == LOW;
}
uint8_t LilyGoLib::getBrightness()
{
return brightness;
}
void LilyGoLib::setBrightness(uint8_t level)
{
if (!level) {
disableALDO2();
writecommand(0x10); //display sleep
setPowerMode(PMODE_MONITOR);
}
if (!brightness && level != 0) {
enableALDO2();
writecommand(0x11); //display wakeup
}
brightness = level;
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0)
ledcWrite(BOARD_TFT_BL, brightness);
#else
ledcWrite(LEDC_BACKLIGHT_CHANNEL, brightness);
#endif
}
void LilyGoLib::decrementBrightness(uint8_t target_level, uint32_t delay_ms)
{
if (target_level > brightness)
return;
for (int i = brightness; i >= target_level; i--) {
setBrightness(i);
delay(delay_ms);
}
}
void LilyGoLib::incrementalBrightness(uint8_t target_level, uint32_t delay_ms)
{
if (target_level < brightness)
return;
for (int i = brightness; i < target_level; i++) {
setBrightness(i);
delay(delay_ms);
}
}
bool LilyGoLib::beginPower()
{
#ifdef USING_TWATCH_S3
bool res = XPowersAXP2101::init(Wire, BOARD_I2C_SDA, BOARD_I2C_SCL);
if (!res) {
return false;
}
// Set the minimum common working voltage of the PMU VBUS input,
// below this value will turn off the PMU
setVbusVoltageLimit(XPOWERS_AXP2101_VBUS_VOL_LIM_4V36);
// Set the maximum current of the PMU VBUS input,
// higher than this value will turn off the PMU
setVbusCurrentLimit(XPOWERS_AXP2101_VBUS_CUR_LIM_100MA);
// Set VSY off voltage as 2600mV , Adjustment range 2600mV ~ 3300mV
setSysPowerDownVoltage(2600);
// ! ESP32S3 VDD, Don't change
// setDC1Voltage(3300);
//! RTC VBAT , Don't change
setALDO1Voltage(3300);
//! TFT BACKLIGHT VDD , Don't change
setALDO2Voltage(3300);
//!Screen touch VDD , Don't change
setALDO3Voltage(3300);
//! Radio VDD , Don't change
setALDO4Voltage(3300);
//!DRV2605 enable
setBLDO2Voltage(3300);
//! No use
disableDC2();
disableDC3();
disableDC4();
disableDC5();
disableBLDO1();
disableCPUSLDO();
disableDLDO1();
disableDLDO2();
enableALDO1(); //! RTC VBAT
enableALDO2(); //! TFT BACKLIGHT VDD
enableALDO3(); //! Screen touch VDD
enableALDO4(); //! Radio VDD
enableBLDO2(); //! drv2605 enable
if (stream) {
log_println("DCDC=======================================================================");
stream->printf("DC1 : %s Voltage:%u mV \n", isEnableDC1() ? "+" : "-", getDC1Voltage());
stream->printf("DC2 : %s Voltage:%u mV \n", isEnableDC2() ? "+" : "-", getDC2Voltage());
stream->printf("DC3 : %s Voltage:%u mV \n", isEnableDC3() ? "+" : "-", getDC3Voltage());
stream->printf("DC4 : %s Voltage:%u mV \n", isEnableDC4() ? "+" : "-", getDC4Voltage());
stream->printf("DC5 : %s Voltage:%u mV \n", isEnableDC5() ? "+" : "-", getDC5Voltage());
log_println("ALDO=======================================================================");
stream->printf("ALDO1: %s Voltage:%u mV\n", isEnableALDO1() ? "+" : "-", getALDO1Voltage());
stream->printf("ALDO2: %s Voltage:%u mV\n", isEnableALDO2() ? "+" : "-", getALDO2Voltage());
stream->printf("ALDO3: %s Voltage:%u mV\n", isEnableALDO3() ? "+" : "-", getALDO3Voltage());
stream->printf("ALDO4: %s Voltage:%u mV\n", isEnableALDO4() ? "+" : "-", getALDO4Voltage());
log_println("BLDO=======================================================================");
stream->printf("BLDO1: %s Voltage:%u mV\n", isEnableBLDO1() ? "+" : "-", getBLDO1Voltage());
stream->printf("BLDO2: %s Voltage:%u mV\n", isEnableBLDO2() ? "+" : "-", getBLDO2Voltage());
log_println("CPUSLDO====================================================================");
stream->printf("CPUSLDO: %s Voltage:%u mV\n", isEnableCPUSLDO() ? "+" : "-", getCPUSLDOVoltage());
log_println("DLDO=======================================================================");
stream->printf("DLDO1: %s Voltage:%u mV\n", isEnableDLDO1() ? "+" : "-", getDLDO1Voltage());
stream->printf("DLDO2: %s Voltage:%u mV\n", isEnableDLDO2() ? "+" : "-", getDLDO2Voltage());
log_println("===========================================================================");
}
// Set the time of pressing the button to turn off
setPowerKeyPressOffTime(XPOWERS_POWEROFF_4S);
// Set the button power-on press time
setPowerKeyPressOnTime(XPOWERS_POWERON_128MS);
// It is necessary to disable the detection function of the TS pin on the board
// without the battery temperature detection function, otherwise it will cause abnormal charging
disableTSPinMeasure();
// Enable internal ADC detection
enableBattDetection();
enableVbusVoltageMeasure();
enableBattVoltageMeasure();
enableSystemVoltageMeasure();
//t-watch no chg led
setChargingLedMode(XPOWERS_CHG_LED_OFF);
disableIRQ(XPOWERS_AXP2101_ALL_IRQ);
// Clear all interrupt flags
XPowersAXP2101::clearIrqStatus();
// Enable the required interrupt function
watch.enableIRQ(
XPOWERS_AXP2101_BAT_INSERT_IRQ | XPOWERS_AXP2101_BAT_REMOVE_IRQ | //BATTERY
XPOWERS_AXP2101_VBUS_INSERT_IRQ | XPOWERS_AXP2101_VBUS_REMOVE_IRQ | //VBUS
XPOWERS_AXP2101_PKEY_SHORT_IRQ | XPOWERS_AXP2101_PKEY_LONG_IRQ | //POWER KEY
XPOWERS_AXP2101_BAT_CHG_DONE_IRQ | XPOWERS_AXP2101_BAT_CHG_START_IRQ //CHARGE
);
// Set the precharge charging current
setPrechargeCurr(XPOWERS_AXP2101_PRECHARGE_50MA);
// Set constant current charge current limit
setChargerConstantCurr(XPOWERS_AXP2101_CHG_CUR_100MA);
// Set stop charging termination current
setChargerTerminationCurr(XPOWERS_AXP2101_CHG_ITERM_25MA);
// Set charge cut-off voltage
setChargeTargetVoltage(XPOWERS_AXP2101_CHG_VOL_4V35);
// Set RTC Battery voltage to 3.3V
setButtonBatteryChargeVoltage(3300);
enableButtonBatteryCharge();
#else
bool res = XPowersAXP202::init(Wire);
if (!res) {
return false;
}
//In the 2020V1 version, the ST7789 chip power supply
//is shared with the backlight, so LDO2 cannot be turned off
setLDO2Voltage(3300);
enableLDO2();
#endif
return true;
}
void LilyGoLib::lowPower()
{
// disableALDO1(); //! RTC VBAT
// disableALDO2(); //! TFT BACKLIGHT VDD
// disableALDO3(); //! Screen touch VDD
// disableALDO4(); //! Radio VDD
// disableBLDO2(); //! drv2605 enable
}
void LilyGoLib::highPower()
{
// enableALDO1(); //! RTC VBAT
// enableALDO2(); //! TFT BACKLIGHT VDD
// enableALDO3(); //! Screen touch VDD
// enableALDO4(); //! Radio VDD
// enableBLDO2(); //! drv2605 enable
}
bool LilyGoLib::initMicrophone()
{
static i2s_config_t i2s_config = {
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_PDM),
.sample_rate = MIC_I2S_SAMPLE_RATE,
.bits_per_sample = MIC_I2S_BITS_PER_SAMPLE,
.channel_format = I2S_CHANNEL_FMT_ONLY_RIGHT,
.communication_format = I2S_COMM_FORMAT_STAND_PCM_SHORT,
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
.dma_buf_count = 6,
.dma_buf_len = 512,
.use_apll = true
};
static i2s_pin_config_t i2s_cfg = {0};
i2s_cfg.bck_io_num = I2S_PIN_NO_CHANGE;
i2s_cfg.ws_io_num = BOARD_MIC_CLOCK;
i2s_cfg.data_out_num = I2S_PIN_NO_CHANGE;
i2s_cfg.data_in_num = BOARD_MIC_DATA;
i2s_cfg.mck_io_num = I2S_PIN_NO_CHANGE;
if (i2s_driver_install(MIC_I2S_PORT, &i2s_config, 0, NULL) != ESP_OK) {
log_println("i2s_driver_install error");
return false;
}
if (i2s_set_pin(MIC_I2S_PORT, &i2s_cfg) != ESP_OK) {
log_println("i2s_set_pin error");
return false;
}
log_println("Microphone init done .");
return true;
}
bool LilyGoLib::readMicrophone(void *dest, size_t size, size_t *bytes_read, TickType_t ticks_to_wait)
{
return i2s_read(MIC_I2S_PORT, dest, size, bytes_read, ticks_to_wait) == ESP_OK;
}
void LilyGoLib::setSleepMode(SleepMode_t mode)
{
sleepMode = mode;
}
void LilyGoLib::sleepLora(bool config)
{
#ifdef USING_TWATCH_S3
SX126x::sleep(config);
#endif
}
void LilyGoLib::sleep(uint32_t second)
{
// SX126x::sleep();
// // SensorBMA423::sleep();
// TouchDrvFT6X36::setPowerMode(PMODE_DEEPSLEEP);
switch (sleepMode) {
case PMU_BTN_WAKEUP:
esp_sleep_enable_ext1_wakeup(_BV(BOARD_PMU_INT), ESP_EXT1_WAKEUP_ALL_LOW);
break;
case ESP_TIMER_WAKEUP:
esp_sleep_enable_timer_wakeup(1000000ULL * second);
break;
case SENSOR_WAKEUP:
esp_sleep_enable_ext1_wakeup(_BV(BOARD_BMA423_INT1), ESP_EXT1_WAKEUP_ANY_HIGH);
break;
case RTC_WAKEUP:
esp_sleep_enable_ext1_wakeup(_BV(BOARD_RTC_INT_PIN), ESP_EXT1_WAKEUP_ALL_LOW);
break;
case TOUCH_WAKEUP:
esp_sleep_enable_ext1_wakeup(_BV(BOARD_TOUCH_INT), ESP_EXT1_WAKEUP_ALL_LOW);
break;
default:
break;
}
esp_deep_sleep_start();
}
LilyGoLib watch;