├── .gitignore ├── .gitmodules ├── CMakeLists.txt ├── ISR.c ├── ISR.h ├── LICENSE ├── README.md ├── build.sh ├── clean.sh ├── debug ├── tftlogger.c └── tftlogger.h ├── frame ├── frame.h ├── frame_event.h ├── frame_rect.h └── frame_type.h ├── pico_sdk_import.cmake ├── test.c ├── ui ├── ui_context.h ├── ui_init.c ├── ui_manage.c └── ui_protos.h └── widgets ├── APRSEventProc.c ├── CalibrationEventProc.c ├── CallsignEventProc.c ├── PSKEventProc.c ├── PhoneEventProc.c ├── SettingsEventProc.c ├── TerminalEventProc.c ├── TopBarEventProc.c ├── widgets_utility.c └── widgets_utility.h /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Object files 5 | *.o 6 | *.ko 7 | *.obj 8 | *.elf 9 | 10 | # Linker output 11 | *.ilk 12 | *.map 13 | *.exp 14 | 15 | # Precompiled Headers 16 | *.gch 17 | *.pch 18 | 19 | # Libraries 20 | *.lib 21 | *.a 22 | *.la 23 | *.lo 24 | 25 | # Shared objects (inc. Windows DLLs) 26 | *.dll 27 | *.so 28 | *.so.* 29 | *.dylib 30 | 31 | # Executables 32 | *.exe 33 | *.out 34 | *.app 35 | *.i*86 36 | *.x86_64 37 | *.hex 38 | 39 | # Debug files 40 | *.dSYM/ 41 | *.su 42 | *.idb 43 | *.pdb 44 | 45 | # Kernel Module Compile Results 46 | *.mod* 47 | *.cmd 48 | .tmp_versions/ 49 | modules.order 50 | Module.symvers 51 | Mkfile.old 52 | dkms.conf 53 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "pico-touchscr-sdk"] 2 | path = pico-touchscr-sdk 3 | url = https://github.com/RPiks/pico-touchscr-sdk.git 4 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Generated Cmake Pico project file 2 | 3 | cmake_minimum_required(VERSION 3.13) 4 | 5 | set(CMAKE_C_STANDARD 11) 6 | set(CMAKE_CXX_STANDARD 17) 7 | 8 | # Initialise pico_sdk from installed location 9 | # (note this can come from environment, CMake cache etc) 10 | # set(PICO_SDK_PATH "/home/jabba/pico-sdk") 11 | 12 | set(PICO_BOARD pico CACHE STRING "Board type") 13 | 14 | # Pull in Raspberry Pi Pico SDK (must be before project) 15 | include(pico_sdk_import.cmake) 16 | 17 | if (PICO_SDK_VERSION_STRING VERSION_LESS "1.4.0") 18 | message(FATAL_ERROR "Raspberry Pi Pico SDK version 1.4.0 (or later) required. Your version is ${PICO_SDK_VERSION_STRING}") 19 | endif() 20 | 21 | project(pico-widgets-test C CXX ASM) 22 | 23 | # Initialise the Raspberry Pi Pico SDK 24 | pico_sdk_init() 25 | 26 | # Add executable. Default name is the project name, version 0.1 27 | add_executable(pico-widgets-test 28 | ${PROJECT_SOURCE_DIR}/pico-touchscr-sdk/lib/assert.c 29 | ${PROJECT_SOURCE_DIR}/pico-touchscr-sdk/ili9341/ili9341.c 30 | ${PROJECT_SOURCE_DIR}/pico-touchscr-sdk/touch/msp2807_touch.c 31 | ${PROJECT_SOURCE_DIR}/pico-touchscr-sdk/touch/msp2807_calibration.c 32 | ) 33 | 34 | target_sources(pico-widgets-test PUBLIC 35 | ${CMAKE_CURRENT_LIST_DIR}/debug/tftlogger.c 36 | ${CMAKE_CURRENT_LIST_DIR}/ui/ui_init.c 37 | ${CMAKE_CURRENT_LIST_DIR}/ui/ui_manage.c 38 | ${CMAKE_CURRENT_LIST_DIR}/widgets/widgets_utility.c 39 | ${CMAKE_CURRENT_LIST_DIR}/widgets/TopBarEventProc.c 40 | ${CMAKE_CURRENT_LIST_DIR}/widgets/SettingsEventProc.c 41 | ${CMAKE_CURRENT_LIST_DIR}/widgets/APRSEventProc.c 42 | ${CMAKE_CURRENT_LIST_DIR}/widgets/PSKEventProc.c 43 | ${CMAKE_CURRENT_LIST_DIR}/widgets/PhoneEventProc.c 44 | ${CMAKE_CURRENT_LIST_DIR}/widgets/CallsignEventProc.c 45 | ${CMAKE_CURRENT_LIST_DIR}/widgets/CalibrationEventProc.c 46 | ${CMAKE_CURRENT_LIST_DIR}/widgets/TerminalEventProc.c 47 | ${CMAKE_CURRENT_LIST_DIR}/ISR.c 48 | ${CMAKE_CURRENT_LIST_DIR}/test.c 49 | ) 50 | 51 | pico_set_program_name(pico-widgets-test "pico-widgets-test") 52 | pico_set_program_version(pico-widgets-test "0.15") 53 | 54 | pico_enable_stdio_uart(pico-widgets-test 1) 55 | #pico_enable_stdio_usb(pico-widgets-test 0) 56 | 57 | #include_directories(${PROJECT_SOURCE_DIR}/lib) 58 | 59 | # Add the standard include files to the build 60 | target_include_directories(pico-widgets-test PRIVATE 61 | ${CMAKE_CURRENT_LIST_DIR}/pico-touchscr-sdk 62 | ${CMAKE_CURRENT_LIST_DIR}/pico-touchscr-sdk/ili9341 63 | ${CMAKE_CURRENT_LIST_DIR}/pico-touchscr-sdk/touch 64 | ${CMAKE_CURRENT_LIST_DIR}/frame 65 | ${CMAKE_CURRENT_LIST_DIR}/ui 66 | ${CMAKE_CURRENT_LIST_DIR}/widgets 67 | ${CMAKE_CURRENT_LIST_DIR}/debug 68 | ${CMAKE_CURRENT_LIST_DIR} 69 | ${CMAKE_CURRENT_LIST_DIR}/.. # for our common lwipopts or any other standard includes, if required 70 | ) 71 | 72 | # Add any user requested libraries 73 | target_link_libraries( 74 | pico-widgets-test 75 | pico_stdlib 76 | hardware_adc 77 | hardware_spi 78 | pico_sync 79 | hardware_timer 80 | hardware_clocks 81 | hardware_spi 82 | ) 83 | 84 | pico_add_extra_outputs(pico-widgets-test) 85 | -------------------------------------------------------------------------------- /ISR.c: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Roman Piksaykin [piksaykin@gmail.com], R2BDY 4 | // https://www.qrz.com/db/r2bdy 5 | // 6 | /////////////////////////////////////////////////////////////////////////////// 7 | // 8 | // 9 | // ISR.c - Testing interrupt service routine where it is supposed to invoke 10 | // UI tick function (UI job). 11 | // 12 | // DESCRIPTION 13 | // 14 | // Implements an 1 kHz oscillator in order to process the data. 15 | // 16 | // PLATFORM 17 | // Hardware: Raspberry Pi Pico. 18 | // Software: https://github.com/RPiks/pico-touchscr-sdk 19 | // 20 | // REVISION HISTORY 21 | // 22 | // Rev 0.5 23 Feb 2023 23 | // Initial release. 24 | // 25 | // LICENCE 26 | // MIT License (http://www.opensource.org/licenses/mit-license.php) 27 | // 28 | // Copyright (c) 2023 by Roman Piksaykin 29 | // 30 | // Permission is hereby granted, free of charge,to any person obtaining a copy 31 | // of this software and associated documentation files (the Software), to deal 32 | // in the Software without restriction,including without limitation the rights 33 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 34 | // copies of the Software, and to permit persons to whom the Software is 35 | // furnished to do so, subject to the following conditions: 36 | // 37 | // The above copyright notice and this permission notice shall be included in 38 | // all copies or substantial portions of the Software. 39 | // 40 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 41 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 42 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 43 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 44 | // LIABILITY,WHETHER IN AN ACTION OF CONTRACT,TORT OR OTHERWISE, ARISING FROM, 45 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 46 | // THE SOFTWARE. 47 | /////////////////////////////////////////////////////////////////////////////// 48 | #include "ISR.h" 49 | 50 | static uint64_t sFutureTm; 51 | 52 | /// @brief 1 kHz oscillator. 53 | void __not_in_flash_func (tmISR)(void) 54 | { 55 | static int32_t sTick = 0; 56 | gpio_put(PICO_DEFAULT_LED_PIN, (++sTick)&1); 57 | 58 | if(0b11 == (sTick & 0b11)) 59 | { 60 | UItick(GetUIContext()); 61 | } 62 | 63 | sFutureTm += OSC_CLK_INTERVAL; /* Increment oscillator phase. */ 64 | 65 | hw_clear_bits(&timer_hw->intr, 1U<alarm[TIMER_ALARM_NUM] = (uint32_t)sFutureTm; /* Set next. */ 67 | } 68 | 69 | /// @brief Inits the timer, the Pico's interrupt system. 70 | void InitISR(void) 71 | { 72 | hw_set_bits(&timer_hw->inte, 1U<timerawl + 500; /* Postpone first ISR call. */ 78 | timer_hw->alarm[TIMER_ALARM_NUM] 79 | = (uint32_t)sFutureTm; /* Set first ISR launch time. */ 80 | } 81 | -------------------------------------------------------------------------------- /ISR.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Roman Piksaykin [piksaykin@gmail.com], R2BDY 4 | // https://www.qrz.com/db/r2bdy 5 | // 6 | /////////////////////////////////////////////////////////////////////////////// 7 | // 8 | // 9 | // ISR.h - Testing interrupt service routine where it is supposed to invoke 10 | // UI tick function (UI job). 11 | // 12 | // DESCRIPTION 13 | // 14 | // Implements ADC initialization as well as ADC ISR with UI tick call. 15 | // 16 | // PLATFORM 17 | // Hardware: Raspberry Pi Pico. 18 | // Software: https://github.com/RPiks/pico-touchscr-sdk 19 | // 20 | // REVISION HISTORY 21 | // 22 | // Rev 0.5 23 Feb 2023 23 | // Initial release. 24 | // 25 | // LICENCE 26 | // MIT License (http://www.opensource.org/licenses/mit-license.php) 27 | // 28 | // Copyright (c) 2023 by Roman Piksaykin 29 | // 30 | // Permission is hereby granted, free of charge,to any person obtaining a copy 31 | // of this software and associated documentation files (the Software), to deal 32 | // in the Software without restriction,including without limitation the rights 33 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 34 | // copies of the Software, and to permit persons to whom the Software is 35 | // furnished to do so, subject to the following conditions: 36 | // 37 | // The above copyright notice and this permission notice shall be included in 38 | // all copies or substantial portions of the Software. 39 | // 40 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 41 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 42 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 43 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 44 | // LIABILITY,WHETHER IN AN ACTION OF CONTRACT,TORT OR OTHERWISE, ARISING FROM, 45 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 46 | // THE SOFTWARE. 47 | /////////////////////////////////////////////////////////////////////////////// 48 | #include "hardware/clocks.h" 49 | #include "pico/stdlib.h" 50 | 51 | #include 52 | #include 53 | 54 | #define kHZ 1000L 55 | #define TIMER_HW_CLK_FREQ (1000000L) 56 | #define TIMER_ALARM_NUM 0 57 | #define TIMER_ALARM_IRQ TIMER_IRQ_0 58 | #define OSC_FREQ (1 * kHZ) 59 | #define OSC_CLK_INTERVAL (TIMER_HW_CLK_FREQ / OSC_FREQ) 60 | 61 | void __not_in_flash_func (tmISR)(void); 62 | void InitISR(void); 63 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Roman Piksaykin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # A tiny GUI for Raspberry Pi Pico 2 | 3 | The pico-widgets for Raspberry Pi Pico is a lightweight graphical user interface (GUI) which is based on Pico Touchscreen SDK https://github.com/RPiks/pico-touchscr-sdk. 4 | 5 | ![ezgif com-add-text](https://user-images.githubusercontent.com/47501785/222282840-043caf1d-04c9-4bf5-8bd5-c6e6c5f35afe.gif) 6 | 7 | # A `Frame` concept 8 | The pico-widgets is based on graphical rectangular frames which receive touch events and process them in highly customizable manner. Which allows to implement a vast range of widgets' types such as dialogs, lists and keyboard. 9 | 10 | # Example Code 11 | 12 | It is included. 13 | 14 | # Quick-start 15 | 16 | 1. Install Raspberry Pi Pico SDK. Configure environment variables. Test 17 | whether it is built successfully. 18 | 19 | 2. git clone this repository. 20 | - cd pico-widgets 21 | - git submodule init 22 | - git submodule update 23 | - ./build.sh 24 | 25 | Check whether output file ./build/pico-widgets.uf2 appears. 26 | 27 | 3. Assemble the test board using pin connection information provided in test.c file of https://github.com/RPiks/pico-touchscr-sdk 28 | 29 | 4. Load the .uf2 file (2) into the Pico. 30 | 31 | 5. You now have the screen with the Top menu. Press 'PSK' in order to bring the keyboard up. 32 | 33 | 6. Use the SDK on your projects freely. Any possible contribution appreciated. 34 | 35 | 7. Please take in account that the project is still in development and many of its features might be a subject of change. 36 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ### VT Colors. 4 | 5 | ECHO_ESCAPE=" -e " 6 | 7 | TEXT_FG_BLACK="" 8 | TEXT_FG_RED="" 9 | TEXT_FG_GREEN="" 10 | TEXT_FG_ORANGE="" 11 | TEXT_FG_BLUE="" 12 | TEXT_FG_MAGENTA="" 13 | TEXT_FG_CYAN="" 14 | TEXT_FG_GRAY="" 15 | TEXT_FG_DARK_GRAY="" 16 | TEXT_FG_LIGHT_RED="" 17 | TEXT_FG_LIGHT_GREEN="" 18 | TEXT_FG_YELLOW="" 19 | TEXT_FG_VIOLET="" 20 | TEXT_FG_LIGHT_MAGENTA="" 21 | TEXT_FG_LIGHT_CYAN="" 22 | TEXT_FG_WHITE="" 23 | 24 | TEXT_BG_BLACK="" 25 | TEXT_BG_RED="" 26 | TEXT_BG_GREEN="" 27 | TEXT_BG_YELLOW="" 28 | TEXT_BG_BLUE="" 29 | TEXT_BG_MAGENTA="" 30 | TEXT_BG_CYAN="" 31 | TEXT_BG_GRAY="" 32 | 33 | TEXT_NORM="" # Back to normal text 34 | 35 | MSG_PREFIX="$TEXT_BG_GREEN$TEXT_FG_YELLOW => $TEXT_NORM" 36 | 37 | _banner() 38 | { 39 | echo 40 | echo $ECHO_ESCAPE " "$TEXT_BG_GREEN$TEXT_FG_DARK_GRAY"┌──────────────"$TEXT_FG_LIGHT_GREEN"┐"$TEXT_NORM 41 | echo $ECHO_ESCAPE " "$TEXT_BG_GREEN$TEXT_FG_DARK_GRAY"│ "$TEXT_FG_GRAY"PICO-WIDGETS "$TEXT_FG_LIGHT_GREEN"│"$TEXT_NORM 42 | echo $ECHO_ESCAPE " "$TEXT_BG_GREEN$TEXT_FG_DARK_GRAY"└"$TEXT_FG_LIGHT_GREEN"──────────────┘"$TEXT_NORM 43 | echo 44 | } 45 | 46 | _failed() 47 | { 48 | echo 49 | echo $ECHO_ESCAPE$MSG_PREFIX$TEXT_BG_RED$TEXT_FG_YELLOW" Failed :( "$TEXT_NORM 50 | echo 51 | } 52 | 53 | _completed() 54 | { 55 | echo 56 | echo $ECHO_ESCAPE$MSG_PREFIX$TEXT_BG_CYAN$TEXT_FG_WHITE" Completed successfully :) "$TEXT_NORM 57 | echo 58 | } 59 | 60 | _ex() 61 | { 62 | echo $@ 63 | if ! $@ 64 | then 65 | _failed 66 | exit 1 67 | fi 68 | } 69 | 70 | ############################################ 71 | 72 | _banner 73 | 74 | export SC_OS=`uname -s | tr '[:upper:]' '[:lower:]'` 75 | 76 | echo $@ | grep -- 'release' > /dev/null 2>&1 77 | if [ "$?" -eq "0" ]; then 78 | CMAKE_BUILD_TYPE=Release 79 | BUILD_PARAMS=$BUILD_PARAMS' release' 80 | else 81 | CMAKE_BUILD_TYPE=Debug 82 | BUILD_PARAMS=$BUILD_PARAMS' debug' 83 | fi 84 | 85 | echo $@ | grep -- 'verbose' > /dev/null 2>&1 86 | if [ "$?" -eq "0" ]; then 87 | CMAKE_VERBOSE_MAKEFILE=TRUE 88 | BUILD_PARAMS=$BUILD_PARAMS' verbose' 89 | else 90 | CMAKE_VERBOSE_MAKEFILE=FALSE 91 | BUILD_PARAMS=$BUILD_PARAMS' silent' 92 | fi 93 | 94 | echo $@ | grep -- 'single' > /dev/null 2>&1 95 | if [ "$?" -eq "0" ]; then 96 | SC_BUILD_THREADS=1 97 | BUILD_PARAMS=$BUILD_PARAMS' single' 98 | else if [ "$SC_OS" == "darwin" ]; then 99 | SC_BUILD_THREADS=`/usr/sbin/system_profiler -detailLevel full SPHardwareDataType | awk '/Total Number of Cores/ {print $5};'` 100 | else 101 | SC_BUILD_THREADS=`cat /proc/cpuinfo | grep ^processor | wc -l` 102 | fi 103 | 104 | BUILD_PARAMS=$BUILD_PARAMS' multi-make' 105 | fi 106 | 107 | SC_BUILD_THREADS=$((SC_BUILD_THREADS / 2 + 1)) 108 | 109 | echo $ECHO_ESCAPE$MSG_PREFIX$TEXT_BG_BLUE$TEXT_FG_WHITE" BUILD MODE:$BUILD_PARAMS "$TEXT_NORM 110 | echo $ECHO_ESCAPE$MSG_PREFIX$TEXT_BG_BLUE$TEXT_FG_WHITE" MAKE JOBS : $SC_BUILD_THREADS "$TEXT_NORM 111 | echo 112 | 113 | cd build 114 | _ex cmake -DCMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -DCMAKE_VERBOSE_MAKEFILE=$CMAKE_VERBOSE_MAKEFILE .. 115 | _ex make -j $SC_BUILD_THREADS 116 | # _ex sudo make install -j $SC_BUILD_THREADS 117 | 118 | _completed 119 | 120 | 121 | #cd build 122 | #cmake .. 123 | #make 124 | 125 | -------------------------------------------------------------------------------- /clean.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | rm -rf build/* 4 | -------------------------------------------------------------------------------- /debug/tftlogger.c: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Roman Piksaykin [piksaykin@gmail.com], R2BDY 4 | // https://www.qrz.com/db/r2bdy 5 | // 6 | /////////////////////////////////////////////////////////////////////////////// 7 | // 8 | // 9 | // tftlogger.c - Logging functions. 10 | // 11 | // 12 | // DESCRIPTION 13 | // 14 | // Implements logging functions for the library. The data is written to 15 | // the TFT screen onto its pre-defines location. 16 | // 17 | // PLATFORM 18 | // Hardware: Raspberry Pi Pico. 19 | // Software: https://github.com/RPiks/pico-touchscr-sdk 20 | // 21 | // REVISION HISTORY 22 | // 23 | // Rev 0.5 25 Feb 2023 24 | // Initial release. 25 | // 26 | // LICENCE 27 | // MIT License (http://www.opensource.org/licenses/mit-license.php) 28 | // 29 | // Copyright (c) 2023 by Roman Piksaykin 30 | // 31 | // Permission is hereby granted, free of charge,to any person obtaining a copy 32 | // of this software and associated documentation files (the Software), to deal 33 | // in the Software without restriction,including without limitation the rights 34 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 35 | // copies of the Software, and to permit persons to whom the Software is 36 | // furnished to do so, subject to the following conditions: 37 | // 38 | // The above copyright notice and this permission notice shall be included in 39 | // all copies or substantial portions of the Software. 40 | // 41 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 42 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 43 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 44 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 45 | // LIABILITY,WHETHER IN AN ACTION OF CONTRACT,TORT OR OTHERWISE, ARISING FROM, 46 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 47 | // THE SOFTWARE. 48 | /////////////////////////////////////////////////////////////////////////////// 49 | #include "tftlogger.h" 50 | 51 | void DebugPrintf(const char* str, ...) 52 | { 53 | static int seq = 0; 54 | 55 | screen_control_t *pscr = &GetUIContext()->mScreenCtl; 56 | 57 | if(!seq) 58 | { 59 | pscr->mCursorX = 0; 60 | pscr->mCursorY = 16; 61 | } 62 | ++seq; 63 | 64 | va_list argptr; 65 | va_start(argptr, str); 66 | 67 | char buf[TEXT_WIDTH * 4]; // 4 rows of text max. 68 | vsnprintf(buf, sizeof(buf), str, argptr); 69 | va_end(argptr); 70 | 71 | TftPutString(pscr, buf, 16, 22, 0, 5); 72 | } 73 | -------------------------------------------------------------------------------- /debug/tftlogger.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Roman Piksaykin [piksaykin@gmail.com], R2BDY 4 | // https://www.qrz.com/db/r2bdy 5 | // 6 | /////////////////////////////////////////////////////////////////////////////// 7 | // 8 | // 9 | // tftlogger.h - Logging functions. 10 | // 11 | // 12 | // DESCRIPTION 13 | // 14 | // Implements logging functions for the library. The data is written to 15 | // the TFT screen onto its pre-defines location. 16 | // 17 | // PLATFORM 18 | // Hardware: Raspberry Pi Pico. 19 | // Software: https://github.com/RPiks/pico-touchscr-sdk 20 | // 21 | // REVISION HISTORY 22 | // 23 | // Rev 0.5 25 Feb 2023 24 | // Initial release. 25 | // 26 | // LICENCE 27 | // MIT License (http://www.opensource.org/licenses/mit-license.php) 28 | // 29 | // Copyright (c) 2023 by Roman Piksaykin 30 | // 31 | // Permission is hereby granted, free of charge,to any person obtaining a copy 32 | // of this software and associated documentation files (the Software), to deal 33 | // in the Software without restriction,including without limitation the rights 34 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 35 | // copies of the Software, and to permit persons to whom the Software is 36 | // furnished to do so, subject to the following conditions: 37 | // 38 | // The above copyright notice and this permission notice shall be included in 39 | // all copies or substantial portions of the Software. 40 | // 41 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 42 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 43 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 44 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 45 | // LIABILITY,WHETHER IN AN ACTION OF CONTRACT,TORT OR OTHERWISE, ARISING FROM, 46 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 47 | // THE SOFTWARE. 48 | /////////////////////////////////////////////////////////////////////////////// 49 | #ifndef TFTLOGGER_H_ 50 | #define TFTLOGGER_H_ 51 | 52 | #include 53 | #include 54 | #include 55 | 56 | void DebugPrintf(const char* str, ...); 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /frame/frame.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Roman Piksaykin [piksaykin@gmail.com], R2BDY 4 | // https://www.qrz.com/db/r2bdy 5 | // 6 | /////////////////////////////////////////////////////////////////////////////// 7 | // 8 | // 9 | // frame.h - The `frame` definition header. 10 | // 11 | // 12 | // DESCRIPTION 13 | // 14 | // Defines a basic atom of the pico-widgets UI. 15 | // 16 | // PLATFORM 17 | // Hardware: Raspberry Pi Pico. 18 | // Software: https://github.com/RPiks/pico-touchscr-sdk 19 | // 20 | // REVISION HISTORY 21 | // 22 | // Rev 0.5 25 Feb 2023 23 | // Initial release. 24 | // 25 | // LICENCE 26 | // MIT License (http://www.opensource.org/licenses/mit-license.php) 27 | // 28 | // Copyright (c) 2023 by Roman Piksaykin 29 | // 30 | // Permission is hereby granted, free of charge,to any person obtaining a copy 31 | // of this software and associated documentation files (the Software), to deal 32 | // in the Software without restriction,including without limitation the rights 33 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 34 | // copies of the Software, and to permit persons to whom the Software is 35 | // furnished to do so, subject to the following conditions: 36 | // 37 | // The above copyright notice and this permission notice shall be included in 38 | // all copies or substantial portions of the Software. 39 | // 40 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 41 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 42 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 43 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 44 | // LIABILITY,WHETHER IN AN ACTION OF CONTRACT,TORT OR OTHERWISE, ARISING FROM, 45 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 46 | // THE SOFTWARE. 47 | /////////////////////////////////////////////////////////////////////////////// 48 | #ifndef FRAME_H_ 49 | #define FRAME_H_ 50 | 51 | #include 52 | #include 53 | #include 54 | #include 55 | 56 | #include "frame_type.h" 57 | #include "frame_rect.h" 58 | #include "frame_event.h" 59 | 60 | #define ASSERT(x) assert_(x) 61 | 62 | typedef struct frame frame; 63 | struct frame 64 | { 65 | frame_type mFrameType; // Type of the frame. 66 | 67 | const char *mpTitle; // Title. 68 | 69 | frame_rect mRegion; // Region of the whole frame, in blocks of 8x8. 70 | 71 | color_t mPaper, mInk; // Color scheme of this frame. 72 | 73 | int (*mpfEventProc) // Ptr to event processing 74 | (frame *pF, frame_event fE, // function. 75 | int x, int y, void *pcntx); 76 | 77 | void *mpPayLoad; // Custom data/func associated with the frame. 78 | }; 79 | 80 | #endif 81 | -------------------------------------------------------------------------------- /frame/frame_event.h: -------------------------------------------------------------------------------- 1 | typedef enum 2 | { 3 | kEventUndef = -1, // Perhaps shouldn't be used. 4 | 5 | kEventPing = 0, // Whether it is alive. 6 | kEventDraw = 1, // To draw. 7 | kEventClickInside = 2, // Click inside BBox. 8 | kEventClickOutside = 3, // ...outside. 9 | kEventTick = 4, // Time has passed. 10 | kEventClose = 5, // To close immediately. 11 | 12 | } frame_event; 13 | -------------------------------------------------------------------------------- /frame/frame_rect.h: -------------------------------------------------------------------------------- 1 | #ifndef FRAME_RECT_H 2 | #define FRAME_RECT_H 3 | 4 | #include 5 | 6 | typedef struct 7 | { 8 | uint16_t mTlx, mTly; 9 | uint16_t mWidth, mHeight; 10 | } frame_rect; 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /frame/frame_type.h: -------------------------------------------------------------------------------- 1 | typedef enum 2 | { 3 | kFrameUndef = -1, 4 | 5 | kFrameRoot = 0, 6 | kFrameBBox = 1, 7 | kFrameTransparent= 2, 8 | kFrameStub = 3, 9 | kFramePersistent = 4 10 | 11 | } frame_type; 12 | -------------------------------------------------------------------------------- /pico_sdk_import.cmake: -------------------------------------------------------------------------------- 1 | # This is a copy of /external/pico_sdk_import.cmake 2 | 3 | # This can be dropped into an external project to help locate this SDK 4 | # It should be include()ed prior to project() 5 | 6 | if (DEFINED ENV{PICO_SDK_PATH} AND (NOT PICO_SDK_PATH)) 7 | set(PICO_SDK_PATH $ENV{PICO_SDK_PATH}) 8 | message("Using PICO_SDK_PATH from environment ('${PICO_SDK_PATH}')") 9 | endif () 10 | 11 | if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT} AND (NOT PICO_SDK_FETCH_FROM_GIT)) 12 | set(PICO_SDK_FETCH_FROM_GIT $ENV{PICO_SDK_FETCH_FROM_GIT}) 13 | message("Using PICO_SDK_FETCH_FROM_GIT from environment ('${PICO_SDK_FETCH_FROM_GIT}')") 14 | endif () 15 | 16 | if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_PATH)) 17 | set(PICO_SDK_FETCH_FROM_GIT_PATH $ENV{PICO_SDK_FETCH_FROM_GIT_PATH}) 18 | message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')") 19 | endif () 20 | 21 | set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK") 22 | set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of SDK from git if not otherwise locatable") 23 | set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK") 24 | 25 | if (NOT PICO_SDK_PATH) 26 | if (PICO_SDK_FETCH_FROM_GIT) 27 | include(FetchContent) 28 | set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR}) 29 | if (PICO_SDK_FETCH_FROM_GIT_PATH) 30 | get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}") 31 | endif () 32 | # GIT_SUBMODULES_RECURSE was added in 3.17 33 | if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.17.0") 34 | FetchContent_Declare( 35 | pico_sdk 36 | GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk 37 | GIT_TAG master 38 | GIT_SUBMODULES_RECURSE FALSE 39 | ) 40 | else () 41 | FetchContent_Declare( 42 | pico_sdk 43 | GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk 44 | GIT_TAG master 45 | ) 46 | endif () 47 | 48 | if (NOT pico_sdk) 49 | message("Downloading Raspberry Pi Pico SDK") 50 | FetchContent_Populate(pico_sdk) 51 | set(PICO_SDK_PATH ${pico_sdk_SOURCE_DIR}) 52 | endif () 53 | set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE}) 54 | else () 55 | message(FATAL_ERROR 56 | "SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git." 57 | ) 58 | endif () 59 | endif () 60 | 61 | get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}") 62 | if (NOT EXISTS ${PICO_SDK_PATH}) 63 | message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' not found") 64 | endif () 65 | 66 | set(PICO_SDK_INIT_CMAKE_FILE ${PICO_SDK_PATH}/pico_sdk_init.cmake) 67 | if (NOT EXISTS ${PICO_SDK_INIT_CMAKE_FILE}) 68 | message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the Raspberry Pi Pico SDK") 69 | endif () 70 | 71 | set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE) 72 | 73 | include(${PICO_SDK_INIT_CMAKE_FILE}) 74 | -------------------------------------------------------------------------------- /test.c: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Roman Piksaykin [piksaykin@gmail.com], R2BDY 4 | // https://www.qrz.com/db/r2bdy 5 | // 6 | /////////////////////////////////////////////////////////////////////////////// 7 | // 8 | // 9 | // test.c - The main testing routine. 10 | // 11 | // 12 | // DESCRIPTION 13 | // 14 | // Implements pretty basic demo of the pico-widgets library. 15 | // 16 | // PLATFORM 17 | // Hardware: Raspberry Pi Pico. 18 | // Software: https://github.com/RPiks/pico-touchscr-sdk 19 | // 20 | // REVISION HISTORY 21 | // 22 | // Rev 0.5 25 Feb 2023 23 | // Initial release. 24 | // 25 | // LICENCE 26 | // MIT License (http://www.opensource.org/licenses/mit-license.php) 27 | // 28 | // Copyright (c) 2023 by Roman Piksaykin 29 | // 30 | // Permission is hereby granted, free of charge,to any person obtaining a copy 31 | // of this software and associated documentation files (the Software), to deal 32 | // in the Software without restriction,including without limitation the rights 33 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 34 | // copies of the Software, and to permit persons to whom the Software is 35 | // furnished to do so, subject to the following conditions: 36 | // 37 | // The above copyright notice and this permission notice shall be included in 38 | // all copies or substantial portions of the Software. 39 | // 40 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 41 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 42 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 43 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 44 | // LIABILITY,WHETHER IN AN ACTION OF CONTRACT,TORT OR OTHERWISE, ARISING FROM, 45 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 46 | // THE SOFTWARE. 47 | /////////////////////////////////////////////////////////////////////////////// 48 | #include 49 | 50 | #include 51 | #include 52 | #include 53 | #include "ISR.h" 54 | 55 | #include 56 | #include 57 | 58 | int main() 59 | { 60 | ui_context *pUI = InitUI(); 61 | 62 | screen_control_t *pScrCtl = &pUI->mScreenCtl; 63 | touch_control_t *pTouchCtl= &pUI->mTouchCtl; 64 | 65 | ili9341_config_t ili9341_hw_config; 66 | pScrCtl->mpHWConfig = &ili9341_hw_config; 67 | ILI9341_Init(pScrCtl->mpHWConfig, spi0, 90 * MHz, 4, 5, 6, 7, 8, 9); 68 | 69 | TftClearScreenBuffer(pScrCtl, kBlack, kYellow); 70 | TftSetCursor(pScrCtl, 0, 20); 71 | 72 | touch_hwconfig_t touch_hwc; 73 | TouchInitHW(&touch_hwc, spi1, 1 * MHz, 12, 13, 10, 11, 15); 74 | TouchInitCtl(pTouchCtl, &touch_hwc, 1000, 50000, 5); 75 | 76 | /* Set reference points of the screen as its corners. */ 77 | const int16_t refpoints[] = 78 | { 79 | 0, 0, 80 | 240, 0, 81 | 0, 320, 82 | 240, 320 83 | }; 84 | /* Set sampled points of the screen as outputs of touchscreen when 85 | reference points had been pressed. 86 | Admittedly there should be a calibration procedure in your project 87 | in order to get these points asking user to click a number of points 88 | of the screen. */ 89 | const int16_t smplpoints[] = 90 | { 91 | 10, 120, // 0, 0. 92 | 119, 119, // 240, 0. 93 | 9, 11, // .. 94 | 118, 12 // .. 95 | }; 96 | /* Calculate transformation matrix using a number of reference points 97 | and sampled ones. */ 98 | CalculateCalibrationMat(refpoints, smplpoints, 4, &pUI->mTouchCalMat); 99 | 100 | gpio_init(PICO_DEFAULT_LED_PIN); 101 | gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT); 102 | 103 | InitISR(); 104 | 105 | for(int tick = 0;;++tick) 106 | { 107 | tight_loop_contents(); 108 | 109 | { 110 | static uint64_t sLastTm = 0; 111 | const uint64_t ktm64_now = GetTime(); 112 | 113 | /* Prevent flicker. */ 114 | if(ktm64_now - 20000L < sLastTm) 115 | { 116 | continue; 117 | } 118 | sLastTm = ktm64_now; 119 | 120 | frame *pfActive = GetActiveFrame(pUI); 121 | static frame *spfActiveM1 = NULL; 122 | if(!pfActive) 123 | { 124 | continue; 125 | } 126 | 127 | if(pfActive != spfActiveM1) 128 | { 129 | pfActive->mpfEventProc(pfActive, kEventDraw, 0, 0, pUI); 130 | spfActiveM1 = pfActive; 131 | continue; 132 | } 133 | spfActiveM1 = pfActive; 134 | 135 | if(pUI->mLastReleaseTm > pUI->mLastTouchTm) 136 | if(pfActive->mpfEventProc) 137 | { 138 | IsInsideRect(&pfActive->mRegion, pUI->mLastX, pUI->mLastY) 139 | ? pfActive->mpfEventProc(pfActive, kEventClickInside, pUI->mLastX, pUI->mLastY, pUI) 140 | : pfActive->mpfEventProc(pfActive, kEventClickOutside, pUI->mLastX, pUI->mLastY, pUI); 141 | } 142 | pUI->mLastTouchTm = ktm64_now; 143 | } 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /ui/ui_context.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Roman Piksaykin [piksaykin@gmail.com], R2BDY 4 | // https://www.qrz.com/db/r2bdy 5 | // 6 | /////////////////////////////////////////////////////////////////////////////// 7 | // 8 | // 9 | // ui_context.h - User interface context structure. 10 | // 11 | // 12 | // DESCRIPTION 13 | // 14 | // Structure which integrates all necessary control structures to operate. 15 | // 16 | // PLATFORM 17 | // Hardware: Raspberry Pi Pico. 18 | // Software: https://github.com/RPiks/pico-touchscr-sdk 19 | // 20 | // REVISION HISTORY 21 | // 22 | // Rev 0.5 23 Feb 2023 23 | // Initial release. 24 | // 25 | // LICENCE 26 | // MIT License (http://www.opensource.org/licenses/mit-license.php) 27 | // 28 | // Copyright (c) 2023 by Roman Piksaykin 29 | // 30 | // Permission is hereby granted, free of charge,to any person obtaining a copy 31 | // of this software and associated documentation files (the Software), to deal 32 | // in the Software without restriction,including without limitation the rights 33 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 34 | // copies of the Software, and to permit persons to whom the Software is 35 | // furnished to do so, subject to the following conditions: 36 | // 37 | // The above copyright notice and this permission notice shall be included in 38 | // all copies or substantial portions of the Software. 39 | // 40 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 41 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 42 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 43 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 44 | // LIABILITY,WHETHER IN AN ACTION OF CONTRACT,TORT OR OTHERWISE, ARISING FROM, 45 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 46 | // THE SOFTWARE. 47 | /////////////////////////////////////////////////////////////////////////////// 48 | #ifndef UI_CONTEXT_H_ 49 | #define UI_CONTEXT_H_ 50 | 51 | #include 52 | #include 53 | #include 54 | 55 | #define MAX_UI_DEPTH 8 56 | 57 | typedef struct 58 | { 59 | const frame* mpFrameStack[MAX_UI_DEPTH]; 60 | uint8_t mFrameActiveIX; 61 | 62 | screen_control_t mScreenCtl; 63 | touch_control_t mTouchCtl; 64 | calibration_mat_t mTouchCalMat; 65 | 66 | int32_t mLastX, mLastY; 67 | volatile uint64_t mLastTouchTm; 68 | volatile uint64_t mLastReleaseTm; 69 | 70 | } ui_context; 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /ui/ui_init.c: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Roman Piksaykin [piksaykin@gmail.com], R2BDY 4 | // https://www.qrz.com/db/r2bdy 5 | // 6 | /////////////////////////////////////////////////////////////////////////////// 7 | // 8 | // 9 | // ui_init.c - User interface initialization. 10 | // 11 | // 12 | // DESCRIPTION 13 | // 14 | // Implements functions of pico-widgets init. This is an example of UI. 15 | // 16 | // PLATFORM 17 | // Hardware: Raspberry Pi Pico. 18 | // Software: https://github.com/RPiks/pico-touchscr-sdk 19 | // 20 | // REVISION HISTORY 21 | // 22 | // Rev 0.5 24 Feb 2023 23 | // Initial release. 24 | // 25 | // LICENCE 26 | // MIT License (http://www.opensource.org/licenses/mit-license.php) 27 | // 28 | // Copyright (c) 2023 by Roman Piksaykin 29 | // 30 | // Permission is hereby granted, free of charge,to any person obtaining a copy 31 | // of this software and associated documentation files (the Software), to deal 32 | // in the Software without restriction,including without limitation the rights 33 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 34 | // copies of the Software, and to permit persons to whom the Software is 35 | // furnished to do so, subject to the following conditions: 36 | // 37 | // The above copyright notice and this permission notice shall be included in 38 | // all copies or substantial portions of the Software. 39 | // 40 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 41 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 42 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 43 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 44 | // LIABILITY,WHETHER IN AN ACTION OF CONTRACT,TORT OR OTHERWISE, ARISING FROM, 45 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 46 | // THE SOFTWARE. 47 | /////////////////////////////////////////////////////////////////////////////// 48 | #ifndef UI_STRUCTURE_H_ 49 | #define UI_STRUCTURE_H_ 50 | 51 | #include 52 | #include "ui_context.h" 53 | #include "ui_protos.h" 54 | 55 | static ui_context sUIcontext = {0}; 56 | 57 | static const frame skUI[] = 58 | { 59 | { kFrameRoot, "root", {0, 0, TEXT_WIDTH, TEXT_HEIGHT}, kBlack, kWhite, NULL, NULL }, // [0] 60 | { kFrameBBox, "TopBar", {0, 0, 240, 16}, kRed, kWhite, TopBarEventProc, NULL }, // [1] 61 | { kFrameBBox, "Settings", {32, 32, 64, 72}, kBlue, kCyan, SettingsEventProc, NULL }, // [2] 62 | { kFrameBBox, "APRS", {32, 32, 0, 72}, kBlue, kCyan, APRSEventProc, NULL }, // [3] 63 | { kFrameBBox, "PSK", {32, 32, 0, 72}, kBlue, kCyan, PSKEventProc, NULL }, // [4] 64 | { kFrameBBox, "Phone", {32, 32, 0, 72}, kBlue, kCyan, PhoneEventProc, NULL }, // [5] 65 | { kFrameBBox, "Callsign", {32, 32, 0, 72}, kBlue, kYellow, CallsignEventProc, NULL }, // [6] 66 | { kFrameBBox, "Calibration", {32, 32, 0, 72}, kBlue, kYellow, CalibrationEventProc, NULL }, // [7] 67 | { kFrameBBox, "Terminal", {0, 32, 240, 320-32}, kBlack, kGreen, TerminalEventProc, NULL }, // [8] 68 | }; 69 | 70 | /// @brief Inits UI - pushes a pair of standard frames onto the UI stack. 71 | /// @return UI context, updated. 72 | ui_context* InitUI(void) 73 | { 74 | PushStdFrame(&sUIcontext, 0); 75 | PushStdFrame(&sUIcontext, 1); 76 | 77 | return &sUIcontext; 78 | } 79 | 80 | /// @brief Obtains the ongoing UI context. 81 | /// @return UI context. 82 | ui_context* GetUIContext(void) 83 | { 84 | return &sUIcontext; 85 | } 86 | 87 | /// @brief Pushes a standard frame onto the UI stack. 88 | /// @param pcntx The UI context. 89 | /// @param ix Index of the library (ROM) frame. 90 | void PushStdFrame(ui_context *pcntx, int ix) 91 | { 92 | ASSERT(pcntx); 93 | pcntx->mpFrameStack[pcntx->mFrameActiveIX++] = &skUI[ix]; 94 | } 95 | 96 | /// @brief Gets a ptr to nth UI item of hardcoded library (ROM). 97 | /// @param n Index of the item. 98 | /// @return Ptr to the frame. 99 | const frame* GetUIItem(int n) 100 | { 101 | return &skUI[n]; 102 | } 103 | 104 | #endif 105 | -------------------------------------------------------------------------------- /ui/ui_manage.c: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Roman Piksaykin [piksaykin@gmail.com], R2BDY 4 | // https://www.qrz.com/db/r2bdy 5 | // 6 | /////////////////////////////////////////////////////////////////////////////// 7 | // 8 | // 9 | // ui_manage.c - User interface service functions. 10 | // 11 | // 12 | // DESCRIPTION 13 | // 14 | // Implements functions of UI. 15 | // 16 | // PLATFORM 17 | // Hardware: Raspberry Pi Pico. 18 | // Software: https://github.com/RPiks/pico-touchscr-sdk 19 | // 20 | // REVISION HISTORY 21 | // 22 | // Rev 0.5 24 Feb 2023 23 | // Initial release. 24 | // 25 | // LICENCE 26 | // MIT License (http://www.opensource.org/licenses/mit-license.php) 27 | // 28 | // Copyright (c) 2023 by Roman Piksaykin 29 | // 30 | // Permission is hereby granted, free of charge,to any person obtaining a copy 31 | // of this software and associated documentation files (the Software), to deal 32 | // in the Software without restriction,including without limitation the rights 33 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 34 | // copies of the Software, and to permit persons to whom the Software is 35 | // furnished to do so, subject to the following conditions: 36 | // 37 | // The above copyright notice and this permission notice shall be included in 38 | // all copies or substantial portions of the Software. 39 | // 40 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 41 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 42 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 43 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 44 | // LIABILITY,WHETHER IN AN ACTION OF CONTRACT,TORT OR OTHERWISE, ARISING FROM, 45 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 46 | // THE SOFTWARE. 47 | /////////////////////////////////////////////////////////////////////////////// 48 | #ifndef UI_MANAGE_H_ 49 | #define UI_MANAGE_H_ 50 | 51 | #include 52 | #include "ui_context.h" 53 | #include "ui_protos.h" 54 | #include 55 | #include 56 | 57 | #include 58 | 59 | void PopFrame(ui_context* pcntx) 60 | { 61 | ASSERT(pcntx); 62 | ASSERT(pcntx->mFrameActiveIX); 63 | --pcntx->mFrameActiveIX; 64 | } 65 | 66 | void PushCustomFrame(ui_context *pcntx, frame *pframe) 67 | { 68 | ASSERT(pcntx); 69 | pcntx->mpFrameStack[pcntx->mFrameActiveIX++] = pframe; 70 | } 71 | 72 | frame *GetActiveFrame(ui_context *pcntx) 73 | { 74 | ASSERT(pcntx); 75 | if(0 == pcntx->mFrameActiveIX) 76 | { 77 | return NULL; 78 | } 79 | return (frame *)pcntx->mpFrameStack[pcntx->mFrameActiveIX - 1]; 80 | } 81 | 82 | void DrawFrame(ui_context *pcntx, frame *pkframe) 83 | { 84 | ASSERT(pkframe); 85 | 86 | switch(pkframe->mFrameType) 87 | { 88 | case kFrameRoot: 89 | //TftClearScreenBuffer() 90 | break; 91 | 92 | case kFrameBBox: 93 | pkframe->mpfEventProc(pkframe, kEventDraw, 0, 0, pcntx); 94 | break; 95 | 96 | default: 97 | break; 98 | }; 99 | } 100 | 101 | /// @brief Measures a current time. 102 | /// @return A count of 1 us ticks from start. 103 | uint64_t GetTime(void) 104 | { 105 | const uint32_t ktlo = timer_hw->timelr; 106 | const uint32_t kthi = timer_hw->timehr; 107 | 108 | return ((uint64_t)kthi << 32) | ktlo; 109 | } 110 | 111 | void UItick(ui_context *pcntx) 112 | { 113 | ASSERT(pcntx); 114 | 115 | //static uint64_t sLastTm = 0; 116 | //const uint64_t ktm64_now = GetTime(); 117 | 118 | /* Check whether enough time has passed. */ 119 | //if(ktm64_now - sleep_interval < sLastTm) 120 | //{ 121 | // return; 122 | //} 123 | //sLastTm = ktm64_now; 124 | 125 | const bool kbnew_touch = GetTouchData(pcntx, &pcntx->mLastX, 126 | &pcntx->mLastY); 127 | if(kbnew_touch) 128 | { 129 | pcntx->mLastTouchTm = GetTime(); 130 | } 131 | 132 | TftFullScreenSelectiveWrite(&pcntx->mScreenCtl, 8); 133 | } 134 | 135 | /// @brief Gets data from touchscreen device. 136 | /// @param puic UI context. 137 | /// @param x X coord of the touch point, if pressed. 138 | /// @param y Y coord of the touch point, if pressed. 139 | /// @return Whether the screen is pressed and {x,y} are valid. 140 | bool GetTouchData(ui_context *puic, int32_t *x, int32_t *y) 141 | { 142 | ASSERT(puic); 143 | 144 | const int res = CheckTouch(&puic->mTouchCtl); 145 | if(0 == res) 146 | { 147 | *x = (puic->mTouchCtl.mXf + 8) >> 4; 148 | *y = (puic->mTouchCtl.mYf + 8) >> 4; 149 | 150 | TouchTransformCoords(&puic->mTouchCalMat, x, y); 151 | 152 | puic->mLastReleaseTm = 0; 153 | 154 | return true; 155 | } 156 | else if(1 == res && !puic->mLastReleaseTm) 157 | { 158 | puic->mLastReleaseTm = GetTime(); 159 | } 160 | 161 | return false; 162 | } 163 | 164 | /// @brief Check if {x,y} `graph mode` are inside rectange. 165 | /// @param rct The rectangle. 166 | /// @param x X coord. 167 | /// @param y Y coord. 168 | /// @return True if is inside. 169 | bool IsInsideRect(const frame_rect *rct, int32_t x, int32_t y) 170 | { 171 | if((x < rct->mTlx) 172 | || (y < rct->mTly) 173 | || (x > rct->mTlx + rct->mWidth) 174 | || (y > rct->mTly + rct->mHeight)) 175 | { 176 | return false; 177 | } 178 | 179 | return true; 180 | } 181 | 182 | #endif 183 | -------------------------------------------------------------------------------- /ui/ui_protos.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Roman Piksaykin [piksaykin@gmail.com], R2BDY 4 | // https://www.qrz.com/db/r2bdy 5 | // 6 | /////////////////////////////////////////////////////////////////////////////// 7 | // 8 | // 9 | // ui_protos.h - User interface functions prototypes. 10 | // 11 | // 12 | // DESCRIPTION 13 | // 14 | // Declares functions which do events processing. 15 | // 16 | // PLATFORM 17 | // Hardware: Raspberry Pi Pico. 18 | // Software: https://github.com/RPiks/pico-touchscr-sdk 19 | // 20 | // REVISION HISTORY 21 | // 22 | // Rev 0.5 24 Feb 2023 23 | // Initial release. 24 | // 25 | // LICENCE 26 | // MIT License (http://www.opensource.org/licenses/mit-license.php) 27 | // 28 | // Copyright (c) 2023 by Roman Piksaykin 29 | // 30 | // Permission is hereby granted, free of charge,to any person obtaining a copy 31 | // of this software and associated documentation files (the Software), to deal 32 | // in the Software without restriction,including without limitation the rights 33 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 34 | // copies of the Software, and to permit persons to whom the Software is 35 | // furnished to do so, subject to the following conditions: 36 | // 37 | // The above copyright notice and this permission notice shall be included in 38 | // all copies or substantial portions of the Software. 39 | // 40 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 41 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 42 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 43 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 44 | // LIABILITY,WHETHER IN AN ACTION OF CONTRACT,TORT OR OTHERWISE, ARISING FROM, 45 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 46 | // THE SOFTWARE. 47 | /////////////////////////////////////////////////////////////////////////////// 48 | #ifndef UI_PROTOS_H_ 49 | #define UI_PROTOS_H_ 50 | 51 | #include 52 | #include "ui_context.h" 53 | 54 | ui_context* InitUI(void); 55 | ui_context* GetUIContext(void); 56 | const frame* GetUIItem(int n); 57 | void PushStdFrame(ui_context *pcntx, int ix); 58 | void PushCustomFrame(ui_context *pcntx, frame *pframe); 59 | void PopFrame(ui_context* pcntx); 60 | frame *GetActiveFrame(ui_context *pcntx); 61 | void UItick(ui_context *pcntx); 62 | bool GetTouchData(ui_context *puic, int32_t *x, int32_t *y); 63 | bool IsInsideRect(const frame_rect *rct, int32_t x, int32_t y); 64 | uint64_t GetTime(void); 65 | 66 | int TopBarEventProc(frame *pF, frame_event fE, int x, int y, void *pctx); 67 | int SettingsEventProc(frame *pF, frame_event fE, int x, int y, void *pctx); 68 | int APRSEventProc(frame *pF, frame_event fE, int x, int y, void *pctx); 69 | int PSKEventProc(frame *pF, frame_event fE, int x, int y, void *pctx); 70 | int PhoneEventProc(frame *pF, frame_event fE, int x, int y, void *pctx); 71 | int CallsignEventProc(frame *pF, frame_event fE, int x, int y, void *pctx); 72 | int CalibrationEventProc(frame *pF, frame_event fE, int x, int y, void *pctx); 73 | int TerminalEventProc(frame *pF, frame_event fE, int x, int y, void *pctx); 74 | 75 | #endif 76 | -------------------------------------------------------------------------------- /widgets/APRSEventProc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int APRSEventProc(frame *pF, frame_event fE, int x, int y, void *pctx) 5 | { 6 | 7 | } -------------------------------------------------------------------------------- /widgets/CalibrationEventProc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int CalibrationEventProc(frame *pF, frame_event fE, int x, int y, void *pctx) 5 | { 6 | 7 | } -------------------------------------------------------------------------------- /widgets/CallsignEventProc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int CallsignEventProc(frame *pF, frame_event fE, int x, int y, void *pctx) 5 | { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /widgets/PSKEventProc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int PSKEventProc(frame *pF, frame_event fE, int x, int y, void *pctx) 5 | { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /widgets/PhoneEventProc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int PhoneEventProc(frame *pF, frame_event fE, int x, int y, void *pctx) 5 | { 6 | 7 | } -------------------------------------------------------------------------------- /widgets/SettingsEventProc.c: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Roman Piksaykin [piksaykin@gmail.com], R2BDY 4 | // https://www.qrz.com/db/r2bdy 5 | // 6 | /////////////////////////////////////////////////////////////////////////////// 7 | // 8 | // 9 | // SettingsEventProc.c - Settings widget functions. 10 | // 11 | // 12 | // DESCRIPTION 13 | // 14 | // Implements the basic `list of options` widget of pico-widgets UI library. 15 | // 16 | // PLATFORM 17 | // Hardware: Raspberry Pi Pico. 18 | // Software: https://github.com/RPiks/pico-touchscr-sdk 19 | // 20 | // REVISION HISTORY 21 | // 22 | // Rev 0.5 25 Feb 2023 23 | // Initial release. 24 | // 25 | // LICENCE 26 | // MIT License (http://www.opensource.org/licenses/mit-license.php) 27 | // 28 | // Copyright (c) 2023 by Roman Piksaykin 29 | // 30 | // Permission is hereby granted, free of charge,to any person obtaining a copy 31 | // of this software and associated documentation files (the Software), to deal 32 | // in the Software without restriction,including without limitation the rights 33 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 34 | // copies of the Software, and to permit persons to whom the Software is 35 | // furnished to do so, subject to the following conditions: 36 | // 37 | // The above copyright notice and this permission notice shall be included in 38 | // all copies or substantial portions of the Software. 39 | // 40 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 41 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 42 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 43 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 44 | // LIABILITY,WHETHER IN AN ACTION OF CONTRACT,TORT OR OTHERWISE, ARISING FROM, 45 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 46 | // THE SOFTWARE. 47 | /////////////////////////////////////////////////////////////////////////////// 48 | #include 49 | #include 50 | #include 51 | #include "widgets_utility.h" 52 | 53 | #include 54 | 55 | static frame_rect sSettingsListActivationRect[2] = {0}; 56 | 57 | void SettingsListDraw(frame *pF, ui_context *pctx); 58 | void SettingsListClickInside(frame *pF, int x, int y, ui_context *pctx); 59 | 60 | /// @brief Event procssor of the Settings widget. 61 | /// @param pF The widget. 62 | /// @param fE Incoming event type. 63 | /// @param x Touch X coord. 64 | /// @param y Touch Y coord. 65 | /// @param pctx User interface context. 66 | /// @return 0. 67 | int SettingsEventProc(frame *pF, frame_event fE, int x, int y, void *pctx) 68 | { 69 | ASSERT(pF); 70 | ASSERT(pctx); 71 | 72 | ui_context *pui = pctx; 73 | 74 | switch (fE) 75 | { 76 | case kEventDraw: 77 | SettingsListDraw(pF, pctx); 78 | break; 79 | 80 | case kEventClickInside: 81 | gpio_put(PICO_DEFAULT_LED_PIN, 1); 82 | SettingsListClickInside(pF, x, y, pui); 83 | break; 84 | 85 | case kEventClickOutside: 86 | PopFrame(pctx); 87 | ClearWidgetBBox(pF, &pui->mScreenCtl); 88 | gpio_put(PICO_DEFAULT_LED_PIN, 0); 89 | break; 90 | 91 | case kEventClose: 92 | break; 93 | 94 | case kEventPing: 95 | break; 96 | 97 | case kEventTick: 98 | break; 99 | 100 | default: 101 | break; 102 | } 103 | 104 | return 0; 105 | } 106 | 107 | /// @brief Draws the widget. 108 | /// @param pF The widget. 109 | /// @param pctx UI context. 110 | void SettingsListDraw(frame *pF, ui_context *pctx) 111 | { 112 | DrawBBox(&pctx->mScreenCtl, &pF->mRegion, 0); 113 | //DebugPrintf("SettingsListDraw\n"); 114 | } 115 | 116 | /// @brief Defines what to do when click inside the widget. 117 | /// @param pF The widget. 118 | /// @param x Click X coord. 119 | /// @param y Click Y coord. 120 | /// @param pctx User interface context. 121 | void SettingsListClickInside(frame *pF, int x, int y, ui_context *pctx) 122 | { 123 | DebugPrintf("SettingsList - ClickInside!\n"); 124 | } 125 | -------------------------------------------------------------------------------- /widgets/TerminalEventProc.c: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Roman Piksaykin [piksaykin@gmail.com], R2BDY 4 | // https://www.qrz.com/db/r2bdy 5 | // 6 | /////////////////////////////////////////////////////////////////////////////// 7 | // 8 | // 9 | // TerminalEventProc.c - Terminal widget functions. 10 | // 11 | // 12 | // DESCRIPTION 13 | // 14 | // Implements the Terminal widget of pico-widgets UI library. 15 | // The widget is a combo of rather basic stylus-activated keyboard & text 16 | // window. It requires scarce RAM due to the fact that keyboard is hard-coded 17 | // in order to use with 240x320 TFT screen via pico-touchscr-sdk. 18 | // 19 | // PLATFORM 20 | // Hardware: Raspberry Pi Pico. 21 | // Software: https://github.com/RPiks/pico-touchscr-sdk 22 | // 23 | // REVISION HISTORY 24 | // 25 | // Rev 0.5 25 Feb 2023 26 | // Initial release. 27 | // 28 | // LICENCE 29 | // MIT License (http://www.opensource.org/licenses/mit-license.php) 30 | // 31 | // Copyright (c) 2023 by Roman Piksaykin 32 | // 33 | // Permission is hereby granted, free of charge,to any person obtaining a copy 34 | // of this software and associated documentation files (the Software), to deal 35 | // in the Software without restriction,including without limitation the rights 36 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 37 | // copies of the Software, and to permit persons to whom the Software is 38 | // furnished to do so, subject to the following conditions: 39 | // 40 | // The above copyright notice and this permission notice shall be included in 41 | // all copies or substantial portions of the Software. 42 | // 43 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 44 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 45 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 46 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 47 | // LIABILITY,WHETHER IN AN ACTION OF CONTRACT,TORT OR OTHERWISE, ARISING FROM, 48 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 49 | // THE SOFTWARE. 50 | /////////////////////////////////////////////////////////////////////////////// 51 | #include 52 | #include 53 | #include 54 | #include "widgets_utility.h" 55 | 56 | #include 57 | 58 | typedef struct 59 | { 60 | uint16_t x; 61 | uint16_t y; 62 | } point2d_t; 63 | 64 | /// @brief Widget's context. 65 | typedef struct 66 | { 67 | uint8_t flags; 68 | uint64_t tm_last; 69 | } terminal_context_t; 70 | 71 | static const int8_t skCrook[][2] = { {1, -1}, {1, 2}, {2, -2}, {2, 3}, {2, -1}, {2, 2} 72 | }; 73 | 74 | static const uint8_t skKeys[][4] = { {2, 0, 18, 16}, {22, 0, 38, 16}, {42, 0, 58, 16}, {62, 0, 78, 16}, 75 | {82, 0, 98, 16}, {102, 0, 118, 16}, {122, 0, 138, 16}, {142, 0, 158, 16}, 76 | {162, 0, 178, 16}, {182, 0, 198, 16}, {202, 0, 218, 16}, {222, 0, 238, 16}, 77 | {2, 20, 18, 36}, {22, 20, 38, 36}, {42, 20, 58, 36}, {62, 20, 78, 36}, 78 | {82, 20, 98, 36}, {102, 20, 118, 36}, {122, 20, 138, 36}, {142, 20, 158, 36}, 79 | {162, 20, 178, 36}, {182, 20, 198, 36}, {2, 40, 18, 56}, 80 | {22, 40, 38, 56}, {42, 40, 58, 56}, {62, 40, 78, 56}, {82, 40, 98, 56}, 81 | {102, 40, 118, 56}, {122, 40, 138, 56}, {142, 40, 158, 56}, {162, 40, 178, 56}, 82 | {182, 40, 198, 56}, {202, 40, 218, 56}, {2, 60, 18, 76}, {22, 60, 38, 76}, 83 | {42, 60, 58, 76}, {62, 60, 78, 76}, {82, 60, 98, 76}, {102, 60, 118, 76}, 84 | {122, 60, 138, 76}, {142, 60, 158, 76}, {162, 60, 178, 76}, {182, 60, 198, 76}, 85 | {202, 60, 218, 76}, 86 | 87 | {202, 20, 238, 36}, // BAK 88 | {222, 40, 238, 76}, // Enter 89 | {62, 80, 178, 98} // Space 90 | }; 91 | 92 | static const char skKeysCap[] = "1234567890-+QWERTYUIOPASDFGHJKL:\"^ZXCVBNM,./\x08\x0d "; 93 | static const char skKeysLow[] = "1234567890-+qwertyuiopasdfghjkl:\"^zxcvbnm,./\x08\x0d "; 94 | 95 | void KeyboardDraw(frame *pkbd, screen_control_t *pscr, 96 | color_t paper, color_t ink, int mode); 97 | int LocateKeyTouch(int x, int y); 98 | void Key16x16Draw(screen_control_t *pscr, point2d_t tl); 99 | void BrickDraw(screen_control_t *pscr, point2d_t tl, point2d_t br, int over); 100 | 101 | /// @brief Event procssor of the Terminal widget. 102 | /// @param pF The widget. 103 | /// @param fE Incoming event type. 104 | /// @param x Touch X coord. 105 | /// @param y Touch Y coord. 106 | /// @param pctx User interface context. 107 | /// @return 0. 108 | int TerminalEventProc(frame *pF, frame_event fE, int x, int y, void *pctx) 109 | { 110 | ASSERT(pF); 111 | ASSERT(pctx); 112 | 113 | static terminal_context_t sTermCtx = { 0 }; 114 | 115 | ui_context *pui = pctx; 116 | 117 | switch (fE) 118 | { 119 | case kEventDraw: 120 | KeyboardDraw(pF, &pui->mScreenCtl, 0, 4, sTermCtx.flags&1); 121 | break; 122 | 123 | case kEventClickInside: 124 | { 125 | const int i = LocateKeyTouch(x, y); 126 | if(-1 == i) 127 | { 128 | break; 129 | } 130 | 131 | const uint64_t tm_press = GetTime(); 132 | if(tm_press - sTermCtx.tm_last < 200000L) 133 | { 134 | break; 135 | } 136 | 137 | sTermCtx.tm_last = tm_press; 138 | 139 | if('^' == skKeysCap[i]) 140 | { 141 | sTermCtx.flags ^= 0b1; 142 | KeyboardDraw(pF, &pui->mScreenCtl, 0, 4, sTermCtx.flags&1); 143 | } 144 | else 145 | { 146 | DebugPrintf("%c", (sTermCtx.flags&1) ? skKeysCap[i] : skKeysLow[i]); 147 | } 148 | 149 | gpio_put(PICO_DEFAULT_LED_PIN, 1); 150 | } 151 | break; 152 | 153 | case kEventClickOutside: 154 | pF->mpPayLoad = NULL; 155 | PopFrame(pctx); 156 | ClearWidgetBBox(pF, &pui->mScreenCtl); 157 | gpio_put(PICO_DEFAULT_LED_PIN, 0); 158 | break; 159 | 160 | case kEventClose: 161 | break; 162 | 163 | case kEventPing: 164 | break; 165 | 166 | case kEventTick: 167 | break; 168 | 169 | default: 170 | break; 171 | } 172 | 173 | return 0; 174 | } 175 | 176 | /// @brief Draws a keyboard. 177 | /// @param pkbd The widget. 178 | /// @param pscr Screen control structure. 179 | /// @param paper Paper color (background). 180 | /// @param ink Ink color (foreground). 181 | /// @param mode Defines which symbol set to display: 182 | /// @param mode mode=1 - capital letters, 0 - lowcase. 183 | void KeyboardDraw(frame *pkbd, screen_control_t *pscr, 184 | color_t paper, color_t ink, int mode) 185 | { 186 | ASSERT(pkbd); 187 | 188 | for(int j = 27; j < 40; ++j) 189 | for(int i = 0; i < 30; ++i) 190 | { 191 | TftPutColorAttr(pscr, i, j, paper, ink); 192 | } 193 | 194 | for(int i = 0; i < _countof(skKeys); ++i) 195 | { 196 | point2d_t pt0 = { skKeys[i][0], 220 + skKeys[i][1] }; 197 | point2d_t pt1 = { skKeys[i][2], 220 + skKeys[i][3] }; 198 | BrickDraw(pscr, pt0, pt1, 1); 199 | 200 | char buf[2]; 201 | buf[0] = mode ? skKeysCap[i] : skKeysLow[i]; 202 | buf[1] = 0x00; 203 | TftPutTextLabel(pscr, buf, pt0.x + 4, pt0.y + 5, 0); 204 | } 205 | 206 | { // Backspace 207 | point2d_t pt0 = { skKeys[_countof(skKeys)-3][0], 208 | 220 + skKeys[_countof(skKeys)-3][1] }; 209 | TftPutTextLabel(pscr, "BSP", pt0.x + 4, pt0.y + 5, 0); 210 | } 211 | 212 | { // Enter 213 | point2d_t pt0 = { 227, 290 }; 214 | point2d_t pt1 = { 235, 292 }; 215 | BrickDraw(pscr, pt0, pt1, 0); 216 | for(int i = 0; i < 6; ++i) 217 | { 218 | CLR_DATA_BIT(pscr->mpPixBuffer, pt0.x + skCrook[i][0] 219 | + (pt0.y + skCrook[i][1]) * PIX_WIDTH); 220 | } 221 | 222 | pt0 = pt1; 223 | pt0.x -= 2; pt0.y -= 22; 224 | BrickDraw(pscr, pt0, pt1, 0); 225 | } 226 | 227 | return; 228 | } 229 | 230 | /// @brief Draws a common key as filled rectangle. 231 | /// @param pscr Screen control sutucture. 232 | /// @param tl Top-left point of the key (rect). 233 | /// @param br Bot-right point of the key (rect). 234 | /// @param over 1-positive drawing, 0-negative. 235 | void BrickDraw(screen_control_t *pscr, point2d_t tl, point2d_t br, int over) 236 | { 237 | for(int j = tl.y; j < br.y; ++j) 238 | { 239 | const int bitline = PIX_WIDTH * j; 240 | for(int i = tl.x; i < br.x; ++i) 241 | { 242 | if(over) 243 | { 244 | SET_DATA_BIT(pscr->mpPixBuffer, i + bitline); 245 | } 246 | else 247 | { 248 | CLR_DATA_BIT(pscr->mpPixBuffer, i + bitline); 249 | } 250 | } 251 | } 252 | } 253 | 254 | /// @brief Touch coords to key index converter. 255 | /// @param x X coord of the touch. 256 | /// @param y Y coord of the touch. 257 | /// @return Index of key has been located. -1 if no. 258 | int LocateKeyTouch(int x, int y) 259 | { 260 | for(int i = 0; i < _countof(skKeys); ++i) 261 | { 262 | const frame_rect rct = 263 | { 264 | skKeys[i][0], 265 | 220 + skKeys[i][1], 266 | skKeys[i][2] - skKeys[i][0], 267 | skKeys[i][3] - skKeys[i][1] 268 | }; 269 | 270 | if(IsInsideRect(&rct, x, y)) 271 | { 272 | return i; 273 | } 274 | } 275 | 276 | return -1; 277 | } 278 | -------------------------------------------------------------------------------- /widgets/TopBarEventProc.c: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Roman Piksaykin [piksaykin@gmail.com], R2BDY 4 | // https://www.qrz.com/db/r2bdy 5 | // 6 | /////////////////////////////////////////////////////////////////////////////// 7 | // 8 | // 9 | // TopBarEventProc.c - Top Bar widget functions. 10 | // 11 | // 12 | // DESCRIPTION 13 | // 14 | // Implements the Top Bar widget of pico-widgets UI library. 15 | // 16 | // PLATFORM 17 | // Hardware: Raspberry Pi Pico. 18 | // Software: https://github.com/RPiks/pico-touchscr-sdk 19 | // 20 | // REVISION HISTORY 21 | // 22 | // Rev 0.5 25 Feb 2023 23 | // Initial release. 24 | // 25 | // LICENCE 26 | // MIT License (http://www.opensource.org/licenses/mit-license.php) 27 | // 28 | // Copyright (c) 2023 by Roman Piksaykin 29 | // 30 | // Permission is hereby granted, free of charge,to any person obtaining a copy 31 | // of this software and associated documentation files (the Software), to deal 32 | // in the Software without restriction,including without limitation the rights 33 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 34 | // copies of the Software, and to permit persons to whom the Software is 35 | // furnished to do so, subject to the following conditions: 36 | // 37 | // The above copyright notice and this permission notice shall be included in 38 | // all copies or substantial portions of the Software. 39 | // 40 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 41 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 42 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 43 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 44 | // LIABILITY,WHETHER IN AN ACTION OF CONTRACT,TORT OR OTHERWISE, ARISING FROM, 45 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 46 | // THE SOFTWARE. 47 | /////////////////////////////////////////////////////////////////////////////// 48 | #include 49 | #include 50 | #include 51 | #include "widgets_utility.h" 52 | 53 | #include 54 | 55 | static frame_rect sTopBarActivationRect[4] = {0}; 56 | 57 | void TopBarDraw(frame *pF, ui_context *pctx); 58 | void TopBarClickInside(frame *pF, int x, int y, ui_context *pctx); 59 | 60 | /// @brief Event procssor of the Top Bar widget. 61 | /// @param pF The widget. 62 | /// @param fE Incoming event type. 63 | /// @param x Touch X coord. 64 | /// @param y Touch Y coord. 65 | /// @param pctx User interface context. 66 | /// @return 0. 67 | int TopBarEventProc(frame *pF, frame_event fE, int x, int y, void *pctx) 68 | { 69 | ASSERT(pF); 70 | ASSERT(pctx); 71 | 72 | ui_context *pui = (ui_context *)pctx; 73 | 74 | switch (fE) 75 | { 76 | case kEventDraw: 77 | TopBarDraw(pF, pui); 78 | break; 79 | 80 | case kEventClickInside: 81 | gpio_put(PICO_DEFAULT_LED_PIN, 1); 82 | TopBarClickInside(pF, x, y, pui); 83 | break; 84 | 85 | case kEventClickOutside: 86 | // No reaction: this is persistent widget. 87 | gpio_put(PICO_DEFAULT_LED_PIN, 0); 88 | break; 89 | 90 | case kEventClose: 91 | break; 92 | 93 | case kEventPing: 94 | break; 95 | 96 | case kEventTick: 97 | break; 98 | 99 | default: 100 | break; 101 | } 102 | 103 | return 0; 104 | } 105 | 106 | /// @brief Draws the Top Bar widget. 107 | /// @param pF The widget. 108 | /// @param pctx User interface context. 109 | void TopBarDraw(frame *pF, ui_context *pctx) 110 | { 111 | ASSERT(pF->mFrameType == kFrameBBox); 112 | 113 | int kTitleLength[4]; 114 | for(int i = 0; i < _countof(kTitleLength); ++i) 115 | { 116 | kTitleLength[i] = 8 * strlen(GetUIItem(2 + i)->mpTitle); 117 | } 118 | 119 | const int kGap = FitTitlesHoriz(kTitleLength, _countof(kTitleLength), 120 | pF->mRegion.mWidth); 121 | 122 | DrawBBox(&pctx->mScreenCtl, &pF->mRegion, 0); 123 | 124 | for(int i = 0, x_draw = kGap; i < _countof(kTitleLength); ++i) 125 | { 126 | const char *pith_title = GetUIItem(2 + i)->mpTitle; 127 | const uint16_t y_top = pF->mRegion.mTly; 128 | const uint16_t xleft = x_draw; 129 | 130 | TftPutTextLabel(&pctx->mScreenCtl, pith_title, x_draw, y_top + 4, 1); 131 | x_draw += kGap + kTitleLength[i]; 132 | 133 | TftPutLine(&pctx->mScreenCtl, x_draw, y_top, x_draw, 134 | y_top + (pF->mRegion.mHeight) - 1); 135 | 136 | /* Assign activation rect. */ 137 | AssignRect(sTopBarActivationRect + i, xleft, y_top, 138 | x_draw - xleft, pF->mRegion.mHeight); 139 | 140 | x_draw += kGap + 1; 141 | } 142 | 143 | frame_rect rect = { pF->mRegion.mTlx>>3, pF->mRegion.mTly>>3, 144 | pF->mRegion.mWidth>>3, pF->mRegion.mHeight>>3}; 145 | 146 | SetRegionColor(&pctx->mScreenCtl, &rect, pF->mPaper, pF->mInk); 147 | } 148 | 149 | /// @brief Defines what to do when click inside the widget. 150 | /// @param pF The widget. 151 | /// @param x Click X coord. 152 | /// @param y Click Y coord. 153 | /// @param pctx User interface context. 154 | void TopBarClickInside(frame *pF, int x, int y, ui_context *pctx) 155 | { 156 | const int ix = SelectTargetRect(sTopBarActivationRect, 157 | _countof(sTopBarActivationRect), x, y); 158 | //DebugPrintf("x:%d y:%d IX click: %d \n", x, y, ix); 159 | 160 | switch (ix) 161 | { 162 | case 0: 163 | PushStdFrame(pctx, 2); 164 | break; 165 | 166 | case 2: 167 | PushStdFrame(pctx, 8); 168 | break; 169 | 170 | default: 171 | break; 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /widgets/widgets_utility.c: -------------------------------------------------------------------------------- 1 | #include "widgets_utility.h" 2 | 3 | /// @brief Draws a bounding box around a text rectangle. 4 | /// @param pscr The control structure. 5 | /// @param prct Text-mode rectangle in symbol coords. 6 | /// @param shft A shift in pixels (<0 means inside one). 7 | void DrawBBox(screen_control_t *pscr, const frame_rect *prct, int8_t shft) 8 | { 9 | ASSERT(pscr); 10 | ASSERT(prct); 11 | ASSERT(prct->mTlx - shft >= 0); 12 | ASSERT(prct->mTly - shft >= 0); 13 | 14 | const int tlx = prct->mTlx - shft; 15 | const int tly = prct->mTly - shft; 16 | const int w = prct->mWidth + (shft<<1) - 1; 17 | const int h = prct->mHeight+ (shft<<1) - 1; 18 | 19 | TftPutLine(pscr, tlx, tly, tlx+w, tly); 20 | TftPutLine(pscr, tlx+w, tly, tlx+w, tly+h); 21 | TftPutLine(pscr, tlx, tly+h, tlx+w, tly+h); 22 | TftPutLine(pscr, tlx, tly, tlx, tly+h); 23 | } 24 | 25 | /// @brief Utility of fitting text titles horizontally. 26 | /// @param pstrlens Ptr to array of strings width in pix. 27 | /// @param strcount count of pstrlen's elements. 28 | /// @param fit_pix Width of pixel line to fit in. 29 | /// @return A gap calculated which should be added btw words. 30 | int FitTitlesHoriz(const int *pstrlens, int strcount, int fit_pix) 31 | { 32 | ASSERT(pstrlens); 33 | ASSERT(strcount); 34 | ASSERT(fit_pix > 8); 35 | 36 | int acc_w = 0; 37 | for(int i = 0; i < strcount; ++i) 38 | { 39 | acc_w += pstrlens[i]; 40 | } 41 | 42 | return (fit_pix - acc_w) / strcount / 2; 43 | } 44 | 45 | /// @brief Sets color attrs of text mode rectangle. 46 | /// @param pscr The screen control structure. 47 | /// @param prct The text mode rectangle. 48 | /// @param paper Paper(background) color. 49 | /// @param ink Ink(foreground) color. 50 | void SetRegionColor(screen_control_t *pscr, const frame_rect *prct, 51 | color_t paper, color_t ink) 52 | { 53 | for(int j = prct->mTly; j < prct->mTly + prct->mHeight; ++j) 54 | for(int i = prct->mTlx; i < prct->mTlx + prct->mWidth; ++i) 55 | { 56 | TftPutColorAttr(pscr, i, j, paper, ink); 57 | } 58 | } 59 | 60 | void AssignRect(frame_rect *pdst, uint16_t x, uint16_t y, 61 | uint16_t w, uint16_t h) 62 | { 63 | ASSERT(pdst); 64 | 65 | pdst->mTlx = x; 66 | pdst->mTly = y; 67 | pdst->mWidth = w; 68 | pdst->mHeight= h; 69 | } 70 | 71 | int SelectTargetRect(const frame_rect *prects, int count, int x, int y) 72 | { 73 | for(int i = 0; i < count; ++i) 74 | { 75 | if(IsInsideRect(prects + i, x, y)) 76 | { 77 | return i; 78 | } 79 | } 80 | return -1; 81 | } 82 | 83 | /// @brief Clear a widget using its bounding box. 84 | /// @param pwidget A widget. 85 | /// @param pscr The screen control structure. 86 | void ClearWidgetBBox(frame *pwidget, screen_control_t *pscr) 87 | { 88 | ASSERT(pwidget); 89 | /* 90 | for(int j = pwidget->mRegion.mTly; j < pwidget->mRegion.mTly + pwidget->mRegion.mHeight; ++j) 91 | { 92 | const int bitline = j * PIX_WIDTH; 93 | for(int i = pwidget->mRegion.mTlx; i < pwidget->mRegion.mTlx + pwidget->mRegion.mWidth; ++i) 94 | { 95 | CLR_DATA_BIT(pscr->mpPixBuffer, i + bitline); 96 | } 97 | } 98 | */ 99 | const int xl = pwidget->mRegion.mTlx >> 3; 100 | const int xr = (pwidget->mRegion.mTlx + pwidget->mRegion.mWidth) >> 3; 101 | const int yl = pwidget->mRegion.mTly >> 3; 102 | const int yr = (pwidget->mRegion.mTly + pwidget->mRegion.mHeight) >> 3; 103 | for(int j = yl; j < yr; ++j) 104 | for(int i = xl; i < xr; ++i) 105 | { 106 | TftClearRect8(pscr, i, j); 107 | uint8_t *pbox = pscr->mpColorBuffer + i + TEXT_WIDTH * j; 108 | *pbox |= 1 << 6; // Set for update. 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /widgets/widgets_utility.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define _countof(array) (sizeof(array) / sizeof(array[0])) 6 | 7 | int FitTitlesHoriz(const int *pstrlens, int strcount, int fit_pix); 8 | void DrawBBox(screen_control_t *pscr, const frame_rect *prct, int8_t shft); 9 | void SetRegionColor(screen_control_t *pscr, const frame_rect *prct, 10 | color_t paper, color_t ink); 11 | void AssignRect(frame_rect *pdst, uint16_t x, uint16_t y, uint16_t w, uint16_t h); 12 | int SelectTargetRect(const frame_rect *prects, int count, int x, int y); 13 | void ClearWidgetBBox(frame *pwidget, screen_control_t *pscr); 14 | --------------------------------------------------------------------------------