MTP_Teensy example "mtp-logger.ino" compile error, on T4.1.

Sandro

Well-known member
Hi all,
I would try to make the SD card on T4.1 accessible as a mass storage from my Windows PC via USB connection; I manually installed MTP_Teensy. I use Arduino IDE 2.2.1 with Teensy tools (https://www.pjrc.com/teensy/package_teensy_index.json) and Teensy library 1.58.1 installed.
Than, trying to compile mtp-logger.ino example, I get this error (copied from the last part of the compile output window):
Code:
Generating function prototypes...
C:\Users\dell\AppData\Local\Arduino15\packages\teensy\tools\teensy-compile\11.3.1/arm/bin/arm-none-eabi-g++ -E -CC -x c++ -w -g -Wall -ffunction-sections -fdata-sections -nostdlib -std=gnu++14 -fno-exceptions -fpermissive -fno-rtti -fno-threadsafe-statics -felide-constructors -Wno-error=narrowing -mthumb -mcpu=cortex-m7 -mfloat-abi=hard -mfpu=fpv5-d16 -D__IMXRT1062__ -DTEENSYDUINO=158 -DARDUINO=10607 -DARDUINO_TEENSY41 -DF_CPU=600000000 -DUSB_SERIAL -DLAYOUT_US_ENGLISH -IC:\Users\dell\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.58.1\cores\teensy4 -Ic:\Users\dell\Il mio Drive\ARDUINO SKETCHES\libraries\MTP_Teensy\src -IC:\Users\dell\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.58.1\libraries\SD\src -IC:\Users\dell\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.58.1\libraries\SdFat\src -IC:\Users\dell\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.58.1\libraries\SPI C:\Users\dell\AppData\Local\Temp\arduino\sketches\5B00F4227D36D543B91859DE7CAC1D4C\sketch\mtp-logger.ino.cpp -o C:\Users\dell\AppData\Local\Temp\863624219\sketch_merged.cpp
In file included from C:\Users\dell\Desktop\mtp-logger\mtp-logger.ino:18:
c:\Users\dell\Il mio Drive\ARDUINO SKETCHES\libraries\MTP_Teensy\src/MTP_Teensy.h:32:2: error: #error "You need to select USB Type: 'MTP Disk (Experimental)' or 'Serial + MTP Disk (Experimental)'"
   32 | #error "You need to select USB Type: 'MTP Disk (Experimental)' or 'Serial + MTP Disk (Experimental)'"
      |  ^~~~~
Multiple libraries were found for "SD.h"
  Used: C:\Users\dell\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.58.1\libraries\SD
  Not used: C:\Users\dell\AppData\Local\Arduino15\libraries\SD
Using library MTP_Teensy at version 1.0.0 in folder: C:\Users\dell\Il mio Drive\ARDUINO SKETCHES\libraries\MTP_Teensy 
Using library SD at version 2.0.0 in folder: C:\Users\dell\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.58.1\libraries\SD 
Using library SdFat at version 2.1.2 in folder: C:\Users\dell\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.58.1\libraries\SdFat 
Using library SPI at version 1.0 in folder: C:\Users\dell\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.58.1\libraries\SPI 
exit status 1

Compilation error: exit status 1

Anyone knows what should I do?
Thanks in advance!
 
The error message hopefully points you in the right direction:
Code:
   32 | #error "You need to select USB Type: 'MTP Disk (Experimental)' or 'Serial + MTP Disk (Experimental)'"

You need to choose one of those two USB types to build with.
Screenshot.png
one of the two with my rough drawn in red arrows
 
if I select MTP Disk I get this error:
Code:
C:\Users\dell\Desktop\mtp-logger\mtp-logger.ino:57:1: error: 'MTPD' does not name a type
   57 | MTPD mtpd(&storage);
      | ^~~~
C:\Users\dell\Desktop\mtp-logger\mtp-logger.ino: In function 'void storage_configure()':
C:\Users\dell\Desktop\mtp-logger\mtp-logger.ino:74:28: error: no matching function for call to 'MTPStorage::addFilesystem(SDClass&, const char*&)'
   74 |       storage.addFilesystem(sdx[ii], sd_str[ii]);
      |       ~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~
In file included from c:\Users\dell\Il mio Drive\ARDUINO SKETCHES\libraries\MTP_Teensy\src/MTP_Teensy.h:45,
                 from C:\Users\dell\Desktop\mtp-logger\mtp-logger.ino:18:
c:\Users\dell\Il mio Drive\ARDUINO SKETCHES\libraries\MTP_Teensy\src/MTP_Storage.h:123:18: note: candidate: 'uint32_t MTPStorage::addFilesystem(FS&, const char*, mtp_fstype_t)'
  123 |         uint32_t addFilesystem(FS &disk, const char *diskname, mtp_fstype_t fstype);
      |                  ^~~~~~~~~~~~~
c:\Users\dell\Il mio Drive\ARDUINO SKETCHES\libraries\MTP_Teensy\src/MTP_Storage.h:123:18: note:   candidate expects 3 arguments, 2 provided
C:\Users\dell\Desktop\mtp-logger\mtp-logger.ino:83:28: error: no matching function for call to 'MTPStorage::addFilesystem(SDClass&, const char*&)'
   83 |       storage.addFilesystem(sdx[ii], sd_str[ii]);
      |       ~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~
In file included from c:\Users\dell\Il mio Drive\ARDUINO SKETCHES\libraries\MTP_Teensy\src/MTP_Teensy.h:45,
                 from C:\Users\dell\Desktop\mtp-logger\mtp-logger.ino:18:
c:\Users\dell\Il mio Drive\ARDUINO SKETCHES\libraries\MTP_Teensy\src/MTP_Storage.h:123:18: note: candidate: 'uint32_t MTPStorage::addFilesystem(FS&, const char*, mtp_fstype_t)'
  123 |         uint32_t addFilesystem(FS &disk, const char *diskname, mtp_fstype_t fstype);
      |                  ^~~~~~~~~~~~~
c:\Users\dell\Il mio Drive\ARDUINO SKETCHES\libraries\MTP_Teensy\src/MTP_Storage.h:123:18: note:   candidate expects 3 arguments, 2 provided
C:\Users\dell\Desktop\mtp-logger\mtp-logger.ino:102:28: error: no matching function for call to 'MTPStorage::addFilesystem(LittleFS_RAM&, const char*&)'
  102 |       storage.addFilesystem(ramfs[ii], lfs_str[ii]);
      |       ~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
In file included from c:\Users\dell\Il mio Drive\ARDUINO SKETCHES\libraries\MTP_Teensy\src/MTP_Teensy.h:45,
                 from C:\Users\dell\Desktop\mtp-logger\mtp-logger.ino:18:
c:\Users\dell\Il mio Drive\ARDUINO SKETCHES\libraries\MTP_Teensy\src/MTP_Storage.h:123:18: note: candidate: 'uint32_t MTPStorage::addFilesystem(FS&, const char*, mtp_fstype_t)'
  123 |         uint32_t addFilesystem(FS &disk, const char *diskname, mtp_fstype_t fstype);
      |                  ^~~~~~~~~~~~~
c:\Users\dell\Il mio Drive\ARDUINO SKETCHES\libraries\MTP_Teensy\src/MTP_Storage.h:123:18: note:   candidate expects 3 arguments, 2 provided
C:\Users\dell\Desktop\mtp-logger\mtp-logger.ino: In function 'void loop()':
C:\Users\dell\Desktop\mtp-logger\mtp-logger.ino:149:5: error: 'mtpd' was not declared in this scope; did you mean 'mtp'?
  149 |     mtpd.loop();
      |     ^~~~
      |     mtp
if i choose Serial + MTP Disk the message seems the same:
Code:
C:\Users\dell\Desktop\mtp-logger\mtp-logger.ino:57:1: error: 'MTPD' does not name a type
   57 | MTPD mtpd(&storage);
      | ^~~~
C:\Users\dell\Desktop\mtp-logger\mtp-logger.ino: In function 'void storage_configure()':
C:\Users\dell\Desktop\mtp-logger\mtp-logger.ino:74:28: error: no matching function for call to 'MTPStorage::addFilesystem(SDClass&, const char*&)'
   74 |       storage.addFilesystem(sdx[ii], sd_str[ii]);
      |       ~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~
In file included from c:\Users\dell\Il mio Drive\ARDUINO SKETCHES\libraries\MTP_Teensy\src/MTP_Teensy.h:45,
                 from C:\Users\dell\Desktop\mtp-logger\mtp-logger.ino:18:
c:\Users\dell\Il mio Drive\ARDUINO SKETCHES\libraries\MTP_Teensy\src/MTP_Storage.h:123:18: note: candidate: 'uint32_t MTPStorage::addFilesystem(FS&, const char*, mtp_fstype_t)'
  123 |         uint32_t addFilesystem(FS &disk, const char *diskname, mtp_fstype_t fstype);
      |                  ^~~~~~~~~~~~~
c:\Users\dell\Il mio Drive\ARDUINO SKETCHES\libraries\MTP_Teensy\src/MTP_Storage.h:123:18: note:   candidate expects 3 arguments, 2 provided
C:\Users\dell\Desktop\mtp-logger\mtp-logger.ino:83:28: error: no matching function for call to 'MTPStorage::addFilesystem(SDClass&, const char*&)'
   83 |       storage.addFilesystem(sdx[ii], sd_str[ii]);
      |       ~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~
In file included from c:\Users\dell\Il mio Drive\ARDUINO SKETCHES\libraries\MTP_Teensy\src/MTP_Teensy.h:45,
                 from C:\Users\dell\Desktop\mtp-logger\mtp-logger.ino:18:
c:\Users\dell\Il mio Drive\ARDUINO SKETCHES\libraries\MTP_Teensy\src/MTP_Storage.h:123:18: note: candidate: 'uint32_t MTPStorage::addFilesystem(FS&, const char*, mtp_fstype_t)'
  123 |         uint32_t addFilesystem(FS &disk, const char *diskname, mtp_fstype_t fstype);
      |                  ^~~~~~~~~~~~~
c:\Users\dell\Il mio Drive\ARDUINO SKETCHES\libraries\MTP_Teensy\src/MTP_Storage.h:123:18: note:   candidate expects 3 arguments, 2 provided
C:\Users\dell\Desktop\mtp-logger\mtp-logger.ino:102:28: error: no matching function for call to 'MTPStorage::addFilesystem(LittleFS_RAM&, const char*&)'
  102 |       storage.addFilesystem(ramfs[ii], lfs_str[ii]);
      |       ~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
In file included from c:\Users\dell\Il mio Drive\ARDUINO SKETCHES\libraries\MTP_Teensy\src/MTP_Teensy.h:45,
                 from C:\Users\dell\Desktop\mtp-logger\mtp-logger.ino:18:
c:\Users\dell\Il mio Drive\ARDUINO SKETCHES\libraries\MTP_Teensy\src/MTP_Storage.h:123:18: note: candidate: 'uint32_t MTPStorage::addFilesystem(FS&, const char*, mtp_fstype_t)'
  123 |         uint32_t addFilesystem(FS &disk, const char *diskname, mtp_fstype_t fstype);
      |                  ^~~~~~~~~~~~~
c:\Users\dell\Il mio Drive\ARDUINO SKETCHES\libraries\MTP_Teensy\src/MTP_Storage.h:123:18: note:   candidate expects 3 arguments, 2 provided
C:\Users\dell\Desktop\mtp-logger\mtp-logger.ino: In function 'void loop()':
C:\Users\dell\Desktop\mtp-logger\mtp-logger.ino:149:5: error: 'mtpd' was not declared in this scope; did you mean 'mtp'?
  149 |     mtpd.loop();
      |     ^~~~
      |     mtp
 
@Sandro
the mtp_logger was designed as example for the original MTP port to Teensy https://github.com/WMXZ-EU/MTP_t4. Meanwhile @KurtE developed it to MTP_Teensy (adapting MTP_t4 also to his own programming style). So mtp_logger.ino in the MTP_Teensy/examples folder may not be compatiple anymore.

At some time in the future Paul will digest/adapt MTP to the Teensy-libraries ecosystem. Until that time I will not modify MTP_t4, as it is working for me.

As mtp-logger is only an example on how to combine data logging with MPT acccess, I guess you could modify this one or use one of the other logger examples in the MTP_Teensy library.
 
Thank you @defragster and @WMXZ; as soon as possible I'll experiment both your suggestions
 
@KurtE made some changes to MTP_teensy to simplify how MTP has to be configured. It looks like we never updated that example for the changes to MTP. Basically in looking at the current sketch:

Code:
MTPStorage storage;
MTPD mtpd(&storage);
These lines are no longer needed. They were replaced by
Code:
MTP.begin();
that you would add to setup before doing any configuring of the MTP storage. In a similar manner:
Code:
mtpd.loop();
becomes
Code:
MTP.loop();
and things like
Code:
storage.addfilesystem(....)
would become
Code:
MTP.addfilesystem(....)
. Makes it simpler in my opinion. So the MTP logger sketch would become:
Code:
#include "Arduino.h"

#define NDAT 128L
#define NCH_ACQ 1
#define NCH_I2S 4
#define NBUF_ACQ (NCH_ACQ * NDAT)
#define NBUF_I2S (NCH_I2S * NDAT)
#define N_ADC 2
#define FRAME_I2S (NCH_I2S / N_ADC)

#define I2S_CONFIG 1
// CONFIG 1 (PURE RX)
// PIN  36 BCLK
// PIN  37 FS
// PIN  13 RXD0
// PIN  38 RXD1

#include "MTP_Teensy.h"
#include "SD.h"

#if defined(__IMXRT1062__)
#include "usb_mtp.h"
#endif

#define USE_SD 1
#define USE_LITTLEFS 1 // set to zero if no LtttleFS is existing or to be used

/****  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

#define SPI_SPEED SD_SCK_MHZ(16) // adjust to sd card

// SDClasses
const char *sd_str[] = {"sdio", "sd6"}; // edit to reflect your configuration
const int cs[] = {BUILTIN_SDCARD, 38};  // edit to reflect your configuration
const int nsd = sizeof(cs) / sizeof(int);

SDClass sdx[nsd];
#endif

// LittleFS classes
#if USE_LITTLEFS == 1
#include "LittleFS.h"
const char *lfs_str[] = {"RAM1", "RAM2"}; // edit to reflect your configuration
const int lfs_size[] = {2'000'000, 4'000'000};
const int nfs = sizeof(lfs_size) / sizeof(int);

LittleFS_RAM
    ramfs[nfs]; // needs to be declared if LittleFS is used in storage.h
#endif

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 (cs[ii] == BUILTIN_SDCARD) {
      if (!sdx[ii].sdfs.begin(SdioConfig(FIFO_SDIO))) {
        Serial.println("No storage");
        while (1)
          ;
      };
      MTP.addFilesystem(sdx[ii], sd_str[ii]);
    } else if (cs[ii] < BUILTIN_SDCARD) {
      pinMode(cs[ii], OUTPUT);
      digitalWriteFast(cs[ii], HIGH);
      if (!sdx[ii].sdfs.begin(SdSpiConfig(cs[ii], SHARED_SPI, SPI_SPEED))) {
        Serial.println("No storage");
        while (1)
          ;
      }
      MTP.addFilesystem(sdx[ii], sd_str[ii]);
    }
    uint64_t totalSize = sdx[ii].totalSize();
    uint64_t usedSize = sdx[ii].usedSize();
    Serial.printf("Storage %d %d %s ", ii, cs[ii], sd_str[ii]);
    Serial.print(totalSize);
    Serial.print(" ");
    Serial.println(usedSize);
  }
#endif

#if USE_LITTLEFS == 1
  for (int ii = 0; ii < nfs; ii++) {
    {
      if (!ramfs[ii].begin(lfs_size[ii])) {
        Serial.println("No storage");
        while (1)
          ;
      }
      MTP.addFilesystem(ramfs[ii], lfs_str[ii]);
    }
    uint64_t totalSize = ramfs[ii].totalSize();
    uint64_t usedSize = ramfs[ii].usedSize();
    Serial.printf("Storage %d %s ", ii, lfs_str[ii]);
    Serial.print(totalSize);
    Serial.print(" ");
    Serial.println(usedSize);
  }
#endif
}
/****  End of device specific change area  ****/

void logg(uint32_t del, const char *txt);

int16_t state;
int16_t do_logger(uint16_t store, int16_t state);
int16_t do_menu(int16_t state);
int16_t check_filing(int16_t state);

void acq_init(int32_t fsamp);
int16_t acq_check(int16_t state);

void setup() {
  while (!Serial && millis() < 3000)
    ;
  Serial.println("MTP logger");

  MTP.begin();

  usb_mtp_configure();
  storage_configure();

  acq_init(93750); // is fixed for this example, to be modified below
  state = -1;

  Serial.println("Setup done");
  Serial.println(" Enter s to start acquisition and q to stop acquisition");
  Serial.flush();
}

uint32_t loop_count = 0;
void loop() {
  loop_count++;
  state = do_menu(state);
  state = acq_check(state);
  state = check_filing(state);
  //
  if (state < 0)
    MTP.loop();
  else
    state = do_logger(0, state);

  if (state >= 0)
    logg(1000, "loop");
  // asm("wfi"); // may wait forever on T4.x
}

/**************** Online logging *******************************/
extern uint32_t loop_count, acq_count, acq_miss, maxDel;
extern uint16_t maxCount;
void logg(uint32_t del, const char *txt) {
  static uint32_t to;
  if (millis() - to > del) {
    Serial.printf("%s: %6d %4d %4d %4d %4d %d\n", txt, loop_count, acq_count,
                  acq_miss, maxCount, maxDel, state);
    loop_count = 0;
    acq_count = 0;
    acq_miss = 0;
    maxCount = 0;
    maxDel = 0;
    to = millis();
  }
}

/*************************** Circular Buffer ********************/
#if defined ARDUINO_TEENSY41
#define HAVE_PSRAM 1
#else
#define HAVE_PSRAM 0
#endif

#if HAVE_PSRAM == 1
#define MAXBUF (1000) // 3000 kB   // < 5461 for 16 MByte PSRAM

//    extern "C" uint8_t external_psram_size;
//    uint8_t size = external_psram_size;
//    uint32_t *memory_begin = (uint32_t *)(0x70000000);
//    uint32_t *data_buffer = memory_begin;

uint32_t *data_buffer =
    (uint32_t *)extmem_malloc(MAXBUF * 128 * sizeof(uint32_t));
#else
#if defined(ARDUINO_TEENSY41)
#define MAXBUF (46) // 138 kB
#elif defined(ARDUINO_TEENSY40)
#define MAXBUF (46) // 138 kB
#elif defined(__MK66FX1M0__)
#define MAXBUF (46) // 138 kB
#elif defined(__MK20DX256__)
#define MAXBUF (12) // 36 kB
#endif
uint32_t data_buffer[MAXBUF * NBUF_ACQ];
#endif

static uint16_t front_ = 0, rear_ = 0;
uint16_t getCount() {
  if (front_ >= rear_)
    return front_ - rear_;
  return front_ + MAXBUF - rear_;
}
uint16_t maxCount = 0;

void resetData(void) {
  front_ = 0;
  rear_ = 0;
}

uint16_t pushData(uint32_t *src) {
  uint16_t f = front_ + 1;
  if (f >= MAXBUF)
    f = 0;
  if (f == rear_)
    return 0;

  uint32_t *ptr = data_buffer + f * NBUF_ACQ;
  memcpy(ptr, src, NBUF_ACQ * 4);
  front_ = f;
  //
  uint16_t count;
  count = (front_ >= rear_) ? (front_ - rear_) : front_ + (MAXBUF - rear_);
  if (count > maxCount)
    maxCount = count;
  //
  return 1;
}

uint16_t pullData(uint32_t *dst, uint32_t ndbl) {
  uint16_t r = (rear_ / ndbl);
  if (r == (front_ / ndbl))
    return 0;
  if (++r >= (MAXBUF / ndbl))
    r = 0;
  uint32_t *ptr = data_buffer + r * ndbl * NBUF_ACQ;
  memcpy(dst, ptr, ndbl * NBUF_ACQ * 4);
  rear_ = r * ndbl;
  return 1;
}

/*************************** Filing *****************************/
int16_t file_open(uint16_t store);
int16_t file_writeHeader(void);
int16_t file_writeData(void *diskBuffer, uint32_t ndbl);
int16_t file_close(void);
#define NDBL 1
#define NBUF_DISK (NDBL * NBUF_ACQ)
uint32_t diskBuffer[NBUF_DISK];
uint32_t maxDel = 0;

int16_t do_logger(uint16_t store, int16_t state) {
  uint32_t to = millis();
  if (pullData(diskBuffer, NDBL)) {
    if (state == 0) { // acquisition is running, need to open file
      if (!file_open(store))
        return -2;
      state = 1;
    }
    if (state == 1) { // file just opended, need to write header
      if (!file_writeHeader())
        return -3;
      state = 2;
    }
    if (state >= 2) { // write data to disk
      if (!file_writeData(diskBuffer, NBUF_DISK * 4))
        return -4;
    }
  }

  if (state == 3) { // close file, but continue acquisition
    if (!file_close())
      return -5;
    state = 0;
  }

  if (state == 4) { // close file and stop acquisition
    if (!file_close())
      return -6;
    state = -1;
  }

  uint32_t dt = millis() - to;
  if (dt > maxDel)
    maxDel = dt;

  return state;
}

/******************** Menu ***************************/
void do_menu1(void);
void do_menu2(void);
void do_menu3(void);

int16_t do_menu(int16_t state) { // check Serial input
  if (!Serial.available())
    return state;
  char cc = Serial.read();
  switch (cc) {
  case 's': // start acquisition
    if (state >= 0)
      return state;
    state = 0;
    Serial.println("\nStart");
    break;
  case 'q': // stop acquisition
    if (state < 0)
      return state;
    state = 4;
    Serial.println("\nStop");
    break;
  case '?': // get parameters
    do_menu1();
    break;
  case '!': // set parameters
    if (state >= 0)
      return state;
    do_menu2();
    break;
  case ':': // misc commands
    if (state >= 0)
      return state;
    do_menu3();
    break;
  default:
    break;
  }
  return state;
}

/************ Basic File System Interface *************************/
#include "SD.h"
extern SDClass sdx[];
static File mfile;

char header[512];

void makeHeader(char *header);
int16_t makeFilename(char *filename);
int16_t checkPath(uint16_t store, char *filename);

int16_t file_open(uint16_t store) {
  char filename[80];
  if (!makeFilename(filename))
    return 0;
  if (!checkPath(store, filename))
    return 0;
  mfile = sdx[store].open(filename, FILE_WRITE);
  return !(!mfile);
}

int16_t file_writeHeader(void) {
  if (!mfile)
    return 0;
  makeHeader(header);
  size_t nb = mfile.write(header, 512);
  return (nb == 512);
}

int16_t file_writeData(void *diskBuffer, uint32_t nd) {
  if (!mfile)
    return 0;
  uint32_t nb = mfile.write(diskBuffer, nd);
  return (nb == nd);
}

int16_t file_close(void) {
  mfile.close();
  return (!mfile);
}

/*
 * Custom Implementation
 *
 */
/************************ some utilities modified from time.cpp
 * ************************/
// leap year calculator expects year argument as years offset from 1970
#define LEAP_YEAR(Y)                                                           \
  (((1970 + (Y)) > 0) && !((1970 + (Y)) % 4) &&                                \
   (((1970 + (Y)) % 100) || !((1970 + (Y)) % 400)))

static const uint8_t monthDays[] = {31, 28, 31, 30, 31, 30,
                                    31, 31, 30, 31, 30, 31};

void day2date(uint32_t dd, uint32_t *day, uint32_t *month, uint32_t *year) {
  uint32_t yy = 0;
  uint32_t days = 0;
  while ((unsigned)(days += (LEAP_YEAR(yy) ? 366 : 365)) <= dd) {
    yy++;
  }

  days -= LEAP_YEAR(yy) ? 366 : 365;
  dd -= days; // now it is days in this year, starting at 0

  uint32_t mm = 0;
  uint32_t monthLength = 0;
  for (mm = 0; mm < 12; mm++) {
    monthLength = monthDays[mm];
    if ((mm == 1) && (LEAP_YEAR(yy)))
      monthLength++;
    if (dd >= monthLength) {
      dd -= monthLength;
    } else {
      break;
    }
  }

  *month = mm + 1; // jan is month 1
  *day = dd + 1;   // day of month
  *year = yy + 1970;
}

void date2day(uint32_t *dd, uint32_t day, uint32_t month, uint32_t year) {
  day -= 1;
  month -= 1;
  year -= 1970;
  uint32_t dx = 0;
  for (uint32_t ii = 0; ii < year; ii++) {
    dx += LEAP_YEAR(ii) ? 366 : 365;
  }
  for (uint32_t ii = 0; ii < month; ii++) {
    dx += monthDays[ii];
    if ((ii == 2) && (LEAP_YEAR(year)))
      dx++; // after feb check for leap year
  }
  *dd = dx + day;
}

/************* Menu implementation ******************************/
void do_menu1(void) { // get parameters
}
void do_menu2(void) { // set parameters
}
void do_menu3(void) { // misc commands
}

/****************** File Utilities *****************************/
void makeHeader(char *header) { memset(header, 0, 512); }

int16_t makeFilename(char *filename) {
  uint32_t tt = rtc_get();
  int hh, mm, ss;
  int dd;
  ss = tt % 60;
  tt /= 60;
  mm = tt % 60;
  tt /= 60;
  hh = tt % 24;
  tt /= 24;
  dd = tt;
  sprintf(filename, "/%d/%02d_%02d_%02d.raw", dd, hh, mm, ss);
  Serial.println(filename);
  return 1;
}

int16_t checkPath(uint16_t store, char *filename) {
  int ln = strlen(filename);
  int i1 = -1;
  for (int ii = 0; ii < ln; ii++)
    if (filename[ii] == '/')
      i1 = ii;
  if (i1 < 0)
    return 1; // no path
  filename[i1] = 0;
  if (!sdx[store].exists(filename)) {
    Serial.println(filename);
    if (!sdx[store].mkdir(filename))
      return 0;
  }

  filename[i1] = '/';
  return 1;
}

uint32_t t_on = 60;
int16_t check_filing(int16_t state) {
  static uint32_t to;
  if (state == 2) {
    uint32_t tt = rtc_get();
    uint32_t dt = tt % t_on;
    if (dt < to)
      state = 3;
    to = dt;
  }
  return state;
}

/****************** Data Acquisition
 * *******************************************/
#define DO_TEST 1
#define DO_I2S 2
#define DO_ACQ DO_TEST

#if DO_ACQ == DO_TEST
/****************** Intervall timer(dummy example)
 * *****************************/
#include "IntervalTimer.h"

IntervalTimer t1;

static uint32_t acq_buffer[NBUF_ACQ];

uint32_t acq_period = 1000;
int16_t acq_state = -1;
void acq_isr(void);

void acq_init(int32_t fsamp) {
  acq_period = 128'000'000 / fsamp;
  acq_state = 0;
}

void acq_start(void) {
  if (acq_state)
    return;
  resetData();
  t1.begin(acq_isr, acq_period);
  acq_state = 1;
}

void acq_stop(void) {
  if (acq_state <= 0)
    return;
  t1.end();
  acq_state = 0;
}

uint32_t acq_count = 0;
uint32_t acq_miss = 0;

void acq_isr(void) {
  acq_count++;
  for (int jj = 0; jj < NCH_ACQ; jj++) {
    for (int ii = 0; ii < NBUF_ACQ; ii++) {
      acq_buffer[jj + ii * NCH_ACQ] = acq_count;
    }
  }
  if (!pushData(acq_buffer))
    acq_miss++;
}

int16_t acq_check(int16_t state) {
  if (!state) { // start acquisition
    acq_start();
  }
  if (state > 3) { // stop acquisition
    acq_stop();
  }
  return state;
}
#else
// try I2S (not working yet)
static uint32_t tdm_rx_buffer[2 * NBUF_I2S];
static uint32_t acq_rx_buffer[NBUF_ACQ];
#define I2S_DMA_PRIO 6

#include "DMAChannel.h"
DMAChannel dma;

void acq_isr(void);

#if defined(__MK66FX1M0__)
// Teensy 3.6
#define MCLK_SRC 3
#define MCLK_SCALE 1

// set MCLK to 48 MHz or a integer fraction (MCLK_SCALE) of it
// MCLK_MULT is set to 1 or 2 to minimize jitter
// this reduces the possibilities for sampling frequencies

#if (F_PLL == 96000000) // PLL is 96 MHz for F_CPU==48 or F_CPU==96 MHz
#define MCLK_MULT 1
#define MCLK_DIV (2 * MCLK_SCALE)
//  #define MCLK_DIV  (3*MCLK_SCALE)
#elif F_PLL == 120000000
#define MCLK_MULT 2
#define MCLK_DIV (5 * MCLK_SCALE)
#elif F_PLL == 144000000
#define MCLK_MULT 1
#define MCLK_DIV (3 * MCLK_SCALE)
#elif F_PLL == 192000000
#define MCLK_MULT 1
#define MCLK_DIV (4 * MCLK_SCALE)
#elif F_PLL == 240000000
#define MCLK_MULT 1
#define MCLK_DIV (5 * MCLK_SCALE)
#else
#error "set F_CPU to (48, 96, 120, 144, 192, 240) MHz"
#endif

#define BIT_DIV 4

/*
 * estimation of sampling frequency
MCLK 98 MHz * 1 / 2 = 48 MHz
N_ADC =1
case 0
nch=8
Bit clock: 93750*(8*32) = 93750*256 = 24 MHz ->(I2S_RCR2_DIV(0))
case 1
nch=4
Bit clock: 93750*(4*32) = 93750*128 = 12 MHz ->(I2S_RCR2_DIV(1))
case 2
nch=2
Bit clock: 93750*(2*32) = 93750*64 = 6 MHz ->(I2S_RCR2_DIV(3))

N_ADC =2
case 3
nch=4
Bit clock: 93750*((4/2)*32) = 93750*64 = 6 MHz ->(I2S_RCR2_DIV(3))

bitclock = fs *( nch*32)/n_adc = f_pll*mckl_mult/mckl_div/(2*bit_div)

fs=bitclock*((nch/n_adc)*32)

bitclock= f_pll*mckl_mult/mckl_div/(2*bit_div)
fs=f_pll*mckl_mult/mckl_div/(2*bit_div)/((nch/n_adc)*32)
*/

const int32_t fsamp0 =
    (((F_PLL * MCLK_MULT) / MCLK_DIV) / (2 * BIT_DIV) / (NCH_I2S * 32 / N_ADC));

void acq_init(int32_t fsamp) {
  Serial.printf("%d %d\n", fsamp, fsamp0);
  SIM_SCGC6 |= SIM_SCGC6_I2S;
  SIM_SCGC7 |= SIM_SCGC7_DMA;
  SIM_SCGC6 |= SIM_SCGC6_DMAMUX;

/*
P23 PTC2   I2S0_TX_FS (6)
P9  PTC3   I2S0_TX_BCLK (6)
P13 PTC5                    I2S0_RXD0 (4)
P11 PTC6   I2S0_MCLK (6)    I2S0_RX_BCLK (4)
P12 PTC7                    I2S0_RX_FS (4)
P35 PTC8                    I2S0_MCLK (4)
P36 PTC9                    I2S0_RX_BCLK (4)
P37 PTC10                   I2S0_RX_FS (4)
P38 PTC11                   I2S0_RXD1 (4)
*/
#if I2S_CONFIG == 0
//            CORE_PIN39_CONFIG = PORT_PCR_MUX(6);  //pin39, PTA17, I2S0_MCLK
//            CORE_PIN11_CONFIG = PORT_PCR_MUX(4);  //pin11, PTC6,  I2S0_RX_BCLK
//            CORE_PIN12_CONFIG = PORT_PCR_MUX(4);  //pin12, PTC7,  I2S0_RX_FS
//            CORE_PIN13_CONFIG = PORT_PCR_MUX(4);  //pin13, PTC5,  I2S0_RXD0
#elif I2S_CONFIG == 1
  CORE_PIN35_CONFIG = PORT_PCR_MUX(4); // PTC8,  I2S0_MCLK
  CORE_PIN36_CONFIG = PORT_PCR_MUX(4); // PTC9,  I2S0_RX_BCLK
  CORE_PIN37_CONFIG = PORT_PCR_MUX(4); // PTC10, I2S0_RX_FS
#elif I2S_CONFIG == 2
//            CORE_PIN35_CONFIG = PORT_PCR_MUX(4) | PORT_PCR_SRE | PORT_PCR_DSE;
//            //pin35, PTC8,   I2S0_MCLK (SLEW rate (SRE)?)
//            CORE_PIN36_CONFIG = PORT_PCR_MUX(4);  //pin36, PTC9, I2S0_RX_BCLK
//            CORE_PIN37_CONFIG = PORT_PCR_MUX(4);  //pin37, PTC10,  I2S0_RX_FS
//            CORE_PIN27_CONFIG = PORT_PCR_MUX(6);  //pin27, PTA15,  I2S0_RXD0
#endif

  I2S0_RCSR = 0;

  // enable MCLK output // MCLK = INP *((MULT)/(DIV))
  I2S0_MDR = I2S_MDR_FRACT((MCLK_MULT - 1)) | I2S_MDR_DIVIDE((MCLK_DIV - 1));
  while (I2S0_MCR & I2S_MCR_DUF)
    ;
  I2S0_MCR = I2S_MCR_MICS(MCLK_SRC) | I2S_MCR_MOE;

  I2S0_RMR = 0; // enable receiver mask
  I2S0_RCR1 = I2S_RCR1_RFW(3);

  I2S0_RCR2 =
      I2S_RCR2_SYNC(0) | I2S_RCR2_BCP | I2S_RCR2_BCD // Bit clock in master mode
      |
      I2S_RCR2_DIV((BIT_DIV - 1)); // divides MCLK down to Bitclock (BIT_DIV)*2

  I2S0_RCR4 = I2S_RCR4_FRSZ((FRAME_I2S - 1)) | I2S_RCR4_FSE // frame sync early
              | I2S_RCR4_FSD // Frame sync in master mode
              | I2S_RCR4_MF;

  I2S0_RCR5 = I2S_RCR5_WNW(31) | I2S_RCR5_W0W(31) | I2S_RCR5_FBT(31);

  dma.begin(true); // Allocate the DMA channel first

#if N_ADC == 1
  CORE_PIN13_CONFIG = PORT_PCR_MUX(4); // PTC5,  I2S0_RXD0

  I2S0_RCR3 = I2S_RCR3_RCE;

  dma.TCD->SADDR = &I2S0_RDR0;
  dma.TCD->SOFF = 0;
  dma.TCD->ATTR = DMA_TCD_ATTR_SSIZE(2) | DMA_TCD_ATTR_DSIZE(2);
  dma.TCD->NBYTES_MLNO = 4;
  dma.TCD->SLAST = 0;
#elif N_ADC == 2
  CORE_PIN13_CONFIG = PORT_PCR_MUX(4); // PTC5,  I2S0_RXD0
  CORE_PIN38_CONFIG = PORT_PCR_MUX(4); // PTC11, I2S0_RXD1

  I2S0_RCR3 = I2S_RCR3_RCE_2CH;

  dma.TCD->SADDR = &I2S0_RDR0;
  dma.TCD->SOFF = 4;
  dma.TCD->ATTR = DMA_TCD_ATTR_SSIZE(2) | DMA_TCD_ATTR_DSIZE(2);
  dma.TCD->NBYTES_MLOFFYES = DMA_TCD_NBYTES_SMLOE |
                             DMA_TCD_NBYTES_MLOFFYES_MLOFF(-8) |
                             DMA_TCD_NBYTES_MLOFFYES_NBYTES(8);
  dma.TCD->SLAST = -8;
#endif
  dma.TCD->DADDR = tdm_rx_buffer;
  dma.TCD->DOFF = 4;
  dma.TCD->CITER_ELINKNO = NBUF_I2S;
  dma.TCD->DLASTSGA = -sizeof(tdm_rx_buffer);
  dma.TCD->BITER_ELINKNO = NBUF_I2S;
  dma.TCD->CSR = DMA_TCD_CSR_INTHALF | DMA_TCD_CSR_INTMAJOR;
  dma.triggerAtHardwareEvent(DMAMUX_SOURCE_I2S0_RX);
  dma.enable();

  I2S0_RCSR = I2S_RCSR_RE | I2S_RCSR_BCE | I2S_RCSR_FRDE | I2S_RCSR_FR;
  dma.attachInterrupt(acq_isr, I2S_DMA_PRIO * 16);
}

void acq_start(void) {}
void acq_stop(void) {}

#elif defined(__IMXRT1062__)
// Teensy 4.x

#define IMXRT_CACHE_ENABLED 2 // 0=disabled, 1=WT, 2= WB

/************************* I2S
 * *************************************************/
void set_audioClock(int nfact, int32_t nmult, uint32_t ndiv,
                    bool force) // sets PLL4
{
  if (!force && (CCM_ANALOG_PLL_AUDIO & CCM_ANALOG_PLL_AUDIO_ENABLE))
    return;

  CCM_ANALOG_PLL_AUDIO =
      CCM_ANALOG_PLL_AUDIO_BYPASS | CCM_ANALOG_PLL_AUDIO_ENABLE |
      CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT(2) // 2: 1/4; 1: 1/2; 0: 1/1
      | CCM_ANALOG_PLL_AUDIO_DIV_SELECT(nfact);

  CCM_ANALOG_PLL_AUDIO_NUM = nmult & CCM_ANALOG_PLL_AUDIO_NUM_MASK;
  CCM_ANALOG_PLL_AUDIO_DENOM = ndiv & CCM_ANALOG_PLL_AUDIO_DENOM_MASK;

  CCM_ANALOG_PLL_AUDIO &= ~CCM_ANALOG_PLL_AUDIO_POWERDOWN; // Switch on PLL
  while (!(CCM_ANALOG_PLL_AUDIO & CCM_ANALOG_PLL_AUDIO_LOCK)) {
  }; // Wait for pll-lock

  const int div_post_pll = 1; // other values: 2,4
  CCM_ANALOG_MISC2 &= ~(CCM_ANALOG_MISC2_DIV_MSB | CCM_ANALOG_MISC2_DIV_LSB);
  if (div_post_pll > 1)
    CCM_ANALOG_MISC2 |= CCM_ANALOG_MISC2_DIV_LSB;
  if (div_post_pll > 3)
    CCM_ANALOG_MISC2 |= CCM_ANALOG_MISC2_DIV_MSB;

  CCM_ANALOG_PLL_AUDIO &= ~CCM_ANALOG_PLL_AUDIO_BYPASS; // Disable Bypass
}

void acq_init(int32_t fsamp) {
  CCM_CCGR5 |= CCM_CCGR5_SAI1(CCM_CCGR_ON);

  // if either transmitter or receiver is enabled, do nothing
  if (I2S1_RCSR & I2S_RCSR_RE)
    return;
  // PLL:
  int fs = fsamp;
  int ovr = FRAME_I2S * 32;
  // PLL between 27*24 = 648MHz und 54*24=1296MHz
  int n1 = 4; // 4; //SAI prescaler 4 => (n1*n2) = multiple of 4
  int n2 = 1 + (24000000 * 27) / (fs * ovr * n1);
  Serial.printf("fs=%d, n1=%d, n2=%d, %d (>27 && < 54)\r\n", fs, n1, n2,
                n1 * n2 * (fs / 1000) * ovr / 24000);

  double C = ((double)fs * ovr * n1 * n2) / 24000000;
  int c0 = C;
  int c2 = 10000;
  int c1 = C * c2 - (c0 * c2);
  set_audioClock(c0, c1, c2, true);

  // clear SAI1_CLK register locations
  CCM_CSCMR1 =
      (CCM_CSCMR1 & ~(CCM_CSCMR1_SAI1_CLK_SEL_MASK)) |
      CCM_CSCMR1_SAI1_CLK_SEL(2); // &0x03 // (0,1,2): PLL3PFD0, PLL5, PLL4

  n1 = n1 / 2; // Double Speed for TDM

  CCM_CS1CDR =
      (CCM_CS1CDR &
       ~(CCM_CS1CDR_SAI1_CLK_PRED_MASK | CCM_CS1CDR_SAI1_CLK_PODF_MASK)) |
      CCM_CS1CDR_SAI1_CLK_PRED((n1 - 1))    // &0x07
      | CCM_CS1CDR_SAI1_CLK_PODF((n2 - 1)); // &0x3f

  IOMUXC_GPR_GPR1 = (IOMUXC_GPR_GPR1 & ~(IOMUXC_GPR_GPR1_SAI1_MCLK1_SEL_MASK)) |
                    (IOMUXC_GPR_GPR1_SAI1_MCLK_DIR |
                     IOMUXC_GPR_GPR1_SAI1_MCLK1_SEL(0)); // Select MCLK

  I2S1_RMR = 0;
  I2S1_RCR1 = I2S_RCR1_RFW(4);
  I2S1_RCR2 = I2S_RCR2_SYNC(0) | I2S_TCR2_BCP | I2S_RCR2_MSEL(1) |
              I2S_RCR2_BCD | I2S_RCR2_DIV(0);

  I2S1_RCR4 = I2S_RCR4_FRSZ((FRAME_I2S - 1)) | I2S_RCR4_SYWD(0) | I2S_RCR4_MF |
              I2S_RCR4_FSE | I2S_RCR4_FSD;
  I2S1_RCR5 = I2S_RCR5_WNW(31) | I2S_RCR5_W0W(31) | I2S_RCR5_FBT(31);

  CORE_PIN23_CONFIG = 3; // 1:MCLK
  CORE_PIN21_CONFIG = 3; // 1:RX_BCLK
  CORE_PIN20_CONFIG = 3; // 1:RX_SYNC
#if N_ADC == 1
  I2S1_RCR3 = I2S_RCR3_RCE;
  CORE_PIN8_CONFIG = 3; // RX_DATA0
  IOMUXC_SAI1_RX_DATA0_SELECT_INPUT = 2;

  dma.TCD->SADDR = &I2S1_RDR0;
  dma.TCD->SOFF = 0;
  dma.TCD->ATTR = DMA_TCD_ATTR_SSIZE(2) | DMA_TCD_ATTR_DSIZE(2);
  dma.TCD->NBYTES_MLNO = 4;
  dma.TCD->SLAST = 0;
#elif N_ADC == 2
  I2S1_RCR3 = I2S_RCR3_RCE_2CH;
  CORE_PIN8_CONFIG = 3;                  // RX_DATA0
  CORE_PIN6_CONFIG = 3;                  // RX_DATA1
  IOMUXC_SAI1_RX_DATA0_SELECT_INPUT = 2; // GPIO_B1_00_ALT3, pg 873
  IOMUXC_SAI1_RX_DATA1_SELECT_INPUT = 1; // GPIO_B0_10_ALT3, pg 873

  dma.TCD->SADDR = &I2S1_RDR0;
  dma.TCD->SOFF = 4;
  dma.TCD->ATTR = DMA_TCD_ATTR_SSIZE(2) | DMA_TCD_ATTR_DSIZE(2);
  dma.TCD->NBYTES_MLOFFYES = DMA_TCD_NBYTES_SMLOE |
                             DMA_TCD_NBYTES_MLOFFYES_MLOFF(-8) |
                             DMA_TCD_NBYTES_MLOFFYES_NBYTES(8);
  dma.TCD->SLAST = -8;
#endif
  dma.TCD->DADDR = tdm_rx_buffer;
  dma.TCD->DOFF = 4;
  dma.TCD->CITER_ELINKNO = NBUF_I2S;
  dma.TCD->DLASTSGA = -sizeof(tdm_rx_buffer);
  dma.TCD->BITER_ELINKNO = NBUF_I2S;
  dma.TCD->CSR = DMA_TCD_CSR_INTHALF | DMA_TCD_CSR_INTMAJOR;
  dma.triggerAtHardwareEvent(DMAMUX_SOURCE_SAI1_RX);
  dma.enable();

  I2S1_RCSR = I2S_RCSR_RE | I2S_RCSR_BCE | I2S_RCSR_FRDE | I2S_RCSR_FR;
  dma.attachInterrupt(acq_isr, I2S_DMA_PRIO * 16);
}

void acq_start(void) {}
void acq_stop(void) {}
#endif

uint32_t acq_count = 0;
uint32_t acq_miss = 0;

void acq_isr(void) {
  uint32_t daddr;
  uint32_t *src;
  acq_count++;

  daddr = (uint32_t)(dma.TCD->DADDR);
  dma.clearInterrupt();

  if (daddr < (uint32_t)tdm_rx_buffer + sizeof(tdm_rx_buffer) / 2) {
    // DMA is receiving to the first half of the buffer
    // need to remove data from the second half
    src = &tdm_rx_buffer[NBUF_I2S];
  } else {
    // DMA is receiving to the second half of the buffer
    // need to remove data from the first half
    src = &tdm_rx_buffer[0];
  }

#if IMXRT_CACHE_ENABLED >= 1
  arm_dcache_delete((void *)src, sizeof(tdm_rx_buffer) / 2);
#endif

  for (int jj = 0; jj < NCH_ACQ; jj++) {
    for (int ii = 0; ii < NBUF_ACQ; ii++) {
      acq_rx_buffer[jj + ii * NCH_ACQ] = src[jj + ii * NCH_I2S];
    }
  }

  if (!pushData(acq_rx_buffer))
    acq_miss++;
}

int16_t acq_check(int16_t state) {
  if (!state) { // start acquisition
    acq_start();
  }
  if (state > 3) { // stop acquisition
    acq_stop();
  }
  return state;
}
#endif

Note - I am running TD0.59.3.
 
@Sandro - Sorry, looks like that example fell through the cracks. I never used it. And there were several other examples for logging, such as SD_MTP-logger which do compile.

I will try to push up a version that compiles.


Thanks @mjs513 - it has been a while since we did anything with it. Like about a year and a half ago! Unfortunately, I have forgotten a lot of the details!

Many of these changes were requested and/or done by Paul. Like to remove showing the storage object, wanting a standard object MTP instead of one you had to specify, etc.

Some of the changes, were as a result of other changes like trying to detect when SD cards were inserted or removed, Likewise for MSC objects.

At that time, there were several other things that Paul, was wanting to enhance, rework and or rewrite, so we put everything on hold
and moved on to other projects. It has been so long, that I forgot most of the details, but I believe a lot of it centered around things like:

Define a new standard way to do callbacks.
Define a way to detect changes in the filesystem

Rewrite the file transfers and changes to Filesystem, as to do everything with callbacks.
I believe many of these changes were as to potentially sacrifice transfer speeds as to not interfere with playing audio.

There are probably several other details, which I have since forgotten. Hopefully all of these changes will be fleshed out at some point
and we integrate all of this into the TD builds and remove the (experimental) from the USB types!

EDIT:Pushed up changes to allow mtp-logger.ino to build. These were the changes that @mjs513 posted plus a change to allow it to compile on a Teensy Micromod.
 
Last edited:
Hi all, I apologize for this long delay; today I finally found time and room for testing your suggestions.

@mjs513 and @KurtE: I tried the new mtp-logger.ino; I can build and upload the example on my T4.1. but it doesn't do what I expected, since the T4.1 (with an SD on it) doesn't appear as an USB storage to my computer; I surely misunderstand the use of this example.

@WMXZ: I added your MTP_t4 library, and mtp_basic.ino does exactly what I was looking for. Nex step I'll try to integrate this functionality with my code.

Thank you to all of you for your kind help!
 
The MTP does not appear as disk (with drive number (C:, D:, etc) on your computer, but as portable device. There exist SW that allows mapping of portable device to drive numbers.

Before using mtp_logger, I would suggest to use mtp_basic, which simply lets you interact with mtp.
 
The MTP does not appear as disk (with drive number (C:, D:, etc) on your computer, but as portable device. There exist SW that allows mapping of portable device to drive numbers.
In my application, it is not fundamental that T1.4 appears on Explorer with a letter: it's enough the "Teensy device" label.

Before using mtp_logger, I would suggest to use mtp_basic, which simply lets you interact with mtp.
MTP_basic.ino is perfect for me :)
 
@WMXZ I haven't found any description about mtp_logger.ino, so I don't know what to expect... Maybe it still runs correctly on my Teensy...
 
So, MTP_basic.ino works perfectly, as far as I've checked. I only noticed that the free/used space is not shown: is this expected, either I did some mistake somehow?
MTP.jpg
 
So, MTP_basic.ino works perfectly, as far as I've checked. I only noticed that the free/used space is not shown: is this expected, either I did some mistake somehow?
View attachment 32179

No, the MTP_basic does not work correctly. Not sure where it fails, but 0-size is not good. Can you tell us more on the type od disk you are using? size, formatted, etc. Also it may be relevant to have a copy of the 'terminal printout', while the system is starting up.
 
@WMXZ I'm using a 16GB Sandisk Ultra micro-SD card, formatted FAT32; this it the printout at startup:
test.jpg
 
@Sandro,
OK, I found a discrepancy between MTP-T4 and lastest SD library and therefore Teensy-MTP, which is due to some 'improvments' by others that broke the backward compatibility. This is due to checking if the disk was previously inserted "cardPreviouslyPresent" which requires an additional call mediaPresent(). It is too late now, will modify tomorrow.
 
@Sandro,
I modified both 'mtp-basic' and 'mtp-logger' to compile and run with updated TD; Do use now SD.begin() and not SD.sdfs.begin() to ensure that presence of card was registered properly. I also added "while(!Serial);" in both programs to see ALL Serial.prints on terminal (monitor). Please comment if you do not use a terminal program.

programs are running here on Arduino 2.2.1; TD 1.58.1; SdFat 2.2.2 (TD 1.58.1 comes with SdFat 2.1.2, there may therefore be some differences, but it should work also)

Using the logger, you have 3 user actions: "s for start logging; q for stop logging; r for resetting MTP"
you need to reset MTP after logging, otherwise the new files are not visible.

github repository is updated, please re-download.

Let us know if it works for you. Obviously, you are free to switch to Teensy-MTP and use of the examples in there.
 
Wow super! later I'll try. Thinking I have to update other tools and libraries also (Teensyduino and SD.h, at least).
 
SD is part of Teensyduino!
@WMXZ: ok. I updated Teensyduino, deleted previous MTP_t4, and installed the new version. Now with mtp-basic the SD is displayed with its real capacity and occupation:

test.jpg

Thank you so much for perfect and super fast fix!!
 
Back
Top