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.
166 lines
2.9 KiB
Go
166 lines
2.9 KiB
Go
package bptc
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
|
|
"github.com/pd0mz/go-dmr"
|
|
"github.com/pd0mz/go-dmr/fec"
|
|
)
|
|
|
|
// deinterleave matrix
|
|
var dm = [256]uint8{}
|
|
var debug bool
|
|
|
|
func init() {
|
|
var i uint32
|
|
for i = 0; i < 0x100; i++ {
|
|
dm[i] = uint8((i * 181) % 196)
|
|
}
|
|
|
|
debug = os.Getenv("DEBUG_DMR_BPTC") != ""
|
|
}
|
|
|
|
func dump(bits []byte) {
|
|
for row := 0; row < 13; row++ {
|
|
if row == 0 {
|
|
fmt.Printf("col # ")
|
|
for col := 0; col < 15; col++ {
|
|
fmt.Printf("%02d ", col+1)
|
|
if col == 10 {
|
|
fmt.Print("| ")
|
|
}
|
|
}
|
|
fmt.Println("")
|
|
}
|
|
if row == 9 {
|
|
fmt.Println(" ------------------------------- ------------")
|
|
}
|
|
for col := 0; col < 15; col++ {
|
|
if col == 0 {
|
|
fmt.Printf("row #%02d: ", row+1)
|
|
}
|
|
fmt.Printf(" %d ", bits[col+row*15+1])
|
|
if col == 10 {
|
|
fmt.Print("| ")
|
|
}
|
|
}
|
|
fmt.Println("")
|
|
}
|
|
}
|
|
|
|
func Decode(info, data []byte) error {
|
|
if len(info) < 196 {
|
|
return fmt.Errorf("bptc: info size %d too small, need at least 196 bits", len(info))
|
|
}
|
|
if len(data) < 12 {
|
|
return fmt.Errorf("bptc: data size %d too small, need at least 12 bytes", len(data))
|
|
}
|
|
|
|
var (
|
|
i, j, k uint32
|
|
datafr = make([]byte, 196)
|
|
extracted = make([]byte, 96)
|
|
)
|
|
|
|
// Deinterleave bits
|
|
for i = 1; i < 197; i++ {
|
|
datafr[i-1] = info[dm[i]]
|
|
}
|
|
|
|
if debug {
|
|
dump(datafr)
|
|
}
|
|
|
|
// Zero reserved bits
|
|
for i = 0; i < 3; i++ {
|
|
datafr[0*15+i] = 0
|
|
}
|
|
|
|
for i = 0; i < 15; i++ {
|
|
var codeword uint32
|
|
for j = 0; j < 13; j++ {
|
|
codeword <<= 1
|
|
codeword |= uint32(datafr[j*15+i])
|
|
}
|
|
|
|
fec.Hamming15_11_3_Correct(&codeword)
|
|
codeword &= 0x01ff
|
|
for j = 0; j < 9; j++ {
|
|
datafr[j*15+i] = byte((codeword >> (8 - j)) & 1)
|
|
}
|
|
}
|
|
for j = 0; j < 9; j++ {
|
|
var codeword uint32
|
|
for i = 0; i < 15; i++ {
|
|
codeword <<= 1
|
|
codeword |= uint32(datafr[j*15+i])
|
|
}
|
|
fec.Hamming15_11_3_Correct(&codeword)
|
|
for i = 0; i < 11; i++ {
|
|
datafr[j*15+10-i] = byte((codeword >> i) & 1)
|
|
}
|
|
}
|
|
|
|
// Extract data bits
|
|
for i, k = 3, 0; i < 11; i, k = i+1, k+1 {
|
|
extracted[k] = datafr[0*15+i]
|
|
}
|
|
for j = 1; j < 9; j++ {
|
|
for i = 0; i < 11; i, k = i+1, k+1 {
|
|
extracted[k] = datafr[j*15+i]
|
|
}
|
|
}
|
|
|
|
copy(data, dmr.BitsToBytes(extracted))
|
|
|
|
return nil
|
|
}
|
|
|
|
func Encode(data, info []byte) error {
|
|
if len(data) < 12 {
|
|
return fmt.Errorf("bptc: data size %d too small, need at least 12 bytes", len(data))
|
|
}
|
|
if len(info) < 196 {
|
|
return fmt.Errorf("bptc: info size %d too small, need at least 196 bits", len(info))
|
|
}
|
|
|
|
var (
|
|
i, j, k uint32
|
|
datafr = make([]byte, 196)
|
|
extracted = make([]byte, 96)
|
|
)
|
|
|
|
copy(extracted, dmr.BytesToBits(data))
|
|
|
|
for i = 0; i < 9; i++ {
|
|
if i == 0 {
|
|
for j = 3; j < 11; j++ {
|
|
datafr[j+1] = extracted[k]
|
|
k++
|
|
}
|
|
} else {
|
|
for j = 0; j < 11; j++ {
|
|
datafr[j+i*15+1] = extracted[k]
|
|
k++
|
|
}
|
|
}
|
|
|
|
datafr[i*15+11+1] = 8
|
|
datafr[i*15+12+1] = 8
|
|
datafr[i*15+13+1] = 8
|
|
datafr[i*15+14+1] = 8
|
|
}
|
|
|
|
// Interleave bits
|
|
for i = 1; i < 197; i++ {
|
|
info[dm[i]] = datafr[i-1]
|
|
}
|
|
|
|
if debug {
|
|
dump(info)
|
|
}
|
|
|
|
return nil
|
|
}
|