diff --git a/preload/apps/blinkisync-receive/__init__.py b/preload/apps/blinkisync-receive/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..05810e28839fad4c7130ac40508ce04dbe074033 --- /dev/null +++ b/preload/apps/blinkisync-receive/__init__.py @@ -0,0 +1,292 @@ +import display +import light_sensor +import utime +import buttons +import os + +TRANSMISSION_RECEIVED_TXT = "blinki-received.txt" +TRANSMISSION_CALIBRATE = [1, 0, 1, 0, 1, 0, 1, 0] +TRANSMISSION_START_SIGNATURE = [0, 0, 0, 0, 0, 1, 0, 1] +TRANSMISSION_END_SIGNATURE = [0, 0, 0, 0, 0, 0, 0, 0] +TRANSMISSION_TIMING_SIGNATURE = [1, 0, 1, 1] +TIMING = 75 +SCROLLSPEED = 20 + + +def init(): + if TRANSMISSION_RECEIVED_TXT not in os.listdir("/"): + with open("/" + TRANSMISSION_RECEIVED_TXT, "w") as f: + f.write("blinki transmissions") + + +def triangle(disp, x, y, left): + yf = 1 if left else -1 + scale = 6 + disp.line(x - scale * yf, int(y + scale / 2), x, y) + disp.line(x, y, x, y + scale) + disp.line(x, y + scale, x - scale * yf, y + int(scale / 2)) + + +def save_transmission(): + with open(TRANSMISSION_RECEIVED_TXT, "a") as myfile: + myfile.write("\n" + decoded_string) + + +def transmission_to_list(length=0): + global read_values_list + global read_values_current + read_values_current = light_sensor.read() + if length != 0: + while len(read_values_list) >= length: + read_values_list.pop(0) + read_values_list.append(read_values_current) + + +def transmission_list_to_byte_list(): + global read_values_list_binary + global read_values_list_copy + global read_values_list + if read_values_list[0] <= read_values_mean: + read_values_list_binary.append(0) + read_values_list_copy.append(0) + else: + read_values_list_binary.append(1) + read_values_list_copy.append(1) + del read_values_list[:1] + if len(read_values_list_binary) == 2: + if read_values_list_binary[:2] == [0, 0]: + read_values_list_binary_filtered.append(0) + del read_values_list_binary[:2] + if read_values_list_binary[:2] == [1, 1]: + read_values_list_binary_filtered.append(1) + del read_values_list_binary[:2] + if read_values_list_binary[:2] == [0, 1]: + read_values_list_binary_filtered.append(0) + del read_values_list_binary[:1] + if read_values_list_binary[:2] == [1, 0]: + read_values_list_binary_filtered.append(1) + del read_values_list_binary[:1] + + +def get_transmission_mean(): + global read_values_mean + transmission_to_list(8) + read_values_mean = sum(read_values_list) / len(read_values_list) + + +def detect_transmission_start(): + global read_values_list_binary_filtered + global transmission_started + #print(read_values_list_binary_filtered) + if read_values_list_binary_filtered[-8:] == TRANSMISSION_START_SIGNATURE: + transmission_started = 1 + + +def detect_transmission_end(): + global transmission_ended + if read_values_list_binary_filtered[-8:] == TRANSMISSION_END_SIGNATURE: + transmission_ended = 1 + + +def strip_timecode(): + global read_values_list_binary_filtered + if read_values_list_binary_filtered[:len(TRANSMISSION_TIMING_SIGNATURE)] == TRANSMISSION_TIMING_SIGNATURE: + del read_values_list_binary_filtered[:len(TRANSMISSION_TIMING_SIGNATURE)] + elif read_values_list_binary_filtered[1:len(TRANSMISSION_TIMING_SIGNATURE)+1] == TRANSMISSION_TIMING_SIGNATURE: + del read_values_list_binary_filtered[:len(TRANSMISSION_TIMING_SIGNATURE)+1] + elif read_values_list_binary_filtered[:len(TRANSMISSION_TIMING_SIGNATURE)-1] == TRANSMISSION_TIMING_SIGNATURE[1:len(TRANSMISSION_TIMING_SIGNATURE)]: + del read_values_list_binary_filtered[:len(TRANSMISSION_TIMING_SIGNATURE)-1] + else: + del read_values_list_binary_filtered[:len(TRANSMISSION_TIMING_SIGNATURE)-1] + if read_values_list_binary_filtered[0] == 1: + del read_values_list_binary_filtered[:1] + + +def decode_byte(): + global read_values_list_binary_filtered + global decoded_string + byte_string = "" + for item in read_values_list_binary_filtered[:8]: + byte_string += str(item) + del read_values_list_binary_filtered[:8] + decoded_string += chr(int(byte_string, 2)) + + +def decode_transmission(): + global decoded_string + del read_values_list_binary_filtered[0] + while len(read_values_list_binary_filtered) >= 8+len(TRANSMISSION_TIMING_SIGNATURE): + decode_byte() + strip_timecode() + + +def menu(): + if app_state == 0: + disp.print("start", posy=0, fg=[255, 255, 255]) + disp.print("receive", posy=20, fg=[255, 255, 255]) + disp.print("calibration", posy=40, fg=[255, 255, 255]) + disp.print("hold", posx=85, posy=60, fg=[0, 255, 255]) + triangle(disp, 150, 66, False) + if app_state == 2: + disp.print("calibrating", posy=0, fg=[0, 255, 255]) + disp.print(str(min(read_values_list)), posx=0, posy=20, fg=[255, 0, 0]) + #disp.print(str(round(read_values_mean, 2)), posx=46, posy=40, fg=[0, 255, 255]) + disp.print(str(max(read_values_list)), posx=50, posy=20, fg=[0, 255, 0]) + disp.print("release", posx=36, posy=40, fg=[255, 255, 255]) + disp.print("first", posx=36, posy=60, fg=[255, 255, 255]) + triangle(disp, 150, 66, False) + if app_state == 1: + disp.print("waiting for", posy=0, fg=[255, 255, 255]) + disp.print("transmission", posy=20, fg=[255, 255, 255]) + printlist = ''.join(str(e) for e in read_values_list_binary_filtered[-22:]) + disp.print(printlist, posx=0, posy=40, fg=[0, 255, 0]) + disp.print("reset", posx=12, posy=60, fg=[255, 0, 0]) + triangle(disp, 10, 66, True) + if app_state == 3: + disp.print("transmission", posy=0, fg=[255, 255, 255]) + disp.print("started", posy=20, fg=[255, 255, 255]) + printlist = ''.join(str(e) for e in read_values_list_binary_filtered[-22:]) + disp.print(printlist, posx=0, posy=40, fg=[0, 255, 0]) + if app_state == 5: + global offset_counter + linelength = len(decoded_string) + maxchars = 11 + if linelength > maxchars: + offset = offset_counter//SCROLLSPEED + #print(offset) + #print(offset_counter) + disp.print(decoded_string[offset:maxchars+offset], posx=0, posy=20, fg=[0, 255, 0]) + offset_counter += 1 + if maxchars + offset > linelength: + offset_counter = 0 + else: + disp.print(decoded_string, posx=0, posy=20, fg=[0, 255, 0]) + disp.print("ended", posy=0, fg=[255, 255, 255]) + disp.print("save", posx=85, posy=60, fg=[255, 255, 255]) + disp.print("back", posx=15, posy=60, fg=[255, 255, 255]) + triangle(disp, 10, 66, True) + triangle(disp, 150, 66, False) + +def reset(): + global app_state + global offset_counter + global read_values_current + global read_values_list + global read_values_list_binary + global read_values_list_binary_filtered + global read_values_list_binary_copy + global read_values_list_copy + global cycle_start_time + global cycle_time + global transmission_decoded + global transmission_started + global transmission_ended + global mean_calculation_started + global counter + global decoded_string + global synchronized + app_state = 0 + offset_counter = 0 + read_values_current = 0 + read_values_list = [0] + read_values_list_binary = [0] + read_values_list_binary_filtered = [] + read_values_list_binary_copy = [] + read_values_list_copy = [] + cycle_start_time = 0 + cycle_time = 0 + transmission_decoded = "" + transmission_started = 0 + transmission_ended = 0 + mean_calculation_started = 0 + counter = 0 + decoded_string = "" + synchronized = 0 + +app_state = 0 +offset_counter = 0 +read_values_current = 0 +read_values_list = [0] +read_values_list_binary = [0] +read_values_list_binary_filtered = [] +read_values_list_binary_copy = [] +read_values_list_copy = [] +cycle_start_time = 0 +cycle_time = 0 +transmission_decoded = "" +read_values_mean = sum(read_values_list) / len(read_values_list) +transmission_started = 0 +transmission_ended = 0 +mean_calculation_started = 0 +button_pressed = False +disp = display.open() +counter = 0 +decoded_string = "" +synchronized = 0 + +init() + +while True: + v = buttons.read(buttons.BOTTOM_LEFT | buttons.BOTTOM_RIGHT | buttons.TOP_RIGHT) + if v == 0: + button_pressed = False + disp.clear() + if app_state == 0: + if v == 4: + mean_calculation_started = 1 + app_state = 2 + cycle_start_time = utime.time_ms() + decoded_string = "" + if app_state == 2: + get_transmission_mean() + if v == 0 and mean_calculation_started == 1: + app_state = 1 + if app_state == 1: + mean_calculation_started = 0 + transmission_to_list() + transmission_list_to_byte_list() + detect_transmission_start() + if not button_pressed and v & buttons.BOTTOM_LEFT != 0: + button_pressed = True + reset() + #print(read_values_list) + #print(read_values_list_binary) + #print(read_values_list_binary_filtered) + if transmission_started == 1: + read_values_list = [] + read_values_list_copy = [] + read_values_list_binary_copy = [] + read_values_list_binary = [] + read_values_list_binary_filtered = [] + app_state = 3 + if app_state == 3: + transmission_to_list() + transmission_list_to_byte_list() + #filter_binary_list() + detect_transmission_end() + if transmission_ended == 1: + app_state = 4 + if app_state == 4: + decode_transmission() + app_state = 5 + if app_state == 5: + if not button_pressed and v & buttons.BOTTOM_RIGHT != 0: + button_pressed = True + print(decoded_string) + save_transmission() + reset() + if not button_pressed and v & buttons.BOTTOM_LEFT != 0: + button_pressed = True + reset() + menu() + disp.update() + if app_state == 1 or app_state == 2 or app_state == 3: + while utime.time_ms() - cycle_start_time <= cycle_time: + wait = True + #print("wait") + #print(utime.time_ms()) + #print(cycle_start_time) + #print(cycle_time) + #print("wait-end") + cycle_time += TIMING + diff --git a/preload/apps/blinkisync-receive/metadata.json b/preload/apps/blinkisync-receive/metadata.json new file mode 100644 index 0000000000000000000000000000000000000000..17e305056e0f79d3b743e7fd2d5017be82164424 --- /dev/null +++ b/preload/apps/blinkisync-receive/metadata.json @@ -0,0 +1 @@ +{"name":"blinkisync-receive","description":"Transmit text over light. Firmware v1.8 required. https://card10.badge.events.ccc.de/blinkisync/","category":"utility","author":"torben","revision":1} \ No newline at end of file diff --git a/preload/apps/blinkisync-transmit/__init__.py b/preload/apps/blinkisync-transmit/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..621875f76f8e61d0e38bdbb7682a5c1a8584a6a4 --- /dev/null +++ b/preload/apps/blinkisync-transmit/__init__.py @@ -0,0 +1,156 @@ +import leds +import utime +import buttons +import display +import os + +TRANSMISSION_SEND_TXT = "blinki-transmission.txt" +TRANSMISSION_CALIBRATE = [1, 0, 1, 0, 1, 0, 1, 0] +TRANSMISSION_START_SIGNATURE = [0, 0, 0, 0, 0, 1, 0, 1] +TRANSMISSION_END_SIGNATURE = [0, 0, 0, 0, 0, 0, 0, 0] +#TRANSMISSION_END_SIGNATURE = [1, 1, 1, 1, 1, 1, 1, 1] +TRANSMISSION_TIMING_SIGNATURE = [1, 0, 1, 1] +TIMING = 150 + + +def init(): + global input_string + if TRANSMISSION_SEND_TXT not in os.listdir("/"): + with open("/" + TRANSMISSION_SEND_TXT, "w") as f: + f.write("hello world!") + with open("/" + TRANSMISSION_SEND_TXT, "r") as f: + input_string = f.readlines()[0] + + +def triangle(disp, x, y, left): + yf = 1 if left else -1 + scale = 6 + disp.line(x - scale * yf, int(y + scale / 2), x, y) + disp.line(x, y, x, y + scale) + disp.line(x, y + scale, x - scale * yf, y + int(scale / 2)) + + +def get_transmission(): + str_to_byte_list = [] + for character in input_string: + str_to_byte_list_dirty = " ".join(map(bin, bytearray(character, "utf-8"))) + while len(str_to_byte_list_dirty) <= 8: + str_to_byte_list_dirty = "0" + str_to_byte_list_dirty + for item in str_to_byte_list_dirty: + if item == "1" or item == "0": + str_to_byte_list.append(int(item)) + transmission = [] + transmission.extend(TRANSMISSION_START_SIGNATURE) + transmission.extend(TRANSMISSION_TIMING_SIGNATURE) + while len(str_to_byte_list) // 8 > 0: + transmission.extend(str_to_byte_list[:8]) + del str_to_byte_list[:8] + transmission.extend(TRANSMISSION_TIMING_SIGNATURE) + transmission.extend(str_to_byte_list) + transmission.extend(TRANSMISSION_END_SIGNATURE) + return transmission + + +def send_stream(): + global timing_test_list + global transmission + global app_state + if transmission[0] == 1: + print(transmission[1]) + leds.set(13, [255, 255, 255]) + elif transmission[0] == 0: + print(transmission[0]) + leds.set(13, [0, 0, 0]) + if len(transmission) == 1: + app_state = 3 + del transmission[0] + + +def send_calibration(): + leds.set(13, [255, 255, 255]) + utime.sleep_ms(int(TIMING/2)) + leds.set(13, [0, 0, 0]) + + +def menu(): + if app_state == 0: + disp.print("start", posy=0, fg=[255, 255, 255]) + disp.print("transmit", posy=20, fg=[255, 255, 255]) + disp.print("calibration", posy=40, fg=[255, 255, 255]) + disp.print("hold", posx=85, posy=60, fg=[0, 255, 255]) + triangle(disp, 150, 66, False) + if app_state == 1: + disp.print("calibrating", posy=0, fg=[0, 255, 255]) + disp.print("release", posx=36, posy=40, fg=[255, 255, 255]) + disp.print("second", posx=36, posy=60, fg=[255, 255, 255]) + if app_state == 2: + disp.print(str("sending"), posy=20, fg=[255, 255, 255]) + disp.print("reset", posx=70, posy=60, fg=[0, 255, 255]) + triangle(disp, 150, 66, False) + if app_state == 3: + disp.print(str("done"), posy=20, fg=[255, 255, 255]) + + +app_state = 0 +input_string = "" +button_pressed = False +disp = display.open() +counter = 0 +calibration_started = 0 +counter = 0 +start_time = 0 +start_time_set = 0 +cycle_time = 0 +cycle_start_time = 0 + +init() +transmission = get_transmission() + +while True: + if app_state == 2: + counter += 1 + if app_state == 2 & start_time_set == 0: + start_time = utime.time() + start_time_set = 1 + disp.clear() + v = buttons.read(buttons.BOTTOM_LEFT | buttons.BOTTOM_RIGHT | buttons.TOP_RIGHT) + if v == 0: + button_pressed = False + if not button_pressed and v & buttons.BOTTOM_RIGHT != 0: + button_pressed = True + app_state += 1 + if app_state == 0: + if v == 4: + calibration_started = 1 + app_state = 1 + cycle_start_time = utime.time_ms() + if app_state == 1: + send_calibration() + if v == 0 and calibration_started == 1: + calibration_started = 0 + app_state = 2 + if app_state == 2: + send_stream() + if app_state == 3: + transmission = get_transmission() + app_state = 0 + cycle_time = 0 + menu() + disp.update() + if app_state == 2: + end_time = utime.time() + print(counter) + print(end_time-start_time) + if app_state == 3: + print(counter) + print(end_time-start_time) + if app_state == 1 or app_state == 2: + while utime.time_ms() - cycle_start_time <= cycle_time: + wait = True + print("wait") + print(utime.time_ms()) + print(cycle_start_time) + print(cycle_time) + print("wait-end") + cycle_time += TIMING + diff --git a/preload/apps/blinkisync-transmit/metadata.json b/preload/apps/blinkisync-transmit/metadata.json new file mode 100644 index 0000000000000000000000000000000000000000..e918d672b94eea8ea8197761f83886505b6e2eca --- /dev/null +++ b/preload/apps/blinkisync-transmit/metadata.json @@ -0,0 +1 @@ +{"name":"blinkisync-transmit","description":"Transmit text over light. Firmware v1.8 required. https://card10.badge.events.ccc.de/blinkisync/","category":"utility","author":"torben","revision":1} \ No newline at end of file