-
Notifications
You must be signed in to change notification settings - Fork 211
/
Copy pathdisplay-touch.rs
213 lines (177 loc) · 7.11 KB
/
display-touch.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
//!
//! Demonstrates use of I2C bus to configure and use FT6x06 touchscreen controller
//!
//! Hardware Required: STM32F412G-DISCO board or STM32F413H-DISCO board
//!
//! Procedure: Compile this example, load it onto the microcontroller, and run it.
//!
//! Example run command: `cargo run --release --features stm32f412,fsmc_lcd --example display_touch`
//!
//! Expected behavior: The display draws circle with its center around the touch. The co-ordinates of the touch
//! are printed on screen.
#![no_main]
#![no_std]
#![allow(unused_variables)]
use cortex_m;
use cortex_m_rt::entry;
use rtt_target::{rprintln, rtt_init_print};
use stm32f4xx_hal::{
fsmc_lcd::{DataPins16, FsmcLcd, LcdPins, Timing},
gpio::Speed,
pac,
prelude::*,
rcc::Rcc,
};
use embedded_graphics_07::{
pixelcolor::Rgb565,
prelude::*,
primitives::{Circle, PrimitiveStyle},
};
#[cfg(feature = "stm32f413")]
use stm32f4xx_hal::fmpi2c::I2c;
#[cfg(feature = "stm32f412")]
use stm32f4xx_hal::i2c::I2c;
#[allow(unused_imports)]
use panic_semihosting;
use ft6x06::{long_hard_reset, Ft6X06};
use st7789::*;
/// A simple example to connect to the FT6x06 crate and get the values for
/// x and y positions of touch.
#[entry]
fn main() -> ! {
rtt_init_print!();
rprintln!("Started");
let p = pac::Peripherals::take().unwrap();
let cp = cortex_m::Peripherals::take().unwrap();
let rcc: Rcc = p.RCC.constrain();
let clocks = rcc.cfgr.sysclk(100.MHz()).freeze();
let mut delay = cp.SYST.delay(&clocks);
let gpiob = p.GPIOB.split();
let gpioc = p.GPIOC.split();
let gpiod = p.GPIOD.split();
let gpioe = p.GPIOE.split();
let gpiof = p.GPIOF.split();
let gpiog = p.GPIOG.split();
// Pins connected to the LCD on the board
use stm32f4xx_hal::gpio::alt::fsmc as alt;
let lcd_pins = LcdPins::new(
DataPins16::new(
gpiod.pd14, gpiod.pd15, gpiod.pd0, gpiod.pd1, gpioe.pe7, gpioe.pe8, gpioe.pe9,
gpioe.pe10, gpioe.pe11, gpioe.pe12, gpioe.pe13, gpioe.pe14, gpioe.pe15, gpiod.pd8,
gpiod.pd9, gpiod.pd10,
),
alt::Address::from(gpiof.pf0),
gpiod.pd4,
gpiod.pd5,
#[cfg(feature = "stm32f413")]
alt::ChipSelect3::from(gpiog.pg10),
#[cfg(feature = "stm32f412")]
alt::ChipSelect1::from(gpiod.pd7),
);
// Enable backlight
#[cfg(feature = "stm32f413")]
let mut backlight_control = gpioe.pe5.into_push_pull_output();
#[cfg(feature = "stm32f412")]
let mut backlight_control = gpiof.pf5.into_push_pull_output();
backlight_control.set_high();
// Setup the RESET pin
#[cfg(feature = "stm32f413")]
let mut lcd_reset = gpiob.pb13.into_push_pull_output().speed(Speed::VeryHigh);
#[cfg(feature = "stm32f412")]
let lcd_reset = gpiod.pd11.into_push_pull_output().speed(Speed::VeryHigh);
#[cfg(feature = "stm32f412")]
let mut ts_reset = gpiof.pf12.into_push_pull_output().speed(Speed::VeryHigh);
// Workaround on STM32F413:
// - On the STM32F413 the touchscreen shares the reset GPIO pin w/ the LCD.
// - The ST7789 driver uses a fast (10uS) reset.
// - The touchscreen controller needs 5mS:
// https://www.displayfuture.com/Display/datasheet/controller/FT6206.pdf
//
// Perform a longer reset here first.
//
#[cfg(feature = "stm32f412")]
long_hard_reset(&mut ts_reset, &mut delay).expect("long hard reset");
#[cfg(feature = "stm32f413")]
long_hard_reset(&mut lcd_reset, &mut delay).expect("long hard reset");
// We're not using the "tearing" signal from the display
let mut _te = gpiob.pb14.into_floating_input();
// Set up timing
let write_timing = Timing::default().data(3).address_setup(3).bus_turnaround(0);
let read_timing = Timing::default().data(8).address_setup(8).bus_turnaround(0);
// Initialise FSMC memory provider
let (_fsmc, interface) = FsmcLcd::new(p.FSMC, lcd_pins, &read_timing, &write_timing);
// Pass display-interface instance ST7789 driver to setup a new display
let mut disp = ST7789::new(
interface,
Some(lcd_reset),
Some(backlight_control),
240,
240,
);
// Initialise the display and clear the screen
disp.init(&mut delay).unwrap();
disp.clear(Rgb565::BLACK).unwrap();
// Orientation set is default. The touch coordinates data changes as per orientation.
// The touch coordinates and shapes are adjusted accordingly.
rprintln!("The orientation set is {}", disp.orientation() as u8);
// Initializing the i2c bus for touchscreen
rprintln!("Connecting to I2c");
// Declare the pins for i2c address bus on each board.
// STM32F412 uses I2c1 type for i2c bus.
// The pins are mentioned in documentation -um2135-discovery-kit-with-stm32f412zg-mcu-stmicroelectronics
#[cfg(feature = "stm32f412")]
let mut i2c = { I2c::new(p.I2C1, (gpiob.pb6, gpiob.pb7), 400.kHz(), &clocks) };
// STM32F413 uses FMPI2C1 type.
// The pins are mentioned in documentation -um2135-discovery-kit-with-stm32f413zh-mcu-stmicroelectronics
#[cfg(feature = "stm32f413")]
let mut i2c = { I2c::new(p.FMPI2C1, (gpioc.pc6, gpioc.pc7), 400.kHz()) };
#[cfg(feature = "stm32f412")]
let ts_int = gpiog.pg5.into_pull_down_input();
#[cfg(feature = "stm32f413")]
let ts_int = gpioc.pc1.into_pull_down_input();
// Create a struct of ft6x06 driver for touchscreen.
let mut touch = Ft6X06::new(&i2c, 0x38, ts_int).unwrap();
// Run internal calibration of touchscreen
let tsc = touch.ts_calibration(&mut i2c, &mut delay);
match tsc {
Err(e) => rprintln!("Error {} from ts_calibration", e),
Ok(u) => rprintln!("ts_calibration returned {}", u),
}
rprintln!("If nothing happens - touch the screen!");
// Loop to get the touch data
loop {
let t = touch.detect_touch(&mut i2c);
let mut num: u8 = 0;
match t {
Err(_e) => rprintln!("Error from fetching number of touches"),
Ok(n) => {
num = n;
if num != 0 {
rprintln!("Number of touches: {}", num)
};
}
}
if num > 0 {
let t = touch.get_touch(&mut i2c, 1);
match t {
Err(_e) => rprintln!("Error fetching touch data"),
Ok(n) => {
// Prints the touch coordinates.
rprintln!(
"Touch: {:>3}x{:>3} - weight: {:>3} misc: {}",
n.x,
n.y,
n.weight,
n.misc
);
// Circle with 1 pixel wide white stroke with top-left point at (10, 20) with a diameter of 3
// The touchscreen coordinates are flipped and have an offset. The following conversion gives correct orientation.
Circle::new(Point::new(i32::from(n.y), 240 - i32::from(n.x)), 20)
.into_styled(PrimitiveStyle::with_stroke(Rgb565::RED, 1))
.draw(&mut disp)
.unwrap();
}
}
}
}
}