static int testCPRRelative() { int ok = 1; unsigned i; for (i = 0; i < sizeof(cprRelativeTests)/sizeof(cprRelativeTests[0]); ++i) { double rlat = 0, rlon = 0; int res; res = decodeCPRrelative(cprRelativeTests[i].reflat, cprRelativeTests[i].reflon, cprRelativeTests[i].cprlat, cprRelativeTests[i].cprlon, cprRelativeTests[i].fflag, cprRelativeTests[i].surface, &rlat, &rlon); if (res != cprRelativeTests[i].result || fabs(rlat - cprRelativeTests[i].rlat) > 1e-6 || fabs(rlon - cprRelativeTests[i].rlon) > 1e-6) { ok = 0; fprintf(stderr, "testCPRRelative[%d]: FAIL: decodeCPRrelative(%.6f,%.6f,%d,%d,%d,%d) failed:\n" " result %d (expected %d)\n" " lat %.6f (expected %.6f)\n" " lon %.6f (expected %.6f)\n", i, cprRelativeTests[i].reflat, cprRelativeTests[i].reflon, cprRelativeTests[i].cprlat, cprRelativeTests[i].cprlon, cprRelativeTests[i].fflag, cprRelativeTests[i].surface, res, cprRelativeTests[i].result, rlat, cprRelativeTests[i].rlat, rlon, cprRelativeTests[i].rlon); } else { fprintf(stderr, "testCPRRelative[%d]: PASS\n", i); } } return ok; }
// //========================================================================= // // 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) { 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 (((mm->bFlags | a->bFlags) & MODES_ACFLAGS_LLEITHER_VALID) == MODES_ACFLAGS_LLBOTH_VALID) { // If we now have both even and odd, decode the CPR // Try relative CPR first if (decodeCPRrelative(a, (mm->bFlags & MODES_ACFLAGS_LLODD_VALID), (mm->bFlags & MODES_ACFLAGS_AOG))) { // If relative CPR fails then try global if the two data are less than 10 seconds apart if (abs((int)(a->even_cprtime - a->odd_cprtime)) <= 10000) { decodeCPR(a, (mm->bFlags & MODES_ACFLAGS_LLODD_VALID), (mm->bFlags & MODES_ACFLAGS_AOG)); } } //If we sucessfully decoded, back copy the results to mm so that we can print them in list output if (a->bFlags & MODES_ACFLAGS_LATLON_VALID) { 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; } } a->fs = mm->fs; return (a); }