Skip to content

Commit 208fa4b

Browse files
committed
Cleaning up
1 parent e915f36 commit 208fa4b

File tree

2 files changed

+96
-77
lines changed

2 files changed

+96
-77
lines changed

src/main.rs

Lines changed: 93 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ pub enum DcPowerState {
5555
/// * Stop Bit
5656
#[derive(Debug)]
5757
pub struct Ps2Decoder {
58-
bit_count: u8,
58+
bit_mask: u16,
5959
collector: u16,
6060
}
6161

@@ -71,22 +71,22 @@ mod app {
7171
use fugit::ExtU32;
7272

7373
#[shared]
74-
struct Resources {
74+
struct Shared {
7575
/// The power LED (D1101)
7676
#[lock_free]
7777
led_power: PB0<Output<PushPull>>,
7878
/// The status LED (D1102)
7979
#[lock_free]
80-
led_status: PB1<Output<PushPull>>,
80+
_led_status: PB1<Output<PushPull>>,
8181
/// The FTDI UART header (J105)
8282
#[lock_free]
8383
serial: serial::Serial<pac::USART1, PA9<Alternate<AF1>>, PA10<Alternate<AF1>>>,
8484
/// The Clear-To-Send line on the FTDI UART header (which the serial object can't handle)
8585
#[lock_free]
86-
pin_uart_cts: PA11<Alternate<AF1>>,
86+
_pin_uart_cts: PA11<Alternate<AF1>>,
8787
/// The Ready-To-Receive line on the FTDI UART header (which the serial object can't handle)
8888
#[lock_free]
89-
pin_uart_rts: PA12<Alternate<AF1>>,
89+
_pin_uart_rts: PA12<Alternate<AF1>>,
9090
/// The power button
9191
#[lock_free]
9292
button_power: PF0<Input<PullUp>>,
@@ -108,25 +108,25 @@ mod app {
108108
ps2_clk0: PA15<Input<Floating>>,
109109
/// Clock pin for PS/2 Mouse port
110110
#[lock_free]
111-
ps2_clk1: PB3<Input<Floating>>,
111+
_ps2_clk1: PB3<Input<Floating>>,
112112
/// Data pin for PS/2 Keyboard port
113113
#[lock_free]
114114
ps2_dat0: PB4<Input<Floating>>,
115115
/// Data pin for PS/2 Mouse port
116116
#[lock_free]
117-
ps2_dat1: PB5<Input<Floating>>,
117+
_ps2_dat1: PB5<Input<Floating>>,
118118
/// The external interrupt peripheral
119119
#[lock_free]
120120
exti: pac::EXTI,
121121
/// Our register state
122122
#[lock_free]
123-
register_state: RegisterState,
123+
_register_state: RegisterState,
124124
/// Keyboard bytes sink
125125
#[lock_free]
126-
kb_c: Consumer<'static, u16, 8>,
126+
kb_q_out: Consumer<'static, u16, 8>,
127127
/// Keyboard bytes source
128128
#[lock_free]
129-
kb_p: Producer<'static, u16, 8>,
129+
kb_q_in: Producer<'static, u16, 8>,
130130
}
131131

132132
#[local]
@@ -135,10 +135,10 @@ mod app {
135135
press_button_power_short: debouncr::Debouncer<u8, debouncr::Repeat2>,
136136
/// Tracks power button state for long presses. 75ms x 16 = 1200ms is a long press
137137
press_button_power_long: debouncr::Debouncer<u16, debouncr::Repeat16>,
138+
/// Tracks reset button state for long presses. 75ms x 16 = 1200ms is a long press
139+
press_button_reset_long: debouncr::Debouncer<u16, debouncr::Repeat16>,
138140
/// Keyboard PS/2 decoder
139141
kb_decoder: Ps2Decoder,
140-
/// Mouse PS/2 decoder
141-
ms_decoder: Ps2Decoder,
142142
}
143143

144144
#[monotonic(binds = TIM2, default = true)]
@@ -151,7 +151,7 @@ mod app {
151151
/// * Task `led_power_blink` - blinks the LED
152152
/// * Task `button_poll` - checks the power and reset buttons
153153
#[init(local = [ queue: Queue<u16, 8> = Queue::new()])]
154-
fn init(ctx: init::Context) -> (Resources, Local, init::Monotonics) {
154+
fn init(ctx: init::Context) -> (Shared, Local, init::Monotonics) {
155155
defmt::info!("Neotron BMC version {:?} booting", VERSION);
156156

157157
let dp: pac::Peripherals = ctx.device;
@@ -172,21 +172,29 @@ mod app {
172172
let gpioa = dp.GPIOA.split(&mut rcc);
173173
let gpiob = dp.GPIOB.split(&mut rcc);
174174
let gpiof = dp.GPIOF.split(&mut rcc);
175+
// We have to have the closure return a tuple of all our configured
176+
// pins because by taking fields from `gpioa`, `gpiob`, etc, we leave
177+
// them as partial structures. This prevents us from having a call to
178+
// `disable_interrupts` for each pin. We can't simply do the `let foo
179+
// = ` inside the closure either, as the pins would be dropped when
180+
// the closure ended. So, we have this slightly awkward syntax
181+
// instead. Do ensure the pins and the variables line-up correctly;
182+
// order is important!
175183
let (
176184
uart_tx,
177185
uart_rx,
178-
pin_uart_cts,
179-
pin_uart_rts,
186+
_pin_uart_cts,
187+
_pin_uart_rts,
180188
mut led_power,
181-
mut led_status,
189+
mut _led_status,
182190
button_power,
183191
button_reset,
184192
mut pin_dc_on,
185193
mut pin_sys_reset,
186194
ps2_clk0,
187-
ps2_clk1,
195+
_ps2_clk1,
188196
ps2_dat0,
189-
ps2_dat1,
197+
_ps2_dat1,
190198
) = disable_interrupts(|cs| {
191199
(
192200
gpioa.pa9.into_alternate_af1(cs),
@@ -216,12 +224,8 @@ mod app {
216224

217225
serial.listen(serial::Event::Rxne);
218226

219-
led_power_blink::spawn().unwrap();
220-
221-
button_poll::spawn().unwrap();
222-
223227
led_power.set_low().unwrap();
224-
led_status.set_low().unwrap();
228+
_led_status.set_low().unwrap();
225229

226230
// Set EXTI15 to use PORT A (PA15)
227231
dp.SYSCFG.exticr4.write(|w| w.exti15().pa15());
@@ -231,52 +235,55 @@ mod app {
231235
dp.EXTI.emr.modify(|_r, w| w.mr15().set_bit());
232236
dp.EXTI.ftsr.modify(|_r, w| w.tr15().set_bit());
233237

238+
// Spawn the tasks that run all the time
239+
led_power_blink::spawn().unwrap();
240+
button_poll::spawn().unwrap();
241+
234242
defmt::info!("Init complete!");
235243

236-
let (kb_p, kb_c) = ctx.local.queue.split();
237-
238-
(
239-
Resources {
240-
serial,
241-
pin_uart_cts,
242-
pin_uart_rts,
243-
led_power,
244-
led_status,
245-
button_power,
246-
button_reset,
247-
state_dc_power_enabled: DcPowerState::Off,
248-
pin_dc_on,
249-
pin_sys_reset,
250-
ps2_clk0,
251-
ps2_clk1,
252-
ps2_dat0,
253-
ps2_dat1,
254-
exti: dp.EXTI,
255-
register_state: RegisterState {
256-
firmware_version: "Neotron BMC v0.0.0",
257-
},
258-
kb_p,
259-
kb_c,
260-
},
261-
Local {
262-
press_button_power_short: debouncr::debounce_2(false),
263-
press_button_power_long: debouncr::debounce_16(false),
264-
kb_decoder: Ps2Decoder::new(),
265-
ms_decoder: Ps2Decoder::new(),
244+
let (kb_q_in, kb_q_out) = ctx.local.queue.split();
245+
246+
let shared_resources = Shared {
247+
serial,
248+
_pin_uart_cts,
249+
_pin_uart_rts,
250+
led_power,
251+
_led_status,
252+
button_power,
253+
button_reset,
254+
state_dc_power_enabled: DcPowerState::Off,
255+
pin_dc_on,
256+
pin_sys_reset,
257+
ps2_clk0,
258+
_ps2_clk1,
259+
ps2_dat0,
260+
_ps2_dat1,
261+
exti: dp.EXTI,
262+
_register_state: RegisterState {
263+
firmware_version: concat!("Neotron BMC ", env!("CARGO_PKG_VERSION")),
266264
},
267-
init::Monotonics(mono),
268-
)
265+
kb_q_in,
266+
kb_q_out,
267+
};
268+
let local_resources = Local {
269+
press_button_power_short: debouncr::debounce_2(false),
270+
press_button_power_long: debouncr::debounce_16(false),
271+
press_button_reset_long: debouncr::debounce_16(false),
272+
kb_decoder: Ps2Decoder::new(),
273+
};
274+
let init = init::Monotonics(mono);
275+
(shared_resources, local_resources, init)
269276
}
270277

271278
/// Our idle task.
272279
///
273280
/// This task is called when there is nothing else to do. We
274281
/// do a little logging, then put the CPU to sleep waiting for an interrupt.
275-
#[idle(shared = [kb_c])]
282+
#[idle(shared = [kb_q_out])]
276283
fn idle(ctx: idle::Context) -> ! {
277284
defmt::info!("Idle is running...");
278285
loop {
279-
if let Some(word) = ctx.shared.kb_c.dequeue() {
286+
if let Some(word) = ctx.shared.kb_q_out.dequeue() {
280287
if let Some(byte) = Ps2Decoder::check_word(word) {
281288
defmt::info!("< KB {:x}", byte);
282289
} else {
@@ -294,15 +301,15 @@ mod app {
294301
#[task(
295302
binds = EXTI4_15,
296303
priority = 4,
297-
shared = [ps2_clk0, ps2_dat0, exti, kb_p],
304+
shared = [ps2_clk0, ps2_dat0, exti, kb_q_in],
298305
local = [kb_decoder]
299306
)]
300307
fn exti4_15_interrupt(ctx: exti4_15_interrupt::Context) {
301308
let data_bit = ctx.shared.ps2_dat0.is_high().unwrap();
302309
// Do we have a complete word (and if so, is the parity OK)?
303310
if let Some(data) = ctx.local.kb_decoder.add_bit(data_bit) {
304311
// Don't dump in the ISR - we're busy. Add it to this nice lockless queue instead.
305-
ctx.shared.kb_p.enqueue(data).unwrap();
312+
ctx.shared.kb_q_in.enqueue(data).unwrap();
306313
}
307314
// Clear the pending flag
308315
ctx.shared.exti.pr.write(|w| w.pr15().set_bit());
@@ -348,21 +355,27 @@ mod app {
348355
/// We poll them rather than setting up an interrupt as we need to debounce them, which involves waiting a short period and checking them again. Given that we have to do that, we might as well not bother with the interrupt.
349356
#[task(
350357
shared = [
351-
led_power, button_power, state_dc_power_enabled,
352-
pin_sys_reset, pin_dc_on
358+
led_power, button_power, button_reset,
359+
state_dc_power_enabled, pin_sys_reset, pin_dc_on
353360
],
354-
local = [ press_button_power_short, press_button_power_long ]
361+
local = [ press_button_power_short, press_button_power_long, press_button_reset_long ]
355362
)]
356363
fn button_poll(ctx: button_poll::Context) {
357-
// Poll button
358-
let pressed: bool = ctx.shared.button_power.is_low().unwrap();
364+
// Poll buttons
365+
let pwr_pressed: bool = ctx.shared.button_power.is_low().unwrap();
366+
let rst_pressed: bool = ctx.shared.button_reset.is_low().unwrap();
359367

360368
// Update state
361-
let short_edge = ctx.local.press_button_power_short.update(pressed);
362-
let long_edge = ctx.local.press_button_power_long.update(pressed);
369+
let pwr_short_edge = ctx.local.press_button_power_short.update(pwr_pressed);
370+
let pwr_long_edge = ctx.local.press_button_power_long.update(pwr_pressed);
371+
let rst_long_edge = ctx.local.press_button_reset_long.update(rst_pressed);
363372

364373
// Dispatch event
365-
match (long_edge, short_edge, *ctx.shared.state_dc_power_enabled) {
374+
match (
375+
pwr_long_edge,
376+
pwr_short_edge,
377+
*ctx.shared.state_dc_power_enabled,
378+
) {
366379
(None, Some(debouncr::Edge::Rising), DcPowerState::Off) => {
367380
defmt::info!("Power button pressed whilst off.");
368381
// Button pressed - power on system
@@ -392,11 +405,17 @@ mod app {
392405
}
393406
_ => {
394407
// Do nothing
395-
// TODO: Put system in reset here
396-
// TODO: Disable DC PSU here
397408
}
398409
}
399410

411+
if let Some(debouncr::Edge::Falling) = rst_long_edge {
412+
defmt::info!("Reset!");
413+
ctx.shared.pin_sys_reset.set_low().unwrap();
414+
// TODO: This pulse will be very short. We should spawn a task to
415+
// take it out of reset after about 100ms.
416+
ctx.shared.pin_sys_reset.set_high().unwrap();
417+
}
418+
400419
// Re-schedule the timer interrupt
401420
button_poll::spawn_after(DEBOUNCE_POLL_INTERVAL_MS.millis()).unwrap();
402421
}
@@ -405,22 +424,22 @@ mod app {
405424
impl Ps2Decoder {
406425
fn new() -> Ps2Decoder {
407426
Ps2Decoder {
408-
bit_count: 0,
427+
bit_mask: 1,
409428
collector: 0,
410429
}
411430
}
412431

413432
fn reset(&mut self) {
414-
self.bit_count = 0;
433+
self.bit_mask = 0;
415434
self.collector = 0;
416435
}
417436

418437
fn add_bit(&mut self, bit: bool) -> Option<u16> {
419438
if bit {
420-
self.collector |= 1 << self.bit_count;
439+
self.collector |= self.bit_mask;
421440
}
422-
self.bit_count += 1;
423-
if self.bit_count == 11 {
441+
self.bit_mask <<= 1;
442+
if self.bit_mask == 0b100000000000 {
424443
let result = self.collector;
425444
self.reset();
426445
Some(result)

src/monotonic.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@ impl<const FREQ: u32> MonoTimer<pac::TIM2, FREQ> {
2222
let rcc = &*pac::RCC::ptr();
2323

2424
// Enable timer
25-
rcc.apb1enr.modify(|_, w| w.tim3en().set_bit());
25+
rcc.apb1enr.modify(|_, w| w.tim2en().set_bit());
2626

2727
// Reset timer
28-
rcc.apb1rstr.modify(|_, w| w.tim3rst().set_bit());
29-
rcc.apb1rstr.modify(|_, w| w.tim3rst().clear_bit());
28+
rcc.apb1rstr.modify(|_, w| w.tim2rst().set_bit());
29+
rcc.apb1rstr.modify(|_, w| w.tim2rst().clear_bit());
3030
}
3131

3232
let prescaler = (clocks.pclk().0 / FREQ) - 1;

0 commit comments

Comments
 (0)