diff options
| author | Dan Halbert <halbert@halwitz.org> | 2018-09-07 14:30:30 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-09-07 14:30:30 -0400 |
| commit | 449756ef2756a5508d82fa7830d3a83eb7f1ffa9 (patch) | |
| tree | 2a6c11276c1bccc43d6b9482bf474813b324d5ba /ports | |
| parent | 23b23dd2b8e3a9a401e6ba8d60728adebe51c840 (diff) | |
| parent | 86288f14f1312c6b65ac7f268a3ecf093b0aaed9 (diff) | |
Merge pull request #1152 from tannewt/hallowing
Introduce displayio to render graphics to displays.
Diffstat (limited to 'ports')
| -rw-r--r-- | ports/atmel-samd/Makefile | 6 | ||||
| -rw-r--r-- | ports/atmel-samd/background.c | 5 | ||||
| -rw-r--r-- | ports/atmel-samd/boards/board.h | 8 | ||||
| -rw-r--r-- | ports/atmel-samd/boards/hallowing_m0_express/board.c | 86 | ||||
| -rw-r--r-- | ports/atmel-samd/boards/hallowing_m0_express/mpconfigboard.h | 8 | ||||
| -rw-r--r-- | ports/atmel-samd/boards/hallowing_m0_express/pins.c | 3 | ||||
| -rw-r--r-- | ports/atmel-samd/common-hal/displayio/FourWire.c | 139 | ||||
| -rw-r--r-- | ports/atmel-samd/common-hal/displayio/FourWire.h | 53 | ||||
| -rw-r--r-- | ports/atmel-samd/mpconfigport.h | 8 | ||||
| -rw-r--r-- | ports/atmel-samd/supervisor/port.c | 12 |
10 files changed, 321 insertions, 7 deletions
diff --git a/ports/atmel-samd/Makefile b/ports/atmel-samd/Makefile index e1634a1b9..9c94e442f 100644 --- a/ports/atmel-samd/Makefile +++ b/ports/atmel-samd/Makefile @@ -308,6 +308,7 @@ SRC_COMMON_HAL = \ busio/UART.c \ digitalio/__init__.c \ digitalio/DigitalInOut.c \ + displayio/FourWire.c \ i2cslave/__init__.c \ i2cslave/I2CSlave.c \ microcontroller/__init__.c \ @@ -381,6 +382,11 @@ SRC_SHARED_MODULE = \ bitbangio/OneWire.c \ bitbangio/SPI.c \ busio/OneWire.c \ + displayio/__init__.c \ + displayio/Bitmap.c \ + displayio/Group.c \ + displayio/Palette.c \ + displayio/Sprite.c \ gamepad/__init__.c \ gamepad/GamePad.c \ _stage/__init__.c \ diff --git a/ports/atmel-samd/background.c b/ports/atmel-samd/background.c index 62d891b15..f25ec7200 100644 --- a/ports/atmel-samd/background.c +++ b/ports/atmel-samd/background.c @@ -30,12 +30,17 @@ #include "usb.h" #include "usb_mass_storage.h" +#include "shared-module/displayio/__init__.h" + volatile uint64_t last_finished_tick = 0; void run_background_tasks(void) { #if (defined(SAMD21) && defined(PIN_PA02)) || defined(SAMD51) audio_dma_background(); #endif + #ifdef CIRCUITPY_DISPLAYIO + displayio_refresh_display(); + #endif usb_msc_background(); usb_cdc_background(); last_finished_tick = ticks_ms; diff --git a/ports/atmel-samd/boards/board.h b/ports/atmel-samd/boards/board.h index a2a73cfab..61acc730e 100644 --- a/ports/atmel-samd/boards/board.h +++ b/ports/atmel-samd/boards/board.h @@ -31,6 +31,14 @@ #include <stdbool.h> +#include "py/mpconfig.h" + +#ifdef CIRCUITPY_DISPLAYIO +#include "common-hal/displayio/FourWire.h" + +extern displayio_fourwire_obj_t board_display_obj; +#endif + // Initializes board related state once on start up. void board_init(void); diff --git a/ports/atmel-samd/boards/hallowing_m0_express/board.c b/ports/atmel-samd/boards/hallowing_m0_express/board.c index c8e20206a..b47c5fbb2 100644 --- a/ports/atmel-samd/boards/hallowing_m0_express/board.c +++ b/ports/atmel-samd/boards/hallowing_m0_express/board.c @@ -26,8 +26,89 @@ #include "boards/board.h" -void board_init(void) -{ +#include "shared-bindings/displayio/FourWire.h" +#include "shared-module/displayio/mipi_constants.h" + +#include "tick.h" + +displayio_fourwire_obj_t board_display_obj; + +#define DELAY 0x80 + +uint8_t display_init_sequence[] = { + 0x01, 0 | DELAY, 150, // SWRESET + 0x11, 0 | DELAY, 255, // SLPOUT + 0xb1, 3, 0x01, 0x2C, 0x2D, // _FRMCTR1 + 0xb2, 3, 0x01, 0x2C, 0x2D, // + 0xb3, 6, 0x01, 0x2C, 0x2D, 0x01, 0x2C, 0x2D, + 0xb4, 1, 0x07, // _INVCTR line inversion + 0xc0, 3, 0xa2, 0x02, 0x84, // _PWCTR1 GVDD = 4.7V, 1.0uA + 0xc1, 1, 0xc5, // _PWCTR2 VGH=14.7V, VGL=-7.35V + 0xc2, 2, 0x0a, 0x00, // _PWCTR3 Opamp current small, Boost frequency + 0xc3, 2, 0x8a, 0x2a, + 0xc4, 2, 0x8a, 0xee, + 0xc5, 1, 0x0e, // _VMCTR1 VCOMH = 4V, VOML = -1.1V + 0x2a, 0, // _INVOFF + 0x36, 1, 0x18, // _MADCTL bottom to top refresh + // 1 clk cycle nonoverlap, 2 cycle gate rise, 3 sycle osc equalie, + // fix on VTL + 0x3a, 1, 0x05, // COLMOD - 16bit color + 0xe0, 16, 0x02, 0x1c, 0x07, 0x12, // _GMCTRP1 Gamma + 0x37, 0x32, 0x29, 0x2d, + 0x29, 0x25, 0x2B, 0x39, + 0x00, 0x01, 0x03, 0x10, + 0xe1, 16, 0x03, 0x1d, 0x07, 0x06, // _GMCTRN1 + 0x2E, 0x2C, 0x29, 0x2D, + 0x2E, 0x2E, 0x37, 0x3F, + 0x00, 0x00, 0x02, 0x10, + 0x2a, 3, 0x02, 0x00, 0x81, // _CASET XSTART = 2, XEND = 129 + 0x2b, 3, 0x02, 0x00, 0x81, // _RASET XSTART = 2, XEND = 129 + 0x13, 0 | DELAY, 10, // _NORON + 0x29, 0 | DELAY, 100, // _DISPON +}; + +void board_init(void) { + board_display_obj.base.type = &displayio_fourwire_type; + common_hal_displayio_fourwire_construct(&board_display_obj, + &pin_PB23, // Clock + &pin_PB22, // Data + &pin_PA28, // Command or data + &pin_PA01, // Chip select + &pin_PA27, // Reset + 128, // Width + 128, // Height + 2, // column start + 0, // row start + 16, // Color depth + MIPI_COMMAND_SET_COLUMN_ADDRESS, // Set column command + MIPI_COMMAND_SET_PAGE_ADDRESS, // Set row command + MIPI_COMMAND_WRITE_MEMORY_START); // Write memory command + + uint32_t i = 0; + common_hal_displayio_fourwire_begin_transaction(&board_display_obj); + while (i < sizeof(display_init_sequence)) { + uint8_t *cmd = display_init_sequence + i; + uint8_t data_size = *(cmd + 1); + bool delay = (data_size & DELAY) != 0; + data_size &= ~DELAY; + uint8_t *data = cmd + 2; + common_hal_displayio_fourwire_send(&board_display_obj, true, cmd, 1); + common_hal_displayio_fourwire_send(&board_display_obj, false, data, data_size); + if (delay) { + data_size++; + uint16_t delay_length_ms = *(cmd + 1 + data_size); + if (delay_length_ms == 255) { + delay_length_ms = 500; + } + uint64_t start = ticks_ms; + while (ticks_ms - start < delay_length_ms) {} + } else { + uint64_t start = ticks_ms; + while (ticks_ms - start < 10) {} + } + i += 2 + data_size; + } + common_hal_displayio_fourwire_end_transaction(&board_display_obj); } bool board_requests_safe_mode(void) { @@ -35,4 +116,5 @@ bool board_requests_safe_mode(void) { } void reset_board(void) { + common_hal_displayio_fourwire_show(&board_display_obj, NULL); } diff --git a/ports/atmel-samd/boards/hallowing_m0_express/mpconfigboard.h b/ports/atmel-samd/boards/hallowing_m0_express/mpconfigboard.h index 34e9ac327..977ba183f 100644 --- a/ports/atmel-samd/boards/hallowing_m0_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/hallowing_m0_express/mpconfigboard.h @@ -3,7 +3,7 @@ #define MICROPY_HW_NEOPIXEL (&pin_PA12) -// Clock rates are off: Salae reads 12MHz which is the limit even though we set it to the safer 8MHz. +// Clock rates are off: Saleae reads 12MHz which is the limit even though we set it to the safer 8MHz. #define SPI_FLASH_BAUDRATE (8000000) #define SPI_FLASH_MOSI_PIN PIN_PB10 @@ -27,8 +27,8 @@ #define SPI_FLASH_DIPO 1 // same as MISO pad // These are pins not to reset. -#define MICROPY_PORT_A (PORT_PA07 | PORT_PA12 | PORT_PA13 | PORT_PA24 | PORT_PA25) -#define MICROPY_PORT_B ( PORT_PB10 | PORT_PB11 ) +#define MICROPY_PORT_A ( PORT_PA01 | PORT_PA07 | PORT_PA12 | PORT_PA13 | PORT_PA24 | PORT_PA25 | PORT_PA27 | PORT_PA28) +#define MICROPY_PORT_B ( PORT_PB10 | PORT_PB11 | PORT_PB22 | PORT_PB23 ) #define MICROPY_PORT_C ( 0 ) #include "external_flash/external_flash.h" @@ -61,3 +61,5 @@ // USB is always used internally so skip the pin objects for it. #define IGNORE_PIN_PA24 1 #define IGNORE_PIN_PA25 1 + +#define CIRCUITPY_DISPLAYIO diff --git a/ports/atmel-samd/boards/hallowing_m0_express/pins.c b/ports/atmel-samd/boards/hallowing_m0_express/pins.c index 8d6f9431e..7d4afc7a4 100644 --- a/ports/atmel-samd/boards/hallowing_m0_express/pins.c +++ b/ports/atmel-samd/boards/hallowing_m0_express/pins.c @@ -1,5 +1,6 @@ #include "shared-bindings/board/__init__.h" +#include "boards/board.h" #include "board_busses.h" STATIC const mp_rom_map_elem_t board_global_dict_table[] = { @@ -56,5 +57,7 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, + + { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&board_display_obj)} }; MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); diff --git a/ports/atmel-samd/common-hal/displayio/FourWire.c b/ports/atmel-samd/common-hal/displayio/FourWire.c new file mode 100644 index 000000000..6c3b75a85 --- /dev/null +++ b/ports/atmel-samd/common-hal/displayio/FourWire.c @@ -0,0 +1,139 @@ +/* + * 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. + */ + +#include "shared-bindings/displayio/FourWire.h" + +#include <stdint.h> + +#include "shared-bindings/busio/SPI.h" +#include "shared-bindings/digitalio/DigitalInOut.h" + +#include "tick.h" + +void common_hal_displayio_fourwire_construct(displayio_fourwire_obj_t* self, + const mcu_pin_obj_t* clock, const mcu_pin_obj_t* data, const mcu_pin_obj_t* command, + const mcu_pin_obj_t* chip_select, const mcu_pin_obj_t* reset, 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) { + + common_hal_busio_spi_construct(&self->bus, clock, data, mp_const_none); + common_hal_digitalio_digitalinout_construct(&self->command, command); + common_hal_digitalio_digitalinout_switch_to_output(&self->command, true, DRIVE_MODE_PUSH_PULL); + common_hal_digitalio_digitalinout_construct(&self->chip_select, chip_select); + common_hal_digitalio_digitalinout_switch_to_output(&self->chip_select, true, DRIVE_MODE_PUSH_PULL); + + common_hal_digitalio_digitalinout_construct(&self->reset, reset); + common_hal_digitalio_digitalinout_switch_to_output(&self->reset, true, DRIVE_MODE_PUSH_PULL); + + 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->current_group = NULL; + self->colstart = colstart; + self->rowstart = rowstart; +} + +bool common_hal_displayio_fourwire_begin_transaction(displayio_fourwire_obj_t* self) { + if (!common_hal_busio_spi_try_lock(&self->bus)) { + return false; + } + // TODO(tannewt): Stop hardcoding SPI frequency, polarity and phase. + common_hal_busio_spi_configure(&self->bus, 12000000, 0, 0, 8); + common_hal_digitalio_digitalinout_set_value(&self->chip_select, false); + return true; +} + +void common_hal_displayio_fourwire_send(displayio_fourwire_obj_t* self, bool command, uint8_t *data, uint32_t data_length) { + common_hal_digitalio_digitalinout_set_value(&self->command, !command); + common_hal_busio_spi_write(&self->bus, data, data_length); +} + +void common_hal_displayio_fourwire_end_transaction(displayio_fourwire_obj_t* self) { + common_hal_digitalio_digitalinout_set_value(&self->chip_select, true); + common_hal_busio_spi_unlock(&self->bus); +} + +void common_hal_displayio_fourwire_show(displayio_fourwire_obj_t* self, displayio_group_t* root_group) { + self->current_group = root_group; + common_hal_displayio_fourwire_refresh_soon(self); +} + +void common_hal_displayio_fourwire_refresh_soon(displayio_fourwire_obj_t* self) { + self->refresh = true; +} + +int32_t common_hal_displayio_fourwire_wait_for_frame(displayio_fourwire_obj_t* self) { + uint64_t last_refresh = self->last_refresh; + while (last_refresh == self->last_refresh) { + MICROPY_VM_HOOK_LOOP + } + return 0; +} + +void displayio_fourwire_start_region_update(displayio_fourwire_obj_t* self, uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) { + // TODO(tannewt): Handle displays with single byte bounds. + common_hal_displayio_fourwire_begin_transaction(self); + uint16_t data[2]; + common_hal_displayio_fourwire_send(self, true, &self->set_column_command, 1); + data[0] = __builtin_bswap16(x0 + self->colstart); + data[1] = __builtin_bswap16(x1-1 + self->colstart); + common_hal_displayio_fourwire_send(self, false, (uint8_t*) data, 4); + common_hal_displayio_fourwire_send(self, true, &self->set_row_command, 1); + data[0] = __builtin_bswap16(y0 + 1 + self->rowstart); + data[1] = __builtin_bswap16(y1 + self->rowstart); + common_hal_displayio_fourwire_send(self, false, (uint8_t*) data, 4); + common_hal_displayio_fourwire_send(self, true, &self->write_ram_command, 1); +} + +bool displayio_fourwire_send_pixels(displayio_fourwire_obj_t* self, uint32_t* pixels, uint32_t length) { + // TODO: Set this up so its async and 32 bit DMA transfers. + common_hal_displayio_fourwire_send(self, false, (uint8_t*) pixels, length*4); + return true; +} + +void displayio_fourwire_finish_region_update(displayio_fourwire_obj_t* self) { + common_hal_displayio_fourwire_end_transaction(self); +} + +bool displayio_fourwire_frame_queued(displayio_fourwire_obj_t* self) { + // Refresh at ~30 fps. + return (ticks_ms - self->last_refresh) > 32; +} + +bool displayio_fourwire_refresh_queued(displayio_fourwire_obj_t* self) { + return self->refresh || (self->current_group != NULL && displayio_group_needs_refresh(self->current_group)); +} + +void displayio_fourwire_finish_refresh(displayio_fourwire_obj_t* self) { + if (self->current_group != NULL) { + displayio_group_finish_refresh(self->current_group); + } + self->refresh = false; + self->last_refresh = ticks_ms; +} diff --git a/ports/atmel-samd/common-hal/displayio/FourWire.h b/ports/atmel-samd/common-hal/displayio/FourWire.h new file mode 100644 index 000000000..b99717670 --- /dev/null +++ b/ports/atmel-samd/common-hal/displayio/FourWire.h @@ -0,0 +1,53 @@ +/* + * 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 MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_DISPLAYIO_FOURWIRE_H +#define MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_DISPLAYIO_FOURWIRE_H + +#include "common-hal/busio/SPI.h" +#include "common-hal/digitalio/DigitalInOut.h" +#include "shared-module/displayio/Group.h" + +typedef struct { + mp_obj_base_t base; + busio_spi_obj_t bus; + digitalio_digitalinout_obj_t command; + digitalio_digitalinout_obj_t chip_select; + digitalio_digitalinout_obj_t reset; + uint16_t width; + uint16_t height; + uint16_t color_depth; + uint8_t set_column_command; + uint8_t set_row_command; + uint8_t write_ram_command; + displayio_group_t *current_group; + bool refresh; + uint64_t last_refresh; + int16_t colstart; + int16_t rowstart; +} displayio_fourwire_obj_t; + +#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_DISPLAYIO_FOURWIRE_H diff --git a/ports/atmel-samd/mpconfigport.h b/ports/atmel-samd/mpconfigport.h index 576325461..14f72ccfb 100644 --- a/ports/atmel-samd/mpconfigport.h +++ b/ports/atmel-samd/mpconfigport.h @@ -171,6 +171,7 @@ extern const struct _mp_obj_module_t audioio_module; extern const struct _mp_obj_module_t audiobusio_module; extern const struct _mp_obj_module_t analogio_module; extern const struct _mp_obj_module_t digitalio_module; +extern const struct _mp_obj_module_t displayio_module; extern const struct _mp_obj_module_t pulseio_module; extern const struct _mp_obj_module_t busio_module; extern const struct _mp_obj_module_t board_module; @@ -232,11 +233,18 @@ extern const struct _mp_obj_module_t usb_hid_module; #define I2CSLAVE_MODULE #endif + #ifdef CIRCUITPY_DISPLAYIO + #define DISPLAYIO_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_displayio), (mp_obj_t)&displayio_module }, + #else + #define DISPLAYIO_MODULE + #endif + #ifndef EXTRA_BUILTIN_MODULES #define EXTRA_BUILTIN_MODULES \ AUDIOIO_MODULE \ AUDIOBUSIO_MODULE \ { MP_OBJ_NEW_QSTR(MP_QSTR_bitbangio), (mp_obj_t)&bitbangio_module }, \ + DISPLAYIO_MODULE \ I2CSLAVE_MODULE \ { MP_OBJ_NEW_QSTR(MP_QSTR_rotaryio), (mp_obj_t)&rotaryio_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_gamepad),(mp_obj_t)&gamepad_module } diff --git a/ports/atmel-samd/supervisor/port.c b/ports/atmel-samd/supervisor/port.c index 957642269..f6d968a1c 100644 --- a/ports/atmel-samd/supervisor/port.c +++ b/ports/atmel-samd/supervisor/port.c @@ -186,8 +186,6 @@ safe_mode_t port_init(void) { #endif clock_init(); - board_init(); - // Configure millisecond timer initialization. tick_init(); @@ -196,6 +194,10 @@ safe_mode_t port_init(void) { #endif init_shared_dma(); + + // Init the board last so everything else is ready + board_init(); + #ifdef CIRCUITPY_CANARY_WORD // Run in safe mode if the canary is corrupt. if (_ezero != CIRCUITPY_CANARY_WORD) { @@ -235,6 +237,12 @@ void reset_port(void) { continue; } #endif +#ifdef CIRCUITPY_DISPLAYIO + // TODO(tannewt): Make this dynamic. + if (sercom_instances[i] == board_display_obj.bus.spi_desc.dev.prvt) { + continue; + } +#endif // SWRST is same for all modes of SERCOMs. sercom_instances[i]->SPI.CTRLA.bit.SWRST = 1; } |
