Merge pull request 'Switch to embassy' (#1) from switch-to-embassy into main

Reviewed-on: #1
This commit is contained in:
fabian 2025-01-12 23:03:22 +01:00
commit f16f5c8347
36 changed files with 640 additions and 1006 deletions

View File

@ -1,8 +1,15 @@
[target.'cfg(all(target_arch = "arm", target_os = "none"))']
rustflags = [
"-C",
"link-arg=-Tlink.x",
"-C",
"link-arg=-Tdefmt.x",
"-C",
"link-arg=--nmagic",
]
[build]
target = "thumbv7em-none-eabihf"
[target.'cfg(all(target_arch = "arm", target_os = "none"))']
rustflags = [
"-C", "link-arg=-Tlink.x",
"-C", "link-arg=--nmagic",
]
[env]
DEFMT_LOG = "debug"

737
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,74 +1,112 @@
[workspace]
members = ["tflite_demo"]
[workspace.features]
default = ["ble-l2cap", "ble-gatt-server", "ble-gatt-client", "ble-sec"]
# [workspace.features]
# default = ["ble-l2cap", "ble-gatt-server", "ble-gatt-client", "ble-sec"]
ble-l2cap = ["nrf-softdevice/ble-l2cap"]
ble-gatt-server = ["nrf-softdevice/ble-gatt-server"]
ble-gatt-client = ["nrf-softdevice/ble-gatt-client"]
ble-sec = ["nrf-softdevice/ble-sec"]
# ble-l2cap = ["nrf-softdevice/ble-l2cap"]
# ble-gatt-server = ["nrf-softdevice/ble-gatt-server"]
# ble-gatt-client = ["nrf-softdevice/ble-gatt-client"]
# ble-sec = ["nrf-softdevice/ble-sec"]
nrf52840 = [
"embassy-nrf/nrf52840",
"nrf-softdevice/nrf52840",
"nrf-softdevice/s140",
"dep:nrf-softdevice-s140",
]
# nrf52840 = [
# "embassy-nrf/nrf52840",
# "nrf-softdevice/nrf52840",
# "nrf-softdevice/s140",
# "dep:nrf-softdevice-s140",
# ]
[workspace.dependencies]
cortex-m = { version = "0.7.7", features = [
"critical-section-single-core",
"inline-asm",
] }
cortex-m-rt = "0.7.2"
nrf52840-hal = "0.16.0"
usb-device = "0.2.7"
usbd-serial = "0.1.0"
cortex-m-rt = "0.7.5"
defmt = "0.3.10"
defmt-rtt = "0.4.1"
defmt-serial = "0.10.0"
embassy-executor = { version = "0.7.0", features = [
"arch-cortex-m",
"defmt",
"executor-thread",
"executor-interrupt",
] }
embassy-futures = { version = "0.1.1", features = ["defmt"] }
embassy-nrf = { version = "0.3.1", features = [
"defmt",
"gpiote",
"nrf52840",
"time",
"time-driver-rtc1",
"unstable-pac",
] }
embassy-sync = { version = "0.6.1", features = ["defmt"] }
embassy-time = { version = "0.4.0", features = [
"defmt",
"defmt-timestamp-uptime",
] }
embassy-embedded-hal = "0.3.0"
embassy-usb = "0.2.0"
embassy-usb-logger = "0.2.0"
panic-probe = { version = "0.3.2", features = ["print-defmt"] }
# cortex-m = { version = "0.7.7", features = [
# "critical-section-single-core",
# "inline-asm",
# ] }
# cortex-m-rt = "0.7.5"
# nrf52840-hal = "0.16.0"
# usb-device = "0.3.2"
# usbd-serial = "0.2.2"
microflow = { path = "../microflow-rs" }
# microflow = "0.1.3"
# # microflow = "0.1.3"
nalgebra = { version = "0.33.2", default-features = false, features = [
"macros",
] }
libm = "0.2"
panic-halt = "1.0.0"
panic-probe = { version = "0.3.1", features = ["print-defmt"] }
# panic-halt = "1.0.0"
# panic-probe = { version = "0.3.2", features = ["print-defmt"] }
heapless = "0.8.0"
lsm6ds3tr = { path = "../lsm6ds3tr-rs" }
embassy-sync = { version = "0.5.0" }
embassy-executor = { version = "0.5.0", features = [
"arch-cortex-m",
"executor-thread",
"executor-interrupt",
"defmt",
"integrated-timers",
] }
embassy-time = { version = "0.3.0", features = [
"defmt",
"defmt-timestamp-uptime",
] }
embassy-nrf = { version = "0.1.0", features = [
"defmt",
"nrf52840",
"time-driver-rtc1",
"gpiote",
"time",
] }
defmt = "0.3.0"
defmt-rtt = "0.4.0"
embedded-storage = "0.3.0"
# lsm6ds3tr = { path = "../lsm6ds3tr-rs" }
# embassy-sync = { version = "0.5.0" }
# # embassy-embedded-hal = "0.3.0"
# embassy-executor = { version = "0.5.0", features = [
# "arch-cortex-m",
# "executor-thread",
# "executor-interrupt",
# "defmt",
# "integrated-timers",
# ] }
# embassy-time = { version = "0.3.0", features = [
# "defmt",
# "defmt-timestamp-uptime",
# ] }
# embassy-nrf = { version = "0.1.0", features = [
# "defmt",
# "nrf52840",
# "time-driver-rtc1",
# "gpiote",
# "time",
# ] }
# defmt = "0.3.10"
# defmt-rtt = "0.4.1"
# embedded-storage = "0.3.0"
embedded-hal = "1.0.0"
embedded-hal-async = { version = "1.0.0" }
embedded-alloc = "0.6.0"
nrf-softdevice = { version = "0.1.0", features = [
"defmt",
"ble-peripheral",
"ble-central",
"critical-section-impl",
"nrf52840",
"s140",
] }
nrf-softdevice-s140 = { version = "0.1.1" }
# embedded-hal-bus = { version = "0.2.0", features = ["async"] }
# nrf-softdevice = { version = "0.1.0", features = [
# "defmt",
# "ble-peripheral",
# "ble-central",
# "critical-section-impl",
# "nrf52840",
# "s140",
# ] }
# nrf-softdevice-s140 = { version = "0.1.1" }
fixed = "1.24.0"
atomic-pool = "1.0.1"
static_cell = "2.0.0"
assign-resources = "0.4.1"

View File

@ -6,27 +6,44 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
cortex-m.workspace = true
cortex-m-rt.workspace = true
nrf52840-hal.workspace = true
usb-device.workspace = true
usbd-serial.workspace = true
microflow.workspace = true
libm.workspace = true
nalgebra.workspace = true
heapless.workspace = true
lsm6ds3tr.workspace = true
defmt.workspace = true
defmt-rtt.workspace = true
embassy-nrf.workspace = true
# embassy-time.workspace = true
embassy-executor.workspace = true
embassy-sync.workspace = true
embassy-embedded-hal.workspace = true
embassy-futures.workspace = true
embassy-usb.workspace = true
embassy-usb-logger.workspace = true
embassy-time.workspace = true
embedded-alloc.workspace = true
embedded-hal.workspace = true
embedded-hal-async.workspace = true
nrf-softdevice.workspace = true
nrf-softdevice-s140.workspace = true
embassy-nrf.workspace = true
embassy-time.workspace = true
embassy-executor.workspace = true
embassy-sync.workspace = true
cortex-m.workspace = true
cortex-m-rt.workspace = true
defmt.workspace = true
defmt-rtt.workspace = true
# nrf52840-hal.workspace = true
# usb-device.workspace = true
# usbd-serial.workspace = true
microflow.workspace = true
libm.workspace = true
nalgebra.workspace = true
# heapless.workspace = true
# lsm6ds3tr.workspace = true
# nrf-softdevice.workspace = true
# nrf-softdevice-s140.workspace = true
fixed.workspace = true
atomic-pool.workspace = true
heapless.workspace = true
panic-probe.workspace = true
defmt-serial.workspace = true
static_cell.workspace = true
assign-resources.workspace = true
# embassy-embedded-hal.workspace = true

View File

@ -1,4 +0,0 @@
#![macro_use]
use defmt_rtt as _; // global logger
use embassy_nrf as _; // time driver

View File

@ -1,16 +0,0 @@
// Hypothetical I2C implementation (replace with your actual hardware I2C)
// struct MyI2c;
// impl I2c for MyI2c {
// // type Error = I2cError;
// fn read(&mut self, _address: u8, _buffer: &mut [u8]) -> Result<(), Self::Error> {
// // Simulate reading data
// Ok(())
// }
// fn write(&mut self, _address: u8, _bytes: &[u8]) -> Result<(), Self::Error> {
// // Simulate writing data
// Ok(())
// }
// }

View File

@ -277,264 +277,3 @@ impl<const BITS_NUM: u8, const BITS_POS: u8> From<bool> for RegisterBits<BITS_NU
Self::from(value as u8)
}
}
#[cfg(test)]
mod tests {
use super::{RegisterBits, RegisterValue};
#[test]
fn new_1_0() {
const BITS: u8 = 1;
const POS: u8 = 0;
let rb = RegisterBits::<BITS, POS>::new(0b11111111);
assert_eq!(rb.value, 0b1);
}
#[test]
fn new_1_1() {
const BITS: u8 = 1;
const POS: u8 = 1;
let rb = RegisterBits::<BITS, POS>::new(0b11111111);
assert_eq!(rb.value, 0b1);
}
#[test]
fn new_1_2() {
const BITS: u8 = 1;
const POS: u8 = 2;
let rb = RegisterBits::<BITS, POS>::new(0b11111111);
assert_eq!(rb.value, 0b1);
}
#[test]
fn new_2_0() {
const BITS: u8 = 2;
const POS: u8 = 0;
let rb = RegisterBits::<BITS, POS>::new(0b11111111);
assert_eq!(rb.value, 0b11);
}
#[test]
fn new_2_1() {
const BITS: u8 = 2;
const POS: u8 = 1;
let rb = RegisterBits::<BITS, POS>::new(0b11111111);
assert_eq!(rb.value, 0b11);
}
#[test]
fn new_2_2() {
const BITS: u8 = 2;
const POS: u8 = 2;
let rb = RegisterBits::<BITS, POS>::new(0b11111111);
assert_eq!(rb.value, 0b11);
}
#[test]
fn shifted_1_0() {
const BITS: u8 = 1;
const POS: u8 = 0;
let rb = RegisterBits::<BITS, POS>::new(0b11111111);
assert_eq!(rb.value, 0b1);
assert_eq!(rb.shifted(), 0b1);
}
#[test]
fn shifted_1_1() {
const BITS: u8 = 1;
const POS: u8 = 1;
let rb = RegisterBits::<BITS, POS>::new(0b11111111);
assert_eq!(rb.value, 0b1);
assert_eq!(rb.shifted(), 0b10);
}
#[test]
fn shifted_1_2() {
const BITS: u8 = 1;
const POS: u8 = 2;
let rb = RegisterBits::<BITS, POS>::new(0b11111111);
assert_eq!(rb.value, 0b1);
assert_eq!(rb.shifted(), 0b100);
}
#[test]
fn shifted_2_1() {
const BITS: u8 = 2;
const POS: u8 = 1;
let rb = RegisterBits::<BITS, POS>::new(0b11111111);
assert_eq!(rb.value, 0b11);
assert_eq!(rb.shifted(), 0b110);
}
#[test]
fn shifted_2_2() {
const BITS: u8 = 2;
const POS: u8 = 2;
let rb = RegisterBits::<BITS, POS>::new(0b11111111);
assert_eq!(rb.value, 0b11);
assert_eq!(rb.shifted(), 0b1100);
}
#[test]
fn new_from_reg_1_0() {
const BITS: u8 = 1;
const POS: u8 = 0;
let rb = RegisterBits::<BITS, POS>::from_reg(0b11111111);
assert_eq!(rb.value, 0b1);
assert_eq!(rb.shifted(), 0b1);
}
#[test]
fn new_from_reg_1_1() {
const BITS: u8 = 1;
const POS: u8 = 1;
let rb = RegisterBits::<BITS, POS>::from_reg(0b11111111);
assert_eq!(rb.value, 0b1);
assert_eq!(rb.shifted(), 0b10);
}
#[test]
fn new_from_reg_2_0() {
const BITS: u8 = 2;
const POS: u8 = 0;
let rb = RegisterBits::<BITS, POS>::from_reg(0b11111111);
assert_eq!(rb.value, 0b11);
assert_eq!(rb.shifted(), 0b11);
}
#[test]
fn new_from_reg_2_1() {
const BITS: u8 = 2;
const POS: u8 = 1;
let rb = RegisterBits::<BITS, POS>::from_reg(0b11111111);
assert_eq!(rb.value, 0b11);
assert_eq!(rb.shifted(), 0b110);
}
#[test]
fn new_from_reg_2_2() {
const BITS: u8 = 2;
const POS: u8 = 2;
let rb = RegisterBits::<BITS, POS>::from_reg(0b11111111);
assert_eq!(rb.value, 0b11);
assert_eq!(rb.shifted(), 0b1100);
}
#[test]
fn from_reg_1_0() {
const BITS: u8 = 1;
const POS: u8 = 0;
let mut rb = RegisterBits::<BITS, POS>::default();
let reg: u8 = 0b11111111;
rb.set_from_reg(reg);
assert_eq!(rb.value, 0b1);
assert_eq!(rb.shifted(), 0b1);
}
#[test]
fn from_reg_1_1() {
const BITS: u8 = 1;
const POS: u8 = 1;
let mut rb = RegisterBits::<BITS, POS>::default();
let reg: u8 = 0b11111111;
rb.set_from_reg(reg);
assert_eq!(rb.value, 0b1);
assert_eq!(rb.shifted(), 0b10);
}
#[test]
fn from_reg_2_0() {
const BITS: u8 = 2;
const POS: u8 = 0;
let mut rb = RegisterBits::<BITS, POS>::default();
let reg: u8 = 0b11111111;
rb.set_from_reg(reg);
assert_eq!(rb.value, 0b11);
assert_eq!(rb.shifted(), 0b11);
}
#[test]
fn from_reg_2_1() {
const BITS: u8 = 2;
const POS: u8 = 1;
let mut rb = RegisterBits::<BITS, POS>::default();
let reg: u8 = 0b11111111;
rb.set_from_reg(reg);
assert_eq!(rb.value, 0b11);
assert_eq!(rb.shifted(), 0b110);
}
#[test]
fn from_reg_2_2() {
const BITS: u8 = 2;
const POS: u8 = 2;
let mut rb = RegisterBits::<BITS, POS>::default();
let reg: u8 = 0b11111111;
rb.set_from_reg(reg);
assert_eq!(rb.value, 0b11);
assert_eq!(rb.shifted(), 0b1100);
}
#[test]
fn bit_mask_1_0() {
const BITS: u8 = 1;
const POS: u8 = 0;
assert_eq!(RegisterBits::<BITS, POS>::bit_mask(), 0b1);
}
#[test]
fn bit_mask_2_0() {
const BITS: u8 = 2;
const POS: u8 = 0;
assert_eq!(RegisterBits::<BITS, POS>::bit_mask(), 0b11);
}
#[test]
fn bit_mask_3_0() {
const BITS: u8 = 3;
const POS: u8 = 0;
assert_eq!(RegisterBits::<BITS, POS>::bit_mask(), 0b111);
}
#[test]
fn bit_shifted_mask_1_0() {
const BITS: u8 = 1;
const POS: u8 = 0;
assert_eq!(RegisterBits::<BITS, POS>::bit_shifted_mask(), 0b1);
}
#[test]
fn bit_shifted_mask_1_1() {
const BITS: u8 = 1;
const POS: u8 = 1;
assert_eq!(RegisterBits::<BITS, POS>::bit_shifted_mask(), 0b10);
}
#[test]
fn bit_shifted_mask_2_0() {
const BITS: u8 = 2;
const POS: u8 = 0;
assert_eq!(RegisterBits::<BITS, POS>::bit_shifted_mask(), 0b11);
}
#[test]
fn bit_shifted_mask_2_1() {
const BITS: u8 = 2;
const POS: u8 = 1;
assert_eq!(RegisterBits::<BITS, POS>::bit_shifted_mask(), 0b110);
}
#[test]
fn bit_shifted_mask_3_0() {
const BITS: u8 = 3;
const POS: u8 = 0;
assert_eq!(RegisterBits::<BITS, POS>::bit_shifted_mask(), 0b111);
}
#[test]
fn bit_shifted_mask_3_1() {
const BITS: u8 = 3;
const POS: u8 = 1;
assert_eq!(RegisterBits::<BITS, POS>::bit_shifted_mask(), 0b1110);
}
}

View File

@ -1,265 +1,213 @@
#![no_main]
#![no_std]
mod common;
mod i2c;
mod lsm6ds;
mod lsm6ds3tr;
use core::fmt::Write;
use defmt::{info, panic, unwrap};
use embassy_embedded_hal::shared_bus::asynch::i2c::I2cDevice;
use embassy_executor::Spawner;
use embassy_nrf::peripherals::TWISPI0;
use embassy_nrf::twim::Twim;
use embassy_nrf::usb::vbus_detect::HardwareVbusDetect;
use embassy_nrf::usb::Driver;
use embassy_nrf::{bind_interrupts, pac, peripherals, twim, usb};
use embassy_sync::blocking_mutex::raw::NoopRawMutex;
use embassy_sync::mutex::Mutex;
use embassy_time::{Duration, Timer};
use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
use embassy_usb::driver::EndpointError;
use embassy_usb::{Builder, Config, UsbDevice};
use embedded_alloc::LlffHeap;
use libm::sinf;
use lsm6ds::Lsm6ds33;
// use lsm6ds3tr::{
// interface::{I2cInterface, SpiInterface},
// LsmSettings, LSM6DS3TR,
// };
// use lsm6ds3tr::{interface::SpiInterface, AccelScale, LsmSettings, LSM6DS3TR};
use microflow::model;
use nalgebra::matrix;
use nrf52840_hal::{self as hal, twim, Spim, Twim};
// use nrf_softdevice::{
// ble::{EncryptionInfo, IdentityKey, MasterId, Uuid},
// Softdevice,
// };
use usb_device::class_prelude::UsbBusAllocator;
use nrf52840_hal::{
gpio::Level,
prelude::{OutputPin, PinState, _embedded_hal_timer_CountDown},
uarte::{Baudrate, Parity, Pins, Uarte},
Rtc,
};
use lsm6ds3tr::interface::i2c::I2cInterface;
// use embassy_embedded_hal::shared_bus::blocking::i2c::I2cDevice;
use static_cell::StaticCell;
use heapless::String;
// const BATTERY_SERVICE: Uuid = Uuid::new_16(0x180f);
// const BATTERY_LEVEL: Uuid = Uuid::new_16(0x2a19);
use {defmt_serial as _, panic_probe as _};
// const LED_SERVICE_UUID: Uuid = Uuid::new_16(0x112f);
// const LED_CONTROL_CHAR_UUID: Uuid = Uuid::new_16(0x321f);
static I2C_BUS: StaticCell<Mutex<NoopRawMutex, Twim<TWISPI0>>> = StaticCell::new();
const RTC_FREQ_MHZ: f32 = 0.032_768;
bind_interrupts!(struct Irqs {
USBD => usb::InterruptHandler<peripherals::USBD>;
CLOCK_POWER => usb::vbus_detect::InterruptHandler;
});
type MyDriver = Driver<'static, peripherals::USBD, HardwareVbusDetect>;
#[global_allocator]
static HEAP: LlffHeap = LlffHeap::empty();
// #[embassy_executor::task]
// async fn softdevice_task(sd: &'static Softdevice) {
// sd.run().await;
// }
// #[derive(Debug, Clone, Copy)]
// struct Peer {
// master_id: MasterId,
// key: EncryptionInfo,
// peer_id: IdentityKey,
// }
#[panic_handler] // panicking behavior
fn panic(_: &core::panic::PanicInfo) -> ! {
reset_into_dfu();
#[embassy_executor::task]
async fn usb_task(mut device: UsbDevice<'static, MyDriver>) {
device.run().await;
}
#[model("tflite_demo/models/sine.tflite")]
struct Sine;
#[model("tflite_demo/models/speech.tflite")]
struct Speech;
/// Resets the device into Device Firmware Update mode (DFU).
fn reset_into_dfu() -> ! {
// Via https://devzone.nordicsemi.com/f/nordic-q-a/50839/start-dfu-mode-or-open_bootloader-from-application-by-function-call
unsafe {
(*hal::pac::POWER::PTR).gpregret.write(|w| w.bits(0xB1));
};
hal::pac::SCB::sys_reset()
}
#[derive(Clone, Copy)]
enum LightState {
Red = 0,
Green = 1,
Blue = 2,
}
#[cortex_m_rt::entry]
fn main() -> ! {
{
use core::mem::MaybeUninit;
const HEAP_SIZE: usize = 1024;
static mut HEAP_MEM: [MaybeUninit<u8>; HEAP_SIZE] = [MaybeUninit::uninit(); HEAP_SIZE];
unsafe { HEAP.init(HEAP_MEM.as_ptr() as usize, HEAP_SIZE) }
}
let p = hal::pac::Peripherals::take().unwrap();
let port0 = hal::gpio::p0::Parts::new(p.P0);
let mut led_red = port0.p0_26.into_push_pull_output(Level::Low);
let mut led_green = port0.p0_30.into_push_pull_output(Level::Low);
let mut led_blue = port0.p0_06.into_push_pull_output(Level::Low);
let clocks = hal::clocks::Clocks::new(p.CLOCK);
let clocks = clocks.enable_ext_hfosc();
let usb_peripheral = hal::usbd::UsbPeripheral::new(p.USBD, &clocks);
let usb_bus = UsbBusAllocator::new(hal::usbd::Usbd::new(usb_peripheral));
let mut serial_port = usbd_serial::SerialPort::new(&usb_bus);
// let spiclk = port0.p0_24.into_push_pull_output(Level::Low).degrade();
// let spimosi = port0.p0_23.into_push_pull_output(Level::Low).degrade();
// let spimiso = port0.p0_22.into_floating_input().degrade();
// let pins = nrf52840_hal::spim::Pins {
// sck: Some(spiclk),
// miso: Some(spimiso),
// mosi: Some(spimosi),
// };
// let spim = Spim::new(
// p.SPIM2,
// pins,
// nrf52840_hal::spim::Frequency::K125,
// nrf52840_hal::spim::MODE_0,
// 0,
// );
// let spi_interface = SpiInterface::new(spim);
// let settings = LsmSettings::basic();
// let mut imu = LSM6DS3TR::new(spi_interface);
// imu.init().expect("Couldn't initialize the LSM6 sensor!");
// let scl = port0.p0_27.into_floating_input().degrade();
// let sda = port0.p0_07.into_floating_input().degrade();
// let pins = twim::Pins { scl: scl, sda: sda };
// let i2c = Twim::new(p.TWIM0, pins, twim::Frequency::K100);
// let i2c_interface = I2cInterface::new(i2c);
// let mut imu = LSM6DS3TR::new(I2cInterface::new(""));
// let mut imu = Lsm6ds33::new(i2c, addr);
let rtc = Rtc::new(p.RTC0, 0).unwrap();
rtc.enable_counter();
let mut usb_device = usb_device::device::UsbDeviceBuilder::new(
&usb_bus,
usb_device::device::UsbVidPid(0x16c0, 0x27dd),
)
.manufacturer("HSRW")
.product("HSRW Pet Tracker nRF52840")
.serial_number("pet1")
.device_class(usbd_serial::USB_CLASS_CDC)
.max_packet_size_0(64) // makes control transfers 8x faster says https://github.com/nrf-rs/nrf-hal/blob/master/examples/usb/src/bin/serial.rs
.build();
let x = 0.5;
let start = rtc.get_counter();
let y_predicted = Sine::predict(matrix![x])[0];
let end = rtc.get_counter();
let y_exact = sinf(x);
// TIMER0 is reserved by Softdevice
// https://devzone.nordicsemi.com/f/nordic-q-a/1160/soft-device-and-timers---how-do-they-work-together
let mut timer = hal::Timer::new(p.TIMER1).into_periodic();
timer.start(hal::Timer::<hal::pac::TIMER0>::TICKS_PER_SECOND);
let mut light = LightState::Red;
#[embassy_executor::task]
async fn echo_task(mut class: CdcAcmClass<'static, MyDriver>) {
loop {
light = match light {
LightState::Red => LightState::Green,
LightState::Green => LightState::Blue,
LightState::Blue => LightState::Red,
};
match light {
LightState::Red => {
led_red.set_state(PinState::Low).unwrap();
led_green.set_state(PinState::High).unwrap();
led_blue.set_state(PinState::High).unwrap();
}
LightState::Green => {
led_red.set_state(PinState::High).unwrap();
led_green.set_state(PinState::Low).unwrap();
led_blue.set_state(PinState::High).unwrap();
}
LightState::Blue => {
led_red.set_state(PinState::High).unwrap();
led_green.set_state(PinState::High).unwrap();
led_blue.set_state(PinState::Low).unwrap();
//reset_into_dfu();
}
class.wait_connection().await;
info!("Connected");
let _ = echo(&mut class).await;
info!("Disconnected");
}
}
// if !usb_dev.poll(&mut [&mut serial]) {
// continue;
// }
#[embassy_executor::task]
// async fn write_task(
// mut class: CdcAcmClass<'static, MyDriver>,
// mut imu: lsm6ds3tr::LSM6DS3TR<
// I2cInterface<I2cDevice<'static, NoopRawMutex, Twim<'static, TWISPI0>>>,
// >,
// ) {
// loop {
// class.wait_connection().await;
// info!("Connected");
let mut buf = [0u8; 64];
// // Read accelerometer data from the IMU
// let accel_data = imu.read_accel().await.unwrap();
match serial_port.read(&mut buf) {
Ok(count) if count > 0 => {
// Check if received data equals to 'reset'
for i in 0..count - 4 {
if buf[i] == b'r'
&& buf[i + 1] == b'e'
&& buf[i + 2] == b's'
&& buf[i + 3] == b'e'
&& buf[i + 4] == b't'
{
reset_into_dfu();
}
}
// let mut data = String::<32>::new();
// if write!(
// data,
// "Accel: x={}, y={}, z={}\r\n",
// accel_data.x, accel_data.y, accel_data.z
// )
// .is_ok()
// {
// if let Err(e) = class.write_packet(data.as_bytes()).await {
// info!("Failed to write to serial console: {:?}", e);
// }
// }
if buf[..12].iter().all(|&x| x == 0) {
reset_into_dfu();
}
// // // Format the accelerometer data
// // let message = format!(
// // "Accel: x={}, y={}, z={}\r\n",
// // accel_data.x, accel_data.y, accel_data.z
// // );
// // if let Err(e) = class.write_packet(message.as_bytes()).await {
// // info!("Failed to write to serial console: {:?}", e);
// // }
// Echo back in upper case
for c in buf[0..count].iter_mut() {
if 0x61 <= *c && *c <= 0x7a {
*c &= !0x20;
}
}
// // Add a delay of 1 second
// Timer::after(Duration::from_secs(1)).await;
let mut write_offset = 0;
while write_offset < count {
match serial_port.write(&buf[write_offset..count]) {
Ok(len) if len > 0 => {
write_offset += len;
}
_ => {}
}
}
}
_ => {}
}
// info!("Disconnected");
// }
// }
async fn write_task(mut class: CdcAcmClass<'static, MyDriver>) {
let mut count = 1;
loop {
class.wait_connection().await;
info!("Connected");
let text = y_predicted.to_bits();
let mut data = String::<32>::new();
if write!(data, "Count: {}\r\n", count).is_ok() {
if let Err(e) = class.write_packet(data.as_bytes()).await {
info!("Failed to write to serial console: {:?}", e);
}
}
count += 1;
let text2 = y_exact.to_bits();
let mut data2 = String::<32>::new();
// Add a delay of 1 second
Timer::after(Duration::from_secs(1)).await;
let _ = serial_port.write("Hello World\n".as_bytes());
info!("Disconnected");
}
}
let _ = serial_port.write("Predicted Y: ".as_bytes());
let _ = write!(data, "data:{text}");
let _ = serial_port.write(data.as_bytes());
let _ = serial_port.write("\n".as_bytes());
#[embassy_executor::main]
async fn main(spawner: Spawner) {
let p = embassy_nrf::init(Default::default());
let _ = serial_port.write("Exact Y: ".as_bytes());
let _ = write!(data2, "data:{text2}");
let _ = serial_port.write(data2.as_bytes());
let _ = serial_port.write("\n".as_bytes());
info!("Enabling ext hfosc...");
pac::CLOCK.tasks_hfclkstart().write_value(1);
while pac::CLOCK.events_hfclkstarted().read() != 1 {}
while timer.wait().is_err() {
// TODO: sleep.
// Spec says poll needs to be called at least every 10ms.
usb_device.poll(&mut [&mut serial_port]);
continue;
// Create the driver, from the HAL.
let driver = Driver::new(p.USBD, Irqs, HardwareVbusDetect::new(Irqs));
// Create embassy-usb Config
let mut config = Config::new(0xc0de, 0xcafe);
config.manufacturer = Some("Embassy");
config.product = Some("USB-serial example");
config.serial_number = Some("12345678");
config.max_power = 100;
config.max_packet_size_0 = 64;
static STATE: StaticCell<State> = StaticCell::new();
let state = STATE.init(State::new());
// Create embassy-usb DeviceBuilder using the driver and config.
static CONFIG_DESC: StaticCell<[u8; 256]> = StaticCell::new();
static BOS_DESC: StaticCell<[u8; 256]> = StaticCell::new();
static MSOS_DESC: StaticCell<[u8; 128]> = StaticCell::new();
static CONTROL_BUF: StaticCell<[u8; 128]> = StaticCell::new();
let mut builder = Builder::new(
driver,
config,
&mut CONFIG_DESC.init([0; 256])[..],
&mut BOS_DESC.init([0; 256])[..],
&mut MSOS_DESC.init([0; 128])[..],
&mut CONTROL_BUF.init([0; 128])[..],
);
// Create classes on the builder.
let class = CdcAcmClass::new(&mut builder, state, 64);
// Build the builder.
let usb = builder.build();
unwrap!(spawner.spawn(usb_task(usb)));
let i2c_bus = {
use embassy_nrf::{
bind_interrupts,
peripherals::{self},
};
// bind_interrupts!(struct Irqs {
// SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0 => twim::InterruptHandler<peripherals::TWISPI0>;
// });
bind_interrupts!(struct Irqs2 {
TWISPI0 => twim::InterruptHandler<peripherals::TWISPI0>;
});
let config = twim::Config::default();
let i2c = Twim::new(p.TWISPI0, Irqs2, p.P0_07, p.P0_27, config);
let i2c_bus = Mutex::<NoopRawMutex, _>::new(i2c);
I2C_BUS.init(i2c_bus)
};
let i2c = I2cDevice::new(i2c_bus);
let interface = I2cInterface::new(i2c);
let mut imu = lsm6ds3tr::LSM6DS3TR::new(interface);
// imu.init().await.unwrap();
// imu.read_accel().await.unwrap();
unwrap!(spawner.spawn(write_task(class)));
}
struct Disconnected {}
impl From<EndpointError> for Disconnected {
fn from(val: EndpointError) -> Self {
match val {
EndpointError::BufferOverflow => panic!("Buffer overflow"),
EndpointError::Disabled => Disconnected {},
}
}
}
async fn echo(class: &mut CdcAcmClass<'static, MyDriver>) -> Result<(), Disconnected> {
let mut buf = [0; 64];
loop {
let n = class.read_packet(&mut buf).await?;
let data = &buf[..n];
info!("data: {:x}", data);
class.write_packet(data).await?;
}
}