Subversion Repositories shark

Rev

Rev 1649 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1648 giacomo 1
/*
2
 * Project: S.Ha.R.K.
3
 * G P S  D E M O : this program receives and displays data from a gps
4
 * transmitter connected to COM1 port. This is also a graphic demo that
5
 * uses a software emulation of MESA libraries to display actual latitude
6
 * and longitude on the earth globe. You can also use the program without
7
 * having a gps transmitter because it can run in a demo mode (to do that
8
 * press d key when the program starts).
9
 *
10
 * In the main function graphics and com1 port are initialized, respectively
11
 * with a call to the functions gl_init and open_com. Then all the tasks
12
 * used in the program are created and activated, these are :
13
 *
14
 *    TASK refresh : copies the gl buffer to video memory
15
 *    TASK draw    : draws all the graphics
16
 *    TASK gps     : receives data from gps transmitter
17
 *
18
 */
19
 
20
#include <kernel/log.h>
21
#include <kernel/kern.h>
22
#include <math.h>
23
#include <stdlib.h>
24
 
25
#include <drivers/shark_fb26.h>
26
#include <drivers/shark_keyb26.h>
27
 
28
#include <GL/osmesa.h>  //MESA header
29
#include <GL/glut.h>    //MESA header
30
#include "texture.h"    //contains three arrayes that define the R, G, B data of the first texture (phisical earth)
31
#include "texture2.h"   //contains three arrayes that define the R, G, B data of the second texture (political earth)
32
#include "comport.h"    //contains constants used by COM1 functions
33
 
34
#ifndef M_PI
35
#define M_PI 3.14159265
36
#endif
37
 
38
//Graphic variables and constants
39
 
40
#define WIDTH 800    //Width of the screen in pixel
41
#define HEIGHT 600   //Height of the screen in pixel
42
#define BYTES_PP 2   //BytesPerPixel
43
 
44
OSMesaContext ctx;
45
 
46
extern void *video_memory;
47
 
48
unsigned char *rgb_565_buf = NULL;                      //RGB 16 bpp Buffer
49
unsigned char *video_buf = NULL;                        //Video Buffer
50
unsigned long int VMEMLONG = WIDTH*HEIGHT*BYTES_PP / 4; //Used by copy_videomem_16to16
51
unsigned long int RGB565MEM = WIDTH*HEIGHT*BYTES_PP;    //Total video mem
52
 
53
//Graphic Objects variables and constants
54
 
55
GLdouble radius, twist;       //radius and twist of the sphere
56
float zoom = 0;               //zoom factor
57
int sel_texture = 1;          //index of the actually selected texture
58
GLubyte tex[256][256][3];     //stores the R, G, B data of the first texture
59
GLubyte tex2[256][256][3];    //stores the R, G, B data of the second texture        
60
GLint sphere;                 //index of the shpere list (see mesa functions for details)
61
 
62
//Tasks variables and constants
63
 
64
unsigned long int PERIOD_REFRESH = 100000; //period of the refresh task in ns
65
unsigned long int PERIOD_DRAW = 100000; //period of the draw task
66
unsigned long int PERIOD_GPS = 1000;       //period of the gps task
67
unsigned long int WCET_REFRESH, WCET_DRAW, WCET_GPS; //deadlines of the tasks
68
PID refresh_PID, draw_PID, gps_PID;     //indexes of the tasks
69
 
70
//Gps receiver task variables and constants
71
 
72
char word[30];       //contains every word received from the gps transmitter
73
int ind = 0;         //contains the index of the next character to be written in the variable word
74
int ind_gpgga = 0;   //index of the next gpgga word to be read from gps
75
int ind_gpgsv = 0;   //index of the next gpgsv word to be read from gps
76
int ind_gprmc = 0;   //index of the next gprmc word to be read from gps
77
int nlist;           //used to index satellites in gps_sat_data structure
78
 
79
//Demo mode variables and functions
80
 
81
int demo_mode = 0;   //indicates if demo mode is active(=1) or not (=0)
82
int ndemo = 0;       //a counter used while running in demo mode
83
int lat, lon;        //auxiliary variables used for integer division
84
int kmov;            //used to change the moving direction 
85
float demolat = 0;   //stores latitude
86
float demolon = 0;   //stores longitude
87
 
88
//Gps data structures
89
 
90
typedef struct {
91
   float id, elevation, azimuth, signal_level;
92
} gps_sat_data;
93
 
94
struct {
95
   float latitude, longitude, altitude, nsat, speed, dir_mov, date, var_mov;
96
   char dirlat, dirlon, time[12], dir_var_mov;
97
   gps_sat_data sat_data[4]; //data of the satellites in view (4 maximum)
98
} gps_data;
99
 
100
TASK refesh(void);
101
TASK draw(void);
102
TASK gps(void);
103
 
104
//converts a string to a floating point
105
float strtof(char *s)
106
{
107
   int d, n;
108
   float f = 0, pot;
109
 
110
   //if the string is null ends returning 0
111
   if(s[0] == '\0')
112
      return 0;
113
 
114
   //finds the dot character until the end of the string
115
   for(d = 0; (s[d] != '.') && (s[d] != '\0') ; d++);
116
 
117
   //converts non decimal numbers
118
   pot = 1;
119
   for(n = d - 1; n >= 0; n--) {
120
      f = f + pot * (s[n] - 48);
121
      pot = pot * 10;      
122
   }
123
 
124
   //ends if there are not decimal numbers
125
   if( s[d] == '\0')
126
      return f;
127
 
128
   //converts decimal numbers
129
   pot = 0.1;
130
   for(n = d + 1; s[n] != '\0'; n++) {
131
      f = f + pot * (s[n] - 48);
132
      pot = pot / 10;
133
      if(n >= 30)
134
         break;
135
 
136
   }
137
   return f;
138
}
139
 
140
//compares two strings returning 1 if they are equal otherwise 0
141
int streq(char *s1, char *s2)
142
{
143
   int n = 0;
144
   while(1)
145
      if( s1[n] == s2[n] )
146
         if( s1[n] == '\0' ) {
147
            return 1;
148
         }
149
         else {
150
            n++;
151
            //ends if the string is larger than the word variable 
152
            if(n >= 30)
153
              return 0;
154
         }
155
      else
156
         return 0;
157
}
158
 
159
//copies s2 string in s1 string
160
void strcp(char *s1, char *s2)
161
{
162
   int n = 0;
163
   while( s2[n] != '\0' ) {
164
      s1[n] = s2[n];
165
      n++;
166
      //ends if the string is larger than the word variable
167
      if(n >= 30)
168
         break;
169
   }
170
   s1[n] = '\0';
171
}
172
 
173
//writes data on the COM1 port (used only by open_com function)
174
void com_write(unsigned int port,unsigned int reg,unsigned int value)
175
{
176
    if (port > 3 || reg > 7) return;
177
    ll_out(com_base[port]+reg,value);
178
}
179
 
180
//reads data from the COM1 port without waiting
181
unsigned int com_read(unsigned int port,unsigned int reg)
182
{
183
    unsigned int b;
184
    if (port > 3 || reg > 7) return(0);
185
    b = ll_in(com_base[port]+reg);
186
    return(b);
187
}
188
 
189
//activates the COM1 port and makes it ready for reading/writing
190
int open_com(unsigned int port, DWORD speed, BYTE parity, BYTE len, BYTE stop)
191
{
192
    unsigned long div,b_mask;
193
 
194
    /* Now set up the serial link */
195
    b_mask = (parity & 3) * 8 + (stop & 1) * 4 + ((len - 5) & 3);
196
    div = 115200L / speed;
197
    /* Clear serial interrupt enable register */
198
    com_write(port,IER,0);
199
    /* Empty input buffer */
200
    com_read(port,RBR);
201
    /* Activate DLAB bit for speed setting */
202
    com_write(port,LCR,0x80);
203
    /* Load baud divisor */
204
    com_write(port,0,div & 0x00FF);
205
    div >>= 8;
206
    com_write(port,1,div & 0x00FF);
207
    /* Load control word (parity,stop bit,bit len) */
208
    com_write(port,LCR,b_mask);
209
    /* Activate OUT1 & OUT2 */
210
    com_write(port,MCR,0x0C);
211
 
212
    return 0;
213
 
214
}
215
 
216
/*rotates the axes of the mesa graphic objects and also of the sphere
217
  using the latitude and longitude data contained in the gps_data structure */
218
void polarView()
219
{
220
    float signlat, signlon; //contains directions of rotation
221
 
222
    //translates the axes far or near from the observer point to make zoom effect
223
    glTranslated(0.0, 0.0, radius + zoom);
224
    glRotated(-twist, 0.0, 0.0, 1.0);
225
 
226
    //direction of rotation in latitude may be Nord 'N' or Suoth 'S'
227
    if(gps_data.dirlat == 'N')
228
       signlat = -1;
229
    else
230
       signlat = 1;
231
 
232
    //direction of rotation in longitude may be East 'E' or West 'W'
233
    if(gps_data.dirlon == 'E')
234
       signlon = -1;
235
    else
236
       signlon = 1;
237
 
238
    /*there are some graphic errors in the two textures that result in a
239
      wrong placing of latitude and longitude on the image displayed.
240
      To compensate these errors some correction factors that depend
241
      on what texture you are using are added to latitude and longitude.*/
242
 
243
    switch(sel_texture) {
244
        case 1 : glRotated(signlat*gps_data.latitude + 3 , 1.0, 0.0, 0.0);
245
                 glRotated(signlon*gps_data.longitude, 0.0, 1.0, 0.0);                  
246
                 break;
247
        case 2 : glRotated(signlat*gps_data.latitude + 7 , 1.0, 0.0, 0.0);
248
                 glRotated(signlon*gps_data.longitude + 15, 0.0, 1.0, 0.0);                
249
    }
250
}
251
 
252
//initializes the mesa memory and prepares the textures
253
void gl_init()
254
{
255
  GLfloat h = (GLfloat) HEIGHT / (GLfloat) WIDTH;
256
  int r, c;
257
 
258
  //Create the OSMesa Context
259
  ctx = OSMesaCreateContext(OSMESA_RGB_565, NULL);
260
 
261
  //Set the memory pointed by rgb_565_buf to be the mesa buffer
262
  OSMesaMakeCurrent(ctx, rgb_565_buf, GL_UNSIGNED_SHORT_5_6_5, WIDTH, HEIGHT);
263
 
264
  glEnable(GL_DEPTH_TEST);
265
  glDisable( GL_DITHER );
266
 
267
  //Set up texturing
268
  glEnable( GL_TEXTURE_2D );
269
  glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL );
270
  glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST );
271
 
272
  /*puts all data contained in the headers in the tex and tex2 structures
273
    using the right order*/
274
  for(r = 0;  r < 256; r++)
275
     for(c = 0; c < 256; c++)
276
     {
277
        tex[r][c][0] = textureR[256*(256-r)+c];
278
        tex[r][c][1] = textureG[256*(256-r)+c];
279
        tex[r][c][2] = textureB[256*(256-r)+c];
280
        tex2[r][c][0] = texture2R[256*(256-r)+c];
281
        tex2[r][c][1] = texture2G[256*(256-r)+c];
282
        tex2[r][c][2] = texture2B[256*(256-r)+c];
283
 
284
     }
285
 
286
  glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
287
  glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
288
  glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
289
  glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
290
 
291
  //creates the list that define the sphere object
292
  sphere = 1;
293
  glNewList(sphere, GL_COMPILE);
294
        glEnable(GL_TEXTURE_2D);
295
        GLUquadricObj *quadObj = gluNewQuadric ();
296
        gluQuadricTexture(quadObj, GL_TRUE);
297
        gluQuadricDrawStyle(quadObj, GLU_FILL);
298
        gluQuadricNormals(quadObj, GLU_SMOOTH);
299
        glRotated(-90, 1.0, 0.0, 0.0);
300
        gluSphere (quadObj, 3, 30, 30);
301
  glEndList();
302
 
303
  glEnable(GL_NORMALIZE);
304
 
305
  //sets mesa(gl) viewport
306
  glViewport(0, 0, (GLint) WIDTH, (GLint) HEIGHT);
307
  glMatrixMode(GL_PROJECTION);
308
  glLoadIdentity();
309
  //sets the 3d visual volume and the observer point
310
  glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0);
311
  glMatrixMode(GL_MODELVIEW);
312
  glLoadIdentity();
313
  //places the origin of the axes of the 3d view
314
  glTranslated(0, -1, -40);
315
 
316
  radius = 0;
317
  twist = 0;    
318
 
319
}
320
 
321
/*Because mesa functions write graphic data on a dedicated buffer (gl buffer)
322
  this buffer once drawn has to be copied on video memory using this task*/
323
TASK refresh(void)
324
{
325
 
326
 /*  The gl buffer is used only by mesa functions, other graphic
327
  *  functions write directly on video memory (es. grx_text, grx_rect,...)
328
  *  so the refresh task can not overwrite the first 90 lines of video memory
329
  *  used by non mesa functions.
330
  */
331
 
332
  while(1) {
333
    task_testcancel();
334
    memcpy((video_buf+90*WIDTH*2), rgb_565_buf, RGB565MEM-90*WIDTH*2);
335
    task_endcycle();
336
  }
337
 
338
  sys_end();
339
 
340
}
341
 
342
/*generates gps-like values to simulate the gps transmitter when it is not connected,
343
  this function is called every time before drawing the image on mesa buffer
344
  if demo mode is on*/
345
void demo_val()
346
{
347
   int ns;
348
   int signal_max[4] = {25, 30, 10, 70};
349
   int azimuth_max[4] = {170, 10, 60, 100};
350
   int elevation_max[4] = {10, 60, 30, 79};
351
   ndemo += 1;
352
 
353
   //generates speed
354
   gps_data.speed = 25;
355
 
356
   //generates next direction increasing or decreasing the last one using kmov
357
   if(gps_data.dir_mov == 135)
358
      kmov = -1;
359
   if(gps_data.dir_mov == 45)
360
      kmov = 1;
361
 
362
   gps_data.dir_mov += kmov;
363
 
364
   //generates next latitude and longitude data using direction and speed
365
   demolat += cos(gps_data.dir_mov / (360/(2*M_PI)) ) * (gps_data.speed / 20);
366
   demolon += sin(gps_data.dir_mov / (360/(2*M_PI)) ) * (gps_data.speed / 20);
367
 
368
   lat = (int) demolat;
369
   lon = (int) demolon;
370
 
371
   /*demolat and demonlon count latitude and longitude from -infinite to
372
     +infinite, but latitude is actually displayed from -90 to +90
373
     (respectively nord or south) and longitude from -180 to +180 (respectively
374
     east or west) and so you have to convert demolat and demolon data into real
375
     latitude and longitude data before putting them in gps_data structure*/
376
 
377
   if(lon < 0)
378
      lon = 360 - (-lon) % 360;
379
 
380
   if(lon % 360 > 180) {
381
      gps_data.longitude = 180 - (lon % 360 - 180);
382
      gps_data.dirlon = 'W';
383
   }
384
   else {
385
      gps_data.longitude = lon % 360;
386
      gps_data.dirlon = 'E';      
387
   }
388
 
389
   if(lat < 0)
390
      lat = 360 - (-lat) % 360;
391
 
392
   if(lat % 360 >= 180) {    
393
      gps_data.dirlat = 'S';
394
      if(lat % 360 > 270)
395
         gps_data.latitude = 90 - (lat % 360 - 270);
396
      else {
397
         gps_data.latitude = lat % 360 - 180;
398
 
399
         gps_data.longitude = 180 - gps_data.longitude;
400
         if(gps_data.dirlon == 'E')
401
            gps_data.dirlon = 'W';
402
         else
403
            gps_data.dirlon = 'E';        
404
      }
405
   }
406
 
407
   if(lat % 360 < 180) {
408
      gps_data.dirlat = 'N';
409
      if(lat % 360 > 90) {
410
         gps_data.latitude = 90 - (lat % 360 - 90);
411
 
412
         gps_data.longitude = 180 - gps_data.longitude;
413
         if(gps_data.dirlon == 'E')
414
            gps_data.dirlon = 'W';
415
         else
416
            gps_data.dirlon = 'E';
417
      }
418
      else
419
         gps_data.latitude = lat % 360;    
420
   }
421
 
422
   //generates altitude and time
423
   gps_data.altitude = 79;
424
   strcp(gps_data.time, "113024.00");
425
 
426
   //generates the data of the satellites
427
   gps_data.nsat = 4;
428
 
429
   for(ns = 0; ns < 4; ns++) {
430
      gps_data.sat_data[ns].id = ns + 20;
431
      gps_data.sat_data[ns].azimuth = ndemo % azimuth_max[ns];
432
      gps_data.sat_data[ns].elevation = ndemo % elevation_max[ns];
433
      gps_data.sat_data[ns].signal_level = ndemo % signal_max[ns];
434
   }
435
 
436
}
437
 
438
//this task draws the whole graphic on video memory and on mesa buffer
439
TASK draw(void)
440
{
441
  char text[100];    
442
  TIME draw_TIME, refresh_TIME, gps_TIME;
443
 
444
  while(1) {
445
 
446
    task_testcancel();
447
 
448
    //if demo mode is on it calls demo_val function to generate gps-like values
449
    if(demo_mode == 1)
450
       demo_val();
451
 
452
    //gets time of execution of all the tasks
453
    jet_gettable(refresh_PID, &refresh_TIME, 1);
454
    jet_gettable(draw_PID, &draw_TIME, 1);
455
    jet_gettable(gps_PID, &gps_TIME, 1);
456
 
457
    //displays text informations and graphics using standard functions (grx functions)
458
 
459
    //displays the data of the execution times of the tasks 
460
    sprintf(text,"Hard Task Refresh PER:%6d us EX:%6d us",(int)PERIOD_REFRESH,(int)refresh_TIME);
461
    grx_text(text,10,55,rgb16(100,100,100),0);    
462
    sprintf(text,"Hard Task Draw    PER:%6d us EX:%6d us",(int)PERIOD_DRAW,(int)draw_TIME);
463
 
464
    //if there is a risk of system crash warns displaying the text in red color
465
    if(draw_TIME > PERIOD_DRAW * 0.65)
466
       grx_text(text,10,65,rgb16(255,0,0),0);
467
    else
468
       grx_text(text,10,65,rgb16(100,100,100),0);
469
 
470
    sprintf(text,"Hard Task Gps     PER:%6d us EX:%6d us",(int)PERIOD_GPS,(int)gps_TIME);
471
    grx_text(text,10,75,rgb16(100,100,100),0);
472
 
473
    //displays data contained in gps_data structure
474
    grx_rect(0, 0, 799, 89, rgb16(0, 0, 250));
475
    grx_rect(1, 52, 380, 88, rgb16(100, 100, 100));
476
 
477
    grx_text("Current position :",390,5,rgb16(0,255,255),0);
478
    sprintf(text,"Latitude %f dir %c      ", gps_data.latitude, gps_data.dirlat);
479
    grx_text(text,390,25,rgb16(0,255,255),0);
480
    sprintf(text,"Longitude %f dir %c      ", gps_data.longitude, gps_data.dirlon);
481
    grx_text(text,390,35,rgb16(0,255,255),0);
482
    sprintf(text,"Altitude %f   ", gps_data.altitude);
483
    grx_text(text,390,45,rgb16(0,255,255),0);
484
    sprintf(text,"Time %c%c:%c%c:%c%c  ", gps_data.time[0], gps_data.time[1], gps_data.time[2], gps_data.time[3], gps_data.time[4], gps_data.time[5]);
485
    grx_text(text,390,55,rgb16(0,255,255),0);
486
    sprintf(text,"Speed %f      ", gps_data.speed);
487
    grx_text(text,390,65,rgb16(0,0,255),0);
488
    sprintf(text,"Direction %f  ", gps_data.dir_mov);
489
    grx_text(text,390,75,rgb16(0,0,255),0);
490
 
491
    //displays satellites data contained in the gps_data structure
492
    grx_text("Satellites in view : ",600,5,rgb16(255,0,0),0);
493
    sprintf(text,"Number of satellites %f ", gps_data.nsat);
494
    grx_text(text,600, 25,rgb16(255,0,0),0);
495
    grx_text("Signal level ", 600, 35,rgb16(255,0,0),0);
496
 
497
    for(nlist = 0; nlist < 4; nlist++)
498
       if( gps_data.sat_data[nlist].signal_level > 99)
499
         gps_data.sat_data[nlist].signal_level = 99;
500
 
501
    grx_box(600, 45, 700, 80, rgb16(0, 0, 0));
502
    grx_box(600, 45, 600+gps_data.sat_data[0].signal_level, 50, rgb16(100, 0, 0));
503
    grx_box(600, 55, 600+gps_data.sat_data[1].signal_level, 60, rgb16(150, 0, 0));
504
    grx_box(600, 65, 600+gps_data.sat_data[2].signal_level, 70, rgb16(200, 0, 0));
505
    grx_box(600, 75, 600+gps_data.sat_data[3].signal_level, 80, rgb16(250, 0, 0));  
506
 
507
    //displays program title and other informations
508
    grx_text("G P S   D E M O", 10, 5, rgb16(0, 255, 0), 0);
509
    grx_text("Esc : end program...",170,5,rgb16(0,255,0),0);  
510
    grx_text("t   : change texture" ,170,15,rgb16(0,255,0),0);
511
    grx_text("d   : demo/gps mode " ,170,25,rgb16(0,255,0),0);
512
    grx_text("a z : zoom near/far " ,170,35,rgb16(0,255,0),0);
513
    if(demo_mode == 1)
514
       grx_text("Demo mode  " ,10,25,rgb16(255,255,0),0);
515
    else
516
       grx_text("Gps mode   " ,10,25,rgb16(0,255,0),0);          
517
 
518
 
519
    //displays mesa graphic
520
    int nmax;
521
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
522
 
523
    //selects and activates the correct texture
524
    if(sel_texture == 1)    
525
       glTexImage2D( GL_TEXTURE_2D, 0, 3, 256, 256, 0, GL_RGB, GL_UNSIGNED_BYTE, tex );
526
    else
527
       glTexImage2D( GL_TEXTURE_2D, 0, 3, 256, 256, 0, GL_RGB, GL_UNSIGNED_BYTE, tex2 );
528
 
529
    //draws the sphere calling the appropriate list defined in gl_init function
530
    glPushMatrix();
531
        polarView();
532
        glCallList(sphere);
533
    glPopMatrix();
534
 
535
    //draws the arrow and the cross on the sphere
536
    glPushMatrix();
537
        glTranslated (0, 0, zoom);        
538
        glDisable(GL_TEXTURE_2D);
539
        glColor3f (0, 1, 1);
540
        glTranslated (0, 0, 6);
541
        glRotated(180 + gps_data.dir_mov, 0.0, 0.0, 1.0);
542
        glLineWidth (2.0);
543
        glBegin(GL_LINES);
544
           glVertex2f(-0.2, 0.2);
545
           glVertex2f(0.2, -0.2);
546
           glVertex2f(0.2, 0.2);
547
           glVertex2f(-0.2, -0.2);
548
           glColor3f (0, 0, 1);
549
           glVertex2f(0, 0);
550
           glVertex2f(0, gps_data.speed/30);
551
           glVertex2f(0, gps_data.speed/30);
552
           glVertex2f(0.2, gps_data.speed/30-0.2);
553
           glVertex2f(0, gps_data.speed/30);
554
           glVertex2f(-0.2, gps_data.speed/30-0.2);
555
        glEnd();
556
        glColor3f (0, 0, 0.3);
557
        glTranslated (0.05, 0.05, 0);
558
        glBegin(GL_LINES);
559
           glVertex2f(-0.2, 0.2);
560
           glVertex2f(0.2, -0.2);
561
           glVertex2f(0.2, 0.2);
562
           glVertex2f(-0.2, -0.2);          
563
           glVertex2f(0, 0);
564
           glVertex2f(0, gps_data.speed/30);
565
           glVertex2f(0, gps_data.speed/30);
566
           glVertex2f(0.2, gps_data.speed/30-0.2);
567
           glVertex2f(0, gps_data.speed/30);
568
           glVertex2f(-0.2, gps_data.speed/30-0.2);          
569
        glEnd();
570
    glPopMatrix();
571
 
572
    //draws sattellites in view using azimuth and elevation data
573
    if(gps_data.nsat < 4) //this function can draw four satellites at maximum
574
       nmax = gps_data.nsat;
575
    else
576
       nmax = 4;
577
 
578
    for(nlist = 0; nlist < nmax; nlist++) {
579
        glPushMatrix();          
580
           glDisable(GL_TEXTURE_2D);
581
           glColor3f (0.4+0.2*nlist, 0, 0);
582
           glLineWidth (2.0);
583
           glRotated(gps_data.sat_data[nlist].azimuth, 0.0, 0.0, 1.0);
584
           glTranslated (0, 0, 3 + zoom);
585
           glRotated(90 - gps_data.sat_data[nlist].elevation, 1.0, 0.0, 0.0);
586
           glTranslated (0, 0, 4);
587
           glBegin(GL_LINES);
588
              glVertex2f(-0.1, -0.1);
589
              glVertex2f(0.1, 0.1);
590
              glVertex2f(-0.1, 0.1);
591
              glVertex2f(0.1, -0.1);
592
           glEnd();
593
        glPopMatrix();
594
    }
595
 
596
    glFinish();
597
 
598
    task_endcycle();
599
 
600
  }
601
 
602
  sys_end();
603
}
604
 
605
/*This task reads the data from the gps transmitter using the polling system.
606
  Gps sends data with a rate of 4800 bit/s this means 1 byte every 1.6 ms.
607
  If you want to be sure to get all the bytes transmitted by the gps you have
608
  to choose a period <1.6 ms for this gps task, in this program the period is
609
  1000ns or 1ms.*/
610
 
611
TASK gps(void)
612
{
613
  char c;
614
  while(1) {
615
    task_testcancel();
616
    //if a character is present on COM1
617
    if((com_read(COM1,LSR) & 1) == 1) {
618
       //reads and stores it in c
619
       c = com_read(COM1,RBR);
620
 
621
       //if c is a word delimiter
622
       if( (c == ',') || (c == '\n') || (c == '*') || (c == '\0') ) {
623
 
624
          //ends the current word and resets the word index
625
          word[ind] = '\0';
626
          ind = 0;
627
 
628
          //decodes the word variable
629
 
630
          //if word is a label that identifies the beginning of a gpgga string
631
          if( streq(word, "$GPGGA") == 1 )
632
             ind_gpgga = 0; //resets the gpgga index
633
 
634
          /*decodes the word depending on the gpgga index that identifies
635
            the position of the word just read in the gpgga string.
636
            then the word decoded is stored in the gps_data structure.*/
637
          switch(ind_gpgga) {
638
             case 1 : strcp(gps_data.time, word);
639
                      break;
640
             case 2 : gps_data.latitude = strtof(word) * 0.01;
641
                      break;
642
             case 3 : gps_data.dirlat = word[0];
643
                      break;
644
             case 4 : gps_data.longitude = strtof(word) * 0.1;
645
                      break;
646
             case 5 : gps_data.dirlon = word[0];
647
                      break;
648
             case 9 : gps_data.altitude = strtof(word);
649
          }
650
 
651
          //if the string is not ended increases the gpgga word counter
652
          if(ind_gpgga <= 14)
653
             ind_gpgga++;  
654
 
655
          //the same for gpgsv string
656
          if( streq(word, "$GPGSV") == 1 )
657
             ind_gpgsv = 0;
658
 
659
          switch(ind_gpgsv) {
660
             case 3 : gps_data.nsat = strtof(word);          
661
                      break;
662
             case 4 : gps_data.sat_data[0].id = strtof(word);
663
                      break;
664
             case 5 : gps_data.sat_data[0].elevation = strtof(word);
665
                      break;
666
             case 6 : gps_data.sat_data[0].azimuth = strtof(word);
667
                      break;
668
             case 7 : gps_data.sat_data[0].signal_level = strtof(word);
669
                      break;
670
             case 8 : gps_data.sat_data[1].id = strtof(word);
671
                      break;
672
             case 9 : gps_data.sat_data[1].elevation = strtof(word);
673
                      break;
674
             case 10 : gps_data.sat_data[1].azimuth = strtof(word);
675
                       break;
676
             case 11 : gps_data.sat_data[1].signal_level = strtof(word);
677
                       break;
678
             case 12 : gps_data.sat_data[2].id = strtof(word);
679
                       break;
680
             case 13 : gps_data.sat_data[2].elevation = strtof(word);
681
                       break;
682
             case 14 : gps_data.sat_data[2].azimuth = strtof(word);
683
                       break;
684
             case 15 : gps_data.sat_data[2].signal_level = strtof(word);
685
                       break;
686
             case 16 : gps_data.sat_data[3].id = strtof(word);
687
                       break;
688
             case 17 : gps_data.sat_data[3].elevation = strtof(word);
689
                       break;
690
             case 18 : gps_data.sat_data[3].azimuth = strtof(word);
691
                       break;
692
             case 19 : gps_data.sat_data[3].signal_level = strtof(word);            
693
          }
694
 
695
          if(ind_gpgsv <= 20)
696
             ind_gpgsv++;
697
 
698
          //the same for gprmc string
699
          if( streq(word, "$GPRMC") == 1 )
700
             ind_gprmc = 0;
701
 
702
          switch(ind_gprmc) {
703
             case 1 : strcp(gps_data.time, word);
704
                      break;
705
             case 3 : gps_data.latitude = strtof(word) * 0.01;
706
                      break;
707
             case 4 : gps_data.dirlat = word[0];
708
                      break;
709
             case 5 : gps_data.longitude = strtof(word) * 0.1;
710
                      break;
711
             case 6 : gps_data.dirlon = word[0];
712
                      break;
713
             case 7 : gps_data.speed = strtof(word);
714
                      break;
715
             case 8 : gps_data.dir_mov = strtof(word);
716
                      break;
717
             case 9 : gps_data.date = strtof(word);
718
                      break;
719
             case 10 : gps_data.var_mov = strtof(word);
720
                       break;
721
             case 11 : gps_data.dir_var_mov = word[0];
722
          }
723
 
724
          if(ind_gprmc <= 11)
725
             ind_gprmc++;  
726
 
727
       }
728
       //if c is not a word delimiter
729
       else {
730
          //store it in word at ind position and increase the index ind
731
          word[ind] = c;
732
          ind++;
733
       }
734
     }
735
     task_endcycle();
736
  }
737
 
738
  sys_end();
739
 
740
}
741
 
742
//is called just before program ends
743
void program_key_end(KEY_EVT *k)
744
{
745
  free(rgb_565_buf); //free the mesa buffer
746
  sys_end();
747
}
748
 
749
//is called when t key is pressed and changes the texture to be displayed on the sphere
750
void program_key_texture(KEY_EVT *k2)
751
{
752
   if(sel_texture == 1)
753
      sel_texture = 2;
754
   else
755
      sel_texture = 1;
756
}
757
 
758
//is called when d key is pressed and changes from demo to gps mode and vice versa
759
void program_key_demo(KEY_EVT *k3)
760
{
761
   if(demo_mode == 0)
762
      demo_mode = 1;
763
   else
764
      demo_mode = 0;
765
   ndemo = 0;
766
   kmov = -1;
767
   lat = 0;
768
   lon = 0;
769
   demolat = 0;
770
   demolon = 0;
771
   gps_data.dirlat = 'N';
772
   gps_data.dirlon = 'E';
773
   gps_data.latitude = 0;
774
   gps_data.longitude = 0;
775
   gps_data.dir_mov = 90;
776
}
777
 
778
//is called when a key is pressed and increases the zoom factor
779
void program_key_near(KEY_EVT *k4)
780
{
781
   zoom += 0.7;
782
}
783
 
784
//is called when a key is pressed and decreases the zoom factor
785
void program_key_far(KEY_EVT *k5)
786
{
787
   zoom -= 0.7;
788
}
789
 
790
int main (int argc, char *argv[])
791
{
792
 
793
    HARD_TASK_MODEL ht_refresh, ht_draw, ht_gps;
794
 
795
    //sets deadline for the tasks
796
    WCET_REFRESH =(int)((float) PERIOD_REFRESH * (0.22));
797
    WCET_DRAW =(int)((float) PERIOD_DRAW * (0.70));
798
    WCET_GPS =(int)((float) PERIOD_GPS * (0.05));
799
 
800
    //prepares refresh task for activation
801
    hard_task_default_model(ht_refresh);
802
    hard_task_def_wcet(ht_refresh,WCET_REFRESH);
803
    hard_task_def_mit(ht_refresh,PERIOD_REFRESH);
804
    hard_task_def_usemath(ht_refresh);
805
    hard_task_def_group(ht_refresh,1);
806
    hard_task_def_ctrl_jet(ht_refresh);
807
 
808
    refresh_PID = task_create("refresh", refresh, &ht_refresh, NULL);
809
    if (refresh_PID == -1) {
810
      sys_end();
811
      return 0;
812
    }
813
 
814
    //prepares draw task for activation
815
    hard_task_default_model(ht_draw);
816
    hard_task_def_mit(ht_draw,PERIOD_DRAW);
817
    hard_task_def_wcet(ht_draw,WCET_DRAW);
818
    hard_task_def_group(ht_draw,1);
819
    hard_task_def_ctrl_jet(ht_draw);
820
    hard_task_def_usemath(ht_draw);
821
    hard_task_def_stack(ht_draw,35000); //VERY IMPORTANT FOR glCallList !!
822
 
823
    draw_PID = task_create("draw", draw, &ht_draw, NULL);
824
    if (draw_PID == -1) {
825
      sys_end();
826
      return 0;
827
    }
828
 
829
    //prepares gps task for activation
830
    hard_task_default_model(ht_gps);
831
    hard_task_def_wcet(ht_gps,WCET_GPS);
832
    hard_task_def_mit(ht_gps,PERIOD_GPS);
833
    hard_task_def_usemath(ht_gps);
834
    hard_task_def_group(ht_gps,1);
835
    hard_task_def_ctrl_jet(ht_gps);
836
 
837
    gps_PID = task_create("gps", gps, &ht_gps, NULL);
838
    if (gps_PID == -1) {
839
      sys_end();
840
      return 0;
841
    }
842
 
843
    //defines and activates all the keyboard events used in the program
844
    {
845
      KEY_EVT k;
846
      k.scan = KEY_ESC;
847
      k.ascii = 27;
848
      k.status = KEY_PRESSED;
849
      keyb_hook(k,program_key_end,FALSE);
850
    }
851
 
852
    {
853
      KEY_EVT k2;
854
      k2.scan = KEY_T;
855
      k2.ascii = 't';
856
      k2.status = KEY_PRESSED;
857
      keyb_hook(k2,program_key_texture,FALSE);
858
    }
859
 
860
    {
861
      KEY_EVT k3;
862
      k3.scan = KEY_D;
863
      k3.ascii = 'd';
864
      k3.status = KEY_PRESSED;
865
      keyb_hook(k3,program_key_demo,FALSE);
866
    }
867
 
868
    {
869
      KEY_EVT k4;
870
      k4.scan = KEY_A;
871
      k4.ascii = 'a';
872
      k4.status = KEY_PRESSED;
873
      keyb_hook(k4,program_key_near,FALSE);
874
    }
875
 
876
    {
877
      KEY_EVT k5;
878
      k5.scan = KEY_Z;
879
      k5.ascii = 'z';
880
      k5.status = KEY_PRESSED;
881
      keyb_hook(k5,program_key_far,FALSE);
882
    }
883
 
884
    //allocates memory for mesa functions (mesa buffer)
885
    rgb_565_buf = malloc(RGB565MEM);
886
 
887
    //puts in a pointer the address of video memory
888
    video_buf = (unsigned char *)video_memory;
889
 
890
    //initializes mesa functions and prepares textures
891
    gl_init();
892
 
893
    //clears mesa buffer
894
    memset(rgb_565_buf, 0, RGB565MEM);
895
 
896
    //clears screen (video memory)
897
    grx_box(0, 0, 1023, 89, rgb16(0, 0, 0));
898
 
899
    //resets the word variable
900
    word[0] = '\0';
901
 
902
    //activates COM1 port to receive data from a gps transmitter
903
    open_com(COM1,4800,NONE,8,0);
904
 
905
    //activates the tasks previously created and prepared (draw, refresh, gps)
906
    group_activate(1);
907
 
908
    return 0;
909
 
910
}