bsptemplate/asspandvariant/template_assp/gpio.cpp
author Simon Howkins <simonh@symbian.org>
Fri, 05 Mar 2010 15:41:00 +0000
branchRCL_3
changeset 73 9c2a3e4960cf
parent 0 a41df078684a
child 90 947f0dc9f7a8
permissions -rw-r--r--
Merge further Compiler Compatibility fixes onto RCL_3 branch.

/*
* Copyright (c) 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:
*
*/
#include <kernel/kern_priv.h>
#include <template_assp.h>
#include <drivers/gpio.h>

const TInt32		KHwGpioPinMax		= 0;	// TO DO: max pin number this GPIO chip supports
const TInt32		KIntIdGpio		= 0;	// TO DO: need to define which interrupt the GPIO chip is attached to

//
// TO DO: if the GPIO chip doesn't support specific features
// such as debouncing or pin modes, then it may be
// necessary to store them ourselves in an array of GpioPins
// other features such as pin bias or idle configurations
// may be left as KErrNotSupported
//
class GpioPin
	{
public:
   	TGpioIsr		iIsr;	// e.g. we may want to remeber the isr attached to a pin
	TAny *			iPtr;	// argument to pass to isr
	};

static GpioPin	GpioPins[KHwGpioPinMax+1];

static TInt32	GpioInterruptId; // place to store interrupt handle returned from Interrupt::Bind()

/**
GPIO interrupt handler
generic argument (TAny*) is a pointer to the GpioPins array
*/
void GpioIsrDispatch(TAny *aPtr)
	{
	// TO DO: work out which pins have interrupts pending
	// and dispatch the appropriate ISR
	GpioPin	*pins = (GpioPin *)aPtr;
	TUint32 interrupt = 0xff; // TO DO: read gpio pending interupts
	TUint32 enabled = 0x00; // TO DO: read gpio enabled interupts
	TUint32	masked = interrupt & enabled; // TO DO: read masked interrupts

	// check each pin and dispatch ISR if necessary
	for (TInt i = 0; i <= KHwGpioPinMax; i++)
		{
		if ((masked & 0x1) && (pins[i].iIsr != NULL))
			{
			// we have a pending interrupt and a registered ISR
			(*pins[i].iIsr)(pins[i].iPtr); // dispatch this pin's ISR
			}
		masked >>= 1;
		}
	Interrupt::Clear(GpioInterruptId);
	}


EXPORT_C TInt GPIO::SetPinMode
	(
	TInt      aId,
   	TGpioMode aMode
	)
	{
	if (aId < 0 || aId > KHwGpioPinMax)
		{
		return KErrArgument;
		}
	// TO DO: store pin mode and return
	return KErrNone;
	}

EXPORT_C TInt GPIO::GetPinMode
	(
	TInt        aId,
   	TGpioMode & aMode
	)
	{
	if (aId < 0 || aId > KHwGpioPinMax)
		{
		return KErrArgument;
		}
	// TO DO: set aMode = pin mode
	return KErrNone;
	}

EXPORT_C TInt GPIO::SetPinDirection
	(
	TInt           aId,
   	TGpioDirection aDirection
	)
	{
	if (aId < 0 || aId > KHwGpioPinMax || aDirection == ETriStated)
		{
		return KErrArgument;
		}
	// TO DO: if we support setting the pin direction then do it here
	return KErrNone;
	}

EXPORT_C TInt GPIO::GetPinDirection
	(
	TInt             aId,
   	TGpioDirection & aDirection
	)
	{
	if (aId < 0 || aId > KHwGpioPinMax)
		{
		return KErrArgument;
		}
	// TO DO: if we support getting the pin direction then do it here
	return KErrNone;
	}

EXPORT_C TInt GPIO::SetPinBias
	(
	TInt      aId,
   	TGpioBias aBias
	)
	{
	if (aId < 0 || aId > KHwGpioPinMax)
		{
		return KErrArgument;
		}
	// TO DO: if we support setting the pin bias then do it here
	return KErrNone;
	}

EXPORT_C TInt GPIO::GetPinBias
	(
	TInt        aId,
   	TGpioBias & aBias
	)
	{
	if (aId < 0 || aId > KHwGpioPinMax)
		{
		return KErrArgument;
		}
	// TO DO: if we support getting the pin bias then do it here
	return KErrNone;
	}

EXPORT_C TInt GPIO::SetPinIdleConfigurationAndState
	(
	TInt        aId,
   	TInt		/*aConf*/
	)
	{
	if (aId < 0 || aId > KHwGpioPinMax)
		{
		return KErrArgument;
		}
	// TO DO: if we support setting the pin idle config then do it here
	return KErrNone;
	}

EXPORT_C TInt GPIO::GetPinIdleConfigurationAndState
	(
	TInt        aId,
   	TInt	  & aBias
	)
	{
	if (aId < 0 || aId > KHwGpioPinMax)
		{
		return KErrArgument;
		}
	// TO DO: if we support getting the pin idle config then do it here
	return KErrNone;
	}

EXPORT_C TInt GPIO::BindInterrupt
	(
	TInt     aId,
   	TGpioIsr aIsr,
   	TAny *   aPtr
	)
	{
	if (aId < 0 || aId > KHwGpioPinMax || aIsr == NULL)
		{
		return KErrArgument;
		}
	if (GpioPins[aId].iIsr != NULL)
		{
		// already bound
		return KErrInUse;
		}
	// record isr and arg bound to this pin
	GpioPins[aId].iIsr = aIsr;
	GpioPins[aId].iPtr = aPtr;
	return KErrNone;
	}

EXPORT_C TInt GPIO::UnbindInterrupt
	(
	TInt aId
	)
	{
	if (aId < 0 || aId > KHwGpioPinMax)
		{
		return KErrArgument;
		}
	if (GpioPins[aId].iIsr == NULL)
		{
		// nothing bound
		return KErrGeneral;
		}
	// NULL isr bound to this pin
	GpioPins[aId].iIsr = NULL;
	GpioPins[aId].iPtr = NULL;
	return KErrNone;
	}

EXPORT_C TInt GPIO::EnableInterrupt
	(
	TInt aId
	)
	{
	if (aId < 0 || aId > KHwGpioPinMax)
		{
		return KErrArgument;
		}
	if (GpioPins[aId].iIsr == NULL)
		{
		// nothing bound
		return KErrGeneral;
		}
	// TODO: enable interrupts on this pin
	return KErrNone;
	}

EXPORT_C TInt GPIO::DisableInterrupt
	(
	TInt aId
	)
	{
	if (aId < 0 || aId > KHwGpioPinMax)
		{
		return KErrArgument;
		}
	if (GpioPins[aId].iIsr == NULL)
		{
		// nothing bound
		return KErrGeneral;
		}
	// TODO: disable interrupts on this pin
	return KErrNone;
	}

EXPORT_C TInt GPIO::IsInterruptEnabled
	(
	TInt    aId,
   	TBool & aEnable
	)
	{
	if (aId < 0 || aId > KHwGpioPinMax)
		{
		return KErrArgument;
		}
	if (GpioPins[aId].iIsr == NULL)
		{
		// nothing bound
		return KErrGeneral;
		}
	// TO DO: are interrupts enabled on this pin ?
	return KErrNone;
	}

EXPORT_C TInt GPIO::ClearInterrupt
	(
	TInt aId
	)
	{
	if (aId < 0 || aId > KHwGpioPinMax)
		{
		return KErrArgument;
		}
	if (GpioPins[aId].iIsr == NULL)
		{
		// nothing bound
		return KErrGeneral;
		}
	// TO DO: clear pin interrupt status
	return KErrNone;
	}

EXPORT_C TInt GPIO::GetMaskedInterruptState
	(
	TInt    aId,
   	TBool & aActive
	)
	{
	if (aId < 0 || aId > KHwGpioPinMax)
		{
		return KErrArgument;
		}
	// TO DO: set aActive to masked interrupt state
	return KErrNone;
	}

EXPORT_C TInt GPIO::GetRawInterruptState
	(
	TInt    aId,
   	TBool & aActive
	)
	{
	if (aId < 0 || aId > KHwGpioPinMax)
		{
		return KErrArgument;
		}
	// TO DO: set aActive to raw (unmasked) interrupt state
	return KErrNone;
	}

EXPORT_C TInt GPIO::SetInterruptTrigger
	(
	TInt                  aId,
   	TGpioDetectionTrigger aTrigger
	)
	{
	if (aId < 0 || aId > KHwGpioPinMax)
		{
		return KErrArgument;
		}
	// TO DO: set interrupt trigger on this pin
	return KErrNone;
	}

EXPORT_C TInt GPIO::EnableWakeup
	(
	TInt aId
	)
	{
	if (aId < 0 || aId > KHwGpioPinMax)
		{
		return KErrArgument;
		}
	// TO DO: enable wakeup on this pin
	return KErrNone;
	}

EXPORT_C TInt GPIO::DisableWakeup
	(
	TInt aId
	)
	{
	if (aId < 0 || aId > KHwGpioPinMax)
		{
		return KErrArgument;
		}
	// TO DO: disable wakeup on this pin
	return KErrNone;
	}

EXPORT_C TInt GPIO::IsWakeupEnabled
	(
	TInt    aId,
   	TBool & aEnable
	)
	{
	if (aId < 0 || aId > KHwGpioPinMax)
		{
		return KErrArgument;
		}
	// TO DO: set aEnable wakeup state for this pin
	return KErrNone;
	}

EXPORT_C TInt GPIO::SetWakeupTrigger
	(
	TInt                  aId,
   	TGpioDetectionTrigger aTrigger
	)
	{
	if (aId < 0 || aId > KHwGpioPinMax)
		{
		return KErrArgument;
		}
	// TO DO: set wakeup trigger on this pin
	return KErrNone;
	}

EXPORT_C TInt GPIO::SetDebounceTime
	(
	TInt aId,
   	TInt aTime
	)
	{
	if (aId < 0 || aId > KHwGpioPinMax)
		{
		return KErrArgument;
		}
	// TO DO: set debounce time for this pin
	// it may be necessary to emulate debouncing ourselves
	return KErrNone;
	}

EXPORT_C TInt GPIO::GetDebounceTime
	(
	TInt   aId,
   	TInt & aTime
	)
	{
	if (aId < 0 || aId > KHwGpioPinMax)
		{
		return KErrArgument;
		}
	// TO DO: get debounce time for this pin
	return KErrNone;
	}

EXPORT_C TInt GPIO::GetInputState
	(
	TInt         aId,
   	TGpioState & aState
	)
	{
	if (aId < 0 || aId > KHwGpioPinMax)
		{
		return KErrArgument;
		}
	// TO DO: read the input state of this pin
	// if debouncing is handled by the driver here
	// is where we will need to work out what the
	// debounced state is

	return KErrNone;
	}

EXPORT_C TInt GPIO::SetOutputState
	(
	TInt       aId,
   	TGpioState aState
	)
	{
	if (aId < 0 || aId > KHwGpioPinMax)
		{
		return KErrArgument;
		}
	// TO DO: set the output state of this pin
	return KErrNone;
	}

EXPORT_C TInt GPIO::GetOutputState
	(
	TInt         aId,
   	TGpioState & aState
	)
	{
	if (aId < 0 || aId > KHwGpioPinMax)
		{
		return KErrArgument;
		}
	// TO DO: get the output state of this pin
	return KErrNone;
	}

EXPORT_C TInt GPIO::GetInputState
	(
	TInt                  aId,
   	TGpioCallback		* aCb
	)
	{
	if (aId < 0 || aId > KHwGpioPinMax)
		{
		return KErrArgument;
		}
	// TO DO: get the input state of this pin
	return KErrNone;
	}

EXPORT_C TInt GPIO::SetOutputState
	(
	TInt                  aId,
	TGpioState			  aState,
   	TGpioCallback		* aCb
	)
	{
	if (aId < 0 || aId > KHwGpioPinMax)
		{
		return KErrArgument;
		}
	// TO DO: set the ouput state of this pin
	return KErrNone;
	}

EXPORT_C TInt GPIO::StaticExtension
	(
	TInt	  aId,
	TInt	  aCmd,
	TAny	* aArg1,
	TAny	* aArg2
	)
	{
	if (aId < 0 || aId > KHwGpioPinMax)
		{
		return KErrArgument;
		}
	// TO DO: call the appropriate static extension if supported
	return KErrNotSupported;
	}


//
// entry point for GPIO setup
//
DECLARE_STANDARD_EXTENSION()
	{

	// initialise GPIO pins array (if necessary)
	for (TInt32 i = 0; i <= KHwGpioPinMax; i++)
		{
		GpioPins[i].iIsr = NULL;
		GpioPins[i].iPtr = NULL;
		}
	// bind and enable GPIO Isr
	// NB Interrupt::Bind() now returns a handle (-ve value means an error)
	TInt r = Interrupt::Bind(KIntIdGpio, GpioIsrDispatch, &GpioPins[0]);
	if (r < 0)
		{
		return r;
		}
	// store handle
	GpioInterruptId = r;
	// NB Interrupt::Enable() now expects the handle return from Bind
	r = Interrupt::Enable(r);
	return r;
	}