You are on page 1of 16

/*----------------------------------------------------------------------------

* RTL Kernel Example

*----------------------------------------------------------------------------

* Name: TRAFFIC.C

* Purpose: Traffic Light Controller example program

* Rev.: V3.20

*----------------------------------------------------------------------------

* This code is part of the RealView Run-Time Library.

* Copyright (c) 2004-2008 KEIL - An ARM Company. All rights reserved.

*---------------------------------------------------------------------------*/

#include <stdio.h> /* standard I/O .h-file */

#include <ctype.h> /* character functions */

#include <string.h> /* string and memory functions */

#include <RTL.h> /* RTX kernel functions & defines */

#include <stm32f10x_lib.h> /* STM32F10x Library Definitions */

#include "STM32_Init.h" /* STM32 Initialization */

#include "lcd.h"

unsigned long TimeTick; /* counts 10ms timeTicks */

/*------------------------------------------------------------------------------

Additional LCD defines and functions used to draw a bargraph

*------------------------------------------------------------------------------*/

#define FONT_WIDTH 16

#define FONT_HEIGHT 24

#define DISPLAY_WIDTH 320


const char menu[] =

"\n"

"+**** TRAFFIC LIGHT CONTROLLER using RVCT and RTX kernel *****+\n"

"| This program is a simple Traffic Light Controller. Between |\n"

"| start time and end time the system controls a traffic light |\n"

"| with pedestrian self-service. Outside of this time range |\n"

"| the yellow caution lamp is blinking. |\n"

"+ command -+ syntax -----+ function --------------------------+\n"

"| Display | D | display times |\n"

"| Time | T hh:mm:ss | set clock time |\n"

"| Start | S hh:mm:ss | set start time |\n"

"| End | E hh:mm:ss | set end time |\n"

"+----------+-------------+------------------------------------+\n";

extern void getline (char *, int);

/* external function: input line */

extern int getkey (void); /* external function: input character */

OS_TID t_command; /* assigned task id of task: command */

OS_TID t_clock; /* assigned task id of task: clock */

OS_TID t_lights; /* assigned task id of task: lights */

OS_TID t_keyread; /* assigned task id of task: keyread */

OS_TID t_getesc; /* assigned task id of task: get_esc */

OS_TID t_lcd; /* assigned task id of task: lcd */


struct time { /* structure of the time record */

U8 hour; /* hour */

U8 min; /* minute */

U8 sec; /* second */

};

struct time ctime = { 12, 0, 0 }; /* storage for clock time values */

struct time start = { 7, 30, 0 }; /* storage for start time values */

struct time end = { 18, 30, 0 }; /* storage for end time values */

#define red 0x000100 /* I/O Pin: red lamp output */

#define yellow 0x000200 /* I/O Pin: yellow lamp output */

#define green 0x000400 /* I/O Pin: green lamp output */

#define stop 0x001000 /* I/O Pin: stop lamp output */

#define walk 0x002000 /* I/O Pin: walk lamp output */

#define key 0x000100 /* I/O Pin: self-service key input */

//#define setLights(o,s) { \

// if (s==0) GPIOB->ODR &= ~(o); \

// else GPIOB->ODR |= (o); \

//};

void setLights (unsigned short light, unsigned short on) {

LCD_SetBackColor(White); /* Set the Back Color */

if (light & red) {

LCD_SetTextColor(Red); /* Set the Text Color */

if (on == 0)
LCD_DisplayChar(Line4, DISPLAY_WIDTH-5*FONT_WIDTH, 0x80+0); /* Circle Empty */

else

LCD_DisplayChar(Line4, DISPLAY_WIDTH-5*FONT_WIDTH, 0x80+1); /* Circle Full */

if (light & yellow) {

LCD_SetTextColor(Yellow); /* Set the Text Color */

if (on == 0)

LCD_DisplayChar(Line5, DISPLAY_WIDTH-5*FONT_WIDTH, 0x80+0); /* Circle Emptyn */

else

LCD_DisplayChar(Line5, DISPLAY_WIDTH-5*FONT_WIDTH, 0x80+1); /* Circle Full */

if (light & green) {

LCD_SetTextColor(Green); /* Set the Text Color */

if (on == 0)

LCD_DisplayChar(Line6, DISPLAY_WIDTH-5*FONT_WIDTH, 0x80+0); /* Circle Empty */

else

LCD_DisplayChar(Line6, DISPLAY_WIDTH-5*FONT_WIDTH, 0x80+1); /* Circle Full */

if (light & stop) {

LCD_SetTextColor(Red); /* Set the Text Color */

if (on == 0)

LCD_DisplayChar(Line5, DISPLAY_WIDTH-7*FONT_WIDTH, 0x80+2); /* Wait Empty */

else

LCD_DisplayChar(Line5, DISPLAY_WIDTH-7*FONT_WIDTH, 0x80+3); /* Wait Full */

if (light & walk) {

LCD_SetTextColor(Green); /* Set the Text Color */


if (on == 0)

LCD_DisplayChar(Line6, DISPLAY_WIDTH-7*FONT_WIDTH, 0x80+4); /* Walk Empty */

else

LCD_DisplayChar(Line6, DISPLAY_WIDTH-7*FONT_WIDTH, 0x80+5); /* Walk Full */

if (on == 0)

GPIOB->ODR &= ~(light);

else

GPIOB->ODR |= (light);

char cmdline[16]; /* storage for command input line */

struct time rtime; /* temporary storage for entry time */

BIT display_time = __FALSE; /* flag signal cmd state display_time */

BIT escape; /* flag: mark ESCAPE character entered */

#define ESC 0x1B /* ESCAPE character code */

static U64 cmd_stack[800/8]; /* A bigger stack for command task */

void init (void) __task; /* Function prototypes */

void clock (void) __task;

void get_escape (void) __task;

void command (void) __task;

void blinking (void) __task;

void lights (void) __task;


void keyread (void) __task;

void lcd (void) __task;

/*---------------------------------------------------------------------------

Delay function

delays number of tick Systicks (happens every 10 ms)

*---------------------------------------------------------------------------*/

void Delay (unsigned long tick) {

os_dly_wait (tick); /* wait for timeout */

/*----------------------------------------------------------------------------

* Main: Initialize and start RTX Kernel

*---------------------------------------------------------------------------*/

int main (void) { /* program execution starts here */

stm32_Init (); /* STM32 setup (must be called first */

os_sys_init (init); /* init and start with task 'INIT' */

/*----------------------------------------------------------------------------

* Task 1 'init': Initialize

*---------------------------------------------------------------------------*/

void init (void) __task {

t_clock = os_tsk_create (clock, 0); /* start clock task */


t_lcd = os_tsk_create (lcd, 0); /* start task lcd */

os_dly_wait (50);

/* start command task */

t_command = os_tsk_create_user (command,0,&cmd_stack,sizeof(cmd_stack));

t_lights = os_tsk_create (lights, 0); /* start lights task */

t_keyread = os_tsk_create (keyread,0); /* start keyread task */

os_tsk_delete_self (); /* stop init task (no longer needed)*/

/*----------------------------------------------------------------------------

* Task 3 'clock'

*---------------------------------------------------------------------------*/

void clock (void) __task {

os_itv_set (100); /* set wait interval: 1 second */

while (1) { /* clock is an endless loop */

if (++ctime.sec == 60) { /* calculate the second */

ctime.sec = 0;

if (++ctime.min == 60) { /* calculate the minute */

ctime.min = 0;

if (++ctime.hour == 24) { /* calculate the hour */

ctime.hour = 0;

if (display_time) { /* if command_status == display_time */

os_evt_set (0x0001,t_command); /* signal to task command time changed */

}
os_itv_wait (); /* wait interval (already set to 1s ) */

/*----------------------------------------------------------------------------

* readtime: convert line input to time values & store in rtime

*---------------------------------------------------------------------------*/

char readtime (char *buffer) {

int args; /* number of arguments */

int hour,min,sec;

rtime.sec = 0; /* preset second */

args = sscanf (buffer, "%d:%d:%d", /* scan input line for */

&hour, &min, &sec); /* hour, minute and second */

if (hour > 23 || min > 59 || /* check for valid inputs */

sec > 59 || args < 2 ){

printf ("\n*** ERROR: INVALID TIME FORMAT\n");

return (0);

rtime.hour = hour; /* setting a new time: hour */

rtime.min = min; /* setting a new time: min */

rtime.sec = sec; /* setting a new time: sec */

return (1);

/*----------------------------------------------------------------------------
* Task 7 'get_escape': check if ESC (escape character) was entered

*---------------------------------------------------------------------------*/

void get_escape (void) __task {

while (1) { /* endless loop */

if (getkey () == ESC) { /* If ESC entered, set flag */

escape = __TRUE; /* 'escape', set event flag of */

os_evt_set (0x0002, t_command); /* task 'command' and */

/*----------------------------------------------------------------------------

* Task 2 'command': command processor

*---------------------------------------------------------------------------*/

void command (void) __task {

U32 i;

printf (menu); /* display command menu */

while (1) { /* endless loop */

printf ("\nCommand: "); /* display prompt */

getline (cmdline, sizeof (cmdline)); /* get command line input */

for (i = 0; cmdline[i] != 0; i++) { /* convert to uppercase */

cmdline[i] = (char) toupper(cmdline[i]);

for (i = 0; cmdline[i] == ' '; i++); /* skip blanks */


switch (cmdline[i]) { /* proceed to command function */

case 'D': /* Display Time Command */

printf ("Start Time: %02d:%02d:%02d "

"End Time: %02d:%02d:%02d\n",

start.hour, start.min, start.sec,

end.hour, end.min, end.sec);

printf (" type ESC to abort\r");

t_getesc = os_tsk_create (get_escape, 0);/* ESC check in display loop*/

escape = __FALSE; /* clear escape flag */

display_time = __TRUE; /* set display time flag */

os_evt_clr (0x0003, t_command); /* clear pending signals */

while (!escape) { /* while no ESC entered */

printf ("Clock Time: %02d:%02d:%02d\r", /* display time */

ctime.hour, ctime.min, ctime.sec);

os_evt_wait_or (0x0003, 0xffff); /* wait for time change or ESC*/

os_tsk_delete (t_getesc); /* terminate 'get_escape' task.*/

display_time = __FALSE; /* clear display time flag */

printf ("\n\n");

break;

case 'T': /* Set Time Command */

if (readtime (&cmdline[i+1])) { /* read time input and */


ctime.hour = rtime.hour; /* store in 'ctime' */

ctime.min = rtime.min;

ctime.sec = rtime.sec;

break;

case 'E': /* Set End Time Command */

if (readtime (&cmdline[i+1])) { /* read time input and */

end.hour = rtime.hour; /* store in 'end' */

end.min = rtime.min;

end.sec = rtime.sec;

break;

case 'S': /* Set Start Time Command */

if (readtime (&cmdline[i+1])) { /* read time input and */

start.hour = rtime.hour; /* store in 'start' */

start.min = rtime.min;

start.sec = rtime.sec;

break;

default: /* Error Handling */

printf (menu); /* display command menu */

break;

}
}

/*----------------------------------------------------------------------------

* signalon: check if clock time is between start and end

*---------------------------------------------------------------------------*/

char signalon (void) {

if (memcmp (&start, &end, sizeof (struct time)) < 0) {

if (memcmp (&start, &ctime, sizeof (struct time)) < 0 &&

memcmp (&ctime, &end, sizeof (struct time)) < 0) {

return (1);

else {

if (memcmp (&end, &ctime, sizeof (start)) > 0 &&

memcmp (&ctime, &start, sizeof (start)) > 0) {

return (1);

return (0); /* signal off, blinking on */

/*----------------------------------------------------------------------------

* Task 4 'blinking': runs if current time is outside start & end time

*---------------------------------------------------------------------------*/

void blinking (void) __task { /* blink yellow light */

setLights (red|yellow|green|stop|walk, 0); /* all lights off */

while (1) { /* endless loop */


setLights (yellow, 1); /* yellow light on */

os_dly_wait (30); /* wait for timeout: 30 ticks */

setLights (yellow, 0); /* yellow light off */

os_dly_wait (30); /* wait for timeout: 30 ticks */

if (signalon ()) { /* if blinking time over */

os_tsk_create (lights, 0); /* start lights */

os_tsk_delete_self (); /* and stop blinking */

/*----------------------------------------------------------------------------

* Task 5 'lights': executes if current time is between start & end time

*---------------------------------------------------------------------------*/

void lights (void) __task { /* traffic light operation */

setLights (red|stop, 1); /* red & stop lights on */

setLights (yellow|green|walk, 0);

while (1) { /* endless loop */

os_dly_wait (50); /* wait for timeout: 50 ticks */

if (!signalon ()) { /* if traffic signal time over */

os_tsk_create (blinking, 0); /* start blinking */

os_tsk_delete_self (); /* stop lights */

setLights (yellow, 1);

os_dly_wait (50); /* wait for timeout: 50 ticks */

setLights (red|yellow, 0); /* green light for cars */

setLights (green, 1);


os_evt_clr (0x0010, t_lights);

os_dly_wait (50); /* wait for timeout: 50 ticks */

os_evt_wait_and (0x0010, 750); /* wait for event with timeout */

setLights (yellow, 1); /* timeout value: 750 ticks */

setLights (green, 0);

os_dly_wait (50); /* wait for timeout: 50 ticks */

setLights (red, 1); /* red light for cars */

setLights (yellow, 0);

os_dly_wait (50); /* wait for timeout: 50 ticks */

setLights (stop, 0); /* green light for walkers */

setLights (walk, 1);

os_dly_wait (250); /* wait for timeout: 250 ticks */

setLights (stop, 1); /* red light for walkers */

setLights (walk, 0);

/*----------------------------------------------------------------------------

* Task 6 'keyread': process key stroke from pedestrian push button

*---------------------------------------------------------------------------*/

void keyread (void) __task {

while (1) { /* endless loop */

if ((GPIOG->IDR & key) == 0) { /* if key pressed */

os_evt_set (0x0010, t_lights); /* send signal to task lights */

os_dly_wait (5); /* wait for timeout: 5 ticks */

}
}

/*----------------------------------------------------------------------------

* Task 8 'lcd': LCD Control task

*---------------------------------------------------------------------------*/

void lcd (void) __task {

STM3210E_LCD_Init(); /* Initialize the LCD */

LCD_Clear(White); /* Clear the LCD */

GPIO_WriteBit(GPIOA, GPIO_Pin_8, Bit_SET); /* Turn On LCD Backlight */

for (;;) {

LCD_SetBackColor(Blue); /* Set the Back Color */

LCD_SetTextColor(White); /* Set the Text Color */

LCD_DisplayStringLine(Line0, " MCBSTM32E Demo ");

LCD_DisplayStringLine(Line1, " RTX Traffic ");

LCD_DisplayStringLine(Line2, " www.keil.com ");

os_dly_wait (400);

LCD_SetBackColor(Blue); /* Set the Back Color */

LCD_SetTextColor(Red); /* Set the Text Color */

LCD_DisplayStringLine(Line0, " MCBSTM32E Demo ");

LCD_DisplayStringLine(Line1, " RTX Traffic ");

LCD_DisplayStringLine(Line2, " www.keil.com ");

os_dly_wait (400);

}
/*----------------------------------------------------------------------------

* end of file

*---------------------------------------------------------------------------*/

You might also like