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/gpio.h>
00041 #include <dev/irqreg.h>
00042 #include <dev/vscodec.h>
00043 #include <dev/spibus.h>
00044
00045 #include <sys/event.h>
00046 #include <sys/timer.h>
00047 #include <sys/heap.h>
00048 #include <sys/nutdebug.h>
00049 #include <sys/bankmem.h>
00050
00051 #include <stdlib.h>
00052 #include <string.h>
00053
00054 #if defined(VSCODEC0_SIGNAL_IRQ) && defined(VSCODEC0_DREQ_BIT) && defined(VSCODEC0_XCS_BIT)
00055 #define VSCODEC0_CONFIGURED 1
00056 #endif
00057
00058 #if VSCODEC0_CONFIGURED
00059
00060 #ifndef VSCODEC0_DREQ_PORT
00061 #define VSCODEC0_DREQ_PORT 0
00062 #endif
00063 #ifndef VSCODEC0_XCS_PORT
00064 #define VSCODEC0_XCS_PORT 0
00065 #endif
00066
00071
00072 #ifndef NUT_THREAD_VSCODEC0STACK
00073 #if defined(__AVR__)
00074 #if defined(__GNUC__)
00075
00076 #define NUT_THREAD_VSCODEC0STACK 128
00077 #else
00078
00079 #define NUT_THREAD_VSCODEC0STACK 384
00080 #endif
00081 #else
00082
00083 #define NUT_THREAD_VSCODEC0STACK 192
00084 #endif
00085 #endif
00086
00087 #ifndef VSCODEC0_HWRST_DURATION
00088
00089 #define VSCODEC0_HWRST_DURATION 1
00090 #endif
00091
00092 #ifndef VSCODEC0_FREQ
00093
00094 #define VSCODEC0_FREQ 12288000UL
00095 #endif
00096
00097 #ifndef VSCODEC0_SPI_RATE
00098
00099 #define VSCODEC0_SPI_RATE (VSCODEC0_FREQ / 8)
00100 #endif
00101
00102 #ifndef VSCODEC0_SPI_MODE
00103
00104 #define VSCODEC0_SPI_MODE SPI_MODE_0
00105 #endif
00106
00107 #ifndef VSCODEC0_SPIBUS_WAIT
00108
00109 #define VSCODEC0_SPIBUS_WAIT NUT_WAIT_INFINITE
00110 #endif
00111
00112 #ifndef VSCODEC0_MAX_OUTPUT_BUFSIZ
00113
00114 #define VSCODEC0_MAX_OUTPUT_BUFSIZ 16384
00115 #endif
00116
00117
00118
00119
00120 #if (VSCODEC0_SIGNAL_IRQ == NUTGPIO_EXTINT0)
00121 #define VSCODEC0_DREQ_SIGNAL sig_INTERRUPT0
00122 #elif (VSCODEC0_SIGNAL_IRQ == NUTGPIO_EXTINT1)
00123 #define VSCODEC0_DREQ_SIGNAL sig_INTERRUPT1
00124 #elif (VSCODEC0_SIGNAL_IRQ == NUTGPIO_EXTINT2)
00125 #define VSCODEC0_DREQ_SIGNAL sig_INTERRUPT2
00126 #elif (VSCODEC0_SIGNAL_IRQ == NUTGPIO_EXTINT3)
00127 #define VSCODEC0_DREQ_SIGNAL sig_INTERRUPT3
00128 #elif (VSCODEC0_SIGNAL_IRQ == NUTGPIO_EXTINT4)
00129 #define VSCODEC0_DREQ_SIGNAL sig_INTERRUPT4
00130 #elif (VSCODEC0_SIGNAL_IRQ == NUTGPIO_EXTINT5)
00131 #define VSCODEC0_DREQ_SIGNAL sig_INTERRUPT5
00132 #elif (VSCODEC0_SIGNAL_IRQ == NUTGPIO_EXTINT6)
00133 #define VSCODEC0_DREQ_SIGNAL sig_INTERRUPT6
00134 #elif (VSCODEC0_SIGNAL_IRQ == NUTGPIO_EXTINT7)
00135 #define VSCODEC0_DREQ_SIGNAL sig_INTERRUPT7
00136 #endif
00137
00141 static NUTSPINODE nodeSpiVsCodec0 = {
00142 NULL,
00143 NULL,
00144 VSCODEC0_SPI_RATE,
00145 VSCODEC0_SPI_MODE,
00146 8,
00147 0
00148 };
00149
00150 static VSDCB dcbVsCodec0;
00151
00152
00153
00154
00155
00156
00157 static void VsCodec0Interrupt(void *arg)
00158 {
00159 NutEventPostFromIrq((void **)arg);
00160 }
00161
00167 static int VsCodec0IsReady(void)
00168 {
00169 return GpioPinGet(VSCODEC0_DREQ_PORT, VSCODEC0_DREQ_BIT) != 0;
00170 }
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182 static int VsCodec0SendCmd(void *cmd, size_t len)
00183 {
00184 int rc;
00185
00186
00187 rc = (*nodeSpiVsCodec0.node_bus->bus_alloc) (&nodeSpiVsCodec0, VSCODEC0_SPIBUS_WAIT);
00188 if (rc == 0) {
00189
00190 #if defined(VSCODEC0_VSCS_PORT) && defined(VSCODEC0_VSCS_BIT)
00191 GpioPinSetLow(VSCODEC0_VSCS_PORT, VSCODEC0_VSCS_BIT);
00192 #endif
00193 GpioPinSetLow(VSCODEC0_XCS_PORT, VSCODEC0_XCS_BIT);
00194
00195 rc = (*nodeSpiVsCodec0.node_bus->bus_transfer) (&nodeSpiVsCodec0, cmd, cmd, len);
00196
00197 GpioPinSetHigh(VSCODEC0_XCS_PORT, VSCODEC0_XCS_BIT);
00198 #if defined(VSCODEC0_VSCS_PORT) && defined(VSCODEC0_VSCS_BIT)
00199 GpioPinSetHigh(VSCODEC0_VSCS_PORT, VSCODEC0_VSCS_BIT);
00200 #endif
00201
00202 (*nodeSpiVsCodec0.node_bus->bus_release) (&nodeSpiVsCodec0);
00203 }
00204 return rc;
00205 }
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222 static int VsCodec0SendData(CONST uint8_t *buf, size_t len)
00223 {
00224 int rc = 0;
00225 CONST uint8_t *bp;
00226 size_t chunk;
00227
00228
00229 if ((*nodeSpiVsCodec0.node_bus->bus_alloc) (&nodeSpiVsCodec0, VSCODEC0_SPIBUS_WAIT) == 0) {
00230 #if defined(VSCODEC0_VSCS_PORT) && defined(VSCODEC0_VSCS_BIT)
00231
00232 GpioPinSetLow(VSCODEC0_VSCS_PORT, VSCODEC0_VSCS_BIT);
00233 #endif
00234 #if defined(VSCODEC0_XDCS_PORT) && defined(VSCODEC0_XDCS_BIT)
00235
00236 GpioPinSetLow(VSCODEC0_XDCS_PORT, VSCODEC0_XDCS_BIT);
00237 #endif
00238
00239
00240 bp = buf ? buf : zero_chunk;
00241
00242 while (len) {
00243
00244 chunk = len > VSCODEC_DATA_CHUNK_SIZE ? VSCODEC_DATA_CHUNK_SIZE : len;
00245
00246 if ((*nodeSpiVsCodec0.node_bus->bus_transfer) (&nodeSpiVsCodec0, bp, NULL, chunk)) {
00247 break;
00248 }
00249
00250 rc += chunk;
00251
00252 if (!VsCodec0IsReady()) {
00253 break;
00254 }
00255
00256 len -= chunk;
00257 if (buf) {
00258 bp += chunk;
00259 }
00260 }
00261 #if defined(VSCODEC0_XDCS_PORT) && defined(VSCODEC0_XDCS_BIT)
00262
00263 GpioPinSetHigh(VSCODEC0_XDCS_PORT, VSCODEC0_XDCS_BIT);
00264 #endif
00265 #if defined(VSCODEC0_VSCS_PORT) && defined(VSCODEC0_VSCS_BIT)
00266
00267 GpioPinSetHigh(VSCODEC0_VSCS_PORT, VSCODEC0_VSCS_BIT);
00268 #endif
00269
00270 (*nodeSpiVsCodec0.node_bus->bus_release) (&nodeSpiVsCodec0);
00271 }
00272 return rc;
00273 }
00274
00282 static int VsCodec0Control(int req, void *conf)
00283 {
00284 int rc = 0;
00285 uint32_t *lvp = (uint32_t *) conf;
00286
00287 switch (req) {
00288 case AUDIO_SET_DECFMTS:
00289
00290 #if defined(VS_SM_LAYER12)
00291 if (*lvp & (AUDIO_FMT_MPEG1_L1 | AUDIO_FMT_MPEG1_L2)) {
00292 VsCodecMode(&devSpiVsCodec0, VS_SM_LAYER12, VS_SM_LAYER12);
00293 } else {
00294 VsCodecMode(&devSpiVsCodec0, 0, VS_SM_LAYER12);
00295 }
00296 #endif
00297 break;
00298 case AUDIO_GET_DECFMTS:
00299
00300 *lvp = VS_DECODER_CAPS;
00301 #if defined(VS_SM_LAYER12)
00302 {
00303 uint16_t mode = VsCodecMode(&devSpiVsCodec0, 0, 0);
00304
00305 if ((mode & VS_SM_LAYER12) == 0) {
00306 *lvp &= ~(AUDIO_FMT_MPEG1_L1 | AUDIO_FMT_MPEG1_L2);
00307 }
00308 }
00309 #endif
00310 break;
00311 case AUDIO_GET_CODFMTS:
00312
00313 *lvp = VS_ENCODER_CAPS;
00314 #if defined(VS_SM_ADPCM)
00315 {
00316 uint16_t mode = VsCodecMode(&devSpiVsCodec0, 0, 0);
00317
00318 if ((mode & VS_SM_ADPCM) == 0) {
00319 *lvp &= ~(AUDIO_FMT_WAV_ADPCM | AUDIO_FMT_WAV_IMA_ADPCM);
00320 }
00321 }
00322 #endif
00323 break;
00324 case AUDIO_SET_CODFMTS:
00325
00326 if (*lvp & AUDIO_FMT_VORBIS) {
00327 }
00328 break;
00329 case AUDIO_IRQ_ENABLE:
00330 if (*lvp) {
00331 NutIrqEnable(&VSCODEC0_DREQ_SIGNAL);
00332 } else {
00333 NutIrqDisable(&VSCODEC0_DREQ_SIGNAL);
00334 }
00335 break;
00336 default:
00337 rc = -1;
00338 break;
00339 }
00340 return rc;
00341 }
00342
00355 static int VsCodec0SetClock(uint32_t xtal, uint_fast8_t dreq)
00356 {
00357 int rc = 0;
00358
00359 #if VS_HAS_SC_X3FREQ
00360
00361 if (dreq) {
00362
00363 VsCodecWaitReady(&devSpiVsCodec0, VSCODEC_CMD_TIMEOUT);
00364 }
00365 {
00366 uint8_t cmd[4] = { VS_OPCODE_WRITE, VS_CLOCKF_REG, 0, 0 };
00367 uint16_t freq = (uint16_t)((xtal - 8000000UL) / 4000UL);
00368
00369 freq |= (VS_SC_MULT_3_5 | VS_SC_ADD_1_0);
00370 cmd[2] = (uint8_t) (freq >> 8);
00371 cmd[3] = (uint8_t) freq;
00372 rc = VsCodec0SendCmd(cmd, 4);
00373 }
00374 #else
00375
00376 if (xtal < 20000000UL) {
00377 VsCodecReg(&devSpiVsCodec0, VS_OPCODE_WRITE, VS_CLOCKF_REG, (uint16_t)(VS_CF_DOUBLER | (xtal / 2000UL)));
00378 } else {
00379 VsCodecReg(&devSpiVsCodec0, VS_OPCODE_WRITE, VS_CLOCKF_REG, (uint16_t)(xtal / 2000UL));
00380 }
00381 #endif
00382
00383
00384 #if defined(AUDIO0_VS1001K)
00385 VsCodecReg(&devSpiVsCodec0, VS_OPCODE_WRITE, VS_INT_FCTLH_REG, 0x8008);
00386 #elif defined(AUDIO0_VSAUTO) && defined(VS_INT_FCTLH_REG)
00387 if (dcbVsCodec0.dcb_codec_ver == 1001) {
00388 VsCodecReg(&devSpiVsCodec0, VS_OPCODE_WRITE, VS_INT_FCTLH_REG, 0x8008);
00389 }
00390 #endif
00391
00392
00393 if (rc == 0) {
00394 #if VS_HAS_SC_X3FREQ
00395 (*nodeSpiVsCodec0.node_bus->bus_set_rate) (&nodeSpiVsCodec0, xtal / 2);
00396 #endif
00397 }
00398 return rc;
00399 }
00400
00412 static int VsCodec0Detect(void)
00413 {
00414 int rc = -1;
00415 uint_fast16_t status;
00416
00417
00418
00419
00420 status = VsCodecReg(&devSpiVsCodec0, VS_OPCODE_READ, VS_STATUS_REG, 0);
00421 #if defined(AUDIO0_VS1001K)
00422 if ((status & VS_SS_VER) == (VS1001_SS_VER << VS_SS_VER_LSB)) {
00423 dcbVsCodec0.dcb_codec_ver = 1001;
00424 dcbVsCodec0.dcb_codec_rev = 'K';
00425 rc = 0;
00426 }
00427 #elif defined(AUDIO0_VS1011E)
00428 if ((status & VS_SS_VER) == (VS1011E_SS_VER << VS_SS_VER_LSB)) {
00429 dcbVsCodec0.dcb_codec_ver = 1011;
00430 dcbVsCodec0.dcb_codec_rev = 'E';
00431 rc = 0;
00432 }
00433 #elif defined(AUDIO0_VS1002D)
00434 if ((status & VS_SS_VER) == (VS1002_SS_VER << VS_SS_VER_LSB)) {
00435 dcbVsCodec0.dcb_codec_ver = 1002;
00436 dcbVsCodec0.dcb_codec_rev = 'D';
00437 rc = 0;
00438 }
00439 #elif defined(AUDIO0_VS1003B)
00440 if ((status & VS_SS_VER) == (VS1003_SS_VER << VS_SS_VER_LSB)) {
00441 dcbVsCodec0.dcb_codec_ver = 1003;
00442 dcbVsCodec0.dcb_codec_rev = 'B';
00443 rc = 0;
00444 }
00445 #elif defined(AUDIO0_VS1033C)
00446 if ((status & VS_SS_VER) == (VS1033_SS_VER << VS_SS_VER_LSB)) {
00447 dcbVsCodec0.dcb_codec_ver = 1033;
00448 dcbVsCodec0.dcb_codec_rev = 'C';
00449 rc = 0;
00450 }
00451 #elif defined(AUDIO0_VS1053B)
00452 if ((status & VS_SS_VER) == (VS1053_SS_VER << VS_SS_VER_LSB)) {
00453 dcbVsCodec0.dcb_codec_ver = 1053;
00454 dcbVsCodec0.dcb_codec_rev = 'B';
00455 rc = 0;
00456 }
00457 #else
00458
00459
00460
00461 rc = 0;
00462 switch ((status & VS_SS_VER) >> VS_SS_VER_LSB) {
00463 case VS1001_SS_VER:
00464 dcbVsCodec0.dcb_codec_ver = 1001;
00465 break;
00466 case VS1011_SS_VER:
00467 dcbVsCodec0.dcb_codec_ver = 1011;
00468 break;
00469 case VS1002_SS_VER:
00470 if (VsCodecReg(&devSpiVsCodec0, VS_OPCODE_READ, VS_MODE_REG, 0) & VS_SM_SDINEW) {
00471 dcbVsCodec0.dcb_codec_ver = 1002;
00472 } else {
00473 dcbVsCodec0.dcb_codec_ver = 1011;
00474 dcbVsCodec0.dcb_codec_rev = 'E';
00475 }
00476 break;
00477 case VS1003_SS_VER:
00478 dcbVsCodec0.dcb_codec_ver = 1003;
00479 break;
00480 case VS1053_SS_VER:
00481 dcbVsCodec0.dcb_codec_ver = 1053;
00482 break;
00483 case VS1033_SS_VER:
00484 dcbVsCodec0.dcb_codec_ver = 1033;
00485 break;
00486 case VS1103_SS_VER:
00487 dcbVsCodec0.dcb_codec_ver = 1103;
00488 break;
00489 default:
00490 rc = -1;
00491 break;
00492 }
00493 #endif
00494 return rc;
00495 }
00496
00508 static int VsCodec0ResetHardware(int on)
00509 {
00510 if (on) {
00511
00512
00513
00514 #if defined(VSCODEC0_XRESET_PORT) && defined(VSCODEC0_XRESET_BIT)
00515
00516 GpioPinSetLow(VSCODEC0_XRESET_PORT, VSCODEC0_XRESET_BIT);
00517 GpioPinConfigSet(VSCODEC0_XRESET_PORT, VSCODEC0_XRESET_BIT, GPIO_CFG_OUTPUT);
00518 NutSleep(VSCODEC0_HWRST_DURATION);
00519 #else
00520 return -1;
00521 #endif
00522 } else {
00523
00524
00525
00526 uint_fast8_t clkset = 0;
00527
00528 #if defined(VSCODEC0_XRESET_PORT) && defined(VSCODEC0_XRESET_BIT)
00529
00530 GpioPinSetHigh(VSCODEC0_XRESET_PORT, VSCODEC0_XRESET_BIT);
00531 #if VSCODEC0_FREQ >= 24000000UL
00532
00533
00534 csrc = VsCodec0SetClock(VSCODEC0_FREQ, 0) == 0;
00535 #endif
00536 #endif
00537
00538 #if VSCODEC0_HWRST_RECOVER
00539
00540 NutSleep(VSCODEC0_HWRST_RECOVER);
00541 #endif
00542
00543 if (VsCodec0Detect()) {
00544 return -1;
00545 }
00546 #if !defined(AUDIO0_VS1001K)
00547 if (dcbVsCodec0.dcb_codec_ver != 1001) {
00548 #if VS_HAS_SM_SDINEW
00549 #if defined(VSCODEC0_XDCS_PORT) && defined(VSCODEC0_XDCS_BIT)
00550 VsCodecMode(&devSpiVsCodec0, VS_SM_SDINEW, VS_SM_SDINEW);
00551 #else
00552 VsCodecMode(&devSpiVsCodec0, VS_SM_SDINEW | VS_SM_SDISHARE, VS_SM_SDINEW | VS_SM_SDISHARE);
00553 #endif
00554 #endif
00555 }
00556 #endif
00557
00558
00559 if (!clkset) {
00560 VsCodec0SetClock(VSCODEC0_FREQ, 1);
00561 }
00562 }
00563 return 0;
00564 }
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574 static int VsCodec0Init(NUTDEVICE * dev)
00575 {
00576 size_t avail;
00577
00578
00579 VsCodec0ResetHardware(1);
00580
00581
00582 dcbVsCodec0.dcb_isready = VsCodec0IsReady;
00583 dcbVsCodec0.dcb_sendcmd = VsCodec0SendCmd;
00584 dcbVsCodec0.dcb_senddata = VsCodec0SendData;
00585 dcbVsCodec0.dcb_control = VsCodec0Control;
00586
00587
00588 #ifdef VS_DECODER_CAPS
00589 dcbVsCodec0.dcb_dec_caps = VS_DECODER_CAPS;
00590 #endif
00591 #ifdef VS_ENCODER_CAPS
00592 dcbVsCodec0.dcb_cod_caps = VS_ENCODER_CAPS;
00593 #endif
00594 #ifdef VS_MIDI_CAPS
00595 dcbVsCodec0.dcb_midi_caps = VS_MIDI_CAPS;
00596 #endif
00597
00598
00599 GpioPinConfigSet(VSCODEC0_DREQ_PORT, VSCODEC0_DREQ_BIT, 0);
00600
00601 GpioPinSetHigh(VSCODEC0_XCS_PORT, VSCODEC0_XCS_BIT);
00602 GpioPinConfigSet(VSCODEC0_XCS_PORT, VSCODEC0_XCS_BIT, GPIO_CFG_OUTPUT);
00603 #if defined(VSCODEC0_XDCS_PORT) && defined(VSCODEC0_XDCS_BIT)
00604 GpioPinSetHigh(VSCODEC0_XDCS_PORT, VSCODEC0_XDCS_BIT);
00605 GpioPinConfigSet(VSCODEC0_XDCS_PORT, VSCODEC0_XDCS_BIT, GPIO_CFG_OUTPUT);
00606 #endif
00607 #if defined(VSCODEC0_VSCS_PORT) && defined(VSCODEC0_VSCS_BIT)
00608 GpioPinSetHigh(VSCODEC0_VSCS_PORT, VSCODEC0_VSCS_BIT);
00609 GpioPinConfigSet(VSCODEC0_VSCS_PORT, VSCODEC0_VSCS_BIT, GPIO_CFG_OUTPUT);
00610 #endif
00611
00612
00613 NutRegisterIrqHandler(&VSCODEC0_DREQ_SIGNAL, VsCodec0Interrupt, &dcbVsCodec0.dcb_feedme);
00614
00615
00616 GpioPinConfigSet(VSCODEC0_DREQ_PORT, VSCODEC0_DREQ_BIT, GPIO_CFG_DISABLED);
00617 NutIrqSetMode(&VSCODEC0_DREQ_SIGNAL, NUT_IRQMODE_RISINGEDGE);
00618 NutIrqEnable(&VSCODEC0_DREQ_SIGNAL);
00619
00620
00621 if (VsCodec0ResetHardware(0)) {
00622
00623 return -1;
00624 }
00625
00626
00627
00628
00629 #ifdef VSCODEC0_OUTPUT_BUFSIZ
00630 avail = VSCODEC0_OUTPUT_BUFSIZ;
00631 #else
00632 avail = NutHeapAvailable() / 2;
00633 if (avail > VSCODEC0_MAX_OUTPUT_BUFSIZ) {
00634 avail = VSCODEC0_MAX_OUTPUT_BUFSIZ;
00635 }
00636 #endif
00637 if (VsDecoderBufferInit(dev, avail)) {
00638 return -1;
00639 }
00640
00641
00642 if (NutThreadCreate(dev->dev_name, FeederThread, dev,
00643 (NUT_THREAD_VSCODEC0STACK * NUT_THREAD_STACK_MULT) + NUT_THREAD_STACK_ADD) == 0) {
00644 return -1;
00645 }
00646 return 0;
00647 }
00648
00659 NUTDEVICE devSpiVsCodec0 = {
00660 0,
00661 {'a', 'u', 'd', 'i', 'o', '0', 0, 0, 0},
00662 IFTYP_CHAR,
00663 0,
00664 0,
00665 &nodeSpiVsCodec0,
00666 &dcbVsCodec0,
00667 VsCodec0Init,
00668 VsCodecIOCtl,
00669 VsCodecRead,
00670 VsCodecWrite,
00671 #ifdef __HARVARD_ARCH__
00672 VsCodecWrite_P,
00673 #endif
00674 VsCodecOpen,
00675 VsCodecClose,
00676 NULL
00677 };
00678
00681 #endif