Statistics
| Branch: | Revision:

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

History | View | Annotate | Download (9.14 KB)

1
/*
2
 * scrollPhat.c:
3
 *        Simple driver for the Pimoroni Scroll Phat device
4
 *
5
 * Copyright (c) 2015 Gordon Henderson.
6
 ***********************************************************************
7
 * This file is part of wiringPi:
8
 *        https://projects.drogon.net/raspberry-pi/wiringpi/
9
 *
10
 *    wiringPi is free software: you can redistribute it and/or modify
11
 *    it under the terms of the GNU Lesser General Public License as published by
12
 *    the Free Software Foundation, either version 3 of the License, or
13
 *    (at your option) any later version.
14
 *
15
 *    wiringPi is distributed in the hope that it will be useful,
16
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 *    GNU Lesser General Public License for more details.
19
 *
20
 *    You should have received a copy of the GNU Lesser General Public License
21
 *    along with wiringPi.  If not, see <http://www.gnu.org/licenses/>.
22
 ***********************************************************************
23
 */
24

    
25
#include <stdio.h>
26
#include <stdlib.h>
27
#include <stdarg.h>
28
#include <string.h>
29
#include <time.h>
30

    
31
#include <wiringPiI2C.h>
32

    
33
#include "scrollPhatFont.h"
34
#include "scrollPhat.h"
35

    
36
// Size
37

    
38
#define        SP_WIDTH        11
39
#define        SP_HEIGHT         5
40

    
41
// I2C
42

    
43
#define        PHAT_I2C_ADDR        0x60
44

    
45
// Software copy of the framebuffer
46
//        it's 8-bit deep although the display itself is only 1-bit deep.
47

    
48
static unsigned char frameBuffer [SP_WIDTH * SP_HEIGHT] ;
49

    
50
static int lastX,   lastY ;
51
static int printDelayFactor  ;
52
static int scrollPhatFd ;
53

    
54
static int putcharX ;
55

    
56
#undef        DEBUG
57

    
58

    
59
/*
60
 * delay:
61
 *        Wait for some number of milliseconds.
62
 *        This taken from wiringPi as there is no-need to include the whole of
63
 *        wiringPi just for the delay function.
64
 *********************************************************************************
65
 */
66

    
67
static void delay (unsigned int howLong)
68
{
69
  struct timespec sleeper, dummy ;
70

    
71
  sleeper.tv_sec  = (time_t)(howLong / 1000) ;
72
  sleeper.tv_nsec = (long)(howLong % 1000) * 1000000 ;
73

    
74
  nanosleep (&sleeper, &dummy) ;
75
}
76

    
77

    
78

    
79
/*
80
 * scrollPhatUpdate:
81
 *        Copy our software version to the real display
82
 *********************************************************************************
83
 */
84

    
85
void scrollPhatUpdate (void)
86
{
87
  register int x, y ;
88
  register unsigned char data, pixel ;
89
  unsigned char pixels [SP_WIDTH] ;
90

    
91
#ifdef        DEBUG
92
  printf ("+-----------+\n") ;
93
  for (y = 0 ; y < SP_HEIGHT ; ++y)
94
  {
95
    putchar ('|') ;
96
    for (x = 0 ; x < SP_WIDTH ; ++x)
97
    {
98
      pixel = frameBuffer [x + y * SP_WIDTH] ;
99
      putchar (pixel == 0 ? ' ' : '*') ;
100
    }
101
    printf ("|\n") ;
102
  }
103
  printf ("+-----------+\n") ;
104
#endif 
105

    
106
  for (x = 0 ; x < SP_WIDTH ; ++x)
107
  {
108
    data = 0 ;
109
    for (y = 0 ; y < SP_HEIGHT ; ++y)
110
    {
111
      pixel = frameBuffer [x + y * SP_WIDTH] ;
112
      data = (data << 1) | ((pixel == 0) ? 0 : 1) ;
113
    }
114
    pixels [x] = data ;
115
  }
116

    
117
  for (x = 0 ; x < SP_WIDTH ; ++x)
118
    wiringPiI2CWriteReg8 (scrollPhatFd, 1 + x, pixels [x]) ;
119

    
120
  wiringPiI2CWriteReg8 (scrollPhatFd, 0x0C, 0) ;
121
}
122

    
123

    
124
/*
125
 *********************************************************************************
126
 * Standard Graphical Functions
127
 *********************************************************************************
128
 */
129

    
130

    
131
/*
132
 * scrollPhatPoint:
133
 *        Plot a pixel. Crude clipping - speed is not the essence here.
134
 *********************************************************************************
135
 */
136

    
137
void scrollPhatPoint (int x, int y, int colour)
138
{
139
  lastX = x ;
140
  lastY = y ;
141

    
142
  if ((x < 0) || (x >= SP_WIDTH) || (y < 0) || (y >= SP_HEIGHT))
143
    return ;
144

    
145
  frameBuffer [x + y * SP_WIDTH] = colour ;
146
}
147

    
148

    
149
/*
150
 * scrollPhatLine: scrollPhatLineTo:
151
 *        Classic Bressenham Line code - rely on the point function to do the
152
 *        clipping for us here.
153
 *********************************************************************************
154
 */
155

    
156
void scrollPhatLine (int x0, int y0, int x1, int y1, int colour)
157
{
158
  int dx, dy ;
159
  int sx, sy ;
160
  int err, e2 ;
161

    
162
  lastX = x1 ;
163
  lastY = y1 ;
164

    
165
  dx = abs (x1 - x0) ;
166
  dy = abs (y1 - y0) ;
167

    
168
  sx = (x0 < x1) ? 1 : -1 ;
169
  sy = (y0 < y1) ? 1 : -1 ;
170

    
171
  err = dx - dy ;
172
 
173
  for (;;)
174
  {
175
    scrollPhatPoint (x0, y0, colour) ;
176

    
177
    if ((x0 == x1) && (y0 == y1))
178
      break ;
179

    
180
    e2 = 2 * err ;
181

    
182
    if (e2 > -dy)
183
    {
184
      err -= dy ;
185
      x0  += sx ;
186
    }
187

    
188
    if (e2 < dx)
189
    {
190
      err += dx ;
191
      y0  += sy ;
192
    }
193
  }
194

    
195
}
196

    
197
void scrollPhatLineTo (int x, int y, int colour)
198
{
199
  scrollPhatLine (lastX, lastY, x, y, colour) ;
200
}
201

    
202

    
203
/*
204
 * scrollPhatRectangle:
205
 *        A rectangle is a spoilt days fishing
206
 *********************************************************************************
207
 */
208

    
209
void scrollPhatRectangle (int x1, int y1, int x2, int y2, int colour, int filled)
210
{
211
  register int x ;
212

    
213
  if (filled)
214
  {
215
    /**/ if (x1 == x2)
216
      scrollPhatLine (x1, y1, x2, y2, colour) ;
217
    else if (x1 < x2)
218
      for (x = x1 ; x <= x2 ; ++x)
219
        scrollPhatLine (x, y1, x, y2, colour) ;
220
    else
221
      for (x = x2 ; x <= x1 ; ++x)
222
        scrollPhatLine (x, y1, x, y2, colour) ;
223
  }
224
  else
225
  {
226
    scrollPhatLine   (x1, y1, x2, y1, colour) ;
227
    scrollPhatLineTo (x2, y2, colour) ;
228
    scrollPhatLineTo (x1, y2, colour) ;
229
    scrollPhatLineTo (x1, y1, colour) ;
230
  }
231
}
232

    
233

    
234
/*
235
 * scrollPhatPutchar:
236
 *      Print a single character to the screen then advance the pointer by an
237
 *        appropriate ammount (variable width font).
238
 *      We rely on the clipping done by the pixel plot function to keep us
239
 *      out of trouble.
240
 *        Return the width + space
241
 *********************************************************************************
242
 */
243

    
244
int scrollPhatPutchar (int c)
245
{
246
  register int x, y ;
247

    
248
  unsigned char line ;
249
  unsigned char *fontPtr ;
250
  unsigned char *p2 ;
251
  int lineWidth, width, mask ;
252

    
253
// The font is printable characters, uppercase only...
254
//        and somewhat varaible width...
255

    
256
  c &= 0x7F ;
257
  if (c > 0x60)
258
    c -= 64 ;
259
  else
260
    c -= 32 ;
261

    
262
  fontPtr = scrollPhatFont + c * fontHeight ;
263

    
264
// Work out width of this character
265
//        There probably is a more efficient way to do this, but...
266

    
267
  p2    = fontPtr ;
268
  width = 0 ;
269
  for (y = 0 ; y < fontHeight ; ++y)
270
  {
271
    mask = 0x80 ;
272
    for (lineWidth = 8 ; lineWidth > 0 ; --lineWidth)
273
    {
274
      if ((*p2 & mask) != 0)
275
        break ;
276
      mask >>= 1 ;
277
    }
278
    if (lineWidth > width)
279
      width = lineWidth ;
280

    
281
    ++p2 ;
282
  }
283

    
284
  if (width == 0)        // Likely to be a blank or space character
285
    width = 3 ;
286

    
287
  for (y = fontHeight - 1 ; y >= 0 ; --y)
288
  {
289
    x    = 0 ;
290
    line = *fontPtr++ ;
291
    for (mask = 1 << (width - 1) ; mask != 0 ; mask >>= 1)
292
    {
293
      scrollPhatPoint (putcharX + x, y, (line & mask)) ;
294
      ++x ;
295
    }
296
  }
297

    
298
// make a line of space
299

    
300
  for (y = fontHeight - 1 ; y >= 0 ; --y)
301
    scrollPhatPoint (putcharX + width, y, 0) ;
302

    
303
  putcharX = putcharX + width + 1 ;
304

    
305
  return width + 1 ;
306
}
307

    
308

    
309
/*
310
 * scrollPhatPuts:
311
 *        Send a string to the display - and scroll it across.
312
 *        This is somewhat of a hack in that we print the entire string to the
313
 *        display and let the point clipping take care of what's off-screen...
314
 *********************************************************************************
315
 */
316

    
317
void scrollPhatPuts (const char *str)
318
{
319
  int i ;
320
  int movingX = 0 ;
321
  const char *s ;
322
  int pixelLen ;
323

    
324
// Print it once, then we know the width in pixels...
325

    
326
  putcharX = 0 ;
327
  s = str ;
328
  while (*s)
329
    scrollPhatPutchar (*s++) ;
330

    
331
  pixelLen = putcharX ;
332

    
333
// Now scroll it by printing it and moving left one pixel
334

    
335
  movingX = 0 ;
336
  for (i = 0 ; i < pixelLen ; ++i)
337
  {
338
    putcharX = movingX ;
339
    s = str ;
340
    while (*s)
341
      scrollPhatPutchar (*s++) ;
342
    --movingX ;
343
    scrollPhatUpdate () ;
344
    delay (printDelayFactor) ;
345
  }
346
}
347

    
348

    
349
/*
350
 * scrollPhatPrintf:
351
 *        Does what it says
352
 *********************************************************************************
353
 */
354

    
355
void scrollPhatPrintf (const char *message, ...)
356
{
357
  va_list argp ;
358
  char buffer [1024] ;
359

    
360
  va_start (argp, message) ;
361
    vsnprintf (buffer, 1023, message, argp) ;
362
  va_end (argp) ;
363

    
364
  scrollPhatPuts (buffer) ;
365
}
366

    
367

    
368
/*
369
 * scrollPhatPrintSpeed:
370
 *        Change the print speed - mS per shift by 1 pixel
371
 *********************************************************************************
372
 */
373

    
374
void scrollPhatPrintSpeed (const int pps)
375
{
376
  if (pps < 0)
377
    printDelayFactor = 0 ;
378
  else
379
    printDelayFactor = pps ;
380
}
381

    
382

    
383
/*
384
 * scrollPhatClear:
385
 *        Clear the display
386
 *********************************************************************************
387
 */
388

    
389
void scrollPhatClear (void)
390
{
391
  register int i ;
392
  register unsigned char *ptr = frameBuffer ;
393

    
394
  for (i = 0 ; i < (SP_WIDTH * SP_HEIGHT) ; ++i)
395
    *ptr++ = 0 ;
396

    
397
  scrollPhatUpdate () ;
398
}
399

    
400

    
401
/*
402
 * scrollPhatIntensity:
403
 *        Set the display brightness - percentage
404
 *********************************************************************************
405
 */
406

    
407
void scrollPhatIntensity (const int percent)
408
{
409
  wiringPiI2CWriteReg8 (scrollPhatFd, 0x19, (127 * percent) / 100) ;
410
}
411

    
412

    
413
/*
414
 * scrollPhatSetup:
415
 *        Initialise the Scroll Phat display
416
 *********************************************************************************
417
 */
418

    
419
int scrollPhatSetup (void)
420
{
421
  if ((scrollPhatFd = wiringPiI2CSetup (PHAT_I2C_ADDR)) < 0)
422
    return scrollPhatFd ;
423

    
424
  wiringPiI2CWriteReg8 (scrollPhatFd, 0x00, 0x03) ;        // Enable display, set to 5x11 mode
425
  scrollPhatIntensity (10) ;
426
  scrollPhatClear () ;
427
  scrollPhatPrintSpeed (100) ;
428

    
429
  return 0 ;
430
}