Jump to content
43oh

State Machine-based Pedestrian Crossing Simulator


Recommended Posts

As promised: a pedestrian crossing simulator - requires a 74HC595 shift register (though I could have done this without it)

 

/*
* State Machine demo for MSP430
* Simulates a UK pedestrian crossing with sound
* http://en.wikipedia.org/wiki/Pelican_crossing
* Requires a 74HC595 shift register and an optional piezo speaker
* WDT timer is used to control traffic light phases and beeps
* Timer_A0 used as a beep frequency generator
*/

#include 

#define TF 23		// Approx. WDT ticks per second 

// Pin definitions
// 74HC595: Data - P1.4, Clock = P1.5, Latch = P1.2 

#define PIN_DATA	BIT4
#define PIN_CLOCK	BIT5
#define PIN_LATCH	BIT2

// Pedestrian button on P1.7
#define PIN_BUTTON	BIT7

// Piezo speaker on P1.1
#define PIN_SPEAKER	BIT1

// LED connections for 74HC595
// T = traffic, P = pedestrian
#define T_RED		BIT0
#define T_AMBER		BIT1
#define	T_GREEN		BIT2
#define	P_RED		BIT3
#define	P_GREEN		BIT4
#define P_WAIT		BIT5

#define DEL_P_MIN		    TF*20	// Minimum time for traffic to stay green
#define DEL_T_AMBER 		TF*2	// Traffic amber phase
#define DEL_T_RED			TF*2	// Traffic red phase
#define DEL_P_GREEN			TF*8	// Pedestrian green phase
#define DEL_P_GREEN_FLASH	TF*4	// Pedestrian green / traffic amber flashing phase

#define FREQ 		4000			// Beep frequency x 2
#define BEEP_D 		3				// Beep duration in ticks
#define FLASH_D		10				// Flash duration in ticks			
#define SMCLK 		1000000			// SMCLK frequency

static enum {
INIT = 0,						// Init phase
TRAF_GREEN = 1,					// Traffic green
PED_WAITING = 2,				// Pedestrian waiting
TRAF_AMBER = 3,					// Traffic amber, pedestrian red
TRAF_RED = 4,					// Traffic red, pedestrian red
PED_GREEN = 5,					// Traffic red, pedestrian green
PED_GREEN_FLASH = 6				// Traffic amber flashing, pedestrian green flashing
} state=INIT;

unsigned char lights=0, button=0;

void main(void)
{
// Set up timers
// WDT used for light phases and timing beeps
// Timer_A used for beeps frequency

   BCSCTL1 = CALBC1_1MHZ;                  // Set DCO
   DCOCTL = CALDCO_1MHZ;

 	BCSCTL3 |= LFXT1S_2;					// 12khz VLOCLK for ACLK
	WDTCTL =  WDTPW | WDTTMSEL | WDTSSEL | WDTIS1;
											// Interval timer mode, ACLK,
											// 12 khz / 512 ~ 23 Hz  
IE1 |= WDTIE;                           // Enable WDT interrupt
P1SEL |= PIN_SPEAKER;					// PIN_SPEAKER to alternative output (CO0)
TACCTL0 = OUTMOD_0;						// OUT output mode
TACCR0 = SMCLK / FREQ;					// Set beep frequency
TACTL = TASSEL_2 | MC_0;				// SMCLK, stop timer

// Set up interrupt for button
P1OUT &= ~PIN_BUTTON;					// Pull button pin down
P1REN = PIN_BUTTON;						//	Enable resistor on button pin
P1IES &= ~PIN_BUTTON;					// Lo/Hi Edge
P1IE |= PIN_BUTTON;						// Enable interrupt
P1IFG &= ~PIN_BUTTON;					// Clear interrupt flag

P1DIR |= PIN_DATA | PIN_CLOCK | PIN_LATCH | PIN_SPEAKER;	
_enable_interrupts();
_low_power_mode_0();
}

#pragma vector=WDT_VECTOR
__interrupt void watchdog_timer(void)
{
static unsigned int ticks=0, wait=0;
unsigned char new_lights = lights;
ticks++;
if (wait)
	wait--;	
switch (state)
{
	case INIT:						// First cycle - initialize lights
	new_lights = T_GREEN | P_RED;	// Traffic green, Pedestrian red
	state = TRAF_GREEN;
	break;

	case TRAF_GREEN:
	if (button)						// If button was pressed
	{
		button = 0;					// Reset button flag
		new_lights |= P_WAIT;		// Pedestrian wait light on
		state = PED_WAITING;
	}
	break;

	case PED_WAITING:
	if (wait == 0)					// If interval expired
	{
		new_lights = T_AMBER | P_RED | P_WAIT;	// Traffic amber, Pedestrian red + wait
		wait = DEL_T_AMBER;			// Wait for traffic amber phase
		state = TRAF_AMBER;
	}
	break;

	case TRAF_AMBER:
	if (wait == 0)					// If interval expired
	{
		new_lights = T_RED | P_RED | P_WAIT;
		wait = DEL_T_RED;
		state = TRAF_RED;
	}
	break;

	case TRAF_RED:
	if (wait == 0)
	{
		new_lights = T_RED | P_GREEN;
		wait = DEL_P_GREEN;
		TACTL |= MC_1;				// start timer to sound beeps
		state = PED_GREEN;
	}
	break;

	case PED_GREEN:
	if (ticks % BEEP_D == 0)
		TACCTL0 ^= OUTMOD_4;		// Toggle TimerA output mode OUT/Toggle for intermittent beeps
	if (wait == 0)
	{
		wait = DEL_P_GREEN_FLASH;	
		state = PED_GREEN_FLASH;
		new_lights = T_AMBER | P_GREEN;
		TACTL &= ~MC_1;				// stop timer - disable beeps
	}
	break;

	case PED_GREEN_FLASH:
	if (ticks % FLASH_D == 0)
		new_lights ^= T_AMBER | P_GREEN;	// Toggle Traffic Amber + Pedestrian Green
	if (wait == 0)
	{
		new_lights = T_GREEN | P_RED;
		wait = DEL_P_MIN;
		button = 0;
		state = TRAF_GREEN;
	}
	break;
}

if (lights != new_lights)			// Shift out new lights to 74HC595
{
	unsigned char b;
	P1OUT &= ~PIN_LATCH;			// latch to low 
	lights = new_lights; 
	for (b=0; b<8; b++)				
	{
		P1OUT &= ~PIN_CLOCK;		// clock to low
		if (lights & (BIT7 >> )		// if bit is set
			P1OUT |=  PIN_DATA;		// data pin to high
		else
			P1OUT &= ~PIN_DATA;		// data pin to low
		P1OUT |= PIN_CLOCK;			// clock to high
	}
	P1OUT |= PIN_LATCH;				// latch to high
}
}

// Port 1 interrupt service routine
#pragma vector=PORT1_VECTOR
__interrupt void Port_1(void)
{
button = 1;
P1IFG &= ~PIN_BUTTON;					// P1.4 IFG cleared
}

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...