]> git.rkrishnan.org Git - dttsp.git/blob - jDttSP/keyer.c
Major update
[dttsp.git] / jDttSP / keyer.c
1 /* keyer.c */
2 /*
3 This file is part of a program that implements a Software-Defined Radio.
4
5 The code in this file is derived from routines originally written by
6 Pierre-Philippe Coupard for his CWirc X-chat program. That program
7 is issued under the GPL and is
8 Copyright (C) Pierre-Philippe Coupard - 18/06/2003
9
10 This derived version is
11 Copyright (C) 2004 by Frank Brickle, AB2KT and Bob McGwier, N4HY
12
13 This program is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 2 of the License, or
16 (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 GNU General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26
27 The authors can be reached by email at
28
29 ab2kt@arrl.net
30 or
31 rwmcgwier@comcast.net
32
33 or by paper mail at
34
35 The DTTS Microwave Society
36 6 Kathleen Place
37 Bridgewater, NJ 08807
38 */  
39
40 // see below for places where serial port is read
41 // and needs replacement for parallel port hookup
42
43 #include <keyer.h>
44
45 //========================================================================
46 // nothing affected by physical port connection here
47
48 BOOLEAN
49 klogic(KeyerLogic kl,
50        BOOLEAN dit,
51        BOOLEAN dah,
52        double wpm,
53        int iambicmode,
54        BOOLEAN midelementmodeB,
55        BOOLEAN ditmemory,
56        BOOLEAN dahmemory,
57        BOOLEAN autocharspacing,
58        BOOLEAN autowordspacing,
59        int weight,
60        double ticklen) {
61
62   double ditlen = 1200 / wpm;
63   int set_element_timeouts = NO_TIMEOUTS_SCHED;
64
65   /* Do we need to initialize the keyer? */
66   if (!kl->flag.init) {
67     kl->flag.prev.dit = dit;
68     kl->flag.prev.dah = dah;
69     kl->element.last = kl->element.curr = NO_ELEMENT;
70     kl->element.iamb = NO_PADDLE_SQUEEZE;
71     kl->element.psqam = 0;
72     kl->element.invtd = 0;
73     kl->timeout.midl = kl->timeout.beep = kl->timeout.elem = 0;
74     kl->timeout.dlay = 0;
75     kl->dlay_type = NO_DELAY;
76     kl->flag.init = 1;
77   }
78
79   /* Decrement the timeouts */
80   kl->timeout.dlay -= kl->timeout.dlay > 0 ? ticklen : 0;
81   if (kl->timeout.dlay <= 0) {
82     /* If nothing is scheduled to play, and we just did a character
83        spacing delay, and we do auto word spacing, wait for a word
84        spacing delay, otherwise resume the normal element timeout
85        countdowns */
86     if (kl->timeout.elem <= 0 &&
87         kl->dlay_type == CHAR_SPACING_DELAY &&
88         autowordspacing) {
89       kl->timeout.dlay = ditlen * 4;
90       kl->dlay_type = WORD_SPACING_DELAY;
91     } else {
92       kl->dlay_type = NO_DELAY;
93       kl->timeout.midl -= kl->timeout.midl > 0 ? ticklen : 0;
94       kl->timeout.beep -= kl->timeout.beep > 0 ? ticklen : 0;
95       kl->timeout.elem -= kl->timeout.elem > 0 ? ticklen : 0;
96     }
97   }
98
99   /* Are both paddles squeezed? */
100   if (dit && dah) {
101     kl->element.iamb = PADDLES_SQUEEZED;
102
103     /* Are the paddles squeezed past the middle of the element? */
104     if (kl->timeout.midl <= 0)
105       kl->element.psqam = 1;
106   } else
107     /* Are both paddles released and we had gotten a squeeze in this element? */
108   if (!dit && !dah && kl->element.iamb == PADDLES_SQUEEZED)
109     kl->element.iamb = PADDLES_RELEASED;
110
111   /* Is the current element finished? */
112   if (kl->timeout.elem <= 0 && kl->element.curr != NO_ELEMENT) {
113     kl->element.last = kl->element.curr;
114
115     /* Should we insert an inverted element? */
116     if (((dit && dah) ||
117          (kl->element.invtd &&
118           kl->element.iamb != PADDLES_RELEASED) ||
119          (kl->element.iamb == PADDLES_RELEASED &&
120           iambicmode == MODE_B &&
121           (!midelementmodeB || kl->element.psqam)))) {
122       if (kl->element.last == DAH)
123         set_element_timeouts = kl->element.curr = DIT;
124       else
125         set_element_timeouts = kl->element.curr = DAH;
126     } else {
127       /* No more element */
128       kl->element.curr = NO_ELEMENT;
129
130       /* Do we do automatic character spacing? */
131       if (autocharspacing && !dit && !dah) {
132         kl->timeout.dlay = ditlen * 2;
133         kl->dlay_type = CHAR_SPACING_DELAY;
134       }
135     }
136
137     kl->element.invtd = 0;
138     kl->element.iamb = NO_PADDLE_SQUEEZE;
139     kl->element.psqam = 0;
140   }
141
142   /* Is an element currently being played? */
143   if (kl->element.curr == NO_ELEMENT) {
144     if (dah)                    /* Dah paddle down ? */
145       set_element_timeouts = kl->element.curr = DAH;
146     else if (dit)               /* Dit paddle down ? */
147       set_element_timeouts = kl->element.curr = DIT;
148   }
149
150   /* Do the dah memory */
151   if (kl->element.curr == DIT &&
152       !kl->flag.prev.dah &&
153       dah &&
154       dahmemory)
155     kl->element.invtd = 1;
156
157   /* Do the dit memory */
158   if (kl->element.curr == DAH &&
159       !kl->flag.prev.dit &&
160       dit &&
161       ditmemory)
162     kl->element.invtd = 1;
163
164   /* If we had a dit (or dah) scheduled to be played after a delay,
165      and the operator lifted both paddles before the end of the delay,
166      and we have no dit (or dah) memory, forget it */
167
168   if (kl->timeout.dlay > 0 &&
169       !dit &&
170       !dah &&
171       ((kl->element.curr == DIT &&
172         !ditmemory) ||
173        (kl->element.curr == DAH
174         && !dahmemory)))
175     set_element_timeouts = kl->element.curr = NO_ELEMENT;
176
177   /* Do we need to set the playing timeouts of an element? */
178   switch (set_element_timeouts) {
179   case NO_ELEMENT:              /* Cancel any dit or dah */
180     kl->timeout.beep = 0;
181     kl->timeout.midl = 0;
182     kl->timeout.elem = 0;
183     break;
184
185   case DIT:                     /* Schedule a dit? */
186     kl->timeout.beep = (ditlen * (double) weight) / 50;
187     kl->timeout.midl = kl->timeout.beep / 2;
188     kl->timeout.elem = ditlen * 2;
189     break;
190
191   case DAH:                     /* Schedule a dah? */
192     kl->timeout.beep = (ditlen * (double) weight) / 50 + ditlen * 2;
193     kl->timeout.midl = kl->timeout.beep / 2;
194     kl->timeout.elem = ditlen * 4;
195     break;
196   }
197
198   kl->flag.prev.dit = dit;
199   kl->flag.prev.dah = dah;
200
201   return kl->timeout.beep > 0 && kl->timeout.dlay <= 0;
202 }
203
204
205 KeyerState
206 newKeyerState(void) {
207   return (KeyerState) safealloc(1, sizeof(KeyerStateInfo), "newKeyerState");
208 }
209
210 void
211 delKeyerState(KeyerState ks) {
212   safefree((char *) ks);
213 }
214
215 KeyerLogic
216 newKeyerLogic(void) {
217   return (KeyerLogic) safealloc(1, sizeof(KeyerLogicInfo), "newKeyerLogic");
218 }
219
220 void
221 delKeyerLogic(KeyerLogic kl) {
222   safefree((char *) kl);
223 }
224
225 //========================================================================