adc & rcontrol work

This commit is contained in:
Olaf Rempel 2008-03-10 21:37:56 +01:00
parent 580d8369fa
commit 8414aeac15
6 changed files with 151 additions and 69 deletions

22
include/at91_adc.h Normal file
View File

@ -0,0 +1,22 @@
#ifndef AT91_ADC_H_
#define AT91_ADC_H_
#include <stdint.h>
#define ADC_GYRO_ROLL 0
#define ADC_GYRO_NICK 1
#define ADC_GYRO_YAW 2
#define ADC_ACC_ROLL 3
#define ADC_ACC_NICK 4
#define ADC_ACC_YAW 5
#define ADC_VOLTAGE 6
#define ADC_CAL_GYRO 1
#define ADC_CAL_ACC 2
void adc_trigger(void);
void adc_calibrate(uint32_t mode);
void at91_adc_init(void);
#endif /*AT91_ADC_H_*/

View File

@ -12,6 +12,7 @@ struct rc_values {
uint32_t rcontrol_getvalues(struct rc_values *rc);
void rcontrol_calibrate(uint32_t mode);
void rcontrol_print_cal(void);
void at91_tc1_init(void);

View File

@ -3,7 +3,4 @@
void at91_rttc_test_init(void);
void at91_adc_test_init(void);
void at91_adc_printresults(void);
#endif /*AT91_TESTS_H_*/

44
main.c
View File

@ -20,6 +20,7 @@
#include "at91_sysc.h"
#include "at91_dbgu.h"
#include "at91_pitc.h"
#include "at91_adc.h"
#include "at91_tests.h"
#include "at91_udp.h"
#include "at91_pio.h"
@ -48,16 +49,27 @@ static uint32_t pitc_test(struct pitc_timer *timer)
printf("%+5d ", rc.chan[j]);
printf("\r");
*/
static uint32_t cnt;
if (cnt++ == 300) {
rcontrol_calibrate(RC_CAL_END);
printf("\n\r");
rcontrol_print_cal();
}
*/
/*
static uint8_t data[4] = { 0x00, 0x00, 0x00, 0x00 };
twi_setpwm(data);
*/
adc_trigger();
return PITC_RESTART_TIMER;
}
static struct pitc_timer pitc_test_timer = {
.interval = 10,
.interval = 20,
.func = &pitc_test,
};
@ -83,7 +95,7 @@ int main(void)
/* twi */
at91_twi_init();
// at91_twi_test();
at91_twi_test();
/* usb */
at91_udp_init();
@ -91,30 +103,10 @@ int main(void)
printf("static alloc: %5ld bytes\n\r", static_alloc_used());
/* adc, need timer */
// at91_adc_test_init();
at91_adc_init();
uint8_t buf[0x80];
memset(buf, 0xAA, sizeof(buf));
uint32_t ret = twi_read_eeprom(0x1234, buf, sizeof(buf));
printf("read:%ld\n\r", ret);
uint32_t i;
for (i = 0; i < sizeof(buf); i += 16) {
uint32_t j;
for (j = 0; j < 16; j++)
printf("0x%02x ", buf[i +j]);
printf("\n\r");
}
for (i = 0; i < sizeof(buf); i++)
buf[i] ^= 0xFF;
ret = twi_write_eeprom(0x1234, buf, sizeof(buf));
printf("write:%ld\n\r", ret);
// pitc_schedule_timer(&pitc_test_timer);
pitc_schedule_timer(&pitc_test_timer);
// rcontrol_calibrate(RC_CAL_START);
while (1);
}

View File

@ -21,45 +21,132 @@
#include "AT91SAM7S256.h"
#include "board.h"
#include "at91_adc.h"
#include "at91_pitc.h"
static uint16_t adc_result[7];
#define ADC_CAL_COUNT 1024
static uint16_t adc_tmp[7];
static int16_t adc_result[7];
static uint16_t adc_offset[6];
static uint32_t adc_cal_count;
volatile static uint32_t adc_cal_mode;
static uint32_t adc_cal_data[3];
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_RPR = (uint32_t) &adc_tmp;
pdc->PDC_RCR = ARRAY_SIZE(adc_tmp);
pdc->PDC_PTCR = AT91C_PDC_RXTEN;
/* clear interrupts */
AT91S_ADC *adc = AT91C_BASE_ADC;
uint32_t status = adc->ADC_SR;
uint32_t status = *AT91C_ADC_SR;
status = status;
uint32_t i;
for (i = 0; i < ARRAY_SIZE(adc_offset); i++)
adc_result[i] = adc_tmp[i] - adc_offset[i];
/* (adc / 1024) * 3.3V * (11k / 1k) * 100 */
adc_result[ADC_VOLTAGE] = ((uint32_t)adc_tmp[ADC_VOLTAGE] * 3630) / 1024;
}
static uint32_t adc_trigger(struct pitc_timer *timer)
static uint32_t adc_calibrate_cb(struct pitc_timer *timer)
{
uint32_t i;
for (i = 0; i < ARRAY_SIZE(adc_result); i++)
printf("%+4d ", 0x200 - adc_result[i]);
printf("\n\r");
/* trigger next cycle */
*AT91C_ADC_CR = AT91C_ADC_START;
if (adc_cal_mode == ADC_CAL_GYRO) {
adc_cal_data[0] += adc_tmp[ADC_GYRO_ROLL];
adc_cal_data[1] += adc_tmp[ADC_GYRO_NICK];
adc_cal_data[2] += adc_tmp[ADC_GYRO_YAW];
} else {
adc_cal_data[0] += adc_tmp[ADC_ACC_ROLL];
adc_cal_data[1] += adc_tmp[ADC_ACC_NICK];
adc_cal_data[2] += adc_tmp[ADC_ACC_YAW];
}
adc_cal_count--;
if (adc_cal_count == 0) {
adc_cal_data[0] /= ADC_CAL_COUNT;
adc_cal_data[1] /= ADC_CAL_COUNT;
adc_cal_data[2] /= ADC_CAL_COUNT;
adc_cal_mode = 0;
return PITC_REMOVE_TIMER;
}
return PITC_RESTART_TIMER;
}
static struct pitc_timer adc_timer = {
.interval = 100,
.func = &adc_trigger,
static struct pitc_timer adc_cal_timer = {
.interval = 1,
.func = &adc_calibrate_cb,
};
void at91_adc_test_init(void)
void adc_trigger(void)
{
printf("R:%4d N:%4d Y:%4d R:%4d N:%4d Y:%4d U:%4d\n\r",
adc_result[ADC_GYRO_ROLL], adc_result[ADC_GYRO_NICK], adc_result[ADC_GYRO_YAW],
adc_result[ADC_ACC_ROLL], adc_result[ADC_ACC_NICK], adc_result[ADC_ACC_YAW],
adc_result[ADC_VOLTAGE]);
*AT91C_ADC_CR = AT91C_ADC_START;
}
void adc_calibrate(uint32_t mode)
{
if (mode == ADC_CAL_GYRO || mode == ADC_CAL_ACC) {
adc_cal_count = ADC_CAL_COUNT;
adc_cal_mode = mode;
adc_cal_data[0] = 0;
adc_cal_data[1] = 0;
adc_cal_data[2] = 0;
pitc_schedule_timer(&adc_cal_timer);
// wait (1024 * 1ms ~> 1s)
while (adc_cal_mode);
if (mode == ADC_CAL_GYRO) {
adc_offset[ADC_GYRO_ROLL] = adc_cal_data[0];
adc_offset[ADC_GYRO_NICK] = adc_cal_data[1];
adc_offset[ADC_GYRO_YAW] = adc_cal_data[2];
// TODO: check for invalid values (not centered) -> return value?
printf("GYRO offsets: %4d/%4d/%4d\n\r",
adc_offset[ADC_GYRO_ROLL],
adc_offset[ADC_GYRO_NICK],
adc_offset[ADC_GYRO_YAW]);
} else {
adc_offset[ADC_ACC_ROLL] = adc_cal_data[0];
adc_offset[ADC_ACC_NICK] = adc_cal_data[1];
// TODO: only 1/2 offset?
adc_offset[ADC_ACC_YAW] = adc_cal_data[2];
// TODO: save to eeprom
printf("ACC offsets: %4d/%4d/%4d\n\r",
adc_offset[ADC_ACC_ROLL],
adc_offset[ADC_ACC_NICK],
adc_offset[ADC_ACC_YAW]);
}
}
}
void at91_adc_init(void)
{
/* enable ADC clock */
*AT91C_PMC_PCER = (1 << AT91C_ID_ADC);
// TODO: load calibration data from eeprom / use default values
/* ADC Software reset */
AT91S_ADC *adc = AT91C_BASE_ADC;
adc->ADC_CR = AT91C_ADC_SWRST;
@ -80,11 +167,11 @@ void at91_adc_test_init(void)
/* 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_RPR = (uint32_t) &adc_tmp;
pdc->PDC_RCR = ARRAY_SIZE(adc_tmp);
pdc->PDC_PTCR = AT91C_PDC_RXTEN;
/* enable 4 channels, PDC Interrupt */
/* enable 7 channels (0-1-2-4-5-6-7), PDC Interrupt */
adc->ADC_CHER = 0xF7;
adc->ADC_IER = AT91C_ADC_ENDRX;
@ -94,5 +181,7 @@ void at91_adc_test_init(void)
aic->AIC_SVR[AT91C_ID_ADC] = (uint32_t)at91_adc_isr;
aic->AIC_IECR = (1<<AT91C_ID_ADC);
pitc_schedule_timer(&adc_timer);
// TODO: trigger via rc
adc_calibrate(ADC_CAL_GYRO);
adc_calibrate(ADC_CAL_ACC);
}

View File

@ -22,7 +22,6 @@
#include "AT91SAM7S256.h"
#include "board.h"
#include "at91_tc1.h"
#include "at91_pio.h"
/* Hard limits for ISR */
#define PULSE_MIN 0x0500
@ -123,7 +122,7 @@ uint32_t rcontrol_getvalues(struct rc_values *rc)
uint16_t width = (filter) ? ch_data[i].width_slow : ch_data[i].width;
/* expand the value to +/- VALUE_RANGE */
int32_t tmp = (width - ch_data[i].mid) * VALUE_RANGE;
int32_t tmp = (uint32_t)(width - ch_data[i].mid) * VALUE_RANGE;
tmp = tmp / ((tmp > 0) ? (ch_data[i].max - ch_data[i].mid) : (ch_data[i].mid - ch_data[i].min));
/* keep result in range */
@ -207,21 +206,3 @@ void at91_tc1_init(void)
aic->AIC_SVR[AT91C_ID_TC1] = (uint32_t)ppm_isr;
aic->AIC_IECR = (1 << AT91C_ID_TC1);
}
static void tast_monitor(uint32_t status, uint32_t input)
{
if (!(input & TAST1) && (cal_in_progress == 0)) {
printf("start calibration\n\r");
rcontrol_calibrate(RC_CAL_START);
} else if (!(input & TAST2) && (cal_in_progress == 1)) {
printf("end calibration\n\r");
rcontrol_calibrate(RC_CAL_END);
rcontrol_print_cal();
}
}
PIO_PINCHANGE_ISR(TAST1 | TAST2, tast_monitor);