A TextDisplay driver that supports graphical displays using on of the SED133x conrtrolers. Allows stdout and stderr output to be redirected to the display.
Sed133xLCD.cpp
- Committer:
- llagendijk
- Date:
- 2011-01-29
- Revision:
- 6:2f8aed3d2be4
- Child:
- 7:d79600310cfe
File content as of revision 6:2f8aed3d2be4:
// 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(); }