Igor Skochinsky
/
DOGLCDDemo
A demo program for DOGL-128 LCD module. Based on Mike Sheldon's 3D Tie Fighter demo.
Embed:
(wiki syntax)
Show/hide line numbers
DogLCD.cpp
00001 #include "DogLCD.h" 00002 00003 // macro to make sure x falls into range from low to high (inclusive) 00004 #define CLAMP(x, low, high) { if ( (x) < (low) ) x = (low); if ( (x) > (high) ) x = (high); } while (0); 00005 00006 void DogLCD::_send_commands(const unsigned char* buf, size_t size) 00007 { 00008 // for commands, A0 is low 00009 _spi.format(8,0); 00010 _spi.frequency(10000000); 00011 _cs = 0; 00012 _a0 = 0; 00013 while ( size-- > 0 ) 00014 _spi.write(*buf++); 00015 _cs = 1; 00016 } 00017 00018 void DogLCD::_send_data(const unsigned char* buf, size_t size) 00019 { 00020 // for data, A0 is high 00021 _spi.format(8,0); 00022 _spi.frequency(10000000); 00023 _cs = 0; 00024 _a0 = 1; 00025 while ( size-- > 0 ) 00026 _spi.write(*buf++); 00027 _cs = 1; 00028 _a0 = 0; 00029 } 00030 00031 // set column and page number 00032 void DogLCD::_set_xy(int x, int y) 00033 { 00034 //printf("_set_xy(%d,%d)\n", x, y); 00035 CLAMP(x, 0, LCDWIDTH-1); 00036 CLAMP(y, 0, LCDPAGES-1); 00037 unsigned char cmd[3]; 00038 cmd[0] = 0xB0 | (y&0xF); 00039 cmd[1] = 0x10 | (x&0xF); 00040 cmd[2] = (x>>4)&0xF; 00041 _send_commands(cmd, 3); 00042 } 00043 00044 // initialize and turn on the display 00045 void DogLCD::init() 00046 { 00047 const unsigned char init_seq[] = { 00048 0x40, //Display start line 0 00049 0xa1, //ADC reverse 00050 0xc0, //Normal COM0...COM63 00051 0xa6, //Display normal 00052 0xa2, //Set Bias 1/9 (Duty 1/65) 00053 0x2f, //Booster, Regulator and Follower On 00054 0xf8, //Set internal Booster to 4x 00055 0x00, 00056 0x27, //Contrast set 00057 0x81, 00058 0x16, 00059 0xac, //No indicator 00060 0x00, 00061 0xaf, //Display on 00062 }; 00063 //printf("Reset=L\n"); 00064 _reset = 0; 00065 //printf("Power=H\n"); 00066 _power = 1; 00067 //wait_ms(1); 00068 //printf("Reset=H\n"); 00069 _reset = 1; 00070 //wait(5); 00071 //printf("Sending init commands\n"); 00072 _send_commands(init_seq, sizeof(init_seq)); 00073 } 00074 00075 void DogLCD::send_pic(const unsigned char* data) 00076 { 00077 //printf("Sending picture\n"); 00078 for (int i=0; i<LCDPAGES; i++) 00079 { 00080 _set_xy(0, i); 00081 _send_data(data + i*LCDWIDTH, LCDWIDTH); 00082 } 00083 } 00084 00085 void DogLCD::clear_screen() 00086 { 00087 //printf("Clear screen\n"); 00088 memset(_framebuffer, 0, sizeof(_framebuffer)); 00089 if ( _updating == 0 ) 00090 { 00091 send_pic(_framebuffer); 00092 } 00093 } 00094 00095 void DogLCD::all_on(bool on) 00096 { 00097 //printf("Sending all on %d\n", on); 00098 unsigned char cmd = 0xA4 | (on ? 1 : 0); 00099 _send_commands(&cmd, 1); 00100 } 00101 00102 void DogLCD::pixel(int x, int y, int colour) 00103 { 00104 CLAMP(x, 0, LCDWIDTH-1); 00105 CLAMP(y, 0, LCDHEIGHT-1); 00106 int page = y / 8; 00107 unsigned char mask = 1<<(y%8); 00108 unsigned char *byte = &_framebuffer[page*LCDWIDTH + x]; 00109 if ( colour == 0 ) 00110 *byte &= ~mask; // clear pixel 00111 else 00112 *byte |= mask; // set pixel 00113 if ( !_updating ) 00114 { 00115 _set_xy(x, page); 00116 _send_data(byte, 1); 00117 } 00118 } 00119 00120 void DogLCD::fill(int x, int y, int width, int height, int colour) 00121 { 00122 /* 00123 If we need to fill partial pages at the top: 00124 00125 ......+---+---+..... 00126 ^ | = | = | = : don't touch 00127 | | = | = | * : update 00128 y%8 | = | = | 00129 | | = | = | 00130 v | = | = | 00131 y----> | * | * | 00132 | * | * | 00133 | * | * | 00134 +---+---+ 00135 */ 00136 //printf("fill(x=%d, y=%d, width=%d, height=%d, colour=%x)\n", x, y, width, height, colour); 00137 CLAMP(x, 0, LCDWIDTH-1); 00138 CLAMP(y, 0, LCDHEIGHT-1); 00139 CLAMP(width, 0, LCDWIDTH - x); 00140 CLAMP(height, 0, LCDHEIGHT - y); 00141 int page = y/8; 00142 int firstpage = page; 00143 int partpage = y%8; 00144 if ( partpage != 0 ) 00145 { 00146 // we need to process partial bytes in the top page 00147 unsigned char mask = (1<<partpage) - 1; // this mask has 1s for bits we need to leave 00148 unsigned char *bytes = &_framebuffer[page*LCDWIDTH + x]; 00149 for ( int i = 0; i < width; i++, bytes++ ) 00150 { 00151 // clear "our" bits 00152 *bytes &= mask; 00153 if ( colour != 0 ) 00154 *bytes |= ~mask; // set our bits 00155 } 00156 height -= partpage; 00157 page++; 00158 } 00159 while ( height >= 8 ) 00160 { 00161 memset(&_framebuffer[page*LCDWIDTH + x], colour == 0 ? 0 : 0xFF, width); 00162 page++; 00163 height -= 8; 00164 } 00165 if ( height != 0 ) 00166 { 00167 // we need to process partial bytes in the bottom page 00168 unsigned char mask = ~((1<<partpage) - 1); // this mask has 1s for bits we need to leave 00169 unsigned char *bytes = &_framebuffer[page*LCDWIDTH + x]; 00170 for ( int i = 0; i < width; i++, bytes++ ) 00171 { 00172 // clear "our" bits 00173 *bytes &= mask; 00174 if ( colour != 0 ) 00175 *bytes |= ~mask; // set our bits 00176 } 00177 page++; 00178 } 00179 //printf("_updating=%d\n", _updating); 00180 if ( !_updating ) 00181 { 00182 int laststpage = page; 00183 for ( page = firstpage; page < laststpage; page++) 00184 { 00185 //printf("setting x=%d, page=%d\n", x, page); 00186 _set_xy(x, page); 00187 //printf("sending %d bytes at offset %x\n", width, page*LCDWIDTH + x); 00188 _send_data(&_framebuffer[page*LCDWIDTH + x], width); 00189 } 00190 } 00191 } 00192 00193 void DogLCD::beginupdate() 00194 { 00195 _updating++; 00196 //printf("beginupdate: %d\n", _updating); 00197 } 00198 00199 void DogLCD::endupdate() 00200 { 00201 _updating--; 00202 //printf("endupdate: %d\n", _updating); 00203 if ( _updating == 0 ) 00204 { 00205 send_pic(_framebuffer); 00206 } 00207 }
Generated on Fri Jul 15 2022 20:49:26 by 1.7.2