doku newon / Mbed 2 deprecated Peach_AudioChannelDividerAndCompensator

Dependencies:   DokuFFTPACK DokuUSBDevice DokuUSBHost DokuUSBHostWithIso mbed

Fork of Peach_AudioChannelDividerAndCompensator by doku newon

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /*
00002  *  this is free software; you can redistribute it and/or modify
00003  *  it under the terms of the GNU General Public License as published by
00004  *  the Free Software Foundation; either version 2 of the License, or
00005  *  (at your option) any later version.
00006  *
00007  *  this software is distributed in the hope that it will be useful,
00008  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00009  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00010  *  GNU General Public License for more details.
00011  *
00012  *  You should have received a copy of the GNU General Public License
00013  *  along with libfftpack; if not, write to the Free Software
00014  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00015  */
00016  
00017 #include "mbed.h"
00018 #include "USBHost6ChDac.h"
00019 #include "USBHostMSD.h"
00020 #include "filter.h"
00021 #include "USBAudio.h"
00022 
00023 #if defined(TARGET_RZ_A1H)
00024 #include "usb_host_setting.h"
00025 #else
00026 #define USB_HOST_CH     0
00027 #endif
00028 
00029 //data size of receiving buffer in long word (32767samples 16bit stereo)
00030 #define IN_DWORDS               32768                       
00031 #define IN_BANKS                2
00032 //data size of sending buffer in long word (32767samples 16bit 6ch)
00033 #define OUT_DWORDS              (3 * IN_DWORDS)             
00034 #define OUT_BANKS               2
00035 //data size of silence data in long word (48ksps 16bit 6ch 100msec)
00036 #define NULL_DWORDS             (48 * 2 * 6 * 100 / 4)      
00037 
00038 //shows USB audio is attached or not
00039 extern int USB_Audio_Attached;
00040 //receiving buffer (2 banks)
00041 static volatile uint32_t BufR[IN_BANKS][IN_DWORDS];
00042 //sending buffer (2 banks)
00043 static volatile uint32_t BufW[OUT_BANKS][OUT_DWORDS];
00044 //silence data buffer to adjust buffer volume
00045 static volatile uint32_t BufNull[NULL_DWORDS] = {};
00046 //overflow flag of FFT
00047 int FFTOverFlow = 0;                                        
00048 
00049 //push button on the board
00050 DigitalIn  button(USER_BUTTON0);                            
00051 
00052 //shows adjustment for buffer short or full is done
00053 DigitalOut LedR(LED1);                                      
00054 DigitalOut LedG(LED2);
00055 //shows FFT is in process
00056 DigitalOut LedB(LED3);                                      
00057 
00058 //USBDAC host
00059 USBHostDac *pusbdac;
00060 
00061 //receive buffer bank 0 or 1 ready
00062 Semaphore semR0(0);
00063 Semaphore semR1(0);
00064 //send buffer bank 0 or 1 ready
00065 Semaphore semW0(0);
00066 Semaphore semW1(0);
00067 
00068 Semaphore *semR[2] = {&semR0, &semR1}; 
00069 Semaphore *semW[2] = {&semW0, &semW1}; 
00070 
00071 //measures latency of semaphore waiting
00072 Timer Tmr;
00073 
00074 //target latency for buffer slack in mili sec (88msec for buffer full at 11 ITDs)
00075 #define TARGET_LATENCY          40
00076 //allowance of latency
00077 //latency is controled in TARGET_LATENCY - LATENCY_ALLOWANCE to TARGET_LATENCY + LATENCY_ALLOWANCE
00078 #define LATENCY_ALLOWANCE       30
00079 //output byte number to get 1msecond adjustment (48ksps 16bit 6ch at 1milisec)
00080 #define OUT_BYTE_PER_MILISEC    (48*2*6)    
00081 
00082 //sound data sending task
00083 void UsbSend(void const* arg) 
00084 {
00085     //usb host
00086     USBHostDac * p_usbdac = (USBHostDac *)arg;
00087     //bank number of buffer (0 or 1)
00088     int Bank = 0;
00089     //waiting latency of semaphore
00090     int Latency;
00091     //adjust time in mili second
00092     int Adjmsec;
00093     //number of skipping byte 
00094     int SkipBytes;
00095 
00096     Tmr.start();
00097     for(;;) 
00098     {
00099         //riset adjusting display
00100         LedR = 0;
00101         //reset timer to measure latency of semaphore
00102         Tmr.reset();
00103         semW[Bank]->wait();
00104         //get latency
00105         Latency = Tmr.read_ms();
00106         printf("Latency:%d\n",Latency);
00107         //if semahore's latency is too large, data shortage has happen
00108         if(Latency > (TARGET_LATENCY + LATENCY_ALLOWANCE)) 
00109         {
00110             //get period for adjustment 
00111             Adjmsec = Latency - TARGET_LATENCY;
00112             if(Adjmsec > TARGET_LATENCY) Adjmsec = TARGET_LATENCY;
00113             printf("Recover %dmsec\n",Adjmsec);
00114             //put silence data into sending queue to prevent data shortage
00115             p_usbdac->send((uint8_t *)BufNull, Adjmsec * OUT_BYTE_PER_MILISEC, false);
00116             //data skip is unnecessary for buffer have some vacancy
00117             SkipBytes = 0;
00118             //Show adjusting happend
00119             LedR = 1;
00120         }
00121         //if semahore's latency is too small, buffer is nearly full
00122         else if(Latency < (TARGET_LATENCY - LATENCY_ALLOWANCE))
00123         {
00124             //get period for adjustment 
00125             Adjmsec = TARGET_LATENCY - Latency;
00126             if(Adjmsec > TARGET_LATENCY) Adjmsec = TARGET_LATENCY;
00127             //decrease sending data, to make some vacancy on the buffer
00128             SkipBytes = Adjmsec * OUT_BYTE_PER_MILISEC;
00129             printf("Skip %dmsec %dByte\n",Adjmsec,SkipBytes);
00130             //Show adjusting happend
00131             LedR = 1;
00132         }
00133         else
00134         {
00135             //no demand for data skip because buffer have regular vacancy
00136             SkipBytes = 0;
00137         }
00138         //send music data
00139         p_usbdac->send((uint8_t *)&BufW[Bank][SkipBytes / 4], OUT_DWORDS * 4 - SkipBytes, false);
00140         //next bank
00141         Bank++;
00142         Bank &= 1;
00143     }
00144 }
00145 
00146 //FFT solving task
00147 void FFTSolve(void const* arg) 
00148 {
00149     int Bank = 0;
00150     for(;;)  
00151     {  
00152         //wait for FFT sorce data ready
00153         semR[Bank]->wait();
00154         //show FFT is in work
00155         LedB = 1;
00156         //apply FIR filters and write the result on the buffer
00157         FFTOverFlow = FLT_Filter((int16_t *)(BufW[Bank]),(int16_t *)(BufR[Bank]),!button);
00158 //      FFTOverFlow = FLT_Through((int16_t *)(BufW[Bank]),(int16_t *)BufR[Bank]);
00159         //show FFT ended
00160         LedB = 0;
00161         //order to send the FFT result 
00162         semW[Bank]->release();
00163         //next bank
00164         Bank++;
00165         Bank &= 1;
00166     }
00167 }
00168 
00169 //receive 32768 sample of audio input from USB audio device
00170 int usbdevice_receive32k(USBAudio *paudio,uint32_t *Buf)
00171 {
00172     int i;
00173     
00174     //repat reading in 1 second
00175     for(i = 0;i < 70;i++)
00176     {
00177         //attempting to read
00178         if(paudio->read32k(Buf))
00179         {
00180             //returns 1 if correctly read
00181             return 1;
00182         }
00183         else
00184         {
00185             //if read error, wait a moment and retry
00186             Thread::wait(10);
00187         }
00188     }
00189     //returns 0 if read error
00190     return 0;
00191 }
00192 
00193 int main() 
00194 {
00195     //receiving bank (0 or 1)
00196     int Bank = 0;
00197     //receiving result
00198     int rc = 0;
00199     //input mode 1:USB audio device 0:LINE-IN of USB DAC
00200     int InModeUSB = 1;
00201     
00202     printf("\n\nStarted\n");
00203 
00204     //initializing silence buffer
00205     memset((uint8_t *)BufNull,0,NULL_DWORDS * 4);
00206 
00207     //USB audio device initialize
00208     static USBAudio audio(48000, 2, 8000, 1, 0x7180, 0x7500);
00209 
00210     //start Mass Strage Device host
00211     USBHostMSD msd("usb");
00212     //start Audio host
00213     USBHostDac usbdac;
00214     //get pointer to Audio host to use it in other function
00215     pusbdac = &usbdac;
00216 
00217     //wait connection of MSD
00218     while(!msd.connect()) 
00219     {
00220         printf("Attempting to connect a MSD\n");
00221         Thread::wait(500);
00222     }
00223     
00224     //initializing FIR filters (setting up FFT and reading filter coefficients)
00225     while(! FLT_Init())
00226     {
00227         printf("Filter initialization error\n");
00228         Thread::wait(500);
00229     }
00230 
00231     //create sending and FFT task
00232     Thread SendTask(UsbSend, &usbdac, osPriorityNormal, 1024 * 8);
00233     Thread FFTTask(FFTSolve, &usbdac, osPriorityNormal, 1024 * 8);
00234 
00235     for(;;)
00236     {
00237         //
00238         //      CONNECTION WITH USB-DAC
00239         //
00240         //if USB-DAC is disconnected
00241         if(! pusbdac->connected())
00242         {
00243             //connect USB-DAC
00244             pusbdac->connect(); 
00245         }
00246         //
00247         //      INPUT SWITCHING
00248         //
00249         //if now switched to USB_INPUT mode
00250         if(InModeUSB)
00251         {
00252             //if USB_INPUT is detached
00253             if(! USB_Audio_Attached)
00254             {
00255                 //select LINE_INPUT for input
00256                 printf("Switched to LINE-IN\n");
00257                 InModeUSB = 0;
00258             }
00259         }
00260         //if now switched to LINE_INPUT mode
00261         else
00262         {
00263             //if USB_INPUT is attached
00264             if(USB_Audio_Attached)
00265             {
00266                 //select USB_INPUT for input
00267                 printf("Switched to USB-IN\n");
00268                 InModeUSB = 1;
00269             }
00270         }
00271         //
00272         //      RECEIVING AUDIO DATA
00273         //
00274         //if using USB-INPUT
00275         if(InModeUSB)
00276         {
00277             //receive USB-IN
00278             rc = usbdevice_receive32k(&audio,(uint32_t *)BufR[Bank]);
00279         }
00280         //if using LINE-IN
00281         else
00282         {
00283             //receive LINE-IN
00284             rc = usbdac.receive((uint8_t *)(BufR[Bank]), IN_DWORDS * 4);
00285         }
00286         //
00287         //      ERROR HANDLING and ORDERING TO START FFT
00288         //
00289         //if error occurs
00290         if(! rc)
00291         {
00292             //order send task to full some data to prevent data short 
00293             //Recover = 1;
00294             //clear all buffers to mute
00295             audio.clear32k();
00296             FLT_Clear();
00297             memset((uint8_t *)BufR,0,IN_DWORDS * IN_BANKS * 4);
00298             memset((uint8_t *)BufW,0,OUT_DWORDS * OUT_BANKS * 4);
00299         }
00300         //if read correctly
00301         else
00302         {
00303             //order to start FFT
00304             semR[Bank]->release();
00305             //select next bank  
00306             Bank++;
00307             Bank &= 1;
00308         }
00309     }
00310 }