A demo program for DOGL-128 LCD module. Based on Mike Sheldon's 3D Tie Fighter demo.

Dependencies:   mbed

Committer:
igorsk
Date:
Thu Jan 14 00:49:39 2010 +0000
Revision:
0:2a5dccfd318f

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
igorsk 0:2a5dccfd318f 1 #include "DogLCD.h"
igorsk 0:2a5dccfd318f 2
igorsk 0:2a5dccfd318f 3 // macro to make sure x falls into range from low to high (inclusive)
igorsk 0:2a5dccfd318f 4 #define CLAMP(x, low, high) { if ( (x) < (low) ) x = (low); if ( (x) > (high) ) x = (high); } while (0);
igorsk 0:2a5dccfd318f 5
igorsk 0:2a5dccfd318f 6 void DogLCD::_send_commands(const unsigned char* buf, size_t size)
igorsk 0:2a5dccfd318f 7 {
igorsk 0:2a5dccfd318f 8 // for commands, A0 is low
igorsk 0:2a5dccfd318f 9 _spi.format(8,0);
igorsk 0:2a5dccfd318f 10 _spi.frequency(10000000);
igorsk 0:2a5dccfd318f 11 _cs = 0;
igorsk 0:2a5dccfd318f 12 _a0 = 0;
igorsk 0:2a5dccfd318f 13 while ( size-- > 0 )
igorsk 0:2a5dccfd318f 14 _spi.write(*buf++);
igorsk 0:2a5dccfd318f 15 _cs = 1;
igorsk 0:2a5dccfd318f 16 }
igorsk 0:2a5dccfd318f 17
igorsk 0:2a5dccfd318f 18 void DogLCD::_send_data(const unsigned char* buf, size_t size)
igorsk 0:2a5dccfd318f 19 {
igorsk 0:2a5dccfd318f 20 // for data, A0 is high
igorsk 0:2a5dccfd318f 21 _spi.format(8,0);
igorsk 0:2a5dccfd318f 22 _spi.frequency(10000000);
igorsk 0:2a5dccfd318f 23 _cs = 0;
igorsk 0:2a5dccfd318f 24 _a0 = 1;
igorsk 0:2a5dccfd318f 25 while ( size-- > 0 )
igorsk 0:2a5dccfd318f 26 _spi.write(*buf++);
igorsk 0:2a5dccfd318f 27 _cs = 1;
igorsk 0:2a5dccfd318f 28 _a0 = 0;
igorsk 0:2a5dccfd318f 29 }
igorsk 0:2a5dccfd318f 30
igorsk 0:2a5dccfd318f 31 // set column and page number
igorsk 0:2a5dccfd318f 32 void DogLCD::_set_xy(int x, int y)
igorsk 0:2a5dccfd318f 33 {
igorsk 0:2a5dccfd318f 34 //printf("_set_xy(%d,%d)\n", x, y);
igorsk 0:2a5dccfd318f 35 CLAMP(x, 0, LCDWIDTH-1);
igorsk 0:2a5dccfd318f 36 CLAMP(y, 0, LCDPAGES-1);
igorsk 0:2a5dccfd318f 37 unsigned char cmd[3];
igorsk 0:2a5dccfd318f 38 cmd[0] = 0xB0 | (y&0xF);
igorsk 0:2a5dccfd318f 39 cmd[1] = 0x10 | (x&0xF);
igorsk 0:2a5dccfd318f 40 cmd[2] = (x>>4)&0xF;
igorsk 0:2a5dccfd318f 41 _send_commands(cmd, 3);
igorsk 0:2a5dccfd318f 42 }
igorsk 0:2a5dccfd318f 43
igorsk 0:2a5dccfd318f 44 // initialize and turn on the display
igorsk 0:2a5dccfd318f 45 void DogLCD::init()
igorsk 0:2a5dccfd318f 46 {
igorsk 0:2a5dccfd318f 47 const unsigned char init_seq[] = {
igorsk 0:2a5dccfd318f 48 0x40, //Display start line 0
igorsk 0:2a5dccfd318f 49 0xa1, //ADC reverse
igorsk 0:2a5dccfd318f 50 0xc0, //Normal COM0...COM63
igorsk 0:2a5dccfd318f 51 0xa6, //Display normal
igorsk 0:2a5dccfd318f 52 0xa2, //Set Bias 1/9 (Duty 1/65)
igorsk 0:2a5dccfd318f 53 0x2f, //Booster, Regulator and Follower On
igorsk 0:2a5dccfd318f 54 0xf8, //Set internal Booster to 4x
igorsk 0:2a5dccfd318f 55 0x00,
igorsk 0:2a5dccfd318f 56 0x27, //Contrast set
igorsk 0:2a5dccfd318f 57 0x81,
igorsk 0:2a5dccfd318f 58 0x16,
igorsk 0:2a5dccfd318f 59 0xac, //No indicator
igorsk 0:2a5dccfd318f 60 0x00,
igorsk 0:2a5dccfd318f 61 0xaf, //Display on
igorsk 0:2a5dccfd318f 62 };
igorsk 0:2a5dccfd318f 63 //printf("Reset=L\n");
igorsk 0:2a5dccfd318f 64 _reset = 0;
igorsk 0:2a5dccfd318f 65 //printf("Power=H\n");
igorsk 0:2a5dccfd318f 66 _power = 1;
igorsk 0:2a5dccfd318f 67 //wait_ms(1);
igorsk 0:2a5dccfd318f 68 //printf("Reset=H\n");
igorsk 0:2a5dccfd318f 69 _reset = 1;
igorsk 0:2a5dccfd318f 70 //wait(5);
igorsk 0:2a5dccfd318f 71 //printf("Sending init commands\n");
igorsk 0:2a5dccfd318f 72 _send_commands(init_seq, sizeof(init_seq));
igorsk 0:2a5dccfd318f 73 }
igorsk 0:2a5dccfd318f 74
igorsk 0:2a5dccfd318f 75 void DogLCD::send_pic(const unsigned char* data)
igorsk 0:2a5dccfd318f 76 {
igorsk 0:2a5dccfd318f 77 //printf("Sending picture\n");
igorsk 0:2a5dccfd318f 78 for (int i=0; i<LCDPAGES; i++)
igorsk 0:2a5dccfd318f 79 {
igorsk 0:2a5dccfd318f 80 _set_xy(0, i);
igorsk 0:2a5dccfd318f 81 _send_data(data + i*LCDWIDTH, LCDWIDTH);
igorsk 0:2a5dccfd318f 82 }
igorsk 0:2a5dccfd318f 83 }
igorsk 0:2a5dccfd318f 84
igorsk 0:2a5dccfd318f 85 void DogLCD::clear_screen()
igorsk 0:2a5dccfd318f 86 {
igorsk 0:2a5dccfd318f 87 //printf("Clear screen\n");
igorsk 0:2a5dccfd318f 88 memset(_framebuffer, 0, sizeof(_framebuffer));
igorsk 0:2a5dccfd318f 89 if ( _updating == 0 )
igorsk 0:2a5dccfd318f 90 {
igorsk 0:2a5dccfd318f 91 send_pic(_framebuffer);
igorsk 0:2a5dccfd318f 92 }
igorsk 0:2a5dccfd318f 93 }
igorsk 0:2a5dccfd318f 94
igorsk 0:2a5dccfd318f 95 void DogLCD::all_on(bool on)
igorsk 0:2a5dccfd318f 96 {
igorsk 0:2a5dccfd318f 97 //printf("Sending all on %d\n", on);
igorsk 0:2a5dccfd318f 98 unsigned char cmd = 0xA4 | (on ? 1 : 0);
igorsk 0:2a5dccfd318f 99 _send_commands(&cmd, 1);
igorsk 0:2a5dccfd318f 100 }
igorsk 0:2a5dccfd318f 101
igorsk 0:2a5dccfd318f 102 void DogLCD::pixel(int x, int y, int colour)
igorsk 0:2a5dccfd318f 103 {
igorsk 0:2a5dccfd318f 104 CLAMP(x, 0, LCDWIDTH-1);
igorsk 0:2a5dccfd318f 105 CLAMP(y, 0, LCDHEIGHT-1);
igorsk 0:2a5dccfd318f 106 int page = y / 8;
igorsk 0:2a5dccfd318f 107 unsigned char mask = 1<<(y%8);
igorsk 0:2a5dccfd318f 108 unsigned char *byte = &_framebuffer[page*LCDWIDTH + x];
igorsk 0:2a5dccfd318f 109 if ( colour == 0 )
igorsk 0:2a5dccfd318f 110 *byte &= ~mask; // clear pixel
igorsk 0:2a5dccfd318f 111 else
igorsk 0:2a5dccfd318f 112 *byte |= mask; // set pixel
igorsk 0:2a5dccfd318f 113 if ( !_updating )
igorsk 0:2a5dccfd318f 114 {
igorsk 0:2a5dccfd318f 115 _set_xy(x, page);
igorsk 0:2a5dccfd318f 116 _send_data(byte, 1);
igorsk 0:2a5dccfd318f 117 }
igorsk 0:2a5dccfd318f 118 }
igorsk 0:2a5dccfd318f 119
igorsk 0:2a5dccfd318f 120 void DogLCD::fill(int x, int y, int width, int height, int colour)
igorsk 0:2a5dccfd318f 121 {
igorsk 0:2a5dccfd318f 122 /*
igorsk 0:2a5dccfd318f 123 If we need to fill partial pages at the top:
igorsk 0:2a5dccfd318f 124
igorsk 0:2a5dccfd318f 125 ......+---+---+.....
igorsk 0:2a5dccfd318f 126 ^ | = | = | = : don't touch
igorsk 0:2a5dccfd318f 127 | | = | = | * : update
igorsk 0:2a5dccfd318f 128 y%8 | = | = |
igorsk 0:2a5dccfd318f 129 | | = | = |
igorsk 0:2a5dccfd318f 130 v | = | = |
igorsk 0:2a5dccfd318f 131 y----> | * | * |
igorsk 0:2a5dccfd318f 132 | * | * |
igorsk 0:2a5dccfd318f 133 | * | * |
igorsk 0:2a5dccfd318f 134 +---+---+
igorsk 0:2a5dccfd318f 135 */
igorsk 0:2a5dccfd318f 136 //printf("fill(x=%d, y=%d, width=%d, height=%d, colour=%x)\n", x, y, width, height, colour);
igorsk 0:2a5dccfd318f 137 CLAMP(x, 0, LCDWIDTH-1);
igorsk 0:2a5dccfd318f 138 CLAMP(y, 0, LCDHEIGHT-1);
igorsk 0:2a5dccfd318f 139 CLAMP(width, 0, LCDWIDTH - x);
igorsk 0:2a5dccfd318f 140 CLAMP(height, 0, LCDHEIGHT - y);
igorsk 0:2a5dccfd318f 141 int page = y/8;
igorsk 0:2a5dccfd318f 142 int firstpage = page;
igorsk 0:2a5dccfd318f 143 int partpage = y%8;
igorsk 0:2a5dccfd318f 144 if ( partpage != 0 )
igorsk 0:2a5dccfd318f 145 {
igorsk 0:2a5dccfd318f 146 // we need to process partial bytes in the top page
igorsk 0:2a5dccfd318f 147 unsigned char mask = (1<<partpage) - 1; // this mask has 1s for bits we need to leave
igorsk 0:2a5dccfd318f 148 unsigned char *bytes = &_framebuffer[page*LCDWIDTH + x];
igorsk 0:2a5dccfd318f 149 for ( int i = 0; i < width; i++, bytes++ )
igorsk 0:2a5dccfd318f 150 {
igorsk 0:2a5dccfd318f 151 // clear "our" bits
igorsk 0:2a5dccfd318f 152 *bytes &= mask;
igorsk 0:2a5dccfd318f 153 if ( colour != 0 )
igorsk 0:2a5dccfd318f 154 *bytes |= ~mask; // set our bits
igorsk 0:2a5dccfd318f 155 }
igorsk 0:2a5dccfd318f 156 height -= partpage;
igorsk 0:2a5dccfd318f 157 page++;
igorsk 0:2a5dccfd318f 158 }
igorsk 0:2a5dccfd318f 159 while ( height >= 8 )
igorsk 0:2a5dccfd318f 160 {
igorsk 0:2a5dccfd318f 161 memset(&_framebuffer[page*LCDWIDTH + x], colour == 0 ? 0 : 0xFF, width);
igorsk 0:2a5dccfd318f 162 page++;
igorsk 0:2a5dccfd318f 163 height -= 8;
igorsk 0:2a5dccfd318f 164 }
igorsk 0:2a5dccfd318f 165 if ( height != 0 )
igorsk 0:2a5dccfd318f 166 {
igorsk 0:2a5dccfd318f 167 // we need to process partial bytes in the bottom page
igorsk 0:2a5dccfd318f 168 unsigned char mask = ~((1<<partpage) - 1); // this mask has 1s for bits we need to leave
igorsk 0:2a5dccfd318f 169 unsigned char *bytes = &_framebuffer[page*LCDWIDTH + x];
igorsk 0:2a5dccfd318f 170 for ( int i = 0; i < width; i++, bytes++ )
igorsk 0:2a5dccfd318f 171 {
igorsk 0:2a5dccfd318f 172 // clear "our" bits
igorsk 0:2a5dccfd318f 173 *bytes &= mask;
igorsk 0:2a5dccfd318f 174 if ( colour != 0 )
igorsk 0:2a5dccfd318f 175 *bytes |= ~mask; // set our bits
igorsk 0:2a5dccfd318f 176 }
igorsk 0:2a5dccfd318f 177 page++;
igorsk 0:2a5dccfd318f 178 }
igorsk 0:2a5dccfd318f 179 //printf("_updating=%d\n", _updating);
igorsk 0:2a5dccfd318f 180 if ( !_updating )
igorsk 0:2a5dccfd318f 181 {
igorsk 0:2a5dccfd318f 182 int laststpage = page;
igorsk 0:2a5dccfd318f 183 for ( page = firstpage; page < laststpage; page++)
igorsk 0:2a5dccfd318f 184 {
igorsk 0:2a5dccfd318f 185 //printf("setting x=%d, page=%d\n", x, page);
igorsk 0:2a5dccfd318f 186 _set_xy(x, page);
igorsk 0:2a5dccfd318f 187 //printf("sending %d bytes at offset %x\n", width, page*LCDWIDTH + x);
igorsk 0:2a5dccfd318f 188 _send_data(&_framebuffer[page*LCDWIDTH + x], width);
igorsk 0:2a5dccfd318f 189 }
igorsk 0:2a5dccfd318f 190 }
igorsk 0:2a5dccfd318f 191 }
igorsk 0:2a5dccfd318f 192
igorsk 0:2a5dccfd318f 193 void DogLCD::beginupdate()
igorsk 0:2a5dccfd318f 194 {
igorsk 0:2a5dccfd318f 195 _updating++;
igorsk 0:2a5dccfd318f 196 //printf("beginupdate: %d\n", _updating);
igorsk 0:2a5dccfd318f 197 }
igorsk 0:2a5dccfd318f 198
igorsk 0:2a5dccfd318f 199 void DogLCD::endupdate()
igorsk 0:2a5dccfd318f 200 {
igorsk 0:2a5dccfd318f 201 _updating--;
igorsk 0:2a5dccfd318f 202 //printf("endupdate: %d\n", _updating);
igorsk 0:2a5dccfd318f 203 if ( _updating == 0 )
igorsk 0:2a5dccfd318f 204 {
igorsk 0:2a5dccfd318f 205 send_pic(_framebuffer);
igorsk 0:2a5dccfd318f 206 }
igorsk 0:2a5dccfd318f 207 }