Subject: non-PPS clock signals (CHU)
To: Ken Hornstein <kenh@cmf.nrl.navy.mil>
From: Jonathan Stone <jonathan@DSG.Stanford.EDU>
List: tech-kern
Date: 03/27/1998 14:50:36
OK, just a reminder: this thread is NOT a discussion about adding
pulse-per-second (PPS) to the kernel: its a blue-sky session about
getting NTP to work better on non-PPS clocks, like the cheap,
hobbyist-level clocks that a novice can bang together from a
breadbroad for (according to Ken) $20 or less.  (ken says
the hardest part is finding a source for the 300 baud modem chips!)
It can all be ifdef'ed out and not impact on normal use.  Or
maintained as a private patch.

First, some background, between the dashes, so we're all clear about
what _this_ problem is:

------Start background-----

The CHU signal is a periodic timecode sent
out using standard 300 baud modem signals, in a shortware radio
signal, from a radio station in Canada.  The signal includes something
like ten timecodes per minute, each of about 12 bytes.  The arrival
time of each of those bytes contributes to the clock signal.

The NTP gagdet box has circuitry based aroud a 300 baud modem chip
that decodes the time signal from a radio.  The problem is how to
accurately recover the time from those bytes as they come in, one by
one, at 300 baud.

The traditional solution is to use a line discipline that timestamps
each byte as it recevies it from the hardware driver.  The line
discipline then assembles an entire timesequence and feeds up to the
user-level NTP dameon which parses it and does the NTP magic.

The problem Ken is, in essence, trying to overcome, is the extra
latency due to deferring the upcall to the line discipline to a
software-interrupt routine.  With current NetbSD serial drivers, any
delay gets sandwiched between the arrival of the character and the
actual timestamping.  (We don't even know ye tknow how big this is.)

The idea on the table, from Ken, is to upcall from the hard-interrupt
routine directly into the line-discipline call, to make the interrupt
and the timestamp as cloase together as possible.

------End background-----

My take on this is different:
	1) add a multibyte path from  serial drivers up to
	   the line discipline. We want that anyway, so its going to happen.

	2)  Establish a software convention, that the tty_clk
	    and tty_chu line disciplines always take five-byte
	     ``packets'' from the lower-level serial driver.

	3)  add ioctls to switch the lower-level driver
	    into and out of a mode where it generates the
	     data-byte-plus-timestamp  values.

I think that's all that's really needed here.  it requires the
multibyte path, so until then Ken could experiment with doing the
gross upcall from the hard-interrupt straight into the line
discipline, just to see how much difference it makes, if any.


>It seems like a good first step would be to put the CLK_CHU line
>discipline in place, without any special speed hacks at all, and see
>how well it works.  Then you could decide based on your clock
>accuracy what kind (if any) sort of changes you'd need to do to
>improve things.

Yup.  The code changes from a SunOS-compatible line discipline are
pretty simple if you've done them before. I'd been taking this as
read.


>On the "improve accuracy" front ... it seems that if you put the
>timestamping directly into comintr(), you'd get about the most accurate
>measurment of character time that would be possible, even with a
>special driver (that's assuming I understand the way the interrupt
>system works, and that could be wrong :-/).  Before anyone else says
>anything ... of course this hypothetical code would be appropriately
>#ifdef'd to not affect the normal user in the least bit.  And of course
>you could toggle this on and off via an ioctl() or whatever.  I think
>you could do the same for the MI zs driver fairly easily.

Yup.  In fact you could have the hard-interrupt routine grab each
char, timestamp it, and stuff both the char and each byt eof the
timestamp into the softtty() loop. The problem here is, what happens
if you lose the implicit framing boundaries (character drop, or worse,
overflowing the line-discipline queue).  How does the line discipline
even notice, let alone get back in synch?


With the direct multibyte interface, it should be much easier. 
each serial driver can know about and support a `frame size',
and drop entire `frames' if they dont' fit. This could be used
for SLIP and PPP and mouse and tablet `disciplines', too.