131 lines
4.8 KiB
Go
131 lines
4.8 KiB
Go
package dmr
|
||
|
||
// Data Type information element definitions, DMR Air Interface (AI) protocol, Table 6.1
|
||
const (
|
||
PrivacyIndicator uint8 = iota // Privacy Indicator information in a standalone burst
|
||
VoiceLC // Indicates the beginning of voice transmission, carries addressing information
|
||
TerminatorWithLC // Indicates the end of transmission, carries LC information
|
||
CSBK // Carries a control block
|
||
MultiBlockControl // Header for multi-block control
|
||
MultiBlockControlContinuation // Follow-on blocks for multi-block control
|
||
Data // Carries addressing and numbering of packet data blocks
|
||
Rate12Data // Payload for rate 1/2 packet data
|
||
Rate34Data // Payload for rate 3⁄4 packet data
|
||
Idle // Fills channel when no info to transmit
|
||
VoiceBurstA // Burst A marks the start of a superframe and always contains a voice SYNC pattern
|
||
VoiceBurstB // Bursts B to F carry embedded signalling in place of the SYNC pattern
|
||
VoiceBurstC // Bursts B to F carry embedded signalling in place of the SYNC pattern
|
||
VoiceBurstD // Bursts B to F carry embedded signalling in place of the SYNC pattern
|
||
VoiceBurstE // Bursts B to F carry embedded signalling in place of the SYNC pattern
|
||
VoiceBurstF // Bursts B to F carry embedded signalling in place of the SYNC pattern
|
||
IPSCSync
|
||
UnknownSlotType
|
||
)
|
||
|
||
var DataTypeName = map[uint8]string{
|
||
PrivacyIndicator: "privacy indicator",
|
||
VoiceLC: "voice LC",
|
||
TerminatorWithLC: "terminator with LC",
|
||
CSBK: "control block",
|
||
MultiBlockControl: "multi-block control",
|
||
MultiBlockControlContinuation: "multi-block control follow-on",
|
||
Data: "data",
|
||
Rate12Data: "rate ½ packet data",
|
||
Rate34Data: "rate ¾ packet data",
|
||
Idle: "idle",
|
||
VoiceBurstA: "voice (burst A)",
|
||
VoiceBurstB: "voice (burst B)",
|
||
VoiceBurstC: "voice (burst C)",
|
||
VoiceBurstD: "voice (burst D)",
|
||
VoiceBurstE: "voice (burst E)",
|
||
VoiceBurstF: "voice (burst F)",
|
||
IPSCSync: "IPSC sync",
|
||
UnknownSlotType: "uknown",
|
||
}
|
||
|
||
// Call Type
|
||
const (
|
||
CallTypePrivate uint8 = iota
|
||
CallTypeGroup
|
||
)
|
||
|
||
// Packet represents a frame transported by the Air Interface
|
||
type Packet struct {
|
||
// 0 for slot 1, 1 for slot 2
|
||
Timeslot uint8
|
||
|
||
// Starts at zero for each incoming transmission, wraps back to zero when 256 is reached
|
||
Sequence uint8
|
||
|
||
// Source and destination DMR ID
|
||
SrcID uint32
|
||
DstID uint32
|
||
|
||
// 3 bytes registered DMR-ID for public repeaters, 4 bytes for private repeaters
|
||
RepeaterID uint32
|
||
|
||
// Random or incremented number which stays the same from PTT-press to PTT-release which identifies a stream
|
||
StreamID uint32
|
||
|
||
// Data Type or Slot type
|
||
DataType uint8
|
||
|
||
// 0 for group call, 1 for unit to unit
|
||
CallType uint8
|
||
|
||
// The on-air DMR data with possible FEC fixes to the AMBE data and/or Slot Type and/or EMB, etc
|
||
Data []byte // 34 bytes
|
||
Bits []byte // 264 bits
|
||
}
|
||
|
||
// EMBBits returns the frame EMB bits from the SYNC bits
|
||
func (p *Packet) EMBBits() []byte {
|
||
var (
|
||
b = make([]byte, EMBBits)
|
||
o = EMBHalfBits + EMBSignallingLCFragmentBits
|
||
sync = p.SyncBits()
|
||
)
|
||
copy(b[:EMBHalfBits], sync[:EMBHalfBits])
|
||
copy(b[EMBHalfBits:], sync[o:o+EMBHalfBits])
|
||
return b
|
||
}
|
||
|
||
// InfoBits returns the frame Info bits
|
||
func (p *Packet) InfoBits() []byte {
|
||
var b = make([]byte, InfoBits)
|
||
copy(b[0:InfoHalfBits], p.Bits[0:InfoHalfBits])
|
||
copy(b[InfoHalfBits:], p.Bits[InfoHalfBits+SlotTypeBits+SignalBits:])
|
||
return b
|
||
}
|
||
|
||
// SyncBits returns the frame SYNC bits
|
||
func (p *Packet) SyncBits() []byte {
|
||
return p.Bits[SyncOffsetBits : SyncOffsetBits+SyncBits]
|
||
}
|
||
|
||
// SlotType returns the frame Slot Type parsed from the Slot Type bits
|
||
func (p *Packet) SlotType() []byte {
|
||
return BitsToBytes(p.SlotTypeBits())
|
||
}
|
||
|
||
// SlotTypeBits returns the SloT Type bits
|
||
func (p *Packet) SlotTypeBits() []byte {
|
||
var o = InfoHalfBits + SlotTypeHalfBits + SyncBits
|
||
return append(p.Bits[InfoHalfBits:InfoHalfBits+SlotTypeHalfBits], p.Bits[o:o+SlotTypeHalfBits]...)
|
||
}
|
||
|
||
// VoiceBits returns the bits containing voice data
|
||
func (p *Packet) VoiceBits() []byte {
|
||
var b = make([]byte, VoiceBits)
|
||
copy(b[:VoiceHalfBits], p.Bits[:VoiceHalfBits])
|
||
copy(b[VoiceHalfBits:], p.Bits[VoiceHalfBits+SignalBits:])
|
||
return b
|
||
}
|
||
|
||
func (p *Packet) SetData(data []byte) {
|
||
p.Data = data
|
||
p.Bits = BytesToBits(data)
|
||
}
|
||
|
||
// PacketFunc is a callback function that handles DMR packets
|
||
type PacketFunc func(Repeater, *Packet) error
|