moving everything out of dump1090.h and interactive.c

Former-commit-id: 09fc0bec299442fa1ac44ee6e41f237134ab2b73
Former-commit-id: 0f3edc36d54876849854abd4ef5ab8531f374b38
This commit is contained in:
nathan 2019-09-08 23:23:38 -05:00
parent 8cd0fa2a9d
commit 081ecda409
36 changed files with 779 additions and 865 deletions

View file

@ -25,8 +25,8 @@ all: view1090
%.o: %.c %.o: %.c
$(CC) $(CFLAGS) $(EXTRACFLAGS) -c $< $(CC) $(CFLAGS) $(EXTRACFLAGS) -c $<
view1090: view1090.o anet.o interactive.o mode_ac.o mode_s.o net_io.o input.o draw.o font.o init.o maps.o mapdata.o status.o list.o parula.o monokai.o view1090: view1090.o anet.o interactive.o mode_ac.o mode_s.o net_io.o planeObj.o input.o draw.o font.o init.o mapdata.o status.o list.o parula.o monokai.o
$(CC) -g -o view1090 view1090.o anet.o interactive.o mode_ac.o mode_s.o net_io.o input.o draw.o font.o init.o maps.o mapdata.o status.o list.o parula.o monokai.o $(LIBS) $(LDFLAGS) $(CC) -g -o view1090 view1090.o anet.o interactive.o mode_ac.o mode_s.o net_io.o planeObj.o input.o draw.o font.o init.o mapdata.o status.o list.o parula.o monokai.o $(LIBS) $(LDFLAGS)
clean: clean:
rm -f *.o view1090 rm -f *.o view1090

BIN
anet.o

Binary file not shown.

16
defs.h
View file

@ -6,18 +6,18 @@
#include "SDL2/SDL_ttf.h" #include "SDL2/SDL_ttf.h"
#include "mapdata.h" #include "mapdata.h"
#ifdef RPI
#include <wiringPi.h>
#endif
#define SCREEN_WIDTH 320 #define SCREEN_WIDTH 320
#define SCREEN_HEIGHT 480 #define SCREEN_HEIGHT 480
#define UPSCALE 1
#define UISCALE 1 #define UISCALE 1
#define AA 0 #define ROUND_RADIUS 3 //radius of text box corners
#define MAGMA 0 #define CENTEROFFSET .375 //vertical offset for middle of screen
#define ROUND_RADIUS 3 #define TRAIL_LENGTH 120
#define TRAIL_TTL 240.0
#define DISPLAY_ACTIVE 30
#define TRAIL_TTL_STEP 2
#define FRAMETIME 33

446
draw.c
View file

@ -1,6 +1,11 @@
#include "dump1090.h" #include "dump1090.h"
#include "structs.h" #include "structs.h"
#include "SDL2/SDL2_rotozoom.h" #include "SDL2/SDL2_rotozoom.h"
#include "SDL2/SDL2_gfxPrimitives.h"
//color schemes
#include "parula.h"
#include "monokai.h"
static uint64_t mstime(void) { static uint64_t mstime(void) {
struct timeval tv; struct timeval tv;
@ -12,25 +17,450 @@ static uint64_t mstime(void) {
return mst; return mst;
} }
void draw() { void CROSSVP(double *v, double *u, double *w)
{
v[0] = u[1]*w[2] - u[2]*(w)[1];
v[1] = u[2]*w[0] - u[0]*(w)[2];
v[2] = u[0]*w[1] - u[1]*(w)[0];
}
if ((mstime() - Modes.interactive_last_update) < MODES_INTERACTIVE_REFRESH_TIME) { SDL_Color setColor(uint8_t r, uint8_t g, uint8_t b) {
return; SDL_Color out;
out.r = r;
out.g = g;
out.b = b;
return out;
}
SDL_Color signalToColor(int signal) {
SDL_Color planeColor;
if(signal > 127) {
signal = 127;
} }
Modes.interactive_last_update = mstime(); if(signal < 0) {
planeColor = setColor(96, 96, 96);
} else {
planeColor = setColor(parula[signal][0], parula[signal][1], parula[signal][2]);
}
return planeColor;
}
int screenDist(double d) {
double scale_factor = (appData.screen_width > appData.screen_height) ? appData.screen_width : appData.screen_height;
if(appData.mapLogDist) {
return round(0.95 * scale_factor * 0.5 * log(1.0+fabs(d)) / log(1.0+appData.maxDist));
} else {
return round(0.95 * scale_factor * 0.5 * fabs(d) / appData.maxDist);
}
}
void pxFromLonLat(double *dx, double *dy, double lon, double lat) {
if(!lon || !lat) {
*dx = 0;
*dy = 0;
return;
}
*dx = 6371.0 * (lon - appData.centerLon) * M_PI / 180.0f * cos(((lat + appData.centerLat)/2.0f) * M_PI / 180.0f);
*dy = 6371.0 * (lat - appData.centerLat) * M_PI / 180.0f;
}
void screenCoords(int *outX, int *outY, double dx, double dy) {
*outX = (appData.screen_width>>1) + ((dx>0) ? 1 : -1) * screenDist(dx);
*outY = (appData.screen_height * CENTEROFFSET) + ((dy>0) ? -1 : 1) * screenDist(dy);
}
int outOfBounds(int x, int y) {
if(x < 0 || x >= appData.screen_width || y < 0 || y >= appData.screen_height ) {
return 1;
} else {
return 0;
}
}
void drawPlaneOffMap(int x, int y, int *returnx, int *returny, SDL_Color planeColor) {
double arrowWidth = 6.0 * appData.screen_uiscale;
float inx = x - (appData.screen_width>>1);
float iny = y - appData.screen_height * CENTEROFFSET;
float outx, outy;
outx = inx;
outy = iny;
if(abs(inx) > abs(y - (appData.screen_height>>1)) * (float)(appData.screen_width>>1) / (float)(appData.screen_height * CENTEROFFSET)) { //left / right quadrants
outx = (appData.screen_width>>1) * ((inx > 0) ? 1.0 : -1.0);
outy = (outx) * iny / (inx);
} else { // up / down quadrants
outy = appData.screen_height * ((iny > 0) ? 1.0-CENTEROFFSET : -CENTEROFFSET );
outx = (outy) * inx / (iny);
}
// circleRGBA (appData.renderer,(appData.screen_width>>1) + outx, appData.screen_height * CENTEROFFSET + outy,50,planeColor.r,planeColor.g,planeColor.b,SDL_ALPHA_OPAQUE);
// thickLineRGBA(appData.renderer,appData.screen_width>>1,appData.screen_height * CENTEROFFSET, (appData.screen_width>>1) + outx, appData.screen_height * CENTEROFFSET + outy,arrowWidth,planeColor.r,planeColor.g,planeColor.b,SDL_ALPHA_OPAQUE);
double inmag = sqrt(inx *inx + iny*iny);
double vec[3];
vec[0] = inx / inmag;
vec[1] = iny /inmag;
vec[2] = 0;
double up[] = {0,0,1};
double out[3];
CROSSVP(out,vec,up);
int x1, x2, x3, y1, y2, y3;
// arrow 1
x1 = (appData.screen_width>>1) + outx - 2.0 * arrowWidth * vec[0] + round(-arrowWidth*out[0]);
y1 = (appData.screen_height * CENTEROFFSET) + outy - 2.0 * arrowWidth * vec[1] + round(-arrowWidth*out[1]);
x2 = (appData.screen_width>>1) + outx - 2.0 * arrowWidth * vec[0] + round(arrowWidth*out[0]);
y2 = (appData.screen_height * CENTEROFFSET) + outy - 2.0 * arrowWidth * vec[1] + round(arrowWidth*out[1]);
x3 = (appData.screen_width>>1) + outx - arrowWidth * vec[0];
y3 = (appData.screen_height * CENTEROFFSET) + outy - arrowWidth * vec[1];
filledTrigonRGBA(appData.renderer, x1, y1, x2, y2, x3, y3, planeColor.r,planeColor.g,planeColor.b,SDL_ALPHA_OPAQUE);
// arrow 2
x1 = (appData.screen_width>>1) + outx - 3.0 * arrowWidth * vec[0] + round(-arrowWidth*out[0]);
y1 = (appData.screen_height * CENTEROFFSET) + outy - 3.0 * arrowWidth * vec[1] + round(-arrowWidth*out[1]);
x2 = (appData.screen_width>>1) + outx - 3.0 * arrowWidth * vec[0] + round(arrowWidth*out[0]);
y2 = (appData.screen_height * CENTEROFFSET) + outy - 3.0 * arrowWidth * vec[1] + round(arrowWidth*out[1]);
x3 = (appData.screen_width>>1) + outx - 2.0 * arrowWidth * vec[0];
y3 = (appData.screen_height * CENTEROFFSET) + outy - 2.0 * arrowWidth * vec[1];
filledTrigonRGBA(appData.renderer, x1, y1, x2, y2, x3, y3, planeColor.r,planeColor.g,planeColor.b,SDL_ALPHA_OPAQUE);
*returnx = x3;
*returny = y3;
}
void drawPlaneHeading(int x, int y, double heading, SDL_Color planeColor)
{
double body = 8.0 * appData.screen_uiscale;
double wing = 6.0 * appData.screen_uiscale;
double tail = 3.0 * appData.screen_uiscale;
double bodyWidth = 2.0 * appData.screen_uiscale;
double vec[3];
vec[0] = sin(heading * M_PI / 180);
vec[1] = -cos(heading * M_PI / 180);
vec[2] = 0;
double up[] = {0,0,1};
double out[3];
CROSSVP(out,vec,up);
int x1, x2, y1, y2;
// tempCenter
// circleRGBA(appData.renderer, x, y, 10, 255, 0, 0, 255);
//body
x1 = x + round(-body*vec[0]);
y1 = y + round(-body*vec[1]);
x2 = x + round(body*vec[0]);
y2 = y + round(body*vec[1]);
thickLineRGBA(appData.renderer,x,y,x2,y2,bodyWidth,planeColor.r,planeColor.g,planeColor.b,SDL_ALPHA_OPAQUE);
filledTrigonRGBA(appData.renderer, x + round(-wing*.35*out[0]), y + round(-wing*.35*out[1]), x + round(wing*.35*out[0]), y + round(wing*.35*out[1]), x1, y1,planeColor.r,planeColor.g,planeColor.b,SDL_ALPHA_OPAQUE);
filledCircleRGBA(appData.renderer, x2,y2,appData.screen_uiscale,planeColor.r,planeColor.g,planeColor.b,SDL_ALPHA_OPAQUE);
//wing
x1 = x + round(-wing*out[0]);
y1 = y + round(-wing*out[1]);
x2 = x + round(wing*out[0]);
y2 = y + round(wing*out[1]);
filledTrigonRGBA(appData.renderer, x1, y1, x2, y2, x+round(body*.35*vec[0]), y+round(body*.35*vec[1]),planeColor.r,planeColor.g,planeColor.b,SDL_ALPHA_OPAQUE);
//tail
x1 = x + round(-body*.75*vec[0]) + round(-tail*out[0]);
y1 = y + round(-body*.75*vec[1]) + round(-tail*out[1]);
x2 = x + round(-body*.75*vec[0]) + round(tail*out[0]);
y2 = y + round(-body*.75*vec[1]) + round(tail*out[1]);
filledTrigonRGBA (appData.renderer, x1, y1, x2, y2, x+round(-body*.5*vec[0]), y+round(-body*.5*vec[1]),planeColor.r,planeColor.g,planeColor.b,SDL_ALPHA_OPAQUE);
}
void drawPlane(int x, int y, SDL_Color planeColor)
{
int length = 3.0;
rectangleRGBA (appData.renderer, x - length, y - length, x+length, y + length, planeColor.r, planeColor.g, planeColor.b, SDL_ALPHA_OPAQUE);
}
void drawTrail(double *oldDx, double *oldDy, double *oldHeading, time_t * oldSeen, int idx) {
int currentIdx, prevIdx;
int currentX, currentY, prevX, prevY;
time_t now = time(NULL);
for(int i=0; i < (TRAIL_LENGTH - 1); i++) {
currentIdx = (idx - i) % TRAIL_LENGTH;
currentIdx = currentIdx < 0 ? currentIdx + TRAIL_LENGTH : currentIdx;
prevIdx = (idx - (i + 1)) % TRAIL_LENGTH;
prevIdx = prevIdx < 0 ? prevIdx + TRAIL_LENGTH : prevIdx;
if(oldDx[currentIdx] == 0 || oldDy[currentIdx] == 0) {
continue;
}
if(oldDx[prevIdx] == 0 || oldDy[prevIdx] == 0) {
continue;
}
double dx, dy;
pxFromLonLat(&dx, &dy, oldDx[currentIdx], oldDy[currentIdx]);
screenCoords(&currentX, &currentY, dx, dy);
pxFromLonLat(&dx, &dy, oldDx[prevIdx], oldDy[prevIdx]);
screenCoords(&prevX, &prevY, dx, dy);
if(outOfBounds(currentX,currentY)) {
return;
}
if(outOfBounds(prevX,prevY)) {
return;
}
double age = pow(1.0 - (double)(now - oldSeen[currentIdx]) / TRAIL_TTL, 2.2);
if(age < 0) {
age = 0;
}
uint8_t colorVal = (uint8_t)floor(255.0 * age);
thickLineRGBA(appData.renderer, prevX, prevY, currentX, currentY, 4 * appData.screen_uiscale, colorVal, colorVal, colorVal, 127);
//tick marks
double vec[3];
vec[0] = sin(oldHeading[currentIdx] * M_PI / 180);
vec[1] = -cos(oldHeading[currentIdx] * M_PI / 180);
vec[2] = 0;
double up[] = {0,0,1};
double out[3];
CROSSVP(out,vec,up);
int x1, y1, x2, y2;
int cross_size = 8 * appData.screen_uiscale;
//forward cross
x1 = currentX + round(-cross_size*vec[0]);
y1 = currentY + round(-cross_size*vec[1]);
x2 = currentX + round(cross_size*vec[0]);
y2 = currentY + round(cross_size*vec[1]);
lineRGBA(appData.renderer,x1,y1,x2,y2,colorVal,colorVal,colorVal,127);
//side cross
x1 = currentX + round(-cross_size*out[0]);
y1 = currentY + round(-cross_size*out[1]);
x2 = currentX + round(cross_size*out[0]);
y2 = currentY + round(cross_size*out[1]);
lineRGBA(appData.renderer,x1,y1,x2,y2,colorVal,colorVal,colorVal,127);
}
}
void drawGrid()
{
int p1km = screenDist(1.0);
int p10km = screenDist(10.0);
int p100km = screenDist(100.0);
circleRGBA (appData.renderer, appData.screen_width>>1, appData.screen_height * CENTEROFFSET, p1km, pink.r, pink.g, pink.b, 255);
circleRGBA (appData.renderer, appData.screen_width>>1, appData.screen_height * CENTEROFFSET, p10km, pink.r, pink.g, pink.b, 195);
circleRGBA (appData.renderer, appData.screen_width>>1, appData.screen_height * CENTEROFFSET, p100km, pink.r, pink.g, pink.b, 127);
drawString("1km", (appData.screen_width>>1) + (0.707 * p1km) + 5, (appData.screen_height * CENTEROFFSET) + (0.707 * p1km) + 5, appData.mapFont, pink);
drawString("10km", (appData.screen_width>>1) + (0.707 * p10km) + 5, (appData.screen_height * CENTEROFFSET) + (0.707 * p10km) + 5, appData.mapFont, pink);
drawString("100km", (appData.screen_width>>1) + (0.707 * p100km) + 5, (appData.screen_height * CENTEROFFSET) + (0.707 * p100km) + 5, appData.mapFont, pink);
}
void drawGeography() {
int x1, y1, x2, y2;
for(int i=1; i<mapPoints_count/2; i++) {
double dx, dy;
pxFromLonLat(&dx, &dy, mapPoints_relative[(i - 1) * 2], mapPoints_relative[(i - 1) * 2 + 1]);
if(!dx || !dy) {
continue;
}
screenCoords(&x1, &y1, dx, dy);
if(outOfBounds(x1,y1)) {
continue;
}
double d1 = sqrt(dx * dx + dy * dy);
pxFromLonLat(&dx, &dy, mapPoints_relative[i * 2], mapPoints_relative[i * 2 + 1]);
if(!dx || !dy) {
continue;
}
screenCoords(&x2, &y2, dx, dy);
if(outOfBounds(x2,y2)) {
continue;
}
double d2 = sqrt(dx* dx + dy * dy);
//double alpha = 255.0 * (d1+d2) / 2;
//alpha = 255.0 - alpha / appData.maxDist;
double alpha = 1.0 - (d1+d2) / (2 * appData.maxDist);
alpha = (alpha < 0) ? 0 : alpha;
lineRGBA(appData.renderer, x1, y1, x2, y2, alpha * purple.r + (1.0-alpha) * blue.r, alpha * purple.g + (1.0-alpha) * blue.g, alpha * purple.b + (1.0-alpha) * blue.b, 255 * alpha);
}
}
void drawMap() {
struct planeObj *p = planes;
time_t now = time(NULL);
drawGeography();
drawGrid();
while(p) {
if ((now - p->seen) < Modes.interactive_display_ttl) {
if (p->lon && p->lat) {
unsigned char * pSig = p->signalLevel;
unsigned int signalAverage = (pSig[0] + pSig[1] + pSig[2] + pSig[3] +
pSig[4] + pSig[5] + pSig[6] + pSig[7] + 3) >> 3;
drawTrail(p->oldLon, p->oldLat, p->oldHeading, p->oldSeen, p->oldIdx);
int colorIdx;
if((int)(now - p->seen) > DISPLAY_ACTIVE) {
colorIdx = -1;
} else {
colorIdx = signalAverage;
}
SDL_Color planeColor = signalToColor(colorIdx);
int x, y;
//screenCoords(&x, &y, p->dx, p->dy);
double dx, dy;
pxFromLonLat(&dx, &dy, p->lon, p->lat);
screenCoords(&x, &y, dx, dy);
if(outOfBounds(x,y)) {
int outx, outy;
drawPlaneOffMap(x, y, &outx, &outy, planeColor);
drawStringBG(p->flight, outx + 5, outy + appData.mapFontHeight, appData.mapBoldFont, white, black);
char alt[10] = " ";
snprintf(alt,10,"%dm", p->altitude);
drawStringBG(alt, outx + 5, outy + 2*appData.mapFontHeight, appData.mapFont, grey, black);
char speed[10] = " ";
snprintf(speed,10,"%dkm/h", p->speed);
drawStringBG(speed, outx + 5, outy + 3*appData.mapFontHeight, appData.mapFont, grey, black);
// continue;
}
if(p->created == 0) {
p->created = mstime();
}
double age_ms = (double)(mstime() - p->created);
if(age_ms < 500) {
circleRGBA(appData.renderer, x, y, 500 - age_ms, 255,255, 255, (uint8_t)(255.0 * age_ms / 500.0));
} else {
if(MODES_ACFLAGS_HEADING_VALID) {
drawPlaneHeading(x, y,p->track, planeColor);
//char flight[11] = " ";
//snprintf(flight,11," %s ", p->flight);
//drawStringBG(flight, x, y + appData.mapFontHeight, appData.mapBoldFont, black, planeColor);
drawStringBG(p->flight, x + 5, y + appData.mapFontHeight, appData.mapBoldFont, white, black);
char alt[10] = " ";
snprintf(alt,10,"%dm", p->altitude);
drawStringBG(alt, x + 5, y + 2*appData.mapFontHeight, appData.mapFont, grey, black);
char speed[10] = " ";
snprintf(speed,10,"%dkm/h", p->speed);
drawStringBG(speed, x + 5, y + 3*appData.mapFontHeight, appData.mapFont, grey, black);
lineRGBA(appData.renderer, x, y, x, y + 4*appData.mapFontHeight, grey.r, grey.g, grey.b, SDL_ALPHA_OPAQUE);
} else {
drawPlane(x, y, planeColor);
}
}
}
}
p = p->next;
}
}
//
//
//
void draw() {
if ((mstime() - appData.lastFrameTime) < FRAMETIME) {
return;
}
appData.lastFrameTime = mstime();
updatePlanes();
updateStatus(); updateStatus();
SDL_SetRenderDrawColor( game.renderer, 0, 0, 0, 0); SDL_SetRenderDrawColor( appData.renderer, 0, 0, 0, 0);
SDL_RenderClear(game.renderer); SDL_RenderClear(appData.renderer);
drawMap(); drawMap();
drawStatus(); drawStatus();
if(!Modes.map) { if(appData.showList) {
drawList(0); drawList(0);
} }
SDL_RenderPresent(game.renderer); SDL_RenderPresent(appData.renderer);
} }

BIN
draw.o

Binary file not shown.

1
draw.o.REMOVED.git-id Normal file
View file

@ -0,0 +1 @@
935a39fc34ea31bd03a177786917177c0d74191a

View file

@ -160,14 +160,10 @@
// at least greater than a given level for us to dump the signal. // at least greater than a given level for us to dump the signal.
#define MODES_DEBUG_NOPREAMBLE_LEVEL 25 #define MODES_DEBUG_NOPREAMBLE_LEVEL 25
#define MODES_INTERACTIVE_REFRESH_TIME 33 // Milliseconds #define MODES_INTERACTIVE_REFRESH_TIME 250 // Milliseconds
#define MODES_INTERACTIVE_ROWS 22 // Rows on screen #define MODES_INTERACTIVE_ROWS 22 // Rows on screen
#define MODES_INTERACTIVE_DELETE_TTL 300 // Delete from the list after 300 seconds #define MODES_INTERACTIVE_DELETE_TTL 300 // Delete from the list after 300 seconds
#define MODES_INTERACTIVE_DISPLAY_TTL 60 // Delete from display after 60 seconds #define MODES_INTERACTIVE_DISPLAY_TTL 60 // Delete from display after 60 seconds
#define MODES_INTERACTIVE_DISPLAY_ACTIVE 30 // Gray out after 30 seconds
#define MODES_INTERACTIVE_TRAIL_LENGTH 120 // entries to keep in trail
#define MODES_INTERACTIVE_TRAIL_TTL_STEP 2 // minimum time between entries
#define MODES_INTERACTIVE_TRAIL_TTL 240.0 // # seconds to fade out
#define MODES_NET_HEARTBEAT_RATE 900 // Each block is approx 65mS - default is > 1 min #define MODES_NET_HEARTBEAT_RATE 900 // Each block is approx 65mS - default is > 1 min
@ -209,12 +205,10 @@ struct aircraft {
int track; // Angle of flight int track; // Angle of flight
int vert_rate; // Vertical rate. int vert_rate; // Vertical rate.
time_t seen; // Time at which the last packet was received time_t seen; // Time at which the last packet was received
time_t prev_seen;
time_t seenLatLon; // Time at which the last lat long was calculated time_t seenLatLon; // Time at which the last lat long was calculated
uint64_t timestamp; // Timestamp at which the last packet was received uint64_t timestamp; // Timestamp at which the last packet was received
uint64_t timestampLatLon;// Timestamp at which the last lat long was calculated uint64_t timestampLatLon;// Timestamp at which the last lat long was calculated
long messages; // Number of Mode S messages received long messages; // Number of Mode S messages received
double messageRate[8]; // Number of Mode S messages received
int modeA; // Squawk int modeA; // Squawk
int modeC; // Altitude int modeC; // Altitude
long modeAcount; // Mode A Squawk hit Count long modeAcount; // Mode A Squawk hit Count
@ -229,24 +223,10 @@ struct aircraft {
uint64_t odd_cprtime; uint64_t odd_cprtime;
uint64_t even_cprtime; uint64_t even_cprtime;
double lat, lon; // Coordinated obtained from CPR encoded data double lat, lon; // Coordinated obtained from CPR encoded data
double dx, dy; // distance in km
double oldDx[MODES_INTERACTIVE_TRAIL_LENGTH], oldDy[MODES_INTERACTIVE_TRAIL_LENGTH], oldHeading[MODES_INTERACTIVE_TRAIL_LENGTH]; // position history
time_t oldSeen[MODES_INTERACTIVE_TRAIL_LENGTH];// position time
uint8_t oldIdx; // index for ring buffer
uint64_t created;
int bFlags; // Flags related to valid fields in this structure int bFlags; // Flags related to valid fields in this structure
struct aircraft *next; // Next aircraft in our linked list struct aircraft *next; // Next aircraft in our linked list
}; };
struct {
double msgRate;
double avgSig;
int numPlanes;
int numVisiblePlanes;
double maxDist;
struct aircraft *closeCall;
} Status;
struct stDF { struct stDF {
struct stDF *pNext; // Pointer to next item in the linked list struct stDF *pNext; // Pointer to next item in the linked list
struct stDF *pPrev; // Pointer to previous item in the linked list struct stDF *pPrev; // Pointer to previous item in the linked list
@ -339,19 +319,6 @@ struct { // Internal state
int mlat; // Use Beast ascii format for raw data output, i.e. @...; iso *...; int mlat; // Use Beast ascii format for raw data output, i.e. @...; iso *...;
int interactive_rtl1090; // flight table in interactive mode is formatted like RTL1090 int interactive_rtl1090; // flight table in interactive mode is formatted like RTL1090
// map options
int map;
int mapLogDist;
float maxDist;
//display options
int screen_upscale;
int screen_uiscale;
int screen_width;
int screen_height;
int screen_depth;
int fullscreen;
// User details // User details
double fUserLat; // Users receiver/antenna lat/lon needed for initial surface location double fUserLat; // Users receiver/antenna lat/lon needed for initial surface location
double fUserLon; // Users receiver/antenna lat/lon needed for initial surface location double fUserLon; // Users receiver/antenna lat/lon needed for initial surface location
@ -492,13 +459,6 @@ void modesSendAllClients (int service, void *msg, int len);
void modesQueueOutput (struct modesMessage *mm); void modesQueueOutput (struct modesMessage *mm);
void modesReadFromClient(struct client *c, char *sep, int(*handler)(struct client *, char *)); void modesReadFromClient(struct client *c, char *sep, int(*handler)(struct client *, char *));
//
// Functions exported from maps.c
//
void drawMap (void);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

10
font.c
View file

@ -1,4 +1,4 @@
#include "font.h" #include "structs.h"
#include "SDL2/SDL2_rotozoom.h" #include "SDL2/SDL2_rotozoom.h"
TTF_Font *loadFont(char *name, int size) TTF_Font *loadFont(char *name, int size)
@ -51,8 +51,8 @@ void drawString(char * text, int x, int y, TTF_Font *font, SDL_Color color)
dest.w = surface->w; dest.w = surface->w;
dest.h = surface->h; dest.h = surface->h;
SDL_Texture *texture = SDL_CreateTextureFromSurface(game.renderer, surface); SDL_Texture *texture = SDL_CreateTextureFromSurface(appData.renderer, surface);
SDL_RenderCopy(game.renderer, texture, NULL, &dest); SDL_RenderCopy(appData.renderer, texture, NULL, &dest);
SDL_DestroyTexture(texture); SDL_DestroyTexture(texture);
SDL_FreeSurface(surface); SDL_FreeSurface(surface);
} }
@ -81,8 +81,8 @@ void drawStringBG(char * text, int x, int y, TTF_Font *font, SDL_Color color, SD
dest.w = surface->w; dest.w = surface->w;
dest.h = surface->h; dest.h = surface->h;
SDL_Texture *texture = SDL_CreateTextureFromSurface(game.renderer, surface); SDL_Texture *texture = SDL_CreateTextureFromSurface(appData.renderer, surface);
SDL_RenderCopy(game.renderer, texture, NULL, &dest); SDL_RenderCopy(appData.renderer, texture, NULL, &dest);
SDL_DestroyTexture(texture); SDL_DestroyTexture(texture);
SDL_FreeSurface(surface); SDL_FreeSurface(surface);
} }

3
font.h
View file

@ -1,3 +0,0 @@
#include "structs.h"
extern Game game;

BIN
font.o

Binary file not shown.

62
init.c
View file

@ -1,5 +1,5 @@
#include "dump1090.h" #include "dump1090.h"
#include "init.h" #include "structs.h"
void init(char *title) { void init(char *title) {
// raspberry pi compiler flag enables these options // raspberry pi compiler flag enables these options
@ -19,67 +19,53 @@ void init(char *title) {
exit(1); exit(1);
} }
// #ifdef RPI
// const SDL_VideoInfo* vInfo = SDL_GetVideoInfo();
// if (!vInfo) {
// fprintf(stderr,"ERROR in SDL_GetVideoInfo(): %s\n",SDL_GetError());
// exit(1);
// }
// Modes.screen_width = vInfo->current_w;
// Modes.screen_height = vInfo->current_h;
// Modes.screen_depth = vInfo->vfmt->BitsPerPixel;
// Modes.screen_upscale = 1;
// #endifX
SDL_ShowCursor(SDL_DISABLE); SDL_ShowCursor(SDL_DISABLE);
Uint32 flags = 0; Uint32 flags = 0;
if(Modes.fullscreen) { if(appData.fullscreen) {
flags = flags | SDL_WINDOW_FULLSCREEN_DESKTOP; flags = flags | SDL_WINDOW_FULLSCREEN_DESKTOP;
} }
game.window = SDL_CreateWindow(title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, Modes.screen_width, Modes.screen_height, flags); appData.window = SDL_CreateWindow(title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, appData.screen_width, appData.screen_height, flags);
game.renderer = SDL_CreateRenderer(game.window, -1, 0); appData.renderer = SDL_CreateRenderer(appData.window, -1, 0);
game.texture = SDL_CreateTexture(game.renderer, appData.texture = SDL_CreateTexture(appData.renderer,
SDL_PIXELFORMAT_ARGB8888, SDL_PIXELFORMAT_ARGB8888,
SDL_TEXTUREACCESS_STREAMING, SDL_TEXTUREACCESS_STREAMING,
Modes.screen_width, Modes.screen_height); appData.screen_width, appData.screen_height);
if(Modes.fullscreen) { if(appData.fullscreen) {
//SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear"); // make the scaled rendering look smoother. //SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear"); // make the scaled rendering look smoother.
SDL_RenderSetLogicalSize(game.renderer, Modes.screen_width, Modes.screen_height); SDL_RenderSetLogicalSize(appData.renderer, appData.screen_width, appData.screen_height);
} }
game.mapFont = loadFont("font/TerminusTTF-4.46.0.ttf", 12 * Modes.screen_uiscale); appData.mapFont = loadFont("font/TerminusTTF-4.46.0.ttf", 12 * appData.screen_uiscale);
game.mapBoldFont = loadFont("font/TerminusTTF-Bold-4.46.0.ttf", 12 * Modes.screen_uiscale); appData.mapBoldFont = loadFont("font/TerminusTTF-Bold-4.46.0.ttf", 12 * appData.screen_uiscale);
game.listFont = loadFont("font/TerminusTTF-4.46.0.ttf", 12 * Modes.screen_uiscale); appData.listFont = loadFont("font/TerminusTTF-4.46.0.ttf", 12 * appData.screen_uiscale);
game.messageFont = loadFont("font/TerminusTTF-Bold-4.46.0.ttf", 12 * Modes.screen_uiscale); appData.messageFont = loadFont("font/TerminusTTF-Bold-4.46.0.ttf", 12 * appData.screen_uiscale);
game.labelFont = loadFont("font/TerminusTTF-Bold-4.46.0.ttf", 12 * Modes.screen_uiscale); appData.labelFont = loadFont("font/TerminusTTF-Bold-4.46.0.ttf", 12 * appData.screen_uiscale);
game.mapFontWidth = 5 * Modes.screen_uiscale; appData.mapFontWidth = 5 * appData.screen_uiscale;
game.mapFontHeight = 12 * Modes.screen_uiscale; appData.mapFontHeight = 12 * appData.screen_uiscale;
game.messageFontWidth = 6 * Modes.screen_uiscale; appData.messageFontWidth = 6 * appData.screen_uiscale;
game.messageFontHeight = 12 * Modes.screen_uiscale; appData.messageFontHeight = 12 * appData.screen_uiscale;
game.labelFontWidth = 6 * Modes.screen_uiscale; appData.labelFontWidth = 6 * appData.screen_uiscale;
game.labelFontHeight = 12 * Modes.screen_uiscale; appData.labelFontHeight = 12 * appData.screen_uiscale;
initMaps(); initMaps();
} }
void cleanup() { void cleanup() {
closeFont(game.mapFont); closeFont(appData.mapFont);
closeFont(game.mapBoldFont); closeFont(appData.mapBoldFont);
closeFont(game.messageFont); closeFont(appData.messageFont);
closeFont(game.labelFont); closeFont(appData.labelFont);
closeFont(game.listFont); closeFont(appData.listFont);
TTF_Quit(); TTF_Quit();

3
init.h
View file

@ -1,3 +0,0 @@
#include "structs.h"
extern Game game;

BIN
init.o

Binary file not shown.

43
input.c
View file

@ -1,33 +1,14 @@
#include "input.h" #include "structs.h"
#include "view1090.h" #include "view1090.h"
void getInput() void getInput()
{ {
#ifdef RPI
if(!digitalRead(27)) {
exit(0);
}
if(!digitalRead(22)) {
Modes.mapLogDist = !Modes.mapLogDist;
}
if(!digitalRead(23)) {
Modes.map = !Modes.map;
}
#endif
SDL_Event event; SDL_Event event;
/* Loop through waiting messages and process them */
while (SDL_PollEvent(&event)) while (SDL_PollEvent(&event))
{ {
switch (event.type) switch (event.type)
{ {
/* Closing the Window or pressing Escape will exit the program */
case SDL_QUIT: case SDL_QUIT:
exit(0); exit(0);
break; break;
@ -40,11 +21,11 @@ void getInput()
break; break;
case SDLK_l: case SDLK_l:
Modes.mapLogDist = !Modes.mapLogDist; appData.mapLogDist = !appData.mapLogDist;
break; break;
case SDLK_m: case SDLK_m:
Modes.map = !Modes.map; appData.showList = !appData.showList;
break; break;
default: default:
@ -55,11 +36,11 @@ void getInput()
case SDL_MOUSEWHEEL: case SDL_MOUSEWHEEL:
Modes.maxDist *= 1.0 + event.wheel.y / 10.0; appData.maxDist *= 1.0 + event.wheel.y / 10.0;
break; break;
case SDL_MULTIGESTURE: case SDL_MULTIGESTURE:
Modes.maxDist /=1.0 + 4.0*event.mgesture.dDist; appData.maxDist /=1.0 + 4.0*event.mgesture.dDist;
break; break;
case SDL_FINGERMOTION:; case SDL_FINGERMOTION:;
@ -68,18 +49,18 @@ void getInput()
// need to make lonlat to screen conversion class - this is just the inverse of the stuff in draw.c, without offsets // need to make lonlat to screen conversion class - this is just the inverse of the stuff in draw.c, without offsets
// //
double scale_factor = (Modes.screen_width > Modes.screen_height) ? Modes.screen_width : Modes.screen_height; double scale_factor = (appData.screen_width > appData.screen_height) ? appData.screen_width : appData.screen_height;
double dx = -1.0 * (0.75*(double)Modes.screen_width / (double)Modes.screen_height) * Modes.screen_width * event.tfinger.dx * Modes.maxDist / (0.95 * scale_factor * 0.5); double dx = -1.0 * (0.75*(double)appData.screen_width / (double)appData.screen_height) * appData.screen_width * event.tfinger.dx * appData.maxDist / (0.95 * scale_factor * 0.5);
double dy = 1.0 * Modes.screen_height * event.tfinger.dy * Modes.maxDist / (0.95 * scale_factor * 0.5); double dy = 1.0 * appData.screen_height * event.tfinger.dy * appData.maxDist / (0.95 * scale_factor * 0.5);
double outLat = dy * (1.0/6371.0) * (180.0f / M_PI); double outLat = dy * (1.0/6371.0) * (180.0f / M_PI);
double outLon = dx * (1.0/6371.0) * (180.0f / M_PI) / cos(((Modes.fUserLat)/2.0f) * M_PI / 180.0f); double outLon = dx * (1.0/6371.0) * (180.0f / M_PI) / cos(((appData.centerLat)/2.0f) * M_PI / 180.0f);
Modes.fUserLon += outLon; appData.centerLon += outLon;
Modes.fUserLat += outLat; appData.centerLat += outLat;
break; break;
} }
} }

View file

@ -1 +0,0 @@
#include "defs.h"

View file

@ -1 +1 @@
9b48800a24ee4c8a8e0c2a773765026724773f6f a9f8d1424252b1371bb410c58e63a5ec55a7fcb3

View file

@ -29,7 +29,6 @@
// //
#include "dump1090.h" #include "dump1090.h"
// //
// ============================= Utility functions ========================== // ============================= Utility functions ==========================
// //
@ -138,19 +137,9 @@ struct aircraft *interactiveCreateAircraft(struct modesMessage *mm) {
// Now initialise things that should not be 0/NULL to their defaults // Now initialise things that should not be 0/NULL to their defaults
a->addr = mm->addr; a->addr = mm->addr;
a->lat = a->lon = 0.0; a->lat = a->lon = 0.0;
a->created = 0;
a->oldIdx = 0;
memset(a->oldDx, 0, sizeof(a->oldDx));
memset(a->oldDy, 0, sizeof(a->oldDy));
memset(a->oldHeading, 0, sizeof(a->oldHeading));
memset(a->signalLevel, mm->signalLevel, 8); // First time, initialise everything memset(a->signalLevel, mm->signalLevel, 8); // First time, initialise everything
// to the first signal strength // to the first signal strength
memset(a->messageRate, 0, sizeof(a->messageRate));
// mm->msgtype 32 is used to represent Mode A/C. These values can never change, so // mm->msgtype 32 is used to represent Mode A/C. These values can never change, so
// set them once here during initialisation, and don't bother to set them every // set them once here during initialisation, and don't bother to set them every
// time this ModeA/C is received again in the future // time this ModeA/C is received again in the future
@ -278,8 +267,7 @@ struct aircraft *interactiveReceiveData(struct modesMessage *mm) {
a = interactiveFindAircraft(mm->addr); a = interactiveFindAircraft(mm->addr);
if (!a) { // If it's a currently unknown aircraft.... if (!a) { // If it's a currently unknown aircraft....
a = interactiveCreateAircraft(mm); // ., create a new record for it, a = interactiveCreateAircraft(mm); // ., create a new record for it,
a->prev_seen = time(NULL); a->next = Modes.aircrafts; // .. and put it at the head of the list
a->next = Modes.aircrafts; // .. and put it at the head of the list
Modes.aircrafts = a; Modes.aircrafts = a;
} else { } else {
/* If it is an already known aircraft, move it on head /* If it is an already known aircraft, move it on head
@ -298,23 +286,11 @@ struct aircraft *interactiveReceiveData(struct modesMessage *mm) {
a->next = Modes.aircrafts; a->next = Modes.aircrafts;
Modes.aircrafts = a; Modes.aircrafts = a;
} }
a->prev_seen = a->seen;
}
//strip trailing spaces
for(int i = 0; i<8; i++) {
a->flight[i] = (a->flight[i] == 32) ? 0 : a->flight[i];
} }
a->signalLevel[a->messages & 7] = mm->signalLevel;// replace the 8th oldest signal strength a->signalLevel[a->messages & 7] = mm->signalLevel;// replace the 8th oldest signal strength
a->seen = time(NULL); a->seen = time(NULL);
a->timestamp = mm->timestampMsg; a->timestamp = mm->timestampMsg;
if((a->seen - a->prev_seen) > 0) {
a->messageRate[a->messages & 7] = 1.0 / (double)(a->seen - a->prev_seen);
}
a->messages++; a->messages++;
// If a (new) CALLSIGN has been received, copy it to the aircraft structure // If a (new) CALLSIGN has been received, copy it to the aircraft structure
@ -396,26 +372,6 @@ struct aircraft *interactiveReceiveData(struct modesMessage *mm) {
mm->bFlags |= MODES_ACFLAGS_LATLON_VALID; mm->bFlags |= MODES_ACFLAGS_LATLON_VALID;
mm->fLat = a->lat; mm->fLat = a->lat;
mm->fLon = a->lon; mm->fLon = a->lon;
// double dLon = a->lon;// - Modes.fUserLon;
// double dLat = a->lat;// - Modes.fUserLat;
// a->dx = 6371.0 * dLon * M_PI / 180.0f * cos(((a->lat + Modes.fUserLat)/2.0f) * M_PI / 180.0f);
// a->dy = 6371.0 * dLat * M_PI / 180.0f;
a->dx = a->lon;
a->dy = a->lat;
if(time(NULL) - a->oldSeen[a->oldIdx] > MODES_INTERACTIVE_TRAIL_TTL_STEP) {
a->oldIdx = (a->oldIdx+1) % 32;
a->oldDx[a->oldIdx] = a->dx;
a->oldDy[a->oldIdx] = a->dy;
a->oldHeading[a->oldIdx] = a->track;
a->oldSeen[a->oldIdx] = a->seen;
}
} }
} }
@ -480,7 +436,7 @@ void interactiveShowData(void) {
if (Modes.interactive_rtl1090 == 0) { if (Modes.interactive_rtl1090 == 0) {
printf ( printf (
"Hex Mode Sqwk Flight Alt Spd Hdg dx(km) dy(km) Sig Msgs Ti%c\n", progress); "Hex Mode Sqwk Flight Alt Spd Hdg Lat Long Sig Msgs Ti%c\n", progress);
} else { } else {
printf ( printf (
"Hex Flight Alt V/S GS TT SSR G*456^ Msgs Seen %c\n", progress); "Hex Flight Alt V/S GS TT SSR G*456^ Msgs Seen %c\n", progress);
@ -548,10 +504,8 @@ void interactiveShowData(void) {
if (flags & MODEAC_MSG_MODEC_HIT) {strMode[3] = 'c';} if (flags & MODEAC_MSG_MODEC_HIT) {strMode[3] = 'c';}
if (a->bFlags & MODES_ACFLAGS_LATLON_VALID) { if (a->bFlags & MODES_ACFLAGS_LATLON_VALID) {
snprintf(strLat, 8,"%7.03f", a->lat);
snprintf(strLat, 8,"%7.03f", a->dx); snprintf(strLon, 9,"%8.03f", a->lon);
snprintf(strLon, 9,"%8.03f", a->dy);
} }
if (a->bFlags & MODES_ACFLAGS_AOG) { if (a->bFlags & MODES_ACFLAGS_AOG) {

Binary file not shown.

46
list.c
View file

@ -13,24 +13,14 @@ void drawList(int top) {
progress = spinner[time(NULL)%4]; progress = spinner[time(NULL)%4];
drawStringBG(" Flight Alt(m) km/h D(km) H S ", 0, top, game.mapBoldFont, black, (SDL_Color){255,255,255,64}); drawStringBG(" Flight Alt(m) km/h D(km) H S ", 0, top, appData.mapBoldFont, black, (SDL_Color){255,255,255,64});
top = top + game.mapFontHeight; top = top + appData.mapFontHeight;
// int xstride = 10;
// for(int i = 0; i < 320 / xstride; i++) {
// vlineRGBA (game.screen, i*xstride, 0, SCREEN_HEIGHT, 127, 127, 127, SDL_ALPHA_OPAQUE);
// }
// int ystride = 20;
// for(int i = 0; i < 240 / ystride; i++) {
// hlineRGBA (game.screen, 0, SCREEN_WIDTH, i * ystride, 127, 127, 127, SDL_ALPHA_OPAQUE);
// }
int numNoDir = 0; int numNoDir = 0;
while(a) { while(a) {
if(top > Modes.screen_height) { if(top > appData.screen_height) {
return; return;
} }
@ -102,20 +92,20 @@ void drawList(int top) {
if (a->bFlags & MODES_ACFLAGS_LATLON_VALID) { if (a->bFlags & MODES_ACFLAGS_LATLON_VALID) {
if(fabs(a->dx) < .01 && fabs(a->dy) > fabs(a->dx)) { if(fabs(a->lon) < .01 && fabs(a->lat) > fabs(a->lon)) {
cLon = ' '; cLon = ' ';
} else { } else {
if(a->dx < 0) { if(a->lon < 0) {
cLon = 'W'; cLon = 'W';
} else { } else {
cLon = 'E'; cLon = 'E';
} }
} }
if(fabs(a->dy) < .01 && fabs(a->dx) > fabs(a->dy)) { if(fabs(a->lat) < .01 && fabs(a->lon) > fabs(a->lat)) {
cLat = ' '; cLat = ' ';
} else { } else {
if(a->dy < 0) { if(a->lat < 0) {
cLat = 'S'; cLat = 'S';
} else { } else {
cLat = 'N'; cLat = 'N';
@ -124,26 +114,28 @@ void drawList(int top) {
snprintf(strDir,3,"%c%c",cLat,cLon); snprintf(strDir,3,"%c%c",cLat,cLon);
d = sqrt(a->dx * a->dx + a->dy * a->dy); //distance is borked during refactor
snprintf(strD, 5,"%4.01f", d); //d = sqrt(a->dx * a->dx + a->dy * a->dy);
//snprintf(strD, 5,"%4.01f", d);
if ((now - a->seen) > 30 ) { if ((now - a->seen) > 30 ) {
drawString(a->flight, 0, top, game.listFont, (SDL_Color){96,96,96,255}); drawString(a->flight, 0, top, appData.listFont, (SDL_Color){96,96,96,255});
} else { } else {
drawString(a->flight, 10, top, game.listFont, pink); drawString(a->flight, 10, top, appData.listFont, pink);
drawString(strFl, 90, top, game.listFont, orange); drawString(strFl, 90, top, appData.listFont, orange);
drawString(strGs, 160, top, game.listFont, green); drawString(strGs, 160, top, appData.listFont, green);
drawString(strD, 210, top, game.listFont, blue); drawString(strD, 210, top, appData.listFont, blue);
drawString(strDir, 270, top, game.listFont, yellow); drawString(strDir, 270, top, appData.listFont, yellow);
// drawString(strS, 290, (count + 1) * 20, game.listFont, (SDL_Color){255,9,96,255}); // drawString(strS, 290, (count + 1) * 20, appData.listFont, (SDL_Color){255,9,96,255});
// printf("\x1B[1;31m%-8s\x1B[1;32m%5s \x1B[1;33m%4s \x1B[1;34m%5s \x1B[1;36m%c%c \x1B[1;35m%d", // printf("\x1B[1;31m%-8s\x1B[1;32m%5s \x1B[1;33m%4s \x1B[1;34m%5s \x1B[1;36m%c%c \x1B[1;35m%d",
// a->flight, // a->flight,
@ -153,7 +145,7 @@ void drawList(int top) {
// cLat, cLon, // cLat, cLon,
// (int)((float)signalAverage/25.0f)); // (int)((float)signalAverage/25.0f));
} }
top = top + game.mapFontHeight; top = top + appData.mapFontHeight;
count++; count++;
} else { } else {
numNoDir++; numNoDir++;

BIN
list.o

Binary file not shown.

View file

@ -1 +1 @@
4d8d502c9a227a17f0fbd09a492c86eb5f1545cb c95610367de3a9e8503644016da9760739f94993

546
maps.c
View file

@ -1,546 +0,0 @@
#include "dump1090.h"
#include "structs.h"
#include "parula.h"
#include "magma.h"
#include "monokai.h"
#include "SDL2/SDL2_gfxPrimitives.h"
#define CENTEROFFSET .375
static uint64_t mstime(void) {
struct timeval tv;
uint64_t mst;
gettimeofday(&tv, NULL);
mst = ((uint64_t)tv.tv_sec)*1000;
mst += tv.tv_usec/1000;
return mst;
}
void CROSSVP(double *v, double *u, double *w)
{
v[0] = u[1]*w[2] - u[2]*(w)[1];
v[1] = u[2]*w[0] - u[0]*(w)[2];
v[2] = u[0]*w[1] - u[1]*(w)[0];
}
SDL_Color setColor(uint8_t r, uint8_t g, uint8_t b) {
SDL_Color out;
out.r = r;
out.g = g;
out.b = b;
return out;
}
SDL_Color signalToColor(int signal) {
SDL_Color planeColor;
if(signal > 127) {
signal = 127;
}
if(signal < 0) {
planeColor = setColor(96, 96, 96);
} else {
if(MAGMA) {
planeColor = setColor(magma[signal][0], magma[signal][1], magma[signal][2]);
} else {
planeColor = setColor(parula[signal][0], parula[signal][1], parula[signal][2]);
}
}
return planeColor;
}
int screenDist(double d) {
double scale_factor = (Modes.screen_width > Modes.screen_height) ? Modes.screen_width : Modes.screen_height;
if(Modes.mapLogDist) {
return round(0.95 * scale_factor * 0.5 * log(1.0+fabs(d)) / log(1.0+Modes.maxDist));
} else {
return round(0.95 * scale_factor * 0.5 * fabs(d) / Modes.maxDist);
}
}
void pxFromLonLat(double *dx, double *dy, double lon, double lat) {
if(!lon || !lat) {
*dx = 0;
*dy = 0;
return;
}
*dx = 6371.0 * (lon - Modes.fUserLon) * M_PI / 180.0f * cos(((lat + Modes.fUserLat)/2.0f) * M_PI / 180.0f);
*dy = 6371.0 * (lat - Modes.fUserLat) * M_PI / 180.0f;
}
void screenCoords(int *outX, int *outY, double dx, double dy) {
*outX = (Modes.screen_width>>1) + ((dx>0) ? 1 : -1) * screenDist(dx);
*outY = (Modes.screen_height * CENTEROFFSET) + ((dy>0) ? -1 : 1) * screenDist(dy);
}
int outOfBounds(int x, int y) {
if(x < 0 || x >= Modes.screen_width || y < 0 || y >= Modes.screen_height ) {
return 1;
} else {
return 0;
}
}
void drawPlaneOffMap(int x, int y, int *returnx, int *returny, SDL_Color planeColor) {
double arrowWidth = 6.0 * Modes.screen_uiscale;
float inx = x - (Modes.screen_width>>1);
float iny = y - Modes.screen_height * CENTEROFFSET;
float outx, outy;
outx = inx;
outy = iny;
if(abs(inx) > abs(y - (Modes.screen_height>>1)) * (float)(Modes.screen_width>>1) / (float)(Modes.screen_height * CENTEROFFSET)) { //left / right quadrants
outx = (Modes.screen_width>>1) * ((inx > 0) ? 1.0 : -1.0);
outy = (outx) * iny / (inx);
} else { // up / down quadrants
outy = Modes.screen_height * ((iny > 0) ? 1.0-CENTEROFFSET : -CENTEROFFSET );
outx = (outy) * inx / (iny);
}
// circleRGBA (game.renderer,(Modes.screen_width>>1) + outx, Modes.screen_height * CENTEROFFSET + outy,50,planeColor.r,planeColor.g,planeColor.b,SDL_ALPHA_OPAQUE);
// thickLineRGBA(game.renderer,Modes.screen_width>>1,Modes.screen_height * CENTEROFFSET, (Modes.screen_width>>1) + outx, Modes.screen_height * CENTEROFFSET + outy,arrowWidth,planeColor.r,planeColor.g,planeColor.b,SDL_ALPHA_OPAQUE);
double inmag = sqrt(inx *inx + iny*iny);
double vec[3];
vec[0] = inx / inmag;
vec[1] = iny /inmag;
vec[2] = 0;
double up[] = {0,0,1};
double out[3];
CROSSVP(out,vec,up);
int x1, x2, x3, y1, y2, y3;
// arrow 1
x1 = (Modes.screen_width>>1) + outx - 2.0 * arrowWidth * vec[0] + round(-arrowWidth*out[0]);
y1 = (Modes.screen_height * CENTEROFFSET) + outy - 2.0 * arrowWidth * vec[1] + round(-arrowWidth*out[1]);
x2 = (Modes.screen_width>>1) + outx - 2.0 * arrowWidth * vec[0] + round(arrowWidth*out[0]);
y2 = (Modes.screen_height * CENTEROFFSET) + outy - 2.0 * arrowWidth * vec[1] + round(arrowWidth*out[1]);
x3 = (Modes.screen_width>>1) + outx - arrowWidth * vec[0];
y3 = (Modes.screen_height * CENTEROFFSET) + outy - arrowWidth * vec[1];
filledTrigonRGBA(game.renderer, x1, y1, x2, y2, x3, y3, planeColor.r,planeColor.g,planeColor.b,SDL_ALPHA_OPAQUE);
// arrow 2
x1 = (Modes.screen_width>>1) + outx - 3.0 * arrowWidth * vec[0] + round(-arrowWidth*out[0]);
y1 = (Modes.screen_height * CENTEROFFSET) + outy - 3.0 * arrowWidth * vec[1] + round(-arrowWidth*out[1]);
x2 = (Modes.screen_width>>1) + outx - 3.0 * arrowWidth * vec[0] + round(arrowWidth*out[0]);
y2 = (Modes.screen_height * CENTEROFFSET) + outy - 3.0 * arrowWidth * vec[1] + round(arrowWidth*out[1]);
x3 = (Modes.screen_width>>1) + outx - 2.0 * arrowWidth * vec[0];
y3 = (Modes.screen_height * CENTEROFFSET) + outy - 2.0 * arrowWidth * vec[1];
filledTrigonRGBA(game.renderer, x1, y1, x2, y2, x3, y3, planeColor.r,planeColor.g,planeColor.b,SDL_ALPHA_OPAQUE);
*returnx = x3;
*returny = y3;
}
void drawPlaneHeading(int x, int y, double heading, SDL_Color planeColor)
{
double body = 8.0 * Modes.screen_uiscale;
double wing = 6.0 * Modes.screen_uiscale;
double tail = 3.0 * Modes.screen_uiscale;
double bodyWidth = 2.0 * Modes.screen_uiscale;
double vec[3];
vec[0] = sin(heading * M_PI / 180);
vec[1] = -cos(heading * M_PI / 180);
vec[2] = 0;
double up[] = {0,0,1};
double out[3];
CROSSVP(out,vec,up);
int x1, x2, y1, y2;
// tempCenter
// circleRGBA(game.renderer, x, y, 10, 255, 0, 0, 255);
//body
x1 = x + round(-body*vec[0]);
y1 = y + round(-body*vec[1]);
x2 = x + round(body*vec[0]);
y2 = y + round(body*vec[1]);
if(AA) {
aalineRGBA(game.renderer,x1,y1,x2,y2,planeColor.r,planeColor.g,planeColor.b,SDL_ALPHA_OPAQUE);
aatrigonRGBA(game.renderer, x + round(-wing*.35*out[0]), y + round(-wing*.35*out[1]), x + round(wing*.35*out[0]), y + round(wing*.35*out[1]), x1, y1,planeColor.r,planeColor.g,planeColor.b,SDL_ALPHA_OPAQUE);
aacircleRGBA(game.renderer, x2,y2,1,planeColor.r,planeColor.g,planeColor.b,SDL_ALPHA_OPAQUE);
} else {
thickLineRGBA(game.renderer,x,y,x2,y2,bodyWidth,planeColor.r,planeColor.g,planeColor.b,SDL_ALPHA_OPAQUE);
filledTrigonRGBA(game.renderer, x + round(-wing*.35*out[0]), y + round(-wing*.35*out[1]), x + round(wing*.35*out[0]), y + round(wing*.35*out[1]), x1, y1,planeColor.r,planeColor.g,planeColor.b,SDL_ALPHA_OPAQUE);
filledCircleRGBA(game.renderer, x2,y2,Modes.screen_uiscale,planeColor.r,planeColor.g,planeColor.b,SDL_ALPHA_OPAQUE);
}
//wing
x1 = x + round(-wing*out[0]);
y1 = y + round(-wing*out[1]);
x2 = x + round(wing*out[0]);
y2 = y + round(wing*out[1]);
if(AA) {
aatrigonRGBA(game.renderer, x1, y1, x2, y2, x+round(body*.35*vec[0]), y+round(body*.35*vec[1]),planeColor.r,planeColor.g,planeColor.b,SDL_ALPHA_OPAQUE);
} else {
filledTrigonRGBA(game.renderer, x1, y1, x2, y2, x+round(body*.35*vec[0]), y+round(body*.35*vec[1]),planeColor.r,planeColor.g,planeColor.b,SDL_ALPHA_OPAQUE);
}
//tail
x1 = x + round(-body*.75*vec[0]) + round(-tail*out[0]);
y1 = y + round(-body*.75*vec[1]) + round(-tail*out[1]);
x2 = x + round(-body*.75*vec[0]) + round(tail*out[0]);
y2 = y + round(-body*.75*vec[1]) + round(tail*out[1]);
if(AA) {
aatrigonRGBA (game.renderer, x1, y1, x2, y2, x+round(-body*.5*vec[0]), y+round(-body*.5*vec[1]),planeColor.r,planeColor.g,planeColor.b,SDL_ALPHA_OPAQUE);
} else {
filledTrigonRGBA (game.renderer, x1, y1, x2, y2, x+round(-body*.5*vec[0]), y+round(-body*.5*vec[1]),planeColor.r,planeColor.g,planeColor.b,SDL_ALPHA_OPAQUE);
}
}
void drawPlane(int x, int y, SDL_Color planeColor)
{
int length = 3.0;
rectangleRGBA (game.renderer, x - length, y - length, x+length, y + length, planeColor.r, planeColor.g, planeColor.b, SDL_ALPHA_OPAQUE);
}
void drawTrail(double *oldDx, double *oldDy, double *oldHeading, time_t * oldSeen, int idx) {
int currentIdx, prevIdx;
int currentX, currentY, prevX, prevY;
time_t now = time(NULL);
for(int i=0; i < (MODES_INTERACTIVE_TRAIL_LENGTH - 1); i++) {
currentIdx = (idx - i) % MODES_INTERACTIVE_TRAIL_LENGTH;
currentIdx = currentIdx < 0 ? currentIdx + MODES_INTERACTIVE_TRAIL_LENGTH : currentIdx;
prevIdx = (idx - (i + 1)) % MODES_INTERACTIVE_TRAIL_LENGTH;
prevIdx = prevIdx < 0 ? prevIdx + MODES_INTERACTIVE_TRAIL_LENGTH : prevIdx;
if(oldDx[currentIdx] == 0 || oldDy[currentIdx] == 0) {
continue;
}
if(oldDx[prevIdx] == 0 || oldDy[prevIdx] == 0) {
continue;
}
double dx, dy;
pxFromLonLat(&dx, &dy, oldDx[currentIdx], oldDy[currentIdx]);
screenCoords(&currentX, &currentY, dx, dy);
pxFromLonLat(&dx, &dy, oldDx[prevIdx], oldDy[prevIdx]);
screenCoords(&prevX, &prevY, dx, dy);
if(outOfBounds(currentX,currentY)) {
return;
}
if(outOfBounds(prevX,prevY)) {
return;
}
double age = pow(1.0 - (double)(now - oldSeen[currentIdx]) / MODES_INTERACTIVE_TRAIL_TTL, 2.2);
if(age < 0) {
age = 0;
}
uint8_t colorVal = (uint8_t)floor(255.0 * age);
if(AA) {
aalineRGBA(game.renderer, prevX, prevY, currentX, currentY,colorVal, colorVal, colorVal, SDL_ALPHA_OPAQUE);
} else {
//thickLineRGBA(game.renderer, prevX, prevY, currentX, currentY, 2, colorVal, colorVal, colorVal, SDL_ALPHA_OPAQUE);
thickLineRGBA(game.renderer, prevX, prevY, currentX, currentY, 4 * Modes.screen_uiscale, colorVal, colorVal, colorVal, 127);
}
//tick marks
double vec[3];
vec[0] = sin(oldHeading[currentIdx] * M_PI / 180);
vec[1] = -cos(oldHeading[currentIdx] * M_PI / 180);
vec[2] = 0;
double up[] = {0,0,1};
double out[3];
CROSSVP(out,vec,up);
int x1, y1, x2, y2;
int cross_size = 8 * Modes.screen_uiscale;
//forward cross
x1 = currentX + round(-cross_size*vec[0]);
y1 = currentY + round(-cross_size*vec[1]);
x2 = currentX + round(cross_size*vec[0]);
y2 = currentY + round(cross_size*vec[1]);
lineRGBA(game.renderer,x1,y1,x2,y2,colorVal,colorVal,colorVal,127);
//side cross
x1 = currentX + round(-cross_size*out[0]);
y1 = currentY + round(-cross_size*out[1]);
x2 = currentX + round(cross_size*out[0]);
y2 = currentY + round(cross_size*out[1]);
lineRGBA(game.renderer,x1,y1,x2,y2,colorVal,colorVal,colorVal,127);
}
}
void drawGrid()
{
int p1km = screenDist(1.0);
int p10km = screenDist(10.0);
int p100km = screenDist(100.0);
//hlineRGBA (game.renderer, (Modes.screen_width>>1) - p100km, (Modes.screen_width>>1) + p100km, Modes.screen_height * CENTEROFFSET, grey.r, grey.g, grey.b, SDL_ALPHA_OPAQUE);
//vlineRGBA (game.renderer, Modes.screen_width>>1, (Modes.screen_height * CENTEROFFSET) - p100km, (Modes.screen_height * CENTEROFFSET) + p100km, grey.r, grey.g, grey.b, SDL_ALPHA_OPAQUE);
if(AA) {
aacircleRGBA (game.renderer, Modes.screen_width>>1, Modes.screen_height>>1, p1km, pink.r, pink.g, pink.b, 255);
aacircleRGBA (game.renderer, Modes.screen_width>>1, Modes.screen_height>>1, p10km, pink.r, pink.g, pink.b, 195);
aacircleRGBA (game.renderer, Modes.screen_width>>1, Modes.screen_height>>1, p100km, pink.r, pink.g, pink.b, 127);
} else {
circleRGBA (game.renderer, Modes.screen_width>>1, Modes.screen_height * CENTEROFFSET, p1km, pink.r, pink.g, pink.b, 255);
circleRGBA (game.renderer, Modes.screen_width>>1, Modes.screen_height * CENTEROFFSET, p10km, pink.r, pink.g, pink.b, 195);
circleRGBA (game.renderer, Modes.screen_width>>1, Modes.screen_height * CENTEROFFSET, p100km, pink.r, pink.g, pink.b, 127);
}
drawString("1km", (Modes.screen_width>>1) + (0.707 * p1km) + 5, (Modes.screen_height * CENTEROFFSET) + (0.707 * p1km) + 5, game.mapFont, pink);
drawString("10km", (Modes.screen_width>>1) + (0.707 * p10km) + 5, (Modes.screen_height * CENTEROFFSET) + (0.707 * p10km) + 5, game.mapFont, pink);
drawString("100km", (Modes.screen_width>>1) + (0.707 * p100km) + 5, (Modes.screen_height * CENTEROFFSET) + (0.707 * p100km) + 5, game.mapFont, pink);
}
void drawGeography() {
int x1, y1, x2, y2;
for(int i=1; i<mapPoints_count/2; i++) {
double dx, dy;
pxFromLonLat(&dx, &dy, mapPoints_relative[(i - 1) * 2], mapPoints_relative[(i - 1) * 2 + 1]);
if(!dx || !dy) {
continue;
}
screenCoords(&x1, &y1, dx, dy);
if(outOfBounds(x1,y1)) {
continue;
}
double d1 = sqrt(dx * dx + dy * dy);
pxFromLonLat(&dx, &dy, mapPoints_relative[i * 2], mapPoints_relative[i * 2 + 1]);
if(!dx || !dy) {
continue;
}
screenCoords(&x2, &y2, dx, dy);
if(outOfBounds(x2,y2)) {
continue;
}
double d2 = sqrt(dx* dx + dy * dy);
//double alpha = 255.0 * (d1+d2) / 2;
//alpha = 255.0 - alpha / Modes.maxDist;
double alpha = 1.0 - (d1+d2) / (2 * Modes.maxDist);
alpha = (alpha < 0) ? 0 : alpha;
if(AA) {
aalineRGBA(game.renderer, x1, y1, x2, y2,purple.r,purple.g,purple.b, (alpha < 0) ? 0 : (uint8_t) alpha);
} else {
//thickLineRGBA(game.renderer, x1, y1, x2, y2, Modes.screen_uiscale, purple.r,purple.g,purple.b, (alpha < 0) ? 0 : (uint8_t) alpha);
//thickLineRGBA(game.renderer, x1, y1, x2, y2, Modes.screen_uiscale, alpha * purple.r + (1.0-alpha) * blue.r, alpha * purple.g + (1.0-alpha) * blue.g, alpha * purple.b + (1.0-alpha) * blue.b, 255 * alpha);
lineRGBA(game.renderer, x1, y1, x2, y2, alpha * purple.r + (1.0-alpha) * blue.r, alpha * purple.g + (1.0-alpha) * blue.g, alpha * purple.b + (1.0-alpha) * blue.b, 255 * alpha);
}
}
// int *screen_x = (int *) malloc(mapPoints_count * sizeof(int));
// int *screen_y = (int *) malloc(mapPoints_count * sizeof(int));
// initializeMap(screen_x, screen_y);
// filledPolygonRGBA(game.renderer,screen_x, screen_y, mapPoints_count, 100, 100, 100, 255);
}
void drawMap(void) {
struct aircraft *a = Modes.aircrafts;
time_t now = time(NULL);
drawGeography();
drawGrid();
while(a) {
if ((now - a->seen) < Modes.interactive_display_ttl) {
if (a->bFlags & MODES_ACFLAGS_LATLON_VALID) {
unsigned char * pSig = a->signalLevel;
unsigned int signalAverage = (pSig[0] + pSig[1] + pSig[2] + pSig[3] +
pSig[4] + pSig[5] + pSig[6] + pSig[7] + 3) >> 3;
drawTrail(a->oldDx, a->oldDy, a->oldHeading, a->oldSeen, a->oldIdx);
int colorIdx;
if((int)(now - a->seen) > MODES_INTERACTIVE_DISPLAY_ACTIVE) {
colorIdx = -1;
} else {
colorIdx = signalAverage;
}
SDL_Color planeColor = signalToColor(colorIdx);
int x, y;
//screenCoords(&x, &y, a->dx, a->dy);
double dx, dy;
pxFromLonLat(&dx, &dy, a->lon, a->lat);
screenCoords(&x, &y, dx, dy);
if(outOfBounds(x,y)) {
int outx, outy;
drawPlaneOffMap(x, y, &outx, &outy, planeColor);
drawStringBG(a->flight, outx + 5, outy + game.mapFontHeight, game.mapBoldFont, white, black);
char alt[10] = " ";
snprintf(alt,10,"%dm", a->altitude);
drawStringBG(alt, outx + 5, outy + 2*game.mapFontHeight, game.mapFont, grey, black);
char speed[10] = " ";
snprintf(speed,10,"%dkm/h", a->speed);
drawStringBG(speed, outx + 5, outy + 3*game.mapFontHeight, game.mapFont, grey, black);
// continue;
}
if(a->created == 0) {
a->created = mstime();
}
double age_ms = (double)(mstime() - a->created);
if(age_ms < 500) {
circleRGBA(game.renderer, x, y, 500 - age_ms, 255,255, 255, (uint8_t)(255.0 * age_ms / 500.0));
} else {
if(MODES_ACFLAGS_HEADING_VALID) {
drawPlaneHeading(x, y,a->track, planeColor);
//char flight[11] = " ";
//snprintf(flight,11," %s ", a->flight);
//drawStringBG(flight, x, y + game.mapFontHeight, game.mapBoldFont, black, planeColor);
drawStringBG(a->flight, x + 5, y + game.mapFontHeight, game.mapBoldFont, white, black);
char alt[10] = " ";
snprintf(alt,10,"%dm", a->altitude);
drawStringBG(alt, x + 5, y + 2*game.mapFontHeight, game.mapFont, grey, black);
char speed[10] = " ";
snprintf(speed,10,"%dkm/h", a->speed);
drawStringBG(speed, x + 5, y + 3*game.mapFontHeight, game.mapFont, grey, black);
lineRGBA(game.renderer, x, y, x, y + 4*game.mapFontHeight, grey.r, grey.g, grey.b, SDL_ALPHA_OPAQUE);
} else {
drawPlane(x, y, planeColor);
}
}
}
}
a = a->next;
}
// int mx, my;
// SDL_GetMouseState(&mx, &my);
// mx /= Modes.screen_upscale;
// my /= Modes.screen_upscale;
// char mousepos[10] = " ";
// snprintf(mousepos,10,"%d %d", mx, my);
// int outx, outy;
// drawPlaneOffMap(mx, my, &outx, &outy, white);
// char linepos[10] = " ";
// snprintf(linepos,10,"%2.2f %2.2f", outx, outy);
// int shiftedx, shiftedy;
// if(outx > (Modes.screen_width>>1)) {
// shiftedx = outx - 5 * game.mapFontHeight;
// } else {
// shiftedx = outx + game.mapFontHeight;
// }
// if(outy > (Modes.screen_height>>1)) {
// shiftedy = outy - game.mapFontHeight;
// } else {
// shiftedy = outy + game.mapFontHeight;
// }
// drawStringBG(linepos, shiftedx, shiftedy, game.mapBoldFont, white, black);
// // drawPlane(mx, my, signalToColor(100));
// drawStringBG(mousepos, mx + 5, my - game.mapFontHeight, game.mapBoldFont, white, black);
}
// void initializeMap(short *screen_x, short *screen_y) {
// int out_x, out_y;
// for(int i=0; i<mapPoints_count; i++) {
// screenCoords(&out_x, &out_y, (double) mapPoints_x[i], (double) -mapPoints_y[i]);
// // if(out_x < 0) {
// // out_x = 0;
// // }
// // if(out_y < 0) {
// // out_y = 0;
// // }
// // if(out_x >= Modes.screen_width) {
// // out_x = Modes.screen_width;
// // }
// // if(out_y >= Modes.screen_height) {
// // out_y = Modes.screen_height;
// // }
// screen_x[i] = out_x;
// screen_y[i] = out_y;
// }
// }

View file

@ -1 +0,0 @@
2ace4751610e844ddd57046a819bd5e045a690f3

BIN
mode_ac.o

Binary file not shown.

View file

@ -1 +1 @@
a3e48b2319025f5869b2710bf017dfcb96c1fb89 7d25253c93eb99094372df3b61630599ce0cb4ff

BIN
monokai.o

Binary file not shown.

View file

@ -1 +1 @@
bdaa5132f81b7d6b55135413ab297b03f4791e00 22b5fc5c241eb98e511019d0ffa249f80ba7a933

BIN
parula.o

Binary file not shown.

102
planeObj.c Normal file
View file

@ -0,0 +1,102 @@
#include "structs.h"
#include "dump1090.h"
struct planeObj *findPlaneObj(uint32_t addr) {
struct planeObj *p = planes;
while(p) {
if (p->addr == addr) return (p);
p = p->next;
}
return (NULL);
}
struct planeObj *createPlaneObj(struct aircraft *a) {
struct planeObj *p = (struct planeObj *) malloc(sizeof(*p));
memset(p, 0, sizeof(*p));
p->addr = a->addr;
p->created = 0;
p->oldIdx = 0;
memset(p->oldLon, 0, sizeof(p->oldLon));
memset(p->oldLat, 0, sizeof(p->oldLat));
memset(p->oldHeading, 0, sizeof(p->oldHeading));
memset(p->messageRate, 0, sizeof(p->messageRate));
return (p);
}
void updatePlanes() {
struct aircraft *a = Modes.aircrafts;
struct planeObj *p = planes;
while(p) {
p->live = 0;
p = p->next;
}
while(a) {
p = findPlaneObj(a->addr);
if (!p) {
p = createPlaneObj(a);
p->next = planes;
planes = p;
}
p->live = 1;
if(p->seen == a->seen) {
a = a->next;
continue;
}
memcpy(p->flight, a->flight, sizeof(p->flight));
memcpy(p->signalLevel, a->signalLevel, sizeof(p->signalLevel));
p->altitude = a->altitude;
p->speed = a->speed;
p->track = a->track;
p->vert_rate = a->vert_rate;
p->seen = a->seen;
p->lon = a->lon;
p->lat = a->lat;
if(time(NULL) - p->oldSeen[p->oldIdx] > TRAIL_TTL_STEP) {
p->oldIdx = (p->oldIdx+1) % 32;
p->oldLon[p->oldIdx] = p->lon;
p->oldLat[p->oldIdx] = p->lat;
p->oldHeading[p->oldIdx] = p->track;
p->oldSeen[p->oldIdx] = p->seen;
}
a = a->next;
}
p = planes;
struct planeObj *prev = NULL;
while(p) {
if(!p->live) {
if (!prev) {
planes = p->next;
free(p);
p = planes;
} else {
prev->next = p->next;
free(p);
p = prev->next;
}
} else {
prev = p;
p = p->next;
}
}
}

BIN
planeObj.o Normal file

Binary file not shown.

116
status.c
View file

@ -7,7 +7,7 @@
#define PAD 5 #define PAD 5
void updateStatus() { void updateStatus() {
struct aircraft *a = Modes.aircrafts; // struct aircraft *a = Modes.aircrafts;
int numVisiblePlanes = 0; int numVisiblePlanes = 0;
double maxDist = 0; double maxDist = 0;
@ -15,8 +15,7 @@ void updateStatus() {
double sigAccumulate = 0.0; double sigAccumulate = 0.0;
double msgRateAccumulate = 0.0; double msgRateAccumulate = 0.0;
Status.closeCall = NULL; /*
while(a) { while(a) {
int flags = a->modeACflags; int flags = a->modeACflags;
int msgs = a->messages; int msgs = a->messages;
@ -35,7 +34,7 @@ void updateStatus() {
if (a->bFlags & MODES_ACFLAGS_LATLON_VALID) { if (a->bFlags & MODES_ACFLAGS_LATLON_VALID) {
double d = sqrt(a->dx * a->dx + a->dy * a->dy); double d = sqrt(a->dx * a->dx + a->dy * a->dy);
if(d < Modes.maxDist) { if(d < appData.maxDist) {
if(d > maxDist) { if(d > maxDist) {
maxDist = d; maxDist = d;
} }
@ -56,6 +55,39 @@ void updateStatus() {
a = a->next; a = a->next;
} }
*/
struct planeObj *p = planes;
while(p) {
unsigned char * pSig = p->signalLevel;
unsigned int signalAverage = (pSig[0] + pSig[1] + pSig[2] + pSig[3] +
pSig[4] + pSig[5] + pSig[6] + pSig[7]);
sigAccumulate += signalAverage;
//distance measurements got borked during refactor - need to redo here
/*
if (p->lon && p->lat) {
double d = sqrt(p->dx * a->dx + a->dy * a->dy);
if(d < appData.maxDist) {
if(d > maxDist) {
maxDist = d;
}
numVisiblePlanes++;
}
}
*/
totalCount++;
msgRateAccumulate += (p->messageRate[0] + p->messageRate[1] + p->messageRate[2] + p->messageRate[3] +
p->messageRate[4] + p->messageRate[5] + p->messageRate[6] + p->messageRate[7]);
p = p->next;
}
Status.msgRate = msgRateAccumulate; Status.msgRate = msgRateAccumulate;
Status.avgSig = sigAccumulate / (double) totalCount; Status.avgSig = sigAccumulate / (double) totalCount;
@ -65,48 +97,48 @@ void updateStatus() {
} }
void drawStatusBox(int *left, int *top, char *label, char *message, SDL_Color color) { void drawStatusBox(int *left, int *top, char *label, char *message, SDL_Color color) {
//int labelWidth = ((strlen(label) > 0 ) ? 1.5 : 0) * game.labelFont; //int labelWidth = ((strlen(label) > 0 ) ? 1.5 : 0) * appData.labelFont;
int labelWidth = (strlen(label) + ((strlen(label) > 0 ) ? 1 : 0)) * game.labelFontWidth; int labelWidth = (strlen(label) + ((strlen(label) > 0 ) ? 1 : 0)) * appData.labelFontWidth;
int messageWidth = (strlen(message) + ((strlen(message) > 0 ) ? 1 : 0)) * game.messageFontWidth; int messageWidth = (strlen(message) + ((strlen(message) > 0 ) ? 1 : 0)) * appData.messageFontWidth;
//newline if no message or label //newline if no message or label
if(strlen(label) == 0 && strlen(message) == 0 ) { if(strlen(label) == 0 && strlen(message) == 0 ) {
boxRGBA(game.renderer, *left, *top, Modes.screen_width - PAD, *top + game.messageFontHeight,0, 0, 0, 0); boxRGBA(appData.renderer, *left, *top, appData.screen_width - PAD, *top + appData.messageFontHeight,0, 0, 0, 0);
*left = PAD; *left = PAD;
*top = *top - game.messageFontHeight - PAD; *top = *top - appData.messageFontHeight - PAD;
return; return;
} }
if(*left + labelWidth + messageWidth + PAD > Modes.screen_width) { if(*left + labelWidth + messageWidth + PAD > appData.screen_width) {
// if(*left + PAD < Modes.screen_width) { // if(*left + PAD < appData.screen_width) {
// boxRGBA(game.screen, *left, *top, Modes.screen_width - PAD, *top + game.messageFontHeight, darkGrey.r, darkGrey.g, darkGrey.b, SDL_ALPHA_OPAQUE); // boxRGBA(appData.screen, *left, *top, appData.screen_width - PAD, *top + appData.messageFontHeight, darkGrey.r, darkGrey.g, darkGrey.b, SDL_ALPHA_OPAQUE);
// } // }
*left = PAD; *left = PAD;
*top = *top - game.messageFontHeight - PAD; *top = *top - appData.messageFontHeight - PAD;
} }
// filled black background // filled black background
if(messageWidth) { if(messageWidth) {
roundedBoxRGBA(game.renderer, *left, *top, *left + labelWidth + messageWidth, *top + game.messageFontHeight, ROUND_RADIUS, black.r, black.g, black.b, SDL_ALPHA_OPAQUE); roundedBoxRGBA(appData.renderer, *left, *top, *left + labelWidth + messageWidth, *top + appData.messageFontHeight, ROUND_RADIUS, black.r, black.g, black.b, SDL_ALPHA_OPAQUE);
} }
// filled label box // filled label box
if(labelWidth) { if(labelWidth) {
roundedBoxRGBA(game.renderer, *left, *top, *left + labelWidth, *top + game.messageFontHeight, ROUND_RADIUS,color.r, color.g, color.b, SDL_ALPHA_OPAQUE); roundedBoxRGBA(appData.renderer, *left, *top, *left + labelWidth, *top + appData.messageFontHeight, ROUND_RADIUS,color.r, color.g, color.b, SDL_ALPHA_OPAQUE);
} }
// outline message box // outline message box
if(messageWidth) { if(messageWidth) {
roundedRectangleRGBA(game.renderer, *left, *top, *left + labelWidth + messageWidth, *top + game.messageFontHeight, ROUND_RADIUS,color.r, color.g, color.b, SDL_ALPHA_OPAQUE); roundedRectangleRGBA(appData.renderer, *left, *top, *left + labelWidth + messageWidth, *top + appData.messageFontHeight, ROUND_RADIUS,color.r, color.g, color.b, SDL_ALPHA_OPAQUE);
} }
// label // label
//drawString90(label, *left, *top + game.labelFontWidth/2, game.labelFont, black); //drawString90(label, *left, *top + appData.labelFontWidth/2, appData.labelFont, black);
drawString(label, *left + game.labelFontWidth/2, *top, game.labelFont, black); drawString(label, *left + appData.labelFontWidth/2, *top, appData.labelFont, black);
//message //message
drawString(message, *left + labelWidth + game.messageFontWidth/2, *top, game.messageFont, color); drawString(message, *left + labelWidth + appData.messageFontWidth/2, *top, appData.messageFont, color);
*left = *left + labelWidth + messageWidth + PAD; *left = *left + labelWidth + messageWidth + PAD;
} }
@ -114,31 +146,31 @@ void drawStatusBox(int *left, int *top, char *label, char *message, SDL_Color co
void drawButtonBox(int *left, int *top, char *label, SDL_Color color) { void drawButtonBox(int *left, int *top, char *label, SDL_Color color) {
int labelWidth = (strlen(label) + ((strlen(label) > 0 ) ? 1 : 0)) * game.labelFontWidth; int labelWidth = (strlen(label) + ((strlen(label) > 0 ) ? 1 : 0)) * appData.labelFontWidth;
//newline if no message or label //newline if no message or label
if(strlen(label) == 0) { if(strlen(label) == 0) {
boxRGBA(game.renderer, *left, *top, Modes.screen_width - PAD, *top + game.messageFontHeight,0, 0, 0, 0); boxRGBA(appData.renderer, *left, *top, appData.screen_width - PAD, *top + appData.messageFontHeight,0, 0, 0, 0);
*left = PAD; *left = PAD;
*top = *top - game.messageFontHeight - PAD; *top = *top - appData.messageFontHeight - PAD;
return; return;
} }
if(*left + labelWidth + PAD > Modes.screen_width) { if(*left + labelWidth + PAD > appData.screen_width) {
*left = PAD; *left = PAD;
*top = *top - game.messageFontHeight - PAD; *top = *top - appData.messageFontHeight - PAD;
} }
// outline message box // outline message box
if(labelWidth) { if(labelWidth) {
roundedRectangleRGBA(game.renderer, *left, *top , *left + labelWidth - 1, *top + game.messageFontHeight - 1, ROUND_RADIUS, 255, 255, 255, SDL_ALPHA_OPAQUE); roundedRectangleRGBA(appData.renderer, *left, *top , *left + labelWidth - 1, *top + appData.messageFontHeight - 1, ROUND_RADIUS, 255, 255, 255, SDL_ALPHA_OPAQUE);
roundedRectangleRGBA(game.renderer, *left + 1, *top + 1, *left + labelWidth , *top + game.messageFontHeight, ROUND_RADIUS, 20, 20, 20, SDL_ALPHA_OPAQUE); roundedRectangleRGBA(appData.renderer, *left + 1, *top + 1, *left + labelWidth , *top + appData.messageFontHeight, ROUND_RADIUS, 20, 20, 20, SDL_ALPHA_OPAQUE);
roundedBoxRGBA(game.renderer, *left + 1, *top + 1, *left + labelWidth - 1, *top + game.messageFontHeight - 1, ROUND_RADIUS, color.r, color.g, color.b, SDL_ALPHA_OPAQUE); roundedBoxRGBA(appData.renderer, *left + 1, *top + 1, *left + labelWidth - 1, *top + appData.messageFontHeight - 1, ROUND_RADIUS, color.r, color.g, color.b, SDL_ALPHA_OPAQUE);
} }
drawString(label, *left + game.labelFontWidth/2, *top, game.labelFont, black); drawString(label, *left + appData.labelFontWidth/2, *top, appData.labelFont, black);
*left = *left + labelWidth + PAD; *left = *left + labelWidth + PAD;
} }
@ -153,26 +185,26 @@ void drawBattery(int *left, int *top, double level) {
float yList[9] = {0.2, 0.2, 0.0, 0.0, 0.2, 0.2, 1.0, 1.0, 0.2}; float yList[9] = {0.2, 0.2, 0.0, 0.0, 0.2, 0.2, 1.0, 1.0, 0.2};
for(int k = 0; k < pointCount - 1; k++) { for(int k = 0; k < pointCount - 1; k++) {
thickLineRGBA(game.renderer, thickLineRGBA(appData.renderer,
*left + game.messageFontWidth * xList[k], *left + appData.messageFontWidth * xList[k],
*top + game.messageFontHeight * yList[k], *top + appData.messageFontHeight * yList[k],
*left + game.messageFontWidth * xList[k+1], *left + appData.messageFontWidth * xList[k+1],
*top + game.messageFontHeight * yList[k+1], *top + appData.messageFontHeight * yList[k+1],
lineWidth, grey.r, grey.g, grey.b, SDL_ALPHA_OPAQUE); lineWidth, grey.r, grey.g, grey.b, SDL_ALPHA_OPAQUE);
} }
boxRGBA(game.renderer, *left, *top + (0.2 + 0.8 * (1.0 - level)) * game.messageFontHeight, *left + game.messageFontWidth, *top + game.messageFontHeight, grey.r, grey.g, grey.b, SDL_ALPHA_OPAQUE); boxRGBA(appData.renderer, *left, *top + (0.2 + 0.8 * (1.0 - level)) * appData.messageFontHeight, *left + appData.messageFontWidth, *top + appData.messageFontHeight, grey.r, grey.g, grey.b, SDL_ALPHA_OPAQUE);
*left = *left + game.messageFontWidth; *left = *left + appData.messageFontWidth;
} }
void drawStatus() { void drawStatus() {
int left = PAD + 2 * game.messageFontHeight ; int left = PAD + 2 * appData.messageFontHeight ;
int top = Modes.screen_height - 2 * game.messageFontHeight - PAD; int top = appData.screen_height - 2 * appData.messageFontHeight - PAD;
char strLoc[20] = " "; char strLoc[20] = " ";
snprintf(strLoc, 20, "%3.3fN %3.3f%c", Modes.fUserLat, fabs(Modes.fUserLon),(Modes.fUserLon > 0) ? 'E' : 'W'); snprintf(strLoc, 20, "%3.3fN %3.3f%c", appData.centerLat, fabs(appData.centerLon),(appData.centerLon > 0) ? 'E' : 'W');
drawStatusBox(&left, &top, "loc", strLoc, pink); drawStatusBox(&left, &top, "loc", strLoc, pink);
// drawBattery(&left, &top, 0.85); // drawBattery(&left, &top, 0.85);
@ -181,9 +213,11 @@ void drawStatus() {
snprintf(strPlaneCount, 10,"%d/%d", Status.numVisiblePlanes, Status.numPlanes); snprintf(strPlaneCount, 10,"%d/%d", Status.numVisiblePlanes, Status.numPlanes);
drawStatusBox(&left, &top, "disp", strPlaneCount, yellow); drawStatusBox(&left, &top, "disp", strPlaneCount, yellow);
char strDMax[5] = " "; //distance measurements got borked during refactor - need to redo here
snprintf(strDMax, 5, "%.0fkm", Status.maxDist);
drawStatusBox(&left, &top, "mDst", strDMax, blue); // char strDMax[5] = " ";
// snprintf(strDMax, 5, "%.0fkm", Status.maxDist);
// drawStatusBox(&left, &top, "mDst", strDMax, blue);
char strMsgRate[18] = " "; char strMsgRate[18] = " ";
snprintf(strMsgRate, 18,"%.0f/s", Status.msgRate); snprintf(strMsgRate, 18,"%.0f/s", Status.msgRate);

View file

@ -1 +1 @@
4c882fece9c30acf73d1f87d59f36e90da75ca30 73f15d7f49718ad2118fa30449dffa3f088a20bd

View file

@ -3,7 +3,7 @@
#include "defs.h" #include "defs.h"
typedef struct Game typedef struct AppData
{ {
SDL_Window *window; SDL_Window *window;
SDL_Renderer *renderer; SDL_Renderer *renderer;
@ -22,9 +22,64 @@ typedef struct Game
int labelFontHeight; int labelFontHeight;
int messageFontWidth; int messageFontWidth;
int messageFontHeight; int messageFontHeight;
} Game;
Game game; // map options
int showList;
int mapLogDist;
float maxDist;
//display options
int screen_upscale;
int screen_uiscale;
int screen_width;
int screen_height;
int screen_depth;
int fullscreen;
double centerLon;
double centerLat;
uint64_t lastFrameTime;
} AppData;
AppData appData;
// mirrors aircraft struct in dump1090, separating for refactoring
struct planeObj {
uint32_t addr; // ICAO address
char flight[16]; // Flight number
unsigned char signalLevel[8]; // Last 8 Signal Amplitudes
double messageRate[8];
int altitude; // Altitude
int speed; // Velocity
int track; // Angle of flight
int vert_rate; // Vertical rate.
time_t seen; // Time at which the last packet was received
double lat, lon; // Coordinated obtained from CPR encoded data
//history
double oldLon[TRAIL_LENGTH];
double oldLat[TRAIL_LENGTH];
double oldHeading[TRAIL_LENGTH];
time_t oldSeen[TRAIL_LENGTH];
uint8_t oldIdx;
uint64_t created;
int live;
struct planeObj *next; // Next aircraft in our linked list
};
struct planeObj *planes;
struct {
double msgRate;
double avgSig;
int numPlanes;
int numVisiblePlanes;
double maxDist;
struct aircraft *closeCall;
} Status;
// functions // functions
@ -55,4 +110,8 @@ void draw();
void updateStatus(); void updateStatus();
void drawStatus(); void drawStatus();
//planeObj.c
void updatePlanes();
#endif #endif

View file

@ -1 +1 @@
53426cac38852a6505d629ec7324b5ec7a2d18da cc7b8e99972e34a43bebde90a9679815d2219511

View file

@ -31,8 +31,6 @@
#include "view1090.h" #include "view1090.h"
#include "structs.h" #include "structs.h"
Game game;
int go = 1; int go = 1;
// //
@ -43,27 +41,7 @@ void sigintHandler(int dummy) {
signal(SIGINT, SIG_DFL); // reset signal handler - bit extra safety signal(SIGINT, SIG_DFL); // reset signal handler - bit extra safety
Modes.exit = 1; // Signal to threads that we are done Modes.exit = 1; // Signal to threads that we are done
} }
//
// =============================== Terminal handling ========================
//
#ifndef _WIN32
// Get the number of rows after the terminal changes size.
int getTermRows() {
struct winsize w;
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
return (w.ws_row);
}
// Handle resizing terminal
void sigWinchCallback() {
signal(SIGWINCH, SIG_IGN);
Modes.interactive_rows = getTermRows();
interactiveShowData();
signal(SIGWINCH, sigWinchCallback);
}
#else
int getTermRows() { return MODES_INTERACTIVE_ROWS;}
#endif
// //
// =============================== Initialization =========================== // =============================== Initialization ===========================
// //
@ -76,7 +54,7 @@ void view1090InitConfig(void) {
Modes.check_crc = 1; Modes.check_crc = 1;
strcpy(View1090.net_input_beast_ipaddr,VIEW1090_NET_OUTPUT_IP_ADDRESS); strcpy(View1090.net_input_beast_ipaddr,VIEW1090_NET_OUTPUT_IP_ADDRESS);
Modes.net_input_beast_port = MODES_NET_OUTPUT_BEAST_PORT; Modes.net_input_beast_port = MODES_NET_OUTPUT_BEAST_PORT;
Modes.interactive_rows = getTermRows(); Modes.interactive_rows = MODES_INTERACTIVE_ROWS;
Modes.interactive_delete_ttl = MODES_INTERACTIVE_DELETE_TTL; Modes.interactive_delete_ttl = MODES_INTERACTIVE_DELETE_TTL;
Modes.interactive_display_ttl = MODES_INTERACTIVE_DISPLAY_TTL; Modes.interactive_display_ttl = MODES_INTERACTIVE_DISPLAY_TTL;
Modes.fUserLat = MODES_USER_LATITUDE_DFLT; Modes.fUserLat = MODES_USER_LATITUDE_DFLT;
@ -86,17 +64,18 @@ void view1090InitConfig(void) {
Modes.quiet = 1; Modes.quiet = 1;
// Map options // Map options
Modes.map = 1; appData.showList = 0;
Modes.mapLogDist = 0; appData.mapLogDist = 0;
Modes.maxDist = 25.0; appData.maxDist = 25.0;
appData.centerLon = Modes.fUserLon;
appData.centerLat = Modes.fUserLat;
// Display options // Display options
Modes.screen_upscale = UPSCALE; appData.screen_uiscale = UISCALE;
Modes.screen_uiscale = UISCALE; appData.screen_width = SCREEN_WIDTH;
Modes.screen_width = SCREEN_WIDTH; appData.screen_height = SCREEN_HEIGHT;
Modes.screen_height = SCREEN_HEIGHT; appData.screen_depth = 32;
Modes.screen_depth = 32; appData.fullscreen = 0;
Modes.fullscreen = 0;
// Initialize status // Initialize status
Status.msgRate = 0; Status.msgRate = 0;
@ -186,6 +165,8 @@ int setupConnection(struct client *c) {
// replace with gps // replace with gps
Modes.fUserLat = ***REMOVED***; Modes.fUserLat = ***REMOVED***;
Modes.fUserLon = ***REMOVED***; Modes.fUserLon = ***REMOVED***;
appData.centerLon = Modes.fUserLon;
appData.centerLat = Modes.fUserLat;
} }
return fd; return fd;
} }
@ -215,7 +196,6 @@ void showHelp(void) {
"\n-----------------------------------------------------------------------------\n" "\n-----------------------------------------------------------------------------\n"
"| SDL DISPLAY OPTIONS |\n" "| SDL DISPLAY OPTIONS |\n"
"-----------------------------------------------------------------------------\n" "-----------------------------------------------------------------------------\n"
"--upscale <factor> Buffer upscaling\n"
"--uiscale <factor> UI global scaling\n" "--uiscale <factor> UI global scaling\n"
"--screensize <width> <height>\n" "--screensize <width> <height>\n"
"--fullscreen Start fullscreen\n" "--fullscreen Start fullscreen\n"
@ -291,8 +271,10 @@ int main(int argc, char **argv) {
Modes.interactive_rtl1090 = 1; Modes.interactive_rtl1090 = 1;
} else if (!strcmp(argv[j],"--lat") && more) { } else if (!strcmp(argv[j],"--lat") && more) {
Modes.fUserLat = atof(argv[++j]); Modes.fUserLat = atof(argv[++j]);
appData.centerLat = Modes.fUserLat;
} else if (!strcmp(argv[j],"--lon") && more) { } else if (!strcmp(argv[j],"--lon") && more) {
Modes.fUserLon = atof(argv[++j]); Modes.fUserLon = atof(argv[++j]);
appData.centerLon = Modes.fUserLon;
} else if (!strcmp(argv[j],"--metric")) { } else if (!strcmp(argv[j],"--metric")) {
Modes.metric = 1; Modes.metric = 1;
} else if (!strcmp(argv[j],"--no-crc-check")) { } else if (!strcmp(argv[j],"--no-crc-check")) {
@ -304,14 +286,12 @@ int main(int argc, char **argv) {
} else if (!strcmp(argv[j],"--aggressive")) { } else if (!strcmp(argv[j],"--aggressive")) {
Modes.nfix_crc = MODES_MAX_BITERRORS; Modes.nfix_crc = MODES_MAX_BITERRORS;
} else if (!strcmp(argv[j],"--fullscreen")) { } else if (!strcmp(argv[j],"--fullscreen")) {
Modes.fullscreen = 1; appData.fullscreen = 1;
} else if (!strcmp(argv[j],"--upscale") && more) {
Modes.screen_upscale = atoi(argv[++j]);
} else if (!strcmp(argv[j],"--uiscale") && more) { } else if (!strcmp(argv[j],"--uiscale") && more) {
Modes.screen_uiscale = atoi(argv[++j]); appData.screen_uiscale = atoi(argv[++j]);
} else if (!strcmp(argv[j],"--screensize") && more) { } else if (!strcmp(argv[j],"--screensize") && more) {
Modes.screen_width = atoi(argv[++j]); appData.screen_width = atoi(argv[++j]);
Modes.screen_height = atoi(argv[++j]); appData.screen_height = atoi(argv[++j]);
} else if (!strcmp(argv[j],"--help")) { } else if (!strcmp(argv[j],"--help")) {
showHelp(); showHelp();
exit(0); exit(0);
@ -322,17 +302,6 @@ int main(int argc, char **argv) {
} }
} }
#ifdef _WIN32
// Try to comply with the Copyright license conditions for binary distribution
if (!Modes.quiet) {showCopyright();}
#define MSG_DONTWAIT 0
#endif
#ifndef _WIN32
// Setup for SIGWINCH for handling lines
if (Modes.interactive) {signal(SIGWINCH, sigWinchCallback);}
#endif
// Initialization // Initialization
view1090Init(); view1090Init();

View file

@ -1 +1 @@
a1f04fa3c4375ebfef8558b27bf27cad234f3a4e 6a3d6fb29439db4b118b48c859c390d687566a2d