refactor(winkeyer): learn the slow boot instead of naming the keyer
The K3NG entry added an hour ago is gone. It named one clone among many — WKmini, home-built Arduinos, unbranded boxes — for hardware that speaks exactly the same protocol, and it was the only line in the engine list that picked a boot delay rather than a protocol. An operator with an unlabelled clone would have had to guess. The delay is now learnt per port. The first connect finds out by failing the quick attempt and succeeding on the slow one; that fact is written to a global setting keyed by the port, and every connect afterwards goes straight to the slow attempt. Global rather than per profile on purpose: which keyer is plugged into COM3 belongs to the computer, and switching profiles for a different rig does not change the keyer on the desk. Two tests hold the contract from both sides — a slow keyer must be reported as slow, and a keyer that answers at once must not be, or every K1EL connect would inherit seconds it never needed.
This commit is contained in:
@@ -51,10 +51,15 @@ type Config struct {
|
||||
UsePTT bool `json:"use_ptt"` // key PTT (Key/PTT output)
|
||||
SerialEcho bool `json:"serial_echo"` // device echoes sent chars back to host
|
||||
|
||||
// SlowBoot skips the quick opening attempt and waits for a keyer that reboots
|
||||
// when the port opens — a K3NG or any other Arduino-based WinKeyer with its
|
||||
// auto-reset still enabled. Not an operator setting: it is remembered per port
|
||||
// the first time a keyer only answers the long attempt, so the second connect
|
||||
// is as quick as a K1EL's and nobody has to know what is inside the box.
|
||||
SlowBoot bool `json:"-"`
|
||||
|
||||
// Type selects the keyer engine on this serial port:
|
||||
// "" / "k1el" → a K1EL WinKeyer chip (the default, everything above applies)
|
||||
// "k3ng" → a K3NG keyer: an Arduino running the same protocol. Identical
|
||||
// once open; it just needs time to reboot when the port opens.
|
||||
// "serial" → the PC bit-bangs Morse on a control line (no WinKeyer chip):
|
||||
// the "hardware CW keying" a Yaesu SCU-17 / generic interface
|
||||
// uses. WPM / Weight / Farnsworth / LeadIn / Tail / UsePTT still
|
||||
@@ -110,12 +115,20 @@ type Manager struct {
|
||||
|
||||
onStatus func(Status)
|
||||
onEcho func(string) // chars the device echoes back as it keys them
|
||||
// onSlowBoot fires when a keyer answered only after the long wait, so the
|
||||
// caller can persist that for this port. See Config.SlowBoot.
|
||||
onSlowBoot func(port string)
|
||||
}
|
||||
|
||||
func NewManager(onStatus func(Status), onEcho func(string)) *Manager {
|
||||
return &Manager{onStatus: onStatus, onEcho: onEcho}
|
||||
}
|
||||
|
||||
// OnSlowBoot registers the callback that persists "this port needs the long
|
||||
// opening wait". Optional: without it a slow keyer still connects, it just
|
||||
// pays the failed quick attempt on every connect.
|
||||
func (m *Manager) OnSlowBoot(fn func(port string)) { m.onSlowBoot = fn }
|
||||
|
||||
// ListPorts returns the available serial port names (COM3, COM6, …).
|
||||
func ListPorts() ([]string, error) {
|
||||
ports, err := serial.GetPortsList()
|
||||
@@ -166,13 +179,15 @@ func (m *Manager) Connect(cfg Config) error {
|
||||
return fmt.Errorf("winkeyer: open %s: %w", cfg.Port, err)
|
||||
}
|
||||
|
||||
// A K3NG keyer reboots when the port opens (DTR is its reset line), so it is
|
||||
// given the long wait from the start rather than being failed once first.
|
||||
ver, err := hostOpen(p, cfg.Type == "k3ng")
|
||||
ver, slowBoot, err := hostOpen(p, cfg.SlowBoot)
|
||||
if err != nil {
|
||||
_ = p.Close()
|
||||
return fmt.Errorf("winkeyer: %s: %w", cfg.Port, err)
|
||||
}
|
||||
// Tell the caller to remember it, so this port opens quickly next time.
|
||||
if slowBoot && !cfg.SlowBoot && m.onSlowBoot != nil {
|
||||
m.onSlowBoot(cfg.Port)
|
||||
}
|
||||
_ = p.SetReadTimeout(200 * time.Millisecond)
|
||||
|
||||
m.mu.Lock()
|
||||
|
||||
Reference in New Issue
Block a user