Nut/OS  4.10.3
API Reference
vs1001k.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2003 by Pavel Chromy. All rights reserved.
00003  * Copyright (C) 2001-2006 by egnite Software GmbH. All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * 1. Redistributions of source code must retain the above copyright
00010  *    notice, this list of conditions and the following disclaimer.
00011  * 2. Redistributions in binary form must reproduce the above copyright
00012  *    notice, this list of conditions and the following disclaimer in the
00013  *    documentation and/or other materials provided with the distribution.
00014  * 3. Neither the name of the copyright holders nor the names of
00015  *    contributors may be used to endorse or promote products derived
00016  *    from this software without specific prior written permission.
00017  *
00018  * THIS SOFTWARE IS PROVIDED BY EGNITE SOFTWARE GMBH AND CONTRIBUTORS
00019  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00020  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00021  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EGNITE
00022  * SOFTWARE GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00023  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00024  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00025  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00026  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00027  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00028  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00029  * SUCH DAMAGE.
00030  *
00031  * For additional information see http://www.ethernut.de/
00032  * -
00033  *
00034  * This software has been inspired by all the valuable work done by
00035  * Jesper Hansen <jesperh@telia.com>. Many thanks for all his help.
00036  */
00037 
00038 /*
00039  * $Log$
00040  * Revision 1.4  2008/08/11 06:59:18  haraldkipp
00041  * BSD types replaced by stdint types (feature request #1282721).
00042  *
00043  * Revision 1.3  2006/05/15 11:46:00  haraldkipp
00044  * Bug corrected, which stopped player on flush. Now flushing plays
00045  * the remaining bytes in the buffer.
00046  * VS1001 ports are now fully configurable.
00047  * Several changes had been added to adapt the code to newer
00048  * Nut/OS style, like replacing outp with outb and using API
00049  * routines for interrupt control.
00050  *
00051  * Revision 1.2  2006/01/23 19:52:10  haraldkipp
00052  * Added required typecasts before left shift.
00053  *
00054  * Revision 1.1  2005/07/26 18:02:40  haraldkipp
00055  * Moved from dev.
00056  *
00057  * Revision 1.3  2004/03/16 16:48:27  haraldkipp
00058  * Added Jan Dubiec's H8/300 port.
00059  *
00060  * Revision 1.2  2003/07/21 18:06:34  haraldkipp
00061  * Buffer function removed. The driver is now using the banked memory routines.
00062  * New functions allows the application to enable/disable decoder interrupts.
00063  *
00064  * Revision 1.1.1.1  2003/05/09 14:40:58  haraldkipp
00065  * Initial using 3.2.1
00066  *
00067  * Revision 1.12  2003/05/06 18:35:21  harald
00068  * ICCAVR port
00069  *
00070  * Revision 1.11  2003/04/21 16:43:54  harald
00071  * Added more comments.
00072  * Avoid initializing static globals to zero.
00073  * New function VsSdiWrite/_P checks DREQ
00074  * Removed decoder interrupt en/disable from low level routines.
00075  * Keep decoder in reset state until ports have been initialized.
00076  * Do not send initial zero bytes as the datasheet recommends.
00077  * A single nop is sufficient delay during reset active.
00078  * Clear interrupt flag after reset to avoid useless interrupt.
00079  * Available buffer size corrected.
00080  * New function to read header information.
00081  * New function invokes decoder memory test.
00082  * Beep makes use of VsSdiWrite.
00083  *
00084  * Revision 1.10  2003/04/18 14:46:08  harald
00085  * Copyright update by the maintainer, after none of the original code had
00086  * been left. We have a clean BSD licence now.
00087  * This release had been prepared by Pavel Chromy.
00088  * BSYNC vs. transfer in progress issue in VsSdiPutByte().
00089  * Fixed possible transfer in progress issue in VsPlayerFeed().
00090  * HW reset may be forced by VS_SM_RESET mode bit
00091  *
00092  * Revision 1.9  2003/04/07 20:29:20  harald
00093  * Redesigned by Pavel Chromy
00094  *
00095  * Revision 1.9  2003/04/04 15:01:00  mac
00096  * VS_STATUS_EMTY is reported correctly.
00097  *
00098  * Revision 1.9  2003/02/14 13:39:00  mac
00099  * Several serious bugs fixed,
00100  * interrupt routine completely remade.
00101  * Unreliable spurious interrupts detection removed.
00102  * Mpeg frame detection removed.
00103  * Watermark check removed (this was rather limiting)
00104  * Can be optionaly compiled not to use SPI
00105  *
00106  * Revision 1.8  2003/02/04 17:50:55  harald
00107  * Version 3 released
00108  *
00109  * Revision 1.7  2003/01/14 16:15:19  harald
00110  * Sending twice the number of zeros to end MP3 stream.
00111  * Check for spurious interrupts to detect hanging chip.
00112  * Simpler portable inline assembler for short delays.
00113  *
00114  * Revision 1.6  2002/11/02 15:15:13  harald
00115  * Library dependencies removed
00116  *
00117  * Revision 1.5  2002/09/15 16:44:14  harald
00118  * *** empty log message ***
00119  *
00120  * Revision 1.4  2002/08/16 17:49:02  harald
00121  * First public release
00122  *
00123  * Revision 1.3  2002/06/26 17:29:08  harald
00124  * First pre-release with 2.4 stack
00125  *
00126  */
00127 
00128 /*
00129  * This header file specifies the hardware port bits. You
00130  * need to change or replace it, if your hardware differs.
00131  */
00132 #include <cfg/arch/avr.h>
00133 
00134 #include <sys/atom.h>
00135 #include <sys/event.h>
00136 #include <sys/timer.h>
00137 #include <sys/heap.h>
00138 
00139 #include <dev/irqreg.h>
00140 #include <dev/vs1001k.h>
00141 
00142 #include <sys/bankmem.h>
00143 
00144 #include <stddef.h> /* NULL definition */
00145 
00150 
00151 #ifndef VS_SCK_BIT
00152 
00158 #define VS_SCK_BIT      0
00159 #endif
00160 
00161 #if !defined(VS_SCK_AVRPORT) || (VS_SCK_AVRPORT == AVRPORTB)
00162 #define VS_SCK_PORT PORTB   
00163 #define VS_SCK_DDR  DDRB    
00164 #elif (VS_SCK_AVRPORT == AVRPORTD)
00165 #define VS_SCK_PORT PORTD
00166 #define VS_SCK_DDR  DDRD
00167 #elif (VS_SCK_AVRPORT == AVRPORTE)
00168 #define VS_SCK_PORT PORTE
00169 #define VS_SCK_DDR  DDRE
00170 #elif (VS_SCK_AVRPORT == AVRPORTF)
00171 #define VS_SCK_PORT PORTF
00172 #define VS_SCK_DDR  DDRF
00173 #else
00174 #warning "Bad SCK port specification"
00175 #endif
00176 
00177 #ifndef VS_SS_BIT
00178 
00181 #define VS_SS_BIT       1       
00182 #endif
00183 
00184 #if !defined(VS_SS_AVRPORT) || (VS_SS_AVRPORT == AVRPORTB)
00185 #define VS_SS_PORT  PORTB   
00186 #define VS_SS_DDR   DDRB    
00187 #elif (VS_SS_AVRPORT == AVRPORTD)
00188 #define VS_SS_PORT  PORTD
00189 #define VS_SS_DDR   DDRD
00190 #elif (VS_SS_AVRPORT == AVRPORTE)
00191 #define VS_SS_PORT  PORTE
00192 #define VS_SS_DDR   DDRE
00193 #elif (VS_SS_AVRPORT == AVRPORTF)
00194 #define VS_SS_PORT  PORTF
00195 #define VS_SS_DDR   DDRF
00196 #else
00197 #warning "Bad SS port specification"
00198 #endif
00199 
00200 #ifndef VS_SI_BIT
00201 
00206 #define VS_SI_BIT       2       
00207 #endif
00208 
00209 #if !defined(VS_SI_AVRPORT) || (VS_SI_AVRPORT == AVRPORTB)
00210 #define VS_SI_PORT  PORTB   
00211 #define VS_SI_DDR   DDRB    
00212 #elif (VS_SI_AVRPORT == AVRPORTD)
00213 #define VS_SI_PORT  PORTD
00214 #define VS_SI_DDR   DDRD
00215 #elif (VS_SI_AVRPORT == AVRPORTE)
00216 #define VS_SI_PORT  PORTE
00217 #define VS_SI_DDR   DDRE
00218 #elif (VS_SI_AVRPORT == AVRPORTF)
00219 #define VS_SI_PORT  PORTF
00220 #define VS_SI_DDR   DDRF
00221 #else
00222 #warning "Bad SI port specification"
00223 #endif
00224 
00225 #ifndef VS_SO_BIT
00226 
00233 #define VS_SO_BIT       3
00234 #endif
00235 
00236 #if !defined(VS_SO_AVRPORT) || (VS_SO_AVRPORT == AVRPORTB)
00237 #define VS_SO_PIN   PINB    
00238 #define VS_SO_DDR   DDRB    
00239 #elif (VS_SO_AVRPORT == AVRPORTD)
00240 #define VS_SO_PIN   PIND
00241 #define VS_SO_DDR   DDRD
00242 #elif (VS_SO_AVRPORT == AVRPORTE)
00243 #define VS_SO_PIN   PINE
00244 #define VS_SO_DDR   DDRE
00245 #elif (VS_SO_AVRPORT == AVRPORTF)
00246 #define VS_SO_PIN   PINF
00247 #define VS_SO_DDR   DDRF
00248 #else
00249 #warning "Bad SO port specification"
00250 #endif
00251 
00252 #ifndef VS_XCS_BIT
00253 
00260 #define VS_XCS_BIT      4
00261 #endif
00262 
00263 #if !defined(VS_XCS_AVRPORT) || (VS_XCS_AVRPORT == AVRPORTB)
00264 #define VS_XCS_PORT PORTB   
00265 #define VS_XCS_DDR  DDRB    
00266 #elif (VS_XCS_AVRPORT == AVRPORTD)
00267 #define VS_XCS_PORT PORTD
00268 #define VS_XCS_DDR  DDRD
00269 #elif (VS_XCS_AVRPORT == AVRPORTE)
00270 #define VS_XCS_PORT PORTE
00271 #define VS_XCS_DDR  DDRE
00272 #elif (VS_XCS_AVRPORT == AVRPORTF)
00273 #define VS_XCS_PORT PORTF
00274 #define VS_XCS_DDR  DDRF
00275 #else
00276 #warning "Bad XCS port specification"
00277 #endif
00278 
00279 #ifndef VS_BSYNC_BIT
00280 
00286 #define VS_BSYNC_BIT    5
00287 #endif
00288 
00289 #if !defined(VS_BSYNC_AVRPORT) || (VS_BSYNC_AVRPORT == AVRPORTB)
00290 #define VS_BSYNC_PORT   PORTB   
00291 #define VS_BSYNC_DDR    DDRB    
00292 #elif (VS_BSYNC_AVRPORT == AVRPORTD)
00293 #define VS_BSYNC_PORT   PORTD
00294 #define VS_BSYNC_DDR    DDRD
00295 #elif (VS_BSYNC_AVRPORT == AVRPORTE)
00296 #define VS_BSYNC_PORT   PORTE
00297 #define VS_BSYNC_DDR    DDRE
00298 #elif (VS_BSYNC_AVRPORT == AVRPORTF)
00299 #define VS_BSYNC_PORT   PORTF
00300 #define VS_BSYNC_DDR    DDRF
00301 #else
00302 #warning "Bad BSYNC port specification"
00303 #endif
00304 
00305 #ifndef VS_RESET_BIT
00306 
00309 #define VS_RESET_BIT    7       
00310 #endif
00311 
00312 #if !defined(VS_RESET_AVRPORT) || (VS_RESET_AVRPORT == AVRPORTB)
00313 #define VS_RESET_PORT   PORTB   
00314 #define VS_RESET_DDR    DDRB    
00315 #elif (VS_RESET_AVRPORT == AVRPORTD)
00316 #define VS_RESET_PORT   PORTD
00317 #define VS_RESET_DDR    DDRD
00318 #elif (VS_RESET_AVRPORT == AVRPORTE)
00319 #define VS_RESET_PORT   PORTE
00320 #define VS_RESET_DDR    DDRE
00321 #elif (VS_RESET_AVRPORT == AVRPORTF)
00322 #define VS_RESET_PORT   PORTF
00323 #define VS_RESET_DDR    DDRF
00324 #else
00325 #warning "Bad RESET port specification"
00326 #endif
00327 
00328 #ifndef VS_SIGNAL_IRQ
00329 
00332 #define VS_SIGNAL       sig_INTERRUPT6
00333 #define VS_DREQ_BIT     6
00334 #define VS_DREQ_PORT    PORTE   
00335 #define VS_DREQ_PIN     PINE    
00336 #define VS_DREQ_DDR     DDRE    
00338 #elif (VS_SIGNAL_IRQ == INT0)
00339 #define VS_SIGNAL       sig_INTERRUPT0
00340 #define VS_DREQ_BIT     0
00341 #define VS_DREQ_PORT    PORTD
00342 #define VS_DREQ_PIN     PIND
00343 #define VS_DREQ_DDR     DDRD
00344 
00345 #elif (VS_SIGNAL_IRQ == INT1)
00346 #define VS_SIGNAL       sig_INTERRUPT1
00347 #define VS_DREQ_BIT     1
00348 #define VS_DREQ_PORT    PORTD
00349 #define VS_DREQ_PIN     PIND
00350 #define VS_DREQ_DDR     DDRD
00351 
00352 #elif (VS_SIGNAL_IRQ == INT2)
00353 #define VS_SIGNAL       sig_INTERRUPT2
00354 #define VS_DREQ_BIT     2
00355 #define VS_DREQ_PORT    PORTD
00356 #define VS_DREQ_PIN     PIND
00357 #define VS_DREQ_DDR     DDRD
00358 
00359 #elif (VS_SIGNAL_IRQ == INT3)
00360 #define VS_SIGNAL       sig_INTERRUPT3
00361 #define VS_DREQ_BIT     3
00362 #define VS_DREQ_PORT    PORTD
00363 #define VS_DREQ_PIN     PIND
00364 #define VS_DREQ_DDR     DDRD
00365 
00366 #elif (VS_SIGNAL_IRQ == INT4)
00367 #define VS_SIGNAL       sig_INTERRUPT4
00368 #define VS_DREQ_BIT     4
00369 #define VS_DREQ_PORT    PORTE
00370 #define VS_DREQ_PIN     PINE
00371 #define VS_DREQ_DDR     DDRE
00372 
00373 #elif (VS_SIGNAL_IRQ == INT5)
00374 #define VS_SIGNAL       sig_INTERRUPT5
00375 #define VS_DREQ_BIT     5
00376 #define VS_DREQ_PORT    PORTE
00377 #define VS_DREQ_PIN     PINE
00378 #define VS_DREQ_DDR     DDRE
00379 
00380 #elif (VS_SIGNAL_IRQ == INT7)
00381 #define VS_SIGNAL       sig_INTERRUPT7
00382 #define VS_DREQ_BIT     7
00383 #define VS_DREQ_PORT    PORTE
00384 #define VS_DREQ_PIN     PINE
00385 #define VS_DREQ_DDR     DDRE
00386 
00387 #else
00388 #warning "Bad interrupt specification"
00389 #endif
00390 
00391 static volatile uint8_t vs_status = VS_STATUS_STOPPED;
00392 static volatile uint16_t vs_flush;
00393 
00394 /*
00395  * \brief Write a byte to the VS1001 data interface.
00396  *
00397  * The caller is responsible for checking the DREQ line. Also make sure,
00398  * that decoder interrupts are disabled.
00399  *
00400  * \param b Byte to be shifted to the decoder's data interface.
00401  */
00402 static INLINE void VsSdiPutByte(uint8_t b)
00403 {
00404 #ifdef VS_NOSPI
00405     uint8_t mask = 0x80;
00406     sbi(VS_BSYNC_PORT, VS_BSYNC_BIT);
00407     while (mask) {
00408         if (b & mask)
00409             sbi(VS_SI_PORT, VS_SI_BIT);
00410         else
00411             cbi(VS_SI_PORT, VS_SI_BIT);
00412 
00413         sbi(VS_SS_PORT, VS_SS_BIT);
00414         mask >>= 1;
00415         cbi(VS_SS_PORT, VS_SS_BIT);
00416         cbi(VS_BSYNC_PORT, VS_BSYNC_BIT);
00417     }
00418 #else
00419     /* Wait for previous SPI transfer to finish. */
00420     loop_until_bit_is_set(SPSR, SPIF);
00421     sbi(VS_BSYNC_PORT, VS_BSYNC_BIT);
00422     outb(SPDR, b);
00423     _NOP();
00424     _NOP();
00425     _NOP();
00426     _NOP();
00427     cbi(VS_BSYNC_PORT, VS_BSYNC_BIT);
00428 #endif
00429 }
00430 
00437 static int VsSdiWrite(CONST uint8_t * data, uint16_t len)
00438 {
00439     uint16_t try = 5000;
00440 
00441     while (len--) {
00442         while (try-- && bit_is_clear(VS_DREQ_PIN, VS_DREQ_BIT));
00443         VsSdiPutByte(*data);
00444         data++;
00445     }
00446     return try ? 0 : -1;
00447 }
00448 
00456 static int VsSdiWrite_P(PGM_P data, uint16_t len)
00457 {
00458     uint16_t try = 5000;
00459 
00460     while (len--) {
00461         while (try-- && bit_is_clear(VS_DREQ_PIN, VS_DREQ_BIT));
00462         VsSdiPutByte(PRG_RDB(data));
00463         data++;
00464     }
00465     return try ? 0 : -1;
00466 }
00467 
00474 static INLINE void VsSciPutByte(uint8_t data)
00475 {
00476     uint8_t mask = 0x80;
00477 
00478     /*
00479      * Loop until all 8 bits are processed.
00480      */
00481     while (mask) {
00482 
00483         /* Set data line. */
00484         if (data & mask)
00485             sbi(VS_SI_PORT, VS_SI_BIT);
00486         else
00487             cbi(VS_SI_PORT, VS_SI_BIT);
00488 
00489         /* Toggle clock and shift mask. */
00490         sbi(VS_SCK_PORT, VS_SCK_BIT);
00491         mask >>= 1;
00492         cbi(VS_SCK_PORT, VS_SCK_BIT);
00493     }
00494 }
00495 
00502 static INLINE uint8_t VsSciGetByte(void)
00503 {
00504     uint8_t mask = 0x80;
00505     uint8_t data = 0;
00506 
00507     /*
00508      * Loop until all 8 bits are processed.
00509      */
00510     while (mask) {
00511         /* Toggle clock and get the data. */
00512         sbi(VS_SCK_PORT, VS_SCK_BIT);
00513         if (bit_is_set(VS_SO_PIN, VS_SO_BIT))
00514             data |= mask;
00515         mask >>= 1;
00516         cbi(VS_SCK_PORT, VS_SCK_BIT);
00517     }
00518     return data;
00519 }
00520 
00526 static void VsRegWrite(uint8_t reg, uint16_t data)
00527 {
00528     /* Select chip. */
00529     cbi(VS_XCS_PORT, VS_XCS_BIT);
00530 
00531 #ifndef VS_NOSPI
00532     /* Disable SPI */
00533     cbi(SPCR, SPE);
00534 #endif
00535 
00536     VsSciPutByte(VS_OPCODE_WRITE);
00537     VsSciPutByte(reg);
00538     VsSciPutByte((uint8_t) (data >> 8));
00539     VsSciPutByte((uint8_t) data);
00540 
00541 #ifndef VS_NOSPI
00542     /* Re-enable SPI. Hint given by Jesper Hansen. */
00543     outb(SPCR, BV(MSTR) | BV(SPE));
00544     outb(SPSR, inb(SPSR));
00545 #endif
00546 
00547     /* Deselect chip. */
00548     sbi(VS_XCS_PORT, VS_XCS_BIT);
00549 }
00550 
00551 /*
00552  * \brief Read from a register.
00553  *
00554  * Decoder interrupts must have been disabled before calling this function.
00555  * 
00556  * \return Register contents.
00557  */
00558 static uint16_t VsRegRead(uint8_t reg)
00559 {
00560     uint16_t data;
00561 
00562     /* Disable interrupts and select chip. */
00563     cbi(VS_XCS_PORT, VS_XCS_BIT);
00564 
00565 #ifndef VS_NOSPI
00566     /* Disable SPI. */
00567     cbi(SPCR, SPE);
00568 #endif
00569 
00570     VsSciPutByte(VS_OPCODE_READ);
00571     VsSciPutByte(reg);
00572     data = (uint16_t)VsSciGetByte() << 8;
00573     data |= VsSciGetByte();
00574 
00575 #ifndef VS_NOSPI
00576     /* Re-enable SPI. Changed due to a hint by Jesper. */
00577     outb(SPCR, BV(MSTR) | BV(SPE));
00578     outb(SPSR, inb(SPSR));
00579 #endif
00580 
00581     /* Deselect chip and enable interrupts. */
00582     sbi(VS_XCS_PORT, VS_XCS_BIT);
00583 
00584     return data;
00585 }
00586 
00598 uint8_t VsPlayerInterrupts(uint8_t enable)
00599 {
00600     static uint8_t is_enabled = 0;
00601     uint8_t rc;
00602 
00603     rc = is_enabled;
00604     if(enable) {
00605         NutIrqEnable(&VS_SIGNAL);
00606     }
00607     else {
00608         NutIrqDisable(&VS_SIGNAL);
00609     }
00610     is_enabled = enable;
00611 
00612     return rc;
00613 }
00614 
00615 /*
00616  * \brief Feed the decoder with data.
00617  *
00618  * This function serves two purposes: 
00619  * - It is called by VsPlayerKick() to initially fill the decoder buffer.
00620  * - It is used as an interrupt handler for the decoder.
00621  */
00622 static void VsPlayerFeed(void *arg)
00623 {
00624     uint8_t ief;
00625     uint8_t j = 32;
00626     size_t total = 0;
00627 
00628     if (bit_is_clear(VS_DREQ_PIN, VS_DREQ_BIT)) {
00629         return;
00630     }
00631 
00632     /*
00633      * We are hanging around here some time and may block other important
00634      * interrupts. Disable decoder interrupts and enable global interrupts.
00635      */
00636     ief = VsPlayerInterrupts(0);
00637     sei();
00638 
00639     /* 
00640      * Feed the decoder until its buffer is full or we ran out of data.
00641      */
00642     if (vs_status == VS_STATUS_RUNNING) {
00643         char *bp = 0;
00644         size_t consumed = 0;
00645         size_t available = 0;
00646         do {
00647             if(consumed >= available) {
00648                 /* Commit previously consumed bytes. */
00649                 if(consumed) {
00650                     NutSegBufReadCommit(consumed);
00651                     consumed = 0;
00652                 }
00653                 /* All bytes consumed, request new. */
00654                 bp = NutSegBufReadRequest(&available);
00655                 if(available == 0) {
00656                     /* End of stream. */
00657                     vs_status = VS_STATUS_EOF;
00658                     break;
00659                 }
00660             }
00661             /* We have some data in the buffer, feed it. */
00662             VsSdiPutByte(*bp);
00663             bp++;
00664             consumed++;
00665             total++;
00666             if (total > 4096) {
00667                 vs_status = VS_STATUS_EOF;
00668                 break;
00669             }
00670 
00671             /* Allow 32 bytes to be sent as long as DREQ is set, This includes
00672                the one in progress. */
00673             if (bit_is_set(VS_DREQ_PIN, VS_DREQ_BIT))
00674                 j = 32;
00675         } while(j--);
00676 
00677         /* Finally re-enable the producer buffer. */
00678         NutSegBufReadLast(consumed);
00679     }
00680 
00681     /* 
00682      * Flush the internal VS buffer. 
00683      */
00684     if(vs_status != VS_STATUS_RUNNING && vs_flush) {
00685         do {
00686             VsSdiPutByte(0);
00687             if (--vs_flush == 0) {
00688                 /* Decoder internal buffer is flushed. */
00689                 vs_status = VS_STATUS_EMPTY;
00690                 break;
00691             }
00692             /* Allow 32 bytes to be sent as long as DREQ is set, This includes
00693                the one in progress. */
00694             if (bit_is_set(VS_DREQ_PIN, VS_DREQ_BIT))
00695                 j = 32;
00696         } while(j--);
00697     }
00698     VsPlayerInterrupts(ief);
00699 }
00700 
00712 int VsPlayerKick(void)
00713 {
00714     /*
00715      * Start feeding the decoder with data.
00716      */
00717     VsPlayerInterrupts(0);
00718     vs_status = VS_STATUS_RUNNING;
00719     VsPlayerFeed(NULL);
00720     VsPlayerInterrupts(1);
00721 
00722     return 0;
00723 }
00724 
00733 int VsPlayerStop(void)
00734 {
00735     uint8_t ief;
00736 
00737     ief = VsPlayerInterrupts(0);
00738     /* Check whether we need to stop at all to not overwrite other than running status */
00739     if (vs_status == VS_STATUS_RUNNING) {
00740         vs_status = VS_STATUS_STOPPED;
00741     }
00742     VsPlayerInterrupts(ief);
00743 
00744     return 0;
00745 }
00746 
00747 
00760 int VsPlayerFlush(void)
00761 {
00762     VsPlayerInterrupts(0);
00763     /* Set up fluhing unless both buffers are empty. */
00764     if (vs_status != VS_STATUS_EMPTY || NutSegBufUsed()) {
00765         if (vs_flush == 0)
00766             vs_flush = VS_FLUSH_BYTES;
00767         /* start the playback if necessary */
00768         if (vs_status != VS_STATUS_RUNNING)
00769             VsPlayerKick();
00770     }
00771     VsPlayerInterrupts(1);
00772     return 0;
00773 }
00774 
00775 
00781 int VsPlayerInit(void)
00782 {
00783     /* Disable decoder interrupts. */
00784     VsPlayerInterrupts(0);
00785 
00786     /* Keep decoder in reset state. */
00787     cbi(VS_RESET_PORT, VS_RESET_BIT);
00788     sbi(VS_RESET_DDR, VS_RESET_BIT);
00789 
00790     /* Set BSYNC output low. */
00791     cbi(VS_BSYNC_PORT, VS_BSYNC_BIT);
00792     sbi(VS_BSYNC_DDR, VS_BSYNC_BIT);
00793 
00794     /* Set MP3 chip select output low. */
00795     sbi(VS_XCS_PORT, VS_XCS_BIT);
00796     sbi(VS_XCS_DDR, VS_XCS_BIT);
00797 
00798     /* Set DREQ input with pullup. */
00799     sbi(VS_DREQ_PORT, VS_DREQ_BIT);
00800     cbi(VS_DREQ_DDR, VS_DREQ_BIT);
00801 
00802     /* Init SPI Port. */
00803     sbi(VS_SI_DDR, VS_SI_BIT);
00804     sbi(VS_SS_DDR, VS_SS_BIT);
00805     cbi(VS_SO_DDR, VS_SO_BIT);
00806 
00807     /* Set SCK output low. */
00808     cbi(VS_SCK_PORT, VS_SCK_BIT);
00809     sbi(VS_SCK_DDR, VS_SCK_BIT);
00810 
00811 #ifndef VS_NOSPI
00812     {
00813         uint8_t dummy;           /* Required by some compilers. */
00814 
00815         /* 
00816          * Init SPI mode to no interrupts, enabled, MSB first, master mode, 
00817          * rising clock and fosc/4 clock speed. Send an initial zero byte to 
00818          * make sure SPIF is set. Note, that the decoder reset line is still
00819          * active.
00820          */
00821         outb(SPCR, BV(MSTR) | BV(SPE));
00822         dummy = inb(SPSR);
00823         outb(SPDR, 0);
00824     }
00825 #endif
00826 
00827     /* Register the interrupt routine */
00828     if (NutRegisterIrqHandler(&VS_SIGNAL, VsPlayerFeed, NULL)) {
00829         return -1;
00830     }
00831 
00832     /* Rising edge will generate interrupts. */
00833     NutIrqSetMode(&VS_SIGNAL, NUT_IRQMODE_RISINGEDGE);
00834 
00835     /* Release decoder reset line. */
00836     sbi(VS_RESET_PORT, VS_RESET_BIT);
00837     NutDelay(4);
00838 
00839     /* Force frequency change (see datasheet). */
00840     VsRegWrite(VS_CLOCKF_REG, 0x9800);
00841     VsRegWrite(VS_INT_FCTLH_REG, 0x8008);
00842     NutDelay(200);
00843 
00844     /* Clear any spurious interrupt. */
00845     outb(EIFR, BV(VS_DREQ_BIT));
00846 
00847     return 0;
00848 }
00849 
00865 int VsPlayerReset(uint16_t mode)
00866 {
00867     /* Disable decoder interrupts and feeding. */
00868     VsPlayerInterrupts(0);
00869     vs_status = VS_STATUS_STOPPED;
00870 
00871     /* Software reset, set modes of decoder. */
00872     VsRegWrite(VS_MODE_REG, VS_SM_RESET | mode);
00873     NutDelay(2);
00874 
00875     /*
00876      * Check for correct reset.
00877      */
00878     if ((mode & VS_SM_RESET) != 0 || bit_is_clear(VS_DREQ_PIN, VS_DREQ_BIT)) {
00879         /* If not succeeded, give it one more chance and try hw reset,
00880            HW reset may also be forced by VS_SM_RESET mode bit. */
00881         cbi(VS_RESET_PORT, VS_RESET_BIT);
00882         _NOP();
00883         sbi(VS_RESET_PORT, VS_RESET_BIT);
00884         NutDelay(4);
00885 
00886         /* Set the requested modes. */
00887         VsRegWrite(VS_MODE_REG, VS_SM_RESET | mode);
00888         NutDelay(2);
00889         if (bit_is_clear(VS_DREQ_PIN, VS_DREQ_BIT))
00890             return -1;
00891     }
00892 
00893     /* Force frequency change (see datasheet). */
00894     VsRegWrite(VS_CLOCKF_REG, 0x9800);
00895     VsRegWrite(VS_INT_FCTLH_REG, 0x8008);
00896     NutDelay(2);
00897 
00898     /* Clear any spurious interrupts. */
00899     outb(EIFR, BV(VS_DREQ_BIT));
00900 
00901     return 0;
00902 }
00903 
00916 int VsPlayerSetMode(uint16_t mode)
00917 {
00918     uint8_t ief;
00919     
00920     ief = VsPlayerInterrupts(0);
00921     VsRegWrite(VS_MODE_REG, mode);
00922     VsPlayerInterrupts(ief);
00923 
00924     return 0;
00925 }
00926 
00932 uint16_t VsPlayTime(void)
00933 {
00934     uint16_t rc;
00935     uint8_t ief;
00936 
00937     ief = VsPlayerInterrupts(0);
00938     rc = VsRegRead(VS_DECODE_TIME_REG);
00939     VsPlayerInterrupts(ief);
00940 
00941     return rc;
00942 }
00943 
00953 uint8_t VsGetStatus(void)
00954 {
00955     return vs_status;
00956 }
00957 
00958 #ifdef __GNUC__
00959 
00967 int VsGetHeaderInfo(VS_HEADERINFO * vshi)
00968 {
00969     uint16_t *usp = (uint16_t *) vshi;
00970     uint8_t ief;
00971 
00972     ief = VsPlayerInterrupts(0);
00973     *usp = VsRegRead(VS_HDAT1_REG);
00974     *++usp = VsRegRead(VS_HDAT0_REG);
00975     VsPlayerInterrupts(ief);
00976 
00977     return 0;
00978 }
00979 #endif
00980 
00993 uint16_t VsMemoryTest(void)
00994 {
00995     uint16_t rc;
00996     uint8_t ief;
00997     static prog_char mtcmd[] = { 0x4D, 0xEA, 0x6D, 0x54, 0x00, 0x00, 0x00, 0x00 };
00998 
00999     ief = VsPlayerInterrupts(0);
01000     VsSdiWrite_P(mtcmd, sizeof(mtcmd));
01001     NutDelay(40);
01002     rc = VsRegRead(VS_HDAT0_REG);
01003     VsPlayerInterrupts(ief);
01004 
01005     return rc;
01006 }
01007 
01016 int VsSetVolume(uint8_t left, uint8_t right)
01017 {
01018     uint8_t ief;
01019 
01020     ief = VsPlayerInterrupts(0);
01021     VsRegWrite(VS_VOL_REG, (((uint16_t) left) << 8) | (uint16_t) right);
01022     VsPlayerInterrupts(ief);
01023 
01024     return 0;
01025 }
01026 
01035 int VsBeep(uint8_t fsin, uint8_t ms)
01036 {
01037     uint8_t ief;
01038     static prog_char on[] = { 0x53, 0xEF, 0x6E };
01039     static prog_char off[] = { 0x45, 0x78, 0x69, 0x74 };
01040     static prog_char end[] = { 0x00, 0x00, 0x00, 0x00 };
01041 
01042     /* Disable decoder interrupts. */
01043     ief = VsPlayerInterrupts(0);
01044 
01045     fsin = 56 + (fsin & 7) * 9;
01046     VsSdiWrite_P(on, sizeof(on));
01047     VsSdiWrite(&fsin, 1);
01048     VsSdiWrite_P(end, sizeof(end));
01049     NutDelay(ms);
01050     VsSdiWrite_P(off, sizeof(off));
01051     VsSdiWrite_P(end, sizeof(end));
01052 
01053     /* Enable decoder interrupts. */
01054     VsPlayerInterrupts(ief);
01055 
01056     return 0;
01057 }
01058 
01059