Keelan Lightfoot пре 7 година
родитељ
комит
c0d45acc38
8 измењених фајлова са 263 додато и 465 уклоњено
  1. 11
    38
      code.go
  2. 24
    102
      common.go
  3. 16
    42
      decoder.go
  4. 73
    81
      demodulator.go
  5. 33
    59
      dsp.go
  6. 47
    71
      encoder.go
  7. 9
    4
      examples/main.go
  8. 50
    68
      modulator.go

+ 11
- 38
code.go Прегледај датотеку

@@ -1,45 +1,18 @@
1
+// Copyright (C) 2017 Keelan Lightfoot
2
+// Copyright (C) 2007-2008 Board of Regents of the University of Wisconsin
3
+//             System (Univ. of Wisconsin-Madison, Trace R&D Center)
4
+// Copyright (C) 2007-2008 Omnitor AB
5
+// Copyright (C) 2007-2008 Voiceriver Inc
6
+//
7
+// This library is free software; you can redistribute it and/or modify it
8
+// under the terms of the GNU Lesser General Public License as published by
9
+// the Free Software Foundation; either version 2.1 of the License, or (at
10
+// your option) any later version.
11
+
1 12
 package openbaudot
2 13
 
3 14
 import "unicode"
4 15
 
5
-/*
6
- * OBL openbaudot Library
7
- *
8
- * Copyright (C) 2017 Keelan Lightfoot
9
- * Copyright (C) 2007-2008 Board of Regents of the University of Wisconsin
10
- *                   System (Univ. of Wisconsin-Madison, Trace R&D Center)
11
- * Copyright (C) 2007-2008 Omnitor AB
12
- * Copyright (C) 2007-2008 Voiceriver Inc
13
- *
14
- * This software was developed with support from the National Institute on
15
- * Disability and Rehabilitation Research, US Dept of Education under Grant
16
- * # H133E990006 and H133E040014
17
- *
18
- * This library is free software; you can redistribute it and/or modify it
19
- * under the terms of the GNU Lesser General Public License as published by
20
- * the Free Software Foundation; either version 2.1 of the License, or (at
21
- * your option) any later version.
22
- *
23
- * This library is distributed in the hope that it will be useful, but
24
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
25
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
26
- * License for more details.
27
- *
28
- * You should have received a copy of the GNU Lesser General Public License
29
- * along with this library; if not, write to the Free Software Foundation,
30
- * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
31
- *
32
- * Please send a copy of any improved versions of the library to:
33
- * Jeff Knighton, Voiceriver Inc, jeff.knighton@voiceriver.com
34
- * Gunnar Hellstrom, Omnitor AB, Box 92054, 12006 Stockholm, SWEDEN
35
- * Gregg Vanderheiden, Trace Center, U of Wisconsin, Madison, Wi 53706
36
- *
37
- * file...: obl.go
38
- * original author.: Keelan Lightfoot
39
- * Created: 20 May 2017
40
- *
41
- */
42
-
43 16
 const (
44 17
 	shiftUnknown = iota
45 18
 	shiftLetter

+ 24
- 102
common.go Прегледај датотеку

@@ -1,95 +1,21 @@
1
+// Copyright (C) 2017 Keelan Lightfoot
2
+// Copyright (C) 2007-2008 Board of Regents of the University of Wisconsin
3
+//             System (Univ. of Wisconsin-Madison, Trace R&D Center)
4
+// Copyright (C) 2007-2008 Omnitor AB
5
+// Copyright (C) 2007-2008 Voiceriver Inc
6
+//
7
+// This library is free software; you can redistribute it and/or modify it
8
+// under the terms of the GNU Lesser General Public License as published by
9
+// the Free Software Foundation; either version 2.1 of the License, or (at
10
+// your option) any later version.
11
+
12
+// Package openbaudot provides a set of tools to encode, modulate, demodulate and
13
+// baudot/TTY/RTTY data streams
1 14
 package openbaudot
2 15
 
3 16
 import "math"
4 17
 
5
-/*
6
- * OBL openbaudot Library
7
- *
8
- * Copyright (C) 2017 Keelan Lightfoot
9
- * Copyright (C) 2007-2008 Board of Regents of the University of Wisconsin
10
- *                   System (Univ. of Wisconsin-Madison, Trace R&D Center)
11
- * Copyright (C) 2007-2008 Omnitor AB
12
- * Copyright (C) 2007-2008 Voiceriver Inc
13
- *
14
- * This software was developed with support from the National Institute on
15
- * Disability and Rehabilitation Research, US Dept of Education under Grant
16
- * # H133E990006 and H133E040014
17
- *
18
- * This library is free software; you can redistribute it and/or modify it
19
- * under the terms of the GNU Lesser General Public License as published by
20
- * the Free Software Foundation; either version 2.1 of the License, or (at
21
- * your option) any later version.
22
- *
23
- * This library is distributed in the hope that it will be useful, but
24
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
25
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
26
- * License for more details.
27
- *
28
- * You should have received a copy of the GNU Lesser General Public License
29
- * along with this library; if not, write to the Free Software Foundation,
30
- * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
31
- *
32
- * Please send a copy of any improved versions of the library to:
33
- * Jeff Knighton, Voiceriver Inc, jeff.knighton@voiceriver.com
34
- * Gunnar Hellstrom, Omnitor AB, Box 92054, 12006 Stockholm, SWEDEN
35
- * Gregg Vanderheiden, Trace Center, U of Wisconsin, Madison, Wi 53706
36
- *
37
- * file...: obl.go
38
- * original author.: Keelan Lightfoot
39
- * Created: 20 May 2017
40
- *
41
- */
42
-
43 18
 const (
44
-
45
-	// LETR  Letters Baudot code
46
-	LETR byte = 0x1f
47
-	// FIGR Figures Baudot code
48
-	FIGR byte = 0x1b
49
-	// CRLFThresh start looking for space
50
-	CRLFThresh = 60
51
-	// CRLFForce force CR-LF
52
-	CRLFForce = 72
53
-
54
-	// ModStateIdle no data in mod buffer, idling
55
-	ModStateIdle = 0
56
-	// ModStateStart modulating start bit
57
-	ModStateStart = 1
58
-	// ModStateBit modulating a baudot bit
59
-	ModStateBit = 2
60
-	// ModStateStop modulating stop bit
61
-	ModStateStop = 3
62
-	// ModStateHold modulating hold tone
63
-	ModStateHold = 4
64
-
65
-	// LPFOrder Low pass filter order
66
-	LPFOrder = 20 // 20
67
-
68
-	/* oblDemodulate() state machine states */
69
-
70
-	// DemodStateWaitStart wait for start bit
71
-	DemodStateWaitStart = 0 /**/
72
-	// DemodStateSample sampling demod bits
73
-	DemodStateSample = 1 /**/
74
-	// DemodStateWaitStop wait for stop bit
75
-	DemodStateWaitStop = 2 /**/
76
-
77
-	// MinThresh ratio for vaild signal
78
-	MinThresh = 3
79
-
80
-	/* auto baud detection state machine states */
81
-
82
-	// AutobaudStateWaitStart waiting for start bit
83
-	AutobaudStateWaitStart = 0
84
-	// AutobaudStateWaitZeroX waiting for zero crossing
85
-	AutobaudStateWaitZeroX = 1
86
-	// AutobaudStateWaitStop waiting for stop bit
87
-	AutobaudStateWaitStop = 2
88
-	// AutobaudStateDisabled disabled
89
-	AutobaudStateDisabled = 3
90
-
91
-	/* top level state machines states */
92
-
93 19
 	// EventDemodChar is fun
94 20
 	EventDemodChar = iota
95 21
 	// EventDemodAbort is fun
@@ -102,21 +28,21 @@ const (
102 28
 	EventIdle
103 29
 )
104 30
 
105
-/* precomputed constants for demodDsp */
31
+// Callback is func
32
+type Callback func(event int, data interface{})
106 33
 
107
-var (
108
-	// sampleRate Sample rate
109
-	sampleRate = 8000
110
-	// Beta filter bandwidth factor
111
-	Beta = 0.95 //.95
112
-)
34
+// ModemSettings is fun
35
+type ModemSettings struct {
36
+	Baud       float64
37
+	StopBits   float64
38
+	DataBits   int
39
+	SampleRate int
40
+}
113 41
 
114
-func multq(x, y int16) int16 {
42
+func multq15(x, y int16) int16 {
115 43
 	return int16((int(x) * int(y)) >> 15)
116
-
117 44
 }
118 45
 
119
-// abs16 returns the absolute value of x.
120 46
 func abs16(x int16) int16 {
121 47
 	if x < 0 {
122 48
 		return -x
@@ -124,7 +50,6 @@ func abs16(x int16) int16 {
124 50
 	return x
125 51
 }
126 52
 
127
-// absint returns the absolute value of x.
128 53
 func absint(x int) int {
129 54
 	if x < 0 {
130 55
 		return -x
@@ -132,11 +57,8 @@ func absint(x int) int {
132 57
 	return x
133 58
 }
134 59
 
135
-func calculateW(oneF int, zeroF int) (float64, float64) {
60
+func calculateW(oneF int, zeroF int, sampleRate int) (float64, float64) {
136 61
 	wOne := (2 * math.Pi * float64(oneF) / float64(sampleRate))   //1400 // WOne 1 freq in normalised rads
137 62
 	wZero := (2 * math.Pi * float64(zeroF) / float64(sampleRate)) //1800 // WZero 0 freq in normazlised rads
138 63
 	return wOne, wZero
139 64
 }
140
-
141
-// Callback is func
142
-type Callback func(event int, data interface{})

+ 16
- 42
decoder.go Прегледај датотеку

@@ -1,51 +1,25 @@
1
-package openbaudot
1
+// Copyright (C) 2017 Keelan Lightfoot
2
+// Copyright (C) 2007-2008 Board of Regents of the University of Wisconsin
3
+//             System (Univ. of Wisconsin-Madison, Trace R&D Center)
4
+// Copyright (C) 2007-2008 Omnitor AB
5
+// Copyright (C) 2007-2008 Voiceriver Inc
6
+//
7
+// This library is free software; you can redistribute it and/or modify it
8
+// under the terms of the GNU Lesser General Public License as published by
9
+// the Free Software Foundation; either version 2.1 of the License, or (at
10
+// your option) any later version.
2 11
 
3
-/*
4
- * OBL openbaudot Library
5
- *
6
- * Copyright (C) 2017 Keelan Lightfoot
7
- * Copyright (C) 2007-2008 Board of Regents of the University of Wisconsin
8
- *                   System (Univ. of Wisconsin-Madison, Trace R&D Center)
9
- * Copyright (C) 2007-2008 Omnitor AB
10
- * Copyright (C) 2007-2008 Voiceriver Inc
11
- *
12
- * This software was developed with support from the National Institute on
13
- * Disability and Rehabilitation Research, US Dept of Education under Grant
14
- * # H133E990006 and H133E040014
15
- *
16
- * This library is free software; you can redistribute it and/or modify it
17
- * under the terms of the GNU Lesser General Public License as published by
18
- * the Free Software Foundation; either version 2.1 of the License, or (at
19
- * your option) any later version.
20
- *
21
- * This library is distributed in the hope that it will be useful, but
22
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
23
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
24
- * License for more details.
25
- *
26
- * You should have received a copy of the GNU Lesser General Public License
27
- * along with this library; if not, write to the Free Software Foundation,
28
- * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
29
- *
30
- * Please send a copy of any improved versions of the library to:
31
- * Jeff Knighton, Voiceriver Inc, jeff.knighton@voiceriver.com
32
- * Gunnar Hellstrom, Omnitor AB, Box 92054, 12006 Stockholm, SWEDEN
33
- * Gregg Vanderheiden, Trace Center, U of Wisconsin, Madison, Wi 53706
34
- *
35
- * file...: obl.go
36
- * original author.: Keelan Lightfoot
37
- * Created: 20 May 2017
38
- *
39
- */
12
+package openbaudot
40 13
 
41
-// Decoder is fun
14
+// Decoder converts a stream of bytes representing baudot codes into a stream
15
+// of unicode runes.
42 16
 type Decoder struct {
43 17
 	input   chan byte
44 18
 	output  chan rune
45 19
 	charset *CodeSet
46 20
 }
47 21
 
48
-// NewDecoder is fun
22
+// NewDecoder creates a new decoder.
49 23
 func NewDecoder(input chan byte, output chan rune, charset *CodeSet) *Decoder {
50 24
 	d := new(Decoder)
51 25
 	d.input = input
@@ -60,10 +34,10 @@ func (d *Decoder) run() {
60 34
 	shift := shiftLetter
61 35
 	for c := range d.input {
62 36
 		switch c {
63
-		case LETR:
37
+		case d.charset.UnshiftCode:
64 38
 			shift = shiftLetter
65 39
 			//obl.callback(EventDemodCase, Letters)
66
-		case FIGR:
40
+		case d.charset.ShiftCode:
67 41
 			shift = shiftFigure
68 42
 		//	obl.callback(EventDemodCase, Figures)
69 43
 		default:

+ 73
- 81
demodulator.go Прегледај датотеку

@@ -1,44 +1,28 @@
1
+// Copyright (C) 2017 Keelan Lightfoot
2
+// Copyright (C) 2007-2008 Board of Regents of the University of Wisconsin
3
+//             System (Univ. of Wisconsin-Madison, Trace R&D Center)
4
+// Copyright (C) 2007-2008 Omnitor AB
5
+// Copyright (C) 2007-2008 Voiceriver Inc
6
+//
7
+// This library is free software; you can redistribute it and/or modify it
8
+// under the terms of the GNU Lesser General Public License as published by
9
+// the Free Software Foundation; either version 2.1 of the License, or (at
10
+// your option) any later version.
11
+
1 12
 package openbaudot
2 13
 
3 14
 import "math"
4 15
 
5
-/*
6
- * OBL openbaudot Library
7
- *
8
- * Copyright (C) 2017 Keelan Lightfoot
9
- * Copyright (C) 2007-2008 Board of Regents of the University of Wisconsin
10
- *                   System (Univ. of Wisconsin-Madison, Trace R&D Center)
11
- * Copyright (C) 2007-2008 Omnitor AB
12
- * Copyright (C) 2007-2008 Voiceriver Inc
13
- *
14
- * This software was developed with support from the National Institute on
15
- * Disability and Rehabilitation Research, US Dept of Education under Grant
16
- * # H133E990006 and H133E040014
17
- *
18
- * This library is free software; you can redistribute it and/or modify it
19
- * under the terms of the GNU Lesser General Public License as published by
20
- * the Free Software Foundation; either version 2.1 of the License, or (at
21
- * your option) any later version.
22
- *
23
- * This library is distributed in the hope that it will be useful, but
24
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
25
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
26
- * License for more details.
27
- *
28
- * You should have received a copy of the GNU Lesser General Public License
29
- * along with this library; if not, write to the Free Software Foundation,
30
- * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
31
- *
32
- * Please send a copy of any improved versions of the library to:
33
- * Jeff Knighton, Voiceriver Inc, jeff.knighton@voiceriver.com
34
- * Gunnar Hellstrom, Omnitor AB, Box 92054, 12006 Stockholm, SWEDEN
35
- * Gregg Vanderheiden, Trace Center, U of Wisconsin, Madison, Wi 53706
36
- *
37
- * file...: obl.go
38
- * original author.: Keelan Lightfoot
39
- * Created: 20 May 2017
40
- *
41
- */
16
+const (
17
+	demodStateWaitStart = iota
18
+	demodStateSample
19
+	demodStateWaitStop
20
+
21
+	autobaudStateWaitStart = iota
22
+	autobaudStateWaitZeroX
23
+	autobaudStateWaitStop
24
+	autobaudStateDisabled
25
+)
42 26
 
43 27
 // Demodulator is fun
44 28
 type Demodulator struct {
@@ -54,6 +38,7 @@ type Demodulator struct {
54 38
 	samplesPerBit int
55 39
 	dsp           *dsp
56 40
 	dataBits      int
41
+	sampleRate    int
57 42
 	autobaud      struct {
58 43
 		enabled  bool    // audio baud detection enable/disable flag
59 44
 		state    int     // auto buad detection state mach state
@@ -63,30 +48,37 @@ type Demodulator struct {
63 48
 }
64 49
 
65 50
 // NewDemodulator is fun
66
-func NewDemodulator(baud float64, stopBits float64, dataBits int, input chan int16, output chan byte) *Demodulator {
51
+func NewDemodulator(s ModemSettings, input chan int16, output chan byte) *Demodulator {
67 52
 
68 53
 	d := new(Demodulator)
69 54
 	d.input = input
70 55
 	d.output = output
71
-	d.state = DemodStateWaitStart
56
+	d.state = demodStateWaitStart
72 57
 	//d.lettersFigures = Letters
73
-	d.baud = baud
74
-	d.dataBits = dataBits
75
-	d.samplesPerBit = int(float64(sampleRate) / d.baud)
58
+	d.baud = s.Baud
59
+	d.dataBits = s.DataBits
60
+	d.sampleRate = s.SampleRate
61
+	d.samplesPerBit = int(float64(d.sampleRate) / d.baud)
62
+
63
+	wOne, wZero := calculateW(2125, 2295, d.sampleRate)
76 64
 
77
-	wOne, wZero := calculateW(2125, 2295)
65
+	lfpOrder := 20
66
+	beta := 0.95 //.95
78 67
 
79 68
 	d.dsp = &dsp{
80
-		c1: int16((2.0 * math.Cos(wOne) * Beta) * 32768),
81
-		c2: int16(Beta * Beta * 32768),
82
-		c3: int16((2.0 * math.Cos(wZero) * Beta) * 32768),
69
+		c1:         int16((2.0 * math.Cos(wOne) * beta) * 32768),
70
+		c2:         int16(beta * beta * 32768),
71
+		c3:         int16((2.0 * math.Cos(wZero) * beta) * 32768),
72
+		demLpfIn:   make([]int16, lfpOrder),
73
+		demTotalIn: make([]int16, lfpOrder),
74
+		lpfOrder:   lfpOrder,
83 75
 	}
84 76
 
85 77
 	d.autobaud.estimate = d.baud
86 78
 	if d.autobaud.enabled {
87
-		d.autobaud.state = AutobaudStateWaitStart
79
+		d.autobaud.state = autobaudStateWaitStart
88 80
 	} else {
89
-		d.autobaud.state = AutobaudStateDisabled
81
+		d.autobaud.state = autobaudStateDisabled
90 82
 	}
91 83
 	go d.run()
92 84
 	return d
@@ -111,21 +103,21 @@ func (d *Demodulator) run() {
111 103
 		nextState = d.state
112 104
 
113 105
 		switch d.state {
114
-		case DemodStateWaitStart:
106
+		case demodStateWaitStart:
115 107
 			/*
116 108
 			   The demodulator sits in this state when it
117
-			   is waiting for a start bit.  When a sampleRateK
109
+			   is waiting for a start bit.  When a d.sampleRateK
118 110
 			   "0" (1800 Hz) start-bit is detected that is
119 111
 			   above a minimum threshold it transitions
120 112
 			   out of this state.
121 113
 			*/
122 114
 			if d.dsp.signalPresent() {
123
-				d.sample = int(float64(sampleRate)/d.baud + float64(sampleRate)/(2*d.baud))
115
+				d.sample = int(float64(d.sampleRate)/d.baud + float64(d.sampleRate)/(2*d.baud))
124 116
 				d.baudot = 0
125 117
 				d.bit = 0
126
-				nextState = DemodStateSample
118
+				nextState = demodStateSample
127 119
 			}
128
-		case DemodStateSample:
120
+		case demodStateSample:
129 121
 
130 122
 			d.sample--
131 123
 			if d.sample == 0 {
@@ -140,15 +132,15 @@ func (d *Demodulator) run() {
140 132
 					d.output <- d.baudot
141 133
 					//fmt.Printf("Demodulator done %d\n", d.baudot)
142 134
 
143
-					d.sample = int(float64(sampleRate) / d.baud)
144
-					nextState = DemodStateWaitStop
135
+					d.sample = int(float64(d.sampleRate) / d.baud)
136
+					nextState = demodStateWaitStop
145 137
 				} else {
146 138
 					/* sample next bit 1 bit-period later */
147
-					d.sample = int(float64(sampleRate) / d.baud)
139
+					d.sample = int(float64(d.sampleRate) / d.baud)
148 140
 				}
149 141
 			}
150 142
 
151
-			/* check for sampleRateK signal drop out */
143
+			/* check for d.sampleRateK signal drop out */
152 144
 
153 145
 			//return d.demTotal != 0 && d.demLpf < -1*MinThresh*d.demTotal
154 146
 
@@ -156,21 +148,21 @@ func (d *Demodulator) run() {
156 148
 				d.minSigTimeout++
157 149
 
158 150
 				/* If signal drops out for approx one bit period
159
-				   assume we have lost sampleRateK signal */
151
+				   assume we have lost d.sampleRateK signal */
160 152
 				if d.minSigTimeout > d.samplesPerBit {
161
-					nextState = DemodStateWaitStart
153
+					nextState = demodStateWaitStart
162 154
 				}
163 155
 			} else {
164 156
 				d.minSigTimeout = 0
165 157
 			}
166 158
 
167
-		case DemodStateWaitStop:
159
+		case demodStateWaitStop:
168 160
 
169 161
 			/* wait until we are in the middle of stop bit */
170 162
 
171 163
 			d.sample--
172 164
 			if d.sample == 0 {
173
-				nextState = DemodStateWaitStart
165
+				nextState = demodStateWaitStart
174 166
 			}
175 167
 
176 168
 		}
@@ -195,13 +187,13 @@ func (d *Demodulator) run() {
195 187
 		nextState = d.autobaud.state
196 188
 
197 189
 		switch d.autobaud.state {
198
-		case AutobaudStateWaitStart:
190
+		case autobaudStateWaitStart:
199 191
 			/* start bit kicks off this state machine */
200
-			if d.state == DemodStateSample {
201
-				nextState = AutobaudStateWaitZeroX
192
+			if d.state == demodStateSample {
193
+				nextState = autobaudStateWaitZeroX
202 194
 				d.autobaud.zeroX = 0
203 195
 			}
204
-		case AutobaudStateWaitZeroX:
196
+		case autobaudStateWaitZeroX:
205 197
 
206 198
 			d.autobaud.zeroX++
207 199
 
@@ -210,50 +202,50 @@ func (d *Demodulator) run() {
210 202
 
211 203
 				/* determine distance to closest edge assuming 50 baud */
212 204
 
213
-				dist75 := sampleRate / 75
205
+				dist75 := d.sampleRate / 75
214 206
 				edge = 0
215 207
 				for i := 0; i < (d.dataBits + 1); i++ {
216 208
 					dist = absint(edge - d.autobaud.zeroX)
217 209
 					if dist < dist75 {
218 210
 						dist75 = dist
219 211
 					}
220
-					edge += sampleRate / 75
212
+					edge += d.sampleRate / 75
221 213
 				}
222 214
 
223 215
 				/* determine distance to closest edge assuming 50 baud */
224 216
 
225
-				dist50 := sampleRate / 50
217
+				dist50 := d.sampleRate / 50
226 218
 				edge = 0
227 219
 				for i := 0; i < (d.dataBits + 1); i++ {
228 220
 					dist = absint(edge - d.autobaud.zeroX)
229 221
 					if dist < dist50 {
230 222
 						dist50 = dist
231 223
 					}
232
-					edge += sampleRate / 50
224
+					edge += d.sampleRate / 50
233 225
 				}
234 226
 
235 227
 				/* determine distance to closest edge assuming 47 baud */
236 228
 
237
-				dist47 := sampleRate / 47
229
+				dist47 := d.sampleRate / 47
238 230
 				edge = 0
239 231
 				for i := 0; i < (d.dataBits + 1); i++ {
240 232
 					dist = absint(edge - d.autobaud.zeroX)
241 233
 					if dist < dist47 {
242 234
 						dist47 = dist
243 235
 					}
244
-					edge += sampleRate / 47
236
+					edge += d.sampleRate / 47
245 237
 				}
246 238
 
247 239
 				/* determine distance to closest edge assuming 45 baud */
248 240
 
249
-				dist45 := sampleRate / 45
241
+				dist45 := d.sampleRate / 45
250 242
 				edge = 0
251 243
 				for i := 0; i < (d.dataBits + 1); i++ {
252 244
 					dist = absint(edge - d.autobaud.zeroX)
253 245
 					if dist < dist45 {
254 246
 						dist45 = dist
255 247
 					}
256
-					edge += sampleRate / 45
248
+					edge += d.sampleRate / 45
257 249
 				}
258 250
 
259 251
 				/* update 3-point smoothed distance estimates */
@@ -291,22 +283,22 @@ func (d *Demodulator) run() {
291 283
 
292 284
 				//printf("obl.autobaud_zerox: %d dist50: %02d dist47: %02d dist45: %02d est: %d\n",
293 285
 				//       obl.autobaud_zerox, dist50Smooth, dist47Smooth, dist45Smooth, obl.dem_baud_est);
294
-				nextState = AutobaudStateWaitStop
286
+				nextState = autobaudStateWaitStop
295 287
 			}
296 288
 
297
-			/* reset autobaud state machine, e.g. if sampleRateK drops out before
289
+			/* reset autobaud state machine, e.g. if d.sampleRateK drops out before
298 290
 			   we get a zero crossing */
299 291
 
300
-			if d.state != DemodStateSample {
301
-				nextState = AutobaudStateWaitStop
292
+			if d.state != demodStateSample {
293
+				nextState = autobaudStateWaitStop
302 294
 			}
303 295
 
304
-		case AutobaudStateWaitStop:
305
-			if d.state == DemodStateWaitStop {
306
-				nextState = AutobaudStateWaitStart
296
+		case autobaudStateWaitStop:
297
+			if d.state == demodStateWaitStop {
298
+				nextState = autobaudStateWaitStart
307 299
 			}
308 300
 
309
-		case AutobaudStateDisabled:
301
+		case autobaudStateDisabled:
310 302
 
311 303
 		default:
312 304
 

+ 33
- 59
dsp.go Прегледај датотеку

@@ -1,68 +1,42 @@
1
-package openbaudot
1
+// Copyright (C) 2017 Keelan Lightfoot
2
+// Copyright (C) 2007-2008 Board of Regents of the University of Wisconsin
3
+//             System (Univ. of Wisconsin-Madison, Trace R&D Center)
4
+// Copyright (C) 2007-2008 Omnitor AB
5
+// Copyright (C) 2007-2008 Voiceriver Inc
6
+//
7
+// This library is free software; you can redistribute it and/or modify it
8
+// under the terms of the GNU Lesser General Public License as published by
9
+// the Free Software Foundation; either version 2.1 of the License, or (at
10
+// your option) any later version.
2 11
 
3
-/*
4
- * OBL openbaudot Library
5
- *
6
- * Copyright (C) 2017 Keelan Lightfoot
7
- * Copyright (C) 2007-2008 Board of Regents of the University of Wisconsin
8
- *                   System (Univ. of Wisconsin-Madison, Trace R&D Center)
9
- * Copyright (C) 2007-2008 Omnitor AB
10
- * Copyright (C) 2007-2008 Voiceriver Inc
11
- *
12
- * This software was developed with support from the National Institute on
13
- * Disability and Rehabilitation Research, US Dept of Education under Grant
14
- * # H133E990006 and H133E040014
15
- *
16
- * This library is free software; you can redistribute it and/or modify it
17
- * under the terms of the GNU Lesser General Public License as published by
18
- * the Free Software Foundation; either version 2.1 of the License, or (at
19
- * your option) any later version.
20
- *
21
- * This library is distributed in the hope that it will be useful, but
22
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
23
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
24
- * License for more details.
25
- *
26
- * You should have received a copy of the GNU Lesser General Public License
27
- * along with this library; if not, write to the Free Software Foundation,
28
- * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
29
- *
30
- * Please send a copy of any improved versions of the library to:
31
- * Jeff Knighton, Voiceriver Inc, jeff.knighton@voiceriver.com
32
- * Gunnar Hellstrom, Omnitor AB, Box 92054, 12006 Stockholm, SWEDEN
33
- * Gregg Vanderheiden, Trace Center, U of Wisconsin, Madison, Wi 53706
34
- *
35
- * file...: obl.go
36
- * original author.: Keelan Lightfoot
37
- * Created: 20 May 2017
38
- *
39
- */
12
+package openbaudot
40 13
 
41 14
 type dsp struct {
42
-	demOne      [2]float64      // previous 2 output samples of one filter
43
-	demOneQ0    [2]int16        // previous 2 output samples of one filter
44
-	demZero     [2]float64      // previous 2 output samples of zero filter
45
-	demZeroQ0   [2]int16        // previous 2 output samples of one filter
46
-	demLpfIn    [LPFOrder]int16 // previous LPFOrder LPF input samples
47
-	pdemLpfIn   int             // ptr to oldest LPF input sample
48
-	demLpf      int             // current LPF output value
49
-	demTotalIn  [LPFOrder]int16 // previous LPFOrder energy input samples
50
-	pdemTotalIn int             // ptr to oldest energy sample
51
-	demTotal    int             // current energy output value
52
-	c1, c2, c3  int16           // precomputed values for demod_dsp
53
-
15
+	demOne      [2]float64 // previous 2 output samples of one filter
16
+	demOneQ0    [2]int16   // previous 2 output samples of one filter
17
+	demZero     [2]float64 // previous 2 output samples of zero filter
18
+	demZeroQ0   [2]int16   // previous 2 output samples of one filter
19
+	demLpfIn    []int16    // previous LPFOrder LPF input samples
20
+	pdemLpfIn   int        // ptr to oldest LPF input sample
21
+	demLpf      int        // current LPF output value
22
+	demTotalIn  []int16    // previous LPFOrder energy input samples
23
+	pdemTotalIn int        // ptr to oldest energy sample
24
+	demTotal    int        // current energy output value
25
+	c1, c2, c3  int16      // precomputed values for demod_dsp
26
+	lpfOrder    int        // LPFOrder Low pass filter order
27
+	minThresh   int        // MinThresh ratio for vaild signal
54 28
 }
55 29
 
56 30
 func (d *dsp) edgeDetected() bool {
57
-	return d.demLpf > MinThresh*d.demTotal
31
+	return d.demLpf > d.minThresh*d.demTotal
58 32
 }
59 33
 
60 34
 func (d *dsp) dropout() bool {
61
-	return absint(d.demLpf) < MinThresh*d.demTotal || d.demTotal == 0
35
+	return absint(d.demLpf) < d.minThresh*d.demTotal || d.demTotal == 0
62 36
 }
63 37
 
64 38
 func (d *dsp) signalPresent() bool {
65
-	return d.demTotal != 0 && d.demLpf < -1*MinThresh*d.demTotal
39
+	return d.demTotal != 0 && d.demLpf < -1*d.minThresh*d.demTotal
66 40
 }
67 41
 
68 42
 func (d *dsp) onePresent() bool {
@@ -74,14 +48,14 @@ func (d *dsp) demod(sam int16) { //short *buffer, int samples)
74 48
 	sam >>= 5
75 49
 
76 50
 	oneQ0 := sam
77
-	oneQ0 += multq(d.c1, d.demOneQ0[0])
78
-	oneQ0 -= multq(d.c2, d.demOneQ0[1])
51
+	oneQ0 += multq15(d.c1, d.demOneQ0[0])
52
+	oneQ0 -= multq15(d.c2, d.demOneQ0[1])
79 53
 	d.demOneQ0[1] = d.demOneQ0[0]
80 54
 	d.demOneQ0[0] = oneQ0
81 55
 
82 56
 	zeroQ0 := sam
83
-	zeroQ0 += multq(d.c3, d.demZeroQ0[0])
84
-	zeroQ0 -= multq(d.c2, d.demZeroQ0[1])
57
+	zeroQ0 += multq15(d.c3, d.demZeroQ0[0])
58
+	zeroQ0 -= multq15(d.c2, d.demZeroQ0[1])
85 59
 	d.demZeroQ0[1] = d.demZeroQ0[0]
86 60
 	d.demZeroQ0[0] = zeroQ0
87 61
 
@@ -89,7 +63,7 @@ func (d *dsp) demod(sam int16) { //short *buffer, int samples)
89 63
 	d.demLpf -= int(d.demLpfIn[d.pdemLpfIn])
90 64
 	d.demLpf += int(x)
91 65
 	d.demLpfIn[d.pdemLpfIn] = x
92
-	d.pdemLpfIn = (d.pdemLpfIn + 1) % LPFOrder
66
+	d.pdemLpfIn = (d.pdemLpfIn + 1) % d.lpfOrder
93 67
 
94 68
 	/* now work out total energy estimate, this is used to
95 69
 	   determine if a valid signal is present by comparing
@@ -99,5 +73,5 @@ func (d *dsp) demod(sam int16) { //short *buffer, int samples)
99 73
 	d.demTotal -= int(d.demTotalIn[d.pdemTotalIn])
100 74
 	d.demTotal += int(x)
101 75
 	d.demTotalIn[d.pdemTotalIn] = x
102
-	d.pdemTotalIn = (d.pdemTotalIn + 1) % LPFOrder
76
+	d.pdemTotalIn = (d.pdemTotalIn + 1) % d.lpfOrder
103 77
 }

+ 47
- 71
encoder.go Прегледај датотеку

@@ -1,50 +1,25 @@
1
-package openbaudot
1
+// Copyright (C) 2017 Keelan Lightfoot
2
+// Copyright (C) 2007-2008 Board of Regents of the University of Wisconsin
3
+//             System (Univ. of Wisconsin-Madison, Trace R&D Center)
4
+// Copyright (C) 2007-2008 Omnitor AB
5
+// Copyright (C) 2007-2008 Voiceriver Inc
6
+//
7
+// This library is free software; you can redistribute it and/or modify it
8
+// under the terms of the GNU Lesser General Public License as published by
9
+// the Free Software Foundation; either version 2.1 of the License, or (at
10
+// your option) any later version.
2 11
 
3
-/*
4
- * OBL openbaudot Library
5
- *
6
- * Copyright (C) 2017 Keelan Lightfoot
7
- * Copyright (C) 2007-2008 Board of Regents of the University of Wisconsin
8
- *                   System (Univ. of Wisconsin-Madison, Trace R&D Center)
9
- * Copyright (C) 2007-2008 Omnitor AB
10
- * Copyright (C) 2007-2008 Voiceriver Inc
11
- *
12
- * This software was developed with support from the National Institute on
13
- * Disability and Rehabilitation Research, US Dept of Education under Grant
14
- * # H133E990006 and H133E040014
15
- *
16
- * This library is free software; you can redistribute it and/or modify it
17
- * under the terms of the GNU Lesser General Public License as published by
18
- * the Free Software Foundation; either version 2.1 of the License, or (at
19
- * your option) any later version.
20
- *
21
- * This library is distributed in the hope that it will be useful, but
22
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
23
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
24
- * License for more details.
25
- *
26
- * You should have received a copy of the GNU Lesser General Public License
27
- * along with this library; if not, write to the Free Software Foundation,
28
- * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
29
- *
30
- * Please send a copy of any improved versions of the library to:
31
- * Jeff Knighton, Voiceriver Inc, jeff.knighton@voiceriver.com
32
- * Gunnar Hellstrom, Omnitor AB, Box 92054, 12006 Stockholm, SWEDEN
33
- * Gregg Vanderheiden, Trace Center, U of Wisconsin, Madison, Wi 53706
34
- *
35
- * file...: obl.go
36
- * original author.: Keelan Lightfoot
37
- * Created: 20 May 2017
38
- *
39
- */
12
+package openbaudot
40 13
 
41 14
 // Encoder is fun
42 15
 type Encoder struct {
43
-	input    chan rune
44
-	output   chan byte
45
-	autoWrap bool // true for auto CRLF mode
46
-	autoCRLF bool
47
-	charset  *CodeSet
16
+	input           chan rune
17
+	output          chan byte
18
+	autoWrap        bool // true for auto CRLF mode
19
+	autoCRLF        bool
20
+	charset         *CodeSet
21
+	crlfThresh      int // start looking for a space to replace with a crlf at this threshold
22
+	crlfForceThresh int // force a crlf if it hasn't happend by this threshold
48 23
 }
49 24
 
50 25
 // NewEncoder is fun
@@ -53,27 +28,28 @@ func NewEncoder(input chan rune, output chan byte, charset *CodeSet) *Encoder {
53 28
 	e.input = input
54 29
 	e.output = output
55 30
 	e.charset = charset
56
-
31
+	e.crlfThresh = 60
32
+	e.crlfForceThresh = 72
57 33
 	go e.run()
58 34
 	return e
59 35
 }
60 36
 
61 37
 // EncodeString is fun
62
-func (t *Encoder) EncodeString(s string) {
38
+func (e *Encoder) EncodeString(s string) {
63 39
 	go func() {
64 40
 		for _, c := range s {
65
-			t.input <- c
41
+			e.input <- c
66 42
 		}
67 43
 	}()
68 44
 }
69 45
 
70
-func (t *Encoder) run() {
46
+func (e *Encoder) run() {
71 47
 
72 48
 	var modCase int           // current Letters/Figures state
73 49
 	var charsWithoutCRLF int  // number of chars we have handled without inserting a CR-LF
74 50
 	var charsWithoutShift int // number of chars we have handled without seeing a shift
75
-	for r := range t.input {
76
-		c := t.charset.toCode(r)
51
+	for r := range e.input {
52
+		c := e.charset.toCode(r)
77 53
 
78 54
 		/*this rune can either be rendered as a Figures character,
79 55
 		  a Letters character or WHITESPACE which can be rendered by
@@ -92,7 +68,7 @@ func (t *Encoder) run() {
92 68
 			we must send something, so we'll choose the more common
93 69
 			Letters case*/
94 70
 			if modCase == shiftUnknown {
95
-				t.output <- t.charset.unshift()
71
+				e.output <- e.charset.unshift()
96 72
 			}
97 73
 
98 74
 			modCase = shiftWhitespace
@@ -101,9 +77,9 @@ func (t *Encoder) run() {
101 77
 			  our modulator's current state, so add a new case char
102 78
 			  here*/
103 79
 			if c.shift == shiftLetter {
104
-				t.output <- t.charset.unshift()
80
+				e.output <- e.charset.unshift()
105 81
 			} else {
106
-				t.output <- t.charset.shift()
82
+				e.output <- e.charset.shift()
107 83
 			}
108 84
 
109 85
 			/*and save our current state*/
@@ -119,11 +95,11 @@ func (t *Encoder) run() {
119 95
 		   at least every 72 characters. */
120 96
 		if charsWithoutShift > 70 {
121 97
 			if modCase == shiftWhitespace {
122
-				t.output <- t.charset.unshift() /*doesn't matter which, so how 'bout LETR*/
98
+				e.output <- e.charset.unshift() /*doesn't matter which, so how 'bout LETR*/
123 99
 			} else if modCase == shiftLetter {
124
-				t.output <- t.charset.unshift()
100
+				e.output <- e.charset.unshift()
125 101
 			} else {
126
-				t.output <- t.charset.shift()
102
+				e.output <- e.charset.shift()
127 103
 			}
128 104
 			charsWithoutShift = 0
129 105
 		}
@@ -131,38 +107,38 @@ func (t *Encoder) run() {
131 107
 		/* we need to ensure that we send a carriage return/linefeed
132 108
 		 * at least every 72 characters, but we start looking for a
133 109
 		 * space character starting at 60 characters */
134
-		if !t.autoWrap {
110
+		if !e.autoWrap {
135 111
 			/*we just insert our regular character*/
136
-			t.output <- c.toByte()
112
+			e.output <- c.toByte()
137 113
 
138
-			if t.autoCRLF {
114
+			if e.autoCRLF {
139 115
 				if r == '\n' {
140
-					t.output <- t.charset.toByte('\r')
116
+					e.output <- e.charset.toByte('\r')
141 117
 				} else if r == '\r' {
142
-					t.output <- t.charset.toByte('\n')
118
+					e.output <- e.charset.toByte('\n')
143 119
 				}
144 120
 			}
145 121
 
146
-		} else if (charsWithoutCRLF > 59) && (modCase == shiftWhitespace) {
122
+		} else if (charsWithoutCRLF > e.crlfThresh) && (modCase == shiftWhitespace) {
147 123
 			/*insert the cr-lf instead of the space character*/
148
-			t.output <- t.charset.toByte('\r')
149
-			t.output <- t.charset.toByte('\n')
124
+			e.output <- e.charset.toByte('\r')
125
+			e.output <- e.charset.toByte('\n')
150 126
 			charsWithoutCRLF = 0
151
-		} else if charsWithoutCRLF > 70 {
127
+		} else if charsWithoutCRLF > e.crlfForceThresh {
152 128
 			/*insert the cr-lf followed by the character*/
153
-			t.output <- t.charset.toByte('\r')
154
-			t.output <- t.charset.toByte('\n')
155
-			t.output <- c.toByte()
129
+			e.output <- e.charset.toByte('\r')
130
+			e.output <- e.charset.toByte('\n')
131
+			e.output <- c.toByte()
156 132
 			charsWithoutCRLF = 0
157 133
 		} else {
158 134
 			/*we just insert our regular character*/
159
-			t.output <- c.toByte()
135
+			e.output <- c.toByte()
160 136
 
161
-			if t.autoCRLF {
137
+			if e.autoCRLF {
162 138
 				if r == '\n' {
163
-					t.output <- t.charset.toByte('\r')
139
+					e.output <- e.charset.toByte('\r')
164 140
 				} else if r == '\r' {
165
-					t.output <- t.charset.toByte('\n')
141
+					e.output <- e.charset.toByte('\n')
166 142
 				}
167 143
 			}
168 144
 

+ 9
- 4
examples/main.go Прегледај датотеку

@@ -8,8 +8,13 @@ import (
8 8
 )
9 9
 
10 10
 func main() {
11
-	baud := 45.45
12
-	stopBits := 2.0
11
+
12
+	s := openbaudot.ModemSettings{
13
+		Baud:       45.45,
14
+		StopBits:   2,
15
+		DataBits:   5,
16
+		SampleRate: 8000,
17
+	}
13 18
 
14 19
 	charset := openbaudot.USTTY.Initialize()
15 20
 
@@ -23,7 +28,7 @@ func main() {
23 28
 	done := make(chan struct{})
24 29
 
25 30
 	encoder := openbaudot.NewEncoder(encoderIn, modulatorIn, charset)
26
-	modulator := openbaudot.NewModulator(baud, stopBits, 5, modulatorIn, modulatorOut)
31
+	modulator := openbaudot.NewModulator(s, modulatorIn, modulatorOut)
27 32
 
28 33
 	callback := func(event int, data interface{}) {
29 34
 		switch event {
@@ -44,7 +49,7 @@ func main() {
44 49
 		}
45 50
 	}()
46 51
 
47
-	openbaudot.NewDemodulator(baud, stopBits, 5, demodulatorIn, decoderIn)
52
+	openbaudot.NewDemodulator(s, demodulatorIn, decoderIn)
48 53
 	openbaudot.NewDecoder(decoderIn, decoderOut, charset)
49 54
 
50 55
 	running := true

+ 50
- 68
modulator.go Прегледај датотеку

@@ -1,66 +1,47 @@
1
+// Copyright (C) 2017 Keelan Lightfoot
2
+// Copyright (C) 2007-2008 Board of Regents of the University of Wisconsin
3
+//             System (Univ. of Wisconsin-Madison, Trace R&D Center)
4
+// Copyright (C) 2007-2008 Omnitor AB
5
+// Copyright (C) 2007-2008 Voiceriver Inc
6
+//
7
+// This library is free software; you can redistribute it and/or modify it
8
+// under the terms of the GNU Lesser General Public License as published by
9
+// the Free Software Foundation; either version 2.1 of the License, or (at
10
+// your option) any later version.
11
+
1 12
 package openbaudot
2 13
 
3 14
 import "math"
4 15
 
5
-/*
6
- * OBL openbaudot Library
7
- *
8
- * Copyright (C) 2017 Keelan Lightfoot
9
- * Copyright (C) 2007-2008 Board of Regents of the University of Wisconsin
10
- *                   System (Univ. of Wisconsin-Madison, Trace R&D Center)
11
- * Copyright (C) 2007-2008 Omnitor AB
12
- * Copyright (C) 2007-2008 Voiceriver Inc
13
- *
14
- * This software was developed with support from the National Institute on
15
- * Disability and Rehabilitation Research, US Dept of Education under Grant
16
- * # H133E990006 and H133E040014
17
- *
18
- * This library is free software; you can redistribute it and/or modify it
19
- * under the terms of the GNU Lesser General Public License as published by
20
- * the Free Software Foundation; either version 2.1 of the License, or (at
21
- * your option) any later version.
22
- *
23
- * This library is distributed in the hope that it will be useful, but
24
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
25
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
26
- * License for more details.
27
- *
28
- * You should have received a copy of the GNU Lesser General Public License
29
- * along with this library; if not, write to the Free Software Foundation,
30
- * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
31
- *
32
- * Please send a copy of any improved versions of the library to:
33
- * Jeff Knighton, Voiceriver Inc, jeff.knighton@voiceriver.com
34
- * Gunnar Hellstrom, Omnitor AB, Box 92054, 12006 Stockholm, SWEDEN
35
- * Gregg Vanderheiden, Trace Center, U of Wisconsin, Madison, Wi 53706
36
- *
37
- * file...: obl.go
38
- * original author.: Keelan Lightfoot
39
- * Created: 20 May 2017
40
- *
41
- */
16
+const (
17
+	modStateIdle = iota
18
+	modStateStart
19
+	modStateBit
20
+	modStateStop
21
+	modStateHold
22
+)
42 23
 
43 24
 // Modulator is fun
44 25
 type Modulator struct {
45 26
 	input  chan byte
46 27
 	output chan int16
47 28
 
48
-	baud           float64 // modulator baud rate
49
-	dataBits       int
50
-	samplesPerBit  int    // number of samples for one bit
51
-	phaseQ16       uint16 // phase acc 0..2math.Pi -> 0..65536
52
-	amplitude      int16  // peak modulator amplitude for one tone
53
-	numStopBits    int    // number of stop bits
54
-	numStopSamples int    // number of samples for stop bit
55
-	wOneQ16        uint16 // scaled one freq 0..2math.Pi -> 0..65536
56
-	wZeroQ16       uint16 // scaled zero freq 0..2math.Pi -> 0..65536
57
-	sinLutQ15      []int16
58
-
59
-	callback Callback
29
+	baud            float64 // modulator baud rate
30
+	dataBits        int
31
+	samplesPerBit   int     // number of samples for one bit
32
+	phaseQ16        uint16  // phase acc 0..2math.Pi -> 0..65536
33
+	amplitude       int16   // peak modulator amplitude for one tone
34
+	numStopHalfBits int     // number of stop bits
35
+	numStopSamples  int     // number of samples for stop bit
36
+	wOneQ16         uint16  // scaled one freq 0..2math.Pi -> 0..65536
37
+	wZeroQ16        uint16  // scaled zero freq 0..2math.Pi -> 0..65536
38
+	sinLutQ15       []int16 // sine lookup table
39
+	sampleRate      int     // sample rate
40
+	callback        Callback
60 41
 }
61 42
 
62 43
 // NewModulator is fun
63
-func NewModulator(baud float64, stopBits float64, dataBits int, input chan byte, output chan int16) *Modulator {
44
+func NewModulator(s ModemSettings, input chan byte, output chan int16) *Modulator {
64 45
 
65 46
 	m := new(Modulator)
66 47
 	// mod.input = make(chan code)
@@ -69,14 +50,15 @@ func NewModulator(baud float64, stopBits float64, dataBits int, input chan byte,
69 50
 	m.input = input
70 51
 	m.output = output
71 52
 
72
-	m.baud = baud
73
-	m.dataBits = dataBits
74
-	m.samplesPerBit = int(float64(sampleRate) / m.baud)
75
-	m.numStopBits = int(math.Floor(stopBits / .5))
76
-	m.numStopSamples = m.numStopBits * m.samplesPerBit / 2
53
+	m.baud = s.Baud
54
+	m.dataBits = s.DataBits
55
+	m.sampleRate = s.SampleRate
56
+	m.samplesPerBit = int(float64(m.sampleRate) / m.baud)
57
+	m.numStopHalfBits = int(math.Floor(s.StopBits / .5))
58
+	m.numStopSamples = m.numStopHalfBits * m.samplesPerBit / 2
77 59
 	m.amplitude = 16384
78 60
 
79
-	wOne, wZero := calculateW(2125, 2295)
61
+	wOne, wZero := calculateW(2125, 2295, m.sampleRate)
80 62
 
81 63
 	m.wOneQ16 = uint16((65536 / (2.0 * math.Pi)) * wOne)
82 64
 	m.wZeroQ16 = uint16((65536 / (2.0 * math.Pi)) * wZero)
@@ -106,11 +88,11 @@ func (m *Modulator) modulate(bit int) { //short *buffer, int samples)
106 88
 	*/
107 89
 	if bit != 0 {
108 90
 		m.phaseQ16 += m.wOneQ16
109
-		m.output <- multq(m.amplitude, m.sinLutQ15[m.phaseQ16>>2])
91
+		m.output <- multq15(m.amplitude, m.sinLutQ15[m.phaseQ16>>2])
110 92
 
111 93
 	} else {
112 94
 		m.phaseQ16 += m.wZeroQ16
113
-		m.output <- multq(m.amplitude, m.sinLutQ15[m.phaseQ16>>2])
95
+		m.output <- multq15(m.amplitude, m.sinLutQ15[m.phaseQ16>>2])
114 96
 	}
115 97
 }
116 98
 
@@ -127,26 +109,26 @@ func (m *Modulator) run() {
127 109
 	for {
128 110
 		nextState = modState
129 111
 		switch modState {
130
-		case ModStateIdle:
112
+		case modStateIdle:
131 113
 			select {
132 114
 			case c = <-m.input:
133 115
 				modSample = 0
134
-				nextState = ModStateStart
116
+				nextState = modStateStart
135 117
 				//obl.callback(EventTransmitState, TransmitStart)
136 118
 				idleSamples = 0
137 119
 			default:
138 120
 				m.modulate(0)
139 121
 
140
-				if idleSamples < sampleRate {
122
+				if idleSamples < m.sampleRate {
141 123
 					idleSamples++
142
-				} else if idleSamples == sampleRate {
124
+				} else if idleSamples == m.sampleRate {
143 125
 					if m.callback != nil {
144 126
 						m.callback(EventIdle, 0)
145 127
 					}
146 128
 					idleSamples++
147 129
 				}
148 130
 			}
149
-		case ModStateStart:
131
+		case modStateStart:
150 132
 			m.modulate(0)
151 133
 			modSample++
152 134
 			// after sending start bit send LSB data bit
@@ -154,9 +136,9 @@ func (m *Modulator) run() {
154 136
 				modNbit = 0
155 137
 				modBit = int(c & 0x1)
156 138
 				modSample = 0
157
-				nextState = ModStateBit
139
+				nextState = modStateBit
158 140
 			}
159
-		case ModStateBit:
141
+		case modStateBit:
160 142
 			m.modulate(modBit)
161 143
 			modSample++
162 144
 			// when this data bit complete, send next data bit
@@ -165,16 +147,16 @@ func (m *Modulator) run() {
165 147
 				modNbit++
166 148
 				modBit = int((c >> uint(modNbit)) & 0x1)
167 149
 				if modNbit == m.dataBits {
168
-					nextState = ModStateStop
150
+					nextState = modStateStop
169 151
 				}
170 152
 			}
171
-		case ModStateStop:
153
+		case modStateStop:
172 154
 			m.modulate(1)
173 155
 			modSample++
174 156
 			// when stop bit complete start transmission of next char, or enter idle state
175 157
 			if modSample == m.numStopSamples {
176 158
 				modSample = 0
177
-				nextState = ModStateIdle
159
+				nextState = modStateIdle
178 160
 			}
179 161
 			// 	(obl.callback)(obl,OBL_EVENT_TX_STATE, OBL_TRANSMIT_STOP);
180 162
 		}