aboutsummaryrefslogtreecommitdiff
path: root/lib/chibios-contrib/testhal/NUMICRO/NUC123/NUTINY-SDK-NUC123-V2.0/I2C/ssd1306.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/chibios-contrib/testhal/NUMICRO/NUC123/NUTINY-SDK-NUC123-V2.0/I2C/ssd1306.c')
-rw-r--r--lib/chibios-contrib/testhal/NUMICRO/NUC123/NUTINY-SDK-NUC123-V2.0/I2C/ssd1306.c193
1 files changed, 193 insertions, 0 deletions
diff --git a/lib/chibios-contrib/testhal/NUMICRO/NUC123/NUTINY-SDK-NUC123-V2.0/I2C/ssd1306.c b/lib/chibios-contrib/testhal/NUMICRO/NUC123/NUTINY-SDK-NUC123-V2.0/I2C/ssd1306.c
new file mode 100644
index 000000000..f4b37c195
--- /dev/null
+++ b/lib/chibios-contrib/testhal/NUMICRO/NUC123/NUTINY-SDK-NUC123-V2.0/I2C/ssd1306.c
@@ -0,0 +1,193 @@
1/*
2 Copyright (C) 2020 Ein Terakawa
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15*/
16
17#include "hal.h"
18#include "ssd1306.h"
19#include "string.h"
20
21/* timeout value must be increased for i2cclk less than its default, 100kHz. */
22#define CMD_TRANSMIT_TIMEOUT TIME_MS2I(10)
23#define DATA_TRANSMIT_TIMEOUT TIME_MS2I(100)
24
25#define CTRL_CMD_STREAM 0x00
26#define CTRL_DATA_STREAM 0x40
27#define CTRL_CMD_SINGLE 0x80
28
29#define I2CD ((ssd1306)->i2cd)
30#define ADDR ((ssd1306)->i2caddr)
31
32#define send_cmd(ssd1306, ...) \
33 do { \
34 uint8_t buf[] = { CTRL_CMD_STREAM, __VA_ARGS__ }; \
35 bool _success = _send_cmd(I2CD, ADDR, buf, sizeof(buf)); \
36 if (!_success) goto done; \
37 } while(0)
38
39#define send_cmd_static(ssd1306, ...) \
40 do{ \
41 static const uint8_t buf[] = { CTRL_CMD_STREAM, __VA_ARGS__ }; \
42 bool _success = _send_cmd(I2CD, ADDR, buf, sizeof(buf)); \
43 if (!_success) goto done; \
44 } while(0)
45
46#define CMD1(c) c
47#define CMD2(c, d) c, d
48#define CMD3(c, d, e) c, d, e
49
50static bool _send_cmd(I2CDriver *i2cd, uint8_t addr, const uint8_t *buf, int len) {
51
52 msg_t status = i2cMasterTransmitTimeout(i2cd, addr,
53 buf, len, NULL, 0, CMD_TRANSMIT_TIMEOUT);
54
55 if (MSG_OK != status) {
56 /* i2cflags_t error_code = i2cGetErrors(i2cd); */
57 return false;
58 }
59
60 return true;
61}
62
63#define send_data(ssd1306, buf, len) \
64 do { \
65 bool _success = _send_data(I2CD, ADDR, buf, len); \
66 if (!_success) goto done; \
67 } while(0)
68
69static bool _send_data(I2CDriver *i2cd, uint8_t addr, const uint8_t *buf, int len) {
70 bool success = false;
71
72 msg_t status = i2cMasterTransmitTimeout(i2cd, addr,
73 buf, len, NULL, 0, DATA_TRANSMIT_TIMEOUT);
74
75 if (MSG_OK != status) {
76 /* i2cflags_t error_code = i2cGetErrors(I2CD); */
77 goto done;
78 }
79
80 success = true;
81
82done:
83 return success;
84}
85
86bool ssd1306_init(SSD1306_DRIVER *ssd1306) {
87 bool success = false;
88 uint8_t width = ssd1306->width;
89 uint8_t height = ssd1306->height;
90 uint8_t num_pages = height / 8;
91
92 i2cStart(I2CD, ssd1306->i2ccfg);
93
94 send_cmd_static(ssd1306,
95 CMD1(SetDisplayOff),
96 CMD1(DeactivateScroll),
97 CMD1(DisableEntireDisplayOn),
98 CMD2(SetOscFreqAndClkDiv, 0x80),
99 CMD2(SetDisplayOffset, 0x00),
100 CMD1(SetDisplayStartLine | 0x00),
101 CMD2(SetMemoryAddressMode, 0x00)); /* Horizontal Addressing Mode */
102
103 send_cmd(ssd1306, CMD2(SetMultiplexRatio, height - 1));
104
105 if (ssd1306->rotate180) {
106 /* rotate 180 degrees == upside down */
107 send_cmd_static(ssd1306,
108 CMD1(SetSegmentRemapReverse),
109 CMD1(SetComScanOrderReverse));
110 } else {
111 /* no rotation */
112 send_cmd_static(ssd1306,
113 CMD1(SetSegmentRemapNormal),
114 CMD1(SetComScanOrderNormal));
115 }
116
117 if (height == 32) {
118 /* 128x32 module uses SequentialComMode */
119 send_cmd_static(ssd1306, CMD2(SetComPins, 0x02));
120 } else {
121 /* 128x64 module uses AlternativeComMode */
122 send_cmd_static(ssd1306, CMD2(SetComPins, 0x12));
123 }
124
125 /* Clear Graphic Display Data RAM */
126 send_cmd(ssd1306,
127 CMD3(SetPageAddress, 0, num_pages - 1),
128 CMD3(SetColumnAddress, 0, width - 1));
129
130 uint8_t *buf = ssd1306->buf;
131 size_t len = SSD1306_PREAMBLE_LENGTH + num_pages * width;
132 memset(buf, 0, len);
133 buf[0] = CTRL_DATA_STREAM; /* need this byte proceeding the actual data */
134 send_data(ssd1306, buf, len);
135
136 send_cmd_static(ssd1306,
137 CMD2(SetPreChargePeriod, 0xC4),
138 CMD2(SetVcomhLevel, 0x20),
139 CMD1(SetNormalDisplay),
140 CMD2(SetContrastControl, 0x3F),
141 CMD2(ChargePumpSetting, 0x14),
142 CMD1(SetDisplayOn));
143
144 success = true;
145
146done:
147 i2cStop(I2CD);
148 return success;
149}
150
151bool ssd1306_data(SSD1306_DRIVER *ssd1306) {
152 bool success = false;
153 uint8_t width = ssd1306->width;
154 uint8_t height = ssd1306->height;
155 uint8_t num_pages = height / 8;
156
157 i2cStart(I2CD, ssd1306->i2ccfg);
158
159 /* Transfer to Graphic Display Data RAM */
160 send_cmd(ssd1306,
161 CMD3(SetPageAddress, 0, num_pages - 1),
162 CMD3(SetColumnAddress, 0, width - 1));
163
164 uint8_t *buf = ssd1306->buf;
165 size_t len = SSD1306_PREAMBLE_LENGTH + num_pages * width;
166 send_data(ssd1306, buf, len);
167
168 success = true;
169
170done:
171 i2cStop(I2CD);
172 return success;
173}
174
175bool ssd1306_display_on(SSD1306_DRIVER *ssd1306) {
176 bool success = false;
177 i2cStart(I2CD, ssd1306->i2ccfg);
178 send_cmd_static(ssd1306, CMD1(SetDisplayOn));
179 success = true;
180done:
181 i2cStop(I2CD);
182 return success;
183}
184
185bool ssd1306_display_off(SSD1306_DRIVER *ssd1306) {
186 bool success = false;
187 i2cStart(I2CD, ssd1306->i2ccfg);
188 send_cmd_static(ssd1306, CMD1(SetDisplayOff));
189 success = true;
190done:
191 i2cStop(I2CD);
192 return success;
193}