Text console library for ST7565 graphics LCD controller over SPI interface.

Dependents:   TextLCD_ST7565SPI_Test OpPanel_Offline OpPanel_Offline_cmake_gcc_arm_NUCLEO_F303RENew

Revision:
0:1ea133b6a4de
Child:
1:a32310f5dab1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TextLCD_ST7565SPI.cpp	Mon Mar 02 23:10:13 2015 +0000
@@ -0,0 +1,334 @@
+// ==================================================== Mar 03 2015, kayeks ==
+// TextLCD_ST7565SPI.cpp
+// ===========================================================================
+// Text console library for ST7565 graphics LCD controller over SPI interface.
+
+#include <string.h>
+#include "TextLCD_ST7565SPI.h"
+
+const uint8_t TextLCD_ST7565SPI::FONT_5X7[128][5] = {
+    { 0x77, 0x55, 0x55, 0x55, 0x77 },  // unimplemented NUL
+    { 0x77, 0x52, 0x52, 0x52, 0x76 },  // unimplemented SOH
+    { 0x77, 0x54, 0x57, 0x51, 0x77 },  // unimplemented STX
+    { 0x77, 0x51, 0x56, 0x51, 0x77 },  // unimplemented ETX
+    { 0x71, 0x57, 0x55, 0x55, 0x71 },  // unimplemented EOT
+    { 0x77, 0x51, 0x57, 0x54, 0x77 },  // unimplemented ENQ
+    { 0x77, 0x55, 0x57, 0x54, 0x77 },  // unimplemented ACK
+    { 0x74, 0x54, 0x52, 0x51, 0x77 },  // unimplemented BEL
+    // 08h..0Fh
+    { 0x77, 0x55, 0x57, 0x55, 0x77 },  // unimplemented BS
+    { 0x77, 0x51, 0x57, 0x55, 0x77 },  // unimplemented HT
+    { 0x75, 0x57, 0x55, 0x55, 0x77 },  // unimplemented LF
+    { 0x77, 0x55, 0x55, 0x57, 0x74 },  // unimplemented VT
+    { 0x77, 0x54, 0x54, 0x54, 0x77 },  // unimplemented FF
+    { 0x77, 0x55, 0x55, 0x57, 0x71 },  // unimplemented CR
+    { 0x77, 0x54, 0x57, 0x54, 0x77 },  // unimplemented SO
+    { 0x74, 0x54, 0x57, 0x54, 0x77 },  // unimplemented SI
+    // 10h..17h
+    { 0x77, 0x25, 0x25, 0x25, 0x67 },  // unimplemented DLE
+    { 0x77, 0x22, 0x22, 0x22, 0x66 },  // unimplemented DC1
+    { 0x77, 0x24, 0x27, 0x21, 0x67 },  // unimplemented DC2
+    { 0x77, 0x21, 0x26, 0x21, 0x67 },  // unimplemented DC3
+    { 0x71, 0x27, 0x25, 0x25, 0x61 },  // unimplemented DC4
+    { 0x77, 0x21, 0x27, 0x24, 0x67 },  // unimplemented NAK
+    { 0x77, 0x25, 0x27, 0x24, 0x67 },  // unimplemented SYN
+    { 0x74, 0x24, 0x22, 0x21, 0x67 },  // unimplemented ETB
+    // 18h..1Fh
+    { 0x77, 0x25, 0x27, 0x25, 0x67 },  // unimplemented CAN
+    { 0x77, 0x21, 0x27, 0x25, 0x67 },  // unimplemented EM
+    { 0x75, 0x27, 0x25, 0x25, 0x67 },  // unimplemented SUB
+    { 0x77, 0x25, 0x25, 0x27, 0x64 },  // unimplemented ESC
+    { 0x77, 0x24, 0x24, 0x24, 0x67 },  // unimplemented FS
+    { 0x77, 0x25, 0x25, 0x27, 0x61 },  // unimplemented GS
+    { 0x77, 0x24, 0x27, 0x24, 0x67 },  // unimplemented RS
+    { 0x74, 0x24, 0x27, 0x24, 0x67 },  // unimplemented US  // 20h..27h
+    // 20h..27h
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },  // SPC
+    { 0x00, 0x00, 0x7d, 0x00, 0x00 },  // !
+    { 0x00, 0x60, 0x00, 0x60, 0x00 },  // "
+    { 0x22, 0x7f, 0x22, 0x7f, 0x22 },  // #
+    { 0x32, 0x49, 0x7f, 0x49, 0x26 },  // $
+    { 0x72, 0x54, 0x7f, 0x15, 0x27 },  // %
+    { 0x36, 0x49, 0x75, 0x02, 0x0d },  // &
+    { 0x00, 0x20, 0x40, 0x00, 0x00 },  // '
+    // 28h..2Fh
+    { 0x00, 0x00, 0x00, 0x3e, 0x41 },  // (
+    { 0x41, 0x3e, 0x00, 0x00, 0x00 },  // )
+    { 0x14, 0x08, 0x3e, 0x08, 0x14 },  // *
+    { 0x08, 0x08, 0x3e, 0x08, 0x08 },  // +
+    { 0x00, 0x01, 0x02, 0x00, 0x00 },  // ,
+    { 0x08, 0x08, 0x08, 0x08, 0x08 },  // -
+    { 0x00, 0x00, 0x01, 0x00, 0x00 },  // .
+    { 0x00, 0x03, 0x1c, 0x60, 0x00 },  // /
+    // 30h..37h
+    { 0x3e, 0x41, 0x49, 0x41, 0x3e },  // 0
+    { 0x00, 0x41, 0x7f, 0x01, 0x00 },  // 1
+    { 0x27, 0x49, 0x49, 0x49, 0x31 },  // 2
+    { 0x42, 0x41, 0x51, 0x51, 0x6e },  // 3
+    { 0x0e, 0x12, 0x22, 0x7f, 0x02 },  // 4
+    { 0x72, 0x51, 0x51, 0x51, 0x4e },  // 5
+    { 0x3e, 0x51, 0x51, 0x51, 0x0e },  // 6
+    { 0x40, 0x40, 0x47, 0x58, 0x60 },  // 7
+    // 38h..3Fh
+    { 0x36, 0x49, 0x49, 0x49, 0x36 },  // 8
+    { 0x38, 0x45, 0x45, 0x45, 0x3e },  // 9
+    { 0x00, 0x00, 0x12, 0x00, 0x00 },  // :
+    { 0x00, 0x01, 0x12, 0x00, 0x00 },  // ;
+    { 0x00, 0x08, 0x14, 0x22, 0x41 },  // <
+    { 0x14, 0x14, 0x14, 0x14, 0x14 },  // =
+    { 0x41, 0x22, 0x14, 0x08, 0x00 },  // >
+    { 0x20, 0x40, 0x45, 0x48, 0x30 },  // ?
+    // 40h..47h
+    { 0x3e, 0x41, 0x5d, 0x55, 0x3c },  // @
+    { 0x0f, 0x34, 0x44, 0x34, 0x0f },  // A
+    { 0x7f, 0x49, 0x49, 0x49, 0x36 },  // B
+    { 0x3e, 0x41, 0x41, 0x41, 0x22 },  // C
+    { 0x7f, 0x41, 0x41, 0x41, 0x3e },  // D
+    { 0x7f, 0x49, 0x49, 0x49, 0x41 },  // E
+    { 0x7f, 0x48, 0x48, 0x48, 0x40 },  // F
+    { 0x3e, 0x41, 0x49, 0x49, 0x2e },  // G
+    // 48h..4Fh
+    { 0x7f, 0x08, 0x08, 0x08, 0x7f },  // H
+    { 0x00, 0x41, 0x7f, 0x41, 0x00 },  // I
+    { 0x02, 0x01, 0x01, 0x41, 0x7e },  // J
+    { 0x7f, 0x08, 0x14, 0x22, 0x41 },  // K
+    { 0x7f, 0x01, 0x01, 0x01, 0x01 },  // L
+    { 0x7f, 0x20, 0x1c, 0x20, 0x7f },  // M
+    { 0x7f, 0x20, 0x10, 0x08, 0x7f },  // N
+    { 0x3e, 0x41, 0x41, 0x41, 0x3e },  // O
+    // 50h..57h
+    { 0x7f, 0x48, 0x48, 0x48, 0x30 },  // P
+    { 0x3e, 0x41, 0x45, 0x42, 0x3d },  // Q
+    { 0x7f, 0x48, 0x4c, 0x4a, 0x31 },  // R
+    { 0x32, 0x49, 0x49, 0x49, 0x26 },  // S
+    { 0x40, 0x40, 0x7f, 0x40, 0x40 },  // T
+    { 0x7e, 0x01, 0x01, 0x01, 0x7e },  // U
+    { 0x78, 0x06, 0x01, 0x06, 0x78 },  // V
+    { 0x7e, 0x01, 0x1e, 0x01, 0x7e },  // W
+    // 58h..5Fh
+    { 0x63, 0x14, 0x08, 0x14, 0x63 },  // X
+    { 0x60, 0x10, 0x0f, 0x10, 0x60 },  // Y
+    { 0x43, 0x45, 0x49, 0x51, 0x61 },  // Z
+    { 0x00, 0x00, 0x00, 0x7f, 0x41 },  // [
+    { 0x00, 0x60, 0x1c, 0x03, 0x00 },  // backslash
+    { 0x41, 0x7f, 0x00, 0x00, 0x00 },  // ]
+    { 0x00, 0x20, 0x40, 0x20, 0x00 },  // ^
+    { 0x01, 0x01, 0x01, 0x01, 0x01 },  // _
+    // 60h..67h
+    { 0x00, 0x00, 0x40, 0x20, 0x00 },  // `
+    { 0x02, 0x15, 0x15, 0x15, 0x0f },  // a
+    { 0x7f, 0x11, 0x11, 0x11, 0x0e },  // b
+    { 0x0e, 0x11, 0x11, 0x11, 0x0a },  // c
+    { 0x0e, 0x11, 0x11, 0x11, 0x7f },  // d
+    { 0x0e, 0x15, 0x15, 0x15, 0x0c },  // e
+    { 0x00, 0x08, 0x3f, 0x48, 0x48 },  // f
+    { 0x08, 0x15, 0x15, 0x15, 0x1e },  // g
+    // 68h..6Fh
+    { 0x7f, 0x10, 0x10, 0x10, 0x0f },  // h
+    { 0x00, 0x10, 0x5f, 0x00, 0x00 },  // i
+    { 0x01, 0x11, 0x5e, 0x00, 0x00 },  // j
+    { 0x00, 0x7f, 0x04, 0x0a, 0x11 },  // k
+    { 0x00, 0x40, 0x7f, 0x00, 0x00 },  // l
+    { 0x1f, 0x10, 0x1f, 0x10, 0x0f },  // m
+    { 0x1f, 0x10, 0x10, 0x10, 0x0f },  // n
+    { 0x0e, 0x11, 0x11, 0x11, 0x0e },  // o
+    // 70h..77h
+    { 0x1f, 0x12, 0x12, 0x12, 0x0c },  // p
+    { 0x0c, 0x12, 0x12, 0x12, 0x1f },  // q
+    { 0x1f, 0x08, 0x10, 0x10, 0x10 },  // r
+    { 0x09, 0x15, 0x15, 0x15, 0x12 },  // s
+    { 0x00, 0x3e, 0x11, 0x11, 0x00 },  // t
+    { 0x1e, 0x01, 0x01, 0x01, 0x1f },  // u
+    { 0x18, 0x06, 0x01, 0x06, 0x18 },  // v
+    { 0x1e, 0x01, 0x0e, 0x01, 0x1e },  // w
+    // 78h..7Fh
+    { 0x11, 0x0a, 0x04, 0x0a, 0x11 },  // x
+    { 0x18, 0x05, 0x05, 0x05, 0x1e },  // y
+    { 0x11, 0x13, 0x15, 0x19, 0x11 },  // z
+    { 0x00, 0x00, 0x08, 0x7f, 0x41 },  // {
+    { 0x00, 0x00, 0x7f, 0x00, 0x00 },  // |
+    { 0x41, 0x7f, 0x08, 0x00, 0x00 },  // }
+    { 0x08, 0x10, 0x18, 0x08, 0x10 },  // ~ 
+    { 0x44, 0x44, 0x77, 0x44, 0x77 }   // unimplemented DEL
+};
+
+TextLCD_ST7565SPI::TextLCD_ST7565SPI(PinName mosi, PinName sck, PinName cs,
+                                     PinName rs, PinName rst,
+                                     uint8_t columns, uint8_t rows)
+:
+    _rs(rs),
+    _rst(rst),
+    _spi(mosi, NC, sck),
+    _cs(cs)
+{
+    // Allocate line buffer
+    _columns = columns;
+    _rows = rows;
+    _lineBuffer = new uint8_t*[_rows];
+    for (uint8_t i = 0; i < _rows; i++) {
+        _lineBuffer[i] = new uint8_t[_columns];
+    }
+    
+    // Initialize SPI
+    _spi.format(8, 0);
+    
+    // Initialize pins
+    _rs = 0;
+    _rst = 1;
+    _cs = 1;
+    
+    reset();
+}
+
+TextLCD_ST7565SPI::~TextLCD_ST7565SPI() {
+    for (uint8_t i = 0; i < _rows; i++) {
+        delete[] _lineBuffer[i];
+    }
+    delete[] _lineBuffer;
+}
+
+void TextLCD_ST7565SPI::reset() {
+    wait_ms(10);
+    _rst = 0;
+    wait_ms(10);
+    _rst = 1;
+}
+
+void TextLCD_ST7565SPI::clear() {
+    for (uint8_t j = 7; j <= 7; j--) {
+        setPage(j);
+        setColumn(0);
+        for (uint8_t i = 0; i < 132; i++) {
+            data(0x00);
+        }
+    }
+}
+
+void TextLCD_ST7565SPI::init(uint8_t v0, uint8_t contrast, Bias bias) {
+    command(INTERNAL_RESET);
+    wait_ms(5);
+    
+    command(DISPLAY_ON);
+    command(PCTRL_BOOSTER_ON | PCTRL_REGULATOR_ON | PCTRL_VFOLLOWER_ON);
+    command(V0_INTERNAL_R_0 + (v0 & 0x07));
+    command(ELECTRONIC_VOL_MODE);
+    if (contrast == 0) {
+        contrast = 1;
+    }
+    command(ELECTRONIC_VOL_1 - 1 + (contrast & 0x3f));
+    switch (bias) {
+    case Bias1_7:
+        command(BIAS_1_7);
+        break;
+    case Bias1_9:
+        command(BIAS_1_9);
+    }
+    command(COMMON_ASCENDING);
+    command(SEGMENT_ASCENDING);
+    command(ENTIRE_DISPLAY_OFF);
+    command(INVERT_DISPLAY_OFF);
+    command(COMMON_OFFSET);
+    cls();
+}
+
+void TextLCD_ST7565SPI::cls() {
+    clear();
+    for (uint8_t j = 0; j < _rows; j++) {
+        memset(_lineBuffer[j], ' ', _columns);
+    }
+    _column = 0;
+    _row = 0;
+}
+
+void TextLCD_ST7565SPI::locate(uint8_t column, uint8_t row) {
+    if (column < _columns && row < _rows) {
+        setPage(_rows - row - 1);
+        setColumn(6 * column);
+        _column = column;
+        _row = row;
+    }
+}
+
+int TextLCD_ST7565SPI::_putc(int c) {
+    switch (c) {
+    case '\r':  // Carriage return
+        _column = 0;
+        locate(_column, _row);
+        break;
+    case '\n':  // Line feed
+        if (_row == _rows - 1) {
+            shiftUp();
+        } else {
+            _row++;
+        }
+        break;
+    default:
+        // Break line if the cursor reaches end
+        if (_column == _columns) {
+            if (_row == _rows - 1) {
+                shiftUp();
+            } else {
+                _row++;
+            }
+            _column = 0;
+        }
+        locate(_column, _row);
+        for (uint8_t k = 0; k < 5; k++) {
+            data(FONT_5X7[c][k]);
+        }
+        data(0x00);
+        _lineBuffer[_row][_column] = c;
+        _column++;
+        break;
+    }
+    return 0;
+}
+
+int TextLCD_ST7565SPI::_getc() {
+    return 0;
+}
+
+void TextLCD_ST7565SPI::shiftUp() {
+    // Move line buffer content
+    for (uint8_t j = 0; j < _rows - 1; j++) {
+        memcpy(_lineBuffer[j], _lineBuffer[j + 1], _columns);
+    }
+    // Clear last line
+    memset(_lineBuffer[_rows - 1], ' ', _columns);
+    
+    // Redraw
+    for (uint8_t j = 0; j < _rows; j++) {
+        locate(0, j);
+        for (uint8_t i = 0; i < _columns; i++) {
+            for (uint8_t k = 0; k < 5; k++) {
+                data(FONT_5X7[_lineBuffer[j][i]][k]);
+            }
+            data(0x00);
+        }
+    }
+}
+
+void TextLCD_ST7565SPI::setPage(uint8_t page) {
+    if (page < 16) {
+        command(0xb0 | page);
+    }
+}
+
+void TextLCD_ST7565SPI::setColumn(uint8_t column) {
+    command(0x10 | (column >> 4));
+    command(column & 0x0f);
+}
+
+void TextLCD_ST7565SPI::command(uint8_t c) {
+    _rs = 0;
+    _cs = 0;
+    _spi.write(c);
+    _cs = 1;
+}
+
+void TextLCD_ST7565SPI::data(uint8_t d) {
+    _rs = 1;
+    _cs = 0;
+    _spi.write(d);
+    _cs = 1;
+}