IM920のライブラリ

IM920.cpp

Committer:
Gaku0606
Date:
2018-02-22
Revision:
1:11ae0d702ecc
Parent:
0:ccdeb3bea793

File content as of revision 1:11ae0d702ecc:

#include "IM920.h"
#include "mbed.h"

short IM920::toShort(char *array){
    im920_cast.s = ((uint16_t)array[0] << 8) | (uint16_t)array[1];
    return im920_cast.s;   
}
int IM920::toInt(char *array){
    im920_cast.i = ((uint32_t)array[0] << 24) | ((uint32_t)array[1] << 16) | ((uint32_t)array[2] << 8) | (uint32_t)array[3];
    return im920_cast.i;   
}
float IM920::toFloat(char *array){
    im920_cast.u[0] = array[0];
    im920_cast.u[1] = array[1];
    im920_cast.u[2] = array[2];
    im920_cast.u[3] = array[3];
    
    return im920_cast.f;   
}
long IM920::toLong(char *array){
    for(int i = 0; i < 8; i++){
        im920_cast.u[i] = array[i];   
    }   
    return im920_cast.l;
}
double IM920::toDouble(char *array){
    for(int i = 0; i< 8; i++){
        im920_cast.u[i] = array[i];   
    }   
    return im920_cast.d;
}

void IM920::dummyFunc(){
    printf("NO FUNCTION\r\n");    
};

char IM920::im920CheckSum(int count){
    char ans = 0;
    for(int i = 0; i < count; i++){
       ans = ans ^ data[i];
    }
    return ans;
}

IM920::IM920(Serial &serial, Serial &pc, int baudrate){
    
    ser = &serial;//参照渡し
    _pc = &pc;
    
    ser->baud(baudrate);
    
    memset(buff_A, '\0', IM920_BUFF_SIZE);
    memset(buff_B, '\0', IM920_BUFF_SIZE);
    readBuffAddr = buff_B;
    writeBuffAddr = buff_A;
    sendDataSize = 0;
    interactiveFlag = 0;
    for(int i = 0;i < 256; i++){
        p_callFunc[i] = &this->dummyFunc;   
    }
    memset(data, 0, 64);
    im920_dataLength = 0;
    memset(im920_sendBuff, '\0', 129);
    sendDataSize = 0;
    nodeNumber = 0;
    AS = DATA_STRING;
    checkSum = 0;
    for(int i = 0; i < 8; i++){
        im920_cast.u[i] = 0;   
    }
    node = 0;
    RSSI = 0;
    rID = 0;
    ID = 0;
    
    receiveCheckSum = 0;
    ser->attach(this, &IM920::im920Handler, Serial::RxIrq);
}






void IM920::im920_debug(){
    printf("%s\r\n", readBuffAddr);
    return;
}



int IM920::asciiToNumber(char c){
    //printf("%c ", c);
    if((int)c >= 65){//A ~ F
        return ((int)c - 55);
    }
    else{//0 ~ 9
        return ((int)c - 48);
    }
}

void IM920::data_analyze(){
    //00,0001,78:01,02,03,04,...,FF\0
    //|  |    |  |                  +- <CR><LF>文字列終了
    //|  |    |  +-------------------- 16進数をascii文字にしたもの、最大64区切り(64Byte)
    //|  |    +----------------------- 受信強度、RSSI値
    //|  +---------------------------- 送信モジュールの固有ID
    //+------------------------------- ノード番号
    char tempStr[IM920_BUFF_SIZE];
    strcpy(tempStr, readBuffAddr);
    char *tok = strtok(tempStr, ",");//ノード番号
    node = ((asciiToNumber(tok[0]) << 4)) | asciiToNumber(tok[1]);
    tok = strtok(NULL, ",");//送信機のID
    rID = 0;
    rID = (asciiToNumber(tok[0]) << 12) | (asciiToNumber(tok[1]) << 8) | (asciiToNumber(tok[2]) << 4) | asciiToNumber(tok[3]);
    tok = strtok(NULL, ":");//受信強度
    RSSI = (char)((asciiToNumber(tok[0]) << 4) | (asciiToNumber(tok[1])));
    im920_dataLength = 64;
    memset(data, 0, 64);
    receiveCheckSum = 0;
    if(tok != NULL){
        for(int i = 0; i < 64; i++){
            if(tok[0] == '\0'){
                im920_dataLength = i - 1;
                break;
            }
            tok = strtok(NULL, ",");
            data[i] = (asciiToNumber(tok[0]) << 4) | asciiToNumber(tok[1]);
            receiveCheckSum = receiveCheckSum ^ tok[0] ^ tok[1];
        }
    }
    else{
        im920_dataLength = 0;   
    }
    return;
}

void IM920::im920Handler(){
    static int current = 0;
    static char c = 0;
    c = ser->getc();
    if(AS == RESPONSE_STRING || AS == INTERACTIVE_STRING){
        printf("%c", c);//描画、後で1行描画だと次の行がすぐ来た時にハングアップしてしまう
    }

    if(c == '\r'){//文字列終了
        printf("\r\n");
        writeBuffAddr[current] = '\0';
        if(AB == BUFF_A){//現在バッファAに書き込み中
            readBuffAddr = buff_A;
            writeBuffAddr = buff_B;
            AB = BUFF_B;
        }
        else{//現在バッファBに書き込み中
            readBuffAddr = buff_B;
            writeBuffAddr = buff_A;
            AB = BUFF_A;
        }

        //im920_debug();
        //----------------------
        //  文字列の解析
        //----------------------
        if(AS == DATA_STRING){//データの形式によって分岐 
            if(current > 9){
                //データの取り出し、配列化
                data_analyze();
                /*for(int i = 0;i < 64;i++){
                    printf("%d ",data[i]);   
                }
                printf("\r\n");
                printf("header: %0X\r\n",(uint8_t)data[0]);*/
                //header0xFF();
                // 関数の呼び出し
                (*p_callFunc[(uint8_t)data[0]])();
            }        
        }
        //初期化
        current = 0;
        //memset(writeBuffAddr, '\0', IM920_BUFF_SIZE);
        return;
    }
    else if(c !='\n'){
        //文字列生成
        writeBuffAddr[current] = c;
        current++;
        if(current >= IM920_BUFF_SIZE){//初期化
            current = 0;
            memset(writeBuffAddr, '\0', IM920_BUFF_SIZE);   
        }
        return;   
    }
}

void IM920::attach(void (*funcAddr)(void), unsigned header){
    p_callFunc[header] = funcAddr;
    return;    
}

/**
      @bref パラメータ不揮発メモリ書き込み許可モードへ移行
*/
bool IM920::enableWrite(){
    AS = RESPONSE_STRING;//レスポンス受信モードへ移行
    ser->printf("ENWR\r\n");
    wait_us(WAIT_TIME_US);//待つ
    AS = DATA_STRING; //データ受信モードへ以降
    if(strncmp(readBuffAddr, "OK", 2) == 0){
        return true;   
    }
    else{
        return false;   
    }
}

bool IM920::disableWrite(){
    AS = RESPONSE_STRING;//レスポンス受信モードへ移行
    ser->printf("DSWR\r\n");
    wait_us(WAIT_TIME_US);
    AS = DATA_STRING;  
    if(strncmp(readBuffAddr, "OK", 2) == 0){
        return true;   
    }
    else{
        return false;   
    }         
}
    
/**
    @bref 固有IDを読み出す
*/
int IM920::readID(){
    AS = NORMAL_STRING;
    ser->printf("RDID\r\n");
    wait_us(WAIT_TIME_US);
    AS = DATA_STRING;
    int val = 0;
  
    //pc.printf("%c:%c:%c:%c\r\n",readBuffAddr[0],readBuffAddr[1],readBuffAddr[2],readBuffAddr[3]); 
    val = asciiToNumber(readBuffAddr[0]) << 24;
    val |= asciiToNumber(readBuffAddr[1]) << 16;
    val |= asciiToNumber(readBuffAddr[2]) << 8;
    val |= asciiToNumber(readBuffAddr[3]);
    ID = val;
    return val;   
}         

bool IM920::setReceiveID(int ID){
    AS = RESPONSE_STRING;
    printf("SRID %4X\r\n", ID);   
    ser->printf("SRID %4X\r\n", ID);
    wait_us(WAIT_TIME_US);
    if(strncmp(readBuffAddr, "OK", 2) == 0){
        return true;   
    }
    else{
        return false;   
    }   
}
    
bool IM920::setChannel(char ch){
    AS = RESPONSE_STRING;
    printf("STCH %2d\r\n", ch);
    ser->printf("STCH %4d\r\n", ch);
    wait_us(WAIT_TIME_US);
    AS = DATA_STRING;
    if(strncmp(readBuffAddr, "OK", 2) == 0){
        return true;
    }
    else return false;
}  
    
char IM920::readChannel(){
    AS = RESPONSE_STRING;
    printf("RDCH\r\n");
    ser->printf("RDCH\r\n");
    wait_us(WAIT_TIME_US);
    AS = DATA_STRING;
    if(strncmp(readBuffAddr, "OK", 2 ) == 0){
        return true;   
    }
    else{
        return false;   
    }
}     
    
bool IM920::enableCharacterIO(){
    AS = RESPONSE_STRING;
    printf("ECIO\r\n");
    ser->printf("ECIO\r\n");
    wait_us(WAIT_TIME_US);
    AS = DATA_STRING;
    if(strncmp(readBuffAddr, "OK", 2) == 0){
        return true;   
    }
    else{
        return false;   
    }
}
    
bool IM920::disableCharacterIO(){
    AS = RESPONSE_STRING;
    printf("DCIO\r\n");
    ser->printf("DCIO\r\n");
    wait_us(WAIT_TIME_US);
    AS = DATA_STRING;
    if(strncmp(readBuffAddr, "OK", 2) == 0){
        return true;   
    }
    else{
        return false;   
    }
}
void IM920::printFormat(){
    _pc->printf("-----------------------\r\n");
    _pc->printf(" ENWR            : EEPROMへの書き込みを許可\r\n");
    _pc->printf(" DSWR            : EEPROMへの書き込みを禁止\r\n");
    _pc->printf(" RDID            : 固有IDを読み出す\r\n");
    _pc->printf(" STNN パラメータ : ノード番号を設定,00~FF\r\n");
    _pc->printf(" RDNN            : ノード番号を読み出す\r\n");
    _pc->printf(" SRID XXXX       : 受信ID設定,0000~FFFF\r\n");
    _pc->printf(" RRID            : 受信IDを読み出す\r\n");
    _pc->printf(" ERID            : 設定された受信IDの全消去\r\n");
    _pc->printf(" STCH XX         : チャンネル設定,01~15\r\n");
    _pc->printf(" RDCH            : チャンネル読み出し\r\n");
    _pc->printf(" ECIO            : キャラクタ入出力設定\r\n");
    _pc->printf(" DCIO            : キャラクタ入出力設定解除\r\n");
    _pc->printf(" TXDT data       : 8バイトデータ送信,dataは16進数をASCII文字で入力\r\n");
    _pc->printf(" TXDA data       : 1~64バイトデータ送信,dataは16進数をASCII文字で入力\r\n");
    _pc->printf(" RDRS            : RSSI値読み出し\r\n");
    _pc->printf(" STPO 送信出力   : 1~3で入力, 1:0.1mW, 2:1mW, 3:10mW\r\n");
    _pc->printf(" RDPO            : 送信出力読み出し\r\n");
    _pc->printf(" STRT 速度値     : 無線通信速度設定, 1:高速(50kbps), 2:長距離(1.25kbps)\r\n");
    _pc->printf(" RDRT            : 無線通信速度を読み出す\r\n");
    _pc->printf(" RDVR            : 製品バージョンの読み出し\r\n");
    _pc->printf(" ERPT            : 簡易中継ON\r\n");
    _pc->printf(" DRPT            : 簡易中継OFF\r\n");
    _pc->printf(" RPRM            : パラメータ一括読み出し\r\n");
    _pc->printf(" SRST            : ソフトウェアリセット\r\n");
    _pc->printf(" PCLR            : パラメータクリア\r\n");
    _pc->printf("-----------------------\r\n");
}
void IM920::interactiveMode(){
    AS = INTERACTIVE_STRING;
    //interactiveFlag = 1;
    int current = 0;
    static char buf[IM920_BUFF_SIZE] = {'\0'};
    memset(buf, '\0', IM920_BUFF_SIZE);
    _pc->printf("Start Interactive mode!!\r\n");
    printFormat();
    while(1){
        if(_pc->readable()){
            char ccc = _pc->getc();  
             
            if(ccc == '@'){
                _pc->printf("Interactive mode finish!!\r\n");
                break;
            }
            if(ccc == '\r'){
                _pc->printf("\r\n");
                buf[current] = '\0';
                
                ser->printf("%s\r\n", buf);
                current = 0;
                memset(buf, '\0', IM920_BUFF_SIZE);
                wait(1.0);
                printFormat();
                while(_pc->readable()){ _pc->getc();}
            }
            else if(ccc != '\n'){
                _pc->printf("%c", ccc);
                buf[current] = ccc;
                current++;
                if(current >= 160){
                    current = 0;
                    memset(buf, '\0', IM920_BUFF_SIZE);   
                }
            }
        }
    }
    AS = DATA_STRING;
    return;
}