266 lines
8.1 KiB
Rust
Raw Normal View History

2025-01-03 16:15:22 +01:00
#![no_main]
#![no_std]
2025-01-12 00:22:13 +01:00
mod common;
mod i2c;
2025-01-12 00:53:26 +01:00
mod lsm6ds;
2025-01-12 00:22:13 +01:00
2025-01-03 16:15:22 +01:00
use core::fmt::Write;
2025-01-12 00:22:13 +01:00
use embedded_alloc::LlffHeap;
2025-01-03 16:15:22 +01:00
use libm::sinf;
2025-01-12 00:53:26 +01:00
use lsm6ds::Lsm6ds33;
// use lsm6ds3tr::{
// interface::{I2cInterface, SpiInterface},
// LsmSettings, LSM6DS3TR,
// };
2025-01-12 00:22:13 +01:00
// use lsm6ds3tr::{interface::SpiInterface, AccelScale, LsmSettings, LSM6DS3TR};
2025-01-03 16:15:22 +01:00
use microflow::model;
use nalgebra::matrix;
2025-01-12 00:22:13 +01:00
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,
};
2025-01-03 16:15:22 +01:00
use heapless::String;
2025-01-12 00:22:13 +01:00
// const BATTERY_SERVICE: Uuid = Uuid::new_16(0x180f);
// const BATTERY_LEVEL: Uuid = Uuid::new_16(0x2a19);
// const LED_SERVICE_UUID: Uuid = Uuid::new_16(0x112f);
// const LED_CONTROL_CHAR_UUID: Uuid = Uuid::new_16(0x321f);
const RTC_FREQ_MHZ: f32 = 0.032_768;
#[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,
// }
2025-01-03 16:15:22 +01:00
#[panic_handler] // panicking behavior
fn panic(_: &core::panic::PanicInfo) -> ! {
reset_into_dfu();
}
#[model("tflite_demo/models/sine.tflite")]
struct Sine;
2025-01-12 00:22:13 +01:00
#[model("tflite_demo/models/speech.tflite")]
struct Speech;
2025-01-03 16:15:22 +01:00
/// 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
2025-01-12 00:22:13 +01:00
unsafe {
(*hal::pac::POWER::PTR).gpregret.write(|w| w.bits(0xB1));
};
hal::pac::SCB::sys_reset()
2025-01-03 16:15:22 +01:00
}
#[derive(Clone, Copy)]
enum LightState {
Red = 0,
Green = 1,
Blue = 2,
}
#[cortex_m_rt::entry]
fn main() -> ! {
2025-01-12 00:22:13 +01:00
{
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);
2025-01-03 16:15:22 +01:00
2025-01-12 00:22:13 +01:00
let clocks = hal::clocks::Clocks::new(p.CLOCK);
2025-01-03 16:15:22 +01:00
let clocks = clocks.enable_ext_hfosc();
2025-01-12 00:22:13 +01:00
let usb_peripheral = hal::usbd::UsbPeripheral::new(p.USBD, &clocks);
2025-01-03 16:15:22 +01:00
let usb_bus = UsbBusAllocator::new(hal::usbd::Usbd::new(usb_peripheral));
let mut serial_port = usbd_serial::SerialPort::new(&usb_bus);
2025-01-12 00:22:13 +01:00
// 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!");
2025-01-12 00:53:26 +01:00
// let scl = port0.p0_27.into_floating_input().degrade();
// let sda = port0.p0_07.into_floating_input().degrade();
2025-01-12 00:22:13 +01:00
2025-01-12 00:53:26 +01:00
// let pins = twim::Pins { scl: scl, sda: sda };
2025-01-12 00:22:13 +01:00
2025-01-12 00:53:26 +01:00
// let i2c = Twim::new(p.TWIM0, pins, twim::Frequency::K100);
2025-01-12 00:22:13 +01:00
2025-01-12 00:53:26 +01:00
// let i2c_interface = I2cInterface::new(i2c);
2025-01-12 00:22:13 +01:00
// let mut imu = LSM6DS3TR::new(I2cInterface::new(""));
2025-01-12 00:53:26 +01:00
// let mut imu = Lsm6ds33::new(i2c, addr);
2025-01-12 00:22:13 +01:00
let rtc = Rtc::new(p.RTC0, 0).unwrap();
2025-01-03 16:15:22 +01:00
rtc.enable_counter();
let mut usb_device = usb_device::device::UsbDeviceBuilder::new(
&usb_bus,
usb_device::device::UsbVidPid(0x16c0, 0x27dd),
)
2025-01-12 00:22:13 +01:00
.manufacturer("HSRW")
.product("HSRW Pet Tracker nRF52840")
.serial_number("pet1")
2025-01-03 16:15:22 +01:00
.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
2025-01-12 00:22:13 +01:00
let mut timer = hal::Timer::new(p.TIMER1).into_periodic();
2025-01-03 16:15:22 +01:00
timer.start(hal::Timer::<hal::pac::TIMER0>::TICKS_PER_SECOND);
let mut light = LightState::Red;
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 => {
2025-01-12 00:22:13 +01:00
led_red.set_state(PinState::High).unwrap();
led_green.set_state(PinState::High).unwrap();
led_blue.set_state(PinState::Low).unwrap();
2025-01-03 16:15:22 +01:00
//reset_into_dfu();
}
}
2025-01-12 00:22:13 +01:00
// if !usb_dev.poll(&mut [&mut serial]) {
// continue;
// }
let mut buf = [0u8; 64];
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();
}
}
if buf[..12].iter().all(|&x| x == 0) {
reset_into_dfu();
}
// Echo back in upper case
for c in buf[0..count].iter_mut() {
if 0x61 <= *c && *c <= 0x7a {
*c &= !0x20;
}
}
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;
}
_ => {}
}
}
}
_ => {}
}
2025-01-03 16:15:22 +01:00
let text = y_predicted.to_bits();
let mut data = String::<32>::new();
let text2 = y_exact.to_bits();
let mut data2 = String::<32>::new();
let _ = serial_port.write("Hello World\n".as_bytes());
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());
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());
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;
}
}
2025-01-12 00:22:13 +01:00
}