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_BEEP 0x00000008
00066
00069
00070 uint8_t zero_chunk[VSCODEC_DATA_CHUNK_SIZE];
00071
00080 int VsCodecWaitReady(NUTDEVICE *dev, uint32_t tmo)
00081 {
00082 VSDCB *dcb = (VSDCB *) dev->dev_dcb;
00083
00084 while (!(* dcb->dcb_isready)()) {
00085 if (NutEventWait(&dcb->dcb_feedme, tmo)) {
00086 return -1;
00087 }
00088 }
00089 return 0;
00090 }
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105 uint16_t VsCodecReg(NUTDEVICE *dev, uint_fast8_t op, uint_fast8_t reg, uint_fast16_t val)
00106 {
00107 uint8_t cmd[4];
00108 VSDCB *dcb = (VSDCB *) dev->dev_dcb;
00109
00110
00111 cmd[0] = (uint8_t) op;
00112 cmd[1] = (uint8_t) reg;
00113 cmd[2] = (uint8_t) (val >> 8);
00114 cmd[3] = (uint8_t) val;
00115
00116 VsCodecWaitReady(dev, VSCODEC_CMD_TIMEOUT);
00117 (*dcb->dcb_sendcmd)(cmd, 4);
00118 val = cmd[2];
00119 val <<= 8;
00120 val |= cmd[3];
00121 return (uint16_t) val;
00122 }
00123
00136 uint16_t VsCodecMode(NUTDEVICE *dev, uint_fast16_t flags, uint_fast16_t mask)
00137 {
00138 uint16_t rc;
00139
00140
00141 rc = VsCodecReg(dev, VS_OPCODE_READ, VS_MODE_REG, 0);
00142 if (mask | flags) {
00143 VsCodecReg(dev, VS_OPCODE_WRITE, VS_MODE_REG, (rc & ~mask) | flags);
00144
00145 #if defined(VSCODEC_SWRST_RECOVER)
00146 if (flags & VS_SM_RESET) {
00147 NutSleep(VSCODEC_SWRST_RECOVER);
00148 }
00149 #endif
00150 }
00151 return rc;
00152 }
00153
00163 int VsDecoderSetVolume(NUTDEVICE *dev, int left, int right)
00164 {
00165 VSDCB *dcb = (VSDCB *)dev->dev_dcb;
00166 uint16_t l;
00167 uint16_t r;
00168
00169
00170 left = left > AUDIO_DAC_MAX_GAIN ? AUDIO_DAC_MAX_GAIN : left;
00171 left = left < AUDIO_DAC_MIN_GAIN ? AUDIO_DAC_MIN_GAIN : left;
00172 right = right > AUDIO_DAC_MAX_GAIN ? AUDIO_DAC_MAX_GAIN : right;
00173 right = right < AUDIO_DAC_MIN_GAIN ? AUDIO_DAC_MIN_GAIN : right;
00174
00175
00176 l = (uint16_t)(-2 * left);
00177 r = (uint16_t)(-2 * right);
00178
00179 VsCodecReg(dev, VS_OPCODE_WRITE, VS_VOL_REG, (l << VS_VOL_LEFT_LSB) | (r << VS_VOL_RIGHT_LSB));
00180 dcb->dcb_lvol = left;
00181 dcb->dcb_rvol = right;
00182
00183 return 0;
00184 }
00185
00197 uint16_t VsCodecBeep(NUTDEVICE *dev, uint16_t fsin)
00198 {
00199 uint16_t rc = 0;
00200 static uint8_t on[] = { 0x53, 0xEF, 0x6E, 0x3F, 0x00, 0x00, 0x00, 0x00 };
00201 static CONST uint8_t off[] = { 0x45, 0x78, 0x69, 0x74, 0x00, 0x00, 0x00, 0x00 };
00202 static CONST uint16_t ftab[] = { 44100, 48000, 32000, 22050, 24000, 16000, 11025, 12000 };
00203 static uint16_t mode;
00204 VSDCB *dcb = (VSDCB *)dev->dev_dcb;
00205
00206 if (fsin) {
00207 uint_fast16_t s;
00208 uint32_t f;
00209 uint_fast16_t d;
00210 int_fast8_t i = sizeof(ftab) / sizeof(ftab[0]);
00211 int_fast8_t ie = 0;
00212 int_fast16_t dmin = fsin;
00213 uint32_t fs = (long)fsin * 128;
00214
00215 while (--i >= ie) {
00216
00217 f = ftab[i];
00218 s = (fs + f / 2) / f;
00219
00220 if (s && s < 32) {
00221
00222 f *= s;
00223 f += 64;
00224 f >>= 7;
00225 d = (uint_fast16_t)(fsin > f ? fsin - f : f - fsin);
00226
00227 if (d < dmin) {
00228 dmin = d;
00229 rc = (uint16_t) f;
00230
00231 on[3] = (i << 5) | s;
00232
00233 if (i > 1) {
00234 ie = i - 2;
00235 }
00236 }
00237 }
00238 }
00239 mode = VsCodecMode(dev, VS_SM_RESET, VS_SM_RESET);
00240 #ifdef VS_SM_TESTS
00241 VsCodecMode(dev, mode | VS_SM_TESTS, 0xffff);
00242 #endif
00243 (*dcb->dcb_senddata)(on, sizeof(on));
00244 } else {
00245 (*dcb->dcb_senddata)(off, sizeof(off));
00246 #ifdef VS_SM_TESTS
00247 VsCodecMode(dev, VS_SM_RESET, VS_SM_RESET | VS_SM_TESTS);
00248 #else
00249 VsCodecMode(dev, VS_SM_RESET, VS_SM_RESET);
00250 #endif
00251 VsCodecMode(dev, mode, 0xffff);
00252 }
00253 return rc;
00254 }
00255
00256
00257
00258
00259
00260
00261 int VsDecoderBufferInit(NUTDEVICE *dev, uint32_t size)
00262 {
00263 VSDCB *dcb = (VSDCB *)dev->dev_dcb;
00264
00265
00266 if (dcb->dcb_pbstat != CODEC_STATUS_IDLE) {
00267 return -1;
00268 }
00269
00270 if (NutSegBufInit((size_t)size) == NULL) {
00271 return -1;
00272 }
00273
00274 dcb->dcb_pbwlo = NutSegBufAvailable() / 3;
00275 dcb->dcb_pbwhi = dcb->dcb_pbwlo * 2;
00276
00277 return 0;
00278 }
00279
00280
00281
00282
00283 THREAD(FeederThread, arg)
00284 {
00285 uint8_t *bp;
00286 size_t avail;
00287 int filled;
00288 uint_fast8_t intest = 0;
00289 uint_fast16_t idlefill = 0;
00290 NUTDEVICE *dev = (NUTDEVICE *)arg;
00291 VSDCB *dcb = (VSDCB *)dev->dev_dcb;
00292
00293
00294 NutThreadSetPriority(7);
00295 for (;;) {
00296
00297
00298
00299 if (dcb->dcb_pbstat == CODEC_STATUS_IDLE) {
00300
00301 do {
00302
00303 NutEventWait(&dcb->dcb_feedme, NUT_WAIT_INFINITE);
00304
00305 if (dcb->dcb_scmd & VSREQ_BEEP) {
00306 if ((*dcb->dcb_isready)()) {
00307 dcb->dcb_scmd &= ~VSREQ_BEEP;
00308 intest = VsCodecBeep(dev, dcb->dcb_sinefreq) != 0;
00309 }
00310 }
00311 } while (intest);
00312
00313
00314
00315 if ((dcb->dcb_scmd & VSREQ_PLAY) != 0 || NutSegBufUsed() >= dcb->dcb_pbwhi) {
00316 dcb->dcb_scmd &= ~(VSREQ_PLAY | VSREQ_CANCEL);
00317 dcb->dcb_pbstat = CODEC_STATUS_PLAYING;
00318 VsDecoderSetVolume(dev, dcb->dcb_lvol, dcb->dcb_rvol);
00319 }
00320 }
00321
00322
00323
00324
00325 if (dcb->dcb_pbstat == CODEC_STATUS_PLAYING) {
00326
00327 VsCodecWaitReady(dev, NUT_WAIT_INFINITE);
00328
00329 if (dcb->dcb_scmd & VSREQ_CANCEL) {
00330 dcb->dcb_scmd &= ~VSREQ_CANCEL;
00331 NutSegBufReset();
00332 #if VS_HAS_SM_CANCEL
00333 VsCodecMode(dev, VS_SM_CANCEL, VS_SM_CANCEL);
00334 #endif
00335 }
00336
00337 bp = (uint8_t *) NutSegBufReadRequest(&avail);
00338 if (avail) {
00339
00340
00341
00342 filled = (*dcb->dcb_senddata)(bp, avail);
00343 if (filled) {
00344
00345 NutSegBufReadLast(filled);
00346 NutEventPost(&dcb->dcb_bufque);
00347 idlefill = 2048;
00348 }
00349 if (dcb->dcb_scmd & VSREQ_VOLUPD) {
00350 VsDecoderSetVolume(dev, dcb->dcb_lvol, dcb->dcb_rvol);
00351 dcb->dcb_scmd &= ~VSREQ_VOLUPD;
00352 }
00353 } else if (NutSegBufUsed() == 0) {
00354
00355 if (idlefill) {
00356
00357
00358
00359
00360
00361
00362 idlefill -= (*dcb->dcb_senddata)(NULL, idlefill);
00363 }
00364 if (idlefill == 0) {
00365
00366 dcb->dcb_pbstat = CODEC_STATUS_IDLE;
00367 NutEventPost(&dcb->dcb_bufque);
00368 }
00369 }
00370 }
00371 }
00372 }
00373
00395 int VsCodecIOCtl(NUTDEVICE * dev, int req, void *conf)
00396 {
00397 int rc = 0;
00398 uint32_t *lvp = (uint32_t *) conf;
00399 int *ivp = (int *) conf;
00400 VSDCB *dcb = (VSDCB *)dev->dev_dcb;
00401
00402 switch (req) {
00403 case AUDIO_PLAY:
00404 if (dcb->dcb_pbstat == CODEC_STATUS_IDLE) {
00405
00406 dcb->dcb_scmd |= VSREQ_PLAY;
00407 }
00408 NutEventPost(&dcb->dcb_feedme);
00409 break;
00410 case AUDIO_CANCEL:
00411 if (dcb->dcb_pbstat == CODEC_STATUS_PLAYING) {
00412
00413 dcb->dcb_scmd |= VSREQ_CANCEL;
00414 }
00415 NutEventPost(&dcb->dcb_feedme);
00416 break;
00417 case AUDIO_GET_STATUS:
00418 *ivp = dcb->dcb_pbstat;
00419 break;
00420 case AUDIO_GET_PLAYGAIN:
00421 *ivp = dcb->dcb_rvol > dcb->dcb_lvol ? dcb->dcb_rvol : dcb->dcb_lvol;
00422 break;
00423 case AUDIO_SET_PLAYGAIN:
00424 dcb->dcb_lvol = *ivp;
00425 dcb->dcb_rvol = *ivp;
00426 dcb->dcb_scmd |= VSREQ_VOLUPD;
00427 break;
00428 case AUDIO_GET_PBSIZE:
00429 *lvp = NutSegBufAvailable() + NutSegBufUsed();
00430 break;
00431 case AUDIO_SET_PBSIZE:
00432 rc = VsDecoderBufferInit(dev, *lvp);
00433 break;
00434 case AUDIO_GET_PBLEVEL:
00435 *lvp = NutSegBufUsed();
00436 break;
00437 case AUDIO_GET_PBWLOW:
00438 *lvp = dcb->dcb_pbwlo;
00439 break;
00440 case AUDIO_SET_PBWLOW:
00441 dcb->dcb_pbwlo = *lvp;
00442 break;
00443 case AUDIO_GET_PBWHIGH:
00444 *lvp = dcb->dcb_pbwhi;
00445 break;
00446 case AUDIO_SET_PBWHIGH:
00447 dcb->dcb_pbwhi = *lvp;
00448 break;
00449 case AUDIO_SETWRITETIMEOUT:
00450 dcb->dcb_wtmo = *lvp;
00451 break;
00452 case AUDIO_GETWRITETIMEOUT:
00453 *lvp = dcb->dcb_wtmo;
00454 break;
00455 case AUDIO_BEEP:
00456 if (dcb->dcb_pbstat == CODEC_STATUS_IDLE) {
00457 dcb->dcb_sinefreq = *((uint16_t *) conf);
00458 dcb->dcb_scmd |= VSREQ_BEEP;
00459 NutEventPost(&dcb->dcb_feedme);
00460 } else {
00461 rc = -1;
00462 }
00463 break;
00464 #if 0
00465 case AUDIO_GET_DECINFO:
00466
00467 break;
00468 case AUDIO_GET_DECCAPS:
00469
00470 break;
00471 case AUDIO_GET_DECFMTS:
00472
00473 break;
00474 case AUDIO_SET_DECFMTS:
00475
00476 break;
00477 case AUDIO_GET_CODINFO:
00478
00479 break;
00480 case AUDIO_GET_CODCAPS:
00481
00482 break;
00483 case AUDIO_GET_CODFMTS:
00484
00485 break;
00486 case AUDIO_SET_CODFMTS:
00487
00488 break;
00489 case AUDIO_GET_MIDINFO:
00490
00491 break;
00492 case AUDIO_GET_MIDCAPS:
00493
00494 break;
00495 #endif
00496 default:
00497 rc = -1;
00498 break;
00499 }
00500 return rc;
00501 }
00502
00515 static int VsDecoderBufferFlush(NUTDEVICE *dev, uint32_t tmo)
00516 {
00517 int rc = 0;
00518 VSDCB *dcb = dev->dev_dcb;
00519
00520 for (;;) {
00521
00522 if (NutSegBufUsed()) {
00523 VsCodecIOCtl(dev, AUDIO_PLAY, NULL);
00524 }
00525
00526 else if (dcb->dcb_pbstat == CODEC_STATUS_IDLE) {
00527
00528 break;
00529 }
00530
00531 rc = NutEventWait(&dcb->dcb_bufque, tmo);
00532 if (rc) {
00533 break;
00534 }
00535 }
00536 return rc;
00537 }
00538
00552 int VsCodecWrite(NUTFILE * nfp, CONST void *data, int len)
00553 {
00554 int rc = 0;
00555 uint8_t *bp;
00556 CONST uint8_t *dp;
00557 size_t rbytes;
00558 VSDCB *dcb = nfp->nf_dev->dev_dcb;
00559
00560
00561 if (data == NULL || len == 0) {
00562 return VsDecoderBufferFlush(nfp->nf_dev, dcb->dcb_wtmo);
00563 }
00564 dp = data;
00565 while (len) {
00566 bp = (uint8_t *)NutSegBufWriteRequest(&rbytes);
00567 if (rbytes == 0) {
00568
00569 if (NutEventWait(&dcb->dcb_bufque, dcb->dcb_wtmo)) {
00570
00571 break;
00572 }
00573 } else {
00574 if (rbytes > len) {
00575 rbytes = len;
00576 }
00577 memcpy(bp, dp, rbytes);
00578 NutSegBufWriteLast(rbytes);
00579 NutEventPost(&dcb->dcb_feedme);
00580 len -= rbytes;
00581 rc += rbytes;
00582 dp += rbytes;
00583 }
00584 }
00585 return rc;
00586 }
00587
00588 #ifdef __HARVARD_ARCH__
00589
00611 int VsCodecWrite_P(NUTFILE * nfp, PGM_P buffer, int len)
00612 {
00613 return -1;
00614 }
00615 #endif
00616
00617
00618
00619
00620 NUTFILE *VsCodecOpen(NUTDEVICE * dev, CONST char *name, int mode, int acc)
00621 {
00622 NUTFILE *nfp;
00623
00624 #if defined(VS_SW_RESET_ON_OPEN)
00625 VsCodecMode(dev, VS_SM_RESET, VS_SM_RESET);
00626 #endif
00627
00628 nfp = malloc(sizeof(NUTFILE));
00629 if (nfp) {
00630 nfp->nf_next = NULL;
00631 nfp->nf_dev = dev;
00632 nfp->nf_fcb = NULL;
00633 }
00634
00635 NutSegBufReset();
00636
00637 return nfp;
00638 }
00639
00640
00641
00642
00643 int VsCodecClose(NUTFILE * nfp)
00644 {
00645 VSDCB *dcb = nfp->nf_dev->dev_dcb;
00646
00647 int rc = VsDecoderBufferFlush(nfp->nf_dev, dcb->dcb_wtmo);
00648
00649 if (nfp) {
00650 free(nfp);
00651 }
00652 return rc;
00653 }
00654