pinetime-rs/src/main.rs
2020-06-20 18:53:49 +02:00

170 lines
5.6 KiB
Rust

#![no_std]
#![no_main]
mod monotonic_nrf52;
use nrf52832_hal as p_hal;
use p_hal::gpio::{GpioExt, Level};
use p_hal::nrf52832_pac as pac;
use p_hal::{delay::Delay, spim, twim};
use cortex_m_rt as rt;
use cst816s::CST816S;
use embedded_graphics::prelude::*;
use rt::entry;
use st7789::Orientation;
use core::cell::Cell;
use cstr_core::CStr;
use lvgl::input_device::{BufferStatus, InputData, Pointer};
use lvgl::style::Style;
use lvgl::widgets::{Btn, Label};
use lvgl::{self, Align, Color, Part, State, Widget, UI};
use crate::monotonic_nrf52::Instant;
use core::panic::PanicInfo;
use core::time::Duration;
use embedded_hal::blocking::delay::DelayMs;
use nrf52832_hal::prelude::ClocksExt;
pub type HalSpimError = p_hal::spim::Error;
pub type Spim0PortType = p_hal::spim::Spim<pac::SPIM0>;
pub type DisplaySckPinType = p_hal::gpio::p0::P0_18<p_hal::gpio::Output<p_hal::gpio::PushPull>>;
pub type DisplayMosiPinType = p_hal::gpio::p0::P0_26<p_hal::gpio::Output<p_hal::gpio::PushPull>>;
///
/// This example was written and tested for the PineTime smart watch
///
#[entry]
fn main() -> ! {
let cp = pac::CorePeripherals::take().unwrap();
let mut delay_source = Delay::new(cp.SYST);
// PineTime has a 32 MHz HSE (HFXO) and a 32.768 kHz LSE (LFXO)
// Optimize clock config
let dp = pac::Peripherals::take().unwrap();
let _clockit = dp.CLOCK.constrain().enable_ext_hfosc();
let port0 = dp.P0.split();
// internal i2c0 bus devices: BMA421 (accel), HRS3300 (hrs), CST816S (TouchPad)
// BMA421-INT: P0.08
// TP-INT: P0.28
let i2c0_pins = twim::Pins {
scl: port0.p0_07.into_floating_input().degrade(),
sda: port0.p0_06.into_floating_input().degrade(),
};
let i2c_port = twim::Twim::new(dp.TWIM1, i2c0_pins, twim::Frequency::K400);
// let i2c_bus0 = shared_bus::CortexMBusManager::new(i2c_port);
delay_source.delay_ms(1u8);
let spim0_pins = spim::Pins {
sck: port0.p0_02.into_push_pull_output(Level::Low).degrade(),
miso: None,
mosi: Some(port0.p0_03.into_push_pull_output(Level::Low).degrade()),
};
// create SPIM0 interface, 8 Mbps, use 122 as "over read character"
let spim0 = spim::Spim::new(dp.SPIM0, spim0_pins, spim::Frequency::M8, spim::MODE_3, 122);
let spi_bus0 = shared_bus::CortexMBusManager::new(spim0);
// backlight control pin for display: always on
let mut _backlight = port0.p0_22.into_push_pull_output(Level::Low);
// SPI chip select (CSN) for the display.
let display_csn = port0.p0_25.into_push_pull_output(Level::High);
// data/clock switch pin for display
let display_dc = port0.p0_18.into_push_pull_output(Level::Low);
// reset pin for display
let display_rst = port0.p0_26.into_push_pull_output(Level::Low);
// create display driver
let mut display = st7789::new_display_driver(
spi_bus0.acquire(),
display_csn,
display_dc,
display_rst,
lvgl::HOR_RES_MAX as u16,
lvgl::VER_RES_MAX as u16,
);
display.init(&mut delay_source).unwrap();
display.set_orientation(&Orientation::Portrait).unwrap();
// setup touchpad external interrupt pin: P0.28/AIN4 (TP_INT)
let touch_int = port0.p0_28.into_pullup_input().degrade();
// setup touchpad reset pin: P0.10/NFC2 (TP_RESET)
let touch_rst = port0.p0_10.into_push_pull_output(Level::High).degrade();
let mut touchpad = CST816S::new(i2c_port, touch_int, touch_rst);
touchpad.setup(&mut delay_source).unwrap();
// Initialize LVGL
let mut ui = UI::init().unwrap();
ui.disp_drv_register(display).unwrap();
// Define the initial state of the input
let mut latest_touch_point = Point::new(0, 0);
let mut latest_touch_status = InputData::Touch(latest_touch_point.clone())
.released()
.once();
// Register a new input device that's capable of reading the current state of the input
let mut touch_device = Pointer::new(|| latest_touch_status);
ui.indev_drv_register(&mut touch_device).unwrap();
// Create screen and widgets
let mut screen = ui.scr_act().unwrap();
// Draw a black background to the screen
let mut screen_style = Style::default();
screen_style.set_bg_color(State::DEFAULT, Color::from_rgb((0, 0, 0)));
screen.add_style(Part::Main, screen_style).unwrap();
// Create the button
let text_click_me = CStr::from_bytes_with_nul("Click me!\0".as_bytes()).unwrap();
let mut button = Btn::new(&mut screen).unwrap();
button
.set_align(&mut screen, Align::InLeftMid, 30, 0)
.unwrap();
button.set_size(180, 80).unwrap();
let mut btn_lbl = Label::new(&mut button).unwrap();
btn_lbl.set_text(text_click_me).unwrap();
let mut btn_state = false;
button
.on_event(|mut btn, event| {
if let lvgl::Event::Clicked = event {
btn_state = !btn_state;
btn.toggle().unwrap();
}
})
.unwrap();
let mut loop_start = Instant::now();
loop {
ui.task_handler();
if let Some(evt) = touchpad.read_one_touch_event(true) {
latest_touch_point = Point::new(evt.x, evt.y);
// Pressed
latest_touch_status = InputData::Touch(latest_touch_point.clone())
.pressed()
.once();
} else {
// Released
latest_touch_status = InputData::Touch(latest_touch_point.clone())
.released()
.once();
}
ui.tick_inc(Duration::from_millis(50));
//delay_source.delay_ms(2u32);
loop_start = Instant::now();
}
}
#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
loop {}
}