Channel Implementation

Describes how to use the template port to implement the physical channel for the Digitizer Driver.

Define the size of the digitizer

The following four constants defined at the top of the template implementation in xyin.cpp define the origin and size of the digitizer device in pixels. Modify the values to define your own origin and size.

const TUint KConfigXyOffsetX    = 0;
const TUint KConfigXyOffsetY    = 0;
const TUint KConfigXyWidth = 640;  // pixels per line
const TUint KConfigXyHeight = 480; // lines per panel

This is information that is returned when calls are made:

See User-Side Hardware Abstraction.

The following four constants define the digitizer origin and size in digitizer ADC coordinates. Modify the values for your own digitizer:

const Tint KConfigXySpreadX = 4096; // maximum valid X spread
const Tint KConfigXySpreadY = 4096; // maximum valid Y spread
const Tint KConfigXyMinX = 0;       // minimum valid X value
const Tint KConfigXyMinY = 0;       // minimum valid Y value

Implement power on behaviour

In the template port, this is implemented by DTemplatedigitizer::digitizerPowerUp(). Note that this function is not derived from any base class function.

  • Add code to this function to do these things:

    1. Clear all digitizer interrupts.

    2. Request power resources from the power controller. This will power the device up from sleep mode. Note that power up, and power down, can be implemented later.

    3. Configure the hardware so that it generates an interrupt when the digitizer is touched.

  • Make sure that the digitizer interrupt is defined. In the template port, the interrupt id is defined as the constant:

    const TInt KIntIddigitizer=EAsspIntIdC

    in the file ...\template\template_assp\template_assp.h.

  • Make sure that the interrupt controller is configured for the digitizer interrupt. See Interrupt Dispatcher.

Implement Ddigitizer::WaitForPenDown()

This code is executed at startup or whenever the pen is lifted up. It implements a request for an interrupt to be generated when the pen next touches the digitizer. It is called by the platform independent layer:

  • at startup

  • when the pen is removed from the digitizer after a pen-up event has been issued.

There are two main cases to deal with: the digitizer is powering down; the digitizer is not powering down

The digitizer is powering down

The implementation for this case can be left until later. It is discussed in Implement power up and power down handling.

The digitizer is not powering down

To deal with this case, your implementation needs to:

  • clear the digitizer interrupt

  • set up the hardware so that it can detect when the digitizer is touched.

The pen interrupt is now enabled; if the digitizer is now touched, the pen interrupt ISR (interrupt service routine) DTemplatedigitizer::PenInterrupt() is called.

In the template port, the ISR includes the statement:

__KTRACE_OPT(KHARDWARE,Kern::Printf("I"));

and means that if the KHARDWARE tracing flag has been set, and tracing is on, then a single ā€œIā€ is printed whenever the digitizer is touched.

Tracing note
If the KEXTENSION, KPOWER and KHARDWARE tracing flags have been set, and tracing is on, then by the time WaitForPenDown() is called, you should be able to see the following sequence of calls in the trace:
  • DoCreate()

  • digitizerPowerUp()

  • WaitForPenDown()

Implement the pen interrupt ISR

In the template port, the interrupt service routine (ISR) that handles a pen interrupt is implemented by DTemplatedigitizer::PenInterrupt(). Note that this function is not derived from any base class function.

There are two main things to consider here:

  1. You need to add code to the start of the function to decide whether the pen is now up (i.e. removed from the screen panel), or whether the pen is now down (i.e. touching the digitizer panel). To make the decision, you may need to read the appropriate hardware register. The detail depends on the hardware.

  2. If the pen is down, you need to check the value of the configurable constant KPenDownDelayTime. What you do next depends on the value of this constant:

    • If the value is greater than zero, then you do not need to change the code at this time. The existing code just starts a timer to delay the beginning of the collection of samples. Note, however, that you will need to modify the debounce timer callback function timerIntExpired() to clear the digitizer interrupt - see Add code to the debounce timer callback function.

    • If the value is zero, then you must clear the digitizer interrupt here in this function, PenInterrupt().

  3. To contribute the timing of pen interrupts as a source of random data for the Random Number Generator (see CSPRNG Implementation in Kernel), ensure that a call to Interrupt::AddTimingEntropy() is made in the ISR.

Initialise sampling

In the template port, the initialisation of sampling is implemented in the first half of the function DTemplatedigitizer::TakeSample() function. Note that this function is not derived from any base class function.

There are two main things to consider here:

  1. You need to decide whether the pen is up or down. Set the variable penDown to ETrue if the pen is down or EFalse if the pen is up.

    To do this you may need to read the appropriate hardware register - the detail depends on the hardware.

  2. Change the section of code that is executed when the pen is found to be up after a power on, i.e. the block of code:

    if (iState==E_HW_PowerUp)
        {
        if (!penDown)
            {
            ...
            }

    The block of code needs to do the following:

    • reset the sample buffer

    • clear the digitizer interrupt

    • set up the hardware so that it can detect when the digitizer is touched

    • enable the digitizer interrupt.

Take sample readings

In the template port, the initialisation of sampling is implemented in the second half of the function DTemplatedigitizer::TakeSample() function. Note that this function is not derived from any base class function.

This code is executed while the pen is down, and needs to do the following:

  • read the hardware for the digitizer samples and put the results into the sample buffer. The sample buffer resides in the platform independent layer.

  • set up the hardware so that it can detect when the digitizer is touched

  • schedule the reading of the next sample using a one shot timer; the time interval is defined by the value of the configurable constant KInterSampleTime

  • when a complete group of samples has been taken, tell the platform independent layer by calling RawSampleValid(); the function is a member of the base class Ddigitizer.

Tracing note

If the KHARDWARE tracing flag has been set, and tracing is on, then it should be possible to move the pen over the screen and see the raw sample values on the debug output. Check they are correct.

Add code to the debounce timer callback function

In the template port, the debounce timer callback function is implemented by the local function timerIntExpired().

If not already done in Implement the pen interrupt ISR, add code to this callback function to clear the digitizer interrupt.

Deal with a pen up interrupt

If the digitizer generates an interrupt when the pen is lifted, then you need to add code to the pen interrupt ISR to handle this. This is the same function, DTemplatedigitizer::PenInterrupt(), referred to in Implement the pen interrupt ISR.

The code should:

  • clear the digitizer interrupt.

  • set up the hardware so that it can detect when the digitizer panel is touched.

If there is no pen up interrupt by design, then you need to add code into the DTemplatedigitizer::TakeSample() function at the point where the pen is up and the digitizer is in the pen up debounce state (i.e. E_HW_PenUpDebounce):

if (!penDown)
    {
    if (iState==E_HW_PenUpDebounce)
        {
        . . .

At this point, you should have almost all digitizer capability ā€“ pen up handling, pen down handling, and the taking of digitizer readings.

Implement Ddigitizer::digitizerOff()

This function is called when the digitizer is being powered down.

If the device is powered on, then the function needs to do disable the digitizer interrupt.

If the digitizer is in the collect sample state (i.e. E_HW_CollectSample), then it also needs to do the following:

  • set up the hardware so that the device wakes up from standby if the digitizer panel is touched.

  • relinquish the request for power resources; this will place the peripheral hardware into a low power "sleep" mode, which is capable of detecting an interrupt.

Implement power up and power down handling

At this point, the device should be working successfully.

You now need to put the device into a low power "sleep" mode when it is switched off, and to bring it out of "sleep" mode when the digitizer is touched.

  • Add code to the template port function DTemplatedigitizer::digitizerPowerUp() to request power resources from the power controller. This will power the device up from sleep mode.

  • Add code to the powering down part of your implementation of Ddigitizer::WaitForPenDown() that does the following:

    • sets up the hardware to wake the device from standby if the digitizer is touched.

    • relinquishes the request for power resources - this will place the peripheral hardware into a low power "sleep" mode, which is capable of detecting an interrupt.