209 lines
6.1 KiB
Rust
209 lines
6.1 KiB
Rust
#![no_main]
|
|
#![no_std]
|
|
use defmt_rtt as _; // global logger
|
|
|
|
use panic_probe as _;
|
|
use stm32f1xx_hal as _;
|
|
|
|
// same panicking *behavior* as `panic-probe` but doesn't print a panic message
|
|
// this prevents the panic message being printed *twice* when `defmt::panic` is invoked
|
|
#[defmt::panic_handler]
|
|
fn panic() -> ! {
|
|
cortex_m::asm::udf()
|
|
}
|
|
|
|
use rtic::app;
|
|
|
|
mod si5153;
|
|
|
|
#[app(device = stm32f1xx_hal::pac)]
|
|
mod app {
|
|
use stm32f1xx_hal::{
|
|
delay::Delay,
|
|
gpio::{gpiob, gpioc, Alternate, Floating, Input, OpenDrain, Output, PushPull},
|
|
i2c,
|
|
i2c::BlockingI2c,
|
|
pac::I2C1,
|
|
pac::{self, Interrupt},
|
|
prelude::*,
|
|
prelude::*,
|
|
serial::{Config, Serial},
|
|
stm32,
|
|
timer::{Event, Timer},
|
|
};
|
|
|
|
use nmea0183::{datetime::Time, ParseResult, Parser};
|
|
|
|
use crate::si5153::Si5153;
|
|
|
|
type AppI2C1 = BlockingI2c<
|
|
I2C1,
|
|
(
|
|
gpiob::PB6<Alternate<OpenDrain>>,
|
|
gpiob::PB7<Alternate<OpenDrain>>,
|
|
),
|
|
>;
|
|
|
|
#[shared]
|
|
struct Shared {
|
|
i2c: AppI2C1,
|
|
time: Time,
|
|
}
|
|
|
|
#[local]
|
|
struct Local {
|
|
gps_parser: Parser,
|
|
usart: Serial<
|
|
stm32::USART3,
|
|
(
|
|
gpiob::PB10<Alternate<PushPull>>,
|
|
gpiob::PB11<Input<Floating>>,
|
|
),
|
|
>,
|
|
board_led: gpioc::PC13<Output<PushPull>>,
|
|
pll: Si5153<AppI2C1>,
|
|
}
|
|
|
|
#[init]
|
|
fn init(_: init::Context) -> (Shared, Local, init::Monotonics) {
|
|
// Get access to the core peripherals from the cortex-m crate
|
|
let cp = cortex_m::Peripherals::take().unwrap();
|
|
// Get access to the device specific peripherals from the peripheral access crate
|
|
let dp = pac::Peripherals::take().unwrap();
|
|
|
|
// Take ownership over the raw flash and rcc devices and convert them into the corresponding
|
|
// HAL structs
|
|
let mut flash = dp.FLASH.constrain();
|
|
|
|
let mut rcc = dp.RCC.constrain();
|
|
|
|
// Freeze the configuration of all the clocks in the system and store the frozen frequencies in
|
|
// `clocks`
|
|
let clocks = rcc
|
|
.cfgr
|
|
.use_hse(8.mhz())
|
|
.sysclk(72.mhz())
|
|
.pclk1(36.mhz())
|
|
.freeze(&mut flash.acr);
|
|
|
|
defmt::info!("Clock Setup done");
|
|
|
|
let mut timer = Timer::tim2(dp.TIM2, &clocks, &mut rcc.apb1).start_count_down(1.khz());
|
|
// Generate an interrupt when the timer expires
|
|
timer.listen(Event::Update);
|
|
|
|
// Acquire the GPIOC peripheral
|
|
let mut gpiob = dp.GPIOB.split(&mut rcc.apb2);
|
|
let mut gpioc = dp.GPIOC.split(&mut rcc.apb2);
|
|
|
|
let mut afio = dp.AFIO.constrain(&mut rcc.apb2);
|
|
|
|
let board_led = gpioc.pc13.into_push_pull_output(&mut gpioc.crh);
|
|
|
|
// USART3
|
|
// Configure pb10 as a push_pull output, this will be the tx pin
|
|
let tx = gpiob.pb10.into_alternate_push_pull(&mut gpiob.crh);
|
|
// Take ownership over pb11
|
|
let rx = gpiob.pb11;
|
|
|
|
// Set up the usart device. Taks ownership over the USART register and tx/rx pins. The rest of
|
|
// the registers are used to enable and configure the device.
|
|
let usart = Serial::usart3(
|
|
dp.USART3,
|
|
(tx, rx),
|
|
&mut afio.mapr,
|
|
Config::default().baudrate(9600.bps()),
|
|
clocks,
|
|
&mut rcc.apb1,
|
|
);
|
|
|
|
let gps_parser = Parser::new();
|
|
|
|
let scl = gpiob.pb6.into_alternate_open_drain(&mut gpiob.crl);
|
|
let sda = gpiob.pb7.into_alternate_open_drain(&mut gpiob.crl);
|
|
let i2c = i2c::BlockingI2c::i2c1(
|
|
dp.I2C1,
|
|
(scl, sda),
|
|
&mut afio.mapr,
|
|
i2c::Mode::Standard {
|
|
frequency: 400_000.hz(),
|
|
},
|
|
clocks,
|
|
&mut rcc.apb1,
|
|
5,
|
|
1,
|
|
5,
|
|
5,
|
|
);
|
|
|
|
let pll = Si5153::new(&i2c);
|
|
|
|
let time = Time {
|
|
hours: 0,
|
|
minutes: 0,
|
|
seconds: 0.0,
|
|
};
|
|
|
|
(
|
|
Shared { i2c, time },
|
|
Local {
|
|
gps_parser,
|
|
usart,
|
|
board_led,
|
|
pll,
|
|
},
|
|
init::Monotonics(),
|
|
)
|
|
}
|
|
|
|
#[task(binds = USART3, local=[usart, board_led, gps_parser], shared=[time])]
|
|
fn usart3(mut ctx: usart3::Context) {
|
|
match ctx.local.usart.read() {
|
|
Ok(byte) => {
|
|
ctx.local.board_led.toggle().unwrap();
|
|
if let Some(result) = ctx.local.gps_parser.parse_from_byte(byte) {
|
|
match result {
|
|
Ok(ParseResult::GGA(Some(gga))) => {
|
|
ctx.shared.time.lock(|time| {
|
|
time.hours = gga.time.hours;
|
|
time.minutes = gga.time.minutes;
|
|
time.seconds = gga.time.seconds;
|
|
});
|
|
/*
|
|
self.locator = loc::locator_from_coordinates(
|
|
gga.latitude.as_f64(),
|
|
gga.longitude.as_f64(),
|
|
);
|
|
defmt::info!("Got GGA. New locator: {}", self.locator.as_str());
|
|
*/
|
|
}
|
|
Ok(_) => {} // Some other sentences..
|
|
Err(_) => {} // Got parse error
|
|
}
|
|
}
|
|
}
|
|
Err(nb::Error::WouldBlock) => {}
|
|
Err(nb::Error::Other(_)) => {}
|
|
}
|
|
}
|
|
|
|
#[task(binds = TIM2, shared=[time])]
|
|
fn tim2(mut ctx: tim2::Context) {
|
|
ctx.shared.time.lock(|time| {
|
|
time.seconds += 0.001;
|
|
|
|
if time.seconds >= 60.0 {
|
|
time.seconds -= 60.0;
|
|
time.minutes += 1;
|
|
}
|
|
if time.minutes == 60 {
|
|
time.minutes = 0;
|
|
time.hours += 1;
|
|
}
|
|
if time.hours == 24 {
|
|
time.hours = 0;
|
|
}
|
|
});
|
|
}
|
|
}
|