OSDN Git Service

First commitment for the BlackTank LPC1769.
[blacktank/blacktank.git] / task_display.c
1 /**
2  * @file task_display.c
3  * @author Shinichiro Nakamura
4  * @brief ディスプレイタスクの実装(task_display)
5  * @details
6  * ディスプレイタスクは有機ELディスプレイを制御するタスクである。
7  * ディスプレイの制御は以下のマクロを使って行うことができる。
8  *
9  * DISP_CLEAR(r, g, b);
10  * DISP_LINE(x1, y1, x2, y2, r, g, b);
11  * DISP_BOX(x1, y1, x2, y2, r, g, b);
12  * DISP_FILLBOX(x1, y1, x2, y2, r1, g1, b1, r2, g2, b2);
13  * DISP_TEXT(x, y, r, g, b, "text");
14  * DISP_BMPFILE("filename");
15  */
16
17 #include <LPC17xx.h>
18 #include <kernel.h>
19 #include <t_syslog.h>
20 #include <itron.h>
21
22 #include "kernel_cfg.h"
23 #include "task_display.h"
24 #include "oled.h"
25 #include "ff.h"
26 #include "bmplowio.h"
27
28 static const uint8_t FONT_X = 5;
29 static const uint8_t FONT_Y = 7;
30 static const uint16_t FONT_MIN_CODE = 0x20;
31 static const uint16_t FONT_MAX_CODE = 0x7F;
32 static const uint8_t font5x7_data[] = {
33     0x00, 0x00, 0x00, 0x00, 0x00, // (white space)
34     0x00, 0x00, 0x5F, 0x00, 0x00, // !
35     0x00, 0x07, 0x00, 0x07, 0x00, // "
36     0x14, 0x7F, 0x14, 0x7F, 0x14, // #
37     0x24, 0x2A, 0x7F, 0x2A, 0x12, // $
38     0x23, 0x13, 0x08, 0x64, 0x62, // %
39     0x36, 0x49, 0x55, 0x22, 0x50, // &
40     0x00, 0x05, 0x03, 0x00, 0x00, // '
41     0x00, 0x1C, 0x22, 0x41, 0x00, // (
42     0x00, 0x41, 0x22, 0x1C, 0x00, // )
43     0x08, 0x2A, 0x1C, 0x2A, 0x08, // *
44     0x08, 0x08, 0x3E, 0x08, 0x08, // +
45     0x00, 0x50, 0x30, 0x00, 0x00, // ,
46     0x08, 0x08, 0x08, 0x08, 0x08, // -
47     0x00, 0x60, 0x60, 0x00, 0x00, // .
48     0x20, 0x10, 0x08, 0x04, 0x02, // /
49     0x3E, 0x51, 0x49, 0x45, 0x3E, // 0
50     0x00, 0x42, 0x7F, 0x40, 0x00, // 1
51     0x42, 0x61, 0x51, 0x49, 0x46, // 2
52     0x21, 0x41, 0x45, 0x4B, 0x31, // 3
53     0x18, 0x14, 0x12, 0x7F, 0x10, // 4
54     0x27, 0x45, 0x45, 0x45, 0x39, // 5
55     0x3C, 0x4A, 0x49, 0x49, 0x30, // 6
56     0x01, 0x71, 0x09, 0x05, 0x03, // 7
57     0x36, 0x49, 0x49, 0x49, 0x36, // 8
58     0x06, 0x49, 0x49, 0x29, 0x1E, // 9
59     0x00, 0x36, 0x36, 0x00, 0x00, // :
60     0x00, 0x56, 0x36, 0x00, 0x00, // ;
61     0x00, 0x08, 0x14, 0x22, 0x41, // <
62     0x14, 0x14, 0x14, 0x14, 0x14, // =
63     0x41, 0x22, 0x14, 0x08, 0x00, // >
64     0x02, 0x01, 0x51, 0x09, 0x06, // ?
65     0x32, 0x49, 0x79, 0x41, 0x3E, // @
66     0x7E, 0x11, 0x11, 0x11, 0x7E, // A
67     0x7F, 0x49, 0x49, 0x49, 0x36, // B
68     0x3E, 0x41, 0x41, 0x41, 0x22, // C
69     0x7F, 0x41, 0x41, 0x22, 0x1C, // D
70     0x7F, 0x49, 0x49, 0x49, 0x41, // E
71     0x7F, 0x09, 0x09, 0x01, 0x01, // F
72     0x3E, 0x41, 0x41, 0x51, 0x32, // G
73     0x7F, 0x08, 0x08, 0x08, 0x7F, // H
74     0x00, 0x41, 0x7F, 0x41, 0x00, // I
75     0x20, 0x40, 0x41, 0x3F, 0x01, // J
76     0x7F, 0x08, 0x14, 0x22, 0x41, // K
77     0x7F, 0x40, 0x40, 0x40, 0x40, // L
78     0x7F, 0x02, 0x04, 0x02, 0x7F, // M
79     0x7F, 0x04, 0x08, 0x10, 0x7F, // N
80     0x3E, 0x41, 0x41, 0x41, 0x3E, // O
81     0x7F, 0x09, 0x09, 0x09, 0x06, // P
82     0x3E, 0x41, 0x51, 0x21, 0x5E, // Q
83     0x7F, 0x09, 0x19, 0x29, 0x46, // R
84     0x46, 0x49, 0x49, 0x49, 0x31, // S
85     0x01, 0x01, 0x7F, 0x01, 0x01, // T
86     0x3F, 0x40, 0x40, 0x40, 0x3F, // U
87     0x1F, 0x20, 0x40, 0x20, 0x1F, // V
88     0x7F, 0x20, 0x18, 0x20, 0x7F, // W
89     0x63, 0x14, 0x08, 0x14, 0x63, // X
90     0x03, 0x04, 0x78, 0x04, 0x03, // Y
91     0x61, 0x51, 0x49, 0x45, 0x43, // Z
92     0x00, 0x00, 0x7F, 0x41, 0x41, // [
93     0x02, 0x04, 0x08, 0x10, 0x20, // /
94     0x41, 0x41, 0x7F, 0x00, 0x00, // ]
95     0x04, 0x02, 0x01, 0x02, 0x04, // ^
96     0x40, 0x40, 0x40, 0x40, 0x40, // _
97     0x00, 0x01, 0x02, 0x04, 0x00, // `
98     0x20, 0x54, 0x54, 0x54, 0x78, // a
99     0x7F, 0x48, 0x44, 0x44, 0x38, // b
100     0x38, 0x44, 0x44, 0x44, 0x20, // c
101     0x38, 0x44, 0x44, 0x48, 0x7F, // d
102     0x38, 0x54, 0x54, 0x54, 0x18, // e
103     0x08, 0x7E, 0x09, 0x01, 0x02, // f
104     0x08, 0x14, 0x54, 0x54, 0x3C, // g
105     0x7F, 0x08, 0x04, 0x04, 0x78, // h
106     0x00, 0x44, 0x7D, 0x40, 0x00, // i
107     0x20, 0x40, 0x44, 0x3D, 0x00, // j
108     0x00, 0x7F, 0x10, 0x28, 0x44, // k
109     0x00, 0x41, 0x7F, 0x40, 0x00, // l
110     0x7C, 0x04, 0x18, 0x04, 0x78, // m
111     0x7C, 0x08, 0x04, 0x04, 0x78, // n
112     0x38, 0x44, 0x44, 0x44, 0x38, // o
113     0x7C, 0x14, 0x14, 0x14, 0x08, // p
114     0x08, 0x14, 0x14, 0x18, 0x7C, // q
115     0x7C, 0x08, 0x04, 0x04, 0x08, // r
116     0x48, 0x54, 0x54, 0x54, 0x20, // s
117     0x04, 0x3F, 0x44, 0x40, 0x20, // t
118     0x3C, 0x40, 0x40, 0x20, 0x7C, // u
119     0x1C, 0x20, 0x40, 0x20, 0x1C, // v
120     0x3C, 0x40, 0x30, 0x40, 0x3C, // w
121     0x44, 0x28, 0x10, 0x28, 0x44, // x
122     0x0C, 0x50, 0x50, 0x50, 0x3C, // y
123     0x44, 0x64, 0x54, 0x4C, 0x44, // z
124     0x00, 0x08, 0x36, 0x41, 0x00, // {
125     0x00, 0x00, 0x7F, 0x00, 0x00, // |
126     0x00, 0x41, 0x36, 0x08, 0x00, // }
127     0x08, 0x08, 0x2A, 0x1C, 0x08, // ->
128     0x08, 0x1C, 0x2A, 0x08, 0x08  // <-
129 };
130
131 typedef struct {
132     FATFS fatfs[_VOLUMES];
133     DIR dir;
134     FIL fil;
135     FILINFO filinfo;
136 } work_t;
137
138 work_t work;
139
140 void disp_clear(const uint8_t r, const uint8_t g, const uint8_t b)
141 {
142     VP vp;
143     get_mpf(MPF_DISPLAY, &vp);
144     ((display_msg_t*)vp)->cmd = DISPLAY_CMD_CLEAR;
145     display_clear_t *param =
146         (display_clear_t *)&(((display_msg_t*)vp)->param);
147     param->r = r;
148     param->g = g;
149     param->b = b;
150     snd_mbx(MBX_DISPLAY, vp);
151 }
152
153 void disp_line(
154         const uint8_t x1,
155         const uint8_t y1,
156         const uint8_t x2,
157         const uint8_t y2,
158         const uint8_t r,
159         const uint8_t g,
160         const uint8_t b)
161 {
162     VP vp;
163     get_mpf(MPF_DISPLAY, &vp);
164     ((display_msg_t*)vp)->cmd = DISPLAY_CMD_LINE;
165     display_line_t *param =
166         (display_line_t *)&(((display_msg_t*)vp)->param);
167     param->x1 = x1;
168     param->y1 = y1;
169     param->x2 = x2;
170     param->y2 = y2;
171     param->r = r;
172     param->g = g;
173     param->b = b;
174     snd_mbx(MBX_DISPLAY, vp);
175 }
176
177 void disp_box(
178         const uint8_t x1,
179         const uint8_t y1,
180         const uint8_t x2,
181         const uint8_t y2,
182         const uint8_t r,
183         const uint8_t g,
184         const uint8_t b)
185 {
186     VP vp;
187     get_mpf(MPF_DISPLAY, &vp);
188     ((display_msg_t*)vp)->cmd = DISPLAY_CMD_BOX;
189     display_box_t *param =
190         (display_box_t *)&(((display_msg_t*)vp)->param);
191     param->x1 = x1;
192     param->y1 = y1;
193     param->x2 = x2;
194     param->y2 = y2;
195     param->r = r;
196     param->g = g;
197     param->b = b;
198     snd_mbx(MBX_DISPLAY, vp);
199 }
200
201 void disp_fillbox(
202         const uint8_t x1,
203         const uint8_t y1,
204         const uint8_t x2,
205         const uint8_t y2,
206         const uint8_t r1,
207         const uint8_t g1,
208         const uint8_t b1,
209         const uint8_t r2,
210         const uint8_t g2,
211         const uint8_t b2)
212 {
213     VP vp;
214     get_mpf(MPF_DISPLAY, &vp);
215     ((display_msg_t*)vp)->cmd = DISPLAY_CMD_FILLBOX;
216     display_fillbox_t *param =
217         (display_fillbox_t *)&(((display_msg_t*)vp)->param);
218     param->x1 = x1;
219     param->y1 = y1;
220     param->x2 = x2;
221     param->y2 = y2;
222     param->r1 = r1;
223     param->g1 = g1;
224     param->b1 = b1;
225     param->r2 = r2;
226     param->g2 = g2;
227     param->b2 = b2;
228     snd_mbx(MBX_DISPLAY, vp);
229 }
230
231 void disp_text(
232         const uint8_t x,
233         const uint8_t y,
234         const uint8_t r,
235         const uint8_t g,
236         const uint8_t b,
237         const char *text)
238 {
239     int i;
240     const char *strp;
241     VP vp;
242     get_mpf(MPF_DISPLAY, &vp);
243     ((display_msg_t*)vp)->cmd = DISPLAY_CMD_TEXT;
244     display_text_t *param =
245         (display_text_t *)&(((display_msg_t*)vp)->param);
246     param->x = x;
247     param->y = y;
248     param->r = r;
249     param->g = g;
250     param->b = b;
251     strp = text;
252     i = 0;
253     while (*strp) {
254         param->text[i] = *strp;
255         i++;
256         strp++;
257     }
258     param->text[i] = '\0';
259     snd_mbx(MBX_DISPLAY, vp);
260 }
261
262 void disp_bmpfile(const char *filename)
263 {
264     int i;
265     char *strp;
266     VP vp;
267     get_mpf(MPF_DISPLAY, &vp);
268     ((display_msg_t*)vp)->cmd = DISPLAY_CMD_BMPFILE;
269     display_bmpfile_t *param =
270         (display_bmpfile_t *)&(((display_msg_t*)vp)->param);
271     strp = (char *)filename;
272     i = 0;
273     while (*strp) {
274         param->filename[i++] = *strp;
275         strp++;
276     }
277     param->filename[i++] = '\0';
278     snd_mbx(MBX_DISPLAY, vp);
279 }
280
281 void disp_audio_levelmeter(const int left, const int right)
282 {
283     VP vp;
284     get_mpf(MPF_DISPLAY, &vp);
285     ((display_msg_t*)vp)->cmd = DISPLAY_CMD_AUDIO_LEVELMETER;
286     display_audio_levelmeter_t *param =
287         (display_audio_levelmeter_t *)&(((display_msg_t*)vp)->param);
288     param->left = left;
289     param->right = right;
290     snd_mbx(MBX_DISPLAY, vp);
291 }
292
293 void cmd_clear(display_clear_t *p)
294 {
295     Color c;
296     c.r = p->r;
297     c.g = p->g;
298     c.b = p->b;
299
300     oled_fill_box(0, 0, OLED_X - 1, OLED_Y - 1, c, c);
301 }
302
303 void cmd_line(display_line_t *p)
304 {
305     Color c;
306     c.r = p->r;
307     c.g = p->g;
308     c.b = p->b;
309
310     oled_draw_line(p->x1, p->y1, p->x2, p->y2, c);
311 }
312
313 void cmd_box(display_box_t *p)
314 {
315     Color c;
316     c.r = p->r;
317     c.g = p->g;
318     c.b = p->b;
319
320     oled_draw_line(p->x1, p->y1, p->x2, p->y1, c);
321     oled_draw_line(p->x2, p->y1, p->x2, p->y2, c);
322     oled_draw_line(p->x2, p->y2, p->x1, p->y2, c);
323     oled_draw_line(p->x1, p->y2, p->x1, p->y1, c);
324 }
325
326 void cmd_fillbox(display_fillbox_t *p)
327 {
328     Color c1, c2;
329     c1.r = p->r1;
330     c1.g = p->g1;
331     c1.b = p->b1;
332     c2.r = p->r2;
333     c2.g = p->g2;
334     c2.b = p->b2;
335
336     oled_fill_box(p->x1, p->y1, p->x2, p->y2, c1, c2);
337 }
338
339 void draw_char(uint8_t x, uint8_t y, char c, Color *col) {
340     int i, j;
341     if ((FONT_MIN_CODE <= c) &&(c <= FONT_MAX_CODE)) {
342         int aofs = (c - FONT_MIN_CODE) * FONT_X;
343         for (i = 0; i < FONT_X; i++) {
344             uint8_t pat = font5x7_data[aofs + i];
345             for (j = 0; j < FONT_Y; j++) {
346                 if (pat & (1 << j)) {
347                     oled_draw_pixel(x + i, y + j, *col);
348                 }
349             }
350         }
351     } else {
352         for (i = 0; i < FONT_X; i++) {
353             uint8_t pat = (i % 2) ? 0x55 : 0xAA;
354             for (j = 0; j < FONT_Y; j++) {
355                 if (pat & (1 << j)) {
356                     oled_draw_pixel(x + i, y + j, *col);
357                 }
358             }
359         }
360     }
361 }
362
363 void cmd_text(display_text_t *p)
364 {
365     Color col;
366     col.r = p->r;
367     col.g = p->g;
368     col.b = p->b;
369
370     char *strp = p->text;
371     int cnt = 0;
372     while (*strp) {
373         draw_char(p->x + (FONT_X * cnt), p->y, *strp, &col);
374         strp++;
375         cnt++;
376     }
377 }
378
379 int ff_getc(void)
380 {
381     uint8_t c;
382     UINT n;
383     FRESULT fr = f_read(&work.fil, &c, 1, &n);
384     return ((fr == FR_OK) ? c : -1);
385 }
386
387 void dispfunc(int x, int y, int r, int g, int b)
388 {
389     Color c;
390     if ((0 <= x) && (0 <= y) && (x < OLED_X) && (y < OLED_Y)) {
391         c.r = r;
392         c.g = g;
393         c.b = b;
394         oled_draw_pixel(x, y, c);
395     }
396 }
397
398 void cmd_bmpfile(display_bmpfile_t *p)
399 {
400     bmp_file_t bmpfile;
401     bmp_info_t bmpinfo;
402     bmp_rgbquad_t bmprgbquad;
403
404     int a = f_mount(0, &work.fatfs[0]);
405     int b = f_opendir(&work.dir, "");
406     if ((a == 0) && (b == 0)) {
407         FRESULT res = f_open(
408                 &work.fil, p->filename, FA_OPEN_EXISTING|FA_READ);
409         if (res == FR_OK) {
410             bmplowio_header_read(ff_getc, &bmpfile, &bmpinfo);
411             if (have_palette(&bmpinfo)) {
412                 bmplowio_palette_read(
413                         ff_getc,
414                         &bmprgbquad,
415                         (1 << bmpinfo.biBitCount));
416             }
417             bmplowio_image_read(
418                     ff_getc,
419                     &bmpfile,
420                     &bmpinfo,
421                     dispfunc);
422         } else {
423             syslog(LOG_NOTICE, "file open failed.(%d)", res);
424         }
425     } else {
426         syslog(LOG_NOTICE, "mount failed.");
427     }
428 }
429
430 void cmd_audio_levelmeter(display_audio_levelmeter_t *p)
431 {
432     Color c1, c2;
433     c1.r = 0xFF;
434     c1.g = 0xFF;
435     c1.b = 0xFF;
436     c2.r = 0x00;
437     c2.g = 0x00;
438     c2.b = 0x00;
439
440     static const int LVW = OLED_X;
441     static const int LVH = 2;
442     static const int LVOFSX = 0;
443     static const int LVOFSY = 10;
444
445     unsigned int PL = ((((uint32_t)p->left ) ^ 0x80000000) >> 24) - 128;
446     unsigned int PR = ((((uint32_t)p->right) ^ 0x80000000) >> 24) - 128;
447     PL = PL / 5;
448     PR = PR / 5;
449     if (PL < 0) { PL = 0; }
450     if (PR < 0) { PR = 0; }
451     if (LVW <= PL) { PL = LVW - 1; }
452     if (LVW <= PR) { PR = LVW - 1; }
453
454     /*
455      * Left side.
456      */
457     oled_fill_box(
458             LVOFSX + 0, LVOFSY + 0,
459             LVOFSX + PL - 1, LVOFSY + LVH - 1,
460             c1, c1);
461     oled_fill_box(
462             LVOFSX + PL, LVOFSY + 0,
463             LVOFSX + OLED_X - 1, LVOFSY + LVH - 1,
464             c2, c2);
465
466     /*
467      * Right side.
468      */
469     oled_fill_box(
470             LVOFSX + 0, LVOFSY + LVH,
471             LVOFSX + PR - 1, LVOFSY + LVH + LVH - 1,
472             c1, c1);
473     oled_fill_box(
474             LVOFSX + PR, LVOFSY + LVH,
475             LVOFSX + OLED_X - 1, LVOFSY + LVH + LVH - 1,
476             c2, c2);
477 }
478
479 void task_display(intptr_t exinf)
480 {
481     display_msg_t *p;
482
483     /*
484      * OLEDを初期化する。
485      */
486     oled_init();
487     oled_clear(0, 0, OLED_X - 1, OLED_Y - 1);
488
489     while(1)
490     {
491         /*
492          * メールボックスの受信を待つ。
493          * 待つまでタスクは受信待ちとなる。
494          */
495         if (rcv_mbx(MBX_DISPLAY, (T_MSG**)&p) == E_OK) {
496             /*
497              * コマンドによってパラメータの型が決まる。
498              * コマンドによって処理関数が決まる。
499              */
500             uint8_t cmd = ((display_msg_t*)p)->cmd;
501             void* param = ((display_msg_t*)p)->param;
502             switch (cmd) {
503                 case DISPLAY_CMD_CLEAR:
504                     cmd_clear((display_clear_t *)param);
505                     break;
506                 case DISPLAY_CMD_LINE:
507                     cmd_line((display_line_t *)param);
508                     break;
509                 case DISPLAY_CMD_BOX:
510                     cmd_box((display_box_t *)param);
511                     break;
512                 case DISPLAY_CMD_FILLBOX:
513                     cmd_fillbox((display_fillbox_t *)param);
514                     break;
515                 case DISPLAY_CMD_TEXT:
516                     cmd_text((display_text_t *)param);
517                     break;
518                 case DISPLAY_CMD_BMPFILE:
519                     cmd_bmpfile((display_bmpfile_t *)param);
520                     break;
521                 case DISPLAY_CMD_AUDIO_LEVELMETER:
522                     cmd_audio_levelmeter((display_audio_levelmeter_t *)param);
523                     break;
524                 default:
525                     syslog(LOG_NOTICE, "Unknown command number %d.", cmd);
526                     break;
527             }
528             rel_mpf(MPF_DISPLAY, (VP)p);
529         }
530     }
531 }
532