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