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

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