adds rotary encoder+SPI based Display: ili9341
This commit is contained in:
		
							parent
							
								
									dd2a5bf637
								
							
						
					
					
						commit
						a8f8586756
					
				
					 11 changed files with 2184 additions and 269 deletions
				
			
		|  | @ -1,3 +1,12 @@ | ||||||
| # Spinny boy | # Spinny boy | ||||||
| 
 | 
 | ||||||
| this readme will contain documentation and stuff | this readme will contain documentation and stuff | ||||||
|  | 
 | ||||||
|  | # Flashing programm on the ESP32 | ||||||
|  | ``` | ||||||
|  | rshell -p /dev/ttyUSB0  # connect | ||||||
|  | rsync src /pyboard/  # sync code to ESP32 | ||||||
|  | repl  # enter MicroPython REPL, press ctrl+D to soft reboot | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |  | ||||||
							
								
								
									
										540
									
								
								src/font_to_py.py
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										540
									
								
								src/font_to_py.py
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,540 @@ | ||||||
|  | #! /usr/bin/python3 | ||||||
|  | # -*- coding: utf-8 -*- | ||||||
|  | # Needs freetype-py>=1.0 | ||||||
|  | 
 | ||||||
|  | # Implements multi-pass solution to setting an exact font height | ||||||
|  | 
 | ||||||
|  | # Some code adapted from Daniel Bader's work at the following URL | ||||||
|  | # http://dbader.org/blog/monochrome-font-rendering-with-freetype-and-python | ||||||
|  | 
 | ||||||
|  | # The MIT License (MIT) | ||||||
|  | # | ||||||
|  | # Copyright (c) 2016 Peter Hinch | ||||||
|  | # | ||||||
|  | # Permission is hereby granted, free of charge, to any person obtaining a copy | ||||||
|  | # of this software and associated documentation files (the "Software"), to deal | ||||||
|  | # in the Software without restriction, including without limitation the rights | ||||||
|  | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||||
|  | # copies of the Software, and to permit persons to whom the Software is | ||||||
|  | # furnished to do so, subject to the following conditions: | ||||||
|  | # | ||||||
|  | # The above copyright notice and this permission notice shall be included in | ||||||
|  | # all copies or substantial portions of the Software. | ||||||
|  | # | ||||||
|  | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||||
|  | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||||
|  | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||||
|  | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||||
|  | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||||
|  | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||||
|  | # THE SOFTWARE. | ||||||
|  | 
 | ||||||
|  | import argparse | ||||||
|  | import sys | ||||||
|  | import os | ||||||
|  | import freetype | ||||||
|  | 
 | ||||||
|  | # UTILITIES FOR WRITING PYTHON SOURCECODE TO A FILE | ||||||
|  | 
 | ||||||
|  | # ByteWriter takes as input a variable name and data values and writes | ||||||
|  | # Python source to an output stream of the form | ||||||
|  | # my_variable = b'\x01\x02\x03\x04\x05\x06\x07\x08'\ | ||||||
|  | 
 | ||||||
|  | # Lines are broken with \ for readability. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class ByteWriter(object): | ||||||
|  |     bytes_per_line = 16 | ||||||
|  | 
 | ||||||
|  |     def __init__(self, stream, varname): | ||||||
|  |         self.stream = stream | ||||||
|  |         self.stream.write('{} =\\\n'.format(varname)) | ||||||
|  |         self.bytecount = 0  # For line breaks | ||||||
|  | 
 | ||||||
|  |     def _eol(self): | ||||||
|  |         self.stream.write("'\\\n") | ||||||
|  | 
 | ||||||
|  |     def _eot(self): | ||||||
|  |         self.stream.write("'\n") | ||||||
|  | 
 | ||||||
|  |     def _bol(self): | ||||||
|  |         self.stream.write("b'") | ||||||
|  | 
 | ||||||
|  |     # Output a single byte | ||||||
|  |     def obyte(self, data): | ||||||
|  |         if not self.bytecount: | ||||||
|  |             self._bol() | ||||||
|  |         self.stream.write('\\x{:02x}'.format(data)) | ||||||
|  |         self.bytecount += 1 | ||||||
|  |         self.bytecount %= self.bytes_per_line | ||||||
|  |         if not self.bytecount: | ||||||
|  |             self._eol() | ||||||
|  | 
 | ||||||
|  |     # Output from a sequence | ||||||
|  |     def odata(self, bytelist): | ||||||
|  |         for byt in bytelist: | ||||||
|  |             self.obyte(byt) | ||||||
|  | 
 | ||||||
|  |     # ensure a correct final line | ||||||
|  |     def eot(self):  # User force EOL if one hasn't occurred | ||||||
|  |         if self.bytecount: | ||||||
|  |             self._eot() | ||||||
|  |         self.stream.write('\n') | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | # Define a global | ||||||
|  | def var_write(stream, name, value): | ||||||
|  |     stream.write('{} = {}\n'.format(name, value)) | ||||||
|  | 
 | ||||||
|  | # FONT HANDLING | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class Bitmap(object): | ||||||
|  |     """ | ||||||
|  |     A 2D bitmap image represented as a list of byte values. Each byte indicates | ||||||
|  |     the state of a single pixel in the bitmap. A value of 0 indicates that the | ||||||
|  |     pixel is `off` and any other value indicates that it is `on`. | ||||||
|  |     """ | ||||||
|  |     def __init__(self, width, height, pixels=None): | ||||||
|  |         self.width = width | ||||||
|  |         self.height = height | ||||||
|  |         self.pixels = pixels or bytearray(width * height) | ||||||
|  | 
 | ||||||
|  |     def display(self): | ||||||
|  |         """Print the bitmap's pixels.""" | ||||||
|  |         for row in range(self.height): | ||||||
|  |             for col in range(self.width): | ||||||
|  |                 char = '#' if self.pixels[row * self.width + col] else '.' | ||||||
|  |                 print(char, end='') | ||||||
|  |             print() | ||||||
|  |         print() | ||||||
|  | 
 | ||||||
|  |     def bitblt(self, src, row): | ||||||
|  |         """Copy all pixels from `src` into this bitmap""" | ||||||
|  |         srcpixel = 0 | ||||||
|  |         dstpixel = row * self.width | ||||||
|  |         row_offset = self.width - src.width | ||||||
|  | 
 | ||||||
|  |         for _ in range(src.height): | ||||||
|  |             for _ in range(src.width): | ||||||
|  |                 self.pixels[dstpixel] = src.pixels[srcpixel] | ||||||
|  |                 srcpixel += 1 | ||||||
|  |                 dstpixel += 1 | ||||||
|  |             dstpixel += row_offset | ||||||
|  | 
 | ||||||
|  |     # Horizontal mapping generator function | ||||||
|  |     def get_hbyte(self, reverse): | ||||||
|  |         for row in range(self.height): | ||||||
|  |             col = 0 | ||||||
|  |             while True: | ||||||
|  |                 bit = col % 8 | ||||||
|  |                 if bit == 0: | ||||||
|  |                     if col >= self.width: | ||||||
|  |                         break | ||||||
|  |                     byte = 0 | ||||||
|  |                 if col < self.width: | ||||||
|  |                     if reverse: | ||||||
|  |                         byte |= self.pixels[row * self.width + col] << bit | ||||||
|  |                     else: | ||||||
|  |                         # Normal map MSB of byte 0 is (0, 0) | ||||||
|  |                         byte |= self.pixels[row * self.width + col] << (7 - bit) | ||||||
|  |                 if bit == 7: | ||||||
|  |                     yield byte | ||||||
|  |                 col += 1 | ||||||
|  | 
 | ||||||
|  |     # Vertical mapping | ||||||
|  |     def get_vbyte(self, reverse): | ||||||
|  |         for col in range(self.width): | ||||||
|  |             row = 0 | ||||||
|  |             while True: | ||||||
|  |                 bit = row % 8 | ||||||
|  |                 if bit == 0: | ||||||
|  |                     if row >= self.height: | ||||||
|  |                         break | ||||||
|  |                     byte = 0 | ||||||
|  |                 if row < self.height: | ||||||
|  |                     if reverse: | ||||||
|  |                         byte |= self.pixels[row * self.width + col] << (7 - bit) | ||||||
|  |                     else: | ||||||
|  |                         # Normal map MSB of byte 0 is (0, 7) | ||||||
|  |                         byte |= self.pixels[row * self.width + col] << bit | ||||||
|  |                 if bit == 7: | ||||||
|  |                     yield byte | ||||||
|  |                 row += 1 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class Glyph(object): | ||||||
|  |     def __init__(self, pixels, width, height, top, advance_width): | ||||||
|  |         self.bitmap = Bitmap(width, height, pixels) | ||||||
|  | 
 | ||||||
|  |         # The glyph bitmap's top-side bearing, i.e. the vertical distance from | ||||||
|  |         # the baseline to the bitmap's top-most scanline. | ||||||
|  |         self.top = top | ||||||
|  | 
 | ||||||
|  |         # Ascent and descent determine how many pixels the glyph extends | ||||||
|  |         # above or below the baseline. | ||||||
|  |         self.descent = max(0, self.height - self.top) | ||||||
|  |         self.ascent = max(0, max(self.top, self.height) - self.descent) | ||||||
|  | 
 | ||||||
|  |         # The advance width determines where to place the next character | ||||||
|  |         # horizontally, that is, how many pixels we move to the right to | ||||||
|  |         # draw the next glyph. | ||||||
|  |         self.advance_width = advance_width | ||||||
|  | 
 | ||||||
|  |     @property | ||||||
|  |     def width(self): | ||||||
|  |         return self.bitmap.width | ||||||
|  | 
 | ||||||
|  |     @property | ||||||
|  |     def height(self): | ||||||
|  |         return self.bitmap.height | ||||||
|  | 
 | ||||||
|  |     @staticmethod | ||||||
|  |     def from_glyphslot(slot): | ||||||
|  |         """Construct and return a Glyph object from a FreeType GlyphSlot.""" | ||||||
|  |         pixels = Glyph.unpack_mono_bitmap(slot.bitmap) | ||||||
|  |         width, height = slot.bitmap.width, slot.bitmap.rows | ||||||
|  |         top = slot.bitmap_top | ||||||
|  | 
 | ||||||
|  |         # The advance width is given in FreeType's 26.6 fixed point format, | ||||||
|  |         # which means that the pixel values are multiples of 64. | ||||||
|  |         advance_width = slot.advance.x / 64 | ||||||
|  | 
 | ||||||
|  |         return Glyph(pixels, width, height, top, advance_width) | ||||||
|  | 
 | ||||||
|  |     @staticmethod | ||||||
|  |     def unpack_mono_bitmap(bitmap): | ||||||
|  |         """ | ||||||
|  |         Unpack a freetype FT_LOAD_TARGET_MONO glyph bitmap into a bytearray | ||||||
|  |         where each pixel is represented by a single byte. | ||||||
|  |         """ | ||||||
|  |         # Allocate a bytearray of sufficient size to hold the glyph bitmap. | ||||||
|  |         data = bytearray(bitmap.rows * bitmap.width) | ||||||
|  | 
 | ||||||
|  |         # Iterate over every byte in the glyph bitmap. Note that we're not | ||||||
|  |         # iterating over every pixel in the resulting unpacked bitmap -- | ||||||
|  |         # we're iterating over the packed bytes in the input bitmap. | ||||||
|  |         for row in range(bitmap.rows): | ||||||
|  |             for byte_index in range(bitmap.pitch): | ||||||
|  | 
 | ||||||
|  |                 # Read the byte that contains the packed pixel data. | ||||||
|  |                 byte_value = bitmap.buffer[row * bitmap.pitch + byte_index] | ||||||
|  | 
 | ||||||
|  |                 # We've processed this many bits (=pixels) so far. This | ||||||
|  |                 # determines where we'll read the next batch of pixels from. | ||||||
|  |                 num_bits_done = byte_index * 8 | ||||||
|  | 
 | ||||||
|  |                 # Pre-compute where to write the pixels that we're going | ||||||
|  |                 # to unpack from the current byte in the glyph bitmap. | ||||||
|  |                 rowstart = row * bitmap.width + byte_index * 8 | ||||||
|  | 
 | ||||||
|  |                 # Iterate over every bit (=pixel) that's still a part of the | ||||||
|  |                 # output bitmap. Sometimes we're only unpacking a fraction of | ||||||
|  |                 # a byte because glyphs may not always fit on a byte boundary. | ||||||
|  |                 # So we make sure to stop if we unpack past the current row | ||||||
|  |                 # of pixels. | ||||||
|  |                 for bit_index in range(min(8, bitmap.width - num_bits_done)): | ||||||
|  | 
 | ||||||
|  |                     # Unpack the next pixel from the current glyph byte. | ||||||
|  |                     bit = byte_value & (1 << (7 - bit_index)) | ||||||
|  | 
 | ||||||
|  |                     # Write the pixel to the output bytearray. We ensure that | ||||||
|  |                     # `off` pixels have a value of 0 and `on` pixels have a | ||||||
|  |                     # value of 1. | ||||||
|  |                     data[rowstart + bit_index] = 1 if bit else 0 | ||||||
|  | 
 | ||||||
|  |         return data | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | # A Font object is a dictionary of ASCII chars indexed by a character e.g. | ||||||
|  | # myfont['a'] | ||||||
|  | # Each entry comprises a list | ||||||
|  | # [0] A Bitmap instance containing the character | ||||||
|  | # [1] The width of the character data including advance (actual data stored) | ||||||
|  | # Public attributes: | ||||||
|  | # height (in pixels) of all characters | ||||||
|  | # width (in pixels) for monospaced output (advance width of widest char) | ||||||
|  | class Font(dict): | ||||||
|  |     def __init__(self, filename, size, minchar, maxchar, monospaced, defchar): | ||||||
|  |         super().__init__() | ||||||
|  |         self._face = freetype.Face(filename) | ||||||
|  |         if defchar is None: # Binary font | ||||||
|  |             self.charset = [chr(char) for char in range(minchar, maxchar + 1)] | ||||||
|  |         else: | ||||||
|  |             self.charset = [chr(defchar)] + [chr(char) for char in range(minchar, maxchar + 1)] | ||||||
|  |         self.max_width = self.get_dimensions(size) | ||||||
|  |         self.width = self.max_width if monospaced else 0 | ||||||
|  |         for char in self.charset:  # Populate dictionary | ||||||
|  |             self._render_char(char) | ||||||
|  | 
 | ||||||
|  |     # n-pass solution to setting a precise height. | ||||||
|  |     def get_dimensions(self, required_height): | ||||||
|  |         error = 0 | ||||||
|  |         height = required_height | ||||||
|  |         for npass in range(10): | ||||||
|  |             height += error | ||||||
|  |             self._face.set_pixel_sizes(0, height) | ||||||
|  |             max_descent = 0 | ||||||
|  | 
 | ||||||
|  |             # For each character in the charset string we get the glyph | ||||||
|  |             # and update the overall dimensions of the resulting bitmap. | ||||||
|  |             max_width = 0 | ||||||
|  |             max_ascent = 0 | ||||||
|  |             for char in self.charset: | ||||||
|  |                 glyph = self._glyph_for_character(char) | ||||||
|  |                 max_ascent = max(max_ascent, glyph.ascent) | ||||||
|  |                 max_descent = max(max_descent, glyph.descent) | ||||||
|  |                 # for a few chars e.g. _ glyph.width > glyph.advance_width | ||||||
|  |                 max_width = int(max(max_width, glyph.advance_width, | ||||||
|  |                                         glyph.width)) | ||||||
|  | 
 | ||||||
|  |             new_error = required_height - (max_ascent + max_descent) | ||||||
|  |             if (new_error == 0) or (abs(new_error) - abs(error) == 0): | ||||||
|  |                 break | ||||||
|  |             error = new_error | ||||||
|  |         self.height = int(max_ascent + max_descent) | ||||||
|  |         st = 'Height set in {} passes. Actual height {} pixels.\nMax character width {} pixels.' | ||||||
|  |         print(st.format(npass + 1, self.height, max_width)) | ||||||
|  |         self._max_descent = int(max_descent) | ||||||
|  |         return max_width | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     def _glyph_for_character(self, char): | ||||||
|  |         # Let FreeType load the glyph for the given character and tell it to | ||||||
|  |         # render a monochromatic bitmap representation. | ||||||
|  |         self._face.load_char(char, freetype.FT_LOAD_RENDER | | ||||||
|  |                              freetype.FT_LOAD_TARGET_MONO) | ||||||
|  |         return Glyph.from_glyphslot(self._face.glyph) | ||||||
|  | 
 | ||||||
|  |     def _render_char(self, char): | ||||||
|  |         glyph = self._glyph_for_character(char) | ||||||
|  |         char_width = int(max(glyph.width, glyph.advance_width))  # Actual width | ||||||
|  |         width = self.width if self.width else char_width  # Space required if monospaced | ||||||
|  |         outbuffer = Bitmap(width, self.height) | ||||||
|  | 
 | ||||||
|  |         # The vertical drawing position should place the glyph | ||||||
|  |         # on the baseline as intended. | ||||||
|  |         row = self.height - int(glyph.ascent) - self._max_descent | ||||||
|  |         outbuffer.bitblt(glyph.bitmap, row) | ||||||
|  |         self[char] = [outbuffer, width, char_width] | ||||||
|  | 
 | ||||||
|  |     def stream_char(self, char, hmap, reverse): | ||||||
|  |         outbuffer, _, _ = self[char] | ||||||
|  |         if hmap: | ||||||
|  |             gen = outbuffer.get_hbyte(reverse) | ||||||
|  |         else: | ||||||
|  |             gen = outbuffer.get_vbyte(reverse) | ||||||
|  |         yield from gen | ||||||
|  | 
 | ||||||
|  |     def build_arrays(self, hmap, reverse): | ||||||
|  |         data = bytearray() | ||||||
|  |         index = bytearray((0, 0)) | ||||||
|  |         for char in self.charset: | ||||||
|  |             width = self[char][1] | ||||||
|  |             data += (width).to_bytes(2, byteorder='little') | ||||||
|  |             data += bytearray(self.stream_char(char, hmap, reverse)) | ||||||
|  |             index += (len(data)).to_bytes(2, byteorder='little') | ||||||
|  |         return data, index | ||||||
|  | 
 | ||||||
|  |     def build_binary_array(self, hmap, reverse, sig): | ||||||
|  |         data = bytearray((0x3f + sig, 0xe7, self.max_width, self.height)) | ||||||
|  |         for char in self.charset: | ||||||
|  |             width = self[char][2] | ||||||
|  |             data += bytes((width,)) | ||||||
|  |             data += bytearray(self.stream_char(char, hmap, reverse)) | ||||||
|  |         return data | ||||||
|  | 
 | ||||||
|  | # PYTHON FILE WRITING | ||||||
|  | 
 | ||||||
|  | STR01 = """# Code generated by font-to-py.py. | ||||||
|  | # Font: {} | ||||||
|  | version = '0.2' | ||||||
|  | """ | ||||||
|  | 
 | ||||||
|  | STR02 = """_mvfont = memoryview(_font) | ||||||
|  | 
 | ||||||
|  | def _chr_addr(ordch): | ||||||
|  |     offset = 2 * (ordch - {}) | ||||||
|  |     return int.from_bytes(_index[offset:offset + 2], 'little') | ||||||
|  |      | ||||||
|  | def get_width(s): | ||||||
|  |     width = 0 | ||||||
|  |     for ch in s: | ||||||
|  |         ordch = ord(ch) | ||||||
|  |         ordch = ordch + 1 if ordch >= {} and ordch <= {} else 32 | ||||||
|  |         offset = _chr_addr(ordch) | ||||||
|  |         width += int.from_bytes(_font[offset:offset + 2], 'little') | ||||||
|  |     return width | ||||||
|  | 
 | ||||||
|  | def get_ch(ch): | ||||||
|  |     ordch = ord(ch) | ||||||
|  |     ordch = ordch + 1 if ordch >= {} and ordch <= {} else {} | ||||||
|  |     offset = _chr_addr(ordch) | ||||||
|  |     width = int.from_bytes(_font[offset:offset + 2], 'little') | ||||||
|  |     next_offs = _chr_addr(ordch +1) | ||||||
|  |     return _mvfont[offset + 2:next_offs], width | ||||||
|  |   | ||||||
|  | """ | ||||||
|  | 
 | ||||||
|  | def write_func(stream, name, arg): | ||||||
|  |     stream.write('def {}():\n    return {}\n\n'.format(name, arg)) | ||||||
|  | 
 | ||||||
|  | # filename, size, minchar=32, maxchar=126, monospaced=False, defchar=ord('?'): | ||||||
|  | 
 | ||||||
|  | def write_font(op_path, font_path, height, monospaced, hmap, reverse, minchar, maxchar, defchar): | ||||||
|  |     try: | ||||||
|  |         fnt = Font(font_path, height, minchar, maxchar, monospaced, defchar) | ||||||
|  |     except freetype.ft_errors.FT_Exception: | ||||||
|  |         print("Can't open", font_path) | ||||||
|  |         return False | ||||||
|  |     try: | ||||||
|  |         with open(op_path, 'w') as stream: | ||||||
|  |             write_data(stream, fnt, font_path, monospaced, hmap, reverse, minchar, maxchar) | ||||||
|  |     except OSError: | ||||||
|  |         print("Can't open", op_path, 'for writing') | ||||||
|  |         return False | ||||||
|  |     return True | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def write_data(stream, fnt, font_path, monospaced, hmap, reverse, minchar, maxchar): | ||||||
|  |     height = fnt.height  # Actual height, not target height | ||||||
|  |     stream.write(STR01.format(os.path.split(font_path)[1])) | ||||||
|  |     stream.write('\n') | ||||||
|  |     write_func(stream, 'height', height) | ||||||
|  |     write_func(stream, 'max_width', fnt.max_width) | ||||||
|  |     write_func(stream, 'hmap', hmap) | ||||||
|  |     write_func(stream, 'reverse', reverse) | ||||||
|  |     write_func(stream, 'monospaced', monospaced) | ||||||
|  |     write_func(stream, 'min_ch', minchar) | ||||||
|  |     write_func(stream, 'max_ch', maxchar) | ||||||
|  |     data, index = fnt.build_arrays(hmap, reverse) | ||||||
|  |     bw_font = ByteWriter(stream, '_font') | ||||||
|  |     bw_font.odata(data) | ||||||
|  |     bw_font.eot() | ||||||
|  |     bw_index = ByteWriter(stream, '_index') | ||||||
|  |     bw_index.odata(index) | ||||||
|  |     bw_index.eot() | ||||||
|  |     stream.write(STR02.format(minchar, minchar, maxchar, minchar, maxchar, minchar)) | ||||||
|  | 
 | ||||||
|  | # BINARY OUTPUT | ||||||
|  | # hmap reverse magic bytes | ||||||
|  | # 0    0       0x3f 0xe7 | ||||||
|  | # 1    0       0x40 0xe7 | ||||||
|  | # 0    1       0x41 0xe7 | ||||||
|  | # 1    1       0x42 0xe7 | ||||||
|  | def write_binary_font(op_path, font_path, height, hmap, reverse): | ||||||
|  |     try: | ||||||
|  |         fnt = Font(font_path, height, 32, 126, True, None)  # All chars have same width | ||||||
|  |     except freetype.ft_errors.FT_Exception: | ||||||
|  |         print("Can't open", font_path) | ||||||
|  |         return False | ||||||
|  |     sig = 1 if hmap else 0 | ||||||
|  |     if reverse: | ||||||
|  |         sig += 2 | ||||||
|  |     try: | ||||||
|  |         with open(op_path, 'wb') as stream: | ||||||
|  |             data = fnt.build_binary_array(hmap, reverse, sig) | ||||||
|  |             stream.write(data) | ||||||
|  |     except OSError: | ||||||
|  |         print("Can't open", op_path, 'for writing') | ||||||
|  |         return False | ||||||
|  |     return True | ||||||
|  | 
 | ||||||
|  | # PARSE COMMAND LINE ARGUMENTS | ||||||
|  | 
 | ||||||
|  | def quit(msg): | ||||||
|  |     print(msg) | ||||||
|  |     sys.exit(1) | ||||||
|  | 
 | ||||||
|  | DESC = """font_to_py.py | ||||||
|  | Utility to convert ttf or otf font files to Python source. | ||||||
|  | Sample usage: | ||||||
|  | font_to_py.py FreeSans.ttf 23 freesans.py | ||||||
|  | 
 | ||||||
|  | This creates a font with nominal height 23 pixels with these defaults: | ||||||
|  | Mapping is vertical, pitch variable, character set 32-126 inclusive. | ||||||
|  | Illegal characters will be rendered as "?". | ||||||
|  | 
 | ||||||
|  | To specify monospaced rendering issue: | ||||||
|  | font_to_py.py FreeSans.ttf 23 --fixed freesans.py | ||||||
|  | """ | ||||||
|  | 
 | ||||||
|  | BINARY = """Invalid arguments. Binary (random access) font files support the standard ASCII | ||||||
|  | character set (from 32 to 126 inclusive). This range cannot be overridden. | ||||||
|  | Random access font files don't support an error character. | ||||||
|  | """ | ||||||
|  | 
 | ||||||
|  | if __name__ == "__main__": | ||||||
|  |     parser = argparse.ArgumentParser(__file__, description=DESC, | ||||||
|  |                                      formatter_class=argparse.RawDescriptionHelpFormatter) | ||||||
|  |     parser.add_argument('infile', type=str, help='Input file path') | ||||||
|  |     parser.add_argument('height', type=int, help='Font height in pixels') | ||||||
|  |     parser.add_argument('outfile', type=str, | ||||||
|  |                         help='Path and name of output file') | ||||||
|  | 
 | ||||||
|  |     parser.add_argument('-x', '--xmap', action='store_true', | ||||||
|  |                         help='Horizontal (x) mapping') | ||||||
|  |     parser.add_argument('-r', '--reverse', action='store_true', | ||||||
|  |                         help='Bit reversal') | ||||||
|  |     parser.add_argument('-f', '--fixed', action='store_true', | ||||||
|  |                         help='Fixed width (monospaced) font') | ||||||
|  |     parser.add_argument('-b', '--binary', action='store_true', | ||||||
|  |                         help='Produce binary (random access) font file.') | ||||||
|  | 
 | ||||||
|  |     parser.add_argument('-s', '--smallest', | ||||||
|  |                         type = int, | ||||||
|  |                         default = 32, | ||||||
|  |                         help = 'Ordinal value of smallest character default %(default)i') | ||||||
|  | 
 | ||||||
|  |     parser.add_argument('-l', '--largest', | ||||||
|  |                         type = int, | ||||||
|  |                         help = 'Ordinal value of largest character default %(default)i', | ||||||
|  |                         default = 126) | ||||||
|  | 
 | ||||||
|  |     parser.add_argument('-e', '--errchar', | ||||||
|  |                         type = int, | ||||||
|  |                         help = 'Ordinal value of error character default %(default)i ("?")', | ||||||
|  |                         default = 63) | ||||||
|  | 
 | ||||||
|  |     args = parser.parse_args() | ||||||
|  |     if not args.infile[0].isalpha(): | ||||||
|  |         quit('Font filenames must be valid Python variable names.') | ||||||
|  | 
 | ||||||
|  |     if not os.path.isfile(args.infile): | ||||||
|  |         quit("Font filename does not exist") | ||||||
|  | 
 | ||||||
|  |     if not os.path.splitext(args.infile)[1].upper() in ('.TTF', '.OTF'): | ||||||
|  |         quit("Font file should be a ttf or otf file.") | ||||||
|  | 
 | ||||||
|  |     if args.binary: | ||||||
|  |         if os.path.splitext(args.outfile)[1].upper() == '.PY': | ||||||
|  |             quit('Binary file must not have a .py extension.') | ||||||
|  | 
 | ||||||
|  |         if args.smallest != 32 or args.largest != 126 or args.errchar != ord('?'): | ||||||
|  |             quit(BINARY) | ||||||
|  | 
 | ||||||
|  |         print('Writing binary font file.') | ||||||
|  |         if not write_binary_font(args.outfile, args.infile, args.height, | ||||||
|  |                                  args.xmap, args.reverse): | ||||||
|  |             sys.exit(1) | ||||||
|  |     else: | ||||||
|  |         if not os.path.splitext(args.outfile)[1].upper() == '.PY': | ||||||
|  |             quit('Output filename must have a .py extension.') | ||||||
|  | 
 | ||||||
|  |         if args.smallest < 0: | ||||||
|  |             quit('--smallest must be >= 0') | ||||||
|  | 
 | ||||||
|  |         if args.largest > 255: | ||||||
|  |             quit('--largest must be < 256') | ||||||
|  | 
 | ||||||
|  |         if args.errchar < 0 or args.errchar > 255: | ||||||
|  |             quit('--errchar must be between 0 and 255') | ||||||
|  | 
 | ||||||
|  |         print('Writing Python font file.') | ||||||
|  |         if not write_font(args.outfile, args.infile, args.height, args.fixed, | ||||||
|  |                           args.xmap, args.reverse, args.smallest, args.largest, | ||||||
|  |                           args.errchar): | ||||||
|  |             sys.exit(1) | ||||||
|  | 
 | ||||||
|  |     print(args.outfile, 'written successfully.') | ||||||
|  | 
 | ||||||
							
								
								
									
										294
									
								
								src/glcdfont.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										294
									
								
								src/glcdfont.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,294 @@ | ||||||
|  | # Original Adafruit_GFX 5x7 font | ||||||
|  | 
 | ||||||
|  | def height(): | ||||||
|  |     return 8 | ||||||
|  | 
 | ||||||
|  | def max_width(): | ||||||
|  |     return 6 | ||||||
|  | 
 | ||||||
|  | def hmap(): | ||||||
|  |     return False | ||||||
|  | 
 | ||||||
|  | def reverse(): | ||||||
|  |     return False | ||||||
|  | 
 | ||||||
|  | def monospaced(): | ||||||
|  |     return True | ||||||
|  | 
 | ||||||
|  | def min_ch(): | ||||||
|  |     return 0 | ||||||
|  | 
 | ||||||
|  | def max_ch(): | ||||||
|  |     return 255 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | _font = \ | ||||||
|  | 	b'\x00\x00\x00\x00\x00'\ | ||||||
|  | 	b'\x3E\x5B\x4F\x5B\x3E'\ | ||||||
|  | 	b'\x3E\x6B\x4F\x6B\x3E'\ | ||||||
|  | 	b'\x1C\x3E\x7C\x3E\x1C'\ | ||||||
|  | 	b'\x18\x3C\x7E\x3C\x18'\ | ||||||
|  | 	b'\x1C\x57\x7D\x57\x1C'\ | ||||||
|  | 	b'\x1C\x5E\x7F\x5E\x1C'\ | ||||||
|  | 	b'\x00\x18\x3C\x18\x00'\ | ||||||
|  | 	b'\xFF\xE7\xC3\xE7\xFF'\ | ||||||
|  | 	b'\x00\x18\x24\x18\x00'\ | ||||||
|  | 	b'\xFF\xE7\xDB\xE7\xFF'\ | ||||||
|  | 	b'\x30\x48\x3A\x06\x0E'\ | ||||||
|  | 	b'\x26\x29\x79\x29\x26'\ | ||||||
|  | 	b'\x40\x7F\x05\x05\x07'\ | ||||||
|  | 	b'\x40\x7F\x05\x25\x3F'\ | ||||||
|  | 	b'\x5A\x3C\xE7\x3C\x5A'\ | ||||||
|  | 	b'\x7F\x3E\x1C\x1C\x08'\ | ||||||
|  | 	b'\x08\x1C\x1C\x3E\x7F'\ | ||||||
|  | 	b'\x14\x22\x7F\x22\x14'\ | ||||||
|  | 	b'\x5F\x5F\x00\x5F\x5F'\ | ||||||
|  | 	b'\x06\x09\x7F\x01\x7F'\ | ||||||
|  | 	b'\x00\x66\x89\x95\x6A'\ | ||||||
|  | 	b'\x60\x60\x60\x60\x60'\ | ||||||
|  | 	b'\x94\xA2\xFF\xA2\x94'\ | ||||||
|  | 	b'\x08\x04\x7E\x04\x08'\ | ||||||
|  | 	b'\x10\x20\x7E\x20\x10'\ | ||||||
|  | 	b'\x08\x08\x2A\x1C\x08'\ | ||||||
|  | 	b'\x08\x1C\x2A\x08\x08'\ | ||||||
|  | 	b'\x1E\x10\x10\x10\x10'\ | ||||||
|  | 	b'\x0C\x1E\x0C\x1E\x0C'\ | ||||||
|  | 	b'\x30\x38\x3E\x38\x30'\ | ||||||
|  | 	b'\x06\x0E\x3E\x0E\x06'\ | ||||||
|  | 	b'\x00\x00\x00\x00\x00'\ | ||||||
|  | 	b'\x00\x00\x5F\x00\x00'\ | ||||||
|  | 	b'\x00\x07\x00\x07\x00'\ | ||||||
|  | 	b'\x14\x7F\x14\x7F\x14'\ | ||||||
|  | 	b'\x24\x2A\x7F\x2A\x12'\ | ||||||
|  | 	b'\x23\x13\x08\x64\x62'\ | ||||||
|  | 	b'\x36\x49\x56\x20\x50'\ | ||||||
|  | 	b'\x00\x08\x07\x03\x00'\ | ||||||
|  | 	b'\x00\x1C\x22\x41\x00'\ | ||||||
|  | 	b'\x00\x41\x22\x1C\x00'\ | ||||||
|  | 	b'\x2A\x1C\x7F\x1C\x2A'\ | ||||||
|  | 	b'\x08\x08\x3E\x08\x08'\ | ||||||
|  | 	b'\x00\x80\x70\x30\x00'\ | ||||||
|  | 	b'\x08\x08\x08\x08\x08'\ | ||||||
|  | 	b'\x00\x00\x60\x60\x00'\ | ||||||
|  | 	b'\x20\x10\x08\x04\x02'\ | ||||||
|  | 	b'\x3E\x51\x49\x45\x3E'\ | ||||||
|  | 	b'\x00\x42\x7F\x40\x00'\ | ||||||
|  | 	b'\x72\x49\x49\x49\x46'\ | ||||||
|  | 	b'\x21\x41\x49\x4D\x33'\ | ||||||
|  | 	b'\x18\x14\x12\x7F\x10'\ | ||||||
|  | 	b'\x27\x45\x45\x45\x39'\ | ||||||
|  | 	b'\x3C\x4A\x49\x49\x31'\ | ||||||
|  | 	b'\x41\x21\x11\x09\x07'\ | ||||||
|  | 	b'\x36\x49\x49\x49\x36'\ | ||||||
|  | 	b'\x46\x49\x49\x29\x1E'\ | ||||||
|  | 	b'\x00\x00\x14\x00\x00'\ | ||||||
|  | 	b'\x00\x40\x34\x00\x00'\ | ||||||
|  | 	b'\x00\x08\x14\x22\x41'\ | ||||||
|  | 	b'\x14\x14\x14\x14\x14'\ | ||||||
|  | 	b'\x00\x41\x22\x14\x08'\ | ||||||
|  | 	b'\x02\x01\x59\x09\x06'\ | ||||||
|  | 	b'\x3E\x41\x5D\x59\x4E'\ | ||||||
|  | 	b'\x7C\x12\x11\x12\x7C'\ | ||||||
|  | 	b'\x7F\x49\x49\x49\x36'\ | ||||||
|  | 	b'\x3E\x41\x41\x41\x22'\ | ||||||
|  | 	b'\x7F\x41\x41\x41\x3E'\ | ||||||
|  | 	b'\x7F\x49\x49\x49\x41'\ | ||||||
|  | 	b'\x7F\x09\x09\x09\x01'\ | ||||||
|  | 	b'\x3E\x41\x41\x51\x73'\ | ||||||
|  | 	b'\x7F\x08\x08\x08\x7F'\ | ||||||
|  | 	b'\x00\x41\x7F\x41\x00'\ | ||||||
|  | 	b'\x20\x40\x41\x3F\x01'\ | ||||||
|  | 	b'\x7F\x08\x14\x22\x41'\ | ||||||
|  | 	b'\x7F\x40\x40\x40\x40'\ | ||||||
|  | 	b'\x7F\x02\x1C\x02\x7F'\ | ||||||
|  | 	b'\x7F\x04\x08\x10\x7F'\ | ||||||
|  | 	b'\x3E\x41\x41\x41\x3E'\ | ||||||
|  | 	b'\x7F\x09\x09\x09\x06'\ | ||||||
|  | 	b'\x3E\x41\x51\x21\x5E'\ | ||||||
|  | 	b'\x7F\x09\x19\x29\x46'\ | ||||||
|  | 	b'\x26\x49\x49\x49\x32'\ | ||||||
|  | 	b'\x03\x01\x7F\x01\x03'\ | ||||||
|  | 	b'\x3F\x40\x40\x40\x3F'\ | ||||||
|  | 	b'\x1F\x20\x40\x20\x1F'\ | ||||||
|  | 	b'\x3F\x40\x38\x40\x3F'\ | ||||||
|  | 	b'\x63\x14\x08\x14\x63'\ | ||||||
|  | 	b'\x03\x04\x78\x04\x03'\ | ||||||
|  | 	b'\x61\x59\x49\x4D\x43'\ | ||||||
|  | 	b'\x00\x7F\x41\x41\x41'\ | ||||||
|  | 	b'\x02\x04\x08\x10\x20'\ | ||||||
|  | 	b'\x00\x41\x41\x41\x7F'\ | ||||||
|  | 	b'\x04\x02\x01\x02\x04'\ | ||||||
|  | 	b'\x40\x40\x40\x40\x40'\ | ||||||
|  | 	b'\x00\x03\x07\x08\x00'\ | ||||||
|  | 	b'\x20\x54\x54\x78\x40'\ | ||||||
|  | 	b'\x7F\x28\x44\x44\x38'\ | ||||||
|  | 	b'\x38\x44\x44\x44\x28'\ | ||||||
|  | 	b'\x38\x44\x44\x28\x7F'\ | ||||||
|  | 	b'\x38\x54\x54\x54\x18'\ | ||||||
|  | 	b'\x00\x08\x7E\x09\x02'\ | ||||||
|  | 	b'\x18\xA4\xA4\x9C\x78'\ | ||||||
|  | 	b'\x7F\x08\x04\x04\x78'\ | ||||||
|  | 	b'\x00\x44\x7D\x40\x00'\ | ||||||
|  | 	b'\x20\x40\x40\x3D\x00'\ | ||||||
|  | 	b'\x7F\x10\x28\x44\x00'\ | ||||||
|  | 	b'\x00\x41\x7F\x40\x00'\ | ||||||
|  | 	b'\x7C\x04\x78\x04\x78'\ | ||||||
|  | 	b'\x7C\x08\x04\x04\x78'\ | ||||||
|  | 	b'\x38\x44\x44\x44\x38'\ | ||||||
|  | 	b'\xFC\x18\x24\x24\x18'\ | ||||||
|  | 	b'\x18\x24\x24\x18\xFC'\ | ||||||
|  | 	b'\x7C\x08\x04\x04\x08'\ | ||||||
|  | 	b'\x48\x54\x54\x54\x24'\ | ||||||
|  | 	b'\x04\x04\x3F\x44\x24'\ | ||||||
|  | 	b'\x3C\x40\x40\x20\x7C'\ | ||||||
|  | 	b'\x1C\x20\x40\x20\x1C'\ | ||||||
|  | 	b'\x3C\x40\x30\x40\x3C'\ | ||||||
|  | 	b'\x44\x28\x10\x28\x44'\ | ||||||
|  | 	b'\x4C\x90\x90\x90\x7C'\ | ||||||
|  | 	b'\x44\x64\x54\x4C\x44'\ | ||||||
|  | 	b'\x00\x08\x36\x41\x00'\ | ||||||
|  | 	b'\x00\x00\x77\x00\x00'\ | ||||||
|  | 	b'\x00\x41\x36\x08\x00'\ | ||||||
|  | 	b'\x02\x01\x02\x04\x02'\ | ||||||
|  | 	b'\x3C\x26\x23\x26\x3C'\ | ||||||
|  | 	b'\x1E\xA1\xA1\x61\x12'\ | ||||||
|  | 	b'\x3A\x40\x40\x20\x7A'\ | ||||||
|  | 	b'\x38\x54\x54\x55\x59'\ | ||||||
|  | 	b'\x21\x55\x55\x79\x41'\ | ||||||
|  | 	b'\x21\x54\x54\x78\x41'\ | ||||||
|  | 	b'\x21\x55\x54\x78\x40'\ | ||||||
|  | 	b'\x20\x54\x55\x79\x40'\ | ||||||
|  | 	b'\x0C\x1E\x52\x72\x12'\ | ||||||
|  | 	b'\x39\x55\x55\x55\x59'\ | ||||||
|  | 	b'\x39\x54\x54\x54\x59'\ | ||||||
|  | 	b'\x39\x55\x54\x54\x58'\ | ||||||
|  | 	b'\x00\x00\x45\x7C\x41'\ | ||||||
|  | 	b'\x00\x02\x45\x7D\x42'\ | ||||||
|  | 	b'\x00\x01\x45\x7C\x40'\ | ||||||
|  | 	b'\xF0\x29\x24\x29\xF0'\ | ||||||
|  | 	b'\xF0\x28\x25\x28\xF0'\ | ||||||
|  | 	b'\x7C\x54\x55\x45\x00'\ | ||||||
|  | 	b'\x20\x54\x54\x7C\x54'\ | ||||||
|  | 	b'\x7C\x0A\x09\x7F\x49'\ | ||||||
|  | 	b'\x32\x49\x49\x49\x32'\ | ||||||
|  | 	b'\x32\x48\x48\x48\x32'\ | ||||||
|  | 	b'\x32\x4A\x48\x48\x30'\ | ||||||
|  | 	b'\x3A\x41\x41\x21\x7A'\ | ||||||
|  | 	b'\x3A\x42\x40\x20\x78'\ | ||||||
|  | 	b'\x00\x9D\xA0\xA0\x7D'\ | ||||||
|  | 	b'\x39\x44\x44\x44\x39'\ | ||||||
|  | 	b'\x3D\x40\x40\x40\x3D'\ | ||||||
|  | 	b'\x3C\x24\xFF\x24\x24'\ | ||||||
|  | 	b'\x48\x7E\x49\x43\x66'\ | ||||||
|  | 	b'\x2B\x2F\xFC\x2F\x2B'\ | ||||||
|  | 	b'\xFF\x09\x29\xF6\x20'\ | ||||||
|  | 	b'\xC0\x88\x7E\x09\x03'\ | ||||||
|  | 	b'\x20\x54\x54\x79\x41'\ | ||||||
|  | 	b'\x00\x00\x44\x7D\x41'\ | ||||||
|  | 	b'\x30\x48\x48\x4A\x32'\ | ||||||
|  | 	b'\x38\x40\x40\x22\x7A'\ | ||||||
|  | 	b'\x00\x7A\x0A\x0A\x72'\ | ||||||
|  | 	b'\x7D\x0D\x19\x31\x7D'\ | ||||||
|  | 	b'\x26\x29\x29\x2F\x28'\ | ||||||
|  | 	b'\x26\x29\x29\x29\x26'\ | ||||||
|  | 	b'\x30\x48\x4D\x40\x20'\ | ||||||
|  | 	b'\x38\x08\x08\x08\x08'\ | ||||||
|  | 	b'\x08\x08\x08\x08\x38'\ | ||||||
|  | 	b'\x2F\x10\xC8\xAC\xBA'\ | ||||||
|  | 	b'\x2F\x10\x28\x34\xFA'\ | ||||||
|  | 	b'\x00\x00\x7B\x00\x00'\ | ||||||
|  | 	b'\x08\x14\x2A\x14\x22'\ | ||||||
|  | 	b'\x22\x14\x2A\x14\x08'\ | ||||||
|  | 	b'\xAA\x00\x55\x00\xAA'\ | ||||||
|  | 	b'\xAA\x55\xAA\x55\xAA'\ | ||||||
|  | 	b'\x00\x00\x00\xFF\x00'\ | ||||||
|  | 	b'\x10\x10\x10\xFF\x00'\ | ||||||
|  | 	b'\x14\x14\x14\xFF\x00'\ | ||||||
|  | 	b'\x10\x10\xFF\x00\xFF'\ | ||||||
|  | 	b'\x10\x10\xF0\x10\xF0'\ | ||||||
|  | 	b'\x14\x14\x14\xFC\x00'\ | ||||||
|  | 	b'\x14\x14\xF7\x00\xFF'\ | ||||||
|  | 	b'\x00\x00\xFF\x00\xFF'\ | ||||||
|  | 	b'\x14\x14\xF4\x04\xFC'\ | ||||||
|  | 	b'\x14\x14\x17\x10\x1F'\ | ||||||
|  | 	b'\x10\x10\x1F\x10\x1F'\ | ||||||
|  | 	b'\x14\x14\x14\x1F\x00'\ | ||||||
|  | 	b'\x10\x10\x10\xF0\x00'\ | ||||||
|  | 	b'\x00\x00\x00\x1F\x10'\ | ||||||
|  | 	b'\x10\x10\x10\x1F\x10'\ | ||||||
|  | 	b'\x10\x10\x10\xF0\x10'\ | ||||||
|  | 	b'\x00\x00\x00\xFF\x10'\ | ||||||
|  | 	b'\x10\x10\x10\x10\x10'\ | ||||||
|  | 	b'\x10\x10\x10\xFF\x10'\ | ||||||
|  | 	b'\x00\x00\x00\xFF\x14'\ | ||||||
|  | 	b'\x00\x00\xFF\x00\xFF'\ | ||||||
|  | 	b'\x00\x00\x1F\x10\x17'\ | ||||||
|  | 	b'\x00\x00\xFC\x04\xF4'\ | ||||||
|  | 	b'\x14\x14\x17\x10\x17'\ | ||||||
|  | 	b'\x14\x14\xF4\x04\xF4'\ | ||||||
|  | 	b'\x00\x00\xFF\x00\xF7'\ | ||||||
|  | 	b'\x14\x14\x14\x14\x14'\ | ||||||
|  | 	b'\x14\x14\xF7\x00\xF7'\ | ||||||
|  | 	b'\x14\x14\x14\x17\x14'\ | ||||||
|  | 	b'\x10\x10\x1F\x10\x1F'\ | ||||||
|  | 	b'\x14\x14\x14\xF4\x14'\ | ||||||
|  | 	b'\x10\x10\xF0\x10\xF0'\ | ||||||
|  | 	b'\x00\x00\x1F\x10\x1F'\ | ||||||
|  | 	b'\x00\x00\x00\x1F\x14'\ | ||||||
|  | 	b'\x00\x00\x00\xFC\x14'\ | ||||||
|  | 	b'\x00\x00\xF0\x10\xF0'\ | ||||||
|  | 	b'\x10\x10\xFF\x10\xFF'\ | ||||||
|  | 	b'\x14\x14\x14\xFF\x14'\ | ||||||
|  | 	b'\x10\x10\x10\x1F\x00'\ | ||||||
|  | 	b'\x00\x00\x00\xF0\x10'\ | ||||||
|  | 	b'\xFF\xFF\xFF\xFF\xFF'\ | ||||||
|  | 	b'\xF0\xF0\xF0\xF0\xF0'\ | ||||||
|  | 	b'\xFF\xFF\xFF\x00\x00'\ | ||||||
|  | 	b'\x00\x00\x00\xFF\xFF'\ | ||||||
|  | 	b'\x0F\x0F\x0F\x0F\x0F'\ | ||||||
|  | 	b'\x38\x44\x44\x38\x44'\ | ||||||
|  | 	b'\x7C\x2A\x2A\x3E\x14'\ | ||||||
|  | 	b'\x7E\x02\x02\x06\x06'\ | ||||||
|  | 	b'\x02\x7E\x02\x7E\x02'\ | ||||||
|  | 	b'\x63\x55\x49\x41\x63'\ | ||||||
|  | 	b'\x38\x44\x44\x3C\x04'\ | ||||||
|  | 	b'\x40\x7E\x20\x1E\x20'\ | ||||||
|  | 	b'\x06\x02\x7E\x02\x02'\ | ||||||
|  | 	b'\x99\xA5\xE7\xA5\x99'\ | ||||||
|  | 	b'\x1C\x2A\x49\x2A\x1C'\ | ||||||
|  | 	b'\x4C\x72\x01\x72\x4C'\ | ||||||
|  | 	b'\x30\x4A\x4D\x4D\x30'\ | ||||||
|  | 	b'\x30\x48\x78\x48\x30'\ | ||||||
|  | 	b'\xBC\x62\x5A\x46\x3D'\ | ||||||
|  | 	b'\x3E\x49\x49\x49\x00'\ | ||||||
|  | 	b'\x7E\x01\x01\x01\x7E'\ | ||||||
|  | 	b'\x2A\x2A\x2A\x2A\x2A'\ | ||||||
|  | 	b'\x44\x44\x5F\x44\x44'\ | ||||||
|  | 	b'\x40\x51\x4A\x44\x40'\ | ||||||
|  | 	b'\x40\x44\x4A\x51\x40'\ | ||||||
|  | 	b'\x00\x00\xFF\x01\x03'\ | ||||||
|  | 	b'\xE0\x80\xFF\x00\x00'\ | ||||||
|  | 	b'\x08\x08\x6B\x6B\x08'\ | ||||||
|  | 	b'\x36\x12\x36\x24\x36'\ | ||||||
|  | 	b'\x06\x0F\x09\x0F\x06'\ | ||||||
|  | 	b'\x00\x00\x18\x18\x00'\ | ||||||
|  | 	b'\x00\x00\x10\x10\x00'\ | ||||||
|  | 	b'\x30\x40\xFF\x01\x01'\ | ||||||
|  | 	b'\x00\x1F\x01\x01\x1E'\ | ||||||
|  | 	b'\x00\x19\x1D\x17\x12'\ | ||||||
|  | 	b'\x00\x3C\x3C\x3C\x3C'\ | ||||||
|  | 	b'\x00\x00\x00\x00\x00' | ||||||
|  | 
 | ||||||
|  | _mvfont = memoryview(_font) | ||||||
|  | 
 | ||||||
|  | def get_width(s): | ||||||
|  |     return len(s)*6 | ||||||
|  | 
 | ||||||
|  | def get_ch(ch):  | ||||||
|  |     ordch = ord(ch) | ||||||
|  |     offset = ordch*5 | ||||||
|  |     buf = bytearray(6) | ||||||
|  |     buf[0] = 0 | ||||||
|  |     buf[1:]=_mvfont[offset:offset+5] | ||||||
|  |     return buf, 6 | ||||||
|  | 
 | ||||||
							
								
								
									
										327
									
								
								src/ili934xnew.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										327
									
								
								src/ili934xnew.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,327 @@ | ||||||
|  | # This is an adapted version of the ILI934X driver as below. | ||||||
|  | # It works with multiple fonts and also works with the esp32 H/W SPI implementation | ||||||
|  | # Also includes a word wrap print function | ||||||
|  | # Proportional fonts are generated by Peter Hinch's Font-to-py | ||||||
|  | # MIT License; Copyright (c) 2017 Jeffrey N. Magee | ||||||
|  | 
 | ||||||
|  | # This file is part of MicroPython ILI934X driver | ||||||
|  | # Copyright (c) 2016 - 2017 Radomir Dopieralski, Mika Tuupola | ||||||
|  | # | ||||||
|  | # Licensed under the MIT license: | ||||||
|  | #   http://www.opensource.org/licenses/mit-license.php | ||||||
|  | # | ||||||
|  | # Project home: | ||||||
|  | #   https://github.com/tuupola/micropython-ili934x | ||||||
|  | 
 | ||||||
|  | import time | ||||||
|  | import ustruct | ||||||
|  | import glcdfont | ||||||
|  | import framebuf | ||||||
|  | from micropython import const | ||||||
|  | 
 | ||||||
|  | _RDDSDR = const(0x0f) # Read Display Self-Diagnostic Result | ||||||
|  | _SLPOUT = const(0x11) # Sleep Out | ||||||
|  | _GAMSET = const(0x26) # Gamma Set | ||||||
|  | _DISPOFF = const(0x28) # Display Off | ||||||
|  | _DISPON = const(0x29) # Display On | ||||||
|  | _CASET = const(0x2a) # Column Address Set | ||||||
|  | _PASET = const(0x2b) # Page Address Set | ||||||
|  | _RAMWR = const(0x2c) # Memory Write | ||||||
|  | _RAMRD = const(0x2e) # Memory Read | ||||||
|  | _MADCTL = const(0x36) # Memory Access Control | ||||||
|  | _VSCRSADD = const(0x37) # Vertical Scrolling Start Address | ||||||
|  | _PIXSET = const(0x3a) # Pixel Format Set | ||||||
|  | _PWCTRLA = const(0xcb) # Power Control A | ||||||
|  | _PWCRTLB = const(0xcf) # Power Control B | ||||||
|  | _DTCTRLA = const(0xe8) # Driver Timing Control A | ||||||
|  | _DTCTRLB = const(0xea) # Driver Timing Control B | ||||||
|  | _PWRONCTRL = const(0xed) # Power on Sequence Control | ||||||
|  | _PRCTRL = const(0xf7) # Pump Ratio Control | ||||||
|  | _PWCTRL1 = const(0xc0) # Power Control 1 | ||||||
|  | _PWCTRL2 = const(0xc1) # Power Control 2 | ||||||
|  | _VMCTRL1 = const(0xc5) # VCOM Control 1 | ||||||
|  | _VMCTRL2 = const(0xc7) # VCOM Control 2 | ||||||
|  | _FRMCTR1 = const(0xb1) # Frame Rate Control 1 | ||||||
|  | _DISCTRL = const(0xb6) # Display Function Control | ||||||
|  | _ENA3G = const(0xf2) # Enable 3G | ||||||
|  | _PGAMCTRL = const(0xe0) # Positive Gamma Control | ||||||
|  | _NGAMCTRL = const(0xe1) # Negative Gamma Control | ||||||
|  | 
 | ||||||
|  | _CHUNK = const(1024) #maximum number of pixels per spi write | ||||||
|  | 
 | ||||||
|  | def color565(r, g, b): | ||||||
|  |     return (r & 0xf8) << 8 | (g & 0xfc) << 3 | b >> 3 | ||||||
|  | 
 | ||||||
|  | class ILI9341: | ||||||
|  | 
 | ||||||
|  |     def __init__(self, spi, cs, dc, rst, w, h, r): | ||||||
|  |         self.spi = spi | ||||||
|  |         self.cs = cs | ||||||
|  |         self.dc = dc | ||||||
|  |         self.rst = rst | ||||||
|  |         self._init_width = w | ||||||
|  |         self._init_height = h | ||||||
|  |         self.width = w | ||||||
|  |         self.height = h | ||||||
|  |         self.rotation = r | ||||||
|  |         self.cs.init(self.cs.OUT, value=1) | ||||||
|  |         self.dc.init(self.dc.OUT, value=0) | ||||||
|  |         self.rst.init(self.rst.OUT, value=0) | ||||||
|  |         self.reset() | ||||||
|  |         self.init() | ||||||
|  |         self._scroll = 0 | ||||||
|  |         self._buf = bytearray(_CHUNK * 2) | ||||||
|  |         self._colormap = bytearray(b'\x00\x00\xFF\xFF') #default white foregraound, black background | ||||||
|  |         self._x = 0 | ||||||
|  |         self._y = 0 | ||||||
|  |         self._font = glcdfont | ||||||
|  |         self.scrolling = False | ||||||
|  | 
 | ||||||
|  |     def set_color(self,fg,bg): | ||||||
|  |         self._colormap[0] = bg>>8 | ||||||
|  |         self._colormap[1] = bg & 255 | ||||||
|  |         self._colormap[2] = fg>>8 | ||||||
|  |         self._colormap[3] = fg & 255 | ||||||
|  | 
 | ||||||
|  |     def set_pos(self,x,y): | ||||||
|  |         self._x = x | ||||||
|  |         self._y = y | ||||||
|  | 
 | ||||||
|  |     def reset_scroll(self): | ||||||
|  |         self.scrolling = False | ||||||
|  |         self._scroll = 0 | ||||||
|  |         self.scroll(0) | ||||||
|  | 
 | ||||||
|  |     def set_font(self, font): | ||||||
|  |         self._font = font | ||||||
|  | 
 | ||||||
|  |     def init(self): | ||||||
|  |         for command, data in ( | ||||||
|  |             (_RDDSDR, b"\x03\x80\x02"), | ||||||
|  |             (_PWCRTLB, b"\x00\xc1\x30"), | ||||||
|  |             (_PWRONCTRL, b"\x64\x03\x12\x81"), | ||||||
|  |             (_DTCTRLA, b"\x85\x00\x78"), | ||||||
|  |             (_PWCTRLA, b"\x39\x2c\x00\x34\x02"), | ||||||
|  |             (_PRCTRL, b"\x20"), | ||||||
|  |             (_DTCTRLB, b"\x00\x00"), | ||||||
|  |             (_PWCTRL1, b"\x23"), | ||||||
|  |             (_PWCTRL2, b"\x10"), | ||||||
|  |             (_VMCTRL1, b"\x3e\x28"), | ||||||
|  |             (_VMCTRL2, b"\x86")): | ||||||
|  |             self._write(command, data) | ||||||
|  | 
 | ||||||
|  |         if self.rotation == 0:                  # 0 deg | ||||||
|  |             self._write(_MADCTL, b"\x48") | ||||||
|  |             self.width = self._init_height | ||||||
|  |             self.height = self._init_width | ||||||
|  |         elif self.rotation == 1:                # 90 deg | ||||||
|  |             self._write(_MADCTL, b"\x28") | ||||||
|  |             self.width = self._init_width | ||||||
|  |             self.height = self._init_height | ||||||
|  |         elif self.rotation == 2:                # 180 deg | ||||||
|  |             self._write(_MADCTL, b"\x88") | ||||||
|  |             self.width = self._init_height | ||||||
|  |             self.height = self._init_width | ||||||
|  |         elif self.rotation == 3:                # 270 deg | ||||||
|  |             self._write(_MADCTL, b"\xE8") | ||||||
|  |             self.width = self._init_width | ||||||
|  |             self.height = self._init_height | ||||||
|  |         elif self.rotation == 4:                # Mirrored + 0 deg | ||||||
|  |             self._write(_MADCTL, b"\xC8") | ||||||
|  |             self.width = self._init_height | ||||||
|  |             self.height = self._init_width | ||||||
|  |         elif self.rotation == 5:                # Mirrored + 90 deg | ||||||
|  |             self._write(_MADCTL, b"\x68") | ||||||
|  |             self.width = self._init_width | ||||||
|  |             self.height = self._init_height | ||||||
|  |         elif self.rotation == 6:                # Mirrored + 180 deg | ||||||
|  |             self._write(_MADCTL, b"\x08") | ||||||
|  |             self.width = self._init_height | ||||||
|  |             self.height = self._init_width | ||||||
|  |         elif self.rotation == 7:                # Mirrored + 270 deg | ||||||
|  |             self._write(_MADCTL, b"\xA8") | ||||||
|  |             self.width = self._init_width | ||||||
|  |             self.height = self._init_height | ||||||
|  |         else: | ||||||
|  |             self._write(_MADCTL, b"\x08") | ||||||
|  | 
 | ||||||
|  |         for command, data in ( | ||||||
|  |             (_PIXSET, b"\x55"), | ||||||
|  |             (_FRMCTR1, b"\x00\x18"), | ||||||
|  |             (_DISCTRL, b"\x08\x82\x27"), | ||||||
|  |             (_ENA3G, b"\x00"), | ||||||
|  |             (_GAMSET, b"\x01"), | ||||||
|  |             (_PGAMCTRL, b"\x0f\x31\x2b\x0c\x0e\x08\x4e\xf1\x37\x07\x10\x03\x0e\x09\x00"), | ||||||
|  |             (_NGAMCTRL, b"\x00\x0e\x14\x03\x11\x07\x31\xc1\x48\x08\x0f\x0c\x31\x36\x0f")): | ||||||
|  |             self._write(command, data) | ||||||
|  |         self._write(_SLPOUT) | ||||||
|  |         time.sleep_ms(120) | ||||||
|  |         self._write(_DISPON) | ||||||
|  | 
 | ||||||
|  |     def reset(self): | ||||||
|  |         self.rst(0) | ||||||
|  |         time.sleep_ms(50) | ||||||
|  |         self.rst(1) | ||||||
|  |         time.sleep_ms(50) | ||||||
|  | 
 | ||||||
|  |     def _write(self, command, data=None): | ||||||
|  |         self.dc(0) | ||||||
|  |         self.cs(0) | ||||||
|  |         self.spi.write(bytearray([command])) | ||||||
|  |         self.cs(1) | ||||||
|  |         if data is not None: | ||||||
|  |             self._data(data) | ||||||
|  | 
 | ||||||
|  |     def _data(self, data): | ||||||
|  |         self.dc(1) | ||||||
|  |         self.cs(0) | ||||||
|  |         self.spi.write(data) | ||||||
|  |         self.cs(1) | ||||||
|  | 
 | ||||||
|  |     def _writeblock(self, x0, y0, x1, y1, data=None): | ||||||
|  |         self._write(_CASET, ustruct.pack(">HH", x0, x1)) | ||||||
|  |         self._write(_PASET, ustruct.pack(">HH", y0, y1)) | ||||||
|  |         self._write(_RAMWR, data) | ||||||
|  | 
 | ||||||
|  |     def _readblock(self, x0, y0, x1, y1, data=None): | ||||||
|  |         self._write(_CASET, ustruct.pack(">HH", x0, x1)) | ||||||
|  |         self._write(_PASET, ustruct.pack(">HH", y0, y1)) | ||||||
|  |         if data is None: | ||||||
|  |             return self._read(_RAMRD, (x1 - x0 + 1) * (y1 - y0 + 1) * 3) | ||||||
|  | 
 | ||||||
|  |     def _read(self, command, count): | ||||||
|  |         self.dc(0) | ||||||
|  |         self.cs(0) | ||||||
|  |         self.spi.write(bytearray([command])) | ||||||
|  |         data = self.spi.read(count) | ||||||
|  |         self.cs(1) | ||||||
|  |         return data | ||||||
|  | 
 | ||||||
|  |     def pixel(self, x, y, color=None): | ||||||
|  |         if color is None: | ||||||
|  |             r, b, g = self._readblock(x, y, x, y) | ||||||
|  |             return color565(r, g, b) | ||||||
|  |         if not 0 <= x < self.width or not 0 <= y < self.height: | ||||||
|  |             return | ||||||
|  |         self._writeblock(x, y, x, y, ustruct.pack(">H", color)) | ||||||
|  | 
 | ||||||
|  |     def fill_rectangle(self, x, y, w, h, color=None): | ||||||
|  |         x = min(self.width - 1, max(0, x)) | ||||||
|  |         y = min(self.height - 1, max(0, y)) | ||||||
|  |         w = min(self.width - x, max(1, w)) | ||||||
|  |         h = min(self.height - y, max(1, h)) | ||||||
|  |         if color: | ||||||
|  |             color = ustruct.pack(">H", color) | ||||||
|  |         else: | ||||||
|  |             color = self._colormap[0:2] #background | ||||||
|  |         for i in range(_CHUNK): | ||||||
|  |             self._buf[2*i]=color[0]; self._buf[2*i+1]=color[1] | ||||||
|  |         chunks, rest = divmod(w * h, _CHUNK) | ||||||
|  |         self._writeblock(x, y, x + w - 1, y + h - 1, None) | ||||||
|  |         if chunks: | ||||||
|  |             for count in range(chunks): | ||||||
|  |                 self._data(self._buf) | ||||||
|  |         if rest != 0: | ||||||
|  |             mv = memoryview(self._buf) | ||||||
|  |             self._data(mv[:rest*2]) | ||||||
|  | 
 | ||||||
|  |     def erase(self): | ||||||
|  |         self.fill_rectangle(0, 0, self.width, self.height) | ||||||
|  | 
 | ||||||
|  |     def blit(self, bitbuff, x, y, w, h): | ||||||
|  |         x = min(self.width - 1, max(0, x)) | ||||||
|  |         y = min(self.height - 1, max(0, y)) | ||||||
|  |         w = min(self.width - x, max(1, w)) | ||||||
|  |         h = min(self.height - y, max(1, h)) | ||||||
|  |         chunks, rest = divmod(w * h, _CHUNK) | ||||||
|  |         self._writeblock(x, y, x + w - 1, y + h - 1, None) | ||||||
|  |         written = 0 | ||||||
|  |         for iy in range(h): | ||||||
|  |             for ix in range(w): | ||||||
|  |                 index = ix+iy*w - written | ||||||
|  |                 if index >=_CHUNK: | ||||||
|  |                     self._data(self._buf) | ||||||
|  |                     written += _CHUNK | ||||||
|  |                     index   -= _CHUNK | ||||||
|  |                 c = bitbuff.pixel(ix,iy) | ||||||
|  |                 self._buf[index*2] = self._colormap[c*2] | ||||||
|  |                 self._buf[index*2+1] = self._colormap[c*2+1] | ||||||
|  |         rest = w*h - written | ||||||
|  |         if rest != 0: | ||||||
|  |             mv = memoryview(self._buf) | ||||||
|  |             self._data(mv[:rest*2]) | ||||||
|  | 
 | ||||||
|  |     def chars(self, str, x, y): | ||||||
|  |         str_w  = self._font.get_width(str) | ||||||
|  |         div, rem = divmod(self._font.height(),8) | ||||||
|  |         nbytes = div+1 if rem else div | ||||||
|  |         buf = bytearray(str_w * nbytes) | ||||||
|  |         pos = 0 | ||||||
|  |         for ch in str: | ||||||
|  |             glyph, char_w = self._font.get_ch(ch) | ||||||
|  |             for row in range(nbytes): | ||||||
|  |                 index = row*str_w + pos | ||||||
|  |                 for i in range(char_w): | ||||||
|  |                     buf[index+i] = glyph[nbytes*i+row] | ||||||
|  |             pos += char_w | ||||||
|  |         fb = framebuf.FrameBuffer(buf,str_w, self._font.height(), framebuf.MONO_VLSB) | ||||||
|  |         self.blit(fb,x,y,str_w,self._font.height()) | ||||||
|  |         return x+str_w | ||||||
|  | 
 | ||||||
|  |     def scroll(self, dy): | ||||||
|  |         self._scroll = (self._scroll + dy) % self.height | ||||||
|  |         self._write(_VSCRSADD, ustruct.pack(">H", self._scroll)) | ||||||
|  | 
 | ||||||
|  |     def next_line(self, cury, char_h): | ||||||
|  |         global scrolling | ||||||
|  |         if not self.scrolling: | ||||||
|  |             res = cury + char_h | ||||||
|  |             self.scrolling = (res >= self.height) | ||||||
|  |         if self.scrolling: | ||||||
|  |             self.scroll(char_h) | ||||||
|  |             res = (self.height - char_h + self._scroll)%self.height | ||||||
|  |             self.fill_rectangle(0, res, self.width, self._font.height()) | ||||||
|  |         return res | ||||||
|  | 
 | ||||||
|  |     def write(self, text): #does character wrap, compatible with stream output | ||||||
|  |         curx = self._x; cury = self._y | ||||||
|  |         char_h = self._font.height() | ||||||
|  |         width = 0 | ||||||
|  |         written = 0 | ||||||
|  |         for pos, ch in enumerate(text): | ||||||
|  |             if ch == '\n': | ||||||
|  |                 if pos>0: | ||||||
|  |                     self.chars(text[written:pos],curx,cury) | ||||||
|  |                 curx = 0; written = pos+1; width = 0 | ||||||
|  |                 cury = self.next_line(cury,char_h) | ||||||
|  |             else: | ||||||
|  |                 char_w = self._font.get_width(ch) | ||||||
|  |                 if curx + width + char_w >= self.width: | ||||||
|  |                     self.chars(text[written:pos], curx,cury) | ||||||
|  |                     curx = 0 ; written = pos; width = char_h | ||||||
|  |                     cury = self.next_line(cury,char_h) | ||||||
|  |                 else: | ||||||
|  |                     width += char_w | ||||||
|  |         if written<len(text): | ||||||
|  |             curx = self.chars(text[written:], curx,cury) | ||||||
|  |         self._x = curx; self._y = cury | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     def print(self, text): #does word wrap, leaves self._x unchanged | ||||||
|  |         cury = self._y; curx = self._x | ||||||
|  |         char_h = self._font.height() | ||||||
|  |         char_w = self._font.max_width() | ||||||
|  |         lines = text.split('\n') | ||||||
|  |         for line in lines: | ||||||
|  |             words = line.split(' ') | ||||||
|  |             for word in words: | ||||||
|  |                 if curx + self._font.get_width(word) >= self.width: | ||||||
|  |                     curx = self._x; cury = self.next_line(cury,char_h) | ||||||
|  |                     while self._font.get_width(word) > self.width: | ||||||
|  |                         self.chars(word[:self.width//char_w],curx,cury) | ||||||
|  |                         word = word[self.width//char_w:] | ||||||
|  |                         cury = self.next_line(cury,char_h) | ||||||
|  |                 if len(word)>0: | ||||||
|  |                     curx = self.chars(word+' ', curx,cury) | ||||||
|  |             curx = self._x; cury = self.next_line(cury,char_h) | ||||||
|  |         self._y = cury | ||||||
							
								
								
									
										24
									
								
								src/m5stack.py
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										24
									
								
								src/m5stack.py
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,24 @@ | ||||||
|  | 
 | ||||||
|  | # This file is part of MicroPython M5Stack package | ||||||
|  | # Copyright (c) 2017 Mika Tuupola | ||||||
|  | # | ||||||
|  | # Licensed under the MIT license: | ||||||
|  | #   http://www.opensource.org/licenses/mit-license.php | ||||||
|  | # | ||||||
|  | # Project home: | ||||||
|  | #   https://github.com/tuupola/micropython-m5stacj | ||||||
|  | 
 | ||||||
|  | from micropython import const | ||||||
|  | 
 | ||||||
|  | BUTTON_A_PIN = const(39) | ||||||
|  | BUTTON_B_PIN = const(38) | ||||||
|  | BUTTON_C_PIN = const(37) | ||||||
|  | SPEAKER_PIN = const(25) | ||||||
|  | 
 | ||||||
|  | TFT_LED_PIN = const(32) | ||||||
|  | TFT_DC_PIN = const(27) | ||||||
|  | TFT_CS_PIN = const(14) | ||||||
|  | TFT_MOSI_PIN = const(23) | ||||||
|  | TFT_CLK_PIN = const(18) | ||||||
|  | TFT_RST_PIN = const(33) | ||||||
|  | TFT_MISO_PIN = const(19) | ||||||
							
								
								
									
										365
									
								
								src/main.py
									
										
									
									
									
								
							
							
						
						
									
										365
									
								
								src/main.py
									
										
									
									
									
								
							|  | @ -1,299 +1,128 @@ | ||||||
| from machine import Pin, I2C, Timer, UART | # test of printing multiple fonts to the ILI9341 on an M5Stack using H/W SP | ||||||
| import uasyncio | # MIT License; Copyright (c) 2017 Jeffrey N. Magee | ||||||
| import json |  | ||||||
| 
 | 
 | ||||||
| import ssd1306 | from ili934xnew import ILI9341, color565 | ||||||
|  | from machine import Pin, SPI,Timer | ||||||
|  | import m5stack | ||||||
|  | import tt14 | ||||||
|  | import glcdfont | ||||||
|  | import tt14 | ||||||
|  | import tt24 | ||||||
|  | import tt32 | ||||||
| from rotary_irq_esp import RotaryIRQ | from rotary_irq_esp import RotaryIRQ | ||||||
| from dshot import Dshot | fonts = [glcdfont,tt14,tt24,tt32] | ||||||
| from pid import PID |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def splash(): |  | ||||||
|     # display.fill(0) |  | ||||||
|     # display.fill_rect(0, 0, 32, 32, 1) |  | ||||||
|     # display.fill_rect(2, 2, 28, 28, 0) |  | ||||||
|     # display.vline(9, 8, 22, 1) |  | ||||||
|     # display.vline(16, 2, 22, 1) |  | ||||||
|     # display.vline(23, 8, 22, 1) |  | ||||||
|     # display.fill_rect(26, 24, 2, 4, 1) |  | ||||||
|     # display.text("MicroPython", 40, 0, 1) |  | ||||||
|     # display.text("SSD1306", 40, 12, 1) |  | ||||||
|     # display.text("OLED 128x64", 40, 24, 1) |  | ||||||
| 
 |  | ||||||
|     display.fill(0) |  | ||||||
|     display.text("SPIN", 34, 4, 1) |  | ||||||
|     display.text("COATER", 50, 14, 1) |  | ||||||
| 
 |  | ||||||
|     display.show() |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def start_view(state, rotary): |  | ||||||
|     display.text("SPIN", 34, 4, 1) |  | ||||||
|     display.text("COATER", 50, 14, 1) |  | ||||||
| 
 |  | ||||||
|     before = "> " if rotary.value() == 0 else "  " |  | ||||||
|     display.text(before + "Edit", 12, 36, 1) |  | ||||||
|     before = "> " if rotary.value() == 1 else "  " |  | ||||||
|     display.text(before + "Start", 12, 46, 1) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def draw_edit_menu(state, rotary): |  | ||||||
|     display.text("Deposit speed:", 0, 0, 1) |  | ||||||
|     display.text("{: >{w}} RPM".format(config["deposit_rpm"], w=5), 56, 10, 1) |  | ||||||
|     display.text("Coating speed:", 0, 21, 1) |  | ||||||
|     display.text("{: >{w}} RPM".format(config["coating_rpm"], w=5), 56, 31, 1) |  | ||||||
|     display.text("Coating time:", 0, 42, 1) |  | ||||||
|     display.text("{: >{w}} sec".format(config["coating_time"], w=5), 56, 52, 1) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def edit_deposit_view(state, rotary): |  | ||||||
|     config["deposit_rpm"] = rotary.value() * 100 |  | ||||||
|     draw_edit_menu(state, rotary) |  | ||||||
|     display.text(">", 40, 10, 1) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def edit_coating_rpm_view(state, rotary): |  | ||||||
|     config["coating_rpm"] = rotary.value() * 100 |  | ||||||
|     draw_edit_menu(state, rotary) |  | ||||||
|     display.text(">", 40, 32, 1) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def edit_coating_time_view(state, rotary): |  | ||||||
|     config["coating_time"] = rotary.value() |  | ||||||
|     draw_edit_menu(state, rotary) |  | ||||||
|     display.text(">", 40, 54, 1) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def draw_rpm(rpm): |  | ||||||
|     display.text("RPM:{: >{w}.0f}".format(rpm, w=5), 30, 27, 1) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def deposit_view(state, rotary): |  | ||||||
|     display.fill_rect(0, 0, 127, 14, 1) |  | ||||||
|     display.text("Deposit", 36, 3, 0) |  | ||||||
|     draw_rpm(state["rpm"]) |  | ||||||
|     display.text("Press to", 32, 42, 1) |  | ||||||
|     display.text("continue", 32, 52, 1) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def coating_view(state, rotary): |  | ||||||
|     display.fill_rect(0, 0, 127, 14, 1) |  | ||||||
|     display.text("Coating", 36, 3, 0) |  | ||||||
|     draw_rpm(state["rpm"]) |  | ||||||
|     display.text("{: >{w}} sec".format(state["timer"], w=4), 30, 48, 1) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def decode_ESC_telemetry(data, motor_poles=14): |  | ||||||
|     if len(data) > 10: |  | ||||||
|         # use latest telemetry |  | ||||||
|         data = data[-10:] |  | ||||||
| 
 |  | ||||||
|     temperature = int(data[0])  # degrees Celsius |  | ||||||
|     voltage = int((data[1] << 8) | data[2]) * 0.01  # Volt |  | ||||||
|     current = ( |  | ||||||
|         int((data[3] << 8) | data[4]) * 0.01 |  | ||||||
|     )  # Amps, only available if the ESC has a current meter |  | ||||||
|     consumption = int( |  | ||||||
|         (data[5] << 8) | data[6] |  | ||||||
|     )  # mAh, only available if the ESC has a current meter |  | ||||||
|     erpm = int((data[7] << 8) | data[8]) * 100 |  | ||||||
|     rpm = erpm / (motor_poles / 2) |  | ||||||
|     crc = data[9] |  | ||||||
| 
 |  | ||||||
|     # print("         Temp (C):", temperature) |  | ||||||
|     # print("      Voltage (V):", voltage) |  | ||||||
|     # print("      Current (A):", current) |  | ||||||
|     # print("Consumption (mAh):", consumption) |  | ||||||
|     # print("             Erpm:", erpm) |  | ||||||
|     # print("              RPM:", rpm) |  | ||||||
|     # print("              CRC:", crc) |  | ||||||
|     # print() |  | ||||||
| 
 |  | ||||||
|     return temperature, voltage, current, consumption, erpm, rpm |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| async def update_display(): |  | ||||||
|     global state |  | ||||||
|     global rotary |  | ||||||
|     while True: |  | ||||||
|         display.fill(0) |  | ||||||
|         state["view"](state, rotary) |  | ||||||
|         display.show() |  | ||||||
|         await uasyncio.sleep_ms(33) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| async def update_motor(): |  | ||||||
|     global state |  | ||||||
|     dshot = Dshot(pin=Pin(18)) |  | ||||||
|     rpm_pid = PID( |  | ||||||
|         Kp=config["PID"]["Kp"], |  | ||||||
|         Ki=config["PID"]["Ki"], |  | ||||||
|         Kd=config["PID"]["Kd"], |  | ||||||
|         setpoint=0, |  | ||||||
|         sample_time=None, |  | ||||||
|         output_limits=(0.0, 1.0), |  | ||||||
|         # proportional_on_measurement=True, |  | ||||||
|     ) |  | ||||||
|     while True: |  | ||||||
|         rpm_pid.setpoint = state["target_rpm"] |  | ||||||
| 
 |  | ||||||
|         # read ESC telemetry |  | ||||||
|         if uart.any() >= 10: |  | ||||||
|             telemetry = decode_ESC_telemetry(uart.read()) |  | ||||||
|             if telemetry is not None: |  | ||||||
|                 state["rpm"] = telemetry[5] |  | ||||||
|                 throttle = rpm_pid(state["rpm"]) |  | ||||||
|                 # print( |  | ||||||
|                 #     "Throttle:", |  | ||||||
|                 #     throttle, |  | ||||||
|                 #     "pid components:", |  | ||||||
|                 #     rpm_pid.components, |  | ||||||
|                 #     "RPM:", |  | ||||||
|                 #     state["rpm"], |  | ||||||
|                 # ) |  | ||||||
| 
 |  | ||||||
|         if state["target_rpm"] == 0 and state["rpm"] < 1000: |  | ||||||
|             throttle = 0 |  | ||||||
|             rpm_pid.reset() |  | ||||||
|         dshot.set_throttle(throttle) |  | ||||||
| 
 |  | ||||||
|         await uasyncio.sleep_ms(1) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def debounce_button(p): | def debounce_button(p): | ||||||
|     p.irq(trigger=Pin.IRQ_FALLING, handler=None)  # remove irq |     p.irq(trigger=Pin.IRQ_FALLING, handler=None)  # remove irq | ||||||
|     timer0 = Timer(0) |     timer0 = Timer(0) | ||||||
|  |     print("Button debounced!") | ||||||
|     timer0.init(period=20, mode=Timer.ONE_SHOT, callback=lambda t: on_button_press(p)) |     timer0.init(period=20, mode=Timer.ONE_SHOT, callback=lambda t: on_button_press(p)) | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| def on_button_press(p): | def on_button_press(p): | ||||||
|     p.irq(trigger=Pin.IRQ_FALLING, handler=debounce_button)  # restore irq |     p.irq(trigger=Pin.IRQ_FALLING, handler=debounce_button)  # restore irq | ||||||
|  |     print("Button pressed") | ||||||
|     if p.value() == 1:  # debounce |     if p.value() == 1:  # debounce | ||||||
|         return |         return | ||||||
|     global state |      | ||||||
|     global config |     #     return | ||||||
|     global rotary |     # global state | ||||||
|     if state["view"] == start_view: |     # global config | ||||||
|         if rotary.value() == 0: |     # global rotary | ||||||
|             state["view"] = edit_deposit_view |     # if state["view"] == start_view: | ||||||
|             rotary.set( |     #     if rotary.value() == 0: | ||||||
|                 min_val=0, |     #         state["view"] = edit_deposit_view | ||||||
|                 max_val=1000, |     #         rotary.set( | ||||||
|                 range_mode=RotaryIRQ.RANGE_BOUNDED, |     #             min_val=0, | ||||||
|                 value=int(0.01 * config["deposit_rpm"]), |     #             max_val=1000, | ||||||
|             ) |     #             range_mode=RotaryIRQ.RANGE_BOUNDED, | ||||||
|             return |     #             value=int(0.01 * config["deposit_rpm"]), | ||||||
|         if rotary.value() == 1: |     #         ) | ||||||
|             state["view"] = deposit_view |     #         return | ||||||
|             state["target_rpm"] = config["deposit_rpm"] |     #     if rotary.value() == 1: | ||||||
|             return |     #         state["view"] = deposit_view | ||||||
|     if state["view"] == edit_deposit_view: |     #         state["target_rpm"] = config["deposit_rpm"] | ||||||
|         state["view"] = edit_coating_rpm_view |     #         return | ||||||
|         rotary.set( |     # if state["view"] == edit_deposit_view: | ||||||
|             min_val=0, |     #     state["view"] = edit_coating_rpm_view | ||||||
|             max_val=1000, |     #     rotary.set( | ||||||
|             range_mode=RotaryIRQ.RANGE_BOUNDED, |     #         min_val=0, | ||||||
|             value=int(0.01 * config["coating_rpm"]), |     #         max_val=1000, | ||||||
|         ) |     #         range_mode=RotaryIRQ.RANGE_BOUNDED, | ||||||
|         return |     #         value=int(0.01 * config["coating_rpm"]), | ||||||
|     if state["view"] == edit_coating_rpm_view: |     #     ) | ||||||
|         state["view"] = edit_coating_time_view |     #     return | ||||||
|         rotary.set( |     # if state["view"] == edit_coating_rpm_view: | ||||||
|             min_val=0, |     #     state["view"] = edit_coating_time_view | ||||||
|             max_val=9999, |     #     rotary.set( | ||||||
|             range_mode=RotaryIRQ.RANGE_BOUNDED, |     #         min_val=0, | ||||||
|             value=config["coating_time"], |     #         max_val=9999, | ||||||
|         ) |     #         range_mode=RotaryIRQ.RANGE_BOUNDED, | ||||||
|         return |     #         value=config["coating_time"], | ||||||
|     if state["view"] == edit_coating_time_view: |     #     ) | ||||||
|         save_config() |     #     return | ||||||
|         rotary.set(min_val=0, max_val=1, range_mode=RotaryIRQ.RANGE_BOUNDED, value=0) |     # if state["view"] == edit_coating_time_view: | ||||||
|         state["view"] = start_view |     #     save_config() | ||||||
|         return |     #     rotary.set(min_val=0, max_val=1, range_mode=RotaryIRQ.RANGE_BOUNDED, value=0) | ||||||
|     if state["view"] == deposit_view: |     #     state["view"] = start_view | ||||||
|         state["view"] = coating_view |     #     return | ||||||
|         start_coating(state) |     # if state["view"] == deposit_view: | ||||||
|         return |     #     state["view"] = coating_view | ||||||
|     if state["view"] == coating_view: |     #     start_coating(state) | ||||||
|         stop_coating() |     #     return | ||||||
|         return |     # if state["view"] == coating_view: | ||||||
|  |     #     stop_coating() | ||||||
|  |     #     return | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def start_coating(state): |  | ||||||
|     global timer1 |  | ||||||
|     global timer2 |  | ||||||
| 
 | 
 | ||||||
|     state["timer"] = config["coating_time"] | text = 'Now is the time for all good men to come to the aid of the party.' | ||||||
| 
 | 
 | ||||||
|     timer1.init( | power = Pin(m5stack.TFT_LED_PIN, Pin.OUT) | ||||||
|         period=config["coating_time"] * 1000, | power.value(1) | ||||||
|         mode=Timer.ONE_SHOT, |  | ||||||
|         callback=lambda t: stop_coating(), |  | ||||||
|     ) |  | ||||||
| 
 |  | ||||||
|     def decrement_timer(t): |  | ||||||
|         state["timer"] -= 1 |  | ||||||
| 
 |  | ||||||
|     timer2.init(period=1000, mode=Timer.PERIODIC, callback=decrement_timer) |  | ||||||
| 
 |  | ||||||
|     # state["throttle"] = 0.10 |  | ||||||
|     state["target_rpm"] = config["coating_rpm"] |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def stop_coating(): | # No need to change the software. It's just a matter of different names.. Use this translation: | ||||||
|     global state |  | ||||||
|     global rotary |  | ||||||
|     global timer1 |  | ||||||
|     global timer2 |  | ||||||
|     timer1.deinit() |  | ||||||
|     timer2.deinit() |  | ||||||
|     state["target_rpm"] = 0 |  | ||||||
|     rotary.set(min_val=0, max_val=1, range_mode=RotaryIRQ.RANGE_BOUNDED, value=0) |  | ||||||
|     state["view"] = start_view |  | ||||||
| 
 | 
 | ||||||
|  | # SDO(MISO)	<not used> | ||||||
|  | # LED		BL | ||||||
|  | # SCK		CLK/SCK | ||||||
|  | # SDI(MOSI)	DIN/SDA | ||||||
|  | # DC		D/C (A0) | ||||||
|  | # RESET		RST | ||||||
|  | # CS		CS | ||||||
|  | # GND		GND | ||||||
|  | # VCC		VCC | ||||||
|  | print("BOOOOOOTTTT") | ||||||
|  | spi = SPI( | ||||||
|  |     2, | ||||||
|  |     baudrate=40000000, | ||||||
|  |     miso=Pin(m5stack.TFT_MISO_PIN), | ||||||
|  |     mosi=Pin(m5stack.TFT_MOSI_PIN), | ||||||
|  |     sck=Pin(m5stack.TFT_CLK_PIN)) | ||||||
| 
 | 
 | ||||||
| def save_config(): | display = ILI9341( | ||||||
|     global config |     spi, | ||||||
|     with open("config.json", "w") as f: |     cs=Pin(m5stack.TFT_CS_PIN), | ||||||
|         json.dump(config, f) |     dc=Pin(m5stack.TFT_DC_PIN), | ||||||
| 
 |     rst=Pin(m5stack.TFT_RST_PIN), | ||||||
| 
 |     w=128, | ||||||
| # using default address 0x3c |     h=160, | ||||||
| i2c = I2C(1, sda=Pin(21), scl=Pin(22)) |     r=3) | ||||||
| display = ssd1306.SSD1306_I2C(128, 64, i2c) |  | ||||||
| display.rotate(0) |  | ||||||
| 
 |  | ||||||
| timer1 = Timer(1) |  | ||||||
| timer2 = Timer(2) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| splash() |  | ||||||
| 
 |  | ||||||
| rotary = RotaryIRQ( | rotary = RotaryIRQ( | ||||||
|     pin_num_clk=14, |     pin_num_clk=25, | ||||||
|     pin_num_dt=13, |     pin_num_dt=13, | ||||||
|     min_val=0, |     min_val=0, | ||||||
|     max_val=1, |     max_val=1, | ||||||
|     range_mode=RotaryIRQ.RANGE_BOUNDED, |     range_mode=RotaryIRQ.RANGE_BOUNDED, | ||||||
|     pull_up=True, |     pull_up=True, | ||||||
| ) | ) | ||||||
| 
 | button = Pin(15, Pin.IN, Pin.PULL_UP) | ||||||
| button = Pin(19, Pin.IN, Pin.PULL_UP) |  | ||||||
| button.irq(trigger=Pin.IRQ_FALLING, handler=on_button_press) | button.irq(trigger=Pin.IRQ_FALLING, handler=on_button_press) | ||||||
| 
 | 
 | ||||||
| uart = UART(1, baudrate=115200, rx=5)  # to receive ESC telemetry |  | ||||||
| 
 | 
 | ||||||
| state = { | display.erase() | ||||||
|     "view": start_view, | display.set_pos(0,0) | ||||||
|     "rpm": 0, | for ff in fonts: | ||||||
|     "target_rpm": 0, |     display.set_font(ff) | ||||||
|     "timer": 0, |     display.print(text) | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| with open("config.json", "r") as f: |  | ||||||
|     config = json.load(f) |  | ||||||
| 
 | 
 | ||||||
| event_loop = uasyncio.get_event_loop() |  | ||||||
| event_loop.create_task(update_display()) |  | ||||||
| event_loop.create_task(update_motor()) |  | ||||||
| event_loop.run_forever() |  | ||||||
|  |  | ||||||
|  | @ -90,7 +90,7 @@ class Rotary(object): | ||||||
|             max_val=None, reverse=None, range_mode=None): |             max_val=None, reverse=None, range_mode=None): | ||||||
|         # disable DT and CLK pin interrupts |         # disable DT and CLK pin interrupts | ||||||
|         self._hal_disable_irq() |         self._hal_disable_irq() | ||||||
| 
 |         #print("SETTING VALUE!") | ||||||
|         if value is not None: |         if value is not None: | ||||||
|             self._value = value |             self._value = value | ||||||
|         if min_val is not None: |         if min_val is not None: | ||||||
|  | @ -124,6 +124,7 @@ class Rotary(object): | ||||||
|         self._listener.remove(l) |         self._listener.remove(l) | ||||||
|          |          | ||||||
|     def _process_rotary_pins(self, pin): |     def _process_rotary_pins(self, pin): | ||||||
|  |         print(self._value) | ||||||
|         old_value = self._value |         old_value = self._value | ||||||
|         clk_dt_pins = (self._hal_get_clk_value() << |         clk_dt_pins = (self._hal_get_clk_value() << | ||||||
|                        1) | self._hal_get_dt_value() |                        1) | self._hal_get_dt_value() | ||||||
|  |  | ||||||
							
								
								
									
										16
									
								
								src/rotations_test.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								src/rotations_test.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,16 @@ | ||||||
|  | from ili934xnew import ILI9341, color565 | ||||||
|  | from machine import Pin, SPI | ||||||
|  | import tt14 | ||||||
|  | 
 | ||||||
|  | text = 'F' | ||||||
|  | spi = SPI(2, baudrate=20000000, miso=Pin(19),mosi=Pin(23), sck=Pin(18)) | ||||||
|  | display = ILI9341(spi, cs=Pin(2), dc=Pin(27), rst=Pin(33), w=320, h=240, r=0) | ||||||
|  | display.erase() | ||||||
|  | display.set_font(tt14) | ||||||
|  | display.set_pos(0,0) | ||||||
|  | display.print(text) | ||||||
|  | display.set_pos(0,20) | ||||||
|  | display.print(text) | ||||||
|  | display.set_pos(40,20) | ||||||
|  | display.print(text) | ||||||
|  | 
 | ||||||
							
								
								
									
										159
									
								
								src/tt14.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										159
									
								
								src/tt14.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,159 @@ | ||||||
|  | # Code generated by font-to-py.py. | ||||||
|  | # Font: CM Sans Serif 2012.ttf | ||||||
|  | version = '0.2' | ||||||
|  | 
 | ||||||
|  | def height(): | ||||||
|  |     return 15 | ||||||
|  | 
 | ||||||
|  | def max_width(): | ||||||
|  |     return 12 | ||||||
|  | 
 | ||||||
|  | def hmap(): | ||||||
|  |     return False | ||||||
|  | 
 | ||||||
|  | def reverse(): | ||||||
|  |     return False | ||||||
|  | 
 | ||||||
|  | def monospaced(): | ||||||
|  |     return False | ||||||
|  | 
 | ||||||
|  | def min_ch(): | ||||||
|  |     return 32 | ||||||
|  | 
 | ||||||
|  | def max_ch(): | ||||||
|  |     return 126 | ||||||
|  | 
 | ||||||
|  | _font =\ | ||||||
|  | b'\x08\x00\x08\x00\x0c\x00\x8c\x07\xcc\x07\xcc\x00\x7c\x00\x38\x00'\ | ||||||
|  | b'\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\xfc\x06'\ | ||||||
|  | b'\xfc\x06\x00\x00\x05\x00\x1c\x00\x3c\x00\x00\x00\x3c\x00\x00\x00'\ | ||||||
|  | b'\x07\x00\x40\x03\xf0\x03\xf0\x03\x30\x03\xf0\x03\x30\x03\x30\x00'\ | ||||||
|  | b'\x07\x00\x30\x00\x78\x03\x6c\x02\xfc\x07\xd8\x03\x90\x03\x00\x00'\ | ||||||
|  | b'\x0b\x00\x18\x00\x3c\x00\x3c\x04\x3c\x03\xd8\x01\xf0\x03\xd8\x07'\ | ||||||
|  | b'\xc4\x06\xc0\x07\x80\x03\x00\x00\x09\x00\x80\x03\xf8\x07\x7c\x06'\ | ||||||
|  | b'\x4c\x06\xfc\x06\x98\x07\xc0\x07\xc0\x05\x00\x04\x02\x00\x1c\x00'\ | ||||||
|  | b'\x3c\x00\x04\x00\xf0\x03\xfc\x0f\x0e\x1c\x02\x10\x05\x00\x02\x10'\ | ||||||
|  | b'\x0e\x1c\xfc\x0f\xf0\x03\x00\x00\x05\x00\x0c\x00\x3c\x00\x18\x00'\ | ||||||
|  | b'\x2c\x00\x0c\x00\x07\x00\xc0\x00\xc0\x00\xf0\x03\xf0\x03\xc0\x00'\ | ||||||
|  | b'\xc0\x00\x00\x00\x03\x00\x00\x16\x00\x0e\x00\x00\x04\x00\xc0\x00'\ | ||||||
|  | b'\xc0\x00\xc0\x00\xc0\x00\x03\x00\x00\x06\x00\x06\x00\x00\x04\x00'\ | ||||||
|  | b'\x00\x06\xe0\x07\xfc\x00\x0e\x00\x08\x00\xf0\x01\xf8\x03\x1c\x07'\ | ||||||
|  | b'\x0c\x06\x1c\x07\xf8\x03\xf0\x01\x00\x00\x04\x00\x18\x00\xfc\x07'\ | ||||||
|  | b'\xfc\x07\x00\x00\x08\x00\x18\x04\x1c\x07\x8c\x06\x8c\x06\x4c\x06'\ | ||||||
|  | b'\x7c\x06\x38\x06\x00\x00\x07\x00\x08\x02\x0c\x06\x0c\x06\x6c\x06'\ | ||||||
|  | b'\x6c\x06\xfc\x07\xd8\x03\x07\x00\x80\x01\xe0\x01\xb0\x01\x9c\x01'\ | ||||||
|  | b'\xfc\x07\xfc\x07\x80\x01\x07\x00\x00\x02\xfc\x06\x6c\x06\x6c\x06'\ | ||||||
|  | b'\x6c\x06\xcc\x03\xc0\x03\x08\x00\xf0\x01\xf8\x03\x6c\x06\x6c\x06'\ | ||||||
|  | b'\x6c\x06\xe8\x07\xc0\x03\x00\x00\x06\x00\x0c\x00\x0c\x07\xcc\x07'\ | ||||||
|  | b'\xfc\x00\x1c\x00\x0c\x00\x07\x00\x98\x03\xfc\x07\x6c\x06\x6c\x06'\ | ||||||
|  | b'\x6c\x06\xfc\x07\x98\x03\x08\x00\x78\x02\xfc\x06\xcc\x06\xcc\x06'\ | ||||||
|  | b'\xcc\x06\xf8\x03\xf0\x01\x00\x00\x03\x00\x30\x06\x30\x06\x00\x00'\ | ||||||
|  | b'\x03\x00\x30\x16\x30\x0e\x00\x00\x06\x00\xc0\x01\xc0\x01\x60\x03'\ | ||||||
|  | b'\x60\x03\x30\x06\x00\x00\x06\x00\x60\x03\x60\x03\x60\x03\x60\x03'\ | ||||||
|  | b'\x60\x03\x60\x03\x06\x00\x30\x06\x60\x03\x60\x03\x40\x01\xc0\x01'\ | ||||||
|  | b'\x00\x00\x08\x00\x08\x00\x0c\x00\x8c\x07\xcc\x07\xcc\x00\x7c\x00'\ | ||||||
|  | b'\x38\x00\x00\x00\x0b\x00\xe0\x00\xf8\x01\x18\x03\xec\x07\xbc\x07'\ | ||||||
|  | b'\xfc\x06\xfc\x07\x9c\x03\xf8\x01\xf0\x00\x00\x00\x08\x00\x00\x06'\ | ||||||
|  | b'\x80\x07\xf0\x01\x9c\x01\x8c\x01\xf8\x01\xc0\x07\x00\x07\x08\x00'\ | ||||||
|  | b'\xfc\x07\xfc\x07\x6c\x06\x6c\x06\x6c\x06\xfc\x07\xd8\x03\x00\x00'\ | ||||||
|  | b'\x09\x00\xe0\x00\xf8\x03\x18\x03\x0c\x06\x0c\x06\x0c\x06\x1c\x07'\ | ||||||
|  | b'\x18\x03\x20\x01\x09\x00\xfc\x07\xfc\x07\x0c\x06\x0c\x06\x1c\x07'\ | ||||||
|  | b'\xf8\x03\xf0\x01\x00\x00\x00\x00\x08\x00\xfc\x07\xfc\x07\x6c\x06'\ | ||||||
|  | b'\x6c\x06\x6c\x06\x6c\x06\x0c\x06\x00\x00\x07\x00\xfc\x07\xfc\x07'\ | ||||||
|  | b'\xcc\x00\xcc\x00\xcc\x00\xcc\x00\x0c\x00\x0a\x00\xe0\x01\xf8\x03'\ | ||||||
|  | b'\x18\x07\x0c\x06\x0c\x06\xcc\x06\xdc\x02\xd8\x07\xe0\x07\x00\x00'\ | ||||||
|  | b'\x09\x00\xfc\x07\xfc\x07\x60\x00\x60\x00\x60\x00\xfc\x07\xfc\x07'\ | ||||||
|  | b'\x00\x00\x00\x00\x03\x00\xfc\x07\xfc\x07\x00\x00\x07\x00\x80\x03'\ | ||||||
|  | b'\x80\x07\x00\x06\x00\x06\xfc\x07\xfc\x03\x00\x00\x08\x00\xfc\x07'\ | ||||||
|  | b'\xfc\x07\x60\x00\xf0\x00\xd8\x01\x0c\x07\x04\x06\x04\x04\x07\x00'\ | ||||||
|  | b'\xfc\x07\xfc\x07\x00\x06\x00\x06\x00\x06\x00\x06\x00\x00\x0b\x00'\ | ||||||
|  | b'\xfc\x07\xfc\x07\x3c\x00\xe0\x03\x00\x06\xe0\x03\x3c\x00\xfc\x07'\ | ||||||
|  | b'\xfc\x07\x00\x00\x00\x00\x09\x00\xfc\x07\xfc\x07\x38\x00\xe0\x00'\ | ||||||
|  | b'\x80\x03\xfc\x07\xfc\x07\x00\x00\x00\x00\x0a\x00\xf0\x01\xf8\x03'\ | ||||||
|  | b'\x1c\x07\x0c\x06\x0c\x06\x0c\x06\x1c\x07\xf8\x03\xf0\x01\x00\x00'\ | ||||||
|  | b'\x09\x00\xfc\x07\xfc\x07\xcc\x00\xcc\x00\xcc\x00\xfc\x00\x78\x00'\ | ||||||
|  | b'\x00\x00\x00\x00\x0a\x00\xf0\x01\xf8\x03\x1c\x07\x0c\x06\x8c\x06'\ | ||||||
|  | b'\x8c\x07\x1c\x07\xf8\x07\xf0\x05\x00\x00\x09\x00\xfc\x07\xfc\x07'\ | ||||||
|  | b'\xcc\x00\xcc\x00\xcc\x03\x7c\x07\x78\x04\x00\x00\x00\x00\x09\x00'\ | ||||||
|  | b'\x38\x01\x3c\x03\x4c\x06\x4c\x06\x4c\x06\x4c\x06\x98\x07\x90\x03'\ | ||||||
|  | b'\x00\x00\x07\x00\x0c\x00\x0c\x00\xfc\x07\xfc\x07\x0c\x00\x0c\x00'\ | ||||||
|  | b'\x00\x00\x09\x00\xfc\x03\xfc\x07\x00\x06\x00\x06\x00\x06\xfc\x07'\ | ||||||
|  | b'\xfc\x01\x00\x00\x00\x00\x08\x00\x0c\x00\x7c\x00\xe0\x03\x00\x07'\ | ||||||
|  | b'\x80\x07\xf8\x01\x3c\x00\x04\x00\x0b\x00\x0c\x00\xfc\x00\xe0\x07'\ | ||||||
|  | b'\x80\x07\xf8\x03\x1c\x00\xfc\x00\xc0\x07\x80\x07\xfc\x01\x1c\x00'\ | ||||||
|  | b'\x08\x00\x04\x04\x0c\x07\xb8\x03\xf0\x00\xf0\x01\x9c\x07\x0c\x06'\ | ||||||
|  | b'\x04\x04\x08\x00\x04\x00\x1c\x00\x78\x00\xe0\x07\xe0\x07\x78\x00'\ | ||||||
|  | b'\x1c\x00\x04\x00\x07\x00\x0c\x06\x0c\x07\x8c\x07\xcc\x06\x2c\x06'\ | ||||||
|  | b'\x1c\x06\x0c\x06\x04\x00\xff\x1f\xff\x1f\x03\x18\x00\x00\x04\x00'\ | ||||||
|  | b'\x0e\x00\xfe\x00\xe0\x07\x00\x07\x04\x00\x03\x18\xff\x1f\xff\x1f'\ | ||||||
|  | b'\x00\x00\x07\x00\x80\x00\xe0\x00\x7c\x00\x0c\x00\x7c\x00\xe0\x00'\ | ||||||
|  | b'\x80\x00\x0a\x00\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18\x00\x18'\ | ||||||
|  | b'\x00\x18\x00\x18\x00\x18\x00\x18\x05\x00\x04\x00\x0c\x00\x08\x00'\ | ||||||
|  | b'\x00\x00\x00\x00\x08\x00\x00\x03\xe0\x07\xb0\x06\xb0\x06\xb0\x02'\ | ||||||
|  | b'\xf0\x07\xe0\x07\x00\x00\x09\x00\xfe\x07\xfe\x07\x30\x02\x30\x06'\ | ||||||
|  | b'\x30\x06\xe0\x07\xc0\x01\x00\x00\x00\x00\x07\x00\xc0\x01\xe0\x03'\ | ||||||
|  | b'\x30\x06\x30\x06\x30\x06\x60\x03\x40\x01\x08\x00\xc0\x01\xf0\x07'\ | ||||||
|  | b'\x30\x06\x30\x06\x30\x06\xfe\x07\xfe\x07\x00\x00\x07\x00\xc0\x01'\ | ||||||
|  | b'\xe0\x03\xb0\x07\xb0\x07\xb0\x07\xe0\x03\xc0\x01\x04\x00\x20\x00'\ | ||||||
|  | b'\xfc\x07\xfe\x07\x00\x00\x08\x00\xc0\x11\xf0\x1f\x30\x36\x30\x36'\ | ||||||
|  | b'\x20\x36\xf0\x1f\xf0\x0f\x00\x00\x08\x00\xfe\x07\xfe\x07\x30\x00'\ | ||||||
|  | b'\x30\x00\xf0\x07\xe0\x07\x00\x00\x00\x00\x03\x00\xfc\x07\xfc\x07'\ | ||||||
|  | b'\x00\x00\x03\x00\xec\x7f\xec\x3f\x00\x00\x07\x00\xfe\x07\xfe\x07'\ | ||||||
|  | b'\xc0\x00\xe0\x01\xb0\x07\x10\x06\x10\x04\x03\x00\xfe\x07\xfe\x07'\ | ||||||
|  | b'\x00\x00\x0c\x00\xf0\x07\xf0\x07\x30\x00\x30\x00\xf0\x07\xe0\x07'\ | ||||||
|  | b'\x30\x00\x30\x00\xf0\x07\xe0\x07\x00\x00\x00\x00\x08\x00\xf0\x07'\ | ||||||
|  | b'\xf0\x07\x30\x00\x30\x00\xf0\x07\xe0\x07\x00\x00\x00\x00\x08\x00'\ | ||||||
|  | b'\xc0\x01\xe0\x03\x30\x06\x30\x06\x30\x06\xe0\x03\xc0\x01\x00\x00'\ | ||||||
|  | b'\x09\x00\xf0\x3f\xf0\x3f\x30\x06\x30\x06\x30\x06\xf0\x07\xc0\x01'\ | ||||||
|  | b'\x00\x00\x00\x00\x08\x00\xc0\x01\xf0\x07\x30\x06\x30\x06\x30\x06'\ | ||||||
|  | b'\xf0\x3f\xf0\x3f\x00\x00\x04\x00\xf0\x07\xf0\x07\x30\x00\x30\x00'\ | ||||||
|  | b'\x08\x00\x60\x00\x70\x03\xb0\x07\xf0\x06\xb0\x06\xa0\x07\x00\x03'\ | ||||||
|  | b'\x00\x00\x04\x00\x30\x00\xfe\x03\xfe\x07\x00\x00\x08\x00\xf0\x03'\ | ||||||
|  | b'\xf0\x07\x00\x06\x00\x06\xf0\x07\xf0\x07\x00\x00\x00\x00\x07\x00'\ | ||||||
|  | b'\x30\x00\xf0\x00\x80\x07\x00\x06\xc0\x03\xf0\x00\x10\x00\x0a\x00'\ | ||||||
|  | b'\x30\x00\xf0\x01\x80\x07\xc0\x07\xf0\x00\xf0\x00\x80\x07\x80\x07'\ | ||||||
|  | b'\xf0\x01\x30\x00\x07\x00\x10\x04\x30\x07\xe0\x03\xc0\x01\x70\x07'\ | ||||||
|  | b'\x10\x06\x00\x04\x07\x00\x30\x00\xf0\x30\xc0\x3f\x00\x1f\xe0\x03'\ | ||||||
|  | b'\x70\x00\x10\x00\x06\x00\x30\x06\x30\x07\xb0\x07\xf0\x06\x70\x06'\ | ||||||
|  | b'\x30\x06\x05\x00\x40\x00\xbe\x0f\xbe\x0f\x00\x00\x00\x00\x04\x00'\ | ||||||
|  | b'\xfe\x07\xfe\x07\x00\x00\x00\x00\x04\x00\xbe\x0f\xbe\x0f\x40\x00'\ | ||||||
|  | b'\x00\x00\x05\x00\x04\x00\x04\x00\x04\x00\x06\x00\x04\x00' | ||||||
|  | 
 | ||||||
|  | _index =\ | ||||||
|  | b'\x00\x00\x12\x00\x1c\x00\x24\x00\x30\x00\x40\x00\x50\x00\x68\x00'\ | ||||||
|  | b'\x7c\x00\x82\x00\x8c\x00\x98\x00\xa4\x00\xb4\x00\xbc\x00\xc6\x00'\ | ||||||
|  | b'\xce\x00\xd8\x00\xea\x00\xf4\x00\x06\x01\x16\x01\x26\x01\x36\x01'\ | ||||||
|  | b'\x48\x01\x56\x01\x66\x01\x78\x01\x80\x01\x88\x01\x96\x01\xa4\x01'\ | ||||||
|  | b'\xb2\x01\xc4\x01\xdc\x01\xee\x01\x00\x02\x14\x02\x28\x02\x3a\x02'\ | ||||||
|  | b'\x4a\x02\x60\x02\x74\x02\x7c\x02\x8c\x02\x9e\x02\xae\x02\xc6\x02'\ | ||||||
|  | b'\xda\x02\xf0\x02\x04\x03\x1a\x03\x2e\x03\x42\x03\x52\x03\x66\x03'\ | ||||||
|  | b'\x78\x03\x90\x03\xa2\x03\xb4\x03\xc4\x03\xce\x03\xd8\x03\xe2\x03'\ | ||||||
|  | b'\xf2\x03\x08\x04\x14\x04\x26\x04\x3a\x04\x4a\x04\x5c\x04\x6c\x04'\ | ||||||
|  | b'\x76\x04\x88\x04\x9a\x04\xa2\x04\xaa\x04\xba\x04\xc2\x04\xdc\x04'\ | ||||||
|  | b'\xee\x04\x00\x05\x14\x05\x26\x05\x30\x05\x42\x05\x4c\x05\x5e\x05'\ | ||||||
|  | b'\x6e\x05\x84\x05\x94\x05\xa4\x05\xb2\x05\xbe\x05\xc8\x05\xd2\x05'\ | ||||||
|  | b'\xde\x05' | ||||||
|  | 
 | ||||||
|  | _mvfont = memoryview(_font) | ||||||
|  | 
 | ||||||
|  | def _chr_addr(ordch): | ||||||
|  |     offset = 2 * (ordch - 32) | ||||||
|  |     return int.from_bytes(_index[offset:offset + 2], 'little') | ||||||
|  | 
 | ||||||
|  | def get_width(s): | ||||||
|  |     width = 0 | ||||||
|  |     for ch in s: | ||||||
|  |         ordch = ord(ch) | ||||||
|  |         ordch = ordch + 1 if ordch >= 32 and ordch <= 126 else 32 | ||||||
|  |         offset = _chr_addr(ordch) | ||||||
|  |         width += int.from_bytes(_font[offset:offset + 2], 'little') | ||||||
|  |     return width | ||||||
|  | 
 | ||||||
|  | def get_ch(ch): | ||||||
|  |     ordch = ord(ch) | ||||||
|  |     ordch = ordch + 1 if ordch >= 32 and ordch <= 126 else 32 | ||||||
|  |     offset = _chr_addr(ordch) | ||||||
|  |     width = int.from_bytes(_font[offset:offset + 2], 'little') | ||||||
|  |     next_offs = _chr_addr(ordch +1) | ||||||
|  |     return _mvfont[offset + 2:next_offs], width | ||||||
|  |   | ||||||
							
								
								
									
										286
									
								
								src/tt24.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										286
									
								
								src/tt24.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,286 @@ | ||||||
|  | # Code generated by font-to-py.py. | ||||||
|  | # Font: CM Sans Serif 2012.ttf | ||||||
|  | version = '0.2' | ||||||
|  | 
 | ||||||
|  | def height(): | ||||||
|  |     return 24 | ||||||
|  | 
 | ||||||
|  | def max_width(): | ||||||
|  |     return 20 | ||||||
|  | 
 | ||||||
|  | def hmap(): | ||||||
|  |     return False | ||||||
|  | 
 | ||||||
|  | def reverse(): | ||||||
|  |     return False | ||||||
|  | 
 | ||||||
|  | def monospaced(): | ||||||
|  |     return False | ||||||
|  | 
 | ||||||
|  | def min_ch(): | ||||||
|  |     return 32 | ||||||
|  | 
 | ||||||
|  | def max_ch(): | ||||||
|  |     return 126 | ||||||
|  | 
 | ||||||
|  | _font =\ | ||||||
|  | b'\x0c\x00\xc0\x00\x00\xf0\x00\x00\xf0\x00\x00\x78\x70\x07\x38\x78'\ | ||||||
|  | b'\x07\x38\x7c\x07\x78\x1e\x00\xf0\x0f\x00\xf0\x07\x00\xc0\x03\x00'\ | ||||||
|  | b'\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ | ||||||
|  | b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00'\ | ||||||
|  | b'\x00\x02\xf8\x3f\x07\xf8\x3f\x07\xf8\x3f\x02\x00\x00\x00\x00\x00'\ | ||||||
|  | b'\x00\x08\x00\xf8\x03\x00\xf8\x03\x00\x08\x00\x00\x00\x00\x00\xf8'\ | ||||||
|  | b'\x03\x00\xf8\x03\x00\x08\x00\x00\x00\x00\x00\x0c\x00\x00\xe0\x00'\ | ||||||
|  | b'\x80\xe3\x00\x80\xf3\x03\xe0\xff\x03\xe0\xff\x00\xe0\xe3\x00\x80'\ | ||||||
|  | b'\xe3\x03\x80\xff\x03\xe0\xff\x01\xe0\xe7\x00\x80\xe3\x00\x80\x03'\ | ||||||
|  | b'\x00\x0b\x00\x00\xe0\x00\xc0\xe3\x01\xe0\xc7\x01\x70\x8e\x03\xf8'\ | ||||||
|  | b'\xef\x07\xf8\xff\x07\x70\x8c\x03\xe0\x9d\x01\xc0\xf9\x01\x00\xf0'\ | ||||||
|  | b'\x00\x00\x00\x00\x12\x00\xe0\x01\x00\xf0\x03\x00\x38\x07\x00\x38'\ | ||||||
|  | b'\x07\x04\x38\x07\x07\x38\xc7\x07\xf0\xf3\x01\xe0\x79\x00\x00\x1e'\ | ||||||
|  | b'\x00\x80\x07\x00\xe0\xe3\x01\xf8\xf0\x03\x38\x38\x07\x08\x38\x07'\ | ||||||
|  | b'\x00\x38\x07\x00\xf0\x03\x00\xe0\x01\x00\x00\x00\x0f\x00\x00\xf0'\ | ||||||
|  | b'\x00\x00\xf8\x01\xe0\xfd\x03\xf0\x8f\x07\xf8\x07\x07\x38\x0e\x07'\ | ||||||
|  | b'\x38\x1f\x07\xf8\x3f\x07\xf0\xfb\x07\xe0\xf0\x07\x00\xe0\x03\x00'\ | ||||||
|  | b'\xf8\x07\x00\xf8\x07\x00\x78\x06\x00\x00\x04\x04\x00\xf8\x03\x00'\ | ||||||
|  | b'\xf8\x03\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x7f\x00\xe0\xff'\ | ||||||
|  | b'\x03\xf8\xff\x0f\x7c\x00\x1f\x0e\x00\x38\x02\x00\x20\x02\x00\x20'\ | ||||||
|  | b'\x07\x00\x02\x00\x20\x0e\x00\x38\x7c\x00\x1f\xf8\xff\x0f\xe0\xff'\ | ||||||
|  | b'\x03\x00\x7f\x00\x00\x00\x00\x09\x00\x60\x00\x00\x60\x00\x00\x78'\ | ||||||
|  | b'\x03\x00\xf0\x01\x00\xe0\x00\x00\xf8\x03\x00\x68\x01\x00\x60\x00'\ | ||||||
|  | b'\x00\x00\x00\x00\x0c\x00\x00\x38\x00\x00\x38\x00\x00\x38\x00\x00'\ | ||||||
|  | b'\x38\x00\x80\xff\x03\x80\xff\x03\x80\xff\x03\x00\x38\x00\x00\x38'\ | ||||||
|  | b'\x00\x00\x38\x00\x00\x38\x00\x00\x00\x00\x05\x00\x00\x00\x37\x00'\ | ||||||
|  | b'\x00\x3f\x00\x00\x1f\x00\x00\x00\x00\x00\x00\x07\x00\x00\x38\x00'\ | ||||||
|  | b'\x00\x38\x00\x00\x38\x00\x00\x38\x00\x00\x38\x00\x00\x38\x00\x00'\ | ||||||
|  | b'\x38\x00\x05\x00\x00\x00\x07\x00\x00\x07\x00\x00\x07\x00\x00\x00'\ | ||||||
|  | b'\x00\x00\x00\x08\x00\x00\x00\x06\x00\xe0\x07\x00\xfc\x07\xc0\xff'\ | ||||||
|  | b'\x01\xf8\x3f\x00\xfc\x03\x00\x7c\x00\x00\x04\x00\x00\x0d\x00\x80'\ | ||||||
|  | b'\x7f\x00\xe0\xff\x01\xf0\xff\x03\xf8\xc0\x07\x38\x00\x07\x38\x00'\ | ||||||
|  | b'\x07\x38\x00\x07\xf8\xc0\x07\xf0\xff\x03\xe0\xff\x01\x80\x7f\x00'\ | ||||||
|  | b'\x00\x00\x00\x00\x00\x00\x08\x00\xc0\x01\x00\xc0\x01\x00\xe0\x01'\ | ||||||
|  | b'\x00\xf8\xff\x07\xf8\xff\x07\xf8\xff\x07\x00\x00\x00\x00\x00\x00'\ | ||||||
|  | b'\x0d\x00\xc0\x81\x07\xe0\xe1\x07\xf0\xe1\x07\x78\x70\x07\x38\x38'\ | ||||||
|  | b'\x07\x38\x38\x07\x38\x1c\x07\x78\x1e\x07\xf0\x0f\x07\xf0\x07\x07'\ | ||||||
|  | b'\xc0\x03\x07\x00\x00\x00\x00\x00\x00\x0c\x00\xc0\xc0\x00\xf0\xc0'\ | ||||||
|  | b'\x03\xf0\xc0\x03\x78\x80\x07\x38\x00\x07\x38\x0e\x07\x38\x0e\x07'\ | ||||||
|  | b'\x78\x9e\x07\xf0\xff\x03\xf0\xff\x03\xe0\xf1\x00\x00\x00\x00\x0c'\ | ||||||
|  | b'\x00\x00\xf0\x00\x00\xf8\x00\x00\xfe\x00\x00\xef\x00\xc0\xe7\x00'\ | ||||||
|  | b'\xf0\xe1\x00\xf8\xe0\x00\xf8\xff\x07\xf8\xff\x07\xf8\xff\x07\x00'\ | ||||||
|  | b'\xe0\x00\x00\xe0\x00\x0c\x00\x00\xce\x00\xf8\xcf\x03\xf8\xcf\x03'\ | ||||||
|  | b'\x38\x8e\x07\x38\x07\x07\x38\x07\x07\x38\x07\x07\x38\x8f\x07\x38'\ | ||||||
|  | b'\xfe\x03\x38\xfc\x01\x00\xf8\x00\x00\x00\x00\x0d\x00\x00\x7f\x00'\ | ||||||
|  | b'\xe0\xff\x01\xf0\xff\x03\x78\x8e\x07\x38\x07\x07\x38\x07\x07\x38'\ | ||||||
|  | b'\x07\x07\x78\x8f\x07\xf0\xfe\x03\xe0\xfc\x01\xc0\xf8\x00\x00\x00'\ | ||||||
|  | b'\x00\x00\x00\x00\x0b\x00\x38\x00\x00\x38\x00\x00\x38\xc0\x07\x38'\ | ||||||
|  | b'\xf8\x07\x38\xfe\x07\xb8\x3f\x00\xf8\x07\x00\xf8\x01\x00\xf8\x00'\ | ||||||
|  | b'\x00\x78\x00\x00\x38\x00\x00\x0c\x00\x00\xf0\x00\xe0\xf9\x01\xf0'\ | ||||||
|  | b'\xff\x03\xf0\x9f\x07\x38\x0e\x07\x38\x0e\x07\x38\x0e\x07\x38\x0e'\ | ||||||
|  | b'\x07\xf0\x9f\x07\xf0\xff\x03\xe0\xf9\x01\x00\xf0\x00\x0d\x00\xc0'\ | ||||||
|  | b'\x07\x00\xe0\x0f\x01\xf0\x1f\x03\x78\x3c\x07\x38\x38\x07\x38\x38'\ | ||||||
|  | b'\x07\x38\x38\x07\x38\x38\x07\x70\x9c\x07\xf0\xff\x03\xe0\xff\x01'\ | ||||||
|  | b'\x80\x7f\x00\x00\x00\x00\x05\x00\x00\x07\x07\x00\x07\x07\x00\x07'\ | ||||||
|  | b'\x07\x00\x00\x00\x00\x00\x00\x05\x00\x00\x07\x37\x00\x07\x3f\x00'\ | ||||||
|  | b'\x07\x1f\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x38\x00\x00\x38\x00'\ | ||||||
|  | b'\x00\x7c\x00\x00\x6c\x00\x00\xee\x00\x00\xee\x00\x00\xc7\x01\x00'\ | ||||||
|  | b'\xc7\x01\x80\x83\x03\x00\x00\x00\x0b\x00\x00\xce\x01\x00\xce\x01'\ | ||||||
|  | b'\x00\xce\x01\x00\xce\x01\x00\xce\x01\x00\xce\x01\x00\xce\x01\x00'\ | ||||||
|  | b'\xce\x01\x00\xce\x01\x00\xce\x01\x00\x00\x00\x0a\x00\x80\x83\x03'\ | ||||||
|  | b'\x80\x83\x03\x00\xc7\x01\x00\xc7\x01\x00\xee\x00\x00\xee\x00\x00'\ | ||||||
|  | b'\x7c\x00\x00\x7c\x00\x00\x38\x00\x00\x00\x00\x0c\x00\xc0\x00\x00'\ | ||||||
|  | b'\xf0\x00\x00\xf0\x00\x00\x78\x70\x07\x38\x78\x07\x38\x7c\x07\x78'\ | ||||||
|  | b'\x1e\x00\xf0\x0f\x00\xf0\x07\x00\xc0\x03\x00\x00\x00\x00\x00\x00'\ | ||||||
|  | b'\x00\x11\x00\x00\x3f\x00\xc0\xff\x00\xe0\xe1\x01\xf0\xc0\x03\x70'\ | ||||||
|  | b'\xbc\x03\x78\x7e\x07\x38\x7f\x07\xb8\x73\x07\xb8\x33\x07\xb8\x3f'\ | ||||||
|  | b'\x07\x38\x7f\x07\x70\xf3\x03\x70\x70\x03\xe0\x38\x02\xe0\x3f\x00'\ | ||||||
|  | b'\x80\x0f\x00\x00\x00\x00\x0f\x00\x00\x00\x06\x00\xc0\x07\x00\xf0'\ | ||||||
|  | b'\x07\x00\xfe\x03\xc0\xff\x00\xf8\xef\x00\xf8\xe1\x00\x78\xe0\x00'\ | ||||||
|  | b'\xf8\xe3\x00\xf0\xff\x00\xc0\xff\x00\x00\xfe\x07\x00\xf0\x07\x00'\ | ||||||
|  | b'\x80\x07\x00\x00\x04\x0f\x00\xf8\xff\x07\xf8\xff\x07\xf8\xff\x07'\ | ||||||
|  | b'\x38\x0e\x07\x38\x0e\x07\x38\x0e\x07\x38\x0e\x07\x38\x0e\x07\x38'\ | ||||||
|  | b'\x9e\x07\xf8\xff\x07\xf0\xff\x03\xe0\xf1\x01\x00\x00\x00\x00\x00'\ | ||||||
|  | b'\x00\x00\x00\x00\x10\x00\x00\x3f\x00\xc0\xff\x00\xe0\xff\x01\xf0'\ | ||||||
|  | b'\xe1\x03\x70\x80\x03\x78\x80\x07\x38\x00\x07\x38\x00\x07\x38\x00'\ | ||||||
|  | b'\x07\x38\x00\x07\x78\x80\x03\xf0\xc0\x03\xe0\xc0\x01\xc0\xc0\x00'\ | ||||||
|  | b'\x80\x40\x00\x00\x00\x00\x0f\x00\xf8\xff\x07\xf8\xff\x07\xf8\xff'\ | ||||||
|  | b'\x07\x38\x00\x07\x38\x00\x07\x38\x00\x07\x38\x00\x07\x38\x00\x07'\ | ||||||
|  | b'\x78\x80\x07\xf0\xc0\x03\xe0\xff\x01\xc0\xff\x00\x00\x3f\x00\x00'\ | ||||||
|  | b'\x00\x00\x00\x00\x00\x0e\x00\xf8\xff\x07\xf8\xff\x07\xf8\xff\x07'\ | ||||||
|  | b'\x38\x0e\x07\x38\x0e\x07\x38\x0e\x07\x38\x0e\x07\x38\x0e\x07\x38'\ | ||||||
|  | b'\x0e\x07\x38\x0e\x07\x38\x00\x07\x38\x00\x07\x00\x00\x00\x00\x00'\ | ||||||
|  | b'\x00\x0d\x00\xf8\xff\x07\xf8\xff\x07\xf8\xff\x07\x38\x1c\x00\x38'\ | ||||||
|  | b'\x1c\x00\x38\x1c\x00\x38\x1c\x00\x38\x1c\x00\x38\x1c\x00\x38\x1c'\ | ||||||
|  | b'\x00\x38\x00\x00\x00\x00\x00\x00\x00\x00\x11\x00\x00\x3f\x00\xc0'\ | ||||||
|  | b'\xff\x00\xe0\xff\x01\xf0\xe1\x03\x70\x80\x03\x78\x80\x07\x38\x00'\ | ||||||
|  | b'\x07\x38\x00\x07\x38\x1c\x07\x38\x1c\x07\x78\x9c\x03\xf0\xdc\x01'\ | ||||||
|  | b'\xe0\xfc\x07\xc0\xfc\x07\x80\xfc\x07\x00\x00\x00\x00\x00\x00\x0f'\ | ||||||
|  | b'\x00\xf8\xff\x07\xf8\xff\x07\xf8\xff\x07\x00\x0e\x00\x00\x0e\x00'\ | ||||||
|  | b'\x00\x0e\x00\x00\x0e\x00\x00\x0e\x00\x00\x0e\x00\x00\x0e\x00\xf8'\ | ||||||
|  | b'\xff\x07\xf8\xff\x07\xf8\xff\x07\x00\x00\x00\x00\x00\x00\x06\x00'\ | ||||||
|  | b'\xf8\xff\x07\xf8\xff\x07\xf8\xff\x07\x00\x00\x00\x00\x00\x00\x00'\ | ||||||
|  | b'\x00\x00\x0c\x00\x00\xe0\x00\x00\xe0\x01\x00\xe0\x03\x00\x80\x07'\ | ||||||
|  | b'\x00\x00\x07\x00\x00\x07\x00\x00\x07\x00\x80\x07\xf8\xff\x03\xf8'\ | ||||||
|  | b'\xff\x03\xf8\xff\x00\x00\x00\x00\x0e\x00\xf8\xff\x07\xf8\xff\x07'\ | ||||||
|  | b'\xf8\xff\x07\x00\x1e\x00\x00\x0f\x00\x80\x1f\x00\xc0\x7f\x00\xe0'\ | ||||||
|  | b'\xf9\x00\xf0\xf0\x03\x78\xc0\x07\x38\x80\x07\x18\x00\x07\x08\x00'\ | ||||||
|  | b'\x04\x00\x00\x00\x0c\x00\xf8\xff\x07\xf8\xff\x07\xf8\xff\x07\x00'\ | ||||||
|  | b'\x00\x07\x00\x00\x07\x00\x00\x07\x00\x00\x07\x00\x00\x07\x00\x00'\ | ||||||
|  | b'\x07\x00\x00\x07\x00\x00\x07\x00\x00\x00\x12\x00\xf8\xff\x07\xf8'\ | ||||||
|  | b'\xff\x07\xf8\xff\x07\xf8\x01\x00\xf8\x1f\x00\xc0\xff\x00\x00\xfc'\ | ||||||
|  | b'\x07\x00\xe0\x07\x00\xe0\x07\x00\xfc\x07\xc0\xff\x00\xf8\x1f\x00'\ | ||||||
|  | b'\xf8\x01\x00\xf8\xff\x07\xf8\xff\x07\xf8\xff\x07\x00\x00\x00\x00'\ | ||||||
|  | b'\x00\x00\x0f\x00\xf8\xff\x07\xf8\xff\x07\xf8\xff\x07\xf8\x00\x00'\ | ||||||
|  | b'\xe0\x03\x00\xc0\x0f\x00\x00\x3f\x00\x00\xfc\x00\x00\xf0\x01\x00'\ | ||||||
|  | b'\xe0\x07\xf8\xff\x07\xf8\xff\x07\xf8\xff\x07\x00\x00\x00\x00\x00'\ | ||||||
|  | b'\x00\x11\x00\x00\x3f\x00\xc0\xff\x00\xe0\xff\x01\xf0\xe1\x03\x70'\ | ||||||
|  | b'\x80\x03\x78\x80\x07\x38\x00\x07\x38\x00\x07\x38\x00\x07\x78\x80'\ | ||||||
|  | b'\x07\x70\x80\x03\xf0\xe1\x03\xe0\xff\x01\xc0\xff\x00\x00\x3f\x00'\ | ||||||
|  | b'\x00\x00\x00\x00\x00\x00\x0e\x00\xf8\xff\x07\xf8\xff\x07\xf8\xff'\ | ||||||
|  | b'\x07\x38\x1c\x00\x38\x1c\x00\x38\x1c\x00\x38\x1c\x00\x38\x1c\x00'\ | ||||||
|  | b'\x78\x1e\x00\xf0\x0f\x00\xf0\x0f\x00\xc0\x03\x00\x00\x00\x00\x00'\ | ||||||
|  | b'\x00\x00\x11\x00\x00\x3f\x00\xc0\xff\x00\xe0\xff\x01\xf0\xe1\x03'\ | ||||||
|  | b'\x70\x80\x03\x78\x80\x07\x38\x00\x07\x38\x10\x07\x38\x38\x07\x38'\ | ||||||
|  | b'\x70\x07\x78\xf0\x07\x70\xe0\x03\xf0\xe1\x03\xe0\xff\x07\xc0\xff'\ | ||||||
|  | b'\x03\x00\x3f\x02\x00\x00\x00\x0f\x00\xf8\xff\x07\xf8\xff\x07\xf8'\ | ||||||
|  | b'\xff\x07\x38\x1c\x00\x38\x1c\x00\x38\x1c\x00\x38\x3c\x00\x38\xfc'\ | ||||||
|  | b'\x00\x38\xfc\x03\x78\xfe\x07\xf0\x9f\x07\xf0\x0f\x07\xc0\x07\x04'\ | ||||||
|  | b'\x00\x00\x00\x00\x00\x00\x0e\x00\x00\xc0\x00\xe0\xc1\x01\xf0\xe3'\ | ||||||
|  | b'\x03\xf0\x87\x03\x78\x06\x07\x38\x0e\x07\x38\x0e\x07\x38\x0c\x07'\ | ||||||
|  | b'\x38\x0c\x07\x78\x9c\x07\xf0\xf8\x03\xe0\xf8\x03\xc0\xf0\x00\x00'\ | ||||||
|  | b'\x00\x00\x0c\x00\x38\x00\x00\x38\x00\x00\x38\x00\x00\x38\x00\x00'\ | ||||||
|  | b'\xf8\xff\x07\xf8\xff\x07\xf8\xff\x07\x38\x00\x00\x38\x00\x00\x38'\ | ||||||
|  | b'\x00\x00\x38\x00\x00\x00\x00\x00\x0e\x00\xf8\xff\x00\xf8\xff\x01'\ | ||||||
|  | b'\xf8\xff\x03\x00\x80\x07\x00\x00\x07\x00\x00\x07\x00\x00\x07\x00'\ | ||||||
|  | b'\x00\x07\x00\x80\x07\xf8\xff\x03\xf8\xff\x01\xf8\xff\x00\x00\x00'\ | ||||||
|  | b'\x00\x00\x00\x00\x0e\x00\x18\x00\x00\xf8\x00\x00\xf8\x07\x00\xf0'\ | ||||||
|  | b'\x3f\x00\x00\xff\x01\x00\xf8\x07\x00\x80\x07\x00\xe0\x07\x00\xfe'\ | ||||||
|  | b'\x07\xc0\x7f\x00\xf8\x0f\x00\xf8\x01\x00\x38\x00\x00\x08\x00\x00'\ | ||||||
|  | b'\x14\x00\x18\x00\x00\xf8\x01\x00\xf8\x1f\x00\xe0\xff\x00\x00\xfe'\ | ||||||
|  | b'\x07\x00\xe0\x07\x00\xf8\x07\xc0\xff\x07\xf8\x3f\x00\xf8\x03\x00'\ | ||||||
|  | b'\xf8\x01\x00\xf8\x3f\x00\xc0\xff\x07\x00\xf8\x07\x00\xc0\x07\x00'\ | ||||||
|  | b'\xfe\x07\xe0\xff\x01\xf8\x1f\x00\xf8\x01\x00\x38\x00\x00\x0e\x00'\ | ||||||
|  | b'\x08\x00\x04\x18\x00\x07\x78\x80\x07\xf8\xe0\x07\xf0\xf3\x01\xc0'\ | ||||||
|  | b'\xff\x00\x00\x3f\x00\x80\x7f\x00\xe0\xff\x00\xf0\xf1\x03\xf8\xc0'\ | ||||||
|  | b'\x07\x38\x80\x07\x18\x00\x06\x08\x00\x04\x0d\x00\x18\x00\x00\x38'\ | ||||||
|  | b'\x00\x00\xf8\x00\x00\xf0\x03\x00\xc0\x0f\x00\x00\xff\x07\x00\xfc'\ | ||||||
|  | b'\x07\x00\xff\x07\xc0\x0f\x00\xf0\x03\x00\xf8\x00\x00\x38\x00\x00'\ | ||||||
|  | b'\x18\x00\x00\x0d\x00\x00\x00\x07\x38\x80\x07\x38\xc0\x07\x38\xe0'\ | ||||||
|  | b'\x07\x38\x78\x07\x38\x3c\x07\x38\x1e\x07\x38\x0f\x07\xf8\x07\x07'\ | ||||||
|  | b'\xf8\x01\x07\xf8\x00\x07\x78\x00\x07\x38\x00\x07\x07\x00\xff\xff'\ | ||||||
|  | b'\x3f\xff\xff\x3f\xff\xff\x3f\x07\x00\x38\x07\x00\x38\x07\x00\x38'\ | ||||||
|  | b'\x00\x00\x00\x08\x00\x04\x00\x00\x3c\x00\x00\xfc\x01\x00\xfc\x1f'\ | ||||||
|  | b'\x00\xe0\xff\x00\x00\xfe\x07\x00\xf0\x07\x00\x00\x07\x07\x00\x07'\ | ||||||
|  | b'\x00\x38\x07\x00\x38\x07\x00\x38\xff\xff\x3f\xff\xff\x3f\xff\xff'\ | ||||||
|  | b'\x3f\x00\x00\x00\x0c\x00\x00\x18\x00\x00\x1f\x00\xc0\x1f\x00\xf8'\ | ||||||
|  | b'\x03\x00\xf8\x00\x00\x78\x00\x00\xf8\x03\x00\xe0\x0f\x00\x00\x1f'\ | ||||||
|  | b'\x00\x00\x1c\x00\x00\x10\x00\x00\x00\x00\x12\x00\x00\x00\x38\x00'\ | ||||||
|  | b'\x00\x38\x00\x00\x38\x00\x00\x38\x00\x00\x38\x00\x00\x38\x00\x00'\ | ||||||
|  | b'\x38\x00\x00\x38\x00\x00\x38\x00\x00\x38\x00\x00\x38\x00\x00\x38'\ | ||||||
|  | b'\x00\x00\x38\x00\x00\x38\x00\x00\x38\x00\x00\x38\x00\x00\x38\x00'\ | ||||||
|  | b'\x00\x38\x09\x00\x04\x00\x00\x04\x00\x00\x0c\x00\x00\x1c\x00\x00'\ | ||||||
|  | b'\x18\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0d'\ | ||||||
|  | b'\x00\x00\xc0\x01\x00\xe4\x03\x00\xe6\x07\x00\x37\x07\x80\x37\x07'\ | ||||||
|  | b'\x80\x33\x07\x80\x33\x07\x80\x33\x07\x80\x93\x03\x80\xff\x07\x00'\ | ||||||
|  | b'\xff\x07\x00\xfe\x07\x00\x00\x00\x0e\x00\xfc\xff\x07\xfc\xff\x07'\ | ||||||
|  | b'\xfc\xff\x07\x00\x87\x03\x80\x03\x07\x80\x03\x07\x80\x03\x07\x80'\ | ||||||
|  | b'\x03\x07\x80\x87\x07\x00\xff\x03\x00\xfe\x01\x00\xf8\x00\x00\x00'\ | ||||||
|  | b'\x00\x00\x00\x00\x0d\x00\x00\x78\x00\x00\xfe\x01\x00\xff\x03\x00'\ | ||||||
|  | b'\x87\x03\x80\x03\x07\x80\x03\x07\x80\x03\x07\x80\x03\x07\x80\x87'\ | ||||||
|  | b'\x07\x00\x87\x03\x00\x86\x01\x00\x88\x00\x00\x00\x00\x0e\x00\x00'\ | ||||||
|  | b'\x78\x00\x00\xfe\x01\x00\xff\x03\x00\x87\x03\x80\x87\x07\x80\x03'\ | ||||||
|  | b'\x07\x80\x03\x07\x80\x03\x07\x80\x87\x07\x00\x87\x03\xfc\xff\x07'\ | ||||||
|  | b'\xfc\xff\x07\xfc\xff\x07\x00\x00\x00\x0d\x00\x00\x30\x00\x00\xfc'\ | ||||||
|  | b'\x00\x00\xfe\x01\x00\xff\x03\x80\x77\x07\x80\x73\x07\x80\x73\x07'\ | ||||||
|  | b'\x80\x73\x07\x80\xf7\x07\x00\xff\x03\x00\x7e\x03\x00\x7c\x00\x00'\ | ||||||
|  | b'\x60\x00\x07\x00\x80\x03\x00\xf0\xff\x07\xfc\xff\x07\xfc\xff\x07'\ | ||||||
|  | b'\x9e\x03\x00\x8e\x03\x00\x00\x00\x00\x0e\x00\x00\x78\x00\x00\xfe'\ | ||||||
|  | b'\x01\x00\xff\x23\x00\x87\x73\x80\x87\xf7\x80\x03\xe7\x80\x03\xe7'\ | ||||||
|  | b'\x80\x03\xe7\x00\x87\xe7\x00\x87\xf3\x80\xff\x7f\x80\xff\x3f\x80'\ | ||||||
|  | b'\xff\x1f\x00\x00\x00\x0d\x00\xfc\xff\x07\xfc\xff\x07\xfc\xff\x07'\ | ||||||
|  | b'\x00\x07\x00\x80\x03\x00\x80\x03\x00\x80\x03\x00\x80\x07\x00\x00'\ | ||||||
|  | b'\xff\x07\x00\xff\x07\x00\xfc\x07\x00\x00\x00\x00\x00\x00\x05\x00'\ | ||||||
|  | b'\xb8\xff\x07\xb8\xff\x07\xb8\xff\x07\x00\x00\x00\x00\x00\x00\x05'\ | ||||||
|  | b'\x00\x00\x00\xe0\x00\x00\xe0\xb8\xff\xff\xb8\xff\xff\xb8\xff\x7f'\ | ||||||
|  | b'\x0c\x00\xfc\xff\x07\xfc\xff\x07\xfc\xff\x07\x00\x78\x00\x00\x3c'\ | ||||||
|  | b'\x00\x00\xfe\x00\x80\xff\x01\x80\xe7\x07\x80\x83\x07\x80\x01\x07'\ | ||||||
|  | b'\x80\x00\x04\x00\x00\x00\x05\x00\xfc\xff\x07\xfc\xff\x07\xfc\xff'\ | ||||||
|  | b'\x07\x00\x00\x00\x00\x00\x00\x14\x00\x80\xff\x07\x80\xff\x07\x80'\ | ||||||
|  | b'\xff\x07\x00\x07\x00\x80\x03\x00\x80\x03\x00\x80\x03\x00\x80\x07'\ | ||||||
|  | b'\x00\x00\xff\x07\x00\xfe\x07\x00\xff\x07\x80\x07\x00\x80\x03\x00'\ | ||||||
|  | b'\x80\x03\x00\x80\x07\x00\x00\xff\x07\x00\xff\x07\x00\xfc\x07\x00'\ | ||||||
|  | b'\x00\x00\x00\x00\x00\x0d\x00\x80\xff\x07\x80\xff\x07\x80\xff\x07'\ | ||||||
|  | b'\x00\x07\x00\x80\x03\x00\x80\x03\x00\x80\x03\x00\x80\x07\x00\x00'\ | ||||||
|  | b'\xff\x07\x00\xff\x07\x00\xfc\x07\x00\x00\x00\x00\x00\x00\x0d\x00'\ | ||||||
|  | b'\x00\x78\x00\x00\xfe\x01\x00\xff\x03\x00\x87\x03\x80\x03\x07\x80'\ | ||||||
|  | b'\x03\x07\x80\x03\x07\x80\x03\x07\x00\x87\x03\x00\xff\x03\x00\xfe'\ | ||||||
|  | b'\x01\x00\x78\x00\x00\x00\x00\x0e\x00\x80\xff\xff\x80\xff\xff\x80'\ | ||||||
|  | b'\xff\xff\x00\x87\x03\x80\x03\x07\x80\x03\x07\x80\x03\x07\x80\x03'\ | ||||||
|  | b'\x07\x80\x87\x07\x00\xff\x03\x00\xfe\x01\x00\x7c\x00\x00\x00\x00'\ | ||||||
|  | b'\x00\x00\x00\x0e\x00\x00\x78\x00\x00\xfe\x01\x00\xff\x03\x00\x87'\ | ||||||
|  | b'\x03\x80\x87\x07\x80\x03\x07\x80\x03\x07\x80\x03\x07\x80\x87\x07'\ | ||||||
|  | b'\x00\x87\x03\x80\xff\xff\x80\xff\xff\x80\xff\xff\x00\x00\x00\x08'\ | ||||||
|  | b'\x00\x80\xff\x07\x80\xff\x07\x80\xff\x07\x00\x07\x00\x80\x03\x00'\ | ||||||
|  | b'\x80\x03\x00\x80\x03\x00\x00\x00\x00\x0c\x00\x00\x80\x00\x00\x8e'\ | ||||||
|  | b'\x01\x00\x9f\x03\x80\x9f\x07\x80\x3b\x07\x80\x33\x07\x80\x33\x07'\ | ||||||
|  | b'\x80\x33\x07\x00\xf7\x07\x00\xe7\x03\x00\xc6\x01\x00\x00\x00\x07'\ | ||||||
|  | b'\x00\x80\x03\x00\xfc\xff\x00\xfc\xff\x03\xfc\xff\x07\x80\x03\x07'\ | ||||||
|  | b'\x80\x03\x07\x00\x00\x00\x0d\x00\x80\xff\x00\x80\xff\x03\x80\xff'\ | ||||||
|  | b'\x03\x00\x80\x07\x00\x00\x07\x00\x00\x07\x00\x00\x07\x00\x80\x03'\ | ||||||
|  | b'\x80\xff\x07\x80\xff\x07\x80\xff\x07\x00\x00\x00\x00\x00\x00\x0c'\ | ||||||
|  | b'\x00\x80\x01\x00\x80\x0f\x00\x80\x3f\x00\x00\xfe\x01\x00\xf0\x07'\ | ||||||
|  | b'\x00\x80\x07\x00\xc0\x07\x00\xf8\x07\x00\xff\x00\x80\x3f\x00\x80'\ | ||||||
|  | b'\x07\x00\x80\x00\x00\x12\x00\x80\x01\x00\x80\x0f\x00\x80\xff\x00'\ | ||||||
|  | b'\x00\xfe\x07\x00\xe0\x07\x00\xc0\x07\x00\xfc\x07\x80\xff\x00\x80'\ | ||||||
|  | b'\x0f\x00\x80\x3f\x00\x00\xff\x01\x00\xf0\x07\x00\x80\x07\x00\xf8'\ | ||||||
|  | b'\x07\x80\xff\x03\x80\x3f\x00\x80\x07\x00\x80\x00\x00\x0c\x00\x80'\ | ||||||
|  | b'\x00\x04\x80\x01\x07\x80\x87\x07\x80\xef\x07\x00\xfe\x01\x00\x7c'\ | ||||||
|  | b'\x00\x00\xfe\x00\x00\xff\x03\x80\xc7\x07\x80\x03\x07\x80\x00\x06'\ | ||||||
|  | b'\x00\x00\x04\x0c\x00\x80\x01\x00\x80\x07\xe0\x80\x3f\xe0\x00\xff'\ | ||||||
|  | b'\xf0\x00\xf8\xff\x00\xc0\x7f\x00\xc0\x1f\x00\xf8\x07\x00\xff\x00'\ | ||||||
|  | b'\x80\x1f\x00\x80\x07\x00\x80\x00\x00\x0b\x00\x80\x03\x07\x80\x83'\ | ||||||
|  | b'\x07\x80\xc3\x07\x80\xe3\x07\x80\xf3\x07\x80\x7b\x07\x80\x3f\x07'\ | ||||||
|  | b'\x80\x1f\x07\x80\x0f\x07\x80\x07\x07\x00\x00\x07\x08\x00\x00\x0c'\ | ||||||
|  | b'\x00\x00\x1e\x00\xfc\xff\x0f\xfe\xff\x1f\xfe\xf3\x1f\x06\x00\x38'\ | ||||||
|  | b'\x06\x00\x38\x00\x00\x00\x05\x00\xfc\xff\x07\xfc\xff\x07\xfc\xff'\ | ||||||
|  | b'\x07\x00\x00\x00\x00\x00\x00\x07\x00\x06\x00\x38\xfe\xf3\x1f\xfe'\ | ||||||
|  | b'\xff\x1f\xfc\xff\x0f\x00\x1e\x00\x00\x0c\x00\x00\x00\x00\x09\x00'\ | ||||||
|  | b'\x18\x00\x00\x0c\x00\x00\x0c\x00\x00\x0c\x00\x00\x18\x00\x00\x18'\ | ||||||
|  | b'\x00\x00\x1c\x00\x00\x04\x00\x00\x00\x00\x00' | ||||||
|  | 
 | ||||||
|  | _index =\ | ||||||
|  | b'\x00\x00\x26\x00\x3d\x00\x51\x00\x6b\x00\x91\x00\xb4\x00\xec\x00'\ | ||||||
|  | b'\x1b\x01\x29\x01\x40\x01\x57\x01\x74\x01\x9a\x01\xab\x01\xc2\x01'\ | ||||||
|  | b'\xd3\x01\xed\x01\x16\x02\x30\x02\x59\x02\x7f\x02\xa5\x02\xcb\x02'\ | ||||||
|  | b'\xf4\x02\x17\x03\x3d\x03\x66\x03\x77\x03\x88\x03\xa8\x03\xcb\x03'\ | ||||||
|  | b'\xeb\x03\x11\x04\x46\x04\x75\x04\xa4\x04\xd6\x04\x05\x05\x31\x05'\ | ||||||
|  | b'\x5a\x05\x8f\x05\xbe\x05\xd2\x05\xf8\x05\x24\x06\x4a\x06\x82\x06'\ | ||||||
|  | b'\xb1\x06\xe6\x06\x12\x07\x47\x07\x76\x07\xa2\x07\xc8\x07\xf4\x07'\ | ||||||
|  | b'\x20\x08\x5e\x08\x8a\x08\xb3\x08\xdc\x08\xf3\x08\x0d\x09\x24\x09'\ | ||||||
|  | b'\x4a\x09\x82\x09\x9f\x09\xc8\x09\xf4\x09\x1d\x0a\x49\x0a\x72\x0a'\ | ||||||
|  | b'\x89\x0a\xb5\x0a\xde\x0a\xef\x0a\x00\x0b\x26\x0b\x37\x0b\x75\x0b'\ | ||||||
|  | b'\x9e\x0b\xc7\x0b\xf3\x0b\x1f\x0c\x39\x0c\x5f\x0c\x76\x0c\x9f\x0c'\ | ||||||
|  | b'\xc5\x0c\xfd\x0c\x23\x0d\x49\x0d\x6c\x0d\x86\x0d\x97\x0d\xae\x0d'\ | ||||||
|  | b'\xcb\x0d' | ||||||
|  | 
 | ||||||
|  | _mvfont = memoryview(_font) | ||||||
|  | 
 | ||||||
|  | def _chr_addr(ordch): | ||||||
|  |     offset = 2 * (ordch - 32) | ||||||
|  |     return int.from_bytes(_index[offset:offset + 2], 'little') | ||||||
|  |      | ||||||
|  | def get_width(s): | ||||||
|  |     width = 0 | ||||||
|  |     for ch in s: | ||||||
|  |         ordch = ord(ch) | ||||||
|  |         ordch = ordch + 1 if ordch >= 32 and ordch <= 126 else 32 | ||||||
|  |         offset = _chr_addr(ordch) | ||||||
|  |         width += int.from_bytes(_font[offset:offset + 2], 'little') | ||||||
|  |     return width | ||||||
|  | 
 | ||||||
|  | def get_ch(ch): | ||||||
|  |     ordch = ord(ch) | ||||||
|  |     ordch = ordch + 1 if ordch >= 32 and ordch <= 126 else 32 | ||||||
|  |     offset = _chr_addr(ordch) | ||||||
|  |     width = int.from_bytes(_font[offset:offset + 2], 'little') | ||||||
|  |     next_offs = _chr_addr(ordch +1) | ||||||
|  |     return _mvfont[offset + 2:next_offs], width | ||||||
|  |   | ||||||
							
								
								
									
										430
									
								
								src/tt32.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										430
									
								
								src/tt32.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,430 @@ | ||||||
|  | # Code generated by font-to-py.py. | ||||||
|  | # Font: CM Sans Serif 2012.ttf | ||||||
|  | version = '0.2' | ||||||
|  | 
 | ||||||
|  | def height(): | ||||||
|  |     return 31 | ||||||
|  | 
 | ||||||
|  | def max_width(): | ||||||
|  |     return 26 | ||||||
|  | 
 | ||||||
|  | def hmap(): | ||||||
|  |     return False | ||||||
|  | 
 | ||||||
|  | def reverse(): | ||||||
|  |     return False | ||||||
|  | 
 | ||||||
|  | def monospaced(): | ||||||
|  |     return False | ||||||
|  | 
 | ||||||
|  | def min_ch(): | ||||||
|  |     return 32 | ||||||
|  | 
 | ||||||
|  | def max_ch(): | ||||||
|  |     return 126 | ||||||
|  | 
 | ||||||
|  | _font =\ | ||||||
|  | b'\x0f\x00\x00\x07\x00\x00\xc0\x07\x00\x00\xe0\x07\x00\x00\xe0\x07'\ | ||||||
|  | b'\x00\x00\xf0\x01\x67\x00\xf0\xc0\xf7\x00\xf0\xe0\xf7\x00\xf0\xe0'\ | ||||||
|  | b'\x67\x00\xf0\xf1\x01\x00\xe0\xff\x00\x00\xe0\x7f\x00\x00\xc0\x3f'\ | ||||||
|  | b'\x00\x00\x00\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x09\x00'\ | ||||||
|  | b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ | ||||||
|  | b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ | ||||||
|  | b'\x00\x00\x00\x00\x08\x00\xf0\xff\xf3\x00\xf0\xff\xf3\x00\xf0\xff'\ | ||||||
|  | b'\xf3\x00\xf0\xff\x63\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ | ||||||
|  | b'\x00\x00\x00\x00\x00\x00\x0a\x00\xf0\x0f\x00\x00\xf0\x0f\x00\x00'\ | ||||||
|  | b'\xf0\x0f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0\x0f\x00\x00'\ | ||||||
|  | b'\xf0\x0f\x00\x00\xf0\x0f\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00'\ | ||||||
|  | b'\x0f\x00\x00\x00\x0e\x00\x00\x0e\x0e\x00\x00\x0e\x7e\x00\x00\xfe'\ | ||||||
|  | b'\x7f\x00\xe0\xff\x7f\x00\xe0\xff\x0f\x00\xe0\x0f\x0e\x00\x00\x0e'\ | ||||||
|  | b'\x0e\x00\x00\x0e\x7f\x00\x00\xfe\x7f\x00\xe0\xff\x7f\x00\xe0\xff'\ | ||||||
|  | b'\x0f\x00\xe0\x0f\x0e\x00\x00\x0e\x0e\x00\x00\x0e\x00\x00\x0e\x00'\ | ||||||
|  | b'\x00\x1f\x0e\x00\x80\x3f\x1e\x00\xc0\x3f\x3e\x00\xc0\x79\x3c\x00'\ | ||||||
|  | b'\xc0\x71\x38\x00\xf0\xff\xff\x00\xf0\xff\xff\x00\xc0\xe1\x38\x00'\ | ||||||
|  | b'\xc0\xe3\x38\x00\xc0\xe7\x3f\x00\x80\xc7\x1f\x00\x00\x86\x0f\x00'\ | ||||||
|  | b'\x00\x00\x00\x00\x00\x00\x00\x00\x17\x00\x80\x07\x00\x00\xc0\x0f'\ | ||||||
|  | b'\x00\x00\xe0\x1f\x00\x00\xf0\x3c\x00\x00\x70\x38\x80\x00\x70\x38'\ | ||||||
|  | b'\xe0\x00\x70\x38\xf8\x00\xf0\x3c\x7e\x00\xe0\x1f\x1f\x00\xc0\xcf'\ | ||||||
|  | b'\x0f\x00\x80\xf7\x03\x00\x00\xfc\x00\x00\x00\x3f\x1e\x00\x80\x8f'\ | ||||||
|  | b'\x7f\x00\xe0\x87\x7f\x00\xf0\xc1\xf3\x00\x70\xc0\xe1\x00\x10\xc0'\ | ||||||
|  | b'\xe1\x00\x00\xc0\xf3\x00\x00\x80\x7f\x00\x00\x80\x7f\x00\x00\x00'\ | ||||||
|  | b'\x1e\x00\x00\x00\x00\x00\x13\x00\x00\x00\x0f\x00\x00\x80\x3f\x00'\ | ||||||
|  | b'\x00\xc0\x3f\x00\x80\xe7\x7f\x00\xe0\x7f\xf8\x00\xe0\x3f\xf8\x00'\ | ||||||
|  | b'\xf0\x3f\xf0\x00\xf0\x78\xf0\x00\xf0\xf8\xf0\x00\xf0\xff\xf3\x00'\ | ||||||
|  | b'\xe0\xdf\xff\x00\xe0\x8f\xff\x00\x80\x07\x7e\x00\x00\xc0\xff\x00'\ | ||||||
|  | b'\x00\xc0\xff\x00\x00\xc0\xff\x00\x00\xc0\xc3\x00\x00\x00\x80\x00'\ | ||||||
|  | b'\x00\x00\x00\x00\x05\x00\xf0\x0f\x00\x00\xf0\x0f\x00\x00\xf0\x0f'\ | ||||||
|  | b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x09\x00\x00\xfc\x03\x00'\ | ||||||
|  | b'\x80\xff\x1f\x00\xe0\xff\x7f\x00\xf8\xff\xff\x01\xfc\x01\xf8\x03'\ | ||||||
|  | b'\x3e\x00\xc0\x07\x0e\x00\x00\x07\x02\x00\x00\x04\x00\x00\x00\x00'\ | ||||||
|  | b'\x09\x00\x02\x00\x00\x04\x0e\x00\x00\x07\x3e\x00\xc0\x07\xfc\x01'\ | ||||||
|  | b'\xf8\x03\xf8\xff\xff\x01\xe0\xff\x7f\x00\x80\xff\x1f\x00\x00\xfc'\ | ||||||
|  | b'\x03\x00\x00\x00\x00\x00\x0b\x00\x80\x01\x00\x00\xa0\x09\x00\x00'\ | ||||||
|  | b'\xf0\x1f\x00\x00\xe0\x0f\x00\x00\xc0\x07\x00\x00\xe0\x0f\x00\x00'\ | ||||||
|  | b'\xf0\x1d\x00\x00\xa0\x09\x00\x00\x80\x01\x00\x00\x00\x00\x00\x00'\ | ||||||
|  | b'\x00\x00\x00\x00\x0f\x00\x00\xc0\x03\x00\x00\xc0\x03\x00\x00\xc0'\ | ||||||
|  | b'\x03\x00\x00\xc0\x03\x00\x00\xc0\x03\x00\x00\xfe\x7f\x00\x00\xfe'\ | ||||||
|  | b'\x7f\x00\x00\xfe\x7f\x00\x00\xfe\x7f\x00\x00\xc0\x03\x00\x00\xc0'\ | ||||||
|  | b'\x03\x00\x00\xc0\x03\x00\x00\xc0\x03\x00\x00\xc0\x03\x00\x00\x00'\ | ||||||
|  | b'\x00\x00\x06\x00\x00\x00\x60\x0c\x00\x00\xf0\x0c\x00\x00\xf0\x07'\ | ||||||
|  | b'\x00\x00\xe0\x03\x00\x00\x00\x00\x00\x00\x00\x00\x09\x00\x00\xc0'\ | ||||||
|  | b'\x03\x00\x00\xc0\x03\x00\x00\xc0\x03\x00\x00\xc0\x03\x00\x00\xc0'\ | ||||||
|  | b'\x03\x00\x00\xc0\x03\x00\x00\xc0\x03\x00\x00\x00\x00\x00\x00\x00'\ | ||||||
|  | b'\x00\x00\x06\x00\x00\x00\x60\x00\x00\x00\xf0\x00\x00\x00\xf0\x00'\ | ||||||
|  | b'\x00\x00\x60\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00'\ | ||||||
|  | b'\xe0\x00\x00\x00\xfc\x00\x00\xc0\xff\x00\x00\xf8\xff\x00\x80\xff'\ | ||||||
|  | b'\x1f\x00\xf8\xff\x03\x00\xfc\x3f\x00\x00\xfc\x07\x00\x00\x7c\x00'\ | ||||||
|  | b'\x00\x00\x04\x00\x00\x00\x11\x00\x00\xfc\x03\x00\x80\xff\x1f\x00'\ | ||||||
|  | b'\xc0\xff\x3f\x00\xe0\xff\x7f\x00\xe0\x07\x7e\x00\xf0\x01\xf8\x00'\ | ||||||
|  | b'\xf0\x00\xf0\x00\xf0\x00\xf0\x00\xf0\x00\xf0\x00\xf0\x01\xf8\x00'\ | ||||||
|  | b'\xe0\x07\x7e\x00\xe0\xff\x7f\x00\xc0\xff\x3f\x00\x80\xff\x1f\x00'\ | ||||||
|  | b'\x00\xfc\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x09\x00\x80\x03'\ | ||||||
|  | b'\x00\x00\x80\x03\x00\x00\xc0\x03\x00\x00\xe0\xff\xff\x00\xf0\xff'\ | ||||||
|  | b'\xff\x00\xf0\xff\xff\x00\xf0\xff\xff\x00\x00\x00\x00\x00\x00\x00'\ | ||||||
|  | b'\x00\x00\x10\x00\x00\x07\xf8\x00\xc0\x07\xfc\x00\xc0\x07\xfe\x00'\ | ||||||
|  | b'\xe0\x07\xff\x00\xf0\x81\xf7\x00\xf0\x80\xf3\x00\xf0\xc0\xf1\x00'\ | ||||||
|  | b'\xf0\xe0\xf1\x00\xf0\xe0\xf0\x00\xf0\xf1\xf0\x00\xe0\x7f\xf0\x00'\ | ||||||
|  | b'\xe0\x7f\xf0\x00\xc0\x3f\xf0\x00\x00\x0f\xf0\x00\x00\x00\x00\x00'\ | ||||||
|  | b'\x00\x00\x00\x00\x10\x00\x00\x00\x0e\x00\x00\x07\x3e\x00\xc0\x07'\ | ||||||
|  | b'\x3e\x00\xe0\x07\x7e\x00\xe0\x07\xf8\x00\xf0\x01\xf0\x00\xf0\xf0'\ | ||||||
|  | b'\xf0\x00\xf0\xf0\xf0\x00\xf0\xf0\xf0\x00\xf0\xf9\xf0\x00\xf0\xff'\ | ||||||
|  | b'\xf9\x00\xe0\xff\x7f\x00\xc0\xdf\x7f\x00\x80\x8f\x3f\x00\x00\x00'\ | ||||||
|  | b'\x0f\x00\x00\x00\x00\x00\x10\x00\x00\x00\x0f\x00\x00\x80\x0f\x00'\ | ||||||
|  | b'\x00\xe0\x0f\x00\x00\xf8\x0f\x00\x00\x7c\x0f\x00\x00\x3f\x0f\x00'\ | ||||||
|  | b'\x80\x0f\x0f\x00\xe0\x07\x0f\x00\xf0\x01\x0f\x00\xf0\xff\xff\x00'\ | ||||||
|  | b'\xf0\xff\xff\x00\xf0\xff\xff\x00\xf0\xff\xff\x00\x00\x00\x0f\x00'\ | ||||||
|  | b'\x00\x00\x0f\x00\x00\x00\x00\x00\x0f\x00\x00\x70\x1c\x00\xf0\x7f'\ | ||||||
|  | b'\x3c\x00\xf0\x7f\x7c\x00\xf0\xff\x7c\x00\xf0\x78\xf8\x00\xf0\x3c'\ | ||||||
|  | b'\xf0\x00\xf0\x3c\xf0\x00\xf0\x3c\xf0\x00\xf0\x3c\xf0\x00\xf0\x7c'\ | ||||||
|  | b'\x78\x00\xf0\xf8\x7f\x00\xf0\xf0\x3f\x00\xf0\xe0\x1f\x00\x00\xc0'\ | ||||||
|  | b'\x0f\x00\x00\x00\x00\x00\x10\x00\x00\xfc\x07\x00\x00\xff\x1f\x00'\ | ||||||
|  | b'\xc0\xff\x3f\x00\xe0\xff\x7f\x00\xe0\xf3\x78\x00\xf0\x79\xf0\x00'\ | ||||||
|  | b'\xf0\x78\xf0\x00\xf0\x78\xf0\x00\xf0\x78\xf0\x00\xf0\xf9\xf8\x00'\ | ||||||
|  | b'\xe0\xf3\x7f\x00\xe0\xf3\x7f\x00\xc0\xe3\x3f\x00\x00\x83\x0f\x00'\ | ||||||
|  | b'\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00\xf0\x00\x00\x00\xf0\x00'\ | ||||||
|  | b'\x00\x00\xf0\x00\x00\x00\xf0\x00\xf8\x00\xf0\x80\xff\x00\xf0\xe0'\ | ||||||
|  | b'\xff\x00\xf0\xf8\xff\x00\xf0\xfc\x07\x00\xf0\x7e\x00\x00\xf0\x1f'\ | ||||||
|  | b'\x00\x00\xf0\x07\x00\x00\xf0\x03\x00\x00\xf0\x01\x00\x00\xf0\x00'\ | ||||||
|  | b'\x00\x00\x10\x00\x00\x00\x0f\x00\x80\xc7\x3f\x00\xc0\xef\x7f\x00'\ | ||||||
|  | b'\xe0\xff\x7f\x00\xe0\xff\xf8\x00\xf0\x7d\xf0\x00\xf0\x78\xf0\x00'\ | ||||||
|  | b'\xf0\x78\xf0\x00\xf0\x78\xf0\x00\xf0\x7d\xf0\x00\xe0\xff\xf8\x00'\ | ||||||
|  | b'\xe0\xff\x7f\x00\xc0\xef\x7f\x00\x80\xc7\x3f\x00\x00\x00\x0f\x00'\ | ||||||
|  | b'\x00\x00\x00\x00\x10\x00\x00\x3f\x00\x00\x80\xff\x30\x00\xc0\xff'\ | ||||||
|  | b'\x71\x00\xe0\xff\x71\x00\xf0\xe1\xf3\x00\xf0\xc1\xf3\x00\xf0\xc0'\ | ||||||
|  | b'\xf3\x00\xf0\xc0\xf3\x00\xf0\xc0\xf3\x00\xf0\xc1\xf9\x00\xe0\xe1'\ | ||||||
|  | b'\x7d\x00\xe0\xff\x7f\x00\xc0\xff\x3f\x00\x80\xff\x1f\x00\x00\xfc'\ | ||||||
|  | b'\x03\x00\x00\x00\x00\x00\x06\x00\x00\x18\x60\x00\x00\x3c\xf0\x00'\ | ||||||
|  | b'\x00\x3c\xf0\x00\x00\x18\x60\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ | ||||||
|  | b'\x06\x00\x00\x18\x60\x0c\x00\x3c\xf0\x0c\x00\x3c\xf0\x07\x00\x18'\ | ||||||
|  | b'\xe0\x03\x00\x00\x00\x00\x00\x00\x00\x00\x0c\x00\x00\xc0\x03\x00'\ | ||||||
|  | b'\x00\xe0\x07\x00\x00\xe0\x07\x00\x00\xf0\x0f\x00\x00\xf0\x0f\x00'\ | ||||||
|  | b'\x00\x78\x1e\x00\x00\x78\x1e\x00\x00\x38\x1c\x00\x00\x3c\x3c\x00'\ | ||||||
|  | b'\x00\x1c\x38\x00\x00\x1e\x78\x00\x00\x00\x00\x00\x0e\x00\x00\x78'\ | ||||||
|  | b'\x1e\x00\x00\x78\x1e\x00\x00\x78\x1e\x00\x00\x78\x1e\x00\x00\x78'\ | ||||||
|  | b'\x1e\x00\x00\x78\x1e\x00\x00\x78\x1e\x00\x00\x78\x1e\x00\x00\x78'\ | ||||||
|  | b'\x1e\x00\x00\x78\x1e\x00\x00\x78\x1e\x00\x00\x78\x1e\x00\x00\x00'\ | ||||||
|  | b'\x00\x00\x00\x00\x00\x00\x0c\x00\x00\x1e\x78\x00\x00\x3c\x3c\x00'\ | ||||||
|  | b'\x00\x3c\x3c\x00\x00\x78\x1e\x00\x00\x78\x1e\x00\x00\x70\x0e\x00'\ | ||||||
|  | b'\x00\xf0\x0f\x00\x00\xe0\x07\x00\x00\xe0\x07\x00\x00\xc0\x07\x00'\ | ||||||
|  | b'\x00\xc0\x03\x00\x00\x00\x00\x00\x0f\x00\x00\x07\x00\x00\xc0\x07'\ | ||||||
|  | b'\x00\x00\xe0\x07\x00\x00\xe0\x07\x00\x00\xf0\x01\x67\x00\xf0\xc0'\ | ||||||
|  | b'\xf7\x00\xf0\xe0\xf7\x00\xf0\xe0\x67\x00\xf0\xf1\x01\x00\xe0\xff'\ | ||||||
|  | b'\x00\x00\xe0\x7f\x00\x00\xc0\x3f\x00\x00\x00\x1f\x00\x00\x00\x00'\ | ||||||
|  | b'\x00\x00\x00\x00\x00\x00\x16\x00\x00\xf8\x01\x00\x00\xfe\x07\x00'\ | ||||||
|  | b'\x80\xff\x1f\x00\xc0\x0f\x1e\x00\xc0\x03\x3c\x00\xe0\xe1\x79\x00'\ | ||||||
|  | b'\xe0\xf8\x73\x00\xf0\xfc\xf7\x00\x70\x1c\xe7\x00\x70\x0e\xe7\x00'\ | ||||||
|  | b'\x70\x8e\xe3\x00\x70\xfe\xe1\x00\x70\xfc\xe3\x00\xf0\xfc\xe7\x00'\ | ||||||
|  | b'\xe0\x0c\x77\x00\xe0\x01\x77\x00\xc0\xc3\x23\x00\xc0\xff\x43\x00'\ | ||||||
|  | b'\x00\xff\x01\x00\x00\x7e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ | ||||||
|  | b'\x13\x00\x00\x00\xc0\x00\x00\x00\xf8\x00\x00\x00\xfe\x00\x00\xc0'\ | ||||||
|  | b'\xff\x00\x00\xf8\x3f\x00\x00\xff\x0f\x00\xe0\xff\x0f\x00\xf0\x1f'\ | ||||||
|  | b'\x0f\x00\xf0\x03\x0f\x00\xf0\x00\x0f\x00\xf0\x07\x0f\x00\xf0\x3f'\ | ||||||
|  | b'\x0f\x00\xc0\xff\x0f\x00\x00\xfe\x0f\x00\x00\xf0\x7f\x00\x00\x80'\ | ||||||
|  | b'\xff\x00\x00\x00\xfc\x00\x00\x00\xf0\x00\x00\x00\x80\x00\x12\x00'\ | ||||||
|  | b'\xf0\xff\xff\x00\xf0\xff\xff\x00\xf0\xff\xff\x00\xf0\xff\xff\x00'\ | ||||||
|  | b'\xf0\xf0\xf0\x00\xf0\xf0\xf0\x00\xf0\xf0\xf0\x00\xf0\xf0\xf0\x00'\ | ||||||
|  | b'\xf0\xf0\xf0\x00\xf0\xf0\xf0\x00\xf0\xf0\xf0\x00\xf0\xf9\xf0\x00'\ | ||||||
|  | b'\xf0\xff\xf9\x00\xe0\xff\x7f\x00\xc0\xdf\x7f\x00\x80\x8f\x3f\x00'\ | ||||||
|  | b'\x00\x00\x1f\x00\x00\x00\x00\x00\x14\x00\x00\xf8\x01\x00\x00\xfe'\ | ||||||
|  | b'\x07\x00\x80\xff\x1f\x00\xc0\xff\x3f\x00\xc0\x0f\x3f\x00\xe0\x03'\ | ||||||
|  | b'\x7c\x00\xe0\x01\x78\x00\xf0\x01\xf8\x00\xf0\x00\xf0\x00\xf0\x00'\ | ||||||
|  | b'\xf0\x00\xf0\x00\xf0\x00\xf0\x00\xf0\x00\xf0\x01\xf8\x00\xe0\x01'\ | ||||||
|  | b'\x78\x00\xe0\x07\x7e\x00\xc0\x07\x3e\x00\x80\x07\x1e\x00\x00\x03'\ | ||||||
|  | b'\x0c\x00\x00\x04\x04\x00\x00\x00\x00\x00\x13\x00\xf0\xff\xff\x00'\ | ||||||
|  | b'\xf0\xff\xff\x00\xf0\xff\xff\x00\xf0\xff\xff\x00\xf0\x00\xf0\x00'\ | ||||||
|  | b'\xf0\x00\xf0\x00\xf0\x00\xf0\x00\xf0\x00\xf0\x00\xf0\x00\xf0\x00'\ | ||||||
|  | b'\xf0\x00\xf8\x00\xe0\x01\x78\x00\xe0\x07\x7e\x00\xc0\xff\x3f\x00'\ | ||||||
|  | b'\x80\xff\x1f\x00\x00\xff\x0f\x00\x00\xfc\x03\x00\x00\x00\x00\x00'\ | ||||||
|  | b'\x00\x00\x00\x00\x00\x00\x00\x00\x11\x00\xf0\xff\xff\x00\xf0\xff'\ | ||||||
|  | b'\xff\x00\xf0\xff\xff\x00\xf0\xff\xff\x00\xf0\xf0\xf0\x00\xf0\xf0'\ | ||||||
|  | b'\xf0\x00\xf0\xf0\xf0\x00\xf0\xf0\xf0\x00\xf0\xf0\xf0\x00\xf0\xf0'\ | ||||||
|  | b'\xf0\x00\xf0\xf0\xf0\x00\xf0\xf0\xf0\x00\xf0\xf0\xf0\x00\xf0\x00'\ | ||||||
|  | b'\xf0\x00\xf0\x00\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00'\ | ||||||
|  | b'\xf0\xff\xff\x00\xf0\xff\xff\x00\xf0\xff\xff\x00\xf0\xff\xff\x00'\ | ||||||
|  | b'\xf0\xf0\x00\x00\xf0\xf0\x00\x00\xf0\xf0\x00\x00\xf0\xf0\x00\x00'\ | ||||||
|  | b'\xf0\xf0\x00\x00\xf0\xf0\x00\x00\xf0\xf0\x00\x00\xf0\xf0\x00\x00'\ | ||||||
|  | b'\xf0\xf0\x00\x00\xf0\x00\x00\x00\xf0\x00\x00\x00\x00\x00\x00\x00'\ | ||||||
|  | b'\x15\x00\x00\xf8\x01\x00\x00\xfe\x0f\x00\x80\xff\x1f\x00\xc0\xff'\ | ||||||
|  | b'\x3f\x00\xc0\x0f\x7f\x00\xe0\x03\x7c\x00\xe0\x01\xf8\x00\xf0\x01'\ | ||||||
|  | b'\xf0\x00\xf0\x00\xf0\x00\xf0\x00\xf0\x00\xf0\xe0\xf1\x00\xf0\xe0'\ | ||||||
|  | b'\xf1\x00\xf0\xe1\x79\x00\xe0\xe1\x79\x00\xe0\xe3\x3d\x00\xc0\xe7'\ | ||||||
|  | b'\xff\x00\x80\xe7\xff\x00\x00\xe3\xff\x00\x00\xe4\xff\x00\x00\x00'\ | ||||||
|  | b'\x00\x00\x00\x00\x00\x00\x14\x00\xf0\xff\xff\x00\xf0\xff\xff\x00'\ | ||||||
|  | b'\xf0\xff\xff\x00\xf0\xff\xff\x00\x00\xf0\x00\x00\x00\xf0\x00\x00'\ | ||||||
|  | b'\x00\xf0\x00\x00\x00\xf0\x00\x00\x00\xf0\x00\x00\x00\xf0\x00\x00'\ | ||||||
|  | b'\x00\xf0\x00\x00\x00\xf0\x00\x00\xf0\xff\xff\x00\xf0\xff\xff\x00'\ | ||||||
|  | b'\xf0\xff\xff\x00\xf0\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ | ||||||
|  | b'\x00\x00\x00\x00\x00\x00\x00\x00\x07\x00\xf0\xff\xff\x00\xf0\xff'\ | ||||||
|  | b'\xff\x00\xf0\xff\xff\x00\xf0\xff\xff\x00\x00\x00\x00\x00\x00\x00'\ | ||||||
|  | b'\x00\x00\x00\x00\x00\x00\x0f\x00\x00\x00\x0f\x00\x00\x00\x3f\x00'\ | ||||||
|  | b'\x00\x00\x7f\x00\x00\x00\x7f\x00\x00\x00\xf8\x00\x00\x00\xf0\x00'\ | ||||||
|  | b'\x00\x00\xf0\x00\x00\x00\xf0\x00\x00\x00\xf0\x00\x00\x00\xf8\x00'\ | ||||||
|  | b'\xf0\xff\x7f\x00\xf0\xff\x7f\x00\xf0\xff\x3f\x00\xf0\xff\x0f\x00'\ | ||||||
|  | b'\x00\x00\x00\x00\x12\x00\xf0\xff\xff\x00\xf0\xff\xff\x00\xf0\xff'\ | ||||||
|  | b'\xff\x00\xf0\xff\xff\x00\x00\xf0\x01\x00\x00\xfc\x00\x00\x00\xfe'\ | ||||||
|  | b'\x00\x00\x00\xff\x01\x00\x80\xff\x07\x00\xc0\xef\x0f\x00\xe0\x87'\ | ||||||
|  | b'\x3f\x00\xf0\x01\x7f\x00\xf0\x00\xfc\x00\x70\x00\xf8\x00\x30\x00'\ | ||||||
|  | b'\xf0\x00\x10\x00\xc0\x00\x10\x00\x80\x00\x00\x00\x00\x00\x10\x00'\ | ||||||
|  | b'\xf0\xff\xff\x00\xf0\xff\xff\x00\xf0\xff\xff\x00\xf0\xff\xff\x00'\ | ||||||
|  | b'\x00\x00\xf0\x00\x00\x00\xf0\x00\x00\x00\xf0\x00\x00\x00\xf0\x00'\ | ||||||
|  | b'\x00\x00\xf0\x00\x00\x00\xf0\x00\x00\x00\xf0\x00\x00\x00\xf0\x00'\ | ||||||
|  | b'\x00\x00\xf0\x00\x00\x00\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ | ||||||
|  | b'\x18\x00\xf0\xff\xff\x00\xf0\xff\xff\x00\xf0\xff\xff\x00\xf0\xff'\ | ||||||
|  | b'\xff\x00\xf0\x07\x00\x00\xf0\x7f\x00\x00\x80\xff\x07\x00\x00\xfc'\ | ||||||
|  | b'\x3f\x00\x00\xc0\xff\x00\x00\x00\xfe\x00\x00\x00\xfe\x00\x00\xc0'\ | ||||||
|  | b'\xff\x00\x00\xfc\x3f\x00\x80\xff\x07\x00\xf0\x7f\x00\x00\xf0\x07'\ | ||||||
|  | b'\x00\x00\xf0\xff\xff\x00\xf0\xff\xff\x00\xf0\xff\xff\x00\xf0\xff'\ | ||||||
|  | b'\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ | ||||||
|  | b'\x00\x00\x14\x00\xf0\xff\xff\x00\xf0\xff\xff\x00\xf0\xff\xff\x00'\ | ||||||
|  | b'\xf0\xff\xff\x00\xf0\x07\x00\x00\xc0\x1f\x00\x00\x00\x3f\x00\x00'\ | ||||||
|  | b'\x00\xfc\x00\x00\x00\xf0\x03\x00\x00\xc0\x0f\x00\x00\x80\x3f\x00'\ | ||||||
|  | b'\x00\x00\xfe\x00\xf0\xff\xff\x00\xf0\xff\xff\x00\xf0\xff\xff\x00'\ | ||||||
|  | b'\xf0\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ | ||||||
|  | b'\x00\x00\x00\x00\x16\x00\x00\xf8\x01\x00\x00\xfe\x07\x00\x80\xff'\ | ||||||
|  | b'\x1f\x00\xc0\xff\x3f\x00\xc0\x0f\x3f\x00\xe0\x03\x7c\x00\xe0\x01'\ | ||||||
|  | b'\x78\x00\xf0\x01\xf8\x00\xf0\x00\xf0\x00\xf0\x00\xf0\x00\xf0\x00'\ | ||||||
|  | b'\xf0\x00\xf0\x00\xf0\x00\xf0\x01\xf8\x00\xe0\x01\x78\x00\xe0\x03'\ | ||||||
|  | b'\x7c\x00\xc0\x0f\x3f\x00\xc0\xff\x3f\x00\x80\xff\x1f\x00\x00\xfe'\ | ||||||
|  | b'\x07\x00\x00\xf8\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x12\x00'\ | ||||||
|  | b'\xf0\xff\xff\x00\xf0\xff\xff\x00\xf0\xff\xff\x00\xf0\xff\xff\x00'\ | ||||||
|  | b'\xf0\xe0\x01\x00\xf0\xe0\x01\x00\xf0\xe0\x01\x00\xf0\xe0\x01\x00'\ | ||||||
|  | b'\xf0\xe0\x01\x00\xf0\xe0\x01\x00\xf0\xf1\x01\x00\xe0\xff\x00\x00'\ | ||||||
|  | b'\xe0\xff\x00\x00\xc0\x7f\x00\x00\x00\x1f\x00\x00\x00\x00\x00\x00'\ | ||||||
|  | b'\x00\x00\x00\x00\x00\x00\x00\x00\x15\x00\x00\xf8\x01\x00\x00\xff'\ | ||||||
|  | b'\x0f\x00\x80\xff\x1f\x00\xc0\xff\x3f\x00\xe0\x0f\x7e\x00\xe0\x03'\ | ||||||
|  | b'\x7c\x00\xf0\x01\xf8\x00\xf0\x00\xf0\x00\xf0\x00\xf1\x00\xf0\x80'\ | ||||||
|  | b'\xf3\x00\xf0\xc0\xf7\x00\xf0\x80\xff\x00\xf0\x01\xff\x00\xe0\x03'\ | ||||||
|  | b'\x7e\x00\xe0\x0f\x7e\x00\xc0\xff\x7f\x00\x80\xff\xff\x00\x00\xfe'\ | ||||||
|  | b'\x77\x00\x00\xf8\x21\x00\x00\x00\x00\x00\x00\x00\x00\x00\x12\x00'\ | ||||||
|  | b'\xf0\xff\xff\x00\xf0\xff\xff\x00\xf0\xff\xff\x00\xf0\xff\xff\x00'\ | ||||||
|  | b'\xf0\xe0\x01\x00\xf0\xe0\x01\x00\xf0\xe0\x01\x00\xf0\xe0\x03\x00'\ | ||||||
|  | b'\xf0\xe0\x0f\x00\xf0\xe0\x3f\x00\xf0\xf1\x7f\x00\xe0\xff\xfc\x00'\ | ||||||
|  | b'\xe0\xff\xf0\x00\xc0\x7f\xe0\x00\x00\x1f\x80\x00\x00\x00\x00\x00'\ | ||||||
|  | b'\x00\x00\x00\x00\x00\x00\x00\x00\x12\x00\x00\x00\x04\x00\x80\x0f'\ | ||||||
|  | b'\x1e\x00\xc0\x1f\x3e\x00\xe0\x3f\x7e\x00\xe0\x3f\x7c\x00\xf0\x39'\ | ||||||
|  | b'\xf8\x00\xf0\x70\xf0\x00\xf0\x70\xf0\x00\xf0\x70\xf0\x00\xf0\x70'\ | ||||||
|  | b'\xf0\x00\xf0\x60\xf0\x00\xf0\xe1\xf8\x00\xe0\xe3\x78\x00\xe0\xc7'\ | ||||||
|  | b'\x7f\x00\xc0\xc3\x7f\x00\x80\x83\x3f\x00\x00\x02\x0f\x00\x00\x00'\ | ||||||
|  | b'\x00\x00\x0f\x00\xf0\x00\x00\x00\xf0\x00\x00\x00\xf0\x00\x00\x00'\ | ||||||
|  | b'\xf0\x00\x00\x00\xf0\x00\x00\x00\xf0\xff\xff\x00\xf0\xff\xff\x00'\ | ||||||
|  | b'\xf0\xff\xff\x00\xf0\xff\xff\x00\xf0\x00\x00\x00\xf0\x00\x00\x00'\ | ||||||
|  | b'\xf0\x00\x00\x00\xf0\x00\x00\x00\xf0\x00\x00\x00\x00\x00\x00\x00'\ | ||||||
|  | b'\x12\x00\xf0\xff\x07\x00\xf0\xff\x1f\x00\xf0\xff\x3f\x00\xf0\xff'\ | ||||||
|  | b'\x7f\x00\x00\x00\x7c\x00\x00\x00\xf8\x00\x00\x00\xf0\x00\x00\x00'\ | ||||||
|  | b'\xf0\x00\x00\x00\xf0\x00\x00\x00\xf0\x00\x00\x00\xf8\x00\x00\x00'\ | ||||||
|  | b'\x7c\x00\xf0\xff\x7f\x00\xf0\xff\x3f\x00\xf0\xff\x1f\x00\xf0\xff'\ | ||||||
|  | b'\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11\x00\x30\x00\x00\x00'\ | ||||||
|  | b'\xf0\x01\x00\x00\xf0\x0f\x00\x00\xf0\x7f\x00\x00\xc0\xff\x03\x00'\ | ||||||
|  | b'\x00\xfe\x1f\x00\x00\xe0\xff\x00\x00\x00\xff\x00\x00\x00\xf8\x00'\ | ||||||
|  | b'\x00\x00\xff\x00\x00\xe0\xff\x00\x00\xfe\x1f\x00\xc0\xff\x03\x00'\ | ||||||
|  | b'\xf0\x7f\x00\x00\xf0\x0f\x00\x00\xf0\x01\x00\x00\x30\x00\x00\x00'\ | ||||||
|  | b'\x19\x00\x70\x00\x00\x00\xf0\x03\x00\x00\xf0\x3f\x00\x00\xf0\xff'\ | ||||||
|  | b'\x01\x00\x80\xff\x1f\x00\x00\xf8\xff\x00\x00\x80\xff\x00\x00\x00'\ | ||||||
|  | b'\xfc\x00\x00\xe0\xff\x00\x00\xff\xff\x00\xf0\xff\x07\x00\xf0\x3f'\ | ||||||
|  | b'\x00\x00\xf0\x03\x00\x00\xf0\x1f\x00\x00\xf0\xff\x03\x00\x80\xff'\ | ||||||
|  | b'\x7f\x00\x00\xf8\xff\x00\x00\x00\xff\x00\x00\x00\xff\x00\x00\xf0'\ | ||||||
|  | b'\xff\x00\x00\xff\x3f\x00\xf0\xff\x07\x00\xf0\x7f\x00\x00\xf0\x07'\ | ||||||
|  | b'\x00\x00\xf0\x00\x00\x00\x11\x00\x10\x00\x80\x00\x30\x00\xe0\x00'\ | ||||||
|  | b'\xf0\x00\xf0\x00\xf0\x01\xfc\x00\xf0\x07\xfe\x00\xc0\x9f\x3f\x00'\ | ||||||
|  | b'\x80\xff\x0f\x00\x00\xfe\x07\x00\x00\xfc\x01\x00\x00\xfe\x07\x00'\ | ||||||
|  | b'\x80\xff\x0f\x00\xc0\x9f\x3f\x00\xf0\x07\x7f\x00\xf0\x03\xfc\x00'\ | ||||||
|  | b'\xf0\x00\xf8\x00\x70\x00\xe0\x00\x10\x00\x80\x00\x12\x00\x10\x00'\ | ||||||
|  | b'\x00\x00\x30\x00\x00\x00\xf0\x00\x00\x00\xf0\x03\x00\x00\xf0\x0f'\ | ||||||
|  | b'\x00\x00\xc0\x3f\x00\x00\x00\x7f\x00\x00\x00\xfc\xff\x00\x00\xf0'\ | ||||||
|  | b'\xff\x00\x00\xf0\xff\x00\x00\xfc\xff\x00\x00\x7f\x00\x00\xc0\x3f'\ | ||||||
|  | b'\x00\x00\xf0\x0f\x00\x00\xf0\x03\x00\x00\xf0\x00\x00\x00\x30\x00'\ | ||||||
|  | b'\x00\x00\x10\x00\x00\x00\x11\x00\x00\x00\xe0\x00\xf0\x00\xf8\x00'\ | ||||||
|  | b'\xf0\x00\xfc\x00\xf0\x00\xfe\x00\xf0\x00\xff\x00\xf0\x80\xff\x00'\ | ||||||
|  | b'\xf0\xc0\xf3\x00\xf0\xf0\xf1\x00\xf0\xf8\xf0\x00\xf0\x7c\xf0\x00'\ | ||||||
|  | b'\xf0\x3e\xf0\x00\xf0\x0f\xf0\x00\xf0\x07\xf0\x00\xf0\x03\xf0\x00'\ | ||||||
|  | b'\xf0\x01\xf0\x00\xf0\x00\xf0\x00\x00\x00\x00\x00\x09\x00\xff\xff'\ | ||||||
|  | b'\xff\x0f\xff\xff\xff\x0f\xff\xff\xff\x0f\xff\xff\xff\x0f\x0f\x00'\ | ||||||
|  | b'\x00\x0f\x0f\x00\x00\x0f\x0f\x00\x00\x0f\x00\x00\x00\x00\x00\x00'\ | ||||||
|  | b'\x00\x00\x0a\x00\x04\x00\x00\x00\x3c\x00\x00\x00\xfc\x03\x00\x00'\ | ||||||
|  | b'\xfc\x1f\x00\x00\xf8\xff\x01\x00\xc0\xff\x1f\x00\x00\xfc\xff\x00'\ | ||||||
|  | b'\x00\xe0\xff\x00\x00\x00\xfe\x00\x00\x00\xe0\x00\x09\x00\x0f\x00'\ | ||||||
|  | b'\x00\x0f\x0f\x00\x00\x0f\x0f\x00\x00\x0f\xff\xff\xff\x0f\xff\xff'\ | ||||||
|  | b'\xff\x0f\xff\xff\xff\x0f\xff\xff\xff\x0f\x00\x00\x00\x00\x00\x00'\ | ||||||
|  | b'\x00\x00\x0f\x00\x00\x80\x01\x00\x00\xf0\x01\x00\x00\xfc\x01\x00'\ | ||||||
|  | b'\x80\xff\x01\x00\xe0\x3f\x00\x00\xf0\x07\x00\x00\xf0\x01\x00\x00'\ | ||||||
|  | b'\xf0\x03\x00\x00\xf0\x1f\x00\x00\xc0\xff\x00\x00\x00\xfe\x01\x00'\ | ||||||
|  | b'\x00\xf8\x01\x00\x00\xc0\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00'\ | ||||||
|  | b'\x17\x00\x00\x00\x00\x0f\x00\x00\x00\x0f\x00\x00\x00\x0f\x00\x00'\ | ||||||
|  | b'\x00\x0f\x00\x00\x00\x0f\x00\x00\x00\x0f\x00\x00\x00\x0f\x00\x00'\ | ||||||
|  | b'\x00\x0f\x00\x00\x00\x0f\x00\x00\x00\x0f\x00\x00\x00\x0f\x00\x00'\ | ||||||
|  | b'\x00\x0f\x00\x00\x00\x0f\x00\x00\x00\x0f\x00\x00\x00\x0f\x00\x00'\ | ||||||
|  | b'\x00\x0f\x00\x00\x00\x0f\x00\x00\x00\x0f\x00\x00\x00\x0f\x00\x00'\ | ||||||
|  | b'\x00\x0f\x00\x00\x00\x0f\x00\x00\x00\x0f\x00\x00\x00\x0f\x0c\x00'\ | ||||||
|  | b'\x08\x00\x00\x00\x18\x00\x00\x00\x38\x00\x00\x00\x78\x00\x00\x00'\ | ||||||
|  | b'\x70\x00\x00\x00\x60\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00\x00'\ | ||||||
|  | b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ | ||||||
|  | b'\x11\x00\x00\x40\x3c\x00\x00\x30\x7e\x00\x00\x38\x7f\x00\x00\x7c'\ | ||||||
|  | b'\xff\x00\x00\x3e\xf3\x00\x00\x1e\xf3\x00\x00\x1e\xf3\x00\x00\x1e'\ | ||||||
|  | b'\xf1\x00\x00\x9e\x71\x00\x00\xbe\x79\x00\x00\xfc\xff\x00\x00\xfc'\ | ||||||
|  | b'\xff\x00\x00\xf8\xff\x00\x00\xf0\xff\x00\x00\x00\x00\x00\x00\x00'\ | ||||||
|  | b'\x00\x00\x00\x00\x00\x00\x12\x00\xfc\xff\xff\x00\xfc\xff\xff\x00'\ | ||||||
|  | b'\xfc\xff\xff\x00\xfc\xff\xff\x00\x00\x7c\x3c\x00\x00\x3c\x78\x00'\ | ||||||
|  | b'\x00\x1e\xf0\x00\x00\x1e\xf0\x00\x00\x1e\xf0\x00\x00\x1e\xf0\x00'\ | ||||||
|  | b'\x00\x3e\xf8\x00\x00\x7c\x7c\x00\x00\xfc\x7f\x00\x00\xf8\x3f\x00'\ | ||||||
|  | b'\x00\xf0\x1f\x00\x00\xc0\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ | ||||||
|  | b'\x10\x00\x00\xc0\x07\x00\x00\xf0\x1f\x00\x00\xf8\x3f\x00\x00\xfc'\ | ||||||
|  | b'\x7f\x00\x00\x7c\x7c\x00\x00\x3e\xf8\x00\x00\x1e\xf0\x00\x00\x1e'\ | ||||||
|  | b'\xf0\x00\x00\x1e\xf0\x00\x00\x1e\xf0\x00\x00\x3c\xf8\x00\x00\x7c'\ | ||||||
|  | b'\x7c\x00\x00\x78\x38\x00\x00\x30\x18\x00\x00\x20\x08\x00\x00\x00'\ | ||||||
|  | b'\x00\x00\x12\x00\x00\xc0\x07\x00\x00\xf0\x1f\x00\x00\xf8\x3f\x00'\ | ||||||
|  | b'\x00\xfc\x7f\x00\x00\x7e\xfc\x00\x00\x3e\xf8\x00\x00\x1e\xf0\x00'\ | ||||||
|  | b'\x00\x1e\xf0\x00\x00\x1e\xf0\x00\x00\x3c\x78\x00\x00\x7c\x7c\x00'\ | ||||||
|  | b'\xfc\xff\xff\x00\xfc\xff\xff\x00\xfc\xff\xff\x00\xfc\xff\xff\x00'\ | ||||||
|  | b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\xe0'\ | ||||||
|  | b'\x0f\x00\x00\xf0\x1f\x00\x00\xf8\x3f\x00\x00\xfc\x7f\x00\x00\xdc'\ | ||||||
|  | b'\x7b\x00\x00\xde\xf3\x00\x00\xde\xf3\x00\x00\xde\xf3\x00\x00\xde'\ | ||||||
|  | b'\xf3\x00\x00\xde\xfb\x00\x00\xfc\x7b\x00\x00\xfc\x7b\x00\x00\xf8'\ | ||||||
|  | b'\x33\x00\x00\xf0\x03\x00\x00\x80\x03\x00\x00\x00\x00\x00\x09\x00'\ | ||||||
|  | b'\x00\x1c\x00\x00\x00\x1c\x00\x00\xc0\xff\xff\x00\xf0\xff\xff\x00'\ | ||||||
|  | b'\xf0\xff\xff\x00\xf8\xff\xff\x00\x78\x1c\x00\x00\x3c\x1c\x00\x00'\ | ||||||
|  | b'\x3c\x1c\x00\x00\x11\x00\x00\xc0\x07\x08\x00\xf0\x1f\x1c\x00\xf8'\ | ||||||
|  | b'\x3f\x3c\x00\xfc\x7f\x3c\x00\x7e\xfc\x7c\x00\x3e\xf8\x78\x00\x1e'\ | ||||||
|  | b'\xf0\x78\x00\x1e\xf0\x78\x00\x1e\xf0\x78\x00\x3c\x78\x7c\x00\x78'\ | ||||||
|  | b'\x7c\x3e\x00\xfe\xff\x3f\x00\xfe\xff\x1f\x00\xfe\xff\x0f\x00\xfe'\ | ||||||
|  | b'\xff\x03\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\xfc\xff\xff\x00'\ | ||||||
|  | b'\xfc\xff\xff\x00\xfc\xff\xff\x00\xfc\xff\xff\x00\x00\x3c\x00\x00'\ | ||||||
|  | b'\x00\x1e\x00\x00\x00\x1e\x00\x00\x00\x1e\x00\x00\x00\x1e\x00\x00'\ | ||||||
|  | b'\x00\x3e\x00\x00\x00\xfc\xff\x00\x00\xfc\xff\x00\x00\xf8\xff\x00'\ | ||||||
|  | b'\x00\xe0\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x07\x00\x60\xfe'\ | ||||||
|  | b'\xff\x00\xf0\xfe\xff\x00\xf0\xfe\xff\x00\x60\xfe\xff\x00\x00\x00'\ | ||||||
|  | b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x00\x78'\ | ||||||
|  | b'\x00\x00\x00\x78\x60\xfe\xff\x7f\xf0\xfe\xff\x3f\xf0\xfe\xff\x3f'\ | ||||||
|  | b'\x60\xfe\xff\x0f\x10\x00\xfc\xff\xff\x00\xfc\xff\xff\x00\xfc\xff'\ | ||||||
|  | b'\xff\x00\xfc\xff\xff\x00\x00\xc0\x07\x00\x00\xe0\x03\x00\x00\xf0'\ | ||||||
|  | b'\x07\x00\x00\xfc\x0f\x00\x00\xfe\x3f\x00\x00\x3e\xff\x00\x00\x1e'\ | ||||||
|  | b'\xfc\x00\x00\x0e\xf8\x00\x00\x06\xe0\x00\x00\x02\xc0\x00\x00\x00'\ | ||||||
|  | b'\x80\x00\x00\x00\x00\x00\x07\x00\xfc\xff\xff\x00\xfc\xff\xff\x00'\ | ||||||
|  | b'\xfc\xff\xff\x00\xfc\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ | ||||||
|  | b'\x00\x00\x00\x00\x1a\x00\x00\xfe\xff\x00\x00\xfe\xff\x00\x00\xfe'\ | ||||||
|  | b'\xff\x00\x00\xfe\xff\x00\x00\x3c\x00\x00\x00\x1e\x00\x00\x00\x1e'\ | ||||||
|  | b'\x00\x00\x00\x1e\x00\x00\x00\x1e\x00\x00\x00\x3e\x00\x00\x00\xfc'\ | ||||||
|  | b'\xff\x00\x00\xfc\xff\x00\x00\xf8\xff\x00\x00\xfc\xff\x00\x00\x3e'\ | ||||||
|  | b'\x00\x00\x00\x1e\x00\x00\x00\x1e\x00\x00\x00\x1e\x00\x00\x00\x3e'\ | ||||||
|  | b'\x00\x00\x00\xfc\xff\x00\x00\xfc\xff\x00\x00\xf8\xff\x00\x00\xe0'\ | ||||||
|  | b'\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00'\ | ||||||
|  | b'\x00\xfe\xff\x00\x00\xfe\xff\x00\x00\xfe\xff\x00\x00\xfe\xff\x00'\ | ||||||
|  | b'\x00\x3c\x00\x00\x00\x1c\x00\x00\x00\x1e\x00\x00\x00\x1e\x00\x00'\ | ||||||
|  | b'\x00\x1e\x00\x00\x00\x3e\x00\x00\x00\xfc\xff\x00\x00\xfc\xff\x00'\ | ||||||
|  | b'\x00\xf8\xff\x00\x00\xe0\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ | ||||||
|  | b'\x11\x00\x00\xc0\x07\x00\x00\xf0\x1f\x00\x00\xf8\x3f\x00\x00\xfc'\ | ||||||
|  | b'\x7f\x00\x00\x7c\x7c\x00\x00\x3e\xf8\x00\x00\x1e\xf0\x00\x00\x1e'\ | ||||||
|  | b'\xf0\x00\x00\x1e\xf0\x00\x00\x3e\xf8\x00\x00\x7c\x7c\x00\x00\xfc'\ | ||||||
|  | b'\x7f\x00\x00\xf8\x3f\x00\x00\xf0\x1f\x00\x00\xc0\x07\x00\x00\x00'\ | ||||||
|  | b'\x00\x00\x00\x00\x00\x00\x12\x00\x00\xfe\xff\x7f\x00\xfe\xff\x7f'\ | ||||||
|  | b'\x00\xfe\xff\x7f\x00\xfe\xff\x7f\x00\x7c\x7c\x00\x00\x3c\x78\x00'\ | ||||||
|  | b'\x00\x1e\xf0\x00\x00\x1e\xf0\x00\x00\x1e\xf0\x00\x00\x1e\xf0\x00'\ | ||||||
|  | b'\x00\x3e\xf8\x00\x00\x7c\x7c\x00\x00\xfc\x7f\x00\x00\xf8\x3f\x00'\ | ||||||
|  | b'\x00\xf0\x1f\x00\x00\xc0\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ | ||||||
|  | b'\x11\x00\x00\xc0\x07\x00\x00\xf0\x1f\x00\x00\xf8\x3f\x00\x00\xfc'\ | ||||||
|  | b'\x7f\x00\x00\x7e\xfc\x00\x00\x3e\xf8\x00\x00\x1e\xf0\x00\x00\x1e'\ | ||||||
|  | b'\xf0\x00\x00\x1e\xf0\x00\x00\x3c\x78\x00\x00\x7c\x7c\x00\x00\xfe'\ | ||||||
|  | b'\xff\x7f\x00\xfe\xff\x7f\x00\xfe\xff\x7f\x00\xfe\xff\x7f\x00\x00'\ | ||||||
|  | b'\x00\x00\x00\x00\x00\x00\x0a\x00\x00\xfe\xff\x00\x00\xfe\xff\x00'\ | ||||||
|  | b'\x00\xfe\xff\x00\x00\xfe\xff\x00\x00\x3c\x00\x00\x00\x1e\x00\x00'\ | ||||||
|  | b'\x00\x1e\x00\x00\x00\x0e\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00'\ | ||||||
|  | b'\x0f\x00\x00\x00\x08\x00\x00\x70\x18\x00\x00\xfc\x38\x00\x00\xfc'\ | ||||||
|  | b'\x7d\x00\x00\xfe\xf9\x00\x00\x9e\xf1\x00\x00\x9e\xf1\x00\x00\x9e'\ | ||||||
|  | b'\xf1\x00\x00\x9e\xf3\x00\x00\x3e\xf3\x00\x00\x3c\x7f\x00\x00\x3c'\ | ||||||
|  | b'\x7f\x00\x00\x38\x3e\x00\x00\x20\x1c\x00\x00\x00\x00\x00\x09\x00'\ | ||||||
|  | b'\x00\x0e\x00\x00\x00\x0e\x00\x00\xfc\xff\x1f\x00\xfc\xff\x3f\x00'\ | ||||||
|  | b'\xfc\xff\x7f\x00\xfc\xff\xff\x00\x00\x0e\xf0\x00\x00\x0e\xf0\x00'\ | ||||||
|  | b'\x00\x0e\xf0\x00\x10\x00\x00\xfe\x0f\x00\x00\xfe\x3f\x00\x00\xfe'\ | ||||||
|  | b'\x7f\x00\x00\xfe\x7f\x00\x00\x00\xf8\x00\x00\x00\xf0\x00\x00\x00'\ | ||||||
|  | b'\xf0\x00\x00\x00\xf0\x00\x00\x00\x70\x00\x00\x00\x78\x00\x00\xfe'\ | ||||||
|  | b'\xff\x00\x00\xfe\xff\x00\x00\xfe\xff\x00\x00\xfe\xff\x00\x00\x00'\ | ||||||
|  | b'\x00\x00\x00\x00\x00\x00\x0f\x00\x00\x06\x00\x00\x00\x3e\x00\x00'\ | ||||||
|  | b'\x00\xfe\x00\x00\x00\xfe\x07\x00\x00\xf8\x3f\x00\x00\xc0\xff\x00'\ | ||||||
|  | b'\x00\x00\xfe\x00\x00\x00\xf0\x00\x00\x00\xfe\x00\x00\xc0\xff\x00'\ | ||||||
|  | b'\x00\xf8\x1f\x00\x00\xfe\x07\x00\x00\xfe\x00\x00\x00\x1e\x00\x00'\ | ||||||
|  | b'\x00\x06\x00\x00\x16\x00\x00\x06\x00\x00\x00\x7e\x00\x00\x00\xfe'\ | ||||||
|  | b'\x03\x00\x00\xfe\x1f\x00\x00\xf0\xff\x00\x00\x00\xff\x00\x00\x00'\ | ||||||
|  | b'\xf8\x00\x00\x80\xff\x00\x00\xf8\xff\x00\x00\xfe\x0f\x00\x00\xfe'\ | ||||||
|  | b'\x00\x00\x00\xfe\x00\x00\x00\xfe\x07\x00\x00\xf8\x7f\x00\x00\x80'\ | ||||||
|  | b'\xff\x00\x00\x00\xf8\x00\x00\x00\xff\x00\x00\xf0\xff\x00\x00\xfe'\ | ||||||
|  | b'\x3f\x00\x00\xfe\x03\x00\x00\x7e\x00\x00\x00\x0e\x00\x00\x0f\x00'\ | ||||||
|  | b'\x00\x02\x80\x00\x00\x06\xe0\x00\x00\x1e\xf0\x00\x00\x3e\xfc\x00'\ | ||||||
|  | b'\x00\xfe\x7e\x00\x00\xf8\x3f\x00\x00\xe0\x0f\x00\x00\xe0\x07\x00'\ | ||||||
|  | b'\x00\xf8\x1f\x00\x00\xfc\x7f\x00\x00\x7e\xfc\x00\x00\x1e\xf8\x00'\ | ||||||
|  | b'\x00\x0e\xe0\x00\x00\x02\xc0\x00\x00\x00\x80\x00\x0f\x00\x00\x06'\ | ||||||
|  | b'\x00\x00\x00\x3e\x00\x00\x00\xfe\x00\x78\x00\xfe\x07\x78\x00\xf8'\ | ||||||
|  | b'\x1f\x7c\x00\xc0\xff\x7f\x00\x00\xfe\x3f\x00\x00\xf0\x1f\x00\x00'\ | ||||||
|  | b'\xfe\x07\x00\xc0\xff\x00\x00\xf8\x1f\x00\x00\xfe\x07\x00\x00\xfe'\ | ||||||
|  | b'\x00\x00\x00\x1e\x00\x00\x00\x06\x00\x00\x0e\x00\x00\x00\xe0\x00'\ | ||||||
|  | b'\x00\x1e\xf0\x00\x00\x1e\xf8\x00\x00\x1e\xfc\x00\x00\x1e\xfe\x00'\ | ||||||
|  | b'\x00\x1e\xff\x00\x00\x9e\xf7\x00\x00\xde\xf3\x00\x00\xfe\xf1\x00'\ | ||||||
|  | b'\x00\xfe\xf0\x00\x00\x7e\xf0\x00\x00\x3e\xf0\x00\x00\x1e\xf0\x00'\ | ||||||
|  | b'\x00\x00\x00\x00\x0a\x00\x00\x60\x00\x00\x00\xf0\x00\x00\x00\xf0'\ | ||||||
|  | b'\x00\x00\xf8\xff\xff\x01\xfc\xff\xff\x03\xfe\x9f\xff\x07\xfe\x0f'\ | ||||||
|  | b'\xff\x07\x0e\x00\x00\x07\x0e\x00\x00\x07\x00\x00\x00\x00\x08\x00'\ | ||||||
|  | b'\xfc\xff\xff\x00\xfc\xff\xff\x00\xfc\xff\xff\x00\xfc\xff\xff\x00'\ | ||||||
|  | b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ | ||||||
|  | b'\x09\x00\x0e\x00\x00\x07\x0e\x00\x00\x07\xfe\x0f\xff\x07\xfe\x9f'\ | ||||||
|  | b'\xff\x07\xfc\xff\xff\x03\xf8\xff\xff\x01\x00\xf0\x00\x00\x00\xf0'\ | ||||||
|  | b'\x00\x00\x00\x60\x00\x00\x0c\x00\x30\x00\x00\x00\x38\x00\x00\x00'\ | ||||||
|  | b'\x18\x00\x00\x00\x18\x00\x00\x00\x18\x00\x00\x00\x30\x00\x00\x00'\ | ||||||
|  | b'\x30\x00\x00\x00\x30\x00\x00\x00\x38\x00\x00\x00\x18\x00\x00\x00'\ | ||||||
|  | b'\x00\x00\x00\x00\x00\x00\x00\x00' | ||||||
|  | 
 | ||||||
|  | _index =\ | ||||||
|  | b'\x00\x00\x3e\x00\x64\x00\x86\x00\xb0\x00\xee\x00\x28\x01\x86\x01'\ | ||||||
|  | b'\xd4\x01\xea\x01\x10\x02\x36\x02\x64\x02\xa2\x02\xbc\x02\xe2\x02'\ | ||||||
|  | b'\xfc\x02\x26\x03\x6c\x03\x92\x03\xd4\x03\x16\x04\x58\x04\x96\x04'\ | ||||||
|  | b'\xd8\x04\x12\x05\x54\x05\x96\x05\xb0\x05\xca\x05\xfc\x05\x36\x06'\ | ||||||
|  | b'\x68\x06\xa6\x06\x00\x07\x4e\x07\x98\x07\xea\x07\x38\x08\x7e\x08'\ | ||||||
|  | b'\xc0\x08\x16\x09\x68\x09\x86\x09\xc4\x09\x0e\x0a\x50\x0a\xb2\x0a'\ | ||||||
|  | b'\x04\x0b\x5e\x0b\xa8\x0b\xfe\x0b\x48\x0c\x92\x0c\xd0\x0c\x1a\x0d'\ | ||||||
|  | b'\x60\x0d\xc6\x0d\x0c\x0e\x56\x0e\x9c\x0e\xc2\x0e\xec\x0e\x12\x0f'\ | ||||||
|  | b'\x50\x0f\xae\x0f\xe0\x0f\x26\x10\x70\x10\xb2\x10\xfc\x10\x3e\x11'\ | ||||||
|  | b'\x64\x11\xaa\x11\xec\x11\x0a\x12\x24\x12\x66\x12\x84\x12\xee\x12'\ | ||||||
|  | b'\x30\x13\x76\x13\xc0\x13\x06\x14\x30\x14\x6e\x14\x94\x14\xd6\x14'\ | ||||||
|  | b'\x14\x15\x6e\x15\xac\x15\xea\x15\x24\x16\x4e\x16\x70\x16\x96\x16'\ | ||||||
|  | b'\xc8\x16' | ||||||
|  | 
 | ||||||
|  | _mvfont = memoryview(_font) | ||||||
|  | 
 | ||||||
|  | def _chr_addr(ordch): | ||||||
|  |     offset = 2 * (ordch - 32) | ||||||
|  |     return int.from_bytes(_index[offset:offset + 2], 'little') | ||||||
|  |      | ||||||
|  | def get_width(s): | ||||||
|  |     width = 0 | ||||||
|  |     for ch in s: | ||||||
|  |         ordch = ord(ch) | ||||||
|  |         ordch = ordch + 1 if ordch >= 32 and ordch <= 126 else 32 | ||||||
|  |         offset = _chr_addr(ordch) | ||||||
|  |         width += int.from_bytes(_font[offset:offset + 2], 'little') | ||||||
|  |     return width | ||||||
|  | 
 | ||||||
|  | def get_ch(ch): | ||||||
|  |     ordch = ord(ch) | ||||||
|  |     ordch = ordch + 1 if ordch >= 32 and ordch <= 126 else 32 | ||||||
|  |     offset = _chr_addr(ordch) | ||||||
|  |     width = int.from_bytes(_font[offset:offset + 2], 'little') | ||||||
|  |     next_offs = _chr_addr(ordch +1) | ||||||
|  |     return _mvfont[offset + 2:next_offs], width | ||||||
|  |   | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Robert Schauklies
						Robert Schauklies