my new gear...

Dependencies:   mbed

Revision:
3:a9b4b2565a23
diff -r e7b09385d197 -r a9b4b2565a23 scrp_slave.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scrp_slave.cpp	Sun Mar 27 04:51:16 2022 +0000
@@ -0,0 +1,324 @@
+#include "scrp_slave.hpp"
+
+#define STX 0x41
+#define DMY 0xff
+
+ScrpSlave::ScrpSlave(PinName TX1,PinName RX1,uint32_t addr,bool interrupt)
+    :port1(TX1,RX1,115200),port2(port1),address_(addr),interrupt_(interrupt){
+    mode_ = 0;
+    init();
+}
+
+ScrpSlave::ScrpSlave(PinName TX1,PinName RX1,PinName REDE1,uint32_t addr,bool interrupt)
+    :port1(TX1,RX1,115200),port2(port1),address_(addr),interrupt_(interrupt){
+    mode_ = 1;
+    rede_ = new DigitalOut(REDE1,0);
+    init();
+}
+
+ScrpSlave::ScrpSlave(PinName TX1,PinName RX1,PinName TX2,PinName RX2,uint32_t addr,bool interrupt)
+    :port1(TX1,RX1,115200),port2(TX2,RX2,115200),address_(addr),interrupt_(interrupt){
+    mode_ = 2;
+    serial_[1] = &port2;
+    if(interrupt_){
+        serial_[1]->attach(callback(this,&ScrpSlave::receive1),Serial::RxIrq);
+    }
+    init();
+}
+
+ScrpSlave::ScrpSlave(PinName TX1,PinName RX1,PinName REDE1,PinName TX2,PinName RX2,uint32_t addr,bool interrupt)
+    :port1(TX1,RX1,115200),port2(TX2,RX2,115200),address_(addr),interrupt_(interrupt){
+    mode_ = 3;
+    rede_ = new DigitalOut(REDE1,0);
+    serial_[1] = &port2;
+    if(interrupt_){
+        serial_[1]->attach(callback(this,&ScrpSlave::receive1),Serial::RxIrq);
+    }
+    init();
+}
+
+void ScrpSlave::init(){
+    for(int i = 0;i<2;i++){
+        wait_data_[i] = false;
+        stx_flag_[i] = false;
+        id_ok_[i] = false;
+        get_response_[i] = false;
+    }
+    for(int i = 1;i<256;++i){
+        procs_[i] = NULL;
+    }
+    responseFunc_ = NULL;
+    all_receive_ = false;
+    serial_[0] = &port1;
+    if(interrupt_){
+        serial_[0]->attach(callback(this,&ScrpSlave::receive0),Serial::RxIrq);
+    }
+    if(address_ < 256){
+        my_id_ = address_;//引数addressが0~254の時その値をidとして使用
+        all_receive_ = (address_ == 255);//引数addressが255の時すべてのidに応答する、全受信モードになる
+        return;
+    }
+    //フラッシュメモリーのアクセスにエラーが出たら、アドレスは10に設定される。
+    flash_ = new FlashIAP;
+    if(flash_->init()==0){
+        if(flash_->read(&my_id_,address_,1) != 0){
+            send2(222,222,222);
+            my_id_ = 10;
+        }
+    }else{
+        send2(111,111,111);
+        my_id_ = 10;
+    }
+}
+
+void ScrpSlave::receive(){
+    if(interrupt_){
+        return;
+    }
+    while(port1.readable()){
+        check(0);
+    }
+    if(mode_ > 1){
+        while(port2.readable()){
+            check(1);
+        }
+    }
+}
+
+void ScrpSlave::receive0(){
+    check(0);
+}
+
+void ScrpSlave::receive1(){
+    check(1);
+}
+
+void ScrpSlave::attachResponse(void (*func)(uint8_t id, uint8_t cmd, int16_t response)){
+    responseFunc_ = func;
+}
+
+void ScrpSlave::addCMD(uint8_t cmd, bool (*proc)(int rx_data, int& tx_data)){
+    if(cmd == 0 || cmd == 254 || cmd == 253)return;
+    procs_[cmd] = proc;
+}
+
+void ScrpSlave::changeID(uint8_t id){
+    if(address_ < 256){
+        return;
+    }
+    flash_->erase(address_,flash_->get_sector_size(address_));
+    flash_->program(&id,address_,1);
+}
+
+bool ScrpSlave::send1(uint8_t id,uint8_t cmd,int16_t tx_data, bool flag){
+    return sending(0,id,cmd,tx_data,flag);
+}
+
+bool ScrpSlave::send2(uint8_t id,uint8_t cmd,int16_t tx_data, bool flag){
+    return sending((mode_ > 1),id,cmd,tx_data,flag);
+}
+
+bool ScrpSlave::sending(int port,uint8_t id,uint8_t cmd,int16_t tx_data,bool flag){
+    if(!serial_[port]->writeable()){
+        return false;
+    }
+    if(flag){
+        wait_data_[port] = true;//データ返信待ち
+        get_response_[port] = false;
+    }
+    uint8_t tx_dataL = tx_data;
+    uint8_t tx_dataH = tx_data >> 8;
+    uint8_t tx_sum = id + cmd + tx_dataL + tx_dataH;
+
+    const uint8_t data[8] = {DMY, STX, id, cmd, tx_dataL, tx_dataH, tx_sum, DMY};
+    memcpy(send_data_[port],data,8);
+    if(interrupt_){
+        prime(port);
+    }else{
+        sendNoInterrupt(port);
+    }
+    return true;
+}
+
+void ScrpSlave::sendNoInterrupt(uint8_t port){
+    if(mode_%2 == 1 && port == 0){
+        rede_->write(1);
+    }
+    for(int i = 0;i < 8;i++){
+        serial_[port]->putc(send_data_[port][i]);
+        while(!serial_[port]->writeable());
+    }
+    if(mode_%2 == 1 && port == 0){
+        rede_->write(0);
+    }
+}
+
+bool ScrpSlave::getResponse(uint8_t port){
+    if(port > 1 || (port == 1 && mode_ < 2)){
+        return false;
+    }
+    return get_response_[port];
+}
+
+bool ScrpSlave::isWaiting(uint8_t port){
+    if(port > 1 || (port == 1 && mode_ < 2)){
+        return false;
+    }
+    return wait_data_[port];
+}
+
+int16_t ScrpSlave::receiveData(uint8_t port){
+    //ポート指定が正しいかどうか。
+    if(port > 1 || (port == 1 && mode_ < 2)){
+        return -1;
+    }
+    //データがあるか確認。
+    if(get_response_[port]){
+        return rx_data_[port];
+    }else{
+        return -1;
+    }
+}
+
+uint8_t ScrpSlave::receiveCmd(){
+    return rx_cmd_;//受信したcmd番号を返す。
+}
+
+uint8_t ScrpSlave::receiveId(){
+    return rx_id_;//受信したidを返す。
+}
+
+uint8_t ScrpSlave::receivePort(){
+    return receive_port_;//直近で受信したポートを返す。
+}
+
+void ScrpSlave::check(int port){
+    if(id_ok_[port]){
+        tmp_data_[port][data_count_[port]] = serial_[port]->getc();
+        data_count_[port]++;
+        if(data_count_[port] > 4){
+            stx_flag_[port] = false;//通信フラグクリア
+            id_ok_[port] = false;
+            
+            uint8_t sum = 0;
+            for(int i = 0;i<4;i++){
+                sum += tmp_data_[port][i];
+            }
+            if(sum != tmp_data_[port][4]){//check sum照合
+                return;
+            }
+            receive_port_ = port;//受信したポート番号を保存
+            uint8_t rx_id = tmp_data_[port][0];
+            uint8_t rx_cmd = tmp_data_[port][1];
+            rx_data_[port] = (int16_t)(tmp_data_[port][2] + ((int16_t)tmp_data_[port][3] << 8));
+            if(wait_data_[port]){//データ返信待ち時
+                wait_data_[port] = false;
+                get_response_[port] = true;
+                if(responseFunc_ != NULL){
+                    responseFunc_(rx_id,rx_cmd,rx_data_[port]);
+                }
+                return;
+            }else if(get_response_[port]){
+                get_response_[port] = false;
+            }
+            rx_cmd_ = rx_cmd;//メンバ変数に保存
+            bool broadcast = (tmp_data_[port][0] == 255);
+            
+            int tx_data = rx_data_[port];
+            if(rx_cmd == 0){//通信テスト
+            }else if(rx_cmd == 254){//id変更
+                uint8_t new_id = rx_data_[port];
+                my_id_ = new_id;
+                changeID(new_id);
+            }else if(rx_cmd == 253){//id確認
+                tx_data = my_id_;
+                rx_cmd = 250 + all_receive_*5;
+                broadcast = false;
+            }else if(procs_[rx_cmd] == NULL || !procs_[rx_cmd](rx_data_[port],tx_data)){
+                return;
+            }
+            if(broadcast){
+                return;//全体送信の時はレスポンスを返さない。
+            }
+            uint8_t tx_dataL = tx_data;
+            uint8_t tx_dataH = tx_data >> 8;
+            uint8_t tx_sum = my_id_ + rx_cmd + tx_dataL + tx_dataH;
+    
+            const uint8_t data[8] = {DMY, STX, my_id_, rx_cmd, tx_dataL, tx_dataH, tx_sum, DMY};
+            memcpy(send_data_[port],data,8);
+            if(interrupt_){
+                prime(port);
+            }else{
+                sendNoInterrupt(port);
+            }
+        }
+    }else if(stx_flag_[port]){
+        uint8_t get_data = serial_[port]->getc();
+        if(get_data == my_id_ || get_data == 255 || (all_receive_ && !wait_data_[port])){
+            id_ok_[port] = true;
+            wait_data_[port] = false;
+            tmp_data_[port][0] = get_data;
+            data_count_[port]++;
+        }else if(wait_data_[port]){
+            id_ok_[port] = true;
+            tmp_data_[port][0] = get_data;
+            data_count_[port]++;
+        }else{
+            stx_flag_[port] = false;
+        }
+        rx_id_ = get_data;//メンバ変数に保存
+    }else if(serial_[port]->getc() == STX){
+        stx_flag_[port] = true;
+        data_count_[port] = 0;
+        id_ok_[port] = false;
+        //id_ok_[port] = wait_data_[port];//データ返信待ち時はidチェック無し
+    }
+    return;
+}
+
+void ScrpSlave::dataSend0(){
+    while(serial_[0]->writeable()){
+        if(data_count_[0] < 8){
+            serial_[0]->putc(send_data_[0][data_count_[0]++]);
+        }else{
+            serial_[0]->attach(NULL, Serial::TxIrq);
+            if(mode_%2 == 1){
+                rede_->write(0);
+            }
+            break;
+        }
+    }
+}
+
+void ScrpSlave::dataSend1(){
+    while(serial_[1]->writeable()){
+        if(data_count_[1] < 8){
+            serial_[1]->putc(send_data_[1][data_count_[1]++]);
+        }else{
+            serial_[1]->attach(NULL, Serial::TxIrq);
+            break;
+        }
+    }
+}
+
+void ScrpSlave::prime(int port){
+    serial_[port]->attach(NULL, Serial::TxIrq);
+    data_count_[port] = 0;
+    if(port == 0){
+        if(mode_%2 == 1){
+            rede_->write(1);
+        }
+        dataSend0();
+        serial_[0]->attach(callback(this, &ScrpSlave::dataSend0), Serial::TxIrq);
+    }else{
+        dataSend1();
+        serial_[1]->attach(callback(this, &ScrpSlave::dataSend1), Serial::TxIrq);
+    }
+}
+
+ScrpSlave::~ScrpSlave(){
+    delete flash_;
+    if(mode_%2 == 1){
+        delete rede_;
+    }
+}
\ No newline at end of file