Wave-Player with TLV320
Dependencies: FatFileSystemCpp I2SSlave TLV320 mbed
Diff: main.cpp
- Revision:
- 0:3087f1924901
diff -r 000000000000 -r 3087f1924901 main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Wed Dec 09 20:58:55 2015 +0000 @@ -0,0 +1,204 @@ +//------------------------------------------------------------------------------------------------------------ +// Demoprogramm 6 für die Audio-Ausgabe über das AudioCODEC Board (RS Product Code 754-1965) +//------------------------------------------------------------------------------------------------------------ +//(c) Roland Elmiger, ELcon Consulting & Engineering, Switzerland +// +// Version 1.0A +// +// Enwickelt am : 22.11.2015 +// Letzter Update : 06.12.2015 +//------------------------------------------------------------------------------------------------------------ +// Jedes WAV-Files mit den Bedingungen 44100Hz, 16-bit, Stereo sollte funktionieren. +// +// Beschaltung: +// +// AudioCODEC Board mbed NXP LPC1768 +// --------------------- --------------------- +// GND | 1 <-------> 1 | GND (0V) +// LRCOUT | 2 | +// DOUT | 3 | +// BCLK | 4 <-------- 7 | P7 (SCLK) +// DIN | 5 <-------- 5 | P5 (MOSI) +// LCRIN | 6 <-------- 6 | P6 (MISO) +// /CS | 7 <-------> 1 | GND (0V) +// MODE | 8 <-------> 1 | GND (0V) +// SDIN | 9 <-------- 9 | P9 (SDA) +// SCLK |10 <--------10 | P10 (SCL) +// +3.3V |11 <------->40 | Vout (3.3V) +// --------------------- --------------------- + + +//------------------------------------------------------------------------------------------------------------ + +#include "mbed.h" +#include "TLV320.h" +#include "SDHCFileSystem.h" +#include "LCD.h" + + +DigitalOut led1(LED1), led2(LED2), led3(LED3), led4(LED4); +Serial pc(USBTX, USBRX); + +TextLCD lcd(p26, p25, p24, p23, p22, p20, p19, TextLCD::LCD20x4); // RS, RW, E, D0, D1, D2, D3, Typ +TLV320 audio(p9, p10, 0x34, p5, p6, p7, p8, p29); //Objekt I2S Codec + +SDFileSystem sd(p11, p12, p13, p14, "sd"); //Objekt SD-Karte (MOSI, MISO, SCLK, CS, "SD-Kartenname") + +FILE *fp; //Zeiger auf die Audiodatei + +AnalogIn aIn(p15); //Lautstärke + +#define DEBOUNCING_INTERVAL 20 //Debouncing Interval (in Millisekunden) + +// Variablen +//--------------------------------------------------------------------------------------------------------------------------------------- +int RingBuffer[4096]; //Ringspeicher +volatile int ReadPointer = 0; +volatile int Theta = 0; + +/* Wav file header data, for setting up the transfer protocol */ +short Channels; //Kanalzahl (2 = Stereo, 1 = Mono) +long SampleRate; //Abtastrate +short WordWidth; //Bit-Anzahl der Daten (z.B. 16 Bit) + +bool AnsagePlay = false; // +char AnsageNr = 0; //Nr. der Ansage + +// Texte für die Anzeigen und die Audio-Dateiauswahl +//--------------------------------------------------------------------------------------------------------------------------------------- +const char AnsageAudio[5][40] = { + {"/sd/Bahnhof1.wav"}, + {"/sd/Bahnhof2.wav"}, + {"/sd/Bahnhof3.wav"}, + {"/sd/Bahnhof4.wav"}, + {"/sd/Bahnhof5.wav"} }; + +const char AnzeigeText[5][40] = { + {"Bahnhof 1\n\nEndstation\nRestaurant"}, + {"Bahnhof 2\n\nLoewengehege"}, + {"Bahnhof 3\n\nRegenwald"}, + {"Bahnhof 4\n\nSchweizer-Tiere"}, + {"Bahnhof 5\n\nEndstation\nStreichel-Zoo"} }; + +InterruptIn Reed1(p16); //Eingänge der Reed-Kontakte (LOW aktiv) +InterruptIn Reed2(p17); +InterruptIn Reed3(p18); +InterruptIn Reed4(p28); +InterruptIn Reed5(p30); + + +// Funktion zum lesen des Potentiometerwerts und setzten der Ausgangslautstärke +//------------------------------------------------------------------------------------------------------------ +void SetVolume(void) + { + audio.outputVolume(1-aIn, 1-aIn); + } + + +// Funktion zum lesen des Zirkular-Speichers und zum senden der Daten zum TLV320 +//------------------------------------------------------------------------------------------------------------ +void isr_audio(void) + { + audio.write(RingBuffer, ReadPointer, 8); + ReadPointer += 8; + ReadPointer &= 0xfff; + Theta -= 8; + } + + +// Funktion um den Zirkular-Speicher von der SD Karte zu laden +//------------------------------------------------------------------------------------------------------------ +void FillBuffer(void) + { + while(!feof(fp)) + { //füllt den Zirkularspeicher bis zum Ende des Files + static volatile int WritePointer = 0; + if(Theta < 4096) + { + fread(&RingBuffer[WritePointer], 4, 4, fp); //liest 4 integer Werte auf einmal in den Zirzularspeicher + Theta += 4; + WritePointer += 4; + WritePointer &= 0xfff; + } + } + } + + +// Interruptroutine für die Abfrage der Reed Kontakte (LOW aktiv) +//------------------------------------------------------------------------------------------------------------ +void ReedClosed() + { + wait_ms(DEBOUNCING_INTERVAL); + { + if((Reed1 == 0 || Reed2 == 0 || Reed3 == 0 || Reed4 == 0 || Reed5 == 0) && (AnsagePlay == false)) + { + AnsagePlay = true; //eine Ansage ist zum abspielen bereit + + if(Reed1 == 0) AnsageNr = 0; //Ansage Nr 1 Endstation Restaurant + else if(Reed2 == 0) AnsageNr = 1; //Ansage Nr 2 Löwengehege + else if(Reed3 == 0) AnsageNr = 2; //Ansage Nr 3 Regenwald + else if(Reed4 == 0) AnsageNr = 3; //Ansage Nr 4 Schweizer Tiere + else if(Reed5 == 0) AnsageNr = 4; //Ansage Nr 5 Endstation Streichelzoo + + pc.printf("%s\n",AnzeigeText[AnsageNr]);//zur Kontrolle den Text auch auf der serielle Schnittstelle ausgeben + lcd.cls(); //LC-Display löschen + lcd.printf("%s",AnzeigeText[AnsageNr]); //Bahnhoftext auf LCD ausgeben + } + } + } + + +// Hauptprogramm (hier beginnt der Programmablauf, "main" muss immer existieren) +//--------------------------------------------------------------------------------------------------------------------------------------- +int main(int argc, char *argv[]) + { + pc.baud(115200); + + audio.power(0x02); //Mikrofon aus + audio.inputVolume(0.2, 0.2); //Eingangspegel 0.0 bis 1.0 (leftVolumeIn, rightVolumeIn) + audio.outputVolume(0.5, 0.5); //Ausgangspegel 0.0 bis 1.0 (leftVolumeOut, rightVolumeOut) + audio.frequency(44100); //8kHz, 8.021kHz, 32kHz, 44.1kHz, 48kHz, 88.2kHz, 96kHz -> Default ist 44.1kHz + audio.attach(&isr_audio); //Interrupt für die I2SxxFIFOs + + Reed1.mode(PullUp); Reed1.fall(ReedClosed); + Reed2.mode(PullUp); Reed2.fall(ReedClosed); + Reed3.mode(PullUp); Reed3.fall(ReedClosed); + Reed4.mode(PullUp); Reed4.fall(ReedClosed); + Reed5.mode(PullUp); Reed5.fall(ReedClosed); + + pc.printf("--------------------\nSTART\n--------------------\n\n"); // "START" auf erste Zeile schreiben + wait(2); // 2s warten + +// t.start(); //Timer start + + while(1) + { + if (AnsagePlay == true) + { +// audio.start(TRANSMIT); //Interrupt starten (NONE, nur TRANSMIT, nur RECEIVE, BOTH) + pc.printf("%s\n\n",AnsageAudio[AnsageNr]); + + fp = fopen(AnsageAudio[AnsageNr],"rb"); + + if(!fp) return(printf("File Error\n")); + + fseek(fp, 22, SEEK_SET); fread(&Channels, 2, 1, fp); //Parse WAV File Header + fseek(fp, 24, SEEK_SET); fread(&SampleRate, 4, 1, fp); + fseek(fp, 34, SEEK_SET); fread(&WordWidth, 2, 1, fp); + audio.format(WordWidth, (2-Channels)); //setzen des Transferprotokoll + + for(int j = 0; j < 4096; ++j) //RingSpeicher löschen + { + RingBuffer[j] = 0; //Zirkularspeicher löschen + } + + SetVolume(); //Ausgangspegel vom Potentiometer lesen (leftVolumeOut, rightVolumeOut) + audio.start(TRANSMIT); //Interrupt kommt nur vom I2STXFIFO + FillBuffer(); //kontinuierlich den Zirkularspeicher füllen + audio.stop(); + fclose(fp); + AnsagePlay = false; + } + } + } +