Simon Blandford
/
OLEDSeps525f
OLEDSeps525f/OLEDSeps525f.cpp
- Committer:
- simonb
- Date:
- 2010-01-12
- Revision:
- 0:a136481b0662
File content as of revision 0:a136481b0662:
/* mbed Library - OLEDSeps525f * Copyright (c) 2010, sblandford * Based on MobileLCD library * Copyright (c) 2007/8, sford * released under MIT license http://mbed.org/licence/mit */ #include "OLEDSeps525f.h" #include "mbed.h" //Serial pc1(USBTX, USBRX); // tx, rx using namespace mbed; OLEDSeps525f::OLEDSeps525f(PinName mosi, PinName miso, PinName clk, PinName cs, PinName rst, PinName rs) : _spi(mosi, miso, clk) , _cs(cs) , _rst(rst) , _rs(rs) { _row = 0; _column = 0; _width = _physical_width; _height = _physical_height; _rotation = 0; _columns = _width/8; _rows = _height/8; _tablength = 4; _writing_pixels = 0; foreground(0x00FFFFFF); background(0x00000000); reset(); } void OLEDSeps525f::reset() { unsigned int i=0,j,k; const unsigned char init_commands[]= { 0x06, // Display off 0x00, //Osc control //Export1 internal clock and OSC operates with external resistor 0x02, 0x01, //Reduce current 0x04, 0x00, //Clock div ratio 1: freq setting 90Hz 0x03, 0x30, //Iref controlled by external resistor 0x80, 0x00, //Precharge time R 0x08, 0x01, //Precharge time G 0x09, 0x01, //Precharge time B 0x0A, 0x01, //Precharge current R 0x0B, 0x0A, //Precharge current G 0x0C, 0x0A, //Precharge current B 0x0D, 0x0A, //Driving current R = 82uA 0x10, 0x52, //Driving current G = 56uA 0x11, 0x38, //Driving current B = 58uA 0x12, 0x3A, //Display mode set //RGB,column=0-159, column data display=Normal display 0x13, 0x00, //External interface mode=MPU 0x14, 0x01, //Memory write mode //6 bits triple transfer, 262K support, Horizontal address counter is increased, //vertical address counter is increased. The data is continuously written //horizontally 0x16, 0x76, //Memory address setting range 0x17~0x19 to width x height 0x17, //Column start 0x00, 0x18, //Column end _physical_width-1, 0x19, //row start 0x00, 0x1A, //row end _physical_height-1, //Memory start address set to 0x20~0x21 0x20, //X 0x00, 0x21, //Y 0x00, //Duty 0x29, 0x00, //Display start line 0x29, 0x00, //DDRAM read address start point 0x2E~0x2F 0x2E, //X 0x00, 0x2F, //Y 0x00, //Display screen saver size 0x33~0x36 0x33, //Screen saver columns start 0x00, 0x34, //Screen saver columns end _physical_width-1, 0x35, //screen saver row start 0x00, 0x36, //Screen saver row end _physical_height-1, //Display ON 0x06, 0x01, //End of commands 0xFF, 0xFF }; //Initialize interface and reset display driver chip _cs = 1; wait(0.01); _rst = 0; wait(0.001); _rst = 1; wait(0.01); _spi.format(8); _spi.frequency(10000000); //Send initialization commands for (i=0; ;i+=2) { j=(int)init_commands[i]; k=(int)init_commands[i+1]; if ((j==0xFF) && (k==0xFF)) break; command(j); data(k); } } void OLEDSeps525f::command(int value) { _writing_pixels=(value == 0x22); _rs = 0; _cs = 0; _spi.write(value); _cs = 1; _rs = 1; } void OLEDSeps525f::data(int value) { _rs = 1; _cs = 0; _spi.write(value); _cs = 1; } inline void OLEDSeps525f::rgbdot(int r, int g, int b) { _rs = 1; _cs = 0; _spi.write(r); _cs = 1; _cs = 0; _spi.write(g); _cs = 1; _cs = 0; _spi.write(b); _cs = 1; } void OLEDSeps525f::_window(int x, int y, int width, int height) { int x1, x2, y1, y2, start_x, start_y; switch (_rotation) { default: case 0: x1 = x; y1 = y; x2 = x + width - 1; y2 = y + height - 1; break; case 1: x1 = _physical_width - y - height; y1 = x; x2 = _physical_width - y - 1; y2 = x + width - 1; break; case 2: x1= _physical_width - x - width; y1= _physical_height - y - height; x2= _physical_width - x - 1; y2= _physical_height - y - 1; break; case 3: x1 = y; y1 = _physical_height - x - width; x2 = y + height - 1; y2 = _physical_height - x - 1; break; } //Limit values if (x1 < 0) x1=0; if (x1 >= _physical_width) x1=_physical_width-1; if (x2 < 0) x2=0; if (x2 >= _physical_width) x2=_physical_width-1; if (y1 < 0) y1=0; if (y1 >= _physical_height) y1=_physical_height-1; if (y2 < 0) y2=0; if (y2 >= _physical_height) y2=_physical_height-1; /* if ((width > 100) || (height > 100)) { pc1.printf("x=%d\ty=%d\twidth=%d\theight=%d\tx1=%d\tx2=%d\ty1=%d\ty2=%d\n",x,y,width,height,x1,x2,y1,y2); } */ command(0x19); // Y start data(y1); command(0x1A); // Y end data(y2); command(0x17); // X start data(x1); command(0x18); // x end data(x2); switch (_rotation) { default: case 0: start_x=x1; start_y=y1; break; case 1: start_x=x1; start_y=y2; break; case 2: start_x=x2; start_y=y2; break; case 3: start_x=x2; start_y=y1; break; } command(0x20); // memory accesspointer x data(start_x); command(0x21); // memory accesspointer y data(start_y); } inline void OLEDSeps525f::_putp(int colour) { static int colour_prev=0xF000000, r=0, g=0, b=0; //Start "write data" command if not done already if ( ! _writing_pixels ) { command(0x22); } //Only calculate rgb values if colour has changed if (colour_prev != colour) { r=(colour & 0xFF0000) >> 16; g=(colour & 0x00FF00) >> 8; b=colour & 0xFF; colour_prev=colour; } rgbdot(r,g,b); } void OLEDSeps525f::orientation(int o) { _rotation=o & 3; //Set write direction command(0x16); switch(_rotation) { case 0: default: //HC=1, VC=1, HV=0 data(0x76); _width=_physical_width; _height=_physical_height; break; case 1: //HC=0, VC=1, HV=1 data(0x73); _width=_physical_height; _height=_physical_width; break; case 2: //HC=0, VC=0, HV=0 data(0x70); _width=_physical_width; _height=_physical_height; break; case 3: //HC=1, VC=0, HV=1 data(0x75); _width=_physical_height; _height=_physical_width; break; } _columns = _width/8; _rows = _height/8; } const unsigned char FONT8x8[97][8] = { 0x08,0x08,0x08,0x00,0x00,0x00,0x00,0x00, // columns, rows, num_bytes_per_char 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // space 0x20 0x30,0x78,0x78,0x30,0x30,0x00,0x30,0x00, // ! 0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00, // " 0x6C,0x6C,0xFE,0x6C,0xFE,0x6C,0x6C,0x00, // # 0x18,0x3E,0x60,0x3C,0x06,0x7C,0x18,0x00, // $ 0x00,0x63,0x66,0x0C,0x18,0x33,0x63,0x00, // % 0x1C,0x36,0x1C,0x3B,0x6E,0x66,0x3B,0x00, // & 0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00, // ' 0x0C,0x18,0x30,0x30,0x30,0x18,0x0C,0x00, // ( 0x30,0x18,0x0C,0x0C,0x0C,0x18,0x30,0x00, // ) 0x00,0x66,0x3C,0xFF,0x3C,0x66,0x00,0x00, // * 0x00,0x30,0x30,0xFC,0x30,0x30,0x00,0x00, // + 0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x30, // , 0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x00, // - 0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00, // . 0x03,0x06,0x0C,0x18,0x30,0x60,0x40,0x00, // / (forward slash) 0x3E,0x63,0x63,0x6B,0x63,0x63,0x3E,0x00, // 0 0x30 0x18,0x38,0x58,0x18,0x18,0x18,0x7E,0x00, // 1 0x3C,0x66,0x06,0x1C,0x30,0x66,0x7E,0x00, // 2 0x3C,0x66,0x06,0x1C,0x06,0x66,0x3C,0x00, // 3 0x0E,0x1E,0x36,0x66,0x7F,0x06,0x0F,0x00, // 4 0x7E,0x60,0x7C,0x06,0x06,0x66,0x3C,0x00, // 5 0x1C,0x30,0x60,0x7C,0x66,0x66,0x3C,0x00, // 6 0x7E,0x66,0x06,0x0C,0x18,0x18,0x18,0x00, // 7 0x3C,0x66,0x66,0x3C,0x66,0x66,0x3C,0x00, // 8 0x3C,0x66,0x66,0x3E,0x06,0x0C,0x38,0x00, // 9 0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x00, // : 0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x30, // ; 0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x00, // < 0x00,0x00,0x7E,0x00,0x00,0x7E,0x00,0x00, // = 0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x00, // > 0x3C,0x66,0x06,0x0C,0x18,0x00,0x18,0x00, // ? 0x3E,0x63,0x6F,0x69,0x6F,0x60,0x3E,0x00, // @ 0x40 0x18,0x3C,0x66,0x66,0x7E,0x66,0x66,0x00, // A 0x7E,0x33,0x33,0x3E,0x33,0x33,0x7E,0x00, // B 0x1E,0x33,0x60,0x60,0x60,0x33,0x1E,0x00, // C 0x7C,0x36,0x33,0x33,0x33,0x36,0x7C,0x00, // D 0x7F,0x31,0x34,0x3C,0x34,0x31,0x7F,0x00, // E 0x7F,0x31,0x34,0x3C,0x34,0x30,0x78,0x00, // F 0x1E,0x33,0x60,0x60,0x67,0x33,0x1F,0x00, // G 0x66,0x66,0x66,0x7E,0x66,0x66,0x66,0x00, // H 0x3C,0x18,0x18,0x18,0x18,0x18,0x3C,0x00, // I 0x0F,0x06,0x06,0x06,0x66,0x66,0x3C,0x00, // J 0x73,0x33,0x36,0x3C,0x36,0x33,0x73,0x00, // K 0x78,0x30,0x30,0x30,0x31,0x33,0x7F,0x00, // L 0x63,0x77,0x7F,0x7F,0x6B,0x63,0x63,0x00, // M 0x63,0x73,0x7B,0x6F,0x67,0x63,0x63,0x00, // N 0x3E,0x63,0x63,0x63,0x63,0x63,0x3E,0x00, // O 0x7E,0x33,0x33,0x3E,0x30,0x30,0x78,0x00, // P 0x50 0x3C,0x66,0x66,0x66,0x6E,0x3C,0x0E,0x00, // Q 0x7E,0x33,0x33,0x3E,0x36,0x33,0x73,0x00, // R 0x3C,0x66,0x30,0x18,0x0C,0x66,0x3C,0x00, // S 0x7E,0x5A,0x18,0x18,0x18,0x18,0x3C,0x00, // T 0x66,0x66,0x66,0x66,0x66,0x66,0x7E,0x00, // U 0x66,0x66,0x66,0x66,0x66,0x3C,0x18,0x00, // V 0x63,0x63,0x63,0x6B,0x7F,0x77,0x63,0x00, // W 0x63,0x63,0x36,0x1C,0x1C,0x36,0x63,0x00, // X 0x66,0x66,0x66,0x3C,0x18,0x18,0x3C,0x00, // Y 0x7F,0x63,0x46,0x0C,0x19,0x33,0x7F,0x00, // Z 0x3C,0x30,0x30,0x30,0x30,0x30,0x3C,0x00, // [ 0x60,0x30,0x18,0x0C,0x06,0x03,0x01,0x00, // \ (back slash) 0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00, // ] 0x08,0x1C,0x36,0x63,0x00,0x00,0x00,0x00, // ^ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF, // _ 0x18,0x18,0x0C,0x00,0x00,0x00,0x00,0x00, // ` 0x60 0x00,0x00,0x3C,0x06,0x3E,0x66,0x3B,0x00, // a 0x70,0x30,0x3E,0x33,0x33,0x33,0x6E,0x00, // b 0x00,0x00,0x3C,0x66,0x60,0x66,0x3C,0x00, // c 0x0E,0x06,0x3E,0x66,0x66,0x66,0x3B,0x00, // d 0x00,0x00,0x3C,0x66,0x7E,0x60,0x3C,0x00, // e 0x1C,0x36,0x30,0x78,0x30,0x30,0x78,0x00, // f 0x00,0x00,0x3B,0x66,0x66,0x3E,0x06,0x7C, // g 0x70,0x30,0x36,0x3B,0x33,0x33,0x73,0x00, // h 0x18,0x00,0x38,0x18,0x18,0x18,0x3C,0x00, // i 0x06,0x00,0x06,0x06,0x06,0x66,0x66,0x3C, // j 0x70,0x30,0x33,0x36,0x3C,0x36,0x73,0x00, // k 0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00, // l 0x00,0x00,0x66,0x7F,0x7F,0x6B,0x63,0x00, // m 0x00,0x00,0x7C,0x66,0x66,0x66,0x66,0x00, // n 0x00,0x00,0x3C,0x66,0x66,0x66,0x3C,0x00, // o 0x00,0x00,0x6E,0x33,0x33,0x3E,0x30,0x78, // p 0x00,0x00,0x3B,0x66,0x66,0x3E,0x06,0x0F, // q 0x00,0x00,0x6E,0x3B,0x33,0x30,0x78,0x00, // r 0x00,0x00,0x3E,0x60,0x3C,0x06,0x7C,0x00, // s 0x08,0x18,0x3E,0x18,0x18,0x1A,0x0C,0x00, // t 0x00,0x00,0x66,0x66,0x66,0x66,0x3B,0x00, // u 0x00,0x00,0x66,0x66,0x66,0x3C,0x18,0x00, // v 0x00,0x00,0x63,0x6B,0x7F,0x7F,0x36,0x00, // w 0x00,0x00,0x63,0x36,0x1C,0x36,0x63,0x00, // x 0x00,0x00,0x66,0x66,0x66,0x3E,0x06,0x7C, // y 0x00,0x00,0x7E,0x4C,0x18,0x32,0x7E,0x00, // z 0x0E,0x18,0x18,0x70,0x18,0x18,0x0E,0x00, // { 0x0C,0x0C,0x0C,0x00,0x0C,0x0C,0x0C,0x00, // | 0x70,0x18,0x18,0x0E,0x18,0x18,0x70,0x00, // } 0x3B,0x6E,0x00,0x00,0x00,0x00,0x00,0x00, // ~ 0x1C,0x36,0x36,0x1C,0x00,0x00,0x00,0x00 }; // DEL void OLEDSeps525f::locate(int column, int row) { _row = row; _column = column; } void OLEDSeps525f::newline() { _column = 0; _row++; if (_row >= _rows) { _row = 0; } } void OLEDSeps525f::tablength(int l) { _tablength = l; } int OLEDSeps525f::_putc(int value) { int x = _column * 8; // FIXME: Char sizes int y = _row * 8; //Interpret some ASCII control codes if (value < 0x1F) { switch (value) { //Backspace case 0x08: _column--; if (_column < 0) { _column = 0; _row--; if (_row < 0) { _row = _rows - 1; } } break; //Tab case 0x09: _column=((_column / _tablength) * _tablength) + _tablength; if (_column > _columns) { newline(); } break; //Line feed case 0x0A: newline(); break; //Vertical tab case 0x0B: _row++; if (_row >= _rows) { _row = 0; } break; //Carriage return case 0x0D: _column = 0; break; //Default ignore default: break; } } else { if (value < 128) { bitblit(x + 1, y + 1, 8, 8, (char*)&(FONT8x8[value - 0x1F][0])); _column++; } } if (_column < 0) _column=0; if (_column >= _columns) { _row++; _column = 0; } if (_row < 0) _row=0; if (_row >= _rows) { _row = 0; } return value; } void OLEDSeps525f::cls() { fill(0, 0, _width, _height, _background); _row = 0; _column = 0; } int OLEDSeps525f::width() { return _width; } int OLEDSeps525f::height() { return _height; } int OLEDSeps525f::columns() { return _columns; } int OLEDSeps525f::rows() { return _rows; } int OLEDSeps525f::tablength() { return _tablength; } int OLEDSeps525f::orientation() { return(_rotation); } int OLEDSeps525f::foreground() { return(_foreground); } int OLEDSeps525f::background() { return(_background); } void OLEDSeps525f::window(int x, int y, int width, int height) { _window(x, y, width, height); } void OLEDSeps525f::putp(int colour) { _putp(colour); } void OLEDSeps525f::pixel(int x, int y, int colour) { _window(x, y, 1, 1); _putp(colour); } void OLEDSeps525f::fill(int x, int y, int width, int height, int colour) { int r, g, b; _window(x, y, width, height); //Start "write data" command if not done already if ( ! _writing_pixels ) { command(0x22); } r=(colour & 0xFF0000) >> 16; g=(colour & 0x00FF00) >> 8; b=colour & 0xFF; for (int i=0; i<width*height; i++) { rgbdot(r, g, b); } _window(0, 0, _width, _height); } void OLEDSeps525f::blit(int x, int y, int width, int height, const int* colour) { _window(x, y, width, height); for (int i=0; i<width*height; i++) { _putp(colour[i]); } _window(0, 0, _width, _height); } void OLEDSeps525f::foreground(int v) { _foreground = v; } void OLEDSeps525f::background(int v) { _background = v; } void OLEDSeps525f::bitblit(int x, int y, int width, int height, const char* bitstream) { _window(x, y, width, height); for (int i=0; i<height*width; i++) { int byte = i / 8; int bit = i % 8; int colour = ((bitstream[byte] << bit) & 0x80) ? _foreground : _background; _putp(colour); } _window(0, 0, _width, _height); }