00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 
00046 
00047 
00048 
00049 
00050 
00051 
00052 
00053 #include <sys/atom.h>
00054 #include <sys/event.h>
00055 #include <sys/timer.h>
00056 #include <sys/heap.h>
00057 
00058 #include <cfg/arch/gpio.h>
00059 #include <cfg/audio.h>
00060 #include <dev/irqreg.h>
00061 
00062 #include <contrib/hxmp3/mp3dec.h>
00063 #include <contrib/hxmp3/hermite.h>
00064 #include <dev/hxcodec.h>
00065 #include <dev/tlv320dac.h>
00066 
00067 #include <sys/bankmem.h>
00068 
00069 #include <stdlib.h>
00070 #include <stddef.h>
00071 #include <string.h>
00072 #include <memdebug.h>
00073 
00074 #if 0
00075 
00076 #define NUTDEBUG
00077 #include <stdio.h>
00078 #endif
00079 
00080 #ifndef NUT_THREAD_HXCODEC0STACK
00081 
00082 #define NUT_THREAD_HXCODEC0STACK    768
00083 #endif
00084 
00085 #ifndef HXCODEC0_MAX_OUTPUT_BUFSIZ
00086 
00087 #define HXCODEC0_MAX_OUTPUT_BUFSIZ  16384
00088 #endif
00089 
00090 #ifndef DAC_OUTPUT_RATE
00091 #if defined (AT91SAM9260_EK)
00092 #define DAC_OUTPUT_RATE     44100
00093 #else
00094 #define DAC_OUTPUT_RATE     8000
00095 #endif
00096 #endif
00097 
00098 #ifndef MP3_BUFSIZ
00099 #if defined (AT91SAM9260_EK)
00100 #define MP3_BUFSIZ          1048576
00101 #else
00102 #define MP3_BUFSIZ          (4 * MAINBUF_SIZE)
00103 #endif
00104 #endif
00105 
00106 #ifdef HXCODEC0_RESAMPLER
00107 static int rs_maxout;
00108 static short *rs_pcmbuf;
00109 #endif
00110 
00114 #define HXREQ_PLAY      0x00000001
00115 
00116 #define HXREQ_CANCEL    0x00000002
00117 
00118 #define HXREQ_VOLUPD    0x00000004
00119 
00120 #define HXREQ_BEEP      0x00000008
00121 
00127 
00128 typedef struct _HXDCB {
00129     int dcb_pbstat;     
00130     uint32_t dcb_scmd;    
00131     int dcb_rvol;           
00132     int dcb_lvol;           
00133     uint32_t dcb_pbwlo;   
00134     uint32_t dcb_pbwhi;   
00135     uint32_t dcb_wtmo;      
00136     HANDLE dcb_bufque;      
00137     HANDLE dcb_feedme;      
00138 } HXDCB;
00139 
00140 static HXDCB dcb;
00141 
00142 typedef struct _MP3PLAYERINFO {
00143     HMP3Decoder mpi_mp3dec;
00144     MP3FrameInfo mpi_frameinfo;
00145 } MP3PLAYERINFO;
00146 
00147 static MP3PLAYERINFO mpi;
00148 
00149 static short pi_pcmbuf[MAX_NCHAN * MAX_NGRAN * MAX_NSAMP];
00150 
00151 static int first_frame;
00152 static int samprate;
00153 
00163 static int HelixPlayerSetVolume(NUTDEVICE *dev, int left, int right)
00164 {
00165     HXDCB *dcb = (HXDCB *)dev->dev_dcb;
00166 
00167     
00168     left = left > AUDIO_DAC_MAX_GAIN ? AUDIO_DAC_MAX_GAIN : left;
00169     left = left < AUDIO_DAC_MIN_GAIN ? AUDIO_DAC_MIN_GAIN : left;
00170     right = right > AUDIO_DAC_MAX_GAIN ? AUDIO_DAC_MAX_GAIN : right;
00171     right = right < AUDIO_DAC_MIN_GAIN ? AUDIO_DAC_MIN_GAIN : right;
00172 
00173     Tlv320DacSetVolume(left, right);
00174 
00175     dcb->dcb_lvol = left;
00176     dcb->dcb_rvol = right;
00177 
00178     return 0;
00179 }
00180 
00181 static int DecodeFrame(uint8_t *buf, int len)
00182 {
00183     int rc = len;
00184     int skip;
00185 
00186     while (len > 2 * MAINBUF_SIZE) {
00187         if ((skip = MP3FindSyncWord(buf, len)) < 0) {
00188                     return -1;
00189             }
00190         if (skip) {
00191             len -= skip;
00192             buf += skip;
00193         } else {
00194             if (MP3Decode(mpi.mpi_mp3dec, &buf, &len, pi_pcmbuf, 0)) {
00195                 return -1;
00196             }
00197             if (first_frame) {
00198                 MP3GetLastFrameInfo(mpi.mpi_mp3dec, &mpi.mpi_frameinfo);
00199                 if (mpi.mpi_frameinfo.nChans == 1) {
00200                     samprate = mpi.mpi_frameinfo.samprate / 2;
00201                 }
00202                 else if (mpi.mpi_frameinfo.nChans == 2) {
00203                     samprate = mpi.mpi_frameinfo.samprate;
00204                 }
00205                 else {
00206                     return -1;
00207                 }
00208                 if (mpi.mpi_frameinfo.samprate < 8000 || samprate > DAC_OUTPUT_RATE) {
00209                     return -1;
00210                 }
00211                 if (mpi.mpi_frameinfo.bitsPerSample != 16) {
00212                     return -1;
00213                 }
00214 #ifdef HXCODEC0_RESAMPLER
00215                 
00216                 if (samprate != DAC_OUTPUT_RATE) {
00217                     void *hres;
00218 
00219                     if ((hres = RAInitResamplerHermite(samprate, DAC_OUTPUT_RATE, mpi.mpi_frameinfo.nChans)) == NULL) {
00220                         return -1;
00221                     }
00222                     rs_maxout = RAGetMaxOutputHermite(mpi.mpi_frameinfo.outputSamps, hres);
00223                     if ((rs_pcmbuf = malloc(rs_maxout * 2)) == NULL) {
00224                         return -1;
00225                     }
00226                 }
00227 #endif
00228                 first_frame = 0;
00229             }
00230             if (Tlv320DacWrite(pi_pcmbuf, mpi.mpi_frameinfo.outputSamps)) {
00231                 return -1;
00232             }
00233             break;
00234         }
00235     }
00236     return rc - len;
00237 }
00238 
00239 
00240 
00241 
00242 
00243 
00244 static int HelixPlayerBufferInit(NUTDEVICE *dev, uint32_t size)
00245 {
00246     HXDCB *dcb = (HXDCB *)dev->dev_dcb;
00247 
00248     
00249     if (dcb->dcb_pbstat != CODEC_STATUS_IDLE) {
00250         return -1;
00251     }
00252     
00253     if (NutSegBufInit((size_t)size) == NULL) {
00254         return -1;
00255     }
00256     
00257     dcb->dcb_pbwlo = NutSegBufAvailable() / 3;
00258     dcb->dcb_pbwhi = dcb->dcb_pbwlo * 2;
00259 
00260     return 0;
00261 }
00262 
00263 
00264 
00265 
00266 THREAD(FeederThread, arg)
00267 {
00268     uint8_t *bp;
00269     uint8_t *backbuf = NULL;
00270     int backcnt = 0;
00271     size_t avail;
00272     int filled;
00273     NUTDEVICE *dev = (NUTDEVICE *)arg;
00274     HXDCB *dcb = (HXDCB *)dev->dev_dcb;
00275 
00276     
00277     NutThreadSetPriority(7);
00278     for (;;) {
00279         
00280 
00281 
00282         if (dcb->dcb_pbstat == CODEC_STATUS_IDLE) {
00283             
00284             NutEventWait(&dcb->dcb_feedme, NUT_WAIT_INFINITE);
00285             
00286 
00287 
00288             if ((dcb->dcb_scmd & HXREQ_PLAY) != 0 || NutSegBufUsed() >=  dcb->dcb_pbwhi) {
00289                 dcb->dcb_scmd &= ~(HXREQ_PLAY | HXREQ_CANCEL);
00290                 dcb->dcb_pbstat = CODEC_STATUS_PLAYING;
00291                 HelixPlayerSetVolume(dev, dcb->dcb_lvol, dcb->dcb_rvol);
00292             }
00293         }
00294 
00295         
00296 
00297 
00298         if (dcb->dcb_pbstat == CODEC_STATUS_PLAYING) {
00299             
00300             if (dcb->dcb_scmd & HXREQ_CANCEL) {
00301                 dcb->dcb_scmd &= ~HXREQ_CANCEL;
00302                 NutSegBufReset();
00303             }
00304             if (dcb->dcb_scmd & HXREQ_VOLUPD) {
00305                 HelixPlayerSetVolume(dev, dcb->dcb_lvol, dcb->dcb_rvol);
00306                 dcb->dcb_scmd &= ~HXREQ_VOLUPD;
00307             }
00308             
00309             bp = (uint8_t *) NutSegBufReadRequest(&avail);
00310             if (backcnt && backcnt + avail >= 4 * MAINBUF_SIZE) {
00311                 memcpy(&backbuf[backcnt], bp, 4 * MAINBUF_SIZE - backcnt);
00312                 filled = DecodeFrame(backbuf, 4 * MAINBUF_SIZE);
00313                 if (filled < 0) {
00314                     backcnt = 0;
00315                     free(backbuf);
00316                 } else if (filled < backcnt) {
00317                     bp = backbuf;
00318                     backcnt -= filled;
00319                     backbuf = malloc(4 * MAINBUF_SIZE);
00320                     memcpy(backbuf, &bp[filled], backcnt);
00321                     free(bp);
00322                 } else {
00323                     if (filled > backcnt) {
00324                         NutSegBufReadLast(filled - backcnt);
00325                     }
00326                     backcnt = 0;
00327                     free(backbuf);
00328                 }
00329             } else if (avail > 2 * MAINBUF_SIZE) {
00330                 filled = DecodeFrame(bp, avail);
00331                 if (filled < 0) {
00332                     NutSegBufReadLast(1);
00333                 } else if (filled) {
00334                     NutSegBufReadLast(filled);
00335                 }
00336                 NutEventPost(&dcb->dcb_bufque);
00337             }
00338             else if (NutSegBufUsed() == 0) {
00339                 
00340                 dcb->dcb_pbstat = CODEC_STATUS_IDLE;
00341                 NutEventPost(&dcb->dcb_bufque);
00342             } else if (avail && backcnt == 0) {
00343                 backcnt = avail;
00344                 backbuf = malloc(4 * MAINBUF_SIZE);
00345                 memcpy(backbuf, bp, backcnt);
00346                 NutSegBufReadLast(backcnt);
00347                 NutEventPost(&dcb->dcb_bufque);
00348             } else {
00349                 
00350                 NutEventWait(&dcb->dcb_feedme, 1000);
00351             }
00352         }
00353     }
00354 }
00355 
00375 static int HelixIOCtl(NUTDEVICE * dev, int req, void *conf)
00376 {
00377     int rc = 0;
00378     uint32_t *lvp = (uint32_t *) conf;
00379     int *ivp = (int *) conf;
00380     HXDCB *dcb = (HXDCB *)dev->dev_dcb;
00381 
00382     switch (req) {
00383     case AUDIO_PLAY:
00384         if (dcb->dcb_pbstat == CODEC_STATUS_IDLE) {
00385             
00386             dcb->dcb_scmd |= HXREQ_PLAY;
00387         }
00388         NutEventPost(&dcb->dcb_feedme);
00389         break;
00390     case AUDIO_CANCEL:
00391         if (dcb->dcb_pbstat == CODEC_STATUS_PLAYING) {
00392             
00393             dcb->dcb_scmd |= HXREQ_CANCEL;
00394         }
00395         NutEventPost(&dcb->dcb_feedme);
00396         break;
00397     case AUDIO_GET_STATUS:
00398         *ivp = dcb->dcb_pbstat;
00399         break;
00400     case AUDIO_GET_PLAYGAIN:
00401         *ivp = dcb->dcb_rvol > dcb->dcb_lvol ? dcb->dcb_rvol : dcb->dcb_lvol;
00402         break;
00403     case AUDIO_SET_PLAYGAIN:
00404         dcb->dcb_lvol = *ivp;
00405         dcb->dcb_rvol = *ivp;
00406         dcb->dcb_scmd |= HXREQ_VOLUPD;
00407         break;
00408     case AUDIO_GET_PBSIZE:
00409         *lvp = NutSegBufAvailable() + NutSegBufUsed();
00410         break;
00411     case AUDIO_SET_PBSIZE:
00412         rc = HelixPlayerBufferInit(dev, *lvp);
00413         break;
00414     case AUDIO_GET_PBLEVEL:
00415         *lvp = NutSegBufUsed();
00416         break;
00417     case AUDIO_GET_PBWLOW:
00418         *lvp = dcb->dcb_pbwlo;
00419         break;
00420     case AUDIO_SET_PBWLOW:
00421         dcb->dcb_pbwlo = *lvp;
00422         break;
00423     case AUDIO_GET_PBWHIGH:
00424         *lvp = dcb->dcb_pbwhi;
00425         break;
00426     case AUDIO_SET_PBWHIGH:
00427         dcb->dcb_pbwhi = *lvp;
00428         break;
00429     case AUDIO_SETWRITETIMEOUT:
00430         dcb->dcb_wtmo = *lvp;
00431         break;
00432     case AUDIO_GETWRITETIMEOUT:
00433         *lvp = dcb->dcb_wtmo;
00434         break;
00435     default:
00436         rc = -1;
00437         break;
00438     }
00439     return rc;
00440 }
00441 
00454 static int HelixPlayerFlush(NUTDEVICE *dev, uint32_t tmo)
00455 {
00456     int rc = 0;
00457     HXDCB *dcb = dev->dev_dcb;
00458 
00459     for (;;) {
00460         
00461         if (NutSegBufUsed()) {
00462             HelixIOCtl(dev, AUDIO_PLAY, NULL);
00463         }
00464         
00465         else if (dcb->dcb_pbstat == CODEC_STATUS_IDLE) {
00466             
00467             break;
00468         }
00469         
00470         rc = NutEventWait(&dcb->dcb_bufque, tmo);
00471         if (rc) {
00472             break;
00473         }
00474     }
00475     return rc;
00476 }
00477 
00486 static int HelixWrite(NUTFILE * nfp, CONST void *data, int len)
00487 {
00488     int rc = 0;
00489     uint8_t *bp;
00490     CONST uint8_t *dp;
00491     size_t rbytes;
00492     HXDCB *dcb = nfp->nf_dev->dev_dcb;
00493 
00494     dcb->dcb_wtmo = 3000; 
00495     
00496     if (data == NULL || len == 0) {
00497         return HelixPlayerFlush(nfp->nf_dev, dcb->dcb_wtmo);
00498     }
00499     dp = data;
00500     while (len) {
00501         bp = (uint8_t *)NutSegBufWriteRequest(&rbytes);
00502         if (rbytes == 0) {
00503             
00504             if (NutEventWait(&dcb->dcb_bufque, dcb->dcb_wtmo)) {
00505                 
00506                 break;
00507             }
00508         } else {
00509             if (rbytes > len) {
00510                 rbytes = len;
00511             }
00512             memcpy(bp, dp, rbytes);
00513             NutSegBufWriteLast(rbytes);
00514             NutEventPost(&dcb->dcb_feedme);
00515             len -= rbytes;
00516             rc += rbytes;
00517             dp += rbytes;
00518         }
00519     }
00520     return rc;
00521 }
00522 
00523 #ifdef __HARVARD_ARCH__
00524 
00546 static int HelixWrite_P(NUTFILE * nfp, PGM_P buffer, int len)
00547 {
00548     return -1;
00549 }
00550 #endif
00551 
00557 static NUTFILE *HelixOpen(NUTDEVICE * dev, CONST char *name, int mode, int acc)
00558 {
00559     NUTFILE *nfp;
00560 
00561     if ((mpi.mpi_mp3dec = MP3InitDecoder()) == NULL) {
00562         return NUTFILE_EOF;
00563     }
00564 
00565     first_frame = 1;
00566 
00567     NutSleep(2);
00568 
00569     nfp = malloc(sizeof(NUTFILE));
00570     nfp->nf_next = NULL;
00571     nfp->nf_dev = dev;
00572     nfp->nf_fcb = NULL;
00573 
00574     NutSegBufReset();
00575 
00576     return nfp;
00577 }
00578 
00582 static int HelixClose(NUTFILE * nfp)
00583 {
00584     HXDCB *dcb = nfp->nf_dev->dev_dcb;
00585     int rc = HelixPlayerFlush(nfp->nf_dev, dcb->dcb_wtmo);
00586 
00587     if (nfp) {
00588         if (mpi.mpi_mp3dec) {
00589             MP3FreeDecoder(mpi.mpi_mp3dec);
00590             mpi.mpi_mp3dec = NULL;
00591         }
00592         free(nfp);
00593     }
00594     return rc;
00595 }
00596 
00597 
00598 
00599 
00600 static int HelixInit(NUTDEVICE * dev)
00601 {
00602     size_t avail;
00603 
00604     Tlv320DacInit(DAC_OUTPUT_RATE);
00605 
00606     dcb.dcb_rvol = -32;
00607     dcb.dcb_lvol = -32;
00608     Tlv320DacSetVolume(dcb.dcb_lvol, dcb.dcb_rvol);
00609 
00610     
00611 
00612 
00613 #ifdef HXCODEC0_OUTPUT_BUFSIZ
00614     avail = HXCODEC0_OUTPUT_BUFSIZ;
00615 #else
00616     avail = NutHeapAvailable() / 2;
00617     if (avail > HXCODEC0_MAX_OUTPUT_BUFSIZ) {
00618         avail = HXCODEC0_MAX_OUTPUT_BUFSIZ;
00619     }
00620 #endif
00621     if (HelixPlayerBufferInit(dev, avail)) {
00622         return -1;
00623     }
00624 
00625     
00626     if (NutThreadCreate(dev->dev_name, FeederThread, dev, 
00627         (NUT_THREAD_HXCODEC0STACK * NUT_THREAD_STACK_MULT) + NUT_THREAD_STACK_ADD) == 0) {
00628         return -1;
00629     }
00630     return 0;
00631 }
00632 
00643 NUTDEVICE devHelixCodec = {
00644     0,              
00645     {'a', 'u', 'd', 'i', 'o', '0', 0, 0, 0},    
00646     IFTYP_CHAR,     
00647     0,              
00648     0,              
00649     0,              
00650     &dcb,           
00651     HelixInit,         
00652     HelixIOCtl,        
00653     NULL,           
00654     HelixWrite,        
00655 #ifdef __HARVARD_ARCH__
00656     HelixWrite_P,      
00657 #endif
00658     HelixOpen,         
00659     HelixClose,        
00660     NULL            
00661 };
00662