Skip to content

Commit c312705

Browse files
jonathanpallantthejpster
authored andcommitted
Working on adding keyboard bytes to the SPI interface
1 parent d395bdd commit c312705

File tree

5 files changed

+237
-26
lines changed

5 files changed

+237
-26
lines changed

Cargo.toml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
[workspace]
2+
3+
# Include all the generic library crates
4+
members = [
5+
"neotron-bmc-protocol",
6+
"neotron-bmc-commands"
7+
]
8+
9+
# Exclude the BMC firmwares as they build using different targets/features
10+
exclude = [
11+
"neotron-bmc-pico",
12+
"neotron-bmc-nucleo",
13+
]

neotron-bmc-commands/Cargo.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[package]
2+
name = "neotron-bmc-commands"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7+
8+
[dependencies]

neotron-bmc-commands/src/lib.rs

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
//! # Neotron BMC Commands
2+
//!
3+
//! Definitions of all the commands supported by the BMC.
4+
5+
#![no_std]
6+
7+
#[derive(Debug, Copy, Clone)]
8+
#[repr(u8)]
9+
pub enum Command {
10+
/// # Protocol Version
11+
/// The NBMC protocol version, [1, 0, 0]
12+
/// * Length: 3
13+
/// * Mode: RO
14+
ProtocolVersion = 0x00,
15+
/// # Firmware Version
16+
/// The NBMC firmware version, as a null-padded UTF-8 string
17+
/// * Length: 32
18+
/// * Mode: RO
19+
FirmwareVersion = 0x01,
20+
/// # Interrupt Status
21+
/// Which interrupts are currently active, as a bitmask.
22+
/// * Length: 2
23+
/// * Mode: R/W1C
24+
InterruptStatus = 0x10,
25+
/// # Interrupt Control
26+
/// Which interrupts are currently enabled, as a bitmask.
27+
/// * Length: 2
28+
/// * Mode: R/W
29+
InterruptControl = 0x11,
30+
/// # Button Status
31+
/// The current state of the buttons
32+
/// * Length: 1
33+
/// * Mode: RO
34+
ButtonStatus = 0x20,
35+
/// # System Temperature
36+
/// Temperature in °C, as an `i8`
37+
/// * Length: 1
38+
/// * Mode: RO
39+
SystemTemperature = 0x21,
40+
/// # System Voltage (Standby 3.3V rail)
41+
/// Voltage in Volts/32, as a `u8`
42+
/// * Length: 1
43+
/// * Mode: RO
44+
SystemVoltage33S = 0x22,
45+
/// # System Voltage (Main 3.3V rail)
46+
/// Voltage in Volts/32, as a `u8`
47+
/// * Length: 1
48+
/// * Mode: RO
49+
SystemVoltage33 = 0x23,
50+
/// # System Voltage (5.0V rail)
51+
/// Voltage in Volts/32, as a `u8`
52+
/// * Length: 1
53+
/// * Mode: RO
54+
SystemVoltage55 = 0x24,
55+
/// # Power Control
56+
/// Enable/disable the power supply
57+
/// * Length: 1
58+
/// * Mode: R/W
59+
PowerControl = 0x25,
60+
/// # UART Receive/Transmit Buffer
61+
/// Data received/to be sent over the UART
62+
/// * Length: up to 64
63+
/// * Mode: FIFO
64+
UartBuffer = 0x30,
65+
/// # UART FIFO Control
66+
/// Settings for the UART FIFO
67+
/// * Length: 1
68+
/// * Mode: R/W
69+
UartFifoControl = 0x31,
70+
/// # UART Control
71+
/// Settings for the UART
72+
/// * Length: 1
73+
/// * Mode: R/W
74+
UartControl = 0x32,
75+
/// # UART Status
76+
/// The current state of the UART
77+
/// * Length: 1
78+
/// * Mode: R/W1C
79+
UartStatus = 0x33,
80+
/// # UART Baud Rate
81+
/// The UART baud rate in bps, as a `u32le`
82+
/// * Length: 4
83+
/// * Mode: R/W
84+
UartBaudRate = 0x34,
85+
/// # PS/2 Keyboard Receive/Transmit Buffer
86+
/// Data received/to be sent over the PS/2 keyboard port
87+
/// * Length: up to 16
88+
/// * Mode: FIFO
89+
Ps2KbBuffer = 0x40,
90+
/// # PS/2 Keyboard Control
91+
/// Settings for the PS/2 Keyboard port
92+
/// * Length: 1
93+
/// * Mode: R/W
94+
Ps2KbControl = 0x41,
95+
/// # PS/2 Keyboard Status
96+
/// Current state of the PS/2 Keyboard port
97+
/// * Length: 1
98+
/// * Mode: R/W1C
99+
Ps2KbStatus = 0x42,
100+
/// # PS/2 Mouse Receive/Transmit Buffer
101+
/// Data received/to be sent over the PS/2 Mouse port
102+
/// * Length: up to 16
103+
/// * Mode: FIFO
104+
Ps2MouseBuffer = 0x50,
105+
/// # PS/2 Mouse Control
106+
/// Settings for the PS/2 Mouse port
107+
/// * Length: 1
108+
/// * Mode: R/W
109+
Ps2MouseControl = 0x51,
110+
/// # PS/2 Mouse Status
111+
/// Current state of the PS/2 Mouse port
112+
/// * Length: 1
113+
/// * Mode: R/W1C
114+
Ps2MouseStatus = 0x52,
115+
/// # I²C Receive/Transmit Buffer
116+
/// Data received/to be sent over the I²C Bus
117+
/// * Length: up to 16
118+
/// * Mode: FIFO
119+
I2cBuffer = 0x60,
120+
/// # I²C FIFO Control
121+
/// Settings for the I²C FIFO
122+
/// * Length: 1
123+
/// * Mode: R/W
124+
I2cFifoControl = 0x61,
125+
/// # I²C Control
126+
/// Settings for the I²C Bus
127+
/// * Length: 1
128+
/// * Mode: R/W
129+
I2cControl = 0x62,
130+
/// # I²C Status
131+
/// Current state of the I²C Bus
132+
/// * Length: 1
133+
/// * Mode: R/W1C
134+
I2cStatus = 0x63,
135+
/// # I²C Baud Rate
136+
/// The I²C clock rate in Hz, as a `u32le`
137+
/// * Length: 4
138+
/// * Mode: R/W
139+
I2cBaudRate = 0x64,
140+
}
141+
142+
impl Command {
143+
pub fn parse(byte: u8) -> Option<Command> {
144+
match byte {
145+
0x00 => Some(Command::ProtocolVersion),
146+
0x01 => Some(Command::FirmwareVersion),
147+
0x10 => Some(Command::InterruptStatus),
148+
0x11 => Some(Command::InterruptControl),
149+
0x20 => Some(Command::ButtonStatus),
150+
0x21 => Some(Command::SystemTemperature),
151+
0x22 => Some(Command::SystemVoltage33S),
152+
0x23 => Some(Command::SystemVoltage33),
153+
0x24 => Some(Command::SystemVoltage55),
154+
0x25 => Some(Command::PowerControl),
155+
0x30 => Some(Command::UartBuffer),
156+
0x31 => Some(Command::UartFifoControl),
157+
0x32 => Some(Command::UartControl),
158+
0x33 => Some(Command::UartStatus),
159+
0x34 => Some(Command::UartBaudRate),
160+
0x40 => Some(Command::Ps2KbBuffer),
161+
0x41 => Some(Command::Ps2KbControl),
162+
0x42 => Some(Command::Ps2KbStatus),
163+
0x50 => Some(Command::Ps2MouseBuffer),
164+
0x51 => Some(Command::Ps2MouseControl),
165+
0x52 => Some(Command::Ps2MouseStatus),
166+
0x60 => Some(Command::I2cBuffer),
167+
0x61 => Some(Command::I2cFifoControl),
168+
0x62 => Some(Command::I2cControl),
169+
0x63 => Some(Command::I2cStatus),
170+
0x64 => Some(Command::I2cBaudRate),
171+
_ => None,
172+
}
173+
}
174+
}

neotron-bmc-pico/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ heapless= "0.7"
1414
panic-probe = { version = "0.3", features = ["print-defmt"] }
1515
stm32f0xx-hal = { version = "0.18", features = ["stm32f030x6", "rt"] }
1616
neotron-bmc-protocol = { version = "0.1", path = "../neotron-bmc-protocol" }
17+
neotron-bmc-commands = { version = "0.1", path = "../neotron-bmc-commands" }
1718
systick-monotonic = "1.0"
1819
embedded-hal = "*"
1920

neotron-bmc-pico/src/main.rs

Lines changed: 41 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ use stm32f0xx_hal::{
2323
serial,
2424
};
2525

26+
use neotron_bmc_commands::Command;
2627
use neotron_bmc_pico as _;
2728
use neotron_bmc_protocol as proto;
2829

@@ -126,9 +127,6 @@ mod app {
126127
/// The external interrupt peripheral
127128
#[lock_free]
128129
exti: pac::EXTI,
129-
/// Our register state
130-
#[lock_free]
131-
register_state: RegisterState,
132130
/// Read messages here
133131
#[lock_free]
134132
msg_q_out: Consumer<'static, Message, 8>,
@@ -320,10 +318,6 @@ mod app {
320318
ps2_dat0,
321319
_ps2_dat1,
322320
exti: dp.EXTI,
323-
register_state: RegisterState {
324-
firmware_version:
325-
*b"Neotron BMC v0.3.1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
326-
},
327321
msg_q_out,
328322
msg_q_in,
329323
spi,
@@ -342,14 +336,21 @@ mod app {
342336
/// Our idle task.
343337
///
344338
/// This task is called when there is nothing else to do.
345-
#[idle(shared = [msg_q_out, msg_q_in, spi, register_state])]
339+
#[idle(shared = [msg_q_out, msg_q_in, spi])]
346340
fn idle(mut ctx: idle::Context) -> ! {
341+
let mut register_state = RegisterState {
342+
firmware_version:
343+
*b"Neotron BMC v0.3.1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
344+
};
345+
347346
defmt::info!("Idle is running...");
348347
loop {
349348
match ctx.shared.msg_q_out.dequeue() {
350349
Some(Message::Ps2Data0(word)) => {
351350
if let Some(byte) = neotron_bmc_pico::ps2::Ps2Decoder::check_word(word) {
352351
defmt::info!("< KB 0x{:x}", byte);
352+
// TODO: Copy byte to software buffer and turn PS/2 bus off
353+
// if buffer is full
353354
} else {
354355
defmt::warn!("< Bad KB 0x{:x}", word);
355356
}
@@ -366,24 +367,10 @@ mod app {
366367
Some(Message::ResetButtonShortPress) => {}
367368
Some(Message::SpiRequest(req)) => match req.request_type {
368369
proto::RequestType::Read | proto::RequestType::ReadAlt => {
369-
let rsp = match req.register {
370-
0x00 => {
371-
let length = req.length_or_data as usize;
372-
if length > ctx.shared.register_state.firmware_version.len() {
373-
proto::Response::new_without_data(
374-
proto::ResponseResult::BadLength,
375-
)
376-
} else {
377-
let bytes = &ctx.shared.register_state.firmware_version;
378-
proto::Response::new_ok_with_data(&bytes[0..length])
379-
}
380-
}
381-
_ => proto::Response::new_without_data(
382-
proto::ResponseResult::BadRegister,
383-
),
384-
};
385-
ctx.shared.spi.lock(|spi| {
386-
spi.set_transmit_sendable(&rsp).unwrap();
370+
process_command(req, &mut register_state, |rsp| {
371+
ctx.shared.spi.lock(|spi| {
372+
spi.set_transmit_sendable(rsp).unwrap();
373+
});
387374
});
388375
}
389376
_ => {
@@ -633,6 +620,34 @@ mod app {
633620
}
634621
}
635622

623+
/// Process an incoming command, converting a request into a response.
624+
fn process_command<F>(req: proto::Request, register_state: &mut RegisterState, rsp_handler: F)
625+
where
626+
F: FnOnce(&proto::Response),
627+
{
628+
let rsp = match Command::parse(req.register) {
629+
Some(Command::ProtocolVersion) => {
630+
let length = req.length_or_data as usize;
631+
if length != 3 {
632+
proto::Response::new_without_data(proto::ResponseResult::BadLength)
633+
} else {
634+
proto::Response::new_ok_with_data(&[0, 1, 1])
635+
}
636+
}
637+
Some(Command::FirmwareVersion) => {
638+
let length = req.length_or_data as usize;
639+
if length > register_state.firmware_version.len() {
640+
proto::Response::new_without_data(proto::ResponseResult::BadLength)
641+
} else {
642+
let bytes = &register_state.firmware_version;
643+
proto::Response::new_ok_with_data(&bytes[0..length])
644+
}
645+
}
646+
_ => proto::Response::new_without_data(proto::ResponseResult::BadRegister),
647+
};
648+
rsp_handler(&rsp);
649+
}
650+
636651
// TODO: Pins we haven't used yet
637652
// SPI pins
638653
// spi_clk: gpioa.pa5.into_alternate_af0(cs),

0 commit comments

Comments
 (0)