[quote="pstudio"]I have been away for the weekend on a secluded island which means that I've had some time to fool araound with my GP2X.
I've been succesful reading input from the touchscreen*. It even worked at first attempt
If any are interested in it (have a GP2X F200), I've uploaded the code and binaries here.
It's not 100 % accurate since it isn't calibrated correct. I know some guys have manged to load the settings from the GP2X, so I'll have to look into that next.
*Thanks to joyrider, hangman etc. @ gp32x.com and their example c code.
@Paul
I've also taken a closer look at Eugenes code and worked a bit with SDL_Mixer. Blocks work fine regarding playing ogg-files via mixer. However when I wrote my own testprogram it worked fine on windows, but crashed on the GP2X. But when I compiled the program I got a warning that said something about static ]
Hi pstudio,
Great work with the touch screen stuff :-)
I was 'talking' to Eugene via email and asking him about dynamic linking and he says that he only uses static linking as he can't get a batch file? for dynamic linking...
I also told him about the SDL_Mixer crashes on the gp2x and he suggested I make a small project with sound and send it to him so he can compile and test it. I am going to do this and I will get back to you guys when I know more.
PS
If it helps I had created a pascal unit that links some ARM asm which allows you to use access the gp2x linux system 'files' stuff ('/dev/fb0', etc) in the same way as the C/C++ guys do.
libgp2x_asm.s
Code:
@ gp2x demo article code by Dzz
@ this code is placed in the public domain. do anything you want with it.
.align 4
.globl OpenFile
.globl CloseFile
.globl WriteFile
.globl MUnmap
.globl ChangeDir
.globl ExecuteFile
.globl MMap
.globl CopyScreen
.globl ClearScreen
.globl Ioctl3
OpenFile:
swi #0x900005
mov pc, lr
CloseFile:
swi #0x900006
mov pc, lr
WriteFile:
swi #0x900004
mov pc, lr
MUnmap:
swi #0x90005B
mov pc, lr
ChangeDir:
swi #0x90000C
mov pc, lr
ExecuteFile:
swi #0x90000B
mov pc, lr
Ioctl3:
swi #0x900036
mov pc, lr
MMap:
stmdb sp!, {r0, r1, r2, r3}
mov r0, sp
swi #0x90005A
add sp, sp, #16
mov pc, lr
CopyScreen:
stmfd sp!, {r4-r10} @ remember registers 4-10
mov r2, #4800 @ we will run the loop 4800 times to copy the screen
.CopyScreenLoop:
ldmia r1!, {r3-r10} @ pull in 32 bytes from the source
stmia r0!, {r3-r10} @ write the 32 bytes to the destination
subs r2, r2, #1 @ decrement the loop counter
bne .CopyScreenLoop @ if we're not done, do it again
ldmfd sp!, {r4-r10} @ restore the registers
mov pc, lr @ return
ClearScreen:
stmfd sp!, {r4-r10} @ remember registers 4-10
mov r2, #4800 @ we will run the loop 4800 times to copy the screen
mov r3, #0 @ load up the registers with zeros
mov r4, #0
mov r5, #0
mov r6, #0
mov r7, #0
mov r8, #0
mov r9, #0
mov r10, #0
.ClearScreenLoop:
stmia r0!, {r3-r10} @ write the 32 bytes of zeros to the destination
subs r2, r2, #1 @ decrement the loop counter
bne .ClearScreenLoop @ if we're not done, do it again
ldmfd sp!, {r4-r10} @ restore the registers
mov pc, lr @ return
assemble the .s file like so
Code:
arm-linux-gcc.exe -c libgp2x_asm.s
libgp2x.pas
Code:
Unit libgp2x;
{$link libgp2x_asm.o}
{$linklib c}
Interface
Uses
CTypes;
Const
MREMAP_MAYMOVE = 1;
MREMAP_FIXED = 2;
PROT_READ = $1; // page can be read
PROT_WRITE = $2; // page can be written
PROT_EXEC = $4; // page can be executed
PROT_NONE = $0; // page can not be accessed
MAP_SHARED = $01; // Share changes
MAP_PRIVATE = $02; // Changes are private
{$IFDEF gp2x}
MAP_FIXED = $10; // Interpret addr exactly
MAP_ANONYMOUS = $20; // don't use a file
MAP_GROWSDOWN = $0100; // stack-like segment
MAP_DENYWRITE = $0800; // ETXTBSY
MAP_EXECUTABLE = $1000; // mark it as an executable
MAP_LOCKED = $2000; // pages are locked
MAP_NORESERVE = $4000; // don't check for reservations
MS_ASYNC = 1; // sync memory asynchronously
MS_INVALIDATE = 2; // invalidate the caches
MS_SYNC = 4; // synchronous memory sync
MCL_CURRENT = 1; // lock all current mappings
MCL_FUTURE = 2; // lock all future mappings
MADV_NORMAL = $0; // default page-in behavior
MADV_RANDOM = $1; // page-in minimum required
MADV_SEQUENTIAL = $2; // read-ahead aggressively
MADV_WILLNEED = $3; // pre-fault pages
MADV_DONTNEED = $4; // discard these pages
O_RDWR = 2;
{$ENDIF}
// compatibility flags
MAP_ANON = MAP_ANONYMOUS;
MAP_FILE = 0;
MAP_FAILED = Pointer(-1);
Type
Tgp2xDevice = Class
Protected
FDev : ctypes.cint32;
FMemData : Pointer;
FMemSize : ctypes.cint32;
Public
Constructor Create(pszFile: PChar; nMode: ctypes.cint32);
Destructor Destroy; Override;
Procedure MapMem(pAddr: Pointer; nLen,nProtection,nFlags,nOff: ctypes.cint32);
Procedure UnmapMem;
Property MemData: Pointer Read FMemData;
End;
Function OpenFile(pszFile: PChar; nMode: ctypes.cint32): ctypes.cint32; Cdecl; External;
Procedure CloseFile(nFile: ctypes.cint32); Cdecl; External;
Function MMap(pAddr: Pointer; nLen,nProtection,nFlags,nFD,nOff: ctypes.cint32): Pointer; Cdecl; External;
Procedure MUnmap(p: Pointer; nSize: ctypes.cint32); Cdecl; External;
Procedure ChangeDir(pszDir: PChar); Cdecl; External;
Procedure ExecuteFile(pszFile: PChar; nZero1,nZero2: ctypes.cint32); Cdecl; External;
Function Ioctl3(fd: ctypes.cint32; ulFunction,ulParameter: ctypes.cushort): ctypes.cint32; Cdecl; External;
Procedure CopyScreen(pDest,pSrc: ctypes.pcushort); Cdecl; External;
Procedure ClearScreen(pus: ctypes.pcushort); Cdecl; External;
Procedure RestartMenu;
Implementation
Constructor Tgp2xDevice.Create(pszFile: PChar; nMode: ctypes.cint32);
Begin
Inherited Create;
FDev := 0;
FMemData := Nil;
FMemSize := 0;
FDev := OpenFile(pszFile,nMode);
End;
{..............................................................................}
{..............................................................................}
Destructor Tgp2xDevice.Destroy;
Begin
UnmapMem;
If FDev <> 0 Then
CloseFile(FDev);
Inherited Destroy;
End;
{..............................................................................}
{..............................................................................}
Procedure Tgp2xDevice.UnmapMem;
Begin
If FMemData <> Nil Then
Begin
MUnmap(FMemData,FMemSize);
FMemData := Nil;
FMemSize := 0;
End;
End;
{..............................................................................}
{..............................................................................}
Procedure Tgp2xDevice.MapMem(pAddr: Pointer; nLen,nProtection,nFlags,nOff: ctypes.cint32);
Begin
UnmapMem;
FMemSize := nLen;
FMemData := MMap(pAddr, FMemSize, nProtection, nFlags, FDev, nOff);
End;
{..............................................................................}
{..............................................................................}
Procedure RestartMenu;
Begin
ChangeDir (PChar('/usr/gp2x'));
ExecuteFile(PChar('/usr/gp2x/gp2xmenu'), 0, 0);
End;
{..............................................................................}
{..............................................................................}
End.
usage examples
Code:
Const
cRscale = 5;
cGscale = 6;
cBscale = 5;
cRshift = 11;
cGshift = 5;
cBshift = 0;
{..............................................................................}
{..............................................................................}
Function RGBTo16Bit(r,g,b: Uint8): Uint16;
Begin
Result := (((r Shl cRscale) Shl 8) Shl cRshift) +
(((g Shl cGscale) Shl 8) Shl cGshift) +
(((b Shl cBscale) Shl 8) Shl cBshift);
End;
{..............................................................................}
{..............................................................................}
Ffb0 := Tgp2xDevice.Create('/dev/fb0', O_RDWR);
Ffb1 := Tgp2xDevice.Create('/dev/fb1', O_RDWR);
FWidth := 320;
FHeight := 240;
FBitsPerPixel := 16;
Ffb0.MapMem(Nil, FWidth * FHeight * (FBitsPerPixel Div 8), PROT_WRITE, MAP_SHARED, 0);
Ffb1.MapMem(Nil, FWidth * FHeight * (FBitsPerPixel Div 8), PROT_WRITE, MAP_SHARED, 0);
{...}
Procedure TRendererModule_gp2x.ClearScreen(r,g,b: Byte);
Var
c : Uint32;
i : LongInt;
addr : PUint8;
Begin
c := RGBTo16Bit(r,g,b);
addr := Ffb1.MemData;
i := FWidth * FHeight;
While i <= 0 Do
Begin
PUint16(addr)^ := Uint16(c);
Inc(addr,2);
Dec(i);
End;
End;
{..............................................................................}
{..............................................................................}
Procedure TRendererModule_gp2x.FlipScreen;
Begin
CopyScreen(Ffb0.MemData,Ffb1.MemData);
End;
{..............................................................................}
{..............................................................................}
{...}
Ffb0.Free;
Ffb1.Free;
You could use this for your touchscreen code as well by opening up the device using the Tgp2xDevice class.
Enjoy
cheers,
Paul
Bookmarks