⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vs1001k.c

📁 含有完整TCP/IP PPP协议的嵌入式操作系统
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (C) 2003 by Pavel Chromy. All rights reserved. * Copyright (C) 2001-2003 by egnite Software GmbH. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor the names of *    contributors may be used to endorse or promote products derived *    from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY EGNITE SOFTWARE GMBH AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EGNITE * SOFTWARE GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * For additional information see http://www.ethernut.de/ * - * * This software has been inspired by all the valuable work done by * Jesper Hansen <jesperh@telia.com>. Many thanks for all his help. *//* * $Log: vs1001k.c,v $ * Revision 1.1  2003/07/21 18:09:51  haraldkipp * Backup of old driver * * Revision 1.1.1.1  2003/05/09 14:40:58  haraldkipp * Initial using 3.2.1 * * Revision 1.12  2003/05/06 18:35:21  harald * ICCAVR port * * Revision 1.11  2003/04/21 16:43:54  harald * Added more comments. * Avoid initializing static globals to zero. * New function VsSdiWrite/_P checks DREQ * Removed decoder interrupt en/disable from low level routines. * Keep decoder in reset state until ports have been initialized. * Do not send initial zero bytes as the datasheet recommends. * A single nop is sufficient delay during reset active. * Clear interrupt flag after reset to avoid useless interrupt. * Available buffer size corrected. * New function to read header information. * New function invokes decoder memory test. * Beep makes use of VsSdiWrite. * * Revision 1.10  2003/04/18 14:46:08  harald * Copyright update by the maintainer, after none of the original code had * been left. We have a clean BSD licence now. * This release had been prepared by Pavel Chromy. * BSYNC vs. transfer in progress issue in VsSdiPutByte(). * Fixed possible transfer in progress issue in VsPlayerFeed(). * HW reset may be forced by VS_SM_RESET mode bit * * Revision 1.9  2003/04/07 20:29:20  harald * Redesigned by Pavel Chromy * * Revision 1.9  2003/04/04 15:01:00  mac * VS_STATUS_EMTY is reported correctly. * * Revision 1.9  2003/02/14 13:39:00  mac * Several serious bugs fixed, * interrupt routine completely remade. * Unreliable spurious interrupts detection removed. * Mpeg frame detection removed. * Watermark check removed (this was rather limiting) * Can be optionaly compiled not to use SPI * * Revision 1.8  2003/02/04 17:50:55  harald * Version 3 released * * Revision 1.7  2003/01/14 16:15:19  harald * Sending twice the number of zeros to end MP3 stream. * Check for spurious interrupts to detect hanging chip. * Simpler portable inline assembler for short delays. * * Revision 1.6  2002/11/02 15:15:13  harald * Library dependencies removed * * Revision 1.5  2002/09/15 16:44:14  harald * *** empty log message *** * * Revision 1.4  2002/08/16 17:49:02  harald * First public release * * Revision 1.3  2002/06/26 17:29:08  harald * First pre-release with 2.4 stack * */#include <sys/atom.h>#include <sys/event.h>#include <sys/timer.h>#include <sys/heap.h>#include <dev/irqreg.h>#include <dev/vs1001k.h>/*! * \addtogroup xgVs1001 *//*@{*/static volatile u_char vs_status = VS_STATUS_STOPPED;static volatile u_short vs_flush;static u_char *vs_databuff;static u_char *vs_dataend;static u_char *vs_writeptr;static u_char *volatile vs_readptr;/* * \brief Write a byte to the VS1001 data interface. * * The caller is responsible for checking the DREQ line. Also make sure, * that decoder interrupts are disabled. * * \param b Byte to be shifted to the decoder's data interface. */static INLINE void VsSdiPutByte(u_char b){#ifdef VS_NOSPI    u_char mask = 0x80;    sbi(VS_BSYNC_PORT, VS_BSYNC_BIT);    while (mask) {        if (b & mask)            sbi(VS_SI_PORT, VS_SI_BIT);        else            cbi(VS_SI_PORT, VS_SI_BIT);        sbi(VS_SS_PORT, VS_SS_BIT);        mask >>= 1;        cbi(VS_SS_PORT, VS_SS_BIT);        cbi(VS_BSYNC_PORT, VS_BSYNC_BIT);    }#else    /* Wait for previous SPI transfer to finish. */    loop_until_bit_is_set(SPSR, SPIF);    sbi(VS_BSYNC_PORT, VS_BSYNC_BIT);    outp(b, SPDR);    _NOP();    _NOP();    _NOP();    _NOP();    cbi(VS_BSYNC_PORT, VS_BSYNC_BIT);#endif}/*! * \brief Write a specified number of bytes to the VS1001 data interface. * * This function will check the DREQ line. Decoder interrupts must have  * been disabled before calling this function. */static int VsSdiWrite(CONST u_char * data, u_short len){    u_short try = 5000;    while (len--) {        while (try-- && bit_is_clear(VS_DREQ_PIN, VS_DREQ_BIT));        VsSdiPutByte(*data);        data++;    }    return try ? 0 : -1;}/*! * \brief Write a specified number of bytes from program space to the  *        VS1001 data interface. * * This function is similar to VsSdiWrite() except that the data is  * located in program space. */static int VsSdiWrite_P(PGM_P data, u_short len){    u_short try = 5000;    while (len--) {        while (try-- && bit_is_clear(VS_DREQ_PIN, VS_DREQ_BIT));        VsSdiPutByte(PRG_RDB(data));        data++;    }    return try ? 0 : -1;}/*! * \brief Write a byte to the serial control interface. * * Decoder interrupts must have been disabled and the decoder chip * select must have been enabled before calling this function. */static INLINE void VsSciPutByte(u_char data){    u_char mask = 0x80;    /*     * Loop until all 8 bits are processed.     */    while (mask) {        /* Set data line. */        if (data & mask)            sbi(VS_SI_PORT, VS_SI_BIT);        else            cbi(VS_SI_PORT, VS_SI_BIT);        /* Toggle clock and shift mask. */        sbi(VS_SCK_PORT, VS_SCK_BIT);        mask >>= 1;        cbi(VS_SCK_PORT, VS_SCK_BIT);    }}/*! * \brief Read a byte from the serial control interface. * * Decoder interrupts must have been disabled and the decoder chip * select must have been enabled before calling this function. */static INLINE u_char VsSciGetByte(void){    u_char mask = 0x80;    u_char data = 0;    /*     * Loop until all 8 bits are processed.     */    while (mask) {        /* Toggle clock and get the data. */        sbi(VS_SCK_PORT, VS_SCK_BIT);        if (bit_is_set(VS_SO_PIN, VS_SO_BIT))            data |= mask;        mask >>= 1;        cbi(VS_SCK_PORT, VS_SCK_BIT);    }    return data;}/*! * \brief Write to a decoder register. * * Decoder interrupts must have been disabled before calling this function. */static void VsRegWrite(u_char reg, u_short data){    /* Select chip. */    cbi(VS_XCS_PORT, VS_XCS_BIT);#ifndef VS_NOSPI    /* Disable SPI */    cbi(SPCR, SPE);#endif    VsSciPutByte(VS_OPCODE_WRITE);    VsSciPutByte(reg);    VsSciPutByte((u_char) (data >> 8));    VsSciPutByte((u_char) data);#ifndef VS_NOSPI    /* Re-enable SPI. Hint given by Jesper Hansen. */    outp(BV(MSTR) | BV(SPE), SPCR);    outp(inp(SPSR), SPSR);#endif    /* Deselect chip. */    sbi(VS_XCS_PORT, VS_XCS_BIT);}/* * \brief Read from a register. * * Decoder interrupts must have been disabled before calling this function. *  * \return Register contents. */static u_short VsRegRead(u_char reg){    u_short data;    /* Disable interrupts and select chip. */    cbi(EIMSK, VS_DREQ_BIT);    cbi(VS_XCS_PORT, VS_XCS_BIT);#ifndef VS_NOSPI    /* Disable SPI. */    cbi(SPCR, SPE);#endif    VsSciPutByte(VS_OPCODE_READ);    VsSciPutByte(reg);    data = VsSciGetByte() << 8;    data |= VsSciGetByte();#ifndef VS_NOSPI    /* Re-enable SPI. Changed due to a hint by Jesper. */    outp(BV(MSTR) | BV(SPE), SPCR);    outp(inp(SPSR), SPSR);#endif    /* Deselect chip and enable interrupts. */    sbi(VS_XCS_PORT, VS_XCS_BIT);    sbi(EIMSK, VS_DREQ_BIT);    return data;}/* * \brief Feed the decoder with data. * * This function serves two purposes:  * - It is called by VsPlayerKick() to initially fill the decoder buffer. * - It is used as an interrupt handler for the decoder. */static void VsPlayerFeed(void *arg){    u_char j;    /* Cancel interrupt if not running. */    if (vs_status != VS_STATUS_RUNNING)        return;    /* We may feed 32 bytes to the decoder. */    if (bit_is_set(VS_DREQ_PIN, VS_DREQ_BIT))        j = 32;    else        j = 0;    /*      * Feed the decoder until its buffer is full.      */    while (j--) {        /* Is main buffer empty? */        if (vs_readptr == vs_writeptr) {            if (vs_flush) {                /* Auto flush the internal VS buffer. */                VsSdiPutByte(0);                if (--vs_flush == 0) {                    /* Decoder internal buffer is flushed. */                    vs_status = VS_STATUS_EMPTY;                    break;                }            } else {                /* End of stream. */                vs_status = VS_STATUS_EOF;                break;            }        }        /* We have some data in the buffer, feed it. */        else {            VsSdiPutByte(*vs_readptr);            if (++vs_readptr == vs_dataend)                vs_readptr = vs_databuff;        }        /* If DREQ is high, allow 31 bytes to be sent, SPI transfer may            still be in progress, which is the 32nd byte. */        if (bit_is_set(VS_DREQ_PIN, VS_DREQ_BIT))            j = 31;    }}/*! * \brief Start playback. * * This routine will send the first MP3 data bytes to the * decoder, until it is completely filled. The data buffer * should have been filled before calling this routine. * * \return 0 on success, -1 otherwise. */int VsPlayerKick(void){    cbi(EIMSK, VS_DREQ_BIT);    /*     * Start feeding the decoder with data and     * enable interrupts.     */    vs_status = VS_STATUS_RUNNING;    VsPlayerFeed(NULL);    sbi(EIMSK, VS_DREQ_BIT);    return 0;}/*! * \brief Stops the playback. * * This routine will stops the MP3 playback, VsPlayerKick() may be used  * to resume the playback. *

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -