11import re
2+ from math import log2
23from functools import partial
34from pandas import DataFrame , Series
45from typing import Iterable , Callable , Union
5- from harp .model import BitMask , GroupMask , MaskValueItem , Model , Register
6+ from harp .model import BitMask , GroupMask , MaskValueItem , Model , PayloadMember , Register
67from harp .io import read
78
89_camel_to_snake_regex = re .compile (r"(?<!^)(?=[A-Z])" )
@@ -63,12 +64,55 @@ def parser(df: DataFrame):
6364 return parser
6465
6566
67+ def _create_groupmask_lookup (groupMask : GroupMask ):
68+ return {v .root : n for n , v in groupMask .values .items ()}
69+
70+
6671def _create_groupmask_parser (name : str , groupMask : GroupMask ):
67- name = _id_camel_to_snake (name )
68- lookup = {v .root : n for n , v in groupMask .values .items ()}
72+ lookup = _create_groupmask_lookup (groupMask )
6973
7074 def parser (df : DataFrame ):
71- return DataFrame ({name : df .map (lambda x : lookup [x ])})
75+ return DataFrame ({name : df [0 ].map (lookup )})
76+
77+ return parser
78+
79+
80+ def _mask_shift (mask : int ):
81+ lsb = mask & (~ mask + 1 )
82+ return int (log2 (lsb ))
83+
84+
85+ def _create_payloadmember_parser (device : Model , member : PayloadMember ):
86+ offset = member .offset
87+ if offset is None :
88+ offset = 0
89+
90+ shift = None
91+ if member .mask is not None :
92+ shift = _mask_shift (member .mask )
93+
94+ lookup = None
95+ if member .maskType is not None :
96+ key = member .maskType .root
97+ groupMask = device .groupMasks .get (key )
98+ if groupMask is not None :
99+ lookup = _create_groupmask_lookup (groupMask )
100+
101+ is_boolean = False
102+ if member .interfaceType is not None :
103+ is_boolean = member .interfaceType .root == "bool"
104+
105+ def parser (df : DataFrame ):
106+ series = df [offset ]
107+ if member .mask is not None :
108+ series = series & member .mask
109+ if shift > 0 :
110+ series = Series (series .values >> shift , series .index )
111+ if is_boolean :
112+ series = series != 0
113+ elif lookup is not None :
114+ series = series .map (lookup )
115+ return series
72116
73117 return parser
74118
@@ -92,9 +136,15 @@ def _create_register_reader(device: Model, name: str):
92136 return RegisterReader (register , reader )
93137
94138 if register .payloadSpec is not None :
95- columns = register .payloadSpec .keys ()
96- columns = _keys_camel_to_snake (columns )
97- reader = partial (reader , columns = columns )
139+ payload_parsers = [
140+ (_id_camel_to_snake (key ), _create_payloadmember_parser (device , member ))
141+ for key , member in register .payloadSpec .items ()
142+ ]
143+
144+ def parser (df : DataFrame ):
145+ return DataFrame ({n : f (df ) for n , f in payload_parsers }, index = df .index )
146+
147+ reader = _compose (parser , reader )
98148 return RegisterReader (register , reader )
99149
100150 columns = [_id_camel_to_snake (name )]
0 commit comments