]> git.rkrishnan.org Git - dttsp.git/blobdiff - jDttSP/keyd.c
Further keyer improvements: update commands for both physical and type-in keyers
[dttsp.git] / jDttSP / keyd.c
index 61d7ac86dda72483107434151d0410206ed4fd4a..091f6651f19e0d5493558044691494e411d573ab 100644 (file)
@@ -60,8 +60,8 @@ Bridgewater, NJ 08807
 KeyerState ks;
 KeyerLogic kl;
 
-pthread_t play, key;
-sem_t clock_fired, keyer_started;
+pthread_t play, key, update;
+sem_t clock_fired, keyer_started, update_ok;
 
 int fdser, fdrtc;
 
@@ -72,7 +72,7 @@ jack_nframes_t size;
 
 CWToneGen gen;
 BOOLEAN playing = FALSE, iambic = FALSE;
-double wpm = 18.0, freq = 750.0;
+double wpm = 18.0, freq = 750.0, ramp = 5.0, gain = -3.0;
 
 //------------------------------------------------------------
 
@@ -127,8 +127,11 @@ send_silence(void) {
   }
 }
 
+//------------------------------------------------------------------------
+
 // sound/silence generation
 // tone turned on/off asynchronously
+
 void
 sound_thread(void) {
   for (;;) {
@@ -140,18 +143,24 @@ sound_thread(void) {
       // returns FALSE when it's actually done.
       playing = CWTone(gen);
       send_tone();
-    } else
+    } else {
       send_silence();
+      // only let updates run when we've just generated silence
+      sem_post(&update_ok);
+    }
   }
 
   pthread_exit(0);
 }
 
+//------------------------------------------------------------------------
+
 // basic heartbeat
 // returns actual dur in msec since last tick;
 // uses Linux rtc interrupts.
 // other strategies will work too, so long as they
 // provide a measurable delay in msec.
+
 double
 timed_delay(void) {
   double del, std = 1000 / (double) RTC_RATE;
@@ -170,6 +179,7 @@ timed_delay(void) {
 }
 
 // key down? (real or via keyer logic)
+
 BOOLEAN
 read_key(double del) {
   if (iambic)
@@ -178,8 +188,10 @@ read_key(double del) {
     return read_straight_key_serial(ks, fdser);
 }
 
+//------------------------------------------------------------------------
+
 // main keyer loop
-// 
+
 void
 key_thread(void) {
 
@@ -202,6 +214,70 @@ key_thread(void) {
   pthread_exit(0);
 }
 
+//------------------------------------------------------------------------
+
+// update keyer parameters via text input from stdin
+// <wpm xxx> -> set keyer speed to xxx
+// <gain xxx> -> set gain to xxx (dB)
+// <freq xxx> -> set freq to xxx
+// <ramp xxx> -> set attack/decay times to xxx ms
+
+#define MAX_ESC (512)
+#define ESC_L '<'
+#define ESC_R '>'
+
+void
+updater(void) {
+  for (;;) {
+    int c;
+
+    // get or wait for next input char
+    if ((c = getchar()) == EOF) goto finish;
+
+    // if we see the beginning of a command,
+    if (c == ESC_L) {
+      int i = 0;
+      char buf[MAX_ESC];
+
+      // gather up the remainder
+      while ((c = getchar()) != EOF) {
+       if (c == ESC_R) break;
+       buf[i] = c;
+       if (++i >= (MAX_ESC - 1)) break;
+      }
+      if (c == EOF) goto finish;
+      buf[i] = 0;
+
+      // wait until changes are safe
+      sem_wait(&update_ok);
+
+      if (!strncmp(buf, "wpm", 3))
+       ks->wpm = wpm = atof(buf + 3);
+      else if (!strncmp(buf, "ramp", 4)) {
+       ramp = atof(buf + 4);
+       setCWToneGenVals(gen, gain, freq, ramp, ramp);
+      } else if (!strncmp(buf, "freq", 4)) {
+       freq = atof(buf + 4);
+       setCWToneGenVals(gen, gain, freq, ramp, ramp);
+      } else if (!strncmp(buf, "gain", 4)) {
+       gain = atof(buf + 4);
+       setCWToneGenVals(gen, gain, freq, ramp, ramp);
+      } else if (!strncmp(buf, "quit", 4))
+       goto finish;
+
+    } // otherwise go around again
+  }
+
+  // we saw an EOF or quit; kill other threads and exit neatly
+
+ finish:
+  pthread_cancel(play);
+  pthread_cancel(key);
+  pthread_exit(0);
+}
+
+//------------------------------------------------------------------------
+
 PRIVATE void
 jack_xrun(void *arg) {
   char *str = "xrun";
@@ -250,18 +326,31 @@ main(int argc, char **argv) {
       case 'i':
        iambic = TRUE;
        break;
+      case 'g':
+       gain = atof(argv[++i]);
+       break;
+      case 'r':
+       ramp = atof(argv[++i]);
+       break;
       case 'w':
        wpm = atof(argv[++i]);
        break;
       default:
-       fprintf(stderr, "keyd [-i] [-w wpm]\n");
+       fprintf(stderr,
+               "keyd [-i] [-w wpm] [-g gain_dB] [-r ramp_ms]\n");
        exit(1);
       }
     else break;
 
+  if (i < argc) {
+    if (!freopen(argv[i], "r", stdin))
+      perror(argv[i]), exit(1);
+    i++;
+  }
+
   //------------------------------------------------------------
 
-  gen = newCWToneGen(-3.0, freq, 5.0, 5.0, TONE_SIZE, 48000.0);
+  gen = newCWToneGen(gain, freq, ramp, ramp, TONE_SIZE, 48000.0);
 
   //------------------------------------------------------------
 
@@ -335,8 +424,10 @@ main(int argc, char **argv) {
 
   sem_init(&clock_fired, 0, 0);
   sem_init(&keyer_started, 0, 0);
+  sem_init(&update_ok, 0, 0);
   pthread_create(&play, 0, (void *) sound_thread, 0);
   pthread_create(&key, 0, (void *) key_thread, 0);
+  pthread_create(&update, 0, (void *) updater, 0);
 
   //------------------------------------------------------------
 
@@ -361,6 +452,7 @@ main(int argc, char **argv) {
 
   pthread_join(play, 0);
   pthread_join(key, 0);
+  pthread_join(update, 0);
   jack_client_close(client);
 
   //------------------------------------------------------------