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
00287 static int VsCodec0SetClock(uint32_t xtal, uint_fast8_t dreq)
00288 {
00289 int rc = 0;
00290
00291 #if VS_HAS_SC_X3FREQ
00292
00293 if (dreq) {
00294
00295 VsCodecWaitReady(&devSpiVsCodec0, VSCODEC_CMD_TIMEOUT);
00296 }
00297 {
00298 uint8_t cmd[4] = { VS_OPCODE_WRITE, VS_CLOCKF_REG, 0, 0 };
00299 uint16_t freq = (uint16_t)((xtal - 8000000UL) / 4000UL);
00300
00301 freq |= (VS_SC_MULT_3_5 | VS_SC_ADD_1_0);
00302 cmd[2] = (uint8_t) (freq >> 8);
00303 cmd[3] = (uint8_t) freq;
00304 rc = VsCodec0SendCmd(cmd, 4);
00305 }
00306 #else
00307
00308 if (xtal < 20000000UL) {
00309 VsCodecReg(&devSpiVsCodec0, VS_OPCODE_WRITE, VS_CLOCKF_REG, (uint16_t)(VS_CF_DOUBLER | (xtal / 2000UL)));
00310 } else {
00311 VsCodecReg(&devSpiVsCodec0, VS_OPCODE_WRITE, VS_CLOCKF_REG, (uint16_t)(xtal / 2000UL));
00312 }
00313 #endif
00314
00315
00316 #if defined(AUDIO0_VS1001K)
00317 VsCodecReg(&devSpiVsCodec0, VS_OPCODE_WRITE, VS_INT_FCTLH_REG, 0x8008);
00318 #elif defined(AUDIO0_VSAUTO) && defined(VS_INT_FCTLH_REG)
00319 if (dcbVsCodec0.dcb_codec_ver == 1001) {
00320 VsCodecReg(&devSpiVsCodec0, VS_OPCODE_WRITE, VS_INT_FCTLH_REG, 0x8008);
00321 }
00322 #endif
00323
00324
00325 if (rc == 0) {
00326 #if VS_HAS_SC_X3FREQ
00327 (*nodeSpiVsCodec0.node_bus->bus_set_rate) (&nodeSpiVsCodec0, xtal / 2);
00328 #else
00329 (*nodeSpiVsCodec0.node_bus->bus_set_rate) (&nodeSpiVsCodec0, xtal / 3);
00330 #endif
00331 }
00332 return rc;
00333 }
00334
00346 static int VsCodec0Detect(void)
00347 {
00348 int rc = -1;
00349 uint_fast16_t status;
00350
00351
00352
00353 status = VsCodecReg(&devSpiVsCodec0, VS_OPCODE_READ, VS_STATUS_REG, 0);
00354 status = VsCodecReg(&devSpiVsCodec0, VS_OPCODE_READ, VS_STATUS_REG, 0);
00355
00356
00357
00358
00359 #if defined(AUDIO0_VS1001K)
00360 if ((status & VS_SS_VER) == (VS1001_SS_VER << VS_SS_VER_LSB)) {
00361 dcbVsCodec0.dcb_codec_ver = 1001;
00362 dcbVsCodec0.dcb_codec_rev = 'K';
00363 rc = 0;
00364 }
00365 #elif defined(AUDIO0_VS1011E)
00366 if ((status & VS_SS_VER) == (VS1011E_SS_VER << VS_SS_VER_LSB)) {
00367 dcbVsCodec0.dcb_codec_ver = 1011;
00368 dcbVsCodec0.dcb_codec_rev = 'E';
00369 rc = 0;
00370 }
00371 #elif defined(AUDIO0_VS1002D)
00372 if ((status & VS_SS_VER) == (VS1002_SS_VER << VS_SS_VER_LSB)) {
00373 dcbVsCodec0.dcb_codec_ver = 1002;
00374 dcbVsCodec0.dcb_codec_rev = 'D';
00375 rc = 0;
00376 }
00377 #elif defined(AUDIO0_VS1003B)
00378 if ((status & VS_SS_VER) == (VS1003_SS_VER << VS_SS_VER_LSB)) {
00379 dcbVsCodec0.dcb_codec_ver = 1003;
00380 dcbVsCodec0.dcb_codec_rev = 'B';
00381 rc = 0;
00382 }
00383 #elif defined(AUDIO0_VS1033C)
00384 if ((status & VS_SS_VER) == (VS1033_SS_VER << VS_SS_VER_LSB)) {
00385 dcbVsCodec0.dcb_codec_ver = 1033;
00386 dcbVsCodec0.dcb_codec_rev = 'C';
00387 rc = 0;
00388 }
00389 #elif defined(AUDIO0_VS1053B)
00390 if ((status & VS_SS_VER) == (VS1053_SS_VER << VS_SS_VER_LSB)) {
00391 dcbVsCodec0.dcb_codec_ver = 1053;
00392 dcbVsCodec0.dcb_codec_rev = 'B';
00393 rc = 0;
00394 }
00395 #else
00396
00397
00398
00399 rc = 0;
00400 switch ((status & VS_SS_VER) >> VS_SS_VER_LSB) {
00401 case VS1001_SS_VER:
00402 dcbVsCodec0.dcb_codec_ver = 1001;
00403 break;
00404 case VS1011_SS_VER:
00405 dcbVsCodec0.dcb_codec_ver = 1011;
00406 break;
00407 case VS1002_SS_VER:
00408 if (VsCodecReg(&devSpiVsCodec0, VS_OPCODE_READ, VS_MODE_REG, 0) & VS_SM_SDINEW) {
00409 dcbVsCodec0.dcb_codec_ver = 1002;
00410 } else {
00411 dcbVsCodec0.dcb_codec_ver = 1011;
00412 dcbVsCodec0.dcb_codec_rev = 'E';
00413 }
00414 break;
00415 case VS1003_SS_VER:
00416 dcbVsCodec0.dcb_codec_ver = 1003;
00417 break;
00418 case VS1053_SS_VER:
00419 dcbVsCodec0.dcb_codec_ver = 1053;
00420 break;
00421 case VS1033_SS_VER:
00422 dcbVsCodec0.dcb_codec_ver = 1033;
00423 break;
00424 case VS1103_SS_VER:
00425 dcbVsCodec0.dcb_codec_ver = 1103;
00426 break;
00427 default:
00428 rc = -1;
00429 break;
00430 }
00431 #endif
00432 return rc;
00433 }
00434
00446 static int VsCodec0ResetHardware(int on)
00447 {
00448 if (on) {
00449
00450
00451
00452 #if defined(VSCODEC0_XRESET_PORT) && defined(VSCODEC0_XRESET_BIT)
00453
00454 GpioPinSetLow(VSCODEC0_XRESET_PORT, VSCODEC0_XRESET_BIT);
00455 GpioPinConfigSet(VSCODEC0_XRESET_PORT, VSCODEC0_XRESET_BIT, GPIO_CFG_OUTPUT);
00456 NutSleep(VSCODEC0_HWRST_DURATION);
00457 #else
00458 return -1;
00459 #endif
00460 } else {
00461
00462
00463
00464 uint_fast8_t clkset = 0;
00465
00466 #if defined(VSCODEC0_XRESET_PORT) && defined(VSCODEC0_XRESET_BIT)
00467
00468 GpioPinSetHigh(VSCODEC0_XRESET_PORT, VSCODEC0_XRESET_BIT);
00469 #if VSCODEC0_FREQ >= 24000000UL
00470
00471
00472 csrc = VsCodec0SetClock(VSCODEC0_FREQ, 0) == 0;
00473 #endif
00474 #endif
00475
00476 #if VSCODEC0_HWRST_RECOVER
00477
00478 NutSleep(VSCODEC0_HWRST_RECOVER);
00479 #endif
00480
00481 if (VsCodec0Detect()) {
00482 return -1;
00483 }
00484 #if !defined(AUDIO0_VS1001K)
00485 if (dcbVsCodec0.dcb_codec_ver != 1001) {
00486 #if VS_HAS_SM_SDINEW
00487 #if defined(VSCODEC0_XDCS_PORT) && defined(VSCODEC0_XDCS_BIT)
00488 VsCodecMode(&devSpiVsCodec0, VS_SM_SDINEW, VS_SM_SDINEW);
00489 #else
00490 VsCodecMode(&devSpiVsCodec0, VS_SM_SDINEW | VS_SM_SDISHARE, VS_SM_SDINEW | VS_SM_SDISHARE);
00491 #endif
00492 #endif
00493 }
00494 #endif
00495
00496
00497 if (!clkset) {
00498 VsCodec0SetClock(VSCODEC0_FREQ, 1);
00499 }
00500 }
00501 return 0;
00502 }
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512 static int VsCodec0Init(NUTDEVICE * dev)
00513 {
00514 size_t avail;
00515
00516
00517 dcbVsCodec0.dcb_isready = VsCodec0IsReady;
00518 dcbVsCodec0.dcb_sendcmd = VsCodec0SendCmd;
00519 dcbVsCodec0.dcb_senddata = VsCodec0SendData;
00520
00521
00522 VsCodec0ResetHardware(1);
00523
00524
00525 GpioPinConfigSet(VSCODEC0_DREQ_PORT, VSCODEC0_DREQ_BIT, 0);
00526
00527 GpioPinSetHigh(VSCODEC0_XCS_PORT, VSCODEC0_XCS_BIT);
00528 GpioPinConfigSet(VSCODEC0_XCS_PORT, VSCODEC0_XCS_BIT, GPIO_CFG_OUTPUT);
00529 #if defined(VSCODEC0_XDCS_PORT) && defined(VSCODEC0_XDCS_BIT)
00530 GpioPinSetHigh(VSCODEC0_XDCS_PORT, VSCODEC0_XDCS_BIT);
00531 GpioPinConfigSet(VSCODEC0_XDCS_PORT, VSCODEC0_XDCS_BIT, GPIO_CFG_OUTPUT);
00532 #endif
00533 #if defined(VSCODEC0_VSCS_PORT) && defined(VSCODEC0_VSCS_BIT)
00534 GpioPinSetHigh(VSCODEC0_VSCS_PORT, VSCODEC0_VSCS_BIT);
00535 GpioPinConfigSet(VSCODEC0_VSCS_PORT, VSCODEC0_VSCS_BIT, GPIO_CFG_OUTPUT);
00536 #endif
00537
00538
00539 NutRegisterIrqHandler(&VSCODEC0_DREQ_SIGNAL, VsCodec0Interrupt, &dcbVsCodec0.dcb_feedme);
00540
00541
00542 GpioPinConfigSet(VSCODEC0_DREQ_PORT, VSCODEC0_DREQ_BIT, GPIO_CFG_DISABLED);
00543 NutIrqSetMode(&VSCODEC0_DREQ_SIGNAL, NUT_IRQMODE_RISINGEDGE);
00544 NutIrqEnable(&VSCODEC0_DREQ_SIGNAL);
00545
00546
00547 if (VsCodec0ResetHardware(0)) {
00548
00549 return -1;
00550 }
00551
00552
00553
00554
00555 #ifdef VSCODEC0_OUTPUT_BUFSIZ
00556 avail = VSCODEC0_OUTPUT_BUFSIZ;
00557 #else
00558 avail = NutHeapAvailable() / 2;
00559 if (avail > VSCODEC0_MAX_OUTPUT_BUFSIZ) {
00560 avail = VSCODEC0_MAX_OUTPUT_BUFSIZ;
00561 }
00562 #endif
00563 if (VsDecoderBufferInit(dev, avail)) {
00564 return -1;
00565 }
00566
00567
00568 if (NutThreadCreate(dev->dev_name, FeederThread, dev,
00569 (NUT_THREAD_VSCODEC0STACK * NUT_THREAD_STACK_MULT) + NUT_THREAD_STACK_ADD) == 0) {
00570 return -1;
00571 }
00572 return 0;
00573 }
00574
00585 NUTDEVICE devSpiVsCodec0 = {
00586 0,
00587 {'a', 'u', 'd', 'i', 'o', '0', 0, 0, 0},
00588 IFTYP_CHAR,
00589 0,
00590 0,
00591 &nodeSpiVsCodec0,
00592 &dcbVsCodec0,
00593 VsCodec0Init,
00594 VsCodecIOCtl,
00595 NULL,
00596 VsCodecWrite,
00597 #ifdef __HARVARD_ARCH__
00598 VsCodecWrite_P,
00599 #endif
00600 VsCodecOpen,
00601 VsCodecClose,
00602 NULL
00603 };
00604
00607 #endif