Subversion Repositories Code-Repo

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
155 Kevin 1
#include <xc.h>
2
#include <delays.h>
3
#include <string.h>
4
#include <stdio.h>
5
#include "defines.h"
158 Kevin 6
#include "display_oled_ssd1331.h"
7
#include "base_SPI.h"
155 Kevin 8
#include "string.h"
9
#include "glcdfont.c"
10
 
11
static SSD1331_DATA *ssd1331_data_p;
12
 
13
int SSD1331_Abs(int i) {
14
    if (i < 0)
15
        return -i;
16
    else
17
        return i;
18
}
19
 
20
void SSD1331_Swap(int *a, int *b) {
21
    int tmp = *a;
22
    *a = *b;
23
    *b = tmp;
24
}
25
 
26
void SSD1331_Init(SSD1331_DATA *data) {
27
    ssd1331_data_p = data;
28
    ssd1331_data_p->_width = ssd1331_data_p->WIDTH = SSD1331_LCDWIDTH;
29
    ssd1331_data_p->_height = ssd1331_data_p->HEIGHT = SSD1331_LCDHEIGHT;
30
    ssd1331_data_p->rotation = 0;
31
    ssd1331_data_p->cursor_x = ssd1331_data_p->cursor_y = 0;
32
    ssd1331_data_p->textsize = 1;
33
    ssd1331_data_p->textcolor = ssd1331_data_p->textbgcolor = 0xFFFF;
34
    ssd1331_data_p->wrap = 1;
35
}
36
 
37
void SSD1331_Begin() {
38
    char buffer[37];
39
 
40
    // Toggle reset pin
41
    SPI_RESET_LAT = 0;
42
    Delay10KTCYx(1);
43
    SPI_RESET_LAT = 1;
44
 
45
    // Initialization Sequence
46
    buffer[0] = SSD1331_CMD_DISPLAYOFF; // 0xAE
47
    buffer[1] = SSD1331_CMD_SETREMAP; // 0xA0
48
#if defined SSD1331_COLORORDER_RGB
49
    buffer[2] = 0x72; // RGB Color
50
#else
51
    buffer[2] = 0x76; // BGR Color
52
#endif
53
    buffer[3] = SSD1331_CMD_STARTLINE; // 0xA1
54
    buffer[4] = 0x0;
55
    buffer[5] = SSD1331_CMD_DISPLAYOFFSET; // 0xA2
56
    buffer[6] = 0x0;
57
    buffer[7] = SSD1331_CMD_NORMALDISPLAY; // 0xA4
58
    buffer[8] = SSD1331_CMD_SETMULTIPLEX; // 0xA8
59
    buffer[9] = 0x3F; // 0x3F 1/64 duty
60
    buffer[10] = SSD1331_CMD_SETMASTER; // 0xAD
61
    buffer[11] = 0x8E;
62
    buffer[12] = SSD1331_CMD_POWERMODE; // 0xB0
63
    buffer[13] = 0x0B;
64
    buffer[14] = SSD1331_CMD_PRECHARGE; // 0xB1
65
    buffer[15] = 0x31;
66
    buffer[16] = SSD1331_CMD_CLOCKDIV; // 0xB3
67
    buffer[17] = 0xF0; // 7:4 = Oscillator Frequency, 3:0 = CLK Div Ratio (A[3:0]+1 = 1..16)
68
    buffer[18] = SSD1331_CMD_PRECHARGEA; // 0x8A
69
    buffer[19] = 0x64;
70
    buffer[20] = SSD1331_CMD_PRECHARGEB; // 0x8B
71
    buffer[21] = 0x78;
72
    buffer[22] = SSD1331_CMD_PRECHARGEA; // 0x8C
73
    buffer[23] = 0x64;
74
    buffer[24] = SSD1331_CMD_PRECHARGELEVEL; // 0xBB
75
    buffer[25] = 0x3A;
76
    buffer[26] = SSD1331_CMD_VCOMH; // 0xBE
77
    buffer[27] = 0x3E;
78
    buffer[28] = SSD1331_CMD_MASTERCURRENT; // 0x87
79
    buffer[29] = 0x06;
80
    buffer[30] = SSD1331_CMD_CONTRASTA; // 0x81
81
    buffer[31] = 0x91;
82
    buffer[32] = SSD1331_CMD_CONTRASTB; // 0x82
83
    buffer[33] = 0x50;
84
    buffer[34] = SSD1331_CMD_CONTRASTC; // 0x83
85
    buffer[35] = 0x7D;
86
    buffer[36] = SSD1331_CMD_DISPLAYON; //--turn on oled panel
87
 
88
    SPI_DC_SELECT_LAT = 0; // D/C low (cmd)
89
    SPI2_Write(buffer, 37);
90
}
91
 
92
void SSD1331_GoTo(int x, int y) {
93
    char buffer[6];
94
    if ((x >= SSD1331_LCDWIDTH) || (y >= SSD1331_LCDHEIGHT)) return;
95
 
96
    // set x and y coordinate
97
    buffer[0] = (SSD1331_CMD_SETCOLUMN);
98
    buffer[1] = (x); // Start x address
99
    buffer[2] = (SSD1331_LCDWIDTH - 1); // End x address
100
 
101
    buffer[3] = (SSD1331_CMD_SETROW);
102
    buffer[4] = (y); // Start y address
103
    buffer[5] = (SSD1331_LCDHEIGHT - 1); // End y address
104
 
105
    SPI_DC_SELECT_LAT = 0; // D/C low (cmd)
106
    SPI2_Write(buffer, 6);
107
}
108
 
109
void SSD1331_Command(char cmd) {
110
    SPI_DC_SELECT_LAT = 0; // D/C low (cmd)
111
    SPI2_Write(&cmd, 1);
112
}
113
 
114
void SSD1331_Data(char data) {
115
    SPI_DC_SELECT_LAT = 1; // D/C high (data)
116
    SPI2_Write(&data, 1);
117
}
118
 
119
void SSD1331_Clear_Display() {
120
    char buffer[5];
121
 
122
    buffer[0] = SSD1331_CMD_CLEARWINDOW;
123
    buffer[1] = 0;
124
    buffer[2] = 0;
125
    buffer[3] = SSD1331_LCDWIDTH-1;
126
    buffer[4] = SSD1331_LCDHEIGHT-1;
127
 
128
    SPI_DC_SELECT_LAT = 0; // D/C low (cmd)
129
    SPI2_Write(buffer, 5);
130
 
131
    Delay1KTCYx(4);
132
}
133
 
134
void SSD1331_Draw_Pixel(int x, int y, unsigned int color) {
135
    char buffer[2];
136
    buffer[0] = color >> 8;
137
    buffer[1] = color;
138
    if ((x < 0) || (x >= ssd1331_data_p->_width) || (y < 0) || (y >= ssd1331_data_p->_height)) return;
139
 
140
    // check rotation, move pixel around if necessary
141
    switch (ssd1331_data_p->rotation) {
142
        case 1:
143
            SSD1331_Swap(&x, &y);
144
            x = SSD1331_LCDWIDTH - x - 1;
145
            break;
146
        case 2:
147
            x = SSD1331_LCDWIDTH - x - 1;
148
            y = SSD1331_LCDHEIGHT - y - 1;
149
            break;
150
        case 3:
151
            SSD1331_Swap(&x, &y);
152
            y = SSD1331_LCDHEIGHT - y - 1;
153
            break;
154
    }
155
 
156
    SSD1331_GoTo(x, y);
157
 
158
    // setup for data
159
    SPI_DC_SELECT_LAT = 1; // D/C high (data)
160
 
161
    SPI2_Write(buffer, 2);
162
}
163
 
164
void SSD1331_Draw_Line(int x0, int y0, int x1, int y1, unsigned int color) {
165
    char buffer[8];
166
 
167
    // check rotation, move pixel around if necessary
168
    switch (ssd1331_data_p->rotation) {
169
        case 1:
170
            SSD1331_Swap(&x0, &y0);
171
            SSD1331_Swap(&x1, &y1);
172
            x0 = SSD1331_LCDWIDTH - x0 - 1;
173
            x1 = SSD1331_LCDWIDTH - x1 - 1;
174
            break;
175
        case 2:
176
            x0 = SSD1331_LCDWIDTH - x0 - 1;
177
            y0 = SSD1331_LCDHEIGHT - y0 - 1;
178
            x1 = SSD1331_LCDWIDTH - x1 - 1;
179
            y1 = SSD1331_LCDHEIGHT - y1 - 1;
180
            break;
181
        case 3:
182
            SSD1331_Swap(&x0, &y0);
183
            SSD1331_Swap(&x1, &y1);
184
            y0 = SSD1331_LCDHEIGHT - y0 - 1;
185
            y1 = SSD1331_LCDHEIGHT - y1 - 1;
186
            break;
187
    }
188
 
189
    // Boundary check
190
    if ((y0 >= SSD1331_LCDHEIGHT) && (y1 >= SSD1331_LCDHEIGHT))
191
        return;
192
    if ((x0 >= SSD1331_LCDWIDTH) && (x1 >= SSD1331_LCDWIDTH))
193
        return;
194
    if (x0 >= SSD1331_LCDWIDTH)
195
        x0 = SSD1331_LCDWIDTH - 1;
196
    if (y0 >= SSD1331_LCDHEIGHT)
197
        y0 = SSD1331_LCDHEIGHT - 1;
198
    if (x1 >= SSD1331_LCDWIDTH)
199
        x1 = SSD1331_LCDWIDTH - 1;
200
    if (y1 >= SSD1331_LCDHEIGHT)
201
        y1 = SSD1331_LCDHEIGHT - 1;
202
    if (x0 < 0)
203
        x0 = 0;
204
    if (y0 < 0)
205
        y0 = 0;
206
    if (x1 < 0)
207
        x1 = 0;
208
    if (y1 < 0)
209
        y1 = 0;
210
 
211
    buffer[0] = SSD1331_CMD_DRAWLINE;
212
    buffer[1] = x0;
213
    buffer[2] = y0;
214
    buffer[3] = x1;
215
    buffer[4] = y1;
216
    buffer[5] = (color >> 11) << 1;
217
    buffer[6] = (color >> 5) & 0x3F;
218
    buffer[7] = (color << 1) & 0x3F;
219
 
220
    SPI_DC_SELECT_LAT = 0; // D/C low (cmd)
221
    SPI2_Write(buffer, 8);
222
}
223
 
224
void SSD1331_Draw_Fast_VLine(int x, int y, int h, unsigned int color) {
225
    SSD1331_Draw_Line(x, y, x, y + h - 1, color);
226
}
227
 
228
void SSD1331_Draw_Fast_HLine(int x, int y, int w, unsigned int color) {
229
    SSD1331_Draw_Line(x, y, x + w - 1, y, color);
230
}
231
 
232
void SSD1331_Draw_Rect(int tx0, int ty0, int tx1, int ty1, unsigned int color) {
233
    char buffer[13];
234
    int x0,y0,x1,y1;
235
 
236
    // check rotation, move pixel around if necessary
237
    switch (ssd1331_data_p->rotation) {
238
        case 0:
239
            x0 = tx0;
240
            y0 = ty0;
241
            x1 = tx1;
242
            y1 = ty1;
243
            break;
244
        case 1:
245
            x0 = SSD1331_LCDWIDTH - ty1 - 1;
246
            y0 = tx0;
247
            x1 = SSD1331_LCDWIDTH - ty0 - 1;
248
            y1 = tx1;
249
            break;
250
        case 2:
251
            x0 = SSD1331_LCDWIDTH - tx1 - 1;
252
            y0 = SSD1331_LCDHEIGHT - ty1 - 1;
253
            x1 = SSD1331_LCDWIDTH - tx0 - 1;
254
            y1 = SSD1331_LCDHEIGHT - ty0 - 1;
255
            break;
256
        case 3:
257
            x0 = ty0;
258
            y0 = SSD1331_LCDHEIGHT - tx1 - 1;
259
            x1 = ty1;
260
            y1 = SSD1331_LCDHEIGHT - tx0 - 1;
261
            break;
262
    }
263
 
264
    // Boundary check
265
    if ((y0 >= SSD1331_LCDHEIGHT) && (y1 >= SSD1331_LCDHEIGHT))
266
        return;
267
    if ((x0 >= SSD1331_LCDWIDTH) && (x1 >= SSD1331_LCDWIDTH))
268
        return;
269
    if (x0 >= SSD1331_LCDWIDTH)
270
        x0 = SSD1331_LCDWIDTH - 1;
271
    if (y0 >= SSD1331_LCDHEIGHT)
272
        y0 = SSD1331_LCDHEIGHT - 1;
273
    if (x1 >= SSD1331_LCDWIDTH)
274
        x1 = SSD1331_LCDWIDTH - 1;
275
    if (y1 >= SSD1331_LCDHEIGHT)
276
        y1 = SSD1331_LCDHEIGHT - 1;
277
    if (x0 < 0)
278
        x0 = 0;
279
    if (y0 < 0)
280
        y0 = 0;
281
    if (x1 < 0)
282
        x1 = 0;
283
    if (y1 < 0)
284
        y1 = 0;
285
 
286
    buffer[0] = SSD1331_CMD_FILL;
287
    buffer[1] = 0;
288
    buffer[2] = SSD1331_CMD_DRAWRECT;
289
    buffer[3] = x0;
290
    buffer[4] = y0;
291
    buffer[5] = x1;
292
    buffer[6] = y1;
293
    buffer[7] = (color >> 11) << 1;
294
    buffer[8] = (color >> 5) & 0x3F;
295
    buffer[9] = (color << 1) & 0x3F;
296
    buffer[10] = 0;
297
    buffer[11] = 0;
298
    buffer[12] = 0;
299
 
300
    SPI_DC_SELECT_LAT = 0; // D/C low (cmd)
301
    SPI2_Write(buffer, 13);
302
}
303
 
304
void SSD1331_Fill_Rect(int tx0, int ty0, int tx1, int ty1, unsigned int color) {
305
    char buffer[13];
306
    int x0,y0,x1,y1;
307
 
308
    // check rotation, move pixel around if necessary
309
    switch (ssd1331_data_p->rotation) {
310
        case 0:
311
            x0 = tx0;
312
            y0 = ty0;
313
            x1 = tx1;
314
            y1 = ty1;
315
            break;
316
        case 1:
317
            x0 = SSD1331_LCDWIDTH - ty1 - 1;
318
            y0 = tx0;
319
            x1 = SSD1331_LCDWIDTH - ty0 - 1;
320
            y1 = tx1;
321
            break;
322
        case 2:
323
            x0 = SSD1331_LCDWIDTH - tx1 - 1;
324
            y0 = SSD1331_LCDHEIGHT - ty1 - 1;
325
            x1 = SSD1331_LCDWIDTH - tx0 - 1;
326
            y1 = SSD1331_LCDHEIGHT - ty0 - 1;
327
            break;
328
        case 3:
329
            x0 = ty0;
330
            y0 = SSD1331_LCDHEIGHT - tx1 - 1;
331
            x1 = ty1;
332
            y1 = SSD1331_LCDHEIGHT - tx0 - 1;
333
            break;
334
    }
335
 
336
    // Boundary check
337
    if ((y0 >= SSD1331_LCDHEIGHT) && (y1 >= SSD1331_LCDHEIGHT))
338
        return;
339
    if ((x0 >= SSD1331_LCDWIDTH) && (x1 >= SSD1331_LCDWIDTH))
340
        return;
341
    if (x0 >= SSD1331_LCDWIDTH)
342
        x0 = SSD1331_LCDWIDTH - 1;
343
    if (y0 >= SSD1331_LCDHEIGHT)
344
        y0 = SSD1331_LCDHEIGHT - 1;
345
    if (x1 >= SSD1331_LCDWIDTH)
346
        x1 = SSD1331_LCDWIDTH - 1;
347
    if (y1 >= SSD1331_LCDHEIGHT)
348
        y1 = SSD1331_LCDHEIGHT - 1;
349
    if (x0 < 0)
350
        x0 = 0;
351
    if (y0 < 0)
352
        y0 = 0;
353
    if (x1 < 0)
354
        x1 = 0;
355
    if (y1 < 0)
356
        y1 = 0;
357
 
358
    buffer[0] = SSD1331_CMD_FILL;
359
    buffer[1] = 1;
360
    buffer[2] = SSD1331_CMD_DRAWRECT;
361
    buffer[3] = x0;
362
    buffer[4] = y0;
363
    buffer[5] = x1;
364
    buffer[6] = y1;
365
    buffer[7] = (color >> 11) << 1;
366
    buffer[8] = (color >> 5) & 0x3F;
367
    buffer[9] = (color << 1) & 0x3F;
368
    buffer[10] = (color >> 11) << 1;
369
    buffer[11] = (color >> 5) & 0x3F;
370
    buffer[12] = (color << 1) & 0x3F;
371
 
372
    SPI_DC_SELECT_LAT = 0; // D/C low (cmd)
373
    SPI2_Write(buffer, 13);
374
 
375
    Delay1KTCYx(4);
376
}
377
 
378
void SSD1331_Draw_Circle(int x0, int y0, int r, unsigned int color) {
379
    int f = 1 - r;
380
    int ddF_x = 1;
381
    int ddF_y = -2 * r;
382
    int x = 0;
383
    int y = r;
384
 
385
    SSD1331_Draw_Pixel(x0, y0 + r, color);
386
    SSD1331_Draw_Pixel(x0, y0 - r, color);
387
    SSD1331_Draw_Pixel(x0 + r, y0, color);
388
    SSD1331_Draw_Pixel(x0 - r, y0, color);
389
 
390
    while (x < y) {
391
        if (f >= 0) {
392
            y--;
393
            ddF_y += 2;
394
            f += ddF_y;
395
        }
396
        x++;
397
        ddF_x += 2;
398
        f += ddF_x;
399
 
400
        SSD1331_Draw_Pixel(x0 + x, y0 + y, color);
401
        SSD1331_Draw_Pixel(x0 - x, y0 + y, color);
402
        SSD1331_Draw_Pixel(x0 + x, y0 - y, color);
403
        SSD1331_Draw_Pixel(x0 - x, y0 - y, color);
404
        SSD1331_Draw_Pixel(x0 + y, y0 + x, color);
405
        SSD1331_Draw_Pixel(x0 - y, y0 + x, color);
406
        SSD1331_Draw_Pixel(x0 + y, y0 - x, color);
407
        SSD1331_Draw_Pixel(x0 - y, y0 - x, color);
408
    }
409
}
410
 
411
void SSD1331_Draw_Circle_Helper(int x0, int y0, int r, char cornername, unsigned int color) {
412
    int f = 1 - r;
413
    int ddF_x = 1;
414
    int ddF_y = -2 * r;
415
    int x = 0;
416
    int y = r;
417
 
418
    while (x < y) {
419
        if (f >= 0) {
420
            y--;
421
            ddF_y += 2;
422
            f += ddF_y;
423
        }
424
        x++;
425
        ddF_x += 2;
426
        f += ddF_x;
427
 
428
        if (cornername & 0x4) {
429
            SSD1331_Draw_Pixel(x0 + x, y0 + y, color);
430
            SSD1331_Draw_Pixel(x0 + y, y0 + x, color);
431
        }
432
        if (cornername & 0x2) {
433
            SSD1331_Draw_Pixel(x0 + x, y0 - y, color);
434
            SSD1331_Draw_Pixel(x0 + y, y0 - x, color);
435
        }
436
        if (cornername & 0x8) {
437
            SSD1331_Draw_Pixel(x0 - y, y0 + x, color);
438
            SSD1331_Draw_Pixel(x0 - x, y0 + y, color);
439
        }
440
        if (cornername & 0x1) {
441
            SSD1331_Draw_Pixel(x0 - y, y0 - x, color);
442
            SSD1331_Draw_Pixel(x0 - x, y0 - y, color);
443
        }
444
    }
445
}
446
 
447
void SSD1331_Fill_Circle(int x0, int y0, int r, unsigned int color) {
448
    SSD1331_Draw_Fast_VLine(x0, y0 - r, 2 * r + 1, color);
449
    SSD1331_Fill_Circle_Helper(x0, y0, r, 3, 0, color);
450
}
451
 
452
void SSD1331_Fill_Circle_Helper(int x0, int y0, int r, char cornername, int delta, unsigned int color) {
453
    int f = 1 - r;
454
    int ddF_x = 1;
455
    int ddF_y = -2 * r;
456
    int x = 0;
457
    int y = r;
458
 
459
    while (x < y) {
460
        if (f >= 0) {
461
            y--;
462
            ddF_y += 2;
463
            f += ddF_y;
464
        }
465
        x++;
466
        ddF_x += 2;
467
        f += ddF_x;
468
 
469
        if (cornername & 0x1) {
470
            SSD1331_Draw_Fast_VLine(x0 + x, y0 - y, 2 * y + 1 + delta, color);
471
            SSD1331_Draw_Fast_VLine(x0 + y, y0 - x, 2 * x + 1 + delta, color);
472
        }
473
        if (cornername & 0x2) {
474
            SSD1331_Draw_Fast_VLine(x0 - x, y0 - y, 2 * y + 1 + delta, color);
475
            SSD1331_Draw_Fast_VLine(x0 - y, y0 - x, 2 * x + 1 + delta, color);
476
        }
477
    }
478
}
479
void SSD1331_Draw_Triangle(int x0, int y0, int x1, int y1, int x2, int y2, unsigned int color) {
480
    SSD1331_Draw_Line(x0, y0, x1, y1, color);
481
    SSD1331_Draw_Line(x1, y1, x2, y2, color);
482
    SSD1331_Draw_Line(x2, y2, x0, y0, color);
483
}
484
 
485
void SSD1331_Fill_Triangle(int x0, int y0, int x1, int y1, int x2, int y2, unsigned int color) {
486
    int a, b, y, last;
487
    int dx01 = x1 - x0;
488
    int dy01 = y1 - y0;
489
    int dx02 = x2 - x0;
490
    int dy02 = y2 - y0;
491
    int dx12 = x2 - x1;
492
    int dy12 = y2 - y1;
493
    int sa = 0;
494
    int sb = 0;
495
 
496
    // Sort coordinates by Y order (y2 >= y1 >= y0)
497
    if (y0 > y1) {
498
        SSD1331_Swap(&y0, &y1);
499
        SSD1331_Swap(&x0, &x1);
500
    }
501
    if (y1 > y2) {
502
        SSD1331_Swap(&y2, &y1);
503
        SSD1331_Swap(&x2, &x1);
504
    }
505
    if (y0 > y1) {
506
        SSD1331_Swap(&y0, &y1);
507
        SSD1331_Swap(&x0, &x1);
508
    }
509
 
510
    if (y0 == y2) { // Handle awkward all-on-same-line case as its own thing
511
        a = b = x0;
512
        if (x1 < a) a = x1;
513
        else if (x1 > b) b = x1;
514
        if (x2 < a) a = x2;
515
        else if (x2 > b) b = x2;
516
        SSD1331_Draw_Fast_HLine(a, y0, b - a + 1, color);
517
        return;
518
    }
519
 
520
    // For upper part of triangle, find scanline crossings for segments
521
    // 0-1 and 0-2.  If y1=y2 (flat-bottomed triangle), the scanline y1
522
    // is included here (and second loop will be skipped, avoiding a /0
523
    // error there), otherwise scanline y1 is skipped here and handled
524
    // in the second loop...which also avoids a /0 error here if y0=y1
525
    // (flat-topped triangle).
526
    if (y1 == y2) last = y1; // Include y1 scanline
527
    else last = y1 - 1; // Skip it
528
 
529
    for (y = y0; y <= last; y++) {
530
        a = x0 + sa / dy01;
531
        b = x0 + sb / dy02;
532
        sa += dx01;
533
        sb += dx02;
534
        /* longhand:
535
        a = x0 + (x1 - x0) * (y - y0) / (y1 - y0);
536
        b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
537
         */
538
        if (a > b) SSD1331_Swap(&a, &b);
539
        SSD1331_Draw_Fast_HLine(a, y, b - a + 1, color);
540
    }
541
 
542
    // For lower part of triangle, find scanline crossings for segments
543
    // 0-2 and 1-2.  This loop is skipped if y1=y2.
544
    sa = dx12 * (y - y1);
545
    sb = dx02 * (y - y0);
546
    for (; y <= y2; y++) {
547
        a = x1 + sa / dy12;
548
        b = x0 + sb / dy02;
549
        sa += dx12;
550
        sb += dx02;
551
        /* longhand:
552
        a = x1 + (x2 - x1) * (y - y1) / (y2 - y1);
553
        b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
554
         */
555
        if (a > b) SSD1331_Swap(&a, &b);
556
        SSD1331_Draw_Fast_HLine(a, y, b - a + 1, color);
557
    }
558
}
559
 
560
void SSD1331_Draw_Round_Rect(int x, int y, int w, int h, int r, unsigned int color) {
561
    // smarter version
562
    SSD1331_Draw_Fast_HLine(x + r, y, w - 2 * r, color); // Top
563
    SSD1331_Draw_Fast_HLine(x + r, y + h - 1, w - 2 * r, color); // Bottom
564
    SSD1331_Draw_Fast_VLine(x, y + r, h - 2 * r, color); // Left
565
    SSD1331_Draw_Fast_VLine(x + w - 1, y + r, h - 2 * r, color); // Right
566
 
567
    // draw four corners
568
    SSD1331_Draw_Circle_Helper(x + r, y + r, r, 1, color);
569
    SSD1331_Draw_Circle_Helper(x + w - r - 1, y + r, r, 2, color);
570
    SSD1331_Draw_Circle_Helper(x + w - r - 1, y + h - r - 1, r, 4, color);
571
    SSD1331_Draw_Circle_Helper(x + r, y + h - r - 1, r, 8, color);
572
}
573
 
574
void SSD1331_Fill_Round_Rect(int x, int y, int w, int h, int r, unsigned int color) {
575
    // smarter version
576
    SSD1331_Fill_Rect(x + r, y, w - 2 * r, h, color);
577
 
578
    // draw four corners
579
    SSD1331_Fill_Circle_Helper(x + w - r - 1, y + r, r, 1, h - 2 * r - 1, color);
580
    SSD1331_Fill_Circle_Helper(x + r, y + r, r, 2, h - 2 * r - 1, color);
581
}
582
 
583
void SSD1331_Draw_Bitmap(int x, int y, const char* bitmap, int w, int h, unsigned int color) {
584
    int i, j;
585
    for (j = 0; j < h; j++) {
586
        for (i = 0; i < w; i++) {
587
            if (bitmap[i + (j / 8) * w] & (j % 8)) {
588
                SSD1331_Draw_Pixel(x + i, y + j, color);
589
            }
590
        }
591
    }
592
}
593
 
594
void SSD1331_Draw_Char(int x, int y, char c, unsigned int color, unsigned int bg, char size) {
595
    int i, j;
596
    unsigned int line;
597
 
598
    if ((x >= ssd1331_data_p->_width) || // Clip right
599
            (y >= ssd1331_data_p->_height) || // Clip bottom
600
            ((x + 5 * size - 1) < 0) || // Clip left
601
            ((y + 8 * size - 1) < 0)) // Clip top
602
        return;
603
 
604
    for (i = 0; i < 6; i++) {
605
        if (i == 5)
606
            line = 0x0;
607
        else
608
            line = font[(c * 5) + i];
609
        for (j = 0; j < 8; j++) {
610
            if (line & 0x1) {
611
                if (size == 1) {// default size
612
                    SSD1331_Draw_Pixel(x + i, y + j, color);
613
                } else { // big size
614
                    SSD1331_Fill_Rect(x + (i * size), y + (j * size), size, size, color);
615
                }
616
            } else if (bg != color) {
617
                if (size == 1) { // default size
618
                    SSD1331_Draw_Pixel(x + i, y + j, bg);
619
                } else { // big size
620
                    SSD1331_Fill_Rect(x + i*size, y + j*size, size, size, bg);
621
                }
622
            }
623
            line >>= 1;
624
        }
625
    }
626
}
627
 
628
void SSD1331_Write(char c) {
629
    if (c == '\n' || c == '\r') {
630
        ssd1331_data_p->cursor_y += ssd1331_data_p->textsize * 8;
631
        ssd1331_data_p->cursor_x = 0;
632
        //    } else if (c == '\r') {
633
        //        // skip em
634
    } else {
635
        SSD1331_Draw_Char(ssd1331_data_p->cursor_x, ssd1331_data_p->cursor_y, c, ssd1331_data_p->textcolor, ssd1331_data_p->textbgcolor, ssd1331_data_p->textsize);
636
        ssd1331_data_p->cursor_x += ssd1331_data_p->textsize * 6;
637
        if (ssd1331_data_p->wrap && (ssd1331_data_p->cursor_x > (ssd1331_data_p->_width - ssd1331_data_p->textsize * 6))) {
638
            ssd1331_data_p->cursor_y += ssd1331_data_p->textsize * 8;
639
            ssd1331_data_p->cursor_x = 0;
640
        }
641
    }
642
}
643
 
644
void SSD1331_Write_String(char* msg, char length) {
645
    for (char i = 0; i < length; i++) {
646
        SSD1331_Write(msg[i]);
647
    }
648
}
649
 
650
//void SSD1331_Write_String(const rom char *fmt, ...) {
651
//    unsigned char i, len;
652
//    unsigned char buffer[SSD1331_STRING_BUFFER_SIZE];
653
//
654
//    // Parse and create string
655
//    va_list args;
656
//    va_start(args, fmt);
657
//    vsprintf((char *) buffer, fmt, args);
658
//    va_end(args);
659
//    len = strlen((char *) buffer);
660
//
661
//    // Make sure string to insert fits in buffer, truncate if necessary
662
//    if (len > SSD1331_STRING_BUFFER_SIZE)
663
//        len = SSD1331_STRING_BUFFER_SIZE;
664
//
665
//    // Print buffer to string
666
//    for (i = 0; i < len; i++) {
667
//        SSD1331_Write(buffer[i]);
668
//    }
669
//}
670
 
671
void SSD1331_Set_Cursor(int x, int y) {
672
    ssd1331_data_p->cursor_x = x;
673
    ssd1331_data_p->cursor_y = y;
674
}
675
 
676
void SSD1331_Set_Text_Color(unsigned int c) {
677
    // for 'transparent' background, we'll set the bg
678
    // to the same as fg instead of using a flag
679
    ssd1331_data_p->textcolor = c;
680
    ssd1331_data_p->textbgcolor = c;
681
}
682
 
683
void SSD1331_Set_Text_Color_BG(unsigned int c, unsigned int bg) {
684
    ssd1331_data_p->textcolor = c;
685
    ssd1331_data_p->textbgcolor = bg;
686
}
687
 
688
void SSD1331_Set_Text_Size(char s) {
689
    ssd1331_data_p->textsize = (s > 0) ? s : 1;
690
}
691
 
692
void SSD1331_Set_Text_Wrap(char w) {
693
    ssd1331_data_p->wrap = w;
694
}
695
 
696
void SSD1331_Set_Rotation(char x) {
697
    x %= 4; // cant be higher than 3
698
    ssd1331_data_p->rotation = x;
699
    switch (x) {
700
        case 0:
701
        case 2:
702
            ssd1331_data_p->_width = ssd1331_data_p->WIDTH;
703
            ssd1331_data_p->_height = ssd1331_data_p->HEIGHT;
704
            break;
705
        case 1:
706
        case 3:
707
            ssd1331_data_p->_width = ssd1331_data_p->HEIGHT;
708
            ssd1331_data_p->_height = ssd1331_data_p->WIDTH;
709
            break;
710
    }
711
}
712
 
713
unsigned int SSD1331_Color565(char r, char g, char b) {
714
    unsigned int c;
715
    c = r >> 3;
716
    c <<= 6;
717
    c |= g >> 2;
718
    c <<= 5;
719
    c |= b >> 3;
720
 
721
    return c;
722
}
723
 
724
void SSD1331_Test_DrawLines(unsigned int color) {
725
    int x, y;
726
    SSD1331_Clear_Display();
727
    for (x = 0; x < ssd1331_data_p->_width - 1; x += 6) {
728
        SSD1331_Draw_Line(0, 0, x, ssd1331_data_p->_height - 1, color);
729
    }
730
    for (y = 0; y < ssd1331_data_p->_height - 1; y += 6) {
731
        SSD1331_Draw_Line(0, 0, ssd1331_data_p->_width - 1, y, color);
732
    }
733
 
734
    SSD1331_Clear_Display();
735
    for (x = 0; x < ssd1331_data_p->_width - 1; x += 6) {
736
        SSD1331_Draw_Line(ssd1331_data_p->_width - 1, 0, x, ssd1331_data_p->_height - 1, color);
737
    }
738
    for (y = 0; y < ssd1331_data_p->_height - 1; y += 6) {
739
        SSD1331_Draw_Line(ssd1331_data_p->_width - 1, 0, 0, y, color);
740
    }
741
 
742
    SSD1331_Clear_Display();
743
    for (x = 0; x < ssd1331_data_p->_width - 1; x += 6) {
744
        SSD1331_Draw_Line(0, ssd1331_data_p->_height - 1, x, 0, color);
745
    }
746
    for (y = 0; y < ssd1331_data_p->_height - 1; y += 6) {
747
        SSD1331_Draw_Line(0, ssd1331_data_p->_height - 1, ssd1331_data_p->_width - 1, y, color);
748
    }
749
 
750
    SSD1331_Clear_Display();
751
    for (x = 0; x < ssd1331_data_p->_width - 1; x += 6) {
752
        SSD1331_Draw_Line(ssd1331_data_p->_width - 1, ssd1331_data_p->_height - 1, x, 0, color);
753
    }
754
    for (y = 0; y < ssd1331_data_p->_height - 1; y += 6) {
755
        SSD1331_Draw_Line(ssd1331_data_p->_width - 1, ssd1331_data_p->_height - 1, 0, y, color);
756
    }
757
}
758
 
759
void SSD1331_Test_DrawRect(unsigned int color) {
760
    int x;
761
    SSD1331_Clear_Display();
762
    if (ssd1331_data_p->_height < ssd1331_data_p->_width) {
763
        for (x = 0; x < ssd1331_data_p->_height - 1; x += 6) {
764
            SSD1331_Draw_Rect((ssd1331_data_p->_width - 1) / 2 - x / 2, (ssd1331_data_p->_height - 1) / 2 - x / 2, x, x, color);
765
        }
766
    } else {
767
        for (x = 0; x < ssd1331_data_p->_width - 1; x += 6) {
768
            SSD1331_Draw_Rect((ssd1331_data_p->_width - 1) / 2 - x / 2, (ssd1331_data_p->_height - 1) / 2 - x / 2, x, x, color);
769
        }
770
    }
771
}
772
 
773
void SSD1331_Test_FillRect(unsigned int color1, unsigned int color2) {
774
    int x;
775
    SSD1331_Clear_Display();
776
    if (ssd1331_data_p->_height < ssd1331_data_p->_width) {
777
        for (x = ssd1331_data_p->_height - 1; x > 6; x -= 6) {
778
            SSD1331_Fill_Rect((ssd1331_data_p->_width - 1) / 2 - x / 2, (ssd1331_data_p->_height - 1) / 2 - x / 2, x, x, color1);
779
            SSD1331_Draw_Rect((ssd1331_data_p->_width - 1) / 2 - x / 2, (ssd1331_data_p->_height - 1) / 2 - x / 2, x, x, color2);
780
        }
781
    } else {
782
        for (x = ssd1331_data_p->_width - 1; x > 6; x -= 6) {
783
            SSD1331_Fill_Rect((ssd1331_data_p->_width - 1) / 2 - x / 2, (ssd1331_data_p->_height - 1) / 2 - x / 2, x, x, color1);
784
            SSD1331_Draw_Rect((ssd1331_data_p->_width - 1) / 2 - x / 2, (ssd1331_data_p->_height - 1) / 2 - x / 2, x, x, color2);
785
        }
786
    }
787
}
788
 
789
void SSD1331_Test_DrawCircle(unsigned int radius, unsigned int color) {
790
    int x, y;
791
    for (x = 0; x < ssd1331_data_p->_width - 1 + radius; x += radius * 2) {
792
        for (y = 0; y < ssd1331_data_p->_height - 1 + radius; y += radius * 2) {
793
            SSD1331_Draw_Circle(x, y, radius, color);
794
        }
795
    }
796
}
797
 
798
void SSD1331_Test_FillCircle(unsigned int radius, unsigned int color) {
799
    char x, y;
800
    for (x = radius; x < ssd1331_data_p->_width - 1; x += radius * 2) {
801
        for (y = radius; y < ssd1331_data_p->_height - 1; y += radius * 2) {
802
            SSD1331_Fill_Circle(x, y, radius, color);
803
        }
804
    }
805
}
806
 
807
void SSD1331_Test_DrawTria(void) {
808
    int color = 0xF800;
809
    int t;
810
    int w = ssd1331_data_p->_width / 2;
811
    int x = ssd1331_data_p->_height;
812
    int y = 0;
813
    int z = ssd1331_data_p->_width;
814
    SSD1331_Clear_Display();
815
    for (t = 0; t <= 15; t += 1) {
816
        SSD1331_Draw_Triangle(w, y, y, x, z, x, color);
817
        x -= 4;
818
        y += 4;
819
        z -= 4;
820
        color += 100;
821
    }
822
}
823
 
824
void SSD1331_Test_DrawRoundRect(void) {
825
    int color = 100;
826
    int i, t, x, y, w, h;
827
    SSD1331_Clear_Display();
828
    for (t = 0; t <= 4; t += 1) {
829
        x = 0;
830
        y = 0;
831
        w = ssd1331_data_p->_width;
832
        h = ssd1331_data_p->_height;
833
        for (i = 0; i <= 24; i += 1) {
834
            SSD1331_Draw_Round_Rect(x, y, w, h, 5, color);
835
            x += 2;
836
            y += 3;
837
            w -= 4;
838
            h -= 6;
839
            color += 1100;
840
        }
841
        color += 100;
842
    }
843
}
844
 
845
void SSD1331_Test_MediaButtons(void) {
846
    // play
847
    SSD1331_Clear_Display();
848
    SSD1331_Fill_Round_Rect(25, 10, 78, 60, 8, SSD1331_WHITE);
849
    SSD1331_Fill_Triangle(42, 20, 42, 60, 90, 40, SSD1331_RED);
850
    Delay10KTCYx(100);
851
    // pause
852
    SSD1331_Fill_Round_Rect(25, 90, 78, 60, 8, SSD1331_WHITE);
853
    SSD1331_Fill_Round_Rect(39, 98, 20, 45, 5, SSD1331_GREEN);
854
    SSD1331_Fill_Round_Rect(69, 98, 20, 45, 5, SSD1331_GREEN);
855
    Delay10KTCYx(100);
856
    // play color
857
    SSD1331_Fill_Triangle(42, 20, 42, 60, 90, 40, SSD1331_BLUE);
858
    Delay10KTCYx(100);
859
    // pause color
860
    SSD1331_Fill_Round_Rect(39, 98, 20, 45, 5, SSD1331_RED);
861
    SSD1331_Fill_Round_Rect(69, 98, 20, 45, 5, SSD1331_RED);
862
    // play color
863
    SSD1331_Fill_Triangle(42, 20, 42, 60, 90, 40, SSD1331_GREEN);
864
}
865
 
866
void SSD1331_Test_Pattern(void) {
867
    char buffer[2];
868
    unsigned int i, j;
869
    SSD1331_GoTo(0, 0);
870
 
871
    for (i = 0; i < 64; i++) {
872
        for (j = 0; j < 96; j++) {
873
            if (i > 55) {
874
                buffer[0] = (SSD1331_WHITE >> 8);
875
                buffer[1] = (SSD1331_WHITE);
876
            } else if (i > 47) {
877
                buffer[0] = (SSD1331_BLUE >> 8);
878
                buffer[1] = (SSD1331_BLUE);
879
            } else if (i > 39) {
880
                buffer[0] = (SSD1331_GREEN >> 8);
881
                buffer[1] = (SSD1331_GREEN);
882
            } else if (i > 31) {
883
                buffer[0] = (SSD1331_CYAN >> 8);
884
                buffer[1] = (SSD1331_CYAN);
885
            } else if (i > 23) {
886
                buffer[0] = (SSD1331_RED >> 8);
887
                buffer[1] = (SSD1331_RED);
888
            } else if (i > 15) {
889
                buffer[0] = (SSD1331_MAGENTA >> 8);
890
                buffer[1] = (SSD1331_MAGENTA);
891
            } else if (i > 7) {
892
                buffer[0] = (SSD1331_YELLOW >> 8);
893
                buffer[1] = (SSD1331_YELLOW);
894
            } else {
895
                buffer[0] = (SSD1331_BLACK >> 8);
896
                buffer[1] = (SSD1331_BLACK);
897
            }
898
            SPI_DC_SELECT_LAT = 1; // D/C high (data)
899
            SPI2_Write(buffer, 2);
900
        }
901
    }
902
}