Many client updates

This commit is contained in:
Neale Pickett 2020-05-01 15:07:09 -06:00
parent 56486979a8
commit 3a16ebb7af
3 changed files with 762 additions and 622 deletions

View File

@ -34,7 +34,8 @@
<div class="mdl-layout__drawer"> <div class="mdl-layout__drawer">
<span class="mdl-layout-title">Repeaters</span> <span class="mdl-layout-title">Repeaters</span>
<nav class="mdl-navigation"> <nav class="mdl-navigation">
<a class="mdl-navigation__link" href="?repeater=">1-15 WPM</a> <a class="mdl-navigation__link" href="?repeater=">General Chaos</a>
<a class="mdl-navigation__link" href="?repeater=beg">1-15 WPM</a>
<a class="mdl-navigation__link" href="?repeater=int">16-20 WPM</a> <a class="mdl-navigation__link" href="?repeater=int">16-20 WPM</a>
<a class="mdl-navigation__link" href="?repeater=adv">21-99 WPM</a> <a class="mdl-navigation__link" href="?repeater=adv">21-99 WPM</a>
</nav> </nav>
@ -48,9 +49,7 @@
<div class="flex"> <div class="flex">
<div class="mdl-card mdl-shadow--4dp"> <div class="mdl-card mdl-shadow--4dp">
<div class="mdl-card__title"> <div class="mdl-card__title">
<h2 class="mdl-card__title-text"> <h2 class="mdl-card__title-text">Input</h2>
Input
</h2>
</div> </div>
<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect"> <div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
<div class="mdl-tabs__tab-bar"> <div class="mdl-tabs__tab-bar">
@ -69,7 +68,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<code></code> <kbd>c</kbd> or <kbd>,</kbd> or <kbd>⇧ Shift</kbd>
</td> </td>
</tr> </tr>
</table> </table>
@ -90,10 +89,12 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<code>.</code> or <code>z</code> <kbd>.</kbd> or <kbd>z</kbd>
<br>
right-click for Dah
</td> </td>
<td> <td>
<code>/</code> or <code>x</code> <kbd>/</kbd> or <kbd>x</kbd>
</td> </td>
</tr> </tr>
</table> </table>
@ -117,13 +118,42 @@
<div class="mdl-card mdl-shadow--4dp"> <div class="mdl-card mdl-shadow--4dp">
<div class="mdl-card__title"> <div class="mdl-card__title">
<h2 class="mdl-card__title-text"> <h2 class="mdl-card__title-text">Knobs</h2>
Knobs
</h2>
</div> </div>
<div class="mdl-card__supporting-text"> <div class="mdl-card__supporting-text">
<p>
Dit length (iambic):
<output id="iambic-duration-value"></output>ms
<input
id="iambic-duration"
class="mdl-slider mdl-js-slider"
type="range"
min="40"
max="255"
value="100">
</p>
<p>
Recieve delay:
<output id="rx-delay-value"></output>ms
<input
id="rx-delay"
class="mdl-slider mdl-js-slider"
type="range"
min="0"
max="9999"
value="4000">
</p>
<hr>
<table> <table>
<tbody> <tbody>
<tr>
<td>
Suggested receive delay:
</td>
<td>
<output id="suggested-delay-value">0</output>ms
</td>
</tr>
<tr> <tr>
<td> <td>
Average round-trip time: Average round-trip time:
@ -142,47 +172,23 @@
</tr> </tr>
<tr> <tr>
<td> <td>
Suggested receive delay: Repeater:
</td> </td>
<td> <td>
<output id="suggested-delay-value">0</output>ms <span id="repeater"></span>
</td> </td>
</tr> </tr>
<tr>
</tr>
</tbody> </tbody>
</table> </table>
<hr> <hr>
<p> <p>Errors</p>
Recieve delay: <div id="errors"></div>
<output id="rx-delay-value"></output>ms
<input
id="rx-delay"
class="mdl-slider mdl-js-slider"
type="range"
min="0"
max="5000"
value="400">
</p>
<p>
Dit length (iambic):
<output id="iambic-duration-value"></output>ms
<input
id="iambic-duration"
class="mdl-slider mdl-js-slider"
type="range"
min="40"
max="255"
value="100">
</p>
</div> </div>
</div> </div>
<div class="mdl-card mdl-shadow--4dp"> <div class="mdl-card mdl-shadow--4dp">
<div class="mdl-card__title"> <div class="mdl-card__title">
<h2 class="mdl-card__title-text"> <h2 class="mdl-card__title-text">Code Tree</h2>
Code Tree
</h2>
</div> </div>
<div class="mdl-card__supporting-text"> <div class="mdl-card__supporting-text">
<img src="code-tree.png"> <img src="code-tree.png">
@ -191,9 +197,7 @@
<div class="mdl-card mdl-shadow--4dp"> <div class="mdl-card mdl-shadow--4dp">
<div class="mdl-card__title"> <div class="mdl-card__title">
<h2 class="mdl-card__title-text"> <h2 class="mdl-card__title-text">Vail</h2>
Vail
</h2>
</div> </div>
<div class="mdl-card__supporting-text"> <div class="mdl-card__supporting-text">
<p> <p>
@ -220,6 +224,99 @@
</div> </div>
</div> </div>
<div class="mdl-card mdl-shadow--4dp">
<div class="mdl-card__title">
<h2 class="mdl-card__title-text">How It Works</h2>
</div>
<div class="mdl-card__supporting-text">
<p>
The Internet isn't exactly like radio waves:
it still goes at near the speed of light,
but there are multiple hops between endpoints,
which buffer up transmissions, and multiplex them onto a single uplink connection.
These repeaters (routers)
are also allowed to just drop things if they need to.
It's the responsibility of the communicating parties
to work out whether something needs to be retransmitted.
Because of this,
there's no telling how long it will take for a transmission to get to a destination.
</p>
<p>
Each Vail transmission (packet) consists of:
</p>
<ul>
<li>timestamp (milliseconds since 1 Jan 1970, 00:00:00 in Reykjavík)</li>
<li>transmission duration (milliseconds)</li>
<li>silence duration (milliseconds, optional)</li>
<li>transmission duration (milliseconds, optional)</li>
<li>silence duration (milliseconds, optional)</li>
<li>Repeat as necessary</li>
</ul>
<p>
The repeater does nothing but broadcast everything it gets
to every connected Vail client,
including the one that sent the packet.
When your client gets back the exact same thing it sent,
it compares the current time to the time in the packet.
This is the <i>round-trip time</i>:
the time it takes for a packet to get from your computer to the repeater and back.
</p>
<p>
When the client gets a packet it didn't send,
it adds the <i>receive delay</i> to the timestamp,
and schedules to play the tones and silences in the packet
at that time.
</p>
<p>
By adding the maximum round-trip time to the <i>longest recent transmission</i>
(the length of a dah, hopefully),
your client can make a guess about how much time needs to be added to a received timestamp,
in order to have it play back in the future at the time it comes in.
This is just a guess.
If you're communicating with somebody with a higher round-trip time than you have,
you'll need to raise your receive delay to account for it.
</p>
</div>
</div>
<div class="mdl-card mdl-shadow--4dp">
<div class="mdl-card__title">
<h2 class="mdl-card__title-text">Why do I hear a low tone?</h2>
</div>
<div class="mdl-card__supporting-text">
<p>
This is the "drop tone", and will be accompanied by an error.
</p>
<p>
This means the packet arrived so late, it can't be played in time.
In technical terms: the timestamp of the packet plus the receive delay
is less than the current time.
It can't be scheduled to play, because we can't go back in time.
</p>
<p>
This could be happening for three reasons:
</p>
<ol>
<li>You (the person hearing the drop tone) need a larger receive delay</li>
<li>The receiving computer's clock is in the future (running fast)</li>
<li>The sending computer's clock is in the past (running slow)</li>
</ol>
<p>
Make sure your clock is synced with an Internet time server.
Accurate time is very important to how Vail works.
</p>
</div>
</div>
<div class="mdl-card mdl-shadow--4dp"> <div class="mdl-card mdl-shadow--4dp">
<div class="mdl-card__title"> <div class="mdl-card__title">
<h2 class="mdl-card__title-text">Future plans</h2> <h2 class="mdl-card__title-text">Future plans</h2>

View File

@ -22,6 +22,29 @@
width: 100%; width: 100%;
} }
#errors {
color: rgba(127, 0, 0, .54);
max-height: 5em;
overflow-y: scroll;
}
@keyframes yellow-fade {
0% {background: yellow;}
100% {background: none;}
}
#errors p {
margin: 0;
animation: yellow-fade 2s ease-in 1;
}
kbd {
background-color: #eee;
border: 1px solid #bbb;
border-radius: 3px;
font-size: 9pt;
padding: .1em .6em;
}
code { code {
background-color: #333; background-color: #333;
color: #fff; color: #fff;
@ -31,3 +54,8 @@ code {
img { img {
max-width: 20em; max-width: 20em;
} }
.mdl-card__supporting-text {
max-height: 20em;
overflow-y: scroll;
}

View File

@ -228,6 +228,10 @@ class Vail {
// Listen for slider values // Listen for slider values
this.inputInit("#iambic-duration", e => this.iambic.SetInterval(e.target.value)) this.inputInit("#iambic-duration", e => this.iambic.SetInterval(e.target.value))
this.inputInit("#rx-delay", e => {this.rxDelay = Number(e.target.value)}) this.inputInit("#rx-delay", e => {this.rxDelay = Number(e.target.value)})
// Show what repeater we're on
let repeater = (new URL(location)).searchParams.get("repeater") || "Default"
document.querySelector("#repeater").textContent = repeater
} }
inputInit(selector, func) { inputInit(selector, func) {
@ -247,6 +251,17 @@ class Vail {
element.dispatchEvent(new Event("input")) element.dispatchEvent(new Event("input"))
} }
error(msg) {
let now = new Date()
let e = document.querySelector("#errors")
if (e) {
let p = e.appendChild(document.createElement("p"))
p.innerText = "[" + now.toLocaleTimeString() + "] " + msg
e.scrollTop = e.scrollHeight
}
this.buzzer.ErrorTone()
}
beginTx() { beginTx() {
this.beginTxTime = Date.now() this.beginTxTime = Date.now()
this.buzzer.Buzz(true) this.buzzer.Buzz(true)
@ -320,7 +335,7 @@ class Vail {
let adjustedTxTime = beginTxTime+this.rxDelay let adjustedTxTime = beginTxTime+this.rxDelay
if (adjustedTxTime < now) { if (adjustedTxTime < now) {
this.buzzer.ErrorTone() this.error("Packet requested playback " + (now - adjustedTxTime) + "ms in the past. Increase receive delay!")
return return
} }
@ -353,7 +368,7 @@ class Vail {
event.preventDefault() event.preventDefault()
this.iambic.Key(begin, DAH) this.iambic.Key(begin, DAH)
} }
if ((event.key == "Shift")) { if ((event.code == "KeyC") || (event.code == "Comma") || (event.key == "Shift")) {
event.preventDefault() event.preventDefault()
if (begin) { if (begin) {
this.beginTx() this.beginTx()