@@ -135,10 +135,23 @@ const uint8_t ssd1680_display_refresh_sequence[] = {
135135 0x20 , 0x00 , 0x00
136136};
137137
138- static bool detect_ssd1680 (void ) {
139- // Bitbang 4-wire SPI with a bidirectional data line to read register 0x71.
140- // On the IL0373 it will return 0x13 or similar. On the SSD1680 it is
141- // unsupported and will be 0xff.
138+
139+ typedef enum {
140+ DISPLAY_IL0373 ,
141+ DISPLAY_SSD1680_COLSTART_0 ,
142+ DISPLAY_SSD1680_COLSTART_8 ,
143+ } display_type_t ;
144+
145+ static display_type_t detect_display_type (void ) {
146+ // Bitbang 4-wire SPI with a bidirectional data line to read the first word of register 0x2e,
147+ // which is the 10-byte USER ID.
148+ // On the IL0373 it will return 0xff because it's not a valid register.
149+ // With SSD1680, we have seen two types:
150+ // 1. The first batch of displays, labeled "FPC-A005 20.06.15 TRX", which needs colstart=0.
151+ // These have 10 byes of zeros in the User ID
152+ // 2. Second batch, labeled "FPC-7619rev.b", which needs colstart=8.
153+ // The USER ID for these boards is [0x44, 0x0, 0x4, 0x0, 0x25, 0x0, 0x1, 0x78, 0x2b, 0xe]
154+ // So let's distinguish just by the first byte.
142155 digitalio_digitalinout_obj_t data ;
143156 digitalio_digitalinout_obj_t clock ;
144157 digitalio_digitalinout_obj_t chip_select ;
@@ -163,7 +176,7 @@ static bool detect_ssd1680(void) {
163176 common_hal_digitalio_digitalinout_switch_to_output (& reset , true, DRIVE_MODE_PUSH_PULL );
164177 common_hal_digitalio_digitalinout_switch_to_output (& clock , false, DRIVE_MODE_PUSH_PULL );
165178
166- uint8_t status_read = 0x71 ;
179+ uint8_t status_read = 0x2e ; // SSD1680 User ID register. Not a valid register on IL0373.
167180 for (int i = 0 ; i < 8 ; i ++ ) {
168181 common_hal_digitalio_digitalinout_set_value (& data , (status_read & (1 << (7 - i ))) != 0 );
169182 common_hal_digitalio_digitalinout_set_value (& clock , true);
@@ -192,11 +205,20 @@ static bool detect_ssd1680(void) {
192205 common_hal_digitalio_digitalinout_deinit (& chip_select );
193206 common_hal_digitalio_digitalinout_deinit (& data_command );
194207 common_hal_digitalio_digitalinout_deinit (& reset );
195- return status == 0xff ;
208+
209+ switch (status ) {
210+ case 0xff :
211+ return DISPLAY_IL0373 ;
212+ default : // who knows? Just guess.
213+ case 0x00 :
214+ return DISPLAY_SSD1680_COLSTART_0 ;
215+ case 0x44 :
216+ return DISPLAY_SSD1680_COLSTART_8 ;
217+ }
196218}
197219
198220void board_init (void ) {
199- bool is_ssd1680 = detect_ssd1680 ();
221+ display_type_t display_type = detect_display_type ();
200222
201223 fourwire_fourwire_obj_t * bus = & allocate_display_bus ()-> fourwire_bus ;
202224 busio_spi_obj_t * spi = & bus -> inline_bus ;
@@ -216,8 +238,33 @@ void board_init(void) {
216238 epaperdisplay_epaperdisplay_obj_t * display = & allocate_display ()-> epaper_display ;
217239 display -> base .type = & epaperdisplay_epaperdisplay_type ;
218240
219- if (is_ssd1680 ) {
241+ if (display_type == DISPLAY_IL0373 ) {
242+ epaperdisplay_construct_args_t args = EPAPERDISPLAY_CONSTRUCT_ARGS_DEFAULTS ;
243+ args .bus = bus ;
244+ args .start_sequence = il0373_display_start_sequence ;
245+ args .start_sequence_len = sizeof (il0373_display_start_sequence );
246+ args .stop_sequence = il0373_display_stop_sequence ;
247+ args .stop_sequence_len = sizeof (il0373_display_stop_sequence );
248+ args .width = 296 ;
249+ args .height = 128 ;
250+ args .ram_width = 160 ;
251+ args .ram_height = 296 ;
252+ args .rotation = 270 ;
253+ args .write_black_ram_command = 0x10 ;
254+ args .write_color_ram_command = 0x13 ;
255+ args .refresh_sequence = il0373_display_refresh_sequence ;
256+ args .refresh_sequence_len = sizeof (il0373_display_refresh_sequence );
257+ args .refresh_time = 1.0 ;
258+ args .busy_pin = & pin_GPIO5 ;
259+ args .seconds_per_frame = 5.0 ;
260+ args .grayscale = true;
261+ common_hal_epaperdisplay_epaperdisplay_construct (display , & args );
262+ } else {
220263 epaperdisplay_construct_args_t args = EPAPERDISPLAY_CONSTRUCT_ARGS_DEFAULTS ;
264+ // Default colstart is 0.
265+ if (display_type == DISPLAY_SSD1680_COLSTART_8 ) {
266+ args .colstart = 8 ;
267+ }
221268 args .bus = bus ;
222269 args .start_sequence = ssd1680_display_start_sequence ;
223270 args .start_sequence_len = sizeof (ssd1680_display_start_sequence );
@@ -244,27 +291,6 @@ void board_init(void) {
244291 args .two_byte_sequence_length = true;
245292 args .address_little_endian = true;
246293 common_hal_epaperdisplay_epaperdisplay_construct (display , & args );
247- } else {
248- epaperdisplay_construct_args_t args = EPAPERDISPLAY_CONSTRUCT_ARGS_DEFAULTS ;
249- args .bus = bus ;
250- args .start_sequence = il0373_display_start_sequence ;
251- args .start_sequence_len = sizeof (il0373_display_start_sequence );
252- args .stop_sequence = il0373_display_stop_sequence ;
253- args .stop_sequence_len = sizeof (il0373_display_stop_sequence );
254- args .width = 296 ;
255- args .height = 128 ;
256- args .ram_width = 160 ;
257- args .ram_height = 296 ;
258- args .rotation = 270 ;
259- args .write_black_ram_command = 0x10 ;
260- args .write_color_ram_command = 0x13 ;
261- args .refresh_sequence = il0373_display_refresh_sequence ;
262- args .refresh_sequence_len = sizeof (il0373_display_refresh_sequence );
263- args .refresh_time = 1.0 ;
264- args .busy_pin = & pin_GPIO5 ;
265- args .seconds_per_frame = 5.0 ;
266- args .grayscale = true;
267- common_hal_epaperdisplay_epaperdisplay_construct (display , & args );
268294 }
269295}
270296
0 commit comments