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