diff --git a/components/badge23/CMakeLists.txt b/components/badge23/CMakeLists.txt index 90a2355b754ba8851d2b898152d338b63283a3cb..4c394395e8db8e5069bb810c3e3a7325e826d30c 100644 --- a/components/badge23/CMakeLists.txt +++ b/components/badge23/CMakeLists.txt @@ -3,7 +3,6 @@ idf_component_register( apa102LEDStrip.c audio.c captouch.c - display.c espan.c leds.c scope.c diff --git a/components/badge23/display.c b/components/badge23/display.c deleted file mode 100644 index 3a8629f0969506b7dd85ebd4f6c93a0c447e011f..0000000000000000000000000000000000000000 --- a/components/badge23/display.c +++ /dev/null @@ -1,110 +0,0 @@ -#include "badge23/display.h" - -#include <stdio.h> -#include <string.h> -#include <math.h> - -#include "esp_log.h" -#include "esp_system.h" -#include "freertos/FreeRTOS.h" - - -#include "../../usermodule/uctx/uctx/ctx.h" - -#include "flow3r_bsp.h" -#include "st3m_gfx.h" - - -typedef struct { - Ctx *ctx; - st3m_framebuffer_desc_t *desc; -} ctx_target_t; - -static void new_ctx_target(ctx_target_t *target, st3m_framebuffer_desc_t *desc) { - Ctx *ctx = ctx_new_for_framebuffer( - desc->buffer, - FLOW3R_BSP_DISPLAY_WIDTH, - FLOW3R_BSP_DISPLAY_HEIGHT, - FLOW3R_BSP_DISPLAY_WIDTH * 2, - CTX_FORMAT_RGB565_BYTESWAPPED - ); - assert(ctx != NULL); - - int32_t offset_x = FLOW3R_BSP_DISPLAY_WIDTH / 2; - int32_t offset_y = FLOW3R_BSP_DISPLAY_HEIGHT / 2; - // rotate by 180 deg and translate x and y by 120 px to have (0,0) at the center of the screen - ctx_apply_transform(ctx,-1,0,offset_x,0,-1,offset_y,0,0,1); - - target->ctx = ctx; - target->desc = desc; -} - -static ctx_target_t targets[ST3M_GFX_NBUFFERS]; - -static void display_loading_splash(ctx_target_t *target) { - ctx_rgb(target->ctx, 0.157, 0.129, 0.167); - ctx_rectangle(target->ctx, -120, -120, 240, 240); - ctx_fill(target->ctx); - - ctx_move_to(target->ctx, 0, 0); - ctx_rgb(target->ctx, 0.9, 0.9, 0.9); - ctx_text_align(target->ctx, CTX_TEXT_ALIGN_CENTER); - ctx_text_baseline(target->ctx, CTX_TEXT_BASELINE_ALPHABETIC); - ctx_text(target->ctx, "Loading..."); -} - -static ctx_target_t *next_target(void) { - st3m_framebuffer_desc_t *desc = st3m_gfx_framebuffer_get(portMAX_DELAY); - if (targets[desc->num].ctx == NULL) { - new_ctx_target(&targets[desc->num], desc); - } - - return &targets[desc->num]; -} - -static bool initialized = false; -static ctx_target_t *sync_target = NULL; - -void display_init() { - // HACK: needed until we have new async gfx api. - assert(ST3M_GFX_NBUFFERS == 1); - - st3m_gfx_init(); - for (int i = 0; i < ST3M_GFX_NBUFFERS; i++) { - targets[i].ctx = NULL; - targets[i].desc = NULL; - } - - ctx_target_t *tgt = next_target(); - display_loading_splash(tgt); - st3m_gfx_framebuffer_queue(tgt->desc); - - sync_target = next_target(); - flow3r_bsp_display_set_backlight(100); - initialized = true; -} - - -void display_update(){ - if (!initialized) { - return; - } - - st3m_gfx_framebuffer_queue(sync_target->desc); - ctx_target_t *tgt = next_target(); - assert(tgt == sync_target); -} - -void display_set_backlight(uint8_t percent) { - if (!initialized) { - return; - } - flow3r_bsp_display_set_backlight(percent); -} - -Ctx *display_global_ctx(void) { - if (!initialized) { - return NULL; - } - return sync_target->ctx; -} \ No newline at end of file diff --git a/components/badge23/espan.c b/components/badge23/espan.c index a2aa2ff754e131d3cebc2abf4b110aacceae6596..26e2921304bd1955ca1d07ab4036fd050eeaee2d 100644 --- a/components/badge23/espan.c +++ b/components/badge23/espan.c @@ -1,16 +1,16 @@ #include "badge23/captouch.h" #include "badge23/audio.h" #include "badge23/leds.h" -#include "badge23/display.h" #include "badge23/spio.h" #include "badge23/lock.h" #include "flow3r_bsp.h" +#include "st3m_gfx.h" #include "esp_log.h" #include "driver/i2c.h" #include "driver/spi_master.h" -#include <freertos/timers.h> +#include "freertos/timers.h" #include <stdio.h> #include <string.h> @@ -92,11 +92,13 @@ void locks_init(){ mutex_LED = xSemaphoreCreateMutex(); } -void os_app_main(void) -{ +void os_app_early_init(void) { // Initialize display first as that gives us a nice splash screen. - display_init(); + st3m_gfx_init(); +} +void os_app_main(void) +{ locks_init(); ESP_LOGI(TAG, "Starting on %s...", flow3r_bsp_hw_name); ESP_ERROR_CHECK(i2c_master_init()); diff --git a/components/badge23/include/badge23/display.h b/components/badge23/include/badge23/display.h deleted file mode 100644 index ed043c27deb89247baaf3ca1825237a2721afd69..0000000000000000000000000000000000000000 --- a/components/badge23/include/badge23/display.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include <stdbool.h> -#include <stdint.h> -#include "../../usermodule/uctx/uctx/ctx.h" - -void display_init(); -void display_set_backlight(uint8_t percent); - -// Transitional functionality operating on global framebuffer and global ctx. -// Will get replaced with 'real' ctx rendering system. -void display_ctx_init(); -void display_update(); -Ctx *display_global_ctx(void); diff --git a/components/badge23/include/badge23/espan.h b/components/badge23/include/badge23/espan.h index 7915f33e09ea0752b7b01903d018534cca7d6dd6..b118335d69a82f0daaf8fea28a194fa6691e39c4 100644 --- a/components/badge23/include/badge23/espan.h +++ b/components/badge23/include/badge23/espan.h @@ -1,4 +1,5 @@ #pragma once #include <stdint.h> +void os_app_early_init(void); void os_app_main(void); uint8_t hardware_is_initialized(void); diff --git a/usermodule/uctx/.gitignore b/components/ctx/.gitignore similarity index 100% rename from usermodule/uctx/.gitignore rename to components/ctx/.gitignore diff --git a/components/ctx/CMakeLists.txt b/components/ctx/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..e368ff48f17ce8878f11761bf64e5067ecdb8303 --- /dev/null +++ b/components/ctx/CMakeLists.txt @@ -0,0 +1,7 @@ +idf_component_register( + SRCS + ctx.c + INCLUDE_DIRS + . + ./fonts/ +) \ No newline at end of file diff --git a/usermodule/uctx/LICENSE b/components/ctx/LICENSE similarity index 100% rename from usermodule/uctx/LICENSE rename to components/ctx/LICENSE diff --git a/components/ctx/ctx.c b/components/ctx/ctx.c new file mode 100644 index 0000000000000000000000000000000000000000..6edde39a15a37fae46e75bdb89234e39f5e18565 --- /dev/null +++ b/components/ctx/ctx.c @@ -0,0 +1,3 @@ +#include "ctx_config.h" +#define CTX_IMPLEMENTATION +#include "ctx.h" \ No newline at end of file diff --git a/usermodule/uctx/uctx/ctx.h b/components/ctx/ctx.h similarity index 100% rename from usermodule/uctx/uctx/ctx.h rename to components/ctx/ctx.h diff --git a/sim/wasm/ctx_config.h b/components/ctx/ctx_config.h similarity index 90% rename from sim/wasm/ctx_config.h rename to components/ctx/ctx_config.h index 9e70abc56c2cc71934a96d344754212ed0205b33..a466619655f84db677d5d96bccadf3dee2fa3aa7 100644 --- a/sim/wasm/ctx_config.h +++ b/components/ctx/ctx_config.h @@ -1,6 +1,6 @@ #pragma once -// Keep in sync with defines in usermodule/uctx/uctx.c. +#include <stdint.h> #define CTX_TINYVG 1 #define CTX_TVG_STDIO 0 @@ -13,10 +13,10 @@ #define CTX_ENABLE_FLOAT 0 #define CTX_32BIT_SEGMENTS 0 #define CTX_ENABLE_RGBA8 1 -#define CTX_ENABLE_RGB332 1 -#define CTX_ENABLE_GRAY1 1 -#define CTX_ENABLE_GRAY2 1 -#define CTX_ENABLE_GRAY4 1 +#define CTX_ENABLE_RGB332 0 +#define CTX_ENABLE_GRAY1 0 +#define CTX_ENABLE_GRAY2 0 +#define CTX_ENABLE_GRAY4 0 #define CTX_ENABLE_RGB565 1 #define CTX_ENABLE_RGB565_BYTESWAPPED 1 #define CTX_ENABLE_CBRLE 0 @@ -35,8 +35,8 @@ #define CTX_MAX_DASHES 10 #define CTX_MAX_GRADIENT_STOPS 10 #define CTX_CM 0 -#define CTX_SHAPE_CACHE 0 -#define CTX_SHAPE_CACHE_DEFAULT 0 +#define CTX_SHAPE_CACHE 1 +#define CTX_SHAPE_CACHE_DEFAULT 1 #define CTX_RASTERIZER_MAX_CIRCLE_SEGMENTS 128 #define CTX_NATIVE_GRAYA8 0 #define CTX_ENABLE_SHADOW_BLUR 0 @@ -64,7 +64,7 @@ #define CTX_BAREMETAL 1 -#define CTX_EVENTS 1 +#define CTX_EVENTS 0 #define CTX_MAX_DEVICES 1 #define CTX_MAX_KEYBINDINGS 16 #define CTX_RASTERIZER 1 diff --git a/usermodule/uctx/fonts/Arimo-Bold.h b/components/ctx/fonts/Arimo-Bold.h similarity index 100% rename from usermodule/uctx/fonts/Arimo-Bold.h rename to components/ctx/fonts/Arimo-Bold.h diff --git a/usermodule/uctx/fonts/Arimo-BoldItalic.h b/components/ctx/fonts/Arimo-BoldItalic.h similarity index 100% rename from usermodule/uctx/fonts/Arimo-BoldItalic.h rename to components/ctx/fonts/Arimo-BoldItalic.h diff --git a/usermodule/uctx/fonts/Arimo-Italic.h b/components/ctx/fonts/Arimo-Italic.h similarity index 100% rename from usermodule/uctx/fonts/Arimo-Italic.h rename to components/ctx/fonts/Arimo-Italic.h diff --git a/usermodule/uctx/fonts/Arimo-Regular.h b/components/ctx/fonts/Arimo-Regular.h similarity index 100% rename from usermodule/uctx/fonts/Arimo-Regular.h rename to components/ctx/fonts/Arimo-Regular.h diff --git a/usermodule/uctx/fonts/Cousine-Bold.h b/components/ctx/fonts/Cousine-Bold.h similarity index 100% rename from usermodule/uctx/fonts/Cousine-Bold.h rename to components/ctx/fonts/Cousine-Bold.h diff --git a/usermodule/uctx/fonts/Cousine-Regular.h b/components/ctx/fonts/Cousine-Regular.h similarity index 100% rename from usermodule/uctx/fonts/Cousine-Regular.h rename to components/ctx/fonts/Cousine-Regular.h diff --git a/usermodule/uctx/fonts/Roboto-Bold.h b/components/ctx/fonts/Roboto-Bold.h similarity index 100% rename from usermodule/uctx/fonts/Roboto-Bold.h rename to components/ctx/fonts/Roboto-Bold.h diff --git a/usermodule/uctx/fonts/Roboto-BoldItalic.h b/components/ctx/fonts/Roboto-BoldItalic.h similarity index 100% rename from usermodule/uctx/fonts/Roboto-BoldItalic.h rename to components/ctx/fonts/Roboto-BoldItalic.h diff --git a/usermodule/uctx/fonts/Roboto-Italic.h b/components/ctx/fonts/Roboto-Italic.h similarity index 100% rename from usermodule/uctx/fonts/Roboto-Italic.h rename to components/ctx/fonts/Roboto-Italic.h diff --git a/usermodule/uctx/fonts/Roboto-Regular.h b/components/ctx/fonts/Roboto-Regular.h similarity index 100% rename from usermodule/uctx/fonts/Roboto-Regular.h rename to components/ctx/fonts/Roboto-Regular.h diff --git a/usermodule/uctx/fonts/Tinos-Bold.h b/components/ctx/fonts/Tinos-Bold.h similarity index 100% rename from usermodule/uctx/fonts/Tinos-Bold.h rename to components/ctx/fonts/Tinos-Bold.h diff --git a/usermodule/uctx/fonts/Tinos-Regular.h b/components/ctx/fonts/Tinos-Regular.h similarity index 100% rename from usermodule/uctx/fonts/Tinos-Regular.h rename to components/ctx/fonts/Tinos-Regular.h diff --git a/components/flow3r_bsp/flow3r_bsp_gc9a01.c b/components/flow3r_bsp/flow3r_bsp_gc9a01.c index 0c7f51e98af5b4e76a19df43e7e9ae1e1994b7e5..400bc539034539944f946498842a07a9a603375d 100644 --- a/components/flow3r_bsp/flow3r_bsp_gc9a01.c +++ b/components/flow3r_bsp/flow3r_bsp_gc9a01.c @@ -80,6 +80,8 @@ #define MADCTL_BGR 0x08 #define MADCTL_MH 0x04 +static const char *TAG = "flow3r-bsp-gc9a01"; + // Transaction 'user' structure as used by SPI transactions to the display. // Provides enough data for the pre-transaction callback to be able to set the // DC pin as needed. @@ -551,7 +553,13 @@ static esp_err_t flow3r_bsp_gc9a01_blit_next(flow3r_bsp_gc9a01_blit_t *blit) { blit->left -= size; blit->fb += size; - return spi_device_queue_trans(blit->gc9a01->spi, &blit->spi_tx, portMAX_DELAY); + esp_err_t res = spi_device_queue_trans(blit->gc9a01->spi, &blit->spi_tx, portMAX_DELAY); + if (res != ESP_OK) { + + ESP_LOGE(TAG, "spi_device_queue_trans (size %d, buf %p, dma capab: %d, largest block: %d): %s", + size, blit->fb, esp_ptr_dma_capable(blit->fb), heap_caps_get_largest_free_block(MALLOC_CAP_DMA), esp_err_to_name(res)); + } + return res; } static esp_err_t flow3r_bsp_gc9a01_blit_start(flow3r_bsp_gc9a01_t *gc9a01, flow3r_bsp_gc9a01_blit_t *blit, const uint16_t *fb) { diff --git a/components/st3m/CMakeLists.txt b/components/st3m/CMakeLists.txt index 7196e6632afe7bed752925c7b8348f807d8f2c00..33bcf75e02a9823af8ffd3773aae2d82bf0c6001 100644 --- a/components/st3m/CMakeLists.txt +++ b/components/st3m/CMakeLists.txt @@ -1,8 +1,10 @@ idf_component_register( SRCS st3m_gfx.c + st3m_counter.c INCLUDE_DIRS . REQUIRES flow3r_bsp + ctx ) diff --git a/components/st3m/st3m_gfx.c b/components/st3m/st3m_gfx.c index 8aa4ae0e665eddeb6bedd1fa71c626027f312b5d..1fd02d3ff8fd0c76a8bc0af0767088e530a23bc9 100644 --- a/components/st3m/st3m_gfx.c +++ b/components/st3m/st3m_gfx.c @@ -4,33 +4,134 @@ #include "esp_system.h" #include "esp_log.h" +#include "esp_task.h" #include "freertos/FreeRTOS.h" #include "freertos/queue.h" +#include "ctx_config.h" +#include "ctx.h" + #include "flow3r_bsp.h" +#include "st3m_counter.h" + +static const char *TAG = "st3m-gfx"; -// Actual framebuffers, efficiently accessible via DMA. -static DMA_ATTR uint16_t framebuffers[ST3M_GFX_NBUFFERS][FLOW3R_BSP_DISPLAY_WIDTH * FLOW3R_BSP_DISPLAY_HEIGHT]; +// SRAM framebuffer into which ctx drawlists will be rasterized. After +// rasterization, their contents will be copied into SPIRAM. Then, the ESP SPI +// driver will piecewise copy the buffer back into DMA-able memory to send it +// over to the display. +// +// This Rube Goldberg contraption is still faster than directly rasterizing into +// SPIRAM (~20% faster). Ideally we would also keep both buffers in DMAble SRAM, +// but we don't have enough SRAM for that. +static uint16_t framebuffer_staging[240*240]; + +// framebuffer_staging-backed Ctx instance, used to render drawlists into +// framebuffer_staging. +static Ctx *framebuffer_staging_ctx; static st3m_framebuffer_desc_t framebuffer_descs[ST3M_GFX_NBUFFERS]; +static st3m_ctx_desc_t dctx_descs[ST3M_GFX_NCTX]; + // Queue of free framebuffer descriptors, written into by crtc once rendered, // read from by rasterizer when new frame starts. static QueueHandle_t framebuffer_freeq = NULL; - // Queue of framebuffer descriptors to blit out. static QueueHandle_t framebuffer_blitq = NULL; +static st3m_counter_rate_t blit_rate; +static st3m_counter_timer_t blit_read_time; +static st3m_counter_timer_t blit_work_time; +static st3m_counter_timer_t blit_write_time; + +static QueueHandle_t dctx_freeq = NULL; +static QueueHandle_t dctx_rastq = NULL; + +static st3m_counter_rate_t rast_rate; +static st3m_counter_timer_t rast_read_fb_time; +static st3m_counter_timer_t rast_read_dctx_time; +static st3m_counter_timer_t rast_work_time; +static st3m_counter_timer_t rast_write_time; + +static TaskHandle_t crtc_task; +static TaskHandle_t rast_task; + static void st3m_gfx_crtc_task(void *_arg) { (void)_arg; while (true) { int descno; + + int64_t start = esp_timer_get_time(); xQueueReceive(framebuffer_blitq, &descno, portMAX_DELAY); + int64_t end = esp_timer_get_time(); + st3m_counter_timer_sample(&blit_read_time, end-start); + start = esp_timer_get_time(); flow3r_bsp_display_send_fb(framebuffer_descs[descno].buffer); + end = esp_timer_get_time(); + st3m_counter_timer_sample(&blit_work_time, end-start); + start = esp_timer_get_time(); xQueueSend(framebuffer_freeq, &descno, portMAX_DELAY); + end = esp_timer_get_time(); + st3m_counter_timer_sample(&blit_write_time, end-start); + + st3m_counter_rate_sample(&blit_rate); + + if (st3m_counter_rate_report(&blit_rate, 1)) { + float rate = 1000000.0 / st3m_counter_rate_average(&blit_rate); + float read = st3m_counter_timer_average(&blit_read_time) / 1000.0; + float work = st3m_counter_timer_average(&blit_work_time) / 1000.0; + float write = st3m_counter_timer_average(&blit_write_time) / 1000.0; + ESP_LOGI(TAG, "blitting: %.3f/sec, read %.3fms, work %.3fms, write %.3fms", rate, read, work, write); + } + } +} + +static void st3m_gfx_rast_task(void *_arg) { + (void)_arg; + + while (true) { + int fb_descno, dctx_descno; + int64_t start = esp_timer_get_time(); + xQueueReceive(framebuffer_freeq, &fb_descno, portMAX_DELAY); + int64_t end = esp_timer_get_time(); + st3m_counter_timer_sample(&rast_read_fb_time, end-start); + + start = esp_timer_get_time(); + xQueueReceive(dctx_rastq, &dctx_descno, portMAX_DELAY); + end = esp_timer_get_time(); + st3m_counter_timer_sample(&rast_read_dctx_time, end-start); + + + start = esp_timer_get_time(); + + // Render to staging and memcpy to framebuffer. + ctx_render_ctx(dctx_descs[dctx_descno].ctx, framebuffer_staging_ctx); + memcpy(framebuffer_descs[fb_descno].buffer, framebuffer_staging, 240*240*2); + ctx_drawlist_clear(dctx_descs[dctx_descno].ctx); + + end = esp_timer_get_time(); + st3m_counter_timer_sample(&rast_work_time, end-start); + + start = esp_timer_get_time(); + xQueueSend(dctx_freeq, &dctx_descno, portMAX_DELAY); + xQueueSend(framebuffer_blitq, &fb_descno, portMAX_DELAY); + end = esp_timer_get_time(); + st3m_counter_timer_sample(&rast_write_time, end-start); + + st3m_counter_rate_sample(&rast_rate); + + if (st3m_counter_rate_report(&rast_rate, 1)) { + float rate = 1000000.0 / st3m_counter_rate_average(&rast_rate); + float read_fb = st3m_counter_timer_average(&rast_read_fb_time) / 1000.0; + float read_dctx = st3m_counter_timer_average(&rast_read_dctx_time) / 1000.0; + float work = st3m_counter_timer_average(&rast_work_time) / 1000.0; + float write = st3m_counter_timer_average(&rast_write_time) / 1000.0; + ESP_LOGI(TAG, "rasterization: %.3f/sec, read fb %.3fms, read dctx %.3fms, work %.3fms, write %.3fms", rate, read_fb, read_dctx, work, write); + } } } @@ -38,40 +139,121 @@ void st3m_gfx_init(void) { // Make sure we're not being re-initialized. assert(framebuffer_freeq == NULL); + st3m_counter_rate_init(&blit_rate); + st3m_counter_timer_init(&blit_read_time); + st3m_counter_timer_init(&blit_work_time); + st3m_counter_timer_init(&blit_write_time); + + st3m_counter_rate_init(&rast_rate); + st3m_counter_timer_init(&rast_read_fb_time); + st3m_counter_timer_init(&rast_read_dctx_time); + st3m_counter_timer_init(&rast_work_time); + st3m_counter_timer_init(&rast_write_time); + flow3r_bsp_display_init(); + flow3r_bsp_display_set_backlight(100); // Create framebuffer queues. - framebuffer_freeq = xQueueCreate(2, sizeof(int)); + framebuffer_freeq = xQueueCreate(ST3M_GFX_NBUFFERS+1, sizeof(int)); assert(framebuffer_freeq != NULL); - framebuffer_blitq = xQueueCreate(2, sizeof(int)); + framebuffer_blitq = xQueueCreate(ST3M_GFX_NBUFFERS+1, sizeof(int)); assert(framebuffer_blitq != NULL); - // Zero out framebuffers and set up descriptors. + // Create drawlist ctx queues. + dctx_freeq = xQueueCreate(ST3M_GFX_NCTX+1, sizeof(int)); + assert(dctx_freeq != NULL); + dctx_rastq = xQueueCreate(ST3M_GFX_NCTX+1, sizeof(int)); + assert(dctx_rastq != NULL); + + // Create staging framebuffer Ctx. + framebuffer_staging_ctx = ctx_new_for_framebuffer( + framebuffer_staging, + FLOW3R_BSP_DISPLAY_WIDTH, + FLOW3R_BSP_DISPLAY_HEIGHT, + FLOW3R_BSP_DISPLAY_WIDTH * 2, + CTX_FORMAT_RGB565_BYTESWAPPED + ); + assert(framebuffer_staging_ctx != NULL); + // Rotate by 180 deg and translate x and y by 120 px to have (0,0) at the center of the screen + int32_t offset_x = FLOW3R_BSP_DISPLAY_WIDTH / 2; + int32_t offset_y = FLOW3R_BSP_DISPLAY_HEIGHT / 2; + ctx_apply_transform(framebuffer_staging_ctx, -1, 0, offset_x, 0, -1, offset_y, 0, 0, 1); + for (int i = 0; i < ST3M_GFX_NBUFFERS; i++) { - memset(&framebuffers[i], 0, FLOW3R_BSP_DISPLAY_WIDTH * FLOW3R_BSP_DISPLAY_HEIGHT * 2); - st3m_framebuffer_desc_t *desc = &framebuffer_descs[i]; - desc->num = i; - desc->buffer = framebuffers[i]; + // Setup framebuffer descriptor. + st3m_framebuffer_desc_t *fb_desc = &framebuffer_descs[i]; + fb_desc->num = i; + fb_desc->buffer = malloc(2 * FLOW3R_BSP_DISPLAY_WIDTH * FLOW3R_BSP_DISPLAY_HEIGHT); + assert(fb_desc->buffer != NULL); + memset(fb_desc->buffer, 0, 2 * FLOW3R_BSP_DISPLAY_WIDTH * FLOW3R_BSP_DISPLAY_HEIGHT); // Push descriptor to freeq. BaseType_t res = xQueueSend(framebuffer_freeq, &i, 0); assert(res == pdTRUE); } + for (int i = 0; i < ST3M_GFX_NCTX; i++) { + // Setup dctx descriptor. + st3m_ctx_desc_t *dctx_desc = &dctx_descs[i]; + dctx_desc->num = i; + dctx_desc->ctx = ctx_new_drawlist(FLOW3R_BSP_DISPLAY_WIDTH, FLOW3R_BSP_DISPLAY_HEIGHT); + assert(dctx_desc->ctx != NULL); + + // Push descriptor to freeq. + BaseType_t res = xQueueSend(dctx_freeq, &i, 0); + assert(res == pdTRUE); + } + // Start crtc. - BaseType_t res = xTaskCreate(st3m_gfx_crtc_task, "crtc", 2048, NULL, configMAX_PRIORITIES - 2, NULL); + BaseType_t res = xTaskCreate(st3m_gfx_crtc_task, "crtc", 4096, NULL, ESP_TASK_PRIO_MIN+3, &crtc_task); + assert(res == pdPASS); + + // Start rast. + res = xTaskCreate(st3m_gfx_rast_task, "rast", 4096, NULL, ESP_TASK_PRIO_MIN+1, &rast_task); assert(res == pdPASS); } -st3m_framebuffer_desc_t *st3m_gfx_framebuffer_get(TickType_t ticks_to_wait) { +st3m_ctx_desc_t *st3m_gfx_drawctx_free_get(TickType_t ticks_to_wait) { int descno; - BaseType_t res = xQueueReceive(framebuffer_freeq, &descno, ticks_to_wait); + BaseType_t res = xQueueReceive(dctx_freeq, &descno, ticks_to_wait); if (res != pdTRUE) { return NULL; } - return &framebuffer_descs[descno]; + return &dctx_descs[descno]; } -void st3m_gfx_framebuffer_queue(st3m_framebuffer_desc_t *desc) { - xQueueSend(framebuffer_blitq, &desc->num, portMAX_DELAY); +void st3m_gfx_drawctx_pipe_put(st3m_ctx_desc_t *desc) { + xQueueSend(dctx_rastq, &desc->num, portMAX_DELAY); +} + +uint8_t st3m_gfx_drawctx_pipe_full(void) { + return uxQueueSpacesAvailable(dctx_rastq) == 0; +} + +void st3m_gfx_flush(void) { + ESP_LOGW(TAG, "Pipeline flush/reset requested..."); + // Drain all workqs and freeqs. + xQueueReset(dctx_freeq); + xQueueReset(dctx_rastq); + xQueueReset(framebuffer_freeq); + xQueueReset(framebuffer_blitq); + + // Delay, making sure pipeline tasks have returned all used descriptors. One + // second is enough to make sure we've processed everything. + vTaskDelay(1000 / portTICK_RATE_MS); + + // And drain again. + xQueueReset(framebuffer_freeq); + xQueueReset(dctx_freeq); + + // Now, re-submit all descriptors to freeqs. + for (int i = 0; i < ST3M_GFX_NBUFFERS; i++) { + BaseType_t res = xQueueSend(framebuffer_freeq, &i, 0); + assert(res == pdTRUE); + } + for (int i = 0; i < ST3M_GFX_NCTX; i++) { + BaseType_t res = xQueueSend(dctx_freeq, &i, 0); + assert(res == pdTRUE); + } + ESP_LOGW(TAG, "Pipeline flush/reset done."); } \ No newline at end of file diff --git a/components/st3m/st3m_gfx.h b/components/st3m/st3m_gfx.h index 55849fd682ae98170eff8788051e94060868aecc..53c6c7880935d767c0bc1067efc0203e626044f3 100644 --- a/components/st3m/st3m_gfx.h +++ b/components/st3m/st3m_gfx.h @@ -2,18 +2,53 @@ #include "freertos/FreeRTOS.h" -// Each buffer takes ~116kB SRAM. While one framebuffer is being blitted, the +#include "ctx_config.h" +#include "ctx.h" + +// Each buffer takes ~116kB SPIRAM. While one framebuffer is being blitted, the // other one is being written to by the rasterizer. -#define ST3M_GFX_NBUFFERS 1 +#define ST3M_GFX_NBUFFERS 2 +// More ctx drawlists than buffers so that micropython doesn't get starved when +// pipeline runs in lockstep. +#define ST3M_GFX_NCTX 2 // A framebuffer descriptor, pointing at a framebuffer. typedef struct { + // The numeric ID of this descriptor. int num; + // SPIRAM buffer. uint16_t *buffer; } st3m_framebuffer_desc_t; +// Initialize the gfx subsystem of st3m, includng the rasterization and +// crtx/blitter pipeline. void st3m_gfx_init(void); -st3m_framebuffer_desc_t *st3m_gfx_framebuffer_get(TickType_t ticks_to_wait); +// A drawlist ctx descriptor, pointing to a drawlist-backed Ctx. +typedef struct { + // The numeric ID of this descriptor. + int num; + Ctx *ctx; +} st3m_ctx_desc_t; + +// Get a free drawlist ctx to draw into. +// +// ticks_to_wait can be used to limit the time to wait for a free ctx +// descriptor, or portDELAY_MAX can be specified to wait forever. If the timeout +// expires, NULL will be returned. +st3m_ctx_desc_t *st3m_gfx_drawctx_free_get(TickType_t ticks_to_wait); + +// Submit a filled ctx descriptor to the rasterization pipeline. +void st3m_gfx_drawctx_pipe_put(st3m_ctx_desc_t *desc); + +// Returns true if the rasterizaiton pipeline submission would block. +uint8_t st3m_gfx_drawctx_pipe_full(void); -void st3m_gfx_framebuffer_queue(st3m_framebuffer_desc_t *desc); \ No newline at end of file +// Flush any in-flight pipelined work, resetting the free ctx/framebuffer queues +// to their initial state. This should be called if there has been any drawlist +// ctx dropped (ie. drawctx_free_get was called but then drawctx_pipe_put +// wasn't, for exaple if Micropython restarted). +// +// This causes a graphical disturbance and shouldn't be called during normal +// operation. +void st3m_gfx_flush(void); \ No newline at end of file diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 9c48a075709a06037c948ca6af2a5864e20e0269..6f00a3cd8ba1f52ed9f813baed6ce8bdc5a9a90e 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -102,9 +102,12 @@ set(MICROPY_SOURCE_QSTR ) set(IDF_COMPONENTS - app_update badge23 flow3r_bsp + st3m + ctx + + app_update bootloader_support bt driver diff --git a/micropython/ports/esp32/main.c b/micropython/ports/esp32/main.c index 7b7ac36be12f24f591398c3d01e72b392db99261..eeb0cd5d8d7dfa26aa832c627b277473f1b86971 100644 --- a/micropython/ports/esp32/main.c +++ b/micropython/ports/esp32/main.c @@ -69,7 +69,7 @@ #endif // MicroPython runs as a task under FreeRTOS -#define MP_TASK_PRIORITY (ESP_TASK_PRIO_MIN + 1) +#define MP_TASK_PRIORITY (ESP_TASK_PRIO_MIN + 2) #define MP_TASK_STACK_SIZE (16 * 1024) // Set the margin for detecting stack overflow, depending on the CPU architecture. @@ -240,6 +240,8 @@ void app_main(void) { MICROPY_BOARD_STARTUP(); // Create and transfer control to the MicroPython task. + + os_app_early_init(); xTaskCreatePinnedToCore(mp_task, "mp_task", MP_TASK_STACK_SIZE / sizeof(StackType_t), NULL, MP_TASK_PRIORITY, &mp_main_task_handle, MP_TASK_COREID); os_app_main(); // ./badge23/ entry point } diff --git a/usermodule/micropython.cmake b/usermodule/micropython.cmake index 326524e3bb510b6bfa6ff877ab30b44e14eadb3a..03ce93dbd18fd63bb291f63b1a06ab53a3c2b09a 100644 --- a/usermodule/micropython.cmake +++ b/usermodule/micropython.cmake @@ -11,15 +11,11 @@ target_sources(usermod_badge23 INTERFACE ${CMAKE_CURRENT_LIST_DIR}/mp_badge_link.c ${CMAKE_CURRENT_LIST_DIR}/mp_synth.c ${CMAKE_CURRENT_LIST_DIR}/mp_kernel.c + ${CMAKE_CURRENT_LIST_DIR}/mp_uctx.c ) target_include_directories(usermod_badge23 INTERFACE ${CMAKE_CURRENT_LIST_DIR} ) -target_link_libraries(usermod INTERFACE usermod_badge23) - - - -#Also add uctx as a usermodule -include(${CMAKE_CURRENT_LIST_DIR}/uctx/uctx/micropython.cmake) +target_link_libraries(usermod INTERFACE usermod_badge23) \ No newline at end of file diff --git a/usermodule/mp_hardware.c b/usermodule/mp_hardware.c index fcabf2cd6235dac41ddcf718c841718da9189a77..b7b62c4dffbf7dc45da65376ef91210ab40cebca 100644 --- a/usermodule/mp_hardware.c +++ b/usermodule/mp_hardware.c @@ -13,11 +13,14 @@ #include "badge23/audio.h" #include "badge23/captouch.h" -#include "badge23/display.h" #include "badge23/spio.h" #include "badge23/espan.h" #include "flow3r_bsp.h" +#include "st3m_gfx.h" + +#include "ctx_config.h" +#include "ctx.h" mp_obj_t mp_ctx_from_ctx(Ctx *ctx); @@ -31,15 +34,9 @@ STATIC mp_obj_t mp_captouch_calibration_active(void) { } STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_captouch_calibration_active_obj, mp_captouch_calibration_active); -STATIC mp_obj_t mp_display_update(void) { - display_update(); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_display_update_obj, mp_display_update); - STATIC mp_obj_t mp_display_set_backlight(mp_obj_t percent_in) { uint8_t percent = mp_obj_get_int(percent_in); - display_set_backlight(percent); + flow3r_bsp_display_set_backlight(percent); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_display_set_backlight_obj, mp_display_set_backlight); @@ -172,14 +169,16 @@ STATIC mp_obj_t mp_version(void) { } STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_version_obj, mp_version); -STATIC mp_obj_t mp_get_ctx(size_t n_args, const mp_obj_t *args) { - Ctx *ctx = NULL; - // This might be called before the ctx is ready. - // HACK: this will go away with the new drawing API. - while ((ctx = display_global_ctx()) == NULL) { - vTaskDelay(100 / portTICK_PERIOD_MS); +static st3m_ctx_desc_t *gfx_last_desc = NULL; + +STATIC mp_obj_t mp_get_ctx(void) { + if (gfx_last_desc == NULL) { + gfx_last_desc = st3m_gfx_drawctx_free_get(0); + if (gfx_last_desc == NULL) { + return mp_const_none; + } } - mp_obj_t mp_ctx = mp_ctx_from_ctx(ctx); + mp_obj_t mp_ctx = mp_ctx_from_ctx(gfx_last_desc->ctx); return mp_ctx; } STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_get_ctx_obj, mp_get_ctx); @@ -193,6 +192,31 @@ STATIC mp_obj_t mp_freertos_sleep(mp_obj_t ms_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_freertos_sleep_obj, mp_freertos_sleep); +STATIC mp_obj_t mp_display_update(mp_obj_t in_ctx) { + // TODO(q3k): check in_ctx? Or just drop from API? + + if (gfx_last_desc != NULL) { + st3m_gfx_drawctx_pipe_put(gfx_last_desc); + gfx_last_desc = NULL; + } + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_display_update_obj, mp_display_update); + +STATIC mp_obj_t mp_display_pipe_full(void) { + if (st3m_gfx_drawctx_pipe_full()) { + return mp_const_true; + } + return mp_const_false; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_display_pipe_full_obj, mp_display_pipe_full); + +STATIC mp_obj_t mp_display_pipe_flush(void) { + st3m_gfx_flush(); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_display_pipe_flush_obj, mp_display_pipe_flush); + STATIC const mp_rom_map_elem_t mp_module_hardware_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_badge_audio) }, { MP_ROM_QSTR(MP_QSTR_init_done), MP_ROM_PTR(&mp_init_done_obj) }, @@ -219,6 +243,8 @@ STATIC const mp_rom_map_elem_t mp_module_hardware_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_dump_all_sources), MP_ROM_PTR(&mp_dump_all_sources_obj) }, { MP_ROM_QSTR(MP_QSTR_display_update), MP_ROM_PTR(&mp_display_update_obj) }, { MP_ROM_QSTR(MP_QSTR_freertos_sleep), MP_ROM_PTR(&mp_freertos_sleep_obj) }, + { MP_ROM_QSTR(MP_QSTR_display_pipe_full), MP_ROM_PTR(&mp_display_pipe_full_obj) }, + { MP_ROM_QSTR(MP_QSTR_display_pipe_flush), MP_ROM_PTR(&mp_display_pipe_flush_obj) }, { MP_ROM_QSTR(MP_QSTR_display_set_backlight), MP_ROM_PTR(&mp_display_set_backlight_obj) }, { MP_ROM_QSTR(MP_QSTR_version), MP_ROM_PTR(&mp_version_obj) }, { MP_ROM_QSTR(MP_QSTR_get_ctx), MP_ROM_PTR(&mp_get_ctx_obj) }, diff --git a/usermodule/uctx/uctx/uctx.c b/usermodule/mp_uctx.c similarity index 73% rename from usermodule/uctx/uctx/uctx.c rename to usermodule/mp_uctx.c index cce8f8140e45659d9e242e63d56ccf83dd628bf3..f8cfb288d9147f55b9f794a8f92df3d171d788f2 100644 --- a/usermodule/uctx/uctx/uctx.c +++ b/usermodule/mp_uctx.c @@ -6,193 +6,12 @@ #include "py/objarray.h" #include "py/runtime.h" -#define CTX_TINYVG 1 -#define CTX_TVG_STDIO 0 -#define CTX_DITHER 1 - -#define CTX_PDF 0 -#define CTX_PROTOCOL_U8_COLOR 1 -#define CTX_AVOID_CLIPPED_SUBDIVISION 0 -#define CTX_LIMIT_FORMATS 1 -#define CTX_ENABLE_FLOAT 0 -#define CTX_32BIT_SEGMENTS 0 -#define CTX_ENABLE_RGBA8 1 -#define CTX_ENABLE_RGB332 1 -#define CTX_ENABLE_GRAY1 1 -#define CTX_ENABLE_GRAY2 1 -#define CTX_ENABLE_GRAY4 1 -#define CTX_ENABLE_RGB565 1 -#define CTX_ENABLE_RGB565_BYTESWAPPED 1 -#define CTX_ENABLE_CBRLE 0 -#define CTX_BITPACK_PACKER 0 -#define CTX_COMPOSITING_GROUPS 0 -#define CTX_RENDERSTREAM_STATIC 0 -#define CTX_GRADIENT_CACHE 1 -#define CTX_ENABLE_CLIP 1 -#define CTX_MIN_JOURNAL_SIZE 512 // grows dynamically -#define CTX_MIN_EDGE_LIST_SIZE 512 // is also max and limits complexity - // of paths that can be filled -#define CTX_STATIC_OPAQUE 1 -#define CTX_MAX_SCANLINE_LENGTH 512 -#define CTX_1BIT_CLIP 1 - -#define CTX_MAX_DASHES 10 -#define CTX_MAX_GRADIENT_STOPS 10 -#define CTX_CM 0 -#define CTX_SHAPE_CACHE 0 -#define CTX_SHAPE_CACHE_DEFAULT 0 -#define CTX_RASTERIZER_MAX_CIRCLE_SEGMENTS 128 -#define CTX_NATIVE_GRAYA8 0 -#define CTX_ENABLE_SHADOW_BLUR 0 -#define CTX_FONTS_FROM_FILE 0 -#define CTX_MAX_KEYDB 16 -#define CTX_FRAGMENT_SPECIALIZE 1 -#define CTX_FAST_FILL_RECT 1 -#define CTX_MAX_TEXTURES 1 -#define CTX_PARSER_MAXLEN 512 -#define CTX_PARSER_FIXED_TEMP 1 -#define CTX_CURRENT_PATH 1 -#define CTX_BLENDING_AND_COMPOSITING 1 -#define CTX_STRINGPOOL_SIZE 256 -#define CTX_AUDIO 0 -#define CTX_CLIENTS 0 - -#ifdef MICROPY_UNIX_MACHINE_IDLE - - // we enable more for the unix port - -#include <threads.h> -#define CTX_FB 1 -#define CTX_THREADS 1 -#define CTX_TERMINAL_EVENTS 1 -#define CTX_TILED 1 -#define CTX_FORMATTER 1 -#define CTX_PARSER 1 -#define CTX_MATH 1 -#define CTX_RAW_KB_EVENTS 1 -#define CTX_BRAILLE_TEXT 0 -#else -#define CTX_RAW_KB_EVENTS 0 -#define CTX_MATH 0 -#define CTX_TERMINAL_EVENTS 0 // gets rid of posix bits and bobs -#define CTX_THREADS 0 -#define CTX_TILED 0 -#define CTX_FORMATTER 0 // we want these eventually -#define CTX_PARSER 0 // enabled -#define CTX_BRAILLE_TEXT 0 - -#define CTX_BAREMETAL 1 -#endif - - -#define CTX_EVENTS 1 -#define CTX_MAX_DEVICES 1 -#define CTX_MAX_KEYBINDINGS 16 -#define CTX_RASTERIZER 1 -#define CTX_MAX_STATES 5 -#define CTX_MAX_EDGES 127 -#define CTX_MAX_PENDING 64 -#define CTX_MAX_CBS 8 -#define CTX_MAX_LISTEN_FDS 1 - -#define CTX_ONE_FONT_ENGINE 1 -/* we keep the ctx implementation here, this compilation taget changes less - * than the micropython target - */ - -#define CTX_STATIC_FONT(font) \ - ctx_load_font_ctx(ctx_font_##font##_name, \ - ctx_font_##font, \ - sizeof (ctx_font_##font)) - - - -#define CTX_MAX_FONTS 10 - -#if 0 -#include "Roboto-Regular.h" -#include "Roboto-Bold.h" -#include "Roboto-Italic.h" -#include "Roboto-BoldItalic.h" -#define CTX_FONT_0 CTX_STATIC_FONT(Roboto_Regular) -#define CTX_FONT_1 CTX_STATIC_FONT(Roboto_Bold) -#define CTX_FONT_2 CTX_STATIC_FONT(Roboto_Italic) -//#define CTX_FONT_3 CTX_STATIC_FONT(Roboto_BoldItalic) -#endif - - -#if 1 -#include "Arimo-Regular.h" -#include "Arimo-Bold.h" -#include "Arimo-Italic.h" -#include "Arimo-BoldItalic.h" -#define CTX_FONT_0 CTX_STATIC_FONT(Arimo_Regular) -#define CTX_FONT_1 CTX_STATIC_FONT(Arimo_Bold) -#define CTX_FONT_2 CTX_STATIC_FONT(Arimo_Italic) -#define CTX_FONT_3 CTX_STATIC_FONT(Arimo_BoldItalic) -#endif - -#if 0 -#define CTX_FONT_4 CTX_STATIC_FONT(Roboto_Thin) -#include "Roboto-Thin.h" -#endif - -#if 0 -#include "Carlito-Regular.h" -#include "Carlito-Bold.h" -#include "Carlito-Italic.h" -#include "Carlito-BoldItalic.h" -#define CTX_FONT_5 CTX_STATIC_FONT(Carlito_Regular) -#define CTX_FONT_6 CTX_STATIC_FONT(Carlito_Bold) -#define CTX_FONT_7 CTX_STATIC_FONT(Carlito_Italic) -#define CTX_FONT_8 CTX_STATIC_FONT(Carlito_BoldItalic) -#endif - - -#include "Tinos-Regular.h" -#define CTX_FONT_13 CTX_STATIC_FONT(Tinos_Regular) -//#include "Tinos-Bold.h" -//#define CTX_FONT_14 CTX_STATIC_FONT(Tinos_Bold) - -#if 0 -#include "Tinos-Italic.h" -#include "Tinos-BoldItalic.h" -#define CTX_FONT_15 CTX_STATIC_FONT(Tinos_Italic) -#define CTX_FONT_16 CTX_STATIC_FONT(Tinos_BoldItalic) -#endif - -#if 0 -#include "Caladea-Regular.h" -#include "Caladea-Bold.h" -#include "Caladea-Italic.h" -#define CTX_FONT_17 CTX_STATIC_FONT(Caladea_Regular) -#define CTX_FONT_18 CTX_STATIC_FONT(Caladea_Bold) -#define CTX_FONT_19 CTX_STATIC_FONT(Caladea_Italic) -#if 0 -#include "Caladea-BoldItalic.h" -#define CTX_FONT_20 CTX_STATIC_FONT(Caladea_BoldItalic) -#endif -#endif - -#if 1 -#include "Cousine-Regular.h" -#include "Cousine-Bold.h" -#define CTX_FONT_21 CTX_STATIC_FONT(Cousine_Regular) -#define CTX_FONT_22 CTX_STATIC_FONT(Cousine_Bold) -//#include "Cousine-Italic.h" -//#include "Cousine-BoldItalic.h" -//#define CTX_FONT_23 CTX_STATIC_FONT(Cousine_Italic) -//#define CTX_FONT_24 CTX_STATIC_FONT(Cousine_BoldItalic) -#endif - -#define CTX_IMPLEMENTATION +#include "ctx_config.h" #include "ctx.h" -typedef struct _mp_ctx_event_obj_t mp_ctx_event_obj_t; typedef struct _mp_ctx_obj_t { mp_obj_base_t base; Ctx *ctx; - //mp_ctx_event_obj_t *ctx_event; mp_obj_t user_data; } mp_ctx_obj_t; @@ -220,18 +39,6 @@ void gc_collect(void); } \ MP_DEFINE_CONST_FUN_OBJ_1(mp_ctx_##name##_obj, mp_ctx_##name); -#define MP_CTX_COMMON_FUN_0_idle(name) \ - static mp_obj_t mp_ctx_##name(mp_obj_t self_in) \ - { \ - mp_ctx_obj_t *self = MP_OBJ_TO_PTR(self_in); \ - gc_collect();\ - ctx_##name(self->ctx); \ - mp_idle(0);\ - while(ctx_get_event(self->ctx)){};\ - return self_in; \ - } \ - MP_DEFINE_CONST_FUN_OBJ_1(mp_ctx_##name##_obj, mp_ctx_##name); - #define MP_CTX_COMMON_FUN_1F(name) \ static mp_obj_t mp_ctx_##name(mp_obj_t self_in, mp_obj_t arg1) \ { \ @@ -425,9 +232,8 @@ MP_CTX_COMMON_FUN_0(begin_path); MP_CTX_COMMON_FUN_0(save); MP_CTX_COMMON_FUN_0(restore); -MP_CTX_COMMON_FUN_0(consume_events); MP_CTX_COMMON_FUN_0(start_frame); -MP_CTX_COMMON_FUN_0_idle(end_frame); +MP_CTX_COMMON_FUN_0(end_frame); MP_CTX_COMMON_FUN_0(start_group); MP_CTX_COMMON_FUN_0(end_group); @@ -737,253 +543,8 @@ STATIC void generic_method_lookup(mp_obj_t obj, qstr attr, mp_obj_t *dest) { } } -extern const mp_obj_type_t mp_ctx_event_type; -struct _mp_ctx_event_obj_t { - mp_obj_base_t base; - CtxEvent event; - mp_obj_t user_data; - mp_obj_t mp_ev; -}; - - -static mp_obj_t mp_ctx_event_new (void) -{ - mp_ctx_event_obj_t *o = m_new_obj(mp_ctx_event_obj_t); - o->base.type = &mp_ctx_event_type; - return MP_OBJ_FROM_PTR(o); -} extern const mp_obj_type_t mp_ctx_type; -/** CtxEvent **/ - -STATIC mp_obj_t -mp_ctx_event_attr_op (mp_obj_t self_in, qstr attr, mp_obj_t set_val) -{ - mp_ctx_event_obj_t *self = MP_OBJ_TO_PTR(self_in); - if (set_val == MP_OBJ_NULL) { - switch (attr) - { - case MP_QSTR_ctx: - { - mp_ctx_obj_t *o = m_new_obj(mp_ctx_obj_t); - o->base.type = &mp_ctx_type; - o->ctx = self->event.ctx; - return MP_OBJ_FROM_PTR(o); - } - case MP_QSTR_x: return mp_obj_new_float(self->event.x); - case MP_QSTR_y: return mp_obj_new_float(self->event.y); - case MP_QSTR_device_x: return mp_obj_new_float(self->event.device_x); - case MP_QSTR_device_y: return mp_obj_new_float(self->event.device_y); - case MP_QSTR_start_x: return mp_obj_new_float(self->event.start_x); - case MP_QSTR_start_y: return mp_obj_new_float(self->event.start_y); - case MP_QSTR_prev_x: return mp_obj_new_float(self->event.prev_x); - case MP_QSTR_prev_y: return mp_obj_new_float(self->event.prev_y); - case MP_QSTR_delta_x: return mp_obj_new_float(self->event.delta_x); - case MP_QSTR_delta_y: return mp_obj_new_float(self->event.delta_y); - case MP_QSTR_device_no: return mp_obj_new_int(self->event.device_no); - case MP_QSTR_unicode: return mp_obj_new_int(self->event.unicode); - case MP_QSTR_user_data: return self->user_data; - case MP_QSTR_scroll_direction: return mp_obj_new_int(self->event.scroll_direction); - case MP_QSTR_time: return mp_obj_new_int(self->event.time); - case MP_QSTR_modifier_state: return mp_obj_new_int(self->event.state); - case MP_QSTR_string: if (self->event.string) - // gambling on validity - return mp_obj_new_str(self->event.string, strlen(self->event.string)); - else - return mp_obj_new_str("", 0); - } - } - else - { - return set_val; - } - return self_in; -} - -STATIC void mp_ctx_event_attr(mp_obj_t obj, qstr attr, mp_obj_t *dest) { - - if(attr == MP_QSTR_x - ||attr == MP_QSTR_y - ||attr == MP_QSTR_ctx - ||attr == MP_QSTR_start_x - ||attr == MP_QSTR_start_y - ||attr == MP_QSTR_prev_x - ||attr == MP_QSTR_prev_y - ||attr == MP_QSTR_delta_x - ||attr == MP_QSTR_delta_y - ||attr == MP_QSTR_device_no - ||attr == MP_QSTR_unicode - ||attr == MP_QSTR_user_data - ||attr == MP_QSTR_scroll_direction - ||attr == MP_QSTR_time - ||attr == MP_QSTR_modifier_state - ||attr == MP_QSTR_string - ||attr == MP_QSTR_device_x - ||attr == MP_QSTR_device_y) - { - if (dest[0] == MP_OBJ_NULL) { - // load attribute - mp_obj_t val = mp_ctx_event_attr_op(obj, attr, MP_OBJ_NULL); - dest[0] = val; - } else { - // delete/store attribute - if (mp_ctx_event_attr_op(obj, attr, dest[1]) != MP_OBJ_NULL) - dest[0] = MP_OBJ_NULL; // indicate success - } - } - else { - // A method call - generic_method_lookup(obj, attr, dest); - } -} - -static const mp_rom_map_elem_t mp_ctx_event_locals_dict_table[] = { - MP_CTX_ATTR(x), - MP_CTX_ATTR(y), - MP_CTX_ATTR(ctx), - MP_CTX_ATTR(device_x), - MP_CTX_ATTR(device_y), - MP_CTX_ATTR(start_x), - MP_CTX_ATTR(start_y), - MP_CTX_ATTR(prev_x), - MP_CTX_ATTR(prev_y), - MP_CTX_ATTR(delta_x), - MP_CTX_ATTR(delta_y), - MP_CTX_ATTR(device_no), - MP_CTX_ATTR(unicode), - MP_CTX_ATTR(user_data), - MP_CTX_ATTR(scroll_direction), - MP_CTX_ATTR(time), - MP_CTX_ATTR(modifier_state), - MP_CTX_ATTR(string) -}; -static MP_DEFINE_CONST_DICT(mp_ctx_event_locals_dict, mp_ctx_event_locals_dict_table); - -static mp_obj_t mp_ctx_event_make_new( - const mp_obj_type_t *type, - size_t n_args, - size_t n_kw, - const mp_obj_t *args -) { - mp_ctx_event_obj_t *o = m_new_obj(mp_ctx_event_obj_t); - o->base.type = type; - return MP_OBJ_FROM_PTR(o); -} - -MP_DEFINE_CONST_OBJ_TYPE( - mp_ctx_event_type, - MP_QSTR_ctx_event_type, - MP_TYPE_FLAG_NONE, - //print, array_print, - make_new, mp_ctx_event_make_new, - attr, mp_ctx_event_attr, - locals_dict, &mp_ctx_event_locals_dict -); - -/* -const mp_obj_type_t mp_ctx_event_type = { - .base = { &mp_type_type }, - .name = MP_QSTR_CtxEvent, - .make_new = mp_ctx_event_make_new, - .locals_dict = (mp_obj_t)&mp_ctx_event_locals_dict, - .attr = mp_ctx_event_attr -}; -*/ - -static void mp_ctx_listen_cb_handler (CtxEvent *event, void *data1, void*data2) -{ - mp_obj_t event_in = data2; - mp_ctx_event_obj_t *mp_ctx_event = MP_OBJ_TO_PTR(event_in); - mp_ctx_event->event = *event; // XXX todo stop copying, make stop_propagate work - mp_call_function_1(data1, event_in); -} - -static void mp_ctx_listen_cb_handler_stop_propagate (CtxEvent *event, void *data1, void*data2) -{ - mp_obj_t event_in = data2; - mp_ctx_event_obj_t *mp_ctx_event = MP_OBJ_TO_PTR(event_in); - mp_ctx_event->event = *event; - mp_call_function_1(data1, event_in); - event->stop_propagate = 1; -} - -static mp_obj_t mp_ctx_listen (size_t n_args, const mp_obj_t *args) -{ - mp_obj_t self_in = args[0]; - mp_obj_t event_mask = args[1]; - mp_obj_t cb_in = args[2]; - mp_obj_t user_data_in = n_args==4?args[3]:mp_const_none; - mp_ctx_obj_t *self = MP_OBJ_TO_PTR(self_in); - if (cb_in != mp_const_none && - !mp_obj_is_callable(cb_in)) - mp_raise_ValueError(MP_ERROR_TEXT("invalid handler")); - mp_ctx_event_obj_t *ctx_event = mp_ctx_event_new (); - ctx_event->user_data = user_data_in; - ctx_listen (self->ctx, - mp_obj_get_int(event_mask), - mp_ctx_listen_cb_handler, - (cb_in), ctx_event); - return MP_OBJ_FROM_PTR(self); -} -MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_ctx_listen_obj, 3, 4, mp_ctx_listen); - -static void mp_ctx_key_binding_cb_handler (CtxEvent *event, void *data1, void*data2) -{ - mp_ctx_event_obj_t *ctx_event = mp_ctx_event_new (); - //mp_ctx_event_obj_t *mp_ctx_event = MP_OBJ_TO_PTR(event_in); - ctx_event->event = *event; -#if 0 - mp_sched_schedule (data1, event_in); -#else - mp_call_function_1(data1, ctx_event); -#endif -} - -static mp_obj_t mp_ctx_add_key_binding (size_t n_args, const mp_obj_t *args) -{ - mp_obj_t self_in = args[0]; - mp_obj_t key_in = args[1]; - mp_obj_t action_in = args[2]; - mp_obj_t label_in = args[3]; - mp_obj_t cb_in = args[4]; - //mp_obj_t user_data_in = args[5]; - mp_ctx_obj_t *self = MP_OBJ_TO_PTR(self_in); - if (cb_in != mp_const_none && - !mp_obj_is_callable(cb_in)) - mp_raise_ValueError(MP_ERROR_TEXT("invalid handler")); - ctx_add_key_binding (self->ctx, - mp_obj_str_get_str(key_in), - mp_obj_str_get_str(action_in), - mp_obj_str_get_str(label_in), - mp_ctx_key_binding_cb_handler, - (cb_in));//, ctx_event); - return MP_OBJ_FROM_PTR(self); -} -MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_ctx_add_key_binding_obj, 5, 5, mp_ctx_add_key_binding); - - -static mp_obj_t mp_ctx_listen_stop_propagate (size_t n_args, const mp_obj_t *args) -{ - mp_obj_t self_in = args[0]; - mp_obj_t event_mask = args[1]; - mp_obj_t cb_in = args[2]; - mp_obj_t user_data_in = n_args==4?args[3]:mp_const_none; - mp_ctx_obj_t *self = MP_OBJ_TO_PTR(self_in); - if (cb_in != mp_const_none && - !mp_obj_is_callable(cb_in)) - mp_raise_ValueError(MP_ERROR_TEXT("invalid handler")); - mp_ctx_event_obj_t *ctx_event = mp_ctx_event_new (); - ctx_event->user_data = user_data_in; - ctx_listen (self->ctx, - mp_obj_get_int(event_mask), - mp_ctx_listen_cb_handler_stop_propagate, - (cb_in), ctx_event); - return MP_OBJ_FROM_PTR(self); -} -MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_ctx_listen_stop_propagate_obj, 3, 4, mp_ctx_listen_stop_propagate); - - - #if CTX_TINYVG static mp_obj_t mp_ctx_tinyvg_get_size (mp_obj_t self_in, mp_obj_t buffer_in) { @@ -1145,9 +706,6 @@ mp_ctx_attr_op (mp_obj_t self_in, qstr attr, mp_obj_t set_val) case MP_QSTR_flags: return mp_obj_new_int(ctx_cb_get_flags (self->ctx)); - case MP_QSTR_need_redraw: - return mp_obj_new_bool(ctx_need_redraw (self->ctx)); - case MP_QSTR_line_cap: return mp_obj_new_int(ctx_get_line_cap (self->ctx)); case MP_QSTR_line_join: @@ -1196,8 +754,6 @@ mp_ctx_attr_op (mp_obj_t self_in, qstr attr, mp_obj_t set_val) ctx_line_cap (self->ctx, mp_obj_get_int (set_val)); break; case MP_QSTR_flags: ctx_cb_set_flags (self->ctx, mp_obj_get_int (set_val)); break; - case MP_QSTR_need_redraw: - ctx_queue_draw (self->ctx); break; case MP_QSTR_line_join: ctx_line_join (self->ctx, mp_obj_get_int (set_val)); break; case MP_QSTR_text_align: @@ -1244,7 +800,6 @@ STATIC void mp_ctx_attr(mp_obj_t obj, qstr attr, mp_obj_t *dest) { ||attr == MP_QSTR_compositing_mode #endif ||attr == MP_QSTR_flags - ||attr == MP_QSTR_need_redraw ||attr == MP_QSTR_line_cap ||attr == MP_QSTR_line_join ||attr == MP_QSTR_text_align @@ -1320,11 +875,7 @@ static const mp_rom_map_elem_t mp_ctx_locals_dict_table[] = { MP_CTX_METHOD(save), MP_CTX_METHOD(restore), MP_CTX_METHOD(start_frame), - //MP_CTX_METHOD(consume_events), MP_CTX_METHOD(end_frame), - MP_CTX_METHOD(add_key_binding), - MP_CTX_METHOD(listen), - MP_CTX_METHOD(listen_stop_propagate), MP_CTX_METHOD(get_font_name), MP_CTX_METHOD(gray), @@ -1341,16 +892,6 @@ static const mp_rom_map_elem_t mp_ctx_locals_dict_table[] = { #endif MP_CTX_METHOD(logo), - MP_CTX_METHOD(pointer_motion), - MP_CTX_METHOD(pointer_release), - MP_CTX_METHOD(pointer_press), - MP_CTX_METHOD(scrolled), - MP_CTX_METHOD(key_press), - MP_CTX_METHOD(key_up), - MP_CTX_METHOD(key_down), - MP_CTX_METHOD(incoming_message), - - // Instance attributes MP_CTX_ATTR(x), MP_CTX_ATTR(y), @@ -1362,7 +903,6 @@ static const mp_rom_map_elem_t mp_ctx_locals_dict_table[] = { MP_CTX_ATTR(compositing_mode), MP_CTX_ATTR(blend_mode), #endif - MP_CTX_ATTR(need_redraw), MP_CTX_ATTR(flags), MP_CTX_ATTR(line_cap), MP_CTX_ATTR(line_join), @@ -1506,7 +1046,6 @@ const mp_obj_type_t mp_ctx_type = { static const mp_rom_map_elem_t mp_ctx_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ctx_module) }, { MP_ROM_QSTR(MP_QSTR_Context), MP_ROM_PTR(&mp_ctx_type) }, - { MP_ROM_QSTR(MP_QSTR_CtxEvent), MP_ROM_PTR(&mp_ctx_event_type) }, MP_CTX_INT_CONSTANT(FORMAT,GRAY8), MP_CTX_INT_CONSTANT(FORMAT,GRAYA8), diff --git a/usermodule/uctx/examples/332pal.py b/usermodule/uctx/examples/332pal.py deleted file mode 100755 index 36688a0e0a7ee64cf3aefa8cc51c1af71062645e..0000000000000000000000000000000000000000 --- a/usermodule/uctx/examples/332pal.py +++ /dev/null @@ -1,27 +0,0 @@ -#!/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() diff --git a/usermodule/uctx/examples/Calculator.py b/usermodule/uctx/examples/Calculator.py deleted file mode 100755 index a9c8ad4370f2fe1a87de24a896cf5313545faefc..0000000000000000000000000000000000000000 --- a/usermodule/uctx/examples/Calculator.py +++ /dev/null @@ -1,242 +0,0 @@ -#!/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) - - diff --git a/usermodule/uctx/examples/canvas.py b/usermodule/uctx/examples/canvas.py deleted file mode 100755 index ed978cf72f31d3edbab95759e73ed7cef0777495..0000000000000000000000000000000000000000 --- a/usermodule/uctx/examples/canvas.py +++ /dev/null @@ -1,300 +0,0 @@ -#!/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() - - - diff --git a/usermodule/uctx/examples/fonts.py b/usermodule/uctx/examples/fonts.py deleted file mode 100755 index 428cb18d25efd5f32fc7fc5ad64cb2961c7ef38c..0000000000000000000000000000000000000000 --- a/usermodule/uctx/examples/fonts.py +++ /dev/null @@ -1,48 +0,0 @@ -#!/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() - - diff --git a/usermodule/uctx/examples/ililcd.py b/usermodule/uctx/examples/ililcd.py deleted file mode 100644 index a4895ceb636e4d985bf34c9c9ef3f0416359939e..0000000000000000000000000000000000000000 --- a/usermodule/uctx/examples/ililcd.py +++ /dev/null @@ -1,183 +0,0 @@ -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) - diff --git a/usermodule/uctx/examples/lcd13.py b/usermodule/uctx/examples/lcd13.py deleted file mode 100644 index e5d66528d065fff744f6076c8c31754786f92dcb..0000000000000000000000000000000000000000 --- a/usermodule/uctx/examples/lcd13.py +++ /dev/null @@ -1,146 +0,0 @@ -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) - diff --git a/usermodule/uctx/examples/menu.py b/usermodule/uctx/examples/menu.py deleted file mode 100755 index 00651f3e2645c3e2fe740f363b9d3690112eea49..0000000000000000000000000000000000000000 --- a/usermodule/uctx/examples/menu.py +++ /dev/null @@ -1,365 +0,0 @@ -#!/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() - - diff --git a/usermodule/uctx/examples/rectangles.py b/usermodule/uctx/examples/rectangles.py deleted file mode 100755 index d12f9762c956bcaabc83fd786d4f4dda19b75ea7..0000000000000000000000000000000000000000 --- a/usermodule/uctx/examples/rectangles.py +++ /dev/null @@ -1,58 +0,0 @@ -#!/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 - diff --git a/usermodule/uctx/examples/simple.py b/usermodule/uctx/examples/simple.py deleted file mode 100755 index 0f105aad2669fce7976632c4f1786da85802f981..0000000000000000000000000000000000000000 --- a/usermodule/uctx/examples/simple.py +++ /dev/null @@ -1,60 +0,0 @@ -#!/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 - diff --git a/usermodule/uctx/examples/st7789py.py b/usermodule/uctx/examples/st7789py.py deleted file mode 100644 index e37ef4b098b3a001d677ccd21230fe0783284f1d..0000000000000000000000000000000000000000 --- a/usermodule/uctx/examples/st7789py.py +++ /dev/null @@ -1,403 +0,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 diff --git a/usermodule/uctx/examples/uimui.py b/usermodule/uctx/examples/uimui.py deleted file mode 100755 index 04912711405b93bb35894ad56664803c118b51eb..0000000000000000000000000000000000000000 --- a/usermodule/uctx/examples/uimui.py +++ /dev/null @@ -1,492 +0,0 @@ -#!/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 - diff --git a/usermodule/uctx/uctx/micropython.cmake b/usermodule/uctx/uctx/micropython.cmake deleted file mode 100644 index d89ff8286087503cf573b45ec6eb3a93ce9f9640..0000000000000000000000000000000000000000 --- a/usermodule/uctx/uctx/micropython.cmake +++ /dev/null @@ -1,12 +0,0 @@ -add_library(usermod_ctx INTERFACE) - -target_sources(usermod_ctx INTERFACE - ${CMAKE_CURRENT_LIST_DIR}/uctx.c -) - -target_include_directories(usermod_ctx INTERFACE - ${CMAKE_CURRENT_LIST_DIR} - ${CMAKE_CURRENT_LIST_DIR}/../fonts -) - -target_link_libraries(usermod INTERFACE usermod_ctx) diff --git a/usermodule/uctx/uctx/micropython.mk b/usermodule/uctx/uctx/micropython.mk deleted file mode 100644 index c9c838e78e1f22da2d9614e506a7433d558b09ee..0000000000000000000000000000000000000000 --- a/usermodule/uctx/uctx/micropython.mk +++ /dev/null @@ -1,6 +0,0 @@ -CTX_MOD_DIR := $(USERMOD_DIR) -SRC_USERMOD += $(addprefix $(CTX_MOD_DIR)/, \ - uctx.c \ -) -CFLAGS_USERMOD += -I$(CTX_MOD_DIR) -DMODULE_CTX_ENABLED=1 -I$(CTX_MOD_DIR)/../fonts -# CFLAGS_USERMOD += -DEXPOSE_EXTRA_METHODS=1