Created
May 22, 2022 23:46
-
-
Save samneggs/f8b353756bedde202b34b3396c676e61 to your computer and use it in GitHub Desktop.
Falling Sand and Water
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 gc9a01 import color565 | |
from machine import Pin, SPI, PWM, WDT, freq | |
import framebuf | |
from time import sleep_ms, sleep_us, ticks_diff, ticks_us, sleep | |
from micropython import const | |
import array | |
from usys import exit | |
import gc | |
from random import randint | |
from uctypes import addressof | |
import _thread | |
MAXSCREEN_X = const(240) | |
MAXSCREEN_Y = const(240) | |
display_buffer=bytearray(MAXSCREEN_X * MAXSCREEN_Y * 2) | |
text_buffer=bytearray(8*80*2) | |
DONE=False | |
RIGHT=False | |
def bl_ctrl(duty): | |
pwm = PWM(Pin(13)) | |
pwm.freq(1000) | |
if(duty>=100): | |
pwm.duty_u16(65535) | |
else: | |
pwm.duty_u16(655*duty) | |
# http://www.penguintutor.com/programming/picodisplayanimations | |
def blit_image_file(filename,width,height): # file width, file height | |
#print(filename,gc.mem_free()) | |
with open (filename, "rb") as file: | |
file_position = 0 | |
char_position = 0 | |
current_byte = file.read(4) # header | |
while file_position < (width * height * 2): | |
current_byte = file.read(1) | |
# if eof | |
if len(current_byte) == 0: | |
break | |
# copy to buffer | |
tex_buff[char_position] = ord(current_byte) | |
char_position += 1 | |
file_position += 1 | |
file.close() | |
#screen.blit(texture,50,50) | |
#tft.blit_buffer(screen, 20, 0, MAXSCREEN_X, MAXSCREEN_Y) | |
#exit() | |
def blocks(): | |
for i in range(10): | |
dx=20 | |
min_y=120 | |
screen.fill_rect(randint(0,220),randint(min_y,220),10,10,0xffff) | |
x=randint(50,220) | |
y=randint(min_y,220) | |
screen.line(x,y,x+dx,y+dx,0xffff) | |
screen.line(x,y+1,x+dx,y+dx+1,0xffff) | |
x=randint(50,220) | |
y=randint(min_y,220) | |
screen.line(x,y,x-dx,y+dx,0xffff) | |
screen.line(x,y+1,x-dx,y+dx+1,0xffff) | |
@micropython.viper | |
def sand2(): | |
screen_addr=ptr16(display_buffer) | |
for y in range(220,0,-1): | |
for x in range(0,240): | |
source=y*MAXSCREEN_X+x-MAXSCREEN_X | |
sourcecolor=screen_addr[source] | |
if sourcecolor == 0xff00 or sourcecolor == 0: | |
continue | |
dest=y*MAXSCREEN_X+x | |
destcolor=screen_addr[dest] | |
if destcolor == 0: | |
screen_addr[source] = 0 | |
screen_addr[dest] = sourcecolor | |
elif screen_addr[source+1+MAXSCREEN_X] == 0: | |
screen_addr[source] = 0 | |
screen_addr[source+1+MAXSCREEN_X] = sourcecolor | |
elif screen_addr[source-1+MAXSCREEN_X] == 0: | |
screen_addr[source] = 0 | |
screen_addr[source-1+MAXSCREEN_X] = sourcecolor | |
@micropython.asm_thumb | |
def water_lasm(r0): | |
mov(r1,239) # r1 = y | |
label(LOOP_Y) | |
mov(r7,255) # stack marker | |
push({r7}) | |
mov(r7,1) | |
mov(r2,r1) | |
and_(r2,r7) | |
bne(LEFT2RIGHT) | |
mov(r2,120) # max x | |
b(LOOP_X) | |
label(LEFT2RIGHT) | |
mov(r2,0) # r2 = x | |
label(LOOP_X) | |
mov(r3,240) # 240 | |
mul(r3,r1) # 240*y | |
add(r3,r3,r2) # 240*y+x | |
mov(r4,r3) | |
sub(r4,240) # -XMAX | |
add(r3,r3,r3) # double ldrh | |
add(r3,r3,r0) # r3 = dest addr | |
add(r4,r4,r4) # double ldrh | |
add(r4,r4,r0) # r4 = source addr | |
ldrh(r5,[r4,0]) # r5 = sourcecolor | |
cmp(r5,0) | |
beq(NEXT_X) # skip if source=0 | |
mov(r7,0x1) | |
lsl(r7,r7,16) | |
sub(r7,1) # 0xffff | |
cmp(r5,r7) | |
beq(NEXT_X) # skip if source=0xffff | |
ldrh(r6,[r3,0]) # r6=destcolor | |
cmp(r6,0) | |
beq(MOVEDOWN) # move down if dest=0 | |
mov(r7,255) | |
lsl(r7,r7,8) # 0xff00 water color | |
cmp(r7,r5) | |
beq(TRYPLUS1) # try move diag if source=water | |
cmp(r5,0xff) # 0x00ff=yellow | |
beq(YELLOW) | |
b(NEXT_X) | |
label(YELLOW) | |
cmp(r6,r7) # is dest water? | |
bne(TRYPLUS1) | |
strh(r7,[r4,0]) # source = 0 | |
strh(r5,[r3,0]) # dest = sourcecolor | |
b(NEXT_X) | |
label(MOVEDOWN) | |
mov(r6,0) | |
strh(r6,[r4,0]) # source = 0 | |
strh(r5,[r3,0]) # dest = sourcecolor | |
b(NEXT_X) | |
label(TRYPLUS1) | |
mov(r3,r4) # source | |
mov(r6,241) # 1 + MAX_X | |
add(r6,r6,r6) # double ldrh | |
add(r3,r3,r6) # source + 1 + MAX_X | |
ldrh(r6,[r3,0]) # r6=diag color | |
cmp(r6,0) | |
beq(DIAGRIGHT) | |
cmp(r6,0x0) # if empty move diag | |
beq(DIAGRIGHT) | |
cmp(r6,r7) # if water move diag | |
bne(TRYMINUS1) | |
cmp(r5,0xff) # if sand move diag | |
bne(TRYMINUS1) | |
label(DIAGRIGHT) # move diag to right | |
#mov(r6,0) | |
strh(r6,[r4,0]) # source = 0 | |
strh(r5,[r3,0]) # source + 1 + MAX_X = sourcecolor | |
b(NEXT_X) | |
label(TRYMINUS1) | |
sub(r3,4) # source-1+MAXSCREEN_X | |
ldrh(r6,[r3,0]) | |
cmp(r6,0) # is diag empty? | |
beq(DIAGLEFT) | |
cmp(r5,r7) # is source water | |
beq(SAVE_WATER) | |
cmp(r6,r7) # is dest water? | |
beq(DIAGLEFT) | |
b(SAVE_WATER) | |
label(DIAGLEFT) | |
strh(r6,[r4,0]) # source = 0 | |
strh(r5,[r3,0]) # source - 2 + MAX_X = sourcecolor | |
b(NEXT_X) | |
label(SAVE_WATER) | |
cmp(r5,0xff) # is sand? | |
beq(NEXT_X) | |
mov(r7,r2) | |
push({r7}) | |
label(NEXT_X) | |
mov(r7,1) | |
mov(r6,r1) | |
and_(r6,r7) | |
bne(LEFT2RIGHT1) | |
sub(r2,1) | |
bne(LOOP_X) | |
b(WATER) | |
label(LEFT2RIGHT1) | |
add(r2,1) | |
cmp(r2,120) # max x | |
bne(LOOP_X) | |
label(WATER) #------DO WATER LEFT/RIGHT---------- | |
pop({r7}) | |
cmp(r7,255) | |
beq(WATER_DONE) | |
add(r7,1) | |
mov(r4,r1) | |
sub(r4,1) | |
mov(r3,240) # 240 | |
mul(r3,r4) # 240*y | |
add(r3,r3,r7) # 240*y+x | |
sub(r3,2) # 240*y+x-2 | |
add(r3,r3,r3) # double ldrh | |
add(r3,r3,r0) # r3 = dest addr | |
ldrh(r5,[r3,2]) # r5 = source color | |
label(RANDOM) | |
align(4) | |
mov(r7,pc) | |
b(RANDBIT_ADDR) | |
data(2,0x001c,0x4006) | |
align(4) | |
label(RANDBIT_ADDR) | |
ldr(r7,[r7,0]) # get random addr | |
ldr(r7,[r7,0]) # get random bit | |
cmp(r7,1) # choose left/right first | |
beq(LEFT_FIRST) | |
b(TEST_RIGHT2) | |
label(LEFT_FIRST) | |
b(TEST_LEFT) | |
label(TEST_LEFT) | |
ldrh(r4,[r3,0]) # r4 = left dest color | |
cmp(r4,0) | |
bne(TEST_RIGHT) | |
mov(r6,0) | |
strh(r6,[r3,2]) | |
strh(r5,[r3,0]) # move color to left | |
b(WATER) | |
label(TEST_RIGHT) | |
ldrh(r4,[r3,4]) # r4 = right dest color | |
cmp(r4,0) | |
bne(WATER) | |
mov(r6,0) | |
strh(r6,[r3,2]) | |
strh(r5,[r3,4]) # move color to right | |
b(WATER) | |
label(TEST_RIGHT2) | |
ldrh(r4,[r3,4]) # r4 = right dest color | |
cmp(r4,0) | |
bne(TEST_LEFT2) | |
mov(r6,0) | |
strh(r6,[r3,2]) | |
strh(r5,[r3,4]) # move color to right | |
b(WATER) | |
label(TEST_LEFT2) | |
ldrh(r4,[r3,0]) # r4 = left dest color | |
cmp(r4,0) | |
bne(WATER) | |
mov(r6,0) | |
strh(r6,[r3,2]) | |
strh(r5,[r3,0]) # move color to left | |
b(WATER) | |
label(WATER_DONE) | |
sub(r1,1) | |
beq(EXIT) | |
b(LOOP_Y) | |
label(EXIT) | |
@micropython.asm_thumb | |
def water_rasm(r0): | |
mov(r1,239) # r1 = y | |
label(LOOP_Y) | |
mov(r7,255) # stack marker | |
push({r7}) | |
mov(r7,1) | |
mov(r2,r1) | |
and_(r2,r7) | |
bne(LEFT2RIGHT) | |
mov(r2,240) # max x | |
b(LOOP_X) | |
label(LEFT2RIGHT) | |
mov(r2,120) # r2 = x | |
label(LOOP_X) | |
mov(r3,240) # 240 | |
mul(r3,r1) # 240*y | |
add(r3,r3,r2) # 240*y+x | |
mov(r4,r3) | |
sub(r4,240) # -XMAX | |
add(r3,r3,r3) # double ldrh | |
add(r3,r3,r0) # r3 = dest addr | |
add(r4,r4,r4) # double ldrh | |
add(r4,r4,r0) # r4 = source addr | |
ldrh(r5,[r4,0]) # r5 = sourcecolor | |
cmp(r5,0) | |
beq(NEXT_X) # skip if source=0 | |
mov(r7,0x1) | |
lsl(r7,r7,16) | |
sub(r7,1) # 0xffff | |
cmp(r5,r7) | |
beq(NEXT_X) # skip if source=0xffff | |
ldrh(r6,[r3,0]) # r6=destcolor | |
cmp(r6,0) | |
beq(MOVEDOWN) # move down if dest=0 | |
mov(r7,255) | |
lsl(r7,r7,8) # 0xff00 water color | |
cmp(r7,r5) | |
beq(TRYPLUS1) # try move diag if source=water | |
cmp(r5,0xff) # 0x00ff=yellow | |
beq(YELLOW) | |
b(NEXT_X) | |
label(YELLOW) | |
cmp(r6,r7) # is dest water? | |
bne(TRYPLUS1) | |
strh(r7,[r4,0]) # source = 0 | |
strh(r5,[r3,0]) # dest = sourcecolor | |
b(NEXT_X) | |
label(MOVEDOWN) | |
mov(r6,0) | |
strh(r6,[r4,0]) # source = 0 | |
strh(r5,[r3,0]) # dest = sourcecolor | |
b(NEXT_X) | |
label(TRYPLUS1) | |
mov(r3,r4) # source | |
mov(r6,241) # 1 + MAX_X | |
add(r6,r6,r6) # double ldrh | |
add(r3,r3,r6) # source + 1 + MAX_X | |
ldrh(r6,[r3,0]) # r6=diag color | |
cmp(r6,0) | |
beq(DIAGRIGHT) | |
cmp(r6,0x0) # if empty move diag | |
beq(DIAGRIGHT) | |
cmp(r6,r7) # if water move diag | |
bne(TRYMINUS1) | |
cmp(r5,0xff) # if sand move diag | |
bne(TRYMINUS1) | |
label(DIAGRIGHT) # move diag to right | |
#mov(r6,0) | |
strh(r6,[r4,0]) # source = 0 | |
strh(r5,[r3,0]) # source + 1 + MAX_X = sourcecolor | |
b(NEXT_X) | |
label(TRYMINUS1) | |
sub(r3,4) # source-1+MAXSCREEN_X | |
ldrh(r6,[r3,0]) | |
cmp(r6,0) # is diag empty? | |
beq(DIAGLEFT) | |
cmp(r5,r7) # is source water | |
beq(SAVE_WATER) | |
cmp(r6,r7) # is dest water? | |
beq(DIAGLEFT) | |
b(SAVE_WATER) | |
label(DIAGLEFT) # move diag to left | |
strh(r6,[r4,0]) # source = 0 | |
strh(r5,[r3,0]) # source - 2 + MAX_X = sourcecolor | |
b(NEXT_X) | |
label(SAVE_WATER) | |
cmp(r5,0xff) # is sand? | |
beq(NEXT_X) | |
mov(r7,r2) | |
push({r7}) | |
label(NEXT_X) | |
mov(r7,1) | |
mov(r6,r1) | |
and_(r6,r7) | |
bne(LEFT2RIGHT1) | |
sub(r2,1) | |
cmp(r2,120) | |
bne(LOOP_X) | |
b(WATER) | |
label(LEFT2RIGHT1) | |
add(r2,1) | |
cmp(r2,240) # max x | |
bne(LOOP_X) | |
label(WATER) #------DO WATER LEFT/RIGHT---------- | |
pop({r7}) | |
cmp(r7,255) | |
beq(WATER_DONE) | |
add(r7,1) | |
mov(r4,r1) | |
sub(r4,1) | |
mov(r3,240) # 240 | |
mul(r3,r4) # 240*y | |
add(r3,r3,r7) # 240*y+x | |
sub(r3,2) # 240*y+x-2 | |
add(r3,r3,r3) # double ldrh | |
add(r3,r3,r0) # r3 = dest addr | |
ldrh(r5,[r3,2]) # r5 = source color | |
label(RANDOM) | |
align(4) | |
mov(r7,pc) | |
b(RANDBIT_ADDR) | |
data(2,0x001c,0x4006) | |
align(4) | |
label(RANDBIT_ADDR) | |
ldr(r7,[r7,0]) # get random addr | |
ldr(r7,[r7,0]) # get random bit | |
cmp(r7,1) # choose left/right first | |
beq(LEFT_FIRST) | |
b(TEST_RIGHT2) | |
label(LEFT_FIRST) | |
b(TEST_LEFT) | |
label(TEST_LEFT) | |
ldrh(r4,[r3,0]) # r4 = left dest color | |
cmp(r4,0) | |
bne(TEST_RIGHT) | |
mov(r6,0) | |
strh(r6,[r3,2]) | |
strh(r5,[r3,0]) # move color to left | |
b(WATER) | |
label(TEST_RIGHT) | |
ldrh(r4,[r3,4]) # r4 = right dest color | |
cmp(r4,0) | |
bne(WATER) | |
mov(r6,0) | |
strh(r6,[r3,2]) | |
strh(r5,[r3,4]) # move color to right | |
b(WATER) | |
label(TEST_RIGHT2) | |
ldrh(r4,[r3,4]) # r4 = right dest color | |
cmp(r4,0) | |
bne(TEST_LEFT2) | |
mov(r6,0) | |
strh(r6,[r3,2]) | |
strh(r5,[r3,4]) # move color to right | |
b(WATER) | |
label(TEST_LEFT2) | |
ldrh(r4,[r3,0]) # r4 = left dest color | |
cmp(r4,0) | |
bne(WATER) | |
mov(r6,0) | |
strh(r6,[r3,2]) | |
strh(r5,[r3,0]) # move color to left | |
b(WATER) | |
label(WATER_DONE) | |
sub(r1,1) | |
beq(EXIT) | |
b(LOOP_Y) | |
label(EXIT) | |
def core1(): | |
global DONE,screen,RIGHT | |
#print(hex(water_asm(screen))) | |
#exit() | |
i=0 | |
while i<150: | |
i+=1 | |
gticks=ticks_us() | |
if i==50: | |
screen.fill_rect(randint(0,220),0,20,20,0xff) #0x7c02) | |
if i==100: | |
screen.fill_rect(randint(0,220),0,20,20,0xff00) #0x7c02) | |
i=0 | |
screen.pixel(randint(0,240),0,0xff00) | |
screen.pixel(randint(90,95),0,0xff) | |
RIGHT=True | |
water_lasm(screen) | |
#if i==25 or i==50 or i==75 or i==99: | |
tft.blit_buffer(screen, 0, 0, MAXSCREEN_X, MAXSCREEN_Y) | |
fps=1_000_000//ticks_diff(ticks_us(), gticks) | |
print(fps) | |
DONE=True | |
@micropython.viper | |
def resize(): | |
screen_addr=ptr16(display_buffer) | |
text_addr=ptr16(text_buffer) | |
offset = 80*MAXSCREEN_X+10 | |
for y in range(8): | |
for x in range(60): | |
color=text_addr[y*80+x] | |
for ly in range(5): | |
for lx in range(5): | |
screen_addr[(ly+(5*y))*MAXSCREEN_X+(4*x)+lx+offset]=color | |
if __name__=='__main__': | |
spi = SPI(1, baudrate=80_000_000, sck=Pin(10), mosi=Pin(11)) | |
tft = gc9a01.GC9A01( | |
spi, | |
240, | |
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) | |
tft.inversion_mode(True) | |
bl_ctrl(100) | |
sleep(0.5) | |
screen=framebuf.FrameBuffer(display_buffer, MAXSCREEN_X , MAXSCREEN_Y, framebuf.RGB565) | |
txt=framebuf.FrameBuffer(text_buffer, 80 , 8, framebuf.RGB565) | |
txt.text('PI PICO',0,0,0xffff) | |
resize() | |
#blit_image_file('floor.bin',32,32*8) # width, height | |
gticks=ticks_us() | |
#wdt = WDT(timeout=8300) # Watchdog timer reset | |
#blocks() | |
#tft.blit_buffer(screen, 0, 0, MAXSCREEN_X, MAXSCREEN_Y) | |
#exit() | |
#screen.fill(0xff00) | |
screen.fill_rect(0,200,239,239,0xff00) | |
#screen.line(0,50,240,50,0xffff) | |
_thread.start_new_thread(core1, ()) | |
while not DONE: | |
if RIGHT: | |
RIGHT=False | |
water_rasm(screen) | |
exit() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment