]> rtime.felk.cvut.cz Git - fpga/rpi-motor-control.git/blob - pmsm-control/test_sw/main_pmsm.c
Controllers moved to separate file.
[fpga/rpi-motor-control.git] / pmsm-control / test_sw / main_pmsm.c
1 /**
2  * \file main_pmsm.c
3  * \author Martin Prudek
4  * \brief Mainfile pro pmsm control.
5  */
6
7 #ifndef NULL
8 #define NULL (void*) 0
9 #endif /*NULL*/
10
11
12 #include <stdlib.h>     /*exit*/
13 #include <signal.h>     /*signal handler Ctrl+C*/
14 #include <stdio.h>      /*printf*/
15 #include <sched.h>      /*sheduler*/
16 #include <unistd.h>     /*usleep*/
17 #include <pthread.h>    /*threads*/
18 #include <time.h>       /*nanosleep*/
19 #include <string.h>
20
21 #include "rpin.h"       /*gpclk*/
22 #include "rp_spi.h"     /*spi*/
23 #include "misc.h"       /*structure for priorities*/
24 #include "pxmc_sin_fixed.h"     /*to test sin commutation */
25 #include "pmsm_state.h"
26 #include "cmd_proc.h"
27 #include "controllers.h"
28
29
30
31
32 #define PRIOR_KERN      50
33 #define PRIOR_HIGH      49
34 #define PRIOR_LOW       20
35
36 #define THREAD_SHARED   0
37 #define INIT_VALUE      1       /*init value for semaphor*/
38
39
40 #define NSEC_PER_SEC    (1000000000) /* The number of nsecs per sec. */
41
42
43 struct rpi_in data;
44 struct rpi_state rps={
45         //.MAX_DUTY=170,
46         .spi_dat=&data,
47         .test=0,
48         .pwm1=0,.pwm2=0, .pwm3=0,
49         .pwm1=0, .t_pwm2=0, .t_pwm3=0,
50         .commutate=0,
51         .duty=0,                        /* duty cycle of pwm */
52         .index_dist=0,          /* distance to index position */
53         .index_ok=0,
54         .tf_count=0,            /*number of transfer*/
55         .desired_pos=0,         /* desired position */
56         .pos_reg_ena=0,
57         .desired_spd=0,
58         .spd_reg_ena=0,
59         .old_pos={0},
60         .spd_err_sum=0,
61         .log_col_count=0,       /* pocet radku zaznamu */
62         .log_col=0,
63         .doLogs=0,
64         .alpha_offset=960
65 };
66
67 /**
68  * \brief Initilizes GPCLK.
69  */
70 int clk_init()
71 {
72         initialise(); /*namapovani gpio*/
73         initClock(PLLD_500_MHZ, 10, 0);
74         gpioSetMode(4, FSEL_ALT0);
75         return 0;
76 }
77 /*
78  * \brief Terminates GPCLK.
79  */
80
81 inline void clk_disable(){
82         termClock(0);
83 }
84 /*
85  * \brief
86  * Count minimum value of three numbers.
87  * Input values must be in range <-2^28;2^28>.
88  */
89 int32_t min(int32_t x, int32_t y, int32_t z){
90         int32_t diff,sign;
91
92         diff=x-y; /*rozdil*/
93         sign=(*((uint32_t*)&diff))>>31; /*znamenko -> detekuje, ze y je vetsi*/
94         x=y+sign*diff; /*ulozime mensi cislo, pokud sign>0, pak diff<0 */
95
96         diff=x-z; /*rozdil*/
97         sign=(*((uint32_t*)&diff))>>31; /*znamenko -> detekuje, ze z je vetsi*/
98         x=z+sign*diff; /*ulozime mensi cislo, pokud sign>0, pak diff<0 */
99
100         return x;
101 }
102
103 /*
104  * \brief
105  * Free logs
106  */
107 void freeLogs(){
108         int r;
109         if (rps.log_col_count){
110                 for (r=0;r<LOG_ROWS;r++){
111                         free(rps.logs[r]);
112                 }
113         }
114         rps.log_col_count=0;
115         rps.doLogs=0;
116 }
117
118 /*
119  * \brief
120  * Makes log.
121  */
122 void makeLog(){
123         int r;
124         if (rps.log_col==MAX_LOGS-1){
125                 rps.doLogs=0;
126                 return;
127         }
128         rps.logs[0][rps.log_col]=(int)rps.tf_count;
129         rps.logs[1][rps.log_col]=(int)rps.spi_dat->pozice;
130
131         rps.logs[2][rps.log_col]=(int)rps.pwm1;
132         rps.logs[3][rps.log_col]=(int)rps.pwm2;
133         rps.logs[4][rps.log_col]=(int)rps.pwm3;
134         rps.logs[5][rps.log_col]=rps.duty;
135
136         rps.logs[6][rps.log_col]=rps.desired_spd;
137         rps.logs[7][rps.log_col]=rps.speed;
138
139         rps.logs[8][rps.log_col]=(int)(rps.spi_dat->ch1/rps.spi_dat->adc_m_count);
140         rps.logs[9][rps.log_col]=(int)(rps.spi_dat->ch2/rps.spi_dat->adc_m_count);
141         rps.logs[10][rps.log_col]=(int)(rps.spi_dat->ch0/rps.spi_dat->adc_m_count);
142
143         rps.log_col++;
144      /*
145         if (rps.log_col==rps.log_col_count-1){
146                 rps.log_col_count*=2;
147                 rps.log_col_count%=MAX_LOGS;
148                 for (r=0;r<LOG_ROWS;r++){
149                         rps.logs[r]=realloc(rps.logs[r],rps.log_col_count*sizeof(int));
150                         if (rps.logs[r]==NULL){
151                                 rps.doLogs=0;
152                                 rps.error=1;
153                         }
154                 }
155         }
156      */
157 }
158
159 /*
160  * \brief
161  * Pripravi psi buffer
162  */
163 void prepare_tx(uint8_t * tx){
164
165         /*Data format:
166          * tx[4] - bity 95 downto 88 - bits that are sent first
167          * tx[5] - bity 87 downto 80
168          * tx[6] - bity 79 downto 72
169          * tx[7] - bity 71 downto 64
170          * tx[8] - bity 63 downto 56
171          * tx[9] - bity 55 downto 48
172          * tx[10] - bity 47 downto 40
173          * tx[11] - bity 39 downto 32
174          * tx[12] - bity 31 downto 24
175          * tx[13] - bity 23 downto 16
176          * tx[14] - bity 15 downto 8
177          * tx[15] - bity 7 downto 0
178          *
179          * bit 95 - ADC reset
180          * bit 94 - enable PWM1
181          * bit 93 - enable PWM2
182          * bit 92 - enable PWM3
183          * bit 91 - shutdown1
184          * bit 90 - shutdown2
185          * bit 89 - shutdown3
186          *      .
187          *      .
188          *      Unused
189          *      .
190          *      .
191          * bits 47 .. 32 - match PWM1
192          * bits 31 .. 16 - match PWM2
193          * bits 15 .. 0  - match PWM3
194          */
195
196
197         uint16_t tmp;
198
199         /* keep the 11-bit cap*/
200
201         if (rps.pwm1>2047) rps.pwm1=2047;
202         if (rps.pwm2>2047) rps.pwm2=2047;
203         if (rps.pwm3>2047) rps.pwm3=2047;
204
205         tx[0]=rps.test; /*bit 94 - enable PWM1*/
206
207         /*now we have to switch the bytes due to endianess */
208         /* ARMv6 & ARMv7 instructions are little endian */
209         /*pwm1*/
210         tx[10]=((uint8_t*)&rps.pwm1)[1]; /*MSB*/
211         tx[11]=((uint8_t*)&rps.pwm1)[0]; /*LSB*/
212
213         /*pwm2*/
214         tx[12]=((uint8_t*)&rps.pwm2)[1]; /*MSB*/
215         tx[13]=((uint8_t*)&rps.pwm2)[0]; /*LSB*/
216
217         /*pwm3*/
218         tx[14]=((uint8_t*)&rps.pwm3)[1]; /*MSB*/
219         tx[15]=((uint8_t*)&rps.pwm3)[0]; /*LSB*/
220
221
222 }
223
224
225 /**
226  * \brief Signal handler pro Ctrl+C
227  */
228 void appl_stop(){
229         uint8_t tx[16];
230         sem_wait(&rps.thd_par_sem);
231
232         memset(tx,0,16*sizeof(int));
233         rps.pwm1=0;
234         rps.pwm2=0;
235         rps.pwm3=0;
236         prepare_tx(tx);                 /*save the data to send*/
237         data=spi_read(tx);
238
239         spi_disable();
240         clk_disable();
241         freeLogs();
242         /*muzeme zavrit semafor*/
243         sem_destroy(&rps.thd_par_sem);
244         printf("\nprogram bezpecne ukoncen\n");
245 }
246
247 void substractOffset(struct rpi_in* data, struct rpi_in* offset){
248         data->pozice=data->pozice_raw-offset->pozice_raw;
249         return;
250 }
251 /*
252  * \brief
253  * Transformace pro uhel pocitany po smeru hodinovych rucicek
254  */
255 void dq2alphabeta(int32_t *alpha, int32_t *beta, int d, int q, int32_t sin, int32_t cos){
256         *alpha=cos*d+sin*q;
257         *beta=-sin*d+cos*q;
258         return;
259 }
260 void alphabeta2pwm3(int32_t * ia, int32_t * ib, int32_t *ic,int32_t alpha, int32_t beta){
261         *ia=alpha;
262         *ib=-alpha/2+beta*887/1024;
263         *ic=-alpha/2-beta*887/1024;
264 }
265 /*
266  * \brief
267  * Preocita napeti na jednotlivych civkach na napeti,
268  *      ktera budou privedena na svorky motoru.
269  *      Tedy na A(yel)-pwm1, B(red)-pwm2, C(blk)-pwm3
270  */
271 void transDelta(int32_t * u1, int32_t * u2, int32_t *u3, int32_t ub , int32_t uc){
272         int32_t t;
273
274         /*vypocte napeti tak, aby odpovidaly rozdily*/
275         *u1=uc;
276         *u2=uc+ub;
277         *u3=0;
278
279         /*najde zaporne napeti*/
280         t=min(*u1,*u2,*u3);
281
282         /*dorovna zaporna napeti na nulu*/
283         *u1-=t;
284         *u2-=t;
285         *u3-=t;
286 }
287 void inv_trans_comm(int duty){
288         uint32_t pos;
289         int32_t sin, cos;
290         int32_t alpha, beta;
291         int32_t pwma,pwmb,pwmc;
292         pos=rps.index_dist;
293         /*melo by byt urceno co nejpresneji, aby faze 'a' splyvala s osou 'alpha'*/
294         pos+=717;
295         /*use it as cyclic 32-bit logic*/
296         pos*=4294967;
297         pxmc_sincos_fixed_inline(&sin, &cos, pos, 16);
298         dq2alphabeta(&alpha, &beta,0,duty, sin, cos);
299         alpha>>=16;
300         beta>>=16;
301         alphabeta2pwm3(&pwma,&pwmb, &pwmc,alpha,beta);
302
303         if (pwma<0) pwma=0;
304         if (pwmb<0) pwmb=0;
305         if (pwmc<0) pwmc=0;
306
307
308         rps.t_pwm1=(uint16_t)pwma;
309         rps.t_pwm3=(uint16_t)pwmb;
310         rps.t_pwm2=(uint16_t)pwmc;
311 }
312
313 void inv_trans_comm_2(int duty){
314         uint32_t pos;
315         int32_t sin, cos;
316         int32_t alpha, beta;
317         int32_t ua,ub,uc;
318         int32_t ia,ib,ic;
319         int32_t u1,u2,u3;
320         pos=rps.index_dist;
321
322         pos+=rps.alpha_offset; /*zarovnani faze 'a' s osou 'alpha'*/
323
324         /*pro výpočet sin a cos je pouzita 32-bit cyklicka logika*/
325         pos*=4294967;
326         pxmc_sincos_fixed_inline(&sin, &cos, pos, 16);
327
328         dq2alphabeta(&alpha, &beta,0,duty, sin, cos);
329         alpha>>=16;
330         beta>>=16;
331
332         alphabeta2pwm3(&ia,&ib, &ic,alpha,beta);
333
334         ua=ia;
335         ub=ib;
336         uc=ic;
337
338         transDelta(&u1,&u2, &u3,ub,uc);
339
340         rps.pwm1=(uint16_t)u1;
341         rps.pwm2=(uint16_t)u2;
342         rps.pwm3=(uint16_t)u3;
343 }
344
345 /**
346  * Funkce pravidelne vypisuje posledni zjistenou pozici lokalniho motoru
347  */
348 void * pos_monitor(void* param){
349         while(1){
350                 printData(&rps);
351                 usleep(1000000);        /*1 Hz*/
352         }
353         return (void*)0;
354 }
355 /*
356  * \brief
357  * Multiplication of 11 bit
358  * Zaporne vysledky prvede na nulu.
359  */
360 inline uint16_t mult_cap(int32_t s,int d){
361         int j;
362         int res=0;
363         for(j=0;j!=11;j++){
364                 /* multiplicate as if maximum sinus value was unity */
365                 res+=(!(s & 0x10000000))*(((1 << j) & s)>>j)*(d>>(10-j));
366         }
367         return res;
368 }
369
370 inline
371 int sin_commutator(int duty){
372         #define DEGREE_60        715827883
373         #define DEGREE_120      1431655765
374         #define DEGREE_180      2147483648
375         #define DEGREE_240      2863311531
376         #define DEGREE_300      3579139413
377         uint32_t j,pos;
378         int32_t sin;
379         pos=rps.index_dist;
380         int32_t pwm;
381         /*aby prictene uhly mohla byt kulata cisla, musime index posunout*/
382         pos+=38;
383         /*use it as cyclic 32-bit logic*/
384         pos*=4294967;
385         if (duty>=0){   /*clockwise rotation*/
386                 /* 1st phase */
387                 sin = pxmc_sin_fixed_inline(pos+DEGREE_240,10); /*10+1 bity*/ /*-120*/
388                 pwm=sin*duty/1024;
389                 if (pwm<0) pwm=0;
390                 rps.pwm1=(uint16_t)pwm;
391
392                 /* 2nd phase */
393                 sin = pxmc_sin_fixed_inline(pos+DEGREE_120,10); /*10+1 bity*/ /*-240*/
394                 pwm=sin*duty/1024;
395                 if (pwm<0) pwm=0;
396                 rps.pwm2=(uint16_t)pwm;
397
398                 /* 3rd phase */
399                 sin = pxmc_sin_fixed_inline(pos,10); /*10+1 bity*/
400                 pwm=sin*duty/1024;
401                 if (pwm<0) pwm=0;
402                 rps.pwm3=(uint16_t)pwm;
403         }else{
404                 duty=-duty;
405
406                 /* 1st phase */
407                 sin = pxmc_sin_fixed_inline(pos+DEGREE_60,10); /*10+1 bity*/ /*-300*/
408                 pwm=sin*duty/1024;
409                 if (pwm<0) pwm=0;
410                 rps.pwm1=(uint16_t)pwm;
411
412                 /* 2nd phase */
413                 sin = pxmc_sin_fixed_inline(pos+DEGREE_300,10); /*10+1 bity*/ /*-60-*/
414                 pwm=sin*duty/1024;
415                 if (pwm<0) pwm=0;
416                 rps.pwm2=(uint16_t)pwm;
417
418                 /* 3rd phase */
419                 sin = pxmc_sin_fixed_inline(pos+DEGREE_180,10); /*10+1 bity*/ /*-180*/
420                 pwm=sin*duty/1024;
421                 if (pwm<0) pwm=0;
422                 rps.pwm3=(uint16_t)pwm;
423         }
424         return 0;
425 }
426 /*
427  * \brief
428  * Test function to be placed in controll loop.
429  * Switches PWM's at point where they produce same force.
430  * This points are found thanks to IRC position,
431  */
432 inline
433 void simple_ind_dist_commutator(int duty){
434         if (duty>=0){ /* clockwise - so that position increase */
435                 /* pwm3 */
436                 if ((rps.index_dist>=45 && rps.index_dist<=373) ||
437                 (rps.index_dist>=1048 && rps.index_dist<=1377)){
438                         rps.pwm1=0;
439                         rps.pwm2=0;
440                         rps.pwm3=duty;
441                         /* pwm1 */
442                 }else if ((rps.index_dist>=373 && rps.index_dist<=711) ||
443                 (rps.index_dist>=1377 && rps.index_dist<=1711)){
444                         rps.pwm1=duty;
445                         rps.pwm2=0;
446                         rps.pwm3=0;
447                         /* pwm2 */
448                 }else if ((rps.index_dist>=0 && rps.index_dist<=45) ||
449                 (rps.index_dist>=711 && rps.index_dist<=1048) ||
450                 (rps.index_dist>=1711 && rps.index_dist<=1999)){
451                         rps.pwm1=0;
452                         rps.pwm2=duty;
453                         rps.pwm3=0;
454                 }
455         }else{  /*counter-clockwise - position decrease */
456                 /* pwm3 */
457                 if ((rps.index_dist>=544 && rps.index_dist<=881) ||
458                 (rps.index_dist>=1544 && rps.index_dist<=1878)){
459                         rps.pwm1=0;
460                         rps.pwm2=0;
461                         rps.pwm3=-duty;
462                         /* pwm1 */
463                 }else if ((rps.index_dist>=0 && rps.index_dist<=211) ||
464                 (rps.index_dist>=881 && rps.index_dist<=1210) ||
465                 (rps.index_dist>=1878 && rps.index_dist<=1999)){
466                         rps.pwm1=-duty;
467                         rps.pwm2=0;
468                         rps.pwm3=0;
469                         /* pwm2 */
470                 }else if ((rps.index_dist>=211 && rps.index_dist<=544) ||
471                 (rps.index_dist>=1210 && rps.index_dist<=1544)){
472                         rps.pwm1=0;
473                         rps.pwm2=-duty;
474                         rps.pwm3=0;
475                 }
476         }
477 }
478 /*
479  * \brief
480  * Test function to be placed in controll loop.
481  * Switches PWM's at point where they produce same force
482  */
483 inline void simple_hall_commutator(int duty){
484         if (duty>=0){ /* clockwise - so that position increase */
485                 /* pwm3 */
486                 if (data.hal2 && !data.hal3){
487                         rps.pwm1=0;
488                         rps.pwm2=0;
489                         rps.pwm3=duty;
490                         /* pwm1 */
491                 }else if (data.hal1 && !data.hal2){
492                         rps.pwm1=duty;
493                         rps.pwm2=0;
494                         rps.pwm3=0;
495                         /* pwm2 */
496                 }else if (!data.hal1 && data.hal3){
497                         rps.pwm1=0;
498                         rps.pwm2=duty;
499                         rps.pwm3=0;
500                 }
501         }else{  /*counter-clockwise - position decrease */
502                 /* pwm3 */
503                 if (!data.hal2 && data.hal3){
504                         rps.pwm1=0;
505                         rps.pwm2=0;
506                         rps.pwm3=-duty;
507                         /* pwm1 */
508                 }else if (!data.hal1 && data.hal2){
509                         rps.pwm1=-duty;
510                         rps.pwm2=0;
511                         rps.pwm3=0;
512                         /* pwm2 */
513                 }else if (data.hal1 && !data.hal3){
514                         rps.pwm1=0;
515                         rps.pwm2=-duty;
516                         rps.pwm3=0;
517                 }
518         }
519 }
520 /**
521  * \brief
522  * Computation of distance to index.
523  *
524  * K dispozici je 12-bit index, to umoznuje ulozit 4096 ruznych bodu
525  * Je nutne vyjadrit 1999 bodu proti i posmeru h.r. od indexu -
526  *      to je 3999 bodu
527  *      =>12 bitu je dostacujicich, pokud nikdy nedojde ke ztrate
528  *              signalu indexu
529  */
530 void comIndDist(){
531         uint16_t pos = 0x0FFF & data.pozice_raw;
532         uint16_t dist;
533         uint16_t index = data.index_position;
534
535         if (index<1999){                /*index e<0,1998> */
536                 if (pos<index){                 /*pozice e<0,index-1> */
537                         /*proti smeru h.r. od indexu*/
538                         dist=pos+2000-index;
539                 }else if (pos<=index+1999){     /*pozice e<index,index+1999> */
540                         /*po smeru h.r. od indexu*/
541                         dist=pos-index;
542                 }else if (pos<index+2096){      /*pozice e<index+2000,index+2095> */
543                         goto index_lost;
544                 }else{                          /*pozice e<index+2096,4095> */
545                         /*proti smeru h.r. od indexu - podtecena pozice*/
546                         dist=pos-index-2096;
547                 }
548         }else if (index<=2096){         /*index e<1999,2096>*/
549                 if (pos<index-1999){            /*pozice e<0,index-2000> */
550                         goto index_lost;
551                 }else if (pos<index){           /*pozice e<index-1999,index-1> */
552                         /*proti smeru h.r. od indexu*/
553                         dist=pos+2000-index;
554                 }else if (pos<=index+1999){     /*pozice e<index,index+1999> */
555                         /*po smeru h.r. od indexu*/
556                         dist=pos-index;
557                 }else {                         /*pozice e<index+2000,4095> */
558                         goto index_lost;
559                 }
560         }else{                          /*index e<2097,4095> */
561                 if (pos<=index-2097){           /*pozice e<0,index-2097> */
562                         /*po smeru h.r. od indexu - pretecena pozice*/
563                         dist=4096+pos-index;
564                 }else if (pos<index-1999){      /*pozice e<index-2096,index-2000> */
565                         goto index_lost;
566                 }else if (pos<index){           /*pozice e<index-1999,index-1> */
567                         /*proti smeru h.r. od indexu*/
568                         dist=pos+2000-index;
569                 }else{                          /*pozice e<index,4095> */
570                         /*po smeru h.r. od indexu*/
571                         dist=pos-index;
572                 }
573         }
574
575         rps.index_dist = dist;
576         return;
577
578         index_lost:
579                 rps.index_ok=0;
580                 return;
581 }
582
583
584 /*
585  * \brief
586  * Computate speed.
587  */
588 void compSpeed(){
589         signed long int spd;
590         spd=rps.spi_dat->pozice-rps.old_pos[rps.tf_count%OLD_POS_NUM];
591         rps.speed=(int32_t)spd;
592 }
593
594 /*
595  * \brief
596  * Feedback loop.
597  * TODO: replace bunch of 'IFs' with Object-like pattern
598  */
599 void * read_data(void* param){
600         int i;
601         struct rpi_in pocatek;
602         struct timespec t;
603         int interval = 1000000; /* 1ms ~ 1kHz*/
604         uint8_t tx[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} ;
605         char first=1;
606         uint16_t last_index;                            /*we have index up-to date*/
607         pocatek = spi_read(tx);
608         clock_gettime(CLOCK_MONOTONIC ,&t);
609         /* start after one second */
610         t.tv_sec++;
611                 while(1){
612                         /* wait until next shot */
613                         clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &t, NULL);
614                         sem_wait(&rps.thd_par_sem);             /*---take semaphore---*/
615
616                         /*old positions*/
617                         rps.old_pos[rps.tf_count%OLD_POS_NUM]=rps.spi_dat->pozice;
618                         prepare_tx(tx);                 /*save the data to send*/
619                         data = spi_read(tx);            /*exchange data*/
620                         /*subtract initiate postion */
621                         rps.tf_count++;
622                         substractOffset(&data,&pocatek);
623                         compSpeed();                    /*spocita rychlost*/
624
625                         if (!rps.index_ok){
626                                 if (first){
627                                         last_index=data.index_position;
628                                         first=0;
629                                 }else if (last_index!=data.index_position){
630                                         rps.index_ok=1;
631                                         comIndDist();   /*vypocet vzdalenosti indexu*/
632                                 }
633                         }else{ /*index je v poradku*/
634                                 comIndDist();           /*vypocet vzdalenosti indexu*/
635                         }
636
637                         /* pocitame sirku plneni podle potreb rizeni*/
638                         if (rps.pos_reg_ena){           /*pozicni rizeni*/
639                                 pos_pid(&rps);
640                         }else if(rps.spd_reg_ena){      /*rizeni na rychlost*/
641                                 spd_pid(&rps);
642                         }
643
644                         /* sirka plneni prepoctena na jednotlive pwm */
645                         if (rps.index_ok && rps.commutate){
646                                 /*simple_ind_dist_commutator(rps.duty);*/
647                                 /*sin_commutator(rps.duty);*/
648                                 inv_trans_comm(rps.duty);
649                                 inv_trans_comm_2(rps.duty);
650                         }else if(!rps.index_ok && rps.commutate){
651                                 simple_hall_commutator(rps.duty);
652                         }
653
654                         /*zalogujeme hodnoty*/
655                         if (rps.doLogs && !(rps.tf_count%LOG_PERIOD)){
656                                 makeLog();
657                         }
658
659                         sem_post(&rps.thd_par_sem);             /*--post semaphore---*/
660
661                         /* calculate next shot */
662                         t.tv_nsec += interval;
663
664                         while (t.tv_nsec >= NSEC_PER_SEC) {
665                                 t.tv_nsec -= NSEC_PER_SEC;
666                                 t.tv_sec++;
667                         }
668
669                 }
670 }
671
672
673 /**
674  * \brief Main function.
675  */
676
677 int main(){
678         pthread_t base_thread_id;
679         clk_init();             /* inicializace gpio hodin */
680         spi_init();             /* iniicializace spi*/
681
682         /*semafor pro detekci zpracovani parametru vlaken*/
683         sem_init(&rps.thd_par_sem,THREAD_SHARED,INIT_VALUE);
684         setup_environment();
685
686         base_thread_id=pthread_self();
687
688         /*main control loop*/
689         create_rt_task(&base_thread_id,PRIOR_HIGH,read_data,NULL);
690
691         /*monitor of current state*/
692         create_rt_task(&base_thread_id,PRIOR_LOW,pos_monitor,NULL);
693
694         /*wait for commands*/
695         poll_cmd(&rps);
696
697         return 0;
698 }