Created
April 13, 2022 01:23
-
-
Save samneggs/01d16e5003bf5bfa6d8e131b0619a09c to your computer and use it in GitHub Desktop.
16 color pallet to RGB565 on Pi Pico in MicroPython and inline assembly
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import gc9a01 | |
from machine import Pin, SPI, PWM, WDT | |
from math import sin,cos,radians | |
import array, micropython, framebuf | |
import _thread, gc | |
from time import sleep_ms, sleep_us, ticks_diff, ticks_us, sleep | |
from sys import exit | |
from uctypes import addressof | |
MAXSCREEN_X=const(240) | |
MAXSCREEN_Y=const(240) | |
MAXCHUNK_Y=const(80) | |
TOKEN = True | |
CORE0_DONE=False | |
def core0(): | |
global TOKEN,CORE0_DONE | |
#screen.pixel(0,0,1) | |
#chunk_ctl[2]=0 | |
#print(chunk_asm16(chunk_ctl,pallet)) | |
#print(chunk_asm2(chunk_ctl)) | |
#CORE0_DONE=True | |
#exit() | |
i=0 | |
ticks=ticks_us() | |
while(i>0): | |
if TOKEN: | |
diff=ticks_diff(ticks_us(),ticks) | |
ticks=ticks_us() | |
screen.text('TEXT',100,100,0xffff) | |
tft.blit_buffer(chunk, 0, 0, MAXSCREEN_X, MAXCHUNK_Y) | |
tft.blit_buffer(chunk, 0, 80, MAXSCREEN_X, MAXCHUNK_Y) | |
tft.blit_buffer(chunk, 0, 160, MAXSCREEN_X, MAXCHUNK_Y) | |
i-=1 | |
print(1_000_000//diff) | |
#TOKEN = False | |
for j in range(10): | |
i=10 | |
while(i>0): | |
ticks=ticks_us() | |
cls_asm16(screen) | |
screen.text('HELLO',100,10) | |
for x in range(0,230,10): | |
screen.line(x+i,0,239,x+i,1) | |
screen.line(0,x+i,x+i,239,1) | |
show16() | |
diff=ticks_diff(ticks_us(),ticks) | |
i-=1 | |
print(1_000_000//diff) | |
CORE0_DONE=True | |
def show(): | |
chunk_ctl[2]=0 | |
chunk_asm1(chunk_ctl) | |
tft.blit_buffer(chunk, 0, 0, MAXSCREEN_X, MAXCHUNK_Y) | |
chunk_ctl[2]=2400 | |
chunk_asm1(chunk_ctl) | |
tft.blit_buffer(chunk, 0, 80, MAXSCREEN_X, MAXCHUNK_Y) | |
chunk_ctl[2]=2400*2 | |
chunk_asm1(chunk_ctl) | |
tft.blit_buffer(chunk, 0, 160, MAXSCREEN_X, MAXCHUNK_Y) | |
def show16(): | |
chunk_ctl[3]=9600 | |
chunk_ctl[2]=0 | |
chunk_asm16(chunk_ctl,pallet) | |
tft.blit_buffer(chunk, 0, 0, MAXSCREEN_X, MAXCHUNK_Y) | |
chunk_ctl[2]=9600 | |
chunk_asm16(chunk_ctl,pallet) | |
tft.blit_buffer(chunk, 0, 80, MAXSCREEN_X, MAXCHUNK_Y) | |
chunk_ctl[2]=9600*2 | |
chunk_asm16(chunk_ctl,pallet) | |
tft.blit_buffer(chunk, 0, 160, MAXSCREEN_X, MAXCHUNK_Y) | |
@micropython.asm_thumb | |
def chunk_asm(r0,r1,r2,r3): # from, to, #bytes, color | |
label(LOOP) | |
ldrb(r4,[r0,0]) | |
mov(r6,8) | |
label(BYTE) | |
asr(r4,r4,1) | |
bcs(ONE) | |
mov(r5,0) | |
b(NEXT) | |
label(ONE) | |
mov(r5,r3) | |
label(NEXT) | |
strh(r5,[r1,0]) | |
add(r1,r1,2) | |
sub(r6,r6,1) | |
bne(BYTE) | |
add(r0,r0,1) | |
sub(r2,r2,1) | |
bne(LOOP) | |
label(EXIT) | |
#one color | |
@micropython.asm_thumb | |
def chunk_asm1(r0): # 0=from, 4=to, 8=offset, 12=#bytes, 16=color | |
ldr(r1,[r0,0]) # r1=screen addr | |
ldr(r2,[r0,8]) # offset | |
add(r1,r1,r2) # r1=screen addr+offset | |
ldr(r2,[r0,4]) # r2=chunk addr | |
ldr(r3,[r0,12]) # r3=#bytes | |
ldr(r4,[r0,16]) # r4=color | |
label(LOOP) | |
ldrb(r5,[r1,0]) # r5=load screen byte | |
mov(r6,8) # r6=bit count | |
label(BYTE) | |
asr(r5,r5,1) # next bit | |
bcs(ONE) | |
mov(r7,0) # color = 0 | |
b(NEXT) | |
label(ONE) | |
mov(r7,r4) # color = 1 | |
label(NEXT) | |
strh(r7,[r2,0]) # write chunk byte | |
add(r2,r2,2) # next chunk byte | |
sub(r6,r6,1) # next bit | |
bne(BYTE) | |
add(r1,r1,1) # next screen byte | |
sub(r3,r3,1) # number bytes -1 | |
bne(LOOP) | |
label(EXIT) | |
@micropython.asm_thumb | |
def cls_asm1(r0): # screen | |
mov(r1,225) | |
lsl(r1,r1,5) # 7200, screen size | |
mov(r2,0) | |
label(LOOP) | |
strb(r2,[r0,0]) | |
add(r0,1) | |
sub(r1,1) | |
bne(LOOP) | |
label(EXIT) | |
@micropython.asm_thumb | |
def cls_asm16(r0): # screen | |
mov(r1,225) | |
lsl(r1,r1,7) # 28800, screen size | |
mov(r2,0) | |
label(LOOP) | |
strb(r2,[r0,0]) | |
add(r0,1) | |
sub(r1,1) | |
bne(LOOP) | |
label(EXIT) | |
#16 colors | |
@micropython.asm_thumb | |
def chunk_asm16(r0,r1): # r0=ctl, r1=color pallet | |
# ctl 0=from, 4=to, 8=offset, 12=#bytes | |
ldr(r2,[r0,4]) # r2=chunk addr | |
ldr(r3,[r0,12]) # r3=#bytes | |
ldr(r4,[r0,0]) # screen addr | |
ldr(r6,[r0,8]) # offset | |
add(r0,r6,r4) # r0=screen addr+offset | |
mov(r7,0xf) # low nibble mask | |
label(LOOP) | |
ldrb(r6,[r0,0]) # r6=screen byte | |
asr(r4,r6,4) # high nibble | |
add(r4,r4,r4) # double for ldrh | |
add(r4,r4,r1) # pallet address | |
ldrh(r4,[r4,0]) # r4=color | |
strh(r4,[r2,0]) # write color to chunk | |
add(r2,r2,2) # next chunk byte | |
and_(r6,r7) # low nibble | |
add(r6,r6,r6) # double for ldrh | |
add(r6,r6,r1) # pallet address | |
ldrh(r6,[r6,0]) # r4=color | |
strh(r6,[r2,0]) # write color to chunk | |
add(r2,r2,2) # next chunk byte | |
add(r0,r0,1) # next screen byte | |
sub(r3,r3,1) # number bytes -1 | |
bne(LOOP) | |
label(EXIT) | |
def draw(): | |
global TOKEN | |
if TOKEN==False: | |
screen.text('TEXT',100,50,0xffff) | |
TOKEN = True | |
print('pre alloc',gc.mem_alloc()) | |
if __name__=='__main__': | |
spi = SPI(1, baudrate=63_000_000, sck=Pin(10), mosi=Pin(11)) | |
tft = gc9a01.GC9A01( | |
spi, | |
MAXSCREEN_X, | |
240, | |
reset=Pin(12, Pin.OUT), | |
cs=Pin(9, Pin.OUT), | |
dc=Pin(8, Pin.OUT), | |
backlight=Pin(13, Pin.OUT), | |
rotation=0) | |
tft.init() | |
tft.rotation(0) | |
tft.fill(gc9a01.BLACK) | |
display_buffer=bytearray(240 * MAXCHUNK_Y * 2) | |
draw_buffer=bytearray(240*240//2) # //8 | |
chunk=framebuf.FrameBuffer(display_buffer, MAXSCREEN_X , MAXCHUNK_Y, framebuf.RGB565) | |
# screen=framebuf.FrameBuffer(draw_buffer, MAXSCREEN_X , MAXSCREEN_Y, framebuf.MONO_HMSB) | |
screen=framebuf.FrameBuffer(draw_buffer, MAXSCREEN_X , MAXSCREEN_Y, framebuf.GS4_HMSB) | |
chunk_ctl=array.array('i',(addressof(screen),addressof(chunk),2400,2400,0xffff)) | |
pallet=array.array('H',(0,0x00fe,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)) | |
print('after screen free',gc.mem_free()) | |
_thread.start_new_thread(core0, ()) | |
while CORE0_DONE==False: | |
pass | |
gc.collect() | |
print(gc.mem_free()) | |
exit() | |
while(0): | |
core0() | |
screen.text('HELLO',100,10) | |
chunky() | |
tft.blit_buffer(chunk, 0, 0, MAXSCREEN_X, MAXCHUNK_Y) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment