/****************************************************************************** * WriteTrack, v. 1.10 * * * * by * * * * L. Padilla (e-mail: padilla at domain "gae ucm es") * * * * Madrid, February 2003 - June 2012 * * * * Compile with: cc writetrack.c -o writetrack -O * * Latest version at http://www.gae.ucm.es/~padilla/extrawork/writetrack.c * ******************************************************************************/ #include #include #include #include #include #include #define TRUE 1 #define FALSE 0 #define OPORT1 0x03FC /* Modem control register serial port COM1 */ #define OPORT2 0x02FC /* Modem control register serial port COM2 */ #define OPORT3 0x03EC /* Modem control register serial port COM3 */ #define OPORT4 0x02EC /* Modem control register serial port COM4 */ #define IPORT1 0x03FE /* Modem status register serial port COM1 */ #define IPORT2 0x02FE /* Modem status register serial port COM2 */ #define IPORT3 0x03EE /* Modem status register serial port COM3 */ #define IPORT4 0x02EE /* Modem status register serial port COM4 */ #define OPORT OPORT1 /* Select control COM port */ #define IPORT IPORT1 /* Select status COM port */ #define OSMASK 0x02 /* RTS bit (pin 7/9 or 4/25), sensor signal */ #define OCMASK 0x01 /* DTR bit (pin 4/9 or 20/25), writing signal */ #define INMASK 0x20 /* DSR bit (pin 6/9 or 6/25), sensor input */ /* GND is pin 5/9 or 7/25 */ #define BITBCD 5 /* Bits in a BCD byte */ #define BITALPHA 7 /* Bits in an ALPHA byte */ #define OFFBCD 48 /* Start of BCD characters in ASCII table */ #define OFFALPHA 32 /* Start of ALPHA characters in ASCII table */ #define DENLOW 1.0 /* Relative bit density in low density format */ #define DENHIGH 1.7 /* Relative bit density in high density format */ #define CLKLOW 20 /* Leading clocking bits in low density format */ #define CLKHIGH 60 /* Leading clocking bits in high density format */ #define FILEN 256 /* Max. name length of data file */ #define BITS 2000 /* Max. number of bits to record */ #define TOUT 20000 /* Approx. time out waiting for sensor signals */ /* in units of 0.5 ms */ #define DIST 1.8 /* Distance between sensors in cm */ #define SPDLOW 40.0 /* Low density recommended swipe speed */ #define SPDHIGH 24.3 /* High density recommended swipe speed */ #define MINSPD 10.0 /* Min. advisable swipe speed */ #define MAXSPD 60.0 /* Max. advisable swipe speed */ #define RSNSPD 150.0 /* Max. reasonable swipe speed */ #define DELAY1 500 /* Loop 1 delay (must be integer) */ //#define DELAY2 423.3 /* Loop 2 base delay (must be float ) */ #define DELAY2 211.7 /* Loop 2 base delay (must be float ) */ // Theoretical value divided by 2 (empirical result) #define ROUND(x) ((int) ((float) (x) + 0.5)) main (int argc, char * argv[]) { char file[FILEN] = "writetrack.dat", data[BITS] = "", aux[2] = "0"; int i, j, k, counter1, counter2, dsr, odsr, track = 0, clk = -1, bit, off, bytes, doLRC = FALSE, shortbit1 = FALSE, invclk = FALSE, parity, bits[BITS], LRCbit[BITALPHA] = {}; float density, refspd, speed = 0.0; FILE * file_p; struct timeval time_val1, time_val2, time_val3, time_val4, time_val5, time_val6; struct sched_param schpar; printf ("\n"); /* Processing command line arguments */ for (i = 1; i < argc; i++) { if (strcmp (argv[i], "-t") == 0) { i++; if (i < argc) { track = atoi (argv[i]); } else { printf ("Parameter -t error!\n\n"); return -1; } } else if (strcmp (argv[i], "-c") == 0) { i++; if (i < argc) { clk = atoi (argv[i]); } else { printf ("Parameter -c error!\n\n"); return -1; } } else if (strcmp (argv[i], "-f") == 0) { i++; if (i < argc && strlen (argv[i]) <= FILEN) { strcpy (file, argv[i]); } else { printf ("Parameter -f error!\n\n"); return -1; } } else if (strcmp (argv[i], "-l") == 0) { doLRC = TRUE; } else if (strcmp (argv[i], "-1") == 0) { shortbit1 = TRUE; } else if (strcmp (argv[i], "-i") == 0) { invclk = TRUE; } else { printf ("Usage: writetrack [-t ] [-c ] "); printf ("[-f ] [-l] [-1] [-i]\n\n"); printf ("Options:\n\n"); printf ("-t : Track number.\n"); printf ("-c : Number of leading clocking bits.\n"); printf ("-f : File with bytes or bits to write.\n"); printf ("-l : Calculate and add LRC character.\n"); printf ("-1 : Bits 1 are just one flux reversal.\n"); printf ("-i : Inverse clocking bits, 1s instead of 0s."); printf ("\n\n"); return 1; } } if (track == 1) /* Track 1 */ { printf ("Track: 1\n"); density = DENHIGH; refspd = SPDHIGH; bit = BITALPHA; off = OFFALPHA; if (clk < 0) { clk = CLKHIGH; printf ("Bad or no clocking bits parameter, using default: %i\n", clk); } else printf ("Clocking bits: %i\n", clk); } else if (track == 2) /* Track 2 */ { printf ("Track: 2\n"); density = DENLOW; refspd = SPDLOW; bit = BITBCD; off = OFFBCD; if (clk < 0) { clk = CLKLOW; printf ("Bad or no clocking bits parameter, using default: %i\n", clk); } else printf ("Clocking bits: %i\n", clk); } else if (track == 3) /* Track 3 */ { printf ("Track: 3\n"); density = DENHIGH; refspd = SPDHIGH; bit = BITBCD; off = OFFBCD; if (clk < 0) { clk = CLKHIGH; printf ("Bad or no clocking bits parameter, using default: %i\n", clk); } else printf ("Clocking bits: %i\n", clk); } else { printf ("Bad or no track number, using default: 2\n"); density = DENLOW; refspd = SPDLOW; bit = BITBCD; off = OFFBCD; if (clk < 0) { clk = CLKLOW; printf ("Bad or no clocking bits parameter, using default: %i\n", clk); } else printf ("Clocking bits: %i\n", clk); } if ((file_p = fopen (file, "r")) == NULL) { printf ("Could not open file: %s\n\n", file); return -2; } else { fgets (data, BITS, file_p); if (strlen (data) > 0) { if (data[strlen (data) - 1] == '\n') data[strlen (data) - 1] = '\0'; printf ("Data to write: %s\n", data); } else { printf ("Data error!\n\n"); return -3; } fclose (file_p); } if (data[0] == '0' || data[0] == '1') { bytes = FALSE; printf ("Input data are bits.\n"); } else { bytes = TRUE; printf ("Input data are bytes.\n"); } if (doLRC) { if (bytes) printf ("LRC will be added.\n"); else printf ("LRC option is only for byte data input.\n"); } if (shortbit1) printf ("Short bits 1 will be used.\n"); if (invclk) printf ("Inverse clocking bits will be used.\n"); /* Creating data bits */ for (i = 0, j = 0; i < BITS; i++) { if (i < clk || i > BITS - 2 * BITALPHA) { if (invclk) bits[i] = 1; else bits[i] = 0; } else { if (! bytes) { if (j < strlen (data)) { aux[0] = data[j]; bits[i] = atoi (aux); j++; if (bits[i] == 1 && ! shortbit1) { i++; bits[i] = 1; } } else { if (invclk) bits[i] = 1; else bits[i] = 0; } } else { if (j < strlen (data)) { for (k = 0, parity = 0; k < bit - 1; k++, i++) { bits[i] = ((int) data[j] - off)>>k & 1; parity ^= bits[i]; if (doLRC) LRCbit[k] ^= bits[i]; if (bits[i] == 1 && ! shortbit1) { i++; bits[i] = 1; } } bits[i] = ~parity & 1; if (bits[i] == 1 && ! shortbit1) { i++; bits[i] = 1; } j++; } else if (doLRC && j < strlen (data) + 1) { for (k = 0, parity = 0; k < bit - 1; k++, i++) { bits[i] = LRCbit[k]; parity ^= bits[i]; if (bits[i] == 1 && ! shortbit1) { i++; bits[i] = 1; } } bits[i] = ~parity & 1; if (bits[i] == 1 && ! shortbit1) { i++; bits[i] = 1; } j++; } else { if (invclk) bits[i] = 1; else bits[i] = 0; } } } } // for (i = 0; i < BITS; i++) // printf ("%i", bits[i]); // printf ("\n"); /* Granting access permission and highest priority (root privilege needed) */ if (ioperm (OPORT, 3, 1) != 0) { printf ("ioperm error! Are you root?\n\n"); return -4; } schpar.sched_priority = 99; if (sched_setscheduler (0, SCHED_FIFO, & schpar) != 0) { printf ("sched_setscheduler error!\n\n"); return -4; } if (sched_setparam (0, & schpar) != 0) { printf ("sched_setparam error!\n\n"); return -4; } /* First loop: waiting for sensor signals */ i = 0; odsr = 0; counter1 = 0; outb (OSMASK, OPORT); /* Set RTS high */ gettimeofday (& time_val1, NULL); do { usleep (DELAY1); /* Wait approx. half millisecond */ counter1++; dsr = inb (IPORT) & INMASK; /* Read DSR */ if (dsr && ! odsr) { if (i == 0) { i++; gettimeofday (& time_val2, NULL); } else { gettimeofday (& time_val3, NULL); speed = DIST/((float) (time_val3.tv_sec - time_val2.tv_sec) + (float) (time_val3.tv_usec - time_val2.tv_usec) /1.0e+06); if (speed < RSNSPD) break; else speed = 0.0; } } odsr = dsr; } while (counter1 < TOUT); gettimeofday (& time_val4, NULL); outb (0, OPORT); /* Set RTS low */ if (speed == 0.0) { printf ("No good sensor signals!\n\n"); return 2; } /* Second loop: writing data */ counter2 = 0; gettimeofday (& time_val5, NULL); do { outb (counter2 & OCMASK, OPORT); /* Change DTR */ usleep (ROUND((float) (2 - bits[counter2]) * DELAY2/density * refspd /speed)); counter2++; } while (counter2 < BITS); gettimeofday (& time_val6, NULL); /* Print statistics */ printf ("Loop1 period: %.2f ms.\n", 1000.0 * ((float) (time_val4.tv_sec - time_val1.tv_sec) + (float) (time_val4.tv_usec - time_val1.tv_usec) /1.0e+06)/(float) counter1); printf ("Loop1 frequency: %.2f Hz.\n", (float) counter1/((float) (time_val4.tv_sec - time_val1.tv_sec) + (float) (time_val4.tv_usec - time_val1.tv_usec)/1.0e+06)); printf ("Loop1 duration: %.2f s.\n", (float) (time_val4.tv_sec - time_val1.tv_sec) + (float) (time_val4.tv_usec - time_val1.tv_usec) /1.0e+06); printf ("Initial swipe speed: %.2f cm/s\n", speed); printf ("Loop2 period: %.2f ms.\n", 1000.0 * ((float) (time_val6.tv_sec - time_val5.tv_sec) + (float) (time_val6.tv_usec - time_val5.tv_usec) /1.0e+06)/(float) counter2); printf ("Loop2 frequency: %.2f Hz.\n", (float) counter2/((float) (time_val6.tv_sec - time_val5.tv_sec) + (float) (time_val6.tv_usec - time_val5.tv_usec)/1.0e+06)); printf ("Loop2 duration: %.2f s.\n", (float) (time_val6.tv_sec - time_val5.tv_sec) + (float) (time_val6.tv_usec - time_val5.tv_usec) /1.0e+06); if (speed < MINSPD) printf ("Swipe was probably too slow!\n"); else if (speed > MAXSPD) printf ("Swipe was probably too fast!\n"); else printf ("Record done, check quality!\n"); printf ("\n"); return 0; }