1 /*
2  * Author: Jon Trulson <jtrulson@ics.com>
3  * Copyright (c) 2015 Intel Corporation.
4  *
5  * Author: Tyler Gibson <tgibson@microsoft.com>
6  * Copyright (c) 2015 Microsoft Corporation.
7  *
8  * Credits to Adafruit.
9  * Based on Adafruit ST7735 library, see original license in license.txt file.
10  *
11  * Permission is hereby granted, free of charge, to any person obtaining
12  * a copy of this software and associated documentation files (the
13  * "Software"), to deal in the Software without restriction, including
14  * without limitation the rights to use, copy, modify, merge, publish,
15  * distribute, sublicense, and/or sell copies of the Software, and to
16  * permit persons to whom the Software is furnished to do so, subject to
17  * the following conditions:
18  *
19  * The above copyright notice and this permission notice shall be
20  * included in all copies or substantial portions of the Software.
21  *
22  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29  */
30 #pragma once
31 
32 #include <string>
33 #include <mraa/spi.hpp>
34 
35 #include <mraa/gpio.hpp>
36 
37 #include "lcd.h"
38 #include "ssd.h"
39 
40 #define EBOLED_DEFAULT_SPI_BUS 0
41 #define EBOLED_DEFAULT_CD      36
42 #define EBOLED_DEFAULT_RESET   48
43 
44 #define swap(a, b) { uint8_t t = a; a = b; b = t; }
45 
46 namespace upm
47 {
48   /**
49    * @library i2clcd
50    * @sensor eboled
51    * @comname Sparkfun Edison Block OLED Display
52    * @altname ssd1306
53    * @type display
54    * @man sparkfun
55    * @web https://www.sparkfun.com/products/13035
56    * @con spi
57    *
58    * @brief API for EBOLED spi controlled OLED display
59    *
60    * The EBOLED is an ssd1306 with some modifications to work as an
61    * Edison Block.  It is a 64x48 pixel OLED display that connects
62    * directly to an edison via it's 80-pin connector.  Edison Blocks
63    * are stackable modules created by Sparkfun.
64    *
65    * This block has some buttons on it that can be accessed using
66    * standard GPIO -- this driver only concerns itself with the
67    * display.
68    *
69    * @snippet eboled.cxx Interesting
70    */
71 
72   const uint8_t COLOR_WHITE     = 0x01;
73   const uint8_t COLOR_BLACK     = 0x00;
74   const uint8_t COLOR_XOR       = 0x02;
75   const uint8_t OLED_WIDTH      = 0x40; // 64 pixels
76   const uint8_t VERT_COLUMNS    = 0x20; // half width for hi/lo 16bit writes.
77   const uint8_t OLED_HEIGHT     = 0x30; // 48 pixels
78   const int     BUFFER_SIZE     = 192;
79 
80   class EBOLED : public LCD
81   {
82     // SSD commands
83     typedef enum {
84       CMD_SETLOWCOLUMN          = 0x00,
85       CMD_EXTERNALVCC           = 0x01,
86       CMD_SWITCHCAPVCC          = 0x02,
87       CMD_SETHIGHCOLUMN         = 0x10,
88       CMD_MEMORYADDRMODE        = 0x20,
89       CMD_SETCOLUMNADDRESS      = 0x21,
90       CMD_SETPAGEADDRESS        = 0x22,
91       CMD_SETSTARTLINE          = 0x40, // 0x40 - 0x7f
92       CMD_SETCONTRAST           = 0x81,
93       CMD_CHARGEPUMP            = 0x8d,
94       CMD_SEGREMAP              = 0xa0,
95       CMD_DISPLAYALLONRESUME    = 0xa4,
96       CMD_DISPLAYALLON          = 0xa5,
97       CMD_NORMALDISPLAY         = 0xa6,
98       CMD_INVERTDISPLAY         = 0xa7,
99       CMD_SETMULTIPLEX          = 0xa8,
100       CMD_DISPLAYOFF            = 0xae,
101       CMD_DISPLAYON             = 0xaf,
102       CMD_SETPAGESTARTADDR      = 0xb0, // 0xb0-0xb7
103       CMD_COMSCANINC            = 0xc0,
104       CMD_COMSCANDEC            = 0xc8,
105       CMD_SETDISPLAYOFFSET      = 0xd3,
106       CMD_SETDISPLAYCLOCKDIV    = 0xd5,
107       CMD_SETPRECHARGE          = 0xd9,
108       CMD_SETCOMPINS            = 0xda,
109       CMD_SETVCOMDESELECT       = 0xdb
110     } SSD_CMDS_T;
111 
112   public:
113     /**
114      * EBOLED Constructor.  Note that you will not have any choice as
115      * to the pins used, so they are all set to default values.
116      *
117      * @param spi spi bus to use
118      * @param CD Command/Data select pin
119      * @param reset reset pin
120      * @param address the slave address the lcd is registered on
121      */
122     EBOLED(int spi=EBOLED_DEFAULT_SPI_BUS, int CD=EBOLED_DEFAULT_CD,
123            int reset=EBOLED_DEFAULT_RESET);
124 
125     /**
126      * EBOLED Destructor
127      */
128     ~EBOLED();
129 
130     /**
131      * Draw the buffer to screen, see examples/python/make_oled_pic.py for an
132      * explanation on how the pixels are mapped to bytes.
133      *
134      * @param data the buffer to write
135      * @param bytes the number of bytes to write
136      * @return result of operation
137      */
138     mraa::Result refresh();
139 
140     /**
141      * Write a string to LCD
142      *
143      * @param msg the std::string to write to display, note only ascii
144      * chars are supported
145      * @return result of operation
146      */
147     mraa::Result write(std::string msg);
148 
149     /**
150      * Set cursor to a coordinate
151      *
152      * @param y Axis on the vertical scale. This device supports 6 rows.
153      * @param x Axis on the horizontal scale This device supports 64 columns
154      *
155      * @return result of operation
156      */
157     mraa::Result setCursor (int row, int column);
158 
159     /**
160       * Sets a text color for a message
161       *
162       * @param textColor Font color: COLOR_WHITE, COLOR_BLACK or COLOR_XOR
163       */
164     void setTextColor (uint8_t textColor);
165 
166     /**
167       * Sets the size of the font
168       *
169       * @param size Font size
170       */
171     void setTextSize (uint8_t size);
172 
173     /**
174       * Wraps a printed message
175       *
176       * @param wrap True (1) or false (0)
177       */
178     void setTextWrap (uint8_t wrap);
179 
180     /**
181       * Write a single character to the screen.
182       *
183       * @param x Axis on the horizontal scale
184       * @param y Axis on the vertical scale
185       * @param data Character to write
186       * @param color Character color
187       * @param bg Character background color
188       * @param size Size of the font
189       */
190     void drawChar (uint8_t x, uint8_t y, uint8_t data, uint8_t color, uint8_t size);
191 
192     /**
193      * Clear display
194      *
195      * @return result of operation
196      */
197     mraa::Result clear();
198 
199     void clearScreenBuffer();
200 
201     /**
202      * Return to coordinate 0,0
203      *
204      * @return result of operation
205      */
206     mraa::Result home();
207 
208     /**
209      * Write a single pixel to the screen buffer.
210      * Can do an specific color write or toggle (xor) a pixel.
211      *
212      * @param x the x position of the pixel
213      * @param y the y position of the pixel
214      * @param color pixel is COLOR_WHITE, COLOR_BLACK or COLOR_XOR
215      */
216     void drawPixel (int8_t x, int8_t y, uint8_t color=COLOR_WHITE);
217 
218     /**
219      * Draw a line to the screen buffer.
220      *
221      * @param x0 the x position of the beginning of the line
222      * @param y0 the y position of the beginning of the line
223      * @param x1 the x position of the end of the line
224      * @param y1 the y position of the end of the line
225      * @param color line is COLOR_WHITE, COLOR_BLACK or COLOR_XOR
226      */
227     void drawLine (int8_t x0, int8_t y0, int8_t x1, int8_t y1, uint8_t color = COLOR_WHITE);
228 
229     /**
230      * Draw a horizontal line to the screen buffer.
231      *
232      * @param x the x position of the beginning of the line
233      * @param y the y position of the beginning of the line
234      * @param width is the horizontal length of the line
235      * @param color line is COLOR_WHITE, COLOR_BLACK or COLOR_XOR
236      */
237     void drawLineHorizontal (int8_t x, int8_t y, uint8_t width, uint8_t color = COLOR_WHITE);
238 
239     /**
240      * Draw a vertical line to the screen buffer.
241      *
242      * @param x the x position of the beginning of the line
243      * @param y the y position of the beginning of the line
244      * @param width is the vertical length of the line
245      * @param color line is COLOR_WHITE, COLOR_BLACK or COLOR_XOR
246      */
247     void drawLineVertical (int8_t x, int8_t y, uint8_t height, uint8_t color = COLOR_WHITE);
248 
249     /**
250      * Draw a rectangle to the screen buffer.
251      *
252      * @param x the left edge
253      * @param y the top edge
254      * @param width sets the right edge
255      * @param height bottom edge
256      * @param color outline is COLOR_WHITE, COLOR_BLACK or COLOR_XOR
257      */
258     void drawRectangle (int8_t x, int8_t y, uint8_t width, uint8_t height, uint8_t color = COLOR_WHITE);
259 
260     /**
261      * Draw a rectangle with rounded corners to the screen buffer.
262      *
263      * @param x the left edge
264      * @param y the top edge
265      * @param width sets the right edge
266      * @param height bottom edge
267      * @param radius of the rounded corners
268      * @param color outline is COLOR_WHITE, COLOR_BLACK or COLOR_XOR
269      */
270     void drawRoundedRectangle(int8_t x, int8_t y, int8_t width, int8_t height, int16_t radius, uint8_t color);
271 
272     /**
273      * Draw a filled rectangle to the screen buffer.
274      *
275      * @param x the left edge
276      * @param y the top edge
277      * @param width sets the right edge
278      * @param height bottom edge
279      * @param color fill color is COLOR_WHITE, COLOR_BLACK or COLOR_XOR
280      */
281     void drawRectangleFilled (int8_t x, int8_t y, uint8_t width, uint8_t height, uint8_t color = COLOR_WHITE);
282 
283     /**
284      * Draw a triangle to the screen buffer.
285      *
286      * @param x0 the x coordinate of the first corner
287      * @param y0 the y coordinate of the first corner
288      * @param x1 the x coordinate of the second corner
289      * @param y1 the y coordinate of the second corner
290      * @param x2 the x coordinate of the third corner
291      * @param y2 the y coordinate of the third corner
292      * @param color outline is COLOR_WHITE, COLOR_BLACK or COLOR_XOR
293      */
294     void drawTriangle (int8_t x0, int8_t y0, int8_t x1, int8_t y1, int8_t x2, int8_t y2, uint8_t color = COLOR_WHITE);
295 
296     /**
297      * Draw a filled triangle to the screen buffer.
298      *
299      * @param x0 the x coordinate of the first corner
300      * @param y0 the y coordinate of the first corner
301      * @param x1 the x coordinate of the second corner
302      * @param y1 the y coordinate of the second corner
303      * @param x2 the x coordinate of the third corner
304      * @param y2 the y coordinate of the third corner
305      * @param color fill color is COLOR_WHITE, COLOR_BLACK or COLOR_XOR
306      */
307     void drawTriangleFilled ( int8_t x0, int8_t y0, int8_t x1, int8_t y1, int8_t x2, int8_t y2, uint8_t color);
308 
309     /**
310      * Draw a circle to the screen buffer.
311      *
312      * @param x0 the x coordinate of the circle's center
313      * @param y0 the y coordinate of the circle's center
314      * @param radius the radius of the circle
315      * @param color outline is COLOR_WHITE, COLOR_BLACK or COLOR_XOR
316      */
317     void drawCircle (int16_t x0, int16_t y0, int16_t radius, uint8_t color = COLOR_WHITE);
318 
319     /**
320      * Draw a quarter circle arc to the screen buffer.
321      *
322      * @param x0 the x coordinate of the arc's center
323      * @param y0 the y coordinate of the arc's center
324      * @param radius the radius of the arc
325      * @param cornername denotes which of the 4 quarters to draw - 1,2,4,8
326      * @param color outline is COLOR_WHITE, COLOR_BLACK or COLOR_XOR
327      */
328     void drawRoundCorners( int8_t x0, int8_t y0, int16_t radius, uint8_t cornername, uint8_t color);
329 
330     /**
331      * Draw a filled circle to the screen buffer.
332      *
333      * @param x0 the x coordinate of the circle's center
334      * @param y0 the y coordinate of the circle's center
335      * @param radius the radius of the circle
336      * @param color outline is COLOR_WHITE, COLOR_BLACK or COLOR_XOR
337      */
338     void drawCircleFilled(int8_t x0, int8_t y0, int16_t radius, uint8_t color);
339 
340     /**
341      * Draw a quarter pie to the screen buffer.
342      *
343      * @param x0 the x coordinate of the arc's center
344      * @param y0 the y coordinate of the arc's center
345      * @param radius the radius of the arc
346      * @param cornername denotes which of the 4 quarters to draw - 1,2,4,8
347      * @param color fill color is COLOR_WHITE, COLOR_BLACK or COLOR_XOR
348      */
349     void drawRoundedCornersFilled(int8_t x0, int8_t y0, int16_t radius, uint8_t cornername, int16_t delta, uint8_t color);
350 
351     /**
352      * Fill the screen buffer with specified color.
353      *
354      * @param color fill color is COLOR_WHITE, COLOR_BLACK or COLOR_XOR
355      */
356     void fillScreen (uint8_t color=COLOR_WHITE);
357 
358 
359   protected:
360     mraa::Result command(uint8_t cmd);
361     mraa::Result data(uint16_t data);
362     mraa::Result writeChar(uint8_t value);
363     mraa::Result setAddressingMode(displayAddressingMode mode);
364 
365   private:
366     mraa::Gpio m_gpioCD;        // command(0)/data(1)
367     mraa::Gpio m_gpioRST;       // reset pin
368 
369     mraa::Spi m_spi;
370 
371     uint8_t m_cursorX;
372     uint8_t m_cursorY;
373     uint8_t m_textSize;
374     uint8_t m_textColor;
375     uint8_t m_textWrap;
376   };
377 }
378