Stefan Schuermans commited on 2017-05-26 17:35:57
Showing 4 changed files, with 83 additions and 15 deletions.
| ... | ... |
@@ -1,3 +1,5 @@ |
| 1 |
+import socket |
|
| 2 |
+ |
|
| 1 | 3 |
from distributor import Distributor |
| 2 | 4 |
from mapping import Mapping |
| 3 | 5 |
from msg import Msg, MsgDef |
| ... | ... |
@@ -20,6 +22,14 @@ class Display(object): |
| 20 | 22 |
# read config file |
| 21 | 23 |
if not self._proc_config_file(config_file): |
| 22 | 24 |
raise Exception("error(s) while reading config file")
|
| 25 |
+ # create and bind socket |
|
| 26 |
+ self._socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) |
|
| 27 |
+ self._socket.setblocking(False) |
|
| 28 |
+ self._socket.bind(self._bind_addr) |
|
| 29 |
+ |
|
| 30 |
+ def close(self): |
|
| 31 |
+ """close display""" |
|
| 32 |
+ self._socket.close() |
|
| 23 | 33 |
|
| 24 | 34 |
def get_size(self): |
| 25 | 35 |
"""get size of display as (width, height) in pixels""" |
| ... | ... |
@@ -27,18 +37,18 @@ class Display(object): |
| 27 | 37 |
|
| 28 | 38 |
def data_clear(self): |
| 29 | 39 |
"""clear image data, i.e. set entire image to black""" |
| 30 |
- # TODO |
|
| 31 |
- pass |
|
| 40 |
+ for distri in self._distris.values(): |
|
| 41 |
+ distri.data_clear() |
|
| 32 | 42 |
|
| 33 |
- def data_set(self, TODO): |
|
| 43 |
+ def data_image(self, image): |
|
| 34 | 44 |
"""set image data""" |
| 35 |
- # TODO |
|
| 36 |
- pass |
|
| 45 |
+ for distri in self._distris.values(): |
|
| 46 |
+ distri.data_image(image) |
|
| 37 | 47 |
|
| 38 | 48 |
def send(self): |
| 39 |
- """send image data to distributors""" |
|
| 40 |
- # TODO |
|
| 41 |
- pass |
|
| 49 |
+ """send image data to actual distributor modules using UDP""" |
|
| 50 |
+ for distri in self._distris.values(): |
|
| 51 |
+ distri.send(self._socket) |
|
| 42 | 52 |
|
| 43 | 53 |
def _proc_config_file(self, config_file): |
| 44 | 54 |
"""process config file |
| ... | ... |
@@ -1,3 +1,6 @@ |
| 1 |
+import socket |
|
| 2 |
+import struct |
|
| 3 |
+ |
|
| 1 | 4 |
from mapping import Mapping |
| 2 | 5 |
|
| 3 | 6 |
|
| ... | ... |
@@ -19,6 +22,11 @@ class Distributor(object): |
| 19 | 22 |
self._mappings.append(Mapping()) |
| 20 | 23 |
# pixel coordinates: all unknown |
| 21 | 24 |
self._pixel_coords = [[None] * self._pixels] * self._outputs |
| 25 |
+ # header for UDP packets |
|
| 26 |
+ self._udp_hdr = struct.pack("!I4H", 0x23542666,
|
|
| 27 |
+ outputs, pixels, Mapping.CHANNELS, 255) |
|
| 28 |
+ # initial image data is cleared |
|
| 29 |
+ self.data_clear() |
|
| 22 | 30 |
|
| 23 | 31 |
def check_output_no(self, output_no): |
| 24 | 32 |
"""check output number, return True if okay, False if not okay""" |
| ... | ... |
@@ -36,6 +44,35 @@ class Distributor(object): |
| 36 | 44 |
"""set distributor address""" |
| 37 | 45 |
self._addr = addr |
| 38 | 46 |
|
| 47 |
+ def data_clear(self): |
|
| 48 |
+ """clear image data, i.e. set entire image to black""" |
|
| 49 |
+ # prepare message buffer with all pixels cleared (black) |
|
| 50 |
+ clr = "".join([self._mappings[channel].table[0] |
|
| 51 |
+ for channel in range(Mapping.CHANNELS)]) |
|
| 52 |
+ self._buffer = self._udp_hdr + (clr * (self._outputs * self._pixels)) |
|
| 53 |
+ |
|
| 54 |
+ def data_image(self, image): |
|
| 55 |
+ """set image data""" |
|
| 56 |
+ # collect pixels from image and assemble message in buffer |
|
| 57 |
+ clr = [0] * Mapping.CHANNELS |
|
| 58 |
+ data = [] |
|
| 59 |
+ for output_pixel_coords in self._pixel_coords: |
|
| 60 |
+ for pixel_coord in output_pixel_coords: |
|
| 61 |
+ if pixel_coord is None: |
|
| 62 |
+ pix = clr |
|
| 63 |
+ else: |
|
| 64 |
+ pix = (128, 128, 0) # TODO |
|
| 65 |
+ data += [self._mappings[channel].table[pix[channel]] |
|
| 66 |
+ for channel in range(Mapping.CHANNELS)] |
|
| 67 |
+ self._buffer = self._udp_hdr + "".join(data) |
|
| 68 |
+ |
|
| 69 |
+ def send(self, socket): |
|
| 70 |
+ """send image data to actual distributor module using UDP""" |
|
| 71 |
+ try: |
|
| 72 |
+ socket.sendto(self._buffer, self._addr) |
|
| 73 |
+ except: |
|
| 74 |
+ pass |
|
| 75 |
+ |
|
| 39 | 76 |
def set_pixel_coords(self, output_no, pixel_coords): |
| 40 | 77 |
"""set distributor address |
| 41 | 78 |
output_no: number of output |
| ... | ... |
@@ -1,6 +1,8 @@ |
| 1 | 1 |
#! /usr/bin/env python |
| 2 | 2 |
|
| 3 | 3 |
import sys |
| 4 |
+import time |
|
| 5 |
+ |
|
| 4 | 6 |
import pyetherpix |
| 5 | 7 |
|
| 6 | 8 |
|
| ... | ... |
@@ -10,6 +12,20 @@ def main(argv): |
| 10 | 12 |
return 2 |
| 11 | 13 |
config_file = argv[1] |
| 12 | 14 |
display = pyetherpix.Display(config_file) |
| 15 |
+ (width, height) = display.get_size() |
|
| 16 |
+ print "width %u, height %u" % (width, height) |
|
| 17 |
+ print "blink" |
|
| 18 |
+ for i in range(5): |
|
| 19 |
+ print "on" |
|
| 20 |
+ display.data_image("ON") # TODO
|
|
| 21 |
+ display.send() |
|
| 22 |
+ time.sleep(0.5) |
|
| 23 |
+ print "off" |
|
| 24 |
+ display.data_clear() |
|
| 25 |
+ display.send() |
|
| 26 |
+ time.sleep(0.5) |
|
| 27 |
+ print "done" |
|
| 28 |
+ display.close() |
|
| 13 | 29 |
return 0 |
| 14 | 30 |
|
| 15 | 31 |
|
| ... | ... |
@@ -1,3 +1,6 @@ |
| 1 |
+from struct import Struct |
|
| 2 |
+ |
|
| 3 |
+ |
|
| 1 | 4 |
class Mapping(object): |
| 2 | 5 |
|
| 3 | 6 |
RED = 0 |
| ... | ... |
@@ -23,14 +26,16 @@ class Mapping(object): |
| 23 | 26 |
"""pre-compute mapping table""" |
| 24 | 27 |
# display_value := base + factor * input_value ^ (1 / gamma) |
| 25 | 28 |
gamma_1 = 1.0 / self._gamma |
| 29 |
+ s = Struct("!B")
|
|
| 26 | 30 |
tab = [] |
| 27 | 31 |
for v in range(256): |
| 28 |
- val = self._base + self._factor * (v / 255.0) ** gamma_1 |
|
| 29 |
- if val < 0: |
|
| 30 |
- tab.append(0) |
|
| 31 |
- elif val > 1.0: |
|
| 32 |
- tab.append(255) |
|
| 32 |
+ display_val = self._base + self._factor * (v / 255.0) ** gamma_1 |
|
| 33 |
+ if display_val < 0: |
|
| 34 |
+ display_no = 0 |
|
| 35 |
+ elif display_val > 1.0: |
|
| 36 |
+ display_no = 255 |
|
| 33 | 37 |
else: |
| 34 |
- tab.append(int(round(val * 255.0))) |
|
| 35 |
- self._table = tuple(tab) |
|
| 38 |
+ display_no = int(round(display_val * 255.0)) |
|
| 39 |
+ tab.append(s.pack(display_no)) |
|
| 40 |
+ self.table = tuple(tab) |
|
| 36 | 41 |
|
| 37 | 42 |