MTP file dates

domingo

Well-known member
Hi everyone,

I'm using the following code to view files from a Teensy 4's SD card into my computer, via USB and MTP. It works great, but for some reason it doesn't show the files' creation or modification date on the file browser. I'm using linux and 'simple-mtfs' or other tools to mount the disk. The code is based on the @WMXZ MTP_t4 library. I suppose there is a problem in the code, because trying with another MTP library available (Kurt) I can see the files' dates. That other library is simpler to implement in code, but unfortunately it doesn't perform as well as the WMXZ for me in other aspects.

Any advice please, if anyone feels like taking a look at the code. It is based (simplified for SDIO only) on an example published with the library, which exhibits the same problem when used as published.

Kind regards,
Domingo

Code:
//Uses https://github.com/WMXZ-EU/MTP_t4
#include "SPI.h"
#include "SD.h"
#include "MTP.h"

#define USE_SD  1         // SDFAT based SDIO and SPI

#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_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 (following is for T4.1)
  #define SD_MOSI 11
  #define SD_MISO 12
  #define SD_SCK  13

  #if defined (BUILTIN_SDCARD)
    const char *sd_str[]={"sdio"}; // edit to reflect your configuration
    const int cs[] = {BUILTIN_SDCARD,10}; // edit to reflect your configuration
  #else
    const char *sd_str[]={"sd1"}; // 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


MTPStorage_SD storage;
MTPD    mtpd(&storage);

void storage_configure()
{
  // Using SD card for storage
  #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(cs[ii]<BUILTIN_SDCARD)
      {
        pinMode(cs[ii],OUTPUT); digitalWriteFast(cs[ii],HIGH);
      }
      if(!sdx[ii].begin(cs[ii]))
      { Serial.printf("SD/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("; total "); Serial.print(totalSize); Serial.print(" used: "); Serial.println(usedSize);
      }
    }
  #endif
}
 
void setup()
{
/*  while(!Serial);
  Serial.println("MTP_test");
*/
  #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
}
 
I guess, I have not added creation/modification date to the property list. I personally do not need it, but if important I can have look.
 
I guess, I have not added creation/modification date to the property list. I personally do not need it, but if important I can have look.
That would be amazing WMXZ! For me it is very important and the archiving of all my field recordings 🙏 The code works otherwise like a charm. Count on me for any check-ups needed, whenever if you feel like digging into it.
 
Updated github.
Archive your old version (simply zip it) before updating with github version. A quick test of mine shows the creation/modification timestamp
 
It Works! Amazing. It shows now modification date :) Creation date is empty, but I think that might be a linux limitation.
When compiling the code though I get some new errors, which didn't appear before. I confirmed they are new by reverting to the previous version, which I thankfully backed-up as you suggested me.

These are the errors.

Code:
In file included from /usr/share/arduino/hardware/teensy/avr/libraries/Audio/MTP.h:37,
                 from /home/domingo/Desktop/Teensy/MTPWMXZ/MTPWMXZ.ino:13: (MTP.h)
/usr/share/arduino/hardware/teensy/avr/libraries/Audio/Storage.h:42: warning: "FILE_WRITE_BEGIN" redefined
   42 |         #define FILE_WRITE_BEGIN (O_RDWR | O_CREAT)
      |
In file included from /usr/share/arduino/hardware/teensy/avr/libraries/SD/src/SD.h:38,
                 from /usr/share/arduino/hardware/teensy/avr/libraries/Audio/play_sd_raw.h:32,
                 from /usr/share/arduino/hardware/teensy/avr/libraries/Audio/Audio.h:127,
                 /home/domingo/Desktop/Teensy/MTPWMXZ/MTPWMXZ.ino:6: (Audio.h)
/usr/share/arduino/hardware/teensy/avr/cores/teensy4/FS.h:39: note: this is the location of the previous definition
   39 | #define FILE_WRITE_BEGIN 2
 
Updated Github.
There is a conflict to Fs.h, which I'm not using in Storage.
I removed SD.h from Storage and use SdFat directly in Storage
Note: if you are using SD.h, somewhere else, check if this generates issues, and let me know
 
Last edited:
I use actually SD.h to record WAV files, which I retrieve later via MTP. With the latest updated git I get again some errors, as follows. I attach the full code at the end, sorry it's a bit long.

ERRORS
Code:
In file included from /usr/share/arduino/hardware/teensy/avr/libraries/Audio/MTP.h:37,
                 from /home/chuma/Desktop/Teensy/PeakLED_MTPWMXZ/PeakLED_MTPWMXZ.ino:13:
/usr/share/arduino/hardware/teensy/avr/libraries/Audio/Storage.h:50: warning: "FILE_READ" redefined
   50 | #define FILE_READ  O_READ
      |
In file included from /usr/share/arduino/hardware/teensy/avr/libraries/SD/src/SD.h:38,
                 from /usr/share/arduino/hardware/teensy/avr/libraries/Audio/play_sd_raw.h:32,
                 from /usr/share/arduino/hardware/teensy/avr/libraries/Audio/Audio.h:127,
                 from /home/chuma/Desktop/Teensy/PeakLED_MTPWMXZ/PeakLED_MTPWMXZ.ino:6:
/usr/share/arduino/hardware/teensy/avr/cores/teensy4/FS.h:37: note: this is the location of the previous definition
   37 | #define FILE_READ  0
      |
In file included from /usr/share/arduino/hardware/teensy/avr/libraries/Audio/MTP.h:37,
                 from /home/chuma/Desktop/Teensy/PeakLED_MTPWMXZ/PeakLED_MTPWMXZ.ino:13:
/usr/share/arduino/hardware/teensy/avr/libraries/Audio/Storage.h:51: warning: "FILE_WRITE" redefined
   51 | #define FILE_WRITE  (O_RDWR | O_CREAT | O_AT_END)
      |
In file included from /usr/share/arduino/hardware/teensy/avr/libraries/SD/src/SD.h:38,
                 from /usr/share/arduino/hardware/teensy/avr/libraries/Audio/play_sd_raw.h:32,
                 from /usr/share/arduino/hardware/teensy/avr/libraries/Audio/Audio.h:127,
                 from /home/chuma/Desktop/Teensy/PeakLED_MTPWMXZ/PeakLED_MTPWMXZ.ino:6:
/usr/share/arduino/hardware/teensy/avr/cores/teensy4/FS.h:38: note: this is the location of the previous definition
   38 | #define FILE_WRITE 1
      |
In file included from /usr/share/arduino/hardware/teensy/avr/libraries/Audio/MTP.h:37,
                 from /home/chuma/Desktop/Teensy/PeakLED_MTPWMXZ/PeakLED_MTPWMXZ.ino:13:
/usr/share/arduino/hardware/teensy/avr/libraries/Audio/Storage.h:52: warning: "FILE_WRITE_BEGIN" redefined
   52 | #define FILE_WRITE_BEGIN (O_RDWR | O_CREAT)
      |
In file included from /usr/share/arduino/hardware/teensy/avr/libraries/SD/src/SD.h:38,
                 from /usr/share/arduino/hardware/teensy/avr/libraries/Audio/play_sd_raw.h:32,
                 from /usr/share/arduino/hardware/teensy/avr/libraries/Audio/Audio.h:127,
                 from /home/chuma/Desktop/Teensy/PeakLED_MTPWMXZ/PeakLED_MTPWMXZ.ino:6:
/usr/share/arduino/hardware/teensy/avr/cores/teensy4/FS.h:39: note: this is the location of the previous definition
   39 | #define FILE_WRITE_BEGIN 2


FULL CODE
Code:
//Use following Audio Library (SD Buffered)
//https://github.com/h4yn0nnym0u5e/Audio/tree/feature/buffered-SD
//Uses WMXZ MTP_T4 library.
//https://github.com/WMXZ-EU/MTP_t4
//Replace content in /usr/share/arduino/hardware/teensy/avr/libraries/Audio

#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <Bounce.h>
#include <SerialFlash.h>
#include <EEPROM.h>
#include "MTP.h"

//AudioEffectEnvelope      envelope1;      //xy=459.99998474121094,771.249921798706
AudioInputI2S            i2s1;           //xy=220,698
AudioInputUSB            usb2;           //xy=223,853
AudioPlayWAVstereo       playWAVstereo1;     //xy=244,609
AudioRecordWAVstereo     recordWAVstereo1; //xy=321,98
AudioMixer4              mixer1;         //xy=468,691
AudioMixer4              mixer2;         //xy=467,769
AudioMixer4              mixer3;         //xy=470,854
AudioMixer4              mixer4;         //xy=482,934
AudioAnalyzePeak         peak1;          //xy=743
AudioAnalyzePeak         peak2;          //xy=603,576
AudioOutputI2S2          i2s2_1;         //xy=643,732
AudioOutputUSB           usb1;           //xy=649,914
AudioConnection          patchCord1(i2s1, 0, mixer1, 0);
AudioConnection          patchCord2(i2s1, 1, mixer2, 0);
AudioConnection          patchCord3(i2s1, 0, mixer3, 0);
AudioConnection          patchCord4(i2s1, 1, mixer4, 0);
AudioConnection          patchCord5(playWAVstereo1, 0, mixer1, 2);
AudioConnection          patchCord6(playWAVstereo1, 1, mixer2, 2);
AudioConnection          patchCord7(usb2, 0, mixer1, 1);
AudioConnection          patchCord8(usb2, 1, mixer2, 1);
AudioConnection          patchCord9(mixer1, 0, i2s2_1, 0);
AudioConnection          patchCord10(i2s1, 0, recordWAVstereo1, 0);
AudioConnection          patchCord11(i2s1, 0, peak1, 0);
AudioConnection          patchCord12(mixer2, 0, i2s2_1, 1);
AudioConnection          patchCord13(i2s1, 1, recordWAVstereo1, 1);
AudioConnection          patchCord14(mixer3, 0, usb1, 0);
AudioConnection          patchCord15(mixer4, 0, usb1, 1);
AudioConnection          patchCord16(i2s1, 1, peak2, 0);

//MTP
#define USE_SD  1         // SDFAT based SDIO and SPI

#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_SDCARD
    #define BUILTIN_SDCARD 254
  #endif
  void usb_mtp_configure(void) {}
#endif

// SDClasses (Start device specific change area)
#if USE_SD==1
  // edit SPI to reflect your configuration (following is for T4.1)
  #define SD_MOSI 11
  #define SD_MISO 12
  #define SD_SCK  13

  #if defined (BUILTIN_SDCARD)
    const char *sd_str[]={"sdio"}; // edit to reflect your configuration
    const int cs[] = {BUILTIN_SDCARD,10}; // edit to reflect your configuration
  #else
    const char *sd_str[]={"sd1"}; // 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

MTPStorage_SD storage;
MTPD    mtpd(&storage);

void storage_configure()
{
  // Using SD card for storage
  #if USE_SD==1
    for(int ii=0; ii<nsd; ii++)
    {
      if(cs[ii]<BUILTIN_SDCARD)
      {
        pinMode(cs[ii],OUTPUT); digitalWriteFast(cs[ii],HIGH);
      }
      if(!sdx[ii].begin(cs[ii]))
      { Serial.printf("SD/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("; total "); Serial.print(totalSize); Serial.print(" used: "); Serial.println(usedSize);
      }
    }
  #endif
}
//End MTP

const int pdnADC = 22;
const int pdnDAC = 1;
//const int VOLUME_POT = 14;
int anodeLED = 12;
int redLED = 15;
int greenLED = 14;
float peak;

int anodeBrightness = 0;
int dB0_Brightness = 0;

int drive20dB_v = 20;
int drive12dB_v = 20;
int drive6dB_v = 20;
int drive3dB_v = 20;
int drive0dB_v = 20;

int dB20;
int dB12;
int dB6;
int dB3;
int dB0;
int strobe_v = 0;

elapsedMillis msecPeak;

elapsedMillis drive20dB;
elapsedMillis wait20dB;

elapsedMillis drive12dB;
elapsedMillis wait12dB;

elapsedMillis drive6dB;
elapsedMillis wait6dB;

elapsedMillis drive3dB;
elapsedMillis wait3dB;

elapsedMillis drive0dB;
elapsedMillis wait0dB;
elapsedMillis strobe;

elapsedMillis msecRec;


Bounce buttonRecord = Bounce(7, 8);
Bounce buttonStop =   Bounce(9, 8);  // 8 = 8 ms debounce time
Bounce buttonPlay =   Bounce(10, 8);

#define SDCARD_CS_PIN    BUILTIN_SDCARD
#define SDCARD_MOSI_PIN  11  // not actually used
#define SDCARD_SCK_PIN   13  // not actually used

// Remember which mode we're doing
int mode = 0;  // 0=stopped, 1=recording, 2=playing

int File_Number;
int address = 10;

// The file where data is recorded
File frec;


void setup() {

  AudioMemory(120);

//MTP
{
  #if USE_EVENTS==1
    usb_init_events();
  #endif

  #if !__has_include("usb_mtp.h")
    usb_mtp_configure();
  #endif
  storage_configure();
}
//End MTP

  pinMode(pdnADC, OUTPUT);
  delay(10);               // wait
  digitalWrite(pdnADC, HIGH);    // set the PDN on

  pinMode(pdnDAC, OUTPUT);
  delay(10);               // wait
  digitalWrite(pdnDAC, HIGH);    // set the PDN on

  pinMode(anodeLED, OUTPUT);
  pinMode(redLED, OUTPUT);
  pinMode(greenLED, OUTPUT);
 
 
  //mdr20190828 IOMUXC stuff below was required to get SDcard to work and to attach to other boards.
  //from: https://forum.pjrc.com/threads/57167-Teensy-4-0-I2S-Support?p=213128&viewfull=1#post213128
  // defaults were all 0x10B0 which is keeper, Medium speed (100 Mhz), drive strength = R0/6 = 150/6 = 25 ohms (the second strongest drive strength available) // My changes were:
  IOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B1_09 = 0x8; // MCLK, low speed, drive strength at R0 (150 ohm).
  IOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B1_10 = 0x8; // LRCLK
  IOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B1_11 = 0x8; // BCKL
  IOMUXC_SW_PAD_CTL_PAD_GPIO_B1_01 = 0x8; // OUT1A
  IOMUXC_SW_PAD_CTL_PAD_GPIO_B1_00 = 0x8; // IN1
  IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_04 = 0x8; // OUT2
  IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_05 = 0x8; // LRCLK2
  IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_06 = 0x8; // BCLK2
  IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_07 = 0x8; // MCLK2
  IOMUXC_SW_PAD_CTL_PAD_GPIO_B1_00 = 0x8; // IN2
  IOMUXC_SW_MUX_CTL_PAD_GPIO_SD_B0_00 = 0x8;
 // IOMUXC_SW_MUX_CTL_PAD_GPIO_SD_B0_01 = 0x8; //CLK
  IOMUXC_SW_MUX_CTL_PAD_GPIO_SD_B0_02 = 0x8;
  IOMUXC_SW_MUX_CTL_PAD_GPIO_SD_B0_03 = 0x8;
  IOMUXC_SW_MUX_CTL_PAD_GPIO_SD_B0_04 = 0x8;
  IOMUXC_SW_MUX_CTL_PAD_GPIO_SD_B0_05 = 0x8;
  IOMUXC_SW_PAD_CTL_PAD_GPIO_B1_02 = 0x8; // PIN 14

 
  // Configure the pushbutton pins
  pinMode(7, INPUT_PULLUP);
  pinMode(9, INPUT_PULLUP);
  pinMode(10, INPUT_PULLUP);

  // Initialize the SD card
  SPI.setMOSI(SDCARD_MOSI_PIN);
  SPI.setSCK(SDCARD_SCK_PIN);
  if (!(SD.begin(SDCARD_CS_PIN))) {
      Serial.println("Unable to access the SD card");
  }

    // SD audio objects need buffers configuring:
  const size_t sz = 65536;
  const AudioBuffer::bufType bufMem = AudioBuffer::inHeap;
  playWAVstereo1.createBuffer(sz,bufMem);
  recordWAVstereo1.createBuffer(sz,bufMem);

  //Filename numbers
  File_Number = EEPROM16_Read(address);
  Serial.print("Actual File Number: ");
  Serial.println(File_Number);

}

void loop() {
//MTP
  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
//End MTP

  if (msecPeak > 20) {
    if (peak1.available() && peak2.available()) {
      msecPeak = 0;
      float leftPeak = peak1.read();
      float rightPeak = peak2.read();

      if (leftPeak > rightPeak) {
      peak = leftPeak;
      } else {
      peak = rightPeak;
      }
    }
  }

  //40dB
  if ((peak < 0.10) && (dB20 < 1) && (dB12 < 1) && (dB6 < 1) && (dB3 < 1) && (dB0 < 1)){
    analogWrite(greenLED, 255);
    analogWrite(redLED, 255);
  }

  //20dB
  if (drive20dB > drive20dB_v) {
    drive20dB = 0;
    drive20dB_v = 20;
    dB20 = 0;
    if ((peak > 0.10) && (peak < 0.25) && (dB12 < 1) && (dB6 < 1) && (dB3 < 1) && (dB0 < 1)) {
      dB20 = 2;
      analogWrite(greenLED, 180);
      analogWrite(redLED, 255);
      wait20dB = 0;
      if (wait20dB < 400) {
        drive20dB_v = 400;
      }
    }
  }
      
  //12dB
  if (drive12dB > drive12dB_v) {
    drive12dB = 0;
    drive12dB_v = 20;
    dB12 = 0;
    if ((peak > 0.25) && (peak < 0.5) && (dB6 < 1) && (dB3 < 1) && (dB0 < 1)) {
      dB12 = 2;
      analogWrite(greenLED, 0);
      analogWrite(redLED, 255);
      wait12dB = 0;
      if (wait12dB < 400) {
        drive12dB_v = 400;
      }
    }
  }

  //6dB
  if (drive6dB > drive6dB_v) {
    drive6dB = 0;
    drive6dB_v = 20;
    dB6 = 0;
    if ((peak > 0.5) && (peak < 0.7) && (dB3 < 1) && (dB0 < 1)) {
      dB6 = 2;
      analogWrite(redLED, 0);
      analogWrite(greenLED, 0);
      wait6dB = 0;
      if (wait6dB < 600) {
        drive6dB_v = 600;
      }
    }
  }

  //3dB
  if (drive3dB > drive3dB_v) {
    drive3dB = 0;
    drive3dB_v = 20;
    dB3 = 0;
    if ((peak > 0.7) && (peak < 0.99) && (dB0 < 1)) {
      dB3 = 2;
      analogWrite(redLED, 80);
      analogWrite(greenLED, 255);
      wait3dB = 0;
      if (wait3dB < 800) {
        drive3dB_v = 800;
      }
    }
  }

  //0dB
  if (drive0dB > drive0dB_v) {
    drive0dB = 0;
    drive0dB_v = 20;
    dB0 = 0;
    strobe_v = 0;
    if (peak >= 1) { 
      dB0 = 2;
      wait0dB = 0;
      if (wait0dB < 2000) {
        drive0dB_v = 2000;
        strobe_v = 2;
        }
      }
    }
  if (strobe_v > 1) {
    if (strobe >= 200) {
      strobe = 0;
      dB0_Brightness = (dB0_Brightness == 255) ? 0 : 255;
      analogWrite(redLED, dB0_Brightness);
      analogWrite(greenLED, 255);
    }
  }

 
// Serial.println(dB40_redBrightness);
 
//  float vol = analogRead(VOLUME_POT);
//   vol = vol / 1023;
//  mixer1.gain(0, 1*vol);
//  mixer2.gain(0, 1*vol);
 
  //Serial.print("Digital volume is: ");
  //Serial.println(vol);
  //delay(250);
 
  // First, read the buttons
  buttonRecord.update();
  buttonStop.update();
  buttonPlay.update();

  // Respond to button presses
  if (buttonRecord.fallingEdge()) {
    Serial.println("Record Button Press");
    if (mode == 2) stopPlaying();
    if (mode == 0) startRecording();
  }
  if (buttonStop.fallingEdge()) {
    Serial.println("Stop Button Press");
    if (mode == 1) stopRecording();
    if (mode == 2) stopPlaying();
  }
  if (buttonPlay.fallingEdge()) {
    Serial.println("Play Button Press");
    if (mode == 1) stopRecording();
    if (mode == 0) startPlaying();
//    if (mode == 2) playPrevious();
  }


  if (mode == 1) {
    continueRecording();
  if (msecRec >= 50) {
    msecRec = 0;
    anodeBrightness = (anodeBrightness == 0) ? 255 : 0;
    analogWrite(anodeLED, anodeBrightness);
    }
  }

  if (mode == 2) {
    continuePlaying();
  }
  if (mode == 0) {
    anodeBrightness = 255;
    analogWrite(anodeLED, anodeBrightness);
  }
}


void startRecording() {
  Serial.print("startRecording RECORD_");
  Serial.println(File_Number);
  char buffer[40];
  sprintf(buffer, "%d.wav", File_Number);
  if (SD.exists(buffer)) { 
    // The SD library writes new data to the end of the
    // file, so to start a new recording, the old file
    // must be deleted before new data is written.
    SD.remove(buffer);
  }
  frec = SD.open(buffer, FILE_WRITE);
  if (frec) {

 
patchCord9.disconnect();
patchCord12.disconnect();
delay(200);
patchCord9.connect();
patchCord12.connect();
 
  recordWAVstereo1.recordSD(buffer);
  mode = 1;
  }
}


void continueRecording() {
  // nothing to do here!
}

void stopRecording() {
  Serial.println("stopRecording");
  recordWAVstereo1.stop();

  patchCord9.disconnect();
  patchCord12.disconnect();
  delay(200);
  patchCord9.connect();
  patchCord12.connect();
 
  File_Number = File_Number + 1;
  EEPROM16_Write(address, File_Number);
  mode = 0;
}


void startPlaying() {
  Serial.print("startPlaying RECORD_");
  Serial.println(File_Number - 1);
 
  char buffer[40];
  sprintf(buffer, "%d.wav", File_Number - 1);
 
  playWAVstereo1.playSD(buffer);
  patchCord1.disconnect();
  patchCord2.disconnect();
  mode = 2;
}

void continuePlaying() {
  if (!playWAVstereo1.isPlaying())
  {
    Serial.println("endOfPlayback");
   patchCord1.connect();
   patchCord2.connect();
    mode = 0;
  }
}
 
void stopPlaying() {
  Serial.println("stopPlaying");
  playWAVstereo1.stop();
  patchCord1.connect();
  patchCord2.connect();
  mode = 0;
}

void EEPROM16_Write(uint8_t a, uint16_t b) {
  EEPROM.write(a, lowByte(b));
  EEPROM.write(a + 1, highByte(b));
}

uint16_t EEPROM16_Read(uint8_t a) {
  return word(EEPROM.read(a + 1), EEPROM.read(a));
}
 
Where does Storage.h come from? Pretty sure it’s not in my buffered playback/record Audio library… You could maybe try deleting it temporarily to see if it gets rid of the warnings (they’re not errors), and your sketch still works.
 
@hyn0nnym0u5e. Storage.h is from MTP_t4
Maybe one can get rid of the definitions, They arise from the fact that PJRC's SdFat implementation is diverged from Greiman's original without following Greimans modifications. As the symbol is only used in 3 locations, I will modify it to avoid conflicts.

Edit: removed the #defines and changed symbols in code (AKA avoid preprocessor). Github updated.
 
Last edited:
At the risk of hijacking the thread - we have hit a weird issue with the MTP library. If we have around 200 or more files in the directory then some files are missing from the directory listing.

We have a data logger that is generating files with sequential file names. Once there are over 200 files we start seeing gaps in the names of the files that show up. But if we remove the SD card and check directly they are all there. Rebooting / re-initialising MTP seems to change which files are missing. There is no obvious pattern to which files are skipped.

We are using a modified version of the file system and running this over the USB2 port with some modified drivers. The MTP code is very close to your latest version (I just merged in the file timestamp changes, thanks :)) with the minimal changes needed for the filesystem and USB changes. There is enough non-standard about the setup that this could well be an us problem but it's odd that it works fine when there are less files in the directory. Any ideas on where to look would be appreciated.

-- edit --
Increasing RX_NUM in usb_mtp.c seems to have improved things.
 
Last edited:
There may be a speed issue with USB2 (Teensy sending data too fast while scanning directories).
I admit that I have not worked on MTP_t4 for a while (especially after KurtE's version was getting speed). However I use it in nearly all my data acquisition systems). Further, I always structure my directories to have a reasonable number of entries (daily, hourly, etc) and therefore I did not encounter this issue.
 
Very nice @WMXZ. My program compiles now without any warnings and SD.h (@h4yn0nnym0u5e code) is unaffected. All tip-top :) Bless you.

I wonder if you guys ever play or open files directly from the Teensy/SD card via MTP, or rather always copy them to a local drive before. File transfers are super fast, also mounting and file listing. But if I ever dare to double click on any file directly on the file browser things will freeze for a long long time.
I know MTP is mostly a transfer protocol, but I just wonder if there are methods for reading files directly from the file browser. Different tools in linux give me different results actually. gvfs-mtp is very fast and effective for file transfers, but horrible at playback. simple-mtfs is a bit better in playback, but horrible at file transfers and listing. I wonder what are your experiences in this regard, it would be cool to preview files before copying them

@AndyA I haven't noticed any files missing so far but didn't reach the 200+ file count yet. My files are relatively large, so slower and easier to index I hope.
 
To access a teensy file from a program, you need some SW that lets you mount the file. I use windows and there is no easy way to get the device letter assigned to Teensy disk without another interface layer. Also one needs very likely partial access to file. Do not recall if this was implemented correctly and tested. Anyhow I recall that double clicking on a text file allowed it to be opened by an editor to see the text. However, what is happening is that PC copies file first into temporary storage before opening it. Remember: MTP is not a FS, so it has no knowledge on where the data is written on disk.
 
I suspect our issue could be resolved by calling the loop function more frequently and so preventing the receive buffers from filling up as much. But the system is doing a lot of other things at the same time so that's not the easiest thing to do. It could well be that simpler applications that run through the background loop faster don't have the same issue.
A nicer directory structure would be good but we want to maintain the structure/naming convention of older products :-(
Fortunately this is purely a test/debug feature, it lets the automated test system read the log files without having an operator remove the card. So while not ideal we can simply structure the tests so that there are never that many files.
 
My own use case is that I exclude MTP while doing data acquisition, and respond to MTP only when acquisition is stopped. I asynchronous handling of MTP request is possible and I have done it in the past. Simply use a timer to run the MTP loop()
 
Back
Top