/* $Id: warner.c,v 1.5 1999/07/06 05:33:22 root Exp $ warner, speedometer, odometer and data logger for laptop Copyright (C) 1999 James Cameron (quozl@us.netrek.org) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef lint static char vcid[] = "$Id: warner.c,v 1.5 1999/07/06 05:33:22 root Exp $"; #endif /* lint */ #include #include #include #include #include #include #include #define MAXMARK 13 /* mark stack size */ main() { FILE *input, *calibrate, *output = NULL, *current; int fd, sample, was, c, wm, sound = 1; time_t now; struct tm *tm; int i; char *p, buffer[128]; /* buffer for data from sensor */ int ct, cd, ot, od, dt, dd; float mm, range, speed, previous; struct termios termios; struct mark { int entering; float range; int ct, cd; char name[128]; } mark[MAXMARK]; for(i=0;itm_hour, tm->tm_min, tm->tm_sec ); clrtoeol ( ); if ( output != NULL ) fprintf ( output, "\n\n" ); ot = -1; od = -1; continue; } /* ignore any empty lines from sensor */ if ( strlen(p) < 8 ) continue; /* perform conversion from decimal */ sscanf ( p, "%d %d", &ct, &cd ); /* avoid calculation if no data yet, need two data points to proceed */ if ( ot == -1 ) { ot = ct; od = cd; continue; } /* calculate offsets, delta time, delta distance */ dt = ct - ot; dd = cd - od; /* remember old numbers for next time */ ot = ct; od = cd; /* sanity check, if time or distance goes down, reset */ if ( dt < 0 ) { mvprintw ( 23, 0, "%02d:%02d:%02d insane delta time %d", tm->tm_hour, tm->tm_min, tm->tm_sec, dt ); clrtoeol ( ); continue; } if ( dd < 0 ) { mvprintw ( 23, 0, "%02d:%02d:%02d insane delta distance %d", tm->tm_hour, tm->tm_min, tm->tm_sec, dd ); clrtoeol ( ); continue; } /* check for new calibration constant */ #ifdef notdef calibrate = fopen ( "calibrate.dat", "r" ); if ( calibrate != NULL ) { fscanf ( calibrate, "%f", &mm ); mvprintw ( 23, 0, "%02d:%02d:%02d recalibrate to %f mm/pulse", tm->tm_hour, tm->tm_min, tm->tm_sec, mm ); clrtoeol ( ); fclose ( calibrate ); remove ( "calibrate.dat" ); } #endif /* calculate speed (mm/ms -> km/h) */ speed = (float) dd * mm / dt * 3.6; /* suppress low speed data */ if ( speed < 3.0 ) { if ( output != NULL ) { fprintf ( output, "\n" ); } mvprintw ( 23, 0, "%02d:%02d:%02d below threshold (%3.1f km/h)", tm->tm_hour, tm->tm_min, tm->tm_sec, speed ); clrtoeol ( ); continue; } /* ignore clearly bogus data */ if ( speed > 200.0 ) { mvprintw ( 23, 0, "%02d:%02d:%02d bogus speed (%f km/h)", tm->tm_hour, tm->tm_min, tm->tm_sec, speed ); clrtoeol ( ); continue; } /* calculate odometer reading */ range = (float) ( cd * mm / 1000000 ); /* if keyboard used, process it */ c = getch ( ); while ( c != ERR ) { switch ( c ) { case '\f': redrawwin(stdscr); break; case KEY_PPAGE: sound = 0; mvprintw ( 23, 0, "Speed warning sounds : off" ); clrtoeol ( ); break; case KEY_NPAGE: sound = 1; mvprintw ( 23, 0, "Speed warning sounds : ON" ); clrtoeol ( ); break; case KEY_DC: mark[wm].range = 0.0; mark[wm].name[0] = '\0'; mark[wm].entering = 0; move ( 10, 0 ); clrtoeol ( ); move ( 12, 0 ); clrtoeol ( ); move ( 13, 0 ); clrtoeol ( ); move ( 14, 0 ); clrtoeol ( ); move ( 15, 0 ); clrtoeol ( ); move ( 16, 0 ); clrtoeol ( ); mvprintw ( 23, 0, "Mark F%d deleted.", wm ); clrtoeol ( ); break; case KEY_F(1): case KEY_F(2): case KEY_F(3): case KEY_F(4): case KEY_F(5): case KEY_F(6): case KEY_F(7): case KEY_F(8): case KEY_F(9): case KEY_F(10): case KEY_F(11): case KEY_F(12): wm = c - KEY_F0; if ( mark[wm].range == 0.0 ) { move ( 10, 21 ); clrtoeol ( ); } else { mvprintw ( 10, 21, "Mark = %7.3f km", mark[wm].range ); } move ( 12, 0 ); clrtoeol ( ); move ( 13, 0 ); clrtoeol ( ); move ( 14, 0 ); clrtoeol ( ); move ( 15, 0 ); clrtoeol ( ); move ( 16, 0 ); clrtoeol ( ); mvprintw ( 23, 0, "Mark F%d.", wm ); clrtoeol ( ); break; case KEY_IC: case '\n': case '\r': case '\\': case 0x09: fprintf ( output, "mark\t%7.3f\t%d\t%d\t%s\n", mark[wm].range, mark[wm].ct, mark[wm].cd, mark[wm].name ); mark[wm].entering = 0; mvprintw ( 23, 0, "Mark F%d recorded to log.", wm ); clrtoeol ( ); break; case KEY_BACKSPACE: case 0x08: case 0xff: case 0x7f: if ( strlen ( mark[wm].name ) > 0 ) { mark[wm].name[strlen(mark[wm].name)-1] = '\0'; } break; default: if ( ! mark[wm].entering ) { mark[wm].name[0] = '\0'; mark[wm].range = range; mark[wm].ct = ct; mark[wm].cd = cd; mvprintw ( 10, 21, "Mark = %7.3f km", range ); move ( 12, 0 ); clrtoeol ( ); move ( 13, 0 ); clrtoeol ( ); move ( 14, 0 ); clrtoeol ( ); move ( 15, 0 ); clrtoeol ( ); move ( 16, 0 ); clrtoeol ( ); mark[wm].entering++; mvprintw ( 23, 0, "Mark F%d set.", wm ); clrtoeol ( ); } mark[wm].name[strlen(mark[wm].name)+1] = '\0'; mark[wm].name[strlen(mark[wm].name)] = c; break; } move ( 10, 40 ); if ( strlen ( mark[wm].name ) > 0 ) printw ( "F%d \"%s\"", wm, mark[wm].name ); clrtoeol ( ); c = getch ( ); } mvprintw ( 4, 0, "##############################################################################" ); mvprintw ( 4, (int) ( speed / 2.0 ), "#" ); clrtoeol ( ); mvprintw ( 7, 21, "Time = %02d:%02d:%02d", tm->tm_hour, tm->tm_min, tm->tm_sec ); mvprintw ( 6, 20, "Speed = %6.2f km/h", speed ); mvprintw ( 8, 17, "Odometer = %7.3f km", range ); /* 12345678901234567890 (28 peanut butter sangers) */ if ( mark[wm].range != 0 ) { char *c = mark[wm].name; int remain; float since; /* ? */ remain = atoi ( mark[wm].name ); since = range - mark[wm].range; mvprintw ( 12, 6, "Distance since mark = %7.3f km", since ); if ( remain != 0 ) { struct tm tm; float until = (float) remain - since; int dd = cd - mark[wm].cd; int dt = ct - mark[wm].ct; float speed = ( dd * mm / dt * 3.6 ); float guess = until / speed; /* hours */ time_t then = now + ( (float) guess * 3600.0 ); localtime_r ( &then, &tm ); if ( until < 0 ) { move ( 13, 0 ); clrtoeol ( ); mvprintw ( 13, 28, "(passed)" ); move ( 14, 0 ); clrtoeol ( ); move ( 15, 0 ); clrtoeol ( ); move ( 16, 0 ); clrtoeol ( ); } else { mvprintw ( 13, 1, "Distance to destination = %7.3f km", until ); mvprintw ( 14, 1, "Average speed since mark = %6.2f km/h", speed ); /* 1234567890123456789012345678901234567890 */ mvprintw ( 16, 1, "Predicted arrival time = %02d:%02d:%02d", tm.tm_hour, tm.tm_min, tm.tm_sec ); mvprintw ( 15, 1, "Predicted travel time = %6.2f hours", (float) guess ); } } } /* mvprintw ( 18, 20, "Ct:Cd = %d:%d", ct, cd ); clrtoeol ( ); mvprintw ( 19, 20, "Dt:Dd = %d:%d", dt, dd ); clrtoeol ( ); */ /* detect overspeed conditions */ if ( sound ) for(i=60;i<120;i+=10) { if ( previous < i && speed > i ) { /* rising tone, major chord, C, E, G */ ioctl(0, KDMKTONE, (100<<16 | (1193180/1000))); usleep(100000); ioctl(0, KDMKTONE, (100<<16 | (1193180/1260))); usleep(100000); ioctl(0, KDMKTONE, (200<<16 | (1193180/1498))); usleep(200000); } if ( previous > i && speed < i ) { /* falling tone, minor chord, G, D#, C */ ioctl(0, KDMKTONE, (100<<16 | (1193180/1498))); usleep(100000); ioctl(0, KDMKTONE, (100<<16 | (1193180/1189))); usleep(100000); ioctl(0, KDMKTONE, (200<<16 | (1193180/1000))); usleep(200000); } } previous = speed; /* announce we are working fine in the first few metres of travel */ if ( sound ) if ( cd * mm < 10000 ) { ioctl(0, KDMKTONE, (100<<16 | (1193180/4000))); usleep(100000); } /* format line for output */ #ifdef notdef sprintf ( buffer, "%07.4f\t%06.2f\t%d\t%d\t%d\t%d\t%f\tcar-%04.4d-%03.3d.log\n", (float) tm->tm_hour + (float) tm->tm_min / 60.0 + (float) tm->tm_sec / 3600.0, speed, ct, cd, dt, dd, mm, tm->tm_year+1900, tm->tm_yday ); /* write current sample to new output file */ current = fopen ( "warner.tmp", "w" ); fclose ( current ); rename ( "warner.tmp", "warner.dat" ); #endif /* save this sample to output log if we have reached sample time */ if ( ( now / sample ) != was ) { char new[256]; static char old[256]; static int lines; was = now / sample; sprintf ( new, "car-%04.4d-%03.3d.log", tm->tm_year+1900, tm->tm_yday ); mvprintw ( 21, 21, "File = %s", new ); if ( output == NULL ) { output = fopen ( new, "a" ); lines = 0; } else { if ( strcmp ( old, new ) ) { mvprintw ( 23, 70, "(new file)" ); clrtoeol ( ); fclose ( output ); output = fopen ( new, "a" ); strcpy ( old, new ); lines = 0; } } fprintf ( output, "%.4f %.2f %d %d %d %d %f\n", (float) tm->tm_hour + (float) tm->tm_min / 60.0 + (float) tm->tm_sec / 3600.0, speed, ct, cd, dt, dd, mm ); fflush ( output ); lines++; mvprintw ( 21, 60, "Lines = %d", lines ); clrtoeol ( ); } } }