Skip to content

Commit 857c625

Browse files
authored
Merge pull request #10505 from tannewt/magtag2025
Autodetect new MagTag displays
2 parents 3512e66 + f4316cb commit 857c625

File tree

1 file changed

+177
-36
lines changed
  • ports/espressif/boards/adafruit_magtag_2.9_grayscale

1 file changed

+177
-36
lines changed

ports/espressif/boards/adafruit_magtag_2.9_grayscale/board.c

Lines changed: 177 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ static const char *TAG = "board";
2121

2222
// This is an ILO373 control chip. The display is a 2.9" grayscale EInk.
2323

24-
const uint8_t display_start_sequence[] = {
24+
const uint8_t il0373_display_start_sequence[] = {
2525
0x01, 5, 0x03, 0x00, 0x2b, 0x2b, 0x13, // power setting
2626
0x06, 3, 0x17, 0x17, 0x17, // booster soft start
2727
0x04, DELAY, 200, // power on and wait 200 ms
@@ -83,17 +83,121 @@ const uint8_t display_start_sequence[] = {
8383
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
8484
};
8585

86-
const uint8_t display_stop_sequence[] = {
86+
const uint8_t il0373_display_stop_sequence[] = {
8787
0x50, 0x01, 0x17, // CDI Setting
8888
0x82, 0x01, 0x00, // VCM DC to -0.1V
8989
0x02, 0x00 // Power off
9090
};
9191

92-
const uint8_t refresh_sequence[] = {
92+
const uint8_t il0373_display_refresh_sequence[] = {
9393
0x12, 0x00
9494
};
9595

96+
97+
// This is an SSD1680 control chip. The display is a 2.9" grayscale EInk.
98+
const uint8_t ssd1680_display_start_sequence[] = {
99+
0x12, DELAY, 0x00, 0x14, // soft reset and wait 20ms
100+
0x11, 0x00, 0x01, 0x03, // Ram data entry mode
101+
0x3c, 0x00, 0x01, 0x03, // border color
102+
0x2c, 0x00, 0x01, 0x28, // Set vcom voltage
103+
0x03, 0x00, 0x01, 0x17, // Set gate voltage
104+
0x04, 0x00, 0x03, 0x41, 0xae, 0x32, // Set source voltage
105+
0x4e, 0x00, 0x01, 0x01, // ram x count
106+
0x4f, 0x00, 0x02, 0x00, 0x00, // ram y count
107+
0x01, 0x00, 0x03, 0x27, 0x01, 0x00, // set display size
108+
0x32, 0x00, 0x99, // Update waveforms
109+
0x2a, 0x60, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // VS L0
110+
0x20, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // VS L1
111+
0x28, 0x60, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // VS L2
112+
0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // VS L3
113+
0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // VS L4
114+
0x00, 0x02, 0x00, 0x05, 0x14, 0x00, 0x00, // TP, SR, RP of Group0
115+
0x1E, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x01, // TP, SR, RP of Group1
116+
0x00, 0x02, 0x00, 0x05, 0x14, 0x00, 0x00, // TP, SR, RP of Group2
117+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // TP, SR, RP of Group3
118+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // TP, SR, RP of Group4
119+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // TP, SR, RP of Group5
120+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // TP, SR, RP of Group6
121+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // TP, SR, RP of Group7
122+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // TP, SR, RP of Group8
123+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // TP, SR, RP of Group9
124+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // TP, SR, RP of Group10
125+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // TP, SR, RP of Group11
126+
0x24, 0x22, 0x22, 0x22, 0x23, 0x32, 0x00, 0x00, 0x00, // FR, XON
127+
0x22, 0x00, 0x01, 0xc7 // display update mode
128+
};
129+
130+
const uint8_t ssd1680_display_stop_sequence[] = {
131+
0x10, DELAY, 0x01, 0x01, 0x64
132+
};
133+
134+
const uint8_t ssd1680_display_refresh_sequence[] = {
135+
0x20, 0x00, 0x00
136+
};
137+
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.
142+
digitalio_digitalinout_obj_t data;
143+
digitalio_digitalinout_obj_t clock;
144+
digitalio_digitalinout_obj_t chip_select;
145+
digitalio_digitalinout_obj_t data_command;
146+
digitalio_digitalinout_obj_t reset;
147+
data.base.type = &digitalio_digitalinout_type;
148+
clock.base.type = &digitalio_digitalinout_type;
149+
chip_select.base.type = &digitalio_digitalinout_type;
150+
data_command.base.type = &digitalio_digitalinout_type;
151+
reset.base.type = &digitalio_digitalinout_type;
152+
153+
common_hal_digitalio_digitalinout_construct(&data, &pin_GPIO35);
154+
common_hal_digitalio_digitalinout_construct(&clock, &pin_GPIO36);
155+
common_hal_digitalio_digitalinout_construct(&chip_select, &pin_GPIO8);
156+
common_hal_digitalio_digitalinout_construct(&data_command, &pin_GPIO7);
157+
common_hal_digitalio_digitalinout_construct(&reset, &pin_GPIO6);
158+
159+
// Set CS and DC low
160+
common_hal_digitalio_digitalinout_switch_to_output(&chip_select, false, DRIVE_MODE_PUSH_PULL);
161+
common_hal_digitalio_digitalinout_switch_to_output(&data_command, false, DRIVE_MODE_PUSH_PULL);
162+
common_hal_digitalio_digitalinout_switch_to_output(&data, false, DRIVE_MODE_PUSH_PULL);
163+
common_hal_digitalio_digitalinout_switch_to_output(&reset, true, DRIVE_MODE_PUSH_PULL);
164+
common_hal_digitalio_digitalinout_switch_to_output(&clock, false, DRIVE_MODE_PUSH_PULL);
165+
166+
uint8_t status_read = 0x71;
167+
for (int i = 0; i < 8; i++) {
168+
common_hal_digitalio_digitalinout_set_value(&data, (status_read & (1 << (7 - i))) != 0);
169+
common_hal_digitalio_digitalinout_set_value(&clock, true);
170+
common_hal_digitalio_digitalinout_set_value(&clock, false);
171+
}
172+
173+
// Set DC high for data and switch to input with pull-up in case the SSD1680 doesn't send any
174+
// data back (as it should.)
175+
common_hal_digitalio_digitalinout_switch_to_input(&data, PULL_UP);
176+
common_hal_digitalio_digitalinout_set_value(&data_command, true);
177+
uint8_t status = 0;
178+
for (int bit = 0; bit < 8; bit++) {
179+
status <<= 1;
180+
if (common_hal_digitalio_digitalinout_get_value(&data)) {
181+
status |= 1;
182+
}
183+
common_hal_digitalio_digitalinout_set_value(&clock, true);
184+
common_hal_digitalio_digitalinout_set_value(&clock, false);
185+
}
186+
187+
// Set CS high
188+
common_hal_digitalio_digitalinout_set_value(&chip_select, true);
189+
190+
common_hal_digitalio_digitalinout_deinit(&data);
191+
common_hal_digitalio_digitalinout_deinit(&clock);
192+
common_hal_digitalio_digitalinout_deinit(&chip_select);
193+
common_hal_digitalio_digitalinout_deinit(&data_command);
194+
common_hal_digitalio_digitalinout_deinit(&reset);
195+
return status == 0xff;
196+
}
197+
96198
void board_init(void) {
199+
bool is_ssd1680 = detect_ssd1680();
200+
97201
fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus;
98202
busio_spi_obj_t *spi = &bus->inline_bus;
99203
common_hal_busio_spi_construct(spi, &pin_GPIO36, &pin_GPIO35, NULL, false);
@@ -111,39 +215,76 @@ void board_init(void) {
111215

112216
epaperdisplay_epaperdisplay_obj_t *display = &allocate_display()->epaper_display;
113217
display->base.type = &epaperdisplay_epaperdisplay_type;
114-
common_hal_epaperdisplay_epaperdisplay_construct(
115-
display,
116-
bus,
117-
display_start_sequence, sizeof(display_start_sequence),
118-
0, // start up time
119-
display_stop_sequence, sizeof(display_stop_sequence),
120-
296, // width
121-
128, // height
122-
160, // ram_width
123-
296, // ram_height
124-
0, // colstart
125-
0, // rowstart
126-
270, // rotation
127-
NO_COMMAND, // set_column_window_command
128-
NO_COMMAND, // set_row_window_command
129-
NO_COMMAND, // set_current_column_command
130-
NO_COMMAND, // set_current_row_command
131-
0x10, // write_black_ram_command
132-
false, // black_bits_inverted
133-
0x13, // write_color_ram_command
134-
false, // color_bits_inverted
135-
0x000000, // highlight_color
136-
refresh_sequence, sizeof(refresh_sequence),
137-
1.0, // refresh_time
138-
&pin_GPIO5, // busy_pin
139-
false, // busy_state
140-
5.0, // seconds_per_frame
141-
false, // always_toggle_chip_select
142-
true, // grayscale
143-
false, // acep
144-
false, // spectra6
145-
false, // two_byte_sequence_length
146-
false); // address_little_endian
218+
219+
if (is_ssd1680) {
220+
common_hal_epaperdisplay_epaperdisplay_construct(
221+
display,
222+
bus,
223+
ssd1680_display_start_sequence, sizeof(ssd1680_display_start_sequence),
224+
0, // start up time
225+
ssd1680_display_stop_sequence, sizeof(ssd1680_display_stop_sequence),
226+
296, // width
227+
128, // height
228+
250, // ram_width
229+
296, // ram_height
230+
0, // colstart
231+
0, // rowstart
232+
270, // rotation
233+
0x44, // set_column_window_command
234+
0x45, // set_row_window_command
235+
0x4e, // set_current_column_command
236+
0x4f, // set_current_row_command
237+
0x24, // write_black_ram_command
238+
false, // black_bits_inverted
239+
0x26, // write_color_ram_command
240+
false, // color_bits_inverted
241+
0x000000, // highlight_color
242+
ssd1680_display_refresh_sequence, sizeof(ssd1680_display_refresh_sequence),
243+
1.0, // refresh_time
244+
&pin_GPIO5, // busy_pin
245+
true, // busy_state
246+
5.0, // seconds_per_frame
247+
false, // always_toggle_chip_select
248+
true, // grayscale
249+
false, // acep
250+
false, // spectra6
251+
true, // two_byte_sequence_length
252+
true); // address_little_endian
253+
} else {
254+
common_hal_epaperdisplay_epaperdisplay_construct(
255+
display,
256+
bus,
257+
il0373_display_start_sequence, sizeof(il0373_display_start_sequence),
258+
0, // start up time
259+
il0373_display_stop_sequence, sizeof(il0373_display_stop_sequence),
260+
296, // width
261+
128, // height
262+
160, // ram_width
263+
296, // ram_height
264+
0, // colstart
265+
0, // rowstart
266+
270, // rotation
267+
NO_COMMAND, // set_column_window_command
268+
NO_COMMAND, // set_row_window_command
269+
NO_COMMAND, // set_current_column_command
270+
NO_COMMAND, // set_current_row_command
271+
0x10, // write_black_ram_command
272+
false, // black_bits_inverted
273+
0x13, // write_color_ram_command
274+
false, // color_bits_inverted
275+
0x000000, // highlight_color
276+
il0373_display_refresh_sequence, sizeof(il0373_display_refresh_sequence),
277+
1.0, // refresh_time
278+
&pin_GPIO5, // busy_pin
279+
false, // busy_state
280+
5.0, // seconds_per_frame
281+
false, // always_toggle_chip_select
282+
true, // grayscale
283+
false, // acep
284+
false, // spectra6
285+
false, // two_byte_sequence_length
286+
false); // address_little_endian
287+
}
147288
}
148289

149290
bool espressif_board_reset_pin_number(gpio_num_t pin_number) {

0 commit comments

Comments
 (0)