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:: 2008-12-08#$
14   $Rev: 9562 $
15   $Author: kitase_hirotake $
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 the Demo
24      -- A : Changes 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     DEMOInitVRAM();
128     InitializeGraphics();
129 
130     DEMOStartDisplay();
131 
132     // Because at first there is a possibility that WRAM might have been allocated to something as per the ROM header, clear it
133     (void)MI_FreeWram_B( MI_WRAM_ARM9 );
134     (void)MI_CancelWram_B( MI_WRAM_ARM9 );
135     (void)MI_FreeWram_C( MI_WRAM_ARM9 );
136     (void)MI_CancelWram_C( MI_WRAM_ARM9 );
137 
138     FS_Init(DMA_NO_FOR_FS);
139 
140     (void)OS_EnableInterrupts();
141 
142     IsDspProcessing = FALSE;
143 
144     // Clear the screen buffer
145     MI_CpuClear8(ScrBuf, sizeof(ScrBuf));
146 
147     // Load graphics component
148     DSP_OpenStaticComponentGraphics(&file);
149     if(!DSP_LoadGraphics(&file, 0xFF, 0xFF))
150     {
151         OS_TPanic("failed to load graphics DSP-component! (lack of WRAM-B/C)");
152     }
153 
154     // Initial execution
155     ExecScaling();
156 
157     while (1)
158     {
159         DEMOReadKey();
160 
161         if (DEMO_IS_TRIG( PAD_BUTTON_START ))
162         {
163             break;    // Quit
164         }
165 
166         // Move area targeted for processing
167         if (DEMO_IS_PRESS( PAD_KEY_RIGHT ))
168         {
169             AreaX += 5;
170 
171             if (AreaX >= DATA_WIDTH - AREA_WIDTH - 1)
172             {
173                 AreaX = DATA_WIDTH - AREA_WIDTH - 1;
174             }
175             ExecScaling();
176         }
177         else if (DEMO_IS_PRESS( PAD_KEY_LEFT ))
178         {
179             if (AreaX != 0)
180             {
181                 if (AreaX <= 5)
182                 {
183                     AreaX = 0;
184                 }
185                 else
186                 {
187                     AreaX -= 5;
188                 }
189 
190                 ExecScaling();
191             }
192         }
193 
194         if (DEMO_IS_PRESS( PAD_KEY_UP ))
195         {
196             if (AreaY != 0)
197             {
198                 if (AreaY <= 5)
199                 {
200                     AreaY = 0;
201                 }
202                 else
203                 {
204                     AreaY -= 5;
205                 }
206 
207                 ExecScaling();
208             }
209         }
210         else if (DEMO_IS_PRESS( PAD_KEY_DOWN ))
211         {
212             AreaY += 5;
213             if (AreaY >= DATA_HEIGHT - AREA_HEIGHT - 1)
214             {
215                 AreaY = DATA_HEIGHT - AREA_HEIGHT - 1;
216             }
217             ExecScaling();
218         }
219 
220         // Change the interpolation mode
221         if (DEMO_IS_TRIG( PAD_BUTTON_A ))
222         {
223             DspMode++;
224             if (DspMode >= 3)
225             {
226                 DspMode = 0;
227             }
228 
229             ExecScaling();
230         }
231 
232         OS_WaitVBlankIntr();           // Waiting for the end of the V-Blank interrupt
233     }
234 
235     OS_TPrintf("demo end.\n");
236 
237     // Unload graphics component
238     DSP_UnloadGraphics();
239     OS_Terminate();
240 }
241 
242 //--------------------------------------------------------------------------------
243 //    V-Blank interrupt process
244 //
VBlankIntr(void)245 void VBlankIntr(void)
246 {
247     OS_SetIrqCheckFlag(OS_IE_V_BLANK); // Checking V-Blank interrupt
248 }
249 
250 /*--------------------------------------------------------------------------------
251     Scale image data using the DSP and the configured options
252  ---------------------------------------------------------------------------------*/
ExecScaling()253 static void ExecScaling()
254 {
255     // Execute
256 #if RUN_ASYNC
257 
258 	if ( !IsDspProcessing )
259 	{
260 		StartTick = OS_GetTick();
261 
262 	    DSP_ScalingAsyncEx(_binary_output_dat, TmpBuf, DATA_WIDTH, DATA_HEIGHT,
263 	                       SCALING_FACTOR_X, SCALING_FACTOR_Y, ModeNames[DspMode], AreaX, AreaY, AREA_WIDTH, AREA_HEIGHT, ScalingCallbackFunc);
264 
265 	    IsDspProcessing = TRUE;
266 	}
267 
268 #else
269 	StartTick = OS_GetTick();
270     (void)DSP_ScalingEx(_binary_output_dat, TmpBuf, DATA_WIDTH, DATA_HEIGHT,
271                   SCALING_FACTOR_X, SCALING_FACTOR_Y, ModeNames[DspMode], AreaX, AreaY, AREA_WIDTH, AREA_HEIGHT);
272     OS_TPrintf("mode: %s, time: %d microsec.\n", ModeNameStrings[DspMode], OS_TicksToMicroSeconds(OS_GetTick() - StartTick));
273 
274     // Adjust data for display on screen
275     WriteScreenBuffer(TmpBuf, OUTPUT_WIDTH, OUTPUT_HEIGHT, ScrBuf);
276 
277     // Destroy the screen buffer cache
278     DC_FlushAll();
279 
280     // Load processing results to VRAM
281     GX_LoadBG3Bmp(ScrBuf, 0, HW_LCD_WIDTH * HW_LCD_HEIGHT * sizeof(u16));
282 #endif
283 
284 }
285 
InitializeGraphics()286 static void InitializeGraphics()
287 {
288     // VRAM allocation
289     GX_SetBankForBG(GX_VRAM_BG_128_A);
290     GX_SetBankForSubBG(GX_VRAM_SUB_BG_128_C);
291 
292     GX_SetGraphicsMode(GX_DISPMODE_GRAPHICS, GX_BGMODE_5, GX_BG0_AS_2D);
293     GX_SetVisiblePlane( GX_PLANEMASK_BG3 );
294     GXS_SetGraphicsMode( GX_BGMODE_4 );
295     GXS_SetVisiblePlane( GX_PLANEMASK_BG3 );
296 
297     GX_SetBGScrOffset(GX_BGSCROFFSET_0x00000);  // Set screen offset value
298     GX_SetBGCharOffset(GX_BGCHAROFFSET_0x20000);  // Configure character base offset value
299 
300     G2_BlendNone();
301     G2S_BlendNone();
302     GX_Power2DSub(TRUE);    // Turn the sub 2D graphic engine off
303 
304     // Main-BG
305     // BG3: scr 96KB
306     {
307         G2_SetBG3ControlDCBmp(GX_BG_SCRSIZE_DCBMP_256x256, GX_BG_AREAOVER_XLU, GX_BG_BMPSCRBASE_0x00000);
308         G2_SetBG3Priority(2);
309         G2_BG3Mosaic(FALSE);
310     }
311 
312     // Sub-BG
313     // BG3: scr 96KB
314     {
315         G2S_SetBG3ControlDCBmp(GX_BG_SCRSIZE_DCBMP_256x256, GX_BG_AREAOVER_XLU, GX_BG_BMPSCRBASE_0x00000);
316         G2S_SetBG3Priority(2);
317         G2S_BG3Mosaic(FALSE);
318     }
319 }
320 
321 /* Write the contents of 'data' to a 256x192 screen buffer*/
WriteScreenBuffer(u16 * data,u32 width,u32 height,u16 * scr)322 static void WriteScreenBuffer(u16 *data, u32 width, u32 height, u16 *scr)
323 {
324     int i;
325     u32 lp_count;
326     u32 tmp_linesize;
327 
328     // Create scrbuf
329     if( height > HW_LCD_HEIGHT )
330     {
331         lp_count = HW_LCD_HEIGHT;
332     }
333     else
334     {
335         lp_count = height;
336     }
337 
338     // Because it is displayed on the lower screen as a 256x256 BMP, you need to take size into account.
339     // Copy line by line
340     if( width > HW_LCD_WIDTH)
341     {
342         tmp_linesize = HW_LCD_WIDTH * sizeof(u16);
343     }
344     else
345     {
346         tmp_linesize = width * sizeof(u16);
347     }
348 
349     for ( i=0; i < lp_count; i++ )
350     {
351         MI_CpuCopy( data + width * i, scr + HW_LCD_WIDTH * i, tmp_linesize );
352     }
353 }
354 
355 /* Callback function called when scaling is done*/
ScalingCallbackFunc(void)356 static void ScalingCallbackFunc(void)
357 {
358     OS_TPrintf("[Async]mode: %s, time: %d microsec.\n", ModeNameStrings[DspMode], OS_TicksToMicroSeconds(OS_GetTick() - StartTick));
359 
360 	    // Adjust data for display on screen
361     WriteScreenBuffer(TmpBuf, OUTPUT_WIDTH, OUTPUT_HEIGHT, ScrBuf);
362 
363     // Destroy the screen buffer cache
364     DC_FlushAll();
365 
366     // Load processing results to VRAM
367     GX_LoadBG3Bmp(ScrBuf, 0, HW_LCD_WIDTH * HW_LCD_HEIGHT * sizeof(u16));
368 
369     IsDspProcessing = FALSE;
370 }
371