package homebrew import ( "fmt" "github.com/tehmaze/go-dmr/bit" "github.com/tehmaze/go-dmr/ipsc" ) // ParseData reads a raw DMR data frame from the homebrew protocol and parses it as it were an IPSC packet. func ParseData(data []byte) (*ipsc.Packet, error) { if len(data) != 53 { return nil, fmt.Errorf("invalid packet length %d, expected 53 bytes", len(data)) } var ( slotType uint16 dataType = (data[15] & bit.B11110000) >> 4 frameType = (data[15] & bit.B00001100) >> 2 ) switch frameType { case bit.B00000000, bit.B00000001: // voice/voice sync switch dataType { case bit.B00000000: slotType = ipsc.VoiceDataA case bit.B00000001: slotType = ipsc.VoiceDataB case bit.B00000010: slotType = ipsc.VoiceDataC case bit.B00000011: slotType = ipsc.VoiceDataD case bit.B00000100: slotType = ipsc.VoiceDataE case bit.B00000101: slotType = ipsc.VoiceDataF } case bit.B00000010: // data sync switch dataType { case bit.B00000001: slotType = ipsc.VoiceLCHeader case bit.B00000010: slotType = ipsc.TerminatorWithLC case bit.B00000011: slotType = ipsc.CSBK case bit.B00000110: slotType = ipsc.DataHeader case bit.B00000111: slotType = ipsc.Rate12Data case bit.B00001000: slotType = ipsc.Rate34Data } } return &ipsc.Packet{ Timeslot: (data[15] & bit.B00000001), CallType: (data[15] & bit.B00000010) >> 1, FrameType: (data[15] & bit.B00001100) >> 2, SlotType: slotType, SrcID: uint32(data[5])<<16 | uint32(data[6])<<8 | uint32(data[7]), DstID: uint32(data[8])<<16 | uint32(data[9])<<8 | uint32(data[10]), Payload: data[20:], PayloadBits: bit.NewBits(data[20:]), Sequence: data[4], }, nil }