#include <avr/io.h>
#include <avr/interrupt.h>
// Constants for button debounce
#define DEBOUNCE_TIME 150 // in milliseconds
volatile int intensity = 0; // Duty cycle of PWM (0-255)
volatile bool updateDisplay = false; // Flag to update 7-segment display
const uint8_t segmentMap[10] = {
0x3F, // 0 0b 0011 1111 dGFE DCBA << segment addresses
0x06, // 1 0b 0000 0110
0x5B, // 2 0b 0101 1011
0x4F, // 3 0b 0100 1111
0x66, // 4 0b 0110 0110
0x6D, // 5 0b 0110 1101
0x7D, // 6 0b 0111 1101
0x07, // 7 0b 0000 0111
0x7F, // 8 0b 0111 1111
0x6F // 9 0b 0110 1111
};
void setup() {
//Initialize Outputs
DDRD |= 0xF0; //0xF0 Initialize DDRD ports 4 - 7 as outputs
DDRB |= 0x0F; //0x0D Initialize DDRB ports 0 - 3 as outputs
update7SegmentDisplay(); // Initialize display to 0
// Initialize PWM on pin D9
// TCCR1A = (1 << WGM10) | (1 << COM1A1); //Set Waveform Generation Mode (WGM)bit from 0 to 1
TCCR1A = 0x81;
// TCCR1B = (1 << CS11) | (1 << CS10); // Prescaler 64
TCCR1B = 0x03;
OCR1A = 0; // Initial duty cycle at 0 for LED
// Initialise Interrupt (Buttons)
EICRA = 0x0A;
EIMSK = 0x03;
sei(); // Enable global interrupts
}
// Update 7-segment display for common anode
void update7SegmentDisplay() {
uint8_t segments = segmentMap[intensity];
// Using PORTD for pins 4-7 and PORTB for pins 8, 10, 11
// Segment A (PD4)
if (segments & 0b00000001)
PORTD &= ~(1 << PD4); // LOW
else PORTD |= (1 << PD4); // HIGH
// Segment B (PD5)
if (segments & 0b00000010)
PORTD &= ~(1 << PD5); // LOW
else PORTD |= (1 << PD5); // HIGH
// Segment C (PD6)
if (segments & 0b00000100)
PORTD &= ~(1 << PD6); // LOW
else PORTD |= (1 << PD6); // HIGH
// Segment D (PD7)
if (segments & 0b00001000)
PORTD &= ~(1 << PD7); // LOW
else PORTD |= (1 << PD7); // HIGH
// Segment E (PB0)
if (segments & 0b00010000)
PORTB &= ~(1 << PB0); // LOW
else PORTB |= (1 << PB0); // HIGH
// Segment F (PB2)
if (segments & 0b00100000)
PORTB &= ~(1 << PB2); // LOW
else PORTB |= (1 << PB2); // HIGH
// Segment G (PB3)
if (segments & 0b01000000)
PORTB &= ~(1 << PB3); // LOW
else PORTB |= (1 << PB3); // HIGH
updateDisplay = false;
}
// Interrupt Service Routine for INT0
ISR(INT0_vect) {
static unsigned long lastInterruptTime0 = 0;
unsigned long interruptTime = millis();
if (interruptTime - lastInterruptTime0 > DEBOUNCE_TIME) {
if (intensity < 9) intensity += 1;
OCR1A = intensity * 28;
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 (intensity > 0) intensity -= 1;
OCR1A = intensity * 28;
updateDisplay = true;
lastInterruptTime1 = interruptTime;
}
}
void loop() {
if (updateDisplay) {
update7SegmentDisplay(); // Display the step 0-9
}
}