mixer-slider/firmware/slider/adc.c
2019-02-09 21:33:45 +01:00

76 lines
1.3 KiB
C

/*
* adc.c
*
* Created on: 08.02.2019
* Author: julian
*/
#include "adc.h"
#include <avr/io.h>
#include <avr/interrupt.h>
#include "led.h"
// global adc instance
volatile adc_t adc;
static inline void adc_next() {
do {
adc.current_channel = (adc.current_channel+1)%8;
if (!adc.current_channel) {
adc.current_sample = adc.buffer.ptr-1;
if (adc.interrupt)
adc.interrupt(&adc.buffer);
}
} while(!(adc.channel_mask & (1<<adc.current_channel)));
if (adc.current_sample < (adc.buffer.ptr + adc.buffer.size)) {
adc.current_sample++;
}
// set mux input
ADMUX = adc.current_channel;
}
void adc_on_done(adc_interrupt_t interrupt) {
adc.interrupt = interrupt;
}
/* adc driver */
void adc_init(adc_buffer_t buffer, uint8_t mask) {
if (!mask) {
return;
}
adc.buffer = buffer;
adc.current_sample = adc.buffer.ptr;
adc.channel_mask = mask;
adc.current_channel = 0;
// find first channel
while(!((1<<adc.current_channel) & mask)) {
adc.current_channel++;
}
adc.interrupt = 0;
ADMUX = 0;
ADCSRA = (1<<ADATE) | (1<<ADEN) ; // enable adc, maximum prescaler value
}
void adc_start() {
ADCSRA |= (1<<ADIE) | (1<<ADSC); // enable adc interrupt
}
void adc_stop( ){
ADCSRA &= ~(1<<ADIE);
}
ISR(ADC_vect) {
*adc.current_sample = ADC;
adc_next();
}