mirror of
https://github.com/hubaldv/bioz-firmware-rs.git
synced 2025-12-06 05:01:18 +00:00
Included lib for adg2128.
This commit is contained in:
59
Cargo.lock
generated
59
Cargo.lock
generated
@@ -39,14 +39,19 @@ dependencies = [
|
||||
name = "bioz-firmware-rs"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bitflags 2.9.1",
|
||||
"cortex-m",
|
||||
"cortex-m-rt",
|
||||
"defmt 1.0.1",
|
||||
"defmt-rtt",
|
||||
"embassy-embedded-hal",
|
||||
"embassy-executor",
|
||||
"embassy-stm32",
|
||||
"embassy-sync 0.7.0",
|
||||
"embassy-time",
|
||||
"embedded-hal 1.0.0",
|
||||
"panic-probe",
|
||||
"static_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -230,13 +235,14 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "embassy-embedded-hal"
|
||||
version = "0.3.0"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41fea5ef5bed4d3468dfd44f5c9fa4cda8f54c86d4fb4ae683eacf9d39e2ea12"
|
||||
checksum = "8578db196d74db92efdd5ebc546736dac1685499ee245b22eff92fa5e4b57945"
|
||||
dependencies = [
|
||||
"defmt 0.3.100",
|
||||
"defmt 1.0.1",
|
||||
"embassy-futures",
|
||||
"embassy-sync",
|
||||
"embassy-hal-internal 0.3.0",
|
||||
"embassy-sync 0.7.0",
|
||||
"embassy-time",
|
||||
"embedded-hal 0.2.7",
|
||||
"embedded-hal 1.0.0",
|
||||
@@ -289,6 +295,15 @@ dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "embassy-hal-internal"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95285007a91b619dc9f26ea8f55452aa6c60f7115a4edc05085cd2bd3127cd7a"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "embassy-net-driver"
|
||||
version = "0.2.0"
|
||||
@@ -317,9 +332,9 @@ dependencies = [
|
||||
"embassy-embedded-hal",
|
||||
"embassy-executor",
|
||||
"embassy-futures",
|
||||
"embassy-hal-internal",
|
||||
"embassy-hal-internal 0.2.0",
|
||||
"embassy-net-driver",
|
||||
"embassy-sync",
|
||||
"embassy-sync 0.6.2",
|
||||
"embassy-time",
|
||||
"embassy-time-driver",
|
||||
"embassy-time-queue-utils",
|
||||
@@ -362,6 +377,21 @@ dependencies = [
|
||||
"heapless",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "embassy-sync"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cef1a8a1ea892f9b656de0295532ac5d8067e9830d49ec75076291fd6066b136"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"critical-section",
|
||||
"defmt 1.0.1",
|
||||
"embedded-io-async",
|
||||
"futures-sink",
|
||||
"futures-util",
|
||||
"heapless",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "embassy-time"
|
||||
version = "0.4.0"
|
||||
@@ -415,7 +445,7 @@ checksum = "08e753b23799329780c7ac434264026d0422044d6649ed70a73441b14a6436d7"
|
||||
dependencies = [
|
||||
"critical-section",
|
||||
"defmt 0.3.100",
|
||||
"embassy-sync",
|
||||
"embassy-sync 0.6.2",
|
||||
"embassy-usb-driver",
|
||||
]
|
||||
|
||||
@@ -610,6 +640,12 @@ version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||
|
||||
[[package]]
|
||||
name = "portable-atomic"
|
||||
version = "1.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error-attr2"
|
||||
version = "2.0.0"
|
||||
@@ -698,6 +734,15 @@ version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||
|
||||
[[package]]
|
||||
name = "static_cell"
|
||||
version = "2.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0530892bb4fa575ee0da4b86f86c667132a94b74bb72160f58ee5a4afec74c23"
|
||||
dependencies = [
|
||||
"portable-atomic",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "stm32-fmc"
|
||||
version = "0.3.2"
|
||||
|
||||
@@ -6,9 +6,10 @@ edition = "2021"
|
||||
[dependencies]
|
||||
# Change stm32h563zi to your chip name, if necessary.
|
||||
embassy-stm32 = { version = "0.2.0", features = ["defmt", "stm32h533re", "memory-x", "time-driver-any", "exti", "unstable-pac", "low-power"] }
|
||||
# embassy-sync = { version = "0.7.0", features = ["defmt"] }
|
||||
embassy-sync = { version = "0.7.0", features = ["defmt"] }
|
||||
embassy-executor = { version = "0.7.0", features = ["arch-cortex-m", "executor-thread", "defmt"] }
|
||||
embassy-time = { version = "0.4.0", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
|
||||
embassy-embedded-hal = { version = "0.3.1", features = ["defmt"] }
|
||||
# embassy-net = { version = "0.7.0", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "proto-ipv6"] }
|
||||
# embassy-usb = { version = "0.4.0", features = ["defmt"] }
|
||||
# embassy-futures = { version = "0.1.0"}
|
||||
@@ -21,7 +22,7 @@ bitflags = "2.9.1"
|
||||
cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
|
||||
cortex-m-rt = "0.7.0"
|
||||
# embedded-hal = "0.2.6"
|
||||
# embedded-hal-1 = { package = "embedded-hal", version = "1.0" }
|
||||
embedded-hal-1 = { package = "embedded-hal", version = "1.0" }
|
||||
# embedded-hal-async = { version = "1.0" }
|
||||
# embedded-io-async = { version = "0.6.1" }
|
||||
# embedded-nal-async = "0.8.0"
|
||||
@@ -31,7 +32,7 @@ panic-probe = { version = "1.0.0", features = ["print-defmt"] }
|
||||
# micromath = "2.0.0"
|
||||
# stm32-fmc = "0.3.0"
|
||||
# embedded-storage = "0.3.1"
|
||||
# static_cell = "2"
|
||||
static_cell = "2"
|
||||
|
||||
# # cargo build/run
|
||||
# [profile.dev]
|
||||
|
||||
160
src/adg2128.rs
Normal file
160
src/adg2128.rs
Normal file
@@ -0,0 +1,160 @@
|
||||
use embassy_embedded_hal::shared_bus::blocking::i2c::I2cDevice;
|
||||
use embassy_stm32::{i2c::I2c, mode::Blocking};
|
||||
use embassy_sync::blocking_mutex::raw::NoopRawMutex;
|
||||
|
||||
use embedded_hal_1::i2c::I2c as _;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
#[allow(dead_code)]
|
||||
pub enum SetX {
|
||||
X0 = 0b0000,
|
||||
X1,
|
||||
X2,
|
||||
X3,
|
||||
X4,
|
||||
X5,
|
||||
X6 = 0b1000,
|
||||
X7,
|
||||
X8,
|
||||
X9,
|
||||
X10,
|
||||
X11,
|
||||
}
|
||||
|
||||
impl SetX{
|
||||
pub fn from_u8(value: u8) -> Self {
|
||||
const VARIANTS: [SetX; 12] = [
|
||||
SetX::X0, SetX::X1, SetX::X2, SetX::X3,
|
||||
SetX::X4, SetX::X5, SetX::X6, SetX::X7,
|
||||
SetX::X8, SetX::X9, SetX::X10, SetX::X11,
|
||||
];
|
||||
|
||||
*VARIANTS.get(value as usize).expect("Invalid value for SetX")
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
#[allow(dead_code)]
|
||||
pub enum SetY {
|
||||
Y0 = 0b000,
|
||||
Y1,
|
||||
Y2,
|
||||
Y3,
|
||||
Y4,
|
||||
Y5,
|
||||
Y6,
|
||||
Y7,
|
||||
}
|
||||
|
||||
impl SetY {
|
||||
pub fn from_u8(value: u8) -> Self {
|
||||
const VARIANTS: [SetY; 8] = [
|
||||
SetY::Y0, SetY::Y1, SetY::Y2, SetY::Y3,
|
||||
SetY::Y4, SetY::Y5, SetY::Y6, SetY::Y7,
|
||||
];
|
||||
|
||||
*VARIANTS.get(value as usize).expect("Invalid value for SetY")
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
#[allow(dead_code)]
|
||||
pub enum GetX {
|
||||
X0 = 0b0011_0100,
|
||||
X1 = 0b0011_1100,
|
||||
X2 = 0b0111_0100,
|
||||
X3 = 0b0111_1100,
|
||||
X4 = 0b0011_0101,
|
||||
X5 = 0b0011_1101,
|
||||
X6 = 0b0111_0101,
|
||||
X7 = 0b0111_1101,
|
||||
X8 = 0b0011_0110,
|
||||
X9 = 0b0011_1110,
|
||||
X10 = 0b0111_0110,
|
||||
X11 = 0b0111_1110,
|
||||
}
|
||||
|
||||
impl GetX {
|
||||
pub fn from_u8(value: u8) -> Self {
|
||||
const VARIANTS: [GetX; 12] = [
|
||||
GetX::X0, GetX::X1, GetX::X2, GetX::X3,
|
||||
GetX::X4, GetX::X5, GetX::X6, GetX::X7,
|
||||
GetX::X8, GetX::X9, GetX::X10, GetX::X11,
|
||||
];
|
||||
|
||||
*VARIANTS.get(value as usize).expect("Invalid value for GetX")
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub enum State {
|
||||
DISABLED = 0b0,
|
||||
ENABLED = 0b1,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
enum LDSW {
|
||||
EN = 0b1,
|
||||
DIS = 0b0,
|
||||
}
|
||||
|
||||
pub struct ADG2128 {
|
||||
i2c: I2cDevice<'static, NoopRawMutex, I2c<'static, Blocking>>,
|
||||
address: u8,
|
||||
states_xy: [u8; 12]
|
||||
}
|
||||
|
||||
impl ADG2128 {
|
||||
pub fn new(i2c: I2cDevice<'static, NoopRawMutex, I2c<'static, Blocking>>, address: u8) -> Self {
|
||||
ADG2128 { i2c, address, states_xy: [0u8; 12]}
|
||||
}
|
||||
|
||||
pub fn set(&mut self, io_1: SetX, io_2: SetY, state: State) {
|
||||
let mut data = [0u8; 2];
|
||||
data[0] = (state as u8) << 7 | (io_1 as u8) << 3 | (io_2 as u8);
|
||||
data[1] = LDSW::EN as u8;
|
||||
self.i2c.write(self.address, &data).unwrap()
|
||||
}
|
||||
|
||||
pub fn get(&mut self, io: GetX) -> u8 {
|
||||
let mut data_out = [0u8; 2];
|
||||
let mut data_in = [0u8; 2];
|
||||
data_out[0] = io as u8;
|
||||
self.i2c.write_read(self.address, &mut data_out, &mut data_in).unwrap();
|
||||
|
||||
data_in[1]
|
||||
}
|
||||
|
||||
pub fn get_all(&mut self) -> [u8; 12] {
|
||||
let mut states_xy = [0u8; 12];
|
||||
|
||||
for (x_line, y_states) in states_xy.iter_mut().enumerate() {
|
||||
let x_line_data = GetX::from_u8(x_line as u8);
|
||||
*y_states = self.get(x_line_data);
|
||||
}
|
||||
|
||||
self.states_xy.copy_from_slice(states_xy.as_slice());
|
||||
|
||||
states_xy
|
||||
}
|
||||
|
||||
pub fn reset_all(&mut self) {
|
||||
let states_xy = self.get_all();
|
||||
|
||||
// Find bits that are set
|
||||
for (x_line, &state) in states_xy.iter().enumerate() {
|
||||
if state == 0 {
|
||||
continue; // Skip zero states early
|
||||
}
|
||||
for value in 0..8 {
|
||||
if (state >> value) & 1 == 1 {
|
||||
self.set(
|
||||
SetX::from_u8(x_line as u8),
|
||||
SetY::from_u8(value),
|
||||
State::DISABLED,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
88
src/electrodes.rs
Normal file
88
src/electrodes.rs
Normal file
@@ -0,0 +1,88 @@
|
||||
use embassy_embedded_hal::shared_bus::blocking::i2c::I2cDevice;
|
||||
use embassy_stm32::{i2c, mode::Blocking};
|
||||
use embassy_sync::blocking_mutex::NoopMutex;
|
||||
use static_cell::StaticCell;
|
||||
use core::cell::RefCell;
|
||||
|
||||
use crate::{ad5940, adg2128::{GetX, SetX, SetY, State, ADG2128}};
|
||||
|
||||
static I2C_BUS: StaticCell<NoopMutex<RefCell<i2c::I2c<'static, Blocking>>>> = StaticCell::new();
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
#[allow(dead_code)]
|
||||
pub enum Electrode {
|
||||
E0, E1, E2, E3, E4, E5, E6, E7,
|
||||
E8, E9, E10, E11, E12, E13, E14, E15,
|
||||
E16, E17, E18, E19, E20, E21, E22, E23,
|
||||
}
|
||||
|
||||
impl Electrode {
|
||||
pub fn from_u8(value: u8) -> Self {
|
||||
const VARIANTS: [Electrode; 24] = [
|
||||
Electrode::E0, Electrode::E1, Electrode::E2, Electrode::E3,
|
||||
Electrode::E4, Electrode::E5, Electrode::E6, Electrode::E7,
|
||||
Electrode::E8, Electrode::E9, Electrode::E10, Electrode::E11,
|
||||
Electrode::E12, Electrode::E13, Electrode::E14, Electrode::E15,
|
||||
Electrode::E16, Electrode::E17, Electrode::E18, Electrode::E19,
|
||||
Electrode::E20, Electrode::E21, Electrode::E22, Electrode::E23,
|
||||
];
|
||||
|
||||
*VARIANTS.get(value as usize).expect("Invalid value for SetX")
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
#[allow(dead_code)]
|
||||
pub enum AD5940Pin {
|
||||
CE0, RE0, SE0, DE0,
|
||||
AIN0, AIN1, AIN2, AIN3,
|
||||
}
|
||||
|
||||
pub struct Electrodes {
|
||||
mux_1: ADG2128,
|
||||
mux_2: ADG2128,
|
||||
}
|
||||
|
||||
impl Electrodes {
|
||||
pub fn new(i2c: i2c::I2c<'static, Blocking>) -> Self {
|
||||
let i2c_bus = NoopMutex::new(RefCell::new(i2c));
|
||||
let i2c_bus = I2C_BUS.init(i2c_bus);
|
||||
|
||||
Electrodes {
|
||||
mux_1: ADG2128::new(I2cDevice::new(i2c_bus), 0b1110_000),
|
||||
mux_2: ADG2128::new(I2cDevice::new(i2c_bus), 0b1110_001),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set(&mut self, electrode: Electrode, ad5940_pin: AD5940Pin, state: State) {
|
||||
let electrode = electrode as u8;
|
||||
let ad5940_pin = ad5940_pin as u8;
|
||||
match electrode {
|
||||
0..=11 => {
|
||||
self.mux_1.set(SetX::from_u8(electrode), SetY::from_u8(ad5940_pin), state);
|
||||
}
|
||||
12..=23 => {
|
||||
self.mux_2.set(SetX::from_u8(electrode-12), SetY::from_u8(ad5940_pin), state);
|
||||
}
|
||||
_ => panic!("Invalid electrode number"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get(&mut self, io: Electrode) -> u8 {
|
||||
let number = io as u8;
|
||||
match number {
|
||||
0..=11 => self.mux_1.get(GetX::from_u8(number)),
|
||||
12..=23 => self.mux_2.get(GetX::from_u8(number-12)),
|
||||
_ => panic!("Invalid electrode number"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_all(&mut self) -> ([u8; 12], [u8; 12]) {
|
||||
(self.mux_1.get_all(), self.mux_2.get_all())
|
||||
}
|
||||
|
||||
pub fn reset_all(&mut self) {
|
||||
self.mux_1.reset_all();
|
||||
self.mux_2.reset_all();
|
||||
}
|
||||
}
|
||||
28
src/main.rs
28
src/main.rs
@@ -4,13 +4,20 @@
|
||||
use defmt::*;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_stm32::gpio::{Level, Output, Speed};
|
||||
use embassy_stm32::{adc, spi, Config};
|
||||
use embassy_stm32::{i2c, spi, Config};
|
||||
use embassy_stm32::time::Hertz;
|
||||
use embassy_time::Timer;
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
mod ad5940;
|
||||
use ad5940::AD5940;
|
||||
|
||||
mod adg2128;
|
||||
use adg2128::State;
|
||||
|
||||
mod electrodes;
|
||||
use electrodes::{Electrodes, Electrode, AD5940Pin};
|
||||
|
||||
mod ad5940_registers;
|
||||
|
||||
#[embassy_executor::main]
|
||||
@@ -34,6 +41,7 @@ async fn main(_spawner: Spawner) {
|
||||
|
||||
// let mut led = Output::new(p.PA5, Level::High, Speed::Low);
|
||||
|
||||
// Set up SPI for AD5940
|
||||
let cs = Output::new(p.PC9, Level::High, Speed::Low);
|
||||
|
||||
let spi = spi::Spi::new_blocking(
|
||||
@@ -49,6 +57,21 @@ async fn main(_spawner: Spawner) {
|
||||
|
||||
ad5940.init_temperature().await.unwrap();
|
||||
|
||||
// Set up I2C for ADG2128
|
||||
let i2c = i2c::I2c::new_blocking(
|
||||
p.I2C1,
|
||||
p.PB6,
|
||||
p.PB7,
|
||||
Hertz(400_000),
|
||||
i2c::Config::default()
|
||||
);
|
||||
|
||||
// Initialize electrodes
|
||||
let mut electrodes = Electrodes::new(i2c);
|
||||
electrodes.reset_all();
|
||||
electrodes.set(Electrode::E11, AD5940Pin::CE0, State::ENABLED);
|
||||
electrodes.set(Electrode::E12, AD5940Pin::RE0, State::ENABLED);
|
||||
|
||||
loop {
|
||||
// Read chip id
|
||||
// let chip_id = ad5940.get_chipid().await.unwrap();
|
||||
@@ -58,6 +81,9 @@ async fn main(_spawner: Spawner) {
|
||||
let temp = ad5940.get_temperature().await.unwrap();
|
||||
info!("Temperature: {}°C", temp);
|
||||
|
||||
let result = electrodes.get_all();
|
||||
info!("Electrodes states: {:?}", result);
|
||||
|
||||
// info!("high");
|
||||
// led.set_high();
|
||||
Timer::after_millis(500).await;
|
||||
|
||||
Reference in New Issue
Block a user