Richard Parker / EALCD
Committer:
richardparker
Date:
Mon Apr 26 21:37:54 2010 +0000
Revision:
4:f8f7f4f9c58d
Parent:
3:24fbf4dbd7e5
Child:
6:4fe6f365cbeb

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
richardparker 0:839ecbf5cb2a 1 // Copyright 2010 Richard Parker
richardparker 0:839ecbf5cb2a 2
richardparker 0:839ecbf5cb2a 3 #include "mbed.h"
richardparker 0:839ecbf5cb2a 4 #include "EALCD.h"
richardparker 0:839ecbf5cb2a 5
richardparker 0:839ecbf5cb2a 6 // Register addresses.
richardparker 0:839ecbf5cb2a 7 #define EALCD_DEVICE_CODE_ADDRESS 0x00
richardparker 0:839ecbf5cb2a 8 #define EALCD_TOUCH_FREQ 10000
richardparker 0:839ecbf5cb2a 9 #define EALCD_LCD_FREQ 20000000
richardparker 0:839ecbf5cb2a 10
richardparker 0:839ecbf5cb2a 11 EALCD::EALCD( PinName LED_PWM,
richardparker 0:839ecbf5cb2a 12 PinName LCD_RS,
richardparker 0:839ecbf5cb2a 13 PinName LCD_SO,
richardparker 0:839ecbf5cb2a 14 PinName LCD_SI,
richardparker 0:839ecbf5cb2a 15 PinName LCD_SCL,
richardparker 0:839ecbf5cb2a 16 PinName LCD_CS,
richardparker 0:839ecbf5cb2a 17 PinName TCH_CS)
richardparker 0:839ecbf5cb2a 18 : _backlight(LED_PWM),
richardparker 0:839ecbf5cb2a 19 _comm(LCD_SI, LCD_SO, LCD_SCL),
richardparker 0:839ecbf5cb2a 20 _rs(LCD_RS),
richardparker 0:839ecbf5cb2a 21 _cs(LCD_CS),
richardparker 4:f8f7f4f9c58d 22 _tch_cs(TCH_CS),
richardparker 4:f8f7f4f9c58d 23 _maxBright(0.4)
richardparker 0:839ecbf5cb2a 24 {
richardparker 0:839ecbf5cb2a 25 // Make sure not selecting either chip.
richardparker 0:839ecbf5cb2a 26 _cs = 1;
richardparker 0:839ecbf5cb2a 27 _tch_cs = 1;
richardparker 0:839ecbf5cb2a 28
richardparker 0:839ecbf5cb2a 29 // Set the frequency of the PWM backlight to have a period ~400us.
richardparker 0:839ecbf5cb2a 30 _backlight.period_us(400);
richardparker 4:f8f7f4f9c58d 31 // By default fully on.
richardparker 4:f8f7f4f9c58d 32 setBrightness(maxBrightness());
richardparker 0:839ecbf5cb2a 33
richardparker 0:839ecbf5cb2a 34 // Set up comms, 8 bit interface.
richardparker 0:839ecbf5cb2a 35 _comm.format(8);
richardparker 0:839ecbf5cb2a 36 _comm.frequency(EALCD_LCD_FREQ);
richardparker 0:839ecbf5cb2a 37
richardparker 0:839ecbf5cb2a 38 // Now actual initialise the connection.
richardparker 0:839ecbf5cb2a 39 _initialise();
richardparker 0:839ecbf5cb2a 40 }
richardparker 0:839ecbf5cb2a 41
richardparker 0:839ecbf5cb2a 42 EALCD::~EALCD()
richardparker 0:839ecbf5cb2a 43 {
richardparker 0:839ecbf5cb2a 44 }
richardparker 0:839ecbf5cb2a 45
richardparker 0:839ecbf5cb2a 46 void EALCD::setBrightness(float percentage)
richardparker 0:839ecbf5cb2a 47 {
richardparker 0:839ecbf5cb2a 48 // Check the value is within the correct range.
richardparker 0:839ecbf5cb2a 49 if (percentage < 0)
richardparker 0:839ecbf5cb2a 50 {
richardparker 0:839ecbf5cb2a 51 percentage = 0;
richardparker 0:839ecbf5cb2a 52 }
richardparker 0:839ecbf5cb2a 53 else if (percentage > 1)
richardparker 0:839ecbf5cb2a 54 {
richardparker 0:839ecbf5cb2a 55 percentage = 1;
richardparker 0:839ecbf5cb2a 56 }
richardparker 0:839ecbf5cb2a 57
richardparker 0:839ecbf5cb2a 58 _backlight = 1-percentage;
richardparker 0:839ecbf5cb2a 59 }
richardparker 0:839ecbf5cb2a 60
richardparker 0:839ecbf5cb2a 61 void EALCD::_writeToDisplay(unsigned short data)
richardparker 0:839ecbf5cb2a 62 {
richardparker 0:839ecbf5cb2a 63 // Set RS which is connected to DC and so when high is to data.
richardparker 0:839ecbf5cb2a 64 _rs = 1;
richardparker 0:839ecbf5cb2a 65 // Activate the chip (active low).
richardparker 0:839ecbf5cb2a 66 _cs = 0;
richardparker 0:839ecbf5cb2a 67
richardparker 0:839ecbf5cb2a 68 // Write the msb data.
richardparker 0:839ecbf5cb2a 69 _comm.write(data >> 8);
richardparker 0:839ecbf5cb2a 70 // Write the lsb data.
richardparker 0:839ecbf5cb2a 71 _comm.write(data & 0xff);
richardparker 0:839ecbf5cb2a 72
richardparker 0:839ecbf5cb2a 73 // Deactivate the chip (active low).
richardparker 0:839ecbf5cb2a 74 _cs = 1;
richardparker 0:839ecbf5cb2a 75 }
richardparker 0:839ecbf5cb2a 76
richardparker 0:839ecbf5cb2a 77 void EALCD::_writeToRegister(unsigned short addr, unsigned short data)
richardparker 0:839ecbf5cb2a 78 {
richardparker 0:839ecbf5cb2a 79 // Command phase.
richardparker 0:839ecbf5cb2a 80 // Set RS which is connected to DC and so when low is to command.
richardparker 0:839ecbf5cb2a 81 _rs = 0;
richardparker 0:839ecbf5cb2a 82 // Activate the chip (active low).
richardparker 0:839ecbf5cb2a 83 _cs = 0;
richardparker 0:839ecbf5cb2a 84
richardparker 0:839ecbf5cb2a 85 // Write the msb address.
richardparker 0:839ecbf5cb2a 86 _comm.write(addr >> 8);
richardparker 0:839ecbf5cb2a 87 // Write the lsb address.
richardparker 0:839ecbf5cb2a 88 _comm.write(addr & 0xff);
richardparker 0:839ecbf5cb2a 89
richardparker 0:839ecbf5cb2a 90 // Deactivate the chip (active low).
richardparker 0:839ecbf5cb2a 91 _cs = 1;
richardparker 0:839ecbf5cb2a 92
richardparker 0:839ecbf5cb2a 93 // Data phase.
richardparker 0:839ecbf5cb2a 94 // Set RS which is connected to DC and so when high is data.
richardparker 0:839ecbf5cb2a 95 _rs = 1;
richardparker 0:839ecbf5cb2a 96 // Activate the chip (active low).
richardparker 0:839ecbf5cb2a 97 _cs = 0;
richardparker 0:839ecbf5cb2a 98
richardparker 0:839ecbf5cb2a 99 // Write the msb data.
richardparker 0:839ecbf5cb2a 100 _comm.write(data >> 8);
richardparker 0:839ecbf5cb2a 101 // Write the lsb data.
richardparker 0:839ecbf5cb2a 102 _comm.write(data & 0xff);
richardparker 0:839ecbf5cb2a 103
richardparker 0:839ecbf5cb2a 104 // Deactivate the chip (active low).
richardparker 0:839ecbf5cb2a 105 _cs = 1;
richardparker 0:839ecbf5cb2a 106
richardparker 0:839ecbf5cb2a 107 // Restore index to GRAM by accessing GRAM register.
richardparker 0:839ecbf5cb2a 108 // Set RS which is connected to DC and so when low is to command.
richardparker 0:839ecbf5cb2a 109 _rs = 0;
richardparker 0:839ecbf5cb2a 110 // Activate the chip (active low).
richardparker 0:839ecbf5cb2a 111 _cs = 0;
richardparker 0:839ecbf5cb2a 112
richardparker 0:839ecbf5cb2a 113 // Write the msb address.
richardparker 0:839ecbf5cb2a 114 _comm.write(0x00);
richardparker 0:839ecbf5cb2a 115 // Write the lsb address.
richardparker 0:839ecbf5cb2a 116 _comm.write(0x22);
richardparker 0:839ecbf5cb2a 117
richardparker 0:839ecbf5cb2a 118 // Deactivate the chip (active low).
richardparker 0:839ecbf5cb2a 119 _cs = 1;
richardparker 0:839ecbf5cb2a 120 }
richardparker 0:839ecbf5cb2a 121
richardparker 0:839ecbf5cb2a 122 void EALCD::_initialise()
richardparker 0:839ecbf5cb2a 123 {
richardparker 0:839ecbf5cb2a 124 // Start up sequence. See page 72 of SSD1289 V1.3 datasheet for reasons.
richardparker 0:839ecbf5cb2a 125 _writeToRegister(0x07, 0x0021);
richardparker 0:839ecbf5cb2a 126 // Oscillator on.
richardparker 0:839ecbf5cb2a 127 _writeToRegister(0x00, 0x0001);
richardparker 0:839ecbf5cb2a 128 _writeToRegister(0x07, 0x0723);
richardparker 0:839ecbf5cb2a 129 // Exit sleep mode
richardparker 0:839ecbf5cb2a 130 _writeToRegister(0x10, 0x0000);
richardparker 0:839ecbf5cb2a 131 // Pause 200ms (need at least 30ms).
richardparker 0:839ecbf5cb2a 132 wait(0.2);
richardparker 0:839ecbf5cb2a 133 _writeToRegister(0x07, 0x0033);
richardparker 0:839ecbf5cb2a 134 // Setup screen orientation and colour mode etc.
richardparker 0:839ecbf5cb2a 135 _writeToRegister(0x11, 0x6828);
richardparker 0:839ecbf5cb2a 136 // LCD driving waveform.
richardparker 0:839ecbf5cb2a 137 _writeToRegister(0x02, 0x0600);
richardparker 0:839ecbf5cb2a 138 _writeToRegister(0x0f, 0x0000);
richardparker 0:839ecbf5cb2a 139 // Driver output control.
richardparker 0:839ecbf5cb2a 140 _writeToRegister(0x01, 0x2b3f);
richardparker 0:839ecbf5cb2a 141 _writeToRegister(0x0b, 0x5308);
richardparker 0:839ecbf5cb2a 142 // Set refresh rate to 70Hz.
richardparker 0:839ecbf5cb2a 143 _writeToRegister(0x25, 0xa000);
richardparker 0:839ecbf5cb2a 144
richardparker 0:839ecbf5cb2a 145 }
richardparker 0:839ecbf5cb2a 146
richardparker 0:839ecbf5cb2a 147 void EALCD::_moveTo(short x, short y)
richardparker 0:839ecbf5cb2a 148 {
richardparker 0:839ecbf5cb2a 149 // Limit movement.
richardparker 0:839ecbf5cb2a 150 if (x < 0)
richardparker 0:839ecbf5cb2a 151 {
richardparker 0:839ecbf5cb2a 152 x = 0;
richardparker 0:839ecbf5cb2a 153 }
richardparker 0:839ecbf5cb2a 154
richardparker 0:839ecbf5cb2a 155 if (y < 0)
richardparker 0:839ecbf5cb2a 156 {
richardparker 0:839ecbf5cb2a 157 y = 0;
richardparker 0:839ecbf5cb2a 158 }
richardparker 0:839ecbf5cb2a 159
richardparker 0:839ecbf5cb2a 160 if (x >= width())
richardparker 0:839ecbf5cb2a 161 {
richardparker 0:839ecbf5cb2a 162 x = width()-1;
richardparker 0:839ecbf5cb2a 163 }
richardparker 0:839ecbf5cb2a 164
richardparker 0:839ecbf5cb2a 165 if (y >= height())
richardparker 0:839ecbf5cb2a 166 {
richardparker 0:839ecbf5cb2a 167 y = height()-1;
richardparker 0:839ecbf5cb2a 168 }
richardparker 0:839ecbf5cb2a 169
richardparker 0:839ecbf5cb2a 170 // Masking values to prevent too large.
richardparker 0:839ecbf5cb2a 171 x = x & 0x1ff;
richardparker 0:839ecbf5cb2a 172 _writeToRegister(0x4f, x);
richardparker 0:839ecbf5cb2a 173
richardparker 0:839ecbf5cb2a 174 // Mask to get down to a sensible number.
richardparker 0:839ecbf5cb2a 175 y = y & 0xff;
richardparker 0:839ecbf5cb2a 176 // -1 because pixel at top of screen is 239 (as 0 indexed therefore 240 high).
richardparker 0:839ecbf5cb2a 177 y = height() - 1 - y;
richardparker 0:839ecbf5cb2a 178 _writeToRegister(0x4e, y);
richardparker 0:839ecbf5cb2a 179 }
richardparker 0:839ecbf5cb2a 180
richardparker 0:839ecbf5cb2a 181 void EALCD::_window(short x, short y, unsigned short w, unsigned short h)
richardparker 0:839ecbf5cb2a 182 {
richardparker 0:839ecbf5cb2a 183 // If start off screen then no need to even try drawing.
richardparker 0:839ecbf5cb2a 184 if ((x >= width()) || (y >= height()))
richardparker 0:839ecbf5cb2a 185 {
richardparker 0:839ecbf5cb2a 186 return;
richardparker 0:839ecbf5cb2a 187 }
richardparker 0:839ecbf5cb2a 188
richardparker 0:839ecbf5cb2a 189 // Limit to not go off screen.
richardparker 0:839ecbf5cb2a 190 if ((x + w) > width())
richardparker 0:839ecbf5cb2a 191 {
richardparker 0:839ecbf5cb2a 192 w = width()-x;
richardparker 0:839ecbf5cb2a 193 }
richardparker 0:839ecbf5cb2a 194
richardparker 0:839ecbf5cb2a 195 if ((y + h) > height())
richardparker 0:839ecbf5cb2a 196 {
richardparker 0:839ecbf5cb2a 197 h = height()-y;
richardparker 0:839ecbf5cb2a 198 }
richardparker 0:839ecbf5cb2a 199
richardparker 0:839ecbf5cb2a 200 // Move x and y to correct location.
richardparker 0:839ecbf5cb2a 201 if (x < 0)
richardparker 0:839ecbf5cb2a 202 {
richardparker 0:839ecbf5cb2a 203 x = 0;
richardparker 0:839ecbf5cb2a 204 }
richardparker 0:839ecbf5cb2a 205
richardparker 0:839ecbf5cb2a 206 if (y < 0)
richardparker 0:839ecbf5cb2a 207 {
richardparker 0:839ecbf5cb2a 208 y = 0;
richardparker 0:839ecbf5cb2a 209 }
richardparker 0:839ecbf5cb2a 210
richardparker 0:839ecbf5cb2a 211 y = height() - 1 - y;
richardparker 0:839ecbf5cb2a 212
richardparker 0:839ecbf5cb2a 213 // Vertical.
richardparker 0:839ecbf5cb2a 214 unsigned short hsa = y - h + 1;
richardparker 0:839ecbf5cb2a 215 unsigned short hea = y;
richardparker 0:839ecbf5cb2a 216 hea = hea << 8;
richardparker 0:839ecbf5cb2a 217
richardparker 0:839ecbf5cb2a 218 _writeToRegister(0x44, hsa | hea);
richardparker 0:839ecbf5cb2a 219
richardparker 0:839ecbf5cb2a 220 // Horizontal
richardparker 0:839ecbf5cb2a 221 unsigned short vsa = x;
richardparker 0:839ecbf5cb2a 222 unsigned short vea = x + w - 1;
richardparker 0:839ecbf5cb2a 223
richardparker 0:839ecbf5cb2a 224 _writeToRegister(0x45, vsa);
richardparker 0:839ecbf5cb2a 225 _writeToRegister(0x46, vea);
richardparker 0:839ecbf5cb2a 226 }
richardparker 0:839ecbf5cb2a 227
richardparker 0:839ecbf5cb2a 228 void EALCD::_getTouch(unsigned short& x, unsigned short& y, unsigned short& z1, unsigned short& z2)
richardparker 0:839ecbf5cb2a 229 {
richardparker 0:839ecbf5cb2a 230 // As about to change clock freq and so data is not valid for screen disable.
richardparker 0:839ecbf5cb2a 231 _cs = 1;
richardparker 0:839ecbf5cb2a 232
richardparker 0:839ecbf5cb2a 233 x = 0;
richardparker 0:839ecbf5cb2a 234 y = 0;
richardparker 0:839ecbf5cb2a 235 z1 = 0;
richardparker 0:839ecbf5cb2a 236 z2 = 0;
richardparker 0:839ecbf5cb2a 237
richardparker 0:839ecbf5cb2a 238 // Set comm frequency to access touch screen.
richardparker 0:839ecbf5cb2a 239 _comm.frequency(EALCD_TOUCH_FREQ);
richardparker 0:839ecbf5cb2a 240
richardparker 0:839ecbf5cb2a 241 // Read the x value.
richardparker 0:839ecbf5cb2a 242 // Activate the chip (active low).
richardparker 0:839ecbf5cb2a 243 _tch_cs = 0;
richardparker 0:839ecbf5cb2a 244
richardparker 0:839ecbf5cb2a 245 // 0x83 = Set start bit high, power mode is 2'b11 (always on).
richardparker 0:839ecbf5cb2a 246 // 0x50 = Set address to 3'b101
richardparker 0:839ecbf5cb2a 247 _comm.write(0x83 | 0x50 | 0x00);
richardparker 0:839ecbf5cb2a 248 // Read two bytes in, the last 3 bits are uninteresting (12 bit reading).
richardparker 0:839ecbf5cb2a 249 x = _comm.write(0x00) << 8;
richardparker 0:839ecbf5cb2a 250 x = x | _comm.write(0x00);
richardparker 0:839ecbf5cb2a 251 x = x << 1;
richardparker 0:839ecbf5cb2a 252 x = x >> 4;
richardparker 0:839ecbf5cb2a 253
richardparker 0:839ecbf5cb2a 254 // Deactivate the chip (active low).
richardparker 0:839ecbf5cb2a 255 _tch_cs = 1;
richardparker 0:839ecbf5cb2a 256
richardparker 0:839ecbf5cb2a 257 // Read the y value.
richardparker 0:839ecbf5cb2a 258 // Activate the chip (active low).
richardparker 0:839ecbf5cb2a 259 _tch_cs = 0;
richardparker 0:839ecbf5cb2a 260
richardparker 0:839ecbf5cb2a 261 // 0x83 = Set start bit high, power mode is 2'b11 (always on).
richardparker 0:839ecbf5cb2a 262 // 0x50 = Set address to 3'b001
richardparker 0:839ecbf5cb2a 263 _comm.write(0x83 | 0x10 | 0x00);
richardparker 0:839ecbf5cb2a 264 // Read two bytes in, the last 3 bits are uninteresting (12 bit reading).
richardparker 0:839ecbf5cb2a 265 y = _comm.write(0x00) << 8;
richardparker 0:839ecbf5cb2a 266 y = y | _comm.write(0x00);
richardparker 0:839ecbf5cb2a 267 y = y << 1;
richardparker 0:839ecbf5cb2a 268 y = y >> 4;
richardparker 0:839ecbf5cb2a 269
richardparker 0:839ecbf5cb2a 270 // Deactivate the chip (active low).
richardparker 0:839ecbf5cb2a 271 _tch_cs = 1;
richardparker 0:839ecbf5cb2a 272
richardparker 0:839ecbf5cb2a 273 // Read the z1 value.
richardparker 0:839ecbf5cb2a 274 // Activate the chip (active low).
richardparker 0:839ecbf5cb2a 275 _tch_cs = 0;
richardparker 0:839ecbf5cb2a 276
richardparker 0:839ecbf5cb2a 277 // 0x83 = Set start bit high, power mode is 2'b11 (always on).
richardparker 0:839ecbf5cb2a 278 // 0x50 = Set address to 3'b011
richardparker 0:839ecbf5cb2a 279 _comm.write(0x83 | 0x30 | 0x00);
richardparker 0:839ecbf5cb2a 280 // Read two bytes in, the last 3 bits are uninteresting (12 bit reading).
richardparker 0:839ecbf5cb2a 281 z1 = _comm.write(0x00) << 8;
richardparker 0:839ecbf5cb2a 282 z1 = z1 | _comm.write(0x00);
richardparker 0:839ecbf5cb2a 283 z1 = z1 << 1;
richardparker 0:839ecbf5cb2a 284 z1 = z1 >> 4;
richardparker 0:839ecbf5cb2a 285
richardparker 0:839ecbf5cb2a 286 // Deactivate the chip (active low).
richardparker 0:839ecbf5cb2a 287 _tch_cs = 1;
richardparker 0:839ecbf5cb2a 288
richardparker 0:839ecbf5cb2a 289 // Read the z2 value.
richardparker 0:839ecbf5cb2a 290 // Activate the chip (active low).
richardparker 0:839ecbf5cb2a 291 _tch_cs = 0;
richardparker 0:839ecbf5cb2a 292
richardparker 0:839ecbf5cb2a 293 // 0x83 = Set start bit high, power mode is 2'b11 (always on).
richardparker 0:839ecbf5cb2a 294 // 0x50 = Set address to 3'b100
richardparker 0:839ecbf5cb2a 295 _comm.write(0x83 | 0x40 | 0x00);
richardparker 0:839ecbf5cb2a 296 // Read two bytes in, the last 3 bits are uninteresting (12 bit reading).
richardparker 0:839ecbf5cb2a 297 z2 = _comm.write(0x00) << 8;
richardparker 0:839ecbf5cb2a 298 z2 = z2 | _comm.write(0x00);
richardparker 0:839ecbf5cb2a 299 z2 = z2 << 1;
richardparker 0:839ecbf5cb2a 300 z2 = z2 >> 4;
richardparker 0:839ecbf5cb2a 301
richardparker 0:839ecbf5cb2a 302 // Deactivate the chip (active low).
richardparker 0:839ecbf5cb2a 303 _tch_cs = 1;
richardparker 0:839ecbf5cb2a 304
richardparker 0:839ecbf5cb2a 305 // Set comm frequency to access lcd.
richardparker 0:839ecbf5cb2a 306 _comm.frequency(EALCD_LCD_FREQ);
richardparker 0:839ecbf5cb2a 307 }
richardparker 0:839ecbf5cb2a 308
richardparker 0:839ecbf5cb2a 309 void EALCD::_drawPoint(short x, short y, unsigned short c)
richardparker 0:839ecbf5cb2a 310 {
richardparker 0:839ecbf5cb2a 311 // No need to draw if off screen.
richardparker 0:839ecbf5cb2a 312 if ((x >= width())
richardparker 0:839ecbf5cb2a 313 ||
richardparker 0:839ecbf5cb2a 314 (y >= height())
richardparker 0:839ecbf5cb2a 315 ||
richardparker 0:839ecbf5cb2a 316 (x < 0)
richardparker 0:839ecbf5cb2a 317 ||
richardparker 0:839ecbf5cb2a 318 (y < 0))
richardparker 0:839ecbf5cb2a 319 {
richardparker 0:839ecbf5cb2a 320 return;
richardparker 0:839ecbf5cb2a 321 }
richardparker 0:839ecbf5cb2a 322
richardparker 0:839ecbf5cb2a 323 // Move to the position on the screen to place the pixel.
richardparker 0:839ecbf5cb2a 324 _moveTo(x, y);
richardparker 0:839ecbf5cb2a 325
richardparker 0:839ecbf5cb2a 326 // Draw the pixel with the current pen value.
richardparker 0:839ecbf5cb2a 327 _writeToDisplay(c);
richardparker 0:839ecbf5cb2a 328 }
richardparker 0:839ecbf5cb2a 329
richardparker 0:839ecbf5cb2a 330 void EALCD::_swap(short& i, short& j)
richardparker 0:839ecbf5cb2a 331 {
richardparker 0:839ecbf5cb2a 332 short temp = i;
richardparker 0:839ecbf5cb2a 333 i = j;
richardparker 0:839ecbf5cb2a 334 j = temp;
richardparker 0:839ecbf5cb2a 335 }
richardparker 0:839ecbf5cb2a 336
richardparker 0:839ecbf5cb2a 337 void EALCD::_draw4EllipsePoints(short cX, short cY, short x, short y, bool filled)
richardparker 0:839ecbf5cb2a 338 {
richardparker 0:839ecbf5cb2a 339 if (filled == true)
richardparker 0:839ecbf5cb2a 340 {
richardparker 0:839ecbf5cb2a 341 // line in quadrant 2 to 1.
richardparker 0:839ecbf5cb2a 342 _drawLine(cX-x, cY+y, cX+x, cY+y, _brush.color().rawValue());
richardparker 0:839ecbf5cb2a 343 // Point in quadrant 3 to 4.
richardparker 0:839ecbf5cb2a 344 _drawLine(cX-x, cY-y, cX+x, cY-y, _brush.color().rawValue());
richardparker 0:839ecbf5cb2a 345 } else {
richardparker 0:839ecbf5cb2a 346 // Point in quadrant 1.
richardparker 0:839ecbf5cb2a 347 _drawPoint(cX+x, cY+y, _pen.color().rawValue());
richardparker 0:839ecbf5cb2a 348 // Point in quadrant 2.
richardparker 0:839ecbf5cb2a 349 _drawPoint(cX-x, cY+y, _pen.color().rawValue());
richardparker 0:839ecbf5cb2a 350 // Point in quadrant 3.
richardparker 0:839ecbf5cb2a 351 _drawPoint(cX-x, cY-y, _pen.color().rawValue());
richardparker 0:839ecbf5cb2a 352 // Point in quadrant 4.
richardparker 0:839ecbf5cb2a 353 _drawPoint(cX+x, cY-y, _pen.color().rawValue());
richardparker 0:839ecbf5cb2a 354 }
richardparker 0:839ecbf5cb2a 355 }
richardparker 0:839ecbf5cb2a 356
richardparker 0:839ecbf5cb2a 357 void EALCD::_drawEllipse(short x, short y, unsigned short w, unsigned short h, bool filled)
richardparker 0:839ecbf5cb2a 358 {
richardparker 0:839ecbf5cb2a 359 // Algorithm taken from http://homepage.smc.edu/kennedy_john/belipse.pdf
richardparker 0:839ecbf5cb2a 360 short xRadius = w/2;
richardparker 0:839ecbf5cb2a 361 short yRadius = h/2;
richardparker 0:839ecbf5cb2a 362 short cX = x + xRadius;
richardparker 0:839ecbf5cb2a 363 short cY = y + yRadius;
richardparker 0:839ecbf5cb2a 364
richardparker 0:839ecbf5cb2a 365 int xChange = yRadius*yRadius*(1 - 2*xRadius);
richardparker 0:839ecbf5cb2a 366 int yChange = xRadius*xRadius;
richardparker 0:839ecbf5cb2a 367 int ellipseError = 0;
richardparker 0:839ecbf5cb2a 368 int twoASquare = 2*xRadius*xRadius;
richardparker 0:839ecbf5cb2a 369 int twoBSquare = 2*yRadius*yRadius;
richardparker 0:839ecbf5cb2a 370 int stoppingX = twoBSquare*xRadius;
richardparker 0:839ecbf5cb2a 371 int stoppingY = 0;
richardparker 0:839ecbf5cb2a 372
richardparker 0:839ecbf5cb2a 373 x = xRadius;
richardparker 0:839ecbf5cb2a 374 y = 0;
richardparker 0:839ecbf5cb2a 375
richardparker 0:839ecbf5cb2a 376 while (stoppingX >= stoppingY)
richardparker 0:839ecbf5cb2a 377 {
richardparker 0:839ecbf5cb2a 378 // 1st set of points, y' > -1.
richardparker 0:839ecbf5cb2a 379 _draw4EllipsePoints(cX, cY, x, y, filled);
richardparker 0:839ecbf5cb2a 380 y += 1;
richardparker 0:839ecbf5cb2a 381 stoppingY += twoASquare;
richardparker 0:839ecbf5cb2a 382 ellipseError += yChange;
richardparker 0:839ecbf5cb2a 383 yChange += twoASquare;
richardparker 0:839ecbf5cb2a 384 if ((2*ellipseError + yChange) > 0)
richardparker 0:839ecbf5cb2a 385 {
richardparker 0:839ecbf5cb2a 386 x -= 1;
richardparker 0:839ecbf5cb2a 387 stoppingX -= twoBSquare;
richardparker 0:839ecbf5cb2a 388 ellipseError += xChange;
richardparker 0:839ecbf5cb2a 389 xChange += twoBSquare;
richardparker 0:839ecbf5cb2a 390 }
richardparker 0:839ecbf5cb2a 391 }
richardparker 0:839ecbf5cb2a 392
richardparker 0:839ecbf5cb2a 393 // 1st point set is done; start the 2nd set of points.
richardparker 0:839ecbf5cb2a 394 x = 0;
richardparker 0:839ecbf5cb2a 395 y = yRadius-1;
richardparker 0:839ecbf5cb2a 396 xChange = yRadius*yRadius;
richardparker 0:839ecbf5cb2a 397 yChange = xRadius*xRadius*(1 - 2*yRadius);
richardparker 0:839ecbf5cb2a 398 ellipseError = 0;
richardparker 0:839ecbf5cb2a 399 stoppingX = 0;
richardparker 0:839ecbf5cb2a 400 stoppingY = twoASquare*yRadius;
richardparker 0:839ecbf5cb2a 401
richardparker 0:839ecbf5cb2a 402 while (stoppingX <= stoppingY)
richardparker 0:839ecbf5cb2a 403 {
richardparker 0:839ecbf5cb2a 404 // 2nd set of points, y' < -1.
richardparker 0:839ecbf5cb2a 405 _draw4EllipsePoints(cX, cY, x, y, filled);
richardparker 0:839ecbf5cb2a 406 x += 1;
richardparker 0:839ecbf5cb2a 407 stoppingX += twoBSquare;
richardparker 0:839ecbf5cb2a 408 ellipseError += xChange;
richardparker 0:839ecbf5cb2a 409 xChange += twoBSquare;
richardparker 0:839ecbf5cb2a 410
richardparker 0:839ecbf5cb2a 411 if ((2*ellipseError + yChange) > 0)
richardparker 0:839ecbf5cb2a 412 {
richardparker 0:839ecbf5cb2a 413 y -= 1;
richardparker 0:839ecbf5cb2a 414 stoppingY -= twoASquare;
richardparker 0:839ecbf5cb2a 415 ellipseError += yChange;
richardparker 0:839ecbf5cb2a 416 yChange += twoASquare;
richardparker 0:839ecbf5cb2a 417 }
richardparker 0:839ecbf5cb2a 418 }
richardparker 0:839ecbf5cb2a 419 }
richardparker 0:839ecbf5cb2a 420
richardparker 0:839ecbf5cb2a 421 void EALCD::_drawLine(short x0, short y0, short x1, short y1, unsigned short c)
richardparker 0:839ecbf5cb2a 422 {
richardparker 0:839ecbf5cb2a 423 // Check if can be done faster.
richardparker 3:24fbf4dbd7e5 424 /*
richardparker 0:839ecbf5cb2a 425 if (y0 == y1)
richardparker 0:839ecbf5cb2a 426 {
richardparker 0:839ecbf5cb2a 427 // Not on screen so don't draw.
richardparker 0:839ecbf5cb2a 428 if ((y0 >= height()) || (y0 < 0))
richardparker 0:839ecbf5cb2a 429 {
richardparker 0:839ecbf5cb2a 430 return;
richardparker 0:839ecbf5cb2a 431 }
richardparker 0:839ecbf5cb2a 432
richardparker 0:839ecbf5cb2a 433 // Horizontal line.
richardparker 0:839ecbf5cb2a 434 unsigned short sx = (x0 < x1) ? x0 : x1;
richardparker 0:839ecbf5cb2a 435 unsigned short length = abs(x1 - x0);
richardparker 0:839ecbf5cb2a 436
richardparker 0:839ecbf5cb2a 437 // Make sure not going off edge of screen.
richardparker 0:839ecbf5cb2a 438 if (sx+length > width())
richardparker 0:839ecbf5cb2a 439 {
richardparker 0:839ecbf5cb2a 440 length = width()-sx;
richardparker 0:839ecbf5cb2a 441 }
richardparker 0:839ecbf5cb2a 442
richardparker 0:839ecbf5cb2a 443 // Move to start of line and just draw.
richardparker 0:839ecbf5cb2a 444 _moveTo(sx, y0);
richardparker 0:839ecbf5cb2a 445 for (int i = 0; i < length; i++)
richardparker 0:839ecbf5cb2a 446 {
richardparker 0:839ecbf5cb2a 447 _writeToDisplay(c);
richardparker 0:839ecbf5cb2a 448 }
richardparker 0:839ecbf5cb2a 449
richardparker 0:839ecbf5cb2a 450 return;
richardparker 0:839ecbf5cb2a 451 }
richardparker 3:24fbf4dbd7e5 452 */
richardparker 0:839ecbf5cb2a 453
richardparker 0:839ecbf5cb2a 454 // This code is from http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm - the fast section i.e.
richardparker 0:839ecbf5cb2a 455 // relies on only integer maths.
richardparker 0:839ecbf5cb2a 456
richardparker 0:839ecbf5cb2a 457 bool steep = (abs(y1 - y0) > abs(x1 - x0));
richardparker 0:839ecbf5cb2a 458
richardparker 0:839ecbf5cb2a 459 if (steep == true)
richardparker 0:839ecbf5cb2a 460 {
richardparker 0:839ecbf5cb2a 461 _swap(x0, y0);
richardparker 0:839ecbf5cb2a 462 _swap(x1, y1);
richardparker 0:839ecbf5cb2a 463 }
richardparker 0:839ecbf5cb2a 464
richardparker 0:839ecbf5cb2a 465 if (x0 > x1)
richardparker 0:839ecbf5cb2a 466 {
richardparker 0:839ecbf5cb2a 467 _swap(x0, x1);
richardparker 0:839ecbf5cb2a 468 _swap(y0, y1);
richardparker 0:839ecbf5cb2a 469 }
richardparker 0:839ecbf5cb2a 470
richardparker 0:839ecbf5cb2a 471 int deltaX = x1 - x0;
richardparker 0:839ecbf5cb2a 472 int deltaY = abs(y1 - y0);
richardparker 0:839ecbf5cb2a 473 int error = deltaX / 2;
richardparker 0:839ecbf5cb2a 474 int yStep;
richardparker 0:839ecbf5cb2a 475 int y = y0;
richardparker 0:839ecbf5cb2a 476 int x = 0;
richardparker 0:839ecbf5cb2a 477
richardparker 0:839ecbf5cb2a 478 if (y0 < y1)
richardparker 0:839ecbf5cb2a 479 {
richardparker 0:839ecbf5cb2a 480 yStep = 1;
richardparker 0:839ecbf5cb2a 481 } else {
richardparker 0:839ecbf5cb2a 482 yStep = -1;
richardparker 0:839ecbf5cb2a 483 }
richardparker 0:839ecbf5cb2a 484
richardparker 0:839ecbf5cb2a 485 // Now actually loop and draw the line.
richardparker 0:839ecbf5cb2a 486 for (x = x0; x < x1; x++)
richardparker 0:839ecbf5cb2a 487 {
richardparker 0:839ecbf5cb2a 488 // Channge drawing if drawing horizontal or vertical.
richardparker 0:839ecbf5cb2a 489 if (steep == true)
richardparker 0:839ecbf5cb2a 490 {
richardparker 0:839ecbf5cb2a 491 _drawPoint(y, x, c);
richardparker 0:839ecbf5cb2a 492 } else {
richardparker 0:839ecbf5cb2a 493 _drawPoint(x, y, c);
richardparker 0:839ecbf5cb2a 494 }
richardparker 0:839ecbf5cb2a 495
richardparker 0:839ecbf5cb2a 496 // Calculate the error to decide to step or not.
richardparker 0:839ecbf5cb2a 497 error = error - deltaY;
richardparker 0:839ecbf5cb2a 498
richardparker 0:839ecbf5cb2a 499 if (error < 0)
richardparker 0:839ecbf5cb2a 500 {
richardparker 0:839ecbf5cb2a 501 y = y + yStep;
richardparker 0:839ecbf5cb2a 502 error = error + deltaX;
richardparker 0:839ecbf5cb2a 503 }
richardparker 0:839ecbf5cb2a 504 }
richardparker 0:839ecbf5cb2a 505 }
richardparker 0:839ecbf5cb2a 506
richardparker 0:839ecbf5cb2a 507 void EALCD::clearScreen()
richardparker 0:839ecbf5cb2a 508 {
richardparker 0:839ecbf5cb2a 509 // First move to the top left.
richardparker 0:839ecbf5cb2a 510 _window(0, 0, width(), height());
richardparker 0:839ecbf5cb2a 511 _moveTo(0, 0);
richardparker 0:839ecbf5cb2a 512
richardparker 0:839ecbf5cb2a 513 // Now fill in relying on the addresses to be automatically updated.
richardparker 0:839ecbf5cb2a 514 for(int i = 0; i < (width()*height()); i++)
richardparker 0:839ecbf5cb2a 515 {
richardparker 0:839ecbf5cb2a 516 _writeToDisplay(_brush.color().rawValue());
richardparker 0:839ecbf5cb2a 517 }
richardparker 0:839ecbf5cb2a 518 }
richardparker 0:839ecbf5cb2a 519
richardparker 0:839ecbf5cb2a 520 void EALCD::drawPoint(short x, short y)
richardparker 0:839ecbf5cb2a 521 {
richardparker 0:839ecbf5cb2a 522 // Draw the pixel with the current pen value.
richardparker 0:839ecbf5cb2a 523 _drawPoint(x, y, _pen.color().rawValue());
richardparker 0:839ecbf5cb2a 524 }
richardparker 0:839ecbf5cb2a 525
richardparker 0:839ecbf5cb2a 526 void EALCD::drawLine(short x0, short y0, short x1, short y1)
richardparker 0:839ecbf5cb2a 527 {
richardparker 0:839ecbf5cb2a 528 _drawLine(x0, y0, x1, y1, _pen.color().rawValue());
richardparker 0:839ecbf5cb2a 529 }
richardparker 0:839ecbf5cb2a 530
richardparker 0:839ecbf5cb2a 531 void EALCD::drawRect(short x, short y, unsigned short w, unsigned short h)
richardparker 0:839ecbf5cb2a 532 {
richardparker 0:839ecbf5cb2a 533 // Draw the top horizontal line.
richardparker 0:839ecbf5cb2a 534 drawLine(x, y, x + w - 1, y);
richardparker 0:839ecbf5cb2a 535
richardparker 0:839ecbf5cb2a 536 // Draw the bottom horizontal line.
richardparker 0:839ecbf5cb2a 537 drawLine(x, y + h - 1, x + w - 1, y + h - 1);
richardparker 0:839ecbf5cb2a 538
richardparker 0:839ecbf5cb2a 539 // Draw the left vertical line.
richardparker 0:839ecbf5cb2a 540 drawLine(x, y, x, y + h - 1);
richardparker 0:839ecbf5cb2a 541
richardparker 0:839ecbf5cb2a 542 // Draw the right vertical line.
richardparker 0:839ecbf5cb2a 543 drawLine(x + w - 1, y, x + w - 1, y + h);
richardparker 0:839ecbf5cb2a 544 }
richardparker 0:839ecbf5cb2a 545
richardparker 0:839ecbf5cb2a 546 void EALCD::drawFilledRect(short x, short y, unsigned short w, unsigned short h)
richardparker 0:839ecbf5cb2a 547 {
richardparker 0:839ecbf5cb2a 548 if (x < 0)
richardparker 0:839ecbf5cb2a 549 {
richardparker 0:839ecbf5cb2a 550 x = 0;
richardparker 0:839ecbf5cb2a 551 }
richardparker 0:839ecbf5cb2a 552
richardparker 0:839ecbf5cb2a 553 if (y < 0)
richardparker 0:839ecbf5cb2a 554 {
richardparker 0:839ecbf5cb2a 555 y = 0;
richardparker 0:839ecbf5cb2a 556 }
richardparker 0:839ecbf5cb2a 557
richardparker 0:839ecbf5cb2a 558 // Set the window so that automatically wrap and go inside the box.
richardparker 0:839ecbf5cb2a 559 _window(x, y, w, h);
richardparker 0:839ecbf5cb2a 560 _moveTo(x, y);
richardparker 0:839ecbf5cb2a 561
richardparker 0:839ecbf5cb2a 562 for (int i = 0; i < (w*h); i++)
richardparker 0:839ecbf5cb2a 563 {
richardparker 0:839ecbf5cb2a 564 _writeToDisplay(_brush.color().rawValue());
richardparker 0:839ecbf5cb2a 565 }
richardparker 0:839ecbf5cb2a 566
richardparker 0:839ecbf5cb2a 567 drawRect(x, y, w, h);
richardparker 3:24fbf4dbd7e5 568
richardparker 3:24fbf4dbd7e5 569 // Reset window to whole of the screen.
richardparker 3:24fbf4dbd7e5 570 _window(0, 0, width(), height());
richardparker 0:839ecbf5cb2a 571 }
richardparker 0:839ecbf5cb2a 572
richardparker 0:839ecbf5cb2a 573
richardparker 0:839ecbf5cb2a 574 void EALCD::drawEllipse(short x, short y, unsigned short w, unsigned short h)
richardparker 0:839ecbf5cb2a 575 {
richardparker 0:839ecbf5cb2a 576 _drawEllipse(x, y, w, h, false);
richardparker 0:839ecbf5cb2a 577 }
richardparker 0:839ecbf5cb2a 578
richardparker 0:839ecbf5cb2a 579 void EALCD::drawFilledEllipse(short x, short y, unsigned short w, unsigned short h)
richardparker 0:839ecbf5cb2a 580 {
richardparker 0:839ecbf5cb2a 581 _drawEllipse(x, y, w, h, true);
richardparker 0:839ecbf5cb2a 582 _drawEllipse(x, y, w, h, false);
richardparker 0:839ecbf5cb2a 583 }
richardparker 0:839ecbf5cb2a 584
richardparker 0:839ecbf5cb2a 585 void EALCD::drawImage(unsigned short x, unsigned short y, EAImage& img)
richardparker 0:839ecbf5cb2a 586 {
richardparker 0:839ecbf5cb2a 587 // Don't try painting an invalid image.
richardparker 0:839ecbf5cb2a 588 if (img.isValid() == false)
richardparker 0:839ecbf5cb2a 589 {
richardparker 0:839ecbf5cb2a 590 return;
richardparker 0:839ecbf5cb2a 591 }
richardparker 0:839ecbf5cb2a 592
richardparker 0:839ecbf5cb2a 593 // Set the position to draw.
richardparker 0:839ecbf5cb2a 594 img.setX(x);
richardparker 0:839ecbf5cb2a 595 img.setY(y);
richardparker 0:839ecbf5cb2a 596
richardparker 0:839ecbf5cb2a 597 // Draw the image.
richardparker 0:839ecbf5cb2a 598 img.paint(*this);
richardparker 0:839ecbf5cb2a 599 }
richardparker 0:839ecbf5cb2a 600
richardparker 0:839ecbf5cb2a 601 void EALCD::drawText(unsigned short x, unsigned short y, char* text)
richardparker 0:839ecbf5cb2a 602 {
richardparker 0:839ecbf5cb2a 603 // Don't try painting with an invalid font or no text
richardparker 0:839ecbf5cb2a 604 if ((_font.isValid() == false) || (text == NULL))
richardparker 0:839ecbf5cb2a 605 {
richardparker 0:839ecbf5cb2a 606 return;
richardparker 0:839ecbf5cb2a 607 }
richardparker 0:839ecbf5cb2a 608
richardparker 0:839ecbf5cb2a 609 EAImage img;
richardparker 0:839ecbf5cb2a 610 EAFont::EACharacter detail;
richardparker 0:839ecbf5cb2a 611
richardparker 0:839ecbf5cb2a 612 img.load(_font.path());
richardparker 1:f04bcaea1d60 613 // Treat the font image as a mask to allow pen colour to be used for the text.
richardparker 1:f04bcaea1d60 614 img.setMask(true);
richardparker 0:839ecbf5cb2a 615
richardparker 0:839ecbf5cb2a 616 for (int i = 0; i < strlen(text); i++)
richardparker 0:839ecbf5cb2a 617 {
richardparker 0:839ecbf5cb2a 618 if (_font.getCharacter(text[i], detail) == true)
richardparker 0:839ecbf5cb2a 619 {
richardparker 0:839ecbf5cb2a 620 img.setX(x+detail.xOffset);
richardparker 0:839ecbf5cb2a 621 img.setY(y+detail.yOffset);
richardparker 0:839ecbf5cb2a 622 img.paint(*this, detail.x, detail.y, detail.width, detail.height);
richardparker 0:839ecbf5cb2a 623
richardparker 0:839ecbf5cb2a 624 x += detail.xAdvance;
richardparker 0:839ecbf5cb2a 625 } else {
richardparker 0:839ecbf5cb2a 626 // Character is unrecognised.
richardparker 0:839ecbf5cb2a 627 }
richardparker 0:839ecbf5cb2a 628 }
richardparker 0:839ecbf5cb2a 629 }
richardparker 1:f04bcaea1d60 630
richardparker 1:f04bcaea1d60 631 void EALCD::noop()
richardparker 1:f04bcaea1d60 632 {
richardparker 1:f04bcaea1d60 633 // Turn off the mask so that nothing written.
richardparker 1:f04bcaea1d60 634 _writeToRegister(0x23, 0xfcfc);
richardparker 1:f04bcaea1d60 635 _writeToRegister(0x24, 0x00fc);
richardparker 1:f04bcaea1d60 636
richardparker 1:f04bcaea1d60 637 // Write blank to increment address.
richardparker 1:f04bcaea1d60 638 _writeToDisplay(0x0000);
richardparker 1:f04bcaea1d60 639
richardparker 1:f04bcaea1d60 640 // Turn mask back on.
richardparker 1:f04bcaea1d60 641 _writeToRegister(0x23, 0x0000);
richardparker 1:f04bcaea1d60 642 _writeToRegister(0x24, 0x0000);
richardparker 1:f04bcaea1d60 643 }