mirror of
https://github.com/alexhopeoconnor/firmware.git
synced 2026-10-21 18:52:36 +10:00
Merge branch 'develop' into pioarduino (resolve conflicts favoring pioarduino)
Co-authored-by: vidplace7 <1779290+vidplace7@users.noreply.github.com>
This commit is contained in:
@@ -8,20 +8,127 @@
|
||||
|
||||
CSE_CST328 tsPanel = CSE_CST328(EINK_WIDTH, EINK_HEIGHT, &Wire, CST328_PIN_RST, CST328_PIN_INT);
|
||||
|
||||
static bool is_cst3530 = false;
|
||||
volatile bool touch_isr = false;
|
||||
#define CST3530_ADDR 0x1A
|
||||
|
||||
bool read_cst3530_touch(int16_t *x, int16_t *y)
|
||||
{
|
||||
uint8_t buffer[9] = {0};
|
||||
uint8_t r_cmd[] = {0xD0, 0x07, 0x00, 0x00};
|
||||
uint8_t clear_cmd[] = {0xD0, 0x00, 0x02, 0xAB};
|
||||
|
||||
Wire.beginTransmission(CST3530_ADDR);
|
||||
Wire.write(r_cmd, sizeof(r_cmd));
|
||||
if (Wire.endTransmission() != 0) {
|
||||
LOG_DEBUG("CST3530 I2C send addr failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
int read_len = Wire.requestFrom((int)CST3530_ADDR, sizeof(buffer));
|
||||
if (read_len != sizeof(buffer)) {
|
||||
LOG_DEBUG("CST3530 read len error: %d (expect 9)", read_len);
|
||||
return false;
|
||||
}
|
||||
int actual_read = Wire.readBytes(buffer, sizeof(buffer));
|
||||
if (actual_read != sizeof(buffer)) {
|
||||
LOG_DEBUG("CST3530 read bytes error: %d (expect 9)", actual_read);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t report_typ = buffer[2];
|
||||
if (report_typ != 0xFF) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t touch_points = buffer[3] & 0x0F;
|
||||
if (touch_points == 0 || touch_points > 1) {
|
||||
LOG_DEBUG("CST3530 touch points invalid: %d", touch_points);
|
||||
return false;
|
||||
}
|
||||
|
||||
*x = buffer[4] + ((uint16_t)(buffer[7] & 0x0F) << 8);
|
||||
*y = buffer[5] + ((uint16_t)(buffer[7] & 0xF0) << 4);
|
||||
|
||||
// LOG_DEBUG("CST3530 touch: num:%d x=%d,y=%d", touch_points, *x, *y);
|
||||
|
||||
Wire.beginTransmission(CST3530_ADDR);
|
||||
Wire.write(clear_cmd, sizeof(clear_cmd));
|
||||
if (Wire.endTransmission() != 0) {
|
||||
LOG_DEBUG("CST3530 clear cmd failed");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool readTouch(int16_t *x, int16_t *y)
|
||||
{
|
||||
if (tsPanel.getTouches()) {
|
||||
*x = tsPanel.getPoint(0).x;
|
||||
*y = tsPanel.getPoint(0).y;
|
||||
return true;
|
||||
|
||||
if (is_cst3530) {
|
||||
if (touch_isr) {
|
||||
touch_isr = false;
|
||||
return read_cst3530_touch(x, y);
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
if (tsPanel.getTouches()) {
|
||||
*x = tsPanel.getPoint(0).x;
|
||||
*y = tsPanel.getPoint(0).y;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void IRAM_ATTR touchInterruptHandler()
|
||||
{
|
||||
touch_isr = true;
|
||||
}
|
||||
|
||||
// T-Deck Pro specific init
|
||||
void lateInitVariant()
|
||||
{
|
||||
tsPanel.begin();
|
||||
// Reset touch
|
||||
pinMode(CST328_PIN_RST, OUTPUT);
|
||||
digitalWrite(CST328_PIN_RST, HIGH);
|
||||
delay(20);
|
||||
digitalWrite(CST328_PIN_RST, LOW);
|
||||
delay(80);
|
||||
digitalWrite(CST328_PIN_RST, HIGH);
|
||||
delay(20);
|
||||
|
||||
int retry = 5;
|
||||
uint8_t buffer[7];
|
||||
uint8_t r_cmd[] = {0x0d0, 0x03, 0x00, 0x00};
|
||||
|
||||
// Probe touch chip
|
||||
while (retry--) {
|
||||
Wire.beginTransmission(CST3530_ADDR);
|
||||
Wire.write(r_cmd, sizeof(r_cmd));
|
||||
if (Wire.endTransmission() == 0) {
|
||||
Wire.requestFrom((int)CST3530_ADDR, 7);
|
||||
Wire.readBytes(buffer, 7);
|
||||
if (buffer[2] == 0xCA && buffer[3] == 0xCA) {
|
||||
LOG_DEBUG("CST3530 detected");
|
||||
is_cst3530 = true;
|
||||
|
||||
// The CST3530 will automatically enter sleep mode;
|
||||
// polling should not be used, but rather an interrupt method should be employed.
|
||||
pinMode(CST328_PIN_INT, INPUT);
|
||||
attachInterrupt(digitalPinToInterrupt(CST328_PIN_INT), touchInterruptHandler, FALLING);
|
||||
|
||||
break;
|
||||
} else {
|
||||
LOG_DEBUG("CST3530 not response ~!");
|
||||
}
|
||||
}
|
||||
uint8_t cmd1[] = {0xD0, 0x00, 0x04, 0x00};
|
||||
Wire.beginTransmission(CST3530_ADDR);
|
||||
Wire.write(cmd1, sizeof(cmd1));
|
||||
Wire.endTransmission();
|
||||
delay(50);
|
||||
}
|
||||
|
||||
touchScreenImpl1 = new TouchScreenImpl1(EINK_WIDTH, EINK_HEIGHT, readTouch);
|
||||
touchScreenImpl1->init();
|
||||
}
|
||||
|
||||
@@ -182,6 +182,10 @@ void portduinoSetup()
|
||||
// Force stdout to be line buffered
|
||||
setvbuf(stdout, stdoutBuffer, _IOLBF, sizeof(stdoutBuffer));
|
||||
|
||||
// We do this super early so that we can log from the rest of the init code
|
||||
concurrency::hasBeenSetup = true;
|
||||
consoleInit();
|
||||
|
||||
if (portduino_config.force_simradio == true) {
|
||||
portduino_config.lora_module = use_simradio;
|
||||
} else if (configPath != nullptr) {
|
||||
@@ -650,7 +654,9 @@ void portduinoSetup()
|
||||
if (verboseEnabled && portduino_config.logoutputlevel != level_trace) {
|
||||
portduino_config.logoutputlevel = level_debug;
|
||||
}
|
||||
|
||||
if (portduino_config.lora_spi_dev != "") {
|
||||
portduinoSetOptions({.realHardware = true});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,57 @@
|
||||
#include <stm32wle5xx.h>
|
||||
#include <stm32wlxx_hal.h>
|
||||
|
||||
// ─── Bootloader redirect ──────────────────────────────────────────────────────
|
||||
//
|
||||
// Why .noinit + constructor instead of TAMP backup registers:
|
||||
//
|
||||
// The STM32duino startup sequence initialises clocks which may call
|
||||
// __HAL_RCC_BACKUPRESET_FORCE/RELEASE when configuring the LSE oscillator,
|
||||
// wiping the entire backup domain (including TAMP->BKP0R) before setup()
|
||||
// ever runs. The backup-register approach therefore cannot reliably survive
|
||||
// a soft reset in this toolchain.
|
||||
//
|
||||
// Solution: store the magic in a .noinit SRAM variable.
|
||||
// - NVIC_SystemReset() does NOT clear SRAM.
|
||||
// - The linker script skips zero-init for .noinit sections.
|
||||
// - __attribute__((constructor)) fires before main()/HAL_Init(), so we can
|
||||
// intercept and jump before anything disturbs peripheral state.
|
||||
|
||||
#define BOOTLOADER_MAGIC 0xD00DB007UL
|
||||
#define SYS_MEM_BASE 0x1FFF0000UL
|
||||
|
||||
// Placed in .noinit — not zeroed at startup, survives NVIC_SystemReset().
|
||||
__attribute__((section(".noinit"), used)) volatile uint32_t g_bootloaderMagic;
|
||||
|
||||
// Fires before main() / HAL_Init(). Must use only core Cortex-M registers.
|
||||
__attribute__((constructor(101), used)) static void earlyBootCheck(void)
|
||||
{
|
||||
if (g_bootloaderMagic != BOOTLOADER_MAGIC)
|
||||
return;
|
||||
g_bootloaderMagic = 0;
|
||||
|
||||
SysTick->CTRL = 0;
|
||||
SysTick->LOAD = 0;
|
||||
SysTick->VAL = 0;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
NVIC->ICER[i] = 0xFFFFFFFF;
|
||||
NVIC->ICPR[i] = 0xFFFFFFFF;
|
||||
}
|
||||
__DSB();
|
||||
__ISB();
|
||||
SCB->VTOR = SYS_MEM_BASE;
|
||||
__set_MSP(*(volatile uint32_t *)SYS_MEM_BASE);
|
||||
((void (*)(void))(*(volatile uint32_t *)(SYS_MEM_BASE + 4)))();
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
void enterDfuMode()
|
||||
{
|
||||
g_bootloaderMagic = BOOTLOADER_MAGIC;
|
||||
HAL_NVIC_SystemReset();
|
||||
}
|
||||
|
||||
void setBluetoothEnable(bool enable) {}
|
||||
|
||||
void playStartMelody() {}
|
||||
|
||||
Reference in New Issue
Block a user