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