Source code for bibliopixel.drivers.driver_base

from . channel_order import ChannelOrder
from .. colors import gamma as _gamma
from .. project import attributes, clock, data_maker, fields
import threading, time


[docs]class DriverBase(object): """ Base driver class to build other drivers from. :param int num: Number of total pixels held by this driver :param int width: Width of matrix, for use with :py:class:`bibliopixel.layout.matrix.Matrix` :param int height: Height of matrix, for use with :py:class:`bibliopixel.layout.matrix.Matrix` :param str c_order: Color channel order :param gamma: Gamma correction table. Preset tables available in :py:mod:`bibliopixel.colors.gamma` """ # If set_device_brightness is not empty, it's a method that allows you # to directly set the brightness for the device. # # If it is empty, then the brightness is used as a scale factor in rendering # the pixels. set_device_brightness = None pre_recursion = fields.default_converter
[docs] @classmethod def construct(cls, project, **desc): """Construct a driver from a project and a description.""" return cls(maker=project.maker, **desc)
def __init__(self, num=0, width=0, height=0, c_order="RGB", gamma=None, maker=data_maker.MAKER, **kwds): attributes.set_reserved(self, 'driver', **kwds) if num == 0: num = width * height if num == 0: raise ValueError("Either num, or width and height are needed!") self.numLEDs = num gamma = gamma or _gamma.DEFAULT self.gamma = gamma if isinstance(c_order, str): c_order = ChannelOrder.make(c_order) self.c_order = c_order self.perm = ChannelOrder.ORDERS.index(c_order) self.pixel_positions = None self.width = width self.height = height self.maker = maker self._buf = self._make_buffer() self.lastUpdate = 0 self.brightness_lock = threading.Lock() self._brightness = 255 self._waiting_brightness = None self.clock = clock.Clock()
[docs] def set_pixel_positions(self, pixel_positions): """ Internal Use Only Placeholder callback for sending physical pixel layout data to the ``SimPixel`` driver. """ pass
[docs] def set_colors(self, colors, pos): """ Use with caution! Directly set the pixel buffers. :param colors: A list of color tuples :param int pos: Position in color list to begin set operation. """ self._colors = colors self._pos = pos end = self._pos + self.numLEDs if end > len(self._colors): raise ValueError('Needed %d colors but found %d' % ( end, len(self._colors)))
[docs] def set_project(self, project): self.clock = project.clock
[docs] def start(self): """ Called right before this driver will run. This is the place to do things like start threads, not in the constructor. """
[docs] def stop(self): """ Called to request any threads or resources to shut down. """
[docs] def cleanup(self): """ Called to shut this driver down, and stop all threads and processes. """
[docs] def join(self, timeout=None): """ Called to join threads. """
[docs] def bufByteCount(self): """ Total number of bytes that the pixel buffer represents. Mainly used for drivers such as :py:mod:`bibliopixel.drivers.serial` and :py:mod:`.network` """ return 3 * self.numLEDs
[docs] def sync(self): """ The sync() method is called after the entire frame has been sent to the device to indicate that it may now be displayed. This is particularly useful when there are multiple drivers comprising one display which all need to display the next frame at exactly the same time. """
def _compute_packet(self): """Compute the packet from the colors and position. Eventually, this will run on the compute thread. """ def _send_packet(self): """Send the packet to the driver. Eventually, this will run on an I/O thread. """
[docs] def update_colors(self): """Apply any corrections to the current color list and send the results to the driver output. This function primarily provided as a wrapper for each driver's implementation of :py:func:`_compute_packet` and :py:func:`_send_packet`. """ start = self.clock.time() with self.brightness_lock: # Swap in a new brightness. brightness, self._waiting_brightness = ( self._waiting_brightness, None) if brightness is not None: self._brightness = brightness if self.set_device_brightness: self.set_device_brightness(brightness) self._compute_packet() self._send_packet() self.lastUpdate = self.clock.time() - start
[docs] def set_brightness(self, brightness): """Set the global brightness for this driver's output. :param int brightness: 0-255 value representing the desired brightness level """ with self.brightness_lock: self._waiting_brightness = brightness
def _render(self): """Typically called from :py:func:`_compute_packet` this applies brightness and gamma correction to the pixels controlled by this driver. """ if self.set_device_brightness: level = 1.0 else: level = self._brightness / 255.0 gam, (r, g, b) = self.gamma.get, self.c_order for i in range(min(self.numLEDs, len(self._buf) / 3)): c = [int(level * x) for x in self._colors[i + self._pos]] self._buf[i * 3:(i + 1) * 3] = gam(c[r]), gam(c[g]), gam(c[b]) def _make_buffer(self): return self.maker.bytes(self.bufByteCount())