A TextDisplay driver that supports graphical displays using on of the SED133x conrtrolers. Allows stdout and stderr output to be redirected to the display.

Revision:
6:2f8aed3d2be4
Child:
7:d79600310cfe
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Sed133xLCD.cpp	Sat Jan 29 20:48:08 2011 +0000
@@ -0,0 +1,424 @@
+// mbed sed1330LCD Library Base Class
+// Based on TextLCD (Copyright (c) 2007-2009 sford)
+// Released under the MIT License: http://mbed.org/license/mit
+// Author: louis Lagendijk
+//
+// Supports SED1330 (and probably the SED1335 and SED1336).
+// Based on datasheet 268-0.4
+//
+// This code drives the display using the 8080 interface:
+//      SEL1 = 0
+//      SEL2 = 0
+// These things require a lot of pins:
+// 8 bits for the databus +
+// *Reset (1)
+// *Read
+// *Write
+// *ChipSelect
+// A0
+//
+// Note(1): Reset is a Schmitt trigger input that can normally not be driven from
+// an MBED output pin. We just pull it high with  a 5k resistor feeding a 10uF elco
+// and the reset pin. This will reset the display once. Right now we do not use
+// the reset pin.
+//
+// Character sizes can be set as desired (default 6*8). The SED seems to use a
+// 5*7 font internally other font sizes use additional white space around the
+// characters.
+// Font widths of more than 8 pixels are not supported.
+// The actual size in characters is caluclated from the horizontal/ vertical
+// resolution and the specified font size.
+// Recommended fontsize = 6*9 or 6*10
+//
+#include "mbed.h"
+#include "Sed133xLCD.h"
+
+//
+//memory layout, datasheet shows 64kBit memory, 8 kByte * 8
+// text screen, reserve 2k
+//
+#define TEXT_SCREEN_START (int) 0
+// reserve one line of text extra as parts of it may be shown
+#define TEXT_SCREEN_SIZE (int) (_columns * (_rows + 1))
+#define TEXT_SCREEN_RESERVED (int) (2 * TEXT_SCREEN_SIZE)
+
+// Graphical screen, reserve 4kB, not used
+
+#define GRAPHICAL_SCREEN_START (int) (TEXT_SCREEN_START + TEXT_SCREEN_RESERVED)
+#define GRAPHICAL_SCREEN_SIZE  (int) (_hor_dots * _vert_dots / 8)
+#define GRAPHICAL_SCREEN_RESERVED (int) 0x1000
+
+// char. gen. RAM, take whatever is left, not used
+
+#define CG_RAM_START (int) (GRAPHICAL_SCREEN_START + GRAPHICAL_SCREEN_RESERVED)
+// reserve room for 32 chars * 8 lines of 8 dots, only 32 can be squeeed in
+#define CG_RAM_SIZE (int) (32 * 8 * 8)
+#define CG_RAM_RESERVED (int)(0x8000 - CG_RAM_START)
+
+
+commandName_t commandNameTab[] = {
+    { SYSTEM_SET, "System set" },
+    { SET_MEM, "Set memory" },
+    { GET_MEM, "Get memory" },
+    { SCROLL_SET, "Scroll set" },
+    { SET_CURSOR, "Set cursor" },
+    { GET_CURSOR, "Get cursor" },
+    { CURSOR_DIR_RIGHT, "Cursor right" },
+    { CURSOR_DIR_LEFT, "Cursor left" },
+    { CURSOR_DIR_UP, "Cursor up" },
+    { CURSOR_DIR_DOWN, "Cursor down" },
+    { SLEEP_IN, "Sleep in" },
+    { DISPLAY_OFF, "Display off" },
+    { DISPLAY_ON, "Display on" },
+    { HORIZONTAL_SCROLL_POSITION, "Horizontal scroll pos" },
+    { OVERLAY_FORMAT, "Display format" },
+    { CHAR_GEN_RAM_ADDR, "Char gen. ram address" },
+    { CURSOR_FORM, "Cursor form" },
+    { NO_COMMAND, ""}
+};
+
+char * Sed133xLCD::commandName(command_t command_val) {
+    int i;
+    for (i=0; commandNameTab[i].value != NO_COMMAND; i++) {
+        if (commandNameTab[i].value == command_val) {
+            return commandNameTab[i].text;
+        }
+    }
+    return NULL;
+}
+
+/* low level interface functions
+*/
+
+void Sed133xLCD::busWait() {
+    wait_us(0);
+}
+
+void Sed133xLCD::resetSed(void) {
+
+    /* send reset */
+    _reset = 1;
+    wait_ms(50);
+    _reset = 0;
+    /* initialize databus */
+
+    _dataBus.mode(PullNone);
+
+    /* initialize control pins */
+     _reset = 0;
+    _nRead = _nWrite  = 1;
+
+    /* wait for reset to complete */
+    wait_ms(50);
+}
+
+void Sed133xLCD::sendByte(dataType_t type, uint8_t data) {
+
+    /* sends one byte to the SED133X. A0 is set depending to the type of data
+       to be sent (data or command)
+     */
+    _addr0 = type;
+    _dataBus.output();
+    _dataBus = data;
+    Sed133xLCD::busWait();
+    _nSelect = 0;
+    _nWrite = 0;
+    Sed133xLCD::busWait();
+    _nWrite = 1;
+    _nSelect = 1;
+    Sed133xLCD::busWait();
+}
+
+void  Sed133xLCD::sendCommand(uint8_t data) {
+    sendByte(t_command, data);
+}
+
+void  Sed133xLCD::sendData(uint8_t data) {
+    sendByte(t_data, data);
+}
+
+uint8_t Sed133xLCD::getByte(dataType_t type) {
+
+    /* reads one byte from the SED133X. A0 is set according to the type of data
+       to be retrieved (data or command)
+      */
+
+    uint8_t data;
+
+    _addr0 = type;
+    _dataBus.input();
+    busWait();
+    _nRead = 0;
+    Sed133xLCD::busWait();
+    data = _dataBus;
+    _nRead = 1;
+    Sed133xLCD::busWait();
+    return data;
+}
+
+
+/* Send SED133x commands
+*/
+
+void Sed133xLCD::systemSet(void) {
+
+    sendCommand(SYSTEM_SET);
+
+    // p1
+    uint8_t M0 = 0;    // Internal char. generator
+    uint8_t M1 = 0;    // CGRAM1, 32 characters
+    uint8_t M2 = 0;    // 8 pixel character height
+    uint8_t WS = 0;    // single panel drive
+    uint8_t IV = 1;    // no top-line correction
+    uint8_t TL = 0;    // LCD mode
+    uint8_t DR = 0;    // normal operation (single panel)
+    sendData((DR << 7) | (TL << 6) | (IV  << 5) | (1 << 4) | (WS << 3) | (M2 << 2) | (M1 << 1) | M0);
+
+    // p2
+    uint8_t WF = 1;    // usually 1, 16 line AC drive
+    uint8_t FX = _char_width;
+    sendData((WF << 7) | (FX - 1));
+
+    // p3  FY: Char height
+    sendData(_char_height - 1);
+
+    // p4 CR: Bytes (not chars!) per line!
+    uint8_t CR = ((_columns -1) * (_char_width > 8 ? 2 : 1) );
+    sendData(CR);
+
+    // p5 TCR: length of line incl hor. blanking
+    sendData(CR + 4);
+
+    // LF, lines per frame
+    sendData(_vert_dots - 1);
+
+    // AP graphical display: size of a scan line
+    int AP =  ((_char_width > 8 ? 2 : 1) * (_columns));
+    sendData(AP & 0xff);
+    sendData(AP >> 8);
+}
+
+void Sed133xLCD::scrollSet(void) {
+
+    /* allocate Screen 1 at 0 */
+    int SA1 = TEXT_SCREEN_START;
+
+    /* Start of graphical screen  */
+    int SA2 = GRAPHICAL_SCREEN_START;
+
+    sendCommand(SCROLL_SET);
+    /* SAD 1 Low */
+    sendData(SA1 & 255);
+    /* SAD 1 high */
+    sendData(SA1 >> 8);
+    /* SL 1 */
+    sendData(_vert_dots -1);
+    /* SAD 2 low */
+    sendData( SA2 & 255);
+    /* SAD 2 high */
+    sendData( SA2 >> 8);
+    /* SL 2 */
+    sendData( _vert_dots -1);
+}
+
+void Sed133xLCD::horizontalScrollPosition(void) {
+
+    sendCommand(HORIZONTAL_SCROLL_POSITION);
+    sendData( 0x0);      /* no offset */
+}
+
+void Sed133xLCD::overlayFormat(void) {
+
+    sendCommand(OVERLAY_FORMAT);
+
+    int MX = 0;     /* 0 = logical OR between layers, 1 is exclusive OR */
+    int DM1 = 0;    /* Screen block 1: text mode */
+    int DM2 = 0;    /* screen block 3: text mode */
+    int OV = 0;     /* 2 layer compositioon */
+
+    sendData( (OV << 4) | (DM2 << 3) | (DM1 << 2) |MX);
+}
+
+void Sed133xLCD::cursorDirection(void) {
+    sendCommand(CURSOR_DIR_RIGHT);
+}
+
+void Sed133xLCD::cursorForm(void) {
+
+    sendCommand(CURSOR_FORM);
+
+    /* cursor width is uint8_twidth - 3 pixels */
+    sendData(_char_width - 3 - 1);
+
+    /* set block cursor as we are in graphical mode */
+    int CM = 1;
+
+    /* cursor vertical size 7 pixels */
+    int CRY = 7 - 1;
+
+    sendData( (CM << 7) | CRY);
+}
+
+void Sed133xLCD::displayOn(void) {
+
+    sendCommand(DISPLAY_ON);
+
+    /* flash cursor? */
+    uint8_t FC = 0; /* cursor off */
+
+    uint8_t layer1 = 1; /* on, no flashing */
+    uint8_t layer2 = 0; /* off */
+    uint8_t layer3 = 0; /* off */
+
+
+    sendData((layer3 << 6) | (layer2 << 4) | (layer1 << 2) | FC);
+}
+
+void Sed133xLCD::displayOff(void) {
+
+    sendCommand(DISPLAY_OFF);
+}
+
+void Sed133xLCD::charGenRamAddr(void) {
+    sendCommand(CHAR_GEN_RAM_ADDR);
+    sendData(CG_RAM_START & 255);
+    sendData(CG_RAM_START >> 8);
+}
+
+void Sed133xLCD::clsText(void) {
+    /**
+     * Clear text screen
+     */
+     
+    int i;
+    setCursor(TEXT_SCREEN_START);
+    sendCommand(SET_MEM);
+    for (i=0; i < TEXT_SCREEN_RESERVED; i++) {
+        sendData(' ');
+    }
+    setCursor(TEXT_SCREEN_START);
+}
+
+void Sed133xLCD::clsGraphics(void) {
+    /**
+     * clear graphics screen
+     */
+
+    int i;
+    setCursor(GRAPHICAL_SCREEN_START);
+    sendCommand(SET_MEM);
+    for (i=0; i < GRAPHICAL_SCREEN_RESERVED; i++) {
+        sendData(0);
+    }
+    setCursor(GRAPHICAL_SCREEN_START);
+}
+
+void Sed133xLCD::clearCharacterGeneratorRam(void) {
+    /**
+     * Clear character generator RAM
+     */
+     
+    int i;
+    setCursor(CG_RAM_START);
+    sendCommand(SET_MEM);
+    for (i=0; i < CG_RAM_SIZE; i++) {
+        sendData(0);
+    }
+    setCursor(TEXT_SCREEN_START);
+}
+
+void Sed133xLCD::printText(uint8_t *text) {
+    /* 
+     * write text to screen
+     */
+    int len = strlen((char*)text);
+    sendCommand(SET_MEM);
+    while (len > 0) {
+        sendData(text[len--]);
+    }
+}
+
+void Sed133xLCD::printData(int len, uint8_t*data) {
+    /* 
+     * write (binary) data to screen
+     */
+    sendCommand(SET_MEM);
+    while (len > 0) {
+        sendData(data[len--]);
+    }
+}
+
+void Sed133xLCD::setCursor(uint8_t column, uint8_t row) {
+    /**
+      * set cursor on text screen 
+      */
+    int pos = row * _columns + column;
+    sendCommand(SET_CURSOR);
+    sendData( pos & 255);
+    sendData( pos >> 8);
+}
+
+void Sed133xLCD::setCursor(int pos) {
+    /**
+     * set cursor on graphical screen 
+     */
+    sendCommand(SET_CURSOR);
+    sendData( pos & 255);
+    sendData( pos >> 8);
+}
+
+/**
+ * Public functions 
+ */
+ 
+ Sed133xLCD::Sed133xLCD(PinName reset, PinName nRead, PinName nWrite, PinName nSelect, PinName addr0,
+                       PinName d0, PinName d1, PinName d2, PinName d3,
+                       PinName d4, PinName d5, PinName d6, PinName d7,
+                       uint16_t hor_dots, uint16_t vert_dots,
+                       uint8_t char_width, uint8_t char_height,
+                       const char *name) :
+        TextDisplay(name),
+        _reset(reset), _nRead(nRead), _nWrite(nWrite), _nSelect(nSelect), _addr0(addr0),
+        _dataBus(d0, d1, d2, d3, d4, d5, d6, d7),
+        _hor_dots(hor_dots), _vert_dots(vert_dots),
+        _char_width(char_width), _char_height(char_height) {
+
+    // if we have at least 8 dots left we can squeeze in one more row
+    _rows = _vert_dots /_char_height + (((_vert_dots % _char_height) > 7) ? 1: 0);
+    _columns = _hor_dots / char_width;
+    initializeSed();
+}
+
+
+
+void Sed133xLCD::initializeSed(void) {
+    resetSed();
+    systemSet();
+    scrollSet();
+    horizontalScrollPosition();
+    overlayFormat();
+    cursorDirection();
+    clsText();
+    clsGraphics();
+    clearCharacterGeneratorRam();
+    cursorForm();
+    displayOn();
+    charGenRamAddr();
+}
+
+void Sed133xLCD::character(uint16_t column, uint16_t row, int c) {
+    /*
+     * Write character at specified position on screen
+     */
+     
+    // check for illegal input
+    if ( (column >= _columns) || (row >= _rows) )
+        return;
+    setCursor((char) column, (char)row);
+    sendCommand(SET_MEM);
+    sendData(c);
+}
+
+void Sed133xLCD::cls(void) {
+    clsText();
+}