1 /*
2 * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <stddef.h>
17 #include <stdio.h>
18 #include "ohos_types.h"
19 #include "iot_errno.h"
20 #include "iot_gpio.h"
21 #include "iot_i2c.h"
22 #include "iot_gpio_ex.h"
23 #include "oled_fonts.h"
24 #include "oled_ssd1306.h"
25
26 #define OLED_I2C_IDX 0
27
28 #define OLED_WIDTH (128)
29 #define OLED_I2C_ADDR 0x78 // 默认地址为 0x78
30 #define OLED_I2C_CMD 0x00 // 0000 0000 写命令
31 #define OLED_I2C_DATA 0x40 // 0100 0000(0x40) 写数据
32 #define OLED_I2C_BAUDRATE (400 * 1000) // 400k
33
34 #define DELAY_100_MS (100 * 1000)
35
36 typedef struct {
37 /** Pointer to the buffer storing data to send */
38 unsigned char *sendBuf;
39 /** Length of data to send */
40 unsigned int sendLen;
41 /** Pointer to the buffer for storing data to receive */
42 unsigned char *receiveBuf;
43 /** Length of data received */
44 unsigned int receiveLen;
45 } IotI2cData;
46
I2cWiteByte(uint8_t regAddr,uint8_t byte)47 static uint32_t I2cWiteByte(uint8_t regAddr, uint8_t byte)
48 {
49 unsigned int id = OLED_I2C_IDX;
50 uint8_t buffer[] = {regAddr, byte};
51 IotI2cData i2cData = {0};
52
53 i2cData.sendBuf = buffer;
54 i2cData.sendLen = sizeof(buffer) / sizeof(buffer[0]);
55
56 return IoTI2cWrite(id, OLED_I2C_ADDR, i2cData.sendBuf, i2cData.sendLen);
57 }
58
59 /**
60 * @brief Write a command byte to OLED device.
61 *
62 * @param cmd the commnad byte to be writen.
63 * @return Returns {@link IOT_SUCCESS} if the operation is successful;
64 * returns an error code defined in {@link wifiiot_errno.h} otherwise.
65 */
WriteCmd(uint8_t cmd)66 static uint32_t WriteCmd(uint8_t cmd)
67 {
68 return I2cWiteByte(OLED_I2C_CMD, cmd);
69 }
70
71 /**
72 * @brief Write a data byte to OLED device.
73 *
74 * @param cmd the data byte to be writen.
75 * @return Returns {@link IOT_SUCCESS} if the operation is successful;
76 * returns an error code defined in {@link wifiiot_errno.h} otherwise.
77 */
WriteData(uint8_t data)78 static uint32_t WriteData(uint8_t data)
79 {
80 return I2cWiteByte(OLED_I2C_DATA, data);
81 }
82
83 /**
84 * @brief ssd1306 OLED Initialize.
85 */
OledInit(void)86 uint32_t OledInit(void)
87 {
88 static const uint8_t initCmds[] = {
89 0xAE, // --display off
90 0x00, // ---set low column address
91 0x10, // ---set high column address
92 0x40, // --set start line address
93 0xB0, // --set page address
94 0x81, // contract control
95 0xFF, // --128
96 0xA1, // set segment remap
97 0xA6, // --normal / reverse
98 0xA8, // --set multiplex ratio(1 to 64)
99 0x3F, // --1/32 duty
100 0xC8, // Com scan direction
101 0xD3, // -set display offset
102 0x00,
103 0xD5, // set osc division
104 0x80,
105 0xD8, // set area color mode off
106 0x05,
107 0xD9, // Set Pre-Charge Period
108 0xF1,
109 0xDA, // set com pin configuration
110 0x12,
111 0xDB, // set Vcomh
112 0x30,
113 0x8D, // set charge pump enable
114 0x14,
115 0xAF, // --turn on oled panel
116 };
117
118 IoTGpioInit(13); /* 初始化gpio13 */
119 IoSetFunc(13, 6); /* gpio13使用6功能 */
120 IoTGpioInit(14); /* 初始化gpio14 */
121 IoSetFunc(14, 6); /* gpio14使用6功能 */
122
123 IoTI2cInit(0, OLED_I2C_BAUDRATE);
124
125 for (size_t i = 0; i < ARRAY_SIZE(initCmds); i++) {
126 uint32_t status = WriteCmd(initCmds[i]);
127 if (status != IOT_SUCCESS) {
128 return status;
129 }
130 }
131 return IOT_SUCCESS;
132 }
133
OledSetPosition(uint8_t x,uint8_t y)134 void OledSetPosition(uint8_t x, uint8_t y)
135 {
136 WriteCmd(0xb0 + y);
137 WriteCmd(((x & 0xf0) >> 4) | 0x10); /* 在0xf0右移4位,与0x10或,实现了写数据 */
138 WriteCmd(x & 0x0f);
139 }
140
141 /* 全屏填充 */
OledFillScreen(uint8_t fillData)142 void OledFillScreen(uint8_t fillData)
143 {
144 for (uint8_t m = 0; m < 8; m++) { /* 循环8次实现横屏填充 */
145 WriteCmd(0xb0 + m);
146 WriteCmd(0x00);
147 WriteCmd(0x10);
148
149 for (uint8_t n = 0; n < 128; n++) { /* 循环128次实现竖屏填充 */
150 WriteData(fillData);
151 }
152 }
153 }
154
155 /**
156 * @brief 8*16 typeface
157 * @param x: write positon start from x axis
158 * @param y: write positon start from y axis
159 * @param ch: write data
160 * @param font: selected font
161 */
OledShowChar(uint8_t x,uint8_t y,uint8_t ch,Font font)162 void OledShowChar(uint8_t x, uint8_t y, uint8_t ch, Font font)
163 {
164 uint8_t c = ch - ' '; // 得到偏移后的值
165 uint8_t b = x;
166 uint8_t d = y;
167 if (b > OLED_WIDTH - 1) {
168 b = 0;
169 d = d + 2; /* 得到偏移后的值2 */
170 }
171
172 if (font == FONT8_X16) {
173 OledSetPosition(b, d);
174 for (uint8_t i = 0; i < 8; i++) { /* 循环8次实现横屏填充 */
175 WriteData(g_f8X16[c * 16 + i]); /* 循环16次实现横屏填充 */
176 }
177
178 OledSetPosition(b, d + 1);
179 for (uint8_t i = 0; i < 8; i++) { /* 循环8次实现横屏填充 */
180 WriteData(g_f8X16[c * 16 + i + 8]); /* 循环16次实现横屏填充8列 */
181 }
182 } else {
183 OledSetPosition(b, d);
184 for (uint8_t i = 0; i < 6; i++) { /* 循环6次实现横屏填充 */
185 WriteData(g_f6X8[c][i]);
186 }
187 }
188 }
189
OledShowString(uint8_t x,uint8_t y,const char * str,Font font)190 void OledShowString(uint8_t x, uint8_t y, const char* str, Font font)
191 {
192 uint8_t j = 0;
193 uint8_t b = x;
194 uint8_t d = y;
195 if (str == NULL) {
196 printf("param is NULL,Please check!!!\r\n");
197 return;
198 }
199
200 while (str[j]) {
201 OledShowChar(b, d, str[j], font);
202 b += 8; /* 循环8次实现横屏填充 */
203 if (b > 120) { /* 循环120次实现横屏填充 */
204 b = 0;
205 d += 2; /* 循环2次实现横屏填充 */
206 }
207 j++;
208 }
209 }