fin SETR2
This commit is contained in:
90
P7_SETR2/P7_SMT4497/TouchGFX/App/app_touchgfx.c
Normal file
90
P7_SETR2/P7_SMT4497/TouchGFX/App/app_touchgfx.c
Normal file
@@ -0,0 +1,90 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* File Name : app_touchgfx.c
|
||||
******************************************************************************
|
||||
* This file was created by TouchGFX Generator 4.26.0. This file is only
|
||||
* generated once! Delete this file from your project and re-generate code
|
||||
* using STM32CubeMX or change this file manually to update it.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2025 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "app_touchgfx.h"
|
||||
|
||||
/* Private includes ----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Includes */
|
||||
|
||||
/* USER CODE END Includes */
|
||||
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
|
||||
/* USER CODE BEGIN PD */
|
||||
|
||||
/* USER CODE END PD */
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN PM */
|
||||
|
||||
/* USER CODE END PM */
|
||||
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
|
||||
/* USER CODE BEGIN PV */
|
||||
|
||||
/* USER CODE END PV */
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
void touchgfx_init(void);
|
||||
void touchgfx_components_init(void);
|
||||
void touchgfx_taskEntry(void);
|
||||
|
||||
/* USER CODE BEGIN PFP */
|
||||
|
||||
/* USER CODE END PFP */
|
||||
|
||||
/**
|
||||
* PreOS Initialization function
|
||||
*/
|
||||
void MX_TouchGFX_PreOSInit(void)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize TouchGFX application
|
||||
*/
|
||||
void MX_TouchGFX_Init(void)
|
||||
{
|
||||
// Calling forward to touchgfx_init in C++ domain
|
||||
touchgfx_components_init();
|
||||
touchgfx_init();
|
||||
}
|
||||
|
||||
/**
|
||||
* TouchGFX application entry function
|
||||
*/
|
||||
void MX_TouchGFX_Process(void)
|
||||
{
|
||||
// Calling forward to touchgfx_taskEntry in C++ domain
|
||||
touchgfx_taskEntry();
|
||||
}
|
||||
|
||||
/**
|
||||
* TouchGFX application thread
|
||||
*/
|
||||
void TouchGFX_Task(void* argument)
|
||||
{
|
||||
// Calling forward to touchgfx_taskEntry in C++ domain
|
||||
touchgfx_taskEntry();
|
||||
}
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
60
P7_SETR2/P7_SMT4497/TouchGFX/App/app_touchgfx.h
Normal file
60
P7_SETR2/P7_SMT4497/TouchGFX/App/app_touchgfx.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* File Name : app_touchgfx.h
|
||||
******************************************************************************
|
||||
* This file was created by TouchGFX Generator 4.26.0. This file is only
|
||||
* generated once! Delete this file from your project and re-generate code
|
||||
* using STM32CubeMX or change this file manually to update it.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2025 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef APP_TOUCHGFX_H
|
||||
#define APP_TOUCHGFX_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN ET */
|
||||
|
||||
/* USER CODE END ET */
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* USER CODE BEGIN EC */
|
||||
|
||||
/* USER CODE END EC */
|
||||
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN EM */
|
||||
|
||||
/* USER CODE END EM */
|
||||
|
||||
/* Exported functions prototypes ---------------------------------------------*/
|
||||
void MX_TouchGFX_PreOSInit(void);
|
||||
void MX_TouchGFX_Init(void);
|
||||
void MX_TouchGFX_Process(void);
|
||||
void TouchGFX_Task(void* argument);
|
||||
|
||||
/* USER CODE BEGIN EFP */
|
||||
|
||||
/* USER CODE END EFP */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* APP_TOUCHGFX_H */
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
@@ -0,0 +1,33 @@
|
||||
|
||||
{
|
||||
"Application": {
|
||||
"Name": "STM32F746G_DISCO",
|
||||
"TouchGfxPath": "../Middlewares/ST/touchgfx",
|
||||
"AvailableColorDepths": [ 16 ],
|
||||
"AvailableLCDs":
|
||||
{
|
||||
"16": "LCD16bpp"
|
||||
},
|
||||
"AvailableResolutions": [
|
||||
{
|
||||
"Width": 480,
|
||||
"Height": 272
|
||||
}
|
||||
],
|
||||
"PostGenerateTargetCommand": "touchgfx update_project",
|
||||
"Family": "STM32F7",
|
||||
"SubFamily": "STM32F7x6",
|
||||
"Platform": "m7",
|
||||
"Toolchain": "STM32CubeIDE",
|
||||
"ProjectFile": "../STM32F746G_DISCO.ioc",
|
||||
"OptionalComponentsRoot": "../Middlewares/ST/touchgfx_components",
|
||||
"OptionalComponents": [
|
||||
],
|
||||
"AdditionalFeatures": [
|
||||
"CWRVector",
|
||||
"VectorFonts",
|
||||
"Video"
|
||||
]
|
||||
},
|
||||
"Version": "4.26.0"
|
||||
}
|
||||
128
P7_SETR2/P7_SMT4497/TouchGFX/P7_SMT4497.touchgfx
Normal file
128
P7_SETR2/P7_SMT4497/TouchGFX/P7_SMT4497.touchgfx
Normal file
@@ -0,0 +1,128 @@
|
||||
{
|
||||
"Application": {
|
||||
"Screens": [
|
||||
{
|
||||
"Name": "MainScreen",
|
||||
"Components": [
|
||||
{
|
||||
"Type": "Image",
|
||||
"Name": "background",
|
||||
"Width": 480,
|
||||
"Height": 272,
|
||||
"RelativeFilename": "fondo_blanco.png"
|
||||
},
|
||||
{
|
||||
"Type": "Image",
|
||||
"Name": "led_off",
|
||||
"X": 341,
|
||||
"Y": 87,
|
||||
"Width": 54,
|
||||
"Height": 98,
|
||||
"RelativeFilename": "led_off.png"
|
||||
},
|
||||
{
|
||||
"Type": "Image",
|
||||
"Name": "led_on",
|
||||
"X": 341,
|
||||
"Y": 87,
|
||||
"Width": 54,
|
||||
"Height": 98,
|
||||
"Visible": false,
|
||||
"RelativeFilename": "led_on.png"
|
||||
},
|
||||
{
|
||||
"Type": "Gauge",
|
||||
"Name": "temperature",
|
||||
"X": 16,
|
||||
"Y": 16,
|
||||
"Width": 240,
|
||||
"Height": 240,
|
||||
"Preset": "alternate_theme\\presets\\gauges\\medium\\active.json",
|
||||
"FileNameBackground": "__generated\\alternate_theme_images_widgets_gauge_medium_backgrounds_active.png",
|
||||
"RotationCenterX": 120.0,
|
||||
"RotationCenterY": 120.0,
|
||||
"StartAngle": -113.0,
|
||||
"EndAngle": 112.0,
|
||||
"RangeMax": 100.0,
|
||||
"InitialValue": 50.0,
|
||||
"Easing": "Linear",
|
||||
"EasingOption": "In",
|
||||
"FileNameNeedle": "__generated\\alternate_theme_images_widgets_gauge_medium_needles_smooth.png",
|
||||
"NeedleRotationCenterX": 7.0,
|
||||
"NeedleRotationCenterY": 67.0,
|
||||
"NeedleMovingRenderingAlgorithm": "Bilinear Interpolation",
|
||||
"NeedleSteadyRenderingAlgorithm": "Bilinear Interpolation",
|
||||
"ArcColor": {
|
||||
"Red": 20,
|
||||
"Green": 151,
|
||||
"Blue": 197
|
||||
},
|
||||
"ArcCapStyle": "Butt"
|
||||
}
|
||||
],
|
||||
"Interactions": []
|
||||
}
|
||||
],
|
||||
"CustomContainerDefinitions": [],
|
||||
"Name": "P7_SMT4497",
|
||||
"Resolution": {
|
||||
"Width": 480,
|
||||
"Height": 272
|
||||
},
|
||||
"SelectedColorDepth": 16,
|
||||
"StartupScreenName": "MainScreen",
|
||||
"SelectedStartupLanguage": "GB",
|
||||
"TouchGfxPath": "../Middlewares/ST/touchgfx",
|
||||
"UIPath": ".",
|
||||
"AvailableColorDepths": [
|
||||
16
|
||||
],
|
||||
"AvailableLCDs": {
|
||||
"16": "LCD16bpp"
|
||||
},
|
||||
"AvailableSections": [
|
||||
"ExtFlashSection",
|
||||
"IntFlashSection"
|
||||
],
|
||||
"AvailableResolutions": [
|
||||
{
|
||||
"Width": 480,
|
||||
"Height": 272
|
||||
}
|
||||
],
|
||||
"PhysicalButtons": [],
|
||||
"FrameworkFeatures": {
|
||||
"LCD16bpp": {
|
||||
"Id": "LCD16bpp",
|
||||
"IsEnabled": true
|
||||
}
|
||||
},
|
||||
"GenerateAssetsCommand": "make -f simulator/gcc/Makefile assets -j8",
|
||||
"PostGenerateCommand": "touchgfx update_project --project-file=simulator/msvs/Application.vcxproj",
|
||||
"PostGenerateTargetCommand": "touchgfx update_project",
|
||||
"CompileSimulatorCommand": "make -f simulator/gcc/Makefile -j8",
|
||||
"RunSimulatorCommand": "build\\bin\\simulator.exe",
|
||||
"CompileTargetCommand": "make -f ../gcc/Makefile -j8",
|
||||
"FlashTargetCommand": "make -f ../gcc/Makefile flash -j8",
|
||||
"FlashTargetIntCommandOverride": "make -f ../gcc/Makefile intflash -j8",
|
||||
"LandscapeSkinX": 0,
|
||||
"LandscapeSkinY": 0,
|
||||
"PortraitSkinX": 0,
|
||||
"PortraitSkinY": 0,
|
||||
"DisplayOrientation": "Landscape",
|
||||
"Family": "STM32F7",
|
||||
"SubFamily": "STM32F7x6",
|
||||
"Toolchain": "STM32CubeIDE",
|
||||
"Platform": "m7",
|
||||
"ProjectFile": "../STM32F746G_DISCO.ioc",
|
||||
"OptionalComponentsRoot": "../Middlewares/ST/touchgfx_components",
|
||||
"OptionalComponents": [],
|
||||
"AdditionalFeatures": [
|
||||
"CWRVector",
|
||||
"VectorFonts",
|
||||
"Video"
|
||||
]
|
||||
},
|
||||
"Version": "4.26.0",
|
||||
"CreatedBy": "4.26.0"
|
||||
}
|
||||
24
P7_SETR2/P7_SMT4497/TouchGFX/application.config
Normal file
24
P7_SETR2/P7_SMT4497/TouchGFX/application.config
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"image_configuration": {
|
||||
"dither_algorithm": "2",
|
||||
"alpha_dither": "yes",
|
||||
"layout_rotation": "0",
|
||||
"opaque_image_format": "RGB565",
|
||||
"nonopaque_image_format": "ARGB8888",
|
||||
"l8_compression": "no",
|
||||
"rgb_compression": "no",
|
||||
"section": "ExtFlashSection",
|
||||
"extra_section": "ExtFlashSection",
|
||||
"images": {}
|
||||
},
|
||||
"text_configuration": {
|
||||
"remap": "yes",
|
||||
"a4": "yes",
|
||||
"binary_translations": "no",
|
||||
"binary_fonts": "no",
|
||||
"framebuffer_bpp": "16",
|
||||
"font_format": "0",
|
||||
"cache_size": 4096,
|
||||
"copy_translations_to_ram": "no"
|
||||
}
|
||||
}
|
||||
BIN
P7_SETR2/P7_SMT4497/TouchGFX/assets/fonts/verdana.ttf
Normal file
BIN
P7_SETR2/P7_SMT4497/TouchGFX/assets/fonts/verdana.ttf
Normal file
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 917 B |
BIN
P7_SETR2/P7_SMT4497/TouchGFX/assets/images/fondo_blanco.png
Normal file
BIN
P7_SETR2/P7_SMT4497/TouchGFX/assets/images/fondo_blanco.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
BIN
P7_SETR2/P7_SMT4497/TouchGFX/assets/images/led_off.png
Normal file
BIN
P7_SETR2/P7_SMT4497/TouchGFX/assets/images/led_off.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.9 KiB |
BIN
P7_SETR2/P7_SMT4497/TouchGFX/assets/images/led_on.png
Normal file
BIN
P7_SETR2/P7_SMT4497/TouchGFX/assets/images/led_on.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 8.3 KiB |
14
P7_SETR2/P7_SMT4497/TouchGFX/assets/texts/texts.xml
Normal file
14
P7_SETR2/P7_SMT4497/TouchGFX/assets/texts/texts.xml
Normal file
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TextDatabase xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="texts.xsd" Version="4.26.0">
|
||||
<Languages>
|
||||
<Language Id="GB" />
|
||||
</Languages>
|
||||
<Texts>
|
||||
<TextGroup Id="Group1" />
|
||||
</Texts>
|
||||
<Typographies>
|
||||
<Typography Id="Default" Font="verdana.ttf" Size="20" Bpp="4" IsVector="no" Direction="LTR" FallbackCharacter="?" />
|
||||
<Typography Id="Large" Font="verdana.ttf" Size="40" Bpp="4" IsVector="no" Direction="LTR" FallbackCharacter="?" />
|
||||
<Typography Id="Small" Font="verdana.ttf" Size="10" Bpp="4" IsVector="no" Direction="LTR" FallbackCharacter="?" />
|
||||
</Typographies>
|
||||
</TextDatabase>
|
||||
168
P7_SETR2/P7_SMT4497/TouchGFX/assets/texts/texts.xsd
Normal file
168
P7_SETR2/P7_SMT4497/TouchGFX/assets/texts/texts.xsd
Normal file
@@ -0,0 +1,168 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<!--Types-->
|
||||
<xs:simpleType name="direction" final="restriction" >
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="LTR" />
|
||||
<xs:enumeration value="RTL" />
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
<xs:simpleType name="alignment" final="restriction" >
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="Left" />
|
||||
<xs:enumeration value="LEFT" />
|
||||
<xs:enumeration value="left" />
|
||||
<xs:enumeration value="Center" />
|
||||
<xs:enumeration value="CENTER" />
|
||||
<xs:enumeration value="center" />
|
||||
<xs:enumeration value="Right" />
|
||||
<xs:enumeration value="RIGHT" />
|
||||
<xs:enumeration value="right" />
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
<xs:simpleType name="bpp" final="restriction" >
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="1" />
|
||||
<xs:enumeration value="2" />
|
||||
<xs:enumeration value="4" />
|
||||
<xs:enumeration value="8" />
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
<xs:simpleType name="fallbackCharacter" final="restriction" >
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:pattern value="|.|skip|(0[xX][0-9a-fA-F]{1,4})" />
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
<xs:simpleType name="ellipsisCharacter" final="restriction" >
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:pattern value="|.|(0[xX][0-9a-fA-F]{1,4})" />
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
<xs:simpleType name="wildcardCharacterRanges" final="restriction" >
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:pattern value="|(.-.|(0[xX][0-9a-fA-F]{1,4}|[0-9]{1,5})(-(0[xX][0-9a-fA-F]{1,4}|[0-9]{1,5}))?)(,(.-.|(0[xX][0-9a-fA-F]{1,4}|[0-9]{1,5})(-(0[xX][0-9a-fA-F]{1,4}|[0-9]{1,5}))?))*" />
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
<xs:simpleType name="validCppIdentifier" final="restriction" >
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:pattern value="[a-zA-Z_][a-zA-Z0-9_]*" />
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
<xs:simpleType name="validIdentifier" final="restriction" >
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:pattern value="[a-zA-Z0-9_]+" />
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
<xs:simpleType name="fontSize" final="restriction">
|
||||
<xs:restriction base="xs:unsignedInt">
|
||||
<xs:minInclusive value="1"/>
|
||||
<xs:maxInclusive value="1000"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
<xs:simpleType name="isVector" final="restriction" >
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="yes" />
|
||||
<xs:enumeration value="no" />
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
<xs:simpleType name="isCompressed" final="restriction" >
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="yes" />
|
||||
<xs:enumeration value="no" />
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
<!--TextDatabase specification-->
|
||||
<xs:element name="TextDatabase">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="Languages">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element minOccurs="0" maxOccurs="unbounded" name="Language">
|
||||
<xs:complexType>
|
||||
<xs:attribute name="Id" type="validCppIdentifier" use="required" />
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:sequence>
|
||||
<xs:element name="Texts">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element minOccurs="0" maxOccurs="unbounded" name="TextGroup">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element minOccurs="0" maxOccurs="unbounded" name="Text">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element minOccurs="1" maxOccurs="unbounded" name="Translation">
|
||||
<xs:complexType>
|
||||
<xs:simpleContent>
|
||||
<xs:extension base="xs:string">
|
||||
<xs:attribute name="Language" type="validCppIdentifier" use="required" />
|
||||
<xs:attribute name="Alignment" type="alignment" use="optional" />
|
||||
</xs:extension>
|
||||
</xs:simpleContent>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="Id" type="validIdentifier" use="required" />
|
||||
<xs:attribute name="Alignment" type="alignment" use="required" />
|
||||
<xs:attribute name="TypographyId" type="validCppIdentifier" use="required" />
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="Id" type="validIdentifier" use="required" />
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
<xs:element name="Typographies">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element minOccurs="0" maxOccurs="unbounded" name="Typography">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element minOccurs="0" maxOccurs="unbounded" name="LanguageSetting">
|
||||
<xs:complexType>
|
||||
<xs:attribute name="Language" type="validCppIdentifier" use="required" />
|
||||
<xs:attribute name="Font" type="xs:string" use="required" />
|
||||
<xs:attribute name="Size" type="fontSize" use="required" />
|
||||
<xs:attribute name="Bpp" type="bpp" use="required" />
|
||||
<xs:attribute name="IsVector" type="isVector" use="required" />
|
||||
<xs:attribute name="Direction" type="direction" use="required" />
|
||||
<xs:attribute name="IsCompressed" type="isCompressed" use="optional" />
|
||||
<xs:attribute name="FallbackCharacter" type="fallbackCharacter" use="optional" />
|
||||
<xs:attribute name="WildcardCharacters" type="xs:string" use="optional" />
|
||||
<xs:attribute name="WidgetWildcardCharacters" type="xs:string" use="optional" />
|
||||
<xs:attribute name="WildcardCharacterRanges" type="wildcardCharacterRanges" use="optional" />
|
||||
<xs:attribute name="EllipsisCharacter" type="ellipsisCharacter" use="optional" />
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="Id" type="validCppIdentifier" use="required" />
|
||||
<xs:attribute name="Font" type="xs:string" use="required" />
|
||||
<xs:attribute name="Size" type="fontSize" use="required" />
|
||||
<xs:attribute name="Bpp" type="bpp" use="required" />
|
||||
<xs:attribute name="IsVector" type="isVector" use="required" />
|
||||
<xs:attribute name="Direction" type="direction" use="required" />
|
||||
<xs:attribute name="IsCompressed" type="isCompressed" use="optional" />
|
||||
<xs:attribute name="FallbackCharacter" type="fallbackCharacter" use="optional" />
|
||||
<xs:attribute name="WildcardCharacters" type="xs:string" use="optional" />
|
||||
<xs:attribute name="WidgetWildcardCharacters" type="xs:string" use="optional" />
|
||||
<xs:attribute name="WildcardCharacterRanges" type="wildcardCharacterRanges" use="optional" />
|
||||
<xs:attribute name="EllipsisCharacter" type="ellipsisCharacter" use="optional" />
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="Version" type="xs:string" use="required" />
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:schema>
|
||||
@@ -0,0 +1,24 @@
|
||||
#ifndef FRONTENDAPPLICATION_HPP
|
||||
#define FRONTENDAPPLICATION_HPP
|
||||
|
||||
#include <gui_generated/common/FrontendApplicationBase.hpp>
|
||||
|
||||
class FrontendHeap;
|
||||
|
||||
using namespace touchgfx;
|
||||
|
||||
class FrontendApplication : public FrontendApplicationBase
|
||||
{
|
||||
public:
|
||||
FrontendApplication(Model& m, FrontendHeap& heap);
|
||||
virtual ~FrontendApplication() { }
|
||||
|
||||
virtual void handleTickEvent()
|
||||
{
|
||||
model.tick();
|
||||
FrontendApplicationBase::handleTickEvent();
|
||||
}
|
||||
private:
|
||||
};
|
||||
|
||||
#endif // FRONTENDAPPLICATION_HPP
|
||||
@@ -0,0 +1,74 @@
|
||||
#ifndef FRONTENDHEAP_HPP
|
||||
#define FRONTENDHEAP_HPP
|
||||
|
||||
#include <gui_generated/common/FrontendHeapBase.hpp>
|
||||
|
||||
class FrontendHeap : public FrontendHeapBase
|
||||
{
|
||||
public:
|
||||
/* List any user-defined view types here*/
|
||||
typedef touchgfx::meta::TypeList< touchgfx::meta::Nil, //Replace this with first user-defined type
|
||||
touchgfx::meta::Nil //List must always end with meta::Nil !
|
||||
> UserDefinedViewTypes;
|
||||
|
||||
/* List any user-defined presenter types here*/
|
||||
typedef touchgfx::meta::TypeList< touchgfx::meta::Nil, //Replace this with first user-defined type
|
||||
touchgfx::meta::Nil //List must always end with meta::Nil !
|
||||
> UserDefinedPresenterTypes;
|
||||
|
||||
/* List any user-defined transition types here*/
|
||||
typedef touchgfx::meta::TypeList< touchgfx::meta::Nil, //Replace this with first user-defined type
|
||||
touchgfx::meta::Nil //List must always end with meta::Nil !
|
||||
> UserDefinedTransitionTypes;
|
||||
|
||||
|
||||
|
||||
/* Calculate largest view, both from generated and user-defined typelists */
|
||||
typedef touchgfx::meta::select_type_maxsize< UserDefinedViewTypes >::type MaxUserViewType;
|
||||
|
||||
typedef touchgfx::meta::TypeList< MaxGeneratedViewType,
|
||||
touchgfx::meta::TypeList< MaxUserViewType,
|
||||
touchgfx::meta::Nil
|
||||
> > CombinedViewTypes;
|
||||
|
||||
typedef touchgfx::meta::select_type_maxsize< CombinedViewTypes >::type MaxViewType;
|
||||
|
||||
/* Calculate largest presenter, both from generated and user-defined typelists */
|
||||
typedef touchgfx::meta::select_type_maxsize< UserDefinedPresenterTypes >::type MaxUserPresenterType;
|
||||
|
||||
typedef touchgfx::meta::TypeList< MaxGeneratedPresenterType,
|
||||
touchgfx::meta::TypeList< MaxUserPresenterType,
|
||||
touchgfx::meta::Nil
|
||||
> > CombinedPresenterTypes;
|
||||
typedef touchgfx::meta::select_type_maxsize< CombinedPresenterTypes >::type MaxPresenterType;
|
||||
|
||||
/* Calculate largest transition, both from generated and user-defined typelists */
|
||||
typedef touchgfx::meta::select_type_maxsize< UserDefinedTransitionTypes >::type MaxUserTransitionType;
|
||||
|
||||
typedef touchgfx::meta::TypeList< MaxGeneratedTransitionType,
|
||||
touchgfx::meta::TypeList< MaxUserTransitionType,
|
||||
touchgfx::meta::Nil
|
||||
> > CombinedTransitionTypes;
|
||||
typedef touchgfx::meta::select_type_maxsize< CombinedTransitionTypes >::type MaxTransitionType;
|
||||
|
||||
static FrontendHeap& getInstance()
|
||||
{
|
||||
static FrontendHeap instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
touchgfx::Partition< CombinedPresenterTypes, 1 > presenters;
|
||||
touchgfx::Partition< CombinedViewTypes, 1 > views;
|
||||
touchgfx::Partition< CombinedTransitionTypes, 1 > transitions;
|
||||
Model model;
|
||||
FrontendApplication app;
|
||||
|
||||
private:
|
||||
FrontendHeap() : FrontendHeapBase(presenters, views, transitions, app),
|
||||
app(model, *this)
|
||||
{
|
||||
gotoStartScreen(app);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // FRONTENDHEAP_HPP
|
||||
@@ -0,0 +1,39 @@
|
||||
#ifndef MAINSCREENPRESENTER_HPP
|
||||
#define MAINSCREENPRESENTER_HPP
|
||||
|
||||
#include <gui/model/ModelListener.hpp>
|
||||
#include <mvp/Presenter.hpp>
|
||||
|
||||
using namespace touchgfx;
|
||||
|
||||
class MainScreenView;
|
||||
|
||||
class MainScreenPresenter : public touchgfx::Presenter, public ModelListener
|
||||
{
|
||||
public:
|
||||
MainScreenPresenter(MainScreenView& v);
|
||||
|
||||
/**
|
||||
* The activate function is called automatically when this screen is "switched in"
|
||||
* (ie. made active). Initialization logic can be placed here.
|
||||
*/
|
||||
virtual void activate();
|
||||
|
||||
/**
|
||||
* The deactivate function is called automatically when this screen is "switched out"
|
||||
* (ie. made inactive). Teardown functionality can be placed here.
|
||||
*/
|
||||
virtual void deactivate();
|
||||
|
||||
virtual ~MainScreenPresenter() {}
|
||||
|
||||
virtual void set_button(bool state);
|
||||
virtual void set_temperature(uint16_t temp);
|
||||
|
||||
private:
|
||||
MainScreenPresenter();
|
||||
|
||||
MainScreenView& view;
|
||||
};
|
||||
|
||||
#endif // MAINSCREENPRESENTER_HPP
|
||||
@@ -0,0 +1,20 @@
|
||||
#ifndef MAINSCREENVIEW_HPP
|
||||
#define MAINSCREENVIEW_HPP
|
||||
|
||||
#include <gui_generated/mainscreen_screen/MainScreenViewBase.hpp>
|
||||
#include <gui/mainscreen_screen/MainScreenPresenter.hpp>
|
||||
|
||||
class MainScreenView : public MainScreenViewBase
|
||||
{
|
||||
public:
|
||||
MainScreenView();
|
||||
virtual ~MainScreenView() {}
|
||||
virtual void setupScreen();
|
||||
virtual void tearDownScreen();
|
||||
|
||||
virtual void set_button(bool state);
|
||||
virtual void set_temperature(uint16_t temp);
|
||||
protected:
|
||||
};
|
||||
|
||||
#endif // MAINSCREENVIEW_HPP
|
||||
25
P7_SETR2/P7_SMT4497/TouchGFX/gui/include/gui/model/Model.hpp
Normal file
25
P7_SETR2/P7_SMT4497/TouchGFX/gui/include/gui/model/Model.hpp
Normal file
@@ -0,0 +1,25 @@
|
||||
#ifndef MODEL_HPP
|
||||
#define MODEL_HPP
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
class ModelListener;
|
||||
|
||||
class Model
|
||||
{
|
||||
public:
|
||||
Model();
|
||||
|
||||
void bind(ModelListener* listener)
|
||||
{
|
||||
modelListener = listener;
|
||||
}
|
||||
|
||||
void tick();
|
||||
protected:
|
||||
ModelListener* modelListener;
|
||||
bool button_state; // estado del boton en la gui
|
||||
uint16_t temp; // estado del gauge en la gui
|
||||
};
|
||||
|
||||
#endif // MODEL_HPP
|
||||
@@ -0,0 +1,24 @@
|
||||
#ifndef MODELLISTENER_HPP
|
||||
#define MODELLISTENER_HPP
|
||||
|
||||
#include <gui/model/Model.hpp>
|
||||
|
||||
class ModelListener
|
||||
{
|
||||
public:
|
||||
ModelListener() : model(0) {}
|
||||
|
||||
virtual ~ModelListener() {}
|
||||
|
||||
void bind(Model* m)
|
||||
{
|
||||
model = m;
|
||||
}
|
||||
|
||||
virtual void set_button(bool state);
|
||||
virtual void set_temperature(uint16_t temp);
|
||||
protected:
|
||||
Model* model;
|
||||
};
|
||||
|
||||
#endif // MODELLISTENER_HPP
|
||||
@@ -0,0 +1,7 @@
|
||||
#include <gui/common/FrontendApplication.hpp>
|
||||
|
||||
FrontendApplication::FrontendApplication(Model& m, FrontendHeap& heap)
|
||||
: FrontendApplicationBase(m, heap)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
#include <gui/mainscreen_screen/MainScreenView.hpp>
|
||||
#include <gui/mainscreen_screen/MainScreenPresenter.hpp>
|
||||
|
||||
MainScreenPresenter::MainScreenPresenter(MainScreenView& v)
|
||||
: view(v)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void MainScreenPresenter::activate()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void MainScreenPresenter::deactivate()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void MainScreenPresenter::set_button(bool state)
|
||||
{
|
||||
view.set_button(state); // actualiza la view (UI)
|
||||
}
|
||||
|
||||
void MainScreenPresenter::set_temperature(uint16_t temp)
|
||||
{
|
||||
view.set_temperature(temp); // actualiza la view (UI)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
#include <gui/mainscreen_screen/MainScreenView.hpp>
|
||||
|
||||
MainScreenView::MainScreenView()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void MainScreenView::setupScreen()
|
||||
{
|
||||
MainScreenViewBase::setupScreen();
|
||||
}
|
||||
|
||||
void MainScreenView::tearDownScreen()
|
||||
{
|
||||
MainScreenViewBase::tearDownScreen();
|
||||
}
|
||||
|
||||
void MainScreenView::set_button(bool state)
|
||||
{
|
||||
led_on.setVisible(state);
|
||||
led_on.invalidate();
|
||||
}
|
||||
|
||||
void MainScreenView::set_temperature(uint16_t temp)
|
||||
{
|
||||
temperature.setValue(temp);
|
||||
temperature.invalidate();
|
||||
}
|
||||
27
P7_SETR2/P7_SMT4497/TouchGFX/gui/src/model/Model.cpp
Normal file
27
P7_SETR2/P7_SMT4497/TouchGFX/gui/src/model/Model.cpp
Normal file
@@ -0,0 +1,27 @@
|
||||
#include <gui/model/Model.hpp>
|
||||
#include <gui/model/ModelListener.hpp>
|
||||
#include "FreeRTOS.h"
|
||||
#include "queue.h"
|
||||
|
||||
extern "C" {
|
||||
extern QueueHandle_t button_queue;
|
||||
extern QueueHandle_t temperature_queue;
|
||||
}
|
||||
|
||||
Model::Model() : modelListener(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Model::tick()
|
||||
{
|
||||
if(xQueueReceive(button_queue, &button_state, 10) == pdPASS)
|
||||
{
|
||||
modelListener->set_button(button_state); // lo envia al presenter
|
||||
}
|
||||
|
||||
if(xQueueReceive(temperature_queue, &temp, 10) == pdPASS)
|
||||
{
|
||||
modelListener->set_temperature(temp); // lo envia al presenter
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
#include <CortexMMCUInstrumentation.hpp>
|
||||
#include <touchgfx/hal/HAL.hpp>
|
||||
|
||||
namespace touchgfx
|
||||
{
|
||||
void CortexMMCUInstrumentation::init()
|
||||
{
|
||||
// See: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0337e/CEGHJDCF.html
|
||||
//
|
||||
// [24] Read/write TRCENA This bit must be set to 1 to enable use of the trace and debug blocks:
|
||||
// Data Watchpoint and Trace (DWT)
|
||||
// Instrumentation Trace Macrocell (ITM)
|
||||
// Embedded Trace Macrocell (ETM)
|
||||
// Trace Port Interface Unit (TPIU).
|
||||
// This enables control of power usage unless tracing is required. The application can enable this, for ITM use, or use by a debugger.
|
||||
|
||||
// Enable Debug Exception and Monitor Control Register
|
||||
*((volatile unsigned int*)0xE000EDFC) |= 0x01000000;
|
||||
// Enable Lock Access Register
|
||||
*((volatile unsigned int*)0xE0001FB0) |= 0xC5ACCE55;
|
||||
// Enable Data Watchpoint and Trace Control Register
|
||||
*((volatile unsigned int*)0xE0001000) |= 1;
|
||||
}
|
||||
|
||||
//Board specific clockfrequency
|
||||
unsigned int CortexMMCUInstrumentation::getElapsedUS(unsigned int start, unsigned int now, unsigned int clockfrequency)
|
||||
{
|
||||
return ((now - start) + (clockfrequency / 2)) / clockfrequency;
|
||||
}
|
||||
|
||||
unsigned int CortexMMCUInstrumentation::getCPUCycles()
|
||||
{
|
||||
return *((volatile unsigned int*)0xE0001004);
|
||||
}
|
||||
|
||||
void CortexMMCUInstrumentation::setMCUActive(bool active)
|
||||
{
|
||||
if (active) //idle task sched out
|
||||
{
|
||||
uint32_t cc_temp = getCPUCycles() - cc_in;
|
||||
cc_consumed += cc_temp;
|
||||
}
|
||||
else //idle task sched in
|
||||
{
|
||||
cc_in = getCPUCycles();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
#ifndef CORTEXMMCUINSTRUMENTATION_HPP
|
||||
#define CORTEXMMCUINSTRUMENTATION_HPP
|
||||
|
||||
#include <platform/core/MCUInstrumentation.hpp>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace touchgfx
|
||||
{
|
||||
/**
|
||||
* @class CortexMMCUInstrumentation CortexMMCUInstrumentation.hpp platform/core/arm/cortex-m/CortexMMCUInstrumentation.hpp
|
||||
*
|
||||
* @brief Interface for instrumenting Cortex-M processors to measure MCU load via measured CPU
|
||||
* cycles.
|
||||
*
|
||||
* Interface for instrumenting Cortex-M processors to measure MCU load via measured CPU
|
||||
* cycles.
|
||||
*
|
||||
* @sa MCUInstrumentation
|
||||
*/
|
||||
class CortexMMCUInstrumentation : public MCUInstrumentation
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @fn virtual void CortexMMCUInstrumentation::init();
|
||||
*
|
||||
* @brief Initialization.
|
||||
*
|
||||
* Initialization.
|
||||
*/
|
||||
virtual void init();
|
||||
|
||||
/**
|
||||
* @fn virtual unsigned int CortexMMCUInstrumentation::getElapsedUS(unsigned int start, unsigned int now, unsigned int clockfrequency);
|
||||
*
|
||||
* @brief Gets elapsed microseconds basedon clockfrequency.
|
||||
*
|
||||
* Gets elapsed microseconds basedon clockfrequency.
|
||||
*
|
||||
* @param start Start time.
|
||||
* @param now Current time.
|
||||
* @param clockfrequency Clock frequency of the system.
|
||||
*
|
||||
* @return Elapsed microseconds start and now.
|
||||
*/
|
||||
virtual unsigned int getElapsedUS(unsigned int start, unsigned int now, unsigned int clockfrequency);
|
||||
|
||||
/**
|
||||
* @fn virtual unsigned int CortexMMCUInstrumentation::getCPUCycles();
|
||||
*
|
||||
* @brief Gets CPU cycles from register.
|
||||
*
|
||||
* Gets CPU cycles from register.
|
||||
*
|
||||
* @return CPU cycles.
|
||||
*/
|
||||
virtual unsigned int getCPUCycles();
|
||||
|
||||
/**
|
||||
* @fn virtual void CortexMMCUInstrumentation::setMCUActive(bool active);
|
||||
*
|
||||
* @brief Register if MCU is active by measuring cpu cycles.
|
||||
*
|
||||
* Register if MCU is active by measuring cpu cycles. If user wishes to track
|
||||
* MCU load, this method should be called whenever the OS Idle task is scheduled
|
||||
* in or out. This method makes calls to a concrete implementation of GPIO
|
||||
* functionality and a concrete implementation of cpu cycles.
|
||||
*
|
||||
* @param active If true, MCU is registered as being active, inactive otherwise.
|
||||
*/
|
||||
virtual void setMCUActive(bool active);
|
||||
};
|
||||
} // namespace touchgfx
|
||||
|
||||
#endif // CORTEXMMCUINSTRUMENTATION_HPP
|
||||
182
P7_SETR2/P7_SMT4497/TouchGFX/target/STM32TouchController.cpp
Normal file
182
P7_SETR2/P7_SMT4497/TouchGFX/target/STM32TouchController.cpp
Normal file
@@ -0,0 +1,182 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* File Name : STM32TouchController.cpp
|
||||
******************************************************************************
|
||||
* This file is generated by TouchGFX Generator 4.19.1.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2022 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
/* USER CODE END Header */
|
||||
|
||||
/* USER CODE BEGIN STM32TouchController */
|
||||
|
||||
#include <STM32TouchController.hpp>
|
||||
#include <TouchGFXHAL.hpp>
|
||||
#include <ft5336.h>
|
||||
#include <stm32f7xx_hal.h>
|
||||
#include <touchgfx/hal/OSWrappers.hpp>
|
||||
|
||||
static TS_DrvTypeDef* tsDriver;
|
||||
extern I2C_HandleTypeDef hi2c3;
|
||||
|
||||
void STM32TouchController::init()
|
||||
{
|
||||
/* Initialize the TS driver structure */
|
||||
tsDriver = &ft5336_ts_drv;
|
||||
|
||||
/* Initialize the TS driver */
|
||||
tsDriver->Start(TS_I2C_ADDRESS);
|
||||
}
|
||||
|
||||
bool STM32TouchController::sampleTouch(int32_t& x, int32_t& y)
|
||||
{
|
||||
/**
|
||||
* By default sampleTouch returns false,
|
||||
* return true if a touch has been detected, otherwise false.
|
||||
*
|
||||
* Coordinates are passed to the caller by reference by x and y.
|
||||
*
|
||||
* This function is called by the TouchGFX framework.
|
||||
* By default sampleTouch is called every tick, this can be adjusted by HAL::setTouchSampleRate(int8_t);
|
||||
*
|
||||
*/
|
||||
if (tsDriver)
|
||||
{
|
||||
if (tsDriver->DetectTouch(TS_I2C_ADDRESS))
|
||||
{
|
||||
/* Get each touch coordinates */
|
||||
uint16_t _x, _y;
|
||||
tsDriver->GetXY(TS_I2C_ADDRESS, &_y, &_x);
|
||||
x = (int32_t)_x;
|
||||
y = (int32_t)_y;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Manages error callback by re-initializing I2C.
|
||||
* @param i2c_handler : I2C handler
|
||||
* @param Addr: I2C Address
|
||||
* @retval None
|
||||
*/
|
||||
static void I2Cx_Error(I2C_HandleTypeDef* i2c_handler, uint8_t Addr)
|
||||
{
|
||||
/* De-initialize the I2C communication bus */
|
||||
HAL_I2C_DeInit(i2c_handler);
|
||||
|
||||
/* Re-Initialize the I2C communication bus */
|
||||
//I2Cx_Init(i2c_handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reads multiple data.
|
||||
* @param i2c_handler : I2C handler
|
||||
* @param Addr: I2C address
|
||||
* @param Reg: Reg address
|
||||
* @param MemAddress: Memory address
|
||||
* @param Buffer: Pointer to data buffer
|
||||
* @param Length: Length of the data
|
||||
* @retval Number of read data
|
||||
*/
|
||||
static HAL_StatusTypeDef I2Cx_ReadMultiple(I2C_HandleTypeDef* i2c_handler,
|
||||
uint8_t Addr,
|
||||
uint16_t Reg,
|
||||
uint16_t MemAddress,
|
||||
uint8_t* Buffer,
|
||||
uint16_t Length)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
status = HAL_I2C_Mem_Read(i2c_handler, Addr, (uint16_t)Reg, MemAddress, Buffer, Length, 1000);
|
||||
|
||||
/* Check the communication status */
|
||||
if (status != HAL_OK)
|
||||
{
|
||||
/* I2C error occurred */
|
||||
I2Cx_Error(i2c_handler, Addr);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Writes a value in a register of the device through BUS in using DMA mode.
|
||||
* @param i2c_handler : I2C handler
|
||||
* @param Addr: Device address on BUS Bus.
|
||||
* @param Reg: The target register address to write
|
||||
* @param MemAddress: Memory address
|
||||
* @param Buffer: The target register value to be written
|
||||
* @param Length: buffer size to be written
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef I2Cx_WriteMultiple(I2C_HandleTypeDef* i2c_handler,
|
||||
uint8_t Addr,
|
||||
uint16_t Reg,
|
||||
uint16_t MemAddress,
|
||||
uint8_t* Buffer,
|
||||
uint16_t Length)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
status = HAL_I2C_Mem_Write(i2c_handler, Addr, (uint16_t)Reg, MemAddress, Buffer, Length, 1000);
|
||||
|
||||
/* Check the communication status */
|
||||
if (status != HAL_OK)
|
||||
{
|
||||
/* Re-Initiaize the I2C Bus */
|
||||
I2Cx_Error(i2c_handler, Addr);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Writes a single data.
|
||||
* @param Addr: I2C address
|
||||
* @param Reg: Reg address
|
||||
* @param Value: Data to be written
|
||||
* @retval None
|
||||
*/
|
||||
void TS_IO_Write(uint8_t Addr, uint8_t Reg, uint8_t Value)
|
||||
{
|
||||
I2Cx_WriteMultiple(&hi2c3, Addr, (uint16_t)Reg, I2C_MEMADD_SIZE_8BIT, (uint8_t*)&Value, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reads a single data.
|
||||
* @param Addr: I2C address
|
||||
* @param Reg: Reg address
|
||||
* @retval Data to be read
|
||||
*/
|
||||
uint8_t TS_IO_Read(uint8_t Addr, uint8_t Reg)
|
||||
{
|
||||
uint8_t read_value = 0;
|
||||
|
||||
I2Cx_ReadMultiple(&hi2c3, Addr, Reg, I2C_MEMADD_SIZE_8BIT, (uint8_t*)&read_value, 1);
|
||||
|
||||
return read_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief TS delay
|
||||
* @param Delay: Delay in ms
|
||||
* @retval None
|
||||
*/
|
||||
void TS_IO_Delay(uint32_t Delay)
|
||||
{
|
||||
HAL_Delay(Delay);
|
||||
}
|
||||
|
||||
/* USER CODE END STM32TouchController */
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
73
P7_SETR2/P7_SMT4497/TouchGFX/target/STM32TouchController.hpp
Normal file
73
P7_SETR2/P7_SMT4497/TouchGFX/target/STM32TouchController.hpp
Normal file
@@ -0,0 +1,73 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* File Name : STM32TouchController.hpp
|
||||
******************************************************************************
|
||||
* This file is generated by TouchGFX Generator 4.19.1.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2022 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
/* USER CODE END Header */
|
||||
|
||||
/* USER CODE BEGIN STM32TouchController */
|
||||
|
||||
#ifndef STM32TOUCHCONTROLLER_HPP
|
||||
#define STM32TOUCHCONTROLLER_HPP
|
||||
|
||||
#include <platform/driver/touch/TouchController.hpp>
|
||||
|
||||
/**
|
||||
* @class STM32TouchController
|
||||
*
|
||||
* @brief This class specializes TouchController Interface.
|
||||
*
|
||||
* @sa touchgfx::TouchController
|
||||
*/
|
||||
|
||||
class STM32TouchController : public touchgfx::TouchController
|
||||
{
|
||||
public:
|
||||
|
||||
STM32TouchController() {}
|
||||
|
||||
/**
|
||||
* @fn virtual void STM32TouchController::init() = 0;
|
||||
*
|
||||
* @brief Initializes touch controller.
|
||||
*
|
||||
* Initializes touch controller.
|
||||
*/
|
||||
virtual void init();
|
||||
|
||||
/**
|
||||
* @fn virtual bool STM32TouchController::sampleTouch(int32_t& x, int32_t& y) = 0;
|
||||
*
|
||||
* @brief Checks whether the touch screen is being touched, and if so, what coordinates.
|
||||
*
|
||||
* Checks whether the touch screen is being touched, and if so, what coordinates.
|
||||
*
|
||||
* @param [out] x The x position of the touch
|
||||
* @param [out] y The y position of the touch
|
||||
*
|
||||
* @return True if a touch has been detected, otherwise false.
|
||||
*/
|
||||
virtual bool sampleTouch(int32_t& x, int32_t& y);
|
||||
|
||||
private:
|
||||
static const uint16_t TS_I2C_ADDRESS = ((uint16_t)0x70);
|
||||
};
|
||||
|
||||
#endif // STM32TOUCHCONTROLLER_HPP
|
||||
|
||||
/* USER CODE END STM32TouchController */
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
196
P7_SETR2/P7_SMT4497/TouchGFX/target/TouchGFXGPIO.cpp
Normal file
196
P7_SETR2/P7_SMT4497/TouchGFX/target/TouchGFXGPIO.cpp
Normal file
@@ -0,0 +1,196 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* File Name : TouchGFXGPIO.cpp
|
||||
******************************************************************************
|
||||
* This file is generated by TouchGFX Generator 4.19.1.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2022 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
/* USER CODE END Header */
|
||||
|
||||
#include <touchgfx/hal/GPIO.hpp>
|
||||
|
||||
/**
|
||||
* GPIO_ID Enum
|
||||
* The signals represented by this enum are used by TouchGFX framework to signal internal events.
|
||||
*
|
||||
* VSYNC_FREQ, /// Pin is toggled at each VSYNC
|
||||
* RENDER_TIME, /// Pin is high when frame rendering begins, low when finished
|
||||
* FRAME_RATE, /// Pin is toggled when the frame buffers are swapped.
|
||||
* MCU_ACTIVE /// Pin is high when framework is utilizing the MCU.
|
||||
*
|
||||
* Configure GPIO's with the same name as the GPIO_IDs above, as output, in CubeMX to export
|
||||
* the signals for performance measuring. See support.touchgfx.com for further details.
|
||||
*
|
||||
*/
|
||||
|
||||
/* USER CODE BEGIN TouchGFXGPIO.cpp */
|
||||
#include "stm32f7xx.h"
|
||||
#include "main.h"
|
||||
|
||||
/* USER CODE BEGIN user includes */
|
||||
// VSYNC_FREQ - Pin PB4(D3).
|
||||
// RENDER_TIME - Pin PC6(D1)
|
||||
// FRAME_RATE - Pin PC7(D0)
|
||||
// MCU_ACTIVE - Pin PG6(D2)
|
||||
/* USER CODE END user includes */
|
||||
|
||||
using namespace touchgfx;
|
||||
|
||||
static int GPIO_InvertedLevels[4];
|
||||
|
||||
#define M_GPIO_PIN_SET(id) (GPIO_InvertedLevels[id] ? GPIO_PIN_RESET : GPIO_PIN_SET)
|
||||
#define M_GPIO_PIN_RESET(id) (GPIO_InvertedLevels[id] ? GPIO_PIN_SET : GPIO_PIN_RESET)
|
||||
|
||||
/*
|
||||
* Perform configuration of IO pins.
|
||||
*/
|
||||
void GPIO::init()
|
||||
{
|
||||
for (int id = 0; id <= 4; id++)
|
||||
{
|
||||
if (GPIO::get(static_cast<GPIO_ID>(id)))
|
||||
{
|
||||
if (GPIO_InvertedLevels[id] != 1)
|
||||
{
|
||||
GPIO_InvertedLevels[id] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets a pin high.
|
||||
*/
|
||||
void GPIO::set(GPIO_ID id)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case GPIO::VSYNC_FREQ:
|
||||
#if defined(VSYNC_FREQ_GPIO_Port) && defined(VSYNC_FREQ_Pin)
|
||||
HAL_GPIO_WritePin(VSYNC_FREQ_GPIO_Port, VSYNC_FREQ_Pin, M_GPIO_PIN_SET(id));
|
||||
#endif
|
||||
break;
|
||||
case GPIO::RENDER_TIME:
|
||||
#if defined(RENDER_TIME_GPIO_Port) && defined(RENDER_TIME_Pin)
|
||||
HAL_GPIO_WritePin(RENDER_TIME_GPIO_Port, RENDER_TIME_Pin, M_GPIO_PIN_SET(id));
|
||||
#endif
|
||||
break;
|
||||
case GPIO::FRAME_RATE:
|
||||
#if defined(FRAME_RATE_GPIO_Port) && defined(FRAME_RATE_Pin)
|
||||
HAL_GPIO_WritePin(FRAME_RATE_GPIO_Port, FRAME_RATE_Pin, M_GPIO_PIN_SET(id));
|
||||
#endif
|
||||
break;
|
||||
case GPIO::MCU_ACTIVE:
|
||||
#if defined(MCU_ACTIVE_GPIO_Port) && defined(MCU_ACTIVE_Pin)
|
||||
HAL_GPIO_WritePin(MCU_ACTIVE_GPIO_Port, MCU_ACTIVE_Pin, M_GPIO_PIN_SET(id));
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets a pin low.
|
||||
*/
|
||||
void GPIO::clear(GPIO_ID id)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case GPIO::VSYNC_FREQ:
|
||||
#if defined(VSYNC_FREQ_GPIO_Port) && defined(VSYNC_FREQ_Pin)
|
||||
HAL_GPIO_WritePin(VSYNC_FREQ_GPIO_Port, VSYNC_FREQ_Pin, M_GPIO_PIN_RESET(id));
|
||||
#endif
|
||||
break;
|
||||
case GPIO::RENDER_TIME:
|
||||
#if defined(RENDER_TIME_GPIO_Port) && defined(RENDER_TIME_Pin)
|
||||
HAL_GPIO_WritePin(RENDER_TIME_GPIO_Port, RENDER_TIME_Pin, M_GPIO_PIN_RESET(id));
|
||||
#endif
|
||||
break;
|
||||
case GPIO::FRAME_RATE:
|
||||
#if defined(FRAME_RATE_GPIO_Port) && defined(FRAME_RATE_Pin)
|
||||
HAL_GPIO_WritePin(FRAME_RATE_GPIO_Port, FRAME_RATE_Pin, M_GPIO_PIN_RESET(id));
|
||||
#endif
|
||||
break;
|
||||
case GPIO::MCU_ACTIVE:
|
||||
#if defined(MCU_ACTIVE_GPIO_Port) && defined(MCU_ACTIVE_Pin)
|
||||
HAL_GPIO_WritePin(MCU_ACTIVE_GPIO_Port, MCU_ACTIVE_Pin, M_GPIO_PIN_RESET(id));
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Toggles a pin.
|
||||
*/
|
||||
void GPIO::toggle(GPIO_ID id)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case GPIO::VSYNC_FREQ:
|
||||
#if defined(VSYNC_FREQ_GPIO_Port) && defined(VSYNC_FREQ_Pin)
|
||||
HAL_GPIO_TogglePin(VSYNC_FREQ_GPIO_Port, VSYNC_FREQ_Pin);
|
||||
#endif
|
||||
break;
|
||||
case GPIO::RENDER_TIME:
|
||||
#if defined(RENDER_TIME_GPIO_Port) && defined(RENDER_TIME_Pin)
|
||||
HAL_GPIO_TogglePin(RENDER_TIME_GPIO_Port, RENDER_TIME_Pin);
|
||||
#endif
|
||||
break;
|
||||
case GPIO::FRAME_RATE:
|
||||
#if defined(FRAME_RATE_GPIO_Port) && defined(FRAME_RATE_Pin)
|
||||
HAL_GPIO_TogglePin(FRAME_RATE_GPIO_Port, FRAME_RATE_Pin);
|
||||
#endif
|
||||
break;
|
||||
case GPIO::MCU_ACTIVE:
|
||||
#if defined(MCU_ACTIVE_GPIO_Port) && defined(MCU_ACTIVE_Pin)
|
||||
HAL_GPIO_TogglePin(MCU_ACTIVE_GPIO_Port, MCU_ACTIVE_Pin);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets the state of a pin.
|
||||
*/
|
||||
bool GPIO::get(GPIO_ID id)
|
||||
{
|
||||
GPIO_PinState bitstatus = GPIO_PIN_RESET;
|
||||
switch (id)
|
||||
{
|
||||
case GPIO::VSYNC_FREQ:
|
||||
#if defined(VSYNC_FREQ_GPIO_Port) && defined(VSYNC_FREQ_Pin)
|
||||
bitstatus = HAL_GPIO_ReadPin(VSYNC_FREQ_GPIO_Port, VSYNC_FREQ_Pin);
|
||||
#endif
|
||||
break;
|
||||
case GPIO::RENDER_TIME:
|
||||
#if defined(RENDER_TIME_GPIO_Port) && defined(RENDER_TIME_Pin)
|
||||
bitstatus = HAL_GPIO_ReadPin(RENDER_TIME_GPIO_Port, RENDER_TIME_Pin);
|
||||
#endif
|
||||
break;
|
||||
case GPIO::FRAME_RATE:
|
||||
#if defined(FRAME_RATE_GPIO_Port) && defined(FRAME_RATE_Pin)
|
||||
bitstatus = HAL_GPIO_ReadPin(FRAME_RATE_GPIO_Port, FRAME_RATE_Pin);
|
||||
#endif
|
||||
break;
|
||||
case GPIO::MCU_ACTIVE:
|
||||
#if defined(MCU_ACTIVE_GPIO_Port) && defined(MCU_ACTIVE_Pin)
|
||||
bitstatus = HAL_GPIO_ReadPin(MCU_ACTIVE_GPIO_Port, MCU_ACTIVE_Pin);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
return (bitstatus == GPIO_PIN_SET);
|
||||
}
|
||||
|
||||
/* USER CODE END TouchGFXGPIO.cpp */
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
188
P7_SETR2/P7_SMT4497/TouchGFX/target/TouchGFXHAL.cpp
Normal file
188
P7_SETR2/P7_SMT4497/TouchGFX/target/TouchGFXHAL.cpp
Normal file
@@ -0,0 +1,188 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* File Name : TouchGFXHAL.cpp
|
||||
******************************************************************************
|
||||
* This file is generated by TouchGFX Generator 4.19.1.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2022 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
/* USER CODE END Header */
|
||||
|
||||
#include <TouchGFXHAL.hpp>
|
||||
|
||||
/* USER CODE BEGIN TouchGFXHAL.cpp */
|
||||
|
||||
#include "stm32f7xx.h"
|
||||
#include <touchgfx/hal/OSWrappers.hpp>
|
||||
#include <CortexMMCUInstrumentation.hpp>
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
using namespace touchgfx;
|
||||
CortexMMCUInstrumentation instrumentation;
|
||||
|
||||
namespace
|
||||
{
|
||||
LOCATION_PRAGMA_NOLOAD("TouchGFX_Framebuffer")
|
||||
uint32_t animationBuffer[(480 * 272 * 2 + 3) / 4] LOCATION_ATTRIBUTE_NOLOAD("TouchGFX_Framebuffer");
|
||||
}
|
||||
|
||||
void TouchGFXHAL::initialize()
|
||||
{
|
||||
// Calling parent implementation of initialize().
|
||||
//
|
||||
// To overwrite the generated implementation, omit call to parent function
|
||||
// and implemented needed functionality here.
|
||||
// Please note, HAL::initialize() must be called to initialize the framework.
|
||||
|
||||
TouchGFXGeneratedHAL::initialize();
|
||||
setAnimationStorage((void*)animationBuffer); //enable the animation storage to allow slide animations
|
||||
lockDMAToFrontPorch(false);
|
||||
instrumentation.init();
|
||||
setMCUInstrumentation(&instrumentation);
|
||||
enableMCULoadCalculation(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the frame buffer address used by the TFT controller.
|
||||
*
|
||||
* @return The address of the frame buffer currently being displayed on the TFT.
|
||||
*/
|
||||
uint16_t* TouchGFXHAL::getTFTFrameBuffer() const
|
||||
{
|
||||
// Calling parent implementation of getTFTFrameBuffer().
|
||||
//
|
||||
// To overwrite the generated implementation, omit call to parent function
|
||||
// and implemented needed functionality here.
|
||||
|
||||
return TouchGFXGeneratedHAL::getTFTFrameBuffer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the frame buffer address used by the TFT controller.
|
||||
*
|
||||
* @param [in] address New frame buffer address.
|
||||
*/
|
||||
void TouchGFXHAL::setTFTFrameBuffer(uint16_t* address)
|
||||
{
|
||||
// Calling parent implementation of setTFTFrameBuffer(uint16_t* address).
|
||||
//
|
||||
// To overwrite the generated implementation, omit call to parent function
|
||||
// and implemented needed functionality here.
|
||||
|
||||
TouchGFXGeneratedHAL::setTFTFrameBuffer(address);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is called whenever the framework has performed a partial draw.
|
||||
*
|
||||
* @param rect The area of the screen that has been drawn, expressed in absolute coordinates.
|
||||
*
|
||||
* @see flushFrameBuffer().
|
||||
*/
|
||||
void TouchGFXHAL::flushFrameBuffer(const touchgfx::Rect& rect)
|
||||
{
|
||||
// Calling parent implementation of flushFrameBuffer(const touchgfx::Rect& rect).
|
||||
//
|
||||
// To overwrite the generated implementation, omit call to parent function
|
||||
// and implemented needed functionality here.
|
||||
// Please note, HAL::flushFrameBuffer(const touchgfx::Rect& rect) must
|
||||
// be called to notify the touchgfx framework that flush has been performed.
|
||||
|
||||
TouchGFXGeneratedHAL::flushFrameBuffer(rect);
|
||||
|
||||
// If the framebuffer is placed in Write Through cached memory (e.g. SRAM) then we need
|
||||
// to flush the Dcache to make sure framebuffer is correct in RAM. That's done
|
||||
// using SCB_CleanInvalidateDCache().
|
||||
|
||||
SCB_CleanInvalidateDCache();
|
||||
}
|
||||
|
||||
bool TouchGFXHAL::blockCopy(void* RESTRICT dest, const void* RESTRICT src, uint32_t numBytes)
|
||||
{
|
||||
return TouchGFXGeneratedHAL::blockCopy(dest, src, numBytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the interrupts relevant for TouchGFX. This primarily entails setting
|
||||
* the interrupt priorities for the DMA and LCD interrupts.
|
||||
*/
|
||||
void TouchGFXHAL::configureInterrupts()
|
||||
{
|
||||
// Calling parent implementation of configureInterrupts().
|
||||
//
|
||||
// To overwrite the generated implementation, omit call to parent function
|
||||
// and implemented needed functionality here.
|
||||
|
||||
TouchGFXGeneratedHAL::configureInterrupts();
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for enabling interrupts set in configureInterrupts()
|
||||
*/
|
||||
void TouchGFXHAL::enableInterrupts()
|
||||
{
|
||||
// Calling parent implementation of enableInterrupts().
|
||||
//
|
||||
// To overwrite the generated implementation, omit call to parent function
|
||||
// and implemented needed functionality here.
|
||||
|
||||
TouchGFXGeneratedHAL::enableInterrupts();
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for disabling interrupts set in configureInterrupts()
|
||||
*/
|
||||
void TouchGFXHAL::disableInterrupts()
|
||||
{
|
||||
// Calling parent implementation of disableInterrupts().
|
||||
//
|
||||
// To overwrite the generated implementation, omit call to parent function
|
||||
// and implemented needed functionality here.
|
||||
|
||||
TouchGFXGeneratedHAL::disableInterrupts();
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the LCD controller to fire interrupts at VSYNC. Called automatically
|
||||
* once TouchGFX initialization has completed.
|
||||
*/
|
||||
void TouchGFXHAL::enableLCDControllerInterrupt()
|
||||
{
|
||||
// Calling parent implementation of enableLCDControllerInterrupt().
|
||||
//
|
||||
// To overwrite the generated implementation, omit call to parent function
|
||||
// and implemented needed functionality here.
|
||||
|
||||
TouchGFXGeneratedHAL::enableLCDControllerInterrupt();
|
||||
}
|
||||
|
||||
extern "C"
|
||||
{
|
||||
portBASE_TYPE IdleTaskHook(void* p)
|
||||
{
|
||||
if ((int)p) //idle task sched out
|
||||
{
|
||||
touchgfx::HAL::getInstance()->setMCUActive(true);
|
||||
}
|
||||
else //idle task sched in
|
||||
{
|
||||
touchgfx::HAL::getInstance()->setMCUActive(false);
|
||||
}
|
||||
return pdTRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* USER CODE END TouchGFXHAL.cpp */
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
165
P7_SETR2/P7_SMT4497/TouchGFX/target/TouchGFXHAL.hpp
Normal file
165
P7_SETR2/P7_SMT4497/TouchGFX/target/TouchGFXHAL.hpp
Normal file
@@ -0,0 +1,165 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* File Name : TouchGFXHAL.hpp
|
||||
******************************************************************************
|
||||
* This file is generated by TouchGFX Generator 4.19.1.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2022 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
/* USER CODE END Header */
|
||||
#ifndef TouchGFXHAL_HPP
|
||||
#define TouchGFXHAL_HPP
|
||||
|
||||
/* USER CODE BEGIN TouchGFXHAL.hpp */
|
||||
|
||||
#include <TouchGFXGeneratedHAL.hpp>
|
||||
|
||||
/**
|
||||
* @class TouchGFXHAL
|
||||
*
|
||||
* @brief HAL implementation for TouchGFX.
|
||||
*
|
||||
* @sa HAL
|
||||
*/
|
||||
class TouchGFXHAL : public TouchGFXGeneratedHAL
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @fn TouchGFXHAL::TouchGFXHAL(touchgfx::DMA_Interface& dma, touchgfx::LCD& display, touchgfx::TouchController& tc, uint16_t width, uint16_t height) : TouchGFXGeneratedHAL(dma, display, tc, width, height)
|
||||
*
|
||||
* @brief Constructor.
|
||||
*
|
||||
* Constructor. Initializes members.
|
||||
*
|
||||
* @param [in,out] dma Reference to DMA interface.
|
||||
* @param [in,out] display Reference to LCD interface.
|
||||
* @param [in,out] tc Reference to Touch Controller driver.
|
||||
* @param width Width of the display.
|
||||
* @param height Height of the display.
|
||||
*/
|
||||
TouchGFXHAL(touchgfx::DMA_Interface& dma, touchgfx::LCD& display, touchgfx::TouchController& tc, uint16_t width, uint16_t height) : TouchGFXGeneratedHAL(dma, display, tc, width, height)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void initialize();
|
||||
|
||||
/**
|
||||
* @fn virtual void TouchGFXHAL::disableInterrupts();
|
||||
*
|
||||
* @brief Disables the DMA and LCD interrupts.
|
||||
*
|
||||
* Disables the DMA and LCD interrupts.
|
||||
*/
|
||||
virtual void disableInterrupts();
|
||||
|
||||
/**
|
||||
* @fn virtual void TouchGFXHAL::enableInterrupts();
|
||||
*
|
||||
* @brief Enables the DMA and LCD interrupts.
|
||||
*
|
||||
* Enables the DMA and LCD interrupts.
|
||||
*/
|
||||
virtual void enableInterrupts();
|
||||
|
||||
/**
|
||||
* @fn virtual void TouchGFXHAL::configureInterrupts();
|
||||
*
|
||||
* @brief Sets the DMA and LCD interrupt priorities.
|
||||
*
|
||||
* Sets the DMA and LCD interrupt priorities.
|
||||
*/
|
||||
virtual void configureInterrupts();
|
||||
|
||||
/**
|
||||
* @fn virtual void TouchGFXHAL::enableLCDControllerInterrupt();
|
||||
*
|
||||
* @brief Configure the LCD controller to fire interrupts at VSYNC.
|
||||
*
|
||||
* Configure the LCD controller to fire interrupts at VSYNC. Called automatically
|
||||
* once TouchGFX initialization has completed.
|
||||
*/
|
||||
virtual void enableLCDControllerInterrupt();
|
||||
|
||||
/**
|
||||
* @fn virtual void TouchGFXHAL::flushFrameBuffer();
|
||||
*
|
||||
* @brief This function is called whenever the framework has performed a complete draw.
|
||||
*
|
||||
* This specialization is only in place to keep compilers happy. Base impl. will call the
|
||||
* Rect version.
|
||||
* @see HAL::flushFrameBuffer
|
||||
*/
|
||||
virtual void flushFrameBuffer()
|
||||
{
|
||||
TouchGFXGeneratedHAL::flushFrameBuffer();
|
||||
}
|
||||
|
||||
/**
|
||||
* @fn virtual void TouchGFXHAL::flushFrameBuffer(const Rect& rect);
|
||||
*
|
||||
* @brief This function is called whenever the framework has performed a partial draw.
|
||||
*
|
||||
* This function is called whenever the framework has performed a partial draw.
|
||||
* On the STM32F7, make sure to clean and invalidate the data cache. This is to
|
||||
* ensure that LTDC sees correct data when transferring to the display.
|
||||
*
|
||||
* @param rect The area of the screen that has been drawn, expressed in absolute coordinates.
|
||||
*
|
||||
* @see flushFrameBuffer().
|
||||
*/
|
||||
virtual void flushFrameBuffer(const touchgfx::Rect& rect);
|
||||
|
||||
/**
|
||||
* @fn virtual bool TouchGFXHAL::blockCopy(void* RESTRICT dest, const void* RESTRICT src, uint32_t numBytes);
|
||||
*
|
||||
* @brief This function performs a platform-specific memcpy.
|
||||
*
|
||||
* This function performs a platform-specific memcpy, if supported by the hardware.
|
||||
*
|
||||
* @param [out] dest Pointer to destination memory.
|
||||
* @param [in] src Pointer to source memory.
|
||||
* @param numBytes Number of bytes to copy.
|
||||
*
|
||||
* @return true if the copy succeeded, false if copy was not performed.
|
||||
*/
|
||||
virtual bool blockCopy(void* RESTRICT dest, const void* RESTRICT src, uint32_t numBytes);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @fn virtual uint16_t* TouchGFXHAL::getTFTFrameBuffer() const;
|
||||
*
|
||||
* @brief Gets the frame buffer address used by the TFT controller.
|
||||
*
|
||||
* Gets the frame buffer address used by the TFT controller.
|
||||
*
|
||||
* @return The address of the frame buffer currently being displayed on the TFT.
|
||||
*/
|
||||
virtual uint16_t* getTFTFrameBuffer() const;
|
||||
|
||||
/**
|
||||
* @fn virtual void TouchGFXHAL::setTFTFrameBuffer(uint16_t* adr);
|
||||
*
|
||||
* @brief Sets the frame buffer address used by the TFT controller.
|
||||
*
|
||||
* Sets the frame buffer address used by the TFT controller.
|
||||
*
|
||||
* @param [in,out] adr New frame buffer address.
|
||||
*/
|
||||
virtual void setTFTFrameBuffer(uint16_t* adr);
|
||||
};
|
||||
|
||||
/* USER CODE END TouchGFXHAL.hpp */
|
||||
|
||||
#endif // TouchGFXHAL_HPP
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
@@ -0,0 +1,539 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* File Name : DoubleBufferedVideoController.hpp
|
||||
******************************************************************************
|
||||
* This file is generated by TouchGFX Generator 4.26.0. Please, do not edit!
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2025 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
#ifndef BUFFERPOOLVIDEOCONTROLLER_HPP
|
||||
#define BUFFERPOOLVIDEOCONTROLLER_HPP
|
||||
|
||||
#include <touchgfx/widgets/VideoWidget.hpp>
|
||||
#include <MJPEGDecoder.hpp>
|
||||
#include <touchgfx/Utils.hpp>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "cmsis_os.h"
|
||||
#if defined(osCMSIS) && (osCMSIS < 0x20000)
|
||||
#define MUTEX_CREATE() osMutexCreate(0)
|
||||
#define MUTEX_LOCK(m) osMutexWait(m, osWaitForever)
|
||||
#define MUTEX_TYPE osMutexId
|
||||
#define MUTEX_UNLOCK(m) osMutexRelease(m)
|
||||
#define SEM_CREATE() osSemaphoreCreate(0, 1)
|
||||
#define SEM_POST(s) osSemaphoreRelease(s)
|
||||
#define SEM_TYPE osSemaphoreId
|
||||
#define SEM_WAIT(s) osSemaphoreWait(s, osWaitForever)
|
||||
#else
|
||||
#define MUTEX_CREATE() osMutexNew(0)
|
||||
#define MUTEX_LOCK(m) osMutexAcquire(m, osWaitForever)
|
||||
#define MUTEX_TYPE osMutexId_t
|
||||
#define MUTEX_UNLOCK(m) osMutexRelease(m)
|
||||
#define SEM_CREATE() osSemaphoreNew(1, 0, 0)
|
||||
#define SEM_POST(s) osSemaphoreRelease(s)
|
||||
#define SEM_TYPE osSemaphoreId_t
|
||||
#define SEM_WAIT(s) osSemaphoreAcquire(s, osWaitForever)
|
||||
#endif
|
||||
|
||||
template <uint32_t no_streams, uint32_t width, uint32_t height, uint32_t stride, touchgfx::Bitmap::BitmapFormat output_format>
|
||||
class DoubleBufferedVideoController : public touchgfx::VideoController
|
||||
{
|
||||
public:
|
||||
DoubleBufferedVideoController()
|
||||
: VideoController(),
|
||||
bufferRGB(0), sizeBufferRGB(0), topBufferRGB(0), allowSkipFrames(true),
|
||||
semDecode(0), mutexBuffers(0)
|
||||
{
|
||||
assert((no_streams > 0) && "Video: Number of streams zero!");
|
||||
|
||||
// Clear decoder array
|
||||
memset(mjpegDecoders, 0, sizeof(mjpegDecoders));
|
||||
|
||||
// Initialize synchronization primitives
|
||||
semDecode = SEM_CREATE(); // Binary semaphore
|
||||
mutexBuffers = MUTEX_CREATE();
|
||||
}
|
||||
|
||||
virtual Handle registerVideoWidget(touchgfx::VideoWidget& widget)
|
||||
{
|
||||
// Running in UI thread
|
||||
|
||||
// Find stream handle for Widget
|
||||
Handle handle = getFreeHandle();
|
||||
|
||||
streams[handle].isActive = true;
|
||||
|
||||
// Set Widget buffer format and address
|
||||
widget.setVideoBufferFormat(output_format, width, height);
|
||||
widget.setVideoBuffer((uint8_t*)0);
|
||||
|
||||
streams[handle].frameNumberShown = 0;
|
||||
|
||||
// Todo, make buffer size depending on widget
|
||||
const uint32_t sizeOfOneDecodeBuffer = height * stride;
|
||||
|
||||
// Allocate two buffers for this stream, if possible
|
||||
if (topBufferRGB + 2 * sizeOfOneDecodeBuffer > (bufferRGB + sizeBufferRGB))
|
||||
{
|
||||
assert(0 && "registerVideoWidget: Unable to allocate two RGB buffers!");
|
||||
return 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
streams[handle].bufferA = (uint8_t*)topBufferRGB;
|
||||
topBufferRGB += sizeOfOneDecodeBuffer;
|
||||
streams[handle].bufferB = (uint8_t*)topBufferRGB;
|
||||
topBufferRGB += sizeOfOneDecodeBuffer;
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
virtual void unregisterVideoWidget(const Handle handle)
|
||||
{
|
||||
// Running in UI thread
|
||||
|
||||
// Reset active for this handle
|
||||
streams[handle].isActive = false;
|
||||
|
||||
// If all handles are free, reset top pointer
|
||||
bool oneIsActive = false;
|
||||
for (uint32_t i = 0; i < no_streams; i++)
|
||||
{
|
||||
oneIsActive |= streams[i].isActive;
|
||||
}
|
||||
if (oneIsActive == false)
|
||||
{
|
||||
// Reset memory usage
|
||||
topBufferRGB = bufferRGB;
|
||||
}
|
||||
}
|
||||
|
||||
virtual uint32_t getCurrentFrameNumber(const Handle handle)
|
||||
{
|
||||
assert(handle < no_streams);
|
||||
const Stream& stream = streams[handle];
|
||||
return stream.frameNumberShown;
|
||||
}
|
||||
|
||||
virtual void setFrameRate(const Handle handle, uint32_t ui_frames, uint32_t video_frames)
|
||||
{
|
||||
// Running in UI thread
|
||||
|
||||
assert(handle < no_streams);
|
||||
Stream& stream = streams[handle];
|
||||
|
||||
// Reset counters
|
||||
stream.tickCount = 0;
|
||||
stream.frameCount = 0;
|
||||
|
||||
// Save requested frame rate ratio
|
||||
stream.frame_rate_ticks = ui_frames;
|
||||
stream.frame_rate_video = video_frames;
|
||||
}
|
||||
|
||||
virtual void setVideoData(const Handle handle, const uint8_t* movie, const uint32_t length)
|
||||
{
|
||||
// Running in UI thread
|
||||
|
||||
mjpegDecoders[handle]->setVideoData(movie, length);
|
||||
|
||||
clearState(handle);
|
||||
}
|
||||
|
||||
virtual void setVideoData(const Handle handle, VideoDataReader& reader)
|
||||
{
|
||||
// Running in UI thread
|
||||
mjpegDecoders[handle]->setVideoData(reader);
|
||||
|
||||
clearState(handle);
|
||||
}
|
||||
|
||||
virtual void setCommand(const Handle handle, Command cmd, uint32_t param)
|
||||
{
|
||||
// Running in UI thread
|
||||
|
||||
assert(handle < no_streams);
|
||||
Stream& stream = streams[handle];
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case PLAY:
|
||||
// Cannot Play without movie
|
||||
if (mjpegDecoders[handle]->hasVideo())
|
||||
{
|
||||
MUTEX_LOCK(mutexBuffers);
|
||||
stream.isPlaying = true;
|
||||
stream.cancelDecoding = false;
|
||||
// Reset counters
|
||||
stream.frameCount = 0;
|
||||
stream.tickCount = 0;
|
||||
// Seek to start of video if stopped
|
||||
if (stream.isStopped)
|
||||
{
|
||||
stream.seek_to_frame = 1;
|
||||
}
|
||||
stream.isStopped = false;
|
||||
// Kick decoder if next buffer is available
|
||||
stream.skip_frames = 0;
|
||||
if (stream.nextBuffer == 0)
|
||||
{
|
||||
stream.doDecodeNewFrame = true;
|
||||
SEM_POST(semDecode);
|
||||
}
|
||||
MUTEX_UNLOCK(mutexBuffers);
|
||||
}
|
||||
break;
|
||||
case PAUSE:
|
||||
stream.isPlaying = false;
|
||||
stream.isStopped = false;
|
||||
break;
|
||||
case SEEK:
|
||||
stream.seek_to_frame = param;
|
||||
// Reset counters
|
||||
stream.frameCount = 0;
|
||||
stream.tickCount = 0;
|
||||
break;
|
||||
case SHOW:
|
||||
stream.seek_to_frame = param;
|
||||
// Reset counters
|
||||
stream.frameCount = 0;
|
||||
stream.tickCount = 0;
|
||||
stream.isStopped = false;
|
||||
break;
|
||||
case STOP:
|
||||
stream.isPlaying = false;
|
||||
stream.isStopped = true;
|
||||
break;
|
||||
case SET_REPEAT:
|
||||
stream.repeat = (param > 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by VideoWidget::handleTickEvent.
|
||||
* Update frame counters.
|
||||
* Decide if widget should be invalidated.
|
||||
*/
|
||||
virtual bool updateFrame(const Handle handle, touchgfx::VideoWidget& widget)
|
||||
{
|
||||
// Running in UI thread
|
||||
|
||||
assert(handle < no_streams);
|
||||
Stream& stream = streams[handle];
|
||||
|
||||
// Increase tickCount if playing
|
||||
if (stream.isPlaying)
|
||||
{
|
||||
stream.tickCount += HAL::getInstance()->getLCDRefreshCount();
|
||||
}
|
||||
|
||||
// Assume more frames are available, flag is lowered once, when changing to the last frame
|
||||
bool hasMoreFrames = true;
|
||||
|
||||
// See if we have a nextBuffer and if next frame of specific frame is to be decoded
|
||||
if (stream.nextBuffer && (decodeForNextTick(stream) || stream.seek_to_frame > 0))
|
||||
{
|
||||
MUTEX_LOCK(mutexBuffers);
|
||||
|
||||
// Do nothing if seek to frame
|
||||
if (stream.seek_to_frame > 0)
|
||||
{
|
||||
stream.nextBuffer = 0;
|
||||
}
|
||||
|
||||
if (stream.nextBuffer != 0)
|
||||
{
|
||||
// Use nextBuffer as current
|
||||
stream.currentBuffer = stream.nextBuffer;
|
||||
stream.nextBuffer = 0;
|
||||
|
||||
// Copy frameNumber, increase count
|
||||
stream.frameNumberShown = stream.frameNumberNext;
|
||||
stream.frameCount++;
|
||||
|
||||
hasMoreFrames = stream.hasMoreFramesAfterNext;
|
||||
|
||||
// Update widget to show current buffer
|
||||
widget.setVideoBuffer(stream.currentBuffer);
|
||||
widget.invalidate();
|
||||
|
||||
if (!hasMoreFrames && !stream.repeat)
|
||||
{
|
||||
stream.isPlaying = false;
|
||||
}
|
||||
}
|
||||
|
||||
MUTEX_UNLOCK(mutexBuffers);
|
||||
}
|
||||
|
||||
// Kick decoder if playing or seeking frame and next buffer is ready
|
||||
if ((stream.isPlaying || stream.seek_to_frame > 0) && (stream.nextBuffer == 0))
|
||||
{
|
||||
stream.doDecodeNewFrame = true;
|
||||
SEM_POST(semDecode);
|
||||
}
|
||||
|
||||
return hasMoreFrames;
|
||||
}
|
||||
|
||||
virtual void draw(const Handle handle, const touchgfx::Rect& invalidatedArea, const touchgfx::VideoWidget& widget)
|
||||
{
|
||||
// Running in UI thread
|
||||
|
||||
// Nothing in this decoder
|
||||
}
|
||||
|
||||
void setRGBBuffer(uint8_t* buffer, size_t sizeOfBuffer)
|
||||
{
|
||||
// Running in UI thread / main
|
||||
|
||||
bufferRGB = buffer;
|
||||
topBufferRGB = bufferRGB;
|
||||
sizeBufferRGB = sizeOfBuffer;
|
||||
}
|
||||
|
||||
void addDecoder(MJPEGDecoder& decoder, uint32_t index)
|
||||
{
|
||||
// Running in UI thread / main
|
||||
|
||||
assert(index < no_streams);
|
||||
mjpegDecoders[index] = &decoder;
|
||||
}
|
||||
|
||||
void endFrame()
|
||||
{
|
||||
// Running in UI thread
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
void decoderTaskEntry()
|
||||
{
|
||||
// Running in Decoder thread!!
|
||||
|
||||
while (1)
|
||||
{
|
||||
// Look for a stream to decode
|
||||
uint32_t stream_index = getStreamIndexToDecode();
|
||||
|
||||
if (stream_index == NO_STREAM)
|
||||
{
|
||||
// All streams decoded, wait for synchronisation signal from UI thread
|
||||
SEM_WAIT(semDecode);
|
||||
|
||||
// Try from the beginning
|
||||
continue;
|
||||
}
|
||||
|
||||
// Lock out UI by taking the mutex
|
||||
MUTEX_LOCK(mutexBuffers);
|
||||
|
||||
// Now decode the stream
|
||||
Stream& stream = streams[stream_index];
|
||||
|
||||
// Select the unused buffer for decoding
|
||||
uint8_t* decodeBuffer = (stream.currentBuffer == stream.bufferA) ? stream.bufferB : stream.bufferA;
|
||||
|
||||
MJPEGDecoder* const decoder = mjpegDecoders[stream_index];
|
||||
// Seek or increment video frame
|
||||
if (stream.seek_to_frame > 0)
|
||||
{
|
||||
decoder->gotoFrame(stream.seek_to_frame);
|
||||
stream.seek_to_frame = 0;
|
||||
stream.cancelDecoding = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (stream.skip_frames > 0)
|
||||
{
|
||||
decoder->gotoFrame(decoder->getCurrentFrameNumber() + stream.skip_frames);
|
||||
stream.frameCount += stream.skip_frames;
|
||||
stream.skip_frames = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Unlock mutex while decoding
|
||||
MUTEX_UNLOCK(mutexBuffers);
|
||||
|
||||
// Decode frame
|
||||
const bool hasMoreFrames = decoder->decodeNextFrame(decodeBuffer, width, height, stride);
|
||||
|
||||
MUTEX_LOCK(mutexBuffers);
|
||||
|
||||
// Save new frame in stream unless cancelled
|
||||
if (stream.cancelDecoding)
|
||||
{
|
||||
stream.cancelDecoding = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
stream.nextBuffer = decodeBuffer;
|
||||
if (hasMoreFrames)
|
||||
{
|
||||
stream.frameNumberNext = decoder->getCurrentFrameNumber() - 1; // Points to frame after this
|
||||
}
|
||||
else
|
||||
{
|
||||
stream.frameNumberNext = 1;
|
||||
}
|
||||
stream.hasMoreFramesAfterNext = hasMoreFrames;
|
||||
|
||||
// Lower decode flag
|
||||
stream.doDecodeNewFrame = false;
|
||||
}
|
||||
|
||||
// Release the mutex
|
||||
MUTEX_UNLOCK(mutexBuffers);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void getVideoInformation(const Handle handle, touchgfx::VideoInformation* data)
|
||||
{
|
||||
assert(handle < no_streams);
|
||||
mjpegDecoders[handle]->getVideoInfo(data);
|
||||
}
|
||||
|
||||
virtual bool getIsPlaying(const Handle handle)
|
||||
{
|
||||
assert(handle < no_streams);
|
||||
Stream& stream = streams[handle];
|
||||
return stream.isPlaying;
|
||||
}
|
||||
|
||||
virtual void setVideoFrameRateCompensation(bool allow)
|
||||
{
|
||||
allowSkipFrames = allow;
|
||||
}
|
||||
|
||||
private:
|
||||
class Stream
|
||||
{
|
||||
public:
|
||||
Stream() : frameCount(0), frameNumberNext(0), frameNumberShown(0), tickCount(0),
|
||||
frame_rate_video(0), frame_rate_ticks(0),
|
||||
seek_to_frame(0), skip_frames(0),
|
||||
currentBuffer(0), nextBuffer(0), bufferA(0), bufferB(0),
|
||||
isActive(false), isPlaying(false),
|
||||
doDecodeNewFrame(false), cancelDecoding(false),
|
||||
hasMoreFramesAfterNext(false), repeat(true), isStopped(false)
|
||||
{}
|
||||
uint32_t frameCount; // Video frame count since play/speed change
|
||||
uint32_t frameNumberNext; // Next Video frame number (if any)
|
||||
uint32_t frameNumberShown; // Shown Video frame number
|
||||
uint32_t tickCount; // UI frames since play
|
||||
uint32_t frame_rate_video; // Ratio of frames wanted counter
|
||||
uint32_t frame_rate_ticks; // Ratio of frames wanted divider
|
||||
uint32_t seek_to_frame; // Requested next frame number
|
||||
uint32_t skip_frames; // Number of frames to skip to keep frame rate
|
||||
uint8_t* currentBuffer; // Current Video frame, used for drawing
|
||||
uint8_t* nextBuffer; // Already decode next video frame, or zero
|
||||
uint8_t* bufferA; // One buffer allocated for this stream
|
||||
uint8_t* bufferB; // Another buffer allocated for this stream
|
||||
bool isActive;
|
||||
bool isPlaying;
|
||||
bool doDecodeNewFrame;
|
||||
bool cancelDecoding;
|
||||
bool hasMoreFramesAfterNext;
|
||||
bool repeat;
|
||||
bool isStopped;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
NO_STREAM = 0xFFFF
|
||||
};
|
||||
|
||||
MJPEGDecoder* mjpegDecoders[no_streams];
|
||||
Stream streams[no_streams];
|
||||
uint8_t* bufferRGB;
|
||||
size_t sizeBufferRGB; // Size in Bytes
|
||||
uint8_t* topBufferRGB; // Pointer to unused memory in buffer
|
||||
bool allowSkipFrames;
|
||||
|
||||
SEM_TYPE semDecode; // Post by UI, wait by Decoder thread
|
||||
MUTEX_TYPE mutexBuffers; // Mutual exclusion of the video buffers and stream data
|
||||
|
||||
/* return true, if new video frame should be decoded for the next tick (keep video decode framerate low) */
|
||||
bool decodeForNextTick(Stream& stream)
|
||||
{
|
||||
// Running in UI thread
|
||||
|
||||
// Compare tickCount/frameCount to frame_rate_ticks/frame_rate_video
|
||||
if ((stream.tickCount * stream.frame_rate_video) >= (stream.frame_rate_ticks * stream.frameCount))
|
||||
{
|
||||
if (allowSkipFrames)
|
||||
{
|
||||
stream.skip_frames = (stream.tickCount * stream.frame_rate_video - stream.frame_rate_ticks * stream.frameCount) / stream.frame_rate_ticks;
|
||||
if (stream.skip_frames > 0)
|
||||
{
|
||||
stream.skip_frames--;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Handle getFreeHandle()
|
||||
{
|
||||
// Running in UI thread
|
||||
|
||||
for (uint32_t i = 0; i < no_streams; i++)
|
||||
{
|
||||
if (streams[i].isActive == false)
|
||||
{
|
||||
// Reset stream parameters
|
||||
streams[i] = Stream();
|
||||
|
||||
return static_cast<VideoController::Handle>(i);
|
||||
}
|
||||
}
|
||||
|
||||
assert(0 && "Unable to find free video stream handle!");
|
||||
return static_cast<VideoController::Handle>(0);
|
||||
}
|
||||
|
||||
uint32_t getStreamIndexToDecode()
|
||||
{
|
||||
for (uint32_t i = 0; i < no_streams; i++)
|
||||
{
|
||||
Stream& stream = streams[i];
|
||||
if (stream.doDecodeNewFrame) // Marked by UI for decoding
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return NO_STREAM;
|
||||
}
|
||||
|
||||
void clearState(const Handle handle)
|
||||
{
|
||||
// Stop playing, and clear next buffer if any, cancel ongoing decoding
|
||||
setCommand(handle, STOP, 0);
|
||||
|
||||
MUTEX_LOCK(mutexBuffers);
|
||||
|
||||
Stream& stream = streams[handle];
|
||||
if (stream.nextBuffer != 0)
|
||||
{
|
||||
// Ignore any decoded buffer
|
||||
stream.nextBuffer = 0;
|
||||
}
|
||||
stream.cancelDecoding = true;
|
||||
stream.isPlaying = false;
|
||||
|
||||
MUTEX_UNLOCK(mutexBuffers);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif // TOUCHGFX_BUFFERPOOLVIDEOCONTROLLER_HPP
|
||||
@@ -0,0 +1,89 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* File Name : MJPEGDecoder.hpp
|
||||
******************************************************************************
|
||||
* This file is generated by TouchGFX Generator 4.26.0. Please, do not edit!
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2025 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
#ifndef TOUCHGFX_MJPEGDECODER_HPP
|
||||
#define TOUCHGFX_MJPEGDECODER_HPP
|
||||
|
||||
#include <touchgfx/hal/Types.hpp>
|
||||
#include <touchgfx/hal/VideoController.hpp>
|
||||
|
||||
class MJPEGDecoder
|
||||
{
|
||||
public:
|
||||
virtual ~MJPEGDecoder()
|
||||
{
|
||||
}
|
||||
|
||||
//Set video data for the decoder
|
||||
virtual void setVideoData(const uint8_t* movie, const uint32_t length) = 0;
|
||||
|
||||
//Set video data for the decoder
|
||||
virtual void setVideoData(touchgfx::VideoDataReader& reader) = 0;
|
||||
|
||||
/**
|
||||
* Check if MJPEGDecoder has a video.
|
||||
*
|
||||
* @return Returns true if the MJPEGDecoder has a video.
|
||||
*/
|
||||
virtual bool hasVideo() = 0;
|
||||
|
||||
//Increment position to next frame and decode and convert to RGB
|
||||
virtual bool decodeNextFrame(uint8_t* buffer, uint16_t width, uint16_t height, uint32_t stride) = 0;
|
||||
|
||||
//Increment position to next frame and decode. Used with decodeFrame.
|
||||
virtual bool gotoNextFrame() = 0;
|
||||
|
||||
//Decode part of the current frame, framebuffer is locked, area is drawn relative to frameBuffer
|
||||
virtual bool decodeFrame(const touchgfx::Rect& area, uint8_t* frameBuffer, uint32_t framebufferStride) = 0;
|
||||
|
||||
//Decode thumbnail, assumes buffer stride is width
|
||||
virtual bool decodeThumbnail(uint32_t frameno, uint8_t* buffer, uint16_t width, uint16_t height) = 0;
|
||||
|
||||
//Set current frame number
|
||||
virtual void gotoFrame(uint32_t frameno) = 0;
|
||||
|
||||
//Get current frame number
|
||||
virtual uint32_t getCurrentFrameNumber() const = 0;
|
||||
|
||||
//Get number of frames in video
|
||||
virtual uint32_t getNumberOfFrames() = 0;
|
||||
|
||||
//Read video information
|
||||
virtual void getVideoInfo(touchgfx::VideoInformation* data) = 0;
|
||||
|
||||
enum AVIErrors
|
||||
{
|
||||
AVI_NO_ERROR,
|
||||
AVI_NO_BUFFERS,
|
||||
AVI_NO_FILE,
|
||||
AVI_ERROR_NOT_RIFF,
|
||||
AVI_ERROR_AVI_HEADER_NOT_FOUND,
|
||||
AVI_ERROR_AVI_LIST_NOT_FOUND,
|
||||
AVI_ERROR_AVI_HDRL_NOT_FOUND,
|
||||
AVI_ERROR_AVI_AVIH_NOT_FOUND,
|
||||
AVI_ERROR_AVI_HEADER_TO_SHORT, //not full header provided
|
||||
AVI_ERROR_FILE_BUFFER_TO_SMALL,
|
||||
AVI_ERROR_MOVI_NOT_FOUND,
|
||||
AVI_ERROR_IDX1_NOT_FOUND,
|
||||
AVI_ERROR_FRAMENO_TO_HIGH,
|
||||
AVI_ERROR_EOF_REACHED
|
||||
};
|
||||
|
||||
AVIErrors virtual getLastError() = 0;
|
||||
};
|
||||
|
||||
#endif // TOUCHGFX_MJPEGDECODER_HPP
|
||||
156
P7_SETR2/P7_SMT4497/TouchGFX/target/generated/OSWrappers.cpp
Normal file
156
P7_SETR2/P7_SMT4497/TouchGFX/target/generated/OSWrappers.cpp
Normal file
@@ -0,0 +1,156 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* File Name : OSWrappers.cpp
|
||||
******************************************************************************
|
||||
* This file is generated by TouchGFX Generator 4.26.0. Please, do not edit!
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2025 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include <touchgfx/hal/HAL.hpp>
|
||||
#include <touchgfx/hal/OSWrappers.hpp>
|
||||
|
||||
#include <cmsis_os2.h>
|
||||
#include <cassert>
|
||||
|
||||
static osSemaphoreId_t frame_buffer_sem = NULL;
|
||||
static osMessageQueueId_t vsync_queue = NULL;
|
||||
|
||||
// Just a dummy value to insert in the VSYNC queue.
|
||||
static uint32_t dummy = 0x5a;
|
||||
|
||||
using namespace touchgfx;
|
||||
|
||||
/*
|
||||
* Initialize frame buffer semaphore and queue/mutex for VSYNC signal.
|
||||
*/
|
||||
void OSWrappers::initialize()
|
||||
{
|
||||
// Create a queue of length 1
|
||||
frame_buffer_sem = osSemaphoreNew(1, 1, NULL); // Binary semaphore
|
||||
assert((frame_buffer_sem != NULL) && "Creation of framebuffer semaphore failed");
|
||||
|
||||
// Create a queue of length 1
|
||||
vsync_queue = osMessageQueueNew(1, 4, NULL);
|
||||
assert((vsync_queue != NULL) && "Creation of vsync message queue failed");
|
||||
}
|
||||
|
||||
/*
|
||||
* Take the frame buffer semaphore. Blocks until semaphore is available.
|
||||
*/
|
||||
void OSWrappers::takeFrameBufferSemaphore()
|
||||
{
|
||||
osSemaphoreAcquire(frame_buffer_sem, osWaitForever);
|
||||
}
|
||||
|
||||
/*
|
||||
* Release the frame buffer semaphore.
|
||||
*/
|
||||
void OSWrappers::giveFrameBufferSemaphore()
|
||||
{
|
||||
osSemaphoreRelease(frame_buffer_sem);
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempt to obtain the frame buffer semaphore. If semaphore is not available, do
|
||||
* nothing.
|
||||
*
|
||||
* Note must return immediately! This function does not care who has the taken the semaphore,
|
||||
* it only serves to make sure that the semaphore is taken by someone.
|
||||
*/
|
||||
void OSWrappers::tryTakeFrameBufferSemaphore()
|
||||
{
|
||||
osSemaphoreAcquire(frame_buffer_sem, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Release the frame buffer semaphore in a way that is safe in interrupt context. Called
|
||||
* from ISR.
|
||||
*
|
||||
* Release the frame buffer semaphore in a way that is safe in interrupt context.
|
||||
* Called from ISR.
|
||||
*/
|
||||
void OSWrappers::giveFrameBufferSemaphoreFromISR()
|
||||
{
|
||||
osSemaphoreRelease(frame_buffer_sem);
|
||||
}
|
||||
|
||||
/*
|
||||
* Signal that a VSYNC has occurred. Should make the vsync queue/mutex available.
|
||||
*
|
||||
* Note This function is called from an ISR, and should (depending on OS) trigger a
|
||||
* scheduling.
|
||||
*/
|
||||
void OSWrappers::signalVSync()
|
||||
{
|
||||
osMessageQueuePut(vsync_queue, &dummy, 0, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Signal that the rendering of the frame has completed. Used by
|
||||
* some systems to avoid using any previous vsync.
|
||||
*/
|
||||
void OSWrappers::signalRenderingDone()
|
||||
{
|
||||
// Empty implementation for CMSIS V2
|
||||
}
|
||||
|
||||
/*
|
||||
* This function blocks until a VSYNC occurs.
|
||||
*
|
||||
* Note This function must first clear the mutex/queue and then wait for the next one to
|
||||
* occur.
|
||||
*/
|
||||
void OSWrappers::waitForVSync()
|
||||
{
|
||||
uint32_t dummyGet;
|
||||
// First make sure the queue is empty, by trying to remove an element with 0 timeout.
|
||||
osMessageQueueGet(vsync_queue, &dummyGet, 0, 0);
|
||||
|
||||
// Then, wait for next VSYNC to occur.
|
||||
osMessageQueueGet(vsync_queue, &dummyGet, 0, osWaitForever);
|
||||
}
|
||||
|
||||
/*
|
||||
* A function that causes executing task to sleep for a number of milliseconds.
|
||||
*
|
||||
* A function that causes executing task to sleep for a number of milliseconds.
|
||||
* This function is OPTIONAL. It is only used by the TouchGFX in the case of
|
||||
* a specific frame refresh strategy (REFRESH_STRATEGY_OPTIM_SINGLE_BUFFER_TFT_CTRL).
|
||||
* Due to backwards compatibility, in order for this function to be useable by the HAL
|
||||
* the function must be explicitly registered:
|
||||
* hal.registerTaskDelayFunction(&OSWrappers::taskDelay)
|
||||
*
|
||||
* see HAL::setFrameRefreshStrategy(FrameRefreshStrategy s)
|
||||
* see HAL::registerTaskDelayFunction(void (*delayF)(uint16_t))
|
||||
*/
|
||||
void OSWrappers::taskDelay(uint16_t ms)
|
||||
{
|
||||
osDelay(static_cast<uint32_t>(ms));
|
||||
}
|
||||
|
||||
/**
|
||||
* A function that causes the executing task to yield control to
|
||||
* another thread. This function is used by the framework when it
|
||||
* is necessary to wait a little before continuing (e.g. drawing).
|
||||
*
|
||||
* The implementation should typically request the operating
|
||||
* system to change to another task of similar priority. When
|
||||
* running without an operating system, the implementation can run
|
||||
* a very short task and return.
|
||||
*/
|
||||
void OSWrappers::taskYield()
|
||||
{
|
||||
osThreadYield();
|
||||
}
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
714
P7_SETR2/P7_SMT4497/TouchGFX/target/generated/STM32DMA.cpp
Normal file
714
P7_SETR2/P7_SMT4497/TouchGFX/target/generated/STM32DMA.cpp
Normal file
@@ -0,0 +1,714 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* File Name : STM32DMA.cpp
|
||||
******************************************************************************
|
||||
* This file is generated by TouchGFX Generator 4.26.0. Please, do not edit!
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2025 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "stm32f7xx_hal.h"
|
||||
#include "stm32f7xx_hal_dma2d.h"
|
||||
#include <STM32DMA.hpp>
|
||||
#include <cassert>
|
||||
#include <touchgfx/hal/HAL.hpp>
|
||||
#include <touchgfx/hal/Paint.hpp>
|
||||
|
||||
/* Makes touchgfx specific types and variables visible to this file */
|
||||
using namespace touchgfx;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const uint16_t format;
|
||||
const uint16_t size;
|
||||
const uint32_t* const data;
|
||||
} clutData_t;
|
||||
|
||||
extern "C" DMA2D_HandleTypeDef hdma2d;
|
||||
|
||||
extern "C" {
|
||||
static void DMA2D_XferCpltCallback(DMA2D_HandleTypeDef* handle)
|
||||
{
|
||||
(void)handle; // Unused argument
|
||||
HAL::getInstance()->signalDMAInterrupt();
|
||||
}
|
||||
|
||||
static void DMA2D_XferErrorCallback(DMA2D_HandleTypeDef* handle)
|
||||
{
|
||||
(void)handle; // Unused argument
|
||||
while (1)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
STM32DMA::STM32DMA()
|
||||
: DMA_Interface(dma_queue), dma_queue(queue_storage, sizeof(queue_storage) / sizeof(queue_storage[0]))
|
||||
{
|
||||
}
|
||||
|
||||
STM32DMA::~STM32DMA()
|
||||
{
|
||||
/* Disable DMA2D global Interrupt */
|
||||
NVIC_DisableIRQ(DMA2D_IRQn);
|
||||
}
|
||||
|
||||
void STM32DMA::initialize()
|
||||
{
|
||||
/* Ensure DMA2D Clock is enabled */
|
||||
__HAL_RCC_DMA2D_CLK_ENABLE();
|
||||
__HAL_RCC_DMA2D_FORCE_RESET();
|
||||
__HAL_RCC_DMA2D_RELEASE_RESET();
|
||||
|
||||
/* Add transfer error callback function */
|
||||
hdma2d.XferErrorCallback = DMA2D_XferErrorCallback;
|
||||
|
||||
/* Add transfer complete callback function */
|
||||
hdma2d.XferCpltCallback = DMA2D_XferCpltCallback;
|
||||
|
||||
/* Enable DMA2D global Interrupt */
|
||||
NVIC_EnableIRQ(DMA2D_IRQn);
|
||||
}
|
||||
|
||||
inline uint32_t STM32DMA::getChromARTInputFormat(Bitmap::BitmapFormat format)
|
||||
{
|
||||
// Default color mode set to ARGB8888
|
||||
uint32_t dma2dColorMode = DMA2D_INPUT_ARGB8888;
|
||||
|
||||
switch (format)
|
||||
{
|
||||
case Bitmap::ARGB8888: /* DMA2D input mode set to 32bit ARGB */
|
||||
dma2dColorMode = DMA2D_INPUT_ARGB8888;
|
||||
break;
|
||||
case Bitmap::RGB888: /* DMA2D input mode set to 24bit RGB */
|
||||
dma2dColorMode = DMA2D_INPUT_RGB888;
|
||||
break;
|
||||
case Bitmap::RGB565: /* DMA2D input mode set to 16bit RGB */
|
||||
dma2dColorMode = DMA2D_INPUT_RGB565;
|
||||
break;
|
||||
case Bitmap::ARGB2222: /* Fall through */
|
||||
case Bitmap::ABGR2222: /* Fall through */
|
||||
case Bitmap::RGBA2222: /* Fall through */
|
||||
case Bitmap::BGRA2222: /* Fall through */
|
||||
case Bitmap::L8: /* DMA2D input mode set to 8bit Color Look up table*/
|
||||
dma2dColorMode = DMA2D_INPUT_L8;
|
||||
break;
|
||||
case Bitmap::BW: /* Fall through */
|
||||
case Bitmap::BW_RLE: /* Fall through */
|
||||
case Bitmap::GRAY4: /* Fall through */
|
||||
case Bitmap::GRAY2: /* Fall through */
|
||||
default: /* Unsupported input format for DMA2D */
|
||||
assert(0 && "Unsupported Format!");
|
||||
break;
|
||||
}
|
||||
|
||||
return dma2dColorMode;
|
||||
}
|
||||
|
||||
inline uint32_t STM32DMA::getChromARTOutputFormat(Bitmap::BitmapFormat format)
|
||||
{
|
||||
// Default color mode set to ARGB8888
|
||||
uint32_t dma2dColorMode = DMA2D_OUTPUT_ARGB8888;
|
||||
|
||||
switch (format)
|
||||
{
|
||||
case Bitmap::ARGB8888: /* DMA2D output mode set to 32bit ARGB */
|
||||
dma2dColorMode = DMA2D_OUTPUT_ARGB8888;
|
||||
break;
|
||||
case Bitmap::RGB888: /* Fall through */
|
||||
case Bitmap::ARGB2222: /* Fall through */
|
||||
case Bitmap::ABGR2222: /* Fall through */
|
||||
case Bitmap::RGBA2222: /* Fall through */
|
||||
case Bitmap::BGRA2222: /* DMA2D output mode set to 24bit RGB */
|
||||
dma2dColorMode = DMA2D_OUTPUT_RGB888;
|
||||
break;
|
||||
case Bitmap::RGB565: /* DMA2D output mode set to 16bit RGB */
|
||||
dma2dColorMode = DMA2D_OUTPUT_RGB565;
|
||||
break;
|
||||
case Bitmap::L8: /* Fall through */
|
||||
case Bitmap::BW: /* Fall through */
|
||||
case Bitmap::BW_RLE: /* Fall through */
|
||||
case Bitmap::GRAY4: /* Fall through */
|
||||
case Bitmap::GRAY2: /* Fall through */
|
||||
default: /* Unsupported output format for DMA2D */
|
||||
assert(0 && "Unsupported Format!");
|
||||
break;
|
||||
}
|
||||
|
||||
return dma2dColorMode;
|
||||
}
|
||||
|
||||
BlitOperations STM32DMA::getBlitCaps()
|
||||
{
|
||||
return static_cast<BlitOperations>(BLIT_OP_FILL
|
||||
| BLIT_OP_FILL_WITH_ALPHA
|
||||
| BLIT_OP_COPY
|
||||
| BLIT_OP_COPY_L8
|
||||
| BLIT_OP_COPY_WITH_ALPHA
|
||||
| BLIT_OP_COPY_ARGB8888
|
||||
| BLIT_OP_COPY_ARGB8888_WITH_ALPHA
|
||||
| BLIT_OP_COPY_A4
|
||||
| BLIT_OP_COPY_A8);
|
||||
}
|
||||
|
||||
/*
|
||||
* void STM32DMA::setupDataCopy(const BlitOp& blitOp) handles blit operation of
|
||||
* BLIT_OP_COPY
|
||||
* BLIT_OP_COPY_L8
|
||||
* BLIT_OP_COPY_WITH_ALPHA
|
||||
* BLIT_OP_COPY_ARGB8888
|
||||
* BLIT_OP_COPY_ARGB8888_WITH_ALPHA
|
||||
* BLIT_OP_COPY_A4
|
||||
* BLIT_OP_COPY_A8
|
||||
*/
|
||||
void STM32DMA::setupDataCopy(const BlitOp& blitOp)
|
||||
{
|
||||
uint32_t dma2dForegroundColorMode = getChromARTInputFormat(static_cast<Bitmap::BitmapFormat>(blitOp.srcFormat));
|
||||
uint32_t dma2dBackgroundColorMode = getChromARTInputFormat(static_cast<Bitmap::BitmapFormat>(blitOp.dstFormat));
|
||||
uint32_t dma2dOutputColorMode = getChromARTOutputFormat(static_cast<Bitmap::BitmapFormat>(blitOp.dstFormat));
|
||||
|
||||
/* DMA2D OOR register configuration */
|
||||
WRITE_REG(DMA2D->OOR, blitOp.dstLoopStride - blitOp.nSteps);
|
||||
|
||||
/* DMA2D BGOR register configuration */
|
||||
WRITE_REG(DMA2D->BGOR, blitOp.dstLoopStride - blitOp.nSteps);
|
||||
|
||||
/* DMA2D FGOR register configuration */
|
||||
WRITE_REG(DMA2D->FGOR, blitOp.srcLoopStride - blitOp.nSteps);
|
||||
|
||||
/* DMA2D OPFCCR register configuration */
|
||||
WRITE_REG(DMA2D->OPFCCR, dma2dOutputColorMode);
|
||||
|
||||
/* Configure DMA2D data size */
|
||||
WRITE_REG(DMA2D->NLR, (blitOp.nLoops | (blitOp.nSteps << DMA2D_NLR_PL_Pos)));
|
||||
|
||||
/* Configure DMA2D destination address */
|
||||
WRITE_REG(DMA2D->OMAR, reinterpret_cast<uint32_t>(blitOp.pDst));
|
||||
|
||||
/* Configure DMA2D source address */
|
||||
WRITE_REG(DMA2D->FGMAR, reinterpret_cast<uint32_t>(blitOp.pSrc));
|
||||
|
||||
switch (blitOp.operation)
|
||||
{
|
||||
case BLIT_OP_COPY_A4:
|
||||
/* Set DMA2D color mode and alpha mode */
|
||||
WRITE_REG(DMA2D->FGPFCCR, DMA2D_INPUT_A4 | (DMA2D_COMBINE_ALPHA << DMA2D_FGPFCCR_AM_Pos) | (blitOp.alpha << 24));
|
||||
|
||||
/* set DMA2D foreground color */
|
||||
WRITE_REG(DMA2D->FGCOLR, blitOp.color);
|
||||
|
||||
/* Write DMA2D BGPFCCR register */
|
||||
WRITE_REG(DMA2D->BGPFCCR, dma2dBackgroundColorMode | (DMA2D_NO_MODIF_ALPHA << DMA2D_BGPFCCR_AM_Pos));
|
||||
|
||||
/* Configure DMA2D Stream source2 address */
|
||||
WRITE_REG(DMA2D->BGMAR, reinterpret_cast<uint32_t>(blitOp.pDst));
|
||||
|
||||
/* Set DMA2D mode */
|
||||
WRITE_REG(DMA2D->CR, DMA2D_M2M_BLEND | DMA2D_IT_TC | DMA2D_CR_START | DMA2D_IT_CE | DMA2D_IT_TE);
|
||||
break;
|
||||
case BLIT_OP_COPY_A8:
|
||||
/* Set DMA2D color mode and alpha mode */
|
||||
WRITE_REG(DMA2D->FGPFCCR, DMA2D_INPUT_A8 | (DMA2D_COMBINE_ALPHA << DMA2D_FGPFCCR_AM_Pos) | (blitOp.alpha << 24));
|
||||
|
||||
/* set DMA2D foreground color */
|
||||
WRITE_REG(DMA2D->FGCOLR, blitOp.color);
|
||||
|
||||
/* Write DMA2D BGPFCCR register */
|
||||
WRITE_REG(DMA2D->BGPFCCR, dma2dBackgroundColorMode | (DMA2D_NO_MODIF_ALPHA << DMA2D_BGPFCCR_AM_Pos));
|
||||
|
||||
/* Configure DMA2D Stream source2 address */
|
||||
WRITE_REG(DMA2D->BGMAR, reinterpret_cast<uint32_t>(blitOp.pDst));
|
||||
|
||||
/* Set DMA2D mode */
|
||||
WRITE_REG(DMA2D->CR, DMA2D_M2M_BLEND | DMA2D_IT_TC | DMA2D_CR_START | DMA2D_IT_CE | DMA2D_IT_TE);
|
||||
break;
|
||||
case BLIT_OP_COPY_WITH_ALPHA:
|
||||
/* Set DMA2D color mode and alpha mode */
|
||||
WRITE_REG(DMA2D->FGPFCCR, dma2dForegroundColorMode | (DMA2D_COMBINE_ALPHA << DMA2D_FGPFCCR_AM_Pos) | (blitOp.alpha << 24));
|
||||
|
||||
/* Write DMA2D BGPFCCR register */
|
||||
WRITE_REG(DMA2D->BGPFCCR, dma2dBackgroundColorMode | (DMA2D_NO_MODIF_ALPHA << DMA2D_BGPFCCR_AM_Pos));
|
||||
|
||||
/* Configure DMA2D Stream source2 address */
|
||||
WRITE_REG(DMA2D->BGMAR, reinterpret_cast<uint32_t>(blitOp.pDst));
|
||||
|
||||
/* Set DMA2D mode */
|
||||
WRITE_REG(DMA2D->CR, DMA2D_M2M_BLEND | DMA2D_IT_TC | DMA2D_CR_START | DMA2D_IT_CE | DMA2D_IT_TE);
|
||||
break;
|
||||
case BLIT_OP_COPY_L8:
|
||||
{
|
||||
bool blend = true;
|
||||
const clutData_t* const palette = reinterpret_cast<const clutData_t*>(blitOp.pClut);
|
||||
|
||||
/* Write foreground CLUT memory address */
|
||||
WRITE_REG(DMA2D->FGCMAR, reinterpret_cast<uint32_t>(&palette->data));
|
||||
|
||||
/* Set DMA2D color mode and alpha mode */
|
||||
WRITE_REG(DMA2D->FGPFCCR, dma2dForegroundColorMode | (DMA2D_COMBINE_ALPHA << DMA2D_FGPFCCR_AM_Pos) | (blitOp.alpha << 24));
|
||||
|
||||
/* Write DMA2D BGPFCCR register */
|
||||
WRITE_REG(DMA2D->BGPFCCR, dma2dBackgroundColorMode | (DMA2D_NO_MODIF_ALPHA << DMA2D_BGPFCCR_AM_Pos));
|
||||
|
||||
/* Configure DMA2D Stream source2 address */
|
||||
WRITE_REG(DMA2D->BGMAR, reinterpret_cast<uint32_t>(blitOp.pDst));
|
||||
|
||||
/* Configure CLUT */
|
||||
switch ((Bitmap::ClutFormat)palette->format)
|
||||
{
|
||||
case Bitmap::CLUT_FORMAT_L8_ARGB8888:
|
||||
/* Write foreground CLUT size and CLUT color mode */
|
||||
MODIFY_REG(DMA2D->FGPFCCR, (DMA2D_FGPFCCR_CS | DMA2D_FGPFCCR_CCM), (((palette->size - 1) << DMA2D_FGPFCCR_CS_Pos) | (DMA2D_CCM_ARGB8888 << DMA2D_FGPFCCR_CCM_Pos)));
|
||||
break;
|
||||
case Bitmap::CLUT_FORMAT_L8_RGB888:
|
||||
if (blitOp.alpha == 255)
|
||||
{
|
||||
blend = false;
|
||||
}
|
||||
MODIFY_REG(DMA2D->FGPFCCR, (DMA2D_FGPFCCR_CS | DMA2D_FGPFCCR_CCM), (((palette->size - 1) << DMA2D_FGPFCCR_CS_Pos) | (DMA2D_CCM_RGB888 << DMA2D_FGPFCCR_CCM_Pos)));
|
||||
break;
|
||||
|
||||
case Bitmap::CLUT_FORMAT_L8_RGB565:
|
||||
default:
|
||||
assert(0 && "Unsupported format");
|
||||
break;
|
||||
}
|
||||
|
||||
/* Enable the CLUT loading for the foreground */
|
||||
SET_BIT(DMA2D->FGPFCCR, DMA2D_FGPFCCR_START);
|
||||
|
||||
while ((READ_REG(DMA2D->FGPFCCR) & DMA2D_FGPFCCR_START) != 0U)
|
||||
{
|
||||
}
|
||||
DMA2D->IFCR = (DMA2D_FLAG_CTC);
|
||||
|
||||
/* Set DMA2D mode */
|
||||
if (blend)
|
||||
{
|
||||
WRITE_REG(DMA2D->CR, DMA2D_M2M_BLEND | DMA2D_IT_TC | DMA2D_CR_START | DMA2D_IT_CE | DMA2D_IT_TE);
|
||||
}
|
||||
else
|
||||
{
|
||||
WRITE_REG(DMA2D->CR, DMA2D_M2M_PFC | DMA2D_IT_TC | DMA2D_CR_START | DMA2D_IT_CE | DMA2D_IT_TE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case BLIT_OP_COPY_ARGB8888:
|
||||
case BLIT_OP_COPY_ARGB8888_WITH_ALPHA:
|
||||
/* Set DMA2D color mode and alpha mode */
|
||||
WRITE_REG(DMA2D->FGPFCCR, dma2dForegroundColorMode | (DMA2D_COMBINE_ALPHA << DMA2D_FGPFCCR_AM_Pos) | (blitOp.alpha << 24));
|
||||
|
||||
/* Write DMA2D BGPFCCR register */
|
||||
WRITE_REG(DMA2D->BGPFCCR, dma2dBackgroundColorMode | (DMA2D_NO_MODIF_ALPHA << DMA2D_BGPFCCR_AM_Pos));
|
||||
|
||||
/* Configure DMA2D Stream source2 address */
|
||||
WRITE_REG(DMA2D->BGMAR, reinterpret_cast<uint32_t>(blitOp.pDst));
|
||||
|
||||
/* Set DMA2D mode */
|
||||
WRITE_REG(DMA2D->CR, DMA2D_M2M_BLEND | DMA2D_IT_TC | DMA2D_CR_START | DMA2D_IT_CE | DMA2D_IT_TE);
|
||||
break;
|
||||
default: /* BLIT_OP_COPY */
|
||||
/* Set DMA2D color mode and alpha mode */
|
||||
WRITE_REG(DMA2D->FGPFCCR, dma2dForegroundColorMode | (DMA2D_COMBINE_ALPHA << DMA2D_FGPFCCR_AM_Pos) | (blitOp.alpha << 24));
|
||||
|
||||
/* Perform pixel-format-conversion (PFC) If Bitmap format is not same format as framebuffer format */
|
||||
if (blitOp.srcFormat != blitOp.dstFormat)
|
||||
{
|
||||
/* Start DMA2D : PFC Mode */
|
||||
WRITE_REG(DMA2D->CR, DMA2D_M2M_PFC | DMA2D_IT_TC | DMA2D_CR_START | DMA2D_IT_CE | DMA2D_IT_TE);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Start DMA2D : M2M Mode */
|
||||
WRITE_REG(DMA2D->CR, DMA2D_M2M | DMA2D_IT_TC | DMA2D_CR_START | DMA2D_IT_CE | DMA2D_IT_TE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* void STM32DMA::setupDataFill(const BlitOp& blitOp) handles blit operation of
|
||||
* BLIT_OP_FILL
|
||||
* BLIT_OP_FILL_WITH_ALPHA
|
||||
*/
|
||||
void STM32DMA::setupDataFill(const BlitOp& blitOp)
|
||||
{
|
||||
uint32_t dma2dOutputColorMode = getChromARTOutputFormat(static_cast<Bitmap::BitmapFormat>(blitOp.dstFormat));
|
||||
|
||||
/* DMA2D OPFCCR register configuration */
|
||||
WRITE_REG(DMA2D->OPFCCR, dma2dOutputColorMode);
|
||||
|
||||
/* Configure DMA2D data size */
|
||||
WRITE_REG(DMA2D->NLR, (blitOp.nLoops | (blitOp.nSteps << DMA2D_NLR_PL_Pos)));
|
||||
|
||||
/* Configure DMA2D destination address */
|
||||
WRITE_REG(DMA2D->OMAR, reinterpret_cast<uint32_t>(blitOp.pDst));
|
||||
|
||||
/* DMA2D OOR register configuration */
|
||||
WRITE_REG(DMA2D->OOR, blitOp.dstLoopStride - blitOp.nSteps);
|
||||
|
||||
if (blitOp.operation == BLIT_OP_FILL_WITH_ALPHA)
|
||||
{
|
||||
/* DMA2D BGOR register configuration */
|
||||
WRITE_REG(DMA2D->BGOR, blitOp.dstLoopStride - blitOp.nSteps);
|
||||
|
||||
/* DMA2D FGOR register configuration */
|
||||
WRITE_REG(DMA2D->FGOR, blitOp.dstLoopStride - blitOp.nSteps);
|
||||
|
||||
/* Write DMA2D BGPFCCR register */
|
||||
WRITE_REG(DMA2D->BGPFCCR, dma2dOutputColorMode | (DMA2D_NO_MODIF_ALPHA << DMA2D_BGPFCCR_AM_Pos));
|
||||
|
||||
/* Write DMA2D FGPFCCR register */
|
||||
WRITE_REG(DMA2D->FGPFCCR, DMA2D_INPUT_A8 | (DMA2D_REPLACE_ALPHA << DMA2D_FGPFCCR_AM_Pos) | ((blitOp.alpha << 24) & DMA2D_FGPFCCR_ALPHA));
|
||||
|
||||
/* DMA2D FGCOLR register configuration */
|
||||
WRITE_REG(DMA2D->FGCOLR, blitOp.color);
|
||||
|
||||
/* Configure DMA2D Stream source2 address */
|
||||
WRITE_REG(DMA2D->BGMAR, reinterpret_cast<uint32_t>(blitOp.pDst));
|
||||
|
||||
/* Configure DMA2D source address */
|
||||
WRITE_REG(DMA2D->FGMAR, reinterpret_cast<uint32_t>(blitOp.pDst));
|
||||
|
||||
/* Enable the Peripheral and Enable the transfer complete interrupt */
|
||||
WRITE_REG(DMA2D->CR, (DMA2D_IT_TC | DMA2D_CR_START | DMA2D_M2M_BLEND | DMA2D_IT_CE | DMA2D_IT_TE));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Write DMA2D FGPFCCR register */
|
||||
WRITE_REG(DMA2D->FGPFCCR, dma2dOutputColorMode | (DMA2D_NO_MODIF_ALPHA << DMA2D_FGPFCCR_AM_Pos));
|
||||
|
||||
/* DMA2D FGOR register configuration */
|
||||
WRITE_REG(DMA2D->FGOR, 0);
|
||||
|
||||
/* Set color */
|
||||
WRITE_REG(DMA2D->OCOLR, blitOp.color);
|
||||
|
||||
/* Enable the Peripheral and Enable the transfer complete interrupt */
|
||||
WRITE_REG(DMA2D->CR, (DMA2D_IT_TC | DMA2D_CR_START | DMA2D_R2M | DMA2D_IT_CE | DMA2D_IT_TE));
|
||||
}
|
||||
}
|
||||
|
||||
namespace touchgfx
|
||||
{
|
||||
namespace paint
|
||||
{
|
||||
namespace
|
||||
{
|
||||
const clutData_t* L8CLUT = 0;
|
||||
uint32_t L8ClutLoaded = 0;
|
||||
} // namespace
|
||||
|
||||
void setL8Palette(const uint8_t* const data)
|
||||
{
|
||||
L8CLUT = reinterpret_cast<const clutData_t*>(data - offsetof(clutData_t, data));
|
||||
L8ClutLoaded = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @fn void tearDown();
|
||||
*
|
||||
* @brief Waits until previous DMA drawing operation has finished
|
||||
*/
|
||||
void tearDown()
|
||||
{
|
||||
/* Wait for DMA2D to finish last run */
|
||||
while ((READ_REG(DMA2D->CR) & DMA2D_CR_START) != 0U);
|
||||
|
||||
/* Clear transfer flags */
|
||||
WRITE_REG(DMA2D->IFCR, DMA2D_FLAG_TC | DMA2D_FLAG_CE | DMA2D_FLAG_TE);
|
||||
}
|
||||
|
||||
/** Flushes a line of pixels in the data cache if used.
|
||||
*
|
||||
* @brief Flushes decoded RGB pixels when rendering compressed images
|
||||
*/
|
||||
void flushLine(uint32_t* addr, int sizebytes)
|
||||
{
|
||||
// This function is used when decompressing data to flush
|
||||
// the currently decoded data in the cache to allow the DMA2D
|
||||
// to blend the pixels correctly.
|
||||
if (SCB->CCR & SCB_CCR_DC_Msk)
|
||||
{
|
||||
SCB_CleanDCache_by_Addr(addr, sizebytes);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @fn void invalidateTextureCache();
|
||||
*
|
||||
* @brief Flushes the data cache if used.
|
||||
*/
|
||||
void invalidateTextureCache()
|
||||
{
|
||||
}
|
||||
|
||||
namespace rgb565
|
||||
{
|
||||
/**
|
||||
* @fn void lineFromColor();
|
||||
*
|
||||
* @brief Renders Canvas Widget chunks using DMA.
|
||||
* This functions will not generate an interrupt, and will not affect the DMA queue.
|
||||
*/
|
||||
void lineFromColor(uint16_t* const ptr, const unsigned count, const uint32_t color, const uint8_t alpha, const uint32_t color565)
|
||||
{
|
||||
/* Wait for DMA2D to finish last run */
|
||||
while ((READ_REG(DMA2D->CR) & DMA2D_CR_START) != 0U);
|
||||
|
||||
/* Clear transfer flags */
|
||||
WRITE_REG(DMA2D->IFCR, DMA2D_FLAG_TC | DMA2D_FLAG_CE | DMA2D_FLAG_TE);
|
||||
|
||||
/* DMA2D OPFCCR register configuration */
|
||||
WRITE_REG(DMA2D->OPFCCR, DMA2D_OUTPUT_RGB565);
|
||||
|
||||
/* Configure DMA2D data size */
|
||||
WRITE_REG(DMA2D->NLR, (1 | (count << DMA2D_NLR_PL_Pos)));
|
||||
|
||||
/* Configure DMA2D destination address */
|
||||
WRITE_REG(DMA2D->OMAR, reinterpret_cast<uint32_t>(ptr));
|
||||
|
||||
if (alpha < 0xFF)
|
||||
{
|
||||
/* Write DMA2D BGPFCCR register */
|
||||
WRITE_REG(DMA2D->BGPFCCR, DMA2D_OUTPUT_RGB565 | (DMA2D_NO_MODIF_ALPHA << DMA2D_BGPFCCR_AM_Pos));
|
||||
|
||||
/* Write DMA2D FGPFCCR register */
|
||||
WRITE_REG(DMA2D->FGPFCCR, DMA2D_INPUT_A8 | (DMA2D_REPLACE_ALPHA << DMA2D_FGPFCCR_AM_Pos) | (alpha << DMA2D_FGPFCCR_ALPHA_Pos));
|
||||
|
||||
/* DMA2D FGCOLR register configuration */
|
||||
WRITE_REG(DMA2D->FGCOLR, color);
|
||||
|
||||
/* Configure DMA2D Stream source2 address */
|
||||
WRITE_REG(DMA2D->BGMAR, (uint32_t)ptr);
|
||||
|
||||
/* Configure DMA2D source address */
|
||||
WRITE_REG(DMA2D->FGMAR, (uint32_t)ptr);
|
||||
|
||||
/* Enable the Peripheral and Enable the transfer complete interrupt */
|
||||
WRITE_REG(DMA2D->CR, (DMA2D_CR_START | DMA2D_M2M_BLEND));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Write DMA2D FGPFCCR register */
|
||||
WRITE_REG(DMA2D->FGPFCCR, DMA2D_OUTPUT_RGB565 | (DMA2D_NO_MODIF_ALPHA << DMA2D_FGPFCCR_AM_Pos));
|
||||
|
||||
/* Set color */
|
||||
WRITE_REG(DMA2D->OCOLR, color565);
|
||||
|
||||
/* Enable the Peripheral and Enable the transfer complete interrupt */
|
||||
WRITE_REG(DMA2D->CR, (DMA2D_CR_START | DMA2D_R2M));
|
||||
}
|
||||
}
|
||||
|
||||
void lineFromRGB565(uint16_t* const ptr, const uint16_t* const data, const unsigned count, const uint8_t alpha)
|
||||
{
|
||||
/* Wait for DMA2D to finish last run */
|
||||
while ((READ_REG(DMA2D->CR) & DMA2D_CR_START) != 0U);
|
||||
|
||||
/* Clear transfer flags */
|
||||
WRITE_REG(DMA2D->IFCR, DMA2D_FLAG_TC | DMA2D_FLAG_CE | DMA2D_FLAG_TE);
|
||||
|
||||
/* DMA2D OPFCCR register configuration */
|
||||
WRITE_REG(DMA2D->OPFCCR, DMA2D_OUTPUT_RGB565);
|
||||
|
||||
/* Configure DMA2D data size */
|
||||
WRITE_REG(DMA2D->NLR, (1 | (count << DMA2D_NLR_PL_Pos)));
|
||||
|
||||
/* Configure DMA2D destination address */
|
||||
WRITE_REG(DMA2D->OMAR, reinterpret_cast<uint32_t>(ptr));
|
||||
|
||||
/* Configure DMA2D source address */
|
||||
WRITE_REG(DMA2D->FGMAR, reinterpret_cast<uint32_t>(data));
|
||||
|
||||
if (alpha < 0xFF)
|
||||
{
|
||||
/* Set DMA2D color mode and alpha mode */
|
||||
WRITE_REG(DMA2D->FGPFCCR, DMA2D_INPUT_RGB565 | (DMA2D_COMBINE_ALPHA << DMA2D_FGPFCCR_AM_Pos) | (alpha << DMA2D_FGPFCCR_ALPHA_Pos));
|
||||
|
||||
/* Write DMA2D BGPFCCR register */
|
||||
WRITE_REG(DMA2D->BGPFCCR, DMA2D_INPUT_RGB565 | (DMA2D_NO_MODIF_ALPHA << DMA2D_BGPFCCR_AM_Pos));
|
||||
|
||||
/* Configure DMA2D Stream source2 address */
|
||||
WRITE_REG(DMA2D->BGMAR, reinterpret_cast<uint32_t>(ptr));
|
||||
|
||||
/* Set DMA2D mode */
|
||||
WRITE_REG(DMA2D->CR, DMA2D_M2M_BLEND | DMA2D_CR_START);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set DMA2D color mode and alpha mode */
|
||||
WRITE_REG(DMA2D->FGPFCCR, DMA2D_INPUT_RGB565 | (DMA2D_COMBINE_ALPHA << DMA2D_FGPFCCR_AM_Pos) | (alpha << DMA2D_FGPFCCR_ALPHA_Pos));
|
||||
|
||||
/* Start DMA2D : M2M Mode */
|
||||
WRITE_REG(DMA2D->CR, DMA2D_M2M | DMA2D_CR_START);
|
||||
}
|
||||
}
|
||||
|
||||
void lineFromARGB8888(uint16_t* const ptr, const uint32_t* const data, const unsigned count, const uint8_t alpha)
|
||||
{
|
||||
/* Wait for DMA2D to finish last run */
|
||||
while ((READ_REG(DMA2D->CR) & DMA2D_CR_START) != 0U);
|
||||
|
||||
/* Clear transfer flags */
|
||||
WRITE_REG(DMA2D->IFCR, DMA2D_FLAG_TC | DMA2D_FLAG_CE | DMA2D_FLAG_TE);
|
||||
|
||||
/* DMA2D OPFCCR register configuration */
|
||||
WRITE_REG(DMA2D->OPFCCR, DMA2D_OUTPUT_RGB565);
|
||||
|
||||
/* Configure DMA2D data size */
|
||||
WRITE_REG(DMA2D->NLR, (1 | (count << DMA2D_NLR_PL_Pos)));
|
||||
|
||||
/* Configure DMA2D destination address */
|
||||
WRITE_REG(DMA2D->OMAR, reinterpret_cast<uint32_t>(ptr));
|
||||
|
||||
/* Configure DMA2D source address */
|
||||
WRITE_REG(DMA2D->FGMAR, reinterpret_cast<uint32_t>(data));
|
||||
|
||||
/* Set DMA2D color mode and alpha mode */
|
||||
WRITE_REG(DMA2D->FGPFCCR, DMA2D_INPUT_ARGB8888 | (DMA2D_COMBINE_ALPHA << DMA2D_FGPFCCR_AM_Pos) | (alpha << DMA2D_FGPFCCR_ALPHA_Pos));
|
||||
|
||||
/* Write DMA2D BGPFCCR register */
|
||||
WRITE_REG(DMA2D->BGPFCCR, DMA2D_INPUT_RGB565 | (DMA2D_NO_MODIF_ALPHA << DMA2D_BGPFCCR_AM_Pos));
|
||||
|
||||
/* Configure DMA2D Stream source2 address */
|
||||
WRITE_REG(DMA2D->BGMAR, reinterpret_cast<uint32_t>(ptr));
|
||||
|
||||
/* Set DMA2D mode */
|
||||
WRITE_REG(DMA2D->CR, DMA2D_M2M_BLEND | DMA2D_CR_START);
|
||||
}
|
||||
|
||||
void lineFromL8RGB888(uint16_t* const ptr, const uint8_t* const data, const unsigned count, const uint8_t alpha)
|
||||
{
|
||||
/* wait for DMA2D to finish last run */
|
||||
while ((READ_REG(DMA2D->CR) & DMA2D_CR_START) != 0U);
|
||||
|
||||
/* DMA2D OPFCCR register configuration */
|
||||
WRITE_REG(DMA2D->OPFCCR, DMA2D_OUTPUT_RGB565);
|
||||
|
||||
/* Configure DMA2D data size */
|
||||
WRITE_REG(DMA2D->NLR, (1 | (count << DMA2D_NLR_PL_Pos)));
|
||||
|
||||
/* Configure DMA2D destination address */
|
||||
WRITE_REG(DMA2D->OMAR, reinterpret_cast<uint32_t>(ptr));
|
||||
|
||||
/* Configure DMA2D source address */
|
||||
WRITE_REG(DMA2D->FGMAR, reinterpret_cast<uint32_t>(data));
|
||||
|
||||
/* Configure DMA2D Stream source2 address */
|
||||
WRITE_REG(DMA2D->BGMAR, reinterpret_cast<uint32_t>(ptr));
|
||||
|
||||
/* Load CLUT if not already loaded */
|
||||
if (L8ClutLoaded == 0)
|
||||
{
|
||||
/* Write foreground CLUT memory address */
|
||||
WRITE_REG(DMA2D->FGCMAR, reinterpret_cast<uint32_t>(&L8CLUT->data));
|
||||
|
||||
/* Set DMA2D color mode and alpha mode */
|
||||
WRITE_REG(DMA2D->FGPFCCR, DMA2D_INPUT_L8 | (DMA2D_COMBINE_ALPHA << DMA2D_FGPFCCR_AM_Pos) | (alpha << DMA2D_FGPFCCR_ALPHA_Pos));
|
||||
|
||||
MODIFY_REG(DMA2D->FGPFCCR, (DMA2D_FGPFCCR_CS | DMA2D_FGPFCCR_CCM), (((L8CLUT->size - 1) << DMA2D_FGPFCCR_CS_Pos) | (DMA2D_CCM_RGB888 << DMA2D_FGPFCCR_CCM_Pos)));
|
||||
|
||||
/* Enable the CLUT loading for the foreground */
|
||||
SET_BIT(DMA2D->FGPFCCR, DMA2D_FGPFCCR_START);
|
||||
|
||||
/* Write DMA2D BGPFCCR register */
|
||||
WRITE_REG(DMA2D->BGPFCCR, DMA2D_INPUT_RGB565 | (DMA2D_NO_MODIF_ALPHA << DMA2D_BGPFCCR_AM_Pos));
|
||||
|
||||
/* Mark CLUT loaded */
|
||||
L8ClutLoaded = 1;
|
||||
|
||||
/* Wait for load to finish */
|
||||
while ((READ_REG(DMA2D->FGPFCCR) & DMA2D_FGPFCCR_START) != 0U);
|
||||
|
||||
/* Clear CLUT Transfer Complete flag */
|
||||
DMA2D->IFCR = (DMA2D_FLAG_CTC);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set correct alpha for these pixels */
|
||||
MODIFY_REG(DMA2D->FGPFCCR, DMA2D_BGPFCCR_ALPHA_Msk, alpha << DMA2D_FGPFCCR_ALPHA_Pos);
|
||||
}
|
||||
|
||||
/* Start pixel transfer in correct mode */
|
||||
if (alpha < 0xFF)
|
||||
{
|
||||
/* Set DMA2D mode */
|
||||
WRITE_REG(DMA2D->CR, DMA2D_M2M_BLEND | DMA2D_CR_START);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set DMA2D mode */
|
||||
WRITE_REG(DMA2D->CR, DMA2D_M2M_PFC | DMA2D_CR_START);
|
||||
}
|
||||
}
|
||||
|
||||
void lineFromL8ARGB8888(uint16_t* const ptr, const uint8_t* const data, const unsigned count, const uint8_t alpha)
|
||||
{
|
||||
/* wait for DMA2D to finish last run */
|
||||
while ((READ_REG(DMA2D->CR) & DMA2D_CR_START) != 0U);
|
||||
|
||||
/* DMA2D OPFCCR register configuration */
|
||||
WRITE_REG(DMA2D->OPFCCR, DMA2D_OUTPUT_RGB565);
|
||||
|
||||
/* Configure DMA2D data size */
|
||||
WRITE_REG(DMA2D->NLR, (1 | (count << DMA2D_NLR_PL_Pos)));
|
||||
|
||||
/* Configure DMA2D destination address */
|
||||
WRITE_REG(DMA2D->OMAR, reinterpret_cast<uint32_t>(ptr));
|
||||
|
||||
/* Configure DMA2D source address */
|
||||
WRITE_REG(DMA2D->FGMAR, reinterpret_cast<uint32_t>(data));
|
||||
|
||||
/* Configure DMA2D Stream source2 address */
|
||||
WRITE_REG(DMA2D->BGMAR, reinterpret_cast<uint32_t>(ptr));
|
||||
|
||||
/* Load CLUT if not already loaded */
|
||||
if (L8ClutLoaded == 0)
|
||||
{
|
||||
/* Write foreground CLUT memory address */
|
||||
WRITE_REG(DMA2D->FGCMAR, reinterpret_cast<uint32_t>(&L8CLUT->data));
|
||||
|
||||
/* Set DMA2D color mode and alpha mode */
|
||||
WRITE_REG(DMA2D->FGPFCCR, DMA2D_INPUT_L8 | (DMA2D_COMBINE_ALPHA << DMA2D_FGPFCCR_AM_Pos) | (alpha << DMA2D_FGPFCCR_ALPHA_Pos));
|
||||
|
||||
MODIFY_REG(DMA2D->FGPFCCR, (DMA2D_FGPFCCR_CS | DMA2D_FGPFCCR_CCM), (((L8CLUT->size - 1) << DMA2D_FGPFCCR_CS_Pos) | (DMA2D_CCM_ARGB8888 << DMA2D_FGPFCCR_CCM_Pos)));
|
||||
|
||||
/* Enable the CLUT loading for the foreground */
|
||||
SET_BIT(DMA2D->FGPFCCR, DMA2D_FGPFCCR_START);
|
||||
|
||||
/* Write DMA2D BGPFCCR register */
|
||||
WRITE_REG(DMA2D->BGPFCCR, DMA2D_INPUT_RGB565 | (DMA2D_NO_MODIF_ALPHA << DMA2D_BGPFCCR_AM_Pos));
|
||||
|
||||
/* Mark CLUT loaded */
|
||||
L8ClutLoaded = 1;
|
||||
|
||||
/* Wait for load to finish */
|
||||
while ((READ_REG(DMA2D->FGPFCCR) & DMA2D_FGPFCCR_START) != 0U);
|
||||
|
||||
/* Clear CLUT Transfer Complete flag */
|
||||
DMA2D->IFCR = (DMA2D_FLAG_CTC);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set correct alpha for these pixels */
|
||||
MODIFY_REG(DMA2D->FGPFCCR, DMA2D_BGPFCCR_ALPHA_Msk, alpha << DMA2D_FGPFCCR_ALPHA_Pos);
|
||||
}
|
||||
|
||||
/* Start pixel transfer in blending mode */
|
||||
WRITE_REG(DMA2D->CR, DMA2D_M2M_BLEND | DMA2D_CR_START);
|
||||
}
|
||||
|
||||
} // namespace rgb565
|
||||
} // namespace paint
|
||||
} // namespace touchgfx
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
164
P7_SETR2/P7_SMT4497/TouchGFX/target/generated/STM32DMA.hpp
Normal file
164
P7_SETR2/P7_SMT4497/TouchGFX/target/generated/STM32DMA.hpp
Normal file
@@ -0,0 +1,164 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* File Name : STM32DMA.hpp
|
||||
******************************************************************************
|
||||
* This file is generated by TouchGFX Generator 4.26.0. Please, do not edit!
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2025 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
#ifndef STM32DMA_HPP
|
||||
#define STM32DMA_HPP
|
||||
|
||||
#include <touchgfx/Bitmap.hpp>
|
||||
#include <touchgfx/hal/DMA.hpp>
|
||||
|
||||
/**
|
||||
* @class STM32DMA
|
||||
*
|
||||
* @brief This class specializes DMA_Interface for the STM32 processors.
|
||||
*
|
||||
* @sa touchgfx::DMA_Interface
|
||||
*/
|
||||
class STM32DMA : public touchgfx::DMA_Interface
|
||||
{
|
||||
/**
|
||||
* @typedef touchgfx::DMA_Interface Base
|
||||
*
|
||||
* @brief Defines an alias representing the base.
|
||||
*
|
||||
Defines an alias representing the base.
|
||||
*/
|
||||
typedef touchgfx::DMA_Interface Base;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @fn STM32DMA::STM32DMA();
|
||||
*
|
||||
* @brief Default constructor.
|
||||
*
|
||||
* Default constructor.
|
||||
*/
|
||||
STM32DMA();
|
||||
|
||||
/**
|
||||
* @fn STM32DMA::~STM32DMA();
|
||||
*
|
||||
* @brief Destructor.
|
||||
*
|
||||
* Destructor.
|
||||
*/
|
||||
virtual ~STM32DMA();
|
||||
|
||||
/**
|
||||
* @fn DMAType touchgfx::STM32DMA::getDMAType()
|
||||
*
|
||||
* @brief Function for obtaining the DMA type of the concrete DMA_Interface implementation.
|
||||
*
|
||||
* Function for obtaining the DMA type of the concrete DMA_Interface implementation.
|
||||
* As default, will return DMA_TYPE_CHROMART type value.
|
||||
*
|
||||
* @return a DMAType value of the concrete DMA_Interface implementation.
|
||||
*/
|
||||
virtual touchgfx::DMAType getDMAType(void)
|
||||
{
|
||||
return touchgfx::DMA_TYPE_CHROMART;
|
||||
}
|
||||
|
||||
/**
|
||||
* @fn touchgfx::BlitOperations STM32DMA::getBlitCaps();
|
||||
*
|
||||
* @brief Gets the blit capabilities.
|
||||
*
|
||||
* Gets the blit capabilities.
|
||||
*
|
||||
* This DMA supports a range of blit caps: BLIT_OP_COPY, BLIT_OP_COPY_ARGB8888,
|
||||
* BLIT_OP_COPY_ARGB8888_WITH_ALPHA, BLIT_OP_COPY_A4, BLIT_OP_COPY_A8.
|
||||
*
|
||||
*
|
||||
* @return Currently supported blitcaps.
|
||||
*/
|
||||
virtual touchgfx::BlitOperations getBlitCaps();
|
||||
|
||||
/**
|
||||
* @fn void STM32DMA::initialize();
|
||||
*
|
||||
* @brief Perform hardware specific initialization.
|
||||
*
|
||||
* Perform hardware specific initialization.
|
||||
*/
|
||||
virtual void initialize();
|
||||
|
||||
/**
|
||||
* @fn void STM32DMA::signalDMAInterrupt()
|
||||
*
|
||||
* @brief Raises a DMA interrupt signal.
|
||||
*
|
||||
* Raises a DMA interrupt signal.
|
||||
*/
|
||||
virtual void signalDMAInterrupt()
|
||||
{
|
||||
executeCompleted();
|
||||
}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @fn virtual void STM32DMA::setupDataCopy(const touchgfx::BlitOp& blitOp);
|
||||
*
|
||||
* @brief Configures the DMA for copying data to the frame buffer.
|
||||
*
|
||||
* Configures the DMA for copying data to the frame buffer.
|
||||
*
|
||||
* @param blitOp Details on the copy to perform.
|
||||
*/
|
||||
virtual void setupDataCopy(const touchgfx::BlitOp& blitOp);
|
||||
|
||||
/**
|
||||
* @fn virtual void STM32DMA::setupDataFill(const touchgfx::BlitOp& blitOp);
|
||||
*
|
||||
* @brief Configures the DMA for "filling" the frame-buffer with a single color.
|
||||
*
|
||||
* Configures the DMA for "filling" the frame-buffer with a single color.
|
||||
*
|
||||
* @param blitOp Details on the "fill" to perform.
|
||||
*/
|
||||
virtual void setupDataFill(const touchgfx::BlitOp& blitOp);
|
||||
|
||||
private:
|
||||
touchgfx::LockFreeDMA_Queue dma_queue;
|
||||
touchgfx::BlitOp queue_storage[96];
|
||||
|
||||
/**
|
||||
* @fn void STM32DMA::getChromARTInputFormat()
|
||||
*
|
||||
* @brief Convert Bitmap format to ChromART Input format.
|
||||
*
|
||||
* @param format Bitmap format.
|
||||
*
|
||||
* @return ChromART Input format.
|
||||
*/
|
||||
|
||||
inline uint32_t getChromARTInputFormat(touchgfx::Bitmap::BitmapFormat format);
|
||||
|
||||
/**
|
||||
* @fn void STM32DMA::getChromARTOutputFormat()
|
||||
*
|
||||
* @brief Convert Bitmap format to ChromART Output format.
|
||||
*
|
||||
* @param format Bitmap format.
|
||||
*
|
||||
* @return ChromART Output format.
|
||||
*/
|
||||
inline uint32_t getChromARTOutputFormat(touchgfx::Bitmap::BitmapFormat format);
|
||||
};
|
||||
|
||||
#endif // STM32DMA_HPP
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
@@ -0,0 +1,579 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* File Name : SoftwareMJPEGDecoder.cpp
|
||||
******************************************************************************
|
||||
* This file is generated by TouchGFX Generator 4.26.0. Please, do not edit!
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2025 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include <jinclude.h>
|
||||
#include <jpeglib.h>
|
||||
#include <string.h>
|
||||
#include <SoftwareMJPEGDecoder.hpp>
|
||||
|
||||
#define RGB565 0
|
||||
#define RGB888 1
|
||||
#define ARGB8888 2
|
||||
#define VIDEO_DECODE_FORMAT RGB565
|
||||
namespace
|
||||
{
|
||||
struct JPEG_RGB
|
||||
{
|
||||
uint8_t B;
|
||||
uint8_t G;
|
||||
uint8_t R;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
SoftwareMJPEGDecoder::SoftwareMJPEGDecoder(uint8_t* buffer)
|
||||
: frameNumber(0), currentMovieOffset(0), indexOffset(0), firstFrameOffset(0), lastFrameEnd(0), movieLength(0), movieData(0),
|
||||
reader(0), lineBuffer(buffer), aviBuffer(0), aviBufferLength(0), aviBufferStartOffset(0), lastError(AVI_NO_ERROR)
|
||||
{
|
||||
// Clear video info
|
||||
videoInfo.frame_height = 0;
|
||||
videoInfo.frame_width = 0;
|
||||
videoInfo.ms_between_frames = 0;
|
||||
videoInfo.number_of_frames = 0;
|
||||
}
|
||||
|
||||
int SoftwareMJPEGDecoder::compare(const uint32_t offset, const char* str, uint32_t num)
|
||||
{
|
||||
const char* src;
|
||||
if (reader != 0)
|
||||
{
|
||||
// Assuming data is in buffer!
|
||||
src = reinterpret_cast<const char*>(aviBuffer + (offset - aviBufferStartOffset));
|
||||
}
|
||||
else
|
||||
{
|
||||
src = (const char*)movieData + offset;
|
||||
}
|
||||
return strncmp(src, str, num);
|
||||
}
|
||||
|
||||
inline uint32_t SoftwareMJPEGDecoder::getU32(const uint32_t offset)
|
||||
{
|
||||
if (reader != 0)
|
||||
{
|
||||
// Assuming data is in buffer!
|
||||
const uint32_t index = offset - aviBufferStartOffset;
|
||||
return aviBuffer[index + 0] | (aviBuffer[index + 1] << 8) | (aviBuffer[index + 2] << 16) | (aviBuffer[index + 3] << 24);
|
||||
}
|
||||
else
|
||||
{
|
||||
const uint8_t* const d = movieData + offset;
|
||||
return d[0] | (d[1] << 8) | (d[2] << 16) | (d[3] << 24);
|
||||
}
|
||||
}
|
||||
|
||||
inline uint32_t SoftwareMJPEGDecoder::getU16(const uint32_t offset)
|
||||
{
|
||||
if (reader != 0)
|
||||
{
|
||||
// Assuming data is in buffer!
|
||||
const uint32_t index = offset - aviBufferStartOffset;
|
||||
return aviBuffer[index + 0] | (aviBuffer[index + 1] << 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
const uint8_t* const d = movieData + offset;
|
||||
return d[0] | (d[1] << 8);
|
||||
}
|
||||
}
|
||||
|
||||
const uint8_t* SoftwareMJPEGDecoder::readData(uint32_t offset, uint32_t length)
|
||||
{
|
||||
if (reader != 0)
|
||||
{
|
||||
if (length > aviBufferLength)
|
||||
{
|
||||
lastError = AVI_ERROR_FILE_BUFFER_TO_SMALL;
|
||||
assert(!"Buffer to small");
|
||||
}
|
||||
|
||||
reader->seek(offset);
|
||||
if (!reader->readData(aviBuffer, length))
|
||||
{
|
||||
lastError = AVI_ERROR_EOF_REACHED;
|
||||
}
|
||||
|
||||
aviBufferStartOffset = offset;
|
||||
return aviBuffer;
|
||||
}
|
||||
|
||||
return movieData + offset;
|
||||
}
|
||||
|
||||
bool SoftwareMJPEGDecoder::decodeNextFrame(uint8_t* buffer, uint16_t buffer_width, uint16_t buffer_height, uint32_t buffer_stride)
|
||||
{
|
||||
assert((frameNumber > 0) && "SoftwareMJPEGDecoder decoding without frame data!");
|
||||
|
||||
//find next frame and decode it
|
||||
readData(currentMovieOffset, 8);
|
||||
uint32_t streamNo = getU16(currentMovieOffset);
|
||||
uint32_t chunkType = getU16(currentMovieOffset + 2);
|
||||
uint32_t chunkSize = getU32(currentMovieOffset + 4);
|
||||
const uint16_t STREAM0 = 0x3030;
|
||||
const uint16_t TYPEDC = 0x6364;
|
||||
|
||||
bool isCurrentFrameLast;
|
||||
//play frame if we have it all
|
||||
if (currentMovieOffset + 8 + chunkSize < movieLength)
|
||||
{
|
||||
if (streamNo == STREAM0 && chunkType == TYPEDC && chunkSize > 0)
|
||||
{
|
||||
currentMovieOffset += 8;
|
||||
//decode frame
|
||||
const uint8_t* chunk = readData(currentMovieOffset, chunkSize);
|
||||
decodeMJPEGFrame(chunk, chunkSize, buffer, buffer_width, buffer_height, buffer_stride);
|
||||
frameNumber++;
|
||||
}
|
||||
|
||||
isCurrentFrameLast = false;
|
||||
|
||||
// Advance to next frame
|
||||
currentMovieOffset += chunkSize;
|
||||
if (chunkSize == 0) // Empty frame - Skip
|
||||
{
|
||||
currentMovieOffset += 8;
|
||||
}
|
||||
currentMovieOffset = (currentMovieOffset + 1) & 0xFFFFFFFE; //pad to next word
|
||||
|
||||
if (currentMovieOffset == lastFrameEnd)
|
||||
{
|
||||
frameNumber = 1;
|
||||
currentMovieOffset = firstFrameOffset; //start over
|
||||
isCurrentFrameLast = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
frameNumber = 1;
|
||||
currentMovieOffset = firstFrameOffset; //start over
|
||||
isCurrentFrameLast = true;
|
||||
}
|
||||
return !isCurrentFrameLast;
|
||||
}
|
||||
|
||||
bool SoftwareMJPEGDecoder::gotoNextFrame()
|
||||
{
|
||||
assert((frameNumber > 0) && "SoftwareMJPEGDecoder decoding without frame data!");
|
||||
|
||||
readData(currentMovieOffset, 8);
|
||||
uint32_t chunkSize = getU32(currentMovieOffset + 4);
|
||||
|
||||
//increment until next video frame
|
||||
while (currentMovieOffset + 8 + chunkSize < movieLength)
|
||||
{
|
||||
//increment one frame
|
||||
currentMovieOffset += chunkSize + 8;
|
||||
currentMovieOffset = (currentMovieOffset + 1) & 0xFFFFFFFE; //pad to next word
|
||||
frameNumber++;
|
||||
|
||||
//next chunk
|
||||
readData(currentMovieOffset, 8);
|
||||
//check it is a video frame
|
||||
uint32_t streamNo = getU16(currentMovieOffset);
|
||||
uint32_t chunkType = getU16(currentMovieOffset + 2);
|
||||
chunkSize = getU32(currentMovieOffset + 4);
|
||||
const uint16_t STREAM0 = 0x3030;
|
||||
const uint16_t TYPEDC = 0x6364;
|
||||
|
||||
if (streamNo == STREAM0 && chunkType == TYPEDC && chunkSize > 0)
|
||||
{
|
||||
// Found next frame
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//skip back to first frame
|
||||
frameNumber = 1;
|
||||
currentMovieOffset = firstFrameOffset; //start over
|
||||
return false;
|
||||
}
|
||||
|
||||
void SoftwareMJPEGDecoder::setVideoData(const uint8_t* movie, const uint32_t length)
|
||||
{
|
||||
movieData = movie;
|
||||
movieLength = length;
|
||||
reader = 0; //not using reader
|
||||
|
||||
readVideoHeader();
|
||||
}
|
||||
|
||||
void SoftwareMJPEGDecoder::setVideoData(touchgfx::VideoDataReader& reader)
|
||||
{
|
||||
this->reader = &reader;
|
||||
movieData = 0;
|
||||
movieLength = reader.getDataLength();
|
||||
|
||||
readVideoHeader();
|
||||
}
|
||||
|
||||
bool SoftwareMJPEGDecoder::hasVideo()
|
||||
{
|
||||
return (reader != 0) || (movieData != 0);
|
||||
}
|
||||
|
||||
void SoftwareMJPEGDecoder::readVideoHeader()
|
||||
{
|
||||
// Start from the start
|
||||
currentMovieOffset = 0;
|
||||
lastError = AVI_NO_ERROR;
|
||||
|
||||
// Make header available in buffer
|
||||
readData(0, 72);
|
||||
|
||||
// Decode the movie header to find first frame
|
||||
// Must be RIFF file
|
||||
if (compare(currentMovieOffset, "RIFF", 4))
|
||||
{
|
||||
lastError = AVI_ERROR_NOT_RIFF;
|
||||
assert(!"RIFF header not found");
|
||||
}
|
||||
|
||||
//skip fourcc and length
|
||||
currentMovieOffset += 8;
|
||||
if (compare(currentMovieOffset, "AVI ", 4))
|
||||
{
|
||||
lastError = AVI_ERROR_AVI_HEADER_NOT_FOUND;
|
||||
assert(!"AVI header not found");
|
||||
}
|
||||
|
||||
currentMovieOffset += 4;
|
||||
if (compare(currentMovieOffset, "LIST", 4))
|
||||
{
|
||||
lastError = AVI_ERROR_AVI_LIST_NOT_FOUND;
|
||||
assert(!"AVI LIST not found");
|
||||
}
|
||||
|
||||
//save AVI List info
|
||||
const uint32_t aviListSize = getU32(currentMovieOffset + 4);
|
||||
const uint32_t aviListOffset = currentMovieOffset;
|
||||
assert(aviListSize);
|
||||
|
||||
//look into header to find frame rate
|
||||
bool foundFrame = true;
|
||||
uint32_t offset = currentMovieOffset + 8;
|
||||
if (compare(offset, "hdrl", 4))
|
||||
{
|
||||
lastError = AVI_ERROR_AVI_HDRL_NOT_FOUND;
|
||||
foundFrame = false;
|
||||
}
|
||||
|
||||
offset += 4;
|
||||
if (compare(offset, "avih", 4))
|
||||
{
|
||||
lastError = AVI_ERROR_AVI_AVIH_NOT_FOUND;
|
||||
foundFrame = false;
|
||||
}
|
||||
|
||||
if (foundFrame)
|
||||
{
|
||||
offset += 8; //skip fourcc and cb in AVIMAINHEADER
|
||||
videoInfo.ms_between_frames = getU32(offset) / 1000;
|
||||
videoInfo.number_of_frames = getU32(offset + 16);
|
||||
videoInfo.frame_width = getU32(offset + 32);
|
||||
videoInfo.frame_height = getU32(offset + 36);
|
||||
}
|
||||
//skip rest of AVI header, start from end of AVI List
|
||||
|
||||
//look for list with 'movi' header
|
||||
uint32_t listOffset = aviListOffset + aviListSize + 8;
|
||||
readData(listOffset, 12);
|
||||
while (compare(listOffset + 8, "movi", 4) && (lastError == AVI_NO_ERROR) && listOffset < movieLength)
|
||||
{
|
||||
const uint32_t listSize = getU32(listOffset + 4) + 8;
|
||||
listOffset += listSize;
|
||||
readData(listOffset, 12);
|
||||
}
|
||||
|
||||
if (lastError != AVI_NO_ERROR)
|
||||
{
|
||||
lastError = AVI_ERROR_MOVI_NOT_FOUND;
|
||||
return;
|
||||
}
|
||||
|
||||
//save first frame and end of last frame
|
||||
currentMovieOffset = listOffset + 8 + 4; //skip LIST and 'movi'
|
||||
lastFrameEnd = listOffset + 8 + getU32(listOffset + 4);
|
||||
|
||||
//find idx
|
||||
const uint32_t listSize = getU32(listOffset + 4) + 8;
|
||||
listOffset += listSize;
|
||||
readData(listOffset, 4);
|
||||
if (!compare(listOffset, "idx1", 4))
|
||||
{
|
||||
indexOffset = listOffset;
|
||||
}
|
||||
else
|
||||
{
|
||||
lastError = AVI_ERROR_IDX1_NOT_FOUND;
|
||||
return;
|
||||
}
|
||||
|
||||
//start on first frame
|
||||
frameNumber = 1; //next frame number is 1
|
||||
firstFrameOffset = currentMovieOffset;
|
||||
}
|
||||
|
||||
#if VIDEO_DECODE_FORMAT == RGB565 || VIDEO_DECODE_FORMAT == RGB888 || VIDEO_DECODE_FORMAT == ARGB8888
|
||||
void SoftwareMJPEGDecoder::decodeMJPEGFrame(const uint8_t* const mjpgdata, const uint32_t length, uint8_t* outputBuffer, uint16_t bufferWidth, uint16_t bufferHeight, uint32_t bufferStride)
|
||||
{
|
||||
if (length == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (outputBuffer && lineBuffer) //only decode if buffers are assigned.
|
||||
{
|
||||
/* This struct contains the JPEG decompression parameters */
|
||||
struct jpeg_decompress_struct cinfo;
|
||||
/* This struct represents a JPEG error handler */
|
||||
struct jpeg_error_mgr jerr;
|
||||
|
||||
JSAMPROW lines[2] = { lineBuffer, 0 }; /* Output row buffer */
|
||||
|
||||
/* Step 1: allocate and initialize JPEG decompression object */
|
||||
cinfo.err = jpeg_std_error(&jerr);
|
||||
|
||||
/* Initialize the JPEG decompression object */
|
||||
jpeg_create_decompress(&cinfo);
|
||||
|
||||
//jpeg_stdio_src (&cinfo, file);
|
||||
jpeg_mem_src(&cinfo, const_cast<uint8_t*>(mjpgdata), length);
|
||||
|
||||
/* Step 3: read image parameters with jpeg_read_header() */
|
||||
jpeg_read_header(&cinfo, TRUE);
|
||||
|
||||
/* Step 4: set parameters for decompression */
|
||||
cinfo.dct_method = JDCT_FLOAT;
|
||||
|
||||
/* Step 5: start decompressor */
|
||||
jpeg_start_decompress(&cinfo);
|
||||
|
||||
//restrict to minimum of movie and output buffer size
|
||||
const uint32_t width = MIN(bufferWidth, cinfo.image_width);
|
||||
const uint32_t height = MIN(bufferHeight, cinfo.output_height);
|
||||
|
||||
#if VIDEO_DECODE_FORMAT == RGB565
|
||||
uint16_t* lineptr = reinterpret_cast<uint16_t*>(outputBuffer);
|
||||
#elif VIDEO_DECODE_FORMAT == RGB888
|
||||
uint8_t* lineptr = outputBuffer;
|
||||
#else
|
||||
uint32_t* lineptr = reinterpret_cast<uint32_t*>(outputBuffer);
|
||||
#endif
|
||||
while (cinfo.output_scanline < height)
|
||||
{
|
||||
(void)jpeg_read_scanlines(&cinfo, lines, 1);
|
||||
#if VIDEO_DECODE_FORMAT == RGB565
|
||||
JPEG_RGB* RGB_matrix = (JPEG_RGB*)lineBuffer;
|
||||
JPEG_RGB* const RGB_end = RGB_matrix + width;
|
||||
while (RGB_matrix < RGB_end)
|
||||
{
|
||||
const uint16_t pix = ((RGB_matrix->R & 0xF8) << 8) | ((RGB_matrix->G & 0xFC) << 3) | ((RGB_matrix->B & 0xF8) >> 3);
|
||||
*lineptr++ = pix;
|
||||
RGB_matrix++;
|
||||
}
|
||||
lineptr += bufferWidth - width; //move to next line
|
||||
#elif VIDEO_DECODE_FORMAT == RGB888
|
||||
memcpy(lineptr, lineBuffer, width * 3);
|
||||
lineptr += bufferStride; //move to next line
|
||||
#else
|
||||
JPEG_RGB* RGB_matrix = (JPEG_RGB*)lineBuffer;
|
||||
JPEG_RGB* const RGB_end = RGB_matrix + width;
|
||||
while (RGB_matrix < RGB_end)
|
||||
{
|
||||
const uint32_t pix = (0xFF << 24) | (RGB_matrix->R << 16) | (RGB_matrix->G << 8) | (RGB_matrix->B);
|
||||
*lineptr++ = pix;
|
||||
RGB_matrix++;
|
||||
}
|
||||
lineptr += bufferWidth - width; //move to next line
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef SIMULATOR
|
||||
cinfo.output_scanline = cinfo.output_height;
|
||||
#endif
|
||||
/* Step 6: Finish decompression */
|
||||
jpeg_finish_decompress(&cinfo);
|
||||
|
||||
/* Step 7: Release JPEG decompression object */
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
}
|
||||
}
|
||||
|
||||
bool SoftwareMJPEGDecoder::decodeFrame(const touchgfx::Rect& area, uint8_t* frameBuffer, uint32_t framebuffer_width)
|
||||
{
|
||||
// Assuming that chunk is available and streamNo and chunkType is correct.
|
||||
// Check by gotoNextFrame
|
||||
|
||||
readData(currentMovieOffset, 8);
|
||||
const uint32_t length = getU32(currentMovieOffset + 4);
|
||||
|
||||
// Ensure whole frame is read
|
||||
const uint8_t* mjpgdata = readData(currentMovieOffset + 8, length);
|
||||
|
||||
assert(lineBuffer && "LineBuffer must be assigned prior to decoding directly to framebuffer");
|
||||
|
||||
/* This struct contains the JPEG decompression parameters */
|
||||
struct jpeg_decompress_struct cinfo;
|
||||
/* This struct represents a JPEG error handler */
|
||||
struct jpeg_error_mgr jerr;
|
||||
|
||||
JSAMPROW lines[2] = { lineBuffer, 0 }; /* Output row buffer */
|
||||
|
||||
/* Step 1: allocate and initialize JPEG decompression object */
|
||||
cinfo.err = jpeg_std_error(&jerr);
|
||||
|
||||
/* Initialize the JPEG decompression object */
|
||||
jpeg_create_decompress(&cinfo);
|
||||
|
||||
//jpeg_stdio_src (&cinfo, file);
|
||||
jpeg_mem_src(&cinfo, const_cast<uint8_t*>(mjpgdata), length);
|
||||
|
||||
/* Step 3: read image parameters with jpeg_read_header() */
|
||||
jpeg_read_header(&cinfo, TRUE);
|
||||
|
||||
/* Step 4: set parameters for decompression */
|
||||
cinfo.dct_method = JDCT_FLOAT;
|
||||
|
||||
/* Step 5: start decompressor */
|
||||
jpeg_start_decompress(&cinfo);
|
||||
|
||||
//restrict to minimum of movie and output buffer size
|
||||
const uint32_t startY = area.y;
|
||||
|
||||
//scan down to startY
|
||||
while (cinfo.output_scanline < startY)
|
||||
{
|
||||
(void)jpeg_read_scanlines(&cinfo, lines, 1);
|
||||
}
|
||||
|
||||
const uint32_t startX = area.x;
|
||||
const uint32_t endX = MIN((uint32_t)area.right(), cinfo.image_width);
|
||||
|
||||
#if VIDEO_DECODE_FORMAT == RGB565
|
||||
uint16_t* lineptr = reinterpret_cast<uint16_t*>(frameBuffer);
|
||||
lineptr += framebuffer_width * startY;
|
||||
#elif VIDEO_DECODE_FORMAT == RGB888
|
||||
uint8_t* lineptr = frameBuffer;
|
||||
lineptr += framebuffer_width * 3 * startY;
|
||||
#else
|
||||
uint32_t* lineptr = reinterpret_cast<uint32_t*>(frameBuffer);
|
||||
lineptr += framebuffer_width * startY;
|
||||
#endif
|
||||
const uint32_t endY = MIN((uint32_t)area.bottom(), cinfo.output_height);
|
||||
|
||||
//scan relevant part
|
||||
while (cinfo.output_scanline < endY)
|
||||
{
|
||||
(void)jpeg_read_scanlines(&cinfo, lines, 1);
|
||||
#if VIDEO_DECODE_FORMAT == RGB565
|
||||
JPEG_RGB* RGB_matrix = (JPEG_RGB*)lineBuffer;
|
||||
//loop row RGB888->RGB565 for required line part
|
||||
for (uint32_t counter = startX; counter < endX; counter++)
|
||||
{
|
||||
const uint16_t pix = ((RGB_matrix[counter].R & 0xF8) << 8) | ((RGB_matrix[counter].G & 0xFC) << 3) | ((RGB_matrix[counter].B & 0xF8) >> 3);
|
||||
*(lineptr + counter) = pix;
|
||||
}
|
||||
lineptr += framebuffer_width; //move to next line
|
||||
#elif VIDEO_DECODE_FORMAT == RGB888
|
||||
memcpy(lineptr + startX * 3, lineBuffer + startX * 3, (endX - startX) * 3);
|
||||
lineptr += framebuffer_width * 3; //move to next line
|
||||
#else
|
||||
JPEG_RGB* RGB_matrix = (JPEG_RGB*)lineBuffer;
|
||||
//loop row RGB888->ARGB8888 for required line part
|
||||
for (uint32_t counter = startX; counter < endX; counter++)
|
||||
{
|
||||
const uint32_t pix = (0xFF << 24) | (RGB_matrix[counter].R << 16) | (RGB_matrix[counter].G << 8) | RGB_matrix[counter].B;
|
||||
*(lineptr + counter) = pix;
|
||||
}
|
||||
lineptr += framebuffer_width; //move to next line
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef SIMULATOR
|
||||
cinfo.output_scanline = cinfo.output_height;
|
||||
#endif
|
||||
|
||||
/* Step 6: Finish decompression */
|
||||
jpeg_finish_decompress(&cinfo);
|
||||
|
||||
/* Step 7: Release JPEG decompression object */
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
void SoftwareMJPEGDecoder::decodeMJPEGFrame(const uint8_t* const, const uint32_t, uint8_t*, uint16_t, uint16_t, uint32_t)
|
||||
{
|
||||
}
|
||||
bool SoftwareMJPEGDecoder::decodeFrame(const touchgfx::Rect&, uint8_t*, uint32_t)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#endif // VIDEO_DECODE_FORMAT == RGB565 || VIDEO_DECODE_FORMAT == RGB888 || VIDEO_DECODE_FORMAT == ARGB888
|
||||
|
||||
bool SoftwareMJPEGDecoder::decodeThumbnail(uint32_t frameno, uint8_t* buffer, uint16_t width, uint16_t height)
|
||||
{
|
||||
assert(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
void SoftwareMJPEGDecoder::gotoFrame(uint32_t frameNumber)
|
||||
{
|
||||
if (frameNumber == 0)
|
||||
{
|
||||
frameNumber = 1;
|
||||
}
|
||||
|
||||
if (frameNumber > getNumberOfFrames())
|
||||
{
|
||||
frameNumber = getNumberOfFrames();
|
||||
}
|
||||
|
||||
uint32_t offset = indexOffset + 8 + (frameNumber - 1) * 16;
|
||||
|
||||
readData(offset, 16);
|
||||
|
||||
currentMovieOffset = getU32(offset + 8) + firstFrameOffset - 4;
|
||||
this->frameNumber = frameNumber;
|
||||
}
|
||||
|
||||
uint32_t SoftwareMJPEGDecoder::getNumberOfFrames()
|
||||
{
|
||||
return videoInfo.number_of_frames;
|
||||
}
|
||||
|
||||
void SoftwareMJPEGDecoder::getVideoInfo(touchgfx::VideoInformation* data)
|
||||
{
|
||||
*data = videoInfo;
|
||||
// For unsupported decode formats, set video dimension to 0x0, to avoid drawing anything
|
||||
#if VIDEO_DECODE_FORMAT == RGB565 || VIDEO_DECODE_FORMAT == RGB888 || VIDEO_DECODE_FORMAT == ARGB8888
|
||||
#else
|
||||
data->frame_width = 0;
|
||||
data->frame_height = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
//#ifndef SIMULATOR
|
||||
//link libjpeg file operation to fileinput namespace
|
||||
extern "C" {
|
||||
size_t jpeg_read_file(FILE* file, uint8_t* buf, uint32_t sizeofbuf)
|
||||
{
|
||||
assert(!"jpeg_read_file called with no implementation");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
//#endif
|
||||
@@ -0,0 +1,86 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* File Name : SoftwareMJPEGDecoder.hpp
|
||||
******************************************************************************
|
||||
* This file is generated by TouchGFX Generator 4.26.0. Please, do not edit!
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2025 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
#ifndef TOUCHGFX_SOFTWAREMJPEGDECODER_HPP
|
||||
#define TOUCHGFX_SOFTWAREMJPEGDECODER_HPP
|
||||
|
||||
#include <MJPEGDecoder.hpp>
|
||||
|
||||
class SoftwareMJPEGDecoder : public MJPEGDecoder
|
||||
{
|
||||
public:
|
||||
SoftwareMJPEGDecoder(uint8_t* linebuffer);
|
||||
|
||||
virtual void setVideoData(const uint8_t* movie, const uint32_t length);
|
||||
|
||||
virtual void setVideoData(touchgfx::VideoDataReader& reader);
|
||||
|
||||
virtual bool hasVideo();
|
||||
|
||||
virtual bool decodeNextFrame(uint8_t* frameBuffer, uint16_t width, uint16_t height, uint32_t framebuffer_width);
|
||||
|
||||
virtual bool gotoNextFrame();
|
||||
|
||||
virtual bool decodeFrame(const touchgfx::Rect& area, uint8_t* frameBuffer, uint32_t framebuffer_width);
|
||||
|
||||
virtual bool decodeThumbnail(uint32_t frameno, uint8_t* buffer, uint16_t width, uint16_t height);
|
||||
|
||||
virtual void gotoFrame(uint32_t frameno);
|
||||
|
||||
virtual uint32_t getCurrentFrameNumber() const
|
||||
{
|
||||
return frameNumber;
|
||||
}
|
||||
|
||||
virtual uint32_t getNumberOfFrames();
|
||||
|
||||
virtual void getVideoInfo(touchgfx::VideoInformation* data);
|
||||
|
||||
void setAVIFileBuffer(uint8_t* buffer, uint32_t size)
|
||||
{
|
||||
aviBuffer = buffer, aviBufferLength = size;
|
||||
}
|
||||
|
||||
virtual AVIErrors getLastError()
|
||||
{
|
||||
return lastError;
|
||||
}
|
||||
private:
|
||||
void readVideoHeader();
|
||||
void decodeMJPEGFrame(const uint8_t* const mjpgdata, const uint32_t length, uint8_t* buffer, uint16_t width, uint16_t height, uint32_t stride);
|
||||
int compare(const uint32_t offset, const char* str, uint32_t num);
|
||||
uint32_t getU32(const uint32_t offset);
|
||||
uint32_t getU16(const uint32_t offset);
|
||||
const uint8_t* readData(uint32_t offset, uint32_t length);
|
||||
|
||||
touchgfx::VideoInformation videoInfo;
|
||||
uint32_t frameNumber;
|
||||
uint32_t currentMovieOffset;
|
||||
uint32_t indexOffset;
|
||||
uint32_t firstFrameOffset;
|
||||
uint32_t lastFrameEnd;
|
||||
uint32_t movieLength;
|
||||
const uint8_t* movieData;
|
||||
touchgfx::VideoDataReader* reader;
|
||||
uint8_t* lineBuffer;
|
||||
uint8_t* aviBuffer;
|
||||
uint32_t aviBufferLength;
|
||||
uint32_t aviBufferStartOffset;
|
||||
AVIErrors lastError;
|
||||
};
|
||||
|
||||
#endif // TOUCHGFX_SOFTWAREMJPEGDECODER_HPP
|
||||
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* File Name : TouchGFXConfiguration.cpp
|
||||
******************************************************************************
|
||||
* This file is generated by TouchGFX Generator 4.26.0. Please, do not edit!
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2025 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include <texts/TypedTextDatabase.hpp>
|
||||
#include <fonts/ApplicationFontProvider.hpp>
|
||||
#include <gui/common/FrontendHeap.hpp>
|
||||
#include <BitmapDatabase.hpp>
|
||||
#include <touchgfx/VectorFontRendererImpl.hpp>
|
||||
#include <platform/driver/lcd/LCD16bpp.hpp>
|
||||
#include <STM32DMA.hpp>
|
||||
#include <TouchGFXHAL.hpp>
|
||||
#include <STM32TouchController.hpp>
|
||||
#include <stm32f7xx_hal.h>
|
||||
|
||||
extern "C" void touchgfx_init();
|
||||
extern "C" void touchgfx_taskEntry();
|
||||
extern "C" void touchgfx_components_init();
|
||||
|
||||
static STM32TouchController tc;
|
||||
static STM32DMA dma;
|
||||
static LCD16bpp display;
|
||||
static VectorFontRendererImpl vectorFontRenderer;
|
||||
|
||||
static ApplicationFontProvider fontProvider;
|
||||
static Texts texts;
|
||||
static TouchGFXHAL hal(dma, display, tc, 480, 272);
|
||||
|
||||
void touchgfx_init()
|
||||
{
|
||||
Bitmap::registerBitmapDatabase(BitmapDatabase::getInstance(), BitmapDatabase::getInstanceSize());
|
||||
TypedText::registerTexts(&texts);
|
||||
Texts::setLanguage(0);
|
||||
|
||||
display.setVectorFontRenderer(&vectorFontRenderer);
|
||||
|
||||
FontManager::setFontProvider(&fontProvider);
|
||||
|
||||
FrontendHeap& heap = FrontendHeap::getInstance();
|
||||
/*
|
||||
* we need to obtain the reference above to initialize the frontend heap.
|
||||
*/
|
||||
(void)heap;
|
||||
|
||||
/*
|
||||
* Initialize TouchGFX
|
||||
*/
|
||||
hal.initialize();
|
||||
}
|
||||
|
||||
void touchgfx_components_init()
|
||||
{
|
||||
}
|
||||
|
||||
void touchgfx_taskEntry()
|
||||
{
|
||||
/*
|
||||
* Main event loop. Will wait for VSYNC signal, and then process next frame. Call
|
||||
* this function from your GUI task.
|
||||
*
|
||||
* Note This function never returns
|
||||
*/
|
||||
hal.taskEntry();
|
||||
}
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
@@ -0,0 +1,211 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* File Name : TouchGFXGeneratedHAL.cpp
|
||||
******************************************************************************
|
||||
* This file is generated by TouchGFX Generator 4.26.0. Please, do not edit!
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2025 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include <TouchGFXGeneratedHAL.hpp>
|
||||
#include <touchgfx/hal/OSWrappers.hpp>
|
||||
#include <gui/common/FrontendHeap.hpp>
|
||||
#include <touchgfx/hal/GPIO.hpp>
|
||||
|
||||
#include <touchgfx/widgets/canvas/CWRVectorRenderer.hpp>
|
||||
|
||||
#include <DoubleBufferedVideoController.hpp>
|
||||
|
||||
#include <SoftwareMJPEGDecoder.hpp>
|
||||
uint32_t lineBuffer[480];
|
||||
|
||||
SoftwareMJPEGDecoder mjpegdecoder1((uint8_t*)lineBuffer);
|
||||
|
||||
namespace
|
||||
{
|
||||
LOCATION_PRAGMA_NOLOAD("Video_RGB_Buffer")
|
||||
uint32_t videoRGBBuffer[130560] LOCATION_ATTRIBUTE_NOLOAD("Video_RGB_Buffer");
|
||||
DoubleBufferedVideoController<1, 480, 272, 480 * 2U, Bitmap::RGB565> videoController;
|
||||
}
|
||||
|
||||
//Singleton Factory
|
||||
VideoController& VideoController::getInstance()
|
||||
{
|
||||
return videoController;
|
||||
}
|
||||
|
||||
namespace touchgfx
|
||||
{
|
||||
VectorRenderer* VectorRenderer::getInstance()
|
||||
{
|
||||
static CWRVectorRendererRGB565 renderer;
|
||||
|
||||
return &renderer;
|
||||
}
|
||||
} // namespace touchgfx
|
||||
|
||||
#include "stm32f7xx.h"
|
||||
#include "stm32f7xx_hal_ltdc.h"
|
||||
|
||||
using namespace touchgfx;
|
||||
|
||||
namespace
|
||||
{
|
||||
// Use the section "TouchGFX_Framebuffer" in the linker script to specify the placement of the buffer
|
||||
LOCATION_PRAGMA_NOLOAD("TouchGFX_Framebuffer")
|
||||
uint32_t frameBuf[(480 * 272 * 2 + 3) / 4 * 2] LOCATION_ATTRIBUTE_NOLOAD("TouchGFX_Framebuffer");
|
||||
static uint16_t lcd_int_active_line;
|
||||
static uint16_t lcd_int_porch_line;
|
||||
}
|
||||
|
||||
void TouchGFXGeneratedHAL::initialize()
|
||||
{
|
||||
HAL::initialize();
|
||||
registerEventListener(*(Application::getInstance()));
|
||||
setFrameBufferStartAddresses((void*)frameBuf, (void*)(frameBuf + sizeof(frameBuf) / (sizeof(uint32_t) * 2)), (void*)0);
|
||||
|
||||
/*
|
||||
* Add software decoder to video controller
|
||||
*/
|
||||
videoController.addDecoder(mjpegdecoder1, 0);
|
||||
|
||||
videoController.setRGBBuffer((uint8_t*)videoRGBBuffer, sizeof(videoRGBBuffer));
|
||||
}
|
||||
|
||||
void TouchGFXGeneratedHAL::configureInterrupts()
|
||||
{
|
||||
NVIC_SetPriority(DMA2D_IRQn, 9);
|
||||
NVIC_SetPriority(LTDC_IRQn, 9);
|
||||
}
|
||||
|
||||
void TouchGFXGeneratedHAL::enableInterrupts()
|
||||
{
|
||||
NVIC_EnableIRQ(DMA2D_IRQn);
|
||||
NVIC_EnableIRQ(LTDC_IRQn);
|
||||
}
|
||||
|
||||
void TouchGFXGeneratedHAL::disableInterrupts()
|
||||
{
|
||||
NVIC_DisableIRQ(DMA2D_IRQn);
|
||||
NVIC_DisableIRQ(LTDC_IRQn);
|
||||
}
|
||||
|
||||
void TouchGFXGeneratedHAL::enableLCDControllerInterrupt()
|
||||
{
|
||||
lcd_int_active_line = (LTDC->BPCR & LTDC_BPCR_AVBP_Msk) - 1;
|
||||
lcd_int_porch_line = (LTDC->AWCR & LTDC_AWCR_AAH_Msk) - 1;
|
||||
|
||||
/* Sets the Line Interrupt position */
|
||||
LTDC->LIPCR = lcd_int_active_line;
|
||||
/* Line Interrupt Enable */
|
||||
LTDC->IER |= LTDC_IER_LIE;
|
||||
}
|
||||
|
||||
bool TouchGFXGeneratedHAL::beginFrame()
|
||||
{
|
||||
return HAL::beginFrame();
|
||||
}
|
||||
|
||||
void TouchGFXGeneratedHAL::endFrame()
|
||||
{
|
||||
HAL::endFrame();
|
||||
videoController.endFrame();
|
||||
}
|
||||
|
||||
uint16_t* TouchGFXGeneratedHAL::getTFTFrameBuffer() const
|
||||
{
|
||||
return (uint16_t*)LTDC_Layer1->CFBAR;
|
||||
}
|
||||
|
||||
void TouchGFXGeneratedHAL::setTFTFrameBuffer(uint16_t* adr)
|
||||
{
|
||||
LTDC_Layer1->CFBAR = (uint32_t)adr;
|
||||
|
||||
/* Reload immediate */
|
||||
LTDC->SRCR = (uint32_t)LTDC_SRCR_IMR;
|
||||
}
|
||||
|
||||
void TouchGFXGeneratedHAL::flushFrameBuffer(const touchgfx::Rect& rect)
|
||||
{
|
||||
HAL::flushFrameBuffer(rect);
|
||||
}
|
||||
|
||||
bool TouchGFXGeneratedHAL::blockCopy(void* RESTRICT dest, const void* RESTRICT src, uint32_t numBytes)
|
||||
{
|
||||
return HAL::blockCopy(dest, src, numBytes);
|
||||
}
|
||||
|
||||
void TouchGFXGeneratedHAL::InvalidateCache()
|
||||
{
|
||||
// Because DMA2D access main memory directly, the DCache must be invalidated
|
||||
// becuase it could hold a wrong image of the framebuffer. That's done
|
||||
// using the function SCB_CleanInvalidateDCache(). Remember to enable
|
||||
// "CPU Cache" in the "System Core" settings for "Cortex M7" in CubeMX
|
||||
// in order for this function call to work.
|
||||
if (SCB->CCR & SCB_CCR_DC_Msk)
|
||||
{
|
||||
SCB_CleanInvalidateDCache();
|
||||
}
|
||||
}
|
||||
|
||||
void TouchGFXGeneratedHAL::FlushCache()
|
||||
{
|
||||
// If the framebuffer is placed in Write-Back cached memory (e.g. SRAM) then
|
||||
// the DCache must be flushed prior to DMA2D accessing it. That's done
|
||||
// using the function SCB_CleanInvalidateDCache(). Remember to enable
|
||||
// "CPU Cache" in the "System Core" settings for "Cortex M7" in CubeMX in
|
||||
// order for this function call to work.
|
||||
if (SCB->CCR & SCB_CCR_DC_Msk)
|
||||
{
|
||||
SCB_CleanInvalidateDCache();
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void videoTaskFunc(void* argument)
|
||||
{
|
||||
videoController.decoderTaskEntry();
|
||||
}
|
||||
|
||||
extern "C"
|
||||
{
|
||||
void HAL_LTDC_LineEventCallback(LTDC_HandleTypeDef* hltdc)
|
||||
{
|
||||
if (!HAL::getInstance())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (LTDC->LIPCR == lcd_int_active_line)
|
||||
{
|
||||
//entering active area
|
||||
HAL_LTDC_ProgramLineEvent(hltdc, lcd_int_porch_line);
|
||||
HAL::getInstance()->vSync();
|
||||
OSWrappers::signalVSync();
|
||||
|
||||
// Swap frame buffers immediately instead of waiting for the task to be scheduled in.
|
||||
// Note: task will also swap when it wakes up, but that operation is guarded and will not have
|
||||
// any effect if already swapped.
|
||||
HAL::getInstance()->swapFrameBuffers();
|
||||
GPIO::set(GPIO::VSYNC_FREQ);
|
||||
}
|
||||
else
|
||||
{
|
||||
//exiting active area
|
||||
HAL_LTDC_ProgramLineEvent(hltdc, lcd_int_active_line);
|
||||
|
||||
// Signal to the framework that display update has finished.
|
||||
HAL::getInstance()->frontPorchEntered();
|
||||
GPIO::clear(GPIO::VSYNC_FREQ);
|
||||
}
|
||||
}
|
||||
}
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
@@ -0,0 +1,188 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* File Name : TouchGFXGeneratedHAL.hpp
|
||||
******************************************************************************
|
||||
* This file is generated by TouchGFX Generator 4.26.0. Please, do not edit!
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2025 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
#ifndef TouchGFXGeneratedHAL_HPP
|
||||
#define TouchGFXGeneratedHAL_HPP
|
||||
|
||||
#include <touchgfx/hal/HAL.hpp>
|
||||
|
||||
/**
|
||||
* @class TouchGFXGeneratedHAL
|
||||
*
|
||||
* @brief HAL implementation for TouchGFXGenerated.
|
||||
*
|
||||
* @sa HAL
|
||||
*/
|
||||
class TouchGFXGeneratedHAL : public touchgfx::HAL
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @fn TouchGFXGeneratedHAL::TouchGFXGeneratedHAL(touchgfx::DMA_Interface& dma, touchgfx::LCD& display, touchgfx::TouchController& tc, uint16_t width, uint16_t height) : touchgfx::HAL(dma, display, tc, width, height)
|
||||
*
|
||||
* @brief Constructor.
|
||||
*
|
||||
* Constructor. Initializes members.
|
||||
*
|
||||
* @param [in,out] dma Reference to DMA interface.
|
||||
* @param [in,out] display Reference to LCD interface.
|
||||
* @param [in,out] tc Reference to Touch Controller driver.
|
||||
* @param width Width of the display.
|
||||
* @param height Height of the display.
|
||||
*/
|
||||
TouchGFXGeneratedHAL(touchgfx::DMA_Interface& dma, touchgfx::LCD& display, touchgfx::TouchController& tc, uint16_t width, uint16_t height) :
|
||||
touchgfx::HAL(dma, display, tc, width, height)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @fn void TouchGFXGeneratedHAL::initialize();
|
||||
*
|
||||
* @brief This function is responsible for initializing the entire framework.
|
||||
*
|
||||
* This function is responsible for initializing the entire framework.
|
||||
*/
|
||||
virtual void initialize();
|
||||
|
||||
/**
|
||||
* @fn virtual void TouchGFXGeneratedHAL::configureInterrupts();
|
||||
*
|
||||
* @brief Sets the DMA, LCD, and GPU2D (if enabled) interrupt priorities.
|
||||
*
|
||||
* Sets the DMA, LCD, and GPU2D (if enabled) interrupt priorities.
|
||||
*/
|
||||
virtual void configureInterrupts();
|
||||
|
||||
/**
|
||||
* @fn virtual void TouchGFXGeneratedHAL::enableInterrupts();
|
||||
*
|
||||
* @brief Enables the DMA, LCD, and GPU2D (if enabled) interrupts.
|
||||
*
|
||||
* Enables the DMA, LCD, and GPU2D (if enabled) interrupts.
|
||||
*/
|
||||
virtual void enableInterrupts();
|
||||
|
||||
/**
|
||||
* @fn virtual void TouchGFXGeneratedHAL::disableInterrupts();
|
||||
*
|
||||
* @brief Disables the DMA, LDC, and GPU2D (if enabled) interrupts.
|
||||
*
|
||||
* Disables the DMA, LDC, and GPU2D (if enabled) interrupts.
|
||||
*/
|
||||
virtual void disableInterrupts();
|
||||
|
||||
/**
|
||||
* @fn virtual void TouchGFXGeneratedHAL::enableLCDControllerInterrupt();
|
||||
*
|
||||
* @brief Configure the LCD controller to fire interrupts at VSYNC.
|
||||
*
|
||||
* Configure the LCD controller to fire interrupts at VSYNC. Called automatically
|
||||
* once TouchGFX initialization has completed.
|
||||
*/
|
||||
virtual void enableLCDControllerInterrupt();
|
||||
|
||||
/**
|
||||
* @fn virtual void TouchGFXGeneratedHAL::flushFrameBuffer();
|
||||
*
|
||||
* @brief This function is called whenever the framework has performed a complete draw.
|
||||
*
|
||||
* This specialization is only in place to keep compilers happy. Base impl. will call the
|
||||
* Rect version.
|
||||
* @see HAL::flushFrameBuffer
|
||||
*/
|
||||
virtual void flushFrameBuffer()
|
||||
{
|
||||
HAL::flushFrameBuffer();
|
||||
}
|
||||
|
||||
/**
|
||||
* @fn virtual void TouchGFXGeneratedHAL::flushFrameBuffer(const touchgfx::Rect& rect);
|
||||
*
|
||||
* @brief This function is called whenever the framework has performed a partial draw.
|
||||
*
|
||||
* This function is called whenever the framework has performed a partial draw.
|
||||
*
|
||||
* @param rect The area of the screen that has been drawn, expressed in absolute coordinates.
|
||||
*
|
||||
* @see flushFrameBuffer().
|
||||
*/
|
||||
virtual void flushFrameBuffer(const touchgfx::Rect& rect);
|
||||
|
||||
/**
|
||||
*
|
||||
* @fn virtual void TouchGFXGeneratedHAL::blockCopy();
|
||||
*
|
||||
* This function performs a platform-specific memcpy, if supported by the hardware.
|
||||
*
|
||||
* @param [out] dest Pointer to destination memory.
|
||||
* @param [in] src Pointer to source memory.
|
||||
* @param numBytes Number of bytes to copy.
|
||||
*
|
||||
* @return true if the copy succeeded, false if copy was not performed.
|
||||
*/
|
||||
virtual bool blockCopy(void* RESTRICT dest, const void* RESTRICT src, uint32_t numBytes);
|
||||
|
||||
/**
|
||||
* @fn virtual void TouchGFXGeneratedHAL::beginFrame();
|
||||
*
|
||||
* @brief Called when beginning to rendering a frame.
|
||||
*
|
||||
* Called when beginning to rendering a frame.
|
||||
*
|
||||
* @return true if rendering can begin, false otherwise.
|
||||
*/
|
||||
virtual bool beginFrame();
|
||||
|
||||
/**
|
||||
* @fn virtual void TouchGFXGeneratedHAL::endFrame();
|
||||
*
|
||||
* @brief Called when a rendering pass is completed.
|
||||
*
|
||||
* Called when a rendering pass is completed.
|
||||
*/
|
||||
virtual void endFrame();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @fn virtual uint16_t* TouchGFXGeneratedHAL::getTFTFrameBuffer() const;
|
||||
*
|
||||
* @brief Gets the frame buffer address used by the TFT controller.
|
||||
*
|
||||
* Gets the frame buffer address used by the TFT controller.
|
||||
*
|
||||
* @return The address of the frame buffer currently being displayed on the TFT.
|
||||
*/
|
||||
virtual uint16_t* getTFTFrameBuffer() const;
|
||||
|
||||
/**
|
||||
* @fn virtual void TouchGFXGeneratedHAL::setTFTFrameBuffer(uint16_t* adr);
|
||||
*
|
||||
* @brief Sets the frame buffer address used by the TFT controller.
|
||||
*
|
||||
* Sets the frame buffer address used by the TFT controller.
|
||||
*
|
||||
* @param [in,out] adr New frame buffer address.
|
||||
*/
|
||||
virtual void setTFTFrameBuffer(uint16_t* adr);
|
||||
|
||||
virtual void InvalidateCache();
|
||||
|
||||
virtual void FlushCache();
|
||||
|
||||
};
|
||||
#endif // TouchGFXGeneratedHAL_HPP
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
Reference in New Issue
Block a user