123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081 |
- #include "adc.h"
- #include <stdio.h>
- #include <avr/io.h>
- #include <avr/interrupt.h>
- #include <avr/pgmspace.h>
- #include <string.h>
- #include "pins.h"
- static uint8_t adc_count; //used for oversampling
- static uint8_t adc_channel_idx; //bitmask index
- volatile uint8_t adc_channel; //regular index
- volatile uint16_t adc_values[ADC_CHAN_CNT];
- static void adc_reset();
- static void adc_setmux(uint8_t ch);
- void adc_init()
- {
- puts_P(PSTR("adc_init"));
- DIDR0 = ((ADC_CHAN_MSK & ADC_DIDR_MSK) & 0xff); //disable digital inputs PORTF
- DIDR2 = ((ADC_CHAN_MSK & ADC_DIDR_MSK) >> 8); //disable digital inputs PORTK
- ADMUX |= (1 << REFS0); //use AVCC as reference
- //enable ADC, set prescaler/128, enable interrupt
- ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0) | (1 << ADIF) | (1 << ADIE);
- }
- static void adc_reset()
- {
- static const uint8_t first_channel_idx = 0;
- static_assert((1 << first_channel_idx) & ADC_CHAN_MSK);
- ADCSRA &= ~(1 << ADSC); //stop conversion just in case
- adc_count = 0;
- adc_channel = 0;
- adc_channel_idx = first_channel_idx;
- adc_setmux(adc_channel_idx);
- memset((void*)adc_values, 0, sizeof(adc_values));
- }
- static void adc_setmux(uint8_t ch)
- {
- ch &= 0x0f;
- if (ch & 0x08) ADCSRB |= (1 << MUX5);
- else ADCSRB &= ~(1 << MUX5);
- ADMUX = (ADMUX & ~(0x07)) | (ch & 0x07);
- }
- void adc_start_cycle() {
- adc_reset();
- ADCSRA |= (1 << ADSC); //start conversion
- }
- #ifdef ADC_CALLBACK
- extern void ADC_CALLBACK();
- #endif //ADC_CALLBACK
- ISR(ADC_vect)
- {
- adc_values[adc_channel] += ADC;
- if (++adc_count == ADC_OVRSAMPL)
- {
- // go to the next channel
- if (++adc_channel == ADC_CHAN_CNT) {
- #ifdef ADC_CALLBACK
- ADC_CALLBACK();
- #endif
- return; // do not start the next measurement since there are no channels remaining
- }
- // find the next channel
- while (++adc_channel_idx) {
- if (ADC_CHAN_MSK & (1 << adc_channel_idx)) {
- adc_setmux(adc_channel_idx);
- adc_count = 0;
- break;
- }
- }
- }
- ADCSRA |= (1 << ADSC); //start conversion
- }
|