Extend FX16 functionality.

pull/4/head
Richard Barry 16 years ago
parent 46c3268670
commit 269de4b1e7

@ -51,14 +51,9 @@
#include "task.h"
#include "semphr.h"
#define diceMIN 1
#define diceMAX 6
#define diceRUN_MIN 600000L
#define diceRUN_MAX 1200000L
#define diceDELAY_BETWEEN_RANDOM_NUMBERS_ms ( 20 )
#define diceRUN_TIME ( 2000 / diceDELAY_BETWEEN_RANDOM_NUMBERS_ms )
#define diceSTATE_STOPPED 0
#define diceSTATE_STARTUP 1
#define diceSTATE_RUNNING 2
#define diceEND_DELAY ( 5000 / portTICK_RATE_MS )
@ -80,61 +75,72 @@ extern volatile unsigned char *pucDisplayOutput[ 2 ];
void vDiceTask( void *pvParameters )
{
char cDiceState = diceSTATE_STOPPED;
unsigned char ucDiceValue, ucIndex;
unsigned long ulDiceRunTime, ulDiceDelay, ulDiceDelayReload;
extern void vToggleFlashTaskSuspendState( void );
unsigned long ulDiceRunTime;
extern void vSuspendFlashTasks( unsigned char ucIndex, short sSuspendTasks );
/* Two instances of this task are created so the task parameter is used
to pass in an index that allows this task to know which file scope variables
it should use. Cast this index into a usable type. */
ucIndex = ( unsigned char ) pvParameters;
/* A binary semaphore is used to signal button push events. Create the
semaphore before it is used. */
vSemaphoreCreateBinary( xSemaphores[ ucIndex ] );
srand( ( unsigned char ) diceRUN_MIN );
/* Make sure the semaphore starts in the wanted state - no button pushes
pending. This call will just clear any button pushes that are latched.
Passing in 0 as the block time means the call will not wait for any further
button pushes. */
prvButtonHit( ucIndex, 0 );
/* Seed the random number generator. */
srand( ( unsigned char ) diceRUN_TIME );
for( ;; )
{
switch( cDiceState )
{
case diceSTATE_STOPPED:
/* Wait for a button push. This task will enter the Blocked state
(will not run again) until after a button has been pushed. */
prvButtonHit( ucIndex, portMAX_DELAY );
ulDiceRunTime = diceRUN_MIN;
cDiceState = diceSTATE_RUNNING;
ulDiceDelay = 1;
ulDiceDelayReload = 1;
cDiceState = diceSTATE_RUNNING;
if( ucIndex == 0 )
{
vToggleFlashTaskSuspendState();
}
break;
/* The next line will only execute after a button has been pushed -
initialise the variable used to shake the dice. */
ulDiceRunTime = diceRUN_TIME;;
case diceSTATE_RUNNING:
/* Suspend the flash tasks so this task has exclusive access to the
display. */
vSuspendFlashTasks( ucIndex, pdTRUE );
while( ulDiceRunTime > 0 )
{
ulDiceRunTime--;
ulDiceDelay--;
if( !ulDiceDelay )
{
/* Generate and display a random number. */
ucDiceValue = rand() % 6 + 1;
dice7SEG_Value( ucIndex ) = ( dice7SEG_Value( ucIndex ) | 0xf7 ) & cDisplaySegments[ ucIndex ][ ucDiceValue ];
ulDiceDelayReload = ulDiceDelayReload + 100;
ulDiceDelay = ulDiceDelayReload;
/* Block/sleep for a very short time before generating the next
random number. */
vTaskDelay( diceDELAY_BETWEEN_RANDOM_NUMBERS_ms / portTICK_RATE_MS );
}
if( ulDiceRunTime == 0 )
{
dice7SEG_Value( ucIndex ) = ( dice7SEG_Value( ucIndex ) | 0xf7 ) & cDisplaySegments[ ucIndex ][ rand() % 6 + 1 ];
cDiceState = diceSTATE_STOPPED;
/* Wait for a short time before resuming (un-suspending) the flash
task. The flash tasks are only restarted if a button is not pushed
during this delay - if a button is pushed then the dice are shaken
again.
First...clear any button pushes that are already pending. Again a
block time of zero is used so the function does not wait for any
pushes. */
prvButtonHit( ucIndex, 0 );
if( ucIndex == 0 )
/* Second...peek the semaphore. This task will block/sleep until a
button is pushed again, but because the peek function is used a
button being pushed will unblock the task but remain pending. */
if( xQueuePeek( xSemaphores[ ucIndex ], NULL, diceEND_DELAY ) == pdFALSE )
{
vTaskDelay( diceEND_DELAY );
*pucDisplayOutput[ ucIndex ] = 0xff;
vToggleFlashTaskSuspendState();
}
}
break;
vSuspendFlashTasks( ucIndex, pdFALSE );
}
}
}

@ -66,80 +66,92 @@
/* Scheduler include files. */
#include "FreeRTOS.h"
#include "task.h"
#include "croutine.h"
/* Demo program include files. */
#include "partest.h"
#include "flash.h"
#define ledSTACK_SIZE configMINIMAL_STACK_SIZE
#define ledNUMBER_OF_LEDS ( 3 )
#define ledNUMBER_OF_LEDS ( 7 )
#define ledFLASH_RATE_BASE ( ( portTickType ) 333 )
/* Variable used by the created tasks to calculate the LED number to use, and
the rate at which they should flash the LED. */
static volatile unsigned portBASE_TYPE uxFlashTaskNumber = 0;
#define ledMAX_FLASH_CO_ROUTINES 7
#define ledCO_ROUTINE_PRIORITY 0
/* The task that is created three times. */
static portTASK_FUNCTION_PROTO( vLEDFlashTask, pvParameters );
static void vLEDFlashTask( void *pvParameters );
static void prvFixedDelayCoRoutine( xCoRoutineHandle xHandle, unsigned short usIndex );
/* This task is created once, but itself creates 7 co-routines. */
static void vLEDCoRoutineControlTask( void *pvParameters );
static xTaskHandle xFlashTaskHandles[ ledNUMBER_OF_LEDS ] = { 0 };
static xTaskHandle xCoroutineTask;
/*-----------------------------------------------------------*/
void vStartLEDFlashTasks( unsigned portBASE_TYPE uxPriority )
{
signed portBASE_TYPE xLEDTask;
signed short sLEDTask;
/* Create the three tasks. */
for( xLEDTask = 0; xLEDTask < ledNUMBER_OF_LEDS; ++xLEDTask )
/* Create the three tasks that flash segments on the first LED. */
for( sLEDTask = 0; sLEDTask < ledNUMBER_OF_LEDS; ++sLEDTask )
{
/* Spawn the task. */
xTaskCreate( vLEDFlashTask, ( signed portCHAR * ) "LEDx", ledSTACK_SIZE, NULL, uxPriority, &( xFlashTaskHandles[ xLEDTask ] ) );
xTaskCreate( vLEDFlashTask, ( signed char * ) "LEDt", ledSTACK_SIZE, ( void * ) sLEDTask, uxPriority, &( xFlashTaskHandles[ sLEDTask ] ) );
}
/* Create the task in which the co-routines run. */
xTaskCreate( vLEDCoRoutineControlTask, ( signed char * ) "LEDc", ledSTACK_SIZE, NULL, tskIDLE_PRIORITY, &xCoroutineTask );
}
/*-----------------------------------------------------------*/
void vSuspendFlashTasks( short sSuspendTasks )
void vSuspendFlashTasks( unsigned char ucIndex, short sSuspendTasks )
{
signed portBASE_TYPE xLEDTask;
short sLEDTask;
for( xLEDTask = 0; xLEDTask < ledNUMBER_OF_LEDS; ++xLEDTask )
if( ucIndex == 0 )
{
for( sLEDTask = 0; sLEDTask < ledNUMBER_OF_LEDS; ++sLEDTask )
{
if( xFlashTaskHandles[ xLEDTask ] != NULL )
if( xFlashTaskHandles[ sLEDTask ] != NULL )
{
if( sSuspendTasks == pdTRUE )
{
vTaskSuspend( xFlashTaskHandles[ xLEDTask ] );
vTaskSuspend( xFlashTaskHandles[ sLEDTask ] );
}
else
{
vTaskResume( xFlashTaskHandles[ xLEDTask ] );
vTaskResume( xFlashTaskHandles[ sLEDTask ] );
}
}
}
}
else
{
if( sSuspendTasks == pdTRUE )
{
vTaskSuspend( xCoroutineTask );
}
else
{
vTaskResume( xCoroutineTask );
}
}
}
/*-----------------------------------------------------------*/
static portTASK_FUNCTION( vLEDFlashTask, pvParameters )
static void vLEDFlashTask( void * pvParameters )
{
portTickType xFlashRate, xLastFlashTime;
unsigned portBASE_TYPE uxLED;
/* The parameters are not used. */
( void ) pvParameters;
unsigned short usLED;
/* Calculate the LED and flash rate. */
portENTER_CRITICAL();
{
/* See which of the eight LED's we should use. */
uxLED = uxFlashTaskNumber;
/* The LED to flash is passed in as the task parameter. */
usLED = ( unsigned short ) pvParameters;
/* Update so the next task uses the next LED. */
uxFlashTaskNumber++;
}
portEXIT_CRITICAL();
xFlashRate = ledFLASH_RATE_BASE + ( ledFLASH_RATE_BASE * ( portTickType ) uxLED );
/* Calculate the rate at which this task is going to toggle its LED. */
xFlashRate = ledFLASH_RATE_BASE + ( ledFLASH_RATE_BASE * ( portTickType ) usLED );
xFlashRate /= portTICK_RATE_MS;
/* We will turn the LED on and off again in the delay period, so each
@ -154,11 +166,57 @@ unsigned portBASE_TYPE uxLED;
{
/* Delay for half the flash period then turn the LED on. */
vTaskDelayUntil( &xLastFlashTime, xFlashRate );
vParTestToggleLED( uxLED );
vParTestToggleLED( usLED );
/* Delay for half the flash period then turn the LED off. */
vTaskDelayUntil( &xLastFlashTime, xFlashRate );
vParTestToggleLED( uxLED );
vParTestToggleLED( usLED );
}
}
} /*lint !e715 !e818 !e830 Function definition must be standard for task creation. */
/*-----------------------------------------------------------*/
static void vLEDCoRoutineControlTask( void *pvParameters )
{
unsigned short usCoroutine;
( void ) pvParameters;
for( usCoroutine = 0; usCoroutine < ledMAX_FLASH_CO_ROUTINES; usCoroutine++ )
{
xCoRoutineCreate( prvFixedDelayCoRoutine, ledCO_ROUTINE_PRIORITY, usCoroutine );
}
for( ;; )
{
vCoRoutineSchedule();
}
}
/*-----------------------------------------------------------*/
static void prvFixedDelayCoRoutine( xCoRoutineHandle xHandle, unsigned short usIndex )
{
/* The usIndex parameter of the co-routine function is used as an index into
the xFlashRates array to obtain the delay period to use. */
static const portTickType xFlashRates[ ledMAX_FLASH_CO_ROUTINES ] = { 150 / portTICK_RATE_MS,
300 / portTICK_RATE_MS,
450 / portTICK_RATE_MS,
600 / portTICK_RATE_MS,
750 / portTICK_RATE_MS,
900 / portTICK_RATE_MS,
1050 / portTICK_RATE_MS };
/* Co-routines MUST start with a call to crSTART. */
crSTART( xHandle );
for( ;; )
{
vParTestToggleLED( usIndex + 8 );
crDELAY( xHandle, xFlashRates[ usIndex ] );
}
/* Co-routines MUST end with a call to crEND. */
crEND();
}
/*-----------------------------------------------------------*/

@ -36,8 +36,8 @@ void InitIrqLevels(void)
ICR = ( (54 & 0xFF) << 8 ) | configKERNEL_INTERRUPT_PRIORITY; /* Reload Timer 0 */
ICR = ( (12 & 0xFF) << 8 ) | configKERNEL_INTERRUPT_PRIORITY; /* Delayed interrupt of 16FX Family */
ICR = ( (24 & 0xFF) << 8 ) | ( configKERNEL_INTERRUPT_PRIORITY - 1 ); /* INT8 */
ICR = ( (25 & 0xFF) << 8 ) | ( configKERNEL_INTERRUPT_PRIORITY - 1 ); /* INT9 */
ICR = ( (24 & 0xFF) << 8 ) | configKERNEL_INTERRUPT_PRIORITY; /* INT8 */
ICR = ( (25 & 0xFF) << 8 ) | configKERNEL_INTERRUPT_PRIORITY; /* INT9 */
}
/*---------------------------------------------------------------------------

Loading…
Cancel
Save