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_PORT) && defined(VSCODEC0_DREQ_BIT)
00055 #if defined(VSCODEC0_XCS_PORT) && defined(VSCODEC0_XCS_BIT)
00056 #define VSCODEC0_CONFIGURED 1
00057 #endif
00058 #endif
00059
00060 #if VSCODEC0_CONFIGURED
00061
00066
00067 #ifndef NUT_THREAD_VSCODEC0STACK
00068 #if defined(__AVR__)
00069
00070 #define NUT_THREAD_VSCODEC0STACK 128
00071 #else
00072
00073 #define NUT_THREAD_VSCODEC0STACK 192
00074 #endif
00075 #endif
00076
00077 #ifndef VSCODEC0_HWRST_DURATION
00078
00079 #define VSCODEC0_HWRST_DURATION 1
00080 #endif
00081
00082 #ifndef VSCODEC0_FREQ
00083
00084 #define VSCODEC0_FREQ 12288000UL
00085 #endif
00086
00087 #ifndef VSCODEC0_SPI_RATE
00088
00089 #define VSCODEC0_SPI_RATE (VSCODEC0_FREQ / 8)
00090 #endif
00091
00092 #ifndef VSCODEC0_SPI_MODE
00093
00094 #define VSCODEC0_SPI_MODE SPI_MODE_0
00095 #endif
00096
00097 #ifndef VSCODEC0_SPIBUS_WAIT
00098
00099 #define VSCODEC0_SPIBUS_WAIT NUT_WAIT_INFINITE
00100 #endif
00101
00102 #ifndef VSCODEC0_MAX_OUTPUT_BUFSIZ
00103
00104 #define VSCODEC0_MAX_OUTPUT_BUFSIZ 16384
00105 #endif
00106
00107
00108
00109
00110 #if (VSCODEC0_SIGNAL_IRQ == NUTGPIO_EXTINT0)
00111 #define VSCODEC0_DREQ_SIGNAL sig_INTERRUPT0
00112 #elif (VSCODEC0_SIGNAL_IRQ == NUTGPIO_EXTINT1)
00113 #define VSCODEC0_DREQ_SIGNAL sig_INTERRUPT1
00114 #elif (VSCODEC0_SIGNAL_IRQ == NUTGPIO_EXTINT2)
00115 #define VSCODEC0_DREQ_SIGNAL sig_INTERRUPT2
00116 #elif (VSCODEC0_SIGNAL_IRQ == NUTGPIO_EXTINT3)
00117 #define VSCODEC0_DREQ_SIGNAL sig_INTERRUPT3
00118 #elif (VSCODEC0_SIGNAL_IRQ == NUTGPIO_EXTINT4)
00119 #define VSCODEC0_DREQ_SIGNAL sig_INTERRUPT4
00120 #elif (VSCODEC0_SIGNAL_IRQ == NUTGPIO_EXTINT5)
00121 #define VSCODEC0_DREQ_SIGNAL sig_INTERRUPT5
00122 #elif (VSCODEC0_SIGNAL_IRQ == NUTGPIO_EXTINT6)
00123 #define VSCODEC0_DREQ_SIGNAL sig_INTERRUPT6
00124 #elif (VSCODEC0_SIGNAL_IRQ == NUTGPIO_EXTINT7)
00125 #define VSCODEC0_DREQ_SIGNAL sig_INTERRUPT7
00126 #endif
00127
00131 static NUTSPINODE nodeSpiVsCodec0 = {
00132 NULL,
00133 NULL,
00134 VSCODEC0_SPI_RATE,
00135 VSCODEC0_SPI_MODE,
00136 8,
00137 0
00138 };
00139
00140 static VSDCB dcbVsCodec0;
00141
00142
00143
00144
00145
00146
00147 static void VsCodec0Interrupt(void *arg)
00148 {
00149 NutEventPostFromIrq((void **)arg);
00150 }
00151
00157 static int VsCodec0IsReady(void)
00158 {
00159 return GpioPinGet(VSCODEC0_DREQ_PORT, VSCODEC0_DREQ_BIT) != 0;
00160 }
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172 static int VsCodec0SendCmd(void *cmd, size_t len)
00173 {
00174 int rc;
00175
00176
00177 rc = (*nodeSpiVsCodec0.node_bus->bus_alloc) (&nodeSpiVsCodec0, VSCODEC0_SPIBUS_WAIT);
00178 if (rc == 0) {
00179
00180 #if defined(VSCODEC0_VSCS_PORT) && defined(VSCODEC0_VSCS_BIT)
00181 GpioPinSetLow(VSCODEC0_VSCS_PORT, VSCODEC0_VSCS_BIT);
00182 #endif
00183 GpioPinSetLow(VSCODEC0_XCS_PORT, VSCODEC0_XCS_BIT);
00184
00185 rc = (*nodeSpiVsCodec0.node_bus->bus_transfer) (&nodeSpiVsCodec0, cmd, cmd, len);
00186
00187 GpioPinSetHigh(VSCODEC0_XCS_PORT, VSCODEC0_XCS_BIT);
00188 #if defined(VSCODEC0_VSCS_PORT) && defined(VSCODEC0_VSCS_BIT)
00189 GpioPinSetHigh(VSCODEC0_VSCS_PORT, VSCODEC0_VSCS_BIT);
00190 #endif
00191
00192 (*nodeSpiVsCodec0.node_bus->bus_release) (&nodeSpiVsCodec0);
00193 }
00194 return rc;
00195 }
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212 static int VsCodec0SendData(CONST uint8_t *buf, size_t len)
00213 {
00214 int rc = 0;
00215 CONST uint8_t *bp;
00216 size_t chunk;
00217
00218
00219 if ((*nodeSpiVsCodec0.node_bus->bus_alloc) (&nodeSpiVsCodec0, VSCODEC0_SPIBUS_WAIT) == 0) {
00220 #if defined(VSCODEC0_VSCS_PORT) && defined(VSCODEC0_VSCS_BIT)
00221
00222 GpioPinSetLow(VSCODEC0_VSCS_PORT, VSCODEC0_VSCS_BIT);
00223 #endif
00224 #if defined(VSCODEC0_XDCS_PORT) && defined(VSCODEC0_XDCS_BIT)
00225
00226 GpioPinSetLow(VSCODEC0_XDCS_PORT, VSCODEC0_XDCS_BIT);
00227 #endif
00228
00229
00230 bp = buf ? buf : zero_chunk;
00231
00232 while (len) {
00233
00234 chunk = len > VSCODEC_DATA_CHUNK_SIZE ? VSCODEC_DATA_CHUNK_SIZE : len;
00235
00236 if ((*nodeSpiVsCodec0.node_bus->bus_transfer) (&nodeSpiVsCodec0, bp, NULL, chunk)) {
00237 break;
00238 }
00239
00240 rc += chunk;
00241
00242 if (!VsCodec0IsReady()) {
00243 break;
00244 }
00245
00246 len -= chunk;
00247 if (buf) {
00248 bp += chunk;
00249 }
00250 }
00251 #if defined(VSCODEC0_XDCS_PORT) && defined(VSCODEC0_XDCS_BIT)
00252
00253 GpioPinSetHigh(VSCODEC0_XDCS_PORT, VSCODEC0_XDCS_BIT);
00254 #endif
00255 #if defined(VSCODEC0_VSCS_PORT) && defined(VSCODEC0_VSCS_BIT)
00256
00257 GpioPinSetHigh(VSCODEC0_VSCS_PORT, VSCODEC0_VSCS_BIT);
00258 #endif
00259
00260 (*nodeSpiVsCodec0.node_bus->bus_release) (&nodeSpiVsCodec0);
00261 }
00262 return rc;
00263 }
00264
00277 static int VsCodec0SetClock(uint32_t xtal, uint_fast8_t dreq)
00278 {
00279 int rc = 0;
00280
00281 #if VS_HAS_SC_X3FREQ
00282
00283 if (dreq) {
00284
00285 VsCodecWaitReady(&devSpiVsCodec0, VSCODEC_CMD_TIMEOUT);
00286 }
00287 {
00288 uint8_t cmd[4] = { VS_OPCODE_WRITE, VS_CLOCKF_REG, 0, 0 };
00289 uint16_t freq = (uint16_t)((xtal - 8000000UL) / 4000UL);
00290
00291 freq |= (VS_SC_MULT_3_5 | VS_SC_ADD_1_0);
00292 cmd[2] = (uint8_t) (freq >> 8);
00293 cmd[3] = (uint8_t) freq;
00294 rc = VsCodec0SendCmd(cmd, 4);
00295 }
00296 #else
00297
00298 if (xtal < 20000000UL) {
00299 VsCodecReg(&devSpiVsCodec0, VS_OPCODE_WRITE, VS_CLOCKF_REG, (uint16_t)(VS_CF_DOUBLER | (xtal / 2000UL)));
00300 } else {
00301 VsCodecReg(&devSpiVsCodec0, VS_OPCODE_WRITE, VS_CLOCKF_REG, (uint16_t)(xtal / 2000UL));
00302 }
00303 #endif
00304
00305
00306 #if defined(AUDIO0_VS1001K)
00307 VsCodecReg(&devSpiVsCodec0, VS_OPCODE_WRITE, VS_INT_FCTLH_REG, 0x8008);
00308 #elif defined(AUDIO0_VSAUTO) && defined(VS_INT_FCTLH_REG)
00309 if (dcbVsCodec0.dcb_codec_ver == 1001) {
00310 VsCodecReg(&devSpiVsCodec0, VS_OPCODE_WRITE, VS_INT_FCTLH_REG, 0x8008);
00311 }
00312 #endif
00313
00314
00315 if (rc == 0) {
00316 #if VS_HAS_SC_X3FREQ
00317 (*nodeSpiVsCodec0.node_bus->bus_set_rate) (&nodeSpiVsCodec0, xtal / 2);
00318 #else
00319 (*nodeSpiVsCodec0.node_bus->bus_set_rate) (&nodeSpiVsCodec0, xtal / 3);
00320 #endif
00321 }
00322 return rc;
00323 }
00324
00336 static int VsCodec0Detect(void)
00337 {
00338 int rc = -1;
00339 uint_fast16_t status;
00340
00341
00342
00343 status = VsCodecReg(&devSpiVsCodec0, VS_OPCODE_READ, VS_STATUS_REG, 0);
00344 status = VsCodecReg(&devSpiVsCodec0, VS_OPCODE_READ, VS_STATUS_REG, 0);
00345
00346
00347
00348
00349 #if defined(AUDIO0_VS1001K)
00350 if ((status & VS_SS_VER) == (VS1001_SS_VER << VS_SS_VER_LSB)) {
00351 dcbVsCodec0.dcb_codec_ver = 1001;
00352 dcbVsCodec0.dcb_codec_rev = 'K';
00353 rc = 0;
00354 }
00355 #elif defined(AUDIO0_VS1011E)
00356 if ((status & VS_SS_VER) == (VS1011E_SS_VER << VS_SS_VER_LSB)) {
00357 dcbVsCodec0.dcb_codec_ver = 1011;
00358 dcbVsCodec0.dcb_codec_rev = 'E';
00359 rc = 0;
00360 }
00361 #elif defined(AUDIO0_VS1002D)
00362 if ((status & VS_SS_VER) == (VS1002_SS_VER << VS_SS_VER_LSB)) {
00363 dcbVsCodec0.dcb_codec_ver = 1002;
00364 dcbVsCodec0.dcb_codec_rev = 'D';
00365 rc = 0;
00366 }
00367 #elif defined(AUDIO0_VS1003B)
00368 if ((status & VS_SS_VER) == (VS1003_SS_VER << VS_SS_VER_LSB)) {
00369 dcbVsCodec0.dcb_codec_ver = 1003;
00370 dcbVsCodec0.dcb_codec_rev = 'B';
00371 rc = 0;
00372 }
00373 #elif defined(AUDIO0_VS1033C)
00374 if ((status & VS_SS_VER) == (VS1033_SS_VER << VS_SS_VER_LSB)) {
00375 dcbVsCodec0.dcb_codec_ver = 1033;
00376 dcbVsCodec0.dcb_codec_rev = 'C';
00377 rc = 0;
00378 }
00379 #elif defined(AUDIO0_VS1053B)
00380 if ((status & VS_SS_VER) == (VS1053_SS_VER << VS_SS_VER_LSB)) {
00381 dcbVsCodec0.dcb_codec_ver = 1053;
00382 dcbVsCodec0.dcb_codec_rev = 'B';
00383 rc = 0;
00384 }
00385 #else
00386
00387
00388
00389 rc = 0;
00390 switch ((status & VS_SS_VER) >> VS_SS_VER_LSB) {
00391 case VS1001_SS_VER:
00392 dcbVsCodec0.dcb_codec_ver = 1001;
00393 break;
00394 case VS1011_SS_VER:
00395 dcbVsCodec0.dcb_codec_ver = 1011;
00396 break;
00397 case VS1002_SS_VER:
00398 if (VsCodecReg(&devSpiVsCodec0, VS_OPCODE_READ, VS_MODE_REG, 0) & VS_SM_SDINEW) {
00399 dcbVsCodec0.dcb_codec_ver = 1002;
00400 } else {
00401 dcbVsCodec0.dcb_codec_ver = 1011;
00402 dcbVsCodec0.dcb_codec_rev = 'E';
00403 }
00404 break;
00405 case VS1003_SS_VER:
00406 dcbVsCodec0.dcb_codec_ver = 1003;
00407 break;
00408 case VS1053_SS_VER:
00409 dcbVsCodec0.dcb_codec_ver = 1053;
00410 break;
00411 case VS1033_SS_VER:
00412 dcbVsCodec0.dcb_codec_ver = 1033;
00413 break;
00414 case VS1103_SS_VER:
00415 dcbVsCodec0.dcb_codec_ver = 1103;
00416 break;
00417 default:
00418 rc = -1;
00419 break;
00420 }
00421 #endif
00422 return rc;
00423 }
00424
00436 static int VsCodec0ResetHardware(int on)
00437 {
00438 if (on) {
00439
00440
00441
00442 #if defined(VSCODEC0_XRESET_PORT) && defined(VSCODEC0_XRESET_BIT)
00443
00444 GpioPinSetLow(VSCODEC0_XRESET_PORT, VSCODEC0_XRESET_BIT);
00445 GpioPinConfigSet(VSCODEC0_XRESET_PORT, VSCODEC0_XRESET_BIT, GPIO_CFG_OUTPUT);
00446 NutSleep(VSCODEC0_HWRST_DURATION);
00447 #else
00448 return -1;
00449 #endif
00450 } else {
00451
00452
00453
00454 uint_fast8_t clkset = 0;
00455
00456 #if defined(VSCODEC0_XRESET_PORT) && defined(VSCODEC0_XRESET_BIT)
00457
00458 GpioPinSetHigh(VSCODEC0_XRESET_PORT, VSCODEC0_XRESET_BIT);
00459 #if VSCODEC0_FREQ >= 24000000UL
00460
00461
00462 csrc = VsCodec0SetClock(VSCODEC0_FREQ, 0) == 0;
00463 #endif
00464 #endif
00465
00466 #if VSCODEC0_HWRST_RECOVER
00467
00468 NutSleep(VSCODEC0_HWRST_RECOVER);
00469 #endif
00470
00471 if (VsCodec0Detect()) {
00472 return -1;
00473 }
00474 #if !defined(AUDIO0_VS1001K)
00475 if (dcbVsCodec0.dcb_codec_ver != 1001) {
00476 #if VS_HAS_SM_SDINEW
00477 #if defined(VSCODEC0_XDCS_PORT) && defined(VSCODEC0_XDCS_BIT)
00478 VsCodecMode(&devSpiVsCodec0, VS_SM_SDINEW, VS_SM_SDINEW);
00479 #else
00480 VsCodecMode(&devSpiVsCodec0, VS_SM_SDINEW | VS_SM_SDISHARE, VS_SM_SDINEW | VS_SM_SDISHARE);
00481 #endif
00482 #endif
00483 }
00484 #endif
00485
00486
00487 if (!clkset) {
00488 VsCodec0SetClock(VSCODEC0_FREQ, 1);
00489 }
00490 }
00491 return 0;
00492 }
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502 static int VsCodec0Init(NUTDEVICE * dev)
00503 {
00504 size_t avail;
00505
00506
00507 dcbVsCodec0.dcb_isready = VsCodec0IsReady;
00508 dcbVsCodec0.dcb_sendcmd = VsCodec0SendCmd;
00509 dcbVsCodec0.dcb_senddata = VsCodec0SendData;
00510
00511
00512 VsCodec0ResetHardware(1);
00513
00514
00515 GpioPinConfigSet(VSCODEC0_DREQ_PORT, VSCODEC0_DREQ_BIT, 0);
00516
00517 GpioPinSetHigh(VSCODEC0_XCS_PORT, VSCODEC0_XCS_BIT);
00518 GpioPinConfigSet(VSCODEC0_XCS_PORT, VSCODEC0_XCS_BIT, GPIO_CFG_OUTPUT);
00519 #if defined(VSCODEC0_XDCS_PORT) && defined(VSCODEC0_XDCS_BIT)
00520 GpioPinSetHigh(VSCODEC0_XDCS_PORT, VSCODEC0_XDCS_BIT);
00521 GpioPinConfigSet(VSCODEC0_XDCS_PORT, VSCODEC0_XDCS_BIT, GPIO_CFG_OUTPUT);
00522 #endif
00523 #if defined(VSCODEC0_VSCS_PORT) && defined(VSCODEC0_VSCS_BIT)
00524 GpioPinSetHigh(VSCODEC0_VSCS_PORT, VSCODEC0_VSCS_BIT);
00525 GpioPinConfigSet(VSCODEC0_VSCS_PORT, VSCODEC0_VSCS_BIT, GPIO_CFG_OUTPUT);
00526 #endif
00527
00528
00529 NutRegisterIrqHandler(&VSCODEC0_DREQ_SIGNAL, VsCodec0Interrupt, &dcbVsCodec0.dcb_feedme);
00530
00531
00532 GpioPinConfigSet(VSCODEC0_DREQ_PORT, VSCODEC0_DREQ_BIT, GPIO_CFG_DISABLED);
00533 NutIrqSetMode(&VSCODEC0_DREQ_SIGNAL, NUT_IRQMODE_RISINGEDGE);
00534 NutIrqEnable(&VSCODEC0_DREQ_SIGNAL);
00535
00536
00537 if (VsCodec0ResetHardware(0)) {
00538
00539 return -1;
00540 }
00541
00542
00543
00544
00545 #ifdef VSCODEC0_OUTPUT_BUFSIZ
00546 avail = VSCODEC0_OUTPUT_BUFSIZ;
00547 #else
00548 avail = NutHeapAvailable() / 2;
00549 if (avail > VSCODEC0_MAX_OUTPUT_BUFSIZ) {
00550 avail = VSCODEC0_MAX_OUTPUT_BUFSIZ;
00551 }
00552 #endif
00553 if (VsDecoderBufferInit(dev, avail)) {
00554 return -1;
00555 }
00556
00557
00558 if (NutThreadCreate(dev->dev_name, FeederThread, dev,
00559 (NUT_THREAD_VSCODEC0STACK * NUT_THREAD_STACK_MULT) + NUT_THREAD_STACK_ADD) == 0) {
00560 return -1;
00561 }
00562 return 0;
00563 }
00564
00575 NUTDEVICE devSpiVsCodec0 = {
00576 0,
00577 {'a', 'u', 'd', 'i', 'o', '0', 0, 0, 0},
00578 IFTYP_CHAR,
00579 0,
00580 0,
00581 &nodeSpiVsCodec0,
00582 &dcbVsCodec0,
00583 VsCodec0Init,
00584 VsCodecIOCtl,
00585 NULL,
00586 VsCodecWrite,
00587 #ifdef __HARVARD_ARCH__
00588 VsCodecWrite_P,
00589 #endif
00590 VsCodecOpen,
00591 VsCodecClose,
00592 NULL
00593 };
00594
00597 #endif