diff options
| -rw-r--r-- | boards/base/Olimex-SAM7EX256-GE8/gaudio_record_board.h | 7 | ||||
| -rw-r--r-- | demos/modules/gadc/gfxconf.h | 1 | ||||
| -rw-r--r-- | demos/modules/gadc/gwinosc.c | 34 | ||||
| -rw-r--r-- | demos/modules/gadc/gwinosc.h | 3 | ||||
| -rw-r--r-- | demos/modules/gadc/main.c | 5 | ||||
| -rw-r--r-- | drivers/gadc/AT91SAM7/gadc_lld.c | 72 | ||||
| -rw-r--r-- | drivers/gadc/AT91SAM7/gadc_lld_config.h | 7 | ||||
| -rw-r--r-- | drivers/gaudio/gadc/gaudio_record_board_template.h | 8 | ||||
| -rw-r--r-- | drivers/gaudio/gadc/gaudio_record_config.h | 18 | ||||
| -rw-r--r-- | drivers/gaudio/gadc/gaudio_record_lld.c | 34 | ||||
| -rw-r--r-- | src/gadc/driver.h | 93 | ||||
| -rw-r--r-- | src/gadc/gadc.c | 218 | ||||
| -rw-r--r-- | src/gadc/sys_defs.h | 70 | ||||
| -rw-r--r-- | src/gadc/sys_rules.h | 11 | 
14 files changed, 278 insertions, 303 deletions
| diff --git a/boards/base/Olimex-SAM7EX256-GE8/gaudio_record_board.h b/boards/base/Olimex-SAM7EX256-GE8/gaudio_record_board.h index cdea5e06..68063881 100644 --- a/boards/base/Olimex-SAM7EX256-GE8/gaudio_record_board.h +++ b/boards/base/Olimex-SAM7EX256-GE8/gaudio_record_board.h @@ -20,12 +20,17 @@  #define GAUDIO_RECORD_NUM_CHANNELS					1  /** + * @brief	Whether each channel is mono or stereo + */ +#define GAUDIO_RECORD_CHANNEL0_IS_STEREO			FALSE + +/**   * The list of audio channels and their uses   */  #define	GAUDIO_RECORD_MICROPHONE					0  #ifdef GAUDIO_RECORD_IMPLEMENTATION -	static uint32_t gaudin_lld_physdevs[GAUDIO_RECORD_NUM_CHANNELS] = { +	static uint32_t gaudio_gadc_physdevs[GAUDIO_RECORD_NUM_CHANNELS] = {  			GADC_PHYSDEV_MICROPHONE,  			};  #endif diff --git a/demos/modules/gadc/gfxconf.h b/demos/modules/gadc/gfxconf.h index 297265b5..d0da3943 100644 --- a/demos/modules/gadc/gfxconf.h +++ b/demos/modules/gadc/gfxconf.h @@ -51,7 +51,6 @@  #define GDISP_NEED_VALIDATION	TRUE  #define GDISP_NEED_CLIP			TRUE  #define GDISP_NEED_TEXT			TRUE -#define GDISP_NEED_CONTROL		TRUE  #define GDISP_NEED_MULTITHREAD	TRUE  /* GDISP - builtin fonts */ diff --git a/demos/modules/gadc/gwinosc.c b/demos/modules/gadc/gwinosc.c index afa12bfc..84e7d645 100644 --- a/demos/modules/gadc/gwinosc.c +++ b/demos/modules/gadc/gwinosc.c @@ -38,9 +38,6 @@  /* Include internal GWIN routines so we can build our own superset class */  #include "src/gwin/class_gwin.h" -/* The size of our dynamically allocated audio buffer */ -#define AUDIOBUFSZ				64*2 -  /* How many flat-line sample before we trigger */  #define FLATLINE_SAMPLES		8 @@ -50,10 +47,6 @@ static void _destroy(GHandle gh) {  		gfxFree(((GScopeObject *)gh)->lastscopetrace);  		((GScopeObject *)gh)->lastscopetrace = 0;  	} -	if (((GScopeObject *)gh)->audiobuf) { -		gfxFree(((GScopeObject *)gh)->audiobuf); -		((GScopeObject *)gh)->audiobuf = 0; -	}  }  static const gwinVMT scopeVMT = { @@ -68,12 +61,9 @@ GHandle gwinGScopeCreate(GDisplay *g, GScopeObject *gs, GWindowInit *pInit, uint  	/* Initialise the base class GWIN */  	if (!(gs = (GScopeObject *)_gwindowCreate(g, &gs->g, pInit, &scopeVMT, 0)))  		return 0; -	gfxSemInit(&gs->bsem, 0, 1);  	gs->nextx = 0;  	if (!(gs->lastscopetrace = gfxAlloc(gs->g.width * sizeof(coord_t))))  		return 0; -	if (!(gs->audiobuf = gfxAlloc(AUDIOBUFSZ * sizeof(adcsample_t)))) -		return 0;  #if TRIGGER_METHOD == TRIGGER_POSITIVERAMP  	gs->lasty = gs->g.height/2;  #elif TRIGGER_METHOD == TRIGGER_MINVALUE @@ -82,8 +72,7 @@ GHandle gwinGScopeCreate(GDisplay *g, GScopeObject *gs, GWindowInit *pInit, uint  #endif  	/* Start the GADC high speed converter */ -	gadcHighSpeedInit(physdev, frequency, gs->audiobuf, AUDIOBUFSZ, AUDIOBUFSZ/2); -	gadcHighSpeedSetBSem(&gs->bsem, &gs->myEvent); +	gadcHighSpeedInit(physdev, frequency);  	gadcHighSpeedStart();  	gwinSetVisible((GHandle)gs, pInit->show); @@ -97,6 +86,8 @@ void gwinScopeWaitForTrace(GHandle gh) {  	coord_t			yoffset;  	adcsample_t		*pa;  	coord_t			*pc; +	GDataBuffer		*pd; +	uint8_t			shr;  #if TRIGGER_METHOD == TRIGGER_POSITIVERAMP  	bool_t			rdytrigger;  	int				flsamples; @@ -109,20 +100,21 @@ void gwinScopeWaitForTrace(GHandle gh) {  	if (gh->vmt != &scopeVMT)  		return; -	/* Wait for a set of audio conversions */ -	gfxSemWait(&gs->bsem, TIME_INFINITE); +	/* Wait for a set of conversions */ +	pd = gadcHighSpeedGetData(TIME_INFINITE);  	/* Ensure we are drawing in the right area */  	#if GDISP_NEED_CLIP  		gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);  	#endif +	shr = 16 - gfxSampleFormatBits(GADC_SAMPLE_FORMAT);  	yoffset = gh->height/2; -	if (!(GADC_SAMPLE_FORMAT & 1)) +	if (!gfxSampleFormatIsSigned(GADC_SAMPLE_FORMAT))  		yoffset += (1<<SCOPE_Y_BITS)/2;  	x = gs->nextx;  	pc = gs->lastscopetrace+x; -	pa = gs->myEvent.buffer; +	pa = (adcsample_t *)(pd+1);  #if TRIGGER_METHOD == TRIGGER_POSITIVERAMP  	rdytrigger = FALSE;  	flsamples = 0; @@ -132,14 +124,10 @@ void gwinScopeWaitForTrace(GHandle gh) {  	scopemin = 0;  #endif -	for(i = gs->myEvent.count; i; i--) { +	for(i = pd->len/sizeof(adcsample_t); i; i--) {  		/* Calculate the new scope value - re-scale using simple shifts for efficiency, re-center and y-invert */ -		#if GADC_BITS_PER_SAMPLE > SCOPE_Y_BITS -			y = yoffset - (*pa++ >> (GADC_BITS_PER_SAMPLE - SCOPE_Y_BITS)); -		#else -			y = yoffset - (*pa++ << (SCOPE_Y_BITS - GADC_BITS_PER_SAMPLE)); -		#endif +		y = yoffset - (((coord_t)(*pa++) << shr) >> (16-SCOPE_Y_BITS));  #if TRIGGER_METHOD == TRIGGER_MINVALUE  		/* Calculate the scopemin ready for the next trace */ @@ -205,5 +193,7 @@ void gwinScopeWaitForTrace(GHandle gh) {  	gs->scopemin = scopemin;  #endif +	gfxBufferRelease(pd); +  	#undef gs  } diff --git a/demos/modules/gadc/gwinosc.h b/demos/modules/gadc/gwinosc.h index 56de0f11..8f5c1be3 100644 --- a/demos/modules/gadc/gwinosc.h +++ b/demos/modules/gadc/gwinosc.h @@ -64,9 +64,6 @@ typedef struct GScopeObject_t {  	GWindowObject		g;						// Base Class  	coord_t				*lastscopetrace;		// To store last scope trace -	gfxSem				bsem;					// We get signalled on this -	adcsample_t			*audiobuf;				// To store audio samples -	GEventADC			myEvent;				// Information on received samples  	coord_t				nextx;					// Where we are up to  #if TRIGGER_METHOD == TRIGGER_POSITIVERAMP  	coord_t				lasty;					// The last y value - used for trigger slope detection diff --git a/demos/modules/gadc/main.c b/demos/modules/gadc/main.c index 928635fa..8e5ecaa4 100644 --- a/demos/modules/gadc/main.c +++ b/demos/modules/gadc/main.c @@ -167,6 +167,11 @@ int main(void) {  		gtimerStart(&lsTimer, LowSpeedTimer, ghText, TRUE, MY_LS_DELAY);  	#endif +	// Allocate buffers for the high speed GADC device - 4 x 128 byte buffers. +	//	You may need to increase this for slower cpu's. +	//	You may be able to decrease this for low latency operating systems. +	gfxBufferAlloc(4, 128); +  	/* Set up the scope window in the top right on the screen */  	{  		GWindowInit	wi; diff --git a/drivers/gadc/AT91SAM7/gadc_lld.c b/drivers/gadc/AT91SAM7/gadc_lld.c index f18f2717..52b06539 100644 --- a/drivers/gadc/AT91SAM7/gadc_lld.c +++ b/drivers/gadc/AT91SAM7/gadc_lld.c @@ -8,10 +8,6 @@  /**   * @file    drivers/gadc/AT91SAM7/gadc_lld.c   * @brief   GADC - Periodic ADC driver source file for the AT91SAM7 cpu. - * - * @defgroup Driver Driver - * @ingroup GADC - * @{   */  #include "gfx.h" @@ -20,44 +16,76 @@  #include "src/gadc/driver.h" +static GDataBuffer	*pData; +static size_t		bytesperconversion; + +static void ISR_CompleteI(ADCDriver *adcp, adcsample_t *buffer, size_t n); +static void ISR_ErrorI(ADCDriver *adcp, adcerror_t err); + +  static ADCConversionGroup acg = {  		FALSE,					// circular  		1,						// num_channels -		GADC_ISR_CompleteI,		// end_cb -		GADC_ISR_ErrorI,		// error_cb +		ISR_CompleteI,			// end_cb +		ISR_ErrorI,				// error_cb  		0,						// channelselects  		0,						// trigger  		0,						// frequency  		}; +static void ISR_CompleteI(ADCDriver *adcp, adcsample_t *buffer, size_t n) { +	(void)	adcp; +	(void)	buffer; + +	if (pData) { +		// A set of timer base conversions is complete +		pData->len += n * bytesperconversion; + +		// Are we finished yet? +		// In ChibiOS we (may) get a half-buffer complete. In this situation the conversions +		//	are really not complete and so we just wait for the next lot of data. +		if (pData->len + bytesperconversion > pData->size) +			gadcDataReadyI(); + +	} else { +		// A single non-timer conversion is complete +		gadcDataReadyI(); +	} +} + +static void ISR_ErrorI(ADCDriver *adcp, adcerror_t err) { +	(void)	adcp; +	(void)	err; + +	gadcDataFailI(); +} +  void gadc_lld_init(void) {  	adcStart(&ADCD1, 0);  } -size_t gadc_lld_samples_per_conversion(uint32_t physdev) { -	size_t	cnt; -	int		i; +void gadc_lld_start_timer(GadcLldTimerData *pgtd) { +	int			phys; +	/* Calculate the bytes per conversion from physdev */  	/* The AT91SAM7 has AD0..7 - physdev is a bitmap of those channels */ -	for(cnt = 0, i = 0; i < 8; i++, physdev >>= 1) -		if (physdev & 0x01) -			cnt++; -	return cnt; -} +	phys = pgtd->physdev; +	for(bytesperconversion = 0; phys; phys >>= 1) +		if (phys & 0x01) +			bytesperconversion++; +	bytesperconversion *= (gfxSampleFormatBits(GADC_SAMPLE_FORMAT)+7)/8; -void gadc_lld_start_timer(uint32_t physdev, uint32_t frequency) { -	(void) physdev;  	/**  	 * The AT91SAM7 ADC driver supports triggering the ADC using a timer without having to implement  	 * an interrupt handler for the timer. The driver also initialises the timer correctly for us.  	 * Because we aren't trapping the interrupt ourselves we can't increment GADC_Timer_Missed if an  	 * interrupt is missed.  	 */ -	acg.frequency = frequency; +	acg.frequency = pgtd->frequency;  } -void gadc_lld_stop_timer(uint32_t physdev) { -	(void) physdev; +void gadc_lld_stop_timer(GadcLldTimerData *pgtd) { +	(void) pgtd;  	if ((acg.trigger & ~ADC_TRIGGER_SOFTWARE) == ADC_TRIGGER_TIMER)  		adcStop(&ADCD1);  } @@ -69,7 +97,8 @@ void gadc_lld_adc_timerI(GadcLldTimerData *pgtd) {  	acg.channelselects = pgtd->physdev;  	acg.trigger = pgtd->now ? (ADC_TRIGGER_TIMER|ADC_TRIGGER_SOFTWARE) : ADC_TRIGGER_TIMER; -	adcStartConversionI(&ADCD1, &acg, pgtd->buffer, pgtd->count); +	pData = pgtd->pdata; +	adcStartConversionI(&ADCD1, &acg, (adcsample_t *)(pgtd->pdata+1), pData->size/bytesperconversion);  	/* Next time assume the same (still running) timer */  	acg.frequency = 0; @@ -81,8 +110,9 @@ void gadc_lld_adc_nontimerI(GadcLldNonTimerData *pgntd) {  	 */  	acg.channelselects = pgntd->physdev;  	acg.trigger = ADC_TRIGGER_SOFTWARE; + +	pData = 0;  	adcStartConversionI(&ADCD1, &acg, pgntd->buffer, 1);  }  #endif /* GFX_USE_GADC */ -/** @} */ diff --git a/drivers/gadc/AT91SAM7/gadc_lld_config.h b/drivers/gadc/AT91SAM7/gadc_lld_config.h index ba6cbda2..de5af3d3 100644 --- a/drivers/gadc/AT91SAM7/gadc_lld_config.h +++ b/drivers/gadc/AT91SAM7/gadc_lld_config.h @@ -35,7 +35,7 @@   * @note	For the AT91SAM7 ADC driver, it post-dates the finding of the bug so we safely   * 			say that the bug doesn't exist for this driver.   */ -#define ADC_ISR_FULL_CODE_BUG				FALSE +#define CHIBIOS_ADC_ISR_FULL_CODE_BUG		FALSE  /**   * @brief	The maximum sample frequency supported by this CPU @@ -43,11 +43,6 @@  #define GADC_MAX_SAMPLE_FREQUENCY			132000  /** - * @brief	The number of bits in a sample - */ -#define GADC_BITS_PER_SAMPLE				AT91_ADC1_RESOLUTION - -/**   * @brief	The sample format   */  #define GADC_SAMPLE_FORMAT					ARRAY_DATA_10BITUNSIGNED diff --git a/drivers/gaudio/gadc/gaudio_record_board_template.h b/drivers/gaudio/gadc/gaudio_record_board_template.h index 26e87d88..59168be1 100644 --- a/drivers/gaudio/gadc/gaudio_record_board_template.h +++ b/drivers/gaudio/gadc/gaudio_record_board_template.h @@ -27,6 +27,12 @@  #define GAUDIO_RECORD_NUM_CHANNELS					1  /** + * @brief	Whether each channel is mono or stereo + * @note	This is an example + */ +#define GAUDIO_RECORD_CHANNEL0_IS_STEREO			FALSE + +/**   * @brief	The list of audio channels and their uses   * @note	This is an example   * @{ @@ -40,7 +46,7 @@   * @{   */  #ifdef GAUDIO_RECORD_LLD_IMPLEMENTATION -	static uint32_t gaudin_lld_physdevs[GAUDIO_RECORD_NUM_CHANNELS] = { +	static uint32_t gaudio_gadc_physdevs[GAUDIO_RECORD_NUM_CHANNELS] = {  			GADC_PHYSDEV_MICROPHONE,  			};  #endif diff --git a/drivers/gaudio/gadc/gaudio_record_config.h b/drivers/gaudio/gadc/gaudio_record_config.h index 22d8750f..88092a63 100644 --- a/drivers/gaudio/gadc/gaudio_record_config.h +++ b/drivers/gaudio/gadc/gaudio_record_config.h @@ -23,28 +23,20 @@  /*===========================================================================*/  /** - * @brief	The audio record sample type - * @details	For this driver it matches the cpu sample type - */ -typedef adcsample_t		audio_record_sample_t; - -/**   * @brief	The maximum sample frequency supported by this audio device   * @details	For this driver it matches the GADC maximum high speed sample rate   */ -#define GAUDIO_RECORD_MAX_SAMPLE_FREQUENCY		GADC_MAX_HIGH_SPEED_SAMPLERATE +#define GAUDIO_RECORD_MAX_SAMPLE_FREQUENCY			GADC_MAX_HIGH_SPEED_SAMPLERATE  /** - * @brief	The number of bits in a sample - * @details	For this driver it matches the cpu sample bits + * @brief	The number of audio formats supported by this driver   */ -#define GAUDIO_RECORD_BITS_PER_SAMPLE			GADC_BITS_PER_SAMPLE +#define GAUDIO_RECORD_NUM_FORMATS					1  /** - * @brief	The format of an audio sample - * @details	For this driver it matches the cpu sample format + * @brief	The available audio sample formats in order of preference   */ -#define GAUDIO_RECORD_SAMPLE_FORMAT				GADC_SAMPLE_FORMAT +#define GAUDIO_RECORD_FORMAT1						GADC_SAMPLE_FORMAT  /**   * For the GAUDIO driver that uses GADC - all the remaining config definitions are specific diff --git a/drivers/gaudio/gadc/gaudio_record_lld.c b/drivers/gaudio/gadc/gaudio_record_lld.c index ee994dc1..6f4cb2de 100644 --- a/drivers/gaudio/gadc/gaudio_record_lld.c +++ b/drivers/gaudio/gadc/gaudio_record_lld.c @@ -8,10 +8,6 @@  /**   * @file    drivers/gaudio/gadc/gaudio_record_lld.c   * @brief   GAUDIO - Record Driver file for using the cpu ADC (via GADC). - * - * @addtogroup GAUDIO - * - * @{   */  /** @@ -19,8 +15,6 @@   * from the board definitions.   */  #define GAUDIO_RECORD_IMPLEMENTATION - -  #include "gfx.h"  #if GFX_USE_GAUDIO && GAUDIO_NEED_RECORD @@ -33,30 +27,38 @@  /* Include the driver defines */  #include "src/gaudio/driver_record.h" +static void gadcCallbackI(void) { +	GDataBuffer *pd; + +	pd = gadcHighSpeedGetDataI(); +	if (pd) +		gaudioRecordSaveDataBlockI(pd); +} +  /*===========================================================================*/  /* External declarations.                                                    */  /*===========================================================================*/ -void gaudin_lld_init(const gaudin_params *paud) { +bool_t gaudio_record_lld_init(uint16_t channel, uint32_t frequency, ArrayDataFormat format) { +	/* Check the parameters */ +	if (channel >= GAUDIO_RECORD_NUM_CHANNELS || frequency > GAUDIO_RECORD_MAX_SAMPLE_FREQUENCY || format != GAUDIO_RECORD_FORMAT1) +		return FALSE; +  	/* Setup the high speed GADC */ -	gadcHighSpeedInit(gaudin_lld_physdevs[paud->channel], paud->frequency, paud->buffer, paud->bufcount, paud->samplesPerEvent); +	gadcHighSpeedInit(gaudio_gadc_physdevs[channel], frequency);  	/* Register ourselves for ISR callbacks */ -	gadcHighSpeedSetISRCallback(GAUDIN_ISR_CompleteI); +	gadcHighSpeedSetISRCallback(gadcCallbackI); -	/** -	 * The gadc driver handles any errors for us by restarting the transaction so there is -	 * no need for us to setup anything for GAUDIN_ISR_ErrorI() -	 */ +	return TRUE;  } -void gaudin_lld_start(void) { +void gaudio_record_lld_start(void) {  	gadcHighSpeedStart();  } -void gaudin_lld_stop(void) { +void gaudio_record_lld_stop(void) {  	gadcHighSpeedStop();  }  #endif /* GFX_USE_GAUDIO && GAUDIO_NEED_RECORD */ -/** @} */ diff --git a/src/gadc/driver.h b/src/gadc/driver.h index 4427f4f0..6e935576 100644 --- a/src/gadc/driver.h +++ b/src/gadc/driver.h @@ -32,9 +32,9 @@   * @{   */  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. */ +	uint32_t		physdev;		/* @< Which physical ADC devices/channels to use. Filled in by High Level Code */ +	uint32_t		frequency;		/* @< The conversion frequency. Filled in by High Level Code */ +	GDataBuffer		*pdata;			/* @< The buffer to put the ADC samples into. */  	bool_t			now;			/* @< Trigger the first conversion now rather than waiting for the first timer interrupt (if possible) */  	} GadcLldTimerData;  /* @} */ @@ -52,30 +52,6 @@ typedef struct GadcLldNonTimerData_t {  /* @} */  /** - * @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.   * @@ -92,70 +68,75 @@ extern "C" {  #endif  /** - * @brief				Initialise the driver + * @brief				These routines are the callbacks that the driver uses. + * @details				Defined in the high level GADC code.   * - * @api + * @notapi + * @{ + */ +	/** +	 * @brief	The last conversion requested is now complete +	 */ +	void gadcDataReadyI(void); + +	/** +	 * @brief	The last conversion requested failed +	 */ +	void gadcDataFailI(void); +/** + * @}   */ -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. + * @brief				Initialise the driver   * - * @return				Number of samples of the convesion   * @api   */ -size_t gadc_lld_samples_per_conversion(uint32_t physdev); +void gadc_lld_init(void);  /**   * @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 + * @param[in] pgtd		The structure containing the sample frequency and physical device to use.   *   * @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 + * @details				When a timer interrupt occurs a conversion should start if there 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 + * @note				Timer interrupts occurring before @p gadc_lld_adc_timerI() has been called, + * 						if  @p gadc_lld_adc_timerI() has been called quick enough, or while + * 						a non-timer conversion is active should be ignored other than (optionally) incrementing   * 						the GADC_Timer_Missed variable. + * @note				The pdata and now members of the pgtd structure are now yet valid.   *   * @api   */ -void gadc_lld_start_timer(uint32_t physdev, uint32_t frequency); +void gadc_lld_start_timer(GadcLldTimerData *pgtd);  /**   * @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. + * @param[in] pgtd		The structure containing the sample frequency and physical device to use.   * + * @note				After this function returns there should be no more calls to @p gadcDataReadyI() + * 						or @p gadcDataFailI() in relation to timer conversions.   * @api   */ -void gadc_lld_stop_timer(uint32_t physdev); +void gadc_lld_stop_timer(GadcLldTimerData *pgtd);  /** - * @brief				Start a "timer" conversion. + * @brief				Start a set of "timer" conversions.   * @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 driver should call @p gadcDataReadyI() when it completes the operation + * 						or @p gadcDataFailI() on an error.   * @note				The high level code ensures that this is not called while a non-timer conversion is in   * 						progress   * @@ -171,8 +152,8 @@ void gadc_lld_adc_timerI(GadcLldTimerData *pgtd);   *   * @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 driver should call @p gadcDataReadyI() when it completes the operation + * 						or @p gadcDataFailI() on an error.   * @note				The high level code ensures that this is not called while a timer conversion is in   * 						progress   * diff --git a/src/gadc/gadc.c b/src/gadc/gadc.c index 8ae431b0..e2d2d461 100644 --- a/src/gadc/gadc.c +++ b/src/gadc/gadc.c @@ -31,42 +31,30 @@  volatile bool_t GADC_Timer_Missed; -static gfxSem	gadcsem; -static gfxMutex	gadcmutex; -static GTimer	LowSpeedGTimer; +static bool_t			gadcRunning; +static gfxSem			LowSpeedSlotSem; +static gfxMutex			LowSpeedMutex; +static GTimer			LowSpeedGTimer; +static gfxQueueGSync	HighSpeedBuffers; +  #if GFX_USE_GEVENT -	static GTimer	HighSpeedGTimer; +	static GTimer		HighSpeedGTimer;  #endif -static volatile uint16_t	gflags = 0; -	#define GADC_GFLG_ISACTIVE	0x0001  #define GADC_FLG_ISACTIVE	0x0001  #define GADC_FLG_ISDONE		0x0002  #define GADC_FLG_ERROR		0x0004  #define GADC_FLG_GTIMER		0x0008 +#define GADC_FLG_STALLED	0x0010  static struct hsdev {  	// Our status flags  	uint16_t				flags; -	// What we started with -	uint32_t				frequency; -	adcsample_t				*buffer; -	size_t					bufcount; -	size_t					samplesPerEvent; - -	// The last set of results -	size_t					lastcount; -	adcsample_t				*lastbuffer; -	uint16_t				lastflags; -  	// Other stuff we need to track progress and for signaling  	GadcLldTimerData		lld; -	size_t					samplesPerConversion; -	size_t					remaining; -	gfxSem					*bsem; -	GEventADC				*pEvent; +	uint16_t				eventflags;  	GADCISRCallbackFunction	isrfn;  	} hs; @@ -101,49 +89,59 @@ static inline void FindNextConversionI(void) {  	/**  	 * Look for the next thing to do.  	 */ -	while(curlsdev < &ls[GADC_MAX_LOWSPEED_DEVICES]) { +	gadcRunning = TRUE; +	for(; curlsdev < &ls[GADC_MAX_LOWSPEED_DEVICES]; curlsdev++) {  		if ((curlsdev->flags & (GADC_FLG_ISACTIVE|GADC_FLG_ISDONE)) == GADC_FLG_ISACTIVE) {  			gadc_lld_adc_nontimerI(&curlsdev->lld);  			return;  		} -		curlsdev++;  	}  	curlsdev = 0;  	/* No more low speed devices - do a high speed conversion */  	if (hs.flags & GADC_FLG_ISACTIVE) { -		hs.lld.now = GADC_Timer_Missed ? TRUE : FALSE; -		GADC_Timer_Missed = 0; -		gadc_lld_adc_timerI(&hs.lld); -		return; +		hs.lld.pdata = gfxBufferGetI(); +		if (hs.lld.pdata) { +			hs.lld.now = GADC_Timer_Missed || (hs.flags & GADC_FLG_STALLED); +			hs.flags &= ~GADC_FLG_STALLED; +			GADC_Timer_Missed = 0; +			gadc_lld_adc_timerI(&hs.lld); +			return; +		} + +		// Oops - no free buffers - mark stalled and go back to low speed devices +		hs.flags |= GADC_FLG_STALLED; +		hs.eventflags &= ~GADC_HSADC_RUNNING; +		for(curlsdev = ls; curlsdev < &ls[GADC_MAX_LOWSPEED_DEVICES]; curlsdev++) { +			if ((curlsdev->flags & (GADC_FLG_ISACTIVE|GADC_FLG_ISDONE)) == GADC_FLG_ISACTIVE) { +				gadc_lld_adc_nontimerI(&curlsdev->lld); +				return; +			} +		} +		curlsdev = 0;  	}  	/* Nothing more to do */ -	gflags &= ~GADC_GFLG_ISACTIVE; +	gadcRunning = FALSE;  } -void GADC_ISR_CompleteI(ADCDriver *adcp, adcsample_t *buffer, size_t n) { -	(void) adcp; +void gadcDataReadyI(void) {  	if (curlsdev) {  		/* This interrupt must be in relation to the low speed device */  		if (curlsdev->flags & GADC_FLG_ISACTIVE) { -			/** -			 * As we only handle a single low speed conversion at a time, we know -			 * we know we won't get any half completion interrupts. -			 */  			curlsdev->flags |= GADC_FLG_ISDONE;  			gtimerJabI(&LowSpeedGTimer);  		} -		#if ADC_ISR_FULL_CODE_BUG +		#if GFX_USE_OS_CHIBIOS && CHIBIOS_ADC_ISR_FULL_CODE_BUG  			/**  			 * Oops - We have just finished a low speed conversion but a bug prevents us  			 * restarting the ADC here. Other code will restart it in the thread based  			 * ADC handler.  			 */ -			gflags &= ~GADC_GFLG_ISACTIVE; +			gadcRunning = FALSE;  			return;  		#endif @@ -152,49 +150,31 @@ void GADC_ISR_CompleteI(ADCDriver *adcp, adcsample_t *buffer, size_t n) {  		/* This interrupt must be in relation to the high speed device */  		if (hs.flags & GADC_FLG_ISACTIVE) { -			/* Save the details */ -			hs.lastcount = n; -			hs.lastbuffer = buffer; -			hs.lastflags = GADC_Timer_Missed ? GADC_HSADC_LOSTEVENT : 0; +			if (hs.lld.pdata->len) { +				/* Save the current buffer on the HighSpeedBuffers */ +				gfxQueueGSyncPutI(&HighSpeedBuffers, (gfxQueueGSyncItem *)hs.lld.pdata); +				hs.lld.pdata = 0; + +				/* Save the details */ +				hs.eventflags = GADC_HSADC_RUNNING|GADC_HSADC_GOTBUFFER; +				if (GADC_Timer_Missed) +					hs.eventflags |= GADC_HSADC_LOSTEVENT; +				if (hs.flags & GADC_FLG_STALLED) +					hs.eventflags |= GADC_HSADC_STALL; + +				/* Our signalling mechanisms */ +				if (hs.isrfn) +					hs.isrfn(); -			/* Signal the user with the data */ -			if (hs.pEvent) {  				#if GFX_USE_GEVENT -					hs.pEvent->type = GEVENT_ADC; +					if (hs.flags & GADC_FLG_GTIMER) +						gtimerJabI(&HighSpeedGTimer);  				#endif -				hs.pEvent->count = hs.lastcount; -				hs.pEvent->buffer = hs.lastbuffer; -				hs.pEvent->flags = hs.lastflags; -			} - -			/* Our three signalling mechanisms */ -			if (hs.isrfn) -				hs.isrfn(buffer, n); - -			if (hs.bsem) -				gfxSemSignalI(hs.bsem); - -			#if GFX_USE_GEVENT -				if (hs.flags & GADC_FLG_GTIMER) -					gtimerJabI(&HighSpeedGTimer); -			#endif - -			/* Adjust what we have left to do */ -			hs.lld.count -= n; -			hs.remaining -= n; - -			/* Half completion - We have done all we can for now - wait for the next interrupt */ -			if (hs.lld.count) -				return; - -			/* Our buffer is cyclic - set up the new buffer pointers */ -			if (hs.remaining) { -				hs.lld.buffer = buffer + (n * hs.samplesPerConversion);  			} else { -				hs.remaining = hs.bufcount; -				hs.lld.buffer = hs.buffer; +				// Oops - no data in this buffer. Just return it to the free-list +				gfxBufferRelease(hs.lld.pdata); +				hs.lld.pdata = 0;  			} -			hs.lld.count = hs.remaining < hs.samplesPerEvent ? hs.remaining : hs.samplesPerEvent;  		}  	} @@ -204,22 +184,19 @@ void GADC_ISR_CompleteI(ADCDriver *adcp, adcsample_t *buffer, size_t n) {  	FindNextConversionI();  } -void GADC_ISR_ErrorI(ADCDriver *adcp, adcerror_t err) { -	(void) adcp; -	(void) err; - +void gadcDataFailI(void) {  	if (curlsdev) {  		if ((curlsdev->flags & (GADC_FLG_ISACTIVE|GADC_FLG_ISDONE)) == GADC_FLG_ISACTIVE)  			/* Mark the error then try to repeat it */  			curlsdev->flags |= GADC_FLG_ERROR; -		#if ADC_ISR_FULL_CODE_BUG +		#if GFX_USE_OS_CHIBIOS && CHIBIOS_ADC_ISR_FULL_CODE_BUG  			/**  			 * Oops - We have just finished a low speed conversion but a bug prevents us  			 * restarting the ADC here. Other code will restart it in the thread based  			 * ADC handler.  			 */ -			gflags &= ~GADC_GFLG_ISACTIVE; +			gadcRunning = FALSE;  			gtimerJabI(&LowSpeedGTimer);  			return; @@ -239,8 +216,9 @@ void GADC_ISR_ErrorI(ADCDriver *adcp, adcerror_t err) {  void _gadcInit(void)  {  	gadc_lld_init(); -	gfxSemInit(&gadcsem, GADC_MAX_LOWSPEED_DEVICES, GADC_MAX_LOWSPEED_DEVICES); -	gfxMutexInit(&gadcmutex); +	gfxQueueGSyncInit(&HighSpeedBuffers); +	gfxSemInit(&LowSpeedSlotSem, GADC_MAX_LOWSPEED_DEVICES, GADC_MAX_LOWSPEED_DEVICES); +	gfxMutexInit(&LowSpeedMutex);  	gtimerInit(&LowSpeedGTimer);  	#if GFX_USE_GEVENT  		gtimerInit(&HighSpeedGTimer); @@ -252,8 +230,9 @@ void _gadcDeinit(void)  	/* commented stuff is ToDo */  	// gadc_lld_deinit(); -	gfxSemDestroy(&gadcsem); -	gfxMutexDestroy(&gadcmutex); +	gfxQueueGSyncDeinit(&HighSpeedBuffers); +	gfxSemDestroy(&LowSpeedSlotSem); +	gfxMutexDestroy(&LowSpeedMutex);  	gtimerDeinit(&LowSpeedGTimer);  	#if GFX_USE_GEVENT  		gtimerDeinit(&HighSpeedGTimer); @@ -262,7 +241,7 @@ void _gadcDeinit(void)  static inline void StartADC(bool_t onNoHS) {  	gfxSystemLock(); -	if (!(gflags & GADC_GFLG_ISACTIVE) || (onNoHS && !curlsdev)) +	if (!gadcRunning || (onNoHS && !curlsdev))  		FindNextConversionI();  	gfxSystemUnlock();  } @@ -289,9 +268,7 @@ static void BSemSignalCallback(adcsample_t *buffer, void *param) {  			}  			pe->type = GEVENT_ADC; -			pe->count = hs.lastcount; -			pe->buffer = hs.lastbuffer; -			pe->flags = hs.lastflags | psl->srcflags; +			pe->flags = hs.eventflags | psl->srcflags;  			psl->srcflags = 0;  			geventSendEvent(psl);  		} @@ -305,7 +282,7 @@ static void LowSpeedGTimerCallback(void *param) {  	adcsample_t				*buffer;  	struct lsdev			*p; -	#if ADC_ISR_FULL_CODE_BUG +	#if GFX_USE_OS_CHIBIOS && CHIBIOS_ADC_ISR_FULL_CODE_BUG  		/* Ensure the ADC is running if it needs to be - Bugfix HACK */  		StartADC(FALSE);  	#endif @@ -325,33 +302,22 @@ static void LowSpeedGTimerCallback(void *param) {  			p->param = 0;			// Needed to prevent the compiler removing the local variables  			p->lld.buffer = 0;		// Needed to prevent the compiler removing the local variables  			p->flags = 0;			// The slot is available (indivisible operation) -			gfxSemSignal(&gadcsem);	// Tell everyone +			gfxSemSignal(&LowSpeedSlotSem);	// Tell everyone  			fn(buffer, prm);		// Perform the callback  		}  	}  } -void gadcHighSpeedInit(uint32_t physdev, uint32_t frequency, adcsample_t *buffer, size_t bufcount, size_t samplesPerEvent) +void gadcHighSpeedInit(uint32_t physdev, uint32_t frequency)  {  	gadcHighSpeedStop();		/* This does the init for us */  	/* Just save the details and reset everything for now */ -	hs.frequency = frequency; -	hs.buffer = buffer; -	hs.bufcount = bufcount; -	hs.samplesPerEvent = samplesPerEvent; -	hs.lastcount = 0; -	hs.lastbuffer = 0; -	hs.lastflags = 0;  	hs.lld.physdev = physdev; -	hs.lld.buffer = buffer; -	hs.lld.count = samplesPerEvent; +	hs.lld.frequency = frequency; +	hs.lld.pdata = 0;  	hs.lld.now = FALSE; -	hs.samplesPerConversion = gadc_lld_samples_per_conversion(physdev); -	hs.remaining = bufcount; -	hs.bsem = 0; -	hs.pEvent = 0;  	hs.isrfn = 0;  } @@ -368,12 +334,12 @@ void gadcHighSpeedSetISRCallback(GADCISRCallbackFunction isrfn) {  	hs.isrfn = isrfn;  } -void gadcHighSpeedSetBSem(gfxSem *pbsem, GEventADC *pEvent) { -	/* Use the system lock to ensure they occur atomically */ -	gfxSystemLock(); -	hs.pEvent = pEvent; -	hs.bsem = pbsem; -	gfxSystemUnlock(); +GDataBuffer *gadcHighSpeedGetData(delaytime_t ms) { +	return (GDataBuffer *)gfxQueueGSyncGet(&HighSpeedBuffers, ms); +} + +GDataBuffer *gadcHighSpeedGetDataI(void) { +	return (GDataBuffer *)gfxQueueGSyncGetI(&HighSpeedBuffers);  }  void gadcHighSpeedStart(void) { @@ -381,8 +347,8 @@ void gadcHighSpeedStart(void) {  	if (hs.flags & GADC_FLG_ISACTIVE)  		return; -	gadc_lld_start_timer(hs.lld.physdev, hs.frequency);  	hs.flags = GADC_FLG_ISACTIVE; +	gadc_lld_start_timer(&hs.lld);  	StartADC(FALSE);  } @@ -390,7 +356,15 @@ void gadcHighSpeedStop(void) {  	if (hs.flags & GADC_FLG_ISACTIVE) {  		/* No more from us */  		hs.flags = 0; -		gadc_lld_stop_timer(hs.lld.physdev); +		gadc_lld_stop_timer(&hs.lld); +		/* +		 * There might be a buffer still locked up by the driver - if so release it. +		 */ +		if (hs.lld.pdata) { +			gfxBufferRelease(hs.lld.pdata); +			hs.lld.pdata = 0; +		} +  		/*  		 * We have to pass TRUE to StartADC() as we might have the ADC marked as active when it isn't  		 * due to stopping the timer while it was converting. @@ -405,17 +379,17 @@ void gadcLowSpeedGet(uint32_t physdev, adcsample_t *buffer) {  	/* Start the Low Speed Timer */  	gfxSemInit(&mysem, 1, 1); -	gfxMutexEnter(&gadcmutex); +	gfxMutexEnter(&LowSpeedMutex);  	if (!gtimerIsActive(&LowSpeedGTimer))  		gtimerStart(&LowSpeedGTimer, LowSpeedGTimerCallback, 0, TRUE, TIME_INFINITE); -	gfxMutexExit(&gadcmutex); +	gfxMutexExit(&LowSpeedMutex);  	while(1) {  		/* Wait for an available slot */ -		gfxSemWait(&gadcsem, TIME_INFINITE); +		gfxSemWait(&LowSpeedSlotSem, TIME_INFINITE);  		/* Find a slot */ -		gfxMutexEnter(&gadcmutex); +		gfxMutexEnter(&LowSpeedMutex);  		for(p = ls; p < &ls[GADC_MAX_LOWSPEED_DEVICES]; p++) {  			if (!(p->flags & GADC_FLG_ISACTIVE)) {  				p->lld.physdev = physdev; @@ -423,13 +397,13 @@ void gadcLowSpeedGet(uint32_t physdev, adcsample_t *buffer) {  				p->fn = BSemSignalCallback;  				p->param = &mysem;  				p->flags = GADC_FLG_ISACTIVE; -				gfxMutexExit(&gadcmutex); +				gfxMutexExit(&LowSpeedMutex);  				StartADC(FALSE);  				gfxSemWait(&mysem, TIME_INFINITE);  				return;  			}  		} -		gfxMutexExit(&gadcmutex); +		gfxMutexExit(&LowSpeedMutex);  		/**  		 *  We should never get here - the count semaphore must be wrong. @@ -442,7 +416,7 @@ bool_t gadcLowSpeedStart(uint32_t physdev, adcsample_t *buffer, GADCCallbackFunc  	struct lsdev *p;  	/* Start the Low Speed Timer */ -	gfxMutexEnter(&gadcmutex); +	gfxMutexEnter(&LowSpeedMutex);  	if (!gtimerIsActive(&LowSpeedGTimer))  		gtimerStart(&LowSpeedGTimer, LowSpeedGTimerCallback, 0, TRUE, TIME_INFINITE); @@ -450,18 +424,18 @@ bool_t gadcLowSpeedStart(uint32_t physdev, adcsample_t *buffer, GADCCallbackFunc  	for(p = ls; p < &ls[GADC_MAX_LOWSPEED_DEVICES]; p++) {  		if (!(p->flags & GADC_FLG_ISACTIVE)) {  			/* We know we have a slot - this should never wait anyway */ -			gfxSemWait(&gadcsem, TIME_IMMEDIATE); +			gfxSemWait(&LowSpeedSlotSem, TIME_IMMEDIATE);  			p->lld.physdev = physdev;  			p->lld.buffer = buffer;  			p->fn = fn;  			p->param = param;  			p->flags = GADC_FLG_ISACTIVE; -			gfxMutexExit(&gadcmutex); +			gfxMutexExit(&LowSpeedMutex);  			StartADC(FALSE);  			return TRUE;  		}  	} -	gfxMutexExit(&gadcmutex); +	gfxMutexExit(&LowSpeedMutex);  	return FALSE;  } diff --git a/src/gadc/sys_defs.h b/src/gadc/sys_defs.h index f6349dfe..21e81fb6 100644 --- a/src/gadc/sys_defs.h +++ b/src/gadc/sys_defs.h @@ -73,15 +73,10 @@ typedef struct GEventADC_t {  		 * @{  		 */  		#define	GADC_HSADC_LOSTEVENT		0x0001		/**< @brief The last GEVENT_HSDADC event was lost */ +		#define	GADC_HSADC_RUNNING			0x0002		/**< @brief The High Speed ADC is currently running */ +		#define	GADC_HSADC_GOTBUFFER		0x0004		/**< @brief A buffer is ready for processing */ +		#define	GADC_HSADC_STALL			0x0008		/**< @brief The High Speed ADC has stalled due to no free buffers */  		/** @} */ -	/** -	 * @brief The number of conversions in the buffer -	 */ -	size_t			count; -	/** -	 * @brief The buffer containing the conversion samples -	 */ -	adcsample_t		*buffer;  } GEventADC;  /** @} */ @@ -93,7 +88,7 @@ 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); +typedef void (*GADCISRCallbackFunction)(void);  /*===========================================================================*/  /* External declarations.                                                    */ @@ -109,40 +104,28 @@ extern "C" {   *   * @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				ChibiOS ONLY: Due to a bug in ChibiOS each buffer on the free-list must contain an even number of + * 						samples and for multi-channel devices it must hold a number of samples that is evenly divisible + * 						by 2 times the number of active channels.   * @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. + * 						Each channel is then interleaved into the provided buffer. Make sure your buffers all hold + * 						a number of samples evenly divisible by the number of active channels.   * 						As an example, if physdev turns on 2 devices then the buffer contains - * 						alternate device samples and the buffer must contain 2 * bufcount samples. + * 						alternate device samples and the buffer must contain multiples of 2 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 + * 						being created at 50Hz (eg 100 samples/buffer, frequency = 5kHz) then the maximum   * 						frequency for low speed conversions will be 50Hz. + * @note				Only a single sample format is supported - that provided by the GADC driver. That sample + * 						format applies to both high speed and low speed sampling.   *   * @api   */ -void gadcHighSpeedInit(uint32_t physdev, uint32_t frequency, adcsample_t *buffer, size_t bufcount, size_t samplesPerEvent); +void gadcHighSpeedInit(uint32_t physdev, uint32_t frequency);  #if GFX_USE_GEVENT || defined(__DOXYGEN__)  	/** @@ -170,7 +153,7 @@ void gadcHighSpeedInit(uint32_t physdev, uint32_t frequency, adcsample_t *buffer   *   * @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 + * @note				The high speed ADC is capable of signalling via this method, a blocked thread and the GEVENT   * 						sub-system at the same time.   *   * @api @@ -178,19 +161,24 @@ void gadcHighSpeedInit(uint32_t physdev, uint32_t frequency, adcsample_t *buffer  void gadcHighSpeedSetISRCallback(GADCISRCallbackFunction isrfn);  /** - * @brief				Allow retrieving of results from the high speed ADC using a Binary Semaphore and a static event buffer. + * @brief		Get a filled buffer from the ADC + * @return		A GDataBuffer pointer or NULL if the timeout is exceeded   * - * @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. + * @params[in] ms	The maximum amount of time in milliseconds to wait for data if some is not currently available.   * + * @note		After processing the data, your application must return the buffer to the free-list so that + * 				it can be used again. This can be done using @p gfxBufferRelease(). + * @note		A buffer may be returned to the free-list before you have finished processing it provided you finish + * 				processing it before GADC re-uses it. This is useful when RAM usage is critical to reduce the number + * 				of buffers required. It works before the free list is a FIFO queue and therefore buffers are kept + * 				in the queue as long as possible before they are re-used. + * @note		The function ending with "I" is the interrupt class function.   * @api + * @{   */ -void gadcHighSpeedSetBSem(gfxSem *pbsem, GEventADC *pEvent); +GDataBuffer *gadcHighSpeedGetData(delaytime_t ms); +GDataBuffer *gadcHighSpeedGetDataI(void); +/* @} */  /**   * @brief   Start the high speed ADC conversions. diff --git a/src/gadc/sys_rules.h b/src/gadc/sys_rules.h index 7272337e..363b2434 100644 --- a/src/gadc/sys_rules.h +++ b/src/gadc/sys_rules.h @@ -24,6 +24,17 @@  		#undef GFX_USE_GTIMER  		#define	GFX_USE_GTIMER		TRUE  	#endif +	#if !GFX_USE_GQUEUE || !GQUEUE_NEED_GSYNC || !GQUEUE_NEED_BUFFERS +		#if GFX_DISPLAY_RULE_WARNINGS +			#warning "GADC: GFX_USE_GQUEUE, GQUEUE_NEED_BUFFERS and GQUEUE_NEED_GSYNC are required if GFX_USE_GADC is TRUE. They have been turned on for you." +		#endif +		#undef GFX_USE_GQUEUE +		#define	GFX_USE_GQUEUE		TRUE +		#undef GQUEUE_NEED_BUFFERS +		#define	GQUEUE_NEED_BUFFERS		TRUE +		#undef GQUEUE_NEED_GSYNC +		#define	GQUEUE_NEED_GSYNC		TRUE +	#endif  #endif  #endif /* _GADC_RULES_H */ | 
