Windows、C言語でUSB-IO (正確にはUSB-IO2.0(AKI) ) を制御してみました。
「HID(Human Interface Device)として認識するので、ドライバを意識的にインストールする必要が無い」というのが売りのようです。
usb_io.c
#include
#include
#include
#include
#include
#define IO_SIZE 65
typedef struct {
HANDLE hDevice;
int vendor_id, product_id;
HIDP_CAPS caps;
} hid_t;
int openHID(hid_t *hid, int vendor_id, const int product_ids[], int product_id_num) {
GUID hid_guid;
HDEVINFO hDeviceInfo;
int index;
HidD_GetHidGuid(&hid_guid);
if (hid == NULL || product_ids == NULL || product_id_num cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
if (!SetupDiGetDeviceInterfaceDetail(hDeviceInfo, &did, detail, needed_size, &needed_size, &devinfo)) {
HeapFree(GetProcessHeap(), 0, detail);
break;
}
/* このデバイスを開く */
hDevice = CreateFile(detail->DevicePath, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
HeapFree(GetProcessHeap(), 0, detail);
if (hDevice != INVALID_HANDLE_VALUE) {
HIDD_ATTRIBUTES attr;
/* IDがマッチするかを調べる */
if (HidD_GetAttributes(hDevice, &attr) && attr.VendorID == vendor_id) {
int i, matched = 0;
for (i = 0; i caps)) == HIDP_STATUS_SUCCESS) {
/* 結果を返す */
hid->hDevice = hDevice;
hid->vendor_id = attr.VendorID;
hid->product_id = attr.ProductID;
SetupDiDestroyDeviceInfoList(hDeviceInfo);
return 1;
}
}
}
CloseHandle(hDevice);
}
} else {
break;
}
}
SetupDiDestroyDeviceInfoList(hDeviceInfo);
return 0;
}
int writeAndRead(HANDLE hHid,const unsigned char* writeData,unsigned char* readData) {
DWORD size;
if(!WriteFile(hHid,writeData,IO_SIZE,&size,NULL) || size!=IO_SIZE)return 0;
if(!ReadFile(hHid,readData,IO_SIZE,&size,NULL) || size!=IO_SIZE)return 0;
return 1;
}
int writeSettings(HANDLE hUsbIO,int disablePullup,int inputPin) {
unsigned char write_buffer[IO_SIZE]={};
unsigned char read_buffer[IO_SIZE]={};
write_buffer[1]=0xf9;
write_buffer[3]=(disablePullup?1:0);
write_buffer[6]=inputPin&0xff;
write_buffer[7]=(inputPin>>8)&0x0f;
return writeAndRead(hUsbIO,write_buffer,read_buffer);
}
int readSettings(HANDLE hUsbIO,int *disablePullup,int *inputPin) {
unsigned char write_buffer[IO_SIZE]={};
unsigned char read_buffer[IO_SIZE]={};
write_buffer[1]=0xf8;
if(!writeAndRead(hUsbIO,write_buffer,read_buffer))return 0;
if(disablePullup!=NULL)*disablePullup=(read_buffer[3]&1)?1:0;
if(inputPin!=NULL)*inputPin=read_buffer[6]|(read_buffer[7]>8)&0x0f;
if(!writeAndRead(hUsbIO,write_buffer,read_buffer))return 0;
if(readData!=NULL)*readData=read_buffer[2]|(read_buffer[3]>(j+8))&1)?'1':'0');
putchar(((i+1)%16==0)?'\n':'|');
} else {
char err[1024];
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,NULL,GetLastError(),
LANG_USER_DEFAULT,err,sizeof(err),NULL);
printf("%s\n",err);
}
if(wait>0)Sleep(wait);
}
}
int main(int argc,char* argv[]) {
const int vendor_id = 0x1352;
const int product_id[2] = {0x120, 0x121};
const int product_id_num = 2;
hid_t usb_io;
int wait=500;
if(openHID(&usb_io, vendor_id, product_id, product_id_num)) {
printf("vendor_id = 0x%X\n", usb_io.vendor_id);
printf("product_id = 0x%X\n", usb_io.product_id);
printf("writesize = %d\n",usb_io.caps.OutputReportByteLength);
printf("read_size = %d\n",usb_io.caps.InputReportByteLength);
if(usb_io.caps.OutputReportByteLength!=IO_SIZE ||
usb_io.caps.InputReportByteLength!=IO_SIZE) {
puts("unsupported device");
CloseHandle(usb_io.hDevice);
return 1;
}
if(argc>=2) {
if(argv[1][0]=='s' && argv[1][1]=='\0') {
if(argc>=4) {
int disablePullup=0;
int writePin=0xf00;
sscanf(argv[2],"%d",&disablePullup);
sscanf(argv[3],"%x",&writePin);
writeSettings(usb_io.hDevice,disablePullup,writePin);
puts("wrote settings");
CloseHandle(usb_io.hDevice);
return 0;
} else {
printf("Usage for config: %s s \n",argv[0]);
printf("disablePullup: 0 (enable), 1(disable)\n");
printf("inputPin: bit 0-7: port0 bit 8-11: port1 in hex 0->output 1->input\n");
}
} else {
sscanf(argv[1],"%d",&wait);
}
}
asobu(usb_io.hDevice,wait);
CloseHandle(usb_io.hDevice);
} else {
puts("open failed");
return 1;
}
return 0;
}
CC=gcc
CFLAGS=-O2 -Wall -Wextra
LDFLAGS=-s -static
LIBS=-lsetupapi -lhid
OBJS=usb_io.o
usb_io.exe: $(OBJS)
$(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
%.o: %.c
$(CC) $(CFLAGS) -c -o $@ $^
.PHONY: clean
clean:
rm -rf usb_io.exe $(OBJS)
USB-IOをつないでこのプログラムを実行すると、ポート1の出力を順番に変えながら、ポート2のデータを読み取って表示します。
Sleepをしないと大体0.83秒で実行が終わるので、約300クエリ/秒の速さで処理できるようです。(公式ページにも300Hzと書いてあります)
これを用いてPICのプログラムの読み書きができれば、現行のArduinoを用いた方法より安価に読み書きできることになります。
しかし、300クエリ/秒の速さということは、例えば4096ワード書き込むことを考えると、
データを設定(6+16クロック)→書き込み(6クロック)→アドレスをインクリメント(6クロック)
の流れを4096回繰り返すことになります。
1クロックには上げと下げの2クエリを用いるので、合計で278528クエリが必要となり、
300クエリ/秒では約928秒、すなわち約15.5分かかる計算となります。
さすがに遅すぎるでしょうか…
WriteFileしたあとにReadFileしなければ約400クエリ/秒に上がりましたが、それでも約11分かかる上、
これで大丈夫なのかはわかりません。