Added template for film scanner firmware

This commit is contained in:
2022-04-21 16:54:58 +02:00
parent e6126970a5
commit 971f150959
8 changed files with 707 additions and 235 deletions

230
firmware/Cargo.lock generated
View File

@@ -1,230 +0,0 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "ansi_term"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
dependencies = [
"winapi",
]
[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi",
"libc",
"winapi",
]
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "clap"
version = "2.34.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
dependencies = [
"ansi_term",
"atty",
"bitflags",
"strsim",
"textwrap",
"unicode-width",
"vec_map",
]
[[package]]
name = "heck"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
dependencies = [
"unicode-segmentation",
]
[[package]]
name = "hermit-abi"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
dependencies = [
"libc",
]
[[package]]
name = "jerk_control"
version = "0.1.0"
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.123"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb691a747a7ab48abc15c5b42066eaafde10dc427e3b6ee2a1cf43db04c763bd"
[[package]]
name = "motion-tester"
version = "0.1.0"
dependencies = [
"jerk_control",
"structopt",
]
[[package]]
name = "proc-macro-error"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
dependencies = [
"proc-macro-error-attr",
"proc-macro2",
"quote",
"syn",
"version_check",
]
[[package]]
name = "proc-macro-error-attr"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
dependencies = [
"proc-macro2",
"quote",
"version_check",
]
[[package]]
name = "proc-macro2"
version = "1.0.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec757218438d5fda206afc041538b2f6d889286160d649a86a24d37e1235afd1"
dependencies = [
"unicode-xid",
]
[[package]]
name = "quote"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1"
dependencies = [
"proc-macro2",
]
[[package]]
name = "strsim"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
[[package]]
name = "structopt"
version = "0.3.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c6b5c64445ba8094a6ab0c3cd2ad323e07171012d9c98b0b15651daf1787a10"
dependencies = [
"clap",
"lazy_static",
"structopt-derive",
]
[[package]]
name = "structopt-derive"
version = "0.4.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0"
dependencies = [
"heck",
"proc-macro-error",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "syn"
version = "1.0.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b683b2b825c8eef438b77c36a06dc262294da3d5a5813fac20da149241dcd44d"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
]
[[package]]
name = "textwrap"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
dependencies = [
"unicode-width",
]
[[package]]
name = "unicode-segmentation"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99"
[[package]]
name = "unicode-width"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
[[package]]
name = "unicode-xid"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
[[package]]
name = "vec_map"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

View File

@@ -1,2 +1,2 @@
[workspace] [workspace]
members = [ "jerk_control", "motion-tester" ] members = [ "jerk_control", "motion-tester", "film-scanner-fw" ]

View File

@@ -0,0 +1,89 @@
[package]
name = "film-scanner-fw"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
cortex-m = "0.7.3"
cortex-m-rt = "0.7.0"
cortex-m-rtic = "1.0.0"
embedded-hal = { version = "0.2.5", features=["unproven"] }
embedded-time = "0.12.0"
# jnc
usb-device = "0.2.8"
usbd-serial = "0.1.1"
usbd-hid = "0.5.1"
futures = { version = "0.3", default-features = false, optional = true }
defmt = "0.3.0"
defmt-rtt = "0.3.1"
panic-probe = { version = "0.3.0", features = ["print-defmt"] }
# We're using a Pico by default on this template
rp-pico = "0.2.0"
# but you can use any BSP. Uncomment this to use the pro_micro_rp2040 BSP instead
# sparkfun-pro-micro-rp2040 = "0.1.0"
# If you're not going to use a Board Support Package you'll need these:
rp2040-hal = { version="0.4.0", features=["rt"] }
rp2040-boot2 = {version="0.2.0", optional = true }
# cargo build/run
[profile.dev]
codegen-units = 1
debug = 2
debug-assertions = true
incremental = false
opt-level = 3
overflow-checks = true
# cargo build/run --release
[profile.release]
codegen-units = 1
debug = 2
debug-assertions = false
incremental = false
lto = 'fat'
opt-level = 3
overflow-checks = false
# do not optimize proc-macro crates = faster builds from scratch
[profile.dev.build-override]
codegen-units = 8
debug = false
debug-assertions = false
opt-level = 0
overflow-checks = false
[profile.release.build-override]
codegen-units = 8
debug = false
debug-assertions = false
opt-level = 0
overflow-checks = false
# cargo test
[profile.test]
codegen-units = 1
debug = 2
debug-assertions = true
incremental = false
opt-level = 3
overflow-checks = true
# cargo test --release
[profile.bench]
codegen-units = 1
debug = 2
debug-assertions = false
incremental = false
lto = 'fat'
opt-level = 3

View File

@@ -0,0 +1,31 @@
//! This build script copies the `memory.x` file from the crate root into
//! a directory where the linker can always find it at build time.
//! For many projects this is optional, as the linker always searches the
//! project root directory -- wherever `Cargo.toml` is. However, if you
//! are using a workspace or have a more complicated build setup, this
//! build script becomes required. Additionally, by requesting that
//! Cargo re-run the build script whenever `memory.x` is changed,
//! updating `memory.x` ensures a rebuild of the application with the
//! new memory settings.
use std::env;
use std::fs::File;
use std::io::Write;
use std::path::PathBuf;
fn main() {
// Put `memory.x` in our output directory and ensure it's
// on the linker search path.
let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap());
File::create(out.join("memory.x"))
.unwrap()
.write_all(include_bytes!("memory.x"))
.unwrap();
println!("cargo:rustc-link-search={}", out.display());
// By default, Cargo will re-run a build script whenever
// any file in the project changes. By specifying `memory.x`
// here, we ensure the build script is only re-run when
// `memory.x` is changed.
println!("cargo:rerun-if-changed=memory.x");
}

View File

@@ -0,0 +1,15 @@
MEMORY {
BOOT2 : ORIGIN = 0x10000000, LENGTH = 0x100
FLASH : ORIGIN = 0x10000100, LENGTH = 2048K - 0x100
RAM : ORIGIN = 0x20000000, LENGTH = 256K
}
EXTERN(BOOT2_FIRMWARE)
SECTIONS {
/* ### Boot loader */
.boot2 ORIGIN(BOOT2) :
{
KEEP(*(.boot2));
} > BOOT2
} INSERT BEFORE .text;

View File

@@ -0,0 +1,42 @@
// NOTE: This file came from:
// https://github.com/Nashenas88/dactyl-manuform-kb2040-rs/blob/main/src/fmt.rs
//! Formatting module for helping with logging over a serial connection. This
//! is useful on the kb2040 since there are no debugging pins exposed on the
//! board.
use core::fmt;
pub(crate) struct Wrapper<'a> {
buf: &'a mut [u8],
offset: usize,
}
impl<'a> Wrapper<'a> {
pub(crate) fn new(buf: &'a mut [u8]) -> Self {
Wrapper { buf, offset: 0 }
}
}
impl<'a> fmt::Write for Wrapper<'a> {
fn write_str(&mut self, s: &str) -> fmt::Result {
let bytes = s.as_bytes();
// Skip over already-copied data.
let remainder = &mut self.buf[self.offset..];
// Check if there is space remaining (return error instead of panicking).
if remainder.len() < bytes.len() {
return Err(core::fmt::Error);
}
// Make the two slices the same length.
let remainder = &mut remainder[..bytes.len()];
// Copy.
remainder.copy_from_slice(bytes);
// Update offset to avoid overwriting.
self.offset += bytes.len();
Ok(())
}
}

View File

@@ -0,0 +1,523 @@
#![no_std]
#![no_main]
use defmt_rtt as _;
use panic_probe as _;
mod fmt;
#[rtic::app(device = rp_pico::hal::pac, peripherals = true)]
mod app {
use crate::fmt::Wrapper;
use core::fmt::Write;
use embedded_hal::digital::v2::OutputPin;
use embedded_time::duration::Extensions;
use rp_pico::hal;
use rp_pico::pac;
use rp_pico::XOSC_CRYSTAL_FREQ;
// USB Device support
use usb_device::{class_prelude::*, prelude::*};
// USB Communications Class Device support
use usbd_serial::SerialPort;
// Blinck time 5 seconds
const SCAN_TIME_US: u32 = 5000000; // 200000; // 5000000; // 1000000; // 200000;
// IMPORTANT: The USB-Serial with RTIC github project example that I'm following.
// I tried to use the Pico board examples of USB-Serial (without interrupts
// and with interrupts with success, but when using with RTIC I could not make
// it work when merged with the RTIC example.) So I asked some questions
// in the in Matrix chat and received links to examples of there github
// project where it was working, then a used and adapted some parts there
// in this project template.
// This were the kind folks that helped me in the Matrix chat, the 3 projects
// that they suggest me to study are good examples of programs made with RTIC
// and USB and should be studied.
//
// Paul Daniel Faria
// https://github.com/Nashenas88/dactyl-manuform-kb2040-rs/blob/main/src/main.rs#L80
//
// see also:
// korken89
// https://github.com/korken89/pico-probe/tree/master/src
//
// see also:
// Mathias
// https://github.com/mgottschlag/rp2040-usb-sound-card/blob/b8078b57361c1b08755e5ab5f9992c56457ec18b/src/main.rs#L188
//
//
// Global Static variable, has to be written inside unsafe blocks.
// A reference can be obtained with as_ref() method.
pub struct Counter {
counter: u32,
enable: bool,
}
impl Counter {
fn new() -> Self {
Counter {
counter: 0_u32,
enable: true,
}
}
fn get(&self) -> u32 {
self.counter
}
fn reset(&mut self) {
self.counter = 0_u32;
}
fn increment(&mut self) {
self.counter += 1_u32;
}
fn enable(&mut self, state: bool) {
self.enable = state;
}
}
#[shared]
struct Shared {
timer: hal::Timer,
alarm: hal::timer::Alarm0,
led: hal::gpio::Pin<hal::gpio::pin::bank0::Gpio25, hal::gpio::PushPullOutput>,
led_blink_enable: bool,
serial: SerialPort<'static, hal::usb::UsbBus>,
usb_dev: usb_device::device::UsbDevice<'static, hal::usb::UsbBus>,
counter: Counter,
}
#[local]
struct Local {}
#[init(local = [usb_bus: Option<usb_device::bus::UsbBusAllocator<hal::usb::UsbBus>> = None])]
fn init(c: init::Context) -> (Shared, Local, init::Monotonics) {
//*******
// Initialization of the system clock.
let mut resets = c.device.RESETS;
let mut watchdog = hal::watchdog::Watchdog::new(c.device.WATCHDOG);
// Configure the clocks - The default is to generate a 125 MHz system clock
let clocks = hal::clocks::init_clocks_and_plls(
XOSC_CRYSTAL_FREQ,
c.device.XOSC,
c.device.CLOCKS,
c.device.PLL_SYS,
c.device.PLL_USB,
&mut resets,
&mut watchdog,
)
.ok()
.unwrap();
//*******
// Initialization of the USB and Serial and USB Device ID.
// USB
//
// Set up the USB driver
// The bus that is used to manage the device and class below.
let usb_bus: &'static _ =
c.local
.usb_bus
.insert(UsbBusAllocator::new(hal::usb::UsbBus::new(
c.device.USBCTRL_REGS,
c.device.USBCTRL_DPRAM,
clocks.usb_clock,
true,
&mut resets,
)));
// Set up the USB Communications Class Device driver.
let serial = SerialPort::new(usb_bus);
// Create a USB device with a fake VID and PID
let usb_dev = UsbDeviceBuilder::new(usb_bus, UsbVidPid(0x16c0, 0x27dd))
.manufacturer("Fake company")
.product("Serial port")
.serial_number("TEST")
.device_class(2) // from: https://www.usb.org/defined-class-codes
.build();
//*******
// Initialization of the LED GPIO and the timer.
let sio = hal::Sio::new(c.device.SIO);
let pins = rp_pico::Pins::new(
c.device.IO_BANK0,
c.device.PADS_BANK0,
sio.gpio_bank0,
&mut resets,
);
let mut led = pins.led.into_push_pull_output();
led.set_low().unwrap();
let mut timer = hal::Timer::new(c.device.TIMER, &mut resets);
let mut alarm = timer.alarm_0().unwrap();
let _ = alarm.schedule(SCAN_TIME_US.microseconds());
alarm.enable_interrupt(&mut timer);
// Enable led_blink.
let led_blink_enable = true;
// Reset the counter
let counter = Counter::new();
//********
// Return the Shared variables struct, the Local variables struct and the XPTO Monitonics
// (Note: Read again the RTIC book in the section of Monotonics timers)
(
Shared {
timer,
alarm,
led,
led_blink_enable,
serial,
usb_dev,
counter,
},
Local {},
init::Monotonics(),
)
}
/// Task that blinks the rp-pico onboard LED and that send a message "LED ON!" and "LED OFF!" do USB-Serial.
#[task(
binds = TIMER_IRQ_0,
priority = 1,
shared = [timer, alarm, led, led_blink_enable, serial, counter],
local = [tog: bool = true],
)]
fn timer_irq(mut cx: timer_irq::Context) {
let mut buf = [0u8; 64];
let led = cx.shared.led;
let led_blink_enable = cx.shared.led_blink_enable;
let counter = cx.shared.counter;
let tog = cx.local.tog;
// Blinks the LED ON / OFF.
(led, led_blink_enable, counter).lock(|led_a, led_blink_enable_a, counter_a| {
let led_state_str: &str;
if *led_blink_enable_a {
if *tog {
led_a.set_high().unwrap();
led_state_str = "ON ";
} else {
led_a.set_low().unwrap();
led_state_str = "OFF";
}
let _ = writeln!(
Wrapper::new(&mut buf),
"LED {}! counter = {}",
led_state_str,
counter_a.get()
);
}
if counter_a.enable {
counter_a.increment();
}
if *led_blink_enable_a {
*tog = !*tog;
}
});
// Clears the timer interrupt and Set's the new delta_time in the future.
let mut timer = cx.shared.timer;
let mut alarm = cx.shared.alarm;
(alarm).lock(|a| {
(timer).lock(|timer_a| {
a.clear_interrupt(timer_a);
let _ = a.schedule(SCAN_TIME_US.microseconds());
});
});
// Write the message "blabla! 2" do USB-Serial.
cx.shared.serial.lock(|s| {
write_serial(s, unsafe { core::str::from_utf8_unchecked(&buf) }, false);
});
/*
// Write the message "blabla! 2" do USB-Serial.
c.shared.serial.lock(|s| {
let mut buf = [0u8; 64];
let _ = writeln!(Wrapper::new(&mut buf), "blabla! {}", 2); /*"{:?}"*/
write_serial(s, unsafe { core::str::from_utf8_unchecked(&buf) }, false);
});
*/
}
/// Usb interrupt handler. Runs every time the host requests new data.
#[task(binds = USBCTRL_IRQ, priority = 3, shared = [led, led_blink_enable, serial, usb_dev, counter])]
fn usb_rx(cx: usb_rx::Context) {
let led = cx.shared.led;
let led_blink_enable = cx.shared.led_blink_enable;
let usb_dev = cx.shared.usb_dev;
let serial = cx.shared.serial;
let counter = cx.shared.counter;
(led, led_blink_enable, usb_dev, serial, counter).lock(
|led_a, led_blink_enable_a, usb_dev_a, serial_a, counter_a| {
// Check for new data
if usb_dev_a.poll(&mut [serial_a]) {
let mut buf = [0u8; 64];
match serial_a.read(&mut buf) {
Err(_e) => {
// Do nothing
// let _ = serial_a.write(b"Error.");
// let _ = serial_a.flush();
}
Ok(0) => {
// Do nothing
let _ = serial_a.write(b"Didn't received data.");
let _ = serial_a.flush();
}
Ok(_count) => {
match_usb_serial_buf(
&buf,
led_a,
led_blink_enable_a,
serial_a,
counter_a,
);
/*
// Code to echo the characters in Upper Case.
// Convert to upper case
buf.iter_mut().take(count).for_each(|b| {
b.make_ascii_uppercase();
});
if count > 0 {
let _ = serial_a.write(b"Received data! ");
let _ = serial_a.flush();
}
// Send back to the host
let mut wr_ptr = &buf[..count];
while !wr_ptr.is_empty() {
match serial_a.write(wr_ptr) {
Ok(len) => {
wr_ptr = &wr_ptr[len..];
// if wr_ptr.len() == 0 {
// let _ = serial_a.write(b"");
let _ = serial_a.flush();
// }
}
// On error, just drop unwritten data.
// One possible error is Err(WouldBlock), meaning the USB
// write buffer is full.
Err(_) => break,
};
}
*/
}
}
}
},
);
}
// Task with least priority that only runs when nothing else is running.
#[idle(local = [x: u32 = 0])]
fn idle(_cx: idle::Context) -> ! {
// Locals in idle have lifetime 'static
// let _x: &'static mut u32 = cx.local.x;
//hprintln!("idle").unwrap();
loop {
cortex_m::asm::nop();
}
}
/* New Tasks */
/// This function come from the github with USB-Serial example (see link above).
///
/// Helper function to ensure all data is written across the serial interface.
fn write_serial(serial: &mut SerialPort<'static, hal::usb::UsbBus>, buf: &str, block: bool) {
let write_ptr = buf.as_bytes();
// Because the buffer is of constant size and initialized to zero (0) we here
// add a test to determine the size that's really occupied by the str that we
// wan't to send. From index zero to first byte that is as the zero byte value.
let mut index = 0;
while index < write_ptr.len() && write_ptr[index] != 0 {
index += 1;
}
let mut write_ptr = &write_ptr[0..index];
while !write_ptr.is_empty() {
match serial.write(write_ptr) {
Ok(len) => write_ptr = &write_ptr[len..],
// Meaning the USB write buffer is full
Err(UsbError::WouldBlock) => {
if !block {
break;
}
}
// On error, just drop unwritten data.
Err(_) => break,
}
}
// let _ = serial.write("\n".as_bytes());
let _ = serial.flush();
}
fn match_usb_serial_buf(
buf: &[u8; 64],
led: &mut hal::gpio::Pin<hal::gpio::pin::bank0::Gpio25, hal::gpio::PushPullOutput>,
led_blink_enable: &mut bool,
serial: &mut SerialPort<'static, hal::usb::UsbBus>,
counter: &mut Counter,
) {
let _buf_len = buf.len();
match buf[0] {
// Print Menu
b'M' | b'm' => {
write_serial(serial, "M - Print Menu\n", false);
print_menu(serial);
}
// 0 - Reset counter
b'0' => {
write_serial(serial, "M - Print Menu\n", false);
counter.reset();
}
// 1 - Increment counter
b'1' => {
write_serial(serial, "1 - Increment counter\n", false);
counter.increment();
}
// 2 - Start continues counter
b'2' => {
write_serial(serial, "2 - Start continues counter\n", false);
counter.enable(true);
}
// 3 - Stop continues counter
b'3' => {
write_serial(serial, "3 - Stop continues counter\n", false);
counter.enable(false);
}
// 4 - Get switch and LED state
b'4' => {
write_serial(serial, "4 - Get switch and LED state\n", false);
// GPIO 25 onboard LED, we are going to read the bit 8 of the gpio_status register.
// OUTFROMPERI - output signal from selected peripheral, before register
// override is applied.
// See pag 272 of the Pico Datasets:
// https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf#_gpio_functions
let led_status_reg =
unsafe { (*pac::IO_BANK0::ptr()).gpio[25].gpio_status.read().bits() };
// Reserved bit.
// let sio_pin_value = unsafe { (*pac::SIO::ptr()).gpio_out.read().bits() };
let (led_bool, led_status) = if ((led_status_reg & 1 << 8) >> 8) == 1_u32 {
(true, "ON")
} else {
(false, "OFF")
};
let mut buf = [0u8; 64];
let _ = writeln!(
Wrapper::new(&mut buf),
"LED Status {:b}, {} LED {}",
led_status_reg,
led_bool,
led_status
);
write_serial(
serial,
unsafe { core::str::from_utf8_unchecked(&buf) },
false,
);
// unsafe { (*pac::TIMER::ptr()).timerawh.read().bits() };
}
// 5 - Set LED on
b'5' => {
write_serial(serial, "5 - Set LED on\n", false);
*led_blink_enable = false;
let _ = led.set_high();
}
// 6 - Set LED off
b'6' => {
write_serial(serial, "6 - Set LED off\n", false);
*led_blink_enable = false;
let _ = led.set_low();
}
// 7 - Set LED blink enable
b'7' => {
write_serial(serial, "7 - Set LED blink enable\n", false);
*led_blink_enable = true;
}
b'8' => {
write_serial(serial, "8 - Display data rate\n", false);
let data_rate = serial.line_coding().data_rate();
let mut buf = [0u8; 64];
let _ = writeln!(Wrapper::new(&mut buf), "Data rate: {} bit/s", data_rate);
write_serial(
serial,
unsafe { core::str::from_utf8_unchecked(&buf) },
false,
);
}
_ => {
write_serial(
serial,
unsafe { core::str::from_utf8_unchecked(buf) },
false,
);
write_serial(serial, "Invalid option!\n", false);
}
}
}
fn print_menu(serial: &mut SerialPort<'static, hal::usb::UsbBus>) {
let mut _buf = [0u8; 273];
// Create the Menu.
let menu_str = "*****************
* Menu:
*
* M / m - Print menu
* 0 - Reset counter
* 1 - Increment counter
* 2 - Start continues counter
* 3 - Stop continues counter
* 4 - Get switch and LED state
* 5 - Set LED on
* 6 - Set LED off
* 7 - Set LED blink enable
* 8 - Display data rate
*****************
Enter option: ";
write_serial(serial, menu_str, true);
// Send out the data to USB-Serial.
// let _ = serial.write(menu_str);
// let _ = writeln!(Wrapper::new(&mut buf), &menu_str);
// write_serial(serial, unsafe { core::str::from_utf8_unchecked(menu_str) });
}
}

View File

@@ -1,10 +1,12 @@
{ pkgs ? import <nixpkgs> {} }: { pkgs ? import <nixpkgs> {} }:
pkgs.mkShell { pkgs.mkShell {
buildInputs = [ buildInputs = with pkgs; [
pkgs.stdenv tio
stdenv
elf2uf2-rs
probe-run
# keep this line if you use bash # keep this line if you use bash
pkgs.bashInteractive bashInteractive
]; ];
} }