Initial commit
This commit is contained in:
commit
82d4a184a2
|
@ -0,0 +1,4 @@
|
|||
[target.'cfg(all(target_arch = "arm", target_os = "none"))']
|
||||
rustflags = [
|
||||
"-C", "link-arg=-Tlink.x",
|
||||
]
|
|
@ -0,0 +1,4 @@
|
|||
.gdb_history
|
||||
/template
|
||||
Cargo.lock
|
||||
target/
|
|
@ -0,0 +1,30 @@
|
|||
[package]
|
||||
authors = ["Henrik Böving <hargonix@gmail.com>"]
|
||||
edition = "2018"
|
||||
name = "i2c"
|
||||
version = "0.1.0"
|
||||
|
||||
[dependencies.microbit-v2]
|
||||
version = "0.12.0"
|
||||
git = "https://github.com/nrf-rs/microbit/"
|
||||
optional = true
|
||||
|
||||
|
||||
[dependencies.microbit]
|
||||
version = "0.12.0"
|
||||
git = "https://github.com/nrf-rs/microbit/"
|
||||
optional = true
|
||||
|
||||
[dependencies]
|
||||
cortex-m = "0.7.3"
|
||||
cortex-m-rt = "0.7.0"
|
||||
rtt-target = { version = "0.3.1", features = ["cortex-m"] }
|
||||
panic-rtt-target = { version = "0.1.2", features = ["cortex-m"] }
|
||||
nb = "1.0.0"
|
||||
heapless = "0.7.10"
|
||||
lsm303agr = "0.2.2"
|
||||
embedded-hal = "0.2.6"
|
||||
|
||||
[features]
|
||||
v2 = ["microbit-v2"]
|
||||
v1 = ["microbit"]
|
|
@ -0,0 +1,12 @@
|
|||
[default.general]
|
||||
# chip = "nrf52833_xxAA" # uncomment this line for micro:bit V2
|
||||
# chip = "nrf51822_xxAA" # uncomment this line for micro:bit V1
|
||||
|
||||
[default.reset]
|
||||
halt_afterwards = false
|
||||
|
||||
[default.rtt]
|
||||
enabled = true
|
||||
|
||||
[default.gdb]
|
||||
enabled = false
|
|
@ -0,0 +1,13 @@
|
|||
# mbsh - micro:bit shell
|
||||
|
||||
A UART interactive shell for the BBC micro:bit.
|
||||
|
||||
## Supported commands
|
||||
|
||||
- `clear`: Clears the terminal
|
||||
- `accelerometer`: Returns the accelerometer data
|
||||
- `magnetometer`: Returns the magnetometer data
|
||||
|
||||
## Demo
|
||||
|
||||
[![asciicast](https://asciinema.org/a/EYeh6pOV8neKA5e4HE2SYI5OQ.svg)](https://asciinema.org/a/EYeh6pOV8neKA5e4HE2SYI5OQ)
|
|
@ -0,0 +1,30 @@
|
|||
//! 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,
|
||||
//! a rebuild of the application with new memory settings is ensured after updating `memory.x`.
|
||||
|
||||
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");
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
MEMORY
|
||||
{
|
||||
/* NOTE K = KiBi = 1024 bytes */
|
||||
FLASH : ORIGIN = 0x00000000, LENGTH = 256K
|
||||
RAM : ORIGIN = 0x20000000, LENGTH = 16K
|
||||
}
|
|
@ -0,0 +1,134 @@
|
|||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
use cortex_m_rt::entry;
|
||||
use heapless::Vec;
|
||||
use rtt_target::{rtt_init_print, rprintln};
|
||||
use panic_rtt_target as _;
|
||||
use core::fmt::Write;
|
||||
|
||||
use microbit::hal::prelude::*;
|
||||
|
||||
#[cfg(feature = "v1")]
|
||||
use microbit::{
|
||||
hal::twi,
|
||||
pac::twi0::frequency::FREQUENCY_A,
|
||||
};
|
||||
|
||||
#[cfg(feature = "v2")]
|
||||
use microbit::{
|
||||
hal::twim,
|
||||
pac::twim0::frequency::FREQUENCY_A,
|
||||
};
|
||||
|
||||
use lsm303agr::{
|
||||
AccelOutputDataRate, Lsm303agr,
|
||||
};
|
||||
|
||||
#[cfg(feature = "v1")]
|
||||
use microbit::{
|
||||
hal::prelude::*,
|
||||
hal::uart,
|
||||
hal::uart::{Baudrate, Parity},
|
||||
};
|
||||
|
||||
#[cfg(feature = "v2")]
|
||||
use microbit::{
|
||||
hal::prelude::*,
|
||||
hal::uarte,
|
||||
hal::uarte::{Baudrate, Parity},
|
||||
};
|
||||
|
||||
#[cfg(feature = "v2")]
|
||||
mod serial_setup;
|
||||
#[cfg(feature = "v2")]
|
||||
use serial_setup::UartePort;
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
rtt_init_print!();
|
||||
let board = microbit::Board::take().unwrap();
|
||||
|
||||
|
||||
#[cfg(feature = "v1")]
|
||||
let mut i2c = { twi::Twi::new(board.TWI0, board.i2c.into(), FREQUENCY_A::K100) };
|
||||
|
||||
#[cfg(feature = "v2")]
|
||||
let mut i2c = { twim::Twim::new(board.TWIM0, board.i2c_internal.into(), FREQUENCY_A::K100) };
|
||||
|
||||
#[cfg(feature = "v1")]
|
||||
let mut serial = {
|
||||
uart::Uart::new(
|
||||
board.UART0,
|
||||
board.uart.into(),
|
||||
Parity::EXCLUDED,
|
||||
Baudrate::BAUD115200,
|
||||
)
|
||||
};
|
||||
|
||||
#[cfg(feature = "v2")]
|
||||
let mut serial = {
|
||||
let serial = uarte::Uarte::new(
|
||||
board.UARTE0,
|
||||
board.uart.into(),
|
||||
Parity::EXCLUDED,
|
||||
Baudrate::BAUD115200,
|
||||
);
|
||||
UartePort::new(serial)
|
||||
};
|
||||
|
||||
let mut sensor = Lsm303agr::new_with_i2c(i2c);
|
||||
sensor.init().unwrap();
|
||||
sensor.set_accel_odr(AccelOutputDataRate::Hz50);
|
||||
|
||||
let mut buffer: Vec<u8, 1024> = Vec::new();
|
||||
|
||||
write!(serial, "{}[2J$ ", 27 as char).unwrap();
|
||||
|
||||
loop {
|
||||
let byte = nb::block!(serial.read()).unwrap();
|
||||
nb::block!(serial.write(byte)).unwrap();
|
||||
|
||||
if byte == b'\r' {
|
||||
nb::block!(serial.write(b'\n')).unwrap();
|
||||
while let Some(b' ') = buffer.last() {
|
||||
buffer.pop();
|
||||
}
|
||||
let cmd = core::str::from_utf8(buffer.as_slice());
|
||||
match cmd {
|
||||
core::result::Result::Ok("accelerometer") => {
|
||||
rprintln!("INFO: Calculating accelerometer");
|
||||
let data = sensor.accel_data();
|
||||
match data {
|
||||
Result::Ok(data) => write!(serial, "x: {}, y: {}, z: {}\r\n", data.x, data.y, data.z).unwrap(),
|
||||
Result::Err(e) => {
|
||||
rprintln!("ERR: {:?}", e);
|
||||
write!(serial, "ERR: {:?}", e).unwrap();
|
||||
},
|
||||
}
|
||||
},
|
||||
core::result::Result::Ok("magnetometer") => {
|
||||
rprintln!("INFO: Calculating magnetometer");
|
||||
let data = nb::block!(sensor.mag_data()).unwrap();
|
||||
write!(serial, "x: {}, y: {}, z: {}\r\n", data.x, data.y, data.z).unwrap();
|
||||
|
||||
},
|
||||
core::result::Result::Ok("clear") => {
|
||||
write!(serial, "{}[2J", 27 as char).unwrap();
|
||||
},
|
||||
core::result::Result::Ok("") => {},
|
||||
core::result::Result::Ok(cmd) => write!(serial, "Unknown command: `{}`\r\n", cmd).unwrap(),
|
||||
core::result::Result::Err(e) => rprintln!("ERR: couldn't unwrap cmd: {}\r\n", e),
|
||||
}
|
||||
|
||||
buffer.clear();
|
||||
write!(serial, "$ ").unwrap();
|
||||
} else if byte == 8 {
|
||||
buffer.pop();
|
||||
} else if !(buffer.len() == 0 && byte == b' ') {
|
||||
buffer.push(byte);
|
||||
}
|
||||
|
||||
nb::block!(serial.flush()).unwrap();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
use core::fmt;
|
||||
use embedded_hal::blocking::serial as bserial;
|
||||
use embedded_hal::serial;
|
||||
use microbit::hal::uarte::{Error, Instance, Uarte, UarteRx, UarteTx};
|
||||
|
||||
static mut TX_BUF: [u8; 1] = [0; 1];
|
||||
static mut RX_BUF: [u8; 1] = [0; 1];
|
||||
|
||||
pub struct UartePort<T: Instance>(UarteTx<T>, UarteRx<T>);
|
||||
|
||||
impl<T: Instance> UartePort<T> {
|
||||
pub fn new(serial: Uarte<T>) -> UartePort<T> {
|
||||
let (tx, rx) = serial
|
||||
.split(unsafe { &mut TX_BUF }, unsafe { &mut RX_BUF })
|
||||
.unwrap();
|
||||
UartePort(tx, rx)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Instance> fmt::Write for UartePort<T> {
|
||||
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||
self.0.write_str(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Instance> serial::Write<u8> for UartePort<T> {
|
||||
type Error = Error;
|
||||
|
||||
fn write(&mut self, b: u8) -> nb::Result<(), Self::Error> {
|
||||
self.0.write(b)
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> nb::Result<(), Self::Error> {
|
||||
self.0.flush()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Instance> bserial::write::Default<u8> for UartePort<T> {}
|
||||
|
||||
impl<T: Instance> serial::Read<u8> for UartePort<T> {
|
||||
type Error = Error;
|
||||
|
||||
fn read(&mut self) -> nb::Result<u8, Self::Error> {
|
||||
self.1.read()
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue