1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - DSP - demos - scaling-1
3   File:     main.c
4 
5   Copyright 2007-2008 Nintendo. All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law. They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Date:: 2009-09-24#$
14   $Rev: 11063 $
15   $Author: okubata_ryoma $
16 *---------------------------------------------------------------------------*/
17 
18 /*---------------------------------------------------------------------------
19  The demo enlarges (or shrinks) 640x480 image data to fit a specified scale ratio and/or area.
20 
21  Three interpolation methods are available to choose from when scaling.
22 
23  - How to Use
24      -- A : Change the interpolation mode
25            Cycles in order through Nearest Neighbor, Bilinear, Bicubic, Nearest Neighbor, ....
26 
27      -- UP, DOWN, RIGHT, LEFT : Moves the area.
28            Moves the area where the scaling will be performed.
29            Movement cannot exceed the boundaries of the 640x480 image.
30 
31      -- START : Ends the demo.
32 
33  - Other Notes
34      -- To change the scaling ratio, change the SCALING_FACTOR_X and SCALING_FACTOR_Y constants below and rebuild the demo.
35 
36 
37      -- To change the DSP processing area size, change AREA_WIDTH and AREA_HEIGHT and rebuild the demo.
38 
39 
40  ----------------------------------------------------------------------------*/
41 
42 #include <twl.h>
43 #include <twl/dsp.h>
44 
45 #include <DEMO.h>
46 #include <twl/dsp/common/graphics.h>
47 
48 /* Settings */
49 #define RUN_ASYNC     0            // Whether to scale asynchronously
50 #define DMA_NO_FOR_FS 1            // For FS_Init
51 
52 #define AREA_WIDTH   185            // Width of the area to scale
53 #define AREA_HEIGHT  140            // Height of the area to scale
54 
55 #define SCALING_FACTOR_X 1.4f      // Scale ratio for the X direction (valid to the third decimal place, with an upper limit of 31)
56 #define SCALING_FACTOR_Y 1.4f      // Scale ratio for the Y direction (valid to the third decimal place, with an upper limit of 31)
57 
58 #define OUTPUT_WIDTH  DSP_CALC_SCALING_SIZE(AREA_WIDTH, SCALING_FACTOR_X)  // Consider post-processing resolution and rounding errors caused by the f32 type
59 #define OUTPUT_HEIGHT DSP_CALC_SCALING_SIZE(AREA_HEIGHT, SCALING_FACTOR_Y)
60 
61 /*---------------------------------------------------------------------------*
62  Image data (640x480)
63  *---------------------------------------------------------------------------*/
64 extern const u8 _binary_output_dat[];
65 extern const u8 _binary_output_dat_end[];
66 
67 #define DATA_WIDTH    640
68 #define DATA_HEIGHT   480
69 
70 /*---------------------------------------------------------------------------*
71  Prototype Declarations
72 *---------------------------------------------------------------------------*/
73 void VBlankIntr(void);
74 
75 static void ExecScaling(void);
76 static void InitializeGraphics(void);
77 static void WriteScreenBuffer(u16 *data, u32 width, u32 height, u16 *scr);
78 static void ScalingCallbackFunc(void);
79 
80 /*---------------------------------------------------------------------------*
81  Internal Variable Definitions
82 *---------------------------------------------------------------------------*/
83 // Screen buffers for main and sub-screens
84 static u16 ScrBuf[HW_LCD_WIDTH * HW_LCD_HEIGHT] ATTRIBUTE_ALIGN(32);
85 // Buffer storing results after transformation by the DSP
86 static u16 TmpBuf[OUTPUT_WIDTH * OUTPUT_HEIGHT] ATTRIBUTE_ALIGN(32);
87 
88 static OSTick StartTick;       // Variable for measuring DSP processing time
89 static BOOL IsDspProcessing;   // Whether DSP is currently processing something (used when running this as an asynchronous process)
90 
91 static u16 AreaX = 0;          // Upper-left x-coordinate of area to scale
92 static u16 AreaY = 0;          // Upper-left y-coordinate of area to scale
93 
94 // Interpolation mode
95 static u16 ModeNames[3] = {
96     DSP_GRAPHICS_SCALING_MODE_N_NEIGHBOR,
97     DSP_GRAPHICS_SCALING_MODE_BILINEAR,
98     DSP_GRAPHICS_SCALING_MODE_BICUBIC
99     };
100 
101 static u8 ModeNameStrings[3][24] = {
102         "Nearest Neighbor",
103         "Bilinear",
104         "Bicubic"
105         };
106 
107 static u32 DspMode = 0;
108 
109 /*---------------------------------------------------------------------------*
110  Name:         TwlMain
111 
112  Description:  Initialization and main loop.
113 
114  Arguments:    None.
115 
116  Returns:      None.
117 *---------------------------------------------------------------------------*/
TwlMain(void)118 void TwlMain(void)
119 {
120     FSFile file;
121 
122     DEMOInitCommon();
123     OS_InitThread();
124     OS_InitTick();
125     OS_InitAlarm();             // This is required when using synchronous versions of DSP_Scaling* functions (because the OS_Sleep function is used internally)
126 
127     // When in NITRO mode, stopped by Panic
128     DEMOCheckRunOnTWL();
129 
130     DEMOInitVRAM();
131     InitializeGraphics();
132 
133     DEMOStartDisplay();
134 
135     // Because at first there is a possibility that WRAM might have been allocated to something as per the ROM header, clear it
136     (void)MI_FreeWram_B( MI_WRAM_ARM9 );
137     (void)MI_CancelWram_B( MI_WRAM_ARM9 );
138     (void)MI_FreeWram_C( MI_WRAM_ARM9 );
139     (void)MI_CancelWram_C( MI_WRAM_ARM9 );
140 
141     FS_Init(DMA_NO_FOR_FS);
142 
143     (void)OS_EnableInterrupts();
144 
145     IsDspProcessing = FALSE;
146 
147     // Clear the screen buffer
148     MI_CpuClear8(ScrBuf, sizeof(ScrBuf));
149 
150     // Load graphics component
151     DSP_OpenStaticComponentGraphics(&file);
152     if(!DSP_LoadGraphics(&file, 0xFF, 0xFF))
153     {
154         OS_TPanic("failed to load graphics DSP-component! (lack of WRAM-B/C)");
155     }
156 
157     // Initial execution
158     ExecScaling();
159 
160     while (1)
161     {
162         DEMOReadKey();
163 
164         if (DEMO_IS_TRIG( PAD_BUTTON_START ))
165         {
166             break;    // Quit
167         }
168 
169         // Move area targeted for processing
170         if (DEMO_IS_PRESS( PAD_KEY_RIGHT ))
171         {
172             AreaX += 5;
173 
174             if (AreaX >= DATA_WIDTH - AREA_WIDTH - 1)
175             {
176                 AreaX = DATA_WIDTH - AREA_WIDTH - 1;
177             }
178             ExecScaling();
179         }
180         else if (DEMO_IS_PRESS( PAD_KEY_LEFT ))
181         {
182             if (AreaX != 0)
183             {
184                 if (AreaX <= 5)
185                 {
186                     AreaX = 0;
187                 }
188                 else
189                 {
190                     AreaX -= 5;
191                 }
192 
193                 ExecScaling();
194             }
195         }
196 
197         if (DEMO_IS_PRESS( PAD_KEY_UP ))
198         {
199             if (AreaY != 0)
200             {
201                 if (AreaY <= 5)
202                 {
203                     AreaY = 0;
204                 }
205                 else
206                 {
207                     AreaY -= 5;
208                 }
209 
210                 ExecScaling();
211             }
212         }
213         else if (DEMO_IS_PRESS( PAD_KEY_DOWN ))
214         {
215             AreaY += 5;
216             if (AreaY >= DATA_HEIGHT - AREA_HEIGHT - 1)
217             {
218                 AreaY = DATA_HEIGHT - AREA_HEIGHT - 1;
219             }
220             ExecScaling();
221         }
222 
223         // Change the interpolation mode
224         if (DEMO_IS_TRIG( PAD_BUTTON_A ))
225         {
226             DspMode++;
227             if (DspMode >= 3)
228             {
229                 DspMode = 0;
230             }
231 
232             ExecScaling();
233         }
234 
235         OS_WaitVBlankIntr();           // Waiting for the end of the V-Blank interrupt
236     }
237 
238     OS_TPrintf("demo end.\n");
239 
240     // Unload graphics component
241     DSP_UnloadGraphics();
242     OS_Terminate();
243 }
244 
245 //--------------------------------------------------------------------------------
246 //    V-Blank interrupt process
247 //
VBlankIntr(void)248 void VBlankIntr(void)
249 {
250     OS_SetIrqCheckFlag(OS_IE_V_BLANK); // Checking V-Blank interrupt
251 }
252 
253 /*--------------------------------------------------------------------------------
254     Scale the image data using the DSP and the configured options
255  ---------------------------------------------------------------------------------*/
ExecScaling()256 static void ExecScaling()
257 {
258     // Execute
259 #if RUN_ASYNC
260 
261 	if ( !IsDspProcessing )
262 	{
263 		StartTick = OS_GetTick();
264 
265 	    DSP_ScalingAsyncEx(_binary_output_dat, TmpBuf, DATA_WIDTH, DATA_HEIGHT,
266 	                       SCALING_FACTOR_X, SCALING_FACTOR_Y, ModeNames[DspMode], AreaX, AreaY, AREA_WIDTH, AREA_HEIGHT, ScalingCallbackFunc);
267 
268 	    IsDspProcessing = TRUE;
269 	}
270 
271 #else
272 	StartTick = OS_GetTick();
273     (void)DSP_ScalingEx(_binary_output_dat, TmpBuf, DATA_WIDTH, DATA_HEIGHT,
274                   SCALING_FACTOR_X, SCALING_FACTOR_Y, ModeNames[DspMode], AreaX, AreaY, AREA_WIDTH, AREA_HEIGHT);
275     OS_TPrintf("mode: %s, time: %d microsec.\n", ModeNameStrings[DspMode], OS_TicksToMicroSeconds(OS_GetTick() - StartTick));
276 
277     // Adjust data for display on screen
278     WriteScreenBuffer(TmpBuf, OUTPUT_WIDTH, OUTPUT_HEIGHT, ScrBuf);
279 
280     // Destroy the screen buffer cache
281     DC_FlushAll();
282 
283     // Load processing results to VRAM
284     GX_LoadBG3Bmp(ScrBuf, 0, HW_LCD_WIDTH * HW_LCD_HEIGHT * sizeof(u16));
285 #endif
286 
287 }
288 
InitializeGraphics()289 static void InitializeGraphics()
290 {
291     // VRAM allocation
292     GX_SetBankForBG(GX_VRAM_BG_128_A);
293     GX_SetBankForSubBG(GX_VRAM_SUB_BG_128_C);
294 
295     GX_SetGraphicsMode(GX_DISPMODE_GRAPHICS, GX_BGMODE_5, GX_BG0_AS_2D);
296     GX_SetVisiblePlane( GX_PLANEMASK_BG3 );
297     GXS_SetGraphicsMode( GX_BGMODE_4 );
298     GXS_SetVisiblePlane( GX_PLANEMASK_BG3 );
299 
300     GX_SetBGScrOffset(GX_BGSCROFFSET_0x00000);  // Set screen offset value
301     GX_SetBGCharOffset(GX_BGCHAROFFSET_0x20000);  // Configure character base offset value
302 
303     G2_BlendNone();
304     G2S_BlendNone();
305     GX_Power2DSub(TRUE);    // Turn the sub 2D graphic engine off
306 
307     // Main-BG
308     // BG3: scr 96KB
309     {
310         G2_SetBG3ControlDCBmp(GX_BG_SCRSIZE_DCBMP_256x256, GX_BG_AREAOVER_XLU, GX_BG_BMPSCRBASE_0x00000);
311         G2_SetBG3Priority(2);
312         G2_BG3Mosaic(FALSE);
313     }
314 
315     // Sub-BG
316     // BG3: scr 96KB
317     {
318         G2S_SetBG3ControlDCBmp(GX_BG_SCRSIZE_DCBMP_256x256, GX_BG_AREAOVER_XLU, GX_BG_BMPSCRBASE_0x00000);
319         G2S_SetBG3Priority(2);
320         G2S_BG3Mosaic(FALSE);
321     }
322 }
323 
324 /* Write the contents of 'data' to a 256x192 screen buffer */
WriteScreenBuffer(u16 * data,u32 width,u32 height,u16 * scr)325 static void WriteScreenBuffer(u16 *data, u32 width, u32 height, u16 *scr)
326 {
327     int i;
328     u32 lp_count;
329     u32 tmp_linesize;
330 
331     // Create scrbuf
332     if( height > HW_LCD_HEIGHT )
333     {
334         lp_count = HW_LCD_HEIGHT;
335     }
336     else
337     {
338         lp_count = height;
339     }
340 
341     // Because it is displayed on the lower screen as a 256x256 BMP, you need to take size into account.
342     // Copy line by line
343     if( width > HW_LCD_WIDTH)
344     {
345         tmp_linesize = HW_LCD_WIDTH * sizeof(u16);
346     }
347     else
348     {
349         tmp_linesize = width * sizeof(u16);
350     }
351 
352     for ( i=0; i < lp_count; i++ )
353     {
354         MI_CpuCopy( data + width * i, scr + HW_LCD_WIDTH * i, tmp_linesize );
355     }
356 }
357 
358 /* Callback function called when scaling is done */
ScalingCallbackFunc(void)359 static void ScalingCallbackFunc(void)
360 {
361     OS_TPrintf("[Async]mode: %s, time: %d microsec.\n", ModeNameStrings[DspMode], OS_TicksToMicroSeconds(OS_GetTick() - StartTick));
362 
363 	    // Adjust data for display on screen
364     WriteScreenBuffer(TmpBuf, OUTPUT_WIDTH, OUTPUT_HEIGHT, ScrBuf);
365 
366     // Destroy the screen buffer cache
367     DC_FlushAll();
368 
369     // Load processing results to VRAM
370     GX_LoadBG3Bmp(ScrBuf, 0, HW_LCD_WIDTH * HW_LCD_HEIGHT * sizeof(u16));
371 
372     IsDspProcessing = FALSE;
373 }
374 
375