From bf92ffb5bff9eedb36df697397b9a6ae27bc168e Mon Sep 17 00:00:00 2001 From: Kevin O'Connor Date: Tue, 20 Nov 2018 11:39:42 -0500 Subject: avr: Split gpio.c into gpio.c, adc.c, hard_pwm.c, and spi.c Split up gpio.c into multiple files in an effort to make the code a little more understandable. Signed-off-by: Kevin O'Connor --- src/avr/adc.c | 117 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 src/avr/adc.c (limited to 'src/avr/adc.c') diff --git a/src/avr/adc.c b/src/avr/adc.c new file mode 100644 index 00000000..3087dce1 --- /dev/null +++ b/src/avr/adc.c @@ -0,0 +1,117 @@ +// Analog to Digital Converter support +// +// Copyright (C) 2016-2018 Kevin O'Connor +// +// This file may be distributed under the terms of the GNU GPLv3 license. + +#include "autoconf.h" // CONFIG_MACH_atmega644p +#include "command.h" // shutdown +#include "gpio.h" // gpio_adc_read +#include "internal.h" // GPIO +#include "pgm.h" // PROGMEM +#include "sched.h" // sched_shutdown + +static const uint8_t adc_pins[] PROGMEM = { +#if CONFIG_MACH_atmega168 || CONFIG_MACH_atmega328 || CONFIG_MACH_atmega328p + GPIO('C', 0), GPIO('C', 1), GPIO('C', 2), GPIO('C', 3), + GPIO('C', 4), GPIO('C', 5), GPIO('E', 0), GPIO('E', 1), +#elif CONFIG_MACH_atmega644p || CONFIG_MACH_atmega1284p + GPIO('A', 0), GPIO('A', 1), GPIO('A', 2), GPIO('A', 3), + GPIO('A', 4), GPIO('A', 5), GPIO('A', 6), GPIO('A', 7), +#elif CONFIG_MACH_at90usb1286 || CONFIG_MACH_at90usb646 + GPIO('F', 0), GPIO('F', 1), GPIO('F', 2), GPIO('F', 3), + GPIO('F', 4), GPIO('F', 5), GPIO('F', 6), GPIO('F', 7), +#elif CONFIG_MACH_atmega32u4 + GPIO('F', 0), GPIO('F', 1), GPIO('F', 2), GPIO('F', 3), + GPIO('F', 4), GPIO('F', 5), GPIO('F', 6), GPIO('F', 7), + GPIO('D', 4), GPIO('D', 6), GPIO('D', 7), GPIO('B', 4), +#elif CONFIG_MACH_atmega1280 || CONFIG_MACH_atmega2560 + GPIO('F', 0), GPIO('F', 1), GPIO('F', 2), GPIO('F', 3), + GPIO('F', 4), GPIO('F', 5), GPIO('F', 6), GPIO('F', 7), + GPIO('K', 0), GPIO('K', 1), GPIO('K', 2), GPIO('K', 3), + GPIO('K', 4), GPIO('K', 5), GPIO('K', 6), GPIO('K', 7), +#endif +}; + +enum { ADMUX_DEFAULT = 0x40 }; +enum { ADC_ENABLE = (1<= ARRAY_SIZE(adc_pins)) + shutdown("Not a valid ADC pin"); + if (READP(adc_pins[chan]) == pin) + break; + } + + // Enable ADC + ADCSRA = ADC_ENABLE; + + // Disable digital input for this pin +#ifdef DIDR2 + if (chan >= 8) + DIDR2 |= 1 << (chan & 0x07); + else +#endif + DIDR0 |= 1 << chan; + + return (struct gpio_adc){ chan }; +} + +enum { ADC_DUMMY=0xff }; +static uint8_t last_analog_read = ADC_DUMMY; + +// Try to sample a value. Returns zero if sample ready, otherwise +// returns the number of clock ticks the caller should wait before +// retrying this function. +uint32_t +gpio_adc_sample(struct gpio_adc g) +{ + if (ADCSRA & (1<> 3) & 0x01) << MUX5; +#endif + ADMUX = ADMUX_DEFAULT | (g.chan & 0x07); + + // Start the sample + ADCSRA = ADC_ENABLE | (1<