]> git.rkrishnan.org Git - pihpsdr.git/commitdiff
Tied the timing of the CW keyer to the TX sample processing rather
authorc vw <dl1ycf@darc.de>
Mon, 7 Sep 2020 07:40:21 +0000 (09:40 +0200)
committerc vw <dl1ycf@darc.de>
Mon, 7 Sep 2020 07:40:21 +0000 (09:40 +0200)
than to a real-time clock, this may tie the side tone more closely
to the keyer state machine.

iambic.c
iambic.h

index e850bab25d4f751757093ee58e5fbf67c3859521..4e83dbe70d4bb28fe618682e624e021bc40326f3 100644 (file)
--- a/iambic.c
+++ b/iambic.c
@@ -215,6 +215,8 @@ static int dash_held = 0;
 static int key_state = 0;
 static int dot_length = 0;
 static int dash_length = 0;
+static int dot_samples = 0;
+static int dash_samples = 0;
 static int kcwl = 0;
 static int kcwr = 0;
 int *kdot;
@@ -266,6 +268,8 @@ void keyer_update() {
     dot_length = 1200 / cw_keyer_speed;
     // will be 3 * dot length at standard weight
     dash_length = (dot_length * 3 * cw_keyer_weight) / 50;
+    dot_samples = 57600 / cw_keyer_speed;
+    dash_samples = (3456 * cw_keyer_weight) / cw_keyer_speed;
 
     if (cw_keys_reversed) {
         kdot  = &kcwr;
@@ -324,21 +328,6 @@ void keyer_event(int left, int state) {
     }
 }
 
-void set_keyer_out(int state) {
-  if (state) {
-    cw_hold_key(1); // this starts a CW pulse in transmitter.c
-  } else {
-    cw_hold_key(0); // this stops a CW pulse in transmitter.c
-  }
-  //
-  // If GPIO sidetone information is requested,
-  // set GPIO pin to the state
-  //
-  if (gpio_cw_sidetone_enabled()) {
-    gpio_cw_sidetone_set(state);
-  }
-}
-
 static void* keyer_thread(void *arg) {
     struct timespec loop_delay;
     int interval = 1000000; // 1 ms
@@ -416,63 +405,71 @@ static void* keyer_thread(void *arg) {
                // we won't enter the code 10 lines above that de-activates MOX.
                if (cwvox > 1) cwvox--;
                 if (cw_keyer_mode == KEYER_STRAIGHT) {       // Straight/External key or bug
-                    if (*kdash) {                  // send manual dashes
-                      set_keyer_out(1);
-                     clock_gettime(CLOCK_MONOTONIC, &loop_delay);
-                     // wait until dash is released. Check once a milli-sec
-                     for (;;) {
-                       loop_delay.tv_nsec += interval;
-                       while (loop_delay.tv_nsec >= NSEC_PER_SEC) {
-                         loop_delay.tv_nsec -= NSEC_PER_SEC;
-                         loop_delay.tv_sec++;
-                       }
-                       if (!*kdash) break;
-                       clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &loop_delay, NULL);
-                     }
-                     // dash released.
-                      set_keyer_out(0);
-                     // since we stay in CHECK mode, re-trigger cwvox here
-                     cwvox=cw_keyer_hang_time;
+                    if (*kdot) {
+                     // "bug" mode: dot key activates automatic dots
+                      key_state = PREDOT;
                     }
-                   if (*kdot) {
-                       // "bug" mode: dot key activates automatic dots
-                        key_state = SENDDOT;
+                    // If both paddles are pressed (should not happen), then
+                    // the dash paddle wins.
+                    if (*kdash) {                  // send manual dashes
+                      cw_key_up=960000;            // 20 sec maximum
+                      cw_key_down=0;
+                      gpio_cw_sidetone_set(1);
+                      key_state=STRAIGHT;
                     }
-                   // end of KEYER_STRAIGHT case
                 } else {
                    // Paddle
                    // If both following if-statements are true, which one should win?
                    // I think a "simultaneous squeeze" means a dot-dash sequence, since in 
                    // a dash-dot sequence there is a larger time window to hit the dot.
-                    if (*kdash) key_state = SENDDASH;
-                    if (*kdot) key_state = SENDDOT;
+                    if (*kdash) key_state = PREDASH;
+                    if (*kdot) key_state = PREDOT;
                 }
                break;
 
-           case SENDDOT:
+            case STRAIGHT:
+               //
+               // Wait for dash paddle being released in "straight key" mode.
+                //
+                if (! *kdash) {
+                  cw_key_up=0;
+                  gpio_cw_sidetone_set(0);
+                 cwvox=cw_keyer_hang_time;
+                  key_state=CHECK;
+                }
+                break;
+
+           case PREDOT:
+                //
+                // start sending the dot
+                //
                dash_memory = 0;
                 dash_held = *kdash;
-                set_keyer_out(1);
-               clock_gettime(CLOCK_MONOTONIC, &loop_delay);
-               // Wait one dot length, then key-up
-                loop_delay.tv_nsec += 1000000 * dot_length;
-                while (loop_delay.tv_nsec >= NSEC_PER_SEC) {
-                  loop_delay.tv_nsec -= NSEC_PER_SEC;
-                  loop_delay.tv_sec++;
-               }
-                clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &loop_delay, NULL);
-                set_keyer_out(0);
-                key_state = DOTDELAY;       // add inter-character spacing of one dot length
-               kdelay=0;
+                cw_key_down=dot_samples;
+                cw_key_up=dot_samples;
+                gpio_cw_sidetone_set(1);
+                key_state=SENDDOT;
+                break;
+
+            case SENDDOT:
+                //
+                // wait for dot being complete
+                //
+                if (cw_key_down == 0) {
+                  gpio_cw_sidetone_set(0);
+                  key_state=DOTDELAY;
+                }
                 break;
 
             case DOTDELAY:
-                kdelay++;
-                if (kdelay > dot_length) {
+                //
+                // wait for end of inter-element pause
+                //
+                if (cw_key_up == 0) {
                  if (cw_keyer_mode == KEYER_STRAIGHT) {
                    // bug mode: continue sending dots or exit, depending on current dot key status
                    key_state = EXITLOOP;
-                   if (*kdot) key_state=SENDDOT;
+                   if (*kdot) key_state=PREDOT;
                    // end of bug/straight case
                   } else {
 //
@@ -486,9 +483,9 @@ static void* keyer_thread(void *arg) {
                     if (cw_keyer_mode == KEYER_MODE_A && !*kdot && !*kdash) dash_held=0;
 
                     if (dash_memory || *kdash || dash_held)
-                        key_state = SENDDASH;
+                        key_state = PREDASH;
                     else if (*kdot)                                 // dot still held, so send a dot
-                       key_state = SENDDOT;
+                       key_state = PREDOT;
                    else if (cw_keyer_spacing) {
                         dot_memory = dash_memory = 0;
                         key_state = LETTERSPACE;
@@ -500,28 +497,28 @@ static void* keyer_thread(void *arg) {
                 }   
                 break;
 
-           case SENDDASH:
+           case PREDASH:
                dot_memory =  0;
                dot_held = *kdot;  // remember if dot is still held at beginning of the dash
-                set_keyer_out(1);
-                clock_gettime(CLOCK_MONOTONIC, &loop_delay);
-               // Wait one dash length and then key-up
-                loop_delay.tv_nsec += 1000000L * dash_length;
-                while (loop_delay.tv_nsec >= NSEC_PER_SEC) {
-                  loop_delay.tv_nsec -= NSEC_PER_SEC;
-                  loop_delay.tv_sec++;
+                cw_key_down=dash_samples;
+                cw_key_up=dot_samples;
+                gpio_cw_sidetone_set(1);
+                key_state=SENDDASH;
+                break;
+
+            case SENDDASH:
+                //
+                // wait for dot being complete
+                //
+                if (cw_key_down == 0) {
+                  gpio_cw_sidetone_set(0);
+                  key_state=DASHDELAY;
                 }
-                clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &loop_delay, NULL);
-                set_keyer_out(0);
-                key_state = DASHDELAY;       // add inter-character spacing of one dot length
-               kdelay=0;
-               // do not fall through, update VOX at beginning of loop
                 break;
 
             case DASHDELAY:
-               // we never arrive here in STRAIGHT/BUG mode
-                kdelay++;
-                if (kdelay > dot_length) {
+               // Wait for the end of the inter-element delay
+                if (cw_key_up == 0) {
 //
 //                  DL1YCF:
 //                  This is my understanding where MODE A comes in:
@@ -532,9 +529,9 @@ static void* keyer_thread(void *arg) {
 //
                     if (cw_keyer_mode == KEYER_MODE_A && !*kdot && !*kdash) dot_held=0;
                     if (dot_memory || *kdot || dot_held)
-                        key_state = SENDDOT;
+                        key_state = PREDOT;
                     else if (*kdash)
-                       key_state = SENDDASH;
+                       key_state = PREDASH;
                    else if (cw_keyer_spacing) {
                         dot_memory = dash_memory = 0;
                         key_state = LETTERSPACE;
@@ -549,9 +546,9 @@ static void* keyer_thread(void *arg) {
                 kdelay++;
                 if (kdelay > 2 * dot_length) {
                     if (dot_memory)         // check if a dot or dash paddle was pressed during the delay.
-                        key_state = SENDDOT;
+                        key_state = PREDOT;
                     else if (dash_memory)
-                        key_state = SENDDASH;
+                        key_state = PREDASH;
                     else key_state = EXITLOOP;   // no memories set so restart
                 }
                 break;
index cc83c8fe94069a6f0c06e83d10544830ac266785..91fcd4341749967df328021f905058ab728fa916 100644 (file)
--- a/iambic.h
+++ b/iambic.h
@@ -3,7 +3,10 @@
 
 enum {
     CHECK = 0,
+    STRAIGHT,
+    PREDOT,
     SENDDOT,
+    PREDASH,
     SENDDASH,
     DOTDELAY,
     DASHDELAY,