#include <avr/io.h>
#include <avr/interrupt.h>
// Constants for button debounce
#define DEBOUNCE_TIME 5 // in milliseconds
volatile int dutyCycle = 0; // Duty cycle of PWM (0-255)
volatile bool updateDisplay = false; // Flag to update 7-segment display
const uint8_t segmentMap[10] = {
0b00111111, // 0
0b00000110, // 1
0b01011011, // 2
0b01001111, // 3
0b01100110, // 4
0b01101101, // 5
0b01111101, // 6
0b00000111, // 7
0b01111111, // 8
0b01101111 // 9
};
// Initialize PWM on pin D9
void initPWM() {
pinMode(9, OUTPUT);
TCCR1A = (1 << WGM10) | (1 << COM1A1);
TCCR1B = (1 << CS11) | (1 << CS10); // Prescaler 64
OCR1A = 0; // Initial duty cycle
}
// Initialize interrupts for buttons
void initInterrupts() {
EICRA = (1 << ISC01) | (1 << ISC00) | (1 << ISC11) | (1 << ISC10); // Rising edge for INT0 and INT1
EIMSK = (1 << INT0) | (1 << INT1); // Enable INT0 and INT1
sei(); // Enable global interrupts
}
// Update 7-segment display
void update7SegmentDisplay(int value) {
PORTD = segmentMap[value % 10]; // Display single digit 0-9
}
// Interrupt Service Routine for INT0
ISR(INT0_vect) {
static unsigned long lastInterruptTime0 = 0;
unsigned long interruptTime = millis();
if (interruptTime - lastInterruptTime0 > DEBOUNCE_TIME) {
if (dutyCycle < 255) dutyCycle += 28;
if (dutyCycle > 255) dutyCycle = 255;
OCR1A = dutyCycle;
updateDisplay = true;
lastInterruptTime0 = interruptTime;
}
}
// Interrupt Service Routine for INT1
ISR(INT1_vect) {
static unsigned long lastInterruptTime1 = 0;
unsigned long interruptTime = millis();
if (interruptTime - lastInterruptTime1 > DEBOUNCE_TIME) {
if (dutyCycle > 0) dutyCycle -= 28;
if (dutyCycle < 0) dutyCycle = 0;
OCR1A = dutyCycle;
updateDisplay = true;
lastInterruptTime1 = interruptTime;
}
}
void setup() {
// Set up 7-segment display pins
DDRD = 0xFF; // Set PORTD as output for 7-segment display
initPWM();
initInterrupts();
}
void loop() {
if (updateDisplay) {
update7SegmentDisplay(dutyCycle / 28); // Display the step 0-9
updateDisplay = false;
}
}
// #include <avr/io.h>
// #include <util/delay>
// #include <avr/interrupt.h>
// #include <avr/io.h>
// // #include <LiquidCrystal_I2C.h>
// // LiquidCrystal_I2C lcd(0x27, 16, 2);
// ISR(PCINT2_vect) {
// //inputs are active low
// uint8_t pd = ~PIND;
// if (pd & 0x80)//we need to determine which pin generated interrupt
// PORTB |= 1 << PB1;
// else if (pd & 0x40)
// PORTB &= ~(1 << PB1);
// }
// float read_adc() {
// ADCSRA |= (1 << ADSC); // Start the Conversion
// while (ADCSRA & (1 << ADSC)); // Wait for Conversion to Complete
// uint16_t adcValue = ADC; // Read the ADC Value
// int brightness = adcValue / (1023 / 9);
// return brightness;
// }
// volatile float brightness = 0.0;
// volatile int state=LOW;
// byte bit5;
// void print_brightness() {
// }
// void setup() {
// // PORTD = 1 << PD2;//interal pull up
// // brightness = read_adc();
// // print_brightness();
// DDRD &= ~((1 << PD7) | (1 << PD6)) ;//port D as input
// PORTD = (1 << PD7) | (1 << PD6);//use pull up resistors PORTD6 and 7
// DDRB= 1 << PB1;//output port bit
// PORTD = 0x04;//configure to use pull up resistor
// /* set PORTB BIT IN PIN 13 as output */
// DDRB |= 0x20;// DDRB5 pin 13 as output
// // Enable pin change interrupts
// PCICR = 1 << PCIE2; //enable pin change interrupt bank 2
// PCMSK2 = (1 << PCINT22) | (1 << PCINT23); //enable pin change interrupt on PCINT22 PCINT23
// sei();// Set global interrupt flag
// }
// int main() {
// init();
// setup();
// // while(true) {
// // float new_brightness = read_adc();
// // if (new_brightness != brightness) {
// // brightness = new_brightness;
// // print_brightness();
// // }
// // }
// // DDRD = 0x40; //PORTD bit 2 as input
// EIMSK |= 0b00000001;//Enable ext interrupt INT0
// EICRA |= 0b00000010;//Trig. INT0 on falling edge
// bit5 = 1 << 5;//set bit 5 to 1 shifting 5 times
// sei();//Enable interrupts
// while (true) {
// PORTB = state;//change state
// }
// }