Allow TABS in config
[clinton/Smoothieware.git] / src / modules / utils / panel / panels / rrdglcd / RrdGlcd.cpp
1 #include "RrdGlcd.h"
2
3 #include "platform_memory.h"
4 #include "StreamOutputPool.h"
5
6 static const uint8_t font5x8[] = {
7 // 5x8 font each byte is consecutive x bits left aligned then each subsequent byte is Y 8 bytes per character
8 // TODO probably only need someof these characters not all 256
9 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x70,0xF8,0xA8,0xF8,0xD8,0x88,0x70,0x00, // 0x00, 0x01
10 0x70,0xF8,0xA8,0xF8,0x88,0xD8,0x70,0x00, 0x00,0x50,0xF8,0xF8,0xF8,0x70,0x20,0x00, // 0x02, 0x03
11 0x00,0x20,0x70,0xF8,0xF8,0x70,0x20,0x00, 0x70,0x50,0xF8,0xA8,0xF8,0x20,0x70,0x00, // 0x04, 0x05
12 0x20,0x70,0xF8,0xF8,0xF8,0x20,0x70,0x00, 0x00,0x00,0x20,0x70,0x70,0x20,0x00,0x00, // 0x06, 0x07
13 0xF8,0xF8,0xD8,0x88,0x88,0xD8,0xF8,0xF8, 0x00,0x00,0x20,0x50,0x50,0x20,0x00,0x00, // 0x08, 0x09
14 0xF8,0xF8,0xD8,0xA8,0xA8,0xD8,0xF8,0xF8, 0x00,0x38,0x18,0x68,0xA0,0xA0,0x40,0x00, // 0x0A, 0x0B
15 0x70,0x88,0x88,0x70,0x20,0xF8,0x20,0x00, 0x78,0x48,0x78,0x40,0x40,0x40,0xC0,0x00, // 0x0C, 0x0D
16 0x78,0x48,0x78,0x48,0x48,0x58,0xC0,0x00, 0x20,0xA8,0x70,0xD8,0xD8,0x70,0xA8,0x20, // 0x0E, 0x0F
17 0x80,0xC0,0xF0,0xF8,0xF0,0xC0,0x80,0x00, 0x08,0x18,0x78,0xF8,0x78,0x18,0x08,0x00, // 0x10, 0x11
18 0x20,0x70,0xA8,0x20,0xA8,0x70,0x20,0x00, 0xD8,0xD8,0xD8,0xD8,0xD8,0x00,0xD8,0x00, // 0x12, 0x13
19 0x78,0xA8,0xA8,0x68,0x28,0x28,0x28,0x00, 0x30,0x48,0x50,0x28,0x10,0x48,0x48,0x30, // 0x14, 0x15
20 0x00,0x00,0x00,0x00,0x00,0xF8,0xF8,0x00, 0x20,0x70,0xA8,0x20,0xA8,0x70,0x20,0xF8, // 0x16, 0x17
21 0x00,0x20,0x70,0xA8,0x20,0x20,0x20,0x00, 0x00,0x20,0x20,0x20,0xA8,0x70,0x20,0x00, // 0x18, 0x19
22 0x00,0x20,0x10,0xF8,0x10,0x20,0x00,0x00, 0x00,0x20,0x40,0xF8,0x40,0x20,0x00,0x00, // 0x1A, 0x1B
23 0x00,0x80,0x80,0x80,0xF8,0x00,0x00,0x00, 0x00,0x50,0xF8,0xF8,0x50,0x00,0x00,0x00, // 0x1C, 0x1D
24 0x00,0x20,0x20,0x70,0xF8,0xF8,0x00,0x00, 0x00,0xF8,0xF8,0x70,0x20,0x20,0x00,0x00, // 0x1E, 0x1F
25 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00, // 0x20, 0x21
26 0x50,0x50,0x50,0x00,0x00,0x00,0x00,0x00, 0x50,0x50,0xF8,0x50,0xF8,0x50,0x50,0x00, // 0x22, 0x23
27 0x20,0x78,0xA0,0x70,0x28,0xF0,0x20,0x00, 0xC0,0xC8,0x10,0x20,0x40,0x98,0x18,0x00, // 0x24, 0x25
28 0x40,0xA0,0xA0,0x40,0xA8,0x90,0x68,0x00, 0x30,0x30,0x20,0x40,0x00,0x00,0x00,0x00, // 0x26, 0x27
29 0x10,0x20,0x40,0x40,0x40,0x20,0x10,0x00, 0x40,0x20,0x10,0x10,0x10,0x20,0x40,0x00, // 0x28, 0x29
30 0x20,0xA8,0x70,0xF8,0x70,0xA8,0x20,0x00, 0x00,0x20,0x20,0xF8,0x20,0x20,0x00,0x00, // 0x2A, 0x2B
31 0x00,0x00,0x00,0x00,0x30,0x30,0x20,0x40, 0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00, // 0x2C, 0x2D
32 0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00, 0x00,0x08,0x10,0x20,0x40,0x80,0x00,0x00, // 0x2E, 0x2F
33 0x70,0x88,0x98,0xA8,0xC8,0x88,0x70,0x00, 0x20,0x60,0x20,0x20,0x20,0x20,0x70,0x00, // 0x30, 0x31
34 0x70,0x88,0x08,0x70,0x80,0x80,0xF8,0x00, 0xF8,0x08,0x10,0x30,0x08,0x88,0x70,0x00, // 0x32, 0x33
35 0x10,0x30,0x50,0x90,0xF8,0x10,0x10,0x00, 0xF8,0x80,0xF0,0x08,0x08,0x88,0x70,0x00, // 0x34, 0x35
36 0x38,0x40,0x80,0xF0,0x88,0x88,0x70,0x00, 0xF8,0x08,0x08,0x10,0x20,0x40,0x80,0x00, // 0x36, 0x37
37 0x70,0x88,0x88,0x70,0x88,0x88,0x70,0x00, 0x70,0x88,0x88,0x78,0x08,0x10,0xE0,0x00, // 0x38, 0x39
38 0x00,0x00,0x20,0x00,0x20,0x00,0x00,0x00, 0x00,0x00,0x20,0x00,0x20,0x20,0x40,0x00, // 0x3A, 0x3B
39 0x08,0x10,0x20,0x40,0x20,0x10,0x08,0x00, 0x00,0x00,0xF8,0x00,0xF8,0x00,0x00,0x00, // 0x3C, 0x3D
40 0x40,0x20,0x10,0x08,0x10,0x20,0x40,0x00, 0x70,0x88,0x08,0x30,0x20,0x00,0x20,0x00, // 0x3E, 0x3F
41 0x70,0x88,0xA8,0xB8,0xB0,0x80,0x78,0x00, 0x20,0x50,0x88,0x88,0xF8,0x88,0x88,0x00, // 0x40, 0x41
42 0xF0,0x88,0x88,0xF0,0x88,0x88,0xF0,0x00, 0x70,0x88,0x80,0x80,0x80,0x88,0x70,0x00, // 0x42, 0x43
43 0xF0,0x88,0x88,0x88,0x88,0x88,0xF0,0x00, 0xF8,0x80,0x80,0xF0,0x80,0x80,0xF8,0x00, // 0x44, 0x45
44 0xF8,0x80,0x80,0xF0,0x80,0x80,0x80,0x00, 0x78,0x88,0x80,0x80,0x98,0x88,0x78,0x00, // 0x46, 0x47
45 0x88,0x88,0x88,0xF8,0x88,0x88,0x88,0x00, 0x70,0x20,0x20,0x20,0x20,0x20,0x70,0x00, // 0x48, 0x49
46 0x38,0x10,0x10,0x10,0x10,0x90,0x60,0x00, 0x88,0x90,0xA0,0xC0,0xA0,0x90,0x88,0x00, // 0x4A, 0x4B
47 0x80,0x80,0x80,0x80,0x80,0x80,0xF8,0x00, 0x88,0xD8,0xA8,0xA8,0xA8,0x88,0x88,0x00, // 0x4C, 0x4D
48 0x88,0x88,0xC8,0xA8,0x98,0x88,0x88,0x00, 0x70,0x88,0x88,0x88,0x88,0x88,0x70,0x00, // 0x4E, 0x4F
49 0xF0,0x88,0x88,0xF0,0x80,0x80,0x80,0x00, 0x70,0x88,0x88,0x88,0xA8,0x90,0x68,0x00, // 0x50, 0x51
50 0xF0,0x88,0x88,0xF0,0xA0,0x90,0x88,0x00, 0x70,0x88,0x80,0x70,0x08,0x88,0x70,0x00, // 0x52, 0x53
51 0xF8,0xA8,0x20,0x20,0x20,0x20,0x20,0x00, 0x88,0x88,0x88,0x88,0x88,0x88,0x70,0x00, // 0x54, 0x55
52 0x88,0x88,0x88,0x88,0x88,0x50,0x20,0x00, 0x88,0x88,0x88,0xA8,0xA8,0xA8,0x50,0x00, // 0x56, 0x57
53 0x88,0x88,0x50,0x20,0x50,0x88,0x88,0x00, 0x88,0x88,0x50,0x20,0x20,0x20,0x20,0x00, // 0x58, 0x59
54 0xF8,0x08,0x10,0x70,0x40,0x80,0xF8,0x00, 0x78,0x40,0x40,0x40,0x40,0x40,0x78,0x00, // 0x5A, 0x5B
55 0x00,0x80,0x40,0x20,0x10,0x08,0x00,0x00, 0x78,0x08,0x08,0x08,0x08,0x08,0x78,0x00, // 0x5C, 0x5D
56 0x20,0x50,0x88,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x00, // 0x5E, 0x5F
57 0x60,0x60,0x20,0x10,0x00,0x00,0x00,0x00, 0x00,0x00,0x60,0x10,0x70,0x90,0x78,0x00, // 0x60, 0x61
58 0x80,0x80,0xB0,0xC8,0x88,0xC8,0xB0,0x00, 0x00,0x00,0x70,0x88,0x80,0x88,0x70,0x00, // 0x62, 0x63
59 0x08,0x08,0x68,0x98,0x88,0x98,0x68,0x00, 0x00,0x00,0x70,0x88,0xF8,0x80,0x70,0x00, // 0x64, 0x65
60 0x10,0x28,0x20,0x70,0x20,0x20,0x20,0x00, 0x00,0x00,0x70,0x98,0x98,0x68,0x08,0x70, // 0x66, 0x67
61 0x80,0x80,0xB0,0xC8,0x88,0x88,0x88,0x00, 0x20,0x00,0x60,0x20,0x20,0x20,0x70,0x00, // 0x68, 0x69
62 0x10,0x00,0x10,0x10,0x10,0x90,0x60,0x00, 0x80,0x80,0x90,0xA0,0xC0,0xA0,0x90,0x00, // 0x6A, 0x6B
63 0x60,0x20,0x20,0x20,0x20,0x20,0x70,0x00, 0x00,0x00,0xD0,0xA8,0xA8,0xA8,0xA8,0x00, // 0x6C, 0x6D
64 0x00,0x00,0xB0,0xC8,0x88,0x88,0x88,0x00, 0x00,0x00,0x70,0x88,0x88,0x88,0x70,0x00, // 0x6E, 0x6F
65 0x00,0x00,0xB0,0xC8,0xC8,0xB0,0x80,0x80, 0x00,0x00,0x68,0x98,0x98,0x68,0x08,0x08, // 0x70, 0x71
66 0x00,0x00,0xB0,0xC8,0x80,0x80,0x80,0x00, 0x00,0x00,0x78,0x80,0x70,0x08,0xF0,0x00, // 0x72, 0x73
67 0x20,0x20,0xF8,0x20,0x20,0x28,0x10,0x00, 0x00,0x00,0x88,0x88,0x88,0x98,0x68,0x00, // 0x74, 0x75
68 0x00,0x00,0x88,0x88,0x88,0x50,0x20,0x00, 0x00,0x00,0x88,0x88,0xA8,0xA8,0x50,0x00, // 0x76, 0x77
69 0x00,0x00,0x88,0x50,0x20,0x50,0x88,0x00, 0x00,0x00,0x88,0x88,0x78,0x08,0x88,0x70, // 0x78, 0x79
70 0x00,0x00,0xF8,0x10,0x20,0x40,0xF8,0x00, 0x10,0x20,0x20,0x40,0x20,0x20,0x10,0x00, // 0x7A, 0x7B
71 0x20,0x20,0x20,0x00,0x20,0x20,0x20,0x00, 0x40,0x20,0x20,0x10,0x20,0x20,0x40,0x00, // 0x7C, 0x7D
72 0x80,0xC0,0xF0,0xF8,0xF0,0xC0,0x80,0x00, 0x20,0x70,0xD8,0x88,0x88,0xF8,0x00,0x00, // 0x7E, 0x7F // 7e ~ = 0x40,0xA8,0x10,0x00,0x00,0x00,0x00,0x00
73 0x70,0x88,0x80,0x80,0x88,0x70,0x10,0x60, 0x00,0x88,0x00,0x88,0x88,0x98,0x68,0x00, // 0x80, 0x81
74 0x18,0x00,0x70,0x88,0xF8,0x80,0x78,0x00, 0xF8,0x00,0x60,0x10,0x70,0x90,0x78,0x00, // 0x82, 0x83
75 0x88,0x00,0x60,0x10,0x70,0x90,0x78,0x00, 0xC0,0x00,0x60,0x10,0x70,0x90,0x78,0x00, // 0x84, 0x85
76 0x30,0x00,0x60,0x10,0x70,0x90,0x78,0x00, 0x00,0x78,0xC0,0xC0,0x78,0x10,0x30,0x00, // 0x86, 0x87
77 0xF8,0x00,0x70,0x88,0xF8,0x80,0x78,0x00, 0x88,0x00,0x70,0x88,0xF8,0x80,0x78,0x00, // 0x88, 0x89
78 0xC0,0x00,0x70,0x88,0xF8,0x80,0x78,0x00, 0x28,0x00,0x30,0x10,0x10,0x10,0x38,0x00, // 0x8A, 0x8B
79 0x30,0x48,0x30,0x10,0x10,0x10,0x38,0x00, 0x60,0x00,0x30,0x10,0x10,0x10,0x38,0x00, // 0x8C, 0x8D
80 0x50,0x00,0x20,0x50,0x88,0xF8,0x88,0x88, 0x20,0x00,0x20,0x50,0x88,0xF8,0x88,0x88, // 0x8E, 0x8F
81 0x30,0x00,0xF0,0x80,0xE0,0x80,0xF0,0x00, 0x00,0x00,0x78,0x10,0x78,0x90,0x78,0x00, // 0x90, 0x91
82 0x38,0x50,0x90,0xF8,0x90,0x90,0x98,0x00, 0x70,0x88,0x00,0x70,0x88,0x88,0x70,0x00, // 0x92, 0x93
83 0x00,0x88,0x00,0x70,0x88,0x88,0x70,0x00, 0x00,0xC0,0x00,0x70,0x88,0x88,0x70,0x00, // 0x94, 0x95
84 0x70,0x88,0x00,0x88,0x88,0x98,0x68,0x00, 0x00,0xC0,0x00,0x88,0x88,0x98,0x68,0x00, // 0x96, 0x97
85 0x48,0x00,0x48,0x48,0x48,0x38,0x08,0x70, 0x88,0x00,0x70,0x88,0x88,0x88,0x70,0x00, // 0x98, 0x99
86 0x88,0x00,0x88,0x88,0x88,0x88,0x70,0x00, 0x20,0x20,0xF8,0xA0,0xA0,0xF8,0x20,0x20, // 0x9A, 0x9B
87 0x30,0x58,0x48,0xE0,0x40,0x48,0xF8,0x00, 0xD8,0xD8,0x70,0xF8,0x20,0xF8,0x20,0x20, // 0x9C, 0x9D
88 0xE0,0x90,0x90,0xE0,0x90,0xB8,0x90,0x90, 0x18,0x28,0x20,0x70,0x20,0x20,0xA0,0xC0, // 0x9E, 0x9F
89 0x18,0x00,0x60,0x10,0x70,0x90,0x78,0x00, 0x18,0x00,0x30,0x10,0x10,0x10,0x38,0x00, // 0xA0, 0xA1
90 0x00,0x18,0x00,0x70,0x88,0x88,0x70,0x00, 0x00,0x18,0x00,0x88,0x88,0x98,0x68,0x00, // 0xA2, 0xA3
91 0x00,0x78,0x00,0x70,0x48,0x48,0x48,0x00, 0xF8,0x00,0xC8,0xE8,0xB8,0x98,0x88,0x00, // 0xA4, 0xA5
92 0x70,0x90,0x90,0x78,0x00,0xF8,0x00,0x00, 0x70,0x88,0x88,0x70,0x00,0xF8,0x00,0x00, // 0xA6, 0xA7
93 0x20,0x00,0x20,0x60,0x80,0x88,0x70,0x00, 0x00,0x00,0x00,0xF8,0x80,0x80,0x00,0x00, // 0xA8, 0xA9
94 0x00,0x00,0x00,0xF8,0x08,0x08,0x00,0x00, 0x80,0x88,0x90,0xB8,0x48,0x98,0x20,0x38, // 0xAA, 0xAB
95 0x80,0x88,0x90,0xA8,0x58,0xB8,0x08,0x08, 0x20,0x20,0x00,0x20,0x20,0x20,0x20,0x00, // 0xAC, 0xAD
96 0x00,0x28,0x50,0xA0,0x50,0x28,0x00,0x00, 0x00,0xA0,0x50,0x28,0x50,0xA0,0x00,0x00, // 0xAE, 0xAF
97 0x20,0x88,0x20,0x88,0x20,0x88,0x20,0x88, 0x50,0xA8,0x50,0xA8,0x50,0xA8,0x50,0xA8, // 0xB0, 0xB1
98 0xA8,0x50,0xA8,0x50,0xA8,0x50,0xA8,0x50, 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, // 0xB2, 0xB3
99 0x10,0x10,0x10,0x10,0xF0,0x10,0x10,0x10, 0x10,0x10,0xF0,0x10,0xF0,0x10,0x10,0x10, // 0xB4, 0xB5
100 0x28,0x28,0x28,0x28,0xE8,0x28,0x28,0x28, 0x00,0x00,0x00,0x00,0xF8,0x28,0x28,0x28, // 0xB6, 0xB7
101 0x00,0x00,0xF0,0x10,0xF0,0x10,0x10,0x10, 0x28,0x28,0xE8,0x08,0xE8,0x28,0x28,0x28, // 0xB8, 0xB9
102 0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x28, 0x00,0x00,0xF8,0x08,0xE8,0x28,0x28,0x28, // 0xBA, 0xBB
103 0x28,0x28,0xE8,0x08,0xF8,0x00,0x00,0x00, 0x28,0x28,0x28,0x28,0xF8,0x00,0x00,0x00, // 0xBC, 0xBD
104 0x10,0x10,0xF0,0x10,0xF0,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0xF0,0x10,0x10,0x10, // 0xBE, 0xBF
105 0x10,0x10,0x10,0x10,0x18,0x00,0x00,0x00, 0x10,0x10,0x10,0x10,0xF8,0x00,0x00,0x00, // 0xC0, 0xC1
106 0x00,0x00,0x00,0x00,0xF8,0x10,0x10,0x10, 0x10,0x10,0x10,0x10,0x18,0x10,0x10,0x10, // 0xC2, 0xC3
107 0x00,0x00,0x00,0x00,0xF8,0x00,0x00,0x00, 0x10,0x10,0x10,0x10,0xF8,0x10,0x10,0x10, // 0xC4, 0xC5
108 0x10,0x10,0x18,0x10,0x18,0x10,0x10,0x10, 0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x28, // 0xC6, 0xC7
109 0x28,0x28,0x28,0x20,0x38,0x00,0x00,0x00, 0x00,0x00,0x38,0x20,0x28,0x28,0x28,0x28, // 0xC8, 0xC9
110 0x28,0x28,0xE8,0x00,0xF8,0x00,0x00,0x00, 0x00,0x00,0xF8,0x00,0xE8,0x28,0x28,0x28, // 0xCA, 0xCB
111 0x28,0x28,0x28,0x20,0x28,0x28,0x28,0x28, 0x00,0x00,0xF8,0x00,0xF8,0x00,0x00,0x00, // 0xCC, 0xCD
112 0x28,0x28,0xE8,0x00,0xE8,0x28,0x28,0x28, 0x10,0x10,0xF8,0x00,0xF8,0x00,0x00,0x00, // 0xCE, 0xCF
113 0x28,0x28,0x28,0x28,0xF8,0x00,0x00,0x00, 0x00,0x00,0xF8,0x00,0xF8,0x10,0x10,0x10, // 0xD0, 0xD1
114 0x00,0x00,0x00,0x00,0xF8,0x28,0x28,0x28, 0x28,0x28,0x28,0x28,0x38,0x00,0x00,0x00, // 0xD2, 0xD3
115 0x10,0x10,0x18,0x10,0x18,0x00,0x00,0x00, 0x00,0x00,0x18,0x10,0x18,0x10,0x10,0x10, // 0xD4, 0xD5
116 0x00,0x00,0x00,0x00,0x38,0x28,0x28,0x28, 0x28,0x28,0x28,0x28,0xF8,0x28,0x28,0x28, // 0xD6, 0xD7
117 0x10,0x10,0xF8,0x10,0xF8,0x10,0x10,0x10, 0x10,0x10,0x10,0x10,0xF0,0x00,0x00,0x00, // 0xD8, 0xD9
118 0x00,0x00,0x00,0x00,0x18,0x10,0x10,0x10, 0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8, // 0xDA, 0xDB
119 0x00,0x00,0x00,0x00,0xF8,0xF8,0xF8,0xF8, 0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0, // 0xDC, 0xDD
120 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, 0xF8,0xF8,0xF8,0xF8,0x00,0x00,0x00,0x00, // 0xDE, 0xDF
121 0x00,0x00,0x68,0x90,0x90,0x90,0x68,0x00, 0x00,0x70,0x98,0xF0,0x98,0xF0,0x80,0x00, // 0xE0, 0xE1
122 0x00,0xF8,0x98,0x80,0x80,0x80,0x80,0x00, 0x00,0xF8,0x50,0x50,0x50,0x50,0x50,0x00, // 0xE2, 0xE3
123 0xF8,0x88,0x40,0x20,0x40,0x88,0xF8,0x00, 0x00,0x00,0x78,0x90,0x90,0x90,0x60,0x00, // 0xE4, 0xE5
124 0x00,0x50,0x50,0x50,0x50,0x68,0xC0,0x00, 0x00,0xF8,0xA0,0x20,0x20,0x20,0x20,0x00, // 0xE6, 0xE7
125 0xF8,0x20,0x70,0x88,0x88,0x70,0x20,0xF8, 0x20,0x50,0x88,0xF8,0x88,0x50,0x20,0x00, // 0xE8, 0xE9
126 0x20,0x50,0x88,0x88,0x50,0x50,0xD8,0x00, 0x30,0x40,0x30,0x70,0x88,0x88,0x70,0x00, // 0xEA, 0xEB
127 0x00,0x00,0x00,0x70,0xA8,0xA8,0x70,0x00, 0x08,0x70,0x98,0xA8,0xA8,0xC8,0x70,0x80, // 0xEC, 0xED
128 0x70,0x80,0x80,0xF0,0x80,0x80,0x70,0x00, 0x70,0x88,0x88,0x88,0x88,0x88,0x88,0x00, // 0xEE, 0xEF
129 0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00,0x00, 0x20,0x20,0xF8,0x20,0x20,0x00,0xF8,0x00, // 0xF0, 0xF1
130 0x40,0x20,0x10,0x20,0x40,0x00,0xF8,0x00, 0x10,0x20,0x40,0x20,0x10,0x00,0xF8,0x00, // 0xF2, 0xF3
131 0x38,0x28,0x20,0x20,0x20,0x20,0x20,0x20, 0x20,0x20,0x20,0x20,0x20,0xA0,0xA0,0xE0, // 0xF4, 0xF5
132 0x30,0x30,0x00,0xF8,0x00,0x30,0x30,0x00, 0x00,0xE8,0xB8,0x00,0xE8,0xB8,0x00,0x00, // 0xF6, 0xF7
133 0x70,0xD8,0xD8,0x70,0x00,0x00,0x00,0x00, 0x50,0x20,0x00,0x00,0x00,0x00,0x08,0x00, // 0xF8, 0xF9
134 0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x00, 0x38,0x20,0x20,0x20,0xA0,0xA0,0x60,0x20, // 0xFA, 0xFB
135 0x70,0x48,0x48,0x48,0x48,0x00,0x00,0x00, 0x70,0x18,0x30,0x60,0x78,0x00,0x00,0x00, // 0xFC, 0xFD
136 0x00,0x00,0x78,0x78,0x78,0x78,0x00,0x00
137 };
138
139 #define ST7920_CS() {cs.set(1);wait_us(10);}
140 #define ST7920_NCS() {cs.set(0);wait_us(10);}
141 #define ST7920_WRITE_BYTE(a) {this->spi->write((a)&0xf0);this->spi->write((a)<<4);wait_us(10);}
142 #define ST7920_WRITE_BYTES(p,l) {uint8_t i;for(i=0;i<l;i++){this->spi->write(*p&0xf0);this->spi->write(*p<<4);p++;} wait_us(10); }
143 #define ST7920_SET_CMD() {this->spi->write(0xf8);wait_us(10);}
144 #define ST7920_SET_DAT() {this->spi->write(0xfa);wait_us(10);}
145 #define PAGE_HEIGHT 32 //512 byte framebuffer
146 #define WIDTH 128
147 #define HEIGHT 64
148 #define FB_SIZE WIDTH*HEIGHT/8
149
150 RrdGlcd::RrdGlcd(PinName mosi, PinName sclk, Pin cs) {
151 this->spi= new mbed::SPI(mosi, NC, sclk);
152 //chip select
153 this->cs= cs;
154 this->cs.set(0);
155 fb= (uint8_t *)AHB0.alloc(FB_SIZE); // grab some memoery from USB_RAM
156 if(fb == NULL) {
157 THEKERNEL->streams->printf("Not enough memory available for frame buffer");
158 }
159 inited= false;
160 dirty= false;
161 }
162
163 RrdGlcd::~RrdGlcd() {
164 delete this->spi;
165 AHB0.dealloc(fb);
166 }
167
168 void RrdGlcd::setFrequency(int freq) {
169 this->spi->frequency(freq);
170 }
171
172 void RrdGlcd::initDisplay() {
173 if(fb == NULL) return;
174 ST7920_CS();
175 clearScreen(); // clear framebuffer
176 wait_ms(90); //initial delay for boot up
177 ST7920_SET_CMD();
178 ST7920_WRITE_BYTE(0x08); //display off, cursor+blink off
179 ST7920_WRITE_BYTE(0x01); //clear CGRAM ram
180 wait_ms(10); //delay for cgram clear
181 ST7920_WRITE_BYTE(0x3E); //extended mode + gdram active
182 for(int y=0;y<HEIGHT/2;y++) //clear GDRAM
183 {
184 ST7920_WRITE_BYTE(0x80|y); //set y
185 ST7920_WRITE_BYTE(0x80); //set x = 0
186 ST7920_SET_DAT();
187 for(int i=0;i<2*WIDTH/8;i++) //2x width clears both segments
188 ST7920_WRITE_BYTE(0);
189 ST7920_SET_CMD();
190 }
191 ST7920_WRITE_BYTE(0x0C); //display on, cursor+blink off
192 ST7920_NCS();
193 inited= true;
194 }
195
196 void RrdGlcd::clearScreen() {
197 if(fb == NULL) return;
198 memset(this->fb, 0, FB_SIZE);
199 dirty= true;
200 }
201
202 // render into local screenbuffer
203 void RrdGlcd::displayString(int row, int col, const char *ptr, int length) {
204 for (int i = 0; i < length; ++i) {
205 displayChar(row, col, ptr[i]);
206 col+=1;
207 }
208 dirty= true;
209 }
210
211 void RrdGlcd::renderChar(uint8_t *fb, char c, int ox, int oy) {
212 if(fb == NULL) return;
213 // using the specific font data where x is in one byte and y is in consecutive bytes
214 // the x bits are left aligned and right padded
215 int i= c*8; // character offset in font array
216 int o= ox%8; // where in fb byte does it go
217 int a= oy*16 + ox/8; // start address in frame buffer
218 int mask= ~0xF8 >> o; // mask off top bits
219 int mask2= ~0xF8 << (8-o); // mask off bottom bits
220 for(int y=0;y<8;y++) {
221 int b= font5x8[i+y]; // get font byte
222 fb[a] &= mask; // clear top bits for font
223 fb[a] |= (b>>o); // or in the fonts 1 bits
224 if(o >= 4) { // it spans two fb bytes
225 fb[a+1] &= mask2; // clear bottom bits for font
226 fb[a+1] |= (b<<(8-o)); // or in the fonts 1 bits
227 }
228 a+=16; // next line
229 }
230 }
231
232 void RrdGlcd::displayChar(int row, int col, char c) {
233 int x= col*6;
234 // if this wraps the line ignore it
235 if(x+6 > WIDTH) return;
236
237 // convert row/column into y and x pixel positions based on font size
238 renderChar(this->fb, c, x, row*8);
239 }
240
241 void RrdGlcd::renderGlyph(int xp, int yp, const uint8_t *g, int pixelWidth, int pixelHeight) {
242 if(fb == NULL) return;
243 // NOTE the source is expected to be byte aligned and the exact number of pixels
244 // TODO need to optimize by copying bytes instead of pixels...
245 int xf= xp%8;
246 int rf= pixelWidth%8;
247 int a= yp*16 + xp/8; // start address in frame buffer
248 const uint8_t *src= g;
249 if(xf == 0) {
250 // If xp is on a byte boundary simply memcpy each line from source to dest
251 uint8_t *dest= &fb[a];
252 int n= pixelWidth/8; // bytes per line to copy
253 if(rf != 0) n++; // if not a multiple of 8 pixels copy last byte as a byte
254 if(n > 0) {
255 for(int y=0;y<pixelHeight;y++) {
256 memcpy(dest, src, n);
257 src += n;
258 dest+=16; // next line
259 }
260 }
261
262 // TODO now handle ragged end if we have one but as we always render left to right we probably don't need to
263 // if(rf != 0) {
264
265 // }
266 return;
267 }
268
269 // if xp is not on a byte boundary we do the slow pixel by pixel copy
270 for(int y=0;y<pixelHeight;y++) {
271 int m= 0x80;
272 int b= *g++;
273 for(int x=0;x<pixelWidth;x++) {
274 a= (y+yp)*16 + (x+xp)/8;
275 int p= 1<<(7-(x+xp)%8);
276 if((b & m) != 0){
277 fb[a] |= p;
278 }else{
279 fb[a] &= ~p;
280 }
281 m= m>>1;
282 if(m == 0){
283 m= 0x80;
284 b= *g++;
285 }
286 }
287 }
288 }
289
290 // copy frame buffer to graphic buffer on display
291 void RrdGlcd::fillGDRAM(const uint8_t *bitmap) {
292 unsigned char i, y;
293 for ( i = 0 ; i < 2 ; i++ ) {
294 ST7920_CS();
295 for ( y = 0 ; y < PAGE_HEIGHT ; y++ ) {
296 ST7920_SET_CMD();
297 ST7920_WRITE_BYTE(0x80 | y);
298 if ( i == 0 ) {
299 ST7920_WRITE_BYTE(0x80);
300 } else {
301 ST7920_WRITE_BYTE(0x80 | 0x08);
302 }
303 ST7920_SET_DAT();
304 ST7920_WRITE_BYTES(bitmap, WIDTH/8); // bitmap gets incremented in this macro
305 }
306 ST7920_NCS();
307 }
308 }
309
310 void RrdGlcd::refresh() {
311 if(!inited || !dirty) return;
312 fillGDRAM(this->fb);
313 dirty= false;
314 }