Skip to content
Snippets Groups Projects
Commit 8d6281b6 authored by iggy's avatar iggy
Browse files

added uctx, not building yet

parent 48bfbdcd
No related branches found
No related tags found
No related merge requests found
Showing
with 33071 additions and 0 deletions
...@@ -15,3 +15,6 @@ target_include_directories(usermod_badge23 INTERFACE ...@@ -15,3 +15,6 @@ target_include_directories(usermod_badge23 INTERFACE
) )
target_link_libraries(usermod INTERFACE usermod_badge23) target_link_libraries(usermod INTERFACE usermod_badge23)
#include(${CMAKE_CURRENT_LIST_DIR}/uctx/uctx/micropython.cmake)
*.sw*
binaries
The MIT License (MIT)
Copyright (c) 2020-2022 Øyvind Kolås
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
--------------------------------------------------------------------------------
Unless specified otherwise (see below), the above license and copyright applies
to all files in this repository.
Individual files may include additional copyright holders.
The various ports of MicroPython may include third-party software that is
licensed under different terms. These licenses are summarised in the tree
below, please refer to these files and directories for further license and
copyright information. Note that (L)GPL-licensed code listed below is only
used during the build process and is not part of the compiled source code.
/ (MIT)
/drivers
/cc3000 (BSD-3-clause)
/cc3100 (BSD-3-clause)
/wiznet5k (BSD-3-clause)
/lib
/asf4 (Apache-2.0)
/axtls (BSD-3-clause)
/config
/scripts
/config (GPL-2.0-or-later)
/Rules.mak (GPL-2.0)
/berkeley-db-1xx (BSD-4-clause)
/btstack (See btstack/LICENSE)
/cmsis (BSD-3-clause)
/crypto-algorithms (NONE)
/libhydrogen (ISC)
/littlefs (BSD-3-clause)
/lwip (BSD-3-clause)
/mynewt-nimble (Apache-2.0)
/nrfx (BSD-3-clause)
/nxp_driver (BSD-3-Clause)
/oofatfs (BSD-1-clause)
/pico-sdk (BSD-3-clause)
/re15 (BSD-3-clause)
/stm32lib (BSD-3-clause)
/tinytest (BSD-3-clause)
/tinyusb (MIT)
/uzlib (Zlib)
/logo (uses OFL-1.1)
/ports
/cc3200
/hal (BSD-3-clause)
/simplelink (BSD-3-clause)
/FreeRTOS (GPL-2.0 with FreeRTOS exception)
/stm32
/usbd*.c (MCD-ST Liberty SW License Agreement V2)
/stm32_it.* (MIT + BSD-3-clause)
/system_stm32*.c (MIT + BSD-3-clause)
/boards
/startup_stm32*.s (BSD-3-clause)
/*/stm32*.h (BSD-3-clause)
/usbdev (MCD-ST Liberty SW License Agreement V2)
/usbhost (MCD-ST Liberty SW License Agreement V2)
/teensy
/core (PJRC.COM)
/zephyr
/src (Apache-2.0)
/tools
/dfu.py (LGPL-3.0-only)
#!/usr/bin/env uctx
import uimui
exit=False
while not exit:
uimui.start_frame()
uimui.label("foo")
valid_red=(0,40,80,140,174,209,233,255) # 176
valid_green=(0,40,80,140,174,209,233,255) # 176
valid_blue=(0,80,140,255)
ctx = uimui.get_ctx()
y = 0
x = 0
dim = ctx.width / (36)
for green in valid_green:
for red in valid_red:
for blue in valid_blue:
real_blue = blue | (green &31) # mix in low bits of green
ctx.rectangle(x, y, dim, dim).rgb(red/255,green/255,real_blue/255).fill()
x += dim
if x + dim >= ctx.width:
x = 0
y += dim
if uimui.button("X", x= 0, y =0, width = ctx.width/10):
exit = True
uimui.end_frame()
#!/usr/bin/env uctx
import canvas
import micropython
import gc
class Calculator:
def __init__(self):
True
def foo(self):
print("fooed")
calc=Calculator()
calc.foo()
ctx=canvas.ctx
o=ctx
ctx.flags = ctx.HASH_CACHE | ctx.INTRA_UPDATE
pointer_x = 0
pointer_y = 0
pointer_down = False
pointer_was_down = False
widget_font_size_vh = 0.12
widget_bg=[70/255,70/255,90/255]
widget_fg=[1.0,1.0,1.0]
widget_marker=[1.0,0,0]
widget_fs=0.1
button_bg=widget_bg
button_fg=widget_fg
button_bg_active=widget_bg#[200,20,100]
def inside_rect(u,v,x,y,w,h):
if u >= x and u < x + w and v >= y and v < y + h:
return True
return False
def button(x, y, w, h, label):
global pointer_down, pointer_was_down
result = False
ctx.font_size = ctx.height * widget_font_size_vh # why do we need this override
lwidth = ctx.text_width (label)
ctx.rectangle(x, y, w, h)
ctx.rgb(*button_bg)
if pointer_down and pointer_was_down == False and inside_rect(pointer_x,pointer_y,x,y,w,h):
result = True
ctx.rgb(*button_bg_active)
ctx.fill()
ctx.rgb(*button_fg)
ctx.move_to(x + w/2-lwidth/2, y + h/2 + ctx.font_size/3)
ctx.text(label)
return result
def toggle(x, y, w, h, label, value):
global pointer_down, pointer_was_down
result = value
ctx.font_size = ctx.height * widget_font_size_vh # why do we need this override
if pointer_down and pointer_was_down == False and inside_rect(pointer_x,pointer_y,x,y,w,h):
result = not value
ctx.rectangle(x, y, w, h).rgb(*button_bg_active).fill()
ctx.rgb(*widget_fg)
ctx.move_to(x + ctx.font_size*0.1, y + ctx.font_size*0.8)
ctx.text(label)
ctx.save()
ctx.text_align=ctx.RIGHT
ctx.move_to(x+w,y+ctx.font_size*0.8)
if value:
ctx.text("on")
else:
ctx.text("off")
ctx.restore()
return value
def coords_press(x, y):
global pointer_x, pointer_y, pointer_down
pointer_x = x
pointer_y = y
pointer_down = True
def coords_motion(x, y):
global pointer_x, pointer_y
pointer_x = x
pointer_y = y
def coords_release(x, y):
global pointer_x, pointer_y, pointer_down
pointer_x = x
pointer_y = y
pointer_down = False
exit = False
need_clear = True
frame_no = 0
value = 0
accumulator = 0
op = ""
in_decimal = 0 # higher than zero means were in decimals at that digit
hex_mode = False
def compute_op():
global need_clear,value, accumulator, op, in_decimals
if op == '+':
value = accumulator + value
accumulator = 0
if op == '-':
value = accumulator - value
accumulator = 0
if op == 'x':
value = accumulator * value
accumulator = 0
if op == '/':
if value != 0.0:
value = accumulator / value
else:
value = -0.0
accumulator = 0
op = ''
need_clear = True
def calc_loop():
global hex_mode,need_clear,value, accumulator, in_decimal, op, exit, pointer_was_down, pointer_down
bw = ctx.width * 0.13
bh = ctx.height * 0.19
bsx = ctx.width * 0.14
bsy = ctx.height * 0.2
ctx.start_frame()
ctx.translate(0,20)
ctx.rectangle(0,0,ctx.width, ctx.height)#,ctx.height)
o.listen(o.PRESS, lambda e:coords_press(e.x, e.y))
o.listen(o.MOTION, lambda e:coords_motion(e.x, e.y))
o.listen(o.RELEASE, lambda e:coords_release(e.x, e.y))
ctx.gray(0).fill()
ctx.font_size = ctx.height * widget_font_size_vh
ctx.rgb(*widget_fg)
ctx.text_align = ctx.RIGHT
ctx.move_to(bsx*6,ctx.font_size*0.8)
if hex_mode:
value = int(value)
ctx.text(hex(value))
else:
ctx.text(str(value))
ctx.text_align = ctx.LEFT
if accumulator != 0:
ctx.move_to(0,ctx.font_size*0.8)
ctx.text(str(accumulator) + " " + op)
for digit in range(1,10):
if button((((digit-1)%3)+1) * bsx, (3-int((digit-1)/3)) * bsy, bw, bh, str(digit)):
if need_clear:
value = 0
need_clear = False
if in_decimal>0:
value = value + 1.0/pow(10,in_decimal)*digit
in_decimal+=1
else:
value = value * 10 + digit
if button(0 * bsx, 3 * bsy, bw, bh, "0"):
if need_clear:
value = 0
need_clear = False
if in_decimal>0:
value = value + 0.0
else:
value = value * 10 + 0
if button(0 * bsx, 2 * bsy, bw, bh, "."):
in_decimal = 1
if button(4 * bsx, 3 * bsy, bw * 1.5, bh, "="):
compute_op()
if button(5 * bsx, 1 * bsy, bw, bh, "/"):
compute_op()
accumulator = value
value = 0
op = "/"
in_decimal = 0
if button(6 * bsx, 2 * bsy, bw, bh, "sqrt"):
value = pow(value, 0.5)
op = ""
need_clear = 1
in_decimal = 0
if hex_mode:
if button(6 * bsx, 1 * bsy, bw, bh, "hex"):
hex_mode = False
else:
if button(6 * bsx, 1 * bsy, bw, bh, "dec"):
hex_mode = True
if button(5.5 * bsx, 3 * bsy, 1.5 * bw, bh, "C"):
value = 0
accumulator = 0
in_decimal = 0
if button(4 * bsx, 2 * bsy, bw, bh, "+"):
compute_op()
accumulator = value
value = 0
op = "+"
in_decimal = 0
if button(5 * bsx, 2 * bsy, bw, bh, "x"):
compute_op()
accumulator = value
value = 0
op = "x"
in_decimal = 0
if button(4 * bsx, 1 * bsy, bw, bh, "-"):
compute_op()
accumulator = value
value = 0
op = "-"
in_decimal = 0
if button(0, 1 * bsy, bw, bh, "q"):
exit = True
#ctx.rectangle(pointer_x-2, pointer_y-2, 4, 4).color([255,0,0]).fill()
pointer_was_down = pointer_down # must happen after all the buttons
#micropython.mem_info()
ctx.end_frame()
gc.collect()
import micropython
while not exit:
calc_loop()
#micropython.mem_info(1)
#!/usr/bin/env uctx
import os
import sys
import ctx as modctx
_ctx = None
# this is the function exposed to the outside
def get_ctx():
global _ctx
if _ctx != None: # we try to only run once
return _ctx
if sys.platform == 'linux':
_ctx = unix_get_ctx ()
elif sys.platform == 'javascript':
_ctx = wasm_get_ctx ()
else:
print('you need to configure a display config for ctx in canvas.py')
#_ctx = rp_pico_waveshare_240x240_joystick()
_ctx = rp_pico_waveshare_480x320_res_touch()
#_ctx = rp_pico_waveshare_240x320_res_touch()
#_ctx = esp32_waveshare_320x240()
#_ctx = dummy_get_ctx ()
return _ctx
# The canvas module provides backend integration and configuration for
# ctx, by importing canvas.
scratch_size = 53 * 1024
# for the cb backend used on microcontrollers, how much heap
# to use for a scratch compositing buffer.
# For a 480x320 display:
# 14kb is enough for 2x2 GRAY2
# 5x5 LOWRES
# 23kb is enough for 2x2 GRAY4
# 3x3 RGB332
# 4x4 LOWRES
# 1x1 GRAY1 (not currently available)
# 42kb is enough for 2x2 RGB332
# 1x1 GRAY2
# 3x3 LOWRES
canvas_flags = modctx.INTRA_UPDATE|modctx.LOWFI
# the default flags the cb backend gets initialized with
# possible values:
# INTRA_UPDATE : call the event handling between renders in hifi mode
# HASH_CACHE : keep track of rendered content and only re-render changed areas
# LOWFI : do preview rendering with RGB565
# RGB332 : trade color fidelity for higher res preview
# GRAY8 : full grayscale
# GRAY4 : 16 level gray
# GRAY2 : 4 level gray
# CBRLE : constant bitrate RLE
# when non-zero override board default
canvas_width = 0
canvas_height = 0
##### end of basic configuration ###########
############################################
############################################
pointer_down = False
pointer_x = 0
pointer_y = 0
# this is currently used by one of the backends
# adding gpio based input for more boards should
# follow the same pattern
keys={}
key_state={}
def get_pin_events(ctx):
ret = False
for name,pin in keys.items():
if pin.value()== 0:
if key_state[name] != 0:
key_state[name]=0
ctx.key_down(0, name, 0)
ctx.key_press(0, name, 0)
ret = True
else:
if key_state[name] != 1:
ctx.key_up(0, name, 0)
key_state[name]=1
ret = True
return ret
def rp_waveshare_240x240_joystick():
import machine
from machine import Pin,SPI,PWM
global keys,key_state,canvas_width, canvas_height
machine.freq(266_000_000)
keys['a']= Pin(15,Pin.IN,Pin.PULL_UP)
keys['b'] = Pin(17,Pin.IN,Pin.PULL_UP)
keys['x'] = Pin(19 ,Pin.IN,Pin.PULL_UP)
keys['y'] = Pin(21 ,Pin.IN,Pin.PULL_UP)
keys['up'] = Pin(2,Pin.IN,Pin.PULL_UP)
keys['down'] = Pin(18,Pin.IN,Pin.PULL_UP)
keys['left'] = Pin(16,Pin.IN,Pin.PULL_UP)
keys['right'] = Pin(20,Pin.IN,Pin.PULL_UP)
keys['space'] = Pin(3,Pin.IN,Pin.PULL_UP)
for key,value in keys.items():
key_state[key]=1
import lcd13
import machine
display=lcd13.LCD_1inch3()
if canvas_width == 0:
canvas_width = 240
if canvas_height == 0:
canvas_height = 240
ret_ctx = modctx.Context(
width=canvas_width,
height=canvas_height,
format=modctx.RGB565_BYTESWAPPED,
# function to update a subregion of target framebuffer using prepared buf
# with appropriate stride
set_pixels=lambda x, y, w, h, buf: display.blit_buffer(buf, x, y, w, h),
update=lambda:get_pin_events (ret_ctx),
memory_budget=scratch_size,
flags=canvas_flags)
return ret_ctx
def update_events(lcd):
global pointer_down, pointer_x, pointer_y
touch=lcd.touch_get()
if(touch):
pointer_x=touch[0]
pointer_y=touch[1]
if not pointer_down:
_ctx.pointer_press(pointer_x,pointer_y, 0, 0)
else:
_ctx.pointer_motion(pointer_x,pointer_y, 0, 0)
pointer_down = True
return True # abort rendering if in slow refresh
else:
if pointer_down:
_ctx.pointer_release(pointer_x,pointer_y, 0, 0)
pointer_down = False
return True
return False
def rp_pico_waveshare_480x320_res_touch():
global canvas_width, canvas_height
import ililcd
lcd=ililcd.LCD()#480, 320, 15, 8, 9, 10, 11, 12, 13)
if canvas_width == 0:
canvas_width = 480
if canvas_height == 0:
canvas_height = 320
return modctx.Context(
width=canvas_width,
height=canvas_height,
# the format specified here is the format of the lcd
# not neccesarily the format used for rendering
format=modctx.RGB565_BYTESWAPPED,
# function to update a subregion of target framebuffer using prepared buf
# with appropriate stride
set_pixels=lambda x, y, w, h, buf: lcd.blit_buffer(buf, x, y, w, h),
# callback to be invoked in between batches of render+blit
# if True is returned progressive updates are aborted
# this is where touch events and button presses should be fed
# to ctx
update=lambda : update_events(lcd),
memory_budget=scratch_size,
flags=canvas_flags)
def dummy_get_ctx():
global canvas_width, canvas_height
if canvas_width == 0:
canvas_width = 240
if canvas_height == 0:
canvas_height = 240
return modctx.Context(
width=canvas_width,
height=canvas_height,
format=modctx.RGB565_BYTESWAPPED,
# function to update a subregion of target framebuffer using prepared buf
# with appropriate stride
set_pixels = lambda x, y, w, h, buf: True,
update= lambda : False,
memory_budget=scratch_size,
flags=canvas_flags)
def esp32_waveshare_320x240():
import st7789py
import machine
machine.freq(240_000_000) # we want full tilt!
spi = machine.SPI(2, baudrate=40000000, polarity=1)
display = st7789py.ST7789(
spi, 240, 320,
reset=machine.Pin(17, machine.Pin.OUT),
dc=machine.Pin(16, machine.Pin.OUT),
cs=machine.Pin(5, machine.Pin.OUT),
xstart=0,ystart=0
)
display.init()
display.inversion_mode(False)
if canvas_width == 0:
canvas_width = 240
if canvas_height == 0:
canvas_height = 320
return modctx.Context(
width=canvas_width,
height=canvas_height,
format=modctx.RGB565_BYTESWAPPED,
# function to update a subregion of target framebuffer using prepared buf
# with appropriate stride
set_pixels = lambda x, y, w, h, buf: display.blit_buffer(buf, x, y, w, h),
update= lambda : False,
memory_budget=scratch_size,
flags=canvas_flags)
def rp_pico_waveshare_240x320_res_touch():
global canvas_width, canvas_height
import st7789py
import time, machine
machine.Pin(13,machine.Pin.OUT).low()
spi = machine.SPI(1, baudrate=50000000, phase=1,polarity=1)
display = st7789py.ST7789(spi, 240, 320,
reset=machine.Pin(15, machine.Pin.OUT),
backlight=machine.Pin(13, machine.Pin.OUT),
sck=10,#machine.Pin(10, machine.Pin.OUT),
mosi=11,
miso=12,
dc=machine.Pin(8, machine.Pin.OUT),
cs=machine.Pin(9, machine.Pin.OUT),xstart=0,ystart=0,tp_irq=17,tp_cs=18)
display.init()
if canvas_width == 0:
canvas_width = 240
if canvas_height == 0:
canvas_height = 320
return modctx.Context(
width=canvas_width,
height=canvas_height,
format=modctx.RGB565_BYTESWAPPED,
# function to update a subregion of target framebuffer using prepared buf
# with appropriate stride
set_pixels=lambda x, y, w, h, buf: display.blit_buffer(buf, x, y, w, h),
update = lambda : update_events(display),
memory_budget=scratch_size,
flags=canvas_flags)
def reset_terminal():
os.system('reset')
def unix_get_ctx(): # perhaps turn this into an attribute of the module?
print("\e[H\e[2J")
sys.atexit(reset_terminal)
return modctx.Context()
def wasm_get_ctx():
ctx = modctx.Context(memory_budget=scratch_size)
ctx.flags=canvas_flags
return ctx
def __getattr__(name):
if name == 'ctx2d':
return get_ctx()
elif name == 'ctx':
return get_ctx()
elif name == 'width':
return get_ctx().width
elif name == 'height':
return get_ctx().height
raise AttributeError("module '{__name__}' has no attribute '{name}'")
if __name__=='__main__':
ctx = get_ctx()
frames=60
for frame in range(0,frames):
ctx.start_frame()
ctx.rgb(50/255,50/255,30/255).rectangle(0,0,ctx.width,ctx.height).fill()
dim = ctx.height * frame / (frames-2.0)
if frame >= frames-2:
dim = ctx.height
ctx.logo(ctx.width/2,ctx.height/2, dim)
ctx.end_frame()
#!/usr/bin/env uctx
import canvas
ctx = canvas.get_ctx()
ctx.flags=0
frames=400
for frame in range(0,frames):
ctx.start_frame()
ctx.rgb(50/255,50/255,30/255).rectangle(0,0,ctx.width,ctx.height).fill()
dim = ctx.height * frame / (frames-2.0)
ctx.rgb(1.0,1.0,1.0)
ctx.font_size= ctx.height * 0.15
ctx.save()
ctx.translate(0,-frame/frames * ctx.height *2.5)
ctx.move_to(0,ctx.height)
ctx.rgba(1.0,0.0,0.0, .85)
for font in ('Sans','Regular',
'Sans Bold','Bold',
"Courier Italic",
'Times',
'Mono',
'Arial Bold',
'Foobar Bold Italic',
'Helvetica Bold',
'Mono Bold',
'Mono Italic',
'Bold Italic',
'Times Italic'):
ctx.font=font
ctx.text(font+'\n')
ctx.rgba(1.0,1.0,1.0, .85)
font_no = 0
while ctx.get_font_name(font_no) != None:
font = ctx.get_font_name(font_no)
font_no+=1
ctx.font=font
ctx.text(font+"\n")
dim=ctx.height
ctx.restore()
ctx.end_frame()
from machine import Pin,SPI,PWM
import framebuf
import time
import os
LCD_DC = 8
LCD_CS = 9
LCD_SCK = 10
LCD_MOSI = 11
LCD_MISO = 12
LCD_BL = 13
LCD_RST = 15
TP_CS = 16
TP_IRQ = 17
class LCD():
def __init__(self):
self.RED = 0x07E0
self.GREEN = 0x001f
self.BLUE = 0xf800
self.WHITE = 0xffff
self.BLACK = 0x0000
self.width = 480
self.height = 160
self.cs = Pin(LCD_CS,Pin.OUT)
self.rst = Pin(LCD_RST,Pin.OUT)
self.dc = Pin(LCD_DC,Pin.OUT)
self.tp_cs =Pin(TP_CS,Pin.OUT)
self.irq = Pin(TP_IRQ,Pin.IN)
self.cs(1)
self.dc(1)
self.rst(1)
self.tp_cs(1)
self.spi = SPI(1,60_000_000,sck=Pin(LCD_SCK),mosi=Pin(LCD_MOSI),miso=Pin(LCD_MISO))
self.init_display()
def write_cmd(self, cmd):
self.cs(1)
self.dc(0)
self.cs(0)
self.spi.write(bytearray([cmd]))
self.cs(1)
def write_data(self, buf):
self.cs(1)
self.dc(1)
self.cs(0)
#self.spi.write(bytearray([0X00]))
self.spi.write(bytearray([buf]))
self.cs(1)
def init_display(self):
"""Initialize dispaly"""
self.rst(1)
time.sleep_ms(5)
self.rst(0)
time.sleep_ms(10)
self.rst(1)
time.sleep_ms(5)
self.write_cmd(0x21)
self.write_cmd(0xC2)
self.write_data(0x33)
self.write_cmd(0XC5)
self.write_data(0x00)
self.write_data(0x1e)
self.write_data(0x80)
self.write_cmd(0xB1)
self.write_data(0xB0)
self.write_cmd(0x36)
self.write_data(0x28)
self.write_cmd(0XE0)
self.write_data(0x00)
self.write_data(0x13)
self.write_data(0x18)
self.write_data(0x04)
self.write_data(0x0F)
self.write_data(0x06)
self.write_data(0x3a)
self.write_data(0x56)
self.write_data(0x4d)
self.write_data(0x03)
self.write_data(0x0a)
self.write_data(0x06)
self.write_data(0x30)
self.write_data(0x3e)
self.write_data(0x0f)
self.write_cmd(0XE1)
self.write_data(0x00)
self.write_data(0x13)
self.write_data(0x18)
self.write_data(0x01)
self.write_data(0x11)
self.write_data(0x06)
self.write_data(0x38)
self.write_data(0x34)
self.write_data(0x4d)
self.write_data(0x06)
self.write_data(0x0d)
self.write_data(0x0b)
self.write_data(0x31)
self.write_data(0x37)
self.write_data(0x0f)
self.write_cmd(0X3A)
self.write_data(0x55)
self.write_cmd(0x11)
time.sleep_ms(120)
self.write_cmd(0x29)
self.write_cmd(0xB6)
self.write_data(0x00)
self.write_data(0x62)
self.write_cmd(0x36)
self.write_data(0x28)
def blit_buffer(self, buffer,x,y,w,h):
self.write_cmd(0x2A)
self.write_data(int(x/256))
self.write_data(int(x&255))
self.write_data(int((x+w-1)/256))
self.write_data(int((x+w-1)&255))
self.write_cmd(0x2B)
self.write_data(int(y/256))
self.write_data(int(y&255))
self.write_data(int((y+h-1)/256))
self.write_data(int((y+h-1)&255))
self.write_cmd(0x2C)
self.cs(1)
self.dc(1)
self.cs(0)
self.spi.write(buffer)
self.cs(1)
def bl_ctrl(self,duty):
pwm = PWM(Pin(LCD_BL))
pwm.freq(1000)
if(duty>=100):
pwm.duty_u16(65535)
else:
pwm.duty_u16(655*duty)
def touch_get(self):
if self.irq() == 0:
self.spi = SPI(1,5_000_000,sck=Pin(LCD_SCK),mosi=Pin(LCD_MOSI),miso=Pin(LCD_MISO))
self.tp_cs(0)
X_Point = 0
Y_Point = 0
for i in range(0,3):
self.spi.write(bytearray([0XD0]))
Read_date = self.spi.read(2)
time.sleep_us(10)
Y_Point=Y_Point+(((Read_date[0]<<8)+Read_date[1])>>3)
self.spi.write(bytearray([0X90]))
Read_date = self.spi.read(2)
X_Point=X_Point+(((Read_date[0]<<8)+Read_date[1])>>3)
X_Point=X_Point/3
Y_Point=Y_Point/3
self.tp_cs(1)
self.spi = SPI(1,60_000_000,sck=Pin(LCD_SCK),mosi=Pin(LCD_MOSI),miso=Pin(LCD_MISO))
X_Point = int((X_Point-430)*480/3270)
if(X_Point>480):
X_Point = 480
elif X_Point<0:
X_Point = 0
Y_Point = 320-int((Y_Point-430)*320/3270)
Result_list = [X_Point,Y_Point]
#print(Result_list)
return(Result_list)
from machine import Pin,SPI,PWM
import framebuf
import time
import os
BL = 13
DC = 8
RST = 12
MOSI = 11
SCK = 10
CS = 9
class LCD_1inch3():#framebuf.FrameBuffer):
def __init__(self):
pwm = PWM(Pin(BL))
pwm.freq(1000)
pwm.duty_u16(int(65535*0.3))#max 65535
self.width = 240
self.height = 240
self.cs = Pin(CS,Pin.OUT)
self.rst = Pin(RST,Pin.OUT)
self.cs(1)
self.spi = SPI(1,80_000_000,polarity=0, phase=0,sck=Pin(SCK),mosi=Pin(MOSI),miso=None)
self.dc = Pin(DC,Pin.OUT)
self.dc(1)
self.init_display()
def write_cmd(self, cmd):
self.cs(1)
self.dc(0)
self.cs(0)
self.spi.write(bytearray([cmd]))
self.cs(1)
def write_data(self, buf):
self.cs(1)
self.dc(1)
self.cs(0)
self.spi.write(bytearray([buf]))
self.cs(1)
def init_display(self):
"""Initialize dispaly"""
self.rst(1)
self.rst(0)
self.rst(1)
self.write_cmd(0x36)
self.write_data(0x70)
self.write_cmd(0x3A)
self.write_data(0x05)
self.write_cmd(0xB2)
self.write_data(0x0C)
self.write_data(0x0C)
self.write_data(0x00)
self.write_data(0x33)
self.write_data(0x33)
self.write_cmd(0xB7)
self.write_data(0x35)
self.write_cmd(0xBB)
self.write_data(0x19)
self.write_cmd(0xC0)
self.write_data(0x2C)
self.write_cmd(0xC2)
self.write_data(0x01)
self.write_cmd(0xC3)
self.write_data(0x12)
self.write_cmd(0xC4)
self.write_data(0x20)
self.write_cmd(0xC6)
self.write_data(0x0F)
self.write_cmd(0xD0)
self.write_data(0xA4)
self.write_data(0xA1)
self.write_cmd(0xE0)
self.write_data(0xD0)
self.write_data(0x04)
self.write_data(0x0D)
self.write_data(0x11)
self.write_data(0x13)
self.write_data(0x2B)
self.write_data(0x3F)
self.write_data(0x54)
self.write_data(0x4C)
self.write_data(0x18)
self.write_data(0x0D)
self.write_data(0x0B)
self.write_data(0x1F)
self.write_data(0x23)
self.write_cmd(0xE1)
self.write_data(0xD0)
self.write_data(0x04)
self.write_data(0x0C)
self.write_data(0x11)
self.write_data(0x13)
self.write_data(0x2C)
self.write_data(0x3F)
self.write_data(0x44)
self.write_data(0x51)
self.write_data(0x2F)
self.write_data(0x1F)
self.write_data(0x1F)
self.write_data(0x20)
self.write_data(0x23)
self.write_cmd(0x21)
self.write_cmd(0x11)
self.write_cmd(0x29)
def blit_buffer(self, buffer,x,y,w,h):
self.write_cmd(0x2A)
self.write_data(int(x/256))
self.write_data(int(x&255))
self.write_data(int((x+w-1)/256))
self.write_data(int((x+w-1)&255))
self.write_cmd(0x2B)
self.write_data(int(y/256))
self.write_data(int(y&255))
self.write_data(int((y+h-1)/256))
self.write_data(int((y+h-1)&255))
self.write_cmd(0x2C)
self.cs(1)
self.dc(1)
self.cs(0)
self.spi.write(buffer)
self.cs(1)
#!/usr/bin/env uctx
# If you are reading this on the web, this file is probably part of your
# persistent micropython filsystem on this URL (stored in your browser).
# as part of a rapid protoyping environment.
#
# main.py and canvas.py are copied afresh from the server on each reload, if
# canvas.py is missing all the preloaded contents are brought back. Navigate
# filesystem in dropdown, create files and folders by specifying paths to save.
#
# press ctrl+return to run code
#
import canvas # this contains the python configuration to create a context
import io,os,gc,time,sys
ctx=canvas.ctx
clientflags = ctx.flags # the flags used for launching clients
# override client flags
clientflags = ctx.HASH_CACHE | ctx.RGB332
# and set the flags specific for the launcher
ctx.flags |= ctx.HASH_CACHE | ctx.GRAY4
light_red=(255/255,80/255,80/255)
white=(1.0,1.0,1.0)
black=(0,0,0)
dark_gray=(80/255,80/255,80/255)
light_gray=(170/255,170/255,170/255)
wallpaper_bg = black
document_bg = white
document_fg = black
toolbar_bg = dark_gray
toolbar_fg = white
button_bg = dark_gray
button_fg = white
dir_selected_bg = white
dir_selected_fg = black
dir_entry_fg = white
scrollbar_fg = dark_gray
button_height_vh = 0.33
button_width_vh = 0.3
font_size_vh = 0.11
if ctx.width < ctx.height:
font_size_vh = 0.06
button_width_vh = 0.2
cur = 0
def set_cur(event, no):
global cur
cur=no
return 0
maxframe=10
def linear(start_val,end_val):
return (frame/maxframe)*(end_val-start_val)+start_val
def mbutton(ctx, x, y, label, cb, user_data):
ctx.save()
ctx.font_size *= 0.75
ctx.translate(x, y)
ctx.begin_path().rectangle(0,0, ctx.height*button_width_vh * 0.95, ctx.height * button_height_vh * 0.95)
ctx.listen_stop_propagate(ctx.PRESS, lambda e:cb(e, e.user_data), user_data)
ctx.rgb(*button_bg).fill()
ctx.rgb(*button_fg).move_to(ctx.font_size/3, ctx.height * button_height_vh / 2).text(label)
ctx.restore()
def mbutton_thin(ctx, x, y, label, cb, user_data):
ctx.save()
ctx.font_size *= 0.8
ctx.translate(x, y)
ctx.begin_path().rectangle(0,0, ctx.height*button_width_vh * 0.95, ctx.font_size * 3)
ctx.listen_stop_propagate(ctx.PRESS, lambda e:cb(e, e.user_data), user_data)
ctx.begin_path().rectangle(0,0, ctx.height*button_width_vh * 0.95, ctx.font_size)
ctx.rgb(*button_bg).fill()
ctx.rgb(*button_fg).move_to(ctx.font_size/3, ctx.font_size*0.8).text(label)
ctx.restore()
response = False
def respond(val):
global response
response = val
more_actions=False
def show_more_cb(event, userdata):
global more_actions
more_actions = True
#event.stop_propagate=1
def hide_more_cb(userdata):
global more_actions
more_actions = False
#event.stop_propagate=1
def remove_cb(event, path):
global more_actions
os.remove(path)
more_actions = False
#event.stop_propagate=1
offset=0
def drag_cb(event):
global offset
offset -=event.delta_y/(font_size_vh*ctx.height) #20.0
view_file=""
run_file=False
frame_no = 0
def run_cb(event, path):
global run_file
run_file = path
def view_cb(event, path):
global view_file, offset
offset = 0
view_file = path
#event.stop_propagate=1
def space_cb(event):
run_cb(None, current_file)
print(event.string)
def up_cb(event):
global cur
cur -= 1
if cur <= 0:
cur = 0
def down_cb(event):
global cur
cur += 1
def exit_cb(event):
global main_exit
main_exit = True
import micropython
def dir_view(ctx):
global cur,frame_no,current_file,offset
frame_no += 1
# if cur > 4:
#gc.collect()
ctx.start_frame()
#micropython.mem_info()
ctx.add_key_binding("space", "", "", space_cb)
ctx.add_key_binding("up", "", "", up_cb)
ctx.add_key_binding("down", "", "", down_cb)
ctx.add_key_binding("q", "", "", exit_cb)
ctx.font_size=ctx.height*font_size_vh#32
if (offset ) < cur - (ctx.height/ctx.font_size) * 0.75:
offset = cur - (ctx.height/ctx.font_size)*0.42
if (offset ) > cur - (ctx.height/ctx.font_size) * 0.2:
offset = cur - (ctx.height/ctx.font_size)*0.42
if offset < 0:
offset = 0
y = ctx.font_size - offset * ctx.font_size
no = 0
ctx.rectangle(0,0,ctx.width,ctx.height).rgb(0.0,0.0,0.0).fill()
#ctx.listen(ctx.MOTION, drag_cb)
#ctx.begin_path()
current_file = ""
if hasattr(os, 'listdir'):
file_list = os.listdir('/')
else:
file_list = []
for f in os.ilistdir('/'):
file_list.append(f[0])
file_list.sort()
for file in file_list:
if file[0] != '.':
ctx.rectangle(ctx.height * button_width_vh * 1.2,y-ctx.font_size*0.75,
ctx.width - ctx.height * button_width_vh * 1.2, ctx.font_size)
if no == cur:
ctx.rgb(*dir_selected_bg)
current_file = file
ctx.fill()
ctx.rgb(*dir_selected_fg)
else:
ctx.listen(ctx.PRESS, lambda e:set_cur(e, e.user_data), no)
ctx.begin_path()
ctx.rgb(*dir_entry_fg)
ctx.move_to(ctx.height * button_width_vh * 1.2 + ctx.font_size * 0.1,y)
ctx.text(file)
y += ctx.font_size
no += 1
mbutton(ctx, 0, 0,
"view", view_cb, current_file)
mbutton(ctx, 0, ctx.height * button_height_vh,
"run", run_cb, current_file)
mbutton(ctx, 0, ctx.height - ctx.height * button_height_vh * 1,
"...", show_more_cb, current_file)
if more_actions:
ctx.rectangle(60,0,ctx.width,ctx.height)
ctx.listen_stop_propagate(ctx.PRESS, hide_more_cb)
mbutton(ctx, ctx.width-ctx.height * button_width_vh, ctx.height - ctx.height * button_height_vh * 1, "remove", remove_cb, current_file)
if frame_no > 1000:
ctx.save()
global_alpha=((frame_no-32)/50.0)
if global_alpha > 1.0:
global_alpha = 1.0
elif global_alpha < 0:
global_alpha = 0.0
ctx.global_alpha = global_alpha
ctx.logo(ctx.width - 32,ctx.height-32,64)
ctx.restore()
ctx.end_frame()
def scrollbar_cb(event):
global offset
factor = (event.y - ctx.font_size * 1.5) / (ctx.height-ctx.font_size*2);
if factor < 0.0:
factor = 0.0
if factor > 1.0:
factor = 1.0
offset = factor * event.user_data
def prev_page_cb(event):
global offset
offset -= ((ctx.height / ctx.font_size) - 2)
def next_page_cb(event):
global offset
offset += ((ctx.height / ctx.font_size) - 2)
def file_view(ctx):
global offset
gc.collect()
ctx.start_frame()
ctx.save()
ctx.font_size = ctx.height * font_size_vh
#offset += 0.25
ctx.rectangle(0,0,ctx.width,ctx.height)
#ctx.listen(ctx.MOTION, drag_cb)
ctx.rgb(*document_bg).fill()
ctx.rgb(*document_fg)
ctx.translate(0,(int(offset)-offset) * ctx.font_size)
ctx.move_to(0, ctx.font_size*0.8 * 2)
line_no = 0
ctx.font="mono";
y = ctx.font_size * 0.8 * 2
with open(view_file,'r') as file:
for line in file:
if line_no > offset and y - ctx.font_size < ctx.height:
ctx.move_to (0, int(y))
for word in line.split():
ctx.move_to(int(ctx.x), int(ctx.y))
ctx.text(word + ' ')
y+=ctx.font_size
line_no += 1
ctx.restore()
ctx.save()
ctx.rgb(*toolbar_bg)
ctx.rectangle(0,0,ctx.width, ctx.font_size).clip()
ctx.paint()
ctx.text_align=ctx.RIGHT
ctx.rgb(*toolbar_fg)
ctx.move_to(ctx.width, ctx.font_size*0.8)
ctx.text(view_file)
ctx.restore()
mbutton_thin(ctx, 0, ctx.height * button_height_vh * 0, "close", lambda e,d:view_cb(e,False), -3)
ctx.rgb(*scrollbar_fg)
ctx.move_to(ctx.width - ctx.font_size * 1.2, ctx.font_size + ctx.font_size)
if True:#draw scrollbar
ctx.line_to(ctx.width - ctx.font_size * 1.2, ctx.height - ctx.font_size)
ctx.line_width=1
ctx.stroke()
ctx.arc(ctx.width - ctx.font_size * 1.2,
ctx.font_size + ctx.font_size + (offset / line_no) * (ctx.height - ctx.font_size * 2),
ctx.font_size*0.8, 0.0, 3.14152*2, 0).stroke()
ctx.rectangle(ctx.width - ctx.font_size * 2, 0, ctx.font_size * 2, ctx.height)
ctx.listen(ctx.PRESS|ctx.DRAG_MOTION, scrollbar_cb, line_no)
ctx.begin_path()
ctx.rectangle(0, ctx.font_size,
ctx.width, (ctx.height - ctx.font_size)/2-1)
ctx.listen(ctx.PRESS, prev_page_cb)
ctx.begin_path()
ctx.rectangle(0, ctx.font_size + (ctx.height - ctx.font_size)/2,
ctx.width, (ctx.height - ctx.font_size)/2-1)
ctx.listen(ctx.PRESS, next_page_cb)
ctx.begin_path()
ctx.end_frame()
main_exit = False
while not main_exit:
if view_file:
file_view(ctx)
else:
dir_view(ctx)
if run_file != False:
backupflags = ctx.flags
# we remove any scratch format from flags
ctx.flags = backupflags - (ctx.flags&(ctx.GRAY2|ctx.GRAY4|ctx.RGB332))
# and add in low res
ctx.flags = clientflags
gc.collect()
ctx.start_frame()
ctx.rgb(*wallpaper_bg).paint()
ctx.end_frame()
ctx.start_frame()
ctx.rgb(*wallpaper_bg).paint()
ctx.font_size=ctx.height*font_size_vh#32
ctx.rgb(*white).move_to(0,ctx.font_size).text(run_file)
ctx.end_frame()
gc.collect()
try:
exec(open(run_file).read())
except Exception as e:
string_res=io.StringIO(256)
sys.print_exception(e, string_res)
for frame in range(0,2):
ctx.start_frame()
ctx.rgb(*wallpaper_bg).paint()
ctx.font_size=ctx.height*font_size_vh#32
ctx.rgb(*white).move_to(0,ctx.font_size).text(run_file)
#ctx.rgb(*[255,0,0]).move_to(0,ctx.font_size*2).text(str(e))
ctx.rgb(*light_red).move_to(0,ctx.font_size*3).text(string_res.getvalue())
ctx.end_frame()
time.sleep(5)
ctx.flags = backupflags
run_file = False
gc.collect()
#!/usr/bin/env uctx
import canvas
ctx=canvas.ctx
down = False
def on_press(e):
global down
down = True
def on_release(e):
global down
down = False
x = ctx.width/2
y = ctx.height/2
def on_motion(e):
global x,y
x = e.x
y = e.y
exit = False
def exit_cb():
global exit
exit=True
#machine.freq(200_000_000)
max_frame = 100.0
frame_no = 1
while not exit:
ctx.start_frame()
ctx.add_key_binding("q", "", "", exit_cb)
ctx.font_size = ctx.height * 0.1
ctx.rectangle(0,0,ctx.width,ctx.height)
ctx.listen(ctx.PRESS, on_press)
ctx.listen(ctx.RELEASE, on_release)
ctx.listen(ctx.MOTION, on_motion)
if (down):
ctx.color([0,111,222])
else:
ctx.color([255,255,255])
ctx.fill()
dim = (frame_no/max_frame) * ctx.height
if frame_no >= max_frame-2:
dim = ctx.height
ctx.logo(x,y, dim)
ctx.end_frame()
frame_no+=1
#!/usr/bin/env uctx
import canvas
ctx=canvas.ctx
down = False
def on_press(e):
global down
down = True
def on_release(e):
global down
down = False
x = ctx.width/2
y = ctx.height/2
def on_motion(e):
global x,y
x = e.x
y = e.y
exit = False
def exit_cb():
global exit
exit=True
#machine.freq(200_000_000)
max_frame = 100.0
frame_no = 0
while not exit:
ctx.start_frame()
ctx.add_key_binding("q", "", "", exit_cb)
ctx.font_size = ctx.height * 0.1
ctx.rectangle(0,0,ctx.width,ctx.height)
ctx.listen(ctx.PRESS, on_press)
ctx.listen(ctx.RELEASE, on_release)
ctx.listen(ctx.MOTION, on_motion)
if (down):
ctx.rgb(0,111,222)
else:
ctx.rgb(255,255,255)
ctx.fill()
dim = (frame_no/max_frame) * ctx.height
if frame_no >= max_frame-2:
dim = ctx.height
ctx.logo(x,y, dim)
ctx.end_frame()
frame_no+=1
if frame_no > max_frame:
frame_no = 0
#from machine import Pin,SPI,PWM
import machine
import time
import ctx
import gc
from micropython import const
import ustruct as struct
# commands
ST77XX_NOP = const(0x00)
ST77XX_SWRESET = const(0x01)
ST77XX_RDDID = const(0x04)
ST77XX_RDDST = const(0x09)
ST77XX_SLPIN = const(0x10)
ST77XX_SLPOUT = const(0x11)
ST77XX_PTLON = const(0x12)
ST77XX_NORON = const(0x13)
ST77XX_INVOFF = const(0x20)
ST77XX_INVON = const(0x21)
ST77XX_DISPOFF = const(0x28)
ST77XX_DISPON = const(0x29)
ST77XX_CASET = const(0x2A)
ST77XX_RASET = const(0x2B)
ST77XX_RAMWR = const(0x2C)
ST77XX_RAMRD = const(0x2E)
ST77XX_PTLAR = const(0x30)
ST77XX_COLMOD = const(0x3A)
ST7789_MADCTL = const(0x36)
ST7789_MADCTL_MY = const(0x80)
ST7789_MADCTL_MX = const(0x40)
ST7789_MADCTL_MV = const(0x20)
ST7789_MADCTL_ML = const(0x10)
ST7789_MADCTL_BGR = const(0x08)
ST7789_MADCTL_MH = const(0x04)
ST7789_MADCTL_RGB = const(0x00)
ST7789_RDID1 = const(0xDA)
ST7789_RDID2 = const(0xDB)
ST7789_RDID3 = const(0xDC)
ST7789_RDID4 = const(0xDD)
ColorMode_65K = const(0x50)
ColorMode_262K = const(0x60)
ColorMode_12bit = const(0x03)
ColorMode_16bit = const(0x05)
ColorMode_18bit = const(0x06)
ColorMode_16M = const(0x07)
# Color definitions
BLACK = const(0x0000)
BLUE = const(0x001F)
RED = const(0xF800)
GREEN = const(0x07E0)
CYAN = const(0x07FF)
MAGENTA = const(0xF81F)
YELLOW = const(0xFFE0)
WHITE = const(0xFFFF)
_ENCODE_PIXEL = ">H"
_ENCODE_POS = ">HH"
_DECODE_PIXEL = ">BBB"
_BUFFER_SIZE = const(256)
def delay_ms(ms):
time.sleep_ms(ms)
def color565(r, g=0, b=0):
"""Convert red, green and blue values (0-255) into a 16-bit 565 encoding. As
a convenience this is also available in the parent adafruit_rgb_display
package namespace."""
try:
r, g, b = r # see if the first var is a tuple/list
except TypeError:
pass
return (r & 0xf8) << 8 | (g & 0xfc) << 3 | b >> 3
class ST77xx:
def __init__(self, spi, width, height, reset, dc, cs=None, backlight=None,
xstart=-1, ystart=-1, sck=None, mosi=None, miso=None, tp_irq=None, tp_cs=None):
"""
display = st7789.ST7789(
SPI(1, baudrate=40000000, phase=0, polarity=1),
240, 240,
reset=machine.Pin(5, machine.Pin.OUT),
dc=machine.Pin(2, machine.Pin.OUT),
)
"""
self.width = width
self.height = height
self.spi = spi
self.sck = sck
self.ctx = False
if spi == None:
self.spi = machine.SPI(1, baudrate=50000000, polarity=1)
self.reset = reset
self.dc = dc
self.cs = cs
self.mosi = mosi
self.miso = miso
self.backlight = backlight
if xstart >= 0 and ystart >= 0:
self.xstart = xstart
self.ystart = ystart
elif (self.width, self.height) == (320, 240):
self.xstart = 0
self.ystart = 0
elif (self.width, self.height) == (240, 320):
self.xstart = 0
self.ystart = 0
elif (self.width, self.height) == (240, 240):
self.xstart = 0
self.ystart = 0
elif (self.width, self.height) == (135, 240):
self.xstart = 52
self.ystart = 40
else:
raise ValueError(
"Unsupported display. Only 240x240 and 135x240 are supported "
"without xstart and ystart provided"
)
self.X_Point = 0
self.Y_Point = 1
if tp_irq != None:
self.irq = machine.Pin(tp_irq,machine.Pin.IN)
self.tp_cs = machine.Pin(tp_cs,machine.Pin.OUT)
self.tp_cs(1)
self.pointer_down = False
if self.backlight:
self.backlight.high();
def get_id(self):
self.cs_low()
self.dc_low()
self.spi.write(bytes([ST7789_RDID2]))
res = self.spi.read(1)
self.cs_high()
return res[0]
def dc_low(self):
self.dc.off()
def dc_high(self):
self.dc.on()
def reset_low(self):
if self.reset:
self.reset.off()
def reset_high(self):
if self.reset:
self.reset.on()
def cs_low(self):
if self.cs:
self.cs.off()
def cs_high(self):
if self.cs:
self.cs.on()
def write(self, command=None, data=None):
"""SPI write to the device: commands and data"""
self.cs_low()
if command is not None:
self.dc_low()
self.spi.write(bytes([command]))
if data is not None:
self.dc_high()
self.spi.write(data)
self.cs_high()
def hard_reset(self):
self.cs_low()
self.reset_high()
delay_ms(50)
self.reset_low()
delay_ms(50)
self.reset_high()
delay_ms(150)
self.cs_high()
def soft_reset(self):
self.write(ST77XX_SWRESET)
delay_ms(150)
def sleep_mode(self, value):
if value:
self.write(ST77XX_SLPIN)
else:
self.write(ST77XX_SLPOUT)
def inversion_mode(self, value):
if value:
self.write(ST77XX_INVON)
else:
self.write(ST77XX_INVOFF)
def _set_color_mode(self, mode):
self.write(ST77XX_COLMOD, bytes([mode & 0x77]))
def init(self, *args, **kwargs):
self.hard_reset()
self.soft_reset()
self.sleep_mode(False)
return True
def _set_mem_access_mode(self, rotation, vert_mirror, horz_mirror, is_bgr):
rotation &= 7
value = {
0: 0,
1: ST7789_MADCTL_MX,
2: ST7789_MADCTL_MY,
3: ST7789_MADCTL_MX | ST7789_MADCTL_MY,
4: ST7789_MADCTL_MV,
5: ST7789_MADCTL_MV | ST7789_MADCTL_MX,
6: ST7789_MADCTL_MV | ST7789_MADCTL_MY,
7: ST7789_MADCTL_MV | ST7789_MADCTL_MX | ST7789_MADCTL_MY,
}[rotation]
if vert_mirror:
value = ST7789_MADCTL_ML
elif horz_mirror:
value = ST7789_MADCTL_MH
if is_bgr:
value |= ST7789_MADCTL_BGR
self.write(ST7789_MADCTL, bytes([value]))
def _encode_pos(self, x, y):
"""Encode a postion into bytes."""
return struct.pack(_ENCODE_POS, x, y)
def _encode_pixel(self, color):
"""Encode a pixel color into bytes."""
return struct.pack(_ENCODE_PIXEL, color)
def _set_columns(self, start, end):
if start > end or end >= self.width:
return
start += self.xstart
end += self.xstart
self.write(ST77XX_CASET, self._encode_pos(start, end))
def _set_rows(self, start, end):
if start > end or end >= self.height:
return
start += self.ystart
end += self.ystart
self.write(ST77XX_RASET, self._encode_pos(start, end))
def set_window(self, x0, y0, x1, y1):
self._set_columns(x0, x1)
self._set_rows(y0, y1)
self.write(ST77XX_RAMWR)
def vline(self, x, y, length, color):
self.fill_rect(x, y, 1, length, color)
def hline(self, x, y, length, color):
self.fill_rect(x, y, length, 1, color)
def pixel(self, x, y, color):
self.set_window(x, y, x, y)
self.write(None, self._encode_pixel(color))
def blit_buffer(self, buffer, x, y, width, height):
self.set_window(x, y, x + width -1, y + height -1)
self.write(None, buffer)
def rect(self, x, y, w, h, color):
self.hline(x, y, w, color)
self.vline(x, y, h, color)
self.vline(x + w - 1, y, h, color)
self.hline(x, y + h - 1, w, color)
def fill_rect(self, x, y, width, height, color):
self.set_window(x, y, x + width - 1, y + height - 1)
chunks, rest = divmod(width * height, _BUFFER_SIZE)
pixel = self._encode_pixel(color)
self.dc_high()
if chunks:
data = pixel * _BUFFER_SIZE
for _ in range(chunks):
self.write(None, data)
if rest:
self.write(None, pixel * rest)
def fill(self, color):
self.fill_rect(0, 0, self.width, self.height, color)
def line(self, x0, y0, x1, y1, color):
# Line drawing function. Will draw a single pixel wide line starting at
# x0, y0 and ending at x1, y1.
steep = abs(y1 - y0) > abs(x1 - x0)
if steep:
x0, y0 = y0, x0
x1, y1 = y1, x1
if x0 > x1:
x0, x1 = x1, x0
y0, y1 = y1, y0
dx = x1 - x0
dy = abs(y1 - y0)
err = dx // 2
if y0 < y1:
ystep = 1
else:
ystep = -1
while x0 <= x1:
if steep:
self.pixel(y0, x0, color)
else:
self.pixel(x0, y0, color)
err -= dy
if err < 0:
y0 += ystep
err += dx
x0 += 1
def touch_get(self):
if self.irq() == 0:
self.spi =machine.SPI(1, baudrate=5000000, sck=machine.Pin(self.sck),
mosi=machine.Pin(self.mosi),
miso=machine.Pin(self.miso))
self.tp_cs(0)
X_Point = 0
Y_Point = 0
for i in range(0,2):
self.spi.write(bytearray([0XD0]))
Read_date = self.spi.read(3)
time.sleep_us(10)
X_Point=X_Point+(((Read_date[0]<<8)+Read_date[1])>>3)
self.spi.write(bytearray([0X90]))
Read_date = self.spi.read(2)
Y_Point=Y_Point+(((Read_date[0]<<8)+Read_date[1])>>3)
X_Point=X_Point/2
Y_Point=Y_Point/2
self.tp_cs(1)
self.spi =machine.SPI(1, baudrate=40000000, polarity=1, sck=machine.Pin(self.sck),
mosi=machine.Pin(self.mosi),
miso=machine.Pin(self.miso))
X_Point = 240-((X_Point-540)*240.0/3270)
Y_Point = 320-((Y_Point-540)*320.0/3270)
Result_list = [X_Point,Y_Point]
return(Result_list)
def ctx_update_events(self,o):
touch=self.touch_get()
if(touch):
self.X_Point = touch[0]
self.Y_Point = touch[1]
if(self.X_Point>240):
self.X_Point = 240
elif self.X_Point<0:
self.X_Point = 0
if(self.Y_Point>320):
self.Y_Point = 320
elif self.Y_Point<0:
self.Y_Point = 0
if not self.pointer_down:
o.pointer_press(self.X_Point,self.Y_Point, 0, 0, 1)
else:
o.pointer_motion(self.X_Point,self.Y_Point, 0, 0, 1)
#print ("pointer " + str(self.X_Point) + ' ' + str (self.Y_Point))
self.pointer_down = True
return False # abort rendering if in slow refresh
else:
if self.pointer_down:
o.pointer_release(self.X_Point,self.Y_Point, 0, 0, 1)
self.pointer_down = False
return False
class ST7789(ST77xx):
def init(self, *, color_mode=ColorMode_65K | ColorMode_16bit):
super().init()
self._set_color_mode(color_mode)
delay_ms(50)
self._set_mem_access_mode(4, True, True, False)
self.inversion_mode(True)
delay_ms(10)
self.write(ST77XX_NORON)
delay_ms(10)
self.fill(0)
self.write(ST77XX_DISPON)
delay_ms(500)
lcd = False
#!/usr/bin/env uctx
import ctx
import gc
pointer_x = 0
pointer_y = 0
down = False
was_down = False
text_edit_preview = ''
cursor_pos=[0,0]
widget_no = 0
grab_no = 0
text_edit_no = 0
text_edit_font_size = 0
text_edit_copy = None
text_edit_done = False
import canvas
o = canvas.ctx
try:
font_size_vh
except NameError:
if o.width < o.height:
font_size_vh = 0.05
else:
font_size_vh = 0.06
widget_fs=0.1
widget_height_fs=2.0
#o.flags = o.HASH_CACHE | o.RGB332 | o.INTRA_UPDATE
o.flags = o.HASH_CACHE|o.RGB332
wallpaper_bg=(0,0,0)
widget_font_size_vh = font_size_vh
widget_bg=(80/255,80/255,80/255)
widget_fg=(1.0,1.0,1.0)
widget_marker=(163/255,100/255,180/255)
button_bg=widget_bg
button_fg=widget_fg
button_bg_active=(225/255,35/255,90/255)
widget_x=0
widget_y=0
widget_width=0
widget_height=0
edge_left = o.height * font_size_vh * 8
edge_right = o.width - edge_left
def add_widget(x, y, w, h):
global widget_no
widget_no += 1
return widget_no
def get_ctx():
return o
def inside_rect(u,v,x,y,w,h):
if u >= x and u < x + w and v >= y and v < y + h:
return True
return False
def slider_sized(x, y, w, h, label, value, min, max):
global grab_no
add_widget(x, y, w, h)
o.font_size = o.height * widget_font_size_vh # why do we need this override
o.rgb(*widget_bg).rectangle(x, y, w, h - 2).fill()
o.rgb(*widget_marker).rectangle(x + (value-min)/(max-min)*w, y, 0.1*o.font_size, h).fill()
o.rgb(*widget_fg)
o.move_to(x + o.font_size*0.1, y + o.font_size*0.8)
o.text(label)
o.save()
o.text_align=o.RIGHT
o.move_to(x+w,y+o.font_size*0.8)
o.text(str(value))
o.restore()
if text_edit_no != 0:
return value
if down and text_edit_no==0:
if inside_rect(pointer_x,pointer_y,x,y,w,h) or\
grab_no == widget_no:
if was_down == False:
grab_no = widget_no
if grab_no == widget_no:
value = ((pointer_x - x) / w) * (max-min) + min
if value < min:
value = min
if value > max:
value = max
else:
grab_no = 0
o.begin_path()
return value
def label_sized(x, y, w, h, label):
global down, was_down
add_widget(x,y,w,h)
o.font_size = o.height * widget_font_size_vh # why do we need this override
o.rgb(*button_fg)
o.move_to(x + o.font_size/8, y + h/2 + o.font_size/3).text(label)
def button_sized(x, y, w, h, label):
global down, was_down
add_widget(x,y,w,h)
result = False
o.font_size = o.height * widget_font_size_vh # why do we need this override
lwidth = o.text_width (label)
o.rectangle(x, y, w, h)
o.rgb(*button_bg)
if text_edit_no == 0 and down and was_down == False and inside_rect(pointer_x,pointer_y,x,y,w,h):
result = True
o.rgb(*button_bg_active)
o.fill()
o.rgb(*button_fg)
o.move_to(x + w/2-lwidth/2, y + h/2 + o.font_size/3).text(label)
return result
def toggle_sized(x, y, w, h, label, value):
global down, was_down
add_widget(x,y,w,h)
result = value
o.font_size = o.height * widget_font_size_vh # why do we need this override
if text_edit_no == 0 and down and was_down == False and inside_rect(pointer_x,pointer_y,x,y,w,h):
result = not value
o.rectangle(x, y, w, h).rgb(*button_bg_active).fill()
o.rgb(*widget_fg)
o.move_to(x + o.font_size*0.1, y + o.font_size*0.8)
o.text(label)
o.save()
o.text_align=o.RIGHT
o.move_to(x+w,y+o.font_size*0.8)
if value:
o.text("on")
else:
o.text("off")
o.restore()
if text_edit_no != 0:
result = value
return result
def entry_sized(x, y, w, h, label, value, default_value):
global down, was_down, cursor_pos, text_edit_no, text_edit_font_size, text_edit_done, text_edit_copy
widget_no=add_widget(x,y,w,h)
result = value
o.font_size = o.height * widget_font_size_vh # why do we need this override
o.rgb(*widget_fg)
o.move_to(x + o.font_size*0.1, y + o.font_size*0.8)
o.text(label)
o.save()
#o.text_align=o.RIGHT
#o.move_to(x+w,y+o.font_size*0.8)
#if value:
if text_edit_no == widget_no:
o.text(text_edit_copy)
else:
o.text(value)
if text_edit_no == 0 and down and was_down == False and inside_rect(pointer_x,pointer_y,x,y,w,h):
#result = "baah"#not value
#o.rectangle(x, y, w, h).rgb(*button_bg_active).fill()
text_edit_copy = value
text_edit_no = widget_no
text_edit_font_size = o.font_size
if text_edit_no == widget_no:
cursor_pos=[o.x,o.y]
o.move_to(cursor_pos[0],cursor_pos[1])
o.rgb(1.0,1.0,1.0).text(text_edit_preview)
o.rectangle(x, y, w, h).rgb(*button_bg_active).stroke()
o.rectangle(cursor_pos[0],cursor_pos[1]-o.font_size,3, o.font_size * 1.1).fill()
#o.move_to(cursor_pos[0],cursor_pos[1])
if text_edit_done:
text_edit_done = False # we only do this once
text_edit_no = 0
o.restore()
return text_edit_copy
o.restore()
return None
def init_geom(x,y,width,height):
absolute=True
if x==None or y==None:
x = edge_left #o.x
y = o.y
absolute=False
if height==None:
height = o.height * widget_font_size_vh * widget_height_fs
if width==None:
width = edge_right-edge_left #o.width
# convert to integer and drop least signifcant
# bit, this makes 2x2 preview renders avoid
# rectangle AA
x = int(x) & ~1
y = int(y) & ~1
width = int(width) & ~1
height = int(height) & ~1
return (x,y,width,height,absolute)
def slider(label, value, min, max, x=None, y=None, width=None, height=None):
tup = init_geom(x,y,width,height)
x=tup[0];y=tup[1];width=tup[2];height=tup[3];absolute=tup[4]
retval = slider_sized (x, y, width, height, label, value, min, max)
if not absolute:
o.move_to (x, y + height)
return retval
def toggle(label, value, x=None, y=None, width=None, height=None):
tup = init_geom(x,y,width,height)
x=tup[0];y=tup[1];width=tup[2];height=tup[3];absolute=tup[4]
retval = toggle_sized (x, y, width, height, label, value)
if not absolute:
o.move_to (x, y + height)
return retval
def button(string, x=None, y=None, width=None, height=None):
tup = init_geom(x,y,width,height)
x=tup[0];y=tup[1];width=tup[2];height=tup[3];absolute=tup[4]
retval = button_sized (x, y, width, height * 0.98, string)
if not absolute:
o.move_to (x, y + height)
return retval
def label(string, x=None, y=None, width=None, height=None):
tup = init_geom(x,y,width,height)
x=tup[0];y=tup[1];width=tup[2];height=tup[3];absolute=tup[4]
label_sized (x, y, width, height * 0.98, string)
if not absolute:
o.move_to (x, y + height)
def entry(label,string,default_string,x=None,y=None,width=None,height=None):
tup = init_geom(x,y,width,height)
x=tup[0];y=tup[1];width=tup[2];height=tup[3];absolute=tup[4]
string = entry_sized (x, y, width, height * 0.98, label, string, default_string)
if not absolute:
o.move_to (x, y + height)
return string
def coords_press(x, y):
global pointer_x, pointer_y, down
pointer_x = x
pointer_y = y
down = True
def coords_motion(x, y):
global pointer_x, pointer_y
pointer_x = x
pointer_y = y
def coords_release(x, y):
global pointer_x, pointer_y, down
pointer_x = x
pointer_y = y
down = False
exit = False
KEYs = (
(
('q','w','e','r','t','y','u','i','o','p'),
('a','s','d','f','g','h','j','k','l',''),
('z','x','c','v','b','n','m',',','.'),
('ABC',' ',' ',' ',' ',' ',' ',' ',' ','')
),
(
('Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P',),
('A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ''),
('Z', 'X', 'C', 'V', 'B', 'N', 'M', ':', '?'),
('123', ' ',' ', ' ', ' ', ' ', ' ', '!',' ','')
),
(
('1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '|'),
('@', '#', '$', '%', '^', '&', '*', '(', ')', ''),
('+','-','=','_','"','\'','[',']'),
('æøå', ' ', '~', '/', '\\', '{','}','`',' ','')
),
(
('pu','é', 'ñ', 'ß', 'ü', 'Ü', 'æ', 'ø', 'å', '|'),
('pd', '', '®', '©', 'Æ', 'Ø', 'Å',' ', ' ', ''),
('ctr' ,'alt', ' ','', ' ', 'ö','Ö','Å'),
('abc', ' ','','','', ' ',' ',' ',' ','')
)
# add a layout with cursor keys and modifiers, return space tab escape
# home, end insert delta page up page down .. and even some F keys?
)
osk_layout=0
def start_frame():
global widget_no
widget_no = 0
o.start_frame()
o.rgb(*wallpaper_bg).paint()
o.rectangle(0,0,o.width, o.height)#,o.height)
o.listen(o.PRESS, lambda e:coords_press(e.x, e.y))
o.listen(o.MOTION, lambda e:coords_motion(e.x, e.y))
o.listen(o.RELEASE, lambda e:coords_release(e.x, e.y))
o.fill()
import math
keyboard_bg=(70/255,70/255,90/255)
keyboard_fg=(1.0,1.0,1.0)
def keyboard(x,y,width,height):
global text_edit_copy, cursor_pos, text_edit_preview, osk_layout, text_edit_done
o.rectangle(x,y,width,height)
#o.listen_stop_propagate(o.PRESS|o.MOTION, lambda e:update_coords(e.x, e.y, True))
#o.listen_stop_propagate(o.RELEASE, lambda e:update_coords(e.x, e.y, False))
o.rgb(*keyboard_bg).fill()
cell_width = width /11.0;
cell_height = height / 4.0;
o.font_size = cell_height;
row_no=0
o.save()
o.text_align=o.CENTER
o.rgb(*keyboard_fg)
nearest = False
best_dist = 1000
for row in KEYS[osk_layout]:
col_no = 0
for key in row:
keyx = x + (col_no+0.5 + row_no/4.0) * cell_width
keyy = y + row_no * cell_height + cell_height * 0.5
dist = math.sqrt((pointer_x-keyx)*(pointer_x-keyx)+ (pointer_y-keyy)*(pointer_y-keyy))
if dist < best_dist:
best_dist = dist
nearest = key
o.move_to(keyx, keyy + cell_height * 0.3)
label = str(key)
label = {'\b':'bs','\n':'nl'}.get(label,label)
o.text(label)
col_no += 1
row_no += 1
o.restore()
if inside_rect(pointer_x,pointer_y,x,y,width,height):
if down:
text_edit_preview = nearest
else:
text_edit_preview = ''
if not down and was_down:
o.font_size = text_edit_font_size
if nearest == '':
text_edit_done = True
elif nearest == '':
if len(text_edit_copy)>0:
cursor_pos[0] -= o.text_width (text_edit_copy[-1])
text_edit_copy = text_edit_copy[0:-1]
elif nearest == 'ABC':
osk_layout=1
elif nearest == '123':
osk_layout=2
elif nearest == '<>{':
osk_layout=3
elif nearest == 'æøå':
osk_layout=3
elif nearest == 'abc':
osk_layout=0
else:
text_edit_copy += nearest
#cursor_pos[0] += o.text_width (nearest)
text_edit_preview = ''
else:
text_edit_preview = ''
def end_frame():
global was_down, down, text_edit_no
if text_edit_no > 0:
keyboard(0,o.height/2,o.width,o.height/2)
was_down = down # must happen after all the buttons
gc.collect()
o.end_frame()
def nearest_in_list(needle,list):
best_score=400000
best=needle
for i in list:
score = abs(i-needle)
if score < best_score:
best_score = score
best=i
return best
def choice(label, chosen, choices):
return chosen
if __name__=='__main__':
exit = 0
constrain_332 = False
string = ""
red = widget_bg[0]
green = widget_bg[1]
blue = widget_bg[2]
chosen = "foo"
start_frame()
end_frame()
gc.collect()
while exit < 4: # a hack to let the ui re-settle, makes
# switching apps slower though
start_frame()
edited_string = entry ("entry: ", string, "default")
if edited_string:
string = edited_string
chosen = choice ("among", chosen, ("foo","bar","baz"))
label (chosen)
constrain_332 = toggle ("RGB332", constrain_332)
red = int(slider("red", red, 0, 255))
green = int(slider("green", green, 0, 255))
blue = int(slider("blue", blue, 0, 255))
o.rectangle (o.x+o.width/2,o.y - o.font_size * 4,o.width * 0.15, o.height * 0.15)
o.rgb(red/255,green/255,blue/255).fill()
o.rectangle (o.x+o.width/2,o.y - o.font_size * 4,o.width * 0.15, o.height * 0.15)
o.rgb(1.0,1.0,1.0).stroke()
if constrain_332:
valid_red=[0,40,80,140,174,209,233,255] # 176
valid_green=[0,40,80,140,174,209,233,255] # 176
valid_blue=[0,80,170,255]
red = nearest_in_list(red, valid_red)
green = nearest_in_list(green, valid_green)
blue = nearest_in_list(blue, valid_blue)
if button ("done"):
exit = True
if button("x", x=40, y=40, width=50, height=50):
exit = True
if False:
widget_bg[0] = red
widget_bg[1] = green
widget_bg[2] = blue
end_frame()
gc.collect()
if exit > 0:
exit += 1
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment