• R/O
  • HTTP
  • SSH
  • HTTPS

Tags
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

oga's tools


File Info

Rev. 2b80abcdeb00aad07aa265bd434df3975aadbb9a
크기 9,470 bytes
Time 2024-12-10 04:54:07
Author hyperoga
Log Message

add color() func

Content

/* 
 *  irctrl.c
 *    パラレルインタフェースを利用した赤外線データR/W
 *
 *    (注)PCのプリンタのI/OアドレスとPORT_PRT_BASEを合わせること
 *        PCのプリンタのBIOS設定では双方向通信可に設定すること 
 *
 *    04/01/04 V0.10 by oga.
 *    04/06/14 V0.20 by oga.
 */

#ifdef _WIN32
#include <windows.h>
#include <conio.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/io.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <unistd.h>

/* I/O Ports */
#define PORT_PRT_BASE 0x378               /* lp0:0x3bc lp1:0x378 lp2:0x278 */
#define PORT_PRT_DATA (PORT_PRT_BASE+0)   /* Data R/W                      */
#define   BIT_DATA_IRREAD  0x01           /*   Bit0: Input  IR Data        */
#define   BIT_DATA_IRWRITE 0x02           /*   Bit1: Output IR Data        */
#define PORT_PRT_STAT (PORT_PRT_BASE+1)   /* Status (Read Only)            */
#define   BIT_STAT_SLCT    0x10           /*   Bit4: SLCT(Not Use)         */
#define PORT_PRT_CTRL (PORT_PRT_BASE+2)   /* Control(Write Only)           */
#define   BIT_CTRL_DIRECT  0x20           /*   Bit5: Direction 0:OUT 1:IN  */

#define WAIT_TIME 00000  /* 20ms */
/* #define WAIT_TIME 200000  /* 200ms */
/* #define WAIT_SPIN 1000000 /* 6.5ms(loop(K6-2/366MHz)) */
#define WAIT_SPIN 5000   /*  5ms */

/* とりあえず 格納データは可視データで */
#define IR_DATA_OFF '0'
#define IR_DATA_ON  '1'

/* globals */
int  vf = 0;   /* verbose */

/*
 *  tv_diff(tv1, tv2, tv3)
 *
 *  IN 
 *   tv1, tv2 : time value
 *
 *  OUT 
 *   tv3      : tv1 - tv2
 *
 */
void tv_diff(tv1, tv2, tv3)
struct timeval *tv1,*tv2,*tv3;
{
    if (tv1->tv_usec < tv2->tv_usec) {
        tv3->tv_sec  = tv1->tv_sec  - tv2->tv_sec - 1;
        tv3->tv_usec = tv1->tv_usec + 1000000 - tv2->tv_usec;
    } else {
        tv3->tv_sec  = tv1->tv_sec  - tv2->tv_sec;
        tv3->tv_usec = tv1->tv_usec - tv2->tv_usec;
    }
}

/*
 *  SpinSleep
 *    指定μsだけスピンして待つ(1/100秒よりも小さい解像度で待ちたい場合)
 *
 *   usec : micro seconds
 */
void SpinSleep(int usec)
{
    int i;
    struct timeval  tv, tv2, tv3;
    struct timezone tz;

    gettimeofday(&tv, &tz);
    while (1) {
        gettimeofday(&tv2, &tz);
	tv_diff(&tv2, &tv, &tv3);
	if (tv3.tv_sec*1000000+tv3.tv_usec >= usec) {
	    break;
	}
    }
}

/*
 *  IrRead
 *
 *    OUT data : Infrared Read Data
 *    IN  size : data buffer size
 *    OUT ret  : Read Data Size
 */
int IrRead(char *data, int size)
{
    int i = 0;
    int val;
    int off_len = 0;  /* IR_DATA_OFF length */
    int last_point = 0;

    outb(BIT_CTRL_DIRECT, PORT_PRT_CTRL);   /* Bit5:1 ... Input */

    /* Wait IR Data */
    printf("Waiting IR Data...\n");
    fflush(stdout);
    while (1) {
        usleep(WAIT_TIME);   /* DEBUG */
        val = inb(PORT_PRT_DATA);
        if (vf) printf("IrRead1: INB[%d] : %d\n", i++, val);   /* DEBUG */
	if (!(val & BIT_DATA_IRREAD)) {
	    data[0] = IR_DATA_ON;
	    break;
	}
    }
    SpinSleep(WAIT_TIME);

    printf("Reading ...\n");
    fflush(stdout);
    
    for (i=1; i<size; i++) {
	//if (off_len > 500000/WAIT_TIME) {
	if (off_len > 50000) {
            /* 500ms以上データがない場合終了 */
	    break;
	}
        val = inb(PORT_PRT_DATA);
        if (vf) printf("IrRead2: val=%d\n", val);
	if (!(val & BIT_DATA_IRREAD)) { /* Bit0(D0)で入力 */
	    data[i] = IR_DATA_ON;
            off_len = 0;
	    last_point = i;  /* 最後に1になった場所 */
	} else {
	    data[i] = IR_DATA_OFF;
	    ++off_len;
	}
        SpinSleep(WAIT_TIME);
    }
    return (last_point+1);
}

/*
 *  IrWrite
 *
 *    IN  data : Infrared Output Data
 *    IN  size : Data Size
 */
void IrWrite(char *data, int size)
{
    int i;

    outb(0x00, PORT_PRT_CTRL);   /* Bit5:0 ... Output */

    for (i=0; i<size; i++) {
        if (data[i] == IR_DATA_ON) {
            outb(            0x00, PORT_PRT_DATA);
	} else {
            outb(BIT_DATA_IRWRITE, PORT_PRT_DATA);  /* Bit1(D1)で出力 */
	}
        SpinSleep(WAIT_TIME);
    }

    /* Ir Off */
    outb(BIT_DATA_IRWRITE, PORT_PRT_DATA);  /* Bit1(D1)で出力 */
}

/*
 *  ReadIRData
 *    ファイルからIRデータを取得
 *
 *  IN  fname : filename
 *  IN  data  : read data buffer
 *  IN  size  : data buffer size
 *  OUT data  : read data buffer
 *  OUT ret   : read data size
 *
 */
int ReadIRData(char *fname, char *data, int size)
{
    FILE *fp;
    struct stat stbuf;
    int  size2 = size;
    int  ret = 0;

    if (stat(fname, &stbuf) < 0) {
        perror(fname);
        exit(1);
    }
    if (stbuf.st_size < size) {
        size2 = stbuf.st_size;
    }

    if ((fp = fopen(fname,"rb")) == 0) {
        perror(fname);
        exit(1);
    }
    ret = fread(data, 1, size2, fp);
    fclose(fp);

    return ret;
}

/*
 *  WriteIRData
 *    ファイルにIRデータを格納
 *
 *  IN  fname : filename
 *  OUT data  : read data buffer
 *  OUT size  : data buffer size
 *
 */
void WriteIRData(char *fname, char *data, int size)
{
    FILE *fp;
    struct stat stbuf;

    if ((fp = fopen(fname,"wb")) == 0) {
        perror(fname);
        exit(1);
    }
    fwrite(data, 1, size, fp);
    fclose(fp);

    printf("Write %s completed.\n", fname);
}

int main(int a, char* b[])
{
    int  val = 0;
    //char data[200];  /* 0.02x200 = 4sec */
    char data[2000000];  /* 0.02x200 = 4sec */
    int  size;
    char buf[4096];   /* dummy buf */

    char *fname = NULL;
    int  i;

    /* arg check */
    for (i = 1; i<a; i++) {
	if (!strncmp(b[i],"-v",2)) {
	    vf = 1;
	    continue;
	}
	if (!strncmp(b[i],"-h",2)) {
	    printf("usage: irctrl [in_ir_data_file]\n");
	    exit(1);
	}
	fname = b[i];
    }

    /* 書式 ioperm(from, num, turn_on)
     *   from    : アクセスを許すポートの最初のアドレス (0x000〜0x3ff)
     *   num     : fromからいくつの連続アドレスのアクセスを許すかを指定
     *   turn_on : true:1 = アクセスを許可, false:0 = アクセスを禁止
     *
     *   <例>
     *     ioperm(0x300, 5, 1) は、0x300 から 0x304 (合計で 5 つのポート)
     *     に対する許可を指定し、最後のパラメータでは、そのポートに対する
     *     アクセス許可を与えるのか禁止するのかを論理値
     *     (true:1 = アクセスを許可する, false:0 = アクセスを禁止する)で指定
     */
    if (ioperm(PORT_PRT_BASE, 3, 1) < 0) {
        perror("ioperm");
	exit(1);
    }

    memset(data, 0, sizeof(data));

    outb(0x00, PORT_PRT_CTRL);   /* Bit5:0 ... Output */
    outb(0x00, PORT_PRT_DATA);


    /* debug 04/06/13 */
    strcpy(buf, "0101010");
    IrWrite(buf, strlen(buf));

    if (fname != NULL) {
        /* ファイル指定がある場合はファイルからデータ取得 */
        if ((size = ReadIRData(fname, data, sizeof(data))) < 0) {
	    printf("IR Data Read Error\n");
	    exit(1);
	}
    } else {
        /* ファイル指定がない場合はデバイスからデータ取得 */
        printf("IR Read start.\n");
        fflush(stdout);

        size = IrRead(data, sizeof(data)-1);  /* 赤外線入力 */

        printf("IR Read end. size:%d\n", size);
        fflush(stdout);
    }


    while (1) {
        printf("IR Out start.  hit any key! [q:quit]\n");
        fflush(stdout);

        scanf("%s", buf);
        if (buf[0] == 'q' || buf[0] == 'e') {
	    /* "quit" or "exit" */
            break;
        }
        if (buf[0] == 'd') {
	    /* "dump" : dump data */
            printf("## dump Ir Data...\n");
            for (i = 0; i<size; i++) {
                printf("%c", data[i]);
            }                
            printf("\n");
            continue;
        }
        printf("PiPiPi...\n");
        fflush(stdout);

	IrWrite(data, size);  /* 赤外線出力 */

        printf("IR Out end. size:%d\n", size);
        fflush(stdout);
    }

    printf("data=%s\n", data);

    WriteIRData("/tmp/irdata.ir", data, size);

    /* 後始末 */
    if (ioperm(PORT_PRT_BASE, 3, 0) < 0) {
        perror("ioperm");
	exit(1);
    }
    return 0;
}


#if 0
// 参考 Linux HOWTO IO-Port-Programming/useful-ports.html
//
// ■BASE+0のポート(データポート)は、ポートのデータ信号を制御します。
//   D0 〜 D7 はビット 0 〜 7 に対応します。
//   状態 : 0 = low (0V)、1 = high (5V))。
//     このポートに対するライトはデータをラッチして外部のピンに出力します。
//     標準または拡張ライトモードの場合には、リードすると、最後にライト
//     されたデータが読み出されます。
//     拡張リードモードの場合には、外部デバイスからのデータが読み出されます。
//
// ■BASE+1のポート(ステータスポート) はリードオンリーで、以下のような入力信号のステータスを返します: 
//   Bit 0 と 1 は予約済
//   Bit 2 IRQ ステータス (外部ピンの値ではない。どういうふうに動作するか知らない)
//   Bit 3 ERROR (1=high)
//   Bit 4 SLCT (1=high)
//   Bit 5 PE (1=high)
//   Bit 6 ACK (1=high)
//   Bit 7 -BUSY (0=high)
//
// ■BASE+2のポート(制御ポート)はライトオンリー (リードした場合、最後にライトしたデータを返す。)で、以下のステータス信号を制御します: 
//   Bit 0 -STROBE (0=high)
//   Bit 1 -AUTO_FD_XT (0=high)
//   Bit 2 INIT (1=high)
//   Bit 3 -SLCT_IN (0=high)
//   Bit 4 '1' にすると、パラレルポートの割り込みを許可する(ACK の low -> high の遷移で割り込み発生。)
//   Bit 5 拡張モードでの方向(0 = 出力, 1 = 入力) を制御する。 ★
//         このビットは完全にライトオンリーで、リード時には不定の値が返る。
//   Bit 6 と 7 は予約済
//
// ■ピン接続 (25 ピンの D-sub メスコネクタ) (i=input, o=output): 
//     1io -STROBE,
//   ★2io D0, 3io D1, 4io D2, 5io D3, 6io D4, 7io D5, 8io D6, 9io D7,
//     10i ACK, 11i -BUSY, 12i PE, 13i SLCT, 14o -AUTO_FD_XT,
//     15i ERROR, 16o INIT, 17o -SLCT_IN, 
//   ★18-25 Ground
#endif /* 0 */

/* vim:ts=8:sw=8:
 */