void KeyerInit(bool niambic, float wpm) { kl = new KeyerLogic(); ks = new Keyer_state(); ks.flag.iambic = niambic; ks.flag.autospace.khar = ks.flag.autospace.word = false; ks.flag.mdlmdB = true; ks.flag.memory.dah = true; ks.flag.memory.dit = true; ks.debounce = 2; // could be more if sampled faster ks.mode = MODE_B; ks.weight = (int)MainForm.SetupForm.udCWWeight.Value; ks.wpm = wpm; iambic = niambic; TONE_SIZE = 192 * (int)(Audio.SampleRate / 48000.0); }
bool klogic(ref KeyerLogic kl, int dit, int dah, float wpm, int iambicmode, bool midelementmodeB, bool ditmemory, bool dahmemory, bool autocharspacing, bool autowordspacing, int weight, float ticklen) { float ditlen = 1200 / wpm; int set_element_timeouts = NO_TIMEOUTS_SCHED; /* Do we need to initialize the keyer? */ if (!kl.flag.init) { kl.flag.prev.dit = dit; kl.flag.prev.dah = dah; kl.element.last = kl.element.curr = NO_ELEMENT; kl.element.iamb = NO_PADDLE_SQUEEZE; kl.element.psqam = false; kl.element.invtd = false; kl.timeout.midl = kl.timeout.beep = kl.timeout.elem = 0; kl.timeout.dlay = 0; kl.dlay_type = NO_DELAY; kl.flag.init = true; } /* Decrement the timeouts */ kl.timeout.dlay -= kl.timeout.dlay > 0 ? ticklen : 0; if (kl.timeout.dlay <= 0) { /* If nothing is scheduled to play, and we just did a character spacing delay, and we do auto word spacing, wait for a word spacing delay, otherwise resume the normal element timeout countdowns */ if (kl.timeout.elem <= 0 && kl.dlay_type == CHAR_SPACING_DELAY && autowordspacing) { kl.timeout.dlay = ditlen * 4; kl.dlay_type = WORD_SPACING_DELAY; } else { kl.dlay_type = NO_DELAY; kl.timeout.midl -= kl.timeout.midl > 0 ? ticklen : 0; kl.timeout.beep -= kl.timeout.beep > 0 ? ticklen : 0; kl.timeout.elem -= kl.timeout.elem > 0 ? ticklen : 0; } } /* Are both paddles squeezed? */ if (dit == 1 && dah == 1) { kl.element.iamb = PADDLES_SQUEEZED; /* Are the paddles squeezed past the middle of the element? */ if (kl.timeout.midl <= 0) kl.element.psqam = true; } else /* Are both paddles released and we had gotten a squeeze in this element? */ if (dit != 1 && dah != 1 && kl.element.iamb == PADDLES_SQUEEZED) kl.element.iamb = PADDLES_RELEASED; /* Is the current element finished? */ if (kl.timeout.elem <= 0 && kl.element.curr != NO_ELEMENT) { kl.element.last = kl.element.curr; /* Should we insert an inverted element? */ if (((dit == 1 && dah == 1) || (kl.element.invtd && kl.element.iamb != PADDLES_RELEASED) || (kl.element.iamb == PADDLES_RELEASED && iambicmode == MODE_B && (!midelementmodeB || kl.element.psqam)))) { if (kl.element.last == DAH) set_element_timeouts = kl.element.curr = DIT; else set_element_timeouts = kl.element.curr = DAH; } else { /* No more element */ kl.element.curr = NO_ELEMENT; /* Do we do automatic character spacing? */ if (autocharspacing && dit != 1 && dah != 1) { kl.timeout.dlay = ditlen * 2; kl.dlay_type = CHAR_SPACING_DELAY; } } kl.element.invtd = false; kl.element.iamb = NO_PADDLE_SQUEEZE; kl.element.psqam = false; } /* Is an element currently being played? */ if (kl.element.curr == NO_ELEMENT) { if (dah == 1) /* Dah paddle down ? */ set_element_timeouts = kl.element.curr = DAH; else if (dit == 1) /* Dit paddle down ? */ set_element_timeouts = kl.element.curr = DIT; } /* Do the dah memory */ if (kl.element.curr == DIT && kl.flag.prev.dah != 1 && dah == 1 && dahmemory) kl.element.invtd = true; /* Do the dit memory */ if (kl.element.curr == DAH && kl.flag.prev.dit != 1 && dit == 1 && ditmemory) kl.element.invtd = true; /* If we had a dit (or dah) scheduled to be played after a delay, and the operator lifted both paddles before the end of the delay, and we have no dit (or dah) memory, forget it */ if (kl.timeout.dlay > 0 && dit != 1 && dah != 1 && ((kl.element.curr == DIT && !ditmemory) || (kl.element.curr == DAH && !dahmemory))) set_element_timeouts = kl.element.curr = NO_ELEMENT; /* Do we need to set the playing timeouts of an element? */ switch (set_element_timeouts) { case NO_ELEMENT: /* Cancel any dit or dah */ kl.timeout.beep = 0; kl.timeout.midl = 0; kl.timeout.elem = 0; break; case DIT: /* Schedule a dit? */ kl.timeout.beep = (ditlen * (float)weight) / 50; kl.timeout.midl = kl.timeout.beep / 2; kl.timeout.elem = ditlen * 2; break; case DAH: /* Schedule a dah? */ kl.timeout.beep = (ditlen * (float)weight) / 50 + ditlen * 2; kl.timeout.midl = kl.timeout.beep / 2; kl.timeout.elem = ditlen * 4; break; } kl.flag.prev.dit = dit; kl.flag.prev.dah = dah; bool result = kl.timeout.beep > 0 && kl.timeout.dlay <= 0; return result; }
bool read_iambic_key(ref Keyer_state ks, bool dot, bool dash, ref KeyerLogic kl, float ticklen) { int i, j; int dah = 0, dit = 0; dah_debounce_buf[debounce_buf_i] = dash; dit_debounce_buf[debounce_buf_i] = dot; debounce_buf_i++; //*************************************************** // back to business as usual //*************************************************** /* If the debounce buffer is full, determine the state of the keys */ if (debounce_buf_i >= ks.debounce) { debounce_buf_i = 0; j = 0; for (i = 0; i < ks.debounce; i++) { if (dah_debounce_buf[i]) j++; } dah = (j > ks.debounce / 2) ? 1 : 0; j = 0; for (i = 0; i < ks.debounce; i++) { if (dit_debounce_buf[i]) j++; } dit = (j > ks.debounce / 2) ? 1 : 0; } return klogic(ref kl, dit, dah, ks.wpm, ks.mode, ks.flag.mdlmdB, ks.flag.memory.dit, ks.flag.memory.dah, ks.flag.autospace.khar, ks.flag.autospace.word, ks.weight, ticklen); }