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 #ifdef HXCODEC0_RESAMPLER
00142 static void *hres;
00143 #endif
00144
00145 typedef struct _MP3PLAYERINFO {
00146 HMP3Decoder mpi_mp3dec;
00147 MP3FrameInfo mpi_frameinfo;
00148 } MP3PLAYERINFO;
00149
00150 static MP3PLAYERINFO mpi;
00151
00152 static short pi_pcmbuf[MAX_NCHAN * MAX_NGRAN * MAX_NSAMP];
00153
00154 static int first_frame;
00155 static int samprate;
00156
00166 static int HelixPlayerSetVolume(NUTDEVICE *dev, int left, int right)
00167 {
00168 HXDCB *dcb = (HXDCB *)dev->dev_dcb;
00169
00170
00171 left = left > AUDIO_DAC_MAX_GAIN ? AUDIO_DAC_MAX_GAIN : left;
00172 left = left < AUDIO_DAC_MIN_GAIN ? AUDIO_DAC_MIN_GAIN : left;
00173 right = right > AUDIO_DAC_MAX_GAIN ? AUDIO_DAC_MAX_GAIN : right;
00174 right = right < AUDIO_DAC_MIN_GAIN ? AUDIO_DAC_MIN_GAIN : right;
00175
00176 Tlv320DacSetVolume(left, right);
00177
00178 dcb->dcb_lvol = left;
00179 dcb->dcb_rvol = right;
00180
00181 return 0;
00182 }
00183
00184 static int DecodeFrame(uint8_t *buf, int len)
00185 {
00186 int rc = len;
00187 int skip;
00188
00189 while (len >= 2 * MAINBUF_SIZE) {
00190 if ((skip = MP3FindSyncWord(buf, len)) < 0) {
00191 return -1;
00192 }
00193 if (skip) {
00194 len -= skip;
00195 buf += skip;
00196 } else {
00197 if (MP3Decode(mpi.mpi_mp3dec, &buf, &len, pi_pcmbuf, 0)) {
00198 return -1;
00199 }
00200 if (first_frame) {
00201 MP3GetLastFrameInfo(mpi.mpi_mp3dec, &mpi.mpi_frameinfo);
00202 if (mpi.mpi_frameinfo.nChans == 1) {
00203 samprate = mpi.mpi_frameinfo.samprate / 2;
00204 }
00205 else if (mpi.mpi_frameinfo.nChans == 2) {
00206 samprate = mpi.mpi_frameinfo.samprate;
00207 }
00208 else {
00209 return -1;
00210 }
00211 if (mpi.mpi_frameinfo.samprate < 8000 || samprate > DAC_OUTPUT_RATE) {
00212 return -1;
00213 }
00214 if (mpi.mpi_frameinfo.bitsPerSample != 16) {
00215 return -1;
00216 }
00217 #ifdef HXCODEC0_RESAMPLER
00218
00219 if (samprate != DAC_OUTPUT_RATE) {
00220 if ((hres = RAInitResamplerHermite(samprate, DAC_OUTPUT_RATE, mpi.mpi_frameinfo.nChans)) == NULL) {
00221 return -1;
00222 }
00223 rs_maxout = RAGetMaxOutputHermite(mpi.mpi_frameinfo.outputSamps, hres);
00224 if ((rs_pcmbuf = malloc(rs_maxout * 2)) == NULL) {
00225 return -1;
00226 }
00227 }
00228 #endif
00229 first_frame = 0;
00230 }
00231 if (Tlv320DacWrite(pi_pcmbuf, mpi.mpi_frameinfo.outputSamps)) {
00232 return -1;
00233 }
00234 break;
00235 }
00236 }
00237 return rc - len;
00238 }
00239
00240
00241
00242
00243
00244
00245 static int HelixPlayerBufferInit(NUTDEVICE *dev, uint32_t size)
00246 {
00247 HXDCB *dcb = (HXDCB *)dev->dev_dcb;
00248
00249
00250 if (dcb->dcb_pbstat != CODEC_STATUS_IDLE) {
00251 return -1;
00252 }
00253
00254 if (NutSegBufInit((size_t)size) == NULL) {
00255 return -1;
00256 }
00257
00258 dcb->dcb_pbwlo = NutSegBufAvailable() / 3;
00259 dcb->dcb_pbwhi = dcb->dcb_pbwlo * 2;
00260
00261 return 0;
00262 }
00263
00264
00265
00266
00267 THREAD(FeederThread, arg)
00268 {
00269 uint8_t *bp;
00270 uint8_t *backbuf = NULL;
00271 int backcnt = 0;
00272 size_t avail;
00273 int filled;
00274 NUTDEVICE *dev = (NUTDEVICE *)arg;
00275 HXDCB *dcb = (HXDCB *)dev->dev_dcb;
00276
00277
00278 NutThreadSetPriority(7);
00279 for (;;) {
00280
00281
00282
00283 if (dcb->dcb_pbstat == CODEC_STATUS_IDLE) {
00284
00285 NutEventWait(&dcb->dcb_feedme, NUT_WAIT_INFINITE);
00286
00287
00288
00289 if ((dcb->dcb_scmd & HXREQ_PLAY) != 0 || NutSegBufUsed() >= dcb->dcb_pbwhi) {
00290 dcb->dcb_scmd &= ~(HXREQ_PLAY | HXREQ_CANCEL);
00291 dcb->dcb_pbstat = CODEC_STATUS_PLAYING;
00292 HelixPlayerSetVolume(dev, dcb->dcb_lvol, dcb->dcb_rvol);
00293 }
00294 }
00295
00296
00297
00298
00299 if (dcb->dcb_pbstat == CODEC_STATUS_PLAYING) {
00300
00301 if (dcb->dcb_scmd & HXREQ_CANCEL) {
00302 dcb->dcb_scmd &= ~HXREQ_CANCEL;
00303 NutSegBufReset();
00304 }
00305
00306 if (dcb->dcb_scmd & HXREQ_VOLUPD) {
00307 HelixPlayerSetVolume(dev, dcb->dcb_lvol, dcb->dcb_rvol);
00308 dcb->dcb_scmd &= ~HXREQ_VOLUPD;
00309 }
00310
00311
00312 bp = (uint8_t *) NutSegBufReadRequest(&avail);
00313
00314 if (avail == 0) {
00315
00316 NutEventWait(&dcb->dcb_feedme, 10);
00317
00318 if (NutSegBufUsed() == 0) {
00319
00320 while (backcnt > 0) {
00321 filled = DecodeFrame(backbuf, backcnt);
00322 if (filled <= 0 || filled >= backcnt) {
00323 break;
00324 }
00325 backcnt -= filled;
00326 }
00327
00328 if (backcnt) {
00329 backcnt = 0;
00330 free(backbuf);
00331 }
00332 dcb->dcb_pbstat = CODEC_STATUS_IDLE;
00333 NutEventPost(&dcb->dcb_bufque);
00334 }
00335 }
00336
00337 else if (backcnt) {
00338
00339 if (backcnt + avail >= 2 * MAINBUF_SIZE) {
00340 memcpy(&backbuf[backcnt], bp, 2 * MAINBUF_SIZE - backcnt);
00341 filled = DecodeFrame(backbuf, 2 * MAINBUF_SIZE);
00342
00343 if (filled <= 0) {
00344 if (filled) {
00345 backcnt = 0;
00346 free(backbuf);
00347 }
00348 }
00349
00350 else if (filled < backcnt) {
00351 bp = &backbuf[filled];
00352 backcnt -= filled;
00353
00354 if (filled < backcnt) {
00355 #if RADIO_HAS_LARGE_RAM
00356
00357
00358 uint8_t *backrem = malloc(backcnt);
00359 if (backrem) {
00360 memcpy(backrem, bp, backcnt);
00361 memcpy(backbuf, backrem, backcnt);
00362 free(backrem);
00363 } else {
00364
00365 backcnt = 0;
00366 free(backbuf);
00367 }
00368 #else
00369
00370 int i;
00371 for (i = 0; i < backcnt; i++) {
00372 backbuf[i] = *bp++;
00373 }
00374 #endif
00375 }
00376
00377 else {
00378 memcpy(backbuf, bp, backcnt);
00379 }
00380 }
00381
00382 else {
00383 if (filled > backcnt) {
00384 NutSegBufReadLast(filled - backcnt);
00385 NutEventPost(&dcb->dcb_bufque);
00386 }
00387 backcnt = 0;
00388 free(backbuf);
00389 }
00390 }
00391
00392 else {
00393 memcpy(&backbuf[backcnt], bp, avail);
00394 backcnt += avail;
00395 NutSegBufReadLast(avail);
00396 NutEventPost(&dcb->dcb_bufque);
00397 }
00398 }
00399
00400 else if (avail >= 2 * MAINBUF_SIZE) {
00401 filled = DecodeFrame(bp, avail);
00402 if (filled <= 0) {
00403 NutSegBufReadLast(1);
00404 } else {
00405 NutSegBufReadLast(filled);
00406 }
00407 NutEventPost(&dcb->dcb_bufque);
00408 }
00409
00410 else if (NutSegBufUsed() > avail) {
00411 backbuf = malloc(2 * MAINBUF_SIZE);
00412 if (backbuf) {
00413 memcpy(backbuf, bp, avail);
00414 backcnt = avail;
00415 NutSegBufReadLast(avail);
00416 NutEventPost(&dcb->dcb_bufque);
00417 } else {
00418
00419 NutSleep(10);
00420 }
00421 }
00422
00423 else if (NutEventWait(&dcb->dcb_feedme, 10)) {
00424
00425 while (avail) {
00426 filled = DecodeFrame(backbuf, backcnt);
00427 if (filled <= 0 || filled >= avail) {
00428 break;
00429 }
00430 bp = (uint8_t *) NutSegBufReadRequest(&avail);
00431 }
00432
00433 dcb->dcb_pbstat = CODEC_STATUS_IDLE;
00434 NutEventPost(&dcb->dcb_bufque);
00435 }
00436 }
00437 }
00438 }
00439
00459 static int HelixIOCtl(NUTDEVICE * dev, int req, void *conf)
00460 {
00461 int rc = 0;
00462 uint32_t *lvp = (uint32_t *) conf;
00463 int *ivp = (int *) conf;
00464 HXDCB *dcb = (HXDCB *)dev->dev_dcb;
00465
00466 switch (req) {
00467 case AUDIO_PLAY:
00468 if (dcb->dcb_pbstat == CODEC_STATUS_IDLE) {
00469
00470 dcb->dcb_scmd |= HXREQ_PLAY;
00471 }
00472 NutEventPost(&dcb->dcb_feedme);
00473 break;
00474 case AUDIO_CANCEL:
00475 if (dcb->dcb_pbstat == CODEC_STATUS_PLAYING) {
00476
00477 dcb->dcb_scmd |= HXREQ_CANCEL;
00478 }
00479 NutEventPost(&dcb->dcb_feedme);
00480 break;
00481 case AUDIO_GET_STATUS:
00482 *ivp = dcb->dcb_pbstat;
00483 break;
00484 case AUDIO_GET_PLAYGAIN:
00485 *ivp = dcb->dcb_rvol > dcb->dcb_lvol ? dcb->dcb_rvol : dcb->dcb_lvol;
00486 break;
00487 case AUDIO_SET_PLAYGAIN:
00488 dcb->dcb_lvol = *ivp;
00489 dcb->dcb_rvol = *ivp;
00490 dcb->dcb_scmd |= HXREQ_VOLUPD;
00491 break;
00492 case AUDIO_GET_PBSIZE:
00493 *lvp = NutSegBufAvailable() + NutSegBufUsed();
00494 break;
00495 case AUDIO_SET_PBSIZE:
00496 rc = HelixPlayerBufferInit(dev, *lvp);
00497 break;
00498 case AUDIO_GET_PBLEVEL:
00499 *lvp = NutSegBufUsed();
00500 break;
00501 case AUDIO_GET_PBWLOW:
00502 *lvp = dcb->dcb_pbwlo;
00503 break;
00504 case AUDIO_SET_PBWLOW:
00505 dcb->dcb_pbwlo = *lvp;
00506 break;
00507 case AUDIO_GET_PBWHIGH:
00508 *lvp = dcb->dcb_pbwhi;
00509 break;
00510 case AUDIO_SET_PBWHIGH:
00511 dcb->dcb_pbwhi = *lvp;
00512 break;
00513 case AUDIO_SETWRITETIMEOUT:
00514 dcb->dcb_wtmo = *lvp;
00515 break;
00516 case AUDIO_GETWRITETIMEOUT:
00517 *lvp = dcb->dcb_wtmo;
00518 break;
00519 default:
00520 rc = -1;
00521 break;
00522 }
00523 return rc;
00524 }
00525
00538 static int HelixPlayerFlush(NUTDEVICE *dev, uint32_t tmo)
00539 {
00540 int rc = 0;
00541 HXDCB *dcb = dev->dev_dcb;
00542
00543 for (;;) {
00544
00545 if (NutSegBufUsed()) {
00546 HelixIOCtl(dev, AUDIO_PLAY, NULL);
00547 }
00548
00549 else if (dcb->dcb_pbstat == CODEC_STATUS_IDLE) {
00550
00551 break;
00552 }
00553
00554 rc = NutEventWait(&dcb->dcb_bufque, tmo);
00555 if (rc) {
00556 break;
00557 }
00558 }
00559 return rc;
00560 }
00561
00570 static int HelixWrite(NUTFILE * nfp, CONST void *data, int len)
00571 {
00572 int rc = 0;
00573 uint8_t *bp;
00574 CONST uint8_t *dp;
00575 size_t rbytes;
00576 HXDCB *dcb = nfp->nf_dev->dev_dcb;
00577
00578 dcb->dcb_wtmo = 3000;
00579
00580 if (data == NULL || len == 0) {
00581 return HelixPlayerFlush(nfp->nf_dev, dcb->dcb_wtmo);
00582 }
00583 dp = data;
00584 while (len) {
00585 bp = (uint8_t *)NutSegBufWriteRequest(&rbytes);
00586 if (rbytes == 0) {
00587
00588 if (NutEventWait(&dcb->dcb_bufque, dcb->dcb_wtmo)) {
00589
00590 break;
00591 }
00592 } else {
00593 if (rbytes > len) {
00594 rbytes = len;
00595 }
00596 memcpy(bp, dp, rbytes);
00597 NutSegBufWriteLast(rbytes);
00598 NutEventPost(&dcb->dcb_feedme);
00599 len -= rbytes;
00600 rc += rbytes;
00601 dp += rbytes;
00602 }
00603 }
00604 return rc;
00605 }
00606
00607 #ifdef __HARVARD_ARCH__
00608
00630 static int HelixWrite_P(NUTFILE * nfp, PGM_P buffer, int len)
00631 {
00632 return -1;
00633 }
00634 #endif
00635
00641 static NUTFILE *HelixOpen(NUTDEVICE * dev, CONST char *name, int mode, int acc)
00642 {
00643 NUTFILE *nfp;
00644
00645 if ((mpi.mpi_mp3dec = MP3InitDecoder()) == NULL) {
00646 return NUTFILE_EOF;
00647 }
00648
00649 first_frame = 1;
00650
00651 NutSleep(2);
00652
00653 nfp = malloc(sizeof(NUTFILE));
00654 nfp->nf_next = NULL;
00655 nfp->nf_dev = dev;
00656 nfp->nf_fcb = NULL;
00657
00658 NutSegBufReset();
00659
00660 return nfp;
00661 }
00662
00666 static int HelixClose(NUTFILE * nfp)
00667 {
00668 HXDCB *dcb = nfp->nf_dev->dev_dcb;
00669 int rc = HelixPlayerFlush(nfp->nf_dev, dcb->dcb_wtmo);
00670
00671 if (nfp) {
00672 if (mpi.mpi_mp3dec) {
00673 MP3FreeDecoder(mpi.mpi_mp3dec);
00674 mpi.mpi_mp3dec = NULL;
00675 }
00676 free(nfp);
00677 }
00678 return rc;
00679 }
00680
00681
00682
00683
00684 static int HelixInit(NUTDEVICE * dev)
00685 {
00686 size_t avail;
00687
00688 Tlv320DacInit(DAC_OUTPUT_RATE);
00689
00690 dcb.dcb_rvol = -32;
00691 dcb.dcb_lvol = -32;
00692 Tlv320DacSetVolume(dcb.dcb_lvol, dcb.dcb_rvol);
00693
00694
00695
00696
00697 #ifdef HXCODEC0_OUTPUT_BUFSIZ
00698 avail = HXCODEC0_OUTPUT_BUFSIZ;
00699 #else
00700 avail = NutHeapAvailable() / 2;
00701 if (avail > HXCODEC0_MAX_OUTPUT_BUFSIZ) {
00702 avail = HXCODEC0_MAX_OUTPUT_BUFSIZ;
00703 }
00704 #endif
00705 if (HelixPlayerBufferInit(dev, avail)) {
00706 return -1;
00707 }
00708
00709
00710 if (NutThreadCreate(dev->dev_name, FeederThread, dev,
00711 (NUT_THREAD_HXCODEC0STACK * NUT_THREAD_STACK_MULT) + NUT_THREAD_STACK_ADD) == 0) {
00712 return -1;
00713 }
00714 return 0;
00715 }
00716
00727 NUTDEVICE devHelixCodec = {
00728 0,
00729 {'a', 'u', 'd', 'i', 'o', '0', 0, 0, 0},
00730 IFTYP_CHAR,
00731 0,
00732 0,
00733 0,
00734 &dcb,
00735 HelixInit,
00736 HelixIOCtl,
00737 NULL,
00738 HelixWrite,
00739 #ifdef __HARVARD_ARCH__
00740 HelixWrite_P,
00741 #endif
00742 HelixOpen,
00743 HelixClose,
00744 NULL
00745 };
00746