#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
// Traffic Light Pins
#define PR_GREEN PB0 // Park Road Green
#define PR_YELLOW PB1 // Park Road Yellow
#define PR_RED PB2 // Park Road Red
#define RS_GREEN PB3 // Railway Street Green
#define RS_YELLOW PB4 // Railway Street Yellow
#define RS_RED PB5 // Railway Street Red
#define DS_GREEN PC1 // Dam Street Green
#define DS_YELLOW PC2 // Dam Street Yellow
#define DS_RED PC3 // Dam Street Red
// Sensor Pins (Active-Low Buttons)
#define S0 PD2 // Hazard Input
#define S1 PD3
#define S2 PC4
#define S3 PC5
// States
typedef enum {
HAZARD,
PRT, // Park Road Through
RST, // Railway Street Through
DST // Dam Street Through
} Phase;
// Global Variables
volatile Phase currentPhase = HAZARD;
volatile uint8_t sensors = 0;
volatile uint16_t timePeriod = 1000; // Default: 1s
volatile uint32_t phaseTimer = 0;
volatile uint32_t systemTime = 0;
volatile uint8_t hazardFlag = 0;
// Initialize Hardware
void init_hardware() {
// Set sensor pins as inputs with pull-ups
DDRD &= ~((1 << S0) | (1 << S1));
DDRC &= ~((1 << S2) | (1 << S3));
PORTD |= (1 << S0) | (1 << S1);
PORTC |= (1 << S2) | (1 << S3);
// Set traffic light pins as outputs
DDRB |= (1 << PR_GREEN) | (1 << PR_YELLOW) | (1 << PR_RED) |
(1 << RS_GREEN) | (1 << RS_YELLOW) | (1 << RS_RED);
DDRC |= (1 << DS_GREEN) | (1 << DS_YELLOW) | (1 << DS_RED);
// ADC for potentiometer (PC0)
ADMUX = (1 << REFS0); // AVCC reference, ADC0
ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1); // Enable ADC, prescaler=64
// Timer1 for phase timing (1ms interrupt)
TCCR1B = (1 << WGM12) | (1 << CS11); // CTC mode, prescaler=8
OCR1A = 125; // 1ms interrupt @ 1MHz
TIMSK1 = (1 << OCIE1A);
}
// Timer1 Interrupt (Updates time period and system clock)
ISR(TIMER1_COMPA_vect) {
static uint16_t adcCounter = 0;
if (++adcCounter >= 1000) { // Read ADC every 1s
ADCSRA |= (1 << ADSC);
while (ADCSRA & (1 << ADSC));
uint16_t adcValue = ADC;
timePeriod = 50 + (adcValue * 950) / 1023; // Map to 50ms-1000ms
adcCounter = 0;
}
phaseTimer++;
systemTime++;
}
// Read Sensors (Active-Low)
uint8_t read_sensors() {
uint8_t sensorState = 0;
if (!(PIND & (1 << S0))) sensorState |= (1 << 0);
if (!(PIND & (1 << S1))) sensorState |= (1 << 1);
if (!(PINC & (1 << S2))) sensorState |= (1 << 2);
if (!(PINC & (1 << S3))) sensorState |= (1 << 3);
Serial.println(sensorState);
return sensorState;
}
// Control Traffic Lights
void set_lights(Phase phase) {
// Turn off all lights first
PORTB &= ~((1 << PR_GREEN) | (1 << PR_YELLOW) | (1 << PR_RED) |
(1 << RS_GREEN) | (1 << RS_YELLOW) | (1 << RS_RED));
PORTC &= ~((1 << DS_GREEN) | (1 << DS_YELLOW) | (1 << DS_RED));
switch (phase) {
case HAZARD:
Serial.println("Flash yellow lights");
// Flash yellow lights
if (phaseTimer % 2000 < 1000) {
PORTB |= (1 << PR_YELLOW) | (1 << RS_YELLOW);
PORTC |= (1 << DS_YELLOW);
}
break;
case PRT:
Serial.println("Park Road green, others red");
// Park Road green, others red
PORTB |= (1 << PR_GREEN);
PORTC |= (1 << DS_RED);
PORTB |= (1 << RS_RED);
break;
case RST:
Serial.println("Railway Street green, others red");
// Railway Street green, others red
PORTB |= (1 << RS_GREEN);
PORTC |= (1 << DS_RED);
PORTB |= (1 << PR_RED);
break;
case DST:
Serial.println("Dam Street green, others red");
// Dam Street green, others red
PORTC |= (1 << DS_GREEN);
PORTB |= (1 << PR_RED) | (1 << RS_RED);
break;
}
}
// State Machine Logic
void run_state_machine() {
static uint8_t lastPhase = HAZARD;
// Hazard mode override
if (sensors & (1 << 0)) { // S6 grounded
hazardFlag = 1;
currentPhase = HAZARD;
phaseTimer = 0;
set_lights(HAZARD);
return;
}
// Exit hazard after 10s
if (hazardFlag && phaseTimer >= 10000) {
hazardFlag = 0;
currentPhase = PRT;
phaseTimer = 0;
}
// Normal operation
if (!hazardFlag) {
switch (currentPhase) {
case PRT:
if (phaseTimer >= (4 * timePeriod)) {
if (sensors & ((1 << 2) | (1 << 3) | (1 << 4))) { // RST or DST sensors
if (lastPhase != RST) currentPhase = RST;
else currentPhase = DST; // Avoid repeats
phaseTimer = 0;
}
}
break;
case RST:
if (phaseTimer >= (2 * timePeriod)) {
if (sensors & (1 << 4)) { // DST sensor
currentPhase = DST;
phaseTimer = 0;
} else if (phaseTimer >= (3 * timePeriod)) {
currentPhase = PRT;
phaseTimer = 0;
}
}
break;
case DST:
if (phaseTimer >= (2 * timePeriod)) {
if (sensors & ((1 << 0) | (1 << 1))) { // PRT sensors
currentPhase = PRT;
phaseTimer = 0;
} else if (phaseTimer >= (4 * timePeriod)) {
currentPhase = PRT;
phaseTimer = 0;
}
}
break;
}
lastPhase = currentPhase;
set_lights(currentPhase);
}
}
int main(void) {
Serial.begin(115200);
// Initialize hardware
init_hardware();
// Enable global interrupts
sei();
_delay_ms(1000);
while (1) {
// Read sensors
sensors = read_sensors();
// Run state machine
run_state_machine();
// Small delay for debounce
_delay_ms(100);
}
return 0;
}