Skip to content

Commit e0d1327

Browse files
committed
[examples] Add LVGL example for Nucleo-L452RE with Ili9341
1 parent d2abea5 commit e0d1327

File tree

3 files changed

+235
-0
lines changed

3 files changed

+235
-0
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Copyright (c) 2021, Raphael Lehmann
3+
*
4+
* This file is part of the modm project.
5+
*
6+
* This Source Code Form is subject to the terms of the Mozilla Public
7+
* License, v. 2.0. If a copy of the MPL was not distributed with this
8+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
9+
*/
10+
11+
#ifndef LV_CONF_H
12+
# error "Don't include this file directly, use 'lv_conf.h' instead!"
13+
#endif
14+
15+
// Maximal resolutions
16+
#define LV_HOR_RES_MAX 240
17+
#define LV_VER_RES_MAX 320
18+
#define LV_DPI 200
19+
20+
/* Color depth:
21+
* - 1: 1 byte per pixel
22+
* - 8: RGB332
23+
* - 16: RGB565
24+
* - 32: ARGB8888
25+
*/
26+
#define LV_COLOR_DEPTH 16
27+
28+
// Enable logging at INFO level
29+
#define LV_USE_LOG 1
30+
#define LV_LOG_LEVEL LV_LOG_LEVEL_INFO
31+
32+
// Enable a bigger font
33+
#define LV_FONT_MONTSERRAT_36 1
34+
35+
// Disable anti-aliasing
36+
#define LV_ANTIALIAS 0
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
/*
2+
* Copyright (c) 2021, Raphael Lehmann
3+
*
4+
* This file is part of the modm project.
5+
*
6+
* This Source Code Form is subject to the terms of the Mozilla Public
7+
* License, v. 2.0. If a copy of the MPL was not distributed with this
8+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
9+
*/
10+
// ----------------------------------------------------------------------------
11+
12+
#include <modm/board.hpp>
13+
#include <modm/debug.hpp>
14+
#include <modm/processing.hpp>
15+
#include <modm/driver/display/ili9341_spi.hpp>
16+
#include <modm/driver/touch/touch2046.hpp>
17+
18+
#include <lvgl/lvgl.h>
19+
20+
21+
// Set the log level
22+
#undef MODM_LOG_LEVEL
23+
#define MODM_LOG_LEVEL modm::log::DEBUG
24+
25+
using namespace Board;
26+
using namespace modm::literals;
27+
28+
29+
namespace tft
30+
{
31+
using DmaRx = Dma1::Channel2;
32+
using DmaTx = Dma1::Channel3;
33+
using Spi = SpiMaster1_Dma<DmaRx, DmaTx>;
34+
//using Spi = SpiMaster1;
35+
using Cs = modm::platform::GpioC8;
36+
using Sck = modm::platform::GpioA5;
37+
using Miso = modm::platform::GpioA6;
38+
using Mosi = modm::platform::GpioA7;
39+
using DataCommands = modm::platform::GpioC5;
40+
using Reset = modm::platform::GpioC6;
41+
using Backlight = modm::platform::GpioC9;
42+
}
43+
44+
modm::Ili9341Spi<
45+
tft::Spi,
46+
tft::Cs,
47+
tft::DataCommands,
48+
tft::Reset,
49+
tft::Backlight
50+
> tftController;
51+
52+
namespace touch
53+
{
54+
using Spi = SpiMaster2;
55+
using Cs = modm::platform::GpioB3;
56+
using Sck = modm::platform::GpioB13;
57+
using Miso = modm::platform::GpioB14;
58+
using Mosi = modm::platform::GpioB15;
59+
//using Interrupt = modm::platform::GpioA10;
60+
}
61+
62+
modm::Touch2046<touch::Spi, touch::Cs> touchController;
63+
64+
65+
static lv_disp_buf_t disp_buf;
66+
static constexpr size_t buf_size = LV_HOR_RES_MAX * LV_VER_RES_MAX / 8;
67+
static lv_color_t buf[buf_size];
68+
69+
bool my_touchpad_read(lv_indev_drv_t*, lv_indev_data_t* data)
70+
{
71+
data->state = RF_CALL_BLOCKING(touchController.isTouched()) ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL;
72+
if(data->state == LV_INDEV_STATE_PR) {
73+
auto xy = RF_CALL_BLOCKING(touchController.getTouchPosition());
74+
data->point.x = std::get<0>(xy);
75+
data->point.y = std::get<1>(xy);
76+
}
77+
return false;
78+
}
79+
80+
void my_flush_cb(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
81+
{
82+
tftController.drawRaw(
83+
{area->x1, area->y1},
84+
(area->x2 - area->x1 +1),
85+
(area->y2 - area->y1 + 1),
86+
(modm::glcd::Color*)color_p);
87+
lv_disp_flush_ready(disp_drv);
88+
}
89+
90+
int
91+
main()
92+
{
93+
Board::initialize();
94+
Dma1::enable();
95+
96+
tft::Spi::connect<
97+
tft::Sck::Sck,
98+
tft::Miso::Miso,
99+
tft::Mosi::Mosi>();
100+
tft::Spi::initialize<SystemClock, 40_MHz>();
101+
tftController.initialize();
102+
tftController.enableBacklight(true);
103+
104+
touch::Spi::connect<
105+
touch::Sck::Sck,
106+
touch::Miso::Miso,
107+
touch::Mosi::Mosi>();
108+
touch::Spi::initialize<SystemClock, 2500_kHz>();
109+
modm::touch2046::Calibration cal{
110+
.OffsetX = -11,
111+
.OffsetY = 335,
112+
.FactorX = 22018,
113+
.FactorY = -29358,
114+
.MaxX = 240,
115+
.MaxY = 320,
116+
.ThresholdZ = 500,
117+
};
118+
touchController.setCalibration(cal);
119+
120+
MODM_LOG_INFO << "modm LVGL example on Nucleo-L452RE board!\n\n";
121+
122+
lv_init();
123+
124+
// Initialize the display buffer
125+
lv_disp_buf_init(&disp_buf, buf, NULL, buf_size);
126+
127+
// Initialize the display:
128+
lv_disp_drv_t disp_drv;
129+
lv_disp_drv_init(&disp_drv);
130+
disp_drv.buffer = &disp_buf;
131+
disp_drv.flush_cb = my_flush_cb;
132+
disp_drv.hor_res = LV_HOR_RES_MAX;
133+
disp_drv.ver_res = LV_VER_RES_MAX;
134+
lv_disp_t * disp;
135+
disp = lv_disp_drv_register(&disp_drv);
136+
137+
// Initialize touchscreen driver:
138+
lv_indev_drv_t indev_drv;
139+
lv_indev_drv_init(&indev_drv);
140+
indev_drv.type = LV_INDEV_TYPE_POINTER;
141+
indev_drv.read_cb = my_touchpad_read;
142+
lv_indev_drv_register(&indev_drv);
143+
144+
lv_obj_t* scr = lv_disp_get_scr_act(disp); // Get the current screen
145+
146+
lv_obj_t* labelA = lv_label_create(scr, NULL);
147+
lv_label_set_text(labelA, "Hello world!");
148+
lv_obj_set_pos(labelA, 60, 10);
149+
lv_obj_set_size(labelA, 120, 50);
150+
151+
lv_obj_t* btn = lv_btn_create(lv_scr_act(), NULL);
152+
lv_obj_set_pos(btn, 60, 135);
153+
lv_obj_set_size(btn, 120, 50);
154+
lv_obj_t* btnLabel = lv_label_create(btn, NULL);
155+
lv_label_set_text(btnLabel, "Button");
156+
lv_obj_set_event_cb(btn, [](struct _lv_obj_t * obj, lv_event_t event) {
157+
static uint16_t btnCounter = 0;
158+
if(event == LV_EVENT_PRESSED) {
159+
lv_label_set_text_fmt(lv_obj_get_child(obj, NULL), "Button: %d", ++btnCounter);
160+
}
161+
});
162+
163+
lv_obj_t* labelB = lv_label_create(scr, NULL);
164+
lv_label_set_text(labelB, "Big Font");
165+
lv_obj_set_pos(labelB, 40, 260);
166+
lv_obj_set_style_local_text_font(labelB, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &lv_font_montserrat_36);
167+
168+
uint16_t counter = 0;
169+
170+
modm::ShortPeriodicTimer tmr{10ms};
171+
172+
while (true)
173+
{
174+
lv_task_handler();
175+
176+
if (tmr.execute())
177+
{
178+
lv_label_set_text_fmt(labelA, "counter=%d", ++counter);
179+
}
180+
}
181+
182+
return 0;
183+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<library>
2+
<extends>modm:nucleo-l452re</extends>
3+
<options>
4+
<option name="modm:build:build.path">../../../build/nucleo_l452re/lvgl</option>
5+
</options>
6+
<modules>
7+
<module>modm:build:scons</module>
8+
<module>modm:processing:timer</module>
9+
<module>modm:driver:ili9341</module>
10+
<module>modm:driver:touch2046</module>
11+
<module>modm:platform:spi:1</module>
12+
<module>modm:platform:spi:2</module>
13+
<module>modm:platform:dma</module>
14+
<module>modm:lvgl</module>
15+
</modules>
16+
</library>

0 commit comments

Comments
 (0)