summaryrefslogtreecommitdiff
path: root/src/compile_eeprom.py
blob: 52dbbfc8fd8aeb227523a71eb910f8171b6615db (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#!/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()