spi_vscodec0.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2008-2009 by egnite GmbH
00003  * Copyright (C) 2001-2007 by egnite Software GmbH
00004  *
00005  * All rights reserved.
00006  *
00007  * Redistribution and use in source and binary forms, with or without
00008  * modification, are permitted provided that the following conditions
00009  * are met:
00010  *
00011  * 1. Redistributions of source code must retain the above copyright
00012  *    notice, this list of conditions and the following disclaimer.
00013  * 2. Redistributions in binary form must reproduce the above copyright
00014  *    notice, this list of conditions and the following disclaimer in the
00015  *    documentation and/or other materials provided with the distribution.
00016  * 3. Neither the name of the copyright holders nor the names of
00017  *    contributors may be used to endorse or promote products derived
00018  *    from this software without specific prior written permission.
00019  *
00020  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00021  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00022  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00023  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00024  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00025  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00026  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00027  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00028  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00029  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00030  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00031  * SUCH DAMAGE.
00032  *
00033  * For additional information see http://www.ethernut.de/
00034  */
00035 
00036 /*
00037  * $Id: spi_vscodec0.c 2721 2009-09-29 17:44:58Z haraldkipp $
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 #if defined(__GNUC__)
00070 /* avr-gcc optimized code used 88 bytes. */
00071 #define NUT_THREAD_VSCODEC0STACK    128
00072 #else
00073 /* icc-avr stack usage is unknown. */
00074 #define NUT_THREAD_VSCODEC0STACK    384
00075 #endif
00076 #else
00077 /* arm-elf-gcc optimized code used 112 bytes. */
00078 #define NUT_THREAD_VSCODEC0STACK    192
00079 #endif
00080 #endif
00081 
00082 #ifndef VSCODEC0_HWRST_DURATION
00083 
00084 #define VSCODEC0_HWRST_DURATION     1
00085 #endif
00086 
00087 #ifndef VSCODEC0_FREQ
00088 
00089 #define VSCODEC0_FREQ               12288000UL
00090 #endif
00091 
00092 #ifndef VSCODEC0_SPI_RATE
00093 
00094 #define VSCODEC0_SPI_RATE           (VSCODEC0_FREQ / 8)
00095 #endif
00096 
00097 #ifndef VSCODEC0_SPI_MODE
00098 
00099 #define VSCODEC0_SPI_MODE           SPI_MODE_0
00100 #endif
00101 
00102 #ifndef VSCODEC0_SPIBUS_WAIT
00103 
00104 #define VSCODEC0_SPIBUS_WAIT        NUT_WAIT_INFINITE
00105 #endif
00106 
00107 #ifndef VSCODEC0_MAX_OUTPUT_BUFSIZ
00108 
00109 #define VSCODEC0_MAX_OUTPUT_BUFSIZ  16384
00110 #endif
00111 
00112 /*
00113  * Determine interrupt settings.
00114  */
00115 #if (VSCODEC0_SIGNAL_IRQ == NUTGPIO_EXTINT0)
00116 #define VSCODEC0_DREQ_SIGNAL  sig_INTERRUPT0
00117 #elif (VSCODEC0_SIGNAL_IRQ == NUTGPIO_EXTINT1)
00118 #define VSCODEC0_DREQ_SIGNAL  sig_INTERRUPT1
00119 #elif (VSCODEC0_SIGNAL_IRQ == NUTGPIO_EXTINT2)
00120 #define VSCODEC0_DREQ_SIGNAL  sig_INTERRUPT2
00121 #elif (VSCODEC0_SIGNAL_IRQ == NUTGPIO_EXTINT3)
00122 #define VSCODEC0_DREQ_SIGNAL  sig_INTERRUPT3
00123 #elif (VSCODEC0_SIGNAL_IRQ == NUTGPIO_EXTINT4)
00124 #define VSCODEC0_DREQ_SIGNAL  sig_INTERRUPT4
00125 #elif (VSCODEC0_SIGNAL_IRQ == NUTGPIO_EXTINT5)
00126 #define VSCODEC0_DREQ_SIGNAL  sig_INTERRUPT5
00127 #elif (VSCODEC0_SIGNAL_IRQ == NUTGPIO_EXTINT6)
00128 #define VSCODEC0_DREQ_SIGNAL  sig_INTERRUPT6
00129 #elif (VSCODEC0_SIGNAL_IRQ == NUTGPIO_EXTINT7)
00130 #define VSCODEC0_DREQ_SIGNAL  sig_INTERRUPT7
00131 #endif
00132 
00136 static NUTSPINODE nodeSpiVsCodec0 = {
00137     NULL,               
00138     NULL,               
00139     VSCODEC0_SPI_RATE,  
00140     VSCODEC0_SPI_MODE,  
00141     8,                  
00142     0                   
00143 };
00144 
00145 static VSDCB dcbVsCodec0;
00146 
00147 /*
00148  * VLSI codec 0 interrupt handler.
00149  *
00150  * \param arg Pointer to an event queue.
00151  */
00152 static void VsCodec0Interrupt(void *arg)
00153 {
00154     NutEventPostFromIrq((void **)arg);
00155 }
00156 
00162 static int VsCodec0IsReady(void)
00163 {
00164     return GpioPinGet(VSCODEC0_DREQ_PORT, VSCODEC0_DREQ_BIT) != 0;
00165 }
00166 
00167 /*
00168  * \brief Write to command channel of codec 0.
00169  *
00170  * This routine will not check the DREQ line.
00171  *
00172  * \param cmd  Points to the buffer. On entry it contains the data to 
00173  *             send. On exit it will contain the data received from
00174  *             the chip.
00175  * \param len  Number of bytes to send and receive.
00176  */
00177 static int VsCodec0SendCmd(void *cmd, size_t len)
00178 {
00179     int rc;
00180 
00181     /* Allocate the SPI bus. */
00182     rc = (*nodeSpiVsCodec0.node_bus->bus_alloc) (&nodeSpiVsCodec0, VSCODEC0_SPIBUS_WAIT);
00183     if (rc == 0) {
00184         /* Activate chip selects. */
00185 #if defined(VSCODEC0_VSCS_PORT) && defined(VSCODEC0_VSCS_BIT)
00186         GpioPinSetLow(VSCODEC0_VSCS_PORT, VSCODEC0_VSCS_BIT);
00187 #endif
00188         GpioPinSetLow(VSCODEC0_XCS_PORT, VSCODEC0_XCS_BIT);
00189         /* Send command bytes and receive response. */
00190         rc = (*nodeSpiVsCodec0.node_bus->bus_transfer) (&nodeSpiVsCodec0, cmd, cmd, len);
00191         /* Dectivate chip selects. */
00192         GpioPinSetHigh(VSCODEC0_XCS_PORT, VSCODEC0_XCS_BIT);
00193 #if defined(VSCODEC0_VSCS_PORT) && defined(VSCODEC0_VSCS_BIT)
00194         GpioPinSetHigh(VSCODEC0_VSCS_PORT, VSCODEC0_VSCS_BIT);
00195 #endif
00196         /* Release the SPI bus. */
00197         (*nodeSpiVsCodec0.node_bus->bus_release) (&nodeSpiVsCodec0);
00198     }
00199     return rc;
00200 }
00201 
00202 /*
00203  * \brief Write data to the decoder.
00204  *
00205  * Data is sent in fixed chunks. The first one is sent without
00206  * checking the DREQ line. Any subsequent chunk is sent only if
00207  * the DREQ line is still high.
00208  *
00209  * \param node Specifies the SPI node.
00210  * \param buf  Points to the data. May be NULL, in which case the routine
00211  *             will send the specified number of zeros.
00212  * \param len  Number of bytes to send.
00213  *
00214  * \return The number of bytes actually sent. This may be less than the
00215  *         specified data length. Zero is returned in case of an error.
00216  */
00217 static int VsCodec0SendData(CONST uint8_t *buf, size_t len)
00218 {
00219     int rc = 0;
00220     CONST uint8_t *bp;
00221     size_t chunk;
00222 
00223     /* Allocate the SPI bus. */
00224     if ((*nodeSpiVsCodec0.node_bus->bus_alloc) (&nodeSpiVsCodec0, VSCODEC0_SPIBUS_WAIT) == 0) {
00225 #if defined(VSCODEC0_VSCS_PORT) && defined(VSCODEC0_VSCS_BIT)
00226         /* Activate optional VSCS line. */
00227         GpioPinSetLow(VSCODEC0_VSCS_PORT, VSCODEC0_VSCS_BIT);
00228 #endif
00229 #if defined(VSCODEC0_XDCS_PORT) && defined(VSCODEC0_XDCS_BIT)
00230         /* Activate optional XDCS line. */
00231         GpioPinSetLow(VSCODEC0_XDCS_PORT, VSCODEC0_XDCS_BIT);
00232 #endif
00233         /* Set our internal buffer pointer, either to the start of the 
00234         ** encoded data or to a chunk of zeros. */
00235         bp = buf ? buf : zero_chunk;
00236         /* Loop until all data had been sent or DREQ goes low. */
00237         while (len) {
00238             /* Determine chunk size. */
00239             chunk = len > VSCODEC_DATA_CHUNK_SIZE ? VSCODEC_DATA_CHUNK_SIZE : len;
00240             /* Send the chunk, exit on errors. */
00241             if ((*nodeSpiVsCodec0.node_bus->bus_transfer) (&nodeSpiVsCodec0, bp, NULL, chunk)) {
00242                 break;
00243             }
00244             /* Update function result. */
00245             rc += chunk;
00246             /* Check if decoder is ready for more. Exit, if not. */
00247             if (!VsCodec0IsReady()) {
00248                 break;
00249             }
00250             /* Update remaining number of bytes and buffer pointer. */
00251             len -= chunk;
00252             if (buf) {
00253                 bp += chunk;
00254             }
00255         }
00256 #if defined(VSCODEC0_XDCS_PORT) && defined(VSCODEC0_XDCS_BIT)
00257         /* Deactivate optional XDCS line. */
00258         GpioPinSetHigh(VSCODEC0_XDCS_PORT, VSCODEC0_XDCS_BIT);
00259 #endif
00260 #if defined(VSCODEC0_VSCS_PORT) && defined(VSCODEC0_VSCS_BIT)
00261         /* Deactivate optional VSCS line. */
00262         GpioPinSetHigh(VSCODEC0_VSCS_PORT, VSCODEC0_VSCS_BIT);
00263 #endif
00264         /* Release the SPI bus. */
00265         (*nodeSpiVsCodec0.node_bus->bus_release) (&nodeSpiVsCodec0);
00266     }
00267     return rc;
00268 }
00269 
00282 static int VsCodec0SetClock(uint32_t xtal, uint_fast8_t dreq)
00283 {
00284     int rc = 0;
00285 
00286 #if VS_HAS_SC_X3FREQ
00287     /* This hardware got the new CLOCKF register layout. */
00288     if (dreq) {
00289         /* Honor the DREQ line, if requested. */
00290         VsCodecWaitReady(&devSpiVsCodec0, VSCODEC_CMD_TIMEOUT);
00291     }
00292     {
00293         uint8_t cmd[4] = { VS_OPCODE_WRITE, VS_CLOCKF_REG, 0, 0 };
00294         uint16_t freq = (uint16_t)((xtal - 8000000UL) / 4000UL);
00295 
00296         freq |= (VS_SC_MULT_3_5 | VS_SC_ADD_1_0);
00297         cmd[2] = (uint8_t) (freq >> 8);
00298         cmd[3] = (uint8_t) freq;
00299         rc = VsCodec0SendCmd(cmd, 4);
00300     }
00301 #else
00302     /* Old hardware, requires clock doubler with lower frequence crystal. */
00303     if (xtal < 20000000UL) {
00304         VsCodecReg(&devSpiVsCodec0, VS_OPCODE_WRITE, VS_CLOCKF_REG, (uint16_t)(VS_CF_DOUBLER | (xtal / 2000UL)));
00305     } else {
00306         VsCodecReg(&devSpiVsCodec0, VS_OPCODE_WRITE, VS_CLOCKF_REG, (uint16_t)(xtal / 2000UL));
00307     }
00308 #endif
00309 
00310     /* Force frequency change (see VS1001 datasheet). */
00311 #if defined(AUDIO0_VS1001K)
00312     VsCodecReg(&devSpiVsCodec0, VS_OPCODE_WRITE, VS_INT_FCTLH_REG, 0x8008);
00313 #elif defined(AUDIO0_VSAUTO) && defined(VS_INT_FCTLH_REG)
00314     if (dcbVsCodec0.dcb_codec_ver == 1001) {
00315         VsCodecReg(&devSpiVsCodec0, VS_OPCODE_WRITE, VS_INT_FCTLH_REG, 0x8008);
00316     }
00317 #endif
00318 
00319     /* With higher clock we can increase the SPI rate. */
00320     if (rc == 0) {
00321 #if VS_HAS_SC_X3FREQ
00322         (*nodeSpiVsCodec0.node_bus->bus_set_rate) (&nodeSpiVsCodec0, xtal / 2);
00323 #endif
00324     }
00325     return rc;
00326 }
00327 
00339 static int VsCodec0Detect(void)
00340 {
00341     int rc = -1;
00342     uint_fast16_t status;
00343 
00344     /* While the VS1053B works fine on the EIR board, we still need
00345     ** a dummy read on the Ethernut 2.1B with Medianut 2. TODO: Why? */
00346     status = VsCodecReg(&devSpiVsCodec0, VS_OPCODE_READ, VS_STATUS_REG, 0);
00347     status = VsCodecReg(&devSpiVsCodec0, VS_OPCODE_READ, VS_STATUS_REG, 0);
00348 
00349     /*
00350     ** Verify the hardware if chip is pre-configured.
00351     */
00352 #if defined(AUDIO0_VS1001K)
00353     if ((status & VS_SS_VER) == (VS1001_SS_VER << VS_SS_VER_LSB)) {
00354         dcbVsCodec0.dcb_codec_ver = 1001;
00355         dcbVsCodec0.dcb_codec_rev = 'K';
00356         rc = 0;
00357     }
00358 #elif defined(AUDIO0_VS1011E)
00359     if ((status & VS_SS_VER) == (VS1011E_SS_VER << VS_SS_VER_LSB)) {
00360         dcbVsCodec0.dcb_codec_ver = 1011;
00361         dcbVsCodec0.dcb_codec_rev = 'E';
00362         rc = 0;
00363     }
00364 #elif defined(AUDIO0_VS1002D)
00365     if ((status & VS_SS_VER) == (VS1002_SS_VER << VS_SS_VER_LSB)) {
00366         dcbVsCodec0.dcb_codec_ver = 1002;
00367         dcbVsCodec0.dcb_codec_rev = 'D';
00368         rc = 0;
00369     }
00370 #elif defined(AUDIO0_VS1003B)
00371     if ((status & VS_SS_VER) == (VS1003_SS_VER << VS_SS_VER_LSB)) {
00372         dcbVsCodec0.dcb_codec_ver = 1003;
00373         dcbVsCodec0.dcb_codec_rev = 'B';
00374         rc = 0;
00375     }
00376 #elif defined(AUDIO0_VS1033C)
00377     if ((status & VS_SS_VER) == (VS1033_SS_VER << VS_SS_VER_LSB)) {
00378         dcbVsCodec0.dcb_codec_ver = 1033;
00379         dcbVsCodec0.dcb_codec_rev = 'C';
00380         rc = 0;
00381     }
00382 #elif defined(AUDIO0_VS1053B)
00383     if ((status & VS_SS_VER) == (VS1053_SS_VER << VS_SS_VER_LSB)) {
00384         dcbVsCodec0.dcb_codec_ver = 1053;
00385         dcbVsCodec0.dcb_codec_rev = 'B';
00386         rc = 0;
00387     }
00388 #else
00389     /*
00390     ** If not configured, try to figure it out.
00391     */
00392     rc = 0;
00393     switch ((status & VS_SS_VER) >> VS_SS_VER_LSB) {
00394     case VS1001_SS_VER:
00395         dcbVsCodec0.dcb_codec_ver = 1001;
00396         break;
00397     case VS1011_SS_VER:
00398         dcbVsCodec0.dcb_codec_ver = 1011;
00399         break;
00400     case VS1002_SS_VER:
00401         if (VsCodecReg(&devSpiVsCodec0, VS_OPCODE_READ, VS_MODE_REG, 0) & VS_SM_SDINEW) {
00402             dcbVsCodec0.dcb_codec_ver = 1002;
00403         } else {
00404             dcbVsCodec0.dcb_codec_ver = 1011;
00405             dcbVsCodec0.dcb_codec_rev = 'E';
00406         }
00407         break;
00408     case VS1003_SS_VER:
00409         dcbVsCodec0.dcb_codec_ver = 1003;
00410         break;
00411     case VS1053_SS_VER:
00412         dcbVsCodec0.dcb_codec_ver = 1053;
00413         break;
00414     case VS1033_SS_VER:
00415         dcbVsCodec0.dcb_codec_ver = 1033;
00416         break;
00417     case VS1103_SS_VER:
00418         dcbVsCodec0.dcb_codec_ver = 1103;
00419         break;
00420     default:
00421         rc = -1;
00422         break;
00423     }
00424 #endif
00425     return rc;
00426 }
00427 
00439 static int VsCodec0ResetHardware(int on)
00440 {
00441     if (on) {
00442         /*
00443         ** Activate reset.
00444         */
00445 #if defined(VSCODEC0_XRESET_PORT) && defined(VSCODEC0_XRESET_BIT)
00446         /* Activate the reset line. */
00447         GpioPinSetLow(VSCODEC0_XRESET_PORT, VSCODEC0_XRESET_BIT);
00448         GpioPinConfigSet(VSCODEC0_XRESET_PORT, VSCODEC0_XRESET_BIT, GPIO_CFG_OUTPUT);
00449         NutSleep(VSCODEC0_HWRST_DURATION);
00450 #else
00451         return -1;
00452 #endif
00453     } else {
00454         /*
00455         ** Deactivate reset.
00456         */
00457         uint_fast8_t clkset = 0;
00458 
00459 #if defined(VSCODEC0_XRESET_PORT) && defined(VSCODEC0_XRESET_BIT)
00460         /* Release the reset line. */
00461         GpioPinSetHigh(VSCODEC0_XRESET_PORT, VSCODEC0_XRESET_BIT);
00462 #if VSCODEC0_FREQ >= 24000000UL
00463         /* With input clocks equal or above 24MHz we must set CLOCKF early 
00464         ** and must not wait for rising DREQ. */
00465         csrc = VsCodec0SetClock(VSCODEC0_FREQ, 0) == 0;
00466 #endif /* VSCODEC0_FREQ */
00467 #endif /* VSCODEC0_XRESET_PORT */
00468 
00469 #if VSCODEC0_HWRST_RECOVER
00470         /* Optional delay after hardware reset. */
00471         NutSleep(VSCODEC0_HWRST_RECOVER);
00472 #endif
00473         /* Chip hardware detection. */
00474         if (VsCodec0Detect()) {
00475             return -1;
00476         }
00477 #if !defined(AUDIO0_VS1001K)
00478         if (dcbVsCodec0.dcb_codec_ver != 1001) {
00479 #if VS_HAS_SM_SDINEW
00480 #if defined(VSCODEC0_XDCS_PORT) && defined(VSCODEC0_XDCS_BIT)
00481             VsCodecMode(&devSpiVsCodec0, VS_SM_SDINEW, VS_SM_SDINEW);
00482 #else
00483             VsCodecMode(&devSpiVsCodec0, VS_SM_SDINEW | VS_SM_SDISHARE, VS_SM_SDINEW | VS_SM_SDISHARE);
00484 #endif
00485 #endif /* VS_HAS_SM_SDINEW */
00486         }
00487 #endif /* AUDIO0_VS1001K */
00488 
00489         /* Set clock now, if not done successfully before. */
00490         if (!clkset) {
00491             VsCodec0SetClock(VSCODEC0_FREQ, 1);
00492         }
00493     }
00494     return 0;
00495 }
00496 
00497 
00498 /*
00499  * Called via dev_init pointer when the device is registered.
00500  *
00501  * \param dev Specifies the audio codec device.
00502  *
00503  * \return 0 on success, -1 otherwise.
00504  */
00505 static int VsCodec0Init(NUTDEVICE * dev)
00506 {
00507     size_t avail;
00508 
00509     /* Set function pointers. */
00510     dcbVsCodec0.dcb_isready = VsCodec0IsReady;
00511     dcbVsCodec0.dcb_sendcmd = VsCodec0SendCmd;
00512     dcbVsCodec0.dcb_senddata = VsCodec0SendData;
00513 
00514     /* Activate hardware reset. */
00515     VsCodec0ResetHardware(1);
00516 
00517     /* Initialize DREQ input. Will be later used as an external interupt. */
00518     GpioPinConfigSet(VSCODEC0_DREQ_PORT, VSCODEC0_DREQ_BIT, 0);
00519     /* Initialize chip selects, XCS and optional XDCS. */
00520     GpioPinSetHigh(VSCODEC0_XCS_PORT, VSCODEC0_XCS_BIT);
00521     GpioPinConfigSet(VSCODEC0_XCS_PORT, VSCODEC0_XCS_BIT, GPIO_CFG_OUTPUT);
00522 #if defined(VSCODEC0_XDCS_PORT) && defined(VSCODEC0_XDCS_BIT)
00523     GpioPinSetHigh(VSCODEC0_XDCS_PORT, VSCODEC0_XDCS_BIT);
00524     GpioPinConfigSet(VSCODEC0_XDCS_PORT, VSCODEC0_XDCS_BIT, GPIO_CFG_OUTPUT);
00525 #endif
00526 #if defined(VSCODEC0_VSCS_PORT) && defined(VSCODEC0_VSCS_BIT)
00527     GpioPinSetHigh(VSCODEC0_VSCS_PORT, VSCODEC0_VSCS_BIT);
00528     GpioPinConfigSet(VSCODEC0_VSCS_PORT, VSCODEC0_VSCS_BIT, GPIO_CFG_OUTPUT);
00529 #endif
00530 
00531     /* Register the DREQ interrupt routine. */
00532     NutRegisterIrqHandler(&VSCODEC0_DREQ_SIGNAL, VsCodec0Interrupt, &dcbVsCodec0.dcb_feedme);
00533 
00534     /* Rising edge will generate an interrupt. */
00535     GpioPinConfigSet(VSCODEC0_DREQ_PORT, VSCODEC0_DREQ_BIT, GPIO_CFG_DISABLED);
00536     NutIrqSetMode(&VSCODEC0_DREQ_SIGNAL, NUT_IRQMODE_RISINGEDGE);
00537     NutIrqEnable(&VSCODEC0_DREQ_SIGNAL);
00538 
00539     /* Deactivate hardware reset. */
00540     if (VsCodec0ResetHardware(0)) {
00541         /* Probably failed to detect the hardware. */
00542         return -1;
00543     }
00544 
00545     /*
00546     ** Initialize the decoder stream buffer.
00547     */
00548 #ifdef VSCODEC0_OUTPUT_BUFSIZ
00549     avail = VSCODEC0_OUTPUT_BUFSIZ;
00550 #else
00551     avail = NutHeapAvailable() / 2;
00552     if (avail > VSCODEC0_MAX_OUTPUT_BUFSIZ) {
00553         avail = VSCODEC0_MAX_OUTPUT_BUFSIZ;
00554     }
00555 #endif
00556     if (VsDecoderBufferInit(dev, avail)) {
00557         return -1;
00558     }
00559 
00560     /* Start the feeder thread. */
00561     if (NutThreadCreate(dev->dev_name, FeederThread, dev, 
00562         (NUT_THREAD_VSCODEC0STACK * NUT_THREAD_STACK_MULT) + NUT_THREAD_STACK_ADD) == 0) {
00563         return -1;
00564     }
00565     return 0;
00566 }
00567 
00578 NUTDEVICE devSpiVsCodec0 = {
00579     0,                  /* Pointer to next device, dev_next. */
00580     {'a', 'u', 'd', 'i', 'o', '0', 0, 0, 0},    /* Unique device name, dev_name. */
00581     IFTYP_CHAR,         /* Type of device, dev_type. */
00582     0,                  /* Codec number, dev_base. */
00583     0,                  /* First interrupt number, dev_irq (not used). */
00584     &nodeSpiVsCodec0,   /* Interface control block, dev_icb (not used). */
00585     &dcbVsCodec0,       /* Driver control block, dev_dcb. */
00586     VsCodec0Init,       /* Driver initialization routine, dev_init. */
00587     VsCodecIOCtl,       /* Driver specific control function, dev_ioctl. */
00588     NULL,               /* Read from device, dev_read. */
00589     VsCodecWrite,       /* Write to device, dev_write. */
00590 #ifdef __HARVARD_ARCH__
00591     VsCodecWrite_P,     /* Write data from program space to device, dev_write_P. */
00592 #endif
00593     VsCodecOpen,        /* Open a device or file, dev_open. */
00594     VsCodecClose,       /* Close a device or file, dev_close. */
00595     NULL                /* Request file size, dev_size. */
00596 };
00597 
00600 #endif

© 2000-2007 by egnite Software GmbH - visit http://www.ethernut.de/