Rev 1649 |
Go to most recent revision |
Blame |
Compare with Previous |
Last modification |
View Log
| RSS feed
/*
* Project: S.Ha.R.K.
* G P S D E M O : this program receives and displays data from a gps
* transmitter connected to COM1 port. This is also a graphic demo that
* uses a software emulation of MESA libraries to display actual latitude
* and longitude on the earth globe. You can also use the program without
* having a gps transmitter because it can run in a demo mode (to do that
* press d key when the program starts).
*
* In the main function graphics and com1 port are initialized, respectively
* with a call to the functions gl_init and open_com. Then all the tasks
* used in the program are created and activated, these are :
*
* TASK refresh : copies the gl buffer to video memory
* TASK draw : draws all the graphics
* TASK gps : receives data from gps transmitter
*
*/
#include <kernel/log.h>
#include <kernel/kern.h>
#include <math.h>
#include <stdlib.h>
#include <drivers/shark_fb26.h>
#include <drivers/shark_keyb26.h>
#include <GL/osmesa.h> //MESA header
#include <GL/glut.h> //MESA header
#include "texture.h" //contains three arrayes that define the R, G, B data of the first texture (phisical earth)
#include "texture2.h" //contains three arrayes that define the R, G, B data of the second texture (political earth)
#include "comport.h" //contains constants used by COM1 functions
#ifndef M_PI
#define M_PI 3.14159265
#endif
//Graphic variables and constants
#define WIDTH 800 //Width of the screen in pixel
#define HEIGHT 600 //Height of the screen in pixel
#define BYTES_PP 2 //BytesPerPixel
OSMesaContext ctx
;
extern void *video_memory
;
unsigned char *rgb_565_buf
= NULL
; //RGB 16 bpp Buffer
unsigned char *video_buf
= NULL
; //Video Buffer
unsigned long int VMEMLONG
= WIDTH
*HEIGHT
*BYTES_PP
/ 4; //Used by copy_videomem_16to16
unsigned long int RGB565MEM
= WIDTH
*HEIGHT
*BYTES_PP
; //Total video mem
//Graphic Objects variables and constants
GLdouble radius
, twist
; //radius and twist of the sphere
float zoom
= 0; //zoom factor
int sel_texture
= 1; //index of the actually selected texture
GLubyte tex
[256][256][3]; //stores the R, G, B data of the first texture
GLubyte tex2
[256][256][3]; //stores the R, G, B data of the second texture
GLint sphere
; //index of the shpere list (see mesa functions for details)
//Tasks variables and constants
unsigned long int PERIOD_REFRESH
= 100000; //period of the refresh task in ns
unsigned long int PERIOD_DRAW
= 100000; //period of the draw task
unsigned long int PERIOD_GPS
= 1000; //period of the gps task
unsigned long int WCET_REFRESH
, WCET_DRAW
, WCET_GPS
; //deadlines of the tasks
PID refresh_PID
, draw_PID
, gps_PID
; //indexes of the tasks
//Gps receiver task variables and constants
char word
[30]; //contains every word received from the gps transmitter
int ind
= 0; //contains the index of the next character to be written in the variable word
int ind_gpgga
= 0; //index of the next gpgga word to be read from gps
int ind_gpgsv
= 0; //index of the next gpgsv word to be read from gps
int ind_gprmc
= 0; //index of the next gprmc word to be read from gps
int nlist
; //used to index satellites in gps_sat_data structure
//Demo mode variables and functions
int demo_mode
= 0; //indicates if demo mode is active(=1) or not (=0)
int ndemo
= 0; //a counter used while running in demo mode
int lat
, lon
; //auxiliary variables used for integer division
int kmov
; //used to change the moving direction
float demolat
= 0; //stores latitude
float demolon
= 0; //stores longitude
//Gps data structures
typedef struct {
float id
, elevation
, azimuth
, signal_level
;
} gps_sat_data
;
struct {
float latitude
, longitude
, altitude
, nsat
, speed
, dir_mov
, date
, var_mov
;
char dirlat
, dirlon
, time[12], dir_var_mov
;
gps_sat_data sat_data
[4]; //data of the satellites in view (4 maximum)
} gps_data
;
TASK refesh
(void);
TASK draw
(void);
TASK gps
(void);
//converts a string to a floating point
float strtof
(char *s
)
{
int d
, n
;
float f
= 0, pot
;
//if the string is null ends returning 0
if(s
[0] == '\0')
return 0;
//finds the dot character until the end of the string
for(d
= 0; (s
[d
] != '.') && (s
[d
] != '\0') ; d
++);
//converts non decimal numbers
pot
= 1;
for(n
= d
- 1; n
>= 0; n
--) {
f
= f
+ pot
* (s
[n
] - 48);
pot
= pot
* 10;
}
//ends if there are not decimal numbers
if( s
[d
] == '\0')
return f
;
//converts decimal numbers
pot
= 0.1;
for(n
= d
+ 1; s
[n
] != '\0'; n
++) {
f
= f
+ pot
* (s
[n
] - 48);
pot
= pot
/ 10;
if(n
>= 30)
break;
}
return f
;
}
//compares two strings returning 1 if they are equal otherwise 0
int streq
(char *s1
, char *s2
)
{
int n
= 0;
while(1)
if( s1
[n
] == s2
[n
] )
if( s1
[n
] == '\0' ) {
return 1;
}
else {
n
++;
//ends if the string is larger than the word variable
if(n
>= 30)
return 0;
}
else
return 0;
}
//copies s2 string in s1 string
void strcp
(char *s1
, char *s2
)
{
int n
= 0;
while( s2
[n
] != '\0' ) {
s1
[n
] = s2
[n
];
n
++;
//ends if the string is larger than the word variable
if(n
>= 30)
break;
}
s1
[n
] = '\0';
}
//writes data on the COM1 port (used only by open_com function)
void com_write
(unsigned int port
,unsigned int reg
,unsigned int value
)
{
if (port
> 3 || reg
> 7) return;
ll_out
(com_base
[port
]+reg
,value
);
}
//reads data from the COM1 port without waiting
unsigned int com_read
(unsigned int port
,unsigned int reg
)
{
unsigned int b
;
if (port
> 3 || reg
> 7) return(0);
b
= ll_in
(com_base
[port
]+reg
);
return(b
);
}
//activates the COM1 port and makes it ready for reading/writing
int open_com
(unsigned int port
, DWORD speed
, BYTE parity
, BYTE len
, BYTE stop
)
{
unsigned long div,b_mask
;
/* Now set up the serial link */
b_mask
= (parity
& 3) * 8 + (stop
& 1) * 4 + ((len
- 5) & 3);
div = 115200L / speed
;
/* Clear serial interrupt enable register */
com_write
(port
,IER
,0);
/* Empty input buffer */
com_read
(port
,RBR
);
/* Activate DLAB bit for speed setting */
com_write
(port
,LCR
,0x80);
/* Load baud divisor */
com_write
(port
,0,div & 0x00FF);
div >>= 8;
com_write
(port
,1,div & 0x00FF);
/* Load control word (parity,stop bit,bit len) */
com_write
(port
,LCR
,b_mask
);
/* Activate OUT1 & OUT2 */
com_write
(port
,MCR
,0x0C);
return 0;
}
/*rotates the axes of the mesa graphic objects and also of the sphere
using the latitude and longitude data contained in the gps_data structure */
void polarView
()
{
float signlat
, signlon
; //contains directions of rotation
//translates the axes far or near from the observer point to make zoom effect
glTranslated
(0.0, 0.0, radius
+ zoom
);
glRotated
(-twist
, 0.0, 0.0, 1.0);
//direction of rotation in latitude may be Nord 'N' or Suoth 'S'
if(gps_data.
dirlat == 'N')
signlat
= -1;
else
signlat
= 1;
//direction of rotation in longitude may be East 'E' or West 'W'
if(gps_data.
dirlon == 'E')
signlon
= -1;
else
signlon
= 1;
/*there are some graphic errors in the two textures that result in a
wrong placing of latitude and longitude on the image displayed.
To compensate these errors some correction factors that depend
on what texture you are using are added to latitude and longitude.*/
switch(sel_texture
) {
case 1 : glRotated
(signlat
*gps_data.
latitude + 3 , 1.0, 0.0, 0.0);
glRotated
(signlon
*gps_data.
longitude, 0.0, 1.0, 0.0);
break;
case 2 : glRotated
(signlat
*gps_data.
latitude + 7 , 1.0, 0.0, 0.0);
glRotated
(signlon
*gps_data.
longitude + 15, 0.0, 1.0, 0.0);
}
}
//initializes the mesa memory and prepares the textures
void gl_init
()
{
GLfloat h
= (GLfloat
) HEIGHT
/ (GLfloat
) WIDTH
;
int r
, c
;
//Create the OSMesa Context
ctx
= OSMesaCreateContext
(OSMESA_RGB_565
, NULL
);
//Set the memory pointed by rgb_565_buf to be the mesa buffer
OSMesaMakeCurrent
(ctx
, rgb_565_buf
, GL_UNSIGNED_SHORT_5_6_5
, WIDTH
, HEIGHT
);
glEnable
(GL_DEPTH_TEST
);
glDisable
( GL_DITHER
);
//Set up texturing
glEnable
( GL_TEXTURE_2D
);
glTexEnvi
( GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_DECAL
);
glHint
( GL_PERSPECTIVE_CORRECTION_HINT
, GL_FASTEST
);
/*puts all data contained in the headers in the tex and tex2 structures
using the right order*/
for(r
= 0; r
< 256; r
++)
for(c
= 0; c
< 256; c
++)
{
tex
[r
][c
][0] = textureR
[256*(256-r
)+c
];
tex
[r
][c
][1] = textureG
[256*(256-r
)+c
];
tex
[r
][c
][2] = textureB
[256*(256-r
)+c
];
tex2
[r
][c
][0] = texture2R
[256*(256-r
)+c
];
tex2
[r
][c
][1] = texture2G
[256*(256-r
)+c
];
tex2
[r
][c
][2] = texture2B
[256*(256-r
)+c
];
}
glTexParameteri
( GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
glTexParameteri
( GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
glTexParameteri
( GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_REPEAT
);
glTexParameteri
( GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_REPEAT
);
//creates the list that define the sphere object
sphere
= 1;
glNewList
(sphere
, GL_COMPILE
);
glEnable
(GL_TEXTURE_2D
);
GLUquadricObj
*quadObj
= gluNewQuadric
();
gluQuadricTexture
(quadObj
, GL_TRUE
);
gluQuadricDrawStyle
(quadObj
, GLU_FILL
);
gluQuadricNormals
(quadObj
, GLU_SMOOTH
);
glRotated
(-90, 1.0, 0.0, 0.0);
gluSphere
(quadObj
, 3, 30, 30);
glEndList
();
glEnable
(GL_NORMALIZE
);
//sets mesa(gl) viewport
glViewport
(0, 0, (GLint
) WIDTH
, (GLint
) HEIGHT
);
glMatrixMode
(GL_PROJECTION
);
glLoadIdentity
();
//sets the 3d visual volume and the observer point
glFrustum
(-1.0, 1.0, -h
, h
, 5.0, 60.0);
glMatrixMode
(GL_MODELVIEW
);
glLoadIdentity
();
//places the origin of the axes of the 3d view
glTranslated
(0, -1, -40);
radius
= 0;
twist
= 0;
}
/*Because mesa functions write graphic data on a dedicated buffer (gl buffer)
this buffer once drawn has to be copied on video memory using this task*/
TASK refresh
(void)
{
/* The gl buffer is used only by mesa functions, other graphic
* functions write directly on video memory (es. grx_text, grx_rect,...)
* so the refresh task can not overwrite the first 90 lines of video memory
* used by non mesa functions.
*/
while(1) {
task_testcancel
();
memcpy((video_buf
+90*WIDTH
*2), rgb_565_buf
, RGB565MEM
-90*WIDTH
*2);
task_endcycle
();
}
sys_end
();
}
/*generates gps-like values to simulate the gps transmitter when it is not connected,
this function is called every time before drawing the image on mesa buffer
if demo mode is on*/
void demo_val
()
{
int ns
;
int signal_max
[4] = {25, 30, 10, 70};
int azimuth_max
[4] = {170, 10, 60, 100};
int elevation_max
[4] = {10, 60, 30, 79};
ndemo
+= 1;
//generates speed
gps_data.
speed = 25;
//generates next direction increasing or decreasing the last one using kmov
if(gps_data.
dir_mov == 135)
kmov
= -1;
if(gps_data.
dir_mov == 45)
kmov
= 1;
gps_data.
dir_mov += kmov
;
//generates next latitude and longitude data using direction and speed
demolat
+= cos(gps_data.
dir_mov / (360/(2*M_PI
)) ) * (gps_data.
speed / 20);
demolon
+= sin(gps_data.
dir_mov / (360/(2*M_PI
)) ) * (gps_data.
speed / 20);
lat
= (int) demolat
;
lon
= (int) demolon
;
/*demolat and demonlon count latitude and longitude from -infinite to
+infinite, but latitude is actually displayed from -90 to +90
(respectively nord or south) and longitude from -180 to +180 (respectively
east or west) and so you have to convert demolat and demolon data into real
latitude and longitude data before putting them in gps_data structure*/
if(lon
< 0)
lon
= 360 - (-lon
) % 360;
if(lon
% 360 > 180) {
gps_data.
longitude = 180 - (lon
% 360 - 180);
gps_data.
dirlon = 'W';
}
else {
gps_data.
longitude = lon
% 360;
gps_data.
dirlon = 'E';
}
if(lat
< 0)
lat
= 360 - (-lat
) % 360;
if(lat
% 360 >= 180) {
gps_data.
dirlat = 'S';
if(lat
% 360 > 270)
gps_data.
latitude = 90 - (lat
% 360 - 270);
else {
gps_data.
latitude = lat
% 360 - 180;
gps_data.
longitude = 180 - gps_data.
longitude;
if(gps_data.
dirlon == 'E')
gps_data.
dirlon = 'W';
else
gps_data.
dirlon = 'E';
}
}
if(lat
% 360 < 180) {
gps_data.
dirlat = 'N';
if(lat
% 360 > 90) {
gps_data.
latitude = 90 - (lat
% 360 - 90);
gps_data.
longitude = 180 - gps_data.
longitude;
if(gps_data.
dirlon == 'E')
gps_data.
dirlon = 'W';
else
gps_data.
dirlon = 'E';
}
else
gps_data.
latitude = lat
% 360;
}
//generates altitude and time
gps_data.
altitude = 79;
strcp
(gps_data.
time, "113024.00");
//generates the data of the satellites
gps_data.
nsat = 4;
for(ns
= 0; ns
< 4; ns
++) {
gps_data.
sat_data[ns
].
id = ns
+ 20;
gps_data.
sat_data[ns
].
azimuth = ndemo
% azimuth_max
[ns
];
gps_data.
sat_data[ns
].
elevation = ndemo
% elevation_max
[ns
];
gps_data.
sat_data[ns
].
signal_level = ndemo
% signal_max
[ns
];
}
}
//this task draws the whole graphic on video memory and on mesa buffer
TASK draw
(void)
{
char text
[100];
TIME draw_TIME
, refresh_TIME
, gps_TIME
;
while(1) {
task_testcancel
();
//if demo mode is on it calls demo_val function to generate gps-like values
if(demo_mode
== 1)
demo_val
();
//gets time of execution of all the tasks
jet_gettable
(refresh_PID
, &refresh_TIME
, 1);
jet_gettable
(draw_PID
, &draw_TIME
, 1);
jet_gettable
(gps_PID
, &gps_TIME
, 1);
//displays text informations and graphics using standard functions (grx functions)
//displays the data of the execution times of the tasks
sprintf(text
,"Hard Task Refresh PER:%6d us EX:%6d us",(int)PERIOD_REFRESH
,(int)refresh_TIME
);
grx_text
(text
,10,55,rgb16
(100,100,100),0);
sprintf(text
,"Hard Task Draw PER:%6d us EX:%6d us",(int)PERIOD_DRAW
,(int)draw_TIME
);
//if there is a risk of system crash warns displaying the text in red color
if(draw_TIME
> PERIOD_DRAW
* 0.65)
grx_text
(text
,10,65,rgb16
(255,0,0),0);
else
grx_text
(text
,10,65,rgb16
(100,100,100),0);
sprintf(text
,"Hard Task Gps PER:%6d us EX:%6d us",(int)PERIOD_GPS
,(int)gps_TIME
);
grx_text
(text
,10,75,rgb16
(100,100,100),0);
//displays data contained in gps_data structure
grx_rect
(0, 0, 799, 89, rgb16
(0, 0, 250));
grx_rect
(1, 52, 380, 88, rgb16
(100, 100, 100));
grx_text
("Current position :",390,5,rgb16
(0,255,255),0);
sprintf(text
,"Latitude %f dir %c ", gps_data.
latitude, gps_data.
dirlat);
grx_text
(text
,390,25,rgb16
(0,255,255),0);
sprintf(text
,"Longitude %f dir %c ", gps_data.
longitude, gps_data.
dirlon);
grx_text
(text
,390,35,rgb16
(0,255,255),0);
sprintf(text
,"Altitude %f ", gps_data.
altitude);
grx_text
(text
,390,45,rgb16
(0,255,255),0);
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]);
grx_text
(text
,390,55,rgb16
(0,255,255),0);
sprintf(text
,"Speed %f ", gps_data.
speed);
grx_text
(text
,390,65,rgb16
(0,0,255),0);
sprintf(text
,"Direction %f ", gps_data.
dir_mov);
grx_text
(text
,390,75,rgb16
(0,0,255),0);
//displays satellites data contained in the gps_data structure
grx_text
("Satellites in view : ",600,5,rgb16
(255,0,0),0);
sprintf(text
,"Number of satellites %f ", gps_data.
nsat);
grx_text
(text
,600, 25,rgb16
(255,0,0),0);
grx_text
("Signal level ", 600, 35,rgb16
(255,0,0),0);
for(nlist
= 0; nlist
< 4; nlist
++)
if( gps_data.
sat_data[nlist
].
signal_level > 99)
gps_data.
sat_data[nlist
].
signal_level = 99;
grx_box
(600, 45, 700, 80, rgb16
(0, 0, 0));
grx_box
(600, 45, 600+gps_data.
sat_data[0].
signal_level, 50, rgb16
(100, 0, 0));
grx_box
(600, 55, 600+gps_data.
sat_data[1].
signal_level, 60, rgb16
(150, 0, 0));
grx_box
(600, 65, 600+gps_data.
sat_data[2].
signal_level, 70, rgb16
(200, 0, 0));
grx_box
(600, 75, 600+gps_data.
sat_data[3].
signal_level, 80, rgb16
(250, 0, 0));
//displays program title and other informations
grx_text
("G P S D E M O", 10, 5, rgb16
(0, 255, 0), 0);
grx_text
("Esc : end program...",170,5,rgb16
(0,255,0),0);
grx_text
("t : change texture" ,170,15,rgb16
(0,255,0),0);
grx_text
("d : demo/gps mode " ,170,25,rgb16
(0,255,0),0);
grx_text
("a z : zoom near/far " ,170,35,rgb16
(0,255,0),0);
if(demo_mode
== 1)
grx_text
("Demo mode " ,10,25,rgb16
(255,255,0),0);
else
grx_text
("Gps mode " ,10,25,rgb16
(0,255,0),0);
//displays mesa graphic
int nmax
;
glClear
(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
//selects and activates the correct texture
if(sel_texture
== 1)
glTexImage2D
( GL_TEXTURE_2D
, 0, 3, 256, 256, 0, GL_RGB
, GL_UNSIGNED_BYTE
, tex
);
else
glTexImage2D
( GL_TEXTURE_2D
, 0, 3, 256, 256, 0, GL_RGB
, GL_UNSIGNED_BYTE
, tex2
);
//draws the sphere calling the appropriate list defined in gl_init function
glPushMatrix
();
polarView
();
glCallList
(sphere
);
glPopMatrix
();
//draws the arrow and the cross on the sphere
glPushMatrix
();
glTranslated
(0, 0, zoom
);
glDisable
(GL_TEXTURE_2D
);
glColor3f
(0, 1, 1);
glTranslated
(0, 0, 6);
glRotated
(180 + gps_data.
dir_mov, 0.0, 0.0, 1.0);
glLineWidth
(2.0);
glBegin
(GL_LINES
);
glVertex2f
(-0.2, 0.2);
glVertex2f
(0.2, -0.2);
glVertex2f
(0.2, 0.2);
glVertex2f
(-0.2, -0.2);
glColor3f
(0, 0, 1);
glVertex2f
(0, 0);
glVertex2f
(0, gps_data.
speed/30);
glVertex2f
(0, gps_data.
speed/30);
glVertex2f
(0.2, gps_data.
speed/30-0.2);
glVertex2f
(0, gps_data.
speed/30);
glVertex2f
(-0.2, gps_data.
speed/30-0.2);
glEnd
();
glColor3f
(0, 0, 0.3);
glTranslated
(0.05, 0.05, 0);
glBegin
(GL_LINES
);
glVertex2f
(-0.2, 0.2);
glVertex2f
(0.2, -0.2);
glVertex2f
(0.2, 0.2);
glVertex2f
(-0.2, -0.2);
glVertex2f
(0, 0);
glVertex2f
(0, gps_data.
speed/30);
glVertex2f
(0, gps_data.
speed/30);
glVertex2f
(0.2, gps_data.
speed/30-0.2);
glVertex2f
(0, gps_data.
speed/30);
glVertex2f
(-0.2, gps_data.
speed/30-0.2);
glEnd
();
glPopMatrix
();
//draws sattellites in view using azimuth and elevation data
if(gps_data.
nsat < 4) //this function can draw four satellites at maximum
nmax
= gps_data.
nsat;
else
nmax
= 4;
for(nlist
= 0; nlist
< nmax
; nlist
++) {
glPushMatrix
();
glDisable
(GL_TEXTURE_2D
);
glColor3f
(0.4+0.2*nlist
, 0, 0);
glLineWidth
(2.0);
glRotated
(gps_data.
sat_data[nlist
].
azimuth, 0.0, 0.0, 1.0);
glTranslated
(0, 0, 3 + zoom
);
glRotated
(90 - gps_data.
sat_data[nlist
].
elevation, 1.0, 0.0, 0.0);
glTranslated
(0, 0, 4);
glBegin
(GL_LINES
);
glVertex2f
(-0.1, -0.1);
glVertex2f
(0.1, 0.1);
glVertex2f
(-0.1, 0.1);
glVertex2f
(0.1, -0.1);
glEnd
();
glPopMatrix
();
}
glFinish
();
task_endcycle
();
}
sys_end
();
}
/*This task reads the data from the gps transmitter using the polling system.
Gps sends data with a rate of 4800 bit/s this means 1 byte every 1.6 ms.
If you want to be sure to get all the bytes transmitted by the gps you have
to choose a period <1.6 ms for this gps task, in this program the period is
1000ns or 1ms.*/
TASK gps
(void)
{
char c
;
while(1) {
task_testcancel
();
//if a character is present on COM1
if((com_read
(COM1
,LSR
) & 1) == 1) {
//reads and stores it in c
c
= com_read
(COM1
,RBR
);
//if c is a word delimiter
if( (c
== ',') || (c
== '\n') || (c
== '*') || (c
== '\0') ) {
//ends the current word and resets the word index
word
[ind
] = '\0';
ind
= 0;
//decodes the word variable
//if word is a label that identifies the beginning of a gpgga string
if( streq
(word
, "$GPGGA") == 1 )
ind_gpgga
= 0; //resets the gpgga index
/*decodes the word depending on the gpgga index that identifies
the position of the word just read in the gpgga string.
then the word decoded is stored in the gps_data structure.*/
switch(ind_gpgga
) {
case 1 : strcp
(gps_data.
time, word
);
break;
case 2 : gps_data.
latitude = strtof
(word
) * 0.01;
break;
case 3 : gps_data.
dirlat = word
[0];
break;
case 4 : gps_data.
longitude = strtof
(word
) * 0.1;
break;
case 5 : gps_data.
dirlon = word
[0];
break;
case 9 : gps_data.
altitude = strtof
(word
);
}
//if the string is not ended increases the gpgga word counter
if(ind_gpgga
<= 14)
ind_gpgga
++;
//the same for gpgsv string
if( streq
(word
, "$GPGSV") == 1 )
ind_gpgsv
= 0;
switch(ind_gpgsv
) {
case 3 : gps_data.
nsat = strtof
(word
);
break;
case 4 : gps_data.
sat_data[0].
id = strtof
(word
);
break;
case 5 : gps_data.
sat_data[0].
elevation = strtof
(word
);
break;
case 6 : gps_data.
sat_data[0].
azimuth = strtof
(word
);
break;
case 7 : gps_data.
sat_data[0].
signal_level = strtof
(word
);
break;
case 8 : gps_data.
sat_data[1].
id = strtof
(word
);
break;
case 9 : gps_data.
sat_data[1].
elevation = strtof
(word
);
break;
case 10 : gps_data.
sat_data[1].
azimuth = strtof
(word
);
break;
case 11 : gps_data.
sat_data[1].
signal_level = strtof
(word
);
break;
case 12 : gps_data.
sat_data[2].
id = strtof
(word
);
break;
case 13 : gps_data.
sat_data[2].
elevation = strtof
(word
);
break;
case 14 : gps_data.
sat_data[2].
azimuth = strtof
(word
);
break;
case 15 : gps_data.
sat_data[2].
signal_level = strtof
(word
);
break;
case 16 : gps_data.
sat_data[3].
id = strtof
(word
);
break;
case 17 : gps_data.
sat_data[3].
elevation = strtof
(word
);
break;
case 18 : gps_data.
sat_data[3].
azimuth = strtof
(word
);
break;
case 19 : gps_data.
sat_data[3].
signal_level = strtof
(word
);
}
if(ind_gpgsv
<= 20)
ind_gpgsv
++;
//the same for gprmc string
if( streq
(word
, "$GPRMC") == 1 )
ind_gprmc
= 0;
switch(ind_gprmc
) {
case 1 : strcp
(gps_data.
time, word
);
break;
case 3 : gps_data.
latitude = strtof
(word
) * 0.01;
break;
case 4 : gps_data.
dirlat = word
[0];
break;
case 5 : gps_data.
longitude = strtof
(word
) * 0.1;
break;
case 6 : gps_data.
dirlon = word
[0];
break;
case 7 : gps_data.
speed = strtof
(word
);
break;
case 8 : gps_data.
dir_mov = strtof
(word
);
break;
case 9 : gps_data.
date = strtof
(word
);
break;
case 10 : gps_data.
var_mov = strtof
(word
);
break;
case 11 : gps_data.
dir_var_mov = word
[0];
}
if(ind_gprmc
<= 11)
ind_gprmc
++;
}
//if c is not a word delimiter
else {
//store it in word at ind position and increase the index ind
word
[ind
] = c
;
ind
++;
}
}
task_endcycle
();
}
sys_end
();
}
//is called just before program ends
void program_key_end
(KEY_EVT
*k
)
{
free(rgb_565_buf
); //free the mesa buffer
sys_end
();
}
//is called when t key is pressed and changes the texture to be displayed on the sphere
void program_key_texture
(KEY_EVT
*k2
)
{
if(sel_texture
== 1)
sel_texture
= 2;
else
sel_texture
= 1;
}
//is called when d key is pressed and changes from demo to gps mode and vice versa
void program_key_demo
(KEY_EVT
*k3
)
{
if(demo_mode
== 0)
demo_mode
= 1;
else
demo_mode
= 0;
ndemo
= 0;
kmov
= -1;
lat
= 0;
lon
= 0;
demolat
= 0;
demolon
= 0;
gps_data.
dirlat = 'N';
gps_data.
dirlon = 'E';
gps_data.
latitude = 0;
gps_data.
longitude = 0;
gps_data.
dir_mov = 90;
}
//is called when a key is pressed and increases the zoom factor
void program_key_near
(KEY_EVT
*k4
)
{
zoom
+= 0.7;
}
//is called when a key is pressed and decreases the zoom factor
void program_key_far
(KEY_EVT
*k5
)
{
zoom
-= 0.7;
}
int main
(int argc
, char *argv
[])
{
HARD_TASK_MODEL ht_refresh
, ht_draw
, ht_gps
;
//sets deadline for the tasks
WCET_REFRESH
=(int)((float) PERIOD_REFRESH
* (0.22));
WCET_DRAW
=(int)((float) PERIOD_DRAW
* (0.70));
WCET_GPS
=(int)((float) PERIOD_GPS
* (0.05));
//prepares refresh task for activation
hard_task_default_model
(ht_refresh
);
hard_task_def_wcet
(ht_refresh
,WCET_REFRESH
);
hard_task_def_mit
(ht_refresh
,PERIOD_REFRESH
);
hard_task_def_usemath
(ht_refresh
);
hard_task_def_group
(ht_refresh
,1);
hard_task_def_ctrl_jet
(ht_refresh
);
refresh_PID
= task_create
("refresh", refresh
, &ht_refresh
, NULL
);
if (refresh_PID
== -1) {
sys_end
();
return 0;
}
//prepares draw task for activation
hard_task_default_model
(ht_draw
);
hard_task_def_mit
(ht_draw
,PERIOD_DRAW
);
hard_task_def_wcet
(ht_draw
,WCET_DRAW
);
hard_task_def_group
(ht_draw
,1);
hard_task_def_ctrl_jet
(ht_draw
);
hard_task_def_usemath
(ht_draw
);
hard_task_def_stack
(ht_draw
,35000); //VERY IMPORTANT FOR glCallList !!
draw_PID
= task_create
("draw", draw
, &ht_draw
, NULL
);
if (draw_PID
== -1) {
sys_end
();
return 0;
}
//prepares gps task for activation
hard_task_default_model
(ht_gps
);
hard_task_def_wcet
(ht_gps
,WCET_GPS
);
hard_task_def_mit
(ht_gps
,PERIOD_GPS
);
hard_task_def_usemath
(ht_gps
);
hard_task_def_group
(ht_gps
,1);
hard_task_def_ctrl_jet
(ht_gps
);
gps_PID
= task_create
("gps", gps
, &ht_gps
, NULL
);
if (gps_PID
== -1) {
sys_end
();
return 0;
}
//defines and activates all the keyboard events used in the program
{
KEY_EVT k
;
k.
scan = KEY_ESC
;
k.
ascii = 27;
k.
status = KEY_PRESSED
;
keyb_hook
(k
,program_key_end
,FALSE
);
}
{
KEY_EVT k2
;
k2.
scan = KEY_T
;
k2.
ascii = 't';
k2.
status = KEY_PRESSED
;
keyb_hook
(k2
,program_key_texture
,FALSE
);
}
{
KEY_EVT k3
;
k3.
scan = KEY_D
;
k3.
ascii = 'd';
k3.
status = KEY_PRESSED
;
keyb_hook
(k3
,program_key_demo
,FALSE
);
}
{
KEY_EVT k4
;
k4.
scan = KEY_A
;
k4.
ascii = 'a';
k4.
status = KEY_PRESSED
;
keyb_hook
(k4
,program_key_near
,FALSE
);
}
{
KEY_EVT k5
;
k5.
scan = KEY_Z
;
k5.
ascii = 'z';
k5.
status = KEY_PRESSED
;
keyb_hook
(k5
,program_key_far
,FALSE
);
}
//allocates memory for mesa functions (mesa buffer)
rgb_565_buf
= malloc(RGB565MEM
);
//puts in a pointer the address of video memory
video_buf
= (unsigned char *)video_memory
;
//initializes mesa functions and prepares textures
gl_init
();
//clears mesa buffer
memset(rgb_565_buf
, 0, RGB565MEM
);
//clears screen (video memory)
grx_box
(0, 0, 1023, 89, rgb16
(0, 0, 0));
//resets the word variable
word
[0] = '\0';
//activates COM1 port to receive data from a gps transmitter
open_com
(COM1
,4800,NONE
,8,0);
//activates the tasks previously created and prepared (draw, refresh, gps)
group_activate
(1);
return 0;
}