Wave-Player with TLV320
Dependencies: FatFileSystemCpp I2SSlave TLV320 mbed
main.cpp
- Committer:
- HB9GAA
- Date:
- 2015-12-09
- Revision:
- 0:3087f1924901
File content as of revision 0:3087f1924901:
//------------------------------------------------------------------------------------------------------------ // 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; } } }