Hi,
I started a project with Arduino Mega2560. This project contains a library for audio output, SimpleSDAudio, see attachment. This library allows to output audio (speech in my application) by reading blocks of data from an SD card and generating the audio by PWM. Parallel to audio output the controller shall service lots of interrupts coming from a 433 MHz receiver. Both together prooved to be too much load for a Mega2560.
So I decided to change to Teensy 3.2 which is much faster (16 MHz --> 96 MHz), installed Teensyduino IDE, and modified the library to SimpleSDAudio_Teensy, see attachment. This library contains many changes concerning my application, but the part to configure the SD card is the same, see the function SD_L0_init() in sd_l0.cpp respectively sd_l0_Te.cpp.
In a first step I tested reading from the SD card and was disappointed because reading with Teensy 3.2 gets nearly the same speed as reading with Mega2560 inspite of 5 times faster clock. The transfer clock for SD card is defined by F_CPU/n (or f_OSC/n). n is defined by setting some bits in the SPCR register. This setting is the same for Mega2560 and for Teensy 3.2.
Something in the background, I guess deep in some basic libraries, is changing the setting in SPCR for Teensy with the consequence that the 96 MHz are divided down to the same clock as the 16 MHz with Mega2560.
For testing the speed of data transfer the code in SDcardTest.zip is used, see attachment.
The code in the function SD_L0_SpiSetHighSpeed(), see sd_l0_Te.cpp, is based on a posting from Paul Stoffregen:
----------------------------
...
Agreed, the proper way is to use the SPI library. But there's still quite a lot of very old AVR code out there....
I've added these missing AVR SPCR emulation features. Hopefully this makes everything work for you?
https://github.com/PaulStoffregen/cores/commit/8f137ff3fff2f230de02e466d45cc86a3f52f507
Here's the complete sketch I used for testing.
Code:
void setup() {
pinMode(20, OUTPUT); // for comparison to Teensy++ 2.0
pinMode(21, OUTPUT);
pinMode(22, OUTPUT);
digitalWrite(20, HIGH);
SPCR = (0 << SPIE) | /* SPI Interrupt Enable */
(1 << SPE) | /* SPI Enable */
(0 << DORD) | /* Data Order: MSB first */
(1 << MSTR) | /* Master mode */
(0 << CPOL) | /* Clock Polarity: SCK low when idle */
(0 << CPHA) | /* Clock Phase: sample on rising SCK edge */
(1 << SPR1) | /* Clock Frequency: f_OSC / 128 */
(1 << SPR0);
SPSR &= ~(1 << SPI2X); /* No doubled clock frequency */
SPCR &= ~((1 << SPR1) | (1 << SPR0)); /* Clock Frequency: f_OSC / 4 */;
SPSR |= (1 << SPI2X); /* Doubled Clock Frequency: f_OSC / 2 */
}
void loop() {
SPDR = 0x5A;
while (!(SPSR & _BV(SPIF))) ; // wait
SPDR;
delay(10);
}
----------------------------
The SD card shall contain a file with at least 512 consecutive blocks. In my code it is named ANSAGEK5.AHM. Any other name with 8.3 convention can be used. The file shall be located in the root directory.
The SD card is conneted to Teensy 3.2:
MISO 12
MOSI 11
SCK 13
CS 4
Now my question is, how can I increase the SD clock frequency?
I started a project with Arduino Mega2560. This project contains a library for audio output, SimpleSDAudio, see attachment. This library allows to output audio (speech in my application) by reading blocks of data from an SD card and generating the audio by PWM. Parallel to audio output the controller shall service lots of interrupts coming from a 433 MHz receiver. Both together prooved to be too much load for a Mega2560.
So I decided to change to Teensy 3.2 which is much faster (16 MHz --> 96 MHz), installed Teensyduino IDE, and modified the library to SimpleSDAudio_Teensy, see attachment. This library contains many changes concerning my application, but the part to configure the SD card is the same, see the function SD_L0_init() in sd_l0.cpp respectively sd_l0_Te.cpp.
In a first step I tested reading from the SD card and was disappointed because reading with Teensy 3.2 gets nearly the same speed as reading with Mega2560 inspite of 5 times faster clock. The transfer clock for SD card is defined by F_CPU/n (or f_OSC/n). n is defined by setting some bits in the SPCR register. This setting is the same for Mega2560 and for Teensy 3.2.
Something in the background, I guess deep in some basic libraries, is changing the setting in SPCR for Teensy with the consequence that the 96 MHz are divided down to the same clock as the 16 MHz with Mega2560.
For testing the speed of data transfer the code in SDcardTest.zip is used, see attachment.
The code in the function SD_L0_SpiSetHighSpeed(), see sd_l0_Te.cpp, is based on a posting from Paul Stoffregen:
----------------------------
...
Agreed, the proper way is to use the SPI library. But there's still quite a lot of very old AVR code out there....
I've added these missing AVR SPCR emulation features. Hopefully this makes everything work for you?
https://github.com/PaulStoffregen/cores/commit/8f137ff3fff2f230de02e466d45cc86a3f52f507
Here's the complete sketch I used for testing.
Code:
void setup() {
pinMode(20, OUTPUT); // for comparison to Teensy++ 2.0
pinMode(21, OUTPUT);
pinMode(22, OUTPUT);
digitalWrite(20, HIGH);
SPCR = (0 << SPIE) | /* SPI Interrupt Enable */
(1 << SPE) | /* SPI Enable */
(0 << DORD) | /* Data Order: MSB first */
(1 << MSTR) | /* Master mode */
(0 << CPOL) | /* Clock Polarity: SCK low when idle */
(0 << CPHA) | /* Clock Phase: sample on rising SCK edge */
(1 << SPR1) | /* Clock Frequency: f_OSC / 128 */
(1 << SPR0);
SPSR &= ~(1 << SPI2X); /* No doubled clock frequency */
SPCR &= ~((1 << SPR1) | (1 << SPR0)); /* Clock Frequency: f_OSC / 4 */;
SPSR |= (1 << SPI2X); /* Doubled Clock Frequency: f_OSC / 2 */
}
void loop() {
SPDR = 0x5A;
while (!(SPSR & _BV(SPIF))) ; // wait
SPDR;
delay(10);
}
----------------------------
The SD card shall contain a file with at least 512 consecutive blocks. In my code it is named ANSAGEK5.AHM. Any other name with 8.3 convention can be used. The file shall be located in the root directory.
The SD card is conneted to Teensy 3.2:
MISO 12
MOSI 11
SCK 13
CS 4
Now my question is, how can I increase the SD clock frequency?