Wave-Player with TLV320

Dependencies:   FatFileSystemCpp I2SSlave TLV320 mbed

Revision:
0:3087f1924901
--- /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;                        
+            }
+        }
+   }
+