Skip to content

Commit b42d1d7

Browse files
committed
Add support for parsing payload spec members
1 parent 4db09e9 commit b42d1d7

1 file changed

Lines changed: 57 additions & 7 deletions

File tree

harp/reader.py

Lines changed: 57 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import re
2+
from math import log2
23
from functools import partial
34
from pandas import DataFrame, Series
45
from 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
67
from 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+
6671
def _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

Comments
 (0)