@ -28,6 +28,7 @@
# include "py/runtime.h"
# include "shared-bindings/displayio/FourWire.h"
# include "shared-bindings/displayio/I2CDisplay.h"
# include "shared-bindings/displayio/ParallelBus.h"
# include "shared-bindings/microcontroller/Pin.h"
# include "shared-bindings/time/__init__.h"
@ -35,6 +36,7 @@
# include "supervisor/shared/display.h"
# include <stdint.h>
# include <string.h>
# include "tick.h"
@ -42,11 +44,14 @@
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 rotation ,
uint16_t color_depth , uint8_t set_column_command , uint8_t set_row_command ,
uint16_t color_depth , bool grayscale , bool pixels_in_byte_share_row ,
uint8_t set_column_command , uint8_t set_row_command ,
uint8_t write_ram_command , uint8_t set_vertical_scroll , uint8_t * init_sequence , uint16_t init_sequence_len ,
const mcu_pin_obj_t * backlight_pin , mp_float_t brightness , bool auto_brightness ,
const mcu_pin_obj_t * backlight_pin , uint16_t brightness_command , mp_float_t brightness , bool auto_brightness ,
bool single_byte_bounds , bool data_as_commands ) {
self - > color_depth = color_depth ;
self - > colorspace . depth = color_depth ;
self - > colorspace . grayscale = grayscale ;
self - > colorspace . pixels_in_byte_share_row = pixels_in_byte_share_row ;
self - > set_column_command = set_column_command ;
self - > set_row_command = set_row_command ;
self - > write_ram_command = write_ram_command ;
@ -54,6 +59,7 @@ void common_hal_displayio_display_construct(displayio_display_obj_t* self,
self - > current_group = NULL ;
self - > colstart = colstart ;
self - > rowstart = rowstart ;
self - > brightness_command = brightness_command ;
self - > auto_brightness = auto_brightness ;
self - > data_as_commands = data_as_commands ;
self - > single_byte_bounds = single_byte_bounds ;
@ -66,6 +72,10 @@ void common_hal_displayio_display_construct(displayio_display_obj_t* self,
self - > begin_transaction = common_hal_displayio_fourwire_begin_transaction ;
self - > send = common_hal_displayio_fourwire_send ;
self - > end_transaction = common_hal_displayio_fourwire_end_transaction ;
} else if ( MP_OBJ_IS_TYPE ( bus , & displayio_i2cdisplay_type ) ) {
self - > begin_transaction = common_hal_displayio_i2cdisplay_begin_transaction ;
self - > send = common_hal_displayio_i2cdisplay_send ;
self - > end_transaction = common_hal_displayio_i2cdisplay_end_transaction ;
} else {
mp_raise_ValueError ( translate ( " Unsupported display bus type " ) ) ;
}
@ -83,13 +93,13 @@ void common_hal_displayio_display_construct(displayio_display_obj_t* self,
bool delay = ( data_size & DELAY ) ! = 0 ;
data_size & = ~ DELAY ;
uint8_t * data = cmd + 2 ;
self - > send ( self - > bus , true , cmd , 1 ) ;
if ( self - > data_as_commands ) {
// Loop through each parameter to force a CS toggle
for ( uint32_t j = 0 ; j < data_size ; j + + ) {
self - > send ( self - > bus , true , data + j , 1 ) ;
}
uint8_t full_command [ data_size + 1 ] ;
full_command [ 0 ] = cmd [ 0 ] ;
memcpy ( full_command + 1 , data , data_size ) ;
self - > send ( self - > bus , true , full_command , data_size + 1 ) ;
} else {
self - > send ( self - > bus , true , cmd , 1 ) ;
self - > send ( self - > bus , false , data , data_size ) ;
}
uint16_t delay_length_ms = 10 ;
@ -141,11 +151,13 @@ void common_hal_displayio_display_construct(displayio_display_obj_t* self,
} else {
self - > backlight_pwm . base . type = & pulseio_pwmout_type ;
common_hal_pulseio_pwmout_never_reset ( & self - > backlight_pwm ) ;
if ( ! self - > auto_brightness ) {
common_hal_displayio_display_set_brightness ( self , brightness ) ;
}
}
}
if ( ! self - > auto_brightness & & ( self - > backlight_inout . base . type ! = & mp_type_NoneType | | brightness_command < = 0xff ) ) {
common_hal_displayio_display_set_brightness ( self , brightness ) ;
} else {
self - > current_brightness = - 1.0 ;
}
self - > area . x1 = 0 ;
self - > area . y1 = 0 ;
@ -234,17 +246,7 @@ void common_hal_displayio_display_set_auto_brightness(displayio_display_obj_t* s
}
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 ;
return self - > current_brightness ;
}
bool common_hal_displayio_display_set_brightness ( displayio_display_obj_t * self , mp_float_t brightness ) {
@ -256,8 +258,26 @@ bool common_hal_displayio_display_set_brightness(displayio_display_obj_t* self,
} else if ( self - > backlight_inout . base . type = = & digitalio_digitalinout_type ) {
common_hal_digitalio_digitalinout_set_value ( & self - > backlight_inout , brightness > 0.99 ) ;
ok = true ;
} else if ( self - > brightness_command < 0x100 ) {
ok = self - > begin_transaction ( self - > bus ) ;
if ( ok ) {
if ( self - > data_as_commands ) {
uint8_t set_brightness [ 2 ] = { self - > brightness_command , ( uint8_t ) ( 0xff * brightness ) } ;
self - > send ( self - > bus , true , set_brightness , 2 ) ;
} else {
uint8_t command = self - > brightness_command ;
uint8_t hex_brightness = 0xff * brightness ;
self - > send ( self - > bus , true , & command , 1 ) ;
self - > send ( self - > bus , false , & hex_brightness , 1 ) ;
}
self - > end_transaction ( self - > bus ) ;
}
}
self - > updating_backlight = false ;
if ( ok ) {
self - > current_brightness = brightness ;
}
return ok ;
}
@ -269,35 +289,67 @@ void displayio_display_end_transaction(displayio_display_obj_t* self) {
self - > end_transaction ( self - > bus ) ;
}
void displayio_display_set_region_to_update ( displayio_display_obj_t * self , uint16_t x0 , uint16_t y0 , uint16_t x1 , uint16_t y1 ) {
self - > send ( self - > bus , true , & self - > set_column_command , 1 ) ;
bool isCommand = self - > data_as_commands ;
if ( self - > single_byte_bounds ) {
uint8_t data [ 2 ] ;
data [ 0 ] = x0 + self - > colstart ;
data [ 1 ] = x1 - 1 + self - > colstart ;
self - > send ( self - > bus , isCommand , ( uint8_t * ) data , 2 ) ;
} else {
uint16_t data [ 2 ] ;
data [ 0 ] = __builtin_bswap16 ( x0 + self - > colstart ) ;
data [ 1 ] = __builtin_bswap16 ( x1 - 1 + self - > colstart ) ;
self - > send ( self - > bus , isCommand , ( uint8_t * ) data , 4 ) ;
void displayio_display_set_region_to_update ( displayio_display_obj_t * self , displayio_area_t * area ) {
uint16_t x1 = area - > x1 ;
uint16_t x2 = area - > x2 ;
uint16_t y1 = area - > y1 ;
uint16_t y2 = area - > y2 ;
// Collapse down the dimension where multiple pixels are in a byte.
if ( self - > colorspace . depth < 8 ) {
uint8_t pixels_per_byte = 8 / self - > colorspace . depth ;
if ( self - > colorspace . pixels_in_byte_share_row ) {
x1 / = pixels_per_byte ;
x2 / = pixels_per_byte ;
} else {
y1 / = pixels_per_byte ;
y2 / = pixels_per_byte ;
}
}
// Set column.
uint8_t data [ 5 ] ;
data [ 0 ] = self - > set_column_command ;
uint8_t data_length = 1 ;
if ( ! self - > data_as_commands ) {
self - > send ( self - > bus , true , data , 1 ) ;
data_length = 0 ;
}
self - > send ( self - > bus , true , & self - > set_row_command , 1 ) ;
if ( self - > single_byte_bounds ) {
uint8_t data [ 2 ] ;
data [ 0 ] = y0 + self - > rowstart ;
data [ 1 ] = y1 - 1 + self - > rowstart ;
self - > send ( self - > bus , isCommand , ( uint8_t * ) data , 2 ) ;
data [ data_length ] = x1 + self - > colstart ;
data [ data_length + 1 ] = x2 - 1 + self - > colstart ;
data_length + = 2 ;
} else {
uint16_t data [ 2 ] ;
data [ 0 ] = __builtin_bswap16 ( y0 + self - > rowstart ) ;
data [ 1 ] = __builtin_bswap16 ( y1 - 1 + self - > rowstart ) ;
self - > send ( self - > bus , isCommand , ( uint8_t * ) data , 4 ) ;
x1 + = self - > colstart ;
x2 + = self - > colstart - 1 ;
data [ data_length ] = x1 > > 8 ;
data [ data_length + 1 ] = x1 & 0xff ;
data [ data_length + 2 ] = x2 > > 8 ;
data [ data_length + 3 ] = x2 & 0xff ;
data_length + = 4 ;
}
self - > send ( self - > bus , self - > data_as_commands , data , data_length ) ;
// Set row.
data [ 0 ] = self - > set_row_command ;
data_length = 1 ;
if ( ! self - > data_as_commands ) {
self - > send ( self - > bus , true , & self - > write_ram_command , 1 ) ;
self - > send ( self - > bus , true , data , 1 ) ;
data_length = 0 ;
}
if ( self - > single_byte_bounds ) {
data [ data_length ] = y1 + self - > rowstart ;
data [ data_length + 1 ] = y2 - 1 + self - > rowstart ;
data_length + = 2 ;
} else {
y1 + = self - > rowstart ;
y2 + = self - > rowstart - 1 ;
data [ data_length ] = y1 > > 8 ;
data [ data_length + 1 ] = y1 & 0xff ;
data [ data_length + 2 ] = y2 > > 8 ;
data [ data_length + 3 ] = y2 & 0xff ;
data_length + = 4 ;
}
self - > send ( self - > bus , self - > data_as_commands , data , data_length ) ;
}
void displayio_display_start_refresh ( displayio_display_obj_t * self ) {
@ -322,6 +374,9 @@ void displayio_display_finish_refresh(displayio_display_obj_t* self) {
}
void displayio_display_send_pixels ( displayio_display_obj_t * self , uint8_t * pixels , uint32_t length ) {
if ( ! self - > data_as_commands ) {
self - > send ( self - > bus , true , & self - > write_ram_command , 1 ) ;
}
self - > send ( self - > bus , false , pixels , length ) ;
}
@ -349,9 +404,33 @@ void release_display(displayio_display_obj_t* self) {
}
bool displayio_display_fill_area ( displayio_display_obj_t * self , displayio_area_t * area , uint32_t * mask , uint32_t * buffer ) {
return displayio_group_fill_area ( self - > current_group , area , mask , buffer ) ;
return displayio_group_fill_area ( self - > current_group , & self - > colorspace , area , mask , buffer ) ;
}
bool displayio_display_clip_area ( displayio_display_obj_t * self , const displayio_area_t * area , displayio_area_t * clipped ) {
return displayio_area_compute_overlap ( & self - > area , area , clipped ) ;
bool overlaps = displayio_area_compute_overlap ( & self - > area , area , clipped ) ;
if ( ! overlaps ) {
return false ;
}
// Expand the area if we have multiple pixels per byte and we need to byte
// align the bounds.
if ( self - > colorspace . depth < 8 ) {
uint8_t pixels_per_byte = 8 / self - > colorspace . depth ;
if ( self - > colorspace . pixels_in_byte_share_row ) {
if ( clipped - > x1 % pixels_per_byte ! = 0 ) {
clipped - > x1 - = clipped - > x1 % pixels_per_byte ;
}
if ( clipped - > x2 % pixels_per_byte ! = 0 ) {
clipped - > x2 + = pixels_per_byte - clipped - > x2 % pixels_per_byte ;
}
} else {
if ( clipped - > y1 % pixels_per_byte ! = 0 ) {
clipped - > y1 - = clipped - > y1 % pixels_per_byte ;
}
if ( clipped - > y2 % pixels_per_byte ! = 0 ) {
clipped - > y2 + = pixels_per_byte - clipped - > y2 % pixels_per_byte ;
}
}
}
return true ;
}