1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - DSP - demos - scaling-2
3 File: main.c
4
5 Copyright 2008-2009 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 This demo enlarges (or shrinks) 640x480 image data to fit a specified size 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 post-scaling size, modify OUTPUT_WIDTH and OUTPUT_HEIGHT 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 1 // Whether to scale asynchronously
50 #define USE_FX32 1 // This is 1 when using the fx32 version of DSP_Scaling
51
52 #define DMA_NO_FOR_FS 1 // For FS_Init
53
54 #define AREA_WIDTH 185 // Width of the area to scale
55 #define AREA_HEIGHT 140 // Height of the area to scale
56
57 #define OUTPUT_WIDTH HW_LCD_WIDTH // Resolution after processing
58 #define OUTPUT_HEIGHT HW_LCD_HEIGHT
59
60 /*---------------------------------------------------------------------------*
61 Image data (640x480)
62 *---------------------------------------------------------------------------*/
63 extern const u8 _binary_output_dat[];
64 extern const u8 _binary_output_dat_end[];
65
66 #define DATA_WIDTH 640
67 #define DATA_HEIGHT 480
68
69 /*---------------------------------------------------------------------------*
70 Prototype Declarations
71 *---------------------------------------------------------------------------*/
72 void VBlankIntr(void);
73
74 static void ExecScaling(void);
75 static void InitializeGraphics(void);
76 static void WriteScreenBuffer(u16 *data, u32 width, u32 height, u16 *scr);
77 static void ScalingCallbackFunc(void);
78
79 /*---------------------------------------------------------------------------*
80 Internal Variable Definitions
81 *---------------------------------------------------------------------------*/
82 // Screen buffers for main and sub-screens
83 static u16 ScrBuf[HW_LCD_WIDTH * HW_LCD_HEIGHT] ATTRIBUTE_ALIGN(32);
84 // Buffer storing results after transformation by the DSP
85 static u16 TmpBuf[OUTPUT_WIDTH * OUTPUT_HEIGHT] ATTRIBUTE_ALIGN(32);
86
87 static OSTick StartTick; // Variable for measuring DSP processing time
88 static BOOL IsDspProcessing; // Whether DSP is currently processing something (used when running this as an asynchronous process)
89
90 static u16 AreaX = 0; // Upper-left x-coordinate of area to scale
91 static u16 AreaY = 0; // Upper-left y-coordinate of area to scale
92
93 // Interpolation mode
94 static u16 ModeNames[3] = {
95 DSP_GRAPHICS_SCALING_MODE_N_NEIGHBOR,
96 DSP_GRAPHICS_SCALING_MODE_BILINEAR,
97 DSP_GRAPHICS_SCALING_MODE_BICUBIC
98 };
99
100 static u8 ModeNameStrings[3][24] = {
101 "Nearest Neighbor",
102 "Bilinear",
103 "Bicubic"
104 };
105
106 static u32 DspMode = 0;
107
108 /*---------------------------------------------------------------------------*
109 Name: TwlMain
110
111 Description: Initialization and main loop.
112
113 Arguments: None.
114
115 Returns: None.
116 *---------------------------------------------------------------------------*/
TwlMain(void)117 void TwlMain(void)
118 {
119 FSFile file;
120
121 DEMOInitCommon();
122 OS_InitThread();
123 OS_InitTick();
124 OS_InitAlarm(); // This is required when using synchronous versions of DSP_Scaling* functions (because the OS_Sleep function is used internally)
125
126 // When in NITRO mode, stopped by Panic
127 DEMOCheckRunOnTWL();
128
129 DEMOInitVRAM();
130 InitializeGraphics();
131
132 DEMOStartDisplay();
133
134 // Because at first there is a possibility that WRAM might have been allocated to something as per the ROM header, clear it
135 (void)MI_FreeWram_B( MI_WRAM_ARM9 );
136 (void)MI_CancelWram_B( MI_WRAM_ARM9 );
137 (void)MI_FreeWram_C( MI_WRAM_ARM9 );
138 (void)MI_CancelWram_C( MI_WRAM_ARM9 );
139 (void)MI_FreeWram_B( MI_WRAM_ARM7 );
140 (void)MI_CancelWram_B( MI_WRAM_ARM7 );
141 (void)MI_FreeWram_C( MI_WRAM_ARM7 );
142 (void)MI_CancelWram_C( MI_WRAM_ARM7 );
143
144 FS_Init(DMA_NO_FOR_FS);
145
146 (void)OS_EnableInterrupts();
147
148 IsDspProcessing = FALSE;
149
150 // Clear the screen buffer
151 MI_CpuClear8(ScrBuf, sizeof(ScrBuf));
152
153 // Load graphics component
154 DSP_OpenStaticComponentGraphics(&file);
155 if(!DSP_LoadGraphics(&file, 0xFF, 0xFF))
156 {
157 OS_TPanic("failed to load graphics DSP-component! (lack of WRAM-B/C)");
158 }
159
160 // Initial execution
161 ExecScaling();
162
163 while (1)
164 {
165 DEMOReadKey();
166
167 if (DEMO_IS_TRIG( PAD_BUTTON_START ))
168 {
169 break; // Quit
170 }
171
172 // Move area targeted for processing
173 if (DEMO_IS_PRESS( PAD_KEY_RIGHT ))
174 {
175 AreaX += 5;
176
177 if (AreaX >= DATA_WIDTH - AREA_WIDTH - 1)
178 {
179 AreaX = DATA_WIDTH - AREA_WIDTH - 1;
180 }
181 ExecScaling();
182 }
183 else if (DEMO_IS_PRESS( PAD_KEY_LEFT ))
184 {
185 if (AreaX != 0)
186 {
187 if (AreaX <= 5)
188 {
189 AreaX = 0;
190 }
191 else
192 {
193 AreaX -= 5;
194 }
195
196 ExecScaling();
197 }
198 }
199
200 if (DEMO_IS_PRESS( PAD_KEY_UP ))
201 {
202 if (AreaY != 0)
203 {
204 if (AreaY <= 5)
205 {
206 AreaY = 0;
207 }
208 else
209 {
210 AreaY -= 5;
211 }
212
213 ExecScaling();
214 }
215 }
216 else if (DEMO_IS_PRESS( PAD_KEY_DOWN ))
217 {
218 AreaY += 5;
219 if (AreaY >= DATA_HEIGHT - AREA_HEIGHT - 1)
220 {
221 AreaY = DATA_HEIGHT - AREA_HEIGHT - 1;
222 }
223 ExecScaling();
224 }
225
226 // Change the interpolation mode
227 if (DEMO_IS_TRIG( PAD_BUTTON_A ))
228 {
229 DspMode++;
230 if (DspMode >= 3)
231 {
232 DspMode = 0;
233 }
234
235 ExecScaling();
236 }
237
238 OS_WaitVBlankIntr(); // Waiting for the end of the V-Blank interrupt
239 }
240
241 OS_TPrintf("demo end.\n");
242
243 // Unload graphics component
244 DSP_UnloadGraphics();
245 OS_Terminate();
246 }
247
248 //--------------------------------------------------------------------------------
249 // V-Blank interrupt process
250 //
VBlankIntr(void)251 void VBlankIntr(void)
252 {
253 OS_SetIrqCheckFlag(OS_IE_V_BLANK); // Checking V-Blank interrupt
254 }
255
256 /*--------------------------------------------------------------------------------
257 Scale the image data using the DSP and the configured options
258 ---------------------------------------------------------------------------------*/
ExecScaling()259 static void ExecScaling()
260 {
261 // Get the scale ratio for input to the DSP_Scaling function from the desired output size
262 #if USE_FX32
263 fx32 factx, facty;
264 factx = DSP_CalcScalingFactorFx32(AREA_WIDTH, OUTPUT_WIDTH);
265 facty = DSP_CalcScalingFactorFx32(AREA_HEIGHT, OUTPUT_HEIGHT);
266 #else
267 f32 factx, facty;
268 factx = DSP_CalcScalingFactorF32(AREA_WIDTH, OUTPUT_WIDTH);
269 facty = DSP_CalcScalingFactorF32(AREA_HEIGHT, OUTPUT_HEIGHT);
270 #endif
271
272 // Execute
273 #if RUN_ASYNC
274
275 if ( !IsDspProcessing )
276 {
277 StartTick = OS_GetTick();
278 #if USE_FX32
279 (void)DSP_ScalingFxAsyncEx(_binary_output_dat, TmpBuf, DATA_WIDTH, DATA_HEIGHT,
280 factx, facty, ModeNames[DspMode], AreaX, AreaY, AREA_WIDTH, AREA_HEIGHT, ScalingCallbackFunc);
281 #else
282 (void)DSP_ScalingAsyncEx(_binary_output_dat, TmpBuf, DATA_WIDTH, DATA_HEIGHT,
283 factx, facty, ModeNames[DspMode], AreaX, AreaY, AREA_WIDTH, AREA_HEIGHT, ScalingCallbackFunc);
284 #endif // USE_FX32
285
286 IsDspProcessing = TRUE;
287 }
288
289 #else // RUN_ASYNC == 0
290 StartTick = OS_GetTick();
291
292 #if USE_FX32
293 DSP_ScalingFxEx(_binary_output_dat, TmpBuf, DATA_WIDTH, DATA_HEIGHT,
294 factx, facty, ModeNames[DspMode], AreaX, AreaY, AREA_WIDTH, AREA_HEIGHT);
295 #else
296 (void)DSP_ScalingEx(_binary_output_dat, TmpBuf, DATA_WIDTH, DATA_HEIGHT,
297 factx, facty, ModeNames[DspMode], AreaX, AreaY, AREA_WIDTH, AREA_HEIGHT);
298 #endif // USE_FX32
299
300 OS_TPrintf("mode: %s, time: %d microsec.\n", ModeNameStrings[DspMode], OS_TicksToMicroSeconds(OS_GetTick() - StartTick));
301
302 // Adjust data for display on screen
303 WriteScreenBuffer(TmpBuf, OUTPUT_WIDTH, OUTPUT_HEIGHT, ScrBuf);
304 // Destroy the screen buffer cache
305 DC_FlushAll();
306 // Load processing results to VRAM
307 GX_LoadBG3Bmp(ScrBuf, 0, HW_LCD_WIDTH * HW_LCD_HEIGHT * sizeof(u16));
308 #endif // RUN_ASYNC
309
310 }
311
InitializeGraphics()312 static void InitializeGraphics()
313 {
314 // VRAM allocation
315 GX_SetBankForBG(GX_VRAM_BG_128_A);
316 GX_SetBankForSubBG(GX_VRAM_SUB_BG_128_C);
317
318 GX_SetGraphicsMode(GX_DISPMODE_GRAPHICS, GX_BGMODE_5, GX_BG0_AS_2D);
319 GX_SetVisiblePlane( GX_PLANEMASK_BG3 );
320 GXS_SetGraphicsMode( GX_BGMODE_4 );
321 GXS_SetVisiblePlane( GX_PLANEMASK_BG3 );
322
323 GX_SetBGScrOffset(GX_BGSCROFFSET_0x00000); // Set screen offset value
324 GX_SetBGCharOffset(GX_BGCHAROFFSET_0x20000); // Configure character base offset value
325
326 G2_BlendNone();
327 G2S_BlendNone();
328 GX_Power2DSub(TRUE); // Turn the sub 2D graphic engine off
329
330 // Main-BG
331 // BG3: scr 96KB
332 {
333 G2_SetBG3ControlDCBmp(GX_BG_SCRSIZE_DCBMP_256x256, GX_BG_AREAOVER_XLU, GX_BG_BMPSCRBASE_0x00000);
334 G2_SetBG3Priority(2);
335 G2_BG3Mosaic(FALSE);
336 }
337
338 // Sub-BG
339 // BG3: scr 96KB
340 {
341 G2S_SetBG3ControlDCBmp(GX_BG_SCRSIZE_DCBMP_256x256, GX_BG_AREAOVER_XLU, GX_BG_BMPSCRBASE_0x00000);
342 G2S_SetBG3Priority(2);
343 G2S_BG3Mosaic(FALSE);
344 }
345 }
346
347 /* Write the contents of 'data' to a 256x192 screen buffer */
WriteScreenBuffer(u16 * data,u32 width,u32 height,u16 * scr)348 static void WriteScreenBuffer(u16 *data, u32 width, u32 height, u16 *scr)
349 {
350 int i;
351 u32 lp_count;
352 u32 tmp_linesize;
353
354 // Create scrbuf
355 if( height > HW_LCD_HEIGHT )
356 {
357 lp_count = HW_LCD_HEIGHT;
358 }
359 else
360 {
361 lp_count = height;
362 }
363
364 // Because it is displayed on the lower screen as a 256x256 BMP, you need to take size into account.
365 // Copy line by line
366 if( width > HW_LCD_WIDTH)
367 {
368 tmp_linesize = HW_LCD_WIDTH * sizeof(u16);
369 }
370 else
371 {
372 tmp_linesize = width * sizeof(u16);
373 }
374
375 for ( i=0; i < lp_count; i++ )
376 {
377 MI_CpuCopy( data + width * i, scr + HW_LCD_WIDTH * i, tmp_linesize );
378 }
379 }
380
381 /* Callback function called when scaling is done */
ScalingCallbackFunc(void)382 static void ScalingCallbackFunc(void)
383 {
384 OS_TPrintf("[Async]mode: %s, time: %d microsec.\n", ModeNameStrings[DspMode], OS_TicksToMicroSeconds(OS_GetTick() - StartTick));
385
386 // Adjust data for display on screen
387 WriteScreenBuffer(TmpBuf, OUTPUT_WIDTH, OUTPUT_HEIGHT, ScrBuf);
388 // Destroy the screen buffer cache
389 DC_FlushAll();
390 // Load processing results to VRAM
391 GX_LoadBG3Bmp(ScrBuf, 0, HW_LCD_WIDTH * HW_LCD_HEIGHT * sizeof(u16));
392
393 IsDspProcessing = FALSE;
394 }
395
396