Touch working

This commit is contained in:
Rafael Caricio 2020-06-21 08:46:25 +02:00
parent e4c6104c51
commit 99d084fdb4
5 changed files with 228 additions and 75 deletions

29
Cargo.lock generated
View file

@ -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",

View file

@ -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
View 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 (07).
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
View 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);
}
}

View file

@ -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();
}