GD32H7系列的IPA(Image Pixel Accelerator)是一个高效的图像处理硬件加速器,专门设计用于加速图像处理操作,如像素格式转换、图像旋转、缩放等。它的优势在于能够利用硬件加速来实现这些操作,相比于软件实现,可以大大提高处理速度,降低CPU的负担,从而提升整体系统性能。
主要特性
一个访问存储器的AXI 主设备接口;
一个支持8 位,16 位,32 位的IPA 配置的AHB 从设备接口;
3 个4 双字深度的64 位FIFO 独立用于源图像和目标图像;
支持四种像素格式转换模式:
制某一源图像到目标图像中;
– 复制某一源图像到目标图像中并同时进行特定的颜色格式转换;
– 将两个不同的源图像进行混合,并将得到的结果进行特定的颜色格式转换;
– 用特定的颜色填充目标图像区域。
支持两源图像独立配置LUT 大小;
支持两种LUT 像素格式;
支持LUT 自动加载;
支持传输挂起或停止;
对于源图像和目标图像,支持独立配置行偏移量;
支持源图像和目标图像独立预定义的像素通道值;
分别支持两源图像3 种alpha 通道值计算算法;
对于前景层图像,支持16 种像素格式;
对于背景层图像,支持11 种像素格式;
对于目标图像,支持5 种像素格式;
支持配置图像大小;
支持AXI 总线带宽自动调节;
支持一个带有六种事件标志位的中断;
支持中断使能和清除;
支持十进制缩放和双线性缩放;
支持图像旋转(0、90、180、270 度);
前景层图像支持隔行输入。
IPA的优势
- 硬件加速:直接在硬件级别处理图像数据,加速图像处理任务,提供比软件实现更快的处理速度。
- 减轻CPU负担:CPU可以被释放出来处理其他任务,提高系统的多任务处理能力。
- 多种图像处理功能:支持像素格式转换、图像旋转、缩放等常见图像处理功能,满足多样化的应用需求。
- 支持直接内存访问(DMA):可与DMA配合使用,减少CPU介入,进一步提高数据处理效率。
- 灵活配置:提供丰富的配置选项,支持多种图像格式和处理方式,适用于多种不同的应用场景。
功能
IPA 提供从某一个或两个源图像到目标图像的可配置的,灵活的图像处理功能。它支持以下四
种转换模式(主要功能):
1 复制某一源图像到目标图像中;
2 复制某一源图像到目标图像中并同时进行特定的格式转换;
3 将两个不同的源图像进行混合,并将得到的结果进行特定的颜色格式转换;
4 用特定的颜色填充目标图像区域。
前景层图像支持16 种像素格式,背景层图像支持11 种像素格式,每像素从4 位到最高32 位,
对于目标图像支持5 种像素格式,每像素从16 位到最高32 位。采用间接像素模式时,IPA 为
两个源图像分别提供了256*32 的颜色查找表。
IPA的基本功能
- 像素格式转换:IPA可以在不同的像素格式之间转换图像数据,如从RGB565转换到RGB888等,这是图像处理中常见的需求。
- **相机:**相机通常使用 RAW 格式来存储图像数据。为了在显示器上显示图像,需要将 RAW 格式转换为 RGB 格式。
- **视频监控:**视频监控系统通常使用 YUV 格式来传输视频数据。为了在显示器上显示视频,需要将 YUV 格式转换为 RGB 格式。
- **图像编辑:**图像编辑软件通常支持多种像素格式,例如 RGB、YUV、CMYK 等。用户可以根据需要将图像转换为不同的格式。
- **医学影像:**医学影像设备通常使用 DICOM 格式来存储图像数据。为了在显示器上显示图像,需要将 DICOM 格式转换为 RGB 格式。
- 图像旋转:IPA支持对图像进行90°、180°、270°的旋转操作。这个感觉不常用,因为一般实际应用中的旋转大部分是任意角度的, 固定角度的旋转 不常用 ,但是遇到摄像头装的方向不对时,可以调整..
- 图像缩放:支持对图像进行缩放,可以是放大或缩小。
IPA的高级功能
- 图像融合:IPA能够将两幅图像进行融合操作,支持不同的融合模式和透明度设置。
- 色彩空间转换:除了基本的像素格式转换,IPA还支持更复杂的色彩空间转换,如从RGB转换到YCbCr等。色彩空间转换在图像处理和多媒体应用中非常重要,它允许不同设备间图像色彩的一致性和准确性的表达。GD32H7的图像处理加速器(IPA)能够转换色彩空间,这意味着它可以将图像数据从一种色彩格式转换到另一种色彩格式,为不同的应用场景和设备兼容性提供支持。
-
实际应用中的意义
-
显示设备兼容性:不同的显示设备可能采用不同的色彩空间,例如RGB和YCbCr等。IPA能够转换色彩空间,确保图像在不同的显示设备上能够保持色彩的真实性和一致性。
-
图像压缩和存储:某些色彩空间可能更适合于图像压缩和存储。例如,YCbCr色彩空间通常用于视频压缩,因为它能有效降低数据量而保持可接受的视觉质量。IPA的色彩空间转换功能可以在图像被显示之前,将存储或传输中的色彩空间转换为适合于显示的色彩空间。
-
图像编辑和处理:在图像编辑和后期处理中,色彩空间转换可以用于调整图像的色调、饱和度和亮度,以实现更丰富的视觉效果和更精确的色彩控制。
-
适用的情景
-
多媒体播放器:在多媒体播放器中,视频内容可能以YCbCr色彩空间存储,而显示器使用RGB色彩空间。IPA可以在视频播放过程中实时转换色彩空间,保证视频显示的准确性。
-
数字摄影:数字相机通常使用特定的色彩空间来捕获图像。IPA可以用于在图像查看或编辑前,将图像从摄影色彩空间转换到显示器或打印机支持的色彩空间。
-
视频会议和监控系统:视频会议和监控系统中,摄像头捕捉的原始视频数据可能需要转换色彩空间后才能在终端设备上正确显示,或者进行编码传输。IPA提供的色彩空间转换功能可以优化这一处理流程。
-
图像格式转换工具:开发图像格式转换或处理软件时,IPA的色彩空间转换能力可以提高处理速度和效率,支持多种图像格式之间的转换和编辑。
-
- 图像滤波:IPA支持简单的图像滤波操作,如平滑和锐化滤波。
在实际应用中,GD32H7的IPA(Image Pixel Accelerator)的 像素格式转换 具有以下意义和适用情景:
-
兼容性:不同的设备或系统可能采用不同的像素格式,通过IPA可以实现不同格式之间的相互转换,从而增强了系统的兼容性。
-
显示适配:某些显示设备或显示驱动器可能只支持特定的像素格式,而图片源数据的格式可能与其不匹配。使用IPA可以将图片源数据转换为与显示设备兼容的格式,从而确保正常显示。
-
图像处理:在图像处理过程中,可能需要将图像数据从一种格式转换为另一种格式,以便进行特定的处理或分析。通过IPA可以实现这种转换,从而支持更多的图像处理算法和应用。实现特殊图像效果:不同的像素格式可以呈现不同的图像效果。例如黑白图像、灰度图像、伪彩色图像等。
-
节省存储空间:某些像素格式可能会占用更多的存储空间,而某些应用场景对存储空间有限。通过将图像数据转换为更为紧凑的格式,可以节省存储空间。
-
优化性能:某些像素格式可能会对处理器或图形加速器的性能产生影响。通过将图像数据转换为更适合当前硬件处理的格式,可以提高系统性能。
GD32H7的IPA基本使用方法
GD32H7的IPA(Image Pixel Accelerator)是一种硬件加速器,设计用于加速图像处理操作,如像素格式转换、图像缩放和图像叠加等。使用IPA可以提高图像处理的效率,减少CPU的负担,特别是在图形界面应用中非常有用。
要使用IPA,通常需要进行以下步骤:
- 配置IPA的工作模式和参数,如输入和输出图像的地址、尺寸和像素格式。
- 根据需要启用IPA的DMA传输,以便自动地将处理后的图像数据传输到目标地址。
- 启动IPA处理。
- 等待IPA处理完成。可以通过轮询状态位或配置中断来完成。
IPA配置过程中的一些主要参数及其意义和作用:
1. 像素格式转换模式
- 参数:
ipa_pixel_format_convert_mode_set()
- 意义:定义了输入图像数据和输出图像数据的像素格式转换方式。
- 作用:使得IPA能够将图像数据从一种格式转换为另一种格式,如从RGB转换为YUV,或反之,满足不同显示设备或图像处理要求的格式。
2. 目标像素格式
- 参数:
destination_pf
(在ipa_destination_parameter_struct
结构体中) - 意义:指定了输出图像的像素格式。
- 作用:确保图像数据转换后的格式符合输出设备(如LCD)的要求或其他处理流程的需求。
3. 目标内存基地址
- 参数:
destination_memaddr
(在ipa_destination_parameter_struct
结构体中) - 意义:指定了转换后的图像数据存放的内存起始地址。
- 作用:确保IPA处理后的图像数据被正确地存储在指定的内存位置,供后续显示或进一步处理。
4. 前景预定义的alpha值
- 参数:
foreground_prealpha
(在ipa_foreground_parameter_struct
结构体中) - 意义:为整个前景图像设置统一的alpha透明度值。
- 作用:用于在混合操作中调整前景图像的透明度,实现透明效果或图像覆盖。
5. Alpha计算模式
- 参数:
foreground_alpha_algorithm
(在ipa_foreground_parameter_struct
结构体中) - 意义:定义了如何计算最终像素的alpha值。
- 作用:支持多种alpha混合算法,可实现不同的图像透明度混合效果,如加权混合或透明度覆盖等。
6. 前景/背景像素格式
- 参数:
foreground_pf
和background_pf
- 意义:指定了前景和背景图像的像素格式。
- 作用:确保图像混合或格式转换过程中,前景和背景数据的格式被正确解析和处理。
7. 图像大小和行偏移量
- 参数:
image_height
,image_width
,foreground_lineoff
- 意义:定义了待处理图像的尺寸和每行数据的偏移量。
- 作用:控制图像处理的范围和数据排列,确保图像数据按照预期方式进行处理。
8. 交错模式
- 参数:
foreground_interlace_mode
- 意义:指定是否以交错方式处理图像数据。
- 作用:适用于处理交错扫描的视频流,保持视频质量和连贯性。
在配置IPA参数时的一些基本概念
ipa_foreground_init()
前景预定义的alpha值 foreground_prealpha
- 概念:Alpha值用于定义像素的透明度。前景预定义的alpha值是在图像融合或者alpha混合操作中,前景图像像素的默认透明度值。这个值会根据设置的alpha计算模式与前景像素的实际alpha值(如果存在)一起决定最终的像素透明度。
Alpha计算模式 foreground_alpha_algorithm
- 概念:Alpha计算模式定义了如何根据前景图像的alpha值与预定义的alpha值来计算最终的像素透明度。GD32H7的IPA支持多种alpha混合算法,例如完全覆盖(前景完全替代背景)、混合(前景和背景根据各自的alpha值混合)等。
- 模式示例:
IPA_FG_ALPHA_MODE_0
:可能指一种基本的混合模式,例如使用前景图像的alpha值直接替换。IPA_FG_ALPHA_MODE_1
、IPA_FG_ALPHA_MODE_2
:可能引入更复杂的混合策略,如加权混合,或支持预乘alpha值的混合等。
前景预定义的颜色值
- 概念:前景预定义的红、绿、蓝色值允许用户为整个前景图像设置一个统一的颜色调整或色彩偏移。这在需要对前景图像进行颜色校正或特殊效果处理时非常有用。
交错模式 foreground_interlace_mode
- 概念:交错模式通常用于处理交错视频信号,在这种模式下,图像的每一帧由两个字段组成,先传输奇数行(或偶数行),然后是偶数行(或奇数行)。启用交错模式意味着IPA会以特定的方式处理这种类型的图像数据,以保持视频播放的连贯性和质量。
前景偶帧/UV内存基地址 foreground_efuv_memaddr
- 概念:在处理YUV格式或其他需要UV分量的图像数据时,
foreground_efuv_memaddr
指定了UV分量数据的内存起始地址。这在进行像素格式转换时尤其重要,确保Y分量和UV分量都能被正确地处理和映射。
背景Alpha计算模式 (ipa_background_init() )
在图像处理中,alpha值决定了像素的透明度,其中alpha值的范围通常是0到255(0表示完全透明,255表示完全不透明)。背景alpha计算模式用于确定如何结合背景像素和前景像素的alpha值来计算最终像素的alpha值。
模式说明
-
IPA_BG_ALPHA_MODE_0:这种模式可能表示使用固定的背景alpha值,不考虑前景像素的alpha值。这意味着无论前景像素的透明度如何,背景像素的透明度都保持不变。
-
IPA_FG_ALPHA_MODE_1:这种模式可能表示完全使用前景的alpha值,忽略背景的预定义alpha值。这意味着最终的像素透明度将完全由前景像素的alpha值决定。
-
IPA_FG_ALPHA_MODE_2:这种模式可能表示前景和背景的alpha值都被考虑在内,通过某种算法(如加权平均)来计算最终像素的alpha值。这可以用于创建混合效果,其中前景和背景都部分透明,最终像素的透明度是前景和背景透明度的某种组合。
视觉效果
-
固定背景透明度(MODE_0):无论前景如何,背景保持其预定义的透明度。这适用于情况,比如在不干扰背景视觉效果的情况下,叠加前景信息。
-
完全前景透明度(MODE_1):背景的透明度被前景完全覆盖,只显示前景的透明效果。这适合前景需要完全展示,而背景只是作为装饰的场景。
-
混合透明度(MODE_2):前景和背景的透明度被结合,创建一个混合的透明效果。这适合需要将前景和背景融合在一起的复杂视觉效果,如阴影效果或透明图层叠加。
IPA 例子
#include "gd32h7xx.h"
#include "systick.h"
#include <stdio.h>
#include "gd32h759i_eval.h"
#include "image1.h"
#include "image2.h"
#include "image3.h"
#include "image4.h"
#include "image5.h"
#include "image6.h"
#include "image7.h"
#include "image8.h"
#include "image9.h"
#include "image10.h"
#include "image11.h"
#include "image12.h"
#if defined (__clang__)
#include "logo.h"
#elif defined ( __ICCARM__ )
#include "logo_iar.h"
#endif
// 定义显示设备的同步脉冲和有效显示区域参数
// 水平方向参数
#define HORIZONTAL_SYNCHRONOUS_PULSE 41 // 水平同步脉冲宽度
#define HORIZONTAL_BACK_PORCH 2 // 水平后 porch 宽度
#define ACTIVE_WIDTH 480 // 水平有效显示宽度
#define HORIZONTAL_FRONT_PORCH 2 // 水平前 porch 宽度
// 垂直方向参数
#define VERTICAL_SYNCHRONOUS_PULSE 10 // 垂直同步脉冲高度
#define VERTICAL_BACK_PORCH 2 // 垂直后 porch 高度
#define ACTIVE_HEIGHT 272 // 垂直有效显示高度
#define VERTICAL_FRONT_PORCH 2 // 垂直前 porch 高度
__ALIGNED(16) uint8_t blended_address_buffer[58292];
static void ipa_config(uint32_t baseaddress);
static void tli_config(void);
static void tli_blend_config(void);
static void tli_gpio_config(void);
static void lcd_config(void);
static void cache_enable(void);
/*!
\brief main program
\param[in] none
\param[out] none
\retval none
*/
int main(void)
{
/* enable the CPU cache */
cache_enable();
/* configure the SysTick, TLI */
systick_config();
lcd_config();
/* enable TLI layers */
tli_layer_enable(LAYER0);
tli_layer_enable(LAYER1);
tli_reload_config(TLI_FRAME_BLANK_RELOAD_EN);
/* enable TLI */
tli_enable();
/* configure TLI and display blend image */
tli_blend_config();
tli_reload_config(TLI_REQUEST_RELOAD_EN);
while(1) {
/* IPA configuration and display the images one by one */
ipa_config((uint32_t)&gImage_image1);
ipa_transfer_enable();
while(RESET == ipa_interrupt_flag_get(IPA_INT_FLAG_FTF));
delay_1ms(50);
ipa_config((uint32_t)&gImage_image2);
ipa_transfer_enable();
while(RESET == ipa_interrupt_flag_get(IPA_INT_FLAG_FTF));
delay_1ms(50);
ipa_config((uint32_t)&gImage_image3);
ipa_transfer_enable();
while(RESET == ipa_interrupt_flag_get(IPA_INT_FLAG_FTF));
delay_1ms(50);
ipa_config((uint32_t)&gImage_image4);
ipa_transfer_enable();
while(RESET == ipa_interrupt_flag_get(IPA_INT_FLAG_FTF));
delay_1ms(50);
ipa_config((uint32_t)&gImage_image5);
ipa_transfer_enable();
while(RESET == ipa_interrupt_flag_get(IPA_INT_FLAG_FTF));
delay_1ms(50);
ipa_config((uint32_t)&gImage_image6);
ipa_transfer_enable();
while(RESET == ipa_interrupt_flag_get(IPA_INT_FLAG_FTF));
delay_1ms(50);
ipa_config((uint32_t)&gImage_image7);
ipa_transfer_enable();
while(RESET == ipa_interrupt_flag_get(IPA_INT_FLAG_FTF));
delay_1ms(50);
ipa_config((uint32_t)&gImage_image8);
ipa_transfer_enable();
while(RESET == ipa_interrupt_flag_get(IPA_INT_FLAG_FTF));
delay_1ms(50);
ipa_config((uint32_t)&gImage_image9);
ipa_transfer_enable();
while(RESET == ipa_interrupt_flag_get(IPA_INT_FLAG_FTF));
delay_1ms(50);
ipa_config((uint32_t)&gImage_image10);
ipa_transfer_enable();
while(RESET == ipa_interrupt_flag_get(IPA_INT_FLAG_FTF));
delay_1ms(50);
ipa_config((uint32_t)&gImage_image11);
ipa_transfer_enable();
while(RESET == ipa_interrupt_flag_get(IPA_INT_FLAG_FTF));
delay_1ms(50);
ipa_config((uint32_t)&gImage_image12);
ipa_transfer_enable();
while(RESET == ipa_interrupt_flag_get(IPA_INT_FLAG_FTF));
delay_1ms(50);
}
}
/*!
\brief LCD Configuration
\param[in] none
\param[out] none
\retval none
*/
static void lcd_config(void)
{
/* configure the GPIO of TLI */
tli_gpio_config();
/* configure TLI peripheral */
tli_config();
}
/*!
\brief 配置TLI外设
\param[in] 无
\param[out] 无
\retval 无
*/
static void tli_config(void)
{
tli_parameter_struct tli_init_struct; // TLI配置结构体
tli_layer_parameter_struct tli_layer_init_struct; // TLI层配置结构体
// 启用TLI外设的时钟
rcu_periph_clock_enable(RCU_TLI);
tli_gpio_config(); // 配置TLI相关的GPIO
// 配置PLL2时钟:CK_PLL2P/CK_PLL2Q/CK_PLL2R = HXTAL_VALUE / 25 * 150 / 3
rcu_pll_input_output_clock_range_config(IDX_PLL2, RCU_PLL2RNG_1M_2M, RCU_PLL2VCO_150M_420M);
if(ERROR == rcu_pll2_config(25, 150, 3, 3, 3)) {
while(1) {
}
}
// 启用PLL2R时钟输出并配置TLI时钟分频
rcu_pll_clock_output_enable(RCU_PLL2R);
rcu_tli_clock_div_config(RCU_PLL2R_DIV8);
// 启用PLL2时钟
rcu_osci_on(RCU_PLL2_CK);
// 等待PLL2时钟稳定
if(ERROR == rcu_osci_stab_wait(RCU_PLL2_CK)) {
while(1) {
}
}
/* 配置TLI参数结构体 */
// 配置水平同步、垂直同步、DE及像素时钟极性
tli_init_struct.signalpolarity_hs = TLI_HSYN_ACTLIVE_LOW;
tli_init_struct.signalpolarity_vs = TLI_VSYN_ACTLIVE_LOW;
tli_init_struct.signalpolarity_de = TLI_DE_ACTLIVE_LOW;
tli_init_struct.signalpolarity_pixelck = TLI_PIXEL_CLOCK_TLI;
// 配置LCD显示时序参数
tli_init_struct.synpsz_hpsz = HORIZONTAL_SYNCHRONOUS_PULSE - 1;
tli_init_struct.synpsz_vpsz = VERTICAL_SYNCHRONOUS_PULSE - 1;
tli_init_struct.backpsz_hbpsz = HORIZONTAL_SYNCHRONOUS_PULSE + HORIZONTAL_BACK_PORCH - 1;
tli_init_struct.backpsz_vbpsz = VERTICAL_SYNCHRONOUS_PULSE + VERTICAL_BACK_PORCH - 1;
tli_init_struct.activesz_hasz = HORIZONTAL_SYNCHRONOUS_PULSE + HORIZONTAL_BACK_PORCH + ACTIVE_WIDTH
- 1;
tli_init_struct.activesz_vasz = VERTICAL_SYNCHRONOUS_PULSE + VERTICAL_BACK_PORCH + ACTIVE_HEIGHT -
1;
tli_init_struct.totalsz_htsz = HORIZONTAL_SYNCHRONOUS_PULSE + HORIZONTAL_BACK_PORCH + ACTIVE_WIDTH +
HORIZONTAL_FRONT_PORCH - 1;
tli_init_struct.totalsz_vtsz = VERTICAL_SYNCHRONOUS_PULSE + VERTICAL_BACK_PORCH + ACTIVE_HEIGHT +
VERTICAL_FRONT_PORCH - 1;
// 配置LCD背景RGB颜色
tli_init_struct.backcolor_red = 0xFF;
tli_init_struct.backcolor_green = 0xFF;
tli_init_struct.backcolor_blue = 0xFF;
tli_init(&tli_init_struct); // 初始化TLI
/*
* TLI(Transport Layer Interface)层配置
* 此代码段初始化了一个TLI层的配置结构体,并设置了TLI层0的参数。
* 配置包括窗口的位置、颜色格式、透明度、帧缓冲区地址等。
*/
/* 设置TLI层窗口的左边界位置 */
tli_layer_init_struct.layer_window_leftpos = 80 + HORIZONTAL_SYNCHRONOUS_PULSE +
HORIZONTAL_BACK_PORCH + 2;
/* 设置TLI层窗口的右边界位置 */
tli_layer_init_struct.layer_window_rightpos = (80 + 320 + HORIZONTAL_SYNCHRONOUS_PULSE +
HORIZONTAL_BACK_PORCH - 1);
/* 设置TLI层窗口的上边界位置 */
tli_layer_init_struct.layer_window_toppos = 150 + VERTICAL_SYNCHRONOUS_PULSE + VERTICAL_BACK_PORCH;
/* 设置TLI层窗口的下边界位置 */
tli_layer_init_struct.layer_window_bottompos = (150 + 100 + VERTICAL_SYNCHRONOUS_PULSE +
VERTICAL_BACK_PORCH - 1);
/* 设置TLI层的颜色格式为RGB565 */
tli_layer_init_struct.layer_ppf = LAYER_PPF_RGB565;
/* 设置层的饱和度调整因子为最大值 */
tli_layer_init_struct.layer_sa = 0xFF;
/* 设置层的默认蓝色成分值为最大值 */
tli_layer_init_struct.layer_default_blue = 0xFF;
/* 设置层的默认绿色成分值为最大值 */
tli_layer_init_struct.layer_default_green = 0xFF;
/* 设置层的默认红色成分值为最大值 */
tli_layer_init_struct.layer_default_red = 0xFF;
/* 设置层的默认透明度为不透明 */
tli_layer_init_struct.layer_default_alpha = 0x0;
/* 设置层的ACF1属性为PASA */
tli_layer_init_struct.layer_acf1 = LAYER_ACF1_PASA;
/* 设置层的ACF2属性为PASA */
tli_layer_init_struct.layer_acf2 = LAYER_ACF2_PASA;
/* 设置层的帧缓冲区地址 */
tli_layer_init_struct.layer_frame_bufaddr = (uint32_t)gImage_logo;
/* 设置层的帧缓冲区每行字节数 */
tli_layer_init_struct.layer_frame_line_length = ((320 * 2) + 3);
/* 设置层的帧缓冲区步长 */
tli_layer_init_struct.layer_frame_buf_stride_offset = (320 * 2);
/* 设置层的总行数 */
tli_layer_init_struct.layer_frame_total_line_number = 100;
/* 初始化TLI层0并应用配置 */
tli_layer_init(LAYER0, &tli_layer_init_struct);
}
/*
* 函数名称:ipa_config
* 功能描述:初始化并配置IPA(图像处理加速器),包括设置像素格式转换模式、目标内存地址、前景图等。
* 参数说明:baseaddress - 输入前景图像 的基础地址。
* 返回值:无。
*/
static void ipa_config(uint32_t baseaddress)
{
ipa_destination_parameter_struct ipa_destination_init_struct; // 定义IPA目标配置结构体
ipa_foreground_parameter_struct ipa_fg_init_struct; // 定义IPA前景图配置结构体
// 启用IPA的时钟
rcu_periph_clock_enable(RCU_IPA);
// 初始化IPA
ipa_deinit();
/* 配置IPA像素格式转换模式 */
ipa_pixel_format_convert_mode_set(IPA_FGTODE);
/* 配置目标像素格式 */
ipa_destination_init_struct.destination_pf = IPA_DPF_RGB565;
/* 配置目标内存基地址 */
ipa_destination_init_struct.destination_memaddr = (uint32_t)&blended_address_buffer;
/* 配置目标预定义的Alpha值(RGB) */
ipa_destination_init_struct.destination_pregreen = 0;
ipa_destination_init_struct.destination_preblue = 0;
ipa_destination_init_struct.destination_prered = 0;
ipa_destination_init_struct.destination_prealpha = 0;
/* 配置目标行偏移量 */
ipa_destination_init_struct.destination_lineoff = 0;
/* 配置待处理图像的高度 */
ipa_destination_init_struct.image_height = 118;
/* 配置待处理图像的宽度 */
ipa_destination_init_struct.image_width = 247;
ipa_destination_init_struct.image_rotate = DESTINATION_ROTATE_0;
ipa_destination_init_struct.image_hor_decimation = DESTINATION_HORDECIMATE_DISABLE;
ipa_destination_init_struct.image_ver_decimation = DESTINATION_VERDECIMATE_DISABLE;
/* 初始化IPA目标配置 */
ipa_destination_init(&ipa_destination_init_struct);
/* 配置IPA前景图初始化结构体 */
/* baseaddress: 前景图内存地址的起始位置 */
ipa_fg_init_struct.foreground_memaddr = baseaddress;
/* 设置前景图的像素格式为RGB565 */
ipa_fg_init_struct.foreground_pf = FOREGROUND_PPF_RGB565;
/* 设置前景图的透明度计算模式为模式0 */
ipa_fg_init_struct.foreground_alpha_algorithm = IPA_FG_ALPHA_MODE_0;
/* 设置前景图的预透明值为0 */
ipa_fg_init_struct.foreground_prealpha = 0x0;
/* 设置前景图的行偏移为0 */
ipa_fg_init_struct.foreground_lineoff = 0x0;
/* 设置前景图的预蓝色值为0 */
ipa_fg_init_struct.foreground_preblue = 0x0;
/* 设置前景图的预绿色值为0 */
ipa_fg_init_struct.foreground_pregreen = 0x0;
/* 设置前景图的预红色值为0 */
ipa_fg_init_struct.foreground_prered = 0x0;
/* 前景图初始化 */
ipa_foreground_init(&ipa_fg_init_struct);
}
/*!
\brief configure TLI peripheral and display blend image
这个函数负责配置TLI(Thin-Layer Interface)
以进行图像的混合显示。在此函数中,通常会进行层(Layer)的配置,
包括层的背景色、透明度、图像数据源等。
它可能还会设置图像的大小、位置以及如何将多个图像层混合在一起显示的具体参数。
\param[in] none
\param[out] none
\retval none
*/
static void tli_blend_config(void)
{
// 初始化TLI(Terminal Layer Interface)相关的参数和硬件设置
// 此段代码主要配置TLI的时钟源、PLL2的输入输出时钟范围,并启用PLL2时钟输出。
tli_parameter_struct tli_init_struct;
tli_layer_parameter_struct tli_layer_init_struct;
rcu_periph_clock_enable(RCU_TLI); // 启用TLI的外设时钟
tli_gpio_config(); // 配置TLI相关的GPIO
/* 配置PLL2的输入时钟范围和输出时钟范围 */
rcu_pll_input_output_clock_range_config(IDX_PLL2, RCU_PLL2RNG_1M_2M, RCU_PLL2VCO_150M_420M);
/* 配置PLL2时钟:CK_PLL2P/CK_PLL2Q/CK_PLL2R = HXTAL_VALUE / 25 * 150 / 3 */
if(ERROR == rcu_pll2_config(25, 150, 3, 3, 3)) {
while(1) {
}
}
/* 启用PLL2R时钟输出 */
rcu_pll_clock_output_enable(RCU_PLL2R);
rcu_tli_clock_div_config(RCU_PLL2R_DIV8); // 配置TLI时钟分频
rcu_osci_on(RCU_PLL2_CK); // 开启PLL2时钟
if(ERROR == rcu_osci_stab_wait(RCU_PLL2_CK)) { // 等待PLL2时钟稳定
while(1) {
}
}
/*
* 配置TLI(Transport Layer Interface)参数结构体
* 本段代码主要负责初始化TLI参数结构体,并设置LCD显示时序配置和背景颜色。
*/
/* 配置TLI参数结构体中的信号极性 */
tli_init_struct.signalpolarity_hs = TLI_HSYN_ACTLIVE_LOW; /* 水平同步信号极性配置为活动低电平 */
tli_init_struct.signalpolarity_vs = TLI_VSYN_ACTLIVE_LOW; /* 垂直同步信号极性配置为活动低电平 */
tli_init_struct.signalpolarity_de = TLI_DE_ACTLIVE_LOW; /* 数据使能信号极性配置为活动低电平 */
tli_init_struct.signalpolarity_pixelck = TLI_PIXEL_CLOCK_TLI; /* 像素时钟极性配置 */
/* 配置LCD显示时序 */
tli_init_struct.synpsz_hpsz = HORIZONTAL_SYNCHRONOUS_PULSE - 1; /* 水平同步脉冲宽度配置 */
tli_init_struct.synpsz_vpsz = VERTICAL_SYNCHRONOUS_PULSE - 1; /* 垂直同步脉冲宽度配置 */
tli_init_struct.backpsz_hbpsz = HORIZONTAL_SYNCHRONOUS_PULSE + HORIZONTAL_BACK_PORCH - 1; /* 水平方向后 porch 宽度配置 */
tli_init_struct.backpsz_vbpsz = VERTICAL_SYNCHRONOUS_PULSE + VERTICAL_BACK_PORCH - 1; /* 垂直方向后 porch 宽度配置 */
tli_init_struct.activesz_hasz = HORIZONTAL_SYNCHRONOUS_PULSE + HORIZONTAL_BACK_PORCH + ACTIVE_WIDTH
- 1; /* 水平方向活动区域宽度配置 */
tli_init_struct.activesz_vasz = VERTICAL_SYNCHRONOUS_PULSE + VERTICAL_BACK_PORCH + ACTIVE_HEIGHT -
1; /* 垂直方向活动区域高度配置 */
tli_init_struct.totalsz_htsz = HORIZONTAL_SYNCHRONOUS_PULSE + HORIZONTAL_BACK_PORCH + ACTIVE_WIDTH +
HORIZONTAL_FRONT_PORCH - 1; /* 水平方向总线周期配置 */
tli_init_struct.totalsz_vtsz = VERTICAL_SYNCHRONOUS_PULSE + VERTICAL_BACK_PORCH + ACTIVE_HEIGHT +
VERTICAL_FRONT_PORCH - 1; /* 垂直方向总线周期配置 */
/* 配置LCD背景颜色(红色、绿色、蓝色) */
tli_init_struct.backcolor_red = 0xFF; /* 背景红色值配置 */
tli_init_struct.backcolor_green = 0xFF; /* 背景绿色值配置 */
tli_init_struct.backcolor_blue = 0xFF; /* 背景蓝色值配置 */
/* 应用TLI初始化结构体配置 */
tli_init(&tli_init_struct);
/*
* TLI(Transfer Layer Interface)层1配置
* 此代码段初始化TLI层1的设置,包括窗口位置、像素格式、默认颜色及缓冲区配置等。
*/
/* 设置TLI层1的窗口左边界位置 */
tli_layer_init_struct.layer_window_leftpos = 80 + HORIZONTAL_SYNCHRONOUS_PULSE +
HORIZONTAL_BACK_PORCH + 2;
/* 设置TLI层1的窗口右边界位置 */
tli_layer_init_struct.layer_window_rightpos = (80 + 247 + HORIZONTAL_SYNCHRONOUS_PULSE +
HORIZONTAL_BACK_PORCH - 1);
/* 设置TLI层1的窗口上边界位置 */
tli_layer_init_struct.layer_window_toppos = 20 + VERTICAL_SYNCHRONOUS_PULSE + VERTICAL_BACK_PORCH;
/* 设置TLI层1的窗口下边界位置 */
tli_layer_init_struct.layer_window_bottompos = 20 + 118 + VERTICAL_SYNCHRONOUS_PULSE +
VERTICAL_BACK_PORCH - 1;
/* 配置TLI层1的像素格式为RGB565 */
tli_layer_init_struct.layer_ppf = LAYER_PPF_RGB565;
/* 设置层的alpha混合因子为全透 */
tli_layer_init_struct.layer_sa = 0xFF;
/* 配置层的ACF1参数为PASA */
tli_layer_init_struct.layer_acf1 = LAYER_ACF1_PASA;
/* 配置层的ACF2参数为PASA */
tli_layer_init_struct.layer_acf2 = LAYER_ACF2_PASA;
/* 设置层的默认Alpha值为0 */
tli_layer_init_struct.layer_default_alpha = 0;
/* 设置层的默认蓝色值为0 */
tli_layer_init_struct.layer_default_blue = 0;
/* 设置层的默认绿色值为0 */
tli_layer_init_struct.layer_default_green = 0;
/* 设置层的默认红色值为0 */
tli_layer_init_struct.layer_default_red = 0;
/* 设置层的帧缓冲区地址 */
tli_layer_init_struct.layer_frame_bufaddr = (uint32_t)&blended_address_buffer;
/* 设置层的帧缓冲区每行长度 */
tli_layer_init_struct.layer_frame_line_length = ((247 * 2) + 3);
/* 设置层的帧缓冲区步长偏移 */
tli_layer_init_struct.layer_frame_buf_stride_offset = (247 * 2);
/* 设置层的帧缓冲区总行数 */
tli_layer_init_struct.layer_frame_total_line_number = 118;
/* 初始化TLI层1 */
tli_layer_init(LAYER1, &tli_layer_init_struct);
}
/*!
\brief configure TLI GPIO
\param[in] none
\param[out] none
\retval none
*/
static void tli_gpio_config(void)
{
/* enable GPIO clock */
rcu_periph_clock_enable(RCU_GPIOA);
rcu_periph_clock_enable(RCU_GPIOB);
rcu_periph_clock_enable(RCU_GPIOC);
rcu_periph_clock_enable(RCU_GPIOD);
rcu_periph_clock_enable(RCU_GPIOE);
rcu_periph_clock_enable(RCU_GPIOF);
rcu_periph_clock_enable(RCU_GPIOH);
rcu_periph_clock_enable(RCU_GPIOG);
/* configure HSYNC(PE15), VSYNC(PA7), PCLK(PG7) */
gpio_af_set(GPIOE, GPIO_AF_14, GPIO_PIN_15);
gpio_af_set(GPIOA, GPIO_AF_14, GPIO_PIN_7);
gpio_af_set(GPIOG, GPIO_AF_14, GPIO_PIN_7);
gpio_mode_set(GPIOE, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_15);
gpio_output_options_set(GPIOE, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_15);
gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_7);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_7);
gpio_mode_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_7);
gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_7);
/* configure LCD_R7(PG6), LCD_R6(PH12), LCD_R5(PH11), LCD_R4(PA5), LCD_R3(PH9),LCD_R2(PH8),
LCD_R1(PH3), LCD_R0(PH2) */
gpio_af_set(GPIOG, GPIO_AF_14, GPIO_PIN_6);
gpio_af_set(GPIOH, GPIO_AF_14, GPIO_PIN_12);
gpio_af_set(GPIOH, GPIO_AF_14, GPIO_PIN_11);
gpio_af_set(GPIOA, GPIO_AF_14, GPIO_PIN_5);
gpio_af_set(GPIOH, GPIO_AF_14, GPIO_PIN_9);
gpio_af_set(GPIOH, GPIO_AF_14, GPIO_PIN_8);
gpio_af_set(GPIOH, GPIO_AF_14, GPIO_PIN_3);
gpio_af_set(GPIOH, GPIO_AF_14, GPIO_PIN_2);
gpio_mode_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_6);
gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_6);
gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_12);
gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_12);
gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_11);
gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_11);
gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_5);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_5);
gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_9);
gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_9);
gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_8);
gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_8);
gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_3);
gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_3);
gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_2);
gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_2);
/* configure LCD_G7(PD3), LCD_G6(PC7), LCD_G5(PC1), LCD_G4(PH15), LCD_G3(PH14), LCD_G2(PH13),LCD_G1(PB0), LCD_G0(PB1) */
gpio_af_set(GPIOD, GPIO_AF_14, GPIO_PIN_3);
gpio_af_set(GPIOC, GPIO_AF_14, GPIO_PIN_7);
gpio_af_set(GPIOC, GPIO_AF_14, GPIO_PIN_1);
gpio_af_set(GPIOH, GPIO_AF_14, GPIO_PIN_15);
gpio_af_set(GPIOH, GPIO_AF_14, GPIO_PIN_14);
gpio_af_set(GPIOH, GPIO_AF_14, GPIO_PIN_13);
gpio_af_set(GPIOB, GPIO_AF_14, GPIO_PIN_0);
gpio_af_set(GPIOB, GPIO_AF_14, GPIO_PIN_1);
gpio_mode_set(GPIOD, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_3);
gpio_output_options_set(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_3);
gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_7);
gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_7);
gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_1);
gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_1);
gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_15);
gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_15);
gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_14);
gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_14);
gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_13);
gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_13);
gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_0);
gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_0);
gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_1);
gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_1);
/* configure LCD_B7(PB9), LCD_B6(PB8), LCD_B5(PB5), LCD_B4(PC11), LCD_B3(PG11),LCD_B2(PG10), LCD_B1(PG12), LCD_B0(PG14) */
gpio_af_set(GPIOB, GPIO_AF_14, GPIO_PIN_9);
gpio_af_set(GPIOB, GPIO_AF_14, GPIO_PIN_8);
gpio_af_set(GPIOB, GPIO_AF_3, GPIO_PIN_5);
gpio_af_set(GPIOC, GPIO_AF_14, GPIO_PIN_11);
gpio_af_set(GPIOG, GPIO_AF_14, GPIO_PIN_11);
gpio_af_set(GPIOG, GPIO_AF_14, GPIO_PIN_10);
gpio_af_set(GPIOG, GPIO_AF_14, GPIO_PIN_12);
gpio_af_set(GPIOG, GPIO_AF_14, GPIO_PIN_14);
gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_9);
gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_9);
gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_8);
gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_8);
gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_5);
gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_5);
gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_11);
gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_11);
gpio_mode_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_11);
gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_11);
gpio_mode_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_10);
gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_10);
gpio_mode_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_12);
gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_12);
gpio_mode_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_14);
gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_14);
/* configure LCD_DE(PF10) */
gpio_af_set(GPIOF, GPIO_AF_14, GPIO_PIN_10);
gpio_mode_set(GPIOF, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_10);
gpio_output_options_set(GPIOF, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_10);
/* LCD PWM BackLight(PG13) */
gpio_mode_set(GPIOG, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, GPIO_PIN_13);
gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_13);
gpio_bit_set(GPIOG, GPIO_PIN_13);
}
/*!
\brief enable the CPU cache
\param[in] none
\param[out] none
\retval none
*/
static void cache_enable(void)
{
/* enable i-Cache */
SCB_EnableICache();
/* enable d-Cache */
SCB_EnableDCache();
}