mirror of
https://github.com/torlando-tech/pyxis.git
synced 2026-05-20 14:25:07 +00:00
0608af6d38
Display and LoRa were creating separate SPIClass(HSPI) instances which claimed GPIO pins via the matrix, preventing SD card (on FSPI) from accessing MISO after Display init. Now all three peripherals use the global SPI (FSPI) instance, eliminating GPIO routing conflicts. - Display: use &SPI instead of new SPIClass(HSPI) - SX1262Interface: use &SPI instead of new SPIClass(HSPI) - SDAccess: enable format_if_empty for unformatted cards Verified on device: SD (128GB SDHC), display, and LoRa all coexist. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
123 lines
3.0 KiB
C++
123 lines
3.0 KiB
C++
// Copyright (c) 2024 microReticulum contributors
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
#include "SDAccess.h"
|
|
|
|
#ifdef ARDUINO
|
|
|
|
#include <Log.h>
|
|
|
|
using namespace RNS;
|
|
|
|
namespace Hardware {
|
|
namespace TDeck {
|
|
|
|
SemaphoreHandle_t SDAccess::_spi_mutex = nullptr;
|
|
bool SDAccess::_ready = false;
|
|
|
|
bool SDAccess::init(SemaphoreHandle_t mutex) {
|
|
if (_ready) return true;
|
|
if (mutex == nullptr) {
|
|
Serial.println("[SDAccess] ERROR: null mutex");
|
|
return false;
|
|
}
|
|
|
|
_spi_mutex = mutex;
|
|
|
|
// Drive ALL SPI CS lines high to deselect other devices on the bus.
|
|
pinMode(Pin::DISPLAY_CS, OUTPUT);
|
|
digitalWrite(Pin::DISPLAY_CS, HIGH);
|
|
pinMode(Radio::LORA_CS, OUTPUT);
|
|
digitalWrite(Radio::LORA_CS, HIGH);
|
|
pinMode(SDCard::CS, OUTPUT);
|
|
digitalWrite(SDCard::CS, HIGH);
|
|
|
|
// Acquire mutex for SD.begin()
|
|
if (xSemaphoreTake(_spi_mutex, pdMS_TO_TICKS(2000)) != pdTRUE) {
|
|
Serial.println("[SDAccess] Failed to acquire SPI mutex for init");
|
|
return false;
|
|
}
|
|
|
|
// SD card init: use global SPI (FSPI) before Display claims HSPI
|
|
SPI.begin(Pin::DISPLAY_SCK, Radio::SPI_MISO, Pin::DISPLAY_MOSI);
|
|
|
|
// format_if_empty=true auto-formats unformatted cards as FAT
|
|
bool ok = SD.begin(SDCard::CS, SPI, SD_SPI_FREQ, "/sd", 5, true);
|
|
|
|
xSemaphoreGive(_spi_mutex);
|
|
|
|
if (!ok) {
|
|
Serial.println("[SDAccess] SD card mount failed (no card?)");
|
|
return false;
|
|
}
|
|
|
|
uint8_t cardType = SD.cardType();
|
|
if (cardType == CARD_NONE) {
|
|
Serial.println("[SDAccess] No SD card detected");
|
|
return false;
|
|
}
|
|
|
|
_ready = true;
|
|
|
|
const char* type_str = "UNKNOWN";
|
|
switch (cardType) {
|
|
case CARD_MMC: type_str = "MMC"; break;
|
|
case CARD_SD: type_str = "SD"; break;
|
|
case CARD_SDHC: type_str = "SDHC"; break;
|
|
default: break;
|
|
}
|
|
Serial.printf("[SDAccess] Card type: %s, size: %lluMB\n",
|
|
type_str, SD.cardSize() / (1024 * 1024));
|
|
|
|
return true;
|
|
}
|
|
|
|
int SDAccess::read_file(const char* path, uint8_t* buf, size_t max_len) {
|
|
if (!_ready || !_spi_mutex) return -1;
|
|
|
|
if (xSemaphoreTake(_spi_mutex, pdMS_TO_TICKS(500)) != pdTRUE) {
|
|
return -1;
|
|
}
|
|
|
|
File f = SD.open(path, FILE_READ);
|
|
if (!f) {
|
|
xSemaphoreGive(_spi_mutex);
|
|
return -1;
|
|
}
|
|
|
|
int bytes_read = f.read(buf, max_len);
|
|
f.close();
|
|
|
|
xSemaphoreGive(_spi_mutex);
|
|
return bytes_read;
|
|
}
|
|
|
|
bool SDAccess::file_exists(const char* path) {
|
|
if (!_ready || !_spi_mutex) return false;
|
|
|
|
if (xSemaphoreTake(_spi_mutex, pdMS_TO_TICKS(500)) != pdTRUE) {
|
|
return false;
|
|
}
|
|
|
|
bool exists = SD.exists(path);
|
|
|
|
xSemaphoreGive(_spi_mutex);
|
|
return exists;
|
|
}
|
|
|
|
bool SDAccess::acquire_bus(uint32_t timeout_ms) {
|
|
if (!_spi_mutex) return false;
|
|
return xSemaphoreTake(_spi_mutex, pdMS_TO_TICKS(timeout_ms)) == pdTRUE;
|
|
}
|
|
|
|
void SDAccess::release_bus() {
|
|
if (_spi_mutex) {
|
|
xSemaphoreGive(_spi_mutex);
|
|
}
|
|
}
|
|
|
|
} // namespace TDeck
|
|
} // namespace Hardware
|
|
|
|
#endif // ARDUINO
|