common: Implement screen::clear() and screen::draw_text().
[gps-watch.git] / src / common / screen.rs
1 /*
2  * Copyright (c) 2019 Tilman Sauerbeck (tilman at code-monkey de)
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining
5  * a copy of this software and associated documentation files (the
6  * "Software"), to deal in the Software without restriction, including
7  * without limitation the rights to use, copy, modify, merge, publish,
8  * distribute, sublicense, and/or sell copies of the Software, and to
9  * permit persons to whom the Software is furnished to do so, subject to
10  * the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be
13  * included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22  */
23
24 // Stolen from spleen-8x16.bdf (github.com/fcambus/spleen).
25 // See LICENSE.spleen.
26 const FONT_8X16 : [u8; 1024] = [
27     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
28     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29     0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xce, 0xde, 0xf6,
30     0xe6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
31     0x00, 0x00, 0x18, 0x38, 0x78, 0x58, 0x18, 0x18,
32     0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
33     0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x0c, 0x18,
34     0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00,
35     0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06,
36     0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
37     0x00, 0x00, 0xc0, 0xc0, 0xcc, 0xcc, 0xcc, 0xcc,
38     0xfe, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00,
39     0x00, 0x00, 0xfe, 0xc6, 0xc0, 0xc0, 0xfc, 0x06,
40     0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
41     0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xfc, 0xc6,
42     0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
43     0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18,
44     0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00,
45     0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0xc6,
46     0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
47     0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e,
48     0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
49     0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00,
50     0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
51     0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6,
52     0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
53     0x00, 0x00, 0xfc, 0xc6, 0xc6, 0xc6, 0xfc, 0xc6,
54     0xc6, 0xc6, 0xc6, 0xfc, 0x00, 0x00, 0x00, 0x00,
55     0x00, 0x00, 0x7e, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
56     0xc0, 0xc0, 0xc0, 0x7e, 0x00, 0x00, 0x00, 0x00,
57     0x00, 0x00, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
58     0xc6, 0xc6, 0xc6, 0xfc, 0x00, 0x00, 0x00, 0x00,
59     0x00, 0x00, 0x7e, 0xc0, 0xc0, 0xc0, 0xf8, 0xc0,
60     0xc0, 0xc0, 0xc0, 0x7e, 0x00, 0x00, 0x00, 0x00,
61     0x00, 0x00, 0x7e, 0xc0, 0xc0, 0xc0, 0xf8, 0xc0,
62     0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00,
63     0x00, 0x00, 0x7e, 0xc0, 0xc0, 0xc0, 0xde, 0xc6,
64     0xc6, 0xc6, 0xc6, 0x7e, 0x00, 0x00, 0x00, 0x00,
65     0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6,
66     0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
67     0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18,
68     0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
69     0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18,
70     0x18, 0x18, 0x18, 0xf0, 0x00, 0x00, 0x00, 0x00,
71     0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xcc, 0xf8, 0xcc,
72     0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
73     0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
74     0xc0, 0xc0, 0xc0, 0x7e, 0x00, 0x00, 0x00, 0x00,
75     0x00, 0x00, 0xc6, 0xee, 0xfe, 0xd6, 0xc6, 0xc6,
76     0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
77     0x00, 0x00, 0xc6, 0xc6, 0xe6, 0xe6, 0xd6, 0xd6,
78     0xce, 0xce, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
79     0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
80     0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
81     0x00, 0x00, 0xfc, 0xc6, 0xc6, 0xc6, 0xfc, 0xc0,
82     0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00,
83     0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
84     0xc6, 0xd6, 0xd6, 0x7c, 0x18, 0x0c, 0x00, 0x00,
85     0x00, 0x00, 0xfc, 0xc6, 0xc6, 0xc6, 0xfc, 0xc6,
86     0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
87     0x00, 0x00, 0x7e, 0xc0, 0xc0, 0xc0, 0x7c, 0x06,
88     0x06, 0x06, 0x06, 0xfc, 0x00, 0x00, 0x00, 0x00,
89     0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18,
90     0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
91     0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
92     0xc6, 0xc6, 0xc6, 0x7e, 0x00, 0x00, 0x00, 0x00,
93     0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
94     0xc6, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00,
95     0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
96     0xd6, 0xfe, 0xee, 0xc6, 0x00, 0x00, 0x00, 0x00,
97     0x00, 0x00, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x6c,
98     0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
99     0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06,
100     0x06, 0x06, 0x06, 0xfc, 0x00, 0x00, 0x00, 0x00,
101     0x00, 0x00, 0xfe, 0x06, 0x06, 0x0c, 0x18, 0x30,
102     0x60, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00,
103     0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x06, 0x7e,
104     0xc6, 0xc6, 0xc6, 0x7e, 0x00, 0x00, 0x00, 0x00,
105     0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6,
106     0xc6, 0xc6, 0xc6, 0xfc, 0x00, 0x00, 0x00, 0x00,
107     0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xc0, 0xc0,
108     0xc0, 0xc0, 0xc0, 0x7e, 0x00, 0x00, 0x00, 0x00,
109     0x00, 0x00, 0x06, 0x06, 0x06, 0x7e, 0xc6, 0xc6,
110     0xc6, 0xc6, 0xc6, 0x7e, 0x00, 0x00, 0x00, 0x00,
111     0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xc6, 0xc6,
112     0xfe, 0xc0, 0xc0, 0x7e, 0x00, 0x00, 0x00, 0x00,
113     0x00, 0x00, 0x1e, 0x30, 0x30, 0x30, 0x7c, 0x30,
114     0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00,
115     0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xc6, 0xc6,
116     0xc6, 0xc6, 0xc6, 0x7c, 0x06, 0x06, 0xfc, 0x00,
117     0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6,
118     0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
119     0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18,
120     0x18, 0x18, 0x18, 0x1c, 0x00, 0x00, 0x00, 0x00,
121     0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18,
122     0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00,
123     0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xcc, 0xd8, 0xf0,
124     0xf0, 0xd8, 0xcc, 0xc6, 0x00, 0x00, 0x00, 0x00,
125     0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
126     0x30, 0x30, 0x30, 0x1c, 0x00, 0x00, 0x00, 0x00,
127     0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0xd6, 0xd6,
128     0xd6, 0xd6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
129     0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xc6, 0xc6,
130     0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
131     0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6,
132     0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
133     0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xc6, 0xc6,
134     0xc6, 0xc6, 0xc6, 0xfc, 0xc0, 0xc0, 0xc0, 0x00,
135     0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xc6, 0xc6,
136     0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x00,
137     0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xc6, 0xc0,
138     0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00,
139     0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xc0, 0xc0,
140     0x7c, 0x06, 0x06, 0xfc, 0x00, 0x00, 0x00, 0x00,
141     0x00, 0x00, 0x30, 0x30, 0x30, 0x7c, 0x30, 0x30,
142     0x30, 0x30, 0x30, 0x1e, 0x00, 0x00, 0x00, 0x00,
143     0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6,
144     0xc6, 0xc6, 0xc6, 0x7e, 0x00, 0x00, 0x00, 0x00,
145     0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6,
146     0xc6, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00,
147     0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xd6,
148     0xd6, 0xd6, 0xd6, 0x6e, 0x00, 0x00, 0x00, 0x00,
149     0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x6c, 0x38,
150     0x38, 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
151     0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6,
152     0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0xfc, 0x00,
153     0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0x0c,
154     0x18, 0x30, 0x60, 0xfe, 0x00, 0x00, 0x00, 0x00,
155 ];
156
157 pub const HEIGHT_PX: usize = 70;
158 pub const WIDTH_PX: usize = 70;
159
160 pub const WIDTH_BYTES: usize = (WIDTH_PX as usize + 7) / 8;
161
162 pub const SIZE_BYTES: usize = HEIGHT_PX as usize * WIDTH_BYTES;
163
164 pub struct Screen {
165     // Each byte corresponds to 8 pixels, with the MSB referring
166     // to the left-most pixel.
167     pixels: [u8; SIZE_BYTES],
168 }
169
170 impl Screen {
171     pub fn new() -> Screen {
172         Screen {
173             pixels: [0u8; SIZE_BYTES],
174         }
175     }
176
177     pub fn pixel(&self, index: usize) -> u8 {
178         self.pixels[index]
179     }
180
181     pub fn blit(&mut self, new_contents: [u8; SIZE_BYTES]) {
182         self.pixels = new_contents;
183     }
184
185     pub fn clear(&mut self) {
186         self.pixels = [0u8; SIZE_BYTES];
187     }
188
189     pub fn draw_text(&mut self, text: &[u8]) {
190         let xoff = 0;
191         let yoff = 0;
192
193         let glyph_width_px = 8;
194         let glyph_height_px = 16;
195
196         for (i, &c) in text.iter().enumerate() {
197             let glyph_size_in_bytes = (glyph_width_px * glyph_height_px) / 8;
198
199             let o = match c {
200                 b' '        =>  0,
201                 b'0'..=b'9' =>  1 + (c - b'0'),
202                 b':'        => 11,
203                 b'A'..=b'Z' => 12 + (c - b'A'),
204                 b'a'..=b'z' => 38 + (c - b'a'),
205                 _           =>  0,
206             } as usize * glyph_size_in_bytes;
207
208             for row in 0..glyph_height_px {
209                 self.pixels[(yoff + row) * WIDTH_BYTES + xoff + i] |=
210                     FONT_8X16[o + row];
211             }
212         }
213     }
214 }