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 #include <dev/vscodec.h>
00041
00042 #include <sys/event.h>
00043 #include <sys/timer.h>
00044 #include <sys/nutdebug.h>
00045 #include <sys/bankmem.h>
00046
00047 #include <stdlib.h>
00048 #include <string.h>
00049 #include <memdebug.h>
00050
00055
00059 #define VSREQ_PLAY 0x00000001
00060
00061 #define VSREQ_CANCEL 0x00000002
00062
00063 #define VSREQ_VOLUPD 0x00000004
00064
00065 #define VSREQ_AUDIOE 0x00000008
00066
00067 #define VSREQ_BEEP 0x00000010
00068
00071
00072 uint8_t zero_chunk[VSCODEC_DATA_CHUNK_SIZE];
00073
00082 int VsCodecWaitReady(NUTDEVICE *dev, uint32_t tmo)
00083 {
00084 VSDCB *dcb = (VSDCB *) dev->dev_dcb;
00085
00086 while (!(* dcb->dcb_isready)()) {
00087 if (NutEventWait(&dcb->dcb_feedme, tmo)) {
00088 return -1;
00089 }
00090 }
00091 return 0;
00092 }
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107 uint16_t VsCodecReg(NUTDEVICE *dev, uint_fast8_t op, uint_fast8_t reg, uint_fast16_t val)
00108 {
00109 uint8_t cmd[4];
00110 VSDCB *dcb = (VSDCB *) dev->dev_dcb;
00111
00112
00113 cmd[0] = (uint8_t) op;
00114 cmd[1] = (uint8_t) reg;
00115 cmd[2] = (uint8_t) (val >> 8);
00116 cmd[3] = (uint8_t) val;
00117
00118 VsCodecWaitReady(dev, VSCODEC_CMD_TIMEOUT);
00119 (*dcb->dcb_sendcmd)(cmd, 4);
00120 val = cmd[2];
00121 val <<= 8;
00122 val |= cmd[3];
00123 return (uint16_t) val;
00124 }
00125
00138 uint16_t VsCodecMode(NUTDEVICE *dev, uint_fast16_t flags, uint_fast16_t mask)
00139 {
00140 uint16_t rc;
00141
00142
00143 rc = VsCodecReg(dev, VS_OPCODE_READ, VS_MODE_REG, 0);
00144 if (mask | flags) {
00145 VsCodecReg(dev, VS_OPCODE_WRITE, VS_MODE_REG, (rc & ~mask) | flags);
00146
00147 #if defined(VSCODEC_SWRST_RECOVER)
00148 if (flags & VS_SM_RESET) {
00149 NutSleep(VSCODEC_SWRST_RECOVER);
00150 }
00151 #endif
00152 }
00153 return rc;
00154 }
00155
00165 int VsDecoderSetVolume(NUTDEVICE *dev, int left, int right)
00166 {
00167 VSDCB *dcb = (VSDCB *)dev->dev_dcb;
00168 uint16_t l;
00169 uint16_t r;
00170
00171
00172
00173 left = left > AUDIO_DAC_MAX_GAIN ? AUDIO_DAC_MAX_GAIN : left;
00174 left = left < AUDIO_DAC_MIN_GAIN ? AUDIO_DAC_MIN_GAIN : left;
00175 right = right > AUDIO_DAC_MAX_GAIN ? AUDIO_DAC_MAX_GAIN : right;
00176 right = right < AUDIO_DAC_MIN_GAIN ? AUDIO_DAC_MIN_GAIN : right;
00177
00178
00179 l = (uint16_t)(-2 * left);
00180 r = (uint16_t)(-2 * right);
00181
00182 VsCodecReg(dev, VS_OPCODE_WRITE, VS_VOL_REG, (l << VS_VOL_LEFT_LSB) | (r << VS_VOL_RIGHT_LSB));
00183 dcb->dcb_lvol = left;
00184 dcb->dcb_rvol = right;
00185
00186 return 0;
00187 }
00188
00200 int VsDecoderSetBass(NUTDEVICE *dev, int treb, int tfin, int bass, int bfin)
00201 {
00202 #ifdef VS_HAS_BASS_REG
00203 VSDCB *dcb = (VSDCB *)dev->dev_dcb;
00204
00205
00206
00207
00208
00209 treb = treb > AUDIO_DAC_MAX_TREB ? AUDIO_DAC_MAX_TREB : treb;
00210 treb = treb < 0 ? 0 : treb;
00211 tfin = tfin > AUDIO_DAC_MAX_TFIN ? AUDIO_DAC_MAX_TFIN : tfin;
00212 tfin = tfin < 0 ? 0 : tfin;
00213 bass = bass > AUDIO_DAC_MAX_BASS ? AUDIO_DAC_MAX_BASS : bass;
00214 bass = bass < 0 ? 0 : bass;
00215 bfin = bfin > AUDIO_DAC_MAX_BFIN ? AUDIO_DAC_MAX_BFIN : bfin;
00216 bfin = bfin < 0 ? 0 : bfin;
00217
00218
00219
00220
00221
00222
00223
00224 VsCodecReg(dev, VS_OPCODE_WRITE, VS_BASS_REG,
00225 (treb << VS_ST_AMPLITUDE_LSB) | (tfin << VS_ST_FREQLIMIT_LSB) |
00226 (treb << VS_SB_AMPLITUDE_LSB) | (tfin << VS_SB_FREQLIMIT_LSB)
00227 );
00228
00229 dcb->dcb_treb = treb;
00230 dcb->dcb_tfin = tfin;
00231 dcb->dcb_bass = bass;
00232 dcb->dcb_bfin = bfin;
00233 #endif
00234
00235 return 0;
00236 }
00237
00249 uint16_t VsCodecBeep(NUTDEVICE *dev, uint16_t fsin)
00250 {
00251 uint16_t rc = 0;
00252 static uint8_t on[] = { 0x53, 0xEF, 0x6E, 0x3F, 0x00, 0x00, 0x00, 0x00 };
00253 static CONST uint8_t off[] = { 0x45, 0x78, 0x69, 0x74, 0x00, 0x00, 0x00, 0x00 };
00254 static CONST uint16_t ftab[] = { 44100, 48000, 32000, 22050, 24000, 16000, 11025, 12000 };
00255 static uint16_t mode;
00256 VSDCB *dcb = (VSDCB *)dev->dev_dcb;
00257
00258 if (fsin) {
00259 uint_fast16_t s;
00260 uint32_t f;
00261 uint_fast16_t d;
00262 int_fast8_t i = sizeof(ftab) / sizeof(ftab[0]);
00263 int_fast8_t ie = 0;
00264 int_fast16_t dmin = fsin;
00265 uint32_t fs = (long)fsin * 128;
00266
00267 while (--i >= ie) {
00268
00269 f = ftab[i];
00270 s = (fs + f / 2) / f;
00271
00272 if (s && s < 32) {
00273
00274 f *= s;
00275 f += 64;
00276 f >>= 7;
00277 d = (uint_fast16_t)(fsin > f ? fsin - f : f - fsin);
00278
00279 if (d < dmin) {
00280 dmin = d;
00281 rc = (uint16_t) f;
00282
00283 on[3] = (i << 5) | s;
00284
00285 if (i > 1) {
00286 ie = i - 2;
00287 }
00288 }
00289 }
00290 }
00291 mode = VsCodecMode(dev, VS_SM_RESET, VS_SM_RESET);
00292 #ifdef VS_SM_TESTS
00293 VsCodecMode(dev, mode | VS_SM_TESTS, 0xffff);
00294 #endif
00295 (*dcb->dcb_senddata)(on, sizeof(on));
00296 } else {
00297 (*dcb->dcb_senddata)(off, sizeof(off));
00298 #ifdef VS_SM_TESTS
00299 VsCodecMode(dev, VS_SM_RESET, VS_SM_RESET | VS_SM_TESTS);
00300 #else
00301 VsCodecMode(dev, VS_SM_RESET, VS_SM_RESET);
00302 #endif
00303 VsCodecMode(dev, mode, 0xffff);
00304 }
00305 return rc;
00306 }
00307
00308
00309
00310
00311
00312
00313 int VsDecoderBufferInit(NUTDEVICE *dev, uint32_t size)
00314 {
00315 VSDCB *dcb = (VSDCB *)dev->dev_dcb;
00316
00317
00318 if (dcb->dcb_pbstat != CODEC_STATUS_IDLE) {
00319 return -1;
00320 }
00321
00322 if (NutSegBufInit((size_t)size) == NULL) {
00323 return -1;
00324 }
00325
00326 dcb->dcb_pbwlo = NutSegBufAvailable() / 3;
00327 dcb->dcb_pbwhi = dcb->dcb_pbwlo * 2;
00328
00329 return 0;
00330 }
00331
00332
00333
00334
00335 THREAD(FeederThread, arg)
00336 {
00337 uint8_t *bp;
00338 size_t avail;
00339 int filled;
00340 uint_fast8_t intest = 0;
00341 uint_fast16_t idlefill = 0;
00342 NUTDEVICE *dev = (NUTDEVICE *)arg;
00343 VSDCB *dcb = (VSDCB *)dev->dev_dcb;
00344
00345
00346 NutThreadSetPriority(7);
00347 for (;;) {
00348
00349
00350
00351 if (dcb->dcb_pbstat == CODEC_STATUS_IDLE) {
00352
00353 do {
00354
00355 NutEventWait(&dcb->dcb_feedme, NUT_WAIT_INFINITE);
00356
00357 if (dcb->dcb_scmd & VSREQ_BEEP) {
00358 if ((*dcb->dcb_isready)()) {
00359 dcb->dcb_scmd &= ~VSREQ_BEEP;
00360 intest = VsCodecBeep(dev, dcb->dcb_sinefreq) != 0;
00361 }
00362 }
00363 } while (intest);
00364
00365
00366
00367 if ((dcb->dcb_scmd & VSREQ_PLAY) != 0 || NutSegBufUsed() >= dcb->dcb_pbwhi) {
00368 dcb->dcb_scmd &= ~(VSREQ_PLAY | VSREQ_CANCEL);
00369 dcb->dcb_pbstat = CODEC_STATUS_PLAYING;
00370 VsDecoderSetVolume(dev, dcb->dcb_lvol, dcb->dcb_rvol);
00371 }
00372 }
00373
00374
00375
00376
00377 if (dcb->dcb_pbstat == CODEC_STATUS_PLAYING) {
00378
00379 VsCodecWaitReady(dev, NUT_WAIT_INFINITE);
00380
00381 if (dcb->dcb_scmd & VSREQ_CANCEL) {
00382 dcb->dcb_scmd &= ~VSREQ_CANCEL;
00383 NutSegBufReset();
00384 #if VS_HAS_SM_CANCEL
00385 VsCodecMode(dev, VS_SM_CANCEL, VS_SM_CANCEL);
00386 #endif
00387 }
00388
00389 bp = (uint8_t *) NutSegBufReadRequest(&avail);
00390 if (avail) {
00391
00392
00393
00394 filled = (*dcb->dcb_senddata)(bp, avail);
00395 if (filled) {
00396
00397 NutSegBufReadLast(filled);
00398 NutEventPost(&dcb->dcb_bufque);
00399 idlefill = 2048;
00400 }
00401 if (dcb->dcb_scmd & VSREQ_VOLUPD) {
00402 VsDecoderSetVolume(dev, dcb->dcb_lvol, dcb->dcb_rvol);
00403 dcb->dcb_scmd &= ~VSREQ_VOLUPD;
00404 }
00405 if (dcb->dcb_scmd & VSREQ_AUDIOE) {
00406 VsDecoderSetBass( dev, dcb->dcb_treb, dcb->dcb_tfin, dcb->dcb_bass, dcb->dcb_bfin);
00407 dcb->dcb_scmd &= ~VSREQ_AUDIOE;
00408 }
00409 } else if (NutSegBufUsed() == 0) {
00410
00411 if (idlefill) {
00412
00413
00414
00415
00416
00417
00418 idlefill -= (*dcb->dcb_senddata)(NULL, idlefill);
00419 }
00420 if (idlefill == 0) {
00421
00422 dcb->dcb_pbstat = CODEC_STATUS_IDLE;
00423 NutEventPost(&dcb->dcb_bufque);
00424 }
00425 }
00426 }
00427 }
00428 }
00429
00451 int VsCodecIOCtl(NUTDEVICE * dev, int req, void *conf)
00452 {
00453 int rc = 0;
00454 uint32_t *lvp = (uint32_t *) conf;
00455 int *ivp = (int *) conf;
00456 VSDCB *dcb = (VSDCB *)dev->dev_dcb;
00457
00458 switch (req) {
00459 case AUDIO_PLAY:
00460 if (dcb->dcb_pbstat == CODEC_STATUS_IDLE) {
00461
00462 dcb->dcb_scmd |= VSREQ_PLAY;
00463 }
00464 NutEventPost(&dcb->dcb_feedme);
00465 break;
00466 case AUDIO_CANCEL:
00467 if (dcb->dcb_pbstat == CODEC_STATUS_PLAYING) {
00468
00469 dcb->dcb_scmd |= VSREQ_CANCEL;
00470 }
00471 NutEventPost(&dcb->dcb_feedme);
00472 break;
00473 case AUDIO_GET_STATUS:
00474 *ivp = dcb->dcb_pbstat;
00475 break;
00476 case AUDIO_GET_PLAYGAIN:
00477 *ivp = dcb->dcb_rvol > dcb->dcb_lvol ? dcb->dcb_rvol : dcb->dcb_lvol;
00478 break;
00479 case AUDIO_SET_PLAYGAIN:
00480 dcb->dcb_lvol = *ivp;
00481 dcb->dcb_rvol = *ivp;
00482 dcb->dcb_scmd |= VSREQ_VOLUPD;
00483 break;
00484 case AUDIO_SET_TREB:
00485 dcb->dcb_treb = *ivp;
00486 dcb->dcb_scmd |= VSREQ_AUDIOE;
00487 break;
00488 case AUDIO_SET_TFIN:
00489 dcb->dcb_tfin = *ivp;
00490 dcb->dcb_scmd |= VSREQ_AUDIOE;
00491 break;
00492 case AUDIO_SET_BASS:
00493 dcb->dcb_bass = *ivp;
00494 dcb->dcb_scmd |= VSREQ_AUDIOE;
00495 break;
00496 case AUDIO_SET_BFIN:
00497 dcb->dcb_bfin = *ivp;
00498 dcb->dcb_scmd |= VSREQ_AUDIOE;
00499 break;
00500 case AUDIO_GET_PBSIZE:
00501 *lvp = NutSegBufAvailable() + NutSegBufUsed();
00502 break;
00503 case AUDIO_SET_PBSIZE:
00504 rc = VsDecoderBufferInit(dev, *lvp);
00505 break;
00506 case AUDIO_GET_PBLEVEL:
00507 *lvp = NutSegBufUsed();
00508 break;
00509 case AUDIO_GET_PBWLOW:
00510 *lvp = dcb->dcb_pbwlo;
00511 break;
00512 case AUDIO_SET_PBWLOW:
00513 dcb->dcb_pbwlo = *lvp;
00514 break;
00515 case AUDIO_GET_PBWHIGH:
00516 *lvp = dcb->dcb_pbwhi;
00517 break;
00518 case AUDIO_SET_PBWHIGH:
00519 dcb->dcb_pbwhi = *lvp;
00520 break;
00521 case AUDIO_SETWRITETIMEOUT:
00522 dcb->dcb_wtmo = *lvp;
00523 break;
00524 case AUDIO_GETWRITETIMEOUT:
00525 *lvp = dcb->dcb_wtmo;
00526 break;
00527 case AUDIO_BEEP:
00528 if (dcb->dcb_pbstat == CODEC_STATUS_IDLE) {
00529 dcb->dcb_sinefreq = *((uint16_t *) conf);
00530 dcb->dcb_scmd |= VSREQ_BEEP;
00531 NutEventPost(&dcb->dcb_feedme);
00532 } else {
00533 rc = -1;
00534 }
00535 break;
00536 #if 0
00537 case AUDIO_GET_DECINFO:
00538
00539 break;
00540 case AUDIO_GET_DECCAPS:
00541
00542 break;
00543 case AUDIO_GET_DECFMTS:
00544
00545 break;
00546 case AUDIO_SET_DECFMTS:
00547
00548 break;
00549 case AUDIO_GET_CODINFO:
00550
00551 break;
00552 case AUDIO_GET_CODCAPS:
00553
00554 break;
00555 case AUDIO_GET_CODFMTS:
00556
00557 break;
00558 case AUDIO_SET_CODFMTS:
00559
00560 break;
00561 case AUDIO_GET_MIDINFO:
00562
00563 break;
00564 case AUDIO_GET_MIDCAPS:
00565
00566 break;
00567 #endif
00568 default:
00569 rc = -1;
00570 break;
00571 }
00572 return rc;
00573 }
00574
00587 static int VsDecoderBufferFlush(NUTDEVICE *dev, uint32_t tmo)
00588 {
00589 int rc = 0;
00590 VSDCB *dcb = dev->dev_dcb;
00591
00592 for (;;) {
00593
00594 if (NutSegBufUsed()) {
00595 VsCodecIOCtl(dev, AUDIO_PLAY, NULL);
00596 }
00597
00598 else if (dcb->dcb_pbstat == CODEC_STATUS_IDLE) {
00599
00600 break;
00601 }
00602
00603 rc = NutEventWait(&dcb->dcb_bufque, tmo);
00604 if (rc) {
00605 break;
00606 }
00607 }
00608 return rc;
00609 }
00610
00624 int VsCodecWrite(NUTFILE * nfp, CONST void *data, int len)
00625 {
00626 int rc = 0;
00627 uint8_t *bp;
00628 CONST uint8_t *dp;
00629 size_t rbytes;
00630 VSDCB *dcb = nfp->nf_dev->dev_dcb;
00631
00632
00633 if (data == NULL || len == 0) {
00634 return VsDecoderBufferFlush(nfp->nf_dev, dcb->dcb_wtmo);
00635 }
00636 dp = data;
00637 while (len) {
00638 bp = (uint8_t *)NutSegBufWriteRequest(&rbytes);
00639 if (rbytes == 0) {
00640
00641 if (NutEventWait(&dcb->dcb_bufque, dcb->dcb_wtmo)) {
00642
00643 break;
00644 }
00645 } else {
00646 if (rbytes > len) {
00647 rbytes = len;
00648 }
00649 memcpy(bp, dp, rbytes);
00650 NutSegBufWriteLast(rbytes);
00651 NutEventPost(&dcb->dcb_feedme);
00652 len -= rbytes;
00653 rc += rbytes;
00654 dp += rbytes;
00655 }
00656 }
00657 return rc;
00658 }
00659
00660 #ifdef __HARVARD_ARCH__
00661
00683 int VsCodecWrite_P(NUTFILE * nfp, PGM_P buffer, int len)
00684 {
00685 return -1;
00686 }
00687 #endif
00688
00689
00690
00691
00692 NUTFILE *VsCodecOpen(NUTDEVICE * dev, CONST char *name, int mode, int acc)
00693 {
00694 NUTFILE *nfp;
00695
00696 #if defined(VS_SW_RESET_ON_OPEN)
00697 VsCodecMode(dev, VS_SM_RESET, VS_SM_RESET);
00698 #endif
00699
00700 nfp = malloc(sizeof(NUTFILE));
00701 nfp->nf_next = NULL;
00702 nfp->nf_dev = dev;
00703 nfp->nf_fcb = NULL;
00704
00705 NutSegBufReset();
00706
00707 return nfp;
00708 }
00709
00710
00711
00712
00713 int VsCodecClose(NUTFILE * nfp)
00714 {
00715 VSDCB *dcb = nfp->nf_dev->dev_dcb;
00716
00717 int rc = VsDecoderBufferFlush(nfp->nf_dev, dcb->dcb_wtmo);
00718
00719 if (nfp) {
00720 free(nfp);
00721 }
00722 return rc;
00723 }
00724