Skip to content

Commit

Permalink
add working ticking beacon
Browse files Browse the repository at this point in the history
  • Loading branch information
huiminlim committed May 7, 2021
1 parent 6dfa4b4 commit ffd7dbe
Show file tree
Hide file tree
Showing 5 changed files with 205 additions and 188 deletions.
110 changes: 110 additions & 0 deletions CCSDS_Beacon_Decoder.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
from CCSDS_Parsed_Beacon import CCSDS_Parsed_Beacon


class CCSDS_Beacon_Decoder:
def __init__(self):
pass

def parse(self, packet):
# header = packet[0:6]
# telemetry_packet_type = packet[6]

ttnc_field = packet[7:9]
ret_ttnc = self._parse_ttnc_field(ttnc_field)

adcs_field = packet[9:21]
ret_adcs = self._parse_adcs_field(adcs_field)

eps_field = packet[21:27]
ret_eps = self._parse_eps_field(eps_field)

payload_field = packet[27:31]
ret_payload = self._parse_payload_field(payload_field)

timestamp_field = packet[31:]
ret_timestamp = self._parse_timestamp_field(timestamp_field)

return CCSDS_Parsed_Beacon(ret_ttnc, ret_adcs, ret_eps, ret_payload, ret_timestamp)

def _parse_ttnc_field(self, ttnc_field):
# Decode mode
mode_lookup = {0: 'FU1', 1: 'FU2', 2: 'FU3', 3: 'FU4'}
mode_bits = (ttnc_field[0] & 0b01100000) >> 5
mode = mode_lookup.get(mode_bits)

# Decode baud
baud_lookup = {0: '1200', 1: '2400', 2: '4800', 3: '9600',
4: '19200', 5: '38400', 6: '57600', 7: '115200'}
baud_bits = (ttnc_field[0] & 0b00011100) >> 2
baud = baud_lookup.get(baud_bits)

# Channel
channel_bits = ((ttnc_field[0] & 0b00000011)
<< 5) | (ttnc_field[1] >> 3)
channel = str(int(f'{channel_bits:#0}'))

# Transmit Power
tx_power_lookup = {0: '-1', 1: '2', 2: '5',
3: '8', 4: '11', 5: '14', 6: '17', 7: '20'}
tx_power_bits = (ttnc_field[1] & 0b111)
tx_power = tx_power_lookup.get(tx_power_bits)

ret_ttnc = {'Transmission Mode': mode, 'Baud Rate': baud,
'Channel': channel, 'Transmit Power': tx_power}
return ret_ttnc

def _parse_adcs_field(self, adcs_field):
# Decode gx
gx = int.from_bytes(adcs_field[0:2], byteorder='big', signed=True)

# Decode gy
gy = int.from_bytes(adcs_field[2:4], byteorder='big', signed=True)

# Decode gz
gz = int.from_bytes(adcs_field[4:6], byteorder='big', signed=True)

# Decode mx
mx = int.from_bytes(adcs_field[6:8], byteorder='big', signed=True)

# Decode my
my = int.from_bytes(adcs_field[8:10], byteorder='big', signed=True)

# Decode mz
mz = int.from_bytes(
adcs_field[10:12], byteorder='big', signed=True)

ret_adcs = {'gx': gx, 'gy': gy, 'gz': gz,
'mx': mx, 'my': my, 'mz': mz}
return ret_adcs

def _parse_eps_field(self, eps_field):
temp_int = int.from_bytes(
eps_field[0:3], byteorder='big', signed=True)
temp = temp_int / 100
reserved = int.from_bytes(
eps_field[3:6], byteorder='big', signed=True)

return {'Temperature': temp, 'Reserved': reserved}

def _parse_payload_field(self, payload_field):
r1 = payload_field[0]
r2 = payload_field[1]
r3 = payload_field[2]
r4 = payload_field[3]

ret_payload = {'Reserved byte 1': r1, 'Reserved byte 2': r2,
'Reserved byte 3': r3, 'Reserved byte 4': r4}
return ret_payload

def _parse_timestamp_field(self, timestamp_field):
DD = timestamp_field[0]
MM = timestamp_field[1]
YYYY = int.from_bytes(
timestamp_field[2:4], byteorder='big', signed=False)
hh = timestamp_field[4]
mm = timestamp_field[5]
ss = timestamp_field[6]

ret_timestamp = {"DD": DD, "MM": MM,
"YYYY": YYYY, "hh": hh, "mm": mm, "ss": ss}
return ret_timestamp
50 changes: 50 additions & 0 deletions CCSDS_Parsed_Beacon.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
class CCSDS_Parsed_Beacon:
def __init__(self, ret_ttnc, ret_adcs, ret_eps, ret_payload, ret_timestamp):
self.ret = {'TT&C': ret_ttnc, 'ADCS': ret_adcs, 'EPS': ret_eps,
'Payload': ret_payload, 'Timestamp': ret_timestamp}

# Unpack ttnc
self.mode = ret_ttnc['Transmission Mode']
self.baud = ret_ttnc['Baud Rate']
self.channel = ret_ttnc['Channel']
self.tx_power = ret_ttnc['Transmit Power']

# Unpack adcs
self.gx = ret_adcs['gx']
self.gy = ret_adcs['gy']
self.gz = ret_adcs['gz']
self.mx = ret_adcs['mx']
self.my = ret_adcs['my']
self.mz = ret_adcs['mz']

# Unpack eps
self.temp = ret_eps['Temperature']
self.eps_reserved = ret_eps['Reserved']

# Unpack payload
self.r1 = ret_payload['Reserved byte 1']
self.r2 = ret_payload['Reserved byte 2']
self.r3 = ret_payload['Reserved byte 3']
self.r4 = ret_payload['Reserved byte 4']

# Unpack timestamp
self.ts_DD = ret_timestamp['DD']
self.ts_MM = ret_timestamp['MM']
self.ts_YYYY = ret_timestamp['YYYY']
self.ts_hh = ret_timestamp['hh']
self.ts_mm = ret_timestamp['mm']
self.ts_ss = ret_timestamp['ss']

def __str__(self):
ret = ""
for field, field_dict in self.ret.items():
ret += f"---- {field} ----"
ret += "\n".join("{:<30} {}".format(k, v)
for k, v in field_dict.items())
return ret

def get_temp(self):
return self.temp

def get_gyro(self):
return {'gx': self.gx, 'gy': self.gy, 'gz': self.gz}
22 changes: 18 additions & 4 deletions GroundStationGUI.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,14 +103,14 @@ def __init__(self, parent, pipe):
self.parent.after(1000, self.update_beacon_values)

def update_beacon_values(self):
if self.beacon_pipe.poll():
if self.beacon_pipe.poll(timeout=0):
ls = self.beacon_pipe.recv()
temp = ls[0]
gx = ls[1]
gy = ls[2]
gz = ls[3]
self.beacon_frame.update_beacon_values(temp, gx, gy, gz)
self.parent.after(1000, self.update_beacon_values)
self.parent.after(1000, self.update_beacon_values)


class BeaconFrame(tk.LabelFrame):
Expand All @@ -121,9 +121,13 @@ def __init__(self, parent, *args, **kwargs):

# Create variable to store beacon values
self.temp = tk.StringVar()
self.temp.set("0.00")
self.gx = tk.StringVar()
self.gx.set("0")
self.gy = tk.StringVar()
self.gy.set("0")
self.gz = tk.StringVar()
self.gz.set("0")

# Create label for beacon data header
self.temperature_label = self._create_header_label("Temp")
Expand All @@ -140,14 +144,24 @@ def __init__(self, parent, *args, **kwargs):
# Put the labels in grids with row/col
self._arrange_grid()

self.update_beacon_values("0.0", "0", "0", "0")

def update_beacon_values(self, temp, gx, gy, gz):
def uncolor():
self.temperature_label['bg'] = 'grey94'
self.gx_label['bg'] = 'grey94'
self.gy_label['bg'] = 'grey94'
self.gz_label['bg'] = 'grey94'

self.temp.set(temp)
self.gx.set(gx)
self.gy.set(gy)
self.gz.set(gz)

self.temperature_label['bg'] = 'yellow'
self.gx_label['bg'] = 'yellow'
self.gy_label['bg'] = 'yellow'
self.gz_label['bg'] = 'yellow'
self.parent.after(1200, uncolor)

def _create_header_label(self, header_text):
return tk.Label(self, width=6, text=header_text, borderwidth=1, relief="groove")

Expand Down
162 changes: 2 additions & 160 deletions ccsds_decoder.py
Original file line number Diff line number Diff line change
@@ -1,167 +1,9 @@
class CCSDS_Parsed_Beacon():
def __init__(self, ret_ttnc, ret_adcs, ret_eps, ret_payload, ret_timestamp):
self.ret = {'TT&C': ret_ttnc, 'ADCS': ret_adcs, 'EPS': ret_eps,
'Payload': ret_payload, 'Timestamp': ret_timestamp}

# Unpack ttnc
self.mode = ret_ttnc['Transmission Mode']
self.baud = ret_ttnc['Baud Rate']
self.channel = ret_ttnc['Channel']
self.tx_power = ret_ttnc['Transmit Power']

# Unpack adcs
self.gx = ret_adcs['gx']
self.gy = ret_adcs['gy']
self.gz = ret_adcs['gz']
self.mx = ret_adcs['mx']
self.my = ret_adcs['my']
self.mz = ret_adcs['mz']

# Unpack eps
self.temp = ret_eps['Temperature']
self.eps_reserved = ret_eps['Reserved']

# Unpack payload
self.r1 = ret_payload['Reserved byte 1']
self.r2 = ret_payload['Reserved byte 2']
self.r3 = ret_payload['Reserved byte 3']
self.r4 = ret_payload['Reserved byte 4']

# Unpack timestamp
self.ts_DD = ret_timestamp['DD']
self.ts_MM = ret_timestamp['MM']
self.ts_YYYY = ret_timestamp['YYYY']
self.ts_hh = ret_timestamp['hh']
self.ts_mm = ret_timestamp['mm']
self.ts_ss = ret_timestamp['ss']

def __str__(self):
ret = ""
for field, field_dict in self.ret.items():
ret += f"---- {field} ----"
ret += "\n".join("{:<30} {}".format(k, v)
for k, v in field_dict.items())
return ret

def get_temp(self):
return self.temp

def get_gyro(self):
return {'gx': self.gx, 'gy': self.gy, 'gz': self.gz}
from CCSDS_Beacon_Decoder import CCSDS_Beacon_Decoder


class CCSDS_Decoder():
def __init___(self):
def __init__(self):
self.beacon_decoder = CCSDS_Beacon_Decoder()

def parse_beacon(self, beacon):
return self.beacon_decoder.parse(beacon)


class CCSDS_Beacon_Decoder():
def __init__(self):
pass

def parse(self, packet):
# header = packet[0:6]
# telemetry_packet_type = packet[6]

ttnc_field = packet[7:9]
ret_ttnc = self._parse_ttnc_field(ttnc_field)

adcs_field = packet[9:21]
ret_adcs = self._parse_adcs_field(adcs_field)

eps_field = packet[21:27]
ret_eps = self._parse_eps_field(eps_field)

payload_field = packet[27:31]
ret_payload = self._parse_payload_field(payload_field)

timestamp_field = packet[31:]
ret_timestamp = self._parse_timestamp_field(timestamp_field)

return CCSDS_Parsed_Beacon(ret_ttnc, ret_adcs, ret_eps, ret_payload, ret_timestamp)

def _parse_ttnc_field(self, ttnc_field):
# Decode mode
mode_lookup = {0: 'FU1', 1: 'FU2', 2: 'FU3', 3: 'FU4'}
mode_bits = (ttnc_field[0] & 0b01100000) >> 5
mode = mode_lookup.get(mode_bits)

# Decode baud
baud_lookup = {0: '1200', 1: '2400', 2: '4800', 3: '9600',
4: '19200', 5: '38400', 6: '57600', 7: '115200'}
baud_bits = (ttnc_field[0] & 0b00011100) >> 2
baud = baud_lookup.get(baud_bits)

# Channel
channel_bits = ((ttnc_field[0] & 0b00000011)
<< 5) | (ttnc_field[1] >> 3)
channel = str(int(f'{channel_bits:#0}'))

# Transmit Power
tx_power_lookup = {0: '-1', 1: '2', 2: '5',
3: '8', 4: '11', 5: '14', 6: '17', 7: '20'}
tx_power_bits = (ttnc_field[1] & 0b111)
tx_power = tx_power_lookup.get(tx_power_bits)

ret_ttnc = {'Transmission Mode': mode, 'Baud Rate': baud,
'Channel': channel, 'Transmit Power': tx_power}
return ret_ttnc

def _parse_adcs_field(self, adcs_field):
# Decode gx
gx = int.from_bytes(adcs_field[0:2], byteorder='big', signed=True)

# Decode gy
gy = int.from_bytes(adcs_field[2:4], byteorder='big', signed=True)

# Decode gz
gz = int.from_bytes(adcs_field[4:6], byteorder='big', signed=True)

# Decode mx
mx = int.from_bytes(adcs_field[6:8], byteorder='big', signed=True)

# Decode my
my = int.from_bytes(adcs_field[8:10], byteorder='big', signed=True)

# Decode mz
mz = int.from_bytes(
adcs_field[10:12], byteorder='big', signed=True)

ret_adcs = {'gx': gx, 'gy': gy, 'gz': gz,
'mx': mx, 'my': my, 'mz': mz}
return ret_adcs

def _parse_eps_field(self, eps_field):
temp_int = int.from_bytes(
eps_field[0:3], byteorder='big', signed=True)
temp = temp_int / 100
reserved = int.from_bytes(
eps_field[3:6], byteorder='big', signed=True)

return {'Temperature': temp, 'Reserved': reserved}

def _parse_payload_field(self, payload_field):
r1 = payload_field[0]
r2 = payload_field[1]
r3 = payload_field[2]
r4 = payload_field[3]

ret_payload = {'Reserved byte 1': r1, 'Reserved byte 2': r2,
'Reserved byte 3': r3, 'Reserved byte 4': r4}
return ret_payload

def _parse_timestamp_field(self, timestamp_field):
DD = timestamp_field[0]
MM = timestamp_field[1]
YYYY = int.from_bytes(
timestamp_field[2:4], byteorder='big', signed=False)
hh = timestamp_field[4]
mm = timestamp_field[5]
ss = timestamp_field[6]

ret_timestamp = {"DD": DD, "MM": MM,
"YYYY": YYYY, "hh": hh, "mm": mm, "ss": ss}
return ret_timestamp
Loading

0 comments on commit ffd7dbe

Please sign in to comment.