Problem with Teensy 3.1, UNO, and SdFat

I’ve just started playing with the Teensy 3.1, and trying the various SD example sketches. I notice SdFat now includes Teensy support. Also, the Teensyduino-install overwrites and patches the IDE v.1.0.5 SD library [which of course is 2009-2010 version of the SD library].

In any case, SdFat worked with basic examples I’ve tried. However, there seems to be a problem when reading BMP files. This is the usual “parrot.bmp” that comes with the AdafruitST7735 library.

I’ve mounted the Adafruit 1.8" Color LCD Shield on both UNO and Teensy boards. The basics all work.

Note - all of this stuff works fine on the UNO board, but there are 2 problems with Teensy, one is that the BMPs don’t display properly [not the issue here], but the other is SdFat does not appear to read the BMP properly.

[BTW, I did reformat the SD card using SDFormatter4, because the Files.ino demo from the Teensyduino patch SD library ate the card].

Follows are my Serial debug outputs. The only difference between the 2 runs is SD.h was changed to SdFat.h:

USING TEENSYDUINO T3.1 SD Library

T3.1 Bitmap Test … (01/23/15)
Initializing SD card…OK!

Loading image ‘parrot.bmp’
File size: 61496
Image Offset: 54
Header size: 40
Bit Depth: 24
Image size: 128x160
Loaded in 390 ms

SAME DEMO USING SdFat Library:

T3.1 Bitmap Test … (01/23/15)
Initializing SD card…OK!

Loading image ‘parrot.bmp’
File size: 4030221634
Image Offset: 4030221634
Header size: 4030221634
BMP format not recognized.

The complete sketch is attached, start of it is here:

/*
file: t31_spitftbitmap
revised: 01/23/15 (orig 01/22/15)

status: 
1. using SD.h, works good on UNO, but BMP fails to 
   display on Teensy 3.1.
2. using SdFat.h, BMP load fails.
----------------------------------------------

SPI Read Bitmap Demo for Adafruit 1.8" Color LCD Shield.

NOTA BENE: Teensy uses USB as "Serial", and sends "Serial1" 
  to D0,D1.
  
BUGS, BUGS, BUGS BUNNY:
-----------------------
1. shield pinouts in original Adafruit file are wrong.
2. Joystick works differently from Adafruit listing.
----------------------------------------------

Notes:
------
1. modified from spibitmap.ino example sketch found in 
   the T3.1 Adafruit_ST7735 library.
2. modified for 57600, rather than 9600.
3. the Shield Joystick uses ADC chan A3 with 3.3V levels.
-----------------------------------------

ORIGINAL:
  Example sketch for the Adafruit 1.8" SPI display.
  Works with Adafruit 1.8" TFT Breakout w/SD card
    http://www.adafruit.com/products/358
  Works with Adafruit 1.8" Color TFT Shield w/SD+Joystick.
    http://www.adafruit.com/products/802
 
  Check out links for tutorials and wiring diagrams.
  Uses 4 SPI pins to communicate (RST is optional).
  Written by Limor Fried/Ladyada, Adafruit Industries.
  MIT license.
 ****************************************************/

#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library
#include <SPI.h>
//#include <SD.h>
#include <SdFat.h>
SdFat SD;

BTW, I just ran the old IDE “listfiles.ino” demo on the Teensy, and it shows the following, so the card looks ok. [note - the files are repeated in the subdirectory, so that’s ok]:

Initializing SD card…initialization done.
SYSTEM~1/
INDEXE~1 76
SPO-2.TXT 18075
SPO-1.TXT 37047
EXAMPLE.TXT 25
PARROT.BMP 61496
ZZ-SAVE/
SPO-2.TXT 18075
PARROT.BMP 61496
SPO-1.TXT 37047
done!

t31_spitftbitmap.ino (8.55 KB)

Reply to myself:

Sorry, I screwed up [... some days]. Actually, I rechecked, and this is not a Teensy only problem. I mounted the LCD shield back on the UNO, and loaded the exact same sketch as posted, and get the same results as with the Teensy 3.1.

Except in this case, the UNO does both read and display the parrot when SD.h is used, but still won't read parrot.bmp when SdFat.h is used.

USING IDE v1.0.5 SD.h with UNO:

T3.1 Bitmap Test ... (01/23/15)
Initializing SD card...OK!

Loading image 'parrot.bmp'
File size: 61496
Image Offset: 54
Header size: 40
Bit Depth: 24
Image size: 128x160
Loaded in 1046 ms

USING SdFat.h with UNO:

T3.1 Bitmap Test ... (01/23/15)
Initializing SD card...OK!

Loading image 'parrot.bmp'
File size: 4030221634
Image Offset: 4030221634
Header size: 4030221634
BMP format not recognized.

The problem is the File object in SD.h contains a pointer to an SdFat file.

The File class in SdFat is an SdFat file with no wrapper.

When you call these functions, a copy of the argument is made on the stack since you are using call by value.

uint16_t read16(File f) 
{
  uint16_t result;
  ((uint8_t *)&result)[0] = f.read(); // LSB
  ((uint8_t *)&result)[1] = f.read(); // MSB
  return result;
}

/********************************************************/
uint32_t read32(File f) 
{
  uint32_t result;
  ((uint8_t *)&result)[0] = f.read(); // LSB
  ((uint8_t *)&result)[1] = f.read();
  ((uint8_t *)&result)[2] = f.read();
  ((uint8_t *)&result)[3] = f.read(); // MSB
  return result;
}

You need to change these functions to be call by reference then they should work with either SD.h or SdFat.

uint16_t read16(File &f) 
{
  uint16_t result;
  ((uint8_t *)&result)[0] = f.read(); // LSB
  ((uint8_t *)&result)[1] = f.read(); // MSB
  return result;
}

/********************************************************/
uint32_t read32(File &f) 
{
  uint32_t result;
  ((uint8_t *)&result)[0] = f.read(); // LSB
  ((uint8_t *)&result)[1] = f.read();
  ((uint8_t *)&result)[2] = f.read();
  ((uint8_t *)&result)[3] = f.read(); // MSB
  return result;
}

The problem is that the copy of the argument gets updated with SdFat but in SD.h the pointer to the SdFat file is used from the copied argument and there is no copy problem.

You should use call by reference with SD.h functions since some operations also fail when a call by value File argument is used in SD.h.

Thanks a load, Bill, appears to have fixed it. Here are results, all with the Teensy 3.1.
Boy, I never would have found that one myself, :-).

I also checked, and it works ok on the UNO too with the call-by-reference patch. Now to figure out why Teensy won't display the parrot, while UNO does, but I don't think that has to do with the SD card.

USING SD.h:

T3.1 Bitmap Test ... (01/23/15)
Initializing SD card...OK!

Loading image 'parrot.bmp'
File size: 61496
Image Offset: 54
Header size: 40
Bit Depth: 24
Image size: 128x160
Loaded in 388 ms

USING SdFat.h (using call-by-value):

T3.1 Bitmap Test ... (01/23/15)
Initializing SD card...OK!

Loading image 'parrot.bmp'
File size: 4030221634
Image Offset: 4030221634
Header size: 4030221634
BMP format not recognized.

USING SdFat.h (patched with call-by-reference):

T3.1 Bitmap Test ... (01/23/15)
Initializing SD card...OK!

Loading image 'parrot.bmp'
File size: 61496
Image Offset: 54
Header size: 40
Bit Depth: 24
Image size: 128x160
Loaded in 368 ms