1616import distutils .util
1717import os .path
1818import re
19+ import struct
1920from typing import NamedTuple
2021
2122import kmc_python_c_sdls_interface
@@ -823,6 +824,38 @@ class TC_FramePrimaryHeader(NamedTuple):
823824 fl : int # Frame Length
824825 fsn : int # Frame Sequence Number
825826
827+ def hex (self ):
828+ """Convert TC frame primary header to hex string.
829+
830+ Header structure (40 bits / 5 bytes):
831+ tfvn(2) | bypass(1) | cc(1) | spare(2) | scid(10) |
832+ vcid(6) | fl(10) | fsn(8)
833+
834+ Returns:
835+ Hex string representation of the header.
836+ """
837+ # Validation
838+ assert 0 <= self .tfvn <= 3 , f"tfvn must be 2 bits (0-3), got { self .tfvn } "
839+ assert 0 <= self .bypass <= 1 , f"bypass must be 1 bit (0-1), got { self .bypass } "
840+ assert 0 <= self .cc <= 1 , f"cc must be 1 bit (0-1), got { self .cc } "
841+ assert 0 <= self .spare <= 3 , f"spare must be 2 bits (0-3), got { self .spare } "
842+ assert 0 <= self .scid <= 1023 , f"scid must be 10 bits (0-1023), got { self .scid } "
843+ assert 0 <= self .vcid <= 63 , f"vcid must be 6 bits (0-63), got { self .vcid } "
844+ assert 0 <= self .fl <= 1023 , f"fl must be 10 bits (0-1023), got { self .fl } "
845+ assert 0 <= self .fsn <= 255 , f"fsn must be 8 bits (0-255), got { self .fsn } "
846+
847+ # Build 40-bit header using bit accumulation
848+ val = ((self .tfvn & 0x3 ) << 38 |
849+ (self .bypass & 0x1 ) << 37 |
850+ (self .cc & 0x1 ) << 36 |
851+ (self .spare & 0x3 ) << 34 |
852+ (self .scid & 0x3FF ) << 24 |
853+ (self .vcid & 0x3F ) << 18 |
854+ (self .fl & 0x3FF ) << 8 |
855+ (self .fsn & 0xFF ))
856+
857+ return val .to_bytes (5 , 'big' ).hex ()
858+
826859
827860class AOS_FramePrimaryHeader (NamedTuple ):
828861 tfvn : int # Transfer Frame Version Number
@@ -836,61 +869,60 @@ class AOS_FramePrimaryHeader(NamedTuple):
836869 fhec : int # Frame Header Error Control
837870 iz : bytearray
838871
839- def hex (self ):
840- has_fhec = frame_global_config [f"aos.{ self .scid } .{ self .vcid } .{ self .tfvn } " ]["has_fhec" ]
841- has_iz = frame_global_config [f"aos.{ self .scid } .{ self .vcid } .{ self .tfvn } " ]["has_iz" ]
842-
843- from bitstring import Bits , BitArray
844- tfvn_b = Bits (uint = self .tfvn , length = 2 )
845- l = 2
846- scid_b = Bits (uint = self .scid , length = 8 )
847- l += 8
848- vcid_b = Bits (uint = self .vcid , length = 6 )
849- l += 6
850- vcfc_b = Bits (uint = self .vcfc , length = 24 )
851- l += 24
852- replay_b = Bits (uint = self .replay , length = 1 )
853- l += 1
854- vcflag_b = Bits (uint = self .vcflag , length = 1 )
855- l += 1
856- spare_b = Bits (uint = self .spare , length = 2 )
857- l += 2
858- vcfcc_b = Bits (uint = self .vcfcc , length = 4 )
859- l += 4
860- if has_fhec :
861- l += 16
862-
863- if has_iz :
864- l += len (self .iz )
865-
866- header = BitArray (length = l )
867- pos = 0
868- header .overwrite (tfvn_b , pos )
869- pos += 2
870- header .overwrite (scid_b , pos )
871- pos += 8
872- header .overwrite (vcid_b , pos )
873- pos += 6
874- header .overwrite (vcfc_b , pos )
875- pos += 24
876- header .overwrite (replay_b , pos )
877- pos += 1
878- header .overwrite (vcflag_b , pos )
879- pos += 1
880- header .overwrite (spare_b , pos )
881- pos += 2
882- header .overwrite (vcfcc_b , pos )
883- pos += 4
872+ def hex (self , config = None ):
873+ """Convert AOS frame primary header to hex string.
874+
875+ Header structure: tfvn(2) | scid(8) | vcid(6) | vcfc(24) |
876+ replay(1) | vcflag(1) | spare(2) | vcfcc(4)
877+ Optional: fhec(16), insert_zone(variable)
878+
879+ Args:
880+ config: Optional dict with 'has_fhec' and 'has_iz' keys.
881+ If not provided, looks up from frame_global_config.
882+
883+ Returns:
884+ Hex string representation of the header.
885+ """
886+ # Validation
887+ assert 0 <= self .tfvn <= 3 , f"tfvn must be 2 bits (0-3), got { self .tfvn } "
888+ assert 0 <= self .scid <= 255 , f"scid must be 8 bits (0-255), got { self .scid } "
889+ assert 0 <= self .vcid <= 63 , f"vcid must be 6 bits (0-63), got { self .vcid } "
890+ assert 0 <= self .vcfc <= 16777215 , f"vcfc must be 24 bits (0-16777215), got { self .vcfc } "
891+ assert 0 <= self .replay <= 1 , f"replay must be 1 bit (0-1), got { self .replay } "
892+ assert 0 <= self .vcflag <= 1 , f"vcflag must be 1 bit (0-1), got { self .vcflag } "
893+ assert 0 <= self .spare <= 3 , f"spare must be 2 bits (0-3), got { self .spare } "
894+ assert 0 <= self .vcfcc <= 15 , f"vcfcc must be 4 bits (0-15), got { self .vcfcc } "
895+ assert 0 <= self .fhec <= 65535 , f"fhec must be 16 bits (0-65535), got { self .fhec } "
896+
897+ # Single config lookup with defaults
898+ if config is None :
899+ key = f"aos.{ self .scid } .{ self .vcid } .{ self .tfvn } "
900+ config = frame_global_config .get (key , {"has_fhec" : False , "has_iz" : False })
901+
902+ has_fhec = config .get ("has_fhec" , False )
903+ has_iz = config .get ("has_iz" , False )
904+
905+ # Build 48-bit base header using bit accumulation
906+ val = ((self .tfvn & 0x3 ) << 46 |
907+ (self .scid & 0xFF ) << 38 |
908+ (self .vcid & 0x3F ) << 32 |
909+ (self .vcfc & 0xFFFFFF ) << 8 |
910+ (self .replay & 0x1 ) << 7 |
911+ (self .vcflag & 0x1 ) << 6 |
912+ (self .spare & 0x3 ) << 4 |
913+ (self .vcfcc & 0xF ))
914+
915+ res = bytearray (val .to_bytes (6 , 'big' ))
916+
917+ # Optional: fhec(16 bits)
884918 if has_fhec :
885- fhec_b = Bits (uint = self .fhec , length = 16 )
886- header .overwrite (fhec_b , pos )
887- pos += 16
919+ res .extend (struct .pack ('>H' , self .fhec ))
888920
921+ # Optional: insert zone
889922 if has_iz :
890- iz_b = Bits (self .iz )
891- header .overwrite (iz_b , pos )
923+ res .extend (self .iz )
892924
893- return header . h
925+ return res . hex ()
894926
895927
896928class TM_FramePrimaryHeader (NamedTuple ):
@@ -907,31 +939,42 @@ class TM_FramePrimaryHeader(NamedTuple):
907939 fhp : int # First Header Pointer
908940
909941 def hex (self ):
910- from bitstring import Bits , BitArray
911- tfvn_b = Bits (uint = self .tfvn , length = 2 )
912- scid_b = Bits (uint = self .scid , length = 10 )
913- vcid_b = Bits (uint = self .vcid , length = 3 )
914- ocf_f_b = Bits (uint = self .ocf , length = 1 )
915- mcfc_b = Bits (uint = self .mcfc , length = 8 )
916- vcfc_b = Bits (uint = self .vcfc , length = 8 )
917- shf_f_b = Bits (uint = self .shf , length = 1 )
918- sync_f_b = Bits (uint = self .sf , length = 1 )
919- po_f_b = Bits (uint = self .pof , length = 1 )
920- slid_b = Bits (uint = self .slid , length = 2 )
921- fhp_b = Bits (uint = self .fhp , length = 11 )
922- header = BitArray (length = 48 )
923- header .overwrite (tfvn_b , 0 )
924- header .overwrite (scid_b , 2 ) # 0 + 2
925- header .overwrite (vcid_b , 12 ) # 2 + 10
926- header .overwrite (ocf_f_b , 15 ) # 12 + 3
927- header .overwrite (mcfc_b , 16 ) # 15 + 1
928- header .overwrite (vcfc_b , 24 ) # 16 + 8
929- header .overwrite (shf_f_b , 32 ) # 24 + 8
930- header .overwrite (sync_f_b , 33 ) # 32 + 1
931- header .overwrite (po_f_b , 34 ) # 33 + 1
932- header .overwrite (slid_b , 35 ) # 34 + 1
933- header .overwrite (fhp_b , 37 ) # 35 + 2
934- return header .h
942+ """Convert TM frame primary header to hex string.
943+
944+ Header structure (48 bits / 6 bytes):
945+ tfvn(2) | scid(10) | vcid(3) | ocf(1) | mcfc(8) | vcfc(8) |
946+ shf(1) | sf(1) | pof(1) | slid(2) | fhp(11)
947+
948+ Returns:
949+ Hex string representation of the header.
950+ """
951+ # Validation
952+ assert 0 <= self .tfvn <= 3 , f"tfvn must be 2 bits (0-3), got { self .tfvn } "
953+ assert 0 <= self .scid <= 1023 , f"scid must be 10 bits (0-1023), got { self .scid } "
954+ assert 0 <= self .vcid <= 7 , f"vcid must be 3 bits (0-7), got { self .vcid } "
955+ assert 0 <= self .ocf <= 1 , f"ocf must be 1 bit (0-1), got { self .ocf } "
956+ assert 0 <= self .mcfc <= 255 , f"mcfc must be 8 bits (0-255), got { self .mcfc } "
957+ assert 0 <= self .vcfc <= 255 , f"vcfc must be 8 bits (0-255), got { self .vcfc } "
958+ assert 0 <= self .shf <= 1 , f"shf must be 1 bit (0-1), got { self .shf } "
959+ assert 0 <= self .sf <= 1 , f"sf must be 1 bit (0-1), got { self .sf } "
960+ assert 0 <= self .pof <= 1 , f"pof must be 1 bit (0-1), got { self .pof } "
961+ assert 0 <= self .slid <= 3 , f"slid must be 2 bits (0-3), got { self .slid } "
962+ assert 0 <= self .fhp <= 2047 , f"fhp must be 11 bits (0-2047), got { self .fhp } "
963+
964+ # Build 48-bit header using bit accumulation
965+ val = ((self .tfvn & 0x3 ) << 46 |
966+ (self .scid & 0x3FF ) << 36 |
967+ (self .vcid & 0x7 ) << 33 |
968+ (self .ocf & 0x1 ) << 32 |
969+ (self .mcfc & 0xFF ) << 24 |
970+ (self .vcfc & 0xFF ) << 16 |
971+ (self .shf & 0x1 ) << 15 |
972+ (self .sf & 0x1 ) << 14 |
973+ (self .pof & 0x1 ) << 13 |
974+ (self .slid & 0x3 ) << 11 |
975+ (self .fhp & 0x7FF ))
976+
977+ return val .to_bytes (6 , 'big' ).hex ()
935978
936979
937980class FrameSecurityHeader (NamedTuple ):
@@ -945,29 +988,23 @@ class FrameSecurityHeader(NamedTuple):
945988 pad_field_len : int
946989
947990 def hex (self ):
948- from bitstring import Bits , BitArray
949- length = 16 + (self .iv_field_len * 8 ) + (self .sn_field_len * 8 ) + (self .pad_field_len * 8 )
950- spi_b = Bits (uint = self .spi , length = 16 )
951- iv_b = Bits (self .iv )
952- sn_b = Bits (self .sn )
953- pad_b = Bits (self .pad )
954- idx = 0
955- header = BitArray (length = length )
956- header .overwrite (spi_b , idx )
957- idx += 16
958- if self .iv_field_len > 0 :
959- header .overwrite (iv_b , idx )
960- idx += (self .iv_field_len * 8 )
991+ """Convert frame security header to hex string.
961992
962- if self .sn_field_len > 0 :
963- header .overwrite (sn_b , idx )
964- idx += (self .sn_field_len * 8 )
993+ Returns:
994+ Hex string representation of the security header.
995+ """
996+ # Validation
997+ assert 0 <= self .spi <= 65535 , f"spi must be 16 bits (0-65535), got { self .spi } "
965998
999+ res = bytearray ()
1000+ res .extend (struct .pack ('>H' , self .spi ))
1001+ if self .iv_field_len > 0 :
1002+ res .extend (self .iv )
1003+ if self .sn_field_len > 0 :
1004+ res .extend (self .sn )
9661005 if self .pad_field_len > 0 :
967- header .overwrite (pad_b , idx )
968- idx += (self .pad_field_len * 8 )
969-
970- return header .h
1006+ res .extend (self .pad )
1007+ return res .hex ()
9711008
9721009
9731010class FrameSecurityTrailer (NamedTuple ):
@@ -978,24 +1015,21 @@ class FrameSecurityTrailer(NamedTuple):
9781015 fecf : int # Frame Error Control Field
9791016
9801017 def hex (self ):
981- from bitstring import Bits , BitArray
982- mac_b = Bits (self .mac )
983- ocf_b = Bits (self .ocf )
984- fecf_b = Bits (uint = self .fecf , length = 16 )
985-
986- length = 16 + (self .mac_field_len * 8 ) + (self .ocf_field_len * 8 )
987- idx = 0
988- header = BitArray (length = length )
989- if self .mac_field_len > 0 :
990- header .overwrite (mac_b , idx )
991- idx += (self .mac_field_len * 8 )
1018+ """Convert frame security trailer to hex string.
9921019
993- if self .ocf_field_len > 0 :
994- header .overwrite (ocf_b , idx )
995- idx += (self .ocf_field_len * 8 )
1020+ Returns:
1021+ Hex string representation of the security trailer.
1022+ """
1023+ # Validation
1024+ assert 0 <= self .fecf <= 65535 , f"fecf must be 16 bits (0-65535), got { self .fecf } "
9961025
997- header .overwrite (fecf_b , idx )
998- return header .h
1026+ res = bytearray ()
1027+ if self .mac_field_len > 0 :
1028+ res .extend (self .mac )
1029+ if self .ocf_field_len > 0 :
1030+ res .extend (self .ocf )
1031+ res .extend (struct .pack ('>H' , self .fecf ))
1032+ return res .hex ()
9991033
10001034
10011035class TC (NamedTuple ):
0 commit comments