1,7 → 1,7 |
/* |
* 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 |
* transmitter connected to USB 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 |
29,7 → 29,6 |
#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 |
61,11 → 60,10 |
|
//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 |
unsigned long int WCET_DRAW, WCET_GPS; //deadlines of the tasks |
PID draw_PID, gps_PID; //indexes of the tasks |
|
//Gps receiver task variables and constants |
|
78,7 → 76,7 |
|
//Demo mode variables and functions |
|
int demo_mode = 0; //indicates if demo mode is active(=1) or not (=0) |
int demo_mode = 1; //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 |
170,49 → 168,6 |
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() |
318,27 → 273,6 |
|
} |
|
/*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*/ |
439,7 → 373,7 |
TASK draw(void) |
{ |
char text[100]; |
TIME draw_TIME, refresh_TIME, gps_TIME; |
TIME draw_TIME, gps_TIME; |
|
while(1) { |
|
450,7 → 384,6 |
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); |
|
457,8 → 390,6 |
//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 |
595,6 → 526,8 |
|
glFinish(); |
|
memcpy((video_buf+90*WIDTH*2), rgb_565_buf, RGB565MEM-90*WIDTH*2); |
|
task_endcycle(); |
|
} |
610,128 → 543,9 |
|
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(); |
} |
|
742,7 → 556,6 |
//is called just before program ends |
void program_key_end(KEY_EVT *k) |
{ |
free(rgb_565_buf); //free the mesa buffer |
sys_end(); |
} |
|
790,27 → 603,11 |
int main (int argc, char *argv[]) |
{ |
|
HARD_TASK_MODEL ht_refresh, ht_draw, ht_gps; |
HARD_TASK_MODEL 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_DRAW =(int)((float) PERIOD_DRAW * (0.90)); |
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); |
896,12 → 693,21 |
//clears screen (video memory) |
grx_box(0, 0, 1023, 89, rgb16(0, 0, 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; |
|
//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); |
|