Browse files

Converted keyer-control to the Tcl version, started the keyer_decode …

…replacement in Tcl.
  • Loading branch information...
1 parent 0610ea3 commit be2694d9657d40e6dc0cd6a598004de6366eff9a @recri committed Jan 4, 2012
View
108 bin/keyer-control
@@ -4,20 +4,23 @@
lappend auto_path [file join [file dirname [info script]] .. lib]
package require Tk
+package require keyer
+package require sdrkit
##
## parameters and operating data
##
array set data {
ascii 1
iambic 1
-
+ #ascii_tone-verbose 5
ascii_tone-freq 700
ascii_tone-gain -30
ascii_tone-rise 5
ascii_tone-fall 5
+ #ascii-verbose 5
ascii-wpm 15
ascii-word 50
ascii-dah 3
@@ -28,11 +31,13 @@ array set data {
ascii-chan 1
ascii-note 0
+ #iambic_tone-verbose 5
iambic_tone-freq 750
iambic_tone-gain -30
iambic_tone-rise 5
iambic_tone-fall 5
+ iambic-verbose 5
iambic-wpm 15
iambic-word 50
iambic-dah 3
@@ -53,44 +58,32 @@ array set data {
##
proc plug-exists {client} {
global plug
- return [info exists plug($client-fp)]
+ return [info exists plug($client)]
}
-proc plug-open {program client {server default}} {
+proc plug-open {command client {server default}} {
global plug
global data
- set bindir [file dirname [info script]]
- set plug($client-binary) [file join $bindir $program]
- # test for file exists
- set plug($client-out-file) "/tmp/keyer-control-[pid]-$client.out"
- set args [list |$plug($client-binary) --server $server --client $client]
+ set args {}
foreach name [array names data $client-*] {
set val $data($name)
set name [string range $name [expr {1+[string length $client]}] end]
- lappend args "--$name" $val
+ lappend args "-$name" $val
}
- lappend args {>&} $plug($client-out-file)
- set command [join $args]
- set plug($client-fp) [open $command w]
- fconfigure $plug($client-fp) -buffering line
- set plug($client-out-fp) [open "$plug($client-out-file)" r]
- fconfigure $plug($client-out-fp) -blocking 0 -buffering line
- # fileevent $plug($client-out-fp) readable "plug-readable $client"
+ eval [concat [list $command $client -server $server] $args]
+ set plug($client) $client
lappend plug(clients) $client
}
proc plug-close {client} {
global plug
if {[plug-exists $client]} {
- #puts stderr "plug-close $client"
- close $plug($client-fp)
- close $plug($client-out-fp)
- file delete $plug($client-out-file)
foreach name [array names plug $client-*] {
unset plug($name)
}
set i [lsearch -exact $plug(clients) $client]
set plug(clients) [lreplace $plug(clients) $i $i]
+ rename $plug(client) {}
} else {
puts stderr "non-existent client $client in plug-close"
}
@@ -106,7 +99,9 @@ proc plug-close-all {} {
proc plug-puts {client opt value} {
global plug
if {[plug-exists $client]} {
- puts $plug($client-fp) "<$opt$value>"
+ #puts "$plug($client) config -$opt $value"
+ $plug($client) config -$opt $value
+ #puts "$plug($client) cget -$opt -> [$plug($client) cget -$opt]"
} else {
puts stderr "non-existent client $client in plug-puts"
}
@@ -115,28 +110,15 @@ proc plug-puts {client opt value} {
proc plug-puts-text {client text} {
global plug
if {[plug-exists $client]} {
- puts $plug($client-fp) $text
+ $plug($client) puts $text
} else {
puts stderr "non-existent client $client in plug-puts-text"
}
}
-proc plug-readable {client} {
- global plug
- # puts "plug-readable $client"
- if {[gets $plug($client-out-fp) line] < 0} {
- if {[eof $plug($client-out-fp)]} {
- # don't close, they're files that will grow
- # plug-close $client
- }
- return;
- }
- lappend plug($client-input) $line
-}
-
proc plug-read {client} {
global plug
- return [read $plug($client-out-fp)]
+ return [$plug($client) gets]
}
#
@@ -146,45 +128,56 @@ proc plug-init {} {
global data
# start jack
# look for zombie helpers?
- foreach line [split [string trim [exec jack_lsp]] \n] {
- switch -glob $line {
- ascii:* -
- iambic:* -
- ascii_tone:* -
- iambic_tone:* {
- error "the [lindex [split $line :] 0] client is still running"
+ set ports [sdrkit::jack list-ports]
+ foreach port [dict keys $ports] {
+ foreach conn [dict get $ports $port connections] {
+ switch -glob $line {
+ ascii:* -
+ iambic:* -
+ ascii_tone:* -
+ iambic_tone:* {
+ error "the [lindex [split $line :] 0] client is still running"
+ }
+ }
+ }
+ switch -glob $port {
+ system:midi_capture_* {
+ set midi_capture $port
}
}
}
# make helpers
set connects {}
if {$data(ascii)} {
- plug-open keyer_ascii ascii
- plug-open keyer_tone ascii_tone
- lappend connects {jack_connect ascii:midi_out ascii_tone:midi_in}
- lappend connects {jack_connect ascii_tone:out_i system:playback_1}
- lappend connects {jack_connect ascii_tone:out_q system:playback_2}
+ plug-open keyer::ascii ascii
+ plug-open keyer::tone ascii_tone
+ lappend connects {sdrkit::jack connect ascii:midi_out ascii_tone:midi_in}
+ lappend connects {sdrkit::jack connect ascii_tone:out_i system:playback_1}
+ lappend connects {sdrkit::jack connect ascii_tone:out_q system:playback_2}
}
if {$data(iambic)} {
- plug-open keyer_iambic iambic
- # plug-open keyer_iambic2 iambic
- plug-open keyer_tone iambic_tone
- lappend connects {jack_connect system:midi_capture_1 iambic:midi_in}
- lappend connects {jack_connect iambic:midi_out iambic_tone:midi_in}
- lappend connects {jack_connect iambic_tone:out_i system:playback_1}
- lappend connects {jack_connect iambic_tone:out_q system:playback_2}
+ if { ! [info exists midi_capture]} {
+ error "no midi_capture port for keyer connection"
+ }
+ # plug-open keyer::iambic iambic
+ plug-open keyer::iambic iambic
+ plug-open keyer::tone iambic_tone
+ lappend connects [list sdrkit::jack connect $midi_capture iambic:midi_in]
+ lappend connects {sdrkit::jack connect iambic:midi_out iambic_tone:midi_in}
+ lappend connects {sdrkit::jack connect iambic_tone:out_i system:playback_1}
+ lappend connects {sdrkit::jack connect iambic_tone:out_q system:playback_2}
}
# these names may need to change around
after 500
set retry {}
foreach cmd $connects {
- if {[catch "exec $cmd" error]} {
+ if {[catch "eval $cmd" error]} {
puts "$cmd: yielded $error"
lappend retry $cmd
}
}
foreach cmd $retry {
- if {[catch "exec $cmd" error]} {
+ if {[catch "eval $cmd" error]} {
puts "$cmd: failed again, yielded $error"
}
}
@@ -388,6 +381,7 @@ proc main {argv} {
--ascii-freq { set data(ascii_tone-freq) $value }
--ascii-gain { set data(ascii_tone-gain) $value }
--iambic { set data(iambic) $value }
+ --iambicpp { set data(iambicpp) $value }
--iambic-wpm { set data(iambic-wpm) $value }
--iambic-freq { set data(iambic_tone-freq) $value }
--iambic-gain { set data(iambic_tone-gain) $value }
View
37 bin/keyer_decode2
@@ -0,0 +1,37 @@
+#!/usr/bin/tclsh
+# -*- mode: Tcl; tab-width: 8; -*-
+
+lappend auto_path [file join [file dirname [info script]] .. lib]
+
+package require keyer
+
+array set data {
+ -server default
+ -client decode
+ -chan 1
+ -note 0
+}
+
+foreach {option value} $argv {
+ switch -- $option {
+ --server -
+ --client -
+ --chan -
+ --note {
+ set data([string range $option 1 end]) $value
+ }
+ default {
+ error "unrecognized option: $option"
+ }
+ }
+}
+
+keyer::decode decode {*}[array get data]
+
+fconfigure stdout -buffering none
+while {1} {
+ set line [decode gets]
+ if {[string length $line]} {
+ puts -nonewline $line
+ }
+}
View
BIN images/keyer-7.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN images/keyer-8.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
22 keyers/Makefile
@@ -11,8 +11,8 @@ LIBUSB_LIBS=$(shell pkg-config --libs libusb-1.0)
LIBDIR=../lib/keyers
-ALL=../bin/keyer_tone ../bin/keyer_ascii ../bin/keyer_iambic ../bin/keyer_decode ../bin/keyer_iambicpp
-ALL2=$(LIBDIR)/keyer_tone.so $(LIBDIR)/keyer_ascii.so $(LIBDIR)/keyer_iambic.so $(LIBDIR)/keyer_decode.so $(LIBDIR)/keyer_iambicpp.so
+ALL=../bin/keyer_tone ../bin/keyer_ascii ../bin/keyer_iambic ../bin/keyer_decode
+ALL2=$(LIBDIR)/keyer_tone.so $(LIBDIR)/keyer_ascii.so $(LIBDIR)/keyer_iambic.so $(LIBDIR)/keyer_decode.so
all:: $(ALL) $(ALL2)
cd $(LIBDIR) && make all
@@ -35,31 +35,23 @@ clean::
mkdir -p ../bin
cc -o ../bin/keyer_ascii $(CFLAGS) -DAS_BIN keyer_ascii.c $(JACK_LIBS) -lm
-../bin/keyer_iambic: keyer_iambic.c framework.h options.h timing.h midi.h
+../bin/keyer_iambic: keyer_iambic.cc framework.h options.h timing.h midi.h
mkdir -p ../bin
- cc -o ../bin/keyer_iambic $(CFLAGS) -DAS_BIN keyer_iambic.c $(JACK_LIBS) -lm
-
-../bin/keyer_iambicpp: keyer_iambicpp.cc Iambic.hh framework.h options.h timing.h midi.h
- mkdir -p ../bin
- g++ -o ../bin/keyer_iambicpp $(CPPFLAGS) -DAS_BIN keyer_iambicpp.cc $(JACK_LIBS) -lm
+ g++ -o ../bin/keyer_iambic $(CPPFLAGS) -DAS_BIN keyer_iambic.cc $(JACK_LIBS) -lm
$(LIBDIR)/keyer_tone.so: keyer_tone.c framework.h options.h timing.h
mkdir -p $(LIBDIR)
cc -o $(LIBDIR)/keyer_tone.so -shared -fPIC -DAS_TCL $(CFLAGS) keyer_tone.c $(JACK_LIBS) $(LIBS) -lm
-$(LIBDIR)/keyer_decode.so: keyer_decode.c framework.h options.h
+$(LIBDIR)/keyer_decode.so: keyer_decode.c framework.h options.h ring_buffer.h
mkdir -p $(LIBDIR)
cc -o $(LIBDIR)/keyer_decode.so $(CFLAGS) -shared -fPIC -DAS_TCL keyer_decode.c $(JACK_LIBS) $(LIBS) -lm
$(LIBDIR)/keyer_ascii.so: keyer_ascii.c framework.h options.h timing.h midi.h
mkdir -p $(LIBDIR)
cc -o $(LIBDIR)/keyer_ascii.so $(CFLAGS) -shared -fPIC -DAS_TCL keyer_ascii.c $(JACK_LIBS) $(LIBS) -lm
-$(LIBDIR)/keyer_iambic.so: keyer_iambic.c framework.h options.h timing.h midi.h
- mkdir -p $(LIBDIR)
- cc -o $(LIBDIR)/keyer_iambic.so $(CFLAGS) -shared -fPIC -DAS_TCL keyer_iambic.c $(JACK_LIBS) $(LIBS) -lm
-
-$(LIBDIR)/keyer_iambicpp.so: keyer_iambicpp.cc Iambic.hh framework.h options.h timing.h midi.h
+$(LIBDIR)/keyer_iambic.so: keyer_iambic.cc framework.h options.h timing.h midi.h
mkdir -p $(LIBDIR)
- g++ -o $(LIBDIR)/keyer_iambicpp.so $(CPPFLAGS) -shared -fPIC -DAS_TCL keyer_iambicpp.cc $(JACK_LIBS) $(LIBS) -lm
+ g++ -o $(LIBDIR)/keyer_iambic.so $(CPPFLAGS) -shared -fPIC -DAS_TCL keyer_iambic.cc $(JACK_LIBS) $(LIBS) -lm
View
21 keyers/keyer_decode.c
@@ -23,6 +23,7 @@
#include "framework.h"
#include "options.h"
#include "midi.h"
+#include "ring_buffer.h"
typedef struct {
unsigned last_frame; /* frame of last event */
@@ -38,7 +39,10 @@ typedef struct {
framework_t fw;
decode_t decode;
unsigned frame;
- /* Tcl needs a ring buffer to store decoded elements */
+ #define _SIZE 512
+ unsigned rptr;
+ unsigned wptr;
+ char buff[_SIZE];
} _t;
/*
@@ -128,7 +132,12 @@ static void _decode(_t *dp, unsigned count, unsigned char *p) {
fprintf(stdout, "%s", out); fflush(stdout);
#endif
#if AS_TCL
-
+ if (buffer_writeable(dp->wptr, dp->rptr, _SIZE)) {
+ if (*out != 0)
+ dp->buff[buffer_index(dp->wptr++, _SIZE)] = *out;
+ } else {
+ fprintf(stderr, "keyer_decode: buffer overflow writing \"%s\"\n", out);
+ }
#endif
} else if (dp->fw.opts.verbose > 3)
fprintf(stderr, "discarded midi chan=0x%x note=0x%x != mychan=0x%x mynote=0x%x\n", channel, note, dp->fw.opts.chan, dp->fw.opts.note);
@@ -193,6 +202,14 @@ int main(int narg, char **args) {
static int _command(ClientData clientData, Tcl_Interp *interp, int argc, Tcl_Obj* const *objv) {
if (argc == 2 && strcmp(Tcl_GetString(objv[1]), "gets") == 0) {
// return the current decoded string
+ _t *dp = (_t *)clientData;
+ unsigned n = buffer_items_available_to_read(dp->wptr, dp->rptr, _SIZE);
+ char buff[512];
+ if (n > 512)
+ n = 512;
+ for (int i = 0; i < n; i += 1)
+ buff[i] = dp->buff[buffer_index(dp->rptr++, _SIZE)];
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(buff, n));
return TCL_OK;
}
if (framework_command(clientData, interp, argc, objv) != TCL_OK)
View
406 keyers/keyer_iambic.c
@@ -1,406 +0,0 @@
-/**
- Copyright (c) 2011,2012 by Roger E Critchlow Jr
-
- keyer_iambic implements an iambic keyer keyed by midi events
- and generating midi events.
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-*/
-
-#define OPTIONS_TIMING 1
-#define OPTIONS_KEYER 1
-
-#include "framework.h"
-#include "options.h"
-#include "midi.h"
-#include "midi_buffer.h"
-#include "timing.h"
-
-/*
-** iambic keyer
-*/
-
-#define KEYIN(dit,dah) (((dit)<<1)|(dah))
-#define KEYIN_OFF KEYIN(0,0)
-#define KEYIN_DIT KEYIN(1,0)
-#define KEYIN_DAH KEYIN(0,1)
-#define KEYIN_DIDAH KEYIN(1,1)
-#define KEYIN_IS_DIT(k) ((k)&KEYIN_DIT)
-#define KEYIN_IS_DAH(k) ((k)&KEYIN_DAH)
-
-typedef enum {
- IAMBIC_OFF, /* silent, no paddles down */
- IAMBIC_DIT, /* sounding a dit, dit paddle down */
- IAMBIC_DIT_SPACE, /* sounding a space after a dit */
- IAMBIC_DAH, /* sounding a dah, dah paddle down */
- IAMBIC_DAH_SPACE, /* sounding a space after a dah */
- IAMBIC_SYMBOL_SPACE, /* sounding an inter-symbol space */
- IAMBIC_WORD_SPACE, /* sounding an inter-word space */
-} _state_t;
-
-static char *_keys[] = {
- "OFF", "DAH", "DIT", "DIDAH"
-};
-
-static char *_states[] = {
- "OFF",
- "DIT", "DIT_SPACE",
- "DAH", "DAH_SPACE",
- "SYMBOL_SPACE",
- "WORD_SPACE"
-};
-
-typedef struct {
- char _modified;
-
- char _inDit;
- char _inDah;
-
- int _keyerDuration;
- char _keyIn;
- char _lastKeyIn;
- _state_t _keyerState;
-
- int _halfClock;
- int _halfClockCounter;
-#define KEY_IN_MEM 8
- char _prevKeyIn[KEY_IN_MEM];
- unsigned _prevKeyInPtr;
-} iambic_t;
-
-typedef struct {
- framework_t fw;
- timing_t samples_per;
- unsigned char note_on[3];
- unsigned char note_off[3];
- iambic_t iambic;
- unsigned long frames;
- unsigned duration;
- options_t sent;
- midi_buffer_t midi;
-} _t;
-
-static char *preface(_t *dp, const char *file, int line) {
- static char buff[256];
- sprintf(buff, "%s:%s:%d@%ld", dp->fw.opts.client, file, line, dp->frames);
- return buff;
- }
-
-#define PREFACE preface(dp, __FILE__, __LINE__)
-
-// initialize the iambic keyer
-static void _init(void *arg) {
- _t *dp = (_t *)arg;
- if (dp->fw.opts.verbose > 2) fprintf(stderr, "%ld: iambic_init()\n", dp->frames);
- dp->iambic._modified = 1;
- dp->iambic._inDit = 0; /* the midi dit value */
- dp->iambic._inDah = 0; /* the midi dah value */
- dp->iambic._keyIn = KEYIN_OFF;
- dp->iambic._lastKeyIn = KEYIN_OFF;
- dp->iambic._keyerState = IAMBIC_OFF;
- dp->duration = 0;
- midi_init(&dp->midi);
-}
-
-// update the computed parameters
-static void _update(_t *dp) {
- if (dp->fw.opts.modified) {
- dp->fw.opts.modified = 0;
-
- if (dp->fw.opts.verbose > 2) fprintf(stderr, "%ld: recomputing data from options\n", dp->frames);
-
- /* timer recomputation */
- keyer_timing_update(&dp->fw.opts, &dp->samples_per);
- if (dp->fw.opts.verbose > 2) keyer_timing_report(stderr, &dp->fw.opts, &dp->samples_per);
-
- /* midi note on/off */
- dp->note_on[0] = NOTE_ON|(dp->fw.opts.chan-1); dp->note_on[1] = dp->fw.opts.note;
- dp->note_off[0] = NOTE_OFF|(dp->fw.opts.chan-1); dp->note_on[1] = dp->fw.opts.note;
-
- /* pass on parameters to tone keyer */
- char buffer[128];
- if (dp->sent.rise != dp->fw.opts.rise) { sprintf(buffer, "<rise%.1f>", dp->sent.rise = dp->fw.opts.rise); midi_sysex_write(&dp->midi, buffer); }
- if (dp->sent.fall != dp->fw.opts.fall) { sprintf(buffer, "<fall%.1f>", dp->sent.fall = dp->fw.opts.fall); midi_sysex_write(&dp->midi, buffer); }
- if (dp->sent.freq != dp->fw.opts.freq) { sprintf(buffer, "<freq%.1f>", dp->sent.freq = dp->fw.opts.freq); midi_sysex_write(&dp->midi, buffer); }
- if (dp->sent.gain != dp->fw.opts.gain) { sprintf(buffer, "<gain%.1f>", dp->sent.gain = dp->fw.opts.gain); midi_sysex_write(&dp->midi, buffer); }
-
- /* trigger iambic updates */
- dp->iambic._modified = 1;
- }
- if (dp->iambic._modified) {
- dp->iambic._modified = 0;
- dp->iambic._halfClock = dp->samples_per.dit / 2;
- }
-}
-
-// transition to the specified state
-// with the specified duration
-static char _transition_to(_t *dp, _state_t newState, unsigned newDuration) {
- if (dp->fw.opts.verbose > 5) fprintf(stderr, "%ld: to %s for %d\n", dp->frames, _states[newState], newDuration);
- dp->iambic._keyerState = newState;
- dp->iambic._keyerDuration += newDuration;
- return 1;
-}
-
-// transition to the specified state
-// with the specified state duration
-// and send a key event with specified duration
-static char _key_and_transition_to(_t *dp, _state_t newState, unsigned newDuration, char keyOut) {
- if (dp->fw.opts.verbose > 5) fprintf(stderr, "%ld: key %d %x\n", dp->frames, newDuration, keyOut);
- midi_write(&dp->midi, newDuration, 3, keyOut ? dp->note_on : dp->note_off);
- return _transition_to(dp, newState, newDuration);
-}
-
-// start a dit if _dit is pressed
-// or modeB && squeeze was released in last dah
-static char _start_dit(_t *dp) {
- char keyIn = dp->iambic._keyIn;
- if (dp->fw.opts.mode == 'B' && dp->iambic._keyIn == KEYIN_OFF && dp->iambic._prevKeyIn[(dp->iambic._prevKeyInPtr-5) & (KEY_IN_MEM-1)] == KEYIN_DIDAH)
- keyIn = dp->iambic._prevKeyIn[(dp->iambic._prevKeyInPtr-5) & (KEY_IN_MEM-1)];
- return KEYIN_IS_DIT(keyIn) ? _key_and_transition_to(dp, IAMBIC_DIT, dp->samples_per.dit, 1) : 0;
-}
-
-// start a dah if _dah is pressed
-// or modeB && squeeze was released in last dit
-static char _start_dah(_t *dp) {
- char keyIn = dp->iambic._keyIn;
- if (dp->fw.opts.mode == 'B' && dp->iambic._keyIn == KEYIN_OFF && dp->iambic._prevKeyIn[(dp->iambic._prevKeyInPtr-3) & (KEY_IN_MEM-1)] == KEYIN_DIDAH)
- keyIn = dp->iambic._prevKeyIn[(dp->iambic._prevKeyInPtr-3) & (KEY_IN_MEM-1)];
- return KEYIN_IS_DAH(keyIn) ? _key_and_transition_to(dp, IAMBIC_DAH, dp->samples_per.dah, 1) : 0;
-}
-
-// continue an interelement space to an intersymbol space
-// or an intersymbol space to an interword space
-static char _continue_space(_t *dp, _state_t newState, unsigned newDuration) {
- if (dp->fw.opts.verbose > 5) fprintf(stderr, "%ld: continue space %d\n", dp->frames, newDuration);
- midi_write(&dp->midi, newDuration, 0, "");
- return _transition_to(dp, newState, newDuration);
-}
-
-static char _symbol_space(_t *dp) {
- return dp->fw.opts.alsp ? _continue_space(dp, IAMBIC_SYMBOL_SPACE, dp->samples_per.ils-dp->samples_per.ies) : 0;
-}
-
-static char _word_space(_t *dp) {
- return dp->fw.opts.awsp ? _continue_space(dp, IAMBIC_WORD_SPACE, dp->samples_per.iws-dp->samples_per.ils) : 0;
-}
-
-// return to keyer idle state
-static char _finish(_t *dp) {
- return _transition_to(dp, IAMBIC_OFF, 0L);
-}
-
-// at the beginning of the next symbol
-// we may be currently at dit+dah, but
-// we want to start with which ever
-// paddle was pressed first
-static char _start_symbol(_t *dp) {
- if (dp->iambic._keyIn != KEYIN_DIDAH || dp->iambic._lastKeyIn != KEYIN_DAH)
- return _start_dit(dp) || _start_dah(dp) ? 1 : 0;
- else
- return _start_dah(dp) || _start_dit(dp) ? 1 : 0;
-}
-
-// start an interelement space
-static char _start_space(_t *dp, _state_t newState) {
- return _key_and_transition_to(dp, newState, dp->samples_per.ies, 0);
-}
-
-// process keyer state
-// and generate transitions
-static void iambic_transition(_t *dp, unsigned samples) {
- // construct input key state
- char keyIn = dp->fw.opts.swap ? KEYIN(dp->iambic._inDah, dp->iambic._inDit) : KEYIN(dp->iambic._inDit, dp->iambic._inDah);
- if (dp->iambic._keyIn != keyIn) {
- if (dp->fw.opts.verbose > 5) fprintf(stderr, "%ld: keyIn %x\n", dp->frames, keyIn);
- dp->iambic._lastKeyIn = dp->iambic._keyIn;
- }
- dp->iambic._keyIn = keyIn;
-
- // start a symbol if either paddle is pressed
- if (dp->iambic._keyerState == IAMBIC_OFF) {
- _start_symbol(dp);
- dp->iambic._halfClockCounter = dp->iambic._halfClock;
- dp->iambic._prevKeyIn[dp->iambic._prevKeyInPtr++ & (KEY_IN_MEM-1)] = keyIn;
- return;
- }
-
- // reduce the half clock by the time elapsed
- dp->iambic._halfClockCounter -= samples;
-
- // if the half clock has elapsed, reset it
- if (dp->iambic._halfClockCounter < 0) {
- dp->iambic._halfClockCounter = dp->iambic._halfClock;
- dp->iambic._prevKeyIn[dp->iambic._prevKeyInPtr++ & (KEY_IN_MEM-1)] = keyIn;
- }
-
- // reduce the duration by the time elapsed
- dp->iambic._keyerDuration -= samples;
-
- // if the duration has not elapsed, return
- if (dp->iambic._keyerDuration > 0) {
- return;
- }
-
- // compute updated parameters
- _update(dp);
-
- if (dp->fw.opts.verbose > 4) fprintf(stderr, "%ld: dur %d key %s state %s\n", dp->frames, dp->iambic._keyerDuration, _keys[dp->iambic._keyIn], _states[dp->iambic._keyerState]);
-
- // determine the next element by the current paddle state
- switch (dp->iambic._keyerState) {
- case IAMBIC_DIT: // finish the dit with an interelement space
- _start_space(dp, IAMBIC_DIT_SPACE);
- return;
- case IAMBIC_DAH: // finish the dah with an interelement space
- _start_space(dp, IAMBIC_DAH_SPACE);
- return;
- case IAMBIC_DIT_SPACE: // start the next element or finish the symbol
- _start_dah(dp) || _start_dit(dp) || _symbol_space(dp) || _finish(dp);
- return;
- case IAMBIC_DAH_SPACE: // start the next element or finish the symbol
- _start_dit(dp) || _start_dah(dp) || _symbol_space(dp) || _finish(dp);
- return;
- case IAMBIC_SYMBOL_SPACE: // start a new symbol or finish the word
- _start_symbol(dp) || _word_space(dp) || _finish(dp);
- return;
- case IAMBIC_WORD_SPACE: // start a new symbol or go to off
- _start_symbol(dp) || _finish(dp);
- return;
- }
-}
-
-static void _dit_key(_t *dp, int on) {
- dp->iambic._inDit = on;
-}
-
-static void _dah_key(_t *dp, int on) {
- dp->iambic._inDah = on;
-}
-
-static void _decode(_t *dp, int count, unsigned char *p) {
- if (count == 3) {
- unsigned char channel = (p[0]&0xF)+1;
- unsigned char command = p[0]&0xF0;
- unsigned char note = p[1];
- if (channel != dp->fw.opts.chan) {
- if (dp->fw.opts.verbose) fprintf(stderr, "%s _decode discard chan=0x%x note=0x%x != mychan=0x%x\n", PREFACE, channel, note, dp->fw.opts.chan, dp->fw.opts.note);
- } else if (note == dp->fw.opts.note) {
- if (dp->fw.opts.verbose) fprintf(stderr, "%s _decode([%x, %x, ...])\n", PREFACE, p[0], p[1]);
- switch (command) {
- case NOTE_OFF: _dit_key(dp, 0); break;
- case NOTE_ON: _dit_key(dp, 1); break;
- }
- } else if (note == dp->fw.opts.note+1) {
- if (dp->fw.opts.verbose) fprintf(stderr, "%s _decode([%x, %x, ...])\n", PREFACE, p[0], p[1]);
- switch (command) {
- case NOTE_OFF: _dah_key(dp, 0); break;
- case NOTE_ON: _dah_key(dp, 1); break;
- }
- } else {
- if (dp->fw.opts.verbose) fprintf(stderr, "%s _decode discard chan=0x%x note=0x%x != mynote=0x%x\n", PREFACE, channel, note, dp->fw.opts.chan, dp->fw.opts.note);
- }
- } else if (count > 3 && p[0] == SYSEX && p[1] == SYSEX_VENDOR) {
- if (dp->fw.opts.verbose) fprintf(stderr, "%s _decode([%x, %x, %x, ...])\n", PREFACE, p[0], p[1], p[2]);
- options_parse_command(&dp->fw.opts, (char *)p+3);
- }
-}
-
-/*
-** jack process callback
-*/
-
-static int _process(jack_nframes_t nframes, void *arg) {
- _t *dp = (_t *)arg;
- void *midi_in = jack_port_get_buffer(framework_midi_input(dp,0), nframes);
- void *midi_out = jack_port_get_buffer(framework_midi_output(dp,0), nframes);
- jack_midi_event_t in_event;
- int in_event_count = jack_midi_get_event_count(midi_in), in_event_index = 0, in_event_time = 0;
- if (in_event_index < in_event_count) {
- jack_midi_event_get(&in_event, midi_in, in_event_index++);
- // in_event_time += in_event.time;
- in_event_time = in_event.time;
- } else {
- in_event_time = nframes+1;
- }
- /* this is important, very strange if omitted */
- jack_midi_clear_buffer(midi_out);
- /* for all frames in the buffer */
- for(int i = 0; i < nframes; i++) {
- /* process all midi input events at this sample frame */
- while (in_event_time == i) {
- if (dp->fw.opts.verbose > 5) fprintf(stderr, "%ld: process event %x [%x, %x, %x, ...]\n", dp->frames, (unsigned)in_event.size, in_event.buffer[0], in_event.buffer[1], in_event.buffer[2]);
- _decode(dp, in_event.size, in_event.buffer);
- if (in_event_index < in_event_count) {
- jack_midi_event_get(&in_event, midi_in, in_event_index++);
- // in_event_time += in_event.time;
- in_event_time = in_event.time;
- } else {
- in_event_time = nframes+1;
- }
- }
- /* process all midi output events at this sample frame */
- while (dp->duration == i) {
- if (midi_readable(&dp->midi)) {
- if (dp->fw.opts.verbose > 4) fprintf(stderr, "%ld: midi_readable, duration %u, count %u\n", dp->frames, midi_duration(&dp->midi), midi_count(&dp->midi));
- dp->duration += midi_duration(&dp->midi);
- unsigned count = midi_count(&dp->midi);
- if (count != 0) {
- unsigned char* buffer = jack_midi_event_reserve(midi_out, i, count);
- if (buffer == NULL) {
- fprintf(stderr, "%ld: jack won't buffer %d midi bytes!\n", dp->frames, count);
- } else {
- midi_read_bytes(&dp->midi, count, buffer);
- if (dp->fw.opts.verbose > 5) fprintf(stderr, "%ld: sent %x [%x, %x, %x, ...]\n", dp->frames, count, buffer[0], buffer[1], buffer[2]);
- }
- }
- midi_read_next(&dp->midi);
- } else {
- dp->duration = nframes;
- }
- }
- /* clock the iambic keyer */
- iambic_transition(dp, 1);
- }
- dp->frames += 1;
- if (dp->duration >= nframes)
- dp->duration -= nframes;
- return 0;
-}
-
-#if AS_BIN
-int main(int argc, char **argv) {
- _t data;
- framework_main((void *)&data, argc, argv, "keyer_iambic", 0,0,1,1, _init, _process, NULL);
-}
-#endif
-
-#if AS_TCL
-static int _command(ClientData clientData, Tcl_Interp *interp, int argc, Tcl_Obj* const *objv) {
- if (framework_command(clientData, interp, argc, objv) != TCL_OK)
- return TCL_ERROR;
- _update(clientData);
- return TCL_OK;
-}
-
-static int _factory(ClientData clientData, Tcl_Interp *interp, int argc, Tcl_Obj* const *objv) {
- return framework_factory(clientData, interp, argc, objv, 0,0,1,1, _command, _process, sizeof(_t), _init, NULL, "config|cget");
-}
-
-int DLLEXPORT Keyer_iambic_Init(Tcl_Interp *interp) {
- return framework_init(interp, "keyer", "1.0.0", "keyer::iambic", _factory);
-}
-#endif
View
4 keyers/keyer_iambicpp.cc → keyers/keyer_iambic.cc
@@ -207,8 +207,8 @@ static int _factory(ClientData clientData, Tcl_Interp *interp, int argc, Tcl_Obj
return framework_factory(clientData, interp, argc, objv, 0,0,1,1, _command, _process, sizeof(_t), _init, NULL, (char *)"config|cget|cdoc");
}
-int DLLEXPORT Keyer_iambicpp_Init(Tcl_Interp *interp) {
- return framework_init(interp, "keyer", "1.0.0", "keyer::iambicpp", _factory);
+int DLLEXPORT Keyer_iambic_Init(Tcl_Interp *interp) {
+ return framework_init(interp, "keyer", "1.0.0", "keyer::iambic", _factory);
}
#endif
View
11 sdrkit/notes.org
@@ -0,0 +1,11 @@
+* sdrkit
+** computing an fft over some window of audio
+ could be synchronized with the frame clock
+ samples are buffered until frameclock mod fftsize is zero,
+ then compute the fft and start buffering the next input
+ buffer.
+ meanwhile, the results of the previous fft, or second
+ previous, could be supplied as output samples. So the
+ audio time domain signal is transformed to an audio freq
+ domain signal, which is similarly aligned to the frameclock
+ so the time domain makes sense.

0 comments on commit be2694d

Please sign in to comment.