fix: serial CW keyer PTT dropping between words on CP210x (SCU-17)
Confirmed from HB9HBY's log: ptt=true, yet the FT-891 dropped to RX between words during a CQ macro — while the same SCU-17 works in N1MM. Root cause: go.bug.st/serial drives DTR/RTS through GetCommState/SetCommState, which on the SCU-17's Silicon Labs CP210x drops the asserted RTS (PTT) the moment DTR (CW) is toggled. N1MM/WSJT use EscapeCommFunction, which sets one line without disturbing the other. OpsLog now drives the lines the same way: a new lineCtl abstraction with a Windows implementation (linectl_windows.go) that opens the COM port via CreateFile and toggles DTR/RTS with windows.EscapeCommFunction (SETDTR/CLRDTR/ SETRTS/CLRRTS). linectl_other.go keeps go.bug.st/serial for non-Windows builds. The serial keyer holds a lineCtl instead of a serial.Port. RTS (PTT) now stays asserted for the whole macro, so the rig holds TX between words. Promotes golang.org/x/sys to a direct dependency.
This commit is contained in:
@@ -209,17 +209,14 @@ func (m *Manager) ApplySerialConfig(cfg Config) {
|
||||
func (m *Manager) connectSerial(cfg Config) error {
|
||||
m.Disconnect() // drop any existing link first
|
||||
|
||||
p, err := serial.Open(cfg.Port, &serial.Mode{
|
||||
BaudRate: cfg.Baud,
|
||||
DataBits: 8,
|
||||
Parity: serial.NoParity,
|
||||
StopBits: serial.OneStopBit,
|
||||
})
|
||||
// Open for line control only (DTR/RTS). On Windows this uses EscapeCommFunction
|
||||
// so a held RTS (PTT) survives DTR (CW) toggling on USB adapters — see linectl_*.
|
||||
line, err := openLineCtl(cfg.Port)
|
||||
if err != nil {
|
||||
return fmt.Errorf("winkeyer: open %s: %w", cfg.Port, err)
|
||||
}
|
||||
// The keyer updates busy state as it keys; mirror it into status + notify.
|
||||
sk := newSerialKeyer(p, cfg, func(busy bool) {
|
||||
sk := newSerialKeyer(line, cfg, func(busy bool) {
|
||||
m.mu.Lock()
|
||||
changed := m.status.Busy != busy
|
||||
m.status.Busy = busy
|
||||
@@ -230,17 +227,17 @@ func (m *Manager) connectSerial(cfg Config) error {
|
||||
})
|
||||
|
||||
m.mu.Lock()
|
||||
m.port = p
|
||||
m.port = nil // serial keyer owns its own (line-only) port, not m.port
|
||||
m.serial = sk
|
||||
m.cfg = cfg
|
||||
m.status = Status{Connected: true, WPM: cfg.WPM, Port: cfg.Port}
|
||||
m.mu.Unlock()
|
||||
|
||||
line := "DTR (CW) / RTS (PTT)"
|
||||
lineDesc := "DTR (CW) / RTS (PTT)"
|
||||
if strings.EqualFold(cfg.CWKeyLine, "rts") {
|
||||
line = "RTS (CW) / DTR (PTT)"
|
||||
lineDesc = "RTS (CW) / DTR (PTT)"
|
||||
}
|
||||
applog.Printf("winkeyer: serial CW keyer on %s — %s, PTT=%v", cfg.Port, line, cfg.UsePTT)
|
||||
applog.Printf("winkeyer: serial CW keyer on %s — %s, PTT=%v (EscapeCommFunction line ctl)", cfg.Port, lineDesc, cfg.UsePTT)
|
||||
m.emit()
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user