#include <avr/io.h>
#include <avr/interrupt.h>
#define DEBOUNCE_TIME 500 // Constants for button debounce (in milliseconds)
volatile int intensity = 0; // Intensity (0-9)
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
};
// Update 7-segment display for common anode
void writeToDisplayPinD(int pin, uint8_t segments, int LEDhex) {
if (segments & LEDhex) PORTD &= ~(1 << pin); // Set the pin LOW
else PORTD |= (1 << pin); // Set the pin HIGH
}
void writeToDisplayPinB(int pin, uint8_t segments, int LEDhex) {
if (segments & LEDhex) PORTB &= ~(1 << pin); // Set the pin LOW
else PORTB |= (1 << pin); // Set the pin HIGH
// if (segments & 0x01) {
// PORT_REG &= ~(1 << PIN_NUMBER); // Set the pin LOW
// } else {
// PORT_REG |= (1 << PIN_NUMBER); // Set the pin HIGH
// }
}
void update7SegmentDisplay() {
uint8_t segments = segmentMap[intensity];
writeToDisplayPinD(4, segments, 0x01);
writeToDisplayPinD(5, segments, 0x02);
writeToDisplayPinD(6, segments, 0x04);
writeToDisplayPinD(7, segments, 0x08);
// writeToDisplayPinB(8, segments, 0x01);
// writeToDisplayPinB(10, segments, 0x02);
// writeToDisplayPinB(11, segments, 0x04);
digitalWrite(8, segments & 0x10 ? LOW : HIGH); // Segment e
digitalWrite(10, segments & 0x20 ? LOW : HIGH); // Segment f
digitalWrite(11, segments & 0x40 ? LOW : HIGH); // Segment g
}
// 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 setup() {
// Initialise the 7 segment display pins as Outputs
DDRD |= (1 << PD4) | (1 << PD5) | (1 << PD6) | (1 << PD7);
DDRB |= (1 << PB0) | (1 << PB2) | (1 << PB3);
update7SegmentDisplay(); // Initialize display to 0
// Initialise the LED pin as Output
DDRB |= (1 << PB1);
// Initialize PWM on pin D9
TCCR1A = (1 << WGM10) | (1 << COM1A1);
TCCR1B = (1 << CS11) | (1 << CS10); // Prescaler 64
OCR1A = 0; // Initial duty cycle
// Initialise Interrupt (Buttons)
EICRA = (1 << ISC01) | (0 << ISC00) | (1 << ISC11) | (0 << ISC10); // Rising edge for INT0 and INT1
EIMSK = (1 << INT0) | (1 << INT1); // Enable INT0 and INT1
sei(); // Enable global interrupts
}
void loop() {
if (updateDisplay) {
update7SegmentDisplay(); // Display the step 0-9
}
}