//============================================================================
// PMF Player SdFat v2 BETA + DMAMEM Buffer + Audio USB example.
//
// Copyright (c) 2019, Profoundic Technologies, Inc.
// All rights reserved.
//----------------------------------------------------------------------------
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of Profoundic Technologies nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL PROFOUNDIC TECHNOLOGIES BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//============================================================================
// Chris O.
// How to use this example:
// Set Audio USB in Arduino IDE Tools menu - USB Type: "Audio"
// Open serial monitor and change to Newline or Carriage return at the bottom, press send.
// https://forum.pjrc.com/threads/58284-Arduino-Music-Player-on-Teensy-Audio-Shield
// You can download the project at: https://github.com/JarkkoPFC/arduino-music-player
// world's largest collections of music modules. The Mod Archive is currently enjoying its 23rd year online and is still as active as ever.
// https://modarchive.org/
// In order to use other music files than the one that comes with the project you'll need to use PMF Converter tool.
// How to use PMF Converter tool:
// Go to Windows icon on left bottom first, type C now look for - Command prompt and letf click mouse botton - click yas to waring window - select run as Administrator. ( now you shuld see Administrator Command Prompt).
// then type Exeple: "C:\Users\ --??-- \Desktop\pmf_converter\bin\pmf_converter" -hex -dro -o C:\OPEN_MPT\\OPENMPT2\aws_aqua.pmf -i C:\OPEN_MPT\OPENMPT2\aws_aqua.xm
#pragma message ( "ISSUE: Audio library pulls in SD.h library but we need SdFat-beta ver 2.0.0.8 !!!! Needs editing in play_sd_raw.h, play_sd_raw.ccp, play_sd_wav.h & play_sd_wav.ccp." )
// ---- NOTE ISSUE: Audio library pulls in SD.h library but we need SdFat-beta ver "2.0.0"8
// Needs editing in play_sd_raw.h, play_sd_raw.ccp, play_sd_wav.h & play_sd_wav.ccp.
// IN *.h ( #include "SD.h" ) TO - > ( #include "SdFat.h" )
// IN *.ccp ( wavfile = SD.open(filename); // SD.h } TO - > { wavfile.open(filename); // SdFat.h )
// https://forum.pjrc.com/threads/60746-Teensyduino-1-52-Beta-4
// ISSUE: trap stack overflow, trap NULL pointer deref
// C:\Users\-------\Desktop\arduino-1.8.12 BETA4\hardware\teensy\avr\cores\teensy4\startup.c
// quick fix - about line 211:
/*
FLASHMEM void configure_cache(void)
{
//printf("MPU_TYPE = %08lX\n", SCB_MPU_TYPE);
//printf("CCR = %08lX\n", SCB_CCR);
// TODO: check if caches already active - skip?
SCB_MPU_CTRL = 0; // turn off MPU
uint32_t i = 0;
SCB_MPU_RBAR = 0x00000000 | REGION(i++); //https://developer.arm.com/docs/146793866/10/why-does-the-cortex-m7-initiate-axim-read-accesses-to-memory-addresses-that-do-not-fall-under-a-defined-mpu-region
SCB_MPU_RASR = SCB_MPU_RASR_TEX(0) | NOACCESS | NOEXEC | SIZE_4G;
SCB_MPU_RBAR = 0x00000000 | REGION(i++); // ITCM
SCB_MPU_RASR = MEM_NOCACHE | READWRITE | SIZE_512K;
// TODO: trap regions should be created last, because the hardware gives
// priority to the higher number ones.
// --SCB_MPU_RBAR = 0x00000000 | REGION(i++); // trap NULL pointer deref // <------------------
// --SCB_MPU_RASR = DEV_NOCACHE | NOACCESS | SIZE_32B; // <------------------
SCB_MPU_RBAR = 0x00200000 | REGION(i++); // Boot ROM
SCB_MPU_RASR = MEM_CACHE_WT | READONLY | SIZE_128K;
SCB_MPU_RBAR = 0x20000000 | REGION(i++); // DTCM
SCB_MPU_RASR = MEM_NOCACHE | READWRITE | NOEXEC | SIZE_512K;
// -- SCB_MPU_RBAR = ((uint32_t)&_ebss) | REGION(i++); // trap stack overflow // <------------------
// -- SCB_MPU_RASR = SCB_MPU_RASR_TEX(0) | NOACCESS | NOEXEC | SIZE_32B; // <------------------
SCB_MPU_RBAR = 0x20200000 | REGION(i++); // RAM (AXI bus)
SCB_MPU_RASR = MEM_CACHE_WBWA | READWRITE | NOEXEC | SIZE_1M;
SCB_MPU_RBAR = 0x40000000 | REGION(i++); // Peripherals
SCB_MPU_RASR = DEV_NOCACHE | READWRITE | NOEXEC | SIZE_64M;
SCB_MPU_RBAR = 0x60000000 | REGION(i++); // QSPI Flash
SCB_MPU_RASR = MEM_CACHE_WBWA | READONLY | SIZE_16M;
SCB_MPU_RBAR = 0x70000000 | REGION(i++); // FlexSPI2
SCB_MPU_RASR = MEM_CACHE_WBWA | READONLY | SIZE_256M;
SCB_MPU_RBAR = 0x70000000 | REGION(i++); // FlexSPI2
SCB_MPU_RASR = MEM_CACHE_WBWA | READWRITE | SIZE_16M;
// TODO: protect access to power supply config
SCB_MPU_CTRL = SCB_MPU_CTRL_ENABLE;
// cache enable, ARM DDI0403E, pg 628
asm("dsb");
asm("isb");
SCB_CACHE_ICIALLU = 0;
asm("dsb");
asm("isb");
SCB_CCR |= (SCB_CCR_IC | SCB_CCR_DC);
}
*/
#include "pmf_player.h"
#include <Audio.h>
//============================================================================
// SdFat version 2.0.0 BETA ONLY
//============================================================================
// NEED THIS BEFORE MTP LIB.
#include <SdFat.h> // SdFat V "2.0.0"
const char *SDFAT_ver = SD_FAT_VERSION;
// Use built-in SD for SPI modes on Teensy 3.5/3.6.
// Teensy 4.0 use first SPI port.
// SDCARD_SS_PIN is defined for the built-in SD on some boards.
#ifndef SDCARD_SS_PIN
const uint8_t SD_CS_PIN = SS;
#else // SDCARD_SS_PIN
// Assume built-in SD is used.
const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
#endif // SDCARD_SS_PIN
// SD_FAT_TYPE = 0 for SdFat/File as defined in SdFatConfig.h,
// 1 for FAT16/FAT32, 2 for exFAT, 3 for FAT16/FAT32 and exFAT.
#define SD_FAT_TYPE 3
SdFat sd; // SD
// The file to be parsed.
File m_pSource;
uint32_t FILESIZE;
const int DIR_max = 60; // [# of Directory - max]
const int max_DIR_name_lenght = 100;
char CURDIRname[max_DIR_name_lenght] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; //
uint32_t DIRcount = 1; // COUNT of all DIRs on SD CARD
char DIR_list_array[DIR_max][max_DIR_name_lenght]; // [# of DIRs max][max DIR name lenght];
bool op_sd = 0;
char PMFfilename[max_DIR_name_lenght]; // SDFAT
uint32_t CUR_PMF_FILE_counter = 1 ;
uint32_t PMF_FILE_counter = 0 ;
int receivedChar; // an array to store the received data
boolean newData = false;
//----------------------------------------------------------------------------
//============================================================================
// Audio lib. Volume level
//============================================================================
float Volume = 1.00; // 100%
//============================================================================
// music data
//============================================================================
// static const uint8_t PROGMEM s_pmf_file[] =
static const uint8_t FLASHMEM s_pmf_file[] =
{
#include "music.h"
};
//----------------------------------------------------------------------------
//============================================================================
// SD FILE music data storage
//============================================================================
//uint8_t SD_MusicData[450000] DMAMEM; // Upper MEMORY
uint8_t SD_MusicData[500000] DMAMEM; // Upper MEMORY
uint32_t array_counter = 0;
uint32_t TOTAL_PMF_FILE_counter = 0;
//----------------------------------------------------------------------------
//============================================================================
// globals
//============================================================================
static pmf_player s_player;
static unsigned s_effect_channel = 0;
char SDPmfIDCheck[14] = {};
char PmfID[14] = {'/', '/', ' ', 'S', 'o', 'n', 'g', ' ', 'n', 'a', 'm', 'e', ':', ' '}; // Profoundic Music File format - TEXT ID
//----------------------------------------------------------------------------
//============================================================================
// row_callback_test
//============================================================================
void row_callback_test(void *custom_data_, uint8_t channel_idx_, uint8_t ¬e_idx_, uint8_t &inst_idx_, uint8_t &volume_, uint8_t &effect_, uint8_t &effect_data_)
{
if (channel_idx_ == s_effect_channel)
{
static unsigned s_counter = 1;
if (--s_counter == 0)
{
note_idx_ = 0 + 5 * 12; // C-5 (note+octave*12, note: 0=C, 1=C#, 2=D, 3=D#, 4=E, 5=F, 6=F#, 7=G, 8=G#, 9=A, 10=A#, 11=B)
inst_idx_ = 2; // sample 2
volume_ = 63; // volume 63 (max)
s_counter = 8; // hit note every 8th row
}
}
}
//----------------------------------------------------------------------------
//============================================================================
// Teensy 4.0 Serial Number and MAC // 04:E9:E5:09:6A:F3
//============================================================================
static void teensyMAC(uint8_t *mac)
{
uint32_t m1 = HW_OCOTP_MAC1;
uint32_t m2 = HW_OCOTP_MAC0;
mac[0] = m1 >> 8;
mac[1] = m1 >> 0;
mac[2] = m2 >> 24;
mac[3] = m2 >> 16;
mac[4] = m2 >> 8;
mac[5] = m2 >> 0;
}
//----------------------------------------------------------------------------
//============================================================================
// setup
//============================================================================
void setup()
{
Serial.begin(38400);
while (!Serial && millis() < 1000) {} // wait for Serial Monitor with 1s. timeout.
Serial.print("Teensy Serial# and MAC: ");
uint8_t mac[6];
teensyMAC(mac);
for (uint8_t i = 0; i < 6; ++i) {
Serial.printf("%02X", mac[i]);
if (i < 5) {
Serial.print(":");
}
}
Serial.println("");
Serial.print(tempmonGetTemp(), 1); // TEENSY 4.0
Serial.println(" CPU TEMP");
// no mtp
// storage.init(); // MTP
if (!sd.begin(SdioConfig(FIFO_SDIO))) { // SdFat.h Ver 2.0.0 Beta
Serial.println("m.SD initialization failed!");
s_player.load(s_pmf_file); // play from h. file
Serial.println(F(" Playing from h. file"));
} else {
Serial.println("m.SD initialization OK");
LISTDIRs();
m_pSource = sd.open("/"); // ROOT
PrintFiles(m_pSource);
m_pSource.close();
}
s_player.load(s_pmf_file); // play from h. file
Serial.println(F(" Playing from music.h. file"));
s_player.start(44100); //22050
s_player.Volumelevel(Volume, Volume); // SET AT Volume
}
//----------------------------------------------------------------------------
//============================================================================
// loop
//============================================================================
void loop()
{
if (Serial.available() > 0) {
receivedChar = Serial.read();
newData = true;
Serial.print("This just in ... ");
Serial.print(receivedChar);
Serial.print(" ascii: ");
Serial.write(receivedChar);
Serial.println();
}
// PMF accessors
//uint8_t num_pattern_channels() const;
//uint8_t num_playback_channels() const;
//uint16_t playlist_length() const;
//float arr_p_x() const;
//-------------------------------------------------------------------------
// player control
//void start(uint32_t sampling_freq_ =/*44100*/22050, uint16_t playlist_pos_ = 0);
//void stop();
//void update();
//-------------------------------------------------------------------------
// playback state accessors
//float fftlevelbuffer(uint8_t fft_0_) const;
//void Volumelevel(float mixerVol1_, float mixerVol2_) const;
//bool is_playing() const;
//uint8_t playlist_pos() const;
//uint8_t pattern_row() const;
//uint8_t pattern_speed() const;
// auto skip, next song.
// some songs will never get to the end.
//__disable_irq();
if (( s_player.playlist_length() == s_player.playlist_pos() + 1 /*&& s_player.pattern_row() >= 20*/ ) || (newData == true) ) {
//__enable_irq();
newData = false;
s_player.stop(); // todo
// s_player.stop_playback(); // ?
Serial.println("stop# ");
if (op_sd == 0) {
m_pSource = sd.open("/"); //root
op_sd = 1;
PMF_FILE_counter = 0;
Serial.println ("ok 1st open ");
}
if (m_pSource.isOpen()) {
Serial.println(" m_pSource is open "); // SDFAT LIB
int len = strlen(PMFfilename);
char *extension = PMFfilename + len - 4;
while (true) {
File entry = m_pSource.openNextFile();
//FsFile entry = m_pSource.openNextFile();
if (! entry) {
// no more files
Serial.println("\t **no more files**"), Serial.println();
//op_sd = 0; // bool
PMF_FILE_counter = 0; // reset
entry.close();
m_pSource.close();
// TO DO OPEN WITH dirIndex 135
m_pSource = sd.open("/"); //root
}
entry.getName(PMFfilename, sizeof(PMFfilename));
if (entry.isDirectory()) {
// skip
} else {
Serial.print(PMFfilename); // SDFAT LIB
// files have sizes, directories do not
Serial.print(" \t");
Serial.println(entry.size(), DEC);
len = strlen(PMFfilename);
extension = PMFfilename + len - 4;
Serial.println(*extension);
if (!strcmp(".pmf", extension) || !strcmp(".PMF", extension)) { // PMF File Format
// See if there's any touch data for us
/*
if (ts.tirqTouched()) {
TouchData();
}
*/
uint32_t index = entry.dirIndex() ;
Serial.print("\t index ~ "), Serial.println(index);
//entry.close();
PMF_FILE_counter ++;
Serial.print("\t PMF_FILE_counter ++; ~ "), Serial.println(PMF_FILE_counter);
Serial.print("\t CUR_PMF_FILE_counter ++ ~ "), Serial.println(CUR_PMF_FILE_counter);
//BTserial.print("PMF FILE# -> "), BTserial.print(CUR_PMF_FILE_counter);
//BTserial.print(" of "), BTserial.println(TOTAL_PMF_FILE_counter);
if (CUR_PMF_FILE_counter == PMF_FILE_counter) {
PMF_FILE_counter = 0;
CUR_PMF_FILE_counter++;
if (CUR_PMF_FILE_counter >= TOTAL_PMF_FILE_counter) { //
CUR_PMF_FILE_counter = 1;
}
if (CUR_PMF_FILE_counter == 4294967295) { // 0xFFFFFFFF
CUR_PMF_FILE_counter = 1;
}
Serial.print(PMFfilename); // SDFAT LIB
Serial.print("\t PMF player Audio File Format Supported ~ "), Serial.println(PMFfilename);
m_pSource.close();
m_pSource = sd.open(PMFfilename, FILE_READ); //
// uint8_t SD_MusicData[500000] DMAMEM; // Upper MEMORY
ParsePmfHeader( entry.curPosition() );
entry.close();
s_player.load(SD_MusicData); // play from SD buffered file
// player control
//void start(uint32_t sampling_freq_ =/*44100*/22050, uint16_t playlist_pos_ = 0);
//void stop();
//void update();
s_player.start(44100); //(44100,0)
s_player.Volumelevel(Volume, Volume); // SET AT Volume
//Serial.println("\t debug 1 ");
break;
}
}
}
entry.close();
}
//BTserial.print("PMF FILE# -> "), BTserial.print(CUR_PMF_FILE_counter - 1);
//BTserial.print(" of "), BTserial.println(TOTAL_PMF_FILE_counter);
}
} else {
s_player.update(); // keep updating the audio buffer...
}
} // loop end
//----------------------------------------------------------------------------
// # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
//============================================================================
//------------ LIST ALL DIRs ON SD CARD & SAVE IN DIR_list_array -------------
//============================================================================
void LISTDIRs() {
Serial.println("\t**List Directories**");
m_pSource = sd.open("/"); // ROOT
char dirname[max_DIR_name_lenght]; // SDFAT // max_DIR_name_lenght
if (m_pSource.isDirectory()) {
strcpy(DIR_list_array[DIRcount], "/"); // array
Serial.print("ROOT# ");
Serial.print(DIRcount);
Serial.print("\t");
Serial.println(DIR_list_array[DIRcount]); // SDFAT LIB
DIRcount++;
}
while (true) {
File DIR = m_pSource.openNextFile();
if (! DIR) {
// no more files
Serial.println("\t **no more Directories** ");
//dir.close();
break;
}
DIR.getName(dirname, sizeof(dirname));
if (DIR.isDirectory()) {
//DIRcount++;
strcpy(DIR_list_array[DIRcount], dirname); // array
strcat(DIR_list_array[DIRcount], "/");
Serial.print("DIR# ");
Serial.print(DIRcount);
Serial.print("\t");
Serial.println(DIR_list_array[DIRcount]); // SDFAT LIB
DIRcount++;
}
DIR.close();
}
DIRcount --;
Serial.print("\t **Directory count ");
Serial.print(DIRcount), Serial.println(" **"), Serial.println();
m_pSource.close();
}
//============================================================================
// Print Files in Cur. Directory
//============================================================================
void PrintFiles(File dir) {
Serial.println("\t**List Files in Cur. Directory**");
char filename[max_DIR_name_lenght]; // SDFAT
int len = strlen(filename);
char *extension = filename + len - 4;
while (true) {
File entry = dir.openNextFile();
if (! entry) {
// no more files
Serial.println("\t **no more files**");
entry.close();
Serial.print("\t TOTAL PMF_FILE_counter: "), Serial.println(TOTAL_PMF_FILE_counter), Serial.println();
//BTserial.print("TOTAL PMF FILE counter "), BTserial.println(TOTAL_PMF_FILE_counter);
break;
}
entry.getName(filename, sizeof(filename));
if (entry.isDirectory()) {
// skip
} else {
Serial.print(filename); // SDFAT LIB
// files have sizes, directories do not
Serial.print(" \t");
Serial.print(entry.size(), DEC);
Serial.print("\t dirIndex "), Serial.println(entry.dirIndex());
// PMF File Format counter
len = strlen(filename);
extension = filename + len - 4;
if (!strcmp(".pmf", extension) || !strcmp(".PMF", extension)) {
TOTAL_PMF_FILE_counter++;
}
}
entry.close();
}
}
//----------------------------------------------------------------------------
//============================================================================
// Parse File Header.
//============================================================================
// Read a single character.
byte Get(int _CurfilePos )
{
byte in = (m_pSource.read());
// Serial.print("ASCII "), Serial.write(in), Serial.print(" DEC "), Serial.print(in), Serial.println();
if (!m_pSource.available()) { // available(), number of bytes available from the current position to EOF
Serial.println("Unexpected EOF while reading file");
}
return byte(in);
}
//----------------------------------------------------------------------------
//============================================================================
// Read text Pmf ID, (1st 14 Characters -->>// Song name: <<)
//============================================================================
void ReadPmfID(int filepos)
{
Serial.println("\t-- Reading PMF Text Header (Profoundic Music File): "); // DEBUG
SDPmfIDCheck[0] = Get(m_pSource.curPosition());
SDPmfIDCheck[1] = Get(m_pSource.curPosition());
SDPmfIDCheck[2] = Get(m_pSource.curPosition());
SDPmfIDCheck[3] = Get(m_pSource.curPosition());
SDPmfIDCheck[4] = Get(m_pSource.curPosition());
SDPmfIDCheck[5] = Get(m_pSource.curPosition());
SDPmfIDCheck[6] = Get(m_pSource.curPosition());
SDPmfIDCheck[7] = Get(m_pSource.curPosition());
SDPmfIDCheck[8] = Get(m_pSource.curPosition());
SDPmfIDCheck[9] = Get(m_pSource.curPosition());
SDPmfIDCheck[10] = Get(m_pSource.curPosition());
SDPmfIDCheck[11] = Get(m_pSource.curPosition());
SDPmfIDCheck[12] = Get(m_pSource.curPosition());
SDPmfIDCheck[13] = Get(m_pSource.curPosition());
//Serial.println(m_pSource.curPosition()); // DEBUG
}
//----------------------------------------------------------------------------
//============================================================================
// interpret the ascii digits in[0] and in[1] as hex
// notation and convert to an integer 0..255.
//============================================================================
int hex8(char *in)
{
uint8_t c, h;
c = in[0];
if (c <= '9' && c >= '0') {
c -= '0';
}
else if (c <= 'f' && c >= 'a') {
c -= ('a' - 0x0a);
}
else if (c <= 'F' && c >= 'A') {
c -= ('A' - 0x0a);
}
else return (-1);
h = c;
c = in[1];
if (c <= '9' && c >= '0') {
c -= '0';
}
else if (c <= 'f' && c >= 'a') {
c -= ('a' - 0x0a);
}
else if (c <= 'F' && c >= 'A') {
c -= ('A' - 0x0a);
}
else return (-1);
return ( h << 4 | c);
}
//----------------------------------------------------------------------------
//============================================================================
// Parse Pmf Header
//============================================================================
void ParsePmfHeader(int _Fpos)
{
Serial.println();
Serial.println("\t--BEGIN -- Parse Text Header of PMF file, 1st 14 characters");
//BTserial.println();
//BTserial.println("\t--BEGIN -- Parse Text Header of PMF file");
// BTserial.println();
if (m_pSource.isDirectory()) {
Serial.println(" / ");
} else {
char filename[255]; // SDFAT
m_pSource.getName(filename, sizeof(filename)); // SDfat
const char* n = filename; // SDfat
Serial.print("\t-- The file to be parsed -> "), Serial.print(n);
//BTserial.print("\t-- The file to be parsed -> "), BTserial.println(n);
// files have sizes, directories do not
Serial.print("\t size: ");
Serial.println(m_pSource.size(), DEC);
//BTserial.print("\t size: ");
//BTserial.println(m_pSource.size(), DEC);
}
int filepos = _Fpos; // m_pSource.curPosition();
bool PMF_check = 1;
ReadPmfID(filepos);
PMF_check = memcmp(SDPmfIDCheck, PmfID, sizeof(SDPmfIDCheck)); // compares 2 chuncks of memory.
if (PMF_check == 0)
{
Serial.print("\t-- Text Header matches OK");
Serial.println();
//BTserial.println("\t-- Text Header matches OK");
//BTserial.println();
m_pSource.seekSet (0);
// Parsing Header Text
char a = 0;
char b = 0;
char c = 0;
while (a != 'x' && b != '7' && c != '0' ) {
char y;
y = (m_pSource.read()); // read next char
if (y == '0') {
char temp2 = y;
y = (m_pSource.read());
if (y != 'x') { //
Serial.print(temp2);
Serial.print(y);
//BTserial.print(temp2);
//BTserial.print(y);
}
} else if (y == 10) { // 10 0x0A, LF Line Feed
Serial.println();
//BTserial.println();
} else {
if (y != 'x') {
Serial.print(y);
//BTserial.print(y);
}
}
if (y == 'x') {
char temp1 = y;
y = (m_pSource.read()); // read next char
if (y == '7') {
y = (m_pSource.read());
if (y == '0') {
a = 'x';
b = '7';
c = y;
uint32_t fpos = m_pSource.curPosition ();
Serial.print(" DEBUG fpos ");
Serial.println(fpos);
m_pSource.seekSet(fpos - 4); // now ready for Header Data
}
} else if (y != '7') {
Serial.print(temp1);
Serial.print(y);
//BTserial.print(temp1);
//BTserial.print(y);
}
}
}
// Parsing Header Data
while (m_pSource.available()) {
char x;
x = (m_pSource.read());
if (x == '0') {
x = (m_pSource.read()); // read next char
if (x == 'x') { //
char tmp[2];
int n = 0;
tmp[0] = (m_pSource.read());
tmp[1] = (m_pSource.read());
// tmp now has two char hex value
/// ?? n = strtol(tmp, NULL, 16); // n has numeric value
n = hex8(tmp); // well this works ok, arduino strtol had some issue with some pfm files ?
SD_MusicData[array_counter] = (char)n; // SD_MusicData[X] has character value
//if (n > 255) { // debug
// Serial.print(" ASCII to hex issue: ");
// Serial.println(n);
// delay(2000);
//}
if (array_counter < 4) {
//Serial.println(array_counter);
if (array_counter == 0) {
Serial.println(" DATA Header: ");
Serial.print(array_counter);
Serial.print(" Ascii: ");
Serial.write(SD_MusicData[array_counter]);
Serial.println();
} else {
Serial.print(array_counter);
Serial.print(" Ascii: ");
Serial.write(SD_MusicData[array_counter]);
Serial.println();
}
}
array_counter++;
if (array_counter >= sizeof SD_MusicData) {
Serial.println(), Serial.println();
Serial.println(" Error file is too large for destination buffer ( : ");
Serial.print(" byte counter : "), Serial.println(array_counter);
//BTserial.println(), BTserial.println();
//BTserial.println(" Error file is too large for destination buffer ( : ");
//BTserial.print(" byte counter : "), BTserial.println(array_counter);
array_counter = 0;
// return;
break; // ?
}
}
} else if (x == 13) { // 13 0x0D, CR Carriage Return
x = (m_pSource.read()); // read next char
if (x == 10) { // 10 0x0A, LF Line Feed
}
}
}
} else {
Serial.print("No luck");
}
Serial.print(" , Size after conversion : "), Serial.println(array_counter), Serial.println();
array_counter = 0;
}
//----------------------------------------------------------------------------