Add board.DISPLAY to MagTag. Fix luma computation

* Initialize the EPaper display on the MagTag at start.
* Tweak the display send to take a const buffer.
* Correct Luma math
  * Multiply the blue component, not add.
  * Add all of the components together before dividing. This
    reduces the impact of truncated division.
This commit is contained in:
Scott Shawcroft 2020-11-10 18:02:16 -08:00
parent 9169878ebb
commit 8d4296f964
No known key found for this signature in database
GPG Key ID: 0DFD512649C052DA
13 changed files with 152 additions and 17 deletions

View File

@ -26,7 +26,83 @@
#include "boards/board.h"
#include "mpconfigboard.h"
#include "shared-bindings/busio/SPI.h"
#include "shared-bindings/displayio/FourWire.h"
#include "shared-bindings/microcontroller/Pin.h"
#include "shared-module/displayio/__init__.h"
#include "supervisor/shared/board.h"
#define DELAY 0x80
// This is an ILO373 control chip. The display is a 2.9" grayscale EInk.
const uint8_t display_start_sequence[] = {
0x01, 5, 0x03, 0x00, 0x2b, 0x2b, 0x13, // power setting
0x06, 3, 0x17, 0x17, 0x17, // booster soft start
0x04, DELAY, 200, // power on and wait 200 ms
0x00, 1, 0x7f, // panel setting
0x50, 1, 0x97, // CDI setting
0x30, 1, 0x3c, // PLL set to 50 Hx (M = 7, N = 4)
0x61, 3, 0x80, 0x01, 0x28, // Resolution
0x82, DELAY | 1, 0x12, 50, // VCM DC and delay 50ms
// Look up tables for voltage sequence for pixel transition
// Common voltage
0x20, 0x2a,
0x00, 0x0a, 0x00, 0x00, 0x00, 0x01,
0x60, 0x14, 0x14, 0x00, 0x00, 0x01,
0x00, 0x14, 0x00, 0x00, 0x00, 0x01,
0x00, 0x13, 0x0a, 0x01, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// White to white
0x21, 0x2a,
0x40, 0x0a, 0x00, 0x00, 0x00, 0x01,
0x90, 0x14, 0x14, 0x00, 0x00, 0x01,
0x10, 0x14, 0x0a, 0x00, 0x00, 0x01,
0xa0, 0x13, 0x01, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// Black to white
0x22, 0x2a,
0x40, 0x0a, 0x00, 0x00, 0x00, 0x01,
0x90, 0x14, 0x14, 0x00, 0x00, 0x01,
0x00, 0x14, 0x0a, 0x00, 0x00, 0x01,
0x99, 0x0c, 0x01, 0x03, 0x04, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// White to black
0x23, 0x2a,
0x40, 0x0a, 0x00, 0x00, 0x00, 0x01,
0x90, 0x14, 0x14, 0x00, 0x00, 0x01,
0x00, 0x14, 0x0a, 0x00, 0x00, 0x01,
0x99, 0x0b, 0x04, 0x04, 0x01, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// Black to black
0x24, 0x2a,
0x80, 0x0a, 0x00, 0x00, 0x00, 0x01,
0x90, 0x14, 0x14, 0x00, 0x00, 0x01,
0x20, 0x14, 0x0a, 0x00, 0x00, 0x01,
0x50, 0x13, 0x01, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
const uint8_t display_stop_sequence[] = {
0x50, 0x01, 0x17, // CDI Setting
0x82, 0x01, 0x00, // VCM DC to -0.1V
0x02, 0x00 // Power off
};
void board_init(void) {
// USB
@ -36,6 +112,52 @@ void board_init(void) {
// Debug UART
common_hal_never_reset_pin(&pin_GPIO43);
common_hal_never_reset_pin(&pin_GPIO44);
busio_spi_obj_t* spi = &displays[0].fourwire_bus.inline_bus;
common_hal_busio_spi_construct(spi, &pin_GPIO36, &pin_GPIO35, NULL);
common_hal_busio_spi_never_reset(spi);
displayio_fourwire_obj_t* bus = &displays[0].fourwire_bus;
bus->base.type = &displayio_fourwire_type;
common_hal_displayio_fourwire_construct(bus,
spi,
&pin_GPIO7, // EPD_DC Command or data
&pin_GPIO8, // EPD_CS Chip select
&pin_GPIO6, // EPD_RST Reset
4000000, // Baudrate
0, // Polarity
0); // Phase
displayio_epaperdisplay_obj_t* display = &displays[0].epaper_display;
display->base.type = &displayio_epaperdisplay_type;
common_hal_displayio_epaperdisplay_construct(
display,
bus,
display_start_sequence, sizeof(display_start_sequence),
display_stop_sequence, sizeof(display_stop_sequence),
296, // width
128, // height
160, // ram_width
296, // ram_height
0, // colstart
0, // rowstart
270, // rotation
NO_COMMAND, // set_column_window_command
NO_COMMAND, // set_row_window_command
NO_COMMAND, // set_current_column_command
NO_COMMAND, // set_current_row_command
0x10, // write_black_ram_command
false, // black_bits_inverted
0x13, // write_color_ram_command
false, // color_bits_inverted
0x000000, // highlight_color
0x12, // refresh_display_command
1.0, // refresh_time
&pin_GPIO5, // busy_pin
false, // busy_state
5.0, // seconds_per_frame
false, // always_toggle_chip_select
true); // grayscale
}
bool board_requests_safe_mode(void) {

View File

@ -1,5 +1,7 @@
#include "shared-bindings/board/__init__.h"
#include "shared-module/displayio/__init__.h"
STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_GPIO10) },
{ MP_ROM_QSTR(MP_QSTR_AD1), MP_ROM_PTR(&pin_GPIO18) },
@ -37,5 +39,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_DISPLAY), MP_ROM_PTR(&displays[0].epaper_display)}
};
MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);

View File

@ -57,7 +57,8 @@ bool common_hal_displayio_parallelbus_begin_transaction(mp_obj_t obj) {
return false;
}
void common_hal_displayio_parallelbus_send(mp_obj_t obj, display_byte_type_t byte_type, display_chip_select_behavior_t chip_select, uint8_t *data, uint32_t data_length) {
void common_hal_displayio_parallelbus_send(mp_obj_t obj, display_byte_type_t byte_type,
display_chip_select_behavior_t chip_select, const uint8_t *data, uint32_t data_length) {
}

View File

@ -39,7 +39,7 @@ extern const mp_obj_type_t displayio_epaperdisplay_type;
#define NO_COMMAND 0x100
void common_hal_displayio_epaperdisplay_construct(displayio_epaperdisplay_obj_t* self,
mp_obj_t bus, uint8_t* start_sequence, uint16_t start_sequence_len, uint8_t* stop_sequence, uint16_t stop_sequence_len,
mp_obj_t bus, const uint8_t* start_sequence, uint16_t start_sequence_len, const uint8_t* stop_sequence, uint16_t stop_sequence_len,
uint16_t width, uint16_t height, uint16_t ram_width, uint16_t ram_height, int16_t colstart, int16_t rowstart, uint16_t rotation,
uint16_t set_column_window_command, uint16_t set_row_window_command,
uint16_t set_current_column_command, uint16_t set_current_row_command,

View File

@ -48,7 +48,8 @@ bool common_hal_displayio_fourwire_bus_free(mp_obj_t self);
bool common_hal_displayio_fourwire_begin_transaction(mp_obj_t self);
void common_hal_displayio_fourwire_send(mp_obj_t self, display_byte_type_t byte_type, display_chip_select_behavior_t chip_select, uint8_t *data, uint32_t data_length);
void common_hal_displayio_fourwire_send(mp_obj_t self, display_byte_type_t byte_type,
display_chip_select_behavior_t chip_select, const uint8_t *data, uint32_t data_length);
void common_hal_displayio_fourwire_end_transaction(mp_obj_t self);

View File

@ -44,7 +44,8 @@ bool common_hal_displayio_i2cdisplay_bus_free(mp_obj_t self);
bool common_hal_displayio_i2cdisplay_begin_transaction(mp_obj_t self);
void common_hal_displayio_i2cdisplay_send(mp_obj_t self, display_byte_type_t byte_type, display_chip_select_behavior_t chip_select, uint8_t *data, uint32_t data_length);
void common_hal_displayio_i2cdisplay_send(mp_obj_t self, display_byte_type_t byte_type,
display_chip_select_behavior_t chip_select, const uint8_t *data, uint32_t data_length);
void common_hal_displayio_i2cdisplay_end_transaction(mp_obj_t self);

View File

@ -46,7 +46,8 @@ bool common_hal_displayio_parallelbus_bus_free(mp_obj_t self);
bool common_hal_displayio_parallelbus_begin_transaction(mp_obj_t self);
void common_hal_displayio_parallelbus_send(mp_obj_t self, display_byte_type_t byte_type, display_chip_select_behavior_t chip_select, uint8_t *data, uint32_t data_length);
void common_hal_displayio_parallelbus_send(mp_obj_t self, display_byte_type_t byte_type,
display_chip_select_behavior_t chip_select, const uint8_t *data, uint32_t data_length);
void common_hal_displayio_parallelbus_end_transaction(mp_obj_t self);

View File

@ -42,7 +42,8 @@ typedef enum {
typedef bool (*display_bus_bus_reset)(mp_obj_t bus);
typedef bool (*display_bus_bus_free)(mp_obj_t bus);
typedef bool (*display_bus_begin_transaction)(mp_obj_t bus);
typedef void (*display_bus_send)(mp_obj_t bus, display_byte_type_t byte_type, display_chip_select_behavior_t chip_select, uint8_t *data, uint32_t data_length);
typedef void (*display_bus_send)(mp_obj_t bus, display_byte_type_t byte_type,
display_chip_select_behavior_t chip_select, const uint8_t *data, uint32_t data_length);
typedef void (*display_bus_end_transaction)(mp_obj_t bus);
void common_hal_displayio_release_displays(void);

View File

@ -55,7 +55,7 @@ uint8_t displayio_colorconverter_compute_luma(uint32_t color_rgb888) {
uint32_t r8 = (color_rgb888 >> 16);
uint32_t g8 = (color_rgb888 >> 8) & 0xff;
uint32_t b8 = color_rgb888 & 0xff;
return (r8 * 19) / 255 + (g8 * 182) / 255 + (b8 + 54) / 255;
return (r8 * 19 + g8 * 182 + b8 * 54) / 255;
}
uint8_t displayio_colorconverter_compute_chroma(uint32_t color_rgb888) {

View File

@ -43,7 +43,8 @@
#include <string.h>
void common_hal_displayio_epaperdisplay_construct(displayio_epaperdisplay_obj_t* self,
mp_obj_t bus, uint8_t* start_sequence, uint16_t start_sequence_len, uint8_t* stop_sequence, uint16_t stop_sequence_len,
mp_obj_t bus, const uint8_t* start_sequence, uint16_t start_sequence_len,
const uint8_t* stop_sequence, uint16_t stop_sequence_len,
uint16_t width, uint16_t height, uint16_t ram_width, uint16_t ram_height,
int16_t colstart, int16_t rowstart, uint16_t rotation,
uint16_t set_column_window_command, uint16_t set_row_window_command,
@ -133,14 +134,15 @@ STATIC void wait_for_busy(displayio_epaperdisplay_obj_t* self) {
}
}
STATIC void send_command_sequence(displayio_epaperdisplay_obj_t* self, bool should_wait_for_busy, uint8_t* sequence, uint32_t sequence_len) {
STATIC void send_command_sequence(displayio_epaperdisplay_obj_t* self,
bool should_wait_for_busy, const uint8_t* sequence, uint32_t sequence_len) {
uint32_t i = 0;
while (i < sequence_len) {
uint8_t *cmd = sequence + i;
const uint8_t *cmd = sequence + i;
uint8_t data_size = *(cmd + 1);
bool delay = (data_size & DELAY) != 0;
data_size &= ~DELAY;
uint8_t *data = cmd + 2;
const uint8_t *data = cmd + 2;
displayio_display_core_begin_transaction(&self->core);
self->core.send(self->core.bus, DISPLAY_COMMAND, self->chip_select, cmd, 1);
self->core.send(self->core.bus, DISPLAY_DATA, self->chip_select, data, data_size);
@ -375,8 +377,8 @@ void release_epaperdisplay(displayio_epaperdisplay_obj_t* self) {
void displayio_epaperdisplay_collect_ptrs(displayio_epaperdisplay_obj_t* self) {
displayio_display_core_collect_ptrs(&self->core);
gc_collect_ptr(self->start_sequence);
gc_collect_ptr(self->stop_sequence);
gc_collect_ptr((void *) self->start_sequence);
gc_collect_ptr((void *) self->stop_sequence);
}
bool maybe_refresh_epaperdisplay(void) {

View File

@ -38,9 +38,9 @@ typedef struct {
displayio_display_core_t core;
digitalio_digitalinout_obj_t busy;
uint32_t milliseconds_per_frame;
uint8_t* start_sequence;
const uint8_t* start_sequence;
uint32_t start_sequence_len;
uint8_t* stop_sequence;
const uint8_t* stop_sequence;
uint32_t stop_sequence_len;
uint16_t refresh_time;
uint16_t set_column_window_command;

View File

@ -113,7 +113,8 @@ bool common_hal_displayio_fourwire_begin_transaction(mp_obj_t obj) {
return true;
}
void common_hal_displayio_fourwire_send(mp_obj_t obj, display_byte_type_t data_type, display_chip_select_behavior_t chip_select, uint8_t *data, uint32_t data_length) {
void common_hal_displayio_fourwire_send(mp_obj_t obj, display_byte_type_t data_type,
display_chip_select_behavior_t chip_select, const uint8_t *data, uint32_t data_length) {
displayio_fourwire_obj_t* self = MP_OBJ_TO_PTR(obj);
common_hal_digitalio_digitalinout_set_value(&self->command, data_type == DISPLAY_DATA);
if (chip_select == CHIP_SELECT_TOGGLE_EVERY_BYTE) {

View File

@ -103,7 +103,8 @@ bool common_hal_displayio_i2cdisplay_begin_transaction(mp_obj_t obj) {
return common_hal_busio_i2c_try_lock(self->bus);
}
void common_hal_displayio_i2cdisplay_send(mp_obj_t obj, display_byte_type_t data_type, display_chip_select_behavior_t chip_select, uint8_t *data, uint32_t data_length) {
void common_hal_displayio_i2cdisplay_send(mp_obj_t obj, display_byte_type_t data_type,
display_chip_select_behavior_t chip_select, const uint8_t *data, uint32_t data_length) {
displayio_i2cdisplay_obj_t* self = MP_OBJ_TO_PTR(obj);
if (data_type == DISPLAY_COMMAND) {
uint8_t command_bytes[2 * data_length];