📄 lowr.c
字号:
#include "g7to.h"
#define PROCX
long BaseLatitude;
long BaseLongitude;
long TailAdrPointer;
long HeadAdrPointer;
INT timeoutp;
INT validwp;
INT LwrRangeLo=1; // If retrieving a range of waypoints from a LEI unit this
// is the start waypoint #
INT LwrRangeHi=-1; // If retrieving a range of waypoints from a LEI unit this
// is the finish waypoint #
extern unsigned char bmh[118]; // = {
// 66, 77, 182, 31, 0, 0, 0, 0, 0, 0, 118, 0, 0,
// 0, 40, 0, 0, 0, 160, 0, 0, 0, 100, 0, 0, 0,
// 1, 0, 4, 0, 0, 0, 0, 0, 64, 31, 0, 0, 0,
// 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 16, 0,
// 0, 0, 0, 0, 0, 0, 99, 99, 99, 0, 181, 181, 181,
// 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0,
// 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255,
// 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255,
// 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0
//}; // bmh[118]
void readstarttofinish(long Start, long Finish, char * what, void (*fcn)(INT));
void debugOUTstd(BYTE *message, INT len,INT width);
INT totalread=0;
INT Total;
long rstfOffset=0;
INT AbortNow=0;
INT TotalDeltas=0;
INT NumberOfIcons=0;
INT NumOfGraphSymbols=0;
typedef unsigned char BYTE;
#if __BORLANDC__
extern INT WinNT;
#endif
BYTE LowrLogin;
INT LastCommand=0;
INT LowrValidWpts=0;
INT LowrMemBytesRead=0;
long LowrLastLat, LowrLastLong;
struct LowrID {
BYTE Reserved;
INT ProductID;
INT ProtocolVersion;
INT ScreenType;
INT ScreenWidth;
INT ScreenHeight;
INT NumOfWaypoints;
INT NumOfIcons;
INT NumOfRoutes;
INT NumOfWaypointsPerRoute;
BYTE NumOfPlotTrails;
BYTE NumOfIconSym;
BYTE ScreenRotateAngle;
long RunTime;
} LowrID;
struct LowrWPTr {
BYTE Reserved;
short WaypointNumber;
BYTE Status;
BYTE IconSymbol;
long Latitude; // LONG (Mercator Meter)
long Longitude; // LONG (Mercator Meter)
BYTE Name[13];
long Date; // seconds since 00:00 January 1, 1992
} LowrWPTr;
union Hdr {
BYTE Header[8];
struct hdrs {
INT preamble;
INT command;
INT length;
BYTE reserved;
BYTE checksum;
} hdrs;
} Hdr;
struct LowrTrailOrigin {
BYTE Reserved;
BYTE PlotTrailNumber;
long OriginY;
long OriginX;
short NumberOfDeltas;
} LowrTrailOrigin;
struct ND {
BYTE pt;
short no;
} ND;
struct LowrTrailOriginMem {
BYTE Reserved;
BYTE PlotTrailNumber;
long StructurePointer;
short StructureSize;
} LowrTrailOriginMem;
struct LowrMemGet {
long Address;
short Count;
BYTE CtgSelect;
} LowrMemGet;
struct LowrMemRead {
BYTE reserved;
union data {
struct ptp { // for reading Plot trail structure
long BaseLatitude;
long BaseLongitude;
long TailAdrPointer;
long HeadAdrPointer;
} ptp;
short data[80]; // for reading 80 shorts
BYTE bytes[160]; // for reading 360 bytes
unsigned long lbytes[40]; // for reading longs
} data;
} LowrMemRead;
#define MAX_Lowr_LENGTH 256
//
// Lowrance Serial Port Commands
//
enum {
ReadMem =0x0008, // Read from a memory location
WriteMem =0x0009, // Write to a memory location
Login =0x000D, // Wake up external serial port
BaudChange =0x010A, // Change NMEA Baud Rate
GetScreenPointer =0x0301, // Request Screen Pointer to download the current Screen
UnfreezeScreen =0x0302, // unfreeze the current screen (happens after downloading screen)
GetWaypoint =0x0303, // Get a Waypoint
SendWaypoint =0x0304, // Send a Waypoint
GetRoute =0x0305, // Get a Route
SendRoute =0x0306, // Send a Route
GetPlotTrail =0x0307, // Get plot trail Pointer
GetNumIcons =0x0308, // Get number of icons
GetIconSymbol =0x0309, // Get icon symbol
SetNumIcons =0x030A, // Set number of icons
SendIcon =0x030B, // Send icon
GetNumGraphSymbols =0x030C, // Get number of Graphical symbols
GetIconGraphSymbol =0x030D, // Get Icon Graphical symbol
GetProductInfo =0x030E, // Get product information
GetPlotTrailOrigin =0x0312, // Get Plot Trail Origin (Protocol version 2.0)
GetPlotTrailDeltas =0x0313, // Get Plot Trail Deltas (Protocol version 2.0)
SetPlotTrailOrigin =0x0314, // Set Plot Trail Origin (Protocol version 2.0)
SetPlotTrailDeltas =0x0315, // Set Plot Trail Deltas (Protocol version 2.0)
};
// Constants needed
#define RADtoDEG 57.295779513082322
#define EarthRad 6356752.3142
#define DEGtoRAD 0.017453292519943296
#define PI 3.14159265358979323846
#define PIdiv2 1.57079632679489661923
#define EarthRadxRADtoDEG 364215079.013679028
/* -------------------------------------------------------------------------- */
PROCX BYTE sethigh(BYTE b, BYTE val)
{
val&=0xf;
b&=0x0f;
b|=(val<<4);
return b;
} // sethigh
/* -------------------------------------------------------------------------- */
PROCX BYTE setlo(BYTE b, BYTE val)
{
val&=0xf;
b&=0xf0;
b|=val;
return b;
} // setlo
/* -------------------------------------------------------------------------- */
PROCX long swaplongendian(long in)
{
union a {
long b;
BYTE c[4];
} a;
BYTE temp;
a.b = in;
temp=a.c[0];
a.c[0]=a.c[3];
a.c[3]=temp;
temp=a.c[2];
a.c[2]=a.c[1];
a.c[1]=temp;
return a.b;
} // long swaplongendian(long a)
/* -------------------------------------------------------------------------- */
//
// Search the currend pushed waypoints for a name, latitude and longitud
// match. Returns the number of the waypoint in the list. This number is
// a number 1-waypoints
//
PROCX INT MatchRoute(char * namein, double la, double lo)
{
int i;
double lat,lon;
char name[20];
char *p;
char *b;
for(i=1;i<=waypoints;i++) {
b=strdup(waypoint_push[i]);
p=strtok3(b,";"); // Skip waypoint type
p=strtok3(NULL,";"); // Skip datatype
p=strtok3(NULL,";"); // Get name
strcpy(name,p);
p=strtok3(NULL,"!");
//
// skipping lat/long compare because at this point duplicate waypoint names
// are removed.
// lat=atof(strtok3(NULL,";")); // Get Latitude
// lon=atof(strtok3(NULL,";")); // Get Longitude
lat=la;
lon=lo;
free(b);
if((strncmp(name,namein,15) == 0) && la==lat && lo==lon) {
return i;
}
} // for
return -1;
} // MatchRoute
struct DispParms {
BYTE Reserved;
short PixelX;
short PixelY;
long BlackAddress;
short BlackCount;
long GreyAddress;
short GreyCount;
} DispParms;
BYTE *black,*grey;
/* -------------------------------------------------------------------------- */
//
// concatonates bytes to the black array
//
PROCX void DoScreenBlack(INT cnt)
{
static INT ptr=0;
memcpy(&black[ptr],&SerialMessage[1],cnt); // skip login id byte
ptr+=cnt;
} // DoScreenBlack
/* -------------------------------------------------------------------------- */
//
// concatonates bytes to the grey array
//
PROCX void DoScreenGrey(INT cnt)
{
static INT ptr=0;
memcpy(&grey[ptr],&SerialMessage[1],cnt); // skip login id byte
ptr+=cnt;
} // DoScreenGrey
BYTE *nib;
BYTE *nib2;
INT vertical,horizontalblack;
INT nibsize,siz,rowlen,linebytes;
/* -------------------------------------------------------------------------- */
PROCX void rotatedisp(void)
{
BYTE *raw;
INT i,j,k,rl,lb;
// printf("nibsize: %d, siz: %d, rowlen: %d, vertical: %d, horizontal: %d, linebytes: %d\n",
// nibsize, siz, rowlen,vertical,horizontalblack,linebytes);
//
// nib2 contains the data in slices of vertical size, but the length of each
// slice is rowlen bytes;
//
// rowlen: The actual number of bytes involved in the bitmap row (vertical)
// vertical: The actual number of pixels in the vertical row
// horizontalblack:The actual number of pixels in a horizontal row
// linebytes: The actual number of bytes that contain data in the vertical row
//
// For the EEII:
//
// rowlen: 52, vertical: 100, horizontal: 65, linebytes: 50
//
// for the GM100:
//
// siz: 8320, rowlen: 80, vertical: 160, horizontal: 104, linebytes: 80
//
// First we must move the 2 pixels per byte into a 1 pixel per byte array
//
if((raw=(BYTE*)calloc(nibsize*2+1000,1)) == NULL) {
oomem("rotatedisp1");
byebye(0);
}
j=k=0;
for(i=0;i<(nibsize);i++) { // was rowlen*horizontalblack
if(++j<=linebytes) {
raw[k++] = (nib[i]>>4)&0x0f;
if((j==linebytes) && (vertical&1)) continue;
raw[k++] = nib[i]&0x0f;
if(j==rowlen) j=0; // just in case rowlen=linebytes, i.e. no padding to skip
}
else {
if(j>=rowlen) j=0; // skip padding
}
}
//
// code checked good to here
//
lb=(horizontalblack/2)+(horizontalblack&1);
rl=(lb+3)&~3;
siz=vertical*rl;
//
// for the EEII
//
// rowlen: 36, vertical: 100, horizontal: 65, linebytes: 33
//
// for the GM100:
//
// siz: 8320, rowlen: 52, vertical: 160, horizontal: 104, linebytes: 52
//
// stuff the raw array into lines of horizontal black with 2 bits per pixel
//
k=0;
for(i=0;i<vertical;i++) {
for(j=0;j<horizontalblack;j+=2) {
nib2[k]=0;
nib2[k]=sethigh(nib2[k],raw[vertical*j+i]);
if((horizontalblack&1) && (j==(horizontalblack-1))) {
k++;
continue;
}
nib2[k]=setlo(nib2[k],raw[vertical*(j+1)+i]);
k++;
}
for(j=0;j<(rl-lb);j++) {
nib2[k]=0xff;
k++;
}
}
bmh[18]=horizontalblack;
bmh[22]=vertical;
} // rotatedisp
/* -------------------------------------------------------------------------- */
PROCX void DoScreenPointer(void)
{
// INT horizontal;
long tlong,greyadr,blackadr;
INT i,j,k;
if(open_output("wb")==0) return;
memcpy(&DispParms,SerialMessage,sizeof(struct DispParms));
blackadr=(DispParms.BlackAddress);
greyadr=(DispParms.GreyAddress);
vertical=LowrID.ScreenHeight;
if(LowrID.ScreenType<2) vertical++;
horizontalblack=(DispParms.BlackCount*8)/(DispParms.PixelX);
// horizontal =(DispParms.GreyCount/vertical)*8;
// printf("PixelX : %d\n",DispParms.PixelX);
// printf("PixelY : %d\n",DispParms.PixelY);
// printf("BlackAddress : 0x%08lx\n",blackadr);
// printf("BlackCount : %d\n",DispParms.BlackCount);
// printf("GreyAddress : 0x%08lx\n",greyadr);
// printf("GreyCount : %d\n",DispParms.GreyCount);
// printf("vertical: %d, Horizontal: %d\n",vertical,horizontalblack);
// fflush(stdout);
//
// Get Planes
//
rstfOffset=0;
if((black=(BYTE*)calloc(DispParms.BlackCount+100,1)) == NULL) {
oomem("DoScreenPointer1");
byebye(0);
}
totalread=0;
readstarttofinish(blackadr, blackadr+DispParms.BlackCount-1, "black plane", DoScreenBlack);
if(LowrID.ScreenType>0 && DispParms.GreyCount>0) {
if((grey=(BYTE*)calloc(DispParms.GreyCount+100,1)) == NULL) {
oomem("DoScreenPointer2");
byebye(0);
}
totalread=0;
readstarttofinish(greyadr, greyadr+DispParms.GreyCount-1, "grey plane",DoScreenGrey);
}
rowlen= (((vertical/2) + (vertical&1) + 3)&~3); // must end on a long boundary
linebytes=(vertical/2)+(vertical&1); // if vertical is odd must add 1
if(LowrID.ScreenType<2) siz=horizontalblack*vertical;
else siz=horizontalblack*vertical/2;
if((nib=(BYTE*)calloc(siz+1000,1))==NULL)
oomem("Allocating nibble buffer1");
if((nib2=(BYTE*)calloc(siz+1000,1))==NULL)
oomem("Allocating nibble buffer2");
k=0;
//
// Combine planes into 'nibble' buffer
//
// The code here takes the screen memory and converts it from 8 pixels
// per byte to 2 pixels per byte. By using the BlackCount we include
// the screen padding bytes.
//
for(i=0;i<DispParms.BlackCount;i++) {
for(j=6;j>=0;j-=2) {
if(DispParms.GreyCount>0)
if((grey[i]>>j)&1) nib[k]=setlo(nib[k],(BYTE)0x2);
if((black[i]>>j)&1) nib[k]=setlo(nib[k],(BYTE)3);
if((nib[k]&0x3) == 3) nib[k]=0; // invert the black
else if((nib[k]&0xf) == 0) nib[k]=3;
if(DispParms.GreyCount>0)
if((grey[i]>>(j+1))&1) nib[k]=sethigh(nib[k],(BYTE)2);
if((black[i]>>(j+1))&1) nib[k]=sethigh(nib[k],(BYTE)3);
if((nib[k]&0x30) == 0x30) nib[k]=sethigh(nib[k],0);// invert the black
else if((nib[k]&0xf0) == 0) nib[k]=sethigh(nib[k],3);
k++;
}
}
nibsize=k; // bytes in nib
free(black);
if(DispParms.GreyCount>0) free(grey);
k=j=0;
//
// process expanding nibble buffer into proper format
//
// In the following the scan 'row' is actually one vertical line in the
// display.
//
// In a .bmp of 16 colors the pixels each take up a nibble, i.e.
// two pixels per byte. Each row must end on a 4 byte boundary
// if not, 0 nibbles are added until a 4 byte boundary is reached
//
// The 4 byte boundary of x bytes can be calculated by (x+3)&~3
//
// In the input buffer, the GPS screen memory scan row is '0 padded'
// until it's length is equal to DispParms.PixelX. For example,
// in the EEII the DispParms.PixelX value is 112, but the screen scan row is
// only 100 pixels 'wide'. That means that 12 pixels of padding is added. This
// equates to 3 nibbles (8 pixels per byte in screen memory) of padding.
//
// In the code below the 'if(j<=rowlen)' takes care of
// adding the padding for the .bmp file. linebytes-rowlen gives the bytes of
// padding to add.
//
// If the last byte is only one nibble, the lower nibble is already
// set to 0 by the conversion from the screen format and doesn't need to be
// counted and the remainder is sufficient.
//
// The 'if(j>=DispParms.PixelX/2)' line takes care of the GPS screen
// padding bytes by skipping them if they exist. Not all units send padding bytes.
//
// printf("DispParms.BlackCount*4: %d\n",DispParms.BlackCount*4);
// printf("horizontal: %d, vertical: %d, vertical/2: %d\n",horizontalblack,vertical,vertical/2);
// printf("siz: %d\n",siz);
//
for(i=0;i<DispParms.BlackCount*4;i++) { // blackcount * 8 / 2 is the size of the source bfr
if(++j<=linebytes) // actual data
nib2[k++]=nib[i];
else {
if(j<=rowlen) nib2[k++]=0;
}
if(j>=DispParms.PixelX/2) j=0;
}
memcpy(nib,nib2,siz);
//
// mirror display horizontally on output
//
// work a row at a time starting with the last row in the array
// and working toward the front
//
j=0;
k=siz/horizontalblack;
for(i=siz-k;i>=0;i-=k) {
memcpy(&nib2[j],&nib[i],k);
j+=k;
}
bmh[18]=vertical;
bmh[22]=horizontalblack;
if(LowrID.ScreenRotateAngle==90) rotatedisp();
//
// set size of data
//
tlong=siz;
memcpy(&bmh[34],&tlong,4);
//
// set size of file
//
tlong+=118;
memcpy(&bmh[2],&tlong,4);
//
// write a standard 118 byte header for AxBx16 windows bitmaps
//
fwrite(bmh,118,1,out);
fwrite(nib2,siz,1,out);
//
// close out and free memory
//
fclose(out);
free(nib2);
free(nib);
} // DoScreenPointer
//struct LowrMemGet {
// long Address;
// short Count;
// BYTE CtgSelect;
//} LowrMemGet;
/* -------------------------------------------------------------------------- */
PROCX void GetLowrDisplay(void)
{
BYTE *temp;
temp=NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -