// Shing Yan (sy228@cornell.edu)

// Raymond Siow (rs234@cornell.edu)

// Cornell University, Ithaca, NY 14853, USA

// ECE 476

// Final Project - Traffic control

// Section: Mondays 4:30pm-7:30pm

// Last Updated: April 27th, 2003, 6:16 AM.

 

#include <Mega32.h>  

#include <stdio.h>

#include <stdlib.h>

#include <math.h>   

#include <delay.h>

 

// other constants

#define T0reload              256-250

#define maxkeys               16

#define NOBUTTON              99

 

// traffic light FSM states

#define B_GOES_A_WALK         1

#define A_DONT_WALK           2

#define B_YELLOW              3

#define B_RED                 4

#define A_GREEN               5

#define B_WALK                6

#define A_GOES_B_WALK         7

#define B_DONT_WALK           8

#define A_YELLOW              9

#define A_RED                 10

#define B_GREEN               11

#define A_WALK                12

 

// sensor states

#define NO_CAR                31

#define IS_CAR                32

 

// traffic condition constants

#define LO                    13

#define MI                    14

#define HI                    16

 

// traffic sensor condition

#define READY_TO_ADJ          17

#define RECENTLY_ADJ          18

 

// time constants used

#define TEN_MS                10

#define HUNDRED_MS            100

#define HALF_SEC              500

#define FIVE_MIN              300000

#define L_CYCLE_LO            60*2

#define L_CYCLE_NM            90*2  //Normal

#define L_CYCLE_HI            120*2

#define LT_A_FLASH            15*2

#define LT_B_FLASH            15*2

 

// timer variables

int half_sec;

int traf_t;

int peds_t;

 

// traffic light related variables

int lightState;

int lgt_t_a;

int lgt_t_b;

int lgt_t_a_dw;

int lgt_t_b_dw;

int lgt_t_a_reload;

int lgt_t_b_reload;

 

// traffic condition

int traf_cond_a;

int traf_cond_b;

 

// sensors related variables

int sensorState_a1;

int sensorState_a2;

int car_q_time_a1;

int car_q_time_a2;

 

int sensorState_b1;

int sensorState_b2;

int car_q_time_b1;

int car_q_time_b2;

 

int car_q_time_a;

int car_cnt_a;

int time_base_a;

 

int car_q_time_b;

int car_cnt_b;

int time_base_b;

 

// some other constants

int hi = L_CYCLE_HI >> 1;

int mi = L_CYCLE_NM >> 1;

int lo = L_CYCLE_LO >> 1;

 

void light_fsm(void);

void traffic_fsm(void);

void adjust_traf(void);

void pedestrian_fsm(void);

void initalize(void);

void main(void);

 

// timer0 overflow ISR

interrupt [TIM0_OVF] void timer0_overflow(void) {

 

      // reload to force 1 mSec overflow

      TCNT0 = T0reload;

 

      // Decrement the three times if they are not already zero

      if (half_sec > 0) half_sec--;

      if (traf_t > 0) --traf_t;

      if (peds_t > 0) --peds_t;

}

 

// When magnetic field -> 1

// No field -> 0

 

// light_fsm is a function that implements the state machine used

// to control switching of the traffic lights

void light_fsm(void) {

     

      half_sec = HALF_SEC;

 

      /***********************************

     

      PORT A - DIRECTION A

     

      .0 - RED

      .1 - YELLOW

      .2 - GREEN

      .3 - WALK

      .4 - DON'T WALK

     

      PORT B - DIRECTION B

     

      .0 - RED

      .1 - YELLOW

      .2 - GREEN

      .3 - WALK

      .4 - DON'T WALK

     

      ***********************************/

 

      switch (lightState) {

            case B_GOES_A_WALK:

                  // decrement b's counter

                  if (lgt_t_b > 0) --lgt_t_b;

                  // if counter reaches don't walk... switch to a's don't walk state

                  if (lgt_t_b < lgt_t_b_dw) lightState = A_DONT_WALK;

                  // set a's timer

                  break;

            case A_DONT_WALK:

                  // set walk off on a

                  PORTA.3 = 1;

                  // toggle don't walk light while decrementing b's counter

                  PORTA.4 = ~PORTA.4;

                  // if reaches 5 sec before the end of don't walk state... go to next state

                  if (lgt_t_b > 0) --lgt_t_b;

                  if ((lgt_t_b >> 1) < 5) lightState = B_YELLOW;

                  break;

            case B_YELLOW:

                  // set traffic light to yellow on b

                  PORTB.2 = 1;

                  PORTB.1 = 0;

                  // 2 sec before going to state

                  if (lgt_t_b > 0) --lgt_t_b;

                  if ((lgt_t_b >> 1) < 3) lightState = B_RED;

                  // set don't walk light on a if not already

                  PORTA.4 = 0;

                  break;

            case B_RED:

                  // set traffic light to red on b

                  PORTB.1 = 1;

                  PORTB.0 = 0;

                  // 1 sec before going to next state

                  if (lgt_t_b > 0) --lgt_t_b;

                  if ((lgt_t_b >> 1) < 2) lightState = A_GREEN;

                  break;

            case A_GREEN:

                  // set traffic light to green on a

                  PORTA.0 = 1;

                  PORTA.2 = 0;

                  // 1 sec before going to next state

                  if (lgt_t_b > 0) --lgt_t_b;

                  if ((lgt_t_b >> 1) < 1) lightState = B_WALK;

                  break;

            case B_WALK:

                  // set don't walk off and set walk on on b

                  PORTB.4 = 1;

                  PORTB.3 = 0;

                  // 1 sec befire going to next state

                  if (lgt_t_b > 0) --lgt_t_b;

                  lightState = A_GOES_B_WALK;

                  break;

            case A_GOES_B_WALK:

                  // decrement a's counter

                  if (lgt_t_a > 0) --lgt_t_a;

                  // if counter reaches don't walk... switch to b's don't walk state

                  if (lgt_t_a < lgt_t_a_dw) lightState = B_DONT_WALK;

                  // set a's timer

                  break;

            case B_DONT_WALK:

                  // set walk off on b

                  PORTB.3 = 1;

                  // toggle don't walk light while decrementing a's counter

                  PORTB.4 = ~PORTB.4;

                  // if reaches 5 sec before the end of don't walk state... go to next state

                  if (lgt_t_a > 0) --lgt_t_a;

                  if ((lgt_t_a >> 1) < 5) lightState = A_YELLOW;

                  break;

            case A_YELLOW:

                  // set traffic light to yellow on a

                  PORTA.2 = 1;

                  PORTA.1 = 0;

                  // 2 sec before going to state

                  if (lgt_t_a > 0) --lgt_t_a;

                  if ((lgt_t_a >> 1) < 3) lightState = A_RED;

                  // set don't walk light on b if not already

                  PORTB.4 = 0;

                  break;

            case A_RED:

                  // set traffic light to red on a

                  PORTA.1 = 1;

                  PORTA.0 = 0;

                  // 1 sec before going to next state

                  if (lgt_t_a > 0) --lgt_t_a;

                  if ((lgt_t_a >> 1) < 2) lightState = B_GREEN;

                  break;

            case B_GREEN:

                  // set traffic light to green on b

                  PORTB.0 = 1;

                  PORTB.2 = 0;

                  // 1 sec before going to next state

                  if (lgt_t_a > 0) --lgt_t_a;

                  if ((lgt_t_a >> 1) < 1) lightState = A_WALK;

                  break;

            case A_WALK:

                  // set don't walk off and set walk on on a

                  PORTA.4 = 1;

                  PORTA.3 = 0;

                  // 1 sec befire going to next state

                  if (lgt_t_a > 0) --lgt_t_a;

                  lightState = B_GOES_A_WALK;

                  adjust_traf();

                  break;

      }

}

 

// This task checks the road condition every 10ms and adjust the variables

// of the traffic lights if necessary.

void traffic_fsm(void) {

 

      /***********************************

     

      PORT A - DIRECTION A

     

      .6 - SENSOR IN A1

      .7 - SENSOR IN A2

     

      PORT B - DIRECTION B

     

      .6 - SENSOR IN B1

      .7 - SENSOR IN B2

     

      ***********************************/

 

      //update the traffic condition every 10ms

 

      traf_t = TEN_MS;

 

      // state machine for traffic light a1    

      switch (sensorState_a1) {

            case NO_CAR:

                  PORTC.3 = 1;

                  car_q_time_a1 = 0;

                  if (PINA.6 == 0){

                        sensorState_a1 = IS_CAR;

                  }

                  break;

            case IS_CAR:

                  if (PINA.6 == 1) {

                        sensorState_a1 = NO_CAR;

                        car_cnt_a++;           

                  } else {

                  // increment waiting time

                        car_q_time_a1++;       

                  }

                  break;

      }

      // if waiting time at the sensor > 1 sec, we assume that it's stopped

      // this is when the wait time is incremented

      if (car_q_time_a1 > 100) {

            car_q_time_a1-=100;

            car_q_time_a+=2;

            PORTC.3 = ~PORTC.3;

      }

 

      // state machine for traffic light a2    

      switch (sensorState_a2) {

            case NO_CAR:

                  PORTC.3 = 1;

                  car_q_time_a2 = 0;

                  if (PINA.7 == 0) {

                        sensorState_a2 = IS_CAR;

                  }

                  break;

            case IS_CAR:

                  if (PINA.7 == 1){

                        sensorState_a2 = NO_CAR;

                        car_cnt_a++;           

                  } else {

                  // increment waiting time

                        car_q_time_a2++;       

                  }

                  break;

      }

      // if waiting time at the sensor > 1 sec, we assume that it's stopped

      // this is when the wait time is incremented

      if (car_q_time_a2 > 100) {

            car_q_time_a2-=100;

            car_q_time_a+=2;

            PORTC.3 = ~PORTC.3;

      }

 

      // state machine for traffic light b1    

      switch (sensorState_b1) {

            case NO_CAR:

                  PORTC.7 = 1;

                  car_q_time_b1 = 0;

                  if (PINB.6 == 0){

                        sensorState_b1 = IS_CAR;

                  }

                  break;

            case IS_CAR:

                  if (PINB.6 == 1) {

                        sensorState_b1 = NO_CAR;

                        car_cnt_b++;           

                  } else {

                  // increment waiting time

                        car_q_time_b1++;       

                  }

                  break;

      }

      // if waiting time at the sensor > 1 sec, we assume that it's stopped

      // this is when the wait time is incremented

      if (car_q_time_b1 > 100) {

            car_q_time_b1-=100;

            car_q_time_b+=2;

            PORTC.7 = ~PORTC.7;

      }

 

      // state machine for traffic light a2    

      switch (sensorState_b2) {

            case NO_CAR:

                  PORTC.7 = 1;

                  car_q_time_b2 = 0;

                  if (PINB.7 == 0){

                        sensorState_b2 = IS_CAR;

                  }

                  break;

            case IS_CAR:

                  if (PINB.7 == 1){

                        sensorState_b2 = NO_CAR;

                        car_cnt_b++;           

                  } else {

                  // increment waiting time

                        car_q_time_b2++;       

                  }

                  break;

      }

      // if waiting time at the sensor > 1 sec, we assume that it's stopped

      // this is when the wait time is incremented

      if (car_q_time_b2 > 100) {

            car_q_time_b2-=100;

            car_q_time_b+=2;

            PORTC.7 = ~PORTC.7;

      }

 

}

 

void adjust_traf(void) {

 

      int wait_a, rate_a, traf_a;

      int wait_b, rate_b, traf_b;

      int time_base;

     

      time_base = time_base_a + time_base_b;

     

      // set wait time for a1 and a2

      if (car_q_time_a > (time_base_b*3/4)) {

            wait_a = HI;

      } else if (car_q_time_a < (time_base_b/4)) {

            wait_a = LO;

      } else {

            wait_a = MI;

      }

 

      // set rate for a1 and a2

      if (((float)time_base_a)/car_cnt_a < 4) {

            rate_a = HI;

      } else if (((float)time_base_a*2)/car_cnt_a > 10) {

            rate_a = LO;

      } else {

            rate_a = MI;

      }

 

      traf_a = wait_a + rate_a;

     

      // determine the traffic in road a

      if (traf_a < MI*2) {

            traf_cond_a = LO;

            PORTC.0 = 0;

            PORTC.1 = 1;

            PORTC.2 = 1;

      } else if (traf_a < HI*2) {

            traf_cond_a = MI;

            PORTC.0 = 1;

            PORTC.1 = 0;

            PORTC.2 = 1;

      } else {

            traf_cond_a = HI;

            PORTC.0 = 1;

            PORTC.1 = 1;

            PORTC.2 = 0;

      }

 

      // set wait time for b1 and b2

      if (car_q_time_b > (time_base_a*3/4)) {

            wait_b = HI;

      } else if (car_q_time_b < (time_base_a/4)) {

            wait_b = LO;

      } else {

            wait_b = MI;

      }

 

      // set rate for b1 and b2

      if (((float)time_base_b)/car_cnt_b < 2) {

            rate_b = HI;

      } else if (((float)time_base_b)/car_cnt_b > 6) {

            rate_b = LO;

      } else {

            rate_b = MI;

      }

 

      traf_b = wait_b + rate_b;

     

      // determine the traffic in road b

      if (traf_b < MI*2) {

            traf_cond_b = LO;

            PORTC.4 = 0;

            PORTC.5 = 1;

            PORTC.6 = 1;

      } else if (traf_b < HI*2) {

            traf_cond_b = MI;

            PORTC.4 = 1;

            PORTC.5 = 0;

            PORTC.6 = 1;

      } else {

            traf_cond_b = HI;

            PORTC.4 = 1;

            PORTC.5 = 1;

            PORTC.6 = 0;

      }

     

      // reset variables for road a