bsptemplate/asspandvariant/template_variant/camerasc/camerasc_sensor.cpp
changeset 247 d8d70de2bd36
parent 201 43365a9b78a3
child 250 ac18961ed598
child 259 57b9594f5772
--- a/bsptemplate/asspandvariant/template_variant/camerasc/camerasc_sensor.cpp	Tue Jul 06 15:50:07 2010 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,552 +0,0 @@
-// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
-// All rights reserved.
-// This component and the accompanying materials are made available
-// under the terms of the License "Eclipse Public License v1.0"
-// which accompanies this distribution, and is available
-// at the URL "http://www.eclipse.org/legal/epl-v10.html".
-//
-// Initial Contributors:
-// Nokia Corporation - initial contribution.
-//
-// Contributors:
-//
-// Description:
-// template\template_variant\camerasc\camerasc_sensor.cpp
-// Implementation of the template shared chunk camera physical device driver (PDD).
-// This file is part of the Template Base port
-// 
-//
-
-/**
- @file
-*/
-
-#include "camerasc_plat.h"
-#include <kernel/cache.h>
-
-// XXX - Temporary structure containing a logo to be displayed.  Remove this when
-//       changing this template into a "real" camera driver
-#include "logoyuv2.cpp"
-
-
-#define RGBtoBGR565(red, green, blue) (((blue & 0xf8) << 8) | ((green & 0xfc) << 3) | ((red & 0xf8) >> 3));
-
-#define YUVtoYUV565(luma, blueC, redC) (((luma & 0xf8) << 8) | ((blueC & 0xfc) << 3) | ((redC & 0xf8) >> 3));
-
-// Frame sizes and their associated frame rates supported by the Template sensor.  This selection was
-// obtained by observation of typical formats supported by phones already on the market;  It is arbitrary
-// and can be easily added to if desired
-static const SDevCamFrameSize FrameSizes[] =
-	{
-		{ 320, 240, 1, 30 }	,		// QVGA - 0.075 MP
-		// XXX: Although not used in this template driver, the following are suggested standard frame sizes
-		// that should be implemented in your camera driver, as well as 320 x 240 above.  Remember to change
-		// KNumFrameSizes below if you change the number of sizes defined in here!
-		{ 640, 480, 1, 30 },		// VGA - 0.3 MP
-		{ 800, 600, 1, 30 },		// SVGA - 0.5 MP
-		{ 1024, 768, 1, 30 },		// XGA - 0.8 MP
-		{ 2048, 1536, 1, 15 },	// QXGA - 3 MP
-		//{ 2560, 1600, 1, 30 }		// WQXGA - 4.1 MP
-	};
-
-// This constant must be updated if the number of frame sizes listed above changes
-static const TInt KNumFrameSizes = sizeof(FrameSizes) / sizeof(SDevCamFrameSize);
-
-// Pixel formats supported by the three different capture modes.  These are mapped onto the appropriate
-// array of supported frame rates by the FrameSizeCaps() function
-static const SDevCamPixelFormat PixelFormats[] =
-	{
-		// Image pixel formats
-		{ EUidPixelFormatYUV_422Interleaved, KNumFrameSizes, 2 },
-		
-		// Video pixel formats
-		{ EUidPixelFormatYUV_422Interleaved, KNumFrameSizes, 2 },
-
-		// View finder pixel formats
-		{ EUidPixelFormatYUV_422Interleaved, KNumFrameSizes, 2 }
-
-	};
-
-// These constants must be updated if the number of pixel formats listed above changes
-static const TInt KNumImagePixelFormats = 1;
-static const TInt KNumVideoPixelFormats = 1;
-static const TInt KNumViewFinderPixelFormats = 1;
-
-// Alternate logo images after this many frames
-static const TInt KAlternateLogoFrameInterval = 5;
-
-static void ImageTimerCallback(TAny* aSensorIf)
-	{
-	DTemplateSensorIf* sensor = (DTemplateSensorIf*) aSensorIf;
-
-	// XXX - Call the buffer done function in the sensor class.  In this case we are just emulating the
-	// interrupt and DFC callback that would happen when an image is captured, so we always pass in KErrNone.
-	// In a real driver, we would read the hardware here to check that the capture happened successfully and
-	// would pass in the appropriate error code
-	sensor->BufferDoneCallback(KErrNone);
-	}
-
-/**
-Saves a configuration specifying such details as dimensions and pixel format in which the sensor should
-capture images.
-@param	aConfig	A TCameraConfigV02 structure containing the settings to be used.
-@return	KErrNone if successful, otherwise one of the other system wide error codes.
-*/
-TInt DSensorIf::SetConfig(const TCameraConfigV02& aConfig)
-	{
-	// Manual settings for flash mode, focus, white balance etc. are not supported by the sensor,
-	// so check for these and return KErrNotSupported if they have been requested
-	if ((aConfig.iFlashMode != ECamFlashNone) ||
-		(aConfig.iExposureMode != ECamExposureAuto) ||
-		(aConfig.iZoom != 0) /*||
-        (aConfig.iWhiteBalanceMode != ECamWBAuto) ||
-		(aConfig.iContrast != ECamContrastAuto) ||
-		(aConfig.iBrightness != ECamBrightnessAuto)*/)
-		{
-		// XXX: Remove this once support is addded for these modes
-		return KErrNotSupported;
-		}
-
-	// As well as saving the configuration, also save copies of the width and height for easy access,
-	// as they are accessed frequently, as well as the offset in bytes between lines
-	iConfig = aConfig;
-	iWidth = aConfig.iFrameSize.iWidth;
-	iHeight = aConfig.iFrameSize.iHeight;
-	iLineOffset = (iWidth * iConfig.iPixelFormat.iPixelWidthInBytes);
-
-	return KErrNone;
-	}
-
-/**
-Constructor for the Template sensor class.
-*/
-
-DTemplateSensorIf::DTemplateSensorIf(MSensorObserver& aObserver, TDfcQue* aDFCQueue)
-	: iDFCQueue(aDFCQueue)
-	{
-	iObserver = &aObserver;
-	iXDirection = iYDirection = 1;
-	
-	iCounter = 0;
-	iFlipSwitch = EFalse;
-	}
-
-/**
-Second stage constructor for the Template sensor class.
-
-@return KErrNone if successful, otherwise one of the other system wide error codes.
-*/
-TInt DTemplateSensorIf::DoCreate()
-	{
-	__KTRACE_CAM(Kern::Printf("> DTemplateSensorIf::DoCreate()"));
-
-	TInt r = KErrNone;
-
-	for (TInt index = 0; index < KTotalCameraRequests; ++index)
-		{
-		if ((iImageTimerDFCs[index] = new TDfc(ImageTimerCallback, this, iDFCQueue, 0)) == NULL)
-			{
-			r = KErrNoMemory;
-
-			break;
-			}
-		}
-
-	__KTRACE_CAM(Kern::Printf("< DTemplateSensorIf::DoCreate() => Returning %d", r));
-
-	return r;
-	}
-
-/**
-Destructor for the Template sensor class.
-*/
-DTemplateSensorIf::~DTemplateSensorIf()
-	{
-	for (TInt index = 0; index < KTotalCameraRequests; ++index)
-		{
-		iImageTimers[index].Cancel();
-		delete iImageTimerDFCs[index];
-		}
-	}
-
-/**
-Called by the underlying sensor class when an image has been captured.
-@param aResult	KErrNone if the image was captured successfully, otherwise one of
-				the other system wide error codes.
-@return KErrNone if successful, otherwise one of the other system wide error codes.
-*/
-TInt DTemplateSensorIf::BufferDoneCallback(TInt aResult)
-	{
-	TInt r = KErrNone;
-
-	NKern::LockedDec(iPendingRequests);
-
-	TLinAddr linAddr;
-	TPhysAddr physAddr;
-
-	// Call the LDD to let it know that an image capture has completed.  If the LDD needs more images
-	// to be captured, then it will return KErrNone and the virtual and physical addresses of the
-	// next buffer to be filled will be returned in linAddr and physAddr respectively.  Note that as
-	// will as starting a capture of an image in here, the LDD may also call CaptureNextImage() to start
-	// capture as well
-	r = iObserver->NotifyImageCaptureEvent(aResult, linAddr, physAddr);
-
-	if (r == KErrNone)
-		{
-		iNextRequest = ((iNextRequest + 1) % KTotalCameraRequests);
-		NKern::LockedInc(iPendingRequests);
-
-		// XXX: Temporary code to be removed in a real driver.  Fill the buffer for testing
-		//      with user side code
-		FillBuffer(linAddr);
-
-		// XXX: Send buffer to sensor.  Normally the address of the buffer passed in in aLinAddr and
-		//      aPhysAddr would be programmed into the sensor and/or bus hardware here and an interrupt
-		//      would be generated when the iamge had been captured into the buffer.  In this simulated
-		//      driver we will use a nanokernel timer to simulate this process
-		iImageTimers[iNextRequest].OneShot(iImageTimerTicks, *iImageTimerDFCs[iNextRequest]);
-		}
-
-	return r;
-	}
-
-/**
-Fills a buffer with a white background with a moving logo on top.
-@param aBuffer	Pointer to the buffer to be filled.
-*/
-void DTemplateSensorIf::FillBuffer(TLinAddr aBuffer)
-	{
-	const TUint8* LogoData = Logo.iPixelData;
-	const TUint8* LogoData2 = Logo.iPixelData2;
-	TInt index = 0;
-	TInt numPixels = (iConfig.iFrameSize.iWidth * iConfig.iFrameSize.iHeight);
-	TUint yC, uC, vC;
-	TUint16* buffer = (TUint16*) aBuffer;
-
-    // Alternate between the two logos for cheesy animation effect
-    if( ++iCounter == KAlternateLogoFrameInterval )
-         {
-         iFlipSwitch ^= 1;
-         iCounter = 0;
-         }
-	
-	
-	// Set the "photo" background to be all white
-	memset(buffer, 0xff, (numPixels * 2));
-
-	// Point to the correct location in the buffer at which to render the logo
-	buffer += ((iY * iConfig.iFrameSize.iWidth) + iX);
-
-	// Iterate through the data for the logo and copy it into the "photo"
-	for (TUint y = 0; y < Logo.iHeight; ++y)
-		{
-		for (TUint x = 0; x < Logo.iWidth; ++x)
-			{
-			// The logo is in 24 bit BGR format so read each pixel and convert it to 16 bit BGR565
-			// before writing it into the "photo" buffer
-			if( iFlipSwitch )
-			    {
-                yC = LogoData[index];
-                uC = LogoData[index + 1];
-                vC = LogoData[index + 2];
-			    }
-			else
-                {
-                yC = LogoData2[index];
-                uC = LogoData2[index + 1];
-                vC = LogoData2[index + 2];
-                }
-
-			*buffer++ = YUVtoYUV565(yC, uC, vC);
-			// Point to the next source pixel
-			index += 3;
-			}
-
-			// Point to the start of the next line in the buffer, taking into account that the logo
-			// is narrower than the buffer
-			buffer += (iConfig.iFrameSize.iWidth - Logo.iWidth);
-		}
-
-	// Bounce the logo around in the X direction.  This will take effect the next time this is called
-	iX += iXDirection;
-
-	if (iX <= 0)
-		{
-		iX = 0;
-		iXDirection = -iXDirection;
-		}
-	else if (iX >= (TInt) (iConfig.iFrameSize.iWidth - Logo.iWidth))
-		{
-		iX = (iConfig.iFrameSize.iWidth - Logo.iWidth);
-		iXDirection = -iXDirection;
-		}
-
-	// Bounce the logo around in the Y direction.  This will take effect the next time this is called
-	iY += iYDirection;
-
-	if (iY <= 0)
-		{
-		iY = 0;
-		iYDirection = -iYDirection;
-		}
-	else if (iY >= (TInt) (iConfig.iFrameSize.iHeight - Logo.iHeight))
-		{
-		iY = (iConfig.iFrameSize.iHeight - Logo.iHeight);
-		iYDirection = -iYDirection;
-		}
-
-	// Now flush the cache to memory, taking into account the size of each pixel.  This is not normally
-	// necessary but given that we are emulating a camera driver in software we must ensure that the
-	// cache is flushed to memory.  This is because in a real driver the buffer will have been filled
-	// by DMA so upon return to the LDD, the LDD will discard the contents of the cache to ensure the
-	// DMA-written data is ok.  In the case of filling the buffer using the CPU in this virtual camera
-	// driver, that would result in the data being discarded!
-	Cache::SyncMemoryBeforeDmaWrite((TLinAddr) aBuffer, (numPixels * iConfig.iPixelFormat.iPixelWidthInBytes));
-	}
-
-/**
-Based on the capture mode and pixel format passed in, copies an array of supported SFrameSize
-structures into a buffer supplied by the LDD.  These frame sizes and their associated frame rates
-will reflect the capabilities of the given capture mode and pixel format.
-@param aCaptureMode			The capture mode for which to obtain the supported frame sizes.
-@param aUidPixelFormat		The UID of the pixel format (as defined in \epoc32\include\pixelformats.h)
-							for which to obtain the supported frame sizes.
-@param aFrameSizeCapsBuf	A reference to a descriptor that contains a buffer into which to place
-							the frame size structures.  It is up to the LDD to ensure that this is
-							large enough to hold all of the frame sizes.
-@return Always KErrNone.
-*/
-TInt DTemplateSensorIf::FrameSizeCaps(TDevCamCaptureMode /*aCaptureMode*/, TUidPixelFormat /*aUidPixelFormat*/, TDes8& aFrameSizeCapsBuf)
-	{
-	TPtrC8 sourceFrameSizes((const TUint8*) FrameSizes, sizeof(FrameSizes));
-
-	// Ensure the buffer passed in from the LDD is large enough and copy the requested frame sizes
-	if (aFrameSizeCapsBuf.Size() < sourceFrameSizes.Size())
-		{
-		Kern::Printf("*** ECapsBufferTooSmall: %d vs %d",
-				aFrameSizeCapsBuf.Size(),
-				sourceFrameSizes.Size());
-		Kern::Fault("camerasc", ECapsBufferTooSmall);
-		}
-	
-	//__ASSERT_DEBUG((aFrameSizeCapsBuf.Size() >= sourceFrameSizes.Size()), Kern::Fault("camerasc", ECapsBufferTooSmall));
-	aFrameSizeCapsBuf = sourceFrameSizes;
-
-	return KErrNone;
-	}
-
-/**
-Allocates a buffer large enough to hold the TCameraCapsV02 structure and its succeeding array of
-pixel formats, and populates the structure and array with information about the capabilities of
-the sensor.
-@param aCameraCaps	Reference to a pointer into which to place the pointer to allocated buffer
-@return	Size of the capabilities structure if successful, otherwise one of the other system wide
-		error codes.
-*/
-TInt DTemplateSensorIf::GetCaps(TCameraCapsV02*& aCameraCaps)
-	{
-	// Allocate a buffer large enough to hold the TCameraCapsV02 structure and the array of pixel formats
-	// that will follow it
-	TInt r = (sizeof(TCameraCapsV02) + sizeof(PixelFormats));
-	TUint8* capsBuffer = new TUint8[r];
-
-	if (capsBuffer)
-		{
-		aCameraCaps = (TCameraCapsV02*) capsBuffer;
-
-		// No special modes are supported at the moment
-		aCameraCaps->iFlashModes = ECamFlashNone;
-		aCameraCaps->iExposureModes = ECamExposureAuto; // or None?
-		// do we still need whitebalance mode filed?
-		aCameraCaps->iWhiteBalanceModes = ECamWBAuto | ECamWBDaylight | ECamWBCloudy | ECamWBTungsten | ECamWBFluorescent | ECamWBFlash | ECamWBSnow | ECamWBBeach;
-		aCameraCaps->iMinZoom = 0;
-		aCameraCaps->iMaxZoom = 0;
-		aCameraCaps->iCapsMisc = KCamMiscContrast | KCamMiscBrightness | KCamMiscColorEffect;
-
-		// There isn't really such thing as inwards or outwards orientation on an SDP, but we'll pretend it's
-		// an outwards facing camera
-		aCameraCaps->iOrientation = ECamOrientationOutwards;
-
-		// Initialise the number of different pixel formats supported
-		aCameraCaps->iNumImagePixelFormats = KNumImagePixelFormats;
-		aCameraCaps->iNumVideoPixelFormats = KNumVideoPixelFormats;
-		aCameraCaps->iNumViewFinderPixelFormats = KNumViewFinderPixelFormats;
-
-		for (TInt i = 0; i < ECamAttributeMax; i++)
-		    {
-		    if (ECamAttributeColorEffect == (TDevCamDynamicAttribute)(i))
-		        {
-		        // WhiteBalance
-		        // In case of white balance, we shouldn't use MIN and MAX values as some of them in between MIN and MAX can be missed out.
-		        // As this is fake driver, There doesn't seem to be any major issue though.
-		        aCameraCaps->iDynamicRange[i].iMin = ECamWBAuto;
-		        aCameraCaps->iDynamicRange[i].iMax = ECamWBBeach;
-		        aCameraCaps->iDynamicRange[i].iDefault = ECamWBAuto;
-		        }
-		    else
-		        {    
-		        // TBC :: Contrast, Brightness
-		        aCameraCaps->iDynamicRange[i].iMin = 0;
-		        aCameraCaps->iDynamicRange[i].iMax = 6;
-		        aCameraCaps->iDynamicRange[i].iDefault = 3;
-		        }
-		    }
-
-		// Setup some descriptors pointing to the pixel format array and the array passed in by the LDD
-		// (located at the end of the TCameraCapsV02 structure) and copy the pixel format array
-		TPtrC8 sourcePixelFormats((const TUint8*) PixelFormats, sizeof(PixelFormats));
-		TPtr8 destPixelFormats((capsBuffer + sizeof(TCameraCapsV02)), sizeof(PixelFormats), sizeof(PixelFormats));
-		destPixelFormats = sourcePixelFormats;
-		}
-	else
-		{
-		r = KErrNoMemory;
-		}
-
-	return r;
-	}
-
-/**
-Powers up the sensor hardware.
-@return KErrNone if successful, otherwise one of the other system wide error codes.
-*/
-TInt DTemplateSensorIf::RequestPower()
-	{
-	__KTRACE_CAM(Kern::Printf("> DTemplateSensorIf::RequestPower()"));
-
-	TInt r = KErrNone;
-
-	__KTRACE_CAM(Kern::Printf("< DTemplateSensorIf::RequestPower() => Returning %d", r));
-
-	return r;
-	}
-
-/**
-Powers down the sensor hardware.
-@return KErrNone if successful, otherwise one of the other system wide error codes.
-*/
-TInt DTemplateSensorIf::RelinquishPower()
-	{
-	__KTRACE_CAM(Kern::Printf("> DTemplateSensorIf::RelinquishPower()"));
-
-	TInt r = KErrNone;
-
-	__KTRACE_CAM(Kern::Printf("< DTemplateSensorIf::RelinquishPower() => Returning %d", r));
-
-	return r;
-	}
-
-/**
-Begins capture of the next image into the buffer provided.  This function assumes that
-Start() has already been called to start capture.  However, Stop() may also have been
-subsequently called (for example to pause capture) and in this case, this function will
-handle restarting the sensor.
-@param aLinAddr		A virtual pointer to the buffer into which to capture the image.
-@param aPhysAddr	A physical pointer to the buffer into which to capture the image.
-					This points to the same memory as aLinAddr.
-@return KErrNone if successful.
-		KErrNotReady if there are no free requests to capture the image.
-		Otherwise one of the other system wide error codes.
-*/
-TInt DTemplateSensorIf::CaptureNextImage(TLinAddr aLinAddr, TPhysAddr /*aPhysAddr*/)
-	{
-	TInt r = KErrNone;
-
-	// Only start capturing the next image if there are any pending request slots available
-	if (iPendingRequests < KTotalCameraRequests)
-		{
-		// Queue a transfer on the next available channel and indicate that the channel is
-		// in use
-		iNextRequest = ((iNextRequest + 1) % KTotalCameraRequests);
-		NKern::LockedInc(iPendingRequests);
-
-		// XXX: Temporary code to be removed in a real driver.  Fill the buffer for testing
-		//      with user side code.  This is to simulate an image being captured into the buffer that
-		//      has been passed in in aLinAddr.  As well as aLinAddr, which points to the virtual
-		//      address of the buffer, the LDD will pass in the physical address as well, in aPhysAddr.
-		//      Depending on the underlying sensor hardware and/or bus in use, you will have to choose
-		//      which of these to use
-		FillBuffer(aLinAddr);
-
-		// XXX: Send buffer to sensor.  Normally the address of the buffer passed in in aLinAddr and
-		//      aPhysAddr would be programmed into the sensor and/or bus hardware here and an interrupt
-		//      would be generated when the iamge had been captured into the buffer.  In this simulated
-		//      driver we will use a nanokernel timer to simulate this process
-		iImageTimers[iNextRequest].OneShot(iImageTimerTicks, *iImageTimerDFCs[iNextRequest]);
-
-		// If capturing has not yet started or has been paused by Stop(), start it
-		if (!(iEnabled))
-			{
-			iEnabled = ETrue;
-			}
-		}
-	else
-		{
-		r = KErrNotReady;
-		}
-
-	return r;
-	}
-
-/**
-Begins capture of the first image into the buffer provided.  This function is similar to
-CaptureNextImage(), except that it will perform any extra sensor intitialisation required
-to start capture.
-@param aCaptureMode	The capture mode for which to start capturing.
-@param aLinAddr		A virtual pointer to the buffer into which to capture the image.
-@param aPhysAddr	A physical pointer to the buffer into which to capture the image.
-					This points to the same memory as aLinAddr.
-@return KErrNone if successful
-		KErrInUse if capture is already under way.
-		KErrNotSupported if the frame size and/or frame rate are out of range.
-		Otherwise one of the other system wide error codes.
-*/
-TInt DTemplateSensorIf::Start(TDevCamCaptureMode /*aCaptureMode*/, TLinAddr aLinAddr, TPhysAddr aPhysAddr)
-	{
-	__KTRACE_CAM(Kern::Printf("> DTemplateSensorIf::Start()"));
-
-	TInt r = KErrNone;
-
-	// XXX - In a real camera driver, in here we would initialise start the capturing process in here.
-	//       When an image is captured, the sensor hardware (or maybe the CSI bus) will generate an
-	//       which will then be enqueued into the DFC queue that was passed into the constructor of
-	//       the sensor class.  It is important to do the DFC processing in this DFC queue rather than
-	//       a separate one because it ensures that fucntions in the PDD and LDD are called in a serialised
-	//       manner, without the need for mutexts.  In this example camera driver we will convert the
-	//       framerate into a nanokernel tick count and will use an NTimer.OneShot() call to simulate
-	//       the sensor interrupt and DFC callback.  Divides are slow so we'll calculate the tick count
-	//       here and will save it for later use
-	iImageTimerTicks = ((1000000 / NKern::TickPeriod()) / iConfig.iFrameRate);
-
-	// XXX - Once the one off hardware initialisation has been done for starting a new capture, then
-	//       subsequent captures can usually reuse the same code in CaptureNextImage() for starting
-	//       the next capture
-	r = CaptureNextImage(aLinAddr, aPhysAddr);
-
-	__KTRACE_CAM(Kern::Printf("< DTemplateSensorIf::Start() => Returning %d", r));
-
-	return r;
-	}
-
-/**
-Stops capturing any image capture that is currently in progress.  This function will act
-more like a Pause() than a Stop() capturing can be restarted from where it was stopped.
-*/
-TInt DTemplateSensorIf::Stop()
-	{
-	__KTRACE_CAM(Kern::Printf("> DTemplateSensorIf::Stop()"));
-
-	iEnabled = EFalse;
-	iPendingRequests = iNextRequest = 0;
-
-	// XXX - Cancel all of our pending image timer callbacks.  In a real driver we would write to the
-	//       sensor and/or bus hardware here to cause them to cancel any pending image captures
-	for (TInt index = 0; index < KTotalCameraRequests; ++index)
-		{
-		iImageTimers[index].Cancel();
-		}
-
-	__KTRACE_CAM(Kern::Printf("< DTemplateSensorIf::Stop()"));
-
-	return KErrNone;
-	}