Skip to content

Instantly share code, notes, and snippets.

@samneggs
Created April 13, 2022 01:23
Show Gist options
  • Save samneggs/01d16e5003bf5bfa6d8e131b0619a09c to your computer and use it in GitHub Desktop.
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
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