2011年5月14日土曜日

すんげーニッチだけどw

PCに接続して使う広帯域受信機「IC-PCR100」のコントロールソフトを
Linuxで使うために自作して使っていたのですが、そのソースを晒してみます。
まあLinuxのシリアルポート制御の基礎ってところですかね。
昔書いたコードなので、突っ込み所満載w
今見ると、16進変換関数(GetHexStr)なぞは
sprintf(str,"%x",num);
の一行で済むじゃんねwww
まあ基数変換の基礎ってことでおながいしますwww

/* 
/* 
 * File:   pcr100.c
 * Author: kouji
 *
 * Created on 2009/01/05, 11:29
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <time.h>

#define WAIT_TIME  50000
#define BUF_MAX  100
#define ID_FALSE  -1
#define ID_TRUE  1
#define ID_DEFVOL  2
#define ID_FM  0
#define ID_AM  1
#define FREQ_LEN     21
#define RS232C_PORT  "/dev/ttyS0"
#define PCR_RESET    "H000"
#define POWER_ON     "H101"
#define POWER_OFF    "H100"
#define POWER_REQ    "H1?"
#define INITPCR_C    "H101\r\nG300"
#define CRLF_C       "\r\n"
#define RESP_REQ     "G0?"
#define RESP_OK      "G000"
#define RESP_NG      "G001"
#define FREQ_HEAD    "K00"
#define FREQ_AM      "0201"
#define FREQ_FM      "0604"
#define FREQ_FOOT    "00"
#define VOL_SET      "J40"
#define VOL_DEFAULT  "J4088"
#define SQL_OFF      "J4100"
#define OFF_CMD      "off"

// グローバル構造体宣言
struct termios NewTIO,OldTIO;

// Usage表示
void Usage(void)
{
    printf("pcr100 (off) [freq(nnnn or nn.n)] [vol]\n");
    printf("[fleq]:周波数を4桁で指定します。コンマが含まれるとFMに、\n");
    printf("       それ以外はAMとして認識します。\n");
    printf("[vol] :ボリュームを指定します。0〜255までの範囲で指定します。\n");
    printf("off   :PCR100の電源を切ります。このオプションが指定されると、\n");
    printf("       他のオプションは無視されます。\n");
}

// 10進整数を16進文字列に変換
void GetHexStr(int num,char *str)
{
    int x,y;
    char tmpStr[3],hexStr[] ="0123456789ABCDEF";
    if(num > 255) num = 255;
    else if(num < 0) num = 0;
    x = num % 16;
    y = num / 16;
    tmpStr[0] = hexStr[y];
    tmpStr[1] = hexStr[x];
    tmpStr[2] = 0;
    strcpy(str,tmpStr);
}

// シリアルポート初期化
int InitSerial(char *port)
{
    int fd;
    fd = open(port,O_RDWR | O_NOCTTY);
    if (fd < 0){
        perror(port);
        return -1;
    }
    tcgetattr(fd,&NewTIO);
    tcgetattr(fd,&OldTIO);  
    cfsetispeed(&NewTIO,B9600);
    cfsetospeed(&NewTIO,B9600);
    NewTIO.c_cflag |= (CLOCAL | CREAD);
    NewTIO.c_lflag |= (ICANON);
    NewTIO.c_lflag &= ~(ECHO | ECHOE);
    NewTIO.c_oflag &= ~OPOST;
    NewTIO.c_cflag &= ~PARENB;
    NewTIO.c_cflag &= ~CSTOPB;
    NewTIO.c_cflag &= ~CSIZE;
    NewTIO.c_cflag |= CS8;
    NewTIO.c_cflag &= ~HUPCL;
    tcflush(fd, TCIFLUSH);
    tcsetattr(fd, TCSANOW, &NewTIO);
    return fd;
}

// シリアルポートを閉じる
void CloseSerial(int fd)
{
    // プログラム終了後も、信号線の切断をしない。
    OldTIO.c_cflag &= ~HUPCL;
    tcsetattr(fd,TCSANOW,&OldTIO);
    close(fd);
}

// 指定時間待機する
void WaitTimer(int second)
{
    clock_t stTime = clock();
    while(clock()-stTime <= second);
}

// コマンドを送信する
void SendCommand(char *cmd)
{
    int fd,len;
    char output[BUF_MAX];
    fd = InitSerial(RS232C_PORT);
    if(fd <= 0) return;
    strcpy(output,cmd);
    strcat(output,CRLF_C);
    len = write(fd,output,strlen(output));
    WaitTimer(WAIT_TIME);
    CloseSerial(fd);
}

// PCR100の電源を入れ、初期化する
void InitRadio()
{
    WaitTimer(WAIT_TIME);
    SendCommand(INITPCR_C);
    SendCommand(SQL_OFF);
    SendCommand(VOL_DEFAULT);
}

// PCR100の電源を切る
void EndRadio()
{
    SendCommand(POWER_OFF);
}

// 周波数をコマンドに変換する
int GetFreqStr(char *freq,char *tmpStr)
{
    char *p,*p1;
    char addStr[BUF_MAX],tmpFreq[BUF_MAX];
    int freqType;
    if(strlen(freq) != 4) return ID_FALSE;
    strcpy(tmpStr,FREQ_HEAD);
    strcpy(tmpFreq,freq);
    p=strtok(tmpFreq,".");
    p1 = strtok(NULL,".");
    if(p1 == NULL){
        sprintf(addStr,"00%s000%s",p,FREQ_AM);
        freqType = ID_AM;
    }else{
        sprintf(addStr,"0%s%s00000%s",p,p1,FREQ_FM);
        freqType = ID_FM;
    }
    strcat(tmpStr,addStr);
    strcat(tmpStr,FREQ_FOOT);
    return freqType;
}

// ボリュームをコマンドに変換する
int GetVolStr(char *vols,char *tmpStr)
{
    char addStr[BUF_MAX];
    int intvol = atoi(vols);
    if(intvol < 0) intvol = 0;
    if(intvol > 255) intvol = 255;
    strcpy(tmpStr,VOL_SET);
    GetHexStr(intvol,addStr);
    strcat(tmpStr,addStr);    
 return intvol;
}

// メインルーチン
int main(int argc, char** argv) {
    char freqStr[BUF_MAX],volStr[BUF_MAX];
    int fType,vValue;
    /* Debug
    argc = 3;
    argv[1] = malloc(sizeof(char)*4);
    argv[2] = malloc(sizeof(char)*3);
    strcpy(argv[1],"80.4");
    strcpy(argv[2],"100");
    *  Debug End */
    if((argc < 2)||(argc > 3)){
        Usage();
        return ID_FALSE;
    }
    if(argc > 1){
        if(strstr(argv[1],OFF_CMD) == NULL){
            InitRadio();
            fType = GetFreqStr(argv[1],freqStr);
            SendCommand(freqStr);
            printf("周波数=%s",argv[1]);
            if(fType == ID_AM) printf("KHz(AM MODE)にセットしました。\n");
            else printf("MHz(FM MODE)にセットしました。\n");
            if(argc == 3){
                vValue = GetVolStr(argv[2],volStr);
                SendCommand(volStr);
                printf("ボリューム値:%3d に設定しました。\n",vValue);
            }
        }else{
            EndRadio();
            printf("PCR100の電源を切りました。\n");
            return 0;
        }
    }
    /* Debug
    free(argv[1]);
    free(argv[2]);
    *  Debug End */
    return 0;
}