<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://pandorawiki.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Exophase</id>
	<title>Pandora Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://pandorawiki.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Exophase"/>
	<link rel="alternate" type="text/html" href="https://pandorawiki.org/Special:Contributions/Exophase"/>
	<updated>2026-04-13T13:30:42Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.32.0-alpha</generator>
	<entry>
		<id>https://pandorawiki.org/index.php?title=Assembly_Code_Optimization&amp;diff=30181</id>
		<title>Assembly Code Optimization</title>
		<link rel="alternate" type="text/html" href="https://pandorawiki.org/index.php?title=Assembly_Code_Optimization&amp;diff=30181"/>
		<updated>2016-04-30T18:58:37Z</updated>

		<summary type="html">&lt;p&gt;Exophase: /* NEON */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Assembly code optimization on the Cortex-A8 ==&lt;br /&gt;
This guide presents specific optimization techniques for the [[ARM]] Cortex-A8 processor and its dual-issue, in-order pipeline.&lt;br /&gt;
&lt;br /&gt;
== Use the ARMv7 movw/movt instructions ==&lt;br /&gt;
Newer ARM processors allow loading 32-bit values as two 16-bit immediates.  The movw instruction loads the lower 16 bits, and movt loads the upper 16 bits.  The movw instruction clears the upper 16 bits, so that 16-bit values can be loaded using a single instruction.  The movt instruction does not affect the lower bits.&lt;br /&gt;
&lt;br /&gt;
On older ARM processors, it was common to load 32-bit values with a PC-relative load.  This should be avoided because it may result in a cache miss.&lt;br /&gt;
&lt;br /&gt;
== Branch Prediction ==&lt;br /&gt;
There is a one-cycle stall in instruction fetch when a branch is predicted taken.  It is therefore preferable to structure code so that the most likely code path is the one where the branch is not taken.&lt;br /&gt;
&lt;br /&gt;
Unconditional branches may be mispredicted, and load instructions which follow branches may be decoded and cause cache accesses.  Avoid placing load instructions after branches unless you intend the CPU to prefetch the addresses they reference.&lt;br /&gt;
&lt;br /&gt;
The branch predictor has a call/return stack for jumps which reference r14 or stack operations using r13 which load the program counter.  For best performance, make sure any pop, mov pc,lr or bx lr jumps to the same location as was set by the matching bl instruction.  For non-return jumps, use a register other than r14.&lt;br /&gt;
&lt;br /&gt;
Although instructions are decoded in pairs, the branch predictor can only predict one branch target per cycle.  If you have a conditional branch which is immediately followed by another branch, and the first branch is likely to be taken, place a no-operation instruction between the branches to prevent decoding and prediction of the second branch.  Inserting NOPs is detrimental if the first branch is infrequently taken.&lt;br /&gt;
&lt;br /&gt;
== Dual-Issue Restrictions ==&lt;br /&gt;
Only one branch instruction can issue per cycle.  Only one load or store instruction can issue per cycle.  Instructions which write to the same register can not issue together.&lt;br /&gt;
&lt;br /&gt;
There is a one-cycle delay before any written register can be used as the address of a subsequent load or store instruction.  There is a one-cycle delay before any written register can be used by an instruction which performs a shift or rotation on that register.&lt;br /&gt;
&lt;br /&gt;
There is one cycle delay before the result of a load can be used.  In the aforementioned cases involving subsequent shift or rotate instructions, or the address of a load or store instruction, the total delay is two cycles.  &lt;br /&gt;
&lt;br /&gt;
Stores occur at the end of the pipeline and store instructions can issue in the same cycle as another instruction which writes the same register.  Similarly, conditional branches can issue in the same cycle as flag-setting instructions because the branch is not resolved until the following cycle.  In all other cases, instructions can not issue together if the second instruction depends on the results of the first.&lt;br /&gt;
&lt;br /&gt;
== Instruction pairing restrictions following a branch ==&lt;br /&gt;
The Cortex-A8 processor normally fetches two instructions per cycle and the branch predictor tests each against the global history buffer.  However, there is only one entry in the branch target buffer for each pair of instructions.  Therefore, branch instructions, and certain instructions which resemble branches, may adversely affect branch prediction when present in pairs.  To reduce the risk of branch misprediction, avoid pairing branch instructions with the following:&lt;br /&gt;
&lt;br /&gt;
* Branch instructions&lt;br /&gt;
* Load instructions, whether or not they write r15&lt;br /&gt;
* Arithmetic/logic instructions which do not set flags and do not have an immediate value, whether or not they write r15&lt;br /&gt;
&lt;br /&gt;
Flag-setting instructions can be used to avoid this restriction.  Additionally, MOV instructions that do not have immediate values can be replaced with ADD, SUB, ORR, or EOR instructions using zero as an immediate value.&lt;br /&gt;
&lt;br /&gt;
== Code alignment ==&lt;br /&gt;
Code alignment should be used with caution.  Alignment has the potential to increase performance, but may be detrimental in some circumstances.&lt;br /&gt;
&lt;br /&gt;
Because the instruction decoder always fetches 64-bit aligned words from the level-1 instruction cache, aligning code can improve instruction fetch and decode.  However, the global history buffer of the branch predictor is indexed by the low bits of the instruction address.  Excessive code alignment can result in a suboptimal distribution of entries in the branch history tables and increase branch misprediction.  Additionally, the speculative prefetch may retrieve and decode instructions used as padding, even if those instructions are never executed.  The types of instructions used as padding will affect the branch predictor as stated above, and this may affect the prefetch of code into the instruction cache.&lt;br /&gt;
&lt;br /&gt;
== NEON ==&lt;br /&gt;
As the manual states, passing data from NEON (and VFP) back to ARM takes at least 20 cycles, but there are some tricks that can be used. The vmov instruction itself that is passing the data will not cause any stalls (provided the needed NEON register is already available), the stall will actually happen on any ARM instruction that follows instead (including branches). This means that:&lt;br /&gt;
* Multiple &amp;quot;vmov.32 rX, dY[Z]&amp;quot; can be done back-to-back and only incur one stall after the whole sequence&lt;br /&gt;
* Additional NEON instructions can be issued after &amp;quot;vmov&amp;quot; without stalling (with enough instructions the stall can be completely avoided)&lt;br /&gt;
* Additional unrelated NEON instructions can be issued before &amp;quot;vmov&amp;quot; (to hide the latency of instruction that produces the source register data)&lt;br /&gt;
&lt;br /&gt;
Even though the VFP is not pipelined, the VFP vldr instructions are. &amp;quot;vldr s0, [r0]&amp;quot; will be faster than &amp;quot;vld1.32 {d0[0]}, [r0]&amp;quot; (2 vs 3 cycles, vldr also gives more flexible addressing mode). The same can't be said about &amp;quot;vmov sX, sY&amp;quot;, it waits for all previous instructions to complete before issuing.&lt;br /&gt;
&lt;br /&gt;
You should avoid any NEON loads that come from a location that has recently been written to. NEON does not have store forwarding, so this can cost dozens of cycles. This can happen unknowingly if you use unaligned loads, because they're performed with two aligned accesses. For example, if you have this sequence:&lt;br /&gt;
&lt;br /&gt;
 loop:&lt;br /&gt;
  vld1.u32 { q0 }, [r0]&lt;br /&gt;
  vadd.u32 q0, q0, q1&lt;br /&gt;
  vst1.u32 { q0 }, [r0]!&lt;br /&gt;
  subs r1, #1&lt;br /&gt;
  bne loop&lt;br /&gt;
&lt;br /&gt;
If r0 is unaligned, the next iteration of vld1.u32 will overlap with the previous iteration of vst1.u32, which will cause a stall. To avoid this situation you can reorder the loop so that the store happens one element behind.&lt;br /&gt;
&lt;br /&gt;
[[Category:Development]]&lt;br /&gt;
[[Category:Optimization]]&lt;br /&gt;
[[Category:Chipset]]&lt;/div&gt;</summary>
		<author><name>Exophase</name></author>
		
	</entry>
	<entry>
		<id>https://pandorawiki.org/index.php?title=Assembly_Code_Optimization&amp;diff=30180</id>
		<title>Assembly Code Optimization</title>
		<link rel="alternate" type="text/html" href="https://pandorawiki.org/index.php?title=Assembly_Code_Optimization&amp;diff=30180"/>
		<updated>2016-04-30T18:58:25Z</updated>

		<summary type="html">&lt;p&gt;Exophase: /* NEON */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Assembly code optimization on the Cortex-A8 ==&lt;br /&gt;
This guide presents specific optimization techniques for the [[ARM]] Cortex-A8 processor and its dual-issue, in-order pipeline.&lt;br /&gt;
&lt;br /&gt;
== Use the ARMv7 movw/movt instructions ==&lt;br /&gt;
Newer ARM processors allow loading 32-bit values as two 16-bit immediates.  The movw instruction loads the lower 16 bits, and movt loads the upper 16 bits.  The movw instruction clears the upper 16 bits, so that 16-bit values can be loaded using a single instruction.  The movt instruction does not affect the lower bits.&lt;br /&gt;
&lt;br /&gt;
On older ARM processors, it was common to load 32-bit values with a PC-relative load.  This should be avoided because it may result in a cache miss.&lt;br /&gt;
&lt;br /&gt;
== Branch Prediction ==&lt;br /&gt;
There is a one-cycle stall in instruction fetch when a branch is predicted taken.  It is therefore preferable to structure code so that the most likely code path is the one where the branch is not taken.&lt;br /&gt;
&lt;br /&gt;
Unconditional branches may be mispredicted, and load instructions which follow branches may be decoded and cause cache accesses.  Avoid placing load instructions after branches unless you intend the CPU to prefetch the addresses they reference.&lt;br /&gt;
&lt;br /&gt;
The branch predictor has a call/return stack for jumps which reference r14 or stack operations using r13 which load the program counter.  For best performance, make sure any pop, mov pc,lr or bx lr jumps to the same location as was set by the matching bl instruction.  For non-return jumps, use a register other than r14.&lt;br /&gt;
&lt;br /&gt;
Although instructions are decoded in pairs, the branch predictor can only predict one branch target per cycle.  If you have a conditional branch which is immediately followed by another branch, and the first branch is likely to be taken, place a no-operation instruction between the branches to prevent decoding and prediction of the second branch.  Inserting NOPs is detrimental if the first branch is infrequently taken.&lt;br /&gt;
&lt;br /&gt;
== Dual-Issue Restrictions ==&lt;br /&gt;
Only one branch instruction can issue per cycle.  Only one load or store instruction can issue per cycle.  Instructions which write to the same register can not issue together.&lt;br /&gt;
&lt;br /&gt;
There is a one-cycle delay before any written register can be used as the address of a subsequent load or store instruction.  There is a one-cycle delay before any written register can be used by an instruction which performs a shift or rotation on that register.&lt;br /&gt;
&lt;br /&gt;
There is one cycle delay before the result of a load can be used.  In the aforementioned cases involving subsequent shift or rotate instructions, or the address of a load or store instruction, the total delay is two cycles.  &lt;br /&gt;
&lt;br /&gt;
Stores occur at the end of the pipeline and store instructions can issue in the same cycle as another instruction which writes the same register.  Similarly, conditional branches can issue in the same cycle as flag-setting instructions because the branch is not resolved until the following cycle.  In all other cases, instructions can not issue together if the second instruction depends on the results of the first.&lt;br /&gt;
&lt;br /&gt;
== Instruction pairing restrictions following a branch ==&lt;br /&gt;
The Cortex-A8 processor normally fetches two instructions per cycle and the branch predictor tests each against the global history buffer.  However, there is only one entry in the branch target buffer for each pair of instructions.  Therefore, branch instructions, and certain instructions which resemble branches, may adversely affect branch prediction when present in pairs.  To reduce the risk of branch misprediction, avoid pairing branch instructions with the following:&lt;br /&gt;
&lt;br /&gt;
* Branch instructions&lt;br /&gt;
* Load instructions, whether or not they write r15&lt;br /&gt;
* Arithmetic/logic instructions which do not set flags and do not have an immediate value, whether or not they write r15&lt;br /&gt;
&lt;br /&gt;
Flag-setting instructions can be used to avoid this restriction.  Additionally, MOV instructions that do not have immediate values can be replaced with ADD, SUB, ORR, or EOR instructions using zero as an immediate value.&lt;br /&gt;
&lt;br /&gt;
== Code alignment ==&lt;br /&gt;
Code alignment should be used with caution.  Alignment has the potential to increase performance, but may be detrimental in some circumstances.&lt;br /&gt;
&lt;br /&gt;
Because the instruction decoder always fetches 64-bit aligned words from the level-1 instruction cache, aligning code can improve instruction fetch and decode.  However, the global history buffer of the branch predictor is indexed by the low bits of the instruction address.  Excessive code alignment can result in a suboptimal distribution of entries in the branch history tables and increase branch misprediction.  Additionally, the speculative prefetch may retrieve and decode instructions used as padding, even if those instructions are never executed.  The types of instructions used as padding will affect the branch predictor as stated above, and this may affect the prefetch of code into the instruction cache.&lt;br /&gt;
&lt;br /&gt;
== NEON ==&lt;br /&gt;
As the manual states, passing data from NEON (and VFP) back to ARM takes at least 20 cycles, but there are some tricks that can be used. The vmov instruction itself that is passing the data will not cause any stalls (provided the needed NEON register is already available), the stall will actually happen on any ARM instruction that follows instead (including branches). This means that:&lt;br /&gt;
* Multiple &amp;quot;vmov.32 rX, dY[Z]&amp;quot; can be done back-to-back and only incur one stall after the whole sequence&lt;br /&gt;
* Additional NEON instructions can be issued after &amp;quot;vmov&amp;quot; without stalling (with enough instructions the stall can be completely avoided)&lt;br /&gt;
* Additional unrelated NEON instructions can be issued before &amp;quot;vmov&amp;quot; (to hide the latency of instruction that produces the source register data)&lt;br /&gt;
&lt;br /&gt;
Even though the VFP is not pipelined, the VFP vldr instructions are. &amp;quot;vldr s0, [r0]&amp;quot; will be faster than &amp;quot;vld1.32 {d0[0]}, [r0]&amp;quot; (2 vs 3 cycles, vldr also gives more flexible addressing mode). The same can't be said about &amp;quot;vmov sX, sY&amp;quot;, it waits for all previous instructions to complete before issuing.&lt;br /&gt;
&lt;br /&gt;
You should avoid any NEON loads that come from a location that has recently been written to. NEON does not have store forwarding, so this can cost dozens of cycles. This can happen unknowingly if you use unaligned loads, because they're performed with two aligned accesses. For example, if you have this sequence:&lt;br /&gt;
&lt;br /&gt;
 loop:&lt;br /&gt;
  vld1.u32 { q0 }, [r0]&lt;br /&gt;
  vadd.u32 q0, q0, q1&lt;br /&gt;
  vst1.u32 { q0 }, [r0]!&lt;br /&gt;
  subs r1, #1&lt;br /&gt;
  bne loop&lt;br /&gt;
&lt;br /&gt;
If 0 is unaligned, the next iteration of vld1.u32 will overlap with the previous iteration of vst1.u32, which will cause a stall. To avoid this situation you can reorder the loop so that the store happens one element behind.&lt;br /&gt;
&lt;br /&gt;
[[Category:Development]]&lt;br /&gt;
[[Category:Optimization]]&lt;br /&gt;
[[Category:Chipset]]&lt;/div&gt;</summary>
		<author><name>Exophase</name></author>
		
	</entry>
	<entry>
		<id>https://pandorawiki.org/index.php?title=Assembly_Code_Optimization&amp;diff=30179</id>
		<title>Assembly Code Optimization</title>
		<link rel="alternate" type="text/html" href="https://pandorawiki.org/index.php?title=Assembly_Code_Optimization&amp;diff=30179"/>
		<updated>2016-04-30T18:57:49Z</updated>

		<summary type="html">&lt;p&gt;Exophase: Added NEON load-hit-store penalties and misaligned access caveat&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Assembly code optimization on the Cortex-A8 ==&lt;br /&gt;
This guide presents specific optimization techniques for the [[ARM]] Cortex-A8 processor and its dual-issue, in-order pipeline.&lt;br /&gt;
&lt;br /&gt;
== Use the ARMv7 movw/movt instructions ==&lt;br /&gt;
Newer ARM processors allow loading 32-bit values as two 16-bit immediates.  The movw instruction loads the lower 16 bits, and movt loads the upper 16 bits.  The movw instruction clears the upper 16 bits, so that 16-bit values can be loaded using a single instruction.  The movt instruction does not affect the lower bits.&lt;br /&gt;
&lt;br /&gt;
On older ARM processors, it was common to load 32-bit values with a PC-relative load.  This should be avoided because it may result in a cache miss.&lt;br /&gt;
&lt;br /&gt;
== Branch Prediction ==&lt;br /&gt;
There is a one-cycle stall in instruction fetch when a branch is predicted taken.  It is therefore preferable to structure code so that the most likely code path is the one where the branch is not taken.&lt;br /&gt;
&lt;br /&gt;
Unconditional branches may be mispredicted, and load instructions which follow branches may be decoded and cause cache accesses.  Avoid placing load instructions after branches unless you intend the CPU to prefetch the addresses they reference.&lt;br /&gt;
&lt;br /&gt;
The branch predictor has a call/return stack for jumps which reference r14 or stack operations using r13 which load the program counter.  For best performance, make sure any pop, mov pc,lr or bx lr jumps to the same location as was set by the matching bl instruction.  For non-return jumps, use a register other than r14.&lt;br /&gt;
&lt;br /&gt;
Although instructions are decoded in pairs, the branch predictor can only predict one branch target per cycle.  If you have a conditional branch which is immediately followed by another branch, and the first branch is likely to be taken, place a no-operation instruction between the branches to prevent decoding and prediction of the second branch.  Inserting NOPs is detrimental if the first branch is infrequently taken.&lt;br /&gt;
&lt;br /&gt;
== Dual-Issue Restrictions ==&lt;br /&gt;
Only one branch instruction can issue per cycle.  Only one load or store instruction can issue per cycle.  Instructions which write to the same register can not issue together.&lt;br /&gt;
&lt;br /&gt;
There is a one-cycle delay before any written register can be used as the address of a subsequent load or store instruction.  There is a one-cycle delay before any written register can be used by an instruction which performs a shift or rotation on that register.&lt;br /&gt;
&lt;br /&gt;
There is one cycle delay before the result of a load can be used.  In the aforementioned cases involving subsequent shift or rotate instructions, or the address of a load or store instruction, the total delay is two cycles.  &lt;br /&gt;
&lt;br /&gt;
Stores occur at the end of the pipeline and store instructions can issue in the same cycle as another instruction which writes the same register.  Similarly, conditional branches can issue in the same cycle as flag-setting instructions because the branch is not resolved until the following cycle.  In all other cases, instructions can not issue together if the second instruction depends on the results of the first.&lt;br /&gt;
&lt;br /&gt;
== Instruction pairing restrictions following a branch ==&lt;br /&gt;
The Cortex-A8 processor normally fetches two instructions per cycle and the branch predictor tests each against the global history buffer.  However, there is only one entry in the branch target buffer for each pair of instructions.  Therefore, branch instructions, and certain instructions which resemble branches, may adversely affect branch prediction when present in pairs.  To reduce the risk of branch misprediction, avoid pairing branch instructions with the following:&lt;br /&gt;
&lt;br /&gt;
* Branch instructions&lt;br /&gt;
* Load instructions, whether or not they write r15&lt;br /&gt;
* Arithmetic/logic instructions which do not set flags and do not have an immediate value, whether or not they write r15&lt;br /&gt;
&lt;br /&gt;
Flag-setting instructions can be used to avoid this restriction.  Additionally, MOV instructions that do not have immediate values can be replaced with ADD, SUB, ORR, or EOR instructions using zero as an immediate value.&lt;br /&gt;
&lt;br /&gt;
== Code alignment ==&lt;br /&gt;
Code alignment should be used with caution.  Alignment has the potential to increase performance, but may be detrimental in some circumstances.&lt;br /&gt;
&lt;br /&gt;
Because the instruction decoder always fetches 64-bit aligned words from the level-1 instruction cache, aligning code can improve instruction fetch and decode.  However, the global history buffer of the branch predictor is indexed by the low bits of the instruction address.  Excessive code alignment can result in a suboptimal distribution of entries in the branch history tables and increase branch misprediction.  Additionally, the speculative prefetch may retrieve and decode instructions used as padding, even if those instructions are never executed.  The types of instructions used as padding will affect the branch predictor as stated above, and this may affect the prefetch of code into the instruction cache.&lt;br /&gt;
&lt;br /&gt;
== NEON ==&lt;br /&gt;
As the manual states, passing data from NEON (and VFP) back to ARM takes at least 20 cycles, but there are some tricks that can be used. The vmov instruction itself that is passing the data will not cause any stalls (provided the needed NEON register is already available), the stall will actually happen on any ARM instruction that follows instead (including branches). This means that:&lt;br /&gt;
* Multiple &amp;quot;vmov.32 rX, dY[Z]&amp;quot; can be done back-to-back and only incur one stall after the whole sequence&lt;br /&gt;
* Additional NEON instructions can be issued after &amp;quot;vmov&amp;quot; without stalling (with enough instructions the stall can be completely avoided)&lt;br /&gt;
* Additional unrelated NEON instructions can be issued before &amp;quot;vmov&amp;quot; (to hide the latency of instruction that produces the source register data)&lt;br /&gt;
&lt;br /&gt;
Even though the VFP is not pipelined, the VFP vldr instructions are. &amp;quot;vldr s0, [r0]&amp;quot; will be faster than &amp;quot;vld1.32 {d0[0]}, [r0]&amp;quot; (2 vs 3 cycles, vldr also gives more flexible addressing mode). The same can't be said about &amp;quot;vmov sX, sY&amp;quot;, it waits for all previous instructions to complete before issuing.&lt;br /&gt;
&lt;br /&gt;
You should avoid any NEON loads that come from a location that has recently been written to. NEON does not have store forwarding, so this can cost dozens of cycles. This can happen unknowingly if you use unaligned loads, because they're performed with two aligned accesses. For example, if you have this sequence:&lt;br /&gt;
&lt;br /&gt;
loop:&lt;br /&gt;
  vld1.u32 { q0 }, [r0]&lt;br /&gt;
  vadd.u32 q0, q0, q1&lt;br /&gt;
  vst1.u32 { q0 }, [r0]!&lt;br /&gt;
&lt;br /&gt;
  subs r1, #1&lt;br /&gt;
  bne loop&lt;br /&gt;
&lt;br /&gt;
If 0 is unaligned, the next iteration of vld1.u32 will overlap with the previous iteration of vst1.u32, which will cause a stall. To avoid this situation you can reorder the loop so that the store happens one element behind.&lt;br /&gt;
&lt;br /&gt;
[[Category:Development]]&lt;br /&gt;
[[Category:Optimization]]&lt;br /&gt;
[[Category:Chipset]]&lt;/div&gt;</summary>
		<author><name>Exophase</name></author>
		
	</entry>
	<entry>
		<id>https://pandorawiki.org/index.php?title=DraStic_Compatibility_List&amp;diff=29635</id>
		<title>DraStic Compatibility List</title>
		<link rel="alternate" type="text/html" href="https://pandorawiki.org/index.php?title=DraStic_Compatibility_List&amp;diff=29635"/>
		<updated>2014-04-05T04:13:51Z</updated>

		<summary type="html">&lt;p&gt;Exophase: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;DraStic is a Nintendo DS Emulator created by Exophase for ARM devices such as the OpenPandora.&lt;br /&gt;
  &lt;br /&gt;
 * [http://repo.openpandora.org/?page=detail&amp;amp;app=DraStic Download]  &lt;br /&gt;
 * [http://exophase.devzero.co.uk/drastic_readme.txt Readme and Changelog]  &lt;br /&gt;
 * [http://boards.openpandora.org/index.php/topic/12038-emulator-drastic-nintendo-ds/page-1 Forum Thread]  &lt;br /&gt;
&lt;br /&gt;
The current version on the Repo is 2.2.1.0, released on March 28th, 2014. It identifies itself as &amp;quot;Version r2.2.1.0p&amp;quot; on the menu screen.&lt;br /&gt;
&lt;br /&gt;
 * [http://pandorawiki.org/DraStic_Compatibility_List_1.x Outdated Previous 1.x Version Compatibility List]&lt;br /&gt;
&lt;br /&gt;
==Compatibility==&lt;br /&gt;
'By default, games are uncompressed to RAM. 128MB+ compressed games have issues with this CC Pandoras because of limited RAM. 256MB compressed games may work on 512MB systems such as the Rebirth or 1GHz Pandora. 512MB compressed games won't decompress on any system. Compressed games of any size are not dependent on RAM, so should work the same on all systems. You can enable an option to compress to file instead of RAM to get around this problem, but it will make games take longer to start.' &lt;br /&gt;
&lt;br /&gt;
==Adding to the list==&lt;br /&gt;
Note: you can use the [http://repo.openpandora.org/?page=detail&amp;amp;app=drasticwikihelper-PowerGod Drastic Wiki Helper] application from the repo to automatically generate appropriate text to paste in the compatibility list below.&lt;br /&gt;
&lt;br /&gt;
Choose a playability color that reflects a game's best playability state. Also include the clockspeed at which you ran it, for whichever Pandora version you tested. Please also indicate in the name of the Game whether the version is US/EU/JP, since compatibility may differ depending on regions. Include the unzipped ROM size in base-2 mebibytes (16MB, 64MB, 128MB, etc.). If available please indicate the game ID figure, too. The Game ID figure should be 8 characters long and can usually be found by pressing Y on the rom selection menu.&lt;br /&gt;
&lt;br /&gt;
'''Don't''' post a redundant entry unless you are using a different Pandora model and the playability differs from an existing entry. If a game's playability gets worse (new bugs, new crashes) in a new DraStic version, update the entry and add that to notes.  Please don't copy entries from the old list into this one unless you first re-test the game using a recent version of DraStic and update the color and notes as required.&lt;br /&gt;
&lt;br /&gt;
Default frameskip is automatic and 4. Please record a comment if you use a different setting.&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot; style=&amp;quot;font-size: 90%; border:1px solid gray; border-collapse: collapse; text-align: left;&amp;quot;&lt;br /&gt;
|- style=&amp;quot;background: #ececec; text-align: center;&amp;quot;&lt;br /&gt;
!Playability&lt;br /&gt;
!Description&lt;br /&gt;
|- style=&amp;quot;background: #90FF90&amp;quot;&lt;br /&gt;
|Fullspeed&lt;br /&gt;
|Games with a '''green''' background run at fullspeed and are fully playable from start to finish. If frameskip is required, add to notes.&lt;br /&gt;
|- style=&amp;quot;background: #F3F781&amp;quot;&lt;br /&gt;
|Playable&lt;br /&gt;
|Games with a '''yellow''' background run slower than fullspeed, but are otherwise fully playable. Add problems/slowdowns to notes.&lt;br /&gt;
|- style=&amp;quot;background: #F7BE81&amp;quot;&lt;br /&gt;
|Incomplete&lt;br /&gt;
|Games with an '''orange''' background have playability issues and cannot be played from start to finish. This may include missing functionality (wifi) or game crashes. Add problems to notes.&lt;br /&gt;
|- style=&amp;quot;background: #F78181&amp;quot;&lt;br /&gt;
|Unplayable&lt;br /&gt;
|Games with a '''red''' background are unplayable. They either don't run at all, or don't get past the intro. Add any other oddities to notes.&lt;br /&gt;
|-&lt;br /&gt;
|N/A&lt;br /&gt;
|Games with a '''white''' background have not been fully tested. If you see one on this list, try it out and report back!&lt;br /&gt;
|}&lt;br /&gt;
If you are inclined, post your forum username at the end of your notes so you can be contacted by Exophase about further debugging your problems.&lt;br /&gt;
&lt;br /&gt;
==The Compatibility List==&lt;br /&gt;
&amp;lt;!-- template for new entries at bottom of list --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can sort the colums by clicking the table header (javascript required).&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable sortable&amp;quot; border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot; style=&amp;quot;font-size: 90%; border:1px solid gray; border-collapse: collapse; text-align: center; width: 100%;&amp;quot;&lt;br /&gt;
|- style=&amp;quot;background: #ececec&amp;quot;&lt;br /&gt;
! Game ID&lt;br /&gt;
! Game Name&lt;br /&gt;
! DraStic Version&lt;br /&gt;
! ROM Size&lt;br /&gt;
! Pandora Model&amp;lt;sup&amp;gt;[1]&amp;lt;/sup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
! Frequency&lt;br /&gt;
! Notes&lt;br /&gt;
! Status&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #90FF90&amp;quot;&lt;br /&gt;
|454d5341&lt;br /&gt;
|Super Mario 64 DS&lt;br /&gt;
|r2.1.0p&lt;br /&gt;
|16MiB&lt;br /&gt;
|1GHz&lt;br /&gt;
|900MHz&lt;br /&gt;
|Minimal graphical tears; almost none; other than that seems to plays perfectly. :(knightron)&lt;br /&gt;
|Green&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #90FF90&amp;quot;&lt;br /&gt;
|454c4759&lt;br /&gt;
|Geometry Wars - Galaxies&lt;br /&gt;
|r2.1.3p&lt;br /&gt;
|64MiB&lt;br /&gt;
|1Ghz&lt;br /&gt;
|1000Mhz&lt;br /&gt;
|Works very well.  (ekianjo)&lt;br /&gt;
| Green&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #F3F781&amp;quot;&lt;br /&gt;
|55595241&lt;br /&gt;
|Rayman DS&lt;br /&gt;
|r2.1.0p&lt;br /&gt;
|32MiB&lt;br /&gt;
|1GHz&lt;br /&gt;
|900MHz&lt;br /&gt;
|Very choppy sound often, and frameskip choppyness too. :(knightron)&lt;br /&gt;
|Yellow&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #90FF90&amp;quot;&lt;br /&gt;
|50445441&lt;br /&gt;
|42 All Time Classics/Clubhouse Games (E)&lt;br /&gt;
|r2.1.0p&lt;br /&gt;
|16MiB&lt;br /&gt;
|1GHz&lt;br /&gt;
|900MHz&lt;br /&gt;
|Plays fine with frameskip 2&lt;br /&gt;
|Green&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #90FF90&amp;quot;&lt;br /&gt;
|45575941&lt;br /&gt;
|Yoshis Island DS&lt;br /&gt;
|r2.1.0p&lt;br /&gt;
|32MiB&lt;br /&gt;
|1GHz&lt;br /&gt;
|900MHz&lt;br /&gt;
|Seems to play perfectly. :(Knightron)&lt;br /&gt;
|Green&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #90FF90&amp;quot;&lt;br /&gt;
|45474443&lt;br /&gt;
|Disgaea DS (U)&lt;br /&gt;
|r2.1.3p&lt;br /&gt;
|64MiB&lt;br /&gt;
|1Ghz&lt;br /&gt;
|1000Mhz&lt;br /&gt;
|runs very well overall. No issue detected. (ekianjo)&lt;br /&gt;
| Green&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #F3F781&amp;quot;&lt;br /&gt;
|50425341&lt;br /&gt;
|Snowboard Kids&lt;br /&gt;
|r2.1.0p&lt;br /&gt;
|64MiB&lt;br /&gt;
|1GHz&lt;br /&gt;
|900MHz&lt;br /&gt;
|Runs at full speed but has constant choppy sound during races. :(Knightron)&lt;br /&gt;
|Yellow&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #90FF90&amp;quot;&lt;br /&gt;
|45455341&lt;br /&gt;
|Children of Mana&lt;br /&gt;
|r2.1.0p&lt;br /&gt;
|64MiB&lt;br /&gt;
|1GHz&lt;br /&gt;
|900MHz&lt;br /&gt;
|Seems to play perfectly. :(Knightron)&lt;br /&gt;
|Green&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #90FF90&amp;quot;&lt;br /&gt;
|45555159&lt;br /&gt;
|Chrono Trigger&lt;br /&gt;
|r2.1.0p&lt;br /&gt;
|128MiB&lt;br /&gt;
|1GHz&lt;br /&gt;
|900MHz&lt;br /&gt;
|Seems to run perfect. I did not play long enough to test cut scenes. :(Knightron)&lt;br /&gt;
|Green&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #90FF90&amp;quot;&lt;br /&gt;
|45445741&lt;br /&gt;
|Diddy Kong Racing DS&lt;br /&gt;
|r2.1.0p&lt;br /&gt;
|32MiB&lt;br /&gt;
|1GHz&lt;br /&gt;
|900MHz&lt;br /&gt;
|A couple of graphical bugs in a few places, but seems close to perfect. :(Knightron)&lt;br /&gt;
|Green&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #90FF90&amp;quot;&lt;br /&gt;
|4a554a41&lt;br /&gt;
|Jump Ultimate Stars (English patched)&lt;br /&gt;
|r2.1.0p&lt;br /&gt;
|62.9MiB&lt;br /&gt;
|1GHz&lt;br /&gt;
|900MHz&lt;br /&gt;
|Seems to play perfectly. :(Knightron)&lt;br /&gt;
|Green&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #F3F781&amp;quot;&lt;br /&gt;
|45475049&lt;br /&gt;
|Pokemon SoulSilver&lt;br /&gt;
|r2.1.0p&lt;br /&gt;
|128MiB&lt;br /&gt;
|1GHz&lt;br /&gt;
|900MHz&lt;br /&gt;
|Slight graphical tearing. Lags a little when entering buildings ect. Other than that, it seems very playable. :(Knightron)&lt;br /&gt;
|Yellow&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #90FF90&amp;quot;&lt;br /&gt;
|45484d41&lt;br /&gt;
|Metroid Prime Hunters&lt;br /&gt;
|r2.1.0p&lt;br /&gt;
|64MiB&lt;br /&gt;
|1GHz&lt;br /&gt;
|900MHz&lt;br /&gt;
|Seems close to perfect. Full speed most of the time, but when lots of enemies are fireing at you, it slows down a little. May encounter bigger issues further into the game. :(Knightron)&lt;br /&gt;
|Green&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #90FF90&amp;quot;&lt;br /&gt;
|45524341&lt;br /&gt;
|Sprung The Dating Game&lt;br /&gt;
|r2.1.0p&lt;br /&gt;
|32MiB&lt;br /&gt;
|1GHz&lt;br /&gt;
|900MHz&lt;br /&gt;
|Seems to play perfectly. :(Knightron)&lt;br /&gt;
|Green&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #F7BE81&amp;quot;&lt;br /&gt;
|454a4c43&lt;br /&gt;
|Mario and Luigi Bowsers Inside Story&lt;br /&gt;
|r2.1.0p&lt;br /&gt;
|128MiB&lt;br /&gt;
|1GHz&lt;br /&gt;
|900MHz&lt;br /&gt;
|Plays pretty close to perfect, but freezes during the first fight, while playing as Bowser. :(knightron)&lt;br /&gt;
|Orange&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #90FF90&amp;quot;&lt;br /&gt;
|45355659&lt;br /&gt;
|Dragon Quest V Hand of the Heavenly Bride&lt;br /&gt;
|r2.1.0p&lt;br /&gt;
|128MiB&lt;br /&gt;
|1GHz&lt;br /&gt;
|900MHz&lt;br /&gt;
|Seems to play close to perfectly, very slight choppy inconsistancy between two screens, but not as bad as DQIV. :(Knightron)&lt;br /&gt;
|Green&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #90FF90&amp;quot;&lt;br /&gt;
|45425742&lt;br /&gt;
|Plants vs Zombies&lt;br /&gt;
|r2.1.0p&lt;br /&gt;
|64MiB&lt;br /&gt;
|1GHz&lt;br /&gt;
|900MHz&lt;br /&gt;
|Seems to play perfectly. :(Knightron)&lt;br /&gt;
|Green&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #90FF90&amp;quot;&lt;br /&gt;
|454b5441&lt;br /&gt;
|Kirby Canvas Curse&lt;br /&gt;
|r2.1.0p&lt;br /&gt;
|64MiB&lt;br /&gt;
|1GHz&lt;br /&gt;
|900MHz&lt;br /&gt;
|Seems to play perfectly. :(Knightron)&lt;br /&gt;
|Green&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #90FF90&amp;quot;&lt;br /&gt;
|4a534259&lt;br /&gt;
|Soma Bringer (English patched)&lt;br /&gt;
|r2.1.0p&lt;br /&gt;
|122MiB&lt;br /&gt;
|1GHz&lt;br /&gt;
|900MHz&lt;br /&gt;
|Seems to play perfectly. :(Knightron)&lt;br /&gt;
|Green&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #90FF90&amp;quot;&lt;br /&gt;
|45564959&lt;br /&gt;
|Dragon Quest IV Chapters of the Chosen&lt;br /&gt;
|r2.1.0p&lt;br /&gt;
|128MiB&lt;br /&gt;
|1GHz&lt;br /&gt;
|900MHz&lt;br /&gt;
|It can apear a little choppy when playing with vertical screens, but still plays very well: I switch it to one screen mode. :(Knightron)&lt;br /&gt;
|Green&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #90FF90&amp;quot;&lt;br /&gt;
|45464641&lt;br /&gt;
|Final Fantasy III&lt;br /&gt;
|r2.1.0p&lt;br /&gt;
|128MiB&lt;br /&gt;
|1GHz&lt;br /&gt;
|900MHz&lt;br /&gt;
|Plays pretty damn close to perfect. :(Knightron)&lt;br /&gt;
|Green&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #F3F781&amp;quot;&lt;br /&gt;
|45344659&lt;br /&gt;
|Final Fantasy IV&lt;br /&gt;
|r2.1.0p&lt;br /&gt;
|128MiB&lt;br /&gt;
|1GHz&lt;br /&gt;
|900MHz&lt;br /&gt;
|Plays at full speed, but has choppy sound quite often. :(Knightron)&lt;br /&gt;
|Yellow&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #F7BE81&amp;quot;&lt;br /&gt;
|4a545941&lt;br /&gt;
|Tales Of Innocence (English Patched)&lt;br /&gt;
|r2.1.0p&lt;br /&gt;
|128MiB&lt;br /&gt;
|1GHz&lt;br /&gt;
|900MHz&lt;br /&gt;
|Plays at full speed, but there are major graphical issues that make the game very hard to follow. :(Knightron)&lt;br /&gt;
|Orange&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #90FF90&amp;quot;&lt;br /&gt;
|454b5341&lt;br /&gt;
|Lost in Blue&lt;br /&gt;
|r2.1.0p&lt;br /&gt;
|64MiB&lt;br /&gt;
|1GHz&lt;br /&gt;
|900MHz&lt;br /&gt;
|Plays almost perfectly, just a few very minor graphical and sound bugs in a few spots. Microphone fails sometimes but works again once Drastic is restarted. Game crashes occasionally when atempting to light the fire or build something. At the moment, I recommend regular saving through savestates just in case. :(Knightron)&lt;br /&gt;
|Green&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #F78181&amp;quot;&lt;br /&gt;
|45514459&lt;br /&gt;
|Dragon Quest IX Sentinels of the Starry Skies&lt;br /&gt;
|r2.1.0p&lt;br /&gt;
|22.3MiB&lt;br /&gt;
|1GHz&lt;br /&gt;
|900MHz&lt;br /&gt;
|Game crashes on boot. :(Knightron)&lt;br /&gt;
|Red&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #90FF90&amp;quot;&lt;br /&gt;
|454d5241&lt;br /&gt;
|Mario and Luigi Partners in Time&lt;br /&gt;
|r2.1.0p&lt;br /&gt;
|64MiB&lt;br /&gt;
|1GHz&lt;br /&gt;
|900MHz&lt;br /&gt;
|Seems to play perfectly. :(Knightron)&lt;br /&gt;
|Green&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #90FF90&amp;quot;&lt;br /&gt;
|45495941&lt;br /&gt;
|Yoshi Touch &amp;amp; Go&lt;br /&gt;
|r2.1.0p&lt;br /&gt;
|16MiB&lt;br /&gt;
|1GHz&lt;br /&gt;
|900MHz&lt;br /&gt;
|This Game Apears to play perfectly, but it has major problems when the Pandora is put to sleep. :(Knightron)&lt;br /&gt;
|Green&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #90FF90&amp;quot;&lt;br /&gt;
|454b5342&lt;br /&gt;
|9 Hours, 9 Persons, 9 Doors&lt;br /&gt;
|r2.0.1p&lt;br /&gt;
|128MiB&lt;br /&gt;
|Rebirth&lt;br /&gt;
|850&lt;br /&gt;
|Plays at full speed.&lt;br /&gt;
|Green&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #90FF90&amp;quot;&lt;br /&gt;
|45574b59&lt;br /&gt;
|Kirby - Super Star Ultra&lt;br /&gt;
|r2.0.1p&lt;br /&gt;
|128MiB&lt;br /&gt;
|CC&lt;br /&gt;
|800&lt;br /&gt;
|Plays at full speed.&lt;br /&gt;
|Green&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #90FF90&amp;quot;&lt;br /&gt;
|45365359&lt;br /&gt;
|Civilization Revolution DS&lt;br /&gt;
|r2.0.1p&lt;br /&gt;
|64MiB&lt;br /&gt;
|Rebirth&lt;br /&gt;
|825MHz&lt;br /&gt;
|Fully playable. (Long firststart ~62sec.)&lt;br /&gt;
|Green&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #90FF90&amp;quot;&lt;br /&gt;
|45365359&lt;br /&gt;
|Barnyard Blast: Swine of the Night&lt;br /&gt;
|r2.0.1p&lt;br /&gt;
|8MiB&lt;br /&gt;
|1GHz&lt;br /&gt;
|1.1GHz&lt;br /&gt;
|Works Completely fine. No Lag or Graphical Issues even on cut scenes&lt;br /&gt;
|Green&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #90FF90&amp;quot;&lt;br /&gt;
|45454650&lt;br /&gt;
|Fire Emblem: Shadow Dragon (E)&lt;br /&gt;
|r2.1.3p&lt;br /&gt;
|64MiB&lt;br /&gt;
|1GHz&lt;br /&gt;
|900MHz&lt;br /&gt;
|Runs fine since r2.1.3p&lt;br /&gt;
|Green&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #90FF90&amp;quot;&lt;br /&gt;
|4a564942&lt;br /&gt;
|Ivy the Kiwi (J)&lt;br /&gt;
|r2.1.3p&lt;br /&gt;
|8MiB&lt;br /&gt;
|1GHz&lt;br /&gt;
|900MHz&lt;br /&gt;
|Runs fine since r2.1.0p.  Doesn't even need frameskip at 900Mhz.&lt;br /&gt;
|Green&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #90FF90&amp;quot;&lt;br /&gt;
|50505841&lt;br /&gt;
|Picross DS (E)&lt;br /&gt;
|r2.1.3p&lt;br /&gt;
|32MiB&lt;br /&gt;
|1GHz&lt;br /&gt;
|600MHz&lt;br /&gt;
|Very minor graphical glitch where at end of level the top screen image transitions from monochrome to (animated) colour - one pixel line of monochrome image is left above the animated image.&lt;br /&gt;
|Green&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #90FF90&amp;quot;&lt;br /&gt;
|50503643&lt;br /&gt;
|Picross 3D (E)&lt;br /&gt;
|r2.1.3p&lt;br /&gt;
|32MiB&lt;br /&gt;
|1GHz&lt;br /&gt;
|600MHz&lt;br /&gt;
|Absolutely perfect since version r2.1.0p&lt;br /&gt;
|Green&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #F3F781&amp;quot;&lt;br /&gt;
|50344759&lt;br /&gt;
|Suikoden Tierkreis&lt;br /&gt;
|r2.0.1p&lt;br /&gt;
|256MiB&lt;br /&gt;
|Rebirth&lt;br /&gt;
|900MHz&lt;br /&gt;
|Sound sometimes a bit laggy during battle. (tested for 40min only)&lt;br /&gt;
|Yellow&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #90FF90&amp;quot;&lt;br /&gt;
|45375341&lt;br /&gt;
|Summon Night, Twin Age&lt;br /&gt;
|r2.0.1p&lt;br /&gt;
|128MiB&lt;br /&gt;
|Rebirth&lt;br /&gt;
|900MHz&lt;br /&gt;
|nice. (tested for 10h)&lt;br /&gt;
|Green&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #F3F781&amp;quot;&lt;br /&gt;
|404c5741&lt;br /&gt;
|The World Ends With You (E)&lt;br /&gt;
|r2.0.1p&lt;br /&gt;
|128MiB&lt;br /&gt;
|Rebirth&lt;br /&gt;
|900MHz&lt;br /&gt;
|Ran fine as far as the end of the first day. (not further tested.)&lt;br /&gt;
|Yellow&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #90FF90&amp;quot;&lt;br /&gt;
|45434d41&lt;br /&gt;
|MarioKart DS (US)&lt;br /&gt;
|r2.1.3p&lt;br /&gt;
|32MiB&lt;br /&gt;
|1GHz&lt;br /&gt;
|1050MHz&lt;br /&gt;
|Runs fine with frameskip&lt;br /&gt;
|Green&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #90FF90&amp;quot;&lt;br /&gt;
|45444e41&lt;br /&gt;
|Brain Age - Train Your Brain in Minutes a Day! (v01)&lt;br /&gt;
|r2.1.0p&lt;br /&gt;
|16MiB&lt;br /&gt;
|1Ghz&lt;br /&gt;
|800 Mhz&lt;br /&gt;
|Works great. (PowerGod)&lt;br /&gt;
|Green&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #90FF90&amp;quot;&lt;br /&gt;
|50444e41&lt;br /&gt;
|Dr Kawashima's Brain Training - How Old Is Your Brain&lt;br /&gt;
|r2.1.0p&lt;br /&gt;
|16MiB&lt;br /&gt;
|1Ghz&lt;br /&gt;
|800 Mhz&lt;br /&gt;
|Works great. (PowerGod)&lt;br /&gt;
|Green&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #F3F781&amp;quot;&lt;br /&gt;
|455a4443&lt;br /&gt;
|Dragon Ball - Origins&lt;br /&gt;
|r2.1.6.1p&lt;br /&gt;
|64MiB&lt;br /&gt;
|1Ghz&lt;br /&gt;
|800 Mhz&lt;br /&gt;
|Playable with some lag. (PowerGod)&lt;br /&gt;
|Yellow&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #90FF90&amp;quot;&lt;br /&gt;
|45503743&lt;br /&gt;
|Peggle Dual Shot&lt;br /&gt;
|r2.1.3p&lt;br /&gt;
|64MiB&lt;br /&gt;
|1Ghz&lt;br /&gt;
|750MHz&lt;br /&gt;
|Perfect play, fluid motion, just like the real thing. :(kumaki+levi)&lt;br /&gt;
|Green&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #F3F781&amp;quot;&lt;br /&gt;
|45533241&lt;br /&gt;
|Dragon Ball Z - Supersonic Warriors 2&lt;br /&gt;
|r2.0.1p&lt;br /&gt;
|64MiB&lt;br /&gt;
|1Ghz&lt;br /&gt;
|800 Mhz&lt;br /&gt;
|Playable with some lag. (PowerGod)&lt;br /&gt;
|Yellow&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #F3F781&amp;quot;&lt;br /&gt;
|45414441&lt;br /&gt;
|Pokemon Diamond Version (v13)&lt;br /&gt;
|r2.0.1p&lt;br /&gt;
|64MiB&lt;br /&gt;
|1Ghz&lt;br /&gt;
|800 Mhz&lt;br /&gt;
|No text in the introduction tutorial. Only played it a bit. (PowerGod)&lt;br /&gt;
(Edit by knightron: text is now played in DraStic 2.1.0p)&lt;br /&gt;
|Yellow&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #90FF90&amp;quot;&lt;br /&gt;
|45433643&lt;br /&gt;
|Infinite Space&lt;br /&gt;
|r2.1.3p&lt;br /&gt;
|256MiB&lt;br /&gt;
|1Ghz&lt;br /&gt;
|1050Mhz&lt;br /&gt;
|Plays well.  Graphical glitches in the attract mode. Played only as far as the first spaceport. (levi)&lt;br /&gt;
|Green&lt;br /&gt;
|- style=&amp;quot;background: #90FF90&amp;quot;&lt;br /&gt;
|50385243&lt;br /&gt;
|Crash - Mind Over Mutant (U)&lt;br /&gt;
|r2.1.3p&lt;br /&gt;
|64MiB&lt;br /&gt;
|CC&lt;br /&gt;
|800Mhz&lt;br /&gt;
|works perfect at default (dsleaf67)&lt;br /&gt;
| Green&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #90FF90&amp;quot;&lt;br /&gt;
|50595943&lt;br /&gt;
|Giana Sisters DS (U)&lt;br /&gt;
|r2.1.3p&lt;br /&gt;
|8MiB&lt;br /&gt;
|CC&lt;br /&gt;
|800Mhz&lt;br /&gt;
|works perfect (dsleaf67)&lt;br /&gt;
| Green&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #F3F781&amp;quot;&lt;br /&gt;
|50595943&lt;br /&gt;
|Giana Sisters DS (E)&lt;br /&gt;
|r2.1.6.1p&lt;br /&gt;
|8MiB&lt;br /&gt;
|1Ghz&lt;br /&gt;
|800Mhz&lt;br /&gt;
|Playable, but there are issues with the microphone in later levels and it should be disabled (to use the jump button instead) in order to use the bubble. UPDATE: actually seems something related more to the DraStic session than to the game itself, because when the issue happened I made a savestate, and even reloading it had the same issue, but after restarting DraStic that savestate is working right (PowerGod)&lt;br /&gt;
| Yellow&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #90FF90&amp;quot;&lt;br /&gt;
|45563241&lt;br /&gt;
|M&amp;amp;M's - Break'em (U)&lt;br /&gt;
|r2.1.3p&lt;br /&gt;
|8MiB&lt;br /&gt;
|CC&lt;br /&gt;
|800Mhz&lt;br /&gt;
|works great only has minor sound issue at start (dsleaf67)&lt;br /&gt;
| Green&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #90FF90&amp;quot;&lt;br /&gt;
|45575041&lt;br /&gt;
|Pac-Man World 3 (U)&lt;br /&gt;
|r2.1.3p&lt;br /&gt;
|32MiB&lt;br /&gt;
|CC&lt;br /&gt;
|800Mhz&lt;br /&gt;
|works good some slowdowns but very playable (dsleaf67)&lt;br /&gt;
| Green&lt;br /&gt;
|- style=&amp;quot;background: #F3F781&amp;quot;&lt;br /&gt;
|454a5141&lt;br /&gt;
|Crash of the Titans (U)&lt;br /&gt;
|r2.1.3p&lt;br /&gt;
|128MiB&lt;br /&gt;
|CC&lt;br /&gt;
|800Mhz&lt;br /&gt;
|playable with choppy sound and some slow downs (dsleaf67)&lt;br /&gt;
| Yellow&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #F3F781&amp;quot;&lt;br /&gt;
|50394643&lt;br /&gt;
|FIFA 09 (U)&lt;br /&gt;
|r2.1.3p&lt;br /&gt;
|32MiB&lt;br /&gt;
|CC&lt;br /&gt;
|800Mhz&lt;br /&gt;
|playable with sound issues (dsleaf67)&lt;br /&gt;
| Yellow&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #90FF90&amp;quot;&lt;br /&gt;
|45413541&lt;br /&gt;
|Golden Compass, The (U)&lt;br /&gt;
|r2.1.3p&lt;br /&gt;
|64MiB&lt;br /&gt;
|CC&lt;br /&gt;
|800Mhz&lt;br /&gt;
|works good minor sound issues (dsleaf67)&lt;br /&gt;
| Green&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #90FF90&amp;quot;&lt;br /&gt;
|45424a59&lt;br /&gt;
|LEGO Batman - The Videogame (U)&lt;br /&gt;
|r2.1.3p&lt;br /&gt;
|64MiB&lt;br /&gt;
|CC&lt;br /&gt;
|800Mhz&lt;br /&gt;
|works great (dsleaf67)&lt;br /&gt;
| Green&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #F7BE81&amp;quot;&lt;br /&gt;
|50494b42&lt;br /&gt;
|Legend of Zelda - Spirit Tracks, The (E)&lt;br /&gt;
|r2.1.6.1p&lt;br /&gt;
|128MiB&lt;br /&gt;
|1Ghz&lt;br /&gt;
|1100Mhz&lt;br /&gt;
|when you're supposed to use the microphone to blow in the flute it doesn't work. (frostfall)&lt;br /&gt;
| Orange&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #F3F781&amp;quot;&lt;br /&gt;
|45343243&lt;br /&gt;
|Phantasy Star 0 &lt;br /&gt;
|r2.1.6.1p&lt;br /&gt;
|128MiB&lt;br /&gt;
|Rebirth&lt;br /&gt;
|600Mhz&lt;br /&gt;
|Nice gameplay, but the sound with some problem, 80~90% in battle. The game crash if you are using saves state and try to feed the MAG, if you use normal save and reset the game work fine. (MarTinazzI)&lt;br /&gt;
| Yellow&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #90FF90&amp;quot;&lt;br /&gt;
|454d3341&lt;br /&gt;
|Dynasty Warriors DS - Fighter's Battle (E)&lt;br /&gt;
|r2.1.6.1p&lt;br /&gt;
|128MiB&lt;br /&gt;
|Rebirth&lt;br /&gt;
|600Mhz&lt;br /&gt;
| (MarTinazzI)&lt;br /&gt;
| Green&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #90FF90&amp;quot;&lt;br /&gt;
|454d4241&lt;br /&gt;
|Bomberman (E)&lt;br /&gt;
|r2.1.6.1p&lt;br /&gt;
|8MiB&lt;br /&gt;
|Rebirth&lt;br /&gt;
|600Mhz&lt;br /&gt;
| (MarTinazzI)&lt;br /&gt;
| Green&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #90FF90&amp;quot;&lt;br /&gt;
|504e4241&lt;br /&gt;
|Bomberman Story DS (U)&lt;br /&gt;
|r2.1.6.1p&lt;br /&gt;
|128MiB&lt;br /&gt;
|Rebirth&lt;br /&gt;
|600Mhz&lt;br /&gt;
| (MarTinazzI)&lt;br /&gt;
| Green&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #90FF90&amp;quot;&lt;br /&gt;
|45584241&lt;br /&gt;
|Bomberman Land Touch! &lt;br /&gt;
|r2.1.6.1p&lt;br /&gt;
|32MiB&lt;br /&gt;
|Rebirth&lt;br /&gt;
|600Mhz&lt;br /&gt;
| (MarTinazzI)&lt;br /&gt;
| Green&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #90FF90&amp;quot;&lt;br /&gt;
|45324259&lt;br /&gt;
|Bomberman Land Touch! 2 &lt;br /&gt;
|r2.1.6.1p&lt;br /&gt;
|32MiB&lt;br /&gt;
|Rebirth&lt;br /&gt;
|600Mhz&lt;br /&gt;
| (MarTinazzI)&lt;br /&gt;
| Green&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #F3F781&amp;quot;&lt;br /&gt;
|45435741&lt;br /&gt;
|Drone Tactics (U)&lt;br /&gt;
|r2.1.6.1p&lt;br /&gt;
|64MiB&lt;br /&gt;
|Rebirth&lt;br /&gt;
|600Mhz&lt;br /&gt;
|Only in battle scene run about 70~90% (MarTinazzI)&lt;br /&gt;
| Yellow&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #90FF90&amp;quot;&lt;br /&gt;
|454a5841&lt;br /&gt;
|Dungeon Explorer - Warriors of Ancient Arts (U)&lt;br /&gt;
|r2.1.6.1p&lt;br /&gt;
|64MiB&lt;br /&gt;
|Rebirth&lt;br /&gt;
|600Mhz&lt;br /&gt;
| (MarTinazzI)&lt;br /&gt;
| Green&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #F3F781&amp;quot;&lt;br /&gt;
|45474b59&lt;br /&gt;
|Kingdom Hearts - 358-2 Days &lt;br /&gt;
|r2.1.6.1p&lt;br /&gt;
|256MiB&lt;br /&gt;
|Rebirth&lt;br /&gt;
|600Mhz&lt;br /&gt;
|Run 75~90% and bad sound, but playable (MarTinazzI)&lt;br /&gt;
| Yellow&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #90FF90&amp;quot;&lt;br /&gt;
|45574b59&lt;br /&gt;
|Kirby - Super Star Ultra (U)&lt;br /&gt;
|r2.1.6.1p&lt;br /&gt;
|128MiB&lt;br /&gt;
|Rebirth&lt;br /&gt;
|600Mhz&lt;br /&gt;
| (MarTinazzI)&lt;br /&gt;
| Green&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #F3F781&amp;quot;&lt;br /&gt;
|454e4c41&lt;br /&gt;
|Lunar - Dragon Song (U)&lt;br /&gt;
|r2.1.6.1p&lt;br /&gt;
|32MiB&lt;br /&gt;
|Rebirth&lt;br /&gt;
|600Mhz&lt;br /&gt;
|Some lag on action select in battle, 70~90% but in far of the game seem all 100%, need test early game again. (MarTinazzI)&lt;br /&gt;
| Yellow&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #F78181&amp;quot;&lt;br /&gt;
|45555043&lt;br /&gt;
|Pokemon - Platinum Version (v10) (U)&lt;br /&gt;
|r2.1.6.1p&lt;br /&gt;
|128MiB&lt;br /&gt;
|Rebirth&lt;br /&gt;
|600Mhz&lt;br /&gt;
|bug on introduction. blinking screen and game stop (MarTinazzI)&lt;br /&gt;
| Red&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #90FF90&amp;quot;&lt;br /&gt;
|45555043&lt;br /&gt;
|Pokemon - Platinum Version (DE)&lt;br /&gt;
|r2.2.0.0p&lt;br /&gt;
|128MiB&lt;br /&gt;
|CC&lt;br /&gt;
|900Mhz&lt;br /&gt;
|some slowdowns, especially with Pokéfetch. However seem to run quite smooth at 900 Mhz.&lt;br /&gt;
| Green&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #F78181&amp;quot;&lt;br /&gt;
|4f415249&lt;br /&gt;
|Pokemon - White Version (DSi Enhanced)(USA) (U)&lt;br /&gt;
|r2.1.6.1p&lt;br /&gt;
|256MiB&lt;br /&gt;
|Rebirth&lt;br /&gt;
|600Mhz&lt;br /&gt;
|just close the game on introduction (MarTinazzI)&lt;br /&gt;
| Red&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #F78181&amp;quot;&lt;br /&gt;
|454c4859&lt;br /&gt;
|Time Hollow (U)&lt;br /&gt;
|r2.1.6.1p&lt;br /&gt;
|128MiB&lt;br /&gt;
|1Ghz&lt;br /&gt;
|975Mhz&lt;br /&gt;
|Game crashes at the beginning of Chapter 2, also ingame saves doesn't work at all (PowerGod)&lt;br /&gt;
| Red&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;!-- ^^^ INSERT THE ENTRIES UP HERE, BEFORE THE &amp;quot;|}&amp;quot; &amp;gt;&lt;br /&gt;
&amp;lt;!-- ----------------------------------------------- &amp;gt;&lt;br /&gt;
&amp;lt;!-- ----------------------------------------------- &amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- template for new entries, to add a color to an entry, simple choose ONE of these:&lt;br /&gt;
Green: &lt;br /&gt;
|- style=&amp;quot;background: #90FF90&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Yellow:&lt;br /&gt;
|- style=&amp;quot;background: #F3F781&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Orange:&lt;br /&gt;
|- style=&amp;quot;background: #F7BE81&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Red:&lt;br /&gt;
|- style=&amp;quot;background: #F78181&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Leave it at #x for white; invalid values do not change color;&lt;br /&gt;
&lt;br /&gt;
|- style=&amp;quot;background: #x&amp;quot;&lt;br /&gt;
|put the number&lt;br /&gt;
|put the name&lt;br /&gt;
|put the DraStic Version&lt;br /&gt;
|put the ROM Size&lt;br /&gt;
|put the Pandora Model&lt;br /&gt;
|put the Frequency&lt;br /&gt;
|put the Notes&lt;br /&gt;
|put the Status&lt;br /&gt;
&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Notes===&lt;br /&gt;
&lt;br /&gt;
1. Pandora model:&lt;br /&gt;
*  CC - OMAP3530 SoC@600Mhz stock, 256MiB RAM@166MHz&lt;br /&gt;
*  Rebirth - OMAP3530 SoC@600MHz stock, '''512MiB RAM'''@166MHz&lt;br /&gt;
*  1GHz - '''DM3730 SoC@1GHz stock''', 512MiB RAM@'''200Mhz'''&lt;br /&gt;
&lt;br /&gt;
[[Category:Emulators]]&lt;br /&gt;
[[Category: Compatibility]]&lt;br /&gt;
[[Category:List]]&lt;/div&gt;</summary>
		<author><name>Exophase</name></author>
		
	</entry>
	<entry>
		<id>https://pandorawiki.org/index.php?title=Kernel_interface&amp;diff=2460</id>
		<title>Kernel interface</title>
		<link rel="alternate" type="text/html" href="https://pandorawiki.org/index.php?title=Kernel_interface&amp;diff=2460"/>
		<updated>2010-06-21T00:50:46Z</updated>

		<summary type="html">&lt;p&gt;Exophase: /* Input */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Warning''': if your goal is just to write a game/program use higher level libraries/interfaces like SDL, Qt, X or similar for your own good (portability). It may be impossible to retain this layout on some major hardware revision, let's say Pandora 3000, and your program will break. Also this requires some level of Linux programming knowledge.&lt;br /&gt;
&lt;br /&gt;
In case you need to write low level code (you can't/don't want to use high level libs like SDL), you can use kernel interface. This is the recommended way to access hardware (as opposed to GP2X style of accessing chip registers by mmap'ing /dev/mem), because in case hardware changes are needed in future, they could be handled by kernel and all programs would still work. It also should allow several programs to work at the same time and should be more stable.&lt;br /&gt;
&lt;br /&gt;
==Input==&lt;br /&gt;
Buttons, keypad, touchscreen and nubs are all exposed through Linux event interface (EVDEV). All devices are represented by /dev/input/eventX files, which can be opened, read and queried (using ioctl calls). The reads can be synchronous (the read will only return when user does something, like presses the button), or asynchronous (the system will report what changed since the last time you asked).&lt;br /&gt;
&lt;br /&gt;
'''Warning''': don't hardcode device filenames in your program! For example, currently /dev/input/event2 represents game buttons, but in future it may become touchscreen. Scan input device names instead, example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
for (i = 0; 1; i++)&lt;br /&gt;
{&lt;br /&gt;
  sprintf(name, &amp;quot;/dev/input/event%i&amp;quot;, i);&lt;br /&gt;
  fd = open(name, O_RDONLY);&lt;br /&gt;
  if (fd &amp;lt; 0) break; /* no more devices */&lt;br /&gt;
  ioctl(fd, EVIOCGNAME(sizeof(name)), name);&lt;br /&gt;
  if (strcmp(name, &amp;quot;gpio-keys&amp;quot;) == 0)&lt;br /&gt;
    return fd; /* found the buttons! */&lt;br /&gt;
  close(fd); /* we don't need this device */&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List of device names and events they send:&lt;br /&gt;
{|border=1 cellpadding=2 cellspacing=0&lt;br /&gt;
|-&lt;br /&gt;
!name&lt;br /&gt;
!description&lt;br /&gt;
!event.type&lt;br /&gt;
!event.code&lt;br /&gt;
!event.value&lt;br /&gt;
|-&lt;br /&gt;
|keypad&lt;br /&gt;
|keypad&lt;br /&gt;
|EV_KEY&lt;br /&gt;
|KEY_0...KEY_Z, KEY_BACKSPACE, KEY_LEFTSHIFT, KEY_SPACE, KEY_ENTER, KEY_COMMA, KEY_DOT, KEY_FN&lt;br /&gt;
|0 - released, 1 - pressed, 2 - autorepeat event&lt;br /&gt;
|-&lt;br /&gt;
|gpio-keys&lt;br /&gt;
|game buttons&lt;br /&gt;
|EV_KEY&lt;br /&gt;
|KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT, KEY_MENU (Pandora button), KEY_LEFTALT (Start), KEY_LEFTCTRL (Select), KEY_END (Y/North), KEY_HOME (A/East), KEY_PAGEDOWN (X/South), KEY_END (B/West), KEY_RIGHTSHIFT (Shoulder L), KEY_RIGHTCTRL (Shoulder R), KEY_KPPLUS (Shoulder L2), KEY_KPMINUS (Shoulder R2), KEY_COFFEE (Hold)&lt;br /&gt;
|0 - released, 1 - pressed&lt;br /&gt;
|-&lt;br /&gt;
|gpio-keys&lt;br /&gt;
|lid state&lt;br /&gt;
|EV_SW&lt;br /&gt;
|SW_LID&lt;br /&gt;
|0 - closing, 1 - opening&lt;br /&gt;
|-&lt;br /&gt;
|touchscreen&lt;br /&gt;
|touchscreen&lt;br /&gt;
|EV_ABS&lt;br /&gt;
|ABS_X, ABS_Y, ABS_PRESSURE&lt;br /&gt;
|varies, use calibration data&lt;br /&gt;
|-&lt;br /&gt;
|nub0&lt;br /&gt;
|left nub&lt;br /&gt;
|EV_ABS&lt;br /&gt;
|ABS_X, ABS_Y&lt;br /&gt;
| -256 (Left/Up) ...0... +256 (Right/Down)&lt;br /&gt;
|-&lt;br /&gt;
|nub1&lt;br /&gt;
|right nub&lt;br /&gt;
|EV_ABS&lt;br /&gt;
|ABS_X, ABS_Y&lt;br /&gt;
| -256 (Left/Up) ...0... +256 (Right/Down)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Sample code:&amp;lt;br&amp;gt;&lt;br /&gt;
[http://beagleboard.googlecode.com/files/evtest.c evtest.c]&lt;br /&gt;
[http://git.openpandora.org/cgi-bin/gitweb.cgi?p=pandora-misc.git;a=blob;f=op_test_inputs.c;hb=HEAD op_test_inputs.c]&lt;br /&gt;
&lt;br /&gt;
===Touchscreen===&lt;br /&gt;
Event interface returns uncalibrated values directly from driver, so you need to use tslib or manage calibration yourself (using data from /etc/pointercal).&lt;br /&gt;
&lt;br /&gt;
==Sound==&lt;br /&gt;
Pandora uses ALSA, but it has OSS emulation enabled too, so GP2X code should work.&lt;br /&gt;
&lt;br /&gt;
==Video==&lt;br /&gt;
===Architecture===&lt;br /&gt;
Framebuffer device (/dev/fbX) is supported. There are 3 framebuffers available (/dev/fb0, /dev/fb1 and /dev/fb2), which represent 3 graphics/video layers on OMAP3 by default (but can be reconfigured). Only /dev/fb0 is enabled by default.&lt;br /&gt;
&lt;br /&gt;
OMAP3 display subsystem is controlled by a driver known as DSS2, which has various controls available on /sys/devices/platform/omapdss/ (but they are not meant to be changed by programs, so they are root writable only). The driver exposes 3 layers (called overlays) and 2 displays. Overlays 1 and 2 can perform hardware scaling on the fly using 5-tap poly-phase filter, overlay0 can not. Displays 0 and 1 represent LCD and TV respectively. By default the 3 framebuffers (/dev/fbX) are redirected to 3 overlays, which all output to the LCD. This configuration is not meant to be changed by programs, only firmware should manage these.&lt;br /&gt;
&lt;br /&gt;
===Basic usage===&lt;br /&gt;
====framebuffer interface====&lt;br /&gt;
Framebuffers can be accessed Linux fbdev interface:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
fbdev = open(&amp;quot;/dev/fb0&amp;quot;, O_RDONLY);&lt;br /&gt;
buffer = mmap(0, 800*480*2, PROT_WRITE, MAP_SHARED, fbdev, 0);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
(this is basic example, no error checks)&lt;br /&gt;
&lt;br /&gt;
the returned pointer can be used to draw on the screen.&lt;br /&gt;
&lt;br /&gt;
Be sure to #include &amp;lt;linux/fb.h&amp;gt; to get access to the FB device ioctl interface, and &amp;lt;sys/ioctl.h&amp;gt; for access to ioctl itself.&lt;br /&gt;
&lt;br /&gt;
====double buffering====&lt;br /&gt;
This can be achieved using FBIOPAN_DISPLAY ioctl system call. For this you need to mmap framebuffer of double size&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
buffer1 = mmap(0, 800*480*2 * 2, PROT_WRITE, MAP_SHARED, fbdev, 0);&lt;br /&gt;
buffer2 = (char *)mem + 800*480*2;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then to display buffer2 you would call:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
struct fb_var_screeninfo fbvar;&lt;br /&gt;
ioctl(fbdev, FBIOGET_VSCREENINFO, &amp;amp;fbvar);&lt;br /&gt;
fbvar.yoffset = 480;&lt;br /&gt;
ioctl(fbdev, FBIOPAN_DISPLAY, &amp;amp;fbvar);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
going back to buffer1 would be repeating above with fbvar.yoffset = 0. Tripple or quad buffering can be implemented using the same technique.&lt;br /&gt;
&lt;br /&gt;
====vertical sync====&lt;br /&gt;
Linux has standard FBIO_WAITFORVSYNC for this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
int arg = 0;&lt;br /&gt;
ioctl(fbdev, FBIO_WAITFORVSYNC, &amp;amp;arg);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
be sure to pass argument value 0 or it will not work.&lt;br /&gt;
&lt;br /&gt;
Currently FBIO_WAITFORVSYNC is not defined in &amp;lt;linux/fb.h&amp;gt;, although this is in the process of modification. For now, define in the following manner:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#ifndef FBIO_WAITFORVSYNC&lt;br /&gt;
  #define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32)&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====hardware scaling====&lt;br /&gt;
Overlay1 (/dev/fb1) can be used to achieve hardware scaling. Technically overlay2 (fb2) can be used for this too, but it is planned to be used by the system for TV-out functionality, so don't use it. The overlay is configured using series of standard and OMAP specific ioctl calls, but the system ships with some tools to achieve this from scripts too. This way the framebuffer can be set up for some arbitrary size (say 320x240) and can output to LCD as 800x480 with hardware scaling.&lt;br /&gt;
Here is an example script:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ofbset -fb /dev/fb1 -pos 0 0 -size 800 480 -mem 307200 -en 1&lt;br /&gt;
fbset -fb /dev/fb1 -g 320 240 320 480 16&lt;br /&gt;
&lt;br /&gt;
./your_app_here&lt;br /&gt;
&lt;br /&gt;
ofbset -fb /dev/fb1 -pos 0 0 -size 0 0 -mem 0 -en 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What it does:&lt;br /&gt;
* allocates OMAP DSS layer, asks video output to be 800x480 at position 0,0 (could set it to 640x480 at 80,0 instead to get centered 2x scaling of 320x240). 307200 bytes of video memory are allocated for 2 320x240 16bpp screens (for doublebuffering).&lt;br /&gt;
* sets video mode to 320x240@16bpp, virtual resolution 320x480 for doublebuffering.&lt;br /&gt;
* runs your app&lt;br /&gt;
* cleans the video layer on exit&lt;br /&gt;
&lt;br /&gt;
Now the program can act as if works with 16bpp screen.&lt;br /&gt;
&lt;br /&gt;
==LEDs and backlight==&lt;br /&gt;
The LEDs can be controlled via /sys/class/leds/, and then a file [http://www.gp32x.com/board/index.php?s=&amp;amp;showtopic=45309&amp;amp;view=findpost&amp;amp;p=673593]:&lt;br /&gt;
* pandora::sd1&lt;br /&gt;
* pandora::sd2&lt;br /&gt;
* pandora::charger&lt;br /&gt;
* pandora::power&lt;br /&gt;
* pandora::bluetooth&lt;br /&gt;
* pandora::wifi&lt;br /&gt;
* pandora::keypad_bl&lt;br /&gt;
Backlight can be controlled via /sys/class/backlight/.&lt;br /&gt;
&lt;br /&gt;
==Misc==&lt;br /&gt;
Some things can be controlled through files in /proc/pandora/:&lt;br /&gt;
* /proc/pandora/cpu_mhz_max - if [http://www.kernel.org/pub/linux/utils/kernel/cpufreq/cpufreq.html cpufreq] is enabled, sets maximum allowed cpu clock, if not, just sets CPU clock to value supplied (echo 600 &amp;gt; /proc/pandora/cpu_mhz_max). Might also just use cpufreq parameters themselves.&lt;br /&gt;
more to come..&lt;br /&gt;
[[Category:Development]]&lt;/div&gt;</summary>
		<author><name>Exophase</name></author>
		
	</entry>
	<entry>
		<id>https://pandorawiki.org/index.php?title=Kernel_interface&amp;diff=2431</id>
		<title>Kernel interface</title>
		<link rel="alternate" type="text/html" href="https://pandorawiki.org/index.php?title=Kernel_interface&amp;diff=2431"/>
		<updated>2010-06-20T00:05:41Z</updated>

		<summary type="html">&lt;p&gt;Exophase: /* Input */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Warning''': if your goal is just to write a game/program use higher level libraries/interfaces like SDL, Qt, X or similar for your own good (portability). It may be impossible to retain this layout on some major hardware revision, let's say Pandora 3000, and your program will break. Also this requires some level of Linux programming knowledge.&lt;br /&gt;
&lt;br /&gt;
In case you need to write low level code (you can't/don't want to use high level libs like SDL), you can use kernel interface. This is the recommended way to access hardware (as opposed to GP2X style of accessing chip registers by mmap'ing /dev/mem), because in case hardware changes are needed in future, they could be handled by kernel and all programs would still work. It also should allow several programs to work at the same time and should be more stable.&lt;br /&gt;
&lt;br /&gt;
==Input==&lt;br /&gt;
Buttons, keypad, touchscreen and nubs are all exposed through Linux event interface (EVDEV). All devices are represented by /dev/input/eventX files, which can be opened, read and queried (using ioctl calls). The reads can be synchronous (the read will only return when user does something, like presses the button), or asynchronous (the system will report what changed since the last time you asked).&lt;br /&gt;
&lt;br /&gt;
'''Warning''': don't hardcode device filenames in your program! For example, currently /dev/input/event2 represents game buttons, but in future it may become touchscreen. Scan input device names instead, example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
for (i = 0; 1; i++)&lt;br /&gt;
{&lt;br /&gt;
  sprintf(name, &amp;quot;/dev/input/event%i&amp;quot;, i);&lt;br /&gt;
  fd = open(name, O_RDONLY);&lt;br /&gt;
  if (fd &amp;lt; 0) break; /* no more devices */&lt;br /&gt;
  ioctl(fd, EVIOCGNAME(sizeof(name)), name);&lt;br /&gt;
  if (strcmp(name, &amp;quot;gpio-keys&amp;quot;) == 0)&lt;br /&gt;
    return fd; /* found the buttons! */&lt;br /&gt;
  close(fd); /* we don't need this device */&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List of device names and events they send:&lt;br /&gt;
{|border=1 cellpadding=2 cellspacing=0&lt;br /&gt;
|-&lt;br /&gt;
!name&lt;br /&gt;
!description&lt;br /&gt;
!event.type&lt;br /&gt;
!event.code&lt;br /&gt;
!event.value&lt;br /&gt;
|-&lt;br /&gt;
|keypad&lt;br /&gt;
|keypad&lt;br /&gt;
|EV_KEY&lt;br /&gt;
|KEY_0...KEY_Z, KEY_BACKSPACE, KEY_LEFTSHIFT, KEY_SPACE, KEY_ENTER, KEY_COMMA, KEY_DOT, KEY_FN&lt;br /&gt;
|0 - released, 1 - pressed, 2 - autorepeat event&lt;br /&gt;
|-&lt;br /&gt;
|gpio-keys&lt;br /&gt;
|game buttons&lt;br /&gt;
|EV_KEY&lt;br /&gt;
|KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT, KEY_MENU (Pandora button), KEY_LEFTALT (Start), KEY_LEFTCTRL (Select), KEY_END (Y/North), KEY_HOME (A/East), KEY_PAGEDOWN (X/South), KEY_END (B/West), KEY_RIGHTSHIFT (Shoulder L), KEY_RIGHTCTRL (Shoulder R), KEY_KP7 (Shoulder L2), KEY_KP8 (Shoulder R2), KEY_COFFEE (Hold)&lt;br /&gt;
|0 - released, 1 - pressed&lt;br /&gt;
|-&lt;br /&gt;
|gpio-keys&lt;br /&gt;
|lid state&lt;br /&gt;
|EV_SW&lt;br /&gt;
|SW_LID&lt;br /&gt;
|0 - closing, 1 - opening&lt;br /&gt;
|-&lt;br /&gt;
|touchscreen&lt;br /&gt;
|touchscreen&lt;br /&gt;
|EV_ABS&lt;br /&gt;
|ABS_X, ABS_Y, ABS_PRESSURE&lt;br /&gt;
|varies, use calibration data&lt;br /&gt;
|-&lt;br /&gt;
|nub0&lt;br /&gt;
|left nub&lt;br /&gt;
|EV_ABS&lt;br /&gt;
|ABS_X, ABS_Y&lt;br /&gt;
| -256 (Left/Up) ...0... +256 (Right/Down)&lt;br /&gt;
|-&lt;br /&gt;
|nub1&lt;br /&gt;
|right nub&lt;br /&gt;
|EV_ABS&lt;br /&gt;
|ABS_X, ABS_Y&lt;br /&gt;
| -256 (Left/Up) ...0... +256 (Right/Down)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Sample code:&amp;lt;br&amp;gt;&lt;br /&gt;
[http://beagleboard.googlecode.com/files/evtest.c evtest.c]&lt;br /&gt;
[http://git.openpandora.org/cgi-bin/gitweb.cgi?p=pandora-misc.git;a=blob;f=op_test_inputs.c;hb=HEAD op_test_inputs.c]&lt;br /&gt;
&lt;br /&gt;
===Touchscreen===&lt;br /&gt;
Event interface returns uncalibrated values directly from driver, so you need to use tslib or manage calibration yourself (using data from /etc/pointercal).&lt;br /&gt;
&lt;br /&gt;
==Sound==&lt;br /&gt;
Pandora uses ALSA, but it has OSS emulation enabled too, so GP2X code should work.&lt;br /&gt;
&lt;br /&gt;
==Video==&lt;br /&gt;
===Architecture===&lt;br /&gt;
Framebuffer device (/dev/fbX) is supported. There are 3 framebuffers available (/dev/fb0, /dev/fb1 and /dev/fb2), which represent 3 graphics/video layers on OMAP3 by default (but can be reconfigured). Only /dev/fb0 is enabled by default.&lt;br /&gt;
&lt;br /&gt;
OMAP3 display subsystem is controlled by a driver known as DSS2, which has various controls available on /sys/devices/platform/omapdss/ (but they are not meant to be changed by programs, so they are root writable only). The driver exposes 3 layers (called overlays) and 2 displays. Overlays 1 and 2 can perform hardware scaling on the fly using 5-tap poly-phase filter, overlay0 can not. Displays 0 and 1 represent LCD and TV respectively. By default the 3 framebuffers (/dev/fbX) are redirected to 3 overlays, which all output to the LCD. This configuration is not meant to be changed by programs, only firmware should manage these.&lt;br /&gt;
&lt;br /&gt;
===Basic usage===&lt;br /&gt;
====framebuffer interface====&lt;br /&gt;
Framebuffers can be accessed Linux fbdev interface:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
fbdev = open(&amp;quot;/dev/fb0&amp;quot;, O_RDONLY);&lt;br /&gt;
buffer = mmap(0, 800*480*2, PROT_WRITE, MAP_SHARED, fbdev, 0);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
(this is basic example, no error checks)&lt;br /&gt;
&lt;br /&gt;
the returned pointer can be used to draw on the screen.&lt;br /&gt;
&lt;br /&gt;
Be sure to #include &amp;lt;linux/fb.h&amp;gt; to get access to the FB device ioctl interface, and &amp;lt;sys/ioctl.h&amp;gt; for access to ioctl itself.&lt;br /&gt;
&lt;br /&gt;
====double buffering====&lt;br /&gt;
This can be achieved using FBIOPAN_DISPLAY ioctl system call. For this you need to mmap framebuffer of double size&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
buffer1 = mmap(0, 800*480*2 * 2, PROT_WRITE, MAP_SHARED, fbdev, 0);&lt;br /&gt;
buffer2 = (char *)mem + 800*480*2;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then to display buffer2 you would call:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
struct fb_var_screeninfo fbvar;&lt;br /&gt;
ioctl(fbdev, FBIOGET_VSCREENINFO, &amp;amp;fbvar);&lt;br /&gt;
fbvar.yoffset = 480;&lt;br /&gt;
ioctl(fbdev, FBIOPAN_DISPLAY, &amp;amp;fbvar);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
going back to buffer1 would be repeating above with fbvar.yoffset = 0. Tripple or quad buffering can be implemented using the same technique.&lt;br /&gt;
&lt;br /&gt;
====vertical sync====&lt;br /&gt;
Linux has standard FBIO_WAITFORVSYNC for this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
int arg = 0;&lt;br /&gt;
ioctl(fbdev, FBIO_WAITFORVSYNC, &amp;amp;arg);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
be sure to pass argument value 0 or it will not work.&lt;br /&gt;
&lt;br /&gt;
Currently FBIO_WAITFORVSYNC is not defined in &amp;lt;linux/fb.h&amp;gt;, although this is in the process of modification. For now, define in the following manner:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#ifndef FBIO_WAITFORVSYNC&lt;br /&gt;
  #define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32)&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====hardware scaling====&lt;br /&gt;
Overlay1 (/dev/fb1) can be used to achieve hardware scaling. Technically overlay2 (fb2) can be used for this too, but it is planned to be used by the system for TV-out functionality, so don't use it. The overlay is configured using series of standard and OMAP specific ioctl calls, but the system ships with some tools to achieve this from scripts too. This way the framebuffer can be set up for some arbitrary size (say 320x240) and can output to LCD as 800x480 with hardware scaling.&lt;br /&gt;
Here is an example script:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ofbset -fb /dev/fb1 -pos 0 0 -size 800 480 -mem 307200 -en 1&lt;br /&gt;
fbset -fb /dev/fb1 -g 320 240 320 480 16&lt;br /&gt;
&lt;br /&gt;
./your_app_here&lt;br /&gt;
&lt;br /&gt;
ofbset -fb /dev/fb1 -pos 0 0 -size 0 0 -mem 0 -en 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What it does:&lt;br /&gt;
* allocates OMAP DSS layer, asks video output to be 800x480 at position 0,0 (could set it to 640x480 at 80,0 instead to get centered 2x scaling of 320x240). 307200 bytes of video memory are allocated for 2 320x240 16bpp screens (for doublebuffering).&lt;br /&gt;
* sets video mode to 320x240@16bpp, virtual resolution 320x480 for doublebuffering.&lt;br /&gt;
* runs your app&lt;br /&gt;
* cleans the video layer on exit&lt;br /&gt;
&lt;br /&gt;
Now the program can act as if works with 16bpp screen.&lt;br /&gt;
&lt;br /&gt;
==LEDs and backlight==&lt;br /&gt;
The LEDs can be controlled via /sys/class/leds/, and then a file [http://www.gp32x.com/board/index.php?s=&amp;amp;showtopic=45309&amp;amp;view=findpost&amp;amp;p=673593]:&lt;br /&gt;
* pandora::sd1&lt;br /&gt;
* pandora::sd2&lt;br /&gt;
* pandora::charger&lt;br /&gt;
* pandora::power&lt;br /&gt;
* pandora::bluetooth&lt;br /&gt;
* pandora::wifi&lt;br /&gt;
* pandora::keypad_bl&lt;br /&gt;
Backlight can be controlled via /sys/class/backlight/.&lt;br /&gt;
&lt;br /&gt;
==Misc==&lt;br /&gt;
Some things can be controlled through files in /proc/pandora/:&lt;br /&gt;
* /proc/pandora/cpu_mhz_max - if [http://www.kernel.org/pub/linux/utils/kernel/cpufreq/cpufreq.html cpufreq] is enabled, sets maximum allowed cpu clock, if not, just sets CPU clock to value supplied (echo 600 &amp;gt; /proc/pandora/cpu_mhz_max). Might also just use cpufreq parameters themselves.&lt;br /&gt;
more to come..&lt;br /&gt;
[[Category:Development]]&lt;/div&gt;</summary>
		<author><name>Exophase</name></author>
		
	</entry>
	<entry>
		<id>https://pandorawiki.org/index.php?title=Kernel_interface&amp;diff=2417</id>
		<title>Kernel interface</title>
		<link rel="alternate" type="text/html" href="https://pandorawiki.org/index.php?title=Kernel_interface&amp;diff=2417"/>
		<updated>2010-06-19T11:01:10Z</updated>

		<summary type="html">&lt;p&gt;Exophase: /* double buffering */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Warning''': if your goal is just to write a game/program use higher level libraries/interfaces like SDL, Qt, X or similar for your own good (portability). It may be impossible to retain this layout on some major hardware revision, let's say Pandora 3000, and your program will break. Also this requires some level of Linux programming knowledge.&lt;br /&gt;
&lt;br /&gt;
In case you need to write low level code (you can't/don't want to use high level libs like SDL), you can use kernel interface. This is the recommended way to access hardware (as opposed to GP2X style of accessing chip registers by mmap'ing /dev/mem), because in case hardware changes are needed in future, they could be handled by kernel and all programs would still work. It also should allow several programs to work at the same time and should be more stable.&lt;br /&gt;
&lt;br /&gt;
==Input==&lt;br /&gt;
Buttons, keypad, touchscreen and nubs are all exposed through Linux event interface (EVDEV). All devices are represented by /dev/input/eventX files, which can be opened, read and queried (using ioctl calls). The reads can be synchronous (the read will only return when user does something, like presses the button), or asynchronous (the system will report what changed since the last time you asked).&lt;br /&gt;
&lt;br /&gt;
'''Warning''': don't hardcode device filenames in your program! For example, currently /dev/input/event2 represents game buttons, but in future it may become touchscreen. Scan input device names instead, example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
for (i = 0; 1; i++)&lt;br /&gt;
{&lt;br /&gt;
  sprintf(name, &amp;quot;/dev/input/event%i&amp;quot;, i);&lt;br /&gt;
  fd = open(name, O_RDONLY);&lt;br /&gt;
  if (fd &amp;lt; 0) break; /* no more devices */&lt;br /&gt;
  ioctl(fd, EVIOCGNAME(sizeof(name)), name);&lt;br /&gt;
  if (strcmp(name, &amp;quot;gpio-keys&amp;quot;) == 0)&lt;br /&gt;
    return fd; /* found the buttons! */&lt;br /&gt;
  close(fd); /* we don't need this device */&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List of device names and events they send:&lt;br /&gt;
{|border=1 cellpadding=2 cellspacing=0&lt;br /&gt;
|-&lt;br /&gt;
!name&lt;br /&gt;
!description&lt;br /&gt;
!event.type&lt;br /&gt;
!event.code&lt;br /&gt;
!event.value&lt;br /&gt;
|-&lt;br /&gt;
|keypad&lt;br /&gt;
|keypad&lt;br /&gt;
|EV_KEY&lt;br /&gt;
|KEY_0...KEY_Z, KEY_BACKSPACE, KEY_LEFTSHIFT, KEY_SPACE, KEY_ENTER, KEY_COMMA, KEY_DOT, KEY_FN&lt;br /&gt;
|0 - released, 1 - pressed, 2 - autorepeat event&lt;br /&gt;
|-&lt;br /&gt;
|gpio-keys&lt;br /&gt;
|game buttons&lt;br /&gt;
|EV_KEY&lt;br /&gt;
|KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT, KEY_MENU (Pandora button), KEY_LEFTALT (Start), KEY_LEFTCTRL (Select), KEY_KP1 (Y/North), KEY_KP2 (A/East), KEY_KP3 (X/South), KEY_KP4 (B/West), KEY_KP5 (Shoulder L), KEY_KP6 (Shoulder R), KEY_KP7 (Shoulder L2), KEY_KP8 (Shoulder R2), KEY_COFFEE (Hold)&lt;br /&gt;
|0 - released, 1 - pressed&lt;br /&gt;
|-&lt;br /&gt;
|gpio-keys&lt;br /&gt;
|lid state&lt;br /&gt;
|EV_SW&lt;br /&gt;
|SW_LID&lt;br /&gt;
|0 - closing, 1 - opening&lt;br /&gt;
|-&lt;br /&gt;
|touchscreen&lt;br /&gt;
|touchscreen&lt;br /&gt;
|EV_ABS&lt;br /&gt;
|ABS_X, ABS_Y, ABS_PRESSURE&lt;br /&gt;
|varies, use calibration data&lt;br /&gt;
|-&lt;br /&gt;
|nub0&lt;br /&gt;
|left nub&lt;br /&gt;
|EV_ABS&lt;br /&gt;
|ABS_X, ABS_Y&lt;br /&gt;
| -256 (Left/Up) ...0... +256 (Right/Down)&lt;br /&gt;
|-&lt;br /&gt;
|nub1&lt;br /&gt;
|right nub&lt;br /&gt;
|EV_ABS&lt;br /&gt;
|ABS_X, ABS_Y&lt;br /&gt;
| -256 (Left/Up) ...0... +256 (Right/Down)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Sample code:&amp;lt;br&amp;gt;&lt;br /&gt;
[http://beagleboard.googlecode.com/files/evtest.c evtest.c]&lt;br /&gt;
[http://git.openpandora.org/cgi-bin/gitweb.cgi?p=pandora-misc.git;a=blob;f=op_test_inputs.c;hb=HEAD op_test_inputs.c]&lt;br /&gt;
&lt;br /&gt;
===Touchscreen===&lt;br /&gt;
Event interface returns uncalibrated values directly from driver, so you need to use tslib or manage calibration yourself (using data from /etc/pointercal).&lt;br /&gt;
&lt;br /&gt;
==Sound==&lt;br /&gt;
Pandora uses ALSA, but it has OSS emulation enabled too, so GP2X code should work.&lt;br /&gt;
&lt;br /&gt;
==Video==&lt;br /&gt;
===Architecture===&lt;br /&gt;
Framebuffer device (/dev/fbX) is supported. There are 3 framebuffers available (/dev/fb0, /dev/fb1 and /dev/fb2), which represent 3 graphics/video layers on OMAP3 by default (but can be reconfigured). Only /dev/fb0 is enabled by default.&lt;br /&gt;
&lt;br /&gt;
OMAP3 display subsystem is controlled by a driver known as DSS2, which has various controls available on /sys/devices/platform/omapdss/ (but they are not meant to be changed by programs, so they are root writable only). The driver exposes 3 layers (called overlays) and 2 displays. Overlays 1 and 2 can perform hardware scaling on the fly using 5-tap poly-phase filter, overlay0 can not. Displays 0 and 1 represent LCD and TV respectively. By default the 3 framebuffers (/dev/fbX) are redirected to 3 overlays, which all output to the LCD. This configuration is not meant to be changed by programs, only firmware should manage these.&lt;br /&gt;
&lt;br /&gt;
===Basic usage===&lt;br /&gt;
====framebuffer interface====&lt;br /&gt;
Framebuffers can be accessed Linux fbdev interface:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
fbdev = open(&amp;quot;/dev/fb0&amp;quot;, O_RDONLY);&lt;br /&gt;
buffer = mmap(0, 800*480*2, PROT_WRITE, MAP_SHARED, fbdev, 0);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
(this is basic example, no error checks)&lt;br /&gt;
&lt;br /&gt;
the returned pointer can be used to draw on the screen.&lt;br /&gt;
&lt;br /&gt;
Be sure to #include &amp;lt;linux/fb.h&amp;gt; to get access to the FB device ioctl interface, and &amp;lt;sys/ioctl.h&amp;gt; for access to ioctl itself.&lt;br /&gt;
&lt;br /&gt;
====double buffering====&lt;br /&gt;
This can be achieved using FBIOPAN_DISPLAY ioctl system call. For this you need to mmap framebuffer of double size&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
buffer1 = mmap(0, 800*480*2 * 2, PROT_WRITE, MAP_SHARED, fbdev, 0);&lt;br /&gt;
buffer2 = (char *)mem + 800*480*2;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then to display buffer2 you would call:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
struct fb_var_screeninfo fbvar;&lt;br /&gt;
ioctl(fbdev, FBIOGET_VSCREENINFO, &amp;amp;fbvar);&lt;br /&gt;
fbvar.yoffset = 480;&lt;br /&gt;
ioctl(fbdev, FBIOPAN_DISPLAY, &amp;amp;fbvar);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
going back to buffer1 would be repeating above with fbvar.yoffset = 0. Tripple or quad buffering can be implemented using the same technique.&lt;br /&gt;
&lt;br /&gt;
====vertical sync====&lt;br /&gt;
Linux has standard FBIO_WAITFORVSYNC for this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
int arg = 0;&lt;br /&gt;
ioctl(fbdev, FBIO_WAITFORVSYNC, &amp;amp;arg);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
be sure to pass argument value 0 or it will not work.&lt;br /&gt;
&lt;br /&gt;
Currently FBIO_WAITFORVSYNC is not defined in &amp;lt;linux/fb.h&amp;gt;, although this is in the process of modification. For now, define in the following manner:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#ifndef FBIO_WAITFORVSYNC&lt;br /&gt;
  #define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32)&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====hardware scaling====&lt;br /&gt;
Overlay1 (/dev/fb1) can be used to achieve hardware scaling. Technically overlay2 (fb2) can be used for this too, but it is planned to be used by the system for TV-out functionality, so don't use it. The overlay is configured using series of standard and OMAP specific ioctl calls, but the system ships with some tools to achieve this from scripts too. This way the framebuffer can be set up for some arbitrary size (say 320x240) and can output to LCD as 800x480 with hardware scaling.&lt;br /&gt;
Here is an example script:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ofbset -fb /dev/fb1 -pos 0 0 -size 800 480 -mem 307200 -en 1&lt;br /&gt;
fbset -fb /dev/fb1 -g 320 240 320 480 16&lt;br /&gt;
&lt;br /&gt;
./your_app_here&lt;br /&gt;
&lt;br /&gt;
ofbset -fb /dev/fb1 -pos 0 0 -size 0 0 -mem 0 -en 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What it does:&lt;br /&gt;
* allocates OMAP DSS layer, asks video output to be 800x480 at position 0,0 (could set it to 640x480 at 80,0 instead to get centered 2x scaling of 320x240). 307200 bytes of video memory are allocated for 2 320x240 16bpp screens (for doublebuffering).&lt;br /&gt;
* sets video mode to 320x240@16bpp, virtual resolution 320x480 for doublebuffering.&lt;br /&gt;
* runs your app&lt;br /&gt;
* cleans the video layer on exit&lt;br /&gt;
&lt;br /&gt;
Now the program can act as if works with 16bpp screen.&lt;br /&gt;
&lt;br /&gt;
==LEDs and backlight==&lt;br /&gt;
The LEDs can be controlled via /sys/class/leds/, and then a file [http://www.gp32x.com/board/index.php?s=&amp;amp;showtopic=45309&amp;amp;view=findpost&amp;amp;p=673593]:&lt;br /&gt;
* pandora::sd1&lt;br /&gt;
* pandora::sd2&lt;br /&gt;
* pandora::charger&lt;br /&gt;
* pandora::power&lt;br /&gt;
* pandora::bluetooth&lt;br /&gt;
* pandora::wifi&lt;br /&gt;
* pandora::keypad_bl&lt;br /&gt;
Backlight can be controlled via /sys/class/backlight/.&lt;br /&gt;
&lt;br /&gt;
==Misc==&lt;br /&gt;
Some things can be controlled through files in /proc/pandora/:&lt;br /&gt;
* /proc/pandora/cpu_mhz_max - if [http://www.kernel.org/pub/linux/utils/kernel/cpufreq/cpufreq.html cpufreq] is enabled, sets maximum allowed cpu clock, if not, just sets CPU clock to value supplied (echo 600 &amp;gt; /proc/pandora/cpu_mhz_max). Might also just use cpufreq parameters themselves.&lt;br /&gt;
more to come..&lt;br /&gt;
[[Category:Development]]&lt;/div&gt;</summary>
		<author><name>Exophase</name></author>
		
	</entry>
	<entry>
		<id>https://pandorawiki.org/index.php?title=Kernel_interface&amp;diff=2416</id>
		<title>Kernel interface</title>
		<link rel="alternate" type="text/html" href="https://pandorawiki.org/index.php?title=Kernel_interface&amp;diff=2416"/>
		<updated>2010-06-19T10:59:29Z</updated>

		<summary type="html">&lt;p&gt;Exophase: /* vertical sync */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Warning''': if your goal is just to write a game/program use higher level libraries/interfaces like SDL, Qt, X or similar for your own good (portability). It may be impossible to retain this layout on some major hardware revision, let's say Pandora 3000, and your program will break. Also this requires some level of Linux programming knowledge.&lt;br /&gt;
&lt;br /&gt;
In case you need to write low level code (you can't/don't want to use high level libs like SDL), you can use kernel interface. This is the recommended way to access hardware (as opposed to GP2X style of accessing chip registers by mmap'ing /dev/mem), because in case hardware changes are needed in future, they could be handled by kernel and all programs would still work. It also should allow several programs to work at the same time and should be more stable.&lt;br /&gt;
&lt;br /&gt;
==Input==&lt;br /&gt;
Buttons, keypad, touchscreen and nubs are all exposed through Linux event interface (EVDEV). All devices are represented by /dev/input/eventX files, which can be opened, read and queried (using ioctl calls). The reads can be synchronous (the read will only return when user does something, like presses the button), or asynchronous (the system will report what changed since the last time you asked).&lt;br /&gt;
&lt;br /&gt;
'''Warning''': don't hardcode device filenames in your program! For example, currently /dev/input/event2 represents game buttons, but in future it may become touchscreen. Scan input device names instead, example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
for (i = 0; 1; i++)&lt;br /&gt;
{&lt;br /&gt;
  sprintf(name, &amp;quot;/dev/input/event%i&amp;quot;, i);&lt;br /&gt;
  fd = open(name, O_RDONLY);&lt;br /&gt;
  if (fd &amp;lt; 0) break; /* no more devices */&lt;br /&gt;
  ioctl(fd, EVIOCGNAME(sizeof(name)), name);&lt;br /&gt;
  if (strcmp(name, &amp;quot;gpio-keys&amp;quot;) == 0)&lt;br /&gt;
    return fd; /* found the buttons! */&lt;br /&gt;
  close(fd); /* we don't need this device */&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List of device names and events they send:&lt;br /&gt;
{|border=1 cellpadding=2 cellspacing=0&lt;br /&gt;
|-&lt;br /&gt;
!name&lt;br /&gt;
!description&lt;br /&gt;
!event.type&lt;br /&gt;
!event.code&lt;br /&gt;
!event.value&lt;br /&gt;
|-&lt;br /&gt;
|keypad&lt;br /&gt;
|keypad&lt;br /&gt;
|EV_KEY&lt;br /&gt;
|KEY_0...KEY_Z, KEY_BACKSPACE, KEY_LEFTSHIFT, KEY_SPACE, KEY_ENTER, KEY_COMMA, KEY_DOT, KEY_FN&lt;br /&gt;
|0 - released, 1 - pressed, 2 - autorepeat event&lt;br /&gt;
|-&lt;br /&gt;
|gpio-keys&lt;br /&gt;
|game buttons&lt;br /&gt;
|EV_KEY&lt;br /&gt;
|KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT, KEY_MENU (Pandora button), KEY_LEFTALT (Start), KEY_LEFTCTRL (Select), KEY_KP1 (Y/North), KEY_KP2 (A/East), KEY_KP3 (X/South), KEY_KP4 (B/West), KEY_KP5 (Shoulder L), KEY_KP6 (Shoulder R), KEY_KP7 (Shoulder L2), KEY_KP8 (Shoulder R2), KEY_COFFEE (Hold)&lt;br /&gt;
|0 - released, 1 - pressed&lt;br /&gt;
|-&lt;br /&gt;
|gpio-keys&lt;br /&gt;
|lid state&lt;br /&gt;
|EV_SW&lt;br /&gt;
|SW_LID&lt;br /&gt;
|0 - closing, 1 - opening&lt;br /&gt;
|-&lt;br /&gt;
|touchscreen&lt;br /&gt;
|touchscreen&lt;br /&gt;
|EV_ABS&lt;br /&gt;
|ABS_X, ABS_Y, ABS_PRESSURE&lt;br /&gt;
|varies, use calibration data&lt;br /&gt;
|-&lt;br /&gt;
|nub0&lt;br /&gt;
|left nub&lt;br /&gt;
|EV_ABS&lt;br /&gt;
|ABS_X, ABS_Y&lt;br /&gt;
| -256 (Left/Up) ...0... +256 (Right/Down)&lt;br /&gt;
|-&lt;br /&gt;
|nub1&lt;br /&gt;
|right nub&lt;br /&gt;
|EV_ABS&lt;br /&gt;
|ABS_X, ABS_Y&lt;br /&gt;
| -256 (Left/Up) ...0... +256 (Right/Down)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Sample code:&amp;lt;br&amp;gt;&lt;br /&gt;
[http://beagleboard.googlecode.com/files/evtest.c evtest.c]&lt;br /&gt;
[http://git.openpandora.org/cgi-bin/gitweb.cgi?p=pandora-misc.git;a=blob;f=op_test_inputs.c;hb=HEAD op_test_inputs.c]&lt;br /&gt;
&lt;br /&gt;
===Touchscreen===&lt;br /&gt;
Event interface returns uncalibrated values directly from driver, so you need to use tslib or manage calibration yourself (using data from /etc/pointercal).&lt;br /&gt;
&lt;br /&gt;
==Sound==&lt;br /&gt;
Pandora uses ALSA, but it has OSS emulation enabled too, so GP2X code should work.&lt;br /&gt;
&lt;br /&gt;
==Video==&lt;br /&gt;
===Architecture===&lt;br /&gt;
Framebuffer device (/dev/fbX) is supported. There are 3 framebuffers available (/dev/fb0, /dev/fb1 and /dev/fb2), which represent 3 graphics/video layers on OMAP3 by default (but can be reconfigured). Only /dev/fb0 is enabled by default.&lt;br /&gt;
&lt;br /&gt;
OMAP3 display subsystem is controlled by a driver known as DSS2, which has various controls available on /sys/devices/platform/omapdss/ (but they are not meant to be changed by programs, so they are root writable only). The driver exposes 3 layers (called overlays) and 2 displays. Overlays 1 and 2 can perform hardware scaling on the fly using 5-tap poly-phase filter, overlay0 can not. Displays 0 and 1 represent LCD and TV respectively. By default the 3 framebuffers (/dev/fbX) are redirected to 3 overlays, which all output to the LCD. This configuration is not meant to be changed by programs, only firmware should manage these.&lt;br /&gt;
&lt;br /&gt;
===Basic usage===&lt;br /&gt;
====framebuffer interface====&lt;br /&gt;
Framebuffers can be accessed Linux fbdev interface:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
fbdev = open(&amp;quot;/dev/fb0&amp;quot;, O_RDONLY);&lt;br /&gt;
buffer = mmap(0, 800*480*2, PROT_WRITE, MAP_SHARED, fbdev, 0);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
(this is basic example, no error checks)&lt;br /&gt;
&lt;br /&gt;
the returned pointer can be used to draw on the screen.&lt;br /&gt;
&lt;br /&gt;
Be sure to #include &amp;lt;linux/fb.h&amp;gt; to get access to the FB device ioctl interface, and &amp;lt;sys/ioctl.h&amp;gt; for access to ioctl itself.&lt;br /&gt;
&lt;br /&gt;
====double buffering====&lt;br /&gt;
This can be achieved using FBIOPAN_DISPLAY ioctl system call. For this you need to mmap framebuffer of double size&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
buffer1 = mmap(0, 800*480*2 * 2, PROT_WRITE, MAP_SHARED, fbdev, 0);&lt;br /&gt;
buffer2 = (char *)mem + 800*480*2;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
or map 2 buffers&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
buffer1 = mmap(0, 800*480*2 * 2, PROT_WRITE, MAP_SHARED, fbdev, 0);&lt;br /&gt;
buffer2 = mmap(0, 800*480*2 * 2, PROT_WRITE, MAP_SHARED, fbdev, 800*480*2);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Then to display buffer2 you would call:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
struct fb_var_screeninfo fbvar;&lt;br /&gt;
ioctl(fbdev, FBIOGET_VSCREENINFO, &amp;amp;fbvar);&lt;br /&gt;
fbvar.yoffset = 480;&lt;br /&gt;
ioctl(fbdev, FBIOPAN_DISPLAY, &amp;amp;fbvar);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
going back to buffer1 would be repeating above with fbvar.yoffset = 0. Tripple or quad buffering can be implemented using the same technique.&lt;br /&gt;
&lt;br /&gt;
====vertical sync====&lt;br /&gt;
Linux has standard FBIO_WAITFORVSYNC for this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
int arg = 0;&lt;br /&gt;
ioctl(fbdev, FBIO_WAITFORVSYNC, &amp;amp;arg);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
be sure to pass argument value 0 or it will not work.&lt;br /&gt;
&lt;br /&gt;
Currently FBIO_WAITFORVSYNC is not defined in &amp;lt;linux/fb.h&amp;gt;, although this is in the process of modification. For now, define in the following manner:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#ifndef FBIO_WAITFORVSYNC&lt;br /&gt;
  #define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32)&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====hardware scaling====&lt;br /&gt;
Overlay1 (/dev/fb1) can be used to achieve hardware scaling. Technically overlay2 (fb2) can be used for this too, but it is planned to be used by the system for TV-out functionality, so don't use it. The overlay is configured using series of standard and OMAP specific ioctl calls, but the system ships with some tools to achieve this from scripts too. This way the framebuffer can be set up for some arbitrary size (say 320x240) and can output to LCD as 800x480 with hardware scaling.&lt;br /&gt;
Here is an example script:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ofbset -fb /dev/fb1 -pos 0 0 -size 800 480 -mem 307200 -en 1&lt;br /&gt;
fbset -fb /dev/fb1 -g 320 240 320 480 16&lt;br /&gt;
&lt;br /&gt;
./your_app_here&lt;br /&gt;
&lt;br /&gt;
ofbset -fb /dev/fb1 -pos 0 0 -size 0 0 -mem 0 -en 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What it does:&lt;br /&gt;
* allocates OMAP DSS layer, asks video output to be 800x480 at position 0,0 (could set it to 640x480 at 80,0 instead to get centered 2x scaling of 320x240). 307200 bytes of video memory are allocated for 2 320x240 16bpp screens (for doublebuffering).&lt;br /&gt;
* sets video mode to 320x240@16bpp, virtual resolution 320x480 for doublebuffering.&lt;br /&gt;
* runs your app&lt;br /&gt;
* cleans the video layer on exit&lt;br /&gt;
&lt;br /&gt;
Now the program can act as if works with 16bpp screen.&lt;br /&gt;
&lt;br /&gt;
==LEDs and backlight==&lt;br /&gt;
The LEDs can be controlled via /sys/class/leds/, and then a file [http://www.gp32x.com/board/index.php?s=&amp;amp;showtopic=45309&amp;amp;view=findpost&amp;amp;p=673593]:&lt;br /&gt;
* pandora::sd1&lt;br /&gt;
* pandora::sd2&lt;br /&gt;
* pandora::charger&lt;br /&gt;
* pandora::power&lt;br /&gt;
* pandora::bluetooth&lt;br /&gt;
* pandora::wifi&lt;br /&gt;
* pandora::keypad_bl&lt;br /&gt;
Backlight can be controlled via /sys/class/backlight/.&lt;br /&gt;
&lt;br /&gt;
==Misc==&lt;br /&gt;
Some things can be controlled through files in /proc/pandora/:&lt;br /&gt;
* /proc/pandora/cpu_mhz_max - if [http://www.kernel.org/pub/linux/utils/kernel/cpufreq/cpufreq.html cpufreq] is enabled, sets maximum allowed cpu clock, if not, just sets CPU clock to value supplied (echo 600 &amp;gt; /proc/pandora/cpu_mhz_max). Might also just use cpufreq parameters themselves.&lt;br /&gt;
more to come..&lt;br /&gt;
[[Category:Development]]&lt;/div&gt;</summary>
		<author><name>Exophase</name></author>
		
	</entry>
	<entry>
		<id>https://pandorawiki.org/index.php?title=Kernel_interface&amp;diff=2415</id>
		<title>Kernel interface</title>
		<link rel="alternate" type="text/html" href="https://pandorawiki.org/index.php?title=Kernel_interface&amp;diff=2415"/>
		<updated>2010-06-19T10:57:29Z</updated>

		<summary type="html">&lt;p&gt;Exophase: /* vertical sync */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Warning''': if your goal is just to write a game/program use higher level libraries/interfaces like SDL, Qt, X or similar for your own good (portability). It may be impossible to retain this layout on some major hardware revision, let's say Pandora 3000, and your program will break. Also this requires some level of Linux programming knowledge.&lt;br /&gt;
&lt;br /&gt;
In case you need to write low level code (you can't/don't want to use high level libs like SDL), you can use kernel interface. This is the recommended way to access hardware (as opposed to GP2X style of accessing chip registers by mmap'ing /dev/mem), because in case hardware changes are needed in future, they could be handled by kernel and all programs would still work. It also should allow several programs to work at the same time and should be more stable.&lt;br /&gt;
&lt;br /&gt;
==Input==&lt;br /&gt;
Buttons, keypad, touchscreen and nubs are all exposed through Linux event interface (EVDEV). All devices are represented by /dev/input/eventX files, which can be opened, read and queried (using ioctl calls). The reads can be synchronous (the read will only return when user does something, like presses the button), or asynchronous (the system will report what changed since the last time you asked).&lt;br /&gt;
&lt;br /&gt;
'''Warning''': don't hardcode device filenames in your program! For example, currently /dev/input/event2 represents game buttons, but in future it may become touchscreen. Scan input device names instead, example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
for (i = 0; 1; i++)&lt;br /&gt;
{&lt;br /&gt;
  sprintf(name, &amp;quot;/dev/input/event%i&amp;quot;, i);&lt;br /&gt;
  fd = open(name, O_RDONLY);&lt;br /&gt;
  if (fd &amp;lt; 0) break; /* no more devices */&lt;br /&gt;
  ioctl(fd, EVIOCGNAME(sizeof(name)), name);&lt;br /&gt;
  if (strcmp(name, &amp;quot;gpio-keys&amp;quot;) == 0)&lt;br /&gt;
    return fd; /* found the buttons! */&lt;br /&gt;
  close(fd); /* we don't need this device */&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List of device names and events they send:&lt;br /&gt;
{|border=1 cellpadding=2 cellspacing=0&lt;br /&gt;
|-&lt;br /&gt;
!name&lt;br /&gt;
!description&lt;br /&gt;
!event.type&lt;br /&gt;
!event.code&lt;br /&gt;
!event.value&lt;br /&gt;
|-&lt;br /&gt;
|keypad&lt;br /&gt;
|keypad&lt;br /&gt;
|EV_KEY&lt;br /&gt;
|KEY_0...KEY_Z, KEY_BACKSPACE, KEY_LEFTSHIFT, KEY_SPACE, KEY_ENTER, KEY_COMMA, KEY_DOT, KEY_FN&lt;br /&gt;
|0 - released, 1 - pressed, 2 - autorepeat event&lt;br /&gt;
|-&lt;br /&gt;
|gpio-keys&lt;br /&gt;
|game buttons&lt;br /&gt;
|EV_KEY&lt;br /&gt;
|KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT, KEY_MENU (Pandora button), KEY_LEFTALT (Start), KEY_LEFTCTRL (Select), KEY_KP1 (Y/North), KEY_KP2 (A/East), KEY_KP3 (X/South), KEY_KP4 (B/West), KEY_KP5 (Shoulder L), KEY_KP6 (Shoulder R), KEY_KP7 (Shoulder L2), KEY_KP8 (Shoulder R2), KEY_COFFEE (Hold)&lt;br /&gt;
|0 - released, 1 - pressed&lt;br /&gt;
|-&lt;br /&gt;
|gpio-keys&lt;br /&gt;
|lid state&lt;br /&gt;
|EV_SW&lt;br /&gt;
|SW_LID&lt;br /&gt;
|0 - closing, 1 - opening&lt;br /&gt;
|-&lt;br /&gt;
|touchscreen&lt;br /&gt;
|touchscreen&lt;br /&gt;
|EV_ABS&lt;br /&gt;
|ABS_X, ABS_Y, ABS_PRESSURE&lt;br /&gt;
|varies, use calibration data&lt;br /&gt;
|-&lt;br /&gt;
|nub0&lt;br /&gt;
|left nub&lt;br /&gt;
|EV_ABS&lt;br /&gt;
|ABS_X, ABS_Y&lt;br /&gt;
| -256 (Left/Up) ...0... +256 (Right/Down)&lt;br /&gt;
|-&lt;br /&gt;
|nub1&lt;br /&gt;
|right nub&lt;br /&gt;
|EV_ABS&lt;br /&gt;
|ABS_X, ABS_Y&lt;br /&gt;
| -256 (Left/Up) ...0... +256 (Right/Down)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Sample code:&amp;lt;br&amp;gt;&lt;br /&gt;
[http://beagleboard.googlecode.com/files/evtest.c evtest.c]&lt;br /&gt;
[http://git.openpandora.org/cgi-bin/gitweb.cgi?p=pandora-misc.git;a=blob;f=op_test_inputs.c;hb=HEAD op_test_inputs.c]&lt;br /&gt;
&lt;br /&gt;
===Touchscreen===&lt;br /&gt;
Event interface returns uncalibrated values directly from driver, so you need to use tslib or manage calibration yourself (using data from /etc/pointercal).&lt;br /&gt;
&lt;br /&gt;
==Sound==&lt;br /&gt;
Pandora uses ALSA, but it has OSS emulation enabled too, so GP2X code should work.&lt;br /&gt;
&lt;br /&gt;
==Video==&lt;br /&gt;
===Architecture===&lt;br /&gt;
Framebuffer device (/dev/fbX) is supported. There are 3 framebuffers available (/dev/fb0, /dev/fb1 and /dev/fb2), which represent 3 graphics/video layers on OMAP3 by default (but can be reconfigured). Only /dev/fb0 is enabled by default.&lt;br /&gt;
&lt;br /&gt;
OMAP3 display subsystem is controlled by a driver known as DSS2, which has various controls available on /sys/devices/platform/omapdss/ (but they are not meant to be changed by programs, so they are root writable only). The driver exposes 3 layers (called overlays) and 2 displays. Overlays 1 and 2 can perform hardware scaling on the fly using 5-tap poly-phase filter, overlay0 can not. Displays 0 and 1 represent LCD and TV respectively. By default the 3 framebuffers (/dev/fbX) are redirected to 3 overlays, which all output to the LCD. This configuration is not meant to be changed by programs, only firmware should manage these.&lt;br /&gt;
&lt;br /&gt;
===Basic usage===&lt;br /&gt;
====framebuffer interface====&lt;br /&gt;
Framebuffers can be accessed Linux fbdev interface:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
fbdev = open(&amp;quot;/dev/fb0&amp;quot;, O_RDONLY);&lt;br /&gt;
buffer = mmap(0, 800*480*2, PROT_WRITE, MAP_SHARED, fbdev, 0);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
(this is basic example, no error checks)&lt;br /&gt;
&lt;br /&gt;
the returned pointer can be used to draw on the screen.&lt;br /&gt;
&lt;br /&gt;
Be sure to #include &amp;lt;linux/fb.h&amp;gt; to get access to the FB device ioctl interface, and &amp;lt;sys/ioctl.h&amp;gt; for access to ioctl itself.&lt;br /&gt;
&lt;br /&gt;
====double buffering====&lt;br /&gt;
This can be achieved using FBIOPAN_DISPLAY ioctl system call. For this you need to mmap framebuffer of double size&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
buffer1 = mmap(0, 800*480*2 * 2, PROT_WRITE, MAP_SHARED, fbdev, 0);&lt;br /&gt;
buffer2 = (char *)mem + 800*480*2;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
or map 2 buffers&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
buffer1 = mmap(0, 800*480*2 * 2, PROT_WRITE, MAP_SHARED, fbdev, 0);&lt;br /&gt;
buffer2 = mmap(0, 800*480*2 * 2, PROT_WRITE, MAP_SHARED, fbdev, 800*480*2);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Then to display buffer2 you would call:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
struct fb_var_screeninfo fbvar;&lt;br /&gt;
ioctl(fbdev, FBIOGET_VSCREENINFO, &amp;amp;fbvar);&lt;br /&gt;
fbvar.yoffset = 480;&lt;br /&gt;
ioctl(fbdev, FBIOPAN_DISPLAY, &amp;amp;fbvar);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
going back to buffer1 would be repeating above with fbvar.yoffset = 0. Tripple or quad buffering can be implemented using the same technique.&lt;br /&gt;
&lt;br /&gt;
====vertical sync====&lt;br /&gt;
Linux has standard FBIO_WAITFORVSYNC for this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
int arg = 0;&lt;br /&gt;
ioctl(fbdev, FBIO_WAITFORVSYNC, &amp;amp;arg);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
be sure to pass argument value 0 or it will not work.&lt;br /&gt;
&lt;br /&gt;
Currently FBIO_WAITFORVSYNC is not defined in &amp;lt;linux/fb.h&amp;gt;, although this is in the process of modification. For now, define in the following manner:&lt;br /&gt;
&lt;br /&gt;
#ifndef FBIO_WAITFORVSYNC&lt;br /&gt;
  #define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32)&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
====hardware scaling====&lt;br /&gt;
Overlay1 (/dev/fb1) can be used to achieve hardware scaling. Technically overlay2 (fb2) can be used for this too, but it is planned to be used by the system for TV-out functionality, so don't use it. The overlay is configured using series of standard and OMAP specific ioctl calls, but the system ships with some tools to achieve this from scripts too. This way the framebuffer can be set up for some arbitrary size (say 320x240) and can output to LCD as 800x480 with hardware scaling.&lt;br /&gt;
Here is an example script:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ofbset -fb /dev/fb1 -pos 0 0 -size 800 480 -mem 307200 -en 1&lt;br /&gt;
fbset -fb /dev/fb1 -g 320 240 320 480 16&lt;br /&gt;
&lt;br /&gt;
./your_app_here&lt;br /&gt;
&lt;br /&gt;
ofbset -fb /dev/fb1 -pos 0 0 -size 0 0 -mem 0 -en 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What it does:&lt;br /&gt;
* allocates OMAP DSS layer, asks video output to be 800x480 at position 0,0 (could set it to 640x480 at 80,0 instead to get centered 2x scaling of 320x240). 307200 bytes of video memory are allocated for 2 320x240 16bpp screens (for doublebuffering).&lt;br /&gt;
* sets video mode to 320x240@16bpp, virtual resolution 320x480 for doublebuffering.&lt;br /&gt;
* runs your app&lt;br /&gt;
* cleans the video layer on exit&lt;br /&gt;
&lt;br /&gt;
Now the program can act as if works with 16bpp screen.&lt;br /&gt;
&lt;br /&gt;
==LEDs and backlight==&lt;br /&gt;
The LEDs can be controlled via /sys/class/leds/, and then a file [http://www.gp32x.com/board/index.php?s=&amp;amp;showtopic=45309&amp;amp;view=findpost&amp;amp;p=673593]:&lt;br /&gt;
* pandora::sd1&lt;br /&gt;
* pandora::sd2&lt;br /&gt;
* pandora::charger&lt;br /&gt;
* pandora::power&lt;br /&gt;
* pandora::bluetooth&lt;br /&gt;
* pandora::wifi&lt;br /&gt;
* pandora::keypad_bl&lt;br /&gt;
Backlight can be controlled via /sys/class/backlight/.&lt;br /&gt;
&lt;br /&gt;
==Misc==&lt;br /&gt;
Some things can be controlled through files in /proc/pandora/:&lt;br /&gt;
* /proc/pandora/cpu_mhz_max - if [http://www.kernel.org/pub/linux/utils/kernel/cpufreq/cpufreq.html cpufreq] is enabled, sets maximum allowed cpu clock, if not, just sets CPU clock to value supplied (echo 600 &amp;gt; /proc/pandora/cpu_mhz_max). Might also just use cpufreq parameters themselves.&lt;br /&gt;
more to come..&lt;br /&gt;
[[Category:Development]]&lt;/div&gt;</summary>
		<author><name>Exophase</name></author>
		
	</entry>
	<entry>
		<id>https://pandorawiki.org/index.php?title=Kernel_interface&amp;diff=2414</id>
		<title>Kernel interface</title>
		<link rel="alternate" type="text/html" href="https://pandorawiki.org/index.php?title=Kernel_interface&amp;diff=2414"/>
		<updated>2010-06-19T10:56:07Z</updated>

		<summary type="html">&lt;p&gt;Exophase: /* framebuffer interface */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Warning''': if your goal is just to write a game/program use higher level libraries/interfaces like SDL, Qt, X or similar for your own good (portability). It may be impossible to retain this layout on some major hardware revision, let's say Pandora 3000, and your program will break. Also this requires some level of Linux programming knowledge.&lt;br /&gt;
&lt;br /&gt;
In case you need to write low level code (you can't/don't want to use high level libs like SDL), you can use kernel interface. This is the recommended way to access hardware (as opposed to GP2X style of accessing chip registers by mmap'ing /dev/mem), because in case hardware changes are needed in future, they could be handled by kernel and all programs would still work. It also should allow several programs to work at the same time and should be more stable.&lt;br /&gt;
&lt;br /&gt;
==Input==&lt;br /&gt;
Buttons, keypad, touchscreen and nubs are all exposed through Linux event interface (EVDEV). All devices are represented by /dev/input/eventX files, which can be opened, read and queried (using ioctl calls). The reads can be synchronous (the read will only return when user does something, like presses the button), or asynchronous (the system will report what changed since the last time you asked).&lt;br /&gt;
&lt;br /&gt;
'''Warning''': don't hardcode device filenames in your program! For example, currently /dev/input/event2 represents game buttons, but in future it may become touchscreen. Scan input device names instead, example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
for (i = 0; 1; i++)&lt;br /&gt;
{&lt;br /&gt;
  sprintf(name, &amp;quot;/dev/input/event%i&amp;quot;, i);&lt;br /&gt;
  fd = open(name, O_RDONLY);&lt;br /&gt;
  if (fd &amp;lt; 0) break; /* no more devices */&lt;br /&gt;
  ioctl(fd, EVIOCGNAME(sizeof(name)), name);&lt;br /&gt;
  if (strcmp(name, &amp;quot;gpio-keys&amp;quot;) == 0)&lt;br /&gt;
    return fd; /* found the buttons! */&lt;br /&gt;
  close(fd); /* we don't need this device */&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List of device names and events they send:&lt;br /&gt;
{|border=1 cellpadding=2 cellspacing=0&lt;br /&gt;
|-&lt;br /&gt;
!name&lt;br /&gt;
!description&lt;br /&gt;
!event.type&lt;br /&gt;
!event.code&lt;br /&gt;
!event.value&lt;br /&gt;
|-&lt;br /&gt;
|keypad&lt;br /&gt;
|keypad&lt;br /&gt;
|EV_KEY&lt;br /&gt;
|KEY_0...KEY_Z, KEY_BACKSPACE, KEY_LEFTSHIFT, KEY_SPACE, KEY_ENTER, KEY_COMMA, KEY_DOT, KEY_FN&lt;br /&gt;
|0 - released, 1 - pressed, 2 - autorepeat event&lt;br /&gt;
|-&lt;br /&gt;
|gpio-keys&lt;br /&gt;
|game buttons&lt;br /&gt;
|EV_KEY&lt;br /&gt;
|KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT, KEY_MENU (Pandora button), KEY_LEFTALT (Start), KEY_LEFTCTRL (Select), KEY_KP1 (Y/North), KEY_KP2 (A/East), KEY_KP3 (X/South), KEY_KP4 (B/West), KEY_KP5 (Shoulder L), KEY_KP6 (Shoulder R), KEY_KP7 (Shoulder L2), KEY_KP8 (Shoulder R2), KEY_COFFEE (Hold)&lt;br /&gt;
|0 - released, 1 - pressed&lt;br /&gt;
|-&lt;br /&gt;
|gpio-keys&lt;br /&gt;
|lid state&lt;br /&gt;
|EV_SW&lt;br /&gt;
|SW_LID&lt;br /&gt;
|0 - closing, 1 - opening&lt;br /&gt;
|-&lt;br /&gt;
|touchscreen&lt;br /&gt;
|touchscreen&lt;br /&gt;
|EV_ABS&lt;br /&gt;
|ABS_X, ABS_Y, ABS_PRESSURE&lt;br /&gt;
|varies, use calibration data&lt;br /&gt;
|-&lt;br /&gt;
|nub0&lt;br /&gt;
|left nub&lt;br /&gt;
|EV_ABS&lt;br /&gt;
|ABS_X, ABS_Y&lt;br /&gt;
| -256 (Left/Up) ...0... +256 (Right/Down)&lt;br /&gt;
|-&lt;br /&gt;
|nub1&lt;br /&gt;
|right nub&lt;br /&gt;
|EV_ABS&lt;br /&gt;
|ABS_X, ABS_Y&lt;br /&gt;
| -256 (Left/Up) ...0... +256 (Right/Down)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Sample code:&amp;lt;br&amp;gt;&lt;br /&gt;
[http://beagleboard.googlecode.com/files/evtest.c evtest.c]&lt;br /&gt;
[http://git.openpandora.org/cgi-bin/gitweb.cgi?p=pandora-misc.git;a=blob;f=op_test_inputs.c;hb=HEAD op_test_inputs.c]&lt;br /&gt;
&lt;br /&gt;
===Touchscreen===&lt;br /&gt;
Event interface returns uncalibrated values directly from driver, so you need to use tslib or manage calibration yourself (using data from /etc/pointercal).&lt;br /&gt;
&lt;br /&gt;
==Sound==&lt;br /&gt;
Pandora uses ALSA, but it has OSS emulation enabled too, so GP2X code should work.&lt;br /&gt;
&lt;br /&gt;
==Video==&lt;br /&gt;
===Architecture===&lt;br /&gt;
Framebuffer device (/dev/fbX) is supported. There are 3 framebuffers available (/dev/fb0, /dev/fb1 and /dev/fb2), which represent 3 graphics/video layers on OMAP3 by default (but can be reconfigured). Only /dev/fb0 is enabled by default.&lt;br /&gt;
&lt;br /&gt;
OMAP3 display subsystem is controlled by a driver known as DSS2, which has various controls available on /sys/devices/platform/omapdss/ (but they are not meant to be changed by programs, so they are root writable only). The driver exposes 3 layers (called overlays) and 2 displays. Overlays 1 and 2 can perform hardware scaling on the fly using 5-tap poly-phase filter, overlay0 can not. Displays 0 and 1 represent LCD and TV respectively. By default the 3 framebuffers (/dev/fbX) are redirected to 3 overlays, which all output to the LCD. This configuration is not meant to be changed by programs, only firmware should manage these.&lt;br /&gt;
&lt;br /&gt;
===Basic usage===&lt;br /&gt;
====framebuffer interface====&lt;br /&gt;
Framebuffers can be accessed Linux fbdev interface:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
fbdev = open(&amp;quot;/dev/fb0&amp;quot;, O_RDONLY);&lt;br /&gt;
buffer = mmap(0, 800*480*2, PROT_WRITE, MAP_SHARED, fbdev, 0);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
(this is basic example, no error checks)&lt;br /&gt;
&lt;br /&gt;
the returned pointer can be used to draw on the screen.&lt;br /&gt;
&lt;br /&gt;
Be sure to #include &amp;lt;linux/fb.h&amp;gt; to get access to the FB device ioctl interface, and &amp;lt;sys/ioctl.h&amp;gt; for access to ioctl itself.&lt;br /&gt;
&lt;br /&gt;
====double buffering====&lt;br /&gt;
This can be achieved using FBIOPAN_DISPLAY ioctl system call. For this you need to mmap framebuffer of double size&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
buffer1 = mmap(0, 800*480*2 * 2, PROT_WRITE, MAP_SHARED, fbdev, 0);&lt;br /&gt;
buffer2 = (char *)mem + 800*480*2;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
or map 2 buffers&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
buffer1 = mmap(0, 800*480*2 * 2, PROT_WRITE, MAP_SHARED, fbdev, 0);&lt;br /&gt;
buffer2 = mmap(0, 800*480*2 * 2, PROT_WRITE, MAP_SHARED, fbdev, 800*480*2);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Then to display buffer2 you would call:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
struct fb_var_screeninfo fbvar;&lt;br /&gt;
ioctl(fbdev, FBIOGET_VSCREENINFO, &amp;amp;fbvar);&lt;br /&gt;
fbvar.yoffset = 480;&lt;br /&gt;
ioctl(fbdev, FBIOPAN_DISPLAY, &amp;amp;fbvar);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
going back to buffer1 would be repeating above with fbvar.yoffset = 0. Tripple or quad buffering can be implemented using the same technique.&lt;br /&gt;
&lt;br /&gt;
====vertical sync====&lt;br /&gt;
Linux has standard FBIO_WAITFORVSYNC for this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
int arg = 0;&lt;br /&gt;
ioctl(fbdev, FBIO_WAITFORVSYNC, &amp;amp;arg);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
be sure to pass argument value 0 or it will not work.&lt;br /&gt;
&lt;br /&gt;
====hardware scaling====&lt;br /&gt;
Overlay1 (/dev/fb1) can be used to achieve hardware scaling. Technically overlay2 (fb2) can be used for this too, but it is planned to be used by the system for TV-out functionality, so don't use it. The overlay is configured using series of standard and OMAP specific ioctl calls, but the system ships with some tools to achieve this from scripts too. This way the framebuffer can be set up for some arbitrary size (say 320x240) and can output to LCD as 800x480 with hardware scaling.&lt;br /&gt;
Here is an example script:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ofbset -fb /dev/fb1 -pos 0 0 -size 800 480 -mem 307200 -en 1&lt;br /&gt;
fbset -fb /dev/fb1 -g 320 240 320 480 16&lt;br /&gt;
&lt;br /&gt;
./your_app_here&lt;br /&gt;
&lt;br /&gt;
ofbset -fb /dev/fb1 -pos 0 0 -size 0 0 -mem 0 -en 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What it does:&lt;br /&gt;
* allocates OMAP DSS layer, asks video output to be 800x480 at position 0,0 (could set it to 640x480 at 80,0 instead to get centered 2x scaling of 320x240). 307200 bytes of video memory are allocated for 2 320x240 16bpp screens (for doublebuffering).&lt;br /&gt;
* sets video mode to 320x240@16bpp, virtual resolution 320x480 for doublebuffering.&lt;br /&gt;
* runs your app&lt;br /&gt;
* cleans the video layer on exit&lt;br /&gt;
&lt;br /&gt;
Now the program can act as if works with 16bpp screen.&lt;br /&gt;
&lt;br /&gt;
==LEDs and backlight==&lt;br /&gt;
The LEDs can be controlled via /sys/class/leds/, and then a file [http://www.gp32x.com/board/index.php?s=&amp;amp;showtopic=45309&amp;amp;view=findpost&amp;amp;p=673593]:&lt;br /&gt;
* pandora::sd1&lt;br /&gt;
* pandora::sd2&lt;br /&gt;
* pandora::charger&lt;br /&gt;
* pandora::power&lt;br /&gt;
* pandora::bluetooth&lt;br /&gt;
* pandora::wifi&lt;br /&gt;
* pandora::keypad_bl&lt;br /&gt;
Backlight can be controlled via /sys/class/backlight/.&lt;br /&gt;
&lt;br /&gt;
==Misc==&lt;br /&gt;
Some things can be controlled through files in /proc/pandora/:&lt;br /&gt;
* /proc/pandora/cpu_mhz_max - if [http://www.kernel.org/pub/linux/utils/kernel/cpufreq/cpufreq.html cpufreq] is enabled, sets maximum allowed cpu clock, if not, just sets CPU clock to value supplied (echo 600 &amp;gt; /proc/pandora/cpu_mhz_max). Might also just use cpufreq parameters themselves.&lt;br /&gt;
more to come..&lt;br /&gt;
[[Category:Development]]&lt;/div&gt;</summary>
		<author><name>Exophase</name></author>
		
	</entry>
</feed>