-
Notifications
You must be signed in to change notification settings - Fork 0
/
ssd1306.cpp
187 lines (149 loc) · 4.41 KB
/
ssd1306.cpp
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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
/**
* @file ssd1306.cpp
* @brief Simple text mode OLED display driver
* @author Matt Thompson <[email protected]>
*/
#include <inttypes.h>
#include "ssd1306.h"
#include <spark_wiring.h>
#include <spark_wiring_spi.h>
static void inline ssd1306_command(lcd_t *lcd, uint8_t c)
{
digitalWrite(lcd->cs, LOW);
digitalWrite(lcd->dc, LOW);
SPI.transfer(c);
digitalWrite(lcd->cs, HIGH);
}
static void inline ssd1306_data_start(lcd_t *lcd)
{
digitalWrite(lcd->dc, HIGH);
digitalWrite(lcd->cs, LOW);
}
static void inline ssd1306_data_end(lcd_t *lcd)
{
digitalWrite(lcd->cs, HIGH);
}
static void inline ssd1306_data(lcd_t *lcd, uint8_t data)
{
SPI.transfer(data);
}
void ssd1306_init(lcd_t *lcd, int reset_pin, int cs_pin, int dc_pin)
{
lcd->reset = reset_pin;
lcd->cs = cs_pin;
lcd->dc = dc_pin;
lcd->x = 0;
lcd->y = 0;
SPI.setBitOrder(MSBFIRST);
SPI.setClockDivider(SPI_CLOCK_DIV8);
SPI.setDataMode(0);
SPI.begin();
pinMode(lcd->reset, OUTPUT);
pinMode(lcd->cs, OUTPUT);
pinMode(lcd->dc, OUTPUT);
digitalWrite(lcd->cs, HIGH);
digitalWrite(lcd->dc, HIGH);
digitalWrite(lcd->reset, HIGH);
Delay_Microsecond(1000);
digitalWrite(lcd->reset, LOW);
Delay_Microsecond(10000);
digitalWrite(lcd->reset, HIGH);
ssd1306_command(lcd, SSD1306_DISPLAYOFF); // 0xAE
ssd1306_command(lcd, SSD1306_SETDISPLAYCLOCKDIV); // 0xD5
ssd1306_command(lcd, 0x80); // the suggested ratio 0x80
ssd1306_command(lcd, SSD1306_SETMULTIPLEX); // 0xA8
ssd1306_command(lcd, 0x1F);
ssd1306_command(lcd, SSD1306_SETDISPLAYOFFSET); // 0xD3
ssd1306_command(lcd, 0x0); // no offset
ssd1306_command(lcd, SSD1306_SETSTARTLINE | 0x0); // line #0
ssd1306_command(lcd, SSD1306_MEMORYMODE); // 0x20
ssd1306_command(lcd, 0x00); // 0x0 act like ks0108
ssd1306_command(lcd, SSD1306_SEGREMAP | 0x1);
// Set scan direction
ssd1306_command(lcd, SSD1306_COMSCANDEC);
ssd1306_command(lcd, SSD1306_SETCOMPINS); // 0xDA
ssd1306_command(lcd, 0x02);
ssd1306_command(lcd, SSD1306_SETCONTRAST); // 0x81
ssd1306_command(lcd, 0x8F);
ssd1306_command(lcd, SSD1306_SETPRECHARGE); // 0xd9
ssd1306_command(lcd, 0xF1);
ssd1306_command(lcd, SSD1306_SETVCOMDETECT); // 0xDB
ssd1306_command(lcd, 0x40);
ssd1306_command(lcd, SSD1306_DISPLAYALLON_RESUME); // 0xA4
ssd1306_command(lcd, SSD1306_NORMALDISPLAY); // 0xA6
ssd1306_command(lcd, SSD1306_CHARGEPUMP); // 0x8D
ssd1306_command(lcd, 0x14);
ssd1306_command(lcd, SSD1306_DISPLAYON);
}
void ssd1306_clear(lcd_t *lcd)
{
uint16_t i;
ssd1306_command(lcd, SSD1306_MEMORYMODE);
ssd1306_command(lcd, 0);
// Set column start and end address
ssd1306_command(lcd, SSD1306_COLUMNADDR);
ssd1306_command(lcd, 0);
ssd1306_command(lcd, 127);
// Set page start and end address
ssd1306_command(lcd, SSD1306_PAGEADDR);
ssd1306_command(lcd, 0);
ssd1306_command(lcd, 3);
ssd1306_data_start(lcd);
for(i=0;i<128*4;i++)
{
ssd1306_data(lcd, 0);
}
ssd1306_data_end(lcd);
}
void ssd1306_print(lcd_t *lcd, char *str)
{
int len = strlen(str);
int i;
for(i=0;i<len;i++)
{
ssd1306_write(lcd, str[i]);
}
}
void ssd1306_cursor(lcd_t *lcd, int x, int y)
{
lcd->x = x;
lcd->y = y;
}
/**
* @brief Write a single character at the current cursor position
*
* Using vertical addressing mode, we can have the hardware
* automatically move to the next column after writing 7 pixels
* in each page (rows).
*/
void ssd1306_write(lcd_t *lcd, char c)
{
uint8_t *font_bitmap = (uint8_t *)&font[(int)(c*5)];
uint8_t i;
uint8_t start = lcd->x * 6;
// Set vertical addressing mode
ssd1306_command(lcd, SSD1306_MEMORYMODE);
ssd1306_command(lcd, 1);
// Set column start and end address
ssd1306_command(lcd, SSD1306_COLUMNADDR);
ssd1306_command(lcd, start);
ssd1306_command(lcd, start+5);
// Set page start and end address
ssd1306_command(lcd, SSD1306_PAGEADDR);
ssd1306_command(lcd, lcd->y);
ssd1306_command(lcd, lcd->y);
ssd1306_data_start(lcd);
for(i=0;i<5;i++)
{
ssd1306_data(lcd, font_bitmap[i]);
}
ssd1306_data_end(lcd);
lcd->x++;
if(lcd->x >= 21)
{
lcd->y++;
lcd->x = 0;
}
if(lcd->y >= 4)
lcd->y = 0;
}