// From .../MTP_t4.git/trunk/examples/mtp-basic/mtp-basic.ino
#include "SPI.h"
#include "SD.h"
#include "MTP.h"
#if defined(ARDUINO_TEENSY41)
// The Teensy 4.1 has two sets of solder pads underneath the Teensy that you
// can solder either 2 PSram chips, 1 flash memory chip, or 1 flash memory chip
// and a PSram chip. The smaller flash chips tend to use NOR flash while the
// larger flash chips tend to use NAND flash.
#define USE_LFS_RAM 1 // T4.1 PSRAM (or RAM)
#define USE_LFS_QSPI_NOR 1 // T4.1 QSPI NOR flash (16MB)
#define USE_LFS_QSPI_NAND 1 // T4.1 QSPI NAND flash (128MB)
#else
#define USE_LFS_RAM 0 // T4.1 PSRAM (or RAM)
#define USE_LFS_QSPI_NOR 0 // T4.1 QSPI NOR flash (16MB)
#define USE_LFS_QSPI_NAND 0 // T4.1 QSPI NAND flash (128MB)
#endif
#if defined(ARDUINO_TEENSY40) || defined(ARDUINO_TEENSY41)
// Teensy 4.0 and 4.1 can use the upper flash memory as a file system via
// LittleFS. The top bytes (64K for Teensy 4.0 and 256K for Teensy 4.1) of
// this memory is reserved for EEPROM emulation and the LED blink restore
// program. On the Teensy 4.0 you have 1 megabyte - 64K of flash for a
// filesystem. On the Teensy 4.1, you have 7 megabytes - 256K of flash for the
// filesystem.
#define USE_LFS_PROGM 1 // T4.0/T4.1 Progam Flash
#else
#define USE_LFS_PROGM 0 // T4.0/T4.1 Progam Flash
#endif
#define USE_SD 1 // Use either the built-in micro SD card reader or the reader on pin 10 (audio adapter)
#define USE_LFS_SPI 1 // SPI Flash (soldered to the audio adapter or the built-in flash on the prop shield)
// If you use the audio adapter revision A through C on a Teensy LC, 3.2, 3.5,
// or 3.6, it needs to remap the MOSI/SCK pins because those pins (11 and 13)
// are also I2S pins used by the audio shield. But the prop shield wants to
// use the normal definitions. In general, I've used the prop shield mostly on
// the Teensy 3.2 and LC, while if I use it, I use the audio shield on the
// Teensy 3.5 or Teensy 3.6.
//
// The Teensy 4.0 and 4.1 uses the audio adapter revision D, and it uses the
// standard SPI pins.
#if defined(ARDUINO_TEENSY35) || defined(ARDUINO_TEENSY36)
#define USE_TEENSY3_AUDIO_SHIELD 1 // Whether to use the Audio shield MOSI/SCLK for Teensy 3.x processors
#else
#define USE_TEENSY3_AUDIO_SHIELD 0 // Use standard configuration
#endif
#if USE_EVENTS==1
extern "C" int usb_init_events(void);
#else
int usb_init_events(void) {}
#endif
#if USE_LFS_RAM==1 || USE_LFS_PROGM==1 || USE_LFS_QSPI_NOR==1 || USE_LFS_QSPI_NAND==1 || USE_LFS_SPI==1
#include "LittleFS.h"
#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_SDCARD
#define BUILTIN_SDCARD 254
#endif
void usb_mtp_configure(void) {}
#endif
/**** Start device specific change area ****/
// SDClasses
#if USE_SD==1
// edit SPI to reflect your configuration
#if USE_TEENSY3_AUDIO_SHIELD
// Teensy audio adapter for Teensy 3.2, 3.5, and 3.6 (revision A-C) needs to remap the MOSI and SCK pins
#define SD_MOSI 7
#define SD_MISO 12
#define SD_SCK 14
#else
// Standard Teensy configuration
#define SD_MOSI 11
#define SD_MISO 12
#define SD_SCK 13
#endif
#define SPI_SPEED SD_SCK_MHZ(33) // adjust to sd card
#if defined (BUILTIN_SDCARD)
const char *sd_str[]={"BUILTIN-SD", "AUDIO-SD"}; // edit to reflect your configuration
const int cs[] = {BUILTIN_SDCARD, 10}; // edit to reflect your configuration
#else
const char *sd_str[]={"AUDIO-SD"}; // edit to reflect your configuration
const int cs[] = {10}; // edit to reflect your configuration
#endif
const int nsd = sizeof(sd_str)/sizeof(const char *);
SDClass sdx[nsd];
#endif
//LittleFS classes
#if USE_LFS_RAM==1
const char *lfs_ram_str[] = {"RAM1","RAM2"}; // edit to reflect your configuration
const int lfs_ram_size[] = {2'000'000, 4'000'000}; // edit to reflect your configuration
const int nfs_ram = sizeof(lfs_ram_str)/sizeof(const char *);
LittleFS_RAM ramfs[nfs_ram];
#endif
#if USE_LFS_QSPI_NOR==1
const char *lfs_qspi_nor_str[] = {"QSPI-NOR"}; // edit to reflect your configuration
const int nfs_qspi_nor = sizeof(lfs_qspi_nor_str)/sizeof(const char *);
LittleFS_QSPIFlash qspifs_nor[nfs_qspi_nor];
#endif
#if USE_LFS_QSPI_NAND==1
const char *lfs_qspi_nand_str[] = {"QSPI-NAND"}; // edit to reflect your configuration
const int nfs_qspi_nand = sizeof(lfs_qspi_nand_str)/sizeof(const char *);
LittleFS_QPINAND qspifs_nand[nfs_qspi_nand];
#endif
#if USE_LFS_PROGM==1
const char *lfs_progm_str[]={"PROGRAM"}; // edit to reflect your configuration
const int lfs_progm_size[] = {1'000'000}; // edit to reflect your configuration
const int nfs_progm = sizeof(lfs_progm_str)/sizeof(const char *);
LittleFS_Program progmfs[nfs_progm];
#endif
#if USE_LFS_SPI==1
const char *lfs_spi_str[]={"SPI-FLASH"}; // edit to reflect your configuration
const int lfs_cs[] = {6}; // edit to reflect your configuration
const int nfs_spi = sizeof(lfs_spi_str)/sizeof(const char *);
LittleFS_SPIFlash spifs[nfs_spi];
#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 USE_LFS_RAM==1
for(int ii=0; ii<nfs_ram;ii++)
{
if(!ramfs[ii].begin(lfs_ram_size[ii]))
{ Serial.printf("Ram Storage %d %s failed or missing",ii,lfs_ram_str[ii]); Serial.println();
}
else
{
storage.addFilesystem(ramfs[ii], lfs_ram_str[ii]);
uint64_t totalSize = ramfs[ii].totalSize();
uint64_t usedSize = ramfs[ii].usedSize();
Serial.printf("RAM Storage %d %s ",ii,lfs_ram_str[ii]); Serial.print(totalSize); Serial.print(" "); Serial.println(usedSize);
}
}
#endif
#if USE_LFS_PROGM==1
for(int ii=0; ii<nfs_progm;ii++)
{
if(!progmfs[ii].begin(lfs_progm_size[ii]))
{ Serial.printf("Program Storage %d %s failed or missing",ii,lfs_progm_str[ii]); Serial.println();
}
else
{
storage.addFilesystem(progmfs[ii], lfs_progm_str[ii]);
uint64_t totalSize = progmfs[ii].totalSize();
uint64_t usedSize = progmfs[ii].usedSize();
Serial.printf("Program Storage %d %s ",ii,lfs_progm_str[ii]); Serial.print(totalSize); Serial.print(" "); Serial.println(usedSize);
}
}
#endif
#if USE_LFS_QSPI_NOR==1
for(int ii=0; ii<nfs_qspi_nor;ii++)
{
if(!qspifs_nor[ii].begin())
{ Serial.printf("QSPI Storage %d %s failed or missing",ii,lfs_qspi_nor_str[ii]); Serial.println();
}
else
{
storage.addFilesystem(qspifs_nor[ii], lfs_qspi_nor_str[ii]);
uint64_t totalSize = qspifs_nor[ii].totalSize();
uint64_t usedSize = qspifs_nor[ii].usedSize();
Serial.printf("QSPI NOR Storage %d %s ",ii,lfs_qspi_nor_str[ii]); Serial.print(totalSize); Serial.print(" "); Serial.println(usedSize);
}
}
#endif
#if USE_LFS_QSPI_NAND==1
for(int ii=0; ii<nfs_qspi_nand;ii++)
{
if(!qspifs_nand[ii].begin())
{ Serial.printf("QSPI Storage %d %s failed or missing",ii,lfs_qspi_nand_str[ii]); Serial.println();
}
else
{
storage.addFilesystem(qspifs_nand[ii], lfs_qspi_nand_str[ii]);
uint64_t totalSize = qspifs_nand[ii].totalSize();
uint64_t usedSize = qspifs_nand[ii].usedSize();
Serial.printf("QSPI NAND Storage %d %s ",ii,lfs_qspi_nand_str[ii]); Serial.print(totalSize); Serial.print(" "); Serial.println(usedSize);
}
}
#endif
#if USE_LFS_SPI==1
for(int ii=0; ii<nfs_spi;ii++)
{
if(!spifs[ii].begin(lfs_cs[ii]))
{ Serial.printf("SPIFlash Storage %d %d %s failed or missing",ii,lfs_cs[ii],lfs_spi_str[ii]); Serial.println();
}
else
{
storage.addFilesystem(spifs[ii], lfs_spi_str[ii]);
uint64_t totalSize = spifs[ii].totalSize();
uint64_t usedSize = spifs[ii].usedSize();
Serial.printf("SPIFlash Storage %d %d %s ",ii,lfs_cs[ii],lfs_spi_str[ii]); Serial.print(totalSize); Serial.print(" "); Serial.println(usedSize);
}
}
#endif
}
void setup()
{
while (!Serial && millis () < 3000)
;
Serial.println("MTP_test");
Serial.printf ("USE_LFS_RAM = %d\n", USE_LFS_RAM);
Serial.printf ("USE_LFS_QSPI_NOR = %d\n", USE_LFS_QSPI_NOR);
Serial.printf ("USE_LFS_QSPI_NAND = %d\n", USE_LFS_QSPI_NAND);
Serial.printf ("USE_LFS_PROGM = %d\n", USE_LFS_PROGM);
Serial.printf ("USE_SD = %d\n", USE_SD);
Serial.printf ("USE_LFS_SPI = %d\n", USE_LFS_SPI);
Serial.printf ("USE_TEENSY3_AUDIO_SHIELD = %d\n", USE_TEENSY3_AUDIO_SHIELD);
Serial.println ("");
#if USE_EVENTS==1
usb_init_events();
#endif
#if !__has_include("usb_mtp.h")
usb_mtp_configure();
#endif
storage_configure();
}
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();
}
}
#endif
}