明石高専ロボ研 mbedライブラリ

Dependencies:   mbed

Dependents:   MDD_L432KC USB2RS485 pathtracking odometry ... more

scrp_slave.hpp

Committer:
TanakaRobo
Date:
2021-10-13
Revision:
14:bdd394483434
Parent:
13:77c13e86ad12

File content as of revision 14:bdd394483434:

#ifndef SCRP_SLAVE_H
#define SCRP_SLAVE_H
#include "mbed.h"

/*USBでPCにつなぐポートと、基板上でRasPiとつなぐポートを同時に開く。
 *RedePinの有り無しの選択、ポートを一つだけ開くことも可。
 *bool interruptがデフォルトでtrueだが、falseを渡すことで割り込みを無効にできる。
 *その時は、受信のために繰り返しreceive()を呼び出す必要がある。
 *以下から選択。
 *ScrpSlave(PinName TX1,PinName RX1,uint32_t addr,bool interrupt = true);//RedePinなし、1ポート
 *ScrpSlave(PinName TX1,PinName RX1,PinName REDE1,uint32_t addr,bool interrupt = true);//RedePinあり、1ポート
 *ScrpSlave(PinName TX1,PinName RX1,PinName TX2,PinName RX2,uint32_t addr,bool interrupt = true);//RedePinなし、2ポート
 *ScrpSlave(PinName TX1,PinName RX1,PinName REDE1,PinName TX2,PinName RX2,uint32_t addr,bool interrupt = true);//RedePinあり、1ポート+RedePinなし、1ポート
 *example not usb port
 *L432KC : TX = PA_9 , RX = PA_10 , REDE = PA_12 , addr = 0x0803f800
 *F446RE : TX = PC_12 , RX = PD_2 , RDDE = PH_1 , addr = 0x0807f800
 *H743ZI : TX = PD_5 , RX = PD_6 , REDE = PD_7 , addr = 0x081ee000
 *<obj>.addCMD(int cmd, bool (*proc)(int rx_data, int& tx_data))
 *でcmdで指定したコマンドを受信したときに呼び出される
 *bool型で引数が(int rx_data, int& tx_data)の関数を指定する。
 *addrで指定されたフラッシュメモリーのアドレスに通信で使う1バイトのアドレスが保存される。
 *addrに0から254までの値を入れて、この値そのものをidとして通信で使うこともできる。
 *addrに255を入れると全受信モードになります。すべての受信idを自分のものとみなし応答します。
 *この機能はScrpSlaveの性質をよく理解したうえで使ってください。
 *通常のMD通信網に不注意にこれを入れると、送り返すresponseが衝突し、通信状態を悪化させます。
 *
 *このライブラリでは、シリアル送信、受信とも割り込みを利用しています。
 *Nucleoはシリアル通信割り込みを同時に2ポートまでしか利用できません。
 *このライブラリでシリアルポートを2ポート開いた場合、それ以外のシリアル通信で割り込みを利用できないので注意してください。
 *
 *シリアルポートに外部からアクセスして通信することもできるようになりました。
 *このライブラリでは同時に2個シリアルポートを開いていますが、それぞれport1,port2としてアクセスできます。
 *シリアルポートを1つだけ開いているときは、port1とport2,send1とsend2は同じモノ扱いになります。
 *sendのレスポンスはgetResponseがtrueの時に、receiveDataの返り値として知ることができます。
 *isWaitingで、今レスポンス待ち状態かどうか知ることができます。
 *レスポンス受信前に他の命令などを受信するとレスポンス待ちはキャンセルされます。
 *両方引数は0か1で、どちらのシリアルポートかを指定します。
 *レスポンスを受信した時に割り込みで呼ばれる関数を設定することができます。
 *void型。引数は(uint8_t id, uint8_t cmd, int16_t res)です。
 *attachResponseで関数を指定してください。
 *
 *クラス内のシリアルポートに.port1 .port2という形でアクセスできます。
 *printfしたいときなどは、
 *<obj>.port2.printf("hello\n");
 *と書くことできます。
 *また、writeable(),putc()でデータを送信することができますが、LTC485使用時はREDEピンを別に制御する必要があります。
 *その他Serialクラスに存在する機能すべてにアクセスできますが、このライブラリで受信データをすべて処理しているので、
 *getc()などで個別に取り出すことはできません。
 *シリアルのボーレートは基本的に変更しないでください。
 *readable(),getc()は使わないでください。正常に動作しません。
 *また、受信・送信割り込みの設定は行わないでください。ライブラリが正常に動作しません。
 */
//ScrpSlave slave(SERIAL_TX,SERIAL_RX, 3); 3がそのままidとして使われる。
//ScrpSlave slave(PC_12,PD_2 ,PH_1 ,SERIAL_TX,SERIAL_RX,0x0807f800); フラッシュメモリーの0x0807f800番地にidが保存される。
//ScrpSlave slave(PA_9 ,PA_10,PA_12,SERIAL_TX,SERIAL_RX,0x0803f800);
//ScrpSlave slave(PD_5 ,PD_6,PD_7,SERIAL_TX,SERIAL_RX,0x081ee000);
//ScrpSlave slave(PC_12,PD_2 ,PH_1 ,SERIAL_TX,SERIAL_RX,0x0807f800,false);//rtos使用時や3ポート以上開き割り込みを無効にするとき。


inline int constrain(int x,int a,int b){
    return (x < a ? a : x > b ? b : x);
}

inline double constrain(double x,double a,double b){
    return (x < a ? a : x > b ? b : x);
}

class ScrpSlave{
public:
    ScrpSlave(PinName TX1,PinName RX1,uint32_t addr,bool interrupt = true);//RedePinなし、1ポート
    ScrpSlave(PinName TX1,PinName RX1,PinName REDE1,uint32_t addr,bool interrupt = true);//RedePinあり、1ポート
    ScrpSlave(PinName TX1,PinName RX1,PinName TX2,PinName RX2,uint32_t addr,bool interrupt = true);//RedePinなし、2ポート
    ScrpSlave(PinName TX1,PinName RX1,PinName REDE1,PinName TX2,PinName RX2,uint32_t addr,bool interrupt = true);//RedePinあり、1ポート+RedePinなし、1ポート
    ~ScrpSlave();
    RawSerial port1;
    RawSerial port2;
    void addCMD(uint8_t cmd, bool (*proc)(int rx_data,int& tx_data));
    void attachResponse(void (*func)(uint8_t id, uint8_t cmd, int16_t response));//レスポンス受信割り込み関数
    void receive();//割り込みを無効にしたときにこれを繰り返し呼び出して受信する。
    bool send1(uint8_t id, uint8_t cmd, int16_t tx_data, bool flag = true);//返り値 成功:true 失敗:false
    bool send2(uint8_t id, uint8_t cmd, int16_t tx_data, bool flag = true);//レスポンスを待つか、待たないかのflag
    bool isWaiting(uint8_t port);//send,send2の通信のレスポンス待ち状況確認。
    bool getResponse(uint8_t port);//レスポンスを受信したらtrueになる。
    int16_t receiveData(uint8_t port);//0か1か send1のレスポンスは0、send2のレスポンスは1を指定。データがない時は-1を返す。
    uint8_t receiveId();//直前の通信で送られてきたidを返す。
    uint8_t receiveCmd();//直前の通信で送られてきたCMD番号を返す。割り込み関数内でCMDを知りたいときに有効。
    uint8_t receivePort();//直前の通信で受信したポートを返す。
private:
    DigitalOut *rede_;
    FlashIAP *flash_;
    RawSerial *serial_[2];
    uint8_t send_data_[2][8];
    uint8_t mode_;
    uint8_t my_id_;
    uint8_t rx_cmd_;
    uint8_t rx_id_;
    uint8_t receive_port_;
    uint32_t address_;
    bool all_receive_;
    bool interrupt_;
    bool wait_data_[2];
    bool get_response_[2];
    bool stx_flag_[2];
    bool id_ok_[2];
    uint8_t tmp_data_[2][5];
    uint8_t data_count_[2];
    int16_t rx_data_[2];
    void (*responseFunc_)(uint8_t id, uint8_t cmd, int16_t response);
    bool (*procs_[256])(int rx_data, int& tx_data);
    bool sending(int, uint8_t, uint8_t, int16_t, bool = true);
    void sendNoInterrupt(uint8_t port);
    void changeID(uint8_t);
    void init();
    void check(int port);
    void receive0();
    void receive1();
    void dataSend0();
    void dataSend1();
    void prime(int);
};

#endif /* SCRP_SLAVE_H */