|
|
@ -15,6 +15,30 @@ const (
|
|
|
|
MaxPacketFragmentSize = 1500
|
|
|
|
MaxPacketFragmentSize = 1500
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// CRC Masks for data block's CRC-9 calculation, see DMR AI spec. page 148 (Table B.21).
|
|
|
|
|
|
|
|
var crc9Masks = map[uint8]uint16{
|
|
|
|
|
|
|
|
Rate12Data: 0x00f0,
|
|
|
|
|
|
|
|
Rate34Data: 0x01ff,
|
|
|
|
|
|
|
|
//Rate1Data: 0x010f,
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func calculateCRC9(serial uint8, data []byte, dataType uint8) (crc uint16) {
|
|
|
|
|
|
|
|
for _, block := range data {
|
|
|
|
|
|
|
|
crc9(&crc, block, 8)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
crc9(&crc, serial, 7)
|
|
|
|
|
|
|
|
crc9end(&crc, 8)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Inverting according to the inversion polynomial.
|
|
|
|
|
|
|
|
crc = ^crc
|
|
|
|
|
|
|
|
crc &= 0x01ff
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Applying Data Type CRC Mask
|
|
|
|
|
|
|
|
crc ^= crc9Masks[dataType]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return crc
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
type DataBlock struct {
|
|
|
|
type DataBlock struct {
|
|
|
|
Serial uint8
|
|
|
|
Serial uint8
|
|
|
|
CRC uint16
|
|
|
|
CRC uint16
|
|
|
@ -37,17 +61,7 @@ func ParseDataBlock(data []byte, dataType uint8, confirmed bool) (*DataBlock, er
|
|
|
|
db.Data = make([]byte, db.Length)
|
|
|
|
db.Data = make([]byte, db.Length)
|
|
|
|
copy(db.Data, data[2:2+db.Length])
|
|
|
|
copy(db.Data, data[2:2+db.Length])
|
|
|
|
|
|
|
|
|
|
|
|
for _, block := range db.Data {
|
|
|
|
crc = calculateCRC9(db.Serial, db.Data, dataType)
|
|
|
|
crc9(&crc, block, 8)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
crc9(&crc, db.Serial, 7)
|
|
|
|
|
|
|
|
crc9end(&crc, 8)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Inverting according to the inversion polynomial.
|
|
|
|
|
|
|
|
crc = ^crc
|
|
|
|
|
|
|
|
crc &= 0x01ff
|
|
|
|
|
|
|
|
// Applying CRC mask, see DMR AI spec. page 143
|
|
|
|
|
|
|
|
crc ^= 0x01ff
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// FIXME(pd0mz): this is not working
|
|
|
|
// FIXME(pd0mz): this is not working
|
|
|
|
if crc != db.CRC {
|
|
|
|
if crc != db.CRC {
|
|
|
@ -69,17 +83,10 @@ func (db *DataBlock) Bytes(dataType uint8, confirmed bool) []byte {
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
if confirmed {
|
|
|
|
if confirmed {
|
|
|
|
for _, block := range db.Data {
|
|
|
|
db.CRC = calculateCRC9(db.Serial, db.Data, dataType)
|
|
|
|
crc9(&db.CRC, block, 8)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
crc9(&db.CRC, db.Serial, 7)
|
|
|
|
|
|
|
|
crc9end(&db.CRC, 8)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Inverting according to the inversion polynomial.
|
|
|
|
// Grow data slice to support the two byte prefix
|
|
|
|
db.CRC = ^db.CRC
|
|
|
|
data = append(data, make([]byte, 2)...)
|
|
|
|
db.CRC &= 0x01ff
|
|
|
|
|
|
|
|
// Applying CRC mask, see DMR AI spec. page 143
|
|
|
|
|
|
|
|
db.CRC ^= 0x01ff
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
data[0] = (db.Serial << 1) | (uint8(db.CRC>>8) & 0x01)
|
|
|
|
data[0] = (db.Serial << 1) | (uint8(db.CRC>>8) & 0x01)
|
|
|
|
data[1] = uint8(db.CRC)
|
|
|
|
data[1] = uint8(db.CRC)
|
|
|
@ -177,18 +184,7 @@ func (df *DataFragment) DataBlocks(dataType uint8, confirm bool) ([]*DataBlock,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Calculate block CRC9
|
|
|
|
// Calculate block CRC9
|
|
|
|
block.CRC = 0
|
|
|
|
block.CRC = calculateCRC9(block.Serial, block.Data, dataType)
|
|
|
|
for _, b := range block.Data {
|
|
|
|
|
|
|
|
crc9(&block.CRC, b, 8)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
crc9(&block.CRC, block.Serial, 7)
|
|
|
|
|
|
|
|
crc9end(&block.CRC, 8)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Inverting according to the inversion polynomial
|
|
|
|
|
|
|
|
block.CRC = ^block.CRC
|
|
|
|
|
|
|
|
block.CRC &= 0x01ff
|
|
|
|
|
|
|
|
// Applying CRC mask, see DMR AI spec. page 143
|
|
|
|
|
|
|
|
block.CRC ^= 0x01ff
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
blocks[i] = block
|
|
|
|
blocks[i] = block
|
|
|
|
}
|
|
|
|
}
|
|
|
|