rust: Add weather

Add `weather` demo, also extend console as necessary to handle wttr.in's escape codes.
This commit is contained in:
Wladimir J. van der Laan 2019-05-26 15:00:09 +00:00
parent bfe58fe72b
commit 71b427b188
14 changed files with 996 additions and 16 deletions

View File

@ -139,6 +139,21 @@ Control the color of the RGB LED from the touch screen.
[README](rust/rgbcontrol/README.md)
rust/esp8266at
--------------
A crate for communicating with WiFi using the ESP8266 using AT commands. TODO: move this to its own repository.
[README](rust/esp8266at/README.md)
rust/weather
------------
Uses the ESP8285 WiFi chip of the Maix Go to fetch weather data from
[wttr.in](https://wttr.in) and print it to the display using `k210-console`.
[README](rust/weather/README.md)
ROM re'ing
===========

View File

@ -6,6 +6,7 @@ members = [
"accelerometer",
"uart-passthrough",
"rgbcontrol",
"weather",
]
[patch.crates-io]

View File

@ -0,0 +1,3 @@
Based on https://github.com/nabijaczleweli/codepage-437/blob/master/dialect-specs/cp437_wingdings/values.tsv by nabijaczleweli.
- Changed 0xFF to WHITE SQUARE

View File

@ -0,0 +1,161 @@
cp437_wingdings Unicode Comment
0x01 0x263A WHITE SMILING FACE
0x02 0x263B BLACK SMILING FACE
0x03 0x2665 BLACK HEART SUIT
0x04 0x2666 BLACK DIAMOND SUIT
0x05 0x2663 BLACK CLUB SUIT
0x06 0x2660 BLACK SPADE SUIT
0x07 0x2022 BULLET
0x08 0x25D8 INVERSE BULLET
0x09 0x25CB WHITE CIRCLE
0x0A 0x25D9 INVERSE WHITE CIRCLE
0x0B 0x2642 MALE SIGN
0x0C 0x2640 FEMALE SIGN
0x0D 0x266A EIGHTH NOTE
0x0E 0x266B BEAMED EIGHTH NOTES
0x0F 0x263C WHITE SUN WITH RAYS
0x10 0x25BA BLACK RIGHT-POINTING POINTER
0x11 0x25C4 BLACK LEFT-POINTING POINTER
0x12 0x2195 UP DOWN ARROW
0x13 0x203C DOUBLE EXCLAMATION MARK
0x14 0x00B6 PILCROW SIGN
0x15 0x00A7 SECTION SIGN
0x16 0x25AC BLACK RECTANGLE
0x17 0x21A8 UP DOWN ARROW WITH BASE
0x18 0x2191 UPWARDS ARROW
0x19 0x2193 DOWNWARDS ARROW
0x1A 0x2192 RIGHTWARDS ARROW
0x1B 0x2190 LEFTWARDS ARROW
0x1C 0x221F RIGHT ANGLE
0x1D 0x2194 LEFT RIGHT ARROW
0x1E 0x25B2 BLACK UP-POINTING TRIANGLE
0x1F 0x25BC BLACK DOWN-POINTING TRIANGLE
0x7F 0x2302 HOUSE
0x80 0x00C7 LATIN CAPITAL LETTER C WITH CEDILLA
0x81 0x00FC LATIN SMALL LETTER U WITH DIAERESIS
0x82 0x00E9 LATIN SMALL LETTER E WITH ACUTE
0x83 0x00E2 LATIN SMALL LETTER A WITH CIRCUMFLEX
0x84 0x00E4 LATIN SMALL LETTER A WITH DIAERESIS
0x85 0x00E0 LATIN SMALL LETTER A WITH GRAVE
0x86 0x00E5 LATIN SMALL LETTER A WITH RING ABOVE
0x87 0x00E7 LATIN SMALL LETTER C WITH CEDILLA
0x88 0x00EA LATIN SMALL LETTER E WITH CIRCUMFLEX
0x89 0x00EB LATIN SMALL LETTER E WITH DIAERESIS
0x8A 0x00E8 LATIN SMALL LETTER E WITH GRAVE
0x8B 0x00EF LATIN SMALL LETTER I WITH DIAERESIS
0x8C 0x00EE LATIN SMALL LETTER I WITH CIRCUMFLEX
0x8D 0x00EC LATIN SMALL LETTER I WITH GRAVE
0x8E 0x00C4 LATIN CAPITAL LETTER A WITH DIAERESIS
0x8F 0x00C5 LATIN CAPITAL LETTER A WITH RING ABOVE
0x90 0x00C9 LATIN CAPITAL LETTER E WITH ACUTE
0x91 0x00E6 LATIN SMALL LETTER AE
0x92 0x00C6 LATIN CAPITAL LETTER AE
0x93 0x00F4 LATIN SMALL LETTER O WITH CIRCUMFLEX
0x94 0x00F6 LATIN SMALL LETTER O WITH DIAERESIS
0x95 0x00F2 LATIN SMALL LETTER O WITH GRAVE
0x96 0x00FB LATIN SMALL LETTER U WITH CIRCUMFLEX
0x97 0x00F9 LATIN SMALL LETTER U WITH GRAVE
0x98 0x00FF LATIN SMALL LETTER Y WITH DIAERESIS
0x99 0x00D6 LATIN CAPITAL LETTER O WITH DIAERESIS
0x9A 0x00DC LATIN CAPITAL LETTER U WITH DIAERESIS
0x9B 0x00A2 CENT SIGN
0x9C 0x00A3 POUND SIGN
0x9D 0x00A5 YEN SIGN
0x9E 0x20A7 PESETA SIGN
0x9F 0x0192 LATIN SMALL LETTER F WITH HOOK
0xA0 0x00E1 LATIN SMALL LETTER A WITH ACUTE
0xA1 0x00ED LATIN SMALL LETTER I WITH ACUTE
0xA2 0x00F3 LATIN SMALL LETTER O WITH ACUTE
0xA3 0x00FA LATIN SMALL LETTER U WITH ACUTE
0xA4 0x00F1 LATIN SMALL LETTER N WITH TILDE
0xA5 0x00D1 LATIN CAPITAL LETTER N WITH TILDE
0xA6 0x00AA FEMININE ORDINAL INDICATOR
0xA7 0x00BA MASCULINE ORDINAL INDICATOR
0xA8 0x00BF INVERTED QUESTION MARK
0xA9 0x2310 REVERSED NOT SIGN
0xAA 0x00AC NOT SIGN
0xAB 0x00BD VULGAR FRACTION ONE HALF
0xAC 0x00BC VULGAR FRACTION ONE QUARTER
0xAD 0x00A1 INVERTED EXCLAMATION MARK
0xAE 0x00AB LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
0xAF 0x00BB RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
0xB0 0x2591 LIGHT SHADE
0xB1 0x2592 MEDIUM SHADE
0xB2 0x2593 DARK SHADE
0xB3 0x2502 BOX DRAWINGS LIGHT VERTICAL
0xB4 0x2524 BOX DRAWINGS LIGHT VERTICAL AND LEFT
0xB5 0x2561 BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
0xB6 0x2562 BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
0xB7 0x2556 BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
0xB8 0x2555 BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
0xB9 0x2563 BOX DRAWINGS DOUBLE VERTICAL AND LEFT
0xBA 0x2551 BOX DRAWINGS DOUBLE VERTICAL
0xBB 0x2557 BOX DRAWINGS DOUBLE DOWN AND LEFT
0xBC 0x255D BOX DRAWINGS DOUBLE UP AND LEFT
0xBD 0x255C BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
0xBE 0x255B BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
0xBF 0x2510 BOX DRAWINGS LIGHT DOWN AND LEFT
0xC0 0x2514 BOX DRAWINGS LIGHT UP AND RIGHT
0xC1 0x2534 BOX DRAWINGS LIGHT UP AND HORIZONTAL
0xC2 0x252C BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
0xC3 0x251C BOX DRAWINGS LIGHT VERTICAL AND RIGHT
0xC4 0x2500 BOX DRAWINGS LIGHT HORIZONTAL
0xC5 0x253C BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
0xC6 0x255E BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
0xC7 0x255F BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
0xC8 0x255A BOX DRAWINGS DOUBLE UP AND RIGHT
0xC9 0x2554 BOX DRAWINGS DOUBLE DOWN AND RIGHT
0xCA 0x2569 BOX DRAWINGS DOUBLE UP AND HORIZONTAL
0xCB 0x2566 BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
0xCC 0x2560 BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
0xCD 0x2550 BOX DRAWINGS DOUBLE HORIZONTAL
0xCE 0x256C BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
0xCF 0x2567 BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
0xD0 0x2568 BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
0xD1 0x2564 BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
0xD2 0x2565 BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
0xD3 0x2559 BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
0xD4 0x2558 BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
0xD5 0x2552 BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
0xD6 0x2553 BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
0xD7 0x256B BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
0xD8 0x256A BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
0xD9 0x2518 BOX DRAWINGS LIGHT UP AND LEFT
0xDA 0x250C BOX DRAWINGS LIGHT DOWN AND RIGHT
0xDB 0x2588 FULL BLOCK
0xDC 0x2584 LOWER HALF BLOCK
0xDD 0x258C LEFT HALF BLOCK
0xDE 0x2590 RIGHT HALF BLOCK
0xDF 0x2580 UPPER HALF BLOCK
0xE0 0x03B1 GREEK SMALL LETTER ALPHA
0xE1 0x00DF LATIN SMALL LETTER SHARP S
0xE2 0x0393 GREEK CAPITAL LETTER GAMMA
0xE3 0x03C0 GREEK SMALL LETTER PI
0xE4 0x03A3 GREEK CAPITAL LETTER SIGMA
0xE5 0x03C3 GREEK SMALL LETTER SIGMA
0xE6 0x00B5 MICRO SIGN
0xE7 0x03C4 GREEK SMALL LETTER TAU
0xE8 0x03A6 GREEK CAPITAL LETTER PHI
0xE9 0x0398 GREEK CAPITAL LETTER THETA
0xEA 0x03A9 GREEK CAPITAL LETTER OMEGA
0xEB 0x03B4 GREEK SMALL LETTER DELTA
0xEC 0x221E INFINITY
0xED 0x03C6 GREEK SMALL LETTER PHI
0xEE 0x03B5 GREEK SMALL LETTER EPSILON
0xEF 0x2229 INTERSECTION
0xF0 0x2261 IDENTICAL TO
0xF1 0x00B1 PLUS-MINUS SIGN
0xF2 0x2265 GREATER-THAN OR EQUAL TO
0xF3 0x2264 LESS-THAN OR EQUAL TO
0xF4 0x2320 TOP HALF INTEGRAL
0xF5 0x2321 BOTTOM HALF INTEGRAL
0xF6 0x00F7 DIVISION SIGN
0xF7 0x2248 ALMOST EQUAL TO
0xF8 0x00B0 DEGREE SIGN
0xF9 0x2219 BULLET OPERATOR
0xFA 0x00B7 MIDDLE DOT
0xFB 0x221A SQUARE ROOT
0xFC 0x207F SUPERSCRIPT LATIN SMALL LETTER N
0xFD 0x00B2 SUPERSCRIPT TWO
0xFE 0x25A0 BLACK SQUARE
0xFF 0x25A1 WHITE SQUARE
1 cp437_wingdings Unicode Comment
2 0x01 0x263A WHITE SMILING FACE
3 0x02 0x263B BLACK SMILING FACE
4 0x03 0x2665 BLACK HEART SUIT
5 0x04 0x2666 BLACK DIAMOND SUIT
6 0x05 0x2663 BLACK CLUB SUIT
7 0x06 0x2660 BLACK SPADE SUIT
8 0x07 0x2022 BULLET
9 0x08 0x25D8 INVERSE BULLET
10 0x09 0x25CB WHITE CIRCLE
11 0x0A 0x25D9 INVERSE WHITE CIRCLE
12 0x0B 0x2642 MALE SIGN
13 0x0C 0x2640 FEMALE SIGN
14 0x0D 0x266A EIGHTH NOTE
15 0x0E 0x266B BEAMED EIGHTH NOTES
16 0x0F 0x263C WHITE SUN WITH RAYS
17 0x10 0x25BA BLACK RIGHT-POINTING POINTER
18 0x11 0x25C4 BLACK LEFT-POINTING POINTER
19 0x12 0x2195 UP DOWN ARROW
20 0x13 0x203C DOUBLE EXCLAMATION MARK
21 0x14 0x00B6 PILCROW SIGN
22 0x15 0x00A7 SECTION SIGN
23 0x16 0x25AC BLACK RECTANGLE
24 0x17 0x21A8 UP DOWN ARROW WITH BASE
25 0x18 0x2191 UPWARDS ARROW
26 0x19 0x2193 DOWNWARDS ARROW
27 0x1A 0x2192 RIGHTWARDS ARROW
28 0x1B 0x2190 LEFTWARDS ARROW
29 0x1C 0x221F RIGHT ANGLE
30 0x1D 0x2194 LEFT RIGHT ARROW
31 0x1E 0x25B2 BLACK UP-POINTING TRIANGLE
32 0x1F 0x25BC BLACK DOWN-POINTING TRIANGLE
33 0x7F 0x2302 HOUSE
34 0x80 0x00C7 LATIN CAPITAL LETTER C WITH CEDILLA
35 0x81 0x00FC LATIN SMALL LETTER U WITH DIAERESIS
36 0x82 0x00E9 LATIN SMALL LETTER E WITH ACUTE
37 0x83 0x00E2 LATIN SMALL LETTER A WITH CIRCUMFLEX
38 0x84 0x00E4 LATIN SMALL LETTER A WITH DIAERESIS
39 0x85 0x00E0 LATIN SMALL LETTER A WITH GRAVE
40 0x86 0x00E5 LATIN SMALL LETTER A WITH RING ABOVE
41 0x87 0x00E7 LATIN SMALL LETTER C WITH CEDILLA
42 0x88 0x00EA LATIN SMALL LETTER E WITH CIRCUMFLEX
43 0x89 0x00EB LATIN SMALL LETTER E WITH DIAERESIS
44 0x8A 0x00E8 LATIN SMALL LETTER E WITH GRAVE
45 0x8B 0x00EF LATIN SMALL LETTER I WITH DIAERESIS
46 0x8C 0x00EE LATIN SMALL LETTER I WITH CIRCUMFLEX
47 0x8D 0x00EC LATIN SMALL LETTER I WITH GRAVE
48 0x8E 0x00C4 LATIN CAPITAL LETTER A WITH DIAERESIS
49 0x8F 0x00C5 LATIN CAPITAL LETTER A WITH RING ABOVE
50 0x90 0x00C9 LATIN CAPITAL LETTER E WITH ACUTE
51 0x91 0x00E6 LATIN SMALL LETTER AE
52 0x92 0x00C6 LATIN CAPITAL LETTER AE
53 0x93 0x00F4 LATIN SMALL LETTER O WITH CIRCUMFLEX
54 0x94 0x00F6 LATIN SMALL LETTER O WITH DIAERESIS
55 0x95 0x00F2 LATIN SMALL LETTER O WITH GRAVE
56 0x96 0x00FB LATIN SMALL LETTER U WITH CIRCUMFLEX
57 0x97 0x00F9 LATIN SMALL LETTER U WITH GRAVE
58 0x98 0x00FF LATIN SMALL LETTER Y WITH DIAERESIS
59 0x99 0x00D6 LATIN CAPITAL LETTER O WITH DIAERESIS
60 0x9A 0x00DC LATIN CAPITAL LETTER U WITH DIAERESIS
61 0x9B 0x00A2 CENT SIGN
62 0x9C 0x00A3 POUND SIGN
63 0x9D 0x00A5 YEN SIGN
64 0x9E 0x20A7 PESETA SIGN
65 0x9F 0x0192 LATIN SMALL LETTER F WITH HOOK
66 0xA0 0x00E1 LATIN SMALL LETTER A WITH ACUTE
67 0xA1 0x00ED LATIN SMALL LETTER I WITH ACUTE
68 0xA2 0x00F3 LATIN SMALL LETTER O WITH ACUTE
69 0xA3 0x00FA LATIN SMALL LETTER U WITH ACUTE
70 0xA4 0x00F1 LATIN SMALL LETTER N WITH TILDE
71 0xA5 0x00D1 LATIN CAPITAL LETTER N WITH TILDE
72 0xA6 0x00AA FEMININE ORDINAL INDICATOR
73 0xA7 0x00BA MASCULINE ORDINAL INDICATOR
74 0xA8 0x00BF INVERTED QUESTION MARK
75 0xA9 0x2310 REVERSED NOT SIGN
76 0xAA 0x00AC NOT SIGN
77 0xAB 0x00BD VULGAR FRACTION ONE HALF
78 0xAC 0x00BC VULGAR FRACTION ONE QUARTER
79 0xAD 0x00A1 INVERTED EXCLAMATION MARK
80 0xAE 0x00AB LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
81 0xAF 0x00BB RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
82 0xB0 0x2591 LIGHT SHADE
83 0xB1 0x2592 MEDIUM SHADE
84 0xB2 0x2593 DARK SHADE
85 0xB3 0x2502 BOX DRAWINGS LIGHT VERTICAL
86 0xB4 0x2524 BOX DRAWINGS LIGHT VERTICAL AND LEFT
87 0xB5 0x2561 BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
88 0xB6 0x2562 BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
89 0xB7 0x2556 BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
90 0xB8 0x2555 BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
91 0xB9 0x2563 BOX DRAWINGS DOUBLE VERTICAL AND LEFT
92 0xBA 0x2551 BOX DRAWINGS DOUBLE VERTICAL
93 0xBB 0x2557 BOX DRAWINGS DOUBLE DOWN AND LEFT
94 0xBC 0x255D BOX DRAWINGS DOUBLE UP AND LEFT
95 0xBD 0x255C BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
96 0xBE 0x255B BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
97 0xBF 0x2510 BOX DRAWINGS LIGHT DOWN AND LEFT
98 0xC0 0x2514 BOX DRAWINGS LIGHT UP AND RIGHT
99 0xC1 0x2534 BOX DRAWINGS LIGHT UP AND HORIZONTAL
100 0xC2 0x252C BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
101 0xC3 0x251C BOX DRAWINGS LIGHT VERTICAL AND RIGHT
102 0xC4 0x2500 BOX DRAWINGS LIGHT HORIZONTAL
103 0xC5 0x253C BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
104 0xC6 0x255E BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
105 0xC7 0x255F BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
106 0xC8 0x255A BOX DRAWINGS DOUBLE UP AND RIGHT
107 0xC9 0x2554 BOX DRAWINGS DOUBLE DOWN AND RIGHT
108 0xCA 0x2569 BOX DRAWINGS DOUBLE UP AND HORIZONTAL
109 0xCB 0x2566 BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
110 0xCC 0x2560 BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
111 0xCD 0x2550 BOX DRAWINGS DOUBLE HORIZONTAL
112 0xCE 0x256C BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
113 0xCF 0x2567 BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
114 0xD0 0x2568 BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
115 0xD1 0x2564 BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
116 0xD2 0x2565 BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
117 0xD3 0x2559 BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
118 0xD4 0x2558 BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
119 0xD5 0x2552 BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
120 0xD6 0x2553 BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
121 0xD7 0x256B BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
122 0xD8 0x256A BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
123 0xD9 0x2518 BOX DRAWINGS LIGHT UP AND LEFT
124 0xDA 0x250C BOX DRAWINGS LIGHT DOWN AND RIGHT
125 0xDB 0x2588 FULL BLOCK
126 0xDC 0x2584 LOWER HALF BLOCK
127 0xDD 0x258C LEFT HALF BLOCK
128 0xDE 0x2590 RIGHT HALF BLOCK
129 0xDF 0x2580 UPPER HALF BLOCK
130 0xE0 0x03B1 GREEK SMALL LETTER ALPHA
131 0xE1 0x00DF LATIN SMALL LETTER SHARP S
132 0xE2 0x0393 GREEK CAPITAL LETTER GAMMA
133 0xE3 0x03C0 GREEK SMALL LETTER PI
134 0xE4 0x03A3 GREEK CAPITAL LETTER SIGMA
135 0xE5 0x03C3 GREEK SMALL LETTER SIGMA
136 0xE6 0x00B5 MICRO SIGN
137 0xE7 0x03C4 GREEK SMALL LETTER TAU
138 0xE8 0x03A6 GREEK CAPITAL LETTER PHI
139 0xE9 0x0398 GREEK CAPITAL LETTER THETA
140 0xEA 0x03A9 GREEK CAPITAL LETTER OMEGA
141 0xEB 0x03B4 GREEK SMALL LETTER DELTA
142 0xEC 0x221E INFINITY
143 0xED 0x03C6 GREEK SMALL LETTER PHI
144 0xEE 0x03B5 GREEK SMALL LETTER EPSILON
145 0xEF 0x2229 INTERSECTION
146 0xF0 0x2261 IDENTICAL TO
147 0xF1 0x00B1 PLUS-MINUS SIGN
148 0xF2 0x2265 GREATER-THAN OR EQUAL TO
149 0xF3 0x2264 LESS-THAN OR EQUAL TO
150 0xF4 0x2320 TOP HALF INTEGRAL
151 0xF5 0x2321 BOTTOM HALF INTEGRAL
152 0xF6 0x00F7 DIVISION SIGN
153 0xF7 0x2248 ALMOST EQUAL TO
154 0xF8 0x00B0 DEGREE SIGN
155 0xF9 0x2219 BULLET OPERATOR
156 0xFA 0x00B7 MIDDLE DOT
157 0xFB 0x221A SQUARE ROOT
158 0xFC 0x207F SUPERSCRIPT LATIN SMALL LETTER N
159 0xFD 0x00B2 SUPERSCRIPT TWO
160 0xFE 0x25A0 BLACK SQUARE
161 0xFF 0x25A1 WHITE SQUARE

View File

@ -0,0 +1,45 @@
#!/usr/bin/env python3
import unicodedata
mapping = []
with open('../data/values.tsv', 'r') as f:
lines = iter(f)
next(lines)
for line in lines:
(byte, unich, name) = line.rstrip().split('\t')
byte = int(byte, 0)
unich = int(unich, 0)
mapping.append((byte, unich, name))
# add in ASCII
mapping.append((0x00, 0x0000, 'NUL'))
for ch in range(0x20, 0x7f):
mapping.append((ch, ch, unicodedata.name(chr(ch))))
mapping.sort()
fw_mapping = [None] * 256
for byte, unich, name in mapping:
#print('%02x %05x %s' % (byte, unich, name))
fw_mapping[byte] = unich
def qchar(ch):
return "'\\u{%04x}'" % ch
print('static FROM: [char; 256] = [')
for i in range(0x100):
if (i % 8)==0:
print(" ", end='')
print("%s," % qchar(fw_mapping[i]), end='')
if ((i+1) % 8)==0:
print()
else:
print(" ", end='')
print(']')
print('pub fn to(ch: char) -> u8 {')
print(' match ch {')
for byte, unich, name in mapping:
print(' %s => 0x%02x, // %s' % (qchar(unich), byte, name))
print(' }')
print('}')

View File

@ -1,11 +1,16 @@
use core::fmt;
use k210_shared::board::lcd_colors::rgb565;
use crate::cp437;
use crate::cp437_8x8;
use crate::palette_xterm256::PALETTE;
pub const DISP_WIDTH: usize = 320;
pub const DISP_HEIGHT: usize = 240;
const GRID_WIDTH: usize = DISP_WIDTH / 8;
const GRID_HEIGHT: usize = DISP_HEIGHT / 8;
const DEF_FG: u16 = rgb565(192, 192, 192);
const DEF_BG: u16 = rgb565(0, 0, 0);
pub type ScreenImage = [u32; DISP_WIDTH * DISP_HEIGHT / 2];
@ -18,15 +23,15 @@ pub struct Color {
}
impl Color {
pub fn new(r: u8, g: u8, b: u8) -> Color {
pub const fn new(r: u8, g: u8, b: u8) -> Color {
Color { r, g, b, a: 255 }
}
pub fn new_rgba(r: u8, g: u8, b: u8, a: u8) -> Color {
pub const fn new_rgba(r: u8, g: u8, b: u8, a: u8) -> Color {
Color { r, g, b, a: a }
}
pub fn from_rgba32(val: u32) -> Color {
pub const fn from_rgba32(val: u32) -> Color {
Color {
r: ((val >> 24) & 0xff) as u8,
g: ((val >> 16) & 0xff) as u8,
@ -34,6 +39,10 @@ impl Color {
a: ((val >> 0) & 0xff) as u8,
}
}
pub const fn to_rgb565(&self) -> u16 {
rgb565(self.r, self.g, self.b)
}
}
#[derive(Copy, Clone)]
@ -71,27 +80,71 @@ pub struct Cell {
ch: char,
}
enum State {
Initial,
Escape,
CSI,
}
enum Sgr {
Initial,
SpecialFg,
SpecialBg,
Fg256,
Bg256,
FgR,
BgR,
FgG,
BgG,
FgB,
BgB,
}
/** Visual attributes of console */
pub struct Console {
/** Dirty flag */
pub dirty: bool,
/** Array of character cells representing console */
cells: [Cell; GRID_WIDTH * GRID_HEIGHT],
/** Cursor position */
cursor_pos: Coord,
/** Cursor visible flag */
cursor_visible: bool,
/** Default foreground */
def_fg: u16,
/** Default background */
def_bg: u16,
/** Current foreground */
cur_fg: u16,
/** Current background */
cur_bg: u16,
/** Current escape state */
state: State,
/** Current CSI parameter */
idx: usize,
/** CSI parameters */
num: [u16; 16],
}
impl Console {
/** Create new, empty console */
pub fn new() -> Console {
Console {
dirty: false,
cells: [Cell {
fg: 0,
bg: 0,
fg: DEF_FG,
bg: DEF_BG,
ch: '\x00',
}; GRID_WIDTH * GRID_HEIGHT],
cursor_pos: Coord::new(0, 0),
cursor_visible: true,
def_fg: DEF_FG,
def_bg: DEF_BG,
cur_fg: DEF_FG,
cur_bg: DEF_BG,
state: State::Initial,
idx: 0,
num: [0; 16],
}
}
@ -140,11 +193,139 @@ impl Console {
GRID_HEIGHT as u16
}
/** Put a char at an arbitrary position with arbitrary fg/bg color. Does not move the cursor.
* Use this to regard the console as a simple grid of cells a la libtcod. Useful for drawing
* frames and such.
*/
pub fn put(&mut self, x: u16, y: u16, fg: Color, bg: Color, ch: char) {
self.dirty = true;
self.cells[(y as usize) * GRID_WIDTH + (x as usize)] = Cell {
fg: rgb565(fg.r, fg.g, fg.b),
bg: rgb565(bg.r, bg.g, bg.b),
ch,
};
}
/** Handle SGR escape sequence parameters */
pub fn handle_sgr(&mut self) {
let mut state = Sgr::Initial;
let mut color = Color::new(0, 0, 0);
for param in &self.num[0..self.idx+1] {
match state {
Sgr::Initial => {
match param {
0 => { self.cur_fg = self.def_fg; self.cur_bg = self.def_bg; }
30..=37 => { self.cur_fg = Color::from_rgba32(PALETTE[(param - 30) as usize]).to_rgb565(); }
38 => { state = Sgr::SpecialFg; }
40..=47 => { self.cur_bg = Color::from_rgba32(PALETTE[(param - 40) as usize]).to_rgb565(); }
48 => { state = Sgr::SpecialBg; }
90..=97 => { self.cur_fg = Color::from_rgba32(PALETTE[8 + (param - 90) as usize]).to_rgb565(); }
100..=107 => { self.cur_bg = Color::from_rgba32(PALETTE[8 + (param - 100) as usize]).to_rgb565(); }
_ => {}
}
}
Sgr::SpecialFg => {
match param {
2 => { state = Sgr::FgR; }
5 => { state = Sgr::Fg256; }
_ => { state = Sgr::Initial; }
}
}
Sgr::SpecialBg => {
match param {
2 => { state = Sgr::BgR; }
5 => { state = Sgr::Bg256; }
_ => { state = Sgr::Initial; }
}
}
Sgr::Fg256 => {
self.cur_fg = Color::from_rgba32(PALETTE[(param & 0xff) as usize]).to_rgb565();
state = Sgr::Initial;
}
Sgr::Bg256 => {
self.cur_bg = Color::from_rgba32(PALETTE[(param & 0xff) as usize]).to_rgb565();
state = Sgr::Initial;
}
Sgr::FgR => { color.r = (param & 0xff) as u8; state = Sgr::FgG; }
Sgr::FgG => { color.g = (param & 0xff) as u8; state = Sgr::FgB; }
Sgr::FgB => { color.b = (param & 0xff) as u8; state = Sgr::Initial; self.cur_fg = color.to_rgb565(); }
Sgr::BgR => { color.r = (param & 0xff) as u8; state = Sgr::BgG; }
Sgr::BgG => { color.g = (param & 0xff) as u8; state = Sgr::BgB; }
Sgr::BgB => { color.b = (param & 0xff) as u8; state = Sgr::Initial; self.cur_bg = color.to_rgb565(); }
}
}
}
/** Put a char at current cursor position, interpreting control and escape codes. */
pub fn putch(&mut self, ch: char) {
match self.state {
State::Initial => {
match ch {
'\r' => { self.cursor_pos.x = 0; }
'\n' => { self.cursor_pos.y += 1; self.cursor_pos.x = 0; }
'\x1b' => { self.state = State::Escape; }
ch => {
self.dirty = true;
self.cells[(self.cursor_pos.y as usize) * GRID_WIDTH + (self.cursor_pos.x as usize)] = Cell {
fg: self.cur_fg,
bg: self.cur_bg,
ch,
};
self.cursor_pos.x += 1;
}
}
}
State::Escape => {
match ch {
'[' => { self.state = State::CSI; self.idx = 0; self.num[0] = 0; }
_ => { self.state = State::Initial; }
}
}
State::CSI => {
match ch {
'0'..='9' => {
self.num[self.idx] *= 10;
self.num[self.idx] += ((ch as u8) - b'0') as u16;
}
';' => {
self.idx += 1;
if self.idx == self.num.len() {
// Too many arguments, ignore sequence
self.state = State::Initial;
} else {
self.num[self.idx] = 0;
}
}
'm' => {
self.handle_sgr();
self.state = State::Initial;
}
_ => {
self.state = State::Initial;
}
}
}
}
// wrap around
if self.cursor_pos.x == GRID_WIDTH as u16 {
self.cursor_pos.x = 0;
self.cursor_pos.y += 1;
}
if self.cursor_pos.y == GRID_HEIGHT as u16 {
self.cursor_pos.y = 0;
}
}
/** Put a string at current cursor position, interpreting control and escape codes. */
pub fn puts(&mut self, s: &str) {
for ch in s.chars() {
self.putch(ch);
}
}
}
/** Formatting adoption for console */
impl fmt::Write for Console {
fn write_str(&mut self, s: &str) -> Result<(), fmt::Error> { self.puts(s); Ok(()) }
fn write_char(&mut self, c: char) -> Result<(), fmt::Error> { self.putch(c); Ok(()) }
}

View File

@ -1,9 +1,301 @@
/** Table from cp437 to unicode char; generated with create_tables.py */
static FROM: [char; 256] = [
'\u{0000}', '\u{263a}', '\u{263b}', '\u{2665}', '\u{2666}', '\u{2663}', '\u{2660}', '\u{2022}',
'\u{25d8}', '\u{25cb}', '\u{25d9}', '\u{2642}', '\u{2640}', '\u{266a}', '\u{266b}', '\u{263c}',
'\u{25ba}', '\u{25c4}', '\u{2195}', '\u{203c}', '\u{00b6}', '\u{00a7}', '\u{25ac}', '\u{21a8}',
'\u{2191}', '\u{2193}', '\u{2192}', '\u{2190}', '\u{221f}', '\u{2194}', '\u{25b2}', '\u{25bc}',
'\u{0020}', '\u{0021}', '\u{0022}', '\u{0023}', '\u{0024}', '\u{0025}', '\u{0026}', '\u{0027}',
'\u{0028}', '\u{0029}', '\u{002a}', '\u{002b}', '\u{002c}', '\u{002d}', '\u{002e}', '\u{002f}',
'\u{0030}', '\u{0031}', '\u{0032}', '\u{0033}', '\u{0034}', '\u{0035}', '\u{0036}', '\u{0037}',
'\u{0038}', '\u{0039}', '\u{003a}', '\u{003b}', '\u{003c}', '\u{003d}', '\u{003e}', '\u{003f}',
'\u{0040}', '\u{0041}', '\u{0042}', '\u{0043}', '\u{0044}', '\u{0045}', '\u{0046}', '\u{0047}',
'\u{0048}', '\u{0049}', '\u{004a}', '\u{004b}', '\u{004c}', '\u{004d}', '\u{004e}', '\u{004f}',
'\u{0050}', '\u{0051}', '\u{0052}', '\u{0053}', '\u{0054}', '\u{0055}', '\u{0056}', '\u{0057}',
'\u{0058}', '\u{0059}', '\u{005a}', '\u{005b}', '\u{005c}', '\u{005d}', '\u{005e}', '\u{005f}',
'\u{0060}', '\u{0061}', '\u{0062}', '\u{0063}', '\u{0064}', '\u{0065}', '\u{0066}', '\u{0067}',
'\u{0068}', '\u{0069}', '\u{006a}', '\u{006b}', '\u{006c}', '\u{006d}', '\u{006e}', '\u{006f}',
'\u{0070}', '\u{0071}', '\u{0072}', '\u{0073}', '\u{0074}', '\u{0075}', '\u{0076}', '\u{0077}',
'\u{0078}', '\u{0079}', '\u{007a}', '\u{007b}', '\u{007c}', '\u{007d}', '\u{007e}', '\u{2302}',
'\u{00c7}', '\u{00fc}', '\u{00e9}', '\u{00e2}', '\u{00e4}', '\u{00e0}', '\u{00e5}', '\u{00e7}',
'\u{00ea}', '\u{00eb}', '\u{00e8}', '\u{00ef}', '\u{00ee}', '\u{00ec}', '\u{00c4}', '\u{00c5}',
'\u{00c9}', '\u{00e6}', '\u{00c6}', '\u{00f4}', '\u{00f6}', '\u{00f2}', '\u{00fb}', '\u{00f9}',
'\u{00ff}', '\u{00d6}', '\u{00dc}', '\u{00a2}', '\u{00a3}', '\u{00a5}', '\u{20a7}', '\u{0192}',
'\u{00e1}', '\u{00ed}', '\u{00f3}', '\u{00fa}', '\u{00f1}', '\u{00d1}', '\u{00aa}', '\u{00ba}',
'\u{00bf}', '\u{2310}', '\u{00ac}', '\u{00bd}', '\u{00bc}', '\u{00a1}', '\u{00ab}', '\u{00bb}',
'\u{2591}', '\u{2592}', '\u{2593}', '\u{2502}', '\u{2524}', '\u{2561}', '\u{2562}', '\u{2556}',
'\u{2555}', '\u{2563}', '\u{2551}', '\u{2557}', '\u{255d}', '\u{255c}', '\u{255b}', '\u{2510}',
'\u{2514}', '\u{2534}', '\u{252c}', '\u{251c}', '\u{2500}', '\u{253c}', '\u{255e}', '\u{255f}',
'\u{255a}', '\u{2554}', '\u{2569}', '\u{2566}', '\u{2560}', '\u{2550}', '\u{256c}', '\u{2567}',
'\u{2568}', '\u{2564}', '\u{2565}', '\u{2559}', '\u{2558}', '\u{2552}', '\u{2553}', '\u{256b}',
'\u{256a}', '\u{2518}', '\u{250c}', '\u{2588}', '\u{2584}', '\u{258c}', '\u{2590}', '\u{2580}',
'\u{03b1}', '\u{00df}', '\u{0393}', '\u{03c0}', '\u{03a3}', '\u{03c3}', '\u{00b5}', '\u{03c4}',
'\u{03a6}', '\u{0398}', '\u{03a9}', '\u{03b4}', '\u{221e}', '\u{03c6}', '\u{03b5}', '\u{2229}',
'\u{2261}', '\u{00b1}', '\u{2265}', '\u{2264}', '\u{2320}', '\u{2321}', '\u{00f7}', '\u{2248}',
'\u{00b0}', '\u{2219}', '\u{00b7}', '\u{221a}', '\u{207f}', '\u{00b2}', '\u{25a0}', '\u{25a1}',
];
pub fn from(ch: u8) -> char {
// TODO: correct mapping
ch as char
FROM[ch as usize]
}
pub fn to(ch: char) -> u8 {
// TODO: correct mapping
ch as u8
match ch {
'\u{0000}' => 0x00, // NUL
'\u{263a}' => 0x01, // WHITE SMILING FACE
'\u{263b}' => 0x02, // BLACK SMILING FACE
'\u{2665}' => 0x03, // BLACK HEART SUIT
'\u{2666}' => 0x04, // BLACK DIAMOND SUIT
'\u{2663}' => 0x05, // BLACK CLUB SUIT
'\u{2660}' => 0x06, // BLACK SPADE SUIT
'\u{2022}' => 0x07, // BULLET
'\u{25d8}' => 0x08, // INVERSE BULLET
'\u{25cb}' => 0x09, // WHITE CIRCLE
'\u{25d9}' => 0x0a, // INVERSE WHITE CIRCLE
'\u{2642}' => 0x0b, // MALE SIGN
'\u{2640}' => 0x0c, // FEMALE SIGN
'\u{266a}' => 0x0d, // EIGHTH NOTE
'\u{266b}' => 0x0e, // BEAMED EIGHTH NOTES
'\u{263c}' => 0x0f, // WHITE SUN WITH RAYS
'\u{25ba}' => 0x10, // BLACK RIGHT-POINTING POINTER
'\u{25c4}' => 0x11, // BLACK LEFT-POINTING POINTER
'\u{2195}' => 0x12, // UP DOWN ARROW
'\u{203c}' => 0x13, // DOUBLE EXCLAMATION MARK
'\u{00b6}' => 0x14, // PILCROW SIGN
'\u{00a7}' => 0x15, // SECTION SIGN
'\u{25ac}' => 0x16, // BLACK RECTANGLE
'\u{21a8}' => 0x17, // UP DOWN ARROW WITH BASE
'\u{2191}' => 0x18, // UPWARDS ARROW
'\u{2193}' => 0x19, // DOWNWARDS ARROW
'\u{2192}' => 0x1a, // RIGHTWARDS ARROW
'\u{2190}' => 0x1b, // LEFTWARDS ARROW
'\u{221f}' => 0x1c, // RIGHT ANGLE
'\u{2194}' => 0x1d, // LEFT RIGHT ARROW
'\u{25b2}' => 0x1e, // BLACK UP-POINTING TRIANGLE
'\u{25bc}' => 0x1f, // BLACK DOWN-POINTING TRIANGLE
'\u{0020}' => 0x20, // SPACE
'\u{0021}' => 0x21, // EXCLAMATION MARK
'\u{0022}' => 0x22, // QUOTATION MARK
'\u{0023}' => 0x23, // NUMBER SIGN
'\u{0024}' => 0x24, // DOLLAR SIGN
'\u{0025}' => 0x25, // PERCENT SIGN
'\u{0026}' => 0x26, // AMPERSAND
'\u{0027}' => 0x27, // APOSTROPHE
'\u{0028}' => 0x28, // LEFT PARENTHESIS
'\u{0029}' => 0x29, // RIGHT PARENTHESIS
'\u{002a}' => 0x2a, // ASTERISK
'\u{002b}' => 0x2b, // PLUS SIGN
'\u{002c}' => 0x2c, // COMMA
'\u{002d}' => 0x2d, // HYPHEN-MINUS
'\u{002e}' => 0x2e, // FULL STOP
'\u{002f}' => 0x2f, // SOLIDUS
'\u{0030}' => 0x30, // DIGIT ZERO
'\u{0031}' => 0x31, // DIGIT ONE
'\u{0032}' => 0x32, // DIGIT TWO
'\u{0033}' => 0x33, // DIGIT THREE
'\u{0034}' => 0x34, // DIGIT FOUR
'\u{0035}' => 0x35, // DIGIT FIVE
'\u{0036}' => 0x36, // DIGIT SIX
'\u{0037}' => 0x37, // DIGIT SEVEN
'\u{0038}' => 0x38, // DIGIT EIGHT
'\u{0039}' => 0x39, // DIGIT NINE
'\u{003a}' => 0x3a, // COLON
'\u{003b}' => 0x3b, // SEMICOLON
'\u{003c}' => 0x3c, // LESS-THAN SIGN
'\u{003d}' => 0x3d, // EQUALS SIGN
'\u{003e}' => 0x3e, // GREATER-THAN SIGN
'\u{003f}' => 0x3f, // QUESTION MARK
'\u{0040}' => 0x40, // COMMERCIAL AT
'\u{0041}' => 0x41, // LATIN CAPITAL LETTER A
'\u{0042}' => 0x42, // LATIN CAPITAL LETTER B
'\u{0043}' => 0x43, // LATIN CAPITAL LETTER C
'\u{0044}' => 0x44, // LATIN CAPITAL LETTER D
'\u{0045}' => 0x45, // LATIN CAPITAL LETTER E
'\u{0046}' => 0x46, // LATIN CAPITAL LETTER F
'\u{0047}' => 0x47, // LATIN CAPITAL LETTER G
'\u{0048}' => 0x48, // LATIN CAPITAL LETTER H
'\u{0049}' => 0x49, // LATIN CAPITAL LETTER I
'\u{004a}' => 0x4a, // LATIN CAPITAL LETTER J
'\u{004b}' => 0x4b, // LATIN CAPITAL LETTER K
'\u{004c}' => 0x4c, // LATIN CAPITAL LETTER L
'\u{004d}' => 0x4d, // LATIN CAPITAL LETTER M
'\u{004e}' => 0x4e, // LATIN CAPITAL LETTER N
'\u{004f}' => 0x4f, // LATIN CAPITAL LETTER O
'\u{0050}' => 0x50, // LATIN CAPITAL LETTER P
'\u{0051}' => 0x51, // LATIN CAPITAL LETTER Q
'\u{0052}' => 0x52, // LATIN CAPITAL LETTER R
'\u{0053}' => 0x53, // LATIN CAPITAL LETTER S
'\u{0054}' => 0x54, // LATIN CAPITAL LETTER T
'\u{0055}' => 0x55, // LATIN CAPITAL LETTER U
'\u{0056}' => 0x56, // LATIN CAPITAL LETTER V
'\u{0057}' => 0x57, // LATIN CAPITAL LETTER W
'\u{0058}' => 0x58, // LATIN CAPITAL LETTER X
'\u{0059}' => 0x59, // LATIN CAPITAL LETTER Y
'\u{005a}' => 0x5a, // LATIN CAPITAL LETTER Z
'\u{005b}' => 0x5b, // LEFT SQUARE BRACKET
'\u{005c}' => 0x5c, // REVERSE SOLIDUS
'\u{005d}' => 0x5d, // RIGHT SQUARE BRACKET
'\u{005e}' => 0x5e, // CIRCUMFLEX ACCENT
'\u{005f}' => 0x5f, // LOW LINE
'\u{0060}' => 0x60, // GRAVE ACCENT
'\u{0061}' => 0x61, // LATIN SMALL LETTER A
'\u{0062}' => 0x62, // LATIN SMALL LETTER B
'\u{0063}' => 0x63, // LATIN SMALL LETTER C
'\u{0064}' => 0x64, // LATIN SMALL LETTER D
'\u{0065}' => 0x65, // LATIN SMALL LETTER E
'\u{0066}' => 0x66, // LATIN SMALL LETTER F
'\u{0067}' => 0x67, // LATIN SMALL LETTER G
'\u{0068}' => 0x68, // LATIN SMALL LETTER H
'\u{0069}' => 0x69, // LATIN SMALL LETTER I
'\u{006a}' => 0x6a, // LATIN SMALL LETTER J
'\u{006b}' => 0x6b, // LATIN SMALL LETTER K
'\u{006c}' => 0x6c, // LATIN SMALL LETTER L
'\u{006d}' => 0x6d, // LATIN SMALL LETTER M
'\u{006e}' => 0x6e, // LATIN SMALL LETTER N
'\u{006f}' => 0x6f, // LATIN SMALL LETTER O
'\u{0070}' => 0x70, // LATIN SMALL LETTER P
'\u{0071}' => 0x71, // LATIN SMALL LETTER Q
'\u{0072}' => 0x72, // LATIN SMALL LETTER R
'\u{0073}' => 0x73, // LATIN SMALL LETTER S
'\u{0074}' => 0x74, // LATIN SMALL LETTER T
'\u{0075}' => 0x75, // LATIN SMALL LETTER U
'\u{0076}' => 0x76, // LATIN SMALL LETTER V
'\u{0077}' => 0x77, // LATIN SMALL LETTER W
'\u{0078}' => 0x78, // LATIN SMALL LETTER X
'\u{0079}' => 0x79, // LATIN SMALL LETTER Y
'\u{007a}' => 0x7a, // LATIN SMALL LETTER Z
'\u{007b}' => 0x7b, // LEFT CURLY BRACKET
'\u{007c}' => 0x7c, // VERTICAL LINE
'\u{007d}' => 0x7d, // RIGHT CURLY BRACKET
'\u{007e}' => 0x7e, // TILDE
'\u{2302}' => 0x7f, // HOUSE
'\u{00c7}' => 0x80, // LATIN CAPITAL LETTER C WITH CEDILLA
'\u{00fc}' => 0x81, // LATIN SMALL LETTER U WITH DIAERESIS
'\u{00e9}' => 0x82, // LATIN SMALL LETTER E WITH ACUTE
'\u{00e2}' => 0x83, // LATIN SMALL LETTER A WITH CIRCUMFLEX
'\u{00e4}' => 0x84, // LATIN SMALL LETTER A WITH DIAERESIS
'\u{00e0}' => 0x85, // LATIN SMALL LETTER A WITH GRAVE
'\u{00e5}' => 0x86, // LATIN SMALL LETTER A WITH RING ABOVE
'\u{00e7}' => 0x87, // LATIN SMALL LETTER C WITH CEDILLA
'\u{00ea}' => 0x88, // LATIN SMALL LETTER E WITH CIRCUMFLEX
'\u{00eb}' => 0x89, // LATIN SMALL LETTER E WITH DIAERESIS
'\u{00e8}' => 0x8a, // LATIN SMALL LETTER E WITH GRAVE
'\u{00ef}' => 0x8b, // LATIN SMALL LETTER I WITH DIAERESIS
'\u{00ee}' => 0x8c, // LATIN SMALL LETTER I WITH CIRCUMFLEX
'\u{00ec}' => 0x8d, // LATIN SMALL LETTER I WITH GRAVE
'\u{00c4}' => 0x8e, // LATIN CAPITAL LETTER A WITH DIAERESIS
'\u{00c5}' => 0x8f, // LATIN CAPITAL LETTER A WITH RING ABOVE
'\u{00c9}' => 0x90, // LATIN CAPITAL LETTER E WITH ACUTE
'\u{00e6}' => 0x91, // LATIN SMALL LETTER AE
'\u{00c6}' => 0x92, // LATIN CAPITAL LETTER AE
'\u{00f4}' => 0x93, // LATIN SMALL LETTER O WITH CIRCUMFLEX
'\u{00f6}' => 0x94, // LATIN SMALL LETTER O WITH DIAERESIS
'\u{00f2}' => 0x95, // LATIN SMALL LETTER O WITH GRAVE
'\u{00fb}' => 0x96, // LATIN SMALL LETTER U WITH CIRCUMFLEX
'\u{00f9}' => 0x97, // LATIN SMALL LETTER U WITH GRAVE
'\u{00ff}' => 0x98, // LATIN SMALL LETTER Y WITH DIAERESIS
'\u{00d6}' => 0x99, // LATIN CAPITAL LETTER O WITH DIAERESIS
'\u{00dc}' => 0x9a, // LATIN CAPITAL LETTER U WITH DIAERESIS
'\u{00a2}' => 0x9b, // CENT SIGN
'\u{00a3}' => 0x9c, // POUND SIGN
'\u{00a5}' => 0x9d, // YEN SIGN
'\u{20a7}' => 0x9e, // PESETA SIGN
'\u{0192}' => 0x9f, // LATIN SMALL LETTER F WITH HOOK
'\u{00e1}' => 0xa0, // LATIN SMALL LETTER A WITH ACUTE
'\u{00ed}' => 0xa1, // LATIN SMALL LETTER I WITH ACUTE
'\u{00f3}' => 0xa2, // LATIN SMALL LETTER O WITH ACUTE
'\u{00fa}' => 0xa3, // LATIN SMALL LETTER U WITH ACUTE
'\u{00f1}' => 0xa4, // LATIN SMALL LETTER N WITH TILDE
'\u{00d1}' => 0xa5, // LATIN CAPITAL LETTER N WITH TILDE
'\u{00aa}' => 0xa6, // FEMININE ORDINAL INDICATOR
'\u{00ba}' => 0xa7, // MASCULINE ORDINAL INDICATOR
'\u{00bf}' => 0xa8, // INVERTED QUESTION MARK
'\u{2310}' => 0xa9, // REVERSED NOT SIGN
'\u{00ac}' => 0xaa, // NOT SIGN
'\u{00bd}' => 0xab, // VULGAR FRACTION ONE HALF
'\u{00bc}' => 0xac, // VULGAR FRACTION ONE QUARTER
'\u{00a1}' => 0xad, // INVERTED EXCLAMATION MARK
'\u{00ab}' => 0xae, // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
'\u{00bb}' => 0xaf, // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
'\u{2591}' => 0xb0, // LIGHT SHADE
'\u{2592}' => 0xb1, // MEDIUM SHADE
'\u{2593}' => 0xb2, // DARK SHADE
'\u{2502}' => 0xb3, // BOX DRAWINGS LIGHT VERTICAL
'\u{2524}' => 0xb4, // BOX DRAWINGS LIGHT VERTICAL AND LEFT
'\u{2561}' => 0xb5, // BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
'\u{2562}' => 0xb6, // BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
'\u{2556}' => 0xb7, // BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
'\u{2555}' => 0xb8, // BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
'\u{2563}' => 0xb9, // BOX DRAWINGS DOUBLE VERTICAL AND LEFT
'\u{2551}' => 0xba, // BOX DRAWINGS DOUBLE VERTICAL
'\u{2557}' => 0xbb, // BOX DRAWINGS DOUBLE DOWN AND LEFT
'\u{255d}' => 0xbc, // BOX DRAWINGS DOUBLE UP AND LEFT
'\u{255c}' => 0xbd, // BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
'\u{255b}' => 0xbe, // BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
'\u{2510}' => 0xbf, // BOX DRAWINGS LIGHT DOWN AND LEFT
'\u{2514}' => 0xc0, // BOX DRAWINGS LIGHT UP AND RIGHT
'\u{2534}' => 0xc1, // BOX DRAWINGS LIGHT UP AND HORIZONTAL
'\u{252c}' => 0xc2, // BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
'\u{251c}' => 0xc3, // BOX DRAWINGS LIGHT VERTICAL AND RIGHT
'\u{2500}' => 0xc4, // BOX DRAWINGS LIGHT HORIZONTAL
'\u{253c}' => 0xc5, // BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
'\u{255e}' => 0xc6, // BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
'\u{255f}' => 0xc7, // BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
'\u{255a}' => 0xc8, // BOX DRAWINGS DOUBLE UP AND RIGHT
'\u{2554}' => 0xc9, // BOX DRAWINGS DOUBLE DOWN AND RIGHT
'\u{2569}' => 0xca, // BOX DRAWINGS DOUBLE UP AND HORIZONTAL
'\u{2566}' => 0xcb, // BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
'\u{2560}' => 0xcc, // BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
'\u{2550}' => 0xcd, // BOX DRAWINGS DOUBLE HORIZONTAL
'\u{256c}' => 0xce, // BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
'\u{2567}' => 0xcf, // BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
'\u{2568}' => 0xd0, // BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
'\u{2564}' => 0xd1, // BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
'\u{2565}' => 0xd2, // BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
'\u{2559}' => 0xd3, // BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
'\u{2558}' => 0xd4, // BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
'\u{2552}' => 0xd5, // BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
'\u{2553}' => 0xd6, // BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
'\u{256b}' => 0xd7, // BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
'\u{256a}' => 0xd8, // BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
'\u{2518}' => 0xd9, // BOX DRAWINGS LIGHT UP AND LEFT
'\u{250c}' => 0xda, // BOX DRAWINGS LIGHT DOWN AND RIGHT
'\u{2588}' => 0xdb, // FULL BLOCK
'\u{2584}' => 0xdc, // LOWER HALF BLOCK
'\u{258c}' => 0xdd, // LEFT HALF BLOCK
'\u{2590}' => 0xde, // RIGHT HALF BLOCK
'\u{2580}' => 0xdf, // UPPER HALF BLOCK
'\u{03b1}' => 0xe0, // GREEK SMALL LETTER ALPHA
'\u{00df}' => 0xe1, // LATIN SMALL LETTER SHARP S
'\u{0393}' => 0xe2, // GREEK CAPITAL LETTER GAMMA
'\u{03c0}' => 0xe3, // GREEK SMALL LETTER PI
'\u{03a3}' => 0xe4, // GREEK CAPITAL LETTER SIGMA
'\u{03c3}' => 0xe5, // GREEK SMALL LETTER SIGMA
'\u{00b5}' => 0xe6, // MICRO SIGN
'\u{03c4}' => 0xe7, // GREEK SMALL LETTER TAU
'\u{03a6}' => 0xe8, // GREEK CAPITAL LETTER PHI
'\u{0398}' => 0xe9, // GREEK CAPITAL LETTER THETA
'\u{03a9}' => 0xea, // GREEK CAPITAL LETTER OMEGA
'\u{03b4}' => 0xeb, // GREEK SMALL LETTER DELTA
'\u{221e}' => 0xec, // INFINITY
'\u{03c6}' => 0xed, // GREEK SMALL LETTER PHI
'\u{03b5}' => 0xee, // GREEK SMALL LETTER EPSILON
'\u{2229}' => 0xef, // INTERSECTION
'\u{2261}' => 0xf0, // IDENTICAL TO
'\u{00b1}' => 0xf1, // PLUS-MINUS SIGN
'\u{2265}' => 0xf2, // GREATER-THAN OR EQUAL TO
'\u{2264}' => 0xf3, // LESS-THAN OR EQUAL TO
'\u{2320}' => 0xf4, // TOP HALF INTEGRAL
'\u{2321}' => 0xf5, // BOTTOM HALF INTEGRAL
'\u{00f7}' => 0xf6, // DIVISION SIGN
'\u{2248}' => 0xf7, // ALMOST EQUAL TO
'\u{00b0}' => 0xf8, // DEGREE SIGN
'\u{2219}' => 0xf9, // BULLET OPERATOR
'\u{00b7}' => 0xfa, // MIDDLE DOT
'\u{221a}' => 0xfb, // SQUARE ROOT
'\u{207f}' => 0xfc, // SUPERSCRIPT LATIN SMALL LETTER N
'\u{00b2}' => 0xfd, // SUPERSCRIPT TWO
'\u{25a0}' => 0xfe, // BLACK SQUARE
'\u{25a1}' => 0xff, // WHITE SQUARE
_ => 254, // Unknown
}
}

View File

@ -0,0 +1,6 @@
#![no_std]
pub mod console;
pub mod cp437;
pub mod cp437_8x8;
pub mod palette_xterm256;

View File

@ -4,11 +4,7 @@
#![no_std]
#![no_main]
mod console;
mod cp437;
mod cp437_8x8;
mod lfsr;
mod palette_xterm256;
use k210_hal::pac;
use k210_hal::prelude::*;
@ -22,8 +18,9 @@ use k210_shared::soc::spi::SPIExt;
use k210_shared::soc::sysctl;
use riscv_rt::entry;
use crate::console::{Color, Console, ScreenImage, DISP_HEIGHT, DISP_WIDTH};
use crate::palette_xterm256::PALETTE;
use k210_console::console::{Color, Console, ScreenImage, DISP_HEIGHT, DISP_WIDTH};
use k210_console::cp437;
use k210_console::palette_xterm256::PALETTE;
/** Connect pins to internal functions */
fn io_mux_init() {
@ -120,7 +117,7 @@ fn main() -> ! {
let spi = p.SPI0.constrain();
let mut lcd = LCD::new(spi);
lcd.init();
lcd.set_direction(lcd::direction::YX_RLDU);
lcd.set_direction(lcd::direction::YX_LRUD);
lcd.clear(lcd_colors::PURPLE);
let mut image: ScreenImage = [0; DISP_WIDTH * DISP_HEIGHT / 2];

4
rust/weather/.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
/target
**/*.rs.bk
# Do not check in secrets file
config.rs

16
rust/weather/Cargo.toml Normal file
View File

@ -0,0 +1,16 @@
[package]
name = "weather"
version = "0.1.0"
authors = ["W.J. van der Laan <laanwj@protonmail.com>"]
edition = "2018"
[dependencies]
embedded-hal = { version = "0.2.1", features = ["unproven"] }
nb = "0.1.1"
riscv-rt = "0.5.0"
k210-hal = "0.1.0"
riscv = "0.5"
k210-shared = { path = "../k210-shared" }
k210-console = { path = "../k210-console" }
esp8266at = { path = "../esp8266at", default-features = false }
nom = { version = "4", default-features = false }

15
rust/weather/README.md Normal file
View File

@ -0,0 +1,15 @@
# `weather`
Uses the ESP8285 WiFi chip of the Maix Go to fetch weather data from
[wttr.in](https://wttr.in) and print it to the display using `k210-console`.
As it needs to connect to an access point first, this needs configuration of one
to connect to in `src/config.rs`:
```bash
cp src/config.rs.example src/config.rs
vim src/config.rs # ...
```
Set `<ap name>` and `<ap password>` accordingly. Do not check in `src/config.rs` !
(gitignore settings should prevent this)

View File

@ -0,0 +1,8 @@
/** Secrets */
/** Access point name */
pub const APNAME: &str = "<ap name>";
/** Access point password */
pub const APPASS: &str = "<ap password>";

236
rust/weather/src/main.rs Normal file
View File

@ -0,0 +1,236 @@
#![allow(dead_code)]
#![allow(non_snake_case)]
#![allow(non_camel_case_types)]
#![no_std]
#![no_main]
use core::str;
use embedded_hal::serial;
use esp8266at::handler::{NetworkEvent, SerialNetworkHandler};
use esp8266at::response::{parse_response, ConnectionType};
use esp8266at::traits::{self, Write};
use k210_hal::pac;
use k210_hal::prelude::*;
use k210_hal::stdout::Stdout;
use k210_shared::board::def::io;
use k210_shared::board::lcd::{self, LCD, LCDHL};
use k210_shared::soc::fpioa;
use k210_shared::soc::gpio;
use k210_shared::soc::gpiohs;
use k210_shared::soc::sleep::usleep;
use k210_shared::soc::spi::SPIExt;
use k210_shared::soc::sysctl;
use nb::block;
use nom::Offset;
use riscv::register::mcycle;
use riscv_rt::entry;
use k210_console::console::{Console, ScreenImage, DISP_HEIGHT, DISP_WIDTH};
mod config;
const DEFAULT_BAUD: u32 = 115_200;
const TIMEOUT: usize = 390_000_000 * 40 / 115200;
struct WriteAdapter<'a, TX>
where
TX: serial::Write<u8>,
{
tx: &'a mut TX,
}
impl<'a, TX> WriteAdapter<'a, TX>
where
TX: serial::Write<u8>,
TX::Error: core::fmt::Debug,
{
fn new(tx: &'a mut TX) -> Self {
Self { tx }
}
}
impl<'a, TX> traits::Write for WriteAdapter<'a, TX>
where
TX: serial::Write<u8>,
TX::Error: core::fmt::Debug,
{
type Error = TX::Error;
fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error> {
for ch in buf {
block!(self.tx.write(*ch))?;
}
Ok(())
}
}
/** Connect pins to internal functions */
fn io_init() {
/* Init SPI IO map and function settings */
fpioa::set_function(
io::LCD_RST.into(),
fpioa::function::gpiohs(lcd::RST_GPIONUM),
);
fpioa::set_io_pull(io::LCD_RST.into(), fpioa::pull::DOWN); // outputs must be pull-down
fpioa::set_function(io::LCD_DC.into(), fpioa::function::gpiohs(lcd::DCX_GPIONUM));
fpioa::set_io_pull(io::LCD_DC.into(), fpioa::pull::DOWN);
fpioa::set_function(io::LCD_CS.into(), fpioa::function::SPI0_SS3);
fpioa::set_function(io::LCD_WR.into(), fpioa::function::SPI0_SCLK);
sysctl::set_spi0_dvp_data(true);
/* Set dvp and spi pin to 1.8V */
sysctl::set_power_mode(sysctl::power_bank::BANK6, sysctl::io_power_mode::V18);
sysctl::set_power_mode(sysctl::power_bank::BANK7, sysctl::io_power_mode::V18);
}
#[entry]
fn main() -> ! {
let p = pac::Peripherals::take().unwrap();
let clocks = k210_hal::clock::Clocks::new();
usleep(200000);
io_init();
// Configure UARTHS (→host)
let mut serial = p.UARTHS.constrain(DEFAULT_BAUD.bps(), &clocks);
let (mut tx, mut rx) = serial.split();
let mut debug = Stdout(&mut tx);
// Configure UART1 (→WIFI)
sysctl::clock_enable(sysctl::clock::UART1);
sysctl::reset(sysctl::reset::UART1);
fpioa::set_function(io::WIFI_RX as u8, fpioa::function::UART1_TX);
fpioa::set_function(io::WIFI_TX as u8, fpioa::function::UART1_RX);
fpioa::set_function(io::WIFI_EN as u8, fpioa::function::GPIOHS8);
fpioa::set_io_pull(io::WIFI_EN as u8, fpioa::pull::DOWN);
gpiohs::set_pin(8, true);
gpiohs::set_direction(8, gpio::direction::OUTPUT);
let mut wifi_serial = p.UART1.constrain(DEFAULT_BAUD.bps(), &clocks);
let (mut wtx, mut wrx) = wifi_serial.split();
let mut wa = WriteAdapter::new(&mut wtx);
let mut sh = SerialNetworkHandler::new(&mut wa, config::APNAME.as_bytes(), config::APPASS.as_bytes());
// LCD ini
let spi = p.SPI0.constrain();
let mut lcd = LCD::new(spi);
lcd.init();
lcd.set_direction(lcd::direction::YX_LRUD);
let mut console: Console = Console::new();
let mut i:u16 = 0;
writeln!(console, "\x1b[48;2;128;192;255;38;5;0m WEATHER \x1b[0m \x1b[38;2;128;128;128mfetching...\x1b[0m").unwrap();
// Start off connection process state machine
sh.start(false);
writeln!(console, "∙ Connecting to AP").unwrap();
let mut serial_buf = [0u8; 2560]; // 2048 + some
let mut ofs: usize = 0;
let mut cur_link = 0;
loop {
if console.dirty {
let mut image: ScreenImage = [0; DISP_WIDTH * DISP_HEIGHT / 2];
console.render(&mut image);
lcd.draw_picture(0, 0, DISP_WIDTH as u16, DISP_HEIGHT as u16, &image);
console.dirty = false;
}
// Receive byte into buffer
if let Ok(ch) = wrx.read() {
let ofs0 = ofs;
serial_buf[ofs] = ch;
ofs += 1;
let mut lastrecv = mcycle::read();
loop {
// Read until we stop receiving for a certain duration
// This is a hack around the fact that in the time that the parser runs,
// more than one FIFO full of characters can be received so characters could be
// lost. The right way would be to receive in an interrupt handler, but,
// we don't have that yet.
if let Ok(ch) = wrx.read() {
serial_buf[ofs] = ch;
ofs += 1;
lastrecv = mcycle::read();
} else if (mcycle::read().wrapping_sub(lastrecv)) >= TIMEOUT {
break;
}
}
//writeln!(debug, "ofs: {} received {} chars {:?}", ofs0, ofs - ofs0,
// &serial_buf[ofs0..ofs]).unwrap();
// Loop as long as there's something in the buffer to parse, starting at the
// beginning
let mut start = 0;
while start < ofs {
// try parsing
let tail = &serial_buf[start..ofs];
let erase = match parse_response(tail) {
Ok((residue, resp)) => {
sh.message(&resp, &mut |port, ev, debug| {
match ev {
NetworkEvent::Ready => {
writeln!(console, "∙ Connected to AP").unwrap();
cur_link = port.connect(ConnectionType::TCP, b"wttr.in", 80).unwrap();
writeln!(console, "\x1b[38;5;141m[{}]\x1b[0m Opening TCP conn", cur_link).unwrap();
}
NetworkEvent::Error => {
writeln!(console, "∙ Could not connect to AP").unwrap();
}
NetworkEvent::ConnectionEstablished(link) => {
if link == cur_link {
writeln!(console, "\x1b[38;5;141m[{}]\x1b[0m Sending HTTP request", link).unwrap();
port.write_all(b"GET /?0qA HTTP/1.1\r\nHost: wttr.in\r\nConnection: close\r\nUser-Agent: Weather-Spy\r\n\r\n").unwrap();
port.send(link).unwrap();
}
}
NetworkEvent::Data(link, data) => {
// write!(debug, "{}", str::from_utf8(data).unwrap());
if link == cur_link {
console.puts(str::from_utf8(data).unwrap_or("???"));
}
}
NetworkEvent::ConnectionClosed(link) => {
writeln!(console, "\x1b[38;5;141m[{}]\x1b[0m \x1b[38;2;100;100;100m[closed]\x1b[0m", link).unwrap();
}
_ => { }
}
}, &mut debug).unwrap();
tail.offset(residue)
}
Err(nom::Err::Incomplete(_)) => {
// Incomplete, ignored, just retry after a new receive
0
}
Err(err) => {
writeln!(debug, "err: {:?}", err).unwrap();
// Erase unparseable data to next line, if line is complete
if let Some(ofs) = tail.iter().position(|&x| x == b'\n') {
ofs + 1
} else {
// If not, retry next time
0
}
}
};
if erase == 0 {
// End of input or remainder unparseable
break;
}
start += erase;
}
// Erase everything before new starting offset
for i in start..ofs {
serial_buf[i - start] = serial_buf[i];
}
ofs -= start;
}
/*
if let Ok(ch) = rx.read() {
let _res = block!(wtx.write(ch));
}
*/
}
}