Rev Author Line No. Line
2956 poskozby 1 /*
2 ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
3  
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7  
8 http://www.apache.org/licenses/LICENSE-2.0
9  
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16  
17 #include "ch.h"
18 #include "hal.h"
19 #include "test.h"
20 #include "serial.h"
21 #include "gpt.h"
22 #include <string.h>
23 #include "keil/GPS_dekoduj.h"
24 #include <../../os/various/chprintf.h>
25 #include <chstreams.h.>
26  
27 /*MAX delka prikazu, ktery uzivatel muze zadat*/
28 #define MAX_DELKA_PRIKAZU 10
29  
30 /*Velikost GPS bufferu*/
31 #define GPS_BUFFER 700
32 #define PWM_PERIODA_NORMAL 20000
33 #define PWM_SIRKA_NORMAL PWM_PERIODA_NORMAL/2
34  
35 extern NMEA_GPRMC GPRMC_informace;
36 Thread *tp_odpal = NULL;
37 uint8_t uvitaci_zprava[] = "\r\n\r\n* * * * * * * * * * * * * * * * * * * * * * * * * *\r\nVita vas Automaticky Vypoustec Meteobalonu 1.1\r\nZapojeni vyvodu:\r\n\tGPIOB10 - ventil\r\n\tGPIOB11 - lis\r\n\tGPIOB12 - zataveni balonu\r\n\tGPIOB13 - otevreni krytu\r\nPrikazy:\r\n\t<odpal> zahajeni sekvence vypousteni\n\r\t<zrus> zruseni vypousteni\n\r\t<help> napoveda\r\n* * * * * * * * * * * * * * * * * * * * * * * * * *\r\n\r\n";
38  
39 static PWMConfig pwmcfg = {
40 10000, /* 10kHz PWM clock frequency. */
41 PWM_PERIODA_NORMAL, /* PWM period 1S (in ticks). */
42 NULL,
43 {
44 {PWM_OUTPUT_ACTIVE_HIGH, NULL},
45 {PWM_OUTPUT_ACTIVE_HIGH, NULL},
46 {PWM_OUTPUT_DISABLED, NULL},
47 {PWM_OUTPUT_DISABLED, NULL}
48 },
49 /* HW dependent part.*/
50  
51 };
52  
53 /*
54 * Konfigurace USART2
55 */
56  
57 static const SerialConfig USART2_config =
58 {
59 /*Speed*/
60 9600,
61 /*Initialization value for the CR1 register.*/
62 0,
63 /*Initialization value for the CR2 register.*/
64 USART_CR2_STOP1_BITS | USART_CR2_LINEN,
65 /*Initialization value for the CR3 register.*/
66  
67 };
68  
69  
70 /*
71 * GPT2 callback.
72 */
73 static void gpt2cb(GPTDriver *gptp)
74 {
75 (void)gptp;
76 /* Wakes up the thread.*/
77 chSysLockFromIsr();
78 if (tp_odpal != NULL) {
79 tp_odpal->p_u.rdymsg = (msg_t)50; /* Znaci, ze se vlakno probouzi kvuli preruseni od GPT*/
80 chSchReadyI(tp_odpal);
81 tp_odpal = NULL;
82 }
83 chSysUnlockFromIsr();
84 }
85  
86  
87 /*
88 *Konfigurace casovace 2
89 */
90 static const GPTConfig gpt2cfg =
91 {
92 1000, /*1000Hz f*/
93 gpt2cb /*callback fce*/
94 };
95  
96 /*
97 * Vypise cas a datum, pokud jsou tyto informace k dispozici
98 */
99 uint8_t Vypis_cas_datum()
100 {
101 if(GPRMC_informace.Status_GPS[0] == 'A')
102 {
103 chprintf((BaseSequentialStream *)&SD1,(char *)GPRMC_informace.Datum);
104 chprintf((BaseSequentialStream *)&SD1,"\r\n");
105 chprintf((BaseSequentialStream *)&SD1,(char *)GPRMC_informace.UTC_time);
106 chprintf((BaseSequentialStream *)&SD1,"\r\n");
107 return 1;
108 }
109 else
110 return 0;
111 }
112  
113 /*
114 * Vlakno pro ovladani odpalovaci sekvence
115 */
116 static WORKING_AREA(waThread_odpal, 128);
117 static msg_t Thread_odpal(void *arg) {
118 uint8_t stav = 0; // rika, ve ktere fazi je odpalovani
119 uint8_t odpal_povolen = 0;
120 uint8_t odpal_pomocna = 0;
121 uint8_t pocet_opakovani = 1;
122 uint16_t perioda_casovace = 500;
123 (void)arg;
124 chRegSetThreadName("Odpal_vlakno");
125  
126  
127 while (TRUE)
128 {
129 msg_t msg;
130  
131 /* Waiting for the IRQ to happen.*/
132 chSysLock();
133 tp_odpal = chThdSelf();
134 chSchGoSleepS(THD_STATE_SUSPENDED);
135 msg = chThdSelf()->p_u.rdymsg; /* Retrieving the message, optional.*/
136 chSysUnlock();
137 /* Perform processing here.*/
138 if(msg == 1)
139 {
140 odpal_povolen = 1;
141 odpal_pomocna++;
142 stav = 0;
143 pocet_opakovani = 1;
144 }
145 else if (msg == 2) //Pokud se ma odpal zrusit v prubehu vypousteni
146 {
147 /*
148 * Pro jistotu se vypnou vsechny vystupy pri zruseni odpalu
149 */
150 palClearPad(GPIOB, GPIOB_PIN10);
151 palClearPad(GPIOB, GPIOB_PIN11);
152 palClearPad(GPIOB, GPIOB_PIN12);
153 palClearPad(GPIOB, GPIOB_PIN13);
154  
155 if(odpal_povolen == 1)
156 chprintf((BaseSequentialStream *)&SD1,"\r\nOdpal zrusen uzivatelem.\r\n");
157 else
158 chprintf((BaseSequentialStream *)&SD1,"Odpal nebyl aktivovan.\r\n");
159  
160 Vypis_cas_datum();
161 odpal_povolen = 0;
162 odpal_pomocna = 0;
163 stav = 0;
164 pocet_opakovani = 1;
165 }
166 else if (msg == 50 && odpal_povolen == 1) // preruseni od GPT
167 {
168 odpal_pomocna = 1;
169 }
170 if (odpal_povolen == 1 && odpal_pomocna <= 1)
171 {
172 odpal_pomocna = 2; // aby nepretelkla tato promenna
173 switch (stav)
174 {
175 case 0:
176 if (pocet_opakovani == 1)
177 {
178 chprintf((BaseSequentialStream *)&SD1,"Vypousteni zahajeno!\r\n");
179 Vypis_cas_datum();
180 }
181  
182 if (pocet_opakovani <= 20)
183 {
184 //sdWrite(&SD1,,sizeof("1/4)\tVentil otevren -> nafukovani balonu\r\n")/sizeof(char));
185 chprintf((BaseSequentialStream *)&SD1,"(1/4)\tVentil otevren -> nafukovani balonu %d%%\r",pocet_opakovani*5);
186 palSetPad(GPIOB, GPIOB_PIN10);
187 gptStartOneShot(&GPTD2,perioda_casovace);
188 pocet_opakovani++;
189 if (pocet_opakovani == 21)
190 {
191 chprintf((BaseSequentialStream *)&SD1,"\r\n");
192 stav++;
193 pocet_opakovani = 1;
194 }
195 }
196 break;
197 case 1:
198 if (pocet_opakovani <= 10)
199 {
200 palClearPad(GPIOB, GPIOB_PIN10);
201 palSetPad(GPIOB, GPIOB_PIN11);
202 chprintf((BaseSequentialStream *)&SD1,"(2/4)\tPrepalovani lisu... %d%%\r",pocet_opakovani*10);
203 gptStartOneShot(&GPTD2,perioda_casovace);
204 pocet_opakovani++;
205 if (pocet_opakovani == 11)
206 {
207 chprintf((BaseSequentialStream *)&SD1,"\r\n");
208 stav++;
209 pocet_opakovani = 1;
210 }
211 }
212 break;
213 case 2:
214 if (pocet_opakovani <= 10)
215 {
216 palClearPad(GPIOB, GPIOB_PIN11);
217 palSetPad(GPIOB, GPIOB_PIN12);
218 chprintf((BaseSequentialStream *)&SD1,"(3/4)\tZatavovani balonu... %d%%\r",pocet_opakovani*10);
219 gptStartOneShot(&GPTD2,perioda_casovace);
220 pocet_opakovani++;
221 if (pocet_opakovani == 11)
222 {
223 chprintf((BaseSequentialStream *)&SD1,"\r\n");
224 stav++;
225 pocet_opakovani = 1;
226 }
227 }
228 break;
229 case 3:
230 if (pocet_opakovani <= 20)
231 {
232 palClearPad(GPIOB, GPIOB_PIN12);
233 palSetPad(GPIOB, GPIOB_PIN13);
234 chprintf((BaseSequentialStream *)&SD1,"(4/4)\tOtevirani vika... %d%%\r",pocet_opakovani*5);
235 gptStartOneShot(&GPTD2,perioda_casovace);
236 pocet_opakovani++;
237 if (pocet_opakovani == 21)
238 {
239 chprintf((BaseSequentialStream *)&SD1,"\r\n");
240 stav++;
241 pocet_opakovani = 1;
242 }
243 }
244 break;
245 case 4:
246 palClearPad(GPIOB, GPIOB_PIN13);
247 chprintf((BaseSequentialStream *)&SD1,"Vypousteni ukonceno!\r\n");
248 Vypis_cas_datum();
249 odpal_povolen = 0;
250 odpal_pomocna = 0;
251 stav = 0;
252 break;
253 default:
254 break;
255 }
256 }
257 }
258 }
259  
260  
261 /*
262 * Vlakno pro obsluhu GPS prijimace
263 */
264 static WORKING_AREA(waThread_GPS, 1024);
265 static msg_t Thread_GPS(void *arg) {
266 /*
267 * Nacita se jen nekolik NMEA zprav, aby se neplytvalo pameti na ulozeni kompletniho
268 * setu s tím rizikem, ze se nekdy nenacte aktualni informace o poloze.
269 */
270 uint8_t inBuffer[GPS_BUFFER];
271 char *zacatek_retezce;
272 char *konec_retezce;
273 uint8_t pocet_znaku;
274 uint8_t NMEA_zprava[100];
275  
276  
277 (void)arg;
278 chRegSetThreadName("GPS_NMEA");
279  
280 while (TRUE) {
281 chThdSleepMilliseconds(900); //neni potreba data vycitat rychleji
282  
283 sdRead(&SD2,inBuffer,GPS_BUFFER);
284  
285 /*
286 *Nejprve se vycte cast NMEA dat, pote se vyhleda retezec GPGGA zpravy, ta se vyparsuje a pomoci fce
287 *dekoduj_zpravu_GPS, ktera vyparsuje data o poloze a jine, a ulozi je do struktury GPGGA_informace.
288 */
289  
290 if ((zacatek_retezce = strstr((char *)inBuffer,"$GPRMC")) != NULL)
291 {
292 if ((konec_retezce = strstr(zacatek_retezce,"*")) != NULL)
293 {
294 pocet_znaku = (konec_retezce-zacatek_retezce)/sizeof(char);
295 if (pocet_znaku > 100)
296 {
297 pocet_znaku = 100;
298 }
299 strncpy((char *)NMEA_zprava,zacatek_retezce,pocet_znaku);
300 dekoduj_zpravu_GPS(&NMEA_zprava[0],pocet_znaku);
301  
302 chprintf((BaseSequentialStream *)&SD2,"Latitude: %s\r\n",GPRMC_informace.Latitude);
303 chprintf((BaseSequentialStream *)&SD2,"Longitude: %s\r\n",GPRMC_informace.Longitude);
304 chprintf((BaseSequentialStream *)&SD2,"Datum: %s\r\n",GPRMC_informace.Datum);
305 chprintf((BaseSequentialStream *)&SD2,"Status: %s\r\n",GPRMC_informace.Status_GPS);
306 chprintf((BaseSequentialStream *)&SD2,"Cas: %s\r\n",GPRMC_informace.UTC_time);
307 NMEA_zprava[pocet_znaku] = 0;
308 chprintf((BaseSequentialStream *)&SD2,(char *)NMEA_zprava);
309 sdWrite(&SD2,"\r\n",2);
310 }
311 else
312 {
313 sdWrite(&SD2,"\r\n",2);
314 chprintf((BaseSequentialStream *)&SD2,"Nenalezen ukoncovaci znak NMEA zpravy *\r\n");
315 sdWrite(&SD2,inBuffer,GPS_BUFFER);
316 }
317 }
318 else
319 chprintf((BaseSequentialStream *)&SD2,"Nenalezen zacatek GPRMC zpravy\r\n");
320 }
321 }
322  
323 void dekodujPrikaz(char *prikaz)
324 {
325 if(strcmp(prikaz,"odpal") == 0)
326 {
327 /* Wakes up the thread.*/
328 chSysLockFromIsr();
329 if (tp_odpal != NULL) {
330 tp_odpal->p_u.rdymsg = (msg_t)1; /* odpal povolen*/
331 chSchReadyI(tp_odpal);
332 tp_odpal = NULL;
333 }
334 chSysUnlockFromIsr();
335  
336 }
337 else if (strcmp(prikaz,"zrus") == 0)
338 {
339 /* Wakes up the thread.*/
340 chSysLockFromIsr();
341 if (tp_odpal != NULL) {
342 tp_odpal->p_u.rdymsg = (msg_t)2; /* zakazano pokracovat v odpalovaci sekvenci*/
343 chSchReadyI(tp_odpal);
344 tp_odpal = NULL;
345 }
346 chSysUnlockFromIsr();
347 }
348 else if (strcmp(prikaz,"help") == 0)
349 {
350 chprintf((BaseSequentialStream *)&SD1,(char *)uvitaci_zprava);
351 }
352 else
353 {
354 uint8_t zp_neplatny[] = "Neplatny prikaz!\r\n\t<odpal> pro zahajeni sekvence\n\r\t<zrus> pro zruseni vypousteni\n\r\t<help> pro napovedu\r\n";
355 chprintf((BaseSequentialStream *)&SD1,(char *)zp_neplatny);
356 palTogglePad(GPIOB, GPIOB_LED3);
357 }
358 }
359  
360 /*
361 * Application entry point.
362 */
363 int main(void) {
364  
365 uint8_t znaky[20];
366 char prikaz[MAX_DELKA_PRIKAZU + 1];
367 uint8_t pocet_znaku = 0;
368  
369 /*
370 * System initializations.
371 * - HAL initialization, this also initializes the configured device drivers
372 * and performs the board-specific initializations.
373 * - Kernel initialization, the main() function becomes a thread and the
374 * RTOS is active.
375 */
376 halInit();
377 chSysInit();
378  
379 /*
380 * Activates the serial driver 1 using the driver default configuration.
381 * PA9 and PA10 are routed to USART1.
382 * Komunikace s uzivatelem
383 */
384 sdStart(&SD1, NULL);
385 palSetPadMode(GPIOA, 9, PAL_MODE_ALTERNATE(7)); //TX
386 palSetPadMode(GPIOA, 10, PAL_MODE_ALTERNATE(7)); //RX
387  
388 /*
389 * Activates the serial driver 2 using the driver default configuration.
390 * PA2 and PA3 are routed to USART2.
391 *GPS
392 */
393 sdStart(&SD2, &USART2_config);
394 palSetPadMode(GPIOA, 2, PAL_MODE_ALTERNATE(7)); //TX
395 palSetPadMode(GPIOA, 3, PAL_MODE_ALTERNATE(7)); //RX
396  
397 /*
398 * LED na vyvojove desce
399 */
400 palSetPadMode(GPIOB, GPIOB_LED3, PAL_MODE_OUTPUT_PUSHPULL);
401  
402 /*
403 * Initializes the PWM driver 4, routes the TIM4 outputs to the board LEDs.
404 */
405 pwmStart(&PWMD4, &pwmcfg);
406 palSetPadMode(GPIOB, GPIOB_LED4, PAL_MODE_ALTERNATE(2));
407 pwmEnableChannel(&PWMD4,0,PWM_SIRKA_NORMAL);
408  
409  
410 /*
411 * Porty pro vypousteci sekvenci
412 */
413 palSetPadMode(GPIOB, GPIOB_PIN10, PAL_MODE_OUTPUT_PUSHPULL);
414 palClearPad(GPIOB, GPIOB_PIN10);
415 palSetPadMode(GPIOB, GPIOB_PIN11, PAL_MODE_OUTPUT_PUSHPULL);
416 palClearPad(GPIOB, GPIOB_PIN11);
417 palSetPadMode(GPIOB, GPIOB_PIN12, PAL_MODE_OUTPUT_PUSHPULL);
418 palClearPad(GPIOB, GPIOB_PIN12);
419 palSetPadMode(GPIOB, GPIOB_PIN13, PAL_MODE_OUTPUT_PUSHPULL);
420 palClearPad(GPIOB, GPIOB_PIN13);
421 /*
422 * Aktivuje timer2 a timer3 prejde tak do aktivniho stavu
423 */
424 gptStart(&GPTD2,&gpt2cfg);
425 /*
426 * Vytvori vlakno pro prijem dat z GPS modulu
427 */
428 chThdCreateStatic(waThread_GPS, sizeof(waThread_GPS), NORMALPRIO, Thread_GPS, NULL);
429  
430 /*
431 * Vytvori vlakno pro odpalovaci sekvenci
432 */
433 chThdCreateStatic (waThread_odpal, sizeof(waThread_odpal), NORMALPRIO, Thread_odpal, NULL);
434  
435 chprintf((BaseSequentialStream *)&SD1,(char *) uvitaci_zprava);
436 /*
437 * Normal main() thread activity, in this demo it does nothing except
438 * sleeping in a loop and check the button state, when the button is
439 * pressed the test procedure is launched with output on the serial
440 * driver 1.
441 */
442  
443 while (TRUE) {
444  
445 sdRead(&SD1,znaky,1);
446 /*Kdyz uzivatel stiskne enter -> dekoduj a vykonej prikaz, nebo pokud je prikaz delsi, nez by mel byt,
447 *prestane ukladat a upozorni uzivatele
448 */
449 if (znaky[0] == '\r' || pocet_znaku >= MAX_DELKA_PRIKAZU)
450 {
451 pocet_znaku = 0;
452 dekodujPrikaz(prikaz);
453 prikaz[0] = 0;
454 }
455 /*Uklada prikaz*/
456 else
457 {
458 prikaz[pocet_znaku + 1] = 0;
459 prikaz[pocet_znaku++] = znaky[0];
460 }
461 }
462 }