Skip to content

Commit f8c2fa6

Browse files
committed
split up and filter
1 parent 829b9e5 commit f8c2fa6

3 files changed

Lines changed: 366 additions & 203 deletions

File tree

Lines changed: 88 additions & 166 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/**
22
* Marlin 3D Printer Firmware
3-
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
3+
* Copyright (c) 2023 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
44
*
55
* Based on Sprinter and grbl.
66
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
@@ -54,40 +54,90 @@
5454
*/
5555

5656
/**
57-
* These routines are meant for two wire I2C interfaces.
57+
* For two wire I2C interfaces.
5858
*
59-
* Three and four wire I2C interfaces have an A0 line. That line is
59+
* Three and four wire I2C interfaces have an A0 line. That line is
6060
* used to switch between command and data modes.
6161
*
6262
* The two wire LCDs use an instruction byte to signal if data or
63-
* command info is to follow. The command stream needs the instruction
64-
* byte between eack command byte. The data stream needs one at the
63+
* command info is to follow. The command stream needs the instruction
64+
* byte between eack command byte. The data stream needs one at the
6565
* beginning.
6666
*/
6767

6868
#include "../../inc/MarlinConfigPre.h"
6969

70-
#if HAS_MARLINUI_U8GLIB
70+
#if ENABLED(U8GLIB_SH1106)
7171

7272
#include "HAL_LCD_com_defines.h"
7373

7474
#define WIDTH 128
7575
#define HEIGHT 64
7676
#define PAGE_HEIGHT 8
7777

78-
uint8_t u8g_WriteEscSeqP_2_wire(u8g_t *u8g, u8g_dev_t *dev, const uint8_t *esc_seq);
78+
// This routine adds the instruction byte in between the command bytes. This makes the init
79+
// sequences a lot easier to read.
7980

80-
// The sh1106 is compatible to the ssd1306, but is 132x64. 128x64 display area is centered within
81-
// the 132x64.
81+
#define I2C_CMD_MODE 0x80
8282

83-
static const uint8_t u8g_dev_sh1106_128x64_data_start_2_wire[] PROGMEM = {
84-
0x010, // set upper 4 bit of the col adr to 0
85-
0x002, // set lower 4 bit of the col adr to 2 (centered display with ssd1306)
86-
U8G_ESC_END // end of sequence
87-
};
83+
uint8_t u8g_WriteEscSeqP_2_wire(u8g_t *u8g, u8g_dev_t *dev, const uint8_t *esc_seq) {
84+
bool is_escape = false;
85+
for (;;) {
86+
uint8_t value = u8g_pgm_read(esc_seq);
87+
if (!is_escape) {
88+
if (value != 255) {
89+
if (u8g_WriteByte(u8g, dev, value) == 0) return 0;
90+
if (u8g_WriteByte(u8g, dev, I2C_CMD_MODE) == 0) return 0;
91+
}
92+
else {
93+
is_escape = true;
94+
}
95+
}
96+
else {
97+
if (value == 255) {
98+
if (u8g_WriteByte(u8g, dev, value) == 0) return 0;
99+
if (u8g_WriteByte(u8g, dev, I2C_CMD_MODE) == 0) return 0;
100+
}
101+
else if (value == 254) {
102+
break;
103+
}
104+
else if (value >= 0xF0) {
105+
// not yet used, do nothing
106+
}
107+
else if (value >= 0xE0 ) {
108+
u8g_SetAddress(u8g, dev, value & 0x0F);
109+
}
110+
else if (value >= 0xD0) {
111+
u8g_SetChipSelect(u8g, dev, value & 0x0F);
112+
}
113+
else if (value >= 0xC0) {
114+
u8g_SetResetLow(u8g, dev);
115+
value &= 0x0F;
116+
value <<= 4;
117+
value+=2;
118+
u8g_Delay(value);
119+
u8g_SetResetHigh(u8g, dev);
120+
u8g_Delay(value);
121+
}
122+
else if (value >= 0xBE) { // not yet implemented
123+
//u8g_SetVCC(u8g, dev, value & 0x01);
124+
}
125+
else if (value <= 127) {
126+
u8g_Delay(value);
127+
}
128+
is_escape = false;
129+
}
130+
esc_seq++;
131+
}
132+
return 1;
133+
}
88134

135+
// SH1106 is compatible with SSD1306, but is 132x64, so the 128x64 display area
136+
// is centered within the 132x64.
137+
138+
#define SH1106_COL_ADR(N) (0x10 | ((N)>>4)), ((N) & 0x0F)
89139
#define SH1106_PAGE_ADR(N) (0x20), (N)
90-
#define SH1106_COLUMN_RANGE(N) (0x21), (((N) >> 8) & 0xFF), ((N) & 0xFF)
140+
#define SH1106_COLUMN_RANGE(N,O) (0x21), (N), (O)
91141
#define SH1106_PAGE_RANGE(N,O) (0x22), (N), (O)
92142
#define SH1106_SCROLL(N) ((N) ? 0x2F : 0x2E)
93143
#define SH1106_START_LINE(N) (0x40 | (N))
@@ -104,7 +154,12 @@ static const uint8_t u8g_dev_sh1106_128x64_data_start_2_wire[] PROGMEM = {
104154
#define SH1106_CHARGE_PER(P,D) (0xD9), ((D) << 4 | (P))
105155
#define SH1106_COM_CONFIG(N) (0xDA), ((N) ? 0x12 : 0x02)
106156
#define SH1106_VCOM_DESEL(N) (0xDB), (N)
107-
#define SH1106_NOOP() (0xE3)
157+
#define SH1106_NOP() (0xE3)
158+
159+
static const uint8_t u8g_dev_sh1106_128x64_data_start_2_wire[] PROGMEM = {
160+
SH1106_COL_ADR(2), // Start at column 2
161+
U8G_ESC_END // End of sequence
162+
};
108163

109164
static const uint8_t u8g_dev_sh1106_128x64_init_seq_2_wire[] PROGMEM = {
110165
U8G_ESC_ADR(0), // Initiate command mode
@@ -115,17 +170,17 @@ static const uint8_t u8g_dev_sh1106_128x64_init_seq_2_wire[] PROGMEM = {
115170
SH1106_ADC_REVERSE(1), // Segment remap A0/A1
116171
SH1106_OUT_MODE(1), // C0: scan dir normal, C8: reverse
117172
SH1106_COM_CONFIG(1), // Com pin HW config, sequential com pin config (bit 4), disable left/right remap (bit 5)
118-
SH1106_CONTRAST(0xCF), // [2] set contrast control
119-
SH1106_PAGE_ADR(0x02), // 2012-05-27: page addressing mode
120-
SH1106_COLUMN_RANGE(0x281), // Set column range from 0 through 131
173+
SH1106_CONTRAST(0xCF), // [2] Set contrast control
174+
SH1106_PAGE_ADR(0x02), // Page addressing mode
175+
SH1106_COLUMN_RANGE(2, 129), // Set column range from 2 through 129
121176
SH1106_PAGE_RANGE(0, 7), // Set page range from 0 through 7
122-
SH1106_CHARGE_PER(0x1, 0xF), // [2] pre-charge period 0x22/F1
177+
SH1106_CHARGE_PER(0x1, 0xF), // [2] Pre-charge period 0x22/F1
123178
SH1106_VCOM_DESEL(0x40), // Vcomh deselect level
124-
SH1106_ALL_PIX(0), // Output ram to display
179+
SH1106_ALL_PIX(0), // Output RAM to display
125180
SH1106_INVERTED(0), // Normal display mode
126181
SH1106_OSC_FREQ(0, 8), // Clock divide ratio (0:1) and oscillator frequency (8)
127-
SH1106_CHARGE_PUMP(1), // [2] charge pump setting (P62): 0x14 enable, 0x10 disable
128-
SH1106_SCROLL(0), // 2012-05-27: Deactivate scroll
182+
SH1106_CHARGE_PUMP(1), // [2] Charge pump setting (P62): 0x14 enable, 0x10 disable
183+
SH1106_SCROLL(0), // Deactivate scroll
129184
SH1106_ON(1), // Display on
130185
U8G_ESC_END // End of sequence
131186
};
@@ -140,16 +195,16 @@ uint8_t u8g_dev_sh1106_128x64_2x_2_wire_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t m
140195
break;
141196
case U8G_DEV_MSG_PAGE_NEXT: {
142197
u8g_pb_t *pb = (u8g_pb_t *)(dev->dev_mem);
143-
u8g_SetAddress(u8g, dev, 0); // instruction mode
198+
u8g_SetAddress(u8g, dev, 0); // Instruction mode
144199
u8g_WriteEscSeqP_2_wire(u8g, dev, u8g_dev_sh1106_128x64_data_start_2_wire);
145-
u8g_WriteByte(u8g, dev, 0x0B0 | (pb->p.page*2)); // select current page
146-
u8g_SetAddress(u8g, dev, 1); // data mode
147-
u8g_WriteSequence(u8g, dev, pb->width, (uint8_t *) pb->buf);
200+
u8g_WriteByte(u8g, dev, 0xB0 | (pb->p.page*2)); // Select current page
201+
u8g_SetAddress(u8g, dev, 1); // Data mode
202+
u8g_WriteSequence(u8g, dev, pb->width, (uint8_t *)pb->buf);
148203
u8g_SetChipSelect(u8g, dev, 0);
149-
u8g_SetAddress(u8g, dev, 0); // instruction mode
204+
u8g_SetAddress(u8g, dev, 0); // Instruction mode
150205
u8g_WriteEscSeqP_2_wire(u8g, dev, u8g_dev_sh1106_128x64_data_start_2_wire);
151-
u8g_WriteByte(u8g, dev, 0x0B0 | (pb->p.page*2+1)); // select current page
152-
u8g_SetAddress(u8g, dev, 1); // data mode
206+
u8g_WriteByte(u8g, dev, 0xB0 | (pb->p.page*2+1)); // Select current page
207+
u8g_SetAddress(u8g, dev, 1); // Data mode
153208
u8g_WriteSequence(u8g, dev, pb->width, (uint8_t *)(pb->buf)+pb->width);
154209
u8g_SetChipSelect(u8g, dev, 0);
155210
}
@@ -162,141 +217,8 @@ uint8_t u8g_dev_sh1106_128x64_2x_2_wire_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t m
162217
return u8g_dev_pb16v1_base_fn(u8g, dev, msg, arg);
163218
}
164219

165-
uint8_t u8g_dev_sh1106_128x64_2x_i2c_2_wire_buf[WIDTH*2] U8G_NOCOMMON ;
166-
u8g_pb_t u8g_dev_sh1106_128x64_2x_i2c_2_wire_pb = { {16, HEIGHT, 0, 0, 0}, WIDTH, u8g_dev_sh1106_128x64_2x_i2c_2_wire_buf};
220+
uint8_t u8g_dev_sh1106_128x64_2x_i2c_2_wire_buf[WIDTH * 2] U8G_NOCOMMON;
221+
u8g_pb_t u8g_dev_sh1106_128x64_2x_i2c_2_wire_pb = { { 16, HEIGHT, 0, 0, 0 }, WIDTH, u8g_dev_sh1106_128x64_2x_i2c_2_wire_buf };
167222
u8g_dev_t u8g_dev_sh1106_128x64_2x_i2c_2_wire = { u8g_dev_sh1106_128x64_2x_2_wire_fn, &u8g_dev_sh1106_128x64_2x_i2c_2_wire_pb, U8G_COM_SSD_I2C_HAL };
168223

169-
/////////////////////////////////////////////////////////////////////////////////////////////
170-
171-
static const uint8_t u8g_dev_ssd1306_128x64_data_start_2_wire[] PROGMEM = {
172-
0x010, // set upper 4 bit of the col adr to 0
173-
0x000, // set lower 4 bit of the col adr to 0
174-
U8G_ESC_END // end of sequence
175-
};
176-
177-
static const uint8_t u8g_dev_ssd1306_128x64_init_seq_2_wire[] PROGMEM = {
178-
U8G_ESC_ADR(0), // initiate command mode
179-
0x0AE, // display off, sleep mode
180-
0x0A8, 0x03F, // mux ratio
181-
0x0D3, 0x00, // display offset
182-
0x040, // start line
183-
0x0A1, // segment remap a0/a1
184-
0x0C8, // c0: scan dir normal, c8: reverse
185-
0x0DA, 0x012, // com pin HW config, sequential com pin config (bit 4), disable left/right remap (bit 5)
186-
0x081, 0x0CF, // [2] set contrast control
187-
0x020, 0x002, // 2012-05-27: page addressing mode
188-
0x21, 0, 0x7F, // set column range from 0 through 127
189-
0x22, 0, 7, // set page range from 0 through 7
190-
0x0D9, 0x0F1, // [2] pre-charge period 0x022/f1
191-
0x0DB, 0x040, // vcomh deselect level
192-
0x0A4, // output ram to display
193-
0x0A6, // none inverted normal display mode
194-
0x0D5, 0x080, // clock divide ratio (0x00=1) and oscillator frequency (0x8)
195-
0x08D, 0x014, // [2] charge pump setting (p62): 0x014 enable, 0x010 disable
196-
0x02E, // 2012-05-27: Deactivate scroll
197-
0x0AF, // display on
198-
U8G_ESC_END // end of sequence
199-
};
200-
201-
uint8_t u8g_dev_ssd1306_128x64_2x_2_wire_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t msg, void *arg) {
202-
switch (msg) {
203-
case U8G_DEV_MSG_INIT:
204-
u8g_InitCom(u8g, dev, U8G_SPI_CLK_CYCLE_300NS);
205-
u8g_WriteEscSeqP_2_wire(u8g, dev, u8g_dev_ssd1306_128x64_init_seq_2_wire);
206-
break;
207-
case U8G_DEV_MSG_STOP:
208-
break;
209-
case U8G_DEV_MSG_PAGE_NEXT: {
210-
u8g_pb_t *pb = (u8g_pb_t *)(dev->dev_mem);
211-
u8g_SetAddress(u8g, dev, 0); // instruction mode
212-
u8g_WriteEscSeqP_2_wire(u8g, dev, u8g_dev_ssd1306_128x64_data_start_2_wire);
213-
u8g_WriteByte(u8g, dev, 0x0B0 | (pb->p.page*2)); // select current page
214-
u8g_SetAddress(u8g, dev, 1); // data mode
215-
u8g_WriteSequence(u8g, dev, pb->width, (uint8_t *) pb->buf);
216-
u8g_SetChipSelect(u8g, dev, 0);
217-
u8g_SetAddress(u8g, dev, 0); // instruction mode
218-
u8g_WriteEscSeqP_2_wire(u8g, dev, u8g_dev_ssd1306_128x64_data_start_2_wire);
219-
u8g_WriteByte(u8g, dev, 0x0B0 | (pb->p.page*2+1)); // select current page
220-
u8g_SetAddress(u8g, dev, 1); // data mode
221-
u8g_WriteSequence(u8g, dev, pb->width, (uint8_t *)(pb->buf)+pb->width);
222-
u8g_SetChipSelect(u8g, dev, 0);
223-
}
224-
break;
225-
case U8G_DEV_MSG_SLEEP_ON:
226-
return 1;
227-
case U8G_DEV_MSG_SLEEP_OFF:
228-
return 1;
229-
}
230-
return u8g_dev_pb16v1_base_fn(u8g, dev, msg, arg);
231-
}
232-
233-
234-
uint8_t u8g_dev_ssd1306_128x64_2x_i2c_2_wire_buf[WIDTH*2] U8G_NOCOMMON ;
235-
u8g_pb_t u8g_dev_ssd1306_128x64_2x_i2c_2_wire_pb = { {16, HEIGHT, 0, 0, 0}, WIDTH, u8g_dev_ssd1306_128x64_2x_i2c_2_wire_buf};
236-
u8g_dev_t u8g_dev_ssd1306_128x64_2x_i2c_2_wire = { u8g_dev_ssd1306_128x64_2x_2_wire_fn, &u8g_dev_ssd1306_128x64_2x_i2c_2_wire_pb, U8G_COM_SSD_I2C_HAL };
237-
238-
239-
/////////////////////////////////////////////////////////////////////////////////////////////
240-
241-
// This routine adds the instruction byte in between the command bytes. This makes the init
242-
// sequences a lot easier to read.
243-
244-
#define I2C_CMD_MODE 0x080
245-
246-
uint8_t u8g_WriteEscSeqP_2_wire(u8g_t *u8g, u8g_dev_t *dev, const uint8_t *esc_seq) {
247-
uint8_t is_escape = 0;
248-
for (;;) {
249-
uint8_t value = u8g_pgm_read(esc_seq);
250-
if (is_escape == 0) {
251-
if (value != 255) {
252-
if (u8g_WriteByte(u8g, dev, value) == 0 )
253-
return 0;
254-
if (u8g_WriteByte(u8g, dev, I2C_CMD_MODE) == 0 )
255-
return 0;
256-
}
257-
else {
258-
is_escape = 1;
259-
}
260-
}
261-
else {
262-
if (value == 255) {
263-
if (u8g_WriteByte(u8g, dev, value) == 0 )
264-
return 0;
265-
if (u8g_WriteByte(u8g, dev, I2C_CMD_MODE) == 0 )
266-
return 0;
267-
}
268-
else if (value == 254) {
269-
break;
270-
}
271-
else if (value >= 0x0F0) {
272-
/* not yet used, do nothing */
273-
}
274-
else if (value >= 0xE0 ) {
275-
u8g_SetAddress(u8g, dev, value & 0x0F);
276-
}
277-
else if (value >= 0xD0) {
278-
u8g_SetChipSelect(u8g, dev, value & 0x0F);
279-
}
280-
else if (value >= 0xC0) {
281-
u8g_SetResetLow(u8g, dev);
282-
value &= 0x0F;
283-
value <<= 4;
284-
value+=2;
285-
u8g_Delay(value);
286-
u8g_SetResetHigh(u8g, dev);
287-
u8g_Delay(value);
288-
}
289-
else if (value >= 0xBE) { /* not yet implemented */
290-
/* u8g_SetVCC(u8g, dev, value & 0x01); */
291-
}
292-
else if (value <= 127) {
293-
u8g_Delay(value);
294-
}
295-
is_escape = 0;
296-
}
297-
esc_seq++;
298-
}
299-
return 1;
300-
}
301-
302-
#endif // HAS_MARLINUI_U8GLIB
224+
#endif // U8GLIB_SH1106

0 commit comments

Comments
 (0)