/* * Copyright (C) 2001-2007 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 THE COPYRIGHT HOLDERS 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 THE * COPYRIGHT OWNER 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 and Pavel Chromy. Many thanks for all their help. */ /* * $Log$ * Revision 1.6 2009/01/17 11:26:46 haraldkipp * Getting rid of two remaining BSD types in favor of stdint. * Replaced 'u_int' by 'unsinged int' and 'uptr_t' by 'uintptr_t'. * * Revision 1.5 2008/10/23 08:54:07 haraldkipp * Include the correct header file. * * Revision 1.4 2008/09/18 09:51:58 haraldkipp * Use the correct PORT macros. * * Revision 1.3 2008/09/02 14:30:28 haraldkipp * Make it compile for targets without specific configuration. * * Revision 1.2 2008/08/11 06:59:42 haraldkipp * BSD types replaced by stdint types (feature request #1282721). * * Revision 1.1 2007/04/12 08:59:55 haraldkipp * VS10XX decoder support added. * */ #include #include #include #include #include #include #include #include #include #include #ifndef INT0 #define INT0 0 #define INT1 1 #define INT2 2 #define INT3 3 #define INT4 4 #define INT5 5 #define INT6 6 #define INT7 7 #endif /*! * \addtogroup xgVs10xx */ /*@{*/ #if !defined(AUDIO_VS1001K) && !defined(AUDIO_VS1011E) && !defined(AUDIO_VS1002D) && !defined(AUDIO_VS1003B) && !defined(AUDIO_VS1033C) && !defined(AUDIO_VS1053B) #define AUDIO_VS1001K #endif #ifndef VS10XX_FREQ /*! \brief Decoder crystal frequency. */ #define VS10XX_FREQ 12288000UL #endif #ifndef VS10XX_HWRST_DURATION /*! \brief Minimum time in milliseconds to held hardware reset low. */ #define VS10XX_HWRST_DURATION 1 #endif #ifndef VS10XX_HWRST_RECOVER /*! \brief Milliseconds to wait after hardware reset. */ #define VS10XX_HWRST_RECOVER 10 #endif #ifndef VS10XX_SWRST_RECOVER /*! \brief Milliseconds to wait after software reset. */ #define VS10XX_SWRST_RECOVER VS10XX_HWRST_RECOVER #endif #ifndef VS10XX_SCI_MODE #define VS10XX_SCI_MODE 0 #endif #ifndef VS10XX_SCI_RATE #define VS10XX_SCI_RATE (VS10XX_FREQ / 4) #endif #ifndef VS10XX_SDI_MODE #define VS10XX_SDI_MODE 0 #endif #ifndef VS10XX_SDI_RATE #define VS10XX_SDI_RATE (VS10XX_FREQ / 4) #endif #if defined(VS10XX_SCI_SPI0_DEVICE) /* Command SPI device. */ #include #if defined(VS10XX_SELECT_ACTIVE_HIGH) #define SciReset(act) Sppi0ChipReset(VS10XX_SCI_SPI0_DEVICE, act) #else #define SciReset(act) Sppi0ChipReset(VS10XX_SCI_SPI0_DEVICE, !act) #endif #define SciSetMode() Sppi0SetMode(VS10XX_SCI_SPI0_DEVICE, VS10XX_SCI_MODE) #define SciSetSpeed() Sppi0SetSpeed(VS10XX_SCI_SPI0_DEVICE, VS10XX_SCI_RATE) #if defined(VS10XX_SELECT_ACTIVE_HIGH) #define SciSelect() Sppi0SelectDevice(VS10XX_SCI_SPI0_DEVICE) #define SciDeselect() Sppi0DeselectDevice(VS10XX_SCI_SPI0_DEVICE) #else #define SciSelect() Sppi0NegSelectDevice(VS10XX_SCI_SPI0_DEVICE) #define SciDeselect() Sppi0NegDeselectDevice(VS10XX_SCI_SPI0_DEVICE) #endif #define SciByte(b) Sppi0Byte(b) #elif defined(VS10XX_SCI_SBBI0_DEVICE) /* Command SPI device. */ #include #if defined(VS10XX_SELECT_ACTIVE_HIGH) #define SciReset(act) Sbbi0ChipReset(VS10XX_SCI_SBBI0_DEVICE, act) #else #define SciReset(act) Sbbi0ChipReset(VS10XX_SCI_SBBI0_DEVICE, !act) #endif #define SciSetMode() Sbbi0SetMode(VS10XX_SCI_SBBI0_DEVICE, VS10XX_SCI_MODE) #define SciSetSpeed() Sbbi0SetSpeed(VS10XX_SCI_SBBI0_DEVICE, VS10XX_SCI_RATE) #if defined(VS10XX_SELECT_ACTIVE_HIGH) #define SciSelect() Sbbi0SelectDevice(VS10XX_SCI_SBBI0_DEVICE) #define SciDeselect() Sbbi0DeselectDevice(VS10XX_SCI_SBBI0_DEVICE) #else #define SciSelect() Sbbi0NegSelectDevice(VS10XX_SCI_SBBI0_DEVICE) #define SciDeselect() Sbbi0NegDeselectDevice(VS10XX_SCI_SBBI0_DEVICE) #endif #define SciByte(b) Sbbi0Byte(b) #elif defined(VS10XX_SCI_SBBI1_DEVICE) /* Command SPI device. */ #include #if defined(VS10XX_SELECT_ACTIVE_HIGH) #define SciReset(act) Sbbi1ChipReset(VS10XX_SCI_SBBI1_DEVICE, act) #else #define SciReset(act) Sbbi1ChipReset(VS10XX_SCI_SBBI1_DEVICE, !act) #endif #define SciSetMode() Sbbi1SetMode(VS10XX_SCI_SBBI1_DEVICE, VS10XX_SCI_MODE) #define SciSetSpeed() Sbbi1SetSpeed(VS10XX_SCI_SBBI1_DEVICE, VS10XX_SCI_RATE) #if defined(VS10XX_SELECT_ACTIVE_HIGH) #define SciSelect() Sbbi1SelectDevice(VS10XX_SCI_SBBI1_DEVICE) #define SciDeselect() Sbbi1DeselectDevice(VS10XX_SCI_SBBI1_DEVICE) #else #define SciSelect() Sbbi1NegSelectDevice(VS10XX_SCI_SBBI1_DEVICE) #define SciDeselect() Sbbi1NegDeselectDevice(VS10XX_SCI_SBBI1_DEVICE) #endif #define SciByte(b) Sbbi1Byte(b) #elif defined(VS10XX_SCI_SBBI2_DEVICE) /* Command SPI device. */ #include #if defined(VS10XX_SELECT_ACTIVE_HIGH) #define SciReset(act) Sbbi2ChipReset(VS10XX_SCI_SBBI2_DEVICE, act) #else #define SciReset(act) Sbbi2ChipReset(VS10XX_SCI_SBBI2_DEVICE, !act) #endif #define SciSetMode() Sbbi2SetMode(VS10XX_SCI_SBBI2_DEVICE, VS10XX_SCI_MODE) #define SciSetSpeed() Sbbi2SetSpeed(VS10XX_SCI_SBBI2_DEVICE, VS10XX_SCI_RATE) #if defined(VS10XX_SELECT_ACTIVE_HIGH) #define SciSelect() Sbbi2SelectDevice(VS10XX_SCI_SBBI2_DEVICE) #define SciDeselect() Sbbi2DeselectDevice(VS10XX_SCI_SBBI2_DEVICE) #else #define SciSelect() Sbbi2NegSelectDevice(VS10XX_SCI_SBBI2_DEVICE) #define SciDeselect() Sbbi2NegDeselectDevice(VS10XX_SCI_SBBI2_DEVICE) #endif #define SciByte(b) Sbbi2Byte(b) #elif defined(VS10XX_SCI_SBBI3_DEVICE) /* Command SPI device. */ #include #if defined(VS10XX_SELECT_ACTIVE_HIGH) #define SciReset(act) Sbbi3ChipReset(VS10XX_SCI_SBBI3_DEVICE, act) #else #define SciReset(act) Sbbi3ChipReset(VS10XX_SCI_SBBI3_DEVICE, !act) #endif #define SciSetMode() Sbbi3SetMode(VS10XX_SCI_SBBI3_DEVICE, VS10XX_SCI_MODE) #define SciSetSpeed() Sbbi3SetSpeed(VS10XX_SCI_SBBI3_DEVICE, VS10XX_SCI_RATE) #if defined(VS10XX_SELECT_ACTIVE_HIGH) #define SciSelect() Sbbi3SelectDevice(VS10XX_SCI_SBBI3_DEVICE) #define SciDeselect() Sbbi3DeselectDevice(VS10XX_SCI_SBBI3_DEVICE) #else #define SciSelect() Sbbi3NegSelectDevice(VS10XX_SCI_SBBI3_DEVICE) #define SciDeselect() Sbbi3NegDeselectDevice(VS10XX_SCI_SBBI3_DEVICE) #endif #define SciByte(b) Sbbi3Byte(b) #else /* Command SPI device. */ #define SciReset(act) #define SciSetMode() (-1) #define SciSetSpeed() #define SciSelect() #define SciDeselect() #define SciByte(b) 0 #endif /* Command SPI device. */ #if defined(VS10XX_SDI_SPI0_DEVICE) /* Data SPI device. */ #include #define SdiSetMode() Sppi0SetMode(VS10XX_SDI_SPI0_DEVICE, VS10XX_SDI_MODE) #define SdiSetSpeed() Sppi0SetSpeed(VS10XX_SDI_SPI0_DEVICE, VS10XX_SDI_RATE) #if defined(VS10XX_SELECT_ACTIVE_HIGH) #define SdiSelect() Sppi0SelectDevice(VS10XX_SDI_SPI0_DEVICE) #define SdiDeselect() Sppi0DeselectDevice(VS10XX_SDI_SPI0_DEVICE) #else #define SdiSelect() Sppi0NegSelectDevice(VS10XX_SDI_SPI0_DEVICE) #define SdiDeselect() Sppi0NegDeselectDevice(VS10XX_SDI_SPI0_DEVICE) #endif #define SdiByte(b) Sppi0Byte(b) #elif defined(VS10XX_SDI_SBBI0_DEVICE) /* Data SPI device. */ #include #define SdiSetMode() Sbbi0SetMode(VS10XX_SDI_SBBI0_DEVICE, VS10XX_SDI_MODE) #define SdiSetSpeed() Sbbi0SetSpeed(VS10XX_SDI_SBBI0_DEVICE, VS10XX_SDI_RATE) #if defined(VS10XX_SELECT_ACTIVE_HIGH) #define SdiSelect() Sbbi0SelectDevice(VS10XX_SDI_SBBI0_DEVICE) #define SdiDeselect() Sbbi0DeselectDevice(VS10XX_SDI_SBBI0_DEVICE) #else #define SdiSelect() Sbbi0NegSelectDevice(VS10XX_SDI_SBBI0_DEVICE) #define SdiDeselect() Sbbi0NegDeselectDevice(VS10XX_SDI_SBBI0_DEVICE) #endif #define SdiByte(b) Sbbi0Byte(b) #elif defined(VS10XX_SDI_SBBI1_DEVICE) /* Data SPI device. */ #include #define SdiSetMode() Sbbi1SetMode(VS10XX_SDI_SBBI1_DEVICE, VS10XX_SDI_MODE) #define SdiSetSpeed() Sbbi1SetSpeed(VS10XX_SDI_SBBI1_DEVICE, VS10XX_SDI_RATE) #if defined(VS10XX_SELECT_ACTIVE_HIGH) #define SdiSelect() Sbbi1SelectDevice(VS10XX_SDI_SBBI1_DEVICE) #define SdiDeselect() Sbbi1DeselectDevice(VS10XX_SDI_SBBI1_DEVICE) #else #define SdiSelect() Sbbi1NegSelectDevice(VS10XX_SDI_SBBI1_DEVICE) #define SdiDeselect() Sbbi1NegDeselectDevice(VS10XX_SDI_SBBI1_DEVICE) #endif #define SdiByte(b) Sbbi1Byte(b) #elif defined(VS10XX_SDI_SBBI2_DEVICE) /* Data SPI device. */ #include #define SdiSetMode() Sbbi2SetMode(VS10XX_SDI_SBBI2_DEVICE, VS10XX_SDI_MODE) #define SdiSetSpeed() Sbbi2SetSpeed(VS10XX_SDI_SBBI2_DEVICE, VS10XX_SDI_RATE) #if defined(VS10XX_SELECT_ACTIVE_HIGH) #define SdiSelect() Sbbi2SelectDevice(VS10XX_SDI_SBBI2_DEVICE) #define SdiDeselect() Sbbi2DeselectDevice(VS10XX_SDI_SBBI2_DEVICE) #else #define SdiSelect() Sbbi2NegSelectDevice(VS10XX_SDI_SBBI2_DEVICE) #define SdiDeselect() Sbbi2NegDeselectDevice(VS10XX_SDI_SBBI2_DEVICE) #endif #define SdiByte(b) Sbbi2Byte(b) #elif defined(VS10XX_SDI_SBBI3_DEVICE) /* Data SPI device. */ #include #define SdiSetMode() Sbbi3SetMode(VS10XX_SDI_SBBI3_DEVICE, VS10XX_SDI_MODE) #define SdiSetSpeed() Sbbi3SetSpeed(VS10XX_SDI_SBBI3_DEVICE, VS10XX_SDI_RATE) #if defined(VS10XX_SELECT_ACTIVE_HIGH) #define SdiSelect() Sbbi3SelectDevice(VS10XX_SDI_SBBI3_DEVICE) #define SdiDeselect() Sbbi3DeselectDevice(VS10XX_SDI_SBBI3_DEVICE) #else #define SdiSelect() Sbbi3NegSelectDevice(VS10XX_SDI_SBBI3_DEVICE) #define SdiDeselect() Sbbi3NegDeselectDevice(VS10XX_SDI_SBBI3_DEVICE) #endif #define SdiByte(b) Sbbi3Byte(b) #else /* Data SPI device. */ #define SdiSetMode() (-1) #define SdiSetSpeed() #define SdiSelect() #define SdiDeselect() #define SdiByte(b) 0 #endif /* Data SPI device. */ /* ------------------------------------------------- * AT91 port specifications. */ #if MCU_AT91 || __AVR32__ #if (VS10XX_SIGNAL_IRQ == INT0) #define VS10XX_SIGNAL sig_INTERRUPT0 #elif (VS10XX_SIGNAL_IRQ == INT1) #define VS10XX_SIGNAL sig_INTERRUPT1 #else #define VS10XX_SIGNAL sig_INTERRUPT2 #endif #if defined(VS10XX_XCS_BIT) #if !defined(VS10XX_XCS_PORT) #define VS10XX_XCS_PE_REG PIO_PER #define VS10XX_XCS_OE_REG PIO_OER #define VS10XX_XCS_COD_REG PIO_CODR #define VS10XX_XCS_SOD_REG PIO_SODR #elif VS10XX_XCS_PORT == PIOA_ID #define VS10XX_XCS_PE_REG PIOA_PER #define VS10XX_XCS_OE_REG PIOA_OER #define VS10XX_XCS_COD_REG PIOA_CODR #define VS10XX_XCS_SOD_REG PIOA_SODR #elif VS10XX_XCS_PORT == PIOB_ID #define VS10XX_XCS_PE_REG PIOB_PER #define VS10XX_XCS_OE_REG PIOB_OER #define VS10XX_XCS_COD_REG PIOB_CODR #define VS10XX_XCS_SOD_REG PIOB_SODR #elif VS10XX_XCS_PORT == PIOC_ID #define VS10XX_XCS_PE_REG PIOC_PER #define VS10XX_XCS_OE_REG PIOC_OER #define VS10XX_XCS_COD_REG PIOC_CODR #define VS10XX_XCS_SOD_REG PIOC_SODR #endif #define VS10XX_XCS_ENA() \ outr(VS10XX_XCS_PE_REG, _BV(VS10XX_XCS_BIT)); \ outr(VS10XX_XCS_OE_REG, _BV(VS10XX_XCS_BIT)) #define VS10XX_XCS_CLR() outr(VS10XX_XCS_COD_REG, _BV(VS10XX_XCS_BIT)) #define VS10XX_XCS_SET() outr(VS10XX_XCS_SOD_REG, _BV(VS10XX_XCS_BIT)) #else /* VS10XX_XCS_BIT */ #define VS10XX_XCS_ENA() #define VS10XX_XCS_CLR() #define VS10XX_XCS_SET() #endif /* VS10XX_XCS_BIT */ #if defined(VS10XX_XDCS_BIT) #if !defined(VS10XX_XDCS_PORT) #define VS10XX_XDCS_PE_REG PIO_PER #define VS10XX_XDCS_OE_REG PIO_OER #define VS10XX_XDCS_COD_REG PIO_CODR #define VS10XX_XDCS_SOD_REG PIO_SODR #elif VS10XX_XDCS_PORT == PIOA_ID #define VS10XX_XDCS_PE_REG PIOA_PER #define VS10XX_XDCS_OE_REG PIOA_OER #define VS10XX_XDCS_COD_REG PIOA_CODR #define VS10XX_XDCS_SOD_REG PIOA_SODR #elif VS10XX_XDCS_PORT == PIOB_ID #define VS10XX_XDCS_PE_REG PIOB_PER #define VS10XX_XDCS_OE_REG PIOB_OER #define VS10XX_XDCS_COD_REG PIOB_CODR #define VS10XX_XDCS_SOD_REG PIOB_SODR #elif VS10XX_XDCS_PORT == PIOC_ID #define VS10XX_XDCS_PE_REG PIOC_PER #define VS10XX_XDCS_OE_REG PIOC_OER #define VS10XX_XDCS_COD_REG PIOC_CODR #define VS10XX_XDCS_SOD_REG PIOC_SODR #endif #define VS10XX_XDCS_ENA() \ outr(VS10XX_XDCS_PE_REG, _BV(VS10XX_XDCS_BIT)); \ outr(VS10XX_XDCS_OE_REG, _BV(VS10XX_XDCS_BIT)) #define VS10XX_XDCS_CLR() outr(VS10XX_XDCS_COD_REG, _BV(VS10XX_XDCS_BIT)) #define VS10XX_XDCS_SET() outr(VS10XX_XDCS_SOD_REG, _BV(VS10XX_XDCS_BIT)) #else /* VS10XX_XDCS_BIT */ #define VS10XX_XDCS_ENA() #define VS10XX_XDCS_CLR() #define VS10XX_XDCS_SET() #endif /* VS10XX_XDCS_BIT */ #if defined(VS10XX_DREQ_BIT) #if !defined(VS10XX_DREQ_PIO_ID) #define VS10XX_DREQ_PE_REG PIO_PER #define VS10XX_DREQ_OD_REG PIO_ODR #define VS10XX_DREQ_PDS_REG PIO_PDSR #elif VS10XX_DREQ_PIO_ID == PIOA_ID #define VS10XX_DREQ_PE_REG PIOA_PER #define VS10XX_DREQ_OD_REG PIOA_ODR #define VS10XX_DREQ_PDS_REG PIOA_PDSR #elif VS10XX_DREQ_PIO_ID == PIOB_ID #define VS10XX_DREQ_PE_REG PIOB_PER #define VS10XX_DREQ_OD_REG PIOB_ODR #define VS10XX_DREQ_PDS_REG PIOB_PDSR #elif VS10XX_DREQ_PIO_ID == PIOC_ID #define VS10XX_DREQ_PE_REG PIOC_PER #define VS10XX_DREQ_OD_REG PIOC_ODR #define VS10XX_DREQ_PDS_REG PIOC_PDSR #endif #define VS10XX_DREQ_PD_REG PIO_PDR #define VS10XX_DREQ_OD_REG PIO_ODR #define VS10XX_DREQ_PDS_REG PIO_PDSR #define VS10XX_DREQ_ENA() \ outr(VS10XX_DREQ_PD_REG, _BV(VS10XX_DREQ_BIT)); \ outr(VS10XX_DREQ_OD_REG, _BV(VS10XX_DREQ_BIT)) #define VS10XX_DREQ_TST() ((inr(VS10XX_DREQ_PDS_REG) & _BV(VS10XX_DREQ_BIT)) == _BV(VS10XX_DREQ_BIT)) #else /* VS10XX_DREQ_BIT */ #define VS10XX_DREQ_ENA() #define VS10XX_DREQ_TST() 0 #endif /* VS10XX_DREQ_BIT */ #ifdef VS10XX_BSYNC_BIT #if !defined(VS10XX_BSYNC_PIO_ID) #define VS10XX_BSYNC_PE_REG PIO_PER #define VS10XX_BSYNC_OE_REG PIO_OER #define VS10XX_BSYNC_COD_REG PIO_CODR #define VS10XX_BSYNC_SOD_REG PIO_SODR #elif VS10XX_BSYNC_PIO_ID == PIOA_ID #define VS10XX_BSYNC_PE_REG PIOA_PER #define VS10XX_BSYNC_OE_REG PIOA_OER #define VS10XX_BSYNC_COD_REG PIOA_CODR #define VS10XX_BSYNC_SOD_REG PIOA_SODR #elif VS10XX_BSYNC_PIO_ID == PIOB_ID #define VS10XX_BSYNC_PE_REG PIOB_PER #define VS10XX_BSYNC_OE_REG PIOB_OER #define VS10XX_BSYNC_COD_REG PIOB_CODR #define VS10XX_BSYNC_SOD_REG PIOB_SODR #elif VS10XX_BSYNC_PIO_ID == PIOC_ID #define VS10XX_BSYNC_PE_REG PIOC_PER #define VS10XX_BSYNC_OE_REG PIOC_OER #define VS10XX_BSYNC_COD_REG PIOC_CODR #define VS10XX_BSYNC_SOD_REG PIOC_SODR #endif #define VS10XX_BSYNC_ENA() \ outr(VS10XX_BSYNC_PE_REG, _BV(VS10XX_BSYNC_BIT)); \ outr(VS10XX_BSYNC_OE_REG, _BV(VS10XX_BSYNC_BIT)) #define VS10XX_BSYNC_CLR() outr(VS10XX_BSYNC_COD_REG, _BV(VS10XX_BSYNC_BIT)) #define VS10XX_BSYNC_SET() outr(VS10XX_BSYNC_SOD_REG, _BV(VS10XX_BSYNC_BIT)) #else /* VS10XX_BSYNC_BIT */ #define VS10XX_BSYNC_ENA() #define VS10XX_BSYNC_CLR() #define VS10XX_BSYNC_SET() #endif /* VS10XX_BSYNC_BIT */ /* ------------------------------------------------- * AVR port specifications. */ #elif defined(__AVR__) #if !defined(VS10XX_SIGNAL_IRQ) #define VS10XX_SIGNAL_IRQ INT6 #endif #if (VS10XX_SIGNAL_IRQ == INT0) #define VS10XX_SIGNAL sig_INTERRUPT0 #define VS10XX_DREQ_BIT 0 #define VS10XX_DREQ_PDS_REG PIND #define VS10XX_DREQ_PUE_REG PORTD #define VS10XX_DREQ_OE_REG DDRD #elif (VS10XX_SIGNAL_IRQ == INT1) #define VS10XX_SIGNAL sig_INTERRUPT1 #define VS10XX_DREQ_BIT 1 #define VS10XX_DREQ_PDS_REG PIND #define VS10XX_DREQ_PUE_REG PORTD #define VS10XX_DREQ_OE_REG DDRD #elif (VS10XX_SIGNAL_IRQ == INT2) #define VS10XX_SIGNAL sig_INTERRUPT2 #define VS10XX_DREQ_BIT 2 #define VS10XX_DREQ_PDS_REG PIND #define VS10XX_DREQ_PUE_REG PORTD #define VS10XX_DREQ_OE_REG DDRD #elif (VS10XX_SIGNAL_IRQ == INT3) #define VS10XX_SIGNAL sig_INTERRUPT3 #define VS10XX_DREQ_BIT 3 #define VS10XX_DREQ_PDS_REG PIND #define VS10XX_DREQ_PUE_REG PORTD #define VS10XX_DREQ_OE_REG DDRD #elif (VS10XX_SIGNAL_IRQ == INT4) #define VS10XX_SIGNAL sig_INTERRUPT4 #define VS10XX_DREQ_BIT 4 #define VS10XX_DREQ_PDS_REG PINE #define VS10XX_DREQ_PUE_REG PORTE #define VS10XX_DREQ_OE_REG DDRE #elif (VS10XX_SIGNAL_IRQ == INT5) #define VS10XX_SIGNAL sig_INTERRUPT5 #define VS10XX_DREQ_BIT 5 #define VS10XX_DREQ_PDS_REG PINE #define VS10XX_DREQ_PUE_REG PORTE #define VS10XX_DREQ_OE_REG DDRE #elif (VS10XX_SIGNAL_IRQ == INT7) #define VS10XX_SIGNAL sig_INTERRUPT7 #define VS10XX_DREQ_BIT 7 #define VS10XX_DREQ_PDS_REG PINE #define VS10XX_DREQ_PUE_REG PORTE #define VS10XX_DREQ_OE_REG DDRE #else #define VS10XX_SIGNAL sig_INTERRUPT6 #define VS10XX_DREQ_BIT 6 #define VS10XX_DREQ_PDS_REG PINE #define VS10XX_DREQ_PUE_REG PORTE #define VS10XX_DREQ_OE_REG DDRE #endif #define VS10XX_DREQ_ENA() \ cbi(VS10XX_DREQ_OE_REG, VS10XX_DREQ_BIT); \ sbi(VS10XX_DREQ_PUE_REG, VS10XX_DREQ_BIT) #define VS10XX_DREQ_TST() ((inb(VS10XX_DREQ_PDS_REG) & _BV(VS10XX_DREQ_BIT)) == _BV(VS10XX_DREQ_BIT)) #if defined(VS10XX_XCS_BIT) #if (VS10XX_XCS_PORT == AVRPORTA) #define VS10XX_XCS_SOD_REG PORTA #define VS10XX_XCS_OE_REG DDRA #elif (VS10XX_XCS_PORT == AVRPORTB) #define VS10XX_XCS_SOD_REG PORTB #define VS10XX_XCS_OE_REG DDRB #elif (VS10XX_XCS_PORT == AVRPORTD) #define VS10XX_XCS_SOD_REG PORTD #define VS10XX_XCS_OE_REG DDRD #elif (VS10XX_XCS_PORT == AVRPORTE) #define VS10XX_XCS_SOD_REG PORTE #define VS10XX_XCS_OE_REG DDRE #elif (VS10XX_XCS_PORT == AVRPORTF) #define VS10XX_XCS_SOD_REG PORTF #define VS10XX_XCS_OE_REG DDRF #elif (VS10XX_XCS_PORT == AVRPORTG) #define VS10XX_XCS_SOD_REG PORTG #define VS10XX_XCS_OE_REG DDRG #elif (VS10XX_XCS_PORT == AVRPORTH) #define VS10XX_XCS_SOD_REG PORTH #define VS10XX_XCS_OE_REG DDRH #endif #define VS10XX_XCS_ENA() sbi(VS10XX_XCS_OE_REG, VS10XX_XCS_BIT) #define VS10XX_XCS_CLR() cbi(VS10XX_XCS_SOD_REG, VS10XX_XCS_BIT) #define VS10XX_XCS_SET() sbi(VS10XX_XCS_SOD_REG, VS10XX_XCS_BIT) #else /* VS10XX_XCS_BIT */ #define VS10XX_XCS_ENA() #define VS10XX_XCS_CLR() #define VS10XX_XCS_SET() #endif /* VS10XX_XCS_BIT */ #if defined(VS10XX_XDCS_BIT) #if (VS10XX_XDCS_PORT == AVRPORTA) #define VS10XX_XDCS_SOD_REG PORTA #define VS10XX_XDCS_OE_REG DDRA #elif (VS10XX_XDCS_PORT == AVRPORTB) #define VS10XX_XDCS_SOD_REG PORTB #define VS10XX_XDCS_OE_REG DDRB #elif (VS10XX_XDCS_PORT == AVRPORTD) #define VS10XX_XDCS_SOD_REG PORTD #define VS10XX_XDCS_OE_REG DDRD #elif (VS10XX_XDCS_PORT == AVRPORTE) #define VS10XX_XDCS_SOD_REG PORTE #define VS10XX_XDCS_OE_REG DDRE #elif (VS10XX_XDCS_PORT == AVRPORTF) #define VS10XX_XDCS_SOD_REG PORTF #define VS10XX_XDCS_OE_REG DDRF #elif (VS10XX_XDCS_PORT == AVRPORTG) #define VS10XX_XDCS_SOD_REG PORTG #define VS10XX_XDCS_OE_REG DDRG #elif (VS10XX_XDCS_PORT == AVRPORTH) #define VS10XX_XDCS_SOD_REG PORTH #define VS10XX_XDCS_OE_REG DDRH #endif #define VS10XX_XDCS_ENA() sbi(VS10XX_XDCS_OE_REG, VS10XX_XDCS_BIT) #define VS10XX_XDCS_CLR() cbi(VS10XX_XDCS_SOD_REG, VS10XX_XDCS_BIT) #define VS10XX_XDCS_SET() sbi(VS10XX_XDCS_SOD_REG, VS10XX_XDCS_BIT) #else /* VS10XX_XDCS_BIT */ #define VS10XX_XDCS_ENA() #define VS10XX_XDCS_CLR() #define VS10XX_XDCS_SET() #endif /* VS10XX_XDCS_BIT */ #if defined(VS10XX_BSYNC_BIT) #if (VS10XX_BSYNC_PORT == AVRPORTA) #define VS10XX_BSYNC_SOD_REG PORTA #define VS10XX_BSYNC_OE_REG DDRA #elif (VS10XX_BSYNC_PORT == AVRPORTB) #define VS10XX_BSYNC_SOD_REG PORTB #define VS10XX_BSYNC_OE_REG DDRB #elif (VS10XX_BSYNC_PORT == AVRPORTD) #define VS10XX_BSYNC_SOD_REG PORTD #define VS10XX_BSYNC_OE_REG DDRD #elif (VS10XX_BSYNC_PORT == AVRPORTE) #define VS10XX_BSYNC_SOD_REG PORTE #define VS10XX_BSYNC_OE_REG DDRE #elif (VS10XX_BSYNC_PORT == AVRPORTF) #define VS10XX_BSYNC_SOD_REG PORTF #define VS10XX_BSYNC_OE_REG DDRF #elif (VS10XX_BSYNC_PORT == AVRPORTG) #define VS10XX_BSYNC_SOD_REG PORTG #define VS10XX_BSYNC_OE_REG DDRG #elif (VS10XX_BSYNC_PORT == AVRPORTH) #define VS10XX_BSYNC_SOD_REG PORTH #define VS10XX_BSYNC_OE_REG DDRH #endif #define VS10XX_BSYNC_ENA() sbi(VS10XX_BSYNC_OE_REG, VS10XX_BSYNC_BIT) #define VS10XX_BSYNC_CLR() cbi(VS10XX_BSYNC_SOD_REG, VS10XX_BSYNC_BIT) #define VS10XX_BSYNC_SET() sbi(VS10XX_BSYNC_SOD_REG, VS10XX_BSYNC_BIT) #else /* VS10XX_BSYNC_BIT */ #define VS10XX_BSYNC_ENA() #define VS10XX_BSYNC_CLR() #define VS10XX_BSYNC_SET() #endif /* VS10XX_BSYNC_BIT */ /* ------------------------------------------------- * End of port specifications. */ #endif static volatile ureg_t vs_status = VS_STATUS_STOPPED; static volatile unsigned int vs_flush; /* * \brief Write a byte to the VS10XX 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(ureg_t b) { #if defined(VS10XX_BSYNC_BIT) #if defined(VS10XX_SDI_SBBI0_DEVICE) /* VS10XX_SDI_DEVICE */ ureg_t mask; VS10XX_BSYNC_SET(); for (mask = 0x80; mask; mask >>= 1) { SBBI0_SCK_CLR(); if (b & mask) { SBBI0_MOSI_SET(); } else { SBBI0_MOSI_CLR(); } SBBI0_SCK_SET(); if (mask & 0x40) { VS10XX_BSYNC_CLR(); } } SBBI0_SCK_CLR(); #elif defined(VS10XX_SDI_SBBI1_DEVICE) /* VS10XX_SDI_DEVICE */ ureg_t mask; VS10XX_BSYNC_SET(); for (mask = 0x80; mask; mask >>= 1) { SBBI1_SCK_CLR(); if (b & mask) { SBBI1_MOSI_SET(); } else { SBBI1_MOSI_CLR(); } SBBI1_SCK_SET(); if (mask & 0x40) { VS10XX_BSYNC_CLR(); } } SBBI1_SCK_CLR(); #elif defined(VS10XX_SDI_SBBI2_DEVICE) /* VS10XX_SDI_DEVICE */ ureg_t mask; VS10XX_BSYNC_SET(); for (mask = 0x80; mask; mask >>= 1) { SBBI2_SCK_CLR(); if (b & mask) { SBBI2_MOSI_SET(); } else { SBBI2_MOSI_CLR(); } SBBI2_SCK_SET(); if (mask & 0x40) { VS10XX_BSYNC_CLR(); } } SBBI2_SCK_CLR(); #elif defined(VS10XX_SDI_SBBI3_DEVICE) /* VS10XX_SDI_DEVICE */ ureg_t mask; VS10XX_BSYNC_SET(); for (mask = 0x80; mask; mask >>= 1) { SBBI3_SCK_CLR(); if (b & mask) { SBBI3_MOSI_SET(); } else { SBBI3_MOSI_CLR(); } SBBI3_SCK_SET(); if (mask & 0x40) { VS10XX_BSYNC_CLR(); } } SBBI3_SCK_CLR(); #elif defined(VS10XX_SDI_SPI0_DEVICE) /* VS10XX_SDI_DEVICE */ VS10XX_BSYNC_SET(); outb(SPDR, b); _NOP(); _NOP(); _NOP(); _NOP(); VS10XX_BSYNC_CLR(); /* Wait for SPI transfer to finish. */ loop_until_bit_is_set(SPSR, SPIF); #endif /* VS10XX_SDI_DEVICE */ #else /* !VS10XX_BSYNC_BIT */ (void)SdiByte(b); #endif /* !VS10XX_BSYNC_BIT */ } /*! * \brief Enable or disable player interrupts. * * This routine is typically used by applications when dealing with * unprotected buffers. * * \param enable Disables interrupts when zero. Otherwise interrupts * are enabled. * * \return Zero if interrupts were disabled before this call. */ ureg_t VsPlayerInterrupts(ureg_t enable) { static ureg_t is_enabled = 0; ureg_t rc; rc = is_enabled; if(enable) { VS10XX_DREQ_ENA(); NutIrqEnable(&VS10XX_SIGNAL); } else { NutIrqDisable(&VS10XX_SIGNAL); } is_enabled = enable; return rc; } /*! * \brief Throttle decoder activity. * * When sharing SPI with other devices, this function should be called * to disable (and re-enable) the SPI interface of the VS10XX. * * Decoder interrupts must have been disabled before calling this * function. * * \code * #include * * ureg_t ief = VsPlayerInterrupts(0); * ureg_t tef = VsPlayerThrottle(1); * ... use other SPI devices here ... * VsPlayerThrottle(tef); * VsPlayerInterrupts(ief); * \endcode * * \param on Throttles (disables) the decoder interface if not zero. * Otherwise the decoder interface is enabled again. * * \return Zero if the interface was enabled before this call. */ ureg_t VsPlayerThrottle(ureg_t on) { static ureg_t is_throttled = 0; ureg_t rc; rc = is_throttled; if(on) { VS10XX_XDCS_SET(); SdiDeselect(); } else { VS10XX_XDCS_CLR(); SdiSelect(); } is_throttled = on; return rc; } /*! * \brief Switch to or switch back from command mode. */ static void VsSciSelect(ureg_t on) { if (on) { /* Disable data interface. */ SdiDeselect(); #if defined(VS10XX_SDI_SPI0_DEVICE) && !defined(VS10XX_SCI_SPI0_DEVICE) /* Hint given by Jesper Hansen: If data channel uses HW SPI and command channel uses SW SPI, then disable HW SPI while sending using the command channel. */ cbi(SPCR, SPE); #endif /* Deselect data channel. */ VS10XX_XDCS_SET(); /* Select cmd channel. */ VS10XX_XCS_CLR(); /* Enable cmd interface. */ SciSelect(); } else { /* Disable cmd interface. */ SciDeselect(); /* Deselect cmd channel. */ VS10XX_XCS_SET(); /* Re-select data channel. */ VS10XX_XDCS_CLR(); /* Enable data interface. */ SdiSelect(); } } /*! * \brief Wait for decoder ready. * * This function will check the DREQ line. Decoder interrupts must have * been disabled before calling this function. */ static int VsWaitReady(void) { int tmo; for (tmo = 0; tmo < 5000; tmo++) { if (VS10XX_DREQ_TST()) { return 0; } } return -1; } /* * \brief Write a specified number of bytes to the VS10XX data interface. * * This function will check the DREQ line. Decoder interrupts must have * been disabled before calling this function. */ static int VsSdiWrite(const uint8_t * data, size_t len) { while (len--) { if (!VS10XX_DREQ_TST() && VsWaitReady()) { return -1; } VsSdiPutByte(*data); data++; } return 0; } /* * \brief Write a specified number of bytes from program space to the * VS10XX data interface. * * This function is similar to VsSdiWrite() except that the data is * located in program space. */ static int VsSdiWrite_P(PGM_P data, size_t len) { while (len--) { if (!VS10XX_DREQ_TST() && VsWaitReady()) { return -1; } VsSdiPutByte(PRG_RDB(data)); data++; } return 0; } /* * \brief Write to a decoder register. * * Decoder interrupts must have been disabled before calling this function. */ static void VsRegWrite(ureg_t reg, uint16_t data) { /* Select command channel. */ VsWaitReady(); VsSciSelect(1); /* * The VS1011E datasheet demands a minimum of 5 ns between * the falling CS and the first rising SCK. This is a very * short time and doesn't require any additional delay * even on very fast CPUs. */ (void)SciByte(VS_OPCODE_WRITE); (void)SciByte((uint8_t) reg); (void)SciByte((uint8_t) (data >> 8)); (void)SciByte((uint8_t) data); /* Re-select data channel. */ VsSciSelect(0); } /* * \brief Read from a register. * * Decoder interrupts must have been disabled before calling this function. * * \return Register contents. */ static uint16_t VsRegRead(ureg_t reg) { uint16_t data; /* Select command channel. */ VsWaitReady(); VsSciSelect(1); (void)SciByte(VS_OPCODE_READ); (void)SciByte((uint8_t) reg); data = (uint16_t)SciByte(0) << 8; data |= SciByte(0); /* Select data channel. */ VsSciSelect(0); 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) { ureg_t j = 32; size_t total = 0; if (!VS10XX_DREQ_TST()) { return; } /* * Feed the decoder until its buffer is full or we ran out of data. */ if (vs_status == VS_STATUS_RUNNING) { char *bp = 0; size_t consumed = 0; size_t available = 0; do { if(consumed >= available) { /* Commit previously consumed bytes. */ if(consumed) { NutSegBufReadCommit(consumed); consumed = 0; } /* All bytes consumed, request new. */ bp = NutSegBufReadRequest(&available); if(available == 0) { /* End of stream. */ vs_status = VS_STATUS_EOF; break; } } /* We have some data in the buffer, feed it. */ VsSdiPutByte(*bp); bp++; consumed++; total++; if (total > 4096) { vs_status = VS_STATUS_EOF; break; } /* Allow 32 bytes to be sent as long as DREQ is set, This includes the one in progress. */ if (VS10XX_DREQ_TST()) { j = 32; } } while(j--); /* Finally re-enable the producer buffer. */ NutSegBufReadLast(consumed); } /* * Flush the internal VS buffer. */ if(vs_status != VS_STATUS_RUNNING && vs_flush) { do { VsSdiPutByte(0); if (--vs_flush == 0) { /* Decoder internal buffer is flushed. */ vs_status = VS_STATUS_EMPTY; break; } /* Allow 32 bytes to be sent as long as DREQ is set, This includes the one in progress. */ if (VS10XX_DREQ_TST()) { j = 32; } } while(j--); } } /*! * \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. * * Decoder interrupts will be enabled. * * \return 0 on success, -1 otherwise. */ int VsPlayerKick(void) { /* * Start feeding the decoder with data. */ VsPlayerInterrupts(0); vs_status = VS_STATUS_RUNNING; VsPlayerFeed(NULL); VsPlayerInterrupts(1); return 0; } /*! * \brief Stops the playback. * * This routine will stops the MP3 playback, VsPlayerKick() may be used * to resume the playback. * * \return 0 on success, -1 otherwise. */ int VsPlayerStop(void) { ureg_t ief; ief = VsPlayerInterrupts(0); /* Check whether we need to stop at all to not overwrite other than running status */ if (vs_status == VS_STATUS_RUNNING) { vs_status = VS_STATUS_STOPPED; } VsPlayerInterrupts(ief); return 0; } /*! * \brief Sets up decoder internal buffer flushing. * * This routine will set up internal VS buffer flushing, * unless the buffer is already empty and starts the playback * if necessary. The internal VS buffer is flushed in VsPlayerFeed() * at the end of the stream. * * Decoder interrupts will be enabled. * * \return 0 on success, -1 otherwise. */ int VsPlayerFlush(void) { VsPlayerInterrupts(0); /* Set up fluhing unless both buffers are empty. */ if (vs_status != VS_STATUS_EMPTY || NutSegBufUsed()) { if (vs_flush == 0) { vs_flush = VS_FLUSH_BYTES; } /* start the playback if necessary */ if (vs_status != VS_STATUS_RUNNING) { VsPlayerKick(); } } VsPlayerInterrupts(1); return 0; } /*! * \brief Initialize the VS10XX hardware interface. * * \return 0 on success, -1 otherwise. */ int VsPlayerInit(void) { /* Disable decoder interrupts. */ VsPlayerInterrupts(0); /* Keep decoder in reset state. */ SciReset(1); /* Initialize command channel. */ if (SciSetMode()) { return -1; } SciSetSpeed(); SciDeselect(); /* Initialize data channel. */ if (SdiSetMode()) { return -1; } SdiSetSpeed(); SdiDeselect(); /* Set BSYNC output low. */ VS10XX_BSYNC_CLR(); VS10XX_BSYNC_ENA(); /* Set low active data channel select output low. */ VS10XX_XDCS_SET(); VS10XX_XDCS_ENA(); /* Set low active command channel select output high. */ VS10XX_XCS_SET(); VS10XX_XCS_ENA(); /* Enable DREQ interrupt input. */ VS10XX_DREQ_ENA(); /* Register the interrupt routine */ if (NutRegisterIrqHandler(&VS10XX_SIGNAL, VsPlayerFeed, NULL)) { return -1; } /* Rising edge will generate an interrupt. */ NutIrqSetMode(&VS10XX_SIGNAL, NUT_IRQMODE_RISINGEDGE); /* Release decoder reset line. */ SciReset(0); NutDelay(VS10XX_HWRST_RECOVER); return VsPlayerReset(0); } /*! * \brief Software reset the decoder. * * This function is typically called after VsPlayerInit() and at the end * of each track. * * \param mode Any of the following flags may be or'ed (check the data sheet) * - \ref VS_SM_DIFF Left channel inverted. * - \ref VS_SM_LAYER12 Allow MPEG layers I and II. * - \ref VS_SM_MP12 Allow MPEG layers I and II on VS1001K. * - \ref VS_SM_FFWD VS1001K fast forward. * - \ref VS_SM_RESET Software reset. * - \ref VS_SM_OUTOFWAV Jump out of WAV decoding. * - \ref VS_SM_TESTS Allow SDI tests. * - \ref VS_SM_PDOWN Switch to power down mode. * - \ref VS_SM_BASS VS1001K bass/treble enhancer. * - \ref VS_SM_STREAM Stream mode. * - \ref VS_SM_SDISHARE Share SPI chip select. * - \ref VS_SM_SDINEW VS1002 native mode (automatically set). * - \ref VS_SM_ADPCM VS1033 ADPCM recording. * - \ref VS_SM_ADPCM_HP VS1033 ADPCM high pass filter. * - \ref VS_SM_LINE_IN VS1033 ADPCM recording selector. * - \ref VS_SM_CLK_RANGE VS1033 input clock range. * * \return 0 on success, -1 otherwise. */ int VsPlayerReset(uint16_t mode) { /* Disable decoder interrupts and feeding. */ VsPlayerInterrupts(0); vs_status = VS_STATUS_STOPPED; /* Software reset. */ VsRegWrite(VS_MODE_REG, VS_SM_RESET); /* The decoder needs 9600 XTAL cycles. This is at least twice. */ NutDelay(VS10XX_SWRST_RECOVER); /* * Check for correct reset. */ if ((mode & VS_SM_RESET) != 0 || !VS10XX_DREQ_TST()) { /* If not succeeded, give it one more chance and try hw reset. */ SciReset(1); /* No idea how long we must held reset low. */ NutDelay(VS10XX_HWRST_DURATION); SciReset(0); /* No idea how long we need to wait here. */ NutDelay(VS10XX_HWRST_RECOVER); if (!VS10XX_DREQ_TST()) { return -1; } } /* Set codec mode. */ #if defined(VS10XX_BSYNC_BIT) VsRegWrite(VS_MODE_REG, mode); #else VsRegWrite(VS_MODE_REG, VS_SM_SDINEW | mode); #endif #if VS10XX_FREQ < 20000000UL VsRegWrite(VS_CLOCKF_REG, (uint16_t)(VS_CF_DOUBLER | (VS10XX_FREQ / 2000UL))); #else VsRegWrite(VS_CLOCKF_REG, (uint16_t)(VS10XX_FREQ / 2000UL)); #endif #if defined(AUDIO_VS1001K) /* Force frequency change (see datasheet). */ VsRegWrite(VS_INT_FCTLH_REG, 0x8008); #endif NutDelay(1); #if defined(VS10XX_SDI_SPI0_DEVICE) || defined(VS10XX_SCI_SPI0_DEVICE) /* Clear any spurious interrupts. */ outb(EIFR, BV(VS10XX_DREQ_BIT)); #endif return 0; } /*! * \brief Set mode register of the decoder. * * \param mode Any of the following flags may be or'ed (check the data sheet) * - \ref VS_SM_DIFF Left channel inverted. * - \ref VS_SM_LAYER12 Allow MPEG layers I and II. * - \ref VS_SM_MP12 Allow MPEG layers I and II on VS1001K. * - \ref VS_SM_FFWD VS1001K fast forward. * - \ref VS_SM_RESET Software reset. * - \ref VS_SM_OUTOFWAV Jump out of WAV decoding. * - \ref VS_SM_TESTS Allow SDI tests. * - \ref VS_SM_PDOWN Switch to power down mode. * - \ref VS_SM_BASS VS1001K bass/treble enhancer. * - \ref VS_SM_STREAM Stream mode. * - \ref VS_SM_SDISHARE Share SPI chip select. * - \ref VS_SM_SDINEW VS1002 native mode (automatically set). * - \ref VS_SM_ADPCM VS1033 ADPCM recording. * - \ref VS_SM_ADPCM_HP VS1033 ADPCM high pass filter. * - \ref VS_SM_LINE_IN VS1033 ADPCM recording selector. * - \ref VS_SM_CLK_RANGE VS1033 input clock range. * * \return Always 0. */ int VsPlayerSetMode(uint16_t mode) { ureg_t ief; ief = VsPlayerInterrupts(0); #if defined(VS10XX_BSYNC_BIT) VsRegWrite(VS_MODE_REG, mode); #else VsRegWrite(VS_MODE_REG, VS_SM_SDINEW | mode); #endif VsPlayerInterrupts(ief); return 0; } /*! * \brief Returns play time since last reset. * * \return Play time since reset in seconds */ uint16_t VsPlayTime(void) { uint16_t rc; ureg_t ief; ief = VsPlayerInterrupts(0); rc = VsRegRead(VS_DECODE_TIME_REG); VsPlayerInterrupts(ief); return rc; } /*! * \brief Returns status of the player. * * \return Any of the following value: * - VS_STATUS_STOPPED Player is ready to be started by VsPlayerKick(). * - VS_STATUS_RUNNING Player is running. * - VS_STATUS_EOF Player has reached the end of a stream after VsPlayerFlush() has been called. * - VS_STATUS_EMPTY Player runs out of data. VsPlayerKick() will restart it. */ unsigned int VsGetStatus(void) { return vs_status; } #ifdef __GNUC__ /*! * \brief Query MP3 stream header information. * * \param vshi Pointer to VS_HEADERINFO structure. * * \return 0 on success, -1 otherwise. */ int VsGetHeaderInfo(VS_HEADERINFO * vshi) { uint16_t *usp = (uint16_t *) vshi; ureg_t ief; ief = VsPlayerInterrupts(0); *usp = VsRegRead(VS_HDAT1_REG); *++usp = VsRegRead(VS_HDAT0_REG); VsPlayerInterrupts(ief); return 0; } #endif /*! * \brief Initialize decoder memory test and return result. * * \return Memory test result. * - Bit 0: Good X ROM * - Bit 1: Good Y ROM (high) * - Bit 2: Good Y ROM (low) * - Bit 3: Good Y RAM * - Bit 4: Good X RAM * - Bit 5: Good Instruction RAM (high) * - Bit 6: Good Instruction RAM (low) */ uint16_t VsMemoryTest(void) { uint16_t rc; ureg_t ief; static const char mtcmd[] PROGMEM = { 0x4D, 0xEA, 0x6D, 0x54, 0x00, 0x00, 0x00, 0x00 }; ief = VsPlayerInterrupts(0); #if defined(VS10XX_BSYNC_BIT) VsRegWrite(VS_MODE_REG, VS_SM_TESTS); #else VsRegWrite(VS_MODE_REG, VS_SM_TESTS | VS_SM_SDINEW); #endif VsSdiWrite_P(mtcmd, sizeof(mtcmd)); while(((rc = VsRegRead(VS_HDAT0_REG)) & 0x8000) == 0) { NutDelay(1); } #if defined(VS10XX_BSYNC_BIT) VsRegWrite(VS_MODE_REG, 0); #else VsRegWrite(VS_MODE_REG, VS_SM_SDINEW); #endif VsPlayerInterrupts(ief); return rc; } /*! * \brief Set volume. * * \param left Left channel attenuation, provided in 0.5 dB steps. * Set to 255 for ananlog power down. * \param right Right channel attenuation. * * \return Always 0. */ int VsSetVolume(ureg_t left, ureg_t right) { ureg_t ief; ief = VsPlayerInterrupts(0); VsRegWrite(VS_VOL_REG, ((uint16_t)left << VS_VOL_LEFT_LSB) | ((uint16_t)right << VS_VOL_RIGHT_LSB)); VsPlayerInterrupts(ief); return 0; } /*! * \brief Sine wave beep. * * \param fsin Frequency. * \param ms Duration. * * \return Always 0. */ int VsBeep(uint8_t fsin, uint8_t ms) { ureg_t ief; static const char on[] PROGMEM = { 0x53, 0xEF, 0x6E }; static const char off[] PROGMEM = { 0x45, 0x78, 0x69, 0x74 }; static const char end[] PROGMEM = { 0x00, 0x00, 0x00, 0x00 }; /* Disable decoder interrupts. */ ief = VsPlayerInterrupts(0); #if defined(VS10XX_BSYNC_BIT) VsRegWrite(VS_MODE_REG, VS_SM_TESTS); #else VsRegWrite(VS_MODE_REG, VS_SM_TESTS | VS_SM_SDINEW); #endif fsin = 56 + (fsin & 7) * 9; VsSdiWrite_P(on, sizeof(on)); VsSdiWrite(&fsin, 1); VsSdiWrite_P(end, sizeof(end)); NutDelay(ms); VsSdiWrite_P(off, sizeof(off)); VsSdiWrite_P(end, sizeof(end)); #if defined(VS10XX_BSYNC_BIT) VsRegWrite(VS_MODE_REG, 0); #else VsRegWrite(VS_MODE_REG, VS_SM_SDINEW); #endif /* Restore decoder interrupt enable. */ VsPlayerInterrupts(ief); return 0; } /*@}*/