TeensyKeyer side tone latencey measured

175 views
Skip to first unread message

"Christoph v. Wüllen"

unread,
Mar 5, 2021, 10:34:53 AM3/5/21
to herme...@googlegroups.com, Steve Haynal
Hi all,

there was a discussion about the side tone latency with the CW
keyer. I saw speculation but no measurement so here it is:

I triggered a two-channel DSO with
the rising flank of the CW key signal (red trace), and measured at the
headphone output of the AudioShield (blue trace).

The outcome is (24 wpm, dot paddle, 50-msec dits and 50-msec pauses)


and increasing horizonal resolution to 5 msec/grid unit


Once nicely sees the side tone (800 Hz, 4 waves per 5 msec) and how it is shaped at
the beginning and the end (the width of the ramp is only 2.7 msec). But most notably,
one clearly sees that the audio only lags 5 msec behind. 5 msec is the time a sound
wave need to travel from a speaker 1.7m away to your ear, the MAXIMUM distance a
signal travels through your nevers during this time is 0.5 meter (for most nerve fibers
much less), so I think this delay won’t disturb anyone.

Yours,

Christoph DL1YCF.

Steve Haynal

unread,
Mar 6, 2021, 4:03:00 PM3/6/21
to Hermes-Lite
Hi Christoph,

Thanks for the measurement. I was going to make similar measurements after the audio buffers were reduced to 32 samples, but even with the 128 sample buffers the latency looks good. Is the key signal measured at the key input, or is this a key output generated by the Teensy? I am curious how much latency key debounce is adding, if any.

The target I have in mind is 3ms, as that was once mentioned on this list. But I agree with you that 5ms won't be humanly noticeable, even 10ms is hard to notice.

73,

Steve
kf7o

Roger Critchlow

unread,
Mar 8, 2021, 7:33:49 PM3/8/21
to Steve Haynal, Hermes-Lite
Here's another latency measurement.  

This shows two channels of audio coming from the Teensy over usb into Jack and out to x42-scope.  The upper trace is audio from the headset plugged into the Teensy, with the microphone balanced on the base of the paddle.  The ripples are the click and bounce of the contacts closing to initiate a dit.  The lower trace is the start of the sidetone generated for the dit on the Teensy based keyer.  The horizontal grid is 500 µs, triggered on channel 1 rising.  There's no explicit debouncing being done, the iambic keyer responds to the first touch and ignores the bounces while it's waiting for the dit to complete.  

-- 73 -- rec -- ad5dz --

--
You received this message because you are subscribed to the Google Groups "Hermes-Lite" group.
To unsubscribe from this group and stop receiving emails from it, send an email to hermes-lite...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/hermes-lite/e96c56bc-8bed-4aeb-86d4-660e6957d3dfn%40googlegroups.com.
Screenshot from 2021-03-08 18-01-21.png

Graeme Jury

unread,
Mar 8, 2021, 9:12:54 PM3/8/21
to herme...@googlegroups.com
Hi Roger,

Progress! Picking up on your debouncing comments, I have had my head down on this and came to the conclusion that for the paddle inputs there was hugely unlikely to be any glitches and any key down signal would be genuine. The dot or dash timing would for even the fastest senders be greater than the debounce interval for a key/paddle and a debounce routine would not be necessary if the dot/dash timing was used. For the other system key presses of course a debounce algorithm would need to be used in the normal way. As the key/paddle algorithm would be so trivial, I think that it would be best to implement them as two separate procedures. I use a shift register algorithm to detect the completion of bounces for normal buttons or rotary encoders.

73, Graeme zl2apv

Steve Haynal

unread,
Mar 9, 2021, 2:19:13 AM3/9/21
to Hermes-Lite
Hi Group,

Below is a measurement from my setup. The top trace is the "dah" paddle. Closing the switch grounds the input. This trace captures a bounce, which I saw maybe 10% of the time. You can see that due to the capacitor on the Teensy input (I have the same capacitor as the k3ng schematics), the bounce never reaches the full 3.3V. I can see that for a keyer debouncing is of little use, but what about for the straight key input?

Sidetone starts less than 3.5ms after the paddle switch. It is hard to see the actual start as it is very low initial amplitude. Full tone is reached by 4.5ms. This is with an audio buffer length of 64 samples at 48kHz (1.3ms), signal ramp of 2.9ms and i2s latency of less than 1ms. So the number look about right.

DS1104Z_DS1ZA171710608_2021-03-08_21.59.10.png


The capture below illustrates key-to-ear and key-to-rf latency. The bottom trace is the CW RF signal into a dummy load. This is with Quisk setup to key on a midi input. RF starts 20 to 25 ms after the paddle switch. Software can improve this, for example Alan reports 18ms with SparkSDR.  This latency will not matter, even for psuedo QSK, as the TX RF and RX RF are just shifted slightly in time from the users perspective. There will be some who don't believe me, and so this device will also support an optional direct key line from keyer to HL2 when used locally.

DS1104Z_DS1ZA171710608_2021-03-08_22.49.18.png


73,

Steve
kf7o

"Christoph v. Wüllen"

unread,
Mar 9, 2021, 10:53:33 AM3/9/21
to Steve Haynal, herme...@googlegroups.com
Here are some further notes on the keyer latency:


a) Debouncing
=============

for a normal keyer debouncing is of little importance.
Once a dot/dash has been started, the state of the input
line does not matter (and probably is not even looked at)
for at least 10 mseconds. For a straight key once needs
debouncing.

In my keyer, I do not want any delays due to debouncing,
so the code is (actual is the time of the current loop())

if (actual > DebounceTimeForThisPin) {
i=digitalRead(ThisPin);
if (i != StateOfThisPin) {
DebounceTimeForThisPin = actual+10;
StateOfThisPin=i:
}
}

Which simply means that the first 10 millisecs after a state
change, the input line is not even looked at.

b) key-to-ear Delay
===================

Steve has measured half the delay I have with an audio buffer
of half the size (which makes sense). In my previous post
I have displayed the audio vs. the keyer state, and have been
asked about the audio vs. the key input line.

The answer is simply: the picture is the same, since the
key-out follows the paddle contact closure with less than
a milli-second. This might depend on the programming of
the keyer. My keyer is a state machine where almost nothing
is done in one „heart beat“, so key-to-keyer latencies can be
ignored. The more „features“ a software has, the more the
microcontroller might have to finish before it can take
core of the input.

d) Which Key-to-Ear delay do we want
====================================

For me at least (not an un-experienced CW op),
at a speed of 24 wpm the key-to-ear delay could go up to
10 msec without affecting my error rate, so I think a delay of
5 msec is good for (almost) everyone.

e) a note on Key-to-RF delay
============================

This mostly depends on how the SDR software works. The short delays
reported on the list can only be realized if the pulses are shaped in the FPGA
and the FPGA extracts and processes the „key down“ info from the incoming IQ data
stream BEFORE it goes into the TX FIFO

Other software (e.g. pihpsdr) explicitly shape the RF pulses in the RF software,
and there the key-to-RF delay must be much larger since the pulse
must „walk“ all the way through the TX FIFO which ideally is
half-filled (this is, about 1500-2000 samples or 30-40 msec). So I suspect
the key-to-RF delay will be longer by about this amount compared to what
has been reported here.

Several people (including me) consider this immaterial. The speed of the
TX/RX and RX/TX switching is also limited by slew-up/down times etc.
There are people out there which want to minimize key-to-RF delay
but I think for those the ideal setup is

microcontroller —> opto coupler —> HL2 CW jack


Yours Christoph DL1YCF.




Roger Critchlow

unread,
Mar 9, 2021, 2:40:03 PM3/9/21
to Christoph v. Wüllen, Steve Haynal, Hermes-Lite
Christoph's points are very much on target.

Most of the delays we're reporting are beyond perception.  But latency is a cumulative problem, so initially imperceptible delays will be compounded as the signal travels through the processing pipeline.  Some SDR's push a keyed CW tone through the SSB voice processing pipeline, which is a waste of effort, because it doesn't improve the tone in any way, and it introduces filter delays, adding on to the initial latency.  So you do the best you can to introduce as little latency at each step as you can.

The straight key debouncing that Christoph describes is very good.  The hasak keyer does the same thing, but it's done in the key ramp.  The key ramp initiates a ramp up or down whenever it detects a change from an established state, and it ignores any further changes in the key line until the ramp is completed.  You can tune the key ramp to match the straight key's physics by adjusting the length of the ramp time.  And, no, you can't hear the tiny differences in ramp lengths in the local sidetone, they all sound pretty much the same until you get so steep that the codec's output stages start key clicking, or you get so shallow that the key pulses are too soft to distinguish.  RF stages may respond differently than the codec or your ears.

Here's another measurement.  Same setup as the last, but at 1ms horizontal.  First trace is the microphone audio from the key contact.  Second trace is the sidetone generated by the hasak keyer.  Third trace is sidetone from https://github.com/recri/keyer, a MIDI triggered iambic keyer running inside the Jack process loop, being triggered by the same paddle closure transmitted as a MIDI note on event.   The MIDI note event is being generated in the keyer loop() by polling the pin state and sending a note event for each transition detected, and calling usbMIDI.send_now() to flush the event as soon as possible.  The Teensy keyer is running at 44100 with the orignal 128 sample buffers.  Jack is sycnhronized to the Teensy with 1024 samples per buffer. There are no caps on the key switch lines.  

If you key an IQ tone on the Teensy, its samples will reach an SDR on the PC as soon as the sound of the key closure would.  If you send MIDI, the SDR should be able to generate samples about 2-3ms later than the click of the contacts.   What you get in real time will depend on the sample buffering latencies.

-- 73 -- rec -- ad5dz --

Screenshot from 2021-03-09 12-45-16.png

--
You received this message because you are subscribed to the Google Groups "Hermes-Lite" group.
To unsubscribe from this group and stop receiving emails from it, send an email to hermes-lite...@googlegroups.com.

Roger Critchlow

unread,
Mar 10, 2021, 11:10:24 AM3/10/21
to Christoph v. Wüllen, Steve Haynal, Hermes-Lite
Christoph asked me why I thought the squiggles on the audio were the sound of the contacts, which turns out to be a good question.

Here's a trace with the microphone audio above and the left paddle closure below.
Screenshot from 2021-03-09 23-43-23.png
So the paddle closure happens before the squiggles start.   The cheap microphone, even 
though it's only a few mm from the paddle contact, is not registering the initial
closing of the contacts, it's registering an aftershock.  

And my logical streams are active low, because the bit pattern for 1 as a 32 bit fixed, is the
bit pattern for -1 as a 16 bit fixed.

And a trace with the left paddle closure above and the sidetone below.
Screenshot from 2021-03-09 23-40-39.png
So the left paddle closure appears to be about a half ms before the noise of the click and the 
start of the sidetone.  

But the flat part of the sidetone between the paddle closure isn't really flat, it's just too close to zero at this scale.
If we amp up the sidetone by 20dB and spread the horizontal scale we can see that the start of the ramp gets 
closer to the paddle closure.  Samples at 48000 are 20.8 µs so most of what the scope is drawing is interpolated,
and it's a Simple Scope so I can't turn the interpolation off.   But I expect the first non-zero sidetone sample is
only 20.8 or 41.6 µs after the paddle closure.

Screenshot from 2021-03-10 10-45-40.png

And I also learned that Ctrlr Program > Send Snapshot menu entry sends the current values of all the
controls in the panel to the keyer, making it easy to synchronize the panel to the keyer.  There's also 
Program > Program Snapshot which saves the current settings in the Panel > Midi Library in a form
you can rename, copy, and paste back into the panel.

-- 73 -- rec -- ad5dz --

Steve Haynal

unread,
Mar 11, 2021, 11:09:00 PM3/11/21
to Hermes-Lite
Hi All,

I also like Christoph's straight key debounce - early detect of on or off, but then delayed acceptance of change of state.

The snapshot feature of Ctrlr does sound useful.

I have been very busy with my day job this week and have done only a little coding. I hope to commit some changes this weekend.

73,

Steve
kf7o
Reply all
Reply to author
Forward
0 new messages