Skip to content

Commit bd1dc3f

Browse files
committed
Better BER reporting and optimize CC1200 receive BER
1 parent 0b3457e commit bd1dc3f

3 files changed

Lines changed: 30 additions & 14 deletions

File tree

cc1200_modem.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -252,11 +252,13 @@ func (m *CC1200Modem) processSymbols() {
252252
func (m *CC1200Modem) rxPipeline(sampleSource chan int8) (chan float32, error) {
253253
// modem samples -> DC filter --> RRC filter & scale
254254
var err error
255-
dcf, err := NewDCFilter(sampleSource, len(rrcTaps5))
255+
dcf, err := NewDCFilter(sampleSource, 200) //len(rrcTaps5))
256256
if err != nil {
257257
return nil, fmt.Errorf("dc filter: %w", err)
258258
}
259-
s2s := NewSampleToSymbol(dcf.Source(), rrcTaps5, RXSymbolScalingCoeff)
259+
// The 1.15 factor was empirically determined. A 15 second transmission from my CS7000
260+
// had a BER of 3.3%, compared to 4.9% with the factor at 1.0
261+
s2s := NewSampleToSymbol(dcf.Source(), rrcTaps5, RXSymbolScalingCoeff*1.15)
260262
// ds, err := NewDownsampler(s2s.Source(), 5, 0)
261263
// if err != nil {
262264
// return nil, fmt.Errorf("downsampler: %w", err)

decoder.go

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ type Decoder struct {
4949
lsfBytes []byte
5050
dashLog *slog.Logger
5151
lastLogTime time.Time
52+
errors int
53+
bits int
5254
}
5355

5456
// 8 preamble symbols, 8 for the syncword, and 960 for the payload.
@@ -79,6 +81,8 @@ func (d *Decoder) DecodeFrame(typ uint16, softBits []SoftBit) {
7981
d.timeoutCnt = 0
8082
d.lastStreamFN = 0xffff
8183
d.lastPacketFN = 0xff
84+
d.errors = e
85+
d.bits = 368
8286

8387
if d.lsf.Type[1]&byte(LSFTypeStream) == byte(LSFTypeStream) {
8488
d.syncedType = StreamSync
@@ -129,6 +133,8 @@ func (d *Decoder) DecodeFrame(typ uint16, softBits []SoftBit) {
129133

130134
case typ == PacketSync && d.syncedType == PacketSync:
131135
pktFrame, e := d.decodePacketFrame(softBits)
136+
d.errors += e
137+
d.bits += 368
132138
// log.Printf("[DEBUG] pktFrame: % x", pktFrame)
133139
lastFrame := (pktFrame[25] >> 7) != 0
134140

@@ -164,9 +170,9 @@ func (d *Decoder) DecodeFrame(typ uint16, softBits []SoftBit) {
164170
if d.dashLog != nil {
165171
if p.Type == PacketTypeSMS && len(p.Payload) > 0 {
166172
msg := string(p.Payload[0 : len(p.Payload)-1])
167-
d.dashLog.Info("", "type", "RF", "subtype", "Packet", "src", d.lsf.Src.Callsign(), "dst", d.lsf.Dst.Callsign(), "can", d.lsf.CAN(), "mer", json.Number(fmt.Sprintf("%f", float64(e)/3.68)), "packetType", p.Type, "smsMessage", msg)
173+
d.dashLog.Info("", "type", "RF", "subtype", "Packet", "src", d.lsf.Src.Callsign(), "dst", d.lsf.Dst.Callsign(), "can", d.lsf.CAN(), "mer", json.Number(fmt.Sprintf("%f", float64(d.errors)/float64(d.bits)*100)), "packetType", p.Type, "smsMessage", msg)
168174
} else {
169-
d.dashLog.Info("", "type", "RF", "subtype", "Packet", "src", d.lsf.Src.Callsign(), "dst", d.lsf.Dst.Callsign(), "can", d.lsf.CAN(), "mer", json.Number(fmt.Sprintf("%f", float64(e)/3.68)), "packetType", p.Type)
175+
d.dashLog.Info("", "type", "RF", "subtype", "Packet", "src", d.lsf.Src.Callsign(), "dst", d.lsf.Dst.Callsign(), "can", d.lsf.CAN(), "mer", json.Number(fmt.Sprintf("%f", float64(d.errors)/float64(d.bits)*100)), "packetType", p.Type)
170176
}
171177
}
172178
} else {
@@ -183,6 +189,8 @@ func (d *Decoder) DecodeFrame(typ uint16, softBits []SoftBit) {
183189
var fn uint16
184190
d.frameData, lich, fn, lichCnt, e = d.decodeStreamFrame(softBits)
185191
log.Printf("[DEBUG] frameData: [% 2x], lich: %02x, lichCnt: %d, d.lichParts: %04x, fn: %04x, d.lastStreamFN: %04x, e: %d", d.frameData, lich, lichCnt, d.lichParts, fn, d.lastStreamFN, e)
192+
d.errors += e
193+
d.bits += 272
186194
if d.lastStreamFN+1 == fn&0x7fff {
187195
if d.lichParts != 0x3F && lichCnt < 6 { //6 chunks = 0b111111
188196
//reconstruct LSF chunk by chunk
@@ -243,7 +251,7 @@ func (d *Decoder) DecodeFrame(typ uint16, softBits []SoftBit) {
243251
d.timeoutCnt = 0
244252
if d.dashLog != nil && lastFrame {
245253
log.Printf("[DEBUG] Last frame for RF voice stream %04x", d.streamID)
246-
d.dashLog.Info("", "type", "RF", "subtype", "Voice End", "src", d.lsf.Src.Callsign(), "dst", d.lsf.Dst.Callsign(), "can", d.lsf.CAN(), "mer", json.Number(fmt.Sprintf("%f", float64(e)/2.72)))
254+
d.dashLog.Info("", "type", "RF", "subtype", "Voice End", "src", d.lsf.Src.Callsign(), "dst", d.lsf.Dst.Callsign(), "can", d.lsf.CAN(), "mer", json.Number(fmt.Sprintf("%f", float64(d.errors)/float64(d.bits)*100)))
247255
}
248256
}
249257
if lastFrame {
@@ -413,4 +421,6 @@ func (d *Decoder) reset() {
413421
d.lastPacketFN = 0xff
414422
d.lastStreamFN = 0xffff
415423
d.lichParts = 0
424+
d.errors = 0
425+
d.bits = 0
416426
}

transform.go

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,14 @@ const (
1515
//40.0e3 is F_TCXO in kHz
1616
//129 is `CFM_RX_DATA_OUT` register value at max. F_DEV
1717
//datasheet might have this wrong (it says 64)
18+
1819
RXSymbolScalingCoeff = (1.0 / (0.8 / (40.0e3 / 2097152 * 0xAD) * 129.0))
20+
1921
//0xAD is `DEVIATION_M`, 2097152=2^21
2022
//+0.8kHz is the deviation for symbol +1
2123
//40.0e3 is F_TCXO in kHz
2224
//64 is `CFM_TX_DATA_IN` register value for max. F_DEV
25+
2326
TXSymbolScalingCoeff = (0.8 / ((40.0e3 / 2097152) * 0xAD) * 64.0)
2427
)
2528

@@ -196,24 +199,25 @@ func (t *Transform[I, O]) handle() {
196199
// Filter DC from int8 samples by subtracting a moving average
197200
type DCFilter struct {
198201
Transform[int8, int8]
199-
averageN int
200-
movingAvg int8
202+
averageCnt int
203+
movingAvg int
201204
}
202205

203-
func NewDCFilter(sink chan int8, averageN int) (DCFilter, error) {
206+
func NewDCFilter(sink chan int8, averageCnt int) (DCFilter, error) {
204207
ret := DCFilter{
205-
averageN: averageN,
208+
averageCnt: averageCnt,
206209
}
207-
if averageN < 1 {
208-
return ret, fmt.Errorf("averageN must be greater than zero")
210+
if averageCnt < 1 {
211+
return ret, fmt.Errorf("averageCnt must be greater than zero")
209212
}
210213
ret.Transform = NewTransform(sink, ret.dcFilter, 0)
211214
return ret, nil
212215
}
213216
func (t *DCFilter) dcFilter(sample int8) []int8 {
214-
t.movingAvg = int8((int(t.movingAvg)*(t.averageN-1) + int(sample)) / t.averageN)
215-
// log.Printf("[DEBUG] movingAvg: %d, sample: %d, ret: %d", t.movingAvg, sample, sample-t.movingAvg)
216-
return []int8{sample - t.movingAvg}
217+
ret := sample - int8(t.movingAvg)
218+
t.movingAvg = (t.movingAvg*(t.averageCnt-1) + int(sample)) / t.averageCnt
219+
// log.Printf("[DEBUG] movingAvg: %d, sample: %d, ret: %d", t.movingAvg, sample, sample-int8(t.movingAvg))
220+
return []int8{ret}
217221
}
218222

219223
// scale samples by a factor

0 commit comments

Comments
 (0)