summaryrefslogtreecommitdiff
path: root/src/ssd1306.h
blob: 581b683cdfc0d835c2ad7432023dcbac4ea4557e (plain)
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