1/*
2 * Author: Marc Graham <marc@m2ag.net>
3 * Copyright (c) 2015 Intel Corporation
4 *
5 * Adapted from ssd1308 library.
6 * Author: Yevgeniy Kiveisha <yevgeniy.kiveisha@intel.com>
7 * Copyright (c) 2014 Intel Corporation.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining
10 * a copy of this software and associated documentation files (the
11 * "Software"), to deal in the Software without restriction, including
12 * without limitation the rights to use, copy, modify, merge, publish,
13 * distribute, sublicense, and/or sell copies of the Software, and to
14 * permit persons to whom the Software is furnished to do so, subject to
15 * the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be
18 * included in all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 */
28
29#pragma once
30
31#include <string>
32#include <mraa/i2c.hpp>
33#include "lcd.h"
34#include "ssd.h"
35
36namespace upm
37{
38const uint8_t  DISPLAY_CMD_SET_NORMAL_1306 = 0xA6;
39const uint8_t  SSD1306_SETCONTRAST = 0x81;
40const uint8_t  SSD1306_DISPLAYALLON_RESUME =0xA4;
41const uint8_t  SSD1306_DISPLAYALLON = 0xA5;
42const uint8_t  DISPLAY_CMD_SET_INVERT_1306 = 0xA7;
43
44const uint8_t  SSD1306_SETDISPLAYOFFSET =0xD3;
45const uint8_t  SSD1306_SETCOMPINS = 0xDA;
46
47const uint8_t  SSD1306_SETVCOMDETECT = 0xDB;
48
49const uint8_t  SSD1306_SETDISPLAYCLOCKDIV = 0xD5;
50const uint8_t  SSD1306_SETPRECHARGE = 0xD9;
51
52const uint8_t  SSD1306_SETMULTIPLEX = 0xA8;
53
54const uint8_t  SSD1306_SETLOWCOLUM = 0x00;
55const uint8_t  SSD1306_SETHIGHCOLUMN = 0x10;
56
57const uint8_t  SSD1306_SETSTARTLINE = 0x40;
58
59const uint8_t  SSD1306_MEMORYMODE = 0x20;
60const uint8_t  SSD1306_COLUMNADDR = 0x21;
61const uint8_t  SSD1306_PAGEADDR = 0x22;
62
63const uint8_t  SSD1306_COMSCANINC = 0xC0;
64const uint8_t  SSD1306_COMSCANDEC = 0xC8;
65
66const uint8_t  SSD1306_SEGREMAP = 0xA0;
67
68const uint8_t  SSD1306_CHARGEPUMP = 0x8D;
69
70const uint8_t  SSD1306_EXTERNALVCC = 0x1;
71const uint8_t  SSD1306_SWITCHCAPVCC = 0x2;
72
73// Scrolling const uint8_t s
74const uint8_t  SSD1306_ACTIVATE_SCROLL = 0x2F;
75const uint8_t  SSD1306_DEACTIVATE_SCROLL = 0x2E;
76const uint8_t  SSD1306_SET_VERTICAL_SCROLL_AREA = 0xA3;
77const uint8_t  SSD1306_RIGHT_HORIZONTAL_SCROLL = 0x26;
78const uint8_t  SSD1306_LEFT_HORIZONTAL_SCROLL = 0x27;
79const uint8_t  SSD1306_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL = 0x29;
80const uint8_t  SSD1306_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL = 0x2A;
81
82const uint8_t  SSD1306_BLACK = 0;
83const uint8_t  SSD1306_WHITE = 1;
84const uint8_t  SSD1306_LCDWIDTH = 128;
85const uint8_t  SSD1306_LCDHEIGHT = 64;
86
87/**
88 * @library i2clcd
89 * @sensor ssd1306
90 * @comname SSD1306 OLED Display
91 * @altname Adafruit SSD1306 OLED Display 0.96"
92 * @type display
93 * @man adafruit
94 * @web https://www.adafruit.com/datasheets/SSD1306.pdf
95 * @web http://www.farnell.com/datasheets/609753.pdf
96 * @con i2c
97 *
98 * @brief API for SSD1306 I2C-controlled OLED displays
99 *
100 * SSD1306 is a 128x64 dot-matrix OLED/PLED segment driver with a
101 * controller. This device is available from many suppliers for a
102 * very low cost. This implementation was tested using a generic
103 * SSD1306 device from eBay.
104 *
105 * @image html ssd1306.jpeg
106 * @snippet ssd1306-oled.cxx Interesting
107 */
108class SSD1306 : public LCD
109{
110  public:
111    /**
112     * SSD1306 constructor; calls libmraa initialisation functions
113     *
114     * @param bus I2C bus to use
115     * @param address Slave address the LCD is registered on
116     */
117    SSD1306(int bus, int address = 0x3C);
118    /**
119     * SSD1306 destructor
120     */
121    ~SSD1306();
122    /**
123     * Draws an image; see examples/python/make_oled_pic.py for an
124     * explanation of how pixels are mapped to bytes
125     *
126     * @param data Buffer to read
127     * @param bytes Number of bytes to read from the pointer
128     * @return Result of the operation
129     */
130    mraa::Result draw(uint8_t* data, int bytes);
131    /**
132     * Writes a string to the LCD
133     *
134     * @param msg std::string to write to the display; note: only ASCII
135     * characters are supported
136     * @return Result of the operation
137     */
138    mraa::Result write(std::string msg);
139    /**
140     * Sets the cursor to specified coordinates
141     *
142     * @param row Row to set the cursor to
143     * @param column Column to set the cursor to
144     * @return Result of the operation
145     */
146    mraa::Result setCursor(int row, int column);
147    /**
148     * Clears the display of all characters
149     *
150     * @return Result of the operation
151     */
152    mraa::Result clear();
153    /**
154     * Returns to the original coordinates (0,0)
155     *
156     * @return Result of the operation
157     */
158    mraa::Result home();
159    /**
160     * Inverts the display
161     *
162     * @param i true to invert, false for normal display
163     * @return Result of the operation
164     */
165    mraa::Result invert(bool i);
166    /**
167     *  Activate a scroll to the right for rows start through stop
168     *  The display is 16 rows tall. To scroll the whole display, run:
169     *  display.scrollright(0x00, 0x0F)
170     *
171     * @param start First row to scroll
172     * @param stop  Last row to scroll
173     * @return void
174     */
175    void startscrollright(uint8_t start, uint8_t stop);
176    /**
177     *  Activate a scroll to the left for rows start through stop
178     *  The display is 16 rows tall. To scroll the whole display, run:
179     *  display.startscrollright(0x00, 0x0F)
180     *
181     * @param start First row to scroll
182     * @param stop  Last row to scroll
183     * @return void
184     */
185    void startscrollleft(uint8_t start, uint8_t stop);
186    /**
187     *  Activate a scroll to the upper right for rows start through stop
188     *  The display is 16 rows tall. To scroll the whole display, run:
189     *  display.startscrollleft(0x00, 0x0F)
190     *
191     * @param start First row to scroll
192     * @param stop  Last row to scroll
193     * @return void
194     */
195    void startscrolldiagright(uint8_t start, uint8_t stop);
196    /**
197     *  Activate a scroll to the upper left for rows start through stop
198     *  The display is 16 rows tall. To scroll the whole display, run:
199     *  display.startscrolldiaagright(0x00, 0x0F)
200     *
201     * @param start First row to scroll
202     * @param stop  Last row to scroll
203     * @return void
204     */
205    void startscrolldiagleft(uint8_t start, uint8_t stop);
206    /**
207     * Stops display scrolling.
208     *
209     * @return void
210     */
211    void stopscroll(void);
212    /**
213     * Dims display
214     *
215     * @param dim True to dim display, false for max intensity
216     * @return Result of last operation
217     */
218    void dim(bool dim);
219
220  private:
221    mraa::Result writeChar(uint8_t value);
222    mraa::Result setNormalDisplay();
223    mraa::Result setAddressingMode(displayAddressingMode mode);
224
225    int m_lcd_control_address;
226    mraa::I2c m_i2c_lcd_control;
227
228    int _vccstate;
229};
230}
231