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 static void *hres;
00142
00143 typedef struct _MP3PLAYERINFO {
00144 HMP3Decoder mpi_mp3dec;
00145 MP3FrameInfo mpi_frameinfo;
00146 } MP3PLAYERINFO;
00147
00148 static MP3PLAYERINFO mpi;
00149
00150 static short pi_pcmbuf[MAX_NCHAN * MAX_NGRAN * MAX_NSAMP];
00151
00152 static int first_frame;
00153 static int samprate;
00154
00164 static int HelixPlayerSetVolume(NUTDEVICE *dev, int left, int right)
00165 {
00166 HXDCB *dcb = (HXDCB *)dev->dev_dcb;
00167
00168
00169 left = left > AUDIO_DAC_MAX_GAIN ? AUDIO_DAC_MAX_GAIN : left;
00170 left = left < AUDIO_DAC_MIN_GAIN ? AUDIO_DAC_MIN_GAIN : left;
00171 right = right > AUDIO_DAC_MAX_GAIN ? AUDIO_DAC_MAX_GAIN : right;
00172 right = right < AUDIO_DAC_MIN_GAIN ? AUDIO_DAC_MIN_GAIN : right;
00173
00174 Tlv320DacSetVolume(left, right);
00175
00176 dcb->dcb_lvol = left;
00177 dcb->dcb_rvol = right;
00178
00179 return 0;
00180 }
00181
00182 static int DecodeFrame(uint8_t *buf, int len)
00183 {
00184 int rc = len;
00185 int skip;
00186
00187 while (len > 2 * MAINBUF_SIZE) {
00188 if ((skip = MP3FindSyncWord(buf, len)) < 0) {
00189 return -1;
00190 }
00191 if (skip) {
00192 len -= skip;
00193 buf += skip;
00194 } else {
00195 if (MP3Decode(mpi.mpi_mp3dec, &buf, &len, pi_pcmbuf, 0)) {
00196 return -1;
00197 }
00198 if (first_frame) {
00199 MP3GetLastFrameInfo(mpi.mpi_mp3dec, &mpi.mpi_frameinfo);
00200 if (mpi.mpi_frameinfo.nChans == 1) {
00201 samprate = mpi.mpi_frameinfo.samprate / 2;
00202 }
00203 else if (mpi.mpi_frameinfo.nChans == 2) {
00204 samprate = mpi.mpi_frameinfo.samprate;
00205 }
00206 else {
00207 return -1;
00208 }
00209 if (mpi.mpi_frameinfo.samprate < 8000 || samprate > DAC_OUTPUT_RATE) {
00210 return -1;
00211 }
00212 if (mpi.mpi_frameinfo.bitsPerSample != 16) {
00213 return -1;
00214 }
00215 #ifdef HXCODEC0_RESAMPLER
00216
00217 if (samprate != DAC_OUTPUT_RATE) {
00218 if ((hres = RAInitResamplerHermite(samprate, DAC_OUTPUT_RATE, mpi.mpi_frameinfo.nChans)) == NULL) {
00219 return -1;
00220 }
00221 rs_maxout = RAGetMaxOutputHermite(mpi.mpi_frameinfo.outputSamps, hres);
00222 if ((rs_pcmbuf = malloc(rs_maxout * 2)) == NULL) {
00223 return -1;
00224 }
00225 }
00226 #endif
00227 first_frame = 0;
00228 }
00229 if (Tlv320DacWrite(pi_pcmbuf, mpi.mpi_frameinfo.outputSamps)) {
00230 return -1;
00231 }
00232 break;
00233 }
00234 }
00235 return rc - len;
00236 }
00237
00238
00239
00240
00241
00242
00243 static int HelixPlayerBufferInit(NUTDEVICE *dev, uint32_t size)
00244 {
00245 HXDCB *dcb = (HXDCB *)dev->dev_dcb;
00246
00247
00248 if (dcb->dcb_pbstat != CODEC_STATUS_IDLE) {
00249 return -1;
00250 }
00251
00252 if (NutSegBufInit((size_t)size) == NULL) {
00253 return -1;
00254 }
00255
00256 dcb->dcb_pbwlo = NutSegBufAvailable() / 3;
00257 dcb->dcb_pbwhi = dcb->dcb_pbwlo * 2;
00258
00259 return 0;
00260 }
00261
00262
00263
00264
00265 THREAD(FeederThread, arg)
00266 {
00267 uint8_t *bp;
00268 uint8_t *backbuf = NULL;
00269 int backcnt = 0;
00270 size_t avail;
00271 int filled;
00272 NUTDEVICE *dev = (NUTDEVICE *)arg;
00273 HXDCB *dcb = (HXDCB *)dev->dev_dcb;
00274
00275
00276 NutThreadSetPriority(7);
00277 for (;;) {
00278
00279
00280
00281 if (dcb->dcb_pbstat == CODEC_STATUS_IDLE) {
00282
00283 NutEventWait(&dcb->dcb_feedme, NUT_WAIT_INFINITE);
00284
00285
00286
00287 if ((dcb->dcb_scmd & HXREQ_PLAY) != 0 || NutSegBufUsed() >= dcb->dcb_pbwhi) {
00288 dcb->dcb_scmd &= ~(HXREQ_PLAY | HXREQ_CANCEL);
00289 dcb->dcb_pbstat = CODEC_STATUS_PLAYING;
00290 HelixPlayerSetVolume(dev, dcb->dcb_lvol, dcb->dcb_rvol);
00291 }
00292 }
00293
00294
00295
00296
00297 if (dcb->dcb_pbstat == CODEC_STATUS_PLAYING) {
00298
00299 if (dcb->dcb_scmd & HXREQ_CANCEL) {
00300 dcb->dcb_scmd &= ~HXREQ_CANCEL;
00301 NutSegBufReset();
00302 }
00303 if (dcb->dcb_scmd & HXREQ_VOLUPD) {
00304 HelixPlayerSetVolume(dev, dcb->dcb_lvol, dcb->dcb_rvol);
00305 dcb->dcb_scmd &= ~HXREQ_VOLUPD;
00306 }
00307
00308 bp = (uint8_t *) NutSegBufReadRequest(&avail);
00309 if (backcnt && backcnt + avail >= 4 * MAINBUF_SIZE) {
00310 memcpy(&backbuf[backcnt], bp, 4 * MAINBUF_SIZE - backcnt);
00311 filled = DecodeFrame(backbuf, 4 * MAINBUF_SIZE);
00312 if (filled < 0) {
00313 backcnt = 0;
00314 free(backbuf);
00315 } else if (filled < backcnt) {
00316 bp = backbuf;
00317 backcnt -= filled;
00318 backbuf = malloc(4 * MAINBUF_SIZE);
00319 memcpy(backbuf, &bp[filled], backcnt);
00320 free(bp);
00321 } else {
00322 if (filled > backcnt) {
00323 NutSegBufReadLast(filled - backcnt);
00324 }
00325 backcnt = 0;
00326 free(backbuf);
00327 }
00328 } else if (avail > 2 * MAINBUF_SIZE) {
00329 filled = DecodeFrame(bp, avail);
00330 if (filled < 0) {
00331 NutSegBufReadLast(1);
00332 } else if (filled) {
00333 NutSegBufReadLast(filled);
00334 }
00335 NutEventPost(&dcb->dcb_bufque);
00336 }
00337 else if (NutSegBufUsed() == 0) {
00338
00339 dcb->dcb_pbstat = CODEC_STATUS_IDLE;
00340 NutEventPost(&dcb->dcb_bufque);
00341 } else if (avail && backcnt == 0) {
00342 backcnt = avail;
00343 backbuf = malloc(4 * MAINBUF_SIZE);
00344 memcpy(backbuf, bp, backcnt);
00345 NutSegBufReadLast(backcnt);
00346 NutEventPost(&dcb->dcb_bufque);
00347 } else {
00348
00349 NutEventWait(&dcb->dcb_feedme, 1000);
00350 }
00351 }
00352 }
00353 }
00354
00374 static int HelixIOCtl(NUTDEVICE * dev, int req, void *conf)
00375 {
00376 int rc = 0;
00377 uint32_t *lvp = (uint32_t *) conf;
00378 int *ivp = (int *) conf;
00379 HXDCB *dcb = (HXDCB *)dev->dev_dcb;
00380
00381 switch (req) {
00382 case AUDIO_PLAY:
00383 if (dcb->dcb_pbstat == CODEC_STATUS_IDLE) {
00384
00385 dcb->dcb_scmd |= HXREQ_PLAY;
00386 }
00387 NutEventPost(&dcb->dcb_feedme);
00388 break;
00389 case AUDIO_CANCEL:
00390 if (dcb->dcb_pbstat == CODEC_STATUS_PLAYING) {
00391
00392 dcb->dcb_scmd |= HXREQ_CANCEL;
00393 }
00394 NutEventPost(&dcb->dcb_feedme);
00395 break;
00396 case AUDIO_GET_STATUS:
00397 *ivp = dcb->dcb_pbstat;
00398 break;
00399 case AUDIO_GET_PLAYGAIN:
00400 *ivp = dcb->dcb_rvol > dcb->dcb_lvol ? dcb->dcb_rvol : dcb->dcb_lvol;
00401 break;
00402 case AUDIO_SET_PLAYGAIN:
00403 dcb->dcb_lvol = *ivp;
00404 dcb->dcb_rvol = *ivp;
00405 dcb->dcb_scmd |= HXREQ_VOLUPD;
00406 break;
00407 case AUDIO_GET_PBSIZE:
00408 *lvp = NutSegBufAvailable() + NutSegBufUsed();
00409 break;
00410 case AUDIO_SET_PBSIZE:
00411 rc = HelixPlayerBufferInit(dev, *lvp);
00412 break;
00413 case AUDIO_GET_PBLEVEL:
00414 *lvp = NutSegBufUsed();
00415 break;
00416 case AUDIO_GET_PBWLOW:
00417 *lvp = dcb->dcb_pbwlo;
00418 break;
00419 case AUDIO_SET_PBWLOW:
00420 dcb->dcb_pbwlo = *lvp;
00421 break;
00422 case AUDIO_GET_PBWHIGH:
00423 *lvp = dcb->dcb_pbwhi;
00424 break;
00425 case AUDIO_SET_PBWHIGH:
00426 dcb->dcb_pbwhi = *lvp;
00427 break;
00428 case AUDIO_SETWRITETIMEOUT:
00429 dcb->dcb_wtmo = *lvp;
00430 break;
00431 case AUDIO_GETWRITETIMEOUT:
00432 *lvp = dcb->dcb_wtmo;
00433 break;
00434 default:
00435 rc = -1;
00436 break;
00437 }
00438 return rc;
00439 }
00440
00453 static int HelixPlayerFlush(NUTDEVICE *dev, uint32_t tmo)
00454 {
00455 int rc = 0;
00456 HXDCB *dcb = dev->dev_dcb;
00457
00458 for (;;) {
00459
00460 if (NutSegBufUsed()) {
00461 HelixIOCtl(dev, AUDIO_PLAY, NULL);
00462 }
00463
00464 else if (dcb->dcb_pbstat == CODEC_STATUS_IDLE) {
00465
00466 break;
00467 }
00468
00469 rc = NutEventWait(&dcb->dcb_bufque, tmo);
00470 if (rc) {
00471 break;
00472 }
00473 }
00474 return rc;
00475 }
00476
00485 static int HelixWrite(NUTFILE * nfp, CONST void *data, int len)
00486 {
00487 int rc = 0;
00488 uint8_t *bp;
00489 CONST uint8_t *dp;
00490 size_t rbytes;
00491 HXDCB *dcb = nfp->nf_dev->dev_dcb;
00492
00493 dcb->dcb_wtmo = 3000;
00494
00495 if (data == NULL || len == 0) {
00496 return HelixPlayerFlush(nfp->nf_dev, dcb->dcb_wtmo);
00497 }
00498 dp = data;
00499 while (len) {
00500 bp = (uint8_t *)NutSegBufWriteRequest(&rbytes);
00501 if (rbytes == 0) {
00502
00503 if (NutEventWait(&dcb->dcb_bufque, dcb->dcb_wtmo)) {
00504
00505 break;
00506 }
00507 } else {
00508 if (rbytes > len) {
00509 rbytes = len;
00510 }
00511 memcpy(bp, dp, rbytes);
00512 NutSegBufWriteLast(rbytes);
00513 NutEventPost(&dcb->dcb_feedme);
00514 len -= rbytes;
00515 rc += rbytes;
00516 dp += rbytes;
00517 }
00518 }
00519 return rc;
00520 }
00521
00522 #ifdef __HARVARD_ARCH__
00523
00545 static int HelixWrite_P(NUTFILE * nfp, PGM_P buffer, int len)
00546 {
00547 return -1;
00548 }
00549 #endif
00550
00556 static NUTFILE *HelixOpen(NUTDEVICE * dev, CONST char *name, int mode, int acc)
00557 {
00558 NUTFILE *nfp;
00559
00560 if ((mpi.mpi_mp3dec = MP3InitDecoder()) == NULL) {
00561 return NUTFILE_EOF;
00562 }
00563
00564 first_frame = 1;
00565
00566 NutSleep(2);
00567
00568 nfp = malloc(sizeof(NUTFILE));
00569 nfp->nf_next = NULL;
00570 nfp->nf_dev = dev;
00571 nfp->nf_fcb = NULL;
00572
00573 NutSegBufReset();
00574
00575 return nfp;
00576 }
00577
00581 static int HelixClose(NUTFILE * nfp)
00582 {
00583 HXDCB *dcb = nfp->nf_dev->dev_dcb;
00584 int rc = HelixPlayerFlush(nfp->nf_dev, dcb->dcb_wtmo);
00585
00586 if (nfp) {
00587 if (mpi.mpi_mp3dec) {
00588 MP3FreeDecoder(mpi.mpi_mp3dec);
00589 mpi.mpi_mp3dec = NULL;
00590 }
00591 free(nfp);
00592 }
00593 return rc;
00594 }
00595
00596
00597
00598
00599 static int HelixInit(NUTDEVICE * dev)
00600 {
00601 size_t avail;
00602
00603 Tlv320DacInit(DAC_OUTPUT_RATE);
00604
00605 dcb.dcb_rvol = -32;
00606 dcb.dcb_lvol = -32;
00607 Tlv320DacSetVolume(dcb.dcb_lvol, dcb.dcb_rvol);
00608
00609
00610
00611
00612 #ifdef HXCODEC0_OUTPUT_BUFSIZ
00613 avail = HXCODEC0_OUTPUT_BUFSIZ;
00614 #else
00615 avail = NutHeapAvailable() / 2;
00616 if (avail > HXCODEC0_MAX_OUTPUT_BUFSIZ) {
00617 avail = HXCODEC0_MAX_OUTPUT_BUFSIZ;
00618 }
00619 #endif
00620 if (HelixPlayerBufferInit(dev, avail)) {
00621 return -1;
00622 }
00623
00624
00625 if (NutThreadCreate(dev->dev_name, FeederThread, dev,
00626 (NUT_THREAD_HXCODEC0STACK * NUT_THREAD_STACK_MULT) + NUT_THREAD_STACK_ADD) == 0) {
00627 return -1;
00628 }
00629 return 0;
00630 }
00631
00642 NUTDEVICE devHelixCodec = {
00643 0,
00644 {'a', 'u', 'd', 'i', 'o', '0', 0, 0, 0},
00645 IFTYP_CHAR,
00646 0,
00647 0,
00648 0,
00649 &dcb,
00650 HelixInit,
00651 HelixIOCtl,
00652 NULL,
00653 HelixWrite,
00654 #ifdef __HARVARD_ARCH__
00655 HelixWrite_P,
00656 #endif
00657 HelixOpen,
00658 HelixClose,
00659 NULL
00660 };
00661