class TestRegisterSegmentProxyMethods(unittest.TestCase): @classmethod def setUpClass(self): self.bits = [1, 0, 1, 0, 1, 0, 1, 0] def setUp(self): self.seg = RegisterSegment("NAME", 0, 7, self.bits) @patch("py_i2c_register.register_segment.RegisterSegment") def test_bytes_to_int(self, RS): self.seg.bytes_to_int() RS.to_int.assert_called_once_with(self.bits) @patch("py_i2c_register.register_segment.RegisterSegment") def test_bytes_to_twos_comp_int(self, RS): self.seg.bytes_to_twos_comp_int() RS.to_twos_comp_int.assert_called_once_with(self.bits)
def set_bits_from_int(self, reg_name, seg_name, val, write_after=False, write_fn=None): seg = self.get(reg_name).get(seg_name) bits = RegisterSegment.to_bits(val, len(seg)) self.set_bits(reg_name, seg_name, bits, write_after=write_after, write_fn=write_fn)
def test_pos_out_range(self): with self.assertRaises(ValueError): RegisterSegment.to_bits(300, 8)
def add(self, name, lsb_i, msb_i, bits): self.segments[name] = RegisterSegment(name, lsb_i, msb_i, bits) return self
def write(self, i2c): if Register._write_pattern.match(self.op_mode) is not None: bits = {} managing_segment = {} max_bit_i = 0 for segment in self.segments: segment = self.segments[segment] for bit_i in range(len(segment.bits)): actual_bit_i = bit_i + segment.lsb_i # Record maximum bit index for continuous test later if actual_bit_i > max_bit_i: max_bit_i = actual_bit_i # Mark which segment manages bit in case of configuration error if actual_bit_i not in managing_segment: managing_segment[actual_bit_i] = [] managing_segment[actual_bit_i].append(segment.name) bits[bit_i + segment.lsb_i] = segment.bits[bit_i] # Check bits are continuous and only 1 segment controls each bit cont_check_err_is = [] # Indexes where bit array is not continuous managing_segment_check_err_is = [ ] # Indexes where more than 1 RegisterSegment is controlling a bit for bit_i in range(max_bit_i + 1): # Continuous check if bit_i not in bits: cont_check_err_is.append(bit_i) # Managing segment check if (bit_i in managing_segment) and (len( managing_segment[bit_i]) > 1): managing_segment_check_err_is.append(bit_i) # Raise errors if there where any if len(cont_check_err_is) > 0: raise SyntaxError( "RegisterSegments are not configured to make a continuous series of bits, no values at indexes: {}" .format(cont_check_err_is)) if len(managing_segment_check_err_is) > 0: indexes_msg = "" for i in range(len(managing_segment_check_err_is)): bit_i = managing_segment_check_err_is[i] indexes_msg += "{} (competing segments: {})".format( bit_i, managing_segment[bit_i]) if i != len(managing_segment_check_err_is) - 1: indexes_msg += ", " raise KeyError( "More than one RegisterSegment is managing the following bit indexes: {}" .format(indexes_msg)) # Convert from bits map to bits array bits_arr = [] for key in bits: bit = bits[key] bits_arr.append(bit) # Create bytes array bytes_arr = RegisterSegment.to_padded_byte_arr(bits_arr) # Write to i2c write_status = i2c.writeBytes(self.dev_addr, self.reg_addr, bytes_arr) if write_status == 1: raise SystemError("Failed to write to i2c") else: raise AttributeError( "Register {} is not set up to allow write operations, op_mode: \"{}\"" .format(self.name, self.op_mode))
def test_lsb_higher_than_msb(self): with self.assertRaises(ValueError): seg = RegisterSegment("NAME", 7, 0, [0] * 8)
def test_pos_in_range(self): self.assertEqual(RegisterSegment.to_bits(12, 8), [0, 0, 1, 1, 0, 0, 0, 0])
def test_two_bytes_partial_fit(self): self.assertEqual( RegisterSegment.to_padded_byte_arr( [1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1]), [85, 10])
def test_neg(self): with self.assertRaises(ValueError): RegisterSegment.to_bits(-2, 8)
def test_str(self): seg = RegisterSegment("NAME", 0, 2, [0] * 3) self.assertEqual( str(seg), "RegisterSegment<name=NAME, lsb_i=0, msb_i=2, bits=[0, 0, 0]>")
def test_bit_value_err(self): seg = RegisterSegment("NAME", 0, 2, [0] * 3) with self.assertRaises(ValueError): seg.set_bits([1, 2, 3])
def test_too_few_bits(self): seg = RegisterSegment("NAME", 0, 2, [0] * 3) with self.assertRaises(IndexError): seg.set_bits([0])
def test_perfect(self): seg = RegisterSegment("NAME", 0, 2, [0] * 3) seg.set_bits([1, 1, 0]) self.assertEqual(seg.bits, [1, 1, 0])
def test_not_enough_bits(self): seg = RegisterSegment("NAME", 9, 11, [0] * 3) with self.assertRaises(KeyError): seg.update_bits([240])
def test_in_second_byte(self): seg = RegisterSegment("NAME", 9, 11, [0] * 3) seg.update_bits([213, 170]) self.assertEqual(seg.bits, [1, 0, 1])
def test_one_byte_perfect_fit(self): self.assertEqual( RegisterSegment.to_padded_byte_arr([0, 0, 1, 1, 0, 0, 0, 0]), [12])
def test_one_byte_partial_fit(self): self.assertEqual(RegisterSegment.to_padded_byte_arr([1, 1, 1, 1]), [15])
def test_len(self): seg = RegisterSegment("NAME", 0, 2, [0] * 3) self.assertEqual(len(seg), 3)
def test_two_bytes_perfect_fit(self): self.assertEqual( RegisterSegment.to_padded_byte_arr( [0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0]), [170, 85])
def test_neg_number(self): self.assertEqual( RegisterSegment.to_twos_comp_int([0, 1, 0, 1, 1, 1, 1, 1]), -6)
def test_perfect(self): seg = RegisterSegment("NAME", 0, 7, [0] * 8) self.assertEqual(seg.name, "NAME") self.assertEqual(seg.lsb_i, 0) self.assertEqual(seg.msb_i, 7) self.assertEqual(seg.bits, [0] * 8)
def test_pos_number(self): self.assertEqual( RegisterSegment.to_twos_comp_int([0, 0, 1, 1, 0, 0, 0, 0]), 12)
def test_provided_bits_too_small(self): with self.assertRaises(IndexError): seg = RegisterSegment("NAME", 0, 7, [0])
def test_upper_range(self): self.assertEqual(RegisterSegment.num_bytes_for_bits(7), 1)
def setUp(self): self.seg = RegisterSegment("NAME", 0, 7, self.bits)
def test_simple_overflow(self): self.assertEqual(RegisterSegment.num_bytes_for_bits(9), 2)
def len_bytes(self): return RegisterSegment.num_bytes_for_bits(len(self))
def test_zero(self): self.assertEqual(RegisterSegment.num_bytes_for_bits(0), 0)
def test_empty_bits(self): self.assertEqual(RegisterSegment.to_padded_byte_arr([]), [])
def test_perfect(self): seg = RegisterSegment("NAME", 0, 2, [0] * 3) seg.update_bits([213, 170]) self.assertEqual(seg.bits, [1, 0, 1])