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