1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - CAMERA - demos - simpleShoot-1
3   File:     main.c
4 
5   Copyright 2003-2009 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-06-04#$
14   $Rev: 10698 $
15   $Author: okubata_ryoma $
16  *---------------------------------------------------------------------------*/
17 
18 #include <twl.h>
19 #include "DEMO.h"
20 #include <twl/camera.h>
21 #include <twl/dsp.h>
22 #include <twl/dsp/common/g711.h>
23 
24 #include    "snd_data.h"
25 
26 #define NDMA_NO      1           // The NDMA number (0 to 3) to use
27 #define WIDTH       256         // Image width
28 #define HEIGHT      192         // Image height
29 
30 #define LINES_AT_ONCE   CAMERA_GET_MAX_LINES(WIDTH)     // Number of lines transferred in one cycle
31 #define BYTES_PER_LINE  CAMERA_GET_LINE_BYTES(WIDTH)    // Number of bytes in one line's transfer
32 
33 void VBlankIntr(void);
34 static BOOL CameraInit(void);
35 static void CameraIntrVsync(CAMERAResult result);
36 static void CameraIntrError(CAMERAResult result);
37 static void CameraIntrReboot(CAMERAResult result);
38 static void CameraDmaRecvIntr(void* arg);
39 
40 static int wp;  // Buffer while capturing data from camera
41 static int rp;  // Buffer most recently copied to VRAM
42 static BOOL wp_pending; // Data capture was cancelled (recapture to same buffer)
43 static u32 stabilizedCount;
44 static u16 buffer[2][WIDTH*HEIGHT] ATTRIBUTE_ALIGN(32);
45 
46 static BOOL switchFlag;
47 
48 #define STRM_BUF_SIZE 1024*64
49 
50 static char StrmBuf[STRM_BUF_SIZE] ATTRIBUTE_ALIGN(32);
51 static u32 len;
52 
53 // Filename
54 static const char filename1[] = "shutter_sound_32730.wav";
55 
DebugReport(void)56 static void DebugReport(void)
57 {
58     OS_TPrintf("\nCapture to No.%d\tDisplay from No.%d\n", wp, rp);
59 }
PendingCapture(void)60 static void PendingCapture(void)
61 {
62     wp_pending = TRUE;
63 }
64 
65 // Buffer storing photographed/filmed images
66 static u16 shoot_buffer[WIDTH*HEIGHT] ATTRIBUTE_ALIGN(32);
67 static int shoot_flag = 0;
68 
69 static CAMERASelect current_camera = CAMERA_SELECT_IN;
70 
71 //--------------------------------------------------------------------------------
72 //    V-Blank interrupt process
73 //
VBlankIntr(void)74 void VBlankIntr(void)
75 {
76     OS_SetIrqCheckFlag(OS_IE_V_BLANK);
77     if (wp == rp)
78     {
79         rp ^= 1;
80         MI_CpuCopyFast(buffer[rp], (void*)HW_LCDC_VRAM_A, BYTES_PER_LINE * HEIGHT);
81         DC_InvalidateRange(buffer[rp], BYTES_PER_LINE * HEIGHT);
82     }
83     if(shoot_flag == 1)
84     {
85         MI_CpuCopyFast(buffer[rp], (void*)shoot_buffer, BYTES_PER_LINE * HEIGHT);
86         shoot_flag = 2;
87     }
88 }
89 
90 //--------------------------------------------------------------------------------
91 //    Camera initialization (only the Init- and I2C-related initialization)
92 //
CameraInit(void)93 BOOL CameraInit(void)
94 {
95     CAMERAResult result;
96     result = CAMERA_Init();
97     if(result == CAMERA_RESULT_FATAL_ERROR)
98         OS_TPanic("CAMERA_Init was failed.");
99     if(result == CAMERA_RESULT_ILLEGAL_STATUS)
100         return FALSE;
101 
102     result = CAMERA_I2CEffect(current_camera, CAMERA_EFFECT_NONE);
103     if (result != CAMERA_RESULT_SUCCESS)
104     {
105         OS_TPrintf("CAMERA_I2CEffect was failed. (%d)\n", result);
106     }
107 
108     result = CAMERA_I2CActivate(current_camera);
109     if (result == CAMERA_RESULT_FATAL_ERROR)
110         OS_TPanic("CAMERA_I2CActivate was failed. (%d)\n", result);
111     if(result == CAMERA_RESULT_ILLEGAL_STATUS)
112         return FALSE;
113     stabilizedCount = 0;
114 
115     return TRUE;
116 }
117 
118 //--------------------------------------------------------------------------------
119 //    Camera interrupt process (occurs both when there is an error and for Vsync)
120 //
121 #define PRINT_RATE  32
CameraIntrError(CAMERAResult result)122 void CameraIntrError(CAMERAResult result)
123 {
124 #pragma unused(result)
125     OS_TPrintf("Error was occurred.\n");
126     // Camera stop processing
127     CAMERA_StopCapture();
128     MI_StopNDma(NDMA_NO);
129     CAMERA_ClearBuffer();
130     wp_pending = TRUE;      // Also use same frame next time
131     CAMERA_DmaRecvAsync(NDMA_NO, buffer[wp], CAMERA_GetBytesAtOnce(WIDTH), CAMERA_GET_FRAME_BYTES(WIDTH, HEIGHT), CameraDmaRecvIntr, NULL);
132     CAMERA_StartCapture();
133 }
134 
CameraIntrReboot(CAMERAResult result)135 void CameraIntrReboot(CAMERAResult result)
136 {
137     if(result == CAMERA_RESULT_FATAL_ERROR)
138     {
139         return; // Restore was not possible, even after restarting camera
140     }
141     CameraIntrError(result); // DMA synchronization might have drifted, so realign
142 }
143 
CameraIntrVsync(CAMERAResult result)144 void CameraIntrVsync(CAMERAResult result)
145 {
146 #pragma unused(result)
147     if(stabilizedCount <= 30)
148         stabilizedCount++;
149     if(switchFlag)
150     {
151         current_camera = (current_camera == CAMERA_SELECT_IN ? CAMERA_SELECT_OUT : CAMERA_SELECT_IN);
152         result = CAMERA_I2CActivate(current_camera);
153         if(result == CAMERA_RESULT_FATAL_ERROR)
154             OS_Panic("CAMERA FATAL ERROR\n");
155         stabilizedCount = 0;
156         switchFlag = FALSE;
157     }
158 }
159 
CameraDmaRecvIntr(void * arg)160 void CameraDmaRecvIntr(void* arg)
161 {
162 #pragma unused(arg)
163     MI_StopNDma(NDMA_NO);
164 
165     if (CAMERA_IsBusy() == TRUE)
166     {
167         OS_TPrintf(".");
168         if (MI_IsNDmaBusy(NDMA_NO)) // Check whether image transfer is complete
169         {
170             OS_TPrintf("DMA was not done until VBlank.\n");
171             MI_StopNDma(NDMA_NO);
172         }
173         // Start the next frame capture
174         if (wp_pending)
175         {
176             wp_pending = FALSE;
177         }
178         else
179         {
180             // Capture results are not displayed on screen until camera is stable
181             // This demo waits the minimum of four camera frames required to avoid chromatic aberration, but if you want to wait until auto-exposure is stable, you need to wait 14 frames for an indoor shot or 30 for an outdoor one, as indicated in the Function Reference.
182             //
183             if(stabilizedCount > 4)
184             {
185                 wp ^= 1;
186             }
187         }
188         CAMERA_DmaRecvAsync(NDMA_NO, buffer[wp], CAMERA_GetBytesAtOnce(WIDTH), CAMERA_GET_FRAME_BYTES(WIDTH, HEIGHT), CameraDmaRecvIntr, NULL);
189     }
190 
191     {
192         static OSTick begin = 0;
193         static int count = 0;
194         if (begin == 0)
195         {
196             begin = OS_GetTick();
197         }
198         else if (++count == PRINT_RATE)
199         {
200             OSTick uspf = OS_TicksToMicroSeconds(OS_GetTick() - begin) / count;
201             int mfps = (int)(1000000000LL / uspf);
202             OS_TPrintf("%2d.%03d fps\n", mfps / 1000, mfps % 1000);
203             count = 0;
204             begin = OS_GetTick();
205         }
206     }
207 }
208 
TwlMain(void)209 void TwlMain(void)
210 {
211     int     vram_slot = 0, count = 0;
212     CAMERAResult result;
213 
214     //---------------------------------------------------------------------------
215     // Initialize:
216     // Enable IRQ interrupts and initialize VRAM
217     //---------------------------------------------------------------------------
218     DEMOInitCommon();
219     DEMOInitVRAM();
220 
221     // DMA is not used in GX (the old DMA conflicts with camera DMA)
222     (void)GX_SetDefaultDMA(GX_DMA_NOT_USE);
223 
224     GX_SetBankForSubBG(GX_VRAM_SUB_BG_128_C);
225 
226     GXS_SetGraphicsMode(GX_BGMODE_3);
227 
228     GXS_SetVisiblePlane(GX_PLANEMASK_BG3);
229     G2S_SetBG3Priority(0);
230     G2S_BG3Mosaic(FALSE);
231 
232     G2S_SetBG3ControlDCBmp(GX_BG_SCRSIZE_DCBMP_256x256, GX_BG_AREAOVER_XLU, GX_BG_BMPSCRBASE_0x00000);
233 
234     MI_CpuClearFast(shoot_buffer, WIDTH*HEIGHT*sizeof(u16));
235     GXS_LoadBG3Bmp(shoot_buffer, 0, WIDTH*HEIGHT*sizeof(u16));
236 
237     GXS_DispOn();
238 
239     // Initialization
240     OS_InitThread();
241     OS_InitTick();
242     OS_InitAlarm();
243     MI_InitNDmaConfig();
244     FS_Init( FS_DMA_NOT_USE );
245 
246     // V-Blank interrupt settings
247     OS_SetIrqFunction(OS_IE_V_BLANK, VBlankIntr);
248     (void)OS_EnableIrqMask(OS_IE_V_BLANK);
249     (void)OS_EnableIrq();
250     (void)GX_VBlankIntr(TRUE);
251     (void)OS_EnableInterrupts();
252 
253     // VRAM display mode
254     GX_SetBankForLCDC(GX_VRAM_LCDC_A);
255     MI_CpuClearFast((void*)HW_LCDC_VRAM_A, BYTES_PER_LINE * HEIGHT);
256     wp = 0;
257     rp = 1;
258     wp_pending = TRUE;
259     stabilizedCount = 0;
260     switchFlag = FALSE;
261     GX_SetGraphicsMode(GX_DISPMODE_VRAM_A, GX_BGMODE_0, GX_BG0_AS_2D);
262     OS_WaitVBlankIntr();
263     GX_DispOn();
264 
265     // Initialize camera
266     (void)CameraInit();
267 
268     // Configure DMA interrupt
269     (void)OS_EnableIrqMask(OS_IE_NDMA1);
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_SetTrimmingParams(0, 0, WIDTH, HEIGHT);
281     CAMERA_SetTrimming(TRUE);
282     CAMERA_SetOutputFormat(CAMERA_OUTPUT_RGB);
283     CAMERA_SetTransferLines(CAMERA_GET_MAX_LINES(WIDTH));
284 
285     // Start capturing
286     CAMERA_DmaRecvAsync(NDMA_NO, buffer[wp], CAMERA_GetBytesAtOnce(WIDTH), CAMERA_GET_FRAME_BYTES(WIDTH, HEIGHT), CameraDmaRecvIntr, NULL);
287     CAMERA_ClearBuffer();
288     CAMERA_StartCapture(); // The CAMERA_IsBusy function will immediately return TRUE because it is being called during a camera VSYNC
289     OS_TPrintf("Camera is shooting a movie...\n");
290 
291     DEMOStartDisplay();
292 
293     // Initialize the DSP shutter sound
294     {
295         FSFile  file[1];
296         int     slotB;
297         int     slotC;
298         // In this sample, all of the WRAM is allocated for the DSP, but for actual use, you would only need as many slots as were necessary
299         //
300         (void)MI_FreeWram_B(MI_WRAM_ARM9);
301         (void)MI_CancelWram_B(MI_WRAM_ARM9);
302         (void)MI_FreeWram_C(MI_WRAM_ARM9);
303         (void)MI_CancelWram_C(MI_WRAM_ARM9);
304         slotB = 0xFF;
305         slotC = 0xFF;
306         // For simplification, this sample uses files in static memory
307         FS_InitFile(file);
308         DSPi_OpenStaticComponentG711Core(file);
309         if (!DSP_LoadG711(file, slotB, slotC))
310         {
311             OS_TPanic("failed to load G.711 DSP-component! (lack of WRAM-B/C)");
312         }
313         (void)FS_CloseFile(file);
314 
315         // Initialize extended sound features
316         SNDEX_Init();
317 
318         // Load the shutter sound
319         {
320             FSFile file[1];
321             SNDEXFrequency freq;
322 
323             if(SNDEX_GetI2SFrequency(&freq) != SNDEX_RESULT_SUCCESS)
324             {
325                 OS_Panic("failed SNDEX_GetI2SFrequency");
326             }
327             // The initial I2S operating frequency should be 32.73 kHz
328             if(freq != SNDEX_FREQUENCY_32730)
329             {
330                 OS_Panic("default value is SNDEX_FREQUENCY_32730");
331             }
332 
333             FS_InitFile(file);
334             // Load the 32.73-kHz shutter sound
335             if( !FS_OpenFileEx(file, filename1, FS_FILEMODE_R) )
336             {
337                 OS_Panic("failed FS_OpenFileEx");
338             }
339             len = FS_GetFileLength(file);
340             OS_TPrintf("len = %d\n", len);
341             if( FS_ReadFile(file, StrmBuf, (s32)len) == -1)
342             {
343                 OS_Panic("failed FS_ReadFile");
344             }
345             (void)FS_CloseFile(file);
346             DC_StoreRange(StrmBuf, len);
347         }
348     }
349 
350     /* Initialize sound */
351     SND_Init();
352     SND_AssignWaveArc((SNDBankData*)sound_bank_data, 0, (SNDWaveArc*)sound_wave_data);
353     SND_StartSeq(0, sound_seq_data, 0, (SNDBankData*)sound_bank_data);
354 
355     while (1)
356     {
357         // Reading pad information and controls
358         DEMOReadKey();
359 
360         if (PAD_DetectFold() == TRUE)
361         {
362             // Wait until the shutter sound is done if it is playing
363             while(DSP_IsShutterSoundPlaying())
364             {
365                 OS_Sleep(100);
366             }
367             // Stop the DSP before sleeping
368             DSP_UnloadG711();
369 
370             // Camera stop processing
371             CAMERA_StopCapture();
372             MI_StopNDma(NDMA_NO);
373             result = CAMERA_I2CActivate(CAMERA_SELECT_NONE);
374             if(result == CAMERA_RESULT_FATAL_ERROR)
375                 OS_Panic("CAMERA FATAL ERROR\n");
376             wp_pending = TRUE;      // Also use same frame next time
377             CAMERA_DmaRecvAsync(NDMA_NO, buffer[wp], CAMERA_GetBytesAtOnce(WIDTH), CAMERA_GET_FRAME_BYTES(WIDTH, HEIGHT), CameraDmaRecvIntr, NULL);
378             CAMERA_ClearBuffer();
379             CAMERA_StartCapture();
380 
381             PM_GoSleepMode(PM_TRIGGER_COVER_OPEN | PM_TRIGGER_CARD, 0, 0);
382 
383             // Restart DSP after recovering from sleep
384             {
385                 FSFile  file[1];
386                 int     slotB;
387                 int     slotC;
388 
389                 slotB = 0xFF;
390                 slotC = 0xFF;
391                 // For simplification, this sample uses files in static memory
392                 FS_InitFile(file);
393                 DSPi_OpenStaticComponentG711Core(file);
394                 if (!DSP_LoadG711(file, slotB, slotC))
395                 {
396                     OS_TPanic("failed to load G.711 DSP-component! (lack of WRAM-B/C)");
397                 }
398                 (void)FS_CloseFile(file);
399             }
400             // Because the camera is also in standby, make it active
401             result = CAMERA_I2CActivate(current_camera);
402             if(result == CAMERA_RESULT_FATAL_ERROR)
403                 OS_Panic("CAMERA FATAL ERROR\n");
404             stabilizedCount = 0;
405         }
406 
407         if(DEMO_IS_TRIG(PAD_BUTTON_A) && (shoot_flag == 0))
408         {
409             while(DSP_PlayShutterSound(StrmBuf, len) == FALSE)
410             {
411             }
412             // When taking still photos, temporarily turn the outer camera LED OFF
413             if(current_camera == CAMERA_SELECT_OUT)
414             {
415                 if(CAMERA_SwitchOffLED() != CAMERA_RESULT_SUCCESS)
416                     OS_TPanic("CAMERA_SwitchOffLED was failed.\n");
417             }
418             OS_Sleep(200);
419             shoot_flag = 1;
420         }
421 
422         if(DEMO_IS_TRIG(PAD_BUTTON_X))
423         {
424             switchFlag = TRUE;
425         }
426 
427         OS_WaitVBlankIntr();
428 
429         if(shoot_flag == 2)
430         {
431             GXS_LoadBG3Bmp((void*)((int)shoot_buffer), 0, BYTES_PER_LINE * HEIGHT);
432             shoot_flag = 0;
433         }
434 
435         // Main sound processing
436         while (SND_RecvCommandReply(SND_COMMAND_NOBLOCK) != NULL)
437         {
438         }
439         (void)SND_FlushCommand(SND_COMMAND_NOBLOCK);
440     }
441 }
442