Skip to content

Commit b35f636

Browse files
authored
Merge pull request #28 from dotcypress/feature/shell-env
Update LED Shell example
2 parents 37a0225 + 7aa40d7 commit b35f636

File tree

2 files changed

+107
-107
lines changed

2 files changed

+107
-107
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ embedded-sdmmc = { version = "0.3.0", optional = true }
2626
riscv-rt = "0.8.0"
2727
panic-halt = "0.2.0"
2828
embedded-graphics = "0.7.1"
29-
ushell = "0.3.3"
29+
ushell = "0.3.5"
3030

3131
[features]
3232
lcd = ["st7735-lcd"]

examples/led_shell.rs

Lines changed: 106 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -15,36 +15,6 @@ use longan_nano::{
1515
use riscv_rt::entry;
1616
use ushell::{autocomplete::*, history::*, *};
1717

18-
const MAX_COMMAND_LEN: usize = 16;
19-
const HISTORY_SIZE: usize = 4;
20-
const COMMANDS: usize = 5;
21-
22-
const SHELL_PROMPT: &str = "#> ";
23-
const CR: &str = "\r\n";
24-
const HELP: &str = "\r\n\
25-
\x1b[31mL\x1b[32mE\x1b[34mD\x1b[33m Shell\x1b[0m\r\n\r\n\
26-
USAGE:\r\n\
27-
\tcommand [arg]\r\n\r\n\
28-
COMMANDS:\r\n\
29-
\ton <ch> Switch led channel on [r,g,b,a]\r\n\
30-
\toff <ch> Switch led channel off [r,g,b,a]\r\n\
31-
\tstatus Get leds status\r\n\
32-
\tclear Clear screen\r\n\
33-
\thelp Print this message\r\n
34-
";
35-
36-
struct Context {
37-
red: RED,
38-
green: GREEN,
39-
blue: BLUE,
40-
shell: UShell<
41-
ushell::Serial<u8, Tx<USART0>, Rx<USART0>>,
42-
StaticAutocomplete<{ COMMANDS }>,
43-
LRUHistory<{ MAX_COMMAND_LEN }, { HISTORY_SIZE }>,
44-
{ MAX_COMMAND_LEN },
45-
>,
46-
}
47-
4818
#[entry]
4919
fn main() -> ! {
5020
let dp = pac::Peripherals::take().unwrap();
@@ -62,6 +32,11 @@ fn main() -> ! {
6232
let gpioa = dp.GPIOA.split(&mut rcu);
6333
let gpioc = dp.GPIOC.split(&mut rcu);
6434

35+
let (mut red, mut green, mut blue) = rgb(gpioc.pc13, gpioa.pa1, gpioa.pa2);
36+
red.off();
37+
green.off();
38+
blue.off();
39+
6540
let tx = gpioa.pa9.into_alternate_push_pull();
6641
let rx = gpioa.pa10.into_floating_input();
6742

@@ -72,90 +47,115 @@ fn main() -> ! {
7247
};
7348
let uart = serial::Serial::new(dp.USART0, (tx, rx), config, &mut afio, &mut rcu);
7449
let (tx, rx) = uart.split();
50+
let serial = ushell::Serial::from_parts(tx, rx);
7551

7652
let autocomplete = StaticAutocomplete(["clear", "help", "status", "off ", "on "]);
77-
let history = LRUHistory::default();
78-
let shell = UShell::new(ushell::Serial::from_parts(tx, rx), autocomplete, history);
79-
80-
let (mut red, mut green, mut blue) = rgb(gpioc.pc13, gpioa.pa1, gpioa.pa2);
81-
red.off();
82-
green.off();
83-
blue.off();
84-
85-
let mut ctx = Context {
86-
shell,
87-
red,
88-
green,
89-
blue,
90-
};
53+
let mut shell = UShell::new(serial, autocomplete, LRUHistory::default());
54+
let mut env = Env { red, green, blue };
9155

9256
loop {
93-
poll_serial(&mut ctx);
57+
shell.spin(&mut env).ok();
9458
}
9559
}
9660

97-
fn poll_serial(ctx: &mut Context) {
98-
match ctx.shell.poll() {
99-
Ok(Some(Input::Command((cmd, args)))) => {
100-
match cmd {
101-
"help" => {
102-
ctx.shell.write_str(HELP).ok();
103-
}
104-
"clear" => {
105-
ctx.shell.clear().ok();
106-
}
107-
"status" => {
108-
let red = if ctx.red.is_on() { "On" } else { "Off" };
109-
let green = if ctx.green.is_on() { "On" } else { "Off" };
110-
let blue = if ctx.blue.is_on() { "On" } else { "Off" };
111-
write!(
112-
ctx.shell,
113-
"{0:}Red: {1:}{0:}Green: {2:}{0:}Blue: {3:}{0:}",
114-
CR, red, green, blue,
115-
)
116-
.ok();
117-
}
118-
"on" => {
119-
match args {
120-
"r" | "red" => ctx.red.on(),
121-
"g" | "green" => ctx.green.on(),
122-
"b" | "blue" => ctx.blue.on(),
123-
"a" | "all" => {
124-
ctx.red.on();
125-
ctx.green.on();
126-
ctx.blue.on();
127-
}
128-
_ => {
129-
write!(ctx.shell, "{0:}unsupported color channel", CR).ok();
130-
}
131-
}
132-
ctx.shell.write_str(CR).ok();
133-
}
134-
"off" => {
135-
match args {
136-
"r" | "red" => ctx.red.off(),
137-
"g" | "green" => ctx.green.off(),
138-
"b" | "blue" => ctx.blue.off(),
139-
"a" | "all" => {
140-
ctx.red.off();
141-
ctx.green.off();
142-
ctx.blue.off();
143-
}
144-
_ => {
145-
write!(ctx.shell, "{0:}unsupported color channel", CR).ok();
146-
}
147-
}
148-
ctx.shell.write_str(CR).ok();
149-
}
150-
"" => {
151-
ctx.shell.write_str(CR).ok();
152-
}
153-
_ => {
154-
write!(ctx.shell, "{0:}unsupported command{0:}", CR).ok();
155-
}
61+
const CMD_LEN: usize = 16;
62+
const HISTORY_SIZE: usize = 4;
63+
const COMMANDS: usize = 5;
64+
65+
type Serial = ushell::Serial<u8, Tx<USART0>, Rx<USART0>>;
66+
type Autocomplete = StaticAutocomplete<{ COMMANDS }>;
67+
type History = LRUHistory<{ CMD_LEN }, { HISTORY_SIZE }>;
68+
type Shell = UShell<Serial, Autocomplete, History, { CMD_LEN }>;
69+
70+
struct Env {
71+
red: RED,
72+
green: GREEN,
73+
blue: BLUE,
74+
}
75+
76+
type EnvResult = SpinResult<Serial, ()>;
77+
78+
impl Env {
79+
fn on_cmd(&mut self, shell: &mut Shell, args: &str) -> EnvResult {
80+
match args {
81+
"r" | "red" => self.red.on(),
82+
"g" | "green" => self.green.on(),
83+
"b" | "blue" => self.blue.on(),
84+
"a" | "all" => {
85+
self.red.on();
86+
self.green.on();
87+
self.blue.on();
88+
}
89+
_ => {
90+
write!(shell, "{0:}unsupported color channel", CR).ok();
15691
}
157-
ctx.shell.write_str(SHELL_PROMPT).ok();
15892
}
159-
_ => {}
93+
shell.write_str(CR)?;
94+
Ok(())
95+
}
96+
97+
fn off_cmd(&mut self, shell: &mut Shell, args: &str) -> EnvResult {
98+
match args {
99+
"r" | "red" => self.red.off(),
100+
"g" | "green" => self.green.off(),
101+
"b" | "blue" => self.blue.off(),
102+
"a" | "all" => {
103+
self.red.off();
104+
self.green.off();
105+
self.blue.off();
106+
}
107+
_ => {
108+
write!(shell, "{0:}unsupported color channel", CR).ok();
109+
}
110+
}
111+
shell.write_str(CR)?;
112+
Ok(())
113+
}
114+
115+
fn status_cmd(&mut self, shell: &mut Shell, _args: &str) -> EnvResult {
116+
let red = if self.red.is_on() { "On" } else { "Off" };
117+
let green = if self.green.is_on() { "On" } else { "Off" };
118+
let blue = if self.blue.is_on() { "On" } else { "Off" };
119+
write!(
120+
shell,
121+
"{0:}Red: {1:}{0:}Green: {2:}{0:}Blue: {3:}{0:}",
122+
CR, red, green, blue,
123+
)?;
124+
125+
Ok(())
160126
}
161127
}
128+
129+
impl Environment<Serial, Autocomplete, History, (), { CMD_LEN }> for Env {
130+
fn command(&mut self, shell: &mut Shell, cmd: &str, args: &str) -> EnvResult {
131+
match cmd {
132+
"clear" => shell.clear()?,
133+
"help" => shell.write_str(HELP)?,
134+
"status" => self.status_cmd(shell, args)?,
135+
"on" => self.on_cmd(shell, args)?,
136+
"off" => self.off_cmd(shell, args)?,
137+
"" => shell.write_str(CR)?,
138+
_ => write!(shell, "{0:}unsupported command: \"{1:}\"{0:}", CR, cmd)?,
139+
}
140+
shell.write_str(SHELL_PROMPT)?;
141+
Ok(())
142+
}
143+
144+
fn control(&mut self, _shell: &mut Shell, _code: u8) -> EnvResult {
145+
Ok(())
146+
}
147+
}
148+
149+
const SHELL_PROMPT: &str = "#> ";
150+
const CR: &str = "\r\n";
151+
const HELP: &str = "\r\n\
152+
\x1b[31mL\x1b[32mE\x1b[34mD\x1b[33m Shell\x1b[0m\r\n\r\n\
153+
USAGE:\r\n\
154+
\x20 command [arg]\r\n\r\n\
155+
COMMANDS:\r\n\
156+
\x20 on <ch> Switch led channel on [r,g,b,a]\r\n\
157+
\x20 off <ch> Switch led channel off [r,g,b,a]\r\n\
158+
\x20 status Get leds status\r\n\
159+
\x20 clear Clear screen\r\n\
160+
\x20 help Print this message\r\n
161+
";

0 commit comments

Comments
 (0)