Commit 15db2322 authored by Glenn Andrews's avatar Glenn Andrews Committed by Anas Nashif
Browse files

samples: SMF: LVGL: SMF-based Calculator



This sample crates a touchscreen desk calculator based on
the sample state machine in _Practical UML Statecharts in
C/C++_ by Miro Samek.

Sample should build and run on any touchscreen-enabled
board with sufficient resources.

Tested on `disco_l475_iot1` board with
`adafruit_2_8_tft_touch_v2` touchscreen.

Signed-off-by: default avatarGlenn Andrews <glenn.andrews.42@gmail.com>
parent 56d241bd
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
# SPDX-License-Identifier: Apache-2.0

set(CMAKE_CXX_FLAGS "-fstack-usage")
cmake_minimum_required(VERSION 3.20.0)

find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(smf_calculator_demo)

target_sources(app PRIVATE src/main.c)
target_sources(app PRIVATE src/smf_console_cmds.c)
target_sources(app PRIVATE src/smf_calculator_thread.c)
+100 −0
Original line number Diff line number Diff line
.. zephyr:code-sample:: smf_calculator
   :name: SMF Calculator
   :relevant-api: smf

   Create a simple desk calculator using the State Machine Framework.

Overview
********

This sample creates a basic desk calculator driven by a state machine written
with the :ref:`State Machine Framework <smf>`.

The 'business logic' of the calculator is based on the statechart given in
Fig 2.18 of *Practical UML Statecharts in C/C++* 2nd Edition by Miro Samek.
This uses a three-layer hierarchical statechart to handle situations such as
ignoring leading zeroes, and disallowing multiple decimal points.

The statechart has been slightly modified to display different output on the
screen in the ``op_entered`` state depending on if a previous result is
available or not.

.. figure:: img/smf_calculator.svg
    :align: center
    :alt: SMF Calculator Statechart
    :figclass: align-center

    Statechart for the SMF Calculator business logic.

The graphical interface uses an LVGL button matrix for input and text label for
output, based on the sample in samples/drivers/display. The state machine updates
the output text label after every call to :c:func:`smf_run_state`.

:kconfig:option:`CONFIG_LV_Z_VDB_SIZE` has been reduced to 14% to allow it to run
on RAM-constrained boards like the :ref:`disco_l475_iot1_board`.

Requirements
************

The GUI should work with any touchscreen display supported by Zephyr. The shield
must be passed to ``west build`` using the ``--shield`` option, e.g.
``--shield adafruit_2_8_tft_touch_v2``

List of Arduino-based touchscreen shields:

- :ref:`adafruit_2_8_tft_touch_v2`
- :ref:`buydisplay_2_8_tft_touch_arduino`
- :ref:`buydisplay_3_5_tft_touch_arduino`

The demo should also work on STM32 Discovery Kits with built-in touchscreens e.g.

- :ref:`stm32f412g_disco_board`
- :ref:`st25dv_mb1283_disco_board`
- :ref:`stm32f7508_dk_board`
- :ref:`stm32f769i_disco_board`

etc. These will not need a shield defined as the touchscreen is built-in.


Building and Running
********************

Below is an example on how to build for a :ref:`disco_l475_iot1_board` board with
a :ref:`adafruit_2_8_tft_touch_v2`.

.. zephyr-app-commands::
   :zephyr-app: samples/subsys/smf/smf_calculator
   :board: disco_l475_iot1
   :goals: build
   :shield: adafruit_2_8_tft_touch_v2
   :compact:

For testing purpose without the need of any hardware, the :ref:`native_sim <native_sim>`
board is also supported and can be built as follows;

.. zephyr-app-commands::
   :zephyr-app: samples/subsys/smf/smf_calculator
   :board: native_sim
   :goals: build
   :compact:

CLI control
===========

As well as control through the GUI, the calculator can be controlled through the shell,
demonstrating a state machine can receive inputs from multiple sources.
The ``key <key>`` command sends a keypress to the state machine. Valid keys are
``0`` through ``9`` for numbers, ``.``, ``+``, ``-``, ``*``, ``/`` and ``=`` to
perform the expected function, ``C`` for Cancel, and ``E`` for Cancel Entry.

GUI update speed on the :ref:`disco_l475_iot1_board` with :ref:`adafruit_2_8_tft_touch_v2`
touchscreen is of the order of 0.8s due to button matrices invalidating the entire
matrix area when pressed, rather than just the button that was selected. This could
be sped up by using 18 individual buttons rather than a single matrix, but is sufficient
for this demo.

References
**********

*Practical UML Statecharts in C/C++* 2nd Edition by Miro Samek
https://www.state-machine.com/psicc2
+0 −0

File added.

Preview suppressed by a .gitattributes entry or the file's encoding is unsupported.

+37 −0
Original line number Diff line number Diff line
CONFIG_DEBUG=y
CONFIG_LOG=y
CONFIG_SHELL=y

# Needed for boards that enable RTT backends for logging
# e.g. nrf52840dk/nrf52840 and any others that enable it
CONFIG_LOG_BACKEND_RTT=n

# Enable the state machine framework
CONFIG_SMF=y
CONFIG_SMF_ANCESTOR_SUPPORT=y
CONFIG_SMF_INITIAL_TRANSITION=y

# Enable floating point support
CONFIG_REQUIRES_FLOAT_PRINTF=y

# Enable thread awareness for debugging tools supporting it
CONFIG_DEBUG_THREAD_INFO=y

# enable to use thread names
CONFIG_THREAD_NAME=y

# Display Options
CONFIG_DISPLAY=y
CONFIG_DISPLAY_LOG_LEVEL_ERR=y

# LVGL Options
CONFIG_LVGL=y
CONFIG_LV_Z_MEM_POOL_SIZE=16384
CONFIG_LV_Z_SHELL=y
# Percentage of screen size for a video buffer
# LVGL defaults sets this too high for resource-constrained boards.
# 14% ~= 32KB RAM on adafruit_2_8_tft_touch_v2
CONFIG_LV_Z_VDB_SIZE=14

# extra large in case you want to enable LV_USE_REFR_DEBUG
CONFIG_MAIN_STACK_SIZE=4096
+23 −0
Original line number Diff line number Diff line
sample:
  description: SMF Calculator GUI Application
  name: smf_calculator
tests:
  sample.smf.smf_calculator:
    filter: dt_chosen_enabled("zephyr,display")
    # Sample takes ~300k on disco_l475_iot1 board, add 50k just in case.
    # Ram usage is 70k on disco_l475_iot1 board with adafruit_2_8_tft_touch_v2.
    # Can be reduced by changing CONFIG_LV_Z_VDB_SIZE,
    # CONFIG_LV_Z_MEM_POOL_SIZE and CONFIG_MAIN_STACK_SIZE.
    min_flash: 350
    min_ram: 75
    harness: none
    tags:
      - samples
      - display
      - gui
      - lvgl
      - smf
    modules:
      - lvgl
    integration_platforms:
      - native_sim/native/64
Loading