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