sam7fc/src/at91_adc.c

100 lines
3.3 KiB
C

/***************************************************************************
* Copyright (C) 01/2008 by Olaf Rempel *
* razzor@kopf-tisch.de *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; version 2 of the License *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include <stdint.h>
#include <stdio.h>
#include "AT91SAM7S256.h"
#include "board.h"
#include "at91_pitc.h"
#include "static_alloc.h"
static uint16_t adc_result[4];
static void at91_adc_isr(void)
{
AT91S_PDC *pdc = AT91C_BASE_PDC_ADC;
pdc->PDC_RPR = (uint32_t) &adc_result;
pdc->PDC_RCR = ARRAY_SIZE(adc_result);
pdc->PDC_PTCR = AT91C_PDC_RXTEN;
/* clear interrupts */
AT91S_ADC *adc = AT91C_BASE_ADC;
uint32_t status = adc->ADC_SR;
status = status;
}
static uint32_t adc_trigger(struct pitc_timer *timer)
{
*AT91C_ADC_CR = AT91C_ADC_START;
return PITC_RESTART_TIMER;
}
void at91_adc_test_init(void)
{
/* enable ADC clock */
*AT91C_PMC_PCER = (1 << AT91C_ID_ADC);
/* ADC Software reset */
AT91S_ADC *adc = AT91C_BASE_ADC;
adc->ADC_CR = AT91C_ADC_SWRST;
/*
* ADC config: 10bit, no sleep
* 4.8MHz (48MHz / ((4 +1) * 2) = 4.8MHz)
* 96 cycles Startup ((11 +1) * 8 / 4.8MHz = 20us)
* 3 cycles SH ((2 +1) / 4.8MHz = 625ns)
* Conversion time per channel @5MHz ~2us
*/
adc->ADC_MR = AT91C_ADC_TRGEN_DIS |
AT91C_ADC_LOWRES_10_BIT |
AT91C_ADC_SLEEP_NORMAL_MODE |
(AT91C_ADC_PRESCAL & (4 << 8)) |
(AT91C_ADC_STARTUP & (11 << 16)) |
(AT91C_ADC_SHTIM & (2 << 24));
/* setup PDC */
AT91S_PDC *pdc = AT91C_BASE_PDC_ADC;
pdc->PDC_RPR = (uint32_t) &adc_result;
pdc->PDC_RCR = ARRAY_SIZE(adc_result);
pdc->PDC_PTCR = AT91C_PDC_RXTEN;
/* enable 4 channels, PDC Interrupt */
adc->ADC_CHER = 0xF0;
adc->ADC_IER = AT91C_ADC_ENDRX;
/* low priority, level triggered, own vector */
AT91S_AIC *aic = AT91C_BASE_AIC;
aic->AIC_SMR[AT91C_ID_ADC] = IRQPRIO_ADC | AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL;
aic->AIC_SVR[AT91C_ID_ADC] = (uint32_t)at91_adc_isr;
aic->AIC_IECR = (1<<AT91C_ID_ADC);
/* schedule trigger */
struct pitc_timer *adc_timer = alloc_pitc_timer(100, &adc_trigger, NULL);
pitc_schedule_timer(adc_timer);
}
void at91_adc_printresults(void)
{
uint8_t i;
for (i = 0; i < ARRAY_SIZE(adc_result); i++)
printf("%x:0x%03X ", i, adc_result[i]);
printf("\n");
}