├── pico_files
├── root
│ ├── main.py
│ └── boot.py
├── root_eigenmath
│ ├── main.py
│ └── boot.py
├── examples
│ ├── refresh.py
│ ├── mandelbrot.py
│ ├── rotation.py
│ └── wave.py
└── modules
│ ├── default_style.py
│ ├── colorer.py
│ ├── vt.py
│ ├── highlighter.py
│ ├── picocalc_system.py
│ ├── sdcard.py
│ └── picocalc.py
├── flash_nuke.uf2
├── imgs
├── rotation.jpg
├── framebuffer.jpg
├── framebuffer2.jpg
└── picocalc_example.png
├── .vscode
└── settings.json
├── picocalc_micropython_NOfilesystem_pico.uf2
├── picocalc_micropython_NOfilesystem_pico2.uf2
├── picocalc_micropython_NOfilesystem_pico2w.uf2
├── picocalc_micropython_withfilesystem_pico.uf2
├── picocalc_micropython_withfilesystem_pico2.uf2
├── picocalc_micropython_withfilesystem_pico2w.uf2
├── picocalc_micropython_ulab_eigenmath_NOfilesystem_pico2.uf2
├── picocalc_micropython_ulab_eigenmath_withfilesystem_pico2.uf2
├── vtterminal
├── micropython.mk
├── micropython.cmake
├── vtterminal.h
└── vtterminal.c
├── picocalcdisplay
├── micropython.mk
├── picocalcdisplay.h
├── micropython.cmake
├── picocalcdisplay.c
└── font6x8e500.h
└── README.md
/pico_files/root/main.py:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | #now all the init has been moved to boot.py
--------------------------------------------------------------------------------
/pico_files/root_eigenmath/main.py:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | #now all the init has been moved to boot.py
--------------------------------------------------------------------------------
/flash_nuke.uf2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zenodante/PicoCalc-micropython-driver/HEAD/flash_nuke.uf2
--------------------------------------------------------------------------------
/imgs/rotation.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zenodante/PicoCalc-micropython-driver/HEAD/imgs/rotation.jpg
--------------------------------------------------------------------------------
/imgs/framebuffer.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zenodante/PicoCalc-micropython-driver/HEAD/imgs/framebuffer.jpg
--------------------------------------------------------------------------------
/imgs/framebuffer2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zenodante/PicoCalc-micropython-driver/HEAD/imgs/framebuffer2.jpg
--------------------------------------------------------------------------------
/imgs/picocalc_example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zenodante/PicoCalc-micropython-driver/HEAD/imgs/picocalc_example.png
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "files.associations": {
3 | "stdint.h": "c",
4 | "string.h": "c"
5 | }
6 | }
--------------------------------------------------------------------------------
/picocalc_micropython_NOfilesystem_pico.uf2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zenodante/PicoCalc-micropython-driver/HEAD/picocalc_micropython_NOfilesystem_pico.uf2
--------------------------------------------------------------------------------
/picocalc_micropython_NOfilesystem_pico2.uf2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zenodante/PicoCalc-micropython-driver/HEAD/picocalc_micropython_NOfilesystem_pico2.uf2
--------------------------------------------------------------------------------
/picocalc_micropython_NOfilesystem_pico2w.uf2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zenodante/PicoCalc-micropython-driver/HEAD/picocalc_micropython_NOfilesystem_pico2w.uf2
--------------------------------------------------------------------------------
/picocalc_micropython_withfilesystem_pico.uf2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zenodante/PicoCalc-micropython-driver/HEAD/picocalc_micropython_withfilesystem_pico.uf2
--------------------------------------------------------------------------------
/picocalc_micropython_withfilesystem_pico2.uf2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zenodante/PicoCalc-micropython-driver/HEAD/picocalc_micropython_withfilesystem_pico2.uf2
--------------------------------------------------------------------------------
/picocalc_micropython_withfilesystem_pico2w.uf2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zenodante/PicoCalc-micropython-driver/HEAD/picocalc_micropython_withfilesystem_pico2w.uf2
--------------------------------------------------------------------------------
/picocalc_micropython_ulab_eigenmath_NOfilesystem_pico2.uf2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zenodante/PicoCalc-micropython-driver/HEAD/picocalc_micropython_ulab_eigenmath_NOfilesystem_pico2.uf2
--------------------------------------------------------------------------------
/picocalc_micropython_ulab_eigenmath_withfilesystem_pico2.uf2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zenodante/PicoCalc-micropython-driver/HEAD/picocalc_micropython_ulab_eigenmath_withfilesystem_pico2.uf2
--------------------------------------------------------------------------------
/vtterminal/micropython.mk:
--------------------------------------------------------------------------------
1 | VTTERMINAL_MOD_DIR := $(USERMOD_DIR)
2 |
3 | # Add all C files to SRC_USERMOD.
4 | SRC_USERMOD += $(VTTERMINAL_MOD_DIR)/vtterminal.c
5 |
6 | # We can add our module folder to include paths if needed
7 | # This is not actually needed in this example.
8 | CFLAGS_USERMOD += -I$(VTTERMINAL_MOD_DIR)
9 |
--------------------------------------------------------------------------------
/picocalcdisplay/micropython.mk:
--------------------------------------------------------------------------------
1 | PICOCALCDISPLAY_MOD_DIR := $(USERMOD_DIR)
2 |
3 | # Add all C files to SRC_USERMOD.
4 | SRC_USERMOD += $(PICOCALCDISPLAY_MOD_DIR)/picocalcdisplay.c
5 |
6 | # We can add our module folder to include paths if needed
7 | # This is not actually needed in this example.
8 | CFLAGS_USERMOD += -I$(PICOCALCDISPLAY_MOD_DIR)
9 |
--------------------------------------------------------------------------------
/picocalcdisplay/picocalcdisplay.h:
--------------------------------------------------------------------------------
1 | #ifndef _PICOCALCDISPLAY_H
2 | #define _PICOCALCDISPLAY_H
3 |
4 | #define DISPLAY_WIDTH 320
5 | #define DISPLAY_HEIGHT 320
6 |
7 | //cs;sck;mosi;miso;dc;bl;
8 | //13 10 11 12 14 0
9 |
10 |
11 | #define CLK_PIN 10
12 | #define MOSI_PIN 11
13 | #define CS_PIN 13
14 | #define DC_PIN 14
15 | #define RST_PIN 15
16 | #define SPI_DISP spi1
17 |
18 |
19 |
20 |
21 |
22 | #endif // ILI9488_H
--------------------------------------------------------------------------------
/vtterminal/micropython.cmake:
--------------------------------------------------------------------------------
1 | # Create an INTERFACE library for our C module.
2 | add_library(usermod_vtterminal INTERFACE)
3 |
4 | # Add our source files to the lib
5 | target_sources(usermod_vtterminal INTERFACE
6 | ${CMAKE_CURRENT_LIST_DIR}/vtterminal.c
7 | )
8 |
9 | # Add the current directory as an include directory.
10 | target_include_directories(usermod_vtterminal INTERFACE
11 | ${CMAKE_CURRENT_LIST_DIR}
12 | )
13 |
14 | # Link our INTERFACE library to the usermod target.
15 | target_link_libraries(usermod INTERFACE usermod_vtterminal)
16 |
--------------------------------------------------------------------------------
/picocalcdisplay/micropython.cmake:
--------------------------------------------------------------------------------
1 | # Create an INTERFACE library for our C module.
2 | add_library(usermod_picocalcdisplay INTERFACE)
3 |
4 | # Add our source files to the lib
5 | target_sources(usermod_picocalcdisplay INTERFACE
6 | ${CMAKE_CURRENT_LIST_DIR}/picocalcdisplay.c
7 | )
8 |
9 | # Add the current directory as an include directory.
10 | target_include_directories(usermod_picocalcdisplay INTERFACE
11 | ${CMAKE_CURRENT_LIST_DIR}
12 | )
13 |
14 | # Link our INTERFACE library to the usermod target.
15 | target_link_libraries(usermod INTERFACE usermod_picocalcdisplay)
16 |
--------------------------------------------------------------------------------
/vtterminal/vtterminal.h:
--------------------------------------------------------------------------------
1 | #ifndef _VTTERMINAL_H
2 | #define _VTTERMINAL_H
3 |
4 |
5 | #define CH_W 6
6 | #define CH_H 8
7 |
8 | #define SC_W 53
9 | #define SC_H 40
10 | #define SC_PIXEL_WIDTH 320
11 | #define SC_PIXEL_HEIGHT 320
12 |
13 | #define clBlack 0
14 | #define clRed 1
15 | #define clGreen 2
16 | #define clYellow 3
17 | #define clBlue 4
18 | #define clMagenta 5
19 | #define clCyan 6
20 | #define clWhite 7
21 |
22 | #define G0TABLE CP437
23 | #define G1TABLE font6x8G1
24 | #endif
--------------------------------------------------------------------------------
/pico_files/examples/refresh.py:
--------------------------------------------------------------------------------
1 | from picocalc import display,keyboard,terminal
2 |
3 |
4 | terminal.dryBuffer()
5 |
6 |
7 | terminal.wr("\x1b[?25l") # hide cursor
8 | terminal.stopRefresh()
9 | i=0
10 | temp =bytearray(1)
11 |
12 | def processKey():
13 | # Read a key from the keyboard
14 | if keyboard.readinto(temp):
15 | key = temp[0]
16 | if key == ord('E') or key == ord('e'):
17 | return True
18 | return False
19 |
20 | while(True):
21 | while not display.isScreenUpdateDone():
22 | pass
23 | if processKey():
24 | break
25 | display.fill(i)
26 | i+=1
27 | if i>15:
28 | i=0
29 | terminal.wr("\x1b[40;1HPress \'E\' to break...")
30 | display.show()
31 |
32 |
33 | terminal.recoverRefresh()
34 | display.fill(0) #clean the screen
35 | display.restLUT()
36 | terminal.wr("\x1b[2J\x1b[H")#move the cursor to the top, and clear the terminal buffer
37 |
38 | terminal.wr("\x1b[?25h") # show cursor
--------------------------------------------------------------------------------
/pico_files/modules/default_style.py:
--------------------------------------------------------------------------------
1 | syntax_style = {
2 | "def": "\x1b[37;44m", # white on deep blue
3 | "class": "\x1b[37;45m", # white on magenta
4 | "if": "\x1b[37;46m", # white on cyan
5 | "elif": "\x1b[37;46m",
6 | "else": "\x1b[37;46m",
7 | "while": "\x1b[37;46m",
8 | "for": "\x1b[37;46m",
9 | "in": "\x1b[37;46m",
10 | "True": "\x1b[36m", # bright cyan text only
11 | "False": "\x1b[31m", # bright red text only
12 | "import": "\x1b[37;44m",
13 | "from": "\x1b[37;44m",
14 | "as": "\x1b[37;44m",
15 | "return": "\x1b[37;45m",
16 | "pass": "\x1b[37;45m",
17 | "break": "\x1b[37;45m",
18 | "try": "\x1b[37;46m",
19 | "except": "\x1b[37;46m",
20 | "raise": "\x1b[37;46m",
21 | "and": "\x1b[37;46m",
22 | "or": "\x1b[37;46m",
23 | "not": "\x1b[37;46m",
24 | "#": "\x1b[32m", # bright green text only
25 | "string": "\x1b[33m", # yellow on black
26 | "multiline": "\x1b[32m"
27 | }
--------------------------------------------------------------------------------
/pico_files/modules/colorer.py:
--------------------------------------------------------------------------------
1 | """
2 | Limited Colorama Port to Micropython
3 | Written by: Laika, 4/19/2025
4 |
5 | Allows for coloring using Fore, Back, and Style like Colorama
6 | Autoreset functionality is also supplied by shadowing print
7 | """
8 | import sys
9 | import builtins
10 |
11 | # kind of a misnomer, is module level
12 | _global_autoreset = False
13 |
14 | class Fore:
15 | BLACK = "\033[30m"
16 | RED = "\033[31m"
17 | GREEN = "\033[32m"
18 | YELLOW = "\033[33m"
19 | BLUE = "\033[34m"
20 | MAGENTA = "\033[35m"
21 | CYAN = "\033[36m"
22 | WHITE = "\033[37m"
23 | RESET = "\033[39m"
24 |
25 | class Back:
26 | BLACK = "\033[40m"
27 | RED = "\033[41m"
28 | GREEN = "\033[42m"
29 | YELLOW = "\033[43m"
30 | BLUE = "\033[44m"
31 | MAGENTA = "\033[45m"
32 | CYAN = "\033[46m"
33 | WHITE = "\033[47m"
34 | RESET = "\033[49m"
35 |
36 | class Style:
37 | BRIGHT = "\033[1m"
38 | DIM = "\033[2m"
39 | NORMAL = "\033[22m"
40 | UNDERLINE = "\033[4m"
41 | RESET_ALL = "\033[0m"
42 |
43 | def autoreset(state):
44 | """Set the autoreset state for the library."""
45 | global _global_autoreset
46 | _global_autoreset = state
47 |
48 | def print(*args, sep=' ', end='\n', file=sys.stdout):
49 | """Custom print function that respects the global autoreset setting."""
50 | global _global_autoreset
51 | text = sep.join(map(str, args))
52 | if _global_autoreset:
53 | text += Style.RESET_ALL
54 | builtins.print(text, end=end, file=file)
55 |
56 |
--------------------------------------------------------------------------------
/pico_files/root/boot.py:
--------------------------------------------------------------------------------
1 | import picocalc
2 | from picocalc import PicoDisplay, PicoKeyboard, PicoSD, PicoSpeaker
3 | import os
4 | import vt
5 | import sys
6 | # Separated imports because Micropython is super finnicky
7 | from picocalc_system import run, files, memory, disk
8 |
9 | from pye import pye_edit
10 |
11 | try:
12 | pc_display = PicoDisplay(320, 320)
13 | pc_keyboard = PicoKeyboard()
14 | # Mount SD card to /sd on boot
15 | pc_sd = PicoSD()
16 | pc_sd.mount()
17 | pcs_L = PicoSpeaker(26)
18 | pcs_R = PicoSpeaker(27)
19 | pc_terminal = vt.vt(pc_display, pc_keyboard, sd=pc_sd())
20 |
21 | _usb = sys.stdout #
22 |
23 | def usb_debug(msg):
24 | if isinstance(msg, str):
25 | _usb.write(msg)
26 | else:
27 | _usb.write(str(msg))
28 | _usb.write('\r\n')
29 | picocalc.usb_debug = usb_debug
30 |
31 | picocalc.display = pc_display
32 | picocalc.keyboard = pc_keyboard
33 | picocalc.terminal = pc_terminal
34 | picocalc.sd = pc_sd
35 |
36 | def edit(*args, tab_size=2, undo=50):
37 | #dry the key buffer before editing
38 | pc_terminal.dryBuffer()
39 | return pye_edit(args, tab_size=tab_size, undo=undo, io_device=pc_terminal)
40 | picocalc.edit = edit
41 |
42 | os.dupterm(pc_terminal)
43 | pc_sd.check_mount()
44 | #usb_debug("boot.py done.")
45 |
46 | except Exception as e:
47 | import sys
48 | sys.print_exception(e)
49 | try:
50 | os.dupterm(None).write(b"[boot.py error]\n")
51 | except:
52 | pass
53 |
--------------------------------------------------------------------------------
/pico_files/root_eigenmath/boot.py:
--------------------------------------------------------------------------------
1 | import picocalc
2 | from picocalc import PicoDisplay, PicoKeyboard, PicoSD, PicoSpeaker
3 | import os
4 | import vt
5 | import sys
6 | # Separated imports because Micropython is super finnicky
7 | from picocalc_system import run, files, memory, disk
8 | import eigenmath
9 | from pye import pye_edit
10 | import builtins
11 | import gc
12 | try:
13 | em=eigenmath.EigenMath(300*1024)
14 | pc_display = PicoDisplay(320, 320)
15 | pc_keyboard = PicoKeyboard()
16 | # Mount SD card to /sd on boot
17 | pc_sd = PicoSD()
18 | pc_sd.mount()
19 | pcs_L = PicoSpeaker(26)
20 | pcs_R = PicoSpeaker(27)
21 | pc_terminal = vt.vt(pc_display, pc_keyboard, sd=pc_sd())
22 |
23 | _usb = sys.stdout #
24 |
25 | def usb_debug(msg):
26 | if isinstance(msg, str):
27 | _usb.write(msg)
28 | else:
29 | _usb.write(str(msg))
30 | _usb.write('\r\n')
31 | picocalc.usb_debug = usb_debug
32 |
33 | picocalc.display = pc_display
34 | picocalc.keyboard = pc_keyboard
35 | picocalc.terminal = pc_terminal
36 | picocalc.sd = pc_sd
37 | builtins.em=em
38 | def edit(*args, tab_size=2, undo=50):
39 | #dry the key buffer before editing
40 | pc_terminal.dryBuffer()
41 | return pye_edit(args, tab_size=tab_size, undo=undo, io_device=pc_terminal)
42 | picocalc.edit = edit
43 |
44 | os.dupterm(pc_terminal)
45 | pc_sd.check_mount()
46 | #usb_debug("boot.py done.")
47 |
48 | except Exception as e:
49 | import sys
50 | sys.print_exception(e)
51 | try:
52 | os.dupterm(None).write(b"[boot.py error]\n")
53 | except:
54 | pass
55 | gc.collect()
56 |
--------------------------------------------------------------------------------
/pico_files/examples/mandelbrot.py:
--------------------------------------------------------------------------------
1 | from picocalc import display, terminal,keyboard
2 | import time
3 | import micropython
4 | display.switchPredefinedLUT('pico8')
5 | MAX_ITER = 16
6 |
7 | # fixed-point
8 | FIXED_SHIFT = 10 # =*1024
9 | FIXED_ONE = 1 << FIXED_SHIFT
10 |
11 | @micropython.viper
12 | def mandelbrot_pixel(cx: int, cy: int, max_iter: int, fixed_shift: int) -> int:
13 | zx = 0
14 | zy = 0
15 | for i in range(max_iter):
16 | zx2 = (zx * zx) >> fixed_shift
17 | zy2 = (zy * zy) >> fixed_shift
18 | if zx2 + zy2 > (4 << fixed_shift):
19 | return i
20 | zxy = (zx * zy) >> (fixed_shift - 1)
21 | zy = zxy + cy
22 | zx = zx2 - zy2 + cx
23 | return max_iter
24 |
25 | @micropython.native
26 | def render_mandelbrot(scale=1024, center_x=0, center_y=0):
27 | span_x = (3 * FIXED_ONE) * FIXED_ONE // scale
28 | span_y = (3 * FIXED_ONE) * FIXED_ONE // scale
29 | max_iter = 16
30 |
31 | for y in range(312):
32 | cy = center_y - (span_y // 2) + (y * span_y) // 320
33 | for x in range(320):
34 | cx = center_x - (span_x // 2) + (x * span_x) // 320
35 | m = mandelbrot_pixel(cx, cy, max_iter, FIXED_SHIFT)
36 | if m == max_iter:
37 | color = 0
38 | else:
39 | color = (m % 15) + 1
40 | display.pixel(x, y, color)
41 |
42 |
43 | terminal.dryBuffer()
44 | #terminal.stopRefresh()
45 | terminal.wr("\x1b[?25l") # hide cursor
46 | temp =bytearray(1)
47 | for zoom in range(1024, 8192, 64): # from 1x to 8x zoom
48 | render_mandelbrot(scale=zoom, center_x=0, center_y=0)
49 | terminal.wr("\x1b[40;1HPress any key to break...")
50 | #display.show() # show in manual refresh mode
51 | if keyboard.readinto(temp):
52 | break
53 | time.sleep(0.1)
54 |
55 |
56 | #terminal.wr("\x1b[40;1HPress any key to continue...")
57 | #terminal.rd()
58 | del temp,MAX_ITER, FIXED_SHIFT, FIXED_ONE, render_mandelbrot
59 | display.fill(0) #clean the screen
60 | display.restLUT()
61 | terminal.wr("\x1b[2J\x1b[H")#move the cursor to the top, and clear the terminal buffer
62 | #terminal.recoverRefresh()
63 | terminal.wr("\x1b[?25h") # show cursor
--------------------------------------------------------------------------------
/pico_files/examples/rotation.py:
--------------------------------------------------------------------------------
1 | import math
2 | from picocalc import display,terminal
3 |
4 | # ------------------------------------------------------------------
5 | # VT100 palette index (4 bit, format: BRIGHT R G B)
6 | # bit3 = BRIGHT (1 = bright version), bit2 = Red, bit1 = Green, bit0 = Blue
7 | # 0: Black 1: Red 2: Green 3: Yellow
8 | # 4: Blue 5: Magenta 6: Cyan 7: White
9 | # 8: Bright Black(Gray) 9: Bright Red 10: Bright Green 11: Bright Yellow
10 | # 12: Bright Blue 13: Bright Magenta 14: Bright Cyan 15: Bright White
11 | # ------------------------------------------------------------------
12 |
13 | def rgb(r, g, b):
14 |
15 | bright = 1 if max(r, g, b) > 127 else 0
16 | red = 1 if r > 127 else 0
17 | green = 1 if g > 127 else 0
18 | blue = 1 if b > 127 else 0
19 | return (bright << 3) | (red << 2) | (green << 1) | blue
20 |
21 | def rotation(width, height, fun, fb):
22 |
23 | w2 = width // 2
24 | h2 = height // 2
25 |
26 | fb.fill(0)
27 |
28 | m = n = 0
29 |
30 | for x in range(w2):
31 | p = int(math.sqrt(w2*w2 - x*x))
32 | for v in range(2 * p):
33 | z = v - p
34 | r_val = math.sqrt(x*x + z*z) / w2
35 | q = fun(r_val)
36 | y = round(z/3 + q * h2)
37 |
38 | c = rgb(int(r_val*255), int((1-r_val)*255), 128)
39 |
40 | if v == 0:
41 | m = n = y
42 | draw = True
43 | elif y > m:
44 | m = y
45 | draw = True
46 | elif y < n:
47 | n = y
48 | draw = True
49 | else:
50 | draw = False
51 |
52 | if draw:
53 | # 对称画两点
54 | fb.pixel(w2 - x, h2 - y, c)
55 | fb.pixel(w2 + x, h2 - y, c)
56 |
57 |
58 | WIDTH, HEIGHT = 320,312
59 |
60 |
61 |
62 | def my_fun(r):
63 | return (r - 1) * math.sin(r * 24)
64 | #return 2.5 * (1 - r) * (1 - r) + 2 * r * r * 0.7 - 1.5
65 | #return (math.sin(r * 2 * math.pi) + 1) / 2
66 |
67 |
68 | terminal.dryBuffer()
69 | #terminal.stopRefresh()
70 | terminal.wr("\x1b[?25l") # hide cursor
71 | # Execute rotation drawing
72 | rotation(WIDTH, HEIGHT, my_fun, display)
73 |
74 | terminal.wr("\x1b[40;1HPress any key to continue...")
75 | terminal.rd()
76 | display.fill(0) #clean the screen
77 | terminal.wr("\x1b[2J\x1b[H")#move the cursor to the top, and clear the terminal buffer
78 |
79 | del WIDTH
80 | del HEIGHT
81 |
82 |
83 |
84 | #terminal.recoverRefresh()
85 | terminal.wr("\x1b[?25h") # show cursor
86 |
87 |
--------------------------------------------------------------------------------
/pico_files/modules/vt.py:
--------------------------------------------------------------------------------
1 | from collections import deque
2 | import uio
3 | import vtterminal
4 | from micropython import const
5 | import time
6 | import uos
7 | from picocalc_system import screenshot_bmp
8 |
9 | sc_char_width = const(53)
10 | sc_char_height = const(40)
11 |
12 | def ensure_nested_dir(path):
13 | parts = path.split("/")
14 | current = ""
15 | for part in parts:
16 | if not part:
17 | continue
18 | current = current + "/" + part if current else part
19 | try:
20 | uos.stat(current)
21 | except OSError:
22 | uos.mkdir(current)
23 |
24 |
25 |
26 | class vt(uio.IOBase):
27 |
28 |
29 | def __init__(self,framebuf,keyboard,screencaptureKey=0x15,sd=None,captureFolder="/"): #ctrl+U for screen capture
30 | if sd != None:
31 | if not captureFolder.startswith("/"):
32 | captureFolder = "/"+captureFolder
33 | captureFolder = '/sd'+captureFolder
34 | if not captureFolder.endswith("/"):
35 | captureFolder = captureFolder+"/"
36 | self.captureFolder = captureFolder
37 | ensure_nested_dir(self.captureFolder)
38 |
39 | self.framebuf = framebuf
40 | self.sd = sd
41 | self.keyboardInput = bytearray(30)
42 | self.outputBuffer = deque((), 30)
43 | vtterminal.init(self.framebuf)
44 | self.keyboard = keyboard
45 | self.screencaptureKey = screencaptureKey
46 |
47 | def screencapture(self):
48 | if self.sd:
49 | filename = "{}screen_{}.bmp".format(self.captureFolder, time.ticks_ms())
50 | #with open(filename, "wb") as f:
51 | # f.write(self.framebuf.buffer)
52 | screenshot_bmp(self.framebuf.buffer, filename)
53 | return True
54 | return False
55 |
56 | def dryBuffer(self):
57 | self.outputBuffer = deque((), 30)
58 |
59 |
60 | def stopRefresh(self):
61 | self.framebuf.stopRefresh()
62 |
63 | def recoverRefresh(self):
64 | self.framebuf.recoverRefresh()
65 |
66 | def wr(self,input):
67 | #print("WR:", repr(input))
68 | for c in input:
69 | if ord(c) == 0x07:
70 | pass
71 | else:
72 | vtterminal.printChar(ord(c))
73 | return len(input)
74 |
75 | def write(self, buf):
76 | return self.wr(buf.decode())
77 |
78 | def get_screen_size(self):
79 | return[sc_char_height,sc_char_width]
80 |
81 | def _updateInternalBuffer(self):
82 | s = vtterminal.read()
83 | if s:
84 | try:
85 | self.outputBuffer.extend(ord(ch) for ch in s)
86 | except TypeError:
87 | raise ValueError("vtterminal.read() must return str")
88 | except ValueError:
89 | raise ValueError("Non-ASCII character in vtterminal.read()")
90 |
91 | n = self.keyboard.readinto(self.keyboardInput)
92 | if n:
93 | keys = bytes(self.keyboardInput[:n])
94 | if self.screencaptureKey in keys:
95 | self.screencapture()
96 | self.outputBuffer.extend(self.keyboardInput[:n])
97 |
98 | def rd(self):
99 | while not self.outputBuffer:
100 | self._updateInternalBuffer()
101 |
102 | return chr(self.outputBuffer.popleft())
103 |
104 |
105 | def rd_raw(self):
106 | return self.rd()
107 |
108 | def readinto(self, buf):
109 | self._updateInternalBuffer()
110 | count = 0
111 | buf_len = len(buf)
112 | for i in range(buf_len):
113 | if self.outputBuffer:
114 | buf[i] = self.outputBuffer.popleft()
115 | count += 1
116 | else:
117 | break
118 | return count if count > 0 else None
119 |
--------------------------------------------------------------------------------
/pico_files/modules/highlighter.py:
--------------------------------------------------------------------------------
1 | import micropython
2 |
3 |
4 | _RESET = "\x1b[0m"
5 |
6 |
7 | DELIMITERS = " \t\n+-*/=<>()[]{}:,;\"'#"
8 |
9 | COMPOUND_DELIMITERS = ["==", "!=", "<=", ">=", "->", "+=", "-=", "*=", "/="]
10 |
11 | class Highlighter:
12 | def __init__(self, syntax_style=None, max_tokens=300):
13 | self.syntax_style = syntax_style
14 | self.max_tokens = max_tokens
15 | self.token_boundaries = bytearray(max_tokens * 2)
16 | self.token_types = bytearray(max_tokens)
17 |
18 | @micropython.native
19 | def highlight_line(self, line):
20 | code_part, comment_part = self._strip_comment(line)
21 | token_count = self._tokenize(code_part)
22 | result = self._build_highlighted_output(code_part, token_count)
23 | if comment_part:
24 | comment_style = self.syntax_style.get("#", "")
25 | if comment_style:
26 | result += comment_style + comment_part + _RESET
27 | else:
28 | result += comment_part
29 |
30 | return result
31 |
32 | def _tokenize(self, text):
33 | i = 0
34 | token_idx = 0
35 | text_len = len(text)
36 | in_str = False
37 | str_char = None
38 | start_pos = 0
39 |
40 | TOKEN_NORMAL = 0
41 | TOKEN_STRING = 1
42 |
43 | while i < text_len and token_idx < self.max_tokens:
44 | char = text[i]
45 | if in_str:
46 | if char == str_char and (i == 0 or text[i-1] != '\\'):
47 | in_str = False
48 | self.token_boundaries[token_idx*2] = start_pos
49 | self.token_boundaries[token_idx*2+1] = i + 1
50 | self.token_types[token_idx] = TOKEN_STRING
51 | token_idx += 1
52 | start_pos = i + 1
53 | i += 1
54 | continue
55 |
56 | if char in "\"'":
57 | if start_pos < i:
58 | self.token_boundaries[token_idx*2] = start_pos
59 | self.token_boundaries[token_idx*2+1] = i
60 | self.token_types[token_idx] = TOKEN_NORMAL
61 | token_idx += 1
62 | in_str = True
63 | str_char = char
64 | start_pos = i
65 | i += 1
66 | continue
67 | is_compound = False
68 | if i < text_len - 1:
69 | possible_compound = text[i:i+2]
70 | if possible_compound in COMPOUND_DELIMITERS:
71 | if start_pos < i:
72 | self.token_boundaries[token_idx*2] = start_pos
73 | self.token_boundaries[token_idx*2+1] = i
74 | self.token_types[token_idx] = TOKEN_NORMAL
75 | token_idx += 1
76 | self.token_boundaries[token_idx*2] = i
77 | self.token_boundaries[token_idx*2+1] = i + 2
78 | self.token_types[token_idx] = TOKEN_NORMAL
79 | token_idx += 1
80 | start_pos = i + 2
81 | i += 2
82 | is_compound = True
83 | continue
84 | if not is_compound and char in DELIMITERS:
85 | if start_pos < i:
86 | self.token_boundaries[token_idx*2] = start_pos
87 | self.token_boundaries[token_idx*2+1] = i
88 | self.token_types[token_idx] = TOKEN_NORMAL
89 | token_idx += 1
90 |
91 | self.token_boundaries[token_idx*2] = i
92 | self.token_boundaries[token_idx*2+1] = i + 1
93 | self.token_types[token_idx] = TOKEN_NORMAL
94 | token_idx += 1
95 |
96 | start_pos = i + 1
97 |
98 | i += 1
99 | if start_pos < text_len and token_idx < self.max_tokens:
100 | self.token_boundaries[token_idx*2] = start_pos
101 | self.token_boundaries[token_idx*2+1] = text_len
102 | self.token_types[token_idx] = TOKEN_NORMAL
103 | token_idx += 1
104 |
105 | return token_idx
106 |
107 | def _build_highlighted_output(self, text, token_count):
108 | result = ""
109 | TOKEN_NORMAL = 0
110 | TOKEN_STRING = 1
111 |
112 | for i in range(token_count):
113 | start = self.token_boundaries[i*2]
114 | end = self.token_boundaries[i*2+1]
115 | token = text[start:end]
116 | token_type = self.token_types[i]
117 | if token_type == TOKEN_STRING:
118 | style = self.syntax_style.get("string", "")
119 | if style:
120 | result += style + token + _RESET
121 | else:
122 | result += token
123 | else:
124 | style = self.syntax_style.get(token)
125 | if style:
126 | result += style + token + _RESET
127 | else:
128 | result += token
129 |
130 | return result
131 |
132 | def _strip_comment(self, line):
133 | in_str = False
134 | esc = False
135 | quote = None
136 |
137 | for i, ch in enumerate(line):
138 | if esc:
139 | esc = False
140 | continue
141 | if ch == "\\":
142 | esc = True
143 | continue
144 | if ch in ("'", '"'):
145 | if not in_str:
146 | in_str, quote = True, ch
147 | elif ch == quote:
148 | in_str = False
149 | elif ch == "#" and not in_str:
150 | return line[:i], line[i:]
151 |
152 | return line, ""
153 |
154 |
155 |
--------------------------------------------------------------------------------
/pico_files/modules/picocalc_system.py:
--------------------------------------------------------------------------------
1 | """
2 | PicoCalc system functions for micropython
3 | Written by: Laika, 4/19/2025
4 |
5 | Requires sdcard.py from the official Micropython repository
6 | https://github.com/micropython/micropython-lib/blob/master/micropython/drivers/storage/sdcard/sdcard.py
7 |
8 | Features various system functions such as mounting and unmounting the PicoCalc's SD card, a nicer run utility, and an ls utility
9 |
10 | """
11 | import os
12 | import uos
13 | import machine
14 | import sdcard
15 | import gc
16 | from micropython import const
17 | import picocalc
18 | from colorer import Fore, Back, Style, print, autoreset
19 |
20 | autoreset(True)
21 |
22 |
23 | def human_readable_size(size):
24 | """
25 | Returns input size in bytes in a human-readable format
26 |
27 | Inputs: size in bytes
28 | Outputs: size in closest human-readable unit
29 | """
30 | for unit in ['bytes', 'KB', 'MB', 'GB', 'TB']:
31 | if size < 1024:
32 | return f"{size:.2f} {unit}"
33 | size /= 1024
34 | # Fallthrough isnt even possible to be needed on the PicoCalc, neither is TB, but its a universal function
35 | return f"{size:.2f} PB"
36 |
37 | def is_dir(path):
38 | """
39 | Helper function to shittily replace os.path.exists (not in micropython)
40 | Absolutely not a good replacement, but decent enough for seeing if the SD is mounted
41 |
42 | Inputs: path to check for
43 | Outputs: boolean if path is found
44 | """
45 | # List the root directory to check for the existence of the desired path
46 | try:
47 | directories = os.listdir('/')
48 | return path.lstrip('/') in directories
49 | except OSError:
50 | return False
51 |
52 | def prepare_for_launch(keep_vars=( "gc", "__name__")):
53 | for k in list(globals()):
54 | if k not in keep_vars:
55 | del globals()[k]
56 | gc.collect()
57 |
58 | #provided by _burr_
59 | def screenshot_bmp(buffer, filename, width=320, height=320, palette=None):
60 | FILE_HEADER_SIZE = const(14)
61 | INFO_HEADER_SIZE = const(40)
62 | PALETTE_SIZE = const(16 * 4) # 16 colors × 4 bytes (BGRA)
63 |
64 | # Default VT100 16-color palette
65 | if palette is None:
66 | lut = picocalc.display.getLUT() #get memoryview of the current LUT
67 | palette = []
68 | for i in range(16):
69 | raw = lut[i]
70 | raw = ((raw & 0xFF) << 8) | (raw >> 8)
71 |
72 | r = ((raw >> 11) & 0x1F) << 3
73 | g = ((raw >> 5) & 0x3F) << 2
74 | b = (raw & 0x1F) << 3
75 | palette.append((r, g, b))
76 | '''
77 | palette = [
78 | (0x00, 0x00, 0x00), # 0 black
79 | (0x80, 0x00, 0x00), # 1 red
80 | (0x00, 0x80, 0x00), # 2 green
81 | (0x80, 0x80, 0x00), # 3 yellow
82 | (0x00, 0x00, 0x80), # 4 blue
83 | (0x80, 0x00, 0x80), # 5 magenta
84 | (0x00, 0x80, 0x80), # 6 cyan
85 | (0xc0, 0xc0, 0xc0), # 7 white (light gray)
86 | (0x80, 0x80, 0x80), # 8 bright black (dark gray)
87 | (0xff, 0x00, 0x00), # 9 bright red
88 | (0x00, 0xff, 0x00), # 10 bright green
89 | (0xff, 0xff, 0x00), # 11 bright yellow
90 | (0x00, 0x00, 0xff), # 12 bright blue
91 | (0xff, 0x00, 0xff), # 13 bright magenta
92 | (0x00, 0xff, 0xff), # 14 bright cyan
93 | (0xff, 0xff, 0xff), # 15 bright white
94 | ]
95 | '''
96 | row_bytes = ((width + 1) // 2 + 3) & ~3 # align to 4-byte boundary
97 | pixel_data_size = row_bytes * height
98 | file_size = FILE_HEADER_SIZE + INFO_HEADER_SIZE + PALETTE_SIZE + pixel_data_size
99 | pixel_data_offset = FILE_HEADER_SIZE + INFO_HEADER_SIZE + PALETTE_SIZE
100 |
101 | with open(filename, "wb") as f:
102 | # BMP file header
103 | f.write(b'BM')
104 | f.write(file_size.to_bytes(4, 'little'))
105 | f.write((0).to_bytes(4, 'little')) # Reserved
106 | f.write(pixel_data_offset.to_bytes(4, 'little'))
107 |
108 | # DIB header
109 | f.write(INFO_HEADER_SIZE.to_bytes(4, 'little'))
110 | f.write(width.to_bytes(4, 'little'))
111 | f.write(height.to_bytes(4, 'little'))
112 | f.write((1).to_bytes(2, 'little')) # Planes
113 | f.write((4).to_bytes(2, 'little')) # Bits per pixel
114 | f.write((0).to_bytes(4, 'little')) # No compression
115 | f.write(pixel_data_size.to_bytes(4, 'little'))
116 | f.write((0).to_bytes(4, 'little')) # X pixels per meter
117 | f.write((0).to_bytes(4, 'little')) # Y pixels per meter
118 | f.write((16).to_bytes(4, 'little')) # Colors in palette
119 | f.write((0).to_bytes(4, 'little')) # Important colors
120 |
121 | # Palette (BGRA)
122 | for r, g, b in palette:
123 | f.write(bytes([b, g, r, 0]))
124 |
125 | # Pixel data (bottom-up)
126 | for row in range(height - 1, -1, -1):
127 | start = row * ((width + 1) // 2)
128 | row_data = buffer[start:start + ((width + 1) // 2)]
129 | f.write(row_data)
130 | f.write(bytes(row_bytes - len(row_data))) # Padding
131 |
132 |
133 | def run(filename):
134 | """
135 | Simple run utility.
136 | Attempts to run python file provided by filename, returns when done.
137 |
138 | Inputs: python file filename/filepath
139 | Outputs: None, runs file
140 | """
141 | try:
142 | exec(open(filename).read(), globals())
143 | except OSError:
144 | print(f"Failed to open file: {filename}")
145 | except Exception as e:
146 | print(f"An error occurred: {e}")
147 | return
148 |
149 | def files(directory="/"):
150 | """
151 | Basic ls port.
152 |
153 | Inputs: directory/filepath to list files and directories in
154 | Outputs: Print of all files and directories contained, along with size
155 | """
156 | try:
157 | # List entries in the specified directory
158 | entries = uos.listdir(directory)
159 | except OSError as e:
160 | print(f"Error accessing directory {directory}: {e}")
161 | return
162 |
163 | print(f"\nContents of directory: {directory}\n")
164 | for entry in entries:
165 | try:
166 | # Construct the full path
167 | full_path = directory.rstrip("/") + "/" + entry
168 | stat = uos.stat(full_path)
169 | size = stat[6]
170 |
171 | # Check if entry is a directory or a file
172 | if stat[0] & 0x4000: # Directory
173 | print(f"{entry:<25}
")
174 | else: # File
175 | readable_size = human_readable_size(size)
176 | print(f"{entry:<25} {readable_size:<9}")
177 | except OSError as e:
178 | print(f"Error accessing {entry}: {e}")
179 | return
180 |
181 | def memory():
182 | gc.collect()
183 | # Get the available and free RAM
184 | free_memory = gc.mem_free()
185 | allocated_memory = gc.mem_alloc()
186 |
187 | # Total memory is the sum of free and allocated memory
188 | total_memory = free_memory + allocated_memory
189 |
190 | human_readable_total = human_readable_size(total_memory)
191 | human_readable_free = human_readable_size(free_memory)
192 |
193 | print(f"Total RAM: {human_readable_total}")
194 | print(f"Free RAM: {human_readable_free}")
195 |
196 | def disk():
197 | """
198 | Prints available flash and SD card space (if mounted) as well as totals
199 |
200 | Input: None
201 | Outputs: None, prints disk statuses
202 | """
203 | filesystem_paths = ['/', '/sd']
204 | for path in filesystem_paths:
205 | if is_dir(path) or path == '/':
206 | if path == '/sd':
207 | # Indicate SD card status
208 | print("SD card mounted.")
209 | print("Indexing SD Card, Please Wait.")
210 | try:
211 | fs_stat = os.statvfs(path)
212 | block_size = fs_stat[1]
213 | total_blocks = fs_stat[2]
214 | free_blocks = fs_stat[3]
215 | total_size = total_blocks * block_size
216 | free_size = free_blocks * block_size
217 | human_readable_total = human_readable_size(total_size)
218 | human_readable_free = human_readable_size(free_size)
219 |
220 | if path == '/':
221 | print(f"Total filesystem size: {human_readable_total}")
222 | print(f"Free filesystem space: {human_readable_free}")
223 | else:
224 | print(f"Total SD size: {human_readable_total}")
225 | print(f"Free SD space: {human_readable_free}")
226 |
227 | except OSError:
228 | print(f"Unexpected error accessing filesystem at '{path}'.")
229 |
230 | else:
231 | if path == '/sd':
232 | print("No SD Card Mounted.")
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # MicroPython Drivers for PicoCalc
4 | 
5 | ## Build Instructions
6 |
7 | ```
8 | Folder structure:
9 |
10 | |
11 | |- micropython # Clone the MicroPython repo here
12 | | |- ports
13 | | |- rp2
14 | | |- build # Create this build folder
15 | | |- modules # Place all py files from pico_files/modules/
16 | |
17 | |- PicoCalc-micropython-driver # Driver modules
18 | | |- picocalcdisplay
19 | | |- vtterminal
20 | |
21 | |- Any additional modules (e.g., ulab, etc.)
22 | ```
23 |
24 | Copy all files from pico_files/modules/ to micropython/ports/rp2/modules/ folder
25 | Build MicroPython as usual, while including user modules:
26 | ```sh
27 | cd micropython/ports/rp2
28 | git submodule update --init --recursive
29 | mkdir build && cd build
30 | cmake .. \
31 | -DUSER_C_MODULES="Path/To/PicoCalc-micropython-driver/picocalcdisplay/micropython.cmake;Path/To/PicoCalc-micropython-driver/vtterminal/micropython.cmake" \
32 | -DMICROPY_BOARD=[TARGET_BOARD]
33 | ```
34 |
35 | Supported `TARGET_BOARD` values:
36 | - `RPI_PICO`
37 | - `RPI_PICO2`
38 | - `RPI_PICO2_W`
39 |
40 | (Other boards are untested.)
41 |
42 | ---
43 |
44 | ## Installation
45 | ### With filesystem
46 | The uf2 file already included file system and main.py, boot.py. Just flash it and remove the usb link to the pico module, tune on the picocalc.(The auto reboot seems to be broken, after copy finished, the usb driver won't disappear. That's ok, let me check how to fix it >_<>)
47 | - **NO FILE COPY NEEDED!! The old file system will be destroyed!**
48 |
49 | - picocalc_micropython_ulab_eigenmath_withfilesystem_pico2.uf2 (you could use it with your pico 2 or pico 2w module)
50 | Included ulab, eigenmath port (https://github.com/zenodante/eigenmath_micropython), make picocalc a full function advanced calculator!
51 | - picocalc_micropython_withfilesystem_pico.uf2 (for pico)
52 | Only REPL, code editor
53 | - picocalc_micropython_withfilesystem_pico2.uf2 (for pico 2)
54 | Only REPL, code editor
55 | - picocalc_micropython_withfilesystem_pico2w.uf2 (for pico 2w)
56 | Only REPL, code editor
57 |
58 | ### Without filesystem uf2
59 | the filesystem in the pico module is safe, it won't be overwrite during your firmware upgrade.
60 | - picocalc_micropython_NOfilesystem_pico.uf2
61 | - picocalc_micropython_NOfilesystem_pico2.uf2
62 | - picocalc_micropython_NOfilesystem_pico2w.uf2
63 | - Flash the compiled `.uf2` to your Pico as usual.
64 | - **Place only `main.py,boot.py` from pico_files/root/ in the pico root directory.**
65 | - Copy '/examples/' to pico root (if you want)
66 | - **Delete all existing `.py` files in `/lib`** (e.g., `fbconsole.py`, `picocalc.py`, etc.).
67 | > These modules are already *frozen* into the firmware!
68 |
69 | Using Thonny is the easiest method for file transfer and interaction.
70 |
71 | If the flash nuke is needed, flash as normal, however **DO NOT UNPLUG** until the on-board light flashes to indicate it is done.
72 | ---
73 |
74 | ## Features
75 |
76 | ### ✅ Keyboard Driver
77 | Fully functional and tested. Works seamlessly with vt100 terminal emulator.
78 |
79 | ### ✅ ILI9488 Display Driver (C module + Python interface)
80 | - C module supports high-speed 1/2/4/8-bit LUT drawing and 16-bit 565RGB.
81 | - Python wrapper uses `framebuf` interface and handles display swapping.
82 | - Display updates now run on `core1` for a smoother REPL experience.
83 |
84 | ### ✅ screen capture
85 | - Using ctrl + u to capture screen buffer into your sd card. currently only at the root of the sd card
86 | The Data is in raw type. For default 16 color framebuff copy, it is 50kB each. Left pixel in high 4 bit.
87 | Standard vt 100 16 color map may use to rebuild the image. I will upload a python script to convert it.
88 |
89 | ### ✅ Speaker Driver
90 | Enabled by LaikaSpaceDawg!
91 |
92 |
93 | ---
94 |
95 | ## Usage Notes
96 |
97 | #### Working with WIFI on picoW/2W
98 | The wifi chip connect to the rp2040/2350 via spi1, which shared with LCD. As we autorefresh the lcd on core1, it is necessary to stop the auto refresh function first via the function:
99 | pc_terminal.stopRefresh(), after wifi finish its work, use pc_terminal.recoverRefresh() to recover the LCD refreshing.
100 |
101 | ### Internal code editor
102 | You can launch the built-in Python code editor by calling:
103 | ```python
104 | edit("abc.py")
105 | ```
106 | 
107 | Editor is based on [robert-hh/Micropython-Editor](https://github.com/robert-hh/Micropython-Editor)
108 | Now with keyword highlighting support.
109 | ### run examples
110 | Copy examples folder under pico_files to your pico module root.
111 | Run it via command
112 | ```python
113 | run('/examples/rotation.py')
114 | ```
115 | 
116 |
117 |
118 |
119 | ### Using eigenmath
120 |
121 | I initialize Eigenmath early during system startup because it requires a contiguous 300kB block from the MicroPython heap. If we delay this allocation until later stages of the boot process, heap fragmentation may prevent us from obtaining such a large continuous memory region. Therefore, we allocate it at the beginning. So there is a special boot.py in root_eigenmath folder. If you are using the picocalc_micropython_ulab_eigenmath_withfilesystem_pico2.uf2, it is already included.
122 | ```python
123 | #import eigenmath #not necessary, init in the boot
124 | #em = eigenmath.EigenMath(300*1024) #the internal heap size, eigenmath needs A LOT OF RAM. It will be released after you delete the em instance
125 | em.status() #show current resource status
126 | em.run("d(sin(x),x)") #do math calculation, check the eigenmath manual for more details
127 | em.reset() #reset the internal sources
128 |
129 | #if you don't need it anymore
130 | del builtins.em #del the eigenmath from root
131 | gc.collect()
132 | ```
133 |
134 | ## color and screen frame buffer
135 |
136 |
137 |
138 | ### Accessing the Display
139 |
140 | The screen is exposed via `picocalc.display`, which is an instance of the `PicoDisplay` class (a subclass of `framebuf`). You can use **all** standard `framebuf` methods to draw on it.
141 |
142 | ### VT100 Emulator Mode
143 |
144 | - Runs in **4-bit color (16 colors)** mode to save limited RAM (≈50 KB).
145 | - Uses an **internal color lookup table (LUT)** to map logical VT100 colors to the actual RGB565 values sent to the panel.
146 |
147 | ### Color Lookup Table (LUT)
148 |
149 | - **Reset to the default VT100 palette**
150 | ```python
151 | picocalc.display.resetLUT()
152 | ```
153 | - **Switch to a predefined LUT**
154 | ```python
155 | picocalc.display.switchPredefinedLUT("name")
156 | ```
157 | Available presets: `"vt100"`, `"pico8"` (more coming soon).
158 |
159 | ### Inspecting and Modifying the LUT
160 |
161 | - **Get the current LUT**
162 | ```python
163 | lut = picocalc.display.getLUT()
164 | ```
165 | Returns a 256-entry, big-endian 16-bit array you can read from or write to directly.
166 |
167 | - **Note on color format**
168 | - The display expects **RGB565** values.
169 | - Because of SPI byte‐order, you must **swap high/low bytes** when writing back to the LUT.
170 |
171 | - **Set a custom LUT**
172 | ```python
173 | picocalc.display.setLUT(custom_array)
174 | ```
175 | Accepts up to 256 16-bit elements to override the existing table.
176 |
177 | > **Example usage:** see `examples/mandelbrot.py`.
178 |
179 | ### Core Usage & Refresh Modes
180 |
181 | By default:
182 |
183 | - **Core 0** runs the MicroPython VM.
184 | - **Core 1** continuously performs color conversion and refreshes the screen in the background.
185 |
186 | You can switch to **passive refresh mode**:
187 | Please refer the /examples/refresh.py for more details.
188 | ```python
189 | # stop auto refresh
190 | picocalc.display.stopRefresh()
191 | # recover auto refresh
192 | picocalc.display.recoverRefresh()
193 | # manually update the screen by core 0, default is done by core 1, so you could use all core 0 for other logic
194 | picocalc.display.show(0)
195 | # wait the manual refresh function release the vram. If you use the manual refuresh function
196 | picocalc.display.isScreenUpdateDone()
197 | ```
198 |
199 | - In passive mode, the screen only updates when you explicitly call:
200 | ```python
201 | picocalc.display.show(core=1)
202 | ```
203 | - The `show()` method takes a `core` argument (`0` or `1`) to choose which core handles color conversion and DMA ping‐pong buffer setup.
204 | ```
205 |
206 |
207 |
208 | The REPL and editor both run inside a VT100 terminal emulator, based on
209 | [ht-deko/vt100_stm32](https://github.com/ht-deko/vt100_stm32), with bug fixes and additional features.
210 |
211 | ---
212 |
213 | ## Credits
214 | - [robert-hh/Micropython-Editor](https://github.com/robert-hh/Micropython-Editor)
215 | - [ht-deko/vt100_stm32](https://github.com/ht-deko/vt100_stm32)
216 | - `sdcard.py` is from the official MicroPython repository: [micropython-lib/sdcard.py](https://github.com/micropython/micropython-lib/blob/master/micropython/drivers/storage/sdcard/sdcard.py)
217 | - `flash_nuke.uf2` is from the Raspberry Pi Documentation: [Resetting Flash Memory](https://www.raspberrypi.com/documentation/microcontrollers/pico-series.html#resetting-flash-memory)
218 |
--------------------------------------------------------------------------------
/pico_files/examples/wave.py:
--------------------------------------------------------------------------------
1 | from picocalc import display,keyboard,terminal
2 | import math
3 | import micropython
4 | import gc
5 | from array import array
6 | import time
7 | # Enable full optimizations
8 | micropython.opt_level(3)
9 |
10 | # Initialize a 320×320, 4-bit grayscale framebuffer
11 | WIDTH, HEIGHT = 320, 312
12 |
13 |
14 | # Precompute constants
15 | GRID = 15
16 | GRID_POINTS = GRID * GRID
17 | HALF_WIDTH = WIDTH // 2
18 | HALF_HEIGHT = HEIGHT // 2
19 | FOCAL_LEN = 100
20 | MAX_COLOR = 15
21 |
22 | # Viewport boundaries for culling
23 | VIEWPORT_MIN_X = -20
24 | VIEWPORT_MAX_X = WIDTH + 20
25 | VIEWPORT_MIN_Y = -20
26 | VIEWPORT_MAX_Y = HEIGHT + 20
27 |
28 | # --- PRE-ALLOCATE ALL MEMORY STRUCTURES ---
29 |
30 | # Pre-allocate coords array
31 | coords = array('f', [0.0] * GRID)
32 | for i in range(GRID):
33 | coords[i] = ((i / (GRID-1)) * 2 - 1) * 1.2
34 |
35 | # Pre-allocate grid points - store as flat arrays for better memory efficiency
36 | grid_x = array('f', [0.0] * GRID_POINTS)
37 | grid_y = array('f', [0.0] * GRID_POINTS)
38 | grid_r = array('f', [0.0] * GRID_POINTS)
39 |
40 | # Fill the grid arrays
41 | idx = 0
42 | for gy in coords:
43 | for gx in coords:
44 | grid_x[idx] = gx
45 | grid_y[idx] = gy
46 | grid_r[idx] = math.sqrt(gx*gx + gy*gy)
47 | idx += 1
48 |
49 |
50 |
51 | # Pre-allocate arrays for projected coordinates
52 | proj_x = array('i', [0] * GRID_POINTS)
53 | proj_y = array('i', [0] * GRID_POINTS)
54 | proj_size = array('i', [0] * GRID_POINTS)
55 | proj_depth = array('f', [0.0] * GRID_POINTS)
56 | proj_color = array('i', [0] * GRID_POINTS)
57 | proj_visible = array('b', [0] * GRID_POINTS) # 0 = invisible, 1 = visible
58 |
59 | # Pre-allocate draw order array (indices into the projection arrays)
60 | draw_order = array('i', list(range(GRID_POINTS)))
61 |
62 | # Pre-allocate sine lookup table for faster sine calculations
63 | SIN_LUT_SIZE = 256
64 | sin_lut = array('f', [0.0] * SIN_LUT_SIZE)
65 | for i in range(SIN_LUT_SIZE):
66 | sin_lut[i] = math.sin(i * 2 * math.pi / SIN_LUT_SIZE)
67 |
68 | # Pre-allocate the sorting key array
69 | # This will hold depth values for the stable sorting algorithm
70 | sort_keys = array('f', [0.0] * GRID_POINTS)
71 |
72 | @micropython.native
73 | def fast_sin(angle: float) -> float:
74 | # Fast sine approximation using lookup table
75 | index = int((angle % (2 * math.pi)) * SIN_LUT_SIZE / (2 * math.pi))
76 | return sin_lut[index & (SIN_LUT_SIZE - 1)]
77 |
78 | # Simplified bubble sort for depth sorting - avoid creating new data structures
79 | @micropython.native
80 | def depth_sort(visible_count):
81 | # Copy depths to sort_keys array for items that are visible
82 | for i in range(visible_count):
83 | idx = draw_order[i]
84 | sort_keys[i] = proj_depth[idx]
85 |
86 | # Simple bubble sort - works well for mostly-sorted data as in 3D scenes
87 | for i in range(visible_count):
88 | for j in range(visible_count - i - 1):
89 | if sort_keys[j] < sort_keys[j + 1]:
90 | # Swap the sort keys
91 | sort_keys[j], sort_keys[j + 1] = sort_keys[j + 1], sort_keys[j]
92 | # Swap the indices in draw_order
93 | draw_order[j], draw_order[j + 1] = draw_order[j + 1], draw_order[j]
94 |
95 | # Combined rotation and perspective projection with viewport culling
96 | @micropython.native
97 | def transform_points(amplitude: float, freq: float, phase: float,
98 | cam_dist: float, cx: float, sx: float, cy: float, sy: float):
99 | # Reset visibility count
100 | visible_count = 0
101 |
102 | # Process all grid points
103 | for i in range(int(GRID_POINTS)):
104 | # Get original coordinates
105 | x0 = grid_x[i]
106 | y0 = grid_y[i]
107 | r = grid_r[i]
108 |
109 | # Compute height
110 | z0 = amplitude * fast_sin(r * 2 * math.pi * freq + phase)
111 |
112 | # Apply rotations - implemented inline to avoid function calls
113 | # First rotate around Y (horizontal rotation around center)
114 | x1 = z0 * sy + x0 * cy
115 | z1 = z0 * cy - x0 * sy
116 |
117 | # Then rotate around X (vertical tilt/pitch)
118 | y2 = y0 * cx - z1 * sx
119 | z2 = y0 * sx + z1 * cx
120 |
121 | # Store rotated point
122 | #point_x[i] = x1
123 | #point_y[i] = y2
124 | #point_z[i] = z2
125 |
126 | # Apply perspective projection
127 | z_adj = z2 + cam_dist
128 | if z_adj <= 0.001:
129 | z_adj = 0.001
130 |
131 | inv_z = FOCAL_LEN / z_adj
132 | px = int(x1 * inv_z) + HALF_WIDTH
133 | py = int(y2 * inv_z) + HALF_HEIGHT
134 |
135 | # Check if point is within viewport
136 | if (px < VIEWPORT_MIN_X or px > VIEWPORT_MAX_X or
137 | py < VIEWPORT_MIN_Y or py > VIEWPORT_MAX_Y):
138 | proj_visible[i] = 0 # Not visible
139 | continue
140 |
141 | # Store projected coordinates
142 | proj_x[i] = px
143 | proj_y[i] = py
144 | proj_size[i] = max(1, int(inv_z * 4))
145 | proj_depth[i] = z_adj
146 |
147 | # Calculate color based on height (z2 is the rotated z value)
148 | color = int(((z2 / amplitude) + 1) * 0.5 * MAX_COLOR)
149 | proj_color[i] = max(0, min(MAX_COLOR, color))
150 |
151 | # Mark as visible and add to draw order
152 | proj_visible[i] = 1
153 | draw_order[visible_count] = i
154 | visible_count += 1
155 |
156 | return visible_count
157 |
158 | # Main drawing function - completely rewritten to avoid memory allocations
159 | @micropython.native
160 | def draw_wave(amplitude, freq, phase, cam_dist, pitch, yaw):
161 | # Clear framebuffer
162 |
163 |
164 | # Precompute rotation values
165 | cx, sx = math.cos(pitch), math.sin(pitch)
166 | cy, sy = math.cos(yaw), math.sin(yaw)
167 |
168 |
169 | # Transform all points - apply rotation, projection, and viewport culling
170 | visible_count = transform_points(amplitude, freq, phase, cam_dist, cx, sx, cy, sy)
171 |
172 | # Skip sorting and drawing if no points are visible
173 | if visible_count == 0:
174 | return
175 |
176 | # Sort points by depth
177 | depth_sort(visible_count)
178 | while not display.isScreenUpdateDone():
179 | pass # Wait for previous screen update to finish
180 | # Draw points in back-to-front order
181 | display.fill(0)
182 | terminal.wr("\x1b[39;1Hvisible"+str(visible_count))
183 | for i in range(visible_count):
184 | # Get index from draw order
185 | idx = draw_order[i]
186 |
187 | # Skip if not visible (should not happen due to how visible_count works, but just in case)
188 | if not proj_visible[idx]:
189 | continue
190 |
191 | # Draw the point as a filled rectangle
192 | x = proj_x[idx]
193 | y = proj_y[idx]
194 | size = proj_size[idx]
195 | color = proj_color[idx]
196 |
197 | half_size = size // 2
198 | display.fill_rect(x - half_size, y - half_size, size, size, color)
199 |
200 | def processKey():
201 | # Read a key from the keyboard
202 | if keyboard.readinto(temp):
203 | key = temp[0]
204 | if key == ord('E') or key == ord('e'):
205 | return True
206 | return False
207 |
208 | terminal.dryBuffer()
209 |
210 |
211 | terminal.wr("\x1b[?25l") # hide cursor
212 | terminal.stopRefresh()
213 |
214 | gamma = 2.2
215 | # Predefine an array of 16 zeros (type 'H')
216 | color_lut = array('H', [0] * 16)
217 | for i in range(16):
218 | # normalized position [0..1]
219 | f = i / 15
220 | # gamma-corrected channel value [0..31]
221 | v = int(31 * (f ** (1 / gamma)) + 0.5)
222 | # red & blue channels for purple, green remains 0
223 | r5 = v
224 | g6 = 0
225 | b5 = v
226 | # pack into RGB565 format
227 | rgb565 = (r5 << 11) | (g6 << 5) | b5
228 | # swap bytes (low byte first)
229 | swapped = ((rgb565 & 0xFF) << 8) | (rgb565 >> 8)
230 | color_lut[i] = swapped
231 |
232 | display.setLUT(color_lut)
233 | temp =bytearray(30)
234 | amp = 0.5 # Amplitude of the wave
235 | freq = 0.5 # Frequency of the wave
236 | phase = 0.0 # Phase shift of the wave
237 | cam_dist = 10.0 # Camera distance from the wave
238 | pitch = 0.1 # Pitch rotation
239 | yaw = 0.1 # Yaw rotation
240 |
241 | while(True):
242 | phase += 0.05 # Increment phase for animation
243 | if phase > 2 * math.pi:
244 | phase -= 2 * math.pi # Reset phase to keep it within bounds
245 | if processKey():
246 | break
247 | draw_wave(amp, freq, phase, cam_dist, pitch, yaw)
248 | terminal.wr("\x1b[40;1HPress \'E\' to break...")
249 | display.show(0) # show in manual refresh mode
250 | #time.sleep(0.03)
251 |
252 |
253 | #terminal.wr("\x1b[40;1HPress any key to continue...")
254 | #terminal.rd()
255 | #del WIDTH, HEIGHT, GRID, GRID_POINTS, HALF_WIDTH, HALF_HEIGHT, FOCAL_LEN, MAX_COLOR
256 | #del VIEWPORT_MIN_X, VIEWPORT_MAX_X, VIEWPORT_MIN_Y, VIEWPORT_MAX_Y
257 | #del fast_sin, depth_sort, transform_points, draw_wave
258 | #del coords, grid_x, grid_y, grid_r
259 | #del proj_x, proj_y, proj_size, proj_depth, proj_color, proj_visible
260 | #del draw_order, sort_keys, sin_lut
261 | #del temp, amp, freq, phase, cam_dist, pitch, yaw
262 | #del color_lut,gamma
263 | gc.collect() # Run garbage collector to free up memory
264 | terminal.recoverRefresh()
265 | display.fill(0) #clean the screen
266 | display.restLUT()
267 | terminal.wr("\x1b[2J\x1b[H")#move the cursor to the top, and clear the terminal buffer
268 |
269 | terminal.wr("\x1b[?25h") # show cursor
--------------------------------------------------------------------------------
/pico_files/modules/sdcard.py:
--------------------------------------------------------------------------------
1 | """
2 | MicroPython driver for SD cards using SPI bus.
3 |
4 | Requires an SPI bus and a CS pin. Provides readblocks and writeblocks
5 | methods so the device can be mounted as a filesystem.
6 |
7 | Example usage on pyboard:
8 |
9 | import pyb, sdcard, os
10 | sd = sdcard.SDCard(pyb.SPI(1), pyb.Pin.board.X5)
11 | pyb.mount(sd, '/sd2')
12 | os.listdir('/')
13 |
14 | Example usage on ESP8266:
15 |
16 | import machine, sdcard, os
17 | sd = sdcard.SDCard(machine.SPI(1), machine.Pin(15))
18 | os.mount(sd, '/sd')
19 | os.listdir('/')
20 |
21 | """
22 |
23 | from micropython import const
24 | import time
25 |
26 |
27 | _CMD_TIMEOUT = const(100)
28 |
29 | _R1_IDLE_STATE = const(1 << 0)
30 | # R1_ERASE_RESET = const(1 << 1)
31 | _R1_ILLEGAL_COMMAND = const(1 << 2)
32 | # R1_COM_CRC_ERROR = const(1 << 3)
33 | # R1_ERASE_SEQUENCE_ERROR = const(1 << 4)
34 | # R1_ADDRESS_ERROR = const(1 << 5)
35 | # R1_PARAMETER_ERROR = const(1 << 6)
36 | _TOKEN_CMD25 = const(0xFC)
37 | _TOKEN_STOP_TRAN = const(0xFD)
38 | _TOKEN_DATA = const(0xFE)
39 |
40 |
41 | class SDCard:
42 | def __init__(self, spi, cs, baudrate=1320000):
43 | self.spi = spi
44 | self.cs = cs
45 |
46 | self.cmdbuf = bytearray(6)
47 | self.dummybuf = bytearray(512)
48 | self.tokenbuf = bytearray(1)
49 | for i in range(512):
50 | self.dummybuf[i] = 0xFF
51 | self.dummybuf_memoryview = memoryview(self.dummybuf)
52 |
53 | # initialise the card
54 | self.init_card(baudrate)
55 |
56 | def init_spi(self, baudrate):
57 | try:
58 | master = self.spi.MASTER
59 | except AttributeError:
60 | # on ESP8266
61 | self.spi.init(baudrate=baudrate, phase=0, polarity=0)
62 | else:
63 | # on pyboard
64 | self.spi.init(master, baudrate=baudrate, phase=0, polarity=0)
65 |
66 | def init_card(self, baudrate):
67 | # init CS pin
68 | self.cs.init(self.cs.OUT, value=1)
69 |
70 | # init SPI bus; use low data rate for initialisation
71 | self.init_spi(100000)
72 |
73 | # clock card at least 100 cycles with cs high
74 | for i in range(16):
75 | self.spi.write(b"\xff")
76 |
77 | # CMD0: init card; should return _R1_IDLE_STATE (allow 5 attempts)
78 | for _ in range(5):
79 | if self.cmd(0, 0, 0x95) == _R1_IDLE_STATE:
80 | break
81 | else:
82 | raise OSError("no SD card")
83 |
84 | # CMD8: determine card version
85 | r = self.cmd(8, 0x01AA, 0x87, 4)
86 | if r == _R1_IDLE_STATE:
87 | self.init_card_v2()
88 | elif r == (_R1_IDLE_STATE | _R1_ILLEGAL_COMMAND):
89 | self.init_card_v1()
90 | else:
91 | raise OSError("couldn't determine SD card version")
92 |
93 | # get the number of sectors
94 | # CMD9: response R2 (R1 byte + 16-byte block read)
95 | if self.cmd(9, 0, 0, 0, False) != 0:
96 | raise OSError("no response from SD card")
97 | csd = bytearray(16)
98 | self.readinto(csd)
99 | if csd[0] & 0xC0 == 0x40: # CSD version 2.0
100 | self.sectors = ((csd[8] << 8 | csd[9]) + 1) * 1024
101 | elif csd[0] & 0xC0 == 0x00: # CSD version 1.0 (old, <=2GB)
102 | c_size = (csd[6] & 0b11) << 10 | csd[7] << 2 | csd[8] >> 6
103 | c_size_mult = (csd[9] & 0b11) << 1 | csd[10] >> 7
104 | read_bl_len = csd[5] & 0b1111
105 | capacity = (c_size + 1) * (2 ** (c_size_mult + 2)) * (2**read_bl_len)
106 | self.sectors = capacity // 512
107 | else:
108 | raise OSError("SD card CSD format not supported")
109 | # print('sectors', self.sectors)
110 |
111 | # CMD16: set block length to 512 bytes
112 | if self.cmd(16, 512, 0) != 0:
113 | raise OSError("can't set 512 block size")
114 |
115 | # set to high data rate now that it's initialised
116 | self.init_spi(baudrate)
117 |
118 | def init_card_v1(self):
119 | for i in range(_CMD_TIMEOUT):
120 | time.sleep_ms(50)
121 | self.cmd(55, 0, 0)
122 | if self.cmd(41, 0, 0) == 0:
123 | # SDSC card, uses byte addressing in read/write/erase commands
124 | self.cdv = 512
125 | # print("[SDCard] v1 card")
126 | return
127 | raise OSError("timeout waiting for v1 card")
128 |
129 | def init_card_v2(self):
130 | for i in range(_CMD_TIMEOUT):
131 | time.sleep_ms(50)
132 | self.cmd(58, 0, 0, 4)
133 | self.cmd(55, 0, 0)
134 | if self.cmd(41, 0x40000000, 0) == 0:
135 | self.cmd(58, 0, 0, -4) # 4-byte response, negative means keep the first byte
136 | ocr = self.tokenbuf[0] # get first byte of response, which is OCR
137 | if not ocr & 0x40:
138 | # SDSC card, uses byte addressing in read/write/erase commands
139 | self.cdv = 512
140 | else:
141 | # SDHC/SDXC card, uses block addressing in read/write/erase commands
142 | self.cdv = 1
143 | # print("[SDCard] v2 card")
144 | return
145 | raise OSError("timeout waiting for v2 card")
146 |
147 | def cmd(self, cmd, arg, crc, final=0, release=True, skip1=False):
148 | self.cs(0)
149 |
150 | # create and send the command
151 | buf = self.cmdbuf
152 | buf[0] = 0x40 | cmd
153 | buf[1] = arg >> 24
154 | buf[2] = arg >> 16
155 | buf[3] = arg >> 8
156 | buf[4] = arg
157 | buf[5] = crc
158 | self.spi.write(buf)
159 |
160 | if skip1:
161 | self.spi.readinto(self.tokenbuf, 0xFF)
162 |
163 | # wait for the response (response[7] == 0)
164 | for i in range(_CMD_TIMEOUT):
165 | self.spi.readinto(self.tokenbuf, 0xFF)
166 | response = self.tokenbuf[0]
167 | if not (response & 0x80):
168 | # this could be a big-endian integer that we are getting here
169 | # if final<0 then store the first byte to tokenbuf and discard the rest
170 | if final < 0:
171 | self.spi.readinto(self.tokenbuf, 0xFF)
172 | final = -1 - final
173 | for j in range(final):
174 | self.spi.write(b"\xff")
175 | if release:
176 | self.cs(1)
177 | self.spi.write(b"\xff")
178 | return response
179 |
180 | # timeout
181 | self.cs(1)
182 | self.spi.write(b"\xff")
183 | return -1
184 |
185 | def readinto(self, buf):
186 | self.cs(0)
187 |
188 | # read until start byte (0xff)
189 | for i in range(_CMD_TIMEOUT):
190 | self.spi.readinto(self.tokenbuf, 0xFF)
191 | if self.tokenbuf[0] == _TOKEN_DATA:
192 | break
193 | time.sleep_ms(1)
194 | else:
195 | self.cs(1)
196 | raise OSError("timeout waiting for response")
197 |
198 | # read data
199 | mv = self.dummybuf_memoryview
200 | if len(buf) != len(mv):
201 | mv = mv[: len(buf)]
202 | self.spi.write_readinto(mv, buf)
203 |
204 | # read checksum
205 | self.spi.write(b"\xff")
206 | self.spi.write(b"\xff")
207 |
208 | self.cs(1)
209 | self.spi.write(b"\xff")
210 |
211 | def write(self, token, buf):
212 | self.cs(0)
213 |
214 | # send: start of block, data, checksum
215 | self.spi.read(1, token)
216 | self.spi.write(buf)
217 | self.spi.write(b"\xff")
218 | self.spi.write(b"\xff")
219 |
220 | # check the response
221 | if (self.spi.read(1, 0xFF)[0] & 0x1F) != 0x05:
222 | self.cs(1)
223 | self.spi.write(b"\xff")
224 | return
225 |
226 | # wait for write to finish
227 | while self.spi.read(1, 0xFF)[0] == 0:
228 | pass
229 |
230 | self.cs(1)
231 | self.spi.write(b"\xff")
232 |
233 | def write_token(self, token):
234 | self.cs(0)
235 | self.spi.read(1, token)
236 | self.spi.write(b"\xff")
237 | # wait for write to finish
238 | while self.spi.read(1, 0xFF)[0] == 0x00:
239 | pass
240 |
241 | self.cs(1)
242 | self.spi.write(b"\xff")
243 |
244 | def readblocks(self, block_num, buf):
245 | # workaround for shared bus, required for (at least) some Kingston
246 | # devices, ensure MOSI is high before starting transaction
247 | self.spi.write(b"\xff")
248 |
249 | nblocks = len(buf) // 512
250 | assert nblocks and not len(buf) % 512, "Buffer length is invalid"
251 | if nblocks == 1:
252 | # CMD17: set read address for single block
253 | if self.cmd(17, block_num * self.cdv, 0, release=False) != 0:
254 | # release the card
255 | self.cs(1)
256 | raise OSError(5) # EIO
257 | # receive the data and release card
258 | self.readinto(buf)
259 | else:
260 | # CMD18: set read address for multiple blocks
261 | if self.cmd(18, block_num * self.cdv, 0, release=False) != 0:
262 | # release the card
263 | self.cs(1)
264 | raise OSError(5) # EIO
265 | offset = 0
266 | mv = memoryview(buf)
267 | while nblocks:
268 | # receive the data and release card
269 | self.readinto(mv[offset : offset + 512])
270 | offset += 512
271 | nblocks -= 1
272 | if self.cmd(12, 0, 0xFF, skip1=True):
273 | raise OSError(5) # EIO
274 |
275 | def writeblocks(self, block_num, buf):
276 | # workaround for shared bus, required for (at least) some Kingston
277 | # devices, ensure MOSI is high before starting transaction
278 | self.spi.write(b"\xff")
279 |
280 | nblocks, err = divmod(len(buf), 512)
281 | assert nblocks and not err, "Buffer length is invalid"
282 | if nblocks == 1:
283 | # CMD24: set write address for single block
284 | if self.cmd(24, block_num * self.cdv, 0) != 0:
285 | raise OSError(5) # EIO
286 |
287 | # send the data
288 | self.write(_TOKEN_DATA, buf)
289 | else:
290 | # CMD25: set write address for first block
291 | if self.cmd(25, block_num * self.cdv, 0) != 0:
292 | raise OSError(5) # EIO
293 | # send the data
294 | offset = 0
295 | mv = memoryview(buf)
296 | while nblocks:
297 | self.write(_TOKEN_CMD25, mv[offset : offset + 512])
298 | offset += 512
299 | nblocks -= 1
300 | self.write_token(_TOKEN_STOP_TRAN)
301 |
302 | def ioctl(self, op, arg):
303 | if op == 4: # get number of blocks
304 | return self.sectors
305 | if op == 5: # get block size in bytes
306 | return 512
307 |
--------------------------------------------------------------------------------
/pico_files/modules/picocalc.py:
--------------------------------------------------------------------------------
1 | import framebuf
2 | import picocalcdisplay
3 | from micropython import const
4 | import machine
5 | from machine import Pin, I2C, PWM, SPI
6 | from collections import deque
7 | import time
8 | import sdcard
9 | import uos
10 | import array
11 | from colorer import Fore, Back, Style, print, autoreset
12 | sd = None
13 | keyboard, display = None, None
14 | terminal = None
15 | edit = None
16 | usb_debug = None
17 |
18 | _REG_VER = const(0x01) # fw version
19 | _REG_CFG = const(0x02) # config
20 | _REG_INT = const(0x03) # interrupt status
21 | _REG_KEY = const(0x04) # key status
22 | _REG_BKL = const(0x05) # backlight
23 | _REG_DEB = const(0x06) # debounce cfg
24 | _REG_FRQ = const(0x07) # poll freq cfg
25 | _REG_RST = const(0x08) # reset
26 | _REG_FIF = const(0x09) # fifo
27 | _REG_BK2 = const(0x0A) # backlight 2
28 | _REG_BAT = const(0x0B) # battery
29 | _REG_DIR = const(0x0C) # gpio direction
30 | _REG_PUE = const(0x0D) # gpio input pull enable
31 | _REG_PUD = const(0x0E) # gpio input pull direction
32 | _REG_GIO = const(0x0F) # gpio value
33 | _REG_GIC = const(0x10) # gpio interrupt config
34 | _REG_GIN = const(0x11) # gpio interrupt status
35 | _KEY_COUNT_MASK = const(0x1F)
36 | _WRITE_MASK = const(1 << 7)
37 | _StateIdle = const(0)
38 | _StatePress = const(1)
39 | _StateLongPress = const(2)
40 | _StateRelease = const(3)
41 |
42 | '''
43 | import uctypes
44 | from uctypes import struct, OBJ, NATIVE_UINTPTR, UINT16, UINT8, LITTLE_ENDIAN
45 | from uctypes import addressof
46 |
47 | W2, H2 = 320, 320
48 | buf2 = bytearray(W2 * H2/2)
49 |
50 | # typedef struct _mp_obj_framebuf_t {
51 | # mp_obj_base_t base; // offset 0, 4 bytes
52 | # mp_obj_t buf_obj; // offset 4, 4 bytes
53 | # void *buf; // offset 8, 4 bytes
54 | # uint16_t width; // offset 12, 2 bytes
55 | # uint16_t height; // offset 14, 2 bytes
56 | # uint16_t stride; // offset 16, 2 bytes
57 | # uint8_t format; // offset 18, 1 byte
58 | # } mp_obj_framebuf_t;
59 | layout = {
60 | 'buf_obj': (OBJ, 4),
61 | 'buf_ptr': (NATIVE_UINTPTR, 8),
62 | 'width': (UINT16 | LITTLE_ENDIAN, 12),
63 | 'height': (UINT16 | LITTLE_ENDIAN, 14),
64 | 'stride': (UINT16 | LITTLE_ENDIAN, 16),
65 | 'format': (UINT8, 18),
66 | }
67 |
68 |
69 | fb_s = struct(addressof(display), layout)
70 | fb_s.buf_obj = buf2
71 | fb_s.buf_ptr = addressof(buf2)
72 |
73 | #fb_s.width = W2
74 | #fb_s.height = H2
75 | #fb_s.stride = W2
76 |
77 | #fb_s.format = framebuf.GS8
78 |
79 |
80 |
81 | '''
82 | class PicoDisplay(framebuf.FrameBuffer):
83 | def __init__(self, width, height,color_type = framebuf.GS4_HMSB):
84 | self.width = width
85 | self.height = height
86 | if color_type == framebuf.GS4_HMSB:
87 | buffer = bytearray(self.width * self.height//2) # 4bpp mono
88 | elif color_type == framebuf.RGB565:
89 | buffer = bytearray(self.width * self.height*2)
90 | elif color_type == framebuf.GS8:
91 | buffer = bytearray(self.width * self.height)
92 | elif color_type == framebuf.GS2_HMSB:
93 | buffer = bytearray(self.width * self.height//4)
94 | elif color_type == framebuf.MONO_HMSB:
95 | buffer = bytearray(self.width * self.height//8)
96 |
97 |
98 | super().__init__(buffer, self.width, self.height, color_type)
99 | picocalcdisplay.init(buffer,color_type,True)
100 |
101 | def restLUT(self):
102 | picocalcdisplay.resetLUT(0)
103 |
104 | def switchPredefinedLUT(self, name='vt100'):
105 | if name == 'vt100':
106 | picocalcdisplay.resetLUT(0)
107 |
108 | elif name == 'pico8':
109 | picocalcdisplay.resetLUT(1)
110 | else:
111 | raise ValueError("Unknown LUT name. Use 'vt100' or 'pico8'.")
112 |
113 | def getLUT(self):
114 | return picocalcdisplay.getLUTview().cast("H")
115 |
116 | def setLUT(self,lut):
117 | if not (isinstance(lut, array.array)):
118 | raise TypeError("LUT must be an array of type 'H' (unsigned short)")
119 | picocalcdisplay.setLUT(lut)
120 |
121 | def stopRefresh(self):
122 | picocalcdisplay.stopAutoUpdate()
123 |
124 | def recoverRefresh(self):
125 | picocalcdisplay.startAutoUpdate()
126 |
127 | def text(self,c, x0, y0, color):
128 | picocalcdisplay.drawTxt6x8(c,x0,y0,color)
129 |
130 | def show(self,core=1):
131 | picocalcdisplay.update(core)
132 |
133 | def isScreenUpdateDone(self):
134 | return picocalcdisplay.isScreenUpdateDone()
135 |
136 | class PicoKeyboard:
137 | def __init__(self,sclPin=7,sdaPin=6,address=0x1f):
138 | self.hardwarekeyBuf = deque((),30)
139 | self.i2c = I2C(1,scl=Pin(sclPin),sda=Pin(sdaPin),freq=10000)
140 | #self.i2c.scan()
141 | self.ignor = True
142 | self.address = address
143 | self.temp=bytearray(2)
144 | self.reset()
145 | self.isShift = False
146 | self.isCtrl = False
147 | self.isAlt = False
148 |
149 | def ignor_mod(self):
150 | self.ignor = True
151 |
152 | def write_cmd(self,cmd):
153 | self.i2c.writeto(self.address,bytearray([cmd]))
154 |
155 | def read_reg16(self,reg):
156 | self.temp[0]=reg
157 | self.i2c.writeto(self.address,self.temp[0:1])
158 | self.i2c.readfrom_into(self.address,self.temp)
159 | return self.temp
160 |
161 | def read_reg8(self,reg):
162 | self.i2c.writeto(self.address, bytes(reg))
163 | #self.temp[0]=reg
164 | #self.i2c.writeto(self.address,self.temp[0:1])
165 | return self.i2c.readfrom(self.address, 1)[0]
166 | #self.i2c.readfrom_into(self.address,memoryview(self.temp)[0:1])
167 | #return self.temp
168 |
169 | def write_reg(self,reg,value):
170 | self.temp[0]=reg| _WRITE_MASK
171 | self.temp[1]=value
172 | self.i2c.writeto(self.address,self.temp)
173 |
174 | def enable_report_mods(self):
175 | currentCFG = self.read_reg8(_REG_CFG)
176 | self.temp[0]=currentCFG | (0x01<<6)
177 | self.write_reg(_REG_CFG,self.temp[0:1])
178 |
179 | def disable_report_mods(self):
180 | currentCFG = self.read_reg8(_REG_CFG)
181 | self.temp[0]=currentCFG & (~(0x01<<6))
182 | self.write_reg(_REG_CFG,self.temp[0:1])
183 |
184 | def enable_use_mods(self):
185 | currentCFG = self.read_reg8(_REG_CFG)
186 | self.temp[0]=currentCFG | (0x01<<7)
187 | self.write_reg(_REG_CFG,self.temp[0:1])
188 |
189 | def disable_use_mods(self):
190 | currentCFG = self.read_reg8(_REG_CFG)
191 | self.temp[0]=currentCFG & (~(0x01<<7))
192 | self.write_reg(_REG_CFG,self.temp[0:1])
193 |
194 | def reset(self):
195 | self.write_cmd(_REG_RST)
196 | time.sleep_ms(100)
197 |
198 | def keyCount(self):
199 | buf = self.read_reg16(_REG_KEY)
200 | return (buf[0] & _KEY_COUNT_MASK)
201 |
202 | def keyEvent(self):
203 | if (self.keyCount() == 0):
204 | return None
205 | else:
206 | buf = self.read_reg16(_REG_FIF)
207 | return buf
208 |
209 | def backlight(self):
210 | return self.read_reg8(_REG_BKL)
211 |
212 | def setBacklight(self,value):
213 | self.write_reg(_REG_BKL,value)
214 |
215 | def backlight_keyboard(self):
216 | return self.read_reg8(_REG_BK2)
217 |
218 | def setBacklight_keyboard(self,value):
219 | self.write_reg(_REG_BK2,value)
220 |
221 | def battery(self):
222 | return self.read_reg16(_REG_BAT)
223 |
224 | def readinto(self, buf):
225 |
226 | numkeysInhardware = self.keyCount()#how many keys in hardware
227 | if numkeysInhardware != 0:
228 | for i in range(numkeysInhardware):
229 | keyGot=self.keyEvent()
230 | state = keyGot[0]
231 | key = keyGot[1]
232 | if state == _StatePress or state == _StateLongPress:
233 |
234 | if key == 0xa2 or key == 0xa3:
235 | self.isShift = True
236 | elif key == 0xa5:
237 | self.isCtrl = True
238 | elif key == 0xa1:
239 | self.isAlt = True
240 | else:
241 | #check current shift/ctrl/alt state
242 | modifier=b''
243 | if self.isShift and self.isAlt and (not self.isCtrl):
244 | modifier=b';4'
245 | elif self.isShift and self.isCtrl and (not self.isAlt):
246 | modifier=b';6'
247 | elif self.isAlt and self.isCtrl and (not self.isShift):
248 | modifier=b';7'
249 | elif self.isShift and self.isCtrl and self.isAlt:
250 | modifier=b';8'
251 | elif self.isAlt and (not self.isCtrl) and (not self.isShift):
252 | modifier=b';3'
253 | elif (not self.isAlt) and self.isCtrl and (not self.isShift):
254 | modifier=b';5'
255 | elif (not self.isAlt) and (not self.isCtrl) and self.isShift:
256 | modifier=b';2'
257 |
258 | if key >=0xB4 and key <= 0xB7:
259 | #direction keys
260 | #self.hardwarekeyBuf.append(0x1b)
261 | #self.hardwarekeyBuf.append(ord('['))
262 | if modifier != b'':
263 | parameters = b'1'
264 | else:
265 | parameters = b''
266 | if key == 0xB4:
267 | self.hardwarekeyBuf.extend(b'\x1b['+parameters+modifier+b'D')
268 | elif key == 0xB5:
269 | self.hardwarekeyBuf.extend(b'\x1b['+parameters+modifier+b'A')
270 | elif key == 0xB6:
271 | self.hardwarekeyBuf.extend(b'\x1b['+parameters+modifier+b'B')
272 | elif key == 0xB7:
273 | self.hardwarekeyBuf.extend(b'\x1b['+parameters+modifier+b'C')
274 | elif key == 0x0A:
275 | self.hardwarekeyBuf.append(ord('\r'))
276 | #self.hardwarekeyBuf.append(ord('\n')) #return key
277 | elif key == 0xB1: # KEY_ESC
278 | self.hardwarekeyBuf.extend(b'\x1b\x1b')
279 | elif key == 0xD2: #KEY_HOME
280 | self.hardwarekeyBuf.extend(b'\x1b[H')
281 | elif key == 0xD5: #end
282 | self.hardwarekeyBuf.extend(b'\x1b[F')
283 | elif key == 0x08: #backspace
284 | self.hardwarekeyBuf.append(0x7F)
285 | elif key == 0xD4: #delete
286 | self.hardwarekeyBuf.extend(b'\x1b[3'+modifier+b'~')
287 | else:
288 | if self.isAlt == True:
289 | if key !=ord(' ') and key!=ord(',') and key!=ord('.'):
290 | self.hardwarekeyBuf.extend(b'\x1b')#to match the vt100 terminal style
291 | self.hardwarekeyBuf.append(key)
292 | elif self.isCtrl == True:
293 | self.hardwarekeyBuf.append(key&0x1F)
294 | else:
295 | self.hardwarekeyBuf.append(key)
296 | else:
297 | if key == 0xa2 or key == 0xa3:
298 | self.isShift = False
299 | elif key == 0xa5:
300 | self.isCtrl = False
301 | elif key == 0xa1:
302 | self.isAlt = False
303 | #self.hardwarekeyBuf.append(key[:])
304 | #now deside how many keys to send to buf
305 | requestedkeys = len(buf)
306 | keysLeft = requestedkeys
307 | if len(self.hardwarekeyBuf)==0: #after read in the key, still no key in buffer
308 | return None
309 | #print("init buf")
310 | #print(buf)
311 | #print("hardware key buf size")
312 | #print(len(self.hardwarekeyBuf))
313 | while keysLeft > 0:
314 |
315 | #fill all keys until key list is empty
316 | if len(self.hardwarekeyBuf) == 0:
317 | break #all keys has been read and process
318 |
319 | key = self.hardwarekeyBuf.popleft()#remove the processed key from key list
320 | buf[-keysLeft]=key
321 | keysLeft -=1
322 |
323 | #print("read buff")
324 | #print(buf)
325 | #print(requestedkeys-keysLeft)
326 | if requestedkeys-keysLeft == 0:
327 | return None
328 | else:
329 | return (requestedkeys-keysLeft)
330 |
331 | class PicoSD:
332 | """
333 | Example class for SD card configuration and management by LaikaSpaceDawg.
334 | This class handles the mounting and unmounting of the SD card, as well as checking its status.
335 | Also demonstrates basic uColorama usage for colored output.
336 | """
337 | def __init__(self, mount_point="/sd", sck_pin=18, mosi_pin=19, miso_pin=16, cs_pin=17, spi_bus=0, baudrate=1000000):
338 | """
339 | Initialize SD card configuration.
340 |
341 | :param mount_point: Directory to mount the SD card to.
342 | :param sck_pin: GPIO pin connected to SCK.
343 | :param mosi_pin: GPIO pin connected to MOSI.
344 | :param miso_pin: GPIO pin connected to MISO.
345 | :param cs_pin: GPIO pin connected to CS.
346 | :param spi_bus: SPI bus to be used.
347 | :param baudrate: SPI communication speed.
348 | """
349 | self.mount_point = mount_point
350 | self.sck_pin = sck_pin
351 | self.mosi_pin = mosi_pin
352 | self.miso_pin = miso_pin
353 | self.cs_pin = cs_pin
354 | self.spi_bus = spi_bus
355 | self.baudrate = baudrate
356 | self.sd = None
357 |
358 | # Attempt to mount the SD card on initialization
359 | self.mount()
360 |
361 | def __call__(self):
362 | """Allow the SDManager object to be called like a function to get the SDCard object."""
363 | if self.sd:
364 | return self.sd
365 |
366 | def mount(self):
367 | """
368 | Mount the SD card.
369 | """
370 | if self.sd is None:
371 | try:
372 | self.sd = sdcard.SDCard(
373 | machine.SPI(self.spi_bus, baudrate=self.baudrate, polarity=0, phase=0,
374 | sck=machine.Pin(self.sck_pin),
375 | mosi=machine.Pin(self.mosi_pin),
376 | miso=machine.Pin(self.miso_pin)),
377 | machine.Pin(self.cs_pin)
378 | )
379 | uos.mount(self.sd, self.mount_point)
380 | print(f"{Fore.GREEN}SD card mounted successfully at", self.mount_point)
381 | except Exception as e:
382 | print(f"{Fore.RED}Failed to mount SD card: {e}")
383 | self.sd = None
384 | else:
385 | print(f"{Fore.YELLOW}SD card is already mounted.")
386 |
387 | def unmount(self):
388 | """
389 | Unmount the SD card.
390 | """
391 | if self.sd is not None:
392 | try:
393 | uos.umount(self.mount_point)
394 | self.sd = None
395 | print(f"SD card unmounted from {self.mount_point}.")
396 | except Exception as e:
397 | print(f"{Fore.RED}Failed to unmount SD card: {e}")
398 | else:
399 | print("No SD card is mounted to unmount.")
400 |
401 | def check_mount(self):
402 | """
403 | Check if the SD card is mounted.
404 | """
405 | try:
406 | if uos.stat(self.mount_point):
407 | print(f"{Fore.GREEN}SD card is mounted at {self.mount_point}.")
408 | except OSError:
409 | print(f"{Fore.RED}No SD card is mounted at {self.mount_point}.")
410 |
411 | # Frequency definitions for musical notes
412 | NOTE_FREQUENCIES = {
413 | 'B1': 31, 'C2': 33, 'CS2': 35, 'D2': 37, 'DS2': 39, 'E2': 41, 'F2': 44, 'FS2': 46,
414 | 'G2': 49, 'GS2': 52, 'A2': 55, 'AS2': 58, 'B2': 62, 'C3': 65, 'CS3': 69, 'D3': 73,
415 | 'DS3': 78, 'E3': 82, 'F3': 87, 'FS3': 93, 'G3': 98, 'GS3': 104, 'A3': 110, 'AS3': 117,
416 | 'B3': 123, 'C4': 131, 'CS4': 139, 'D4': 147, 'DS4': 156, 'E4': 165, 'F4': 175,
417 | 'FS4': 185, 'G4': 196, 'GS4': 208, 'A4': 220, 'AS4': 233, 'B4': 247, 'C5': 262,
418 | 'CS5': 277, 'D5': 294, 'DS5': 311, 'E5': 330, 'F5': 349, 'FS5': 370, 'G5': 392,
419 | 'GS5': 415, 'A5': 440, 'AS5': 466, 'B5': 494, 'C6': 523, 'CS6': 554, 'D6': 587,
420 | 'DS6': 622, 'E6': 659, 'F6': 698, 'FS6': 740, 'G6': 784, 'GS6': 831, 'A6': 880,
421 | 'AS6': 932, 'B6': 988, 'C7': 1047, 'CS7': 1109, 'D7': 1175, 'DS7': 1245, 'E7': 1319,
422 | 'F7': 1397, 'FS7': 1480, 'G7': 1568, 'GS7': 1661, 'A7': 1760, 'AS7': 1865, 'B7': 1976,
423 | 'C8': 2093, 'CS8': 2217, 'D8': 2349, 'DS8': 2489, 'E8': 2637, 'F8': 2794, 'FS8': 2960,
424 | 'G8': 3136, 'GS8': 3322, 'A8': 3520, 'AS8': 3729, 'B8': 3951, 'C9': 4186, 'CS9': 4435,
425 | 'D9': 4699, 'DS9': 4978, 'P': 0 # 'P' is for pause
426 | }
427 |
428 | class PicoSpeaker:
429 | def __init__(self, pin_number):
430 | self.buzzer_pin = Pin(pin_number)
431 | self.pwm = None
432 |
433 | def tone(self, tone, duration):
434 | """
435 | Play a tone given by a note string from NOTE_FREQUENCIES or directly as a frequency number.
436 |
437 | :param tone: Either a note string ("A4", "C5", etc.) or a frequency in Hz.
438 | :param duration: Duration in seconds for which to play the tone.
439 | Written by @LaikaSpaceDawg (https://github.com/LaikaSpaceDawg/PicoCalc-micropython)
440 | """
441 | frequency = 0
442 |
443 | if isinstance(tone, str) and tone.upper() in NOTE_FREQUENCIES:
444 | frequency = NOTE_FREQUENCIES[tone.upper()]
445 | elif isinstance(tone, (int, float)):
446 | frequency = tone
447 |
448 | if frequency > 0:
449 | self.pwm = PWM(self.buzzer_pin)
450 | self.pwm.freq(frequency)
451 | self.pwm.duty_u16(32768)
452 | time.sleep(duration * 0.9)
453 | if self.pwm:
454 | self.pwm.deinit()
455 | time.sleep(duration * 0.1)
456 |
457 | def tones(self, notes_durations):
458 | """
459 | Play a sequence of notes with their respective durations.
460 |
461 | :param notes_durations: List of tuples where each tuple contains a note and its duration.
462 | e.g., [("A4", 0.5), ("C5", 0.5)]
463 | """
464 | for tone, duration in notes_durations:
465 | self.tone(tone, duration)
466 |
467 | def rtttl(self, text):
468 | """
469 | Convert RTTTL formatted string into frequency-duration pairs.
470 | Provided by: @GraphicHealer (https://github.com/GraphicHealer/MicroPython-RTTTL)
471 | """
472 | try:
473 | title, defaults, song = text.split(':')
474 | d, o, b = defaults.split(',')
475 | d = int(d.split('=')[1])
476 | o = int(o.split('=')[1])
477 | b = int(b.split('=')[1])
478 | whole = (60000 / b) * 4
479 | noteList = song.split(',')
480 | except:
481 | return 'Please enter a valid RTTTL string.'
482 |
483 | notes = 'abcdefgp'
484 | outList = []
485 |
486 | for note in noteList:
487 | index = 0
488 | for i in note:
489 | if i in notes:
490 | index = note.find(i)
491 | break
492 |
493 | length = note[0:index]
494 | value = note[index:].replace('#', 's').replace('.', '')
495 |
496 | if not any(char.isdigit() for char in value):
497 | value += str(o)
498 | if 'p' in value:
499 | value = 'p'
500 |
501 | if length == '':
502 | length = d
503 | else:
504 | length = int(length)
505 |
506 | length = whole / length
507 |
508 | if '.' in note:
509 | length += length / 2
510 |
511 | outList.append((NOTE_FREQUENCIES[value.upper()], length))
512 |
513 | return outList
514 |
515 | def play_rtttl(self, rtttl_string):
516 | """
517 | Play RTTTL formatted song.
518 | Provided by: @GraphicHealer (https://github.com/GraphicHealer/MicroPython-RTTTL)
519 | """
520 | tune = self.rtttl(rtttl_string)
521 |
522 | if type(tune) is not list:
523 | print(tune)
524 | return
525 |
526 | for freqc, msec in tune:
527 | self._play_frequency(freqc, msec * 0.001)
--------------------------------------------------------------------------------
/picocalcdisplay/picocalcdisplay.c:
--------------------------------------------------------------------------------
1 | #include "picocalcdisplay.h"
2 | // Include MicroPython API.
3 | #include "py/runtime.h"
4 |
5 | // Used to get the time in the Timer class example.
6 | #include "py/mphal.h"
7 | #include "py/gc.h"
8 | #include "py/misc.h"
9 | #include
10 | #include
11 | #include
12 | #include "hardware/spi.h"
13 | #include "hardware/dma.h"
14 | #include "hardware/gpio.h"
15 | #include "pico/stdlib.h"
16 | #include "pico/multicore.h"
17 | #include "hardware/sync.h"
18 | #include "font6x8e500.h"
19 |
20 |
21 | #define SWRESET 0x01
22 | #define SLPOUT 0x11
23 | #define INVON 0x21
24 | #define DISPON 0x29
25 | #define CASET 0x2A
26 | #define RASET 0x2B
27 | #define RAMWR 0x2C
28 | #define TEON 0x35
29 | #define MADCTL 0x36 // Memory Data Access Control
30 | #define COLMOD 0x3A//
31 | #define FRMCTR1 0xB1
32 | #define INVCTR 0xB4
33 | #define ETMOD 0xB7
34 | #define CECTRL1 0xB9
35 | #define PWCTR1 0xC0
36 | #define PWCTR2 0xC1
37 | #define PWCTR3 0xC2
38 | #define VMCTR1 0xC5
39 | #define PGAMCTRL 0xE0
40 | #define NGAMCTRL 0xE1
41 | #define CORE1_STACK_SIZE 1024
42 | uint32_t core1_stack[CORE1_STACK_SIZE];
43 |
44 | static uint st_dma;
45 | static uint8_t *frameBuff;
46 | static volatile bool oneShotisDone=true;
47 | static volatile bool autoUpdate;
48 | static uint16_t lineBuffA[64];
49 | static uint16_t lineBuffB[64];
50 | void (*pColorUpdate)(uint8_t *, uint32_t, const uint16_t *);
51 | void (*pSetPixel)(int32_t,int32_t,uint16_t);
52 | static uint8_t currentTextY;
53 | static uint8_t currentTextX;
54 | static const uint8_t *currentTextTable;
55 | static uint16_t LUT[256] = {0}; // Look-Up Table for 4bpp to RGB565 conversion
56 |
57 | static const uint16_t pico8LUT[16]={
58 | 0x0000, 0x4A19, 0x2A79, 0x2A04, 0x86AA, 0xA95A, 0x18C6, 0x9DFF,
59 | 0x09F8, 0x00FD, 0x64FF, 0x2607, 0x7F2D, 0xB383, 0xB5FB, 0x75FE
60 | };
61 | static const uint16_t defaultLUT[256] = {
62 | //0x0000, 0x4A19, 0x2A79, 0x2A04, 0x86AA, 0xA95A, 0x18C6, 0x9DFF,
63 | //0x09F8, 0x00FD, 0x64FF, 0x2607, 0x7F2D, 0xB383, 0xB5FB, 0x75FE
64 | 0x0000, 0x0080, 0x0004, 0x0084, 0x1000, 0x1080, 0x1004, 0x18C6,
65 | 0x1084, 0x00F8, 0xE007, 0xE0FF, 0x1F00, 0x1FF8, 0xFF07, 0xFFFF,
66 | 0x0000, 0x0B00, 0x1000, 0x1500, 0x1A00, 0x1F00, 0xE002, 0xEB02,
67 | 0xF002, 0xF502, 0xFA02, 0xFF02, 0x2004, 0x2B04, 0x3004, 0x3504,
68 | 0x3A04, 0x3F04, 0x6005, 0x6B05, 0x7005, 0x7505, 0x7A05, 0x7F05,
69 | 0xA006, 0xAB06, 0xB006, 0xB506, 0xBA06, 0xBF06, 0xE007, 0xEB07,
70 | 0xF007, 0xF507, 0xFA07, 0xFF07, 0x0058, 0x0B58, 0x1058, 0x1558,
71 | 0x1A58, 0x1F58, 0xE05A, 0xEB5A, 0xF05A, 0xF55A, 0xFA5A, 0xFF5A,
72 | 0x205C, 0x2B5C, 0x305C, 0x355C, 0x3A5C, 0x3F5C, 0x605D, 0x6B5D,
73 | 0x705D, 0x755D, 0x7A5D, 0x7F5D, 0xA05E, 0xAB5E, 0xB05E, 0xB55E,
74 | 0xBA5E, 0xBF5E, 0xE05F, 0xEB5F, 0xF05F, 0xF55F, 0xFA5F, 0xFF5F,
75 | 0x0080, 0x0B80, 0x1080, 0x1580, 0x1A80, 0x1F80, 0xE082, 0xEB82,
76 | 0xF082, 0xF582, 0xFA82, 0xFF82, 0x2084, 0x2B84, 0x3084, 0x3584,
77 | 0x3A84, 0x3F84, 0x6085, 0x6B85, 0x7085, 0x7585, 0x7A85, 0x7F85,
78 | 0xA086, 0xAB86, 0xB086, 0xB586, 0xBA86, 0xBF86, 0xE087, 0xEB87,
79 | 0xF087, 0xF587, 0xFA87, 0xFF87, 0x00A8, 0x0BA8, 0x10A8, 0x15A8,
80 | 0x1AA8, 0x1FA8, 0xE0AA, 0xEBAA, 0xF0AA, 0xF5AA, 0xFAAA, 0xFFAA,
81 | 0x20AC, 0x2BAC, 0x30AC, 0x35AC, 0x3AAC, 0x3FAC, 0x60AD, 0x6BAD,
82 | 0x70AD, 0x75AD, 0x7AAD, 0x7FAD, 0xA0AE, 0xABAE, 0xB0AE, 0xB5AE,
83 | 0xBAAE, 0xBFAE, 0xE0AF, 0xEBAF, 0xF0AF, 0xF5AF, 0xFAAF, 0xFFAF,
84 | 0x00D0, 0x0BD0, 0x10D0, 0x15D0, 0x1AD0, 0x1FD0, 0xE0D2, 0xEBD2,
85 | 0xF0D2, 0xF5D2, 0xFAD2, 0xFFD2, 0x20D4, 0x2BD4, 0x30D4, 0x35D4,
86 | 0x3AD4, 0x3FD4, 0x60D5, 0x6BD5, 0x70D5, 0x75D5, 0x7AD5, 0x7FD5,
87 | 0xA0D6, 0xABD6, 0xB0D6, 0xB5D6, 0xBAD6, 0xBFD6, 0xE0D7, 0xEBD7,
88 | 0xF0D7, 0xF5D7, 0xFAD7, 0xFFD7, 0x00F8, 0x0BF8, 0x10F8, 0x15F8,
89 | 0x1AF8, 0x1FF8, 0xE0FA, 0xEBFA, 0xF0FA, 0xF5FA, 0xFAFA, 0xFFFA,
90 | 0x20FC, 0x2BFC, 0x30FC, 0x35FC, 0x3AFC, 0x3FFC, 0x60FD, 0x6BFD,
91 | 0x70FD, 0x75FD, 0x7AFD, 0x7FFD, 0xA0FE, 0xABFE, 0xB0FE, 0xB5FE,
92 | 0xBAFE, 0xBFFE, 0xE0FF, 0xEBFF, 0xF0FF, 0xF5FF, 0xFAFF, 0xFFFF,
93 | 0x4108, 0x8210, 0xE318, 0x2421, 0x8631, 0xC739, 0x2842, 0x694A,
94 | 0xCB5A, 0x0C63, 0x6D6B, 0xAE73, 0x1084, 0x518C, 0xB294, 0xF39C,
95 | 0x55AD, 0x96B5, 0xF7BD, 0x38C6, 0x9AD6, 0xDBDE, 0x3CE7, 0x7DEF,
96 | };//standar vt100 color table with byte sweep
97 |
98 |
99 | static void Write_dma(const uint8_t *src, size_t len);
100 | static void command(uint8_t com, size_t len, const char *data) ;
101 | void RGB565Update(uint8_t *frameBuff,uint32_t length, const uint16_t *LUT);
102 | void LUT8Update(uint8_t *frameBuff, uint32_t length, const uint16_t *LUT);
103 | void LUT4Update(uint8_t *frameBuff, uint32_t length, const uint16_t *LUT);
104 | void LUT2Update(uint8_t *frameBuff, uint32_t length, const uint16_t *LUT);
105 | void LUT1Update(uint8_t *frameBuff, uint32_t length, const uint16_t *LUT);
106 | //void core1_main(void);
107 | void setpixelRGB565(int32_t x, int32_t y,uint16_t color);
108 | void setpixelLUT8(int32_t x, int32_t y,uint16_t color);
109 | void setpixelLUT4(int32_t x, int32_t y,uint16_t color);
110 | void setpixelLUT2(int32_t x, int32_t y,uint16_t color);
111 | void setpixelLUT1(int32_t x, int32_t y,uint16_t color);
112 |
113 | /*
114 | #define FRAMEBUF_MVLSB (0)
115 | #define FRAMEBUF_RGB565 (1)
116 | #define FRAMEBUF_GS2_HMSB (5)
117 | #define FRAMEBUF_GS4_HMSB (2)
118 | #define FRAMEBUF_GS8 (6)
119 | #define FRAMEBUF_MHLSB (3)
120 | #define FRAMEBUF_MHMSB (4)
121 | */
122 | static void core1_main(void);
123 | static void core1_singleShot(void);
124 |
125 | static void core1_main(void) {
126 | //multicore_lockout_victim_init();
127 | //static int frame = 0;
128 | while (1) {
129 | //if (++frame % 100 == 0) {
130 | // printf("Core1 alive: %d\n", frame);
131 | //}
132 | if (autoUpdate){
133 | pColorUpdate(frameBuff,DISPLAY_HEIGHT*DISPLAY_WIDTH, LUT);
134 | }
135 | sleep_ms(5);
136 |
137 | }
138 | }
139 |
140 | static void core1_singleShot(void){
141 | pColorUpdate(frameBuff,DISPLAY_HEIGHT*DISPLAY_WIDTH, LUT);
142 | oneShotisDone=true;
143 | }
144 |
145 | void setpixelRGB565(int32_t x, int32_t y,uint16_t color){
146 | ((uint16_t *)frameBuff)[x + DISPLAY_WIDTH*y]= color;
147 | }
148 |
149 | void setpixelLUT8(int32_t x, int32_t y,uint16_t color){
150 | ((uint8_t *)frameBuff)[x + DISPLAY_WIDTH*y]= (uint8_t)color;
151 | }
152 |
153 | void setpixelLUT4(int32_t x, int32_t y,uint16_t color){
154 | uint8_t *pixel = &((uint8_t *)frameBuff)[(x + (DISPLAY_WIDTH*y))>>1];
155 |
156 | if (x&0x01) {
157 | *pixel = ((uint8_t)color & 0x0f) | (*pixel & 0xf0);
158 | } else {
159 | *pixel = ((uint8_t)color << 4) | (*pixel & 0x0f);
160 | }
161 | }
162 |
163 | void setpixelLUT2(int32_t x, int32_t y,uint16_t color){
164 | uint8_t *pixel = &((uint8_t *)frameBuff)[(x + (DISPLAY_WIDTH*y))>>2];
165 | uint8_t shift = (x & 0x3) << 1;
166 | uint8_t mask = 0x3 << shift;
167 | color = ((uint8_t)color & 0x3) << shift;
168 | *pixel = color | (*pixel & (~mask));
169 | }
170 |
171 | void setpixelLUT1(int32_t x, int32_t y,uint16_t color){
172 | size_t index = (x + y * DISPLAY_WIDTH) >> 3;
173 | unsigned int offset = x & 0x07;
174 | ((uint8_t *)frameBuff)[index] = (((uint8_t *)frameBuff)[index] & ~(0x01 << offset)) | ((color != 0) << offset);
175 | }
176 |
177 | static mp_obj_t pd_resetLUT(mp_obj_t index){
178 | uint32_t lutIdx = mp_obj_get_int(index);
179 | switch(lutIdx){
180 | case 0: // Default LUT
181 | memcpy(LUT, (uint16_t *)defaultLUT, 256 * sizeof(uint16_t));
182 | break;
183 | case 1: // Pico-8 LUT
184 | memcpy(LUT, (uint16_t *)pico8LUT, 16 * sizeof(uint16_t));
185 | break;
186 |
187 | }
188 | return mp_const_none;
189 | }
190 | static MP_DEFINE_CONST_FUN_OBJ_1(pd_resetLUT_obj, pd_resetLUT);
191 |
192 |
193 |
194 | static mp_obj_t pd_getLUTview(void) {
195 |
196 |
197 |
198 | return mp_obj_new_memoryview('H', 256, (void *)LUT);
199 |
200 | }
201 | static MP_DEFINE_CONST_FUN_OBJ_0(pd_getLUTview_obj, pd_getLUTview);
202 |
203 |
204 | static mp_obj_t pd_init(mp_obj_t fb_obj, mp_obj_t color_type, mp_obj_t autoR){
205 | mp_buffer_info_t buf_info;
206 | mp_get_buffer_raise(fb_obj, &buf_info, MP_BUFFER_READ);
207 | frameBuff=(uint8_t *)buf_info.buf;
208 | autoUpdate = mp_obj_is_true(autoR);
209 |
210 | int32_t colorType = mp_obj_get_int(color_type);
211 | memcpy(LUT, (uint16_t *)defaultLUT, 256 * sizeof(uint16_t));
212 | currentTextY = 8;
213 | currentTextX = 6;
214 | currentTextTable=CP437_display;
215 | switch (colorType){
216 | case 1: //565
217 | pColorUpdate = RGB565Update;
218 | pSetPixel = setpixelRGB565;
219 | break;
220 | case 2: //16 color
221 | pColorUpdate = LUT4Update;
222 | pSetPixel = setpixelLUT4;
223 | break;
224 | case 4: //2 color
225 | pColorUpdate = LUT1Update;
226 | pSetPixel = setpixelLUT1;
227 | break;
228 | case 5: //4 color
229 | pColorUpdate = LUT2Update;
230 | pSetPixel = setpixelLUT2;
231 | break;
232 | case 6: //256 color
233 | pColorUpdate = LUT8Update;
234 | pSetPixel = setpixelLUT8;
235 | break;
236 |
237 | }
238 | //spi init
239 | spi_init(SPI_DISP, 40000000);
240 | gpio_set_function(CLK_PIN, GPIO_FUNC_SPI);
241 | gpio_set_function(MOSI_PIN, GPIO_FUNC_SPI);
242 |
243 | gpio_init(CS_PIN);
244 | gpio_put(CS_PIN, 1);
245 | gpio_set_dir(CS_PIN, GPIO_OUT);
246 |
247 | gpio_init(DC_PIN);
248 | gpio_set_dir(DC_PIN, GPIO_OUT);
249 |
250 | gpio_init(RST_PIN);
251 | gpio_put(RST_PIN, 0);
252 | gpio_set_dir(RST_PIN, GPIO_OUT);
253 | //DMA init
254 | st_dma = dma_claim_unused_channel(true);
255 | dma_channel_config config = dma_channel_get_default_config(st_dma);
256 | channel_config_set_transfer_data_size(&config, DMA_SIZE_8);
257 | channel_config_set_bswap(&config, false);
258 | channel_config_set_dreq(&config, spi_get_dreq(SPI_DISP, true));
259 | dma_channel_configure(st_dma, &config, &spi_get_hw(SPI_DISP)->dr, NULL, 0, false);
260 | gpio_put(RST_PIN, 0);
261 | sleep_ms(20);
262 | gpio_put(RST_PIN, 1);
263 | sleep_ms(10);
264 | command(SWRESET,0,NULL);
265 | sleep_ms(10);
266 | command(0xF0,1,"\xC3");
267 | command(0xF0,1,"\x96");
268 | command(MADCTL,1,"\x48");
269 | command(COLMOD,1,"\x55"); //pixel format rgb565
270 | command(FRMCTR1,1,"\xA0");
271 | command(INVCTR,1,"\x00");
272 | command(ETMOD,1,"\xC6");
273 | command(CECTRL1,2,"\x02\xE0");
274 | command(PWCTR1,2,"\x80\x06");
275 | command(PWCTR2,1,"\x15");
276 | command(PWCTR3,1,"\xA7");
277 | command(VMCTR1,1,"\x04");
278 | command(0xE8,8,"\x40\x8A\x00\x00\x29\x19\xAA\x33");
279 | command(PGAMCTRL,14,"\xF0\x06\x0F\x05\x04\x20\x37\x33\x4C\x37\x13\x14\x2B\x31");
280 | command(NGAMCTRL,14,"\xF0\x11\x1B\x11\x0F\x0A\x37\x43\x4C\x37\x13\x13\x2C\x32");
281 |
282 | command(0xF0,1,"\x3C");
283 | command(0xF0,1,"\x69");
284 | command(INVON,0,NULL);
285 | command(CASET,4,"\x00\x00\x01\x3F");
286 | command(RASET,4,"\x00\x00\x01\x3F");
287 | command(SLPOUT,0,NULL);
288 | sleep_ms(120);
289 | pColorUpdate(frameBuff,DISPLAY_HEIGHT*DISPLAY_WIDTH, LUT);
290 | command(DISPON,0,NULL);
291 | sleep_ms(120);
292 | command(RAMWR,0,NULL);
293 |
294 | //sleep_ms(100);
295 | //pColorUpdate(frameBuff,DISPLAY_HEIGHT*DISPLAY_WIDTH, LUT);
296 | //sleep_ms(10);
297 | if (autoUpdate==true){
298 | multicore_reset_core1();
299 | multicore_launch_core1_with_stack(core1_main, core1_stack, CORE1_STACK_SIZE);
300 | }
301 | //multicore_launch_core1_with_stack(core1_main, core1_stack, CORE1_STACK_SIZE);
302 |
303 | return mp_const_true;
304 | }
305 | static MP_DEFINE_CONST_FUN_OBJ_3(pd_init_obj, pd_init);
306 |
307 |
308 |
309 |
310 |
311 |
312 | static mp_obj_t drawTxt6x8(mp_uint_t n_args, const mp_obj_t *args){
313 | // extract arguments
314 |
315 | const char *str = mp_obj_str_get_str(args[0]);
316 | int x0 = mp_obj_get_int(args[1]);
317 | int y0 = mp_obj_get_int(args[2]);
318 | uint16_t color = mp_obj_get_int(args[3]);
319 | int x;
320 | int y;
321 |
322 | // loop over chars
323 | for (; *str; ++str) {
324 | // get char and make sure its in range of font
325 | int chr = *(uint8_t *)str;
326 | if (chr < 16 ) {
327 | chr = 32;
328 | }
329 | // get char data
330 | const uint8_t *chr_data = ¤tTextTable[(chr - 16) * currentTextY];
331 | // loop over char data
332 | y = y0;
333 |
334 | for (; y < y0+currentTextY; y++) {
335 |
336 | if (0 <= y && y < DISPLAY_HEIGHT) {
337 | x = x0;
338 | uint8_t line_data = *chr_data++;
339 | for (;x sizeof(LUT)) {
361 | bufLen = sizeof(LUT);
362 | }
363 | memcpy(LUT,buf_info.buf,bufLen* sizeof(uint16_t));
364 |
365 | return mp_const_true;
366 | }
367 | static MP_DEFINE_CONST_FUN_OBJ_1(setLUT_obj, pd_setLUT);
368 |
369 | static mp_obj_t startAutoUpdate(void){
370 | autoUpdate = true;
371 | multicore_reset_core1();
372 | multicore_launch_core1_with_stack(core1_main, core1_stack, CORE1_STACK_SIZE);
373 | return mp_const_true;
374 | }
375 | static MP_DEFINE_CONST_FUN_OBJ_0(startAutoUpdate_obj, startAutoUpdate);
376 |
377 |
378 | static mp_obj_t stopAutoUpdate(void){
379 | autoUpdate = false;
380 | multicore_reset_core1();
381 | //wait until possible dma is done
382 | while (dma_channel_is_busy(st_dma)){
383 | tight_loop_contents();
384 | }
385 | return mp_const_true;
386 | }
387 | static MP_DEFINE_CONST_FUN_OBJ_0(stopAutoUpdate_obj, stopAutoUpdate);
388 |
389 |
390 | static void Write_dma(const uint8_t *src, size_t len) {
391 | while (dma_channel_is_busy(st_dma));
392 | dma_channel_set_trans_count(st_dma, len, false);
393 | dma_channel_set_read_addr(st_dma, src, true);
394 | }
395 |
396 |
397 | static void command(uint8_t com, size_t len, const char *data) {
398 |
399 | gpio_put(CS_PIN, 0);
400 | gpio_put(DC_PIN, 0); // command mode
401 | spi_write_blocking(SPI_DISP,&com, 1);
402 | if(data) {
403 | gpio_put(DC_PIN, 1); // data mode
404 | spi_write_blocking(SPI_DISP,(const uint8_t*)data, len);
405 | }
406 | gpio_put(CS_PIN, 1);
407 | }
408 |
409 |
410 |
411 |
412 | static mp_obj_t pd_update(mp_obj_t core){
413 | int coreNum = mp_obj_get_int(core);
414 | if (autoUpdate==false){//only work when autoUpdate is false
415 | if (coreNum == 0){
416 | oneShotisDone=false;
417 | pColorUpdate(frameBuff,DISPLAY_HEIGHT*DISPLAY_WIDTH, LUT);
418 | oneShotisDone=true;
419 | }else{
420 | //single shot core 1 update
421 | while(oneShotisDone==false);
422 | oneShotisDone=false;
423 | multicore_reset_core1();
424 | multicore_launch_core1_with_stack(core1_singleShot, core1_stack, CORE1_STACK_SIZE);
425 | }
426 | }
427 | return mp_const_true;
428 | }
429 | static MP_DEFINE_CONST_FUN_OBJ_1(pd_update_obj, pd_update);
430 |
431 | static mp_obj_t pd_isScreenUpdateDone(void){
432 | if (autoUpdate==false){
433 | return mp_obj_new_bool(oneShotisDone);
434 | }else{
435 | return mp_obj_new_bool(true); //always true when autoUpdate is true
436 | }
437 | }
438 | static MP_DEFINE_CONST_FUN_OBJ_0(pd_isScreenUpdateDone_obj, pd_isScreenUpdateDone);
439 |
440 | void RGB565Update(uint8_t *frameBuff,uint32_t length,const uint16_t *LUT) {
441 | //gpio_put(CS_PIN, 1);
442 | //gpio_put(CS_PIN, 0);
443 | while (dma_channel_is_busy(st_dma));
444 | uint8_t cmd = RAMWR;
445 | gpio_put(CS_PIN, 0);
446 | gpio_put(DC_PIN, 0); // command mode
447 |
448 | spi_write_blocking(SPI_DISP,&cmd, 1);
449 |
450 | gpio_put(DC_PIN, 1); // data mode
451 | Write_dma((const uint8_t*)frameBuff, length*2);
452 | while (dma_channel_is_busy(st_dma));
453 | while (spi_get_hw(SPI_DISP)->sr & SPI_SSPSR_BSY_BITS) {
454 | tight_loop_contents();
455 | }
456 | gpio_put(CS_PIN, 1);
457 | }
458 |
459 | void LUT8Update(uint8_t *frameBuff, uint32_t length, const uint16_t *LUT){
460 | while (dma_channel_is_busy(st_dma));
461 | //uint16_t lineBuffA[64];
462 | //uint16_t lineBuffB[64];
463 | uint16_t *currentLineBuff=lineBuffA;
464 | uint16_t *updateLineBuff=lineBuffA;
465 | uint32_t leftPixels = length - (length&0xFFFFFFC0);
466 | uint32_t count = length>>6;
467 | uint8_t currentPixel=0;
468 | uint16_t color;
469 | uint8_t cmd = RAMWR;
470 | gpio_put(CS_PIN, 0);
471 | gpio_put(DC_PIN, 0); // command mode
472 |
473 | spi_write_blocking(SPI_DISP,&cmd, 1);
474 | gpio_put(DC_PIN, 1); // data mode
475 | while(count--){
476 | if (count&0x00000001){
477 | currentLineBuff = lineBuffA;
478 | updateLineBuff = lineBuffA;
479 | }else{
480 | currentLineBuff = lineBuffB;
481 | updateLineBuff = lineBuffB;
482 | }
483 | for (int i=2;i>0;i--){
484 | currentPixel = *frameBuff++;color = LUT[currentPixel];*currentLineBuff++ = color;
485 | currentPixel = *frameBuff++;color = LUT[currentPixel];*currentLineBuff++ = color;
486 | currentPixel = *frameBuff++;color = LUT[currentPixel];*currentLineBuff++ = color;
487 | currentPixel = *frameBuff++;color = LUT[currentPixel];*currentLineBuff++ = color;
488 | currentPixel = *frameBuff++;color = LUT[currentPixel];*currentLineBuff++ = color;
489 | currentPixel = *frameBuff++;color = LUT[currentPixel];*currentLineBuff++ = color;
490 | currentPixel = *frameBuff++;color = LUT[currentPixel];*currentLineBuff++ = color;
491 | currentPixel = *frameBuff++;color = LUT[currentPixel];*currentLineBuff++ = color;
492 | currentPixel = *frameBuff++;color = LUT[currentPixel];*currentLineBuff++ = color;
493 | currentPixel = *frameBuff++;color = LUT[currentPixel];*currentLineBuff++ = color;
494 | currentPixel = *frameBuff++;color = LUT[currentPixel];*currentLineBuff++ = color;
495 | currentPixel = *frameBuff++;color = LUT[currentPixel];*currentLineBuff++ = color;
496 | currentPixel = *frameBuff++;color = LUT[currentPixel];*currentLineBuff++ = color;
497 | currentPixel = *frameBuff++;color = LUT[currentPixel];*currentLineBuff++ = color;
498 | currentPixel = *frameBuff++;color = LUT[currentPixel];*currentLineBuff++ = color;
499 | currentPixel = *frameBuff++;color = LUT[currentPixel];*currentLineBuff++ = color;
500 | currentPixel = *frameBuff++;color = LUT[currentPixel];*currentLineBuff++ = color;
501 | currentPixel = *frameBuff++;color = LUT[currentPixel];*currentLineBuff++ = color;
502 | currentPixel = *frameBuff++;color = LUT[currentPixel];*currentLineBuff++ = color;
503 | currentPixel = *frameBuff++;color = LUT[currentPixel];*currentLineBuff++ = color;
504 | currentPixel = *frameBuff++;color = LUT[currentPixel];*currentLineBuff++ = color;
505 | currentPixel = *frameBuff++;color = LUT[currentPixel];*currentLineBuff++ = color;
506 | currentPixel = *frameBuff++;color = LUT[currentPixel];*currentLineBuff++ = color;
507 | currentPixel = *frameBuff++;color = LUT[currentPixel];*currentLineBuff++ = color;
508 | currentPixel = *frameBuff++;color = LUT[currentPixel];*currentLineBuff++ = color;
509 | currentPixel = *frameBuff++;color = LUT[currentPixel];*currentLineBuff++ = color;
510 | currentPixel = *frameBuff++;color = LUT[currentPixel];*currentLineBuff++ = color;
511 | currentPixel = *frameBuff++;color = LUT[currentPixel];*currentLineBuff++ = color;
512 | currentPixel = *frameBuff++;color = LUT[currentPixel];*currentLineBuff++ = color;
513 | currentPixel = *frameBuff++;color = LUT[currentPixel];*currentLineBuff++ = color;
514 | currentPixel = *frameBuff++;color = LUT[currentPixel];*currentLineBuff++ = color;
515 | currentPixel = *frameBuff++;color = LUT[currentPixel];*currentLineBuff++ = color;
516 | }
517 | while (dma_channel_is_busy(st_dma));
518 | Write_dma((const uint8_t *)updateLineBuff,64*2);
519 | }
520 | if (leftPixels != 0){
521 | if (updateLineBuff == lineBuffB){
522 | currentLineBuff = lineBuffA;
523 | updateLineBuff = lineBuffA;
524 | }else{
525 | currentLineBuff = lineBuffB;
526 | updateLineBuff = lineBuffB;
527 | }
528 | while(leftPixels--){
529 | currentPixel = *frameBuff++;color = LUT[currentPixel];*currentLineBuff++ = color;
530 | }
531 | while (dma_channel_is_busy(st_dma));
532 | Write_dma((const uint8_t *)lineBuffB,leftPixels*2);
533 | }
534 | while (dma_channel_is_busy(st_dma));
535 | while (spi_get_hw(SPI_DISP)->sr & SPI_SSPSR_BSY_BITS) {
536 | tight_loop_contents();
537 | }
538 | gpio_put(CS_PIN, 1);
539 | }
540 |
541 |
542 | void LUT4Update(uint8_t *frameBuff, uint32_t length, const uint16_t *LUT){
543 | while (dma_channel_is_busy(st_dma));
544 | //uint16_t lineBuffA[64];
545 | //uint16_t lineBuffB[64];
546 | uint16_t *currentLineBuff =lineBuffA;
547 | uint16_t *updateLineBuff =lineBuffA;
548 | uint32_t leftPixels = (length - (length&0xFFFFFFC0))>>1;
549 | uint32_t count = length>>6;
550 | uint8_t currentPixel=0;
551 | uint16_t color;
552 | uint8_t cmd = RAMWR;
553 | gpio_put(CS_PIN, 0);
554 | gpio_put(DC_PIN, 0); // command mode
555 |
556 | spi_write_blocking(SPI_DISP,&cmd, 1);
557 | gpio_put(DC_PIN, 1); // data mode
558 | while(count--){
559 | if (count&0x00000001){
560 | currentLineBuff = lineBuffA;
561 | updateLineBuff = lineBuffA;
562 | }else{
563 | currentLineBuff = lineBuffB;
564 | updateLineBuff = lineBuffB;
565 | }
566 | for (int i=2;i>0;i--){
567 | currentPixel = *frameBuff++;color = LUT[currentPixel>>4];*currentLineBuff++ = color;
568 | color = LUT[currentPixel&0x0F];*currentLineBuff++ = color;
569 | currentPixel = *frameBuff++;color = LUT[currentPixel>>4];*currentLineBuff++ = color;
570 | color = LUT[currentPixel&0x0F];*currentLineBuff++ = color;
571 | currentPixel = *frameBuff++;color = LUT[currentPixel>>4];*currentLineBuff++ = color;
572 | color = LUT[currentPixel&0x0F];*currentLineBuff++ = color;
573 | currentPixel = *frameBuff++;color = LUT[currentPixel>>4];*currentLineBuff++ = color;
574 | color = LUT[currentPixel&0x0F];*currentLineBuff++ = color;
575 | currentPixel = *frameBuff++;color = LUT[currentPixel>>4];*currentLineBuff++ = color;
576 | color = LUT[currentPixel&0x0F];*currentLineBuff++ = color;
577 | currentPixel = *frameBuff++;color = LUT[currentPixel>>4];*currentLineBuff++ = color;
578 | color = LUT[currentPixel&0x0F];*currentLineBuff++ = color;
579 | currentPixel = *frameBuff++;color = LUT[currentPixel>>4];*currentLineBuff++ = color;
580 | color = LUT[currentPixel&0x0F];*currentLineBuff++ = color;
581 | currentPixel = *frameBuff++;color = LUT[currentPixel>>4];*currentLineBuff++ = color;
582 | color = LUT[currentPixel&0x0F];*currentLineBuff++ = color;
583 | currentPixel = *frameBuff++;color = LUT[currentPixel>>4];*currentLineBuff++ = color;
584 | color = LUT[currentPixel&0x0F];*currentLineBuff++ = color;
585 | currentPixel = *frameBuff++;color = LUT[currentPixel>>4];*currentLineBuff++ = color;
586 | color = LUT[currentPixel&0x0F];*currentLineBuff++ = color;
587 | currentPixel = *frameBuff++;color = LUT[currentPixel>>4];*currentLineBuff++ = color;
588 | color = LUT[currentPixel&0x0F];*currentLineBuff++ = color;
589 | currentPixel = *frameBuff++;color = LUT[currentPixel>>4];*currentLineBuff++ = color;
590 | color = LUT[currentPixel&0x0F];*currentLineBuff++ = color;
591 | currentPixel = *frameBuff++;color = LUT[currentPixel>>4];*currentLineBuff++ = color;
592 | color = LUT[currentPixel&0x0F];*currentLineBuff++ = color;
593 | currentPixel = *frameBuff++;color = LUT[currentPixel>>4];*currentLineBuff++ = color;
594 | color = LUT[currentPixel&0x0F];*currentLineBuff++ = color;
595 | currentPixel = *frameBuff++;color = LUT[currentPixel>>4];*currentLineBuff++ = color;
596 | color = LUT[currentPixel&0x0F];*currentLineBuff++ = color;
597 | currentPixel = *frameBuff++;color = LUT[currentPixel>>4];*currentLineBuff++ = color;
598 | color = LUT[currentPixel&0x0F];*currentLineBuff++ = color;
599 | }
600 | while (dma_channel_is_busy(st_dma));
601 | Write_dma((const uint8_t *)updateLineBuff,64*2);
602 | }
603 | if (leftPixels != 0){
604 | if (updateLineBuff == lineBuffB){
605 | currentLineBuff = lineBuffA;
606 | updateLineBuff = lineBuffA;
607 | }else{
608 | currentLineBuff = lineBuffB;
609 | updateLineBuff = lineBuffB;
610 | }
611 |
612 | while(leftPixels--){
613 | currentPixel = *frameBuff++;color = LUT[currentPixel>>4];*currentLineBuff++ = color;
614 | color = LUT[currentPixel&0x0F];*currentLineBuff++ = color;
615 | }
616 | while (dma_channel_is_busy(st_dma));
617 | Write_dma((const uint8_t *)lineBuffB,leftPixels*4);
618 | }
619 | while (dma_channel_is_busy(st_dma));
620 | while (spi_get_hw(SPI_DISP)->sr & SPI_SSPSR_BSY_BITS) {
621 | tight_loop_contents();
622 | }
623 | gpio_put(CS_PIN, 1);
624 | }
625 |
626 | void LUT2Update(uint8_t *frameBuff, uint32_t length, const uint16_t *LUT){
627 | while (dma_channel_is_busy(st_dma));
628 | //uint16_t lineBuffA[64];
629 | //uint16_t lineBuffB[64];
630 | uint16_t *currentLineBuff=lineBuffA;
631 | uint16_t *updateLineBuff=lineBuffA;
632 | uint32_t leftPixels = (length - (length&0xFFFFFFC0))>>2;
633 | uint32_t count = length>>6;
634 | uint8_t currentPixel=0;
635 | uint16_t color;
636 | uint8_t cmd = RAMWR;
637 | gpio_put(CS_PIN, 0);
638 | gpio_put(DC_PIN, 0); // command mode
639 |
640 | spi_write_blocking(SPI_DISP,&cmd, 1);
641 | gpio_put(DC_PIN, 1); // data mode
642 | while(count--){
643 | if (count&0x00000001){
644 | currentLineBuff = lineBuffA;
645 | updateLineBuff = lineBuffA;
646 | }else{
647 | currentLineBuff = lineBuffB;
648 | updateLineBuff = lineBuffB;
649 | }
650 | for (int i=2;i>0;i--){
651 | currentPixel = *frameBuff++;color = LUT[currentPixel&0x03];*currentLineBuff++ = color;
652 | color = LUT[(currentPixel>>2)&0x03];*currentLineBuff++ = color;
653 | color = LUT[(currentPixel>>4)&0x03];*currentLineBuff++ = color;
654 | color = LUT[(currentPixel>>6)];*currentLineBuff++ = color;
655 | currentPixel = *frameBuff++;color = LUT[currentPixel&0x03];*currentLineBuff++ = color;
656 | color = LUT[(currentPixel>>2)&0x03];*currentLineBuff++ = color;
657 | color = LUT[(currentPixel>>4)&0x03];*currentLineBuff++ = color;
658 | color = LUT[(currentPixel>>6)];*currentLineBuff++ = color;
659 | currentPixel = *frameBuff++;color = LUT[currentPixel&0x03];*currentLineBuff++ = color;
660 | color = LUT[(currentPixel>>2)&0x03];*currentLineBuff++ = color;
661 | color = LUT[(currentPixel>>4)&0x03];*currentLineBuff++ = color;
662 | color = LUT[(currentPixel>>6)];*currentLineBuff++ = color;
663 | currentPixel = *frameBuff++;color = LUT[currentPixel&0x03];*currentLineBuff++ = color;
664 | color = LUT[(currentPixel>>2)&0x03];*currentLineBuff++ = color;
665 | color = LUT[(currentPixel>>4)&0x03];*currentLineBuff++ = color;
666 | color = LUT[(currentPixel>>6)];*currentLineBuff++ = color;
667 | currentPixel = *frameBuff++;color = LUT[currentPixel&0x03];*currentLineBuff++ = color;
668 | color = LUT[(currentPixel>>2)&0x03];*currentLineBuff++ = color;
669 | color = LUT[(currentPixel>>4)&0x03];*currentLineBuff++ = color;
670 | color = LUT[(currentPixel>>6)];*currentLineBuff++ = color;
671 | currentPixel = *frameBuff++;color = LUT[currentPixel&0x03];*currentLineBuff++ = color;
672 | color = LUT[(currentPixel>>2)&0x03];*currentLineBuff++ = color;
673 | color = LUT[(currentPixel>>4)&0x03];*currentLineBuff++ = color;
674 | color = LUT[(currentPixel>>6)];*currentLineBuff++ = color;
675 | currentPixel = *frameBuff++;color = LUT[currentPixel&0x03];*currentLineBuff++ = color;
676 | color = LUT[(currentPixel>>2)&0x03];*currentLineBuff++ = color;
677 | color = LUT[(currentPixel>>4)&0x03];*currentLineBuff++ = color;
678 | color = LUT[(currentPixel>>6)];*currentLineBuff++ = color;
679 | currentPixel = *frameBuff++;color = LUT[currentPixel&0x03];*currentLineBuff++ = color;
680 | color = LUT[(currentPixel>>2)&0x03];*currentLineBuff++ = color;
681 | color = LUT[(currentPixel>>4)&0x03];*currentLineBuff++ = color;
682 | color = LUT[(currentPixel>>6)];*currentLineBuff++ = color;
683 | }
684 | while (dma_channel_is_busy(st_dma));
685 | Write_dma((const uint8_t *)updateLineBuff,64*2);
686 | }
687 | if (leftPixels != 0){
688 | if (updateLineBuff == lineBuffB){
689 | currentLineBuff = lineBuffA;
690 | updateLineBuff = lineBuffA;
691 | }else{
692 | currentLineBuff = lineBuffB;
693 | updateLineBuff = lineBuffB;
694 | }
695 |
696 | while(leftPixels--){
697 | currentPixel = *frameBuff++;color = LUT[currentPixel&0x03];*currentLineBuff++ = color;
698 | color = LUT[(currentPixel>>2)&0x03];*currentLineBuff++ = color;
699 | color = LUT[(currentPixel>>4)&0x03];*currentLineBuff++ = color;
700 | color = LUT[(currentPixel>>6)];*currentLineBuff++ = color;
701 | }
702 | while (dma_channel_is_busy(st_dma));
703 | Write_dma((const uint8_t *)lineBuffB,leftPixels*8);
704 | }
705 | while (dma_channel_is_busy(st_dma));
706 | while (spi_get_hw(SPI_DISP)->sr & SPI_SSPSR_BSY_BITS) {
707 | tight_loop_contents();
708 | }
709 | gpio_put(CS_PIN, 1);
710 | }
711 |
712 | void LUT1Update(uint8_t *frameBuff, uint32_t length, const uint16_t *LUT){
713 | while (dma_channel_is_busy(st_dma));
714 | //uint16_t lineBuffA[64];
715 | //uint16_t lineBuffB[64];
716 | uint16_t *currentLineBuff=lineBuffA;
717 | uint16_t *updateLineBuff=lineBuffA;
718 | uint32_t leftPixels = (length - (length&0xFFFFFFC0))>>3;
719 | uint32_t count = length>>6;
720 | uint8_t currentPixel=0;
721 | uint16_t color;
722 | uint8_t cmd = RAMWR;
723 | gpio_put(CS_PIN, 0);
724 | gpio_put(DC_PIN, 0); // command mode
725 |
726 | spi_write_blocking(SPI_DISP,&cmd, 1);
727 | gpio_put(DC_PIN, 1); // data mode
728 | while(count--){
729 | if (count&0x00000001){
730 | currentLineBuff = lineBuffA;
731 | updateLineBuff = lineBuffA;
732 | }else{
733 | currentLineBuff = lineBuffB;
734 | updateLineBuff = lineBuffB;
735 | }
736 | for (int i=2;i>0;i--){
737 | currentPixel = *frameBuff++;color = LUT[currentPixel&0x01];*currentLineBuff++ = color;
738 | color = LUT[(currentPixel>>0x01)&0x01];*currentLineBuff++ = color;
739 | color = LUT[(currentPixel>>0x02)&0x01];*currentLineBuff++ = color;
740 | color = LUT[(currentPixel>>0x03)&0x01];*currentLineBuff++ = color;
741 | color = LUT[(currentPixel>>0x04)&0x01];*currentLineBuff++ = color;
742 | color = LUT[(currentPixel>>0x05)&0x01];*currentLineBuff++ = color;
743 | color = LUT[(currentPixel>>0x06)&0x01];*currentLineBuff++ = color;
744 | color = LUT[(currentPixel>>0x07)&0x01];*currentLineBuff++ = color;
745 | currentPixel = *frameBuff++;color = LUT[currentPixel&0x01];*currentLineBuff++ = color;
746 | color = LUT[(currentPixel>>0x01)&0x01];*currentLineBuff++ = color;
747 | color = LUT[(currentPixel>>0x02)&0x01];*currentLineBuff++ = color;
748 | color = LUT[(currentPixel>>0x03)&0x01];*currentLineBuff++ = color;
749 | color = LUT[(currentPixel>>0x04)&0x01];*currentLineBuff++ = color;
750 | color = LUT[(currentPixel>>0x05)&0x01];*currentLineBuff++ = color;
751 | color = LUT[(currentPixel>>0x06)&0x01];*currentLineBuff++ = color;
752 | color = LUT[(currentPixel>>0x07)&0x01];*currentLineBuff++ = color;
753 | currentPixel = *frameBuff++;color = LUT[currentPixel&0x01];*currentLineBuff++ = color;
754 | color = LUT[(currentPixel>>0x01)&0x01];*currentLineBuff++ = color;
755 | color = LUT[(currentPixel>>0x02)&0x01];*currentLineBuff++ = color;
756 | color = LUT[(currentPixel>>0x03)&0x01];*currentLineBuff++ = color;
757 | color = LUT[(currentPixel>>0x04)&0x01];*currentLineBuff++ = color;
758 | color = LUT[(currentPixel>>0x05)&0x01];*currentLineBuff++ = color;
759 | color = LUT[(currentPixel>>0x06)&0x01];*currentLineBuff++ = color;
760 | color = LUT[(currentPixel>>0x07)&0x01];*currentLineBuff++ = color;
761 | currentPixel = *frameBuff++;color = LUT[currentPixel&0x01];*currentLineBuff++ = color;
762 | color = LUT[(currentPixel>>0x01)&0x01];*currentLineBuff++ = color;
763 | color = LUT[(currentPixel>>0x02)&0x01];*currentLineBuff++ = color;
764 | color = LUT[(currentPixel>>0x03)&0x01];*currentLineBuff++ = color;
765 | color = LUT[(currentPixel>>0x04)&0x01];*currentLineBuff++ = color;
766 | color = LUT[(currentPixel>>0x05)&0x01];*currentLineBuff++ = color;
767 | color = LUT[(currentPixel>>0x06)&0x01];*currentLineBuff++ = color;
768 | color = LUT[(currentPixel>>0x07)&0x01];*currentLineBuff++ = color;
769 | }
770 | while (dma_channel_is_busy(st_dma));
771 | Write_dma((const uint8_t *)updateLineBuff,64*2);
772 | }
773 | if (leftPixels != 0){
774 | if (updateLineBuff == lineBuffB){
775 | currentLineBuff = lineBuffA;
776 | updateLineBuff = lineBuffA;
777 | }else{
778 | currentLineBuff = lineBuffB;
779 | updateLineBuff = lineBuffB;
780 | }
781 |
782 | while(leftPixels--){
783 | currentPixel = *frameBuff++;color = LUT[currentPixel&0x01];*currentLineBuff++ = color;
784 | color = LUT[(currentPixel>>0x01)&0x01];*currentLineBuff++ = color;
785 | color = LUT[(currentPixel>>0x02)&0x01];*currentLineBuff++ = color;
786 | color = LUT[(currentPixel>>0x03)&0x01];*currentLineBuff++ = color;
787 | color = LUT[(currentPixel>>0x04)&0x01];*currentLineBuff++ = color;
788 | color = LUT[(currentPixel>>0x05)&0x01];*currentLineBuff++ = color;
789 | color = LUT[(currentPixel>>0x06)&0x01];*currentLineBuff++ = color;
790 | color = LUT[(currentPixel>>0x07)&0x01];*currentLineBuff++ = color;
791 | }
792 | while (dma_channel_is_busy(st_dma));
793 | Write_dma((const uint8_t *)lineBuffB,leftPixels*16);
794 | }
795 | while (dma_channel_is_busy(st_dma));
796 | while (spi_get_hw(SPI_DISP)->sr & SPI_SSPSR_BSY_BITS) {
797 | tight_loop_contents();
798 | }
799 | gpio_put(CS_PIN, 1);
800 | }
801 |
802 |
803 |
804 |
805 |
806 |
807 | // Define all attributes of the module.
808 | // Table entries are key/value pairs of the attribute name (a string)
809 | // and the MicroPython object reference.
810 | // All identifiers and strings are written as MP_QSTR_xxx and will be
811 | // optimized to word-sized integers by the build system (interned strings).
812 | static const mp_rom_map_elem_t picocalcdisplay_globals_table[] = {
813 | { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_picocalcdisplay) },
814 | { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pd_init_obj) },
815 | { MP_ROM_QSTR(MP_QSTR_setLUT), MP_ROM_PTR(&setLUT_obj) },
816 | { MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&pd_update_obj) },
817 | { MP_ROM_QSTR(MP_QSTR_startAutoUpdate), MP_ROM_PTR(&startAutoUpdate_obj) },
818 | { MP_ROM_QSTR(MP_QSTR_stopAutoUpdate), MP_ROM_PTR(&stopAutoUpdate_obj) },
819 | { MP_ROM_QSTR(MP_QSTR_drawTxt6x8), MP_ROM_PTR(&drawTxt6x8_obj) },
820 | { MP_ROM_QSTR(MP_QSTR_resetLUT), MP_ROM_PTR(&pd_resetLUT_obj) },
821 | { MP_ROM_QSTR(MP_QSTR_getLUTview), MP_ROM_PTR(&pd_getLUTview_obj) },
822 | { MP_ROM_QSTR(MP_QSTR_isScreenUpdateDone), MP_ROM_PTR(&pd_isScreenUpdateDone_obj) },
823 |
824 | };
825 | static MP_DEFINE_CONST_DICT(picocalcdisplay_globals, picocalcdisplay_globals_table);
826 |
827 | // Define module object.
828 | const mp_obj_module_t picocalcdisplay_module = {
829 | .base = { &mp_type_module },
830 | .globals = (mp_obj_dict_t *)&picocalcdisplay_globals,
831 | };
832 |
833 | // Register the module to make it available in Python.
834 | MP_REGISTER_MODULE(MP_QSTR_picocalcdisplay, picocalcdisplay_module);
835 |
--------------------------------------------------------------------------------
/picocalcdisplay/font6x8e500.h:
--------------------------------------------------------------------------------
1 |
2 |
3 | #ifndef FONT6X8TT_H
4 | #define FONT6X8TT_H
5 |
6 |
7 | //CP437 - IBM/MS-DOS Codepage
8 | //https://en.wikipedia.org/wiki/Code_page_437
9 | const uint8_t CP437_display[] = {
10 | // 0x10 ( )
11 | 0b00000000,
12 | 0b11000000,
13 | 0b11110000,
14 | 0b11111100,
15 | 0b11111100,
16 | 0b11110000,
17 | 0b11000000,
18 | 0b00000000,
19 | // 0x11 ( )
20 | 0b00000000,
21 | 0b00001100,
22 | 0b00111100,
23 | 0b11111100,
24 | 0b11111100,
25 | 0b00111100,
26 | 0b00001100,
27 | 0b00000000,
28 | // 0x12 ( )
29 | 0b00100000,
30 | 0b01110000,
31 | 0b10101000,
32 | 0b00100000,
33 | 0b10101000,
34 | 0b01110000,
35 | 0b00100000,
36 | 0b00000000,
37 | // 0x13 ( )
38 | 0b01010000,
39 | 0b01010000,
40 | 0b01010000,
41 | 0b01010000,
42 | 0b01010000,
43 | 0b00000000,
44 | 0b01010000,
45 | 0b00000000,
46 | // 0x14 ( )
47 | 0b01111000,
48 | 0b11101000,
49 | 0b11101000,
50 | 0b01101000,
51 | 0b00101000,
52 | 0b00101000,
53 | 0b00101000,
54 | 0b00000000,
55 | // 0x15 ( )
56 | 0b01110000,
57 | 0b10001000,
58 | 0b01100000,
59 | 0b01010000,
60 | 0b00111000,
61 | 0b10001000,
62 | 0b01110000,
63 | 0b00000000,
64 | // 0x16 ( )
65 | 0b00000000,
66 | 0b00000000,
67 | 0b00000000,
68 | 0b00000000,
69 | 0b00000000,
70 | 0b00000000,
71 | 0b11111100,
72 | 0b11111100,
73 | // 0x17 ( )
74 | 0b00100000,
75 | 0b01110000,
76 | 0b10101000,
77 | 0b00100000,
78 | 0b10101000,
79 | 0b01110000,
80 | 0b00100000,
81 | 0b11111000,
82 | // 0x18 ( )
83 | 0b00100000,
84 | 0b01110000,
85 | 0b10101000,
86 | 0b00100000,
87 | 0b00100000,
88 | 0b00100000,
89 | 0b00100000,
90 | 0b00000000,
91 | // 0x19 ( )
92 | 0b00100000,
93 | 0b00100000,
94 | 0b00100000,
95 | 0b00100000,
96 | 0b10101000,
97 | 0b01110000,
98 | 0b00100000,
99 | 0b00000000,
100 | // 0x1A ( )
101 | 0b00000000,
102 | 0b00100000,
103 | 0b00010000,
104 | 0b11111000,
105 | 0b00010000,
106 | 0b00100000,
107 | 0b00000000,
108 | 0b00000000,
109 | // 0x1B ( )
110 | 0b00000000,
111 | 0b00100000,
112 | 0b01000000,
113 | 0b11111000,
114 | 0b01000000,
115 | 0b00100000,
116 | 0b00000000,
117 | 0b00000000,
118 | // 0x1C ( )
119 | 0b00000000,
120 | 0b00000000,
121 | 0b10000000,
122 | 0b10000000,
123 | 0b10000000,
124 | 0b10000000,
125 | 0b11111000,
126 | 0b00000000,
127 | // 0x1D ( )
128 | 0b00000000,
129 | 0b00000000,
130 | 0b01010000,
131 | 0b11111000,
132 | 0b01010000,
133 | 0b00000000,
134 | 0b00000000,
135 | 0b00000000,
136 | // 0x1E ( )
137 | 0b00000000,
138 | 0b00000000,
139 | 0b00100000,
140 | 0b01110000,
141 | 0b11111000,
142 | 0b00000000,
143 | 0b00000000,
144 | 0b00000000,
145 | // 0x1F ( )
146 | 0b00000000,
147 | 0b00000000,
148 | 0b11111000,
149 | 0b01110000,
150 | 0b00100000,
151 | 0b00000000,
152 | 0b00000000,
153 | 0b00000000,
154 | // 0x20 ( )
155 | 0b00000000,
156 | 0b00000000,
157 | 0b00000000,
158 | 0b00000000,
159 | 0b00000000,
160 | 0b00000000,
161 | 0b00000000,
162 | 0b00000000,
163 | // 0x21 ( ! )
164 | 0b00100000,
165 | 0b00100000,
166 | 0b00100000,
167 | 0b00100000,
168 | 0b00100000,
169 | 0b00000000,
170 | 0b00100000,
171 | 0b00000000,
172 | // 0x22 ( " )
173 | 0b01001000,
174 | 0b01001000,
175 | 0b10010000,
176 | 0b00000000,
177 | 0b00000000,
178 | 0b00000000,
179 | 0b00000000,
180 | 0b00000000,
181 | // 0x23 ( # )
182 | 0b01010000,
183 | 0b11111000,
184 | 0b01010000,
185 | 0b01010000,
186 | 0b01010000,
187 | 0b11111000,
188 | 0b01010000,
189 | 0b00000000,
190 | // 0x24 ( $ )
191 | 0b00100000,
192 | 0b01111000,
193 | 0b10100000,
194 | 0b01110000,
195 | 0b00101000,
196 | 0b11110000,
197 | 0b00100000,
198 | 0b00000000,
199 | // 0x25 ( % )
200 | 0b11000000,
201 | 0b11001000,
202 | 0b00010000,
203 | 0b00100000,
204 | 0b01000000,
205 | 0b10011000,
206 | 0b00011000,
207 | 0b00000000,
208 | // 0x26 ( & )
209 | 0b01100000,
210 | 0b10010000,
211 | 0b10100000,
212 | 0b01000000,
213 | 0b10101000,
214 | 0b10010000,
215 | 0b01101000,
216 | 0b00000000,
217 | // 0x27 ( ' )
218 | 0b01100000,
219 | 0b01100000,
220 | 0b00100000,
221 | 0b01000000,
222 | 0b00000000,
223 | 0b00000000,
224 | 0b00000000,
225 | 0b00000000,
226 | // 0x28 ( ( )
227 | 0b00010000,
228 | 0b00100000,
229 | 0b01000000,
230 | 0b01000000,
231 | 0b01000000,
232 | 0b00100000,
233 | 0b00010000,
234 | 0b00000000,
235 | // 0x29 ( ) )
236 | 0b01000000,
237 | 0b00100000,
238 | 0b00010000,
239 | 0b00010000,
240 | 0b00010000,
241 | 0b00100000,
242 | 0b01000000,
243 | 0b00000000,
244 | // 0x2A ( * )
245 | 0b00000000,
246 | 0b00100000,
247 | 0b10101000,
248 | 0b01110000,
249 | 0b10101000,
250 | 0b00100000,
251 | 0b00000000,
252 | 0b00000000,
253 | // 0x2B ( + )
254 | 0b00000000,
255 | 0b00100000,
256 | 0b00100000,
257 | 0b11111000,
258 | 0b00100000,
259 | 0b00100000,
260 | 0b00000000,
261 | 0b00000000,
262 | // 0x2C ( , )
263 | 0b00000000,
264 | 0b00000000,
265 | 0b00000000,
266 | 0b01100000,
267 | 0b01100000,
268 | 0b00100000,
269 | 0b01000000,
270 | 0b00000000,
271 | // 0x2D ( - )
272 | 0b00000000,
273 | 0b00000000,
274 | 0b00000000,
275 | 0b11111000,
276 | 0b00000000,
277 | 0b00000000,
278 | 0b00000000,
279 | 0b00000000,
280 | // 0x2E ( . )
281 | 0b00000000,
282 | 0b00000000,
283 | 0b00000000,
284 | 0b00000000,
285 | 0b00000000,
286 | 0b01100000,
287 | 0b01100000,
288 | 0b00000000,
289 | // 0x2F ( / )
290 | 0b00001000,
291 | 0b00001000,
292 | 0b00010000,
293 | 0b00100000,
294 | 0b01000000,
295 | 0b10000000,
296 | 0b10000000,
297 | 0b00000000,
298 | // 0x30 ( 0 )
299 | 0b01110000,
300 | 0b10001000,
301 | 0b10011000,
302 | 0b10101000,
303 | 0b11001000,
304 | 0b10001000,
305 | 0b01110000,
306 | 0b00000000,
307 | // 0x31 ( 1 )
308 | 0b00100000,
309 | 0b01100000,
310 | 0b00100000,
311 | 0b00100000,
312 | 0b00100000,
313 | 0b00100000,
314 | 0b01110000,
315 | 0b00000000,
316 | // 0x32 ( 2 )
317 | 0b01110000,
318 | 0b10001000,
319 | 0b00001000,
320 | 0b00010000,
321 | 0b00100000,
322 | 0b01000000,
323 | 0b11111000,
324 | 0b00000000,
325 | // 0x33 ( 3 )
326 | 0b11111000,
327 | 0b00010000,
328 | 0b00100000,
329 | 0b01110000,
330 | 0b00001000,
331 | 0b00001000,
332 | 0b11110000,
333 | 0b00000000,
334 | // 0x34 ( 4 )
335 | 0b00010000,
336 | 0b00110000,
337 | 0b01010000,
338 | 0b10010000,
339 | 0b11111000,
340 | 0b00010000,
341 | 0b00010000,
342 | 0b00000000,
343 | // 0x35 ( 5 )
344 | 0b11111000,
345 | 0b10000000,
346 | 0b10000000,
347 | 0b11110000,
348 | 0b00001000,
349 | 0b10001000,
350 | 0b01110000,
351 | 0b00000000,
352 | // 0x36 ( 6 )
353 | 0b00110000,
354 | 0b01000000,
355 | 0b10000000,
356 | 0b11110000,
357 | 0b10001000,
358 | 0b10001000,
359 | 0b01110000,
360 | 0b00000000,
361 | // 0x37 ( 7 )
362 | 0b11111000,
363 | 0b00001000,
364 | 0b00010000,
365 | 0b00100000,
366 | 0b00100000,
367 | 0b00100000,
368 | 0b00100000,
369 | 0b00000000,
370 | // 0x38 ( 8 )
371 | 0b01110000,
372 | 0b10001000,
373 | 0b10001000,
374 | 0b01110000,
375 | 0b10001000,
376 | 0b10001000,
377 | 0b01110000,
378 | 0b00000000,
379 | // 0x39 ( 9 )
380 | 0b01110000,
381 | 0b10001000,
382 | 0b10001000,
383 | 0b01111000,
384 | 0b00001000,
385 | 0b00010000,
386 | 0b01100000,
387 | 0b00000000,
388 | // 0x3A ( : )
389 | 0b00000000,
390 | 0b01100000,
391 | 0b01100000,
392 | 0b00000000,
393 | 0b01100000,
394 | 0b01100000,
395 | 0b00000000,
396 | 0b00000000,
397 | // 0x3B ( ; )
398 | 0b01100000,
399 | 0b01100000,
400 | 0b00000000,
401 | 0b01100000,
402 | 0b01100000,
403 | 0b00100000,
404 | 0b01000000,
405 | 0b00000000,
406 | // 0x3C ( < )
407 | 0b00010000,
408 | 0b00100000,
409 | 0b01000000,
410 | 0b10000000,
411 | 0b01000000,
412 | 0b00100000,
413 | 0b00010000,
414 | 0b00000000,
415 | // 0x3D ( = )
416 | 0b00000000,
417 | 0b00000000,
418 | 0b11111000,
419 | 0b00000000,
420 | 0b11111000,
421 | 0b00000000,
422 | 0b00000000,
423 | 0b00000000,
424 | // 0x3E ( > )
425 | 0b01000000,
426 | 0b00100000,
427 | 0b00010000,
428 | 0b00001000,
429 | 0b00010000,
430 | 0b00100000,
431 | 0b01000000,
432 | 0b00000000,
433 | // 0x3F ( ? )
434 | 0b01110000,
435 | 0b10001000,
436 | 0b00001000,
437 | 0b00010000,
438 | 0b00100000,
439 | 0b00000000,
440 | 0b00100000,
441 | 0b00000000,
442 | // 0x40 ( @ )
443 | 0b01110000,
444 | 0b10001000,
445 | 0b00001000,
446 | 0b01101000,
447 | 0b10101000,
448 | 0b10101000,
449 | 0b01110000,
450 | 0b00000000,
451 | // 0x41 ( A )
452 | 0b00100000,
453 | 0b01010000,
454 | 0b10001000,
455 | 0b10001000,
456 | 0b11111000,
457 | 0b10001000,
458 | 0b10001000,
459 | 0b00000000,
460 | // 0x42 ( B )
461 | 0b11110000,
462 | 0b01001000,
463 | 0b01001000,
464 | 0b01110000,
465 | 0b01001000,
466 | 0b01001000,
467 | 0b11110000,
468 | 0b00000000,
469 | // 0x43 ( C )
470 | 0b01110000,
471 | 0b10001000,
472 | 0b10000000,
473 | 0b10000000,
474 | 0b10000000,
475 | 0b10001000,
476 | 0b01110000,
477 | 0b00000000,
478 | // 0x44 ( D )
479 | 0b11110000,
480 | 0b01001000,
481 | 0b01001000,
482 | 0b01001000,
483 | 0b01001000,
484 | 0b01001000,
485 | 0b11110000,
486 | 0b00000000,
487 | // 0x45 ( E )
488 | 0b11111000,
489 | 0b10000000,
490 | 0b10000000,
491 | 0b11110000,
492 | 0b10000000,
493 | 0b10000000,
494 | 0b11111000,
495 | 0b00000000,
496 | // 0x46 ( F )
497 | 0b11111000,
498 | 0b10000000,
499 | 0b10000000,
500 | 0b11110000,
501 | 0b10000000,
502 | 0b10000000,
503 | 0b10000000,
504 | 0b00000000,
505 | // 0x47 ( G )
506 | 0b01111000,
507 | 0b10000000,
508 | 0b10000000,
509 | 0b10011000,
510 | 0b10001000,
511 | 0b10001000,
512 | 0b01110000,
513 | 0b00000000,
514 | // 0x48 ( H )
515 | 0b10001000,
516 | 0b10001000,
517 | 0b10001000,
518 | 0b11111000,
519 | 0b10001000,
520 | 0b10001000,
521 | 0b10001000,
522 | 0b00000000,
523 | // 0x49 ( I )
524 | 0b01110000,
525 | 0b00100000,
526 | 0b00100000,
527 | 0b00100000,
528 | 0b00100000,
529 | 0b00100000,
530 | 0b01110000,
531 | 0b00000000,
532 | // 0x4A ( J )
533 | 0b00111000,
534 | 0b00010000,
535 | 0b00010000,
536 | 0b00010000,
537 | 0b00010000,
538 | 0b10010000,
539 | 0b01100000,
540 | 0b00000000,
541 | // 0x4B ( K )
542 | 0b10001000,
543 | 0b10010000,
544 | 0b10100000,
545 | 0b11000000,
546 | 0b10100000,
547 | 0b10010000,
548 | 0b10001000,
549 | 0b00000000,
550 | // 0x4C ( L )
551 | 0b10000000,
552 | 0b10000000,
553 | 0b10000000,
554 | 0b10000000,
555 | 0b10000000,
556 | 0b10000000,
557 | 0b11111000,
558 | 0b00000000,
559 | // 0x4D ( M )
560 | 0b10001000,
561 | 0b11011000,
562 | 0b10101000,
563 | 0b10001000,
564 | 0b10001000,
565 | 0b10001000,
566 | 0b10001000,
567 | 0b00000000,
568 | // 0x4E ( N )
569 | 0b10001000,
570 | 0b10001000,
571 | 0b11001000,
572 | 0b10101000,
573 | 0b10011000,
574 | 0b10001000,
575 | 0b10001000,
576 | 0b00000000,
577 | // 0x4F ( O )
578 | 0b01110000,
579 | 0b10001000,
580 | 0b10001000,
581 | 0b10001000,
582 | 0b10001000,
583 | 0b10001000,
584 | 0b01110000,
585 | 0b00000000,
586 | // 0x50 ( P )
587 | 0b11110000,
588 | 0b10001000,
589 | 0b10001000,
590 | 0b11110000,
591 | 0b10000000,
592 | 0b10000000,
593 | 0b10000000,
594 | 0b00000000,
595 | // 0x51 ( Q )
596 | 0b01110000,
597 | 0b10001000,
598 | 0b10001000,
599 | 0b10001000,
600 | 0b10101000,
601 | 0b10010000,
602 | 0b01101000,
603 | 0b00000000,
604 | // 0x52 ( R )
605 | 0b11110000,
606 | 0b10001000,
607 | 0b10001000,
608 | 0b11110000,
609 | 0b10001000,
610 | 0b10001000,
611 | 0b10001000,
612 | 0b00000000,
613 | // 0x53 ( S )
614 | 0b01111000,
615 | 0b10000000,
616 | 0b10000000,
617 | 0b01110000,
618 | 0b00001000,
619 | 0b10001000,
620 | 0b01110000,
621 | 0b00000000,
622 | // 0x54 ( T )
623 | 0b11111000,
624 | 0b00100000,
625 | 0b00100000,
626 | 0b00100000,
627 | 0b00100000,
628 | 0b00100000,
629 | 0b00100000,
630 | 0b00000000,
631 | // 0x55 ( U )
632 | 0b10001000,
633 | 0b10001000,
634 | 0b10001000,
635 | 0b10001000,
636 | 0b10001000,
637 | 0b10001000,
638 | 0b01110000,
639 | 0b00000000,
640 | // 0x56 ( V )
641 | 0b10001000,
642 | 0b10001000,
643 | 0b10001000,
644 | 0b10001000,
645 | 0b01010000,
646 | 0b01010000,
647 | 0b00100000,
648 | 0b00000000,
649 | // 0x57 ( W )
650 | 0b10001000,
651 | 0b10001000,
652 | 0b10001000,
653 | 0b10101000,
654 | 0b10101000,
655 | 0b11011000,
656 | 0b10001000,
657 | 0b00000000,
658 | // 0x58 ( X )
659 | 0b10001000,
660 | 0b10001000,
661 | 0b01010000,
662 | 0b00100000,
663 | 0b01010000,
664 | 0b10001000,
665 | 0b10001000,
666 | 0b00000000,
667 | // 0x59 ( Y )
668 | 0b10001000,
669 | 0b10001000,
670 | 0b01010000,
671 | 0b00100000,
672 | 0b00100000,
673 | 0b00100000,
674 | 0b00100000,
675 | 0b00000000,
676 | // 0x5A ( Z )
677 | 0b11111000,
678 | 0b00001000,
679 | 0b00010000,
680 | 0b00100000,
681 | 0b01000000,
682 | 0b10000000,
683 | 0b11111000,
684 | 0b00000000,
685 | // 0x5B ( [ )
686 | 0b01110000,
687 | 0b01000000,
688 | 0b01000000,
689 | 0b01000000,
690 | 0b01000000,
691 | 0b01000000,
692 | 0b01110000,
693 | 0b00000000,
694 | // 0x5C ( \ )
695 | 0b10000000,
696 | 0b10000000,
697 | 0b01000000,
698 | 0b00100000,
699 | 0b00010000,
700 | 0b00001000,
701 | 0b00001000,
702 | 0b00000000,
703 | // 0x5D ( ] )
704 | 0b01110000,
705 | 0b00010000,
706 | 0b00010000,
707 | 0b00010000,
708 | 0b00010000,
709 | 0b00010000,
710 | 0b01110000,
711 | 0b00000000,
712 | // 0x5E ( ^ )
713 | 0b00000000,
714 | 0b00100000,
715 | 0b01010000,
716 | 0b10001000,
717 | 0b10001000,
718 | 0b00000000,
719 | 0b00000000,
720 | 0b00000000,
721 | // 0x5F ( _ )
722 | 0b00000000,
723 | 0b00000000,
724 | 0b00000000,
725 | 0b00000000,
726 | 0b00000000,
727 | 0b00000000,
728 | 0b11111000,
729 | 0b00000000,
730 | // 0x60 ( ` )
731 | 0b00110000,
732 | 0b00110000,
733 | 0b00100000,
734 | 0b00010000,
735 | 0b00000000,
736 | 0b00000000,
737 | 0b00000000,
738 | 0b00000000,
739 | // 0x61 ( a )
740 | 0b00000000,
741 | 0b00000000,
742 | 0b01110000,
743 | 0b00001000,
744 | 0b01111000,
745 | 0b10001000,
746 | 0b01111000,
747 | 0b00000000,
748 | // 0x62 ( b )
749 | 0b10000000,
750 | 0b10000000,
751 | 0b11110000,
752 | 0b10001000,
753 | 0b10001000,
754 | 0b10001000,
755 | 0b11110000,
756 | 0b00000000,
757 | // 0x63 ( c )
758 | 0b00000000,
759 | 0b00000000,
760 | 0b01111000,
761 | 0b10000000,
762 | 0b10000000,
763 | 0b10000000,
764 | 0b01111000,
765 | 0b00000000,
766 | // 0x64 ( d )
767 | 0b00001000,
768 | 0b00001000,
769 | 0b01111000,
770 | 0b10001000,
771 | 0b10001000,
772 | 0b10001000,
773 | 0b01111000,
774 | 0b00000000,
775 | // 0x65 ( e )
776 | 0b00000000,
777 | 0b00000000,
778 | 0b01110000,
779 | 0b10001000,
780 | 0b11111000,
781 | 0b10000000,
782 | 0b01111000,
783 | 0b00000000,
784 | // 0x66 ( f )
785 | 0b00110000,
786 | 0b01000000,
787 | 0b11110000,
788 | 0b01000000,
789 | 0b01000000,
790 | 0b01000000,
791 | 0b01000000,
792 | 0b00000000,
793 | // 0x67 ( g )
794 | 0b00000000,
795 | 0b00000000,
796 | 0b01111000,
797 | 0b10001000,
798 | 0b10001000,
799 | 0b01111000,
800 | 0b00001000,
801 | 0b11110000,
802 | // 0x68 ( h )
803 | 0b10000000,
804 | 0b10000000,
805 | 0b11110000,
806 | 0b10001000,
807 | 0b10001000,
808 | 0b10001000,
809 | 0b10001000,
810 | 0b00000000,
811 | // 0x69 ( i )
812 | 0b00000000,
813 | 0b00100000,
814 | 0b00000000,
815 | 0b01100000,
816 | 0b00100000,
817 | 0b00100000,
818 | 0b00100000,
819 | 0b00000000,
820 | // 0x6A ( j )
821 | 0b00000000,
822 | 0b00010000,
823 | 0b00000000,
824 | 0b00110000,
825 | 0b00010000,
826 | 0b00010000,
827 | 0b00010000,
828 | 0b11100000,
829 | // 0x6B ( k )
830 | 0b10000000,
831 | 0b10000000,
832 | 0b10010000,
833 | 0b10100000,
834 | 0b11000000,
835 | 0b10100000,
836 | 0b10010000,
837 | 0b00000000,
838 | // 0x6C ( l )
839 | 0b00100000,
840 | 0b00100000,
841 | 0b00100000,
842 | 0b00100000,
843 | 0b00100000,
844 | 0b00100000,
845 | 0b00010000,
846 | 0b00000000,
847 | // 0x6D ( m )
848 | 0b00000000,
849 | 0b00000000,
850 | 0b01010000,
851 | 0b10101000,
852 | 0b10101000,
853 | 0b10001000,
854 | 0b10001000,
855 | 0b00000000,
856 | // 0x6E ( n )
857 | 0b00000000,
858 | 0b00000000,
859 | 0b11110000,
860 | 0b10001000,
861 | 0b10001000,
862 | 0b10001000,
863 | 0b10001000,
864 | 0b00000000,
865 | // 0x6F ( o )
866 | 0b00000000,
867 | 0b00000000,
868 | 0b01110000,
869 | 0b10001000,
870 | 0b10001000,
871 | 0b10001000,
872 | 0b01110000,
873 | 0b00000000,
874 | // 0x70 ( p )
875 | 0b00000000,
876 | 0b00000000,
877 | 0b11110000,
878 | 0b10001000,
879 | 0b10001000,
880 | 0b11110000,
881 | 0b10000000,
882 | 0b10000000,
883 | // 0x71 ( q )
884 | 0b00000000,
885 | 0b00000000,
886 | 0b01111000,
887 | 0b10001000,
888 | 0b10001000,
889 | 0b01111000,
890 | 0b00001000,
891 | 0b00001000,
892 | // 0x72 ( r )
893 | 0b00000000,
894 | 0b00000000,
895 | 0b10110000,
896 | 0b11000000,
897 | 0b10000000,
898 | 0b10000000,
899 | 0b10000000,
900 | 0b00000000,
901 | // 0x73 ( s )
902 | 0b00000000,
903 | 0b00000000,
904 | 0b01111000,
905 | 0b10000000,
906 | 0b01110000,
907 | 0b00001000,
908 | 0b11110000,
909 | 0b00000000,
910 | // 0x74 ( t )
911 | 0b00000000,
912 | 0b00100000,
913 | 0b01111000,
914 | 0b00100000,
915 | 0b00100000,
916 | 0b00100000,
917 | 0b00011000,
918 | 0b00000000,
919 | // 0x75 ( u )
920 | 0b00000000,
921 | 0b00000000,
922 | 0b10001000,
923 | 0b10001000,
924 | 0b10001000,
925 | 0b10001000,
926 | 0b01111000,
927 | 0b00000000,
928 | // 0x76 ( v )
929 | 0b00000000,
930 | 0b00000000,
931 | 0b10001000,
932 | 0b10001000,
933 | 0b10001000,
934 | 0b01010000,
935 | 0b00100000,
936 | 0b00000000,
937 | // 0x77 ( w )
938 | 0b00000000,
939 | 0b00000000,
940 | 0b10001000,
941 | 0b10001000,
942 | 0b10101000,
943 | 0b10101000,
944 | 0b01010000,
945 | 0b00000000,
946 | // 0x78 ( x )
947 | 0b00000000,
948 | 0b00000000,
949 | 0b10001000,
950 | 0b01010000,
951 | 0b00100000,
952 | 0b01010000,
953 | 0b10001000,
954 | 0b00000000,
955 | // 0x79 ( y )
956 | 0b00000000,
957 | 0b00000000,
958 | 0b10001000,
959 | 0b10001000,
960 | 0b10001000,
961 | 0b01111000,
962 | 0b00001000,
963 | 0b11110000,
964 | // 0x7A ( z )
965 | 0b00000000,
966 | 0b00000000,
967 | 0b11111000,
968 | 0b00010000,
969 | 0b00100000,
970 | 0b01000000,
971 | 0b11111000,
972 | 0b00000000,
973 | // 0x7B ( { )
974 | 0b00011000,
975 | 0b00100000,
976 | 0b00100000,
977 | 0b11000000,
978 | 0b00100000,
979 | 0b00100000,
980 | 0b00011000,
981 | 0b00000000,
982 | // 0x7C ( | )
983 | 0b00100000,
984 | 0b00100000,
985 | 0b00100000,
986 | 0b00100000,
987 | 0b00100000,
988 | 0b00100000,
989 | 0b00100000,
990 | 0b00000000,
991 | // 0x7D ( } )
992 | 0b11000000,
993 | 0b00100000,
994 | 0b00100000,
995 | 0b00011000,
996 | 0b00100000,
997 | 0b00100000,
998 | 0b11000000,
999 | 0b00000000,
1000 | // 0x7E ( ~ )
1001 | 0b00000000,
1002 | 0b00000000,
1003 | 0b01000000,
1004 | 0b10101000,
1005 | 0b00010000,
1006 | 0b00000000,
1007 | 0b00000000,
1008 | 0b00000000,
1009 | // 0x7F (delta)
1010 | 0b00000000,
1011 | 0b00100000,
1012 | 0b00100000,
1013 | 0b01010000,
1014 | 0b01010000,
1015 | 0b10001000,
1016 | 0b11111000,
1017 | 0b00000000,
1018 | // 0x80 (C dot)
1019 | 0b01111000,
1020 | 0b10000000,
1021 | 0b10000000,
1022 | 0b10000000,
1023 | 0b10000000,
1024 | 0b01111000,
1025 | 0b00100000,
1026 | 0b01000000,
1027 | // 0x81 (u..)
1028 | 0b01010000,
1029 | 0b00000000,
1030 | 0b10001000,
1031 | 0b10001000,
1032 | 0b10001000,
1033 | 0b10001000,
1034 | 0b01111000,
1035 | 0b00000000,
1036 | // 0x82 (e~)
1037 | 0b00100000,
1038 | 0b01000000,
1039 | 0b01110000,
1040 | 0b10001000,
1041 | 0b11111000,
1042 | 0b10000000,
1043 | 0b01111000,
1044 | 0b00000000,
1045 | // 0x83 (a^)
1046 | 0b00100000,
1047 | 0b01010000,
1048 | 0b01110000,
1049 | 0b00001000,
1050 | 0b01111000,
1051 | 0b10001000,
1052 | 0b01111000,
1053 | 0b00000000,
1054 | // 0x84 (a..)
1055 | 0b01010000,
1056 | 0b00000000,
1057 | 0b01110000,
1058 | 0b00001000,
1059 | 0b01111000,
1060 | 0b10001000,
1061 | 0b01111000,
1062 | 0b00000000,
1063 | // 0x85 (a~)
1064 | 0b00100000,
1065 | 0b00010000,
1066 | 0b01110000,
1067 | 0b00001000,
1068 | 0b01111000,
1069 | 0b10001000,
1070 | 0b01111000,
1071 | 0b00000000,
1072 | // 0x86 (ao)
1073 | 0b00100000,
1074 | 0b00000000,
1075 | 0b01110000,
1076 | 0b00001000,
1077 | 0b01111000,
1078 | 0b10001000,
1079 | 0b01111000,
1080 | 0b00000000,
1081 | // 0x87 (c,)
1082 | 0b00000000,
1083 | 0b00000000,
1084 | 0b01111000,
1085 | 0b10000000,
1086 | 0b10000000,
1087 | 0b10000000,
1088 | 0b01111000,
1089 | 0b00100000,
1090 | // 0x88 (e^)
1091 | 0b00100000,
1092 | 0b01010000,
1093 | 0b01110000,
1094 | 0b10001000,
1095 | 0b11111000,
1096 | 0b10000000,
1097 | 0b01111000,
1098 | 0b00000000,
1099 | // 0x89 (e..)
1100 | 0b01010000,
1101 | 0b00000000,
1102 | 0b01110000,
1103 | 0b10001000,
1104 | 0b11111000,
1105 | 0b10000000,
1106 | 0b01111000,
1107 | 0b00000000,
1108 | // 0x8A (e~)
1109 | 0b00100000,
1110 | 0b00010000,
1111 | 0b01110000,
1112 | 0b10001000,
1113 | 0b11111000,
1114 | 0b10000000,
1115 | 0b01111000,
1116 | 0b00000000,
1117 | // 0x8B (i..)
1118 | 0b00000000,
1119 | 0b01010000,
1120 | 0b00000000,
1121 | 0b01100000,
1122 | 0b00100000,
1123 | 0b00100000,
1124 | 0b00100000,
1125 | 0b00000000,
1126 | // 0x8C (i^)
1127 | 0b00100000,
1128 | 0b01010000,
1129 | 0b00000000,
1130 | 0b01100000,
1131 | 0b00100000,
1132 | 0b00100000,
1133 | 0b00100000,
1134 | 0b00000000,
1135 | // 0x8D (i~)
1136 | 0b01000000,
1137 | 0b00100000,
1138 | 0b00000000,
1139 | 0b01100000,
1140 | 0b00100000,
1141 | 0b00100000,
1142 | 0b00100000,
1143 | 0b00000000,
1144 | // 0x8E (A..)
1145 | 0b01010000,
1146 | 0b00000000,
1147 | 0b0111000,
1148 | 0b10001000,
1149 | 0b11111000,
1150 | 0b10001000,
1151 | 0b10001000,
1152 | 0b00000000,
1153 | // 0x8F (A.)
1154 | 0b00100000,
1155 | 0b00000000,
1156 | 0b0111000,
1157 | 0b10001000,
1158 | 0b11111000,
1159 | 0b10001000,
1160 | 0b10001000,
1161 | 0b00000000,
1162 | // 0x90 (E~)
1163 | 0b00010000,
1164 | 0b00100000,
1165 | 0b11111000,
1166 | 0b10000000,
1167 | 0b11111000,
1168 | 0b10000000,
1169 | 0b11111000,
1170 | 0b00000000,
1171 | // 0x91 (ee)
1172 | 0b00000000,
1173 | 0b00000000,
1174 | 0b11010000,
1175 | 0b00101000,
1176 | 0b11111000,
1177 | 0b10100000,
1178 | 0b01011000,
1179 | 0b00000000,
1180 | // 0x92 (AE)
1181 | 0b00111000,
1182 | 0b01100000,
1183 | 0b10100000,
1184 | 0b10111000,
1185 | 0b11100000,
1186 | 0b10100000,
1187 | 0b10111000,
1188 | 0b00000000,
1189 | // 0x93 (o^)
1190 | 0b00100000,
1191 | 0b01010000,
1192 | 0b01110000,
1193 | 0b10001000,
1194 | 0b10001000,
1195 | 0b10001000,
1196 | 0b01110000,
1197 | 0b00000000,
1198 | // 0x94 (o.)
1199 | 0b00100000,
1200 | 0b00000000,
1201 | 0b01110000,
1202 | 0b10001000,
1203 | 0b10001000,
1204 | 0b10001000,
1205 | 0b01110000,
1206 | 0b00000000,
1207 | // 0x95 (o~)
1208 | 0b00100000,
1209 | 0b00010000,
1210 | 0b01110000,
1211 | 0b10001000,
1212 | 0b10001000,
1213 | 0b10001000,
1214 | 0b01110000,
1215 | 0b00000000,
1216 | // 0x96 (u^)
1217 | 0b00100000,
1218 | 0b01010000,
1219 | 0b10001000,
1220 | 0b10001000,
1221 | 0b10001000,
1222 | 0b10001000,
1223 | 0b01111000,
1224 | 0b00000000,
1225 | // 0x97 (u~)
1226 | 0b01000000,
1227 | 0b00100000,
1228 | 0b10001000,
1229 | 0b10001000,
1230 | 0b10001000,
1231 | 0b10001000,
1232 | 0b01111000,
1233 | 0b00000000,
1234 | // 0x98 (y..)
1235 | 0b01010000,
1236 | 0b00000000,
1237 | 0b10001000,
1238 | 0b10001000,
1239 | 0b10001000,
1240 | 0b01111000,
1241 | 0b00001000,
1242 | 0b11110000,
1243 | // 0x99 (O..)
1244 | 0b01010000,
1245 | 0b01110000,
1246 | 0b10001000,
1247 | 0b10001000,
1248 | 0b10001000,
1249 | 0b10001000,
1250 | 0b01110000,
1251 | 0b00000000,
1252 | // 0x9A (U..)
1253 | 0b01010000,
1254 | 0b10001000,
1255 | 0b10001000,
1256 | 0b10001000,
1257 | 0b10001000,
1258 | 0b10001000,
1259 | 0b01110000,
1260 | 0b00000000,
1261 | // 0x9B(c/)
1262 | 0b00000000,
1263 | 0b00100000,
1264 | 0b01110000,
1265 | 0b10100000,
1266 | 0b10100000,
1267 | 0b01110000,
1268 | 0b00100000,
1269 | 0b00000000,
1270 | // 0x9C (pound)
1271 | 0b00011000,
1272 | 0b00100000,
1273 | 0b00100000,
1274 | 0b11111000,
1275 | 0b00100000,
1276 | 0b01000000,
1277 | 0b11111000,
1278 | 0b00000000,
1279 | // 0x9D (yuan)
1280 | 0b10001000,
1281 | 0b01010000,
1282 | 0b11111000,
1283 | 0b00100000,
1284 | 0b11111000,
1285 | 0b00100000,
1286 | 0b00100000,
1287 | 0b00000000,
1288 | // 0x9E (pts)
1289 | 0b11000000,
1290 | 0b10100000,
1291 | 0b11000000,
1292 | 0b10100000,
1293 | 0b01110000,
1294 | 0b00100000,
1295 | 0b00111000,
1296 | 0b00000000,
1297 | // 0x9F (special f)
1298 | 0b00011000,
1299 | 0b00100000,
1300 | 0b11111000,
1301 | 0b00100000,
1302 | 0b00100000,
1303 | 0b00100000,
1304 | 0b00100000,
1305 | 0b11000000,
1306 | // 0xA0 (a~)
1307 | 0b00100000,
1308 | 0b01000000,
1309 | 0b01110000,
1310 | 0b00001000,
1311 | 0b01111000,
1312 | 0b10001000,
1313 | 0b01111000,
1314 | 0b00000000,
1315 | // 0xA1(i~)
1316 | 0b00010000,
1317 | 0b00100000,
1318 | 0b00000000,
1319 | 0b01100000,
1320 | 0b00100000,
1321 | 0b00100000,
1322 | 0b00100000,
1323 | 0b00000000,
1324 | // 0xA2(o~)
1325 | 0b00100000,
1326 | 0b01000000,
1327 | 0b01110000,
1328 | 0b10001000,
1329 | 0b10001000,
1330 | 0b10001000,
1331 | 0b01110000,
1332 | 0b00000000,
1333 | // 0xA3 (u~)
1334 | 0b00010000,
1335 | 0b00100000,
1336 | 0b10001000,
1337 | 0b10001000,
1338 | 0b10001000,
1339 | 0b10001000,
1340 | 0b01111000,
1341 | 0b00000000,
1342 | // 0xA4 (n~)
1343 | 0b10100000,
1344 | 0b01010000,
1345 | 0b11110000,
1346 | 0b10001000,
1347 | 0b10001000,
1348 | 0b10001000,
1349 | 0b10001000,
1350 | 0b00000000,
1351 | // 0xA5 (N~)
1352 | 0b10100000,
1353 | 0b01010000,
1354 | 0b10001000,
1355 | 0b11001000,
1356 | 0b10101000,
1357 | 0b10011000,
1358 | 0b10001000,
1359 | 0b00000000,
1360 | // 0xA6 (^a)
1361 | 0b01100000,
1362 | 0b10010000,
1363 | 0b01111000,
1364 | 0b00000000,
1365 | 0b00000000,
1366 | 0b00000000,
1367 | 0b00000000,
1368 | 0b00000000,
1369 | // 0xA7 (^o)
1370 | 0b00110000,
1371 | 0b01001000,
1372 | 0b01001000,
1373 | 0b00110000,
1374 | 0b00000000,
1375 | 0b00000000,
1376 | 0b00000000,
1377 | 0b00000000,
1378 | // 0xA8 (inv ?)
1379 | 0b00100000,
1380 | 0b00000000,
1381 | 0b00100000,
1382 | 0b01000000,
1383 | 0b10000000,
1384 | 0b10001000,
1385 | 0b01110000,
1386 | 0b00000000,
1387 | // 0xA9 (not)
1388 | 0b00000000,
1389 | 0b00000000,
1390 | 0b00000000,
1391 | 0b11111000,
1392 | 0b10000000,
1393 | 0b00000000,
1394 | 0b00000000,
1395 | 0b00000000,
1396 | // 0xAA (not)
1397 | 0b00000000,
1398 | 0b00000000,
1399 | 0b00000000,
1400 | 0b11111000,
1401 | 0b00001000,
1402 | 0b00000000,
1403 | 0b00000000,
1404 | 0b00000000,
1405 | // 0xAB (1/2)
1406 | 0b01000000,
1407 | 0b01001000,
1408 | 0b01010000,
1409 | 0b00111000,
1410 | 0b01001000,
1411 | 0b10010000,
1412 | 0b00111000,
1413 | 0b00000000,
1414 | // 0xAC (1/4)
1415 | 0b01000000,
1416 | 0b01001000,
1417 | 0b01010000,
1418 | 0b00101000,
1419 | 0b01011000,
1420 | 0b10111000,
1421 | 0b00001000,
1422 | 0b00000000,
1423 | // 0xAD (invert !)
1424 | 0b00100000,
1425 | 0b00000000,
1426 | 0b00100000,
1427 | 0b00100000,
1428 | 0b00100000,
1429 | 0b00100000,
1430 | 0b00100000,
1431 | 0b00000000,
1432 | // 0xAE (arrow left)
1433 | 0b00000000,
1434 | 0b00101000,
1435 | 0b01010000,
1436 | 0b10100000,
1437 | 0b01010000,
1438 | 0b00101000,
1439 | 0b00000000,
1440 | 0b00000000,
1441 | // 0xAF (arrow right)
1442 | 0b00000000,
1443 | 0b10100000,
1444 | 0b01010000,
1445 | 0b00101000,
1446 | 0b01010000,
1447 | 0b10100000,
1448 | 0b00000000,
1449 | 0b00000000,
1450 | // 0xB0 (shadow 0)
1451 | 0b10010010,
1452 | 0b00000000,
1453 | 0b01001001,
1454 | 0b00000000,
1455 | 0b00100100,
1456 | 0b00000000,
1457 | 0b10010010,
1458 | 0b00000000,
1459 | // 0xB1(shadow 1)
1460 | 0b10101010,
1461 | 0b01010101,
1462 | 0b10101010,
1463 | 0b01010101,
1464 | 0b10101010,
1465 | 0b01010101,
1466 | 0b10101010,
1467 | 0b01010101,
1468 | // 0xB2(shadow 2)
1469 | 0b01101101,
1470 | 0b11111111,
1471 | 0b10110110,
1472 | 0b11111111,
1473 | 0b11011011,
1474 | 0b11111111,
1475 | 0b01101101,
1476 | 0b11111111,
1477 | // 0xB3 (left vertical line)
1478 | 0b00010000,
1479 | 0b00010000,
1480 | 0b00010000,
1481 | 0b00010000,
1482 | 0b00010000,
1483 | 0b00010000,
1484 | 0b00010000,
1485 | 0b00010000,
1486 | // 0xB4( box right tee )
1487 | 0b00010000,
1488 | 0b00010000,
1489 | 0b00010000,
1490 | 0b11110000,
1491 | 0b00010000,
1492 | 0b00010000,
1493 | 0b00010000,
1494 | 0b00010000,
1495 | // 0xB5( box right tee double line)
1496 | 0b00010000,
1497 | 0b00010000,
1498 | 0b00010000,
1499 | 0b11110000,
1500 | 0b11110000,
1501 | 0b00010000,
1502 | 0b00010000,
1503 | 0b00010000,
1504 | // 0xB6( box right tee vertical double line)
1505 | 0b00011000,
1506 | 0b00011000,
1507 | 0b00011000,
1508 | 0b11111000,
1509 | 0b00011000,
1510 | 0b00011000,
1511 | 0b00011000,
1512 | 0b00011000,
1513 | // 0xB7( box upper right corner vertical double line )
1514 | 0b00000000,
1515 | 0b00000000,
1516 | 0b00000000,
1517 | 0b11111000,
1518 | 0b00011000,
1519 | 0b00011000,
1520 | 0b00011000,
1521 | 0b00011000,
1522 | // 0xB8( box upper right corner double line )
1523 | 0b00000000,
1524 | 0b00000000,
1525 | 0b00000000,
1526 | 0b11110000,
1527 | 0b11110000,
1528 | 0b00010000,
1529 | 0b00010000,
1530 | 0b00010000,
1531 | // 0xB9( box right tee all double line)
1532 | 0b00011000,
1533 | 0b00011000,
1534 | 0b00011000,
1535 | 0b11111000,
1536 | 0b11111000,
1537 | 0b00011000,
1538 | 0b00011000,
1539 | 0b00011000,
1540 | // 0xBA (verticla double line)
1541 | 0b00011000,
1542 | 0b00011000,
1543 | 0b00011000,
1544 | 0b00011000,
1545 | 0b00011000,
1546 | 0b00011000,
1547 | 0b00011000,
1548 | 0b00011000,
1549 | // 0xBB( box upper right corner all double line )
1550 | 0b00000000,
1551 | 0b00000000,
1552 | 0b00000000,
1553 | 0b11111000,
1554 | 0b11111000,
1555 | 0b00011000,
1556 | 0b00011000,
1557 | 0b00011000,
1558 | // 0xBC( box lower right corner all double line )
1559 | 0b00011000,
1560 | 0b00011000,
1561 | 0b00011000,
1562 | 0b11111000,
1563 | 0b11111000,
1564 | 0b00000000,
1565 | 0b00000000,
1566 | 0b00000000,
1567 | // 0xBD( box lower right corner vertical double line )
1568 | 0b00011000,
1569 | 0b00011000,
1570 | 0b00011000,
1571 | 0b11111000,
1572 | 0b00000000,
1573 | 0b00000000,
1574 | 0b00000000,
1575 | 0b00000000,
1576 | // 0xBE( box lower right corner double line )
1577 | 0b00010000,
1578 | 0b00010000,
1579 | 0b00010000,
1580 | 0b11110000,
1581 | 0b11110000,
1582 | 0b00000000,
1583 | 0b00000000,
1584 | 0b00000000,
1585 | // 0xBF( box upper right corner )
1586 | 0b00000000,
1587 | 0b00000000,
1588 | 0b00000000,
1589 | 0b11110000,
1590 | 0b00010000,
1591 | 0b00010000,
1592 | 0b00010000,
1593 | 0b00010000,
1594 | // 0xC0( box lower left corner )
1595 | 0b00010000,
1596 | 0b00010000,
1597 | 0b00010000,
1598 | 0b00011111,
1599 | 0b00000000,
1600 | 0b00000000,
1601 | 0b00000000,
1602 | 0b00000000,
1603 | // 0xC1( box bottom tee )
1604 | 0b00010000,
1605 | 0b00010000,
1606 | 0b00010000,
1607 | 0b11111111,
1608 | 0b00000000,
1609 | 0b00000000,
1610 | 0b00000000,
1611 | 0b00000000,
1612 | // 0xC2( box top tee )
1613 | 0b00000000,
1614 | 0b00000000,
1615 | 0b00000000,
1616 | 0b11111111,
1617 | 0b00010000,
1618 | 0b00010000,
1619 | 0b00010000,
1620 | 0b00010000,
1621 | // 0xC3( box left tee )
1622 | 0b00010000,
1623 | 0b00010000,
1624 | 0b00010000,
1625 | 0b00011111,
1626 | 0b00010000,
1627 | 0b00010000,
1628 | 0b00010000,
1629 | 0b00010000,
1630 | // 0xC4 horizontal line
1631 | 0b00000000,
1632 | 0b00000000,
1633 | 0b00000000,
1634 | 0b11111111,
1635 | 0b00000000,
1636 | 0b00000000,
1637 | 0b00000000,
1638 | 0b00000000,
1639 | // 0xC5( box crossing lines )
1640 | 0b00010000,
1641 | 0b00010000,
1642 | 0b00010000,
1643 | 0b11111111,
1644 | 0b00010000,
1645 | 0b00010000,
1646 | 0b00010000,
1647 | 0b00010000,
1648 | // 0xC6 ( box left tee double line )
1649 | 0b00010000,
1650 | 0b00010000,
1651 | 0b00010000,
1652 | 0b00011111,
1653 | 0b00011111,
1654 | 0b00010000,
1655 | 0b00010000,
1656 | 0b00010000,
1657 | // 0xC7( box left tee vertical double line )
1658 | 0b00011000,
1659 | 0b00011000,
1660 | 0b00011000,
1661 | 0b00011111,
1662 | 0b00011000,
1663 | 0b00011000,
1664 | 0b00011000,
1665 | 0b00011000,
1666 | // 0xC8( box lower left corner all double line )
1667 | 0b00011000,
1668 | 0b00011000,
1669 | 0b00011000,
1670 | 0b00011111,
1671 | 0b00011111,
1672 | 0b00000000,
1673 | 0b00000000,
1674 | 0b00000000,
1675 | // 0xC9( box upper left corner all double line )
1676 | 0b00000000,
1677 | 0b00000000,
1678 | 0b00000000,
1679 | 0b00011111,
1680 | 0b00011111,
1681 | 0b00011000,
1682 | 0b00011000,
1683 | 0b00011000,
1684 | // 0xCA( box bottom tee all double line )
1685 | 0b00011000,
1686 | 0b00011000,
1687 | 0b00011000,
1688 | 0b11111111,
1689 | 0b11111111,
1690 | 0b00000000,
1691 | 0b00000000,
1692 | 0b00000000,
1693 | // 0xCB( box top tee all double line )
1694 | 0b00000000,
1695 | 0b00000000,
1696 | 0b00000000,
1697 | 0b11111111,
1698 | 0b11111111,
1699 | 0b00011000,
1700 | 0b00011000,
1701 | 0b00011000,
1702 | // 0xCC( box left tee )
1703 | 0b00011000,
1704 | 0b00011000,
1705 | 0b00011000,
1706 | 0b00011111,
1707 | 0b00011111,
1708 | 0b00011000,
1709 | 0b00011000,
1710 | 0b00011000,
1711 | // 0xCD horizontal line double line
1712 | 0b00000000,
1713 | 0b00000000,
1714 | 0b00000000,
1715 | 0b11111111,
1716 | 0b11111111,
1717 | 0b00000000,
1718 | 0b00000000,
1719 | 0b00000000,
1720 | // 0xCE( box crossing lines all double line )
1721 | 0b00011000,
1722 | 0b00011000,
1723 | 0b00011000,
1724 | 0b11111111,
1725 | 0b11111111,
1726 | 0b00011000,
1727 | 0b00011000,
1728 | 0b00011000,
1729 | // 0xCF( box bottom tee double line )
1730 | 0b00010000,
1731 | 0b00010000,
1732 | 0b00010000,
1733 | 0b11111111,
1734 | 0b11111111,
1735 | 0b00000000,
1736 | 0b00000000,
1737 | 0b00000000,
1738 | // 0xD0( box bottom tee vertical double line )
1739 | 0b00011000,
1740 | 0b00011000,
1741 | 0b00011000,
1742 | 0b11111111,
1743 | 0b00000000,
1744 | 0b00000000,
1745 | 0b00000000,
1746 | 0b00000000,
1747 | // 0xD1( box top tee double line )
1748 | 0b00000000,
1749 | 0b00000000,
1750 | 0b00000000,
1751 | 0b11111111,
1752 | 0b11111111,
1753 | 0b00010000,
1754 | 0b00010000,
1755 | 0b00010000,
1756 | // 0xD2( box top tee vertical double line )
1757 | 0b00000000,
1758 | 0b00000000,
1759 | 0b00000000,
1760 | 0b11111111,
1761 | 0b00011000,
1762 | 0b00011000,
1763 | 0b00011000,
1764 | 0b00011000,
1765 | // 0xD3( box lower left corner vertical double line )
1766 | 0b00011000,
1767 | 0b00011000,
1768 | 0b00011000,
1769 | 0b00011111,
1770 | 0b00000000,
1771 | 0b00000000,
1772 | 0b00000000,
1773 | 0b00000000,
1774 | // 0xD4( box lower left corner double line )
1775 | 0b00010000,
1776 | 0b00010000,
1777 | 0b00010000,
1778 | 0b00011111,
1779 | 0b00011111,
1780 | 0b00000000,
1781 | 0b00000000,
1782 | 0b00000000,
1783 | // 0xD5( box upper left corner double line )
1784 | 0b00000000,
1785 | 0b00000000,
1786 | 0b00000000,
1787 | 0b00011111,
1788 | 0b00011111,
1789 | 0b00010000,
1790 | 0b00010000,
1791 | 0b00010000,
1792 | // 0xD6( box upper left corner vertical double line )
1793 | 0b00000000,
1794 | 0b00000000,
1795 | 0b00000000,
1796 | 0b00011111,
1797 | 0b00011000,
1798 | 0b00011000,
1799 | 0b00011000,
1800 | 0b00011000,
1801 | // 0xD7( box crossing lines double line )
1802 | 0b00011000,
1803 | 0b00011000,
1804 | 0b00011000,
1805 | 0b11111111,
1806 | 0b00011000,
1807 | 0b00011000,
1808 | 0b00011000,
1809 | 0b00011000,
1810 | // 0xD8( box crossing lines double line )
1811 | 0b00010000,
1812 | 0b00010000,
1813 | 0b00010000,
1814 | 0b11111111,
1815 | 0b11111111,
1816 | 0b00010000,
1817 | 0b00010000,
1818 | 0b00010000,
1819 | // 0xD9( box lower right corner )
1820 | 0b00010000,
1821 | 0b00010000,
1822 | 0b00010000,
1823 | 0b11110000,
1824 | 0b00000000,
1825 | 0b00000000,
1826 | 0b00000000,
1827 | 0b00000000,
1828 | // 0xDA( box upper left corner )
1829 | 0b00000000,
1830 | 0b00000000,
1831 | 0b00000000,
1832 | 0b00011111,
1833 | 0b00010000,
1834 | 0b00010000,
1835 | 0b00010000,
1836 | 0b00010000,
1837 | // 0xDB (full)
1838 | 0b11111111,
1839 | 0b11111111,
1840 | 0b11111111,
1841 | 0b11111111,
1842 | 0b11111111,
1843 | 0b11111111,
1844 | 0b11111111,
1845 | 0b11111111,
1846 | // 0xDC (half)
1847 | 0b00000000,
1848 | 0b00000000,
1849 | 0b00000000,
1850 | 0b00000000,
1851 | 0b11111111,
1852 | 0b11111111,
1853 | 0b11111111,
1854 | 0b11111111,
1855 | // 0xDD (left)
1856 | 0b11100000,
1857 | 0b11100000,
1858 | 0b11100000,
1859 | 0b11100000,
1860 | 0b11100000,
1861 | 0b11100000,
1862 | 0b11100000,
1863 | 0b11100000,
1864 | // 0xDE (right)
1865 | 0b00011100,
1866 | 0b00011100,
1867 | 0b00011100,
1868 | 0b00011100,
1869 | 0b00011100,
1870 | 0b00011100,
1871 | 0b00011100,
1872 | 0b00011100,
1873 | // 0xDF (up)
1874 | 0b11111100,
1875 | 0b11111100,
1876 | 0b11111100,
1877 | 0b11111100,
1878 | 0b00000000,
1879 | 0b00000000,
1880 | 0b00000000,
1881 | 0b00000000,
1882 | // 0xE0 (alpha)
1883 | 0b00000000,
1884 | 0b00000000,
1885 | 0b01101000,
1886 | 0b10011000,
1887 | 0b10010000,
1888 | 0b10010000,
1889 | 0b01101000,
1890 | 0b00000000,
1891 | // 0xE1 (beta)
1892 | 0b01110000,
1893 | 0b10001000,
1894 | 0b10001000,
1895 | 0b11110000,
1896 | 0b10001000,
1897 | 0b10001000,
1898 | 0b11110000,
1899 | 0b10000000,
1900 | // 0xE2 (Gamma)
1901 | 0b11111000,
1902 | 0b10000000,
1903 | 0b10000000,
1904 | 0b10000000,
1905 | 0b10000000,
1906 | 0b10000000,
1907 | 0b10000000,
1908 | 0b00000000,
1909 | // 0xE3 (Pi)
1910 | 0b11111000,
1911 | 0b01010000,
1912 | 0b01010000,
1913 | 0b01010000,
1914 | 0b01010000,
1915 | 0b01010000,
1916 | 0b01010000,
1917 | 0b00000000,
1918 | // 0xE4 (Sigma)
1919 | 0b11111000,
1920 | 0b01000000,
1921 | 0b00100000,
1922 | 0b00010000,
1923 | 0b00100000,
1924 | 0b01000000,
1925 | 0b11111000,
1926 | 0b00000000,
1927 | // 0xE5 (sigma)
1928 | 0b00000000,
1929 | 0b00011000,
1930 | 0b01100000,
1931 | 0b10011000,
1932 | 0b10001000,
1933 | 0b10001000,
1934 | 0b01110000,
1935 | 0b00000000,
1936 | // 0xE6 (mu)
1937 | 0b00000000,
1938 | 0b00000000,
1939 | 0b10001000,
1940 | 0b10001000,
1941 | 0b10001000,
1942 | 0b10011000,
1943 | 0b11101000,
1944 | 0b10000000,
1945 | // 0xE7 (tau)
1946 | 0b00000000,
1947 | 0b00000000,
1948 | 0b00000000,
1949 | 0b11111000,
1950 | 0b00100000,
1951 | 0b00100000,
1952 | 0b00100000,
1953 | 0b00000000,
1954 | // 0xE8(Phi)
1955 | 0b00100000,
1956 | 0b01110000,
1957 | 0b10101000,
1958 | 0b10101000,
1959 | 0b10101000,
1960 | 0b01110000,
1961 | 0b00100000,
1962 | 0b00000000,
1963 | // 0xE9 (Theta)
1964 | 0b01110000,
1965 | 0b10001000,
1966 | 0b11011000,
1967 | 0b11111000,
1968 | 0b11011000,
1969 | 0b10001000,
1970 | 0b01110000,
1971 | 0b00000000,
1972 | // 0xEA (Omega)
1973 | 0b01110000,
1974 | 0b10001000,
1975 | 0b10001000,
1976 | 0b10001000,
1977 | 0b10001000,
1978 | 0b01010000,
1979 | 0b11011000,
1980 | 0b00000000,
1981 | // 0xEB (delta)
1982 | 0b01111000,
1983 | 0b10000000,
1984 | 0b01110000,
1985 | 0b10001000,
1986 | 0b10001000,
1987 | 0b10001000,
1988 | 0b01110000,
1989 | 0b00000000,
1990 | // 0xEC (infinity)
1991 | 0b00000000,
1992 | 0b00000000,
1993 | 0b01010000,
1994 | 0b10101000,
1995 | 0b10101000,
1996 | 0b01010000,
1997 | 0b00000000,
1998 | 0b00000000,
1999 | // 0xED (phi)
2000 | 0b00000000,
2001 | 0b01011000,
2002 | 0b10101000,
2003 | 0b10101000,
2004 | 0b01110000,
2005 | 0b00100000,
2006 | 0b00100000,
2007 | 0b00000000,
2008 | // 0xEE (epsilon)
2009 | 0b00000000,
2010 | 0b00000000,
2011 | 0b01110000,
2012 | 0b10000000,
2013 | 0b01110000,
2014 | 0b10000000,
2015 | 0b01110000,
2016 | 0b00000000,
2017 | // 0xEF (and)
2018 | 0b00100000,
2019 | 0b01010000,
2020 | 0b10001000,
2021 | 0b10001000,
2022 | 0b10001000,
2023 | 0b10001000,
2024 | 0b10001000,
2025 | 0b00000000,
2026 | // 0xF0 (three line)
2027 | 0b00000000,
2028 | 0b11111000,
2029 | 0b00000000,
2030 | 0b11111000,
2031 | 0b00000000,
2032 | 0b11111000,
2033 | 0b00000000,
2034 | 0b00000000,
2035 | // 0xF1( plus-minus )
2036 | 0b00100000,
2037 | 0b00100000,
2038 | 0b11111000,
2039 | 0b00100000,
2040 | 0b00100000,
2041 | 0b00000000,
2042 | 0b11111000,
2043 | 0b00000000,
2044 | // 0xF2( greater than or equal )
2045 | 0b00000000,
2046 | 0b01000000,
2047 | 0b00110000,
2048 | 0b00001000,
2049 | 0b00110000,
2050 | 0b01000000,
2051 | 0b11111000,
2052 | 0b00000000,
2053 | // 0xF3( less than or equal )
2054 | 0b00000000,
2055 | 0b00010000,
2056 | 0b01100000,
2057 | 0b10000000,
2058 | 0b01100000,
2059 | 0b00010000,
2060 | 0b11111000,
2061 | 0b00000000,
2062 | // 0xF4
2063 | 0b00011000,
2064 | 0b00100000,
2065 | 0b00100000,
2066 | 0b00100000,
2067 | 0b00100000,
2068 | 0b00100000,
2069 | 0b0010000,
2070 | 0b00100000,
2071 | // 0xF5
2072 | 0b00100000,
2073 | 0b00100000,
2074 | 0b00100000,
2075 | 0b00100000,
2076 | 0b00100000,
2077 | 0b00100000,
2078 | 0b00100000,
2079 | 0b11000000,
2080 | // 0xF6
2081 | 0b00000000,
2082 | 0b00110000,
2083 | 0b00000000,
2084 | 0b11111000,
2085 | 0b00000000,
2086 | 0b01100000,
2087 | 0b00000000,
2088 | 0b00000000,
2089 | // 0xF7
2090 | 0b00000000,
2091 | 0b00110000,
2092 | 0b11001000,
2093 | 0b00000000,
2094 | 0b00110000,
2095 | 0b11001000,
2096 | 0b00000000,
2097 | 0b00000000,
2098 | // 0xF8 (degree)
2099 | 0b00110000,
2100 | 0b01001000,
2101 | 0b01001000,
2102 | 0b00110000,
2103 | 0b00000000,
2104 | 0b00000000,
2105 | 0b00000000,
2106 | 0b00000000,
2107 | // 0xF9 (dot)
2108 | 0b00000000,
2109 | 0b00000000,
2110 | 0b00000000,
2111 | 0b00010000,
2112 | 0b00000000,
2113 | 0b00000000,
2114 | 0b00000000,
2115 | 0b00000000,
2116 | // 0xFA (dot)
2117 | 0b00000000,
2118 | 0b00000000,
2119 | 0b00000000,
2120 | 0b00010000,
2121 | 0b00000000,
2122 | 0b00000000,
2123 | 0b00000000,
2124 | 0b00000000,
2125 | // 0xFB (r)
2126 | 0b00001000,
2127 | 0b00001000,
2128 | 0b00010000,
2129 | 0b00010000,
2130 | 0b00100000,
2131 | 0b10100000,
2132 | 0b01000000,
2133 | 0b00000000,
2134 | // 0xFC (^n)
2135 | 0b11100000,
2136 | 0b10010000,
2137 | 0b10010000,
2138 | 0b10010000,
2139 | 0b00000000,
2140 | 0b00000000,
2141 | 0b00000000,
2142 | 0b00000000,
2143 | // 0xFD (^2)
2144 | 0b01100000,
2145 | 0b00010000,
2146 | 0b01000000,
2147 | 0b11110000,
2148 | 0b00000000,
2149 | 0b00000000,
2150 | 0b00000000,
2151 | 0b00000000,
2152 | // 0xFE (small squre)
2153 | 0b00000000,
2154 | 0b00000000,
2155 | 0b01110000,
2156 | 0b01110000,
2157 | 0b01110000,
2158 | 0b00000000,
2159 | 0b00000000,
2160 | 0b00000000,
2161 | // 0xFF
2162 | 0b00000000,
2163 | 0b00000000,
2164 | 0b00000000,
2165 | 0b00000000,
2166 | 0b00000000,
2167 | 0b00000000,
2168 | 0b00000000,
2169 | 0b00000000,
2170 | };
2171 |
2172 | #endif
2173 |
--------------------------------------------------------------------------------
/vtterminal/vtterminal.c:
--------------------------------------------------------------------------------
1 | //A modified version of vt100 emulator from https://github.com/ht-deko/vt100_stm32
2 | #include "font6x8.h"
3 | #include "vtterminal.h"
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include "py/runtime.h"
10 |
11 | #include "py/mphal.h"
12 | #include "py/gc.h"
13 | #include "py/misc.h"
14 |
15 |
16 | #include "pico/stdlib.h"
17 | #include "hardware/timer.h"
18 |
19 |
20 | uint8_t* fontTop;
21 |
22 | uint16_t M_TOP = 0;
23 | uint16_t M_BOTTOM = SC_H - 1;
24 |
25 | #define SCSIZE (SC_W * SC_H)
26 | #define SP_W (SC_W * CH_W)
27 | #define SP_H (SC_H * CH_H)
28 | #define MAX_CH_X (CH_W - 1)
29 | #define MAX_CH_Y (CH_H - 1)
30 | #define MAX_SC_X (SC_W - 1)
31 | #define MAX_SC_Y (SC_H - 1)
32 | #define MAX_SP_X (SP_W - 1)
33 | #define MAX_SP_Y (SP_H - 1)
34 |
35 | typedef struct {
36 | uint8_t Bold : 1; // 1
37 | uint8_t Faint : 1; // 2
38 | uint8_t Italic : 1; // 3
39 | uint8_t Underline : 1; // 4
40 | uint8_t Blink : 1; // 5 (Slow Blink)
41 | uint8_t RapidBlink : 1; // 6
42 | uint8_t Reverse : 1; // 7
43 | uint8_t Conceal : 1; // 8
44 | }TATTR ;
45 |
46 | typedef union {
47 | uint8_t value;
48 | TATTR Bits;
49 | }ATTR ;
50 |
51 |
52 |
53 |
54 |
55 | typedef struct {
56 | uint8_t Foreground : 4;
57 | uint8_t Background : 4;
58 | }TCOLOR ;
59 | typedef union {
60 | uint8_t value;
61 | TCOLOR Color;
62 | }COLOR ;
63 |
64 |
65 | typedef struct {
66 | unsigned int g0g1 : 1;
67 | unsigned int Reserved4 : 1;
68 | unsigned int Reserved12 : 1;
69 | unsigned int CrLf : 1;
70 | unsigned int Reserved33 : 1;
71 | unsigned int Reserved34 : 1;
72 | unsigned int Reverse : 2;
73 | } TMODE;
74 |
75 |
76 | typedef union {
77 | uint8_t value;
78 | TMODE Flgs;
79 | } MODE ;
80 |
81 | typedef struct {
82 | unsigned int Reserved1 : 1; // 1 DECCKM (Cursor Keys Mode)
83 | unsigned int Reserved2 : 1; // 2 DECANM (ANSI/VT52 Mode)
84 | unsigned int Reserved3 : 1; // 3 DECCOLM (Column Mode)
85 | unsigned int Reserved4 : 1; // 4 DECSCLM (Scrolling Mode)
86 | unsigned int ScreenReverse : 1; // 5 DECSCNM (Screen Mode)
87 | unsigned int Reserved6 : 1; // 6 DECOM (Origin Mode)
88 | unsigned int WrapLine : 1; // 7 DECAWM (Autowrap Mode)
89 | unsigned int Reserved8 : 1; // 8 DECARM (Auto Repeat Mode)
90 | unsigned int Reserved9 : 1; // 9 DECINLM (Interlace Mode)
91 | unsigned int InsertMode:1; // 10 DECIM (Insert Mode)
92 | unsigned int Reverse : 6;
93 | }TMODE_EX ;
94 |
95 | typedef union {
96 | uint16_t value;
97 | TMODE_EX Flgs;
98 | }MODE_EX ;
99 |
100 | char outputBuf[30]={0};
101 | int outputLen = 0;
102 | uint8_t screen[SCSIZE];
103 | uint8_t attrib[SCSIZE];
104 | uint8_t colors[SCSIZE];
105 | uint8_t tabs[SC_W];
106 | uint8_t *fb;
107 | const uint8_t *currentTextTable;
108 | #define NONE 0
109 | #define ES 1
110 | #define CSI 2
111 | #define CSI2 3
112 | #define LSC 4
113 | #define G0S 5
114 | #define G1S 6
115 |
116 | static const uint8_t defaultMode = 0b00001000;
117 | static const uint16_t defaultModeEx = 0b0000000001000000;
118 | static const ATTR defaultAttr = {0b00000000};
119 | static const COLOR defaultColor = {(clBlack << 4) | clWhite}; // back, fore
120 | uint8_t escMode = NONE; // esc mode indicator
121 | bool isShowCursor = false; // is the cursor shown in last call?
122 | bool canShowCursor = true; // can the cursor be shown?
123 | bool hasParam = false; // [ has parameters
124 | bool isDECPrivateMode = false; // DEC Private Mode ( [ ?)
125 | MODE mode;
126 | //mode.value = defaultMode;
127 | MODE_EX mode_ex;
128 | //mode_ex.value = defaultModeEx;
129 |
130 | int16_t p_XP = 0;
131 | int16_t p_YP = 0;
132 |
133 | int16_t XP = 0;
134 | int16_t YP = 0;
135 | ATTR cAttr ;
136 | COLOR cColor ;
137 |
138 | int16_t b_XP = 0;
139 | int16_t b_YP = 0;
140 | ATTR bAttr ;
141 | COLOR bColor ;
142 |
143 | int16_t nVals = 0;
144 | int16_t vals[10] = {0};
145 | static repeating_timer_t cursor_timer;
146 |
147 |
148 | bool dispCursor(repeating_timer_t *rt) ;
149 |
150 |
151 |
152 | //static void scroll_framebuffer(uint8_t *fb, int scroll_y1, int scroll_y2, int n, uint8_t bg_color);
153 | static void fill_rect_4bpp(uint8_t *fb, int x, int y, int w, int h, uint8_t color);
154 | static void drawTxt6x8(uint8_t *fb,uint8_t c,int x0,int y0, uint8_t color);
155 | static void setpixel(uint8_t *fb,int32_t x, int32_t y,uint8_t color);
156 | static void sc_updateChar(uint16_t x, uint16_t y);
157 | static void drawCursor(uint16_t x, uint16_t y);
158 | static void sc_updateLine(uint16_t ln);
159 | static void setCursorToHome(void);
160 | static void initCursorAndAttribute(void);
161 | static void scroll(void);
162 | static void clearParams(uint8_t m);
163 | static void saveCursor(void);
164 | static void restoreCursor(void);
165 | static void keypadApplicationMode(void);
166 | static void keypadNumericMode(void);
167 | static void vindex(int16_t v);
168 | static void nextLine(void) ;
169 | static void horizontalTabulationSet(void);
170 | static void reverseIndex(int16_t v);
171 | static void identify(void);
172 | static void resetToInitialState(void);
173 | //static void cursorUp(int16_t v);
174 | static void cursorDown(int16_t v);
175 | static void cursorPosition(uint8_t y, uint8_t x);
176 | static void refreshScreen(void);
177 | static void eraseInDisplay(uint8_t m);
178 | static void eraseInLine(uint8_t m);
179 | static void insertLine(uint8_t v);
180 | static void deleteLine(uint8_t v) ;
181 | static void cursorPositionReport(uint16_t y, uint16_t x);
182 | static void deviceAttributes(uint8_t m);
183 | static void tabulationClear(uint8_t m);
184 | static void lineMode(bool m);
185 | static void screenMode(bool m);
186 | static void autoWrapMode(bool m);
187 | static void setMode(int16_t *vals, int16_t nVals);
188 | static void decSetMode(int16_t *vals, int16_t nVals);
189 | static void resetMode(int16_t *vals, int16_t nVals);
190 | static void decResetMode(int16_t *vals, int16_t nVals);
191 | static void selectGraphicRendition(int16_t *vals, int16_t nVals);
192 | static void deviceStatusReport(uint8_t m);
193 | static void loadLEDs(uint8_t m);
194 | static void setTopAndBottomMargins(int16_t s, int16_t e);
195 | static void invokeConfidenceTests(uint8_t m);
196 | static void doubleHeightLine_TopHalf(void);
197 | static void doubleHeightLine_BotomHalf(void);
198 | static void singleWidthLine(void);
199 | static void doubleWidthLine(void);
200 | static void screenAlignmentDisplay(void);
201 | static void setG0charset(char c);
202 | static void setG1charset(char c);
203 | static void unknownSequence(uint8_t m, char c) ;
204 | static void cursorForward(int16_t v);
205 | static void cursorBackward(int16_t v);
206 |
207 | static void setpixel(uint8_t *fb,int32_t x, int32_t y,uint8_t color){
208 | uint8_t *pixel = &((uint8_t *)fb)[(x + (SC_PIXEL_WIDTH*y))>>1];
209 |
210 | if (x&0x01) {
211 | *pixel = ((uint8_t)color & 0x0f) | (*pixel & 0xf0);
212 | } else {
213 | *pixel = ((uint8_t)color << 4) | (*pixel & 0x0f);
214 | }
215 | }
216 | static void sc_updateChar(uint16_t x, uint16_t y) {
217 | uint16_t idx = SC_W * y + x;
218 | uint8_t c = screen[idx];
219 | ATTR a;
220 | COLOR l;
221 | a.value = attrib[idx];
222 | l.value = colors[idx];
223 | uint8_t fore = l.Color.Foreground | (a.Bits.Blink << 3);
224 | uint8_t back = l.Color.Background | (a.Bits.Blink << 3);
225 | if (a.Bits.Reverse){
226 | uint8_t temp = fore; fore = back; back = temp;
227 | }
228 | if (mode_ex.Flgs.ScreenReverse){
229 | uint8_t temp = fore; fore = back; back = temp;
230 | }
231 | uint16_t xx = x * CH_W;
232 | uint16_t yy = y * CH_H;
233 | fill_rect_4bpp(fb, xx, yy, CH_W, CH_H, back);
234 | drawTxt6x8(fb,c,xx,yy, fore);
235 | if (a.Bits.Bold){
236 | drawTxt6x8(fb,c,xx+1,yy, fore);
237 | }
238 |
239 | }
240 |
241 |
242 |
243 |
244 | static void drawCursor(uint16_t x, uint16_t y) {
245 | uint16_t xx = x * CH_W;
246 | uint16_t yy = y * CH_H;
247 | fill_rect_4bpp(fb, xx, yy, CH_W, CH_H, clWhite);
248 | }
249 |
250 | bool dispCursor(repeating_timer_t *rt) {
251 | if (escMode != NONE)
252 | return true;
253 | //sc_updateChar(p_XP, p_YP);
254 | if (canShowCursor){
255 |
256 | isShowCursor = !isShowCursor;
257 | if (isShowCursor){
258 | drawCursor(XP, YP);
259 | }else{
260 | sc_updateChar(p_XP, p_YP);
261 | }
262 | p_XP = XP;
263 | p_YP = YP;
264 | }
265 | return true;
266 | }
267 |
268 | static void sc_updateLine(uint16_t ln) {
269 | for (uint32_t i=0;i M_BOTTOM);
294 |
295 | if (need_scroll) {
296 | YP = M_BOTTOM;
297 | int lines_to_scroll = M_BOTTOM - M_TOP;
298 | if (lines_to_scroll > 0) {
299 | size_t copy_bytes = lines_to_scroll * SC_W;
300 | int dst = M_TOP * SC_W;
301 | int src = (M_TOP + 1) * SC_W;
302 | memmove(&screen[dst], &screen[src], copy_bytes);
303 | memmove(&attrib[dst], &attrib[src], copy_bytes);
304 | memmove(&colors[dst], &colors[src], copy_bytes);
305 | }
306 | int bottom_idx = M_BOTTOM * SC_W;
307 |
308 | memset(&screen[bottom_idx], 0, SC_W);
309 | memset(&attrib[bottom_idx], defaultAttr.value, SC_W);
310 | memset(&colors[bottom_idx], defaultColor.value, SC_W);
311 |
312 | for (int y = M_TOP; y <= M_BOTTOM; y++) {
313 | if (y >= 0 && y < SC_H) {
314 | sc_updateLine(y);
315 | }
316 | }
317 | } else {
318 | YP = nextYP;
319 | }
320 | }
321 |
322 | static void scroll(void) {
323 | if (mode.Flgs.CrLf) XP = 0;
324 | YP++;
325 |
326 | if (YP > M_BOTTOM) {
327 | int lines_to_scroll = M_BOTTOM - M_TOP;
328 |
329 | if (lines_to_scroll > 0) {
330 | size_t copy_bytes = lines_to_scroll * SC_W;
331 | int dst = M_TOP * SC_W;
332 | int src = (M_TOP + 1) * SC_W;
333 |
334 | memmove(&screen[dst], &screen[src], copy_bytes);
335 | memmove(&attrib[dst], &attrib[src], copy_bytes);
336 | memmove(&colors[dst], &colors[src], copy_bytes);
337 | }
338 |
339 |
340 | int bottom_idx = M_BOTTOM * SC_W;
341 | memset(&screen[bottom_idx], 0, SC_W);
342 | memset(&attrib[bottom_idx], defaultAttr.value, SC_W);
343 | memset(&colors[bottom_idx], defaultColor.value, SC_W);
344 |
345 | YP = M_BOTTOM;
346 |
347 | for (uint8_t y = M_TOP; y <= M_BOTTOM; y++)
348 | sc_updateLine(y);
349 | }
350 | }*/
351 | /*
352 | static void scroll(void) {
353 | if (mode.Flgs.CrLf) XP = 0;
354 | YP++;
355 | if (YP > M_BOTTOM) {
356 | uint16_t n = SCSIZE - SC_W - ((M_TOP + MAX_SC_Y - M_BOTTOM) * SC_W);
357 | uint16_t idx = SC_W * M_BOTTOM;
358 | uint16_t idx2;
359 | uint16_t idx3 = M_TOP * SC_W;
360 | memmove(&screen[idx3], &screen[idx3 + SC_W], n);
361 | memmove(&attrib[idx3], &attrib[idx3 + SC_W], n);
362 | memmove(&colors[idx3], &colors[idx3 + SC_W], n);
363 | for (uint8_t x = 0; x < SC_W; x++) {
364 | idx2 = idx + x;
365 | screen[idx2] = 0;
366 | attrib[idx2] = defaultAttr.value;
367 | colors[idx2] = defaultColor.value;
368 | }
369 |
370 | YP = M_BOTTOM;
371 | }
372 | for (uint8_t y = 0; y M_BOTTOM) {
381 | uint16_t n = SCSIZE - SC_W - ((M_TOP + MAX_SC_Y - M_BOTTOM) * SC_W);
382 | uint16_t idx = SC_W * M_BOTTOM;
383 | uint16_t idx2;
384 | uint16_t idx3 = M_TOP * SC_W;
385 | memmove(&screen[idx3], &screen[idx3 + SC_W], n);
386 | memmove(&attrib[idx3], &attrib[idx3 + SC_W], n);
387 | memmove(&colors[idx3], &colors[idx3 + SC_W], n);
388 | for (uint8_t x = 0; x < SC_W; x++) {
389 | idx2 = idx + x;
390 | screen[idx2] = 0;
391 | attrib[idx2] = defaultAttr.value;
392 | colors[idx2] = defaultColor.value;
393 | }
394 | for (uint8_t y = M_TOP; y <= M_BOTTOM; y++)
395 | sc_updateLine(y);
396 | YP = M_BOTTOM;
397 | }
398 | }
399 |
400 |
401 | static void clearParams(uint8_t m) {
402 | escMode = m;
403 | isDECPrivateMode = false;
404 | nVals = 0;
405 | vals[0] = vals[1] = vals[2] = vals[3] = 0;
406 | hasParam = false;
407 | }
408 |
409 |
410 | static mp_obj_t vt_printChar(mp_obj_t value_obj) {
411 | int c = mp_obj_get_int(value_obj);
412 | // [ESC] キー
413 | if (c == 0x1b) {
414 | escMode = ES; // esc mode start
415 | return mp_const_none;
416 | }
417 | // エスケープシーケンス
418 | if (escMode == ES) {
419 | switch (c) {
420 | case '[':
421 | // Control Sequence Introducer (CSI)
422 | clearParams(CSI);
423 | break;
424 | case '#':
425 | // Line Size Command
426 | clearParams(LSC);
427 | break;
428 | case '(':
429 | // G0
430 | clearParams(G0S);
431 | break;
432 | case ')':
433 | // G1
434 | clearParams(G1S);
435 | break;
436 | default:
437 | // xxx:
438 | switch (c) {
439 | case '7':
440 | // DECSC (Save Cursor): save cursor position
441 | saveCursor();
442 | break;
443 | case '8':
444 | // DECRC (Restore Cursor):
445 | restoreCursor();
446 | break;
447 | case '=':
448 | // DECKPAM (Keypad Application Mode):
449 | keypadApplicationMode();
450 | break;
451 | case '>':
452 | // DECKPNM (Keypad Numeric Mode):
453 | keypadNumericMode();
454 | break;
455 | case 'D':
456 | // IND (Index): one line down
457 | vindex(1);
458 | break;
459 | case 'E':
460 | // NEL (Next Line):
461 | nextLine();
462 | break;
463 | case 'H':
464 | // HTS (Horizontal Tabulation Set):
465 | horizontalTabulationSet();
466 | break;
467 | case 'M':
468 | // RI (Reverse Index):
469 | reverseIndex(1);
470 | break;
471 | case 'Z':
472 | // DECID (Identify):
473 | identify();
474 | break;
475 | case 'c':
476 | // RIS (Reset To Initial State):
477 | resetToInitialState();
478 | break;
479 | default:
480 | // not decodeable
481 | unknownSequence(escMode, c);
482 | break;
483 | }
484 | clearParams(NONE);
485 | break;
486 | }
487 | return mp_const_none;
488 | }
489 |
490 | // "[" Control Sequence Introducer (CSI)
491 | int16_t v1 = 0;
492 | int16_t v2 = 0;
493 |
494 | if (escMode == CSI) {
495 | escMode = CSI2;
496 | isDECPrivateMode = (c == '?');
497 | if (isDECPrivateMode) return mp_const_none;
498 | }
499 |
500 | if (escMode == CSI2) {
501 | if (isdigit(c)) {
502 | // [パラメータ]
503 | vals[nVals] = vals[nVals] * 10 + (c - '0');
504 | hasParam = true;
505 | } else if (c == ';') {
506 | // [セパレータ]
507 | nVals++;
508 | hasParam = false;
509 | } else {
510 | if (hasParam) nVals++;
511 | switch (c) {
512 | case 'A':
513 | // CUU (Cursor Up):
514 | v1 = (nVals == 0) ? 1 : vals[0];
515 | reverseIndex(v1);
516 | break;
517 | case 'B':
518 | // CUD (Cursor Down):
519 | v1 = (nVals == 0) ? 1 : vals[0];
520 | cursorDown(v1);
521 | break;
522 | case 'C':
523 | // CUF (Cursor Forward):
524 | v1 = (nVals == 0) ? 1 : vals[0];
525 | cursorForward(v1);
526 | break;
527 | case 'D':
528 | // CUB (Cursor Backward):
529 | v1 = (nVals == 0) ? 1 : vals[0];
530 | cursorBackward(v1);
531 | break;
532 | case 'H':
533 | // CUP (Cursor Position):
534 | case 'f':
535 | // HVP (Horizontal and Vertical Position):
536 | v1 = (nVals == 0) ? 1 : vals[0];
537 | v2 = (nVals <= 1) ? 1 : vals[1];
538 | cursorPosition(v1, v2);
539 | break;
540 | case 'J':
541 | // ED (Erase In Display):
542 | v1 = (nVals == 0) ? 0 : vals[0];
543 | eraseInDisplay(v1);
544 | break;
545 | case 'K':
546 | // EL (Erase In Line)
547 | v1 = (nVals == 0) ? 0 : vals[0];
548 | eraseInLine(v1);
549 | break;
550 | case 'L':
551 | // IL (Insert Line):
552 | v1 = (nVals == 0) ? 1 : vals[0];
553 | insertLine(v1);
554 | break;
555 | case 'M':
556 | // DL (Delete Line):
557 | v1 = (nVals == 0) ? 1 : vals[0];
558 | deleteLine(v1);
559 | break;
560 | case 'c':
561 | // DA (Device Attributes):
562 | v1 = (nVals == 0) ? 0 : vals[0];
563 | deviceAttributes(v1);
564 | break;
565 | case 'g':
566 | // TBC (Tabulation Clear):
567 | v1 = (nVals == 0) ? 0 : vals[0];
568 | tabulationClear(v1);
569 | break;
570 | case 'h':
571 | if (isDECPrivateMode) {
572 | // DECSET (DEC Set Mode):
573 | decSetMode(vals, nVals);
574 | } else {
575 | // SM (Set Mode):
576 | setMode(vals, nVals);
577 | }
578 | break;
579 | case 'l':
580 | if (isDECPrivateMode) {
581 | // DECRST (DEC Reset Mode):
582 | decResetMode(vals, nVals);
583 | } else {
584 | // RM (Reset Mode):
585 | resetMode(vals, nVals);
586 | }
587 | break;
588 | case 'm':
589 | // SGR (Select Graphic Rendition):
590 | if (nVals == 0)
591 | nVals = 1; // vals[0] = 0
592 | selectGraphicRendition(vals, nVals);
593 | break;
594 | case 'n':
595 | // DSR (Device Status Report):
596 | v1 = (nVals == 0) ? 0 : vals[0];
597 | deviceStatusReport(v1);
598 | break;
599 | case 'q':
600 | // DECLL (Load LEDS):
601 | v1 = (nVals == 0) ? 0 : vals[0];
602 | loadLEDs(v1);
603 | break;
604 | case 'r':
605 | // DECSTBM (Set Top and Bottom Margins):
606 | v1 = (nVals == 0) ? 1 : vals[0];
607 | v2 = (nVals <= 1) ? SC_H : vals[1];
608 | setTopAndBottomMargins(v1, v2);
609 | break;
610 | case 'y':
611 | // DECTST (Invoke Confidence Test):
612 | if ((nVals > 1) && (vals[0] = 2))
613 | invokeConfidenceTests(vals[1]);
614 | break;
615 | default:
616 | // unknown command
617 | unknownSequence(escMode, c);
618 | break;
619 | }
620 | clearParams(NONE);
621 | }
622 | return mp_const_none;
623 | }else if (escMode == LSC) {
624 | switch (c) {
625 | case '3':
626 | // DECDHL (Double Height Line):
627 | doubleHeightLine_TopHalf();
628 | break;
629 | case '4':
630 | // DECDHL (Double Height Line):
631 | doubleHeightLine_BotomHalf();
632 | break;
633 | case '5':
634 | // DECSWL (Single-width Line):
635 | singleWidthLine();
636 | break;
637 | case '6':
638 | // DECDWL (Double-Width Line):
639 | doubleWidthLine();
640 | break;
641 | case '8':
642 | // DECALN (Screen Alignment Display):
643 | screenAlignmentDisplay();
644 | break;
645 | default:
646 | // 未確認のシーケンス
647 | unknownSequence(escMode, c);
648 | break;
649 | }
650 | clearParams(NONE);
651 | return mp_const_none;
652 | }else if (escMode == G0S) {
653 | // SCS (Select Character Set): G0
654 | setG0charset(c);
655 | clearParams(NONE);
656 | return mp_const_none;
657 | }else if(escMode == G1S) {
658 | // SCS (Select Character Set): G1
659 | setG1charset(c);
660 | clearParams(NONE);
661 | return mp_const_none;
662 | }
663 |
664 |
665 | if ((c == 0x0a) || (c == 0x0b) || (c == 0x0c)) {
666 | scroll();
667 | return mp_const_none;
668 | }
669 |
670 | // (CR)
671 | if (c == 0x0d) {
672 | XP = 0;
673 | return mp_const_none;
674 | }
675 | if (c== 0x0e){//using g1
676 | mode.Flgs.g0g1 = 1;
677 | currentTextTable=G1TABLE;
678 | return mp_const_none;
679 | }
680 | if (c==0x0f){//using g0
681 | mode.Flgs.g0g1 = 0;
682 | currentTextTable=G0TABLE;
683 | return mp_const_none;
684 | }
685 | // (BS)
686 | if (c == 0x7f) {
687 | cursorBackward(1);
688 | uint16_t idx = YP * SC_W + XP;
689 | screen[idx] = 0;
690 | attrib[idx] = 0;
691 | colors[idx] = cColor.value;
692 | sc_updateChar(XP, YP);
693 | return mp_const_none;
694 | }
695 |
696 | if (c == 0x08) {
697 | cursorBackward(1);
698 | return mp_const_none;
699 | }
700 | // tab
701 | if (c == 0x09) {
702 | int16_t idx = -1;
703 | for (int16_t i = XP + 1; i < SC_W; i++) {
704 | if (tabs[i]) {
705 | idx = i;
706 | break;
707 | }
708 | }
709 | XP = (idx == -1) ? MAX_SC_X : idx;
710 | return mp_const_none;
711 | }
712 |
713 | // normal char
714 | if (XP < SC_W) {
715 | uint16_t idx = YP * SC_W + XP;
716 | if (mode_ex.Flgs.InsertMode){
717 | // insert
718 | for (int16_t i = (YP+1) * SC_W - 1; i > idx; i--) {
719 | screen[i] = screen[i - 1];
720 | attrib[i] = attrib[i - 1];
721 | colors[i] = colors[i - 1];
722 | }
723 | screen[idx] = c;
724 | attrib[idx] = cAttr.value;
725 | colors[idx] = cColor.value;
726 | for (int16_t i = XP; i < SC_W; i++) {
727 | sc_updateChar(i, YP);
728 | }
729 | }else{
730 | screen[idx] = c;
731 | attrib[idx] = cAttr.value;
732 | colors[idx] = cColor.value;
733 | sc_updateChar(XP, YP);
734 | }
735 |
736 | }
737 |
738 |
739 | // return
740 | if (XP+1>=SC_W){
741 | if (mode_ex.Flgs.WrapLine){
742 | XP=0;
743 | scroll();
744 | }
745 |
746 | else{
747 | XP = MAX_SC_X;
748 | }
749 |
750 | }else{
751 | XP++;
752 | }
753 |
754 |
755 | return mp_const_none;
756 | }
757 |
758 | static MP_DEFINE_CONST_FUN_OBJ_1(vt_printChar_obj, vt_printChar);
759 |
760 |
761 |
762 |
763 |
764 | static void saveCursor(void) {
765 | b_XP = XP;
766 | b_YP = YP;
767 | bAttr.value = cAttr.value;
768 | bColor.value = cColor.value;
769 | }
770 |
771 | // DECRC (Restore Cursor):
772 | static void restoreCursor(void){
773 | XP = b_XP;
774 | YP = b_YP;
775 | cAttr.value = bAttr.value;
776 | cColor.value = bColor.value;
777 | }
778 |
779 | // DECKPAM (Keypad Application Mode):
780 | static void keypadApplicationMode(void) {
781 | return;
782 | }
783 |
784 | // DECKPNM (Keypad Numeric Mode):
785 | static void keypadNumericMode(void) {
786 | return;
787 | }
788 |
789 |
790 |
791 |
792 | // IND (Index):
793 |
794 | static void vindex(int16_t v) {
795 | cursorDown(v);
796 | }
797 |
798 | // NEL (Next Line):
799 |
800 | static void nextLine(void) {
801 | scroll();
802 | }
803 |
804 | // HTS (Horizontal Tabulation Set):
805 | static void horizontalTabulationSet(void) {
806 | tabs[XP] = 1;
807 | }
808 |
809 | static void reverseIndex(int16_t v) {
810 | if (v <= 0) return;
811 |
812 | int targetYP = YP - v;
813 |
814 | if (targetYP < M_TOP) {
815 | int lines_to_scroll = v;
816 |
817 | int scroll_region_height = M_BOTTOM - M_TOP + 1;
818 | if (lines_to_scroll > scroll_region_height)
819 | lines_to_scroll = scroll_region_height;
820 |
821 | int lines_to_move = scroll_region_height - lines_to_scroll;
822 |
823 | if (lines_to_move > 0) {
824 | int n = SC_W * lines_to_move;
825 | int dst = SC_W * (M_TOP + lines_to_scroll);
826 | int src = SC_W * M_TOP;
827 |
828 | if (src >= 0 && dst >= 0 &&
829 | src + n <= SC_W * SC_H &&
830 | dst + n <= SC_W * SC_H) {
831 | memmove(&screen[dst], &screen[src], n);
832 | memmove(&attrib[dst], &attrib[src], n);
833 | memmove(&colors[dst], &colors[src], n);
834 | }
835 | }
836 | int top_idx = SC_W * M_TOP;
837 | int fill_len = SC_W * lines_to_scroll;
838 |
839 | if (top_idx >= 0 && top_idx + fill_len <= SC_W * SC_H) {
840 | memset(&screen[top_idx], 0x00, fill_len);
841 | memset(&attrib[top_idx], defaultAttr.value, fill_len);
842 | memset(&colors[top_idx], defaultColor.value, fill_len);
843 | }
844 |
845 | YP = M_TOP;
846 |
847 | for (int y = M_TOP; y <= M_BOTTOM; y++) {
848 | if (y >= 0 && y < SC_H) {
849 | sc_updateLine(y);
850 | }
851 | }
852 | } else {
853 | YP = targetYP;
854 | }
855 | }
856 | // RI (Reverse Index):
857 |
858 | // DECID (Identify):
859 | static void identify(void) {
860 | deviceAttributes(0); // same as DA (Device Attributes)
861 | }
862 |
863 | // RIS (Reset To Initial State) リセット
864 | static void resetToInitialState(void) {
865 | fill_rect_4bpp(fb, 0, 0, SC_PIXEL_WIDTH, SC_PIXEL_HEIGHT, defaultColor.Color.Background);
866 | initCursorAndAttribute();
867 | eraseInDisplay(2);
868 | }
869 |
870 |
871 | // "[" Control Sequence Introducer (CSI)
872 | // -----------------------------------------------------------------------------
873 |
874 | // CUU (Cursor Up):
875 |
876 | /*
877 | static void cursorUp(int16_t v) {
878 | if ((YP - v) <= M_TOP){
879 | YP = M_TOP;
880 | }else{
881 | YP -= v;
882 | }
883 | }
884 | */
885 | // CUD (Cursor Down):
886 |
887 | static void cursorDown(int16_t v) {
888 |
889 | if ((YP+v)>M_BOTTOM){
890 | YP = M_BOTTOM;
891 | }else{
892 | YP += v;
893 | }
894 | }
895 |
896 | // CUF (Cursor Forward):
897 | static void cursorForward(int16_t v) {
898 | if ((XP+v)>=SC_W){
899 | XP = MAX_SC_X;
900 | }else{
901 | XP += v;
902 | }
903 | }
904 |
905 | // CUB (Cursor Backward):
906 | void cursorBackward(int16_t v) {
907 | if ((XP-v)<0){
908 | XP=0;
909 | }else{
910 | XP -=v;
911 | }
912 | }
913 |
914 | // CUP (Cursor Position):
915 | // HVP (Horizontal and Vertical Position):
916 | static void cursorPosition(uint8_t y, uint8_t x) {
917 |
918 | if ((y-1)>=SC_H){
919 | YP = MAX_SC_Y;
920 | }else{
921 | YP= y-1;
922 | }
923 |
924 | if ((x-1)>=SC_W){
925 | XP = MAX_SC_X;
926 | }else{
927 | XP = x -1;
928 | }
929 |
930 | }
931 |
932 |
933 | static void refreshScreen(void) {
934 |
935 | for (uint8_t i = 0; i < SC_H; i++){
936 | sc_updateLine(i);
937 | }
938 | }
939 |
940 |
941 | static void eraseInDisplay(uint8_t m) {
942 | uint8_t sl = 0, el = 0;
943 | uint16_t idx = 0, n = 0;
944 |
945 | switch (m) {
946 | case 0:
947 |
948 | sl = YP;
949 | el = MAX_SC_Y;
950 | idx = YP * SC_W + XP;
951 | n = SCSIZE - (YP * SC_W + XP);
952 | break;
953 | case 1:
954 |
955 | sl = 0;
956 | el = YP;
957 | idx = 0;
958 | n = YP * SC_W + XP + 1;
959 | break;
960 | case 2:
961 |
962 | sl = 0;
963 | el = MAX_SC_Y;
964 | idx = 0;
965 | n = SCSIZE;
966 | break;
967 | }
968 |
969 | if (m <= 2) {
970 | memset(&screen[idx], 0x00, n);
971 | memset(&attrib[idx], defaultAttr.value, n);
972 | memset(&colors[idx], defaultColor.value, n);
973 | for (uint8_t i = sl; i <= el; i++)
974 | sc_updateLine(i);
975 | }
976 | }
977 |
978 | // EL (Erase In Line):
979 | static void eraseInLine(uint8_t m) {
980 | uint16_t slp = 0, elp = 0;
981 |
982 | switch (m) {
983 | case 0:
984 | // current to end
985 | slp = YP * SC_W + XP;
986 | elp = YP * SC_W + MAX_SC_X;
987 | break;
988 | case 1:
989 | // start to current
990 | slp = YP * SC_W;
991 | elp = YP * SC_W + XP;
992 | break;
993 | case 2:
994 | // whole line
995 | slp = YP * SC_W;
996 | elp = YP * SC_W + MAX_SC_X;
997 | break;
998 | }
999 |
1000 | if (m <= 2) {
1001 | uint16_t n = elp - slp + 1;
1002 | memset(&screen[slp], 0x00, n);
1003 | memset(&attrib[slp], defaultAttr.value, n);
1004 | memset(&colors[slp], cColor.value, n);
1005 | //memset(&colors[slp], defaultColor.value, n);
1006 | sc_updateLine(YP);
1007 | }
1008 | }
1009 |
1010 | // IL (Insert Line):
1011 |
1012 | static void insertLine(uint8_t v) {
1013 | int16_t rows = v;
1014 | if (rows == 0) return;
1015 | if (rows > ((M_BOTTOM + 1) - YP)) rows = (M_BOTTOM + 1) - YP;
1016 | int16_t idx = SC_W * YP;
1017 | int16_t n = SC_W * rows;
1018 | int16_t idx2 = idx + n;
1019 | int16_t move_rows = (M_BOTTOM + 1) - YP - rows;
1020 | int16_t n2 = SC_W * move_rows;
1021 |
1022 | if (move_rows > 0) {
1023 | memmove(&screen[idx2], &screen[idx], n2);
1024 | memmove(&attrib[idx2], &attrib[idx], n2);
1025 | memmove(&colors[idx2], &colors[idx], n2);
1026 | }
1027 | memset(&screen[idx], 0x00, n);
1028 | memset(&attrib[idx], defaultAttr.value, n);
1029 | memset(&colors[idx], defaultColor.value, n);
1030 | for (uint8_t y = YP; y <= M_BOTTOM; y++)
1031 | sc_updateLine(y);
1032 | }
1033 |
1034 | // DL (Delete Line):
1035 |
1036 | static void deleteLine(uint8_t v) {
1037 | int16_t rows = v;
1038 | if (rows == 0) return;
1039 | if (rows > ((M_BOTTOM + 1) - YP)) rows = (M_BOTTOM + 1) - YP;
1040 | int16_t idx = SC_W * YP;
1041 | int16_t n = SC_W * rows;
1042 | int16_t idx2 = idx + n;
1043 | int16_t move_rows = (M_BOTTOM + 1) - YP - rows;
1044 | int16_t n2 = SC_W * move_rows;
1045 | int16_t idx3 = (M_BOTTOM + 1) * SC_W - n;
1046 |
1047 | if (move_rows > 0) {
1048 | memmove(&screen[idx], &screen[idx2], n2);
1049 | memmove(&attrib[idx], &attrib[idx2], n2);
1050 | memmove(&colors[idx], &colors[idx2], n2);
1051 | }
1052 | memset(&screen[idx3], 0x00, n);
1053 | memset(&attrib[idx3], defaultAttr.value, n);
1054 | memset(&colors[idx3], defaultColor.value, n);
1055 | for (uint8_t y = YP; y <= M_BOTTOM; y++)
1056 | sc_updateLine(y);
1057 | }
1058 |
1059 | // CPR (Cursor Position Report):
1060 | static void cursorPositionReport(uint16_t y, uint16_t x) {
1061 | char temp[30];
1062 | int32_t len = sprintf(temp, "\x1b[%d;%dR", SC_H, SC_W);
1063 |
1064 | if (outputLen + len <= sizeof(outputBuf)) {
1065 | memcpy(&(outputBuf[outputLen]), temp, len);
1066 | outputLen += len;
1067 | }
1068 | }
1069 |
1070 | // DA (Device Attributes):
1071 |
1072 | static void deviceAttributes(uint8_t m) {
1073 |
1074 | if (outputLen + 7 <= sizeof(outputBuf)) {
1075 | memcpy(&(outputBuf[outputLen]), "\e[?1;0c", 7);
1076 | outputLen += 7;
1077 | }
1078 | }
1079 |
1080 | // TBC (Tabulation Clear):
1081 | static void tabulationClear(uint8_t m) {
1082 | switch (m) {
1083 | case 0:
1084 | // current position
1085 | tabs[XP] = 0;
1086 | break;
1087 | case 3:
1088 | // all tabs
1089 | memset(tabs, 0x00, SC_W);
1090 | break;
1091 | }
1092 | }
1093 |
1094 | // LNM (Line Feed / New Line Mode):
1095 | static void lineMode(bool m) {
1096 | mode.Flgs.CrLf = m;
1097 | }
1098 |
1099 | // DECSCNM (Screen Mode):
1100 | static void screenMode(bool m) {
1101 | mode_ex.Flgs.ScreenReverse = m;
1102 | refreshScreen();
1103 | }
1104 |
1105 | // DECAWM (Auto Wrap Mode):
1106 | static void autoWrapMode(bool m) {
1107 | mode_ex.Flgs.WrapLine = m;
1108 | }
1109 |
1110 | // SM (Set Mode):
1111 | static void setMode(int16_t *vals, int16_t nVals) {
1112 | for (int16_t i = 0; i < nVals; i++) {
1113 | switch (vals[i]) {
1114 | case 20:
1115 | // LNM (Line Feed / New Line Mode)
1116 | lineMode(true);
1117 | break;
1118 | case 4:
1119 | // IRM (Insert Mode):
1120 | mode_ex.Flgs.InsertMode = 1;
1121 | break;
1122 | default:
1123 | break;
1124 | }
1125 | }
1126 | }
1127 |
1128 | // DECSET (DEC Set Mode):
1129 | static void decSetMode(int16_t *vals, int16_t nVals) {
1130 | for (int16_t i = 0; i < nVals; i++) {
1131 | switch (vals[i]) {
1132 | case 5:
1133 | // DECSCNM (Screen Mode):
1134 | screenMode(true);
1135 | break;
1136 | case 7:
1137 | // DECAWM (Auto Wrap Mode):
1138 | autoWrapMode(true);
1139 | break;
1140 |
1141 | case 25:
1142 | // DECTCEM (Cursor Mode):
1143 | canShowCursor = true;
1144 | break;
1145 | default:
1146 | break;
1147 | }
1148 | }
1149 | }
1150 |
1151 | // RM (Reset Mode):
1152 | static void resetMode(int16_t *vals, int16_t nVals) {
1153 | for (int16_t i = 0; i < nVals; i++) {
1154 | switch (vals[i]) {
1155 | case 20:
1156 | // LNM (Line Feed / New Line Mode)
1157 | lineMode(false);
1158 | break;
1159 |
1160 | case 4:
1161 | // IRM (Insert Mode):
1162 | mode_ex.Flgs.InsertMode = 0;
1163 | break;
1164 | default:
1165 | break;
1166 | }
1167 | }
1168 | }
1169 |
1170 | // DECRST (DEC Reset Mode):
1171 | static void decResetMode(int16_t *vals, int16_t nVals) {
1172 | for (int16_t i = 0; i < nVals; i++) {
1173 | switch (vals[i]) {
1174 | case 5:
1175 | // DECSCNM (Screen Mode):
1176 | screenMode(false);
1177 | break;
1178 | case 7:
1179 | // DECAWM (Auto Wrap Mode):
1180 | autoWrapMode(false);
1181 | break;
1182 | case 25:
1183 | // DECTCEM (Cursor Mode):
1184 | canShowCursor = false;
1185 | sc_updateChar(p_XP, p_YP);//cover the hided character at cursor position
1186 | break;
1187 | default:
1188 | break;
1189 | }
1190 | }
1191 | }
1192 |
1193 | // SGR (Select Graphic Rendition):
1194 | static void selectGraphicRendition(int16_t *vals, int16_t nVals) {
1195 | uint8_t seq = 0;
1196 | uint16_t r, g, b, cIdx;
1197 | bool isFore = true;
1198 | for (int16_t i = 0; i < nVals; i++) {
1199 | int16_t v = vals[i];
1200 | switch (seq) {
1201 | case 0:
1202 | switch (v) {
1203 | case 0:
1204 | // Reset all attributes
1205 | cAttr.value = 0;
1206 | cColor.value = defaultColor.value;
1207 | break;
1208 | case 1:
1209 | // Bold
1210 | cAttr.Bits.Bold = 1;
1211 | break;
1212 | case 4:
1213 | // char with underline
1214 | cAttr.Bits.Underline = 1;
1215 | break;
1216 | case 5:
1217 | // blink
1218 | cAttr.Bits.Blink = 1;
1219 | break;
1220 | case 7:
1221 | // reverse
1222 | cAttr.Bits.Reverse = 1;
1223 | break;
1224 | case 21:
1225 | // bold
1226 | cAttr.Bits.Bold = 0;
1227 | break;
1228 | case 22:
1229 | // bold remove
1230 | cAttr.Bits.Bold = 0;
1231 | break;
1232 | case 24:
1233 | // char with underline remove
1234 | cAttr.Bits.Underline = 0;
1235 | break;
1236 | case 25:
1237 | // blink remove
1238 | cAttr.Bits.Blink = 0;
1239 | break;
1240 | case 27:
1241 | // inverse remove
1242 | cAttr.Bits.Reverse = 0;
1243 | break;
1244 | case 38:
1245 | seq = 1;
1246 | isFore = true;
1247 | break;
1248 | case 39:
1249 | // front color recover
1250 | cColor.Color.Foreground = defaultColor.Color.Foreground;
1251 | break;
1252 | case 48:
1253 | seq = 1;
1254 | isFore = false;
1255 | break;
1256 | case 49:
1257 | // background recover
1258 | cColor.Color.Background = defaultColor.Color.Background;
1259 | break;
1260 | default:
1261 | if (v >= 30 && v <= 37) {
1262 | //front color
1263 | cColor.Color.Foreground = v - 30;
1264 | } else if (v >= 40 && v <= 47) {
1265 | // background color
1266 | cColor.Color.Background = v - 40;
1267 | }
1268 | break;
1269 | }
1270 | break;
1271 | case 1:
1272 | switch (v) {
1273 | case 2:
1274 | // RGB
1275 | seq = 3;
1276 | break;
1277 | case 5:
1278 | // Color Index
1279 | seq = 2;
1280 | break;
1281 | default:
1282 | seq = 0;
1283 | break;
1284 | }
1285 | break;
1286 | case 2:
1287 | // Index Color
1288 | if (v < 256) {
1289 | if (v < 16) {
1290 | // 16 color
1291 | cIdx = v;
1292 | } else if (v < 232) {
1293 | // 6x6x6 RGB
1294 | b = ( (v - 16) % 6) / 3;
1295 | g = (((v - 16) / 6) % 6) / 3;
1296 | r = (((v - 16) / 36) % 6) / 3;
1297 | cIdx = (b << 2) | (g << 1) | r;
1298 | } else {
1299 | // 244 color
1300 | if (v < 244)
1301 | cIdx = clBlack;
1302 | else
1303 | cIdx = clWhite;
1304 | }
1305 | if (isFore)
1306 | cColor.Color.Foreground = cIdx;
1307 | else
1308 | cColor.Color.Background = cIdx;
1309 | }
1310 | seq = 0;
1311 | break;
1312 | case 3:
1313 | // RGB - R
1314 | seq = 4;
1315 | break;
1316 | case 4:
1317 | // RGB - G
1318 | seq = 5;
1319 | break;
1320 | case 5:
1321 | // RGB - B
1322 | if (vals[i-2]>128){
1323 | r = 1;
1324 | }else{
1325 | r=0;
1326 | }
1327 | if (vals[i-1]>128){
1328 | g = 1;
1329 | }else{
1330 | g=0;
1331 | }
1332 | if (vals[i-0]>128){
1333 | b = 1;
1334 | }else{
1335 | b=0;
1336 | }
1337 | cIdx = (b << 2) | (g << 1) | r;
1338 | if (isFore)
1339 | cColor.Color.Foreground = cIdx;
1340 | else
1341 | cColor.Color.Background = cIdx;
1342 | seq = 0;
1343 | break;
1344 | default:
1345 | seq = 0;
1346 | break;
1347 | }
1348 | }
1349 | }
1350 |
1351 | // DSR (Device Status Report):
1352 | static void deviceStatusReport(uint8_t m) {
1353 | switch (m) {
1354 | case 5:
1355 | if (outputLen + 4 <= sizeof(outputBuf)) {
1356 | memcpy(&(outputBuf[outputLen]), "\e[0n", 4);
1357 | outputLen += 4;
1358 | }
1359 |
1360 | break;
1361 | case 6:
1362 | cursorPositionReport(XP, YP); // CPR (Cursor Position Report)
1363 | break;
1364 | }
1365 | }
1366 |
1367 | // DECLL (Load LEDS):
1368 | static void loadLEDs(uint8_t m) {
1369 | return;
1370 |
1371 | }
1372 |
1373 | // DECSTBM (Set Top and Bottom Margins):
1374 | static void setTopAndBottomMargins(int16_t s, int16_t e) {
1375 | if (e <= s) return;
1376 | M_TOP = s - 1;
1377 | if (M_TOP > MAX_SC_Y) M_TOP = MAX_SC_Y;
1378 | M_BOTTOM = e - 1;
1379 | if (M_BOTTOM > MAX_SC_Y) M_BOTTOM = MAX_SC_Y;
1380 | setCursorToHome();
1381 | }
1382 |
1383 | // DECTST (Invoke Confidence Test):
1384 | static void invokeConfidenceTests(uint8_t m) {
1385 | return;
1386 | }
1387 |
1388 | // "]" Operating System Command (OSC)
1389 | // -----------------------------------------------------------------------------
1390 |
1391 | // "#" Line Size Command
1392 | // -----------------------------------------------------------------------------
1393 |
1394 | // DECDHL (Double Height Line):
1395 | static void doubleHeightLine_TopHalf(void) {
1396 | return;
1397 | }
1398 |
1399 | // DECDHL (Double Height Line):
1400 | static void doubleHeightLine_BotomHalf(void) {
1401 | return;
1402 | }
1403 |
1404 | // DECSWL (Single-width Line):
1405 | static void singleWidthLine(void) {
1406 | return;
1407 | }
1408 |
1409 | // DECDWL (Double-Width Line):
1410 | static void doubleWidthLine(void) {
1411 | return;
1412 | }
1413 |
1414 | // DECALN (Screen Alignment Display):
1415 | static void screenAlignmentDisplay(void) {
1416 |
1417 | memset(screen, 0x45, SCSIZE);
1418 | memset(attrib, defaultAttr.value, SCSIZE);
1419 | memset(colors, defaultColor.value, SCSIZE);
1420 | for (uint8_t y = 0; y < SC_H; y++)
1421 | sc_updateLine(y);
1422 | }
1423 |
1424 | // "(" G0 Sets Sequence
1425 | // -----------------------------------------------------------------------------
1426 |
1427 | // G0
1428 | static void setG0charset(char c) {
1429 | return;
1430 | }
1431 |
1432 | // "(" G1 Sets Sequence
1433 | // -----------------------------------------------------------------------------
1434 |
1435 | // G1
1436 | static void setG1charset(char c) {
1437 | return;
1438 | }
1439 |
1440 | // Unknown Sequence
1441 | // -----------------------------------------------------------------------------
1442 |
1443 |
1444 | static void unknownSequence(uint8_t m, char c) {
1445 | return;
1446 | }
1447 |
1448 |
1449 |
1450 |
1451 |
1452 |
1453 |
1454 |
1455 | static void drawTxt6x8(uint8_t *fb,uint8_t c,int x0,int y0, uint8_t color){
1456 | // extract arguments
1457 | int x;
1458 | int y;
1459 | if (c < 16 ) {
1460 | c = 32;
1461 | }
1462 | // get char data
1463 | const uint8_t *chr_data = ¤tTextTable[(c - 16) * CH_H];
1464 | // loop over char data
1465 | y = y0;
1466 | for (; y < y0+CH_H; y++) {
1467 | if (0 <= y && y < SC_PIXEL_WIDTH) {
1468 | x = x0;
1469 | uint8_t line_data = *chr_data++;
1470 | for (;x> 1;
1485 | if (scroll_y1 < 0 || scroll_y2 >= SC_PIXEL_HEIGHT || n <= 0 || (scroll_y2 - scroll_y1 + 1) <= n)
1486 | return;
1487 |
1488 | for (int y = scroll_y1; y <= scroll_y2 - n; y++) {
1489 | uint8_t *dst_ptr = fb + y * row_bytes;
1490 | uint8_t *src_ptr = fb + (y + n) * row_bytes;
1491 |
1492 | for (int x = 0; x < row_bytes; x += 8) {
1493 | *dst_ptr++ = *src_ptr++;
1494 | *dst_ptr++ = *src_ptr++;
1495 | *dst_ptr++ = *src_ptr++;
1496 | *dst_ptr++ = *src_ptr++;
1497 | *dst_ptr++ = *src_ptr++;
1498 | *dst_ptr++ = *src_ptr++;
1499 | *dst_ptr++ = *src_ptr++;
1500 | *dst_ptr++ = *src_ptr++;
1501 | }
1502 | }
1503 | bg_color = (bg_color & 0x0F)|(bg_color<<4); //double the bg color as 2 pixels
1504 | for (int y = scroll_y2 - n + 1; y <= scroll_y2; y++) {
1505 | uint8_t *dst_ptr = fb + y * row_bytes;
1506 | for (int x = 0; x < row_bytes; x += 8) {
1507 | *dst_ptr++ = bg_color;
1508 | *dst_ptr++ = bg_color;
1509 | *dst_ptr++ = bg_color;
1510 | *dst_ptr++ = bg_color;
1511 | *dst_ptr++ = bg_color;
1512 | *dst_ptr++ = bg_color;
1513 | *dst_ptr++ = bg_color;
1514 | *dst_ptr++ = bg_color;
1515 | }
1516 | }
1517 | }
1518 | */
1519 | static void fill_rect_4bpp(uint8_t *fb, int x, int y, int w, int h, uint8_t color){
1520 |
1521 | int row_bytes = SC_PIXEL_WIDTH >> 1;
1522 | uint8_t fill_byte = (color << 4) | (color & 0x0F);
1523 | for (int row = y; row < y + h; row++) {
1524 | uint8_t *row_ptr = fb + row * row_bytes;
1525 | int pos = x;
1526 | int pixels_to_fill = w;
1527 | uint8_t *ptr = row_ptr + (pos >> 1);
1528 | if (pos & 1) {
1529 | *ptr = (*ptr & 0xF0) | (color & 0x0F);
1530 | pos++;
1531 | pixels_to_fill--;
1532 | ptr = row_ptr + (pos >> 1);
1533 | }
1534 | int full_bytes = pixels_to_fill >> 1;
1535 | int remaining_pixels = pixels_to_fill & 1;
1536 | while (full_bytes >= 3) {
1537 | *ptr++ = fill_byte;
1538 | *ptr++ = fill_byte;
1539 | *ptr++ = fill_byte;
1540 | full_bytes -= 3;
1541 | }
1542 | while (full_bytes--) {
1543 | *ptr++ = fill_byte;
1544 | }
1545 |
1546 | if (remaining_pixels) {
1547 | *ptr = (*ptr & 0x0F) | (color << 4);
1548 | }
1549 | }
1550 | }
1551 |
1552 |
1553 | static mp_obj_t vtterminal_init(mp_obj_t fb_obj){
1554 |
1555 | mp_buffer_info_t buf_info;
1556 | mp_get_buffer_raise(fb_obj, &buf_info, MP_BUFFER_READ);
1557 | fb=(uint8_t *)buf_info.buf;
1558 |
1559 | currentTextTable=G0TABLE;
1560 | resetToInitialState();
1561 | setCursorToHome();
1562 |
1563 | //init the timer and callback
1564 | add_repeating_timer_ms(250, dispCursor, NULL, &cursor_timer);
1565 | return mp_const_true;
1566 | }
1567 |
1568 | static MP_DEFINE_CONST_FUN_OBJ_1(vt_init_obj, vtterminal_init);
1569 |
1570 |
1571 |
1572 | static mp_obj_t vt_read(void){
1573 |
1574 | mp_obj_t result = mp_obj_new_str(outputBuf, outputLen);
1575 | outputLen = 0;
1576 | return result;
1577 | }
1578 | static MP_DEFINE_CONST_FUN_OBJ_0(vt_read_obj, vt_read);
1579 |
1580 |
1581 |
1582 |
1583 | static const mp_rom_map_elem_t vtterminal_globals_table[] = {
1584 | { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_vtterminal) },
1585 | { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&vt_init_obj) },
1586 | { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&vt_read_obj) },
1587 | { MP_ROM_QSTR(MP_QSTR_printChar), MP_ROM_PTR(&vt_printChar_obj)}
1588 | };
1589 | static MP_DEFINE_CONST_DICT(vtterminal_globals, vtterminal_globals_table);
1590 |
1591 |
1592 | const mp_obj_module_t vtterminal_cmodule = {
1593 | .base = { &mp_type_module },
1594 | .globals = (mp_obj_dict_t*)&vtterminal_globals,
1595 | };
1596 |
1597 |
1598 | MP_REGISTER_MODULE(MP_QSTR_vtterminal, vtterminal_cmodule);
--------------------------------------------------------------------------------