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 2634 2009-07-22 09:27:03Z 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_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 /* avr-gcc optimized code used 88 bytes. */
00076 #define NUT_THREAD_VSCODEC0STACK    128
00077 #else
00078 /* icc-avr stack usage is unknown. */
00079 #define NUT_THREAD_VSCODEC0STACK    384
00080 #endif
00081 #else
00082 /* arm-elf-gcc optimized code used 112 bytes. */
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  * Determine interrupt settings.
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  * VLSI codec 0 interrupt handler.
00154  *
00155  * \param arg Pointer to an event queue.
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  * \brief Write to command channel of codec 0.
00174  *
00175  * This routine will not check the DREQ line.
00176  *
00177  * \param cmd  Points to the buffer. On entry it contains the data to 
00178  *             send. On exit it will contain the data received from
00179  *             the chip.
00180  * \param len  Number of bytes to send and receive.
00181  */
00182 static int VsCodec0SendCmd(void *cmd, size_t len)
00183 {
00184     int rc;
00185 
00186     /* Allocate the SPI bus. */
00187     rc = (*nodeSpiVsCodec0.node_bus->bus_alloc) (&nodeSpiVsCodec0, VSCODEC0_SPIBUS_WAIT);
00188     if (rc == 0) {
00189         /* Activate chip selects. */
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         /* Send command bytes and receive response. */
00195         rc = (*nodeSpiVsCodec0.node_bus->bus_transfer) (&nodeSpiVsCodec0, cmd, cmd, len);
00196         /* Dectivate chip selects. */
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         /* Release the SPI bus. */
00202         (*nodeSpiVsCodec0.node_bus->bus_release) (&nodeSpiVsCodec0);
00203     }
00204     return rc;
00205 }
00206 
00207 /*
00208  * \brief Write data to the decoder.
00209  *
00210  * Data is sent in fixed chunks. The first one is sent without
00211  * checking the DREQ line. Any subsequent chunk is sent only if
00212  * the DREQ line is still high.
00213  *
00214  * \param node Specifies the SPI node.
00215  * \param buf  Points to the data. May be NULL, in which case the routine
00216  *             will send the specified number of zeros.
00217  * \param len  Number of bytes to send.
00218  *
00219  * \return The number of bytes actually sent. This may be less than the
00220  *         specified data length. Zero is returned in case of an error.
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     /* Allocate the SPI bus. */
00229     if ((*nodeSpiVsCodec0.node_bus->bus_alloc) (&nodeSpiVsCodec0, VSCODEC0_SPIBUS_WAIT) == 0) {
00230 #if defined(VSCODEC0_VSCS_PORT) && defined(VSCODEC0_VSCS_BIT)
00231         /* Activate optional VSCS line. */
00232         GpioPinSetLow(VSCODEC0_VSCS_PORT, VSCODEC0_VSCS_BIT);
00233 #endif
00234 #if defined(VSCODEC0_XDCS_PORT) && defined(VSCODEC0_XDCS_BIT)
00235         /* Activate optional XDCS line. */
00236         GpioPinSetLow(VSCODEC0_XDCS_PORT, VSCODEC0_XDCS_BIT);
00237 #endif
00238         /* Set our internal buffer pointer, either to the start of the 
00239         ** encoded data or to a chunk of zeros. */
00240         bp = buf ? buf : zero_chunk;
00241         /* Loop until all data had been sent or DREQ goes low. */
00242         while (len) {
00243             /* Determine chunk size. */
00244             chunk = len > VSCODEC_DATA_CHUNK_SIZE ? VSCODEC_DATA_CHUNK_SIZE : len;
00245             /* Send the chunk, exit on errors. */
00246             if ((*nodeSpiVsCodec0.node_bus->bus_transfer) (&nodeSpiVsCodec0, bp, NULL, chunk)) {
00247                 break;
00248             }
00249             /* Update function result. */
00250             rc += chunk;
00251             /* Check if decoder is ready for more. Exit, if not. */
00252             if (!VsCodec0IsReady()) {
00253                 break;
00254             }
00255             /* Update remaining number of bytes and buffer pointer. */
00256             len -= chunk;
00257             if (buf) {
00258                 bp += chunk;
00259             }
00260         }
00261 #if defined(VSCODEC0_XDCS_PORT) && defined(VSCODEC0_XDCS_BIT)
00262         /* Deactivate optional XDCS line. */
00263         GpioPinSetHigh(VSCODEC0_XDCS_PORT, VSCODEC0_XDCS_BIT);
00264 #endif
00265 #if defined(VSCODEC0_VSCS_PORT) && defined(VSCODEC0_VSCS_BIT)
00266         /* Deactivate optional VSCS line. */
00267         GpioPinSetHigh(VSCODEC0_VSCS_PORT, VSCODEC0_VSCS_BIT);
00268 #endif
00269         /* Release the SPI bus. */
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     /* This hardware got the new CLOCKF register layout. */
00293     if (dreq) {
00294         /* Honor the DREQ line, if requested. */
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     /* Old hardware, requires clock doubler with lower frequence crystal. */
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     /* Force frequency change (see VS1001 datasheet). */
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     /* With higher clock we can increase the SPI rate. */
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     /* While the VS1053B works fine on the EIR board, we still need
00352     ** a dummy read on the Ethernut 2.1B with Medianut 2. TODO: Why? */
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     ** Verify the hardware if chip is pre-configured.
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     ** If not configured, try to figure it out.
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         ** Activate reset.
00451         */
00452 #if defined(VSCODEC0_XRESET_PORT) && defined(VSCODEC0_XRESET_BIT)
00453         /* Activate the reset line. */
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         ** Deactivate reset.
00463         */
00464         uint_fast8_t clkset = 0;
00465 
00466 #if defined(VSCODEC0_XRESET_PORT) && defined(VSCODEC0_XRESET_BIT)
00467         /* Release the reset line. */
00468         GpioPinSetHigh(VSCODEC0_XRESET_PORT, VSCODEC0_XRESET_BIT);
00469 #if VSCODEC0_FREQ >= 24000000UL
00470         /* With input clocks equal or above 24MHz we must set CLOCKF early 
00471         ** and must not wait for rising DREQ. */
00472         csrc = VsCodec0SetClock(VSCODEC0_FREQ, 0) == 0;
00473 #endif /* VSCODEC0_FREQ */
00474 #endif /* VSCODEC0_XRESET_PORT */
00475 
00476 #if VSCODEC0_HWRST_RECOVER
00477         /* Optional delay after hardware reset. */
00478         NutSleep(VSCODEC0_HWRST_RECOVER);
00479 #endif
00480         /* Chip hardware detection. */
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 /* VS_HAS_SM_SDINEW */
00493         }
00494 #endif /* AUDIO0_VS1001K */
00495 
00496         /* Set clock now, if not done successfully before. */
00497         if (!clkset) {
00498             VsCodec0SetClock(VSCODEC0_FREQ, 1);
00499         }
00500     }
00501     return 0;
00502 }
00503 
00504 
00505 /*
00506  * Called via dev_init pointer when the device is registered.
00507  *
00508  * \param dev Specifies the audio codec device.
00509  *
00510  * \return 0 on success, -1 otherwise.
00511  */
00512 static int VsCodec0Init(NUTDEVICE * dev)
00513 {
00514     size_t avail;
00515 
00516     /* Set function pointers. */
00517     dcbVsCodec0.dcb_isready = VsCodec0IsReady;
00518     dcbVsCodec0.dcb_sendcmd = VsCodec0SendCmd;
00519     dcbVsCodec0.dcb_senddata = VsCodec0SendData;
00520 
00521     /* Activate hardware reset. */
00522     VsCodec0ResetHardware(1);
00523 
00524     /* Initialize DREQ input. Will be later used as an external interupt. */
00525     GpioPinConfigSet(VSCODEC0_DREQ_PORT, VSCODEC0_DREQ_BIT, 0);
00526     /* Initialize chip selects, XCS and optional XDCS. */
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     /* Register the DREQ interrupt routine. */
00539     NutRegisterIrqHandler(&VSCODEC0_DREQ_SIGNAL, VsCodec0Interrupt, &dcbVsCodec0.dcb_feedme);
00540 
00541     /* Rising edge will generate an interrupt. */
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     /* Deactivate hardware reset. */
00547     if (VsCodec0ResetHardware(0)) {
00548         /* Probably failed to detect the hardware. */
00549         return -1;
00550     }
00551 
00552     /*
00553     ** Initialize the decoder stream buffer.
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     /* Start the feeder thread. */
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,                  /* Pointer to next device, dev_next. */
00587     {'a', 'u', 'd', 'i', 'o', '0', 0, 0, 0},    /* Unique device name, dev_name. */
00588     IFTYP_CHAR,         /* Type of device, dev_type. */
00589     0,                  /* Codec number, dev_base. */
00590     0,                  /* First interrupt number, dev_irq (not used). */
00591     &nodeSpiVsCodec0,   /* Interface control block, dev_icb (not used). */
00592     &dcbVsCodec0,       /* Driver control block, dev_dcb. */
00593     VsCodec0Init,       /* Driver initialization routine, dev_init. */
00594     VsCodecIOCtl,       /* Driver specific control function, dev_ioctl. */
00595     NULL,               /* Read from device, dev_read. */
00596     VsCodecWrite,       /* Write to device, dev_write. */
00597 #ifdef __HARVARD_ARCH__
00598     VsCodecWrite_P,     /* Write data from program space to device, dev_write_P. */
00599 #endif
00600     VsCodecOpen,        /* Open a device or file, dev_open. */
00601     VsCodecClose,       /* Close a device or file, dev_close. */
00602     NULL                /* Request file size, dev_size. */
00603 };
00604 
00607 #endif

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