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 #include <fcntl.h>
00051
00056
00060 #define VSREQ_PLAY 0x00000001
00061
00062 #define VSREQ_CANCEL 0x00000002
00063
00064 #define VSREQ_VOLUPD 0x00000004
00065
00066 #define VSREQ_AUDIOE 0x00000008
00067
00068 #define VSREQ_BEEP 0x00000010
00069
00070 #define VSREQ_RECORD 0x00000020
00071
00074
00075 uint8_t zero_chunk[VSCODEC_DATA_CHUNK_SIZE];
00076
00085 int VsCodecWaitReady(NUTDEVICE *dev, uint32_t tmo)
00086 {
00087 VSDCB *dcb = (VSDCB *) dev->dev_dcb;
00088
00089 while (!(* dcb->dcb_isready)()) {
00090 if (NutEventWait(&dcb->dcb_feedme, tmo)) {
00091 return -1;
00092 }
00093 }
00094 return 0;
00095 }
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110 uint16_t VsCodecReg(NUTDEVICE *dev, uint_fast8_t op, uint_fast8_t reg, uint_fast16_t val)
00111 {
00112 uint8_t cmd[4];
00113 VSDCB *dcb = (VSDCB *) dev->dev_dcb;
00114
00115
00116 cmd[0] = (uint8_t) op;
00117 cmd[1] = (uint8_t) reg;
00118 cmd[2] = (uint8_t) (val >> 8);
00119 cmd[3] = (uint8_t) val;
00120
00121 VsCodecWaitReady(dev, VSCODEC_CMD_TIMEOUT);
00122 (*dcb->dcb_sendcmd)(cmd, 4);
00123 val = cmd[2];
00124 val <<= 8;
00125 val |= cmd[3];
00126 return (uint16_t) val;
00127 }
00128
00141 uint16_t VsCodecMode(NUTDEVICE *dev, uint_fast16_t flags, uint_fast16_t mask)
00142 {
00143 uint16_t rc;
00144
00145
00146 rc = VsCodecReg(dev, VS_OPCODE_READ, VS_MODE_REG, 0);
00147 if (mask | flags) {
00148 VsCodecReg(dev, VS_OPCODE_WRITE, VS_MODE_REG, (rc & ~mask) | flags);
00149
00150 #if defined(VSCODEC_SWRST_RECOVER)
00151 if (flags & VS_SM_RESET) {
00152 NutSleep(VSCODEC_SWRST_RECOVER);
00153 }
00154 #endif
00155 }
00156 return rc;
00157 }
00158
00168 int VsDecoderSetVolume(NUTDEVICE *dev, int left, int right)
00169 {
00170 VSDCB *dcb = (VSDCB *)dev->dev_dcb;
00171 uint16_t l;
00172 uint16_t r;
00173
00174
00175 left = left > AUDIO_DAC_MAX_GAIN ? AUDIO_DAC_MAX_GAIN : left;
00176 left = left < AUDIO_DAC_MIN_GAIN ? AUDIO_DAC_MIN_GAIN : left;
00177 right = right > AUDIO_DAC_MAX_GAIN ? AUDIO_DAC_MAX_GAIN : right;
00178 right = right < AUDIO_DAC_MIN_GAIN ? AUDIO_DAC_MIN_GAIN : right;
00179
00180
00181 l = (uint16_t)(-2 * left);
00182 r = (uint16_t)(-2 * right);
00183
00184 VsCodecReg(dev, VS_OPCODE_WRITE, VS_VOL_REG, (l << VS_VOL_LEFT_LSB) | (r << VS_VOL_RIGHT_LSB));
00185 dcb->dcb_lvol = left;
00186 dcb->dcb_rvol = right;
00187
00188 return 0;
00189 }
00190
00202 int VsDecoderSetBass(NUTDEVICE *dev, int treb, int tfin, int bass, int bfin)
00203 {
00204 #ifdef VS_HAS_BASS_REG
00205 VSDCB *dcb = (VSDCB *)dev->dev_dcb;
00206
00207
00208
00209
00210
00211 treb = treb > AUDIO_DAC_MAX_TREB ? AUDIO_DAC_MAX_TREB : treb;
00212 treb = treb < 0 ? 0 : treb;
00213 tfin = tfin > AUDIO_DAC_MAX_TFIN ? AUDIO_DAC_MAX_TFIN : tfin;
00214 tfin = tfin < 0 ? 0 : tfin;
00215 bass = bass > AUDIO_DAC_MAX_BASS ? AUDIO_DAC_MAX_BASS : bass;
00216 bass = bass < 0 ? 0 : bass;
00217 bfin = bfin > AUDIO_DAC_MAX_BFIN ? AUDIO_DAC_MAX_BFIN : bfin;
00218 bfin = bfin < 0 ? 0 : bfin;
00219
00220
00221
00222
00223
00224
00225
00226 VsCodecReg(dev, VS_OPCODE_WRITE, VS_BASS_REG,
00227 (treb << VS_ST_AMPLITUDE_LSB) | (tfin << VS_ST_FREQLIMIT_LSB) |
00228 (treb << VS_SB_AMPLITUDE_LSB) | (tfin << VS_SB_FREQLIMIT_LSB)
00229 );
00230
00231 dcb->dcb_treb = treb;
00232 dcb->dcb_tfin = tfin;
00233 dcb->dcb_bass = bass;
00234 dcb->dcb_bfin = bfin;
00235 #endif
00236
00237 return 0;
00238 }
00239
00251 uint16_t VsCodecBeep(NUTDEVICE *dev, uint16_t fsin)
00252 {
00253 uint16_t rc = 0;
00254 static uint8_t on[] = { 0x53, 0xEF, 0x6E, 0x3F, 0x00, 0x00, 0x00, 0x00 };
00255 static CONST uint8_t off[] = { 0x45, 0x78, 0x69, 0x74, 0x00, 0x00, 0x00, 0x00 };
00256 static CONST uint16_t ftab[] = { 44100, 48000, 32000, 22050, 24000, 16000, 11025, 12000 };
00257 static uint16_t mode;
00258 VSDCB *dcb = (VSDCB *)dev->dev_dcb;
00259
00260 if (fsin) {
00261 uint_fast16_t s;
00262 uint32_t f;
00263 uint_fast16_t d;
00264 int_fast8_t i = sizeof(ftab) / sizeof(ftab[0]);
00265 int_fast8_t ie = 0;
00266 int_fast16_t dmin = fsin;
00267 uint32_t fs = (long)fsin * 128;
00268
00269 while (--i >= ie) {
00270
00271 f = ftab[i];
00272 s = (fs + f / 2) / f;
00273
00274 if (s && s < 32) {
00275
00276 f *= s;
00277 f += 64;
00278 f >>= 7;
00279 d = (uint_fast16_t)(fsin > f ? fsin - f : f - fsin);
00280
00281 if (d < dmin) {
00282 dmin = d;
00283 rc = (uint16_t) f;
00284
00285 on[3] = (i << 5) | s;
00286
00287 if (i > 1) {
00288 ie = i - 2;
00289 }
00290 }
00291 }
00292 }
00293 mode = VsCodecMode(dev, VS_SM_RESET, VS_SM_RESET);
00294 #ifdef VS_SM_TESTS
00295 VsCodecMode(dev, mode | VS_SM_TESTS, 0xffff);
00296 #endif
00297 (*dcb->dcb_senddata)(on, sizeof(on));
00298 } else {
00299 (*dcb->dcb_senddata)(off, sizeof(off));
00300 #ifdef VS_SM_TESTS
00301 VsCodecMode(dev, VS_SM_RESET, VS_SM_RESET | VS_SM_TESTS);
00302 #else
00303 VsCodecMode(dev, VS_SM_RESET, VS_SM_RESET);
00304 #endif
00305 VsCodecMode(dev, mode, 0xffff);
00306 }
00307 return rc;
00308 }
00309
00310
00311
00312
00313
00314
00315 int VsDecoderBufferInit(NUTDEVICE *dev, uint32_t size)
00316 {
00317 VSDCB *dcb = (VSDCB *)dev->dev_dcb;
00318
00319
00320 if (dcb->dcb_pbstat != CODEC_STATUS_IDLE) {
00321 return -1;
00322 }
00323
00324 if (NutSegBufInit((size_t)size) == NULL) {
00325 return -1;
00326 }
00327
00328 dcb->dcb_pbwlo = NutSegBufAvailable() / 3;
00329 dcb->dcb_pbwhi = dcb->dcb_pbwlo * 2;
00330
00331 return 0;
00332 }
00333
00334
00335
00336
00337 THREAD(FeederThread, arg)
00338 {
00339 uint8_t *bp;
00340 size_t avail;
00341 int filled;
00342 uint_fast8_t intest = 0;
00343 uint_fast16_t idlefill = 0;
00344 NUTDEVICE *dev = (NUTDEVICE *)arg;
00345 VSDCB *dcb = (VSDCB *)dev->dev_dcb;
00346
00347
00348 NutThreadSetPriority(7);
00349 for (;;) {
00350
00351
00352
00353 if (dcb->dcb_pbstat == CODEC_STATUS_IDLE) {
00354
00355 do {
00356
00357 NutEventWait(&dcb->dcb_feedme, NUT_WAIT_INFINITE);
00358
00359 if (dcb->dcb_scmd & VSREQ_BEEP) {
00360 if ((*dcb->dcb_isready)()) {
00361 dcb->dcb_scmd &= ~VSREQ_BEEP;
00362 intest = VsCodecBeep(dev, dcb->dcb_sinefreq) != 0;
00363 }
00364 }
00365 } while (intest);
00366
00367 if (dcb->dcb_scmd & VSREQ_RECORD) {
00368 dcb->dcb_scmd &= ~(VSREQ_RECORD | VSREQ_CANCEL);
00369 dcb->dcb_pbstat = CODEC_STATUS_RECORDING;
00370
00371 VsCodecReg(dev, VS_OPCODE_WRITE, VS_AIADDR_REG, 0x0034);
00372 }
00373
00374
00375
00376 else if ((dcb->dcb_scmd & VSREQ_PLAY) != 0 || NutSegBufUsed() >= dcb->dcb_pbwhi) {
00377 dcb->dcb_scmd &= ~(VSREQ_PLAY | VSREQ_CANCEL);
00378 dcb->dcb_pbstat = CODEC_STATUS_PLAYING;
00379 VsDecoderSetVolume(dev, dcb->dcb_lvol, dcb->dcb_rvol);
00380 }
00381 }
00382
00383
00384
00385
00386 if (dcb->dcb_pbstat == CODEC_STATUS_PLAYING) {
00387
00388 VsCodecWaitReady(dev, NUT_WAIT_INFINITE);
00389
00390 if (dcb->dcb_scmd & VSREQ_CANCEL) {
00391 dcb->dcb_scmd &= ~VSREQ_CANCEL;
00392 NutSegBufReset();
00393 #if VS_HAS_SM_CANCEL
00394 VsCodecMode(dev, VS_SM_CANCEL, VS_SM_CANCEL);
00395 #endif
00396 }
00397
00398 bp = (uint8_t *) NutSegBufReadRequest(&avail);
00399 if (avail) {
00400
00401
00402
00403 filled = (*dcb->dcb_senddata)(bp, avail);
00404 if (filled) {
00405
00406 NutSegBufReadLast(filled);
00407 NutEventPost(&dcb->dcb_bufque);
00408 idlefill = 2048;
00409 }
00410 if (dcb->dcb_scmd & VSREQ_VOLUPD) {
00411 VsDecoderSetVolume(dev, dcb->dcb_lvol, dcb->dcb_rvol);
00412 dcb->dcb_scmd &= ~VSREQ_VOLUPD;
00413 }
00414 if (dcb->dcb_scmd & VSREQ_AUDIOE) {
00415 VsDecoderSetBass( dev, dcb->dcb_treb, dcb->dcb_tfin, dcb->dcb_bass, dcb->dcb_bfin);
00416 dcb->dcb_scmd &= ~VSREQ_AUDIOE;
00417 }
00418 } else if (NutSegBufUsed() == 0) {
00419
00420 if (idlefill) {
00421
00422
00423
00424
00425
00426
00427 idlefill -= (*dcb->dcb_senddata)(NULL, idlefill);
00428 }
00429 if (idlefill == 0) {
00430
00431 dcb->dcb_pbstat = CODEC_STATUS_IDLE;
00432 NutEventPost(&dcb->dcb_bufque);
00433 }
00434 }
00435 }
00436
00437
00438
00439
00440 else if (dcb->dcb_pbstat == CODEC_STATUS_RECORDING) {
00441 for (;;) {
00442
00443 if (dcb->dcb_scmd & VSREQ_CANCEL) {
00444 dcb->dcb_scmd &= ~VSREQ_CANCEL;
00445 dcb->dcb_pbstat = CODEC_STATUS_IDLE;
00446 break;
00447 }
00448 bp = (uint8_t *)NutSegBufWriteRequest(&avail);
00449 avail >>= 1;
00450 if (avail == 0) {
00451
00452 dcb->dcb_pbstat = CODEC_STATUS_IDLE;
00453 break;
00454 }
00455 #if defined(VS_HDAT0_REG) && defined(VS_HDAT1_REG)
00456
00457 filled = VsCodecReg(dev, VS_OPCODE_READ, VS_HDAT1_REG, 0);
00458 if (filled > 255) {
00459 if (avail > filled) {
00460 avail = filled;
00461 } else {
00462 filled = avail;
00463 }
00464 while (filled--) {
00465 uint16_t data = VsCodecReg(dev, VS_OPCODE_READ, VS_HDAT0_REG, 0);
00466 *bp++ = (uint8_t) data >> 8;
00467 *bp++ = (uint8_t) data >> 8;
00468 }
00469 NutSegBufWriteLast(avail << 1);
00470 NutEventPost(&dcb->dcb_bufque);
00471 } else {
00472 NutSleep(200);
00473 }
00474 #endif
00475 }
00476 NutEventPost(&dcb->dcb_bufque);
00477 }
00478 }
00479 }
00480
00481
00482 static int VsCodecLoadPlugIn(NUTDEVICE *dev, VS_PLUGIN_INFO *plg)
00483 {
00484 uint_fast8_t reg;
00485 uint_fast16_t cnt;
00486 size_t i = 0;
00487
00488 #ifdef VS_SM_ADPCM
00489 VsCodecMode(dev, 0, VS_SM_ADPCM);
00490 #endif
00491 VsCodecReg(dev, VS_OPCODE_WRITE, VS_CLOCKF_REG, 0xC000);
00492 NutSleep(100);
00493 #if VS_HAS_BASS_REG
00494 VsCodecReg(dev, VS_OPCODE_WRITE, VS_BASS_REG, 0);
00495 #endif
00496 VsCodecReg(dev, VS_OPCODE_WRITE, VS_AIADDR_REG, 0);
00497 VsCodecReg(dev, VS_OPCODE_WRITE, VS_WRAMADDR_REG, 0xC01A);
00498 VsCodecReg(dev, VS_OPCODE_WRITE, VS_WRAM_REG, 0x0002);
00499 while (i + 3 <= plg->vsplg_size) {
00500 reg = (uint_fast8_t)plg->vsplg_data[i++];
00501 cnt = plg->vsplg_data[i++];
00502
00503 if (cnt & 0x8000) {
00504 cnt &= 0x7FFF;
00505 while (cnt--) {
00506 VsCodecReg(dev, VS_OPCODE_WRITE, reg, plg->vsplg_data[i]);
00507 }
00508 i++;
00509 }
00510 else if (i + cnt <= plg->vsplg_size) {
00511 while (cnt--) {
00512 VsCodecReg(dev, VS_OPCODE_WRITE, reg, plg->vsplg_data[i]);
00513 i++;
00514 }
00515 }
00516 else {
00517 break;
00518 }
00519 }
00520 if (i != plg->vsplg_size) {
00521 return -1;
00522 }
00523
00524 #ifdef VS_SM_ADPCM
00525
00526
00527 VsCodecMode(dev, VS_SM_LINE_IN | VS_SM_ADPCM, VS_SM_LINE_IN | VS_SM_ADPCM);
00528 #endif
00529
00530 #if VS_HAS_AICTRL0_REG
00531
00532 VsCodecReg(dev, VS_OPCODE_WRITE, VS_AICTRL0_REG, 0);
00533 #endif
00534
00535
00536
00537
00538 #if VS_HAS_AICTRL1_REG
00539
00540 VsCodecReg(dev, VS_OPCODE_WRITE, VS_AICTRL1_REG, 1024);
00541 #endif
00542
00543 #if VS_HAS_AICTRL2_REG
00544
00545 VsCodecReg(dev, VS_OPCODE_WRITE, VS_AICTRL2_REG, 4096);
00546 #endif
00547
00548 #if VS_HAS_AICTRL3_REG
00549
00550 VsCodecReg(dev, VS_OPCODE_WRITE, VS_AICTRL3_REG, 0);
00551 #endif
00552
00553 return 0;
00554 }
00555
00577 int VsCodecIOCtl(NUTDEVICE * dev, int req, void *conf)
00578 {
00579 int rc = 0;
00580 uint32_t *lvp = (uint32_t *) conf;
00581 int *ivp = (int *) conf;
00582 VSDCB *dcb = (VSDCB *)dev->dev_dcb;
00583
00584 switch (req) {
00585 case AUDIO_PLAY:
00586 if (dcb->dcb_pbstat == CODEC_STATUS_IDLE) {
00587
00588 dcb->dcb_scmd |= VSREQ_PLAY;
00589 }
00590 NutEventPost(&dcb->dcb_feedme);
00591 break;
00592 case AUDIO_CANCEL:
00593 if (dcb->dcb_pbstat == CODEC_STATUS_PLAYING) {
00594
00595 dcb->dcb_scmd |= VSREQ_CANCEL;
00596 }
00597 NutEventPost(&dcb->dcb_feedme);
00598 break;
00599 case AUDIO_GET_STATUS:
00600 *ivp = dcb->dcb_pbstat;
00601 break;
00602 case AUDIO_GET_PLAYGAIN:
00603 *ivp = dcb->dcb_rvol > dcb->dcb_lvol ? dcb->dcb_rvol : dcb->dcb_lvol;
00604 break;
00605 case AUDIO_SET_PLAYGAIN:
00606 dcb->dcb_lvol = *ivp;
00607 dcb->dcb_rvol = *ivp;
00608 dcb->dcb_scmd |= VSREQ_VOLUPD;
00609 break;
00610 case AUDIO_SET_TREB:
00611 dcb->dcb_treb = *ivp;
00612 dcb->dcb_scmd |= VSREQ_AUDIOE;
00613 break;
00614 case AUDIO_SET_TFIN:
00615 dcb->dcb_tfin = *ivp;
00616 dcb->dcb_scmd |= VSREQ_AUDIOE;
00617 break;
00618 case AUDIO_SET_BASS:
00619 dcb->dcb_bass = *ivp;
00620 dcb->dcb_scmd |= VSREQ_AUDIOE;
00621 break;
00622 case AUDIO_SET_BFIN:
00623 dcb->dcb_bfin = *ivp;
00624 dcb->dcb_scmd |= VSREQ_AUDIOE;
00625 break;
00626 case AUDIO_GET_PBSIZE:
00627 *lvp = NutSegBufAvailable() + NutSegBufUsed();
00628 break;
00629 case AUDIO_SET_PBSIZE:
00630 rc = VsDecoderBufferInit(dev, *lvp);
00631 break;
00632 case AUDIO_GET_PBLEVEL:
00633 *lvp = NutSegBufUsed();
00634 break;
00635 case AUDIO_GET_PBWLOW:
00636 *lvp = dcb->dcb_pbwlo;
00637 break;
00638 case AUDIO_SET_PBWLOW:
00639 dcb->dcb_pbwlo = *lvp;
00640 break;
00641 case AUDIO_GET_PBWHIGH:
00642 *lvp = dcb->dcb_pbwhi;
00643 break;
00644 case AUDIO_SET_PBWHIGH:
00645 dcb->dcb_pbwhi = *lvp;
00646 break;
00647 case AUDIO_SETWRITETIMEOUT:
00648 dcb->dcb_wtmo = *lvp;
00649 break;
00650 case AUDIO_GETWRITETIMEOUT:
00651 *lvp = dcb->dcb_wtmo;
00652 break;
00653 case AUDIO_BEEP:
00654 if (dcb->dcb_pbstat == CODEC_STATUS_IDLE) {
00655 dcb->dcb_sinefreq = *((uint16_t *) conf);
00656 dcb->dcb_scmd |= VSREQ_BEEP;
00657 NutEventPost(&dcb->dcb_feedme);
00658 } else {
00659 rc = -1;
00660 }
00661 break;
00662 case AUDIO_GET_DECCAPS:
00663
00664 *lvp = dcb->dcb_dec_caps;
00665 break;
00666 case AUDIO_GET_CODCAPS:
00667
00668 *lvp = dcb->dcb_cod_caps;
00669 break;
00670 case AUDIO_GET_MIDCAPS:
00671
00672 *lvp = dcb->dcb_midi_caps;
00673 break;
00674
00675 #if 0
00676 case AUDIO_GET_DECINFO:
00677
00678 break;
00679 case AUDIO_GET_CODINFO:
00680
00681 break;
00682 case AUDIO_GET_MIDINFO:
00683
00684 break;
00685 #endif
00686 case AUDIO_PLUGIN_UPLOAD:
00687 rc = VsCodecLoadPlugIn(dev, (VS_PLUGIN_INFO *) conf);
00688 break;
00689
00690 default:
00691 rc = (*dcb->dcb_control)(req, conf);
00692 break;
00693 }
00694 return rc;
00695 }
00696
00709 static int VsDecoderBufferFlush(NUTDEVICE *dev, uint32_t tmo)
00710 {
00711 int rc = 0;
00712 VSDCB *dcb = dev->dev_dcb;
00713
00714 for (;;) {
00715
00716 if (NutSegBufUsed()) {
00717 VsCodecIOCtl(dev, AUDIO_PLAY, NULL);
00718 }
00719
00720 else if (dcb->dcb_pbstat == CODEC_STATUS_IDLE) {
00721
00722 break;
00723 }
00724
00725 rc = NutEventWait(&dcb->dcb_bufque, tmo);
00726 if (rc) {
00727 break;
00728 }
00729 }
00730 return rc;
00731 }
00732
00746 int VsCodecRead(NUTFILE * nfp, void *data, int len)
00747 {
00748 int rc = 0;
00749 uint8_t *bp;
00750 uint8_t *dp;
00751 size_t rbytes;
00752 NUTDEVICE *dev;
00753 VSDCB *dcb;
00754
00755 dev = nfp->nf_dev;
00756 dcb = dev->dev_dcb;
00757
00758
00759 if (data == NULL || len == 0) {
00760 return 0;
00761 }
00762 if (dcb->dcb_pbstat == CODEC_STATUS_PLAYING) {
00763
00764 return -1;
00765 } else if (dcb->dcb_pbstat == CODEC_STATUS_IDLE) {
00766
00767 if (dcb->dcb_cod_mode & AUDIO_FMT_VORBIS) {
00768 }
00769 dcb->dcb_scmd |= VSREQ_RECORD;
00770 NutEventPost(&dcb->dcb_feedme);
00771 }
00772 dp = data;
00773 while (len) {
00774
00775 bp = (uint8_t *) NutSegBufReadRequest(&rbytes);
00776 if (rbytes) {
00777 if (rbytes > len) {
00778 rbytes = len;
00779 }
00780 memcpy(dp, bp, rbytes);
00781 NutSegBufReadLast(rbytes);
00782 NutEventPost(&dcb->dcb_feedme);
00783 len -= rbytes;
00784 rc += rbytes;
00785 dp += rbytes;
00786 }
00787
00788 else if (NutEventWait(&dcb->dcb_bufque, dcb->dcb_rtmo)) {
00789
00790 break;
00791 }
00792 }
00793 return rc;
00794 }
00795
00809 int VsCodecWrite(NUTFILE * nfp, CONST void *data, int len)
00810 {
00811 int rc = 0;
00812 uint8_t *bp;
00813 CONST uint8_t *dp;
00814 size_t rbytes;
00815 VSDCB *dcb = nfp->nf_dev->dev_dcb;
00816
00817
00818 if (data == NULL || len == 0) {
00819 return VsDecoderBufferFlush(nfp->nf_dev, dcb->dcb_wtmo);
00820 }
00821 dp = data;
00822 while (len) {
00823 bp = (uint8_t *)NutSegBufWriteRequest(&rbytes);
00824 if (rbytes == 0) {
00825
00826 if (NutEventWait(&dcb->dcb_bufque, dcb->dcb_wtmo)) {
00827
00828 break;
00829 }
00830 } else {
00831 if (rbytes > len) {
00832 rbytes = len;
00833 }
00834 memcpy(bp, dp, rbytes);
00835 NutSegBufWriteLast(rbytes);
00836 NutEventPost(&dcb->dcb_feedme);
00837 len -= rbytes;
00838 rc += rbytes;
00839 dp += rbytes;
00840 }
00841 }
00842 return rc;
00843 }
00844
00845 #ifdef __HARVARD_ARCH__
00846
00868 int VsCodecWrite_P(NUTFILE * nfp, PGM_P buffer, int len)
00869 {
00870 return -1;
00871 }
00872 #endif
00873
00874
00875
00876
00877 NUTFILE *VsCodecOpen(NUTDEVICE * dev, CONST char *name, int mode, int acc)
00878 {
00879 NUTFILE *nfp;
00880 VSDCB *dcb;
00881
00882 #if defined(VS_SW_RESET_ON_OPEN)
00883 VsCodecMode(dev, VS_SM_RESET, VS_SM_RESET);
00884 #endif
00885
00886 dcb = dev->dev_dcb;
00887 if (mode & _O_WRONLY) {
00888 uint32_t on = 1;
00889
00890 if (VsCodecIOCtl(dev, AUDIO_IRQ_ENABLE, &on)) {
00891 return NULL;
00892 }
00893 } else {
00894
00895 if (strcmp(name, "vorbis") == 0) {
00896 dcb->dcb_cod_mode = AUDIO_FMT_VORBIS;
00897 } else {
00898 dcb->dcb_cod_mode = AUDIO_FMT_WAV_IMA_ADPCM;
00899 }
00900 }
00901
00902 nfp = malloc(sizeof(NUTFILE));
00903 if (nfp) {
00904 nfp->nf_next = NULL;
00905 nfp->nf_dev = dev;
00906 nfp->nf_fcb = NULL;
00907 }
00908 NutSegBufReset();
00909
00910 return nfp;
00911 }
00912
00913
00914
00915
00916 int VsCodecClose(NUTFILE * nfp)
00917 {
00918 VSDCB *dcb = nfp->nf_dev->dev_dcb;
00919
00920 int rc = VsDecoderBufferFlush(nfp->nf_dev, dcb->dcb_wtmo);
00921
00922 if (nfp) {
00923 free(nfp);
00924 }
00925 return rc;
00926 }
00927