// Simple WAV file player example with pitch shifting
// This example code is in the public domain.
// (c) Jan 2021 Frank B
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
AudioPlaySdWav playWav1;
AudioOutputI2Sslave audioOutput;
AudioConnection patchCord1(playWav1, 0, audioOutput, 0);
AudioConnection patchCord2(playWav1, 1, audioOutput, 1);
AudioControlSGTL5000 sgtl5000_1;
// Use these with the Teensy Audio Shield
#define SDCARD_CS_PIN 10
#define SDCARD_MOSI_PIN 7
#define SDCARD_SCK_PIN 14
// Use these with the Teensy 3.5 & 3.6 SD card
//#define SDCARD_CS_PIN BUILTIN_SDCARD
#if defined(KINETISL) //Teensy LC
const unsigned extMCLK = 16000000;
const unsigned maxSpeed = 51000;
#else
const unsigned extMCLK = 11294118;
const unsigned maxSpeed = 71000;
#endif
void initSGTLasMaster(void);
void SGTLsetSampleFreq(const float freq);
void setup() {
AudioMemory(4);
initSGTLasMaster();
Serial.begin(9600);
sgtl5000_1.volume(0.5);
#if defined(SDCARD_SCK_PIN)
SPI.setMOSI(SDCARD_MOSI_PIN);
SPI.setSCK(SDCARD_SCK_PIN);
#endif
if (!(SD.begin(SDCARD_CS_PIN))) {
// stop here, but print a message repetitively
while (1) {
Serial.println("Unable to access the SD card");
delay(500);
}
}
}
void playFile(const char *filename)
{
Serial.print("Playing file: ");
Serial.println(filename);
playWav1.play(filename);
delay(25);
while (playWav1.isPlaying()) {
float speed = analogRead(15);
float freq = maxSpeed * speed / 1024.0f;
if (freq < extMCLK / 1024) freq = extMCLK / 1024;
SGTLsetSampleFreq(freq);
Serial.println(freq);
delay(200);
}
}
void loop() {
playFile("SDTEST2.WAV"); // filenames are always uppercase 8.3 format
delay(500);
playFile("SDTEST3.WAV");
delay(500);
playFile("SDTEST4.WAV");
delay(500);
playFile("SDTEST1.WAV");
delay(1500);
}
//SGTL-5000 registers
#define CHIP_PLL_CTRL 0x0032
bool writeSgtl(unsigned int reg, unsigned int val)
{
Wire.beginTransmission(0x0A);
Wire.write(reg >> 8);
Wire.write(reg);
Wire.write(val >> 8);
Wire.write(val);
if (Wire.endTransmission() == 0) return true;
return false;
}
void SGTLsetSampleFreq(const float freq) {
float pllFreq = 4096.0f * freq;
uint32_t int_divisor = ((uint32_t)(pllFreq / extMCLK)) & 0x1f;
uint32_t frac_divisor = (uint32_t)(((pllFreq / extMCLK) - int_divisor) * 2048.0) & 0x7ff;
writeSgtl(CHIP_PLL_CTRL, (int_divisor << 11) | frac_divisor);
}
void initSGTLasMaster()
{
#if defined(KINETISL) //Teensy LC
sgtl5000_1.enable(); //Uses SGTL I2S Master Mode automatically
#else //enable MCLK-Output
#if F_CPU == 96000000 || F_CPU == 48000000 || F_CPU == 24000000
// PLL is at 96 MHz in these modes
#define MCLK_MULT 2
#define MCLK_DIV 17
#elif F_CPU == 72000000
#define MCLK_MULT 8
#define MCLK_DIV 51
#elif F_CPU == 120000000
#define MCLK_MULT 8
#define MCLK_DIV 85
#elif F_CPU == 144000000
#define MCLK_MULT 4
#define MCLK_DIV 51
#elif F_CPU == 168000000
#define MCLK_MULT 8
#define MCLK_DIV 119
#elif F_CPU == 180000000
#define MCLK_MULT 16
#define MCLK_DIV 255
#define MCLK_SRC 0
#elif F_CPU == 192000000
#define MCLK_MULT 1
#define MCLK_DIV 17
#elif F_CPU == 216000000
#define MCLK_MULT 12
#define MCLK_DIV 17
#define MCLK_SRC 1
#elif F_CPU == 240000000
#define MCLK_MULT 2
#define MCLK_DIV 85
#define MCLK_SRC 0
#elif F_CPU == 256000000
#define MCLK_MULT 12
#define MCLK_DIV 17
#define MCLK_SRC 1
#elif F_CPU == 16000000
#define MCLK_MULT 12
#define MCLK_DIV 17
#else
#error "This CPU Clock Speed is not supported by the Audio library";
#endif
#ifndef MCLK_SRC
#if F_CPU >= 20000000
#define MCLK_SRC 3 // the PLL
#else
#define MCLK_SRC 0 // system clock
#endif
#endif
I2S0_MCR = I2S_MCR_MICS(MCLK_SRC) | I2S_MCR_MOE;
while (I2S0_MCR & I2S_MCR_DUF);
I2S0_MDR = I2S_MDR_FRACT((MCLK_MULT - 1)) | I2S_MDR_DIVIDE((MCLK_DIV - 1));
CORE_PIN11_CONFIG = PORT_PCR_MUX(6); // pin 11, PTC6, I2S0_MCLK
sgtl5000_1.enable(extMCLK, AUDIO_SAMPLE_RATE_EXACT * 4096.0L); //Use SGTL I2S Master Mode
#endif
}