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