Statistics
| Branch: | Revision:

ddr4s / fw / wiringPi / devLib / lcd128x64.c @ 32:cadb9025f1e0

History | View | Annotate | Download (14.4 KB)

1
/*
2
 * lcd128x64.c:
3
 *        Graphics-based LCD driver.
4
 *        This is designed to drive the parallel interface LCD drivers
5
 *        based on the generic 12864H chips
6
 *
7
 *        There are many variations on these chips, however they all mostly
8
 *        seem to be similar.
9
 *        This implementation has the Pins from the Pi hard-wired into it,
10
 *        in particular wiringPi pins 0-7 so that we can use
11
 *        digitalWriteByete() to speed things up somewhat.
12
 *
13
 * Copyright (c) 2013 Gordon Henderson.
14
 ***********************************************************************
15
 * This file is part of wiringPi:
16
 *        https://projects.drogon.net/raspberry-pi/wiringpi/
17
 *
18
 *    wiringPi is free software: you can redistribute it and/or modify
19
 *    it under the terms of the GNU Lesser General Public License as published by
20
 *    the Free Software Foundation, either version 3 of the License, or
21
 *    (at your option) any later version.
22
 *
23
 *    wiringPi is distributed in the hope that it will be useful,
24
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
25
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26
 *    GNU Lesser General Public License for more details.
27
 *
28
 *    You should have received a copy of the GNU Lesser General Public License
29
 *    along with wiringPi.  If not, see <http://www.gnu.org/licenses/>.
30
 ***********************************************************************
31
 */
32

    
33
#include <stdio.h>
34
#include <stdlib.h>
35

    
36
#include <wiringPi.h>
37

    
38
#include "font.h"
39
#include "lcd128x64.h"
40

    
41
// Size
42

    
43
#define        LCD_WIDTH        128
44
#define        LCD_HEIGHT         64
45

    
46
// Hardware Pins
47
//        Note pins 0-7 are the 8-bit data port
48

    
49
#define        CS1                10
50
#define        CS2                11
51
#define        STROBE                12
52
#define        RS                13
53

    
54
// Software copy of the framebuffer
55
//        it's 8-bit deep although the display itself is only 1-bit deep.
56

    
57
static unsigned char frameBuffer [LCD_WIDTH * LCD_HEIGHT] ;
58

    
59
static int maxX,    maxY ;
60
static int lastX,   lastY ;
61
static int xOrigin, yOrigin ;
62
static int lcdOrientation = 0 ;
63

    
64
/*
65
 * strobe:
66
 *        Toggle the strobe (Really the "E") pin to the device.
67
 *        According to the docs, data is latched on the falling edge.
68
 *********************************************************************************
69
 */
70

    
71
static void strobe (void)
72
{
73
  digitalWrite (STROBE, 1) ; delayMicroseconds (1) ;
74
  digitalWrite (STROBE, 0) ; delayMicroseconds (5) ;
75
}
76

    
77

    
78
/*
79
 * sentData:
80
 *        Send an data or command byte to the display.
81
 *********************************************************************************
82
 */
83

    
84
static void sendData (const int data, const int chip)
85
{
86
  digitalWrite     (chip, 0) ;
87
  digitalWriteByte (data) ;
88
  strobe           () ;
89
  digitalWrite     (chip, 1) ;
90
}
91

    
92

    
93
/*
94
 * sendCommand:
95
 *        Send a command byte to the display
96
 *********************************************************************************
97
 */
98

    
99
static void sendCommand (const int command, const int chip)
100
{
101
  digitalWrite (RS, 0) ;
102
  sendData     (command, chip) ;
103
  digitalWrite (RS, 1) ;
104
}
105

    
106

    
107
/*
108
 * setCol: SetLine:
109
 *        Set the column and line addresses
110
 *********************************************************************************
111
 */
112

    
113
static void setCol  (int col, const int chip)
114
  { sendCommand (0x40 | (col  & 0x3F), chip) ; }
115

    
116
static void setLine (int line, const int chip)
117
  { sendCommand (0xB8 | (line & 0x07), chip) ; }
118

    
119

    
120
/*
121
 * lcd128x64update:
122
 *        Copy our software version to the real display
123
 *********************************************************************************
124
 */
125

    
126
void lcd128x64update (void)
127
{
128
  int line, x, y, fbLoc ;
129
  unsigned char byte ;
130

    
131
// Left side 
132

    
133
  for (line = 0 ; line < 8 ; ++line)
134
  {
135
    setCol  (0,    CS1) ;
136
    setLine (line, CS1) ;
137

    
138
    for (x = 63 ; x >= 0 ; --x)
139
    {
140
      byte = 0 ;
141
      for (y = 0 ; y < 8 ; ++y)
142
      {
143
        fbLoc = x + (((7 - line) * 8) + (7 - y)) * LCD_WIDTH ;
144
        if (frameBuffer [fbLoc] != 0)
145
          byte |= (1 << y) ;
146
      }
147
      sendData (byte, CS1) ;
148
    }
149
  }
150

    
151
// Right side 
152

    
153
  for (line = 0 ; line < 8 ; ++line)
154
  {
155
    setCol  (0,    CS2) ;
156
    setLine (line, CS2) ;
157

    
158
    for (x = 127 ; x >= 64 ; --x)
159
    {
160
      byte = 0 ;
161
      for (y = 0 ; y < 8 ; ++y)
162
      {
163
        fbLoc = x + (((7 - line) * 8) + (7 - y)) * LCD_WIDTH ;
164
        if (frameBuffer [fbLoc] != 0)
165
          byte |= (1 << y) ;
166
      }
167
      sendData (byte, CS2) ;
168
    }
169
  }
170
}
171

    
172

    
173
/*
174
 * lcd128x64setOrigin:
175
 *        Set the display offset origin
176
 *********************************************************************************
177
 */
178

    
179
void lcd128x64setOrigin (int x, int y)
180
{
181
  xOrigin = x ;
182
  yOrigin = y ;
183
}
184

    
185

    
186
/*
187
 * lcd128x64setOrientation:
188
 *        Set the display orientation:
189
 *        0: Normal, the display is portrait mode, 0,0 is top left
190
 *        1: Landscape
191
 *        2: Portrait, flipped
192
 *        3: Landscape, flipped
193
 *********************************************************************************
194
 */
195

    
196
void lcd128x64setOrientation (int orientation)
197
{
198
  lcdOrientation = orientation & 3 ;
199

    
200
  lcd128x64setOrigin (0,0) ;
201

    
202
  switch (lcdOrientation)
203
  {
204
    case 0:
205
      maxX = LCD_WIDTH ;
206
      maxY = LCD_HEIGHT ;
207
      break ;
208

    
209
    case 1:
210
      maxX = LCD_HEIGHT ;
211
      maxY = LCD_WIDTH ;
212
      break ;
213

    
214
    case 2:
215
      maxX = LCD_WIDTH ;
216
      maxY = LCD_HEIGHT ;
217
      break ;
218

    
219
    case 3:
220
      maxX = LCD_HEIGHT ;
221
      maxY = LCD_WIDTH ;
222
      break ;
223
  }
224
}
225

    
226

    
227
/*
228
 * lcd128x64orientCoordinates:
229
 *        Adjust the coordinates given to the display orientation
230
 *********************************************************************************
231
 */
232

    
233
void lcd128x64orientCoordinates (int *x, int *y)
234
{
235
  register int tmp ;
236

    
237
  *x += xOrigin ;
238
  *y += yOrigin ;
239
  *y  = maxY - *y - 1 ;
240

    
241
  switch (lcdOrientation)
242
  {
243
    case 0:
244
      break;
245

    
246
    case 1:
247
      tmp = maxY - *y - 1 ;
248
      *y = *x ;
249
      *x = tmp ;
250
      break;
251

    
252
    case 2:
253
      *x = maxX - *x - 1 ;
254
      *y = maxY - *y - 1 ;
255
      break;
256

    
257
    case 3:
258
      *x = maxX - *x - 1 ;
259
      tmp = *y ;
260
      *y = *x ;
261
      *x = tmp ;
262
      break ;
263
  }
264
}
265

    
266

    
267
/*
268
 * lcd128x64getScreenSize:
269
 *        Return the max X & Y screen sizes. Needs to be called again, if you 
270
 *        change screen orientation.
271
 *********************************************************************************
272
 */
273

    
274
void lcd128x64getScreenSize (int *x, int *y)
275
{
276
  *x = maxX ;
277
  *y = maxY ;
278
}
279

    
280

    
281
/*
282
 *********************************************************************************
283
 * Standard Graphical Functions
284
 *********************************************************************************
285
 */
286

    
287

    
288
/*
289
 * lcd128x64point:
290
 *        Plot a pixel.
291
 *********************************************************************************
292
 */
293

    
294
void lcd128x64point (int x, int y, int colour)
295
{
296
  lastX = x ;
297
  lastY = y ;
298

    
299
  lcd128x64orientCoordinates (&x, &y) ;
300

    
301
  if ((x < 0) || (x >= LCD_WIDTH) || (y < 0) || (y >= LCD_HEIGHT))
302
    return ;
303

    
304
  frameBuffer [x + y * LCD_WIDTH] = colour ;
305
}
306

    
307

    
308
/*
309
 * lcd128x64line: lcd128x64lineTo:
310
 *        Classic Bressenham Line code
311
 *********************************************************************************
312
 */
313

    
314
void lcd128x64line (int x0, int y0, int x1, int y1, int colour)
315
{
316
  int dx, dy ;
317
  int sx, sy ;
318
  int err, e2 ;
319

    
320
  lastX = x1 ;
321
  lastY = y1 ;
322

    
323
  dx = abs (x1 - x0) ;
324
  dy = abs (y1 - y0) ;
325

    
326
  sx = (x0 < x1) ? 1 : -1 ;
327
  sy = (y0 < y1) ? 1 : -1 ;
328

    
329
  err = dx - dy ;
330
 
331
  for (;;)
332
  {
333
    lcd128x64point (x0, y0, colour) ;
334

    
335
    if ((x0 == x1) && (y0 == y1))
336
      break ;
337

    
338
    e2 = 2 * err ;
339

    
340
    if (e2 > -dy)
341
    {
342
      err -= dy ;
343
      x0  += sx ;
344
    }
345

    
346
    if (e2 < dx)
347
    {
348
      err += dx ;
349
      y0  += sy ;
350
    }
351
  }
352

    
353
}
354

    
355
void lcd128x64lineTo (int x, int y, int colour)
356
{
357
  lcd128x64line (lastX, lastY, x, y, colour) ;
358
}
359

    
360

    
361
/*
362
 * lcd128x64rectangle:
363
 *        A rectangle is a spoilt days fishing
364
 *********************************************************************************
365
 */
366

    
367
void lcd128x64rectangle (int x1, int y1, int x2, int y2, int colour, int filled)
368
{
369
  register int x ;
370

    
371
  if (filled)
372
  {
373
    /**/ if (x1 == x2)
374
      lcd128x64line (x1, y1, x2, y2, colour) ;
375
    else if (x1 < x2)
376
      for (x = x1 ; x <= x2 ; ++x)
377
        lcd128x64line (x, y1, x, y2, colour) ;
378
    else
379
      for (x = x2 ; x <= x1 ; ++x)
380
        lcd128x64line (x, y1, x, y2, colour) ;
381
  }
382
  else
383
  {
384
    lcd128x64line   (x1, y1, x2, y1, colour) ;
385
    lcd128x64lineTo (x2, y2, colour) ;
386
    lcd128x64lineTo (x1, y2, colour) ;
387
    lcd128x64lineTo (x1, y1, colour) ;
388
  }
389
}
390

    
391

    
392
/*
393
 * lcd128x64circle:
394
 *      This is the midpoint circle algorithm.
395
 *********************************************************************************
396
 */
397

    
398
void lcd128x64circle (int x, int y, int r, int colour, int filled)
399
{
400
  int ddF_x = 1 ;
401
  int ddF_y = -2 * r ;
402

    
403
  int f = 1 - r ;
404
  int x1 = 0 ;
405
  int y1 = r ;
406

    
407
  if (filled)
408
  {
409
    lcd128x64line (x, y + r, x, y - r, colour) ;
410
    lcd128x64line (x + r, y, x - r, y, colour) ;
411
  }
412
  else
413
  {
414
    lcd128x64point (x, y + r, colour) ;
415
    lcd128x64point (x, y - r, colour) ;
416
    lcd128x64point (x + r, y, colour) ;
417
    lcd128x64point (x - r, y, colour) ;
418
  }
419

    
420
  while (x1 < y1)
421
  {
422
    if (f >= 0)
423
    {
424
      y1-- ;
425
      ddF_y += 2 ;
426
      f += ddF_y ;
427
    }
428
    x1++ ;
429
    ddF_x += 2 ;
430
    f += ddF_x ;
431
    if (filled)
432
    {
433
      lcd128x64line (x + x1, y + y1, x - x1, y + y1, colour) ;
434
      lcd128x64line (x + x1, y - y1, x - x1, y - y1, colour) ;
435
      lcd128x64line (x + y1, y + x1, x - y1, y + x1, colour) ;
436
      lcd128x64line (x + y1, y - x1, x - y1, y - x1, colour) ;
437
    }
438
    else
439
    {
440
      lcd128x64point (x + x1, y + y1, colour) ; lcd128x64point (x - x1, y + y1, colour) ;
441
      lcd128x64point (x + x1, y - y1, colour) ; lcd128x64point (x - x1, y - y1, colour) ;
442
      lcd128x64point (x + y1, y + x1, colour) ; lcd128x64point (x - y1, y + x1, colour) ;
443
      lcd128x64point (x + y1, y - x1, colour) ; lcd128x64point (x - y1, y - x1, colour) ;
444
    }
445
  }
446
}
447

    
448

    
449
/*
450
 * lcd128x64ellipse:
451
 *        Fast ellipse drawing algorithm by 
452
 *      John Kennedy
453
 *        Mathematics Department
454
 *        Santa Monica College
455
 *        1900 Pico Blvd.
456
 *        Santa Monica, CA 90405
457
 *        jrkennedy6@gmail.com
458
 *        -Confirned in email this algorithm is in the public domain -GH-
459
 *********************************************************************************
460
 */
461

    
462
static void plot4ellipsePoints (int cx, int cy, int x, int y, int colour, int filled)
463
{
464
  if (filled)
465
  {
466
    lcd128x64line (cx + x, cy + y, cx - x, cy + y, colour) ;
467
    lcd128x64line (cx - x, cy - y, cx + x, cy - y, colour) ;
468
  }
469
  else
470
  {
471
    lcd128x64point (cx + x, cy + y, colour) ;
472
    lcd128x64point (cx - x, cy + y, colour) ;
473
    lcd128x64point (cx - x, cy - y, colour) ;
474
    lcd128x64point (cx + x, cy - y, colour) ;
475
  }
476
}
477

    
478
void lcd128x64ellipse (int cx, int cy, int xRadius, int yRadius, int colour, int filled)
479
{
480
  int x, y ;
481
  int xChange, yChange, ellipseError ;
482
  int twoAsquare, twoBsquare ;
483
  int stoppingX, stoppingY ;
484

    
485
  twoAsquare = 2 * xRadius * xRadius ;
486
  twoBsquare = 2 * yRadius * yRadius ;
487

    
488
  x = xRadius ;
489
  y = 0 ;
490

    
491
  xChange = yRadius * yRadius * (1 - 2 * xRadius) ;
492
  yChange = xRadius * xRadius ;
493

    
494
  ellipseError = 0 ;
495
  stoppingX    = twoBsquare * xRadius ;
496
  stoppingY    = 0 ;
497

    
498
  while (stoppingX >= stoppingY)        // 1st set of points
499
  {
500
    plot4ellipsePoints (cx, cy, x, y, colour, filled) ;
501
    ++y ;
502
    stoppingY    += twoAsquare ;
503
    ellipseError += yChange ;
504
    yChange      += twoAsquare ;
505

    
506
    if ((2 * ellipseError + xChange) > 0 )
507
    {
508
      --x ;
509
      stoppingX    -= twoBsquare ;
510
      ellipseError += xChange ;
511
      xChange      += twoBsquare ;
512
    }
513
  }
514

    
515
  x = 0 ;
516
  y = yRadius ;
517

    
518
  xChange = yRadius * yRadius ;
519
  yChange = xRadius * xRadius * (1 - 2 * yRadius) ;
520

    
521
  ellipseError = 0 ;
522
  stoppingX    = 0 ;
523
  stoppingY    = twoAsquare * yRadius ;
524

    
525
  while (stoppingX <= stoppingY)        //2nd set of points
526
  {
527
    plot4ellipsePoints (cx, cy, x, y, colour, filled) ;
528
    ++x ;
529
    stoppingX    += twoBsquare ;
530
    ellipseError += xChange ;
531
    xChange      += twoBsquare ;
532

    
533
    if ((2 * ellipseError + yChange) > 0 )
534
    {
535
      --y ;
536
      stoppingY -= twoAsquare ;
537
      ellipseError += yChange ;
538
      yChange += twoAsquare ;
539
    }
540
  }
541
}
542

    
543

    
544
/*
545
 * lcd128x64putchar:
546
 *        Print a single character to the screen
547
 *********************************************************************************
548
 */
549

    
550
void lcd128x64putchar (int x, int y, int c, int bgCol, int fgCol)
551
{
552
  int y1, y2 ;
553

    
554
  unsigned char line ;
555
  unsigned char *fontPtr ;
556

    
557
// Can't print if we're offscreen
558

    
559
//if ((x < 0) || (x >= (maxX - fontWidth)) || (y < 0) || (y >= (maxY - fontHeight)))
560
//  return ;
561

    
562
  fontPtr = font + c * fontHeight ;
563

    
564
  for (y1 = fontHeight - 1 ; y1 >= 0 ; --y1)
565
  {
566
    y2 = y + y1 ;
567
    line = *fontPtr++ ;
568
    lcd128x64point (x + 0, y2, (line & 0x80) == 0 ? bgCol : fgCol) ;
569
    lcd128x64point (x + 1, y2, (line & 0x40) == 0 ? bgCol : fgCol) ;
570
    lcd128x64point (x + 2, y2, (line & 0x20) == 0 ? bgCol : fgCol) ;
571
    lcd128x64point (x + 3, y2, (line & 0x10) == 0 ? bgCol : fgCol) ;
572
    lcd128x64point (x + 4, y2, (line & 0x08) == 0 ? bgCol : fgCol) ;
573
    lcd128x64point (x + 5, y2, (line & 0x04) == 0 ? bgCol : fgCol) ;
574
    lcd128x64point (x + 6, y2, (line & 0x02) == 0 ? bgCol : fgCol) ;
575
    lcd128x64point (x + 7, y2, (line & 0x01) == 0 ? bgCol : fgCol) ;
576
  }
577
}
578

    
579

    
580
/*
581
 * lcd128x64puts:
582
 *        Send a string to the display. Obeys \n and \r formatting
583
 *********************************************************************************
584
 */
585

    
586
void lcd128x64puts (int x, int y, const char *str, int bgCol, int fgCol)
587
{
588
  int c, mx, my ;
589

    
590
  mx = x ; my = y ;
591

    
592
  while (*str)
593
  {
594
    c = *str++ ;
595

    
596
    if (c == '\r')
597
    {
598
      mx = x ;
599
      continue ;
600
    }
601

    
602
    if (c == '\n')
603
    {
604
      mx  = x ;
605
      my -= fontHeight ;
606
      continue ;
607
    }
608

    
609
    lcd128x64putchar (mx, my, c, bgCol, fgCol) ;
610

    
611
    mx += fontWidth ;
612
    if (mx >= (maxX - fontWidth))
613
    {
614
      mx  = 0 ;
615
      my -= fontHeight ;
616
    }
617
  }
618
}
619

    
620

    
621
/*
622
 * lcd128x64clear:
623
 *        Clear the display to the given colour.
624
 *********************************************************************************
625
 */
626

    
627
void lcd128x64clear (int colour)
628
{
629
  register int i ;
630
  register unsigned char *ptr = frameBuffer ;
631

    
632
  for (i = 0 ; i < (maxX * maxY) ; ++i)
633
    *ptr++ = colour ;
634
}
635

    
636

    
637

    
638

    
639
/*
640
 * lcd128x64setup:
641
 *        Initialise the display and GPIO.
642
 *********************************************************************************
643
 */
644

    
645
int lcd128x64setup (void)
646
{
647
  int i ;
648

    
649
  for (i = 0 ; i < 8 ; ++i)
650
    pinMode (i, OUTPUT) ;
651

    
652
  digitalWrite (CS1,    1) ;
653
  digitalWrite (CS2,    1) ;
654
  digitalWrite (STROBE, 0) ;
655
  digitalWrite (RS,     1) ;
656

    
657
  pinMode (CS1,    OUTPUT) ;
658
  pinMode (CS2,    OUTPUT) ;
659
  pinMode (STROBE, OUTPUT) ;
660
  pinMode (RS,     OUTPUT) ;
661

    
662
  sendCommand (0x3F, CS1) ;        // Display ON
663
  sendCommand (0xC0, CS1) ;        // Set display start line to 0
664

    
665
  sendCommand (0x3F, CS2) ;        // Display ON
666
  sendCommand (0xC0, CS2) ;        // Set display start line to 0
667

    
668
  lcd128x64clear          (0) ;
669
  lcd128x64setOrientation (0) ;
670
  lcd128x64update         () ;
671

    
672
  return 0 ;
673
}