You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
179 lines
3.9 KiB
Go
179 lines
3.9 KiB
Go
9 years ago
|
package dmr
|
||
|
|
||
|
import (
|
||
|
"errors"
|
||
|
"fmt"
|
||
|
|
||
|
"github.com/pd0mz/go-dmr/crc/quadres_16_7"
|
||
|
)
|
||
|
|
||
|
// EMB LCSS fragments.
|
||
|
const (
|
||
|
SingleFragment uint8 = iota
|
||
|
FirstFragment
|
||
|
LastFragment
|
||
|
Continuation
|
||
|
)
|
||
|
|
||
|
// LCSSName is a map of LCSS fragment type to string.
|
||
|
var LCSSName = map[uint8]string{
|
||
|
SingleFragment: "single fragment",
|
||
|
FirstFragment: "first fragment",
|
||
|
LastFragment: "last fragment",
|
||
|
Continuation: "continuation",
|
||
|
}
|
||
|
|
||
|
// EMB contains embedded signalling.
|
||
|
type EMB struct {
|
||
|
ColorCode uint8
|
||
|
LCSS uint8
|
||
|
}
|
||
|
|
||
|
func (emb *EMB) String() string {
|
||
|
return fmt.Sprintf("color code %d, %s (%d)", emb.ColorCode, LCSSName[emb.LCSS], emb.LCSS)
|
||
|
}
|
||
|
|
||
|
// ParseEMB parses embedded signalling
|
||
|
func ParseEMB(bits []byte) (*EMB, error) {
|
||
|
if len(bits) != EMBBits {
|
||
|
return nil, fmt.Errorf("dmr/emb: expected %d bits, got %d", EMBBits, len(bits))
|
||
|
}
|
||
|
|
||
|
if !quadres_16_7.Check(bits) {
|
||
|
return nil, errors.New("dmr/emb: checksum error")
|
||
|
}
|
||
|
|
||
|
if bits[4] != 0 {
|
||
|
return nil, errors.New("dmr/emb: pi is not 0")
|
||
|
}
|
||
|
|
||
|
return &EMB{
|
||
|
ColorCode: uint8(bits[0])<<3 | uint8(bits[1])<<2 | uint8(bits[2])<<1 | uint8(bits[3]),
|
||
|
LCSS: uint8(bits[5])<<1 | uint8(bits[6]),
|
||
|
}, nil
|
||
|
}
|
||
|
|
||
|
// ParseEMBBitsFromSync extracts the embedded signalling bits from the SYNC bits.
|
||
|
func ParseEMBBitsFromSync(sync []byte) ([]byte, error) {
|
||
|
if sync == nil {
|
||
|
return nil, errors.New("dmr/emb from sync: bits can't be nil")
|
||
|
}
|
||
|
if len(sync) != 48 {
|
||
|
return nil, fmt.Errorf("dmr/emb from sync: expected 48 sync bits, got %d", len(sync))
|
||
|
}
|
||
|
|
||
|
var bits = make([]byte, 16)
|
||
|
copy(bits[:8], sync[:8])
|
||
|
copy(bits[8:], sync[8+32:])
|
||
|
return bits, nil
|
||
|
}
|
||
|
|
||
|
// ParseEmbeddedSignallingLCFromSyncBits extracts the embedded signalling LC from the SYNC bits.
|
||
|
func ParseEmbeddedSignallingLCFromSyncBits(sync []byte) ([]byte, error) {
|
||
|
if sync == nil {
|
||
|
return nil, errors.New("dmr/emb lc from sync: bits can't be nil")
|
||
|
}
|
||
|
if len(sync) != 48 {
|
||
|
return nil, fmt.Errorf("dmr/emb lc from sync: expected 48 sync bits, got %d", len(sync))
|
||
|
}
|
||
|
|
||
|
var bits = make([]byte, 32)
|
||
|
copy(bits, sync[8:40])
|
||
|
return bits, nil
|
||
|
}
|
||
|
|
||
|
// EmbeddedSignallingLC contains the embedded signalling LC and checksum.
|
||
|
type EmbeddedSignallingLC struct {
|
||
|
Bits []byte
|
||
|
Checksum []byte
|
||
|
}
|
||
|
|
||
|
// Check verifies the checksum in the embedded signalling LC.
|
||
|
func (eslc *EmbeddedSignallingLC) Check() bool {
|
||
|
var checksum uint8
|
||
|
checksum |= eslc.Checksum[0] << 4
|
||
|
checksum |= eslc.Checksum[1] << 3
|
||
|
checksum |= eslc.Checksum[2] << 2
|
||
|
checksum |= eslc.Checksum[3] << 1
|
||
|
checksum |= eslc.Checksum[4] << 0
|
||
|
|
||
|
var data = BitsToBytes(eslc.Bits)
|
||
|
var verify uint16
|
||
|
for _, b := range data {
|
||
|
verify += uint16(b)
|
||
|
}
|
||
|
|
||
|
var calculated = uint8(verify % 31)
|
||
|
return calculated == checksum
|
||
|
}
|
||
|
|
||
|
// Interleave packs the embedded signalling LC to interleaved bits.
|
||
|
func (eslc *EmbeddedSignallingLC) Interleave() []byte {
|
||
|
var bits = make([]byte, 77)
|
||
|
var j int
|
||
|
for i := range bits {
|
||
|
switch i {
|
||
|
case 32:
|
||
|
bits[i] = eslc.Checksum[0]
|
||
|
break
|
||
|
case 43:
|
||
|
bits[i] = eslc.Checksum[1]
|
||
|
break
|
||
|
case 54:
|
||
|
bits[i] = eslc.Checksum[2]
|
||
|
break
|
||
|
case 65:
|
||
|
bits[i] = eslc.Checksum[3]
|
||
|
break
|
||
|
case 76:
|
||
|
bits[i] = eslc.Checksum[4]
|
||
|
break
|
||
|
default:
|
||
|
bits[i] = eslc.Bits[j]
|
||
|
j++
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return bits
|
||
|
}
|
||
|
|
||
|
// DeinterleaveEmbeddedSignallingLC deinterleaves the embedded signalling LC bits.
|
||
|
func DeinterleaveEmbeddedSignallingLC(bits []byte) (*EmbeddedSignallingLC, error) {
|
||
|
if bits == nil {
|
||
|
return nil, errors.New("dmr/emb lc deinterleave: bits can't be nil")
|
||
|
}
|
||
|
if len(bits) != 77 {
|
||
|
return nil, fmt.Errorf("dmr/emb lc deinterleave: expected 77 bits, got %d", len(bits))
|
||
|
}
|
||
|
|
||
|
var eslc = &EmbeddedSignallingLC{
|
||
|
Bits: make([]byte, 72),
|
||
|
Checksum: make([]byte, 5),
|
||
|
}
|
||
|
var j int
|
||
|
for i, b := range bits {
|
||
|
switch i {
|
||
|
case 32:
|
||
|
eslc.Checksum[0] = b
|
||
|
break
|
||
|
case 43:
|
||
|
eslc.Checksum[1] = b
|
||
|
break
|
||
|
case 54:
|
||
|
eslc.Checksum[2] = b
|
||
|
break
|
||
|
case 65:
|
||
|
eslc.Checksum[3] = b
|
||
|
break
|
||
|
case 76:
|
||
|
eslc.Checksum[4] = b
|
||
|
break
|
||
|
default:
|
||
|
eslc.Bits[j] = b
|
||
|
j++
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return eslc, nil
|
||
|
}
|