1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
|
#ifndef PICO1541_SSD1306_H
#define PICO1541_SSD1306_H
#include <stdint.h>
#include <hardware/i2c.h>
/* ------------------------------------------------------------------ */
/* I2C addressing and control bytes */
/* ------------------------------------------------------------------ */
#define SSD1306_I2C_ADDR 0x3C /* 7-bit, SA0 = 0 (D/C# pin low) */
#define SSD1306_I2C_ADDR_ALT 0x3D /* 7-bit, SA0 = 1 */
#define SSD1306_CTRL_CMD 0x00 /* following bytes are commands */
#define SSD1306_CTRL_DATA 0x40 /* following bytes are GDDRAM */
#define SSD1306_CTRL_CMD_SINGLE 0x80 /* one command byte follows */
#define SSD1306_CTRL_DATA_SINGLE 0xC0 /* one data byte follows */
/* ------------------------------------------------------------------ */
/* Fundamental commands */
/* ------------------------------------------------------------------ */
#define SSD1306_SET_CONTRAST 0x81 /* 1 arg: 0x00..0xFF, reset 0x7F */
#define SSD1306_ENTIRE_DISPLAY_RESUME 0xA4 /* output follows RAM (reset) */
#define SSD1306_ENTIRE_DISPLAY_ON 0xA5 /* all pixels on, ignores RAM */
#define SSD1306_NORMAL_DISPLAY 0xA6 /* 1 = pixel on */
#define SSD1306_INVERSE_DISPLAY 0xA7 /* 1 = pixel off */
#define SSD1306_DISPLAY_OFF 0xAE /* sleep mode */
#define SSD1306_DISPLAY_ON 0xAF
/* ------------------------------------------------------------------ */
/* Scrolling commands */
/* ------------------------------------------------------------------ */
#define SSD1306_SCROLL_RIGHT 0x26 /* 6 args: continuous, right */
#define SSD1306_SCROLL_LEFT 0x27 /* 6 args: continuous, left */
#define SSD1306_SCROLL_VERT_RIGHT 0x29 /* 5 args: vertical + horizontal */
#define SSD1306_SCROLL_VERT_LEFT 0x2A /* 5 args: vertical + horizontal */
#define SSD1306_SCROLL_DEACTIVATE 0x2E
#define SSD1306_SCROLL_ACTIVATE 0x2F
#define SSD1306_SET_VERT_SCROLL_AREA 0xA3 /* 2 args: top fixed, scroll rows */
/* Argument layout, 0x26 / 0x27:
* dummy 0x00, start page, frame interval, end page, dummy 0x00, dummy 0xFF
* Argument layout, 0x29 / 0x2A:
* dummy 0x00, start page, frame interval, end page, vertical offset
*/
/* ------------------------------------------------------------------ */
/* Addressing commands */
/* ------------------------------------------------------------------ */
#define SSD1306_SET_MEMORY_MODE 0x20 /* 1 arg, see MODE_* below */
#define SSD1306_SET_COL_ADDR 0x21 /* 2 args: column start, end */
#define SSD1306_SET_PAGE_ADDR 0x22 /* 2 args: page start, end */
/* Page addressing mode only: start address is split across two commands. */
#define SSD1306_SET_LOWER_COL_START 0x00 /* 0x00..0x0F = low nibble */
#define SSD1306_SET_HIGHER_COL_START 0x10 /* 0x10..0x1F = high nibble */
#define SSD1306_SET_PAGE_START 0xB0 /* 0xB0..0xB7 = page 0..7 */
/* ------------------------------------------------------------------ */
/* Hardware configuration */
/* ------------------------------------------------------------------ */
#define SSD1306_SET_START_LINE 0x40 /* 0x40..0x7F, line 0..63 */
#define SSD1306_SEG_REMAP_COL0 0xA0 /* column 0 -> SEG0 (reset) */
#define SSD1306_SEG_REMAP_COL127 0xA1 /* column 127 -> SEG0 (mirror X) */
#define SSD1306_SET_MULTIPLEX 0xA8 /* 1 arg: N+1 rows, 0x0F..0x3F */
#define SSD1306_COM_SCAN_NORMAL 0xC0 /* COM0 -> COM[N-1] */
#define SSD1306_COM_SCAN_REMAP 0xC8 /* COM[N-1] -> COM0 (mirror Y) */
#define SSD1306_SET_DISPLAY_OFFSET 0xD3 /* 1 arg: shift 0..63 by COM */
#define SSD1306_SET_COM_PINS 0xDA /* 1 arg, see COM_PINS_* below */
/* ------------------------------------------------------------------ */
/* Timing and driving scheme */
/* ------------------------------------------------------------------ */
#define SSD1306_SET_CLOCK_DIV 0xD5 /* 1 arg: lo = div-1, hi = freq */
/* reset 0x80 */
#define SSD1306_SET_PRECHARGE 0xD9 /* 1 arg: phase2/phase1 */
/* reset 0x22, 0xF1 for ext VCC*/
#define SSD1306_SET_VCOMH 0xDB /* 1 arg, see VCOMH_* below */
#define SSD1306_NOP 0xE3
#define SSD1306_SET_CHARGE_PUMP 0x8D /* 1 arg: 0x14 on, 0x10 off */
/* (SSD1306B / modules only) */
/* ------------------------------------------------------------------ */
/* Parameter constants */
/* ------------------------------------------------------------------ */
#define SSD1306_MEM_MODE_HORIZONTAL 0x00
#define SSD1306_MEM_MODE_VERTICAL 0x01
#define SSD1306_MEM_MODE_PAGE 0x02 /* reset default */
#define SSD1306_COM_PINS_SEQUENTIAL 0x02
#define SSD1306_COM_PINS_ALTERNATIVE 0x12 /* 128x64 default */
#define SSD1306_COM_PINS_SEQ_REMAP 0x22
#define SSD1306_COM_PINS_ALT_REMAP 0x32
#define SSD1306_VCOMH_0_65 0x00 /* ~0.65 x VCC */
#define SSD1306_VCOMH_0_77 0x20 /* ~0.77 x VCC, reset */
#define SSD1306_VCOMH_0_83 0x30 /* ~0.83 x VCC */
#define SSD1306_CHARGE_PUMP_ON 0x14
#define SSD1306_CHARGE_PUMP_OFF 0x10
#define SSD1306_SCROLL_5_FRAMES 0x00 /* 5 frames per step */
#define SSD1306_SCROLL_64_FRAMES 0x01
#define SSD1306_SCROLL_128_FRAMES 0x02
#define SSD1306_SCROLL_256_FRAMES 0x03
#define SSD1306_SCROLL_3_FRAMES 0x04
#define SSD1306_SCROLL_4_FRAMES 0x05
#define SSD1306_SCROLL_25_FRAMES 0x06
#define SSD1306_SCROLL_2_FRAMES 0x07
/* ------------------------------------------------------------------ */
/* Helper macros for building command bytes */
/* ------------------------------------------------------------------ */
#define SSD1306_COL_ADDR_LO(c) (uint8_t)(SSD1306_SET_LOWER_COL_START | ((c) & 0x0F))
#define SSD1306_COL_ADDR_HI(c) (uint8_t)(SSD1306_SET_HIGHER_COL_START | (((c) >> 4) & 0x0F))
#define SSD1306_PAGE(c) (uint8_t)(SSD1306_SET_PAGE_START | ((c) & 0x07))
#define SSD1306_START_LINE(l) (uint8_t)(SSD1306_SET_START_LINE | ((l) & 0x3F))
#define SSD1306_CONTRAST(v) (uint8_t)(v)
#define SSD1306_MUX_RATIO(rows) (uint8_t)((rows) - 1) /* rows = 16..64 */
#define SSD1306_CLOCK(div, freq) (uint8_t)((((freq) & 0x0F) << 4) | (((div) - 1) & 0x0F))
#define SSD1306_BUFFER_LEN 256
typedef struct ssd1306 {
i2c_inst_t *i2c;
uint8_t addr;
uint8_t buf[SSD1306_BUFFER_LEN];
size_t len;
} ssd1306_t;
int ssd_init(ssd1306_t *display, i2c_inst_t *i2c, uint8_t addr);
int ssd_push(ssd1306_t *display, uint8_t byte);
int ssd_send(ssd1306_t *display);
int ssd_power_on(ssd1306_t *display);
int ssd_putscr(ssd1306_t *display, const uint8_t c, bool shift);
int ssd_putchar(ssd1306_t *display, const char c);
int ssd_putstr(ssd1306_t *display, const char *str);
#endif
|