Subversion Repositories Code-Repo

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
121 Kevin 1
#include "maindefs.h"
2
#include "Adafruit_GFX.h"
3
#include "glcdfont.c"
4
#include "oled_ssd1306.h"
5
#include "oled_ssd1331.h"
6
#include <string.h>
7
#include <stdio.h>
8
 
9
static GFX_DATA gfx_data;
10
 
11
void GFX_Init(int w, int h) {
12
    gfx_data._width = gfx_data.WIDTH = w;
13
    gfx_data._height = gfx_data.HEIGHT = h;
14
    gfx_data.rotation = 0;
15
    gfx_data.cursor_x = gfx_data.cursor_y = 0;
16
    gfx_data.textsize = 1;
17
    gfx_data.textcolor = gfx_data.textbgcolor = 0xFFFF;
18
    gfx_data.wrap = 1;
122 Kevin 19
 
20
    memset(gfx_data.lcd_buffer, 0, GFX_LCD_BUFFER_SIZE);
21
    memset(gfx_data.buffer, 0, GFX_STRING_BUFFER_SIZE);
121 Kevin 22
}
23
 
24
int GFX_Abs(int i) {
25
    if (i < 0)
26
        return -i;
27
    else
28
        return i;
29
}
30
 
31
void GFX_Swap(int *a, int *b) {
32
    int tmp = *a;
33
    *a = *b;
34
    *b = tmp;
35
}
36
 
37
void GFX_drawLine(int x0, int y0, int x1, int y1, unsigned int color) {
38
#ifdef GFX_SSD1306
39
    int dx, dy, err, ystep;
40
    int steep = GFX_Abs(y1 - y0) > GFX_Abs(x1 - x0);
41
    if (steep) {
42
        GFX_Swap(&x0, &y0);
43
        GFX_Swap(&x1, &y1);
44
    }
45
 
46
    if (x0 > x1) {
47
        GFX_Swap(&x0, &x1);
48
        GFX_Swap(&y0, &y1);
49
    }
50
 
51
    dx = x1 - x0;
52
    dy = GFX_Abs(y1 - y0);
53
 
54
    err = dx / 2;
55
 
56
    if (y0 < y1) {
57
        ystep = 1;
58
    } else {
59
        ystep = -1;
60
    }
61
 
62
    for (; x0 <= x1; x0++) {
63
 
64
        if (steep) {
65
            SSD1306_Draw_Pixel(y0, x0, color);
66
        } else {
67
            SSD1306_Draw_Pixel(x0, y0, color);
68
        }
69
        err -= dy;
70
        if (err < 0) {
71
            y0 += ystep;
72
            err += dx;
73
        }
74
    }
75
#endif
76
#ifdef GFX_SSD1331
77
    SSD1331_Draw_Line(x0, y0, x1, y1, color);
78
#endif
79
}
80
 
81
void GFX_drawFastVLine(int x, int y, int h, unsigned int color) {
82
    GFX_drawLine(x, y, x, y + h - 1, color);
83
}
84
 
85
void GFX_drawFastHLine(int x, int y, int w, unsigned int color) {
86
    GFX_drawLine(x, y, x + w - 1, y, color);
87
}
88
 
89
void GFX_drawRect(int x, int y, int w, int h, unsigned int color) {
90
#ifdef GFX_SSD1306
91
    GFX_drawFastHLine(x, y, w, color);
92
    GFX_drawFastHLine(x, y + h, w, color);
93
    GFX_drawFastVLine(x, y, h, color);
94
    GFX_drawFastVLine(x + w, y, h, color);
95
#endif
96
#ifdef GFX_SSD1331
97
    SSD1331_Draw_Rect(x, y, x + w, y + h, color);
98
#endif
99
}
100
 
101
void GFX_fillRect(int x, int y, int w, int h, unsigned int color) {
102
#ifdef GFX_SSD1306
103
    int i;
104
    for (i = x; i < x + w; i++) {
105
        GFX_drawFastVLine(i, y, h, color);
106
    }
107
#endif
108
#ifdef GFX_SSD1331
109
    SSD1331_Fill_Rect(x, y, x + w, y + h, color);
110
#endif
111
}
112
 
113
void GFX_fillScreen(unsigned int color) {
114
    GFX_fillRect(0, 0, gfx_data._width, gfx_data._height, color);
115
}
116
 
117
void GFX_clearScreen() {
118
#ifdef GFX_SSD1306
119
    GFX_fillScreen(SSD1306_BLACK);
120
#endif
121
#ifdef GFX_SSD1331
122
    SSD1331_Clear_Display();
123
#endif
124
}
125
 
126
void GFX_drawCircle(int x0, int y0, int r, unsigned int color) {
127
    int f = 1 - r;
128
    int ddF_x = 1;
129
    int ddF_y = -2 * r;
130
    int x = 0;
131
    int y = r;
132
 
133
#ifdef GFX_SSD1306
134
    SSD1306_Draw_Pixel(x0, y0 + r, color);
135
    SSD1306_Draw_Pixel(x0, y0 - r, color);
136
    SSD1306_Draw_Pixel(x0 + r, y0, color);
137
    SSD1306_Draw_Pixel(x0 - r, y0, color);
138
#endif
139
#ifdef GFX_SSD1331
140
    SSD1331_Draw_Pixel(x0, y0 + r, color);
141
    SSD1331_Draw_Pixel(x0, y0 - r, color);
142
    SSD1331_Draw_Pixel(x0 + r, y0, color);
143
    SSD1331_Draw_Pixel(x0 - r, y0, color);
144
#endif
145
 
146
    while (x < y) {
147
        if (f >= 0) {
148
            y--;
149
            ddF_y += 2;
150
            f += ddF_y;
151
        }
152
        x++;
153
        ddF_x += 2;
154
        f += ddF_x;
155
 
156
#ifdef GFX_SSD1306
157
        SSD1306_Draw_Pixel(x0 + x, y0 + y, color);
158
        SSD1306_Draw_Pixel(x0 - x, y0 + y, color);
159
        SSD1306_Draw_Pixel(x0 + x, y0 - y, color);
160
        SSD1306_Draw_Pixel(x0 - x, y0 - y, color);
161
        SSD1306_Draw_Pixel(x0 + y, y0 + x, color);
162
        SSD1306_Draw_Pixel(x0 - y, y0 + x, color);
163
        SSD1306_Draw_Pixel(x0 + y, y0 - x, color);
164
        SSD1306_Draw_Pixel(x0 - y, y0 - x, color);
165
#endif
166
#ifdef GFX_SSD1331
167
        SSD1331_Draw_Pixel(x0 + x, y0 + y, color);
168
        SSD1331_Draw_Pixel(x0 - x, y0 + y, color);
169
        SSD1331_Draw_Pixel(x0 + x, y0 - y, color);
170
        SSD1331_Draw_Pixel(x0 - x, y0 - y, color);
171
        SSD1331_Draw_Pixel(x0 + y, y0 + x, color);
172
        SSD1331_Draw_Pixel(x0 - y, y0 + x, color);
173
        SSD1331_Draw_Pixel(x0 + y, y0 - x, color);
174
        SSD1331_Draw_Pixel(x0 - y, y0 - x, color);
175
#endif
176
    }
177
}
178
 
179
void GFX_drawCircleHelper(int x0, int y0, int r, unsigned char cornername, unsigned int color) {
180
    int f = 1 - r;
181
    int ddF_x = 1;
182
    int ddF_y = -2 * r;
183
    int x = 0;
184
    int y = r;
185
 
186
    while (x < y) {
187
        if (f >= 0) {
188
            y--;
189
            ddF_y += 2;
190
            f += ddF_y;
191
        }
192
        x++;
193
        ddF_x += 2;
194
        f += ddF_x;
195
#ifdef GFX_SSD1306
196
        if (cornername & 0x4) {
197
            SSD1306_Draw_Pixel(x0 + x, y0 + y, color);
198
            SSD1306_Draw_Pixel(x0 + y, y0 + x, color);
199
        }
200
        if (cornername & 0x2) {
201
            SSD1306_Draw_Pixel(x0 + x, y0 - y, color);
202
            SSD1306_Draw_Pixel(x0 + y, y0 - x, color);
203
        }
204
        if (cornername & 0x8) {
205
            SSD1306_Draw_Pixel(x0 - y, y0 + x, color);
206
            SSD1306_Draw_Pixel(x0 - x, y0 + y, color);
207
        }
208
        if (cornername & 0x1) {
209
            SSD1306_Draw_Pixel(x0 - y, y0 - x, color);
210
            SSD1306_Draw_Pixel(x0 - x, y0 - y, color);
211
        }
212
#endif
213
#ifdef GFX_SSD1331
214
        if (cornername & 0x4) {
215
            SSD1331_Draw_Pixel(x0 + x, y0 + y, color);
216
            SSD1331_Draw_Pixel(x0 + y, y0 + x, color);
217
        }
218
        if (cornername & 0x2) {
219
            SSD1331_Draw_Pixel(x0 + x, y0 - y, color);
220
            SSD1331_Draw_Pixel(x0 + y, y0 - x, color);
221
        }
222
        if (cornername & 0x8) {
223
            SSD1331_Draw_Pixel(x0 - y, y0 + x, color);
224
            SSD1331_Draw_Pixel(x0 - x, y0 + y, color);
225
        }
226
        if (cornername & 0x1) {
227
            SSD1331_Draw_Pixel(x0 - y, y0 - x, color);
228
            SSD1331_Draw_Pixel(x0 - x, y0 - y, color);
229
        }
230
#endif
231
    }
232
}
233
 
234
void GFX_fillCircle(int x0, int y0, int r, unsigned int color) {
235
    GFX_drawFastVLine(x0, y0 - r, 2 * r + 1, color);
236
    GFX_fillCircleHelper(x0, y0, r, 3, 0, color);
237
}
238
 
239
void GFX_fillCircleHelper(int x0, int y0, int r, unsigned char cornername, int delta, unsigned int color) {
240
    int f = 1 - r;
241
    int ddF_x = 1;
242
    int ddF_y = -2 * r;
243
    int x = 0;
244
    int y = r;
245
 
246
    while (x < y) {
247
        if (f >= 0) {
248
            y--;
249
            ddF_y += 2;
250
            f += ddF_y;
251
        }
252
        x++;
253
        ddF_x += 2;
254
        f += ddF_x;
255
 
256
        if (cornername & 0x1) {
257
            GFX_drawFastVLine(x0 + x, y0 - y, 2 * y + 1 + delta, color);
258
            GFX_drawFastVLine(x0 + y, y0 - x, 2 * x + 1 + delta, color);
259
        }
260
        if (cornername & 0x2) {
261
            GFX_drawFastVLine(x0 - x, y0 - y, 2 * y + 1 + delta, color);
262
            GFX_drawFastVLine(x0 - y, y0 - x, 2 * x + 1 + delta, color);
263
        }
264
    }
265
}
266
 
267
void GFX_drawTriangle(int x0, int y0, int x1, int y1, int x2, int y2, unsigned int color) {
268
    GFX_drawLine(x0, y0, x1, y1, color);
269
    GFX_drawLine(x1, y1, x2, y2, color);
270
    GFX_drawLine(x2, y2, x0, y0, color);
271
}
272
 
273
void GFX_fillTriangle(int x0, int y0, int x1, int y1, int x2, int y2, unsigned int color) {
274
    int a, b, y, last;
275
    int dx01 = x1 - x0;
276
    int dy01 = y1 - y0;
277
    int dx02 = x2 - x0;
278
    int dy02 = y2 - y0;
279
    int dx12 = x2 - x1;
280
    int dy12 = y2 - y1;
281
    int sa = 0;
282
    int sb = 0;
283
 
284
    // Sort coordinates by Y order (y2 >= y1 >= y0)
285
    if (y0 > y1) {
286
        GFX_Swap(&y0, &y1);
287
        GFX_Swap(&x0, &x1);
288
    }
289
    if (y1 > y2) {
290
        GFX_Swap(&y2, &y1);
291
        GFX_Swap(&x2, &x1);
292
    }
293
    if (y0 > y1) {
294
        GFX_Swap(&y0, &y1);
295
        GFX_Swap(&x0, &x1);
296
    }
297
 
298
    if (y0 == y2) { // Handle awkward all-on-same-line case as its own thing
299
        a = b = x0;
300
        if (x1 < a) a = x1;
301
        else if (x1 > b) b = x1;
302
        if (x2 < a) a = x2;
303
        else if (x2 > b) b = x2;
304
        GFX_drawFastHLine(a, y0, b - a + 1, color);
305
        return;
306
    }
307
 
308
    // For upper part of triangle, find scanline crossings for segments
309
    // 0-1 and 0-2.  If y1=y2 (flat-bottomed triangle), the scanline y1
310
    // is included here (and second loop will be skipped, avoiding a /0
311
    // error there), otherwise scanline y1 is skipped here and handled
312
    // in the second loop...which also avoids a /0 error here if y0=y1
313
    // (flat-topped triangle).
314
    if (y1 == y2) last = y1; // Include y1 scanline
315
    else last = y1 - 1; // Skip it
316
 
317
    for (y = y0; y <= last; y++) {
318
        a = x0 + sa / dy01;
319
        b = x0 + sb / dy02;
320
        sa += dx01;
321
        sb += dx02;
322
        /* longhand:
323
        a = x0 + (x1 - x0) * (y - y0) / (y1 - y0);
324
        b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
325
         */
326
        if (a > b) GFX_Swap(&a, &b);
327
        GFX_drawFastHLine(a, y, b - a + 1, color);
328
    }
329
 
330
    // For lower part of triangle, find scanline crossings for segments
331
    // 0-2 and 1-2.  This loop is skipped if y1=y2.
332
    sa = dx12 * (y - y1);
333
    sb = dx02 * (y - y0);
334
    for (; y <= y2; y++) {
335
        a = x1 + sa / dy12;
336
        b = x0 + sb / dy02;
337
        sa += dx12;
338
        sb += dx02;
339
        /* longhand:
340
        a = x1 + (x2 - x1) * (y - y1) / (y2 - y1);
341
        b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
342
         */
343
        if (a > b) GFX_Swap(&a, &b);
344
        GFX_drawFastHLine(a, y, b - a + 1, color);
345
    }
346
}
347
 
348
void GFX_drawRoundRect(int x, int y, int w, int h, int r, unsigned int color) {
349
    // smarter version
350
    GFX_drawFastHLine(x + r, y, w - 2 * r, color); // Top
351
    GFX_drawFastHLine(x + r, y + h - 1, w - 2 * r, color); // Bottom
352
    GFX_drawFastVLine(x, y + r, h - 2 * r, color); // Left
353
    GFX_drawFastVLine(x + w - 1, y + r, h - 2 * r, color); // Right
354
 
355
    // draw four corners
356
    GFX_drawCircleHelper(x + r, y + r, r, 1, color);
357
    GFX_drawCircleHelper(x + w - r - 1, y + r, r, 2, color);
358
    GFX_drawCircleHelper(x + w - r - 1, y + h - r - 1, r, 4, color);
359
    GFX_drawCircleHelper(x + r, y + h - r - 1, r, 8, color);
360
}
361
 
362
void GFX_fillRoundRect(int x, int y, int w, int h, int r, unsigned int color) {
363
    // smarter version
364
    GFX_fillRect(x + r, y, w - 2 * r, h, color);
365
 
366
    // draw four corners
367
    GFX_fillCircleHelper(x + w - r - 1, y + r, r, 1, h - 2 * r - 1, color);
368
    GFX_fillCircleHelper(x + r, y + r, r, 2, h - 2 * r - 1, color);
369
}
370
 
371
void GFX_drawBitmap(int x, int y, const unsigned char* bitmap, int w, int h, unsigned int color) {
372
    int i, j;
373
    for (j = 0; j < h; j++) {
374
        for (i = 0; i < w; i++) {
375
            if (bitmap[i + (j / 8) * w] & (j % 8)) {
376
#ifdef GFX_SSD1306
377
                SSD1306_Draw_Pixel(x + i, y + j, color);
378
#endif
379
#ifdef GFX_SSD1331
380
                SSD1331_Draw_Pixel(x + i, y + j, color);
381
#endif
382
            }
383
        }
384
    }
385
}
386
 
387
void GFX_drawChar(int x, int y, unsigned char c, unsigned int color, unsigned int bg, unsigned char size) {
388
    int i, j;
389
    unsigned int line;
390
 
391
    if ((x >= gfx_data._width) || // Clip right
392
            (y >= gfx_data._height) || // Clip bottom
393
            ((x + 5 * size - 1) < 0) || // Clip left
394
            ((y + 8 * size - 1) < 0)) // Clip top
395
        return;
396
 
397
    for (i = 0; i < 6; i++) {
398
        if (i == 5)
399
            line = 0x0;
400
        else
401
            line = font[(c * 5) + i];
402
        for (j = 0; j < 8; j++) {
403
            if (line & 0x1) {
404
                if (size == 1) {// default size
405
#ifdef GFX_SSD1306
406
                    SSD1306_Draw_Pixel(x + i, y + j, color);
407
#endif
408
#ifdef GFX_SSD1331
409
                    SSD1331_Draw_Pixel(x + i, y + j, color);
410
#endif
411
                } else { // big size
412
                    GFX_fillRect(x + (i * size), y + (j * size), size, size, color);
413
                }
414
            } else if (bg != color) {
415
                if (size == 1) { // default size
416
#ifdef GFX_SSD1306
417
                    SSD1306_Draw_Pixel(x + i, y + j, bg);
418
#endif
419
#ifdef GFX_SSD1331
420
                    SSD1331_Draw_Pixel(x + i, y + j, bg);
421
#endif
422
                } else { // big size
423
                    GFX_fillRect(x + i*size, y + j*size, size, size, bg);
424
                }
425
            }
426
            line >>= 1;
427
        }
428
    }
429
}
430
 
431
void GFX_write(unsigned char c) {
122 Kevin 432
    if (c == '\n' || c == '\r') {
121 Kevin 433
        gfx_data.cursor_y += gfx_data.textsize * 8;
434
        gfx_data.cursor_x = 0;
122 Kevin 435
        //    } else if (c == '\r') {
436
        //        // skip em
121 Kevin 437
    } else {
438
        GFX_drawChar(gfx_data.cursor_x, gfx_data.cursor_y, c, gfx_data.textcolor, gfx_data.textbgcolor, gfx_data.textsize);
439
        gfx_data.cursor_x += gfx_data.textsize * 6;
440
        if (gfx_data.wrap && (gfx_data.cursor_x > (gfx_data._width - gfx_data.textsize * 6))) {
441
            gfx_data.cursor_y += gfx_data.textsize * 8;
442
            gfx_data.cursor_x = 0;
443
        }
444
    }
445
}
446
 
447
void GFX_writeString(const rom char *fmt, ...) {
448
    unsigned char i, len;
122 Kevin 449
    // Parse and create string
121 Kevin 450
    va_list args;
451
    va_start(args, fmt);
452
    vsprintf((char *) gfx_data.buffer, fmt, args);
453
    va_end(args);
454
    len = strlen((char *) gfx_data.buffer);
122 Kevin 455
 
456
    // Make sure string to insert fits in buffer, truncate if necessary
457
    if (len > GFX_STRING_BUFFER_SIZE)
458
        len = GFX_STRING_BUFFER_SIZE;
459
 
460
    // Print buffer to string
121 Kevin 461
    for (i = 0; i < len; i++) {
462
        GFX_write(gfx_data.buffer[i]);
463
    }
464
}
465
 
122 Kevin 466
void GFX_appendString(const rom char *fmt, ...) {
467
    unsigned char i, len;
468
 
469
    // Parse and create string
470
    va_list args;
471
    va_start(args, fmt);
472
    vsprintf((char *) gfx_data.buffer, fmt, args);
473
    va_end(args);
474
 
475
    // Make sure string to insert fits in buffer, truncate if necessary
476
    len = strlen((char *) gfx_data.buffer);
477
 
478
    if (len == 1) {  // This will only occur on "\n"
479
        // Do nothing?
480
        return;
481
    }
482
 
483
    if (len > GFX_STRING_BUFFER_SIZE)
484
        len = GFX_STRING_BUFFER_SIZE;
485
 
486
    // Omit the newline if string fill entire line
487
    if (((len - 1)%(GFX_width() / 6)) == 0) { // 16 or 10
488
        len -= 1;
489
    }
490
 
491
    // Shift everything right and insert string at beginning
492
    for (i = 127; i > len - 1; i--) {
493
        gfx_data.lcd_buffer[i] = gfx_data.lcd_buffer[i - len];
494
    }
123 Kevin 495
    memcpy((char *)gfx_data.lcd_buffer, (const char *)gfx_data.buffer, len);
122 Kevin 496
 
497
    // Print full buffer to screen
498
    GFX_clearScreen();
499
    GFX_setCursor(0,0);
500
    for (i = 0; i < GFX_LCD_BUFFER_SIZE-1; i++) {
501
        GFX_write(gfx_data.lcd_buffer[i]);
502
    }
503
}
504
 
121 Kevin 505
void GFX_setCursor(int x, int y) {
506
    gfx_data.cursor_x = x;
507
    gfx_data.cursor_y = y;
508
}
509
 
510
void GFX_setTextColor(unsigned int c) {
511
    // for 'transparent' background, we'll set the bg
512
    // to the same as fg instead of using a flag
513
    gfx_data.textcolor = c;
514
    gfx_data.textbgcolor = c;
515
}
516
 
517
void GFX_setTextColorBG(unsigned int c, unsigned int bg) {
518
    gfx_data.textcolor = c;
519
    gfx_data.textbgcolor = bg;
520
}
521
 
522
void GFX_setTextSize(unsigned char s) {
523
    gfx_data.textsize = (s > 0) ? s : 1;
524
}
525
 
526
void GFX_setTextWrap(unsigned char w) {
527
    gfx_data.wrap = w;
528
}
529
 
530
void GFX_setRotation(unsigned char x) {
531
    x %= 4; // cant be higher than 3
532
    gfx_data.rotation = x;
533
    switch (x) {
534
        case 0:
535
        case 2:
536
            gfx_data._width = gfx_data.WIDTH;
537
            gfx_data._height = gfx_data.HEIGHT;
538
            break;
539
        case 1:
540
        case 3:
541
            gfx_data._width = gfx_data.HEIGHT;
542
            gfx_data._height = gfx_data.WIDTH;
543
            break;
544
    }
545
}
546
 
547
unsigned char GFX_getRotation() {
548
    gfx_data.rotation %= 4;
549
    return gfx_data.rotation;
550
}
551
 
552
int GFX_height() {
553
    return gfx_data._height;
554
}
555
 
556
int GFX_width() {
557
    return gfx_data._width;
558
}