@ -33,7 +33,9 @@
# include "shared-bindings/microcontroller/Pin.h"
# include "shared-bindings/time/__init__.h"
# include "shared-module/displayio/__init__.h"
# include "shared-module/displayio/display_core.h"
# include "supervisor/shared/display.h"
# include "supervisor/usb.h"
# include <stdint.h>
# include <string.h>
@ -41,48 +43,34 @@
# include "tick.h"
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 , bool grayscale , bool pixels_in_byte_share_row , uint8_t bytes_per_cell , bool reverse_pixels_in_byte ,
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 , uint16_t brightness_command , mp_float_t brightness , bool auto_brightness ,
bool single_byte_bounds , bool data_as_commands ) {
self - > colorspace . depth = color_depth ;
self - > colorspace . grayscale = grayscale ;
self - > colorspace . pixels_in_byte_share_row = pixels_in_byte_share_row ;
self - > colorspace . bytes_per_cell = bytes_per_cell ;
self - > colorspace . reverse_pixels_in_byte = reverse_pixels_in_byte ;
mp_obj_t bus , uint16_t width , uint16_t height , int16_t colstart , int16_t rowstart ,
uint16_t rotation , uint16_t color_depth , bool grayscale , bool pixels_in_byte_share_row ,
uint8_t bytes_per_cell , bool reverse_pixels_in_byte , 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 ,
uint16_t brightness_command , mp_float_t brightness , bool auto_brightness ,
bool single_byte_bounds , bool data_as_commands , bool auto_refresh , uint16_t native_frames_per_second ) {
uint16_t ram_width = 0x100 ;
uint16_t ram_height = 0x100 ;
if ( single_byte_bounds ) {
ram_width = 0xff ;
ram_height = 0xff ;
}
displayio_display_core_construct ( & self - > core , bus , width , height , ram_width , ram_height , colstart , rowstart , rotation ,
color_depth , grayscale , pixels_in_byte_share_row , bytes_per_cell , reverse_pixels_in_byte ) ;
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 - > brightness_command = brightness_command ;
self - > auto_brightness = auto_brightness ;
self - > data_as_commands = data_as_commands ;
self - > single_byte_bounds = single_byte_bounds ;
if ( MP_OBJ_IS_TYPE ( bus , & displayio_parallelbus_type ) ) {
self - > begin_transaction = common_hal_displayio_parallelbus_begin_transaction ;
self - > send = common_hal_displayio_parallelbus_send ;
self - > end_transaction = common_hal_displayio_parallelbus_end_transaction ;
} else if ( MP_OBJ_IS_TYPE ( bus , & displayio_fourwire_type ) ) {
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 " ) ) ;
}
self - > bus = bus ;
self - > native_frames_per_second = native_frames_per_second ;
self - > native_frame_time = 1000 / native_frames_per_second ;
uint32_t i = 0 ;
while ( ! self - > begin_transaction ( self - > bus ) ) {
while ( ! displayio_display_core_begin_transaction ( & self - > core ) ) {
RUN_BACKGROUND_TASKS ;
}
while ( i < init_sequence_len ) {
@ -95,10 +83,10 @@ void common_hal_displayio_display_construct(displayio_display_obj_t* self,
uint8_t full_command [ data_size + 1 ] ;
full_command [ 0 ] = cmd [ 0 ] ;
memcpy ( full_command + 1 , data , data_size ) ;
self - > send ( self - > bus , true , true , full_command , data_size + 1 ) ;
self - > core . send ( self - > core . bus , true , true , full_command , data_size + 1 ) ;
} else {
self - > send ( self - > bus , true , true , cmd , 1 ) ;
self - > send ( self - > bus , false , false , data , data_size ) ;
self - > core . send ( self - > core . bus , true , true , cmd , 1 ) ;
self - > core . send ( self - > core . bus , false , false , data , data_size ) ;
}
uint16_t delay_length_ms = 10 ;
if ( delay ) {
@ -111,33 +99,10 @@ void common_hal_displayio_display_construct(displayio_display_obj_t* self,
common_hal_time_delay_ms ( delay_length_ms ) ;
i + = 2 + data_size ;
}
self - > end_transaction ( self - > bus ) ;
self - > core . end_transaction ( self - > core . bus ) ;
supervisor_start_terminal ( width , height ) ;
self - > width = width ;
self - > height = height ;
self - > rotation = rotation % 360 ;
self - > transform . x = 0 ;
self - > transform . y = 0 ;
self - > transform . scale = 1 ;
self - > transform . mirror_x = false ;
self - > transform . mirror_y = false ;
self - > transform . transpose_xy = false ;
if ( rotation = = 0 | | rotation = = 180 ) {
if ( rotation = = 180 ) {
self - > transform . mirror_x = true ;
self - > transform . mirror_y = true ;
}
} else {
self - > transform . transpose_xy = true ;
if ( rotation = = 270 ) {
self - > transform . mirror_y = true ;
} else {
self - > transform . mirror_x = true ;
}
}
// 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 ) ) {
@ -158,101 +123,98 @@ void common_hal_displayio_display_construct(displayio_display_obj_t* self,
self - > current_brightness = - 1.0 ;
}
self - > area . x1 = 0 ;
self - > area . y1 = 0 ;
self - > area . next = NULL ;
self - > transform . dx = 1 ;
self - > transform . dy = 1 ;
if ( self - > transform . transpose_xy ) {
self - > area . x2 = height ;
self - > area . y2 = width ;
if ( self - > transform . mirror_x ) {
self - > transform . x = height ;
self - > transform . dx = - 1 ;
}
if ( self - > transform . mirror_y ) {
self - > transform . y = width ;
self - > transform . dy = - 1 ;
}
} else {
self - > area . x2 = width ;
self - > area . y2 = height ;
if ( self - > transform . mirror_x ) {
self - > transform . x = width ;
self - > transform . dx = - 1 ;
}
if ( self - > transform . mirror_y ) {
self - > transform . y = height ;
self - > transform . dy = - 1 ;
}
}
// Set the group after initialization otherwise we may send pixels while we delay in
// initialization.
common_hal_displayio_display_show ( self , & circuitpython_splash ) ;
}
bool common_hal_displayio_display_show ( displayio_display_obj_t * self , displayio_group_t * root_group ) {
if ( root_group = = NULL ) {
if ( ! circuitpython_splash . in_group ) {
root_group = & circuitpython_splash ;
} else if ( self - > current_group = = & circuitpython_splash ) {
return false ;
return displayio_display_core_show ( & self - > core , root_group ) ;
}
uint16_t common_hal_displayio_display_get_width ( displayio_display_obj_t * self ) {
return displayio_display_core_get_width ( & self - > core ) ;
}
uint16_t common_hal_displayio_display_get_height ( displayio_display_obj_t * self ) {
return displayio_display_core_get_height ( & self - > core ) ;
}
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 ) {
return self - > current_brightness ;
}
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 ;
} else if ( self - > brightness_command ! = NO_BRIGHTNESS_COMMAND ) {
ok = displayio_display_core_begin_transaction ( & self - > core ) ;
if ( ok ) {
if ( self - > data_as_commands ) {
uint8_t set_brightness [ 2 ] = { self - > brightness_command , ( uint8_t ) ( 0xff * brightness ) } ;
self - > core . send ( self - > core . bus , true , true , set_brightness , 2 ) ;
} else {
uint8_t command = self - > brightness_command ;
uint8_t hex_brightness = 0xff * brightness ;
self - > core . send ( self - > core . bus , true , true , & command , 1 ) ;
self - > core . send ( self - > core . bus , false , false , & hex_brightness , 1 ) ;
}
displayio_display_core_end_transaction ( & self - > core ) ;
}
}
if ( root_group = = self - > current_group ) {
return true ;
}
if ( root_group ! = NULL & & root_group - > in_group ) {
return false ;
}
if ( self - > current_group ! = NULL ) {
self - > current_group - > in_group = false ;
self - > updating_backlight = false ;
if ( ok ) {
self - > current_brightness = brightness ;
}
return ok ;
}
if ( root_group ! = NULL ) {
displayio_group_update_transform ( root_group , & self - > transform ) ;
root_group - > in_group = true ;
}
self - > current_group = root_group ;
self - > full_refresh = true ;
common_hal_displayio_display_refresh_soon ( self ) ;
return true ;
mp_obj_t common_hal_displayio_display_get_bus ( displayio_display_obj_t * self ) {
return self - > core . bus ;
}
const displayio_area_t * displayio_display_get_refresh_areas ( displayio_display_obj_t * self ) {
if ( self - > full_refresh ) {
self - > area . next = NULL ;
return & self - > area ;
STATIC const displayio_area_t * _get_refresh_areas ( displayio_display_obj_t * self ) {
if ( self - > core . full_refresh ) {
self - > core . area . next = NULL ;
return & self - > core . area ;
} else {
if ( self - > current_group = = NULL | | self - > current_group - > base . type ! = & displayio_group_type ) {
asm ( " bkpt " ) ;
}
return displayio_group_get_refresh_areas ( self - > current_group , NULL ) ;
return displayio_group_get_refresh_areas ( self - > core . current_group , NULL ) ;
}
}
int32_t common_hal_displayio_display_wait_for_frame ( displayio_display_obj_t * self ) {
uint64_t last_refresh = self - > last_refresh ;
// Don't try to refresh if we got an exception.
while ( last_refresh = = self - > last_refresh & & MP_STATE_VM ( mp_pending_exception ) = = NULL ) {
RUN_BACKGROUND_TASKS ;
STATIC void _send_pixels ( displayio_display_obj_t * self , uint8_t * pixels , uint32_t length ) {
if ( ! self - > data_as_commands ) {
self - > core . send ( self - > core . bus , true , true , & self - > write_ram_command , 1 ) ;
}
return 0 ;
self - > core . send ( self - > core . bus , false , false , pixels , length ) ;
}
STATIC bool refresh_area( displayio_display_obj_t * display , const displayio_area_t * area ) {
STATIC bool _ refresh_area( displayio_display_obj_t * self , const displayio_area_t * area ) {
uint16_t buffer_size = 128 ; // In uint32_ts
displayio_area_t clipped ;
// Clip the area to the display by overlapping the areas. If there is no overlap then we're done.
if ( ! displayio_display_c lip_area( display , area , & clipped ) ) {
if ( ! displayio_display_c ore_clip_area( & self - > core , area , & clipped ) ) {
return true ;
}
uint16_t subrectangles = 1 ;
uint16_t rows_per_buffer = displayio_area_height ( & clipped ) ;
uint8_t pixels_per_word = ( sizeof ( uint32_t ) * 8 ) / display- > colorspace . depth ;
uint8_t pixels_per_word = ( sizeof ( uint32_t ) * 8 ) / self- > core . colorspace . depth ;
uint16_t pixels_per_buffer = displayio_area_size ( & clipped ) ;
if ( displayio_area_size ( & clipped ) > buffer_size * pixels_per_word ) {
rows_per_buffer = buffer_size * pixels_per_word / displayio_area_width ( & clipped ) ;
@ -260,8 +222,8 @@ STATIC bool refresh_area(displayio_display_obj_t* display, const displayio_area_
rows_per_buffer = 1 ;
}
// If pixels are packed by column then ensure rows_per_buffer is on a byte boundary.
if ( display- > colorspace . depth < 8 & & ! display- > colorspace . pixels_in_byte_share_row ) {
uint8_t pixels_per_byte = 8 / display- > colorspace . depth ;
if ( self- > core . colorspace . depth < 8 & & ! self- > core . colorspace . pixels_in_byte_share_row ) {
uint8_t pixels_per_byte = 8 / self- > core . colorspace . depth ;
if ( rows_per_buffer % pixels_per_byte ! = 0 ) {
rows_per_buffer - = rows_per_buffer % pixels_per_byte ;
}
@ -296,15 +258,13 @@ STATIC bool refresh_area(displayio_display_obj_t* display, const displayio_area_
}
remaining_rows - = rows_per_buffer ;
displayio_display_begin_transaction ( display ) ;
displayio_display_set_region_to_update ( display , & subrectangle ) ;
displayio_display_end_transaction ( display ) ;
displayio_display_core_set_region_to_update ( & self - > core , self - > set_column_command , self - > set_row_command , NO_COMMAND , NO_COMMAND , self - > data_as_commands , false , & subrectangle ) ;
uint16_t subrectangle_size_bytes ;
if ( display- > colorspace . depth > = 8 ) {
subrectangle_size_bytes = displayio_area_size ( & subrectangle ) * ( display- > colorspace . depth / 8 ) ;
if ( self- > core . colorspace . depth > = 8 ) {
subrectangle_size_bytes = displayio_area_size ( & subrectangle ) * ( self- > core . colorspace . depth / 8 ) ;
} else {
subrectangle_size_bytes = displayio_area_size ( & subrectangle ) / ( 8 / display- > colorspace . depth ) ;
subrectangle_size_bytes = displayio_area_size ( & subrectangle ) / ( 8 / self- > core . colorspace . depth ) ;
}
for ( uint16_t k = 0 ; k < mask_length ; k + + ) {
@ -314,14 +274,16 @@ STATIC bool refresh_area(displayio_display_obj_t* display, const displayio_area_
buffer [ k ] = 0x00000000 ;
}
displayio_display_ fill_area( display , & subrectangle , mask , buffer ) ;
displayio_display_ core_fill_area( & self - > core , & subrectangle , mask , buffer ) ;
if ( ! displayio_display_begin_transaction ( display ) ) {
// Can't acquire display bus; skip the rest of the data. Try next display.
// Can't acquire display bus; skip the rest of the data.
if ( ! displayio_display_core_bus_free ( & self - > core ) ) {
return false ;
}
displayio_display_send_pixels ( display , ( uint8_t * ) buffer , subrectangle_size_bytes ) ;
displayio_display_end_transaction ( display ) ;
displayio_display_core_begin_transaction ( & self - > core ) ;
_send_pixels ( self , ( uint8_t * ) buffer , subrectangle_size_bytes ) ;
displayio_display_core_end_transaction ( & self - > core ) ;
// TODO(tannewt): Make refresh displays faster so we don't starve other
// background tasks.
@ -330,182 +292,59 @@ STATIC bool refresh_area(displayio_display_obj_t* display, const displayio_area_
return true ;
}
STATIC void refresh_display( displayio_display_obj_t * self ) {
if ( ! displayio_display_ begin_transaction( self ) ) {
STATIC void _ refresh_display( displayio_display_obj_t * self ) {
if ( ! displayio_display_ core_bus_free( & self - > core ) ) {
// Can't acquire display bus; skip updating this display. Try next display.
continue ;
return ;
}
displayio_display_end_transaction ( self ) ;
displayio_display_start_refresh ( self ) ;
const displayio_area_t * current_area = displayio_display_get_refresh_areas ( self ) ;
displayio_display_core_start_refresh ( & self - > core ) ;
const displayio_area_t * current_area = _get_refresh_areas ( self ) ;
while ( current_area ! = NULL ) {
refresh_area( self , current_area ) ;
_ refresh_area( self , current_area ) ;
current_area = current_area - > next ;
}
displayio_display_finish_refresh ( self ) ;
}
void common_hal_displayio_display_refresh ( displayio_display_obj_t * self ) {
// Time to refresh at specified frame rate?
while ( ! displayio_display_frame_queued ( self ) ) {
// Too soon. Try next display.
continue ;
}
refresh_display ( self ) ;
}
bool common_hal_displayio_display_get_auto_brightness ( displayio_display_obj_t * self ) {
return self - > auto_brightness ;
}
uint16_t common_hal_displayio_display_get_width ( displayio_display_obj_t * self ) {
return self - > width ;
}
uint16_t common_hal_displayio_display_get_height ( displayio_display_obj_t * self ) {
return self - > height ;
displayio_display_core_finish_refresh ( & self - > core ) ;
}
uint16_t common_hal_displayio_display_get_rotation ( displayio_display_obj_t * self ) {
return self - > rotation ;
}
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 ) {
return self - > current_brightness ;
return self - > core . rotation ;
}
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 ;
} else if ( self - > brightness_command ! = NO_BRIGHTNESS_COMMAND ) {
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 , true , set_brightness , 2 ) ;
} else {
uint8_t command = self - > brightness_command ;
uint8_t hex_brightness = 0xff * brightness ;
self - > send ( self - > bus , true , true , & command , 1 ) ;
self - > send ( self - > bus , false , false , & hex_brightness , 1 ) ;
}
self - > end_transaction ( self - > bus ) ;
void common_hal_displayio_display_refresh ( displayio_display_obj_t * self , uint32_t target_frame_time , uint32_t maximum_frame_time ) {
if ( ! self - > auto_refresh ) {
uint64_t current_time = ticks_ms ;
uint32_t current_frame_time = current_time - self - > core . last_refresh ;
// Test to see if the real frame time is below our minimum.
if ( current_frame_time > maximum_frame_time ) {
mp_raise_RuntimeError ( translate ( " Below minimum frame rate " ) ) ;
}
}
self - > updating_backlight = false ;
if ( ok ) {
self - > current_brightness = brightness ;
}
return ok ;
}
bool displayio_display_begin_transaction ( displayio_display_obj_t * self ) {
return self - > begin_transaction ( self - > bus ) ;
}
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 , 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 * self - > colorspace . bytes_per_cell ;
x2 / = pixels_per_byte * self - > colorspace . bytes_per_cell ;
} else {
y1 / = pixels_per_byte * self - > colorspace . bytes_per_cell ;
y2 / = pixels_per_byte * self - > colorspace . bytes_per_cell ;
uint32_t current_call_time = current_time - self - > last_refresh_call ;
self - > last_refresh_call = current_time ;
// Skip the actual refresh to help catch up.
if ( current_call_time > target_frame_time ) {
return ;
}
uint32_t remaining_time = target_frame_time - ( current_frame_time % target_frame_time ) ;
// We're ahead of the game so wait until we align with the frame rate.
while ( ticks_ms - self - > last_refresh_call < remaining_time ) {
# ifdef MICROPY_VM_HOOK_LOOP
MICROPY_VM_HOOK_LOOP ;
# endif
}
}
// 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 , true , data , 1 ) ;
data_length = 0 ;
}
if ( self - > single_byte_bounds ) {
data [ data_length + + ] = x1 + self - > colstart ;
data [ data_length + + ] = x2 - 1 + self - > colstart ;
} else {
x1 + = self - > colstart ;
x2 + = self - > colstart - 1 ;
data [ data_length + + ] = x1 > > 8 ;
data [ data_length + + ] = x1 & 0xff ;
data [ data_length + + ] = x2 > > 8 ;
data [ data_length + + ] = x2 & 0xff ;
}
self - > send ( self - > bus , self - > data_as_commands , 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 , true , data , 1 ) ;
data_length = 0 ;
}
if ( self - > single_byte_bounds ) {
data [ data_length + + ] = y1 + self - > rowstart ;
data [ data_length + + ] = y2 - 1 + self - > rowstart ;
} else {
y1 + = self - > rowstart ;
y2 + = self - > rowstart - 1 ;
data [ data_length + + ] = y1 > > 8 ;
data [ data_length + + ] = y1 & 0xff ;
data [ data_length + + ] = y2 > > 8 ;
data [ data_length + + ] = y2 & 0xff ;
}
self - > send ( self - > bus , self - > data_as_commands , self - > data_as_commands , data , data_length ) ;
}
void displayio_display_start_refresh ( displayio_display_obj_t * self ) {
self - > last_refresh = ticks_ms ;
}
bool displayio_display_frame_queued ( displayio_display_obj_t * self ) {
if ( self - > current_group = = NULL ) {
return false ;
}
// Refresh at ~60 fps.
return ( ticks_ms - self - > last_refresh ) > 16 ;
_refresh_display ( self ) ;
}
void displayio_display_finish_refresh ( displayio_display_obj_t * self ) {
if ( self - > current_group ! = NULL ) {
displayio_group_finish_refresh ( self - > current_group ) ;
}
self - > refresh = false ;
self - > full_refresh = false ;
self - > last_refresh = ticks_ms ;
bool common_hal_displayio_display_get_auto_refresh ( displayio_display_obj_t * self ) {
return self - > auto_refresh ;
}
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 , true , & self - > write_ram_command , 1 ) ;
}
self - > send ( self - > bus , false , false , pixels , length ) ;
void common_hal_displayio_display_set_auto_refresh ( displayio_display_obj_t * self ,
bool auto_refresh ) {
self - > auto_refresh = auto_refresh ;
}
void displayio_display _update_backlight( displayio_display_obj_t * self ) {
STATIC void _update_backlight ( displayio_display_obj_t * self ) {
if ( ! self - > auto_brightness | | self - > updating_backlight ) {
return ;
}
@ -520,17 +359,15 @@ void displayio_display_update_backlight(displayio_display_obj_t* self) {
}
void displayio_display_background ( displayio_display_obj_t * self ) {
displayio_display _update_backlight( self ) ;
_update_backlight( self ) ;
if ( self - > auto_refresh & & ( ticks_ms - self - > last_refresh) > 16 ) {
display _refresh( self ) ;
if ( self - > auto_refresh & & ( ticks_ms - self - > core. last_refresh ) > self - > native_frame_time ) {
_refresh_display ( self ) ;
}
}
void release_display ( displayio_display_obj_t * self ) {
if ( self - > current_group ! = NULL ) {
self - > current_group - > in_group = false ;
}
release_display_core ( & self - > core ) ;
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 ) ;
@ -539,34 +376,6 @@ 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 , & self - > colorspace , area , mask , buffer ) ;
}
bool displayio_display_clip_area ( displayio_display_obj_t * self , const displayio_area_t * area , displayio_area_t * 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 * self - > colorspace . bytes_per_cell ;
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 ;
void displayio_display_collect_ptrs ( displayio_display_obj_t * self ) {
displayio_display_core_collect_ptrs ( & self - > core ) ;
}