def unparse(self): flag = bitarray.bitarray(endian="little") flag.frombytes(self.flag) bits = bitarray.bitarray(endian="little") bits.frombytes(b"".join([self.header(), self.info, self.fcs()])) data = flag + bit_stuff(bits) + flag return data
def fcs(self): content = bitarray.bitarray(endian="little") content.frombytes(b"".join([self.header(), self.info])) fcs = FCS() for bit in content: fcs.update_bit(bit) # fcs.update(self.header()) # fcs.update(self.info) return fcs.digest()
def fcs_validate(bits): buffer = bitarray.bitarray() fcs = FCS() for bit in bits: buffer.append(bit) if len(buffer) > 16: bit = buffer.pop(0) fcs.update(bit) yield bit if buffer.tobytes() != fcs.digest(): raise Exception("FCS checksum invalid.")
def bit_unstuff(data): count = 0 skip = False ret_bits = bitarray.bitarray(endian="little") for bit in data: if not (skip): if bit: count += 1 else: count = 0 ret_bits.append(bit) if count == 5: skip = True count = 0 else: skip = False return ret_bits
def fcs(bits): ''' Append running bitwise FCS CRC checksum to end of generator ''' fcs = FCS() for bit in bits: yield bit fcs.update_bit(bit) # test = bitarray.bitarray() # for byte in (digest & 0xff, digest >> 8): # print byte # for i in range(8): # b = (byte >> i) & 1 == 1 # test.append(b) # yield b # append fcs digest to bit stream # n.b. wire format is little-bit-endianness in addition to little-endian digest = bitarray.bitarray(endian="little") digest.frombytes(fcs.digest()) for bit in digest: yield bit
def parse(self, bits): flag = bitarray.bitarray(endian="little") flag.frombytes(self.flag) # extract bits from the first to second flag try: flag_loc = bits.search(flag) bits_noflag = bits[flag_loc[0] + 8:flag_loc[1]] # Bit unstuff bits_unstuff = bit_unstuff(bits_noflag) # Chop to length bits_bytes = bits_unstuff.tobytes() # Split bits # header = bits_unstuff[:240] h_dest = bits_unstuff[:56] h_src = bits_unstuff[56:112] for n in range(14, len(bits_bytes) - 1): if bits_bytes[n:n + 2] == "\x03\xF0": break if n == len(bits_bytes) - 1: self.destination = "no decode" self.source = "no decode" self.info = "no decode" self.digis = "no decode" return digilen = (n - 14) * 8 / 7 h_digi = bits_unstuff[112:112 + (n - 14) * 8] h_len = 112 + (n - 14) * 8 + 16 fcs = bits_unstuff[-16:] info = bits_unstuff[h_len:-16] # Split header # protocol = header[-8:] # control = header[-16:-8] # address = header[:-16] # Decode addresses destination = self.callsign_decode(h_dest) source = self.callsign_decode(h_src) if digilen == 0: digipeaters = () else: digipeters = self.callsign_decode(h_digi) # digipeaters = (self.callsign_decode(header[112:168]), self.callsign_decode(header[168:224])) print("Destination:\t", destination[:-1]) print("Source:\t\t", source[:-1]) # print "Digipeater1:\t", digipeaters[0][:-1], "-", digipeaters[0][-1] print("Digipeaters:\t", digipeaters) print("Info:\t\t", info.tobytes()) self.destination = destination self.source = source self.info = info.tobytes() self.digis = digipeaters except: self.destination = "no decode" self.source = "no decode" self.info = "no decode" self.digis = "no decode" return
def frame(stuffed_data): return nrzi( itertools.chain( bitarray.bitarray("00000000") * PADDED_ZEROS, bitarray.bitarray("01111110") * PADDED_FRAMES, stuffed_data, bitarray.bitarray("01111110")))