summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOmar Magdy <omar.professional8777@gmail.com>2022-08-25 02:24:01 +0200
committerOmar Magdy <omar.professional8777@gmail.com>2022-08-25 02:24:01 +0200
commitc3f4417efaa489c41e5d5d44fb28ae01e65ff6bc (patch)
treee64fe589fe32c39b6cdb4f81f07ca746f38c4b75
parentbc90dfb83866078bce80034d06607b0094aa63e4 (diff)
downloadTraffic-light-c3f4417efaa489c41e5d5d44fb28ae01e65ff6bc.tar.xz
Traffic-light-c3f4417efaa489c41e5d5d44fb28ae01e65ff6bc.zip
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
-rw-r--r--main.c21
-rw-r--r--trafficlight.c121
-rw-r--r--trafficlight.h39
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 <stdint.h>
#include <stdbool.h>
-#include <stdlib.h>
#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);
-