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;                        
            }
        }
   }