Skip to content

Commit

Permalink
Implement decimation, except in R900 decoder.
Browse files Browse the repository at this point in the history
  • Loading branch information
bemasher committed May 24, 2015
1 parent f3d51f2 commit c2855e7
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 85 deletions.
81 changes: 59 additions & 22 deletions decode/decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,36 @@ import (

// PacketConfig specifies packet-specific radio configuration.
type PacketConfig struct {
DataRate int
DataRate int

BlockSize, BlockSize2 int
SymbolLength, SymbolLength2 int
SampleRate int

PreambleSymbols, PacketSymbols int
PreambleLength, PacketLength int
BufferLength int
Preamble string

BufferLength int

CenterFreq uint32
}

func (cfg PacketConfig) Decimate(decimation int) PacketConfig {
cfg.BlockSize /= decimation
cfg.BlockSize2 /= decimation
cfg.SymbolLength /= decimation
cfg.SymbolLength2 /= decimation
cfg.SampleRate /= decimation

cfg.PreambleLength /= decimation
cfg.PacketLength /= decimation

cfg.BufferLength /= decimation

return cfg
}

func (cfg PacketConfig) Log() {
log.Println("BlockSize:", cfg.BlockSize)
log.Println("CenterFreq:", cfg.CenterFreq)
Expand All @@ -55,6 +72,9 @@ func (cfg PacketConfig) Log() {
type Decoder struct {
Cfg PacketConfig

Decimation int
DecCfg PacketConfig

IQ []byte
Signal []float64
Filtered []float64
Expand All @@ -70,16 +90,32 @@ type Decoder struct {
}

// Create a new decoder with the given packet configuration.
func NewDecoder(cfg PacketConfig, fastMag bool) (d Decoder) {
func NewDecoder(cfg PacketConfig, decimation int, fastMag bool) (d Decoder) {
d.Cfg = cfg

d.Cfg.SymbolLength2 = d.Cfg.SymbolLength << 1
d.Cfg.SampleRate = d.Cfg.DataRate * d.Cfg.SymbolLength

d.Cfg.PreambleLength = d.Cfg.PreambleSymbols * d.Cfg.SymbolLength2
d.Cfg.PacketLength = d.Cfg.PacketSymbols * d.Cfg.SymbolLength2

d.Cfg.BlockSize = NextPowerOf2(d.Cfg.PreambleLength)
d.Cfg.BlockSize2 = d.Cfg.BlockSize << 1

d.Cfg.BufferLength = d.Cfg.PacketLength + d.Cfg.BlockSize

d.Decimation = decimation
d.DecCfg = d.Cfg.Decimate(d.Decimation)
fmt.Printf("%+v\n", d.Cfg)
fmt.Printf("%+v\n", d.DecCfg)

// Allocate necessary buffers.
d.IQ = make([]byte, d.Cfg.BufferLength<<1)
d.Signal = make([]float64, d.Cfg.BufferLength)
d.Filtered = make([]float64, d.Cfg.BufferLength)
d.Quantized = make([]byte, d.Cfg.BufferLength)
d.Filtered = make([]float64, d.DecCfg.BufferLength)
d.Quantized = make([]byte, d.DecCfg.BufferLength)

d.csum = make([]float64, d.Cfg.BlockSize+d.Cfg.SymbolLength2+1)
d.csum = make([]float64, (d.Cfg.BlockSize + d.Cfg.SymbolLength2 + 1))

// Calculate magnitude lookup table specified by -fastmag flag.
if fastMag {
Expand All @@ -99,10 +135,10 @@ func NewDecoder(cfg PacketConfig, fastMag bool) (d Decoder) {
// Slice quantized sample buffer to make searching for the preamble more
// memory local. Pre-allocate a flat buffer so memory is contiguous and
// assign slices to the buffer.
d.slices = make([][]byte, d.Cfg.SymbolLength2)
flat := make([]byte, d.Cfg.BlockSize2-(d.Cfg.BlockSize2%d.Cfg.SymbolLength2))
d.slices = make([][]byte, d.DecCfg.SymbolLength2)
flat := make([]byte, d.DecCfg.BlockSize2-(d.DecCfg.BlockSize2%d.DecCfg.SymbolLength2))

symbolsPerBlock := d.Cfg.BlockSize2 / d.Cfg.SymbolLength2
symbolsPerBlock := d.DecCfg.BlockSize2 / d.DecCfg.SymbolLength2
for symbolOffset := range d.slices {
lower := symbolOffset * symbolsPerBlock
upper := (symbolOffset + 1) * symbolsPerBlock
Expand All @@ -111,7 +147,7 @@ func NewDecoder(cfg PacketConfig, fastMag bool) (d Decoder) {

// Signal up to the final stage is 1-bit per byte. Allocate a buffer to
// store packed version 8-bits per byte.
d.pkt = make([]byte, (d.Cfg.PacketSymbols+7)>>3)
d.pkt = make([]byte, (d.DecCfg.PacketSymbols+7)>>3)

return
}
Expand All @@ -121,8 +157,8 @@ func (d Decoder) Decode(input []byte) []int {
// Shift buffers to append new block.
copy(d.IQ, d.IQ[d.Cfg.BlockSize<<1:])
copy(d.Signal, d.Signal[d.Cfg.BlockSize:])
copy(d.Filtered, d.Filtered[d.Cfg.BlockSize:])
copy(d.Quantized, d.Quantized[d.Cfg.BlockSize:])
copy(d.Filtered, d.Filtered[d.DecCfg.BlockSize:])
copy(d.Quantized, d.Quantized[d.DecCfg.BlockSize:])
copy(d.IQ[d.Cfg.PacketLength<<1:], input[:])

iqBlock := d.IQ[d.Cfg.PacketLength<<1:]
Expand All @@ -132,16 +168,16 @@ func (d Decoder) Decode(input []byte) []int {
d.demod.Execute(iqBlock, signalBlock)

signalBlock = d.Signal[d.Cfg.PacketLength-d.Cfg.SymbolLength2:]
filterBlock := d.Filtered[d.Cfg.PacketLength-d.Cfg.SymbolLength2:]
filterBlock := d.Filtered[d.DecCfg.PacketLength-d.DecCfg.SymbolLength2:]

// Perform matched filter on new block.
d.Filter(signalBlock, filterBlock)

// Perform bit-decision on new block.
Quantize(filterBlock, d.Quantized[d.Cfg.PacketLength-d.Cfg.SymbolLength2:])
Quantize(filterBlock, d.Quantized[d.DecCfg.PacketLength-d.DecCfg.SymbolLength2:])

// Pack the quantized signal into slices for searching.
d.Pack(d.Quantized[:d.Cfg.BlockSize2], d.slices)
d.Pack(d.Quantized[:d.DecCfg.BlockSize2], d.slices)

// Return a list of indexes the preamble exists at.
return d.Search(d.slices, d.preamble)
Expand Down Expand Up @@ -217,8 +253,9 @@ func (d Decoder) Filter(input, output []float64) {
// Filter result is difference of summation of lower and upper symbols.
lower := d.csum[d.Cfg.SymbolLength:]
upper := d.csum[d.Cfg.SymbolLength2:]
for idx := range input[:len(input)-d.Cfg.SymbolLength2] {
output[idx] = (lower[idx] - d.csum[idx]) - (upper[idx] - lower[idx])
n := len(input) - d.Cfg.SymbolLength2
for idx := 0; idx < n; idx += d.Decimation {
output[idx/d.Decimation] = (lower[idx] - d.csum[idx]) - (upper[idx] - lower[idx])
}

return
Expand All @@ -239,7 +276,7 @@ func Quantize(input []float64, output []byte) {
func (d Decoder) Pack(input []byte, slices [][]byte) {
for symbolOffset, slice := range slices {
for symbolIdx := range slice {
slice[symbolIdx] = input[symbolIdx*d.Cfg.SymbolLength2+symbolOffset]
slice[symbolIdx] = input[symbolIdx*d.DecCfg.SymbolLength2+symbolOffset]
}
}

Expand All @@ -254,7 +291,7 @@ func (d Decoder) Search(slices [][]byte, preamble []byte) (indexes []int) {
for symbolOffset, slice := range slices {
for symbolIdx := range slice[:len(slice)-preambleLength] {
if bytes.Equal(preamble, slice[symbolIdx:][:preambleLength]) {
indexes = append(indexes, symbolIdx*d.Cfg.SymbolLength2+symbolOffset)
indexes = append(indexes, symbolIdx*d.DecCfg.SymbolLength2+symbolOffset)
}
}
}
Expand All @@ -274,14 +311,14 @@ func (d Decoder) Slice(indices []int) (pkts [][]byte) {
for _, qIdx := range indices {
// Check that we're still within the first sample block. We'll catch
// the message on the next sample block otherwise.
if qIdx > d.Cfg.BlockSize {
if qIdx > d.DecCfg.BlockSize {
continue
}

// Packet is 1 bit per byte, pack to 8-bits per byte.
for pIdx := 0; pIdx < d.Cfg.PacketSymbols; pIdx++ {
for pIdx := 0; pIdx < d.DecCfg.PacketSymbols; pIdx++ {
d.pkt[pIdx>>3] <<= 1
d.pkt[pIdx>>3] |= d.Quantized[qIdx+(pIdx*d.Cfg.SymbolLength2)]
d.pkt[pIdx>>3] |= d.Quantized[qIdx+(pIdx*d.DecCfg.SymbolLength2)]
}

// Store the packet in the seen map and append to the packet list.
Expand Down
5 changes: 4 additions & 1 deletion flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@ var sampleFile *os.File
var msgType = flag.String("msgtype", "scm", "message type to receive: scm, idm or r900")
var fastMag = flag.Bool("fastmag", false, "use faster alpha max + beta min magnitude approximation")

var symbolLength = flag.Int("symbollength", 73, "symbol length in samples, see -help for valid lengths")
var symbolLength = flag.Int("symbollength", 72, "symbol length in samples, see -help for valid lengths")

var decimation = flag.Int("decimation", 1, "integer decimation factor, keep every nth sample")

var timeLimit = flag.Duration("duration", 0, "time to run for, 0 for infinite, ex. 1h5m10s")
var meterID UintMap
Expand All @@ -64,6 +66,7 @@ func RegisterFlags() {
"samplefile": true,
"msgtype": true,
"symbollength": true,
"decimation": true,
"duration": true,
"filterid": true,
"filtertype": true,
Expand Down
26 changes: 4 additions & 22 deletions idm/idm.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,27 +28,13 @@ import (
)

func NewPacketConfig(symbolLength int) (cfg decode.PacketConfig) {
cfg.DataRate = 32768

cfg.CenterFreq = 912600155

cfg.DataRate = 32768
cfg.SymbolLength = symbolLength
cfg.SymbolLength2 = cfg.SymbolLength << 1

cfg.SampleRate = cfg.DataRate * cfg.SymbolLength

cfg.PreambleSymbols = 32
cfg.PacketSymbols = 92 * 8

cfg.PreambleLength = cfg.PreambleSymbols * cfg.SymbolLength2
cfg.PacketLength = cfg.PacketSymbols * cfg.SymbolLength2

cfg.BlockSize = decode.NextPowerOf2(cfg.PreambleLength)
cfg.BlockSize2 = cfg.BlockSize << 1

cfg.BufferLength = cfg.PacketLength + cfg.BlockSize

cfg.Preamble = "01010101010101010001011010100011"

return
}

Expand All @@ -65,8 +51,8 @@ func (p Parser) Cfg() decode.PacketConfig {
return p.Decoder.Cfg
}

func NewParser(symbolLength int, fastMag bool) (p Parser) {
p.Decoder = decode.NewDecoder(NewPacketConfig(symbolLength), fastMag)
func NewParser(symbolLength, decimation int, fastMag bool) (p Parser) {
p.Decoder = decode.NewDecoder(NewPacketConfig(symbolLength), decimation, fastMag)
p.CRC = crc.NewCRC("CCITT", 0xFFFF, 0x1021, 0x1D0F)
return
}
Expand Down Expand Up @@ -94,10 +80,6 @@ type IDM struct {

type Interval [47]uint16

// func (interval Interval) MarshalText() (text []byte, err error) {
// return []byte(fmt.Sprintf("%+v", interval)), nil
// }

func (interval Interval) Record() (r []string) {
for _, val := range interval {
r = append(r, strconv.FormatUint(uint64(val), 10))
Expand Down
22 changes: 3 additions & 19 deletions r900/r900.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,26 +32,10 @@ const (
)

func NewPacketConfig(symbolLength int) (cfg decode.PacketConfig) {
cfg.DataRate = 32768

cfg.CenterFreq = 912380000

cfg.SymbolLength = symbolLength
cfg.SymbolLength2 = cfg.SymbolLength << 1

cfg.SampleRate = cfg.DataRate * cfg.SymbolLength

cfg.DataRate = 32768
cfg.PreambleSymbols = 32
cfg.PacketSymbols = 116

cfg.PreambleLength = cfg.PreambleSymbols * cfg.SymbolLength2
cfg.PacketLength = cfg.PacketSymbols * cfg.SymbolLength2

cfg.BlockSize = decode.NextPowerOf2(cfg.PreambleLength)
cfg.BlockSize2 = cfg.BlockSize << 1

cfg.BufferLength = cfg.PacketLength + cfg.BlockSize

cfg.Preamble = "00000000000000001110010101100100"

return
Expand All @@ -67,8 +51,8 @@ type Parser struct {
quantized []byte
}

func NewParser(symbolLength int, fastMag bool) (p Parser) {
p.Decoder = decode.NewDecoder(NewPacketConfig(symbolLength), fastMag)
func NewParser(symbolLength, decimation int, fastMag bool) (p Parser) {
p.Decoder = decode.NewDecoder(NewPacketConfig(symbolLength), 1, fastMag)

// GF of order 32, polynomial 37, generator 2.
p.field = gf.NewField(32, 37, 2)
Expand Down
6 changes: 3 additions & 3 deletions recv.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,11 @@ type Receiver struct {
func (rcvr *Receiver) NewReceiver() {
switch strings.ToLower(*msgType) {
case "scm":
rcvr.p = scm.NewParser(*symbolLength, *fastMag)
rcvr.p = scm.NewParser(*symbolLength, *decimation, *fastMag)
case "idm":
rcvr.p = idm.NewParser(*symbolLength, *fastMag)
rcvr.p = idm.NewParser(*symbolLength, *decimation, *fastMag)
case "r900":
rcvr.p = r900.NewParser(*symbolLength, *fastMag)
rcvr.p = r900.NewParser(*symbolLength, *decimation, *fastMag)
default:
log.Fatalf("Invalid message type: %q\n", *msgType)
}
Expand Down
21 changes: 3 additions & 18 deletions scm/scm.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,26 +26,11 @@ import (
)

func NewPacketConfig(symbolLength int) (cfg decode.PacketConfig) {
cfg.DataRate = 32768

cfg.CenterFreq = 912600155

cfg.DataRate = 32768
cfg.SymbolLength = symbolLength
cfg.SymbolLength2 = cfg.SymbolLength << 1

cfg.SampleRate = cfg.DataRate * cfg.SymbolLength

cfg.PreambleSymbols = 21
cfg.PacketSymbols = 96

cfg.PreambleLength = cfg.PreambleSymbols * cfg.SymbolLength2
cfg.PacketLength = cfg.PacketSymbols * cfg.SymbolLength2

cfg.BlockSize = decode.NextPowerOf2(cfg.PreambleLength)
cfg.BlockSize2 = cfg.BlockSize << 1

cfg.BufferLength = cfg.PacketLength + cfg.BlockSize

cfg.Preamble = "111110010101001100000"

return
Expand All @@ -56,8 +41,8 @@ type Parser struct {
crc.CRC
}

func NewParser(symbolLength int, fastMag bool) (p Parser) {
p.Decoder = decode.NewDecoder(NewPacketConfig(symbolLength), fastMag)
func NewParser(symbolLength, decimation int, fastMag bool) (p Parser) {
p.Decoder = decode.NewDecoder(NewPacketConfig(symbolLength), decimation, fastMag)
p.CRC = crc.NewCRC("BCH", 0, 0x6F63, 0)
return
}
Expand Down

0 comments on commit c2855e7

Please sign in to comment.