C
Qt Quick Ultralite imagedecoder Example
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial
#ifdef __ghs__
#pragma ghs nowarning 2155
#endif
#include "cy_project.h"
#include "cyjpg_def.h"
#include "cyjpg_basetypes.h"
#include "cyjpg_typedef.h"
#include "cyjpg.h"
#include <cygfx_driver_api.h>
#include <cygfx_basetypes.h>
#include <sm_util.h>
#ifdef __ghs__
#pragma ghs endnowarning
#endif
#include <platforminterface/printf.h>
// #define TVII_DEBUG_JPEG_DECODER
/* Subsample type */
// CYJPG_YUV444 (CYJPG_U32) 0
// CYJPG_YUV422 (CYJPG_U32) 1
// CYJPG_YUV411 (CYJPG_U32) 6
// CYJPG_YUV420 (CYJPG_U32) 2
// CYJPG_GRAYSCALE (CYJPG_U32) 3
// CYJPG_CMYK (CYJPG_U32) 4
// CYJPG_INVALID (CYJPG_U32) 7
/* Call Sample Application function if the previous operation did not fail. */
#define CALL_APPL_FUNC(ret_appl, execute) \
do { \
if ((ret_appl) == RES_DEC_SUCCESS) { \
(ret_appl) = (execute); \
} \
} while (0)
/* Call JPEG Deocde Driver function if the previous operation did not fail. */
#define CALL_JPGDRV_FUNC(ret_appl, ret_drv, execute) \
do { \
if ((ret_appl) == RES_DEC_SUCCESS) { \
(ret_drv) = (execute); \
if ((ret_drv) != CYJPG_OK) { \
(ret_appl) = RES_DEC_FAILED_DRIVER; \
} \
} \
} while (0)
/* AXI bus configuration */
CYJPG_AXICTL_S axi_config;
/* IRQ configuration */
CYJPG_IRQCTL_S irq_config;
/* JPEG Decode Core Configuration */
CYJPG_DECODEINFO_S dec_core_config;
/* JPEG Decode Configuration */
CYJPG_JPGINFO_S jpg_config;
/* Configuration for JPEG Driver initialization */
CYJPG_INIT_S init_config;
/* IRQ Configuration for JPEGDEC */
CYJPG_STATIC const cy_stc_sysint_irq_t irq_cfg_jpeg = {
.sysIntSrc =
// Note: There is a better compatibility layer in the pipeline.
#if defined(cyt4en) || defined(tviic2d6mddr)
videoss_0_interrupt_jpegdec_IRQn
#else
jpegdec_interrupt_jpeg_IRQn
#endif
,
.intIdx = CPUIntIdx3_IRQn,
.isEnabled = true,
};
static void jpeg_configuration_init(void)
{
/* AXI bus configuration */
axi_config.arcache = 0U; /* ARCACHE value of AXI transactions on Fetch Unit */
axi_config.awcache = 0U; /* AWCACHE value of AXI transactions on Store Unit */
axi_config.fetchburstlength = 0U; /* Maximum burst length for Fetch Unit */
axi_config.storeburstlength = 0U; /* Maximum burst length for Store Unit */
/* IRQ configuration */
irq_config.decodeintrmask = CYJPG_ENABLE; /* Masks assertion of INTR.CORE due to decoding completion */
irq_config.frameCompleteClear = CYJPG_DISABLE; /* Clear INTR.FRAME_COMPLETE */
irq_config.jpegCoreClear = CYJPG_DISABLE; /* Clear INTR.JPEG_CORE */
irq_config.fetchErrorClear = CYJPG_DISABLE; /* Clear INTR.FETCH_ERROR */
irq_config.storeErrorClear = CYJPG_DISABLE; /* Clear INTR.STORE_ERROR */
irq_config.frameCompleteMask = CYJPG_ENABLE; /* Interrupt mask for FRAME_COMPLETE */
irq_config.jpegCoreMask = CYJPG_ENABLE; /* Interrupt mask for JPEG_CORE */
irq_config.fetchErrorMask = CYJPG_ENABLE; /* Interrupt mask for FETCH_ERROR */
irq_config.storeErrorMask = CYJPG_ENABLE; /* Interrupt mask for STORE_ERROR */
irq_config.appMarkerEn = CYJPG_ENABLE; /* Interrupt Setting for INTR_DEC_EN.APPMARKER */
irq_config.comMarkerEn = CYJPG_ENABLE; /* Interrupt Setting for INTR_DEC_EN.COMMARKER */
irq_config.unknownMarkerEn = CYJPG_ENABLE; /* Interrupt Setting for INTR_DEC_EN.UNKNOWNMARKER */
irq_config.sizeAvailableEn = CYJPG_ENABLE; /* Interrupt Setting for INTR_DEC_EN.SIZEAVAILABLE */
irq_config.errorIntervalEn = CYJPG_DISABLE; /* Interrupt Setting for INTR_DEC_EN.ERRORINTERVAL */
irq_config.errorTotalDataEn = CYJPG_DISABLE; /* Interrupt Setting for INTR_DEC_EN.ERRORTOTALDATA */
irq_config.intMaskEn = CYJPG_DISABLE; /* Interrupt Setting for INTR_DEC_EN.INTMASK */
/* JPEG Decode Core Configuration */
dec_core_config.subsample = 0U; /* Sub-sampling mode defined in SOF marker segment */
dec_core_config.dri = 0U; /* Value downloaded from DRI marker segment */
dec_core_config.sizey = 0U; /* Y size value downloaded from SOF marker segment */
dec_core_config.sizex = 0U; /* X size value downloaded from SOF marker segment */
dec_core_config.cropstarty = 0U; /* Y crop start position */
dec_core_config.cropstartx = 0U; /* X crop start position */
dec_core_config.cropsizey = 0U; /* Crop size for Y direction */
dec_core_config.cropsizex = 0U; /* Crop size for X direction */
/* JPEG Decode Configuration */
jpg_config.fetchAddress = 0; /* Start address of the JPEG image in bytes */
jpg_config.fetchLength = 0; /* JPEG image length in bytes */
jpg_config.storeAddress0 = 0; /* Start address of the destination buffer 0 in multiple of 64 bytes */
jpg_config.storeStride0 = 0; /* Line stride of the destination buffer 0 in multiple of 64 bytes */
jpg_config.storeLength0 = 0; /* Destination buffer 0 length in multiple of 64 bytes */
jpg_config.storeAddress1 = 0; /* Start address of the destination buffer 1 in multiple of 64 bytes */
jpg_config.storeStride1 = 0; /* Line stride of the destination buffer 1 in multiple of 64 bytes */
jpg_config.storeLength1 = 0; /* Destination buffer 1 length in multiple of 64 bytes */
jpg_config.upsamplingEn = CYJPG_DISABLE; /* Decoded pixels are up-sampled to YUV 4:4:4 */
jpg_config.markerskipEn = CYJPG_DISABLE; /* Enable/Disable Marker Skip Function */
jpg_config.cropEn = CYJPG_DISABLE; /* Enable/Disable Crop Function */
jpg_config.correctionEn = CYJPG_DISABLE; /* Enable/Disable Correction Function */
jpg_config.decodeinfo_s = &dec_core_config; /* Pointer to JPEG Decode Core Configuration */
/* JPEG Initial Configuration */
init_config.axictl_s = &axi_config;
init_config.irqctl_s = &irq_config;
init_config.jpginfo_s = &jpg_config;
}
/*****************************************************************************/
/* Macro Definitions */
/*****************************************************************************/
/* Result of Decoding APIs */
#define RES_DEC_SUCCESS 0x0U /* Success */
#define RES_DEC_FAILED_DRIVER 0x101U /* JPEG Driver API failed */
#define RES_DEC_FAILED_ILLEGAL_STATE 0x102U /* Illegal state error */
#define RES_DEC_FAILED_TIMEOUT_AXI 0x103U /* Timeout of AXI inactive timer */
#define RES_DEC_FAILED_CROPAREALIST 0x104U /* Crop areas include errors */
#define RES_DEC_FAILED_ABNORMAL 0x1FFU /* Abnormal error */
/*****************************************************************************/
/* Type Definitions */
/*****************************************************************************/
/* Decode State */
typedef enum {
DEC_STATE_DISABLED = 0, /* Disabled */
DEC_STATE_CONFIG = 1, /* Configuration */
DEC_STATE_DECODING = 2, /* Decoding */
DEC_STATE_SUSPENDED = 3, /* Suspended */
DEC_STATE_SUSPENDED_SIZEAVAIL = 4, /* Suspended (SIZEAVAILABLE) */
DEC_STATE_COMPLETED = 5, /* Completed */
DEC_STATE_RECOVERY = 6 /* Recovery */
} JPG_SAMPLE_DEC_STATE_E;
/* Recovery Cause */
typedef enum {
DEC_RCV_CAUSE_NOTHING = 0, /* No cause */
DEC_RCV_CAUSE_CANCEL = 1, /* Cancel on-going decoding */
DEC_RCV_CAUSE_FETCH_STORE_ERR = 2, /* Fetch/Store Error */
DEC_RCV_CAUSE_INTR_DEC_ERR = 3, /* INTR_DEC Error */
DEC_RCV_CAUSE_NO_NORMAL_CORRECTED = 4, /* NORMALEND/CORRECTEDEND not generated */
DEC_RCV_CAUSE_UNDEFINED_STATE = 5, /* Undefined State */
} JPG_SAMPLE_DEC_RCV_CAUSE_E;
/*****************************************************************************/
/* Local Variables/Constants */
/*****************************************************************************/
CYJPG_STATIC JPG_SAMPLE_DEC_STATE_E decode_state = DEC_STATE_DISABLED; /* Decode State */
CYJPG_STATIC JPG_SAMPLE_DEC_RCV_CAUSE_E recovery_cause = DEC_RCV_CAUSE_NOTHING; /* Recovery Cause */
CYJPG_STATIC CYJPG_BOOL first_dec_comp = CYJPG_FALSE; /* First decode completion */
CYJPG_STATIC CYJPG_BOOL gen_normal_corrected = CYJPG_FALSE; /* NORMALEND/CORRECTEDEND generated Flag */
/** \brief Update Decode State
** \param upd_state [in] Decode state to be updated
** \return result
** RES_DEC_SUCCESS: Success
** RES_DEC_FAILED_ILLEGAL_STATE: Illegal state error
** RES_DEC_FAILED_ABNORMAL: Abnormal error
**
** No remarks
** */
CYJPG_U32 Jpeg_DecUpdateState(JPG_SAMPLE_DEC_STATE_E upd_state)
{
/* Local variables */
CYJPG_U32 ret = RES_DEC_SUCCESS;
/* Check current decode state */
switch (decode_state) {
case DEC_STATE_DISABLED: {
if (upd_state == DEC_STATE_CONFIG) {
/* Update decode state */
decode_state = upd_state;
} else {
/* Illegal state transition */
ret = RES_DEC_FAILED_ILLEGAL_STATE;
}
break;
}
case DEC_STATE_CONFIG: {
if ((upd_state == DEC_STATE_DECODING) || (upd_state == DEC_STATE_DISABLED)) {
decode_state = upd_state;
} else {
ret = RES_DEC_FAILED_ILLEGAL_STATE;
}
break;
}
case DEC_STATE_DECODING: {
if ((upd_state == DEC_STATE_SUSPENDED) || (upd_state == DEC_STATE_SUSPENDED_SIZEAVAIL)
|| (upd_state == DEC_STATE_COMPLETED) || (upd_state == DEC_STATE_RECOVERY)
|| (upd_state == DEC_STATE_DISABLED)) {
decode_state = upd_state;
} else {
ret = RES_DEC_FAILED_ILLEGAL_STATE;
}
break;
}
case DEC_STATE_SUSPENDED:
case DEC_STATE_SUSPENDED_SIZEAVAIL: {
if ((upd_state == DEC_STATE_DECODING) || (upd_state == DEC_STATE_RECOVERY)
|| (upd_state == DEC_STATE_DISABLED)) {
decode_state = upd_state;
} else {
ret = RES_DEC_FAILED_ILLEGAL_STATE;
}
break;
}
case DEC_STATE_COMPLETED: {
if ((upd_state == DEC_STATE_CONFIG) || (upd_state == DEC_STATE_RECOVERY) || (upd_state == DEC_STATE_DISABLED)) {
decode_state = upd_state;
} else {
ret = RES_DEC_FAILED_ILLEGAL_STATE;
}
break;
}
case DEC_STATE_RECOVERY: {
if ((upd_state == DEC_STATE_CONFIG) || (upd_state == DEC_STATE_DISABLED)) {
decode_state = upd_state;
} else {
ret = RES_DEC_FAILED_ILLEGAL_STATE;
}
break;
}
default: {
ret = RES_DEC_FAILED_ABNORMAL;
break;
}
}
return ret;
}
/** \brief Notify NORMALEND/CORRECTEDEND is generated
** \param gen_normal [in] NORMALEND/CORRECTEDEND is generated or not
** \return void
**
** No remarks
** */
void Jpeg_DecNotifyNormalCorrected(CYJPG_BOOL gen_flag)
{
/* Set NORMALEND/CORRECTEDEND generated flag */
gen_normal_corrected = gen_flag;
return;
}
/** \brief Notify cause of recovery
** \param rcv_cause [in] cause of recovery
** \return void
**
** No remarks
** */
void Jpeg_DecNotifyRcvCause(JPG_SAMPLE_DEC_RCV_CAUSE_E rcv_cause)
{
/* Set recovery cause */
recovery_cause = rcv_cause;
return;
}
/*****************************************************************************/
/* Local Functions */
/*****************************************************************************/
/** \brief JPEG Decoder Core Interrupt
** \param No param
** \return void
**
** No remarks
** */
CYJPG_STATIC void Jpeg_kInterruptJpegDecoderCore(CYJPG_IRQSTATUS_S *irq_status)
{
/* Clear IRQ causes of INTR and INTR_DEC */
(void) CyJpg_ClearJpegCoreIrq();
/* Crop Size/MCU Unit Error occurs */
if ((irq_status->sizeAvailable == CYJPG_TRUE)
&& ((irq_status->cropSizeError == CYJPG_TRUE) || (irq_status->mcuUnitError == CYJPG_TRUE))) {
/* Change state to Recovery */
(void) Jpeg_DecUpdateState(DEC_STATE_RECOVERY);
/* Notify recovery cause as undefined status */
Jpeg_DecNotifyRcvCause(DEC_RCV_CAUSE_UNDEFINED_STATE);
}
/* Error interval/Error Total Data/Error marker occurs */
else if ((irq_status->errorInterval == CYJPG_TRUE) || (irq_status->errorTotalData == CYJPG_TRUE)
|| (irq_status->errorMarker == CYJPG_TRUE)) {
/* Change state to Recovery */
(void) Jpeg_DecUpdateState(DEC_STATE_RECOVERY);
/* Notify recovery cause as INTR_DEC error */
Jpeg_DecNotifyRcvCause(DEC_RCV_CAUSE_INTR_DEC_ERR);
}
/* JPEG image size is available */
else if (irq_status->sizeAvailable == CYJPG_TRUE) {
/* Change state to Suspended (SIZEAVAILBLE) */
(void) Jpeg_DecUpdateState(DEC_STATE_SUSPENDED_SIZEAVAIL);
}
/* APP/COM/Unknown Marker is detected or JPEG image size is available */
else if ((irq_status->appMarker == CYJPG_TRUE) || (irq_status->comMarker == CYJPG_TRUE)
|| (irq_status->unknownMarker == CYJPG_TRUE)) {
/* Change state to Suspended */
(void) Jpeg_DecUpdateState(DEC_STATE_SUSPENDED);
} else {
}
/* JPEG decoder core has finished normally */
if ((irq_status->normalEnd == CYJPG_TRUE) || (irq_status->correctedEnd == CYJPG_TRUE)) {
/* Notify NORMALEND/CORRECTEDEND generated */
Jpeg_DecNotifyNormalCorrected(CYJPG_TRUE);
}
return;
}
/** \brief Pixel Data Store Completion Interrupt
** \param irq_state [in] IRQ status
** \return void
**
** No remarks
** */
CYJPG_STATIC void Jpeg_kInterruptPixelDataStoreComp(CYJPG_IRQSTATUS_S *irq_status)
{
/* Clear IRQ cause of Pixel Data Store Completion Interrupt */
(void) CyJpg_ClearFrameCompIrq();
/* Change state to Completed */
(void) Jpeg_DecUpdateState(DEC_STATE_COMPLETED);
if ((irq_status->normalEnd == CYJPG_TRUE) || (irq_status->correctedEnd == CYJPG_TRUE)) {
/* Notify NORMALEND/CORRECTEDEND generated */
Jpeg_DecNotifyNormalCorrected(CYJPG_TRUE);
}
return;
}
/** \brief Fetch Unit Error Interrupt
** \param No param
** \return void
**
** No remarks
** */
CYJPG_STATIC void Jpeg_kInterruptFetchUnitError(void)
{
/* Clear IRQ cause of Fetch Unit Error Interrupt */
(void) CyJpg_SetErrorInfo(CYJPG_FETCH_ERROR);
/* Change state to Recovery */
(void) Jpeg_DecUpdateState(DEC_STATE_RECOVERY);
/* Notify recovery cause as Fetch/Store error */
Jpeg_DecNotifyRcvCause(DEC_RCV_CAUSE_FETCH_STORE_ERR);
return;
}
/** \brief Store Unit Error Interrupt
** \param No param
** \return void
**
** No remarks
** */
CYJPG_STATIC void Jpeg_kInterruptStoreUnitError(void)
{
/* Clear IRQ cause of Store Unit Error Interrupt */
(void) CyJpg_SetErrorInfo(CYJPG_STORE_ERROR);
/* Change state to Recovery */
(void) Jpeg_DecUpdateState(DEC_STATE_RECOVERY);
/* Notify recovery cause as Fetch/Store error */
Jpeg_DecNotifyRcvCause(DEC_RCV_CAUSE_FETCH_STORE_ERR);
return;
}
// JPEGDEC interrupt handler
static void Jpeg_InterruptHandler(void)
{
/* Local variables */
CYJPG_IRQSTATUS_S irq_status; /* JPEG Decoder IRQ Status */
/* Get IRQ cause */
(void) CyJpg_GetJpgIrqCause(&irq_status);
/* Fetch Unit Error Interrupt */
if (irq_status.intrFetchError == CYJPG_TRUE) {
Jpeg_kInterruptFetchUnitError();
}
/* Store Unit Error Interrupt */
if (irq_status.intrStoreError == CYJPG_TRUE) {
Jpeg_kInterruptStoreUnitError();
}
/* JPEG Decoder Core Interrupt */
if (irq_status.intrJpegCore == CYJPG_TRUE) {
Jpeg_kInterruptJpegDecoderCore(&irq_status);
}
/* Pixel Data Store Completion Interrupt */
if (irq_status.intrFrameComplete == CYJPG_TRUE) {
Jpeg_kInterruptPixelDataStoreComp(&irq_status);
}
return;
}
static CYGFX_BE_CONTEXT_OBJECT_S ctx; // drawing context for Blit Engine
static CYGFX_SURFACE_OBJECT_S surfSrc; // source surface
static CYGFX_SURFACE_OBJECT_S surfDst; // destination surface
uint32_t tvii_convert_decoded_buffers(unsigned char *outbuffer,
uint32_t width,
uint32_t height,
uint32_t storeAddress0,
uint32_t storeAddress1,
CYGFX_SM_FORMAT dst_format)
{
uint32_t ret_gfx = 0;
UTIL_SUCCESS(ret_gfx, CyGfx_BeResetContext(&ctx));
UTIL_SUCCESS(ret_gfx, CyGfx_SmResetSurfaceObject(&surfSrc));
UTIL_SUCCESS(ret_gfx, CyGfx_SmAssignBuffer(&surfSrc, width, height, CYGFX_SM_FORMAT_YUV420, 0, 0));
UTIL_SUCCESS(ret_gfx, CyGfx_SmSetAttribute(&surfSrc, CYGFX_SM_ATTR_STRIDE, width));
UTIL_SUCCESS(ret_gfx, CyGfx_SmSetAttribute(&surfSrc, CYGFX_SM_ATTR_VIRT_ADDRESS, storeAddress0));
UTIL_SUCCESS(ret_gfx, CyGfx_SmSetAttribute(&surfSrc, CYGFX_SM_ATTR_VIRT_ADDRESS_SEC, storeAddress1));
UTIL_SUCCESS(ret_gfx, CyGfx_BeBindSurface(&ctx, CYGFX_BE_TARGET_SRC, &surfSrc));
UTIL_SUCCESS(ret_gfx, CyGfx_SmResetSurfaceObject(&surfDst));
UTIL_SUCCESS(ret_gfx, CyGfx_SmAssignBuffer(&surfDst, width, height, dst_format, (void *) outbuffer, 0));
UTIL_SUCCESS(ret_gfx, CyGfx_BeBindSurface(&ctx, CYGFX_BE_TARGET_STORE, &surfDst));
UTIL_SUCCESS(ret_gfx, CyGfx_BeBlt(&ctx, 0, 0));
CyGfx_BeFinish(&ctx);
return ret_gfx;
}
void tvii_jpeg_init(void)
{
// Configuration
jpeg_configuration_init();
// Initialize JPEG Interrupts
int ret = Cy_SysInt_InitIRQ(&irq_cfg_jpeg);
if (ret != 0) {
qul_printf("Cy_SysInt_InitIRQ() failed\n");
return;
}
// Set interrupt handler
Cy_SysInt_SetSystemIrqVector(irq_cfg_jpeg.sysIntSrc, Jpeg_InterruptHandler);
// Set Priority/Enable IRQ
NVIC_SetPriority(CPUIntIdx3_IRQn, 3);
NVIC_ClearPendingIRQ(CPUIntIdx3_IRQn);
NVIC_EnableIRQ(CPUIntIdx3_IRQn);
// Change state to Configuration */
Jpeg_DecUpdateState(DEC_STATE_CONFIG);
return;
}
CYJPG_STATIC CYJPG_U32 Jpeg_DecOpeStartDec(void);
CYJPG_STATIC CYJPG_U32 Jpeg_DecOpeSizeAvailIntr(void);
CYJPG_STATIC CYJPG_U32 Jpeg_DecOpeCompletion(void);
CYJPG_STATIC CYJPG_U32 Jpeg_DecOpeRecovery(void);
/** \brief Decode JPEG images periodically
** \param No param
** \return Result of initialization
** RES_DEC_SUCCESS: OK
** Others : NG
**
** No remarks
** */
CYJPG_U32 Jpeg_DecStart(uint32_t addr,
uint32_t size,
uint32_t storeAddress0,
uint32_t storeAddress1,
uint32_t storeLength0,
uint32_t storeLength1,
uint32_t stride)
{
/* Local variables */
CYJPG_U32 result_appl = RES_DEC_SUCCESS; /* Result of Sample Application */
CYJPG_ERROR ret_drv; /* Return value from Jpeg Decode Driver */
/* Initialize variables */
first_dec_comp = CYJPG_FALSE; /* First decode completion */
gen_normal_corrected = CYJPG_FALSE; /* NORMALEND/CORRECTEDEND generated Flag */
jpg_config.fetchAddress = addr;
jpg_config.fetchLength = size;
jpg_config.storeStride0 = stride;
jpg_config.storeStride1 = stride;
jpg_config.storeAddress0 = storeAddress0;
jpg_config.storeAddress1 = storeAddress1;
jpg_config.storeLength0 = storeLength0;
jpg_config.storeLength1 = storeLength1;
static bool wasInitialized = false;
if (!wasInitialized) {
// Initialize JPEG Decode Driver
int ret = CyJpg_Init(&init_config);
if (ret != 0) {
qul_printf("CyJpg_Init() failed: 0x%x\n", ret);
return RES_DEC_FAILED_DRIVER;
}
wasInitialized = true;
}
#ifdef TVII_DEBUG_JPEG_DECODER
qul_printf("jpg_config.storeStride0 %u\n", jpg_config.storeStride0);
#endif
/* Change state to Decoding */
CALL_APPL_FUNC(result_appl, Jpeg_DecUpdateState(DEC_STATE_DECODING));
/* Start decoding 1st JPEG image */
CALL_JPGDRV_FUNC(result_appl, ret_drv, CyJpg_StartDecoding(&jpg_config));
while (result_appl == RES_DEC_SUCCESS) {
switch (decode_state) {
case DEC_STATE_CONFIG: {
#ifdef TVII_DEBUG_JPEG_DECODER
qul_printf("DEC_STATE_CONFIG\n");
#endif
/* Start JPEG decoding */
CALL_APPL_FUNC(result_appl, Jpeg_DecOpeStartDec());
break;
}
case DEC_STATE_DECODING: {
#ifdef TVII_DEBUG_JPEG_DECODER
qul_printf("DEC_STATE_DECODING\n");
CYJPG_DECODEINFO_S dec_info; /* Decode Information */
CALL_JPGDRV_FUNC(result_appl, ret_drv, CyJpg_GetDecInfo(&dec_info));
qul_printf("dec_info.subsample %u\n", dec_info.subsample);
#endif
break;
}
case DEC_STATE_SUSPENDED: {
#ifdef TVII_DEBUG_JPEG_DECODER
qul_printf("DEC_STATE_SUSPENDED\n");
#endif
/* Change state to Decoding */
CALL_APPL_FUNC(result_appl, Jpeg_DecUpdateState(DEC_STATE_DECODING));
/* Resume Decoding */
CALL_JPGDRV_FUNC(result_appl, ret_drv, CyJpg_ResumeDecoding(&jpg_config));
#ifdef TVII_DEBUG_JPEG_DECODER
CYJPG_DECODEINFO_S dec_info; /* Decode Information */
CALL_JPGDRV_FUNC(result_appl, ret_drv, CyJpg_GetDecInfo(&dec_info));
qul_printf("DEC_STATE_SUSPENDED\tdec_info.subsample %u\n", dec_info.subsample);
#endif
break;
}
case DEC_STATE_SUSPENDED_SIZEAVAIL: {
#ifdef TVII_DEBUG_JPEG_DECODER
qul_printf("DEC_STATE_SUSPENDED_SIZEAVAIL\n");
#endif
/* Operation when Size Available Interrupt occurs */
CALL_APPL_FUNC(result_appl, Jpeg_DecOpeSizeAvailIntr());
break;
}
case DEC_STATE_COMPLETED: {
#ifdef TVII_DEBUG_JPEG_DECODER
qul_printf("DEC_STATE_COMPLETED\n");
#endif
/* Operation for decoding completion */
CALL_APPL_FUNC(result_appl, Jpeg_DecOpeCompletion());
return RES_DEC_SUCCESS;
break;
}
case DEC_STATE_RECOVERY: {
#ifdef TVII_DEBUG_JPEG_DECODER
qul_printf("DEC_STATE_RECOVERY\n");
#endif
/* Operation for recovery */
CALL_APPL_FUNC(result_appl, Jpeg_DecOpeRecovery());
break;
}
default: {
/* Abnormal error */
qul_printf("Jpeg Decoder: Abnormal error detected.\n");
result_appl = RES_DEC_FAILED_ABNORMAL;
break;
}
}
}
return result_appl;
}
/** \brief Wait for AXI transactions to become inactive
** \param No param
** \return result
** RES_DEC_SUCCESS: Success
** RES_DEC_FAILED_DRIVER: JPEG Driver API failed
** RES_DEC_FAILED_TIMEOUT_AXI: Timeout of AXI inactive timer
**
** No remarks
** */
CYJPG_STATIC CYJPG_U32 Jpeg_DecWaitAxiInactive(void)
{
/* Local variables */
CYJPG_U32 result_appl = RES_DEC_SUCCESS; /* Result of Sample Application */
CYJPG_ERROR ret_drv; /* Return value from Jpeg Decode Driver */
// float elapsed_time; /* Elapsed Time */
CYJPG_CORESTATUS_S core_status; /* HW core status */
/* Get HW status */
CALL_JPGDRV_FUNC(result_appl, ret_drv, CyJpg_GetHwStatus(&core_status));
/* Check fetch/store AXI burst are finished */
if ((core_status.fetchAxiActive != CYJPG_FALSE) || (core_status.storeAxiActive != CYJPG_FALSE)) {
do {
/* Get HW status */
CALL_JPGDRV_FUNC(result_appl, ret_drv, CyJpg_GetHwStatus(&core_status));
if (result_appl == RES_DEC_SUCCESS) {
/* Check fetch/store AXI burst are inactive */
if ((core_status.fetchAxiActive == CYJPG_FALSE) && (core_status.storeAxiActive == CYJPG_FALSE)) {
/* Finish fetch/store AXI burst */
break;
}
}
} while (result_appl == RES_DEC_SUCCESS);
}
return result_appl;
}
/** \brief Operation for Starting JPEG decode
** \param No param
** \return result
** RES_DEC_SUCCESS: Success
** RES_DEC_FAILED_DRIVER: JPEG Driver API failed
** RES_DEC_FAILED_ILLEGAL_STATE: Illegal state error
**
** No remarks
** */
CYJPG_STATIC CYJPG_U32 Jpeg_DecOpeStartDec(void)
{
/* Local variables */
CYJPG_U32 result_appl = RES_DEC_SUCCESS; /* Result of Sample Application */
CYJPG_ERROR ret_drv; /* Return value from Jpeg Decode Driver */
CYJPG_BOOL mod_config = CYJPG_FALSE; /* Flag of modifying configuration */
/* Change state to Decoding */
CALL_APPL_FUNC(result_appl, Jpeg_DecUpdateState(DEC_STATE_DECODING));
if (mod_config == CYJPG_FALSE) {
/* Continue decoding JPEG image */
CALL_JPGDRV_FUNC(result_appl, ret_drv, CyJpg_ContinueDecoding(&jpg_config));
} else {
/* Start decoding with configuration changes */
CALL_JPGDRV_FUNC(result_appl, ret_drv, CyJpg_StartDecoding(&jpg_config));
}
return result_appl;
}
/** \brief Operation when Size Available Interrupt occurs
** \param No param
** \return result
** RES_DEC_SUCCESS: Success
** RES_DEC_FAILED_DRIVER: JPEG Driver API failed
** RES_DEC_FAILED_ILLEGAL_STATE: Illegal state error
**
** No remarks
** */
CYJPG_STATIC CYJPG_U32 Jpeg_DecOpeSizeAvailIntr(void)
{
/* Local variables */
CYJPG_U32 result_appl = RES_DEC_SUCCESS; /* Result of Sample Application */
CYJPG_ERROR ret_drv; /* Return value from Jpeg Decode Driver */
CYJPG_HWERRINFO_S hw_err_info; /* HW Error Information */
CYJPG_BOOL crop_error = CYJPG_FALSE; /* Crop Error Flag */
if (jpg_config.cropEn == CYJPG_ENABLE) {
/* Get HW error information to check crop errors */
CALL_JPGDRV_FUNC(result_appl, ret_drv, CyJpg_GetHwErrorInfo(&hw_err_info));
if ((hw_err_info.correctionCropStatus[hw_err_info.correctionCropNum] & 0x00000030U) != 0U) {
/* Crop Size Error (Bit#4) or MCU Unit Error (Bit#5) occurs */
crop_error = CYJPG_TRUE;
}
}
if (crop_error == CYJPG_FALSE) {
/* Change state to Decoding */
CALL_APPL_FUNC(result_appl, Jpeg_DecUpdateState(DEC_STATE_DECODING));
/* Resume Decoding */
CALL_JPGDRV_FUNC(result_appl, ret_drv, CyJpg_ResumeDecoding(&jpg_config));
} else {
/* Change state to Recovery */
CALL_APPL_FUNC(result_appl, Jpeg_DecUpdateState(DEC_STATE_RECOVERY));
/* Notify recovery cause as undefined status */
Jpeg_DecNotifyRcvCause(DEC_RCV_CAUSE_UNDEFINED_STATE);
}
return result_appl;
}
/** \brief Operation for JPEG decode completion
** \param No param
** \return result
** RES_DEC_SUCCESS: Success
** RES_DEC_FAILED_ILLEGAL_STATE: Illegal state error
**
** No remarks
** */
CYJPG_STATIC CYJPG_U32 Jpeg_DecOpeCompletion(void)
{
/* Local variables */
CYJPG_U32 result_appl = RES_DEC_SUCCESS; /* Result of Sample Application */
/* Check Decode error: Not generated NORMALEND/CORRECTEDEND */
if (gen_normal_corrected == CYJPG_TRUE) {
/* Check if the decoded data is 1st JPEG image */
if (first_dec_comp == CYJPG_FALSE) {
first_dec_comp = CYJPG_TRUE;
}
/* Change state to Configuration */
CALL_APPL_FUNC(result_appl, Jpeg_DecUpdateState(DEC_STATE_CONFIG));
} else {
/* Change state to Recovery */
CALL_APPL_FUNC(result_appl, Jpeg_DecUpdateState(DEC_STATE_RECOVERY));
/* Set recovery cause to "NORMALEND/CORRECTEDEND not generated" */
Jpeg_DecNotifyRcvCause(DEC_RCV_CAUSE_NO_NORMAL_CORRECTED);
}
/* Initialize NORMALEND/CORRECTEDEND generated flag */
Jpeg_DecNotifyNormalCorrected(CYJPG_FALSE);
return result_appl;
}
/** \brief Operation for hardware status recovery
** \param No param
** \return result
** RES_DEC_SUCCESS: Success
** RES_DEC_FAILED_DRIVER: JPEG Driver API failed
** RES_DEC_FAILED_TIMEOUT_AXI: Timeout of AXI inactive timer
** RES_DEC_FAILED_ABNORMAL: Abnormal error
**
** No remarks
** */
CYJPG_STATIC CYJPG_U32 Jpeg_DecOpeRecovery(void)
{
/* Local variables */
CYJPG_U32 result_appl = RES_DEC_SUCCESS; /* Result of Sample Application */
CYJPG_ERROR ret_drv; /* Return value from Jpeg Decode Driver */
switch (recovery_cause) {
case DEC_RCV_CAUSE_FETCH_STORE_ERR: {
/* Wait for AXI transactions to become inactive */
CALL_APPL_FUNC(result_appl, Jpeg_DecWaitAxiInactive());
/* Perform SW reset */
CALL_JPGDRV_FUNC(result_appl, ret_drv, CyJpg_SwReset());
break;
}
case DEC_RCV_CAUSE_INTR_DEC_ERR: {
/* Wait for AXI transactions to become inactive */
CALL_APPL_FUNC(result_appl, Jpeg_DecWaitAxiInactive());
break;
}
case DEC_RCV_CAUSE_CANCEL:
case DEC_RCV_CAUSE_NO_NORMAL_CORRECTED: {
/* Perform SW reset */
CALL_JPGDRV_FUNC(result_appl, ret_drv, CyJpg_SwReset());
/* Wait for AXI transactions to become inactive */
CALL_APPL_FUNC(result_appl, Jpeg_DecWaitAxiInactive());
break;
}
case DEC_RCV_CAUSE_UNDEFINED_STATE: {
/* Perform SW reset */
CALL_JPGDRV_FUNC(result_appl, ret_drv, CyJpg_SwReset());
/* Wait for AXI transactions to become inactive */
CALL_APPL_FUNC(result_appl, Jpeg_DecWaitAxiInactive());
/* Deinitialize JPEG decode driver */
CALL_JPGDRV_FUNC(result_appl, ret_drv, CyJpg_DeInit());
if (result_appl == RES_DEC_SUCCESS) {
/* Marker Skip Function must be disabled */
jpg_config.markerskipEn = CYJPG_DISABLE;
/* Initialize JPEG decode driver */
CALL_JPGDRV_FUNC(result_appl, ret_drv, CyJpg_Init(&init_config));
}
break;
}
default: {
/* Abnormal error */
result_appl = RES_DEC_FAILED_ABNORMAL;
break;
}
}
if (result_appl == RES_DEC_SUCCESS) {
/* Change state to Configuration */
CALL_APPL_FUNC(result_appl, Jpeg_DecUpdateState(DEC_STATE_CONFIG));
/* Initialize Recovery Cause */
Jpeg_DecNotifyRcvCause(DEC_RCV_CAUSE_NOTHING);
/* Initialize first decode completion */
first_dec_comp = CYJPG_FALSE;
}
return result_appl;
}