Skip to content

Commit

Permalink
Added LVGL DEMO
Browse files Browse the repository at this point in the history
  • Loading branch information
StrahinjaJacimovic committed Dec 16, 2024
1 parent 631b105 commit f98ca13
Show file tree
Hide file tree
Showing 29 changed files with 1,859 additions and 6 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ Current demos:
+ *DISPLAY*
+ [LCD](./demos/sdk/demolcd/project/README.md)
+ [DESIGNER](./demos/sdk/demodesigner/project/README.md)
+ [LVGL-TODO](TODO)
+ [LVGL-TODO](./demos/sdk/demolvgl/project/README.md)

---

Expand Down
4 changes: 3 additions & 1 deletion demos/sdk/demodesigner/project/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ void application_task()
/**
* @brief Application main function.
*/
void main()
int main()
{
/* Do not remove this line or clock might not be set correctly. */
#ifdef PREINIT_SUPPORTED
Expand All @@ -191,4 +191,6 @@ void main()
{
application_task();
}

return 0;
}
8 changes: 4 additions & 4 deletions demos/sdk/demogpio/project/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ else()
endif()

## Port
add_subdirectory(demoport)
add_subdirectory(port)

## LED curtain
add_subdirectory(demoledcurtain)
add_subdirectory(ledcurtain)

## LED blinking
add_subdirectory(demoledblinking)
add_subdirectory(ledblinking)

## Read input on one pin, display output on another pin
add_subdirectory(demodigitalinputoutput)
add_subdirectory(digitalinputoutput)
6 changes: 6 additions & 0 deletions demos/sdk/demolvgl/project/1ms_Timer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#ifdef PIC32_TIMER
#include "timer.h"
#endif
#ifdef ARM_TIMER
#include "systick.h"
#endif
16 changes: 16 additions & 0 deletions demos/sdk/demolvgl/project/1ms_timer/TimerHeaderConfig.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
set(tim_list "")
#############################################################################
## Set Timer Variables and Interrupt handler
#############################################################################
if(${TOOLCHAIN_ID} MATCHES "mchp_xc32")
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/1ms_timer/microchip/pic32)
list(APPEND tim_list "PIC32_TIMER=1")
list(APPEND tim_list "CLEAR_FLAG=IFS0bits.T1IF = 0")
list(APPEND tim_list "CLOCK=${OSC}")
list(APPEND tim_list "INTERRUPT_ROUTINE=void __attribute__((interrupt(IPL7AUTO), vector(_TIMER_1_VECTOR))) _TIMER_1_HANDLER(void)")
else()
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/1ms_timer/arm)
list(APPEND tim_list "ARM_TIMER=1")
list(APPEND tim_list "INTERRUPT_ROUTINE=__attribute__ ((interrupt(\"IRQ\"))) void SysTick_Handler(void)")
list(APPEND tim_list "CLEAR_FLAG=0")
endif()
126 changes: 126 additions & 0 deletions demos/sdk/demolvgl/project/1ms_timer/arm/systick.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
#include <mcu.h>
#include <core_header.h>

#ifndef SysTick_IRQn
#define SysTick_IRQn -1
#endif

// CMSIS Core macros.
#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */

#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */
#define SCB ((SCB_Type *)SCB_BASE) /*!< SCB configuration struct */

#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */
#define NVIC ((NVIC_Type *)NVIC_BASE) /*!< NVIC configuration struct */

#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */
#define SysTick ((SysTick_Type *)SysTick_BASE) /*!< SysTick configuration struct */

// SysTick settings.
#define TICK_FREQ_10HZ 100U
#define TICK_FREQ_100HZ 10U
#define TICK_FREQ_1KHZ 1U
#define TICK_FREQ_DEFAULT TICK_FREQ_1KHZ
#define GET_TICK_NUMBER_PER_CLOCK ((FOSC_KHZ_VALUE*1000UL) / (1000U / TICK_FREQ_DEFAULT))

// Systick API prototypes.
static inline uint32_t sysTickConfig(uint32_t ticks) __attribute__((always_inline));
static inline void sysTickInit(uint8_t priority) __attribute__((always_inline));

/**
\brief Structure type to access the System Control Block (SCB).
*/
typedef struct {
volatile uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */
volatile uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */
volatile uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */
volatile uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */
volatile uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */
volatile uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */
volatile uint8_t SHP[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */
volatile uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */
volatile uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */
volatile uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */
volatile uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */
volatile uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */
volatile uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */
volatile uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */
volatile uint32_t PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */
volatile uint32_t DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */
volatile uint32_t ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */
volatile uint32_t MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */
volatile uint32_t ISAR[5U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */
uint32_t RESERVED0[5U];
volatile uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */
} SCB_Type;

/**
\brief Structure type to access the Nested Vectored Interrupt Controller (NVIC).
*/
typedef struct {
volatile uint32_t ISER[8U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */
uint32_t RESERVED0[24U];
volatile uint32_t ICER[8U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */
uint32_t RESERVED1[24U];
volatile uint32_t ISPR[8U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */
uint32_t RESERVED2[24U];
volatile uint32_t ICPR[8U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */
uint32_t RESERVED3[24U];
volatile uint32_t IABR[8U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */
uint32_t RESERVED4[56U];
volatile uint8_t IP[240U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */
uint32_t RESERVED5[644U];
volatile uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */
} NVIC_Type;

/**
\brief Structure type to access the System Timer (SysTick).
*/
typedef struct {
volatile uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */
volatile uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */
volatile uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */
volatile uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */
} SysTick_Type;

__attribute__((always_inline)) static uint32_t getEncodedPriorityGrouping(uint8_t preemptPriority, uint8_t subPriority) {
uint32_t prioritygroup = ((uint32_t)((SCB->AIRCR & (7UL << 8U)) >> 8U));
uint32_t priorityGroupTmp = (prioritygroup & (uint32_t)0x07UL); /* only values 0..7 are used */
uint32_t preemptPriorityBits = ((7UL - priorityGroupTmp) > (uint32_t)(4U)) ? (uint32_t)(4U) : (uint32_t)(7UL - priorityGroupTmp);
uint32_t subPriorityBits = ((priorityGroupTmp + (uint32_t)(4U)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((priorityGroupTmp - 7UL) + (uint32_t)(4U));

return (
((preemptPriority & (uint32_t)((1UL << (preemptPriorityBits)) - 1UL)) << subPriorityBits) |
((subPriority & (uint32_t)((1UL << (subPriorityBits )) - 1UL)))
);
}

static inline uint32_t sysTickConfig(uint32_t ticks) {
if ((ticks - 1UL) > 0xFFFFFFUL) // Reload value impossible.
return (1UL);

// Set reload register.
SysTick->LOAD = (uint32_t)(ticks - 1UL);
// Set priority level MAX.
SCB->SHP[(((uint32_t)SysTick_IRQn) & 0xFUL)-4UL] = (uint8_t)((15 << (8U - 4U)) & (uint32_t)0xFFUL);
// Load the SysTick Counter Value.
SysTick->VAL = 0UL;
// Enable SysTick IRQ and SysTick Timer.
SysTick->CTRL = 0x7U;

return (0UL);
}

static inline void systicInit(uint8_t priority) {
if (!sysTickConfig(GET_TICK_NUMBER_PER_CLOCK)) {
SCB->SHP[(((uint32_t)SysTick_IRQn) & 0xFUL)-4UL] = (uint8_t)(((uint32_t)getEncodedPriorityGrouping(priority, 0) << (8U - 4U)) & (uint32_t)0xFFUL);
} else {
while(1);
}
}

static inline void timerInit() {
systicInit(15);
}

53 changes: 53 additions & 0 deletions demos/sdk/demolvgl/project/1ms_timer/microchip/pic32/timer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#include <mcu.h>

#define PRESCALER_1 0
#define PRESCALER_8 1
#define PRESCALER_64 2
#define PRESCALER_256 3

#define PRESCALER_VALUE_1 1
#define PRESCALER_VALUE_8 8
#define PRESCALER_VALUE_64 64
#define PRESCALER_VALUE_256 256

#ifdef PIC32TIMER
#define _prescale_formula(_presc) ((CLOCK*1000UL)/(_presc*2))
#else
#define _prescale_formula(_presc) ((CLOCK*1000UL)/(_presc))
#endif

#define _prescale_values() (_prescale_formula(1)<UINT16_MAX)?PRESCALER_1:\
(_prescale_formula(8)<UINT16_MAX)?PRESCALER_8:\
(_prescale_formula(64)<UINT16_MAX)?PRESCALER_64:\
PRESCALER_256

#define _clock_values(_presc) (_presc == PRESCALER_1)?_prescale_formula(PRESCALER_VALUE_1):\
(_presc == PRESCALER_8)?_prescale_formula(PRESCALER_VALUE_8):\
(_presc == PRESCALER_64)?_prescale_formula(PRESCALER_VALUE_64):\
_prescale_formula(PRESCALER_VALUE_256)

static inline void timerInit() {
// Configure Timer1 for 1ms interrupt
uint8_t presc;
presc = _prescale_values();
T1CONbits.TON = 0; // Disable Timer1 during configuration.
T1CONbits.TCS = 0; // Select internal peripheral clock.
T1CONbits.TCKPS = presc; // Set prescaler.
T1CONbits.TGATE = 0; // Disable gated time accumulation.
TMR1 = 0; // Clear Timer1 value.
PR1 = _clock_values(presc); // For a 1ms interrupt (Clock KHz / presc ).

// Clear Timer1 interrupt flag.
IFS0bits.T1IF = 0;

// Set Interrupt priority.
IPC1bits.T1IP = 7;

INTCONbits.MVEC = 1; // Enable Multi Vecotr Interrupts.
__builtin_enable_interrupts(); // Enable global interrupts.

// Enable Timer1 interrupt.
IEC0bits.T1IE = 1;

T1CONbits.TON = 1;
}
90 changes: 90 additions & 0 deletions demos/sdk/demolvgl/project/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
cmake_minimum_required(VERSION 3.19)

if (${TOOLCHAIN_LANGUAGE} MATCHES "MikroC")
project(demo_lvgl_widgets LANGUAGES MikroC)
else()
project(demo_lvgl_widgets LANGUAGES C ASM)
endif()

include(mikroeUtils)
include(${CMAKE_CURRENT_SOURCE_DIR}/1ms_timer/TimerHeaderConfig.cmake)

set(PROJECT_TYPE "lvgl_designer" CACHE STRING "" FORCE)

add_executable(demo_lvgl_widgets
main.c
1ms_Timer.h
resource.mres
main_screen.mscr
main_screen.c
main_screen.h
driver/display_lvgl.h
driver/lv_port_indev.h
driver/display_lvgl.c
driver/lv_port_indev.c
widgets/lv_demo_widgets.c
widgets/lv_demo_widgets.h
widgets/assets/img_lvgl_logo.c
)

set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS resource.mres)

find_package(MikroC.Core REQUIRED)
find_package_me(MikroSDK.LVGL.Common REQUIRED)
find_package_me(MikroSDK.GraphicLibrary REQUIRED)
find_package_me(MikroSDK.LVGL)

lvgl_designer_generator(demo_lvgl_widgets resource.mres main_screen.mscr)

target_link_libraries(demo_lvgl_widgets
PUBLIC
MikroC.Core
MikroSDK.LVGL
MikroSDK.LVGL.Common
MikroSDK.GraphicLibrary
)

if(NOT DEFINED IS_PD_SETUP)
set(IS_PD_SETUP 0)
else()
if(${IS_PD_SETUP})
set(IS_PD_SETUP 1)
else()
set(IS_PD_SETUP 0)
endif()
endif()

target_compile_definitions(demo_lvgl_widgets PUBLIC
${tim_list}
IS_PD_SETUP=${IS_PD_SETUP}
TFT_WIDTH=${_MSDK_TFT_WIDTH_}
)

target_include_directories(demo_lvgl_widgets
PUBLIC
.
driver
widgets
1ms_timer
)

if((${MCU_FLASH} LESS 1000000) OR (${MCU_RAM} LESS 80000)) ## 1M Flash / 80KB RAM recommended.
message(FATAL_ERROR ": ${MCU_NAME} does not have recommended memory for this example.")
endif()

if(COMPILER_REVISION)
if(${COMPILER_REVISION} VERSION_GREATER_EQUAL "1.0")
if(${TOOLCHAIN_LANGUAGE} STREQUAL "GNU")
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.meproject)
fetch_startup_name(${CMAKE_CURRENT_SOURCE_DIR}/.meproject startupName)
if(startupName)
add_startup_all_targets(. ${CMAKE_CURRENT_SOURCE_DIR} ${startupName})
endif()
fetch_linker_name(${CMAKE_CURRENT_SOURCE_DIR}/.meproject linkerName)
if(linkerName)
add_ld_all_targets(. ${CMAKE_CURRENT_SOURCE_DIR} ${linkerName})
endif()
endif()
endif()
endif()
endif()
26 changes: 26 additions & 0 deletions demos/sdk/demolvgl/project/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# LVGL Tool DEMO

This Demo shows how to use Widget components of LVGL Tool in NECTOStudio IDE. First it displays the intro screen and then it shows application screen.

- **Authors** : [MikroE](https://github.com/MikroElektronika)
- **Version** : 3.0.0
- **Date** : ${COPYRIGHT_YEAR}.

## Hardware Support

- Place TFT Display into the TFT socket of the Board.

## Software Support

We provide demo code for testing LVGL Tool functionality.
For example to work, TFT Display should be chosen during setup creation. To create a setup with TFT Display follow these steps:

1. Click on Setups and select New.
2. Select GCC ARM or XC32 compiler.
3. Select Board you are using.
4. Select your MCU Card.
5. Select desired display, and choose programmer/debugger tool.
6. Click Finish.
7. Program the MCU.

---
Loading

0 comments on commit f98ca13

Please sign in to comment.