]> git.rkrishnan.org Git - dttsp.git/blob - jDttSP/spottone.c
Bug fixes to jsdr, keyer
[dttsp.git] / jDttSP / spottone.c
1 /* spottone.c */
2
3 /*
4 This file is part of a program that implements a Software-Defined Radio.
5
6 Copyright (C) 2004 by Frank Brickle, AB2KT and Bob McGwier, N4HY
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21
22 The authors can be reached by email at
23
24 ab2kt@arrl.net
25 or
26 rwmcgwier@comcast.net
27
28 or by paper mail at
29
30 The DTTS Microwave Society
31 6 Kathleen Place
32 Bridgewater, NJ 08807
33 */
34
35 #include <spottone.h>
36
37 //------------------------------------------------------------------------
38 // An ASR envelope on a complex phasor,
39 // with asynchronous trigger for R stage.
40 // A/R use sine shaping.
41 //------------------------------------------------------------------------
42
43 BOOLEAN
44 SpotTone(SpotToneGen st) {
45   int i, n = st->size;
46
47   ComplexOSC(st->osc.gen);
48
49   for (i = 0; i < n; i++) {
50
51     // in an envelope stage?
52
53     if (st->stage == SpotTone_RISE) {
54
55       // still going?
56       if (st->rise.have++ < st->rise.want) {
57         st->curr += st->rise.incr;
58         st->mul = st->scl * sin(st->curr * M_PI / 2.0);
59       } else {
60         // no, assert steady-state, force level
61         st->curr = 1.0;
62         st->mul = st->scl;
63         st->stage = SpotTone_STDY;
64         // won't come back into envelopes
65         // until FALL asserted from outside
66       }
67
68     } else if (st->stage == SpotTone_FALL) {
69
70       // still going?
71       if (st->fall.have++ < st->fall.want) {
72         st->curr -= st->fall.incr;
73         st->mul = st->scl * sin(st->curr * M_PI / 2.0);
74       } else {
75         // no, assert trailing, force level
76         st->curr = 0.0;
77         st->mul = 0.0;
78         st->stage = SpotTone_HOLD;
79         // won't come back into envelopes hereafter
80       }
81     }
82
83     // apply envelope
84     // (same base as osc.gen internal buf)
85     CXBdata(st->buf, i) = Cscl(CXBdata(st->buf, i), st->mul);
86   }
87
88   // indicate whether it's turned itself off
89   // sometime during this pass
90   
91   return st->stage != SpotTone_HOLD;
92 }
93
94 //------------------------------------------------------------------------
95 // turn spotting on with current settings
96
97 void
98 SpotToneOn(SpotToneGen st) {
99
100   // gain is in dB
101
102   st->scl = pow(10.0, st->gain / 20.0);
103   st->curr = st->mul = 0.0;
104   
105   // A/R times are in msec
106
107   st->rise.want = (int) (0.5 + st->sr * (st->rise.dur / 1e3));
108   st->rise.have = 0;
109   if (st->rise.want <= 1)
110     st->rise.incr = 1.0;
111   else
112     st->rise.incr = 1.0 / (st->rise.want - 1);
113   
114   st->fall.want = (int) (0.5 + st->sr * (st->fall.dur / 1e3));
115   st->fall.have = 0;
116   if (st->fall.want <= 1)
117     st->fall.incr = 1.0;
118   else
119     st->fall.incr = 1.0 / (st->fall.want - 1);
120
121   // freq is in Hz
122
123   OSCfreq(st->osc.gen) = 2.0 * M_PI * st->osc.freq / st->sr;
124   OSCphase(st->osc.gen) = 0.0;
125
126   st->stage = SpotTone_RISE;
127 }
128
129 //------------------------------------------------------------------------
130 // initiate turn-off
131
132 void
133 SpotToneOff(SpotToneGen st) { st->stage = SpotTone_FALL; }
134
135 //------------------------------------------------------------------------
136
137 void
138 setSpotToneGenVals(SpotToneGen st,
139                    REAL gain,
140                    REAL freq,
141                    REAL rise,
142                    REAL fall) {
143   st->gain = gain;
144   st->osc.freq = freq;
145   st->rise.dur = rise;
146   st->fall.dur = fall;
147 }
148
149 SpotToneGen
150 newSpotToneGen(REAL gain,       // dB
151                REAL freq,
152                REAL rise,       // ms
153                REAL fall,       // ms
154                int size,
155                REAL samplerate) {
156
157   SpotToneGen st = (SpotToneGen) safealloc(1,
158                                            sizeof(SpotToneGenDesc),
159                                            "SpotToneGenDesc");
160
161   setSpotToneGenVals(st, gain, freq, rise, fall);
162   st->size = size;
163   st->sr = samplerate;
164
165   st->osc.gen = newOSC(st->size,
166                        ComplexTone,
167                        st->osc.freq,
168                        0.0,
169                        st->sr,
170                        "SpotTone osc");
171
172   // overload oscillator buf
173   st->buf = newCXB(st->size, OSCCbase(st->osc.gen), "SpotToneGen buf");
174
175   return st;
176 }
177
178 void
179 delSpotToneGen(SpotToneGen st) {
180   if (st) {
181     delCXB(st->buf);
182     delOSC(st->osc.gen);
183     safefree((char *) st);
184   }
185 }