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