Skip to content

Commit

Permalink
refactor snet support
Browse files Browse the repository at this point in the history
  • Loading branch information
Gioyik committed Jul 24, 2023
1 parent f912372 commit c9b989e
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 77 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
*~
apps/*.py
__pycache__
.DS_Store
8 changes: 6 additions & 2 deletions grc/satellites_snet_deframer.block.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,13 @@ parameters:
options: ['True', 'False']
option_labels: ['Yes', 'No']
- id: buggy_crc
label: Verbose
label: Buggy CRC
dtype: bool
default: True
- id: userdata_only
label: UserData Only
dtype: bool
options: ['True', 'False']

inputs:
- domain: message
Expand All @@ -23,6 +27,6 @@ outputs:

templates:
imports: import satellites
make: satellites.snet_deframer(verbose=${verbose}, buggy_crc = ${buggy_crc})
make: satellites.snet_deframer(verbose=${verbose}, buggy_crc = ${buggy_crc}, userdata_only = ${userdata_only})

file_format: 1
20 changes: 17 additions & 3 deletions python/snet_deframer.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@
from gnuradio import gr
import numpy as np
import pmt
from construct import *

from .bch15 import decode_bch15
from .telemetry.snet import LTUFrameHeader
from .telemetry.snet import LTUFrameHeader, PDUFrameHeader


class snet_deframer(gr.basic_block):
Expand Down Expand Up @@ -165,9 +166,22 @@ def handle_msg(self, msg_pmt):
return

pdu = np.packbits(pdu_bytes)
pdu_parsed = PDUFrameHeader.parse(pdu)

if self.verbose:
print(pdu_parsed)

# as output, it's more useful to know the payload and the kind of
# payload
pdu_tags = pmt.make_dict()
pdu_tags = pmt.dict_add(
pdu_tags, pmt.intern('SNET SrcId'), pmt.from_long(hdr.SrcId))
pdu_tags, pmt.intern('UserData'), pmt.to_pmt(pdu_parsed.UserData))
pdu_tags = pmt.dict_add(
pdu_tags, pmt.intern('FCIDSub'), pmt.to_pmt(pdu_parsed.FCIDSub))
pdu_tags = pmt.dict_add(
pdu_tags, pmt.intern('FCIDMajor'),
pmt.to_pmt(pdu_parsed.FCIDMajor))

self.message_port_pub(
pmt.intern('out'),
pmt.cons(pdu_tags, pmt.init_u8vector(len(pdu), pdu)))
pdu_tags)
157 changes: 85 additions & 72 deletions python/telemetry/snet.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import datetime

from construct import *
import construct

from ..adapters import LinearAdapter

Expand All @@ -20,73 +19,6 @@
# amateur-radio/TUBiX10-COM.pdf
# for documentation

LTUFrameHeader = BitStruct(
'SrcId' / BitsInteger(7),
'DstId' / BitsInteger(7),
'FrCntTx' / BitsInteger(4),
'FrCntRx' / BitsInteger(4),
'SNR' / BitsInteger(4),
'AiTypeSrc' / BitsInteger(4),
'AiTypeDst' / BitsInteger(4),
'DfcId' / BitsInteger(2),
'Caller' / Flag,
'Arq' / Flag,
'PduTypeId' / Flag,
'BchRq' / Flag,
'Hailing' / Flag,
'UdFl1' / Flag,
'PduLength' / BitsInteger(10),
'CRC13' / BitsInteger(13),
'CRC5' / BitsInteger(5),
Padding(2)
)


class TimeAdapter(Adapter):
def _encode(self, obj, context, path=None):
d = int((obj - datetime.datetime(2000, 1, 1))*2)
return Container(
days=d.days,
milliseconds=d.seconds * 1000 + d.microseconds / 1000)

def _decode(self, obj, context, path=None):
return (datetime.datetime(2000, 1, 1)
+ datetime.timedelta(seconds=float(obj)/2.0))


TimeStamp = TimeAdapter(BitsInteger(32, swapped=True))


SNETFrameHeaderExtension = BitStruct(
'VersNo' / BitsInteger(2),
'DFCID' / BitsInteger(2),
'ExtensionRFU' / BitsInteger(4),
'ChannelInfo' / BitsInteger(8),
'QoS' / Flag,
'PDUTypeID' / Flag,
'ARQ' / Flag,
'ControlRFU' / BitsInteger(5),
'TimeTagSub' / BitsInteger(16),
'SCID' / BitsInteger(10),
'SeqNo' / BitsInteger(14)
)

SNETFrameHeader = BitStruct(
Const(0b111100110101000000, BitsInteger(18)),
'CRC' / BitsInteger(14),
'FCIDMajor' / BitsInteger(6),
'FCIDSub' / BitsInteger(10),
'Urgent' / Flag,
'Extended' / Flag,
'CheckCRC' / Flag,
'Multiframe' / Flag,
'TimeTaggedSetting' / Flag,
'TimeTagged' / Flag,
'DataLength' / BitsInteger(10),
'TimeTag' / If(lambda c: c.TimeTagged, TimeStamp),
'Extension' / If(lambda c: c.Extended, SNETFrameHeaderExtension)
)

Battery = Struct(
'V_BAT' / LinearAdapter(2, Int16sl),
'A_IN_CHARGER' / LinearAdapter(12, Int16sl),
Expand Down Expand Up @@ -168,10 +100,91 @@ def _decode(self, obj, context, path=None):
'TargetData_ControlIsActive' / Int8ul # flag, really
)

LTUFrameHeader = BitStruct(
'SrcId' / BitsInteger(7),
'DstId' / BitsInteger(7),
'FrCntTx' / BitsInteger(4),
'FrCntRx' / BitsInteger(4),
'SNR' / BitsInteger(4),
'AiTypeSrc' / BitsInteger(4),
'AiTypeDst' / BitsInteger(4),
'DfcId' / BitsInteger(2),
'Caller' / Flag,
'Arq' / Flag,
'PduTypeId' / Flag,
'BchRq' / Flag,
'Hailing' / Flag,
'UdFl1' / Flag,
'PduLength' / BitsInteger(10),
'CRC13' / BitsInteger(13),
'CRC5' / BitsInteger(5),
Padding(2)
)

# For reference:
#
# To send mailbox messages
# FCIDMajor = 56 (COM0)
# FCIDSub = 34 || 134 (COM1)

MailboxTelemetry = Struct(
'SysTime' / BitsInteger(4),
'MemDataType' / BitsInteger(1),
'MemData32' / Hex(GreedyBytes)
# 'MemData32' / LinearAdapter(32, Int8ub)
)


snet = Struct(
'header' / SNETFrameHeader,
'telemetry' / Switch(lambda c: (c.header.FCIDMajor, c.header.FCIDSub), {
class TimeAdapter(Adapter):
def _encode(self, obj, context, path=None):
d = int((obj - datetime.datetime(2000, 1, 1))*2)
return Container(
days=d.days,
milliseconds=d.seconds * 1000 + d.microseconds / 1000)

def _decode(self, obj, context, path=None):
return (datetime.datetime(2000, 1, 1)
+ datetime.timedelta(seconds=float(obj)/2.0))


TimeStamp = TimeAdapter(BitsInteger(32, swapped=True))

PDUFrameHeaderExtension = BitStruct(
'VersNo' / BitsInteger(2),
'DFCID' / BitsInteger(2),
'ExtensionRFU' / BitsInteger(4),
'ChannelInfo' / BitsInteger(8),
'QoS' / Flag,
'PDUTypeID' / Flag,
'ARQ' / Flag,
'ControlRFU' / BitsInteger(5),
'TimeTagSub' / BitsInteger(16),
'SCID' / BitsInteger(10),
'SeqNo' / BitsInteger(14)
)

PDUFrameHeader = BitStruct(
Const(0b111100110101000000, BitsInteger(18)),
'CRC' / BitsInteger(14),
'FCIDMajor' / BitsInteger(6),
'FCIDSub' / BitsInteger(10),
'Urgent' / Flag,
'Extended' / Flag,
'CheckCRC' / Flag,
'Multiframe' / Flag,
'TimeTaggedSetting' / Flag,
'TimeTagged' / Flag,
'DataLength' / BitsInteger(10),
'TimeTag' / If(lambda c: c.TimeTagged, TimeStamp),
'Extension' / If(lambda c: c.Extended, PDUFrameHeaderExtension),
'UserData' / Switch(lambda c: (c.FCIDMajor, c.FCIDSub), {
(0, 0): ADCSTelemetry,
(9, 0): EPSTelemetry,
}, default=Pass))
(54, 17): MailboxTelemetry, # COM0
(54, 117): MailboxTelemetry # COM1
},
# why parse instead of PASS? it would be good to have a repesentation
# in case the wave file contains a new pair of FCIDMajor and FCIDSub not
# supported. It creates a bit of lag, but I guess is worth it instead of
# losing the UserData.
default=GreedyString("utf-8")))

0 comments on commit c9b989e

Please sign in to comment.