Rev 1649 | Details | Compare with Previous | 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 |
||
1649 | giacomo | 4 | * transmitter connected to USB port. This is also a graphic demo that |
1648 | giacomo | 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 | |||
33 | #ifndef M_PI |
||
34 | #define M_PI 3.14159265 |
||
35 | #endif |
||
36 | |||
37 | //Graphic variables and constants |
||
38 | |||
39 | #define WIDTH 800 //Width of the screen in pixel |
||
40 | #define HEIGHT 600 //Height of the screen in pixel |
||
41 | #define BYTES_PP 2 //BytesPerPixel |
||
42 | |||
43 | OSMesaContext ctx; |
||
44 | |||
45 | extern void *video_memory; |
||
46 | |||
47 | unsigned char *rgb_565_buf = NULL; //RGB 16 bpp Buffer |
||
48 | unsigned char *video_buf = NULL; //Video Buffer |
||
49 | unsigned long int VMEMLONG = WIDTH*HEIGHT*BYTES_PP / 4; //Used by copy_videomem_16to16 |
||
50 | unsigned long int RGB565MEM = WIDTH*HEIGHT*BYTES_PP; //Total video mem |
||
51 | |||
52 | //Graphic Objects variables and constants |
||
53 | |||
54 | GLdouble radius, twist; //radius and twist of the sphere |
||
55 | float zoom = 0; //zoom factor |
||
56 | int sel_texture = 1; //index of the actually selected texture |
||
57 | GLubyte tex[256][256][3]; //stores the R, G, B data of the first texture |
||
58 | GLubyte tex2[256][256][3]; //stores the R, G, B data of the second texture |
||
59 | GLint sphere; //index of the shpere list (see mesa functions for details) |
||
60 | |||
61 | //Tasks variables and constants |
||
62 | |||
63 | unsigned long int PERIOD_DRAW = 100000; //period of the draw task |
||
64 | unsigned long int PERIOD_GPS = 1000; //period of the gps task |
||
1649 | giacomo | 65 | unsigned long int WCET_DRAW, WCET_GPS; //deadlines of the tasks |
66 | PID draw_PID, gps_PID; //indexes of the tasks |
||
1648 | giacomo | 67 | |
68 | //Gps receiver task variables and constants |
||
69 | |||
70 | char word[30]; //contains every word received from the gps transmitter |
||
71 | int ind = 0; //contains the index of the next character to be written in the variable word |
||
72 | int ind_gpgga = 0; //index of the next gpgga word to be read from gps |
||
73 | int ind_gpgsv = 0; //index of the next gpgsv word to be read from gps |
||
74 | int ind_gprmc = 0; //index of the next gprmc word to be read from gps |
||
75 | int nlist; //used to index satellites in gps_sat_data structure |
||
76 | |||
77 | //Demo mode variables and functions |
||
78 | |||
1649 | giacomo | 79 | int demo_mode = 1; //indicates if demo mode is active(=1) or not (=0) |
1648 | giacomo | 80 | int ndemo = 0; //a counter used while running in demo mode |
81 | int lat, lon; //auxiliary variables used for integer division |
||
82 | int kmov; //used to change the moving direction |
||
83 | float demolat = 0; //stores latitude |
||
84 | float demolon = 0; //stores longitude |
||
85 | |||
86 | //Gps data structures |
||
87 | |||
88 | typedef struct { |
||
89 | float id, elevation, azimuth, signal_level; |
||
90 | } gps_sat_data; |
||
91 | |||
92 | struct { |
||
93 | float latitude, longitude, altitude, nsat, speed, dir_mov, date, var_mov; |
||
94 | char dirlat, dirlon, time[12], dir_var_mov; |
||
95 | gps_sat_data sat_data[4]; //data of the satellites in view (4 maximum) |
||
96 | } gps_data; |
||
97 | |||
98 | TASK refesh(void); |
||
99 | TASK draw(void); |
||
100 | TASK gps(void); |
||
101 | |||
102 | //converts a string to a floating point |
||
103 | float strtof(char *s) |
||
104 | { |
||
105 | int d, n; |
||
106 | float f = 0, pot; |
||
107 | |||
108 | //if the string is null ends returning 0 |
||
109 | if(s[0] == '\0') |
||
110 | return 0; |
||
111 | |||
112 | //finds the dot character until the end of the string |
||
113 | for(d = 0; (s[d] != '.') && (s[d] != '\0') ; d++); |
||
114 | |||
115 | //converts non decimal numbers |
||
116 | pot = 1; |
||
117 | for(n = d - 1; n >= 0; n--) { |
||
118 | f = f + pot * (s[n] - 48); |
||
119 | pot = pot * 10; |
||
120 | } |
||
121 | |||
122 | //ends if there are not decimal numbers |
||
123 | if( s[d] == '\0') |
||
124 | return f; |
||
125 | |||
126 | //converts decimal numbers |
||
127 | pot = 0.1; |
||
128 | for(n = d + 1; s[n] != '\0'; n++) { |
||
129 | f = f + pot * (s[n] - 48); |
||
130 | pot = pot / 10; |
||
131 | if(n >= 30) |
||
132 | break; |
||
133 | |||
134 | } |
||
135 | return f; |
||
136 | } |
||
137 | |||
138 | //compares two strings returning 1 if they are equal otherwise 0 |
||
139 | int streq(char *s1, char *s2) |
||
140 | { |
||
141 | int n = 0; |
||
142 | while(1) |
||
143 | if( s1[n] == s2[n] ) |
||
144 | if( s1[n] == '\0' ) { |
||
145 | return 1; |
||
146 | } |
||
147 | else { |
||
148 | n++; |
||
149 | //ends if the string is larger than the word variable |
||
150 | if(n >= 30) |
||
151 | return 0; |
||
152 | } |
||
153 | else |
||
154 | return 0; |
||
155 | } |
||
156 | |||
157 | //copies s2 string in s1 string |
||
158 | void strcp(char *s1, char *s2) |
||
159 | { |
||
160 | int n = 0; |
||
161 | while( s2[n] != '\0' ) { |
||
162 | s1[n] = s2[n]; |
||
163 | n++; |
||
164 | //ends if the string is larger than the word variable |
||
165 | if(n >= 30) |
||
166 | break; |
||
167 | } |
||
168 | s1[n] = '\0'; |
||
169 | } |
||
170 | |||
171 | /*rotates the axes of the mesa graphic objects and also of the sphere |
||
172 | using the latitude and longitude data contained in the gps_data structure */ |
||
173 | void polarView() |
||
174 | { |
||
175 | float signlat, signlon; //contains directions of rotation |
||
176 | |||
177 | //translates the axes far or near from the observer point to make zoom effect |
||
178 | glTranslated(0.0, 0.0, radius + zoom); |
||
179 | glRotated(-twist, 0.0, 0.0, 1.0); |
||
180 | |||
181 | //direction of rotation in latitude may be Nord 'N' or Suoth 'S' |
||
182 | if(gps_data.dirlat == 'N') |
||
183 | signlat = -1; |
||
184 | else |
||
185 | signlat = 1; |
||
186 | |||
187 | //direction of rotation in longitude may be East 'E' or West 'W' |
||
188 | if(gps_data.dirlon == 'E') |
||
189 | signlon = -1; |
||
190 | else |
||
191 | signlon = 1; |
||
192 | |||
193 | /*there are some graphic errors in the two textures that result in a |
||
194 | wrong placing of latitude and longitude on the image displayed. |
||
195 | To compensate these errors some correction factors that depend |
||
196 | on what texture you are using are added to latitude and longitude.*/ |
||
197 | |||
198 | switch(sel_texture) { |
||
199 | case 1 : glRotated(signlat*gps_data.latitude + 3 , 1.0, 0.0, 0.0); |
||
200 | glRotated(signlon*gps_data.longitude, 0.0, 1.0, 0.0); |
||
201 | break; |
||
202 | case 2 : glRotated(signlat*gps_data.latitude + 7 , 1.0, 0.0, 0.0); |
||
203 | glRotated(signlon*gps_data.longitude + 15, 0.0, 1.0, 0.0); |
||
204 | } |
||
205 | } |
||
206 | |||
207 | //initializes the mesa memory and prepares the textures |
||
208 | void gl_init() |
||
209 | { |
||
210 | GLfloat h = (GLfloat) HEIGHT / (GLfloat) WIDTH; |
||
211 | int r, c; |
||
212 | |||
213 | //Create the OSMesa Context |
||
214 | ctx = OSMesaCreateContext(OSMESA_RGB_565, NULL); |
||
215 | |||
216 | //Set the memory pointed by rgb_565_buf to be the mesa buffer |
||
217 | OSMesaMakeCurrent(ctx, rgb_565_buf, GL_UNSIGNED_SHORT_5_6_5, WIDTH, HEIGHT); |
||
218 | |||
219 | glEnable(GL_DEPTH_TEST); |
||
220 | glDisable( GL_DITHER ); |
||
221 | |||
222 | //Set up texturing |
||
223 | glEnable( GL_TEXTURE_2D ); |
||
224 | glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL ); |
||
225 | glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST ); |
||
226 | |||
227 | /*puts all data contained in the headers in the tex and tex2 structures |
||
228 | using the right order*/ |
||
229 | for(r = 0; r < 256; r++) |
||
230 | for(c = 0; c < 256; c++) |
||
231 | { |
||
232 | tex[r][c][0] = textureR[256*(256-r)+c]; |
||
233 | tex[r][c][1] = textureG[256*(256-r)+c]; |
||
234 | tex[r][c][2] = textureB[256*(256-r)+c]; |
||
235 | tex2[r][c][0] = texture2R[256*(256-r)+c]; |
||
236 | tex2[r][c][1] = texture2G[256*(256-r)+c]; |
||
237 | tex2[r][c][2] = texture2B[256*(256-r)+c]; |
||
238 | |||
239 | } |
||
240 | |||
241 | glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); |
||
242 | glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); |
||
243 | glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); |
||
244 | glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); |
||
245 | |||
246 | //creates the list that define the sphere object |
||
247 | sphere = 1; |
||
248 | glNewList(sphere, GL_COMPILE); |
||
249 | glEnable(GL_TEXTURE_2D); |
||
250 | GLUquadricObj *quadObj = gluNewQuadric (); |
||
251 | gluQuadricTexture(quadObj, GL_TRUE); |
||
252 | gluQuadricDrawStyle(quadObj, GLU_FILL); |
||
253 | gluQuadricNormals(quadObj, GLU_SMOOTH); |
||
254 | glRotated(-90, 1.0, 0.0, 0.0); |
||
255 | gluSphere (quadObj, 3, 30, 30); |
||
256 | glEndList(); |
||
257 | |||
258 | glEnable(GL_NORMALIZE); |
||
259 | |||
260 | //sets mesa(gl) viewport |
||
261 | glViewport(0, 0, (GLint) WIDTH, (GLint) HEIGHT); |
||
262 | glMatrixMode(GL_PROJECTION); |
||
263 | glLoadIdentity(); |
||
264 | //sets the 3d visual volume and the observer point |
||
265 | glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0); |
||
266 | glMatrixMode(GL_MODELVIEW); |
||
267 | glLoadIdentity(); |
||
268 | //places the origin of the axes of the 3d view |
||
269 | glTranslated(0, -1, -40); |
||
270 | |||
271 | radius = 0; |
||
272 | twist = 0; |
||
273 | |||
274 | } |
||
275 | |||
276 | /*generates gps-like values to simulate the gps transmitter when it is not connected, |
||
277 | this function is called every time before drawing the image on mesa buffer |
||
278 | if demo mode is on*/ |
||
279 | void demo_val() |
||
280 | { |
||
281 | int ns; |
||
282 | int signal_max[4] = {25, 30, 10, 70}; |
||
283 | int azimuth_max[4] = {170, 10, 60, 100}; |
||
284 | int elevation_max[4] = {10, 60, 30, 79}; |
||
285 | ndemo += 1; |
||
286 | |||
287 | //generates speed |
||
288 | gps_data.speed = 25; |
||
289 | |||
290 | //generates next direction increasing or decreasing the last one using kmov |
||
291 | if(gps_data.dir_mov == 135) |
||
292 | kmov = -1; |
||
293 | if(gps_data.dir_mov == 45) |
||
294 | kmov = 1; |
||
295 | |||
296 | gps_data.dir_mov += kmov; |
||
297 | |||
298 | //generates next latitude and longitude data using direction and speed |
||
299 | demolat += cos(gps_data.dir_mov / (360/(2*M_PI)) ) * (gps_data.speed / 20); |
||
300 | demolon += sin(gps_data.dir_mov / (360/(2*M_PI)) ) * (gps_data.speed / 20); |
||
301 | |||
302 | lat = (int) demolat; |
||
303 | lon = (int) demolon; |
||
304 | |||
305 | /*demolat and demonlon count latitude and longitude from -infinite to |
||
306 | +infinite, but latitude is actually displayed from -90 to +90 |
||
307 | (respectively nord or south) and longitude from -180 to +180 (respectively |
||
308 | east or west) and so you have to convert demolat and demolon data into real |
||
309 | latitude and longitude data before putting them in gps_data structure*/ |
||
310 | |||
311 | if(lon < 0) |
||
312 | lon = 360 - (-lon) % 360; |
||
313 | |||
314 | if(lon % 360 > 180) { |
||
315 | gps_data.longitude = 180 - (lon % 360 - 180); |
||
316 | gps_data.dirlon = 'W'; |
||
317 | } |
||
318 | else { |
||
319 | gps_data.longitude = lon % 360; |
||
320 | gps_data.dirlon = 'E'; |
||
321 | } |
||
322 | |||
323 | if(lat < 0) |
||
324 | lat = 360 - (-lat) % 360; |
||
325 | |||
326 | if(lat % 360 >= 180) { |
||
327 | gps_data.dirlat = 'S'; |
||
328 | if(lat % 360 > 270) |
||
329 | gps_data.latitude = 90 - (lat % 360 - 270); |
||
330 | else { |
||
331 | gps_data.latitude = lat % 360 - 180; |
||
332 | |||
333 | gps_data.longitude = 180 - gps_data.longitude; |
||
334 | if(gps_data.dirlon == 'E') |
||
335 | gps_data.dirlon = 'W'; |
||
336 | else |
||
337 | gps_data.dirlon = 'E'; |
||
338 | } |
||
339 | } |
||
340 | |||
341 | if(lat % 360 < 180) { |
||
342 | gps_data.dirlat = 'N'; |
||
343 | if(lat % 360 > 90) { |
||
344 | gps_data.latitude = 90 - (lat % 360 - 90); |
||
345 | |||
346 | gps_data.longitude = 180 - gps_data.longitude; |
||
347 | if(gps_data.dirlon == 'E') |
||
348 | gps_data.dirlon = 'W'; |
||
349 | else |
||
350 | gps_data.dirlon = 'E'; |
||
351 | } |
||
352 | else |
||
353 | gps_data.latitude = lat % 360; |
||
354 | } |
||
355 | |||
356 | //generates altitude and time |
||
357 | gps_data.altitude = 79; |
||
358 | strcp(gps_data.time, "113024.00"); |
||
359 | |||
360 | //generates the data of the satellites |
||
361 | gps_data.nsat = 4; |
||
362 | |||
363 | for(ns = 0; ns < 4; ns++) { |
||
364 | gps_data.sat_data[ns].id = ns + 20; |
||
365 | gps_data.sat_data[ns].azimuth = ndemo % azimuth_max[ns]; |
||
366 | gps_data.sat_data[ns].elevation = ndemo % elevation_max[ns]; |
||
367 | gps_data.sat_data[ns].signal_level = ndemo % signal_max[ns]; |
||
368 | } |
||
369 | |||
370 | } |
||
371 | |||
372 | //this task draws the whole graphic on video memory and on mesa buffer |
||
373 | TASK draw(void) |
||
374 | { |
||
375 | char text[100]; |
||
1649 | giacomo | 376 | TIME draw_TIME, gps_TIME; |
1648 | giacomo | 377 | |
378 | while(1) { |
||
379 | |||
380 | task_testcancel(); |
||
381 | |||
382 | //if demo mode is on it calls demo_val function to generate gps-like values |
||
383 | if(demo_mode == 1) |
||
384 | demo_val(); |
||
385 | |||
386 | //gets time of execution of all the tasks |
||
387 | jet_gettable(draw_PID, &draw_TIME, 1); |
||
388 | jet_gettable(gps_PID, &gps_TIME, 1); |
||
389 | |||
390 | //displays text informations and graphics using standard functions (grx functions) |
||
391 | |||
392 | //displays the data of the execution times of the tasks |
||
393 | sprintf(text,"Hard Task Draw PER:%6d us EX:%6d us",(int)PERIOD_DRAW,(int)draw_TIME); |
||
394 | |||
395 | //if there is a risk of system crash warns displaying the text in red color |
||
396 | if(draw_TIME > PERIOD_DRAW * 0.65) |
||
397 | grx_text(text,10,65,rgb16(255,0,0),0); |
||
398 | else |
||
399 | grx_text(text,10,65,rgb16(100,100,100),0); |
||
400 | |||
401 | sprintf(text,"Hard Task Gps PER:%6d us EX:%6d us",(int)PERIOD_GPS,(int)gps_TIME); |
||
402 | grx_text(text,10,75,rgb16(100,100,100),0); |
||
403 | |||
404 | //displays data contained in gps_data structure |
||
405 | grx_rect(0, 0, 799, 89, rgb16(0, 0, 250)); |
||
406 | grx_rect(1, 52, 380, 88, rgb16(100, 100, 100)); |
||
407 | |||
408 | grx_text("Current position :",390,5,rgb16(0,255,255),0); |
||
409 | sprintf(text,"Latitude %f dir %c ", gps_data.latitude, gps_data.dirlat); |
||
410 | grx_text(text,390,25,rgb16(0,255,255),0); |
||
411 | sprintf(text,"Longitude %f dir %c ", gps_data.longitude, gps_data.dirlon); |
||
412 | grx_text(text,390,35,rgb16(0,255,255),0); |
||
413 | sprintf(text,"Altitude %f ", gps_data.altitude); |
||
414 | grx_text(text,390,45,rgb16(0,255,255),0); |
||
415 | 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]); |
||
416 | grx_text(text,390,55,rgb16(0,255,255),0); |
||
417 | sprintf(text,"Speed %f ", gps_data.speed); |
||
418 | grx_text(text,390,65,rgb16(0,0,255),0); |
||
419 | sprintf(text,"Direction %f ", gps_data.dir_mov); |
||
420 | grx_text(text,390,75,rgb16(0,0,255),0); |
||
421 | |||
422 | //displays satellites data contained in the gps_data structure |
||
423 | grx_text("Satellites in view : ",600,5,rgb16(255,0,0),0); |
||
424 | sprintf(text,"Number of satellites %f ", gps_data.nsat); |
||
425 | grx_text(text,600, 25,rgb16(255,0,0),0); |
||
426 | grx_text("Signal level ", 600, 35,rgb16(255,0,0),0); |
||
427 | |||
428 | for(nlist = 0; nlist < 4; nlist++) |
||
429 | if( gps_data.sat_data[nlist].signal_level > 99) |
||
430 | gps_data.sat_data[nlist].signal_level = 99; |
||
431 | |||
432 | grx_box(600, 45, 700, 80, rgb16(0, 0, 0)); |
||
433 | grx_box(600, 45, 600+gps_data.sat_data[0].signal_level, 50, rgb16(100, 0, 0)); |
||
434 | grx_box(600, 55, 600+gps_data.sat_data[1].signal_level, 60, rgb16(150, 0, 0)); |
||
435 | grx_box(600, 65, 600+gps_data.sat_data[2].signal_level, 70, rgb16(200, 0, 0)); |
||
436 | grx_box(600, 75, 600+gps_data.sat_data[3].signal_level, 80, rgb16(250, 0, 0)); |
||
437 | |||
438 | //displays program title and other informations |
||
439 | grx_text("G P S D E M O", 10, 5, rgb16(0, 255, 0), 0); |
||
440 | grx_text("Esc : end program...",170,5,rgb16(0,255,0),0); |
||
441 | grx_text("t : change texture" ,170,15,rgb16(0,255,0),0); |
||
442 | grx_text("d : demo/gps mode " ,170,25,rgb16(0,255,0),0); |
||
443 | grx_text("a z : zoom near/far " ,170,35,rgb16(0,255,0),0); |
||
444 | if(demo_mode == 1) |
||
445 | grx_text("Demo mode " ,10,25,rgb16(255,255,0),0); |
||
446 | else |
||
447 | grx_text("Gps mode " ,10,25,rgb16(0,255,0),0); |
||
448 | |||
449 | |||
450 | //displays mesa graphic |
||
451 | int nmax; |
||
452 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
||
453 | |||
454 | //selects and activates the correct texture |
||
455 | if(sel_texture == 1) |
||
456 | glTexImage2D( GL_TEXTURE_2D, 0, 3, 256, 256, 0, GL_RGB, GL_UNSIGNED_BYTE, tex ); |
||
457 | else |
||
458 | glTexImage2D( GL_TEXTURE_2D, 0, 3, 256, 256, 0, GL_RGB, GL_UNSIGNED_BYTE, tex2 ); |
||
459 | |||
460 | //draws the sphere calling the appropriate list defined in gl_init function |
||
461 | glPushMatrix(); |
||
462 | polarView(); |
||
463 | glCallList(sphere); |
||
464 | glPopMatrix(); |
||
465 | |||
466 | //draws the arrow and the cross on the sphere |
||
467 | glPushMatrix(); |
||
468 | glTranslated (0, 0, zoom); |
||
469 | glDisable(GL_TEXTURE_2D); |
||
470 | glColor3f (0, 1, 1); |
||
471 | glTranslated (0, 0, 6); |
||
472 | glRotated(180 + gps_data.dir_mov, 0.0, 0.0, 1.0); |
||
473 | glLineWidth (2.0); |
||
474 | glBegin(GL_LINES); |
||
475 | glVertex2f(-0.2, 0.2); |
||
476 | glVertex2f(0.2, -0.2); |
||
477 | glVertex2f(0.2, 0.2); |
||
478 | glVertex2f(-0.2, -0.2); |
||
479 | glColor3f (0, 0, 1); |
||
480 | glVertex2f(0, 0); |
||
481 | glVertex2f(0, gps_data.speed/30); |
||
482 | glVertex2f(0, gps_data.speed/30); |
||
483 | glVertex2f(0.2, gps_data.speed/30-0.2); |
||
484 | glVertex2f(0, gps_data.speed/30); |
||
485 | glVertex2f(-0.2, gps_data.speed/30-0.2); |
||
486 | glEnd(); |
||
487 | glColor3f (0, 0, 0.3); |
||
488 | glTranslated (0.05, 0.05, 0); |
||
489 | glBegin(GL_LINES); |
||
490 | glVertex2f(-0.2, 0.2); |
||
491 | glVertex2f(0.2, -0.2); |
||
492 | glVertex2f(0.2, 0.2); |
||
493 | glVertex2f(-0.2, -0.2); |
||
494 | glVertex2f(0, 0); |
||
495 | glVertex2f(0, gps_data.speed/30); |
||
496 | glVertex2f(0, gps_data.speed/30); |
||
497 | glVertex2f(0.2, gps_data.speed/30-0.2); |
||
498 | glVertex2f(0, gps_data.speed/30); |
||
499 | glVertex2f(-0.2, gps_data.speed/30-0.2); |
||
500 | glEnd(); |
||
501 | glPopMatrix(); |
||
502 | |||
503 | //draws sattellites in view using azimuth and elevation data |
||
504 | if(gps_data.nsat < 4) //this function can draw four satellites at maximum |
||
505 | nmax = gps_data.nsat; |
||
506 | else |
||
507 | nmax = 4; |
||
508 | |||
509 | for(nlist = 0; nlist < nmax; nlist++) { |
||
510 | glPushMatrix(); |
||
511 | glDisable(GL_TEXTURE_2D); |
||
512 | glColor3f (0.4+0.2*nlist, 0, 0); |
||
513 | glLineWidth (2.0); |
||
514 | glRotated(gps_data.sat_data[nlist].azimuth, 0.0, 0.0, 1.0); |
||
515 | glTranslated (0, 0, 3 + zoom); |
||
516 | glRotated(90 - gps_data.sat_data[nlist].elevation, 1.0, 0.0, 0.0); |
||
517 | glTranslated (0, 0, 4); |
||
518 | glBegin(GL_LINES); |
||
519 | glVertex2f(-0.1, -0.1); |
||
520 | glVertex2f(0.1, 0.1); |
||
521 | glVertex2f(-0.1, 0.1); |
||
522 | glVertex2f(0.1, -0.1); |
||
523 | glEnd(); |
||
524 | glPopMatrix(); |
||
525 | } |
||
526 | |||
527 | glFinish(); |
||
1649 | giacomo | 528 | |
529 | memcpy((video_buf+90*WIDTH*2), rgb_565_buf, RGB565MEM-90*WIDTH*2); |
||
530 | |||
1648 | giacomo | 531 | task_endcycle(); |
532 | |||
533 | } |
||
534 | |||
1650 | pj | 535 | exit(1); |
1648 | giacomo | 536 | } |
537 | |||
538 | /*This task reads the data from the gps transmitter using the polling system. |
||
539 | Gps sends data with a rate of 4800 bit/s this means 1 byte every 1.6 ms. |
||
540 | If you want to be sure to get all the bytes transmitted by the gps you have |
||
541 | to choose a period <1.6 ms for this gps task, in this program the period is |
||
542 | 1000ns or 1ms.*/ |
||
543 | |||
544 | TASK gps(void) |
||
545 | { |
||
1649 | giacomo | 546 | |
1648 | giacomo | 547 | while(1) { |
548 | task_testcancel(); |
||
1649 | giacomo | 549 | task_endcycle(); |
1648 | giacomo | 550 | } |
551 | |||
1650 | pj | 552 | exit(1); |
1648 | giacomo | 553 | |
554 | } |
||
555 | |||
556 | //is called just before program ends |
||
557 | void program_key_end(KEY_EVT *k) |
||
558 | { |
||
1650 | pj | 559 | exit(1); |
1648 | giacomo | 560 | } |
561 | |||
562 | //is called when t key is pressed and changes the texture to be displayed on the sphere |
||
563 | void program_key_texture(KEY_EVT *k2) |
||
564 | { |
||
565 | if(sel_texture == 1) |
||
566 | sel_texture = 2; |
||
567 | else |
||
568 | sel_texture = 1; |
||
569 | } |
||
570 | |||
571 | //is called when d key is pressed and changes from demo to gps mode and vice versa |
||
572 | void program_key_demo(KEY_EVT *k3) |
||
573 | { |
||
574 | if(demo_mode == 0) |
||
575 | demo_mode = 1; |
||
576 | else |
||
577 | demo_mode = 0; |
||
578 | ndemo = 0; |
||
579 | kmov = -1; |
||
580 | lat = 0; |
||
581 | lon = 0; |
||
582 | demolat = 0; |
||
583 | demolon = 0; |
||
584 | gps_data.dirlat = 'N'; |
||
585 | gps_data.dirlon = 'E'; |
||
586 | gps_data.latitude = 0; |
||
587 | gps_data.longitude = 0; |
||
588 | gps_data.dir_mov = 90; |
||
589 | } |
||
590 | |||
591 | //is called when a key is pressed and increases the zoom factor |
||
592 | void program_key_near(KEY_EVT *k4) |
||
593 | { |
||
594 | zoom += 0.7; |
||
595 | } |
||
596 | |||
597 | //is called when a key is pressed and decreases the zoom factor |
||
598 | void program_key_far(KEY_EVT *k5) |
||
599 | { |
||
600 | zoom -= 0.7; |
||
601 | } |
||
602 | |||
603 | int main (int argc, char *argv[]) |
||
604 | { |
||
605 | |||
1649 | giacomo | 606 | HARD_TASK_MODEL ht_draw, ht_gps; |
1648 | giacomo | 607 | |
1649 | giacomo | 608 | WCET_DRAW =(int)((float) PERIOD_DRAW * (0.90)); |
1648 | giacomo | 609 | WCET_GPS =(int)((float) PERIOD_GPS * (0.05)); |
610 | |||
611 | //prepares draw task for activation |
||
612 | hard_task_default_model(ht_draw); |
||
613 | hard_task_def_mit(ht_draw,PERIOD_DRAW); |
||
614 | hard_task_def_wcet(ht_draw,WCET_DRAW); |
||
615 | hard_task_def_group(ht_draw,1); |
||
616 | hard_task_def_ctrl_jet(ht_draw); |
||
617 | hard_task_def_usemath(ht_draw); |
||
618 | hard_task_def_stack(ht_draw,35000); //VERY IMPORTANT FOR glCallList !! |
||
619 | |||
620 | draw_PID = task_create("draw", draw, &ht_draw, NULL); |
||
621 | if (draw_PID == -1) { |
||
1650 | pj | 622 | exit(1); |
1648 | giacomo | 623 | return 0; |
624 | } |
||
625 | |||
626 | //prepares gps task for activation |
||
627 | hard_task_default_model(ht_gps); |
||
628 | hard_task_def_wcet(ht_gps,WCET_GPS); |
||
629 | hard_task_def_mit(ht_gps,PERIOD_GPS); |
||
630 | hard_task_def_usemath(ht_gps); |
||
631 | hard_task_def_group(ht_gps,1); |
||
632 | hard_task_def_ctrl_jet(ht_gps); |
||
633 | |||
634 | gps_PID = task_create("gps", gps, &ht_gps, NULL); |
||
635 | if (gps_PID == -1) { |
||
1650 | pj | 636 | exit(1); |
1648 | giacomo | 637 | return 0; |
638 | } |
||
639 | |||
640 | //defines and activates all the keyboard events used in the program |
||
641 | { |
||
642 | KEY_EVT k; |
||
643 | k.scan = KEY_ESC; |
||
644 | k.ascii = 27; |
||
645 | k.status = KEY_PRESSED; |
||
646 | keyb_hook(k,program_key_end,FALSE); |
||
647 | } |
||
648 | |||
649 | { |
||
650 | KEY_EVT k2; |
||
651 | k2.scan = KEY_T; |
||
652 | k2.ascii = 't'; |
||
653 | k2.status = KEY_PRESSED; |
||
654 | keyb_hook(k2,program_key_texture,FALSE); |
||
655 | } |
||
656 | |||
657 | { |
||
658 | KEY_EVT k3; |
||
659 | k3.scan = KEY_D; |
||
660 | k3.ascii = 'd'; |
||
661 | k3.status = KEY_PRESSED; |
||
662 | keyb_hook(k3,program_key_demo,FALSE); |
||
663 | } |
||
664 | |||
665 | { |
||
666 | KEY_EVT k4; |
||
667 | k4.scan = KEY_A; |
||
668 | k4.ascii = 'a'; |
||
669 | k4.status = KEY_PRESSED; |
||
670 | keyb_hook(k4,program_key_near,FALSE); |
||
671 | } |
||
672 | |||
673 | { |
||
674 | KEY_EVT k5; |
||
675 | k5.scan = KEY_Z; |
||
676 | k5.ascii = 'z'; |
||
677 | k5.status = KEY_PRESSED; |
||
678 | keyb_hook(k5,program_key_far,FALSE); |
||
679 | } |
||
680 | |||
681 | //allocates memory for mesa functions (mesa buffer) |
||
682 | rgb_565_buf = malloc(RGB565MEM); |
||
683 | |||
684 | //puts in a pointer the address of video memory |
||
685 | video_buf = (unsigned char *)video_memory; |
||
686 | |||
687 | //initializes mesa functions and prepares textures |
||
688 | gl_init(); |
||
689 | |||
690 | //clears mesa buffer |
||
691 | memset(rgb_565_buf, 0, RGB565MEM); |
||
692 | |||
693 | //clears screen (video memory) |
||
694 | grx_box(0, 0, 1023, 89, rgb16(0, 0, 0)); |
||
695 | |||
1649 | giacomo | 696 | ndemo = 0; |
697 | kmov = -1; |
||
698 | lat = 0; |
||
699 | lon = 0; |
||
700 | demolat = 0; |
||
701 | demolon = 0; |
||
702 | gps_data.dirlat = 'N'; |
||
703 | gps_data.dirlon = 'E'; |
||
704 | gps_data.latitude = 0; |
||
705 | gps_data.longitude = 0; |
||
706 | gps_data.dir_mov = 90; |
||
707 | |||
1648 | giacomo | 708 | //resets the word variable |
709 | word[0] = '\0'; |
||
710 | |||
711 | //activates the tasks previously created and prepared (draw, refresh, gps) |
||
712 | group_activate(1); |
||
713 | |||
714 | return 0; |
||
715 | |||
716 | } |