def rpm_with_rotations(self) -> Tuple[int, int]: if self.control_mode() != MotorControlModes.MODE_2: return None value = self._mcu_device.read_n_unsigned_bytes( self.registers[MotorRegisterTypes.MODE_2_RPM_WITH_ROTATIONS], 4, little_endian=True, ) value_in_bytes = split_into_bytes(value, 4, little_endian=True) speed = join_bytes(value_in_bytes[0:2]) rotations = join_bytes(value_in_bytes[2:4]) return speed, rotations
def __read_n_bytes( self, register_address: int, number_of_bytes: int, signed: bool = False, little_endian: bool = False, ): """Base function to read from an I2C device. :param register_address: Register address to target for reading :param number_of_bytes: Number of bytes to attempt to read from register address :param signed: Indicates whether or not the value could potentially have a negative value, and is therefore represented with a signed number representation :param little_endian: Indicates whether the data to be read is in little-endian byte-order :return: result: The response from the read attempt via I2C """ # Read from device result_array = self.__run_transaction([register_address], number_of_bytes) # Check response length is correct if len(result_array) != number_of_bytes: return None # Invert byte ordering, if appropriate if little_endian: result_array.reverse() # Convert array into integer result = join_bytes(result_array) # Process signed number if appropriate if signed: if result & (1 << ((8 * number_of_bytes) - 1)): result = -(1 << (8 * number_of_bytes)) + result logger.debug( "I2C: Read " + str(number_of_bytes) + " bytes from " + hex(register_address) + " (" + ("Signed," if signed else "Unsigned,") + ("LE" if little_endian else "BE") + ")" ) logger.debug(str(result_array) + " : " + str(result)) return result
def test_control_mode_2_read_write(self): """Registers read/written when using control mode 2 methods.""" rpm_value = 500 rotations_value = 10 # from rpm and rotations values, calculate byte values to use in mocks rpm_and_rotations_in_bytes = split_into_bytes( rotations_value, 2, signed=True, little_endian=True) + split_into_bytes( rpm_value, 2, signed=True, little_endian=True) rpm_and_rotations_read = join_bytes(rpm_and_rotations_in_bytes) for motor_port_registers in MotorControlRegisters: motor_port_name = motor_port_registers.name motor_registers = motor_port_registers.value mode_1_register = motor_registers[ MotorRegisterTypes.MODE_2_RPM_WITH_ROTATIONS] # create instance controller = EncoderMotorController(port=motor_port_name) controller.set_control_mode = Mock() controller.control_mode = Mock() controller.control_mode.return_value = MotorControlModes.MODE_2 # setup r/w mocks write_n_bytes_mock = controller._mcu_device.write_n_bytes = Mock() read_n_unsigned_bytes_mock = ( controller._mcu_device.read_n_unsigned_bytes) = Mock() read_n_unsigned_bytes_mock.return_value = rpm_and_rotations_read # test controller.set_rpm_with_rotations(rpm_value, rotations_value) write_n_bytes_mock.assert_called_with(mode_1_register, rpm_and_rotations_in_bytes) self.assertEquals(controller.rpm_with_rotations(), (rpm_value, rotations_value)) read_n_unsigned_bytes_mock.assert_called_with(mode_1_register, 4, little_endian=True)
def test_join_bytes(self, byte_list, expected_value): test_value = bitwise.join_bytes(byte_list) self.assertEqual(expected_value, test_value)