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