예제 #1
0
    def search_bus(self):
        """
        Returns a list of up to 64 identifiers of the connected 1-Wire devices.
        Each identifier is 64-bit and consists of 8-bit family code, 48-bit ID and
        8-bit CRC.

        To get these identifiers the Bricklet runs the
        `SEARCH ROM algorithm <https://www.maximintegrated.com/en/app-notes/index.mvp/id/187>`__,
        as defined by Maxim.
        """
        with self.stream_lock:
            ret = self.search_bus_low_level()
            identifier_length = ret.identifier_length
            identifier_out_of_sync = ret.identifier_chunk_offset != 0
            identifier_data = ret.identifier_chunk_data

            while not identifier_out_of_sync and len(identifier_data) < identifier_length:
                ret = self.search_bus_low_level()
                identifier_length = ret.identifier_length
                identifier_out_of_sync = ret.identifier_chunk_offset != len(identifier_data)
                identifier_data += ret.identifier_chunk_data

            if identifier_out_of_sync: # discard remaining stream to bring it back in-sync
                while ret.identifier_chunk_offset + 7 < identifier_length:
                    ret = self.search_bus_low_level()
                    identifier_length = ret.identifier_length

                raise Error(Error.STREAM_OUT_OF_SYNC, 'Identifier stream is out-of-sync')

        return SearchBus(identifier_data[:identifier_length], ret.status)
예제 #2
0
    def write_pixels(self, column_start, row_start, column_end, row_end, pixels):
        """

        """
        column_start = int(column_start)
        row_start = int(row_start)
        column_end = int(column_end)
        row_end = int(row_end)
        pixels = list(map(bool, pixels))

        if len(pixels) > 65535:
            raise Error(Error.INVALID_PARAMETER, 'Pixels can be at most 65535 items long')

        pixels_length = len(pixels)
        pixels_chunk_offset = 0

        if pixels_length == 0:
            pixels_chunk_data = [False] * 448
            ret = self.write_pixels_low_level(column_start, row_start, column_end, row_end, pixels_length, pixels_chunk_offset, pixels_chunk_data)
        else:
            with self.stream_lock:
                while pixels_chunk_offset < pixels_length:
                    pixels_chunk_data = create_chunk_data(pixels, pixels_chunk_offset, 448, False)
                    ret = self.write_pixels_low_level(column_start, row_start, column_end, row_end, pixels_length, pixels_chunk_offset, pixels_chunk_data)
                    pixels_chunk_offset += 448

        return ret
예제 #3
0
    def reader_read_page(self):
        """
        Returns the page data from an internal buffer. To fill the buffer
        with specific pages you have to call :func:`Reader Request Page` beforehand.

        The buffer can have a size of up to 8192 bytes.
        """
        with self.stream_lock:
            ret = self.reader_read_page_low_level()
            data_length = ret.data_length
            data_out_of_sync = ret.data_chunk_offset != 0
            data_data = ret.data_chunk_data

            while not data_out_of_sync and len(data_data) < data_length:
                ret = self.reader_read_page_low_level()
                data_length = ret.data_length
                data_out_of_sync = ret.data_chunk_offset != len(data_data)
                data_data += ret.data_chunk_data

            if data_out_of_sync: # discard remaining stream to bring it back in-sync
                while ret.data_chunk_offset + 60 < data_length:
                    ret = self.reader_read_page_low_level()
                    data_length = ret.data_length

                raise Error(Error.STREAM_OUT_OF_SYNC, 'Data stream is out-of-sync')

        return data_data[:data_length]
예제 #4
0
    def reader_read_ndef(self):
        """
        Returns the NDEF data from an internal buffer. To fill the buffer
        with a NDEF message you have to call :func:`Reader Request NDEF` beforehand.

        The buffer can have a size of up to 8192 bytes.
        """
        with self.stream_lock:
            ret = self.reader_read_ndef_low_level()
            ndef_length = ret.ndef_length
            ndef_out_of_sync = ret.ndef_chunk_offset != 0
            ndef_data = ret.ndef_chunk_data

            while not ndef_out_of_sync and len(ndef_data) < ndef_length:
                ret = self.reader_read_ndef_low_level()
                ndef_length = ret.ndef_length
                ndef_out_of_sync = ret.ndef_chunk_offset != len(ndef_data)
                ndef_data += ret.ndef_chunk_data

            if ndef_out_of_sync: # discard remaining stream to bring it back in-sync
                while ret.ndef_chunk_offset + 60 < ndef_length:
                    ret = self.reader_read_ndef_low_level()
                    ndef_length = ret.ndef_length

                raise Error(Error.STREAM_OUT_OF_SYNC, 'NDEF stream is out-of-sync')

        return ndef_data[:ndef_length]
예제 #5
0
    def get_energy_meter_detailed_values(self):
        """
        TBD
        """
        values_length = 84

        with self.stream_lock:
            ret = self.get_energy_meter_detailed_values_low_level()

            if ret.values_chunk_offset == (
                    1 << 16) - 1:  # maximum chunk offset -> stream has no data
                values_length = 0
                values_out_of_sync = False
                values_data = ()
            else:
                values_out_of_sync = ret.values_chunk_offset != 0
                values_data = ret.values_chunk_data

            while not values_out_of_sync and len(values_data) < values_length:
                ret = self.get_energy_meter_detailed_values_low_level()
                values_out_of_sync = ret.values_chunk_offset != len(
                    values_data)
                values_data += ret.values_chunk_data

            if values_out_of_sync:  # discard remaining stream to bring it back in-sync
                while ret.values_chunk_offset + 15 < values_length:
                    ret = self.get_energy_meter_detailed_values_low_level()

                raise Error(Error.STREAM_OUT_OF_SYNC,
                            'Values stream is out-of-sync')

        return values_data[:values_length]
예제 #6
0
    def cardemu_write_ndef(self, ndef):
        """
        Writes the NDEF messages that is to be transferred to the NFC peer.

        The maximum supported NDEF message size in Cardemu mode is 255 byte.

        You can call this function at any time in Cardemu mode. The internal buffer
        will not be overwritten until you call this function again or change the
        mode.
        """
        ndef = list(map(int, ndef))

        if len(ndef) > 65535:
            raise Error(Error.INVALID_PARAMETER, 'NDEF can be at most 65535 items long')

        ndef_length = len(ndef)
        ndef_chunk_offset = 0

        if ndef_length == 0:
            ndef_chunk_data = [0] * 60
            ret = self.cardemu_write_ndef_low_level(ndef_length, ndef_chunk_offset, ndef_chunk_data)
        else:
            with self.stream_lock:
                while ndef_chunk_offset < ndef_length:
                    ndef_chunk_data = create_chunk_data(ndef, ndef_chunk_offset, 60, 0)
                    ret = self.cardemu_write_ndef_low_level(ndef_length, ndef_chunk_offset, ndef_chunk_data)
                    ndef_chunk_offset += 60

        return ret
예제 #7
0
    def get_sensor_identifiers(self):
        """
        Returns the identifiers (number between 0 and 255) of all `sensors
        <https://www.tinkerforge.com/en/shop/accessories/sensors/temperature-humidity-sensor-th-6148.html>`__
        that have been seen since the startup of the Bricklet.

        Each sensor gives itself a random identifier on first startup.
        """
        with self.stream_lock:
            ret = self.get_sensor_identifiers_low_level()
            identifiers_length = ret.identifiers_length
            identifiers_out_of_sync = ret.identifiers_chunk_offset != 0
            identifiers_data = ret.identifiers_chunk_data

            while not identifiers_out_of_sync and len(identifiers_data) < identifiers_length:
                ret = self.get_sensor_identifiers_low_level()
                identifiers_length = ret.identifiers_length
                identifiers_out_of_sync = ret.identifiers_chunk_offset != len(identifiers_data)
                identifiers_data += ret.identifiers_chunk_data

            if identifiers_out_of_sync: # discard remaining stream to bring it back in-sync
                while ret.identifiers_chunk_offset + 60 < identifiers_length:
                    ret = self.get_sensor_identifiers_low_level()
                    identifiers_length = ret.identifiers_length

                raise Error(Error.STREAM_OUT_OF_SYNC, 'Identifiers stream is out-of-sync')

        return identifiers_data[:identifiers_length]
예제 #8
0
    def get_led_values(self, index, length):
        """
        Returns the RGB(W) values as set by :func:`Set LED Values`.
        """
        index = int(index)
        length = int(length)

        with self.stream_lock:
            ret = self.get_led_values_low_level(index, length)
            value_length = ret.value_length
            value_out_of_sync = ret.value_chunk_offset != 0
            value_data = ret.value_chunk_data

            while not value_out_of_sync and len(value_data) < value_length:
                ret = self.get_led_values_low_level(index, length)
                value_length = ret.value_length
                value_out_of_sync = ret.value_chunk_offset != len(value_data)
                value_data += ret.value_chunk_data

            if value_out_of_sync:  # discard remaining stream to bring it back in-sync
                while ret.value_chunk_offset + 60 < value_length:
                    ret = self.get_led_values_low_level(index, length)
                    value_length = ret.value_length

                raise Error(Error.STREAM_OUT_OF_SYNC,
                            'Value stream is out-of-sync')

        return value_data[:value_length]
예제 #9
0
    def read_pixels(self, x_start, y_start, x_end, y_end):
        """

        """
        x_start = int(x_start)
        y_start = int(y_start)
        x_end = int(x_end)
        y_end = int(y_end)

        with self.stream_lock:
            ret = self.read_pixels_low_level(x_start, y_start, x_end, y_end)
            pixels_length = ret.pixels_length
            pixels_out_of_sync = ret.pixels_chunk_offset != 0
            pixels_data = ret.pixels_chunk_data

            while not pixels_out_of_sync and len(pixels_data) < pixels_length:
                ret = self.read_pixels_low_level(x_start, y_start, x_end,
                                                 y_end)
                pixels_length = ret.pixels_length
                pixels_out_of_sync = ret.pixels_chunk_offset != len(
                    pixels_data)
                pixels_data += ret.pixels_chunk_data

            if pixels_out_of_sync:  # discard remaining stream to bring it back in-sync
                while ret.pixels_chunk_offset + 480 < pixels_length:
                    ret = self.read_pixels_low_level(x_start, y_start, x_end,
                                                     y_end)
                    pixels_length = ret.pixels_length

                raise Error(Error.STREAM_OUT_OF_SYNC,
                            'Pixels stream is out-of-sync')

        return pixels_data[:pixels_length]
예제 #10
0
    def read(self, length):
        """
        Returns up to *length* characters from receive buffer.

        Instead of polling with this function, you can also use
        callbacks. But note that this function will return available
        data only when the read callback is disabled.
        See :func:`Enable Read Callback` and :cb:`Read` callback.
        """
        length = int(length)

        with self.stream_lock:
            ret = self.read_low_level(length)
            message_length = ret.message_length
            message_out_of_sync = ret.message_chunk_offset != 0
            message_data = ret.message_chunk_data

            while not message_out_of_sync and len(
                    message_data) < message_length:
                ret = self.read_low_level(length)
                message_length = ret.message_length
                message_out_of_sync = ret.message_chunk_offset != len(
                    message_data)
                message_data += ret.message_chunk_data

            if message_out_of_sync:  # discard remaining stream to bring it back in-sync
                while ret.message_chunk_offset + 60 < message_length:
                    ret = self.read_low_level(length)
                    message_length = ret.message_length

                raise Error(Error.STREAM_OUT_OF_SYNC,
                            'Message stream is out-of-sync')

        return message_data[:message_length]
예제 #11
0
    def get_station_identifiers(self):
        """
        Returns the identifiers (number between 0 and 255) of all `stations
        <https://www.tinkerforge.com/en/shop/accessories/sensors/outdoor-weather-station-ws-6147.html>`__
        that have been seen since the startup of the Bricklet.

        Each station gives itself a random identifier on first startup.

        Since firmware version 2.0.2 a station is removed from the list if no data was received for
        12 hours.
        """
        with self.stream_lock:
            ret = self.get_station_identifiers_low_level()
            identifiers_length = ret.identifiers_length
            identifiers_out_of_sync = ret.identifiers_chunk_offset != 0
            identifiers_data = ret.identifiers_chunk_data

            while not identifiers_out_of_sync and len(
                    identifiers_data) < identifiers_length:
                ret = self.get_station_identifiers_low_level()
                identifiers_length = ret.identifiers_length
                identifiers_out_of_sync = ret.identifiers_chunk_offset != len(
                    identifiers_data)
                identifiers_data += ret.identifiers_chunk_data

            if identifiers_out_of_sync:  # discard remaining stream to bring it back in-sync
                while ret.identifiers_chunk_offset + 60 < identifiers_length:
                    ret = self.get_station_identifiers_low_level()
                    identifiers_length = ret.identifiers_length

                raise Error(Error.STREAM_OUT_OF_SYNC,
                            'Identifiers stream is out-of-sync')

        return identifiers_data[:identifiers_length]
예제 #12
0
    def p2p_read_ndef(self):
        """
        Returns the NDEF message that was written by a NFC peer in NFC P2P mode.
        The maximum NDEF length is 8192 byte.

        The NDEF message is ready if you called :func:`P2P Start Transfer` with a
        read transfer and the P2P state changed to *P2PTransferNDEFReady*.
        """
        with self.stream_lock:
            ret = self.p2p_read_ndef_low_level()
            ndef_length = ret.ndef_length
            ndef_out_of_sync = ret.ndef_chunk_offset != 0
            ndef_data = ret.ndef_chunk_data

            while not ndef_out_of_sync and len(ndef_data) < ndef_length:
                ret = self.p2p_read_ndef_low_level()
                ndef_length = ret.ndef_length
                ndef_out_of_sync = ret.ndef_chunk_offset != len(ndef_data)
                ndef_data += ret.ndef_chunk_data

            if ndef_out_of_sync: # discard remaining stream to bring it back in-sync
                while ret.ndef_chunk_offset + 60 < ndef_length:
                    ret = self.p2p_read_ndef_low_level()
                    ndef_length = ret.ndef_length

                raise Error(Error.STREAM_OUT_OF_SYNC, 'NDEF stream is out-of-sync')

        return ndef_data[:ndef_length]
예제 #13
0
    def get_led_values(self, index, length):
        """
        Returns *length* RGB(W) values starting from the
        given *index*.

        If the channel mapping has 3 colors, you will get the data in the sequence
        RGBRGBRGB... if the channel mapping has 4 colors you will get the data in the
        sequence RGBWRGBWRGBW...
        (assuming you start at an index divisible by 3 (RGB) or 4 (RGBW)).
        """
        index = int(index)
        length = int(length)

        with self.stream_lock:
            ret = self.get_led_values_low_level(index, length)
            value_length = ret.value_length
            value_out_of_sync = ret.value_chunk_offset != 0
            value_data = ret.value_chunk_data

            while not value_out_of_sync and len(value_data) < value_length:
                ret = self.get_led_values_low_level(index, length)
                value_length = ret.value_length
                value_out_of_sync = ret.value_chunk_offset != len(value_data)
                value_data += ret.value_chunk_data

            if value_out_of_sync:  # discard remaining stream to bring it back in-sync
                while ret.value_chunk_offset + 60 < value_length:
                    ret = self.get_led_values_low_level(index, length)
                    value_length = ret.value_length

                raise Error(Error.STREAM_OUT_OF_SYNC,
                            'Value stream is out-of-sync')

        return value_data[:value_length]
예제 #14
0
    def set_led_values(self, index, value):
        """
        Sets the RGB(W) values for the LEDs starting from *index*.
        You can set at most 2048 RGB values or 1536 RGBW values (6144 byte each).

        To make the colors show correctly you need to configure the chip type
        (see :func:`Set Chip Type`) and a channel mapping (see :func:`Set Channel Mapping`)
        according to the connected LEDs.

        If the channel mapping has 3 colors, you need to give the data in the sequence
        RGBRGBRGB... if the channel mapping has 4 colors you need to give data in the
        sequence RGBWRGBWRGBW...

        The data is double buffered and the colors will be transfered to the
        LEDs when the next frame duration ends (see :func:`Set Frame Duration`).

        Generic approach:

        * Set the frame duration to a value that represents the number of frames per
          second you want to achieve.
        * Set all of the LED colors for one frame.
        * Wait for the :cb:`Frame Started` callback.
        * Set all of the LED colors for next frame.
        * Wait for the :cb:`Frame Started` callback.
        * And so on.

        This approach ensures that you can change the LED colors with a fixed frame rate.
        """
        index = int(index)
        value = list(map(int, value))

        if len(value) > 65535:
            raise Error(Error.INVALID_PARAMETER,
                        'Value can be at most 65535 items long')

        value_length = len(value)
        value_chunk_offset = 0

        if value_length == 0:
            value_chunk_data = [0] * 58
            ret = self.set_led_values_low_level(index, value_length,
                                                value_chunk_offset,
                                                value_chunk_data)
        else:
            with self.stream_lock:
                while value_chunk_offset < value_length:
                    value_chunk_data = create_chunk_data(
                        value, value_chunk_offset, 58, 0)
                    ret = self.set_led_values_low_level(
                        index, value_length, value_chunk_offset,
                        value_chunk_data)
                    value_chunk_offset += 58

        return ret
예제 #15
0
    def write_pixels(self, x_start, y_start, x_end, y_end, pixels):
        """
        Writes pixels to the specified window.

        The x-axis goes from 0 to 127 and the y-axis from 0 to 63. The pixels are written
        into the window line by line top to bottom and each line is written from left to
        right.

        If automatic draw is enabled (default) the pixels are directly written to
        the screen. Only pixels that have actually changed are updated on the screen,
        the rest stays the same.

        If automatic draw is disabled the pixels are written to an internal buffer and
        the buffer is transferred to the display only after :func:`Draw Buffered Frame`
        is called. This can be used to avoid flicker when drawing a complex frame in
        multiple steps.

        Automatic draw can be configured with the :func:`Set Display Configuration`
        function.
        """
        x_start = int(x_start)
        y_start = int(y_start)
        x_end = int(x_end)
        y_end = int(y_end)
        pixels = list(map(bool, pixels))

        if len(pixels) > 65535:
            raise Error(Error.INVALID_PARAMETER,
                        'Pixels can be at most 65535 items long')

        pixels_length = len(pixels)
        pixels_chunk_offset = 0

        if pixels_length == 0:
            pixels_chunk_data = [False] * 448
            ret = self.write_pixels_low_level(x_start, y_start, x_end, y_end,
                                              pixels_length,
                                              pixels_chunk_offset,
                                              pixels_chunk_data)
        else:
            with self.stream_lock:
                while pixels_chunk_offset < pixels_length:
                    pixels_chunk_data = create_chunk_data(
                        pixels, pixels_chunk_offset, 448, False)
                    ret = self.write_pixels_low_level(x_start, y_start, x_end,
                                                      y_end, pixels_length,
                                                      pixels_chunk_offset,
                                                      pixels_chunk_data)
                    pixels_chunk_offset += 448

        return ret
예제 #16
0
    def reader_write_page(self, page, data):
        """
        Writes a maximum of 8192 bytes starting from the given page. How many pages are written
        depends on the tag type. The page sizes are as follows:

        * Mifare Classic page size: 16 byte
        * NFC Forum Type 1 page size: 8 byte
        * NFC Forum Type 2 page size: 4 byte
        * NFC Forum Type 3 page size: 16 byte
        * NFC Forum Type 4: No pages, page = file selection (CC or NDEF, see below)

        The general approach for writing to a tag is as follows:

        1. Call :func:`Reader Request Tag ID`
        2. Wait for state to change to *ReaderRequestTagIDReady* (see :func:`Reader Get State` or
           :cb:`Reader State Changed` callback)
        3. If looking for a specific tag then call :func:`Reader Get Tag ID` and check if the
           expected tag was found, if it was not found got back to step 1
        4. Call :func:`Reader Write Page` with page number and data
        5. Wait for state to change to *ReaderWritePageReady* (see :func:`Reader Get State` or
           :cb:`Reader State Changed` callback)

        If you use a Mifare Classic tag you have to authenticate a page before you
        can write to it. See :func:`Reader Authenticate Mifare Classic Page`.

        NFC Forum Type 4 tags are not organized into pages but different files. We currently
        support two files: Capability Container file (CC) and NDEF file.

        Choose CC by setting page to 3 or NDEF by setting page to 4.
        """
        page = int(page)
        data = list(map(int, data))

        if len(data) > 65535:
            raise Error(Error.INVALID_PARAMETER, 'Data can be at most 65535 items long')

        data_length = len(data)
        data_chunk_offset = 0

        if data_length == 0:
            data_chunk_data = [0] * 58
            ret = self.reader_write_page_low_level(page, data_length, data_chunk_offset, data_chunk_data)
        else:
            with self.stream_lock:
                while data_chunk_offset < data_length:
                    data_chunk_data = create_chunk_data(data, data_chunk_offset, 58, 0)
                    ret = self.reader_write_page_low_level(page, data_length, data_chunk_offset, data_chunk_data)
                    data_chunk_offset += 58

        return ret
예제 #17
0
    def write_pixels(self, x_start, y_start, x_end, y_end, pixels):
        """
        Writes pixels to the specified window.

        The x-axis goes from 0-127 and the y-axis from 0-63. The pixels are written
        into the window line by line from left to right.

        If automatic draw is enabled (default) the pixels are directly written to
        the screen and only changes are updated. If you only need to update a few
        pixels, only these pixels are updated on the screen, the rest stays the same.

        If automatic draw is disabled the pixels are written to a buffer and the
        buffer is transferred to the display only after :func:`Draw Buffered Frame`
        is called.

        Automatic draw can be configured with the :func:`Set Display Configuration`
        function.
        """
        x_start = int(x_start)
        y_start = int(y_start)
        x_end = int(x_end)
        y_end = int(y_end)
        pixels = list(map(bool, pixels))

        if len(pixels) > 65535:
            raise Error(Error.INVALID_PARAMETER,
                        'Pixels can be at most 65535 items long')

        pixels_length = len(pixels)
        pixels_chunk_offset = 0

        if pixels_length == 0:
            pixels_chunk_data = [False] * 448
            ret = self.write_pixels_low_level(x_start, y_start, x_end, y_end,
                                              pixels_length,
                                              pixels_chunk_offset,
                                              pixels_chunk_data)
        else:
            with self.stream_lock:
                while pixels_chunk_offset < pixels_length:
                    pixels_chunk_data = create_chunk_data(
                        pixels, pixels_chunk_offset, 448, False)
                    ret = self.write_pixels_low_level(x_start, y_start, x_end,
                                                      y_end, pixels_length,
                                                      pixels_chunk_offset,
                                                      pixels_chunk_data)
                    pixels_chunk_offset += 448

        return ret
예제 #18
0
    def write_color(self, x_start, y_start, x_end, y_end, pixels):
        """
        The E-Paper 296x128 Bricklet is available with the colors black/white/red and
        black/white/gray. Depending on the model this function writes either red or
        gray pixels to the specified window into the buffer.

        The pixels are written into the window line by line top to bottom
        and each line is written from left to right.

        The value 0 (false) means that this pixel does not have color. It will be either black
        or white (see :func:`Write Black White`). The value 1 (true) corresponds to a red or gray
        pixel, depending on the Bricklet model.

        This function writes the pixels into the red or gray pixel buffer, to draw the buffer
        to the display use :func:`Draw`.

        Use :func:`Write Black White` to write black/white pixels.
        """
        x_start = int(x_start)
        y_start = int(y_start)
        x_end = int(x_end)
        y_end = int(y_end)
        pixels = list(map(bool, pixels))

        if len(pixels) > 65535:
            raise Error(Error.INVALID_PARAMETER,
                        'Pixels can be at most 65535 items long')

        pixels_length = len(pixels)
        pixels_chunk_offset = 0

        if pixels_length == 0:
            pixels_chunk_data = [False] * 432
            ret = self.write_color_low_level(x_start, y_start, x_end, y_end,
                                             pixels_length,
                                             pixels_chunk_offset,
                                             pixels_chunk_data)
        else:
            with self.stream_lock:
                while pixels_chunk_offset < pixels_length:
                    pixels_chunk_data = create_chunk_data(
                        pixels, pixels_chunk_offset, 432, False)
                    ret = self.write_color_low_level(x_start, y_start, x_end,
                                                     y_end, pixels_length,
                                                     pixels_chunk_offset,
                                                     pixels_chunk_data)
                    pixels_chunk_offset += 432

        return ret
예제 #19
0
    def write_frame(self, frame_type, identifier, data):
        """
        Writes a data or remote frame to the write queue to be transmitted over the
        CAN transceiver.

        The Bricklet supports the standard 11-bit (CAN 2.0A) and the additional extended
        29-bit (CAN 2.0B) identifiers. For standard frames the Bricklet uses bit 0 to 10
        from the ``identifier`` parameter as standard 11-bit identifier. For extended
        frames the Bricklet uses bit 0 to 28 from the ``identifier`` parameter as
        extended 29-bit identifier.

        The ``data`` parameter can be up to 15 bytes long. For data frames up to 8 bytes
        will be used as the actual data. The length (DLC) field in the data or remote
        frame will be set to the actual length of the ``data`` parameter. This allows
        to transmit data and remote frames with excess length. For remote frames only
        the length of the ``data`` parameter is used. The actual ``data`` bytes are
        ignored.

        Returns *true* if the frame was successfully added to the write queue. Returns
        *false* if the frame could not be added because write queue is already full or
        because the write buffer or the write backlog are configured with a size of
        zero (see :func:`Set Queue Configuration`).

        The write queue can overflow if frames are written to it at a higher rate
        than the Bricklet can transmitted them over the CAN transceiver. This may
        happen if the CAN transceiver is configured as read-only or is using a low baud
        rate (see :func:`Set Transceiver Configuration`). It can also happen if the CAN
        bus is congested and the frame cannot be transmitted because it constantly loses
        arbitration or because the CAN transceiver is currently disabled due to a high
        write error level (see :func:`Get Error Log`).
        """
        frame_type = int(frame_type)
        identifier = int(identifier)
        data = list(map(int, data))

        data_length = len(data)
        data_data = list(data)  # make a copy so we can potentially extend it

        if data_length > 15:
            raise Error(Error.INVALID_PARAMETER,
                        'Data can be at most 15 items long')

        if data_length < 15:
            data_data += [0] * (15 - data_length)

        return self.write_frame_low_level(frame_type, identifier, data_length,
                                          data_data)
예제 #20
0
    def write_frame(self, frame):
        """
        Writes a DMX frame. The maximum frame size is 512 byte. Each byte represents one channel.

        The next frame can be written after the :cb:`Frame Started` callback was called. The frame
        is double buffered, so a new frame can be written as soon as the writing of the prior frame
        starts.

        The data will be transfered when the next frame duration ends, see :func:`Set Frame Duration`.

        Generic approach:

        * Set the frame duration to a value that represents the number of frames per second you want to achieve.
        * Set channels for first frame.
        * Wait for the :cb:`Frame Started` callback.
        * Set channels for next frame.
        * Wait for the :cb:`Frame Started` callback.
        * and so on.

        This approach ensures that you can set new DMX data with a fixed frame rate.

        This function can only be called in master mode.
        """
        frame = list(map(int, frame))

        if len(frame) > 65535:
            raise Error(Error.INVALID_PARAMETER,
                        'Frame can be at most 65535 items long')

        frame_length = len(frame)
        frame_chunk_offset = 0

        if frame_length == 0:
            frame_chunk_data = [0] * 60
            ret = self.write_frame_low_level(frame_length, frame_chunk_offset,
                                             frame_chunk_data)
        else:
            with self.stream_lock:
                while frame_chunk_offset < frame_length:
                    frame_chunk_data = create_chunk_data(
                        frame, frame_chunk_offset, 60, 0)
                    ret = self.write_frame_low_level(frame_length,
                                                     frame_chunk_offset,
                                                     frame_chunk_data)
                    frame_chunk_offset += 60

        return ret
예제 #21
0
    def debug_write_register(self, op_code, value):
        """
        Debug function to write to a SPI register of the A429 chip.
        """
        op_code = int(op_code)
        value = list(map(int, value))

        value_length = len(value)
        value_data = list(value) # make a copy so we can potentially extend it

        if value_length > 32:
            raise Error(Error.INVALID_PARAMETER, 'Value can be at most 32 items long')

        if value_length < 32:
            value_data += [0] * (32 - value_length)

        return self.debug_write_register_low_level(op_code, value_length, value_data)
예제 #22
0
    def read_pixels(self, x_start, y_start, x_end, y_end):
        """
        Reads pixels from the specified window.

        The x-axis goes from 0 to 127 and the y-axis from 0 to 63. The pixels are read
        from the window line by line top to bottom and each line is read from left to
        right.

        If automatic draw is enabled (default) the pixels that are read are always the
        same that are shown on the display.

        If automatic draw is disabled the pixels are read from the internal buffer
        (see :func:`Draw Buffered Frame`).

        Automatic draw can be configured with the :func:`Set Display Configuration`
        function.
        """
        x_start = int(x_start)
        y_start = int(y_start)
        x_end = int(x_end)
        y_end = int(y_end)

        with self.stream_lock:
            ret = self.read_pixels_low_level(x_start, y_start, x_end, y_end)
            pixels_length = ret.pixels_length
            pixels_out_of_sync = ret.pixels_chunk_offset != 0
            pixels_data = ret.pixels_chunk_data

            while not pixels_out_of_sync and len(pixels_data) < pixels_length:
                ret = self.read_pixels_low_level(x_start, y_start, x_end,
                                                 y_end)
                pixels_length = ret.pixels_length
                pixels_out_of_sync = ret.pixels_chunk_offset != len(
                    pixels_data)
                pixels_data += ret.pixels_chunk_data

            if pixels_out_of_sync:  # discard remaining stream to bring it back in-sync
                while ret.pixels_chunk_offset + 480 < pixels_length:
                    ret = self.read_pixels_low_level(x_start, y_start, x_end,
                                                     y_end)
                    pixels_length = ret.pixels_length

                raise Error(Error.STREAM_OUT_OF_SYNC,
                            'Pixels stream is out-of-sync')

        return pixels_data[:pixels_length]
예제 #23
0
    def write_black_white(self, x_start, y_start, x_end, y_end, pixels):
        """
        Writes black/white pixels to the specified window into the buffer.

        The pixels are written into the window line by line top to bottom
        and each line is written from left to right.

        The value 0 (false) corresponds to a black pixel and the value 1 (true) to a
        white pixel.

        This function writes the pixels into the black/white pixel buffer, to draw the
        buffer to the display use :func:`Draw`.

        Use :func:`Write Color` to write red or gray pixels.
        """
        x_start = int(x_start)
        y_start = int(y_start)
        x_end = int(x_end)
        y_end = int(y_end)
        pixels = list(map(bool, pixels))

        if len(pixels) > 65535:
            raise Error(Error.INVALID_PARAMETER,
                        'Pixels can be at most 65535 items long')

        pixels_length = len(pixels)
        pixels_chunk_offset = 0

        if pixels_length == 0:
            pixels_chunk_data = [False] * 432
            ret = self.write_black_white_low_level(x_start, y_start, x_end,
                                                   y_end, pixels_length,
                                                   pixels_chunk_offset,
                                                   pixels_chunk_data)
        else:
            with self.stream_lock:
                while pixels_chunk_offset < pixels_length:
                    pixels_chunk_data = create_chunk_data(
                        pixels, pixels_chunk_offset, 432, False)
                    ret = self.write_black_white_low_level(
                        x_start, y_start, x_end, y_end, pixels_length,
                        pixels_chunk_offset, pixels_chunk_data)
                    pixels_chunk_offset += 432

        return ret
    def get_spectrum(self):
        """
        Returns the frequency spectrum. The length of the spectrum is between
        512 (FFT size 1024) and 64 (FFT size 128). See :func:`Set Configuration`.

        Each array element is one bin of the FFT. The first bin is always the
        DC offset and the other bins have a size between 40Hz (FFT size 1024) and
        320Hz (FFT size 128).

        In sum the frequency of the spectrum always has a range from 0 to
        20480Hz (the FFT is applied to samples with a frequency of 40960Hz).

        The returned data is already equalized, which means that the microphone
        frequency response is compensated and the weighting function is applied
        (see :func:`Set Configuration` for the available weighting standards). Use
        dB(Z) if you need the unaltered spectrum.

        The values are not in dB form yet. If you want a proper dB scale of the
        spectrum you have to apply the formula f(x) = 20*log10(max(1, x/sqrt(2)))
        on each value.
        """
        with self.stream_lock:
            ret = self.get_spectrum_low_level()
            spectrum_length = ret.spectrum_length
            spectrum_out_of_sync = ret.spectrum_chunk_offset != 0
            spectrum_data = ret.spectrum_chunk_data

            while not spectrum_out_of_sync and len(
                    spectrum_data) < spectrum_length:
                ret = self.get_spectrum_low_level()
                spectrum_length = ret.spectrum_length
                spectrum_out_of_sync = ret.spectrum_chunk_offset != len(
                    spectrum_data)
                spectrum_data += ret.spectrum_chunk_data

            if spectrum_out_of_sync:  # discard remaining stream to bring it back in-sync
                while ret.spectrum_chunk_offset + 30 < spectrum_length:
                    ret = self.get_spectrum_low_level()
                    spectrum_length = ret.spectrum_length

                raise Error(Error.STREAM_OUT_OF_SYNC,
                            'Spectrum stream is out-of-sync')

        return spectrum_data[:spectrum_length]
예제 #25
0
    def get_high_contrast_image(self):
        """
        Returns the current high contrast image. See `here <https://www.tinkerforge.com/en/doc/Hardware/Bricklets/Thermal_Imaging.html#high-contrast-image-vs-temperature-image>`__
        for the difference between
        High Contrast and Temperature Image. If you don't know what to use
        the High Contrast Image is probably right for you.

        The data is organized as a 8-bit value 80x60 pixel matrix linearized in
        a one-dimensional array. The data is arranged line by line from top left to
        bottom right.

        Each 8-bit value represents one gray-scale image pixel that can directly be
        shown to a user on a display.

        Before you can use this function you have to enable it with
        :func:`Set Image Transfer Config`.
        """
        image_length = 4800

        with self.stream_lock:
            ret = self.get_high_contrast_image_low_level()

            if ret.image_chunk_offset == (
                    1 << 16) - 1:  # maximum chunk offset -> stream has no data
                image_length = 0
                image_out_of_sync = False
                image_data = ()
            else:
                image_out_of_sync = ret.image_chunk_offset != 0
                image_data = ret.image_chunk_data

            while not image_out_of_sync and len(image_data) < image_length:
                ret = self.get_high_contrast_image_low_level()
                image_out_of_sync = ret.image_chunk_offset != len(image_data)
                image_data += ret.image_chunk_data

            if image_out_of_sync:  # discard remaining stream to bring it back in-sync
                while ret.image_chunk_offset + 62 < image_length:
                    ret = self.get_high_contrast_image_low_level()

                raise Error(Error.STREAM_OUT_OF_SYNC,
                            'Image stream is out-of-sync')

        return image_data[:image_length]
예제 #26
0
    def write_wiegand_data(self, data):
        """
        TBD

        .. versionadded:: 2.0.3$nbsp;(Plugin)
        """
        data = list(map(bool, data))

        data_length = len(data)
        data_data = list(data)  # make a copy so we can potentially extend it

        if data_length > 256:
            raise Error(Error.INVALID_PARAMETER,
                        'Data can be at most 256 items long')

        if data_length < 256:
            data_data += [False] * (256 - data_length)

        return self.write_wiegand_data_low_level(data_length, data_data)
예제 #27
0
    def read_frame(self):
        """
        Returns the last frame that was written by the DMX master. The size of the array
        is equivalent to the number of channels in the frame. Each byte represents one channel.

        The next frame is available after the :cb:`Frame Available` callback was called.

        Generic approach:

        * Call :func:`Read Frame` to get first frame.
        * Wait for the :cb:`Frame Available` callback.
        * Call :func:`Read Frame` to get second frame.
        * Wait for the :cb:`Frame Available` callback.
        * and so on.

        Instead of polling this function you can also use the :cb:`Frame` callback.
        You can enable it with :func:`Set Frame Callback Config`.

        The frame number starts at 0 and it is increased by one with each received frame.

        This function can only be called in slave mode.
        """
        with self.stream_lock:
            ret = self.read_frame_low_level()
            frame_length = ret.frame_length
            frame_out_of_sync = ret.frame_chunk_offset != 0
            frame_data = ret.frame_chunk_data

            while not frame_out_of_sync and len(frame_data) < frame_length:
                ret = self.read_frame_low_level()
                frame_length = ret.frame_length
                frame_out_of_sync = ret.frame_chunk_offset != len(frame_data)
                frame_data += ret.frame_chunk_data

            if frame_out_of_sync:  # discard remaining stream to bring it back in-sync
                while ret.frame_chunk_offset + 56 < frame_length:
                    ret = self.read_frame_low_level()
                    frame_length = ret.frame_length

                raise Error(Error.STREAM_OUT_OF_SYNC,
                            'Frame stream is out-of-sync')

        return ReadFrame(frame_data[:frame_length], ret.frame_number)
예제 #28
0
    def write(self, message):
        """
        Writes characters to the RS232 interface. The characters can be binary data,
        ASCII or similar is not necessary.

        The return value is the number of characters that were written.

        See :func:`Set Configuration` for configuration possibilities
        regarding baud rate, parity and so on.
        """
        message = create_char_list(message)

        if len(message) > 65535:
            raise Error(Error.INVALID_PARAMETER,
                        'Message can be at most 65535 items long')

        message_length = len(message)
        message_chunk_offset = 0

        if message_length == 0:
            message_chunk_data = ['\0'] * 60
            ret = self.write_low_level(message_length, message_chunk_offset,
                                       message_chunk_data)
            message_written = ret
        else:
            message_written = 0

            with self.stream_lock:
                while message_chunk_offset < message_length:
                    message_chunk_data = create_chunk_data(
                        message, message_chunk_offset, 60, '\0')
                    ret = self.write_low_level(message_length,
                                               message_chunk_offset,
                                               message_chunk_data)
                    message_written += ret

                    if ret < 60:
                        break  # either last chunk or short write

                    message_chunk_offset += 60

        return message_written
예제 #29
0
    def get_waveform(self):
        """
        Returns a snapshot of the voltage and current waveform. The values
        in the returned array alternate between voltage and current. The data from
        one getter call contains 768 data points for voltage and current, which
        correspond to about 3 full sine waves.

        The voltage is given with a resolution of 100mV and the current is given
        with a resolution of 10mA.

        This data is meant to be used for a non-realtime graphical representation of
        the voltage and current waveforms.
        """
        waveform_length = 1536

        with self.stream_lock:
            ret = self.get_waveform_low_level()

            if ret.waveform_chunk_offset == (
                    1 << 16) - 1:  # maximum chunk offset -> stream has no data
                waveform_length = 0
                waveform_out_of_sync = False
                waveform_data = ()
            else:
                waveform_out_of_sync = ret.waveform_chunk_offset != 0
                waveform_data = ret.waveform_chunk_data

            while not waveform_out_of_sync and len(
                    waveform_data) < waveform_length:
                ret = self.get_waveform_low_level()
                waveform_out_of_sync = ret.waveform_chunk_offset != len(
                    waveform_data)
                waveform_data += ret.waveform_chunk_data

            if waveform_out_of_sync:  # discard remaining stream to bring it back in-sync
                while ret.waveform_chunk_offset + 30 < waveform_length:
                    ret = self.get_waveform_low_level()

                raise Error(Error.STREAM_OUT_OF_SYNC,
                            'Waveform stream is out-of-sync')

        return waveform_data[:waveform_length]
예제 #30
0
    def read_black_white(self, x_start, y_start, x_end, y_end):
        """
        Returns the current content of the black/white pixel buffer for the specified window.

        The pixels are read into the window line by line top to bottom and
        each line is read from left to right.

        The current content of the buffer does not have to be the current content of the display.
        It is possible that the data was not drawn to the display yet and after a restart of
        the Bricklet the buffer will be reset to black, while the display retains its content.
        """
        x_start = int(x_start)
        y_start = int(y_start)
        x_end = int(x_end)
        y_end = int(y_end)

        with self.stream_lock:
            ret = self.read_black_white_low_level(x_start, y_start, x_end,
                                                  y_end)
            pixels_length = ret.pixels_length
            pixels_out_of_sync = ret.pixels_chunk_offset != 0
            pixels_data = ret.pixels_chunk_data

            while not pixels_out_of_sync and len(pixels_data) < pixels_length:
                ret = self.read_black_white_low_level(x_start, y_start, x_end,
                                                      y_end)
                pixels_length = ret.pixels_length
                pixels_out_of_sync = ret.pixels_chunk_offset != len(
                    pixels_data)
                pixels_data += ret.pixels_chunk_data

            if pixels_out_of_sync:  # discard remaining stream to bring it back in-sync
                while ret.pixels_chunk_offset + 464 < pixels_length:
                    ret = self.read_black_white_low_level(
                        x_start, y_start, x_end, y_end)
                    pixels_length = ret.pixels_length

                raise Error(Error.STREAM_OUT_OF_SYNC,
                            'Pixels stream is out-of-sync')

        return pixels_data[:pixels_length]