diff --git a/output_module/read_values.py b/output_module/read_values.py new file mode 100644 index 0000000..1680794 --- /dev/null +++ b/output_module/read_values.py @@ -0,0 +1,174 @@ +# read the values from ESP32 and call functions to generate ps-file: +import serial # import serial library to read the values from ESP32 via serial (RX) connection +import os # library to use bash commands + +#LED connect to GND and pin 23 +import RPi.GPIO as GPIO # GPIO pins +import time +import logging +#logging gives information for debugging purposes +logging.getLogger().setLevel(5) + + + +from print_button import print_button +from preview_button import preview_button +from friction_label import friction_label +from future_relics import future_relics +from weaver import weaver +from whoosh import whoosh +from dynamic_glyph import dynamic_glyph +from print_or_preview import preview_output, print_output + +function_index = { +"FL": friction_label, +"FR": future_relics, +"WV": weaver, +"WH": whoosh, +"DG": dynamic_glyph +} + +module_index = { +"FL": "friction_label", +"FR": "future_relics", +"WV": "weaver", +"WH": "whoosh", +"DG": "dynamic_glyph" +} + + +#LED +GPIO.setmode(GPIO.BOARD) #Use the physical board number (not GPIO numbering) +GPIO.setup(23, GPIO.OUT, initial=GPIO.LOW) # Set pin 23 to be an output pin and set initial value to low (off) +GPIO.setwarnings(False) #Ignore warnings + + +preview_button_count = 0 + + + +if __name__ == '__main__': + ser = serial.Serial('/dev/ttyS0', 9600, timeout=0.1) # establish a serial connection using Serial Pi Zero (S0), using the RX pin + ser.reset_input_buffer() + + try: + while True: + #for some reason the whole ED setup has to be repeated here: + GPIO.setmode(GPIO.BOARD) #Use the physical board number (not GPIO numbering + GPIO.setup(23, GPIO.OUT, initial=GPIO.LOW) # Set pin 23 to be an output pin and set initial value to low (off) + GPIO.output(23, GPIO.LOW) + + if ser.in_waiting > 0: + print(ser.in_waiting) + #the longer serial data is received, the bigger the data in the buffer + #set a max amount of buffer data, then reset the buffer: + if ser.in_waiting > 400: + ser.reset_input_buffer() + GPIO.output(23, GPIO.HIGH) # Turn on while serial data is incoming + + line = ser.readline() # reads bytes + class theEnd(Exception): pass #defines an exception for the following try (in case, it is executed at the end). + try: + line = line.decode("utf-8", 'ignore').rstrip() # converts bytes to string + line = line.replace("\r\n", "") # replaces "\r\n" (end of line) with nothing + line = line.replace("\r", "") # replaces "\r" (between two modules) with nothing + #print(line) + if not line.startswith("&&&") and not line.endswith("&&&"): # break when line of data is not complete + #print(line) + #print("break") + break + line = line.replace("&&&", "") # delete all &&& + line = line.split("#") # splits the line into a list of lists + # after this split the list begins with an empty list, so delete it: + if line[0] == "": #if first list in lists is empty: + del line[0] #delete the first element + # print(line) + modules = [] + for module in line: + values = module.split(",") # splits each module into values + modules.append(values) + print("These are the values of all connected modules ") + print(modules) + + #for each module: check if all values are being received, if not jump to theEnd execption at the end of this code + for module in modules: + if module[0] == "FL" and len(module) != 9: + raise theEnd + if module[0] == "FR" and len(module) != 6: + raise theEnd + if module[0] == "WV" and len(module) != 6: + raise theEnd + if module[0] == "WH" and len(module) != 10: + raise theEnd + if module[0] == "DG" and len(module) != 2: + raise theEnd + #ser.reset_input_buffer() + + + + if preview_button() == True: + + #increase the preview button count to know if it is a preview start or a preview refresh + preview_button_count = preview_button_count + 1 + + previous_module = "" #define previous_module as non-existent + + for module in modules: #for each module inside the list of modules + if module[0] not in module_index: #this if break is added to avoid the script from breaking at the start (which happens when serial is not yet receiving all values, but only fragments) + # print("break") + break # break and start the for loop again + + current_module = module_index[module[0]] #save the name of the current module, use module_index to replace abbr. with full nam + function_index[module[0]](previous_module, current_module, module) #use function_index to run functions for each module #example: weaver(previous_module, current_module, module) + previous_module = current_module #previous_module is now redefined, bacause current_module becomes previous_module + + if module == modules[-1]: #if module is the last module in list of modules + last_module = current_module + preview_output(preview_button_count, last_module) #call preview function + + #delete text from text file that was written by dynamic glyph module + open('dynamic_glyph.txt', 'w').close() + + + + + + if print_button() == True: + + previous_module = "" #define previous_module as non-existent + + for module in modules: #for each module inside the list of modules + if module[0] not in module_index: #this if break is added to avoid the script from breaking at the start (which happens when serial is not yet receiving all values, but only fragments) + # print("break") + break # break and start the for loop again + + current_module = module_index[module[0]] #save the name of the current module, use module_index to replace abbr. with full name + function_index[module[0]](previous_module, current_module, module) #use function_index to run functions for each module #example: weaver(previous_module, current_module, module) + previous_module = current_module #previous_module is now redefined, bacause current_module becomes previous_module + + if module == modules[-1]: #if module is the last module in list of modules + last_module = current_module #define current_module as last module to know what file to send to the preview/printer + print_output(last_module) #call print function + + #delete text from text file that was written by dynamic glyph module + open('dynamic_glyph.txt', 'w').close() + + #ser.flush() + + + except theEnd: + print("error reading") #prints error if serial does not receive all values of each module + + except OSError as e: + print("Error: could not decode bytes") + print(e) + + + #ser.flush() + + + except KeyboardInterrupt: #is the script is interrupted, turn the LED off + GPIO.output(23, GPIO.LOW) + +# finally: +# GPIO.cleanup() diff --git a/output_module/weaver.py b/output_module/weaver.py new file mode 100644 index 0000000..7b62c26 --- /dev/null +++ b/output_module/weaver.py @@ -0,0 +1,106 @@ +import re # libary to search and replace strings in the postscript file +from dictionary import font_index +from generate_postscript import generate_postscript + +# function with three arguments +def weaver(previous_module, current_module, module): + + patch1 = module[1] + patch2 = module[2] + patternFactor = int(module[3]) + patchFactor = int(module[4]) + patchworkFactor = int(module[5]) + + #replace a, b, c and d with characters I am using nowhere else + patch1 = patch1.replace("a", ("%"*patternFactor)) #∼ + patch1 = patch1.replace("b", ("$"*patternFactor)) #≈ + patch1 = patch1.replace("c", ("§"*patternFactor)) #≅ + patch1 = patch1.replace("d", ("#"*patternFactor)) #≡ + + patch2 = patch2.replace("a", ("%"*patternFactor)) #∼ + patch2 = patch2.replace("b", ("$"*patternFactor)) #≈ + patch2 = patch2.replace("c", ("§"*patternFactor)) #≅ + patch2 = patch2.replace("d", ("#"*patternFactor)) #≡ + + #print(patch1) + + patchwork = ((patch1*patchFactor) + (patch2*patchFactor)) *patchworkFactor + + text = '' + tmp_line = '' + charCount = 0 + lineCount = 0 + lineWidth = 15 + #lineNum = 100 ################################################################################# + for character in patchwork: + + if len(tmp_line) < lineWidth: + tmp_line += character + if len(patchwork) == charCount+1: + text = text + tmp_line + "\n" + else: + tmp_line += character + text = text + tmp_line + "\n" + tmp_line = '' + lineCount += 1 + if lineCount >= 10: #why cannot replace with lineNum?################################### + break + charCount += 1 + + #print(text) + + #split the text into lines to place them separated + text = text.split("\n") + paragraph = "" + for row in text: + paragraph = paragraph + "(" + row + ") true charpath newline-weaver " + + + #replace the character that I am using nowhere else with the number code of the special characters I want to use in the generate_postscript + #the backsplash needs two escapes (one in the replace operation and one later in the generate_postscript when it is written to the file) + paragraph = paragraph.replace("%", ("\\\\176"*patternFactor)) #∼ + paragraph = paragraph.replace("$", ("\\\\273"*patternFactor)) #≈ + paragraph = paragraph.replace("§", ("\\\\100"*patternFactor)) #≅ + paragraph = paragraph.replace("#", ("\\\\272"*patternFactor)) #≡ + + #print(paragraph) + + + script = """ + +newpath +% WEAVER + +/Symbol +% fontname + +16 selectfont +% fontsize in points, establishes the font as the current one + +/x-weaver { 5 } def +% define x position + +/y-weaver { 300 } def +% define y position + +/lg-weaver { 5 } def +% define linespacing + +/newline-weaver { y-weaver lg-weaver sub /y-weaver exch def x-weaver y-weaver moveto } def +% define newline (position of new line) by using subtracting linespacing (lg) from y position and define that as the new y position (exch-ange), finally move to x position and re-defined y position + +x-weaver y-weaver moveto +% x and y coordinates in px (origin is the lower-left corner of the page) + +"""+paragraph+""" + +fill +% fill the text in parentheses + +showpage +% print all on a page +""" + + + + generate_postscript(previous_module, current_module, script) # call function diff --git a/output_module/whoosh.py b/output_module/whoosh.py new file mode 100644 index 0000000..dd07529 --- /dev/null +++ b/output_module/whoosh.py @@ -0,0 +1,155 @@ +from random import choice +from random import randrange +import re # libary to search and replace strings in the postscript file +from dictionary import font_index +from generate_postscript import generate_postscript + + +# function with three arguments +def whoosh(previous_module, current_module, module): + + + font = font_index[module[1]] # use font_index from dictionary to translate the fontname + + paraA = int(module[2]) + paraB = int(module[3]) + paraC = int(module[4]) + paraD = int(module[5]) + paraE = int(module[6]) + paraF = int(module[7]) + paraG = int(module[8]) + + paraLine = int(module[9]) + + + #use text from text file that was written by dynamic glyph module + textFile=open("dynamic_glyph.txt", "rt") + textContent = textFile.read() + if textContent != "": #use content of text file to define text variable + textIn = textContent + text = text.replace("\n", "") + else: #if text file is emptpy: randomly pick a default text (in case keyboard module is not used) + defaultText = ["Modular Matter", "MODULAR MATTER", "Rewire your prints!", "REWIRE YOUR PRINTS!"] + textIn = choice(defaultText) + + + + words = textIn.split(" ") + textOut = "" + firstWords = "" + mashWords = "" + patchWords = "" + + #add to output: original text + origin = textIn + "\n" + textOut += origin + + #add to output: pyramid with the first two words of the text (or the first word only) + #paraA and paraB + for x in range(1, paraA+1): + for y in range(1, paraB+1): + if len(words) >= 2: + firstWords = ((words[0]+" ")*x) + ((words[1] +" ")*y) + textOut += firstWords + "\n" + else: + firstWords = (words[0]+" ")*x*y + textOut += firstWords + "\n" + + #add to output: original text + textOut += origin + + + #add to output: each round a new line with added random word + #paraC + for z in range(1, paraC+1): + mashWords += choice(words) + " " + textOut += mashWords + "\n" + + + #add to output: each round the original text + random number of spaces + #paraD and paraE + for q in range(1, paraD+1): + textOut += origin + textOut += ' ' * randrange(paraE) + + + #add to output: each round the last word of the original text + #paraF + for s in range(1, paraF+1): + lastWord = (words[-1]+" ") + textOut += lastWord + "\n" + + #add to output: each round a new line with 3 added random words + #paraG + for r in range(1, paraG+1): + patchWords += choice(words) + " " + choice(words) + " " + choice(words) + " " + textOut += patchWords + "\n" + + + text = '' + tmp_line = '' + count = 0 + for character in textOut: + + if len(tmp_line) < paraLine: + tmp_line += character + if len(textOut) == count+1: + text = text + tmp_line + "\n" + else: + tmp_line += character + text = text + tmp_line + "\n" + tmp_line = '' + count += 1 + + #print(text) + #return text + + #print(textOut) + #return textOut + + #split the text into lines to place them separated + text = text.split("\n") + paragraph = "" + for row in text: + paragraph = paragraph + "(" + row + ") true charpath newline-whoosh " + + + + script = """ + +newpath +% WHOOSH + +/"""+font+""" +% fontname + +14 selectfont +% fontsize in points, establishes the font as the current one + +/x-whoosh { 5 } def +% define x position + +/y-whoosh { 100 } def +% define y position + +/lg-whoosh { 17 } def +% define linespacing + +/newline-whoosh { y-whoosh lg-whoosh sub /y-whoosh exch def x-whoosh y-whoosh moveto } def +% define newline (position of new line) by using subtracting linespacing (lg) from y posiition and define that as the new y position (exch-ange), finally move to x position and re-defined y position + +x-whoosh y-whoosh moveto +% x and y coordinates in px (origin is the lower-left corner of the page) + +"""+paragraph+""" + +fill +% fill the text in parentheses + +showpage +% print all on a page +""" + + + + generate_postscript(previous_module, current_module, script) # call function