/** Simple register manipulation example ***
*** Using timed interrupt and ADC ***
*** Author: Oscar Oomens **/
long mapCorrect(long x, long in_min, long in_max, long out_min, long out_max)
{
return (x - in_min) * (out_max - out_min + 1) / (in_max - in_min + 1) + out_min;
}
void setup() {
// Disable interrupts
cli();
// Control register reset for TIMER 1
TCCR1A = 0;
TCCR1B = 0;
// Set prescaler (CS12 bit) to 256
TCCR1B |= (1 << CS12);
// Set CTC (Clear timer on compare)
TCCR1B |= (1 << WGM12);
// Set "output compare A match interrupt enable"
TIMSK1 |= (1 << OCIE1A);
// Set match reg
OCR1A = 31250 / 2;
// Set (declare pins as) outputs
DDRB |= B00011111;
DDRD |= B11111000;
// Reset pins and timer counter
PORTB &= !B00011111;
PORTD &= !B11111000;
TCNT1 = 0;
// Re-enable interrupts
sei();
}
void loop() {
ADMUX |= B00000100; // Set MUX to A4
ADMUX |= B01000000; // REFS1 and REFS0 to set reference voltage to VCC (5V)
ADCSRA |= B11000000; // ADEN and ADSC to 1 to start conversion
while(bit_is_set(ADCSRA, ADSC));
int value = ADCL | (ADCH << 8);
// Map pot value from 32 to 500ms
value = mapCorrect(value, 0, 1023, 2000, 31250);
OCR1A = value / 2;
}
ISR(TIMER1_COMPA_vect) {
static int counter = 0;
// Reset pins
PORTB &= !B00011111;
PORTD &= !B11111000;
if (counter < 5) {
PORTD |= (1 << counter + 3);
} else {
PORTB |= (1 << counter - 5);
}
counter = (counter + 1) % 10;
}