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"
24  
25 static void pwmpcb(PWMDriver *pwmp);
26 static void adccb(ADCDriver *adcp, adcsample_t *buffer, size_t n);
27  
28 /* Total number of channels to be sampled by a single ADC operation.*/
29 #define ADC_GRP1_NUM_CHANNELS 2
30  
31 /* Depth of the conversion buffer, channels are sampled four times each.*/
32 #define ADC_GRP1_BUF_DEPTH 4
33  
34 /*MAX delka prikazu, ktery uzivatel muze zadat*/
35 #define MAX_DELKA_PRIKAZU 10
36  
37 /*Velikost GPS bufferu*/
38 #define GPS_BUFFER 500
39  
40 extern NMEA_GPGGA GPGGA_informace;
41 Thread *tp_odpal = NULL;
42 /*
43 * ADC samples buffer.
44 */
45 static adcsample_t samples[ADC_GRP1_NUM_CHANNELS * ADC_GRP1_BUF_DEPTH];
46  
47 /*
48 * ADC conversion group.
49 * Mode: Linear buffer, 4 samples of 2 channels, SW triggered.
50 * Channels: IN10 (48 cycles sample time)
51 * Sensor (192 cycles sample time)
52 */
53 static const ADCConversionGroup adcgrpcfg = {
54 FALSE,
55 ADC_GRP1_NUM_CHANNELS,
56 adccb,
57 NULL,
58 /* HW dependent part.*/
59 0, /* CR1 */
60 ADC_CR2_SWSTART, /* CR2 */
61 0,
62 ADC_SMPR2_SMP_AN10(ADC_SAMPLE_48) | ADC_SMPR2_SMP_SENSOR(ADC_SAMPLE_192),
63 0,
64 ADC_SQR1_NUM_CH(ADC_GRP1_NUM_CHANNELS),
65 0,
66 0,
67 0,
68 ADC_SQR5_SQ2_N(ADC_CHANNEL_IN10) | ADC_SQR5_SQ1_N(ADC_CHANNEL_SENSOR)
69 };
70 /*
71 * Konfigurace USART2
72 */
73  
74 static const SerialConfig USART2_config =
75 {
76 /*Speed*/
77 9600,
78 /*Initialization value for the CR1 register.*/
79 0,
80 /*Initialization value for the CR2 register.*/
81 USART_CR2_STOP1_BITS | USART_CR2_LINEN,
82 /*Initialization value for the CR3 register.*/
83  
84 };
85 //GPTDriver GPTD2;
86 /*
87 * GPT2 callback.
88 */
89 static void gpt2cb(GPTDriver *gptp)
90 {
91 (void)gptp;
92 palTogglePad(GPIOB, GPIOB_LED4);
93 /* Wakes up the thread.*/
94 chSysLockFromIsr();
95 if (tp_odpal != NULL) {
96 //tp_odpal->p_u.rdymsg = (msg_t)55; /* Sending the message, optional.*/
97 chSchReadyI(tp_odpal);
98 tp_odpal = NULL;
99 }
100 chSysUnlockFromIsr();
101 }
102  
103 /*
104 *Konfigurace casovace 2
105 */
106 static const GPTConfig gpt2cfg =
107 {
108 1000, /*1000Hz f*/
109 gpt2cb /*callback fce*/
110 };
111  
112  
113  
114 /*
115 * PWM configuration structure.
116 * Cyclic callback enabled, channels 1 and 2 enabled without callbacks,
117 * the active state is a logic one.
118 */
119 static PWMConfig pwmcfg = {
120 10000, /* 10kHz PWM clock frequency. */
121 10000, /* PWM period 1S (in ticks). */
122 pwmpcb,
123 {
124 {PWM_OUTPUT_ACTIVE_HIGH, NULL},
125 {PWM_OUTPUT_ACTIVE_HIGH, NULL},
126 {PWM_OUTPUT_DISABLED, NULL},
127 {PWM_OUTPUT_DISABLED, NULL}
128 },
129 /* HW dependent part.*/
130  
131 };
132  
133 /*
134 * USART konfigurace
135 */
136  
137  
138 /*
139 * PWM cyclic callback.
140 * A new ADC conversion is started.
141 */
142 static void pwmpcb(PWMDriver *pwmp) {
143  
144 (void)pwmp;
145  
146 /* Starts an asynchronous ADC conversion operation, the conversion
147 will be executed in parallel to the current PWM cycle and will
148 terminate before the next PWM cycle.*/
149 chSysLockFromIsr();
150 adcStartConversionI(&ADCD1, &adcgrpcfg, samples, ADC_GRP1_BUF_DEPTH);
151 chSysUnlockFromIsr();
152 }
153  
154 /*
155 * ADC end conversion callback.
156 * The PWM channels are reprogrammed using the latest ADC samples.
157 * The latest samples are transmitted into a single SPI transaction.
158 */
159 void adccb(ADCDriver *adcp, adcsample_t *buffer, size_t n) {
160  
161 (void) buffer; (void) n;
162 /* Note, only in the ADC_COMPLETE state because the ADC driver fires an
163 intermediate callback when the buffer is half full.*/
164 if (adcp->state == ADC_COMPLETE) {
165 adcsample_t avg_ch1, avg_ch2;
166  
167 /* Calculates the average values from the ADC samples.*/
168 avg_ch1 = (samples[0] + samples[2] + samples[4] + samples[6]) / 4;
169 avg_ch2 = (samples[1] + samples[3] + samples[5] + samples[7]) / 4;
170  
171 chSysLockFromIsr();
172  
173 /* Changes the channels pulse width, the change will be effective
174 starting from the next cycle.*/
175 pwmEnableChannelI(&PWMD4, 0, PWM_FRACTION_TO_WIDTH(&PWMD4, 4096, avg_ch1));
176 pwmEnableChannelI(&PWMD4, 1, PWM_FRACTION_TO_WIDTH(&PWMD4, 4096, avg_ch2));
177  
178  
179 chSysUnlockFromIsr();
180 }
181 }
182  
183 /*
184 * Vlakno pro ovladani odpalovaci sekvence
185 */
2945 poskozby 186 static WORKING_AREA(waThread_odpal, 128);
187 static msg_t Thread_odpal(void *arg) {
188 uint8_t stav = 0; // rika, ve ktere fazi je odpalovani
189 uint8_t odpal_povolen = 0;
2943 poskozby 190 (void)arg;
191 chRegSetThreadName("Odpal_vlakno");
192 while (TRUE)
193 {
2945 poskozby 194 msg_t msg;
2943 poskozby 195  
196 /* Waiting for the IRQ to happen.*/
197 chSysLock();
198 tp_odpal = chThdSelf();
199 chSchGoSleepS(THD_STATE_SUSPENDED);
2945 poskozby 200 msg = chThdSelf()->p_u.rdymsg; /* Retrieving the message, optional.*/
2943 poskozby 201 chSysUnlock();
202 /* Perform processing here.*/
2945 poskozby 203 if(msg == 1)
2943 poskozby 204 {
2945 poskozby 205 odpal_povolen = 1;
2943 poskozby 206 }
2945 poskozby 207 if (odpal_povolen == 1)
208 {
209 switch (stav)
210 {
211 case 0:
212 sdWrite(&SD1,"0",2);
213 gptStartOneShot(&GPTD2,1000);
214 break;
215 case 1:
216 sdWrite(&SD1,"1",2);
217 gptStartOneShot(&GPTD2,1500);
218 break;
219 case 2:
220 sdWrite(&SD1,"2",2);
221 gptStartOneShot(&GPTD2,2000);
222 break;
223 case 3:
224 sdWrite(&SD1,"3",2);
225 gptStartOneShot(&GPTD2,3000);
226 break;
227 case 4:
228 sdWrite(&SD1,"4",2);
229 gptStartOneShot(&GPTD2,5000);
230 break;
231 default:
232 sdWrite(&SD1,"konec",6); //posledni krok
233 odpal_povolen = 0;
234 stav = 0;
235 break;
236 }
237 stav++;
238 }
2943 poskozby 239 }
2945 poskozby 240 }
2943 poskozby 241  
242  
243 /*
244 * Vlakno pro obsluhu GPS prijimace
245 */
246 static WORKING_AREA(waThread_GPS, 768);
247 static msg_t Thread_GPS(void *arg) {
248 /*
249 * Nacita se jen nekolik NMEA zprav, aby se neplytvalo pameti na ulozeni kompletniho
250 * setu s tím rizikem, ze se nekdy nenacte aktualni informace o poloze.
251 */
252 uint8_t inBuffer[GPS_BUFFER];
253 char *zacatek_retezce;
254 char *konec_retezce;
255 uint8_t pocet_znaku;
256 uint8_t NMEA_zprava[100];
257  
258 (void)arg;
259 chRegSetThreadName("GPS_NMEA");
260 /*
261 * Activates the serial driver 2 using the driver default configuration.
262 * PA2 and PA3 are routed to USART2.
263 */
264  
265 sdStart(&SD2, &USART2_config);
266 palSetPadMode(GPIOA, 2, PAL_MODE_ALTERNATE(7)); //TX
267 palSetPadMode(GPIOA, 3, PAL_MODE_ALTERNATE(7)); //RX
268  
269  
270 while (TRUE) {
271 chThdSleepMilliseconds(1000); //neni potreba data vycitat rychleji
272 sdRead(&SD2,inBuffer,GPS_BUFFER);
273  
274 /*
275 *Nejprve se vycte cast NMEA dat, pote se vyhleda retezec GPGGA zpravy, ta se vyparsuje a pomoci fce
276 *dekoduj_zpravu_GPS, ktera vyparsuje data o poloze a jine, a ulozi je do struktury GPGGA_informace.
277 */
278  
279 if ((zacatek_retezce = strstr((char *)inBuffer,"$GPGGA")) != NULL)
280 {
281 if ((konec_retezce = strstr(zacatek_retezce,"*")) != NULL)
282 {
283 pocet_znaku = (konec_retezce-zacatek_retezce)/sizeof(char);
284 if (pocet_znaku > 100)
285 {
286 pocet_znaku = 100;
287 }
288 strncpy((char *)NMEA_zprava,zacatek_retezce,pocet_znaku);
289 dekoduj_zpravu_GPS(&NMEA_zprava[0],pocet_znaku);
290 sdWrite(&SD2,"Latitude: ",sizeof("Latitude: ")/sizeof(char));
291 sdWrite(&SD2,GPGGA_informace.Latitude,sizeof(GPGGA_informace.Latitude)/sizeof(uint8_t));
292 sdWrite(&SD2,"\r\n",2);
293 sdWrite(&SD2,"Longitude: ",sizeof("Longitude: ")/sizeof(char));
294 sdWrite(&SD2,GPGGA_informace.Longitude,sizeof(GPGGA_informace.Longitude)/sizeof(uint8_t));
295 sdWrite(&SD2,"\r\n",2);
296 sdWrite(&SD2,"Altitude: ",sizeof("Altitude: ")/sizeof(char));
297 sdWrite(&SD2,GPGGA_informace.Altitude,sizeof(GPGGA_informace.Altitude)/sizeof(uint8_t));
298 sdWrite(&SD2,"\r\n",2);
299 sdWrite(&SD2,"Status: ",sizeof("Status: ")/sizeof(char));
300 sdWrite(&SD2,&GPGGA_informace.Status_GPS,sizeof(GPGGA_informace.Status_GPS)/sizeof(uint8_t));
301 sdWrite(&SD2,"\r\n",2);
302 sdWrite(&SD2,NMEA_zprava,pocet_znaku);
303 sdWrite(&SD2,"\r\n",2);
304 }
305 else
306 {
307 sdWrite(&SD2,"\r\n",2);
308 sdWrite(&SD2,"Nenalezen ukoncovaci znak NMEA zpravy *",sizeof("Nenalezen ukoncovaci znak NMEA zpravy *")/sizeof(char));
309 sdWrite(&SD2,inBuffer,GPS_BUFFER);
310 sdWrite(&SD2,"\r\n",2);
311 }
312 }
313 else
314 sdWrite(&SD2,"Nenalezen zacatek GPGGA zpravy",sizeof("Nenalezen zacatek GPGGA zpravy")/sizeof(char));
315  
316 }
317 }
318  
319 /*
320 * This is a periodic thread that does absolutely nothing except increasing
321 * a seconds counter.
322 */
323 static WORKING_AREA(waThread1, 128);
324 static msg_t Thread1(void *arg) {
325 static uint32_t seconds_counter;
326  
327 (void)arg;
328 chRegSetThreadName("counter");
329 while (TRUE) {
330 chThdSleepMilliseconds(1000);
331 seconds_counter++;
332 }
333 }
334  
335 void dekodujPrikaz(char *prikaz)
336 {
337 //int8_t porov;
338 //porov = strcmp(prikaz,"ahoj");
2945 poskozby 339 if(strcmp(prikaz,"odpal") == 0)
2943 poskozby 340 {
2945 poskozby 341 /* Wakes up the thread.*/
342 chSysLockFromIsr();
343 if (tp_odpal != NULL) {
344 tp_odpal->p_u.rdymsg = (msg_t)1; /* odpal povolen*/
345 chSchReadyI(tp_odpal);
346 tp_odpal = NULL;
347 }
348 chSysUnlockFromIsr();
2943 poskozby 349 palTogglePad(GPIOB, GPIOB_LED4);
350 }
351 else if (strcmp(prikaz,"zdar") == 0)
352 {
353 palTogglePad(GPIOB, GPIOB_LED3);
354 }
355 else
356 {
357 uint8_t zp_neplatny[] = "Neplatny prikaz, spravny format *<prikaz>\n\r";
358 sdWrite(&SD1,zp_neplatny,sizeof(zp_neplatny)/sizeof(uint8_t));
359 palTogglePad(GPIOB, GPIOB_LED3);
360 }
361 }
362  
363  
364  
365 /*
366 * Application entry point.
367 */
368 int main(void) {
369 uint8_t znaky[20];
370 char prikaz[MAX_DELKA_PRIKAZU + 1];
371 uint8_t uk_pri = 0;
372 uint8_t zapis = 0; // pokud je prijata '*', zacina se s rozpoznanim prikazu az do '\n'
373  
374 /*
375 * System initializations.
376 * - HAL initialization, this also initializes the configured device drivers
377 * and performs the board-specific initializations.
378 * - Kernel initialization, the main() function becomes a thread and the
379 * RTOS is active.
380 */
381 halInit();
382 chSysInit();
383  
384 /*
385 * Activates the serial driver 1 using the driver default configuration.
386 * PA9 and PA10 are routed to USART1.
387 */
388 sdStart(&SD1, NULL);
2945 poskozby 389 palSetPadMode(GPIOA, 9, PAL_MODE_ALTERNATE(7)); //TX
390 palSetPadMode(GPIOA, 10, PAL_MODE_ALTERNATE(7)); //RX
2943 poskozby 391  
392 //gptObjectInit(&GPTD2);
393 /*
394 * aktivuje timer2 a prejde tak do aktivniho stavu
395 */
396 gptStart(&GPTD2,&gpt2cfg);
397  
398 /*
399 * If the user button is pressed after the reset then the test suite is
400 * executed immediately before activating the various device drivers in
401 * order to not alter the benchmark scores.
402 */
403 if (palReadPad(GPIOA, GPIOA_BUTTON))
404 TestThread(&SD1);
405  
406 /*
407 * Initializes the SPI driver 2. The SPI2 signals are routed as follow:
408 * PB12 - NSS.
409 * PB13 - SCK.
410 * PB14 - MISO.
411 * PB15 - MOSI.
412 */
413 palSetPad(GPIOB, 12);
414 palSetPadMode(GPIOB, 12, PAL_MODE_OUTPUT_PUSHPULL |
415 PAL_STM32_OSPEED_HIGHEST); /* NSS. */
416 palSetPadMode(GPIOB, 13, PAL_MODE_ALTERNATE(5) |
417 PAL_STM32_OSPEED_HIGHEST); /* SCK. */
418 palSetPadMode(GPIOB, 14, PAL_MODE_ALTERNATE(5)); /* MISO. */
419 palSetPadMode(GPIOB, 15, PAL_MODE_ALTERNATE(5) |
420 PAL_STM32_OSPEED_HIGHEST); /* MOSI. */
421  
422 /*
423 * Initializes the ADC driver 1 and enable the thermal sensor.
424 * The pin PC0 on the port GPIOC is programmed as analog input.
425 */
426 adcStart(&ADCD1, NULL);
427 adcSTM32EnableTSVREFE();
428 palSetPadMode(GPIOC, 0, PAL_MODE_INPUT_ANALOG);
429  
430 /*
431 * Initializes the PWM driver 4, routes the TIM4 outputs to the board LEDs.
432 */
433 pwmStart(&PWMD4, &pwmcfg);
434 //palSetPadMode(GPIOB, GPIOB_LED4, PAL_MODE_ALTERNATE(2));
435 palSetPadMode(GPIOB, GPIOB_LED3, PAL_MODE_ALTERNATE(2));
436 /*
437 * Zelena led aktivace portu
438 */
439  
440 palSetPadMode(GPIOB, GPIOB_LED4, PAL_MODE_OUTPUT_PUSHPULL);
441 palSetPadMode(GPIOB, GPIOB_LED3, PAL_MODE_OUTPUT_PUSHPULL);
442 //test_println("ahoj");
443 /*sdRead(&SD1,znaky,5);
444 sdWrite(&SD1,"\n",1);
445 sdWrite(&SD1,znaky,2);
446 palWritePad(GPIOB, GPIOB_LED4, PAL_HIGH);
447 */
448 /*
449 * Creates the example thread.
450 */
451 chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL);
452  
453 /*
454 * Vytvori vlakno pro prijem dat z GPS modulu
455 */
456 chThdCreateStatic(waThread_GPS, sizeof(waThread_GPS), NORMALPRIO, Thread_GPS, NULL);
457 /*
458 * Vytvori vlakno pro odpalovaci sekvenci
459 */
460 (void)chThdCreateStatic (waThread_odpal, sizeof(waThread_odpal), NORMALPRIO, Thread_odpal, NULL);
461  
462  
463 /*
464 * Normal main() thread activity, in this demo it does nothing except
465 * sleeping in a loop and check the button state, when the button is
466 * pressed the test procedure is launched with output on the serial
467 * driver 1.
468 */
469 while (TRUE) {
470  
471 sdRead(&SD1,znaky,1);
472 /*Kdyz uzivatel stiskne enter -> dekoduj a vykonej prikaz*/
473 if (znaky[0] == '\r')
474 {
475 uk_pri = 0;
476 zapis = 0;
477 dekodujPrikaz(prikaz);
478 prikaz[0] = 0;
479 }
480 /*Uklada prikaz*/
481 if (zapis == 1 && uk_pri < MAX_DELKA_PRIKAZU)
482 {
483 prikaz[uk_pri++] = znaky[0];
484 prikaz[uk_pri + 1] = 0;
485 }
486 /*Pokud je prikaz delsi, nez by mel byt, prestane ukladat a upozorni uzivatele*/
487 else if (zapis == 1 && uk_pri == MAX_DELKA_PRIKAZU)
488 {
489 uk_pri = 0;
490 zapis = 0;
491 dekodujPrikaz(prikaz);
492 }
493 /*Uzivatel zacal zadavat prikaz*/
494 if(znaky[0] == '*' && zapis == 0)
495 zapis = 1;
496  
497  
498 if (palReadPad(GPIOA, GPIOA_BUTTON))
499  
500 TestThread(&SD1);
501 chThdSleepMilliseconds(500);
502 }
503 }