iambic more responsive, add MIDI control

This commit is contained in:
Neale Pickett 2020-05-02 13:43:18 +00:00
parent 3a16ebb7af
commit 965630e1ad
1 changed files with 93 additions and 17 deletions

View File

@ -11,8 +11,8 @@ class Iambic {
constructor(beginTxFunc, endTxFunc) { constructor(beginTxFunc, endTxFunc) {
this.beginTxFunc = beginTxFunc this.beginTxFunc = beginTxFunc
this.endTxFunc = endTxFunc this.endTxFunc = endTxFunc
this.interval = null this.intervalDuration = null
this.state = this.stateSpace this.state = this.stateBegin
this.keyState = null this.keyState = null
} }
@ -21,19 +21,30 @@ class Iambic {
* *
* @param {number} duration New interval duration, in ms * @param {number} duration New interval duration, in ms
*/ */
SetInterval(duration) { SetIntervalDuration(duration) {
this.intervalDuration = duration
if (this.interval) {
clearInterval(this.interval) clearInterval(this.interval)
this.interval = setInterval(e => this.pulse(), duration) this.interval = setInterval(e => this.pulse(), duration)
} }
}
// An interval has passed, call whatever the current state function is // An interval has passed, call whatever the current state function is
pulse(event) { pulse(event) {
this.state() this.state()
} }
stateSpace() {
stateBegin() {
if (this.keyState) {
// Don't transmit for one interval. // Don't transmit for one interval.
this.state = this.keyState || this.stateSpace this.state = this.keyState
this.state()
} else {
// No key pressed, go back to sleep.
clearInterval(this.interval)
this.interval = null
}
} }
stateDit() { stateDit() {
// Send a dit // Send a dit
@ -54,8 +65,7 @@ class Iambic {
stateEnd() { stateEnd() {
// Stop sending // Stop sending
this.endTxFunc() this.endTxFunc()
this.state = this.stateSpace this.state = this.stateBegin
this.state()
} }
/** /**
@ -80,6 +90,12 @@ class Iambic {
// Only stop when we've released the right key // Only stop when we've released the right key
this.keyState = null this.keyState = null
} }
// Not pulsing yet? Start right away!
if (! this.interval) {
this.interval = setInterval(e => this.pulse(), this.intervalDuration)
this.pulse()
}
} }
} }
@ -226,12 +242,16 @@ class Vail {
this.buzzer = new Buzzer() this.buzzer = new Buzzer()
// 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.SetIntervalDuration(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 // Show what repeater we're on
let repeater = (new URL(location)).searchParams.get("repeater") || "Default" let repeater = (new URL(location)).searchParams.get("repeater") || "Default"
document.querySelector("#repeater").textContent = repeater document.querySelector("#repeater").textContent = repeater
// Request MIDI access
navigator.requestMIDIAccess()
.then(a => this.midiInit(a))
} }
inputInit(selector, func) { inputInit(selector, func) {
@ -251,6 +271,51 @@ class Vail {
element.dispatchEvent(new Event("input")) element.dispatchEvent(new Event("input"))
} }
midiInit(access) {
this.midiAccess = access
for (let input of this.midiAccess.inputs.values()) {
input.addEventListener("midimessage", e => this.midiMessage(e))
}
this.midiAccess.addEventListener("statechange", e => this.midiStateChange(e))
}
midiStateChange(event) {
if (event.port.connection == "open") {
console.log(event)
event.port.addEventListiner("midimessage", e => this.midiMessage(e))
}
}
midiMessage(event) {
let data = Array.from(event.data)
let begin
switch (Number(data[0])) {
case 0x90:
begin = true
break
case 0x80:
begin = false
break
default:
return
}
switch (data[1] % 12) {
case 0: // C
this.straightKey(begin)
break
case 1: // C#
this.iambic.Key(begin, DIT)
break
case 2: // D
this.iambic.Key(begin, DAH)
break
default:
return
}
}
error(msg) { error(msg) {
let now = new Date() let now = new Date()
let e = document.querySelector("#errors") let e = document.querySelector("#errors")
@ -318,7 +383,14 @@ class Vail {
wsMessage(event) { wsMessage(event) {
let now = Date.now() let now = Date.now()
let jmsg = event.data let jmsg = event.data
let msg = JSON.parse(jmsg) let msg
try {
msg = JSON.parse(jmsg)
}
catch(err) {
console.log(err, msg)
return
}
let beginTxTime = msg[0] let beginTxTime = msg[0]
let durations = msg.slice(1) let durations = msg.slice(1)
@ -352,6 +424,14 @@ class Vail {
} }
} }
straightKey(begin) {
if (begin) {
this.beginTx()
} else {
this.endTx()
}
}
key(event) { key(event) {
if (event.repeat) { if (event.repeat) {
// Ignore key repeats generated by the OS, we do this ourselves // Ignore key repeats generated by the OS, we do this ourselves
@ -388,11 +468,7 @@ class Vail {
} else if (event.target.id == "dit") { } else if (event.target.id == "dit") {
this.iambic.Key(begin, DIT) this.iambic.Key(begin, DIT)
} else if (event.target.id == "key") { } else if (event.target.id == "key") {
if (begin) { this.straightKey(begin)
this.beginTx()
} else {
this.endTx()
}
} else if (event.target.id == "ck") { } else if (event.target.id == "ck") {
this.Test() this.Test()
} }