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
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070 #include <sys/atom.h>
00071 #include <sys/event.h>
00072 #include <sys/timer.h>
00073 #include <sys/heap.h>
00074
00075 #include <cfg/arch/gpio.h>
00076 #include <cfg/audio.h>
00077 #include <dev/irqreg.h>
00078 #include <dev/vscodec.h>
00079
00080 #include <sys/bankmem.h>
00081
00082 #include <stdlib.h>
00083 #include <stddef.h>
00084 #include <string.h>
00085 #include <memdebug.h>
00086
00091
00092 #if !defined(AUDIO_VS1001K) && !defined(AUDIO_VS1011E) && !defined(AUDIO_VS1002D) && !defined(AUDIO_VS1003B) && !defined(AUDIO_VS1033C) && !defined(AUDIO_VS1053C)
00093 #define AUDIO_VS1001K
00094 #endif
00095
00096 #ifndef VS10XX_FREQ
00097
00098 #define VS10XX_FREQ 12288000UL
00099 #endif
00100
00101 #ifndef VS10XX_HWRST_DURATION
00102
00103 #define VS10XX_HWRST_DURATION 1
00104 #endif
00105
00106 #ifndef VS10XX_HWRST_RECOVER
00107
00108 #define VS10XX_HWRST_RECOVER 4
00109 #endif
00110
00111 #ifndef VS10XX_SWRST_RECOVER
00112
00113 #define VS10XX_SWRST_RECOVER 2
00114 #endif
00115
00116 #ifndef VS10XX_SCI_MODE
00117 #define VS10XX_SCI_MODE 0
00118 #endif
00119
00120 #ifndef VS10XX_SCI_RATE
00121 #define VS10XX_SCI_RATE (VS10XX_FREQ / 6)
00122 #endif
00123
00124 #ifndef VS10XX_SDI_MODE
00125 #define VS10XX_SDI_MODE 0
00126 #endif
00127
00128 #ifndef VS10XX_SDI_RATE
00129 #define VS10XX_SDI_RATE (VS10XX_FREQ / 6)
00130 #endif
00131
00132
00133
00134
00135
00136 #if defined (MCU_AT91R40008) || defined (MCU_AT91SAM7X) || defined (MCU_AT91SAM7SE512) || defined (MCU_AT91SAM9260)
00137
00138 #if defined(ELEKTOR_IR1)
00139
00140 #define VS_XRESET_BIT 31
00141 #define VS10XX_XCS_BIT PA31_SPI0_NPCS1_A
00142 #define VS10XX_XCS_PORT PIOA_ID
00143 #define VS10XX_XDCS_BIT PB30_SPI0_NPCS2_A
00144 #define VS10XX_XDCS_PORT PIOB_ID
00145 #define VS10XX_DREQ_BIT PA30_IRQ1_A
00146 #define VS10XX_DREQ_PIO_ID PIOA_ID
00147 #define VS10XX_SIGNAL sig_INTERRUPT1
00148
00149 #endif
00150
00151 #if defined(VS10XX_XCS_BIT)
00152
00153 #if !defined(VS10XX_XCS_PORT)
00154 #define VS10XX_XCS_PE_REG PIO_PER
00155 #define VS10XX_XCS_OE_REG PIO_OER
00156 #define VS10XX_XCS_COD_REG PIO_CODR
00157 #define VS10XX_XCS_SOD_REG PIO_SODR
00158 #elif VS10XX_XCS_PORT == PIOA_ID
00159 #define VS10XX_XCS_PE_REG PIOA_PER
00160 #define VS10XX_XCS_OE_REG PIOA_OER
00161 #define VS10XX_XCS_COD_REG PIOA_CODR
00162 #define VS10XX_XCS_SOD_REG PIOA_SODR
00163 #elif VS10XX_XCS_PORT == PIOB_ID
00164 #define VS10XX_XCS_PE_REG PIOB_PER
00165 #define VS10XX_XCS_OE_REG PIOB_OER
00166 #define VS10XX_XCS_COD_REG PIOB_CODR
00167 #define VS10XX_XCS_SOD_REG PIOB_SODR
00168 #elif VS10XX_XCS_PORT == PIOC_ID
00169 #define VS10XX_XCS_PE_REG PIOC_PER
00170 #define VS10XX_XCS_OE_REG PIOC_OER
00171 #define VS10XX_XCS_COD_REG PIOC_CODR
00172 #define VS10XX_XCS_SOD_REG PIOC_SODR
00173 #endif
00174 #define VS10XX_XCS_ENA() \
00175 outr(VS10XX_XCS_PE_REG, _BV(VS10XX_XCS_BIT)); \
00176 outr(VS10XX_XCS_OE_REG, _BV(VS10XX_XCS_BIT))
00177 #define VS10XX_XCS_CLR() outr(VS10XX_XCS_COD_REG, _BV(VS10XX_XCS_BIT))
00178 #define VS10XX_XCS_SET() outr(VS10XX_XCS_SOD_REG, _BV(VS10XX_XCS_BIT))
00179
00180 #else
00181
00182 #define VS10XX_XCS_ENA()
00183 #define VS10XX_XCS_CLR()
00184 #define VS10XX_XCS_SET()
00185
00186 #endif
00187
00188 #if defined(VS10XX_XDCS_BIT)
00189
00190 #if !defined(VS10XX_XDCS_PORT)
00191 #define VS10XX_XDCS_PE_REG PIO_PER
00192 #define VS10XX_XDCS_OE_REG PIO_OER
00193 #define VS10XX_XDCS_COD_REG PIO_CODR
00194 #define VS10XX_XDCS_SOD_REG PIO_SODR
00195 #elif VS10XX_XDCS_PORT == PIOA_ID
00196 #define VS10XX_XDCS_PE_REG PIOA_PER
00197 #define VS10XX_XDCS_OE_REG PIOA_OER
00198 #define VS10XX_XDCS_COD_REG PIOA_CODR
00199 #define VS10XX_XDCS_SOD_REG PIOA_SODR
00200 #elif VS10XX_XDCS_PORT == PIOB_ID
00201 #define VS10XX_XDCS_PE_REG PIOB_PER
00202 #define VS10XX_XDCS_OE_REG PIOB_OER
00203 #define VS10XX_XDCS_COD_REG PIOB_CODR
00204 #define VS10XX_XDCS_SOD_REG PIOB_SODR
00205 #elif VS10XX_XDCS_PORT == PIOC_ID
00206 #define VS10XX_XDCS_PE_REG PIOC_PER
00207 #define VS10XX_XDCS_OE_REG PIOC_OER
00208 #define VS10XX_XDCS_COD_REG PIOC_CODR
00209 #define VS10XX_XDCS_SOD_REG PIOC_SODR
00210 #endif
00211 #define VS10XX_XDCS_ENA() \
00212 outr(VS10XX_XDCS_PE_REG, _BV(VS10XX_XDCS_BIT)); \
00213 outr(VS10XX_XDCS_OE_REG, _BV(VS10XX_XDCS_BIT))
00214 #define VS10XX_XDCS_CLR() outr(VS10XX_XDCS_COD_REG, _BV(VS10XX_XDCS_BIT))
00215 #define VS10XX_XDCS_SET() outr(VS10XX_XDCS_SOD_REG, _BV(VS10XX_XDCS_BIT))
00216
00217 #else
00218
00219 #define VS10XX_XDCS_ENA()
00220 #define VS10XX_XDCS_CLR()
00221 #define VS10XX_XDCS_SET()
00222
00223 #endif
00224
00225 #if defined(VS10XX_DREQ_BIT)
00226
00227 #if !defined(VS10XX_DREQ_PIO_ID)
00228 #define VS10XX_DREQ_PD_REG PIO_PDR
00229 #define VS10XX_DREQ_OD_REG PIO_ODR
00230 #define VS10XX_DREQ_PDS_REG PIO_PDSR
00231 #elif VS10XX_DREQ_PIO_ID == PIOA_ID
00232 #define VS10XX_DREQ_PD_REG PIOA_PDR
00233 #define VS10XX_DREQ_OD_REG PIOA_ODR
00234 #define VS10XX_DREQ_PDS_REG PIOA_PDSR
00235 #elif VS10XX_DREQ_PIO_ID == PIOB_ID
00236 #define VS10XX_DREQ_PD_REG PIOB_PDR
00237 #define VS10XX_DREQ_OD_REG PIOB_ODR
00238 #define VS10XX_DREQ_PDS_REG PIOB_PDSR
00239 #elif VS10XX_DREQ_PIO_ID == PIOC_ID
00240 #define VS10XX_DREQ_PD_REG PIOC_PDR
00241 #define VS10XX_DREQ_OD_REG PIOC_ODR
00242 #define VS10XX_DREQ_PDS_REG PIOC_PDSR
00243 #endif
00244
00245 #define VS10XX_DREQ_ENA() \
00246 outr(VS10XX_DREQ_PD_REG, _BV(VS10XX_DREQ_BIT)); \
00247 outr(VS10XX_DREQ_OD_REG, _BV(VS10XX_DREQ_BIT))
00248 #define VS10XX_DREQ_TST() ((inr(VS10XX_DREQ_PDS_REG) & _BV(VS10XX_DREQ_BIT)) == _BV(VS10XX_DREQ_BIT))
00249
00250 #else
00251
00252 #define VS10XX_DREQ_ENA()
00253 #define VS10XX_DREQ_TST() 0
00254
00255 #endif
00256
00257
00258
00259
00260 #endif
00261
00262
00263 #define VSREQ_PLAY 0x00000001
00264 #define VSREQ_CANCEL 0x00000002
00265 #define VSREQ_BEEP 0x00000004
00266
00267 typedef struct _VSDCB {
00268 int dcb_pbstat;
00269 uint32_t dcb_scmd;
00270 int dcb_crvol;
00271 int dcb_srvol;
00272 int dcb_clvol;
00273 int dcb_slvol;
00274 int dcb_ctreb;
00275 int dcb_streb;
00276 int dcb_ctfin;
00277 int dcb_stfin;
00278 int dcb_cbass;
00279 int dcb_sbass;
00280 int dcb_cbfin;
00281 int dcb_sbfin;
00282 uint32_t dcb_pbwlo;
00283 uint32_t dcb_pbwhi;
00284 } VSDCB;
00285
00286 static VSDCB dcb;
00287 static unsigned int vs_chip;
00288
00289
00290
00291
00292
00293 static uint8_t SpiByte(uint8_t val)
00294 {
00295
00296 outr(SPI0_TDR, val);
00297
00298 while((inr(SPI0_SR) & SPI_RDRF) == 0);
00299
00300 val = (uint8_t)inr(SPI0_RDR);
00301
00302 return val;
00303 }
00304
00305 static void SciSelect(void)
00306 {
00307 outr(SPI0_CSR0, (24 << SPI_SCBR_LSB) | SPI_NCPHA);
00308 outr(SPI0_MR, SPI_MODFDIS | SPI_MSTR);
00309 outr(PIOA_CODR, _BV(VS10XX_XCS_BIT));
00310 }
00311
00312 static void SciDeselect(void)
00313 {
00314 outr(PIOA_SODR, _BV(VS10XX_XCS_BIT));
00315 }
00316
00323 static int VsWaitReady(void)
00324 {
00325 int tmo = 16384;
00326
00327 do {
00328 if (VS10XX_DREQ_TST()) {
00329 return 0;
00330 }
00331 } while (tmo--);
00332
00333 return -1;
00334 }
00335
00336
00337
00338
00339
00340
00341
00342 static int VsSdiWrite(CONST uint8_t * data, size_t len)
00343 {
00344 while (len--) {
00345 if (!VS10XX_DREQ_TST() && VsWaitReady()) {
00346 return -1;
00347 }
00348 SpiByte(*data);
00349 data++;
00350 }
00351 return 0;
00352 }
00353
00354
00355
00356
00357
00358
00359
00360
00361 static int VsSdiWrite_P(PGM_P data, size_t len)
00362 {
00363 while (len--) {
00364 if (!VS10XX_DREQ_TST() && VsWaitReady()) {
00365 return -1;
00366 }
00367 SpiByte(PRG_RDB(data));
00368 data++;
00369 }
00370 return 0;
00371 }
00372
00373
00374
00375
00376
00377
00378 static void VsRegWrite(ureg_t reg, uint16_t data)
00379 {
00380 VsWaitReady();
00381 SciSelect();
00382 SpiByte(VS_OPCODE_WRITE);
00383 SpiByte((uint8_t) reg);
00384 SpiByte((uint8_t) (data >> 8));
00385 SpiByte((uint8_t) data);
00386 SciDeselect();
00387 }
00388
00389
00390
00391
00392
00393
00394
00395
00396 static uint16_t VsRegRead(ureg_t reg)
00397 {
00398 uint16_t data;
00399
00400 VsWaitReady();
00401 SciSelect();
00402 SpiByte(VS_OPCODE_READ);
00403 SpiByte((uint8_t) reg);
00404 data = (uint16_t)SpiByte(0) << 8;
00405 data |= SpiByte(0);
00406 SciDeselect();
00407
00408 return data;
00409 }
00410
00421 static int VsBeep(uint8_t fsin, uint8_t ms)
00422 {
00423 static prog_char on[] = { 0x53, 0xEF, 0x6E };
00424 static prog_char off[] = { 0x45, 0x78, 0x69, 0x74 };
00425 static prog_char end[] = { 0x00, 0x00, 0x00, 0x00 };
00426
00427 VsRegWrite(VS_MODE_REG, VS_SM_TESTS | VS_SM_SDINEW);
00428
00429 fsin = 56 + (fsin & 7) * 9;
00430 VsSdiWrite_P(on, sizeof(on));
00431 VsSdiWrite(&fsin, 1);
00432 VsSdiWrite_P(end, sizeof(end));
00433 NutDelay(ms);
00434 VsSdiWrite_P(off, sizeof(off));
00435 VsSdiWrite_P(end, sizeof(end));
00436
00437 VsRegWrite(VS_MODE_REG, VS_SM_SDINEW);
00438
00439 return 0;
00440 }
00441
00442 static HANDLE vs_ready;
00443
00444 static void VsInterrupt(void *arg)
00445 {
00446 NutEventPostFromIrq(&vs_ready);
00447 }
00448
00449 THREAD(FeederThread, arg)
00450 {
00451 char *bp;
00452 size_t avail;
00453 int filled;
00454 uint8_t crgain;
00455 uint8_t srgain;
00456 uint8_t clgain;
00457 uint8_t slgain;
00458
00459 NutSleep(500);
00460
00461 dcb.dcb_slvol = dcb.dcb_clvol = -12;
00462 dcb.dcb_srvol = dcb.dcb_crvol = -12;
00463 srgain = (uint8_t)(-2 * dcb.dcb_srvol);
00464 crgain = 254;
00465 slgain = (uint8_t)(-2 * dcb.dcb_slvol);
00466 clgain = 254;
00467 VsRegWrite(VS_VOL_REG, ((uint16_t)clgain << VS_VOL_LEFT_LSB) | ((uint16_t)crgain << VS_VOL_RIGHT_LSB));
00468
00469
00470 while (NutRegisterIrqHandler(&VS10XX_SIGNAL, VsInterrupt, NULL)) {
00471 NutSleep(1000);
00472 }
00473
00474
00475 NutIrqSetMode(&VS10XX_SIGNAL, NUT_IRQMODE_RISINGEDGE);
00476
00477 VS10XX_DREQ_ENA();
00478 NutIrqEnable(&VS10XX_SIGNAL);
00479
00480 for (;;) {
00481 NutEventWait(&vs_ready, 100);
00482 if (!VS10XX_DREQ_TST()) {
00483 continue;
00484 }
00485 if (dcb.dcb_scmd) {
00486 if (dcb.dcb_scmd & VSREQ_CANCEL) {
00487 NutSegBufReset();
00488 }
00489 if (dcb.dcb_scmd & VSREQ_BEEP) {
00490 VsBeep(2, 100);
00491 }
00492 dcb.dcb_scmd &= VSREQ_PLAY;
00493 }
00494 if (NutSegBufUsed() < dcb.dcb_pbwlo) {
00495 dcb.dcb_pbstat = CODEC_STATUS_IDLE;
00496 if (crgain != 254) {
00497 clgain = crgain = 254;
00498 VsRegWrite(VS_VOL_REG, ((uint16_t)clgain << VS_VOL_LEFT_LSB) | ((uint16_t)crgain << VS_VOL_RIGHT_LSB));
00499 }
00500 while (NutSegBufUsed() < dcb.dcb_pbwhi) {
00501 if (dcb.dcb_scmd) {
00502 if (dcb.dcb_scmd & VSREQ_PLAY) {
00503 dcb.dcb_pbwhi = dcb.dcb_pbwlo = NutSegBufUsed() / 2;
00504 }
00505 break;
00506 }
00507 NutSleep(100);
00508 }
00509 }
00510 dcb.dcb_scmd &= ~VSREQ_PLAY;
00511 if (dcb.dcb_scmd) {
00512 continue;
00513 }
00514
00515 outr(SPI0_CSR0, (12 << SPI_SCBR_LSB) | SPI_NCPHA);
00516 outr(SPI0_MR, SPI_MODFDIS | SPI_MSTR);
00517 if (dcb.dcb_pbstat != CODEC_STATUS_PLAYING) {
00518 outr(PIOB_CODR, _BV(30));
00519 while (!VS10XX_DREQ_TST()) {
00520 SpiByte(0);
00521 }
00522 outr(PIOB_SODR, _BV(30));
00523 }
00524
00525 for (;;) {
00526 if (!VS10XX_DREQ_TST()) {
00527 break;
00528 }
00529 bp = NutSegBufReadRequest(&avail);
00530 if (avail == 0) {
00531 dcb.dcb_pbstat = CODEC_STATUS_IDLE;
00532 if (crgain != 254) {
00533 clgain = crgain = 254;
00534 VsRegWrite(VS_VOL_REG, ((uint16_t)clgain << VS_VOL_LEFT_LSB) | ((uint16_t)crgain << VS_VOL_RIGHT_LSB));
00535 }
00536 break;
00537 }
00538 outr(PIOB_CODR, _BV(30));
00539 for (filled = 0; avail--; filled++, bp++) {
00540 if (!VS10XX_DREQ_TST()) {
00541 dcb.dcb_pbstat = CODEC_STATUS_PLAYING;
00542 break;
00543 }
00544 SpiByte(*bp);
00545 }
00546 outr(PIOB_SODR, _BV(30));
00547 NutSegBufReadLast(filled);
00548 }
00549 if (dcb.dcb_clvol != dcb.dcb_slvol || dcb.dcb_crvol != dcb.dcb_srvol) {
00550 srgain = (uint8_t)(-2 * dcb.dcb_srvol);
00551 slgain = (uint8_t)(-2 * dcb.dcb_slvol);
00552
00553 dcb.dcb_clvol = dcb.dcb_slvol;
00554 dcb.dcb_crvol = dcb.dcb_srvol;
00555 }
00556 else if (srgain != crgain || slgain != clgain) {
00557 int diff = (int)srgain - (int)crgain;
00558
00559 if (diff > 4) {
00560 diff = 4;
00561 }
00562 else if (diff < -4) {
00563 diff = -4;
00564 }
00565 crgain = (uint8_t)((int)crgain + diff);
00566
00567 diff = (int)slgain - (int)clgain;
00568 if (diff > 4) {
00569 diff = 4;
00570 }
00571 else if (diff < -4) {
00572 diff = -4;
00573 }
00574 clgain = (uint8_t)((int)clgain + diff);
00575 VsRegWrite(VS_VOL_REG, ((uint16_t)clgain << VS_VOL_LEFT_LSB) | ((uint16_t)crgain << VS_VOL_RIGHT_LSB));
00576 }
00577 }
00578 }
00579
00580 static int VsPlayerFlush(void)
00581 {
00582 int tmo = 1000;
00583
00584
00585 while(dcb.dcb_pbstat == CODEC_STATUS_PLAYING) {
00586 NutSleep(1);
00587 if (tmo-- <= 0) {
00588 return -1;
00589 }
00590 }
00591 return 0;
00592 }
00593
00602 static int VsWrite(NUTFILE * fp, CONST void *data, int len)
00603 {
00604 char *buf;
00605 size_t rbytes;
00606
00607
00608 if (data == NULL || len == 0) {
00609 return VsPlayerFlush();
00610 }
00611 if (len) {
00612 buf = NutSegBufWriteRequest(&rbytes);
00613 if (len > rbytes) {
00614 len = rbytes;
00615 }
00616 if (len) {
00617 memcpy(buf, data, len);
00618 }
00619 NutSegBufWriteLast(len);
00620 }
00621 return len;
00622 }
00623
00624 #ifdef __HARVARD_ARCH__
00625
00647 static int VsWrite_P(NUTFILE * nfp, PGM_P buffer, int len)
00648 {
00649 return -1;
00650 }
00651 #endif
00652
00658 static NUTFILE *VsOpen(NUTDEVICE * dev, CONST char *name, int mode, int acc)
00659 {
00660 NUTFILE *nfp;
00661
00662 VsRegWrite(VS_MODE_REG, VS_SM_RESET | VS_SM_SDINEW);
00663 NutSleep(2);
00664
00665 nfp = malloc(sizeof(NUTFILE));
00666 nfp->nf_next = NULL;
00667 nfp->nf_dev = dev;
00668 nfp->nf_fcb = NULL;
00669
00670 NutSegBufReset();
00671
00672 return nfp;
00673 }
00674
00678 static int VsClose(NUTFILE * nfp)
00679 {
00680 int rc = VsPlayerFlush();
00681
00682 if (nfp) {
00683 free(nfp);
00684 }
00685 return rc;
00686 }
00687
00688 static int VsPlayBufferInit(uint32_t size)
00689 {
00690 if (dcb.dcb_pbstat != CODEC_STATUS_IDLE) {
00691 return -1;
00692 }
00693 if (NutSegBufInit((size_t)size) == NULL) {
00694 return -1;
00695 }
00696 dcb.dcb_pbwlo = NutSegBufAvailable() / 3;
00697 dcb.dcb_pbwhi = dcb.dcb_pbwlo * 2;
00698
00699 return 0;
00700 }
00701
00729 static int VsIOCtl(NUTDEVICE * dev, int req, void *conf)
00730 {
00731 int rc = 0;
00732 uint32_t *lvp = (uint32_t *) conf;
00733 int *ivp = (int *) conf;
00734 int iv = *ivp;
00735
00736 switch (req) {
00737 case AUDIO_PLAY:
00738
00739 if (dcb.dcb_pbstat != CODEC_STATUS_PLAYING) {
00740 dcb.dcb_scmd |= VSREQ_PLAY;
00741 }
00742 break;
00743 case AUDIO_CANCEL:
00744
00745 if (dcb.dcb_pbstat == CODEC_STATUS_PLAYING) {
00746 dcb.dcb_scmd |= VSREQ_CANCEL;
00747 }
00748 break;
00749 case AUDIO_GET_STATUS:
00750 *ivp = dcb.dcb_pbstat;
00751 break;
00752 case AUDIO_GET_PLAYGAIN:
00753 if (dcb.dcb_crvol >= dcb.dcb_clvol) {
00754 *ivp = dcb.dcb_crvol;
00755 }
00756 else {
00757 *ivp = dcb.dcb_clvol;
00758 }
00759 break;
00760 case AUDIO_SET_PLAYGAIN:
00761 if (iv > AUDIO_DAC_MAX_GAIN) {
00762 iv = AUDIO_DAC_MAX_GAIN;
00763 }
00764 if (iv < AUDIO_DAC_MIN_GAIN) {
00765 iv = AUDIO_DAC_MIN_GAIN;
00766 }
00767 dcb.dcb_slvol = dcb.dcb_srvol = iv;
00768 break;
00769 case AUDIO_GET_TREB:
00770 *lvp = dcb.dcb_ctreb;
00771 break;
00772 case AUDIO_SET_TREB:
00773 if( iv > AUDIO_DAC_MAX_TREB) {
00774 iv = AUDIO_DAC_MAX_TREB;
00775 }
00776 dcb.dcb_streb = iv;
00777 break;
00778 case AUDIO_GET_TFIN:
00779 *lvp = dcb.dcb_ctfin;
00780 break;
00781 case AUDIO_SET_TFIN:
00782 if( iv > AUDIO_DAC_MAX_TFIN) {
00783 iv = AUDIO_DAC_MAX_TFIN;
00784 }
00785 dcb.dcb_stfin = iv;
00786 break;
00787 case AUDIO_GET_BASS:
00788 *lvp = dcb.dcb_cbass;
00789 break;
00790 case AUDIO_SET_BASS:
00791 if( iv > AUDIO_DAC_MAX_BASS) {
00792 iv = AUDIO_DAC_MAX_BASS;
00793 }
00794 dcb.dcb_sbass = iv;
00795 case AUDIO_GET_BFIN:
00796 *lvp = dcb.dcb_cbass;
00797 break;
00798 case AUDIO_SET_BFIN:
00799 if( iv > AUDIO_DAC_MAX_BFIN) {
00800 iv = AUDIO_DAC_MAX_BFIN;
00801 }
00802 dcb.dcb_sbass = iv;
00803 case AUDIO_GET_PBSIZE:
00804 *lvp = NutSegBufAvailable() + NutSegBufUsed();
00805 break;
00806 case AUDIO_SET_PBSIZE:
00807 rc = VsPlayBufferInit(*lvp);
00808 break;
00809 case AUDIO_GET_PBLEVEL:
00810 *lvp = NutSegBufUsed();
00811 break;
00812 case AUDIO_GET_PBWLOW:
00813 *lvp = dcb.dcb_pbwlo;
00814 break;
00815 case AUDIO_SET_PBWLOW:
00816 dcb.dcb_pbwlo = *lvp;
00817 break;
00818 case AUDIO_GET_PBWHIGH:
00819 *lvp = dcb.dcb_pbwhi;
00820 break;
00821 case AUDIO_SET_PBWHIGH:
00822 dcb.dcb_pbwhi = *lvp;
00823 break;
00824 case AUDIO_BEEP:
00825 dcb.dcb_scmd |= VSREQ_BEEP;
00826 break;
00827 #if 0
00828 case AUDIO_GET_DECINFO:
00829
00830 break;
00831 case AUDIO_GET_DECCAPS:
00832
00833 break;
00834 case AUDIO_GET_DECFMTS:
00835
00836 break;
00837 case AUDIO_SET_DECFMTS:
00838
00839 break;
00840 case AUDIO_GET_CODINFO:
00841
00842 break;
00843 case AUDIO_GET_CODCAPS:
00844
00845 break;
00846 case AUDIO_GET_CODFMTS:
00847
00848 break;
00849 case AUDIO_SET_CODFMTS:
00850
00851 break;
00852 case AUDIO_GET_MIDINFO:
00853
00854 break;
00855 case AUDIO_GET_MIDCAPS:
00856
00857 break;
00858 #endif
00859 default:
00860 rc = -1;
00861 break;
00862 }
00863 return rc;
00864 }
00865
00866
00867
00868
00869 static int VsInit(NUTDEVICE * dev)
00870 {
00871 uint16_t mode;
00872
00873
00874 outr(PIOB_PER, _BV(VS_XRESET_BIT));
00875 outr(PIOB_SODR, _BV(VS_XRESET_BIT));
00876 outr(PIOB_OER, _BV(VS_XRESET_BIT));
00877 NutSleep(3);
00878
00879 VsRegRead(VS_MODE_REG);
00880 mode = VsRegRead(VS_MODE_REG);
00881 if ((mode & VS_SM_SDINEW) == 0) {
00882 VsRegWrite(VS_MODE_REG, VS_SM_RESET | VS_SM_SDINEW);
00883 NutSleep(2);
00884 }
00885 vs_chip = (VsRegRead(VS_STATUS_REG) & VS_SS_VER) >> VS_SS_VER_LSB;
00886 #if VS10XX_FREQ < 20000000UL && defined(VS_CF_DOUBLER)
00887 VsRegWrite(VS_CLOCKF_REG, (uint16_t)(VS_CF_DOUBLER | (VS10XX_FREQ / 2000UL)));
00888 #else
00889 VsRegWrite(VS_CLOCKF_REG, (uint16_t)(VS10XX_FREQ / 2000UL));
00890 #endif
00891 #if defined(VS_INT_FCTLH_REG)
00892 if (vs_chip == 0) {
00893
00894 VsRegWrite(VS_INT_FCTLH_REG, 0x8008);
00895 }
00896 #endif
00897
00898 if (VsPlayBufferInit(0)) {
00899 return -1;
00900 }
00901 if (NutThreadCreate("vsdeco", FeederThread, NULL, 1024) == 0) {
00902 return -1;
00903 }
00904 return 0;
00905 }
00906
00917 NUTDEVICE devVsCodec = {
00918 0,
00919 {'a', 'u', 'd', 'i', 'o', '0', 0, 0, 0},
00920 IFTYP_CHAR,
00921 0,
00922 0,
00923 0,
00924 &dcb,
00925 VsInit,
00926 VsIOCtl,
00927 NULL,
00928 VsWrite,
00929 #ifdef __HARVARD_ARCH__
00930 VsWrite_P,
00931 #endif
00932 VsOpen,
00933 VsClose,
00934 NULL
00935 };
00936