lcd: rename from iiclcd to i2clcd, add swig
[contrib/upm.git] / src / lcd / ssd1327.cxx
1 /*
2  * Author: Yevgeniy Kiveisha <yevgeniy.kiveisha@intel.com>
3  * Copyright (c) 2014 Intel Corporation.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining
6  * a copy of this software and associated documentation files (the
7  * "Software"), to deal in the Software without restriction, including
8  * without limitation the rights to use, copy, modify, merge, publish,
9  * distribute, sublicense, and/or sell copies of the Software, and to
10  * permit persons to whom the Software is furnished to do so, subject to
11  * the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be
14  * included in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */
24
25 #include <string>
26 #include <unistd.h>
27
28 #include "ssd1327.h"
29
30 using namespace upm;
31
32 #define INIT_SLEEP 50000
33 #define CMD_SLEEP  10000
34
35 SSD1327::SSD1327 (int bus_in, int addr_in) : I2CLcd (bus_in, addr_in) {
36     maa_result_t error  = MAA_SUCCESS;
37     usleep (INIT_SLEEP);
38     i2Cmd (m_i2c_lcd_control, 0xFD); // Unlock OLED driver IC MCU interface from entering command. i.e: Accept commands
39     usleep (INIT_SLEEP);
40     i2Cmd (m_i2c_lcd_control, 0x12);
41     usleep (INIT_SLEEP);
42     error = i2Cmd (m_i2c_lcd_control, 0xAE); // Set display off
43     usleep (INIT_SLEEP);
44     i2Cmd (m_i2c_lcd_control, 0xA8); // set multiplex ratio
45     usleep (INIT_SLEEP);
46     error = i2Cmd (m_i2c_lcd_control, 0x5F); // 96
47     usleep (INIT_SLEEP);
48     error = i2Cmd (m_i2c_lcd_control, 0xA1); // set display start line
49     usleep (INIT_SLEEP);
50     error = i2Cmd (m_i2c_lcd_control, 0x00); //
51     usleep (INIT_SLEEP);
52     error = i2Cmd (m_i2c_lcd_control, 0xA2); // set display offset
53     usleep (INIT_SLEEP);
54     error = i2Cmd (m_i2c_lcd_control, 0x60);
55     usleep (INIT_SLEEP);
56     error = i2Cmd (m_i2c_lcd_control, 0xA0); // set remap
57     usleep (INIT_SLEEP);
58     error = i2Cmd (m_i2c_lcd_control, 0x46);
59     usleep (INIT_SLEEP);
60     error = i2Cmd (m_i2c_lcd_control, 0xAB); // set vdd internal
61     usleep (INIT_SLEEP);
62     error = i2Cmd (m_i2c_lcd_control, 0x01); //
63     usleep (INIT_SLEEP);
64     error = i2Cmd (m_i2c_lcd_control, 0x81); // set contrasr
65     usleep (INIT_SLEEP);
66     error = i2Cmd (m_i2c_lcd_control, 0x53); // 100 nit
67     usleep (INIT_SLEEP);
68     error = i2Cmd (m_i2c_lcd_control, 0xB1); // Set Phase Length
69     usleep (INIT_SLEEP);
70     error = i2Cmd (m_i2c_lcd_control, 0X51); //
71     usleep (INIT_SLEEP);
72     error = i2Cmd (m_i2c_lcd_control, 0xB3); // Set Display Clock Divide Ratio/Oscillator Frequency
73     usleep (INIT_SLEEP);
74     error = i2Cmd (m_i2c_lcd_control, 0x01); //
75     usleep (INIT_SLEEP);
76     error = i2Cmd (m_i2c_lcd_control, 0xB9); //
77     usleep (INIT_SLEEP);
78     error = i2Cmd (m_i2c_lcd_control, 0xBC); // set pre_charge voltage/VCOMH
79     usleep (INIT_SLEEP);
80     error = i2Cmd (m_i2c_lcd_control, 0x08); // (0x08);
81     usleep (INIT_SLEEP);
82     error = i2Cmd (m_i2c_lcd_control, 0xBE); // set VCOMH
83     usleep (INIT_SLEEP);
84     error = i2Cmd (m_i2c_lcd_control, 0X07); // (0x07);
85     usleep (INIT_SLEEP);
86     error = i2Cmd (m_i2c_lcd_control, 0xB6); // Set second pre-charge period
87     usleep (INIT_SLEEP);
88     error = i2Cmd (m_i2c_lcd_control, 0x01); //
89     usleep (INIT_SLEEP);
90     error = i2Cmd (m_i2c_lcd_control, 0xD5); // enable second precharge and enternal vsl
91     usleep (INIT_SLEEP);
92     error = i2Cmd (m_i2c_lcd_control, 0X62); // (0x62);
93     usleep (INIT_SLEEP);
94     error = i2Cmd (m_i2c_lcd_control, 0xA4); // Set Normal Display Mode
95     usleep (INIT_SLEEP);
96     error = i2Cmd (m_i2c_lcd_control, 0x2E); // Deactivate Scroll
97     usleep (INIT_SLEEP);
98     error = i2Cmd (m_i2c_lcd_control, 0xAF); // Switch on display
99     usleep (INIT_SLEEP);
100
101     // Row Address
102     error = i2Cmd (m_i2c_lcd_control, 0x75); // Set Row Address
103     usleep (INIT_SLEEP);
104     error = i2Cmd (m_i2c_lcd_control, 0x00); // Start 0
105     usleep (INIT_SLEEP);
106     error = i2Cmd (m_i2c_lcd_control, 0x5f); // End 95
107     usleep (INIT_SLEEP);
108
109     // Column Address
110     error = i2Cmd (m_i2c_lcd_control, 0x15); // Set Column Address
111     usleep (INIT_SLEEP);
112     error = i2Cmd (m_i2c_lcd_control, 0x08); // Start from 8th Column of driver IC. This is 0th Column for OLED
113     usleep (INIT_SLEEP);
114     error = i2Cmd (m_i2c_lcd_control, 0x37); // End at  (8 + 47)th column. Each Column has 2 pixels(segments)
115     usleep (INIT_SLEEP);
116
117     clear ();
118     setNormalDisplay ();
119     setVerticalMode ();
120 }
121
122 SSD1327::~SSD1327 () {
123
124 }
125
126 maa_result_t
127 SSD1327::draw (uint8_t *data, int bytes) {
128     maa_result_t error = MAA_SUCCESS;
129
130     setHorizontalMode ();
131     for (int row = 0; row < bytes; row++) {
132         for (uint8_t col = 0; col < 8; col+=2) {
133             uint8_t value = 0x0;
134
135             uint8_t bitOne = (data[row] << col) & 0x80;
136             uint8_t bitTwo = (data[row] << (col + 1)) & 0x80;
137
138             value |= (bitOne) ? grayHigh : 0x00;
139             value |= (bitTwo) ? grayLow : 0x00;
140
141             i2cData (m_i2c_lcd_control, value);
142             usleep (CMD_SLEEP - 2000);
143         }
144     }
145
146     return error;
147 }
148
149 /*
150  * **************
151  *  virtual area
152  * **************
153  */
154 maa_result_t
155 SSD1327::write (std::string msg) {
156     maa_result_t error = MAA_SUCCESS;
157
158     setVerticalMode ();
159     for (std::string::size_type i = 0; i < msg.size(); ++i) {
160         writeChar (m_i2c_lcd_control, msg[i]);
161     }
162
163     return error;
164 }
165
166 maa_result_t
167 SSD1327::setCursor (int row, int column) {
168     maa_result_t error = MAA_SUCCESS;
169
170     //Column Address
171     i2Cmd (m_i2c_lcd_control, 0x15);                /* Set Column Address */
172     usleep (CMD_SLEEP);
173     i2Cmd (m_i2c_lcd_control, 0x08 + (column * 4));  /* Start Column: Start from 8 */
174     usleep (CMD_SLEEP);
175     i2Cmd (m_i2c_lcd_control, 0x37);                /* End Column */
176     usleep (CMD_SLEEP);
177     // Row Address
178     i2Cmd (m_i2c_lcd_control, 0x75);                /* Set Row Address */
179     usleep (CMD_SLEEP);
180     i2Cmd (m_i2c_lcd_control, 0x00 + (row * 8));     /* Start Row*/
181     usleep (CMD_SLEEP);
182     i2Cmd (m_i2c_lcd_control, 0x07 + (row * 8));     /* End Row*/
183     usleep (CMD_SLEEP);
184
185     return error;
186 }
187
188 maa_result_t
189 SSD1327::clear () {
190     maa_result_t error = MAA_SUCCESS;
191     uint8_t columnIdx, rowIdx;
192
193     for(rowIdx = 0; rowIdx < 12; rowIdx++) {
194         // clear all columns
195         for(columnIdx = 0; columnIdx < 12; columnIdx++) {
196             writeChar (m_i2c_lcd_control, ' ');
197         }
198     }
199
200     return MAA_SUCCESS;
201 }
202
203 maa_result_t
204 SSD1327::home () {
205     return setCursor (0, 0);
206 }
207
208 maa_result_t
209 SSD1327::setGrayLevel (uint8_t level) {
210     grayHigh = (level << 4) & 0xF0;
211     grayLow  =  level & 0x0F;
212 }
213
214 /*
215  * **************
216  *  private area
217  * **************
218  */
219 maa_result_t
220 SSD1327::writeChar (maa_i2c_context ctx, uint8_t value) {
221     if (value < 0x20 || value > 0x7F) {
222         value = 0x20; // space
223     }
224
225     for (uint8_t row = 0; row < 8; row=row+2) {
226         for (uint8_t col = 0; col < 8; col++) {
227             uint8_t data = 0x0;
228
229             uint8_t bitOne = ((BasicFont[value - 32][row]) >> col) & 0x1;
230             uint8_t bitTwo = ((BasicFont[value - 32][row + 1]) >> col) & 0x1;
231
232             data |= (bitOne) ? grayHigh : 0x00;
233             data |= (bitTwo) ? grayLow : 0x00;
234
235             i2cData (m_i2c_lcd_control, data);
236             usleep (CMD_SLEEP - 2000);
237         }
238     }
239 }
240
241 maa_result_t
242 SSD1327::setNormalDisplay () {
243     return i2Cmd (m_i2c_lcd_control, DISPLAY_CMD_SET_NORMAL);    // set to normal display '1' is ON
244 }
245
246 maa_result_t
247 SSD1327::setHorizontalMode () {
248     i2Cmd (m_i2c_lcd_control, 0xA0); // remap to
249     usleep (CMD_SLEEP);
250     i2Cmd (m_i2c_lcd_control, 0x42); // horizontal mode
251     usleep (CMD_SLEEP);
252
253     // Row Address
254     i2Cmd (m_i2c_lcd_control, 0x75); // Set Row Address
255     usleep (CMD_SLEEP);
256     i2Cmd (m_i2c_lcd_control, 0x00); // Start 0
257     usleep (CMD_SLEEP);
258     i2Cmd (m_i2c_lcd_control, 0x5f); // End 95
259     usleep (CMD_SLEEP);
260
261     // Column Address
262     i2Cmd (m_i2c_lcd_control, 0x15); // Set Column Address
263     usleep (CMD_SLEEP);
264     i2Cmd (m_i2c_lcd_control, 0x08); // Start from 8th Column of driver IC. This is 0th Column for OLED
265     usleep (CMD_SLEEP);
266     i2Cmd (m_i2c_lcd_control, 0x37); // End at  (8 + 47)th column. Each Column has 2 pixels(or segments)
267     usleep (CMD_SLEEP);
268 }
269
270 maa_result_t
271 SSD1327::setVerticalMode () {
272     i2Cmd (m_i2c_lcd_control, 0xA0); // remap to
273     usleep (CMD_SLEEP);
274     i2Cmd (m_i2c_lcd_control, 0x46); // Vertical mode
275     usleep (CMD_SLEEP);
276 }