diff options
Diffstat (limited to 'drivers/gaudio')
-rw-r--r-- | drivers/gaudio/Win32/gaudio_play_config.h | 34 | ||||
-rw-r--r-- | drivers/gaudio/Win32/gaudio_play_lld.c | 9 | ||||
-rw-r--r-- | drivers/gaudio/Win32/gaudio_record_config.h | 34 | ||||
-rw-r--r-- | drivers/gaudio/Win32/gaudio_record_lld.c | 11 | ||||
-rw-r--r-- | drivers/gaudio/gadc/driver.mk | 4 | ||||
-rw-r--r-- | drivers/gaudio/gadc/gaudio_record_board_template.h | 29 | ||||
-rw-r--r-- | drivers/gaudio/gadc/gaudio_record_config.h | 39 | ||||
-rw-r--r-- | drivers/gaudio/gadc/gaudio_record_lld.c | 43 | ||||
-rw-r--r-- | drivers/gaudio/pwm/driver.mk | 5 | ||||
-rw-r--r-- | drivers/gaudio/pwm/gaudio_play_board_template.h | 38 | ||||
-rw-r--r-- | drivers/gaudio/pwm/gaudio_play_config.h | 34 | ||||
-rw-r--r-- | drivers/gaudio/pwm/gaudio_play_lld.c | 117 | ||||
-rw-r--r-- | drivers/gaudio/pwm/readme.txt | 12 | ||||
-rw-r--r-- | drivers/gaudio/vs1053/driver.mk | 7 | ||||
-rw-r--r-- | drivers/gaudio/vs1053/gaudio_play_board_template.h | 71 | ||||
-rw-r--r-- | drivers/gaudio/vs1053/gaudio_play_config.h | 29 | ||||
-rw-r--r-- | drivers/gaudio/vs1053/gaudio_play_lld.c | 348 | ||||
-rw-r--r-- | drivers/gaudio/vs1053/readme.txt | 4 | ||||
-rw-r--r-- | drivers/gaudio/vs1053/vs1053.h | 101 |
19 files changed, 799 insertions, 170 deletions
diff --git a/drivers/gaudio/Win32/gaudio_play_config.h b/drivers/gaudio/Win32/gaudio_play_config.h index 4013e91f..c4830010 100644 --- a/drivers/gaudio/Win32/gaudio_play_config.h +++ b/drivers/gaudio/Win32/gaudio_play_config.h @@ -5,14 +5,6 @@ * http://ugfx.org/license.html */ -/** - * @file drivers/gaudio/Win32/gaudio_play_config.h - * @brief GAUDIO Play Driver config file. - * - * @addtogroup GAUDIO - * @{ - */ - #ifndef GAUDIO_PLAY_CONFIG_H #define GAUDIO_PLAY_CONFIG_H @@ -22,42 +14,16 @@ /* Driver hardware support. */ /*===========================================================================*/ -/** - * @brief The maximum sample frequency supported by this audio device - */ #define GAUDIO_PLAY_MAX_SAMPLE_FREQUENCY 44100 - -/** - * @brief The number of audio formats supported by this driver - */ #define GAUDIO_PLAY_NUM_FORMATS 2 - -/** - * @brief The available audio sample formats in order of preference - */ #define GAUDIO_PLAY_FORMAT1 ARRAY_DATA_16BITSIGNED #define GAUDIO_PLAY_FORMAT2 ARRAY_DATA_8BITUNSIGNED - -/** - * @brief The number of audio channels supported by this driver - */ #define GAUDIO_PLAY_NUM_CHANNELS 2 - -/** - * @brief Whether each channel is mono or stereo - */ #define GAUDIO_PLAY_CHANNEL0_IS_STEREO FALSE #define GAUDIO_PLAY_CHANNEL1_IS_STEREO TRUE - -/** - * @brief The list of audio channel names and their uses - * @{ - */ #define GAUDIO_PLAY_MONO 0 #define GAUDIO_PLAY_STEREO 1 -/** @} */ #endif /* GFX_USE_GAUDIO && GAUDIO_NEED_PLAY */ #endif /* GAUDIO_PLAY_CONFIG_H */ -/** @} */ diff --git a/drivers/gaudio/Win32/gaudio_play_lld.c b/drivers/gaudio/Win32/gaudio_play_lld.c index 6b4f2dab..c0adf03e 100644 --- a/drivers/gaudio/Win32/gaudio_play_lld.c +++ b/drivers/gaudio/Win32/gaudio_play_lld.c @@ -5,11 +5,6 @@ * http://ugfx.org/license.html */ -/** - * @file drivers/gaudio/Win32/gaudio_play_lld.c - * @brief GAUDIO - Play Driver file for Win32. - */ - #include "gfx.h" #if GFX_USE_GAUDIO && GAUDIO_NEED_PLAY @@ -47,7 +42,7 @@ static DWORD threadID; *************************************************************************/ static bool_t senddata(WAVEHDR *pwh) { - GAudioData *paud; + GDataBuffer *paud; // Get the next data block to send gfxSystemLock(); @@ -94,7 +89,7 @@ static DWORD WINAPI waveProc(LPVOID arg) { // Give the buffer back to the Audio Free List gfxSystemLock(); - gaudioPlayReleaseDataBlockI((GAudioData *)pwh->dwUser); + gaudioPlayReleaseDataBlockI((GDataBuffer *)pwh->dwUser); gfxSystemUnlock(); pwh->lpData = 0; nQueuedBuffers--; diff --git a/drivers/gaudio/Win32/gaudio_record_config.h b/drivers/gaudio/Win32/gaudio_record_config.h index 4d952e1d..5897212b 100644 --- a/drivers/gaudio/Win32/gaudio_record_config.h +++ b/drivers/gaudio/Win32/gaudio_record_config.h @@ -5,14 +5,6 @@ * http://ugfx.org/license.html */ -/** - * @file drivers/gaudio/Win32/gaudio_record_config.h - * @brief GAUDIO Record Driver config file. - * - * @addtogroup GAUDIO - * @{ - */ - #ifndef GAUDIO_RECORD_CONFIG_H #define GAUDIO_RECORD_CONFIG_H @@ -22,42 +14,16 @@ /* Driver hardware support. */ /*===========================================================================*/ -/** - * @brief The maximum sample frequency supported by this audio device - */ #define GAUDIO_RECORD_MAX_SAMPLE_FREQUENCY 44100 - -/** - * @brief The number of audio formats supported by this driver - */ #define GAUDIO_RECORD_NUM_FORMATS 2 - -/** - * @brief The available audio sample formats in order of preference - */ #define GAUDIO_RECORD_FORMAT1 ARRAY_DATA_16BITSIGNED #define GAUDIO_RECORD_FORMAT2 ARRAY_DATA_8BITUNSIGNED - -/** - * @brief The number of audio channels supported by this driver - */ #define GAUDIO_RECORD_NUM_CHANNELS 2 - -/** - * @brief Whether each channel is mono or stereo - */ #define GAUDIO_RECORD_CHANNEL0_IS_STEREO FALSE #define GAUDIO_RECORD_CHANNEL1_IS_STEREO TRUE - -/** - * @brief The list of audio channels and their uses - * @{ - */ #define GAUDIO_RECORD_MONO 0 #define GAUDIO_RECORD_STEREO 1 -/** @} */ #endif /* GFX_USE_GAUDIO && GAUDIO_NEED_RECORD */ #endif /* GAUDIO_RECORD_CONFIG_H */ -/** @} */ diff --git a/drivers/gaudio/Win32/gaudio_record_lld.c b/drivers/gaudio/Win32/gaudio_record_lld.c index 259707e3..c9ac8187 100644 --- a/drivers/gaudio/Win32/gaudio_record_lld.c +++ b/drivers/gaudio/Win32/gaudio_record_lld.c @@ -5,11 +5,6 @@ * http://ugfx.org/license.html */ -/** - * @file drivers/gaudio/Win32/gaudio_record_lld.c - * @brief GAUDIO - Record Driver file for Win32. - */ - #include "gfx.h" #if GFX_USE_GAUDIO && GAUDIO_NEED_RECORD @@ -47,7 +42,7 @@ static DWORD threadID; *************************************************************************/ static bool_t getbuffer(WAVEHDR *pwh) { - GAudioData *paud; + GDataBuffer *paud; // Get the next data block to send gfxSystemLock(); @@ -81,7 +76,7 @@ static bool_t getbuffer(WAVEHDR *pwh) { static DWORD WINAPI waveProc(LPVOID arg) { MSG msg; WAVEHDR *pwh; - GAudioData *paud; + GDataBuffer *paud; (void) arg; while (GetMessage(&msg, 0, 0, 0)) { @@ -93,7 +88,7 @@ static DWORD WINAPI waveProc(LPVOID arg) { waveInUnprepareHeader(ah, pwh, sizeof(WAVEHDR)); // Save the buffer in the audio record list - paud = (GAudioData *)pwh->dwUser; + paud = (GDataBuffer *)pwh->dwUser; paud->len = pwh->dwBytesRecorded; gfxSystemLock(); gaudioRecordSaveDataBlockI(paud); diff --git a/drivers/gaudio/gadc/driver.mk b/drivers/gaudio/gadc/driver.mk index 4d79da25..b5a2768a 100644 --- a/drivers/gaudio/gadc/driver.mk +++ b/drivers/gaudio/gadc/driver.mk @@ -3,3 +3,7 @@ GFXSRC += $(GFXLIB)/drivers/gaudio/gadc/gaudio_record_lld.c # Required include directories GFXINC += $(GFXLIB)/drivers/gaudio/gadc + +# Make sure the GADC sub-system is turned on +GFXDEFS += -DGFX_USE_GADC=GAUDIO_NEED_RECORD + diff --git a/drivers/gaudio/gadc/gaudio_record_board_template.h b/drivers/gaudio/gadc/gaudio_record_board_template.h index 26e87d88..42c15205 100644 --- a/drivers/gaudio/gadc/gaudio_record_board_template.h +++ b/drivers/gaudio/gadc/gaudio_record_board_template.h @@ -5,14 +5,6 @@ * http://ugfx.org/license.html */ -/** - * @file drivers/gaudio/gadc/gaudio_record_board_template.h - * @brief GAUDIO Record Driver board config board file - * - * @addtogroup GAUDIO - * @{ - */ - #ifndef _GAUDIO_RECORD_BOARD_H #define _GAUDIO_RECORD_BOARD_H @@ -20,31 +12,16 @@ /* Audio inputs on this board */ /*===========================================================================*/ -/** - * @brief The number of audio channels supported by this driver - * @note This is an example - */ #define GAUDIO_RECORD_NUM_CHANNELS 1 -/** - * @brief The list of audio channels and their uses - * @note This is an example - * @{ - */ +#define GAUDIO_RECORD_CHANNEL0_IS_STEREO FALSE + #define GAUDIO_RECORD_MICROPHONE 0 -/** @} */ -/** - * @brief The audio channel to GADC physical device assignment - * @note This is an example - * @{ - */ #ifdef GAUDIO_RECORD_LLD_IMPLEMENTATION - static uint32_t gaudin_lld_physdevs[GAUDIO_RECORD_NUM_CHANNELS] = { + static uint32_t gaudio_gadc_physdevs[GAUDIO_RECORD_NUM_CHANNELS] = { GADC_PHYSDEV_MICROPHONE, }; #endif -/** @} */ #endif /* _GAUDIO_RECORD_BOARD_H */ -/** @} */ diff --git a/drivers/gaudio/gadc/gaudio_record_config.h b/drivers/gaudio/gadc/gaudio_record_config.h index 22d8750f..345625ff 100644 --- a/drivers/gaudio/gadc/gaudio_record_config.h +++ b/drivers/gaudio/gadc/gaudio_record_config.h @@ -5,14 +5,6 @@ * http://ugfx.org/license.html */ -/** - * @file drivers/gaudio/gadc/gaudio_record_config.h - * @brief GAUDIN Record Driver config file. - * - * @addtogroup GAUDIO - * @{ - */ - #ifndef GAUDIO_RECORD_CONFIG_H #define GAUDIO_RECORD_CONFIG_H @@ -22,38 +14,13 @@ /* Driver hardware support. */ /*===========================================================================*/ -/** - * @brief The audio record sample type - * @details For this driver it matches the cpu sample type - */ -typedef adcsample_t audio_record_sample_t; - -/** - * @brief The maximum sample frequency supported by this audio device - * @details For this driver it matches the GADC maximum high speed sample rate - */ -#define GAUDIO_RECORD_MAX_SAMPLE_FREQUENCY GADC_MAX_HIGH_SPEED_SAMPLERATE +#define GAUDIO_RECORD_MAX_SAMPLE_FREQUENCY GADC_MAX_HIGH_SPEED_SAMPLERATE +#define GAUDIO_RECORD_NUM_FORMATS 1 +#define GAUDIO_RECORD_FORMAT1 GADC_SAMPLE_FORMAT -/** - * @brief The number of bits in a sample - * @details For this driver it matches the cpu sample bits - */ -#define GAUDIO_RECORD_BITS_PER_SAMPLE GADC_BITS_PER_SAMPLE - -/** - * @brief The format of an audio sample - * @details For this driver it matches the cpu sample format - */ -#define GAUDIO_RECORD_SAMPLE_FORMAT GADC_SAMPLE_FORMAT - -/** - * For the GAUDIO driver that uses GADC - all the remaining config definitions are specific - * to the board. - */ /* Include the user supplied board definitions */ #include "gaudio_record_board.h" #endif /* GFX_USE_GAUDIO && GAUDIO_NEED_RECORD */ #endif /* GAUDIO_RECORD_CONFIG_H */ -/** @} */ diff --git a/drivers/gaudio/gadc/gaudio_record_lld.c b/drivers/gaudio/gadc/gaudio_record_lld.c index ee994dc1..1d70a259 100644 --- a/drivers/gaudio/gadc/gaudio_record_lld.c +++ b/drivers/gaudio/gadc/gaudio_record_lld.c @@ -5,22 +5,7 @@ * http://ugfx.org/license.html */ -/** - * @file drivers/gaudio/gadc/gaudio_record_lld.c - * @brief GAUDIO - Record Driver file for using the cpu ADC (via GADC). - * - * @addtogroup GAUDIO - * - * @{ - */ - -/** - * We are now implementing the driver - pull in our channel table - * from the board definitions. - */ #define GAUDIO_RECORD_IMPLEMENTATION - - #include "gfx.h" #if GFX_USE_GAUDIO && GAUDIO_NEED_RECORD @@ -33,30 +18,38 @@ /* Include the driver defines */ #include "src/gaudio/driver_record.h" +static void gadcCallbackI(void) { + GDataBuffer *pd; + + pd = gadcHighSpeedGetDataI(); + if (pd) + gaudioRecordSaveDataBlockI(pd); +} + /*===========================================================================*/ /* External declarations. */ /*===========================================================================*/ -void gaudin_lld_init(const gaudin_params *paud) { +bool_t gaudio_record_lld_init(uint16_t channel, uint32_t frequency, ArrayDataFormat format) { + /* Check the parameters */ + if (channel >= GAUDIO_RECORD_NUM_CHANNELS || frequency > GAUDIO_RECORD_MAX_SAMPLE_FREQUENCY || format != GAUDIO_RECORD_FORMAT1) + return FALSE; + /* Setup the high speed GADC */ - gadcHighSpeedInit(gaudin_lld_physdevs[paud->channel], paud->frequency, paud->buffer, paud->bufcount, paud->samplesPerEvent); + gadcHighSpeedInit(gaudio_gadc_physdevs[channel], frequency); /* Register ourselves for ISR callbacks */ - gadcHighSpeedSetISRCallback(GAUDIN_ISR_CompleteI); + gadcHighSpeedSetISRCallback(gadcCallbackI); - /** - * The gadc driver handles any errors for us by restarting the transaction so there is - * no need for us to setup anything for GAUDIN_ISR_ErrorI() - */ + return TRUE; } -void gaudin_lld_start(void) { +void gaudio_record_lld_start(void) { gadcHighSpeedStart(); } -void gaudin_lld_stop(void) { +void gaudio_record_lld_stop(void) { gadcHighSpeedStop(); } #endif /* GFX_USE_GAUDIO && GAUDIO_NEED_RECORD */ -/** @} */ diff --git a/drivers/gaudio/pwm/driver.mk b/drivers/gaudio/pwm/driver.mk new file mode 100644 index 00000000..52f752aa --- /dev/null +++ b/drivers/gaudio/pwm/driver.mk @@ -0,0 +1,5 @@ +# List the required driver. +GFXSRC += $(GFXLIB)/drivers/gaudio/pwm/gaudio_play_lld.c + +# Required include directories +GFXINC += $(GFXLIB)/drivers/gaudio/pwm diff --git a/drivers/gaudio/pwm/gaudio_play_board_template.h b/drivers/gaudio/pwm/gaudio_play_board_template.h new file mode 100644 index 00000000..24039d17 --- /dev/null +++ b/drivers/gaudio/pwm/gaudio_play_board_template.h @@ -0,0 +1,38 @@ +/* + * This file is subject to the terms of the GFX License. If a copy of + * the license was not distributed with this file, you can obtain one at: + * + * http://ugfx.org/license.html + */ + +#ifndef GAUDIO_PLAY_BOARD_H +#define GAUDIO_PLAY_BOARD_H + +/* + * This routine is defined in the driver - the timer interrupt should call this routine. + * + * static void gaudio_play_pwm_timer_callbackI(void); + * + */ + +static bool gaudio_play_pwm_setup(uint32_t frequency, ArrayDataFormat format) { + /* Initialise the PWM - use a midpoint value for the initial PWM value */ + /* Initialise the timer interrupt @ frequency */ + /* Return FALSE if any parameter invalid */ +} + +static void gaudio_play_pwm_start(void) { + /* Start the PWM */ + /* Start the timer interrupt */ +} + +static void gaudio_play_pwm_stop(void) { + /* Stop the timer interrupt */ + /* Stop the PWM */ +} + +static void gaudio_play_pwm_setI(uint16_t value) { + /* Set the PWM value */ +} + +#endif /* GAUDIO_PLAY_BOARD_H */ diff --git a/drivers/gaudio/pwm/gaudio_play_config.h b/drivers/gaudio/pwm/gaudio_play_config.h new file mode 100644 index 00000000..9c65cd11 --- /dev/null +++ b/drivers/gaudio/pwm/gaudio_play_config.h @@ -0,0 +1,34 @@ +/* + * This file is subject to the terms of the GFX License. If a copy of + * the license was not distributed with this file, you can obtain one at: + * + * http://ugfx.org/license.html + */ + +#ifndef GAUDIO_PLAY_CONFIG_H +#define GAUDIO_PLAY_CONFIG_H + +#if GFX_USE_GAUDIO && GAUDIO_NEED_PLAY + +/*===========================================================================*/ +/* Driver hardware support. */ +/*===========================================================================*/ + +/* These may need to change for your hardware. If so copy this file to your + * project directory and then alter it. + * The maximum sample frequency should be less than + * Max PWM Clock / (2 ^ Bits per sample) + * eg. For the AT91SAM7 max PWM clock = 48MHz / 2 + * For 10 bit PWM accuracy that means GAUDIO_PLAY_MAX_SAMPLE_FREQUENCY = 23,437 Hz + */ +#define GAUDIO_PLAY_MAX_SAMPLE_FREQUENCY 22000 +#define GAUDIO_PLAY_NUM_FORMATS 2 +#define GAUDIO_PLAY_FORMAT1 ARRAY_DATA_10BITUNSIGNED +#define GAUDIO_PLAY_FORMAT2 ARRAY_DATA_8BITUNSIGNED +#define GAUDIO_PLAY_NUM_CHANNELS 1 +#define GAUDIO_PLAY_CHANNEL0_IS_STEREO FALSE +#define GAUDIO_PLAY_MONO 0 + +#endif /* GFX_USE_GAUDIO && GAUDIO_NEED_PLAY */ + +#endif /* GAUDIO_PLAY_CONFIG_H */ diff --git a/drivers/gaudio/pwm/gaudio_play_lld.c b/drivers/gaudio/pwm/gaudio_play_lld.c new file mode 100644 index 00000000..07fd14b2 --- /dev/null +++ b/drivers/gaudio/pwm/gaudio_play_lld.c @@ -0,0 +1,117 @@ +/* + * This file is subject to the terms of the GFX License. If a copy of + * the license was not distributed with this file, you can obtain one at: + * + * http://ugfx.org/license.html + */ + +#include "gfx.h" + +#if GFX_USE_GAUDIO && GAUDIO_NEED_PLAY + +/* Include the driver defines */ +#include "src/gaudio/driver_play.h" + +/* Forward definition */ +static void gaudio_play_pwm_timer_callbackI(void); + +/* Include the board interface */ +#include "gaudio_play_board.h" + +static GDataBuffer *pplay; +static ArrayDataFormat playfmt; +static size_t playlen; +static uint8_t *pdata; + +static void gaudio_play_pwm_timer_callbackI(void) { + if (pplay) { + + // Get the next value from the current data buffer + if (gfxSampleFormatBits(playfmt) > 8) { + gaudio_play_pwm_setI(*(uint16_t *)pdata); + pdata += 2; + } else { + gaudio_play_pwm_setI(*pdata); + pdata++; + } + + // Are we done yet + if (--playlen) + return; + gaudioPlayReleaseDataBlockI(pplay); + + // Get a new data buffer + if (!(pplay = gaudioPlayGetDataBlockI())) { + // All is done + gaudioPlayDoneI(); + return; + } + + } else { + // Get a new data buffer + if (!(pplay = gaudioPlayGetDataBlockI())) + return; + } + + // Set up ready for the new buffer + playlen = pplay->len; + if (gfxSampleFormatBits(playfmt) > 8) + playlen >>= 1; + pdata = (uint8_t *)(pplay+1); +} + + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +bool_t gaudio_play_lld_init(uint16_t channel, uint32_t frequency, ArrayDataFormat format) { + (void) channel; + + if (format != ARRAY_DATA_8BITUNSIGNED && format != ARRAY_DATA_10BITUNSIGNED) + return FALSE; + + playfmt = format; + return gaudio_play_pwm_setup(frequency, format); +} + +bool_t gaudio_play_lld_set_volume(uint8_t vol) { + (void) vol; + return FALSE; +} + +void gaudio_play_lld_start(void) { + + gfxSystemLock(); + // Get a new data buffer + if (pplay || !(pplay = gaudioPlayGetDataBlockI())) { + gfxSystemUnlock(); // Nothing to do + return; + } + + // Set up ready for the new buffer + playlen = pplay->len; + if (gfxSampleFormatBits(playfmt) > 8) + playlen >>= 1; + pdata = (uint8_t *)(pplay+1); + gfxSystemUnlock(); + + // Start the playing + gaudio_play_pwm_start(); +} + +void gaudio_play_lld_stop(void) { + // Stop everything + gaudio_play_pwm_stop(); + + // We may need to clean up the remaining buffer. + gfxSystemLock(); + if (pplay) { + gaudioPlayReleaseDataBlockI(pplay); + pplay = 0; + gaudioPlayDoneI(); + } + gfxSystemUnlock(); +} + +#endif /* GFX_USE_GAUDIO && GAUDIO_NEED_PLAY */ diff --git a/drivers/gaudio/pwm/readme.txt b/drivers/gaudio/pwm/readme.txt new file mode 100644 index 00000000..1dd3ed9a --- /dev/null +++ b/drivers/gaudio/pwm/readme.txt @@ -0,0 +1,12 @@ +This driver uses a PWM output and a timer to implement an audio play channel. + +Whilst the default config settings will probably work for your hardware, you may need to change them. +If so copy gaudio_play_config.h to your project directory and then alter it. + +The maximum sample frequency is governed primarily by the number of bits of resolution and the +maximum PWM clock rate. The maximum sample frequency should be less than... + + Max PWM Clock / (2 ^ Bits per sample) + +eg. For the AT91SAM7 max PWM clock = 48MHz / 2 + For 10 bit PWM accuracy that means GAUDIO_PLAY_MAX_SAMPLE_FREQUENCY = 23,437 Hz diff --git a/drivers/gaudio/vs1053/driver.mk b/drivers/gaudio/vs1053/driver.mk new file mode 100644 index 00000000..d0419c80 --- /dev/null +++ b/drivers/gaudio/vs1053/driver.mk @@ -0,0 +1,7 @@ +# List the required driver. +GFXSRC += $(GFXLIB)/drivers/gaudio/vs1053/gaudio_play_lld.c + +# Required include directories +GFXINC += $(GFXLIB)/drivers/gaudio/vs1053 + +GFXDEFS += -DGFX_USE_GTIMER=TRUE diff --git a/drivers/gaudio/vs1053/gaudio_play_board_template.h b/drivers/gaudio/vs1053/gaudio_play_board_template.h new file mode 100644 index 00000000..d6125bbc --- /dev/null +++ b/drivers/gaudio/vs1053/gaudio_play_board_template.h @@ -0,0 +1,71 @@ +/* + * This file is subject to the terms of the GFX License. If a copy of + * the license was not distributed with this file, you can obtain one at: + * + * http://ugfx.org/license.html + */ + +#ifndef GAUDIO_PLAY_BOARD_H +#define GAUDIO_PLAY_BOARD_H + +// Initialise the board +static void board_init(void) { + +} + +// Chip is initialised enough so we can talk fast to it +static void board_init_end(void) { + +} + +// Reset the board +static void board_reset(void) { + +} + +// Returns the state of the dreq pin +static bool board_dreq(void) { + +} + +// Start a command write +static void board_startcmdwrite(void) { + +} + +// End a command write +static void board_endcmdwrite(void) { + +} + +// Start a command read +static void board_startcmdread(void) { + +} + +// End a command read +static void board_endcmdread(void) { + +} + +// Start a data write +static void board_startdatawrite(void) { + +} + +// End a data write +static void board_enddatawrite(void) { + +} + +// Write data to the SPI port +static void board_spiwrite(const uint8_t *buf, unsigned len) { + +} + +// Read data from the SPI port +static void board_spiread(uint8_t *buf, unsigned len) { + +} + +#endif /* GAUDIO_PLAY_BOARD_H */ diff --git a/drivers/gaudio/vs1053/gaudio_play_config.h b/drivers/gaudio/vs1053/gaudio_play_config.h new file mode 100644 index 00000000..bd2af503 --- /dev/null +++ b/drivers/gaudio/vs1053/gaudio_play_config.h @@ -0,0 +1,29 @@ +/* + * This file is subject to the terms of the GFX License. If a copy of + * the license was not distributed with this file, you can obtain one at: + * + * http://ugfx.org/license.html + */ + +#ifndef GAUDIO_PLAY_CONFIG_H +#define GAUDIO_PLAY_CONFIG_H + +#if GFX_USE_GAUDIO && GAUDIO_NEED_PLAY + +/*===========================================================================*/ +/* Driver hardware support. */ +/*===========================================================================*/ + +#define GAUDIO_PLAY_MAX_SAMPLE_FREQUENCY 48000 +#define GAUDIO_PLAY_NUM_FORMATS 2 +#define GAUDIO_PLAY_FORMAT1 ARRAY_DATA_16BITSIGNED +#define GAUDIO_PLAY_FORMAT2 ARRAY_DATA_8BITUNSIGNED +#define GAUDIO_PLAY_NUM_CHANNELS 2 +#define GAUDIO_PLAY_CHANNEL0_IS_STEREO FALSE +#define GAUDIO_PLAY_CHANNEL1_IS_STEREO TRUE +#define GAUDIO_PLAY_MONO 0 +#define GAUDIO_PLAY_STEREO 1 + +#endif /* GFX_USE_GAUDIO && GAUDIO_NEED_PLAY */ + +#endif /* GAUDIO_PLAY_CONFIG_H */ diff --git a/drivers/gaudio/vs1053/gaudio_play_lld.c b/drivers/gaudio/vs1053/gaudio_play_lld.c new file mode 100644 index 00000000..9e77e383 --- /dev/null +++ b/drivers/gaudio/vs1053/gaudio_play_lld.c @@ -0,0 +1,348 @@ +/* + * This file is subject to the terms of the GFX License. If a copy of + * the license was not distributed with this file, you can obtain one at: + * + * http://ugfx.org/license.html + */ + +#include "gfx.h" + +#if GFX_USE_GAUDIO && GAUDIO_NEED_PLAY + +/* Include the driver defines */ +#include "src/gaudio/driver_play.h" + +/* Include the vs1053 registers */ +#include "drivers/gaudio/vs1053/vs1053.h" + +/* Include the board interface */ +#include "gaudio_play_board.h" + +// Override-able parameters +#ifndef VS1053_CLK + #define VS1053_CLK 12288000 +#endif +#ifndef VS1053_FIRMWARE_PATCH + #define VS1053_FIRMWARE_PATCH FALSE +#endif + +// Load the patch file if desired. New format patches only. +#if VS1053_FIRMWARE_PATCH + #define SKIP_PLUGIN_VARNAME + static const uint16_t plugin[] = { /* Compressed plugin */ + #include "vs1053_patch.plg" + }; +#endif + +// Set various stuff based on the clock +#if VS1053_CLK >= 16192000 + #define SCI_MODE_STARTUP (SCI_MODE_DEFAULTS|SM_CLK_RANGE) + #define VS1053_CLKI (VS1053_CLK/2) +#else + #define SCI_MODE_STARTUP (SCI_MODE_DEFAULTS) + #define VS1053_CLKI (VS1053_CLK) +#endif +#if VS1053_CLKI > 13000000 || VS1053_CLKI < 12000000 + #error "GAUDIO(vs1053): VS1053_CLK is out of range" +#endif +#if VS1053_CLKI == 12288000 + #define SC_FREQ_ADJUST 0x0000 +#else + #define SC_FREQ_ADJUST ((VS1053_CLKI-8000000)/4000) +#endif +#define VS1053_MAX_SAMPLE_RATE (VS1053_CLKI/256) +#if VS1053_CLKI > 1228800 + #define SC_CLOCK_MODE (SC_MULT_3|SC_ADD_1|SC_FREQ_ADJUST) +#else + #define SC_CLOCK_MODE (SC_MULT_3_5|SC_ADD_1|SC_FREQ_ADJUST) +#endif + +// Our static variables +static bool_t vs1053_isinit; +static GTimer playTimer; + +// Some common macro's +#define waitforready() while(!board_dreq()) gfxSleepMilliseconds(5) + +static void cmd_write(uint16_t addr, uint16_t data) { + char buf[4]; + buf[0] = 2; + buf[1] = (char)addr; + buf[2] = (char)(data >> 8); + buf[3] = (char)data; + + waitforready(); + board_startcmdwrite(); + board_spiwrite(buf, 4); + board_endcmdwrite(); +} + +#if VS1053_CLK > 12288000 + static inline void cmd_writenodreq(uint16_t addr, uint16_t data) { + uint8_t buf[4]; + + // This is the same as cmd_write() except for it doesn't wait for dreq first + buf[0] = 2; + buf[1] = (uint8_t)addr; + buf[2] = (uint8_t)(data >> 8); + buf[3] = (uint8_t)data; + + board_startcmdwrite(); + board_spiwrite(buf, 4); + board_endcmdwrite(); + } +#endif + +static uint16_t cmd_read(uint16_t addr) { + uint8_t buf[2]; + + buf[0] = 3; + buf[1] = (char)addr; + + board_startcmdread(); + board_spiwrite(buf, 2); + board_spiread(buf, 2); + board_endcmdread(); + return (((uint16_t)buf[0])<<8)|buf[1]; +} + +static void data_write(const uint8_t *data, unsigned len) { + board_startdatawrite(); + board_spiwrite(data, len); + board_enddatawrite(); +} + +#if VS1053_FIRMWARE_PATCH + static void LoadUserCode(void) { + int i; + uint16_t addr, n, val; + + for(i=0; i<sizeof(plugin)/sizeof(plugin[0]);) { + addr = plugin[i++]; + n = plugin[i++]; + if (n & 0x8000U) { /* RLE run, replicate n samples */ + n &= 0x7FFF; + val = plugin[i++]; + while (n--) + cmd_write(addr, val); + } else { /* Copy run, copy n samples */ + while (n--) + cmd_write(addr, plugin[i++]); + } + } + } +#endif + +static void vs1053_hard_reset(void) { + gtimerInit(&playTimer); + + board_init(); + board_reset(); + + #if VS1053_CLK > 12288000 + cmd_writenodreq(SCI_MODE, SCI_MODE_STARTUP); // Set super-clock before dreq + #endif + + // Set up registers + cmd_write(SCI_MODE, SCI_MODE_STARTUP); // Set mode + cmd_write(SCI_CLOCKF, SC_CLOCK_MODE); // Set clocks + board_init_end(); // Clocks are now set up + cmd_write(SCI_BASS, 0x0000); // No treble or bass boost + cmd_write(SCI_VOL, VOL_MAX); // Maximum volume + + // Load any firmware + #if VS1053_FIRMWARE_PATCH + LoadUserCode(); + + // Reset mode just in case + cmd_write(SCI_MODE, SCI_MODE_STARTUP); + #endif +} + +static void vs1053_soft_reset(void) { + cmd_write(SCI_MODE, cmd_read(SCI_MODE)|SM_RESET); + gfxSleepMilliseconds(1); // Wait for at least 2uS + waitforready(); + + // Reload any firmware + #if VS1053_FIRMWARE_PATCH + LoadUserCode(); + + // Reset mode just in case + cmd_write(SCI_MODE, SCI_MODE_STARTUP); + #endif +} + +static uint16_t vs1053_getendbyte(void) { + cmd_write(SCI_WRAMADDR, WRAMADDR_EXTRAPARAMS+4); + return cmd_read(SCI_WRAM); +} + +static GTimer playTimer; +static GDataBuffer *pplay; +static size_t playlen; +static uint8_t *pdata; + +static void FeedData(void *param) { + unsigned len; + (void) param; + + // While there is data space + while (!board_dreq()) { + + // Send up to 32 bytes + len = playlen; + if (len > 32) len = 32; + data_write(pdata, len); + pdata += len; + playlen -= len; + + // Have we finished the buffer + while (!playlen) { + gfxSystemLock(); + gaudioPlayReleaseDataBlockI(pplay); + + // Get a new data buffer + if (!(pplay = gaudioPlayGetDataBlockI())) { + // We should really only do the play-done when the audio + // has really finished playing. Unfortunately there seems + // to be no documented way of determining this. + gaudioPlayDoneI(); + gfxSystemUnlock(); + gtimerStop(&playTimer); + return; + } + + // Set up ready for the new buffer + playlen = pplay->len; + pdata = (uint8_t *)(pplay+1); + gfxSystemUnlock(); + } + } +} + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +bool_t gaudio_play_lld_init(uint16_t channel, uint32_t frequency, ArrayDataFormat format) { + uint32_t brate; + uint32_t bps; + uint8_t buf[4]; + static const uint8_t hdr1[] = { + 'R', 'I', 'F', 'F', + 0xFF, 0xFF, 0xFF, 0xFF, + 'W', 'A', 'V', 'E', + 'f', 'm', 't', ' ', + 16, 0, 0, 0, + 0x01, 0x00, + }; + static const uint8_t hdr2[] = { + 'd', 'a', 't', 'a', + 0xFF, 0xFF, 0xFF, 0xFF, + }; + + if (format != ARRAY_DATA_8BITUNSIGNED && format != ARRAY_DATA_16BITSIGNED) + return FALSE; + if (frequency > VS1053_MAX_SAMPLE_RATE) + return FALSE; + + // Reset the chip if needed + if (!vs1053_isinit) { + vs1053_hard_reset(); + vs1053_isinit = TRUE; + } + + // Setup + bps = (gfxSampleFormatBits(format)+7)/8; + if (channel == GAUDIO_PLAY_STEREO) + bps *= 2; + brate = frequency * bps; + + // Write the RIFF header + waitforready(); + data_write(hdr1, sizeof(hdr1)); + buf[0] = channel == GAUDIO_PLAY_STEREO ? 2 : 1; buf[1] = 0; data_write(buf, 2); + buf[0] = frequency; buf[1] = frequency>>8; buf[2] = frequency>>16; buf[3] = frequency>>24; data_write(buf, 4); + buf[0] = brate; buf[1] = brate>>8; buf[2] = brate>>16; buf[3] = brate>>24; data_write(buf, 4); + waitforready(); // 32 bytes max before checking + buf[0] = bps; buf[1] = 0; data_write(buf, 2); + buf[0] = gfxSampleFormatBits(format); buf[1] = 0; data_write(buf, 2); + data_write(hdr2, sizeof(hdr2)); + return TRUE; +} + +bool_t gaudio_play_lld_set_volume(uint8_t vol) { + // Volume is 0xFE -> 0x00. Adjust vol to match + vol = ~vol; + if (vol == 0xFF) vol = 0xFE; + + cmd_write(SCI_VOL, ((uint16_t)vol) << 8 | vol); + return TRUE; +} + +void gaudio_play_lld_start(void) { + + gfxSystemLock(); + // Get a new data buffer + if (pplay || !(pplay = gaudioPlayGetDataBlockI())) { + gfxSystemUnlock(); // Nothing to do + return; + } + + // Set up ready for the new buffer + playlen = pplay->len; + pdata = (uint8_t *)(pplay+1); + gfxSystemUnlock(); + + // Start the playing by starting the timer and executing FeedData immediately just to get things started + // We really should set the timer to be equivalent to half the available data but that is just too hard to calculate. + gtimerStart(&playTimer, FeedData, 0, TRUE, 5); + FeedData(0); +} + +void gaudio_play_lld_stop(void) { + uint8_t ch; + unsigned i; + + // Stop the timer interrupt + gtimerStop(&playTimer); + + // We may need to clean up the remaining buffer. + gfxSystemLock(); + if (pplay) { + gaudioPlayReleaseDataBlockI(pplay); + pplay = 0; + gaudioPlayDoneI(); + } + gfxSystemUnlock(); + + // Set CANCEL + cmd_write(SCI_MODE, cmd_read(SCI_MODE)|SM_CANCEL); + + // Write up to 2048 bytes of data + ch = 0; + for(i = 0; i < 2048; i++) { + if (!(i & 0x1F)) { + waitforready(); + if (!(cmd_read(SCI_MODE) & SM_CANCEL)) + break; + } + data_write(&ch, 1); + } + + // Make sure the cancel worked + waitforready(); + if ((cmd_read(SCI_MODE) & SM_CANCEL)) + vs1053_soft_reset(); + + // Send the terminating data + ch = vs1053_getendbyte(); + for(i = 0; i < 2052; i++) { + if (!(i & 0x1F)) + waitforready(); + data_write(&ch, 1); + } +} + +#endif /* GFX_USE_GAUDIO && GAUDIO_NEED_PLAY */ diff --git a/drivers/gaudio/vs1053/readme.txt b/drivers/gaudio/vs1053/readme.txt new file mode 100644 index 00000000..6e99e56f --- /dev/null +++ b/drivers/gaudio/vs1053/readme.txt @@ -0,0 +1,4 @@ +This chip supports playing in many formats including MP3 etc. +For this driver however we only support PCM in 8 bit unisgned and 16 bit signed formats. + +Requires GFX_USE_GTIMER
\ No newline at end of file diff --git a/drivers/gaudio/vs1053/vs1053.h b/drivers/gaudio/vs1053/vs1053.h new file mode 100644 index 00000000..1ae613be --- /dev/null +++ b/drivers/gaudio/vs1053/vs1053.h @@ -0,0 +1,101 @@ +/* + * This file is subject to the terms of the GFX License. If a copy of + * the license was not distributed with this file, you can obtain one at: + * + * http://ugfx.org/license.html + */ + +#ifndef _VS1053_H +#define _VS1053_H + +// Registers +#define SCI_MODE 0x00 + #define SM_DIFF 0x0001 + #define SM_LAYER12 0x0002 + #define SM_RESET 0x0004 + #define SM_CANCEL 0x0008 + #define SM_EARSPEAKER_LO 0x0010 + #define SM_TESTS 0x0020 + #define SM_STREAM 0x0040 + #define SM_EARSPEAKER_HI 0x0080 + #define SM_DACT 0x0100 + #define SM_SDIORD 0x0200 + #define SM_SDISHARE 0x0400 + #define SM_SDINEW 0x0800 + #define SM_ADPCM 0x1000 + #define SM_LINE1 0x4000 + #define SM_CLK_RANGE 0x8000 + #define SCI_MODE_DEFAULTS (SM_LINE1|SM_SDINEW) +#define SCI_STATUS 0x01 + #define SS_DO_NOT_JUMP 0x8000 + #define SS_SWING_MASK 0x7000 + #define SS_SWING_SHIFT 12 + #define SS_VCM_OVERLOAD 0x0800 + #define SS_VCM_DISABLE 0x0400 + #define SS_VER_MASK 0x00F0 + #define SS_VER_SHIFT 4 + #define SS_APDOWN2 0x0008 + #define SS_APDOWN1 0x0004 + #define SS_SS_AD_CLOCK 0x0002 + #define SS_REFERENCE_SEL 0x0001 +#define SCI_BASS 0x02 + #define ST_AMPLITUDE_MASK 0xF000 + #define ST_AMPLITUDE_SHIFT 12 + #define ST_FREQLIMIT_MASK 0x0F00 + #define ST_FREQLIMIT_SHIFT 8 + #define SB_AMPLITUDE_MASK 0x00F0 + #define SB_AMPLITUDE_SHIFT 4 + #define SB_FREQLIMIT_MASK 0x000F + #define SB_FREQLIMIT_SHIFT 0 +#define SCI_CLOCKF 0x03 + #define SC_MULT_1 0x0000 + #define SC_MULT_2 0x2000 + #define SC_MULT_2_5 0x4000 + #define SC_MULT_3 0x6000 + #define SC_MULT_3_5 0x8000 + #define SC_MULT_4 0xa000 + #define SC_MULT_4_5 0xc000 + #define SC_MULT_5 0xe000 + #define SC_ADD_NONE 0x0000 + #define SC_ADD_1 0x0800 + #define SC_ADD_1_5 0x1000 + #define SC_ADD_2 0x1800 + #define SC_FREQ_MASK 0x07FF +#define SCI_DECODE_TIME 0x04 +#define SCI_AUDATA 0x05 + #define SR_RATE_MASK 0xFFFE + #define SR_IS_STEREO 0x0001 +#define SCI_WRAM 0x06 +#define SCI_WRAMADDR 0x07 + #define WRAMADDR_XDATA 0x1800 + #define WRAMADDR_YDATA 0x5800 + #define WRAMADDR_INSTR 0x8040 + #define WRAMADDR_IO 0xC000 + #define WRAMADDR_EXTRAPARAMS 0x1E02 +#define SCI_HDAT0 0x08 +#define SCI_HDAT1 0x09 + #define HD_FMT_NONE 0x0000 + #define HD_FMT_WAV 0x7665 + #define HD_FMT_AAC_ADTS 0x4154 + #define HD_FMT_AAC_ADIF 0x4144 + #define HD_FMT_AAC_M4A 0x4D34 + #define HD_FMT_WMA 0x574D + #define HD_FMT_MIDI 0x4D54 + #define HD_FMT_OGG 0x4F67 + #define HD_FMT_MP3_MIN 0xFFE0 + #define HD_FMT_MP3_MAX 0xFFFF +#define SCI_AIADDR 0x0A +#define SCI_VOL 0x0B + #define VOL_LEFT_MASK 0xFF00 + #define VOL_LEFT_SHIFT 8 + #define VOL_RIGHT_MASK 0x00FF + #define VOL_RIGHT_SHIFT 0 + #define VOL_POWERDOWN 0xFFFF + #define VOL_MAX 0x0000 + #define VOL_MIN 0xFEFE +#define SCI_AICTRL0 0x0C +#define SCI_AICTRL1 0x0D +#define SCI_AICTRL2 0x0E +#define SCI_AICTRL3 0x0F + +#endif /* _VS1053_H */ |