1 /*
2 * Copyright (C) 2022 HiHope Open Source Organization .
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 *
14 * limitations under the License.
15 */
16
17
18 #include <stddef.h>
19 #include <stdio.h>
20 #include "wifiiot_gpio.h"
21 #include "wifiiot_gpio_ex.h"
22 #include "wifiiot_i2c.h"
23 #include "wifiiot_errno.h"
24 #include "oled_fonts.h"
25 #include "oled_ssd1306.h"
26 #define OLED_I2C_IDX WIFI_IOT_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 #define FOUR 4
36 #define EIGHT 8
37 #define TWO 2
38 #define SIX 6
39 #define SIXTEEN 16
40 #define ONE_HUNDRED_AND_TWENTY 120
41 #define ONE_HUNDRED_AND_TWENTY_EIGHT 128
42
I2cWiteByte(uint8_t regAddr,uint8_t byte)43 static uint32_t I2cWiteByte(uint8_t regAddr, uint8_t byte)
44 {
45 WifiIotI2cIdx id = OLED_I2C_IDX;
46 uint8_t buffer[] = {regAddr, byte};
47 WifiIotI2cData i2cData = {0};
48
49 i2cData.sendBuf = buffer;
50 i2cData.sendLen = sizeof(buffer)/sizeof(buffer[0]);
51
52 return I2cWrite(id, OLED_I2C_ADDR, &i2cData);
53 }
54
55 /**
56 * @brief Write a command byte to OLED device.
57 *
58 * @param cmd the commnad byte to be writen.
59 * @return Returns {@link WIFI_IOT_SUCCESS} if the operation is successful;
60 * returns an error code defined in {@link wifiiot_errno.h} otherwise.
61 */
WriteCmd(uint8_t cmd)62 static uint32_t WriteCmd(uint8_t cmd)
63 {
64 return I2cWiteByte(OLED_I2C_CMD, cmd);
65 }
66
67 /**
68 * @brief Write a data byte to OLED device.
69 *
70 * @param cmd the data byte to be writen.
71 * @return Returns {@link WIFI_IOT_SUCCESS} if the operation is successful;
72 * returns an error code defined in {@link wifiiot_errno.h} otherwise.
73 */
WriteData(uint8_t data)74 static uint32_t WriteData(uint8_t data)
75 {
76 return I2cWiteByte(OLED_I2C_DATA, data);
77 }
78
79 /**
80 * @brief ssd1306 OLED Initialize.
81 */
OledInit(void)82 uint32_t OledInit(void)
83 {
84 static const uint8_t initCmds[] = {
85 0xAE, // --display off
86 0x00, // ---set low column address
87 0x10, // ---set high column address
88 0x40, // --set start line address
89 0xB0, // --set page address
90 0x81, // contract control
91 0xFF, // --128
92 0xA1, // set segment remap
93 0xA6, // --normal / reverse
94 0xA8, // --set multiplex ratio(1 to 64)
95 0x3F, // --1/32 duty
96 0xC8, // Com scan direction
97 0xD3, // -set display offset
98 0x00, //
99 0xD5, // set osc division
100 0x80, //
101 0xD8, // set area color mode off
102 0x05, //
103 0xD9, // Set Pre-Charge Period
104 0xF1, //
105 0xDA, // set com pin configuration
106 0x12, //
107 0xDB, // set Vcomh
108 0x30, //
109 0x8D, // set charge pump enable
110 0x14, //
111 0xAF, // --turn on oled panel
112 };
113
114 IoSetFunc(WIFI_IOT_IO_NAME_GPIO_13, WIFI_IOT_IO_FUNC_GPIO_13_I2C0_SDA);
115 IoSetFunc(WIFI_IOT_IO_NAME_GPIO_14, WIFI_IOT_IO_FUNC_GPIO_14_I2C0_SCL);
116
117 I2cInit(WIFI_IOT_I2C_IDX_0, OLED_I2C_BAUDRATE);
118
119 for (size_t i = 0; i < sizeof(initCmds)/sizeof(initCmds[0]); i++) {
120 uint32_t status = WriteCmd(initCmds[i]);
121 if (status != WIFI_IOT_SUCCESS) {
122 return status;
123 }
124 }
125 return WIFI_IOT_SUCCESS;
126 }
127
OledSetPosition(uint8_t x,uint8_t y)128 void OledSetPosition(uint8_t x, uint8_t y)
129 {
130 WriteCmd(0xb0 + y);
131 WriteCmd(((x & 0xf0) >> FOUR) | 0x10);
132 WriteCmd(x & 0x0f);
133 }
134
OledFillScreen(uint8_t fillData)135 void OledFillScreen(uint8_t fillData)
136 {
137 uint8_t m = 0;
138 uint8_t n = 0;
139
140 for (m=0; m < EIGHT; m++) {
141 WriteCmd(0xb0 + m);
142 WriteCmd(0x00);
143 WriteCmd(0x10);
144
145 for (n=0; n < ONE_HUNDRED_AND_TWENTY_EIGHT; n++) {
146 WriteData(fillData);
147 }
148 }
149 }
150
151 /**
152 * @brief 8*16 typeface
153 * @param x: write positon start from x axis
154 * @param y: write positon start from y axis
155 * @param ch: write data
156 * @param font: selected font
157 */
OledShowChar(uint8_t x,uint8_t y,uint8_t ch,Font font)158 void OledShowChar(uint8_t x, uint8_t y, uint8_t ch, Font font)
159 {
160 uint8_t c = 0;
161 uint8_t i = 0;
162 int num_x = x;
163 int num_y = y;
164
165 c = ch - ' '; // 得到偏移后的值
166 if (x > OLED_WIDTH - 1) {
167 num_x = 0;
168 num_y = y + TWO;
169 }
170
171 if (font == FONT8x16) {
172 OledSetPosition(x, y);
173 for (i = 0; i < EIGHT; i++) {
174 WriteData(F8X16[c*SIXTEEN + i]);
175 }
176
177 OledSetPosition(x, y+1);
178 for (i = 0; i < EIGHT; i++) {
179 WriteData(F8X16[c*SIXTEEN + i + EIGHT]);
180 }
181 } else {
182 OledSetPosition(x, y);
183 for (i = 0; i < SIX; i++) {
184 WriteData(F6x8[c][i]);
185 }
186 }
187 }
188
OledShowString(uint8_t x,uint8_t y,const char * str,Font font)189 void OledShowString(uint8_t x, uint8_t y, const char* str, Font font)
190 {
191 uint8_t j = 0;
192 int num_x = x;
193 int num_y = y;
194 if (str == NULL) {
195 printf("param is NULL,Please check!!!\r\n");
196 return;
197 }
198
199 while (str[j]) {
200 OledShowChar(x, y, str[j], font);
201 num_x += EIGHT;
202 if (x > ONE_HUNDRED_AND_TWENTY) {
203 num_x = 0;
204 num_y += TWO;
205 }
206 j++;
207 }
208 }
209