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];
2946 poskozby 371 uint8_t pocet_znaku = 0;
2943 poskozby 372  
373 /*
374 * System initializations.
375 * - HAL initialization, this also initializes the configured device drivers
376 * and performs the board-specific initializations.
377 * - Kernel initialization, the main() function becomes a thread and the
378 * RTOS is active.
379 */
380 halInit();
381 chSysInit();
382  
383 /*
384 * Activates the serial driver 1 using the driver default configuration.
385 * PA9 and PA10 are routed to USART1.
386 */
387 sdStart(&SD1, NULL);
2945 poskozby 388 palSetPadMode(GPIOA, 9, PAL_MODE_ALTERNATE(7)); //TX
389 palSetPadMode(GPIOA, 10, PAL_MODE_ALTERNATE(7)); //RX
2943 poskozby 390  
391 //gptObjectInit(&GPTD2);
392 /*
393 * aktivuje timer2 a prejde tak do aktivniho stavu
394 */
395 gptStart(&GPTD2,&gpt2cfg);
396  
397 /*
398 * If the user button is pressed after the reset then the test suite is
399 * executed immediately before activating the various device drivers in
400 * order to not alter the benchmark scores.
401 */
402 if (palReadPad(GPIOA, GPIOA_BUTTON))
403 TestThread(&SD1);
404  
405 /*
406 * Initializes the SPI driver 2. The SPI2 signals are routed as follow:
407 * PB12 - NSS.
408 * PB13 - SCK.
409 * PB14 - MISO.
410 * PB15 - MOSI.
411 */
412 palSetPad(GPIOB, 12);
413 palSetPadMode(GPIOB, 12, PAL_MODE_OUTPUT_PUSHPULL |
414 PAL_STM32_OSPEED_HIGHEST); /* NSS. */
415 palSetPadMode(GPIOB, 13, PAL_MODE_ALTERNATE(5) |
416 PAL_STM32_OSPEED_HIGHEST); /* SCK. */
417 palSetPadMode(GPIOB, 14, PAL_MODE_ALTERNATE(5)); /* MISO. */
418 palSetPadMode(GPIOB, 15, PAL_MODE_ALTERNATE(5) |
419 PAL_STM32_OSPEED_HIGHEST); /* MOSI. */
420  
421 /*
422 * Initializes the ADC driver 1 and enable the thermal sensor.
423 * The pin PC0 on the port GPIOC is programmed as analog input.
424 */
425 adcStart(&ADCD1, NULL);
426 adcSTM32EnableTSVREFE();
427 palSetPadMode(GPIOC, 0, PAL_MODE_INPUT_ANALOG);
428  
429 /*
430 * Initializes the PWM driver 4, routes the TIM4 outputs to the board LEDs.
431 */
432 pwmStart(&PWMD4, &pwmcfg);
433 //palSetPadMode(GPIOB, GPIOB_LED4, PAL_MODE_ALTERNATE(2));
434 palSetPadMode(GPIOB, GPIOB_LED3, PAL_MODE_ALTERNATE(2));
435 /*
436 * Zelena led aktivace portu
437 */
438  
439 palSetPadMode(GPIOB, GPIOB_LED4, PAL_MODE_OUTPUT_PUSHPULL);
440 palSetPadMode(GPIOB, GPIOB_LED3, PAL_MODE_OUTPUT_PUSHPULL);
2946 poskozby 441  
2943 poskozby 442 /*
443 * Creates the example thread.
444 */
445 chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL);
446  
447 /*
448 * Vytvori vlakno pro prijem dat z GPS modulu
449 */
450 chThdCreateStatic(waThread_GPS, sizeof(waThread_GPS), NORMALPRIO, Thread_GPS, NULL);
451 /*
452 * Vytvori vlakno pro odpalovaci sekvenci
453 */
454 (void)chThdCreateStatic (waThread_odpal, sizeof(waThread_odpal), NORMALPRIO, Thread_odpal, NULL);
455  
456  
457 /*
458 * Normal main() thread activity, in this demo it does nothing except
459 * sleeping in a loop and check the button state, when the button is
460 * pressed the test procedure is launched with output on the serial
461 * driver 1.
462 */
463 while (TRUE) {
464  
465 sdRead(&SD1,znaky,1);
466 /*Kdyz uzivatel stiskne enter -> dekoduj a vykonej prikaz*/
467 if (znaky[0] == '\r')
468 {
2946 poskozby 469 pocet_znaku = 0;
2943 poskozby 470 dekodujPrikaz(prikaz);
471 prikaz[0] = 0;
472 }
473 /*Uklada prikaz*/
2946 poskozby 474 else if (pocet_znaku < MAX_DELKA_PRIKAZU)
2943 poskozby 475 {
2946 poskozby 476 prikaz[pocet_znaku + 1] = 0;
477 prikaz[pocet_znaku++] = znaky[0];
2943 poskozby 478 }
479 /*Pokud je prikaz delsi, nez by mel byt, prestane ukladat a upozorni uzivatele*/
2946 poskozby 480 else
2943 poskozby 481 {
2946 poskozby 482 pocet_znaku = 0;
2943 poskozby 483 dekodujPrikaz(prikaz);
484 }
2946 poskozby 485 /*
2943 poskozby 486 if (palReadPad(GPIOA, GPIOA_BUTTON))
487  
488 TestThread(&SD1);
489 chThdSleepMilliseconds(500);
2946 poskozby 490 */
2943 poskozby 491 }
492 }