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