From 22d4c25aa6ad3a9d9112ddcf980bf014d73a2593 Mon Sep 17 00:00:00 2001 From: Gabor Peresztegi Date: Tue, 4 Mar 2025 00:34:40 +0100 Subject: [PATCH] Update LVGL binding: use it as USER_C_MODULE; add unix-lvgl variant and M5Core2 board; remove ESP32 specific LVGL modules (soft links) --- .gitmodules | 6 +- lib/lv_bindings | 1 - ports/esp32/boards/M5CORE2/manifest.py | 2 - ports/esp32/boards/M5CORE2/modules/axp192.py | 1 - ports/esp32/boards/M5CORE2/modules/ft6x36.py | 1 - ports/esp32/boards/M5CORE2/mpconfigboard.h | 2 - .../{M5CORE2 => M5STACK_CORE2}/README.md | 0 .../{M5CORE2 => M5STACK_CORE2}/board.json | 9 +- ports/esp32/boards/M5STACK_CORE2/m5core2.webp | Bin 0 -> 78829 bytes ports/esp32/boards/M5STACK_CORE2/manifest.py | 3 + .../boards/M5STACK_CORE2/modules/axp192.py | 1 + .../boards/M5STACK_CORE2/modules/ft6x36.py | 1 + .../modules/m5core2.py | 0 .../modules/power.py | 0 .../mpconfigboard.cmake | 4 +- .../boards/M5STACK_CORE2/mpconfigboard.h | 7 + .../{M5CORE2 => M5STACK_CORE2}/partitions.csv | 0 .../sdkconfig.board | 2 +- ports/esp32/modules/display_driver_utils.py | 1 - ports/esp32/modules/fs_driver.py | 1 - ports/esp32/modules/ili9341.py | 1 - ports/esp32/modules/ili9XXX.py | 1 - ports/esp32/modules/lv_colors.py | 1 - ports/esp32/modules/lv_spi.py | 1 - ports/esp32/modules/lv_utils.py | 1 - ports/esp32/modules/sdcard.py | 1 - ports/esp32/modules/uftpd.py | 481 ------------------ ports/esp32/modules/utelnetserver.py | 109 ---- ports/esp32/modules/xpt2046.py | 1 - ports/unix/variants/lvgl/manifest.py | 3 + ports/unix/variants/lvgl/mpconfigvariant.h | 36 ++ ports/unix/variants/lvgl/mpconfigvariant.mk | 4 + user_modules/lv_binding_micropython | 1 + 33 files changed, 70 insertions(+), 613 deletions(-) delete mode 160000 lib/lv_bindings delete mode 100644 ports/esp32/boards/M5CORE2/manifest.py delete mode 120000 ports/esp32/boards/M5CORE2/modules/axp192.py delete mode 120000 ports/esp32/boards/M5CORE2/modules/ft6x36.py delete mode 100644 ports/esp32/boards/M5CORE2/mpconfigboard.h rename ports/esp32/boards/{M5CORE2 => M5STACK_CORE2}/README.md (100%) rename ports/esp32/boards/{M5CORE2 => M5STACK_CORE2}/board.json (66%) create mode 100644 ports/esp32/boards/M5STACK_CORE2/m5core2.webp create mode 100644 ports/esp32/boards/M5STACK_CORE2/manifest.py create mode 120000 ports/esp32/boards/M5STACK_CORE2/modules/axp192.py create mode 120000 ports/esp32/boards/M5STACK_CORE2/modules/ft6x36.py rename ports/esp32/boards/{M5CORE2 => M5STACK_CORE2}/modules/m5core2.py (100%) rename ports/esp32/boards/{M5CORE2 => M5STACK_CORE2}/modules/power.py (100%) rename ports/esp32/boards/{M5CORE2 => M5STACK_CORE2}/mpconfigboard.cmake (63%) create mode 100644 ports/esp32/boards/M5STACK_CORE2/mpconfigboard.h rename ports/esp32/boards/{M5CORE2 => M5STACK_CORE2}/partitions.csv (100%) rename ports/esp32/boards/{M5CORE2 => M5STACK_CORE2}/sdkconfig.board (67%) delete mode 120000 ports/esp32/modules/display_driver_utils.py delete mode 120000 ports/esp32/modules/fs_driver.py delete mode 120000 ports/esp32/modules/ili9341.py delete mode 120000 ports/esp32/modules/ili9XXX.py delete mode 120000 ports/esp32/modules/lv_colors.py delete mode 120000 ports/esp32/modules/lv_spi.py delete mode 120000 ports/esp32/modules/lv_utils.py delete mode 120000 ports/esp32/modules/sdcard.py delete mode 100644 ports/esp32/modules/uftpd.py delete mode 100644 ports/esp32/modules/utelnetserver.py delete mode 120000 ports/esp32/modules/xpt2046.py create mode 100644 ports/unix/variants/lvgl/manifest.py create mode 100644 ports/unix/variants/lvgl/mpconfigvariant.h create mode 100644 ports/unix/variants/lvgl/mpconfigvariant.mk create mode 160000 user_modules/lv_binding_micropython diff --git a/.gitmodules b/.gitmodules index 3f273e681..3402338cb 100644 --- a/.gitmodules +++ b/.gitmodules @@ -17,9 +17,6 @@ [submodule "lib/nrfx"] path = lib/nrfx url = https://github.com/NordicSemiconductor/nrfx.git -[submodule "lib/lv_bindings"] - path = lib/lv_bindings - url = https://github.com/lvgl/lv_binding_micropython.git [submodule "lib/mbedtls"] path = lib/mbedtls url = https://github.com/ARMmbed/mbedtls.git @@ -71,3 +68,6 @@ [submodule "lib/arduino-lib"] path = lib/arduino-lib url = https://github.com/arduino/arduino-lib-mpy.git +[submodule "user_modules/lv_binding_micropython"] + path = user_modules/lv_binding_micropython + url = https://github.com/lvgl/lv_binding_micropython.git diff --git a/lib/lv_bindings b/lib/lv_bindings deleted file mode 160000 index 96d6d3538..000000000 --- a/lib/lv_bindings +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 96d6d3538fec4de99c200c1bb388b02b95cbbdaf diff --git a/ports/esp32/boards/M5CORE2/manifest.py b/ports/esp32/boards/M5CORE2/manifest.py deleted file mode 100644 index 18bc6de67..000000000 --- a/ports/esp32/boards/M5CORE2/manifest.py +++ /dev/null @@ -1,2 +0,0 @@ -include("$(PORT_DIR)/boards/manifest.py") -freeze("./modules") \ No newline at end of file diff --git a/ports/esp32/boards/M5CORE2/modules/axp192.py b/ports/esp32/boards/M5CORE2/modules/axp192.py deleted file mode 120000 index ad35dd2e2..000000000 --- a/ports/esp32/boards/M5CORE2/modules/axp192.py +++ /dev/null @@ -1 +0,0 @@ -../../../../../lib/lv_bindings/driver/generic/axp192.py \ No newline at end of file diff --git a/ports/esp32/boards/M5CORE2/modules/ft6x36.py b/ports/esp32/boards/M5CORE2/modules/ft6x36.py deleted file mode 120000 index 8cda07c05..000000000 --- a/ports/esp32/boards/M5CORE2/modules/ft6x36.py +++ /dev/null @@ -1 +0,0 @@ -../../../../../lib/lv_bindings/driver/generic/ft6x36.py \ No newline at end of file diff --git a/ports/esp32/boards/M5CORE2/mpconfigboard.h b/ports/esp32/boards/M5CORE2/mpconfigboard.h deleted file mode 100644 index cb638307f..000000000 --- a/ports/esp32/boards/M5CORE2/mpconfigboard.h +++ /dev/null @@ -1,2 +0,0 @@ -#define MICROPY_HW_BOARD_NAME "M5Stack Core2" -#define MICROPY_HW_MCU_NAME "ESP32" diff --git a/ports/esp32/boards/M5CORE2/README.md b/ports/esp32/boards/M5STACK_CORE2/README.md similarity index 100% rename from ports/esp32/boards/M5CORE2/README.md rename to ports/esp32/boards/M5STACK_CORE2/README.md diff --git a/ports/esp32/boards/M5CORE2/board.json b/ports/esp32/boards/M5STACK_CORE2/board.json similarity index 66% rename from ports/esp32/boards/M5CORE2/board.json rename to ports/esp32/boards/M5STACK_CORE2/board.json index bae63f477..f0762ee61 100644 --- a/ports/esp32/boards/M5CORE2/board.json +++ b/ports/esp32/boards/M5STACK_CORE2/board.json @@ -7,12 +7,17 @@ "BLE", "WiFi", "SPIRAM", + "LCD", + "LED", "IMU", "RTC", "PMU", "SDCard", + "Button", + "Speaker", "Microphone", - "USB-C" + "Vibration Motor", + "USB-C" ], "images": [ "m5core2.jpg" @@ -20,6 +25,6 @@ "mcu": "esp32", "product": "M5Stack Core2", "thumbnail": "", - "url": "https://m5stack.com/", + "url": "https://shop.m5stack.com/products/m5stack-core2-esp32-iot-development-kit", "vendor": "M5 Stack" } diff --git a/ports/esp32/boards/M5STACK_CORE2/m5core2.webp b/ports/esp32/boards/M5STACK_CORE2/m5core2.webp new file mode 100644 index 0000000000000000000000000000000000000000..a9c3d5aa82c5fe7ba3ae17420d8583c30448316d GIT binary patch literal 78829 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 0: - data_client.sendall(chunk) - chunk = file.read(_CHUNK_SIZE) - data_client.close() - - def save_file_data(self, path, data_client, mode): - with open(path, mode) as file: - chunk = data_client.recv(_CHUNK_SIZE) - while len(chunk) > 0: - file.write(chunk) - chunk = data_client.recv(_CHUNK_SIZE) - data_client.close() - - def get_absolute_path(self, cwd, payload): - # Just a few special cases "..", "." and "" - # If payload start's with /, set cwd to / - # and consider the remainder a relative path - if payload.startswith('/'): - cwd = "/" - for token in payload.split("/"): - if token == '..': - cwd = self.split_path(cwd)[0] - elif token != '.' and token != '': - if cwd == '/': - cwd += token - else: - cwd = cwd + '/' + token - return cwd - - def split_path(self, path): # instead of path.rpartition('/') - tail = path.split('/')[-1] - head = path[:-(len(tail) + 1)] - return ('/' if head == '' else head, tail) - - # compare fname against pattern. Pattern may contain - # the wildcards ? and *. - def fncmp(self, fname, pattern): - pi = 0 - si = 0 - while pi < len(pattern) and si < len(fname): - if (fname[si] == pattern[pi]) or (pattern[pi] == '?'): - si += 1 - pi += 1 - else: - if pattern[pi] == '*': # recurse - if pi == len(pattern.rstrip("*?")): # only wildcards left - return True - while si < len(fname): - if self.fncmp(fname[si:], pattern[pi + 1:]): - return True - else: - si += 1 - return False - else: - return False - if pi == len(pattern.rstrip("*")) and si == len(fname): - return True - else: - return False - - def open_dataclient(self): - if self.active: # active mode - data_client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - data_client.settimeout(_DATA_TIMEOUT) - data_client.connect((self.act_data_addr, self.DATA_PORT)) - log_msg(1, "FTP Data connection with:", self.act_data_addr) - else: # passive mode - data_client, data_addr = datasocket.accept() - log_msg(1, "FTP Data connection with:", data_addr[0]) - return data_client - - def exec_ftp_command(self, cl): - global datasocket - global client_busy - global my_ip_addr - - try: - gc.collect() - - data = cl.readline().decode("utf-8").rstrip("\r\n") - - if len(data) <= 0: - # No data, close - # This part is NOT CLEAN; there is still a chance that a - # closing data connection will be signalled as closing - # command connection - log_msg(1, "*** No data, assume QUIT") - close_client(cl) - return - - if client_busy: # check if another client is busy - cl.sendall("400 Device busy.\r\n") # tell so the remote client - return # and quit - client_busy = True # now it's my turn - - # check for log-in state may done here, like - # if self.logged_in == False and not command in\ - # ("USER", "PASS", "QUIT"): - # cl.sendall("530 Not logged in.\r\n") - # return - - command = data.split()[0].upper() - payload = data[len(command):].lstrip() # partition is missing - path = self.get_absolute_path(self.cwd, payload) - log_msg(1, "Command={}, Payload={}".format(command, payload)) - - if command == "USER": - # self.logged_in = True - cl.sendall("230 Logged in.\r\n") - # If you want to see a password,return - # "331 Need password.\r\n" instead - # If you want to reject an user, return - # "530 Not logged in.\r\n" - elif command == "PASS": - # you may check here for a valid password and return - # "530 Not logged in.\r\n" in case it's wrong - # self.logged_in = True - cl.sendall("230 Logged in.\r\n") - elif command == "SYST": - cl.sendall("215 UNIX Type: L8\r\n") - elif command in ("TYPE", "NOOP", "ABOR"): # just accept & ignore - cl.sendall('200 OK\r\n') - elif command == "QUIT": - cl.sendall('221 Bye.\r\n') - close_client(cl) - elif command == "PWD" or command == "XPWD": - cl.sendall('257 "{}"\r\n'.format(self.cwd)) - elif command == "CWD" or command == "XCWD": - try: - if (uos.stat(path)[0] & 0o170000) == 0o040000: - self.cwd = path - cl.sendall('250 OK\r\n') - else: - cl.sendall('550 Fail\r\n') - except: - cl.sendall('550 Fail\r\n') - elif command == "PASV": - cl.sendall('227 Entering Passive Mode ({},{},{}).\r\n'.format( - self.pasv_data_addr.replace('.', ','), - _DATA_PORT >> 8, _DATA_PORT % 256)) - self.active = False - elif command == "PORT": - items = payload.split(",") - if len(items) >= 6: - self.act_data_addr = '.'.join(items[:4]) - if self.act_data_addr == "127.0.1.1": - # replace by command session addr - self.act_data_addr = self.remote_addr - self.DATA_PORT = int(items[4]) * 256 + int(items[5]) - cl.sendall('200 OK\r\n') - self.active = True - else: - cl.sendall('504 Fail\r\n') - elif command == "LIST" or command == "NLST": - if payload.startswith("-"): - option = payload.split()[0].lower() - path = self.get_absolute_path( - self.cwd, payload[len(option):].lstrip()) - else: - option = "" - try: - data_client = self.open_dataclient() - cl.sendall("150 Directory listing:\r\n") - self.send_list_data(path, data_client, - command == "LIST" or 'l' in option) - cl.sendall("226 Done.\r\n") - data_client.close() - except: - cl.sendall('550 Fail\r\n') - if data_client is not None: - data_client.close() - elif command == "RETR": - try: - data_client = self.open_dataclient() - cl.sendall("150 Opened data connection.\r\n") - self.send_file_data(path, data_client) - # if the next statement is reached, - # the data_client was closed. - data_client = None - cl.sendall("226 Done.\r\n") - except: - cl.sendall('550 Fail\r\n') - if data_client is not None: - data_client.close() - elif command == "STOR" or command == "APPE": - try: - data_client = self.open_dataclient() - cl.sendall("150 Opened data connection.\r\n") - self.save_file_data(path, data_client, - "wb" if command == "STOR" else "ab") - # if the next statement is reached, - # the data_client was closed. - data_client = None - cl.sendall("226 Done.\r\n") - except: - cl.sendall('550 Fail\r\n') - if data_client is not None: - data_client.close() - elif command == "SIZE": - try: - cl.sendall('213 {}\r\n'.format(uos.stat(path)[6])) - except: - cl.sendall('550 Fail\r\n') - elif command == "MDTM": - try: - tm=localtime(uos.stat(path)[8]) - cl.sendall('213 {:04d}{:02d}{:02d}{:02d}{:02d}{:02d}\r\n'.format(*tm[0:6])) - except: - cl.sendall('550 Fail\r\n') - elif command == "STAT": - if payload == "": - cl.sendall("211-Connected to ({})\r\n" - " Data address ({})\r\n" - " TYPE: Binary STRU: File MODE: Stream\r\n" - " Session timeout {}\r\n" - "211 Client count is {}\r\n".format( - self.remote_addr, self.pasv_data_addr, - _COMMAND_TIMEOUT, len(client_list))) - else: - cl.sendall("213-Directory listing:\r\n") - self.send_list_data(path, cl, True) - cl.sendall("213 Done.\r\n") - elif command == "DELE": - try: - uos.remove(path) - cl.sendall('250 OK\r\n') - except: - cl.sendall('550 Fail\r\n') - elif command == "RNFR": - try: - # just test if the name exists, exception if not - uos.stat(path) - self.fromname = path - cl.sendall("350 Rename from\r\n") - except: - cl.sendall('550 Fail\r\n') - elif command == "RNTO": - try: - uos.rename(self.fromname, path) - cl.sendall('250 OK\r\n') - except: - cl.sendall('550 Fail\r\n') - self.fromname = None - elif command == "CDUP" or command == "XCUP": - self.cwd = self.get_absolute_path(self.cwd, "..") - cl.sendall('250 OK\r\n') - elif command == "RMD" or command == "XRMD": - try: - uos.rmdir(path) - cl.sendall('250 OK\r\n') - except: - cl.sendall('550 Fail\r\n') - elif command == "MKD" or command == "XMKD": - try: - uos.mkdir(path) - cl.sendall('250 OK\r\n') - except: - cl.sendall('550 Fail\r\n') - elif command == "SITE": - try: - exec(payload.replace('\0','\n')) - cl.sendall('250 OK\r\n') - except: - cl.sendall('550 Fail\r\n') - else: - cl.sendall("502 Unsupported command.\r\n") - # log_msg(2, - # "Unsupported command {} with payload {}".format(command, - # payload)) - # handle unexpected errors - except Exception as err: - log_msg(1, "Exception in exec_ftp_command: {}".format(err)) - # tidy up before leaving - client_busy = False - - -def log_msg(level, *args): - global verbose_l - if verbose_l >= level: - print(*args) - - -# close client and remove it from the list -def close_client(cl): - cl.setsockopt(socket.SOL_SOCKET, _SO_REGISTER_HANDLER, None) - cl.close() - for i, client in enumerate(client_list): - if client.command_client == cl: - del client_list[i] - break - - -def accept_ftp_connect(ftpsocket, local_addr): - # Accept new calls for the server - try: - client_list.append(FTP_client(ftpsocket, local_addr)) - except: - log_msg(1, "Attempt to connect failed") - # try at least to reject - try: - temp_client, temp_addr = ftpsocket.accept() - temp_client.close() - except: - pass - - -def num_ip(ip): - items = ip.split(".") - return (int(items[0]) << 24 | int(items[1]) << 16 | - int(items[2]) << 8 | int(items[3])) - - -def stop(): - global ftpsockets, datasocket - global client_list - global client_busy - - for client in client_list: - client.command_client.setsockopt(socket.SOL_SOCKET, - _SO_REGISTER_HANDLER, None) - client.command_client.close() - del client_list - client_list = [] - client_busy = False - for sock in ftpsockets: - sock.setsockopt(socket.SOL_SOCKET, _SO_REGISTER_HANDLER, None) - sock.close() - ftpsockets = [] - if datasocket is not None: - datasocket.close() - datasocket = None - - -# start listening for ftp connections on port 21 -def start(port=21, verbose=0, splash=True): - global ftpsockets, datasocket - global verbose_l - global client_list - global client_busy - - alloc_emergency_exception_buf(100) - verbose_l = verbose - client_list = [] - client_busy = False - - for interface in [network.AP_IF, network.STA_IF]: - wlan = network.WLAN(interface) - if not wlan.active(): - continue - - ifconfig = wlan.ifconfig() - addr = socket.getaddrinfo(ifconfig[0], port) - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - sock.bind(addr[0][4]) - sock.listen(1) - sock.setsockopt(socket.SOL_SOCKET, - _SO_REGISTER_HANDLER, - lambda s : accept_ftp_connect(s, ifconfig[0])) - ftpsockets.append(sock) - if splash: - print("FTP server started on {}:{}".format(ifconfig[0], port)) - - datasocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - datasocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - datasocket.bind(('0.0.0.0', str(_DATA_PORT))) - datasocket.listen(1) - datasocket.settimeout(10) - -def restart(port=21, verbose=0, splash=True): - stop() - sleep_ms(200) - start(port, verbose, splash) - - -start(splash=True) diff --git a/ports/esp32/modules/utelnetserver.py b/ports/esp32/modules/utelnetserver.py deleted file mode 100644 index 2c47c1749..000000000 --- a/ports/esp32/modules/utelnetserver.py +++ /dev/null @@ -1,109 +0,0 @@ -import socket -import network -import uos -import errno -from uio import IOBase - -last_client_socket = None -server_socket = None - -# Provide necessary functions for dupterm and replace telnet control characters that come in. -class TelnetWrapper(IOBase): - def __init__(self, socket): - self.socket = socket - self.discard_count = 0 - - def readinto(self, b): - readbytes = 0 - for i in range(len(b)): - try: - byte = 0 - # discard telnet control characters and - # null bytes - while(byte == 0): - byte = self.socket.recv(1)[0] - if byte == 0xFF: - self.discard_count = 2 - byte = 0 - elif self.discard_count > 0: - self.discard_count -= 1 - byte = 0 - - b[i] = byte - - readbytes += 1 - except (IndexError, OSError) as e: - if type(e) == IndexError or len(e.args) > 0 and e.args[0] == errno.EAGAIN: - if readbytes == 0: - return None - else: - return readbytes - else: - raise - return readbytes - - def write(self, data): - # we need to write all the data but it's a non-blocking socket - # so loop until it's all written eating EAGAIN exceptions - while len(data) > 0: - try: - written_bytes = self.socket.write(data) - data = data[written_bytes:] - except OSError as e: - if len(e.args) > 0 and e.args[0] == errno.EAGAIN: - # can't write yet, try again - pass - else: - # something else...propagate the exception - raise - - def close(self): - self.socket.close() - -# Attach new clients to dupterm and -# send telnet control characters to disable line mode -# and stop local echoing -def accept_telnet_connect(telnet_server): - global last_client_socket - - if last_client_socket: - # close any previous clients - uos.dupterm(None) - last_client_socket.close() - - last_client_socket, remote_addr = telnet_server.accept() - print("Telnet connection from:", remote_addr) - last_client_socket.setblocking(False) - last_client_socket.setsockopt(socket.SOL_SOCKET, 20, uos.dupterm_notify) - - last_client_socket.sendall(bytes([255, 252, 34])) # dont allow line mode - last_client_socket.sendall(bytes([255, 251, 1])) # turn off local echo - - uos.dupterm(TelnetWrapper(last_client_socket)) - -def stop(): - global server_socket, last_client_socket - uos.dupterm(None) - if server_socket: - server_socket.close() - if last_client_socket: - last_client_socket.close() - -# start listening for telnet connections on port 23 -def start(port=23): - stop() - global server_socket - server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - - ai = socket.getaddrinfo("0.0.0.0", port) - addr = ai[0][4] - - server_socket.bind(addr) - server_socket.listen(1) - server_socket.setsockopt(socket.SOL_SOCKET, 20, accept_telnet_connect) - - for i in (network.AP_IF, network.STA_IF): - wlan = network.WLAN(i) - if wlan.active(): - print("Telnet server started on {}:{}".format(wlan.ifconfig()[0], port)) diff --git a/ports/esp32/modules/xpt2046.py b/ports/esp32/modules/xpt2046.py deleted file mode 120000 index 2b56415bf..000000000 --- a/ports/esp32/modules/xpt2046.py +++ /dev/null @@ -1 +0,0 @@ -../../../lib/lv_bindings/driver/esp32/xpt2046.py \ No newline at end of file diff --git a/ports/unix/variants/lvgl/manifest.py b/ports/unix/variants/lvgl/manifest.py new file mode 100644 index 000000000..8dea677c1 --- /dev/null +++ b/ports/unix/variants/lvgl/manifest.py @@ -0,0 +1,3 @@ +include("$(PORT_DIR)/variants/manifest.py") +include("$(MPY_DIR)/extmod/asyncio") +include("$(MPY_DIR)/user_modules/lv_binding_micropython/ports/unix") \ No newline at end of file diff --git a/ports/unix/variants/lvgl/mpconfigvariant.h b/ports/unix/variants/lvgl/mpconfigvariant.h new file mode 100644 index 000000000..99e9d819e --- /dev/null +++ b/ports/unix/variants/lvgl/mpconfigvariant.h @@ -0,0 +1,36 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Damien P. George + * + * 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. + */ + +// Set base feature level. +#define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_EXTRA_FEATURES) + +// Enable extra Unix features. +#include "../mpconfigvariant_common.h" + +// Required for LVGL +#define MICROPY_ENABLE_SCHEDULER (1) +#define MICROPY_MODULE_BUILTIN_INIT (1) +#define MICROPY_PY_SYS_SETTRACE (0) \ No newline at end of file diff --git a/ports/unix/variants/lvgl/mpconfigvariant.mk b/ports/unix/variants/lvgl/mpconfigvariant.mk new file mode 100644 index 000000000..93572be8b --- /dev/null +++ b/ports/unix/variants/lvgl/mpconfigvariant.mk @@ -0,0 +1,4 @@ +# This is the default variant when you `make` the Unix port. + +FROZEN_MANIFEST ?= $(VARIANT_DIR)/manifest.py +USER_C_MODULES ?= ${TOP}/user_modules diff --git a/user_modules/lv_binding_micropython b/user_modules/lv_binding_micropython new file mode 160000 index 000000000..a2008e505 --- /dev/null +++ b/user_modules/lv_binding_micropython @@ -0,0 +1 @@ +Subproject commit a2008e505ceb44eafa3b1b08cb38d957d2721e95