1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
use apigpio::*;
use apigpio::Level::*;
use tokio::time::{delay_for,Duration};
use tokio::{select,task};
use picollar::ledpins::{RGB,FLASH_SPECIAL,FLASH_NORMAL};
use picollar::local::{SEVERITIES,BUTTON_DEBOUNCE};
use std::result;
use anyhow::anyhow;
use std::fs::File;
use std::io::{BufWriter,Write};
fn level2rppal(l : Level) -> rppal::gpio::Level {
if l==H { rppal::gpio::Level::High } else { rppal::gpio::Level::Low }
}
type Rppal = rppal::gpio::Gpio;
const PIN_SETTLE_DELAY : Duration = BUTTON_DEBOUNCE;
async fn read_initial(gpio : &Rppal) -> result::Result<bool, anyhow::Error> {
let filename = std::env::args().nth(2)
.ok_or_else(|| anyhow!("missing argument for initial pins path"))?;
let pins : result::Result<Vec<_>, anyhow::Error> =
SEVERITIES.iter().map(|s| s.0).flatten()
.map(|&p| {
let mut g = gpio
.get(p as u8)
.expect("get initial pin")
.into_input_pullup();
g.set_reset_on_drop(false);
Ok((p, g))
}).collect();
let pins = pins?;
delay_for(PIN_SETTLE_DELAY).await;
let mut o = BufWriter::new(File::create(filename)?);
let mut special = false;
for (p, g) in &pins {
let l = g.is_high();
writeln!(o,"{} = {}", p, l as u8)?;
if !l { special = true }
}
o.into_inner()?;
Ok(special)
}
#[tokio::main]
async fn main(){
println!("bootup: hello world");
let pipepath = std::env::args().nth(1).expect("need pipe path argument");
assert!(!pipepath.starts_with("-"));
let mut lev = H;
let gpio = Rppal::new().expect("rpal open");
let mut pins : Vec<_> = RGB.iter().map(|&p| {
let mut g = gpio
.get(p as u8)
.expect("get pin")
.into_output();
g.set_reset_on_drop(false);
g
}).collect();
let openpipe = task::spawn_blocking(||{ File::create(pipepath) });
pin_utils::pin_mut!(openpipe);
let initial_special = read_initial(&gpio).await.or_else(|e|{
println!("bootup: warning: could not read initial severities: {}", e);
<result::Result<bool,()>>::Ok(false)
}).unwrap();
let flash_duration =
if initial_special { FLASH_SPECIAL }
else { FLASH_NORMAL };
println!("bootup: in progress");
pins[2].write(rppal::gpio::Level::Low);
select! {
_ = async {
loop {
pins[0].write(level2rppal(lev));
pins[1].write(level2rppal(lev));
lev = !lev;
delay_for(flash_duration).await;
}
} => panic!(),
f = openpipe => {
f.expect("open pipe task").expect("open pipe");
}
}
println!("bootup: initial phase complete");
pins[0].write(level2rppal(H));
pins[1].write(level2rppal(L));
}