|
Posted August 27 2007 PHP has finally taken the plunge into the 1960s by implementing GOTO. Here's an implementation for Java. A patch for a serious Java bug. No longer needed as of June 16. Max & Michael have written a Max/MSP driver based on the multitouch code. This is a little test applet to shows the touch points as reported by the MacBook multitouch pad. The drivers seems to be able to track an impressive 11 fingers at once.
My CSS-fu is weak; please use a recent browser. Random, semi-related image by Chrysophylax. |
Fun with the iPhone accelerometerHistorical note: This is obsolete now that the official Apple SDK has been released.
Note (9/12): there is an application in the iBrickr PXL repository called 'Balls' which links to this page. I have nothing to do with that app; it was created by Grudgnor over at the MacRumors forum. Those who have followed this blog will know that I like to like to play with unusual input methods (see my earlier posts on multitouch, ambient light sensors, and the SmackBook). As it turns out, the iPhone has a built-in LIS302DL, a tiny 3-axis accelerometer. While some have attempted to use it from within the Safari browser (the Tilt game detects changes to the width of the browser page; it is basically used as a 1-bit input device), its potential is still somewhat untapped. After a rather lengthy bout of reverse-engineering (I had barely touched ARM assembly before this), I finally figured out how to access the raw data from the accelerometer itself, as can be seen in the video above. CodeHere's some code to initialize the accelerometer to run at full speed. Pass the desired sample rate (in Hz) to the initialize function. Go wild!
#include <IOKit/IOKitLib.h>
#include <CoreFoundation/CoreFoundation.h>
typedef struct {} *IOHIDEventSystemRef;
typedef struct {} *IOHIDEventRef;
float IOHIDEventGetFloatValue(IOHIDEventRef ref, int param);
void handleHIDEvent(int a, int b, int c, IOHIDEventRef ptr) {
int type = IOHIDEventGetType(ptr);
if (type == 12) {
float x,y,z;
x = IOHIDEventGetFloatValue(ptr, 0xc0000);
y = IOHIDEventGetFloatValue(ptr, 0xc0001);
z = IOHIDEventGetFloatValue(ptr, 0xc0002);
// do whatever you need to do with the gravity
ballSetAccel(x, y);
}
}
#define expect(x) if(!x) { printf("failed: %s\n", #x); return; }
void initialize(int hz) {
mach_port_t master;
expect(0 == IOMasterPort(MACH_PORT_NULL, &master));
int page = 0xff00, usage = 3;
CFNumberRef nums[2];
CFStringRef keys[2];
keys[0] = CFStringCreateWithCString(0, "PrimaryUsagePage", 0);
keys[1] = CFStringCreateWithCString(0, "PrimaryUsage", 0);
nums[0] = CFNumberCreate(0, kCFNumberSInt32Type, &page);
nums[1] = CFNumberCreate(0, kCFNumberSInt32Type, &usage);
CFDictionaryRef dict = CFDictionaryCreate(0,
(const void**)keys,
(const void**)nums,
2,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
expect(dict);
IOHIDEventSystemRef sys = (IOHIDEventSystemRef) IOHIDEventSystemCreate(0);
expect(sys);
CFArrayRef srvs = (CFArrayRef)IOHIDEventSystemCopyMatchingServices(sys, dict, 0, 0, 0);
expect(CFArrayGetCount(srvs)==1);
io_registry_entry_t serv = (io_registry_entry_t)CFArrayGetValueAtIndex(srvs, 0);
expect(serv);
CFStringRef cs = CFStringCreateWithCString(0, "ReportInterval", 0);
int rv = 1000000/hz;
CFNumberRef cn = CFNumberCreate(0, kCFNumberSInt32Type, &rv);
int res = IOHIDServiceSetProperty(serv, cs, cn);
expect(res == 1);
res = IOHIDEventSystemOpen(sys, handleHIDEvent, 0, 0);
expect(res != 0);
}
Comments |