From 11c9033ff00c615da7d3106baca9d38fe6d58788 Mon Sep 17 00:00:00 2001 From: inmarket Date: Wed, 19 Feb 2014 12:30:07 +1000 Subject: Compiler warning fix --- src/ginput/mouse.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/ginput/mouse.c b/src/ginput/mouse.c index c7a20ec1..f7842e33 100644 --- a/src/ginput/mouse.c +++ b/src/ginput/mouse.c @@ -189,6 +189,8 @@ void _tsOrientClip(MouseReading *pt, GDisplay *g, bool_t doClip) { break; } #else + (void) g; + c0 = cross[0].x; c1 = cross[1].x; c2 = cross[2].x; -- cgit v1.2.3 From a56e4ac7dcbf2776690c96656dbcb48b2cf2d818 Mon Sep 17 00:00:00 2001 From: inmarket Date: Thu, 27 Feb 2014 08:04:54 +1000 Subject: First GAUDOUT work. Still incomplete but compiling. Also moved drivers/gaudin to drivers/audio as most audio codecs support input and output in a single device. --- src/gaudin/driver.h | 4 +- src/gaudin/gaudin.c | 8 ++-- src/gaudin/sys_defs.h | 4 +- src/gaudout/driver.h | 123 ++++++++++++++++++++++++++++++++++++++++++++++++ src/gaudout/gaudout.c | 111 ++++++++++++++++++++++++++++++++++++++++++- src/gaudout/sys_defs.h | 121 +++++++++++++++++++++++++++++++++++++++++++++++ src/gaudout/sys_rules.h | 21 +++++++++ 7 files changed, 382 insertions(+), 10 deletions(-) create mode 100644 src/gaudout/driver.h (limited to 'src') diff --git a/src/gaudin/driver.h b/src/gaudin/driver.h index bd04858a..b534e2a5 100644 --- a/src/gaudin/driver.h +++ b/src/gaudin/driver.h @@ -83,14 +83,14 @@ void gaudin_lld_init(const gaudin_params *paud); * * @api */ -void gadc_lld_start(void); +void gaudin_lld_start(void); /** * @brief Stop the audio input sampling * * @api */ -void gadc_lld_stop(void); +void gaudin_lld_stop(void); #ifdef __cplusplus } diff --git a/src/gaudin/gaudin.c b/src/gaudin/gaudin.c index c9ed1c7f..2e3507ef 100644 --- a/src/gaudin/gaudin.c +++ b/src/gaudin/gaudin.c @@ -40,7 +40,7 @@ static uint16_t audFlags; while ((psl = geventGetSourceListener((GSourceHandle)(&aud), psl))) { if (!(pe = (GEventAudioIn *)geventGetEventBuffer(psl))) { // This listener is missing - save this. - psl->srcflags |= GADC_AUDIO_IN_LOSTEVENT; + psl->srcflags |= GAUDIN_LOSTEVENT; continue; } @@ -107,7 +107,7 @@ bool_t gaudinInit(uint16_t channel, uint32_t frequency, audin_sample_t *buffer, /* Stop any existing transfers */ if ((audFlags & AUDFLG_RUNNING)) - gadc_lld_stop(); + gaudin_lld_stop(); audFlags = 0; /* Initialise everything */ @@ -143,13 +143,13 @@ void gaudinSetBSem(gfxSem *pbsem, GEventAudioIn *pEvent) { void gaudinStart(void) { if (!(audFlags & AUDFLG_RUNNING)) { audFlags |= AUDFLG_RUNNING; - gadc_lld_start(); + gaudin_lld_start(); } } void gaudinStop(void) { if ((audFlags & AUDFLG_RUNNING)) { - gadc_lld_stop(); + gaudin_lld_stop(); audFlags &= ~AUDFLG_RUNNING; } } diff --git a/src/gaudin/sys_defs.h b/src/gaudin/sys_defs.h index 3f06fa6e..c65a69c1 100644 --- a/src/gaudin/sys_defs.h +++ b/src/gaudin/sys_defs.h @@ -55,7 +55,7 @@ typedef struct GEventAudioIn_t { * @brief The event flag values. * @{ */ - #define GADC_AUDIO_IN_LOSTEVENT 0x0001 /**< @brief The last GEVENT_AUDIO_IN event was lost */ + #define GAUDIN_LOSTEVENT 0x0001 /**< @brief The last GEVENT_AUDIO_IN event was lost */ /** @} */ /** * @brief The number of audio samples in the buffer @@ -123,7 +123,7 @@ bool_t gaudinInit(uint16_t channel, uint32_t frequency, audin_sample_t *buffer, * @note The audio input will not use the GEVENT system unless this is * called first. This saves processing time if the application does * not want to use the GEVENT sub-system for audio input. - * Once turned on it can only be turned off by calling @p gadcHighSpeedInit() again. + * Once turned on it can only be turned off by calling @p gaudinInit() again. * @note The audio input is capable of signalling via this method and a binary semaphore * at the same time. * diff --git a/src/gaudout/driver.h b/src/gaudout/driver.h new file mode 100644 index 00000000..cd9ab01b --- /dev/null +++ b/src/gaudout/driver.h @@ -0,0 +1,123 @@ +/* + * 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 + */ + +/** + * @file src/gaudout/driver.h + * @brief GAUDOUT - Audio Output driver header file. + * + * @defgroup Driver Driver + * @ingroup GAUDOUT + * @{ + */ + +#ifndef _GAUDOUT_LLD_H +#define _GAUDOUT_LLD_H + +#include "gfx.h" + +#if GFX_USE_GAUDOUT || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Type definitions */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Get a block of audio data to play + * @return A pointer to the GAaudioData structure or NULL if none is currently available + * + * @note Defined in the high level GAUDOUT code for use by the GAUDOUT drivers. + * + * @iclass + * @notapi + */ +GAudioData *gaudoutGetDataBlockI(void); + +/** + * @brief Release a block of audio data after playing + * + * @param[in] paud The GAudioData block to be released. + * + * @note Defined in the high level GAUDOUT code for use by the GAUDOUT drivers. + * + * @iclass + * @notapi + */ +void gaudoutReleaseDataBlockI(GAudioData *paud); + +/** + * @brief Initialise the driver + * @return TRUE if the channel and frequency are valid. + * + * @param[in] channel The channel to use (see the driver for the available channels provided) + * @param[in] frequency The sample frequency to use + * + * @note The driver will always have been stopped and de-init before this is called. + * + * @api + */ +bool_t gaudout_lld_init(uint16_t channel, uint32_t frequency); + +/** + * @brief De-Initialise the driver + * + * @note The audio output will always have been stopped first by the high level layer. + * @note This may be called before a @p gaudout_lld_init() has occurred. + * + * @api + */ +void gaudout_lld_deinit(void); + +/** + * @brief Start the audio output playing + * + * @note This may be called at any stage including while the driver + * is already playing. The driver should check for data blocks + * to play using @p gaudoutGetDataBlockI(). + * + * @api + */ +void gaudout_lld_start(void); + +/** + * @brief Stop the audio output playing. + * + * @note Some drivers may only stop playing at a data block boundary. + * @note This may be called before a @p gaudout_lld_init() has occurred. + * + * @api + */ +void gaudout_lld_stop(void); + +/** + * @brief Set the output volume. + * @return TRUE if successful. + * + * @param[in] 0->255 (0 = muted) + * + * @note Some drivers may not support this. They will return FALSE. + * @note For stereo devices, both channels are set to the same volume. + * + * @api + */ +bool_t gaudout_lld_set_volume(uint8_t vol); + +#ifdef __cplusplus +} +#endif + +#endif /* GFX_USE_GAUDOUT */ + +#endif /* _GAUDOUT_LLD_H */ +/** @} */ diff --git a/src/gaudout/gaudout.c b/src/gaudout/gaudout.c index 56692453..c0d673a0 100644 --- a/src/gaudout/gaudout.c +++ b/src/gaudout/gaudout.c @@ -16,11 +16,47 @@ #if GFX_USE_GAUDOUT || defined(__DOXYGEN__) - #error "GAUDOUT: Not implemented yet" +#include "src/gaudout/driver.h" + +static gfxQueueASync playlist; +static gfxQueueGSync freelist; + +static uint16_t audFlags; + #define AUDOUTFLG_RUNNING 0x0001 + #define AUDOUTFLG_USE_EVENTS 0x0002 + +#if GFX_USE_GEVENT + static GTimer AudGTimer; + + static void AudGTimerCallback(void *param) { + (void) param; + GSourceListener *psl; + GEventADC *pe; + + psl = 0; + while ((psl = geventGetSourceListener((GSourceHandle)(&aud), psl))) { + if (!(pe = (GEventAudioIn *)geventGetEventBuffer(psl))) { + // This listener is missing - save this. + psl->srcflags |= GAUDIN_LOSTEVENT; + continue; + } + + pe->type = GEVENT_AUDIO_IN; + pe->channel = aud.channel; + pe->count = lastcount; + pe->buffer = lastbuffer; + pe->flags = psl->srcflags; + psl->srcflags = 0; + geventSendEvent(psl); + } + } +#endif + void _gaudoutInit(void) { - /* ToDo */ + gfxQueueASyncInit(&playlist); + gfxQueueGSyncInit(&freelist); } void _gaudoutDeinit(void) @@ -28,6 +64,77 @@ void _gaudoutDeinit(void) /* ToDo */ } +bool_t gaudioAllocBuffers(unsigned num, size_t size) { + GAudioData *paud; + + if (num < 1) + return FALSE; + + // Round up to a multiple of 4 to prevent problems with structure alignment + size = (size + 3) & ~0x03; + + // Allocate the memory + if (!(paud = gfxAlloc((size+sizeof(GAudioData)) * num))) + return FALSE; + + // Add each of them to our free list + for(;num--; paud = (GAudioData *)((char *)(paud+1)+size)) { + paud->size = size; + gfxQueueGSyncPut(&freelist, (gfxQueueGSyncItem *)paud); + } + + return TRUE; +} + +void gaudioReleaseBuffer(GAudioData *paud) { + gfxQueueGSyncPut(&freelist, (gfxQueueGSyncItem *)paud); +} + +GAudioData *gaudioGetBuffer(delaytime_t ms) { + return (GAudioData *)gfxQueueGSyncGet(&freelist, ms); +} + +bool_t gaudioPlayInit(uint16_t channel, uint32_t frequency) { + gaudioPlayStop(); + gaudout_lld_deinit(); + return gaudout_lld_init(channel, frequency); +} + +void gaudioPlay(GAudioData *paud) { + if (paud) + gfxQueueASyncPut(&playlist, (gfxQueueASyncItem *)paud); + gaudout_lld_start(); +} + +void gaudioPlayPause(void) { + gaudout_lld_stop(); +} + +void gaudioPlayStop(void) { + GAudioData *paud; + + gaudout_lld_stop(); + while((paud = (GAudioData *)gfxQueueASyncGet(&playlist))) + gfxQueueGSyncPut(&freelist, (gfxQueueGSyncItem *)paud); +} + +bool_t gaudioPlaySetVolume(uint8_t vol) { + return gaudout_lld_set_volume(vol); +} + +/** + * Routines provided for use by drivers. + */ + +GAudioData *gaudoutGetDataBlockI(void) { + return (GAudioData *)gfxQueueASyncGet(&playlist); +} + +void gaudoutReleaseDataBlockI(GAudioData *paud) { + gfxQueueGSyncPut(&freelist, (gfxQueueGSyncItem *)paud); +} + + #endif /* GFX_USE_GAUDOUT */ /** @} */ diff --git a/src/gaudout/sys_defs.h b/src/gaudout/sys_defs.h index f22d269c..c3745b8c 100644 --- a/src/gaudout/sys_defs.h +++ b/src/gaudout/sys_defs.h @@ -22,10 +22,26 @@ #if GFX_USE_GAUDOUT || defined(__DOXYGEN__) +/* Include the driver defines */ +#include "gaudout_lld_config.h" + + /*===========================================================================*/ /* Type definitions */ /*===========================================================================*/ +/** + * @brief Contains Audio Data Samples + * @note This structure is followed immediately by the sample data itself. + * When allocating the buffers for the sample data put this structure + * at the beginning of the buffer. + */ +typedef struct GAudioData { + gfxQueueASyncItem next; // @< Used for queuing the buffers + size_t size; // @< The size of the buffer area following this structure (in bytes) + size_t len; // @< The length of the data in the buffer area (in samples) +} GAudioData; + /*===========================================================================*/ /* External declarations. */ /*===========================================================================*/ @@ -34,6 +50,111 @@ extern "C" { #endif +/** + * @brief Allocate some audio buffers and put them on the free list + * @return TRUE is it succeeded. FALSE on allocation failure. + * + * @param[in] num The number of buffers to allocate + * @param[in] size The size (in bytes) of each buffer + * + * @api + */ +bool_t gaudioAllocBuffers(unsigned num, size_t size); + +/** + * @brief Get an audio buffer from the free list + * @return A GAudioData pointer or NULL if the timeout is exceeded + * + * @params[in] ms The maximum amount of time in milliseconds to wait for a buffer if one is not available. + * + * @api + */ +GAudioData *gaudioGetBuffer(delaytime_t ms); + +/** + * @brief Release a buffer back to the free list + * + * @param[in] paud The buffer to put (back) on the free-list. + * + * @note This call should be used to return any buffers that were taken from + * the free-list once they have been finished with. It can also be used + * to put new buffers onto the free-list. Just make sure the "size" field + * of the GAudioData structure has been filled in first. + * + * @api + */ +void gaudioReleaseBuffer(GAudioData *paud); + +/** + * @brief Set the audio device to play on the specified channel and with the specified + * sample frequency. + * @return TRUE is successful, FALSE if the driver doesn't accept those parameters. + * + * @param[in] channel The audio output channel to use. + * @param[in] frequency The audio sample rate in samples per second + * + * @note Some channels are mono, and some are stereo. See your driver config file + * to determine which channels to use and whether they are stereo or not. + * + * @api + */ +bool_t gaudioPlayInit(uint16_t channel, uint32_t frequency); + +/** + * @brief Play the specified sample data. + * @details The sample data is output to the audio channel. On completion the buffer is returned to the free-list. + * @pre @p gaudioPlayInit must have been called first to set the channel and sample frequency. + * + * @param[in] paud The audio sample buffer to play. It can be NULL (used to restart paused audio) + * + * @note Calling this will cancel any pause. + * @note Before calling this function the len field of the GAudioData structure must be + * specified. While the buffer size is specified in bytes, this length is specified in samples + * and must be even for stereo channels. + * @note For stereo channels the sample data is interleaved in the buffer. + * @note This call returns before the data has completed playing. Subject to available buffers (which + * can be obtained from the free-list), any number of buffers may be played. They will be queued + * for playing in the order they are supplied to this routine and played when previous buffers are + * complete. In this way continuous playing can be obtained without audio gaps. + * + * @api + */ +void gaudioPlay(GAudioData *paud); + +/** + * @brief Pause any currently playing sounds. + * + * @note If nothing is currently playing this routine does nothing. To restart playing call @p gaudioPlay() + * with or without a new sample buffer. + * @note Some drivers will not respond until a buffer boundary. + * + * @api + */ +void gaudioPlayPause(void); + +/** + * @brief Stop any currently playing sounds. + * + * @note This stops any playing sounds and returns any currently queued buffers back to the free-list. + * @note Some drivers will not respond until a buffer boundary. + * + * @api + */ +void gaudioPlayStop(void); + +/** + * @brief Set the output volume. + * @return TRUE if successful. + * + * @param[in] 0->255 (0 = muted) + * + * @note Some drivers may not support this. They will return FALSE. + * @note For stereo devices, both channels are set to the same volume. + * + * @api + */ +bool_t gaudioPlaySetVolume(uint8_t vol); + #ifdef __cplusplus } #endif diff --git a/src/gaudout/sys_rules.h b/src/gaudout/sys_rules.h index 50b9a442..8274e031 100644 --- a/src/gaudout/sys_rules.h +++ b/src/gaudout/sys_rules.h @@ -17,6 +17,27 @@ #define _GAUDOUT_RULES_H #if GFX_USE_GAUDOUT + #if !GFX_USE_GQUEUE + #if GFX_DISPLAY_RULE_WARNINGS + #warning "GAUDOUT: GFX_USE_GQUEUE is required if GFX_USE_GAUDOUT is TRUE. It has been turned on for you." + #endif + #undef GFX_USE_GQUEUE + #define GFX_USE_GQUEUE TRUE + #endif + #if !GQUEUE_NEED_ASYNC + #if GFX_DISPLAY_RULE_WARNINGS + #warning "GAUDOUT: GQUEUE_NEED_ASYNC is required if GFX_USE_GAUDOUT is TRUE. It has been turned on for you." + #endif + #undef GQUEUE_NEED_ASYNC + #define GQUEUE_NEED_ASYNC TRUE + #endif + #if !GQUEUE_NEED_GSYNC + #if GFX_DISPLAY_RULE_WARNINGS + #warning "GAUDOUT: GQUEUE_NEED_GSYNC is required if GFX_USE_GAUDOUT is TRUE. It has been turned on for you." + #endif + #undef GQUEUE_NEED_GSYNC + #define GQUEUE_NEED_GSYNC TRUE + #endif #endif #endif /* _GAUDOUT_RULES_H */ -- cgit v1.2.3 From 17f1f9d7990461cbdb7b40d42b310321ca47b776 Mon Sep 17 00:00:00 2001 From: inmarket Date: Mon, 3 Mar 2014 07:38:57 +1000 Subject: Add I class rouitines to GQUEUE --- src/gqueue/gqueue.c | 126 +++++++++++++++++++++++++++++--------------------- src/gqueue/sys_defs.h | 36 +++++++++++++-- 2 files changed, 106 insertions(+), 56 deletions(-) (limited to 'src') diff --git a/src/gqueue/gqueue.c b/src/gqueue/gqueue.c index 2adfd9ff..f3da1cdf 100644 --- a/src/gqueue/gqueue.c +++ b/src/gqueue/gqueue.c @@ -22,47 +22,64 @@ gfxQueueASyncItem *gfxQueueASyncGet(gfxQueueASync *pqueue) { gfxQueueASyncItem *pi; + // This is just a shortcut to speed execution if (!pqueue->head) return 0; gfxSystemLock(); - if ((pi = pqueue->head)) - pqueue->head = pi->next; - pi->next = 0; + pi = gfxQueueASyncGetI(pqueue); gfxSystemUnlock(); return pi; } + gfxQueueASyncItem *gfxQueueASyncGetI(gfxQueueASync *pqueue) { + gfxQueueASyncItem *pi; - void gfxQueueASyncPut(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem) { - pitem->next = 0; + if ((pi = pqueue->head)) { + pqueue->head = pi->next; + pi->next = 0; + } + + return pi; + } + void gfxQueueASyncPut(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem) { gfxSystemLock(); + gfxQueueASyncPutI(pqueue, pitem); + gfxSystemUnlock(); + } + void gfxQueueASyncPutI(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem) { + pitem->next = 0; if (!pqueue->head) { pqueue->head = pqueue->tail = pitem; } else { pqueue->tail->next = pitem; pqueue->tail = pitem; } - gfxSystemUnlock(); } void gfxQueueASyncPush(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem) { gfxSystemLock(); + gfxQueueASyncPushI(pqueue, pitem); + gfxSystemUnlock(); + } + void gfxQueueASyncPushI(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem) { pitem->next = pqueue->head; pqueue->head = pitem; if (!pitem->next) pqueue->tail = pitem; - gfxSystemUnlock(); } void gfxQueueASyncRemove(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem) { + gfxSystemLock(); + gfxQueueASyncRemoveI(pqueue, pitem); + gfxSystemUnlock(); + } + void gfxQueueASyncRemoveI(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem) { gfxQueueASyncItem *pi; if (!pitem) return; - - gfxSystemLock(); if (pqueue->head) { if (pqueue->head == pitem) { pqueue->head = pitem->next; @@ -79,25 +96,24 @@ } } } - gfxSystemUnlock(); - } - - bool_t gfxQueueASyncIsEmpty(gfxQueueASync *pqueue) { - return pqueue->head == 0; } bool_t gfxQueueASyncIsIn(gfxQueueASync *pqueue, const gfxQueueASyncItem *pitem) { - gfxQueueASyncItem *pi; + bool_t res; gfxSystemLock(); + res = gfxQueueASyncIsInI(pqueue, pitem); + gfxSystemUnlock(); + + return res; + } + bool_t gfxQueueASyncIsInI(gfxQueueASync *pqueue, const gfxQueueASyncItem *pitem) { + gfxQueueASyncItem *pi; + for(pi = pqueue->head; pi; pi = pi->next) { - if (pi == pitem) { - gfxSystemUnlock(); + if (pi == pitem) return TRUE; - } } - gfxSystemUnlock(); - return FALSE; } #endif @@ -124,38 +140,44 @@ } void gfxQueueGSyncPut(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem) { - pitem->next = 0; - gfxSystemLock(); + gfxQueueGSyncPutI(pqueue, pitem); + gfxSystemUnlock(); + } + void gfxQueueGSyncPutI(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem) { + pitem->next = 0; if (!pqueue->head) { pqueue->head = pqueue->tail = pitem; } else { pqueue->tail->next = pitem; pqueue->tail = pitem; } - gfxSystemUnlock(); - - gfxSemSignal(&pqueue->sem); + gfxSemSignalI(&pqueue->sem); } void gfxQueueGSyncPush(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem) { gfxSystemLock(); + gfxQueueGSyncPushI(pqueue, pitem); + gfxSystemUnlock(); + } + void gfxQueueGSyncPushI(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem) { pitem->next = pqueue->head; pqueue->head = pitem; if (!pitem->next) pqueue->tail = pitem; - gfxSystemUnlock(); - - gfxSemSignal(&pqueue->sem); + gfxSemSignalI(&pqueue->sem); } void gfxQueueGSyncRemove(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem) { + gfxSystemLock(); + gfxQueueGSyncRemoveI(pqueue, pitem); + gfxSystemUnlock(); + } + void gfxQueueGSyncRemoveI(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem) { gfxQueueGSyncItem *pi; if (!pitem) return; - - gfxSystemLock(); if (pqueue->head) { if (pqueue->head == pitem) { pqueue->head = pitem->next; @@ -172,25 +194,24 @@ } } } - gfxSystemUnlock(); - } - - bool_t gfxQueueGSyncIsEmpty(gfxQueueGSync *pqueue) { - return pqueue->head == 0; } bool_t gfxQueueGSyncIsIn(gfxQueueGSync *pqueue, const gfxQueueGSyncItem *pitem) { - gfxQueueGSyncItem *pi; + bool_t res; gfxSystemLock(); + res = gfxQueueGSyncIsInI(pqueue, pitem); + gfxSystemUnlock(); + + return res; + } + bool_t gfxQueueGSyncIsInI(gfxQueueGSync *pqueue, const gfxQueueGSyncItem *pitem) { + gfxQueueGSyncItem *pi; + for(pi = pqueue->head; pi; pi = pi->next) { - if (pi == pitem) { - gfxSystemUnlock(); + if (pi == pitem) return TRUE; - } } - gfxSystemUnlock(); - return FALSE; } #endif @@ -213,7 +234,7 @@ pi->next = 0; gfxSystemUnlock(); - gfxSemSignalI(&pi->sem); + gfxSemSignal(&pi->sem); gfxSemDestroy(&pi->sem); return pi; @@ -281,25 +302,24 @@ gfxSystemUnlock(); } - bool_t gfxQueueFSyncIsEmpty(gfxQueueFSync *pqueue) { - return pqueue->head == 0; - } - bool_t gfxQueueFSyncIsIn(gfxQueueFSync *pqueue, const gfxQueueFSyncItem *pitem) { - gfxQueueASyncItem *pi; + bool_t res; gfxSystemLock(); + res = gfxQueueFSyncIsInI(pqueue, pitem); + gfxSystemUnlock(); + + return res; + } + bool_t gfxQueueFSyncIsInI(gfxQueueFSync *pqueue, const gfxQueueFSyncItem *pitem) { + gfxQueueASyncItem *pi; + for(pi = pqueue->head; pi; pi = pi->next) { - if (pi == pitem) { - gfxSystemUnlock(); + if (pi == pitem) return TRUE; - } } - gfxSystemUnlock(); - return FALSE; } #endif #endif /* GFX_USE_GQUEUE */ - diff --git a/src/gqueue/sys_defs.h b/src/gqueue/sys_defs.h index 447ea5be..4446fcba 100644 --- a/src/gqueue/sys_defs.h +++ b/src/gqueue/sys_defs.h @@ -105,10 +105,13 @@ void gfxQueueFSyncInit(gfxQueueFSync *pqueue); * @param[in] ms The maxmimum time to wait for an item. For ASync queues this parameter is * not specified as TIME_IMMEDIATE is assumed. * + * @note The routines ending in "I" are interrupt/system/iclass level routines. + * * @api * @{ */ gfxQueueASyncItem *gfxQueueASyncGet(gfxQueueASync *pqueue); +gfxQueueASyncItem *gfxQueueASyncGetI(gfxQueueASync *pqueue); gfxQueueGSyncItem *gfxQueueGSyncGet(gfxQueueGSync *pqueue, delaytime_t ms); gfxQueueFSyncItem *gfxQueueFSyncGet(gfxQueueFSync *pqueue, delaytime_t ms); /* @} */ @@ -124,12 +127,15 @@ gfxQueueFSyncItem *gfxQueueFSyncGet(gfxQueueFSync *pqueue, delaytime_t ms); * @note FSync: Use a delay time of TIME_IMMEDIATE if you don't want to wait until the * item is removed from the queue. Note that even if the timeout occurs - the item * remains in the queue. + * @note The routines ending in "I" are interrupt/system/iclass level routines. * * @api * @{ */ void gfxQueueASyncPut(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem); +void gfxQueueASyncPutI(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem); void gfxQueueGSyncPut(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem); +void gfxQueueGSyncPutI(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem); bool_t gfxQueueFSyncPut(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem, delaytime_t ms); /* @} */ @@ -141,6 +147,7 @@ bool_t gfxQueueFSyncPut(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem, delayti * @{ */ #define gfxQueueASyncPop(pqueue) gfxQueueASyncGet(pqueue) +#define gfxQueueASyncPopI(pqueue) gfxQueueASyncGetI(pqueue) #define gfxQueueGSyncPop(pqueue, ms) gfxQueueGSyncGet(pqueue, ms) #define gfxQueueFSyncPop(pqueue, ms) gfxQueueFSyncGet(pqueue, ms) /* @} */ @@ -156,12 +163,15 @@ bool_t gfxQueueFSyncPut(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem, delayti * @note FSync: Use a delay time of TIME_IMMEDIATE if you don't want to wait until the * item is removed from the queue. Note that even if the timeout occurs - the item * remains in the queue. + * @note The routines ending in "I" are interrupt/system/iclass level routines. * * @api * @{ */ void gfxQueueASyncPush(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem); +void gfxQueueASyncPushI(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem); void gfxQueueGSyncPush(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem); +void gfxQueueGSyncPushI(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem); bool_t gfxQueueFSyncPush(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem, delaytime_t ms); /* @} */ @@ -175,12 +185,15 @@ bool_t gfxQueueFSyncPush(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem, delayt * @note If the item isn't in the queue the routine just returns. * @note If a process is waiting on the Put/Push operation for the item, that process * will be signaled. + * @note The routines ending in "I" are interrupt/system/iclass level routines. * * @api * @{ */ void gfxQueueASyncRemove(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem); +void gfxQueueASyncRemoveI(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem); void gfxQueueGSyncRemove(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem); +void gfxQueueGSyncRemoveI(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem); void gfxQueueFSyncRemove(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem); /* @} */ @@ -190,12 +203,17 @@ void gfxQueueFSyncRemove(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem); * * @param[in] pqueue A pointer to the queue * + * @note The routines ending in "I" are interrupt/system/iclass level routines. + * * @api * @{ */ -bool_t gfxQueueASyncIsEmpty(gfxQueueASync *pqueue); -bool_t gfxQueueGSyncIsEmpty(gfxQueueGSync *pqueue); -bool_t gfxQueueFSyncIsEmpty(gfxQueueFSync *pqueue); +#define gfxQueueASyncIsEmpty(pqueue) (pqueue->head == 0) +#define gfxQueueASyncIsEmptyI(pqueue) (pqueue->head == 0) +#define gfxQueueGSyncIsEmpty(pqueue) (pqueue->head == 0) +#define gfxQueueGSyncIsEmptyI(pqueue) (pqueue->head == 0) +#define gfxQueueFSyncIsEmpty(pqueue) (pqueue->head == 0) +#define gfxQueueFSyncIsEmptyI(pqueue) (pqueue->head == 0) /* @} */ /** @@ -206,13 +224,17 @@ bool_t gfxQueueFSyncIsEmpty(gfxQueueFSync *pqueue); * @param[in] pitem A pointer to the queue item * * @note This operation may be expensive. + * @note The routines ending in "I" are interrupt/system/iclass level routines. * * @api * @{ */ bool_t gfxQueueASyncIsIn(gfxQueueASync *pqueue, const gfxQueueASyncItem *pitem); +bool_t gfxQueueASyncIsInI(gfxQueueASync *pqueue, const gfxQueueASyncItem *pitem); bool_t gfxQueueGSyncIsIn(gfxQueueGSync *pqueue, const gfxQueueGSyncItem *pitem); +bool_t gfxQueueGSyncIsInI(gfxQueueGSync *pqueue, const gfxQueueGSyncItem *pitem); bool_t gfxQueueFSyncIsIn(gfxQueueFSync *pqueue, const gfxQueueFSyncItem *pitem); +bool_t gfxQueueFSyncIsInI(gfxQueueFSync *pqueue, const gfxQueueFSyncItem *pitem); /* @} */ /** @@ -226,13 +248,17 @@ bool_t gfxQueueFSyncIsIn(gfxQueueFSync *pqueue, const gfxQueueFSyncItem *pitem); * @note As that item is still on the queue, it should be treated as read-only. It could * also be removed from the queue at any time by another thread (thereby altering the * queue item). + * @note The routines ending in "I" are interrupt/system/iclass level routines. * * @api * @{ */ #define gfxQueueASyncPeek(pqueue) ((const gfxQueueASyncItem *)((pqueue)->head)) +#define gfxQueueASyncPeekI(pqueue) ((const gfxQueueASyncItem *)((pqueue)->head)) #define gfxQueueGSyncPeek(pqueue) ((const gfxQueueGSyncItem *)((pqueue)->head)) +#define gfxQueueGSyncPeekI(pqueue) ((const gfxQueueGSyncItem *)((pqueue)->head)) #define gfxQueueFSyncPeek(pqueue) ((const gfxQueueFSyncItem *)((pqueue)->head)) +#define gfxQueueFSyncPeekI(pqueue) ((const gfxQueueFSyncItem *)((pqueue)->head)) /* @} */ /** @@ -246,13 +272,17 @@ bool_t gfxQueueFSyncIsIn(gfxQueueFSync *pqueue, const gfxQueueFSyncItem *pitem); * @note As that item is still on the queue, it should be treated as read-only. It could * also be removed from the queue at any time by another thread (thereby altering the * queue item). + * @note The routines ending in "I" are interrupt/system/iclass level routines. * * @api * @{ */ #define gfxQueueASyncNext(pitem) ((const gfxQueueASyncItem *)((pitem)->next)) +#define gfxQueueASyncNextI(pitem) ((const gfxQueueASyncItem *)((pitem)->next)) #define gfxQueueGSyncNext(pitem) ((const gfxQueueGSyncItem *)((pitem)->next)) +#define gfxQueueGSyncNextI(pitem) ((const gfxQueueGSyncItem *)((pitem)->next)) #define gfxQueueFSyncNext(pitem) ((const gfxQueueFSyncItem *)((pitem)->next)) +#define gfxQueueFSyncNextI(pitem) ((const gfxQueueFSyncItem *)((pitem)->next)) /* @} */ #ifdef __cplusplus -- cgit v1.2.3 From 43527de2c09eb90e5c1cebbce587b5da2bda957d Mon Sep 17 00:00:00 2001 From: inmarket Date: Mon, 3 Mar 2014 07:39:46 +1000 Subject: Updates to GAUDOUT to allow specification of the sample format. Fix threading issues. --- src/gaudout/driver.h | 3 ++- src/gaudout/gaudout.c | 8 ++++---- src/gaudout/sys_defs.h | 8 ++++---- 3 files changed, 10 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/gaudout/driver.h b/src/gaudout/driver.h index cd9ab01b..8e72dff4 100644 --- a/src/gaudout/driver.h +++ b/src/gaudout/driver.h @@ -62,12 +62,13 @@ void gaudoutReleaseDataBlockI(GAudioData *paud); * * @param[in] channel The channel to use (see the driver for the available channels provided) * @param[in] frequency The sample frequency to use + * @param[in] format The sample format * * @note The driver will always have been stopped and de-init before this is called. * * @api */ -bool_t gaudout_lld_init(uint16_t channel, uint32_t frequency); +bool_t gaudout_lld_init(uint16_t channel, uint32_t frequency, ArrayDataFormat format); /** * @brief De-Initialise the driver diff --git a/src/gaudout/gaudout.c b/src/gaudout/gaudout.c index c0d673a0..275677c8 100644 --- a/src/gaudout/gaudout.c +++ b/src/gaudout/gaudout.c @@ -94,10 +94,10 @@ GAudioData *gaudioGetBuffer(delaytime_t ms) { return (GAudioData *)gfxQueueGSyncGet(&freelist, ms); } -bool_t gaudioPlayInit(uint16_t channel, uint32_t frequency) { +bool_t gaudioPlayInit(uint16_t channel, uint32_t frequency, ArrayDataFormat format) { gaudioPlayStop(); gaudout_lld_deinit(); - return gaudout_lld_init(channel, frequency); + return gaudout_lld_init(channel, frequency, format); } void gaudioPlay(GAudioData *paud) { @@ -127,11 +127,11 @@ bool_t gaudioPlaySetVolume(uint8_t vol) { */ GAudioData *gaudoutGetDataBlockI(void) { - return (GAudioData *)gfxQueueASyncGet(&playlist); + return (GAudioData *)gfxQueueASyncGetI(&playlist); } void gaudoutReleaseDataBlockI(GAudioData *paud) { - gfxQueueGSyncPut(&freelist, (gfxQueueGSyncItem *)paud); + gfxQueueGSyncPutI(&freelist, (gfxQueueGSyncItem *)paud); } diff --git a/src/gaudout/sys_defs.h b/src/gaudout/sys_defs.h index c3745b8c..4f09678b 100644 --- a/src/gaudout/sys_defs.h +++ b/src/gaudout/sys_defs.h @@ -39,7 +39,7 @@ typedef struct GAudioData { gfxQueueASyncItem next; // @< Used for queuing the buffers size_t size; // @< The size of the buffer area following this structure (in bytes) - size_t len; // @< The length of the data in the buffer area (in samples) + size_t len; // @< The length of the data in the buffer area (in bytes) } GAudioData; /*===========================================================================*/ @@ -92,13 +92,14 @@ void gaudioReleaseBuffer(GAudioData *paud); * * @param[in] channel The audio output channel to use. * @param[in] frequency The audio sample rate in samples per second + * @param[in] format The audio sample format * * @note Some channels are mono, and some are stereo. See your driver config file * to determine which channels to use and whether they are stereo or not. * * @api */ -bool_t gaudioPlayInit(uint16_t channel, uint32_t frequency); +bool_t gaudioPlayInit(uint16_t channel, uint32_t frequency, ArrayDataFormat format); /** * @brief Play the specified sample data. @@ -109,8 +110,7 @@ bool_t gaudioPlayInit(uint16_t channel, uint32_t frequency); * * @note Calling this will cancel any pause. * @note Before calling this function the len field of the GAudioData structure must be - * specified. While the buffer size is specified in bytes, this length is specified in samples - * and must be even for stereo channels. + * specified (in bytes). * @note For stereo channels the sample data is interleaved in the buffer. * @note This call returns before the data has completed playing. Subject to available buffers (which * can be obtained from the free-list), any number of buffers may be played. They will be queued -- cgit v1.2.3 From c1105485079fba97a62df62baeff3a4dcc7686ef Mon Sep 17 00:00:00 2001 From: inmarket Date: Tue, 4 Mar 2014 14:14:15 +1000 Subject: Add support for ANSI like escape sequences to control display color and attributes in a GWIN console. Updated the console demo to demonstrate this. --- src/gwin/console.c | 176 +++++++++++++++++++++++++++++++++++++++++++++++-- src/gwin/console.h | 6 ++ src/gwin/sys_options.h | 19 ++++++ 3 files changed, 194 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/gwin/console.c b/src/gwin/console.c index 0fe4b722..53557fd6 100644 --- a/src/gwin/console.c +++ b/src/gwin/console.c @@ -26,6 +26,14 @@ #define GCONSOLE_FLG_NOSTORE (GWIN_FIRST_CONTROL_FLAG<<0) #define GCONSOLE_FLG_OVERRUN (GWIN_FIRST_CONTROL_FLAG<<1) +// Meaning of our attribute bits. +#define ESC_REDBIT 0x01 +#define ESC_GREENBIT 0x02 +#define ESC_BLUEBIT 0x04 +#define ESC_USECOLOR 0x08 +#define ESC_UNDERLINE 0x10 +#define ESC_BOLD 0x20 + /* * Stream interface implementation. The interface is write only */ @@ -58,6 +66,68 @@ }; #endif +#if GWIN_CONSOLE_ESCSEQ + // Convert escape sequences to attributes + static bool_t ESCtoAttr(char c, uint8_t *pattr) { + uint8_t attr; + + attr = pattr[0]; + switch(c) { + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + attr &= ~(ESC_REDBIT|ESC_GREENBIT|ESC_BLUEBIT); + attr |= (c - '0') | ESC_USECOLOR; + break; + case 'C': + attr &= ~(ESC_REDBIT|ESC_GREENBIT|ESC_BLUEBIT|ESC_USECOLOR); + break; + case 'u': + attr |= ESC_UNDERLINE; + break; + case 'U': + attr &= ~ESC_UNDERLINE; + break; + case 'b': + attr |= ESC_BOLD; + break; + case 'B': + attr &= ~ESC_BOLD; + break; + default: + return FALSE; + } + if (attr == pattr[0]) + return FALSE; + pattr[0] = attr; + return TRUE; + } + + static color_t ESCPrintColor(GConsoleObject *gcw) { + switch(gcw->currattr & (ESC_REDBIT|ESC_GREENBIT|ESC_BLUEBIT|ESC_USECOLOR)) { + case (ESC_USECOLOR): + return Black; + case (ESC_USECOLOR|ESC_REDBIT): + return Red; + case (ESC_USECOLOR|ESC_GREENBIT): + return Green; + case (ESC_USECOLOR|ESC_REDBIT|ESC_GREENBIT): + return Yellow; + case (ESC_USECOLOR|ESC_BLUEBIT): + return Blue; + case (ESC_USECOLOR|ESC_REDBIT|ESC_BLUEBIT): + return Magenta; + case (ESC_USECOLOR|ESC_GREENBIT|ESC_BLUEBIT): + return Cyan; + case (ESC_USECOLOR|ESC_REDBIT|ESC_GREENBIT|ESC_BLUEBIT): + return White; + default: + return gcw->g.color; + } + } +#else + #define ESCPrintColor(gcw) ((gcw)->g.color) +#endif + #if GWIN_CONSOLE_USE_HISTORY static void HistoryDestroy(GWindowObject *gh) { #define gcw ((GConsoleObject *)gh) @@ -90,6 +160,11 @@ gcw->cx = 0; gcw->cy = 0; + // Reset the current attributes + #if GWIN_CONSOLE_ESCSEQ + gcw->currattr = gcw->startattr; + #endif + // Print the buffer gwinPutCharArray(gh, gcw->buffer, gcw->bufpos); @@ -115,7 +190,7 @@ // Do we have enough space in the buffer if (gcw->bufpos >= gcw->bufsize) { - char * p; + char *p, *ep; size_t dp; /** @@ -130,7 +205,13 @@ */ // Remove one line from the start - for(p = gcw->buffer; *p && *p != '\n'; p++); + ep = gcw->buffer+gcw->bufpos; + for(p = gcw->buffer; p < ep && *p != '\n'; p++) { + #if GWIN_CONSOLE_ESCSEQ + if (*p == 27) + ESCtoAttr(p[1], &gcw->startattr); + #endif + } // Was there a newline? if (*p != '\n') @@ -153,7 +234,7 @@ * Scroll the history buffer by one line */ static void scrollBuffer(GConsoleObject *gcw) { - char * p; + char *p, *ep; size_t dp; // Only scroll if we need to @@ -167,7 +248,13 @@ } // Remove one line from the start - for(p = gcw->buffer; *p && *p != '\n'; p++); + ep = gcw->buffer+gcw->bufpos; + for(p = gcw->buffer; p < ep && *p != '\n'; p++) { + #if GWIN_CONSOLE_ESCSEQ + if (*p == 27) + ESCtoAttr(p[1], &gcw->startattr); + #endif + } // Was there a newline, if not delete everything. if (*p != '\n') { @@ -205,6 +292,9 @@ static void AfterClear(GWindowObject *gh) { gcw->cx = 0; gcw->cy = 0; clearBuffer(gcw); + #if GWIN_CONSOLE_ESCSEQ + gcw->startattr = gcw->currattr; + #endif #undef gcw } @@ -239,6 +329,11 @@ GHandle gwinGConsoleCreate(GDisplay *g, GConsoleObject *gc, const GWindowInit *p gc->cx = 0; gc->cy = 0; + #if GWIN_CONSOLE_ESCSEQ + gc->startattr = gc->currattr = 0; + gc->escstate = 0; + #endif + gwinSetVisible((GHandle)gc, pInit->show); return (GHandle)gc; @@ -313,13 +408,54 @@ void gwinPutChar(GHandle gh, char c) { #if GDISP_NEED_CLIP gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height); #endif - + + #if GWIN_CONSOLE_ESCSEQ + /** + * Handle escape sequences + * ESC color Change subsequent text color + * color: "0" = black, "1" = red, "2" = green, "3" = yellow, "4" = blue, + * "5" = magenta, "6" = cyan, "7" = white + * ESC C Revert subsequent text color to the window default + * ESC u Turn on underline + * ESC U Turn off underline + * ESC b Turn on bold + * ESC B Turn off bold + * ESC J Clear the window + */ + switch (gcw->escstate) { + case 1: + gcw->escstate = 0; + if (ESCtoAttr(c, &gcw->currattr)) { + if (gcw->cx == 0 && gcw->cy == 0) + gcw->startattr = gcw->currattr; + else { + putCharInBuffer(gcw, 27); + putCharInBuffer(gcw, c); + } + } else { + switch(c) { + case 'J': + // Clear the console and reset the cursor + clearBuffer(gcw); + gdispGFillArea(gh->display, gh->x, gh->y, gh->width, gh->height, gh->bgcolor); + gcw->cx = 0; + gcw->cy = 0; + gcw->startattr = gcw->currattr; + break; + } + } + return; + } + #endif + /** * Special Characters: * * Carriage returns and line feeds (\r & \n) are handled in unix terminal cooked mode; that is, * line feeds perform both actions and carriage-returns are ignored. * + * if GWIN_CONSOLE_ESCSEQ is turned on then ESC is trapped ready for the escape command. + * * All other characters are treated as printable. */ switch (c) { @@ -339,12 +475,24 @@ void gwinPutChar(GHandle gh, char c) { case '\r': // gcw->cx = 0; return; + + #if GWIN_CONSOLE_ESCSEQ + case 27: // ESC + gcw->escstate = 1; + return; + #endif } // Characters with no width are ignored if (!(width = gdispGetCharWidth(c, gh->font))) return; + // Allow space for (very crude) bold + #if GWIN_CONSOLE_ESCSEQ + if ((gcw->currattr & ESC_BOLD)) + width++; + #endif + // Do we need to go to the next line to fit this character? if (gcw->cx + width >= gh->width) { gcw->cx = 0; @@ -378,6 +526,9 @@ void gwinPutChar(GHandle gh, char c) { gdispGFillArea(gh->display, gh->x, gh->y, gh->width, gh->height, gh->bgcolor); gcw->cx = 0; gcw->cy = 0; + #if GWIN_CONSOLE_ESCSEQ + gcw->startattr = gcw->currattr; + #endif } #endif } @@ -390,12 +541,23 @@ void gwinPutChar(GHandle gh, char c) { // Draw the character #if GWIN_CONSOLE_USE_FILLED_CHARS - gdispGFillChar(gh->display, gh->x + gcw->cx, gh->y + gcw->cy, c, gh->font, gh->color, gh->bgcolor); + gdispGFillChar(gh->display, gh->x + gcw->cx, gh->y + gcw->cy, c, gh->font, ESCPrintColor(gcw), gh->bgcolor); #else - gdispGDrawChar(gh->display, gh->x + gcw->cx, gh->y + gcw->cy, c, gh->font, gh->color); + gdispGDrawChar(gh->display, gh->x + gcw->cx, gh->y + gcw->cy, c, gh->font, ESCPrintColor(gcw)); #endif putCharInBuffer(gcw, c); + #if GWIN_CONSOLE_ESCSEQ + // Draw the underline + if ((gcw->currattr & ESC_UNDERLINE)) + gdispGDrawLine(gh->display, gh->x + gcw->cx, gh->y + gcw->cy + fy - gdispGetFontMetric(gh->font, fontDescendersHeight), + gh->x + gcw->cx + width + gdispGetFontMetric(gh->font, fontCharPadding), gh->y + gcw->cy + fy - gdispGetFontMetric(gh->font, fontDescendersHeight), + ESCPrintColor(gcw)); + // Bold (very crude) + if ((gcw->currattr & ESC_BOLD)) + gdispGDrawChar(gh->display, gh->x + gcw->cx + 1, gh->y + gcw->cy, c, gh->font, ESCPrintColor(gcw)); + #endif + // Update the cursor gcw->cx += width + gdispGetFontMetric(gh->font, fontCharPadding); diff --git a/src/gwin/console.h b/src/gwin/console.h index 252b627e..14bc7eb3 100644 --- a/src/gwin/console.h +++ b/src/gwin/console.h @@ -31,6 +31,12 @@ typedef struct GConsoleObject { GWindowObject g; coord_t cx, cy; // Cursor position + #if GWIN_CONSOLE_ESCSEQ + uint8_t startattr; // ANSI-like escape sequences + uint8_t currattr; + uint16_t escstate; + #endif + #if GWIN_CONSOLE_USE_HISTORY char * buffer; // buffer to store console content size_t bufsize; // size of buffer diff --git a/src/gwin/sys_options.h b/src/gwin/sys_options.h index 02467916..e7bb93b4 100644 --- a/src/gwin/sys_options.h +++ b/src/gwin/sys_options.h @@ -159,6 +159,25 @@ #ifndef GWIN_CONSOLE_USE_FLOAT #define GWIN_CONSOLE_USE_FLOAT FALSE #endif + /** + * @brief Console windows support escape sequences to control display + * @details Defaults to FALSE + * + * @note + * Currently supported: + * ESC color Change subsequent text color + * color: "0" = black, "1" = red, "2" = green, "3" = yellow, "4" = blue, + * "5" = magenta, "6" = cyan, "7" = white + * ESC C Revert subsequent text color to the window default + * ESC u Turn on underline + * ESC U Turn off underline + * ESC b Turn on bold + * ESC B Turn off bold + * ESC J Clear the window + */ + #ifndef GWIN_CONSOLE_ESCSEQ + #define GWIN_CONSOLE_ESCSEQ FALSE + #endif /** * @brief Console Windows need BaseStreamSequential support (ChibiOS only) * @details Defaults to FALSE -- cgit v1.2.3 From 68a0be8110d2dea408890f819bae443b9b476f84 Mon Sep 17 00:00:00 2001 From: inmarket Date: Wed, 5 Mar 2014 13:43:39 +1000 Subject: Fix to ensure correct clearing of consoles when being redrawn. --- src/gwin/console.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/gwin/console.c b/src/gwin/console.c index 53557fd6..fa93c79d 100644 --- a/src/gwin/console.c +++ b/src/gwin/console.c @@ -168,10 +168,17 @@ // Print the buffer gwinPutCharArray(gh, gcw->buffer, gcw->bufpos); - #if !GWIN_CONSOLE_USE_CLEAR_LINES + #if GWIN_CONSOLE_USE_CLEAR_LINES // Clear the remaining space - if (gcw->cy + fy < gh->height) - gdispGFillArea(gh->display, gh->x, gh->y+gcw->cy+fy, gh->width, gh->height-(gcw->cy+fy), gh->bgcolor); + { + coord_t y; + + y = gcw->cy; + if (gcw->cx) + y += gdispGetFontMetric(gh->font, fontHeight); + if (y < gh->height) + gdispGFillArea(gh->display, gh->x, gh->y+y, gh->width, gh->height-y, gh->bgcolor); + } #endif // Turn back on storing of buffer contents -- cgit v1.2.3 From e762e91bd5d5347071c3b43fbdb021376584c267 Mon Sep 17 00:00:00 2001 From: inmarket Date: Wed, 5 Mar 2014 13:45:37 +1000 Subject: Updates to GAUDOUT. Add Events to the GAUDOUT api. --- src/gaudout/driver.h | 10 ++++++++++ src/gaudout/gaudout.c | 53 ++++++++++++++++++++++++++++++++++++++------------ src/gaudout/sys_defs.h | 51 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 102 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/gaudout/driver.h b/src/gaudout/driver.h index 8e72dff4..bd00d06d 100644 --- a/src/gaudout/driver.h +++ b/src/gaudout/driver.h @@ -56,6 +56,16 @@ GAudioData *gaudoutGetDataBlockI(void); */ void gaudoutReleaseDataBlockI(GAudioData *paud); +/** + * @brief Signal that all playing has now stopped + * + * @note Defined in the high level GAUDOUT code for use by the GAUDOUT drivers. + * + * @iclass + * @notapi + */ +void gaudoutDoneI(void); + /** * @brief Initialise the driver * @return TRUE if the channel and frequency are valid. diff --git a/src/gaudout/gaudout.c b/src/gaudout/gaudout.c index 275677c8..00b01e91 100644 --- a/src/gaudout/gaudout.c +++ b/src/gaudout/gaudout.c @@ -21,32 +21,33 @@ static gfxQueueASync playlist; static gfxQueueGSync freelist; -static uint16_t audFlags; - #define AUDOUTFLG_RUNNING 0x0001 - #define AUDOUTFLG_USE_EVENTS 0x0002 +static uint16_t PlayFlags; + #define PLAYFLG_USEEVENTS 0x0001 + #define PLAYFLG_PLAYING 0x0002 #if GFX_USE_GEVENT - static GTimer AudGTimer; + static GTimer PlayTimer; - static void AudGTimerCallback(void *param) { + static void PlayTimerCallback(void *param) { (void) param; GSourceListener *psl; - GEventADC *pe; + GEventAudioOut *pe; psl = 0; while ((psl = geventGetSourceListener((GSourceHandle)(&aud), psl))) { - if (!(pe = (GEventAudioIn *)geventGetEventBuffer(psl))) { + if (!(pe = (GEventAudioOut *)geventGetEventBuffer(psl))) { // This listener is missing - save this. - psl->srcflags |= GAUDIN_LOSTEVENT; + psl->srcflags |= GAUDOUT_LOSTEVENT; continue; } - pe->type = GEVENT_AUDIO_IN; - pe->channel = aud.channel; - pe->count = lastcount; - pe->buffer = lastbuffer; + pe->type = GEVENT_AUDIO_OUT; pe->flags = psl->srcflags; psl->srcflags = 0; + if ((PlayFlags & PLAYFLG_PLAYING)) + pe->flags |= GAUDOUT_PLAYING; + if (!gfxQueueGSyncIsEmpty(&freelist)) + pe->flags |= GAUDOUT_FREEBLOCK; geventSendEvent(psl); } } @@ -57,11 +58,17 @@ void _gaudoutInit(void) { gfxQueueASyncInit(&playlist); gfxQueueGSyncInit(&freelist); + #if GFX_USE_GEVENT + gtimerInit(&PlayTimer); + #endif } void _gaudoutDeinit(void) { /* ToDo */ + #if GFX_USE_GEVENT + gtimerDeinit(&PlayTimer); + #endif } bool_t gaudioAllocBuffers(unsigned num, size_t size) { @@ -103,6 +110,7 @@ bool_t gaudioPlayInit(uint16_t channel, uint32_t frequency, ArrayDataFormat form void gaudioPlay(GAudioData *paud) { if (paud) gfxQueueASyncPut(&playlist, (gfxQueueASyncItem *)paud); + PlayFlags |= PLAYFLG_PLAYING; gaudout_lld_start(); } @@ -116,12 +124,22 @@ void gaudioPlayStop(void) { gaudout_lld_stop(); while((paud = (GAudioData *)gfxQueueASyncGet(&playlist))) gfxQueueGSyncPut(&freelist, (gfxQueueGSyncItem *)paud); + PlayFlags &= ~PLAYFLG_PLAYING; } bool_t gaudioPlaySetVolume(uint8_t vol) { return gaudout_lld_set_volume(vol); } +#if GFX_USE_GEVENT || defined(__DOXYGEN__) + GSourceHandle gaudioPlayGetSource(void) { + if (!gtimerIsActive(&PlayTimer)) + gtimerStart(&PlayTimer, PlayTimerCallback, 0, TRUE, TIME_INFINITE); + PlayFlags |= PLAYFLG_USEEVENTS; + return (GSourceHandle)&PlayFlags; + } +#endif + /** * Routines provided for use by drivers. */ @@ -132,8 +150,19 @@ GAudioData *gaudoutGetDataBlockI(void) { void gaudoutReleaseDataBlockI(GAudioData *paud) { gfxQueueGSyncPutI(&freelist, (gfxQueueGSyncItem *)paud); + #if GFX_USE_GEVENT + if (PlayFlags & PLAYFLG_USEEVENTS) + gtimerJabI(&PlayTimer); + #endif } +void gaudoutDoneI(void) { + PlayFlags &= ~PLAYFLG_PLAYING; + #if GFX_USE_GEVENT + if (PlayFlags & PLAYFLG_USEEVENTS) + gtimerJabI(&PlayTimer); + #endif +} #endif /* GFX_USE_GAUDOUT */ /** @} */ diff --git a/src/gaudout/sys_defs.h b/src/gaudout/sys_defs.h index 4f09678b..75cda243 100644 --- a/src/gaudout/sys_defs.h +++ b/src/gaudout/sys_defs.h @@ -42,6 +42,36 @@ typedef struct GAudioData { size_t len; // @< The length of the data in the buffer area (in bytes) } GAudioData; + +// Event types for GAUDOUT +#define GEVENT_AUDIO_OUT (GEVENT_GAUDOUT_FIRST+0) + +/** + * @brief The Audio output event structure. + * @{ + */ +typedef struct GEventAudioOut_t { + #if GFX_USE_GEVENT || defined(__DOXYGEN__) + /** + * @brief The type of this event (GEVENT_AUDIO_OUT) + */ + GEventType type; + #endif + /** + * @brief The event flags + */ + uint16_t flags; + /** + * @brief The event flag values. + * @{ + */ + #define GAUDOUT_LOSTEVENT 0x0001 /**< @brief The last GEVENT_AUDIO_OUT event was lost */ + #define GAUDOUT_PLAYING 0x0002 /**< @brief The audio out system is currently playing */ + #define GAUDOUT_FREEBLOCK 0x0004 /**< @brief An audio buffer has been freed */ + /** @} */ +} GEventAudioOut; +/** @} */ + /*===========================================================================*/ /* External declarations. */ /*===========================================================================*/ @@ -96,6 +126,8 @@ void gaudioReleaseBuffer(GAudioData *paud); * * @note Some channels are mono, and some are stereo. See your driver config file * to determine which channels to use and whether they are stereo or not. + * @note Only one channel can be playing at a time. Calling this will stop any + * currently playing channel. * * @api */ @@ -155,6 +187,25 @@ void gaudioPlayStop(void); */ bool_t gaudioPlaySetVolume(uint8_t vol); +#if GFX_USE_GEVENT || defined(__DOXYGEN__) + /** + * @brief Turn on sending results to the GEVENT sub-system. + * @details Returns a GSourceHandle to listen for GEVENT_AUDIO_OUT events. + * + * @note The audio output will not use the GEVENT system unless this is + * called first. This saves processing time if the application does + * not want to use the GEVENT sub-system for audio output. + * Once turned on it can only be turned off by calling @p gaudioPlayInit() again. + * @note The audio output is capable of signalling via this method and other methods + * at the same time. + * + * @return The GSourceHandle + * + * @api + */ + GSourceHandle gaudioPlayGetSource(void); +#endif + #ifdef __cplusplus } #endif -- cgit v1.2.3 From c70d98ef59bddda73cd4d97142a98f1513d11947 Mon Sep 17 00:00:00 2001 From: inmarket Date: Tue, 11 Mar 2014 17:09:00 +1000 Subject: Add bit format testing to sample formats. --- src/gmisc/sys_defs.h | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src') diff --git a/src/gmisc/sys_defs.h b/src/gmisc/sys_defs.h index cbb0111b..41a9bca6 100644 --- a/src/gmisc/sys_defs.h +++ b/src/gmisc/sys_defs.h @@ -39,6 +39,16 @@ typedef enum ArrayDataFormat_e { ARRAY_DATA_16BITUNSIGNED = 16, ARRAY_DATA_16BITSIGNED = 17, } ArrayDataFormat; +/** + * @brief Is the sample data format a "signed" data format? + */ +#define gfxSampleFormatIsSigned(fmt) ((fmt) & 1) + +/** + * @brief How many bits are in the sample data format + */ +#define gfxSampleFormatBits(fmt) ((fmt) & ~1) + /** * @brief The type for a fixed point type. * @details The top 16 bits are the integer component, the bottom 16 bits are the real component. -- cgit v1.2.3 From a29501c7bda2212417e1df4b255690bd7fb61ad2 Mon Sep 17 00:00:00 2001 From: inmarket Date: Tue, 11 Mar 2014 17:10:11 +1000 Subject: Add support for gfxSemWaitI() GOS api. --- src/gos/chibios.c | 7 +++++++ src/gos/chibios.h | 1 + src/gos/linux.h | 1 + src/gos/osx.h | 1 + src/gos/raw32.c | 7 +++++++ src/gos/raw32.h | 1 + src/gos/sys_defs.h | 13 +++++++++++++ src/gos/win32.h | 1 + 8 files changed, 32 insertions(+) (limited to 'src') diff --git a/src/gos/chibios.c b/src/gos/chibios.c index cf02b3e2..7d64fe1c 100644 --- a/src/gos/chibios.c +++ b/src/gos/chibios.c @@ -89,6 +89,13 @@ bool_t gfxSemWait(gfxSem *psem, delaytime_t ms) { return chSemWaitTimeout(&psem->sem, MS2ST(ms)) != RDY_TIMEOUT; } +bool_t gfxSemWaitI(gfxSem *psem) { + if (chSemGetCounterI(&psem->sem) <= 0) + return FALSE; + chSemFastWaitI(&psem->sem); + return TRUE; +} + void gfxSemSignal(gfxSem *psem) { chSysLock(); diff --git a/src/gos/chibios.h b/src/gos/chibios.h index 6373aa43..1db9482e 100644 --- a/src/gos/chibios.h +++ b/src/gos/chibios.h @@ -82,6 +82,7 @@ void gfxSleepMicroseconds(delaytime_t ms); void gfxSemInit(gfxSem *psem, semcount_t val, semcount_t limit); void gfxSemDestroy(gfxSem *psem); bool_t gfxSemWait(gfxSem *psem, delaytime_t ms); +bool_t gfxSemWaitI(gfxSem *psem); void gfxSemSignal(gfxSem *psem); void gfxSemSignalI(gfxSem *psem); #define gfxSemCounterI(psem) ((psem)->sem.s_cnt) diff --git a/src/gos/linux.h b/src/gos/linux.h index f8b049e9..f92fc4e9 100644 --- a/src/gos/linux.h +++ b/src/gos/linux.h @@ -46,6 +46,7 @@ typedef pthread_mutex_t gfxMutex; #define gfxMutexDestroy(pmtx) pthread_mutex_destroy(pmtx) #define gfxMutexEnter(pmtx) pthread_mutex_lock(pmtx) #define gfxMutexExit(pmtx) pthread_mutex_unlock(pmtx) +#define gfxSemWaitI(psem) gfxSemWait(psem, TIME_IMMEDIATE) #define gfxSemSignalI(psem) gfxSemSignal(psem) #define gfxSemCounterI(pSem) ((pSem)->cnt) diff --git a/src/gos/osx.h b/src/gos/osx.h index 56e0551e..80b07eec 100644 --- a/src/gos/osx.h +++ b/src/gos/osx.h @@ -45,6 +45,7 @@ typedef pthread_mutex_t gfxMutex; #define gfxMutexDestroy(pmtx) pthread_mutex_destroy(pmtx) #define gfxMutexEnter(pmtx) pthread_mutex_lock(pmtx) #define gfxMutexExit(pmtx) pthread_mutex_unlock(pmtx) +#define gfxSemWaitI(psem) gfxSemWait(psem, TIME_IMMEDIATE) #define gfxSemSignalI(psem) gfxSemSignal(psem) #define gfxSemCounterI(pSem) ((pSem)->cnt) diff --git a/src/gos/raw32.c b/src/gos/raw32.c index 61d09761..2fdfdf68 100644 --- a/src/gos/raw32.c +++ b/src/gos/raw32.c @@ -346,6 +346,13 @@ bool_t gfxSemWait(gfxSem *psem, delaytime_t ms) { return TRUE; } +bool_t gfxSemWaitI(gfxSem *psem) { + if (psem->cnt <= 0) + return FALSE; + psem->cnt--; + return TRUE; +} + void gfxSemSignal(gfxSem *psem) { INTERRUPTS_OFF(); gfxSemSignalI(psem); diff --git a/src/gos/raw32.h b/src/gos/raw32.h index eb5b5e18..d4e8e548 100644 --- a/src/gos/raw32.h +++ b/src/gos/raw32.h @@ -110,6 +110,7 @@ extern "C" { void gfxMutexExit(gfxMutex *pmutex); void gfxSemInit(gfxSem *psem, semcount_t val, semcount_t limit); bool_t gfxSemWait(gfxSem *psem, delaytime_t ms); + bool_t gfxSemWaitI(gfxSem *psem); void gfxSemSignal(gfxSem *psem); void gfxSemSignalI(gfxSem *psem); gfxThreadHandle gfxThreadCreate(void *stackarea, size_t stacksz, threadpriority_t prio, DECLARE_THREAD_FUNCTION((*fn),p), void *param); diff --git a/src/gos/sys_defs.h b/src/gos/sys_defs.h index b913fb66..f10ddd62 100644 --- a/src/gos/sys_defs.h +++ b/src/gos/sys_defs.h @@ -327,6 +327,19 @@ */ bool_t gfxSemWait(gfxSem *psem, delaytime_t ms); + /** + * @brief Test if a wait on a semaphore can be satisfied immediately + * @details Equivalent to @p gfxSemWait(psem, TIME_IMMEDIATE) except it can be called at interrupt level + * @return FALSE if the wait would occur occurred otherwise TRUE + * + * @param[in] psem A pointer to the semaphore + * @param[in] ms The maximum time to wait for the semaphore + * + * @iclass + * @api + */ + bool_t gfxSemWaitI(gfxSem *psem); + /** * @brief Signal a semaphore * @details The semaphore counter is increased and if the result is non-positive then a waiting thread diff --git a/src/gos/win32.h b/src/gos/win32.h index c704a288..8a5d9025 100644 --- a/src/gos/win32.h +++ b/src/gos/win32.h @@ -74,6 +74,7 @@ typedef HANDLE gfxThreadHandle; #define gfxMutexExit(pmutex) ReleaseMutex(*(pmutex)) #define gfxSemInit(psem, val, limit) *(psem) = CreateSemaphore(0, val, limit, 0) #define gfxSemDestroy(psem) CloseHandle(*(psem)) +#define gfxSemWaitI(psem) gfxSemWait((psem), TIME_IMMEDIATE) #define gfxSemSignal(psem) ReleaseSemaphore(*(psem), 1, 0) #define gfxSemSignalI(psem) ReleaseSemaphore(*(psem), 1, 0) #define gfxSemCounterI(psem) gfxSemCounter(psem) -- cgit v1.2.3 From 944c33cbff5f2cfb1c80f48193aa2161574864fd Mon Sep 17 00:00:00 2001 From: inmarket Date: Tue, 11 Mar 2014 17:11:02 +1000 Subject: Add support for gfxQueueGSyncGetI() --- src/gqueue/gqueue.c | 11 +++++++++++ src/gqueue/sys_defs.h | 13 +++++++------ 2 files changed, 18 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/gqueue/gqueue.c b/src/gqueue/gqueue.c index f3da1cdf..b7ecb032 100644 --- a/src/gqueue/gqueue.c +++ b/src/gqueue/gqueue.c @@ -138,6 +138,17 @@ return pi; } + gfxQueueGSyncItem *gfxQueueGSyncGetI(gfxQueueGSync *pqueue) { + gfxQueueGSyncItem *pi; + + if (!gfxSemWaitI(&pqueue->sem)) + return 0; + + pi = pqueue->head; + pqueue->head = pi->next; + pi->next = 0; + return pi; + } void gfxQueueGSyncPut(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem) { gfxSystemLock(); diff --git a/src/gqueue/sys_defs.h b/src/gqueue/sys_defs.h index 4446fcba..4351d4ad 100644 --- a/src/gqueue/sys_defs.h +++ b/src/gqueue/sys_defs.h @@ -113,6 +113,7 @@ void gfxQueueFSyncInit(gfxQueueFSync *pqueue); gfxQueueASyncItem *gfxQueueASyncGet(gfxQueueASync *pqueue); gfxQueueASyncItem *gfxQueueASyncGetI(gfxQueueASync *pqueue); gfxQueueGSyncItem *gfxQueueGSyncGet(gfxQueueGSync *pqueue, delaytime_t ms); +gfxQueueGSyncItem *gfxQueueGSyncGetI(gfxQueueGSync *pqueue); gfxQueueFSyncItem *gfxQueueFSyncGet(gfxQueueFSync *pqueue, delaytime_t ms); /* @} */ @@ -208,12 +209,12 @@ void gfxQueueFSyncRemove(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem); * @api * @{ */ -#define gfxQueueASyncIsEmpty(pqueue) (pqueue->head == 0) -#define gfxQueueASyncIsEmptyI(pqueue) (pqueue->head == 0) -#define gfxQueueGSyncIsEmpty(pqueue) (pqueue->head == 0) -#define gfxQueueGSyncIsEmptyI(pqueue) (pqueue->head == 0) -#define gfxQueueFSyncIsEmpty(pqueue) (pqueue->head == 0) -#define gfxQueueFSyncIsEmptyI(pqueue) (pqueue->head == 0) +#define gfxQueueASyncIsEmpty(pqueue) ((pqueue)->head == 0) +#define gfxQueueASyncIsEmptyI(pqueue) ((pqueue)->head == 0) +#define gfxQueueGSyncIsEmpty(pqueue) ((pqueue)->head == 0) +#define gfxQueueGSyncIsEmptyI(pqueue) ((pqueue)->head == 0) +#define gfxQueueFSyncIsEmpty(pqueue) ((pqueue)->head == 0) +#define gfxQueueFSyncIsEmptyI(pqueue) ((pqueue)->head == 0) /* @} */ /** -- cgit v1.2.3 From ea5a1b849df6e5085a92957ad387f9e653674415 Mon Sep 17 00:00:00 2001 From: inmarket Date: Tue, 11 Mar 2014 17:13:31 +1000 Subject: Combine GAUDIN and GAUDOUT into a single GAUDIO module. Simplify GAUDIN (now GAUDIO RECORD) api. Update audio demo's to match. Port Win32 driver to new audio api. --- src/gaudin/driver.h | 102 -------------- src/gaudin/gaudin.c | 158 --------------------- src/gaudin/sys_defs.h | 174 ----------------------- src/gaudin/sys_make.mk | 1 - src/gaudin/sys_options.h | 32 ----- src/gaudin/sys_rules.h | 30 ---- src/gaudio/driver_play.h | 126 +++++++++++++++++ src/gaudio/driver_record.h | 108 ++++++++++++++ src/gaudio/gaudio.c | 318 ++++++++++++++++++++++++++++++++++++++++++ src/gaudio/sys_defs.h | 340 +++++++++++++++++++++++++++++++++++++++++++++ src/gaudio/sys_make.mk | 1 + src/gaudio/sys_options.h | 44 ++++++ src/gaudio/sys_rules.h | 54 +++++++ src/gaudout/driver.h | 134 ------------------ src/gaudout/gaudout.c | 169 ---------------------- src/gaudout/sys_defs.h | 217 ----------------------------- src/gaudout/sys_make.mk | 1 - src/gaudout/sys_options.h | 32 ----- src/gaudout/sys_rules.h | 44 ------ src/gevent/sys_defs.h | 3 +- src/gfx.c | 22 +-- 21 files changed, 998 insertions(+), 1112 deletions(-) delete mode 100644 src/gaudin/driver.h delete mode 100644 src/gaudin/gaudin.c delete mode 100644 src/gaudin/sys_defs.h delete mode 100644 src/gaudin/sys_make.mk delete mode 100644 src/gaudin/sys_options.h delete mode 100644 src/gaudin/sys_rules.h create mode 100644 src/gaudio/driver_play.h create mode 100644 src/gaudio/driver_record.h create mode 100644 src/gaudio/gaudio.c create mode 100644 src/gaudio/sys_defs.h create mode 100644 src/gaudio/sys_make.mk create mode 100644 src/gaudio/sys_options.h create mode 100644 src/gaudio/sys_rules.h delete mode 100644 src/gaudout/driver.h delete mode 100644 src/gaudout/gaudout.c delete mode 100644 src/gaudout/sys_defs.h delete mode 100644 src/gaudout/sys_make.mk delete mode 100644 src/gaudout/sys_options.h delete mode 100644 src/gaudout/sys_rules.h (limited to 'src') diff --git a/src/gaudin/driver.h b/src/gaudin/driver.h deleted file mode 100644 index b534e2a5..00000000 --- a/src/gaudin/driver.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * 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 - */ - -/** - * @file src/gaudin/driver.h - * @brief GAUDIN - Audio Input driver header file. - * - * @defgroup Driver Driver - * @ingroup GAUDIN - * @{ - */ - -#ifndef _GAUDIN_LLD_H -#define _GAUDIN_LLD_H - -#include "gfx.h" - -#if GFX_USE_GAUDIN || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Type definitions */ -/*===========================================================================*/ - -/** - * @brief The structure passed to start a audio conversion - * @note We use the structure instead of parameters purely to save - * interrupt stack space which is very limited in some platforms. - * @{ - */ -typedef struct gaudin_params_t { - uint16_t channel; - uint32_t frequency; - audin_sample_t *buffer; - size_t bufcount; - size_t samplesPerEvent; - } gaudin_params; -/** @} */ - -/** - * @brief These routines are the callbacks that the driver uses. - * @details Defined in the high level GAUDIN code. - * - * @iclass - * @notapi - * - * @{ - */ - -/** - * @param[in] buffer The buffer - * @param[in] n The amount of samples - * */ -extern void GAUDIN_ISR_CompleteI(audin_sample_t *buffer, size_t n); - -extern void GAUDIN_ISR_ErrorI(void); -/** - * @} - */ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Initialise the driver - * - * @param[in] paud Initialisation parameters - * - * @api - */ -void gaudin_lld_init(const gaudin_params *paud); - -/** - * @brief Start the audio input sampling - * - * @api - */ -void gaudin_lld_start(void); - -/** - * @brief Stop the audio input sampling - * - * @api - */ -void gaudin_lld_stop(void); - -#ifdef __cplusplus -} -#endif - -#endif /* GFX_USE_GADC */ - -#endif /* _GADC_LLD_H */ -/** @} */ diff --git a/src/gaudin/gaudin.c b/src/gaudin/gaudin.c deleted file mode 100644 index 2e3507ef..00000000 --- a/src/gaudin/gaudin.c +++ /dev/null @@ -1,158 +0,0 @@ -/* - * 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 - */ - -/** - * @file src/gaudin/gaudin.c - * @brief GAUDIN sub-system code. - * - * @addtogroup GAUDIN - * @{ - */ -#include "gfx.h" - -#if GFX_USE_GAUDIN - -/* Include the driver defines */ -#include "src/gaudin/driver.h" - -static gaudin_params aud; -static gfxSem *paudSem; -static GEventAudioIn *paudEvent; -static audin_sample_t *lastbuffer; -static size_t lastcount; -static uint16_t audFlags; - #define AUDFLG_RUNNING 0x0001 - #define AUDFLG_USE_EVENTS 0x0002 - -#if GFX_USE_GEVENT - static GTimer AudGTimer; - - static void AudGTimerCallback(void *param) { - (void) param; - GSourceListener *psl; - GEventADC *pe; - - psl = 0; - while ((psl = geventGetSourceListener((GSourceHandle)(&aud), psl))) { - if (!(pe = (GEventAudioIn *)geventGetEventBuffer(psl))) { - // This listener is missing - save this. - psl->srcflags |= GAUDIN_LOSTEVENT; - continue; - } - - pe->type = GEVENT_AUDIO_IN; - pe->channel = aud.channel; - pe->count = lastcount; - pe->buffer = lastbuffer; - pe->flags = psl->srcflags; - psl->srcflags = 0; - geventSendEvent(psl); - } - } -#endif - -void GAUDIN_ISR_CompleteI(audin_sample_t *buffer, size_t n) { - /* Save the details */ - lastcount = n; - lastbuffer = buffer; - - /* Signal the user with the data */ - if (paudEvent) { - #if GFX_USE_GEVENT - paudEvent->type = GEVENT_AUDIO_IN; - #endif - paudEvent->channel = aud.channel; - paudEvent->count = lastcount; - paudEvent->buffer = lastbuffer; - paudEvent->flags = 0; - } - - /* Our two signalling mechanisms */ - if (paudSem) - gfxSemSignalI(paudSem); - - #if GFX_USE_GEVENT - if (audFlags & AUDFLG_USE_EVENTS) - gtimerJabI(&AudGTimer); - #endif -} - -void GAUDIN_ISR_ErrorI(void) { - /* Ignore any errors for now */ -} - -void _gaudinInit(void) -{ - #if GFX_USE_GEVENT - gtimerInit(&AudGTimer); - #endif -} - -void _gaudinDeinit(void) -{ - // Commented stuff still ToDo - #if GFX_USE_GEVENT - gtimerDeinit(&AudGTimer); - #endif -} - -bool_t gaudinInit(uint16_t channel, uint32_t frequency, audin_sample_t *buffer, size_t bufcount, size_t samplesPerEvent) { - /* Check the channel is valid */ - if (channel >= GAUDIN_NUM_CHANNELS || frequency > GAUDIN_MAX_SAMPLE_FREQUENCY) - return FALSE; - - /* Stop any existing transfers */ - if ((audFlags & AUDFLG_RUNNING)) - gaudin_lld_stop(); - audFlags = 0; - - /* Initialise everything */ - aud.channel = channel; - aud.frequency = frequency; - aud.buffer = buffer; - aud.bufcount = bufcount; - aud.samplesPerEvent = samplesPerEvent; - paudSem = 0; - paudEvent = 0; - - /* Set up the low level driver */ - gaudin_lld_init(&aud); - return TRUE; -} - -#if GFX_USE_GEVENT - GSourceHandle gaudinGetSource(void) { - if (!gtimerIsActive(&AudGTimer)) - gtimerStart(&AudGTimer, AudGTimerCallback, 0, TRUE, TIME_INFINITE); - audFlags |= AUDFLG_USE_EVENTS; - return (GSourceHandle)&aud; - } -#endif - -void gaudinSetBSem(gfxSem *pbsem, GEventAudioIn *pEvent) { - gfxSystemLock(); - paudSem = pbsem; - paudEvent = pEvent; - gfxSystemUnlock(); -} - -void gaudinStart(void) { - if (!(audFlags & AUDFLG_RUNNING)) { - audFlags |= AUDFLG_RUNNING; - gaudin_lld_start(); - } -} - -void gaudinStop(void) { - if ((audFlags & AUDFLG_RUNNING)) { - gaudin_lld_stop(); - audFlags &= ~AUDFLG_RUNNING; - } -} - -#endif /* GFX_USE_GAUDIN */ -/** @} */ diff --git a/src/gaudin/sys_defs.h b/src/gaudin/sys_defs.h deleted file mode 100644 index c65a69c1..00000000 --- a/src/gaudin/sys_defs.h +++ /dev/null @@ -1,174 +0,0 @@ -/* - * 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 - */ - -/** - * @file src/gaudin/sys_defs.h - * - * @addtogroup GAUDIN - * - * @brief Module to read audio inputs - * - * @{ - */ - -#ifndef _GAUDIN_H -#define _GAUDIN_H - -#include "gfx.h" - -#if GFX_USE_GAUDIN || defined(__DOXYGEN__) - -/* Include the driver defines */ -#include "gaudin_lld_config.h" - -/*===========================================================================*/ -/* Type definitions */ -/*===========================================================================*/ - -// Event types for GAUDIN -#define GEVENT_AUDIO_IN (GEVENT_GAUDIN_FIRST+0) - -/** - * @brief The Audio Input event structure. - * @{ - */ -typedef struct GEventAudioIn_t { - #if GFX_USE_GEVENT || defined(__DOXYGEN__) - /** - * @brief The type of this event (GEVENT_AUDIO_IN) - */ - GEventType type; - #endif - /** - * @brief The current channel - */ - uint16_t channel; - /** - * @brief The event flags - */ - uint16_t flags; - /** - * @brief The event flag values. - * @{ - */ - #define GAUDIN_LOSTEVENT 0x0001 /**< @brief The last GEVENT_AUDIO_IN event was lost */ - /** @} */ - /** - * @brief The number of audio samples in the buffer - */ - size_t count; - /** - * @brief The buffer containing the audio samples - */ - audin_sample_t *buffer; -} GEventAudioIn; -/** @} */ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Initialise (but not start) the Audio Input Subsystem. - * @details Returns FALSE for an invalid channel or other invalid parameter. - * - * @param[in] channel The channel to convert. Can be set from 0 to GAUDIN_NUM_CHANNELS - 1. - * @param[in] frequency The sample frequency - * @param[in] buffer The static buffer to put the samples into. - * @param[in] bufcount The total number of conversions that will fit in the buffer. - * @param[in] samplesPerEvent The number of conversions to do before returning an event. - * - * @note Only one channel is active at a time. If an audio input is running it will be stopped. - * The Event subsystem is disconnected from the audio subsystem and any binary semaphore - * event is forgotten. - * @note Some channels may be stereo channels which return twice as much sample data with - * the left and right channel data interleaved. Other channels may be mono channels. - * Where stereo channels exist it would be common for the low level driver to also - * offer the left and right channels separately. - * @note Due to a bug in Chibi-OS countPerEvent must be even if using the GADC low level audio driver. - * If bufcount is not evenly divisable by countPerEvent, the remainder must also be even. - * This requirement may not apply to other GAUDIN drivers. - * @note The number of samples for stereo devices will be double the number of conversions. - * Make sure you allocate your buffers large enough. Each channel is then interleaved - * into the provided buffer. Note 'bufcount' and 'countPerEvent' parameters describe the - * number of conversions not the number of samples. - * @note The buffer is circular. When the end of the buffer is reached it will start - * putting data into the beginning of the buffer again. - * @note The event listener must process the event (and the data in it) before the - * next event occurs. If not, the following event will be lost. - * @note If bufcount is evenly divisable by countPerEvent, then every event will return - * countPerEvent conversions. If bufcount is not evenly divisable, it will return - * a block of samples containing less than countPerEvent samples when it reaches the - * end of the buffer. - * - * @return FALSE if invalid channel or parameter - * - * @api - */ -bool_t gaudinInit(uint16_t channel, uint32_t frequency, audin_sample_t *buffer, size_t bufcount, size_t samplesPerEvent); - -#if GFX_USE_GEVENT || defined(__DOXYGEN__) - /** - * @brief Turn on sending results to the GEVENT sub-system. - * @details Returns a GSourceHandle to listen for GEVENT_AUDIO_IN events. - * - * @note The audio input will not use the GEVENT system unless this is - * called first. This saves processing time if the application does - * not want to use the GEVENT sub-system for audio input. - * Once turned on it can only be turned off by calling @p gaudinInit() again. - * @note The audio input is capable of signalling via this method and a binary semaphore - * at the same time. - * - * @return The GSourceHandle - * - * @api - */ - GSourceHandle gaudinGetSource(void); -#endif - -/** - * @brief Allow retrieving of results from the audio input using a Binary Semaphore and a static event buffer. - * - * @param[in] pbsem The semaphore is signaled when data is available. - * @param[in] pEvent The static event buffer to place the result information. - * - * @note Passing a NULL for pbsem or pEvent will turn off signalling via this method. - * @note The audio input is capable of signalling via this method and the GEVENT - * sub-system at the same time. - * - * @api - */ -void gaudinSetBSem(gfxSem *pbsem, GEventAudioIn *pEvent); - -/** - * @brief Start the audio input conversions. - * @pre It must have been initialised first with @p gaudinInit() - * - * @api - */ -void gaudinStart(void); - -/** - * @brief Stop the audio input conversions. - * - * @api - */ -void gaudinStop(void); - -#ifdef __cplusplus -} -#endif - -#endif /* GFX_USE_GAUDIN */ - -#endif /* _GAUDIN_H */ -/** @} */ - diff --git a/src/gaudin/sys_make.mk b/src/gaudin/sys_make.mk deleted file mode 100644 index 16bb33b7..00000000 --- a/src/gaudin/sys_make.mk +++ /dev/null @@ -1 +0,0 @@ -GFXSRC += $(GFXLIB)/src/gaudin/gaudin.c diff --git a/src/gaudin/sys_options.h b/src/gaudin/sys_options.h deleted file mode 100644 index 305a6f8d..00000000 --- a/src/gaudin/sys_options.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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 - */ - -/** - * @file src/gaudin/sys_options.h - * @brief GAUDIN - Audio Input subsystem options header file. - * - * @addtogroup GAUDIN - * @{ - */ - -#ifndef _GAUDIN_OPTIONS_H -#define _GAUDIN_OPTIONS_H - -/** - * @name GAUDIN Functionality to be included - * @{ - */ -/** - * @} - * - * @name GAUDIN Optional Sizing Parameters - * @{ - */ -/** @} */ - -#endif /* _GAUDIN_OPTIONS_H */ -/** @} */ diff --git a/src/gaudin/sys_rules.h b/src/gaudin/sys_rules.h deleted file mode 100644 index 21d2552f..00000000 --- a/src/gaudin/sys_rules.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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 - */ - -/** - * @file src/gaudin/sys_rules.h - * @brief GAUDIN safety rules header file. - * - * @addtogroup GAUDIN - * @{ - */ - -#ifndef _GAUDIN_RULES_H -#define _GAUDIN_RULES_H - -#if GFX_USE_GAUDIN - #if GFX_USE_GEVENT && !GFX_USE_GTIMER - #if GFX_DISPLAY_RULE_WARNINGS - #warning "GAUDIN: GFX_USE_GTIMER is required if GFX_USE_GAUDIN and GFX_USE_GEVENT are TRUE. It has been turned on for you." - #endif - #undef GFX_USE_GTIMER - #define GFX_USE_GTIMER TRUE - #endif -#endif - -#endif /* _GAUDIN_RULES_H */ -/** @} */ diff --git a/src/gaudio/driver_play.h b/src/gaudio/driver_play.h new file mode 100644 index 00000000..72ad4747 --- /dev/null +++ b/src/gaudio/driver_play.h @@ -0,0 +1,126 @@ +/* + * 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 + */ + +/** + * @file src/gaudio/driver_play.h + * @brief GAUDIO - Audio play driver header file. + * + * @defgroup Driver Driver + * @ingroup GAUDIO + * @{ + */ + +#ifndef _GAUDIO_PLAY_LLD_H +#define _GAUDIO_PLAY_LLD_H + +#include "gfx.h" + +#if (GFX_USE_GAUDIO && GAUDIO_NEED_PLAY) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Type definitions */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Get a block of audio data to play + * @return A pointer to the GAaudioData structure or NULL if none is currently available + * + * @note Defined in the high level GAUDIO code for use by the GAUDIO play drivers. + * + * @iclass + * @notapi + */ +GAudioData *gaudioPlayGetDataBlockI(void); + +/** + * @brief Release a block of audio data to the free list + * + * @param[in] paud The GAudioData block to be released. + * + * @note Defined in the high level GAUDIO code for use by the GAUDIO play drivers. + * + * @iclass + * @notapi + */ +void gaudioPlayReleaseDataBlockI(GAudioData *paud); + +/** + * @brief Signal that all playing has now stopped + * + * @note Defined in the high level GAUDIO code for use by the GAUDIO play drivers. + * + * @iclass + * @notapi + */ +void gaudioPlayDoneI(void); + +/** + * @brief Initialise the play driver + * @return TRUE if the channel, frequency and format are valid. + * + * @param[in] channel The channel to use (see the driver for the available channels provided) + * @param[in] frequency The sample frequency to use + * @param[in] format The sample format + * + * @note The driver will always have been stopped and de-init before this is called. + * + * @api + */ +bool_t gaudio_play_lld_init(uint16_t channel, uint32_t frequency, ArrayDataFormat format); + +/** + * @brief Start the audio output playing + * + * @note This may be called at any stage including while the driver + * is already playing. The driver should check for data blocks + * to play using @p gaudioPlayGetDataBlockI(). + * + * @api + */ +void gaudio_play_lld_start(void); + +/** + * @brief Stop the audio output playing. + * + * @note Some drivers may only stop playing at a data block boundary. + * @note It is possible but unlikely for it to be called when playing has already stopped. + * @note It should not return until all active buffers (currently in use by the driver) + * have been returned to the free-list and @p gaudioPlayDoneI() has been called. + * + * @api + */ +void gaudio_play_lld_stop(void); + +/** + * @brief Set the output volume. + * @return TRUE if successful. + * + * @param[in] 0->255 (0 = muted) + * + * @note Some drivers may not support this. They will return FALSE. + * @note For stereo devices, both channels are set to the same volume. + * + * @api + */ +bool_t gaudio_play_lld_set_volume(uint8_t vol); + +#ifdef __cplusplus +} +#endif + +#endif /* GFX_USE_GAUDIO && GAUDIO_NEED_PLAY */ + +#endif /* _GAUDIO_PLAY_LLD_H */ +/** @} */ diff --git a/src/gaudio/driver_record.h b/src/gaudio/driver_record.h new file mode 100644 index 00000000..252cae5c --- /dev/null +++ b/src/gaudio/driver_record.h @@ -0,0 +1,108 @@ +/* + * 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 + */ + +/** + * @file src/gaudio/driver_record.h + * @brief GAUDIO - Audio Recording driver header file. + * + * @defgroup Driver Driver + * @ingroup GAUDIO + * @{ + */ + +#ifndef _GAUDIO_RECORD_LLD_H +#define _GAUDIO_RECORD_LLD_H + +#include "gfx.h" + +#if (GFX_USE_GAUDIO && GAUDIO_NEED_RECORD) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Type definitions */ +/*===========================================================================*/ + +/** + * @brief Get a free block of audio data that we can record into + * @return A pointer to the GAaudioData structure or NULL if none is currently available + * + * @note Defined in the high level GAUDIO code for use by the GAUDIO record drivers. + * + * @iclass + * @notapi + */ +GAudioData *gaudioRecordGetFreeBlockI(void); + +/** + * @brief Save a block of recorded audio data ready for the application + * + * @param[in] paud The GAudioData block with data. + * + * @note Defined in the high level GAUDIO code for use by the GAUDIO record drivers. + * + * @iclass + * @notapi + */ +void gaudioRecordSaveDataBlockI(GAudioData *paud); + +/** + * @brief Signal that all recording has now stopped + * + * @note Defined in the high level GAUDIO code for use by the GAUDIO record drivers. + * + * @iclass + * @notapi + */ +void gaudioRecordDoneI(void); + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Initialise the record driver + * @return TRUE if the channel, frequency and format are valid. + * + * @param[in] channel The channel to use (see the driver for the available channels provided) + * @param[in] frequency The sample frequency to use + * @param[in] format The sample format + * + * @note The driver will always have been stopped and de-init before this is called. + * + * @api + */ +bool_t gaudio_record_lld_init(uint16_t channel, uint32_t frequency, ArrayDataFormat format); + +/** + * @brief Start the audio recording + * + * @api + */ +void gaudio_record_lld_start(void); + +/** + * @brief Stop the audio recording. + * + * @note Some drivers may only stop recording at a data block boundary. + * @note This routine should not return until any currently active buffers have been + * saved (even if with zero length) and @p gaudioRecordDoneI() has been called. + * + * @api + */ +void gaudio_record_lld_stop(void); + +#ifdef __cplusplus +} +#endif + +#endif /* GFX_USE_GAUDIO && GAUDIO_NEED_RECORD */ + +#endif /* _GAUDIO_RECORD_LLD_H */ +/** @} */ diff --git a/src/gaudio/gaudio.c b/src/gaudio/gaudio.c new file mode 100644 index 00000000..a83dcd85 --- /dev/null +++ b/src/gaudio/gaudio.c @@ -0,0 +1,318 @@ +/* + * 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 + */ + +/** + * @file src/gaudio/gaudio.c + * @brief GAUDIO sub-system code. + * + * @addtogroup GAUDIO + * @{ + */ +#include "gfx.h" + +#if GFX_USE_GAUDIO + +static gfxQueueGSync freeList; + +#if GAUDIO_NEED_PLAY + #include "src/gaudio/driver_play.h" + + static gfxQueueASync playList; + static gfxSem playComplete; + static uint16_t playFlags; + #define PLAYFLG_USEEVENTS 0x0001 + #define PLAYFLG_PLAYING 0x0002 + #define PLAYFLG_ISINIT 0x0004 + #if GFX_USE_GEVENT + static GTimer playTimer; + static void PlayTimerCallback(void *param); + #endif +#endif + +#if GAUDIO_NEED_RECORD + #include "src/gaudio/driver_record.h" + + static gfxQueueGSync recordList; + static uint16_t recordFlags; + #define RECORDFLG_USEEVENTS 0x0001 + #define RECORDFLG_RECORDING 0x0002 + #define RECORDFLG_STALLED 0x0004 + #define RECORDFLG_ISINIT 0x0008 + #if GFX_USE_GEVENT + static GTimer recordTimer; + static void RecordTimerCallback(void *param); + #endif +#endif + + +void _gaudioInit(void) +{ + gfxQueueGSyncInit(&freeList); + #if GAUDIO_NEED_PLAY + gfxQueueASyncInit(&playList); + #if GFX_USE_GEVENT + gtimerInit(&playTimer); + #endif + gfxSemInit(&playComplete, 0, 0); + #endif + #if GAUDIO_NEED_RECORD + gfxQueueGSyncInit(&recordList); + #if GFX_USE_GEVENT + gtimerInit(&recordTimer); + #endif + #endif +} + +void _gaudioDeinit(void) +{ + #if GAUDIO_NEED_PLAY + #if GFX_USE_GEVENT + gtimerDeinit(&playTimer); + #endif + gfxSemDestroy(&playComplete); + #endif + #if GAUDIO_NEED_RECORD + #if GFX_USE_GEVENT + gtimerDeinit(&recordTimer); + #endif + #endif +} + +bool_t gaudioAllocBuffers(unsigned num, size_t size) { + GAudioData *paud; + + if (num < 1) + return FALSE; + + // Round up to a multiple of 4 to prevent problems with structure alignment + size = (size + 3) & ~0x03; + + // Allocate the memory + if (!(paud = gfxAlloc((size+sizeof(GAudioData)) * num))) + return FALSE; + + // Add each of them to our free list + for(;num--; paud = (GAudioData *)((char *)(paud+1)+size)) { + paud->size = size; + gfxQueueGSyncPut(&freeList, (gfxQueueGSyncItem *)paud); + } + + return TRUE; +} + +void gaudioReleaseBuffer(GAudioData *paud) { + gfxQueueGSyncPut(&freeList, (gfxQueueGSyncItem *)paud); +} + +GAudioData *gaudioGetBuffer(delaytime_t ms) { + return (GAudioData *)gfxQueueGSyncGet(&freeList, ms); +} + +#if GAUDIO_NEED_PLAY + + bool_t gaudioPlayInit(uint16_t channel, uint32_t frequency, ArrayDataFormat format) { + gaudioPlayStop(); + playFlags &= ~PLAYFLG_ISINIT; + if (!gaudio_play_lld_init(channel, frequency, format)) + return FALSE; + playFlags |= PLAYFLG_ISINIT; + return TRUE; + } + + void gaudioPlay(GAudioData *paud) { + if (!(playFlags & PLAYFLG_ISINIT)) { + // Oops - init failed - return it directly to the free-list + if (paud) { + gfxQueueGSyncPut(&freeList, (gfxQueueGSyncItem *)paud); + gfxYield(); // Make sure we get no endless cpu hogging loops + } + return; + } + + if (paud) + gfxQueueASyncPut(&playList, (gfxQueueASyncItem *)paud); + playFlags |= PLAYFLG_PLAYING; + gaudio_play_lld_start(); + } + + void gaudioPlayPause(void) { + if ((playFlags & (PLAYFLG_ISINIT|PLAYFLG_PLAYING)) == (PLAYFLG_ISINIT|PLAYFLG_PLAYING)) + gaudio_play_lld_stop(); + } + + void gaudioPlayStop(void) { + GAudioData *paud; + + if (playFlags & PLAYFLG_PLAYING) + gaudio_play_lld_stop(); + while((paud = (GAudioData *)gfxQueueASyncGet(&playList))) + gfxQueueGSyncPut(&freeList, (gfxQueueGSyncItem *)paud); + } + + bool_t gaudioPlaySetVolume(uint8_t vol) { + return gaudio_play_lld_set_volume(vol); + } + + bool_t gaudioPlayWait(delaytime_t ms) { + if (!(playFlags & PLAYFLG_PLAYING)) + return TRUE; + return gfxSemWait(&playComplete, ms); + } + + #if GFX_USE_GEVENT + static void PlayTimerCallback(void *param) { + (void) param; + GSourceListener *psl; + GEventAudioPlay *pe; + + psl = 0; + while ((psl = geventGetSourceListener((GSourceHandle)&playTimer, psl))) { + if (!(pe = (GEventAudioPlay *)geventGetEventBuffer(psl))) { + // This listener is missing - save this. + psl->srcflags |= GAUDIO_PLAY_LOSTEVENT; + continue; + } + + pe->type = GEVENT_AUDIO_PLAY; + pe->flags = psl->srcflags; + psl->srcflags = 0; + if ((playFlags & PLAYFLG_PLAYING)) + pe->flags |= GAUDIO_PLAY_PLAYING; + if (!gfxQueueGSyncIsEmpty(&freeList)) + pe->flags |= GAUDIO_PLAY_FREEBLOCK; + geventSendEvent(psl); + } + } + + GSourceHandle gaudioPlayGetSource(void) { + if (!gtimerIsActive(&playTimer)) + gtimerStart(&playTimer, PlayTimerCallback, 0, TRUE, TIME_INFINITE); + playFlags |= PLAYFLG_USEEVENTS; + return (GSourceHandle)&playTimer; + } + #endif + + /** + * Routines provided for use by drivers. + */ + + GAudioData *gaudioPlayGetDataBlockI(void) { + return (GAudioData *)gfxQueueASyncGetI(&playList); + } + + void gaudioPlayReleaseDataBlockI(GAudioData *paud) { + gfxQueueGSyncPutI(&freeList, (gfxQueueGSyncItem *)paud); + #if GFX_USE_GEVENT + if (playFlags & PLAYFLG_USEEVENTS) + gtimerJabI(&playTimer); + #endif + } + + void gaudioPlayDoneI(void) { + playFlags &= ~PLAYFLG_PLAYING; + #if GFX_USE_GEVENT + if (playFlags & PLAYFLG_USEEVENTS) + gtimerJabI(&playTimer); + #endif + gfxSemSignalI(&playComplete); // This should really be gfxSemSignalAllI(&playComplete); + } +#endif + +#if GAUDIO_NEED_RECORD + bool_t gaudioRecordInit(uint16_t channel, uint32_t frequency, ArrayDataFormat format) { + gaudioRecordStop(); + recordFlags &= ~RECORDFLG_ISINIT; + if (!gaudio_record_lld_init(channel, frequency, format)) + return FALSE; + recordFlags |= RECORDFLG_ISINIT; + return TRUE; + } + + void gaudioRecordStart(void) { + if (!(recordFlags & RECORDFLG_ISINIT)) + return; // Oops - init failed + + recordFlags |= RECORDFLG_RECORDING; + recordFlags &= ~RECORDFLG_STALLED; + gaudio_record_lld_start(); + } + + void gaudioRecordStop(void) { + GAudioData *paud; + + if ((recordFlags & (RECORDFLG_RECORDING|RECORDFLG_STALLED)) == RECORDFLG_RECORDING) + gaudio_record_lld_stop(); + recordFlags &= ~(RECORDFLG_RECORDING|RECORDFLG_STALLED); + while((paud = (GAudioData *)gfxQueueGSyncGet(&recordList, TIME_IMMEDIATE))) + gfxQueueGSyncPut(&freeList, (gfxQueueGSyncItem *)paud); + } + + GAudioData *gaudioRecordGetData(delaytime_t ms) { + return (GAudioData *)gfxQueueGSyncGet(&recordList, ms); + } + + #if GFX_USE_GEVENT + static void RecordTimerCallback(void *param) { + (void) param; + GSourceListener *psl; + GEventAudioRecord *pe; + + psl = 0; + while ((psl = geventGetSourceListener((GSourceHandle)&recordTimer, psl))) { + if (!(pe = (GEventAudioRecord *)geventGetEventBuffer(psl))) { + // This listener is missing - save this. + psl->srcflags |= GAUDIO_RECORD_LOSTEVENT; + continue; + } + pe->type = GEVENT_AUDIO_RECORD; + pe->flags = psl->srcflags; + psl->srcflags = 0; + if ((recordFlags & RECORDFLG_RECORDING)) + pe->flags |= GAUDIO_RECORD_RECORDING; + if ((recordFlags & RECORDFLG_STALLED)) + pe->flags |= GAUDIO_RECORD_STALL; + if (!gfxQueueGSyncIsEmpty(&recordList)) + pe->flags |= GAUDIO_RECORD_GOTBLOCK; + geventSendEvent(psl); + } + } + + GSourceHandle gaudioRecordGetSource(void) { + if (!gtimerIsActive(&recordTimer)) + gtimerStart(&recordTimer, RecordTimerCallback, 0, TRUE, TIME_INFINITE); + recordFlags |= RECORDFLG_USEEVENTS; + return (GSourceHandle)&recordTimer; + } + #endif + + /** + * Routines provided for use by drivers. + */ + + GAudioData *gaudioRecordGetFreeBlockI(void) { + return (GAudioData *)gfxQueueGSyncGetI(&freeList); + } + + void gaudioRecordSaveDataBlockI(GAudioData *paud) { + gfxQueueGSyncPutI(&recordList, (gfxQueueGSyncItem *)paud); + #if GFX_USE_GEVENT + if (recordFlags & RECORDFLG_USEEVENTS) + gtimerJabI(&recordTimer); + #endif + } + + void gaudioRecordDoneI(void) { + recordFlags |= RECORDFLG_STALLED; + #if GFX_USE_GEVENT + if (recordFlags & RECORDFLG_USEEVENTS) + gtimerJabI(&recordTimer); + #endif + } +#endif + +#endif /* GFX_USE_GAUDIO */ +/** @} */ diff --git a/src/gaudio/sys_defs.h b/src/gaudio/sys_defs.h new file mode 100644 index 00000000..a9a951b7 --- /dev/null +++ b/src/gaudio/sys_defs.h @@ -0,0 +1,340 @@ +/* + * 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 + */ + +/** + * @file src/gaudio/sys_defs.h + * + * @addtogroup GAUDIO + * + * @brief Module to handle audio recording and play-back + * + * @{ + */ + +#ifndef _GAUDIO_H +#define _GAUDIO_H + +#include "gfx.h" + +#if GFX_USE_GAUDIO || defined(__DOXYGEN__) + +/* Include the driver defines */ +#if GAUDIO_NEED_PLAY + #include "gaudio_play_config.h" +#endif +#if GAUDIO_NEED_RECORD + #include "gaudio_record_config.h" +#endif + +/*===========================================================================*/ +/* Type definitions */ +/*===========================================================================*/ + +/** + * @brief Contains Audio Data Samples + * @note This structure is followed immediately by the sample data itself. + * When allocating the buffers for the sample data put this structure + * at the beginning of the buffer. + */ +typedef struct GAudioData { + gfxQueueASyncItem next; // @< Used for queuing the buffers + size_t size; // @< The size of the buffer area following this structure (in bytes) + size_t len; // @< The length of the data in the buffer area (in bytes) +} GAudioData; + + +// Event types for GAUDIO +#define GEVENT_AUDIO_PLAY (GEVENT_GAUDIO_FIRST+0) +#define GEVENT_AUDIO_RECORD (GEVENT_GAUDIO_FIRST+1) + +#if GFX_USE_GEVENT || defined(__DOXYGEN__) + /** + * @brief The Audio play event structure. + * @{ + */ + typedef struct GEventAudioPlay_t { + /** + * @brief The type of this event (GEVENT_AUDIO_PLAY) + */ + GEventType type; + /** + * @brief The event flags + */ + uint16_t flags; + /** + * @brief The event flag values. + * @{ + */ + #define GAUDIO_PLAY_LOSTEVENT 0x0001 /**< @brief The last GEVENT_AUDIO_PLAY event was lost */ + #define GAUDIO_PLAY_PLAYING 0x0002 /**< @brief The audio out system is currently playing */ + #define GAUDIO_PLAY_FREEBLOCK 0x0004 /**< @brief An audio buffer has been freed */ + /** @} */ + } GEventAudioPlay; + /** @} */ + + /** + * @brief The Audio record event structure. + * @{ + */ + typedef struct GEventAudioRecord_t { + /** + * @brief The type of this event (GEVENT_AUDIO_RECORD) + */ + GEventType type; + /** + * @brief The event flags + */ + uint16_t flags; + /** + * @brief The event flag values. + * @{ + */ + #define GAUDIO_RECORD_LOSTEVENT 0x0001 /**< @brief The last GEVENT_AUDIO_IN event was lost */ + #define GAUDIO_RECORD_RECORDING 0x0002 /**< @brief The audio recording system is currently recording */ + #define GAUDIO_RECORD_GOTBLOCK 0x0004 /**< @brief An audio buffer is ready for processing */ + #define GAUDIO_RECORD_STALL 0x0008 /**< @brief The recording process has stalled due to no free buffers */ + /** @} */ + } GEventAudioRecord; + /** @} */ +#endif + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Allocate some audio buffers and put them on the free list + * @return TRUE is it succeeded. FALSE on allocation failure. + * + * @param[in] num The number of buffers to allocate + * @param[in] size The size (in bytes) of each buffer + * + * @api + */ +bool_t gaudioAllocBuffers(unsigned num, size_t size); + +/** + * @brief Get an audio buffer from the free list + * @return A GAudioData pointer or NULL if the timeout is exceeded + * + * @params[in] ms The maximum amount of time in milliseconds to wait for a buffer if one is not available. + * + * @api + */ +GAudioData *gaudioGetBuffer(delaytime_t ms); + +/** + * @brief Release a buffer back to the free list + * + * @param[in] paud The buffer to put (back) on the free-list. + * + * @note This call should be used to return any buffers that were taken from + * the free-list once they have been finished with. It can also be used + * to put new buffers onto the free-list. Just make sure the "size" field + * of the GAudioData structure has been filled in first. + * + * @api + */ +void gaudioReleaseBuffer(GAudioData *paud); + +#if GAUDIO_NEED_PLAY || defined(__DOXYGEN__) + /** + * @brief Set the audio device to play on the specified channel and with the specified + * sample frequency. + * @return TRUE is successful, FALSE if the driver doesn't accept those parameters. + * + * @param[in] channel The audio output channel to use. Can be set from 0 to GAUDIO_PLAY_NUM_CHANNELS - 1 + * @param[in] frequency The audio sample rate in samples per second + * @param[in] format The audio sample format + * + * @note Some channels are mono, and some are stereo. See your driver config file + * to determine which channels to use and whether they are stereo or not. + * @note Only one channel can be playing at a time. Calling this will stop any + * currently playing channel. + * + * @api + */ + bool_t gaudioPlayInit(uint16_t channel, uint32_t frequency, ArrayDataFormat format); + + /** + * @brief Play the specified sample data. + * @details The sample data is output to the audio channel. On completion the buffer is returned to the free-list. + * @pre @p gaudioPlayInit must have been called first to set the channel and sample frequency. + * + * @param[in] paud The audio sample buffer to play. It can be NULL (used to restart paused audio) + * + * @note Calling this will cancel any pause. + * @note Before calling this function the len field of the GAudioData structure must be + * specified (in bytes). + * @note For stereo channels the sample data is interleaved in the buffer. + * @note This call returns before the data has completed playing. Subject to available buffers (which + * can be obtained from the free-list), any number of buffers may be played. They will be queued + * for playing in the order they are supplied to this routine and played when previous buffers are + * complete. In this way continuous playing can be obtained without audio gaps. + * + * @api + */ + void gaudioPlay(GAudioData *paud); + + /** + * @brief Pause any currently playing sounds. + * + * @note If nothing is currently playing this routine does nothing. To restart playing call @p gaudioPlay() + * with or without a new sample buffer. + * @note Some drivers will not respond until a buffer boundary. + * + * @api + */ + void gaudioPlayPause(void); + + /** + * @brief Stop any currently playing sounds. + * + * @note This stops any playing sounds and returns any currently queued buffers back to the free-list. + * @note Some drivers will not respond until a buffer boundary. + * + * @api + */ + void gaudioPlayStop(void); + + /** + * @brief Set the output volume. + * @return TRUE if successful. + * + * @param[in] 0->255 (0 = muted) + * + * @note Some drivers may not support this. They will return FALSE. + * @note For stereo devices, both channels are set to the same volume. + * + * @api + */ + bool_t gaudioPlaySetVolume(uint8_t vol); + + #if GFX_USE_GEVENT || defined(__DOXYGEN__) + /** + * @brief Turn on sending results to the GEVENT sub-system. + * @details Returns a GSourceHandle to listen for GEVENT_AUDIO_OUT events. + * + * @note The audio output will not use the GEVENT system unless this is + * called first. This saves processing time if the application does + * not want to use the GEVENT sub-system for audio output. + * Once turned on it can only be turned off by calling @p gaudioPlayInit() again. + * @note The audio output is capable of signaling via this method and other methods + * at the same time. + * + * @return The GSourceHandle + * + * @api + */ + GSourceHandle gaudioPlayGetSource(void); + #endif + + /** + * @brief Wait for any currently playing sounds to complete + * @return TRUE if there is now nothing playing or FALSE if the timeout is exceeded + * + * @params[in] ms The maximum amount of time in milliseconds to wait for playing to complete. + * + * @api + */ + bool_t gaudioPlayWait(delaytime_t ms); +#endif + +#if GAUDIO_NEED_RECORD || defined(__DOXYGEN__) + /** + * @brief Initialise (but not start) the Audio Recording sub-system. + * @details Returns FALSE for an invalid channel or other invalid parameter. + * + * @param[in] channel The channel to convert. Can be set from 0 to GAUDIO_RECORD_NUM_CHANNELS - 1 + * @param[in] frequency The sample frequency + * @param[in] format The audio sample format requested + * + * @note Only one channel is active at a time. If an audio input is running it will be stopped. + * The Event subsystem is disconnected from the audio subsystem and any binary semaphore + * event is forgotten. + * @note Some channels may be stereo channels which return twice as much sample data with + * the left and right channel data interleaved. Other channels may be mono channels. + * Where stereo channels exist the low level driver may also + * offer the left and right channels separately. + * @note Due to a bug in Chibi-OS each buffer on the free-list must contain an even number of + * samples and for stereo devices it must hold a number of samples that is evenly divisible by 4. + * This requirement applies only to ChibiOS where the audio driver uses + * a ChibiOS hal driver like the cpu ADC driver. This applies even it is used indirectly via + * the uGFX GADC driver. + * @note The number of samples for stereo devices will be double the number of conversions. + * Make sure you allocate your buffers large enough. Each channel is then interleaved + * into the provided buffer. + * + * @return FALSE if invalid channel or parameter + * + * @api + */ + bool_t gaudioRecordInit(uint16_t channel, uint32_t frequency, ArrayDataFormat format); + + /** + * @brief Start the audio recording. + * @pre It must have been initialised first with @p gaudioRecordInit() + * + * @api + */ + void gaudioRecordStart(void); + + /** + * @brief Stop the audio recording. + * + * @note All audio recording data that has not yet been retrieved is automatically + * returned to the free-list. + * @api + */ + void gaudioRecordStop(void); + + /** + * @brief Get a filled audio buffer from the recording list + * @return A GAudioData pointer or NULL if the timeout is exceeded + * + * @params[in] ms The maximum amount of time in milliseconds to wait for data if some is not currently available. + * + * @note After processing the audio data, your application must return the buffer to the free-list so that + * it can be used to record more audio into. This can be done via the play list using @p gaudioPlay() or + * directly using @p gaudioReleaseBuffer(). + * @api + */ + GAudioData *gaudioRecordGetData(delaytime_t ms); + + #if GFX_USE_GEVENT || defined(__DOXYGEN__) + /** + * @brief Turn on sending results to the GEVENT sub-system. + * @details Returns a GSourceHandle to listen for GEVENT_AUDIO_RECORD events. + * + * @note Audio recording will not use the GEVENT system unless this is + * called first. This saves processing time if the application does + * not want to use the GEVENT sub-system for audio recording. + * Once turned on it can only be turned off by calling @p gaudioRecordInit() again. + * @note The audio input is capable of signaling via this and other methods + * at the same time. + * + * @return The GSourceHandle + * + * @api + */ + GSourceHandle gaudioRecordGetSource(void); + #endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* GFX_USE_GAUDIO */ + +#endif /* _GAUDIO_H */ +/** @} */ + diff --git a/src/gaudio/sys_make.mk b/src/gaudio/sys_make.mk new file mode 100644 index 00000000..438892c0 --- /dev/null +++ b/src/gaudio/sys_make.mk @@ -0,0 +1 @@ +GFXSRC += $(GFXLIB)/src/gaudio/gaudio.c diff --git a/src/gaudio/sys_options.h b/src/gaudio/sys_options.h new file mode 100644 index 00000000..1363d703 --- /dev/null +++ b/src/gaudio/sys_options.h @@ -0,0 +1,44 @@ +/* + * 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 + */ + +/** + * @file src/gaudio/sys_options.h + * @brief GAUDIO - Audio subsystem options header file. + * + * @addtogroup GAUDIO + * @{ + */ + +#ifndef _GAUDIO_OPTIONS_H +#define _GAUDOUT_OPTIONS_H + +/** + * @name GAUDIO Functionality to be included + * @{ + */ + /** + * @brief Audio Play capability is needed + */ + #ifndef GAUDIO_NEED_PLAY + #define GAUDIO_NEED_PLAY FALSE + #endif + /** + * @brief Audio Recording capability is needed + */ + #ifndef GAUDIO_NEED_RECORD + #define GAUDIO_NEED_RECORD FALSE + #endif +/** + * @} + * + * @name GAUDIO Optional Sizing Parameters + * @{ + */ +/** @} */ + +#endif /* _GAUDIO_OPTIONS_H */ +/** @} */ diff --git a/src/gaudio/sys_rules.h b/src/gaudio/sys_rules.h new file mode 100644 index 00000000..a3f0dffc --- /dev/null +++ b/src/gaudio/sys_rules.h @@ -0,0 +1,54 @@ +/* + * 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 + */ + +/** + * @file src/gaudio/sys_rules.h + * @brief GAUDIO safety rules header file. + * + * @addtogroup GAUDIO + * @{ + */ + +#ifndef _GAUDIO_RULES_H +#define _GAUDIO_RULES_H + +#if GFX_USE_GAUDIO + #if !GAUDIO_NEED_PLAY && !GAUDIO_NEED_RECORD + #error "GAUDIO: GAUDIO_NEED_PLAY and/or GAUDIO_NEED_RECORD is required if GFX_USE_GAUDIO is TRUE" + #endif + #if !GFX_USE_GQUEUE + #if GFX_DISPLAY_RULE_WARNINGS + #warning "GAUDIO: GFX_USE_GQUEUE is required if GFX_USE_GAUDIO is TRUE. It has been turned on for you." + #endif + #undef GFX_USE_GQUEUE + #define GFX_USE_GQUEUE TRUE + #endif + #if !GQUEUE_NEED_ASYNC + #if GFX_DISPLAY_RULE_WARNINGS + #warning "GAUDIO: GQUEUE_NEED_ASYNC is required if GFX_USE_GAUDIO is TRUE. It has been turned on for you." + #endif + #undef GQUEUE_NEED_ASYNC + #define GQUEUE_NEED_ASYNC TRUE + #endif + #if !GQUEUE_NEED_GSYNC + #if GFX_DISPLAY_RULE_WARNINGS + #warning "GAUDIO: GQUEUE_NEED_GSYNC is required if GFX_USE_GAUDIO is TRUE. It has been turned on for you." + #endif + #undef GQUEUE_NEED_GSYNC + #define GQUEUE_NEED_GSYNC TRUE + #endif + #if GFX_USE_GEVENT && !GFX_USE_GTIMER + #if GFX_DISPLAY_RULE_WARNINGS + #warning "GAUDIO: GFX_USE_GTIMER is required if GFX_USE_GAUDIO and GFX_USE_GEVENT are TRUE. It has been turned on for you." + #endif + #undef GFX_USE_GTIMER + #define GFX_USE_GTIMER TRUE + #endif +#endif + +#endif /* _GAUDIO_RULES_H */ +/** @} */ diff --git a/src/gaudout/driver.h b/src/gaudout/driver.h deleted file mode 100644 index bd00d06d..00000000 --- a/src/gaudout/driver.h +++ /dev/null @@ -1,134 +0,0 @@ -/* - * 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 - */ - -/** - * @file src/gaudout/driver.h - * @brief GAUDOUT - Audio Output driver header file. - * - * @defgroup Driver Driver - * @ingroup GAUDOUT - * @{ - */ - -#ifndef _GAUDOUT_LLD_H -#define _GAUDOUT_LLD_H - -#include "gfx.h" - -#if GFX_USE_GAUDOUT || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Type definitions */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Get a block of audio data to play - * @return A pointer to the GAaudioData structure or NULL if none is currently available - * - * @note Defined in the high level GAUDOUT code for use by the GAUDOUT drivers. - * - * @iclass - * @notapi - */ -GAudioData *gaudoutGetDataBlockI(void); - -/** - * @brief Release a block of audio data after playing - * - * @param[in] paud The GAudioData block to be released. - * - * @note Defined in the high level GAUDOUT code for use by the GAUDOUT drivers. - * - * @iclass - * @notapi - */ -void gaudoutReleaseDataBlockI(GAudioData *paud); - -/** - * @brief Signal that all playing has now stopped - * - * @note Defined in the high level GAUDOUT code for use by the GAUDOUT drivers. - * - * @iclass - * @notapi - */ -void gaudoutDoneI(void); - -/** - * @brief Initialise the driver - * @return TRUE if the channel and frequency are valid. - * - * @param[in] channel The channel to use (see the driver for the available channels provided) - * @param[in] frequency The sample frequency to use - * @param[in] format The sample format - * - * @note The driver will always have been stopped and de-init before this is called. - * - * @api - */ -bool_t gaudout_lld_init(uint16_t channel, uint32_t frequency, ArrayDataFormat format); - -/** - * @brief De-Initialise the driver - * - * @note The audio output will always have been stopped first by the high level layer. - * @note This may be called before a @p gaudout_lld_init() has occurred. - * - * @api - */ -void gaudout_lld_deinit(void); - -/** - * @brief Start the audio output playing - * - * @note This may be called at any stage including while the driver - * is already playing. The driver should check for data blocks - * to play using @p gaudoutGetDataBlockI(). - * - * @api - */ -void gaudout_lld_start(void); - -/** - * @brief Stop the audio output playing. - * - * @note Some drivers may only stop playing at a data block boundary. - * @note This may be called before a @p gaudout_lld_init() has occurred. - * - * @api - */ -void gaudout_lld_stop(void); - -/** - * @brief Set the output volume. - * @return TRUE if successful. - * - * @param[in] 0->255 (0 = muted) - * - * @note Some drivers may not support this. They will return FALSE. - * @note For stereo devices, both channels are set to the same volume. - * - * @api - */ -bool_t gaudout_lld_set_volume(uint8_t vol); - -#ifdef __cplusplus -} -#endif - -#endif /* GFX_USE_GAUDOUT */ - -#endif /* _GAUDOUT_LLD_H */ -/** @} */ diff --git a/src/gaudout/gaudout.c b/src/gaudout/gaudout.c deleted file mode 100644 index 00b01e91..00000000 --- a/src/gaudout/gaudout.c +++ /dev/null @@ -1,169 +0,0 @@ -/* - * 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 - */ - -/** - * @file src/gaudout/gaudout.c - * @brief GAUDOUT sub-system code. - * - * @addtogroup GAUDOUT - * @{ - */ -#include "gfx.h" - -#if GFX_USE_GAUDOUT || defined(__DOXYGEN__) - -#include "src/gaudout/driver.h" - -static gfxQueueASync playlist; -static gfxQueueGSync freelist; - -static uint16_t PlayFlags; - #define PLAYFLG_USEEVENTS 0x0001 - #define PLAYFLG_PLAYING 0x0002 - -#if GFX_USE_GEVENT - static GTimer PlayTimer; - - static void PlayTimerCallback(void *param) { - (void) param; - GSourceListener *psl; - GEventAudioOut *pe; - - psl = 0; - while ((psl = geventGetSourceListener((GSourceHandle)(&aud), psl))) { - if (!(pe = (GEventAudioOut *)geventGetEventBuffer(psl))) { - // This listener is missing - save this. - psl->srcflags |= GAUDOUT_LOSTEVENT; - continue; - } - - pe->type = GEVENT_AUDIO_OUT; - pe->flags = psl->srcflags; - psl->srcflags = 0; - if ((PlayFlags & PLAYFLG_PLAYING)) - pe->flags |= GAUDOUT_PLAYING; - if (!gfxQueueGSyncIsEmpty(&freelist)) - pe->flags |= GAUDOUT_FREEBLOCK; - geventSendEvent(psl); - } - } -#endif - - -void _gaudoutInit(void) -{ - gfxQueueASyncInit(&playlist); - gfxQueueGSyncInit(&freelist); - #if GFX_USE_GEVENT - gtimerInit(&PlayTimer); - #endif -} - -void _gaudoutDeinit(void) -{ - /* ToDo */ - #if GFX_USE_GEVENT - gtimerDeinit(&PlayTimer); - #endif -} - -bool_t gaudioAllocBuffers(unsigned num, size_t size) { - GAudioData *paud; - - if (num < 1) - return FALSE; - - // Round up to a multiple of 4 to prevent problems with structure alignment - size = (size + 3) & ~0x03; - - // Allocate the memory - if (!(paud = gfxAlloc((size+sizeof(GAudioData)) * num))) - return FALSE; - - // Add each of them to our free list - for(;num--; paud = (GAudioData *)((char *)(paud+1)+size)) { - paud->size = size; - gfxQueueGSyncPut(&freelist, (gfxQueueGSyncItem *)paud); - } - - return TRUE; -} - -void gaudioReleaseBuffer(GAudioData *paud) { - gfxQueueGSyncPut(&freelist, (gfxQueueGSyncItem *)paud); -} - -GAudioData *gaudioGetBuffer(delaytime_t ms) { - return (GAudioData *)gfxQueueGSyncGet(&freelist, ms); -} - -bool_t gaudioPlayInit(uint16_t channel, uint32_t frequency, ArrayDataFormat format) { - gaudioPlayStop(); - gaudout_lld_deinit(); - return gaudout_lld_init(channel, frequency, format); -} - -void gaudioPlay(GAudioData *paud) { - if (paud) - gfxQueueASyncPut(&playlist, (gfxQueueASyncItem *)paud); - PlayFlags |= PLAYFLG_PLAYING; - gaudout_lld_start(); -} - -void gaudioPlayPause(void) { - gaudout_lld_stop(); -} - -void gaudioPlayStop(void) { - GAudioData *paud; - - gaudout_lld_stop(); - while((paud = (GAudioData *)gfxQueueASyncGet(&playlist))) - gfxQueueGSyncPut(&freelist, (gfxQueueGSyncItem *)paud); - PlayFlags &= ~PLAYFLG_PLAYING; -} - -bool_t gaudioPlaySetVolume(uint8_t vol) { - return gaudout_lld_set_volume(vol); -} - -#if GFX_USE_GEVENT || defined(__DOXYGEN__) - GSourceHandle gaudioPlayGetSource(void) { - if (!gtimerIsActive(&PlayTimer)) - gtimerStart(&PlayTimer, PlayTimerCallback, 0, TRUE, TIME_INFINITE); - PlayFlags |= PLAYFLG_USEEVENTS; - return (GSourceHandle)&PlayFlags; - } -#endif - -/** - * Routines provided for use by drivers. - */ - -GAudioData *gaudoutGetDataBlockI(void) { - return (GAudioData *)gfxQueueASyncGetI(&playlist); -} - -void gaudoutReleaseDataBlockI(GAudioData *paud) { - gfxQueueGSyncPutI(&freelist, (gfxQueueGSyncItem *)paud); - #if GFX_USE_GEVENT - if (PlayFlags & PLAYFLG_USEEVENTS) - gtimerJabI(&PlayTimer); - #endif -} - -void gaudoutDoneI(void) { - PlayFlags &= ~PLAYFLG_PLAYING; - #if GFX_USE_GEVENT - if (PlayFlags & PLAYFLG_USEEVENTS) - gtimerJabI(&PlayTimer); - #endif -} - -#endif /* GFX_USE_GAUDOUT */ -/** @} */ - diff --git a/src/gaudout/sys_defs.h b/src/gaudout/sys_defs.h deleted file mode 100644 index 75cda243..00000000 --- a/src/gaudout/sys_defs.h +++ /dev/null @@ -1,217 +0,0 @@ -/* - * 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 - */ - -/** - * @file src/gaudout/sys_defs.h - * - * @addtogroup GAUDOUT - * - * @brief Module to output audio data (under development) - * - * @{ - */ - -#ifndef _GAUDOUT_H -#define _GAUDOUT_H - -#include "gfx.h" - -#if GFX_USE_GAUDOUT || defined(__DOXYGEN__) - -/* Include the driver defines */ -#include "gaudout_lld_config.h" - - -/*===========================================================================*/ -/* Type definitions */ -/*===========================================================================*/ - -/** - * @brief Contains Audio Data Samples - * @note This structure is followed immediately by the sample data itself. - * When allocating the buffers for the sample data put this structure - * at the beginning of the buffer. - */ -typedef struct GAudioData { - gfxQueueASyncItem next; // @< Used for queuing the buffers - size_t size; // @< The size of the buffer area following this structure (in bytes) - size_t len; // @< The length of the data in the buffer area (in bytes) -} GAudioData; - - -// Event types for GAUDOUT -#define GEVENT_AUDIO_OUT (GEVENT_GAUDOUT_FIRST+0) - -/** - * @brief The Audio output event structure. - * @{ - */ -typedef struct GEventAudioOut_t { - #if GFX_USE_GEVENT || defined(__DOXYGEN__) - /** - * @brief The type of this event (GEVENT_AUDIO_OUT) - */ - GEventType type; - #endif - /** - * @brief The event flags - */ - uint16_t flags; - /** - * @brief The event flag values. - * @{ - */ - #define GAUDOUT_LOSTEVENT 0x0001 /**< @brief The last GEVENT_AUDIO_OUT event was lost */ - #define GAUDOUT_PLAYING 0x0002 /**< @brief The audio out system is currently playing */ - #define GAUDOUT_FREEBLOCK 0x0004 /**< @brief An audio buffer has been freed */ - /** @} */ -} GEventAudioOut; -/** @} */ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Allocate some audio buffers and put them on the free list - * @return TRUE is it succeeded. FALSE on allocation failure. - * - * @param[in] num The number of buffers to allocate - * @param[in] size The size (in bytes) of each buffer - * - * @api - */ -bool_t gaudioAllocBuffers(unsigned num, size_t size); - -/** - * @brief Get an audio buffer from the free list - * @return A GAudioData pointer or NULL if the timeout is exceeded - * - * @params[in] ms The maximum amount of time in milliseconds to wait for a buffer if one is not available. - * - * @api - */ -GAudioData *gaudioGetBuffer(delaytime_t ms); - -/** - * @brief Release a buffer back to the free list - * - * @param[in] paud The buffer to put (back) on the free-list. - * - * @note This call should be used to return any buffers that were taken from - * the free-list once they have been finished with. It can also be used - * to put new buffers onto the free-list. Just make sure the "size" field - * of the GAudioData structure has been filled in first. - * - * @api - */ -void gaudioReleaseBuffer(GAudioData *paud); - -/** - * @brief Set the audio device to play on the specified channel and with the specified - * sample frequency. - * @return TRUE is successful, FALSE if the driver doesn't accept those parameters. - * - * @param[in] channel The audio output channel to use. - * @param[in] frequency The audio sample rate in samples per second - * @param[in] format The audio sample format - * - * @note Some channels are mono, and some are stereo. See your driver config file - * to determine which channels to use and whether they are stereo or not. - * @note Only one channel can be playing at a time. Calling this will stop any - * currently playing channel. - * - * @api - */ -bool_t gaudioPlayInit(uint16_t channel, uint32_t frequency, ArrayDataFormat format); - -/** - * @brief Play the specified sample data. - * @details The sample data is output to the audio channel. On completion the buffer is returned to the free-list. - * @pre @p gaudioPlayInit must have been called first to set the channel and sample frequency. - * - * @param[in] paud The audio sample buffer to play. It can be NULL (used to restart paused audio) - * - * @note Calling this will cancel any pause. - * @note Before calling this function the len field of the GAudioData structure must be - * specified (in bytes). - * @note For stereo channels the sample data is interleaved in the buffer. - * @note This call returns before the data has completed playing. Subject to available buffers (which - * can be obtained from the free-list), any number of buffers may be played. They will be queued - * for playing in the order they are supplied to this routine and played when previous buffers are - * complete. In this way continuous playing can be obtained without audio gaps. - * - * @api - */ -void gaudioPlay(GAudioData *paud); - -/** - * @brief Pause any currently playing sounds. - * - * @note If nothing is currently playing this routine does nothing. To restart playing call @p gaudioPlay() - * with or without a new sample buffer. - * @note Some drivers will not respond until a buffer boundary. - * - * @api - */ -void gaudioPlayPause(void); - -/** - * @brief Stop any currently playing sounds. - * - * @note This stops any playing sounds and returns any currently queued buffers back to the free-list. - * @note Some drivers will not respond until a buffer boundary. - * - * @api - */ -void gaudioPlayStop(void); - -/** - * @brief Set the output volume. - * @return TRUE if successful. - * - * @param[in] 0->255 (0 = muted) - * - * @note Some drivers may not support this. They will return FALSE. - * @note For stereo devices, both channels are set to the same volume. - * - * @api - */ -bool_t gaudioPlaySetVolume(uint8_t vol); - -#if GFX_USE_GEVENT || defined(__DOXYGEN__) - /** - * @brief Turn on sending results to the GEVENT sub-system. - * @details Returns a GSourceHandle to listen for GEVENT_AUDIO_OUT events. - * - * @note The audio output will not use the GEVENT system unless this is - * called first. This saves processing time if the application does - * not want to use the GEVENT sub-system for audio output. - * Once turned on it can only be turned off by calling @p gaudioPlayInit() again. - * @note The audio output is capable of signalling via this method and other methods - * at the same time. - * - * @return The GSourceHandle - * - * @api - */ - GSourceHandle gaudioPlayGetSource(void); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* GFX_USE_GAUDOUT */ - -#endif /* _GAUDOUT_H */ -/** @} */ - diff --git a/src/gaudout/sys_make.mk b/src/gaudout/sys_make.mk deleted file mode 100644 index 14f5bac3..00000000 --- a/src/gaudout/sys_make.mk +++ /dev/null @@ -1 +0,0 @@ -GFXSRC += $(GFXLIB)/src/gaudout/gaudout.c diff --git a/src/gaudout/sys_options.h b/src/gaudout/sys_options.h deleted file mode 100644 index 929bb42a..00000000 --- a/src/gaudout/sys_options.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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 - */ - -/** - * @file src/gaudout/sys_options.h - * @brief GAUDOUT - Audio Output subsystem options header file. - * - * @addtogroup GAUDOUT - * @{ - */ - -#ifndef _GAUDOUT_OPTIONS_H -#define _GAUDOUT_OPTIONS_H - -/** - * @name GAUDOUT Functionality to be included - * @{ - */ -/** - * @} - * - * @name GAUDOUT Optional Sizing Parameters - * @{ - */ -/** @} */ - -#endif /* _GAUDOUT_OPTIONS_H */ -/** @} */ diff --git a/src/gaudout/sys_rules.h b/src/gaudout/sys_rules.h deleted file mode 100644 index 8274e031..00000000 --- a/src/gaudout/sys_rules.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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 - */ - -/** - * @file src/gaudout/sys_rules.h - * @brief GAUDOUT safety rules header file. - * - * @addtogroup GAUDOUT - * @{ - */ - -#ifndef _GAUDOUT_RULES_H -#define _GAUDOUT_RULES_H - -#if GFX_USE_GAUDOUT - #if !GFX_USE_GQUEUE - #if GFX_DISPLAY_RULE_WARNINGS - #warning "GAUDOUT: GFX_USE_GQUEUE is required if GFX_USE_GAUDOUT is TRUE. It has been turned on for you." - #endif - #undef GFX_USE_GQUEUE - #define GFX_USE_GQUEUE TRUE - #endif - #if !GQUEUE_NEED_ASYNC - #if GFX_DISPLAY_RULE_WARNINGS - #warning "GAUDOUT: GQUEUE_NEED_ASYNC is required if GFX_USE_GAUDOUT is TRUE. It has been turned on for you." - #endif - #undef GQUEUE_NEED_ASYNC - #define GQUEUE_NEED_ASYNC TRUE - #endif - #if !GQUEUE_NEED_GSYNC - #if GFX_DISPLAY_RULE_WARNINGS - #warning "GAUDOUT: GQUEUE_NEED_GSYNC is required if GFX_USE_GAUDOUT is TRUE. It has been turned on for you." - #endif - #undef GQUEUE_NEED_GSYNC - #define GQUEUE_NEED_GSYNC TRUE - #endif -#endif - -#endif /* _GAUDOUT_RULES_H */ -/** @} */ diff --git a/src/gevent/sys_defs.h b/src/gevent/sys_defs.h index 0e656145..c50dc5ae 100644 --- a/src/gevent/sys_defs.h +++ b/src/gevent/sys_defs.h @@ -38,8 +38,7 @@ typedef uint16_t GEventType; #define GEVENT_GINPUT_FIRST 0x0100 // GINPUT events range from 0x0100 to 0x01FF #define GEVENT_GWIN_FIRST 0x0200 // GWIN events range from 0x0200 to 0x02FF #define GEVENT_GADC_FIRST 0x0300 // GADC events range from 0x0300 to 0x033F - #define GEVENT_GAUDIN_FIRST 0x0340 // GAUDIN events range from 0x0340 to 0x037F - #define GEVENT_GAUDOUT_FIRST 0x0380 // GAUDOUT events range from 0x0380 to 0x03BF + #define GEVENT_GAUDIO_FIRST 0x0340 // GAUDIO events range from 0x0340 to 0x037F #define GEVENT_USER_FIRST 0x8000 // Any application defined events start at 0x8000 // This object can be typecast to any GEventXxxxx type to allow any sub-system (or the application) to create events. diff --git a/src/gfx.c b/src/gfx.c index d01d3b1f..8e92fc29 100644 --- a/src/gfx.c +++ b/src/gfx.c @@ -44,13 +44,9 @@ extern void _gosDeinit(void); extern void _gadcInit(void); extern void _gadcDeinit(void); #endif -#if GFX_USE_GAUDIN - extern void _gaudinInit(void); - extern void _gaudinDeinit(void); -#endif -#if GFX_USE_GAUDOUT - extern void _gaudoutInit(void); - extern void _gaudoutDeinit(void); +#if GFX_USE_GAUDIO + extern void _gaudioInit(void); + extern void _gaudioDeinit(void); #endif #if GFX_USE_GMISC extern void _gmiscInit(void); @@ -88,11 +84,8 @@ void gfxInit(void) #if GFX_USE_GADC _gadcInit(); #endif - #if GFX_USE_GAUDIN - _gaudinInit(); - #endif - #if GFX_USE_GAUDOUT - _gaudoutInit(); + #if GFX_USE_GAUDIO + _gaudioInit(); #endif } @@ -103,11 +96,8 @@ void gfxDeinit(void) initDone = FALSE; // We deinitialise the opposite way as we initialised - #if GFX_USE_GAUDOUT - _gaudoutDeinit(); - #endif #if GFX_USE_GAUDIN - _gaudinDeinit(); + _gaudioDeinit(); #endif #if GFX_USE_GADC _gadcDeinit(); -- cgit v1.2.3