Browse Source

dev commit

Keelan Lightfoot 7 years ago
parent
commit
4457eeccdb
10 changed files with 123 additions and 74 deletions
  1. 5
    0
      README.md
  2. 1
    1
      code.go
  3. 4
    2
      common.go
  4. 1
    1
      decoder.go
  5. 3
    3
      demodulator.go
  6. 47
    58
      dsp.go
  7. 24
    7
      encoder.go
  8. 1
    1
      examples/demtest.go
  9. 36
    0
      gobaudot_test.go
  10. 1
    1
      modulator.go

+ 5
- 0
README.md View File

@@ -0,0 +1,5 @@
1
+# Gobaudot
2
+
3
+Derived from the Open Baudot C library created David Rowe:
4
+
5
+// sourceforge link

+ 1
- 1
code.go View File

@@ -9,7 +9,7 @@
9 9
 // the Free Software Foundation; either version 2.1 of the License, or (at
10 10
 // your option) any later version.
11 11
 
12
-package openbaudot
12
+package gobaudot
13 13
 
14 14
 import "unicode"
15 15
 

+ 4
- 2
common.go View File

@@ -9,9 +9,9 @@
9 9
 // the Free Software Foundation; either version 2.1 of the License, or (at
10 10
 // your option) any later version.
11 11
 
12
-// Package openbaudot provides a set of tools to encode, modulate, demodulate and
12
+// Package gobaudot provides a set of tools to encode, modulate, demodulate and
13 13
 // baudot/TTY/RTTY data streams
14
-package openbaudot
14
+package gobaudot
15 15
 
16 16
 import "math"
17 17
 
@@ -26,6 +26,8 @@ const (
26 26
 	EventTransmitState
27 27
 	// EventIdle is fun
28 28
 	EventIdle
29
+	// EventEncodeStringComplete is fun
30
+	EventEncodeStringComplete
29 31
 )
30 32
 
31 33
 // Callback is func

+ 1
- 1
decoder.go View File

@@ -9,7 +9,7 @@
9 9
 // the Free Software Foundation; either version 2.1 of the License, or (at
10 10
 // your option) any later version.
11 11
 
12
-package openbaudot
12
+package gobaudot
13 13
 
14 14
 // Decoder converts a stream of bytes representing baudot codes into a stream
15 15
 // of unicode runes.

+ 3
- 3
demodulator.go View File

@@ -9,7 +9,7 @@
9 9
 // the Free Software Foundation; either version 2.1 of the License, or (at
10 10
 // your option) any later version.
11 11
 
12
-package openbaudot
12
+package gobaudot
13 13
 
14 14
 import (
15 15
 	"fmt"
@@ -150,7 +150,7 @@ func (d *Demodulator) run() {
150 150
 				// above a minimum threshold it transitions
151 151
 				// out of this state.
152 152
 
153
-				if d.dsp.zeroPresent() {
153
+				if d.dsp.space() {
154 154
 					sample = int(float64(d.samplerate) / d.settings.Baud * 1.5)
155 155
 					baudot = 0
156 156
 					bit = 0
@@ -163,7 +163,7 @@ func (d *Demodulator) run() {
163 163
 
164 164
 				sample--
165 165
 				if sample == 0 {
166
-					if d.dsp.onePresent() {
166
+					if d.dsp.mark() {
167 167
 						baudot |= (1 << uint(bit))
168 168
 					}
169 169
 					bit++

+ 47
- 58
dsp.go View File

@@ -9,7 +9,7 @@
9 9
 // the Free Software Foundation; either version 2.1 of the License, or (at
10 10
 // your option) any later version.
11 11
 
12
-package openbaudot
12
+package gobaudot
13 13
 
14 14
 import "math"
15 15
 
@@ -18,58 +18,70 @@ type dsp struct {
18 18
 	demTotal  float64 // current energy output value
19 19
 	lpfOrder  int     // LPFOrder Low pass filter order
20 20
 	minThresh float64 // MinThresh ratio for vaild signal
21
-	f1        *bandPass
22
-	f0        *bandPass
23
-	beta      float64
24
-	meter0    float64
25
-	meter1    float64
26
-	meter2    float64
27
-
28
-	carrierDetect bool
29
-	oneTone       bool
30
-	zeroTone      bool
31
-
32
-	lpfc     *lpf
21
+
22
+	meter0 float64
23
+	meter1 float64
24
+	meter2 float64
25
+
26
+	bpfMark  *bpf // mark bandpass filter
27
+	bpfSpace *bpf // space bandpass filter
28
+	lpfDem   *lpf //
33 29
 	lpfTotal *lpf
34 30
 
35 31
 	r float64
36 32
 }
37 33
 
38
-func newDsp(oneF, zeroF, sampleRate int) *dsp {
34
+func newDsp(markF, spaceF, sampleRate int) *dsp {
39 35
 
40
-	lfpOrder := 20
41
-
42
-	beta := .95
36
+	const (
37
+		lfpOrder  = 20
38
+		beta      = .95
39
+		minThresh = 3
40
+	)
43 41
 
44 42
 	return &dsp{
45
-		// demLpfIn:   make([]float64, lfpOrder),
46
-		// demTotalIn: make([]float64, lfpOrder),
47 43
 		lpfOrder:  lfpOrder,
48
-		minThresh: 3,
49
-		f1:        newBandPass(oneF, sampleRate, beta),
50
-		f0:        newBandPass(zeroF, sampleRate, beta),
51
-		lpfc:      newLpf(lfpOrder),
44
+		minThresh: minThresh,
45
+		bpfMark:   newBandPass(markF, sampleRate, beta),
46
+		bpfSpace:  newBandPass(spaceF, sampleRate, beta),
47
+		lpfDem:    newLpf(lfpOrder),
52 48
 		lpfTotal:  newLpf(lfpOrder),
53 49
 	}
54 50
 }
51
+
52
+func (d *dsp) demod(sam float64) {
53
+
54
+	// The demodulator is structured as a pair of band pass filters tuned to
55
+	// the mark and space frequencies. The output of each is 'rectified' and
56
+	// combined, and low pass filtered to produce a signal that goes positive
57
+	// for mark and negative for space.
58
+	mark := d.bpfMark.update(sam)
59
+	space := d.bpfSpace.update(sam)
60
+
61
+	d.demLpf = d.lpfDem.update(math.Abs(mark) - math.Abs(space))
62
+
63
+	d.demTotal = d.lpfTotal.update(math.Abs(sam))
64
+
65
+}
66
+
55 67
 func (d *dsp) edgeDetected() bool {
56
-	return d.demLpf > d.minThresh*d.demTotal
68
+	return math.Abs(d.demLpf) > d.demTotal*d.minThresh
57 69
 }
58 70
 
59 71
 func (d *dsp) carrier() bool {
60
-	return d.carrierDetect
72
+	return math.Abs(d.demLpf) > d.demTotal*d.minThresh
61 73
 }
62 74
 
63 75
 func (d *dsp) level() (float64, float64, float64) {
64 76
 	return d.meter0, d.meter1, d.meter2
65 77
 }
66 78
 
67
-func (d *dsp) onePresent() bool {
68
-	return d.oneTone
79
+func (d *dsp) mark() bool {
80
+	return d.demLpf > d.minThresh*d.demTotal && math.Abs(d.demLpf) > d.demTotal*d.minThresh
69 81
 }
70 82
 
71
-func (d *dsp) zeroPresent() bool {
72
-	return d.zeroTone
83
+func (d *dsp) space() bool {
84
+	return -1*d.demLpf > d.minThresh*d.demTotal && math.Abs(d.demLpf) > d.demTotal*d.minThresh
73 85
 }
74 86
 
75 87
 type lpf struct {
@@ -84,55 +96,32 @@ func newLpf(size int) *lpf {
84 96
 }
85 97
 
86 98
 func (l *lpf) update(v float64) float64 {
87
-
88
-	o := l.x[0]
99
+	l.t -= l.x[0]
100
+	l.t += v
89 101
 	l.x = append(l.x, v)
90 102
 	l.x = l.x[1:]
91 103
 
92
-	l.t -= o
93
-	l.t += v
94
-
95 104
 	return l.t
96 105
 }
97 106
 
98
-type bandPass struct {
107
+type bpf struct {
99 108
 	dem0 float64
100 109
 	dem1 float64
101 110
 	w    float64
102 111
 	beta float64
103 112
 }
104 113
 
105
-func newBandPass(fc int, fs int, beta float64) *bandPass {
106
-	f := new(bandPass)
114
+func newBandPass(fc int, fs int, beta float64) *bpf {
115
+	f := new(bpf)
107 116
 	f.beta = beta
108 117
 	f.w = (2 * math.Pi * float64(fc) / float64(fs))
109 118
 
110
-	//	fmt.Println("fc", fc, "fs", fs, f.beta, f.w)
111 119
 	return f
112 120
 }
113 121
 
114
-func (f *bandPass) update(v float64) float64 {
122
+func (f *bpf) update(v float64) float64 {
115 123
 	n := v + 2.0*math.Cos(f.w)*f.beta*f.dem0 - f.beta*f.beta*f.dem1
116 124
 	f.dem1 = f.dem0
117 125
 	f.dem0 = n
118 126
 	return n
119 127
 }
120
-
121
-func (d *dsp) demod(sam float64) {
122
-
123
-	var one float64
124
-	one = d.f1.update(sam)
125
-
126
-	var zero float64
127
-	zero = d.f0.update(sam)
128
-
129
-	d.demLpf = d.lpfc.update(math.Abs(one) - math.Abs(zero))
130
-
131
-	d.demTotal = d.lpfTotal.update(math.Abs(sam))
132
-
133
-	d.carrierDetect = math.Abs(d.demLpf) > d.demTotal*d.minThresh
134
-
135
-	d.oneTone = d.demLpf > d.minThresh*d.demTotal && d.carrierDetect
136
-	d.zeroTone = -1*d.demLpf > d.minThresh*d.demTotal && d.carrierDetect
137
-
138
-}

+ 24
- 7
encoder.go View File

@@ -9,7 +9,9 @@
9 9
 // the Free Software Foundation; either version 2.1 of the License, or (at
10 10
 // your option) any later version.
11 11
 
12
-package openbaudot
12
+package gobaudot
13
+
14
+import "fmt"
13 15
 
14 16
 // Encoder is fun
15 17
 type Encoder struct {
@@ -20,6 +22,8 @@ type Encoder struct {
20 22
 	charset         *CodeSet
21 23
 	crlfThresh      int // start looking for a space to replace with a crlf at this threshold
22 24
 	crlfForceThresh int // force a crlf if it hasn't happend by this threshold
25
+	shiftThresh     int
26
+	callback        Callback
23 27
 }
24 28
 
25 29
 // NewEncoder is fun
@@ -30,17 +34,27 @@ func NewEncoder(input chan rune, output chan byte, charset *CodeSet) *Encoder {
30 34
 	e.charset = charset
31 35
 	e.crlfThresh = 60
32 36
 	e.crlfForceThresh = 72
37
+	e.shiftThresh = 70
33 38
 	go e.run()
34 39
 	return e
35 40
 }
36 41
 
37 42
 // EncodeString is fun
38 43
 func (e *Encoder) EncodeString(s string) {
39
-	go func() {
40
-		for _, c := range s {
41
-			e.input <- c
42
-		}
43
-	}()
44
+	for _, c := range s {
45
+		e.input <- c
46
+	}
47
+
48
+}
49
+
50
+// SetAutoCRLF is fun
51
+func (e *Encoder) SetAutoCRLF(autoCRLF bool) {
52
+	e.autoCRLF = autoCRLF
53
+}
54
+
55
+// SetCallback is fun
56
+func (e *Encoder) SetCallback(callback Callback) {
57
+	e.callback = callback
44 58
 }
45 59
 
46 60
 func (e *Encoder) run() {
@@ -86,6 +100,7 @@ func (e *Encoder) run() {
86 100
 			modCase = c.shift
87 101
 
88 102
 			/*and update our counter*/
103
+			fmt.Println("charsWithoutShift", charsWithoutShift)
89 104
 			charsWithoutShift = 0
90 105
 		}
91 106
 
@@ -93,7 +108,7 @@ func (e *Encoder) run() {
93 108
 		 * boundry conditions in the protocol*/
94 109
 		/* We need to ensure that we re-send the current case character
95 110
 		   at least every 72 characters. */
96
-		if charsWithoutShift > 70 {
111
+		if charsWithoutShift > e.shiftThresh {
97 112
 			if modCase == shiftWhitespace {
98 113
 				e.output <- e.charset.unshift() /*doesn't matter which, so how 'bout LETR*/
99 114
 			} else if modCase == shiftLetter {
@@ -101,6 +116,8 @@ func (e *Encoder) run() {
101 116
 			} else {
102 117
 				e.output <- e.charset.shift()
103 118
 			}
119
+			fmt.Println("charsWithoutShift", charsWithoutShift)
120
+
104 121
 			charsWithoutShift = 0
105 122
 		}
106 123
 

+ 1
- 1
examples/demtest.go View File

@@ -14,7 +14,7 @@ import (
14 14
 // 22050 = 3
15 15
 // 11025 = 1
16 16
 // 8000 = 1
17
-func maisn() {
17
+func main() {
18 18
 	// lpf := 100
19 19
 	// l := newLpf(lpf)
20 20
 	//	for i := 5000; i <= 44100; i += 1000 {

+ 36
- 0
gobaudot_test.go View File

@@ -0,0 +1,36 @@
1
+package gobaudot_test
2
+
3
+import (
4
+	"testing"
5
+
6
+	"github.com/naleek/openbaudot"
7
+)
8
+
9
+func TestEncoder(t *testing.T) {
10
+	input := make(chan rune)
11
+	output := make(chan byte)
12
+
13
+	charset := gobaudot.LoadCharset(&gobaudot.USTTY)
14
+
15
+	encoder := gobaudot.NewEncoder(input, output, charset)
16
+
17
+	go func() {
18
+		for range output {
19
+		}
20
+	}()
21
+
22
+	encoder.SetAutoCRLF(false)
23
+
24
+	encoder.EncodeString("hello\nworld!")
25
+	encoder.EncodeString("hello                                                                                                                 ")
26
+	encoder.EncodeString("hello!oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo")
27
+	encoder.EncodeString("11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111")
28
+
29
+	encoder.SetAutoCRLF(true)
30
+
31
+	encoder.EncodeString("hello\rworld!")
32
+	encoder.EncodeString("hello                                                                                                                 ")
33
+	encoder.EncodeString("hello!oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo")
34
+	encoder.EncodeString("11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111")
35
+
36
+}

+ 1
- 1
modulator.go View File

@@ -9,7 +9,7 @@
9 9
 // the Free Software Foundation; either version 2.1 of the License, or (at
10 10
 // your option) any later version.
11 11
 
12
-package openbaudot
12
+package gobaudot
13 13
 
14 14
 import "math"
15 15