From 37966ff16d923bbca53c9464815cb49cbd7fc3be Mon Sep 17 00:00:00 2001 From: inmarket Date: Wed, 19 Feb 2014 00:36:52 +1000 Subject: Integrate the include files with each module. Simplifies structure of code. --- src/gadc/driver.h | 190 ++++++++++++++++++++++++++++++++++ src/gadc/gadc.c | 2 +- src/gadc/gadc.mk | 1 - src/gadc/sys_defs.h | 270 +++++++++++++++++++++++++++++++++++++++++++++++++ src/gadc/sys_make.mk | 1 + src/gadc/sys_options.h | 42 ++++++++ src/gadc/sys_rules.h | 30 ++++++ 7 files changed, 534 insertions(+), 2 deletions(-) create mode 100644 src/gadc/driver.h delete mode 100644 src/gadc/gadc.mk create mode 100644 src/gadc/sys_defs.h create mode 100644 src/gadc/sys_make.mk create mode 100644 src/gadc/sys_options.h create mode 100644 src/gadc/sys_rules.h (limited to 'src/gadc') diff --git a/src/gadc/driver.h b/src/gadc/driver.h new file mode 100644 index 00000000..4427f4f0 --- /dev/null +++ b/src/gadc/driver.h @@ -0,0 +1,190 @@ +/* + * 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/gadc/driver.h + * @brief GADC - Periodic ADC driver header file. + * + * @defgroup Driver Driver + * @ingroup GADC + * @{ + */ + +#ifndef _GADC_LLD_H +#define _GADC_LLD_H + +#include "gfx.h" + +#if GFX_USE_GADC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Type definitions */ +/*===========================================================================*/ + +/** + * @brief The structure passed to start a timer conversion + * @note We use the structure instead of parameters purely to save + * interrupt stack space which is very limited in some platforms. + * @{ + */ +typedef struct GadcLldTimerData_t { + uint32_t physdev; /* @< A value passed to describe which physical ADC devices/channels to use. */ + adcsample_t *buffer; /* @< The static buffer to put the ADC samples into. */ + size_t count; /* @< The number of conversions to do before doing a callback and stopping the ADC. */ + bool_t now; /* @< Trigger the first conversion now rather than waiting for the first timer interrupt (if possible) */ + } GadcLldTimerData; +/* @} */ + +/** + * @brief The structure passed to start a non-timer conversion + * @note We use the structure instead of parameters purely to save + * interrupt stack space which is very limited in some platforms. + * @{ + */ +typedef struct GadcLldNonTimerData_t { + uint32_t physdev; /* @< A value passed to describe which physical ADC devices/channels to use. */ + adcsample_t *buffer; /* @< The static buffer to put the ADC samples into. */ + } GadcLldNonTimerData; +/* @} */ + +/** + * @brief These routines are the callbacks that the driver uses. + * @details Defined in the high level GADC code. + * + * @notapi + * @{ + */ + +/** + * @param[in] adcp The ADC driver + * @param[in] buffer The sample buffer + * @param[in] n The amount of samples + */ +extern void GADC_ISR_CompleteI(ADCDriver *adcp, adcsample_t *buffer, size_t n); + +/** + * @param[in] adcp The ADC driver + * @param[in] err ADC error + */ +extern void GADC_ISR_ErrorI(ADCDriver *adcp, adcerror_t err); +/** + * @} + */ + +/** + * @brief This can be incremented by the low level driver if a timer interrupt is missed. + * @details Defined in the high level GADC code. + * + * @notapi + */ +extern volatile bool_t GADC_Timer_Missed; + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Initialise the driver + * + * @api + */ +void gadc_lld_init(void); + +/** + * @brief Get the number of samples in a conversion. + * @details Calculates and returns the number of samples per conversion for the specified physdev. + * + * @note A physdev describing a mono device would return 1, a stereo device would return 2. + * For most ADC's physdev is a bitmap so it is only a matter of counting the bits. + * + * @param[in] physdev A value passed to describe which physical ADC devices/channels to use. + * + * @return Number of samples of the convesion + * @api + */ +size_t gadc_lld_samples_per_conversion(uint32_t physdev); + +/** + * @brief Start a periodic timer for high frequency conversions. + * + * @param[in] physdev A value passed to describe which physical ADC devices/channels to use. + * @param[in] frequency The frequency to create ADC conversions + * + * @note The exact meaning of physdev is hardware dependent. It describes the channels + * the will be used later on when a "timer" conversion is actually scheduled. + * @note It is assumed that the timer is capable of free-running even when the ADC + * is stopped or doing something else. + * @details When a timer interrupt occurs a conversion should start if these is a "timer" conversion + * active. + * @note If the ADC is stopped, doesn't have a "timer" conversion active or is currently executing + * a non-timer conversion then the interrupt can be ignored other than (optionally) incrementing + * the GADC_Timer_Missed variable. + * + * @api + */ +void gadc_lld_start_timer(uint32_t physdev, uint32_t frequency); + +/** + * @brief Stop the periodic timer for high frequency conversions. + * @details Also stops any current "timer" conversion (but not a current "non-timer" conversion). + * + * @param[in] physdev A value passed to describe which physical ADC devices/channels in use. + * + * @note The exact meaning of physdev is hardware dependent. + * + * @api + */ +void gadc_lld_stop_timer(uint32_t physdev); + +/** + * @brief Start a "timer" conversion. + * @details Starts a series of conversions triggered by the timer. + * + * @param[in] pgtd Contains the parameters for the timer conversion. + * + * @note The exact meaning of physdev is hardware dependent. It is likely described in the + * drivers gadc_lld_config.h + * @note Some versions of ChibiOS actually call the callback function more than once, once + * at the half-way point and once on completion. The high level code handles this. + * @note The driver should call @p GADC_ISR_CompleteI() when it completes the operation + * (or at the half-way point), or @p GAD_ISR_ErrorI() on an error. + * @note The high level code ensures that this is not called while a non-timer conversion is in + * progress + * + * @iclass + */ +void gadc_lld_adc_timerI(GadcLldTimerData *pgtd); + +/** + * @brief Start a "non-timer" conversion. + * @details Starts a single conversion now. + * + * @param[in] pgntd Contains the parameters for the non-timer conversion. + * + * @note The exact meaning of physdev is hardware dependent. It is likely described in the + * drivers gadc_lld_config.h + * @note The driver should call @p GADC_ISR_CompleteI() when it completes the operation + * or @p GAD_ISR_ErrorI() on an error. + * @note The high level code ensures that this is not called while a timer conversion is in + * progress + * + * @iclass + */ +void gadc_lld_adc_nontimerI(GadcLldNonTimerData *pgntd); + +#ifdef __cplusplus +} +#endif + +#endif /* GFX_USE_GADC */ + +#endif /* _GADC_LLD_H */ +/** @} */ diff --git a/src/gadc/gadc.c b/src/gadc/gadc.c index c9a4a31b..8ae431b0 100644 --- a/src/gadc/gadc.c +++ b/src/gadc/gadc.c @@ -17,7 +17,7 @@ #if GFX_USE_GADC /* Include the driver defines */ -#include "gadc/lld/gadc_lld.h" +#include "src/gadc/driver.h" #if GADC_MAX_HIGH_SPEED_SAMPLERATE > GADC_MAX_SAMPLE_FREQUENCY/2 #error "GADC: GADC_MAX_HIGH_SPEED_SAMPLERATE has been set too high. It must be less than half the maximum CPU rate" diff --git a/src/gadc/gadc.mk b/src/gadc/gadc.mk deleted file mode 100644 index cfe04177..00000000 --- a/src/gadc/gadc.mk +++ /dev/null @@ -1 +0,0 @@ -GFXSRC += $(GFXLIB)/src/gadc/gadc.c diff --git a/src/gadc/sys_defs.h b/src/gadc/sys_defs.h new file mode 100644 index 00000000..f6349dfe --- /dev/null +++ b/src/gadc/sys_defs.h @@ -0,0 +1,270 @@ +/* + * 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/gadc/sys_defs.h + * + * @addtogroup GADC + * + * @brief Module to abstract the very variable ADC interfaces of the underlying systems + * + * @details The reason why ChibiOS/GFX has it's own ADC abstraction is because + * the Chibi-OS drivers are very CPU specific and do not + * provide a way across all hardware platforms to create periodic + * ADC conversions. There are also issues with devices with different + * characteristics or periodic requirements on the same ADC + * device (but different channels). This layer attempts to solve these + * problems to provide a architecture neutral API. It also provides extra + * features such as multi-buffer chaining for high speed ADC sources. + * It provides one high speed virtual ADC device (eg a microphone) and + * numerous low speed (less than 100Hz) virtual ADC devices (eg dials, + * temperature sensors etc). The high speed device has timer based polling + * to ensure exact conversion periods and a buffer management system. + * The low speed devices are assumed to be non-critical timing devices + * and do not have any buffer management. + * Note that while only one high speed device has been provided it can + * be used to read multiple physical ADC channels on the one physical + * ADC device. + * All callback routines are thread based unlike the Chibi-OS interrupt based + * routines. + * + * @{ + */ + +#ifndef _GADC_H +#define _GADC_H + +#include "gfx.h" + +#if GFX_USE_GADC || defined(__DOXYGEN__) + +/* Include the driver defines */ +#include "gadc_lld_config.h" + +/*===========================================================================*/ +/* Type definitions */ +/*===========================================================================*/ + +// Event types for GADC +#define GEVENT_ADC (GEVENT_GADC_FIRST+0) + +/** + * @brief The High Speed ADC event structure. + * @{ + */ +typedef struct GEventADC_t { + #if GFX_USE_GEVENT || defined(__DOXYGEN__) + /** + * @brief The type of this event (GEVENT_ADC) + */ + GEventType type; + #endif + + /** + * @brief The event flags + */ + uint16_t flags; + /** + * @brief The event flag values. + * @{ + */ + #define GADC_HSADC_LOSTEVENT 0x0001 /**< @brief The last GEVENT_HSDADC event was lost */ + /** @} */ + /** + * @brief The number of conversions in the buffer + */ + size_t count; + /** + * @brief The buffer containing the conversion samples + */ + adcsample_t *buffer; +} GEventADC; +/** @} */ + +/** + * @brief A callback function (executed in a thread context) for a low speed conversion + */ +typedef void (*GADCCallbackFunction)(adcsample_t *buffer, void *param); + +/** + * @brief A callback function (executed in an ISR context) for a high speed conversion + */ +typedef void (*GADCISRCallbackFunction)(adcsample_t *buffer, size_t size); + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Initialise the high speed ADC. + * @details Initialises but does not start the conversions. + * + * @param[in] physdev A value passed to describe which physical ADC devices/channels to use. + * @param[in] frequency The frequency to create ADC conversions + * @param[in] buffer The static buffer to put the ADC 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 If the high speed ADC is running it will be stopped. The Event subsystem is + * disconnected from the high speed ADC and any binary semaphore event is forgotten. + * @note bufcount must be greater than countPerEvent (usually 2 or more times) otherwise + * the buffer will be overwritten with new data while the application is still trying + * to process the old data. + * @note Due to a bug/feature in Chibi-OS countPerEvent must be even. If bufcount is not + * evenly divisable by countPerEvent, the remainder must also be even. + * @note The physdev parameter may be used to turn on more than one ADC channel. + * Each channel is then interleaved into the provided buffer. Note 'bufcount' + * and 'countPerEvent' parameters describe the number of conversions not the + * number of samples. + * As an example, if physdev turns on 2 devices then the buffer contains + * alternate device samples and the buffer must contain 2 * bufcount samples. + * The exact meaning of physdev is hardware dependent. + * @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. + * @note While the high speed ADC is running, low speed conversions can only occur at + * the frequency of the high speed events. Thus if high speed events are + * being created at 50Hz (eg countPerEvent = 100, frequency = 5kHz) then the maximum + * frequency for low speed conversions will be 50Hz. + * + * @api + */ +void gadcHighSpeedInit(uint32_t physdev, uint32_t frequency, adcsample_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_ADC events. + * + * @note The high speed ADC 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 the high speed ADC. + * Once turned on it can only be turned off by calling @p gadcHighSpeedInit() again. + * @note The high speed ADC is capable of signalling via this method, an ISR callback and a + * binary semaphore at the same time. + * + * @return The GSourceHandle + * + * @api + */ + GSourceHandle gadcHighSpeedGetSource(void); +#endif + +/** + * @brief Allow retrieving of results from the high speed ADC using an ISR callback. + * + * @param[in] isrfn The callback function (called in an ISR context). + * + * @note Passing a NULL for isrfn will turn off signalling via this method as will calling + * @p gadcHighSpeedInit(). + * @note The high speed ADC is capable of signalling via this method, a binary semaphore and the GEVENT + * sub-system at the same time. + * + * @api + */ +void gadcHighSpeedSetISRCallback(GADCISRCallbackFunction isrfn); + +/** + * @brief Allow retrieving of results from the high speed ADC 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 as will calling + * @p gadcHighSpeedInit(). + * @note The high speed ADC is capable of signalling via this method, an ISR callback and the GEVENT + * sub-system at the same time. + * + * @api + */ +void gadcHighSpeedSetBSem(gfxSem *pbsem, GEventADC *pEvent); + +/** + * @brief Start the high speed ADC conversions. + * @pre It must have been initialised first with @p gadcHighSpeedInit() + * + * @api + */ +void gadcHighSpeedStart(void); + +/** + * @brief Stop the high speed ADC conversions. + * + * @api + */ +void gadcHighSpeedStop(void); + +/** + * @brief Perform a single low speed ADC conversion + * @details Blocks until the conversion is complete + * @pre This should not be called from within a GTimer callback as this routine + * blocks until the conversion is ready. + * + * @param[in] physdev A value passed to describe which physical ADC devices/channels to use. + * @param[in] buffer The static buffer to put the ADC samples into. + * + * @note This may take a while to complete if the high speed ADC is running as the + * conversion is interleaved with the high speed ADC conversions on a buffer + * completion. + * @note The result buffer must be large enough to store one sample per device + * described by the 'physdev' parameter. + * @note If calling this routine would exceed @p GADC_MAX_LOWSPEED_DEVICES simultaneous low + * speed devices, the routine will wait for an available slot to complete the + * conversion. + * @note Specifying more than one device in physdev is possible but discouraged as the + * calculations to ensure the high speed ADC correctness will be incorrect. Symptoms + * from over-running the high speed ADC include high speed samples being lost. + * + * @api + */ +void gadcLowSpeedGet(uint32_t physdev, adcsample_t *buffer); + +/** + * @brief Perform a low speed ADC conversion with callback (in a thread context) + * @details Returns FALSE if there are no free low speed ADC slots. See @p GADC_MAX_LOWSPEED_DEVICES for details. + * + * @param[in] physdev A value passed to describe which physical ADC devices/channels to use. + * @param[in] buffer The static buffer to put the ADC samples into. + * @param[in] fn The callback function to call when the conversion is complete. + * @param[in] param A parameter to pass to the callback function. + * + * @return FALSE if no free low speed ADC slots. + * + * @note This may be safely called from within a GTimer callback. + * @note The callback may take a while to occur if the high speed ADC is running as the + * conversion is interleaved with the high speed ADC conversions on a buffer + * completion. + * @note The result buffer must be large enough to store one sample per device + * described by the 'physdev' parameter. + * @note As this routine uses a low speed ADC, it asserts if you try to run more than @p GADC_MAX_LOWSPEED_DEVICES + * at the same time. + * @note Specifying more than one device in physdev is possible but discouraged as the + * calculations to ensure the high speed ADC correctness will be incorrect. Symptoms + * from over-running the high speed ADC include high speed samples being lost. + * + * @api + */ +bool_t gadcLowSpeedStart(uint32_t physdev, adcsample_t *buffer, GADCCallbackFunction fn, void *param); + +#ifdef __cplusplus +} +#endif + +#endif /* GFX_USE_GADC */ + +#endif /* _GADC_H */ +/** @} */ + diff --git a/src/gadc/sys_make.mk b/src/gadc/sys_make.mk new file mode 100644 index 00000000..05b1e9cc --- /dev/null +++ b/src/gadc/sys_make.mk @@ -0,0 +1 @@ +GFXSRC += $(GFXLIB)/src/gadc/gadc.c diff --git a/src/gadc/sys_options.h b/src/gadc/sys_options.h new file mode 100644 index 00000000..d9519c39 --- /dev/null +++ b/src/gadc/sys_options.h @@ -0,0 +1,42 @@ +/* + * 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/gadc/sys_options.h + * @brief GADC - Periodic ADC subsystem options header file. + * + * @addtogroup GADC + * @{ + */ + +#ifndef _GADC_OPTIONS_H +#define _GADC_OPTIONS_H + +/** + * @name GADC Functionality to be included + * @{ + */ +/** + * @} + * + * @name GADC Optional Sizing Parameters + * @{ + */ + /** + * @brief The maximum GADC sample rate + * @details Defaults to 44000 + * @note This value must be less than half the maximum sample rate allowed by the CPU. + * This is to ensure there is time between high speed samples to perform low + * speed device sampling. + */ + #ifndef GADC_MAX_HIGH_SPEED_SAMPLERATE + #define GADC_MAX_HIGH_SPEED_SAMPLERATE 44000 + #endif +/** @} */ + +#endif /* _GADC_OPTIONS_H */ +/** @} */ diff --git a/src/gadc/sys_rules.h b/src/gadc/sys_rules.h new file mode 100644 index 00000000..7272337e --- /dev/null +++ b/src/gadc/sys_rules.h @@ -0,0 +1,30 @@ +/* + * 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/gadc/sys_rules.h + * @brief GADC safety rules header file. + * + * @addtogroup GADC + * @{ + */ + +#ifndef _GADC_RULES_H +#define _GADC_RULES_H + +#if GFX_USE_GADC + #if !GFX_USE_GTIMER + #if GFX_DISPLAY_RULE_WARNINGS + #warning "GADC: GFX_USE_GTIMER is required if GFX_USE_GADC is TRUE. It has been turned on for you." + #endif + #undef GFX_USE_GTIMER + #define GFX_USE_GTIMER TRUE + #endif +#endif + +#endif /* _GADC_RULES_H */ +/** @} */ -- cgit v1.2.3