#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#undef VERSION
#endif
#ifdef HAVE_SYS_SOUNDCARD_H
#include <sys/soundcard.h>
#else
# ifdef HAVE_SYS_AUDIOIO_H
# include <sys/audioio.h>
# else
# include <sys/audio.h>
# endif
#endif
#include "ntp_stdlib.h"
#include <math.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#define VERSION (0)
#define ISSUE (23)
#define ISSUE_DATE "2007-02-12"
#define SECOND (8000)
#define BUFLNG (400)
#define DEVICE "/dev/audio"
#define WWV (0)
#define IRIG (1)
#define OFF (0)
#define LOW (1)
#define HIGH (2)
#define DATA0 (200)
#define DATA1 (500)
#define PI (800)
#define M2 (2)
#define M5 (5)
#define M8 (8)
#define NUL (0)
#define SECONDS_PER_MINUTE (60)
#define SECONDS_PER_HOUR (3600)
#define OUTPUT_DATA_STRING_LENGTH (200)
int u6000[] = {
247, 247, 247, 247, 247, 247, 247, 247, 247, 247,
247, 247, 247, 247, 247, 247, 247, 247, 247, 247,
247, 247, 247, 247, 247, 247, 247, 247, 247, 247,
247, 247, 247, 247, 247, 247, 247, 247, 247, 247,
247, 247, 247, 247, 247, 247, 247, 247, 247, 247,
247, 247, 247, 247, 247, 247, 247, 247, 247, 247,
247, 247, 247, 247, 247, 247, 247, 247, 247, 247,
247, 247, 247, 247, 247, 247, 247, 247, 247, 247};
int u3000[] = {
119, 119, 119, 119, 119, 119, 119, 119, 119, 119,
119, 119, 119, 119, 119, 119, 119, 119, 119, 119,
119, 119, 119, 119, 119, 119, 119, 119, 119, 119,
119, 119, 119, 119, 119, 119, 119, 119, 119, 119,
119, 119, 119, 119, 119, 119, 119, 119, 119, 119,
119, 119, 119, 119, 119, 119, 119, 119, 119, 119,
119, 119, 119, 119, 119, 119, 119, 119, 119, 119,
119, 119, 119, 119, 119, 119, 119, 119, 119, 119};
int c3000[] = {1, 48, 63, 70, 78, 82, 85, 89, 92, 94,
96, 98, 99, 100, 101, 101, 102, 103, 103, 103,
103, 103, 103, 103, 102, 101, 101, 100, 99, 98,
96, 94, 92, 89, 85, 82, 78, 70, 63, 48,
129, 176, 191, 198, 206, 210, 213, 217, 220, 222,
224, 226, 227, 228, 229, 229, 230, 231, 231, 231,
231, 231, 231, 231, 230, 229, 229, 228, 227, 226,
224, 222, 220, 217, 213, 210, 206, 198, 191, 176};
int c6000[] = {1, 63, 78, 86, 93, 98, 101, 104, 107, 110,
112, 113, 115, 116, 117, 117, 118, 118, 119, 119,
119, 119, 119, 118, 118, 117, 117, 116, 115, 113,
112, 110, 107, 104, 101, 98, 93, 86, 78, 63,
129, 191, 206, 214, 221, 226, 229, 232, 235, 238,
240, 241, 243, 244, 245, 245, 246, 246, 247, 247,
247, 247, 247, 246, 246, 245, 245, 244, 243, 241,
240, 238, 235, 232, 229, 226, 221, 214, 206, 191};
struct progx {
int sw;
int arg;
};
#define DATA (0)
#define COEF (1)
#define DEC (2)
#define MIN (3)
#define LEAP (4)
#define DUT1 (5)
#define DST1 (6)
#define DST2 (7)
#define DECZ (8)
#define DECC (9)
#define NODEC (10)
#define DECX (11)
#define DATAX (12)
struct progx progx[] = {
{MIN, 800},
{DATA, DATA0},
{DST2, 0},
{LEAP, 0},
{COEF, 1},
{COEF, 2},
{COEF, 4},
{COEF, 8},
{DEC, DATA0},
{DATA, PI},
{COEF, 1},
{COEF, 2},
{COEF, 4},
{COEF, 8},
{DEC, DATA0},
{COEF, 1},
{COEF, 2},
{COEF, 4},
{COEF, 8},
{DEC, PI},
{COEF, 1},
{COEF, 2},
{COEF, 4},
{COEF, 8},
{DEC, DATA0},
{COEF, 1},
{COEF, 2},
{COEF, 4},
{COEF, 8},
{DECX, PI},
{COEF, 1},
{COEF, 2},
{COEF, 4},
{COEF, 8},
{DEC, DATA0},
{COEF, 1},
{COEF, 2},
{COEF, 4},
{COEF, 8},
{DEC, PI},
{COEF, 1},
{COEF, 2},
{COEF, 4},
{COEF, 8},
{DEC, DATA0},
{DATA, DATA0},
{DATA, DATA0},
{DATA, DATA0},
{DATA, DATA0},
{DATA, PI},
{DUT1, 8},
{COEF, 1},
{COEF, 2},
{COEF, 4},
{COEF, 8},
{DST1, 0},
{DUT1, 1},
{DUT1, 2},
{DUT1, 4},
{DATAX, PI},
{DATA, DATA0},
};
struct progx progu[] = {
{COEF, 2},
{COEF, 4},
{COEF, 8},
{DECC, 1},
{COEF, 2},
{COEF, 4},
{COEF, 8},
{DECC, 1},
{COEF, 2},
{NODEC, M8},
};
struct progx progv[] = {
{COEF, 2},
{COEF, 4},
{COEF, 8},
{DECC, 1},
{COEF, 2},
{COEF, 4},
{COEF, 8},
{DECC, 1},
{COEF, 2},
{DEC, M8},
};
struct progx progw[] = {
{COEF, 1},
{COEF, 2},
{COEF, 4},
{COEF, 8},
{DECC, 1},
{COEF, 2},
{COEF, 4},
{COEF, 8},
{DECC, 1},
{NODEC, M8},
};
struct progx progy[] = {
{COEF, 1},
{COEF, 2},
{COEF, 4},
{COEF, 8},
{DECZ, M2},
{COEF, 1},
{COEF, 2},
{COEF, 4},
{COEF, 8},
{DEC, M8},
};
struct progx progz[] = {
{MIN, M8},
{COEF, 1},
{COEF, 2},
{COEF, 4},
{COEF, 8},
{DECZ, M2},
{COEF, 1},
{COEF, 2},
{COEF, 4},
{DEC, M8},
};
#define LEAPSTATE_NORMAL (0)
#define LEAPSTATE_DELETING (1)
#define LEAPSTATE_INSERTING (2)
#define LEAPSTATE_ZERO_AFTER_INSERT (3)
void WWV_Second(int, int);
void WWV_SecondNoTick(int, int);
void digit(int);
void peep(int, int, int);
void poop(int, int, int, int);
void delay(int);
int ConvertMonthDayToDayOfYear (int, int, int);
void Help (void);
void ReverseString(char *);
char buffer[BUFLNG];
int bufcnt = 0;
int fd;
int tone = 1000;
int HourTone = 1500;
int encode = IRIG;
int leap = 0;
int DstFlag = 0;
int dut1 = 0;
int utc = 0;
int IrigIncludeYear = FALSE;
int IrigIncludeIeee = FALSE;
int StraightBinarySeconds = 0;
int ControlFunctions = 0;
int Debug = FALSE;
int Verbose = TRUE;
char *CommandName;
#ifndef HAVE_SYS_SOUNDCARD_H
int level = AUDIO_MAX_GAIN / 8;
int port = AUDIO_LINE_OUT;
#endif
int TotalSecondsCorrected = 0;
int TotalCyclesAdded = 0;
int TotalCyclesRemoved = 0;
int
main(
int argc,
char **argv
)
{
#ifndef HAVE_SYS_SOUNDCARD_H
audio_info_t info;
int rval;
#endif
struct timeval TimeValue;
time_t SecondsPartOfTime;
time_t BaseRealTime;
time_t NowRealTime;
unsigned SecondsRunningRealTime;
unsigned SecondsRunningSimulationTime;
int SecondsRunningDifference;
int ExpectedRunningDifference = 0;
unsigned StabilityCount;
#define RUN_BEFORE_STABILITY_CHECK (30) // Must run this many seconds before even checking stability.
#define MINIMUM_STABILITY_COUNT (10) // Number of consecutive differences that need to be within initial stability band to say we are stable.
#define INITIAL_STABILITY_BAND ( 2) // Determining initial stability for consecutive differences within +/- this value.
#define RUNNING_STABILITY_BAND ( 5) // When running, stability is defined as difference within +/- this value.
struct tm *TimeStructure = NULL;
char device[200];
char code[200];
int temp;
int arg = 0;
int sw = 0;
int ptr = 0;
int Year;
int Month;
int DayOfMonth;
int Hour;
int Minute;
int Second = 0;
int DayOfYear;
int BitNumber;
#ifdef HAVE_SYS_SOUNDCARD_H
int AudioFormat;
int MonoStereo;
#define MONO (0)
#define STEREO (1)
int SampleRate;
int SampleRateDifference;
#endif
int SetSampleRate;
char FormatCharacter = '3';
char AsciiValue;
int HexValue;
int OldPtr = 0;
int FrameNumber = 0;
float TimeOffset = 0.0;
int OffsetSignBit = 0;
int OffsetOnes = 0;
int OffsetHalf = 0;
int TimeQuality = 0;
char ParityString[200];
int ParitySum = 0;
int ParityValue;
char *StringPointer;
int InsertLeapSecond = FALSE;
int DeleteLeapSecond = FALSE;
int LeapYear = 0;
int LeapMonth = 0;
int LeapDayOfMonth = 0;
int LeapHour = 0;
int LeapMinute = 0;
int LeapDayOfYear = 0;
int LeapState = LEAPSTATE_NORMAL;
int LeapSecondPending = FALSE;
int LeapSecondPolarity = FALSE;
int DstSwitchYear = 0;
int DstSwitchMonth = 0;
int DstSwitchDayOfMonth = 0;
int DstSwitchHour = 0;
int DstSwitchMinute = 0;
int DstSwitchDayOfYear = 0;
int DstSwitchFlag = FALSE;
int DstSwitchPendingYear = 0;
int DstSwitchPendingDayOfYear = 0;
int DstSwitchPendingHour = 0;
int DstSwitchPendingMinute = 0;
int DstPendingFlag = FALSE;
int Unmodulated = FALSE;
int UnmodulatedInverted = FALSE;
float UseOffsetHoursFloat;
int UseOffsetSecondsInt = 0;
float UseOffsetSecondsFloat;
char OutputDataString[OUTPUT_DATA_STRING_LENGTH];
int SecondsToSend = 0;
int CountOfSecondsSent = 0;
int AddCycle = FALSE; int RemoveCycle = FALSE; int RateCorrection; int EnableRateCorrection = TRUE;
float RatioError;
CommandName = argv[0];
if (argc < 1)
{
Help ();
exit (-1);
}
strlcpy(device, DEVICE, sizeof(device));
Year = 0;
SetSampleRate = SECOND;
#if HAVE_SYS_SOUNDCARD_H
while ((temp = getopt(argc, argv, "a:b:c:df:g:hHi:jk:l:o:q:r:stu:xy:z?")) != -1) {
#else
while ((temp = getopt(argc, argv, "a:b:c:df:g:hHi:jk:l:o:q:r:stu:v:xy:z?")) != -1) {
#endif
switch (temp) {
case 'a':
strlcpy(device, optarg, sizeof(device));
break;
case 'b':
sscanf(optarg, "%2d%2d%2d%2d%2d", &LeapYear, &LeapMonth, &LeapDayOfMonth,
&LeapHour, &LeapMinute);
InsertLeapSecond = FALSE;
DeleteLeapSecond = TRUE;
break;
case 'c':
sscanf(optarg, "%d", &SecondsToSend);
break;
case 'd':
DstFlag++;
break;
case 'f':
sscanf(optarg, "%c", &FormatCharacter);
break;
case 'g':
sscanf(optarg, "%2d%2d%2d%2d%2d", &DstSwitchYear, &DstSwitchMonth, &DstSwitchDayOfMonth,
&DstSwitchHour, &DstSwitchMinute);
DstSwitchFlag = TRUE;
break;
case 'h':
case 'H':
case '?':
Help ();
exit(-1);
break;
case 'i':
sscanf(optarg, "%2d%2d%2d%2d%2d", &LeapYear, &LeapMonth, &LeapDayOfMonth,
&LeapHour, &LeapMinute);
InsertLeapSecond = TRUE;
DeleteLeapSecond = FALSE;
break;
case 'j':
EnableRateCorrection = FALSE;
break;
case 'k':
sscanf (optarg, "%d", &RateCorrection);
EnableRateCorrection = FALSE;
if (RateCorrection < 0)
{
RemoveCycle = TRUE;
AddCycle = FALSE;
if (Verbose)
printf ("\n> Forcing rate correction removal of cycle...\n");
}
else
{
if (RateCorrection > 0)
{
RemoveCycle = FALSE;
AddCycle = TRUE;
if (Verbose)
printf ("\n> Forcing rate correction addition of cycle...\n");
}
}
break;
case 'l':
sscanf(optarg, "%f", &UseOffsetHoursFloat);
UseOffsetSecondsFloat = UseOffsetHoursFloat * (float) SECONDS_PER_HOUR;
UseOffsetSecondsInt = (int) (UseOffsetSecondsFloat + 0.5);
break;
case 'o':
sscanf(optarg, "%f", &TimeOffset);
if (TimeOffset >= -0.2)
{
OffsetSignBit = 0;
if (TimeOffset > 0)
{
OffsetOnes = TimeOffset;
if ( (TimeOffset - floor(TimeOffset)) >= 0.4)
OffsetHalf = 1;
else
OffsetHalf = 0;
}
else
{
OffsetOnes = 0;
OffsetHalf = 0;
}
}
else
{
OffsetSignBit = 1;
OffsetOnes = -TimeOffset;
if ( (ceil(TimeOffset) - TimeOffset) >= 0.4)
OffsetHalf = 1;
else
OffsetHalf = 0;
}
break;
case 'q':
sscanf(optarg, "%x", &TimeQuality);
TimeQuality &= 0x0F;
break;
case 'r':
sscanf(optarg, "%d", &SetSampleRate);
break;
case 's':
leap++;
break;
case 't':
tone = 1200;
break;
case 'u':
sscanf(optarg, "%d", &dut1);
if (dut1 < 0)
dut1 = abs(dut1);
else
dut1 |= 0x8;
break;
#ifndef HAVE_SYS_SOUNDCARD_H
case 'v':
sscanf(optarg, "%d", &level);
break;
#endif
case 'x':
Verbose = FALSE;
break;
case 'y':
sscanf(optarg, "%2d%2d%2d%2d%2d%2d", &Year, &Month, &DayOfMonth,
&Hour, &Minute, &Second);
utc++;
break;
case 'z':
Debug = TRUE;
break;
default:
printf("Invalid option \"%c\", aborting...\n", temp);
exit (-1);
break;
}
}
if (Debug)
Verbose = TRUE;
if (InsertLeapSecond || DeleteLeapSecond)
{
LeapDayOfYear = ConvertMonthDayToDayOfYear (LeapYear, LeapMonth, LeapDayOfMonth);
if (Debug)
{
printf ("\nHave request for leap second %s at year %4d day %3d at %2.2dh%2.2d....\n",\
DeleteLeapSecond ? "DELETION" : (InsertLeapSecond ? "ADDITION" : "( error ! )" ),
LeapYear, LeapDayOfYear, LeapHour, LeapMinute);
}
}
if (DstSwitchFlag)
{
DstSwitchDayOfYear = ConvertMonthDayToDayOfYear (DstSwitchYear, DstSwitchMonth, DstSwitchDayOfMonth);
DstSwitchPendingYear = DstSwitchYear;
DstSwitchPendingDayOfYear = DstSwitchDayOfYear;
DstSwitchPendingHour = DstSwitchHour;
DstSwitchPendingMinute = DstSwitchMinute - 1;
if (DstSwitchPendingMinute < 0)
{
DstSwitchPendingMinute = 59;
DstSwitchPendingHour--;
if (DstSwitchPendingHour < 0)
{
DstSwitchPendingHour = 23;
DstSwitchPendingDayOfYear--;
if (DstSwitchPendingDayOfYear < 1)
{
DstSwitchPendingYear--;
}
}
}
if (Debug)
{
printf ("\nHave DST switch request for year %4d day %3d at %2.2dh%2.2d,",
DstSwitchYear, DstSwitchDayOfYear, DstSwitchHour, DstSwitchMinute);
printf ("\n so will have warning at year %4d day %3d at %2.2dh%2.2d.\n",
DstSwitchPendingYear, DstSwitchPendingDayOfYear, DstSwitchPendingHour, DstSwitchPendingMinute);
}
}
switch (tolower(FormatCharacter)) {
case 'i':
printf ("\nFormat is IRIG-1998 (no year coded)...\n\n");
encode = IRIG;
IrigIncludeYear = FALSE;
IrigIncludeIeee = FALSE;
break;
case '2':
printf ("\nFormat is IRIG-2004 (BCD year coded)...\n\n");
encode = IRIG;
IrigIncludeYear = TRUE;
IrigIncludeIeee = FALSE;
break;
case '3':
printf ("\nFormat is IRIG with IEEE-1344 (BCD year coded, and more control functions)...\n\n");
encode = IRIG;
IrigIncludeYear = TRUE;
IrigIncludeIeee = TRUE;
break;
case '4':
printf ("\nFormat is unmodulated IRIG with IEEE-1344 (BCD year coded, and more control functions)...\n\n");
encode = IRIG;
IrigIncludeYear = TRUE;
IrigIncludeIeee = TRUE;
Unmodulated = TRUE;
UnmodulatedInverted = FALSE;
break;
case '5':
printf ("\nFormat is inverted unmodulated IRIG with IEEE-1344 (BCD year coded, and more control functions)...\n\n");
encode = IRIG;
IrigIncludeYear = TRUE;
IrigIncludeIeee = TRUE;
Unmodulated = TRUE;
UnmodulatedInverted = TRUE;
break;
case 'w':
printf ("\nFormat is WWV(H)...\n\n");
encode = WWV;
break;
default:
printf ("\n\nUnexpected format value of \'%c\', cannot parse, aborting...\n\n", FormatCharacter);
exit (-1);
break;
}
fd = open(device, O_WRONLY);
if (fd <= 0) {
printf("Unable to open audio device \"%s\", aborting: %s\n", device, strerror(errno));
exit(1);
}
#ifdef HAVE_SYS_SOUNDCARD_H
AudioFormat = AFMT_MU_LAW;
if (ioctl(fd, SNDCTL_DSP_SETFMT, &AudioFormat)==-1)
{
printf ("\nUnable to set output format, aborting...\n\n");
exit(-1);
}
if (AudioFormat != AFMT_MU_LAW)
{
printf ("\nUnable to set output format for mu law, aborting...\n\n");
exit(-1);
}
MonoStereo = MONO;
if (ioctl(fd, SNDCTL_DSP_STEREO, &MonoStereo)==-1)
{
printf ("\nUnable to set mono/stereo, aborting...\n\n");
exit(-1);
}
if (MonoStereo != MONO)
{
printf ("\nUnable to set mono/stereo for mono, aborting...\n\n");
exit(-1);
}
SampleRate = SetSampleRate;
if (ioctl(fd, SNDCTL_DSP_SPEED, &SampleRate)==-1)
{
printf ("\nUnable to set sample rate to %d, returned %d, aborting...\n\n", SetSampleRate, SampleRate);
exit(-1);
}
SampleRateDifference = SampleRate - SetSampleRate;
if (SampleRateDifference < 0)
SampleRateDifference = - SampleRateDifference;
if (SampleRateDifference > (SetSampleRate/1000))
{
printf ("\nUnable to set sample rate to %d, result was %d, more than 0.1 percent, aborting...\n\n", SetSampleRate, SampleRate);
exit(-1);
}
else
{
}
#else
rval = ioctl(fd, AUDIO_GETINFO, &info);
if (rval < 0) {
printf("\naudio control %s", strerror(errno));
exit(0);
}
info.play.port = port;
info.play.gain = level;
info.play.sample_rate = SetSampleRate;
info.play.channels = 1;
info.play.precision = 8;
info.play.encoding = AUDIO_ENCODING_ULAW;
printf("\nport %d gain %d rate %d chan %d prec %d encode %d\n",
info.play.port, info.play.gain, info.play.sample_rate,
info.play.channels, info.play.precision,
info.play.encoding);
ioctl(fd, AUDIO_SETINFO, &info);
#endif
gettimeofday(&TimeValue, NULL); NowRealTime = BaseRealTime = SecondsPartOfTime = TimeValue.tv_sec;
SecondsRunningSimulationTime = 0; StabilityCount = 0;
if (utc)
{
DayOfYear = ConvertMonthDayToDayOfYear (Year, Month, DayOfMonth);
}
else
{
if (UseOffsetSecondsInt >= 0)
SecondsPartOfTime += (time_t) UseOffsetSecondsInt;
else
SecondsPartOfTime -= (time_t) (-UseOffsetSecondsInt);
TimeStructure = gmtime(&SecondsPartOfTime);
Minute = TimeStructure->tm_min;
Hour = TimeStructure->tm_hour;
DayOfYear = TimeStructure->tm_yday + 1;
Year = TimeStructure->tm_year % 100;
Second = TimeStructure->tm_sec;
delay(SECOND - TimeValue.tv_usec * 8 / 1000);
}
StraightBinarySeconds = Second + (Minute * SECONDS_PER_MINUTE) + (Hour * SECONDS_PER_HOUR);
memset(code, 0, sizeof(code));
switch (encode) {
case WWV:
printf("WWV time signal, starting point:\n");
printf(" Year = %02d, Day of year = %03d, Time = %02d:%02d:%02d, Minute tone = %d Hz, Hour tone = %d Hz.\n",
Year, DayOfYear, Hour, Minute, Second, tone, HourTone);
snprintf(code, sizeof(code), "%01d%03d%02d%02d%01d",
Year / 10, DayOfYear, Hour, Minute, Year % 10);
if (Verbose)
{
printf("\n Year = %2.2d, Day of year = %3d, Time = %2.2d:%2.2d:%2.2d, Code = %s",
Year, DayOfYear, Hour, Minute, Second, code);
if ((EnableRateCorrection) || (RemoveCycle) || (AddCycle))
printf (", CountOfSecondsSent = %d, TotalCyclesAdded = %d, TotalCyclesRemoved = %d\n", CountOfSecondsSent, TotalCyclesAdded, TotalCyclesRemoved);
else
printf ("\n");
}
ptr = 8;
for (BitNumber = 0; BitNumber <= Second; BitNumber++) {
if (progx[BitNumber].sw == DEC)
ptr--;
}
break;
case IRIG:
printf ("IRIG-B time signal, starting point:\n");
printf (" Year = %02d, Day of year = %03d, Time = %02d:%02d:%02d, Straight binary seconds (SBS) = %05d / 0x%04X.\n",
Year, DayOfYear, Hour, Minute, Second, StraightBinarySeconds, StraightBinarySeconds);
printf ("\n");
if (Verbose)
{
printf ("Codes: \".\" = marker/position indicator, \"-\" = zero dummy bit, \"0\" = zero bit, \"1\" = one bit.\n");
if ((EnableRateCorrection) || (AddCycle) || (RemoveCycle))
{
printf (" \"o\" = short zero, \"*\" = long zero, \"x\" = short one, \"+\" = long one.\n");
}
printf ("Numerical values are time order reversed in output to make it easier to read.\n");
printf ("\n");
printf ("Legend of output codes:\n");
}
break;
}
for (CountOfSecondsSent=0; ((SecondsToSend==0) || (CountOfSecondsSent<SecondsToSend)); CountOfSecondsSent++)
{
if ((encode == IRIG) && (((Second % 20) == 0) || (CountOfSecondsSent == 0)))
{
printf ("\n");
printf (" Year = %02d, Day of year = %03d, Time = %02d:%02d:%02d, Straight binary seconds (SBS) = %05d / 0x%04X.\n",
Year, DayOfYear, Hour, Minute, Second, StraightBinarySeconds, StraightBinarySeconds);
if ((EnableRateCorrection) || (RemoveCycle) || (AddCycle))
{
printf (" CountOfSecondsSent = %d, TotalCyclesAdded = %d, TotalCyclesRemoved = %d\n", CountOfSecondsSent, TotalCyclesAdded, TotalCyclesRemoved);
if ((CountOfSecondsSent != 0) && ((TotalCyclesAdded != 0) || (TotalCyclesRemoved != 0)))
{
RatioError = ((float) (TotalCyclesAdded - TotalCyclesRemoved)) / (1000.0 * (float) CountOfSecondsSent);
printf (" Adjusted by %2.1f%%, apparent send frequency is %4.2f Hz not %d Hz.\n\n",
RatioError*100.0, (1.0+RatioError)*((float) SetSampleRate), SetSampleRate);
}
}
else
printf ("\n");
printf ("| StraightBinSecs | IEEE_1344_Control | Year | Day_of_Year | Hours | Minutes |Seconds |\n");
printf ("| --------------- | ----------------- | ---- | ----------- | ----- | ------- |------- |\n");
printf ("| | | | | | | |\n");
}
if (RemoveCycle)
{
RateCorrection = -1;
TotalSecondsCorrected ++;
}
else
{
if (AddCycle)
{
TotalSecondsCorrected ++;
RateCorrection = +1;
}
else
RateCorrection = 0;
}
if (LeapState == LEAPSTATE_NORMAL)
{
if ((Year == LeapYear) && (DayOfYear == LeapDayOfYear) && (Hour == LeapHour) && (Minute == LeapMinute))
{
if ((DeleteLeapSecond) && (Second == 58))
{
LeapState = LEAPSTATE_DELETING;
if (Debug)
printf ("\n<--- Ready to delete a leap second...\n");
}
else
{
if ((InsertLeapSecond) && (Second == 59))
{
LeapState = LEAPSTATE_INSERTING;
if (Debug)
printf ("\n<--- Ready to insert a leap second...\n");
}
}
}
}
switch (LeapState)
{
case LEAPSTATE_NORMAL:
Second = (Second + 1) % 60;
break;
case LEAPSTATE_DELETING:
Second = 0;
LeapState = LEAPSTATE_NORMAL;
if (Debug)
printf ("\n<--- Deleting a leap second...\n");
break;
case LEAPSTATE_INSERTING:
Second = 60;
LeapState = LEAPSTATE_ZERO_AFTER_INSERT;
if (Debug)
printf ("\n<--- Inserting a leap second...\n");
break;
case LEAPSTATE_ZERO_AFTER_INSERT:
Second = 0;
LeapState = LEAPSTATE_NORMAL;
if (Debug)
printf ("\n<--- Inserted a leap second, now back to zero...\n");
break;
default:
printf ("\n\nLeap second state invalid value of %d, aborting...", LeapState);
exit (-1);
break;
}
if (Second == 0) {
Minute++;
if (Minute >= 60) {
Minute = 0;
Hour++;
}
if (DstSwitchFlag)
{
if ((Year == DstSwitchYear) && (DayOfYear == DstSwitchDayOfYear) && (Hour == DstSwitchHour) && (Minute == DstSwitchMinute))
{
if (DstFlag == 0)
{
Hour++;
DstFlag = 1;
if (OffsetSignBit == 0)
{
if (OffsetOnes == 0x0F)
{
OffsetSignBit = 1;
OffsetOnes = (OffsetHalf == 0) ? 8 : 7;
}
else
OffsetOnes++;
}
else
{
if (OffsetOnes == 0)
{
OffsetSignBit = 0;
OffsetOnes = (OffsetHalf == 0) ? 1 : 0;
}
else
OffsetOnes--;
}
if (Debug)
printf ("\n<--- DST activated, spring ahead an hour, new offset !...\n");
}
else
{
Hour--;
DstFlag = 0;
if (OffsetSignBit == 0)
{
if (OffsetOnes == 0)
{
OffsetSignBit = 1;
OffsetOnes = (OffsetHalf == 0) ? 1 : 0;
}
else
OffsetOnes--;
}
else
{
if (OffsetOnes == 0x0F)
{
OffsetSignBit = 0;
OffsetOnes = (OffsetHalf == 0) ? 8 : 7;
}
else
OffsetOnes++;
}
if (Debug)
printf ("\n<--- DST de-activated, fall back an hour!...\n");
}
DstSwitchFlag = FALSE;
}
}
if (Hour >= 24) {
Hour = Hour % 24;
DayOfYear++;
}
if (DayOfYear >= (Year & 0x3 ? 366 : 367)) {
if (leap) {
WWV_Second(DATA0, RateCorrection);
if (Verbose)
printf("\nLeap!");
leap = 0;
}
DayOfYear = 1;
Year++;
}
if (encode == WWV) {
snprintf(code, sizeof(code),
"%01d%03d%02d%02d%01d", Year / 10,
DayOfYear, Hour, Minute, Year % 10);
if (Verbose)
printf("\n Year = %2.2d, Day of year = %3d, Time = %2.2d:%2.2d:%2.2d, Code = %s",
Year, DayOfYear, Hour, Minute, Second, code);
if ((EnableRateCorrection) || (RemoveCycle) || (AddCycle))
{
printf (", CountOfSecondsSent = %d, TotalCyclesAdded = %d, TotalCyclesRemoved = %d\n", CountOfSecondsSent, TotalCyclesAdded, TotalCyclesRemoved);
if ((CountOfSecondsSent != 0) && ((TotalCyclesAdded != 0) || (TotalCyclesRemoved != 0)))
{
RatioError = ((float) (TotalCyclesAdded - TotalCyclesRemoved)) / (1000.0 * (float) CountOfSecondsSent);
printf (" Adjusted by %2.1f%%, apparent send frequency is %4.2f Hz not %d Hz.\n\n",
RatioError*100.0, (1.0+RatioError)*((float) SetSampleRate), SetSampleRate);
}
}
else
printf ("\n");
ptr = 8;
}
}
if ((Year == LeapYear) && (DayOfYear == LeapDayOfYear) && (Hour == LeapHour) && (Minute == LeapMinute))
{
LeapSecondPending = TRUE;
LeapSecondPolarity = DeleteLeapSecond;
}
else
{
LeapSecondPending = FALSE;
LeapSecondPolarity = FALSE;
}
if ((Year == DstSwitchPendingYear) && (DayOfYear == DstSwitchPendingDayOfYear) &&
(Hour == DstSwitchPendingHour) && (Minute == DstSwitchPendingMinute))
{
DstPendingFlag = TRUE;
}
else
{
DstPendingFlag = FALSE;
}
StraightBinarySeconds = Second + (Minute * SECONDS_PER_MINUTE) + (Hour * SECONDS_PER_HOUR);
if (encode == IRIG) {
if (IrigIncludeIeee)
{
if ((OffsetOnes == 0) && (OffsetHalf == 0))
OffsetSignBit = 0;
ControlFunctions = (LeapSecondPending == 0 ? 0x00000 : 0x00001) | (LeapSecondPolarity == 0 ? 0x00000 : 0x00002)
| (DstPendingFlag == 0 ? 0x00000 : 0x00004) | (DstFlag == 0 ? 0x00000 : 0x00008)
| (OffsetSignBit == 0 ? 0x00000 : 0x00010) | ((OffsetOnes & 0x0F) << 5) | (OffsetHalf == 0 ? 0x00000 : 0x00200)
| ((TimeQuality & 0x0F) << 10);
}
else
ControlFunctions = 0;
if (IrigIncludeYear) {
snprintf(ParityString, sizeof(ParityString),
"%04X%02d%04d%02d%02d%02d",
ControlFunctions & 0x7FFF, Year,
DayOfYear, Hour, Minute, Second);
} else {
snprintf(ParityString, sizeof(ParityString),
"%04X%02d%04d%02d%02d%02d",
ControlFunctions & 0x7FFF,
0, DayOfYear, Hour, Minute, Second);
}
if (IrigIncludeIeee)
{
ParitySum = 0;
for (StringPointer=ParityString; *StringPointer!=NUL; StringPointer++)
{
switch (toupper(*StringPointer))
{
case '1':
case '2':
case '4':
case '8':
ParitySum += 1;
break;
case '3':
case '5':
case '6':
case '9':
case 'A':
case 'C':
ParitySum += 2;
break;
case '7':
case 'B':
case 'D':
case 'E':
ParitySum += 3;
break;
case 'F':
ParitySum += 4;
break;
}
}
if ((ParitySum & 0x01) == 0x01)
ParityValue = 0x01;
else
ParityValue = 0;
}
else
ParityValue = 0;
ControlFunctions |= ((ParityValue & 0x01) << 14);
if (IrigIncludeYear) {
snprintf(code, sizeof(code),
"%05X%05X%02d%04d%02d%02d%02d",
StraightBinarySeconds,
ControlFunctions, Year, DayOfYear,
Hour, Minute, Second);
} else {
snprintf(code, sizeof(code),
"%05X%05X%02d%04d%02d%02d%02d",
StraightBinarySeconds,
ControlFunctions, 0, DayOfYear,
Hour, Minute, Second);
}
if (Debug)
printf("\nCode string: %s, ParityString = %s, ParitySum = 0x%2.2X, ParityValue = %d, DstFlag = %d...\n", code, ParityString, ParitySum, ParityValue, DstFlag);
ptr = strlen(code)-1;
OldPtr = 0;
}
switch (encode) {
case IRIG:
OutputDataString[0] = '\0';
for (BitNumber = 0; BitNumber < 100; BitNumber++) {
FrameNumber = (BitNumber/10) + 1;
switch (FrameNumber)
{
case 1:
sw = progz[BitNumber % 10].sw;
arg = progz[BitNumber % 10].arg;
break;
case 2:
case 3:
case 4:
case 5:
case 6:
sw = progy[BitNumber % 10].sw;
arg = progy[BitNumber % 10].arg;
break;
case 7:
sw = progw[BitNumber % 10].sw;
arg = progw[BitNumber % 10].arg;
break;
case 8:
sw = progv[BitNumber % 10].sw;
arg = progv[BitNumber % 10].arg;
break;
case 9:
sw = progw[BitNumber % 10].sw;
arg = progw[BitNumber % 10].arg;
break;
case 10:
sw = progu[BitNumber % 10].sw;
arg = progu[BitNumber % 10].arg;
break;
default:
printf ("\n\nUnexpected value of FrameNumber = %d, cannot parse, aborting...\n\n", FrameNumber);
exit (-1);
break;
}
switch(sw) {
case DECC:
ptr--;
case COEF:
AsciiValue = toupper(code[ptr]);
HexValue = isdigit(AsciiValue) ? AsciiValue - '0' : (AsciiValue - 'A')+10;
if ((FrameNumber == 5) && ((BitNumber % 10) > 1))
{
if (RateCorrection < 0)
{ if ((HexValue & arg) != 0)
{
if (Unmodulated)
{
poop(M5, 1000, HIGH, UnmodulatedInverted);
poop(M5-1, 1000, LOW, UnmodulatedInverted);
TotalCyclesRemoved += 1;
}
else
{
peep(M5, 1000, HIGH);
peep(M5-1, 1000, LOW);
TotalCyclesRemoved += 1;
}
strlcat(OutputDataString, "x", OUTPUT_DATA_STRING_LENGTH);
}
else
{
if (Unmodulated)
{
poop(M2, 1000, HIGH, UnmodulatedInverted);
poop(M8-1, 1000, LOW, UnmodulatedInverted);
TotalCyclesRemoved += 1;
}
else
{
peep(M2, 1000, HIGH);
peep(M8-1, 1000, LOW);
TotalCyclesRemoved += 1;
}
strlcat(OutputDataString, "o", OUTPUT_DATA_STRING_LENGTH);
}
} else
{ if (RateCorrection > 0)
{ if ((HexValue & arg) != 0)
{
if (Unmodulated)
{
poop(M5, 1000, HIGH, UnmodulatedInverted);
poop(M5+1, 1000, LOW, UnmodulatedInverted);
TotalCyclesAdded += 1;
}
else
{
peep(M5, 1000, HIGH);
peep(M5+1, 1000, LOW);
TotalCyclesAdded += 1;
}
strlcat(OutputDataString, "+", OUTPUT_DATA_STRING_LENGTH);
}
else
{
if (Unmodulated)
{
poop(M2, 1000, HIGH, UnmodulatedInverted);
poop(M8+1, 1000, LOW, UnmodulatedInverted);
TotalCyclesAdded += 1;
}
else
{
peep(M2, 1000, HIGH);
peep(M8+1, 1000, LOW);
TotalCyclesAdded += 1;
}
strlcat(OutputDataString, "*", OUTPUT_DATA_STRING_LENGTH);
}
} else
{ if ((HexValue & arg) != 0)
{
if (Unmodulated)
{
poop(M5, 1000, HIGH, UnmodulatedInverted);
poop(M5, 1000, LOW, UnmodulatedInverted);
}
else
{
peep(M5, 1000, HIGH);
peep(M5, 1000, LOW);
}
strlcat(OutputDataString, "1", OUTPUT_DATA_STRING_LENGTH);
}
else
{
if (Unmodulated)
{
poop(M2, 1000, HIGH, UnmodulatedInverted);
poop(M8, 1000, LOW, UnmodulatedInverted);
}
else
{
peep(M2, 1000, HIGH);
peep(M8, 1000, LOW);
}
strlcat(OutputDataString, "0", OUTPUT_DATA_STRING_LENGTH);
}
} } } else
{ if ((HexValue & arg) != 0)
{
if (Unmodulated)
{
poop(M5, 1000, HIGH, UnmodulatedInverted);
poop(M5, 1000, LOW, UnmodulatedInverted);
}
else
{
peep(M5, 1000, HIGH);
peep(M5, 1000, LOW);
}
strlcat(OutputDataString, "1", OUTPUT_DATA_STRING_LENGTH);
}
else
{
if (Unmodulated)
{
poop(M2, 1000, HIGH, UnmodulatedInverted);
poop(M8, 1000, LOW, UnmodulatedInverted);
}
else
{
peep(M2, 1000, HIGH);
peep(M8, 1000, LOW);
}
strlcat(OutputDataString, "0", OUTPUT_DATA_STRING_LENGTH);
}
} break;
case DECZ:
ptr--;
if (Unmodulated)
{
poop(M2, 1000, HIGH, UnmodulatedInverted);
poop(M8, 1000, LOW, UnmodulatedInverted);
}
else
{
peep(M2, 1000, HIGH);
peep(M8, 1000, LOW);
}
strlcat(OutputDataString, "-", OUTPUT_DATA_STRING_LENGTH);
break;
case DEC:
ptr--;
case NODEC:
case MIN:
if (Unmodulated)
{
poop(arg, 1000, HIGH, UnmodulatedInverted);
poop(10 - arg, 1000, LOW, UnmodulatedInverted);
}
else
{
peep(arg, 1000, HIGH);
peep(10 - arg, 1000, LOW);
}
strlcat(OutputDataString, ".", OUTPUT_DATA_STRING_LENGTH);
break;
default:
printf ("\n\nUnknown state machine value \"%d\", unable to continue, aborting...\n\n", sw);
exit (-1);
break;
}
if (ptr < 0)
break;
}
ReverseString ( OutputDataString );
if (Verbose)
{
printf("%s", OutputDataString);
if (RateCorrection > 0)
printf(" fast\n");
else
{
if (RateCorrection < 0)
printf (" slow\n");
else
printf ("\n");
}
}
break;
case WWV:
sw = progx[Second].sw;
arg = progx[Second].arg;
switch(sw) {
case DATA:
WWV_Second(arg, RateCorrection);
if (Verbose)
{
if (arg == DATA0)
printf ("0");
else
{
if (arg == DATA1)
printf ("1");
else
{
if (arg == PI)
printf ("P");
else
printf ("?");
}
}
}
break;
case DATAX:
WWV_SecondNoTick(arg, RateCorrection);
if (Verbose)
{
if (arg == DATA0)
printf ("0");
else
{
if (arg == DATA1)
printf ("1");
else
{
if (arg == PI)
printf ("P");
else
printf ("?");
}
}
}
break;
case COEF:
if (code[ptr] & arg) {
WWV_Second(DATA1, RateCorrection);
if (Verbose)
printf("1");
} else {
WWV_Second(DATA0, RateCorrection);
if (Verbose)
printf("0");
}
break;
case LEAP:
if (leap) {
WWV_Second(DATA1, RateCorrection);
if (Verbose)
printf("L");
} else {
WWV_Second(DATA0, RateCorrection);
if (Verbose)
printf("0");
}
break;
case DEC:
ptr--;
WWV_Second(arg, RateCorrection);
if (Verbose)
{
if (arg == DATA0)
printf ("0");
else
{
if (arg == DATA1)
printf ("1");
else
{
if (arg == PI)
printf ("P");
else
printf ("?");
}
}
}
break;
case DECX:
ptr--;
WWV_SecondNoTick(arg, RateCorrection);
if (Verbose)
{
if (arg == DATA0)
printf ("0");
else
{
if (arg == DATA1)
printf ("1");
else
{
if (arg == PI)
printf ("P");
else
printf ("?");
}
}
}
break;
case MIN:
if (Minute == 0)
{
peep(arg, HourTone, HIGH);
if (RateCorrection < 0)
{
peep( 990 - arg, HourTone, OFF);
TotalCyclesRemoved += 10;
if (Debug)
printf ("\n* Shorter Second: ");
}
else
{
if (RateCorrection > 0)
{
peep(1010 - arg, HourTone, OFF);
TotalCyclesAdded += 10;
if (Debug)
printf ("\n* Longer Second: ");
}
else
{
peep(1000 - arg, HourTone, OFF);
}
}
if (Verbose)
printf("H");
}
else
{
peep(arg, tone, HIGH);
if (RateCorrection < 0)
{
peep( 990 - arg, tone, OFF);
TotalCyclesRemoved += 10;
if (Debug)
printf ("\n* Shorter Second: ");
}
else
{
if (RateCorrection > 0)
{
peep(1010 - arg, tone, OFF);
TotalCyclesAdded += 10;
if (Debug)
printf ("\n* Longer Second: ");
}
else
{
peep(1000 - arg, tone, OFF);
}
}
if (Verbose)
printf("M");
}
break;
case DUT1:
if (dut1 & arg)
{
WWV_Second(DATA1, RateCorrection);
if (Verbose)
printf("1");
}
else
{
WWV_Second(DATA0, RateCorrection);
if (Verbose)
printf("0");
}
break;
case DST1:
ptr--;
if (DstFlag)
{
WWV_Second(DATA1, RateCorrection);
if (Verbose)
printf("1");
}
else
{
WWV_Second(DATA0, RateCorrection);
if (Verbose)
printf("0");
}
break;
case DST2:
if (DstFlag)
{
WWV_Second(DATA1, RateCorrection);
if (Verbose)
printf("1");
}
else
{
WWV_Second(DATA0, RateCorrection);
if (Verbose)
printf("0");
}
break;
}
}
if (EnableRateCorrection)
{
SecondsRunningSimulationTime++;
gettimeofday(&TimeValue, NULL);
NowRealTime = TimeValue.tv_sec;
if (NowRealTime >= BaseRealTime) {
SecondsRunningRealTime = (unsigned) (NowRealTime - BaseRealTime);
SecondsRunningDifference = SecondsRunningSimulationTime - SecondsRunningRealTime;
if (Debug)
{
printf ("> NowRealTime = 0x%8.8X, BaseRealtime = 0x%8.8X, SecondsRunningRealTime = 0x%8.8X, SecondsRunningSimulationTime = 0x%8.8X.\n",
(unsigned) NowRealTime, (unsigned) BaseRealTime, SecondsRunningRealTime, SecondsRunningSimulationTime);
printf ("> SecondsRunningDifference = 0x%8.8X, ExpectedRunningDifference = 0x%8.8X.\n",
SecondsRunningDifference, ExpectedRunningDifference);
}
if (SecondsRunningSimulationTime > RUN_BEFORE_STABILITY_CHECK)
{
if (StabilityCount < MINIMUM_STABILITY_COUNT)
{
if (StabilityCount == 0)
{
ExpectedRunningDifference = SecondsRunningDifference;
StabilityCount++;
if (Debug)
printf ("> Starting stability check.\n");
}
else
{ if ((ExpectedRunningDifference+INITIAL_STABILITY_BAND > SecondsRunningDifference)
&& (ExpectedRunningDifference-INITIAL_STABILITY_BAND < SecondsRunningDifference))
{ StabilityCount++;
if (Debug)
printf ("> StabilityCount = %d.\n", StabilityCount);
}
else
{ StabilityCount = 0;
if (Debug)
printf ("> Out of stability band, start over.\n");
}
} } else
{ if (AddCycle)
{
if (ExpectedRunningDifference >= SecondsRunningDifference)
{
if (Debug)
printf ("> Was adding cycles, ExpectedRunningDifference >= SecondsRunningDifference, can stop it now.\n");
AddCycle = FALSE;
RemoveCycle = FALSE;
}
else
{
if (Debug)
printf ("> Was adding cycles, not done yet.\n");
}
}
else
{
if (RemoveCycle)
{
if (ExpectedRunningDifference <= SecondsRunningDifference)
{
if (Debug)
printf ("> Was removing cycles, ExpectedRunningDifference <= SecondsRunningDifference, can stop it now.\n");
AddCycle = FALSE;
RemoveCycle = FALSE;
}
else
{
if (Debug)
printf ("> Was removing cycles, not done yet.\n");
}
}
else
{
if ((ExpectedRunningDifference+RUNNING_STABILITY_BAND > SecondsRunningDifference)
&& (ExpectedRunningDifference-RUNNING_STABILITY_BAND < SecondsRunningDifference))
{ if (Debug)
printf ("> All is well, within tolerances.\n");
}
else
{ if (ExpectedRunningDifference > SecondsRunningDifference)
{
if (Debug)
printf ("> ExpectedRunningDifference > SecondsRunningDifference, running behind real time.\n");
AddCycle = FALSE;
RemoveCycle = TRUE;
}
else
{ if (ExpectedRunningDifference < SecondsRunningDifference)
{
if (Debug)
printf ("> ExpectedRunningDifference < SecondsRunningDifference, running ahead of real time.\n");
AddCycle = TRUE;
RemoveCycle = FALSE;
}
else
{
if (Debug)
printf ("> Oops, outside tolerances, but doesn't fit the profiles, how can this be?\n");
}
} } } } } } } else
{
if (Debug)
printf ("> Hmm, time going backwards?\n");
}
}
fflush (stdout);
}
printf ("\n\n>> Completed %d seconds, exiting...\n\n", SecondsToSend);
return (0);
}
void WWV_Second(
int code,
int Rate
)
{
peep(5, tone, HIGH);
peep(25, tone, OFF);
peep(code - 30, 100, LOW);
if (Rate < 0)
{
peep( 990 - code, 100, OFF);
TotalCyclesRemoved += 10;
if (Debug)
printf ("\n* Shorter Second: ");
}
else
{
if (Rate > 0)
{
peep(1010 - code, 100, OFF);
TotalCyclesAdded += 10;
if (Debug)
printf ("\n* Longer Second: ");
}
else
peep(1000 - code, 100, OFF);
}
}
void WWV_SecondNoTick(
int code,
int Rate
)
{
peep(30, tone, OFF);
peep(code - 30, 100, LOW);
if (Rate < 0)
{
peep( 990 - code, 100, OFF);
TotalCyclesRemoved += 10;
if (Debug)
printf ("\n* Shorter Second: ");
}
else
{
if (Rate > 0)
{
peep(1010 - code, 100, OFF);
TotalCyclesAdded += 10;
if (Debug)
printf ("\n* Longer Second: ");
}
else
peep(1000 - code, 100, OFF);
}
}
void peep(
int pulse,
int freq,
int amp
)
{
int increm;
int i, j;
if (amp == OFF || freq == 0)
increm = 10;
else
increm = freq / 100;
j = 0;
for (i = 0 ; i < pulse * 8; i++) {
switch (amp) {
case HIGH:
buffer[bufcnt++] = ~c6000[j];
break;
case LOW:
buffer[bufcnt++] = ~c3000[j];
break;
default:
buffer[bufcnt++] = ~0;
}
if (bufcnt >= BUFLNG) {
write(fd, buffer, BUFLNG);
bufcnt = 0;
}
j = (j + increm) % 80;
}
}
void poop(
int pulse,
int freq,
int amp,
int inverted
)
{
int increm;
int i, j;
if (amp == OFF || freq == 0)
increm = 10;
else
increm = freq / 100;
j = 0;
for (i = 0 ; i < pulse * 8; i++) {
switch (amp) {
case HIGH:
if (inverted)
buffer[bufcnt++] = ~u3000[j];
else
buffer[bufcnt++] = ~u6000[j];
break;
case LOW:
if (inverted)
buffer[bufcnt++] = ~u6000[j];
else
buffer[bufcnt++] = ~u3000[j];
break;
default:
buffer[bufcnt++] = ~0;
}
if (bufcnt >= BUFLNG) {
write(fd, buffer, BUFLNG);
bufcnt = 0;
}
j = (j + increm) % 80;
}
}
void delay (
int Delay
)
{
int samples;
samples = Delay;
memset(buffer, 0, BUFLNG);
while (samples >= BUFLNG) {
write(fd, buffer, BUFLNG);
samples -= BUFLNG;
}
write(fd, buffer, samples);
}
int
ConvertMonthDayToDayOfYear (int YearValue, int MonthValue, int DayOfMonthValue)
{
int ReturnValue;
int LeapYear;
int MonthCounter;
int DaysInMonth[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
LeapYear = FALSE;
if ((YearValue % 4) == 0)
{
if ((YearValue % 100) == 0)
{
if ((YearValue % 400) == 0)
{
LeapYear = TRUE;
}
}
else
{
LeapYear = TRUE;
}
}
if (Debug)
printf ("\nConvertMonthDayToDayOfYear(): Year %d %s a leap year.\n", YearValue+2000, LeapYear ? "is" : "is not");
ReturnValue = DayOfMonthValue;
for (MonthCounter=1; MonthCounter<MonthValue; MonthCounter++)
{
ReturnValue += DaysInMonth [ MonthCounter - 1 ];
}
if ((LeapYear) && (MonthValue > 2))
{
ReturnValue++;
}
if (Debug)
printf ("\nConvertMonthDayToDayOfYear(): %4.4d-%2.2d-%2.2d represents day %3d of year.\n",
YearValue+2000, MonthValue, DayOfMonthValue, ReturnValue);
return (ReturnValue);
}
void
Help ( void )
{
printf ("\n\nTime Code Generation - IRIG-B or WWV, v%d.%d, %s dmw", VERSION, ISSUE, ISSUE_DATE);
printf ("\n\nRCS Info:");
printf ( "\n $Header: /home/dmw/src/IRIG_generation/ntp-4.2.2p3/util/RCS/tg.c,v 1.28 2007/02/12 23:57:45 dmw Exp $");
printf ("\n\nUsage: %s [option]*", CommandName);
printf ("\n\nOptions: -a device_name Output audio device name (default /dev/audio)");
printf ( "\n -b yymmddhhmm Remove leap second at end of minute specified");
printf ( "\n -c seconds_to_send Number of seconds to send (default 0 = forever)");
printf ( "\n -d Start with IEEE 1344 DST active");
printf ( "\n -f format_type i = Modulated IRIG-B 1998 (no year coded)");
printf ( "\n 2 = Modulated IRIG-B 2002 (year coded)");
printf ( "\n 3 = Modulated IRIG-B w/IEEE 1344 (year & control funcs) (default)");
printf ( "\n 4 = Unmodulated IRIG-B w/IEEE 1344 (year & control funcs)");
printf ( "\n 5 = Inverted unmodulated IRIG-B w/IEEE 1344 (year & control funcs)");
printf ( "\n w = WWV(H)");
printf ( "\n -g yymmddhhmm Switch into/out of DST at beginning of minute specified");
printf ( "\n -i yymmddhhmm Insert leap second at end of minute specified");
printf ( "\n -j Disable time rate correction against system clock (default enabled)");
printf ( "\n -k nn Force rate correction for testing (+1 = add cycle, -1 = remove cycle)");
printf ( "\n -l time_offset Set offset of time sent to UTC as per computer, +/- float hours");
printf ( "\n -o time_offset Set IEEE 1344 time offset, +/-, to 0.5 hour (default 0)");
printf ( "\n -q quality_code_hex Set IEEE 1344 quality code (default 0)");
printf ( "\n -r sample_rate Audio sample rate (default 8000)");
printf ( "\n -s Set leap warning bit (WWV[H] only)");
printf ( "\n -t sync_frequency WWV(H) on-time pulse tone frequency (default 1200)");
printf ( "\n -u DUT1_offset Set WWV(H) DUT1 offset -7 to +7 (default 0)");
#ifndef HAVE_SYS_SOUNDCARD_H
printf ( "\n -v initial_output_level Set initial output level (default %d, must be 0 to 255)", AUDIO_MAX_GAIN/8);
#endif
printf ( "\n -x Turn off verbose output (default on)");
printf ( "\n -y yymmddhhmmss Set initial date and time as specified (default system time)");
printf ("\n\nThis software licenced under the GPL, modifications performed 2006 & 2007 by Dean Weiten");
printf ( "\nContact: Dean Weiten, Norscan Instruments Ltd., Winnipeg, MB, Canada, ph (204)-233-9138, E-mail dmw@norscan.com");
printf ("\n\n");
}
void
ReverseString(char *str)
{
int StringLength;
int IndexCounter;
int CentreOfString;
char TemporaryCharacter;
StringLength = strlen(str);
CentreOfString = (StringLength/2)+1;
for (IndexCounter = StringLength; IndexCounter >= CentreOfString; IndexCounter--)
{
TemporaryCharacter = str[IndexCounter-1];
str[IndexCounter-1] = str[StringLength-IndexCounter];
str[StringLength-IndexCounter] = TemporaryCharacter;
}
}