Igor Skochinsky
/
DOGLCDDemo
A demo program for DOGL-128 LCD module. Based on Mike Sheldon's 3D Tie Fighter demo.
LCD/DogLCD.cpp@0:2a5dccfd318f, 2010-01-14 (annotated)
- Committer:
- igorsk
- Date:
- Thu Jan 14 00:49:39 2010 +0000
- Revision:
- 0:2a5dccfd318f
Who changed what in which revision?
User | Revision | Line number | New 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 | } |