Adaptation/GUID-AF71FDC2-A8CC-5035-91FE-36212844BC07.dita
author Graeme Price <GRAEME.PRICE@NOKIA.COM>
Fri, 15 Oct 2010 14:32:18 +0100
changeset 15 307f4279f433
permissions -rw-r--r--
Initial contribution of the Adaptation Documentation.

<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2007-2010 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: 
-->
<!DOCTYPE concept
  PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
<concept id="GUID-AF71FDC2-A8CC-5035-91FE-36212844BC07" xml:lang="en"><title>Channel
Implementation</title><shortdesc>Describes how to use the template port to implement the physical
channel for the Digitizer Driver. </shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody>
<section id="GUID-EA342370-0293-5762-86FD-E86DC6BC3006"><title>Define the
size of the digitizer</title> <p>The following four constants defined at the
top of the template implementation in <filepath>xyin.cpp</filepath> define
the origin and size of the digitizer device in pixels. Modify the values to
define your own origin and size. </p> <codeblock id="GUID-8A7E9CCC-D6A2-5E5D-B0DB-8AE3334F6EC9" xml:space="preserve">const TUint KConfigXyOffsetX    = 0;
const TUint KConfigXyOffsetY    = 0;
const TUint KConfigXyWidth = 640;  // pixels per line
const TUint KConfigXyHeight = 480; // lines per panel
</codeblock> <p>This is information that is returned when calls are made: </p> <ul>
<li id="GUID-003FE140-2DDF-58B4-AA1F-57F8A0FCF4E7"><p> <i>user side</i> to <xref href="GUID-BD00E7FC-C234-3111-87A5-10F79EB0F2B8.dita#GUID-BD00E7FC-C234-3111-87A5-10F79EB0F2B8/GUID-573C49D6-7763-37AE-B2B2-4C8FB1327E21"><apiname>HAL::Get()</apiname></xref> passing
the attribute(s) <xref href="GUID-696EDBEB-76B2-3F02-AD33-BA4977551F32.dita"><apiname>EPenX</apiname></xref> and <xref href="GUID-3E3B49CC-53F6-3341-A969-1DDC0A837B0B.dita"><apiname>EPenY</apiname></xref>  </p> </li>
<li id="GUID-0C5E452E-5564-5A27-B379-5BF3D9518E78"><p> <i>kernel side</i> to <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-DA115709-A225-3E2A-BCCD-6E2BB15979B9"><apiname>Kern::HalFunction()</apiname></xref>,
passing group <xref href="GUID-357CC84A-F701-3F56-AF4D-0C95002F1A8E.dita"><apiname>EHalGroupdigitizer</apiname></xref> and function-id <xref href="GUID-841ECDFD-7CAB-30BB-A301-CF70C029043B.dita"><apiname>EdigitizerHalXYInfo</apiname></xref>  </p> </li>
</ul> <p>See <xref href="GUID-2D977A02-5928-5441-8AE7-42A722F2A4B8.dita#GUID-2D977A02-5928-5441-8AE7-42A722F2A4B8/GUID-4DA41221-40B9-5BC7-B2C6-7C6EB4522508">User-Side
Hardware Abstraction</xref>. </p> <p>The following four constants define the
digitizer origin and size in digitizer ADC coordinates. Modify the values
for your own digitizer: </p> <codeblock id="GUID-ED04E417-16B5-5AA2-96FB-B450BAC272A9" xml:space="preserve">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
</codeblock> </section>
<section id="GUID-A4B43E01-9638-5967-8EFA-0AABA33189EA"><title>Implement power
on behaviour</title> <p>In the template port, this is implemented by <b>DTemplatedigitizer::digitizerPowerUp()</b>.
Note that this function is not derived from any base class function. </p> <ul>
<li id="GUID-2B31DD8F-DACF-50FD-8FC6-DC6C55954CC5"><p>Add code to this function
to do these things: </p> <ol id="GUID-324D32A9-50F0-53F9-A717-AE026626A76E">
<li id="GUID-7A461F0B-EBEE-5F73-BFA1-031EEAB9BCF9"><p>Clear all digitizer
interrupts. </p> </li>
<li id="GUID-62182E91-A6B0-5C3C-8CC5-4C993235EF02"><p>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. </p> </li>
<li id="GUID-D9CFB381-4D23-5E47-808B-C5CE52F99223"><p>Configure the hardware
so that it generates an interrupt when the digitizer is touched. </p> </li>
</ol> </li>
<li id="GUID-AFFF418C-9FD7-5EE6-9487-968FDCF7B795"><p>Make sure that the digitizer
interrupt is defined. In the template port, the interrupt id is defined as
the constant: </p> <codeblock id="GUID-7D7940D8-4708-501C-AA44-1C9A6961260A" xml:space="preserve">const TInt KIntIddigitizer=EAsspIntIdC</codeblock> <p>in
the file <filepath>...\template\template_assp\template_assp.h</filepath>. </p> </li>
<li id="GUID-EE388EFA-84D7-5E1E-A75F-66310EAEF8E5"><p>Make sure that the interrupt
controller is configured for the digitizer interrupt. See <xref href="GUID-76A30EC4-4B99-5471-9E80-F853C91485BC.dita">Interrupt
Dispatcher</xref>. </p> </li>
</ul> </section>
<section id="GUID-1A1194A0-DF74-59E7-B3AD-FD87D501F00F"><title>Implement Ddigitizer::WaitForPenDown()</title> <p>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: </p> <ul>
<li id="GUID-1D1D1ED7-12EC-51B9-A5B7-228E0390DF4C"><p>at startup </p> </li>
<li id="GUID-C8999684-87B6-5DDA-AB4F-D990B7512365"><p>when the pen is removed
from the digitizer after a pen-up event has been issued. </p> </li>
</ul> <p>There are two main cases to deal with: the digitizer is powering
down; the digitizer is not powering down </p> <p id="GUID-9DC378A0-05F9-52B0-A441-1E451E85D213"><b>The
digitizer is powering down</b> </p> <p>The implementation for this case can
be left until later. It is discussed in <xref href="GUID-AF71FDC2-A8CC-5035-91FE-36212844BC07.dita#GUID-AF71FDC2-A8CC-5035-91FE-36212844BC07/GUID-FE7F24DF-6A65-5A7E-A9C8-DBCF7848DEA6">Implement
power up and power down handling</xref>. </p> <p id="GUID-4B4CF159-E5B2-5EAA-8489-8E1921BA0AF1"><b>The
digitizer is <i>not</i> powering down</b> </p> <p>To deal with this case,
your implementation needs to: </p> <ul>
<li id="GUID-633792DB-C955-57E0-8DB1-2FDB2EC20269"><p>clear the digitizer
interrupt </p> </li>
<li id="GUID-2F88C290-C412-50EF-8E2C-BE0CC5A489DA"><p>set up the hardware
so that it can detect when the digitizer is touched. </p> </li>
</ul> <p>The pen interrupt is now enabled; if the digitizer is now touched,
the pen interrupt ISR (interrupt service routine) <codeph>DTemplatedigitizer::PenInterrupt()</codeph> is
called. </p> <p>In the template port, the ISR includes the statement: </p> <codeblock id="GUID-351F56AC-8B3D-55F6-B3EC-77F623C18BE1" xml:space="preserve">__KTRACE_OPT(KHARDWARE,Kern::Printf("I"));</codeblock> <p>and
means that if the <codeph>KHARDWARE</codeph> tracing flag has been set, and
tracing is on, then a single ā€œIā€ is printed whenever the digitizer is touched. </p><b>Tracing
note</b> <p>If the <codeph>KEXTENSION</codeph>, <codeph>KPOWER</codeph> and <codeph>KHARDWARE</codeph> tracing
flags have been set, and tracing is on, then by the time <codeph>WaitForPenDown()</codeph> is
called, you should be able to see the following sequence of calls in the trace:<ul>
<li><p><codeph>DoCreate()</codeph></p></li>
<li><p><codeph>digitizerPowerUp()</codeph></p></li>
<li><p><codeph>WaitForPenDown()</codeph></p></li>
</ul></p> </section>
<section id="GUID-D74C94E4-83AD-5BC0-B435-754E7D3FECA4"><title>Implement the
pen interrupt ISR</title> <p>In the template port, the interrupt service routine
(ISR) that handles a pen interrupt is implemented by <b>DTemplatedigitizer::PenInterrupt()</b>.
Note that this function is not derived from any base class function. </p> <p>There
are two main things to consider here: </p> <ol id="GUID-4CD5BC52-AC79-55E8-B38F-EA9DCB048A04">
<li id="GUID-4D9F1CC5-E256-53F7-8E7D-B31ED3296C7D"><p>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. </p> </li>
<li id="GUID-4FF2D674-4BB1-50EB-B55C-DF18652A1E5F"><p>If the pen is down,
you need to check the value of the configurable constant <xref href="GUID-3574BE12-9DA9-573D-8545-3B073005A139.dita#GUID-3574BE12-9DA9-573D-8545-3B073005A139/GUID-587D0895-7B8D-5FA1-A2DE-2F346780BB78">KPenDownDelayTime</xref>. What you do next depends on the value of this constant: </p> <ul>
<li id="GUID-C238E00E-7A7C-5A44-A63D-5D214C30727D"><p>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 <codeph>timerIntExpired()</codeph> to
clear the digitizer interrupt - see <xref href="GUID-AF71FDC2-A8CC-5035-91FE-36212844BC07.dita#GUID-AF71FDC2-A8CC-5035-91FE-36212844BC07/GUID-7ADA202E-23F8-52E1-BE57-B44FF75C5612">Add
code to the debounce timer callback function</xref>. </p> </li>
<li id="GUID-985A0D59-B45D-59D3-894F-9B9509B03E70"><p>If the value is zero,
then you must clear the digitizer interrupt here in this function, <codeph>PenInterrupt()</codeph>. </p> </li>
</ul> </li>
<li id="GUID-B2766A95-D916-428F-84AE-2D4ADDFF999A"><p>To contribute the timing
of pen interrupts as a source of random data for the Random Number Generator
(see <xref href="GUID-8290AAF0-577C-51D2-8AC1-0D37A10F45CB.dita">CSPRNG Implementation
in Kernel</xref>), ensure that a call to <xref href="GUID-E7A7083C-97B9-39B9-A147-4A6E314EE3A3.dita#GUID-E7A7083C-97B9-39B9-A147-4A6E314EE3A3/GUID-C46E48EE-6F4A-3A61-A3C9-84B145119541"><apiname>Interrupt::AddTimingEntropy()</apiname></xref> is
made in the ISR.</p></li>
</ol> </section>
<section id="GUID-4B0737BA-74E2-5FF2-BCE3-4BC822C14470"><title>Initialise
sampling</title> <p>In the template port, the initialisation of sampling is
implemented in the first half of the function <b>DTemplatedigitizer::TakeSample()</b> function.
Note that this function is not derived from any base class function. </p> <p>There
are two main things to consider here: </p> <ol id="GUID-1101F7D6-EDEF-5B9F-832C-75D298ACF1E4">
<li id="GUID-A56C4872-FDD0-571C-A721-C267BB1DFD5C"><p>You need to decide whether
the pen is up or down. Set the variable <codeph>penDown</codeph> to <xref href="GUID-781E8158-805B-3784-8FED-D7A191822FC3.dita"><apiname>ETrue</apiname></xref> if
the pen is down or <xref href="GUID-A759CA2D-8327-348F-9337-4886E619D920.dita"><apiname>EFalse</apiname></xref> if the pen is up. </p> <p>To
do this you may need to read the appropriate hardware register - the detail
depends on the hardware. </p> </li>
<li id="GUID-4B498AD5-766B-57DF-8021-2A7BB7FB5C19"><p>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: </p> <codeblock id="GUID-4CE73640-1D2F-50F2-AD85-92B2F0FA35DC" xml:space="preserve">if (iState==E_HW_PowerUp)
    {
    if (!penDown)
        {
        ...
        }</codeblock> <p>The block of code needs to do the following: </p> <ul>
<li id="GUID-22297738-82AA-5F87-AE35-09903161E793"><p>reset the sample buffer </p> </li>
<li id="GUID-D22ED4D2-B602-5270-9131-053E6B17191B"><p>clear the digitizer
interrupt </p> </li>
<li id="GUID-32A574A0-42D0-5953-AB00-BDFAABD4C82E"><p>set up the hardware
so that it can detect when the digitizer is touched </p> </li>
<li id="GUID-B422C5F4-D7F8-5BD1-B9B5-130B9EFBD44A"><p>enable the digitizer
interrupt. </p> </li>
</ul> </li>
</ol> </section>
<section id="GUID-4E84D583-7745-531B-AB62-65D012B4BCB2"><title>Take sample
readings</title> <p>In the template port, the initialisation of sampling is
implemented in the second half of the function <b>DTemplatedigitizer::TakeSample()</b> function.
Note that this function is not derived from any base class function. </p> <p>This
code is executed while the pen is down, and needs to do the following: </p> <ul>
<li id="GUID-F9FB32EF-7967-5753-8D4F-BBEAF3BC2AC9"><p>read the hardware for
the digitizer samples and put the results into the sample buffer. The sample
buffer resides in the platform independent layer. </p> </li>
<li id="GUID-E4F4B6D9-9455-5B43-A025-735A6A1235B0"><p>set up the hardware
so that it can detect when the digitizer is touched </p> </li>
<li id="GUID-642B38D4-658A-59A0-AA7C-D497CB6A0FF4"><p>schedule the reading
of the next sample using a one shot timer; the time interval is defined by
the value of the configurable constant <xref href="GUID-3574BE12-9DA9-573D-8545-3B073005A139.dita#GUID-3574BE12-9DA9-573D-8545-3B073005A139/GUID-C8EC7A1D-7597-57BB-ADE4-0EDFFEB323D0">KInterSampleTime</xref> </p> </li>
<li id="GUID-C3B71C41-8C33-5A39-B1D8-B08CD6D7AE6E"><p>when a complete group
of samples has been taken, tell the platform independent layer by calling <codeph>RawSampleValid()</codeph>;
the function is a member of the base class <xref href="GUID-52E09E60-E29C-359C-926B-9836D960EF20.dita"><apiname>Ddigitizer</apiname></xref>. </p> </li>
</ul> <p><b>Tracing note </b> </p> <p>If the <codeph>KHARDWARE</codeph> 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. </p> </section>
<section id="GUID-7ADA202E-23F8-52E1-BE57-B44FF75C5612"><title>Add code to
the debounce timer callback function</title> <p>In the template port, the
debounce timer callback function is implemented by the local function <b>timerIntExpired()</b>. </p> <p>If
not already done in <xref href="GUID-AF71FDC2-A8CC-5035-91FE-36212844BC07.dita#GUID-AF71FDC2-A8CC-5035-91FE-36212844BC07/GUID-D74C94E4-83AD-5BC0-B435-754E7D3FECA4">Implement
the pen interrupt ISR</xref>, add code to this callback function to clear
the digitizer interrupt. </p> </section>
<section id="GUID-8F229C58-66B5-5D0A-9058-8C57586F5B45"><title>Deal with a
pen up interrupt</title> <p>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, <b>DTemplatedigitizer::PenInterrupt()</b>,
referred to in <xref href="GUID-AF71FDC2-A8CC-5035-91FE-36212844BC07.dita#GUID-AF71FDC2-A8CC-5035-91FE-36212844BC07/GUID-D74C94E4-83AD-5BC0-B435-754E7D3FECA4">Implement
the pen interrupt ISR</xref>. </p> <p>The code should: </p> <ul>
<li id="GUID-46619FF8-B3A0-556C-8B7F-D93CA3BAD2DA"><p>clear the digitizer
interrupt. </p> </li>
<li id="GUID-6E7353D8-118D-5FD9-9557-68DBCCBF32D9"><p>set up the hardware
so that it can detect when the digitizer panel is touched. </p> </li>
</ul> <p>If there is no pen up interrupt by design, then you need to add code
into the <b>DTemplatedigitizer::TakeSample()</b> function at the point where
the pen is up and the digitizer is in the <i>pen up debounce</i> state (i.e. <codeph>E_HW_PenUpDebounce</codeph>): </p> <codeblock id="GUID-6AF28551-7F20-5C70-8D0E-E40F2DD50417" xml:space="preserve">if (!penDown)
    {
    if (iState==E_HW_PenUpDebounce)
        {
        . . .</codeblock> <p>At this point, you should have almost all digitizer
capability ā€“ pen up handling, pen down handling, and the taking of digitizer
readings. </p> </section>
<section id="GUID-6DC8A3DB-452F-5738-9D60-7E34BF8A3596"><title>Implement Ddigitizer::digitizerOff()</title> <p>This
function is called when the digitizer is being powered down. </p> <p>If the
device is powered on, then the function needs to do disable the digitizer
interrupt. </p> <p>If the digitizer is in the <i>collect sample</i> state
(i.e. <codeph>E_HW_CollectSample</codeph>), then it also needs to do the following: </p> <ul>
<li id="GUID-7C5A6267-9CE2-587F-9092-F16DB89E8283"><p>set up the hardware
so that the device wakes up from standby if the digitizer panel is touched. </p> </li>
<li id="GUID-F606C7D1-A0FD-5845-B9A0-EAF13D3F5B01"><p>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. </p> </li>
</ul> </section>
<section id="GUID-FE7F24DF-6A65-5A7E-A9C8-DBCF7848DEA6"><title>Implement power
up and power down handling</title> <p>At this point, the device should be
working successfully. </p> <p>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. </p> <ul>
<li id="GUID-EE805C9C-62F1-5F03-A9F9-643BC025E047"><p>Add code to the template
port function <b>DTemplatedigitizer::digitizerPowerUp()</b> to request power
resources from the power controller. This will power the device up from sleep
mode. </p> </li>
<li id="GUID-141FEF1E-B284-5970-89CF-81F9C6CD3890"><p>Add code to the powering
down part of your implementation of <xref href="GUID-52E09E60-E29C-359C-926B-9836D960EF20.dita#GUID-52E09E60-E29C-359C-926B-9836D960EF20/GUID-43E7AF76-DF07-3688-984A-80365150C080"><apiname>Ddigitizer::WaitForPenDown()</apiname></xref> that
does the following: </p> <ul>
<li id="GUID-310D240A-CCCC-5978-8798-75EE01B13E7D"><p>sets up the hardware
to wake the device from standby if the digitizer is touched. </p> </li>
<li id="GUID-D7C488F1-8727-5948-A7D1-3D1C4A306AF9"><p>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. </p> </li>
</ul> </li>
</ul> </section>
</conbody></concept>