## ## This file is part of the libsigrokdecode project. ## ## Copyright (C) 2012-2013 Uwe Hermann ## Copyright (C) 2023 ALIENTEK(正点原子) <39035605@qq.com> ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, see . ## import binascii import struct import traceback import sys # these reflect the implicit IDs for the 'annotations' variable defined in the Decoder in pd.py ANN_MESSAGE = 0 ANN_ERROR = 1 ANN_BYTES = 2 LEGO_COLORS = {0:'Black', 1:'Pink', 2:'Purple', 3:'Blue', 4:'LightBlue', 5:'Cyan', 6:'Green', 7:'Yellow', 8:'Orange', 9:'Red', 10:'White'} # 255:'None' LEGO_SENSOR_MODES = {0:'ColorOnly', 1:'CoarseDist', 4:'FineDist', 6:'RGB', 8:'Color+Dist', 9:'Luminosity'} def legoColor(colorCode): if(colorCode in LEGO_COLORS): return LEGO_COLORS[colorCode] return 'None' def legoCDSensorMode(modeCode): if(modeCode in LEGO_SENSOR_MODES): return LEGO_SENSOR_MODES[modeCode] return 'Unk {:02X}'.format(modeCode) def valid_checksum(msg): b = 0xFF for c in bytearray(msg): b ^= c return not b # decorator that allows us to specify an expected message length, so we don't have to explicitly check in every message handler def expectedLength(expected_len): def new_funcEL(func): def wrapper(*args, **kwargs): msg = args[0] if(len(msg) < expected_len): return False return func(*args, **kwargs) return wrapper return new_funcEL # decorator that lets us check a message for a valid checksum before handling it def validateChecksum(func): def new_funcVC(*args, **kwargs): msg = args[0] if(not valid_checksum(msg)): return failed_checksum(msg, name=func.__name__) return func(*args, **kwargs) return new_funcVC def failed_checksum(msg, name=None): if(name == None): name = sys._getframe(1).f_code.co_name messageStr = str(binascii.hexlify(bytes(msg))) return [ANN_ERROR, ['Failed checksum: {}({})'.format(name, messageStr)]] # Color/Distance sensor -- possibly sensor mode indicator? @expectedLength(3) @validateChecksum def handle_message_46(msg): sensorMode = legoCDSensorMode(msg[1]) outMessage = ['C/D Sensor: Mode={} ({:02X})'.format(sensorMode, msg[1]), 'SensorMode={}'.format(sensorMode), sensorMode] return [ANN_MESSAGE, outMessage] # Message sent from the Hub to the Motor every ~100ms prompting the motor to send its current status # def handle_message_02(self, rxtx, msg): # expected_len = 1 # return [ANN_MESSAGE, ['Status Request', 'St Req', 'SR']] # CD sensor mode 01 response # C1 0A 34 @expectedLength(3) @validateChecksum def handle_message_C1(msg): outMessage = ['Distance: {} inches'.format(msg[1]), 'Dist: {} in'.format(msg[1]), '{}in'.format(msg[1])] return [ANN_MESSAGE, outMessage] # CD sensor mode 02 response # D2 00 00 00 00 2D @expectedLength(6) @validateChecksum def handle_message_D2(msg): outMessage = [str(binascii.hexlify(bytes(msg)))] return [ANN_MESSAGE, outMessage] # CD sensor mode 03 response -- distance >= 1 inch # C3 00 3C @expectedLength(3) @validateChecksum def handle_message_C3(msg): outMessage = ['CD Mode 03: 1/{} inch?'.format(msg[1])] return [ANN_MESSAGE, outMessage] # CD sensor mode 04 response -- distance < 1 inch # C4 00 3B @expectedLength(3) @validateChecksum def handle_message_C4(msg): outMessage = ['CD Mode 04: 1/{} inch?'.format(msg[1])] return [ANN_MESSAGE, outMessage] # CD sensor mode 05 response # C5 FF 5C # C5 03 39 -- sketch ended? @expectedLength(3) @validateChecksum def handle_message_C5(msg): outMessage = ['CD Mode 05: {:02X}'.format(msg[1])] return [ANN_MESSAGE, outMessage] # CD sensor mode 07 response # CF 00 00 30 @expectedLength(3) @validateChecksum def handle_message_CF(msg): outMessage = ['CD Mode 07: {:02X} {:02X}'.format(msg[1]. msg[2])] return [ANN_MESSAGE, outMessage] # CD sensor mode 0A response # E2 74 04 3D 04 3E 04 40 04 6D 04 A8 04 B6 04 @expectedLength(15) @validateChecksum def handle_message_E2(msg): outMessage = ['CD Mode 0A: ' + str(binascii.hexlify(bytes(msg)))] return [ANN_MESSAGE, outMessage] # CD sensor mode 09 # Color/Distance sensor -- luminosity measurement mode @expectedLength(6) @validateChecksum def handle_message_D1(msg): outMessage = ['CD Mode D1: ' + str(binascii.hexlify(bytes(msg)))] lum = struct.unpack('