#!/usr/bin/env python3 from PIL import BdfFontFile, Image import os import serial import argparse compiled_output_path = 'compiled_eeprom' header_path = 'eeprom_address.h' eeprom_length = 131072 # 128 kib data_path = "./eeprom_data" output = open(compiled_output_path, 'wb') header = open(header_path, 'w') page_bit_width = 128 page_bit_height = 8 page_cnt = 4 #fonts # for some reason BdfFontFile.BdfFontFile.bitmap doesn't have proper spacing # so we'll just manually go through each character ourselves # it's expected I'll rename fonts to how I think they should be refrenced beorehand # also note we have no protection from using unsed chars, I can't let this project # get to big for litteraly no reason header.write("/** GENERATED BY EEPROM COMPILER SCRIPT **/\n\n") header.write("// FONTS\n") for file in os.listdir("{}/fonts/".format(data_path)): path = "{}/fonts/{}".format(data_path, file) if os.path.isfile(path) and path.split('.')[-1] == 'bdf': with open(path, 'rb') as font_fd: font_bdf = BdfFontFile.BdfFontFile(font_fd) font_name = file.split('.')[0].capitalize() header.write("#define FONT_{}_ADDR\t0x{:04x}\n".format(font_name, output.tell())) first_char = False for char in enumerate(font_bdf.glyph): if char[1]: if not first_char: first_char = True header.write(("#define FONT_{}_FIRST_CHAR\t{}\n" "#define FONT_{}_WIDTH\t{}\n" "#define FONT_{}_HEIGHT\t{}\n").format( font_name, char[0], font_name, char[1][-1].size[0], font_name, char[1][-1].size[1])) output.write(char[1][-1].tobytes('raw')) header.write("\n\n// IMAGES\n#define IMG_BEGIN\t0x{:04x}\n".format(output.tell())) image_cnt = 0 # images for file in os.listdir("{}/images/".format(data_path)): path = "{}/images/{}".format(data_path, file) if os.path.isfile(path) and path.split('.')[-1] == 'png': with open(path, 'rb') as image_fd: image_cnt += 1 image_bitmap = [] image_bitmap_remapped = [] image = Image.open(image_fd) if not image.mode == 'RGB': print("this script only compiles RGB formatted photos! (I'm lazy\n") exit(1) header.write("#define IMG_{}_ADDR\t0x{:04x}\n".format( file.split('.')[0].capitalize(), output.tell())) for byte in range(0, len(image.tobytes()), 3): if (byte / 3) % 8 == 0: image_bitmap.append(0) if sum(image.tobytes()[byte:byte+3]) > 0: image_bitmap[-1] |= (int(byte / 3)) % 8 # is this supposed to be big endian? image_bitmap_remapped = [0] * len(image_bitmap) for bit in range(0, page_bit_width * page_bit_height * page_cnt): w = page_bit_width h = page_bit_height i = bit #I am so sorry. extract_bit = (((i % w) * page_bit_height) + (int(i / w) % page_bit_height) + (int(i / (w * page_bit_height)) * (w * page_bit_height))) if (extract_bit % 8) - (bit % 8) >= 0: image_bitmap_remapped[int(bit / 8)] |= \ (image_bitmap[int(extract_bit / 8)] & (extract_bit % 8)) >> \ ((extract_bit % 8) - (bit % 8)) else: image_bitmap_remapped[int(bit / 8)] |= \ (image_bitmap[int(extract_bit / 8)] & (extract_bit % 8)) << \ ((bit % 8) - (extract_bit % 8)) [output.write(byte.to_bytes(1, 'big')) for byte in image_bitmap_remapped] header.write("#define IMG_COUNT\t{}\n\n".format(image_cnt)) print("EEPROM used: {}% ({} out of {} bits)".format( (output.tell() / eeprom_length) * 100, output.tell(), eeprom_length)) if(output.tell() > eeprom_length): print("WARNING: You've used more eeprom then there is available!\n") output.close() header.close()