diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 67495f9db..000000000 --- a/.gitignore +++ /dev/null @@ -1,10 +0,0 @@ -*.o -dump1090 -testfiles/*.bin -misc -frames.js -.*.swp -*~ -*.rej -*.orig -untrackedDeveloperSettings.js \ No newline at end of file diff --git a/Makefile b/Makefile deleted file mode 100644 index 6bfe9ee14..000000000 --- a/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -# -# When building a package or installing otherwise in the system, make -# sure that the variable PREFIX is defined, e.g. make PREFIX=/usr/local -# -PROGNAME=dump1090 - -ifdef PREFIX -BINDIR=$(PREFIX)/bin -SHAREDIR=$(PREFIX)/share/$(PROGNAME) -EXTRACFLAGS=-DHTMLPATH=\"$(SHAREDIR)\" -endif - -CFLAGS=-O2 -g -Wall -W `pkg-config --cflags librtlsdr` -LIBS=`pkg-config --libs librtlsdr` -lpthread -lm -CC=gcc - - -all: dump1090 view1090 - -%.o: %.c - $(CC) $(CFLAGS) $(EXTRACFLAGS) -c $< - -dump1090: dump1090.o anet.o interactive.o mode_ac.o mode_s.o net_io.o - $(CC) -g -o dump1090 dump1090.o anet.o interactive.o mode_ac.o mode_s.o net_io.o $(LIBS) $(LDFLAGS) - -view1090: view1090.o anet.o interactive.o mode_ac.o mode_s.o net_io.o - $(CC) -g -o view1090 view1090.o anet.o interactive.o mode_ac.o mode_s.o net_io.o $(LIBS) $(LDFLAGS) - -clean: - rm -f *.o dump1090 view1090 diff --git a/README.md b/README.md index 3fdd396ed..bd9f27198 100644 --- a/README.md +++ b/README.md @@ -1,284 +1,8 @@ -Dump1090 README -=== +# Old dump1090-mutability fork -Dump 1090 is a Mode S decoder specifically designed for RTLSDR devices. +dump1090-mutability is no longer maintained; please don't use it for new installs. -The main features are: +For new installs and ongoing development, try dump1090-fa, which is available at https://github.com/flightaware/dump1090 -* Robust decoding of weak messages, with mode1090 many users observed - improved range compared to other popular decoders. -* Network support: TCP30003 stream (MSG5...), Raw packets, HTTP. -* Embedded HTTP server that displays the currently detected aircrafts on - Google Map. -* Single bit errors correction using the 24 bit CRC. -* Ability to decode DF11, DF17 messages. -* Ability to decode DF formats like DF0, DF4, DF5, DF16, DF20 and DF21 - where the checksum is xored with the ICAO address by brute forcing the - checksum field using recently seen ICAO addresses. -* Decode raw IQ samples from file (using --ifile command line switch). -* Interactive command-line-interfae mode where aircrafts currently detected - are shown as a list refreshing as more data arrives. -* CPR coordinates decoding and track calculation from velocity. -* TCP server streaming and recceiving raw data to/from connected clients - (using --net). +The historical master branch is available in the `unmaintained` branch. -Installation ---- - -Type "make". - -Normal usage ---- - -To capture traffic directly from your RTL device and show the captured traffic -on standard output, just run the program without options at all: - - ./dump1090 - -To just output hexadecimal messages: - - ./dump1090 --raw - -To run the program in interactive mode: - - ./dump1090 --interactive - -To run the program in interactive mode, with networking support, and connect -with your browser to http://localhost:8080 to see live traffic: - - ./dump1090 --interactive --net - -In iteractive mode it is possible to have a less information dense but more -"arcade style" output, where the screen is refreshed every second displaying -all the recently seen aircrafts with some additional information such as -altitude and flight number, extracted from the received Mode S packets. - -Using files as source of data ---- - -To decode data from file, use: - - ./dump1090 --ifile /path/to/binfile - -The binary file should be created using `rtl_sdr` like this (or with any other -program that is able to output 8-bit unsigned IQ samples at 2Mhz sample rate). - - rtl_sdr -f 1090000000 -s 2000000 -g 50 output.bin - -In the example `rtl_sdr` a gain of 50 is used, simply you should use the highest -gain availabe for your tuner. This is not needed when calling Dump1090 itself -as it is able to select the highest gain supported automatically. - -It is possible to feed the program with data via standard input using -the --ifile option with "-" as argument. - -Additional options ---- - -Dump1090 can be called with other command line options to set a different -gain, frequency, and so forth. For a list of options use: - - ./dump1090 --help - -Everything is not documented here should be obvious, and for most users calling -it without arguments at all is the best thing to do. - -Reliability ---- - -By default Dump1090 checks for decoding errors using the 24-bit CRC checksum, -where available. Messages with errors are discarded. - -The --fix command line switch enables fixing single bit error correction -based on the CRC checksum. Technically, it uses a table of precomputed -checksum differences resulting from single bit errors to look up the -wrong bit position. - -This is indeed able to fix errors and works reliably in my experience, -however if you are interested in very reliable data I suggest to use -the --no-fix command line switch in order to disable error fixing. - -Performances and sensibility of detection ---- - -In my limited experience Dump1090 was able to decode a big number of messages -even in conditions where I encountered problems using other programs, however -no formal test was performed so I can't really claim that this program is -better or worse compared to other similar programs. - -If you can capture traffic that Dump1090 is not able to decode properly, drop -me an email with a download link. I may try to improve the detection during -my free time (this is just an hobby project). - -Network server features ---- - -By enabling the networking support with --net Dump1090 starts listening -for clients connections on port 30002 and 30001 (you can change both the -ports if you want, see --help output). - -Port 30002 ---- - -Connected clients are served with data ASAP as they arrive from the device -(or from file if --ifile is used) in the raw format similar to the following: - - *8D451E8B99019699C00B0A81F36E; - -Every entry is separated by a simple newline (LF character, hex 0x0A). - -Port 30001 ---- - -Port 30001 is the raw input port, and can be used to feed Dump1090 with -data in the same format as specified above, with hex messages starting with -a `*` and ending with a `;` character. - -So for instance if there is another remote Dump1090 instance collecting data -it is possible to sum the output to a local Dump1090 instance doing something -like this: - - nc remote-dump1090.example.net 30002 | nc localhost 30001 - -It is important to note that what is received via port 30001 is also -broadcasted to clients listening to port 30002. - -In general everything received from port 30001 is handled exactly like the -normal traffic from RTL devices or from file when --ifile is used. - -It is possible to use Dump1090 just as an hub using --ifile with /dev/zero -as argument as in the following example: - - ./dump1090 --net-only - -Or alternatively to see what's happening on the screen: - - ./dump1090 --net-only --interactive - -Then you can feed it from different data sources from the internet. - -Port 30003 ---- - -Connected clients are served with messages in SBS1 (BaseStation) format, -similar to: - - MSG,4,,,738065,,,,,,,,420,179,,,0,,0,0,0,0 - MSG,3,,,738065,,,,,,,35000,,,34.81609,34.07810,,,0,0,0,0 - -This can be used to feed data to various sharing sites without the need to use another decoder. - -Antenna ---- - -Mode S messages are transmitted in the 1090 Mhz frequency. If you have a decent -antenna you'll be able to pick up signals from aircrafts pretty far from your -position, especially if you are outdoor and in a position with a good sky view. - -You can easily build a very cheap antenna following the istructions at: - - http://antirez.com/news/46 - -With this trivial antenna I was able to pick up signals of aircrafts 200+ Km -away from me. - -If you are interested in a more serious antenna check the following -resources: - -* http://gnuradio.org/redmine/attachments/download/246/06-foster-adsb.pdf -* http://www.lll.lu/~edward/edward/adsb/antenna/ADSBantenna.html -* http://modesbeast.com/pix/adsb-ant-drawing.gif - -Aggressive mode ---- - -With --aggressive it is possible to activate the *aggressive mode* that is a -modified version of the Mode S packet detection and decoding. -The aggresive mode uses more CPU usually (especially if there are many planes -sending DF17 packets), but can detect a few more messages. - -The algorithm in aggressive mode is modified in the following ways: - -* Up to two demodulation errors are tolerated (adjacent entires in the - magnitude vector with the same eight). Normally only messages without - errors are checked. -* It tries to fix DF17 messages with CRC errors resulting from any two bit - errors. - -The use of aggressive mdoe is only advised in places where there is -low traffic in order to have a chance to capture some more messages. - -Debug mode ---- - -The Debug mode is a visual help to improve the detection algorithm or to -understand why the program is not working for a given input. - -In this mode messages are displayed in an ASCII-art style graphical -representation, where the individial magnitude bars sampled at 2Mhz are -displayed. - -An index shows the sample number, where 0 is the sample where the first -Mode S peak was found. Some additional background noise is also added -before the first peak to provide some context. - -To enable debug mode and check what combinations of packets you can -log, use `mode1090 --help` to obtain a list of available debug flags. - -Debug mode includes an optional javascript output that is used to visualize -packets using a web browser, you can use the file debug.html under the -'tools' directory to load the generated frames.js file. - -How this program works? ---- - -The code is very documented and written in order to be easy to understand. -For the diligent programmer with a Mode S specification on his hands it -should be trivial to understand how it works. - -The algorithms I used were obtained basically looking at many messages -as displayed using a trow-away SDL program, and trying to model the algorithm -based on how the messages look graphically. - -How to test the program? ---- - -If you have an RTLSDR device and you happen to be in an area where there -are aircrafts flying over your head, just run the program and check for signals. - -However if you don't have an RTLSDR device, or if in your area the presence -of aircrafts is very limited, you may want to try the sample file distributed -with the Dump1090 distribution under the "testfiles" directory. - -Just run it like this: - - ./dump1090 --ifile testfiles/modes1.bin - -What is --strip mode? ---- - -It is just a simple filter that will get raw IQ 8 bit samples in input -and will output a file missing all the parts of the file where I and Q -are lower than the specified for more than 32 samples. - -Use it like this: - - cat big.bin | ./dump1090 --snip 25 > small.bin - -I used it in order to create a small test file to include inside this -program source code distribution. - -Contributing ---- - -Dump1090 was written during some free time during xmas 2012, it is an hobby -project so I'll be able to address issues and improve it only during -free time, however you are incouraged to send pull requests in order to -improve the program. A good starting point can be the TODO list included in -the source distribution. - -Credits ---- - -Dump1090 was written by Salvatore Sanfilippo and is -released under the BSD three clause license. diff --git a/TODO b/TODO deleted file mode 100644 index 041ad2949..000000000 --- a/TODO +++ /dev/null @@ -1,5 +0,0 @@ -TODO - -* Extract more information from captured Mode S messages. -* Improve the web interface gmap.html. -* Enhance the algorithm to reliably decode more messages. diff --git a/anet.c b/anet.c deleted file mode 100644 index 859c98c82..000000000 --- a/anet.c +++ /dev/null @@ -1,345 +0,0 @@ -/* anet.c -- Basic TCP socket stuff made a bit less boring - * - * Copyright (c) 2006-2012, Salvatore Sanfilippo - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _WIN32 - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include -#else - #include "winstubs.h" //Put everything Windows specific in here - #include "dump1090.h" -#endif - -#include "anet.h" - -static void anetSetError(char *err, const char *fmt, ...) -{ - va_list ap; - - if (!err) return; - va_start(ap, fmt); - vsnprintf(err, ANET_ERR_LEN, fmt, ap); - va_end(ap); -} - -int anetNonBlock(char *err, int fd) -{ - int flags; -#ifndef _WIN32 - /* Set the socket nonblocking. - * Note that fcntl(2) for F_GETFL and F_SETFL can't be - * interrupted by a signal. */ - if ((flags = fcntl(fd, F_GETFL)) == -1) { - anetSetError(err, "fcntl(F_GETFL): %s", strerror(errno)); - return ANET_ERR; - } - if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) { - anetSetError(err, "fcntl(F_SETFL,O_NONBLOCK): %s", strerror(errno)); - return ANET_ERR; - } -#else - flags = 1; - if (ioctlsocket(fd, FIONBIO, &flags)) { - errno = WSAGetLastError(); - anetSetError(err, "ioctlsocket(FIONBIO): %s", strerror(errno)); - return ANET_ERR; - } -#endif - return ANET_OK; -} - -int anetTcpNoDelay(char *err, int fd) -{ - int yes = 1; - if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (void*)&yes, sizeof(yes)) == -1) - { - anetSetError(err, "setsockopt TCP_NODELAY: %s", strerror(errno)); - return ANET_ERR; - } - return ANET_OK; -} - -int anetSetSendBuffer(char *err, int fd, int buffsize) -{ - if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (void*)&buffsize, sizeof(buffsize)) == -1) - { - anetSetError(err, "setsockopt SO_SNDBUF: %s", strerror(errno)); - return ANET_ERR; - } - return ANET_OK; -} - -int anetTcpKeepAlive(char *err, int fd) -{ - int yes = 1; - if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void*)&yes, sizeof(yes)) == -1) { - anetSetError(err, "setsockopt SO_KEEPALIVE: %s", strerror(errno)); - return ANET_ERR; - } - return ANET_OK; -} - -int anetResolve(char *err, char *host, char *ipbuf) -{ - struct sockaddr_in sa; - - sa.sin_family = AF_INET; - if (inet_aton(host, (void*)&sa.sin_addr) == 0) { - struct hostent *he; - - he = gethostbyname(host); - if (he == NULL) { - anetSetError(err, "can't resolve: %s", host); - return ANET_ERR; - } - memcpy(&sa.sin_addr, he->h_addr, sizeof(struct in_addr)); - } - strcpy(ipbuf,inet_ntoa(sa.sin_addr)); - return ANET_OK; -} - -static int anetCreateSocket(char *err, int domain) { - int s, on = 1; - if ((s = socket(domain, SOCK_STREAM, 0)) == -1) { -#ifdef _WIN32 - errno = WSAGetLastError(); -#endif - anetSetError(err, "creating socket: %s", strerror(errno)); - return ANET_ERR; - } - - /* Make sure connection-intensive things like the redis benckmark - * will be able to close/open sockets a zillion of times */ - if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*)&on, sizeof(on)) == -1) { - anetSetError(err, "setsockopt SO_REUSEADDR: %s", strerror(errno)); - return ANET_ERR; - } - return s; -} - -#define ANET_CONNECT_NONE 0 -#define ANET_CONNECT_NONBLOCK 1 -static int anetTcpGenericConnect(char *err, char *addr, int port, int flags) -{ - int s; - struct sockaddr_in sa; - - if ((s = anetCreateSocket(err,AF_INET)) == ANET_ERR) - return ANET_ERR; - - memset(&sa,0,sizeof(sa)); - sa.sin_family = AF_INET; - sa.sin_port = htons((uint16_t)port); - if (inet_aton(addr, (void*)&sa.sin_addr) == 0) { - struct hostent *he; - - he = gethostbyname(addr); - if (he == NULL) { - anetSetError(err, "can't resolve: %s", addr); - close(s); - return ANET_ERR; - } - memcpy(&sa.sin_addr, he->h_addr, sizeof(struct in_addr)); - } - if (flags & ANET_CONNECT_NONBLOCK) { - if (anetNonBlock(err,s) != ANET_OK) - return ANET_ERR; - } - if (connect(s, (struct sockaddr*)&sa, sizeof(sa)) == -1) { - if (errno == EINPROGRESS && - flags & ANET_CONNECT_NONBLOCK) - return s; - - anetSetError(err, "connect: %s", strerror(errno)); - close(s); - return ANET_ERR; - } - return s; -} - -int anetTcpConnect(char *err, char *addr, int port) -{ - return anetTcpGenericConnect(err,addr,port,ANET_CONNECT_NONE); -} - -int anetTcpNonBlockConnect(char *err, char *addr, int port) -{ - return anetTcpGenericConnect(err,addr,port,ANET_CONNECT_NONBLOCK); -} - -/* Like read(2) but make sure 'count' is read before to return - * (unless error or EOF condition is encountered) */ -int anetRead(int fd, char *buf, int count) -{ - int nread, totlen = 0; - while(totlen != count) { - nread = read(fd,buf,count-totlen); - if (nread == 0) return totlen; - if (nread == -1) return -1; - totlen += nread; - buf += nread; - } - return totlen; -} - -/* Like write(2) but make sure 'count' is read before to return - * (unless error is encountered) */ -int anetWrite(int fd, char *buf, int count) -{ - int nwritten, totlen = 0; - while(totlen != count) { - nwritten = write(fd,buf,count-totlen); - if (nwritten == 0) return totlen; - if (nwritten == -1) return -1; - totlen += nwritten; - buf += nwritten; - } - return totlen; -} - -static int anetListen(char *err, int s, struct sockaddr *sa, socklen_t len) { - if (bind(s,sa,len) == -1) { -#ifdef _WIN32 - errno = WSAGetLastError(); -#endif - anetSetError(err, "bind: %s", strerror(errno)); - close(s); - return ANET_ERR; - } - - /* Use a backlog of 512 entries. We pass 511 to the listen() call because - * the kernel does: backlogsize = roundup_pow_of_two(backlogsize + 1); - * which will thus give us a backlog of 512 entries */ - if (listen(s, 511) == -1) { -#ifdef _WIN32 - errno = WSAGetLastError(); -#endif - anetSetError(err, "listen: %s", strerror(errno)); - close(s); - return ANET_ERR; - } - return ANET_OK; -} - -int anetTcpServer(char *err, int port, char *bindaddr) -{ - int s; - struct sockaddr_in sa; - - if ((s = anetCreateSocket(err,AF_INET)) == ANET_ERR) - return ANET_ERR; - - memset(&sa,0,sizeof(sa)); - sa.sin_family = AF_INET; - sa.sin_port = htons((uint16_t)port); - sa.sin_addr.s_addr = htonl(INADDR_ANY); - if (bindaddr && inet_aton(bindaddr, (void*)&sa.sin_addr) == 0) { - anetSetError(err, "invalid bind address"); - close(s); - return ANET_ERR; - } - if (anetListen(err,s,(struct sockaddr*)&sa,sizeof(sa)) == ANET_ERR) - return ANET_ERR; - return s; -} - -static int anetGenericAccept(char *err, int s, struct sockaddr *sa, socklen_t *len) { - int fd; - while(1) { - fd = accept(s,sa,len); - if (fd == -1) { -#ifndef _WIN32 - if (errno == EINTR) { - continue; -#else - errno = WSAGetLastError(); - if (errno == WSAEWOULDBLOCK) { -#endif - } else { - anetSetError(err, "accept: %s", strerror(errno)); - } - } - break; - } - return fd; -} - -int anetTcpAccept(char *err, int s, char *ip, int *port) { - int fd; - struct sockaddr_in sa; - socklen_t salen = sizeof(sa); - if ((fd = anetGenericAccept(err,s,(struct sockaddr*)&sa,&salen)) == ANET_ERR) - return ANET_ERR; - - if (ip) strcpy(ip,inet_ntoa(sa.sin_addr)); - if (port) *port = ntohs(sa.sin_port); - return fd; -} - -int anetPeerToString(int fd, char *ip, int *port) { - struct sockaddr_in sa; - socklen_t salen = sizeof(sa); - - if (getpeername(fd,(struct sockaddr*)&sa,&salen) == -1) { - *port = 0; - ip[0] = '?'; - ip[1] = '\0'; - return -1; - } - if (ip) strcpy(ip,inet_ntoa(sa.sin_addr)); - if (port) *port = ntohs(sa.sin_port); - return 0; -} - -int anetSockName(int fd, char *ip, int *port) { - struct sockaddr_in sa; - socklen_t salen = sizeof(sa); - - if (getsockname(fd,(struct sockaddr*)&sa,&salen) == -1) { - *port = 0; - ip[0] = '?'; - ip[1] = '\0'; - return -1; - } - if (ip) strcpy(ip,inet_ntoa(sa.sin_addr)); - if (port) *port = ntohs(sa.sin_port); - return 0; -} diff --git a/anet.h b/anet.h deleted file mode 100644 index 6d74af577..000000000 --- a/anet.h +++ /dev/null @@ -1,59 +0,0 @@ -/* anet.c -- Basic TCP socket stuff made a bit less boring - * - * Copyright (c) 2006-2012, Salvatore Sanfilippo - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef ANET_H -#define ANET_H - -#define ANET_OK 0 -#define ANET_ERR -1 -#define ANET_ERR_LEN 256 - -#if defined(__sun) -#define AF_LOCAL AF_UNIX -#endif - -int anetTcpConnect(char *err, char *addr, int port); -int anetTcpNonBlockConnect(char *err, char *addr, int port); -int anetUnixConnect(char *err, char *path); -int anetUnixNonBlockConnect(char *err, char *path); -int anetRead(int fd, char *buf, int count); -int anetResolve(char *err, char *host, char *ipbuf); -int anetTcpServer(char *err, int port, char *bindaddr); -int anetUnixServer(char *err, char *path, mode_t perm); -int anetTcpAccept(char *err, int serversock, char *ip, int *port); -int anetUnixAccept(char *err, int serversock); -int anetWrite(int fd, char *buf, int count); -int anetNonBlock(char *err, int fd); -int anetTcpNoDelay(char *err, int fd); -int anetTcpKeepAlive(char *err, int fd); -int anetPeerToString(int fd, char *ip, int *port); -int anetSetSendBuffer(char *err, int fd, int buffsize); - -#endif diff --git a/coaa.h b/coaa.h deleted file mode 100644 index 3d0770442..000000000 --- a/coaa.h +++ /dev/null @@ -1,6 +0,0 @@ -// coaa.h configuration file for Plane Plotter Uploader -// -// You MUST apply via the COAA website for your own personal version of this file -// Do not disclose the contents of this file to anyone thereafter as it uniquely -// identifies you to the PlanePlotter system -// diff --git a/coaa1090.obj b/coaa1090.obj deleted file mode 100644 index ea54fdef2..000000000 Binary files a/coaa1090.obj and /dev/null differ diff --git a/dump1090-win.1.10.3010.14.zip b/dump1090-win.1.10.3010.14.zip deleted file mode 100644 index 670d4181c..000000000 Binary files a/dump1090-win.1.10.3010.14.zip and /dev/null differ diff --git a/dump1090.c b/dump1090.c deleted file mode 100644 index 60882fc73..000000000 --- a/dump1090.c +++ /dev/null @@ -1,904 +0,0 @@ -// dump1090, a Mode S messages decoder for RTLSDR devices. -// -// Copyright (C) 2012 by Salvatore Sanfilippo -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -#include "coaa.h" -#include "dump1090.h" -// -// ============================= Utility functions ========================== -// -void sigintHandler(int dummy) { - MODES_NOTUSED(dummy); - signal(SIGINT, SIG_DFL); // reset signal handler - bit extra safety - 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 =========================== -// -void modesInitConfig(void) { - // Default everything to zero/NULL - memset(&Modes, 0, sizeof(Modes)); - - // Now initialise things that should not be 0/NULL to their defaults - Modes.gain = MODES_MAX_GAIN; - Modes.freq = MODES_DEFAULT_FREQ; - Modes.ppm_error = MODES_DEFAULT_PPM; - Modes.check_crc = 1; - Modes.net_heartbeat_rate = MODES_NET_HEARTBEAT_RATE; - Modes.net_output_sbs_port = MODES_NET_OUTPUT_SBS_PORT; - Modes.net_output_raw_port = MODES_NET_OUTPUT_RAW_PORT; - Modes.net_input_raw_port = MODES_NET_INPUT_RAW_PORT; - Modes.net_output_beast_port = MODES_NET_OUTPUT_BEAST_PORT; - Modes.net_input_beast_port = MODES_NET_INPUT_BEAST_PORT; - Modes.net_http_port = MODES_NET_HTTP_PORT; - Modes.interactive_rows = getTermRows(); - Modes.interactive_delete_ttl = MODES_INTERACTIVE_DELETE_TTL; - Modes.interactive_display_ttl = MODES_INTERACTIVE_DISPLAY_TTL; - Modes.fUserLat = MODES_USER_LATITUDE_DFLT; - Modes.fUserLon = MODES_USER_LONGITUDE_DFLT; -} -// -//========================================================================= -// -void modesInit(void) { - int i, q; - - pthread_mutex_init(&Modes.pDF_mutex,NULL); - pthread_mutex_init(&Modes.data_mutex,NULL); - pthread_cond_init(&Modes.data_cond,NULL); - - // Allocate the various buffers used by Modes - if ( ((Modes.icao_cache = (uint32_t *) malloc(sizeof(uint32_t) * MODES_ICAO_CACHE_LEN * 2) ) == NULL) || - ((Modes.pFileData = (uint16_t *) malloc(MODES_ASYNC_BUF_SIZE) ) == NULL) || - ((Modes.magnitude = (uint16_t *) malloc(MODES_ASYNC_BUF_SIZE+MODES_PREAMBLE_SIZE+MODES_LONG_MSG_SIZE) ) == NULL) || - ((Modes.maglut = (uint16_t *) malloc(sizeof(uint16_t) * 256 * 256) ) == NULL) || - ((Modes.beastOut = (char *) malloc(MODES_RAWOUT_BUF_SIZE) ) == NULL) || - ((Modes.rawOut = (char *) malloc(MODES_RAWOUT_BUF_SIZE) ) == NULL) ) - { - fprintf(stderr, "Out of memory allocating data buffer.\n"); - exit(1); - } - - // Clear the buffers that have just been allocated, just in-case - memset(Modes.icao_cache, 0, sizeof(uint32_t) * MODES_ICAO_CACHE_LEN * 2); - memset(Modes.pFileData,127, MODES_ASYNC_BUF_SIZE); - memset(Modes.magnitude, 0, MODES_ASYNC_BUF_SIZE+MODES_PREAMBLE_SIZE+MODES_LONG_MSG_SIZE); - - // Validate the users Lat/Lon home location inputs - if ( (Modes.fUserLat > 90.0) // Latitude must be -90 to +90 - || (Modes.fUserLat < -90.0) // and - || (Modes.fUserLon > 360.0) // Longitude must be -180 to +360 - || (Modes.fUserLon < -180.0) ) { - Modes.fUserLat = Modes.fUserLon = 0.0; - } else if (Modes.fUserLon > 180.0) { // If Longitude is +180 to +360, make it -180 to 0 - Modes.fUserLon -= 360.0; - } - // If both Lat and Lon are 0.0 then the users location is either invalid/not-set, or (s)he's in the - // Atlantic ocean off the west coast of Africa. This is unlikely to be correct. - // Set the user LatLon valid flag only if either Lat or Lon are non zero. Note the Greenwich meridian - // is at 0.0 Lon,so we must check for either fLat or fLon being non zero not both. - // Testing the flag at runtime will be much quicker than ((fLon != 0.0) || (fLat != 0.0)) - Modes.bUserFlags &= ~MODES_USER_LATLON_VALID; - if ((Modes.fUserLat != 0.0) || (Modes.fUserLon != 0.0)) { - Modes.bUserFlags |= MODES_USER_LATLON_VALID; - } - - // Limit the maximum requested raw output size to less than one Ethernet Block - if (Modes.net_output_raw_size > (MODES_RAWOUT_BUF_FLUSH)) - {Modes.net_output_raw_size = MODES_RAWOUT_BUF_FLUSH;} - if (Modes.net_output_raw_rate > (MODES_RAWOUT_BUF_RATE)) - {Modes.net_output_raw_rate = MODES_RAWOUT_BUF_RATE;} - if (Modes.net_sndbuf_size > (MODES_NET_SNDBUF_MAX)) - {Modes.net_sndbuf_size = MODES_NET_SNDBUF_MAX;} - - // Initialise the Block Timers to something half sensible - ftime(&Modes.stSystemTimeBlk); - for (i = 0; i < MODES_ASYNC_BUF_NUMBER; i++) - {Modes.stSystemTimeRTL[i] = Modes.stSystemTimeBlk;} - - // Each I and Q value varies from 0 to 255, which represents a range from -1 to +1. To get from the - // unsigned (0-255) range you therefore subtract 127 (or 128 or 127.5) from each I and Q, giving you - // a range from -127 to +128 (or -128 to +127, or -127.5 to +127.5).. - // - // To decode the AM signal, you need the magnitude of the waveform, which is given by sqrt((I^2)+(Q^2)) - // The most this could be is if I&Q are both 128 (or 127 or 127.5), so you could end up with a magnitude - // of 181.019 (or 179.605, or 180.312) - // - // However, in reality the magnitude of the signal should never exceed the range -1 to +1, because the - // values are I = rCos(w) and Q = rSin(w). Therefore the integer computed magnitude should (can?) never - // exceed 128 (or 127, or 127.5 or whatever) - // - // If we scale up the results so that they range from 0 to 65535 (16 bits) then we need to multiply - // by 511.99, (or 516.02 or 514). antirez's original code multiplies by 360, presumably because he's - // assuming the maximim calculated amplitude is 181.019, and (181.019 * 360) = 65166. - // - // So lets see if we can improve things by subtracting 127.5, Well in integer arithmatic we can't - // subtract half, so, we'll double everything up and subtract one, and then compensate for the doubling - // in the multiplier at the end. - // - // If we do this we can never have I or Q equal to 0 - they can only be as small as +/- 1. - // This gives us a minimum magnitude of root 2 (0.707), so the dynamic range becomes (1.414-255). This - // also affects our scaling value, which is now 65535/(255 - 1.414), or 258.433254 - // - // The sums then become mag = 258.433254 * (sqrt((I*2-255)^2 + (Q*2-255)^2) - 1.414) - // or mag = (258.433254 * sqrt((I*2-255)^2 + (Q*2-255)^2)) - 365.4798 - // - // We also need to clip mag just incaes any rogue I/Q values somehow do have a magnitude greater than 255. - // - - for (i = 0; i <= 255; i++) { - for (q = 0; q <= 255; q++) { - int mag, mag_i, mag_q; - - mag_i = (i * 2) - 255; - mag_q = (q * 2) - 255; - - mag = (int) round((sqrt((mag_i*mag_i)+(mag_q*mag_q)) * 258.433254) - 365.4798); - - Modes.maglut[(i*256)+q] = (uint16_t) ((mag < 65535) ? mag : 65535); - } - } - - // Prepare error correction tables - modesInitErrorInfo(); -} -// -// =============================== RTLSDR handling ========================== -// -void modesInitRTLSDR(void) { - int j; - int device_count; - char vendor[256], product[256], serial[256]; - - device_count = rtlsdr_get_device_count(); - if (!device_count) { - fprintf(stderr, "No supported RTLSDR devices found.\n"); - exit(1); - } - - fprintf(stderr, "Found %d device(s):\n", device_count); - for (j = 0; j < device_count; j++) { - rtlsdr_get_device_usb_strings(j, vendor, product, serial); - fprintf(stderr, "%d: %s, %s, SN: %s %s\n", j, vendor, product, serial, - (j == Modes.dev_index) ? "(currently selected)" : ""); - } - - if (rtlsdr_open(&Modes.dev, Modes.dev_index) < 0) { - fprintf(stderr, "Error opening the RTLSDR device: %s\n", - strerror(errno)); - exit(1); - } - - // Set gain, frequency, sample rate, and reset the device - rtlsdr_set_tuner_gain_mode(Modes.dev, - (Modes.gain == MODES_AUTO_GAIN) ? 0 : 1); - if (Modes.gain != MODES_AUTO_GAIN) { - if (Modes.gain == MODES_MAX_GAIN) { - // Find the maximum gain available - int numgains; - int gains[100]; - - numgains = rtlsdr_get_tuner_gains(Modes.dev, gains); - Modes.gain = gains[numgains-1]; - fprintf(stderr, "Max available gain is: %.2f\n", Modes.gain/10.0); - } - rtlsdr_set_tuner_gain(Modes.dev, Modes.gain); - fprintf(stderr, "Setting gain to: %.2f\n", Modes.gain/10.0); - } else { - fprintf(stderr, "Using automatic gain control.\n"); - } - rtlsdr_set_freq_correction(Modes.dev, Modes.ppm_error); - if (Modes.enable_agc) rtlsdr_set_agc_mode(Modes.dev, 1); - rtlsdr_set_center_freq(Modes.dev, Modes.freq); - rtlsdr_set_sample_rate(Modes.dev, MODES_DEFAULT_RATE); - rtlsdr_reset_buffer(Modes.dev); - fprintf(stderr, "Gain reported by device: %.2f\n", - rtlsdr_get_tuner_gain(Modes.dev)/10.0); -} -// -//========================================================================= -// -// We use a thread reading data in background, while the main thread -// handles decoding and visualization of data to the user. -// -// The reading thread calls the RTLSDR API to read data asynchronously, and -// uses a callback to populate the data buffer. -// -// A Mutex is used to avoid races with the decoding thread. -// -void rtlsdrCallback(unsigned char *buf, uint32_t len, void *ctx) { - - MODES_NOTUSED(ctx); - - // Lock the data buffer variables before accessing them - pthread_mutex_lock(&Modes.data_mutex); - - Modes.iDataIn &= (MODES_ASYNC_BUF_NUMBER-1); // Just incase!!! - - // Get the system time for this block - ftime(&Modes.stSystemTimeRTL[Modes.iDataIn]); - - if (len > MODES_ASYNC_BUF_SIZE) {len = MODES_ASYNC_BUF_SIZE;} - - // Queue the new data - Modes.pData[Modes.iDataIn] = (uint16_t *) buf; - Modes.iDataIn = (MODES_ASYNC_BUF_NUMBER-1) & (Modes.iDataIn + 1); - Modes.iDataReady = (MODES_ASYNC_BUF_NUMBER-1) & (Modes.iDataIn - Modes.iDataOut); - - if (Modes.iDataReady == 0) { - // Ooooops. We've just received the MODES_ASYNC_BUF_NUMBER'th outstanding buffer - // This means that RTLSDR is currently overwriting the MODES_ASYNC_BUF_NUMBER+1 - // buffer, but we havent yet processed it, so we're going to lose it. There - // isn't much we can do to recover the lost data, but we can correct things to - // avoid any additional problems. - Modes.iDataOut = (MODES_ASYNC_BUF_NUMBER-1) & (Modes.iDataOut+1); - Modes.iDataReady = (MODES_ASYNC_BUF_NUMBER-1); - Modes.iDataLost++; - } - - // Signal to the other thread that new data is ready, and unlock - pthread_cond_signal(&Modes.data_cond); - pthread_mutex_unlock(&Modes.data_mutex); -} -// -//========================================================================= -// -// This is used when --ifile is specified in order to read data from file -// instead of using an RTLSDR device -// -void readDataFromFile(void) { - pthread_mutex_lock(&Modes.data_mutex); - while(Modes.exit == 0) { - ssize_t nread, toread; - unsigned char *p; - - if (Modes.iDataReady) { - pthread_cond_wait(&Modes.data_cond, &Modes.data_mutex); - continue; - } - - if (Modes.interactive) { - // When --ifile and --interactive are used together, slow down - // playing at the natural rate of the RTLSDR received. - pthread_mutex_unlock(&Modes.data_mutex); - usleep(64000); - pthread_mutex_lock(&Modes.data_mutex); - } - - toread = MODES_ASYNC_BUF_SIZE; - p = (unsigned char *) Modes.pFileData; - while(toread) { - nread = read(Modes.fd, p, toread); - if (nread <= 0) { - Modes.exit = 1; // Signal the other threads to exit. - break; - } - p += nread; - toread -= nread; - } - if (toread) { - // Not enough data on file to fill the buffer? Pad with no signal. - memset(p,127,toread); - } - - Modes.iDataIn &= (MODES_ASYNC_BUF_NUMBER-1); // Just incase!!! - - // Get the system time for this block - ftime(&Modes.stSystemTimeRTL[Modes.iDataIn]); - - // Queue the new data - Modes.pData[Modes.iDataIn] = Modes.pFileData; - Modes.iDataIn = (MODES_ASYNC_BUF_NUMBER-1) & (Modes.iDataIn + 1); - Modes.iDataReady = (MODES_ASYNC_BUF_NUMBER-1) & (Modes.iDataIn - Modes.iDataOut); - - // Signal to the other thread that new data is ready - pthread_cond_signal(&Modes.data_cond); - } -} -// -//========================================================================= -// -// We read data using a thread, so the main thread only handles decoding -// without caring about data acquisition -// -void *readerThreadEntryPoint(void *arg) { - MODES_NOTUSED(arg); - - if (Modes.filename == NULL) { - rtlsdr_read_async(Modes.dev, rtlsdrCallback, NULL, - MODES_ASYNC_BUF_NUMBER, - MODES_ASYNC_BUF_SIZE); - } else { - readDataFromFile(); - } - // Signal to the other thread that new data is ready - dummy really so threads don't mutually lock - pthread_cond_signal(&Modes.data_cond); - pthread_mutex_unlock(&Modes.data_mutex); -#ifndef _WIN32 - pthread_exit(NULL); -#else - return NULL; -#endif -} -// -// ============================== Snip mode ================================= -// -// Get raw IQ samples and filter everything is < than the specified level -// for more than 256 samples in order to reduce example file size -// -void snipMode(int level) { - int i, q; - uint64_t c = 0; - - while ((i = getchar()) != EOF && (q = getchar()) != EOF) { - if (abs(i-127) < level && abs(q-127) < level) { - c++; - if (c > MODES_PREAMBLE_SIZE) continue; - } else { - c = 0; - } - putchar(i); - putchar(q); - } -} -// -// ================================ Main ==================================== -// -void showHelp(void) { - printf( -"-----------------------------------------------------------------------------\n" -"| dump1090 ModeS Receiver Ver : " MODES_DUMP1090_VERSION " |\n" -"-----------------------------------------------------------------------------\n" -"--device-index Select RTL device (default: 0)\n" -"--gain Set gain (default: max gain. Use -10 for auto-gain)\n" -"--enable-agc Enable the Automatic Gain Control (default: off)\n" -"--freq Set frequency (default: 1090 Mhz)\n" -"--ifile Read data from file (use '-' for stdin)\n" -"--interactive Interactive mode refreshing data on screen\n" -"--interactive-rows Max number of rows in interactive mode (default: 15)\n" -"--interactive-ttl Remove from list if idle for (default: 60)\n" -"--interactive-rtl1090 Display flight table in RTL1090 format\n" -"--raw Show only messages hex values\n" -"--net Enable networking\n" -"--modeac Enable decoding of SSR Modes 3/A & 3/C\n" -"--net-beast TCP raw output in Beast binary format\n" -"--net-only Enable just networking, no RTL device or file used\n" -"--net-bind-address IP address to bind to (default: Any; Use 127.0.0.1 for private)\n" -"--net-http-port HTTP server port (default: 8080)\n" -"--net-ri-port TCP raw input listen port (default: 30001)\n" -"--net-ro-port TCP raw output listen port (default: 30002)\n" -"--net-sbs-port TCP BaseStation output listen port (default: 30003)\n" -"--net-bi-port TCP Beast input listen port (default: 30004)\n" -"--net-bo-port TCP Beast output listen port (default: 30005)\n" -"--net-ro-size TCP raw output minimum size (default: 0)\n" -"--net-ro-rate TCP raw output memory flush rate (default: 0)\n" -"--net-heartbeat TCP heartbeat rate in seconds (default: 60 sec; 0 to disable)\n" -"--net-buffer TCP buffer size 64Kb * (2^n) (default: n=0, 64Kb)\n" -"--lat Reference/receiver latitude for surface posn (opt)\n" -"--lon Reference/receiver longitude for surface posn (opt)\n" -"--fix Enable single-bits error correction using CRC\n" -"--no-fix Disable single-bits error correction using CRC\n" -"--no-crc-check Disable messages with broken CRC (discouraged)\n" -"--phase-enhance Enable phase enhancement\n" -"--aggressive More CPU for more messages (two bits fixes, ...)\n" -"--mlat display raw messages in Beast ascii mode\n" -"--stats With --ifile print stats at exit. No other output\n" -"--stats-every Show and reset stats every seconds\n" -"--onlyaddr Show only ICAO addresses (testing purposes)\n" -"--metric Use metric units (meters, km/h, ...)\n" -"--snip Strip IQ file removing samples < level\n" -"--debug Debug mode (verbose), see README for details\n" -"--quiet Disable output to stdout. Use for daemon applications\n" -"--ppm Set receiver error in parts per million (default 0)\n" -"--help Show this help\n" -"\n" -"Debug mode flags: d = Log frames decoded with errors\n" -" D = Log frames decoded with zero errors\n" -" c = Log frames with bad CRC\n" -" C = Log frames with good CRC\n" -" p = Log frames with bad preamble\n" -" n = Log network debugging info\n" -" j = Log frames to frames.js, loadable by debug.html\n" - ); -} - -#ifdef _WIN32 -void showCopyright(void) { - uint64_t llTime = time(NULL) + 1; - - printf( -"-----------------------------------------------------------------------------\n" -"| dump1090 ModeS Receiver Ver : " MODES_DUMP1090_VERSION " |\n" -"-----------------------------------------------------------------------------\n" -"\n" -" Copyright (C) 2012 by Salvatore Sanfilippo \n" -" Copyright (C) 2014 by Malcolm Robb \n" -"\n" -" All rights reserved.\n" -"\n" -" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n" -" ""AS IS"" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n" -" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n" -" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n" -" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n" -" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n" -" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n" -" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n" -" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n" -" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n" -" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n" -"\n" -" For further details refer to \n" -"\n" - ); - - // delay for 1 second to give the user a chance to read the copyright - while (llTime >= time(NULL)) {} -} -#endif - - -static void display_stats(void) { - int j; - time_t now = time(NULL); - - printf("\n\n"); - if (Modes.interactive) - interactiveShowData(); - - printf("Statistics as at %s", ctime(&now)); - - printf("%d sample blocks processed\n", Modes.stat_blocks_processed); - printf("%d sample blocks dropped\n", Modes.stat_blocks_dropped); - - printf("%d ModeA/C detected\n", Modes.stat_ModeAC); - printf("%d valid Mode-S preambles\n", Modes.stat_valid_preamble); - printf("%d DF-?? fields corrected for length\n", Modes.stat_DF_Len_Corrected); - printf("%d DF-?? fields corrected for type\n", Modes.stat_DF_Type_Corrected); - printf("%d demodulated with 0 errors\n", Modes.stat_demodulated0); - printf("%d demodulated with 1 error\n", Modes.stat_demodulated1); - printf("%d demodulated with 2 errors\n", Modes.stat_demodulated2); - printf("%d demodulated with > 2 errors\n", Modes.stat_demodulated3); - printf("%d with good crc\n", Modes.stat_goodcrc); - printf("%d with bad crc\n", Modes.stat_badcrc); - printf("%d errors corrected\n", Modes.stat_fixed); - - for (j = 0; j < MODES_MAX_BITERRORS; j++) { - printf(" %d with %d bit %s\n", Modes.stat_bit_fix[j], j+1, (j==0)?"error":"errors"); - } - - if (Modes.phase_enhance) { - printf("%d phase enhancement attempts\n", Modes.stat_out_of_phase); - printf("%d phase enhanced demodulated with 0 errors\n", Modes.stat_ph_demodulated0); - printf("%d phase enhanced demodulated with 1 error\n", Modes.stat_ph_demodulated1); - printf("%d phase enhanced demodulated with 2 errors\n", Modes.stat_ph_demodulated2); - printf("%d phase enhanced demodulated with > 2 errors\n", Modes.stat_ph_demodulated3); - printf("%d phase enhanced with good crc\n", Modes.stat_ph_goodcrc); - printf("%d phase enhanced with bad crc\n", Modes.stat_ph_badcrc); - printf("%d phase enhanced errors corrected\n", Modes.stat_ph_fixed); - - for (j = 0; j < MODES_MAX_BITERRORS; j++) { - printf(" %d with %d bit %s\n", Modes.stat_ph_bit_fix[j], j+1, (j==0)?"error":"errors"); - } - } - - printf("%d total usable messages\n", Modes.stat_goodcrc + Modes.stat_ph_goodcrc + Modes.stat_fixed + Modes.stat_ph_fixed); - fflush(stdout); - - Modes.stat_blocks_processed = - Modes.stat_blocks_dropped = 0; - - Modes.stat_ModeAC = - Modes.stat_valid_preamble = - Modes.stat_DF_Len_Corrected = - Modes.stat_DF_Type_Corrected = - Modes.stat_demodulated0 = - Modes.stat_demodulated1 = - Modes.stat_demodulated2 = - Modes.stat_demodulated3 = - Modes.stat_goodcrc = - Modes.stat_badcrc = - Modes.stat_fixed = 0; - - Modes.stat_out_of_phase = - Modes.stat_ph_demodulated0 = - Modes.stat_ph_demodulated1 = - Modes.stat_ph_demodulated2 = - Modes.stat_ph_demodulated3 = - Modes.stat_ph_goodcrc = - Modes.stat_ph_badcrc = - Modes.stat_ph_fixed = 0; - - for (j = 0; j < MODES_MAX_BITERRORS; j++) { - Modes.stat_ph_bit_fix[j] = 0; - Modes.stat_bit_fix[j] = 0; - } -} - - -// -//========================================================================= -// -// This function is called a few times every second by main in order to -// perform tasks we need to do continuously, like accepting new clients -// from the net, refreshing the screen in interactive mode, and so forth -// -void backgroundTasks(void) { - static time_t next_stats; - - if (Modes.net) { - modesReadFromClients(); - } - - // If Modes.aircrafts is not NULL, remove any stale aircraft - if (Modes.aircrafts) { - interactiveRemoveStaleAircrafts(); - } - - // Refresh screen when in interactive mode - if (Modes.interactive) { - interactiveShowData(); - } - - if (Modes.stats > 0) { - time_t now = time(NULL); - if (now > next_stats) { - if (next_stats != 0) - display_stats(); - next_stats = now + Modes.stats; - } - } -} -// -//========================================================================= -// -int verbose_device_search(char *s) -{ - int i, device_count, device, offset; - char *s2; - char vendor[256], product[256], serial[256]; - device_count = rtlsdr_get_device_count(); - if (!device_count) { - fprintf(stderr, "No supported devices found.\n"); - return -1; - } - fprintf(stderr, "Found %d device(s):\n", device_count); - for (i = 0; i < device_count; i++) { - rtlsdr_get_device_usb_strings(i, vendor, product, serial); - fprintf(stderr, " %d: %s, %s, SN: %s\n", i, vendor, product, serial); - } - fprintf(stderr, "\n"); - /* does string look like raw id number */ - device = (int)strtol(s, &s2, 0); - if (s2[0] == '\0' && device >= 0 && device < device_count) { - fprintf(stderr, "Using device %d: %s\n", - device, rtlsdr_get_device_name((uint32_t)device)); - return device; - } - /* does string exact match a serial */ - for (i = 0; i < device_count; i++) { - rtlsdr_get_device_usb_strings(i, vendor, product, serial); - if (strcmp(s, serial) != 0) { - continue;} - device = i; - fprintf(stderr, "Using device %d: %s\n", - device, rtlsdr_get_device_name((uint32_t)device)); - return device; - } - /* does string prefix match a serial */ - for (i = 0; i < device_count; i++) { - rtlsdr_get_device_usb_strings(i, vendor, product, serial); - if (strncmp(s, serial, strlen(s)) != 0) { - continue;} - device = i; - fprintf(stderr, "Using device %d: %s\n", - device, rtlsdr_get_device_name((uint32_t)device)); - return device; - } - /* does string suffix match a serial */ - for (i = 0; i < device_count; i++) { - rtlsdr_get_device_usb_strings(i, vendor, product, serial); - offset = strlen(serial) - strlen(s); - if (offset < 0) { - continue;} - if (strncmp(s, serial+offset, strlen(s)) != 0) { - continue;} - device = i; - fprintf(stderr, "Using device %d: %s\n", - device, rtlsdr_get_device_name((uint32_t)device)); - return device; - } - fprintf(stderr, "No matching devices found.\n"); - return -1; -} -// -//========================================================================= -// -int main(int argc, char **argv) { - int j; - - // Set sane defaults - modesInitConfig(); - signal(SIGINT, sigintHandler); // Define Ctrl/C handler (exit program) - - // Parse the command line options - for (j = 1; j < argc; j++) { - int more = j+1 < argc; // There are more arguments - - if (!strcmp(argv[j],"--device-index") && more) { - Modes.dev_index = verbose_device_search(argv[++j]); - } else if (!strcmp(argv[j],"--gain") && more) { - Modes.gain = (int) (atof(argv[++j])*10); // Gain is in tens of DBs - } else if (!strcmp(argv[j],"--enable-agc")) { - Modes.enable_agc++; - } else if (!strcmp(argv[j],"--freq") && more) { - Modes.freq = (int) strtoll(argv[++j],NULL,10); - } else if (!strcmp(argv[j],"--ifile") && more) { - Modes.filename = strdup(argv[++j]); - } else if (!strcmp(argv[j],"--fix")) { - Modes.nfix_crc = 1; - } else if (!strcmp(argv[j],"--no-fix")) { - Modes.nfix_crc = 0; - } else if (!strcmp(argv[j],"--no-crc-check")) { - Modes.check_crc = 0; - } else if (!strcmp(argv[j],"--phase-enhance")) { - Modes.phase_enhance = 1; - } else if (!strcmp(argv[j],"--raw")) { - Modes.raw = 1; - } else if (!strcmp(argv[j],"--net")) { - Modes.net = 1; - } else if (!strcmp(argv[j],"--modeac")) { - Modes.mode_ac = 1; - } else if (!strcmp(argv[j],"--net-beast")) { - Modes.beast = 1; - } else if (!strcmp(argv[j],"--net-only")) { - Modes.net = 1; - Modes.net_only = 1; - } else if (!strcmp(argv[j],"--net-heartbeat") && more) { - Modes.net_heartbeat_rate = atoi(argv[++j]) * 15; - } else if (!strcmp(argv[j],"--net-ro-size") && more) { - Modes.net_output_raw_size = atoi(argv[++j]); - } else if (!strcmp(argv[j],"--net-ro-rate") && more) { - Modes.net_output_raw_rate = atoi(argv[++j]); - } else if (!strcmp(argv[j],"--net-ro-port") && more) { - if (Modes.beast) // Required for legacy backward compatibility - {Modes.net_output_beast_port = atoi(argv[++j]);;} - else - {Modes.net_output_raw_port = atoi(argv[++j]);} - } else if (!strcmp(argv[j],"--net-ri-port") && more) { - Modes.net_input_raw_port = atoi(argv[++j]); - } else if (!strcmp(argv[j],"--net-bo-port") && more) { - Modes.net_output_beast_port = atoi(argv[++j]); - } else if (!strcmp(argv[j],"--net-bi-port") && more) { - Modes.net_input_beast_port = atoi(argv[++j]); - } else if (!strcmp(argv[j],"--net-bind-address") && more) { - Modes.net_bind_address = strdup(argv[++j]); - } else if (!strcmp(argv[j],"--net-http-port") && more) { - Modes.net_http_port = atoi(argv[++j]); - } else if (!strcmp(argv[j],"--net-sbs-port") && more) { - Modes.net_output_sbs_port = atoi(argv[++j]); - } else if (!strcmp(argv[j],"--net-buffer") && more) { - Modes.net_sndbuf_size = atoi(argv[++j]); - } else if (!strcmp(argv[j],"--onlyaddr")) { - Modes.onlyaddr = 1; - } else if (!strcmp(argv[j],"--metric")) { - Modes.metric = 1; - } else if (!strcmp(argv[j],"--aggressive")) { - Modes.nfix_crc = MODES_MAX_BITERRORS; - } else if (!strcmp(argv[j],"--interactive")) { - Modes.interactive = 1; - } else if (!strcmp(argv[j],"--interactive-rows") && more) { - Modes.interactive_rows = atoi(argv[++j]); - } else if (!strcmp(argv[j],"--interactive-ttl") && more) { - Modes.interactive_display_ttl = atoi(argv[++j]); - } else if (!strcmp(argv[j],"--lat") && more) { - Modes.fUserLat = atof(argv[++j]); - } else if (!strcmp(argv[j],"--lon") && more) { - Modes.fUserLon = atof(argv[++j]); - } else if (!strcmp(argv[j],"--debug") && more) { - char *f = argv[++j]; - while(*f) { - switch(*f) { - case 'D': Modes.debug |= MODES_DEBUG_DEMOD; break; - case 'd': Modes.debug |= MODES_DEBUG_DEMODERR; break; - case 'C': Modes.debug |= MODES_DEBUG_GOODCRC; break; - case 'c': Modes.debug |= MODES_DEBUG_BADCRC; break; - case 'p': Modes.debug |= MODES_DEBUG_NOPREAMBLE; break; - case 'n': Modes.debug |= MODES_DEBUG_NET; break; - case 'j': Modes.debug |= MODES_DEBUG_JS; break; - default: - fprintf(stderr, "Unknown debugging flag: %c\n", *f); - exit(1); - break; - } - f++; - } - } else if (!strcmp(argv[j],"--stats")) { - Modes.stats = -1; - } else if (!strcmp(argv[j],"--stats-every") && more) { - Modes.stats = atoi(argv[++j]); - } else if (!strcmp(argv[j],"--snip") && more) { - snipMode(atoi(argv[++j])); - exit(0); - } else if (!strcmp(argv[j],"--help")) { - showHelp(); - exit(0); - } else if (!strcmp(argv[j],"--ppm") && more) { - Modes.ppm_error = atoi(argv[++j]); - } else if (!strcmp(argv[j],"--quiet")) { - Modes.quiet = 1; - } else if (!strcmp(argv[j],"--mlat")) { - Modes.mlat = 1; - } else if (!strcmp(argv[j],"--interactive-rtl1090")) { - Modes.interactive = 1; - Modes.interactive_rtl1090 = 1; - } else { - fprintf(stderr, - "Unknown or not enough arguments for option '%s'.\n\n", - argv[j]); - showHelp(); - exit(1); - } - } - -#ifdef _WIN32 - // Try to comply with the Copyright license conditions for binary distribution - if (!Modes.quiet) {showCopyright();} -#endif - -#ifndef _WIN32 - // Setup for SIGWINCH for handling lines - if (Modes.interactive) {signal(SIGWINCH, sigWinchCallback);} -#endif - - // Initialization - modesInit(); - - if (Modes.net_only) { - fprintf(stderr,"Net-only mode, no RTL device or file open.\n"); - } else if (Modes.filename == NULL) { - modesInitRTLSDR(); - } else { - if (Modes.filename[0] == '-' && Modes.filename[1] == '\0') { - Modes.fd = STDIN_FILENO; - } else if ((Modes.fd = open(Modes.filename, -#ifdef _WIN32 - (O_RDONLY | O_BINARY) -#else - (O_RDONLY) -#endif - )) == -1) { - perror("Opening data file"); - exit(1); - } - } - if (Modes.net) modesInitNet(); - - // If the user specifies --net-only, just run in order to serve network - // clients without reading data from the RTL device - while (Modes.net_only) { - if (Modes.exit) exit(0); // If we exit net_only nothing further in main() - backgroundTasks(); - usleep(100000); - } - - // Create the thread that will read the data from the device. - pthread_create(&Modes.reader_thread, NULL, readerThreadEntryPoint, NULL); - pthread_mutex_lock(&Modes.data_mutex); - - while (Modes.exit == 0) { - - if (Modes.iDataReady == 0) { - pthread_cond_wait(&Modes.data_cond,&Modes.data_mutex); // This unlocks Modes.data_mutex, and waits for Modes.data_cond - continue; // Once (Modes.data_cond) occurs, it locks Modes.data_mutex - } - - // Modes.data_mutex is Locked, and (Modes.iDataReady != 0) - if (Modes.iDataReady) { // Check we have new data, just in case!! - - Modes.iDataOut &= (MODES_ASYNC_BUF_NUMBER-1); // Just incase - - // Translate the next lot of I/Q samples into Modes.magnitude - computeMagnitudeVector(Modes.pData[Modes.iDataOut]); - - Modes.stSystemTimeBlk = Modes.stSystemTimeRTL[Modes.iDataOut]; - - // Update the input buffer pointer queue - Modes.iDataOut = (MODES_ASYNC_BUF_NUMBER-1) & (Modes.iDataOut + 1); - Modes.iDataReady = (MODES_ASYNC_BUF_NUMBER-1) & (Modes.iDataIn - Modes.iDataOut); - - // If we lost some blocks, correct the timestamp - if (Modes.iDataLost) { - Modes.timestampBlk += (MODES_ASYNC_BUF_SAMPLES * 6 * Modes.iDataLost); - Modes.stat_blocks_dropped += Modes.iDataLost; - Modes.iDataLost = 0; - } - - // It's safe to release the lock now - pthread_cond_signal (&Modes.data_cond); - pthread_mutex_unlock(&Modes.data_mutex); - - // Process data after releasing the lock, so that the capturing - // thread can read data while we perform computationally expensive - // stuff at the same time. - detectModeS(Modes.magnitude, MODES_ASYNC_BUF_SAMPLES); - - // Update the timestamp ready for the next block - Modes.timestampBlk += (MODES_ASYNC_BUF_SAMPLES*6); - Modes.stat_blocks_processed++; - } else { - pthread_cond_signal (&Modes.data_cond); - pthread_mutex_unlock(&Modes.data_mutex); - } - - backgroundTasks(); - pthread_mutex_lock(&Modes.data_mutex); - } - - // If --stats were given, print statistics - if (Modes.stats) { - display_stats(); - } - - if (Modes.filename == NULL) { - rtlsdr_cancel_async(Modes.dev); // Cancel rtlsdr_read_async will cause data input thread to terminate cleanly - rtlsdr_close(Modes.dev); - } - pthread_cond_destroy(&Modes.data_cond); // Thread cleanup - pthread_mutex_destroy(&Modes.data_mutex); - pthread_join(Modes.reader_thread,NULL); // Wait on reader thread exit -#ifndef _WIN32 - pthread_exit(0); -#else - return (0); -#endif -} -// -//========================================================================= -// diff --git a/dump1090.dsp b/dump1090.dsp deleted file mode 100644 index 6bd819b18..000000000 --- a/dump1090.dsp +++ /dev/null @@ -1,152 +0,0 @@ -# Microsoft Developer Studio Project File - Name="dump1090" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -CFG=dump1090 - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "dump1090.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "dump1090.mak" CFG="dump1090 - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "dump1090 - Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "dump1090 - Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "dump1090 - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release" -# PROP Intermediate_Dir "Release" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c -# ADD CPP /nologo /W3 /GX /O2 /I ".\pthreads\." /I ".\rtlsdr\." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FR /FD /c -# SUBTRACT CPP /YX /Yc /Yu -# ADD BASE RSC /l 0x809 /d "NDEBUG" -# ADD RSC /l 0x809 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 ws2_32.lib /nologo /subsystem:console /machine:I386 /out:"./dump1090.exe" - -!ELSEIF "$(CFG)" == "dump1090 - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Debug" -# PROP Intermediate_Dir "Debug" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c -# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I ".\pthreads\." /I ".\rtlsdr\." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c -# SUBTRACT CPP /YX /Yc /Yu -# ADD BASE RSC /l 0x809 /d "_DEBUG" -# ADD RSC /l 0x809 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept - -!ENDIF - -# Begin Target - -# Name "dump1090 - Win32 Release" -# Name "dump1090 - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# Begin Source File - -SOURCE=.\anet.c -# End Source File -# Begin Source File - -SOURCE=.\dump1090.c -# End Source File -# Begin Source File - -SOURCE=.\interactive.c -# End Source File -# Begin Source File - -SOURCE=.\mode_ac.c -# End Source File -# Begin Source File - -SOURCE=.\mode_s.c -# End Source File -# Begin Source File - -SOURCE=.\net_io.c -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hpp;hxx;hm;inl" -# Begin Source File - -SOURCE=.\anet.h -# End Source File -# Begin Source File - -SOURCE=.\dump1090.h -# End Source File -# Begin Source File - -SOURCE=.\winstubs.h -# End Source File -# End Group -# Begin Group "Resource Files" - -# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" -# Begin Source File - -SOURCE=.\Dump1090.rc -# End Source File -# End Group -# Begin Group "Library Files" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\pthreads\pthreadVC2.lib -# End Source File -# Begin Source File - -SOURCE=.\rtlsdr\rtlsdr.lib -# End Source File -# End Group -# End Target -# End Project diff --git a/dump1090.dsw b/dump1090.dsw deleted file mode 100644 index c29f0f19e..000000000 --- a/dump1090.dsw +++ /dev/null @@ -1,41 +0,0 @@ -Microsoft Developer Studio Workspace File, Format Version 6.00 -# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! - -############################################################################### - -Project: "dump1090"=.\dump1090.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Project: "view1090"=.\view1090.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Global: - -Package=<5> -{{{ -}}} - -Package=<3> -{{{ -}}} - -############################################################################### - diff --git a/dump1090.h b/dump1090.h deleted file mode 100644 index 9ad4de037..000000000 --- a/dump1090.h +++ /dev/null @@ -1,466 +0,0 @@ -// dump1090, a Mode S messages decoder for RTLSDR devices. -// -// Copyright (C) 2012 by Salvatore Sanfilippo -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -#ifndef __DUMP1090_H -#define __DUMP1090_H - -// File Version number -// ==================== -// Format is : MajorVer.MinorVer.DayMonth.Year" -// MajorVer changes only with significant changes -// MinorVer changes when additional features are added, but not for bug fixes (range 00-99) -// DayDate & Year changes for all changes, including for bug fixes. It represent the release date of the update -// -#define MODES_DUMP1090_VERSION "1.10.3010.14" - -// ============================= Include files ========================== - -#ifndef _WIN32 - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include "rtl-sdr.h" - #include "anet.h" -#else - #include "winstubs.h" //Put everything Windows specific in here - #include "rtl-sdr.h" - #include "anet.h" -#endif - -// ============================= #defines =============================== -// -// If you have a valid coaa.h, these values will come from it. If not, -// then you can enter your own values in the #else section here -// -#ifdef USER_LATITUDE - #define MODES_USER_LATITUDE_DFLT (USER_LATITUDE) - #define MODES_USER_LONGITUDE_DFLT (USER_LONGITUDE) -#else - #define MODES_USER_LATITUDE_DFLT (0.0) - #define MODES_USER_LONGITUDE_DFLT (0.0) -#endif - -#define MODES_DEFAULT_PPM 52 -#define MODES_DEFAULT_RATE 2000000 -#define MODES_DEFAULT_FREQ 1090000000 -#define MODES_DEFAULT_WIDTH 1000 -#define MODES_DEFAULT_HEIGHT 700 -#define MODES_ASYNC_BUF_NUMBER 16 -#define MODES_ASYNC_BUF_SIZE (16*16384) // 256k -#define MODES_ASYNC_BUF_SAMPLES (MODES_ASYNC_BUF_SIZE / 2) // Each sample is 2 bytes -#define MODES_AUTO_GAIN -100 // Use automatic gain -#define MODES_MAX_GAIN 999999 // Use max available gain -#define MODES_MSG_SQUELCH_LEVEL 0x02FF // Average signal strength limit -#define MODES_MSG_ENCODER_ERRS 3 // Maximum number of encoding errors - -// When changing, change also fixBitErrors() and modesInitErrorTable() !! -#define MODES_MAX_BITERRORS 2 // Global max for fixable bit erros - -#define MODEAC_MSG_SAMPLES (25 * 2) // include up to the SPI bit -#define MODEAC_MSG_BYTES 2 -#define MODEAC_MSG_SQUELCH_LEVEL 0x07FF // Average signal strength limit -#define MODEAC_MSG_FLAG (1<<0) -#define MODEAC_MSG_MODES_HIT (1<<1) -#define MODEAC_MSG_MODEA_HIT (1<<2) -#define MODEAC_MSG_MODEC_HIT (1<<3) -#define MODEAC_MSG_MODEA_ONLY (1<<4) -#define MODEAC_MSG_MODEC_OLD (1<<5) - -#define MODES_PREAMBLE_US 8 // microseconds = bits -#define MODES_PREAMBLE_SAMPLES (MODES_PREAMBLE_US * 2) -#define MODES_PREAMBLE_SIZE (MODES_PREAMBLE_SAMPLES * sizeof(uint16_t)) -#define MODES_LONG_MSG_BYTES 14 -#define MODES_SHORT_MSG_BYTES 7 -#define MODES_LONG_MSG_BITS (MODES_LONG_MSG_BYTES * 8) -#define MODES_SHORT_MSG_BITS (MODES_SHORT_MSG_BYTES * 8) -#define MODES_LONG_MSG_SAMPLES (MODES_LONG_MSG_BITS * 2) -#define MODES_SHORT_MSG_SAMPLES (MODES_SHORT_MSG_BITS * 2) -#define MODES_LONG_MSG_SIZE (MODES_LONG_MSG_SAMPLES * sizeof(uint16_t)) -#define MODES_SHORT_MSG_SIZE (MODES_SHORT_MSG_SAMPLES * sizeof(uint16_t)) - -#define MODES_RAWOUT_BUF_SIZE (1500) -#define MODES_RAWOUT_BUF_FLUSH (MODES_RAWOUT_BUF_SIZE - 200) -#define MODES_RAWOUT_BUF_RATE (1000) // 1000 * 64mS = 1 Min approx - -#define MODES_ICAO_CACHE_LEN 1024 // Power of two required -#define MODES_ICAO_CACHE_TTL 60 // Time to live of cached addresses -#define MODES_UNIT_FEET 0 -#define MODES_UNIT_METERS 1 - -#define MODES_USER_LATLON_VALID (1<<0) - -#define MODES_ACFLAGS_LATLON_VALID (1<<0) // Aircraft Lat/Lon is decoded -#define MODES_ACFLAGS_ALTITUDE_VALID (1<<1) // Aircraft altitude is known -#define MODES_ACFLAGS_HEADING_VALID (1<<2) // Aircraft heading is known -#define MODES_ACFLAGS_SPEED_VALID (1<<3) // Aircraft speed is known -#define MODES_ACFLAGS_VERTRATE_VALID (1<<4) // Aircraft vertical rate is known -#define MODES_ACFLAGS_SQUAWK_VALID (1<<5) // Aircraft Mode A Squawk is known -#define MODES_ACFLAGS_CALLSIGN_VALID (1<<6) // Aircraft Callsign Identity -#define MODES_ACFLAGS_EWSPEED_VALID (1<<7) // Aircraft East West Speed is known -#define MODES_ACFLAGS_NSSPEED_VALID (1<<8) // Aircraft North South Speed is known -#define MODES_ACFLAGS_AOG (1<<9) // Aircraft is On the Ground -#define MODES_ACFLAGS_LLEVEN_VALID (1<<10) // Aircraft Even Lot/Lon is known -#define MODES_ACFLAGS_LLODD_VALID (1<<11) // Aircraft Odd Lot/Lon is known -#define MODES_ACFLAGS_AOG_VALID (1<<12) // MODES_ACFLAGS_AOG is valid -#define MODES_ACFLAGS_FS_VALID (1<<13) // Aircraft Flight Status is known -#define MODES_ACFLAGS_NSEWSPD_VALID (1<<14) // Aircraft EW and NS Speed is known -#define MODES_ACFLAGS_LATLON_REL_OK (1<<15) // Indicates it's OK to do a relative CPR - -#define MODES_ACFLAGS_LLEITHER_VALID (MODES_ACFLAGS_LLEVEN_VALID | MODES_ACFLAGS_LLODD_VALID) -#define MODES_ACFLAGS_LLBOTH_VALID (MODES_ACFLAGS_LLEVEN_VALID | MODES_ACFLAGS_LLODD_VALID) -#define MODES_ACFLAGS_AOG_GROUND (MODES_ACFLAGS_AOG_VALID | MODES_ACFLAGS_AOG) - -#define MODES_DEBUG_DEMOD (1<<0) -#define MODES_DEBUG_DEMODERR (1<<1) -#define MODES_DEBUG_BADCRC (1<<2) -#define MODES_DEBUG_GOODCRC (1<<3) -#define MODES_DEBUG_NOPREAMBLE (1<<4) -#define MODES_DEBUG_NET (1<<5) -#define MODES_DEBUG_JS (1<<6) - -// When debug is set to MODES_DEBUG_NOPREAMBLE, the first sample must be -// at least greater than a given level for us to dump the signal. -#define MODES_DEBUG_NOPREAMBLE_LEVEL 25 - -#define MODES_INTERACTIVE_REFRESH_TIME 250 // Milliseconds -#define MODES_INTERACTIVE_ROWS 22 // Rows on screen -#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_NET_HEARTBEAT_RATE 900 // Each block is approx 65mS - default is > 1 min - -#define MODES_NET_SERVICES_NUM 6 -#define MODES_NET_INPUT_RAW_PORT 30001 -#define MODES_NET_OUTPUT_RAW_PORT 30002 -#define MODES_NET_OUTPUT_SBS_PORT 30003 -#define MODES_NET_INPUT_BEAST_PORT 30004 -#define MODES_NET_OUTPUT_BEAST_PORT 30005 -#define MODES_NET_HTTP_PORT 8080 -#define MODES_CLIENT_BUF_SIZE 1024 -#define MODES_NET_SNDBUF_SIZE (1024*64) -#define MODES_NET_SNDBUF_MAX (7) - -#ifndef HTMLPATH -#define HTMLPATH "./public_html" // default path for gmap.html etc -#endif - -#define MODES_NOTUSED(V) ((void) V) - -//======================== structure declarations ========================= - -// Structure used to describe a networking client -struct client { - struct client* next; // Pointer to next client - int fd; // File descriptor - int service; // TCP port the client is connected to - int buflen; // Amount of data on buffer - char buf[MODES_CLIENT_BUF_SIZE+1]; // Read buffer -}; - -// Structure used to describe an aircraft in iteractive mode -struct aircraft { - uint32_t addr; // ICAO address - char flight[16]; // Flight number - unsigned char signalLevel[8]; // Last 8 Signal Amplitudes - 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 - 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 timestampLatLon;// Timestamp at which the last lat long was calculated - long messages; // Number of Mode S messages received - int modeA; // Squawk - int modeC; // Altitude - long modeAcount; // Mode A Squawk hit Count - long modeCcount; // Mode C Altitude hit Count - int modeACflags; // Flags for mode A/C recognition - - // Encoded latitude and longitude as extracted by odd and even CPR encoded messages - int odd_cprlat; - int odd_cprlon; - int even_cprlat; - int even_cprlon; - uint64_t odd_cprtime; - uint64_t even_cprtime; - double lat, lon; // Coordinated obtained from CPR encoded data - int bFlags; // Flags related to valid fields in this structure - struct aircraft *next; // Next aircraft in our linked list -}; - -struct stDF { - struct stDF *pNext; // Pointer to next item in the linked list - struct stDF *pPrev; // Pointer to previous item in the linked list - struct aircraft *pAircraft; // Pointer to the Aircraft structure for this DF - time_t seen; // Dos/UNIX Time at which the this packet was received - uint64_t llTimestamp; // Timestamp at which the this packet was received - uint32_t addr; // Timestamp at which the this packet was received - unsigned char msg[MODES_LONG_MSG_BYTES]; // the binary -} tDF; - -// Program global state -struct { // Internal state - pthread_t reader_thread; - - pthread_mutex_t data_mutex; // Mutex to synchronize buffer access - pthread_cond_t data_cond; // Conditional variable associated - uint16_t *pData [MODES_ASYNC_BUF_NUMBER]; // Raw IQ sample buffers from RTL - struct timeb stSystemTimeRTL[MODES_ASYNC_BUF_NUMBER]; // System time when RTL passed us this block - int iDataIn; // Fifo input pointer - int iDataOut; // Fifo output pointer - int iDataReady; // Fifo content count - int iDataLost; // Count of missed buffers - - uint16_t *pFileData; // Raw IQ samples buffer (from a File) - uint16_t *magnitude; // Magnitude vector - uint64_t timestampBlk; // Timestamp of the start of the current block - struct timeb stSystemTimeBlk; // System time when RTL passed us currently processing this block - int fd; // --ifile option file descriptor - uint32_t *icao_cache; // Recently seen ICAO addresses cache - uint16_t *maglut; // I/Q -> Magnitude lookup table - int exit; // Exit from the main loop when true - - // RTLSDR - int dev_index; - int gain; - int enable_agc; - rtlsdr_dev_t *dev; - int freq; - int ppm_error; - - // Networking - char aneterr[ANET_ERR_LEN]; - struct client *clients; // Our clients - int sbsos; // SBS output listening socket - int ros; // Raw output listening socket - int ris; // Raw input listening socket - int bos; // Beast output listening socket - int bis; // Beast input listening socket - int https; // HTTP listening socket - char *rawOut; // Buffer for building raw output data - int rawOutUsed; // How much of the buffer is currently used - char *beastOut; // Buffer for building beast output data - int beastOutUsed; // How much if the buffer is currently used -#ifdef _WIN32 - WSADATA wsaData; // Windows socket initialisation -#endif - - // Configuration - char *filename; // Input form file, --ifile option - int phase_enhance; // Enable phase enhancement if true - int nfix_crc; // Number of crc bit error(s) to correct - int check_crc; // Only display messages with good CRC - int raw; // Raw output format - int beast; // Beast binary format output - int mode_ac; // Enable decoding of SSR Modes A & C - int debug; // Debugging mode - int net; // Enable networking - int net_only; // Enable just networking - int net_heartbeat_count; // TCP heartbeat counter - int net_heartbeat_rate; // TCP heartbeat rate - int net_output_sbs_port; // SBS output TCP port - int net_output_raw_size; // Minimum Size of the output raw data - int net_output_raw_rate; // Rate (in 64mS increments) of output raw data - int net_output_raw_rate_count; // Rate (in 64mS increments) of output raw data - int net_output_raw_port; // Raw output TCP port - int net_input_raw_port; // Raw input TCP port - int net_output_beast_port; // Beast output TCP port - int net_input_beast_port; // Beast input TCP port - char *net_bind_address; // Bind address - int net_http_port; // HTTP port - int net_sndbuf_size; // TCP output buffer size (64Kb * 2^n) - int quiet; // Suppress stdout - int interactive; // Interactive mode - int interactive_rows; // Interactive mode: max number of rows - int interactive_display_ttl; // Interactive mode: TTL display - int interactive_delete_ttl; // Interactive mode: TTL before deletion - int stats; // Print stats at exit in --ifile mode - int onlyaddr; // Print only ICAO addresses - int metric; // Use metric units - 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 - - // User details - double fUserLat; // Users receiver/antenna lat/lon needed for initial surface location - double fUserLon; // Users receiver/antenna lat/lon needed for initial surface location - int bUserFlags; // Flags relating to the user details - - // Interactive mode - struct aircraft *aircrafts; - uint64_t interactive_last_update; // Last screen update in milliseconds - time_t last_cleanup_time; // Last cleanup time in seconds - - // DF List mode - int bEnableDFLogging; // Set to enable DF Logging - pthread_mutex_t pDF_mutex; // Mutex to synchronize pDF access - struct stDF *pDF; // Pointer to DF list - - // Statistics - unsigned int stat_valid_preamble; - unsigned int stat_demodulated0; - unsigned int stat_demodulated1; - unsigned int stat_demodulated2; - unsigned int stat_demodulated3; - unsigned int stat_goodcrc; - unsigned int stat_badcrc; - unsigned int stat_fixed; - - // Histogram of fixed bit errors: index 0 for single bit erros, - // index 1 for double bit errors etc. - unsigned int stat_bit_fix[MODES_MAX_BITERRORS]; - - unsigned int stat_http_requests; - unsigned int stat_sbs_connections; - unsigned int stat_raw_connections; - unsigned int stat_beast_connections; - unsigned int stat_out_of_phase; - unsigned int stat_ph_demodulated0; - unsigned int stat_ph_demodulated1; - unsigned int stat_ph_demodulated2; - unsigned int stat_ph_demodulated3; - unsigned int stat_ph_goodcrc; - unsigned int stat_ph_badcrc; - unsigned int stat_ph_fixed; - // Histogram of fixed bit errors: index 0 for single bit erros, - // index 1 for double bit errors etc. - unsigned int stat_ph_bit_fix[MODES_MAX_BITERRORS]; - - unsigned int stat_DF_Len_Corrected; - unsigned int stat_DF_Type_Corrected; - unsigned int stat_ModeAC; - - unsigned int stat_blocks_processed; - unsigned int stat_blocks_dropped; -} Modes; - -// The struct we use to store information about a decoded message. -struct modesMessage { - // Generic fields - unsigned char msg[MODES_LONG_MSG_BYTES]; // Binary message. - int msgbits; // Number of bits in message - int msgtype; // Downlink format # - int crcok; // True if CRC was valid - uint32_t crc; // Message CRC - int correctedbits; // No. of bits corrected - char corrected[MODES_MAX_BITERRORS]; // corrected bit positions - uint32_t addr; // ICAO Address from bytes 1 2 and 3 - int phase_corrected; // True if phase correction was applied - uint64_t timestampMsg; // Timestamp of the message - int remote; // If set this message is from a remote station - unsigned char signalLevel; // Signal Amplitude - - // DF 11 - int ca; // Responder capabilities - int iid; - - // DF 17, DF 18 - int metype; // Extended squitter message type. - int mesub; // Extended squitter message subtype. - int heading; // Reported by aircraft, or computed from from EW and NS velocity - int raw_latitude; // Non decoded latitude. - int raw_longitude; // Non decoded longitude. - double fLat; // Coordinates obtained from CPR encoded data if/when decoded - double fLon; // Coordinates obtained from CPR encoded data if/when decoded - char flight[16]; // 8 chars flight number. - int ew_velocity; // E/W velocity. - int ns_velocity; // N/S velocity. - int vert_rate; // Vertical rate. - int velocity; // Reported by aircraft, or computed from from EW and NS velocity - - // DF4, DF5, DF20, DF21 - int fs; // Flight status for DF4,5,20,21 - int modeA; // 13 bits identity (Squawk). - - // Fields used by multiple message types. - int altitude; - int unit; - int bFlags; // Flags related to fields in this structure -}; - -// ======================== function declarations ========================= - -#ifdef __cplusplus -extern "C" { -#endif - -// -// Functions exported from mode_ac.c -// -int detectModeA (uint16_t *m, struct modesMessage *mm); -void decodeModeAMessage(struct modesMessage *mm, int ModeA); -int ModeAToModeC (unsigned int ModeA); - -// -// Functions exported from mode_s.c -// -void detectModeS (uint16_t *m, uint32_t mlen); -void decodeModesMessage (struct modesMessage *mm, unsigned char *msg); -void displayModesMessage(struct modesMessage *mm); -void useModesMessage (struct modesMessage *mm); -void computeMagnitudeVector(uint16_t *pData); -int decodeCPR (struct aircraft *a, int fflag, int surface); -int decodeCPRrelative (struct aircraft *a, int fflag, int surface); -void modesInitErrorInfo (); -// -// Functions exported from interactive.c -// -struct aircraft* interactiveReceiveData(struct modesMessage *mm); -void interactiveShowData(void); -void interactiveRemoveStaleAircrafts(void); -int decodeBinMessage (struct client *c, char *p); -struct aircraft *interactiveFindAircraft(uint32_t addr); -struct stDF *interactiveFindDF (uint32_t addr); - -// -// Functions exported from net_io.c -// -void modesInitNet (void); -void modesReadFromClients (void); -void modesSendAllClients (int service, void *msg, int len); -void modesQueueOutput (struct modesMessage *mm); -void modesReadFromClient(struct client *c, char *sep, int(*handler)(struct client *, char *)); - -#ifdef __cplusplus -} -#endif - -#endif // __DUMP1090_H diff --git a/dump1090.rc b/dump1090.rc deleted file mode 100644 index bde02275d..000000000 --- a/dump1090.rc +++ /dev/null @@ -1,115 +0,0 @@ -//Microsoft Developer Studio generated resource script. -// -#include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#define APSTUDIO_HIDDEN_SYMBOLS -#include "windows.h" -#undef APSTUDIO_HIDDEN_SYMBOLS -#include "ntverp.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// English (U.S.) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -#ifdef _WIN32 -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US -#pragma code_page(1252) -#endif //_WIN32 - -#ifndef _MAC -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,10,2910,14 - PRODUCTVERSION 1,10,2910,14 - FILEFLAGSMASK 0x3fL -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x40004L - FILETYPE 0x3L - FILESUBTYPE 0x7L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904b0" - BEGIN - VALUE "Comments", "Dump1090 for Win32 \0" - VALUE "CompanyName", "\0" - VALUE "FileDescription", "Mode A/C/S decoder for RTL Dongles\0" - VALUE "FileVersion", "1, 10, 2910, 14\0" - VALUE "InternalName", "DUMP1090.EXE\0" - VALUE "LegalCopyright", "Copyright © 2012 by Salvatore Sanfilippo \r\nCopyright © 2014 by Malcolm Robb \0" - VALUE "LegalTrademarks", "\0" - VALUE "OriginalFilename", "DUMP1090.EXE\0" - VALUE "PrivateBuild", "\0" - VALUE "ProductName", "DUMP1090\0" - VALUE "ProductVersion", "1, 10, 2910, 14\0" - VALUE "SpecialBuild", "\0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1200 - END -END - -#endif // !_MAC - - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE DISCARDABLE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE DISCARDABLE -BEGIN - "#define APSTUDIO_HIDDEN_SYMBOLS\r\n" - "#include ""windows.h""\r\n" - "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n" - "#include ""ntverp.h""\r\n" - "\0" -END - -3 TEXTINCLUDE DISCARDABLE -BEGIN - "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - -#endif // English (U.S.) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - diff --git a/dump1090.sh b/dump1090.sh deleted file mode 100644 index d1b63e515..000000000 --- a/dump1090.sh +++ /dev/null @@ -1,74 +0,0 @@ -#!/bin/bash -### BEGIN INIT INFO -# -# Provides: dump1090 -# Required-Start: $remote_fs -# Required-Stop: $remote_fs -# Default-Start: 2 3 4 5 -# Default-Stop: 0 1 6 -# Short-Description: dump1090 initscript - -# -### END INIT INFO -## Fill in name of program here. -PROG="dump1090" -PROG_PATH="/home/pi/dump1090" -PROG_ARGS="--quiet --net --net-ro-size 500 --net-ro-rate 5 --net-buffer 5" -PIDFILE="/var/run/dump1090.pid" - -start() { - if [ -e $PIDFILE ]; then - ## Program is running, exit with error. - echo "Error! $PROG is currently running!" 1>&2 - exit 1 - else - ## Change from /dev/null to something like /var/log/$PROG if you want to save output. - cd $PROG_PATH - ./$PROG $PROG_ARGS 2>&1 >/dev/null & - echo "$PROG started" - touch $PIDFILE - fi -} - -stop() { - if [ -e $PIDFILE ]; then - ## Program is running, so stop it - echo "$PROG is running" - killall $PROG - rm -f $PIDFILE - echo "$PROG stopped" - else - ## Program is not running, exit with error. - echo "Error! $PROG not started!" 1>&2 - exit 1 - fi -} - -## Check to see if we are running as root first. -## Found at http://www.cyberciti.biz/tips/shell-root-user-check-script.html -if [ "$(id -u)" != "0" ]; then - echo "This script must be run as root" 1>&2 - exit 1 -fi - -case "$1" in - start) - start - exit 0 - ;; - stop) - stop - exit 0 - ;; - reload|restart|force-reload) - stop - start - exit 0 - ;; - **) - echo "Usage: $0 {start|stop|reload}" 1>&2 - exit 1 - ;; -esac -# - diff --git a/interactive.c b/interactive.c deleted file mode 100644 index 4f7e02913..000000000 --- a/interactive.c +++ /dev/null @@ -1,561 +0,0 @@ -// dump1090, a Mode S messages decoder for RTLSDR devices. -// -// Copyright (C) 2012 by Salvatore Sanfilippo -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#include "dump1090.h" -// -// ============================= Utility functions ========================== -// -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; -} -// -//========================================================================= -// -// Add a new DF structure to the interactive mode linked list -// -void interactiveCreateDF(struct aircraft *a, struct modesMessage *mm) { - struct stDF *pDF = (struct stDF *) malloc(sizeof(*pDF)); - - if (pDF) { - // Default everything to zero/NULL - memset(pDF, 0, sizeof(*pDF)); - - // Now initialise things - pDF->seen = a->seen; - pDF->llTimestamp = mm->timestampMsg; - pDF->addr = mm->addr; - pDF->pAircraft = a; - memcpy(pDF->msg, mm->msg, MODES_LONG_MSG_BYTES); - - if (!pthread_mutex_lock(&Modes.pDF_mutex)) { - if ((pDF->pNext = Modes.pDF)) { - Modes.pDF->pPrev = pDF; - } - Modes.pDF = pDF; - pthread_mutex_unlock(&Modes.pDF_mutex); - } else { - free(pDF); - } - } -} -// -// Remove stale DF's from the interactive mode linked list -// -void interactiveRemoveStaleDF(time_t now) { - struct stDF *pDF = NULL; - struct stDF *prev = NULL; - - // Only fiddle with the DF list if we gain possession of the mutex - // If we fail to get the mutex we'll get another chance to tidy the - // DF list in a second or so. - if (!pthread_mutex_trylock(&Modes.pDF_mutex)) { - pDF = Modes.pDF; - while(pDF) { - if ((now - pDF->seen) > Modes.interactive_delete_ttl) { - if (Modes.pDF == pDF) { - Modes.pDF = NULL; - } else { - prev->pNext = NULL; - } - - // All DF's in the list from here onwards will be time - // expired, so delete them all - while (pDF) { - prev = pDF; pDF = pDF->pNext; - free(prev); - } - - } else { - prev = pDF; pDF = pDF->pNext; - } - } - pthread_mutex_unlock (&Modes.pDF_mutex); - } -} - -struct stDF *interactiveFindDF(uint32_t addr) { - struct stDF *pDF = NULL; - - if (!pthread_mutex_lock(&Modes.pDF_mutex)) { - pDF = Modes.pDF; - while(pDF) { - if (pDF->addr == addr) { - pthread_mutex_unlock (&Modes.pDF_mutex); - return (pDF); - } - pDF = pDF->pNext; - } - pthread_mutex_unlock (&Modes.pDF_mutex); - } - return (NULL); -} -// -//========================= Interactive mode =============================== -// -// Return a new aircraft structure for the interactive mode linked list -// of aircraft -// -struct aircraft *interactiveCreateAircraft(struct modesMessage *mm) { - struct aircraft *a = (struct aircraft *) malloc(sizeof(*a)); - - // Default everything to zero/NULL - memset(a, 0, sizeof(*a)); - - // Now initialise things that should not be 0/NULL to their defaults - a->addr = mm->addr; - a->lat = a->lon = 0.0; - memset(a->signalLevel, mm->signalLevel, 8); // First time, initialise everything - // to the first signal strength - - // 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 - // time this ModeA/C is received again in the future - if (mm->msgtype == 32) { - int modeC = ModeAToModeC(mm->modeA | mm->fs); - a->modeACflags = MODEAC_MSG_FLAG; - if (modeC < -12) { - a->modeACflags |= MODEAC_MSG_MODEA_ONLY; - } else { - mm->altitude = modeC * 100; - mm->bFlags |= MODES_ACFLAGS_ALTITUDE_VALID; - } - } - return (a); -} -// -//========================================================================= -// -// Return the aircraft with the specified address, or NULL if no aircraft -// exists with this address. -// -struct aircraft *interactiveFindAircraft(uint32_t addr) { - struct aircraft *a = Modes.aircrafts; - - while(a) { - if (a->addr == addr) return (a); - a = a->next; - } - return (NULL); -} -// -//========================================================================= -// -// We have received a Mode A or C response. -// -// Search through the list of known Mode-S aircraft and tag them if this Mode A/C -// matches their known Mode S Squawks or Altitudes(+/- 50feet). -// -// A Mode S equipped aircraft may also respond to Mode A and Mode C SSR interrogations. -// We can't tell if this is a Mode A or C, so scan through the entire aircraft list -// looking for matches on Mode A (squawk) and Mode C (altitude). Flag in the Mode S -// records that we have had a potential Mode A or Mode C response from this aircraft. -// -// If an aircraft responds to Mode A then it's highly likely to be responding to mode C -// too, and vice verca. Therefore, once the mode S record is tagged with both a Mode A -// and a Mode C flag, we can be fairly confident that this Mode A/C frame relates to that -// Mode S aircraft. -// -// Mode C's are more likely to clash than Mode A's; There could be several aircraft -// cruising at FL370, but it's less likely (though not impossible) that there are two -// aircraft on the same squawk. Therefore, give precidence to Mode A record matches -// -// Note : It's theoretically possible for an aircraft to have the same value for Mode A -// and Mode C. Therefore we have to check BOTH A AND C for EVERY S. -// -void interactiveUpdateAircraftModeA(struct aircraft *a) { - struct aircraft *b = Modes.aircrafts; - - while(b) { - if ((b->modeACflags & MODEAC_MSG_FLAG) == 0) {// skip any fudged ICAO records - - // If both (a) and (b) have valid squawks... - if ((a->bFlags & b->bFlags) & MODES_ACFLAGS_SQUAWK_VALID) { - // ...check for Mode-A == Mode-S Squawk matches - if (a->modeA == b->modeA) { // If a 'real' Mode-S ICAO exists using this Mode-A Squawk - b->modeAcount = a->messages; - b->modeACflags |= MODEAC_MSG_MODEA_HIT; - a->modeACflags |= MODEAC_MSG_MODEA_HIT; - if ( (b->modeAcount > 0) && - ( (b->modeCcount > 1) - || (a->modeACflags & MODEAC_MSG_MODEA_ONLY)) ) // Allow Mode-A only matches if this Mode-A is invalid Mode-C - {a->modeACflags |= MODEAC_MSG_MODES_HIT;} // flag this ModeA/C probably belongs to a known Mode S - } - } - - // If both (a) and (b) have valid altitudes... - if ((a->bFlags & b->bFlags) & MODES_ACFLAGS_ALTITUDE_VALID) { - // ... check for Mode-C == Mode-S Altitude matches - if ( (a->modeC == b->modeC ) // If a 'real' Mode-S ICAO exists at this Mode-C Altitude - || (a->modeC == b->modeC + 1) // or this Mode-C - 100 ft - || (a->modeC + 1 == b->modeC ) ) { // or this Mode-C + 100 ft - b->modeCcount = a->messages; - b->modeACflags |= MODEAC_MSG_MODEC_HIT; - a->modeACflags |= MODEAC_MSG_MODEC_HIT; - if ( (b->modeAcount > 0) && - (b->modeCcount > 1) ) - {a->modeACflags |= (MODEAC_MSG_MODES_HIT | MODEAC_MSG_MODEC_OLD);} // flag this ModeA/C probably belongs to a known Mode S - } - } - } - b = b->next; - } -} -// -//========================================================================= -// -void interactiveUpdateAircraftModeS() { - struct aircraft *a = Modes.aircrafts; - - while(a) { - int flags = a->modeACflags; - if (flags & MODEAC_MSG_FLAG) { // find any fudged ICAO records - - // clear the current A,C and S hit bits ready for this attempt - a->modeACflags = flags & ~(MODEAC_MSG_MODEA_HIT | MODEAC_MSG_MODEC_HIT | MODEAC_MSG_MODES_HIT); - - interactiveUpdateAircraftModeA(a); // and attempt to match them with Mode-S - } - a = a->next; - } -} -// -//========================================================================= -// -// Receive new messages and populate the interactive mode with more info -// -struct aircraft *interactiveReceiveData(struct modesMessage *mm) { - struct aircraft *a, *aux; - - // Return if (checking crc) AND (not crcok) AND (not fixed) - if (Modes.check_crc && (mm->crcok == 0) && (mm->correctedbits == 0)) - return NULL; - - // Lookup our aircraft or create a new one - a = interactiveFindAircraft(mm->addr); - if (!a) { // If it's a currently unknown aircraft.... - a = interactiveCreateAircraft(mm); // ., create a new record for it, - a->next = Modes.aircrafts; // .. and put it at the head of the list - Modes.aircrafts = a; - } else { - /* If it is an already known aircraft, move it on head - * so we keep aircrafts ordered by received message time. - * - * However move it on head only if at least one second elapsed - * since the aircraft that is currently on head sent a message, - * othewise with multiple aircrafts at the same time we have an - * useless shuffle of positions on the screen. */ - if (0 && Modes.aircrafts != a && (time(NULL) - a->seen) >= 1) { - aux = Modes.aircrafts; - while(aux->next != a) aux = aux->next; - /* Now we are a node before the aircraft to remove. */ - aux->next = aux->next->next; /* removed. */ - /* Add on head */ - a->next = Modes.aircrafts; - Modes.aircrafts = a; - } - } - - a->signalLevel[a->messages & 7] = mm->signalLevel;// replace the 8th oldest signal strength - a->seen = time(NULL); - a->timestamp = mm->timestampMsg; - a->messages++; - - // If a (new) CALLSIGN has been received, copy it to the aircraft structure - if (mm->bFlags & MODES_ACFLAGS_CALLSIGN_VALID) { - memcpy(a->flight, mm->flight, sizeof(a->flight)); - } - - // If a (new) ALTITUDE has been received, copy it to the aircraft structure - if (mm->bFlags & MODES_ACFLAGS_ALTITUDE_VALID) { - if ( (a->modeCcount) // if we've a modeCcount already - && (a->altitude != mm->altitude ) ) // and Altitude has changed -// && (a->modeC != mm->modeC + 1) // and Altitude not changed by +100 feet -// && (a->modeC + 1 != mm->modeC ) ) // and Altitude not changes by -100 feet - { - a->modeCcount = 0; //....zero the hit count - a->modeACflags &= ~MODEAC_MSG_MODEC_HIT; - } - a->altitude = mm->altitude; - a->modeC = (mm->altitude + 49) / 100; - } - - // If a (new) SQUAWK has been received, copy it to the aircraft structure - if (mm->bFlags & MODES_ACFLAGS_SQUAWK_VALID) { - if (a->modeA != mm->modeA) { - a->modeAcount = 0; // Squawk has changed, so zero the hit count - a->modeACflags &= ~MODEAC_MSG_MODEA_HIT; - } - a->modeA = mm->modeA; - } - - // If a (new) HEADING has been received, copy it to the aircraft structure - if (mm->bFlags & MODES_ACFLAGS_HEADING_VALID) { - a->track = mm->heading; - } - - // If a (new) SPEED has been received, copy it to the aircraft structure - if (mm->bFlags & MODES_ACFLAGS_SPEED_VALID) { - a->speed = mm->velocity; - } - - // If a (new) Vertical Descent rate has been received, copy it to the aircraft structure - if (mm->bFlags & MODES_ACFLAGS_VERTRATE_VALID) { - a->vert_rate = mm->vert_rate; - } - - // if the Aircraft has landed or taken off since the last message, clear the even/odd CPR flags - if ((mm->bFlags & MODES_ACFLAGS_AOG_VALID) && ((a->bFlags ^ mm->bFlags) & MODES_ACFLAGS_AOG)) { - a->bFlags &= ~(MODES_ACFLAGS_LLBOTH_VALID | MODES_ACFLAGS_AOG); - } - - // If we've got a new cprlat or cprlon - if (mm->bFlags & MODES_ACFLAGS_LLEITHER_VALID) { - int location_ok = 0; - - if (mm->bFlags & MODES_ACFLAGS_LLODD_VALID) { - a->odd_cprlat = mm->raw_latitude; - a->odd_cprlon = mm->raw_longitude; - a->odd_cprtime = mstime(); - } else { - a->even_cprlat = mm->raw_latitude; - a->even_cprlon = mm->raw_longitude; - a->even_cprtime = mstime(); - } - - // If we have enough recent data, try global CPR - if (((mm->bFlags | a->bFlags) & MODES_ACFLAGS_LLEITHER_VALID) == MODES_ACFLAGS_LLBOTH_VALID && abs((int)(a->even_cprtime - a->odd_cprtime)) <= 10000) { - if (decodeCPR(a, (mm->bFlags & MODES_ACFLAGS_LLODD_VALID), (mm->bFlags & MODES_ACFLAGS_AOG)) == 0) { - location_ok = 1; - } - } - - // Otherwise try relative CPR. - if (!location_ok && decodeCPRrelative(a, (mm->bFlags & MODES_ACFLAGS_LLODD_VALID), (mm->bFlags & MODES_ACFLAGS_AOG)) == 0) { - location_ok = 1; - } - - //If we sucessfully decoded, back copy the results to mm so that we can print them in list output - if (location_ok) { - mm->bFlags |= MODES_ACFLAGS_LATLON_VALID; - mm->fLat = a->lat; - mm->fLon = a->lon; - } - } - - // Update the aircrafts a->bFlags to reflect the newly received mm->bFlags; - a->bFlags |= mm->bFlags; - - if (mm->msgtype == 32) { - int flags = a->modeACflags; - if ((flags & (MODEAC_MSG_MODEC_HIT | MODEAC_MSG_MODEC_OLD)) == MODEAC_MSG_MODEC_OLD) { - // - // This Mode-C doesn't currently hit any known Mode-S, but it used to because MODEAC_MSG_MODEC_OLD is - // set So the aircraft it used to match has either changed altitude, or gone out of our receiver range - // - // We've now received this Mode-A/C again, so it must be a new aircraft. It could be another aircraft - // at the same Mode-C altitude, or it could be a new airctraft with a new Mods-A squawk. - // - // To avoid masking this aircraft from the interactive display, clear the MODEAC_MSG_MODES_OLD flag - // and set messages to 1; - // - a->modeACflags = flags & ~MODEAC_MSG_MODEC_OLD; - a->messages = 1; - } - } - - // If we are Logging DF's, and it's not a Mode A/C - if ((Modes.bEnableDFLogging) && (mm->msgtype < 32)) { - interactiveCreateDF(a,mm); - } - - return (a); -} -// -//========================================================================= -// -// Show the currently captured interactive data on screen. -// -void interactiveShowData(void) { - struct aircraft *a = Modes.aircrafts; - time_t now = time(NULL); - int count = 0; - char progress; - char spinner[4] = "|/-\\"; - - // Refresh screen every (MODES_INTERACTIVE_REFRESH_TIME) miliseconde - if ((mstime() - Modes.interactive_last_update) < MODES_INTERACTIVE_REFRESH_TIME) - {return;} - - Modes.interactive_last_update = mstime(); - - // Attempt to reconsile any ModeA/C with known Mode-S - // We can't condition on Modes.modeac because ModeA/C could be comming - // in from a raw input port which we can't turn off. - interactiveUpdateAircraftModeS(); - - progress = spinner[time(NULL)%4]; - -#ifndef _WIN32 - printf("\x1b[H\x1b[2J"); // Clear the screen -#else - cls(); -#endif - - if (Modes.interactive_rtl1090 == 0) { - printf ( -"Hex Mode Sqwk Flight Alt Spd Hdg Lat Long Sig Msgs Ti%c\n", progress); - } else { - printf ( -"Hex Flight Alt V/S GS TT SSR G*456^ Msgs Seen %c\n", progress); - } - printf( -"-------------------------------------------------------------------------------\n"); - - while(a && (count < Modes.interactive_rows)) { - - if ((now - a->seen) < Modes.interactive_display_ttl) - { - int msgs = a->messages; - int flags = a->modeACflags; - - if ( (((flags & (MODEAC_MSG_FLAG )) == 0 ) ) - || (((flags & (MODEAC_MSG_MODES_HIT | MODEAC_MSG_MODEA_ONLY)) == MODEAC_MSG_MODEA_ONLY) && (msgs > 4 ) ) - || (((flags & (MODEAC_MSG_MODES_HIT | MODEAC_MSG_MODEC_OLD )) == 0 ) && (msgs > 127) ) - ) { - int altitude = a->altitude, speed = a->speed; - char strSquawk[5] = " "; - char strFl[6] = " "; - char strTt[5] = " "; - char strGs[5] = " "; - - // Convert units to metric if --metric was specified - if (Modes.metric) { - altitude = (int) (altitude / 3.2828); - speed = (int) (speed * 1.852); - } - - if (a->bFlags & MODES_ACFLAGS_SQUAWK_VALID) { - snprintf(strSquawk,5,"%04x", a->modeA);} - - if (a->bFlags & MODES_ACFLAGS_SPEED_VALID) { - snprintf (strGs, 5,"%3d", speed);} - - if (a->bFlags & MODES_ACFLAGS_HEADING_VALID) { - snprintf (strTt, 5,"%03d", a->track);} - - if (msgs > 99999) { - msgs = 99999;} - - if (Modes.interactive_rtl1090) { // RTL1090 display mode - - if (a->bFlags & MODES_ACFLAGS_ALTITUDE_VALID) { - snprintf(strFl,6,"F%03d",(altitude/100)); - } - printf("%06x %-8s %-4s %-3s %-3s %4s %-6d %-2d\n", - a->addr, a->flight, strFl, strGs, strTt, strSquawk, msgs, (int)(now - a->seen)); - - } else { // Dump1090 display mode - char strMode[5] = " "; - char strLat[8] = " "; - char strLon[9] = " "; - 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; - - if ((flags & MODEAC_MSG_FLAG) == 0) { - strMode[0] = 'S'; - } else if (flags & MODEAC_MSG_MODEA_ONLY) { - strMode[0] = 'A'; - } - if (flags & MODEAC_MSG_MODEA_HIT) {strMode[2] = 'a';} - if (flags & MODEAC_MSG_MODEC_HIT) {strMode[3] = 'c';} - - if (a->bFlags & MODES_ACFLAGS_LATLON_VALID) { - snprintf(strLat, 8,"%7.03f", a->lat); - snprintf(strLon, 9,"%8.03f", a->lon); - } - - if (a->bFlags & MODES_ACFLAGS_AOG) { - snprintf(strFl, 6," grnd"); - } else if (a->bFlags & MODES_ACFLAGS_ALTITUDE_VALID) { - snprintf(strFl, 6, "%5d", altitude); - } - - printf("%06X %-4s %-4s %-8s %5s %3s %3s %7s %8s %3d %5d %2d\n", - a->addr, strMode, strSquawk, a->flight, strFl, strGs, strTt, - strLat, strLon, signalAverage, msgs, (int)(now - a->seen)); - } - count++; - } - } - a = a->next; - } -} -// -//========================================================================= -// -// When in interactive mode If we don't receive new nessages within -// MODES_INTERACTIVE_DELETE_TTL seconds we remove the aircraft from the list. -// -void interactiveRemoveStaleAircrafts(void) { - struct aircraft *a = Modes.aircrafts; - struct aircraft *prev = NULL; - time_t now = time(NULL); - - // Only do cleanup once per second - if (Modes.last_cleanup_time != now) { - Modes.last_cleanup_time = now; - - interactiveRemoveStaleDF(now); - - while(a) { - if ((now - a->seen) > Modes.interactive_delete_ttl) { - // Remove the element from the linked list, with care - // if we are removing the first element - if (!prev) { - Modes.aircrafts = a->next; free(a); a = Modes.aircrafts; - } else { - prev->next = a->next; free(a); a = prev->next; - } - } else { - prev = a; a = a->next; - } - } - } -} -// -//========================================================================= -// diff --git a/makedump1090 b/makedump1090 deleted file mode 100644 index 4d3fccbba..000000000 --- a/makedump1090 +++ /dev/null @@ -1,27 +0,0 @@ -# -# When building a package or installing otherwise in the system, make -# sure that the variable PREFIX is defined, e.g. make PREFIX=/usr/local -# -PROGNAME=dump1090 - -ifdef PREFIX -BINDIR=$(PREFIX)/bin -SHAREDIR=$(PREFIX)/share/$(PROGNAME) -EXTRACFLAGS=-DHTMLPATH=\"$(SHAREDIR)\" -endif - -CFLAGS=-O2 -g -Wall -W `pkg-config --cflags librtlsdr` -LIBS=`pkg-config --libs librtlsdr` -lpthread -lm -CC=gcc - - -all: dump1090 - -%.o: %.c - $(CC) $(CFLAGS) $(EXTRACFLAGS) -c $< - -dump1090: dump1090.o anet.o interactive.o mode_ac.o mode_s.o net_io.o - $(CC) -g -o dump1090 dump1090.o anet.o interactive.o mode_ac.o mode_s.o net_io.o $(LIBS) $(LDFLAGS) - -clean: - rm -f *.o dump1090 diff --git a/makeppup1090 b/makeppup1090 deleted file mode 100644 index 9df60aa36..000000000 --- a/makeppup1090 +++ /dev/null @@ -1,27 +0,0 @@ -# -# When building a package or installing otherwise in the system, make -# sure that the variable PREFIX is defined, e.g. make PREFIX=/usr/local -# -PROGNAME=ppup1090 - -ifdef PREFIX -BINDIR=$(PREFIX)/bin -SHAREDIR=$(PREFIX)/share/$(PROGNAME) -EXTRACFLAGS=-DHTMLPATH=\"$(SHAREDIR)\" -endif - -CFLAGS=-O2 -g -Wall -W `pkg-config --cflags librtlsdr` -LIBS=`pkg-config --libs librtlsdr` -lpthread -lm -CC=gcc - - -all: ppup1090 - -%.o: %.c - $(CC) $(CFLAGS) $(EXTRACFLAGS) -c $< - -ppup1090: ppup1090.o anet.o interactive.o mode_ac.o mode_s.o net_io.o - $(CC) -g -o ppup1090 ppup1090.o anet.o interactive.o mode_ac.o mode_s.o net_io.o coaa1090.obj $(LIBS) $(LDFLAGS) - -clean: - rm -f *.o ppup1090 diff --git a/makeview1090 b/makeview1090 deleted file mode 100644 index 6cb76af58..000000000 --- a/makeview1090 +++ /dev/null @@ -1,27 +0,0 @@ -# -# When building a package or installing otherwise in the system, make -# sure that the variable PREFIX is defined, e.g. make PREFIX=/usr/local -# -PROGNAME=view1090 - -ifdef PREFIX -BINDIR=$(PREFIX)/bin -SHAREDIR=$(PREFIX)/share/$(PROGNAME) -EXTRACFLAGS=-DHTMLPATH=\"$(SHAREDIR)\" -endif - -CFLAGS=-O2 -g -Wall -W `pkg-config --cflags librtlsdr` -LIBS=`pkg-config --libs librtlsdr` -lpthread -lm -CC=gcc - - -all: view1090 - -%.o: %.c - $(CC) $(CFLAGS) $(EXTRACFLAGS) -c $< - -view1090: view1090.o anet.o interactive.o mode_ac.o mode_s.o net_io.o - $(CC) -g -o view1090 view1090.o anet.o interactive.o mode_ac.o mode_s.o net_io.o $(LIBS) $(LDFLAGS) - -clean: - rm -f *.o view1090 diff --git a/mode_ac.c b/mode_ac.c deleted file mode 100644 index 881a428c2..000000000 --- a/mode_ac.c +++ /dev/null @@ -1,386 +0,0 @@ -// dump1090, a Mode S messages decoder for RTLSDR devices. -// -// Copyright (C) 2012 by Salvatore Sanfilippo -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#include "dump1090.h" -// -// ===================== Mode A/C detection and decoding =================== -// -// -// This table is used to build the Mode A/C variable called ModeABits.Each -// bit period is inspected, and if it's value exceeds the threshold limit, -// then the value in this table is or-ed into ModeABits. -// -// At the end of message processing, ModeABits will be the decoded ModeA value. -// -// We can also flag noise in bits that should be zeros - the xx bits. Noise in -// these bits cause bits (31-16) in ModeABits to be set. Then at the end of message -// processing we can test for errors by looking at these bits. -// -uint32_t ModeABitTable[24] = { -0x00000000, // F1 = 1 -0x00000010, // C1 -0x00001000, // A1 -0x00000020, // C2 -0x00002000, // A2 -0x00000040, // C4 -0x00004000, // A4 -0x40000000, // xx = 0 Set bit 30 if we see this high -0x00000100, // B1 -0x00000001, // D1 -0x00000200, // B2 -0x00000002, // D2 -0x00000400, // B4 -0x00000004, // D4 -0x00000000, // F2 = 1 -0x08000000, // xx = 0 Set bit 27 if we see this high -0x04000000, // xx = 0 Set bit 26 if we see this high -0x00000080, // SPI -0x02000000, // xx = 0 Set bit 25 if we see this high -0x01000000, // xx = 0 Set bit 24 if we see this high -0x00800000, // xx = 0 Set bit 23 if we see this high -0x00400000, // xx = 0 Set bit 22 if we see this high -0x00200000, // xx = 0 Set bit 21 if we see this high -0x00100000, // xx = 0 Set bit 20 if we see this high -}; -// -// This table is used to produce an error variable called ModeAErrs.Each -// inter-bit period is inspected, and if it's value falls outside of the -// expected range, then the value in this table is or-ed into ModeAErrs. -// -// At the end of message processing, ModeAErrs will indicate if we saw -// any inter-bit anomolies, and the bits that are set will show which -// bits had them. -// -uint32_t ModeAMidTable[24] = { -0x80000000, // F1 = 1 Set bit 31 if we see F1_C1 error -0x00000010, // C1 Set bit 4 if we see C1_A1 error -0x00001000, // A1 Set bit 12 if we see A1_C2 error -0x00000020, // C2 Set bit 5 if we see C2_A2 error -0x00002000, // A2 Set bit 13 if we see A2_C4 error -0x00000040, // C4 Set bit 6 if we see C3_A4 error -0x00004000, // A4 Set bit 14 if we see A4_xx error -0x40000000, // xx = 0 Set bit 30 if we see xx_B1 error -0x00000100, // B1 Set bit 8 if we see B1_D1 error -0x00000001, // D1 Set bit 0 if we see D1_B2 error -0x00000200, // B2 Set bit 9 if we see B2_D2 error -0x00000002, // D2 Set bit 1 if we see D2_B4 error -0x00000400, // B4 Set bit 10 if we see B4_D4 error -0x00000004, // D4 Set bit 2 if we see D4_F2 error -0x20000000, // F2 = 1 Set bit 29 if we see F2_xx error -0x08000000, // xx = 0 Set bit 27 if we see xx_xx error -0x04000000, // xx = 0 Set bit 26 if we see xx_SPI error -0x00000080, // SPI Set bit 15 if we see SPI_xx error -0x02000000, // xx = 0 Set bit 25 if we see xx_xx error -0x01000000, // xx = 0 Set bit 24 if we see xx_xx error -0x00800000, // xx = 0 Set bit 23 if we see xx_xx error -0x00400000, // xx = 0 Set bit 22 if we see xx_xx error -0x00200000, // xx = 0 Set bit 21 if we see xx_xx error -0x00100000, // xx = 0 Set bit 20 if we see xx_xx error -}; -// -// The "off air" format is,, -// _F1_C1_A1_C2_A2_C4_A4_xx_B1_D1_B2_D2_B4_D4_F2_xx_xx_SPI_ -// -// Bit spacing is 1.45uS, with 0.45uS high, and 1.00us low. This is a problem -// because we ase sampling at 2Mhz (500nS) so we are below Nyquist. -// -// The bit spacings are.. -// F1 : 0.00, -// 1.45, 2.90, 4.35, 5.80, 7.25, 8.70, -// X : 10.15, -// : 11.60, 13.05, 14.50, 15.95, 17.40, 18.85, -// F2 : 20.30, -// X : 21.75, 23.20, 24.65 -// -// This equates to the following sample point centers at 2Mhz. -// [ 0.0], -// [ 2.9], [ 5.8], [ 8.7], [11.6], [14.5], [17.4], -// [20.3], -// [23.2], [26.1], [29.0], [31.9], [34.8], [37.7] -// [40.6] -// [43.5], [46.4], [49.3] -// -// We know that this is a supposed to be a binary stream, so the signal -// should either be a 1 or a 0. Therefore, any energy above the noise level -// in two adjacent samples must be from the same pulse, so we can simply -// add the values together.. -// -int detectModeA(uint16_t *m, struct modesMessage *mm) - { - int j, lastBitWasOne; - int ModeABits = 0; - int ModeAErrs = 0; - int byte, bit; - int thisSample, lastBit, lastSpace = 0; - int m0, m1, m2, m3, mPhase; - int n0, n1, n2 ,n3; - int F1_sig, F1_noise; - int F2_sig, F2_noise; - int fSig, fNoise, fLevel, fLoLo; - - // m[0] contains the energy from 0 -> 499 nS - // m[1] contains the energy from 500 -> 999 nS - // m[2] contains the energy from 1000 -> 1499 nS - // m[3] contains the energy from 1500 -> 1999 nS - // - // We are looking for a Frame bit (F1) whose width is 450nS, followed by - // 1000nS of quiet. - // - // The width of the frame bit is 450nS, which is 90% of our sample rate. - // Therefore, in an ideal world, all the energy for the frame bit will be - // in a single sample, preceeded by (at least) one zero, and followed by - // two zeros, Best case we can look for ... - // - // 0 - 1 - 0 - 0 - // - // However, our samples are not phase aligned, so some of the energy from - // each bit could be spread over two consecutive samples. Worst case is - // that we sample half in one bit, and half in the next. In that case, - // we're looking for - // - // 0 - 0.5 - 0.5 - 0. - - m0 = m[0]; m1 = m[1]; - - if (m0 >= m1) // m1 *must* be bigger than m0 for this to be F1 - {return (0);} - - m2 = m[2]; m3 = m[3]; - - // - // if (m2 <= m0), then assume the sample bob on (Phase == 0), so don't look at m3 - if ((m2 <= m0) || (m2 < m3)) - {m3 = m2; m2 = m0;} - - if ( (m3 >= m1) // m1 must be bigger than m3 - || (m0 > m2) // m2 can be equal to m0 if ( 0,1,0,0 ) - || (m3 > m2) ) // m2 can be equal to m3 if ( 0,1,0,0 ) - {return (0);} - - // m0 = noise - // m1 = noise + (signal * X)) - // m2 = noise + (signal * (1-X)) - // m3 = noise - // - // Hence, assuming all 4 samples have similar amounts of noise in them - // signal = (m1 + m2) - ((m0 + m3) * 2) - // noise = (m0 + m3) / 2 - // - F1_sig = (m1 + m2) - ((m0 + m3) << 1); - F1_noise = (m0 + m3) >> 1; - - if ( (F1_sig < MODEAC_MSG_SQUELCH_LEVEL) // minimum required F1 signal amplitude - || (F1_sig < (F1_noise << 2)) ) // minimum allowable Sig/Noise ratio 4:1 - {return (0);} - - // If we get here then we have a potential F1, so look for an equally valid F2 20.3uS later - // - // Our F1 is centered somewhere between samples m[1] and m[2]. We can guestimate where F2 is - // by comparing the ratio of m1 and m2, and adding on 20.3 uS (40.6 samples) - // - mPhase = ((m2 * 20) / (m1 + m2)); - byte = (mPhase + 812) / 20; - n0 = m[byte++]; n1 = m[byte++]; - - if (n0 >= n1) // n1 *must* be bigger than n0 for this to be F2 - {return (0);} - - n2 = m[byte++]; - // - // if the sample bob on (Phase == 0), don't look at n3 - // - if ((mPhase + 812) % 20) - {n3 = m[byte++];} - else - {n3 = n2; n2 = n0;} - - if ( (n3 >= n1) // n1 must be bigger than n3 - || (n0 > n2) // n2 can be equal to n0 ( 0,1,0,0 ) - || (n3 > n2) ) // n2 can be equal to n3 ( 0,1,0,0 ) - {return (0);} - - F2_sig = (n1 + n2) - ((n0 + n3) << 1); - F2_noise = (n0 + n3) >> 1; - - if ( (F2_sig < MODEAC_MSG_SQUELCH_LEVEL) // minimum required F2 signal amplitude - || (F2_sig < (F2_noise << 2)) ) // maximum allowable Sig/Noise ratio 4:1 - {return (0);} - - fSig = (F1_sig + F2_sig) >> 1; - fNoise = (F1_noise + F2_noise) >> 1; - fLoLo = fNoise + (fSig >> 2); // 1/2 - fLevel = fNoise + (fSig >> 1); - lastBitWasOne = 1; - lastBit = F1_sig; - // - // Now step by a half ModeA bit, 0.725nS, which is 1.45 samples, which is 29/20 - // No need to do bit 0 because we've already selected it as a valid F1 - // Do several bits past the SPI to increase error rejection - // - for (j = 1, mPhase += 29; j < 48; mPhase += 29, j ++) - { - byte = 1 + (mPhase / 20); - - thisSample = m[byte] - fNoise; - if (mPhase % 20) // If the bit is split over two samples... - {thisSample += (m[byte+1] - fNoise);} // add in the second sample's energy - - // If we're calculating a space value - if (j & 1) - {lastSpace = thisSample;} - - else - {// We're calculating a new bit value - bit = j >> 1; - if (thisSample >= fLevel) - {// We're calculating a new bit value, and its a one - ModeABits |= ModeABitTable[bit--]; // or in the correct bit - - if (lastBitWasOne) - { // This bit is one, last bit was one, so check the last space is somewhere less than one - if ( (lastSpace >= (thisSample>>1)) || (lastSpace >= lastBit) ) - {ModeAErrs |= ModeAMidTable[bit];} - } - - else - {// This bit,is one, last bit was zero, so check the last space is somewhere less than one - if (lastSpace >= (thisSample >> 1)) - {ModeAErrs |= ModeAMidTable[bit];} - } - - lastBitWasOne = 1; - } - - - else - {// We're calculating a new bit value, and its a zero - if (lastBitWasOne) - { // This bit is zero, last bit was one, so check the last space is somewhere in between - if (lastSpace >= lastBit) - {ModeAErrs |= ModeAMidTable[bit];} - } - - else - {// This bit,is zero, last bit was zero, so check the last space is zero too - if (lastSpace >= fLoLo) - {ModeAErrs |= ModeAMidTable[bit];} - } - - lastBitWasOne = 0; - } - - lastBit = (thisSample >> 1); - } - } - - // - // Output format is : 00:A4:A2:A1:00:B4:B2:B1:00:C4:C2:C1:00:D4:D2:D1 - // - if ((ModeABits < 3) || (ModeABits & 0xFFFF8808) || (ModeAErrs) ) - {return (ModeABits = 0);} - - fSig = (fSig + 0x7F) >> 8; - mm->signalLevel = ((fSig < 255) ? fSig : 255); - - return ModeABits; - } -// -//========================================================================= -// -// Input format is : 00:A4:A2:A1:00:B4:B2:B1:00:C4:C2:C1:00:D4:D2:D1 -// -int ModeAToModeC(unsigned int ModeA) - { - unsigned int FiveHundreds = 0; - unsigned int OneHundreds = 0; - - if ( (ModeA & 0xFFFF888B) // D1 set is illegal. D2 set is > 62700ft which is unlikely - || ((ModeA & 0x000000F0) == 0) ) // C1,,C4 cannot be Zero - {return -9999;} - - if (ModeA & 0x0010) {OneHundreds ^= 0x007;} // C1 - if (ModeA & 0x0020) {OneHundreds ^= 0x003;} // C2 - if (ModeA & 0x0040) {OneHundreds ^= 0x001;} // C4 - - // Remove 7s from OneHundreds (Make 7->5, snd 5->7). - if ((OneHundreds & 5) == 5) {OneHundreds ^= 2;} - - // Check for invalid codes, only 1 to 5 are valid - if (OneHundreds > 5) - {return -9999;} - -//if (ModeA & 0x0001) {FiveHundreds ^= 0x1FF;} // D1 never used for altitude - if (ModeA & 0x0002) {FiveHundreds ^= 0x0FF;} // D2 - if (ModeA & 0x0004) {FiveHundreds ^= 0x07F;} // D4 - - if (ModeA & 0x1000) {FiveHundreds ^= 0x03F;} // A1 - if (ModeA & 0x2000) {FiveHundreds ^= 0x01F;} // A2 - if (ModeA & 0x4000) {FiveHundreds ^= 0x00F;} // A4 - - if (ModeA & 0x0100) {FiveHundreds ^= 0x007;} // B1 - if (ModeA & 0x0200) {FiveHundreds ^= 0x003;} // B2 - if (ModeA & 0x0400) {FiveHundreds ^= 0x001;} // B4 - - // Correct order of OneHundreds. - if (FiveHundreds & 1) {OneHundreds = 6 - OneHundreds;} - - return ((FiveHundreds * 5) + OneHundreds - 13); - } -// -//========================================================================= -// -void decodeModeAMessage(struct modesMessage *mm, int ModeA) - { - mm->msgtype = 32; // Valid Mode S DF's are DF-00 to DF-31. - // so use 32 to indicate Mode A/C - - mm->msgbits = 16; // Fudge up a Mode S style data stream - mm->msg[0] = (ModeA >> 8); - mm->msg[1] = (ModeA); - - // Fudge an ICAO address based on Mode A (remove the Ident bit) - // Use an upper address byte of FF, since this is ICAO unallocated - mm->addr = 0x00FF0000 | (ModeA & 0x0000FF7F); - - // Set the Identity field to ModeA - mm->modeA = ModeA & 0x7777; - mm->bFlags |= MODES_ACFLAGS_SQUAWK_VALID; - - // Flag ident in flight status - mm->fs = ModeA & 0x0080; - - // Not much else we can tell from a Mode A/C reply. - // Just fudge up a few bits to keep other code happy - mm->crcok = 1; - mm->correctedbits = 0; - } -// -// ===================== Mode A/C detection and decoding =================== -// \ No newline at end of file diff --git a/mode_s.c b/mode_s.c deleted file mode 100644 index cd129a02b..000000000 --- a/mode_s.c +++ /dev/null @@ -1,2201 +0,0 @@ -// dump1090, a Mode S messages decoder for RTLSDR devices. -// -// Copyright (C) 2012 by Salvatore Sanfilippo -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#include "dump1090.h" -// -// ===================== Mode S detection and decoding =================== -// -// Parity table for MODE S Messages. -// The table contains 112 elements, every element corresponds to a bit set -// in the message, starting from the first bit of actual data after the -// preamble. -// -// For messages of 112 bit, the whole table is used. -// For messages of 56 bits only the last 56 elements are used. -// -// The algorithm is as simple as xoring all the elements in this table -// for which the corresponding bit on the message is set to 1. -// -// The latest 24 elements in this table are set to 0 as the checksum at the -// end of the message should not affect the computation. -// -// Note: this function can be used with DF11 and DF17, other modes have -// the CRC xored with the sender address as they are reply to interrogations, -// but a casual listener can't split the address from the checksum. -// -uint32_t modes_checksum_table[112] = { -0x3935ea, 0x1c9af5, 0xf1b77e, 0x78dbbf, 0xc397db, 0x9e31e9, 0xb0e2f0, 0x587178, -0x2c38bc, 0x161c5e, 0x0b0e2f, 0xfa7d13, 0x82c48d, 0xbe9842, 0x5f4c21, 0xd05c14, -0x682e0a, 0x341705, 0xe5f186, 0x72f8c3, 0xc68665, 0x9cb936, 0x4e5c9b, 0xd8d449, -0x939020, 0x49c810, 0x24e408, 0x127204, 0x093902, 0x049c81, 0xfdb444, 0x7eda22, -0x3f6d11, 0xe04c8c, 0x702646, 0x381323, 0xe3f395, 0x8e03ce, 0x4701e7, 0xdc7af7, -0x91c77f, 0xb719bb, 0xa476d9, 0xadc168, 0x56e0b4, 0x2b705a, 0x15b82d, 0xf52612, -0x7a9309, 0xc2b380, 0x6159c0, 0x30ace0, 0x185670, 0x0c2b38, 0x06159c, 0x030ace, -0x018567, 0xff38b7, 0x80665f, 0xbfc92b, 0xa01e91, 0xaff54c, 0x57faa6, 0x2bfd53, -0xea04ad, 0x8af852, 0x457c29, 0xdd4410, 0x6ea208, 0x375104, 0x1ba882, 0x0dd441, -0xf91024, 0x7c8812, 0x3e4409, 0xe0d800, 0x706c00, 0x383600, 0x1c1b00, 0x0e0d80, -0x0706c0, 0x038360, 0x01c1b0, 0x00e0d8, 0x00706c, 0x003836, 0x001c1b, 0xfff409, -0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, -0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, -0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000 -}; - -uint32_t modesChecksum(unsigned char *msg, int bits) { - uint32_t crc = 0; - uint32_t rem = 0; - int offset = (bits == 112) ? 0 : (112-56); - uint8_t theByte = *msg; - uint32_t * pCRCTable = &modes_checksum_table[offset]; - int j; - - // We don't really need to include the checksum itself - bits -= 24; - for(j = 0; j < bits; j++) { - if ((j & 7) == 0) - theByte = *msg++; - - // If bit is set, xor with corresponding table entry. - if (theByte & 0x80) {crc ^= *pCRCTable;} - pCRCTable++; - theByte = theByte << 1; - } - - rem = (msg[0] << 16) | (msg[1] << 8) | msg[2]; // message checksum - return ((crc ^ rem) & 0x00FFFFFF); // 24 bit checksum syndrome. -} -// -//========================================================================= -// -// Given the Downlink Format (DF) of the message, return the message length in bits. -// -// All known DF's 16 or greater are long. All known DF's 15 or less are short. -// There are lots of unused codes in both category, so we can assume ICAO will stick to -// these rules, meaning that the most significant bit of the DF indicates the length. -// -int modesMessageLenByType(int type) { - return (type & 0x10) ? MODES_LONG_MSG_BITS : MODES_SHORT_MSG_BITS ; -} -// -//========================================================================= -// -// Try to fix single bit errors using the checksum. On success modifies -// the original buffer with the fixed version, and returns the position -// of the error bit. Otherwise if fixing failed -1 is returned. -/* -int fixSingleBitErrors(unsigned char *msg, int bits) { - int j; - unsigned char aux[MODES_LONG_MSG_BYTES]; - - memcpy(aux, msg, bits/8); - - // Do not attempt to error correct Bits 0-4. These contain the DF, and must - // be correct because we can only error correct DF17 - for (j = 5; j < bits; j++) { - int byte = j/8; - int bitmask = 1 << (7 - (j & 7)); - - aux[byte] ^= bitmask; // Flip j-th bit - - if (0 == modesChecksum(aux, bits)) { - // The error is fixed. Overwrite the original buffer with the - // corrected sequence, and returns the error bit position - msg[byte] = aux[byte]; - return (j); - } - - aux[byte] ^= bitmask; // Flip j-th bit back again - } - return (-1); -} -*/ -//========================================================================= -// -// Similar to fixSingleBitErrors() but try every possible two bit combination. -// This is very slow and should be tried only against DF17 messages that -// don't pass the checksum, and only in Aggressive Mode. -/* -int fixTwoBitsErrors(unsigned char *msg, int bits) { - int j, i; - unsigned char aux[MODES_LONG_MSG_BYTES]; - - memcpy(aux, msg, bits/8); - - // Do not attempt to error correct Bits 0-4. These contain the DF, and must - // be correct because we can only error correct DF17 - for (j = 5; j < bits; j++) { - int byte1 = j/8; - int bitmask1 = 1 << (7 - (j & 7)); - aux[byte1] ^= bitmask1; // Flip j-th bit - - // Don't check the same pairs multiple times, so i starts from j+1 - for (i = j+1; i < bits; i++) { - int byte2 = i/8; - int bitmask2 = 1 << (7 - (i & 7)); - - aux[byte2] ^= bitmask2; // Flip i-th bit - - if (0 == modesChecksum(aux, bits)) { - // The error is fixed. Overwrite the original buffer with - // the corrected sequence, and returns the error bit position - msg[byte1] = aux[byte1]; - msg[byte2] = aux[byte2]; - - // We return the two bits as a 16 bit integer by shifting - // 'i' on the left. This is possible since 'i' will always - // be non-zero because i starts from j+1 - return (j | (i << 8)); - - aux[byte2] ^= bitmask2; // Flip i-th bit back - } - - aux[byte1] ^= bitmask1; // Flip j-th bit back - } - } - return (-1); -} -*/ -// -//========================================================================= -// -// Code for introducing a less CPU-intensive method of correcting -// single bit errors. -// -// Makes use of the fact that the crc checksum is linear with respect to -// the bitwise xor operation, i.e. -// crc(m^e) = (crc(m)^crc(e) -// where m and e are the message resp. error bit vectors. -// -// Call crc(e) the syndrome. -// -// The code below works by precomputing a table of (crc(e), e) for all -// possible error vectors e (here only single bit and double bit errors), -// search for the syndrome in the table, and correct the then known error. -// The error vector e is represented by one or two bit positions that are -// changed. If a second bit position is not used, it is -1. -// -// Run-time is binary search in a sorted table, plus some constant overhead, -// instead of running through all possible bit positions (resp. pairs of -// bit positions). -// -struct errorinfo { - uint32_t syndrome; // CRC syndrome - int bits; // Number of bit positions to fix - int pos[MODES_MAX_BITERRORS]; // Bit positions corrected by this syndrome -}; - -#define NERRORINFO \ - (MODES_LONG_MSG_BITS+MODES_LONG_MSG_BITS*(MODES_LONG_MSG_BITS-1)/2) -struct errorinfo bitErrorTable[NERRORINFO]; - -// Compare function as needed for stdlib's qsort and bsearch functions -int cmpErrorInfo(const void *p0, const void *p1) { - struct errorinfo *e0 = (struct errorinfo*)p0; - struct errorinfo *e1 = (struct errorinfo*)p1; - if (e0->syndrome == e1->syndrome) { - return 0; - } else if (e0->syndrome < e1->syndrome) { - return -1; - } else { - return 1; - } -} -// -//========================================================================= -// -// Compute the table of all syndromes for 1-bit and 2-bit error vectors -void modesInitErrorInfo() { - unsigned char msg[MODES_LONG_MSG_BYTES]; - int i, j, n; - uint32_t crc; - n = 0; - memset(bitErrorTable, 0, sizeof(bitErrorTable)); - memset(msg, 0, MODES_LONG_MSG_BYTES); - // Add all possible single and double bit errors - // don't include errors in first 5 bits (DF type) - for (i = 5; i < MODES_LONG_MSG_BITS; i++) { - int bytepos0 = (i >> 3); - int mask0 = 1 << (7 - (i & 7)); - msg[bytepos0] ^= mask0; // create error0 - crc = modesChecksum(msg, MODES_LONG_MSG_BITS); - bitErrorTable[n].syndrome = crc; // single bit error case - bitErrorTable[n].bits = 1; - bitErrorTable[n].pos[0] = i; - bitErrorTable[n].pos[1] = -1; - n += 1; - - if (Modes.nfix_crc > 1) { - for (j = i+1; j < MODES_LONG_MSG_BITS; j++) { - int bytepos1 = (j >> 3); - int mask1 = 1 << (7 - (j & 7)); - msg[bytepos1] ^= mask1; // create error1 - crc = modesChecksum(msg, MODES_LONG_MSG_BITS); - if (n >= NERRORINFO) { - //fprintf(stderr, "Internal error, too many entries, fix NERRORINFO\n"); - break; - } - bitErrorTable[n].syndrome = crc; // two bit error case - bitErrorTable[n].bits = 2; - bitErrorTable[n].pos[0] = i; - bitErrorTable[n].pos[1] = j; - n += 1; - msg[bytepos1] ^= mask1; // revert error1 - } - } - msg[bytepos0] ^= mask0; // revert error0 - } - qsort(bitErrorTable, NERRORINFO, sizeof(struct errorinfo), cmpErrorInfo); - - // Test code: report if any syndrome appears at least twice. In this - // case the correction cannot be done without ambiguity. - // Tried it, does not happen for 1- and 2-bit errors. - /* - for (i = 1; i < NERRORINFO; i++) { - if (bitErrorTable[i-1].syndrome == bitErrorTable[i].syndrome) { - fprintf(stderr, "modesInitErrorInfo: Collision for syndrome %06x\n", - (int)bitErrorTable[i].syndrome); - } - } - - for (i = 0; i < NERRORINFO; i++) { - printf("syndrome %06x bit0 %3d bit1 %3d\n", - bitErrorTable[i].syndrome, - bitErrorTable[i].pos0, bitErrorTable[i].pos1); - } - */ -} -// -//========================================================================= -// -// Search for syndrome in table and if an entry is found, flip the necessary -// bits. Make sure the indices fit into the array -// Additional parameter: fix only less than maxcorrected bits, and record -// fixed bit positions in corrected[]. This array can be NULL, otherwise -// must be of length at least maxcorrected. -// Return number of fixed bits. -// -int fixBitErrors(unsigned char *msg, int bits, int maxfix, char *fixedbits) { - struct errorinfo *pei; - struct errorinfo ei; - int bitpos, offset, res, i; - memset(&ei, 0, sizeof(struct errorinfo)); - ei.syndrome = modesChecksum(msg, bits); - pei = bsearch(&ei, bitErrorTable, NERRORINFO, - sizeof(struct errorinfo), cmpErrorInfo); - if (pei == NULL) { - return 0; // No syndrome found - } - - // Check if the syndrome fixes more bits than we allow - if (maxfix < pei->bits) { - return 0; - } - - // Check that all bit positions lie inside the message length - offset = MODES_LONG_MSG_BITS-bits; - for (i = 0; i < pei->bits; i++) { - bitpos = pei->pos[i] - offset; - if ((bitpos < 0) || (bitpos >= bits)) { - return 0; - } - } - - // Fix the bits - for (i = res = 0; i < pei->bits; i++) { - bitpos = pei->pos[i] - offset; - msg[bitpos >> 3] ^= (1 << (7 - (bitpos & 7))); - if (fixedbits) { - fixedbits[res++] = bitpos; - } - } - return res; -} -// -// ============================== Debugging ================================= -// -// Helper function for dumpMagnitudeVector(). -// It prints a single bar used to display raw signals. -// -// Since every magnitude sample is between 0-255, the function uses -// up to 63 characters for every bar. Every character represents -// a length of 4, 3, 2, 1, specifically: -// -// "O" is 4 -// "o" is 3 -// "-" is 2 -// "." is 1 -// -void dumpMagnitudeBar(int index, int magnitude) { - char *set = " .-o"; - char buf[256]; - int div = magnitude / 256 / 4; - int rem = magnitude / 256 % 4; - - memset(buf,'O',div); - buf[div] = set[rem]; - buf[div+1] = '\0'; - - if (index >= 0) - printf("[%.3d] |%-66s 0x%04X\n", index, buf, magnitude); - else - printf("[%.2d] |%-66s 0x%04X\n", index, buf, magnitude); -} -// -//========================================================================= -// -// Display an ASCII-art alike graphical representation of the undecoded -// message as a magnitude signal. -// -// The message starts at the specified offset in the "m" buffer. -// The function will display enough data to cover a short 56 bit message. -// -// If possible a few samples before the start of the messsage are included -// for context. -// -void dumpMagnitudeVector(uint16_t *m, uint32_t offset) { - uint32_t padding = 5; // Show a few samples before the actual start. - uint32_t start = (offset < padding) ? 0 : offset-padding; - uint32_t end = offset + (MODES_PREAMBLE_SAMPLES)+(MODES_SHORT_MSG_SAMPLES) - 1; - uint32_t j; - - for (j = start; j <= end; j++) { - dumpMagnitudeBar(j-offset, m[j]); - } -} -// -//========================================================================= -// -// Produce a raw representation of the message as a Javascript file -// loadable by debug.html. -// -void dumpRawMessageJS(char *descr, unsigned char *msg, - uint16_t *m, uint32_t offset, int fixable, char *bitpos) -{ - int padding = 5; // Show a few samples before the actual start. - int start = offset - padding; - int end = offset + (MODES_PREAMBLE_SAMPLES)+(MODES_LONG_MSG_SAMPLES) - 1; - FILE *fp; - int j; - - MODES_NOTUSED(fixable); - if ((fp = fopen("frames.js","a")) == NULL) { - fprintf(stderr, "Error opening frames.js: %s\n", strerror(errno)); - exit(1); - } - - fprintf(fp,"frames.push({\"descr\": \"%s\", \"mag\": [", descr); - for (j = start; j <= end; j++) { - fprintf(fp,"%d", j < 0 ? 0 : m[j]); - if (j != end) fprintf(fp,","); - } - fprintf(fp,"], \"fix1\": %d, \"fix2\": %d, \"bits\": %d, \"hex\": \"", - bitpos[0], bitpos[1] , modesMessageLenByType(msg[0]>>3)); - for (j = 0; j < MODES_LONG_MSG_BYTES; j++) - fprintf(fp,"\\x%02x",msg[j]); - fprintf(fp,"\"});\n"); - fclose(fp); -} -// -//========================================================================= -// -// This is a wrapper for dumpMagnitudeVector() that also show the message -// in hex format with an additional description. -// -// descr is the additional message to show to describe the dump. -// msg points to the decoded message -// m is the original magnitude vector -// offset is the offset where the message starts -// -// The function also produces the Javascript file used by debug.html to -// display packets in a graphical format if the Javascript output was -// enabled. -// -void dumpRawMessage(char *descr, unsigned char *msg, uint16_t *m, uint32_t offset) { - int j; - int msgtype = msg[0] >> 3; - int fixable = 0; - char bitpos[MODES_MAX_BITERRORS]; - - for (j = 0; j < MODES_MAX_BITERRORS; j++) { - bitpos[j] = -1; - } - if (msgtype == 17) { - fixable = fixBitErrors(msg, MODES_LONG_MSG_BITS, MODES_MAX_BITERRORS, bitpos); - } - - if (Modes.debug & MODES_DEBUG_JS) { - dumpRawMessageJS(descr, msg, m, offset, fixable, bitpos); - return; - } - - printf("\n--- %s\n ", descr); - for (j = 0; j < MODES_LONG_MSG_BYTES; j++) { - printf("%02x",msg[j]); - if (j == MODES_SHORT_MSG_BYTES-1) printf(" ... "); - } - printf(" (DF %d, Fixable: %d)\n", msgtype, fixable); - dumpMagnitudeVector(m,offset); - printf("---\n\n"); -} -// -//========================================================================= -// -// Code for testing the timing: run all possible 1- and 2-bit error -// the test message by all 1-bit errors. Run the old code against -// all of them, and new the code. -// -// Example measurements: -// Timing old vs. new crc correction code: -// Old code: 1-bit errors on 112 msgs: 3934 usecs -// New code: 1-bit errors on 112 msgs: 104 usecs -// Old code: 2-bit errors on 6216 msgs: 407743 usecs -// New code: 2-bit errors on 6216 msgs: 5176 usecs -// indicating a 37-fold resp. 78-fold improvement in speed for 1-bit resp. -// 2-bit error. -/* -unsigned char tmsg0[MODES_LONG_MSG_BYTES] = { - // Test data: first ADS-B message from testfiles/modes1.bin - 0x8f, 0x4d, 0x20, 0x23, 0x58, 0x7f, 0x34, 0x5e, - 0x35, 0x83, 0x7e, 0x22, 0x18, 0xb2 -}; -#define NTWOBITS (MODES_LONG_MSG_BITS*(MODES_LONG_MSG_BITS-1)/2) -unsigned char tmsg1[MODES_LONG_MSG_BITS][MODES_LONG_MSG_BYTES]; -unsigned char tmsg2[NTWOBITS][MODES_LONG_MSG_BYTES]; -// Init an array of cloned messages with all possible 1-bit errors present, -// applied to each message at the respective position -// -void inittmsg1() { - int i, bytepos, mask; - for (i = 0; i < MODES_LONG_MSG_BITS; i++) { - bytepos = i >> 3; - mask = 1 << (7 - (i & 7)); - memcpy(&tmsg1[i][0], tmsg0, MODES_LONG_MSG_BYTES); - tmsg1[i][bytepos] ^= mask; - } -} - -// Run sanity check on all but first 5 messages / bits, as those bits -// are not corrected. -// -void checktmsg1(FILE *out) { - int i, k; - uint32_t crc; - for (i = 5; i < MODES_LONG_MSG_BITS; i++) { - crc = modesChecksum(&tmsg1[i][0], MODES_LONG_MSG_BITS); - if (crc != 0) { - fprintf(out, "CRC not fixed for " - "positon %d\n", i); - fprintf(out, " MSG "); - for (k = 0; k < MODES_LONG_MSG_BYTES; k++) { - fprintf(out, "%02x", tmsg1[i][k]); - } - fprintf(out, "\n"); - } - } -} - -void inittmsg2() { - int i, j, n, bytepos0, bytepos1, mask0, mask1; - n = 0; - for (i = 0; i < MODES_LONG_MSG_BITS; i++) { - bytepos0 = i >> 3; - mask0 = 1 << (7 - (i & 7)); - for (j = i+1; j < MODES_LONG_MSG_BITS; j++) { - bytepos1 = j >> 3; - mask1 = 1 << (7 - (j & 7)); - memcpy(&tmsg2[n][0], tmsg0, MODES_LONG_MSG_BYTES); - tmsg2[n][bytepos0] ^= mask0; - tmsg2[n][bytepos1] ^= mask1; - n += 1; - } - } -} - -long difftvusec(struct timeval *t0, struct timeval *t1) { - long res = 0; - res = t1->tv_usec-t0->tv_usec; - res += (t1->tv_sec-t0->tv_sec)*1000000L; - return res; -} - -// the actual test code -void testAndTimeBitCorrection() { - struct timeval starttv, endtv; - int i; - // Run timing on 1-bit errors - printf("Timing old vs. new crc correction code:\n"); - inittmsg1(); - gettimeofday(&starttv, NULL); - for (i = 0; i < MODES_LONG_MSG_BITS; i++) { - fixSingleBitErrors(&tmsg1[i][0], MODES_LONG_MSG_BITS); - } - gettimeofday(&endtv, NULL); - printf(" Old code: 1-bit errors on %d msgs: %ld usecs\n", - MODES_LONG_MSG_BITS, difftvusec(&starttv, &endtv)); - checktmsg1(stdout); - // Re-init - inittmsg1(); - gettimeofday(&starttv, NULL); - for (i = 0; i < MODES_LONG_MSG_BITS; i++) { - fixBitErrors(&tmsg1[i][0], MODES_LONG_MSG_BITS, MODES_MAX_BITERRORS, NULL); - } - gettimeofday(&endtv, NULL); - printf(" New code: 1-bit errors on %d msgs: %ld usecs\n", - MODES_LONG_MSG_BITS, difftvusec(&starttv, &endtv)); - checktmsg1(stdout); - // Run timing on 2-bit errors - inittmsg2(); - gettimeofday(&starttv, NULL); - for (i = 0; i < NTWOBITS; i++) { - fixSingleBitErrors(&tmsg2[i][0], MODES_LONG_MSG_BITS); - } - gettimeofday(&endtv, NULL); - printf(" Old code: 2-bit errors on %d msgs: %ld usecs\n", - NTWOBITS, difftvusec(&starttv, &endtv)); - // Re-init - inittmsg2(); - gettimeofday(&starttv, NULL); - for (i = 0; i < NTWOBITS; i++) { - fixBitErrors(&tmsg2[i][0], MODES_LONG_MSG_BITS, MODES_MAX_BITERRORS, NULL); - } - gettimeofday(&endtv, NULL); - printf(" New code: 2-bit errors on %d msgs: %ld usecs\n", - NTWOBITS, difftvusec(&starttv, &endtv)); -} -*/ -//========================================================================= -// -// Hash the ICAO address to index our cache of MODES_ICAO_CACHE_LEN -// elements, that is assumed to be a power of two -// -uint32_t ICAOCacheHashAddress(uint32_t a) { - // The following three rounds wil make sure that every bit affects - // every output bit with ~ 50% of probability. - a = ((a >> 16) ^ a) * 0x45d9f3b; - a = ((a >> 16) ^ a) * 0x45d9f3b; - a = ((a >> 16) ^ a); - return a & (MODES_ICAO_CACHE_LEN-1); -} -// -//========================================================================= -// -// Add the specified entry to the cache of recently seen ICAO addresses. -// Note that we also add a timestamp so that we can make sure that the -// entry is only valid for MODES_ICAO_CACHE_TTL seconds. -// -void addRecentlySeenICAOAddr(uint32_t addr) { - uint32_t h = ICAOCacheHashAddress(addr); - Modes.icao_cache[h*2] = addr; - Modes.icao_cache[h*2+1] = (uint32_t) time(NULL); -} -// -//========================================================================= -// -// Returns 1 if the specified ICAO address was seen in a DF format with -// proper checksum (not xored with address) no more than * MODES_ICAO_CACHE_TTL -// seconds ago. Otherwise returns 0. -// -int ICAOAddressWasRecentlySeen(uint32_t addr) { - uint32_t h = ICAOCacheHashAddress(addr); - uint32_t a = Modes.icao_cache[h*2]; - uint32_t t = Modes.icao_cache[h*2+1]; - uint64_t tn = time(NULL); - - return ( (a) && (a == addr) && ( (tn - t) <= MODES_ICAO_CACHE_TTL) ); -} -// -//========================================================================= -// -// In the squawk (identity) field bits are interleaved as follows in -// (message bit 20 to bit 32): -// -// C1-A1-C2-A2-C4-A4-ZERO-B1-D1-B2-D2-B4-D4 -// -// So every group of three bits A, B, C, D represent an integer from 0 to 7. -// -// The actual meaning is just 4 octal numbers, but we convert it into a hex -// number tha happens to represent the four octal numbers. -// -// For more info: http://en.wikipedia.org/wiki/Gillham_code -// -int decodeID13Field(int ID13Field) { - int hexGillham = 0; - - if (ID13Field & 0x1000) {hexGillham |= 0x0010;} // Bit 12 = C1 - if (ID13Field & 0x0800) {hexGillham |= 0x1000;} // Bit 11 = A1 - if (ID13Field & 0x0400) {hexGillham |= 0x0020;} // Bit 10 = C2 - if (ID13Field & 0x0200) {hexGillham |= 0x2000;} // Bit 9 = A2 - if (ID13Field & 0x0100) {hexGillham |= 0x0040;} // Bit 8 = C4 - if (ID13Field & 0x0080) {hexGillham |= 0x4000;} // Bit 7 = A4 - //if (ID13Field & 0x0040) {hexGillham |= 0x0800;} // Bit 6 = X or M - if (ID13Field & 0x0020) {hexGillham |= 0x0100;} // Bit 5 = B1 - if (ID13Field & 0x0010) {hexGillham |= 0x0001;} // Bit 4 = D1 or Q - if (ID13Field & 0x0008) {hexGillham |= 0x0200;} // Bit 3 = B2 - if (ID13Field & 0x0004) {hexGillham |= 0x0002;} // Bit 2 = D2 - if (ID13Field & 0x0002) {hexGillham |= 0x0400;} // Bit 1 = B4 - if (ID13Field & 0x0001) {hexGillham |= 0x0004;} // Bit 0 = D4 - - return (hexGillham); - } -// -//========================================================================= -// -// Decode the 13 bit AC altitude field (in DF 20 and others). -// Returns the altitude, and set 'unit' to either MODES_UNIT_METERS or MDOES_UNIT_FEETS. -// -int decodeAC13Field(int AC13Field, int *unit) { - int m_bit = AC13Field & 0x0040; // set = meters, clear = feet - int q_bit = AC13Field & 0x0010; // set = 25 ft encoding, clear = Gillham Mode C encoding - - if (!m_bit) { - *unit = MODES_UNIT_FEET; - if (q_bit) { - // N is the 11 bit integer resulting from the removal of bit Q and M - int n = ((AC13Field & 0x1F80) >> 2) | - ((AC13Field & 0x0020) >> 1) | - (AC13Field & 0x000F); - // The final altitude is resulting number multiplied by 25, minus 1000. - return ((n * 25) - 1000); - } else { - // N is an 11 bit Gillham coded altitude - int n = ModeAToModeC(decodeID13Field(AC13Field)); - if (n < -12) {n = 0;} - - return (100 * n); - } - } else { - *unit = MODES_UNIT_METERS; - // TODO: Implement altitude when meter unit is selected - } - return 0; -} -// -//========================================================================= -// -// Decode the 12 bit AC altitude field (in DF 17 and others). -// -int decodeAC12Field(int AC12Field, int *unit) { - int q_bit = AC12Field & 0x10; // Bit 48 = Q - - *unit = MODES_UNIT_FEET; - if (q_bit) { - /// N is the 11 bit integer resulting from the removal of bit Q at bit 4 - int n = ((AC12Field & 0x0FE0) >> 1) | - (AC12Field & 0x000F); - // The final altitude is the resulting number multiplied by 25, minus 1000. - return ((n * 25) - 1000); - } else { - // Make N a 13 bit Gillham coded altitude by inserting M=0 at bit 6 - int n = ((AC12Field & 0x0FC0) << 1) | - (AC12Field & 0x003F); - n = ModeAToModeC(decodeID13Field(n)); - if (n < -12) {n = 0;} - - return (100 * n); - } -} -// -//========================================================================= -// -// Decode the 7 bit ground movement field PWL exponential style scale -// -int decodeMovementField(int movement) { - int gspeed; - - // Note : movement codes 0,125,126,127 are all invalid, but they are - // trapped for before this function is called. - - if (movement > 123) gspeed = 199; // > 175kt - else if (movement > 108) gspeed = ((movement - 108) * 5) + 100; - else if (movement > 93) gspeed = ((movement - 93) * 2) + 70; - else if (movement > 38) gspeed = ((movement - 38) ) + 15; - else if (movement > 12) gspeed = ((movement - 11) >> 1) + 2; - else if (movement > 8) gspeed = ((movement - 6) >> 2) + 1; - else gspeed = 0; - - return (gspeed); -} -// -//========================================================================= -// -// Capability table -char *ca_str[8] = { - /* 0 */ "Level 1 (Surveillance Only)", - /* 1 */ "Level 2 (DF0,4,5,11)", - /* 2 */ "Level 3 (DF0,4,5,11,20,21)", - /* 3 */ "Level 4 (DF0,4,5,11,20,21,24)", - /* 4 */ "Level 2+3+4 (DF0,4,5,11,20,21,24,code7 - is on ground)", - /* 5 */ "Level 2+3+4 (DF0,4,5,11,20,21,24,code7 - is airborne)", - /* 6 */ "Level 2+3+4 (DF0,4,5,11,20,21,24,code7)", - /* 7 */ "Level 7 ???" -}; - -// DF 18 Control field table. -char *cf_str[8] = { - /* 0 */ "ADS-B ES/NT device with ICAO 24-bit address", - /* 1 */ "ADS-B ES/NT device with other address", - /* 2 */ "Fine format TIS-B", - /* 3 */ "Coarse format TIS-B", - /* 4 */ "TIS-B management message", - /* 5 */ "TIS-B relay of ADS-B message with other address", - /* 6 */ "ADS-B rebroadcast using DF-17 message format", - /* 7 */ "Reserved" -}; - -// Flight status table -char *fs_str[8] = { - /* 0 */ "Normal, Airborne", - /* 1 */ "Normal, On the ground", - /* 2 */ "ALERT, Airborne", - /* 3 */ "ALERT, On the ground", - /* 4 */ "ALERT & Special Position Identification. Airborne or Ground", - /* 5 */ "Special Position Identification. Airborne or Ground", - /* 6 */ "Value 6 is not assigned", - /* 7 */ "Value 7 is not assigned" -}; - -// Emergency state table -// from https://www.ll.mit.edu/mission/aviation/publications/publication-files/atc-reports/Grappel_2007_ATC-334_WW-15318.pdf -// and 1090-DO-260B_FRAC -char *es_str[8] = { - /* 0 */ "No emergency", - /* 1 */ "General emergency (squawk 7700)", - /* 2 */ "Lifeguard/Medical", - /* 3 */ "Minimum fuel", - /* 4 */ "No communications (squawk 7600)", - /* 5 */ "Unlawful interference (squawk 7500)", - /* 6 */ "Downed Aircraft", - /* 7 */ "Reserved" -}; -// -//========================================================================= -// -char *getMEDescription(int metype, int mesub) { - char *mename = "Unknown"; - - if (metype >= 1 && metype <= 4) - mename = "Aircraft Identification and Category"; - else if (metype >= 5 && metype <= 8) - mename = "Surface Position"; - else if (metype >= 9 && metype <= 18) - mename = "Airborne Position (Baro Altitude)"; - else if (metype == 19 && mesub >=1 && mesub <= 4) - mename = "Airborne Velocity"; - else if (metype >= 20 && metype <= 22) - mename = "Airborne Position (GNSS Height)"; - else if (metype == 23 && mesub == 0) - mename = "Test Message"; - else if (metype == 23 && mesub == 7) - mename = "Test Message -- Squawk"; - else if (metype == 24 && mesub == 1) - mename = "Surface System Status"; - else if (metype == 28 && mesub == 1) - mename = "Extended Squitter Aircraft Status (Emergency)"; - else if (metype == 28 && mesub == 2) - mename = "Extended Squitter Aircraft Status (1090ES TCAS RA)"; - else if (metype == 29 && (mesub == 0 || mesub == 1)) - mename = "Target State and Status Message"; - else if (metype == 31 && (mesub == 0 || mesub == 1)) - mename = "Aircraft Operational Status Message"; - return mename; -} -// -//========================================================================= -// -// Decode a raw Mode S message demodulated as a stream of bytes by detectModeS(), -// and split it into fields populating a modesMessage structure. -// -void decodeModesMessage(struct modesMessage *mm, unsigned char *msg) { - char *ais_charset = "?ABCDEFGHIJKLMNOPQRSTUVWXYZ????? ???????????????0123456789??????"; - - // Work on our local copy - memcpy(mm->msg, msg, MODES_LONG_MSG_BYTES); - msg = mm->msg; - - // Get the message type ASAP as other operations depend on this - mm->msgtype = msg[0] >> 3; // Downlink Format - mm->msgbits = modesMessageLenByType(mm->msgtype); - mm->crc = modesChecksum(msg, mm->msgbits); - - if ((mm->crc) && (Modes.nfix_crc) && ((mm->msgtype == 17) || (mm->msgtype == 18))) { -// if ((mm->crc) && (Modes.nfix_crc) && ((mm->msgtype == 11) || (mm->msgtype == 17))) { - // - // Fixing single bit errors in DF-11 is a bit dodgy because we have no way to - // know for sure if the crc is supposed to be 0 or not - it could be any value - // less than 80. Therefore, attempting to fix DF-11 errors can result in a - // multitude of possible crc solutions, only one of which is correct. - // - // We should probably perform some sanity checks on corrected DF-11's before - // using the results. Perhaps check the ICAO against known aircraft, and check - // IID against known good IID's. That's a TODO. - // - mm->correctedbits = fixBitErrors(msg, mm->msgbits, Modes.nfix_crc, mm->corrected); - - // If we correct, validate ICAO addr to help filter birthday paradox solutions. - if (mm->correctedbits) { - uint32_t ulAddr = (msg[1] << 16) | (msg[2] << 8) | (msg[3]); - if (!ICAOAddressWasRecentlySeen(ulAddr)) - mm->correctedbits = 0; - } - } - // - // Note that most of the other computation happens *after* we fix the - // single/two bit errors, otherwise we would need to recompute the fields again. - // - if (mm->msgtype == 11) { // DF 11 - mm->iid = mm->crc; - mm->addr = (msg[1] << 16) | (msg[2] << 8) | (msg[3]); - mm->ca = (msg[0] & 0x07); // Responder capabilities - - if ((mm->crcok = (0 == mm->crc))) { - // DF 11 : if crc == 0 try to populate our ICAO addresses whitelist. - addRecentlySeenICAOAddr(mm->addr); - } else if (mm->crc < 80) { - mm->crcok = ICAOAddressWasRecentlySeen(mm->addr); - if (mm->crcok) { - addRecentlySeenICAOAddr(mm->addr); - } - } - - } else if (mm->msgtype == 17) { // DF 17 - mm->addr = (msg[1] << 16) | (msg[2] << 8) | (msg[3]); - mm->ca = (msg[0] & 0x07); // Responder capabilities - - if ((mm->crcok = (0 == mm->crc))) { - // DF 17 : if crc == 0 try to populate our ICAO addresses whitelist. - addRecentlySeenICAOAddr(mm->addr); - } - - } else if (mm->msgtype == 18) { // DF 18 - mm->addr = (msg[1] << 16) | (msg[2] << 8) | (msg[3]); - mm->ca = (msg[0] & 0x07); // Control Field - - if ((mm->crcok = (0 == mm->crc))) { - // DF 18 : if crc == 0 try to populate our ICAO addresses whitelist. - addRecentlySeenICAOAddr(mm->addr); - } - - } else { // All other DF's - // Compare the checksum with the whitelist of recently seen ICAO - // addresses. If it matches one, then declare the message as valid - mm->crcok = ICAOAddressWasRecentlySeen(mm->addr = mm->crc); - } - - // If we're checking CRC and the CRC is invalid, then we can't trust any - // of the data contents, so save time and give up now. - if ((Modes.check_crc) && (!mm->crcok) && (!mm->correctedbits)) { return;} - - // Fields for DF0, DF16 - if (mm->msgtype == 0 || mm->msgtype == 16) { - if (msg[0] & 0x04) { // VS Bit - mm->bFlags |= MODES_ACFLAGS_AOG_VALID | MODES_ACFLAGS_AOG; - } else { - mm->bFlags |= MODES_ACFLAGS_AOG_VALID; - } - } - - // Fields for DF11, DF17 - if (mm->msgtype == 11 || mm->msgtype == 17) { - if (mm->ca == 4) { - mm->bFlags |= MODES_ACFLAGS_AOG_VALID | MODES_ACFLAGS_AOG; - } else if (mm->ca == 5) { - mm->bFlags |= MODES_ACFLAGS_AOG_VALID; - } - } - - // Fields for DF5, DF21 = Gillham encoded Squawk - if (mm->msgtype == 5 || mm->msgtype == 21) { - int ID13Field = ((msg[2] << 8) | msg[3]) & 0x1FFF; - if (ID13Field) { - mm->bFlags |= MODES_ACFLAGS_SQUAWK_VALID; - mm->modeA = decodeID13Field(ID13Field); - } - } - - // Fields for DF0, DF4, DF16, DF20 13 bit altitude - if (mm->msgtype == 0 || mm->msgtype == 4 || - mm->msgtype == 16 || mm->msgtype == 20) { - int AC13Field = ((msg[2] << 8) | msg[3]) & 0x1FFF; - if (AC13Field) { // Only attempt to decode if a valid (non zero) altitude is present - mm->bFlags |= MODES_ACFLAGS_ALTITUDE_VALID; - mm->altitude = decodeAC13Field(AC13Field, &mm->unit); - } - } - - // Fields for DF4, DF5, DF20, DF21 - if ((mm->msgtype == 4) || (mm->msgtype == 20) || - (mm->msgtype == 5) || (mm->msgtype == 21)) { - mm->bFlags |= MODES_ACFLAGS_FS_VALID; - mm->fs = msg[0] & 7; // Flight status for DF4,5,20,21 - if (mm->fs <= 3) { - mm->bFlags |= MODES_ACFLAGS_AOG_VALID; - if (mm->fs & 1) - {mm->bFlags |= MODES_ACFLAGS_AOG;} - } - } - - // Fields for DF17, DF18_CF0, DF18_CF1, DF18_CF6 squitters - if ( (mm->msgtype == 17) - || ((mm->msgtype == 18) && ((mm->ca == 0) || (mm->ca == 1) || (mm->ca == 6)) )) { - int metype = mm->metype = msg[4] >> 3; // Extended squitter message type - int mesub = mm->mesub = (metype == 29 ? ((msg[4]&6)>>1) : (msg[4] & 7)); // Extended squitter message subtype - - // Decode the extended squitter message - - if (metype >= 1 && metype <= 4) { // Aircraft Identification and Category - uint32_t chars; - mm->bFlags |= MODES_ACFLAGS_CALLSIGN_VALID; - - chars = (msg[5] << 16) | (msg[6] << 8) | (msg[7]); - mm->flight[3] = ais_charset[chars & 0x3F]; chars = chars >> 6; - mm->flight[2] = ais_charset[chars & 0x3F]; chars = chars >> 6; - mm->flight[1] = ais_charset[chars & 0x3F]; chars = chars >> 6; - mm->flight[0] = ais_charset[chars & 0x3F]; - - chars = (msg[8] << 16) | (msg[9] << 8) | (msg[10]); - mm->flight[7] = ais_charset[chars & 0x3F]; chars = chars >> 6; - mm->flight[6] = ais_charset[chars & 0x3F]; chars = chars >> 6; - mm->flight[5] = ais_charset[chars & 0x3F]; chars = chars >> 6; - mm->flight[4] = ais_charset[chars & 0x3F]; - - mm->flight[8] = '\0'; - - } else if (metype == 19) { // Airborne Velocity Message - - // Presumably airborne if we get an Airborne Velocity Message - mm->bFlags |= MODES_ACFLAGS_AOG_VALID; - - if ( (mesub >= 1) && (mesub <= 4) ) { - int vert_rate = ((msg[8] & 0x07) << 6) | (msg[9] >> 2); - if (vert_rate) { - --vert_rate; - if (msg[8] & 0x08) - {vert_rate = 0 - vert_rate;} - mm->vert_rate = vert_rate * 64; - mm->bFlags |= MODES_ACFLAGS_VERTRATE_VALID; - } - } - - if ((mesub == 1) || (mesub == 2)) { - int ew_raw = ((msg[5] & 0x03) << 8) | msg[6]; - int ew_vel = ew_raw - 1; - int ns_raw = ((msg[7] & 0x7F) << 3) | (msg[8] >> 5); - int ns_vel = ns_raw - 1; - - if (mesub == 2) { // If (supersonic) unit is 4 kts - ns_vel = ns_vel << 2; - ew_vel = ew_vel << 2; - } - - if (ew_raw) { // Do East/West - mm->bFlags |= MODES_ACFLAGS_EWSPEED_VALID; - if (msg[5] & 0x04) - {ew_vel = 0 - ew_vel;} - mm->ew_velocity = ew_vel; - } - - if (ns_raw) { // Do North/South - mm->bFlags |= MODES_ACFLAGS_NSSPEED_VALID; - if (msg[7] & 0x80) - {ns_vel = 0 - ns_vel;} - mm->ns_velocity = ns_vel; - } - - if (ew_raw && ns_raw) { - // Compute velocity and angle from the two speed components - mm->bFlags |= (MODES_ACFLAGS_SPEED_VALID | MODES_ACFLAGS_HEADING_VALID | MODES_ACFLAGS_NSEWSPD_VALID); - mm->velocity = (int) sqrt((ns_vel * ns_vel) + (ew_vel * ew_vel)); - - if (mm->velocity) { - mm->heading = (int) (atan2(ew_vel, ns_vel) * 180.0 / M_PI); - // We don't want negative values but a 0-360 scale - if (mm->heading < 0) mm->heading += 360; - } - } - - } else if (mesub == 3 || mesub == 4) { - int airspeed = ((msg[7] & 0x7f) << 3) | (msg[8] >> 5); - if (airspeed) { - mm->bFlags |= MODES_ACFLAGS_SPEED_VALID; - --airspeed; - if (mesub == 4) // If (supersonic) unit is 4 kts - {airspeed = airspeed << 2;} - mm->velocity = airspeed; - } - - if (msg[5] & 0x04) { - mm->bFlags |= MODES_ACFLAGS_HEADING_VALID; - mm->heading = ((((msg[5] & 0x03) << 8) | msg[6]) * 45) >> 7; - } - } - - } else if (metype >= 5 && metype <= 22) { // Position Message - mm->raw_latitude = ((msg[6] & 3) << 15) | (msg[7] << 7) | (msg[8] >> 1); - mm->raw_longitude = ((msg[8] & 1) << 16) | (msg[9] << 8) | (msg[10]); - mm->bFlags |= (mm->msg[6] & 0x04) ? MODES_ACFLAGS_LLODD_VALID - : MODES_ACFLAGS_LLEVEN_VALID; - if (metype >= 9) { // Airborne - int AC12Field = ((msg[5] << 4) | (msg[6] >> 4)) & 0x0FFF; - mm->bFlags |= MODES_ACFLAGS_AOG_VALID; - if (AC12Field) {// Only attempt to decode if a valid (non zero) altitude is present - mm->bFlags |= MODES_ACFLAGS_ALTITUDE_VALID; - mm->altitude = decodeAC12Field(AC12Field, &mm->unit); - } - } else { // Ground - int movement = ((msg[4] << 4) | (msg[5] >> 4)) & 0x007F; - mm->bFlags |= MODES_ACFLAGS_AOG_VALID | MODES_ACFLAGS_AOG; - if ((movement) && (movement < 125)) { - mm->bFlags |= MODES_ACFLAGS_SPEED_VALID; - mm->velocity = decodeMovementField(movement); - } - - if (msg[5] & 0x08) { - mm->bFlags |= MODES_ACFLAGS_HEADING_VALID; - mm->heading = ((((msg[5] << 4) | (msg[6] >> 4)) & 0x007F) * 45) >> 4; - } - } - - } else if (metype == 23) { // Test metype squawk field - if (mesub == 7) { // (see 1090-WP-15-20) - int ID13Field = (((msg[5] << 8) | msg[6]) & 0xFFF1)>>3; - if (ID13Field) { - mm->bFlags |= MODES_ACFLAGS_SQUAWK_VALID; - mm->modeA = decodeID13Field(ID13Field); - } - } - - } else if (metype == 24) { // Reserved for Surface System Status - - } else if (metype == 28) { // Extended Squitter Aircraft Status - if (mesub == 1) { // Emergency status squawk field - int ID13Field = (((msg[5] << 8) | msg[6]) & 0x1FFF); - if (ID13Field) { - mm->bFlags |= MODES_ACFLAGS_SQUAWK_VALID; - mm->modeA = decodeID13Field(ID13Field); - } - } - - } else if (metype == 29) { // Aircraft Trajectory Intent - - } else if (metype == 30) { // Aircraft Operational Coordination - - } else if (metype == 31) { // Aircraft Operational Status - - } else { // Other metypes - - } - } - - // Fields for DF20, DF21 Comm-B - if ((mm->msgtype == 20) || (mm->msgtype == 21)){ - - if (msg[4] == 0x20) { // Aircraft Identification - uint32_t chars; - mm->bFlags |= MODES_ACFLAGS_CALLSIGN_VALID; - - chars = (msg[5] << 16) | (msg[6] << 8) | (msg[7]); - mm->flight[3] = ais_charset[chars & 0x3F]; chars = chars >> 6; - mm->flight[2] = ais_charset[chars & 0x3F]; chars = chars >> 6; - mm->flight[1] = ais_charset[chars & 0x3F]; chars = chars >> 6; - mm->flight[0] = ais_charset[chars & 0x3F]; - - chars = (msg[8] << 16) | (msg[9] << 8) | (msg[10]); - mm->flight[7] = ais_charset[chars & 0x3F]; chars = chars >> 6; - mm->flight[6] = ais_charset[chars & 0x3F]; chars = chars >> 6; - mm->flight[5] = ais_charset[chars & 0x3F]; chars = chars >> 6; - mm->flight[4] = ais_charset[chars & 0x3F]; - - mm->flight[8] = '\0'; - } else { - } - } -} -// -//========================================================================= -// -// This function gets a decoded Mode S Message and prints it on the screen -// in a human readable format. -// -void displayModesMessage(struct modesMessage *mm) { - int j; - unsigned char * pTimeStamp; - - // Handle only addresses mode first. - if (Modes.onlyaddr) { - printf("%06x\n", mm->addr); - return; // Enough for --onlyaddr mode - } - - // Show the raw message. - if (Modes.mlat && mm->timestampMsg) { - printf("@"); - pTimeStamp = (unsigned char *) &mm->timestampMsg; - for (j=5; j>=0;j--) { - printf("%02X",pTimeStamp[j]); - } - } else - printf("*"); - - for (j = 0; j < mm->msgbits/8; j++) printf("%02x", mm->msg[j]); - printf(";\n"); - - if (Modes.raw) { - fflush(stdout); // Provide data to the reader ASAP - return; // Enough for --raw mode - } - - if (mm->msgtype < 32) - printf("CRC: %06x (%s)\n", (int)mm->crc, mm->crcok ? "ok" : "wrong"); - - if (mm->correctedbits != 0) - printf("No. of bit errors fixed: %d\n", mm->correctedbits); - - if (mm->msgtype == 0) { // DF 0 - printf("DF 0: Short Air-Air Surveillance.\n"); - printf(" VS : %s\n", (mm->msg[0] & 0x04) ? "Ground" : "Airborne"); - printf(" CC : %d\n", ((mm->msg[0] & 0x02) >> 1)); - printf(" SL : %d\n", ((mm->msg[1] & 0xE0) >> 5)); - printf(" Altitude : %d %s\n", mm->altitude, - (mm->unit == MODES_UNIT_METERS) ? "meters" : "feet"); - printf(" ICAO Address : %06x\n", mm->addr); - - } else if (mm->msgtype == 4 || mm->msgtype == 20) { - printf("DF %d: %s, Altitude Reply.\n", mm->msgtype, - (mm->msgtype == 4) ? "Surveillance" : "Comm-B"); - printf(" Flight Status : %s\n", fs_str[mm->fs]); - printf(" DR : %d\n", ((mm->msg[1] >> 3) & 0x1F)); - printf(" UM : %d\n", (((mm->msg[1] & 7) << 3) | (mm->msg[2] >> 5))); - printf(" Altitude : %d %s\n", mm->altitude, - (mm->unit == MODES_UNIT_METERS) ? "meters" : "feet"); - printf(" ICAO Address : %06x\n", mm->addr); - - if (mm->msgtype == 20) { - printf(" Comm-B BDS : %x\n", mm->msg[4]); - - // Decode the extended squitter message - if ( mm->msg[4] == 0x20) { // BDS 2,0 Aircraft identification - printf(" BDS 2,0 Aircraft Identification : %s\n", mm->flight); -/* - } else if ( mm->msg[4] == 0x10) { // BDS 1,0 Datalink Capability report - printf(" BDS 1,0 Datalink Capability report\n"); - - } else if ( mm->msg[4] == 0x30) { // BDS 3,0 ACAS Active Resolution Advisory - printf(" BDS 3,0 ACAS Active Resolution Advisory\n"); - - } else if ((mm->msg[4] >> 3) == 28) { // BDS 6,1 Extended Squitter Emergency/Priority Status - printf(" BDS 6,1 Emergency/Priority Status\n"); - - } else if ((mm->msg[4] >> 3) == 29) { // BDS 6,2 Target State and Status - printf(" BDS 6,2 Target State and Status\n"); - - } else if ((mm->msg[4] >> 3) == 31) { // BDS 6,5 Extended Squitter Aircraft Operational Status - printf(" BDS 6,5 Aircraft Operational Status\n"); -*/ - } - } - - } else if (mm->msgtype == 5 || mm->msgtype == 21) { - printf("DF %d: %s, Identity Reply.\n", mm->msgtype, - (mm->msgtype == 5) ? "Surveillance" : "Comm-B"); - printf(" Flight Status : %s\n", fs_str[mm->fs]); - printf(" DR : %d\n", ((mm->msg[1] >> 3) & 0x1F)); - printf(" UM : %d\n", (((mm->msg[1] & 7) << 3) | (mm->msg[2] >> 5))); - printf(" Squawk : %04x\n", mm->modeA); - printf(" ICAO Address : %06x\n", mm->addr); - - if (mm->msgtype == 21) { - printf(" Comm-B BDS : %x\n", mm->msg[4]); - - // Decode the extended squitter message - if ( mm->msg[4] == 0x20) { // BDS 2,0 Aircraft identification - printf(" BDS 2,0 Aircraft Identification : %s\n", mm->flight); -/* - } else if ( mm->msg[4] == 0x10) { // BDS 1,0 Datalink Capability report - printf(" BDS 1,0 Datalink Capability report\n"); - - } else if ( mm->msg[4] == 0x30) { // BDS 3,0 ACAS Active Resolution Advisory - printf(" BDS 3,0 ACAS Active Resolution Advisory\n"); - - } else if ((mm->msg[4] >> 3) == 28) { // BDS 6,1 Extended Squitter Emergency/Priority Status - printf(" BDS 6,1 Emergency/Priority Status\n"); - - } else if ((mm->msg[4] >> 3) == 29) { // BDS 6,2 Target State and Status - printf(" BDS 6,2 Target State and Status\n"); - - } else if ((mm->msg[4] >> 3) == 31) { // BDS 6,5 Extended Squitter Aircraft Operational Status - printf(" BDS 6,5 Aircraft Operational Status\n"); -*/ - } - } - - } else if (mm->msgtype == 11) { // DF 11 - printf("DF 11: All Call Reply.\n"); - printf(" Capability : %d (%s)\n", mm->ca, ca_str[mm->ca]); - printf(" ICAO Address: %06x\n", mm->addr); - if (mm->iid > 16) - {printf(" IID : SI-%02d\n", mm->iid-16);} - else - {printf(" IID : II-%02d\n", mm->iid);} - - } else if (mm->msgtype == 16) { // DF 16 - printf("DF 16: Long Air to Air ACAS\n"); - printf(" VS : %s\n", (mm->msg[0] & 0x04) ? "Ground" : "Airborne"); - printf(" CC : %d\n", ((mm->msg[0] & 0x02) >> 1)); - printf(" SL : %d\n", ((mm->msg[1] & 0xE0) >> 5)); - printf(" Altitude : %d %s\n", mm->altitude, - (mm->unit == MODES_UNIT_METERS) ? "meters" : "feet"); - printf(" ICAO Address : %06x\n", mm->addr); - - } else if (mm->msgtype == 17) { // DF 17 - printf("DF 17: ADS-B message.\n"); - printf(" Capability : %d (%s)\n", mm->ca, ca_str[mm->ca]); - printf(" ICAO Address : %06x\n", mm->addr); - printf(" Extended Squitter Type: %d\n", mm->metype); - printf(" Extended Squitter Sub : %d\n", mm->mesub); - printf(" Extended Squitter Name: %s\n", getMEDescription(mm->metype, mm->mesub)); - - // Decode the extended squitter message - if (mm->metype >= 1 && mm->metype <= 4) { // Aircraft identification - printf(" Aircraft Type : %c%d\n", ('A' + 4 - mm->metype), mm->mesub); - printf(" Identification : %s\n", mm->flight); - - } else if (mm->metype == 19) { // Airborne Velocity - if (mm->mesub == 1 || mm->mesub == 2) { - printf(" EW status : %s\n", (mm->bFlags & MODES_ACFLAGS_EWSPEED_VALID) ? "Valid" : "Unavailable"); - printf(" EW velocity : %d\n", mm->ew_velocity); - printf(" NS status : %s\n", (mm->bFlags & MODES_ACFLAGS_NSSPEED_VALID) ? "Valid" : "Unavailable"); - printf(" NS velocity : %d\n", mm->ns_velocity); - printf(" Vertical status : %s\n", (mm->bFlags & MODES_ACFLAGS_VERTRATE_VALID) ? "Valid" : "Unavailable"); - printf(" Vertical rate src : %d\n", ((mm->msg[8] >> 4) & 1)); - printf(" Vertical rate : %d\n", mm->vert_rate); - - } else if (mm->mesub == 3 || mm->mesub == 4) { - printf(" Heading status : %s\n", (mm->bFlags & MODES_ACFLAGS_HEADING_VALID) ? "Valid" : "Unavailable"); - printf(" Heading : %d\n", mm->heading); - printf(" Airspeed status : %s\n", (mm->bFlags & MODES_ACFLAGS_SPEED_VALID) ? "Valid" : "Unavailable"); - printf(" Airspeed : %d\n", mm->velocity); - printf(" Vertical status : %s\n", (mm->bFlags & MODES_ACFLAGS_VERTRATE_VALID) ? "Valid" : "Unavailable"); - printf(" Vertical rate src : %d\n", ((mm->msg[8] >> 4) & 1)); - printf(" Vertical rate : %d\n", mm->vert_rate); - - } else { - printf(" Unrecognized ME subtype: %d subtype: %d\n", mm->metype, mm->mesub); - } - - } else if (mm->metype >= 5 && mm->metype <= 22) { // Airborne position Baro - printf(" F flag : %s\n", (mm->msg[6] & 0x04) ? "odd" : "even"); - printf(" T flag : %s\n", (mm->msg[6] & 0x08) ? "UTC" : "non-UTC"); - printf(" Altitude : %d feet\n", mm->altitude); - if (mm->bFlags & MODES_ACFLAGS_LATLON_VALID) { - printf(" Latitude : %f\n", mm->fLat); - printf(" Longitude: %f\n", mm->fLon); - } else { - printf(" Latitude : %d (not decoded)\n", mm->raw_latitude); - printf(" Longitude: %d (not decoded)\n", mm->raw_longitude); - } - - } else if (mm->metype == 28) { // Extended Squitter Aircraft Status - if (mm->mesub == 1) { - printf(" Emergency State: %s\n", es_str[(mm->msg[5] & 0xE0) >> 5]); - printf(" Squawk: %04x\n", mm->modeA); - } else { - printf(" Unrecognized ME subtype: %d subtype: %d\n", mm->metype, mm->mesub); - } - - } else if (mm->metype == 23) { // Test Message - if (mm->mesub == 7) { - printf(" Squawk: %04x\n", mm->modeA); - } else { - printf(" Unrecognized ME subtype: %d subtype: %d\n", mm->metype, mm->mesub); - } - } else { - printf(" Unrecognized ME type: %d subtype: %d\n", mm->metype, mm->mesub); - } - - } else if (mm->msgtype == 18) { // DF 18 - printf("DF 18: Extended Squitter.\n"); - printf(" Control Field : %d (%s)\n", mm->ca, cf_str[mm->ca]); - if ((mm->ca == 0) || (mm->ca == 1) || (mm->ca == 6)) { - if (mm->ca == 1) { - printf(" Other Address : %06x\n", mm->addr); - } else { - printf(" ICAO Address : %06x\n", mm->addr); - } - printf(" Extended Squitter Type: %d\n", mm->metype); - printf(" Extended Squitter Sub : %d\n", mm->mesub); - printf(" Extended Squitter Name: %s\n", getMEDescription(mm->metype, mm->mesub)); - - // Decode the extended squitter message - if (mm->metype >= 1 && mm->metype <= 4) { // Aircraft identification - printf(" Aircraft Type : %c%d\n", ('A' + 4 - mm->metype), mm->mesub); - printf(" Identification : %s\n", mm->flight); - - } else if (mm->metype == 19) { // Airborne Velocity - if (mm->mesub == 1 || mm->mesub == 2) { - printf(" EW status : %s\n", (mm->bFlags & MODES_ACFLAGS_EWSPEED_VALID) ? "Valid" : "Unavailable"); - printf(" EW velocity : %d\n", mm->ew_velocity); - printf(" NS status : %s\n", (mm->bFlags & MODES_ACFLAGS_NSSPEED_VALID) ? "Valid" : "Unavailable"); - printf(" NS velocity : %d\n", mm->ns_velocity); - printf(" Vertical status : %s\n", (mm->bFlags & MODES_ACFLAGS_VERTRATE_VALID) ? "Valid" : "Unavailable"); - printf(" Vertical rate src : %d\n", ((mm->msg[8] >> 4) & 1)); - printf(" Vertical rate : %d\n", mm->vert_rate); - - } else if (mm->mesub == 3 || mm->mesub == 4) { - printf(" Heading status : %s\n", (mm->bFlags & MODES_ACFLAGS_HEADING_VALID) ? "Valid" : "Unavailable"); - printf(" Heading : %d\n", mm->heading); - printf(" Airspeed status : %s\n", (mm->bFlags & MODES_ACFLAGS_SPEED_VALID) ? "Valid" : "Unavailable"); - printf(" Airspeed : %d\n", mm->velocity); - printf(" Vertical status : %s\n", (mm->bFlags & MODES_ACFLAGS_VERTRATE_VALID) ? "Valid" : "Unavailable"); - printf(" Vertical rate src : %d\n", ((mm->msg[8] >> 4) & 1)); - printf(" Vertical rate : %d\n", mm->vert_rate); - - } else { - printf(" Unrecognized ME subtype: %d subtype: %d\n", mm->metype, mm->mesub); - } - - } else if (mm->metype >= 5 && mm->metype <= 22) { // Ground or Airborne position, Baro or GNSS - printf(" F flag : %s\n", (mm->msg[6] & 0x04) ? "odd" : "even"); - printf(" T flag : %s\n", (mm->msg[6] & 0x08) ? "UTC" : "non-UTC"); - printf(" Altitude : %d feet\n", mm->altitude); - if (mm->bFlags & MODES_ACFLAGS_LATLON_VALID) { - printf(" Latitude : %f\n", mm->fLat); - printf(" Longitude: %f\n", mm->fLon); - } else { - printf(" Latitude : %d (not decoded)\n", mm->raw_latitude); - printf(" Longitude: %d (not decoded)\n", mm->raw_longitude); - } - - } else { - printf(" Unrecognized ME type: %d subtype: %d\n", mm->metype, mm->mesub); - } - } - - } else if (mm->msgtype == 19) { // DF 19 - printf("DF 19: Military Extended Squitter.\n"); - - } else if (mm->msgtype == 22) { // DF 22 - printf("DF 22: Military Use.\n"); - - } else if (mm->msgtype == 24) { // DF 24 - printf("DF 24: Comm D Extended Length Message.\n"); - - } else if (mm->msgtype == 32) { // DF 32 is special code we use for Mode A/C - printf("SSR : Mode A/C Reply.\n"); - if (mm->fs & 0x0080) { - printf(" Mode A : %04x IDENT\n", mm->modeA); - } else { - printf(" Mode A : %04x\n", mm->modeA); - if (mm->bFlags & MODES_ACFLAGS_ALTITUDE_VALID) - {printf(" Mode C : %d feet\n", mm->altitude);} - } - - } else { - printf("DF %d: Unknown DF Format.\n", mm->msgtype); - } - - printf("\n"); -} -// -//========================================================================= -// -// Turn I/Q samples pointed by Modes.data into the magnitude vector -// pointed by Modes.magnitude. -// -void computeMagnitudeVector(uint16_t *p) { - uint16_t *m = &Modes.magnitude[MODES_PREAMBLE_SAMPLES+MODES_LONG_MSG_SAMPLES]; - uint32_t j; - - memcpy(Modes.magnitude,&Modes.magnitude[MODES_ASYNC_BUF_SAMPLES], MODES_PREAMBLE_SIZE+MODES_LONG_MSG_SIZE); - - // Compute the magnitudo vector. It's just SQRT(I^2 + Q^2), but - // we rescale to the 0-255 range to exploit the full resolution. - for (j = 0; j < MODES_ASYNC_BUF_SAMPLES; j ++) { - *m++ = Modes.maglut[*p++]; - } -} -// -//========================================================================= -// -// Return -1 if the message is out of fase left-side -// Return 1 if the message is out of fase right-size -// Return 0 if the message is not particularly out of phase. -// -// Note: this function will access pPreamble[-1], so the caller should make sure to -// call it only if we are not at the start of the current buffer -// -int detectOutOfPhase(uint16_t *pPreamble) { - if (pPreamble[ 3] > pPreamble[2]/3) return 1; - if (pPreamble[10] > pPreamble[9]/3) return 1; - if (pPreamble[ 6] > pPreamble[7]/3) return -1; - if (pPreamble[-1] > pPreamble[1]/3) return -1; - return 0; -} - - -uint16_t clamped_scale(uint16_t v, uint16_t scale) { - uint32_t scaled = (uint32_t)v * scale / 16384; - if (scaled > 65535) return 65535; - return (uint16_t) scaled; -} -// This function decides whether we are sampling early or late, -// and by approximately how much, by looking at the energy in -// preamble bits before and after the expected pulse locations. -// -// It then deals with one sample pair at a time, comparing samples -// to make a decision about the bit value. Based on this decision it -// modifies the sample value of the *adjacent* sample which will -// contain some of the energy from the bit we just inspected. -// -// pPayload[0] should be the start of the preamble, -// pPayload[-1 .. MODES_PREAMBLE_SAMPLES + MODES_LONG_MSG_SAMPLES - 1] should be accessible. -// pPayload[MODES_PREAMBLE_SAMPLES .. MODES_PREAMBLE_SAMPLES + MODES_LONG_MSG_SAMPLES - 1] will be updated. -void applyPhaseCorrection(uint16_t *pPayload) { - int j; - - // we expect 1 bits at 0, 2, 7, 9 - // and 0 bits at -1, 1, 3, 4, 5, 6, 8, 10, 11, 12, 13, 14 - // use bits -1,6 for early detection (bit 0/7 arrived a little early, our sample period starts after the bit phase so we include some of the next bit) - // use bits 3,10 for late detection (bit 2/9 arrived a little late, our sample period starts before the bit phase so we include some of the last bit) - - uint32_t onTime = (pPayload[0] + pPayload[2] + pPayload[7] + pPayload[9]); - uint32_t early = (pPayload[-1] + pPayload[6]) << 1; - uint32_t late = (pPayload[3] + pPayload[10]) << 1; - - if (early > late) { - // Our sample period starts late and so includes some of the next bit. - - uint16_t scaleUp = 16384 + 16384 * early / (early + onTime); // 1 + early / (early+onTime) - uint16_t scaleDown = 16384 - 16384 * early / (early + onTime); // 1 - early / (early+onTime) - - // trailing bits are 0; final data sample will be a bit low. - pPayload[MODES_PREAMBLE_SAMPLES + MODES_LONG_MSG_SAMPLES - 1] = - clamped_scale(pPayload[MODES_PREAMBLE_SAMPLES + MODES_LONG_MSG_SAMPLES - 1], scaleUp); - for (j = MODES_PREAMBLE_SAMPLES + MODES_LONG_MSG_SAMPLES - 2; j > MODES_PREAMBLE_SAMPLES; j -= 2) { - if (pPayload[j] > pPayload[j+1]) { - // x [1 0] y - // x overlapped with the "1" bit and is slightly high - pPayload[j-1] = clamped_scale(pPayload[j-1], scaleDown); - } else { - // x [0 1] y - // x overlapped with the "0" bit and is slightly low - pPayload[j-1] = clamped_scale(pPayload[j-1], scaleUp); - } - } - } else { - // Our sample period starts early and so includes some of the previous bit. - - uint16_t scaleUp = 16384 + 16384 * late / (late + onTime); // 1 + late / (late+onTime) - uint16_t scaleDown = 16384 - 16384 * late / (late + onTime); // 1 - late / (late+onTime) - - // leading bits are 0; first data sample will be a bit low. - pPayload[MODES_PREAMBLE_SAMPLES] = clamped_scale(pPayload[MODES_PREAMBLE_SAMPLES], scaleUp); - for (j = MODES_PREAMBLE_SAMPLES; j < MODES_PREAMBLE_SAMPLES + MODES_LONG_MSG_SAMPLES - 2; j += 2) { - if (pPayload[j] > pPayload[j+1]) { - // x [1 0] y - // y overlapped with the "0" bit and is slightly low - pPayload[j+2] = clamped_scale(pPayload[j+2], scaleUp); - } else { - // x [0 1] y - // y overlapped with the "1" bit and is slightly high - pPayload[j+2] = clamped_scale(pPayload[j+2], scaleDown); - } - } - } -} -// -//========================================================================= -// -// Detect a Mode S messages inside the magnitude buffer pointed by 'm' and of -// size 'mlen' bytes. Every detected Mode S message is convert it into a -// stream of bits and passed to the function to display it. -// -void detectModeS(uint16_t *m, uint32_t mlen) { - struct modesMessage mm; - unsigned char msg[MODES_LONG_MSG_BYTES], *pMsg; - uint16_t aux[MODES_PREAMBLE_SAMPLES+MODES_LONG_MSG_SAMPLES+1]; - uint32_t j; - int use_correction = 0; - - memset(&mm, 0, sizeof(mm)); - - // The Mode S preamble is made of impulses of 0.5 microseconds at - // the following time offsets: - // - // 0 - 0.5 usec: first impulse. - // 1.0 - 1.5 usec: second impulse. - // 3.5 - 4 usec: third impulse. - // 4.5 - 5 usec: last impulse. - // - // Since we are sampling at 2 Mhz every sample in our magnitude vector - // is 0.5 usec, so the preamble will look like this, assuming there is - // an impulse at offset 0 in the array: - // - // 0 ----------------- - // 1 - - // 2 ------------------ - // 3 -- - // 4 - - // 5 -- - // 6 - - // 7 ------------------ - // 8 -- - // 9 ------------------- - // - for (j = 0; j < mlen; j++) { - int high, i, errors, errors56, errorsTy; - uint16_t *pPreamble, *pPayload, *pPtr; - uint8_t theByte, theErrs; - int msglen, scanlen, sigStrength; - - pPreamble = &m[j]; - pPayload = &m[j+MODES_PREAMBLE_SAMPLES]; - - // Rather than clear the whole mm structure, just clear the parts which are required. The clear - // is required for every bit of the input stream, and we don't want to be memset-ing the whole - // modesMessage structure two million times per second if we don't have to.. - mm.bFlags = - mm.crcok = - mm.correctedbits = 0; - - if (!use_correction) // This is not a re-try with phase correction - { // so try to find a new preamble - - if (Modes.mode_ac) - { - int ModeA = detectModeA(pPreamble, &mm); - - if (ModeA) // We have found a valid ModeA/C in the data - { - mm.timestampMsg = Modes.timestampBlk + ((j+1) * 6); - - // Decode the received message - decodeModeAMessage(&mm, ModeA); - - // Pass data to the next layer - useModesMessage(&mm); - - j += MODEAC_MSG_SAMPLES; - Modes.stat_ModeAC++; - continue; - } - } - - // First check of relations between the first 10 samples - // representing a valid preamble. We don't even investigate further - // if this simple test is not passed - if (!(pPreamble[0] > pPreamble[1] && - pPreamble[1] < pPreamble[2] && - pPreamble[2] > pPreamble[3] && - pPreamble[3] < pPreamble[0] && - pPreamble[4] < pPreamble[0] && - pPreamble[5] < pPreamble[0] && - pPreamble[6] < pPreamble[0] && - pPreamble[7] > pPreamble[8] && - pPreamble[8] < pPreamble[9] && - pPreamble[9] > pPreamble[6])) - { - if (Modes.debug & MODES_DEBUG_NOPREAMBLE && - *pPreamble > MODES_DEBUG_NOPREAMBLE_LEVEL) - dumpRawMessage("Unexpected ratio among first 10 samples", msg, m, j); - continue; - } - - // The samples between the two spikes must be < than the average - // of the high spikes level. We don't test bits too near to - // the high levels as signals can be out of phase so part of the - // energy can be in the near samples - high = (pPreamble[0] + pPreamble[2] + pPreamble[7] + pPreamble[9]) / 6; - if (pPreamble[4] >= high || - pPreamble[5] >= high) - { - if (Modes.debug & MODES_DEBUG_NOPREAMBLE && - *pPreamble > MODES_DEBUG_NOPREAMBLE_LEVEL) - dumpRawMessage("Too high level in samples between 3 and 6", msg, m, j); - continue; - } - - // Similarly samples in the range 11-14 must be low, as it is the - // space between the preamble and real data. Again we don't test - // bits too near to high levels, see above - if (pPreamble[11] >= high || - pPreamble[12] >= high || - pPreamble[13] >= high || - pPreamble[14] >= high) - { - if (Modes.debug & MODES_DEBUG_NOPREAMBLE && - *pPreamble > MODES_DEBUG_NOPREAMBLE_LEVEL) - dumpRawMessage("Too high level in samples between 10 and 15", msg, m, j); - continue; - } - Modes.stat_valid_preamble++; - } - - else { - // If the previous attempt with this message failed, retry using - // magnitude correction - // Make a copy of the Payload, and phase correct the copy - memcpy(aux, &pPreamble[-1], sizeof(aux)); - applyPhaseCorrection(&aux[1]); - Modes.stat_out_of_phase++; - pPayload = &aux[1 + MODES_PREAMBLE_SAMPLES]; - // TODO ... apply other kind of corrections - } - - // Decode all the next 112 bits, regardless of the actual message - // size. We'll check the actual message type later - pMsg = &msg[0]; - pPtr = pPayload; - theByte = 0; - theErrs = 0; errorsTy = 0; - errors = 0; errors56 = 0; - - // We should have 4 'bits' of 0/1 and 1/0 samples in the preamble, - // so include these in the signal strength - sigStrength = (pPreamble[0]-pPreamble[1]) - + (pPreamble[2]-pPreamble[3]) - + (pPreamble[7]-pPreamble[6]) - + (pPreamble[9]-pPreamble[8]); - - msglen = scanlen = MODES_LONG_MSG_BITS; - for (i = 0; i < scanlen; i++) { - uint32_t a = *pPtr++; - uint32_t b = *pPtr++; - - if (a > b) - {theByte |= 1; if (i < 56) {sigStrength += (a-b);}} - else if (a < b) - {/*theByte |= 0;*/ if (i < 56) {sigStrength += (b-a);}} - else if (i >= MODES_SHORT_MSG_BITS) //(a == b), and we're in the long part of a frame - {errors++; /*theByte |= 0;*/} - else if (i >= 5) //(a == b), and we're in the short part of a frame - {scanlen = MODES_LONG_MSG_BITS; errors56 = ++errors;/*theByte |= 0;*/} - else if (i) //(a == b), and we're in the message type part of a frame - {errorsTy = errors56 = ++errors; theErrs |= 1; /*theByte |= 0;*/} - else //(a == b), and we're in the first bit of the message type part of a frame - {errorsTy = errors56 = ++errors; theErrs |= 1; theByte |= 1;} - - if ((i & 7) == 7) - {*pMsg++ = theByte;} - else if (i == 4) { - msglen = modesMessageLenByType(theByte); - if (errors == 0) - {scanlen = msglen;} - } - - theByte = theByte << 1; - if (i < 7) - {theErrs = theErrs << 1;} - - // If we've exceeded the permissible number of encoding errors, abandon ship now - if (errors > MODES_MSG_ENCODER_ERRS) { - - if (i < MODES_SHORT_MSG_BITS) { - msglen = 0; - - } else if ((errorsTy == 1) && (theErrs == 0x80)) { - // If we only saw one error in the first bit of the byte of the frame, then it's possible - // we guessed wrongly about the value of the bit. We may be able to correct it by guessing - // the other way. - // - // We guessed a '1' at bit 7, which is the DF length bit == 112 Bits. - // Inverting bit 7 will change the message type from a long to a short. - // Invert the bit, cross your fingers and carry on. - msglen = MODES_SHORT_MSG_BITS; - msg[0] ^= theErrs; errorsTy = 0; - errors = errors56; // revert to the number of errors prior to bit 56 - Modes.stat_DF_Len_Corrected++; - - } else if (i < MODES_LONG_MSG_BITS) { - msglen = MODES_SHORT_MSG_BITS; - errors = errors56; - - } else { - msglen = MODES_LONG_MSG_BITS; - } - - break; - } - } - - // Ensure msglen is consistent with the DF type - i = modesMessageLenByType(msg[0] >> 3); - if (msglen > i) {msglen = i;} - else if (msglen < i) {msglen = 0;} - - // - // If we guessed at any of the bits in the DF type field, then look to see if our guess was sensible. - // Do this by looking to see if the original guess results in the DF type being one of the ICAO defined - // message types. If it isn't then toggle the guessed bit and see if this new value is ICAO defined. - // if the new value is ICAO defined, then update it in our message. - if ((msglen) && (errorsTy == 1) && (theErrs & 0x78)) { - // We guessed at one (and only one) of the message type bits. See if our guess is "likely" - // to be correct by comparing the DF against a list of known good DF's - int thisDF = ((theByte = msg[0]) >> 3) & 0x1f; - uint32_t validDFbits = 0x017F0831; // One bit per 32 possible DF's. Set bits 0,4,5,11,16.17.18.19,20,21,22,24 - uint32_t thisDFbit = (1 << thisDF); - if (0 == (validDFbits & thisDFbit)) { - // The current DF is not ICAO defined, so is probably an errors. - // Toggle the bit we guessed at and see if the resultant DF is more likely - theByte ^= theErrs; - thisDF = (theByte >> 3) & 0x1f; - thisDFbit = (1 << thisDF); - // if this DF any more likely? - if (validDFbits & thisDFbit) { - // Yep, more likely, so update the main message - msg[0] = theByte; - Modes.stat_DF_Type_Corrected++; - errors--; // decrease the error count so we attempt to use the modified DF. - } - } - } - - // We measured signal strength over the first 56 bits. Don't forget to add 4 - // for the preamble samples, so round up and divide by 60. - sigStrength = (sigStrength + 29) / 60; - - // When we reach this point, if error is small, and the signal strength is large enough - // we may have a Mode S message on our hands. It may still be broken and the CRC may not - // be correct, but this can be handled by the next layer. - if ( (msglen) - && (sigStrength > MODES_MSG_SQUELCH_LEVEL) - && (errors <= MODES_MSG_ENCODER_ERRS) ) { - - // Set initial mm structure details - mm.timestampMsg = Modes.timestampBlk + (j*6); - sigStrength = (sigStrength + 0x7F) >> 8; - mm.signalLevel = ((sigStrength < 255) ? sigStrength : 255); - mm.phase_corrected = use_correction; - - // Decode the received message - decodeModesMessage(&mm, msg); - - // Update statistics - if (Modes.stats) { - if (mm.crcok || use_correction || mm.correctedbits) { - - if (use_correction) { - switch (errors) { - case 0: {Modes.stat_ph_demodulated0++; break;} - case 1: {Modes.stat_ph_demodulated1++; break;} - case 2: {Modes.stat_ph_demodulated2++; break;} - default:{Modes.stat_ph_demodulated3++; break;} - } - } else { - switch (errors) { - case 0: {Modes.stat_demodulated0++; break;} - case 1: {Modes.stat_demodulated1++; break;} - case 2: {Modes.stat_demodulated2++; break;} - default:{Modes.stat_demodulated3++; break;} - } - } - - if (mm.correctedbits == 0) { - if (use_correction) { - if (mm.crcok) {Modes.stat_ph_goodcrc++;} - else {Modes.stat_ph_badcrc++;} - } else { - if (mm.crcok) {Modes.stat_goodcrc++;} - else {Modes.stat_badcrc++;} - } - - } else if (use_correction) { - Modes.stat_ph_badcrc++; - Modes.stat_ph_fixed++; - if ( (mm.correctedbits) - && (mm.correctedbits <= MODES_MAX_BITERRORS) ) { - Modes.stat_ph_bit_fix[mm.correctedbits-1] += 1; - } - - } else { - Modes.stat_badcrc++; - Modes.stat_fixed++; - if ( (mm.correctedbits) - && (mm.correctedbits <= MODES_MAX_BITERRORS) ) { - Modes.stat_bit_fix[mm.correctedbits-1] += 1; - } - } - } - } - - // Output debug mode info if needed - if (use_correction) { - if (Modes.debug & MODES_DEBUG_DEMOD) - dumpRawMessage("Demodulated with 0 errors", msg, m, j); - else if (Modes.debug & MODES_DEBUG_BADCRC && - mm.msgtype == 17 && - (!mm.crcok || mm.correctedbits != 0)) - dumpRawMessage("Decoded with bad CRC", msg, m, j); - else if (Modes.debug & MODES_DEBUG_GOODCRC && mm.crcok && - mm.correctedbits == 0) - dumpRawMessage("Decoded with good CRC", msg, m, j); - } - - // Skip this message if we are sure it's fine - if (mm.crcok) { - j += (MODES_PREAMBLE_US+msglen)*2 - 1; - } - - // Pass data to the next layer - useModesMessage(&mm); - - } else { - if (Modes.debug & MODES_DEBUG_DEMODERR && use_correction) { - printf("The following message has %d demod errors\n", errors); - dumpRawMessage("Demodulated with errors", msg, m, j); - } - } - - // Retry with phase correction if enabled, necessary and possible. - if (Modes.phase_enhance && !mm.crcok && !mm.correctedbits && !use_correction && j && detectOutOfPhase(pPreamble)) { - use_correction = 1; j--; - } else { - use_correction = 0; - } - } - - //Send any remaining partial raw buffers now - if (Modes.rawOutUsed || Modes.beastOutUsed) - { - Modes.net_output_raw_rate_count++; - if (Modes.net_output_raw_rate_count > Modes.net_output_raw_rate) - { - if (Modes.rawOutUsed) { - modesSendAllClients(Modes.ros, Modes.rawOut, Modes.rawOutUsed); - Modes.rawOutUsed = 0; - } - if (Modes.beastOutUsed) { - modesSendAllClients(Modes.bos, Modes.beastOut, Modes.beastOutUsed); - Modes.beastOutUsed = 0; - } - Modes.net_output_raw_rate_count = 0; - } - } - else if ( (Modes.net) - && (Modes.net_heartbeat_rate) - && ((++Modes.net_heartbeat_count) > Modes.net_heartbeat_rate) ) { - // - // We haven't received any Mode A/C/S messages for some time. To try and keep any TCP - // links alive, send a null frame. This will help stop any routers discarding our TCP - // link which will cause an un-recoverable link error if/when a real frame arrives. - // - // Fudge up a null message - memset(&mm, 0, sizeof(mm)); - mm.msgbits = MODES_SHORT_MSG_BITS; - mm.timestampMsg = Modes.timestampBlk; - - // Feed output clients - modesQueueOutput(&mm); - - // Reset the heartbeat counter - Modes.net_heartbeat_count = 0; - } -} -// -//========================================================================= -// -// When a new message is available, because it was decoded from the RTL device, -// file, or received in the TCP input port, or any other way we can receive a -// decoded message, we call this function in order to use the message. -// -// Basically this function passes a raw message to the upper layers for further -// processing and visualization -// -void useModesMessage(struct modesMessage *mm) { - if ((Modes.check_crc == 0) || (mm->crcok) || (mm->correctedbits)) { // not checking, ok or fixed - - // Always track aircraft - interactiveReceiveData(mm); - - // In non-interactive non-quiet mode, display messages on standard output - if (!Modes.interactive && !Modes.quiet) { - displayModesMessage(mm); - } - - // Feed output clients - if (Modes.net) {modesQueueOutput(mm);} - - // Heartbeat not required whilst we're seeing real messages - Modes.net_heartbeat_count = 0; - } -} -// -//========================================================================= -// -// Always positive MOD operation, used for CPR decoding. -// -int cprModFunction(int a, int b) { - int res = a % b; - if (res < 0) res += b; - return res; -} -// -//========================================================================= -// -// The NL function uses the precomputed table from 1090-WP-9-14 -// -int cprNLFunction(double lat) { - if (lat < 0) lat = -lat; // Table is simmetric about the equator - if (lat < 10.47047130) return 59; - if (lat < 14.82817437) return 58; - if (lat < 18.18626357) return 57; - if (lat < 21.02939493) return 56; - if (lat < 23.54504487) return 55; - if (lat < 25.82924707) return 54; - if (lat < 27.93898710) return 53; - if (lat < 29.91135686) return 52; - if (lat < 31.77209708) return 51; - if (lat < 33.53993436) return 50; - if (lat < 35.22899598) return 49; - if (lat < 36.85025108) return 48; - if (lat < 38.41241892) return 47; - if (lat < 39.92256684) return 46; - if (lat < 41.38651832) return 45; - if (lat < 42.80914012) return 44; - if (lat < 44.19454951) return 43; - if (lat < 45.54626723) return 42; - if (lat < 46.86733252) return 41; - if (lat < 48.16039128) return 40; - if (lat < 49.42776439) return 39; - if (lat < 50.67150166) return 38; - if (lat < 51.89342469) return 37; - if (lat < 53.09516153) return 36; - if (lat < 54.27817472) return 35; - if (lat < 55.44378444) return 34; - if (lat < 56.59318756) return 33; - if (lat < 57.72747354) return 32; - if (lat < 58.84763776) return 31; - if (lat < 59.95459277) return 30; - if (lat < 61.04917774) return 29; - if (lat < 62.13216659) return 28; - if (lat < 63.20427479) return 27; - if (lat < 64.26616523) return 26; - if (lat < 65.31845310) return 25; - if (lat < 66.36171008) return 24; - if (lat < 67.39646774) return 23; - if (lat < 68.42322022) return 22; - if (lat < 69.44242631) return 21; - if (lat < 70.45451075) return 20; - if (lat < 71.45986473) return 19; - if (lat < 72.45884545) return 18; - if (lat < 73.45177442) return 17; - if (lat < 74.43893416) return 16; - if (lat < 75.42056257) return 15; - if (lat < 76.39684391) return 14; - if (lat < 77.36789461) return 13; - if (lat < 78.33374083) return 12; - if (lat < 79.29428225) return 11; - if (lat < 80.24923213) return 10; - if (lat < 81.19801349) return 9; - if (lat < 82.13956981) return 8; - if (lat < 83.07199445) return 7; - if (lat < 83.99173563) return 6; - if (lat < 84.89166191) return 5; - if (lat < 85.75541621) return 4; - if (lat < 86.53536998) return 3; - if (lat < 87.00000000) return 2; - else return 1; -} -// -//========================================================================= -// -int cprNFunction(double lat, int fflag) { - int nl = cprNLFunction(lat) - (fflag ? 1 : 0); - if (nl < 1) nl = 1; - return nl; -} -// -//========================================================================= -// -double cprDlonFunction(double lat, int fflag, int surface) { - return (surface ? 90.0 : 360.0) / cprNFunction(lat, fflag); -} -// -//========================================================================= -// -// This algorithm comes from: -// http://www.lll.lu/~edward/edward/adsb/DecodingADSBposition.html. -// -// A few remarks: -// 1) 131072 is 2^17 since CPR latitude and longitude are encoded in 17 bits. -// -int decodeCPR(struct aircraft *a, int fflag, int surface) { - double AirDlat0 = (surface ? 90.0 : 360.0) / 60.0; - double AirDlat1 = (surface ? 90.0 : 360.0) / 59.0; - double lat0 = a->even_cprlat; - double lat1 = a->odd_cprlat; - double lon0 = a->even_cprlon; - double lon1 = a->odd_cprlon; - - // Compute the Latitude Index "j" - int j = (int) floor(((59*lat0 - 60*lat1) / 131072) + 0.5); - double rlat0 = AirDlat0 * (cprModFunction(j,60) + lat0 / 131072); - double rlat1 = AirDlat1 * (cprModFunction(j,59) + lat1 / 131072); - - time_t now = time(NULL); - double surface_rlat = MODES_USER_LATITUDE_DFLT; - double surface_rlon = MODES_USER_LONGITUDE_DFLT; - - if (surface) { - // If we're on the ground, make sure we have a (likely) valid Lat/Lon - if ((a->bFlags & MODES_ACFLAGS_LATLON_VALID) && (((int)(now - a->seenLatLon)) < Modes.interactive_display_ttl)) { - surface_rlat = a->lat; - surface_rlon = a->lon; - } else if (Modes.bUserFlags & MODES_USER_LATLON_VALID) { - surface_rlat = Modes.fUserLat; - surface_rlon = Modes.fUserLon; - } else { - // No local reference, give up - return (-1); - } - rlat0 += floor(surface_rlat / 90.0) * 90.0; // Move from 1st quadrant to our quadrant - rlat1 += floor(surface_rlat / 90.0) * 90.0; - } else { - if (rlat0 >= 270) rlat0 -= 360; - if (rlat1 >= 270) rlat1 -= 360; - } - - // Check to see that the latitude is in range: -90 .. +90 - if (rlat0 < -90 || rlat0 > 90 || rlat1 < -90 || rlat1 > 90) - return (-1); - - // Check that both are in the same latitude zone, or abort. - if (cprNLFunction(rlat0) != cprNLFunction(rlat1)) - return (-1); - - // Compute ni and the Longitude Index "m" - if (fflag) { // Use odd packet. - int ni = cprNFunction(rlat1,1); - int m = (int) floor((((lon0 * (cprNLFunction(rlat1)-1)) - - (lon1 * cprNLFunction(rlat1))) / 131072.0) + 0.5); - a->lon = cprDlonFunction(rlat1, 1, surface) * (cprModFunction(m, ni)+lon1/131072); - a->lat = rlat1; - } else { // Use even packet. - int ni = cprNFunction(rlat0,0); - int m = (int) floor((((lon0 * (cprNLFunction(rlat0)-1)) - - (lon1 * cprNLFunction(rlat0))) / 131072) + 0.5); - a->lon = cprDlonFunction(rlat0, 0, surface) * (cprModFunction(m, ni)+lon0/131072); - a->lat = rlat0; - } - - if (surface) { - a->lon += floor(surface_rlon / 90.0) * 90.0; // Move from 1st quadrant to our quadrant - } else if (a->lon > 180) { - a->lon -= 360; - } - - a->seenLatLon = a->seen; - a->timestampLatLon = a->timestamp; - a->bFlags |= (MODES_ACFLAGS_LATLON_VALID | MODES_ACFLAGS_LATLON_REL_OK); - - return 0; -} -// -//========================================================================= -// -// This algorithm comes from: -// 1090-WP29-07-Draft_CPR101 (which also defines decodeCPR() ) -// -// There is an error in this document related to CPR relative decode. -// Should use trunc() rather than the floor() function in Eq 38 and related for deltaZI. -// floor() returns integer less than argument -// trunc() returns integer closer to zero than argument. -// Note: text of document describes trunc() functionality for deltaZI calculation -// but the formulae use floor(). -// -int decodeCPRrelative(struct aircraft *a, int fflag, int surface) { - double AirDlat; - double AirDlon; - double lat; - double lon; - double lonr, latr; - double rlon, rlat; - int j,m; - - if (a->bFlags & MODES_ACFLAGS_LATLON_REL_OK) { // Ok to try aircraft relative first - latr = a->lat; - lonr = a->lon; - } else if (Modes.bUserFlags & MODES_USER_LATLON_VALID) { // Try ground station relative next - latr = Modes.fUserLat; - lonr = Modes.fUserLon; - } else { - return (-1); // Exit with error - can't do relative if we don't have ref. - } - - if (fflag) { // odd - AirDlat = (surface ? 90.0 : 360.0) / 59.0; - lat = a->odd_cprlat; - lon = a->odd_cprlon; - } else { // even - AirDlat = (surface ? 90.0 : 360.0) / 60.0; - lat = a->even_cprlat; - lon = a->even_cprlon; - } - - // Compute the Latitude Index "j" - j = (int) (floor(latr/AirDlat) + - trunc(0.5 + cprModFunction((int)latr, (int)AirDlat)/AirDlat - lat/131072)); - rlat = AirDlat * (j + lat/131072); - if (rlat >= 270) rlat -= 360; - - // Check to see that the latitude is in range: -90 .. +90 - if (rlat < -90 || rlat > 90) { - a->bFlags &= ~MODES_ACFLAGS_LATLON_REL_OK; // This will cause a quick exit next time if no global has been done - return (-1); // Time to give up - Latitude error - } - - // Check to see that answer is reasonable - ie no more than 1/2 cell away - if (fabs(rlat - a->lat) > (AirDlat/2)) { - a->bFlags &= ~MODES_ACFLAGS_LATLON_REL_OK; // This will cause a quick exit next time if no global has been done - return (-1); // Time to give up - Latitude error - } - - // Compute the Longitude Index "m" - AirDlon = cprDlonFunction(rlat, fflag, surface); - m = (int) (floor(lonr/AirDlon) + - trunc(0.5 + cprModFunction((int)lonr, (int)AirDlon)/AirDlon - lon/131072)); - rlon = AirDlon * (m + lon/131072); - if (rlon > 180) rlon -= 360; - - // Check to see that answer is reasonable - ie no more than 1/2 cell away - if (fabs(rlon - a->lon) > (AirDlon/2)) { - a->bFlags &= ~MODES_ACFLAGS_LATLON_REL_OK; // This will cause a quick exit next time if no global has been done - return (-1); // Time to give up - Longitude error - } - - a->lat = rlat; - a->lon = rlon; - - a->seenLatLon = a->seen; - a->timestampLatLon = a->timestamp; - a->bFlags |= (MODES_ACFLAGS_LATLON_VALID | MODES_ACFLAGS_LATLON_REL_OK); - return (0); -} -// -// ===================== Mode S detection and decoding =================== -// diff --git a/net_io.c b/net_io.c deleted file mode 100644 index a979883f5..000000000 --- a/net_io.c +++ /dev/null @@ -1,1006 +0,0 @@ -// dump1090, a Mode S messages decoder for RTLSDR devices. -// -// Copyright (C) 2012 by Salvatore Sanfilippo -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#include "dump1090.h" -// -// ============================= Networking ============================= -// -// Note: here we disregard any kind of good coding practice in favor of -// extreme simplicity, that is: -// -// 1) We only rely on the kernel buffers for our I/O without any kind of -// user space buffering. -// 2) We don't register any kind of event handler, from time to time a -// function gets called and we accept new connections. All the rest is -// handled via non-blocking I/O and manually polling clients to see if -// they have something new to share with us when reading is needed. -// -//========================================================================= -// -// Networking "stack" initialization -// -struct service { - char *descr; - int *socket; - int port; - int enabled; -}; - -struct service services[MODES_NET_SERVICES_NUM]; - -void modesInitNet(void) { - int j; - - struct service svc[MODES_NET_SERVICES_NUM] = { - {"Raw TCP output", &Modes.ros, Modes.net_output_raw_port, 1}, - {"Raw TCP input", &Modes.ris, Modes.net_input_raw_port, 1}, - {"Beast TCP output", &Modes.bos, Modes.net_output_beast_port, 1}, - {"Beast TCP input", &Modes.bis, Modes.net_input_beast_port, 1}, - {"HTTP server", &Modes.https, Modes.net_http_port, 1}, - {"Basestation TCP output", &Modes.sbsos, Modes.net_output_sbs_port, 1} - }; - - memcpy(&services, &svc, sizeof(svc));//services = svc; - - Modes.clients = NULL; - -#ifdef _WIN32 - if ( (!Modes.wsaData.wVersion) - && (!Modes.wsaData.wHighVersion) ) { - // Try to start the windows socket support - if (WSAStartup(MAKEWORD(2,1),&Modes.wsaData) != 0) - { - fprintf(stderr, "WSAStartup returned Error\n"); - } - } -#endif - - for (j = 0; j < MODES_NET_SERVICES_NUM; j++) { - services[j].enabled = (services[j].port != 0); - if (services[j].enabled) { - int s = anetTcpServer(Modes.aneterr, services[j].port, Modes.net_bind_address); - if (s == -1) { - fprintf(stderr, "Error opening the listening port %d (%s): %s\n", - services[j].port, services[j].descr, Modes.aneterr); - exit(1); - } - anetNonBlock(Modes.aneterr, s); - *services[j].socket = s; - } else { - if (Modes.debug & MODES_DEBUG_NET) printf("%s port is disabled\n", services[j].descr); - } - } - -#ifndef _WIN32 - signal(SIGPIPE, SIG_IGN); -#endif -} -// -//========================================================================= -// -// This function gets called from time to time when the decoding thread is -// awakened by new data arriving. This usually happens a few times every second -// -struct client * modesAcceptClients(void) { - int fd, port; - unsigned int j; - struct client *c; - - for (j = 0; j < MODES_NET_SERVICES_NUM; j++) { - if (services[j].enabled) { - fd = anetTcpAccept(Modes.aneterr, *services[j].socket, NULL, &port); - if (fd == -1) continue; - - anetNonBlock(Modes.aneterr, fd); - c = (struct client *) malloc(sizeof(*c)); - c->service = *services[j].socket; - c->next = Modes.clients; - c->fd = fd; - c->buflen = 0; - Modes.clients = c; - anetSetSendBuffer(Modes.aneterr,fd, (MODES_NET_SNDBUF_SIZE << Modes.net_sndbuf_size)); - - if (*services[j].socket == Modes.sbsos) Modes.stat_sbs_connections++; - if (*services[j].socket == Modes.ros) Modes.stat_raw_connections++; - if (*services[j].socket == Modes.bos) Modes.stat_beast_connections++; - - j--; // Try again with the same listening port - - if (Modes.debug & MODES_DEBUG_NET) - printf("Created new client %d\n", fd); - } - } - return Modes.clients; -} -// -//========================================================================= -// -// On error free the client, collect the structure, adjust maxfd if needed. -// -void modesFreeClient(struct client *c) { - - // Unhook this client from the linked list of clients - struct client *p = Modes.clients; - if (p) { - if (p == c) { - Modes.clients = c->next; - } else { - while ((p) && (p->next != c)) { - p = p->next; - } - if (p) { - p->next = c->next; - } - } - } - - free(c); -} -// -//========================================================================= -// -// Close the client connection and mark it as closed -// -void modesCloseClient(struct client *c) { - close(c->fd); - if (c->service == Modes.sbsos) { - if (Modes.stat_sbs_connections) Modes.stat_sbs_connections--; - } else if (c->service == Modes.ros) { - if (Modes.stat_raw_connections) Modes.stat_raw_connections--; - } else if (c->service == Modes.bos) { - if (Modes.stat_beast_connections) Modes.stat_beast_connections--; - } - - if (Modes.debug & MODES_DEBUG_NET) - printf("Closing client %d\n", c->fd); - - c->fd = -1; -} -// -//========================================================================= -// -// Send the specified message to all clients listening for a given service -// -void modesSendAllClients(int service, void *msg, int len) { - struct client *c = Modes.clients; - - while (c) { - // Read next before servicing client incase the service routine deletes the client! - struct client *next = c->next; - - if (c->fd != -1) { - if (c->service == service) { -#ifndef _WIN32 - int nwritten = write(c->fd, msg, len); -#else - int nwritten = send(c->fd, msg, len, 0 ); -#endif - if (nwritten != len) { - modesCloseClient(c); - } - } - } else { - modesFreeClient(c); - } - c = next; - } -} -// -//========================================================================= -// -// Write raw output in Beast Binary format with Timestamp to TCP clients -// -void modesSendBeastOutput(struct modesMessage *mm) { - char *p = &Modes.beastOut[Modes.beastOutUsed]; - int msgLen = mm->msgbits / 8; - char * pTimeStamp; - char ch; - int j; - int iOutLen = msgLen + 9; // Escape, msgtype, timestamp, sigLevel, msg - - *p++ = 0x1a; - if (msgLen == MODES_SHORT_MSG_BYTES) - {*p++ = '2';} - else if (msgLen == MODES_LONG_MSG_BYTES) - {*p++ = '3';} - else if (msgLen == MODEAC_MSG_BYTES) - {*p++ = '1';} - else - {return;} - - pTimeStamp = (char *) &mm->timestampMsg; - for (j = 5; j >= 0; j--) { - *p++ = (ch = pTimeStamp[j]); - if (0x1A == ch) {*p++ = ch; iOutLen++;} - } - - *p++ = (ch = mm->signalLevel); - if (0x1A == ch) {*p++ = ch; iOutLen++;} - - for (j = 0; j < msgLen; j++) { - *p++ = (ch = mm->msg[j]); - if (0x1A == ch) {*p++ = ch; iOutLen++;} - } - - Modes.beastOutUsed += iOutLen; - if (Modes.beastOutUsed >= Modes.net_output_raw_size) - { - modesSendAllClients(Modes.bos, Modes.beastOut, Modes.beastOutUsed); - Modes.beastOutUsed = 0; - Modes.net_output_raw_rate_count = 0; - } -} -// -//========================================================================= -// -// Write raw output to TCP clients -// -void modesSendRawOutput(struct modesMessage *mm) { - char *p = &Modes.rawOut[Modes.rawOutUsed]; - int msgLen = mm->msgbits / 8; - int j; - unsigned char * pTimeStamp; - - if (Modes.mlat && mm->timestampMsg) { - *p++ = '@'; - pTimeStamp = (unsigned char *) &mm->timestampMsg; - for (j = 5; j >= 0; j--) { - sprintf(p, "%02X", pTimeStamp[j]); - p += 2; - } - Modes.rawOutUsed += 12; // additional 12 characters for timestamp - } else - *p++ = '*'; - - for (j = 0; j < msgLen; j++) { - sprintf(p, "%02X", mm->msg[j]); - p += 2; - } - - *p++ = ';'; - *p++ = '\n'; - - Modes.rawOutUsed += ((msgLen*2) + 3); - if (Modes.rawOutUsed >= Modes.net_output_raw_size) - { - modesSendAllClients(Modes.ros, Modes.rawOut, Modes.rawOutUsed); - Modes.rawOutUsed = 0; - Modes.net_output_raw_rate_count = 0; - } -} -// -//========================================================================= -// -// Write SBS output to TCP clients -// The message structure mm->bFlags tells us what has been updated by this message -// -void modesSendSBSOutput(struct modesMessage *mm) { - char msg[256], *p = msg; - uint32_t offset; - struct timeb epocTime_receive, epocTime_now; - struct tm stTime_receive, stTime_now; - int msgType; - - // - // SBS BS style output checked against the following reference - // http://www.homepages.mcb.net/bones/SBS/Article/Barebones42_Socket_Data.htm - seems comprehensive - // - - // Decide on the basic SBS Message Type - if ((mm->msgtype == 4) || (mm->msgtype == 20)) { - msgType = 5; - } else if ((mm->msgtype == 5) || (mm->msgtype == 21)) { - msgType = 6; - } else if ((mm->msgtype == 0) || (mm->msgtype == 16)) { - msgType = 7; - } else if (mm->msgtype == 11) { - msgType = 8; - } else if ((mm->msgtype != 17) && (mm->msgtype != 18)) { - return; - } else if ((mm->metype >= 1) && (mm->metype <= 4)) { - msgType = 1; - } else if ((mm->metype >= 5) && (mm->metype <= 8)) { - if (mm->bFlags & MODES_ACFLAGS_LATLON_VALID) - {msgType = 2;} - else - {msgType = 7;} - } else if ((mm->metype >= 9) && (mm->metype <= 18)) { - if (mm->bFlags & MODES_ACFLAGS_LATLON_VALID) - {msgType = 3;} - else - {msgType = 7;} - } else if (mm->metype != 19) { - return; - } else if ((mm->mesub == 1) || (mm->mesub == 2)) { - msgType = 4; - } else { - return; - } - - // Fields 1 to 6 : SBS message type and ICAO address of the aircraft and some other stuff - p += sprintf(p, "MSG,%d,111,11111,%06X,111111,", msgType, mm->addr); - - // Find current system time - ftime(&epocTime_now); // get the current system time & date - stTime_now = *localtime(&epocTime_now.time); - - // Find message reception time - if (mm->timestampMsg && !mm->remote) { // Make sure the records' timestamp is valid before using it - epocTime_receive = Modes.stSystemTimeBlk; // This is the time of the start of the Block we're processing - offset = (int) (mm->timestampMsg - Modes.timestampBlk); // This is the time (in 12Mhz ticks) into the Block - offset = offset / 12000; // convert to milliseconds - epocTime_receive.millitm += offset; // add on the offset time to the Block start time - if (epocTime_receive.millitm > 999) { // if we've caused an overflow into the next second... - epocTime_receive.millitm -= 1000; - epocTime_receive.time ++; // ..correct the overflow - } - stTime_receive = *localtime(&epocTime_receive.time); - } else { - epocTime_receive = epocTime_now; // We don't have a usable reception time; use the current system time - stTime_receive = stTime_now; - } - - // Fields 7 & 8 are the message reception time and date - p += sprintf(p, "%04d/%02d/%02d,", (stTime_receive.tm_year+1900),(stTime_receive.tm_mon+1), stTime_receive.tm_mday); - p += sprintf(p, "%02d:%02d:%02d.%03d,", stTime_receive.tm_hour, stTime_receive.tm_min, stTime_receive.tm_sec, epocTime_receive.millitm); - - // Fields 9 & 10 are the current time and date - p += sprintf(p, "%04d/%02d/%02d,", (stTime_now.tm_year+1900),(stTime_now.tm_mon+1), stTime_now.tm_mday); - p += sprintf(p, "%02d:%02d:%02d.%03d", stTime_now.tm_hour, stTime_now.tm_min, stTime_now.tm_sec, epocTime_now.millitm); - - // Field 11 is the callsign (if we have it) - if (mm->bFlags & MODES_ACFLAGS_CALLSIGN_VALID) {p += sprintf(p, ",%s", mm->flight);} - else {p += sprintf(p, ",");} - - // Field 12 is the altitude (if we have it) - force to zero if we're on the ground - if ((mm->bFlags & MODES_ACFLAGS_AOG_GROUND) == MODES_ACFLAGS_AOG_GROUND) { - p += sprintf(p, ",0"); - } else if (mm->bFlags & MODES_ACFLAGS_ALTITUDE_VALID) { - p += sprintf(p, ",%d", mm->altitude); - } else { - p += sprintf(p, ","); - } - - // Field 13 is the ground Speed (if we have it) - if (mm->bFlags & MODES_ACFLAGS_SPEED_VALID) { - p += sprintf(p, ",%d", mm->velocity); - } else { - p += sprintf(p, ","); - } - - // Field 14 is the ground Heading (if we have it) - if (mm->bFlags & MODES_ACFLAGS_HEADING_VALID) { - p += sprintf(p, ",%d", mm->heading); - } else { - p += sprintf(p, ","); - } - - // Fields 15 and 16 are the Lat/Lon (if we have it) - if (mm->bFlags & MODES_ACFLAGS_LATLON_VALID) {p += sprintf(p, ",%1.5f,%1.5f", mm->fLat, mm->fLon);} - else {p += sprintf(p, ",,");} - - // Field 17 is the VerticalRate (if we have it) - if (mm->bFlags & MODES_ACFLAGS_VERTRATE_VALID) {p += sprintf(p, ",%d", mm->vert_rate);} - else {p += sprintf(p, ",");} - - // Field 18 is the Squawk (if we have it) - if (mm->bFlags & MODES_ACFLAGS_SQUAWK_VALID) {p += sprintf(p, ",%x", mm->modeA);} - else {p += sprintf(p, ",");} - - // Field 19 is the Squawk Changing Alert flag (if we have it) - if (mm->bFlags & MODES_ACFLAGS_FS_VALID) { - if ((mm->fs >= 2) && (mm->fs <= 4)) { - p += sprintf(p, ",-1"); - } else { - p += sprintf(p, ",0"); - } - } else { - p += sprintf(p, ","); - } - - // Field 20 is the Squawk Emergency flag (if we have it) - if (mm->bFlags & MODES_ACFLAGS_SQUAWK_VALID) { - if ((mm->modeA == 0x7500) || (mm->modeA == 0x7600) || (mm->modeA == 0x7700)) { - p += sprintf(p, ",-1"); - } else { - p += sprintf(p, ",0"); - } - } else { - p += sprintf(p, ","); - } - - // Field 21 is the Squawk Ident flag (if we have it) - if (mm->bFlags & MODES_ACFLAGS_FS_VALID) { - if ((mm->fs >= 4) && (mm->fs <= 5)) { - p += sprintf(p, ",-1"); - } else { - p += sprintf(p, ",0"); - } - } else { - p += sprintf(p, ","); - } - - // Field 22 is the OnTheGround flag (if we have it) - if (mm->bFlags & MODES_ACFLAGS_AOG_VALID) { - if (mm->bFlags & MODES_ACFLAGS_AOG) { - p += sprintf(p, ",-1"); - } else { - p += sprintf(p, ",0"); - } - } else { - p += sprintf(p, ","); - } - - p += sprintf(p, "\r\n"); - modesSendAllClients(Modes.sbsos, msg, p-msg); -} -// -//========================================================================= -// -void modesQueueOutput(struct modesMessage *mm) { - if (Modes.stat_sbs_connections) {modesSendSBSOutput(mm);} - if (Modes.stat_beast_connections) {modesSendBeastOutput(mm);} - if (Modes.stat_raw_connections) {modesSendRawOutput(mm);} -} -// -//========================================================================= -// -// This function decodes a Beast binary format message -// -// The message is passed to the higher level layers, so it feeds -// the selected screen output, the network output and so forth. -// -// If the message looks invalid it is silently discarded. -// -// The function always returns 0 (success) to the caller as there is no -// case where we want broken messages here to close the client connection. -// -int decodeBinMessage(struct client *c, char *p) { - int msgLen = 0; - int j; - char ch; - char * ptr; - unsigned char msg[MODES_LONG_MSG_BYTES]; - struct modesMessage mm; - MODES_NOTUSED(c); - memset(&mm, 0, sizeof(mm)); - - ch = *p++; /// Get the message type - if (0x1A == ch) {p++;} - - if ((ch == '1') && (Modes.mode_ac)) { // skip ModeA/C unless user enables --modes-ac - msgLen = MODEAC_MSG_BYTES; - } else if (ch == '2') { - msgLen = MODES_SHORT_MSG_BYTES; - } else if (ch == '3') { - msgLen = MODES_LONG_MSG_BYTES; - } - - if (msgLen) { - // Mark messages received over the internet as remote so that we don't try to - // pass them off as being received by this instance when forwarding them - mm.remote = 1; - - ptr = (char*) &mm.timestampMsg; - for (j = 0; j < 6; j++) { // Grab the timestamp (big endian format) - ptr[5-j] = ch = *p++; - if (0x1A == ch) {p++;} - } - - mm.signalLevel = ch = *p++; // Grab the signal level - if (0x1A == ch) {p++;} - - for (j = 0; j < msgLen; j++) { // and the data - msg[j] = ch = *p++; - if (0x1A == ch) {p++;} - } - - if (msgLen == MODEAC_MSG_BYTES) { // ModeA or ModeC - decodeModeAMessage(&mm, ((msg[0] << 8) | msg[1])); - } else { - decodeModesMessage(&mm, msg); - } - - useModesMessage(&mm); - } - return (0); -} -// -//========================================================================= -// -// Turn an hex digit into its 4 bit decimal value. -// Returns -1 if the digit is not in the 0-F range. -// -int hexDigitVal(int c) { - c = tolower(c); - if (c >= '0' && c <= '9') return c-'0'; - else if (c >= 'a' && c <= 'f') return c-'a'+10; - else return -1; -} -// -//========================================================================= -// -// This function decodes a string representing message in raw hex format -// like: *8D4B969699155600E87406F5B69F; The string is null-terminated. -// -// The message is passed to the higher level layers, so it feeds -// the selected screen output, the network output and so forth. -// -// If the message looks invalid it is silently discarded. -// -// The function always returns 0 (success) to the caller as there is no -// case where we want broken messages here to close the client connection. -// -int decodeHexMessage(struct client *c, char *hex) { - int l = strlen(hex), j; - unsigned char msg[MODES_LONG_MSG_BYTES]; - struct modesMessage mm; - MODES_NOTUSED(c); - memset(&mm, 0, sizeof(mm)); - - // Mark messages received over the internet as remote so that we don't try to - // pass them off as being received by this instance when forwarding them - mm.remote = 1; - mm.signalLevel = 0xFF; - - // Remove spaces on the left and on the right - while(l && isspace(hex[l-1])) { - hex[l-1] = '\0'; l--; - } - while(isspace(*hex)) { - hex++; l--; - } - - // Turn the message into binary. - // Accept *-AVR raw @-AVR/BEAST timeS+raw %-AVR timeS+raw (CRC good) <-BEAST timeS+sigL+raw - // and some AVR records that we can understand - if (hex[l-1] != ';') {return (0);} // not complete - abort - - switch(hex[0]) { - case '<': { - mm.signalLevel = (hexDigitVal(hex[13])<<4) | hexDigitVal(hex[14]); - hex += 15; l -= 16; // Skip <, timestamp and siglevel, and ; - break;} - - case '@': // No CRC check - case '%': { // CRC is OK - hex += 13; l -= 14; // Skip @,%, and timestamp, and ; - break;} - - case '*': - case ':': { - hex++; l-=2; // Skip * and ; - break;} - - default: { - return (0); // We don't know what this is, so abort - break;} - } - - if ( (l != (MODEAC_MSG_BYTES * 2)) - && (l != (MODES_SHORT_MSG_BYTES * 2)) - && (l != (MODES_LONG_MSG_BYTES * 2)) ) - {return (0);} // Too short or long message... broken - - if ( (0 == Modes.mode_ac) - && (l == (MODEAC_MSG_BYTES * 2)) ) - {return (0);} // Right length for ModeA/C, but not enabled - - for (j = 0; j < l; j += 2) { - int high = hexDigitVal(hex[j]); - int low = hexDigitVal(hex[j+1]); - - if (high == -1 || low == -1) return 0; - msg[j/2] = (high << 4) | low; - } - - if (l == (MODEAC_MSG_BYTES * 2)) { // ModeA or ModeC - decodeModeAMessage(&mm, ((msg[0] << 8) | msg[1])); - } else { // Assume ModeS - decodeModesMessage(&mm, msg); - } - - useModesMessage(&mm); - return (0); -} -// -//========================================================================= -// -// Return a description of planes in json. No metric conversion -// -char *aircraftsToJson(int *len) { - time_t now = time(NULL); - struct aircraft *a = Modes.aircrafts; - int buflen = 1024; // The initial buffer is incremented as needed - char *buf = (char *) malloc(buflen), *p = buf; - int l; - - l = snprintf(p,buflen,"[\n"); - p += l; buflen -= l; - while(a) { - int position = 0; - int track = 0; - - if (a->modeACflags & MODEAC_MSG_FLAG) { // skip any fudged ICAO records Mode A/C - a = a->next; - continue; - } - - if (a->bFlags & MODES_ACFLAGS_LATLON_VALID) { - position = 1; - } - - if (a->bFlags & MODES_ACFLAGS_HEADING_VALID) { - track = 1; - } - - // No metric conversion - l = snprintf(p,buflen, - "{\"hex\":\"%06x\", \"squawk\":\"%04x\", \"flight\":\"%s\", \"lat\":%f, " - "\"lon\":%f, \"validposition\":%d, \"altitude\":%d, \"vert_rate\":%d,\"track\":%d, \"validtrack\":%d," - "\"speed\":%d, \"messages\":%ld, \"seen\":%d},\n", - a->addr, a->modeA, a->flight, a->lat, a->lon, position, a->altitude, a->vert_rate, a->track, track, - a->speed, a->messages, (int)(now - a->seen)); - p += l; buflen -= l; - - //Resize if needed - if (buflen < 256) { - int used = p-buf; - buflen += 1024; // Our increment. - buf = (char *) realloc(buf,used+buflen); - p = buf+used; - } - - a = a->next; - } - - //Remove the final comma if any, and closes the json array. - if (*(p-2) == ',') { - *(p-2) = '\n'; - p--; - buflen++; - } - - l = snprintf(p,buflen,"]\n"); - p += l; buflen -= l; - - *len = p-buf; - return buf; -} -// -//========================================================================= -// -#define MODES_CONTENT_TYPE_HTML "text/html;charset=utf-8" -#define MODES_CONTENT_TYPE_CSS "text/css;charset=utf-8" -#define MODES_CONTENT_TYPE_JSON "application/json;charset=utf-8" -#define MODES_CONTENT_TYPE_JS "application/javascript;charset=utf-8" -// -// Get an HTTP request header and write the response to the client. -// gain here we assume that the socket buffer is enough without doing -// any kind of userspace buffering. -// -// Returns 1 on error to signal the caller the client connection should -// be closed. -// -int handleHTTPRequest(struct client *c, char *p) { - char hdr[512]; - int clen, hdrlen; - int httpver, keepalive; - int statuscode = 500; - char *url, *content; - char ctype[48]; - char getFile[1024]; - char *ext; - - if (Modes.debug & MODES_DEBUG_NET) - printf("\nHTTP request: %s\n", c->buf); - - // Minimally parse the request. - httpver = (strstr(p, "HTTP/1.1") != NULL) ? 11 : 10; - if (httpver == 10) { - // HTTP 1.0 defaults to close, unless otherwise specified. - //keepalive = strstr(p, "Connection: keep-alive") != NULL; - } else if (httpver == 11) { - // HTTP 1.1 defaults to keep-alive, unless close is specified. - //keepalive = strstr(p, "Connection: close") == NULL; - } - keepalive = 0; - - // Identify he URL. - p = strchr(p,' '); - if (!p) return 1; // There should be the method and a space - url = ++p; // Now this should point to the requested URL - p = strchr(p, ' '); - if (!p) return 1; // There should be a space before HTTP/ - *p = '\0'; - - if (Modes.debug & MODES_DEBUG_NET) { - printf("\nHTTP keep alive: %d\n", keepalive); - printf("HTTP requested URL: %s\n\n", url); - } - - if (strlen(url) < 2) { - snprintf(getFile, sizeof getFile, "%s/gmap.html", HTMLPATH); // Default file - } else { - snprintf(getFile, sizeof getFile, "%s/%s", HTMLPATH, url); - } - - // Select the content to send, we have just two so far: - // "/" -> Our google map application. - // "/data.json" -> Our ajax request to update planes. - if (strstr(url, "/data.json")) { - statuscode = 200; - content = aircraftsToJson(&clen); - //snprintf(ctype, sizeof ctype, MODES_CONTENT_TYPE_JSON); - } else { - struct stat sbuf; - int fd = -1; - char *rp, *hrp; - - rp = realpath(getFile, NULL); - hrp = realpath(HTMLPATH, NULL); - hrp = (hrp ? hrp : HTMLPATH); - clen = -1; - content = strdup("Server error occured"); - if (rp && (!strncmp(hrp, rp, strlen(hrp)))) { - if (stat(getFile, &sbuf) != -1 && (fd = open(getFile, O_RDONLY)) != -1) { - content = (char *) realloc(content, sbuf.st_size); - if (read(fd, content, sbuf.st_size) != -1) { - clen = sbuf.st_size; - statuscode = 200; - } - } - } else { - errno = ENOENT; - } - - if (clen < 0) { - content = realloc(content, 128); - clen = snprintf(content, 128,"Error opening HTML file: %s", strerror(errno)); - statuscode = 404; - } - - if (fd != -1) { - close(fd); - } - } - - // Get file extension and content type - snprintf(ctype, sizeof ctype, MODES_CONTENT_TYPE_HTML); // Default content type - ext = strrchr(getFile, '.'); - - if (strlen(ext) > 0) { - if (strstr(ext, ".json")) { - snprintf(ctype, sizeof ctype, MODES_CONTENT_TYPE_JSON); - } else if (strstr(ext, ".css")) { - snprintf(ctype, sizeof ctype, MODES_CONTENT_TYPE_CSS); - } else if (strstr(ext, ".js")) { - snprintf(ctype, sizeof ctype, MODES_CONTENT_TYPE_JS); - } - } - - // Create the header and send the reply - hdrlen = snprintf(hdr, sizeof(hdr), - "HTTP/1.1 %d \r\n" - "Server: Dump1090\r\n" - "Content-Type: %s\r\n" - "Connection: %s\r\n" - "Content-Length: %d\r\n" - "Cache-Control: no-cache, must-revalidate\r\n" - "Expires: Sat, 26 Jul 1997 05:00:00 GMT\r\n" - "\r\n", - statuscode, - ctype, - keepalive ? "keep-alive" : "close", - clen); - - if (Modes.debug & MODES_DEBUG_NET) { - printf("HTTP Reply header:\n%s", hdr); - } - - // Send header and content. -#ifndef _WIN32 - if ( (write(c->fd, hdr, hdrlen) != hdrlen) - || (write(c->fd, content, clen) != clen) ) { -#else - if ( (send(c->fd, hdr, hdrlen, 0) != hdrlen) - || (send(c->fd, content, clen, 0) != clen) ) { -#endif - free(content); - return 1; - } - free(content); - Modes.stat_http_requests++; - return !keepalive; -} -// -//========================================================================= -// -// This function polls the clients using read() in order to receive new -// messages from the net. -// -// The message is supposed to be separated from the next message by the -// separator 'sep', which is a null-terminated C string. -// -// Every full message received is decoded and passed to the higher layers -// calling the function's 'handler'. -// -// The handler returns 0 on success, or 1 to signal this function we should -// close the connection with the client in case of non-recoverable errors. -// -void modesReadFromClient(struct client *c, char *sep, - int(*handler)(struct client *, char *)) { - int left; - int nread; - int fullmsg; - int bContinue = 1; - char *s, *e, *p; - - while(bContinue) { - - fullmsg = 0; - left = MODES_CLIENT_BUF_SIZE - c->buflen; - // If our buffer is full discard it, this is some badly formatted shit - if (left <= 0) { - c->buflen = 0; - left = MODES_CLIENT_BUF_SIZE; - // If there is garbage, read more to discard it ASAP - } -#ifndef _WIN32 - nread = read(c->fd, c->buf+c->buflen, left); -#else - nread = recv(c->fd, c->buf+c->buflen, left, 0); - if (nread < 0) {errno = WSAGetLastError();} -#endif - if (nread == 0) { - modesCloseClient(c); - return; - } - - // If we didn't get all the data we asked for, then return once we've processed what we did get. - if (nread != left) { - bContinue = 0; - } -#ifndef _WIN32 - if ( (nread < 0 && errno != EAGAIN && errno != EWOULDBLOCK) || nread == 0 ) { // Error, or end of file -#else - if ( (nread < 0) && (errno != EWOULDBLOCK)) { // Error, or end of file -#endif - modesCloseClient(c); - return; - } - if (nread <= 0) { - break; // Serve next client - } - c->buflen += nread; - - // Always null-term so we are free to use strstr() (it won't affect binary case) - c->buf[c->buflen] = '\0'; - - e = s = c->buf; // Start with the start of buffer, first message - - if (c->service == Modes.bis) { - // This is the Beast Binary scanning case. - // If there is a complete message still in the buffer, there must be the separator 'sep' - // in the buffer, note that we full-scan the buffer at every read for simplicity. - - left = c->buflen; // Length of valid search for memchr() - while (left && ((s = memchr(e, (char) 0x1a, left)) != NULL)) { // The first byte of buffer 'should' be 0x1a - s++; // skip the 0x1a - if (*s == '1') { - e = s + MODEAC_MSG_BYTES + 8; // point past remainder of message - } else if (*s == '2') { - e = s + MODES_SHORT_MSG_BYTES + 8; - } else if (*s == '3') { - e = s + MODES_LONG_MSG_BYTES + 8; - } else { - e = s; // Not a valid beast message, skip - left = &(c->buf[c->buflen]) - e; - continue; - } - // we need to be careful of double escape characters in the message body - for (p = s; p < e; p++) { - if (0x1A == *p) { - p++; e++; - if (e > &(c->buf[c->buflen])) { - break; - } - } - } - left = &(c->buf[c->buflen]) - e; - if (left < 0) { // Incomplete message in buffer - e = s - 1; // point back at last found 0x1a. - break; - } - // Have a 0x1a followed by 1, 2 or 3 - pass message less 0x1a to handler. - if (handler(c, s)) { - modesCloseClient(c); - return; - } - fullmsg = 1; - } - s = e; // For the buffer remainder below - - } else { - // - // This is the ASCII scanning case, AVR RAW or HTTP at present - // If there is a complete message still in the buffer, there must be the separator 'sep' - // in the buffer, note that we full-scan the buffer at every read for simplicity. - // - while ((e = strstr(s, sep)) != NULL) { // end of first message if found - *e = '\0'; // The handler expects null terminated strings - if (handler(c, s)) { // Pass message to handler. - modesCloseClient(c); // Handler returns 1 on error to signal we . - return; // should close the client connection - } - s = e + strlen(sep); // Move to start of next message - fullmsg = 1; - } - } - - if (fullmsg) { // We processed something - so - c->buflen = &(c->buf[c->buflen]) - s; // Update the unprocessed buffer length - memmove(c->buf, s, c->buflen); // Move what's remaining to the start of the buffer - } else { // If no message was decoded process the next client - break; - } - } -} -// -//========================================================================= -// -// Read data from clients. This function actually delegates a lower-level -// function that depends on the kind of service (raw, http, ...). -// -void modesReadFromClients(void) { - - struct client *c = modesAcceptClients(); - - while (c) { - // Read next before servicing client incase the service routine deletes the client! - struct client *next = c->next; - - if (c->fd >= 0) { - if (c->service == Modes.ris) { - modesReadFromClient(c,"\n",decodeHexMessage); - } else if (c->service == Modes.bis) { - modesReadFromClient(c,"",decodeBinMessage); - } else if (c->service == Modes.https) { - modesReadFromClient(c,"\r\n\r\n",handleHTTPRequest); - } - } else { - modesFreeClient(c); - } - c = next; - } -} -// -// =============================== Network IO =========================== -// diff --git a/ppup1090.c b/ppup1090.c deleted file mode 100644 index afbbe2fba..000000000 --- a/ppup1090.c +++ /dev/null @@ -1,261 +0,0 @@ -// ppup1090, a Mode S PlanePlotter Uploader for dump1090 devices. -// -// Copyright (C) 2013 by Malcolm Robb -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -#include "coaa.h" -#include "ppup1090.h" -// -// ============================= Utility functions ========================== -// -void sigintHandler(int dummy) { - NOTUSED(dummy); - signal(SIGINT, SIG_DFL); // reset signal handler - bit extra safety - Modes.exit = 1; // Signal to threads that we are done -} -// -// =============================== Initialization =========================== -// -void ppup1090InitConfig(void) { - - int iErr; - - // Default everything to zero/NULL - memset(&Modes, 0, sizeof(Modes)); - memset(&ppup1090, 0, sizeof(ppup1090)); - - // Now initialise things that should not be 0/NULL to their defaults - Modes.check_crc = 1; - Modes.quiet = 1; - Modes.bEnableDFLogging = 1; - strcpy(ppup1090.net_input_beast_ipaddr,PPUP1090_NET_OUTPUT_IP_ADDRESS); - Modes.net_input_beast_port = MODES_NET_OUTPUT_BEAST_PORT; - Modes.interactive_delete_ttl = MODES_INTERACTIVE_DELETE_TTL; - Modes.interactive_display_ttl = MODES_INTERACTIVE_DISPLAY_TTL; - Modes.fUserLat = MODES_USER_LATITUDE_DFLT; - Modes.fUserLon = MODES_USER_LONGITUDE_DFLT; - - if ((iErr = openCOAA())) - { - fprintf(stderr, "Error 0x%X initialising uploader\n", iErr); - exit(1); - } -} -// -//========================================================================= -// -void ppup1090Init(void) { - - int iErr; - - pthread_mutex_init(&Modes.pDF_mutex,NULL); - pthread_mutex_init(&Modes.data_mutex,NULL); - pthread_cond_init(&Modes.data_cond,NULL); - - // Allocate the various buffers used by Modes - if ( NULL == (Modes.icao_cache = (uint32_t *) malloc(sizeof(uint32_t) * MODES_ICAO_CACHE_LEN * 2))) - { - fprintf(stderr, "Out of memory allocating data buffer.\n"); - exit(1); - } - - // Clear the buffers that have just been allocated, just in-case - memset(Modes.icao_cache, 0, sizeof(uint32_t) * MODES_ICAO_CACHE_LEN * 2); - - // Validate the users Lat/Lon home location inputs - if ( (Modes.fUserLat > 90.0) // Latitude must be -90 to +90 - || (Modes.fUserLat < -90.0) // and - || (Modes.fUserLon > 360.0) // Longitude must be -180 to +360 - || (Modes.fUserLon < -180.0) ) { - Modes.fUserLat = Modes.fUserLon = 0.0; - } else if (Modes.fUserLon > 180.0) { // If Longitude is +180 to +360, make it -180 to 0 - Modes.fUserLon -= 360.0; - } - // If both Lat and Lon are 0.0 then the users location is either invalid/not-set, or (s)he's in the - // Atlantic ocean off the west coast of Africa. This is unlikely to be correct. - // Set the user LatLon valid flag only if either Lat or Lon are non zero. Note the Greenwich meridian - // is at 0.0 Lon,so we must check for either fLat or fLon being non zero not both. - // Testing the flag at runtime will be much quicker than ((fLon != 0.0) || (fLat != 0.0)) - Modes.bUserFlags &= ~MODES_USER_LATLON_VALID; - if ((Modes.fUserLat != 0.0) || (Modes.fUserLon != 0.0)) { - Modes.bUserFlags |= MODES_USER_LATLON_VALID; - } - - // Prepare error correction tables - modesInitErrorInfo(); - - // Setup the uploader - read the user paramaters from the coaa.h header file - coaa1090.ppIPAddr = ppup1090.net_pp_ipaddr; - coaa1090.fUserLat = MODES_USER_LATITUDE_DFLT; - coaa1090.fUserLon = MODES_USER_LONGITUDE_DFLT; - strcpy(coaa1090.strAuthCode,STR(USER_AUTHCODE)); - strcpy(coaa1090.strRegNo, STR(USER_REGNO)); - strcpy(coaa1090.strVersion, MODES_DUMP1090_VERSION); - - if ((iErr = initCOAA (coaa1090))) - { - fprintf(stderr, "Error 0x%X initialising uploader\n", iErr); - exit(1); - } -} -// -// ================================ Main ==================================== -// -void showHelp(void) { - printf( -"-----------------------------------------------------------------------------\n" -"| ppup1090 RPi Uploader for COAA Planeplotter Ver : "MODES_DUMP1090_VERSION " |\n" -"-----------------------------------------------------------------------------\n" - "--net-bo-ipaddr TCP Beast output listen IPv4 (default: 127.0.0.1)\n" - "--net-bo-port TCP Beast output listen port (default: 30005)\n" - "--net-pp-ipaddr Plane Plotter LAN IPv4 Address (default: 0.0.0.0)\n" - "--quiet Disable output to stdout. Use for daemon applications\n" - "--help Show this help\n" - ); -} - -#ifdef _WIN32 -void showCopyright(void) { - uint64_t llTime = time(NULL) + 1; - - printf( -"-----------------------------------------------------------------------------\n" -"| ppup1090 RPi Uploader for COAA Planeplotter Ver : "MODES_DUMP1090_VERSION " |\n" -"-----------------------------------------------------------------------------\n" -"\n" -" Copyright (C) 2012 by Salvatore Sanfilippo \n" -" Copyright (C) 2014 by Malcolm Robb \n" -"\n" -" All rights reserved.\n" -"\n" -" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n" -" ""AS IS"" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n" -" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n" -" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n" -" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n" -" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n" -" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n" -" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n" -" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n" -" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n" -" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n" -"\n" -" For further details refer to \n" -"\n" - ); - - // delay for 1 second to give the user a chance to read the copyright - while (llTime >= time(NULL)) {} -} -#endif -// -//========================================================================= -// -int main(int argc, char **argv) { - int j, fd; - struct client *c; - - // Set sane defaults - - ppup1090InitConfig(); - signal(SIGINT, sigintHandler); // Define Ctrl/C handler (exit program) - - // Parse the command line options - for (j = 1; j < argc; j++) { - int more = ((j + 1) < argc); // There are more arguments - - if (!strcmp(argv[j],"--net-bo-port") && more) { - Modes.net_input_beast_port = atoi(argv[++j]); - } else if (!strcmp(argv[j],"--net-bo-ipaddr") && more) { - strcpy(ppup1090.net_input_beast_ipaddr, argv[++j]); - } else if (!strcmp(argv[j],"--net-pp-ipaddr") && more) { - inet_aton(argv[++j], (void *)&ppup1090.net_pp_ipaddr); - } else if (!strcmp(argv[j],"--quiet")) { - ppup1090.quiet = 1; - } else if (!strcmp(argv[j],"--help")) { - showHelp(); - exit(0); - } else { - fprintf(stderr, "Unknown or not enough arguments for option '%s'.\n\n", argv[j]); - showHelp(); - exit(1); - } - } - -#ifdef _WIN32 - // Try to comply with the Copyright license conditions for binary distribution - if (!ppup1090.quiet) {showCopyright();} -#endif - - // Initialization - ppup1090Init(); - - // Try to connect to the selected ip address and port. We only support *ONE* input connection which we initiate.here. - if ((fd = anetTcpConnect(Modes.aneterr, ppup1090.net_input_beast_ipaddr, Modes.net_input_beast_port)) == ANET_ERR) { - fprintf(stderr, "Failed to connect to %s:%d\n", ppup1090.net_input_beast_ipaddr, Modes.net_input_beast_port); - exit(1); - } - // - // Setup a service callback client structure for a beast binary input (from dump1090) - // This is a bit dodgy under Windows. The fd parameter is a handle to the internet - // socket on which we are receiving data. Under Linux, these seem to start at 0 and - // count upwards. However, Windows uses "HANDLES" and these don't nececeriy start at 0. - // dump1090 limits fd to values less than 1024, and then uses the fd parameter to - // index into an array of clients. This is ok-ish if handles are allocated up from 0. - // However, there is no gaurantee that Windows will behave like this, and if Windows - // allocates a handle greater than 1024, then dump1090 won't like it. On my test machine, - // the first Windows handle is usually in the 0x54 (84 decimal) region. - - c = (struct client *) malloc(sizeof(*c)); - c->next = NULL; - c->buflen = 0; - c->fd = - c->service = - Modes.bis = fd; - Modes.clients = c; - - // Keep going till the user does something that stops us - while (!Modes.exit) { - modesReadFromClient(c,"",decodeBinMessage); - interactiveRemoveStaleAircrafts(); - postCOAA (); - } - - // The user has stopped us, so close any socket we opened - if (fd != ANET_ERR) - {close(fd);} - - closeCOAA (); -#ifndef _WIN32 - pthread_exit(0); -#else - return (0); -#endif -} -// -//========================================================================= -// diff --git a/ppup1090.h b/ppup1090.h deleted file mode 100644 index 6d0756d8f..000000000 --- a/ppup1090.h +++ /dev/null @@ -1,110 +0,0 @@ -// ppup1090, a Mode S PlanePlotter Uploader for dump1090 devices. -// -// Copyright (C) 2013 by Malcolm Robb -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -#ifndef __PPUP1090_H -#define __PPUP1090_H - -// ============================= Include files ========================== - -#include "dump1090.h" - -#ifndef _WIN32 - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include "rtl-sdr.h" - #include "anet.h" - #include -#else - #include "winstubs.h" //Put everything Windows specific in here -#endif - -// ============================= #defines =============================== - -#define PPUP1090_NET_OUTPUT_IP_ADDRESS "127.0.0.1" - -#define NOTUSED(V) ((void) V) - -#define STR_HELPER(x) #x -#define STR(x) STR_HELPER(x) - -// ======================== structure declarations ======================== - -// Program global state -struct { // Internal state - int quiet; - // Networking - uint32_t net_pp_ipaddr; // IPv4 address of PP instance - char net_input_beast_ipaddr[32]; // IPv4 address or network name of server/RPi -} ppup1090; - - -// COAA Initialisation structure -struct _coaa1090 { - uint32_t ppIPAddr; - double fUserLat; - double fUserLon; - char strAuthCode[16]; - char strRegNo[16]; - char strVersion[16]; -} coaa1090; - -// ======================== function declarations ========================= - -#ifdef __cplusplus -extern "C" { -#endif - -// -// Functions exported from coaa1090.c -// -int openCOAA (void); -int closeCOAA (void); -int initCOAA (struct _coaa1090 coaa1090); -void postCOAA (void); - -#ifdef __cplusplus -} -#endif - -#endif // __PPUP1090_H diff --git a/ppup1090.sh b/ppup1090.sh deleted file mode 100644 index 8ed4ad3f3..000000000 --- a/ppup1090.sh +++ /dev/null @@ -1,85 +0,0 @@ -#!/bin/bash -### BEGIN INIT INFO -# -# Provides: dump1090 -# Required-Start: $remote_fs -# Required-Stop: $remote_fs -# Default-Start: 2 3 4 5 -# Default-Stop: 0 1 6 -# Short-Description: dump1090 initscript - -# -### END INIT INFO -## Fill in name of program here. -PROG="dump1090" -PROG_PATH="/home/pi/dump1090" -PROG_ARGS="--quiet --net --net-ro-size 500 --net-ro-rate 5 --net-buffer 5" -PIDFILE="/var/run/dump1090.pid" -PROG2="ppup1090" -PROG2_ARGS="--quiet --net-pp-addr 192.168.1.64" -PIDFILE2="/var/run/$PROG2.pid" -DELAY=5 - -start() { - if [ -e $PIDFILE ]; then - ## Program is running, exit with error. - echo "Error! $PROG is currently running!" 1>&2 - exit 1 - else - ## Change from /dev/null to something like /var/log/$PROG if you want to save output. - cd $PROG_PATH - ./$PROG $PROG_ARGS 2>&1 >/dev/null & - echo "$PROG started, waiting $DELAY seconds" - touch $PIDFILE - sleep $DELAY - echo "Attempting to start $PROG2.." - ./$PROG2 $PROG2_ARGS 2>1 >/dev/null & - echo "$PROG2 started" - touch $PIDFILE2 - fi -} - -stop() { - if [ -e $PIDFILE ]; then - ## Program is running, so stop it - echo "$PROG is running" - killall $PROG2 - killall $PROG - rm -f $PIDFILE2 - rm -f $PIDFILE - echo "$PROG stopped" - else - ## Program is not running, exit with error. - echo "Error! $PROG not started!" 1>&2 - exit 1 - fi -} - -## Check to see if we are running as root first. -## Found at http://www.cyberciti.biz/tips/shell-root-user-check-script.html -if [ "$(id -u)" != "0" ]; then - echo "This script must be run as root" 1>&2 - exit 1 -fi - -case "$1" in - start) - start - exit 0 - ;; - stop) - stop - exit 0 - ;; - reload|restart|force-reload) - stop - start - exit 0 - ;; - **) - echo "Usage: $0 {start|stop|reload}" 1>&2 - exit 1 - ;; -esac -# - diff --git a/pthreads/pthread.h b/pthreads/pthread.h deleted file mode 100644 index b4072f72c..000000000 --- a/pthreads/pthread.h +++ /dev/null @@ -1,1368 +0,0 @@ -/* This is an implementation of the threads API of POSIX 1003.1-2001. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#if !defined( PTHREAD_H ) -#define PTHREAD_H - -/* - * See the README file for an explanation of the pthreads-win32 version - * numbering scheme and how the DLL is named etc. - */ -#define PTW32_VERSION 2,9,1,0 -#define PTW32_VERSION_STRING "2, 9, 1, 0\0" - -/* There are three implementations of cancel cleanup. - * Note that pthread.h is included in both application - * compilation units and also internally for the library. - * The code here and within the library aims to work - * for all reasonable combinations of environments. - * - * The three implementations are: - * - * WIN32 SEH - * C - * C++ - * - * Please note that exiting a push/pop block via - * "return", "exit", "break", or "continue" will - * lead to different behaviour amongst applications - * depending upon whether the library was built - * using SEH, C++, or C. For example, a library built - * with SEH will call the cleanup routine, while both - * C++ and C built versions will not. - */ - -/* - * Define defaults for cleanup code. - * Note: Unless the build explicitly defines one of the following, then - * we default to standard C style cleanup. This style uses setjmp/longjmp - * in the cancelation and thread exit implementations and therefore won't - * do stack unwinding if linked to applications that have it (e.g. - * C++ apps). This is currently consistent with most/all commercial Unix - * POSIX threads implementations. - */ -#if !defined( __CLEANUP_SEH ) && !defined( __CLEANUP_CXX ) && !defined( __CLEANUP_C ) -# define __CLEANUP_C -#endif - -#if defined( __CLEANUP_SEH ) && ( !defined( _MSC_VER ) && !defined(PTW32_RC_MSC)) -#error ERROR [__FILE__, line __LINE__]: SEH is not supported for this compiler. -#endif - -/* - * Stop here if we are being included by the resource compiler. - */ -#if !defined(RC_INVOKED) - -#undef PTW32_LEVEL - -#if defined(_POSIX_SOURCE) -#define PTW32_LEVEL 0 -/* Early POSIX */ -#endif - -#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309 -#undef PTW32_LEVEL -#define PTW32_LEVEL 1 -/* Include 1b, 1c and 1d */ -#endif - -#if defined(INCLUDE_NP) -#undef PTW32_LEVEL -#define PTW32_LEVEL 2 -/* Include Non-Portable extensions */ -#endif - -#define PTW32_LEVEL_MAX 3 - -#if ( defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112 ) || !defined(PTW32_LEVEL) -#define PTW32_LEVEL PTW32_LEVEL_MAX -/* Include everything */ -#endif - -#if defined(_UWIN) -# define HAVE_STRUCT_TIMESPEC 1 -# define HAVE_SIGNAL_H 1 -# undef HAVE_PTW32_CONFIG_H -# pragma comment(lib, "pthread") -#endif - -/* - * ------------------------------------------------------------- - * - * - * Module: pthread.h - * - * Purpose: - * Provides an implementation of PThreads based upon the - * standard: - * - * POSIX 1003.1-2001 - * and - * The Single Unix Specification version 3 - * - * (these two are equivalent) - * - * in order to enhance code portability between Windows, - * various commercial Unix implementations, and Linux. - * - * See the ANNOUNCE file for a full list of conforming - * routines and defined constants, and a list of missing - * routines and constants not defined in this implementation. - * - * Authors: - * There have been many contributors to this library. - * The initial implementation was contributed by - * John Bossom, and several others have provided major - * sections or revisions of parts of the implementation. - * Often significant effort has been contributed to - * find and fix important bugs and other problems to - * improve the reliability of the library, which sometimes - * is not reflected in the amount of code which changed as - * result. - * As much as possible, the contributors are acknowledged - * in the ChangeLog file in the source code distribution - * where their changes are noted in detail. - * - * Contributors are listed in the CONTRIBUTORS file. - * - * As usual, all bouquets go to the contributors, and all - * brickbats go to the project maintainer. - * - * Maintainer: - * The code base for this project is coordinated and - * eventually pre-tested, packaged, and made available by - * - * Ross Johnson - * - * QA Testers: - * Ultimately, the library is tested in the real world by - * a host of competent and demanding scientists and - * engineers who report bugs and/or provide solutions - * which are then fixed or incorporated into subsequent - * versions of the library. Each time a bug is fixed, a - * test case is written to prove the fix and ensure - * that later changes to the code don't reintroduce the - * same error. The number of test cases is slowly growing - * and therefore so is the code reliability. - * - * Compliance: - * See the file ANNOUNCE for the list of implemented - * and not-implemented routines and defined options. - * Of course, these are all defined is this file as well. - * - * Web site: - * The source code and other information about this library - * are available from - * - * http://sources.redhat.com/pthreads-win32/ - * - * ------------------------------------------------------------- - */ - -/* Try to avoid including windows.h */ -#if (defined(__MINGW64__) || defined(__MINGW32__)) && defined(__cplusplus) -#define PTW32_INCLUDE_WINDOWS_H -#endif - -#if defined(PTW32_INCLUDE_WINDOWS_H) -#include -#endif - -#if defined(_MSC_VER) && _MSC_VER < 1300 || defined(__DMC__) -/* - * VC++6.0 or early compiler's header has no DWORD_PTR type. - */ -typedef unsigned long DWORD_PTR; -typedef unsigned long ULONG_PTR; -#endif -/* - * ----------------- - * autoconf switches - * ----------------- - */ - -#if defined(HAVE_PTW32_CONFIG_H) -#include "config.h" -#endif /* HAVE_PTW32_CONFIG_H */ - -#if !defined(NEED_FTIME) -#include -#else /* NEED_FTIME */ -/* use native WIN32 time API */ -#endif /* NEED_FTIME */ - -#if defined(HAVE_SIGNAL_H) -#include -#endif /* HAVE_SIGNAL_H */ - -#include - -/* - * Boolean values to make us independent of system includes. - */ -enum { - PTW32_FALSE = 0, - PTW32_TRUE = (! PTW32_FALSE) -}; - -/* - * This is a duplicate of what is in the autoconf config.h, - * which is only used when building the pthread-win32 libraries. - */ - -#if !defined(PTW32_CONFIG_H) -# if defined(WINCE) -# define NEED_ERRNO -# define NEED_SEM -# endif -# if defined(__MINGW64__) -# define HAVE_STRUCT_TIMESPEC -# define HAVE_MODE_T -# elif defined(_UWIN) || defined(__MINGW32__) -# define HAVE_MODE_T -# endif -#endif - -/* - * - */ - -#if PTW32_LEVEL >= PTW32_LEVEL_MAX -#if defined(NEED_ERRNO) -#include "need_errno.h" -#else -#include -#endif -#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ - -/* - * Several systems don't define some error numbers. - */ -#if !defined(ENOTSUP) -# define ENOTSUP 48 /* This is the value in Solaris. */ -#endif - -#if !defined(ETIMEDOUT) -# define ETIMEDOUT 10060 /* Same as WSAETIMEDOUT */ -#endif - -#if !defined(ENOSYS) -# define ENOSYS 140 /* Semi-arbitrary value */ -#endif - -#if !defined(EDEADLK) -# if defined(EDEADLOCK) -# define EDEADLK EDEADLOCK -# else -# define EDEADLK 36 /* This is the value in MSVC. */ -# endif -#endif - -/* POSIX 2008 - related to robust mutexes */ -#if !defined(EOWNERDEAD) -# define EOWNERDEAD 43 -#endif -#if !defined(ENOTRECOVERABLE) -# define ENOTRECOVERABLE 44 -#endif - -#include - -/* - * To avoid including windows.h we define only those things that we - * actually need from it. - */ -#if !defined(PTW32_INCLUDE_WINDOWS_H) -#if !defined(HANDLE) -# define PTW32__HANDLE_DEF -# define HANDLE void * -#endif -#if !defined(DWORD) -# define PTW32__DWORD_DEF -# define DWORD unsigned long -#endif -#endif - -#if !defined(HAVE_STRUCT_TIMESPEC) -#define HAVE_STRUCT_TIMESPEC -#if !defined(_TIMESPEC_DEFINED) -#define _TIMESPEC_DEFINED -struct timespec { - time_t tv_sec; - long tv_nsec; -}; -#endif /* _TIMESPEC_DEFINED */ -#endif /* HAVE_STRUCT_TIMESPEC */ - -#if !defined(SIG_BLOCK) -#define SIG_BLOCK 0 -#endif /* SIG_BLOCK */ - -#if !defined(SIG_UNBLOCK) -#define SIG_UNBLOCK 1 -#endif /* SIG_UNBLOCK */ - -#if !defined(SIG_SETMASK) -#define SIG_SETMASK 2 -#endif /* SIG_SETMASK */ - -#if defined(__cplusplus) -extern "C" -{ -#endif /* __cplusplus */ - -/* - * ------------------------------------------------------------- - * - * POSIX 1003.1-2001 Options - * ========================= - * - * Options are normally set in , which is not provided - * with pthreads-win32. - * - * For conformance with the Single Unix Specification (version 3), all of the - * options below are defined, and have a value of either -1 (not supported) - * or 200112L (supported). - * - * These options can neither be left undefined nor have a value of 0, because - * either indicates that sysconf(), which is not implemented, may be used at - * runtime to check the status of the option. - * - * _POSIX_THREADS (== 200112L) - * If == 200112L, you can use threads - * - * _POSIX_THREAD_ATTR_STACKSIZE (== 200112L) - * If == 200112L, you can control the size of a thread's - * stack - * pthread_attr_getstacksize - * pthread_attr_setstacksize - * - * _POSIX_THREAD_ATTR_STACKADDR (== -1) - * If == 200112L, you can allocate and control a thread's - * stack. If not supported, the following functions - * will return ENOSYS, indicating they are not - * supported: - * pthread_attr_getstackaddr - * pthread_attr_setstackaddr - * - * _POSIX_THREAD_PRIORITY_SCHEDULING (== -1) - * If == 200112L, you can use realtime scheduling. - * This option indicates that the behaviour of some - * implemented functions conforms to the additional TPS - * requirements in the standard. E.g. rwlocks favour - * writers over readers when threads have equal priority. - * - * _POSIX_THREAD_PRIO_INHERIT (== -1) - * If == 200112L, you can create priority inheritance - * mutexes. - * pthread_mutexattr_getprotocol + - * pthread_mutexattr_setprotocol + - * - * _POSIX_THREAD_PRIO_PROTECT (== -1) - * If == 200112L, you can create priority ceiling mutexes - * Indicates the availability of: - * pthread_mutex_getprioceiling - * pthread_mutex_setprioceiling - * pthread_mutexattr_getprioceiling - * pthread_mutexattr_getprotocol + - * pthread_mutexattr_setprioceiling - * pthread_mutexattr_setprotocol + - * - * _POSIX_THREAD_PROCESS_SHARED (== -1) - * If set, you can create mutexes and condition - * variables that can be shared with another - * process.If set, indicates the availability - * of: - * pthread_mutexattr_getpshared - * pthread_mutexattr_setpshared - * pthread_condattr_getpshared - * pthread_condattr_setpshared - * - * _POSIX_THREAD_SAFE_FUNCTIONS (== 200112L) - * If == 200112L you can use the special *_r library - * functions that provide thread-safe behaviour - * - * _POSIX_READER_WRITER_LOCKS (== 200112L) - * If == 200112L, you can use read/write locks - * - * _POSIX_SPIN_LOCKS (== 200112L) - * If == 200112L, you can use spin locks - * - * _POSIX_BARRIERS (== 200112L) - * If == 200112L, you can use barriers - * - * + These functions provide both 'inherit' and/or - * 'protect' protocol, based upon these macro - * settings. - * - * ------------------------------------------------------------- - */ - -/* - * POSIX Options - */ -#undef _POSIX_THREADS -#define _POSIX_THREADS 200809L - -#undef _POSIX_READER_WRITER_LOCKS -#define _POSIX_READER_WRITER_LOCKS 200809L - -#undef _POSIX_SPIN_LOCKS -#define _POSIX_SPIN_LOCKS 200809L - -#undef _POSIX_BARRIERS -#define _POSIX_BARRIERS 200809L - -#undef _POSIX_THREAD_SAFE_FUNCTIONS -#define _POSIX_THREAD_SAFE_FUNCTIONS 200809L - -#undef _POSIX_THREAD_ATTR_STACKSIZE -#define _POSIX_THREAD_ATTR_STACKSIZE 200809L - -/* - * The following options are not supported - */ -#undef _POSIX_THREAD_ATTR_STACKADDR -#define _POSIX_THREAD_ATTR_STACKADDR -1 - -#undef _POSIX_THREAD_PRIO_INHERIT -#define _POSIX_THREAD_PRIO_INHERIT -1 - -#undef _POSIX_THREAD_PRIO_PROTECT -#define _POSIX_THREAD_PRIO_PROTECT -1 - -/* TPS is not fully supported. */ -#undef _POSIX_THREAD_PRIORITY_SCHEDULING -#define _POSIX_THREAD_PRIORITY_SCHEDULING -1 - -#undef _POSIX_THREAD_PROCESS_SHARED -#define _POSIX_THREAD_PROCESS_SHARED -1 - - -/* - * POSIX 1003.1-2001 Limits - * =========================== - * - * These limits are normally set in , which is not provided with - * pthreads-win32. - * - * PTHREAD_DESTRUCTOR_ITERATIONS - * Maximum number of attempts to destroy - * a thread's thread-specific data on - * termination (must be at least 4) - * - * PTHREAD_KEYS_MAX - * Maximum number of thread-specific data keys - * available per process (must be at least 128) - * - * PTHREAD_STACK_MIN - * Minimum supported stack size for a thread - * - * PTHREAD_THREADS_MAX - * Maximum number of threads supported per - * process (must be at least 64). - * - * SEM_NSEMS_MAX - * The maximum number of semaphores a process can have. - * (must be at least 256) - * - * SEM_VALUE_MAX - * The maximum value a semaphore can have. - * (must be at least 32767) - * - */ -#undef _POSIX_THREAD_DESTRUCTOR_ITERATIONS -#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4 - -#undef PTHREAD_DESTRUCTOR_ITERATIONS -#define PTHREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_DESTRUCTOR_ITERATIONS - -#undef _POSIX_THREAD_KEYS_MAX -#define _POSIX_THREAD_KEYS_MAX 128 - -#undef PTHREAD_KEYS_MAX -#define PTHREAD_KEYS_MAX _POSIX_THREAD_KEYS_MAX - -#undef PTHREAD_STACK_MIN -#define PTHREAD_STACK_MIN 0 - -#undef _POSIX_THREAD_THREADS_MAX -#define _POSIX_THREAD_THREADS_MAX 64 - - /* Arbitrary value */ -#undef PTHREAD_THREADS_MAX -#define PTHREAD_THREADS_MAX 2019 - -#undef _POSIX_SEM_NSEMS_MAX -#define _POSIX_SEM_NSEMS_MAX 256 - - /* Arbitrary value */ -#undef SEM_NSEMS_MAX -#define SEM_NSEMS_MAX 1024 - -#undef _POSIX_SEM_VALUE_MAX -#define _POSIX_SEM_VALUE_MAX 32767 - -#undef SEM_VALUE_MAX -#define SEM_VALUE_MAX INT_MAX - - -#if defined(__GNUC__) && !defined(__declspec) -# error Please upgrade your GNU compiler to one that supports __declspec. -#endif - -/* - * When building the library, you should define PTW32_BUILD so that - * the variables/functions are exported correctly. When using the library, - * do NOT define PTW32_BUILD, and then the variables/functions will - * be imported correctly. - */ -#if !defined(PTW32_STATIC_LIB) -# if defined(PTW32_BUILD) -# define PTW32_DLLPORT __declspec (dllexport) -# else -# define PTW32_DLLPORT __declspec (dllimport) -# endif -#else -# define PTW32_DLLPORT -#endif - -/* - * The Open Watcom C/C++ compiler uses a non-standard calling convention - * that passes function args in registers unless __cdecl is explicitly specified - * in exposed function prototypes. - * - * We force all calls to cdecl even though this could slow Watcom code down - * slightly. If you know that the Watcom compiler will be used to build both - * the DLL and application, then you can probably define this as a null string. - * Remember that pthread.h (this file) is used for both the DLL and application builds. - */ -#define PTW32_CDECL __cdecl - -#if defined(_UWIN) && PTW32_LEVEL >= PTW32_LEVEL_MAX -# include -#else -/* - * Generic handle type - intended to extend uniqueness beyond - * that available with a simple pointer. It should scale for either - * IA-32 or IA-64. - */ -typedef struct { - void * p; /* Pointer to actual object */ - unsigned int x; /* Extra information - reuse count etc */ -} ptw32_handle_t; - -typedef ptw32_handle_t pthread_t; -typedef struct pthread_attr_t_ * pthread_attr_t; -typedef struct pthread_once_t_ pthread_once_t; -typedef struct pthread_key_t_ * pthread_key_t; -typedef struct pthread_mutex_t_ * pthread_mutex_t; -typedef struct pthread_mutexattr_t_ * pthread_mutexattr_t; -typedef struct pthread_cond_t_ * pthread_cond_t; -typedef struct pthread_condattr_t_ * pthread_condattr_t; -#endif -typedef struct pthread_rwlock_t_ * pthread_rwlock_t; -typedef struct pthread_rwlockattr_t_ * pthread_rwlockattr_t; -typedef struct pthread_spinlock_t_ * pthread_spinlock_t; -typedef struct pthread_barrier_t_ * pthread_barrier_t; -typedef struct pthread_barrierattr_t_ * pthread_barrierattr_t; - -/* - * ==================== - * ==================== - * POSIX Threads - * ==================== - * ==================== - */ - -enum { -/* - * pthread_attr_{get,set}detachstate - */ - PTHREAD_CREATE_JOINABLE = 0, /* Default */ - PTHREAD_CREATE_DETACHED = 1, - -/* - * pthread_attr_{get,set}inheritsched - */ - PTHREAD_INHERIT_SCHED = 0, - PTHREAD_EXPLICIT_SCHED = 1, /* Default */ - -/* - * pthread_{get,set}scope - */ - PTHREAD_SCOPE_PROCESS = 0, - PTHREAD_SCOPE_SYSTEM = 1, /* Default */ - -/* - * pthread_setcancelstate paramters - */ - PTHREAD_CANCEL_ENABLE = 0, /* Default */ - PTHREAD_CANCEL_DISABLE = 1, - -/* - * pthread_setcanceltype parameters - */ - PTHREAD_CANCEL_ASYNCHRONOUS = 0, - PTHREAD_CANCEL_DEFERRED = 1, /* Default */ - -/* - * pthread_mutexattr_{get,set}pshared - * pthread_condattr_{get,set}pshared - */ - PTHREAD_PROCESS_PRIVATE = 0, - PTHREAD_PROCESS_SHARED = 1, - -/* - * pthread_mutexattr_{get,set}robust - */ - PTHREAD_MUTEX_STALLED = 0, /* Default */ - PTHREAD_MUTEX_ROBUST = 1, - -/* - * pthread_barrier_wait - */ - PTHREAD_BARRIER_SERIAL_THREAD = -1 -}; - -/* - * ==================== - * ==================== - * Cancelation - * ==================== - * ==================== - */ -#define PTHREAD_CANCELED ((void *)(size_t) -1) - - -/* - * ==================== - * ==================== - * Once Key - * ==================== - * ==================== - */ -#define PTHREAD_ONCE_INIT { PTW32_FALSE, 0, 0, 0} - -struct pthread_once_t_ -{ - int done; /* indicates if user function has been executed */ - void * lock; - int reserved1; - int reserved2; -}; - - -/* - * ==================== - * ==================== - * Object initialisers - * ==================== - * ==================== - */ -#define PTHREAD_MUTEX_INITIALIZER ((pthread_mutex_t)(size_t) -1) -#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER ((pthread_mutex_t)(size_t) -2) -#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER ((pthread_mutex_t)(size_t) -3) - -/* - * Compatibility with LinuxThreads - */ -#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP PTHREAD_RECURSIVE_MUTEX_INITIALIZER -#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP PTHREAD_ERRORCHECK_MUTEX_INITIALIZER - -#define PTHREAD_COND_INITIALIZER ((pthread_cond_t)(size_t) -1) - -#define PTHREAD_RWLOCK_INITIALIZER ((pthread_rwlock_t)(size_t) -1) - -#define PTHREAD_SPINLOCK_INITIALIZER ((pthread_spinlock_t)(size_t) -1) - - -/* - * Mutex types. - */ -enum -{ - /* Compatibility with LinuxThreads */ - PTHREAD_MUTEX_FAST_NP, - PTHREAD_MUTEX_RECURSIVE_NP, - PTHREAD_MUTEX_ERRORCHECK_NP, - PTHREAD_MUTEX_TIMED_NP = PTHREAD_MUTEX_FAST_NP, - PTHREAD_MUTEX_ADAPTIVE_NP = PTHREAD_MUTEX_FAST_NP, - /* For compatibility with POSIX */ - PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_FAST_NP, - PTHREAD_MUTEX_RECURSIVE = PTHREAD_MUTEX_RECURSIVE_NP, - PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP, - PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL -}; - - -typedef struct ptw32_cleanup_t ptw32_cleanup_t; - -#if defined(_MSC_VER) -/* Disable MSVC 'anachronism used' warning */ -#pragma warning( disable : 4229 ) -#endif - -typedef void (* PTW32_CDECL ptw32_cleanup_callback_t)(void *); - -#if defined(_MSC_VER) -#pragma warning( default : 4229 ) -#endif - -struct ptw32_cleanup_t -{ - ptw32_cleanup_callback_t routine; - void *arg; - struct ptw32_cleanup_t *prev; -}; - -#if defined(__CLEANUP_SEH) - /* - * WIN32 SEH version of cancel cleanup. - */ - -#define pthread_cleanup_push( _rout, _arg ) \ - { \ - ptw32_cleanup_t _cleanup; \ - \ - _cleanup.routine = (ptw32_cleanup_callback_t)(_rout); \ - _cleanup.arg = (_arg); \ - __try \ - { \ - -#define pthread_cleanup_pop( _execute ) \ - } \ - __finally \ - { \ - if( _execute || AbnormalTermination()) \ - { \ - (*(_cleanup.routine))( _cleanup.arg ); \ - } \ - } \ - } - -#else /* __CLEANUP_SEH */ - -#if defined(__CLEANUP_C) - - /* - * C implementation of PThreads cancel cleanup - */ - -#define pthread_cleanup_push( _rout, _arg ) \ - { \ - ptw32_cleanup_t _cleanup; \ - \ - ptw32_push_cleanup( &_cleanup, (ptw32_cleanup_callback_t) (_rout), (_arg) ); \ - -#define pthread_cleanup_pop( _execute ) \ - (void) ptw32_pop_cleanup( _execute ); \ - } - -#else /* __CLEANUP_C */ - -#if defined(__CLEANUP_CXX) - - /* - * C++ version of cancel cleanup. - * - John E. Bossom. - */ - - class PThreadCleanup { - /* - * PThreadCleanup - * - * Purpose - * This class is a C++ helper class that is - * used to implement pthread_cleanup_push/ - * pthread_cleanup_pop. - * The destructor of this class automatically - * pops the pushed cleanup routine regardless - * of how the code exits the scope - * (i.e. such as by an exception) - */ - ptw32_cleanup_callback_t cleanUpRout; - void * obj; - int executeIt; - - public: - PThreadCleanup() : - cleanUpRout( 0 ), - obj( 0 ), - executeIt( 0 ) - /* - * No cleanup performed - */ - { - } - - PThreadCleanup( - ptw32_cleanup_callback_t routine, - void * arg ) : - cleanUpRout( routine ), - obj( arg ), - executeIt( 1 ) - /* - * Registers a cleanup routine for 'arg' - */ - { - } - - ~PThreadCleanup() - { - if ( executeIt && ((void *) cleanUpRout != (void *) 0) ) - { - (void) (*cleanUpRout)( obj ); - } - } - - void execute( int exec ) - { - executeIt = exec; - } - }; - - /* - * C++ implementation of PThreads cancel cleanup; - * This implementation takes advantage of a helper - * class who's destructor automatically calls the - * cleanup routine if we exit our scope weirdly - */ -#define pthread_cleanup_push( _rout, _arg ) \ - { \ - PThreadCleanup cleanup((ptw32_cleanup_callback_t)(_rout), \ - (void *) (_arg) ); - -#define pthread_cleanup_pop( _execute ) \ - cleanup.execute( _execute ); \ - } - -#else - -#error ERROR [__FILE__, line __LINE__]: Cleanup type undefined. - -#endif /* __CLEANUP_CXX */ - -#endif /* __CLEANUP_C */ - -#endif /* __CLEANUP_SEH */ - -/* - * =============== - * =============== - * Methods - * =============== - * =============== - */ - -/* - * PThread Attribute Functions - */ -PTW32_DLLPORT int PTW32_CDECL pthread_attr_init (pthread_attr_t * attr); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_destroy (pthread_attr_t * attr); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_getdetachstate (const pthread_attr_t * attr, - int *detachstate); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_getstackaddr (const pthread_attr_t * attr, - void **stackaddr); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_getstacksize (const pthread_attr_t * attr, - size_t * stacksize); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_setdetachstate (pthread_attr_t * attr, - int detachstate); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_setstackaddr (pthread_attr_t * attr, - void *stackaddr); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_setstacksize (pthread_attr_t * attr, - size_t stacksize); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_getschedparam (const pthread_attr_t *attr, - struct sched_param *param); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_setschedparam (pthread_attr_t *attr, - const struct sched_param *param); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_setschedpolicy (pthread_attr_t *, - int); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_getschedpolicy (const pthread_attr_t *, - int *); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_setinheritsched(pthread_attr_t * attr, - int inheritsched); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_getinheritsched(const pthread_attr_t * attr, - int * inheritsched); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_setscope (pthread_attr_t *, - int); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_getscope (const pthread_attr_t *, - int *); - -/* - * PThread Functions - */ -PTW32_DLLPORT int PTW32_CDECL pthread_create (pthread_t * tid, - const pthread_attr_t * attr, - void *(PTW32_CDECL *start) (void *), - void *arg); - -PTW32_DLLPORT int PTW32_CDECL pthread_detach (pthread_t tid); - -PTW32_DLLPORT int PTW32_CDECL pthread_equal (pthread_t t1, - pthread_t t2); - -PTW32_DLLPORT void PTW32_CDECL pthread_exit (void *value_ptr); - -PTW32_DLLPORT int PTW32_CDECL pthread_join (pthread_t thread, - void **value_ptr); - -PTW32_DLLPORT pthread_t PTW32_CDECL pthread_self (void); - -PTW32_DLLPORT int PTW32_CDECL pthread_cancel (pthread_t thread); - -PTW32_DLLPORT int PTW32_CDECL pthread_setcancelstate (int state, - int *oldstate); - -PTW32_DLLPORT int PTW32_CDECL pthread_setcanceltype (int type, - int *oldtype); - -PTW32_DLLPORT void PTW32_CDECL pthread_testcancel (void); - -PTW32_DLLPORT int PTW32_CDECL pthread_once (pthread_once_t * once_control, - void (PTW32_CDECL *init_routine) (void)); - -#if PTW32_LEVEL >= PTW32_LEVEL_MAX -PTW32_DLLPORT ptw32_cleanup_t * PTW32_CDECL ptw32_pop_cleanup (int execute); - -PTW32_DLLPORT void PTW32_CDECL ptw32_push_cleanup (ptw32_cleanup_t * cleanup, - ptw32_cleanup_callback_t routine, - void *arg); -#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ - -/* - * Thread Specific Data Functions - */ -PTW32_DLLPORT int PTW32_CDECL pthread_key_create (pthread_key_t * key, - void (PTW32_CDECL *destructor) (void *)); - -PTW32_DLLPORT int PTW32_CDECL pthread_key_delete (pthread_key_t key); - -PTW32_DLLPORT int PTW32_CDECL pthread_setspecific (pthread_key_t key, - const void *value); - -PTW32_DLLPORT void * PTW32_CDECL pthread_getspecific (pthread_key_t key); - - -/* - * Mutex Attribute Functions - */ -PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_init (pthread_mutexattr_t * attr); - -PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_destroy (pthread_mutexattr_t * attr); - -PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getpshared (const pthread_mutexattr_t - * attr, - int *pshared); - -PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setpshared (pthread_mutexattr_t * attr, - int pshared); - -PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_settype (pthread_mutexattr_t * attr, int kind); -PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_gettype (const pthread_mutexattr_t * attr, int *kind); - -PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setrobust( - pthread_mutexattr_t *attr, - int robust); -PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getrobust( - const pthread_mutexattr_t * attr, - int * robust); - -/* - * Barrier Attribute Functions - */ -PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_init (pthread_barrierattr_t * attr); - -PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_destroy (pthread_barrierattr_t * attr); - -PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_getpshared (const pthread_barrierattr_t - * attr, - int *pshared); - -PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_setpshared (pthread_barrierattr_t * attr, - int pshared); - -/* - * Mutex Functions - */ -PTW32_DLLPORT int PTW32_CDECL pthread_mutex_init (pthread_mutex_t * mutex, - const pthread_mutexattr_t * attr); - -PTW32_DLLPORT int PTW32_CDECL pthread_mutex_destroy (pthread_mutex_t * mutex); - -PTW32_DLLPORT int PTW32_CDECL pthread_mutex_lock (pthread_mutex_t * mutex); - -PTW32_DLLPORT int PTW32_CDECL pthread_mutex_timedlock(pthread_mutex_t * mutex, - const struct timespec *abstime); - -PTW32_DLLPORT int PTW32_CDECL pthread_mutex_trylock (pthread_mutex_t * mutex); - -PTW32_DLLPORT int PTW32_CDECL pthread_mutex_unlock (pthread_mutex_t * mutex); - -PTW32_DLLPORT int PTW32_CDECL pthread_mutex_consistent (pthread_mutex_t * mutex); - -/* - * Spinlock Functions - */ -PTW32_DLLPORT int PTW32_CDECL pthread_spin_init (pthread_spinlock_t * lock, int pshared); - -PTW32_DLLPORT int PTW32_CDECL pthread_spin_destroy (pthread_spinlock_t * lock); - -PTW32_DLLPORT int PTW32_CDECL pthread_spin_lock (pthread_spinlock_t * lock); - -PTW32_DLLPORT int PTW32_CDECL pthread_spin_trylock (pthread_spinlock_t * lock); - -PTW32_DLLPORT int PTW32_CDECL pthread_spin_unlock (pthread_spinlock_t * lock); - -/* - * Barrier Functions - */ -PTW32_DLLPORT int PTW32_CDECL pthread_barrier_init (pthread_barrier_t * barrier, - const pthread_barrierattr_t * attr, - unsigned int count); - -PTW32_DLLPORT int PTW32_CDECL pthread_barrier_destroy (pthread_barrier_t * barrier); - -PTW32_DLLPORT int PTW32_CDECL pthread_barrier_wait (pthread_barrier_t * barrier); - -/* - * Condition Variable Attribute Functions - */ -PTW32_DLLPORT int PTW32_CDECL pthread_condattr_init (pthread_condattr_t * attr); - -PTW32_DLLPORT int PTW32_CDECL pthread_condattr_destroy (pthread_condattr_t * attr); - -PTW32_DLLPORT int PTW32_CDECL pthread_condattr_getpshared (const pthread_condattr_t * attr, - int *pshared); - -PTW32_DLLPORT int PTW32_CDECL pthread_condattr_setpshared (pthread_condattr_t * attr, - int pshared); - -/* - * Condition Variable Functions - */ -PTW32_DLLPORT int PTW32_CDECL pthread_cond_init (pthread_cond_t * cond, - const pthread_condattr_t * attr); - -PTW32_DLLPORT int PTW32_CDECL pthread_cond_destroy (pthread_cond_t * cond); - -PTW32_DLLPORT int PTW32_CDECL pthread_cond_wait (pthread_cond_t * cond, - pthread_mutex_t * mutex); - -PTW32_DLLPORT int PTW32_CDECL pthread_cond_timedwait (pthread_cond_t * cond, - pthread_mutex_t * mutex, - const struct timespec *abstime); - -PTW32_DLLPORT int PTW32_CDECL pthread_cond_signal (pthread_cond_t * cond); - -PTW32_DLLPORT int PTW32_CDECL pthread_cond_broadcast (pthread_cond_t * cond); - -/* - * Scheduling - */ -PTW32_DLLPORT int PTW32_CDECL pthread_setschedparam (pthread_t thread, - int policy, - const struct sched_param *param); - -PTW32_DLLPORT int PTW32_CDECL pthread_getschedparam (pthread_t thread, - int *policy, - struct sched_param *param); - -PTW32_DLLPORT int PTW32_CDECL pthread_setconcurrency (int); - -PTW32_DLLPORT int PTW32_CDECL pthread_getconcurrency (void); - -/* - * Read-Write Lock Functions - */ -PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_init(pthread_rwlock_t *lock, - const pthread_rwlockattr_t *attr); - -PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_destroy(pthread_rwlock_t *lock); - -PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_tryrdlock(pthread_rwlock_t *); - -PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_trywrlock(pthread_rwlock_t *); - -PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_rdlock(pthread_rwlock_t *lock); - -PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_timedrdlock(pthread_rwlock_t *lock, - const struct timespec *abstime); - -PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_wrlock(pthread_rwlock_t *lock); - -PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_timedwrlock(pthread_rwlock_t *lock, - const struct timespec *abstime); - -PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_unlock(pthread_rwlock_t *lock); - -PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_init (pthread_rwlockattr_t * attr); - -PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_destroy (pthread_rwlockattr_t * attr); - -PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_getpshared (const pthread_rwlockattr_t * attr, - int *pshared); - -PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_setpshared (pthread_rwlockattr_t * attr, - int pshared); - -#if PTW32_LEVEL >= PTW32_LEVEL_MAX - 1 - -/* - * Signal Functions. Should be defined in but MSVC and MinGW32 - * already have signal.h that don't define these. - */ -PTW32_DLLPORT int PTW32_CDECL pthread_kill(pthread_t thread, int sig); - -/* - * Non-portable functions - */ - -/* - * Compatibility with Linux. - */ -PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setkind_np(pthread_mutexattr_t * attr, - int kind); -PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getkind_np(pthread_mutexattr_t * attr, - int *kind); - -/* - * Possibly supported by other POSIX threads implementations - */ -PTW32_DLLPORT int PTW32_CDECL pthread_delay_np (struct timespec * interval); -PTW32_DLLPORT int PTW32_CDECL pthread_num_processors_np(void); -PTW32_DLLPORT unsigned __int64 PTW32_CDECL pthread_getunique_np(pthread_t thread); - -/* - * Useful if an application wants to statically link - * the lib rather than load the DLL at run-time. - */ -PTW32_DLLPORT int PTW32_CDECL pthread_win32_process_attach_np(void); -PTW32_DLLPORT int PTW32_CDECL pthread_win32_process_detach_np(void); -PTW32_DLLPORT int PTW32_CDECL pthread_win32_thread_attach_np(void); -PTW32_DLLPORT int PTW32_CDECL pthread_win32_thread_detach_np(void); - -/* - * Features that are auto-detected at load/run time. - */ -PTW32_DLLPORT int PTW32_CDECL pthread_win32_test_features_np(int); -enum ptw32_features { - PTW32_SYSTEM_INTERLOCKED_COMPARE_EXCHANGE = 0x0001, /* System provides it. */ - PTW32_ALERTABLE_ASYNC_CANCEL = 0x0002 /* Can cancel blocked threads. */ -}; - -/* - * Register a system time change with the library. - * Causes the library to perform various functions - * in response to the change. Should be called whenever - * the application's top level window receives a - * WM_TIMECHANGE message. It can be passed directly to - * pthread_create() as a new thread if desired. - */ -PTW32_DLLPORT void * PTW32_CDECL pthread_timechange_handler_np(void *); - -#endif /*PTW32_LEVEL >= PTW32_LEVEL_MAX - 1 */ - -#if PTW32_LEVEL >= PTW32_LEVEL_MAX - -/* - * Returns the Win32 HANDLE for the POSIX thread. - */ -PTW32_DLLPORT HANDLE PTW32_CDECL pthread_getw32threadhandle_np(pthread_t thread); -/* - * Returns the win32 thread ID for POSIX thread. - */ -PTW32_DLLPORT DWORD PTW32_CDECL pthread_getw32threadid_np (pthread_t thread); - - -/* - * Protected Methods - * - * This function blocks until the given WIN32 handle - * is signaled or pthread_cancel had been called. - * This function allows the caller to hook into the - * PThreads cancel mechanism. It is implemented using - * - * WaitForMultipleObjects - * - * on 'waitHandle' and a manually reset WIN32 Event - * used to implement pthread_cancel. The 'timeout' - * argument to TimedWait is simply passed to - * WaitForMultipleObjects. - */ -PTW32_DLLPORT int PTW32_CDECL pthreadCancelableWait (HANDLE waitHandle); -PTW32_DLLPORT int PTW32_CDECL pthreadCancelableTimedWait (HANDLE waitHandle, - DWORD timeout); - -#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ - -/* - * Thread-Safe C Runtime Library Mappings. - */ -#if !defined(_UWIN) -# if defined(NEED_ERRNO) - PTW32_DLLPORT int * PTW32_CDECL _errno( void ); -# else -# if !defined(errno) -# if (defined(_MT) || defined(_DLL)) - __declspec(dllimport) extern int * __cdecl _errno(void); -# define errno (*_errno()) -# endif -# endif -# endif -#endif - -/* - * Some compiler environments don't define some things. - */ -#if defined(__BORLANDC__) -# define _ftime ftime -# define _timeb timeb -#endif - -#if defined(__cplusplus) - -/* - * Internal exceptions - */ -class ptw32_exception {}; -class ptw32_exception_cancel : public ptw32_exception {}; -class ptw32_exception_exit : public ptw32_exception {}; - -#endif - -#if PTW32_LEVEL >= PTW32_LEVEL_MAX - -/* FIXME: This is only required if the library was built using SEH */ -/* - * Get internal SEH tag - */ -PTW32_DLLPORT DWORD PTW32_CDECL ptw32_get_exception_services_code(void); - -#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ - -#if !defined(PTW32_BUILD) - -#if defined(__CLEANUP_SEH) - -/* - * Redefine the SEH __except keyword to ensure that applications - * propagate our internal exceptions up to the library's internal handlers. - */ -#define __except( E ) \ - __except( ( GetExceptionCode() == ptw32_get_exception_services_code() ) \ - ? EXCEPTION_CONTINUE_SEARCH : ( E ) ) - -#endif /* __CLEANUP_SEH */ - -#if defined(__CLEANUP_CXX) - -/* - * Redefine the C++ catch keyword to ensure that applications - * propagate our internal exceptions up to the library's internal handlers. - */ -#if defined(_MSC_VER) - /* - * WARNING: Replace any 'catch( ... )' with 'PtW32CatchAll' - * if you want Pthread-Win32 cancelation and pthread_exit to work. - */ - -#if !defined(PtW32NoCatchWarn) - -#pragma message("Specify \"/DPtW32NoCatchWarn\" compiler flag to skip this message.") -#pragma message("------------------------------------------------------------------") -#pragma message("When compiling applications with MSVC++ and C++ exception handling:") -#pragma message(" Replace any 'catch( ... )' in routines called from POSIX threads") -#pragma message(" with 'PtW32CatchAll' or 'CATCHALL' if you want POSIX thread") -#pragma message(" cancelation and pthread_exit to work. For example:") -#pragma message("") -#pragma message(" #if defined(PtW32CatchAll)") -#pragma message(" PtW32CatchAll") -#pragma message(" #else") -#pragma message(" catch(...)") -#pragma message(" #endif") -#pragma message(" {") -#pragma message(" /* Catchall block processing */") -#pragma message(" }") -#pragma message("------------------------------------------------------------------") - -#endif - -#define PtW32CatchAll \ - catch( ptw32_exception & ) { throw; } \ - catch( ... ) - -#else /* _MSC_VER */ - -#define catch( E ) \ - catch( ptw32_exception & ) { throw; } \ - catch( E ) - -#endif /* _MSC_VER */ - -#endif /* __CLEANUP_CXX */ - -#endif /* ! PTW32_BUILD */ - -#if defined(__cplusplus) -} /* End of extern "C" */ -#endif /* __cplusplus */ - -#if defined(PTW32__HANDLE_DEF) -# undef HANDLE -#endif -#if defined(PTW32__DWORD_DEF) -# undef DWORD -#endif - -#undef PTW32_LEVEL -#undef PTW32_LEVEL_MAX - -#endif /* ! RC_INVOKED */ - -#endif /* PTHREAD_H */ diff --git a/pthreads/sched.h b/pthreads/sched.h deleted file mode 100644 index f36a97a66..000000000 --- a/pthreads/sched.h +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Module: sched.h - * - * Purpose: - * Provides an implementation of POSIX realtime extensions - * as defined in - * - * POSIX 1003.1b-1993 (POSIX.1b) - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ -#if !defined(_SCHED_H) -#define _SCHED_H - -#undef PTW32_SCHED_LEVEL - -#if defined(_POSIX_SOURCE) -#define PTW32_SCHED_LEVEL 0 -/* Early POSIX */ -#endif - -#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309 -#undef PTW32_SCHED_LEVEL -#define PTW32_SCHED_LEVEL 1 -/* Include 1b, 1c and 1d */ -#endif - -#if defined(INCLUDE_NP) -#undef PTW32_SCHED_LEVEL -#define PTW32_SCHED_LEVEL 2 -/* Include Non-Portable extensions */ -#endif - -#define PTW32_SCHED_LEVEL_MAX 3 - -#if ( defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112 ) || !defined(PTW32_SCHED_LEVEL) -#define PTW32_SCHED_LEVEL PTW32_SCHED_LEVEL_MAX -/* Include everything */ -#endif - - -#if defined(__GNUC__) && !defined(__declspec) -# error Please upgrade your GNU compiler to one that supports __declspec. -#endif - -/* - * When building the library, you should define PTW32_BUILD so that - * the variables/functions are exported correctly. When using the library, - * do NOT define PTW32_BUILD, and then the variables/functions will - * be imported correctly. - */ -#if !defined(PTW32_STATIC_LIB) -# if defined(PTW32_BUILD) -# define PTW32_DLLPORT __declspec (dllexport) -# else -# define PTW32_DLLPORT __declspec (dllimport) -# endif -#else -# define PTW32_DLLPORT -#endif - -/* - * This is a duplicate of what is in the autoconf config.h, - * which is only used when building the pthread-win32 libraries. - */ - -#if !defined(PTW32_CONFIG_H) -# if defined(WINCE) -# define NEED_ERRNO -# define NEED_SEM -# endif -# if defined(__MINGW64__) -# define HAVE_STRUCT_TIMESPEC -# define HAVE_MODE_T -# elif defined(_UWIN) || defined(__MINGW32__) -# define HAVE_MODE_T -# endif -#endif - -/* - * - */ - -#if PTW32_SCHED_LEVEL >= PTW32_SCHED_LEVEL_MAX -#if defined(NEED_ERRNO) -#include "need_errno.h" -#else -#include -#endif -#endif /* PTW32_SCHED_LEVEL >= PTW32_SCHED_LEVEL_MAX */ - -#if (defined(__MINGW64__) || defined(__MINGW32__)) || defined(_UWIN) -# if PTW32_SCHED_LEVEL >= PTW32_SCHED_LEVEL_MAX -/* For pid_t */ -# include -/* Required by Unix 98 */ -# include -# else - typedef int pid_t; -# endif -#else - typedef int pid_t; -#endif - -/* Thread scheduling policies */ - -enum { - SCHED_OTHER = 0, - SCHED_FIFO, - SCHED_RR, - SCHED_MIN = SCHED_OTHER, - SCHED_MAX = SCHED_RR -}; - -struct sched_param { - int sched_priority; -}; - -#if defined(__cplusplus) -extern "C" -{ -#endif /* __cplusplus */ - -PTW32_DLLPORT int __cdecl sched_yield (void); - -PTW32_DLLPORT int __cdecl sched_get_priority_min (int policy); - -PTW32_DLLPORT int __cdecl sched_get_priority_max (int policy); - -PTW32_DLLPORT int __cdecl sched_setscheduler (pid_t pid, int policy); - -PTW32_DLLPORT int __cdecl sched_getscheduler (pid_t pid); - -/* - * Note that this macro returns ENOTSUP rather than - * ENOSYS as might be expected. However, returning ENOSYS - * should mean that sched_get_priority_{min,max} are - * not implemented as well as sched_rr_get_interval. - * This is not the case, since we just don't support - * round-robin scheduling. Therefore I have chosen to - * return the same value as sched_setscheduler when - * SCHED_RR is passed to it. - */ -#define sched_rr_get_interval(_pid, _interval) \ - ( errno = ENOTSUP, (int) -1 ) - - -#if defined(__cplusplus) -} /* End of extern "C" */ -#endif /* __cplusplus */ - -#undef PTW32_SCHED_LEVEL -#undef PTW32_SCHED_LEVEL_MAX - -#endif /* !_SCHED_H */ - diff --git a/pthreads/semaphore.h b/pthreads/semaphore.h deleted file mode 100644 index c6e9407e2..000000000 --- a/pthreads/semaphore.h +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Module: semaphore.h - * - * Purpose: - * Semaphores aren't actually part of the PThreads standard. - * They are defined by the POSIX Standard: - * - * POSIX 1003.1b-1993 (POSIX.1b) - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ -#if !defined( SEMAPHORE_H ) -#define SEMAPHORE_H - -#undef PTW32_SEMAPHORE_LEVEL - -#if defined(_POSIX_SOURCE) -#define PTW32_SEMAPHORE_LEVEL 0 -/* Early POSIX */ -#endif - -#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309 -#undef PTW32_SEMAPHORE_LEVEL -#define PTW32_SEMAPHORE_LEVEL 1 -/* Include 1b, 1c and 1d */ -#endif - -#if defined(INCLUDE_NP) -#undef PTW32_SEMAPHORE_LEVEL -#define PTW32_SEMAPHORE_LEVEL 2 -/* Include Non-Portable extensions */ -#endif - -#define PTW32_SEMAPHORE_LEVEL_MAX 3 - -#if !defined(PTW32_SEMAPHORE_LEVEL) -#define PTW32_SEMAPHORE_LEVEL PTW32_SEMAPHORE_LEVEL_MAX -/* Include everything */ -#endif - -#if defined(__GNUC__) && ! defined (__declspec) -# error Please upgrade your GNU compiler to one that supports __declspec. -#endif - -/* - * When building the library, you should define PTW32_BUILD so that - * the variables/functions are exported correctly. When using the library, - * do NOT define PTW32_BUILD, and then the variables/functions will - * be imported correctly. - */ -#if !defined(PTW32_STATIC_LIB) -# if defined(PTW32_BUILD) -# define PTW32_DLLPORT __declspec (dllexport) -# else -# define PTW32_DLLPORT __declspec (dllimport) -# endif -#else -# define PTW32_DLLPORT -#endif - -/* - * This is a duplicate of what is in the autoconf config.h, - * which is only used when building the pthread-win32 libraries. - */ - -#if !defined(PTW32_CONFIG_H) -# if defined(WINCE) -# define NEED_ERRNO -# define NEED_SEM -# endif -# if defined(__MINGW64__) -# define HAVE_STRUCT_TIMESPEC -# define HAVE_MODE_T -# elif defined(_UWIN) || defined(__MINGW32__) -# define HAVE_MODE_T -# endif -#endif - -/* - * - */ - -#if PTW32_SEMAPHORE_LEVEL >= PTW32_SEMAPHORE_LEVEL_MAX -#if defined(NEED_ERRNO) -#include "need_errno.h" -#else -#include -#endif -#endif /* PTW32_SEMAPHORE_LEVEL >= PTW32_SEMAPHORE_LEVEL_MAX */ - -#define _POSIX_SEMAPHORES - -#if defined(__cplusplus) -extern "C" -{ -#endif /* __cplusplus */ - -#if !defined(HAVE_MODE_T) -typedef unsigned int mode_t; -#endif - - -typedef struct sem_t_ * sem_t; - -PTW32_DLLPORT int __cdecl sem_init (sem_t * sem, - int pshared, - unsigned int value); - -PTW32_DLLPORT int __cdecl sem_destroy (sem_t * sem); - -PTW32_DLLPORT int __cdecl sem_trywait (sem_t * sem); - -PTW32_DLLPORT int __cdecl sem_wait (sem_t * sem); - -PTW32_DLLPORT int __cdecl sem_timedwait (sem_t * sem, - const struct timespec * abstime); - -PTW32_DLLPORT int __cdecl sem_post (sem_t * sem); - -PTW32_DLLPORT int __cdecl sem_post_multiple (sem_t * sem, - int count); - -PTW32_DLLPORT int __cdecl sem_open (const char * name, - int oflag, - mode_t mode, - unsigned int value); - -PTW32_DLLPORT int __cdecl sem_close (sem_t * sem); - -PTW32_DLLPORT int __cdecl sem_unlink (const char * name); - -PTW32_DLLPORT int __cdecl sem_getvalue (sem_t * sem, - int * sval); - -#if defined(__cplusplus) -} /* End of extern "C" */ -#endif /* __cplusplus */ - -#undef PTW32_SEMAPHORE_LEVEL -#undef PTW32_SEMAPHORE_LEVEL_MAX - -#endif /* !SEMAPHORE_H */ diff --git a/public_html/config.js b/public_html/config.js deleted file mode 100644 index f7d8e2eb1..000000000 --- a/public_html/config.js +++ /dev/null @@ -1,34 +0,0 @@ -// -------------------------------------------------------- -// -// This file is to configure the configurable settings. -// Load this file before script.js file at gmap.html. -// -// -------------------------------------------------------- - -// -- Output Settings ------------------------------------- -// Show metric values -Metric = false; // true or false - -// -- Map settings ---------------------------------------- -// The Latitude and Longitude in decimal format -CONST_CENTERLAT = 45.0; -CONST_CENTERLON = 9.0; -// The google maps zoom level, 0 - 16, lower is further out -CONST_ZOOMLVL = 5; - -// -- Marker settings ------------------------------------- -// The default marker color -MarkerColor = "rgb(127, 127, 127)"; -SelectedColor = "rgb(225, 225, 225)"; -StaleColor = "rgb(190, 190, 190)"; - -// -- Site Settings --------------------------------------- -SiteShow = false; // true or false -// The Latitude and Longitude in decimal format -SiteLat = 45.0; -SiteLon = 9.0; - -SiteCircles = true; // true or false (Only shown if SiteShow is true) -// In nautical miles or km (depending settings value 'Metric') -SiteCirclesDistances = new Array(100,150,200); - diff --git a/public_html/coolclock/coolclock.js b/public_html/coolclock/coolclock.js deleted file mode 100644 index 44119746d..000000000 --- a/public_html/coolclock/coolclock.js +++ /dev/null @@ -1,318 +0,0 @@ -/** - * CoolClock 2.1.4 - * Copyright 2010, Simon Baird - * Released under the BSD License. - * - * Display an analog clock using canvas. - * http://randomibis.com/coolclock/ - * - */ - -// Constructor for CoolClock objects -window.CoolClock = function(options) { - return this.init(options); -} - -// Config contains some defaults, and clock skins -CoolClock.config = { - tickDelay: 1000, - longTickDelay: 15000, - defaultRadius: 85, - renderRadius: 100, - defaultSkin: "chunkySwiss", - // Should be in skin probably... - // (TODO: allow skinning of digital display) - showSecs: true, - showAmPm: true, - - skins: { - // There are more skins in moreskins.js - // Try making your own skin by copy/pasting one of these and tweaking it - swissRail: { - outerBorder: { lineWidth: 2, radius:95, color: "black", alpha: 1 }, - smallIndicator: { lineWidth: 2, startAt: 88, endAt: 92, color: "black", alpha: 1 }, - largeIndicator: { lineWidth: 4, startAt: 79, endAt: 92, color: "black", alpha: 1 }, - hourHand: { lineWidth: 8, startAt: -15, endAt: 50, color: "black", alpha: 1 }, - minuteHand: { lineWidth: 7, startAt: -15, endAt: 75, color: "black", alpha: 1 }, - secondHand: { lineWidth: 1, startAt: -20, endAt: 85, color: "red", alpha: 1 }, - secondDecoration: { lineWidth: 1, startAt: 70, radius: 4, fillColor: "red", color: "red", alpha: 1 } - }, - chunkySwiss: { - outerBorder: { lineWidth: 4, radius:97, color: "black", alpha: 1 }, - smallIndicator: { lineWidth: 4, startAt: 89, endAt: 93, color: "black", alpha: 1 }, - largeIndicator: { lineWidth: 8, startAt: 80, endAt: 93, color: "black", alpha: 1 }, - hourHand: { lineWidth: 12, startAt: -15, endAt: 60, color: "black", alpha: 1 }, - minuteHand: { lineWidth: 10, startAt: -15, endAt: 85, color: "black", alpha: 1 }, - secondHand: { lineWidth: 4, startAt: -20, endAt: 85, color: "red", alpha: 1 }, - secondDecoration: { lineWidth: 2, startAt: 70, radius: 8, fillColor: "red", color: "red", alpha: 1 } - }, - chunkySwissOnBlack: { - outerBorder: { lineWidth: 4, radius:97, color: "white", alpha: 1 }, - smallIndicator: { lineWidth: 4, startAt: 89, endAt: 93, color: "white", alpha: 1 }, - largeIndicator: { lineWidth: 8, startAt: 80, endAt: 93, color: "white", alpha: 1 }, - hourHand: { lineWidth: 12, startAt: -15, endAt: 60, color: "white", alpha: 1 }, - minuteHand: { lineWidth: 10, startAt: -15, endAt: 85, color: "white", alpha: 1 }, - secondHand: { lineWidth: 4, startAt: -20, endAt: 85, color: "red", alpha: 1 }, - secondDecoration: { lineWidth: 2, startAt: 70, radius: 8, fillColor: "red", color: "red", alpha: 1 } - } - - }, - - // Test for IE so we can nurse excanvas in a couple of places - isIE: !!document.all, - - // Will store (a reference to) each clock here, indexed by the id of the canvas element - clockTracker: {}, - - // For giving a unique id to coolclock canvases with no id - noIdCount: 0 -}; - -// Define the CoolClock object's methods -CoolClock.prototype = { - - // Initialise using the parameters parsed from the colon delimited class - init: function(options) { - // Parse and store the options - this.canvasId = options.canvasId; - this.skinId = options.skinId || CoolClock.config.defaultSkin; - this.displayRadius = options.displayRadius || CoolClock.config.defaultRadius; - this.showSecondHand = typeof options.showSecondHand == "boolean" ? options.showSecondHand : true; - this.gmtOffset = (options.gmtOffset != null && options.gmtOffset != '') ? parseFloat(options.gmtOffset) : null; - this.showDigital = typeof options.showDigital == "boolean" ? options.showDigital : false; - this.logClock = typeof options.logClock == "boolean" ? options.logClock : false; - this.logClockRev = typeof options.logClock == "boolean" ? options.logClockRev : false; - - this.tickDelay = CoolClock.config[ this.showSecondHand ? "tickDelay" : "longTickDelay" ]; - - // Get the canvas element - this.canvas = document.getElementById(this.canvasId); - - // Make the canvas the requested size. It's always square. - this.canvas.setAttribute("width",this.displayRadius*2); - this.canvas.setAttribute("height",this.displayRadius*2); - this.canvas.style.width = this.displayRadius*2 + "px"; - this.canvas.style.height = this.displayRadius*2 + "px"; - - // Explain me please...? - this.renderRadius = CoolClock.config.renderRadius; - this.scale = this.displayRadius / this.renderRadius; - - // Initialise canvas context - this.ctx = this.canvas.getContext("2d"); - this.ctx.scale(this.scale,this.scale); - - // Keep track of this object - CoolClock.config.clockTracker[this.canvasId] = this; - - // Start the clock going - this.tick(); - - return this; - }, - - // Draw a circle at point x,y with params as defined in skin - fullCircleAt: function(x,y,skin) { - this.ctx.save(); - this.ctx.globalAlpha = skin.alpha; - this.ctx.lineWidth = skin.lineWidth; - - if (!CoolClock.config.isIE) { - this.ctx.beginPath(); - } - - if (CoolClock.config.isIE) { - // excanvas doesn't scale line width so we will do it here - this.ctx.lineWidth = this.ctx.lineWidth * this.scale; - } - - this.ctx.arc(x, y, skin.radius, 0, 2*Math.PI, false); - - if (CoolClock.config.isIE) { - // excanvas doesn't close the circle so let's fill in the tiny gap - this.ctx.arc(x, y, skin.radius, -0.1, 0.1, false); - } - - if (skin.fillColor) { - this.ctx.fillStyle = skin.fillColor - this.ctx.fill(); - } - else { - // XXX why not stroke and fill - this.ctx.strokeStyle = skin.color; - this.ctx.stroke(); - } - this.ctx.restore(); - }, - - // Draw some text centered vertically and horizontally - drawTextAt: function(theText,x,y) { - this.ctx.save(); - this.ctx.font = '15px sans-serif'; - var tSize = this.ctx.measureText(theText); - if (!tSize.height) tSize.height = 15; // no height in firefox.. :( - this.ctx.fillText(theText,x - tSize.width/2,y - tSize.height/2); - this.ctx.restore(); - }, - - lpad2: function(num) { - return (num < 10 ? '0' : '') + num; - }, - - tickAngle: function(second) { - // Log algorithm by David Bradshaw - var tweak = 3; // If it's lower the one second mark looks wrong (?) - if (this.logClock) { - return second == 0 ? 0 : (Math.log(second*tweak) / Math.log(60*tweak)); - } - else if (this.logClockRev) { - // Flip the seconds then flip the angle (trickiness) - second = (60 - second) % 60; - return 1.0 - (second == 0 ? 0 : (Math.log(second*tweak) / Math.log(60*tweak))); - } - else { - return second/60.0; - } - }, - - timeText: function(hour,min,sec) { - var c = CoolClock.config; - return '' + - (c.showAmPm ? ((hour%12)==0 ? 12 : (hour%12)) : hour) + ':' + - this.lpad2(min) + - (c.showSecs ? ':' + this.lpad2(sec) : '') + - (c.showAmPm ? (hour < 12 ? ' am' : ' pm') : '') - ; - }, - - // Draw a radial line by rotating then drawing a straight line - // Ha ha, I think I've accidentally used Taus, (see http://tauday.com/) - radialLineAtAngle: function(angleFraction,skin) { - this.ctx.save(); - this.ctx.translate(this.renderRadius,this.renderRadius); - this.ctx.rotate(Math.PI * (2.0 * angleFraction - 0.5)); - this.ctx.globalAlpha = skin.alpha; - this.ctx.strokeStyle = skin.color; - this.ctx.lineWidth = skin.lineWidth; - - if (CoolClock.config.isIE) - // excanvas doesn't scale line width so we will do it here - this.ctx.lineWidth = this.ctx.lineWidth * this.scale; - - if (skin.radius) { - this.fullCircleAt(skin.startAt,0,skin) - } - else { - this.ctx.beginPath(); - this.ctx.moveTo(skin.startAt,0) - this.ctx.lineTo(skin.endAt,0); - this.ctx.stroke(); - } - this.ctx.restore(); - }, - - render: function(hour,min,sec) { - // Get the skin - var skin = CoolClock.config.skins[this.skinId]; - if (!skin) skin = CoolClock.config.skins[CoolClock.config.defaultSkin]; - - // Clear - this.ctx.clearRect(0,0,this.renderRadius*2,this.renderRadius*2); - - // Draw the outer edge of the clock - if (skin.outerBorder) - this.fullCircleAt(this.renderRadius,this.renderRadius,skin.outerBorder); - - // Draw the tick marks. Every 5th one is a big one - for (var i=0;i<60;i++) { - (i%5) && skin.smallIndicator && this.radialLineAtAngle(this.tickAngle(i),skin.smallIndicator); - !(i%5) && skin.largeIndicator && this.radialLineAtAngle(this.tickAngle(i),skin.largeIndicator); - } - - // Write the time - if (this.showDigital) { - this.drawTextAt( - this.timeText(hour,min,sec), - this.renderRadius, - this.renderRadius+this.renderRadius/2 - ); - } - - // Draw the hands - if (skin.hourHand) - this.radialLineAtAngle(this.tickAngle(((hour%12)*5 + min/12.0)),skin.hourHand); - - if (skin.minuteHand) - this.radialLineAtAngle(this.tickAngle((min + sec/60.0)),skin.minuteHand); - - if (this.showSecondHand && skin.secondHand) - this.radialLineAtAngle(this.tickAngle(sec),skin.secondHand); - - // Second hand decoration doesn't render right in IE so lets turn it off - if (!CoolClock.config.isIE && this.showSecondHand && skin.secondDecoration) - this.radialLineAtAngle(this.tickAngle(sec),skin.secondDecoration); - }, - - // Check the time and display the clock - refreshDisplay: function() { - var now = new Date(); - if (this.gmtOffset != null) { - // Use GMT + gmtOffset - var offsetNow = new Date(now.valueOf() + (this.gmtOffset * 1000 * 60 * 60)); - this.render(offsetNow.getUTCHours(),offsetNow.getUTCMinutes(),offsetNow.getUTCSeconds()); - } - else { - // Use local time - this.render(now.getHours(),now.getMinutes(),now.getSeconds()); - } - }, - - // Set timeout to trigger a tick in the future - nextTick: function() { - setTimeout("CoolClock.config.clockTracker['"+this.canvasId+"'].tick()",this.tickDelay); - }, - - // Check the canvas element hasn't been removed - stillHere: function() { - return document.getElementById(this.canvasId) != null; - }, - - // Main tick handler. Refresh the clock then setup the next tick - tick: function() { - if (this.stillHere()) { - this.refreshDisplay() - this.nextTick(); - } - } -}; - -// Find all canvas elements that have the CoolClock class and turns them into clocks -CoolClock.findAndCreateClocks = function() { - // (Let's not use a jQuery selector here so it's easier to use frameworks other than jQuery) - var canvases = document.getElementsByTagName("canvas"); - for (var i=0;i -// If you do have jQuery and it's loaded already then we can do it right now -if (window.jQuery) jQuery(document).ready(CoolClock.findAndCreateClocks); diff --git a/public_html/coolclock/excanvas.js b/public_html/coolclock/excanvas.js deleted file mode 100644 index 3e1aedf80..000000000 --- a/public_html/coolclock/excanvas.js +++ /dev/null @@ -1,785 +0,0 @@ -// Copyright 2006 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - - -// Known Issues: -// -// * Patterns are not implemented. -// * Radial gradient are not implemented. The VML version of these look very -// different from the canvas one. -// * Clipping paths are not implemented. -// * Coordsize. The width and height attribute have higher priority than the -// width and height style values which isn't correct. -// * Painting mode isn't implemented. -// * Canvas width/height should is using content-box by default. IE in -// Quirks mode will draw the canvas using border-box. Either change your -// doctype to HTML5 -// (http://www.whatwg.org/specs/web-apps/current-work/#the-doctype) -// or use Box Sizing Behavior from WebFX -// (http://webfx.eae.net/dhtml/boxsizing/boxsizing.html) -// * Optimize. There is always room for speed improvements. - -// only add this code if we do not already have a canvas implementation -if (!window.CanvasRenderingContext2D) { - -(function () { - - // alias some functions to make (compiled) code shorter - var m = Math; - var mr = m.round; - var ms = m.sin; - var mc = m.cos; - - // this is used for sub pixel precision - var Z = 10; - var Z2 = Z / 2; - - var G_vmlCanvasManager_ = { - init: function (opt_doc) { - var doc = opt_doc || document; - if (/MSIE/.test(navigator.userAgent) && !window.opera) { - var self = this; - doc.attachEvent("onreadystatechange", function () { - self.init_(doc); - }); - } - }, - - init_: function (doc) { - if (doc.readyState == "complete") { - // create xmlns - if (!doc.namespaces["g_vml_"]) { - doc.namespaces.add("g_vml_", "urn:schemas-microsoft-com:vml"); - } - - // setup default css - var ss = doc.createStyleSheet(); - ss.cssText = "canvas{display:inline-block;overflow:hidden;" + - // default size is 300x150 in Gecko and Opera - "text-align:left;width:300px;height:150px}" + - "g_vml_\\:*{behavior:url(#default#VML)}"; - - // find all canvas elements - var els = doc.getElementsByTagName("canvas"); - for (var i = 0; i < els.length; i++) { - if (!els[i].getContext) { - this.initElement(els[i]); - } - } - } - }, - - fixElement_: function (el) { - // in IE before version 5.5 we would need to add HTML: to the tag name - // but we do not care about IE before version 6 - var outerHTML = el.outerHTML; - - var newEl = el.ownerDocument.createElement(outerHTML); - // if the tag is still open IE has created the children as siblings and - // it has also created a tag with the name "/FOO" - if (outerHTML.slice(-2) != "/>") { - var tagName = "/" + el.tagName; - var ns; - // remove content - while ((ns = el.nextSibling) && ns.tagName != tagName) { - ns.removeNode(); - } - // remove the incorrect closing tag - if (ns) { - ns.removeNode(); - } - } - el.parentNode.replaceChild(newEl, el); - return newEl; - }, - - /** - * Public initializes a canvas element so that it can be used as canvas - * element from now on. This is called automatically before the page is - * loaded but if you are creating elements using createElement you need to - * make sure this is called on the element. - * @param {HTMLElement} el The canvas element to initialize. - * @return {HTMLElement} the element that was created. - */ - initElement: function (el) { - el = this.fixElement_(el); - el.getContext = function () { - if (this.context_) { - return this.context_; - } - return this.context_ = new CanvasRenderingContext2D_(this); - }; - - // do not use inline function because that will leak memory - el.attachEvent('onpropertychange', onPropertyChange); - el.attachEvent('onresize', onResize); - - var attrs = el.attributes; - if (attrs.width && attrs.width.specified) { - // TODO: use runtimeStyle and coordsize - // el.getContext().setWidth_(attrs.width.nodeValue); - el.style.width = attrs.width.nodeValue + "px"; - } else { - el.width = el.clientWidth; - } - if (attrs.height && attrs.height.specified) { - // TODO: use runtimeStyle and coordsize - // el.getContext().setHeight_(attrs.height.nodeValue); - el.style.height = attrs.height.nodeValue + "px"; - } else { - el.height = el.clientHeight; - } - //el.getContext().setCoordsize_() - return el; - } - }; - - function onPropertyChange(e) { - var el = e.srcElement; - - switch (e.propertyName) { - case 'width': - el.style.width = el.attributes.width.nodeValue + "px"; - el.getContext().clearRect(); - break; - case 'height': - el.style.height = el.attributes.height.nodeValue + "px"; - el.getContext().clearRect(); - break; - } - } - - function onResize(e) { - var el = e.srcElement; - if (el.firstChild) { - el.firstChild.style.width = el.clientWidth + 'px'; - el.firstChild.style.height = el.clientHeight + 'px'; - } - } - - G_vmlCanvasManager_.init(); - - // precompute "00" to "FF" - var dec2hex = []; - for (var i = 0; i < 16; i++) { - for (var j = 0; j < 16; j++) { - dec2hex[i * 16 + j] = i.toString(16) + j.toString(16); - } - } - - function createMatrixIdentity() { - return [ - [1, 0, 0], - [0, 1, 0], - [0, 0, 1] - ]; - } - - function matrixMultiply(m1, m2) { - var result = createMatrixIdentity(); - - for (var x = 0; x < 3; x++) { - for (var y = 0; y < 3; y++) { - var sum = 0; - - for (var z = 0; z < 3; z++) { - sum += m1[x][z] * m2[z][y]; - } - - result[x][y] = sum; - } - } - return result; - } - - function copyState(o1, o2) { - o2.fillStyle = o1.fillStyle; - o2.lineCap = o1.lineCap; - o2.lineJoin = o1.lineJoin; - o2.lineWidth = o1.lineWidth; - o2.miterLimit = o1.miterLimit; - o2.shadowBlur = o1.shadowBlur; - o2.shadowColor = o1.shadowColor; - o2.shadowOffsetX = o1.shadowOffsetX; - o2.shadowOffsetY = o1.shadowOffsetY; - o2.strokeStyle = o1.strokeStyle; - o2.arcScaleX_ = o1.arcScaleX_; - o2.arcScaleY_ = o1.arcScaleY_; - } - - function processStyle(styleString) { - var str, alpha = 1; - - styleString = String(styleString); - if (styleString.substring(0, 3) == "rgb") { - var start = styleString.indexOf("(", 3); - var end = styleString.indexOf(")", start + 1); - var guts = styleString.substring(start + 1, end).split(","); - - str = "#"; - for (var i = 0; i < 3; i++) { - str += dec2hex[Number(guts[i])]; - } - - if ((guts.length == 4) && (styleString.substr(3, 1) == "a")) { - alpha = guts[3]; - } - } else { - str = styleString; - } - - return [str, alpha]; - } - - function processLineCap(lineCap) { - switch (lineCap) { - case "butt": - return "flat"; - case "round": - return "round"; - case "square": - default: - return "square"; - } - } - - /** - * This class implements CanvasRenderingContext2D interface as described by - * the WHATWG. - * @param {HTMLElement} surfaceElement The element that the 2D context should - * be associated with - */ - function CanvasRenderingContext2D_(surfaceElement) { - this.m_ = createMatrixIdentity(); - - this.mStack_ = []; - this.aStack_ = []; - this.currentPath_ = []; - - // Canvas context properties - this.strokeStyle = "#000"; - this.fillStyle = "#000"; - - this.lineWidth = 1; - this.lineJoin = "miter"; - this.lineCap = "butt"; - this.miterLimit = Z * 1; - this.globalAlpha = 1; - this.canvas = surfaceElement; - - var el = surfaceElement.ownerDocument.createElement('div'); - el.style.width = surfaceElement.clientWidth + 'px'; - el.style.height = surfaceElement.clientHeight + 'px'; - el.style.overflow = 'hidden'; - el.style.position = 'absolute'; - surfaceElement.appendChild(el); - - this.element_ = el; - this.arcScaleX_ = 1; - this.arcScaleY_ = 1; - }; - - var contextPrototype = CanvasRenderingContext2D_.prototype; - contextPrototype.clearRect = function() { - this.element_.innerHTML = ""; - this.currentPath_ = []; - }; - - contextPrototype.beginPath = function() { - // TODO: Branch current matrix so that save/restore has no effect - // as per safari docs. - - this.currentPath_ = []; - }; - - contextPrototype.moveTo = function(aX, aY) { - this.currentPath_.push({type: "moveTo", x: aX, y: aY}); - this.currentX_ = aX; - this.currentY_ = aY; - }; - - contextPrototype.lineTo = function(aX, aY) { - this.currentPath_.push({type: "lineTo", x: aX, y: aY}); - this.currentX_ = aX; - this.currentY_ = aY; - }; - - contextPrototype.bezierCurveTo = function(aCP1x, aCP1y, - aCP2x, aCP2y, - aX, aY) { - this.currentPath_.push({type: "bezierCurveTo", - cp1x: aCP1x, - cp1y: aCP1y, - cp2x: aCP2x, - cp2y: aCP2y, - x: aX, - y: aY}); - this.currentX_ = aX; - this.currentY_ = aY; - }; - - contextPrototype.quadraticCurveTo = function(aCPx, aCPy, aX, aY) { - // the following is lifted almost directly from - // http://developer.mozilla.org/en/docs/Canvas_tutorial:Drawing_shapes - var cp1x = this.currentX_ + 2.0 / 3.0 * (aCPx - this.currentX_); - var cp1y = this.currentY_ + 2.0 / 3.0 * (aCPy - this.currentY_); - var cp2x = cp1x + (aX - this.currentX_) / 3.0; - var cp2y = cp1y + (aY - this.currentY_) / 3.0; - this.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, aX, aY); - }; - - contextPrototype.arc = function(aX, aY, aRadius, - aStartAngle, aEndAngle, aClockwise) { - aRadius *= Z; - var arcType = aClockwise ? "at" : "wa"; - - var xStart = aX + (mc(aStartAngle) * aRadius) - Z2; - var yStart = aY + (ms(aStartAngle) * aRadius) - Z2; - - var xEnd = aX + (mc(aEndAngle) * aRadius) - Z2; - var yEnd = aY + (ms(aEndAngle) * aRadius) - Z2; - - // IE won't render arches drawn counter clockwise if xStart == xEnd. - if (xStart == xEnd && !aClockwise) { - xStart += 0.125; // Offset xStart by 1/80 of a pixel. Use something - // that can be represented in binary - } - - this.currentPath_.push({type: arcType, - x: aX, - y: aY, - radius: aRadius, - xStart: xStart, - yStart: yStart, - xEnd: xEnd, - yEnd: yEnd}); - - }; - - contextPrototype.rect = function(aX, aY, aWidth, aHeight) { - this.moveTo(aX, aY); - this.lineTo(aX + aWidth, aY); - this.lineTo(aX + aWidth, aY + aHeight); - this.lineTo(aX, aY + aHeight); - this.closePath(); - }; - - contextPrototype.strokeRect = function(aX, aY, aWidth, aHeight) { - // Will destroy any existing path (same as FF behaviour) - this.beginPath(); - this.moveTo(aX, aY); - this.lineTo(aX + aWidth, aY); - this.lineTo(aX + aWidth, aY + aHeight); - this.lineTo(aX, aY + aHeight); - this.closePath(); - this.stroke(); - }; - - contextPrototype.fillRect = function(aX, aY, aWidth, aHeight) { - // Will destroy any existing path (same as FF behaviour) - this.beginPath(); - this.moveTo(aX, aY); - this.lineTo(aX + aWidth, aY); - this.lineTo(aX + aWidth, aY + aHeight); - this.lineTo(aX, aY + aHeight); - this.closePath(); - this.fill(); - }; - - contextPrototype.createLinearGradient = function(aX0, aY0, aX1, aY1) { - var gradient = new CanvasGradient_("gradient"); - return gradient; - }; - - contextPrototype.createRadialGradient = function(aX0, aY0, - aR0, aX1, - aY1, aR1) { - var gradient = new CanvasGradient_("gradientradial"); - gradient.radius1_ = aR0; - gradient.radius2_ = aR1; - gradient.focus_.x = aX0; - gradient.focus_.y = aY0; - return gradient; - }; - - contextPrototype.drawImage = function (image, var_args) { - var dx, dy, dw, dh, sx, sy, sw, sh; - - // to find the original width we overide the width and height - var oldRuntimeWidth = image.runtimeStyle.width; - var oldRuntimeHeight = image.runtimeStyle.height; - image.runtimeStyle.width = 'auto'; - image.runtimeStyle.height = 'auto'; - - // get the original size - var w = image.width; - var h = image.height; - - // and remove overides - image.runtimeStyle.width = oldRuntimeWidth; - image.runtimeStyle.height = oldRuntimeHeight; - - if (arguments.length == 3) { - dx = arguments[1]; - dy = arguments[2]; - sx = sy = 0; - sw = dw = w; - sh = dh = h; - } else if (arguments.length == 5) { - dx = arguments[1]; - dy = arguments[2]; - dw = arguments[3]; - dh = arguments[4]; - sx = sy = 0; - sw = w; - sh = h; - } else if (arguments.length == 9) { - sx = arguments[1]; - sy = arguments[2]; - sw = arguments[3]; - sh = arguments[4]; - dx = arguments[5]; - dy = arguments[6]; - dw = arguments[7]; - dh = arguments[8]; - } else { - throw "Invalid number of arguments"; - } - - var d = this.getCoords_(dx, dy); - - var w2 = sw / 2; - var h2 = sh / 2; - - var vmlStr = []; - - var W = 10; - var H = 10; - - // For some reason that I've now forgotten, using divs didn't work - vmlStr.push(' ' , - '', - ''); - - this.element_.insertAdjacentHTML("BeforeEnd", - vmlStr.join("")); - }; - - contextPrototype.stroke = function(aFill) { - var lineStr = []; - var lineOpen = false; - var a = processStyle(aFill ? this.fillStyle : this.strokeStyle); - var color = a[0]; - var opacity = a[1] * this.globalAlpha; - - var W = 10; - var H = 10; - - lineStr.push(' max.x) { - max.x = c.x; - } - if (min.y == null || c.y < min.y) { - min.y = c.y; - } - if (max.y == null || c.y > max.y) { - max.y = c.y; - } - } - } - lineStr.push(' ">'); - - if (typeof this.fillStyle == "object") { - var focus = {x: "50%", y: "50%"}; - var width = (max.x - min.x); - var height = (max.y - min.y); - var dimension = (width > height) ? width : height; - - focus.x = mr((this.fillStyle.focus_.x / width) * 100 + 50) + "%"; - focus.y = mr((this.fillStyle.focus_.y / height) * 100 + 50) + "%"; - - var colors = []; - - // inside radius (%) - if (this.fillStyle.type_ == "gradientradial") { - var inside = (this.fillStyle.radius1_ / dimension * 100); - - // percentage that outside radius exceeds inside radius - var expansion = (this.fillStyle.radius2_ / dimension * 100) - inside; - } else { - var inside = 0; - var expansion = 100; - } - - var insidecolor = {offset: null, color: null}; - var outsidecolor = {offset: null, color: null}; - - // We need to sort 'colors' by percentage, from 0 > 100 otherwise ie - // won't interpret it correctly - this.fillStyle.colors_.sort(function (cs1, cs2) { - return cs1.offset - cs2.offset; - }); - - for (var i = 0; i < this.fillStyle.colors_.length; i++) { - var fs = this.fillStyle.colors_[i]; - - colors.push( (fs.offset * expansion) + inside, "% ", fs.color, ","); - - if (fs.offset > insidecolor.offset || insidecolor.offset == null) { - insidecolor.offset = fs.offset; - insidecolor.color = fs.color; - } - - if (fs.offset < outsidecolor.offset || outsidecolor.offset == null) { - outsidecolor.offset = fs.offset; - outsidecolor.color = fs.color; - } - } - colors.pop(); - - lineStr.push(''); - } else if (aFill) { - lineStr.push(''); - } else { - lineStr.push( - '' - ); - } - - lineStr.push(""); - - this.element_.insertAdjacentHTML("beforeEnd", lineStr.join("")); - - this.currentPath_ = []; - }; - - contextPrototype.fill = function() { - this.stroke(true); - } - - contextPrototype.closePath = function() { - this.currentPath_.push({type: "close"}); - }; - - /** - * @private - */ - contextPrototype.getCoords_ = function(aX, aY) { - return { - x: Z * (aX * this.m_[0][0] + aY * this.m_[1][0] + this.m_[2][0]) - Z2, - y: Z * (aX * this.m_[0][1] + aY * this.m_[1][1] + this.m_[2][1]) - Z2 - } - }; - - contextPrototype.save = function() { - var o = {}; - copyState(this, o); - this.aStack_.push(o); - this.mStack_.push(this.m_); - this.m_ = matrixMultiply(createMatrixIdentity(), this.m_); - }; - - contextPrototype.restore = function() { - copyState(this.aStack_.pop(), this); - this.m_ = this.mStack_.pop(); - }; - - contextPrototype.translate = function(aX, aY) { - var m1 = [ - [1, 0, 0], - [0, 1, 0], - [aX, aY, 1] - ]; - - this.m_ = matrixMultiply(m1, this.m_); - }; - - contextPrototype.rotate = function(aRot) { - var c = mc(aRot); - var s = ms(aRot); - - var m1 = [ - [c, s, 0], - [-s, c, 0], - [0, 0, 1] - ]; - - this.m_ = matrixMultiply(m1, this.m_); - }; - - contextPrototype.scale = function(aX, aY) { - this.arcScaleX_ *= aX; - this.arcScaleY_ *= aY; - var m1 = [ - [aX, 0, 0], - [0, aY, 0], - [0, 0, 1] - ]; - - this.m_ = matrixMultiply(m1, this.m_); - }; - - /******** STUBS ********/ - contextPrototype.clip = function() { - // TODO: Implement - }; - - contextPrototype.arcTo = function() { - // TODO: Implement - }; - - contextPrototype.createPattern = function() { - return new CanvasPattern_; - }; - - // Gradient / Pattern Stubs - function CanvasGradient_(aType) { - this.type_ = aType; - this.radius1_ = 0; - this.radius2_ = 0; - this.colors_ = []; - this.focus_ = {x: 0, y: 0}; - } - - CanvasGradient_.prototype.addColorStop = function(aOffset, aColor) { - aColor = processStyle(aColor); - this.colors_.push({offset: 1-aOffset, color: aColor}); - }; - - function CanvasPattern_() {} - - // set up externs - G_vmlCanvasManager = G_vmlCanvasManager_; - CanvasRenderingContext2D = CanvasRenderingContext2D_; - CanvasGradient = CanvasGradient_; - CanvasPattern = CanvasPattern_; - -})(); - -} // if diff --git a/public_html/coolclock/moreskins.js b/public_html/coolclock/moreskins.js deleted file mode 100644 index e31618117..000000000 --- a/public_html/coolclock/moreskins.js +++ /dev/null @@ -1,212 +0,0 @@ -CoolClock.config.skins = { - - swissRail: { - outerBorder: { lineWidth: 2, radius: 95, color: "black", alpha: 1 }, - smallIndicator: { lineWidth: 2, startAt: 88, endAt: 92, color: "black", alpha: 1 }, - largeIndicator: { lineWidth: 4, startAt: 79, endAt: 92, color: "black", alpha: 1 }, - hourHand: { lineWidth: 8, startAt: -15, endAt: 50, color: "black", alpha: 1 }, - minuteHand: { lineWidth: 7, startAt: -15, endAt: 75, color: "black", alpha: 1 }, - secondHand: { lineWidth: 1, startAt: -20, endAt: 85, color: "red", alpha: 1 }, - secondDecoration: { lineWidth: 1, startAt: 70, radius: 4, fillColor: "red", color: "red", alpha: 1 } - }, - - chunkySwiss: { - outerBorder: { lineWidth: 4, radius: 97, color: "black", alpha: 1 }, - smallIndicator: { lineWidth: 4, startAt: 89, endAt: 93, color: "black", alpha: 1 }, - largeIndicator: { lineWidth: 8, startAt: 80, endAt: 93, color: "black", alpha: 1 }, - hourHand: { lineWidth: 12, startAt: -15, endAt: 60, color: "black", alpha: 1 }, - minuteHand: { lineWidth: 10, startAt: -15, endAt: 85, color: "black", alpha: 1 }, - secondHand: { lineWidth: 4, startAt: -20, endAt: 85, color: "red", alpha: 1 }, - secondDecoration: { lineWidth: 2, startAt: 70, radius: 8, fillColor: "red", color: "red", alpha: 1 } - }, - - chunkySwissOnBlack: { - outerBorder: { lineWidth: 4, radius: 97, color: "white", alpha: 1 }, - smallIndicator: { lineWidth: 4, startAt: 89, endAt: 93, color: "white", alpha: 1 }, - largeIndicator: { lineWidth: 8, startAt: 80, endAt: 93, color: "white", alpha: 1 }, - hourHand: { lineWidth: 12, startAt: -15, endAt: 60, color: "white", alpha: 1 }, - minuteHand: { lineWidth: 10, startAt: -15, endAt: 85, color: "white", alpha: 1 }, - secondHand: { lineWidth: 4, startAt: -20, endAt: 85, color: "red", alpha: 1 }, - secondDecoration: { lineWidth: 2, startAt: 70, radius: 8, fillColor: "red", color: "red", alpha: 1 } - }, - - fancy: { - outerBorder: { lineWidth: 5, radius: 95, color: "green", alpha: 0.7 }, - smallIndicator: { lineWidth: 1, startAt: 80, endAt: 93, color: "black", alpha: 0.4 }, - largeIndicator: { lineWidth: 1, startAt: 30, endAt: 93, color: "black", alpha: 0.5 }, - hourHand: { lineWidth: 8, startAt: -15, endAt: 50, color: "blue", alpha: 0.7 }, - minuteHand: { lineWidth: 7, startAt: -15, endAt: 92, color: "red", alpha: 0.7 }, - secondHand: { lineWidth: 10, startAt: 80, endAt: 85, color: "blue", alpha: 0.3 }, - secondDecoration: { lineWidth: 1, startAt: 30, radius: 50, fillColor: "blue", color: "red", alpha: 0.15 } - }, - - machine: { - outerBorder: { lineWidth: 60, radius: 55, color: "#dd6655", alpha: 1 }, - smallIndicator: { lineWidth: 4, startAt: 80, endAt: 95, color: "white", alpha: 1 }, - largeIndicator: { lineWidth: 14, startAt: 77, endAt: 92, color: "#dd6655", alpha: 1 }, - hourHand: { lineWidth: 18, startAt: -15, endAt: 40, color: "white", alpha: 1 }, - minuteHand: { lineWidth: 14, startAt: 24, endAt: 100, color: "#771100", alpha: 0.5 }, - secondHand: { lineWidth: 3, startAt: 22, endAt: 83, color: "green", alpha: 0 }, - secondDecoration: { lineWidth: 1, startAt: 52, radius: 26, fillColor: "#ffcccc", color: "red", alpha: 0.5 } - }, - - simonbaird_com: { - hourHand: { lineWidth: 80, startAt: -15, endAt: 35, color: 'magenta', alpha: 0.5 }, - minuteHand: { lineWidth: 80, startAt: -15, endAt: 65, color: 'cyan', alpha: 0.5 }, - secondDecoration: { lineWidth: 1, startAt: 40, radius: 40, color: "#fff", fillColor: 'yellow', alpha: 0.5 } - }, - - // by bonstio, http://bonstio.net - classic/*was gIG*/: { - outerBorder: { lineWidth: 185, radius: 1, color: "#E5ECF9", alpha: 1 }, - smallIndicator: { lineWidth: 2, startAt: 89, endAt: 94, color: "#3366CC", alpha: 1 }, - largeIndicator: { lineWidth: 4, startAt: 83, endAt: 94, color: "#3366CC", alpha: 1 }, - hourHand: { lineWidth: 5, startAt: 0, endAt: 60, color: "black", alpha: 1 }, - minuteHand: { lineWidth: 4, startAt: 0, endAt: 80, color: "black", alpha: 1 }, - secondHand: { lineWidth: 1, startAt: -20, endAt: 85, color: "red", alpha: .85 }, - secondDecoration: { lineWidth: 3, startAt: 0, radius: 2, fillColor: "black", color: "black", alpha: 1 } - }, - - modern/*was gIG2*/: { - outerBorder: { lineWidth: 185, radius: 1, color: "#E5ECF9", alpha: 1 }, - smallIndicator: { lineWidth: 5, startAt: 88, endAt: 94, color: "#3366CC", alpha: 1 }, - largeIndicator: { lineWidth: 5, startAt: 88, endAt: 94, color: "#3366CC", alpha: 1 }, - hourHand: { lineWidth: 8, startAt: 0, endAt: 60, color: "black", alpha: 1 }, - minuteHand: { lineWidth: 8, startAt: 0, endAt: 80, color: "black", alpha: 1 }, - secondHand: { lineWidth: 5, startAt: 80, endAt: 85, color: "red", alpha: .85 }, - secondDecoration: { lineWidth: 3, startAt: 0, radius: 4, fillColor: "black", color: "black", alpha: 1 } - }, - - simple/*was gIG3*/: { - outerBorder: { lineWidth: 185, radius: 1, color: "#E5ECF9", alpha: 1 }, - smallIndicator: { lineWidth: 10, startAt: 90, endAt: 94, color: "#3366CC", alpha: 1 }, - largeIndicator: { lineWidth: 10, startAt: 90, endAt: 94, color: "#3366CC", alpha: 1 }, - hourHand: { lineWidth: 8, startAt: 0, endAt: 60, color: "black", alpha: 1 }, - minuteHand: { lineWidth: 8, startAt: 0, endAt: 80, color: "black", alpha: 1 }, - secondHand: { lineWidth: 5, startAt: 80, endAt: 85, color: "red", alpha: .85 }, - secondDecoration: { lineWidth: 3, startAt: 0, radius: 4, fillColor: "black", color: "black", alpha: 1 } - }, - - // by securephp - securephp: { - outerBorder: { lineWidth: 100, radius: 0.45, color: "#669900", alpha: 0.3 }, - smallIndicator: { lineWidth: 2, startAt: 80, endAt: 90 , color: "green", alpha: 1 }, - largeIndicator: { lineWidth: 8.5, startAt: 20, endAt: 40 , color: "green", alpha: 0.4 }, - hourHand: { lineWidth: 3, startAt: 0, endAt: 60, color: "black", alpha: 1 }, - minuteHand: { lineWidth: 2, startAt: 0, endAt: 75, color: "black", alpha: 1 }, - secondHand: { lineWidth: 1, startAt: -10, endAt: 80, color: "blue", alpha: 0.8 }, - secondDecoration: { lineWidth: 1, startAt: 70, radius: 4, fillColor: "blue", color: "red", alpha: 1 } - }, - - Tes2: { - outerBorder: { lineWidth: 4, radius: 95, color: "black", alpha: 0.5 }, - smallIndicator: { lineWidth: 1, startAt: 10, endAt: 50 , color: "#66CCFF", alpha: 1 }, - largeIndicator: { lineWidth: 8.5, startAt: 60, endAt: 70, color: "#6699FF", alpha: 1 }, - hourHand: { lineWidth: 5, startAt: -15, endAt: 60, color: "black", alpha: 0.7 }, - minuteHand: { lineWidth: 3, startAt: -25, endAt: 75, color: "black", alpha: 0.7 }, - secondHand: { lineWidth: 1.5, startAt: -20, endAt: 88, color: "red", alpha: 1 }, - secondDecoration: { lineWidth: 1, startAt: 20, radius: 4, fillColor: "blue", color: "red", alpha: 1 } - }, - - - Lev: { - outerBorder: { lineWidth: 10, radius: 95, color: "#CCFF33", alpha: 0.65 }, - smallIndicator: { lineWidth: 5, startAt: 84, endAt: 90, color: "#996600", alpha: 1 }, - largeIndicator: { lineWidth: 40, startAt: 25, endAt: 95, color: "#336600", alpha: 0.55 }, - hourHand: { lineWidth: 4, startAt: 0, endAt: 65, color: "black", alpha: 0.9 }, - minuteHand: { lineWidth: 3, startAt: 0, endAt: 80, color: "black", alpha: 0.85 }, - secondHand: { lineWidth: 1, startAt: 0, endAt: 85, color: "black", alpha: 1 }, - secondDecoration: { lineWidth: 2, startAt: 5, radius: 10, fillColor: "black", color: "black", alpha: 1 } - }, - - Sand: { - outerBorder: { lineWidth: 1, radius: 70, color: "black", alpha: 0.5 }, - smallIndicator: { lineWidth: 3, startAt: 50, endAt: 70, color: "#0066FF", alpha: 0.5 }, - largeIndicator: { lineWidth: 200, startAt: 80, endAt: 95, color: "#996600", alpha: 0.75 }, - hourHand: { lineWidth: 4, startAt: 0, endAt: 65, color: "black", alpha: 0.9 }, - minuteHand: { lineWidth: 3, startAt: 0, endAt: 80, color: "black", alpha: 0.85 }, - secondHand: { lineWidth: 1, startAt: 0, endAt: 85, color: "black", alpha: 1 }, - secondDecoration: { lineWidth: 2, startAt: 5, radius: 10, fillColor: "black", color: "black", alpha: 1 } - }, - - Sun: { - outerBorder: { lineWidth: 100, radius: 140, color: "#99FFFF", alpha: 0.2 }, - smallIndicator: { lineWidth: 300, startAt: 50, endAt: 70, color: "black", alpha: 0.1 }, - largeIndicator: { lineWidth: 5, startAt: 80, endAt: 95, color: "black", alpha: 0.65 }, - hourHand: { lineWidth: 4, startAt: 0, endAt: 65, color: "black", alpha: 0.9 }, - minuteHand: { lineWidth: 3, startAt: 0, endAt: 80, color: "black", alpha: 0.85 }, - secondHand: { lineWidth: 1, startAt: 0, endAt: 90, color: "black", alpha: 1 }, - secondDecoration: { lineWidth: 2, startAt: 5, radius: 10, fillColor: "black", color: "black", alpha: 1 } - }, - - Tor: { - outerBorder: { lineWidth: 10, radius: 88, color: "#996600", alpha: 0.9 }, - smallIndicator: { lineWidth: 6, startAt: -10, endAt: 73, color: "green", alpha: 0.3 }, - largeIndicator: { lineWidth: 6, startAt: 73, endAt: 100, color: "black", alpha: 0.65 }, - hourHand: { lineWidth: 4, startAt: 0, endAt: 65, color: "black", alpha: 1 }, - minuteHand: { lineWidth: 3, startAt: 0, endAt: 80, color: "black", alpha: 1 }, - secondHand: { lineWidth: 1, startAt: -73, endAt: 73, color: "black", alpha: 0.8 }, - secondDecoration: { lineWidth: 2, startAt: 5, radius: 10, fillColor: "black", color: "black", alpha: 1 } - }, - - Cold: { - outerBorder: { lineWidth: 15, radius: 90, color: "black", alpha: 0.3 }, - smallIndicator: { lineWidth: 15, startAt: -10, endAt: 95, color: "blue", alpha: 0.1 }, - largeIndicator: { lineWidth: 3, startAt: 80, endAt: 95, color: "blue", alpha: 0.65 }, - hourHand: { lineWidth: 4, startAt: 0, endAt: 65, color: "black", alpha: 1 }, - minuteHand: { lineWidth: 3, startAt: 0, endAt: 80, color: "black", alpha: 1 }, - secondHand: { lineWidth: 1, startAt: 0, endAt: 85, color: "black", alpha: 0.8 }, - secondDecoration: { lineWidth: 5, startAt: 30, radius: 10, fillColor: "black", color: "black", alpha: 1 } - }, - - Babosa: { - outerBorder: { lineWidth: 100, radius: 25, color: "blue", alpha: 0.25 }, - smallIndicator: { lineWidth: 3, startAt: 90, endAt: 95, color: "#3366CC", alpha: 1 }, - largeIndicator: { lineWidth: 4, startAt: 75, endAt: 95, color: "#3366CC", alpha: 1 }, - hourHand: { lineWidth: 4, startAt: 0, endAt: 60, color: "black", alpha: 1 }, - minuteHand: { lineWidth: 3, startAt: 0, endAt: 85, color: "black", alpha: 1 }, - secondHand: { lineWidth: 12, startAt: 75, endAt: 90, color: "red", alpha: 0.8 }, - secondDecoration: { lineWidth: 3, startAt: 0, radius: 4, fillColor: "black", color: "black", alpha: 1 } - }, - - Tumb: { - outerBorder: { lineWidth: 105, radius: 5, color: "green", alpha: 0.4 }, - smallIndicator: { lineWidth: 1, startAt: 93, endAt: 98, color: "green", alpha: 1 }, - largeIndicator: { lineWidth: 50, startAt: 0, endAt: 89, color: "red", alpha: 0.14 }, - hourHand: { lineWidth: 4, startAt: 0, endAt: 65, color: "black", alpha: 1 }, - minuteHand: { lineWidth: 3, startAt: 0, endAt: 80, color: "black", alpha: 1 }, - secondHand: { lineWidth: 1, startAt: 0, endAt: 85, color: "black", alpha: 0.8 }, - secondDecoration: { lineWidth: 5, startAt: 50, radius: 90, fillColor: "black", color: "black", alpha: 0.05 } - }, - - Stone: { - outerBorder: { lineWidth: 15, radius: 80, color: "#339933", alpha: 0.5 }, - smallIndicator: { lineWidth: 2, startAt: 70, endAt: 90, color: "#FF3300", alpha: 0.7 }, - largeIndicator: { lineWidth: 15, startAt: 0, endAt: 29, color: "#FF6600", alpha: 0.3 }, - hourHand: { lineWidth: 4, startAt: 0, endAt: 65, color: "black", alpha: 1 }, - minuteHand: { lineWidth: 3, startAt: 0, endAt: 75, color: "black", alpha: 1 }, - secondHand: { lineWidth: 1, startAt: 0, endAt: 85, color: "black", alpha: 0.8 }, - secondDecoration: { lineWidth: 5, startAt: 50, radius: 90, fillColor: "black", color: "black", alpha: 0.05 } - }, - - Disc: { - outerBorder: { lineWidth: 105, radius: 1, color: "#666600", alpha: 0.2 }, - smallIndicator: { lineWidth: 1, startAt: 58, endAt: 95, color: "#669900", alpha: 0.8 }, - largeIndicator: { lineWidth: 6, startAt: 25, endAt: 35, color: "#666600", alpha: 1 }, - hourHand: { lineWidth: 4, startAt: 0, endAt: 65, color: "black", alpha: 1 }, - minuteHand: { lineWidth: 3, startAt: 0, endAt: 75, color: "black", alpha: 1 }, - secondHand: { lineWidth: 1, startAt: -75, endAt: 75, color: "#99CC00", alpha: 0.8 }, - secondDecoration: { lineWidth: 5, startAt: 50, radius: 90, fillColor: "#00FF00", color: "green", alpha: 0.05 } - }, - - // By Yoo Nhe - watermelon: { - outerBorder: { lineWidth: 100, radius: 1.7, color: "#d93d04", alpha: 5 }, - smallIndicator: { lineWidth: 2, startAt: 50, endAt: 70, color: "#d93d04", alpha: 5 }, - largeIndicator: { lineWidth: 2, startAt: 45, endAt: 94, color: "#a9bf04", alpha: 1 }, - hourHand: { lineWidth: 5, startAt: -20, endAt: 80, color: "#8c0d17", alpha: 1 }, - minuteHand: { lineWidth: 2, startAt: -20, endAt: 80, color: "#7c8c03", alpha: .9 }, - secondHand: { lineWidth: 2, startAt: 70, endAt: 94, color: "#d93d04", alpha: .85 }, - secondDecoration: { lineWidth: 1, startAt: 70, radius: 3, fillColor: "red", color: "black", alpha: .7 } - } -}; diff --git a/public_html/extension.js b/public_html/extension.js deleted file mode 100644 index f71fe170c..000000000 --- a/public_html/extension.js +++ /dev/null @@ -1,19 +0,0 @@ -// ----------------------------------------------------- -// -// This file is so users can modify how the page acts -// without diving to deep in the code. This way we can -// also try out or hold custom code for ourselves and -// not check it into the repo. -// -// There is a div id'ed as plane_extension for use with -// this javascript file. -// ----------------------------------------------------- - -function extendedInitalize() { - // Write your initalization here - // Gets called just before the 1-sec function call loop is setup -} - -function extendedPulse() { - // This will get called every second after all the main functions -} diff --git a/public_html/gmap.html b/public_html/gmap.html deleted file mode 100644 index 9ab2dc28d..000000000 --- a/public_html/gmap.html +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - - - - - - - DUMP1090 - - - -
-
-
- -
- Squak 7x00 is reported and shown.
- This is most likely an error in reciving or decoding.
- Please do not call the local authorities, they already know about it if it is valid squak. -
-
- - diff --git a/public_html/options.js b/public_html/options.js deleted file mode 100644 index f4e3627d3..000000000 --- a/public_html/options.js +++ /dev/null @@ -1,17 +0,0 @@ -var listKMLType = ['Approch', 'Departure', 'Transit', 'Custom1', 'Custom2']; -var listKMLs = localStorage['listKMLs'] || []; - -function optionsInitalize() { - // Write your initalization here - // Gets called just before the 1-sec function call loop is setup - $( "#dialog-modal" ).dialog({ - height: 140, - modal: true, - autoOpen: false, - closeOnEscape: false - }); -} - -function optionsModal() { - $( "#dialog-modal" ).dialog( "open"); -} diff --git a/public_html/planeObject.js b/public_html/planeObject.js deleted file mode 100644 index 98153fd57..000000000 --- a/public_html/planeObject.js +++ /dev/null @@ -1,260 +0,0 @@ -var planeObject = { - oldlat : null, - oldlon : null, - oldalt : null, - - // Basic location information - altitude : null, - speed : null, - track : null, - latitude : null, - longitude : null, - - // Info about the plane - flight : null, - squawk : null, - icao : null, - is_selected : false, - - // Data packet numbers - messages : null, - seen : null, - - // Vaild... - vPosition : false, - vTrack : false, - - // GMap Details - marker : null, - markerColor : MarkerColor, - lines : [], - trackdata : new Array(), - trackline : new Array(), - - // When was this last updated? - updated : null, - reapable : false, - - // Appends data to the running track so we can get a visual tail on the plane - // Only useful for a long running browser session. - funcAddToTrack : function(){ - // TODO: Write this function out - this.trackdata.push([this.latitude, this.longitude, this.altitude, this.track, this.speed]); - this.trackline.push(new google.maps.LatLng(this.latitude, this.longitude)); - }, - - // This is to remove the line from the screen if we deselect the plane - funcClearLine : function() { - if (this.line) { - this.line.setMap(null); - this.line = null; - } - }, - - // Should create an icon for us to use on the map... - funcGetIcon : function() { - this.markerColor = MarkerColor; - // If this marker is selected we should make it lighter than the rest. - if (this.is_selected == true) { - this.markerColor = SelectedColor; - } - - // If we have not seen a recent update, change color - if (this.seen > 15) { - this.markerColor = StaleColor; - } - - // Plane marker - var baseSvg = { - planeData : "M 1.9565564,41.694305 C 1.7174505,40.497708 1.6419973,38.448747 " + - "1.8096508,37.70494 1.8936398,37.332056 2.0796653,36.88191 2.222907,36.70461 " + - "2.4497603,36.423844 4.087816,35.47248 14.917931,29.331528 l 12.434577," + - "-7.050718 -0.04295,-7.613412 c -0.03657,-6.4844888 -0.01164,-7.7625804 " + - "0.168134,-8.6194061 0.276129,-1.3160905 0.762276,-2.5869575 1.347875," + - "-3.5235502 l 0.472298,-0.7553719 1.083746,-0.6085497 c 1.194146,-0.67053522 " + - "1.399524,-0.71738842 2.146113,-0.48960552 1.077005,0.3285939 2.06344," + - "1.41299352 2.797602,3.07543322 0.462378,1.0469993 0.978731,2.7738408 " + - "1.047635,3.5036272 0.02421,0.2570284 0.06357,3.78334 0.08732,7.836246 0.02375," + - "4.052905 0.0658,7.409251 0.09345,7.458546 0.02764,0.04929 5.600384,3.561772 " + - "12.38386,7.805502 l 12.333598,7.715871 0.537584,0.959688 c 0.626485,1.118378 " + - "0.651686,1.311286 0.459287,3.516442 -0.175469,2.011604 -0.608966,2.863924 " + - "-1.590344,3.127136 -0.748529,0.200763 -1.293144,0.03637 -10.184829,-3.07436 " + - "C 48.007733,41.72562 44.793806,40.60197 43.35084,40.098045 l -2.623567," + - "-0.916227 -1.981212,-0.06614 c -1.089663,-0.03638 -1.985079,-0.05089 -1.989804," + - "-0.03225 -0.0052,0.01863 -0.02396,2.421278 -0.04267,5.339183 -0.0395,6.147742 " + - "-0.143635,7.215456 -0.862956,8.845475 l -0.300457,0.680872 2.91906,1.361455 " + - "c 2.929379,1.366269 3.714195,1.835385 4.04589,2.41841 0.368292,0.647353 " + - "0.594634,2.901439 0.395779,3.941627 -0.0705,0.368571 -0.106308,0.404853 " + - "-0.765159,0.773916 L 41.4545,62.83158 39.259237,62.80426 c -6.030106,-0.07507 " + - "-16.19508,-0.495041 -16.870991,-0.697033 -0.359409,-0.107405 -0.523792," + - "-0.227482 -0.741884,-0.541926 -0.250591,-0.361297 -0.28386,-0.522402 -0.315075," + - "-1.52589 -0.06327,-2.03378 0.23288,-3.033615 1.077963,-3.639283 0.307525," + - "-0.2204 4.818478,-2.133627 6.017853,-2.552345 0.247872,-0.08654 0.247455," + - "-0.102501 -0.01855,-0.711959 -0.330395,-0.756986 -0.708622,-2.221756 -0.832676," + - "-3.224748 -0.05031,-0.406952 -0.133825,-3.078805 -0.185533,-5.937448 -0.0517," + - "-2.858644 -0.145909,-5.208974 -0.209316,-5.222958 -0.06341,-0.01399 -0.974464," + - "-0.0493 -2.024551,-0.07845 L 23.247235,38.61921 18.831373,39.8906 C 4.9432155," + - "43.88916 4.2929558,44.057819 3.4954426,43.86823 2.7487826,43.690732 2.2007966," + - "42.916622 1.9565564,41.694305 z" - }; - - // If the squawk code is one of the international emergency codes, - // match the info window alert color. - if (this.squawk == 7500) { - this.markerColor = "rgb(255, 85, 85)"; - } - if (this.squawk == 7600) { - this.markerColor = "rgb(0, 255, 255)"; - } - if (this.squawk == 7700) { - this.markerColor = "rgb(255, 255, 0)"; - } - - // If we have not overwritten color by now, an extension still could but - // just keep on trucking. :) - - return { - strokeWeight: (this.is_selected ? 2 : 1), - path: "M 0,0 "+ baseSvg["planeData"], - scale: 0.4, - fillColor: this.markerColor, - fillOpacity: 0.9, - anchor: new google.maps.Point(32, 32), // Set anchor to middle of plane. - rotation: this.track - }; - }, - - // TODO: Trigger actions of a selecting a plane - funcSelectPlane : function(selectedPlane){ - selectPlaneByHex(this.icao); - }, - - // Update our data - funcUpdateData : function(data){ - // So we can find out if we moved - var oldlat = this.latitude; - var oldlon = this.longitude; - var oldalt = this.altitude; - - // Update all of our data - this.updated = new Date().getTime(); - this.altitude = data.altitude; - this.speed = data.speed; - this.track = data.track; - this.latitude = data.lat; - this.longitude = data.lon; - this.flight = data.flight; - this.squawk = data.squawk; - this.icao = data.hex; - this.messages = data.messages; - this.seen = data.seen; - - // If no packet in over 58 seconds, consider the plane reapable - // This way we can hold it, but not show it just in case the plane comes back - if (this.seen > 58) { - this.reapable = true; - if (this.marker) { - this.marker.setMap(null); - this.marker = null; - } - if (this.line) { - this.line.setMap(null); - this.line = null; - } - if (SelectedPlane == this.icao) { - if (this.is_selected) { - this.is_selected = false; - } - SelectedPlane = null; - } - } else { - if (this.reapable == true) { - } - this.reapable = false; - } - - // Is the position valid? - if ((data.validposition == 1) && (this.reapable == false)) { - this.vPosition = true; - - // Detech if the plane has moved - changeLat = false; - changeLon = false; - changeAlt = false; - if (oldlat != this.latitude) { - changeLat = true; - } - if (oldlon != this.longitude) { - changeLon = true; - } - if (oldalt != this.altitude) { - changeAlt = true; - } - // Right now we only care about lat/long, if alt is updated only, oh well - if ((changeLat == true) || (changeLon == true)) { - this.funcAddToTrack(); - if (this.is_selected) { - this.line = this.funcUpdateLines(); - } - } - this.marker = this.funcUpdateMarker(); - PlanesOnMap++; - } else { - this.vPosition = false; - } - - // Do we have a valid track for the plane? - if (data.validtrack == 1) - this.vTrack = true; - else - this.vTrack = false; - }, - - // Update our marker on the map - funcUpdateMarker: function() { - if (this.marker) { - this.marker.setPosition(new google.maps.LatLng(this.latitude, this.longitude)); - this.marker.setIcon(this.funcGetIcon()); - } else { - this.marker = new google.maps.Marker({ - position: new google.maps.LatLng(this.latitude, this.longitude), - map: GoogleMap, - icon: this.funcGetIcon(), - visable: true - }); - - // This is so we can match icao address - this.marker.icao = this.icao; - - // Trap clicks for this marker. - google.maps.event.addListener(this.marker, 'click', this.funcSelectPlane); - } - - // Setting the marker title - if (this.flight.length == 0) { - this.marker.setTitle(this.hex); - } else { - this.marker.setTitle(this.flight+' ('+this.icao+')'); - } - return this.marker; - }, - - // Update our planes tail line, - // TODO: Make this multi colored based on options - // altitude (default) or speed - funcUpdateLines: function() { - if (this.line) { - var path = this.line.getPath(); - path.push(new google.maps.LatLng(this.latitude, this.longitude)); - } else { - this.line = new google.maps.Polyline({ - strokeColor: '#000000', - strokeOpacity: 1.0, - strokeWeight: 3, - map: GoogleMap, - path: this.trackline - }); - } - return this.line; - } -}; diff --git a/public_html/script.js b/public_html/script.js deleted file mode 100644 index 8212e5026..000000000 --- a/public_html/script.js +++ /dev/null @@ -1,658 +0,0 @@ -// Define our global variables -var GoogleMap = null; -var Planes = {}; -var PlanesOnMap = 0; -var PlanesOnTable = 0; -var PlanesToReap = 0; -var SelectedPlane = null; -var SpecialSquawk = false; - -var iSortCol=-1; -var bSortASC=true; -var bDefaultSortASC=true; -var iDefaultSortCol=3; - -// Get current map settings -CenterLat = Number(localStorage['CenterLat']) || CONST_CENTERLAT; -CenterLon = Number(localStorage['CenterLon']) || CONST_CENTERLON; -ZoomLvl = Number(localStorage['ZoomLvl']) || CONST_ZOOMLVL; - -function fetchData() { - $.getJSON('/dump1090/data.json', function(data) { - PlanesOnMap = 0 - SpecialSquawk = false; - - // Loop through all the planes in the data packet - for (var j=0; j < data.length; j++) { - // Do we already have this plane object in Planes? - // If not make it. - if (Planes[data[j].hex]) { - var plane = Planes[data[j].hex]; - } else { - var plane = jQuery.extend(true, {}, planeObject); - } - - /* For special squawk tests - if (data[j].hex == '48413x') { - data[j].squawk = '7700'; - } //*/ - - // Set SpecialSquawk-value - if (data[j].squawk == '7500' || data[j].squawk == '7600' || data[j].squawk == '7700') { - SpecialSquawk = true; - } - - // Call the function update - plane.funcUpdateData(data[j]); - - // Copy the plane into Planes - Planes[plane.icao] = plane; - } - - PlanesOnTable = data.length; - }); -} - -// Initalizes the map and starts up our timers to call various functions -function initialize() { - // Make a list of all the available map IDs - var mapTypeIds = []; - for(var type in google.maps.MapTypeId) { - mapTypeIds.push(google.maps.MapTypeId[type]); - } - // Push OSM on to the end - mapTypeIds.push("OSM"); - mapTypeIds.push("dark_map"); - - // Styled Map to outline airports and highways - var styles = [ - { - "featureType": "administrative", - "stylers": [ - { "visibility": "off" } - ] - },{ - "featureType": "landscape", - "stylers": [ - { "visibility": "off" } - ] - },{ - "featureType": "poi", - "stylers": [ - { "visibility": "off" } - ] - },{ - "featureType": "road", - "stylers": [ - { "visibility": "off" } - ] - },{ - "featureType": "transit", - "stylers": [ - { "visibility": "off" } - ] - },{ - "featureType": "landscape", - "stylers": [ - { "visibility": "on" }, - { "weight": 8 }, - { "color": "#000000" } - ] - },{ - "featureType": "water", - "stylers": [ - { "lightness": -74 } - ] - },{ - "featureType": "transit.station.airport", - "stylers": [ - { "visibility": "on" }, - { "weight": 8 }, - { "invert_lightness": true }, - { "lightness": 27 } - ] - },{ - "featureType": "road.highway", - "stylers": [ - { "visibility": "simplified" }, - { "invert_lightness": true }, - { "gamma": 0.3 } - ] - },{ - "featureType": "road", - "elementType": "labels", - "stylers": [ - { "visibility": "off" } - ] - } - ] - - // Add our styled map - var styledMap = new google.maps.StyledMapType(styles, {name: "Dark Map"}); - - // Define the Google Map - var mapOptions = { - center: new google.maps.LatLng(CenterLat, CenterLon), - zoom: ZoomLvl, - mapTypeId: google.maps.MapTypeId.ROADMAP, - mapTypeControl: true, - streetViewControl: false, - mapTypeControlOptions: { - mapTypeIds: mapTypeIds, - position: google.maps.ControlPosition.TOP_LEFT, - style: google.maps.MapTypeControlStyle.DROPDOWN_MENU - } - }; - - GoogleMap = new google.maps.Map(document.getElementById("map_canvas"), mapOptions); - - //Define OSM map type pointing at the OpenStreetMap tile server - GoogleMap.mapTypes.set("OSM", new google.maps.ImageMapType({ - getTileUrl: function(coord, zoom) { - return "http://tile.openstreetmap.org/" + zoom + "/" + coord.x + "/" + coord.y + ".png"; - }, - tileSize: new google.maps.Size(256, 256), - name: "OpenStreetMap", - maxZoom: 18 - })); - - GoogleMap.mapTypes.set("dark_map", styledMap); - - // Listeners for newly created Map - google.maps.event.addListener(GoogleMap, 'center_changed', function() { - localStorage['CenterLat'] = GoogleMap.getCenter().lat(); - localStorage['CenterLon'] = GoogleMap.getCenter().lng(); - }); - - google.maps.event.addListener(GoogleMap, 'zoom_changed', function() { - localStorage['ZoomLvl'] = GoogleMap.getZoom(); - }); - - // Add home marker if requested - if (SiteShow && (typeof SiteLat !== 'undefined' || typeof SiteLon !== 'undefined')) { - var siteMarker = new google.maps.LatLng(SiteLat, SiteLon); - var markerImage = new google.maps.MarkerImage( - 'http://maps.google.com/mapfiles/kml/pal4/icon57.png', - new google.maps.Size(32, 32), // Image size - new google.maps.Point(0, 0), // Origin point of image - new google.maps.Point(16, 16)); // Position where marker should point - var marker = new google.maps.Marker({ - position: siteMarker, - map: GoogleMap, - icon: markerImage, - title: 'My Radar Site', - zIndex: -99999 - }); - - if (SiteCircles) { - for (var i=0;i