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