volatile uint16_t redValue, greenValue;
volatile uint16_t redLevel, greenLevel;
volatile bool redbutton, greenbutton;
// Interrupt Service Routine for Timer1 Compare Match A
ISR(TIMER1_COMPA_vect)
{
OCR1A = redLevel; // Set the output compare register for the RED LED PWM
}
// Interrupt Service Routine for Timer1 Compare Match B
ISR(TIMER1_COMPB_vect)
{
OCR1B = greenLevel; // Set the output compare register for the GREEN LED PWM
}
// Interrupt Service Routine for ADC Conversion Complete
ISR(ADC_vect)
{
if (ADCSRA &= ~(1 << ADSC)) { // Check if ADC conversion is complete
if (ADMUX == 0x40) { // Check if we are reading from the RED LED potentiometer
redValue = ADC; // Read the ADC value for the RED LED
redLevel = mapADC(redValue); // Map the ADC value to the PWM duty cycle for the RED LED
ADMUX = 0x41; // Switch to reading from the GREEN LED potentiometer
} else { // We are reading from the GREEN LED potentiometer
greenValue = ADC; // Read the ADC value for the GREEN LED
greenLevel = mapADC(greenValue); // Map the ADC value to the PWM duty cycle for the GREEN LED
ADMUX = 0x40; // Switch to reading from the RED LED potentiometer
}
ADCSRA |= (1 << ADSC); // Start the next ADC conversion
}
}
// Function to map the ADC value to the PWM duty cycle
uint16_t mapADC(uint16_t x) {
return (1+((uint32_t)x * 50000 ) / 1023) ; // Map the ADC value from 0-1023 to 1-65536 (1-100% duty cycle)
}
// Main function
int main()
{
// Set the Input/Output pins
DDRD &= ~(1 << PD2); // Set PD2 (RED LED switch) as input
DDRD &= ~(1 << PD3); // Set PD3 (GREEN LED switch) as input
DDRD &= ~(1 << PD4); // Set PD4 (BLUE LED switch) as input
DDRB |= (1 << PB1); // Set PB1 (OC1A) as output for the RED LED PWM
DDRB |= (1 << PB2); // Set PB1 (OC1B) as output for the GREEN LED PWM
DDRB |= (1 << PB4); // Set PB3 as output for the BLUE LED (without PWM)
// Set up Timer1 for PWM with overflow interrupt
TCCR1A |= (1 << WGM11) | (1 << COM1A1) | (1 << COM1B1); // Fast PWM mode, Non-inverting
TCCR1B |= (1 << WGM12) | (1 << WGM13) | (1 << CS10); // Fast PWM mode, No Prescaler
ICR1 = 39999; // Set the frequency to 200Hz
TIMSK1 |= (1 << OCIE1A); // Enable Timer1 Compare Match A Interrupt
TIMSK1 |= (1 << OCIE1B); // Enable Timer1 Compare Match B Interrupt
// Set up ADC Channel0 and ADC Channel1 for potentiometer reads
ADMUX = 0x40; // Set reference voltage to AVcc with external capacitor at AREF pin
// enable ADC, enable interrupt, set prescaler to 128
ADCSRA = (1 << ADEN) | (1 << ADIE) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);
ADCSRA |= (1 << ADSC); // start first conversion
// Set RGB LED pins as outputs
// Enable interrupts
sei();
// Loop forever
while (1)
{
if(PIND & (1<<PD2)) // Check if RED LED button is ON
DDRB |= (1 << PB1); // Turn ON RED LED
else
DDRB &= ~(1 << PB1); // Turn OFF RED LED
if(PIND & (1<<PD3)) // Check if GREEN LED button is ON
DDRB |= (1 << PB2); // Turn ON GREEN LED
else
DDRB &= ~(1 << PB2); // Turn OFF GREEN LED
if(PIND & (1<<PD4)) // Check if BLUE LED button is ON
PORTB |= (1 << PB4); // Turn ON BLUE LED
else
PORTB &= ~(1 << PB4); // Turn OFF BLUE LED
}
}