mirror of
https://github.com/justcallmekoko/ESP32Marauder.git
synced 2026-04-28 03:53:06 -07:00
Add support for the M5Stack Cardputer ADV hardware variant, which replaces the original GPIO matrix keyboard with a TCA8418 I2C keypad controller. Changes: - Vendor Adafruit_TCA8418 library for I2C keyboard communication - Add MARAUDER_CARDPUTER_ADV board target with feature flags in configs.h - Implement TCA8418 keyboard driver with interrupt-driven FIFO scanning, coordinate remapping (verified against M5Cardputer-UserDemo-ADV), and persistent key state tracking for compatibility with menu polling - Extend all MARAUDER_CARDPUTER preprocessor guards to include ADV variant - Add TFT_eSPI display configuration (same display as original Cardputer) - Add CI build matrix entries for both parallel and nightly workflows
304 lines
7.9 KiB
C++
304 lines
7.9 KiB
C++
#include "SDInterface.h"
|
|
#include "lang_var.h"
|
|
|
|
#ifdef HAS_C5_SD
|
|
SDInterface::SDInterface(SPIClass* spi, int cs)
|
|
: _spi(spi), _cs(cs) {}
|
|
#endif
|
|
|
|
bool SDInterface::initSD() {
|
|
#ifdef HAS_SD
|
|
String display_string = "";
|
|
|
|
#ifdef KIT
|
|
pinMode(SD_DET, INPUT);
|
|
if (digitalRead(SD_DET) != LOW) {
|
|
this->supported = false;
|
|
return false;
|
|
}
|
|
#endif
|
|
|
|
pinMode(SD_CS, OUTPUT);
|
|
|
|
delay(10);
|
|
#if (defined(MARAUDER_M5STICKC)) || (defined(HAS_CYD_TOUCH)) || (defined(MARAUDER_CARDPUTER)) || (defined(MARAUDER_CARDPUTER_ADV))
|
|
/* Set up SPI SD Card using external pin header
|
|
StickCPlus Header - SPI SD Card Reader
|
|
3v3 - 3v3
|
|
GND - GND
|
|
G0 - CLK
|
|
G36/G25 - MISO
|
|
G26 - MOSI
|
|
- CS (jumper to SD Card GND Pin)
|
|
*/
|
|
#if defined(MARAUDER_M5STICKC)
|
|
enum { SPI_SCK = 0, SPI_MISO = 36, SPI_MOSI = 26 };
|
|
#elif defined(HAS_CYD_TOUCH) || defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV) || defined(HAS_SEPARATE_SD)
|
|
enum { SPI_SCK = SD_SCK, SPI_MISO = SD_MISO, SPI_MOSI = SD_MOSI };
|
|
#else
|
|
enum { SPI_SCK = 0, SPI_MISO = 36, SPI_MOSI = 26 };
|
|
#endif
|
|
#if !defined(MARAUDER_CARDPUTER) && !defined(MARAUDER_CARDPUTER_ADV)
|
|
this->spiExt = new SPIClass();
|
|
#else
|
|
this->spiExt = new SPIClass(FSPI);
|
|
#endif
|
|
Serial.println(F("Using external SPI configuration..."));
|
|
this->spiExt->begin(SPI_SCK, SPI_MISO, SPI_MOSI, SD_CS);
|
|
if (!SD.begin(SD_CS, *(this->spiExt))) {
|
|
#elif defined(HAS_C5_SD)
|
|
Serial.println(F("Using C5 SD configuration..."));
|
|
if (!SD.begin(SD_CS, *_spi)) {
|
|
#else
|
|
if (!SD.begin(SD_CS)) {
|
|
#endif
|
|
Serial.println(F("Failed to mount SD Card"));
|
|
this->supported = false;
|
|
return false;
|
|
}
|
|
else {
|
|
this->supported = true;
|
|
this->cardType = SD.cardType();
|
|
|
|
this->cardSizeMB = SD.cardSize() / (1024 * 1024);
|
|
|
|
if (this->supported) {
|
|
const int NUM_DIGITS = log10(this->cardSizeMB) + 1;
|
|
|
|
char sz[NUM_DIGITS + 1];
|
|
|
|
sz[NUM_DIGITS] = 0;
|
|
for ( size_t i = NUM_DIGITS; i--; this->cardSizeMB /= 10)
|
|
{
|
|
sz[i] = '0' + (this->cardSizeMB % 10);
|
|
display_string.concat((String)sz[i]);
|
|
}
|
|
|
|
this->card_sz = sz;
|
|
}
|
|
|
|
if (!SD.exists("/SCRIPTS")) {
|
|
|
|
SD.mkdir("/SCRIPTS");
|
|
}
|
|
|
|
this->sd_files = new LinkedList<String>();
|
|
|
|
//this->sd_files->add("Back");
|
|
|
|
return true;
|
|
}
|
|
|
|
#else
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
File SDInterface::getFile(String path) {
|
|
if (this->supported) {
|
|
File file = SD.open(path, FILE_READ);
|
|
|
|
//if (file)
|
|
return file;
|
|
}
|
|
}
|
|
|
|
bool SDInterface::removeFile(String file_path) {
|
|
if (SD.remove(file_path))
|
|
return true;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
void SDInterface::listDirToLinkedList(LinkedList<String>* file_names, String str_dir, String ext) {
|
|
if (this->supported) {
|
|
File dir = SD.open(str_dir);
|
|
while (true)
|
|
{
|
|
File entry = dir.openNextFile();
|
|
if (!entry)
|
|
{
|
|
break;
|
|
}
|
|
|
|
if (entry.isDirectory())
|
|
continue;
|
|
|
|
String file_name = entry.name();
|
|
if (ext != "") {
|
|
if (file_name.endsWith(ext)) {
|
|
file_names->add(file_name);
|
|
}
|
|
}
|
|
else
|
|
file_names->add(file_name);
|
|
}
|
|
}
|
|
}
|
|
|
|
void SDInterface::listDir(String str_dir){
|
|
if (this->supported) {
|
|
File dir = SD.open(str_dir);
|
|
while (true)
|
|
{
|
|
File entry = dir.openNextFile();
|
|
if (! entry)
|
|
{
|
|
break;
|
|
}
|
|
//for (uint8_t i = 0; i < numTabs; i++)
|
|
//{
|
|
// Serial.print('\t');
|
|
//}
|
|
Serial.print(entry.name());
|
|
Serial.print("\t");
|
|
Serial.println(entry.size());
|
|
entry.close();
|
|
}
|
|
}
|
|
}
|
|
|
|
void SDInterface::runUpdate(String file_name) {
|
|
if (file_name == "")
|
|
file_name = "/update.bin";
|
|
|
|
#ifdef HAS_SCREEN
|
|
display_obj.tft.setTextWrap(false);
|
|
display_obj.tft.setFreeFont(NULL);
|
|
display_obj.tft.setCursor(0, TFT_HEIGHT / 3);
|
|
display_obj.tft.setTextSize(1);
|
|
display_obj.tft.setTextColor(TFT_WHITE);
|
|
|
|
display_obj.tft.println("Opening " + file_name + "...");
|
|
#endif
|
|
|
|
File updateBin = SD.open(file_name);
|
|
|
|
if (updateBin) {
|
|
if(updateBin.isDirectory()){
|
|
#ifdef HAS_SCREEN
|
|
display_obj.tft.setTextColor(TFT_RED);
|
|
display_obj.tft.println(F(text_table2[0]));
|
|
#endif
|
|
Serial.print(F("Error, could not find \""));
|
|
Serial.print(file_name);
|
|
Serial.println(F("\""));
|
|
#ifdef HAS_SCREEN
|
|
display_obj.tft.setTextColor(TFT_WHITE);
|
|
#endif
|
|
updateBin.close();
|
|
return;
|
|
}
|
|
|
|
size_t updateSize = updateBin.size();
|
|
|
|
if (updateSize > 0) {
|
|
#ifdef HAS_SCREEN
|
|
display_obj.tft.println(F(text_table2[1]));
|
|
#endif
|
|
Serial.println(F("Starting update over SD. Please wait..."));
|
|
this->performUpdate(updateBin, updateSize);
|
|
}
|
|
else {
|
|
#ifdef HAS_SCREEN
|
|
display_obj.tft.setTextColor(TFT_RED);
|
|
display_obj.tft.println(F(text_table2[2]));
|
|
#endif
|
|
Serial.println(F("Error, file is empty"));
|
|
#ifdef HAS_SCREEN
|
|
display_obj.tft.setTextColor(TFT_WHITE);
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
updateBin.close();
|
|
|
|
// whe finished remove the binary from sd card to indicate end of the process
|
|
#ifdef HAS_SCREEN
|
|
display_obj.tft.println(F(text_table2[3]));
|
|
#endif
|
|
const esp_partition_t *running = esp_ota_get_running_partition();
|
|
|
|
const esp_partition_t *next = esp_ota_get_next_update_partition(NULL);
|
|
|
|
esp_err_t result = esp_ota_set_boot_partition(next);
|
|
|
|
Serial.println(F("rebooting..."));
|
|
//SD.remove("/update.bin");
|
|
delay(1000);
|
|
ESP.restart();
|
|
}
|
|
else {
|
|
#ifdef HAS_SCREEN
|
|
display_obj.tft.setTextColor(TFT_RED);
|
|
display_obj.tft.println(F(text_table2[4]));
|
|
#endif
|
|
Serial.println(F("Could not load update.bin from sd root"));
|
|
#ifdef HAS_SCREEN
|
|
display_obj.tft.setTextColor(TFT_WHITE);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void SDInterface::performUpdate(Stream &updateSource, size_t updateSize) {
|
|
if (Update.begin(updateSize)) {
|
|
#ifdef HAS_SCREEN
|
|
display_obj.tft.println(text_table2[5] + String(updateSize));
|
|
display_obj.tft.println(F(text_table2[6]));
|
|
#endif
|
|
size_t written = Update.writeStream(updateSource);
|
|
if (written == updateSize) {
|
|
#ifdef HAS_SCREEN
|
|
display_obj.tft.println(text_table2[7] + String(written) + text_table2[10]);
|
|
#endif
|
|
Serial.print(F("Written : "));
|
|
Serial.print(written);
|
|
Serial.println(F(" successfully"));
|
|
}
|
|
else {
|
|
#ifdef HAS_SCREEN
|
|
display_obj.tft.println(text_table2[8] + String(written) + "/" + String(updateSize) + text_table2[9]);
|
|
#endif
|
|
Serial.print(F("Written only : "));
|
|
Serial.print(written);
|
|
Serial.print(F("/"));
|
|
Serial.print(updateSize);
|
|
Serial.println(F(". Retry?"));
|
|
}
|
|
if (Update.end()) {
|
|
Serial.println(F("OTA done!"));
|
|
if (Update.isFinished()) {
|
|
#ifdef HAS_SCREEN
|
|
display_obj.tft.println(F(text_table2[11]));
|
|
#endif
|
|
Serial.println(F("Update successfully completed. Rebooting."));
|
|
}
|
|
else {
|
|
#ifdef HAS_SCREEN
|
|
display_obj.tft.setTextColor(TFT_RED);
|
|
display_obj.tft.println(text_table2[12]);
|
|
#endif
|
|
Serial.println(F("Update not finished? Something went wrong!"));
|
|
#ifdef HAS_SCREEN
|
|
display_obj.tft.setTextColor(TFT_WHITE);
|
|
#endif
|
|
}
|
|
}
|
|
else {
|
|
#ifdef HAS_SCREEN
|
|
display_obj.tft.println(text_table2[13] + String(Update.getError()));
|
|
#endif
|
|
Serial.print(F("Error Occurred. Error #: "));
|
|
Serial.println(Update.getError());
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
#ifdef HAS_SCREEN
|
|
display_obj.tft.println(text_table2[14]);
|
|
#endif
|
|
Serial.println(F("Not enough space to begin OTA"));
|
|
}
|
|
}
|