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:: 2009-09-24#$
14 $Rev: 11063 $
15 $Author: okubata_ryoma $
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
107 FS_Init(DMA_NO_FOR_FS);
108
109 (void)OS_EnableInterrupts();
110
111 // Load graphics component
112 DSP_OpenStaticComponentGraphics(&file);
113 if(!DSP_LoadGraphics(&file, 0xFF, 0xFF))
114 {
115 OS_TPanic("failed to load graphics DSP-component! (lack of WRAM-B/C)");
116 }
117
118 // Camera start
119 wp = 0;
120 rp = 1;
121 wp_pending = TRUE;
122 StartRequest = TRUE;
123 CameraIntrVsync(CAMERA_RESULT_SUCCESS);
124 OS_TPrintf("Camera is shooting a movie...\n");
125 OS_TPrintf("Press A Button.\n");
126
127 while (1)
128 {
129 DEMOReadKey();
130
131 if (DEMO_IS_TRIG( PAD_BUTTON_START ))
132 {
133 break; // Quit
134 }
135
136 if (wp == rp && !IsConvertNow)
137 {
138 rp ^= 1;
139 DC_FlushRange(TmpBuf[rp], BYTES_PER_LINE * CAM_HEIGHT);
140 GX_LoadBG3Scr(TmpBuf[rp], 0, BYTES_PER_LINE * CAM_HEIGHT);
141 }
142
143 OS_WaitVBlankIntr(); // Waiting for the end of the V-Blank interrupt
144 }
145
146 OS_TPrintf("demo end.\n");
147
148 // Unload graphics component
149 DSP_UnloadGraphics();
150 OS_Terminate();
151 }
152
153 //--------------------------------------------------------------------------------
154 // V-Blank interrupt process
155 //
VBlankIntr(void)156 void VBlankIntr(void)
157 {
158 OS_SetIrqCheckFlag(OS_IE_V_BLANK); // Checking V-Blank interrupt
159 }
160
161 // Camera interrupt
CameraIntrError(CAMERAResult result)162 void CameraIntrError(CAMERAResult result)
163 {
164 #pragma unused(result)
165 OS_TPrintf("Error was occurred.\n");
166 // Stopping
167 CAMERA_StopCapture(); // Stop the camera
168 CAMERA_ClearBuffer(); // Clear
169 MI_StopNDma(CAMERA_NEW_DMA_NO); // Stop DMA
170 wp_pending = TRUE; // Also use same frame next time
171 StartRequest = TRUE; // Camera restart request
172 }
173
CameraIntrReboot(CAMERAResult result)174 void CameraIntrReboot(CAMERAResult result)
175 {
176 if(result == CAMERA_RESULT_FATAL_ERROR)
177 {
178 return; // Restore was not possible, even after restarting camera
179 }
180 // Camera start
181 CAMERA_ClearBuffer();
182 MI_StopNDma(CAMERA_NEW_DMA_NO);
183 wp_pending = TRUE; // Also use same frame next time
184 StartRequest = TRUE; // Camera restart request
185 }
186
187
CameraIntrVsync(CAMERAResult result)188 void CameraIntrVsync(CAMERAResult result)
189 {
190 #pragma unused(result)
191 // The following is processing during V-sync
192 if (StartRequest)
193 {
194 CAMERA_ClearBuffer();
195 CAMERA_StartCapture();
196 StartRequest = FALSE;
197 }
198
199 if (CAMERA_IsBusy() == FALSE) // Done executing stop command?
200 {
201 }
202 else
203 {
204 if (MI_IsNDmaBusy(CAMERA_NEW_DMA_NO)) // NOT done capturing last frame?
205 {
206 OS_TPrintf("DMA was not done until VBlank.\n");
207 MI_StopNDma(CAMERA_NEW_DMA_NO); // Stop DMA
208 }
209 // Start to capture for next frame
210 if (wp_pending)
211 {
212 wp_pending = FALSE;
213 }
214 else
215 {
216 // Change update buffer
217 wp ^= 1;
218 IsConvertNow = TRUE;
219 StartTick = OS_GetTick();
220 (void)DSP_ConvertYuvToRgbAsync(TmpBuf[rp ^1], TmpBuf[rp ^1], CAM_WIDTH * CAM_HEIGHT * sizeof(u16), ConvertCallbackFunc);
221 }
222
223 CAMERA_DmaRecvAsync(CAMERA_NEW_DMA_NO, TmpBuf[wp], CAMERA_GetBytesAtOnce(CAM_WIDTH), CAMERA_GET_FRAME_BYTES(CAM_WIDTH, CAM_HEIGHT), NULL, NULL);
224 }
225 }
226
InitializeGraphics()227 static void InitializeGraphics()
228 {
229 // VRAM allocation
230 GX_SetBankForBG(GX_VRAM_BG_128_A);
231 GX_SetBankForSubBG(GX_VRAM_SUB_BG_128_C);
232
233 GX_SetGraphicsMode(GX_DISPMODE_GRAPHICS, GX_BGMODE_5, GX_BG0_AS_2D);
234 GX_SetVisiblePlane( GX_PLANEMASK_BG3 );
235 GXS_SetGraphicsMode( GX_BGMODE_4 );
236 GXS_SetVisiblePlane( GX_PLANEMASK_BG3 );
237
238 GX_SetBGScrOffset(GX_BGSCROFFSET_0x00000); // Set screen offset value
239 GX_SetBGCharOffset(GX_BGCHAROFFSET_0x20000); // Configure character base offset value
240
241 G2_BlendNone();
242 G2S_BlendNone();
243 GX_Power2DSub(TRUE); // Turn the sub 2D graphic engine off
244
245 // Main-BG
246 // BG3: scr 96KB
247 {
248 G2_SetBG3ControlDCBmp(GX_BG_SCRSIZE_DCBMP_256x256, GX_BG_AREAOVER_XLU, GX_BG_BMPSCRBASE_0x00000);
249 G2_SetBG3Priority(2);
250 G2_BG3Mosaic(FALSE);
251 }
252
253 // Sub-BG
254 // BG3: scr 96KB
255 {
256 G2S_SetBG3ControlDCBmp(GX_BG_SCRSIZE_DCBMP_256x256, GX_BG_AREAOVER_XLU, GX_BG_BMPSCRBASE_0x00000);
257 G2S_SetBG3Priority(2);
258 G2S_BG3Mosaic(FALSE);
259 }
260 }
261
InitializeCamera(void)262 static void InitializeCamera(void)
263 {
264 CAMERAResult result;
265
266 result = CAMERA_Init();
267 if(result == CAMERA_RESULT_FATAL_ERROR)
268 OS_TPanic("CAMERA_Init was failed.");
269
270 result = CAMERA_I2CActivate(CAMERA_SELECT_IN);
271 if (result == CAMERA_RESULT_FATAL_ERROR)
272 OS_TPanic("CAMERA_I2CActivate was failed. (%d)\n", result);
273
274 // Camera VSYNC interrupt callback
275 CAMERA_SetVsyncCallback(CameraIntrVsync);
276
277 // Camera error interrupt callback
278 CAMERA_SetBufferErrorCallback(CameraIntrError);
279
280 // Camera restart completion callback
281 CAMERA_SetRebootCallback(CameraIntrReboot);
282
283 CAMERA_SetOutputFormat(CAMERA_OUTPUT_YUV);
284 CAMERA_SetTransferLines(CAMERA_GET_MAX_LINES(CAM_WIDTH));
285 }
286
287 /* Callback function called when YUV to RGB conversion is done */
ConvertCallbackFunc(void)288 static void ConvertCallbackFunc(void)
289 {
290 OS_TPrintf("[Async]time: %d microsec.\n", OS_TicksToMicroSeconds(OS_GetTick() - StartTick));
291 IsConvertNow = FALSE;
292 }
293
294