Skip to content

Commit

Permalink
Work (broken)
Browse files Browse the repository at this point in the history
  • Loading branch information
sky-dragn committed Feb 21, 2024
1 parent 4fe0c0a commit 52157f6
Show file tree
Hide file tree
Showing 39 changed files with 10,650 additions and 47 deletions.
1 change: 0 additions & 1 deletion .cargo/config.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
[target.'cfg(all(target_arch = "arm", target_os = "none"))']
# TODO(2) replace `$CHIP` with your chip's name (see `probe-rs chip list` output)
runner = "probe-rs run --chip STM32L412KBUx"
rustflags = [
"-C", "linker=flip-link",
Expand Down
12 changes: 7 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
# TODO fix `authors` and `name` if you didn't use `cargo-generate`
name = "gps-watch"
authors = ["Gary Bailey", "Carson Swoveland", "Twain Byrnes"]
edition = "2021"
version = "0.1.0"

Expand All @@ -9,21 +9,22 @@ cortex-m = { version = "0.7", features = ["critical-section-single-core"] }
defmt = { version = "0.3", features = ["encoding-rzcobs"] }
defmt-brtt = { version = "0.1", default-features = false, features = ["rtt"] }
panic-probe = { version = "0.3", features = ["print-defmt"] }
# TODO(4) Select the correct rtic backend
rtic = { version = "2.0.0", features = [ "thumbv7-backend" ] }
# TODO(5) Add hal as dependency
stm32l4xx-hal = { version = "0.7.1", features = ["stm32l442"] }
# TODO add a monotonic if you use scheduling
rtic-monotonics = { version = "1.0.0", features = [ "cortex-m-systick", "systick-100hz"]}
rtic-monotonics = { version = "1.0.0", features = ["cortex-m-systick", "systick-100hz"]}
thiserror = { version = "1.0.50", package = "thiserror-core", default-features = false }
embedded-graphics = "0.8.1"
tinyvec = "1.6.0"
#nmea0183 = "0.4.0"
ublox = { version = "0.4.5", default-features = false }

# cargo build/run
[profile.dev]
codegen-units = 1
debug = 2
debug-assertions = true # <-
incremental = false
lto = "fat"
opt-level = "s" # <-
overflow-checks = true # <-

Expand Down Expand Up @@ -58,6 +59,7 @@ overflow-checks = false # <-

[patch.crates-io]
stm32l4xx-hal = { path = "./stm32l4xx-hal" }
ublox = { path = "./ublox/ublox" }

# uncomment this to switch from the crates.io version of defmt to its git version
# check app-template's README for instructions
Expand Down
8 changes: 7 additions & 1 deletion gdb.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,15 @@ end

define flash
monitor program target/thumbv7em-none-eabihf/debug/minimal
file target/thumbv7em-none-eabihf/debug/minimal
monitor reset halt
end

define rebuild
shell cargo build
end

target remote localhost:1337

symbol-file target/thumbv7em-none-eabihf/debug/minimal
file target/thumbv7em-none-eabihf/debug/minimal
monitor reset halt
6 changes: 3 additions & 3 deletions memory.x
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
MEMORY
{
/* NOTE K = KiBi = 1024 bytes */
FLASH : ORIGIN = 0x8000000, LENGTH = 128K
RAM : ORIGIN = 0x20000000, LENGTH = 32K
FLASH : ORIGIN = 0x08000000, LENGTH = 128K
/* FLASH : ORIGIN = 0x08000000, LENGTH = 256K */
RAM : ORIGIN = 0x20000000, LENGTH = 32K
}

/* This is where the call stack will be allocated. */
Expand Down
1 change: 1 addition & 0 deletions openocd.cfg
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
telnet_port 4444
# compat with `probe-rs gdb`
gdb_port 1337

source [find interface/stlink.cfg]
Expand Down
103 changes: 75 additions & 28 deletions src/bin/minimal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,45 +3,55 @@
#![feature(type_alias_impl_trait)]

use gps_watch as _;
use stm32l4xx_hal as hal;

use hal::{pac, prelude::*};
use stm32l4xx_hal::{self as hal, pac, prelude::*};
use rtic_monotonics::create_systick_token;
use rtic_monotonics::systick::Systick;
use stm32l4xx_hal::gpio::{Alternate, Output, PA11, PB3, PB4, PB5, PinExt, PushPull};
use stm32l4xx_hal::gpio::{Alternate, Output, PA10, PA11, PA9, PB3, PB4, PB5, PushPull};
use stm32l4xx_hal::hal::spi::{Mode, Phase, Polarity};
use stm32l4xx_hal::pac::SPI1;
use stm32l4xx_hal::pac::{SPI1, USART1};
use stm32l4xx_hal::spi::Spi;
use defmt::{trace, info};
use core::num::Wrapping;
use embedded_graphics::primitives::PrimitiveStyle;
use embedded_graphics::prelude::*;
use embedded_graphics::pixelcolor::BinaryColor;
use embedded_graphics::primitives::Rectangle;
use stm32l4xx_hal::serial::Serial;
use core::fmt::Write;
use rtic::Mutex;

use stm32l4xx_hal::pac::Interrupt;
use stm32l4xx_hal::rcc::{ClockSecuritySystem, CrystalBypass};
use stm32l4xx_hal::rtc::{Event, RtcClockSource, RtcConfig};
use stm32l4xx_hal::serial;
use stm32l4xx_hal::serial::Config;
use gps_watch::gps::Gps;

// Rename type to squash generics
type SharpMemDisplay = gps_watch::display::SharpMemDisplay<
Spi<SPI1, (
PB3<Alternate<PushPull, 5>>,
PB4<Alternate<PushPull, 5>>,
PB5<Alternate<PushPull, 5>>
)>, PA11<Output<PushPull>>>;

type GpsUart = Serial<USART1, (PA9<Alternate<PushPull, 7>>, PA10<Alternate<PushPull, 7>>)>;

#[rtic::app(
device = stm32l4xx_hal::pac,
// peripherals = true,
// TODO: Replace the `FreeInterrupt1, ...` with free interrupt vectors if software tasks are used
// You can usually find the names of the interrupt vectors in the some_hal::pac::interrupt enum.
dispatchers = [EXTI0],
)]
mod app {
use embedded_graphics::pixelcolor::BinaryColor;
use embedded_graphics::primitives::Rectangle;
use super::*;

// Shared resources go here
#[shared]
struct Shared {
display: SharpMemDisplay
display: SharpMemDisplay,
gps: Gps<GpsUart>
}

// Local resources go here
Expand All @@ -51,7 +61,7 @@ mod app {
}

#[init]
fn init(cx: init::Context) -> (Shared, Local) {
fn init(mut cx: init::Context) -> (Shared, Local) {
trace!("init enter");

// Configure clocks
Expand All @@ -65,53 +75,78 @@ mod app {
let mut flash = cx.device.FLASH.constrain();
let mut rcc = cx.device.RCC.constrain();
let mut pwr = cx.device.PWR.constrain(&mut rcc.apb1r1);
// let clocks = rcc.cfgr.lse(CrystalBypass::Disable, ClockSecuritySystem::Disable).freeze(&mut flash.acr, &mut pwr);
let clocks = rcc.cfgr.freeze(&mut flash.acr, &mut pwr);

// Create SysTick monotonic for task scheduling
Systick::start(
cx.core.SYST,
4_000_000,
// 200_000,
clocks.sysclk().raw(),
create_systick_token!()
);

// Initialize SPI
let mut gpioa = cx.device.GPIOA.split(&mut rcc.ahb2);
let mut gpiob = cx.device.GPIOB.split(&mut rcc.ahb2);

// Initialize SPI and display
let mut cs = gpioa.pa11.into_push_pull_output(&mut gpioa.moder, &mut gpioa.otyper);
cs.set_low();
let sck = gpiob.pb3.into_alternate(&mut gpiob.moder, &mut gpiob.otyper, &mut gpiob.afrl);
let mosi = gpiob.pb5.into_alternate(&mut gpiob.moder, &mut gpiob.otyper, &mut gpiob.afrl);
let miso = gpiob.pb4.into_alternate(&mut gpiob.moder, &mut gpiob.otyper, &mut gpiob.afrl);

// <cs as hal::hal::digital::v2::OutputPin>;
let mut sck = gpiob.pb3.into_alternate(&mut gpiob.moder, &mut gpiob.otyper, &mut gpiob.afrl);
let mut mosi = gpiob.pb5.into_alternate(&mut gpiob.moder, &mut gpiob.otyper, &mut gpiob.afrl);
let mut miso = gpiob.pb4.into_alternate(&mut gpiob.moder, &mut gpiob.otyper, &mut gpiob.afrl);


let SPI1_COPY = unsafe { core::ptr::read(&cx.device.SPI1) };
let spi1 = hal::spi::Spi::spi1(
cx.device.SPI1,
(sck, miso, mosi),
Mode {
phase: Phase::CaptureOnFirstTransition,
polarity: Polarity::IdleLow
},
true,
1.MHz(),
clocks,
&mut rcc.apb2
);
// SPI1_COPY.cr1.write(|w| w.lsbfirst().lsbfirst());
// let spi1_cr1 = 0x4001_3000 as *mut u32;
// unsafe { core::ptr::write_volatile(spi1_cr1, core::ptr::read_volatile(spi1_cr1) | (1u32 << 7)); }

let mut display: SharpMemDisplay = SharpMemDisplay::new(spi1, cs);
let display = SharpMemDisplay::new(spi1, cs);

// Initialize RTC and interrupts
// let mut rtc = hal::rtc::Rtc::rtc(
// cx.device.RTC,
// &mut rcc.apb1r1,
// &mut rcc.bdcr,
// &mut pwr.cr1,
// RtcConfig::default().clock_config(RtcClockSource::LSE)
// );
// rtc.wakeup_timer().start(10000u16);
// rtc.listen(&mut cx.device.EXTI, Event::WakeupTimer);
// rtic::pend(Interrupt::RTC_WKUP);

// Initialize UART for GPS
let tx = gpioa.pa9.into_alternate(&mut gpioa.moder, &mut gpioa.otyper, &mut gpioa.afrh);
let rx = gpioa.pa10.into_alternate(&mut gpioa.moder, &mut gpioa.otyper, &mut gpioa.afrh);

let mut gps_uart = hal::serial::Serial::usart1(
cx.device.USART1,
(tx, rx),
Config::default().baudrate(115200.bps()),
clocks,
&mut rcc.apb2
);
gps_uart.listen(serial::Event::Rxne);
rtic::pend(Interrupt::USART1);

let gps = Gps::new(gps_uart);

// Spawn tasks
display_task::spawn().unwrap();

info!("done initializing!");
trace!("init exit");
(
Shared {
display
display,
gps
},
Local {
// Initialization of local resources go here
Expand All @@ -127,7 +162,9 @@ mod app {
// let device_stolen = unsafe { pac::Peripherals::steal() };

loop {
core::hint::spin_loop();
trace!("idle spin");
rtic::export::wfi();

// Sleep
// rtic::export::wfi();
// defmt::info!("hewo 1");
Expand All @@ -145,6 +182,16 @@ mod app {
}
}

#[task(binds = USART1, shared = [gps])]
fn on_uart(mut cx: on_uart::Context) {
cx.shared.gps.lock(|gps| gps.handle());
}

#[task(binds = RTC_WKUP)]
fn on_rtc(_cx: on_rtc::Context) {
info!("rtc wakeup!");
}

// TODO: Add tasks
#[task(
priority = 1,
Expand All @@ -156,15 +203,15 @@ mod app {

let mut i = Wrapping(0u8);
loop {
Systick::delay(500.millis()).await;
let stroke = PrimitiveStyle::with_stroke(BinaryColor::On, 3);
let rect_styled = Rectangle { top_left: Point {x: i.0 as i32, y: i.0 as i32}, size: Size { width: 20, height: 20 } }
.into_styled(stroke);
cx.shared.display.lock(|display| {
rect_styled.draw(display).unwrap();
display.flush();
});
info!("hello world");
Systick::delay(500.millis()).await;
// info!("loop {}", i.0);
i += 1;
}
}
Expand Down
40 changes: 31 additions & 9 deletions src/display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ const HEIGHT: usize = 240;
const WIDTH_BYTES: usize = WIDTH.div_ceil(8);
const HEIGHT_BYTES: usize = HEIGHT.div_ceil(8);

const UPDATE_BIT: u8 = 0b0000_0001;
const VCOM_BIT: u8 = 0b0000_0010;
const CLEAR_BIT: u8 = 0b0000_0100;

// #[derive(thiserror::Error, Debug)]
// pub enum DisplayError {
Expand Down Expand Up @@ -46,12 +48,12 @@ impl<'a, SPI, CS> SpiTransaction<'a, SPI, CS>
}
}

fn send(mut self, data: &[u8]) -> Self {
fn send(self, data: &[u8]) -> Self {
self.spi.write(data).unwrap();
self
}

fn finish(mut self) {
fn finish(self) {
self.cs.set_low().unwrap();
}
}
Expand Down Expand Up @@ -80,17 +82,18 @@ impl<SPI, CS> SharpMemDisplayDriver<SPI, CS>
}

pub fn clear(&mut self) {
self.start(0b0000_0100).send(&[0x00]).finish();
self.start(CLEAR_BIT).send(&[0x00]).finish();
}

pub fn write_line(&mut self, line: u8, data: &[u8; WIDTH_BYTES]) {
self.start(0b0000_0001).send(&[line]).send(data).send(&[0x00, 0x00]).finish();
self.start(UPDATE_BIT).send(&[line]).send(data).send(&[0x00, 0x00]).finish();
}
}

pub struct SharpMemDisplay<SPI, CS> {
buf: [[u8; WIDTH_BYTES]; HEIGHT],
dirty: [u8; HEIGHT_BYTES],
dirty_any: bool,
driver: SharpMemDisplayDriver<SPI, CS>
}

Expand All @@ -102,6 +105,7 @@ impl<SPI, CS> SharpMemDisplay<SPI, CS>
Self {
buf: [[0; WIDTH_BYTES]; HEIGHT],
dirty: [0; HEIGHT_BYTES],
dirty_any: false,
driver: SharpMemDisplayDriver::new(spi, cs)
}
}
Expand All @@ -114,21 +118,39 @@ impl<SPI, CS> SharpMemDisplay<SPI, CS>
self.buf[y][x / 8] &= !(1u8 << (x % 8));
}
self.dirty[y / 8] |= 1u8 << (y % 8);
self.dirty_any = true;
}

pub fn flush(&mut self) {
for y in 0usize..HEIGHT {
if (self.dirty[y / 8] & (1u8 << (y % 8))) != 0u8 {
self.driver.write_line(y as u8, &self.buf[y]);
}
// Don't send anything if there's nothing to flush
if !self.dirty_any {
return
}
// For each line
self.buf.iter().enumerate()
// If the line is dirty
.filter(|(y, row)| (self.dirty[y / 8] & (1u8 << (y % 8))) != 0u8)
// Send it
.fold(
self.driver.start(UPDATE_BIT), // command byte
|trn, (y, row)|
trn.send(&[y as u8]) // address byte
.send(row) // row data
.send(&[0x00]) // spacing byte
)
.send(&[0x00]) // termination byte
.finish();

// Clear dirty bits
self.dirty = [0; HEIGHT_BYTES];
self.dirty_any = false;
}

pub fn clear(&mut self) {
self.driver.clear();
self.buf = [[0xFF; WIDTH_BYTES]; HEIGHT];
self.dirty = [0; HEIGHT_BYTES];
self.driver.clear();
self.dirty_any = false;
}
}

Expand Down
Loading

0 comments on commit 52157f6

Please sign in to comment.