A TextDisplay driver that supports graphical displays using on of the SED133x conrtrolers. Allows stdout and stderr output to be redirected to the display.
Diff: Sed133xLCD.cpp
- Revision:
- 6:2f8aed3d2be4
- Child:
- 7:d79600310cfe
diff -r 684f79f70ac9 -r 2f8aed3d2be4 Sed133xLCD.cpp --- /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(); +}