From 1356a1e31b60b945da0706fd5076d30579b75b30 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Wed, 12 Mar 2008 05:48:38 +0000 Subject: working object for getting the sensor data from the Apple LMU aka 'ambient light sensor' svn path=/trunk/externals/apple/; revision=9572 --- ambient_light_sensor.c | 202 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 202 insertions(+) create mode 100644 ambient_light_sensor.c (limited to 'ambient_light_sensor.c') diff --git a/ambient_light_sensor.c b/ambient_light_sensor.c new file mode 100644 index 0000000..f1899e8 --- /dev/null +++ b/ambient_light_sensor.c @@ -0,0 +1,202 @@ +/* --------------------------------------------------------------------------*/ +/* */ +/* read the ambient light sensor on Apple Mac OS X */ +/* Written by Hans-Christoph Steiner */ +/* */ +/* Copyright (c) 2008 Free Software Foundation */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* See file LICENSE for further informations on licensing terms. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program; if not, write to the Free Software Foundation, */ +/* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ +/* */ +/* --------------------------------------------------------------------------*/ + +#include +#include +#include +#include + +#define DEBUG(x) +//#define DEBUG(x) x + +#define DEFAULT_DELAYTIME 250 + +/*------------------------------------------------------------------------------ + * CLASS DEF + */ + +static t_class *ambient_light_sensor_class; + +typedef struct _ambient_light_sensor { + t_object x_obj; + t_clock* clock; + t_float delaytime; + + t_symbol* sensor_name; + + io_service_t io_service; + io_connect_t io_connect; + + t_outlet* data_outlet; + t_outlet* status_outlet; +} t_ambient_light_sensor; + + + +enum { + kGetSensorReadingID = 0, // getSensorReading(int *, int *) + kGetLEDBrightnessID = 1, // getLEDBrightness(int, int *) + kSetLEDBrightnessID = 2, // setLEDBrightness(int, int, int *) + kSetLEDFadeID = 3, // setLEDFade(int, int, int, int *) + // other firmware-related functions + // verifyFirmwareID = 4, + // verifyFirmware(int *) + // getFirmwareVersionID = 5, + // getFirmwareVersion(int *) + // other flashing-related functions + // ... +}; + +/*------------------------------------------------------------------------------ + * IMPLEMENTATION + */ + +static void ambient_light_sensor_output(t_ambient_light_sensor* x) +{ + DEBUG(post("ambient_light_sensor_output");); + kern_return_t kernResult; + IOItemCount scalarInputCount = 0; + IOItemCount scalarOutputCount = 2; + SInt32 left = 0, right = 0; + t_atom output_atoms[2]; + + if(x->io_connect) + { + kernResult = IOConnectMethodScalarIScalarO(x->io_connect, + kGetSensorReadingID, + scalarInputCount, + scalarOutputCount, + &left, + &right); + if( kernResult == KERN_SUCCESS) + { + SETFLOAT(output_atoms, left); + SETFLOAT(output_atoms + 1, right); + outlet_anything(x->x_obj.ob_outlet, gensym("light"), 2, output_atoms); + } + else if(kernResult == kIOReturnBusy) + pd_error(x,"[ambient_light_sensor]: device busy"); + else + pd_error(x,"[ambient_light_sensor]: could not read device"); + } +} + + +static void ambient_light_sensor_info(t_ambient_light_sensor* x) +{ + t_atom output_atom; + SETSYMBOL(&output_atom, x->sensor_name); + outlet_anything(x->status_outlet, gensym("sensor"), 1, &output_atom); + SETFLOAT(&output_atom, x->delaytime); + outlet_anything(x->status_outlet, gensym("poll"), 1, &output_atom); +} + + +static void ambient_light_sensor_tick(t_ambient_light_sensor* x) +{ + ambient_light_sensor_output(x); + clock_delay(x->clock, x->delaytime); +} + + +static void ambient_light_sensor_float(t_ambient_light_sensor* x, t_float f) +{ + DEBUG(post("ambient_light_sensor_float");); + if(f < 1.) + clock_unset(x->clock); + else if(f > 1.) + { + x->delaytime = f; + clock_delay(x->clock, x->delaytime); + } + else + clock_delay(x->clock, x->delaytime); + +} + + +static void ambient_light_sensor_free(t_ambient_light_sensor* x) +{ + DEBUG(post("ambient_light_sensor_free");); + clock_free(x->clock); +} + + +static void *ambient_light_sensor_new(void) +{ + DEBUG(post("ambient_light_sensor_new");); + t_ambient_light_sensor *x = (t_ambient_light_sensor *)pd_new(ambient_light_sensor_class); + kern_return_t kernResult; + + x->io_service = IOServiceGetMatchingService(kIOMasterPortDefault, + IOServiceMatching("AppleLMUController")); + if(x->io_service) + { + post("[ambient_light_sensor]: found AppleLMUController"); + x->sensor_name = gensym("AppleLMUController"); + } + else + { + error("[ambient_light_sensor]: AppleLMUController not found, trying IOI2CDeviceLMU"); + x->io_service = IOServiceGetMatchingService(kIOMasterPortDefault, + IOServiceMatching("IOI2CDeviceLMU")); + if(x->io_service) + { + x->sensor_name = gensym("IOI2CDeviceLMU"); + post("[ambient_light_sensor]: found IOI2CDeviceLMU"); + } + else + pd_error(x,"[ambient_light_sensor]: no sensor found"); + } + kernResult = IOServiceOpen(x->io_service, mach_task_self(), 0, &x->io_connect); + + IOObjectRelease(x->io_service); + if (kernResult != KERN_SUCCESS) + { + error("[ambient_light_sensor]: IOServiceOpen(): %d", kernResult); + } + + x->clock = clock_new(x, (t_method)ambient_light_sensor_tick); + x->delaytime = DEFAULT_DELAYTIME; + x->data_outlet = outlet_new(&x->x_obj, &s_anything); + x->status_outlet = outlet_new(&x->x_obj, &s_anything); + + return (x); +} + +void ambient_light_sensor_setup(void) +{ + ambient_light_sensor_class = class_new(gensym("ambient_light_sensor"), + (t_newmethod)ambient_light_sensor_new, + (t_method)ambient_light_sensor_free, + sizeof(t_ambient_light_sensor), + CLASS_DEFAULT, + 0); + /* add inlet datatype methods */ + class_addbang(ambient_light_sensor_class,(t_method) ambient_light_sensor_output); + class_addfloat(ambient_light_sensor_class,(t_method) ambient_light_sensor_float); + class_addmethod(ambient_light_sensor_class,(t_method) ambient_light_sensor_info, + gensym("info"), 0); +} -- cgit v1.2.1