// // wwvb1.c - Generate & display WWVB subcode // // 03-Feb-2005 /tvb // #include #include #include // Define basic types typedef unsigned char byte; typedef unsigned int uint; typedef unsigned long ulong; // Define time code elements struct timecode { uint min; uint hour; uint days; uint year; uint leapyear; uint dst; int ut1; uint leapsec; }; // Define forward referenced function prototypes void tick_set (time_t t, struct timecode *tc); void tick_show (struct timecode *tc); void tick_tock (struct timecode *tc); int wwvb_telegram (struct timecode *tc, byte code[]); int main (int argc, char *argv[]) { int i, n; long minutes; time_t now; struct timecode tco; // Set WWVB time from PC time time(&now); tick_set(now, &tco); // Get number of minutes if (argc > 1) { minutes = atol(argv[1]); if (minutes <= 0) { fprintf(stderr, "Invalid Number of minutes: %s\n", argv[1]); exit(1); } } else { fprintf(stderr, "** Number of minutes not specified (defaulting to 10)\n"); minutes = 10; } if (argc > 2) { fprintf(stderr, "Unexpected argument: %s\n", argv[2]); exit(1); } // Generate time code, minute by minute fprintf(stderr, "\nNIST WWVB subcode test generator\n\n"); fprintf(stderr, "PC local time: %s", ctime(&now)); printf("WWVB timecode: "); tick_show(&tco); do { byte bits[61]; printf("'%.2d+%.3d %.2d:%.2d ", tco.year, tco.days, tco.hour, tco.min); n = wwvb_telegram(&tco, bits); for (i = 0; i < n; i += 1) { printf("%d", bits[i]); } printf("\n"); tick_tock(&tco); } while (--minutes > 0) ; return 0; } // Extract one binary coded decimal bit int BCD (int n, int d) { if (n < 0) { n = -n; } while (d >= 10) { n /= 10; d /= 10; } return ((n % 10) & d) ? 1 : 0; } // Convert date and time to 60 bit WWVB time code int wwvb_telegram (struct timecode *tc, byte code[]) { int n; code[0] = 2; code[1] = BCD(tc->min, 40); code[2] = BCD(tc->min, 20); code[3] = BCD(tc->min, 10); code[4] = 0; code[5] = BCD(tc->min, 8); code[6] = BCD(tc->min, 4); code[7] = BCD(tc->min, 2); code[8] = BCD(tc->min, 1); code[9] = 2; code[10] = 0; code[11] = 0; code[12] = BCD(tc->hour, 20); code[13] = BCD(tc->hour, 10); code[14] = 0; code[15] = BCD(tc->hour, 8); code[16] = BCD(tc->hour, 4); code[17] = BCD(tc->hour, 2); code[18] = BCD(tc->hour, 1); code[19] = 2; code[20] = 0; code[21] = 0; code[22] = BCD(tc->days, 200); code[23] = BCD(tc->days, 100); code[24] = 0; code[25] = BCD(tc->days, 80); code[26] = BCD(tc->days, 40); code[27] = BCD(tc->days, 20); code[28] = BCD(tc->days, 10); code[29] = 2; code[30] = BCD(tc->days, 8); code[31] = BCD(tc->days, 4); code[32] = BCD(tc->days, 2); code[33] = BCD(tc->days, 1); code[34] = 0; code[35] = 0; code[36] = tc->ut1 >= 0; code[37] = !code[36]; code[38] = code[36]; code[39] = 2; code[40] = BCD(tc->ut1, 800); code[41] = BCD(tc->ut1, 400); code[42] = BCD(tc->ut1, 200); code[43] = BCD(tc->ut1, 100); code[44] = 0; code[45] = BCD(tc->year, 80); code[46] = BCD(tc->year, 40); code[47] = BCD(tc->year, 20); code[48] = BCD(tc->year, 10); code[49] = 2; code[50] = BCD(tc->year, 8); code[51] = BCD(tc->year, 4); code[52] = BCD(tc->year, 2); code[53] = BCD(tc->year, 1); code[54] = 0; code[55] = tc->leapyear; code[56] = tc->leapsec; code[57] = (tc->dst & 2) == 2; code[58] = (tc->dst & 1) == 1; code[59] = 2; // Handle positive or negative leap second exception n = 60; if (tc->leapsec != 0 && tc->hour == 23 && tc->min == 59) { if (tc->ut1 > 0) { tc->ut1 -= 1000; n = 59; } else if (tc->ut1 < 0) { tc->ut1 += 1000; n = 61; code[60] = 2; } tc->leapsec = 0; } return n; } // Set timecode from PC clock void tick_set (time_t t, struct timecode *tc) { struct tm *tm; tm = gmtime(&t); tc->min = tm->tm_min; tc->hour = tm->tm_hour; tc->days = 1 + tm->tm_yday; tc->year = tm->tm_year % 100; tc->leapyear = (tc->year % 4) == 0; tc->dst = 0; // normal tc->ut1 = 0; // place holder tc->leapsec = 0; // normal return; } // Display timecode values void tick_show (struct timecode *tc) { printf("year=%.2d days=%.3d hour=%.2d min=%.2d ", tc->year, tc->days, tc->hour, tc->min); printf("dst=%d ut1=%d ly=%d ls=%d\n", tc->dst, tc->ut1, tc->leapyear, tc->leapsec); return; } // Increment timecode by one minute void tick_tock (struct timecode *tc) { tc->min += 1; if (tc->min >= 60) { tc->min = 0; tc->hour += 1; if (tc->hour >= 24) { tc->hour = 0; tc->days += 1; if (tc->days >= 365 + tc->leapyear) { tc->days = 1; tc->year += 1; tc->year %= 100; tc->leapyear = (tc->year % 4) == 0; } } } return; }