def handle_data(self): """Process read data.""" if self.write: # Info row if self.reg in [Register.MTHIGH, Register.MTLOW]: ann = AnnInfo.MTREG val = hlp.format_data(self.mtreg, self.options["radix"]) annots = hlp.compose_annot(info[ann], ann_value=val) self.put(self.ssb, self.es, self.out_ann, [ann, annots]) if self.reg in range(Register.MCHIGH, Register.MOLOW + 1): ann = AnnInfo.SENSE val = "{:.2f}".format(self.calculate_sensitivity()) unit = " {}/cnt".format(Params.UNIT_LIGHT) annots = hlp.compose_annot(info[ann], ann_value=val, ann_unit=unit) self.put(self.ssb, self.es, self.out_ann, [ann, annots]) else: regword = (self.bytes[1] << 8) + self.bytes[0] # Registers row ann = AnnRegs.DATA annots = hlp.compose_annot(registers[ann]) self.put(self.ssd, self.es, self.out_ann, [ann, annots]) # # Info row ann = AnnInfo.LIGHT val = "{:.2f}".format(self.calculate_light(regword)) unit = " {}".format(Params.UNIT_LIGHT) annots = hlp.compose_annot(info[ann], ann_value=val, ann_unit=unit) self.put(self.ssb, self.es, self.out_ann, [ann, annots]) self.clear_data()
def handle_reg_0x07(self, databyte): """Process control register.""" # Bits row - Reserved bits self.putb(2, 4) self.putb(5, 7) # Bits row - OUT bit out = databyte >> ControlBits.OUT & 1 ann = AnnBits.OUT annots = hlp.compose_annot(bits[ann], ann_value=out) self.putd(ControlBits.OUT, ControlBits.OUT, [ann, annots]) # Bits row - SQWE bit sqwe = databyte >> ControlBits.SQWE & 1 sqwe_l = ("dis", "en")[sqwe] + "abled" sqwe_s = sqwe_l[0].upper() ann = AnnBits.SQWE val = [sqwe, sqwe_l, sqwe_s] annots = hlp.compose_annot(bits[ann], ann_value=val) self.putd(ControlBits.SQWE, ControlBits.SQWE, [ann, annots]) # Bits row - RS bits rate = rates[databyte & 0x03] ann = AnnBits.RS0 val = rate unit = Params.UNIT_HZ annots = hlp.compose_annot(bits[ann], ann_value=val, ann_unit=unit) val //= 1000 unit = Params.UNIT_KHZ annots_add = hlp.compose_annot(bits[ann], ann_value=val, ann_unit=unit) annots.extend(annots_add) self.putd(ControlBits.RS0, ControlBits.RS1, [ann, annots]) # Registers row ann = AnnRegs.CONTROL act = self.format_rw() annots = hlp.compose_annot(registers[ann], ann_action=act) self.put(self.ssd, self.es, self.out_ann, [ann, annots])
def handle_reg_0x03(self, databyte): """Process weekday (1-7). - Recalculate weekday in respect to starting weekday option to instance variable for formatting. """ # Bits row - reserved self.putb(3, 8) # Bits row - calculate weekday self.weekday = hlp.bcd2int(databyte & 0x07) start_weekday_index = 0 for i, weekday in enumerate(weekdays): if weekday == self.options["start_weekday"]: start_weekday_index = i break start_weekday_index += self.weekday - 1 start_weekday_index %= 7 self.weekday = start_weekday_index weekday = weekdays[self.weekday] # Bits row - weekday ann = AnnBits.WEEKDAY val = weekday annots = hlp.compose_annot(bits[ann], ann_value=val) self.putd(0, 2, [ann, annots]) # Registers row ann = AnnRegs.WEEKDAY act = self.format_rw() annots = hlp.compose_annot(registers[ann], ann_action=act) self.put(self.ssd, self.es, self.out_ann, [ann, annots])
def handle_datareg_0x00(self, dataword): """Process temperature register.""" temp, unit = self.calculate_temperature(dataword) # Bits row - EM bit - extended mode em = int(self.em) em_l = ("dis", "en")[self.em] + "abled" em_s = em_l[0].upper() ann = AnnBits.EM annots = hlp.compose_annot(bits[ann], [em, em_l, em_s]) self.putd(TempBits.EM, TempBits.EM, [ann, annots]) # Bits row - reserved bits res_bits = (3, 2)[self.em] bit_min = TempBits.RESERVED bit_max = bit_min + res_bits self.putb(bit_min, bit_max) # Bits row - data bits data_bits = 8 * len(self.bytes) - 1 - res_bits bit_min = bit_max bit_max = bit_min + data_bits self.putb(bit_min, bit_max, AnnBits.DATA) # Registers row ann = AnnRegs.TEMP val = hlp.format_data(dataword, self.options["radix"]) annots = hlp.compose_annot(registers[ann], ann_value=val) self.put(self.ssd, self.es, self.out_ann, [ann, annots]) # Info row ann = AnnInfo.TEMP annots = hlp.compose_annot(info[ann], ann_value=temp, ann_unit=unit) self.put(self.ssb, self.es, self.out_ann, [ann, annots])
def handle_reg_0x3f(self, databyte): """Process NVRAM.""" # Bits row ann = AnnBits.NVRAM val = hlp.format_data(databyte, self.options["radix"]) annots = hlp.compose_annot(bits[ann], ann_value=val) self.putd(0, 7, [ann, annots]) # Registers row ann = AnnRegs.NVRAM act = self.format_rw() annots = hlp.compose_annot(registers[ann], ann_action=act) self.put(self.ssd, self.es, self.out_ann, [ann, annots])
def handle_reg_0x04(self, databyte): """Process day (1-31).""" # Bits row self.putb(6, 8) self.day = hlp.bcd2int(databyte & 0x3f) ann = AnnBits.DAY val = self.day annots = hlp.compose_annot(bits[ann], ann_value=val) self.putd(0, 5, [ann, annots]) # Registers row ann = AnnRegs.DAY act = self.format_rw() annots = hlp.compose_annot(registers[ann], ann_action=act) self.put(self.ssd, self.es, self.out_ann, [ann, annots])
def handle_reg_0x05(self, databyte): """Process month (1-12).""" # Bits row self.putb(5, 8) self.month = hlp.bcd2int(databyte & 0x1f) ann = AnnBits.MONTH val = months[self.month] annots = hlp.compose_annot(bits[ann], ann_value=val) self.putd(0, 4, [ann, annots]) # Registers row ann = AnnRegs.MONTH act = self.format_rw() annots = hlp.compose_annot(registers[ann], ann_action=act) self.put(self.ssd, self.es, self.out_ann, [ann, annots])
def handle_reg_0x01(self, databyte): """Process minutes (0-59).""" # Bits row self.putb(7) self.minute = hlp.bcd2int(databyte & 0x7f) ann = AnnBits.MINUTE val = self.minute annots = hlp.compose_annot(bits[ann], ann_value=val) self.putd(0, 6, [ann, annots]) # Registers row ann = AnnRegs.MINUTE act = self.format_rw() annots = hlp.compose_annot(registers[ann], ann_action=act) self.put(self.ssd, self.es, self.out_ann, [ann, annots])
def handle_command_display(self, data): """Process display command.""" # Bits row - Reserved self.putr(DisplayBits.SWITCH + 1, CommandBits.MIN) # Bits row - Switch bit ann = (AnnBits.OFF, AnnBits.ON)[data >> DisplayBits.SWITCH & 1] annots = hlp.compose_annot(bits[ann]) self.putd(DisplayBits.SWITCH, DisplayBits.SWITCH, [ann, annots]) # Bits row - PWM bits mask = 0 for i in range(DisplayBits.MIN, DisplayBits.MAX + 1): mask |= 1 << i pwm = contrasts[data & mask] ann = AnnBits.CONTRAST annots = hlp.compose_annot(bits[ann], ann_value=pwm) self.putd(DisplayBits.MIN, DisplayBits.MAX, [ann, annots])
def handle_datareg_0x03(self, dataword): """Process THIGH register.""" temp, unit = self.calculate_temperature(dataword) # Registers row ann = AnnRegs.THIGH val = hlp.format_data(dataword, self.options["radix"]) annots = hlp.compose_annot(registers[ann], ann_value=val) self.put(self.ssd, self.es, self.out_ann, [ann, annots]) # Info row ann = AnnInfo.THIGH act = self.format_rw() annots = hlp.compose_annot(info[ann], ann_value=temp, ann_unit=unit, ann_action=act) self.put(self.ssb, self.es, self.out_ann, [ann, annots])
def output_datetime(self): """Format datetime string and prefix it by recent r/w operation. - Applied decoder options for the starting weekday and date format. - Datetime parts are numbered in the format string equally to numbering of time keeping registers. """ if self.options["date_format"] == "European": format_datetime =\ "{3:s} {4:02d}.{5:02d}.{6:04d} {2:02d}:{1:02d}:{0:02d}" elif self.options["date_format"] == "American": format_datetime =\ "{3:s}, {5:02d}/{4:02d}/{6:04d} {2:02d}:{1:02d}:{0:02d}" elif self.options["date_format"] == "ANSI": format_datetime =\ "{6:04d}-{4:02d}-{5:02d}T{2:02d}:{1:02d}:{0:02d}" else: format_datetime = "Unknown format" dt_str = format_datetime.format( self.second, self.minute, self.hour, weekdays[self.weekday], self.day, self.month, self.year, ) # Info row ann = AnnInfo.DATETIME val = dt_str act = self.format_rw() annots = hlp.compose_annot(info[ann], ann_value=val, ann_action=act) self.put(self.ssb, self.es, self.out_ann, [ann, annots])
def handle_reg_0x06(self, databyte): """Process year (0-99). - Add 2000 to double digit year number (expect 21st century) to instance variable for formatting. """ # Bits row self.year = hlp.bcd2int(databyte & 0xff) + 2000 ann = AnnBits.YEAR val = self.year annots = hlp.compose_annot(bits[ann], ann_value=val) self.putd(0, 7, [ann, annots]) # Registers row ann = AnnRegs.YEAR act = self.format_rw() annots = hlp.compose_annot(registers[ann], ann_action=act) self.put(self.ssd, self.es, self.out_ann, [ann, annots])
def handle_info(self): """Process display.""" # Display row if self.display: ann = AnnInfo.DISPLAY val = "{}".format("".join(self.display)) annots = hlp.compose_annot(info[ann], ann_value=val) self.put(self.ssb, self.es, self.out_ann, [ann, annots]) self.clear_data()
def check_addr(self, addr_slave): """Check correct slave address.""" if addr_slave == Address.SLAVE: return True ann = AnnInfo.BADADD val = hlp.format_data(self.addr, self.options["radix"]) annots = hlp.compose_annot(info[ann], ann_value=val) self.put(self.ss, self.es, self.out_ann, [ann, annots]) return False
def handle_address(self): """Process slave address.""" if not self.bytes: return # Registers row ann = AnnAddrs.SLAVE annots = hlp.compose_annot(addresses[ann]) self.put(self.ssd, self.es, self.out_ann, [ann, annots]) self.clear_data()
def handle_addr(self): """Process slave address.""" if not self.bytes: return # Registers row self.addr = self.bytes[0] ann = addr_annots[self.addr] annots = hlp.compose_annot(addresses[ann]) self.put(self.ss, self.es, self.out_ann, [ann, annots]) self.clear_data()
def putr(self, start, end=None): """Span reserved bit annotation across bit range bit by bit. - Parameters should be considered as a range, so that the end bit number is not annotated. """ annots = hlp.compose_annot(bits[AnnBits.RESERVED]) for bit in range(start, end or (start + 1)): self.put(self.bits[bit][1], self.bits[bit][2], self.out_ann, [AnnBits.RESERVED, annots])
def handle_data_led(self, data): """Process LED data.""" # Bits row - Active LED led = Params.LEDOFF for i in range(8): if data >> i & 1: annots = hlp.compose_annot(bits[led_annot[i]]) self.putd(i, i, [AnnBits.LED, annots]) led = leds[i] # Register LED self.leds.append(led)
def handle_command_data(self, data): """Process data command.""" # Bits row - Reserved self.putr(DataBits.MODE + 1, CommandBits.MIN) # Bits row - Mode bit ann = (AnnBits.NORMAL, AnnBits.TEST)[data >> DataBits.MODE & 1] annots = hlp.compose_annot(bits[ann]) self.putd(DataBits.MODE, DataBits.MODE, [ann, annots]) # Bits row - Addressing bit ann = (AnnBits.AUTO, AnnBits.FIXED)[data >> DataBits.ADDR & 1] self.auto = (ann == AnnBits.AUTO) annots = hlp.compose_annot(bits[ann]) self.putd(DataBits.ADDR, DataBits.ADDR, [ann, annots]) # Bits row - Read/Write bit self.write = (data >> DataBits.RW & 1 == 0) ann = (AnnBits.READ, AnnBits.WRITE)[self.write] annots = hlp.compose_annot(bits[ann]) self.putd(DataBits.RW, DataBits.RW, [ann, annots]) # Bits row - Prohibited bit self.putr(0, DataBits.RW)
def handle_pointer(self): """Process register pointer.""" # Registers row ann = AnnRegs.POINTER val = hlp.format_data(self.reg, self.options["radix"]) act = self.format_rw() annots = hlp.compose_annot(registers[ann], ann_value=val, ann_action=act) self.put(self.ssd, self.es, self.out_ann, [ann, annots]) self.clear_data()
def handle_reg_0x00(self, databyte): """Process seconds (0-59) and Clock halt bit.""" # Bits row - Clock Halt bit ch = databyte >> TimeBits.CH & 1 ch_l = ("Run", "Halt")[ch] ch_s = ch_l[0].upper() ann = AnnBits.CH val = [ch, ch_l, ch_s] annots = hlp.compose_annot(bits[ann], ann_value=val) self.putd(TimeBits.CH, TimeBits.CH, [ann, annots]) # Bits row - Second bits self.second = hlp.bcd2int(databyte & ~(1 << TimeBits.CH)) ann = AnnBits.SECOND val = self.second annots = hlp.compose_annot(bits[ann], ann_value=val) self.putd(0, TimeBits.CH - 1, [ann, annots]) # Registers row ann = AnnRegs.SECOND act = self.format_rw() annots = hlp.compose_annot(registers[ann], ann_action=act) self.put(self.ssd, self.es, self.out_ann, [ann, annots])
def handle_info(self): """Process info rows.""" # Display row if self.display: ann = AnnInfo.DISPLAY val = "{}".format("".join(self.display)) annots = hlp.compose_annot(info[ann], ann_value=val) self.put(self.ssb, self.es, self.out_ann, [ann, annots]) # LEDchain row if self.leds: ann = AnnInfo.LEDS val = "{}".format("".join(self.leds)) annots = hlp.compose_annot(info[ann], ann_value=val) self.put(self.ssb, self.es, self.out_ann, [ann, annots]) # Keyboard row if self.keys: ann = AnnInfo.KEYS val = "{}".format(",".join( map(lambda key: switches[key], self.keys))) annots = hlp.compose_annot(info[ann], ann_value=val) self.put(self.ssb, self.es, self.out_ann, [ann, annots]) self.clear_data()
def handle_command_address(self, data): """Process address command.""" # Bits row - Reserved self.putr(AddressBits.MAX + 1, CommandBits.MIN) # Bits row - Digit bits mask = 0 for i in range(AddressBits.MIN, AddressBits.MAX + 1): mask |= 1 << i adr = (data & mask) + 1 self.position = adr # Start address ann = AnnBits.POSITION annots = hlp.compose_annot(bits[ann], ann_value=adr) self.putd(AddressBits.MIN, AddressBits.MAX, [ann, annots])
def check_addr(self, addr_slave, check_gencall=False): """Check correct slave address or general call.""" if addr_slave in ( Address.GND, Address.VCC, Address.SDA, Address.SCL, ) or not check_gencall or addr_slave == GeneralCall.ADDRESS: return True ann = AnnInfo.BADADD val = hlp.format_data(self.addr, self.options["radix"]) annots = hlp.compose_annot(info[ann], ann_value=val) self.put(self.ss, self.es, self.out_ann, [ann, annots]) return False
def handle_reg(self): """Process slave register.""" if not self.bytes: return self.reg = self.bytes[0] if self.addr == GeneralCall.ADDRESS: ann = reg_annots_gc[self.reg] act = None else: ann = reg_annots[self.reg] act = info[AnnInfo.SELECT] annots = hlp.compose_annot(registers[ann], ann_action=act) self.put(self.ss, self.es, self.out_ann, [ann, annots]) self.clear_data()
def handle_command(self, data): """Detect command and call its handler.""" mask = 0 for i in range(CommandBits.MIN, CommandBits.MAX + 1): mask |= 1 << i cmd = data & mask for attr, value in vars(Command).items(): if not attr.startswith("__") and value == cmd: # Bits row - Command bits ann = cmd_annot[cmd] annots = hlp.compose_annot(bits[ann]) self.putd(CommandBits.MIN, CommandBits.MAX, [ann, annots]) # Handler fn = getattr(self, "handle_command_{}".format(attr.lower())) fn(data & ~mask)
def handle_mtreg_high(self): """Process measurement time register with high bits.""" mask = (1 << (MTregLowBits.MAX + 1)) - 1 self.mtreg &= mask # Clear high bits mtreg = (self.reg << (MTregLowBits.MAX + 1)) & 0xff self.mtreg |= mtreg self.reg = Register.MTHIGH # Bits row - high bits bit_min = MTregHighBits.MIN bit_max = MTregHighBits.MAX + 1 self.putb(bit_min, bit_max, AnnBits.DATA) # Registers row ann = AnnRegs.MTHIGH annots = hlp.compose_annot(registers[ann]) self.put(self.ssd, self.es, self.out_ann, [ann, annots]) self.clear_data()
def handle_mtreg_low(self): """Process measurement time register with low bits.""" mask = (1 << (MTregLowBits.MAX + 1)) - 1 self.mtreg &= ~mask # Clear low bits mtreg = self.reg & mask self.mtreg |= mtreg self.reg = Register.MTLOW # Bits row - low bits bit_min = MTregLowBits.MIN bit_max = MTregLowBits.MAX + 1 self.putb(bit_min, bit_max, AnnBits.DATA) # Registers row ann = AnnRegs.MTLOW annots = hlp.compose_annot(registers[ann]) self.put(self.ssd, self.es, self.out_ann, [ann, annots]) self.clear_data()
def handle_reg_0x02(self, databyte): """Process hours (1-12+AM/PM or 0-23) and 12/24 hours mode. - In case of 12 hours mode convert hours to 24 hours mode to instance variable for formatting. """ # Bits row self.putb(7) mode12h = databyte >> TimeBits.MODE & 1 if mode12h: # Bits row - 12h mode ann = AnnBits.MODE val = "12h" annots = hlp.compose_annot(bits[ann], ann_value=val) self.putd(TimeBits.MODE, TimeBits.MODE, [ann, annots]) # Bits row - AM/PM mode pm = databyte >> TimeBits.AMPM & 1 pm_l = ("AM", "PM")[pm] pm_s = pm_l[0].upper() ann = AnnBits.AMPM val = [pm, pm_l, pm_s] annots = hlp.compose_annot(bits[ann], ann_value=val) self.putd(TimeBits.AMPM, TimeBits.AMPM, [ann, annots]) # Bits row - hours self.hour = hlp.bcd2int(databyte & 0x1f) # Convert to 24h expression self.hour %= 12 if pm: self.hour += 12 ann = AnnBits.HOUR val = self.hour annots = hlp.compose_annot(bits[ann], ann_value=val) self.putd(0, TimeBits.AMPM - 1, [ann, annots]) else: # Bits row - 24h mode ann = AnnBits.MODE val = "24h" annots = hlp.compose_annot(bits[ann], ann_value=val) self.putd(TimeBits.MODE, TimeBits.MODE, [ann, annots]) # Bits row - hours self.hour = hlp.bcd2int(databyte & 0x3f) ann = AnnBits.HOUR val = self.hour annots = hlp.compose_annot(bits[ann], ann_value=val) self.putd(0, TimeBits.MODE - 1, [ann, annots]) # Registers row ann = AnnRegs.HOUR act = self.format_rw() annots = hlp.compose_annot(registers[ann], ann_action=act) self.put(self.ssd, self.es, self.out_ann, [ann, annots])
def putb(self, sb, eb=None, ann=AnnBits.RESERVED): """Span special bit annotation across bit range bit by bit. Arguments --------- sb : integer Number of the annotated start bit counting from 0. eb : integer Number of the end bit right after the last annotated bit counting from 0. If none value is provided, the method uses start value increased by 1, so that just the first bit will be annotated. ann : integer Index of the special bit's annotation in the annotations list `bits`. Default value is for reserved bit. """ annots = hlp.compose_annot(bits[ann]) for bit in range(sb, eb or (sb + 1)): self.put(self.bits[bit][1], self.bits[bit][2], self.out_ann, [ann, annots])