Touch working
This commit is contained in:
parent
e4c6104c51
commit
99d084fdb4
5 changed files with 228 additions and 75 deletions
29
Cargo.lock
generated
29
Cargo.lock
generated
|
@ -219,8 +219,6 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "cst816s"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "988624bfaeaa34565792f7badc33cd02e84ba51fff4bbc3cd76f59d4af5658e7"
|
||||
dependencies = [
|
||||
"cortex-m 0.6.2",
|
||||
"embedded-hal",
|
||||
|
@ -242,22 +240,6 @@ version = "0.2.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7313c0d620d0cb4dbd9d019e461a4beb501071ff46ec0ab933efb4daa76d73e3"
|
||||
|
||||
[[package]]
|
||||
name = "display-interface"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07dda8d2dfb92b17bff0395151e8fe7f266f0923c75383200c09bc7ef472f28f"
|
||||
|
||||
[[package]]
|
||||
name = "display-interface-spi"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "63d2de9922255f2313ce64ffcf587c4380c7a54accc1ba0e02dbf8af16caacd4"
|
||||
dependencies = [
|
||||
"display-interface",
|
||||
"embedded-hal",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "embedded-graphics"
|
||||
version = "0.6.2"
|
||||
|
@ -416,7 +398,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "lvgl-codegen"
|
||||
version = "0.4.0"
|
||||
version = "0.5.0"
|
||||
dependencies = [
|
||||
"Inflector",
|
||||
"lazy_static",
|
||||
|
@ -428,7 +410,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "lvgl-sys"
|
||||
version = "0.4.0"
|
||||
version = "0.5.0"
|
||||
dependencies = [
|
||||
"bindgen",
|
||||
"cc",
|
||||
|
@ -644,11 +626,10 @@ checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2"
|
|||
|
||||
[[package]]
|
||||
name = "st7789"
|
||||
version = "0.2.2"
|
||||
source = "git+https://github.com/tstellanova/st7789#b1fe2c7af1947a044f37665315ddb28d9845b3ec"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ccc7b7e79f9e578e981bfab45b502b72ca02717a4356df0478228a6ff7c47c4"
|
||||
dependencies = [
|
||||
"display-interface",
|
||||
"display-interface-spi",
|
||||
"embedded-graphics",
|
||||
"embedded-hal",
|
||||
"heapless",
|
||||
|
|
|
@ -9,13 +9,13 @@ license = "BSD-3-Clause"
|
|||
cortex-m = "0.6"
|
||||
cortex-m-rt = "0.6"
|
||||
embedded-graphics = "0.6"
|
||||
embedded-hal = "0.2"
|
||||
nrf52832-hal = {version = "0.8.1", default-features = false, features = ["xxAA-package", "rt"]}
|
||||
embedded-hal = {version ="0.2.3", features = ["unproven"] }
|
||||
#nrf52832-hal = { version = "0.10", default-features = false, features = ["xxAA-package", "rt"] }
|
||||
nrf52832-hal = {version = "0.8.1", default-features = false, features = ["xxAA-package", "rt"]}
|
||||
shared-bus = {version = "0.1.4", features = ["cortexm"] }
|
||||
st7789 = { git = "https://github.com/tstellanova/st7789" }
|
||||
cst816s = "0.1.4"
|
||||
st7789 = { version = "0.2", features = ["graphics", "batch", "buffer"], default-features = false }
|
||||
cstr_core = "0.2.0"
|
||||
cst816s = { path = "../cst816s" }
|
||||
lvgl = { path = "../lvgl-rs/lvgl" }
|
||||
|
||||
[profile.dev]
|
||||
|
|
85
src/backlight.rs
Normal file
85
src/backlight.rs
Normal file
|
@ -0,0 +1,85 @@
|
|||
use embedded_hal::digital::v2::OutputPin;
|
||||
use nrf52832_hal::gpio::{Output, Pin, PushPull};
|
||||
|
||||
/// Control the backlight.
|
||||
///
|
||||
/// There are three active-low backlight pins, each connected to a FET that
|
||||
/// toggles backlight power through a resistor.
|
||||
///
|
||||
/// - Low: 2.2 kΩ
|
||||
/// - Mid: 100 Ω
|
||||
/// - High: 30 Ω
|
||||
///
|
||||
/// Through combinations of these pins, 7 brightness levels (+ off) can be
|
||||
/// configured.
|
||||
pub struct Backlight {
|
||||
low: Pin<Output<PushPull>>,
|
||||
mid: Pin<Output<PushPull>>,
|
||||
high: Pin<Output<PushPull>>,
|
||||
|
||||
/// The current brightness level (value between 0 and 7).
|
||||
brightness: u8,
|
||||
}
|
||||
|
||||
impl Backlight {
|
||||
/// Initialize the backlight with the specified level (0–7).
|
||||
pub fn init(
|
||||
low: Pin<Output<PushPull>>,
|
||||
mid: Pin<Output<PushPull>>,
|
||||
high: Pin<Output<PushPull>>,
|
||||
brightness: u8,
|
||||
) -> Self {
|
||||
let mut backlight = Self {
|
||||
low,
|
||||
mid,
|
||||
high,
|
||||
brightness,
|
||||
};
|
||||
backlight.set(brightness);
|
||||
backlight
|
||||
}
|
||||
|
||||
/// Set the brightness level. Must be a value between 0 (off) and 7 (max
|
||||
/// brightness). Higher values are clamped to 7.
|
||||
pub fn set(&mut self, mut brightness: u8) {
|
||||
if brightness > 7 {
|
||||
brightness = 7;
|
||||
}
|
||||
if brightness & 0x01 > 0 {
|
||||
self.low.set_low().unwrap();
|
||||
} else {
|
||||
self.low.set_high().unwrap();
|
||||
}
|
||||
if brightness & 0x02 > 0 {
|
||||
self.mid.set_low().unwrap();
|
||||
} else {
|
||||
self.mid.set_high().unwrap();
|
||||
}
|
||||
if brightness & 0x04 > 0 {
|
||||
self.high.set_low().unwrap();
|
||||
} else {
|
||||
self.high.set_high().unwrap();
|
||||
}
|
||||
self.brightness = brightness;
|
||||
}
|
||||
|
||||
/// Turn off the backlight.
|
||||
pub fn off(&mut self) {
|
||||
self.set(0);
|
||||
}
|
||||
|
||||
/// Increase backlight brightness.
|
||||
pub fn brighter(&mut self) {
|
||||
self.set(self.brightness + 1);
|
||||
}
|
||||
|
||||
/// Decrease backlight brightness.
|
||||
pub fn darker(&mut self) {
|
||||
self.set(self.brightness - 1);
|
||||
}
|
||||
|
||||
/// Return the current brightness level (value between 0 and 7).
|
||||
pub fn get_brightness(&self) -> u8 {
|
||||
self.brightness
|
||||
}
|
||||
}
|
31
src/delay.rs
Normal file
31
src/delay.rs
Normal file
|
@ -0,0 +1,31 @@
|
|||
//! Delay implementation using regular timers.
|
||||
//!
|
||||
//! This is done because RTFM takes ownership of SYST, and the nrf52-hal by
|
||||
//! default also wants SYST for its Delay implementation.
|
||||
|
||||
use embedded_hal::blocking::delay::DelayUs;
|
||||
use hal::nrf52832_pac as pac;
|
||||
use nrf52832_hal::prelude::TimerExt;
|
||||
use nrf52832_hal::{self as hal, timer::Timer};
|
||||
|
||||
pub struct TimerDelay {
|
||||
timer: hal::Timer<pac::TIMER0>,
|
||||
}
|
||||
|
||||
impl TimerDelay {
|
||||
pub fn new(timer0: pac::TIMER0) -> Self {
|
||||
Self {
|
||||
//timer: Timer::new(timer0),
|
||||
timer: timer0.constrain(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DelayUs<u32> for TimerDelay {
|
||||
fn delay_us(&mut self, us: u32) {
|
||||
// Currently the HAL timer is hardcoded at 1 MHz,
|
||||
// so 1 cycle = 1 µs.
|
||||
let cycles = us;
|
||||
self.timer.delay(cycles);
|
||||
}
|
||||
}
|
150
src/main.rs
150
src/main.rs
|
@ -1,12 +1,17 @@
|
|||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
mod backlight;
|
||||
mod delay;
|
||||
mod monotonic_nrf52;
|
||||
|
||||
// use nrf52832_hal::gpio::Level;
|
||||
// use nrf52832_hal::{self as p_hal, pac};
|
||||
// use p_hal::{delay::Delay, spim, twim};
|
||||
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 p_hal::{delay::Delay, rng::RngExt, spim, twim};
|
||||
|
||||
use cortex_m_rt as rt;
|
||||
use cst816s::CST816S;
|
||||
|
@ -14,9 +19,8 @@ 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::input_device::{InputData, Pointer};
|
||||
use lvgl::style::Style;
|
||||
use lvgl::widgets::{Btn, Label};
|
||||
use lvgl::{self, Align, Color, Part, State, Widget, UI};
|
||||
|
@ -24,7 +28,8 @@ 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 embedded_hal::blocking::delay::{DelayMs, DelayUs};
|
||||
use embedded_hal::digital::v2::OutputPin;
|
||||
use nrf52832_hal::prelude::ClocksExt;
|
||||
|
||||
pub type HalSpimError = p_hal::spim::Error;
|
||||
|
@ -44,64 +49,99 @@ fn main() -> ! {
|
|||
// PineTime has a 32 MHz HSE (HFXO) and a 32.768 kHz LSE (LFXO)
|
||||
// Optimize clock config
|
||||
let dp = pac::Peripherals::take().unwrap();
|
||||
|
||||
let mut lcd_delay = delay::TimerDelay::new(dp.TIMER0);
|
||||
|
||||
// Set up clocks. On reset, the high frequency clock is already used,
|
||||
// but we also need to switch to the external HF oscillator. This is
|
||||
// needed for Bluetooth to work.
|
||||
|
||||
//let _clocks = p_hal::clocks::Clocks::new(dp.CLOCK).enable_ext_hfosc();
|
||||
let _clockit = dp.CLOCK.constrain().enable_ext_hfosc();
|
||||
|
||||
let port0 = dp.P0.split();
|
||||
//let gpio = p_hal::gpio::p0::Parts::new(dp.P0);
|
||||
let gpio = dp.P0.split();
|
||||
|
||||
// Set up SPI pins
|
||||
let spi_clk = gpio.p0_02.into_push_pull_output(Level::Low).degrade();
|
||||
let spi_mosi = gpio.p0_03.into_push_pull_output(Level::Low).degrade();
|
||||
let spi_miso = gpio.p0_04.into_floating_input().degrade();
|
||||
let spi_pins = spim::Pins {
|
||||
sck: spi_clk,
|
||||
miso: Some(spi_miso),
|
||||
mosi: Some(spi_mosi),
|
||||
};
|
||||
|
||||
// Enable backlight
|
||||
let mut backlight = backlight::Backlight::init(
|
||||
gpio.p0_14.into_push_pull_output(Level::High).degrade(),
|
||||
gpio.p0_22.into_push_pull_output(Level::High).degrade(),
|
||||
gpio.p0_23.into_push_pull_output(Level::High).degrade(),
|
||||
1,
|
||||
);
|
||||
backlight.set(5);
|
||||
|
||||
delay_source.delay_ms(1u8);
|
||||
// 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(),
|
||||
scl: gpio.p0_07.into_floating_input().degrade(),
|
||||
sda: gpio.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();
|
||||
let touch_int = gpio.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 touch_rst = gpio.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();
|
||||
|
||||
// Set up LCD pins
|
||||
// LCD_CS (P0.25): Chip select
|
||||
let mut lcd_cs = gpio.p0_25.into_push_pull_output(Level::Low);
|
||||
// LCD_RS (P0.18): Data/clock pin
|
||||
let lcd_dc = gpio.p0_18.into_push_pull_output(Level::Low);
|
||||
// LCD_RESET (P0.26): Display reset
|
||||
let lcd_rst = gpio.p0_26.into_push_pull_output(Level::Low);
|
||||
|
||||
// Initialize SPI
|
||||
let spi = spim::Spim::new(
|
||||
dp.SPIM0,
|
||||
spi_pins,
|
||||
// Use SPI at 8MHz (the fastest clock available on the nRF52832)
|
||||
// because otherwise refreshing will be super slow.
|
||||
spim::Frequency::M8,
|
||||
// SPI must be used in mode 3. Mode 0 (the default) won't work.
|
||||
spim::MODE_3,
|
||||
0,
|
||||
);
|
||||
let spi_bus0 = shared_bus::CortexMBusManager::new(spi);
|
||||
|
||||
// Chip select must be held low while driving the display. It must be high
|
||||
// when using other SPI devices on the same bus (such as external flash
|
||||
// storage) so that the display controller won't respond to the wrong
|
||||
// commands.
|
||||
lcd_cs.set_low().unwrap();
|
||||
|
||||
// Initialize LCD
|
||||
let mut lcd = st7789::ST7789::new(
|
||||
spi_bus0.acquire(),
|
||||
lcd_dc,
|
||||
lcd_rst,
|
||||
lvgl::HOR_RES_MAX as u16,
|
||||
lvgl::VER_RES_MAX as u16,
|
||||
lcd_delay,
|
||||
);
|
||||
|
||||
lcd.init().unwrap();
|
||||
lcd.set_orientation(&Orientation::Portrait).unwrap();
|
||||
|
||||
// Initialize LVGL
|
||||
let mut ui = UI::init().unwrap();
|
||||
ui.disp_drv_register(display).unwrap();
|
||||
ui.disp_drv_register(lcd).unwrap();
|
||||
|
||||
// Define the initial state of the input
|
||||
let mut latest_touch_point = Point::new(0, 0);
|
||||
|
@ -131,11 +171,20 @@ fn main() -> ! {
|
|||
let mut btn_lbl = Label::new(&mut button).unwrap();
|
||||
btn_lbl.set_text(text_click_me).unwrap();
|
||||
|
||||
let mut btn_state = false;
|
||||
let mut time_style = Style::default();
|
||||
time_style.set_text_color(State::DEFAULT, Color::from_rgb((255, 255, 255)));
|
||||
|
||||
let mut time_lbl = Label::new(&mut screen).unwrap();
|
||||
time_lbl
|
||||
.set_align(&mut button, Align::OutTopMid, 0, -50)
|
||||
.unwrap();
|
||||
let time_text = CStr::from_bytes_with_nul("TIME\0".as_bytes()).unwrap();
|
||||
time_lbl.set_text(time_text).unwrap();
|
||||
time_lbl.add_style(Part::Main, time_style).unwrap();
|
||||
|
||||
button
|
||||
.on_event(|mut btn, event| {
|
||||
if let lvgl::Event::Clicked = event {
|
||||
btn_state = !btn_state;
|
||||
btn.toggle().unwrap();
|
||||
}
|
||||
})
|
||||
|
@ -150,6 +199,13 @@ fn main() -> ! {
|
|||
latest_touch_status = InputData::Touch(latest_touch_point.clone())
|
||||
.pressed()
|
||||
.once();
|
||||
|
||||
time_lbl
|
||||
.set_text(CStr::from_bytes_with_nul("PRESSED\0".as_bytes()).unwrap())
|
||||
.unwrap();
|
||||
time_lbl
|
||||
.set_align(&mut button, Align::OutTopMid, 0, -50)
|
||||
.unwrap();
|
||||
} else {
|
||||
// Released
|
||||
latest_touch_status = InputData::Touch(latest_touch_point.clone())
|
||||
|
@ -157,7 +213,7 @@ fn main() -> ! {
|
|||
.once();
|
||||
}
|
||||
|
||||
ui.tick_inc(Duration::from_millis(50));
|
||||
ui.tick_inc(Duration::from_millis(100));
|
||||
//delay_source.delay_ms(2u32);
|
||||
loop_start = Instant::now();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue