| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480 |
- /*
- * 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 <cfg/arch/gpio.h>
- #include <cfg/audio.h>
- #include <dev/irqreg.h>
- #include <dev/vs10xx.h>
- #include <sys/atom.h>
- #include <sys/event.h>
- #include <sys/timer.h>
- #include <sys/heap.h>
- #include <sys/bankmem.h>
- #include <stddef.h>
- #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 <dev/sppif0.h>
- #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 <dev/sbbif0.h>
- #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 <dev/sbbif1.h>
- #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 <dev/sbbif2.h>
- #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 <dev/sbbif3.h>
- #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 <dev/sppif0.h>
- #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 <dev/sbbif0.h>
- #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 <dev/sbbif1.h>
- #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 <dev/sbbif2.h>
- #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 <dev/sbbif3.h>
- #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 <dev/vs10xx.h>
- *
- * 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;
- }
- /*@}*/
|