#include "Arduino.h"
#include "SD.h"
#include "MTP.h"
#if USE_EVENTS==1
extern "C" int usb_init_events(void);
#else
int usb_init_events(void) {}
#endif
#if defined(__IMXRT1062__)
// following only as long usb_mtp is not included in cores
#if !__has_include("usb_mtp.h")
#include "usb1_mtp.h"
#endif
#else
#ifndef BUILTIN_SCCARD
#define BUILTIN_SDCARD 254
#endif
void usb_mtp_configure(void) {}
#endif
#define USE_SD 1
#define HAVE_LITTLEFS 1 // set to zero if no LtttleFS is existing or to be used
#if HAVE_LITTLEFS==1
#include "LittleFS.h"
#include "LittleFS_NAND.h"
#define USE_RAM 0
#define USE_SPI 1
#define USE_QSPI 0
#define USE_HS_QSPI 0
#define USE_NAND 1
#define USE_QSPI_NAND 0
#define USE_FRAM 0
#endif
/**** Start device specific change area ****/
// edit SPI to reflect your configuration (following is fot T4.1)
#define SD_MOSI 11
#define SD_MISO 12
#define SD_SCK 13
#define SPI_SPEED SD_SCK_MHZ(16) // adjust to sd card
// SDClasses
const char *sd_str[]={"sdio"}; // edit to reflect your configuration
const int cs[] = {BUILTIN_SDCARD}; // edit to reflect your configuration
const int nsd = sizeof(cs)/sizeof(int);
SDClass sdx[nsd];
//LittleFS classes
#if HAVE_LITTLEFS==1
#include "LittleFS.h"
#if USE_RAM == 1
const char *ram_str[]={"RAM0", "RAM1"}; // edit to reflect your configuration
const int ram_size[] = {2'000'000, 4'000'000};
const int ram_nsd = sizeof(ram_size)/sizeof(int);
LittleFS_RAM ramfs[ram_nsd]; // needs to be declared if LittleFS is used in storage.h
#endif
#if USE_SPI == 1
const char *spi_str[]={"WINBOND"}; // edit to reflect your configuration
const int spi_cs[] = {6}; // edit to reflect your configuration
const int spi_nsd = sizeof(spi_cs)/sizeof(int);
LittleFS_SPIFlash spifs[spi_nsd]; // needs to be declared if LittleFS is used in storage.h
#endif
#if USE_FRAM == 1
const char *fram_str[]={"CYPRESS"}; // edit to reflect your configuration
const int fram_cs[] = {10}; // edit to reflect your configuration
const int fram_nsd = sizeof(fram_cs)/sizeof(int);
LittleFS_SPIFlash fram[fram_nsd]; // needs to be declared if LittleFS is used in storage.h
#endif
#if USE_NAND == 1
const char *nspi_str[]={"WINBOND1G", "WINBOND2G"}; // edit to reflect your configuration
const int nspi_cs[] = {3,4}; // edit to reflect your configuration
const int nspi_nsd = sizeof(nspi_cs)/sizeof(int);
LittleFS_SPINAND nspifs[nspi_nsd]; // needs to be declared if LittleFS is used in storage.h
#endif
#if USE_QSPI_NAND == 1
const char *qnspi_str[]={"WINBOND1G"}; // edit to reflect your configuration
const int qnspi_nsd = 1;
LittleFS_QPINAND qnspifs[qnspi_nsd]; // needs to be declared if LittleFS is used in storage.h
#endif
#if USE_QSPI == 1
const char *qspi_str[]={"QSPI0"}; // edit to reflect your configuration
const int qspi_nsd = 1;
LittleFS_QSPIFlash qspifs[qspi_nsd]; // needs to be declared if LittleFS is used in storage.h
#endif
#endif
MTPStorage_SD storage;
MTPD mtpd(&storage);
void storage_configure()
{
#if USE_SD==1
#if defined SD_SCK
SPI.setMOSI(SD_MOSI);
SPI.setMISO(SD_MISO);
SPI.setSCK(SD_SCK);
#endif
for(int ii=0; ii<nsd; ii++)
{
#if defined(BUILTIN_SDCARD)
if(cs[ii] == BUILTIN_SDCARD)
{
if(!sdx[ii].sdfs.begin(SdioConfig(FIFO_SDIO)))
{ Serial.printf("SDIO Storage %d %d %s failed or missing",ii,cs[ii],sd_str[ii]); Serial.println();
}
else
{
storage.addFilesystem(sdx[ii], sd_str[ii]);
uint64_t totalSize = sdx[ii].totalSize();
uint64_t usedSize = sdx[ii].usedSize();
Serial.printf("SDIO Storage %d %d %s ",ii,cs[ii],sd_str[ii]);
Serial.print(totalSize); Serial.print(" "); Serial.println(usedSize);
}
}
else if(cs[ii]<BUILTIN_SDCARD)
#endif
{
pinMode(cs[ii],OUTPUT); digitalWriteFast(cs[ii],HIGH);
if(!sdx[ii].sdfs.begin(SdSpiConfig(cs[ii], SHARED_SPI, SPI_SPEED)))
{ Serial.printf("SD Storage %d %d %s failed or missing",ii,cs[ii],sd_str[ii]); Serial.println();
}
else
{
storage.addFilesystem(sdx[ii], sd_str[ii]);
uint64_t totalSize = sdx[ii].totalSize();
uint64_t usedSize = sdx[ii].usedSize();
Serial.printf("SD Storage %d %d %s ",ii,cs[ii],sd_str[ii]);
Serial.print(totalSize); Serial.print(" "); Serial.println(usedSize);
}
}
}
#endif
#if HAVE_LITTLEFS==1
#if USE_RAM == 1
for(int ii=0; ii<ram_nsd;ii++)
{
{ if(!ramfs[ii].begin(ram_size[ii])) { Serial.println("No storage"); while(1);}
storage.addFilesystem(ramfs[ii], ram_str[ii]);
}
uint64_t totalSize = ramfs[ii].totalSize();
uint64_t usedSize = ramfs[ii].usedSize();
Serial.printf("Storage %d %s ",ii,ram_str[ii]); Serial.print(totalSize); Serial.print(" "); Serial.println(usedSize);
}
#endif
#if USE_SPI == 1
for(int ii=0; ii<spi_nsd;ii++) {
pinMode(spi_cs[ii],OUTPUT); digitalWriteFast(spi_cs[ii],HIGH);
if(!spifs[ii].begin(spi_cs[ii], SPI)) {Serial.println("No storage"); while(1);}
storage.addFilesystem(spifs[ii], spi_str[ii]);
uint64_t totalSize = spifs[ii].totalSize();
uint64_t usedSize = spifs[ii].usedSize();
Serial.printf("Storage %d %d %s ",ii,spi_cs[ii],spi_str[ii]); Serial.print(totalSize); Serial.print(" "); Serial.println(usedSize);
}
#endif
#if USE_FRAM == 1
for(int ii=0; ii<fram_nsd;ii++) {
pinMode(fram_cs[ii],OUTPUT); digitalWriteFast(fram_cs[ii],HIGH);
if(!fram[ii].begin(fram_cs[ii], SPI)) {Serial.println("No storage"); while(1);}
storage.addFilesystem(fram[ii], fram_str[ii]);
uint64_t totalSize = fram[ii].totalSize();
uint64_t usedSize = fram[ii].usedSize();
Serial.printf("Storage %d %d %s ",ii,fram_cs[ii],fram_str[ii]); Serial.print(totalSize); Serial.print(" "); Serial.println(usedSize);
}
#endif
#if USE_NAND == 1
for(int ii=0; ii<nspi_nsd;ii++) {
pinMode(nspi_cs[ii],OUTPUT); digitalWriteFast(nspi_cs[ii],HIGH);
if(!nspifs[ii].begin(nspi_cs[ii], SPI)) {Serial.println("No storage"); while(1);}
storage.addFilesystem(nspifs[ii], nspi_str[ii]);
uint64_t totalSize = nspifs[ii].totalSize();
uint64_t usedSize = nspifs[ii].usedSize();
Serial.printf("Storage %d %d %s ",ii,nspi_cs[ii],nspi_str[ii]); Serial.print(totalSize); Serial.print(" "); Serial.println(usedSize);
}
#endif
#if USE_QSPI_NAND == 1
for(int ii=0; ii<qnspi_nsd;ii++) {
if(!qnspifs[ii].begin()) {Serial.println("No storage"); while(1);}
storage.addFilesystem(qnspifs[ii], qnspi_str[ii]);
uint64_t totalSize = qnspifs[ii].totalSize();
uint64_t usedSize = qnspifs[ii].usedSize();
Serial.printf("Storage %d %s ",ii,qnspi_str[ii]); Serial.print(totalSize); Serial.print(" "); Serial.println(usedSize);
}
#endif
#if USE_QSPI == 1
for(int ii=0; ii<qspi_nsd;ii++) {
if(!qspifs[ii].begin()) {Serial.println("No storage"); while(1);}
storage.addFilesystem(qspifs[ii], qspi_str[ii]);
uint64_t totalSize = qspifs[ii].totalSize();
uint64_t usedSize = qspifs[ii].usedSize();
Serial.printf("Storage %d %s ",ii,qspi_str[ii]); Serial.print(totalSize); Serial.print(" "); Serial.println(usedSize);
}
#endif
#endif
}
/**** End of device specific change area ****/
#if USE_SD==1
// Call back for file timestamps. Only called for file create and sync(). needed by SDFat-beta
#include "TimeLib.h"
void dateTime(uint16_t* date, uint16_t* time, uint8_t* ms10)
{ *date = FS_DATE(year(), month(), day());
*time = FS_TIME(hour(), minute(), second());
*ms10 = second() & 1 ? 100 : 0;
}
#endif
void setup()
{
#if defined(USB_MTPDISK_SERIAL)
while(!Serial); // comment if you do not want to wait for terminal
#else
while(!Serial.available()); // comment if you do not want to wait for terminal (otherwise press any key to continue)
#endif
Serial.println("MTP_test");
#if USE_EVENTS==1
usb_init_events();
#endif
#if !__has_include("usb_mtp.h")
usb_mtp_configure();
#endif
storage_configure();
#if USE_SD==1
// Set Time callback // needed for SDFat
FsDateTime::callback = dateTime;
{
const char *str = "test1.txt";
if(sdx[0].exists(str)) sdx[0].remove(str);
File file=sdx[0].open(str,FILE_WRITE_BEGIN);
file.println("This is a test line");
file.close();
Serial.println("\n**** dir of sd[0] ****");
sdx[0].sdfs.ls();
}
#endif
#if USE_LFS_RAM==1
for(int ii=0; ii<10;ii++)
{ char filename[80];
sprintf(filename,"/test_%d.txt",ii);
File file=ramfs[0].open(filename,FILE_WRITE_BEGIN);
file.println("This is a test line");
file.close();
}
ramfs[0].mkdir("Dir0");
for(int ii=0; ii<10;ii++)
{ char filename[80];
sprintf(filename,"/Dir0/test_%d.txt",ii);
File file=ramfs[0].open(filename,FILE_WRITE_BEGIN);
file.println("This is a test line");
file.close();
}
ramfs[0].mkdir("Dir0/dir1");
for(int ii=0; ii<10;ii++)
{ char filename[80];
sprintf(filename,"/Dir0/dir1/test_%d.txt",ii);
File file=ramfs[0].open(filename,FILE_WRITE_BEGIN);
file.println("This is a test line");
file.close();
}
uint32_t buffer[256];
File file = ramfs[1].open("LargeFile.bin",FILE_WRITE_BEGIN);
for(int ii=0;ii<3000;ii++)
{ memset(buffer,ii%256,1024);
file.write(buffer,1024);
}
file.close();
#endif
Serial.println("\nSetup done");
}
void loop()
{
mtpd.loop();
#if USE_EVENTS==1
if(Serial.available())
{
char ch=Serial.read();
Serial.println(ch);
if(ch=='r')
{
Serial.println("Reset");
mtpd.send_DeviceResetEvent();
}
#if USE_LFS_RAM==1
if(ch=='a')
{
Serial.println("Add Files");
static int count=100;
for(int ii=0; ii<10;ii++)
{ char filename[80];
sprintf(filename,"/test_%d.txt",count++);
Serial.println(filename);
File file=ramfs[0].open(filename,FILE_WRITE_BEGIN);
file.println("This is a test line");
file.close();
}
// attempt to notify PC on added files (does not work yet)
uint32_t store = storage.getStoreID("RAM1");
Serial.print("Store "); Serial.println(store);
mtpd.send_StorageInfoChangedEvent(store);
}
#elif USE_SD==1
if(ch=='a')
{
Serial.println("Add Files");
static int count=100;
for(int ii=0; ii<10;ii++)
{ char filename[80];
sprintf(filename,"/test_%d.txt",count++);
Serial.println(filename);
File file=sdx[0].open(filename,FILE_WRITE_BEGIN);
file.println("This is a test line");
file.close();
}
// attempt to notify PC on added files (does not work yet)
uint32_t store = storage.getStoreID("sdio");
Serial.print("Store "); Serial.println(store);
mtpd.send_StorageInfoChangedEvent(store);
}
#endif
}
#endif
}