From c3f4417efaa489c41e5d5d44fb28ae01e65ff6bc Mon Sep 17 00:00:00 2001 From: Omar Magdy Date: Thu, 25 Aug 2022 02:24:01 +0200 Subject: Fixed a bug of the pedestrain traffic timer where it would restart from 5 to 1 again and Added comments for the whole project and added timers as a member of the Traffic struct to add more generlization of the --- main.c | 21 +++++----- trafficlight.c | 121 +++++++++++++++++++++++++++++++++++++-------------------- trafficlight.h | 39 ++++++++++--------- 3 files changed, 109 insertions(+), 72 deletions(-) diff --git a/main.c b/main.c index afbcce7..2d412b6 100644 --- a/main.c +++ b/main.c @@ -1,24 +1,23 @@ #include "trafficlight.h" -uint32_t period_1 = RED_PERIOD; -uint32_t period_2 = GREEN_PERIOD; -uint32_t period_3 = GREEN_PERIOD; -bool switch_pressed = false; +uint32_t period_1 = RED_PERIOD; // Intial period of tf1 +uint32_t period_2 = GREEN_PERIOD; // Intial period of tf2 +uint32_t period_3 = 0; // Intial peroid of tf_ped -//Traffics -Traffic tf1 = {RED , GPIO_PORTA_BASE, 2, 3, 4}; -Traffic tf2 = {YELLOW, GPIO_PORTF_BASE, 1, 2, 3}; -Traffic tf_ped = {RED , GPIO_PORTB_BASE, 5, 0, 7}; +bool switch_pressed = false; //Decoders Bcd bcd1 = {GPIO_PORTE_BASE, 1, 2, 3, 5}; Bcd bcd2 = {GPIO_PORTD_BASE, 1, 2, 3, 6}; Bcd bcd_ped = {GPIO_PORTA_BASE, 5, 6, 7, 4}; // (5, 6, 7) A and 4 of E +//Traffics +Traffic tf1 = {RED , GPIO_PORTA_BASE, 2, 3, 4, TIMER0_BASE}; +Traffic tf2 = {YELLOW, GPIO_PORTF_BASE, 1, 2, 3, TIMER1_BASE}; +Traffic tf_ped = {RED , GPIO_PORTB_BASE, 5, 0, 7, TIMER2_BASE}; + + int main() { TrafficInit(); - // PortInit(GPIO_PORTE_BASE, SYSCTL_PERIPH_GPIOE, 0x0, 0xFF); // Initialize porta - // GPIOPinWrite(GPIO_PORTE_BASE, 0xFF, 0); - // GPIOPinWrite(GPIO_PORTE_BASE, 0xFF, (1 << 1) | (1 << 2)); } diff --git a/trafficlight.c b/trafficlight.c index c46ae48..969ffae 100644 --- a/trafficlight.c +++ b/trafficlight.c @@ -1,5 +1,8 @@ #include "trafficlight.h" +/* + Function to handle the state machine of each traffic light +*/ void set_tf_color(Traffic tf, uint8_t color) { uint32_t pins = 0xFF; switch (color) { @@ -15,6 +18,9 @@ void set_tf_color(Traffic tf, uint8_t color) { } } +/* + Function that takes port base address and the clk of the port and the corresponding input and output pins +*/ void PortInit(uint32_t port, uint32_t clk, uint32_t input, uint32_t output) { uint32_t pins = 0xFF; SysCtlPeripheralEnable(clk); @@ -26,6 +32,18 @@ void PortInit(uint32_t port, uint32_t clk, uint32_t input, uint32_t output) { GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU); } +void portsInit() { + PortInit(GPIO_PORTA_BASE, SYSCTL_PERIPH_GPIOA, 0x0, 0xFF); // Initialize porta as all output + PortInit(GPIO_PORTB_BASE, SYSCTL_PERIPH_GPIOB, 0x0, 0xFF); // Initialize portb as all output + PortInit(GPIO_PORTD_BASE, SYSCTL_PERIPH_GPIOD, 0x0, 0xFF); // Initialize portb as all output + PortInit(GPIO_PORTE_BASE, SYSCTL_PERIPH_GPIOE, 0x0, 0xFF); // Initialize portb as all output + PortInit(GPIO_PORTF_BASE, SYSCTL_PERIPH_GPIOF, 0x1, 0x7E); // Initialize portf as the first pin input and the rest output +} + +/* + Function that takes a timer address and the function that handler the timer interrupt flag, + the clock of the timer and the intial delay of the timer +*/ void TimerInit(uint32_t timer, void(*timer_handler)(), uint32_t clk, uint32_t delay) { SysCtlPeripheralEnable(clk); while(!SysCtlPeripheralReady(clk)) {} @@ -38,35 +56,45 @@ void TimerInit(uint32_t timer, void(*timer_handler)(), uint32_t clk, uint32_t de TimerIntEnable(timer, TIMER_TIMA_TIMEOUT | TIMER_TIMB_TIMEOUT); } +/* + Function that handles traffic_1 timer +*/ void Timer0_Handler() { - Traffic_Handler(&tf1, TIMER0_BASE); + Traffic_Handler(&tf1); } +/* + Function that handles traffic_2 timer +*/ void Timer1_Handler() { - Traffic_Handler(&tf2, TIMER1_BASE); + Traffic_Handler(&tf2); } +/* + Function that handles pedestrian traffic timer +*/ void Timer2_Handler() { - TimerIntClear(TIMER2_BASE, TIMER_BOTH); + TimerIntClear(tf_ped.timer, TIMER_BOTH); switch(tf_ped.cur_color) { - case RED: + case RED: // If I am here it means I finished my red period tf_ped.cur_color = GREEN; set_tf_color(tf_ped, GREEN); - TimerLoadSet(TIMER2_BASE, TIMER_BOTH, GREEN_PERIOD); + TimerLoadSet(tf_ped.timer, TIMER_BOTH, GREEN_PERIOD); break; - case YELLOW: + case YELLOW: // If I am here it means I finished my yellow period + // set both traffic1 and traffic2 to their previous color before the pedestrian pushed the button set_tf_color(tf1, tf1.cur_color); set_tf_color(tf2, tf2.cur_color); set_tf_color(tf_ped, RED); - TimerEnable(TIMER0_BASE, TIMER_BOTH); - TimerEnable(TIMER1_BASE, TIMER_BOTH); - // TimerDisable(TIMER2_BASE, TIMER_BOTH); + // Re enable traffic1 and 2 timers + TimerEnable(tf1.timer, TIMER_BOTH); + TimerEnable(tf2.timer, TIMER_BOTH); switch_pressed = false; break; - case GREEN: + case GREEN: // If I am here it means I finished my green period tf_ped.cur_color = YELLOW; set_tf_color(tf_ped, YELLOW); - TimerLoadSet(TIMER2_BASE, TIMER_BOTH, YELLOW_PERIOD); + TimerLoadSet(tf_ped.timer, TIMER_BOTH, YELLOW_PERIOD); break; } } @@ -74,74 +102,83 @@ void Timer2_Handler() { void Switch_Handler() { GPIOIntClear(GPIO_PORTF_BASE, GPIO_PIN_0); switch_pressed = true; - TimerDisable(TIMER0_BASE, TIMER_BOTH); - TimerDisable(TIMER1_BASE, TIMER_BOTH); + // Disable the timers of both tf1 and tf2 + TimerDisable(tf1.timer, TIMER_BOTH); + TimerDisable(tf2.timer, TIMER_BOTH); + // set both traffic light to red set_tf_color(tf1, RED); set_tf_color(tf2, RED); + // set pedestrian traffic light to green set_tf_color(tf_ped, GREEN); tf_ped.cur_color = RED; - TimerInit(TIMER2_BASE, Timer2_Handler, SYSCTL_PERIPH_TIMER2, period_3); // Intialize Timer2 with period_3 + TimerInit(tf_ped.timer, Timer2_Handler, SYSCTL_PERIPH_TIMER2, period_3); // Intialize Timer2 with period_3 } void TrafficInit() { - PortInit(GPIO_PORTF_BASE, SYSCTL_PERIPH_GPIOF, 0x1, 0x7E); // Initialize portf - PortInit(GPIO_PORTA_BASE, SYSCTL_PERIPH_GPIOA, 0x0, 0xFF); // Initialize porta - PortInit(GPIO_PORTB_BASE, SYSCTL_PERIPH_GPIOB, 0x0, 0xFF); // Initialize portb - PortInit(GPIO_PORTE_BASE, SYSCTL_PERIPH_GPIOE, 0x0, 0xFF); // Initialize portb - PortInit(GPIO_PORTD_BASE, SYSCTL_PERIPH_GPIOD, 0x0, 0xFF); // Initialize portb + portsInit(); // Used ports intialization __asm("CPSID I"); // Disable all interrupts - GPIOIntUnregister(GPIO_PORTF_BASE); - GPIOIntRegister(GPIO_PORTF_BASE, Switch_Handler); - GPIOIntEnable(GPIO_PORTF_BASE, GPIO_INT_PIN_0); - GPIOIntTypeSet(GPIO_PORTF_BASE, GPIO_PIN_0, GPIO_RISING_EDGE); - IntEnable(INT_GPIOF_TM4C123); + GPIOIntUnregister(GPIO_PORTF_BASE); // unregister interrupts for portf as a precaution + GPIOIntRegister(GPIO_PORTF_BASE, Switch_Handler); // Set Switch_handler as the interrupt handler for portf + GPIOIntEnable(GPIO_PORTF_BASE, GPIO_INT_PIN_0); // Enable interrupts for pin0 of portf + GPIOIntTypeSet(GPIO_PORTF_BASE, GPIO_PIN_0, GPIO_RISING_EDGE); // Make interrupts happen with rising edge + IntEnable(INT_GPIOF_TM4C123); // Enable CPU interrupts IntMasterEnable(); - TimerInit(TIMER0_BASE, Timer0_Handler, SYSCTL_PERIPH_TIMER0, period_1); // Intialize Timer0 with period_1 - TimerInit(TIMER1_BASE, Timer1_Handler, SYSCTL_PERIPH_TIMER1, period_2); // Intialize Timer1 with period_2 + TimerInit(tf1.timer, Timer0_Handler, SYSCTL_PERIPH_TIMER0, period_1); // Intialize Timer0 with period_1 + TimerInit(tf2.timer, Timer1_Handler, SYSCTL_PERIPH_TIMER1, period_2); // Intialize Timer1 with period_2 __asm("CPSIE I"); // Enable all interrupts while(1) { - BcdWrite(bcd1, TIMER0_BASE, false); - BcdWrite(bcd2, TIMER1_BASE, false); if(switch_pressed) { - BcdWrite(bcd_ped, TIMER2_BASE, true); - } + BcdWrite(bcd_ped, tf_ped.timer, true); + } else { + BcdWrite(bcd1, tf1.timer, false); + BcdWrite(bcd2, tf2.timer, false); + } } } -void Traffic_Handler(Traffic *tf, uint32_t timer) { - TimerIntClear(timer, TIMER_BOTH); +/* + Function that handles the timers of each traffic light +*/ +void Traffic_Handler(Traffic *tf) { + TimerIntClear(tf->timer, TIMER_BOTH); if(switch_pressed) { set_tf_color(*tf, RED); } else { switch(tf->cur_color) { - case RED: + case RED: // If I am here it means I finished my red period tf->cur_color = GREEN; set_tf_color(*tf, GREEN); - TimerLoadSet(timer, TIMER_BOTH, GREEN_PERIOD); + TimerLoadSet(tf->timer, TIMER_BOTH, GREEN_PERIOD); break; - case YELLOW: + case YELLOW: // If I am here it means I finished my yellow period tf->cur_color = RED; set_tf_color(*tf, RED); - TimerLoadSet(timer, TIMER_BOTH, RED_PERIOD); + TimerLoadSet(tf->timer, TIMER_BOTH, RED_PERIOD); break; - case GREEN: + case GREEN: // If I am here it means I finished my green period tf->cur_color = YELLOW; set_tf_color(*tf, YELLOW); - TimerLoadSet(timer, TIMER_BOTH, YELLOW_PERIOD); + TimerLoadSet(tf->timer, TIMER_BOTH, YELLOW_PERIOD); break; } } } +/* + A function that takes a bcd(decoder) and a timer and flag ped which states if the bcd is a pedestrian bcd or not, + and the function writes the current value of the timer in the right pins of the right port +*/ void BcdWrite(Bcd bcd, uint32_t timer, bool ped) { - uint8_t n = (TimerValueGet(timer, TIMER_A) / TIVA_CLK) + 1; - int bin[4]; + // n is the current value of the timer, we add one because we don't want 0 indexing + uint8_t n = (TimerValueGet(timer, TIMER_A) / TIVA_CLK) + 1; + int bin[4]; // An array that will contain the binary representation of the current value of the timer in seconds + // treat pedestrian as a special case because it contains pins in two different ports 3 in A and 1 in E if(ped) { + // loop to get the binary representation of current timer for(int i = 0; i < 4; i++) { bin[i] = n % 2; n /= 2; } - // GPIOPinWrite(GPIO_PORTA_BASE, 0xFF, (((bin[1]) << bcd.B) | ((bin[2]) << bcd.C))); DIO_WritePin(&GPIO_PORTA_DATA_R, bcd.A, bin[0]); DIO_WritePin(&GPIO_PORTA_DATA_R, bcd.B, bin[1]); DIO_WritePin(&GPIO_PORTA_DATA_R, bcd.C, bin[2]); @@ -153,7 +190,5 @@ void BcdWrite(Bcd bcd, uint32_t timer, bool ped) { n /= 2; } GPIOPinWrite(bcd.port, 0xFF, ((bin[0]) << bcd.A) | ((bin[1]) << bcd.B) | (bin[2] << bcd.C) | (bin[3] << bcd.D)); - // GPIOPinWrite(bcd.port, 0xFF, (1 << bcd.pins[i])); - } } diff --git a/trafficlight.h b/trafficlight.h index f1f94a9..c449609 100644 --- a/trafficlight.h +++ b/trafficlight.h @@ -1,25 +1,16 @@ #include #include -#include #include "tivaware.h" -#define TIVA_CLK 16e6 -#define GREEN_PERIOD TIVA_CLK * 5 -#define YELLOW_PERIOD TIVA_CLK * 2 -#define RED_PERIOD TIVA_CLK * 7 -#define RED 1 -#define YELLOW 2 -#define GREEN 3 +#define TIVA_CLK 16e6 //16MHz clock +#define GREEN_PERIOD TIVA_CLK * 5 // 5 seconds +#define YELLOW_PERIOD TIVA_CLK * 2 // 2 seconds +#define RED_PERIOD TIVA_CLK * 7 // 7 seconds +#define RED 1 +#define YELLOW 2 +#define GREEN 3 -typedef struct Traffic{ - uint8_t cur_color; - uint32_t port; - uint8_t red; - uint8_t yellow; - uint8_t green; -} Traffic; - typedef struct Bcd{ uint32_t port; uint8_t A; @@ -28,21 +19,33 @@ typedef struct Bcd{ uint8_t D; } Bcd; +typedef struct Traffic{ + uint8_t cur_color; + uint32_t port; + uint8_t red; + uint8_t yellow; + uint8_t green; + uint32_t timer; +} Traffic; + extern Traffic tf1; extern Traffic tf2; extern Traffic tf_ped; + extern Bcd bcd1; extern Bcd bcd2; extern Bcd bcd_ped; + extern bool switch_pressed; + + extern uint32_t period_1; extern uint32_t period_2; extern uint32_t period_3; void TrafficInit(); -void Traffic_Handler(Traffic *tf, uint32_t timer); +void Traffic_Handler(Traffic *tf); void set_tf_color(Traffic tf, uint8_t color); void PortInit(uint32_t port, uint32_t clk, uint32_t input, uint32_t output); void TimerInit(uint32_t timer, void(*timer_handler)(), uint32_t clk, uint32_t delay); void BcdWrite(Bcd bcd, uint32_t timer, bool ped); - -- cgit v1.2.3