diff options
| author | Dan Halbert <halbert@halwitz.org> | 2019-01-31 16:03:51 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-01-31 16:03:51 -0500 |
| commit | 7c443fbef2b92bfdd382db9aeaddcdcecbc02cd0 (patch) | |
| tree | 93c06f6ba863e234148555f41042b354286cb52e /shared-module | |
| parent | 63d456127b783efb376bd2b25598cc9e7f9dceb6 (diff) | |
| parent | d72cd5b2d6cbc95665c41a43d6d914e71ac58017 (diff) | |
Merge pull request #1510 from tannewt/terminalio
Add a terminal that shows by default on displays.
Diffstat (limited to 'shared-module')
| -rw-r--r-- | shared-module/displayio/Display.c | 95 | ||||
| -rw-r--r-- | shared-module/displayio/Display.h | 14 | ||||
| -rw-r--r-- | shared-module/displayio/Group.c | 26 | ||||
| -rw-r--r-- | shared-module/displayio/TileGrid.c (renamed from shared-module/displayio/Sprite.c) | 80 | ||||
| -rw-r--r-- | shared-module/displayio/TileGrid.h | 59 | ||||
| -rw-r--r-- | shared-module/displayio/__init__.c | 113 | ||||
| -rw-r--r-- | shared-module/displayio/__init__.h | 3 | ||||
| -rw-r--r-- | shared-module/terminalio/Terminal.c | 127 | ||||
| -rw-r--r-- | shared-module/terminalio/Terminal.h (renamed from shared-module/displayio/Sprite.h) | 32 | ||||
| -rw-r--r-- | shared-module/terminalio/__init__.c | 27 | ||||
| -rw-r--r-- | shared-module/terminalio/__init__.h | 30 |
11 files changed, 468 insertions, 138 deletions
diff --git a/shared-module/displayio/Display.c b/shared-module/displayio/Display.c index 7946111b7..ef0334d10 100644 --- a/shared-module/displayio/Display.c +++ b/shared-module/displayio/Display.c @@ -29,7 +29,10 @@ #include "py/runtime.h" #include "shared-bindings/displayio/FourWire.h" #include "shared-bindings/displayio/ParallelBus.h" +#include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/time/__init__.h" +#include "shared-module/displayio/__init__.h" +#include "supervisor/shared/display.h" #include <stdint.h> @@ -40,16 +43,19 @@ void common_hal_displayio_display_construct(displayio_display_obj_t* self, mp_obj_t bus, uint16_t width, uint16_t height, int16_t colstart, int16_t rowstart, uint16_t color_depth, uint8_t set_column_command, uint8_t set_row_command, - uint8_t write_ram_command, uint8_t* init_sequence, uint16_t init_sequence_len) { + uint8_t write_ram_command, uint8_t* init_sequence, uint16_t init_sequence_len, + const mcu_pin_obj_t* backlight_pin) { self->width = width; self->height = height; self->color_depth = color_depth; self->set_column_command = set_column_command; self->set_row_command = set_row_command; self->write_ram_command = write_ram_command; + self->refresh = false; self->current_group = NULL; self->colstart = colstart; self->rowstart = rowstart; + self->auto_brightness = false; if (MP_OBJ_IS_TYPE(bus, &displayio_parallelbus_type)) { self->begin_transaction = common_hal_displayio_parallelbus_begin_transaction; @@ -86,9 +92,33 @@ void common_hal_displayio_display_construct(displayio_display_obj_t* self, i += 2 + data_size; } self->end_transaction(self->bus); + + supervisor_start_terminal(width, height); + + // Set the group after initialization otherwise we may send pixels while we delay in + // initialization. + self->refresh = true; + self->current_group = &circuitpython_splash; + + // Always set the backlight type in case we're reusing memory. + self->backlight_inout.base.type = &mp_type_NoneType; + if (backlight_pin != NULL && common_hal_mcu_pin_is_free(backlight_pin)) { + pwmout_result_t result = common_hal_pulseio_pwmout_construct(&self->backlight_pwm, backlight_pin, 0, 5000, false); + if (result != PWMOUT_OK) { + self->backlight_inout.base.type = &digitalio_digitalinout_type; + common_hal_digitalio_digitalinout_construct(&self->backlight_inout, backlight_pin); + never_reset_pin_number(backlight_pin->number); + } else { + self->backlight_pwm.base.type = &pulseio_pwmout_type; + common_hal_pulseio_pwmout_never_reset(&self->backlight_pwm); + } + } } void common_hal_displayio_display_show(displayio_display_obj_t* self, displayio_group_t* root_group) { + if (root_group == NULL) { + root_group = &circuitpython_splash; + } self->current_group = root_group; common_hal_displayio_display_refresh_soon(self); } @@ -105,6 +135,42 @@ int32_t common_hal_displayio_display_wait_for_frame(displayio_display_obj_t* sel return 0; } +bool common_hal_displayio_display_get_auto_brightness(displayio_display_obj_t* self) { + return self->auto_brightness; +} + +void common_hal_displayio_display_set_auto_brightness(displayio_display_obj_t* self, bool auto_brightness) { + self->auto_brightness = auto_brightness; +} + +mp_float_t common_hal_displayio_display_get_brightness(displayio_display_obj_t* self) { + if (self->backlight_pwm.base.type == &pulseio_pwmout_type) { + uint16_t duty_cycle = common_hal_pulseio_pwmout_get_duty_cycle(&self->backlight_pwm); + return duty_cycle / ((mp_float_t) 0xffff); + } else if (self->backlight_inout.base.type == &digitalio_digitalinout_type) { + if (common_hal_digitalio_digitalinout_get_value(&self->backlight_inout)) { + return 1.0; + } else { + return 0.0; + } + } + return -1.0; +} + +bool common_hal_displayio_display_set_brightness(displayio_display_obj_t* self, mp_float_t brightness) { + self->updating_backlight = true; + bool ok = false; + if (self->backlight_pwm.base.type == &pulseio_pwmout_type) { + common_hal_pulseio_pwmout_set_duty_cycle(&self->backlight_pwm, (uint16_t) (0xffff * brightness)); + ok = true; + } else if (self->backlight_inout.base.type == &digitalio_digitalinout_type) { + common_hal_digitalio_digitalinout_set_value(&self->backlight_inout, brightness > 0.99); + ok = true; + } + self->updating_backlight = false; + return ok; +} + void displayio_display_start_region_update(displayio_display_obj_t* self, uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) { // TODO(tannewt): Handle displays with single byte bounds. self->begin_transaction(self->bus); @@ -114,8 +180,8 @@ void displayio_display_start_region_update(displayio_display_obj_t* self, uint16 data[1] = __builtin_bswap16(x1 - 1 + self->colstart); self->send(self->bus, false, (uint8_t*) data, 4); self->send(self->bus, true, &self->set_row_command, 1); - data[0] = __builtin_bswap16(y0 + 1 + self->rowstart); - data[1] = __builtin_bswap16(y1 + self->rowstart); + data[0] = __builtin_bswap16(y0 + self->rowstart); + data[1] = __builtin_bswap16(y1 - 1 + self->rowstart); self->send(self->bus, false, (uint8_t*) data, 4); self->send(self->bus, true, &self->write_ram_command, 1); } @@ -145,3 +211,26 @@ bool displayio_display_send_pixels(displayio_display_obj_t* self, uint32_t* pixe self->send(self->bus, false, (uint8_t*) pixels, length * 4); return true; } + +void displayio_display_update_backlight(displayio_display_obj_t* self) { + if (!self->auto_brightness || self->updating_backlight) { + return; + } + if (ticks_ms - self->last_backlight_refresh < 100) { + return; + } + // TODO(tannewt): Fade the backlight based on it's existing value and a target value. The target + // should account for ambient light when possible. + common_hal_displayio_display_set_brightness(self, 1.0); + + self->last_backlight_refresh = ticks_ms; +} + +void release_display(displayio_display_obj_t* self) { + if (self->backlight_pwm.base.type == &pulseio_pwmout_type) { + common_hal_pulseio_pwmout_reset_ok(&self->backlight_pwm); + common_hal_pulseio_pwmout_deinit(&self->backlight_pwm); + } else if (self->backlight_inout.base.type == &digitalio_digitalinout_type) { + common_hal_digitalio_digitalinout_deinit(&self->backlight_inout); + } +} diff --git a/shared-module/displayio/Display.h b/shared-module/displayio/Display.h index 1f1355d31..0d7393aff 100644 --- a/shared-module/displayio/Display.h +++ b/shared-module/displayio/Display.h @@ -27,7 +27,9 @@ #ifndef MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_DISPLAY_H #define MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_DISPLAY_H -#include "shared-module/displayio/Group.h" +#include "shared-bindings/digitalio/DigitalInOut.h" +#include "shared-bindings/displayio/Group.h" +#include "shared-bindings/pulseio/PWMOut.h" typedef bool (*display_bus_begin_transaction)(mp_obj_t bus); typedef void (*display_bus_send)(mp_obj_t bus, bool command, uint8_t *data, uint32_t data_length); @@ -50,6 +52,16 @@ typedef struct { display_bus_begin_transaction begin_transaction; display_bus_send send; display_bus_end_transaction end_transaction; + union { + digitalio_digitalinout_obj_t backlight_inout; + pulseio_pwmout_obj_t backlight_pwm; + }; + uint64_t last_backlight_refresh; + bool auto_brightness:1; + bool updating_backlight:1; } displayio_display_obj_t; +void displayio_display_update_backlight(displayio_display_obj_t* self); +void release_display(displayio_display_obj_t* self); + #endif // MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_DISPLAY_H diff --git a/shared-module/displayio/Group.c b/shared-module/displayio/Group.c index 255349d7c..95043e4f3 100644 --- a/shared-module/displayio/Group.c +++ b/shared-module/displayio/Group.c @@ -27,7 +27,7 @@ #include "shared-bindings/displayio/Group.h" #include "py/runtime.h" -#include "shared-bindings/displayio/Sprite.h" +#include "shared-bindings/displayio/TileGrid.h" void common_hal_displayio_group_construct(displayio_group_t* self, uint32_t max_size) { mp_obj_t* children = m_new(mp_obj_t, max_size); @@ -40,10 +40,10 @@ void common_hal_displayio_group_append(displayio_group_t* self, mp_obj_t layer) } mp_obj_t native_layer = mp_instance_cast_to_native_base(layer, &displayio_group_type); if (native_layer == MP_OBJ_NULL) { - native_layer = mp_instance_cast_to_native_base(layer, &displayio_sprite_type); + native_layer = mp_instance_cast_to_native_base(layer, &displayio_tilegrid_type); } if (native_layer == MP_OBJ_NULL) { - mp_raise_ValueError(translate("Layer must be a Group or Sprite subclass.")); + mp_raise_ValueError(translate("Layer must be a Group or TileGrid subclass.")); } self->children[self->size] = layer; self->size++; @@ -77,8 +77,8 @@ bool displayio_group_get_pixel(displayio_group_t *self, int16_t x, int16_t y, ui y /= self->scale; for (int32_t i = self->size - 1; i >= 0 ; i--) { mp_obj_t layer = self->children[i]; - if (MP_OBJ_IS_TYPE(layer, &displayio_sprite_type)) { - if (displayio_sprite_get_pixel(layer, x, y, pixel)) { + if (MP_OBJ_IS_TYPE(layer, &displayio_tilegrid_type)) { + if (displayio_tilegrid_get_pixel(layer, x, y, pixel)) { return true; } } else if (MP_OBJ_IS_TYPE(layer, &displayio_group_type)) { @@ -97,12 +97,15 @@ bool displayio_group_needs_refresh(displayio_group_t *self) { } for (int32_t i = self->size - 1; i >= 0 ; i--) { mp_obj_t layer = self->children[i]; - if (MP_OBJ_IS_TYPE(layer, &displayio_sprite_type)) { - if (displayio_sprite_needs_refresh(layer)) { + if (MP_OBJ_IS_TYPE(layer, &displayio_tilegrid_type)) { + if (displayio_tilegrid_needs_refresh(layer)) { + return true; + } + } else if (MP_OBJ_IS_TYPE(layer, &displayio_group_type)) { + if (displayio_group_needs_refresh(layer)) { return true; } } - // TODO: Tiled layer } return false; } @@ -111,9 +114,10 @@ void displayio_group_finish_refresh(displayio_group_t *self) { self->needs_refresh = false; for (int32_t i = self->size - 1; i >= 0 ; i--) { mp_obj_t layer = self->children[i]; - if (MP_OBJ_IS_TYPE(layer, &displayio_sprite_type)) { - displayio_sprite_finish_refresh(layer); + if (MP_OBJ_IS_TYPE(layer, &displayio_tilegrid_type)) { + displayio_tilegrid_finish_refresh(layer); + } else if (MP_OBJ_IS_TYPE(layer, &displayio_group_type)) { + displayio_group_finish_refresh(layer); } - // TODO: Tiled layer } } diff --git a/shared-module/displayio/Sprite.c b/shared-module/displayio/TileGrid.c index da6eff896..b90603afe 100644 --- a/shared-module/displayio/Sprite.c +++ b/shared-module/displayio/TileGrid.c @@ -24,7 +24,7 @@ * THE SOFTWARE. */ -#include "shared-bindings/displayio/Sprite.h" +#include "shared-bindings/displayio/TileGrid.h" #include "shared-bindings/displayio/Bitmap.h" #include "shared-bindings/displayio/ColorConverter.h" @@ -32,50 +32,78 @@ #include "shared-bindings/displayio/Palette.h" #include "shared-bindings/displayio/Shape.h" -void common_hal_displayio_sprite_construct(displayio_sprite_t *self, mp_obj_t bitmap, - mp_obj_t pixel_shader, uint16_t width, uint16_t height, uint16_t x, uint16_t y) { - self->width = width; - self->height = height; +void common_hal_displayio_tilegrid_construct(displayio_tilegrid_t *self, mp_obj_t bitmap, + uint16_t bitmap_width_in_tiles, + mp_obj_t pixel_shader, uint16_t width, uint16_t height, + uint16_t tile_width, uint16_t tile_height, uint16_t x, uint16_t y, uint8_t default_tile) { + uint32_t total_tiles = width * height; + // Sprites will only have one tile so save a little memory by inlining values in the pointer. + uint8_t inline_tiles = sizeof(uint8_t*); + if (total_tiles <= inline_tiles) { + self->inline_tiles = true; + } else { + self->tiles = (uint8_t*) m_malloc(total_tiles, false); + self->inline_tiles = false; + } + self->bitmap_width_in_tiles = bitmap_width_in_tiles; + self->width_in_tiles = width; + self->height_in_tiles = height; + self->total_width = width * tile_width; + self->total_height = height * tile_height; + self->tile_width = tile_width; + self->tile_height = tile_height; self->bitmap = bitmap; self->pixel_shader = pixel_shader; self->x = x; self->y = y; } -void common_hal_displayio_sprite_get_position(displayio_sprite_t *self, int16_t* x, int16_t* y) { +void common_hal_displayio_tilegrid_get_position(displayio_tilegrid_t *self, int16_t* x, int16_t* y) { *x = self->x; *y = self->y; } -void common_hal_displayio_sprite_set_position(displayio_sprite_t *self, int16_t x, int16_t y) { +void common_hal_displayio_tilegrid_set_position(displayio_tilegrid_t *self, int16_t x, int16_t y) { self->x = x; self->y = y; self->needs_refresh = true; } - -mp_obj_t common_hal_displayio_sprite_get_pixel_shader(displayio_sprite_t *self) { +mp_obj_t common_hal_displayio_tilegrid_get_pixel_shader(displayio_tilegrid_t *self) { return self->pixel_shader; } -void common_hal_displayio_sprite_set_pixel_shader(displayio_sprite_t *self, mp_obj_t pixel_shader) { +void common_hal_displayio_tilegrid_set_pixel_shader(displayio_tilegrid_t *self, mp_obj_t pixel_shader) { self->pixel_shader = pixel_shader; self->needs_refresh = true; } -bool displayio_sprite_get_pixel(displayio_sprite_t *self, int16_t x, int16_t y, uint16_t* pixel) { +bool displayio_tilegrid_get_pixel(displayio_tilegrid_t *self, int16_t x, int16_t y, uint16_t* pixel) { x -= self->x; y -= self->y; - if (y < 0 || y >= self->height || x >= self->width || x < 0) { + if (y < 0 || y >= self->total_height || x >= self->total_width || x < 0) { + return false; + } + + uint8_t* tiles = self->tiles; + if (self->inline_tiles) { + tiles = (uint8_t*) &self->tiles; + } + if (tiles == NULL) { return false; } + uint16_t tile_location = ((y / self->tile_height + self->top_left_y) % self->height_in_tiles) * self->width_in_tiles + (x / self->tile_width + self->top_left_x) % self->width_in_tiles; + uint8_t tile = tiles[tile_location]; + uint16_t tile_x = tile_x = (tile % self->bitmap_width_in_tiles) * self->tile_width + x % self->tile_width; + uint16_t tile_y = tile_y = (tile / self->bitmap_width_in_tiles) * self->tile_height + y % self->tile_height; + uint32_t value = 0; if (MP_OBJ_IS_TYPE(self->bitmap, &displayio_bitmap_type)) { - value = common_hal_displayio_bitmap_get_pixel(self->bitmap, x, y); + value = common_hal_displayio_bitmap_get_pixel(self->bitmap, tile_x, tile_y); } else if (MP_OBJ_IS_TYPE(self->bitmap, &displayio_shape_type)) { - value = common_hal_displayio_shape_get_pixel(self->bitmap, x, y); + value = common_hal_displayio_shape_get_pixel(self->bitmap, tile_x, tile_y); } else if (MP_OBJ_IS_TYPE(self->bitmap, &displayio_ondiskbitmap_type)) { - value = common_hal_displayio_ondiskbitmap_get_pixel(self->bitmap, x, y); + value = common_hal_displayio_ondiskbitmap_get_pixel(self->bitmap, tile_x, tile_y); } if (self->pixel_shader == mp_const_none) { @@ -90,11 +118,29 @@ bool displayio_sprite_get_pixel(displayio_sprite_t *self, int16_t x, int16_t y, return false; } -bool displayio_sprite_needs_refresh(displayio_sprite_t *self) { +void common_hal_displayio_textgrid_set_tile(displayio_tilegrid_t *self, uint16_t x, uint16_t y, uint8_t tile_index) { + uint8_t* tiles = self->tiles; + if (self->inline_tiles) { + tiles = (uint8_t*) &self->tiles; + } + if (tiles == NULL) { + return; + } + tiles[y * self->width_in_tiles + x] = tile_index; + self->needs_refresh = true; +} + + +void common_hal_displayio_textgrid_set_top_left(displayio_tilegrid_t *self, uint16_t x, uint16_t y) { + self->top_left_x = x; + self->top_left_y = y; +} + +bool displayio_tilegrid_needs_refresh(displayio_tilegrid_t *self) { return self->needs_refresh || displayio_palette_needs_refresh(self->pixel_shader); } -void displayio_sprite_finish_refresh(displayio_sprite_t *self) { +void displayio_tilegrid_finish_refresh(displayio_tilegrid_t *self) { self->needs_refresh = false; displayio_palette_finish_refresh(self->pixel_shader); // TODO(tannewt): We could double buffer changes to position and move them over here. diff --git a/shared-module/displayio/TileGrid.h b/shared-module/displayio/TileGrid.h new file mode 100644 index 000000000..59645553d --- /dev/null +++ b/shared-module/displayio/TileGrid.h @@ -0,0 +1,59 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_TILEGRID_H +#define MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_TILEGRID_H + +#include <stdbool.h> +#include <stdint.h> + +#include "py/obj.h" + +typedef struct { + mp_obj_base_t base; + mp_obj_t bitmap; + mp_obj_t pixel_shader; + uint16_t x; + uint16_t y; + uint16_t bitmap_width_in_tiles; + uint16_t width_in_tiles; + uint16_t height_in_tiles; + uint16_t total_width; + uint16_t total_height; + uint16_t tile_width; + uint16_t tile_height; + uint16_t top_left_x; + uint16_t top_left_y; + uint8_t* tiles; + bool needs_refresh; + bool inline_tiles; +} displayio_tilegrid_t; + +bool displayio_tilegrid_get_pixel(displayio_tilegrid_t *self, int16_t x, int16_t y, uint16_t *pixel); +bool displayio_tilegrid_needs_refresh(displayio_tilegrid_t *self); +void displayio_tilegrid_finish_refresh(displayio_tilegrid_t *self); + +#endif // MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_TILEGRID_H diff --git a/shared-module/displayio/__init__.c b/shared-module/displayio/__init__.c index c86e48a12..f09e4e791 100644 --- a/shared-module/displayio/__init__.c +++ b/shared-module/displayio/__init__.c @@ -6,7 +6,8 @@ #include "shared-bindings/displayio/Display.h" #include "shared-bindings/displayio/Group.h" #include "shared-bindings/displayio/Palette.h" -#include "shared-bindings/displayio/Sprite.h" +#include "supervisor/shared/display.h" +#include "supervisor/memory.h" #include "supervisor/usb.h" primary_display_t displays[CIRCUITPY_DISPLAY_LIMIT]; @@ -17,6 +18,7 @@ void displayio_refresh_displays(void) { continue; } displayio_display_obj_t* display = &displays[i].display; + displayio_display_update_backlight(display); if (!displayio_display_frame_queued(display)) { return; @@ -66,78 +68,28 @@ void displayio_refresh_displays(void) { } } -uint32_t blinka_bitmap_data[32] = { - 0x00000011, 0x11000000, - 0x00000111, 0x53100000, - 0x00000111, 0x56110000, - 0x00000111, 0x11140000, - 0x00000111, 0x20002000, - 0x00000011, 0x13000000, - 0x00000001, 0x11200000, - 0x00000000, 0x11330000, - 0x00000000, 0x01122000, - 0x00001111, 0x44133000, - 0x00032323, 0x24112200, - 0x00111114, 0x44113300, - 0x00323232, 0x34112200, - 0x11111144, 0x44443300, - 0x11111111, 0x11144401, - 0x23232323, 0x21111110 -}; - -displayio_bitmap_t blinka_bitmap = { - .base = {.type = &displayio_bitmap_type }, - .width = 16, - .height = 16, - .data = blinka_bitmap_data, - .stride = 2, - .bits_per_value = 4, - .x_shift = 3, - .x_mask = 0x7, - .bitmask = 0xf -}; - -uint32_t blinka_transparency[1] = {0x80000000}; - -// These colors are RGB 565 with the bytes swapped. -uint32_t blinka_colors[8] = {0x78890000, 0x9F86B8FC, 0xffff0D5A, 0x0000f501, - 0x00000000, 0x00000000, 0x00000000, 0x00000000}; - -displayio_palette_t blinka_palette = { - .base = {.type = &displayio_palette_type }, - .opaque = blinka_transparency, - .colors = blinka_colors, - .color_count = 16, - .needs_refresh = false -}; - -displayio_sprite_t blinka_sprite = { - .base = {.type = &displayio_sprite_type }, - .bitmap = &blinka_bitmap, - .pixel_shader = &blinka_palette, - .x = 0, - .y = 0, - .width = 16, - .height = 16, - .needs_refresh = false -}; - -mp_obj_t splash_children[1] = { - &blinka_sprite, -}; +void common_hal_displayio_release_displays(void) { + for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) { + mp_const_obj_t bus_type = displays[i].fourwire_bus.base.type; + if (bus_type == NULL) { + continue; + } else if (bus_type == &displayio_fourwire_type) { + common_hal_displayio_fourwire_deinit(&displays[i].fourwire_bus); + } else if (bus_type == &displayio_parallelbus_type) { + common_hal_displayio_parallelbus_deinit(&displays[i].parallel_bus); + } + displays[i].fourwire_bus.base.type = &mp_type_NoneType; + } + for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) { + release_display(&displays[i].display); + displays[i].display.base.type = &mp_type_NoneType; + } -displayio_group_t splash = { - .base = {.type = &displayio_group_type }, - .x = 0, - .y = 0, - .scale = 2, - .size = 1, - .max_size = 1, - .children = splash_children, - .needs_refresh = true -}; + supervisor_stop_terminal(); +} void reset_displays(void) { + #if CIRCUITPY_DISPLAYIO // The SPI buses used by FourWires may be allocated on the heap so we need to move them inline. for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) { if (displays[i].fourwire_bus.base.type != &displayio_fourwire_type) { @@ -166,23 +118,8 @@ void reset_displays(void) { continue; } displayio_display_obj_t* display = &displays[i].display; - common_hal_displayio_display_show(display, &splash); - } -} - -void common_hal_displayio_release_displays(void) { - for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) { - mp_const_obj_t bus_type = displays[i].fourwire_bus.base.type; - if (bus_type == NULL) { - continue; - } else if (bus_type == &displayio_fourwire_type) { - common_hal_displayio_fourwire_deinit(&displays[i].fourwire_bus); - } else if (bus_type == &displayio_parallelbus_type) { - common_hal_displayio_parallelbus_deinit(&displays[i].parallel_bus); - } - displays[i].fourwire_bus.base.type = &mp_type_NoneType; - } - for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) { - displays[i].display.base.type = &mp_type_NoneType; + display->auto_brightness = true; + common_hal_displayio_display_show(display, &circuitpython_splash); } + #endif } diff --git a/shared-module/displayio/__init__.h b/shared-module/displayio/__init__.h index fdabd4ec4..5b56ed55c 100644 --- a/shared-module/displayio/__init__.h +++ b/shared-module/displayio/__init__.h @@ -29,6 +29,7 @@ #include "shared-bindings/displayio/Display.h" #include "shared-bindings/displayio/FourWire.h" +#include "shared-bindings/displayio/Group.h" #include "shared-bindings/displayio/ParallelBus.h" typedef struct { @@ -41,6 +42,8 @@ typedef struct { extern primary_display_t displays[CIRCUITPY_DISPLAY_LIMIT]; +extern displayio_group_t circuitpython_splash; + void displayio_refresh_displays(void); void reset_displays(void); diff --git a/shared-module/terminalio/Terminal.c b/shared-module/terminalio/Terminal.c new file mode 100644 index 000000000..6734fa30e --- /dev/null +++ b/shared-module/terminalio/Terminal.c @@ -0,0 +1,127 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "shared-module/terminalio/Terminal.h" + +#include "shared-module/displayio/__init__.h" +#include "shared-bindings/displayio/TileGrid.h" + +void common_hal_terminalio_terminal_construct(terminalio_terminal_obj_t *self, displayio_tilegrid_t* tilegrid, const uint8_t* unicode_characters, size_t unicode_characters_len) { + self->cursor_x = 0; + self->cursor_y = 0; + self->tilegrid = tilegrid; + self->unicode_characters = unicode_characters; + self->unicode_characters_len = unicode_characters_len; + self->first_row = 0; +} + +size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self, const byte *data, size_t len, int *errcode) { + const byte* i = data; + uint16_t start_y = self->cursor_y; + while (i < data + len) { + unichar c = utf8_get_char(i); + i = utf8_next_char(i); + // Always handle ASCII. + if (c < 128) { + if (c >= 0x20 && c <= 0x7e) { + common_hal_displayio_textgrid_set_tile(self->tilegrid, self->cursor_x, self->cursor_y, c - 0x20); + self->cursor_x++; + } + if (c == '\r') { + self->cursor_x = 0; + } else if (c == '\n') { + self->cursor_y++; + // Commands below are used by MicroPython in the REPL + } else if (c == '\b') { + if (self->cursor_x > 0) { + self->cursor_x--; + } + } else if (c == 0x1b) { + if (i[0] == '[') { + if (i[1] == 'K') { + // Clear the rest of the line. + for (uint16_t j = self->cursor_x; j < self->tilegrid->width_in_tiles; j++) { + common_hal_displayio_textgrid_set_tile(self->tilegrid, j, self->cursor_y, 0); + } + i += 2; + } else { + // Handle commands of the form \x1b[####D + uint16_t n = 0; + uint8_t j = 1; + for (; j < 6; j++) { + if ('0' <= i[j] && i[j] <= '9') { + n = n * 10 + (i[j] - '0'); + } else { + c = i[j]; + } + } + if (c == 'D') { + if (n > self->cursor_x) { + self->cursor_x = 0; + } else { + self->cursor_x -= n; + } + i += j; + } + } + } + } + } else { + // Do a linear search of the mapping for unicode. + const byte* j = self->unicode_characters; + uint8_t k = 0; + while (j < self->unicode_characters + self->unicode_characters_len) { + unichar potential_c = utf8_get_char(j); + j = utf8_next_char(j); + if (c == potential_c) { + common_hal_displayio_textgrid_set_tile(self->tilegrid, self->cursor_x, self->cursor_y, 0x7f - 0x20 + k); + self->cursor_x++; + break; + } + } + } + if (self->cursor_x >= self->tilegrid->width_in_tiles) { + self->cursor_y++; + self->cursor_x %= self->tilegrid->width_in_tiles; + } + if (self->cursor_y >= self->tilegrid->height_in_tiles) { + self->cursor_y %= self->tilegrid->height_in_tiles; + } + if (self->cursor_y != start_y) { + // clear the new row + for (uint16_t j = 0; j < self->tilegrid->width_in_tiles; j++) { + common_hal_displayio_textgrid_set_tile(self->tilegrid, j, self->cursor_y, 0); + start_y = self->cursor_y; + } + common_hal_displayio_textgrid_set_top_left(self->tilegrid, 0, (start_y + self->tilegrid->height_in_tiles + 1) % self->tilegrid->height_in_tiles); + } + } + return i - data; +} + +bool common_hal_terminalio_terminal_ready_to_tx(terminalio_terminal_obj_t *self) { + return true; +} diff --git a/shared-module/displayio/Sprite.h b/shared-module/terminalio/Terminal.h index dc368c4b7..fe9dcf0c4 100644 --- a/shared-module/displayio/Sprite.h +++ b/shared-module/terminalio/Terminal.h @@ -1,5 +1,5 @@ /* - * This file is part of the Micro Python project, http://micropython.org/ + * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * @@ -24,27 +24,23 @@ * THE SOFTWARE. */ -#ifndef MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_SPRITE_H -#define MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_SPRITE_H +#ifndef SHARED_MODULE_TERMINALIO_TERMINAL_H +#define SHARED_MODULE_TERMINALIO_TERMINAL_H -#include <stdbool.h> #include <stdint.h> +#include <stdbool.h> #include "py/obj.h" +#include "shared-module/displayio/TileGrid.h" -typedef struct { +typedef struct { mp_obj_base_t base; - mp_obj_t bitmap; - mp_obj_t pixel_shader; - uint16_t x; - uint16_t y; - uint16_t width; - uint16_t height; - bool needs_refresh; -} displayio_sprite_t; - -bool displayio_sprite_get_pixel(displayio_sprite_t *sprite, int16_t x, int16_t y, uint16_t *pixel); -bool displayio_sprite_needs_refresh(displayio_sprite_t *self); -void displayio_sprite_finish_refresh(displayio_sprite_t *self); + uint16_t cursor_x; + uint16_t cursor_y; + displayio_tilegrid_t* tilegrid; + const byte* unicode_characters; + uint16_t unicode_characters_len; + uint16_t first_row; +} terminalio_terminal_obj_t; -#endif // MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_SPRITE_H +#endif /* SHARED_MODULE_TERMINALIO_TERMINAL_H */ diff --git a/shared-module/terminalio/__init__.c b/shared-module/terminalio/__init__.c new file mode 100644 index 000000000..3f61f4823 --- /dev/null +++ b/shared-module/terminalio/__init__.c @@ -0,0 +1,27 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 hathach for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "shared-bindings/terminalio/__init__.h" diff --git a/shared-module/terminalio/__init__.h b/shared-module/terminalio/__init__.h new file mode 100644 index 000000000..e925dd429 --- /dev/null +++ b/shared-module/terminalio/__init__.h @@ -0,0 +1,30 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef SHARED_MODULE_TERMINALIO___INIT___H +#define SHARED_MODULE_TERMINALIO___INIT___H + +#endif /* SHARED_MODULE_TERMINALIO___INIT___H */ |
