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