Medallia Blog

August 28, 2007

iPhone accelerometer source code

Here'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!

[updated 9/3: fixed typo]

#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);
}

August 27, 2007

Fun with the iPhone accelerometer

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 , 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. Source code will be posted as soon as possible is posted here. (update: yes, it is possible to access the accelerometer directly through UIKit without this hack -- however, you'll be locked to the default sample rate, which is too slow for some of the fun stuff)

Straw poll: What would you like to see on the iPhone?