diff --git a/clients/cellular.py b/clients/cellular.py index 2fd5825..683dd84 100644 --- a/clients/cellular.py +++ b/clients/cellular.py @@ -12,7 +12,7 @@ local_port = 5001 # UDP webserver port to bypass frameserver for testing remote_port = 4422 # port to frameserver -#remote_port = 4321 +remote_port = 4321 # TODO: autodetect interface address for remote application outgoing_if = "127.0.0.1" @@ -56,6 +56,9 @@ frequency = 1000 / sleeptime # frames per second # function resets map to zero def set_wdata(r, g, b): + global wdata + wdata = [] + for x in xrange(width): wdata.append([0] * height) for y in xrange(height): @@ -80,6 +83,21 @@ def i2c(rgba): # ignore rgba[0] because it is the state return chr(int(rgba[1])) + chr(int(rgba[2])) + chr(int(rgba[3])) + chr(int(rgba[4])) +# determine if a cells neighbour is active (any will do) +def has_active_neighb(x, y): + # check the cell to the left + if x > 0 and wdata[x - 1][y][0] > 0: + return True + # check the cell above + if y > 0 and wdata[x][y - 1][0] > 0: + return True + # check the cell to the right + if x < (width - 1) and wdata[x + 1][y][0] > 0: + return True + # check the cell below + if y < (height - 1) and wdata[x][y + 1][0] > 0: + return True + # function sends wdata and sdata state to server def send_update(): #zero out the data buffer @@ -105,101 +123,75 @@ def send_update(): # send the data packet to remote host UDPSock.sendto(data,(remote_host,remote_port)) -# initialize map -set_wdata(67,67,67) -set_sdata(0,0,255) +# main loop +while True: + # reset/initialize map + set_wdata(67,67,67) + set_sdata(255,255,255) -# set start seed -# get random location -rx = randint(0, width - 1) -ry = randint(0, height - 1) -wdata[rx][ry] = [1,1,0,0,1] -print "origin(" + str(rx) + "," + str(ry) + ")" - -def has_active_neighb(x, y): - # check the cell to the left - if x > 0 and wdata[x - 1][y][0] > 0: - return True - # check the cell above - if y > 0 and wdata[x][y - 1][0] > 0: - return True - # check the cell to the right - if x < (width - 1) and wdata[x + 1][y][0] > 0: - return True - # check the cell below - if y < (height - 1) and wdata[x][y + 1][0] > 0: - return True - -# main logic loop -for t in range(60): - - # push update to clients - send_update() - - # create CA buffer - data_buffer = deepcopy(wdata) - - for y in xrange(height): - for x in xrange(width): - # if cell is active, increase its rating/value - if wdata[x][y][0] > 0: - # change the state of the cell - data_buffer[x][y][0] += 10 - - # assign stat to red colour - data_buffer[x][y][1] = data_buffer[x][y][0] - - # check we don't go too high - if data_buffer[x][y][0] > 127: - data_buffer[x][y][1] = 127 - # assign stat to green colour - data_buffer[x][y][2] = data_buffer[x][y][0] - 127 - - if data_buffer[x][y][0] > 255: - data_buffer[x][y][2] = 127 - # assign stat to blue colour - data_buffer[x][y][3] = data_buffer[x][y][0] - 255 - - if data_buffer[x][y][0] > 383: - data_buffer[x][y][3] = 127 - - set_sdata(0,0,0) - # E - sdata[0][0] = [0,255,0,0,1] - sdata[0][3] = [0,255,0,0,1] - sdata[0][4] = [0,255,0,0,1] - sdata[0][5] = [0,255,0,0,1] - sdata[0][6] = [0,255,0,0,1] - # N - sdata[1][2] = [0,255,0,0,1] - sdata[1][4] = [0,255,0,0,1] - sdata[1][5] = [0,255,0,0,1] - sdata[1][6] = [0,255,0,0,1] - # D - sdata[2][1] = [0,255,0,0,1] - sdata[2][2] = [0,255,0,0,1] - sdata[2][3] = [0,255,0,0,1] - sdata[2][4] = [0,255,0,0,1] - sdata[2][6] = [0,255,0,0,1] - - send_update() - exit() + # set start seed + # get random location + rx = randint(0, width - 1) + ry = randint(0, height - 1) + wdata[rx][ry] = [1,1,0,0,1] + # print "origin(" + str(rx) + "," + str(ry) + ")" + # main logic loop + for t in range(23): + + # push update to clients + send_update() - # if not active, check if adjacent cell is active - if wdata[x][y][0] == 0 and has_active_neighb(x, y): - # activate and colour - data_buffer[x][y][0] = 1 - data_buffer[x][y][1] = 1 - data_buffer[x][y][2] = 0 - data_buffer[x][y][3] = 0 + # create CA buffer + data_buffer = deepcopy(wdata) + + for y in xrange(height): + for x in xrange(width): + # if cell is active, increase its rating/value + if wdata[x][y][0] > 0: + # change the state of the cell + data_buffer[x][y][0] += 16 + + # assign stat to red colour + data_buffer[x][y][1] = data_buffer[x][y][0] + + # check we don't go too high + # if the state is over 127, reset red + if data_buffer[x][y][0] > 127: + # assign max stat to red colour + data_buffer[x][y][1] = 0 + # assign stat to green colour + data_buffer[x][y][2] = data_buffer[x][y][0] - 128 + + # if the state is over 128*2, reset green + if data_buffer[x][y][0] > 255: + # assign max stat to green colour + data_buffer[x][y][2] = 0 + # assign stat to blue colour + data_buffer[x][y][3] = data_buffer[x][y][0] - 255 + + # if the state is over 128*3, reset blue + if data_buffer[x][y][0] > 383: + data_buffer[x][y][3] = data_buffer[x][y][0]%128 + + # if not active, check if adjacent cell is active + if wdata[x][y][0] == 0 and has_active_neighb(x, y): + # activate and colour + data_buffer[x][y][0] = 1 + data_buffer[x][y][1] = 1 + data_buffer[x][y][2] = 0 + data_buffer[x][y][3] = 0 - # set wdata to new buffer - wdata = data_buffer + # set wdata to new buffer + wdata = data_buffer - # wait to paint process next frame - time.sleep(sleeptime/1000.0) + # wait to paint process next frame + time.sleep(sleeptime/1000.0) + + # end of iteration, restart + + # end of main animation loop # close socket UDPSock.close() diff --git a/clients/plasma.py b/clients/plasma.py index 455cb86..2120f41 100644 --- a/clients/plasma.py +++ b/clients/plasma.py @@ -27,8 +27,6 @@ UDPSock.bind((outgoing_if, local_port)) # goes down or refuses connection #UDPSock.connect((remote_host, remote_port)) -segmentsfile = open('segments','r') - hash = "s2l\n<8<18 " # 10 bytes alpha = chr(255) diff --git a/clients/s2llib.py b/clients/s2llib.py new file mode 100644 index 0000000..c562a81 --- /dev/null +++ b/clients/s2llib.py @@ -0,0 +1,99 @@ +# s2llib.py +# Python utility functions for syndelights + +from socket import * +import sys, time +#from copy import deepcopy + +class syndelights_canvas: + """Holds the state of the canvas to be sent""" + segments_in_window = 8 + + def __init__(self, hpc, zb, w, h, seg_wins, hs, hsp, ts, tsp, deblvl): + # get hash passcode and z-buffer depth + self.hash_passcode = hpc + self.zed_buffer = zb + + # main window dimensions + self.width = w + self.height = h + + # number of windows with segment displays + self.segmented_windows_num = seg_wins + + # set servers and ports + self.host_server = hs + self.host_server_port = hsp + self.target_server = ts + self.target_server_port = tsp + + # debugging + self.debug_level = deblvl + + # make data structures for windows and segments + self.reset_windows(0,127,127,127, 255) + self.reset_segment_windows(0, 127, 127, 127, 255) + + + def reset_windows(self, state, red, green, blue, alpha): + self.window_data = [] + for y in xrange(self.height): + self.window_data.append([0] * self.width) + for x in xrange(self.width): + self.window_data[y][x] = dict(s=state, r=red, g=green, b=blue, a=alpha) + + def reset_segment_windows(self, state, red, green, blue, alpha): + self.segmented_windows = [] + for w in xrange(self.segmented_windows_num): + self.segmented_windows.append([0] * self.segments_in_window) + for s in xrange(self.segments_in_window): + self.segmented_windows[w][s] = dict(s=state, r=red, g=green, b=blue, a=alpha) + + # convert [r, g, b, a] into a 4 character string + def int2chr(self, rgba_dict): + return chr(int(rgba_dict["r"])) + chr(int(rgba_dict["g"])) + chr(int(rgba_dict["b"])) + chr(int(rgba_dict["a"])) + + # draw the data object, send it to the target server + def draw(self): + # prep header with hash, z-buffer and new line (12 bytes) + data = self.hash_passcode + chr(self.zed_buffer) + "\n" + + # package window data + for y in xrange(self.height): + for x in xrange(self.width): + data = data + self.int2chr( self.window_data[y][x] ) + data = data + "\n" + + # package segment data + for w in xrange(self.segmented_windows_num): + for s in xrange(self.segments_in_window): + data = data + self.int2chr( self.segmented_windows[w][s] ) + data = data + "\n" + + if self.debug_level > 2: + print data + + # send the data through UDP to remote server + self.UDPSock.sendto(data, (self.target_server, self.target_server_port)) + + def setwin_xy_srgba_array(self, x, y, srgba): + self.window_data[y][x] = dict(s=srgba[0], r=srgba[1], g=srgba[2], b=srgba[3], a=srgba[4]) + + def setwin_xy_sval(self, x, y, col, val): + if col == 's': + self.window_data[y][x]['s'] = val + if col == 'r': + self.window_data[y][x]['r'] = val + if col == 'g': + self.window_data[y][x]['r'] = val + if col == 'b': + self.window_data[y][x]['r'] = val + if col == 'a': + self.window_data[y][x]['r'] = val + + def connect(self): + self.UDPSock = socket(AF_INET, SOCK_DGRAM) + self.UDPSock.bind((self.host_server, self.host_server_port)) + + def disconnect(self): + self.UDPSock.close() diff --git a/clients/test.py b/clients/test.py new file mode 100644 index 0000000..877fc60 --- /dev/null +++ b/clients/test.py @@ -0,0 +1,22 @@ +from s2llib import * +import time + +width = 12 +height = 8 + +test = syndelights_canvas("s2l\n<8<18 ", 1, width, height, width, "127.0.0.1", 5001, "127.0.0.1", 4422, 3) +test = syndelights_canvas("s2l\n<8<18 ", 1, width, height, width, "127.0.0.1", 5001, "127.0.0.1", 4321, 3) + +test.connect() +test.reset_windows(0, 0, 0, 0, 127) +test.reset_segment_windows(0, 62, 62, 62, 63) + + +for y in xrange(height): + for x in xrange(width): + test.setwin_xy_srgba_array(x, y, [0, 255, 0, 0, 127]) + test.draw() + time.sleep(0.5) + test.setwin_xy_srgba_array(x, y, [0, 0, 0, 0, 127]) + +test.disconnect() diff --git a/frameserver/Server.cpp b/frameserver/Server.cpp index 1377638..659e331 100644 --- a/frameserver/Server.cpp +++ b/frameserver/Server.cpp @@ -173,7 +173,7 @@ void Server::listen() void Server::send() { - const int length = 12 + HEIGHT*(WIDTH*CHANNELS+1) + SEGWIDTH*(SEGNUM*SEGCHANNELS+1); + const int length = HEADEROFFSET + HEIGHT*(WIDTH*CHANNELS+1) + SEGWIDTH*(SEGNUM*SEGCHANNELS+1); static char data[length]; while(1) @@ -188,10 +188,10 @@ void Server::send() { for(int k = 0; k < CHANNELS; k++) { - data[i*(WIDTH*CHANNELS+1) + j*CHANNELS + k] = frame.windows[i][j][k]; + data[HEADEROFFSET + i*(WIDTH*CHANNELS+1) + j*CHANNELS + k] = frame.windows[i][j][k]; } } - data[i*(WIDTH*CHANNELS+1) + (WIDTH*CHANNELS)] = '\n'; + data[HEADEROFFSET + i*(WIDTH*CHANNELS+1) + (WIDTH*CHANNELS)] = '\n'; } for(int i = 0; i < SEGWIDTH; i++) @@ -200,11 +200,11 @@ void Server::send() { for(int k = 0; k < SEGCHANNELS; k++) { - data[HEIGHT*(WIDTH*CHANNELS+1) + + data[HEADEROFFSET + HEIGHT*(WIDTH*CHANNELS+1) + i*(SEGNUM*SEGCHANNELS+1) + j*SEGCHANNELS + k] = frame.segments[i][j][k]; } } - data[HEIGHT*(WIDTH*CHANNELS+1) + + data[HEADEROFFSET + HEIGHT*(WIDTH*CHANNELS+1) + i*(SEGNUM*SEGCHANNELS+1) + (SEGNUM*SEGCHANNELS)] = '\n'; } }