[ai] refactoring, fixes, still a directory problem
This commit is contained in:
parent
33701636af
commit
dc735c044f
150
src/main.cpp
150
src/main.cpp
|
|
@ -18,73 +18,16 @@
|
|||
#include <esp_system.h>
|
||||
#endif
|
||||
|
||||
// define pins for RFID
|
||||
#define CS_RFID 32 // SIC, tried 4 and 32 but only this worked!
|
||||
#define RST_RFID 33
|
||||
// this does not work as the irq pin is input only:
|
||||
#define IRQ_RFID 34
|
||||
|
||||
// Audio DAC
|
||||
#define I2S_DOUT 26 // connect to DAC pin DIN
|
||||
#define I2S_BCLK 27 // connect to DAC pin BCK
|
||||
#define I2S_LRC 25 // connect to DAC pin LCK
|
||||
|
||||
#define BTN_START_STOP 4 // Button on XX and GND
|
||||
#define BTN_NEXT 17
|
||||
#define BTN_PREV 16
|
||||
|
||||
#define CS_SDCARD 22
|
||||
|
||||
#define BAT_VOLTAGE_PIN 35
|
||||
|
||||
#define RFID_LOOP_INTERVAL 25
|
||||
|
||||
#define VOLTAGE_LOOP_INTERVAL 5000
|
||||
|
||||
#define VOLTAGE_THRESHOLD 0
|
||||
|
||||
#define SHORT_PRESS_TIME 250
|
||||
|
||||
#define LONG_PRESS_TIME 1000
|
||||
|
||||
#define MAX_VOL 15
|
||||
#include <vector>
|
||||
|
||||
#include "globals.h"
|
||||
#include "main.h"
|
||||
#include "DirectoryNode.h"
|
||||
#include "config.h"
|
||||
#include "main.h"
|
||||
|
||||
File root;
|
||||
File mp3File;
|
||||
|
||||
Audio audio;
|
||||
|
||||
uint volume = 7;
|
||||
|
||||
// Folder-play tracking: flattened list of files inside a mapped folder and current index
|
||||
// Used when a mapping targets a folder (play folder once or loop folder)
|
||||
#include <vector>
|
||||
static std::vector<std::pair<DirectoryNode *, int>> folderFlatList;
|
||||
static int folderFlatIndex = -1;
|
||||
static String folderRootPath = "";
|
||||
// Pointer to the root DirectoryNode for active folder-mode playback
|
||||
DirectoryNode *folderRootNode = nullptr;
|
||||
|
||||
AsyncWebServer server(80);
|
||||
DNSServer dns;
|
||||
|
||||
// static variable has to be instantiated outside of class definition:
|
||||
uint16_t DirectoryNode::idCounter = 0;
|
||||
|
||||
DirectoryNode rootNode("/");
|
||||
DirectoryNode *currentNode = nullptr;
|
||||
|
||||
volatile bool newRfidInt = false;
|
||||
volatile bool playButtonDown = false;
|
||||
// Track if play button hold is active and if volume was adjusted during this hold
|
||||
volatile bool playHoldActive = false;
|
||||
volatile bool volumeAdjustedDuringHold = false;
|
||||
volatile uint8_t sd_lock_flag = 0;
|
||||
|
||||
/* Simple spinlock using older GCC sync builtins (no libatomic required).
|
||||
sd_lock_acquire() will block (with a small delay) until the lock is free.
|
||||
|
|
@ -102,33 +45,21 @@ static inline void sd_lock_release()
|
|||
__sync_lock_release(&sd_lock_flag);
|
||||
}
|
||||
|
||||
MFRC522 rfid(CS_RFID, RST_RFID); // instatiate a MFRC522 reader object.
|
||||
|
||||
TaskHandle_t RfidTask;
|
||||
|
||||
bool asyncStop = false;
|
||||
|
||||
bool asyncStart = false;
|
||||
|
||||
bool asyncTogglePlayPause = false;
|
||||
|
||||
bool asyncNext = false;
|
||||
|
||||
bool asyncPrev = false;
|
||||
|
||||
bool SDActive = false;
|
||||
|
||||
bool RFIDActive = false;
|
||||
volatile uint8_t dir_lock_flag = 0;
|
||||
/* Lightweight spinlock to guard directory tree access (rootNode) */
|
||||
static inline void dir_lock_acquire()
|
||||
{
|
||||
while (__sync_lock_test_and_set(&dir_lock_flag, 1))
|
||||
{
|
||||
delay(1);
|
||||
}
|
||||
}
|
||||
static inline void dir_lock_release()
|
||||
{
|
||||
__sync_lock_release(&dir_lock_flag);
|
||||
}
|
||||
|
||||
|
||||
// Web request concurrency counter and helpers (atomic via GCC builtins)
|
||||
volatile uint32_t webreq_cnt = 0;
|
||||
static inline void webreq_enter() { __sync_add_and_fetch(&webreq_cnt, 1); }
|
||||
static inline void webreq_exit() { __sync_sub_and_fetch(&webreq_cnt, 1); }
|
||||
|
||||
uint16_t voltage_threshold_counter = 0;
|
||||
|
||||
size_t free_heap = 0;
|
||||
|
||||
// webrequest_blockings is a simple watchdog counter that tracks how long at least one HTTP request has been “active” (not yet disconnected) according to the AsyncWebServer.
|
||||
int webrequest_blockings = 0;
|
||||
|
|
@ -316,8 +247,10 @@ void handleUpload(AsyncWebServerRequest *request, String filename, size_t index,
|
|||
Serial.println(logBuffer);
|
||||
logBuffer.clear();
|
||||
|
||||
// Rebuild directory tree to include new file
|
||||
// Rebuild directory tree to include new file (guarded)
|
||||
dir_lock_acquire();
|
||||
rootNode.buildDirectoryTree("/");
|
||||
dir_lock_release();
|
||||
|
||||
request->send(200, "text/plain", "Upload successful");
|
||||
}
|
||||
|
|
@ -341,8 +274,10 @@ void handleMoveFile(AsyncWebServerRequest *request)
|
|||
SD.rename(from, to);
|
||||
sd_lock_release();
|
||||
Serial.println("Moved file: " + from + " to " + to);
|
||||
// Rebuild directory tree to update file list
|
||||
// Rebuild directory tree to update file list (guarded)
|
||||
dir_lock_acquire();
|
||||
rootNode.buildDirectoryTree("/");
|
||||
dir_lock_release();
|
||||
request->send(200, "text/plain", "File moved successfully.");
|
||||
}
|
||||
else
|
||||
|
|
@ -364,8 +299,10 @@ void handleDeleteFile(AsyncWebServerRequest *request)
|
|||
SD.remove(filename.c_str());
|
||||
sd_lock_release();
|
||||
Serial.println("Deleted file: " + filename);
|
||||
// Rebuild directory tree to update file list
|
||||
// Rebuild directory tree to update file list (guarded)
|
||||
dir_lock_acquire();
|
||||
rootNode.buildDirectoryTree("/");
|
||||
dir_lock_release();
|
||||
request->send(200, "text/plain", "File deleted successfully.");
|
||||
}
|
||||
else
|
||||
|
|
@ -924,7 +861,10 @@ String processor(const String &var)
|
|||
{
|
||||
if (var == "DIRECTORY")
|
||||
{
|
||||
return rootNode.getDirectoryStructureHTML();
|
||||
dir_lock_acquire();
|
||||
String out = rootNode.getDirectoryStructureHTML();
|
||||
dir_lock_release();
|
||||
return out;
|
||||
}
|
||||
|
||||
if (var == "MAPPING")
|
||||
|
|
@ -1277,16 +1217,29 @@ server.on("/", HTTP_GET, [](AsyncWebServerRequest *request)
|
|||
{
|
||||
webreq_enter();
|
||||
request->onDisconnect([](){ webreq_exit(); });
|
||||
String html = processor(String("DIRECTORY"));
|
||||
request->send(200, "text/html; charset=UTF-8", html);
|
||||
// Stream the response to avoid lifetime issues with temporary Strings and to prevent wrong Content-Length
|
||||
AsyncResponseStream* stream = request->beginResponseStream("text/html; charset=UTF-8");
|
||||
stream->addHeader("Cache-Control", "no-store");
|
||||
stream->addHeader("Connection", "close");
|
||||
// Build HTML under lock, then print into stream
|
||||
dir_lock_acquire();
|
||||
String html = rootNode.getDirectoryStructureHTML();
|
||||
dir_lock_release();
|
||||
stream->print(html);
|
||||
request->send(stream);
|
||||
});
|
||||
|
||||
server.on("/mapping", HTTP_GET, [](AsyncWebServerRequest *request)
|
||||
{
|
||||
webreq_enter();
|
||||
request->onDisconnect([](){ webreq_exit(); });
|
||||
// Stream mapping to avoid Content-Length mismatches and reduce heap spikes
|
||||
AsyncResponseStream* stream = request->beginResponseStream("text/html; charset=UTF-8");
|
||||
stream->addHeader("Cache-Control", "no-store");
|
||||
stream->addHeader("Connection", "close");
|
||||
String html = processor(String("MAPPING"));
|
||||
request->send(200, "text/html; charset=UTF-8", html);
|
||||
stream->print(html);
|
||||
request->send(stream);
|
||||
});
|
||||
|
||||
server.on("/state", HTTP_GET, [](AsyncWebServerRequest *request)
|
||||
|
|
@ -1294,7 +1247,10 @@ server.on("/", HTTP_GET, [](AsyncWebServerRequest *request)
|
|||
webreq_enter();
|
||||
request->onDisconnect([](){ webreq_exit(); });
|
||||
String state = getState();
|
||||
request->send(200, "application/json; charset=UTF-8", state.c_str()); });
|
||||
AsyncWebServerResponse* resp = request->beginResponse(200, "application/json; charset=UTF-8", state);
|
||||
resp->addHeader("Cache-Control", "no-store");
|
||||
resp->addHeader("Connection", "close");
|
||||
request->send(resp); });
|
||||
|
||||
server.on("/start", HTTP_GET, [](AsyncWebServerRequest *request)
|
||||
{
|
||||
|
|
@ -1549,12 +1505,14 @@ const String getSysDir(const String filename)
|
|||
|
||||
void loop()
|
||||
{
|
||||
if (webreq_cnt > 0 && webrequest_blockings > 10000) {
|
||||
Serial.println("excessive webrequest blocking!");
|
||||
webreq_cnt = 0;
|
||||
webrequest_blockings = 0;
|
||||
if (webreq_cnt > 0 && webrequest_blockings > MAX_WEBREQUEST_BLOCKINGS) {
|
||||
Serial.println("excessive webrequest blocking - suppress reset");
|
||||
// Avoid resetting server mid-response to prevent mixing headers/body or truncation
|
||||
server.reset();
|
||||
init_webserver();
|
||||
|
||||
webreq_cnt = 0;
|
||||
webrequest_blockings = 0;
|
||||
server.begin();
|
||||
}
|
||||
|
||||
|
|
|
|||
92
src/main.h
92
src/main.h
|
|
@ -1,6 +1,98 @@
|
|||
#ifndef MAIN_H_
|
||||
#define MAIN_H_
|
||||
|
||||
// define pins for RFID
|
||||
#define CS_RFID 32 // SIC, tried 4 and 32 but only this worked!
|
||||
#define RST_RFID 33
|
||||
// this does not work as the irq pin is input only:
|
||||
#define IRQ_RFID 34
|
||||
|
||||
// Audio DAC
|
||||
#define I2S_DOUT 26 // connect to DAC pin DIN
|
||||
#define I2S_BCLK 27 // connect to DAC pin BCK
|
||||
#define I2S_LRC 25 // connect to DAC pin LCK
|
||||
|
||||
#define BTN_START_STOP 4 // Button on XX and GND
|
||||
#define BTN_NEXT 17
|
||||
#define BTN_PREV 16
|
||||
|
||||
#define CS_SDCARD 22
|
||||
|
||||
#define BAT_VOLTAGE_PIN 35
|
||||
|
||||
#define RFID_LOOP_INTERVAL 25
|
||||
|
||||
#define VOLTAGE_LOOP_INTERVAL 5000
|
||||
|
||||
#define VOLTAGE_THRESHOLD 0
|
||||
|
||||
#define SHORT_PRESS_TIME 250
|
||||
|
||||
#define LONG_PRESS_TIME 1000
|
||||
|
||||
#define MAX_WEBREQUEST_BLOCKINGS 10000
|
||||
|
||||
#define MAX_VOL 15
|
||||
|
||||
File root;
|
||||
File mp3File;
|
||||
|
||||
Audio audio;
|
||||
|
||||
uint volume = 7;
|
||||
|
||||
// Folder-play tracking: flattened list of files inside a mapped folder and current index
|
||||
// Used when a mapping targets a folder (play folder once or loop folder)
|
||||
static std::vector<std::pair<DirectoryNode *, int>> folderFlatList;
|
||||
static int folderFlatIndex = -1;
|
||||
static String folderRootPath = "";
|
||||
// Pointer to the root DirectoryNode for active folder-mode playback
|
||||
DirectoryNode *folderRootNode = nullptr;
|
||||
|
||||
AsyncWebServer server(80);
|
||||
DNSServer dns;
|
||||
|
||||
// static variable has to be instantiated outside of class definition:
|
||||
uint16_t DirectoryNode::idCounter = 0;
|
||||
|
||||
DirectoryNode rootNode("/");
|
||||
DirectoryNode *currentNode = nullptr;
|
||||
|
||||
volatile bool newRfidInt = false;
|
||||
volatile bool playButtonDown = false;
|
||||
// Track if play button hold is active and if volume was adjusted during this hold
|
||||
volatile bool playHoldActive = false;
|
||||
volatile bool volumeAdjustedDuringHold = false;
|
||||
volatile uint8_t sd_lock_flag = 0;
|
||||
|
||||
MFRC522 rfid(CS_RFID, RST_RFID); // instatiate a MFRC522 reader object.
|
||||
|
||||
TaskHandle_t RfidTask;
|
||||
|
||||
bool asyncStop = false;
|
||||
|
||||
bool asyncStart = false;
|
||||
|
||||
bool asyncTogglePlayPause = false;
|
||||
|
||||
bool asyncNext = false;
|
||||
|
||||
bool asyncPrev = false;
|
||||
|
||||
bool SDActive = false;
|
||||
|
||||
bool RFIDActive = false;
|
||||
|
||||
|
||||
// Web request concurrency counter and helpers (atomic via GCC builtins)
|
||||
volatile uint32_t webreq_cnt = 0;
|
||||
static inline void webreq_enter() { __sync_add_and_fetch(&webreq_cnt, 1); }
|
||||
static inline void webreq_exit() { __sync_sub_and_fetch(&webreq_cnt, 1); }
|
||||
|
||||
uint16_t voltage_threshold_counter = 0;
|
||||
|
||||
size_t free_heap = 0;
|
||||
|
||||
void stop();
|
||||
|
||||
void start();
|
||||
|
|
|
|||
Loading…
Reference in New Issue