]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/MB96350_Softune_Dice_Kit/DiceTask.c
cae046f767b5542c8fd1c50dfff409f3933e5653
[freertos] / FreeRTOS / Demo / MB96350_Softune_Dice_Kit / DiceTask.c
1 /*\r
2     FreeRTOS V8.2.0rc1 - Copyright (C) 2014 Real Time Engineers Ltd.\r
3     All rights reserved\r
4 \r
5     VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
6 \r
7     This file is part of the FreeRTOS distribution.\r
8 \r
9     FreeRTOS is free software; you can redistribute it and/or modify it under\r
10     the terms of the GNU General Public License (version 2) as published by the\r
11     Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.\r
12 \r
13     >>!   NOTE: The modification to the GPL is included to allow you to     !<<\r
14     >>!   distribute a combined work that includes FreeRTOS without being   !<<\r
15     >>!   obliged to provide the source code for proprietary components     !<<\r
16     >>!   outside of the FreeRTOS kernel.                                   !<<\r
17 \r
18     FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
19     WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
20     FOR A PARTICULAR PURPOSE.  Full license text is available on the following\r
21     link: http://www.freertos.org/a00114.html\r
22 \r
23     1 tab == 4 spaces!\r
24 \r
25     ***************************************************************************\r
26      *                                                                       *\r
27      *    Having a problem?  Start by reading the FAQ "My application does   *\r
28      *    not run, what could be wrong?".  Have you defined configASSERT()?  *\r
29      *                                                                       *\r
30      *    http://www.FreeRTOS.org/FAQHelp.html                               *\r
31      *                                                                       *\r
32     ***************************************************************************\r
33 \r
34     ***************************************************************************\r
35      *                                                                       *\r
36      *    FreeRTOS provides completely free yet professionally developed,    *\r
37      *    robust, strictly quality controlled, supported, and cross          *\r
38      *    platform software that is more than just the market leader, it     *\r
39      *    is the industry's de facto standard.                               *\r
40      *                                                                       *\r
41      *    Help yourself get started quickly while simultaneously helping     *\r
42      *    to support the FreeRTOS project by purchasing a FreeRTOS           *\r
43      *    tutorial book, reference manual, or both:                          *\r
44      *    http://www.FreeRTOS.org/Documentation                              *\r
45      *                                                                       *\r
46     ***************************************************************************\r
47 \r
48     ***************************************************************************\r
49      *                                                                       *\r
50      *   Investing in training allows your team to be as productive as       *\r
51      *   possible as early as possible, lowering your overall development    *\r
52      *   cost, and enabling you to bring a more robust product to market     *\r
53      *   earlier than would otherwise be possible.  Richard Barry is both    *\r
54      *   the architect and key author of FreeRTOS, and so also the world's   *\r
55      *   leading authority on what is the world's most popular real time     *\r
56      *   kernel for deeply embedded MCU designs.  Obtaining your training    *\r
57      *   from Richard ensures your team will gain directly from his in-depth *\r
58      *   product knowledge and years of usage experience.  Contact Real Time *\r
59      *   Engineers Ltd to enquire about the FreeRTOS Masterclass, presented  *\r
60      *   by Richard Barry:  http://www.FreeRTOS.org/contact\r
61      *                                                                       *\r
62     ***************************************************************************\r
63 \r
64     ***************************************************************************\r
65      *                                                                       *\r
66      *    You are receiving this top quality software for free.  Please play *\r
67      *    fair and reciprocate by reporting any suspected issues and         *\r
68      *    participating in the community forum:                              *\r
69      *    http://www.FreeRTOS.org/support                                    *\r
70      *                                                                       *\r
71      *    Thank you!                                                         *\r
72      *                                                                       *\r
73     ***************************************************************************\r
74 \r
75     http://www.FreeRTOS.org - Documentation, books, training, latest versions,\r
76     license and Real Time Engineers Ltd. contact details.\r
77 \r
78     http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
79     including FreeRTOS+Trace - an indispensable productivity tool, a DOS\r
80     compatible FAT file system, and our tiny thread aware UDP/IP stack.\r
81 \r
82     http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.\r
83     Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.\r
84 \r
85     http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High\r
86     Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS\r
87     licenses offer ticketed support, indemnification and commercial middleware.\r
88 \r
89     http://www.SafeRTOS.com - High Integrity Systems also provide a safety\r
90     engineered and independently SIL3 certified version for use in safety and\r
91     mission critical applications that require provable dependability.\r
92 \r
93     1 tab == 4 spaces!\r
94 */\r
95 \r
96 \r
97 /* \r
98  * Defines the 'dice' tasks as described at the top of main.c\r
99  */\r
100 \r
101 \r
102 /* Kernel includes. */\r
103 #include "FreeRTOS.h"\r
104 #include "task.h"\r
105 #include "semphr.h"\r
106 \r
107 /* Delays used within the dice functionality.  All delays are defined in milliseconds. */\r
108 #define diceDELAY_BETWEEN_RANDOM_NUMBERS_ms             ( 20 / portTICK_PERIOD_MS )\r
109 #define diceSHAKE_TIME                                                  ( ( 2000 / portTICK_PERIOD_MS ) / diceDELAY_BETWEEN_RANDOM_NUMBERS_ms )\r
110 #define diceSHORT_PAUSE_BEFORE_SHAKE                    ( 250 / portTICK_PERIOD_MS )\r
111 #define diceDELAY_WHILE_DISPLAYING_RESULT               ( 5000 / portTICK_PERIOD_MS )\r
112 \r
113 /* Macro to access the display ports. */\r
114 #define dice7SEG_Value( x )             ( *( pucDisplayOutput[ x ] ) )\r
115 \r
116 /* Checks the semaphore use to communicate button push events.  A block time\r
117 can be specified - this is the time to wait for a button push to occur should\r
118 one have not already occurred. */\r
119 #define prvButtonHit( ucIndex, xTicksToWait ) xSemaphoreTake( xSemaphores[ ucIndex ], xTicksToWait )\r
120 \r
121 /* Defines the outputs required for each digit on the display. */\r
122 static const char cDisplaySegments[ 2 ][ 11 ] =\r
123 {\r
124         { 0x48, 0xeb, 0x8c, 0x89, 0x2b, 0x19, 0x18, 0xcb, 0x08, 0x09, 0xf7 }, /* Left display. */\r
125         { 0xa0, 0xf3, 0xc4, 0xc1, 0x93, 0x89, 0x88, 0xe3, 0x80, 0x81, 0x7f }  /* Right display. */\r
126 };\r
127 \r
128 /* The semaphores used to communicate button push events between the button\r
129 input interrupt handlers and the dice tasks.  Two dice tasks are created so two\r
130 semaphores are required. */\r
131 static SemaphoreHandle_t xSemaphores[ 2 ] = { 0 };\r
132 \r
133 /* Defines the ports used to write to the display.  This variable is defined in\r
134 partest.c, which contains the LED set/clear/toggle functions. */\r
135 extern volatile unsigned char *pucDisplayOutput[ 2 ];\r
136 \r
137 /*-----------------------------------------------------------*/\r
138 \r
139 /* \r
140  * Defines the 'dice' tasks as described at the top of main.c\r
141  */\r
142 void vDiceTask( void *pvParameters )\r
143 {\r
144 unsigned char ucDiceValue, ucIndex;\r
145 unsigned long ulDiceRunTime;\r
146 extern void vSuspendFlashTasks( unsigned char ucIndex, short sSuspendTasks );\r
147 \r
148 \r
149 \r
150         /* Two instances of this task are created so the task parameter is used\r
151         to pass in a constant that indicates whether this task is controlling\r
152         the left side or right side display.  The constant is used as an index\r
153         into the arrays defined at file scope within this file. */\r
154         ucIndex = ( unsigned char ) pvParameters;\r
155         \r
156         /* A binary semaphore is used to signal button push events.  Create the\r
157         semaphore before it is used. */\r
158         vSemaphoreCreateBinary( xSemaphores[ ucIndex ] );\r
159 \r
160         /* Make sure the semaphore starts in the wanted state - no button pushes \r
161         pending. This call will just clear any button pushes that are latched.\r
162         Passing in 0 as the block time means the call will not wait for any further\r
163         button pushes but instead return immediately. */\r
164         prvButtonHit( ucIndex, 0 );\r
165 \r
166         /* Seed the random number generator. */\r
167         srand( ( unsigned char ) diceSHAKE_TIME );\r
168 \r
169 \r
170 \r
171 \r
172         /* Start the task proper.  A loop will be performed each time a button is\r
173         pushed.  The task will remain in the blocked state (sleeping) until a \r
174         button is pushed. */\r
175         for( ;; )\r
176         {\r
177                 /* Wait for a button push.  This task will enter the Blocked state\r
178                 (will not run again) until after a button has been pushed. */\r
179                 prvButtonHit( ucIndex, portMAX_DELAY );\r
180                 \r
181                 /* The next line will only execute after a button has been pushed -\r
182                 initialise the variable used to control the time the dice is shaken\r
183                 for. */\r
184                 ulDiceRunTime = diceSHAKE_TIME;                         \r
185 \r
186                 /* Suspend the flash tasks so this task has exclusive access to the\r
187                 display. */\r
188                 vSuspendFlashTasks( ucIndex, pdTRUE );\r
189 \r
190                 /* Clear the display and pause for a short time, before starting to\r
191                 shake. */\r
192                 *pucDisplayOutput[ ucIndex ] = 0xff;\r
193                 vTaskDelay( diceSHORT_PAUSE_BEFORE_SHAKE );\r
194 \r
195                 /* Keep generating and displaying random numbers until the shake time\r
196                 expires. */\r
197                 while( ulDiceRunTime > 0 )\r
198                 {\r
199                         ulDiceRunTime--;\r
200 \r
201                         /* Generate and display a random number. */\r
202                         ucDiceValue = rand() % 6 + 1;\r
203                         dice7SEG_Value( ucIndex ) = ( dice7SEG_Value( ucIndex ) | 0xf7 ) & cDisplaySegments[ ucIndex ][ ucDiceValue ];\r
204 \r
205                         /* Block/sleep for a very short time before generating the next\r
206                         random number. */\r
207                         vTaskDelay( diceDELAY_BETWEEN_RANDOM_NUMBERS_ms );\r
208                 }\r
209 \r
210 \r
211 \r
212                 /* Clear any button pushes that are pending because a button bounced, or\r
213                 was pressed while the dice were shaking.  Again a block time of zero is \r
214                 used so the function does not wait for any pushes but instead returns\r
215                 immediately. */\r
216                 prvButtonHit( ucIndex, 0 );\r
217 \r
218                 /* Delay for a short while to display the dice shake result.  Use a queue\r
219                 peek here instead of a vTaskDelay() allows the delay to be interrupted by\r
220                 a button push.  If a button is pressed xQueuePeek() will return but the\r
221                 button push will remain pending to be read again at the top of this for\r
222                 loop.  It is safe to uses a queue function on a semaphore handle as\r
223                 semaphores are implemented as macros that uses queues, so the two are \r
224                 basically the same thing. */\r
225                 xQueuePeek( xSemaphores[ ucIndex ], NULL, diceDELAY_WHILE_DISPLAYING_RESULT );\r
226 \r
227                 /* Clear the display then resume the tasks or co-routines that were using\r
228                 the segments of the display. */\r
229                 *pucDisplayOutput[ ucIndex ] = 0xff;\r
230                 vSuspendFlashTasks( ucIndex, pdFALSE );\r
231         }\r
232 }\r
233 /*-----------------------------------------------------------*/\r
234 \r
235 /* Handler for the SW2 button push interrupt. */\r
236 __interrupt void vExternalInt8Handler( void )\r
237 {\r
238 short sHigherPriorityTaskWoken = pdFALSE;\r
239 \r
240         /* Reset the interrupt. */\r
241         EIRR1_ER8 = 0;\r
242 \r
243         /* Check the semaphore has been created before attempting to use it. */\r
244         if( xSemaphores[ configLEFT_DISPLAY ] != NULL )\r
245         {\r
246                 /* Send a message via the semaphore to the dice task that controls the\r
247                 left side display.  This will unblock the task if it is blocked waiting\r
248                 for a button push. */\r
249                 xSemaphoreGiveFromISR( xSemaphores[ configLEFT_DISPLAY ], &sHigherPriorityTaskWoken );\r
250         }\r
251 \r
252         /* If sending the semaphore unblocked a task, and the unblocked task has a\r
253         priority that is higher than the currently running task, then force a context\r
254         switch. */\r
255         if( sHigherPriorityTaskWoken != pdFALSE )\r
256         {\r
257                 portYIELD_FROM_ISR();\r
258         }\r
259 }\r
260 /*-----------------------------------------------------------*/\r
261 \r
262 /* As per vExternalInt8Handler(), but for SW3 and the right side display. */\r
263 __interrupt void vExternalInt9Handler( void )\r
264 {\r
265 short sHigherPriorityTaskWoken = pdFALSE;\r
266 \r
267         /* Reset the interrupt. */\r
268         EIRR1_ER9 = 0;\r
269 \r
270         if( xSemaphores[ configRIGHT_DISPLAY ] != NULL )\r
271         {\r
272                 xSemaphoreGiveFromISR( xSemaphores[ configRIGHT_DISPLAY ], &sHigherPriorityTaskWoken );\r
273         }\r
274 \r
275         if( sHigherPriorityTaskWoken != pdFALSE )\r
276         {\r
277                 portYIELD_FROM_ISR();\r
278         }\r
279 }\r
280 \r
281 \r
282 \r
283 \r
284 \r
285 \r
286 \r