Improve dynamic configuration
* Control framerate in the forwarder * The processing client can use a smaller framerate than the default/max * The processing client can send an image smaller than the full screen Known Bug: doesn't work if the width is smaller than the one of the screen * The default config is sent to the processing client by the server Sanity checks are made on the client configuration * Code Cleanupmaster
parent
8d371b95df
commit
9da3123796
|
@ -92,12 +92,10 @@ void loop() {
|
|||
if (startChar == '*') {
|
||||
unsigned int startAt = micros();
|
||||
unsigned int usecUntilFrameSync = 0;
|
||||
count = Serial.readBytes((char *)drawingMemory, sizeof(int) * ledsPerStrip*6);
|
||||
if (count >= sizeof(int) * ledsPerStrip*6) {
|
||||
count = Serial.readBytesUntil('#', (char *)drawingMemory, sizeof(int) * ledsPerStrip*6 + 1);
|
||||
digitalWrite(13, HIGH);
|
||||
leds.show();
|
||||
digitalWrite(13, LOW);
|
||||
}
|
||||
} else if (startChar >= 0) {
|
||||
// discard unknown characters
|
||||
}
|
||||
|
|
|
@ -1,13 +1,4 @@
|
|||
Forwarder
|
||||
=========
|
||||
Both sides
|
||||
==========
|
||||
|
||||
* Control framerate in send function
|
||||
* Define a max framerate and announce it in the config (redis)
|
||||
* Remove commented code
|
||||
|
||||
Receiver
|
||||
========
|
||||
|
||||
* Listen on an other port to give the config to the client (H/W, max framerate)
|
||||
* Allow the user to set a lower framerate than the max one anounced by the forwarder
|
||||
* Remove debug code
|
||||
Support screen sizes > 1byte
|
||||
|
|
|
@ -5,22 +5,31 @@ import time
|
|||
from serial import Serial, SerialException
|
||||
import sys
|
||||
|
||||
height = 50
|
||||
width = 20
|
||||
max_height = 5
|
||||
max_width = 8
|
||||
max_framerate = 40
|
||||
|
||||
wait_time = None
|
||||
|
||||
|
||||
def update_framerate():
|
||||
global wait_time
|
||||
new_framerate = int(r.hget('config', 'cur_framerate'))
|
||||
if new_framerate >= max_framerate or new_framerate == 0:
|
||||
wait_time = 1.0 / max_framerate
|
||||
else:
|
||||
wait_time = 1.0 / new_framerate
|
||||
|
||||
|
||||
def send(r, s):
|
||||
print(r.llen('new'))
|
||||
data = r.rpop('new')
|
||||
if data is not None and len(data) > 0:
|
||||
a = bytes([ord('*')]) + bytearray(data)
|
||||
#la = len(a)
|
||||
now = time.time()
|
||||
end = now + wait_time
|
||||
a = bytes([ord('*')]) + bytearray(data) + bytes([ord('#')])
|
||||
s.write(a)
|
||||
#time.sleep(.05)
|
||||
#data = s.read(la)
|
||||
#print(data)
|
||||
# size = s.write(data)
|
||||
# print('Data sent ({} bytes)'.format(size))
|
||||
time.sleep(end - now)
|
||||
|
||||
|
||||
def serialConfigure(port_name, baudrate=9600):
|
||||
|
@ -38,7 +47,7 @@ def serialConfigure(port_name, baudrate=9600):
|
|||
sys.stderr.write("Could not open serial port %s: %s\n" % (ser.portstr, e))
|
||||
return
|
||||
|
||||
ledsPerStrip = height * width
|
||||
ledsPerStrip = max_height * max_width
|
||||
print(ledsPerStrip)
|
||||
ser.write(ledsPerStrip.to_bytes(4, byteorder='little'))
|
||||
|
||||
|
@ -64,10 +73,16 @@ def serialDataConfigure(port_name, baudrate=115200):
|
|||
|
||||
if __name__ == "__main__":
|
||||
r = redis.Redis()
|
||||
r.hset('config', 'imgsize', height * width * 24)
|
||||
r.hset('config', 'height', max_height)
|
||||
r.hset('config', 'width', max_width)
|
||||
r.hset('config', 'imgsize', max_height * max_width * 24)
|
||||
r.hset('config', 'max_framerate', max_framerate)
|
||||
r.hset('config', 'cur_framerate', max_framerate)
|
||||
s = serialConfigure('/dev/ttyACM0')
|
||||
# s_data = serialDataConfigure('/dev/ttyUSB0')
|
||||
wait_time = 1.0 / max_framerate
|
||||
while True:
|
||||
while r.llen('new') > 0:
|
||||
send(r, s)
|
||||
time.sleep(1)
|
||||
update_framerate()
|
||||
|
|
|
@ -13,16 +13,51 @@ class MyTCPHandler(socketserver.BaseRequestHandler):
|
|||
client.
|
||||
"""
|
||||
|
||||
def get_config(self):
|
||||
def _get_config(self):
|
||||
self.max_height = int(self.r.hget('config', 'height'))
|
||||
self.max_width = int(self.r.hget('config', 'width'))
|
||||
self.max_framerate = int(self.r.hget('config', 'max_framerate'))
|
||||
self.cur_framerate = int(self.r.hget('config', 'cur_framerate'))
|
||||
self.imgsize = int(self.r.hget('config', 'imgsize'))
|
||||
|
||||
def _set_config(self, framerate, height, width):
|
||||
self.r.hset('config', 'cur_framerate', framerate)
|
||||
self.imgsize = height * width * 24
|
||||
|
||||
def _send_config_to_client(self):
|
||||
self.request.sendall(bytearray([self.max_height]))
|
||||
self.request.sendall(bytearray([self.max_width]))
|
||||
self.request.sendall(bytearray([self.max_framerate]))
|
||||
|
||||
def _receive_client_config(self):
|
||||
height = int.from_bytes(self.request.recv(1), byteorder='little')
|
||||
width = int.from_bytes(self.request.recv(1), byteorder='little')
|
||||
framerate = int.from_bytes(self.request.recv(1), byteorder='little')
|
||||
good, reason = self._check_config(height, width, framerate)
|
||||
if good:
|
||||
self._set_config(framerate, height, width)
|
||||
return good, reason
|
||||
|
||||
def _check_config(self, height, width, framerate):
|
||||
if height > 0 and height > self.max_height:
|
||||
return False, "height has to be between 0 and {}. Current: {}".format(self.max_height, height)
|
||||
if width > 0 and width > self.max_width:
|
||||
return False, "width has to be between 0 and {}. Current: {}".format(self.max_width, width)
|
||||
if framerate > 0 and framerate > self.max_framerate:
|
||||
return False, "framerate has to be between 0 and {}. Current: {}".format(self.max_framerate, framerate)
|
||||
return True, None
|
||||
|
||||
def handle(self):
|
||||
print('Start receiving from {}...'.format(self.client_address[0]))
|
||||
self.r = redis.Redis()
|
||||
self.get_config()
|
||||
self._get_config()
|
||||
self._send_config_to_client()
|
||||
good, reason = self._receive_client_config()
|
||||
if not good:
|
||||
print(reason)
|
||||
return None
|
||||
print('Start receiving from {}...'.format(self.client_address[0]))
|
||||
while True:
|
||||
data = self.request.recv(self.imgsize)
|
||||
print(len(data))
|
||||
self.r.lpush('new', data)
|
||||
if len(data) == 0:
|
||||
break
|
||||
|
|
|
@ -1,11 +1,17 @@
|
|||
add_library('net')
|
||||
import math
|
||||
import jarray
|
||||
import time
|
||||
import struct
|
||||
|
||||
# Config, will be checked upstream
|
||||
height = 5
|
||||
width = 8
|
||||
framerate = 30
|
||||
#####################################
|
||||
|
||||
gamma = 1.7
|
||||
brightness = 4
|
||||
errorCount = 0
|
||||
framerate = 30
|
||||
dimension = 0
|
||||
|
||||
# TODO: test with real serial
|
||||
|
@ -58,22 +64,53 @@ def colorWiring(c):
|
|||
|
||||
def send_TCP():
|
||||
image2data(data)
|
||||
#println(data)
|
||||
ledTCP.write(data)
|
||||
|
||||
def prepare_data():
|
||||
global data
|
||||
data = jarray.zeros(dimension * 24, "b")
|
||||
|
||||
def receive_config():
|
||||
max_height = jarray.zeros(1, "b")
|
||||
max_width = jarray.zeros(1, "b")
|
||||
max_framerate = jarray.zeros(1, "b")
|
||||
while True:
|
||||
available_bytes = ledTCP.available()
|
||||
if available_bytes > 0:
|
||||
break
|
||||
time.sleep(1)
|
||||
ledTCP.readBytes(max_height)
|
||||
ledTCP.readBytes(max_width)
|
||||
ledTCP.readBytes(max_framerate)
|
||||
return max_height[0], max_width[0], max_framerate[0]
|
||||
|
||||
def check_config(max_height, max_width, max_framerate):
|
||||
if height > max_height:
|
||||
return False, "height cannot be higher than {}".format(max_height)
|
||||
if width > max_width:
|
||||
return False, "width cannot be higher than {}".format(max_width)
|
||||
if framerate > max_framerate:
|
||||
return False, "framerate cannot be higher than {}".format(max_framerate)
|
||||
return True, None
|
||||
|
||||
def send_config():
|
||||
ledTCP.write(height)
|
||||
ledTCP.write(width)
|
||||
ledTCP.write(framerate)
|
||||
|
||||
def setup():
|
||||
global gammatable
|
||||
global dimension
|
||||
size(50, 30)
|
||||
TCPConfigure("127.0.0.1", 9999)
|
||||
max_height, max_width, max_framerate = receive_config()
|
||||
|
||||
good, reason = check_config(max_height, max_width, max_framerate)
|
||||
if not good:
|
||||
raise Exception(reason)
|
||||
send_config()
|
||||
size(width, height)
|
||||
dimension = width * height
|
||||
frameRate(framerate)
|
||||
TCPConfigure("127.0.0.1", 9999)
|
||||
if (errorCount > 0):
|
||||
exit()
|
||||
gammatable = [int((math.pow(i / 255.0, gamma) * 255.0 + 0.5) * brightness) for i in range(0, 256)]
|
||||
prepare_data()
|
||||
loadPixels()
|
||||
|
|
|
@ -1,4 +1,2 @@
|
|||
* Get config (H/W and max framerate) from the config server
|
||||
* Set current framerate (lower than max), ad send it to the config server
|
||||
* Optimize the datastream generator
|
||||
* Split the processing code (setup & dray) from the datastreem generator => library
|
||||
|
|
Loading…
Reference in New Issue