]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/MB96350_Softune_Dice_Kit/DiceTask.c
Prepare for V7.3.0 release.
[freertos] / FreeRTOS / Demo / MB96350_Softune_Dice_Kit / DiceTask.c
1 /*\r
2     FreeRTOS V7.3.0 - Copyright (C) 2012 Real Time Engineers Ltd.\r
3 \r
4     FEATURES AND PORTS ARE ADDED TO FREERTOS ALL THE TIME.  PLEASE VISIT \r
5     http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
6 \r
7     ***************************************************************************\r
8      *                                                                       *\r
9      *    FreeRTOS tutorial books are available in pdf and paperback.        *\r
10      *    Complete, revised, and edited pdf reference manuals are also       *\r
11      *    available.                                                         *\r
12      *                                                                       *\r
13      *    Purchasing FreeRTOS documentation will not only help you, by       *\r
14      *    ensuring you get running as quickly as possible and with an        *\r
15      *    in-depth knowledge of how to use FreeRTOS, it will also help       *\r
16      *    the FreeRTOS project to continue with its mission of providing     *\r
17      *    professional grade, cross platform, de facto standard solutions    *\r
18      *    for microcontrollers - completely free of charge!                  *\r
19      *                                                                       *\r
20      *    >>> See http://www.FreeRTOS.org/Documentation for details. <<<     *\r
21      *                                                                       *\r
22      *    Thank you for using FreeRTOS, and thank you for your support!      *\r
23      *                                                                       *\r
24     ***************************************************************************\r
25 \r
26 \r
27     This file is part of the FreeRTOS distribution.\r
28 \r
29     FreeRTOS is free software; you can redistribute it and/or modify it under\r
30     the terms of the GNU General Public License (version 2) as published by the\r
31     Free Software Foundation AND MODIFIED BY the FreeRTOS exception.\r
32     >>>NOTE<<< The modification to the GPL is included to allow you to\r
33     distribute a combined work that includes FreeRTOS without being obliged to\r
34     provide the source code for proprietary components outside of the FreeRTOS\r
35     kernel.  FreeRTOS is distributed in the hope that it will be useful, but\r
36     WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
37     or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for\r
38     more details. You should have received a copy of the GNU General Public\r
39     License and the FreeRTOS license exception along with FreeRTOS; if not it\r
40     can be viewed here: http://www.freertos.org/a00114.html and also obtained\r
41     by writing to Richard Barry, contact details for whom are available on the\r
42     FreeRTOS WEB site.\r
43 \r
44     1 tab == 4 spaces!\r
45     \r
46     ***************************************************************************\r
47      *                                                                       *\r
48      *    Having a problem?  Start by reading the FAQ "My application does   *\r
49      *    not run, what could be wrong?"                                     *\r
50      *                                                                       *\r
51      *    http://www.FreeRTOS.org/FAQHelp.html                               *\r
52      *                                                                       *\r
53     ***************************************************************************\r
54 \r
55     \r
56     http://www.FreeRTOS.org - Documentation, training, latest versions, license \r
57     and contact details.  \r
58     \r
59     http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
60     including FreeRTOS+Trace - an indispensable productivity tool.\r
61 \r
62     Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell \r
63     the code with commercial support, indemnification, and middleware, under \r
64     the OpenRTOS brand: http://www.OpenRTOS.com.  High Integrity Systems also\r
65     provide a safety engineered and independently SIL3 certified version under \r
66     the SafeRTOS brand: http://www.SafeRTOS.com.\r
67 */\r
68 \r
69 \r
70 /* \r
71  * Defines the 'dice' tasks as described at the top of main.c\r
72  */\r
73 \r
74 \r
75 /* Kernel includes. */\r
76 #include "FreeRTOS.h"\r
77 #include "task.h"\r
78 #include "semphr.h"\r
79 \r
80 /* Delays used within the dice functionality.  All delays are defined in milliseconds. */\r
81 #define diceDELAY_BETWEEN_RANDOM_NUMBERS_ms             ( 20 / portTICK_RATE_MS )\r
82 #define diceSHAKE_TIME                                                  ( ( 2000 / portTICK_RATE_MS ) / diceDELAY_BETWEEN_RANDOM_NUMBERS_ms )\r
83 #define diceSHORT_PAUSE_BEFORE_SHAKE                    ( 250 / portTICK_RATE_MS )\r
84 #define diceDELAY_WHILE_DISPLAYING_RESULT               ( 5000 / portTICK_RATE_MS )\r
85 \r
86 /* Macro to access the display ports. */\r
87 #define dice7SEG_Value( x )             ( *( pucDisplayOutput[ x ] ) )\r
88 \r
89 /* Checks the semaphore use to communicate button push events.  A block time\r
90 can be specified - this is the time to wait for a button push to occur should\r
91 one have not already occurred. */\r
92 #define prvButtonHit( ucIndex, xTicksToWait ) xSemaphoreTake( xSemaphores[ ucIndex ], xTicksToWait )\r
93 \r
94 /* Defines the outputs required for each digit on the display. */\r
95 static const char cDisplaySegments[ 2 ][ 11 ] =\r
96 {\r
97         { 0x48, 0xeb, 0x8c, 0x89, 0x2b, 0x19, 0x18, 0xcb, 0x08, 0x09, 0xf7 }, /* Left display. */\r
98         { 0xa0, 0xf3, 0xc4, 0xc1, 0x93, 0x89, 0x88, 0xe3, 0x80, 0x81, 0x7f }  /* Right display. */\r
99 };\r
100 \r
101 /* The semaphores used to communicate button push events between the button\r
102 input interrupt handlers and the dice tasks.  Two dice tasks are created so two\r
103 semaphores are required. */\r
104 static xSemaphoreHandle xSemaphores[ 2 ] = { 0 };\r
105 \r
106 /* Defines the ports used to write to the display.  This variable is defined in\r
107 partest.c, which contains the LED set/clear/toggle functions. */\r
108 extern volatile unsigned char *pucDisplayOutput[ 2 ];\r
109 \r
110 /*-----------------------------------------------------------*/\r
111 \r
112 /* \r
113  * Defines the 'dice' tasks as described at the top of main.c\r
114  */\r
115 void vDiceTask( void *pvParameters )\r
116 {\r
117 unsigned char ucDiceValue, ucIndex;\r
118 unsigned long ulDiceRunTime;\r
119 extern void vSuspendFlashTasks( unsigned char ucIndex, short sSuspendTasks );\r
120 \r
121 \r
122 \r
123         /* Two instances of this task are created so the task parameter is used\r
124         to pass in a constant that indicates whether this task is controlling\r
125         the left side or right side display.  The constant is used as an index\r
126         into the arrays defined at file scope within this file. */\r
127         ucIndex = ( unsigned char ) pvParameters;\r
128         \r
129         /* A binary semaphore is used to signal button push events.  Create the\r
130         semaphore before it is used. */\r
131         vSemaphoreCreateBinary( xSemaphores[ ucIndex ] );\r
132 \r
133         /* Make sure the semaphore starts in the wanted state - no button pushes \r
134         pending. This call will just clear any button pushes that are latched.\r
135         Passing in 0 as the block time means the call will not wait for any further\r
136         button pushes but instead return immediately. */\r
137         prvButtonHit( ucIndex, 0 );\r
138 \r
139         /* Seed the random number generator. */\r
140         srand( ( unsigned char ) diceSHAKE_TIME );\r
141 \r
142 \r
143 \r
144 \r
145         /* Start the task proper.  A loop will be performed each time a button is\r
146         pushed.  The task will remain in the blocked state (sleeping) until a \r
147         button is pushed. */\r
148         for( ;; )\r
149         {\r
150                 /* Wait for a button push.  This task will enter the Blocked state\r
151                 (will not run again) until after a button has been pushed. */\r
152                 prvButtonHit( ucIndex, portMAX_DELAY );\r
153                 \r
154                 /* The next line will only execute after a button has been pushed -\r
155                 initialise the variable used to control the time the dice is shaken\r
156                 for. */\r
157                 ulDiceRunTime = diceSHAKE_TIME;                         \r
158 \r
159                 /* Suspend the flash tasks so this task has exclusive access to the\r
160                 display. */\r
161                 vSuspendFlashTasks( ucIndex, pdTRUE );\r
162 \r
163                 /* Clear the display and pause for a short time, before starting to\r
164                 shake. */\r
165                 *pucDisplayOutput[ ucIndex ] = 0xff;\r
166                 vTaskDelay( diceSHORT_PAUSE_BEFORE_SHAKE );\r
167 \r
168                 /* Keep generating and displaying random numbers until the shake time\r
169                 expires. */\r
170                 while( ulDiceRunTime > 0 )\r
171                 {\r
172                         ulDiceRunTime--;\r
173 \r
174                         /* Generate and display a random number. */\r
175                         ucDiceValue = rand() % 6 + 1;\r
176                         dice7SEG_Value( ucIndex ) = ( dice7SEG_Value( ucIndex ) | 0xf7 ) & cDisplaySegments[ ucIndex ][ ucDiceValue ];\r
177 \r
178                         /* Block/sleep for a very short time before generating the next\r
179                         random number. */\r
180                         vTaskDelay( diceDELAY_BETWEEN_RANDOM_NUMBERS_ms );\r
181                 }\r
182 \r
183 \r
184 \r
185                 /* Clear any button pushes that are pending because a button bounced, or\r
186                 was pressed while the dice were shaking.  Again a block time of zero is \r
187                 used so the function does not wait for any pushes but instead returns\r
188                 immediately. */\r
189                 prvButtonHit( ucIndex, 0 );\r
190 \r
191                 /* Delay for a short while to display the dice shake result.  Use a queue\r
192                 peek here instead of a vTaskDelay() allows the delay to be interrupted by\r
193                 a button push.  If a button is pressed xQueuePeek() will return but the\r
194                 button push will remain pending to be read again at the top of this for\r
195                 loop.  It is safe to uses a queue function on a semaphore handle as\r
196                 semaphores are implemented as macros that uses queues, so the two are \r
197                 basically the same thing. */\r
198                 xQueuePeek( xSemaphores[ ucIndex ], NULL, diceDELAY_WHILE_DISPLAYING_RESULT );\r
199 \r
200                 /* Clear the display then resume the tasks or co-routines that were using\r
201                 the segments of the display. */\r
202                 *pucDisplayOutput[ ucIndex ] = 0xff;\r
203                 vSuspendFlashTasks( ucIndex, pdFALSE );\r
204         }\r
205 }\r
206 /*-----------------------------------------------------------*/\r
207 \r
208 /* Handler for the SW2 button push interrupt. */\r
209 __interrupt void vExternalInt8Handler( void )\r
210 {\r
211 short sHigherPriorityTaskWoken = pdFALSE;\r
212 \r
213         /* Reset the interrupt. */\r
214         EIRR1_ER8 = 0;\r
215 \r
216         /* Check the semaphore has been created before attempting to use it. */\r
217         if( xSemaphores[ configLEFT_DISPLAY ] != NULL )\r
218         {\r
219                 /* Send a message via the semaphore to the dice task that controls the\r
220                 left side display.  This will unblock the task if it is blocked waiting\r
221                 for a button push. */\r
222                 xSemaphoreGiveFromISR( xSemaphores[ configLEFT_DISPLAY ], &sHigherPriorityTaskWoken );\r
223         }\r
224 \r
225         /* If sending the semaphore unblocked a task, and the unblocked task has a\r
226         priority that is higher than the currently running task, then force a context\r
227         switch. */\r
228         if( sHigherPriorityTaskWoken != pdFALSE )\r
229         {\r
230                 portYIELD_FROM_ISR();\r
231         }\r
232 }\r
233 /*-----------------------------------------------------------*/\r
234 \r
235 /* As per vExternalInt8Handler(), but for SW3 and the right side display. */\r
236 __interrupt void vExternalInt9Handler( void )\r
237 {\r
238 short sHigherPriorityTaskWoken = pdFALSE;\r
239 \r
240         /* Reset the interrupt. */\r
241         EIRR1_ER9 = 0;\r
242 \r
243         if( xSemaphores[ configRIGHT_DISPLAY ] != NULL )\r
244         {\r
245                 xSemaphoreGiveFromISR( xSemaphores[ configRIGHT_DISPLAY ], &sHigherPriorityTaskWoken );\r
246         }\r
247 \r
248         if( sHigherPriorityTaskWoken != pdFALSE )\r
249         {\r
250                 portYIELD_FROM_ISR();\r
251         }\r
252 }\r
253 \r
254 \r
255 \r
256 \r
257 \r
258 \r
259 \r