diff options
Diffstat (limited to 'drivers/gadc')
-rw-r--r-- | drivers/gadc/AT91SAM7/gadc_lld.c | 88 |
1 files changed, 29 insertions, 59 deletions
diff --git a/drivers/gadc/AT91SAM7/gadc_lld.c b/drivers/gadc/AT91SAM7/gadc_lld.c index 52b06539..b01fdd6c 100644 --- a/drivers/gadc/AT91SAM7/gadc_lld.c +++ b/drivers/gadc/AT91SAM7/gadc_lld.c @@ -16,13 +16,12 @@ #include "src/gadc/driver.h" -static GDataBuffer *pData; -static size_t bytesperconversion; +static uint32_t nextfreq; +// Forward references to ISR routines 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 @@ -37,82 +36,53 @@ 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(); - } + gadcGotDataI(n); } static void ISR_ErrorI(ADCDriver *adcp, adcerror_t err) { (void) adcp; (void) err; - gadcDataFailI(); + gadcGotDataI(0); } void gadc_lld_init(void) { adcStart(&ADCD1, 0); } -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 */ - phys = pgtd->physdev; - for(bytesperconversion = 0; phys; phys >>= 1) - if (phys & 0x01) - bytesperconversion++; - bytesperconversion *= (gfxSampleFormatBits(GADC_SAMPLE_FORMAT)+7)/8; - - /** - * 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 = pgtd->frequency; -} +size_t gadc_lld_samplesperconversion(uint32_t physdev) { + size_t samples; -void gadc_lld_stop_timer(GadcLldTimerData *pgtd) { - (void) pgtd; - if ((acg.trigger & ~ADC_TRIGGER_SOFTWARE) == ADC_TRIGGER_TIMER) - adcStop(&ADCD1); + for(samples = 0; physdev; physdev >>= 1) + if (physdev & 0x01) + samples++; + return samples; } -void gadc_lld_adc_timerI(GadcLldTimerData *pgtd) { - /** - * We don't need to calculate num_channels because the AT91SAM7 ADC does this for us. - */ - acg.channelselects = pgtd->physdev; - acg.trigger = pgtd->now ? (ADC_TRIGGER_TIMER|ADC_TRIGGER_SOFTWARE) : ADC_TRIGGER_TIMER; +void gadc_lld_start_timerI(uint32_t frequency) { + // Nothing to do here - the AT91SAM7 adc driver uses an internal timer + // which is set up when the job is started. We save this here just to + // indicate the timer should be re-initialised on the next timer job + nextfreq = frequency; +} - pData = pgtd->pdata; - adcStartConversionI(&ADCD1, &acg, (adcsample_t *)(pgtd->pdata+1), pData->size/bytesperconversion); +void gadc_lld_stop_timerI(void) { + // Nothing to do here. The AT91SAM7 adc driver automatically turns off timer interrupts + // on completion of the job +} - /* Next time assume the same (still running) timer */ - acg.frequency = 0; +void gadc_lld_timerjobI(GadcTimerJob *pj) { + acg.channelselects = pj->physdev; + acg.trigger = ADC_TRIGGER_TIMER; + acg.frequency = nextfreq; + nextfreq = 0; // Next job use the same timer + adcStartConversionI(&ADCD1, &acg, pj->buffer, pj->todo); } -void gadc_lld_adc_nontimerI(GadcLldNonTimerData *pgntd) { - /** - * We don't need to calculate num_channels because the AT91SAM7 ADC does this for us. - */ - acg.channelselects = pgntd->physdev; +void gadc_lld_nontimerjobI(GadcNonTimerJob *pj) { + acg.channelselects = pj->physdev; acg.trigger = ADC_TRIGGER_SOFTWARE; - - pData = 0; - adcStartConversionI(&ADCD1, &acg, pgntd->buffer, 1); + adcStartConversionI(&ADCD1, &acg, pj->buffer, 1); } #endif /* GFX_USE_GADC */ |