1 /* Arduino SSD1306Ascii Library
2 * Copyright (C) 2015 by William Greiman
4 * This file is part of the Arduino SSD1306Ascii Library
6 * This Library is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This Library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with the Arduino SSD1306Ascii Library. If not, see
18 * <http://www.gnu.org/licenses/>.
20 #include "SSD1306Ascii.h"
21 //------------------------------------------------------------------------------
22 uint8_t SSD1306Ascii::charWidth(uint8_t c
) const {
26 uint8_t first
= readFontByte(m_font
+ FONT_FIRST_CHAR
);
27 uint8_t count
= readFontByte(m_font
+ FONT_CHAR_COUNT
);
28 if (c
< first
|| c
>= (first
+ count
)) {
33 return m_magFactor
*readFontByte(m_font
+ FONT_WIDTH_TABLE
+ c
- first
);
36 return m_magFactor
*readFontByte(m_font
+ FONT_WIDTH
);
38 //------------------------------------------------------------------------------
39 void SSD1306Ascii::clear() {
43 #endif // INCLUDE_SCROLLING
44 clear(0, displayWidth() - 1, 0 , displayRows() - 1);
46 //------------------------------------------------------------------------------
47 void SSD1306Ascii::clear(uint8_t c0
, uint8_t c1
, uint8_t r0
, uint8_t r1
) {
48 if (r1
>= displayRows()) r1
= displayRows() - 1;
49 for (uint8_t r
= r0
; r
<= r1
; r
++) {
51 for (uint8_t c
= c0
; c
<= c1
; c
++) {
52 // Insure clear() writes zero. result is (m_invertMask^m_invertMask).
53 ssd1306WriteRamBuf(m_invertMask
);
58 //------------------------------------------------------------------------------
59 void SSD1306Ascii::clearToEOL() {
60 clear(m_col
, displayWidth() -1, m_row
, m_row
+ fontRows() - 1);
62 //------------------------------------------------------------------------------
63 void SSD1306Ascii::clearField(uint8_t col
, uint8_t row
, uint8_t n
) {
64 clear(col
, col
+ fieldWidth(n
) - 1, row
, row
+ fontRows() - 1);
66 //------------------------------------------------------------------------------
67 void SSD1306Ascii::displayRemap(bool mode
) {
68 ssd1306WriteCmd(mode
? SSD1306_SEGREMAP
: SSD1306_SEGREMAP
| 1);
69 ssd1306WriteCmd(mode
? SSD1306_COMSCANINC
: SSD1306_COMSCANDEC
);
71 //------------------------------------------------------------------------------
72 size_t SSD1306Ascii::fieldWidth(uint8_t n
) {
73 return n
*(fontWidth() + letterSpacing());
75 //------------------------------------------------------------------------------
76 uint8_t SSD1306Ascii::fontCharCount() const {
77 return m_font
? readFontByte(m_font
+ FONT_CHAR_COUNT
) : 0;
79 //------------------------------------------------------------------------------
80 char SSD1306Ascii::fontFirstChar() const {
81 return m_font
? readFontByte(m_font
+ FONT_FIRST_CHAR
) : 0;
83 //------------------------------------------------------------------------------
84 uint8_t SSD1306Ascii::fontHeight() const {
85 return m_font
? m_magFactor
*readFontByte(m_font
+ FONT_HEIGHT
) : 0;
87 //------------------------------------------------------------------------------
88 uint8_t SSD1306Ascii::fontRows() const {
89 return m_font
? m_magFactor
*((readFontByte(m_font
+ FONT_HEIGHT
) + 7)/8) : 0;
91 //------------------------------------------------------------------------------
92 uint16_t SSD1306Ascii::fontSize() const {
93 return (readFontByte(m_font
) << 8) | readFontByte(m_font
+ 1);
95 //------------------------------------------------------------------------------
96 uint8_t SSD1306Ascii::fontWidth() const {
97 return m_font
? m_magFactor
*readFontByte(m_font
+ FONT_WIDTH
) : 0;
99 //------------------------------------------------------------------------------
100 void SSD1306Ascii::init(const DevType
* dev
) {
104 const uint8_t* table
= (const uint8_t*)pgm_read_word(&dev
->initcmds
);
106 const uint8_t* table
= dev
->initcmds
;
108 uint8_t size
= readFontByte(&dev
->initSize
);
109 m_displayWidth
= readFontByte(&dev
->lcdWidth
);
110 m_displayHeight
= readFontByte(&dev
->lcdHeight
);
111 m_colOffset
= readFontByte(&dev
->colOffset
);
112 for (uint8_t i
= 0; i
< size
; i
++) {
113 ssd1306WriteCmd(readFontByte(table
+ i
));
117 //------------------------------------------------------------------------------
118 void SSD1306Ascii::invertDisplay(bool invert
) {
119 ssd1306WriteCmd(invert
? SSD1306_INVERTDISPLAY
: SSD1306_NORMALDISPLAY
);
121 //------------------------------------------------------------------------------
122 void SSD1306Ascii::setCol(uint8_t col
) {
123 if (col
>= m_displayWidth
) return;
126 ssd1306WriteCmd(SSD1306_SETLOWCOLUMN
| (col
& 0XF));
127 ssd1306WriteCmd(SSD1306_SETHIGHCOLUMN
| (col
>> 4));
129 //------------------------------------------------------------------------------
130 void SSD1306Ascii::setContrast(uint8_t value
) {
131 ssd1306WriteCmd(SSD1306_SETCONTRAST
);
132 ssd1306WriteCmd(value
);
134 //------------------------------------------------------------------------------
135 void SSD1306Ascii::setCursor(uint8_t col
, uint8_t row
) {
139 //------------------------------------------------------------------------------
140 void SSD1306Ascii::setFont(const uint8_t* font
) {
142 if (font
&& fontSize() == 1) {
148 //------------------------------------------------------------------------------
149 void SSD1306Ascii::setRow(uint8_t row
) {
150 if (row
>= displayRows()) {
154 #if INCLUDE_SCROLLING
155 ssd1306WriteCmd(SSD1306_SETSTARTPAGE
| ((m_row
+ m_pageOffset
) & 7));
156 #else // INCLUDE_SCROLLING
157 ssd1306WriteCmd(SSD1306_SETSTARTPAGE
| m_row
);
158 #endif // INCLUDE_SCROLLING
160 #if INCLUDE_SCROLLING
161 //------------------------------------------------------------------------------
162 void SSD1306Ascii::setPageOffset(uint8_t page
) {
163 m_pageOffset
= page
& 7;
166 //------------------------------------------------------------------------------
167 void SSD1306Ascii::setStartLine(uint8_t line
) {
168 m_startLine
= line
& 0X3F;
169 ssd1306WriteCmd(SSD1306_SETSTARTLINE
| m_startLine
);
171 #endif // INCLUDE_SCROLLING
172 //-----------------------------------------------------------------------------
173 void SSD1306Ascii::ssd1306WriteRam(uint8_t c
) {
174 if (m_col
>= m_displayWidth
) return;
175 writeDisplay(c
^m_invertMask
, SSD1306_MODE_RAM
);
178 //-----------------------------------------------------------------------------
179 void SSD1306Ascii::ssd1306WriteRamBuf(uint8_t c
) {
180 if (m_col
>= m_displayWidth
) return;
181 writeDisplay(c
^m_invertMask
, SSD1306_MODE_RAM_BUF
);
184 //------------------------------------------------------------------------------
185 GLCDFONTDECL(scaledNibble
) = {
186 0X00, 0X03, 0X0C, 0X0F,
187 0X30, 0X33, 0X3C, 0X3F,
188 0XC0, 0XC3, 0XCC, 0XCF,
189 0XF0, 0XF3, 0XFC, 0XFF
191 //------------------------------------------------------------------------------
192 size_t SSD1306Ascii::strWidth(const char* str
) const {
195 uint8_t cw
= charWidth(*str
++);
199 sw
+= cw
+ letterSpacing();
203 //------------------------------------------------------------------------------
204 size_t SSD1306Ascii::write(uint8_t ch
) {
208 uint8_t w
= readFontByte(m_font
+ FONT_WIDTH
);
209 uint8_t h
= readFontByte(m_font
+ FONT_HEIGHT
);
210 uint8_t nr
= (h
+ 7)/8;
211 uint8_t first
= readFontByte(m_font
+ FONT_FIRST_CHAR
);
212 uint8_t count
= readFontByte(m_font
+ FONT_CHAR_COUNT
);
213 const uint8_t* base
= m_font
+ FONT_WIDTH_TABLE
;
215 if (ch
< first
|| ch
>= (first
+ count
)) {
222 uint8_t fr
= m_magFactor
*nr
;
223 #if INCLUDE_SCROLLING
224 uint8_t dr
= displayRows();
225 uint8_t tmpRow
= m_row
+ fr
;
226 int8_t delta
= tmpRow
+ fr
- dr
;
227 if (m_scrollMode
== SCROLL_MODE_OFF
|| delta
<= 0) {
230 m_pageOffset
= (m_pageOffset
+ delta
) & 7;
232 // Cursor will be positioned by clearToEOL.
234 if (m_scrollMode
== SCROLL_MODE_AUTO
) {
235 setStartLine(8*m_pageOffset
);
238 #else // INCLUDE_SCROLLING
240 #endif // INCLUDE_SCROLLING
246 uint8_t s
= letterSpacing();
247 uint8_t thieleShift
= 0;
248 if (fontSize() < 2) {
253 thieleShift
= 8 - (h
& 7);
256 for (uint8_t i
= 0; i
< ch
; i
++) {
257 index
+= readFontByte(base
+ i
);
259 w
= readFontByte(base
+ ch
);
260 base
+= nr
*index
+ count
;
262 uint8_t scol
= m_col
;
263 uint8_t srow
= m_row
;
264 for (uint8_t r
= 0; r
< nr
; r
++) {
265 for (uint8_t m
= 0; m
< m_magFactor
; m
++) {
266 if (r
|| m
) setCursor(scol
, m_row
+ 1);
267 for (uint8_t c
= 0; c
< w
; c
++) {
268 uint8_t b
= readFontByte(base
+ c
+ r
*w
);
269 if (thieleShift
&& (r
+ 1) == nr
) {
272 if (m_magFactor
== 2) {
273 b
= m
? b
>> 4 : b
& 0XF;
274 b
= readFontByte(scaledNibble
+ b
);
275 ssd1306WriteRamBuf(b
);
277 ssd1306WriteRamBuf(b
);
279 for (uint8_t i
= 0; i
< s
; i
++) {
280 ssd1306WriteRamBuf(0);