2010年5月27日木曜日

USBシリアルを監視するパッチ

動機
ScratchのようにArduinoでなにか信号をもらうのをQuartzComposerに出すとかやってみようかな.


参考
Re: Serial Read in Objective C under OSX? Reply #2 http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1243282360/2#2
感謝



やってみた
#import <Quartz/Quartz.h>

#include <stdio.h> /* Standard input/output definitions */
#include <string.h> /* String function definitions */
#include <unistd.h> /* UNIX standard function definitions */
#include <fcntl.h> /* File control definitions */
#include <errno.h> /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */

@interface USBSerialRXPlugIn : QCPlugIn
{
int fd;
NSMutableArray *lineBuffer;

BOOL isAlive;
}

@property NSUInteger inputPort;
@property(assign) NSString *outputMessage;

int USBSerialInit(const char *port);

@end


#import <OpenGL/CGLMacro.h>

#import "USBSerialRXPlugIn.h"

#define kQCPlugIn_Name @"USBSerial RX"
#define kQCPlugIn_Description @"USBSerial RX description"

@implementation USBSerialRXPlugIn

@dynamic inputPort;
@dynamic outputMessage;

+ (NSDictionary*) attributes
{
return [NSDictionary dictionaryWithObjectsAndKeys:
kQCPlugIn_Name, QCPlugInAttributeNameKey,
kQCPlugIn_Description, QCPlugInAttributeDescriptionKey,
nil];
}

static NSMutableArray *ports;
+ (NSArray *)ports
{
if (ports==nil) {
ports= [[NSMutableArray alloc] init];

NSFileManager *fileManager= [NSFileManager defaultManager];
NSError *err= nil;
NSArray *devices= [fileManager contentsOfDirectoryAtPath:@"/dev" error:&err];
if (err==nil && devices!=nil) {
int i, ic= [devices count];
for(i= 0; i<ic; i++) {
NSString *device= [devices objectAtIndex:i];
if ([device hasPrefix:@"tty.usbserial-"]) {
NSString *portStr= [NSString stringWithFormat:@"/dev/%@", device];
if (![ports containsObject:portStr]) {
[ports addObject:portStr];
}
}
}
}
}
return ports;
}

+ (NSDictionary*) attributesForPropertyPortWithKey:(NSString*)key
{
if([key isEqualToString:@"inputPort"]) {
NSArray *items= [USBSerialRXPlugIn ports];
return [NSDictionary dictionaryWithObjectsAndKeys:
@"Port", QCPortAttributeNameKey,
QCPortTypeIndex, QCPortAttributeTypeKey,
[NSNumber numberWithUnsignedInteger:[items count]-1], QCPortAttributeMaximumValueKey,
items, QCPortAttributeMenuItemsKey,
nil];
}
if([key isEqualToString:@"outputMessage"]) {
return [NSDictionary dictionaryWithObjectsAndKeys:
@"Message", QCPortAttributeNameKey,
nil];
}
return nil;
}

+ (QCPlugInExecutionMode) executionMode
{
return kQCPlugInExecutionModeProcessor;
}

+ (QCPlugInTimeMode) timeMode
{
return kQCPlugInTimeModeIdle;
}

- (id) init
{
if(self = [super init]) {
lineBuffer= [[NSMutableArray array] retain];
}

return self;
}

- (void) finalize
{
[super finalize];
}

- (void) dealloc
{
[lineBuffer release];
[super dealloc];
}
@end

@implementation USBSerialRXPlugIn (Execution)

- (BOOL) startExecution:(id<QCPlugInContext>)context
{
return YES;
}

- (void) enableExecution:(id<QCPlugInContext>)context
{
if (self.inputPort<0) {
return;
}
NSString *port= [[USBSerialRXPlugIn ports] objectAtIndex:self.inputPort];
fd = USBSerialInit([port UTF8String]);
if (fd>-1) {
isAlive= YES;
[NSThread detachNewThreadSelector:@selector(listen)
toTarget:self
withObject:nil];
}
}

- (BOOL) execute:(id<QCPlugInContext>)context
atTime:(NSTimeInterval)time
withArguments:(NSDictionary*)arguments
{
if ([lineBuffer count]>0) {
self.outputMessage= [lineBuffer objectAtIndex:0];
[lineBuffer removeObjectAtIndex:0];
}
else {
if (NO) {
self.outputMessage= [NSString stringWithString:@""];
}
}
return YES;
}

- (void) disableExecution:(id<QCPlugInContext>)context
{
isAlive= NO;
if (fd>-1) {
close(fd);
}
}

- (void) stopExecution:(id<QCPlugInContext>)context
{
[self disableExecution:context];
}

#pragma mark --
- (void)listen
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
char *buffer= (char *)malloc(256);
char *bufptr;
int nbytes;
char inchar;

while (isAlive) {
bufptr = buffer;
while ((nbytes = read(fd, &inchar, 1)) > 0)
{
if (inchar == '\r') continue;
if (inchar == '\n') break;
*bufptr = inchar;
++bufptr;
if (bufptr-buffer>254) break;
}
*bufptr = '\0';
[lineBuffer addObject:[NSString stringWithCString:buffer
encoding:NSUTF8StringEncoding]];
}

free(buffer);
[pool release];
}
int USBSerialInit(const char *port)
{
int fd;
struct termios options;

/* open the USB Serial Port */
fd = open(port, O_RDONLY | O_NOCTTY | O_NDELAY);
if (fd == -1)
{
perror("open_port: Unable to open serial port - ");
return -1;
}
else fcntl(fd, F_SETFL, 0);
/* set the port to 9600 Baud, 8 data bits, etc. */
tcgetattr(fd, &options);
cfsetispeed(&options, B9600);
cfsetospeed(&options, B9600);
options.c_cflag |= (CLOCAL | CREAD);
options.c_cflag &= ~CSIZE; /* Mask the character size bits */
options.c_cflag |= CS8; /* Select 8 data bits */
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
tcsetattr(fd, TCSANOW, &options);
return fd;
}
@end


できた

0 件のコメント: