Richard Parker / EALCD
Committer:
richardparker
Date:
Wed Mar 31 22:22:21 2010 +0000
Revision:
3:24fbf4dbd7e5
Parent:
1:f04bcaea1d60
Child:
4:f8f7f4f9c58d

        

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 3:24fbf4dbd7e5 423 /*
richardparker 0:839ecbf5cb2a 424 if (y0 == y1)
richardparker 0:839ecbf5cb2a 425 {
richardparker 0:839ecbf5cb2a 426 // Not on screen so don't draw.
richardparker 0:839ecbf5cb2a 427 if ((y0 >= height()) || (y0 < 0))
richardparker 0:839ecbf5cb2a 428 {
richardparker 0:839ecbf5cb2a 429 return;
richardparker 0:839ecbf5cb2a 430 }
richardparker 0:839ecbf5cb2a 431
richardparker 0:839ecbf5cb2a 432 // Horizontal line.
richardparker 0:839ecbf5cb2a 433 unsigned short sx = (x0 < x1) ? x0 : x1;
richardparker 0:839ecbf5cb2a 434 unsigned short length = abs(x1 - x0);
richardparker 0:839ecbf5cb2a 435
richardparker 0:839ecbf5cb2a 436 // Make sure not going off edge of screen.
richardparker 0:839ecbf5cb2a 437 if (sx+length > width())
richardparker 0:839ecbf5cb2a 438 {
richardparker 0:839ecbf5cb2a 439 length = width()-sx;
richardparker 0:839ecbf5cb2a 440 }
richardparker 0:839ecbf5cb2a 441
richardparker 0:839ecbf5cb2a 442 // Move to start of line and just draw.
richardparker 0:839ecbf5cb2a 443 _moveTo(sx, y0);
richardparker 0:839ecbf5cb2a 444 for (int i = 0; i < length; i++)
richardparker 0:839ecbf5cb2a 445 {
richardparker 0:839ecbf5cb2a 446 _writeToDisplay(c);
richardparker 0:839ecbf5cb2a 447 }
richardparker 0:839ecbf5cb2a 448
richardparker 0:839ecbf5cb2a 449 return;
richardparker 0:839ecbf5cb2a 450 }
richardparker 3:24fbf4dbd7e5 451 */
richardparker 0:839ecbf5cb2a 452
richardparker 0:839ecbf5cb2a 453 // This code is from http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm - the fast section i.e.
richardparker 0:839ecbf5cb2a 454 // relies on only integer maths.
richardparker 0:839ecbf5cb2a 455
richardparker 0:839ecbf5cb2a 456 bool steep = (abs(y1 - y0) > abs(x1 - x0));
richardparker 0:839ecbf5cb2a 457
richardparker 0:839ecbf5cb2a 458 if (steep == true)
richardparker 0:839ecbf5cb2a 459 {
richardparker 0:839ecbf5cb2a 460 _swap(x0, y0);
richardparker 0:839ecbf5cb2a 461 _swap(x1, y1);
richardparker 0:839ecbf5cb2a 462 }
richardparker 0:839ecbf5cb2a 463
richardparker 0:839ecbf5cb2a 464 if (x0 > x1)
richardparker 0:839ecbf5cb2a 465 {
richardparker 0:839ecbf5cb2a 466 _swap(x0, x1);
richardparker 0:839ecbf5cb2a 467 _swap(y0, y1);
richardparker 0:839ecbf5cb2a 468 }
richardparker 0:839ecbf5cb2a 469
richardparker 0:839ecbf5cb2a 470 int deltaX = x1 - x0;
richardparker 0:839ecbf5cb2a 471 int deltaY = abs(y1 - y0);
richardparker 0:839ecbf5cb2a 472 int error = deltaX / 2;
richardparker 0:839ecbf5cb2a 473 int yStep;
richardparker 0:839ecbf5cb2a 474 int y = y0;
richardparker 0:839ecbf5cb2a 475 int x = 0;
richardparker 0:839ecbf5cb2a 476
richardparker 0:839ecbf5cb2a 477 if (y0 < y1)
richardparker 0:839ecbf5cb2a 478 {
richardparker 0:839ecbf5cb2a 479 yStep = 1;
richardparker 0:839ecbf5cb2a 480 } else {
richardparker 0:839ecbf5cb2a 481 yStep = -1;
richardparker 0:839ecbf5cb2a 482 }
richardparker 0:839ecbf5cb2a 483
richardparker 0:839ecbf5cb2a 484 // Now actually loop and draw the line.
richardparker 0:839ecbf5cb2a 485 for (x = x0; x < x1; x++)
richardparker 0:839ecbf5cb2a 486 {
richardparker 0:839ecbf5cb2a 487 // Channge drawing if drawing horizontal or vertical.
richardparker 0:839ecbf5cb2a 488 if (steep == true)
richardparker 0:839ecbf5cb2a 489 {
richardparker 0:839ecbf5cb2a 490 _drawPoint(y, x, c);
richardparker 0:839ecbf5cb2a 491 } else {
richardparker 0:839ecbf5cb2a 492 _drawPoint(x, y, c);
richardparker 0:839ecbf5cb2a 493 }
richardparker 0:839ecbf5cb2a 494
richardparker 0:839ecbf5cb2a 495 // Calculate the error to decide to step or not.
richardparker 0:839ecbf5cb2a 496 error = error - deltaY;
richardparker 0:839ecbf5cb2a 497
richardparker 0:839ecbf5cb2a 498 if (error < 0)
richardparker 0:839ecbf5cb2a 499 {
richardparker 0:839ecbf5cb2a 500 y = y + yStep;
richardparker 0:839ecbf5cb2a 501 error = error + deltaX;
richardparker 0:839ecbf5cb2a 502 }
richardparker 0:839ecbf5cb2a 503 }
richardparker 0:839ecbf5cb2a 504 }
richardparker 0:839ecbf5cb2a 505
richardparker 0:839ecbf5cb2a 506 void EALCD::clearScreen()
richardparker 0:839ecbf5cb2a 507 {
richardparker 0:839ecbf5cb2a 508 // First move to the top left.
richardparker 0:839ecbf5cb2a 509 _window(0, 0, width(), height());
richardparker 0:839ecbf5cb2a 510 _moveTo(0, 0);
richardparker 0:839ecbf5cb2a 511
richardparker 0:839ecbf5cb2a 512 // Now fill in relying on the addresses to be automatically updated.
richardparker 0:839ecbf5cb2a 513 for(int i = 0; i < (width()*height()); i++)
richardparker 0:839ecbf5cb2a 514 {
richardparker 0:839ecbf5cb2a 515 _writeToDisplay(_brush.color().rawValue());
richardparker 0:839ecbf5cb2a 516 }
richardparker 0:839ecbf5cb2a 517 }
richardparker 0:839ecbf5cb2a 518
richardparker 0:839ecbf5cb2a 519 void EALCD::drawPoint(short x, short y)
richardparker 0:839ecbf5cb2a 520 {
richardparker 0:839ecbf5cb2a 521 // Draw the pixel with the current pen value.
richardparker 0:839ecbf5cb2a 522 _drawPoint(x, y, _pen.color().rawValue());
richardparker 0:839ecbf5cb2a 523 }
richardparker 0:839ecbf5cb2a 524
richardparker 0:839ecbf5cb2a 525 void EALCD::drawLine(short x0, short y0, short x1, short y1)
richardparker 0:839ecbf5cb2a 526 {
richardparker 0:839ecbf5cb2a 527 _drawLine(x0, y0, x1, y1, _pen.color().rawValue());
richardparker 0:839ecbf5cb2a 528 }
richardparker 0:839ecbf5cb2a 529
richardparker 0:839ecbf5cb2a 530 void EALCD::drawRect(short x, short y, unsigned short w, unsigned short h)
richardparker 0:839ecbf5cb2a 531 {
richardparker 0:839ecbf5cb2a 532 // Draw the top horizontal line.
richardparker 0:839ecbf5cb2a 533 drawLine(x, y, x + w - 1, y);
richardparker 0:839ecbf5cb2a 534
richardparker 0:839ecbf5cb2a 535 // Draw the bottom horizontal line.
richardparker 0:839ecbf5cb2a 536 drawLine(x, y + h - 1, x + w - 1, y + h - 1);
richardparker 0:839ecbf5cb2a 537
richardparker 0:839ecbf5cb2a 538 // Draw the left vertical line.
richardparker 0:839ecbf5cb2a 539 drawLine(x, y, x, y + h - 1);
richardparker 0:839ecbf5cb2a 540
richardparker 0:839ecbf5cb2a 541 // Draw the right vertical line.
richardparker 0:839ecbf5cb2a 542 drawLine(x + w - 1, y, x + w - 1, y + h);
richardparker 0:839ecbf5cb2a 543 }
richardparker 0:839ecbf5cb2a 544
richardparker 0:839ecbf5cb2a 545 void EALCD::drawFilledRect(short x, short y, unsigned short w, unsigned short h)
richardparker 0:839ecbf5cb2a 546 {
richardparker 0:839ecbf5cb2a 547 if (x < 0)
richardparker 0:839ecbf5cb2a 548 {
richardparker 0:839ecbf5cb2a 549 x = 0;
richardparker 0:839ecbf5cb2a 550 }
richardparker 0:839ecbf5cb2a 551
richardparker 0:839ecbf5cb2a 552 if (y < 0)
richardparker 0:839ecbf5cb2a 553 {
richardparker 0:839ecbf5cb2a 554 y = 0;
richardparker 0:839ecbf5cb2a 555 }
richardparker 0:839ecbf5cb2a 556
richardparker 0:839ecbf5cb2a 557 // Set the window so that automatically wrap and go inside the box.
richardparker 0:839ecbf5cb2a 558 _window(x, y, w, h);
richardparker 0:839ecbf5cb2a 559 _moveTo(x, y);
richardparker 0:839ecbf5cb2a 560
richardparker 0:839ecbf5cb2a 561 for (int i = 0; i < (w*h); i++)
richardparker 0:839ecbf5cb2a 562 {
richardparker 0:839ecbf5cb2a 563 _writeToDisplay(_brush.color().rawValue());
richardparker 0:839ecbf5cb2a 564 }
richardparker 0:839ecbf5cb2a 565
richardparker 0:839ecbf5cb2a 566 drawRect(x, y, w, h);
richardparker 3:24fbf4dbd7e5 567
richardparker 3:24fbf4dbd7e5 568 // Reset window to whole of the screen.
richardparker 3:24fbf4dbd7e5 569 _window(0, 0, width(), height());
richardparker 0:839ecbf5cb2a 570 }
richardparker 0:839ecbf5cb2a 571
richardparker 0:839ecbf5cb2a 572
richardparker 0:839ecbf5cb2a 573 void EALCD::drawEllipse(short x, short y, unsigned short w, unsigned short h)
richardparker 0:839ecbf5cb2a 574 {
richardparker 0:839ecbf5cb2a 575 _drawEllipse(x, y, w, h, false);
richardparker 0:839ecbf5cb2a 576 }
richardparker 0:839ecbf5cb2a 577
richardparker 0:839ecbf5cb2a 578 void EALCD::drawFilledEllipse(short x, short y, unsigned short w, unsigned short h)
richardparker 0:839ecbf5cb2a 579 {
richardparker 0:839ecbf5cb2a 580 _drawEllipse(x, y, w, h, true);
richardparker 0:839ecbf5cb2a 581 _drawEllipse(x, y, w, h, false);
richardparker 0:839ecbf5cb2a 582 }
richardparker 0:839ecbf5cb2a 583
richardparker 0:839ecbf5cb2a 584 void EALCD::drawImage(unsigned short x, unsigned short y, EAImage& img)
richardparker 0:839ecbf5cb2a 585 {
richardparker 0:839ecbf5cb2a 586 // Don't try painting an invalid image.
richardparker 0:839ecbf5cb2a 587 if (img.isValid() == false)
richardparker 0:839ecbf5cb2a 588 {
richardparker 0:839ecbf5cb2a 589 return;
richardparker 0:839ecbf5cb2a 590 }
richardparker 0:839ecbf5cb2a 591
richardparker 0:839ecbf5cb2a 592 // Set the position to draw.
richardparker 0:839ecbf5cb2a 593 img.setX(x);
richardparker 0:839ecbf5cb2a 594 img.setY(y);
richardparker 0:839ecbf5cb2a 595
richardparker 0:839ecbf5cb2a 596 // Draw the image.
richardparker 0:839ecbf5cb2a 597 img.paint(*this);
richardparker 0:839ecbf5cb2a 598 }
richardparker 0:839ecbf5cb2a 599
richardparker 0:839ecbf5cb2a 600 void EALCD::drawText(unsigned short x, unsigned short y, char* text)
richardparker 0:839ecbf5cb2a 601 {
richardparker 0:839ecbf5cb2a 602 // Don't try painting with an invalid font or no text
richardparker 0:839ecbf5cb2a 603 if ((_font.isValid() == false) || (text == NULL))
richardparker 0:839ecbf5cb2a 604 {
richardparker 0:839ecbf5cb2a 605 return;
richardparker 0:839ecbf5cb2a 606 }
richardparker 0:839ecbf5cb2a 607
richardparker 0:839ecbf5cb2a 608 EAImage img;
richardparker 0:839ecbf5cb2a 609 EAFont::EACharacter detail;
richardparker 0:839ecbf5cb2a 610
richardparker 0:839ecbf5cb2a 611 img.load(_font.path());
richardparker 1:f04bcaea1d60 612 // Treat the font image as a mask to allow pen colour to be used for the text.
richardparker 1:f04bcaea1d60 613 img.setMask(true);
richardparker 0:839ecbf5cb2a 614
richardparker 0:839ecbf5cb2a 615 for (int i = 0; i < strlen(text); i++)
richardparker 0:839ecbf5cb2a 616 {
richardparker 0:839ecbf5cb2a 617 if (_font.getCharacter(text[i], detail) == true)
richardparker 0:839ecbf5cb2a 618 {
richardparker 0:839ecbf5cb2a 619 img.setX(x+detail.xOffset);
richardparker 0:839ecbf5cb2a 620 img.setY(y+detail.yOffset);
richardparker 0:839ecbf5cb2a 621 img.paint(*this, detail.x, detail.y, detail.width, detail.height);
richardparker 0:839ecbf5cb2a 622
richardparker 0:839ecbf5cb2a 623 x += detail.xAdvance;
richardparker 0:839ecbf5cb2a 624 } else {
richardparker 0:839ecbf5cb2a 625 // Character is unrecognised.
richardparker 0:839ecbf5cb2a 626 }
richardparker 0:839ecbf5cb2a 627 }
richardparker 0:839ecbf5cb2a 628 }
richardparker 1:f04bcaea1d60 629
richardparker 1:f04bcaea1d60 630 void EALCD::noop()
richardparker 1:f04bcaea1d60 631 {
richardparker 1:f04bcaea1d60 632 // Turn off the mask so that nothing written.
richardparker 1:f04bcaea1d60 633 _writeToRegister(0x23, 0xfcfc);
richardparker 1:f04bcaea1d60 634 _writeToRegister(0x24, 0x00fc);
richardparker 1:f04bcaea1d60 635
richardparker 1:f04bcaea1d60 636 // Write blank to increment address.
richardparker 1:f04bcaea1d60 637 _writeToDisplay(0x0000);
richardparker 1:f04bcaea1d60 638
richardparker 1:f04bcaea1d60 639 // Turn mask back on.
richardparker 1:f04bcaea1d60 640 _writeToRegister(0x23, 0x0000);
richardparker 1:f04bcaea1d60 641 _writeToRegister(0x24, 0x0000);
richardparker 1:f04bcaea1d60 642 }