Richard Parker / EALCD
Committer:
richardparker
Date:
Thu Mar 04 10:54:06 2010 +0000
Revision:
1:f04bcaea1d60
Parent:
0:839ecbf5cb2a
Child:
3:24fbf4dbd7e5

        

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