]> git.sur5r.net Git - freertos/blob - Demo/MB96350_Softune_Dice_Kit/DiceTask.c
Update to V5.1.2.
[freertos] / Demo / MB96350_Softune_Dice_Kit / DiceTask.c
1 /*\r
2         FreeRTOS.org V5.1.2 - Copyright (C) 2003-2009 Richard Barry.\r
3 \r
4         This file is part of the FreeRTOS.org distribution.\r
5 \r
6         FreeRTOS.org is free software; you can redistribute it and/or modify\r
7         it under the terms of the GNU General Public License as published by\r
8         the Free Software Foundation; either version 2 of the License, or\r
9         (at your option) any later version.\r
10 \r
11         FreeRTOS.org is distributed in the hope that it will be useful,\r
12         but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14         GNU General Public License for more details.\r
15 \r
16         You should have received a copy of the GNU General Public License\r
17         along with FreeRTOS.org; if not, write to the Free Software\r
18         Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
19 \r
20         A special exception to the GPL can be applied should you wish to distribute\r
21         a combined work that includes FreeRTOS.org, without being obliged to provide\r
22         the source code for any proprietary components.  See the licensing section \r
23         of http://www.FreeRTOS.org for full details of how and when the exception\r
24         can be applied.\r
25 \r
26     ***************************************************************************\r
27     ***************************************************************************\r
28     *                                                                         *\r
29     * Get the FreeRTOS eBook!  See http://www.FreeRTOS.org/Documentation      *\r
30         *                                                                         *\r
31         * This is a concise, step by step, 'hands on' guide that describes both   *\r
32         * general multitasking concepts and FreeRTOS specifics. It presents and   *\r
33         * explains numerous examples that are written using the FreeRTOS API.     *\r
34         * Full source code for all the examples is provided in an accompanying    *\r
35         * .zip file.                                                              *\r
36     *                                                                         *\r
37     ***************************************************************************\r
38     ***************************************************************************\r
39 \r
40         Please ensure to read the configuration and relevant port sections of the\r
41         online documentation.\r
42 \r
43         http://www.FreeRTOS.org - Documentation, latest information, license and \r
44         contact details.\r
45 \r
46         http://www.SafeRTOS.com - A version that is certified for use in safety \r
47         critical systems.\r
48 \r
49         http://www.OpenRTOS.com - Commercial support, development, porting, \r
50         licensing and training services.\r
51 */\r
52 \r
53 \r
54 /* \r
55  * Defines the 'dice' tasks as described at the top of main.c\r
56  */\r
57 \r
58 \r
59 /* Kernel includes. */\r
60 #include "FreeRTOS.h"\r
61 #include "task.h"\r
62 #include "semphr.h"\r
63 \r
64 /* Delays used within the dice functionality.  All delays are defined in milliseconds. */\r
65 #define diceDELAY_BETWEEN_RANDOM_NUMBERS_ms             ( 20 / portTICK_RATE_MS )\r
66 #define diceSHAKE_TIME                                                  ( ( 2000 / portTICK_RATE_MS ) / diceDELAY_BETWEEN_RANDOM_NUMBERS_ms )\r
67 #define diceSHORT_PAUSE_BEFORE_SHAKE                    ( 250 / portTICK_RATE_MS )\r
68 #define diceDELAY_WHILE_DISPLAYING_RESULT               ( 5000 / portTICK_RATE_MS )\r
69 \r
70 /* Macro to access the display ports. */\r
71 #define dice7SEG_Value( x )             ( *( pucDisplayOutput[ x ] ) )\r
72 \r
73 /* Checks the semaphore use to communicate button push events.  A block time\r
74 can be specified - this is the time to wait for a button push to occur should\r
75 one have not already occurred. */\r
76 #define prvButtonHit( ucIndex, xTicksToWait ) xSemaphoreTake( xSemaphores[ ucIndex ], xTicksToWait )\r
77 \r
78 /* Defines the outputs required for each digit on the display. */\r
79 static const char cDisplaySegments[ 2 ][ 11 ] =\r
80 {\r
81         { 0x48, 0xeb, 0x8c, 0x89, 0x2b, 0x19, 0x18, 0xcb, 0x08, 0x09, 0xf7 }, /* Left display. */\r
82         { 0xa0, 0xf3, 0xc4, 0xc1, 0x93, 0x89, 0x88, 0xe3, 0x80, 0x81, 0x7f }  /* Right display. */\r
83 };\r
84 \r
85 /* The semaphores used to communicate button push events between the button\r
86 input interrupt handlers and the dice tasks.  Two dice tasks are created so two\r
87 semaphores are required. */\r
88 static xSemaphoreHandle xSemaphores[ 2 ] = { 0 };\r
89 \r
90 /* Defines the ports used to write to the display.  This variable is defined in\r
91 partest.c, which contains the LED set/clear/toggle functions. */\r
92 extern volatile unsigned char *pucDisplayOutput[ 2 ];\r
93 \r
94 /*-----------------------------------------------------------*/\r
95 \r
96 /* \r
97  * Defines the 'dice' tasks as described at the top of main.c\r
98  */\r
99 void vDiceTask( void *pvParameters )\r
100 {\r
101 unsigned char ucDiceValue, ucIndex;\r
102 unsigned long ulDiceRunTime;\r
103 extern void vSuspendFlashTasks( unsigned char ucIndex, short sSuspendTasks );\r
104 \r
105 \r
106 \r
107         /* Two instances of this task are created so the task parameter is used\r
108         to pass in a constant that indicates whether this task is controlling\r
109         the left side or right side display.  The constant is used as an index\r
110         into the arrays defined at file scope within this file. */\r
111         ucIndex = ( unsigned char ) pvParameters;\r
112         \r
113         /* A binary semaphore is used to signal button push events.  Create the\r
114         semaphore before it is used. */\r
115         vSemaphoreCreateBinary( xSemaphores[ ucIndex ] );\r
116 \r
117         /* Make sure the semaphore starts in the wanted state - no button pushes \r
118         pending. This call will just clear any button pushes that are latched.\r
119         Passing in 0 as the block time means the call will not wait for any further\r
120         button pushes but instead return immediately. */\r
121         prvButtonHit( ucIndex, 0 );\r
122 \r
123         /* Seed the random number generator. */\r
124         srand( ( unsigned char ) diceSHAKE_TIME );\r
125 \r
126 \r
127 \r
128 \r
129         /* Start the task proper.  A loop will be performed each time a button is\r
130         pushed.  The task will remain in the blocked state (sleeping) until a \r
131         button is pushed. */\r
132         for( ;; )\r
133         {\r
134                 /* Wait for a button push.  This task will enter the Blocked state\r
135                 (will not run again) until after a button has been pushed. */\r
136                 prvButtonHit( ucIndex, portMAX_DELAY );\r
137                 \r
138                 /* The next line will only execute after a button has been pushed -\r
139                 initialise the variable used to control the time the dice is shaken\r
140                 for. */\r
141                 ulDiceRunTime = diceSHAKE_TIME;                         \r
142 \r
143                 /* Suspend the flash tasks so this task has exclusive access to the\r
144                 display. */\r
145                 vSuspendFlashTasks( ucIndex, pdTRUE );\r
146 \r
147                 /* Clear the display and pause for a short time, before starting to\r
148                 shake. */\r
149                 *pucDisplayOutput[ ucIndex ] = 0xff;\r
150                 vTaskDelay( diceSHORT_PAUSE_BEFORE_SHAKE );\r
151 \r
152                 /* Keep generating and displaying random numbers until the shake time\r
153                 expires. */\r
154                 while( ulDiceRunTime > 0 )\r
155                 {\r
156                         ulDiceRunTime--;\r
157 \r
158                         /* Generate and display a random number. */\r
159                         ucDiceValue = rand() % 6 + 1;\r
160                         dice7SEG_Value( ucIndex ) = ( dice7SEG_Value( ucIndex ) | 0xf7 ) & cDisplaySegments[ ucIndex ][ ucDiceValue ];\r
161 \r
162                         /* Block/sleep for a very short time before generating the next\r
163                         random number. */\r
164                         vTaskDelay( diceDELAY_BETWEEN_RANDOM_NUMBERS_ms );\r
165                 }\r
166 \r
167 \r
168 \r
169                 /* Clear any button pushes that are pending because a button bounced, or\r
170                 was pressed while the dice were shaking.  Again a block time of zero is \r
171                 used so the function does not wait for any pushes but instead returns\r
172                 immediately. */\r
173                 prvButtonHit( ucIndex, 0 );\r
174 \r
175                 /* Delay for a short while to display the dice shake result.  Use a queue\r
176                 peek here instead of a vTaskDelay() allows the delay to be interrupted by\r
177                 a button push.  If a button is pressed xQueuePeek() will return but the\r
178                 button push will remain pending to be read again at the top of this for\r
179                 loop.  It is safe to uses a queue function on a semaphore handle as\r
180                 semaphores are implemented as macros that uses queues, so the two are \r
181                 basically the same thing. */\r
182                 xQueuePeek( xSemaphores[ ucIndex ], NULL, diceDELAY_WHILE_DISPLAYING_RESULT );\r
183 \r
184                 /* Clear the display then resume the tasks or co-routines that were using\r
185                 the segments of the display. */\r
186                 *pucDisplayOutput[ ucIndex ] = 0xff;\r
187                 vSuspendFlashTasks( ucIndex, pdFALSE );\r
188         }\r
189 }\r
190 /*-----------------------------------------------------------*/\r
191 \r
192 /* Handler for the SW2 button push interrupt. */\r
193 __interrupt void vExternalInt8Handler( void )\r
194 {\r
195 short sHigherPriorityTaskWoken = pdFALSE;\r
196 \r
197         /* Reset the interrupt. */\r
198         EIRR1_ER8 = 0;\r
199 \r
200         /* Check the semaphore has been created before attempting to use it. */\r
201         if( xSemaphores[ configLEFT_DISPLAY ] != NULL )\r
202         {\r
203                 /* Send a message via the semaphore to the dice task that controls the\r
204                 left side display.  This will unblock the task if it is blocked waiting\r
205                 for a button push. */\r
206                 xSemaphoreGiveFromISR( xSemaphores[ configLEFT_DISPLAY ], &sHigherPriorityTaskWoken );\r
207         }\r
208 \r
209         /* If sending the semaphore unblocked a task, and the unblocked task has a\r
210         priority that is higher than the currently running task, then force a context\r
211         switch. */\r
212         if( sHigherPriorityTaskWoken != pdFALSE )\r
213         {\r
214                 portYIELD_FROM_ISR();\r
215         }\r
216 }\r
217 /*-----------------------------------------------------------*/\r
218 \r
219 /* As per vExternalInt8Handler(), but for SW3 and the right side display. */\r
220 __interrupt void vExternalInt9Handler( void )\r
221 {\r
222 short sHigherPriorityTaskWoken = pdFALSE;\r
223 \r
224         /* Reset the interrupt. */\r
225         EIRR1_ER9 = 0;\r
226 \r
227         if( xSemaphores[ configRIGHT_DISPLAY ] != NULL )\r
228         {\r
229                 xSemaphoreGiveFromISR( xSemaphores[ configRIGHT_DISPLAY ], &sHigherPriorityTaskWoken );\r
230         }\r
231 \r
232         if( sHigherPriorityTaskWoken != pdFALSE )\r
233         {\r
234                 portYIELD_FROM_ISR();\r
235         }\r
236 }\r
237 \r
238 \r
239 \r
240 \r
241 \r
242 \r
243 \r