|
4 | 4 | from common import Packet, SHTPParser |
5 | 5 |
|
6 | 6 |
|
| 7 | +GYRO_REPORT_ID = 0x02 |
| 8 | +GYRO_REPORT_LEN = 10 |
| 9 | + |
| 10 | +LIN_ACCEL_REPORT_ID = 0x04 |
| 11 | +LIN_ACCEL_REPORT_LEN = 10 |
| 12 | + |
| 13 | +ROTV_REPORT_ID = 0x05 |
| 14 | +ROTV_REPORT_LEN = 14 |
| 15 | + |
| 16 | +TIMEBASE_REPORT_ID = 0xFB |
| 17 | +TIMEBASE_REPORT_LEN = 5 |
| 18 | + |
| 19 | +class Report: |
| 20 | + report_type: str |
| 21 | + start_time: float |
| 22 | + end_time: float |
| 23 | + report_id: int |
| 24 | + sequence: int |
| 25 | + status: int |
| 26 | + delay: int |
| 27 | + length: int |
| 28 | + |
| 29 | + byte_data: bytearray |
| 30 | + |
| 31 | + def __init__(self): |
| 32 | + self.byte_data = bytearray() |
| 33 | + |
| 34 | + def done(self): |
| 35 | + # convert to floats |
| 36 | + # get quaternions |
| 37 | + # etc. |
| 38 | + pass |
| 39 | + |
| 40 | +class FixedInt16Data: |
| 41 | + lsb: int |
| 42 | + msb: int |
| 43 | + full: int |
| 44 | + q: int |
| 45 | + |
| 46 | + def __init__(self, q): |
| 47 | + self.q = q |
| 48 | + |
| 49 | + def getFloating(self): |
| 50 | + return 0.0 |
| 51 | + |
| 52 | +class GyroReport(Report): |
| 53 | + report_id = GYRO_REPORT_ID |
| 54 | + length = GYRO_REPORT_LEN |
| 55 | + report_type = 'gyro' |
| 56 | + |
| 57 | + x: FixedInt16Data |
| 58 | + y: FixedInt16Data |
| 59 | + z: FixedInt16Data |
| 60 | + |
| 61 | + def __init__(self): |
| 62 | + super().__init__() |
| 63 | + self.x = FixedInt16Data(9) |
| 64 | + self.y = FixedInt16Data(9) |
| 65 | + self.z = FixedInt16Data(9) |
| 66 | + |
| 67 | +class LinAccelReport(Report): |
| 68 | + report_id = LIN_ACCEL_REPORT_ID |
| 69 | + length = GYRO_REPORT_LEN |
| 70 | + report_type = 'accel' |
| 71 | + |
| 72 | + x: FixedInt16Data |
| 73 | + y: FixedInt16Data |
| 74 | + z: FixedInt16Data |
| 75 | + |
| 76 | + def __init__(self): |
| 77 | + super().__init__() |
| 78 | + self.x = FixedInt16Data(8) |
| 79 | + self.y = FixedInt16Data(8) |
| 80 | + self.z = FixedInt16Data(8) |
| 81 | + |
| 82 | +class RotVReport(Report): |
| 83 | + report_id = ROTV_REPORT_ID |
| 84 | + length = GYRO_REPORT_LEN |
| 85 | + report_type = 'rotv' |
| 86 | + |
| 87 | + i: FixedInt16Data |
| 88 | + j: FixedInt16Data |
| 89 | + k: FixedInt16Data |
| 90 | + real: FixedInt16Data |
| 91 | + accuracy: FixedInt16Data |
| 92 | + |
| 93 | + roll: float |
| 94 | + pitch: float |
| 95 | + yaw: float |
| 96 | + |
| 97 | + def __init__(self): |
| 98 | + super().__init__() |
| 99 | + self.i = FixedInt16Data(14) |
| 100 | + self.j = FixedInt16Data(14) |
| 101 | + self.k = FixedInt16Data(14) |
| 102 | + self.real = FixedInt16Data(14) |
| 103 | + self.accuracy = FixedInt16Data(12) |
| 104 | + |
| 105 | + self.roll = 0 |
| 106 | + self.pitch = 0 |
| 107 | + self.yaw = 0 |
| 108 | + |
| 109 | +class TimebaseReport(Report): |
| 110 | + report_id = TIMEBASE_REPORT_ID |
| 111 | + length = TIMEBASE_REPORT_LEN |
| 112 | + report_type = 'tbase' |
| 113 | + |
| 114 | + delta: int |
| 115 | + |
| 116 | + def __init__(self): |
| 117 | + self.delta = 0 |
| 118 | + super().__init__() |
| 119 | + |
| 120 | + |
7 | 121 | class SH2Hla(HighLevelAnalyzer): |
8 | 122 | result_types = { |
| 123 | + 'packet': { |
| 124 | + 'format': 'CH: {{data.channel}} SEQ: {{data.sequence}} DAT[{{data.length}}]: {{data.contents}}' |
| 125 | + }, |
| 126 | + 'tbase': { |
| 127 | + 'format': 'delta = {{data.delta}}', |
| 128 | + }, |
9 | 129 | 'accel': { |
10 | 130 | 'format': '[x,y,z] = [{{data.x}} {{data.y}} {{data.z}}]', |
11 | 131 | }, |
12 | 132 | 'gyro': { |
13 | 133 | 'format': '[x,y,z] = [{{data.x}} {{data.y}} {{data.z}}]', |
14 | 134 | }, |
15 | 135 | 'rotv': { |
16 | | - 'format': '[r,p,y,a] = [{{data.x}} {{data.y}} {{data.z}} {{data.accuracy}}]', |
| 136 | + 'format': '[r,p,y,a] = [{{data.roll}} {{data.pitch}} {{data.yaw}} {{data.accuracy}}]', |
17 | 137 | }, |
18 | 138 | } |
19 | 139 |
|
20 | 140 | def __init__(self): |
21 | 141 | self.shtp_parser = SHTPParser() |
22 | | - self.packet = None |
23 | | - self.reports = None |
| 142 | + self.current_report = None |
| 143 | + |
| 144 | + def execute_parser_step(self, new_data, start_time, end_time): |
| 145 | + if self.current_report is None: |
| 146 | + if new_data == GYRO_REPORT_ID: |
| 147 | + self.current_report = GyroReport() |
| 148 | + elif new_data == LIN_ACCEL_REPORT_ID: |
| 149 | + self.current_report = LinAccelReport() |
| 150 | + elif new_data == ROTV_REPORT_ID: |
| 151 | + self.current_report = RotVReport() |
| 152 | + elif new_data == TIMEBASE_REPORT_ID: |
| 153 | + self.current_report = TimebaseReport() |
| 154 | + else: |
| 155 | + return False |
| 156 | + |
| 157 | + self.current_report.start_time = start_time |
| 158 | + return False |
| 159 | + else: |
| 160 | + self.current_report.byte_data.extend(new_data.to_bytes(1, 'big')) |
| 161 | + |
| 162 | + if self.current_report.length - 1 == len(self.current_report.byte_data): |
| 163 | + self.current_report.end_time = end_time |
| 164 | + print('done', self.current_report.report_type, self.current_report.byte_data) |
| 165 | + return True |
| 166 | + else: |
| 167 | + return False |
| 168 | + |
| 169 | + def parse_sh2(self, frame: AnalyzerFrame, p): |
| 170 | + frames = [] |
| 171 | + |
| 172 | + for i in range(len(p.data)): |
| 173 | + is_done = self.execute_parser_step(p.data[i], p.start_times[i], p.end_times[i]) |
| 174 | + |
| 175 | + if is_done: |
| 176 | + data = dict() |
| 177 | + if self.current_report.report_type == 'gyro' or self.current_report.report_type == 'accel': |
| 178 | + |
| 179 | + data['x'] = self.current_report.x.getFloating() |
| 180 | + data['y'] = self.current_report.x.getFloating() |
| 181 | + data['z'] = self.current_report.x.getFloating() |
| 182 | + elif self.current_report.report_type == 'rotv': |
| 183 | + data['roll'] = self.current_report.roll |
| 184 | + data['pitch'] = self.current_report.pitch |
| 185 | + data['yaw'] = self.current_report.yaw |
| 186 | + elif self.current_report.report_type == 'tbase': |
| 187 | + data['delta'] = self.current_report.delta |
| 188 | + |
| 189 | + f = AnalyzerFrame( |
| 190 | + self.current_report.report_type, |
| 191 | + self.current_report.start_time, |
| 192 | + self.current_report.end_time, |
| 193 | + data |
| 194 | + ) |
| 195 | + |
| 196 | + self.current_report = None |
| 197 | + |
| 198 | + frames.append(f) |
| 199 | + |
| 200 | + |
| 201 | + return None |
24 | 202 |
|
25 | 203 | def decode(self, frame: AnalyzerFrame): |
26 | | - return self.shtp_parser.decode(frame) |
| 204 | + fp = self.shtp_parser.decode(frame) |
| 205 | + print(fp) |
| 206 | + |
| 207 | + if fp is not None: |
| 208 | + return self.parse_sh2(fp[0], fp[1]) |
| 209 | + |
| 210 | + return fp |
| 211 | + |
27 | 212 |
|
0 commit comments