Skip to content

Commit

Permalink
[example] Add LGVL example on NUCLEO-L476RG
Browse files Browse the repository at this point in the history
  • Loading branch information
frnktank authored and salkinium committed Dec 19, 2024
1 parent 4ad8f5d commit 9c06e6c
Show file tree
Hide file tree
Showing 5 changed files with 321 additions and 0 deletions.
39 changes: 39 additions & 0 deletions examples/nucleo_l476rg/lvgl/lv_conf_local.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright (c) 2024, Frank Altheim
*
* This file is part of the modm project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
// ----------------------------------------------------------------------------

#ifndef LV_CONF_H
# error "Don't include this file directly, use 'lv_conf.h' instead!"
#endif

// Maximal resolutions
#define LV_HOR_RES_MAX 240
#define LV_VER_RES_MAX 320
#define LV_DPI 200

/* Color depth:
* - 1: 1 byte per pixel
* - 8: RGB332
* - 16: RGB565
* - 32: ARGB8888
*/
#define LV_COLOR_DEPTH 16

// Enable logging at INFO level
#define LV_USE_LOG 1
#define LV_LOG_LEVEL LV_LOG_LEVEL_INFO

// Fonts:
#define LV_FONT_MONTSERRAT_36 1
#define LV_FONT_MONTSERRAT_24 1
#define LV_FONT_MONTSERRAT_16 1

// Disable anti-aliasing
#define LV_ANTIALIAS 0
164 changes: 164 additions & 0 deletions examples/nucleo_l476rg/lvgl/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
/*
* Copyright (c) 2024, Frank Altheim
*
* This file is part of the modm project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
// ----------------------------------------------------------------------------

#include <modm/board.hpp>
#include <modm/debug.hpp>
#include <modm/processing.hpp>
#include <modm/driver/display/ili9341_spi.hpp>
#include <modm/driver/touch/touch2046.hpp>

#include <lvgl/lvgl.h>

// USER INCLUDES
#include "test_screen.h"


// Set the log level
#undef MODM_LOG_LEVEL
#define MODM_LOG_LEVEL modm::log::DEBUG

using namespace Board;
using namespace modm::literals;


namespace tft
{
using DmaRx = Dma1::Channel2;
using DmaTx = Dma1::Channel3;
using Spi = SpiMaster1_Dma<DmaRx, DmaTx>;
//using Spi = SpiMaster1;
using Cs = Board::D10;
using Sck = Board::D13;
using Miso = Board::D12;
using Mosi = Board::D11;
using DataCommands = Board::D9;
using Reset = Board::D8;
using Backlight = modm::platform::GpioC9;
}

modm::Ili9341Spi<
tft::Spi,
tft::Cs,
tft::DataCommands,
tft::Reset,
tft::Backlight
> tftController;

namespace touch
{
using Spi = SpiMaster3;
using Cs = modm::platform::GpioD2;
using Sck = modm::platform::GpioC10;
using Miso = modm::platform::GpioC11;
using Mosi = modm::platform::GpioC12;
using Interrupt = modm::platform::GpioC9;
}

modm::Touch2046<touch::Spi, touch::Cs> touchController;

// Define display buffer 1
static constexpr size_t buf_size = 240 * 320 / 8;
static lv_color_t modm_aligned(4) buf[buf_size];

// Define display buffer 2
static constexpr size_t buf2_size = 240 * 320 / 8;
static lv_color_t modm_aligned(4) buf2[buf2_size];

void my_touchpad_read(lv_indev_t*, lv_indev_data_t* data)
{
data->state = touchController.isTouched() ? LV_INDEV_STATE_PRESSED : LV_INDEV_STATE_RELEASED;
if(data->state == LV_INDEV_STATE_PRESSED) {
std::tuple xy = touchController.getTouchPosition();
data->point.x = std::get<0>(xy);
data->point.y = std::get<1>(xy);

std::tuple xyRAW = touchController.getRawValues();
int16_t rawX = std::get<0>(xyRAW);
int16_t rawY = std::get<1>(xyRAW);
// Display on test screen
setTouchText(data->point.x, data->point.y, rawX, rawY);

}
}

void disp_flush(lv_display_t* disp, const lv_area_t* area, uint8_t* px_map)
{
tftController.drawRaw(
{uint16_t(area->x1), uint16_t(area->y1)},
(area->x2 - area->x1 +1),
(area->y2 - area->y1 + 1),
(modm::color::Rgb565*)px_map);
lv_display_flush_ready(disp);
}

int
main()
{
Board::initialize();
Dma1::enable();

tft::Spi::connect<
tft::Sck::Sck,
tft::Miso::Miso,
tft::Mosi::Mosi>();
tft::Spi::initialize<Board::SystemClock, 24_MHz>();
tftController.initialize();
tftController.enableBacklight(true);

touch::Spi::connect<
touch::Sck::Sck,
touch::Miso::Miso,
touch::Mosi::Mosi>();
touch::Spi::initialize<Board::SystemClock, 1.5_MHz>();
modm::touch2046::Calibration cal{
.OffsetX = -11,
.OffsetY = 335,
.FactorX = 22018,
.FactorY = -29358,
.MaxX = 240,
.MaxY = 320,
.ThresholdZ = 100,
};
touchController.setCalibration(cal);

MODM_LOG_INFO << "reflow-display on nucleo-l476rg!\n\n";

lv_display_t *disp = lv_display_create(240, 320);
lv_display_set_flush_cb(disp, disp_flush);
lv_display_set_buffers(disp, buf, buf2, sizeof(buf), LV_DISPLAY_RENDER_MODE_PARTIAL);

// Initialize touchscreen driver:
lv_indev_t* indev = lv_indev_create();
// Assert touchscreen driver was created successfully:
if (indev == NULL) {
MODM_LOG_ERROR << "Failed to create input device\n";
while (1) {}
}

lv_indev_set_type(indev, LV_INDEV_TYPE_POINTER);
lv_indev_set_read_cb(indev, my_touchpad_read);

drawTestScreen();

modm::ShortPeriodicTimer tmr{20ms};

while (true)
{
lv_timer_handler();

if (tmr.execute())
{
setLblText();
}
}

return 0;
}
16 changes: 16 additions & 0 deletions examples/nucleo_l476rg/lvgl/project.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<library>
<extends>modm:nucleo-l476rg</extends>
<options>
<option name="modm:build:build.path">../../../build/nucleo_l476rg/lvgl</option>
</options>
<modules>
<module>modm:build:scons</module>
<module>modm:processing:timer</module>
<module>modm:driver:ili9341</module>
<module>modm:driver:touch2046</module>
<module>modm:platform:spi:1</module>
<module>modm:platform:spi:3</module>
<module>modm:platform:dma</module>
<module>modm:lvgl</module>
</modules>
</library>
78 changes: 78 additions & 0 deletions examples/nucleo_l476rg/lvgl/test_screen.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* Copyright (c) 2024, Frank Altheim
*
* This file is part of the modm project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
// ----------------------------------------------------------------------------

#include "test_screen.h"
#include <lvgl/lvgl.h>

static lv_obj_t* screen;
static uint16_t counter = 0;
static lv_obj_t* labelA;
static lv_obj_t* labelTouch;
static lv_obj_t* labelRawTouch;

void btn_event_cb(lv_event_t *event)
{
static uint16_t btnCounter = 0;
lv_label_set_text_fmt((lv_obj_t*) lv_event_get_user_data(event),
"Button: %d", ++btnCounter);
}

void drawTestScreen(void)
{
screen = lv_obj_create(NULL);

labelA = lv_label_create(screen);
lv_label_set_text(labelA, "Hello world!");
lv_obj_set_pos(labelA, 60, 10);
lv_obj_set_size(labelA, 120, 50);

labelTouch = lv_label_create(screen);
lv_label_set_text_fmt(labelTouch, "Pos Touch: x = %d, y = %d", 0, 0);
lv_obj_set_pos(labelTouch, 60, 30);
lv_obj_set_size(labelTouch, 120, 50);

labelRawTouch = lv_label_create(screen);
lv_label_set_text_fmt(labelRawTouch, "Raw Touch: x = %d, y = %d", 0, 0);
lv_obj_set_pos(labelRawTouch, 60, 80);
lv_obj_set_size(labelRawTouch, 120, 50);

lv_obj_t* btn = lv_button_create(screen);
lv_obj_set_pos(btn, 60, 135);
lv_obj_set_size(btn, 120, 50);

lv_obj_t* btnLabel = lv_label_create(btn);
lv_label_set_text(btnLabel, "Button");

static lv_style_t style_btn_pressed;
lv_style_init(&style_btn_pressed);
lv_style_set_bg_color(&style_btn_pressed, lv_palette_main(LV_PALETTE_ORANGE));

lv_obj_add_style(btn, &style_btn_pressed, LV_STATE_PRESSED);
lv_obj_add_event_cb(btn, btn_event_cb, LV_EVENT_PRESSED, btnLabel);
lv_obj_t* labelB = lv_label_create(screen);
lv_label_set_text(labelB, "Big Font");
lv_obj_set_pos(labelB, 40, 260);
lv_obj_set_style_text_font(labelB, &lv_font_montserrat_36, LV_PART_MAIN);

// Load screen
lv_scr_load(screen);
}

void setLblText(void)
{
lv_label_set_text_fmt(labelA, "counter=%d", ++counter);
}

void setTouchText(int16_t x, int16_t y, int16_t rawX, int16_t rawY)
{
lv_label_set_text_fmt(labelTouch, "Pos Touch: x = %d, y = %d", x, y);
lv_label_set_text_fmt(labelRawTouch, "Raw Touch: x = %d, y = %d", rawX, rawY);
}
24 changes: 24 additions & 0 deletions examples/nucleo_l476rg/lvgl/test_screen.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Copyright (c) 2024, Frank Altheim
*
* This file is part of the modm project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
// ----------------------------------------------------------------------------

#ifndef TEST_SCREEN_H
#define TEST_SCREEN_H

#pragma once

#include <cstdint>

void drawTestScreen(void);
void setLblText(void);
void setTouchText(int16_t x, int16_t y, int16_t rawX, int16_t rawY);


#endif //TEST_SCREEN_H

0 comments on commit 9c06e6c

Please sign in to comment.