diff --git a/exsamples/myoptions.h b/exsamples/myoptions.h index 63c4fac..0272003 100644 --- a/exsamples/myoptions.h +++ b/exsamples/myoptions.h @@ -72,6 +72,10 @@ The connection tables are located here https://github.com/e2002/yoradio#connecti //#define ENC_HALFQUARD true /* Experiment with it */ /******************************************/ +/* SDCARD */ +//#define SDC_SPI 18, 19, 23 /* SDCARD SPI pins (SCK, MISO, MOSI) */ +//#define SDC_CS 255 /* SDCARD CS pin */ + /* ENCODER2 */ //#define ENC2_BTNL 255 /* Left rotation */ //#define ENC2_BTNB 255 /* Encoder button */ diff --git a/yoRadio/src/core/config.cpp b/yoRadio/src/core/config.cpp index 3e505c7..1589989 100644 --- a/yoRadio/src/core/config.cpp +++ b/yoRadio/src/core/config.cpp @@ -1,6 +1,6 @@ #include "config.h" #include -#include +//#include #include "display.h" #include "player.h" @@ -9,6 +9,7 @@ Config config; #if DSP_HSPI || TS_HSPI || VS_HSPI SPIClass SPI2(HSPI); #endif +SPIClass SDSPI(VSPI); void u8fix(char *src){ char last = src[strlen(src)-1]; @@ -22,13 +23,28 @@ void Config::init() { #endif eepromRead(EEPROM_START, store); if (store.config_set != 4262) setDefaults(); + if(store.play_mode==80) store.play_mode=PM_WEB; + //if (!SPIFFS.begin(false, "/spiffs", 30)) { if (!SPIFFS.begin(false)) { return; } + loadTheme(); ssidsCount = 0; - initPlaylist(); + if(SDC_CS!=255 && store.play_mode==/*PM_SDCARD*/PM_WEB){ + pinMode(SDC_CS, OUTPUT); digitalWrite(SDC_CS, HIGH); + SDSPI.begin(SDC_SPI); + SDSPI.setFrequency(1000000); + if(!SD.begin(SDC_CS)){ + store.play_mode=PM_WEB; + Serial.println("##[ERROR]#\tCard Mount Failed"); + }else{ + initSDPlaylist(); + } + } + if(store.play_mode==PM_WEB) initPlaylist(); + if (store.lastStation == 0 && store.countStation > 0) { store.lastStation = 1; save(); @@ -138,7 +154,7 @@ void Config::setDefaults() { strlcpy(store.weatherkey,"", 64); store.volsteps = 1; store.encacc = 200; - store.irto = 80; + store.play_mode = 0; store.irtlp = 35; store.btnpullup = true; store.btnlongpress = 200; @@ -268,6 +284,88 @@ void Config::initPlaylist() { } } +bool endsWith (const char* base, const char* str) { +//fb + int slen = strlen(str) - 1; + const char *p = base + strlen(base) - 1; + while(p > base && isspace(*p)) p--; // rtrim + p -= slen; + if (p < base) return false; + return (strncmp(p, str, slen) == 0); +} + +void Config::listSD(File &plSDfile, File &plSDindex, const char * dirname, uint8_t levels){ + File root = SD.open(dirname); + if(!root){ + Serial.println("Failed to open directory"); + return; + } + if(!root.isDirectory()){ + Serial.println("Not a directory"); + return; + } + + File file = root.openNextFile(); + uint32_t pos = 0; + + while(file){ + + if(file.isDirectory()){ +// Serial.print(" DIR : "); +// Serial.println(file.name()); + if(levels){ + listSD(plSDfile, plSDindex, file.path(), levels -1); + } + } else { +// Serial.print(" FILE: "); +// Serial.print(file.name()); +// Serial.print(" SIZE: "); +// Serial.println(file.size()); + if(endsWith(file.name(), ".mp3") || endsWith(file.name(), ".m4a") || endsWith(file.name(), ".aac") || endsWith(file.name(), ".wav") || endsWith(file.name(), ".flac")){ + pos = plSDfile.position(); + plSDfile.print(file.name()); plSDfile.print("\t"); plSDfile.print(file.path()); plSDfile.print("\t"); plSDfile.println(0); + plSDindex.write((byte *) &pos, 4); + Serial.print(" plSDfile.position:\t"); + Serial.println(pos); + } + } + file = root.openNextFile(); + } +} + +void Config::indexSDPlaylist() { + File playlist = SPIFFS.open(PLAYLIST_SD_PATH, "w"); + if (!playlist) { + return; + } + + +// char sName[BUFLEN], sUrl[BUFLEN]; +// int sOvol; + File index = SPIFFS.open(INDEX_SD_PATH, "w"); + listSD(playlist, index, "/", 2); +/* while (playlist.available()) { + uint32_t pos = playlist.position(); + if (parseCSV(playlist.readStringUntil('\n').c_str(), sName, sUrl, sOvol)) { + index.write((byte *) &pos, 4); + } + }*/ + index.close(); + playlist.close(); +} + +void Config::initSDPlaylist() { + store.countStation = 0; + indexSDPlaylist(); + + if (SPIFFS.exists(INDEX_SD_PATH)) { + File index = SD.open(INDEX_SD_PATH, "r"); + store.countStation = index.size() / 4; + index.close(); + save(); + } +} + void Config::loadStation(uint16_t ls) { char sName[BUFLEN], sUrl[BUFLEN]; int sOvol; diff --git a/yoRadio/src/core/config.h b/yoRadio/src/core/config.h index 06cbef6..29dd843 100644 --- a/yoRadio/src/core/config.h +++ b/yoRadio/src/core/config.h @@ -3,6 +3,8 @@ #include "Arduino.h" #include #include +#include +#include #include "options.h" #define EEPROM_SIZE 768 @@ -15,6 +17,9 @@ #define TMP_PATH "/data/tmpfile.txt" #define INDEX_PATH "/data/index.dat" +#define PLAYLIST_SD_PATH "/data/playlistsd.csv" +#define INDEX_SD_PATH "/data/indexsd.dat" + #ifdef DEBUG_V #define DBGH() { Serial.printf("[%s:%s:%d] Heap: %d\n", __PRETTY_FUNCTION__, __FILE__, __LINE__, xPortGetFreeHeapSize()); } #define DBGVB( ... ) { char buf[200]; sprintf( buf, __VA_ARGS__ ) ; Serial.print("[DEBUG]\t"); Serial.println(buf); } @@ -90,7 +95,7 @@ struct config_t char weatherkey[64]; uint8_t volsteps; uint16_t encacc; - uint8_t irto; + uint8_t play_mode; //0 WEB, 1 SD uint8_t irtlp; bool btnpullup; uint16_t btnlongpress; @@ -169,6 +174,9 @@ class Config { void setSmartStart(byte ss); void initPlaylist(); void indexPlaylist(); + void listSD(File &plSDfile, File &plSDindex, const char * dirname, uint8_t levels); + void initSDPlaylist(); + void indexSDPlaylist(); void fillPlMenu(char plmenu[][40], int from, byte count, bool removeNum = false); void setTimezone(int8_t tzh, int8_t tzm); void setTimezoneOffset(uint16_t tzo); diff --git a/yoRadio/src/core/netserver.cpp b/yoRadio/src/core/netserver.cpp index 2b13a37..87fdc99 100644 --- a/yoRadio/src/core/netserver.cpp +++ b/yoRadio/src/core/netserver.cpp @@ -54,6 +54,8 @@ bool NetServer::begin() { webserver.on("/", HTTP_ANY, handleHTTPArgs); webserver.on(PLAYLIST_PATH, HTTP_GET, handleHTTPArgs); webserver.on(INDEX_PATH, HTTP_GET, handleHTTPArgs); + webserver.on(PLAYLIST_SD_PATH, HTTP_GET, handleHTTPArgs); + webserver.on(INDEX_SD_PATH, HTTP_GET, handleHTTPArgs); webserver.on(SSIDS_PATH, HTTP_GET, handleHTTPArgs); webserver.on("/upload", HTTP_POST, beginUpload, handleUpload); webserver.on("/update", HTTP_GET, handleHTTPArgs); @@ -630,7 +632,7 @@ void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventTyp void handleHTTPArgs(AsyncWebServerRequest * request) { if (request->method() == HTTP_GET) { DBGVB("[%s] client ip=%s request of %s", __func__, request->client()->remoteIP().toString().c_str(), request->url().c_str()); - if (strcmp(request->url().c_str(), PLAYLIST_PATH) == 0 || strcmp(request->url().c_str(), SSIDS_PATH) == 0 || strcmp(request->url().c_str(), INDEX_PATH) == 0 || strcmp(request->url().c_str(), TMP_PATH) == 0) { + if (strcmp(request->url().c_str(), PLAYLIST_PATH) == 0 || strcmp(request->url().c_str(), SSIDS_PATH) == 0 || strcmp(request->url().c_str(), INDEX_PATH) == 0 || strcmp(request->url().c_str(), TMP_PATH) == 0 || strcmp(request->url().c_str(), PLAYLIST_SD_PATH) == 0 || strcmp(request->url().c_str(), INDEX_SD_PATH) == 0) { #ifdef MQTT_HOST if (strcmp(request->url().c_str(), PLAYLIST_PATH) == 0) while (mqttplaylistblock) vTaskDelay(5); #endif diff --git a/yoRadio/src/core/options.h b/yoRadio/src/core/options.h index 855d0ed..b9a4f65 100644 --- a/yoRadio/src/core/options.h +++ b/yoRadio/src/core/options.h @@ -1,7 +1,7 @@ #ifndef options_h #define options_h -#define YOVERSION "0.8.173" +#define YOVERSION "0.9.000" /******************************************************* DO NOT EDIT THIS FILE. @@ -114,6 +114,14 @@ The connection tables are located here https://github.com/e2002/yoradio#connecti #define I2S_LRC 25 // WSEL Left Right Clock #endif +/* SDCARD */ +#ifndef SDC_SPI + #define SDC_SPI 18, 19, 23 // SDCARD SPI pins (SCK, MISO, MOSI) +#endif +#ifndef SDC_CS + #define SDC_CS 255 // SDCARD CS pin +#endif + /* ENCODER */ #ifndef ENC_BTNL #define ENC_BTNL 255 diff --git a/yoRadio/src/core/player.h b/yoRadio/src/core/player.h index ada85c6..ea5cec4 100644 --- a/yoRadio/src/core/player.h +++ b/yoRadio/src/core/player.h @@ -9,6 +9,8 @@ #endif enum audioMode_e { PLAYING, STOPPED }; +enum playMode_e : uint8_t { PM_WEB=0, PM_SDCARD=1 }; + struct audiorequest_t { uint16_t station;