/**************************************************************************//** * @file main.c * @brief Demonstrate BLT functions * * SPDX-License-Identifier: Apache-2.0 * @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. *****************************************************************************/ //#include <stdio.h> #include <string.h> #include <stdint.h> #include <math.h> #include "N9H20.h" /* Color format * * RGB565 : 2-byte, no alpha * RGB888(xRGB8888) : 4-byte with MSB byte ignored, no alpha * ARGB8888 : 4-byte with MSB byte representing alpha */ static uint8_t src_pat[] = { //#include "Pat_RGB888_size160x120.txt" #include "Pat_ARGB888_size160x120.txt" }; /* Source image spec. Must be consistent with source image data */ #define SRCIMG_HASALPHA 1 #define SRCIMG_WIDTH 160 #define SRCIMG_STRIDE (SRCIMG_WIDTH * 4) #define SRCIMG_HEIGHT 120 #define DISP_WIDTH 320 #define DISP_STRIDE (DISP_WIDTH * 2) #define DISP_HEIGHT 240 #define SIZE_SRCIMG (SRCIMG_STRIDE * SRCIMG_HEIGHT) #define SIZE_SRCIMG_BUF ((SIZE_SRCIMG + 31) / 32 * 32) #define SIZE_DISP (DISP_STRIDE * DISP_HEIGHT) #define SIZE_DISP_BUF ((SIZE_DISP + 31) / 32 * 32) #define SIZE_TXMEM (SIZE_SRCIMG_BUF + SIZE_DISP_BUF) #if defined (__GNUC__) uint8_t txmem[SIZE_TXMEM] __attribute__((aligned (32))); #else __align (32) uint8_t txmem[SIZE_TXMEM]; #endif /* To avoid error-prone cache synchronization, the txmem for CPU and BLT operation is always * non-cacheable. */ #define ADDR_SRCIMG (sysGetCacheState() ? (((uint32_t) txmem) | 0x80000000) : (((uint32_t) txmem))) #define ADDR_DISP (ADDR_SRCIMG + SIZE_SRCIMG_BUF) #define FMT_DST eDRVBLT_DEST_RGB565 #define COLOR_WHITE 0xFFFFFFFF #define COLOR_BLACK 0xFF000000 #define COLOR_GRAY 0xFF808080 #define COLOR_RED 0xFFFF0000 #define COLOR_GREEN 0xFF00FF00 #define COLOR_BLUE 0xFF0000FF #define DELAY_INTER_FRAME 50 void clr_disp_buf(uint32_t fill_color) { S_FI_FILLOP clr_op; // Fill color is non-premultiplied alpha. clr_op.sRect.i16Xmin = 0; clr_op.sRect.i16Ymin = 0; clr_op.sRect.i16Xmax = DISP_WIDTH; clr_op.sRect.i16Ymax = DISP_HEIGHT; clr_op.sARGB8.u8Blue = (fill_color & 0x000000FF); clr_op.sARGB8.u8Green = (fill_color & 0x0000FF00) >> 8; clr_op.sARGB8.u8Red = (fill_color & 0x00FF0000) >> 16; clr_op.sARGB8.u8Alpha = (fill_color & 0xFF000000) >> 24; clr_op.u32FBAddr = ADDR_DISP; clr_op.i32Stride = DISP_STRIDE; clr_op.eDisplayFmt = FMT_DST; clr_op.i32Blend = 0; // No alpha blending. bltFIFill(clr_op); } /** * @brief Scale source pattern with top-left point as center. * @param[in] ox,oy coordinates of center in FB CS. * @param[in] sx scale factor along x-axis * @param[in] sy scale factor along y-axis * * Ma * Mt * Mm * Src = Dst, where * Ma: matrix for amendment to mapping point error * Ms: scale matrix * Mm: reflect matrix * * / 1 0 -0.5 \ / 1 0 tx \ / sx 0 0 \ * Ma = | 0 0 -0.5 | Mt = | 0 1 ty | Ms = | 0 sy 0 | * \ 0 0 1 / \ 0 0 1 / \ 0 0 1 / * * Src = Inv(Ms) * Inv(Mt) * Inv(Ma) * DST * * / 1/sx 0 0 \ / 1 0 -tx \ / 1 0 0.5 \ * Inv(Ms) = | 0 1/sy 0 | Inv(Mt) = | 0 1 -ty | Inv(Ma) = | 0 1 0.5 | * \ 0 0 1 / \ 0 0 1 / \ 0 0 1 / * * / 1/sx 0 -(1/sx)*tx+0.5*(a+c) \ / a c src.xoffset \ * Inv(Ms) * Inv(Mt) * Inv(Ma) = | 0 1/sy -(1/sy)*ty+0.5*(b+d) | = | b d src.yoffset | * \ 0 0 1 / \ 0 0 0 / */ void demo_scale(float ox, float oy, float sx, float sy, int is_tiling) { bltSetFillOP((E_DRVBLT_FILLOP) FALSE); // Blit operation. bltSetDisplayFormat(FMT_DST); // Set destination format. bltSetSrcFormat(eDRVBLT_SRC_ARGB8888); // Set source image format to RGB888/ARGB8888. bltSetRevealAlpha(eDRVBLT_NO_EFFECTIVE); // Source image format is non-premultiplied alpha. { // Set transform matrix a/b/c/d S_DRVBLT_MATRIX xform_mx; xform_mx.a = (INT32) ((1 / sx) * 0x10000); xform_mx.b = 0; xform_mx.c = 0; xform_mx.d = (INT32) ((1 / sy) * 0x10000); bltSetTransformMatrix(xform_mx); } { // Set color multiplier for color transform. S_DRVBLT_ARGB16 color_multiplier; color_multiplier.i16Blue = 0x100; color_multiplier.i16Green = 0x100; color_multiplier.i16Red = 0x100; color_multiplier.i16Alpha = 0x100; bltSetColorMultiplier(color_multiplier); } { // Set color offset for color transform S_DRVBLT_ARGB16 color_offset; color_offset.i16Blue = 0; color_offset.i16Green = 0; color_offset.i16Red = 0; color_offset.i16Alpha = 0; bltSetColorOffset(color_offset); } // Apply color transformation on all 4 channels. if (SRCIMG_HASALPHA) { bltSetTransformFlag(eDRVBLT_HASTRANSPARENCY | eDRVBLT_HASCOLORTRANSFORM); } else { bltSetTransformFlag(eDRVBLT_HASCOLORTRANSFORM); } bltSetFillStyle((E_DRVBLT_FILL_STYLE) (eDRVBLT_NOTSMOOTH | (is_tiling ? 0 : eDRVBLT_NONE_FILL))); // No smoothing. { // Set source image. S_DRVBLT_SRC_IMAGE src_img; src_img.u32SrcImageAddr = ADDR_SRCIMG; { S_DRVBLT_MATRIX xform_mx; src_img.i32XOffset = (INT32) (0 - ((1 / sx) * ox * 0x10000)); // 16.16 src_img.i32YOffset = (INT32) (0 - ((1 / sy) * oy * 0x10000)); // 16.16 // Apply amendment to mapping point error. bltGetTransformMatrix(&xform_mx); src_img.i32XOffset += (xform_mx.a + xform_mx.c) / 2; src_img.i32YOffset += (xform_mx.b + xform_mx.d) / 2; } src_img.i16Width = SRCIMG_WIDTH; src_img.i32Stride = SRCIMG_STRIDE; src_img.i16Height = SRCIMG_HEIGHT; bltSetSrcImage(src_img); } { // Set destination buffer. S_DRVBLT_DEST_FB dst_img; dst_img.u32FrameBufAddr = ADDR_DISP; dst_img.i16Width = DISP_WIDTH; dst_img.i32Stride = DISP_STRIDE; dst_img.i16Height = DISP_HEIGHT; bltSetDestFrameBuf(dst_img); } /* We assume txmem for CPU and BLT is non-cacheable, so we needn't do any cache-related * synchronization. */ bltTrigger(); // Trigger Blit operation. bltFlush(); // Wait for complete. } #define PI_OVER_180 0.01745329252f /** * @brief Rotate source pattern around pivot * @param[in] ox,oy coordinates of center in FB CS * @param[in] px,py coordinates of pivot relative to top-left point of source pattern * @param[in] deg Angle in degree * * Ma * Mt * Mr * Mp * Src = Dst, where * Ma: matrix for amendment to mapping point error * Mt: translation matrix * Mr: rotation matrix * Mp: translation matrix to adjust pivot * * / 1 0 -0.5 \ / 1 0 tx \ / cos�c -sin�c 0 \ / 1 0 -px \ * Ma = | 0 0 -0.5 | Mt = | 0 1 ty | Mr = | sin�c con�c 0 | Mp = | 0 1 -py | * \ 0 0 1 / \ 0 0 1 / \ 0 0 1 / \ 0 0 1 / * * Src = Inv(Mp) * Inv(Mr) * Inv(Mt) * Inv(Ma) * DST * * / 1 0 px \ / cos�c sin�c 0 \ / 1 0 -tx \ / 1 0 0.5 \ * Inv(Mp) = | 0 1 py | Inv(Mr) = | -sin�c con�c 0 | Inv(Mt) = | 0 1 -ty | Inv(Ma) = | 0 1 0.5 | * \ 0 0 1 / \ 0 0 1 / \ 0 0 1 / \ 0 0 1 / * * / con�c sin�c px - con�c*tx-sin�c*ty+0.5*(a+c) \ / a c src.xoffset \ * Inv(Mp) * Inv(Mr) * Inv(Mt) * Inv(Ma) = | -sin�c con�c py + sin�c*tx-con�c*ty+0.5*(b+d) | = | b d src.yoffset | * \ 0 0 1 / \ 0 0 1 / */ void demo_rotate(float ox, float oy, float px, float py, float deg) { bltSetFillOP((E_DRVBLT_FILLOP) FALSE); // Blit operation. bltSetDisplayFormat(FMT_DST); // Set destination format. bltSetSrcFormat(eDRVBLT_SRC_ARGB8888); // Set source image format to RGB888/ARGB8888. bltSetRevealAlpha(eDRVBLT_NO_EFFECTIVE); // Source image format is non-premultiplied alpha. { // Set transform matrix a/b/c/d S_DRVBLT_MATRIX xform_mx; xform_mx.a = cos(PI_OVER_180 * deg) * 0x10000; xform_mx.b = -sin(PI_OVER_180 * deg) * 0x10000; xform_mx.c = sin(PI_OVER_180 * deg) * 0x10000; xform_mx.d = cos(PI_OVER_180 * deg) * 0x10000; bltSetTransformMatrix(xform_mx); } { // Set color multiplier for color transform. S_DRVBLT_ARGB16 color_multiplier; color_multiplier.i16Blue = 0x100; color_multiplier.i16Green = 0x100; color_multiplier.i16Red = 0x100; color_multiplier.i16Alpha = 0x100; bltSetColorMultiplier(color_multiplier); } { // Set color offset for color transform S_DRVBLT_ARGB16 color_offset; color_offset.i16Blue = 0; color_offset.i16Green = 0; color_offset.i16Red = 0; color_offset.i16Alpha = 0; bltSetColorOffset(color_offset); } // Apply color transformation on all 4 channels. if (SRCIMG_HASALPHA) { bltSetTransformFlag(eDRVBLT_HASTRANSPARENCY | eDRVBLT_HASCOLORTRANSFORM); } else { bltSetTransformFlag(eDRVBLT_HASCOLORTRANSFORM); } bltSetFillStyle((E_DRVBLT_FILL_STYLE) (eDRVBLT_NONE_FILL | eDRVBLT_NOTSMOOTH)); // No smoothing. { // Set source image. S_DRVBLT_SRC_IMAGE src_img; src_img.u32SrcImageAddr = ADDR_SRCIMG; { S_DRVBLT_MATRIX xform_mx; // Pivot src_img.i32XOffset = px * 0x10000; // 16.16 src_img.i32YOffset = py * 0x10000; // 16.16 // Translate after rotate src_img.i32XOffset += -(cos(PI_OVER_180 * deg) * ox + sin(PI_OVER_180 * deg) * oy) * 0x10000; // 16.16 src_img.i32YOffset += (sin(PI_OVER_180 * deg) * ox - cos(PI_OVER_180 * deg) * oy) * 0x10000; // 16.16 // Apply amendment to mapping point error. bltGetTransformMatrix(&xform_mx); src_img.i32XOffset += (xform_mx.a + xform_mx.c) / 2; src_img.i32YOffset += (xform_mx.b + xform_mx.d) / 2; } src_img.i16Width = SRCIMG_WIDTH; src_img.i32Stride = SRCIMG_STRIDE; src_img.i16Height = SRCIMG_HEIGHT; bltSetSrcImage(src_img); } { // Set destination buffer. S_DRVBLT_DEST_FB dst_img; dst_img.u32FrameBufAddr = ADDR_DISP; dst_img.i16Width = DISP_WIDTH; dst_img.i32Stride = DISP_STRIDE; dst_img.i16Height = DISP_HEIGHT; bltSetDestFrameBuf(dst_img); } /* We assume txmem for CPU and BLT is non-cacheable, so we needn't do any cache-related * synchronization. */ bltTrigger(); // Trigger Blit operation. bltFlush(); // Wait for complete. } /** * @brief Reflect source pattern about x-axis/y-axis/origin with top-left point as center. * @param[in] ox,oy coordinates of center in FB CS. * @param[in] mx reflect about x-axis * @param[in] my reflect about y-axis * * Ma * Mt * Mm * Src = Dst, where * Ma: matrix for amendment to mapping point error * Mt: translation matrix * Mm: reflect matrix * * / 1 0 -0.5 \ / 1 0 tx \ / my?-1:1 0 0 \ * Ma = | 0 0 -0.5 | Mt = | 0 1 ty | Mm = | 0 mx?-1:1 0 | * \ 0 0 1 / \ 0 0 1 / \ 0 0 1 / * * Src = Inv(Mm) * Inv(Mt) * Inv(Ma) * DST * * / my?-1:1 0 0 \ / 1 0 -tx \ / 1 0 0.5 \ * Inv(Mm) = | 0 mx?-1:1 0 | Inv(Mt) = | 0 1 -ty | Inv(Ma) = | 0 1 0.5 | * \ 0 0 1 / \ 0 0 1 / \ 0 0 1 / * * / my?-1:1 0 -(my?-1:1)*tx+0.5*(a+c) \ / a c src.xoffset \ * Inv(Mm) * Inv(Mt) * Inv(Ma) = | 0 mx?-1:1 -(mx?-1:1)*ty+0.5*(b+d) | = | b d src.yoffset | * \ 0 0 1 / \ 0 0 0 / */ void demo_reflect(float ox, float oy, int mx, int my) { bltSetFillOP((E_DRVBLT_FILLOP) FALSE); // Blit operation. bltSetDisplayFormat(FMT_DST); // Set destination format. bltSetSrcFormat(eDRVBLT_SRC_ARGB8888); // Set source image format to RGB888/ARGB8888. bltSetRevealAlpha(eDRVBLT_NO_EFFECTIVE); // Source image format is non-premultiplied alpha. { // Set transform matrix a/b/c/d S_DRVBLT_MATRIX xform_mx; xform_mx.a = (my ? -1 : 1) * 0x10000; xform_mx.b = 0; xform_mx.c = 0; xform_mx.d = (mx ? -1 : 1) * 0x10000; bltSetTransformMatrix(xform_mx); } { // Set color multiplier for color transform. S_DRVBLT_ARGB16 color_multiplier; color_multiplier.i16Blue = 0x100; color_multiplier.i16Green = 0x100; color_multiplier.i16Red = 0x100; color_multiplier.i16Alpha = 0x100; bltSetColorMultiplier(color_multiplier); } { // Set color offset for color transform S_DRVBLT_ARGB16 color_offset; color_offset.i16Blue = 0; color_offset.i16Green = 0; color_offset.i16Red = 0; color_offset.i16Alpha = 0; bltSetColorOffset(color_offset); } // Apply color transformation on all 4 channels. if (SRCIMG_HASALPHA) { bltSetTransformFlag(eDRVBLT_HASTRANSPARENCY | eDRVBLT_HASCOLORTRANSFORM); } else { bltSetTransformFlag(eDRVBLT_HASCOLORTRANSFORM); } bltSetFillStyle((E_DRVBLT_FILL_STYLE) (eDRVBLT_NONE_FILL | eDRVBLT_NOTSMOOTH)); // No smoothing. { // Set source image. S_DRVBLT_SRC_IMAGE src_img; src_img.u32SrcImageAddr = ADDR_SRCIMG; { S_DRVBLT_MATRIX xform_mx; src_img.i32XOffset = -((my ? -1 : 1) * ox) * 0x10000; // 16.16 src_img.i32YOffset = -((mx ? -1 : 1) * oy) * 0x10000; // 16.16 // Apply amendment to mapping point error. bltGetTransformMatrix(&xform_mx); src_img.i32XOffset += (xform_mx.a + xform_mx.c) / 2; src_img.i32YOffset += (xform_mx.b + xform_mx.d) / 2; } src_img.i16Width = SRCIMG_WIDTH; src_img.i32Stride = SRCIMG_STRIDE; src_img.i16Height = SRCIMG_HEIGHT; bltSetSrcImage(src_img); } { // Set destination buffer. S_DRVBLT_DEST_FB dst_img; dst_img.u32FrameBufAddr = ADDR_DISP; dst_img.i16Width = DISP_WIDTH; dst_img.i32Stride = DISP_STRIDE; dst_img.i16Height = DISP_HEIGHT; bltSetDestFrameBuf(dst_img); } /* We assume txmem for CPU and BLT is non-cacheable, so we needn't do any cache-related * synchronization. */ bltTrigger(); // Trigger Blit operation. bltFlush(); // Wait for complete. } void demo_alpha(float ox, float oy, float alpha) { bltSetFillOP((E_DRVBLT_FILLOP) FALSE); // Blit operation. bltSetDisplayFormat(FMT_DST); // Set destination format. bltSetSrcFormat(eDRVBLT_SRC_ARGB8888); // Set source image format to RGB888/ARGB8888. bltSetRevealAlpha(eDRVBLT_NO_EFFECTIVE); // Source image format is non-premultiplied alpha. { // Set transform matrix to identify matrix. So no scaling, no rotation, no shearing, etc. S_DRVBLT_MATRIX xform_mx; xform_mx.a = 0x10000; xform_mx.b = 0; xform_mx.c = 0; xform_mx.d = 0x10000; bltSetTransformMatrix(xform_mx); } { // Set color multiplier for color transform. S_DRVBLT_ARGB16 color_multiplier; color_multiplier.i16Blue = 0x100; color_multiplier.i16Green = 0x100; color_multiplier.i16Red = 0x100; color_multiplier.i16Alpha = (int16_t) (alpha * 256); bltSetColorMultiplier(color_multiplier); } { // Set color offset for color transform S_DRVBLT_ARGB16 color_offset; color_offset.i16Blue = 0; color_offset.i16Green = 0; color_offset.i16Red = 0; color_offset.i16Alpha = 0; bltSetColorOffset(color_offset); } // Apply color transformation on all 4 channels. if (SRCIMG_HASALPHA) { bltSetTransformFlag(eDRVBLT_HASTRANSPARENCY | eDRVBLT_HASCOLORTRANSFORM); } else { bltSetTransformFlag(eDRVBLT_HASCOLORTRANSFORM); } bltSetFillStyle((E_DRVBLT_FILL_STYLE) (eDRVBLT_NONE_FILL | eDRVBLT_NOTSMOOTH)); // No smoothing. { // Set source image. S_DRVBLT_SRC_IMAGE src_img; src_img.u32SrcImageAddr = ADDR_SRCIMG; src_img.i32XOffset = -ox * 0x10000; // 16.16 src_img.i32YOffset = -oy * 0x10000; // 16.16 src_img.i16Width = SRCIMG_WIDTH; src_img.i32Stride = SRCIMG_STRIDE; src_img.i16Height = SRCIMG_HEIGHT; bltSetSrcImage(src_img); } { // Set destination buffer. S_DRVBLT_DEST_FB dst_img; dst_img.u32FrameBufAddr = ADDR_DISP; dst_img.i16Width = DISP_WIDTH; dst_img.i32Stride = DISP_STRIDE; dst_img.i16Height = DISP_HEIGHT; bltSetDestFrameBuf(dst_img); } /* We assume txmem for CPU and BLT is non-cacheable, so we needn't do any cache-related * synchronization. */ bltTrigger(); // Trigger Blit operation. bltFlush(); // Wait for complete. } int main() { { // Initialize UART. UINT32 u32ExtFreq; WB_UART_T uart; u32ExtFreq = sysGetExternalClock(); sysUartPort(1); uart.uiFreq = u32ExtFreq * 1000; uart.uiBaudrate = 115200; uart.uiDataBits = WB_DATA_BITS_8; uart.uiStopBits = WB_STOP_BITS_1; uart.uiParity = WB_PARITY_NONE; uart.uiRxTriggerLevel = LEVEL_1_BYTE; sysInitializeUART(&uart); } { // Initialize timer. UINT32 u32ExtFreq = sysGetExternalClock() * 1000; sysSetTimerReferenceClock (TIMER0, u32ExtFreq); } { // Initialize VPOST. LCDFORMATEX lcdFormat; lcdFormat.ucVASrcFormat = DRVVPOST_FRAME_RGB565; // Initialize VPOST. lcdFormat.nScreenWidth = DISP_WIDTH; lcdFormat.nScreenHeight = DISP_HEIGHT; vpostLCMInit(&lcdFormat, (UINT32 *) ADDR_DISP); /* If backlight control signal is different from nuvoton's demo board, * please don't call this function and must implement another similar one * to enable LCD backlight. */ vpostEnaBacklight(); } // Cache on. if (! sysGetCacheState()) { sysInvalidCache(); sysEnableCache(CACHE_WRITE_THROUGH); sysFlushCache(I_D_CACHE); } sysSetLocalInterrupt (ENABLE_IRQ); // Enable CPSR I bit do { memcpy((void *) ADDR_SRCIMG, src_pat, SIZE_SRCIMG); bltOpen(); // Scale. No tiling. clr_disp_buf(COLOR_GRAY); demo_scale(0.0f, 0.0f, 0.5f, 0.5f, 0); sysDelay(DELAY_INTER_FRAME); clr_disp_buf(COLOR_GRAY); demo_scale(0.0f, 0.0f, 1.0f, 1.0f, 0); sysDelay(DELAY_INTER_FRAME); clr_disp_buf(COLOR_GRAY); demo_scale(0.0f, 0.0f, 1.5f, 1.5f, 0); sysDelay(DELAY_INTER_FRAME); clr_disp_buf(COLOR_GRAY); demo_scale(0.0f, 0.0f, 2.0f, 2.0f, 0); sysDelay(DELAY_INTER_FRAME); // Scale without aspect ratio kept. No tiling. clr_disp_buf(COLOR_GRAY); demo_scale(0.0f, 0.0f, 2.0f, 0.5f, 0); sysDelay(DELAY_INTER_FRAME); clr_disp_buf(COLOR_GRAY); demo_scale(0.0f, 0.0f, 0.5f, 2.0f, 0); sysDelay(DELAY_INTER_FRAME); // Scale. Tiling. clr_disp_buf(COLOR_GRAY); demo_scale(0.0f, 0.0f, 0.5f, 0.5f, 1); sysDelay(DELAY_INTER_FRAME); clr_disp_buf(COLOR_GRAY); demo_scale(0.0f, 0.0f, 1.0f, 1.0f, 1); sysDelay(DELAY_INTER_FRAME); // Rotate with pivot unchanged { float deg_arr[] = {0.0f, 30.0f, 60.0f, 90.0f, 120.0f, 150.0f, 180.0f, 210.0f, 240.0f, 270.0f, 300.0f, 330.0f, 360.0f}; float *deg_ind = deg_arr; float *deg_end = deg_arr + sizeof (deg_arr) / sizeof (deg_arr[0]); while (deg_ind != deg_end) { clr_disp_buf(COLOR_GRAY); demo_rotate(160.0f, 120.0f, 0.0f, 0.0f, *deg_ind); sysDelay(DELAY_INTER_FRAME); deg_ind ++; } } // Rotate with pivot changed { float deg_arr[] = {0.0f, 30.0f, 60.0f, 90.0f, 120.0f, 150.0f, 180.0f, 210.0f, 240.0f, 270.0f, 300.0f, 330.0f, 360.0f}; float *deg_ind = deg_arr; float *deg_end = deg_arr + sizeof (deg_arr) / sizeof (deg_arr[0]); while (deg_ind != deg_end) { clr_disp_buf(COLOR_GRAY); demo_rotate(160.0f, 120.0f, 40.0f, 30.0f, *deg_ind); sysDelay(DELAY_INTER_FRAME); deg_ind ++; } } // Reflect // Reflect about x-axis clr_disp_buf(COLOR_GRAY); demo_reflect(0.0f, 120.0f, 1, 0); sysDelay(DELAY_INTER_FRAME); // Reflect about y-axis clr_disp_buf(COLOR_GRAY); demo_reflect(160.0f, 0.0f, 0, 1); sysDelay(DELAY_INTER_FRAME); // Reflect about both x-axis/y-axis (origin) clr_disp_buf(COLOR_GRAY); demo_reflect(160.0f, 120.0f, 1, 1); sysDelay(DELAY_INTER_FRAME); // Fade-in/Fase-out. { float alpha_arr[] = { 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f, 0.9f, 0.8f, 0.7f, 0.6f, 0.5f, 0.4f, 0.3f, 0.2f, 0.1f, 0.0f }; float *alpha_ind = alpha_arr; float *alpha_end = alpha_arr + sizeof (alpha_arr) / sizeof (alpha_arr[0]); while (alpha_ind != alpha_end) { clr_disp_buf(COLOR_GRAY); demo_alpha(80.0f, 60.0f, *alpha_ind); sysDelay(DELAY_INTER_FRAME); alpha_ind ++; } } } while (0); bltClose(); return 0; }