1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - DSP - demos - yuvToRgb
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:: 2010-05-17#$
14 $Rev: 11335 $
15 $Author: kitase_hirotake $
16 *---------------------------------------------------------------------------*/
17
18 /*---------------------------------------------------------------------------
19 This demo gets an image in YUV422 format from the camera and uses the DSP to convert to RGB555 and display it on screen.
20
21
22 Exit with the START Button.
23 ----------------------------------------------------------------------------*/
24
25 #include <twl.h>
26 #include <twl/dsp.h>
27
28 #include <twl/camera.h>
29
30 #include <DEMO.h>
31 #include <twl/dsp/common/graphics.h>
32
33 /* Settings */
34 #define DMA_NO_FOR_FS 3 // For FS_Init
35 #define CAMERA_NEW_DMA_NO 1 // New DMA number used for CAMERA
36
37 #define CAM_WIDTH 256 // Width of image the camera gets
38 #define CAM_HEIGHT 192 // Height of image the camera gets
39
40 #define LINES_AT_ONCE CAMERA_GET_MAX_LINES(CAM_WIDTH) // Number of lines transferred in one cycle
41 #define BYTES_PER_LINE CAMERA_GET_LINE_BYTES(CAM_WIDTH) // Number of bytes in one line's transfer
42
43 /*---------------------------------------------------------------------------*
44 Prototype Declarations
45 *---------------------------------------------------------------------------*/
46 void VBlankIntr(void);
47 static void CameraIntrVsync(CAMERAResult result);
48 static void CameraIntrError(CAMERAResult result);
49 static void CameraIntrReboot(CAMERAResult result);
50 static void InitializeGraphics(void);
51 static void InitializeCamera(void);
52 static void WriteScreenBuffer(u16 *data, u32 width, u32 height, u16 *scr);
53 static void ConvertCallbackFunc(void);
54
55 /*---------------------------------------------------------------------------*
56 Internal Variable Definitions
57 *---------------------------------------------------------------------------*/
58 // Screen buffers for main and sub-screens
59 // Buffer that stores the image obtained by the camera as well as the DSP conversion results
60 static u16 TmpBuf[2][CAM_WIDTH * CAM_HEIGHT] ATTRIBUTE_ALIGN(32);
61
62 static BOOL StartRequest = FALSE;
63 static OSTick StartTick; // Variable for measuring DSP processing time
64
65 static int wp; // Buffer while capturing data from camera
66 static int rp; // Buffer most recently copied to VRAM
67 static BOOL wp_pending; // Data capture was cancelled (recapture to same buffer)
68
69 static BOOL IsConvertNow = FALSE; // Whether YUV to RGB conversion is underway
70
71 /*---------------------------------------------------------------------------*
72 Name: TwlMain
73
74 Description: Initialization and main loop.
75
76 Arguments: None.
77
78 Returns: None.
79 *---------------------------------------------------------------------------*/
TwlMain(void)80 void TwlMain(void)
81 {
82 FSFile file;
83
84 DEMOInitCommon();
85 OS_InitThread();
86 OS_InitTick();
87 OS_InitAlarm();
88
89 // When in NITRO mode, stopped by Panic
90 DEMOCheckRunOnTWL();
91
92 DEMOInitVRAM();
93 InitializeGraphics();
94 InitializeCamera();
95
96 DEMOStartDisplay();
97
98 // DMA is not used in GX (the old DMA conflicts with camera DMA)
99 (void)GX_SetDefaultDMA(GX_DMA_NOT_USE);
100
101 // Because at first there is a possibility that WRAM might have been allocated to something as per the ROM header, clear it
102 (void)MI_FreeWram_B( MI_WRAM_ARM9 );
103 (void)MI_CancelWram_B( MI_WRAM_ARM9 );
104 (void)MI_FreeWram_C( MI_WRAM_ARM9 );
105 (void)MI_CancelWram_C( MI_WRAM_ARM9 );
106 (void)MI_FreeWram_B( MI_WRAM_ARM7 );
107 (void)MI_CancelWram_B( MI_WRAM_ARM7 );
108 (void)MI_FreeWram_C( MI_WRAM_ARM7 );
109 (void)MI_CancelWram_C( MI_WRAM_ARM7 );
110
111 FS_Init(DMA_NO_FOR_FS);
112
113 (void)OS_EnableInterrupts();
114
115 // Load graphics component
116 DSP_OpenStaticComponentGraphics(&file);
117 if(!DSP_LoadGraphics(&file, 0xFF, 0xFF))
118 {
119 OS_TPanic("failed to load graphics DSP-component! (lack of WRAM-B/C)");
120 }
121
122 // Camera start
123 wp = 0;
124 rp = 1;
125 wp_pending = TRUE;
126 StartRequest = TRUE;
127 CameraIntrVsync(CAMERA_RESULT_SUCCESS);
128 OS_TPrintf("Camera is shooting a movie...\n");
129 OS_TPrintf("Press A Button.\n");
130
131 while (1)
132 {
133 DEMOReadKey();
134
135 if (DEMO_IS_TRIG( PAD_BUTTON_START ))
136 {
137 break; // Quit
138 }
139
140 if (wp == rp && !IsConvertNow)
141 {
142 rp ^= 1;
143 DC_FlushRange(TmpBuf[rp], BYTES_PER_LINE * CAM_HEIGHT);
144 GX_LoadBG3Scr(TmpBuf[rp], 0, BYTES_PER_LINE * CAM_HEIGHT);
145 }
146
147 OS_WaitVBlankIntr(); // Waiting for the end of the V-Blank interrupt
148 }
149
150 OS_TPrintf("demo end.\n");
151
152 // Unload graphics component
153 DSP_UnloadGraphics();
154 OS_Terminate();
155 }
156
157 //--------------------------------------------------------------------------------
158 // V-Blank interrupt process
159 //
VBlankIntr(void)160 void VBlankIntr(void)
161 {
162 OS_SetIrqCheckFlag(OS_IE_V_BLANK); // Checking V-Blank interrupt
163 }
164
165 // Camera interrupt
CameraIntrError(CAMERAResult result)166 void CameraIntrError(CAMERAResult result)
167 {
168 #pragma unused(result)
169 OS_TPrintf("Error was occurred.\n");
170 // Stopping
171 CAMERA_StopCapture(); // Stop the camera
172 CAMERA_ClearBuffer(); // Clear
173 MI_StopNDma(CAMERA_NEW_DMA_NO); // Stop DMA
174 wp_pending = TRUE; // Also use same frame next time
175 StartRequest = TRUE; // Camera restart request
176 }
177
CameraIntrReboot(CAMERAResult result)178 void CameraIntrReboot(CAMERAResult result)
179 {
180 if(result == CAMERA_RESULT_FATAL_ERROR)
181 {
182 return; // Restore was not possible, even after restarting camera
183 }
184 // Camera start
185 CAMERA_ClearBuffer();
186 MI_StopNDma(CAMERA_NEW_DMA_NO);
187 wp_pending = TRUE; // Also use same frame next time
188 StartRequest = TRUE; // Camera restart request
189 }
190
191
CameraIntrVsync(CAMERAResult result)192 void CameraIntrVsync(CAMERAResult result)
193 {
194 #pragma unused(result)
195 // The following is processing during V-sync
196 if (StartRequest)
197 {
198 CAMERA_ClearBuffer();
199 CAMERA_StartCapture();
200 StartRequest = FALSE;
201 }
202
203 if (CAMERA_IsBusy() == FALSE) // Done executing stop command?
204 {
205 }
206 else
207 {
208 if (MI_IsNDmaBusy(CAMERA_NEW_DMA_NO)) // NOT done capturing last frame?
209 {
210 OS_TPrintf("DMA was not done until VBlank.\n");
211 MI_StopNDma(CAMERA_NEW_DMA_NO); // Stop DMA
212 }
213 // Start to capture for next frame
214 if (wp_pending)
215 {
216 wp_pending = FALSE;
217 }
218 else
219 {
220 // Change update buffer
221 wp ^= 1;
222 IsConvertNow = TRUE;
223 StartTick = OS_GetTick();
224 (void)DSP_ConvertYuvToRgbAsync(TmpBuf[rp ^1], TmpBuf[rp ^1], CAM_WIDTH * CAM_HEIGHT * sizeof(u16), ConvertCallbackFunc);
225 }
226
227 CAMERA_DmaRecvAsync(CAMERA_NEW_DMA_NO, TmpBuf[wp], CAMERA_GetBytesAtOnce(CAM_WIDTH), CAMERA_GET_FRAME_BYTES(CAM_WIDTH, CAM_HEIGHT), NULL, NULL);
228 }
229 }
230
InitializeGraphics()231 static void InitializeGraphics()
232 {
233 // VRAM allocation
234 GX_SetBankForBG(GX_VRAM_BG_128_A);
235 GX_SetBankForSubBG(GX_VRAM_SUB_BG_128_C);
236
237 GX_SetGraphicsMode(GX_DISPMODE_GRAPHICS, GX_BGMODE_5, GX_BG0_AS_2D);
238 GX_SetVisiblePlane( GX_PLANEMASK_BG3 );
239 GXS_SetGraphicsMode( GX_BGMODE_4 );
240 GXS_SetVisiblePlane( GX_PLANEMASK_BG3 );
241
242 GX_SetBGScrOffset(GX_BGSCROFFSET_0x00000); // Set screen offset value
243 GX_SetBGCharOffset(GX_BGCHAROFFSET_0x20000); // Configure character base offset value
244
245 G2_BlendNone();
246 G2S_BlendNone();
247 GX_Power2DSub(TRUE); // Turn the sub 2D graphic engine off
248
249 // Main-BG
250 // BG3: scr 96KB
251 {
252 G2_SetBG3ControlDCBmp(GX_BG_SCRSIZE_DCBMP_256x256, GX_BG_AREAOVER_XLU, GX_BG_BMPSCRBASE_0x00000);
253 G2_SetBG3Priority(2);
254 G2_BG3Mosaic(FALSE);
255 }
256
257 // Sub-BG
258 // BG3: scr 96KB
259 {
260 G2S_SetBG3ControlDCBmp(GX_BG_SCRSIZE_DCBMP_256x256, GX_BG_AREAOVER_XLU, GX_BG_BMPSCRBASE_0x00000);
261 G2S_SetBG3Priority(2);
262 G2S_BG3Mosaic(FALSE);
263 }
264 }
265
InitializeCamera(void)266 static void InitializeCamera(void)
267 {
268 CAMERAResult result;
269
270 result = CAMERA_Init();
271 if(result == CAMERA_RESULT_FATAL_ERROR)
272 OS_TPanic("CAMERA_Init was failed.");
273
274 result = CAMERA_I2CActivate(CAMERA_SELECT_IN);
275 if (result == CAMERA_RESULT_FATAL_ERROR)
276 OS_TPanic("CAMERA_I2CActivate was failed. (%d)\n", result);
277
278 // Camera VSYNC interrupt callback
279 CAMERA_SetVsyncCallback(CameraIntrVsync);
280
281 // Camera error interrupt callback
282 CAMERA_SetBufferErrorCallback(CameraIntrError);
283
284 // Camera restart completion callback
285 CAMERA_SetRebootCallback(CameraIntrReboot);
286
287 CAMERA_SetOutputFormat(CAMERA_OUTPUT_YUV);
288 CAMERA_SetTransferLines(CAMERA_GET_MAX_LINES(CAM_WIDTH));
289 }
290
291 /* Callback function called when YUV to RGB conversion is done */
ConvertCallbackFunc(void)292 static void ConvertCallbackFunc(void)
293 {
294 OS_TPrintf("[Async]time: %d microsec.\n", OS_TicksToMicroSeconds(OS_GetTick() - StartTick));
295 IsConvertNow = FALSE;
296 }
297
298