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 2565 2009-03-27 17:26:15Z 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 #else
00324         (*nodeSpiVsCodec0.node_bus->bus_set_rate) (&nodeSpiVsCodec0, xtal / 3);
00325 #endif
00326     }
00327     return rc;
00328 }
00329 
00341 static int VsCodec0Detect(void)
00342 {
00343     int rc = -1;
00344     uint_fast16_t status;
00345 
00346     /* While the VS1053B works fine on the EIR board, we still need
00347     ** a dummy read on the Ethernut 2.1B with Medianut 2. TODO: Why? */
00348     status = VsCodecReg(&devSpiVsCodec0, VS_OPCODE_READ, VS_STATUS_REG, 0);
00349     status = VsCodecReg(&devSpiVsCodec0, VS_OPCODE_READ, VS_STATUS_REG, 0);
00350 
00351     /*
00352     ** Verify the hardware if chip is pre-configured.
00353     */
00354 #if defined(AUDIO0_VS1001K)
00355     if ((status & VS_SS_VER) == (VS1001_SS_VER << VS_SS_VER_LSB)) {
00356         dcbVsCodec0.dcb_codec_ver = 1001;
00357         dcbVsCodec0.dcb_codec_rev = 'K';
00358         rc = 0;
00359     }
00360 #elif defined(AUDIO0_VS1011E)
00361     if ((status & VS_SS_VER) == (VS1011E_SS_VER << VS_SS_VER_LSB)) {
00362         dcbVsCodec0.dcb_codec_ver = 1011;
00363         dcbVsCodec0.dcb_codec_rev = 'E';
00364         rc = 0;
00365     }
00366 #elif defined(AUDIO0_VS1002D)
00367     if ((status & VS_SS_VER) == (VS1002_SS_VER << VS_SS_VER_LSB)) {
00368         dcbVsCodec0.dcb_codec_ver = 1002;
00369         dcbVsCodec0.dcb_codec_rev = 'D';
00370         rc = 0;
00371     }
00372 #elif defined(AUDIO0_VS1003B)
00373     if ((status & VS_SS_VER) == (VS1003_SS_VER << VS_SS_VER_LSB)) {
00374         dcbVsCodec0.dcb_codec_ver = 1003;
00375         dcbVsCodec0.dcb_codec_rev = 'B';
00376         rc = 0;
00377     }
00378 #elif defined(AUDIO0_VS1033C)
00379     if ((status & VS_SS_VER) == (VS1033_SS_VER << VS_SS_VER_LSB)) {
00380         dcbVsCodec0.dcb_codec_ver = 1033;
00381         dcbVsCodec0.dcb_codec_rev = 'C';
00382         rc = 0;
00383     }
00384 #elif defined(AUDIO0_VS1053B)
00385     if ((status & VS_SS_VER) == (VS1053_SS_VER << VS_SS_VER_LSB)) {
00386         dcbVsCodec0.dcb_codec_ver = 1053;
00387         dcbVsCodec0.dcb_codec_rev = 'B';
00388         rc = 0;
00389     }
00390 #else
00391     /*
00392     ** If not configured, try to figure it out.
00393     */
00394     rc = 0;
00395     switch ((status & VS_SS_VER) >> VS_SS_VER_LSB) {
00396     case VS1001_SS_VER:
00397         dcbVsCodec0.dcb_codec_ver = 1001;
00398         break;
00399     case VS1011_SS_VER:
00400         dcbVsCodec0.dcb_codec_ver = 1011;
00401         break;
00402     case VS1002_SS_VER:
00403         if (VsCodecReg(&devSpiVsCodec0, VS_OPCODE_READ, VS_MODE_REG, 0) & VS_SM_SDINEW) {
00404             dcbVsCodec0.dcb_codec_ver = 1002;
00405         } else {
00406             dcbVsCodec0.dcb_codec_ver = 1011;
00407             dcbVsCodec0.dcb_codec_rev = 'E';
00408         }
00409         break;
00410     case VS1003_SS_VER:
00411         dcbVsCodec0.dcb_codec_ver = 1003;
00412         break;
00413     case VS1053_SS_VER:
00414         dcbVsCodec0.dcb_codec_ver = 1053;
00415         break;
00416     case VS1033_SS_VER:
00417         dcbVsCodec0.dcb_codec_ver = 1033;
00418         break;
00419     case VS1103_SS_VER:
00420         dcbVsCodec0.dcb_codec_ver = 1103;
00421         break;
00422     default:
00423         rc = -1;
00424         break;
00425     }
00426 #endif
00427     return rc;
00428 }
00429 
00441 static int VsCodec0ResetHardware(int on)
00442 {
00443     if (on) {
00444         /*
00445         ** Activate reset.
00446         */
00447 #if defined(VSCODEC0_XRESET_PORT) && defined(VSCODEC0_XRESET_BIT)
00448         /* Activate the reset line. */
00449         GpioPinSetLow(VSCODEC0_XRESET_PORT, VSCODEC0_XRESET_BIT);
00450         GpioPinConfigSet(VSCODEC0_XRESET_PORT, VSCODEC0_XRESET_BIT, GPIO_CFG_OUTPUT);
00451         NutSleep(VSCODEC0_HWRST_DURATION);
00452 #else
00453         return -1;
00454 #endif
00455     } else {
00456         /*
00457         ** Deactivate reset.
00458         */
00459         uint_fast8_t clkset = 0;
00460 
00461 #if defined(VSCODEC0_XRESET_PORT) && defined(VSCODEC0_XRESET_BIT)
00462         /* Release the reset line. */
00463         GpioPinSetHigh(VSCODEC0_XRESET_PORT, VSCODEC0_XRESET_BIT);
00464 #if VSCODEC0_FREQ >= 24000000UL
00465         /* With input clocks equal or above 24MHz we must set CLOCKF early 
00466         ** and must not wait for rising DREQ. */
00467         csrc = VsCodec0SetClock(VSCODEC0_FREQ, 0) == 0;
00468 #endif /* VSCODEC0_FREQ */
00469 #endif /* VSCODEC0_XRESET_PORT */
00470 
00471 #if VSCODEC0_HWRST_RECOVER
00472         /* Optional delay after hardware reset. */
00473         NutSleep(VSCODEC0_HWRST_RECOVER);
00474 #endif
00475         /* Chip hardware detection. */
00476         if (VsCodec0Detect()) {
00477             return -1;
00478         }
00479 #if !defined(AUDIO0_VS1001K)
00480         if (dcbVsCodec0.dcb_codec_ver != 1001) {
00481 #if VS_HAS_SM_SDINEW
00482 #if defined(VSCODEC0_XDCS_PORT) && defined(VSCODEC0_XDCS_BIT)
00483             VsCodecMode(&devSpiVsCodec0, VS_SM_SDINEW, VS_SM_SDINEW);
00484 #else
00485             VsCodecMode(&devSpiVsCodec0, VS_SM_SDINEW | VS_SM_SDISHARE, VS_SM_SDINEW | VS_SM_SDISHARE);
00486 #endif
00487 #endif /* VS_HAS_SM_SDINEW */
00488         }
00489 #endif /* AUDIO0_VS1001K */
00490 
00491         /* Set clock now, if not done successfully before. */
00492         if (!clkset) {
00493             VsCodec0SetClock(VSCODEC0_FREQ, 1);
00494         }
00495     }
00496     return 0;
00497 }
00498 
00499 
00500 /*
00501  * Called via dev_init pointer when the device is registered.
00502  *
00503  * \param dev Specifies the audio codec device.
00504  *
00505  * \return 0 on success, -1 otherwise.
00506  */
00507 static int VsCodec0Init(NUTDEVICE * dev)
00508 {
00509     size_t avail;
00510 
00511     /* Set function pointers. */
00512     dcbVsCodec0.dcb_isready = VsCodec0IsReady;
00513     dcbVsCodec0.dcb_sendcmd = VsCodec0SendCmd;
00514     dcbVsCodec0.dcb_senddata = VsCodec0SendData;
00515 
00516     /* Activate hardware reset. */
00517     VsCodec0ResetHardware(1);
00518 
00519     /* Initialize DREQ input. Will be later used as an external interupt. */
00520     GpioPinConfigSet(VSCODEC0_DREQ_PORT, VSCODEC0_DREQ_BIT, 0);
00521     /* Initialize chip selects, XCS and optional XDCS. */
00522     GpioPinSetHigh(VSCODEC0_XCS_PORT, VSCODEC0_XCS_BIT);
00523     GpioPinConfigSet(VSCODEC0_XCS_PORT, VSCODEC0_XCS_BIT, GPIO_CFG_OUTPUT);
00524 #if defined(VSCODEC0_XDCS_PORT) && defined(VSCODEC0_XDCS_BIT)
00525     GpioPinSetHigh(VSCODEC0_XDCS_PORT, VSCODEC0_XDCS_BIT);
00526     GpioPinConfigSet(VSCODEC0_XDCS_PORT, VSCODEC0_XDCS_BIT, GPIO_CFG_OUTPUT);
00527 #endif
00528 #if defined(VSCODEC0_VSCS_PORT) && defined(VSCODEC0_VSCS_BIT)
00529     GpioPinSetHigh(VSCODEC0_VSCS_PORT, VSCODEC0_VSCS_BIT);
00530     GpioPinConfigSet(VSCODEC0_VSCS_PORT, VSCODEC0_VSCS_BIT, GPIO_CFG_OUTPUT);
00531 #endif
00532 
00533     /* Register the DREQ interrupt routine. */
00534     NutRegisterIrqHandler(&VSCODEC0_DREQ_SIGNAL, VsCodec0Interrupt, &dcbVsCodec0.dcb_feedme);
00535 
00536     /* Rising edge will generate an interrupt. */
00537     GpioPinConfigSet(VSCODEC0_DREQ_PORT, VSCODEC0_DREQ_BIT, GPIO_CFG_DISABLED);
00538     NutIrqSetMode(&VSCODEC0_DREQ_SIGNAL, NUT_IRQMODE_RISINGEDGE);
00539     NutIrqEnable(&VSCODEC0_DREQ_SIGNAL);
00540 
00541     /* Deactivate hardware reset. */
00542     if (VsCodec0ResetHardware(0)) {
00543         /* Probably failed to detect the hardware. */
00544         return -1;
00545     }
00546 
00547     /*
00548     ** Initialize the decoder stream buffer.
00549     */
00550 #ifdef VSCODEC0_OUTPUT_BUFSIZ
00551     avail = VSCODEC0_OUTPUT_BUFSIZ;
00552 #else
00553     avail = NutHeapAvailable() / 2;
00554     if (avail > VSCODEC0_MAX_OUTPUT_BUFSIZ) {
00555         avail = VSCODEC0_MAX_OUTPUT_BUFSIZ;
00556     }
00557 #endif
00558     if (VsDecoderBufferInit(dev, avail)) {
00559         return -1;
00560     }
00561 
00562     /* Start the feeder thread. */
00563     if (NutThreadCreate(dev->dev_name, FeederThread, dev, 
00564         (NUT_THREAD_VSCODEC0STACK * NUT_THREAD_STACK_MULT) + NUT_THREAD_STACK_ADD) == 0) {
00565         return -1;
00566     }
00567     return 0;
00568 }
00569 
00580 NUTDEVICE devSpiVsCodec0 = {
00581     0,                  /* Pointer to next device, dev_next. */
00582     {'a', 'u', 'd', 'i', 'o', '0', 0, 0, 0},    /* Unique device name, dev_name. */
00583     IFTYP_CHAR,         /* Type of device, dev_type. */
00584     0,                  /* Codec number, dev_base. */
00585     0,                  /* First interrupt number, dev_irq (not used). */
00586     &nodeSpiVsCodec0,   /* Interface control block, dev_icb (not used). */
00587     &dcbVsCodec0,       /* Driver control block, dev_dcb. */
00588     VsCodec0Init,       /* Driver initialization routine, dev_init. */
00589     VsCodecIOCtl,       /* Driver specific control function, dev_ioctl. */
00590     NULL,               /* Read from device, dev_read. */
00591     VsCodecWrite,       /* Write to device, dev_write. */
00592 #ifdef __HARVARD_ARCH__
00593     VsCodecWrite_P,     /* Write data from program space to device, dev_write_P. */
00594 #endif
00595     VsCodecOpen,        /* Open a device or file, dev_open. */
00596     VsCodecClose,       /* Close a device or file, dev_close. */
00597     NULL                /* Request file size, dev_size. */
00598 };
00599 
00602 #endif

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