Example #1
0
    def __init__(self, redraw_last_image_func):
        self.__redraw_last_image_func = redraw_last_image_func
        self.__spi_bus = self.__get_spi_bus_from_ptdm()
        self.__device = None
        self.lock = PTLock("miniscreen")

        self.__ptdm_subscribe_client = None
        self.__setup_subscribe_client()

        atexit.register(self.__clean_up)
Example #2
0
    def test_acquire_locks_all_instances(self):
        lock1 = PTLock(self.__dummy_lock_id)
        lock2 = PTLock(self.__dummy_lock_id)

        lock1.acquire()
        for lock in (lock1, lock2):
            self.assertTrue(lock.is_locked())
        lock1.release()
Example #3
0
    def __init__(self, device_path: str, device_address: int):
        self._device_path = device_path
        self._device_address = device_address

        self._post_read_delay = 0.020
        self._post_write_delay = 0.020

        self._lock = PTLock(f"i2c_{device_address:#0{4}x}")

        self._read_device = None
        self._write_device = None
Example #4
0
    def test_is_locked_method(self):
        lock1 = PTLock(self.__dummy_lock_id)
        lock2 = PTLock(self.__dummy_lock_id)

        lock1.acquire()
        for lock in (lock1, lock2):
            self.assertTrue(lock.is_locked())

        lock1.release()
        for lock in (lock1, lock2):
            self.assertFalse(lock.is_locked())
Example #5
0
    def test_acquire_locks_thread_until_unlocked(self):
        def acquire_lock(_lock: PTLock):
            _lock.acquire()

        lock = PTLock(self.__dummy_lock_id)
        lock.acquire()

        lock2 = PTLock(self.__dummy_lock_id)
        thread = Thread(target=acquire_lock, args=[lock2])
        thread.start()

        self.assertTrue(thread.is_alive())
        lock.release()
        thread.join()
        self.assertFalse(thread.is_alive())
Example #6
0
 def acquire_lock(_lock: PTLock):
     _lock.acquire()
Example #7
0
 def test_release_an_unlocked_lock_returns_false(self):
     lock = PTLock(self.__dummy_lock_id)
     self.assertFalse(lock.release())
Example #8
0
    def test_release_a_locked_lock_by_other_object_fails(self):
        lock1 = PTLock(self.__dummy_lock_id)
        self.assertTrue(lock1.acquire())

        lock2 = PTLock(self.__dummy_lock_id)
        self.assertFalse(lock2.release())
Example #9
0
 def test_release_a_locked_lock_by_same_object_returns_true(self):
     lock = PTLock(self.__dummy_lock_id)
     self.assertTrue(lock.acquire())
     self.assertTrue(lock.release())
Example #10
0
 def test_acquire_an_already_acquired_lock_by_same_object_fails(self):
     lock = PTLock(self.__dummy_lock_id)
     self.assertTrue(lock.acquire())
     self.assertFalse(lock.acquire())
Example #11
0
 def test_acquire_success(self):
     lock = PTLock(self.__dummy_lock_id)
     self.assertTrue(lock.acquire())
Example #12
0
 def test_chmod_is_called_if_file_doesnt_exist(self, exists_mock):
     _ = PTLock(self.__dummy_lock_id)
     exists_mock.assert_called_once_with(self.lock_file_path)
     mock_os.chmod.assert_called_once_with(self.lock_file_path, 146)
Example #13
0
 def test_instance_opens_file(self, m):
     _ = PTLock(self.__dummy_lock_id)
     m.assert_called_with(self.lock_file_path, "w")
Example #14
0
class OledDeviceController:
    SPI_DEVICE = 0
    SPI_BUS_SPEED_HZ = 8000000
    SPI_TRANSFER_SIZE = 4096

    # TODO: drop 'redraw last image' logic at v1.0.0
    #
    # this is only necessary to support users with SPI0 on device
    # with older SDK version that only supported SPI1
    def __init__(self, redraw_last_image_func):
        self.__redraw_last_image_func = redraw_last_image_func
        self.__spi_bus = self.__get_spi_bus_from_ptdm()
        self.__device = None
        self.lock = PTLock("miniscreen")

        self.__ptdm_subscribe_client = None
        self.__setup_subscribe_client()

        atexit.register(self.__clean_up)

    def __setup_subscribe_client(self):
        def on_spi_bus_changed(parameters):
            self.__spi_bus = int(parameters[0])
            self.reset_device()
            self.__redraw_last_image_func()

        self.__ptdm_subscribe_client = PTDMSubscribeClient()
        self.__ptdm_subscribe_client.initialise(
            {Message.PUB_OLED_SPI_BUS_CHANGED: on_spi_bus_changed}
        )
        self.__ptdm_subscribe_client.start_listening()

    def __clean_up(self):
        try:
            self.__ptdm_subscribe_client.stop_listening()
        except Exception:
            pass

    def __set_controls(self, controlled_by_pi):
        message = Message.from_parts(
            Message.REQ_SET_OLED_CONTROL, [str(int(controlled_by_pi))]
        )

        with PTDMRequestClient() as request_client:
            request_client.send_message(message)

    def __setup_device(self):
        if getenv("PT_MINISCREEN_SYSTEM", "0") != "1":
            self.lock.acquire()
            atexit.register(self.reset_device)

        self.__device = sh1106(
            serial_interface=spi(
                port=self.__spi_bus,
                device=self.SPI_DEVICE,
                bus_speed_hz=self.SPI_BUS_SPEED_HZ,
                transfer_size=self.SPI_TRANSFER_SIZE,
                gpio_DC=17 if self.__spi_bus == 1 else 7,  # Always use CE1
                gpio_RST=None,
            ),
            rotate=0,
        )

    def __get_spi_bus_from_ptdm(self):
        message = Message.from_parts(Message.REQ_GET_OLED_SPI_BUS)

        with PTDMRequestClient() as request_client:
            response = request_client.send_message(message)

        return int(response.parameters[0])

    ##############################
    # Public methods
    ##############################

    def device_is_active(self):
        return self.lock.is_locked()

    def reset_device(self):
        self.__device = None
        if self.device_is_active():
            self.lock.release()

    def get_device(self):
        if self.__device is None:
            self.__setup_device()

        return self.__device

    def set_control_to_pi(self):
        self.__set_controls(controlled_by_pi=True)

    def set_control_to_hub(self):
        self.__set_controls(controlled_by_pi=False)

    @property
    def spi_bus(self):
        return self.__spi_bus

    @spi_bus.setter
    def spi_bus(self, bus):
        """Request SPI bus change from pi-top device manager."""
        assert bus in range(0, 2)

        if self.__spi_bus == bus:
            return

        message = Message.from_parts(Message.REQ_SET_OLED_SPI_BUS, [str(bus)])

        with PTDMRequestClient() as request_client:
            request_client.send_message(message)