TI社のBLDCモータードライバDRV8301を コントロールするためのユーティリティのようなクラスです。 できるだけユーザーにわかりやすく レジスタの設定・読み取りなどを行います。 尚、データシートは必須の模様。

Dependents:   BLDC1Axis_DRV8301CTRL

Files at this revision

API Documentation at this revision

Comitter:
Yajirushi
Date:
Wed Aug 31 17:03:35 2016 +0000
Commit message:
FIRST COMMIT

Changed in this revision

DRV8301CTRL.cpp Show annotated file Show diff for this revision Revisions of this file
DRV8301CTRL.h Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r 72d833823fd5 DRV8301CTRL.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DRV8301CTRL.cpp	Wed Aug 31 17:03:35 2016 +0000
@@ -0,0 +1,1011 @@
+#include "DRV8301CTRL.h"
+
+//ショートカット
+#define DRV8301_CS_ACTIVE cs->write(0)
+#define DRV8301_CS_INACTIVE cs->write(1)
+#define DRV8301_GATE_ACTIVE gate->write(1)
+#define DRV8301_GATE_INACTIVE gate->write(0)
+
+//コンストラクタ(オーバーロード +3) =================================
+/*
+ * シリアルとSPIのアドレス、CSとEN_GATEのピンネームを指定してインスタンスを生成
+ */
+drv8301ctrl::drv8301ctrl(Serial *serial, SPI *spi, PinName csel, PinName en_gate){
+    pc = serial;
+    si = spi;
+    cs = new DigitalOut(csel);
+    gate = new DigitalOut(en_gate);
+    hasSerial = !(pc == NULL);
+}
+
+//コンストラクタ(オーバーロード +3) =================================
+/*
+ * シリアルとSPIのアドレス、CSとEN_GATEのアドレスを指定してインスタンスを生成
+ */
+drv8301ctrl::drv8301ctrl(Serial *serial, SPI *spi, DigitalOut *csel, DigitalOut *en_gate){
+    pc = serial;
+    si = spi;
+    cs = csel;
+    gate = en_gate;
+    hasSerial = !(pc == NULL);
+}
+
+//コンストラクタ(オーバーロード +3) =================================
+/*
+ * SPIのアドレス、CSとEN_GATEのピンネームを指定してインスタンスを生成
+ * この場合、デバッグ(シリアルでのSPI通信内容の出力)は使用できない
+ */
+drv8301ctrl::drv8301ctrl(SPI *spi, PinName csel, PinName en_gate){
+    si = spi;
+    cs = new DigitalOut(csel);
+    gate = new DigitalOut(en_gate);
+    hasSerial = false;
+}
+
+//コンストラクタ(オーバーロード +3) =================================
+/*
+ * SPIのアドレス、CSとEN_GATEのアドレスを指定してインスタンスを生成
+ * この場合、デバッグ(シリアルでのSPI通信内容の出力)は使用できない
+ */
+drv8301ctrl::drv8301ctrl(SPI *spi, DigitalOut *csel, DigitalOut *en_gate){
+    si = spi;
+    cs = csel;
+    gate = en_gate;
+    hasSerial = false;
+}
+
+//デストラクタ  =================================================
+drv8301ctrl::~drv8301ctrl(){
+    delete pc;
+    delete si;
+    delete cs;
+    delete gate;
+}
+
+//private:SPIコマンド送信  ======================================
+/*
+ * SPIコマンドを送信し、DRV8301からの返答を受け取って返す
+ * DRV8301は16bitの命令を送信した際、次回送信時に前回の返答を返す
+ * つまり1回目でコマンドを送信し、2回目の空送信で返答を得る
+ *
+ * 引数debugを有効にした場合、SPIでのやりとりの内容をシリアルに出力する
+ * 引数debugはデフォルトでtrue
+ */
+int drv8301ctrl::spi_cmd(int val, bool debug){
+    DRV8301_CS_ACTIVE;
+    wait_us(1);
+
+    //送信
+    si->write(val);
+
+    wait_us(1);
+    DRV8301_CS_INACTIVE;
+
+    wait_us(1);
+
+    DRV8301_CS_ACTIVE;
+
+    //返答
+    int ret = si->write(0x0000);
+
+    if(debug && hasSerial){
+        pc->printf("CS ACTIVE\r\n\tSPI SEND >>>> values = 0x%08x\r\n\tRECEIVE  <<<< return = 0x%08x\r\nCS INACTIVE\r\n", val, ret);
+    }
+
+    wait_us(1);
+    DRV8301_CS_INACTIVE;
+    wait_us(1);
+
+    return ret;
+}
+
+//private:SPI関連の初期化とか  ====================================
+/*
+ * SPIインターフェースの初期化およびDRV8301への初期化コマンドの送信
+ *
+ * 引数reset_ifaceをfalseにすることでSPIインタフェースの初期化をスキップ
+ * すでに外部でSPIインターフェースを使用している等の場合はfalseを指定
+ * 引数reset_ifaceはデフォルトでtrue
+ *
+ */
+void drv8301ctrl::init(bool reset_iface){
+    //SPI初期化
+    if(reset_iface){
+        si->frequency(DRV8301CTRL_FREQ);
+        si->format(16, 1);
+    }
+
+    //EN_GATEの状態をリセット
+    gateReset();
+
+    //CS状態をセット
+    DRV8301_CS_INACTIVE;
+
+    //現在のレジスタ内容を出力
+    if(hasSerial){
+        pc->printf(
+            "1\tSTATUS 1   NOW : 0x%08x, STATUS 2   NOW : 0x%08x\r\n",
+            (spi_cmd(DRV8301REG_READMODE | DRV8301REG_STATUS1, false) & 0x07FF),
+            (spi_cmd(DRV8301REG_READMODE | DRV8301REG_STATUS2, false) & 0x07FF)
+        );
+        pc->printf(
+            "1\tREGISTER 1 NOW : 0x%08x, REGISTER 2 NOW : 0x%08x\r\n",
+            (spi_cmd(DRV8301REG_READMODE | DRV8301REG_CTRL1, false) & 0x07FF),
+            (spi_cmd(DRV8301REG_READMODE | DRV8301REG_CTRL2, false) & 0x07FF)
+        );
+    }
+
+    //初期設定
+    /*
+     * コントロールレジスタは、自分で格納用の値を作って列挙体の値を論理和でくっつけた後
+     * updateWriteValueやwriteCtrl(引数あり)で値を直接更新する方法と、
+     * クラスのメンバ変数が所持している値をメソッドで更新してから
+     * writeCtrl1(引数なし)で更新する方法などがある。
+     * 基本的にはクラスメソッドで値を更新して、writeCtrlを引数なしで呼ぶことが妥当。
+     *
+     * 下記の方法は前者。
+     */
+    unsigned short settingVal1 =
+        GATE_CURRENT_PEAKCURRENT_1_7A |
+        GATE_RESET_NORMAL |
+        PWM_MODE_PWMLINES_3 |
+        OCP_MODE_CURRENTLIMIT |
+        OC_ADJ_SET_ADJUST_0_358
+    ;
+
+    //上記をメソッド更新版で書いた場合
+    //setGATE_CURRENT(1.7f);
+    //setGATE_RESET(true);
+    //setPWM_MODE(false);
+    //setOCP_MODE(0x00);
+    //setOC_ADJ(0.358f);
+
+    //初期設定内容を書き込む
+    //メソッド更新のみで値を書き換えた場合は引数は不要
+    //writeCtrl1(); //メソッドで更新した場合 コントロールレジスタ1
+    //writeCtrl2(); //メソッドで更新した場合 コントロールレジスタ2
+    writeCtrl1(settingVal1); //コントロールレジスタ1
+
+    //現在のレジスタ内容を出力
+    if(hasSerial){
+        pc->printf(
+            "2\tSTATUS 1   NOW : 0x%08x, STATUS 2   NOW : 0x%08x\r\n",
+            (spi_cmd(DRV8301REG_READMODE | DRV8301REG_STATUS1, false) & 0x07FF),
+            (spi_cmd(DRV8301REG_READMODE | DRV8301REG_STATUS2, false) & 0x07FF)
+        );
+        pc->printf(
+            "2\tREGISTER 1 NOW : 0x%08x, REGISTER 2 NOW : 0x%08x\r\n",
+            (spi_cmd(DRV8301REG_READMODE | DRV8301REG_CTRL1, false) & 0x07FF),
+            (spi_cmd(DRV8301REG_READMODE | DRV8301REG_CTRL2, false) & 0x07FF)
+        );
+    }
+
+    unsigned short settingVal2 =
+        OCTW_MODE_REPORT_OT_OC_BOTH |
+        SHUNTGAIN_GAIN_40V_PER_V |
+        DC_CAL_CH1_ENABLE |
+        DC_CAL_CH2_ENABLE |
+        OC_TOFF_CYCLE_BY_CYCLE
+    ;
+
+    //上記をメソッド更新版で書いた場合
+    //setOCTW_MODE(0x00);
+    //setGAIN(2);
+    //setDC_CAL_CH1_Enabled(true);
+    //setDC_CAL_CH2_Enabled(true);
+    //setOC_TOFF_CycleByCycle(true);
+
+    //初期設定内容を書き込む
+    //メソッド更新のみで値を書き換えた場合は引数は不要
+    //writeCtrl1(); //メソッドで更新した場合 コントロールレジスタ1
+    //writeCtrl2(); //メソッドで更新した場合 コントロールレジスタ2
+    writeCtrl2(settingVal2); //コントロールレジスタ1
+
+    //デバイスIDを取得
+    devID = readDEVICE_ID();
+
+    //シリアル出力
+    if(hasSerial){
+        pc->printf("INITIALIZE BEGIN\r\n\tSPI Freq = %d[Hz], SPI Mode = 16, 1\r\n", (int)DRV8301CTRL_FREQ);
+        pc->printf("\tDEVICE ID = [%d]\r\n", (int)devID);
+    }
+
+    //現在のレジスタ内容を出力
+    if(hasSerial){
+        pc->printf(
+            "3\tSTATUS 1   NOW : 0x%08x, STATUS 2   NOW : 0x%08x\r\n",
+            (spi_cmd(DRV8301REG_READMODE | DRV8301REG_STATUS1, false) & 0x07FF),
+            (spi_cmd(DRV8301REG_READMODE | DRV8301REG_STATUS2, false) & 0x07FF)
+        );
+        pc->printf(
+            "3\tREGISTER 1 NOW : 0x%08x, REGISTER 2 NOW : 0x%08x\r\n",
+            (spi_cmd(DRV8301REG_READMODE | DRV8301REG_CTRL1, false) & 0x07FF),
+            (spi_cmd(DRV8301REG_READMODE | DRV8301REG_CTRL2, false) & 0x07FF)
+        );
+        pc->printf("\tINITIAL CTRL1 REG = 0x%08x\r\n\tINITIAL CTRL2 REG = 0x%08x\r\n", settingVal1, settingVal2);
+    }
+
+    //シリアル出力
+    if(hasSerial){
+        pc->printf("INITIALIZE END\r\n   ---===---===---   \r\n");
+    }
+
+    //待ち時間
+    wait_ms(5);
+}
+
+//ステータスレジスタ1の読み取り  ========================================
+/*
+ * DRV8301の現在の状態を読み取り、返す(ステータスレジスタ1)
+ *
+ * この情報で読み取れるものは、
+ * FAULT(何らかの異常), GVDD_UV(GVDD電圧下降), PVDD_UV(PVDD電圧下降),
+ * OTSD(温度上昇シャットダウン), OTW(温度上昇警告),
+ * FETHA_OC(A相FETハイサイド過電流), FETLA_OC(A相FETローサイド過電流),
+ * FETHB_OC(B相FETハイサイド過電流), FETLB_OC(B相FETローサイド過電流),
+ * FETHC_OC(B相FETハイサイド過電流), FETLC_OC(B相FETローサイド過電流)
+ *
+ * 異常がなければ0, 異常があれば1が設定される
+ */
+unsigned short drv8301ctrl::readStatus1(){
+    //SPIで値を読み取り、返す
+    return (unsigned short)(spi_cmd(DRV8301REG_READMODE | DRV8301REG_STATUS1) & 0x07FF);
+}
+
+//ステータスレジスタ2の読み取り  ========================================
+/*
+ * DRV8301の現在の状態を読み取り、返す(ステータスレジスタ2)
+ *
+ * この情報で読み取れるものは、
+ * GVDD_OV(GVDD過電圧)、DEVICE_ID(デバイスID)
+ *
+ * GVDD_OVは異常がなければ0, 異常があれば1が設定される
+ * デバイスIDは4bitの値で、通常は1(0x0001)を返す
+ */
+unsigned short drv8301ctrl::readStatus2(){
+    //SPIで値を読み取り、返す
+    return (unsigned short)(spi_cmd(DRV8301REG_READMODE | DRV8301REG_STATUS2) & 0x07FF);
+}
+
+//ステータスレジスタ:FAULTの読み取り  ===================================
+/*
+ * ステータスレジスタからFAULTの状態だけを切り取って返す
+ * 戻り値がtrueであればFAULT(何らかの異常)が発生している
+ */
+bool drv8301ctrl::readFault(){
+    return (((readStatus1() >> 10) & 0x0001) == 1);
+}
+
+//ステータスレジスタ:GVDD_UVの読み取り  =================================
+/*
+ * ステータスレジスタからGVDD_UVの状態だけを切り取って返す
+ * 戻り値がtrueであればGVDD_UV(GVDDの電圧下降)が発生している
+ */
+bool drv8301ctrl::readGVDD_UV(){
+    return (((readStatus1() >> 9) & 0x0001) == 1);
+}
+
+//ステータスレジスタ:PVDD_UVの読み取り  =================================
+/*
+ * ステータスレジスタからPVDD_UVの状態だけを切り取って返す
+ * 戻り値がtrueであればPVDD_UV(PVDDの電圧下降)が発生している
+ */
+bool drv8301ctrl::readPVDD_UV(){
+    return (((readStatus1() >> 8) & 0x0001) == 1);
+}
+
+//ステータスレジスタ:OTSDの読み取り  ====================================
+/*
+ * ステータスレジスタからOTSDの状態だけを切り取って返す
+ * 戻り値がtrueであればOTSD(温度上昇によるシャットダウン)が発生している
+ *
+ * 温度上昇によるシャットダウンは摂氏150度で設定される
+ */
+bool drv8301ctrl::readOTSD(){
+    return (((readStatus1() >> 7) & 0x0001) == 1);
+}
+
+//ステータスレジスタ:OTWの読み取り  =====================================
+/*
+ * ステータスレジスタからOTWの状態だけを切り取って返す
+ * 戻り値がtrueであればOTW(温度上昇による警告)が発生している
+ *
+ * 温度上昇による警告は摂氏130度で設定される
+ * この警告は摂氏115度になるまで発生し続ける
+ */
+bool drv8301ctrl::readOTW(){
+    return (((readStatus1() >> 6) & 0x0001) == 1);
+}
+
+//ステータスレジスタ:FETHA_OCの読み取り  ================================
+/*
+ * ステータスレジスタからFETHA_OCの状態だけを切り取って返す
+ * 戻り値がtrueであればFETHA_OC(A相FETハイサイド過電流)が発生している
+ */
+bool drv8301ctrl::readFETHA_OC(){
+    return (((readStatus1() >> 5) & 0x0001) == 1);
+}
+
+//ステータスレジスタ:FETLA_OCの読み取り  ================================
+/*
+ * ステータスレジスタからFETLA_OCの状態だけを切り取って返す
+ * 戻り値がtrueであればFETLA_OC(A相FETローサイド過電流)が発生している
+ */
+bool drv8301ctrl::readFETLA_OC(){
+    return (((readStatus1() >> 4) & 0x0001) == 1);
+}
+
+//ステータスレジスタ:FETHB_OCの読み取り  ================================
+/*
+ * ステータスレジスタからFETHB_OCの状態だけを切り取って返す
+ * 戻り値がtrueであればFETHB_OC(B相FETハイサイド過電流)が発生している
+ */
+bool drv8301ctrl::readFETHB_OC(){
+    return (((readStatus1() >> 3) & 0x0001) == 1);
+}
+
+//ステータスレジスタ:FETLB_OCの読み取り  ================================
+/*
+ * ステータスレジスタからFETLB_OCの状態だけを切り取って返す
+ * 戻り値がtrueであればFETLB_OC(B相FETローサイド過電流)が発生している
+ */
+bool drv8301ctrl::readFETLB_OC(){
+    return (((readStatus1() >> 2) & 0x0001) == 1);
+}
+
+//ステータスレジスタ:FETHC_OCの読み取り  ================================
+/*
+ * ステータスレジスタからFETHC_OCの状態だけを切り取って返す
+ * 戻り値がtrueであればFETHC_OC(C相FETハイサイド過電流)が発生している
+ */
+bool drv8301ctrl::readFETHC_OC(){
+    return (((readStatus1() >> 1) & 0x0001) == 1);
+}
+
+//ステータスレジスタ:FETLC_OCの読み取り  ================================
+/*
+ * ステータスレジスタからFETLC_OCの状態だけを切り取って返す
+ * 戻り値がtrueであればFETLC_OC(C相FETローサイド過電流)が発生している
+ */
+bool drv8301ctrl::readFETLC_OC(){
+    return ((readStatus1() & 0x0001) == 1);
+}
+
+//ステータスレジスタ:GVDD_OVの読み取り  =================================
+/*
+ * ステータスレジスタからGVDD_OVの状態だけを切り取って返す
+ * 戻り値がtrueであればGVDD_OV(GVDD過電圧)が発生している
+ */
+bool drv8301ctrl::readGVDD_OV(){
+    return (((readStatus2() >> 7) & 0x0001) == 1);
+}
+
+//ステータスレジスタ:Device IDの読み取り  ===============================
+/*
+ * ステータスレジスタからDevideIDの状態だけを切り取って返す
+ * 戻り値は4bitの値、0 - 15の中のいずれか
+ */
+unsigned char drv8301ctrl::readDEVICE_ID(){
+    return (unsigned char)(readStatus2() & 0x0F);
+}
+
+//コントロールレジスタ1の読み取り  =======================================
+/*
+ * DRV8301の現在の状態を読み取り、返す(コントロールレジスタ1)
+ * 読み取った情報は、内部の保存用変数に格納する
+ *
+ * この情報で読み取れるものは、
+ * GATE_CURRENT(FETゲートカレント設定), GATE_RESET(ゲートリセット監視),
+ * PWM_MODE(PWM信号送出方法), OCP_MODE(過電流監視モード),
+ * OC_ADJ_SET(過電流調整値)
+ *
+ * 設定値はデフォルトであればOC_ADJ_SET以外は0を返す
+ */
+unsigned short drv8301ctrl::readCtrl1(){
+    //取得した値を次回書き込み用変数に格納
+    writeValue1 = (unsigned short)(spi_cmd(DRV8301REG_READMODE | DRV8301REG_CTRL1) & 0x07FF);
+    return writeValue1;
+}
+
+//コントロールレジスタ2の読み取り  =======================================
+/*
+ * DRV8301の現在の状態を読み取り、返す(コントロールレジスタ2)
+ * 読み取った情報は、内部の保存用変数に格納する
+ *
+ * この情報で読み取れるものは、
+ * OCTW_MODE(過電流、温度上昇監視方法), GAIN(電流読み取り値増幅),
+ * DC_CAL_CH1(電流読み取り値オフセットch1),
+ * DC_CAL_CH2(電流読み取り値オフセットch2),
+ * OC_TOFF(過電流発生時オフタイム設定)
+ *
+ * 設定値はデフォルトであれば0を返す
+ */
+unsigned short drv8301ctrl::readCtrl2(){
+    //取得した値を次回書き込み用変数に格納
+    writeValue2 = (unsigned short)(spi_cmd(DRV8301REG_READMODE | DRV8301REG_CTRL2) & 0x07FF);
+    return writeValue2;
+}
+
+//コントロールレジスタ:GATE_CURRENTの読み取り  ===========================
+/*
+ * コントロールレジスタからGATE_CURRENTの状態だけを切り取って返す
+ *
+ * 戻り値の値は0 - 3の4種類
+ * Gate drive peak current 1.7 A = 0
+ * Gate drive peak current 0.7 A = 1
+ * Gate drive peak current 0.25 A = 2
+ * Reserved = 3
+ */
+unsigned char drv8301ctrl::readGATE_CURRENT(){
+    return (unsigned char)(readCtrl1() & 0x03);
+}
+
+//コントロールレジスタ:GATE_CURRENTの読み取り:実際の値で返す  ===================
+/*
+ * コントロールレジスタからGATE_CURRENTの状態だけを切り取って返す
+ *
+ * 戻り値の値は4種類
+ * Gate drive peak current 1.7 A = 1.7f
+ * Gate drive peak current 0.7 A = 0.7f
+ * Gate drive peak current 0.25 A = 0.25f
+ * Reserved = -1.0f
+ */
+float drv8301ctrl::readValGATE_CURRENT(){
+    float ret = 0.0f;
+    switch(readCtrl1() & 0x03){
+        case 0:
+            //1.7A
+            ret = 1.7f;
+            break;
+        case 1:
+            //0.7A
+            ret = 0.7f;
+            break;
+        case 2:
+            //0.25A
+            ret = 0.25f;
+            break;
+        default:
+            //reserved
+            ret = -1.0f;
+    }
+    return ret;
+}
+
+//コントロールレジスタ:GATE_RESETの読み取り  =============================
+/*
+ * コントロールレジスタからGATE_RESETの状態だけを切り取って返す
+ *
+ * 戻り値がtrueならNormal mode
+ * falseならReset gate driver latched faults (reverts to 0)
+ */
+bool drv8301ctrl::readGATE_RESETisNormal(){
+    //設定がNormalならtrue、そうでないならfalseを返す
+    return (((readCtrl1() >> 2) & 0x01) == 0);
+}
+
+//コントロールレジスタ:PWM_MODEの読み取り  ===============================
+/*
+ * コントロールレジスタからPWM_MODEの状態だけを切り取って返す
+ *
+ * 戻り値がtrueなら6線式PWMモード
+ * falseなら3線式PWMモード
+ */
+bool drv8301ctrl::readPWM_MODEis6PWM(){
+    //設定が6-PWM Modeならtrue、3-PWM Modeならfalseを返す
+    return (((readCtrl1() >> 3) & 0x01) == 0);
+}
+
+//コントロールレジスタ:OCP_MODEの読み取り  ===============================
+/*
+ * コントロールレジスタからOCP_MODEの状態だけを切り取って返す
+ *
+ * 戻り値の値は0 - 3の4種類
+ * Current limit = 0
+ * OC latch shut down = 1
+ * Report only = 2
+ * OC disabled = 3
+ */
+unsigned char drv8301ctrl::readOCP_MODE(){
+    return (unsigned char)((readCtrl1() >> 4) & 0x03);
+}
+
+//コントロールレジスタ:OC_ADJ_SETの読み取り  =============================
+/*
+ * コントロールレジスタからOC_ADJ_SETの状態だけを切り取って返す
+ *
+ * 戻り値の値は設定値の5bit(0 - 32)
+ */
+unsigned char drv8301ctrl::readOC_ADJ_SET(){
+    return (unsigned char)((readCtrl1() >> 6) & 0x1F);
+}
+
+//コントロールレジスタ:OC_ADJ_SETの読み取り:実際の値で返す  =====================
+/*
+ * コントロールレジスタからOC_ADJ_SETの状態だけを切り取って返す
+ *
+ * 戻り値の値は設定値の実際の値
+ */
+float drv8301ctrl::readValOC_ADJ_SET(){
+    float ret = 0.0f;
+    switch(readCtrl1() & 0x07C0){
+        case 0x0000: ret = 0.060; break;
+        case 0x0040: ret = 0.068; break;
+        case 0x0080: ret = 0.076; break;
+        case 0x00C0: ret = 0.086; break;
+        case 0x0100: ret = 0.097; break;
+        case 0x0140: ret = 0.109; break;
+        case 0x0180: ret = 0.123; break;
+        case 0x01C0: ret = 0.138; break;
+        case 0x0200: ret = 0.155; break;
+        case 0x0240: ret = 0.175; break;
+        case 0x0280: ret = 0.197; break;
+        case 0x02C0: ret = 0.222; break;
+        case 0x0300: ret = 0.250; break;
+        case 0x0340: ret = 0.282; break;
+        case 0x0380: ret = 0.317; break;
+        case 0x03C0: ret = 0.358; break;
+        case 0x0400: ret = 0.403; break;
+        case 0x0440: ret = 0.454; break;
+        case 0x0480: ret = 0.511; break;
+        case 0x04C0: ret = 0.576; break;
+        case 0x0500: ret = 0.648; break;
+        case 0x0540: ret = 0.730; break;
+        case 0x0580: ret = 0.822; break;
+        case 0x05C0: ret = 0.926; break;
+        case 0x0600: ret = 1.043; break;
+        case 0x0640: ret = 1.175; break;
+        case 0x0680: ret = 1.324; break;
+        case 0x06C0: ret = 1.491; break;
+        case 0x0700: ret = 1.679; break;
+        case 0x0740: ret = 1.892; break;
+        case 0x0780: ret = 2.131; break;
+        case 0x07C0: ret = 2.400; break;
+    }
+    return ret;
+}
+
+//コントロールレジスタ:OCTW_MODEの読み取り  ==============================
+/*
+ * コントロールレジスタからOCTW_MODEの状態だけを切り取って返す
+ *
+ * 戻り値の値は0 - 3の4種類
+ * Report both OT and OC at nOCTW pin = 0
+ * Report OT only = 1
+ * Report OC only = 2
+ * Report OC only (reserved) = 3
+ */
+unsigned char drv8301ctrl::readOCTW_MODE(){
+    return (unsigned char)(readCtrl2() & 0x03);
+}
+
+//コントロールレジスタ:GAINの読み取り  ===================================
+/*
+ * コントロールレジスタからGAINの状態だけを切り取って返す
+ *
+ * 戻り値の値は0 - 3の4種類
+ * Gain of shunt amplifier: 10 V/V = 0
+ * Gain of shunt amplifier: 20 V/V = 1
+ * Gain of shunt amplifier: 40 V/V = 2
+ * Gain of shunt amplifier: 80 V/V = 3
+ */
+unsigned char drv8301ctrl::readGAIN(){
+    return (unsigned char)((readCtrl2() >> 2) & 0x03);
+}
+
+//コントロールレジスタ:DC_CAL_CH1の読み取り  =============================
+/*
+ * コントロールレジスタからDC_CAL_CH1の状態だけを切り取って返す
+ *
+ * 戻り値がtrueならオフセット有効
+ * falseならオフセット無効
+ */
+bool drv8301ctrl::readDC_CAL_CH1isEnabled(){
+    //設定が有効(Enabled)ならtrue、そうでないならfalseを返す
+    return (((readCtrl2() >> 4) & 0x01) == 0);
+}
+
+//コントロールレジスタ:DC_CAL_CH2の読み取り  =============================
+/*
+ * コントロールレジスタからDC_CAL_CH2の状態だけを切り取って返す
+ *
+ * 戻り値がtrueならオフセット有効
+ * falseならオフセット無効
+ */
+bool drv8301ctrl::readDC_CAL_CH2isEnabled(){
+    //設定が有効(Enabled)ならtrue、そうでないならfalseを返す
+    return (((readCtrl2() >> 5) & 0x01) == 0);
+}
+
+//コントロールレジスタ:OC_TOFFの読み取り  ================================
+/*
+ * コントロールレジスタからOC_TOFFの状態だけを切り取って返す
+ *
+ * 戻り値がtrueならCycle by cycle
+ * falseならOff-time control
+ */
+bool drv8301ctrl::readOC_TOFFisCycleByCycle(){
+    //設定がCycle by Cycleならtrue、そうでないならfalseを返す
+    return (((readCtrl2() >> 6) & 0x01) == 0);
+}
+
+//コントロールレジスタ1への書き込み:valが0xffffならwriteValue1を使用する  =========
+/*
+ *  コントロールレジスタ1へ値を書き込む
+ *  引数valが指定されていれば、引数の中の値を書き込み
+ *  引数valが指定されていないか、もしくは引数valが0xffffであれば
+ *  内部に保存しているwriteValue1の中の値を書き込む
+ *
+ *  戻り値がtrueであれば書き込み成功
+ */
+bool drv8301ctrl::writeCtrl1(unsigned short val){
+    //シリアル出力
+    if(hasSerial){
+        pc->printf("CURRENT SETTING = 0x%08x\r\n", (spi_cmd(DRV8301REG_READMODE | DRV8301REG_CTRL1, false) & 0x07FF));
+        pc->printf(">>>>WRITE CTRL1 REGISTER\r\n\tval         = 0x%08x\r\n\twriteValue1 = 0x%08x\r\n", val, writeValue1);
+    }
+
+    //値の書き込み(先頭(MSB)に1がついていたら書き込み失敗)
+    unsigned short ret = spi_cmd(DRV8301REG_WRITEMODE | DRV8301REG_CTRL1 | ((val == 0xffff)? writeValue1 : val));
+
+    //値の書き込みが終わったら現在の値を取得して値をリセットする
+    resetWriteValue1();
+
+    //先頭ビットに1がついていなければ(32768未満であれば)書き込み成功(trueを返す)
+    return (ret < 32768);
+}
+
+//コントロールレジスタ2への書き込み:valが0xffffならwriteValue2を使用する  =========
+/*
+ *  コントロールレジスタ2へ値を書き込む
+ *  引数valが指定されていれば、引数の中の値を書き込み
+ *  引数valが指定されていないか、もしくは引数valが0xffffであれば
+ *  内部に保存しているwriteValue2の中の値を書き込む
+ *
+ *  戻り値がtrueであれば書き込み成功
+ */
+bool drv8301ctrl::writeCtrl2(unsigned short val){
+    //シリアル出力
+    if(hasSerial){
+        pc->printf("CURRENT SETTING = 0x%08x\r\n", (spi_cmd(DRV8301REG_READMODE | DRV8301REG_CTRL2, false) & 0x07FF));
+        pc->printf(">>>>WRITE CTRL2 REGISTER\r\n\tval         = 0x%08x\r\n\twriteValue2 = 0x%08x\r\n", val, writeValue2);
+    }
+
+    //値の書き込み(先頭(MSB)に1がついていたら書き込み失敗)
+    unsigned short ret = spi_cmd(DRV8301REG_WRITEMODE | DRV8301REG_CTRL2 | ((val == 0xffff)? writeValue2 : val));
+
+    //値の書き込みが終わったら現在の値を取得して値をリセットする
+    resetWriteValue2();
+
+    //先頭ビットに1がついていなければ(32768未満であれば)書き込み成功(trueを返す)
+    return (ret < 32768);
+}
+
+//コントロールレジスタ1に設定する内容を格納した変数をリセット  =========================
+void drv8301ctrl::resetWriteValue1(){
+    writeValue1 = (unsigned short)(spi_cmd(DRV8301REG_READMODE | DRV8301REG_CTRL1) & 0x07FF);
+}
+
+//コントロールレジスタ2に設定する内容を格納した変数をリセット  =========================
+void drv8301ctrl::resetWriteValue2(){
+    writeValue2 = (unsigned short)(spi_cmd(DRV8301REG_READMODE | DRV8301REG_CTRL2) & 0x07FF);
+}
+
+//コントロールレジスタ1に設定する内容を格納した変数を直接アップデート  =====================
+void drv8301ctrl::updateWriteValue1(unsigned short val){
+    writeValue1 = val;
+}
+
+//コントロールレジスタ2に設定する内容を格納した変数を直接アップデート  =====================
+void drv8301ctrl::updateWriteValue2(unsigned short val){
+    writeValue2 = val;
+}
+
+//コントロールレジスタ:GATE_CURRENTの書き込み  ===========================
+void drv8301ctrl::setGATE_CURRENT(unsigned char val){
+    //値は0x00,0x01,0x10,0x11の4種類。値が3(0x11)以上のものは0x00として扱う
+    if(val > 3) val = 0;
+
+    //writeValueの対象部分をゼロにして、論理和をとる
+    writeValue1 &= 0xFFFC;
+    writeValue1 |= val;
+
+    //シリアル出力
+    if(hasSerial){
+        pc->printf("Register1 temporary value changed, [GATE_CURRENT]\r\n\tval = 0x%08x, writeValue1 = 0x%08x\r\n", val, writeValue1);
+    }
+}
+
+//コントロールレジスタ:GATE_CURRENTの書き込み:実際の値に近いものを書き込む  ============
+void drv8301ctrl::setGATE_CURRENT(float realVal){
+    //値は0.0(reserved),0.25,0.7,1.7の4種類。値が1.7以上は1.7として扱う
+    realVal = (realVal < 0.0f) ? 0.0f : (realVal > 1.7f) ? 1.7f : realVal;
+
+    //writeValueの対象部分をゼロにする
+    writeValue1 &= 0xFFFC;
+
+    if(realVal < 0.25f){
+        writeValue1 |= GATE_CURRENT_PEAKCURRENT_RESERVED; //reserved
+    }else if(realVal < 0.7f){
+        writeValue1 |= GATE_CURRENT_PEAKCURRENT_0_25A; //0.25A
+    }else if(realVal < 1.7f){
+        writeValue1 |= GATE_CURRENT_PEAKCURRENT_0_7A; //0.7A
+    }else{
+        writeValue1 |= GATE_CURRENT_PEAKCURRENT_1_7A; //1.7A
+    }
+
+    //シリアル出力
+    if(hasSerial){
+        pc->printf("Register1 temporary value changed, [GATE_CURRENT]\r\n\tval = %01.2f, writeValue1 = 0x%08x\r\n", realVal, writeValue1);
+    }
+}
+
+//コントロールレジスタ:GATE_RESETの書き込み  =============================
+void drv8301ctrl::setGATE_RESET(bool isNormal){
+    //writeValueの対象部分をゼロにする
+    writeValue1 &= 0xFFFB;
+
+    writeValue1 |= isNormal ? GATE_RESET_NORMAL : GATE_RESET_RESETGATE_LATCHED_FAULT;
+
+    //シリアル出力
+    if(hasSerial){
+        pc->printf(
+            "Register1 temporary value changed, [GATE_RESET]\r\n\tisNormal = %s, writeValue1 = 0x%08x\r\n",
+            (isNormal ? "true" : "false"),
+            writeValue1
+        );
+    }
+}
+
+//コントロールレジスタ:PWM_MODEの書き込み  ===============================
+void drv8301ctrl::setPWM_MODE(bool is6PWM){
+    //writeValueの対象部分をゼロにする
+    writeValue1 &= 0xFFF7;
+
+    writeValue1 |= is6PWM ? PWM_MODE_PWMLINES_6 : PWM_MODE_PWMLINES_3;
+
+    //シリアル出力
+    if(hasSerial){
+        pc->printf(
+            "Register1 temporary value changed, [PWM_MODE]\r\n\tis6PWM = %s, writeValue1 = 0x%08x\r\n",
+            (is6PWM ? "true" : "false"),
+            writeValue1
+        );
+    }
+}
+
+//コントロールレジスタ:OCP_MODEの書き込み  ===============================
+void drv8301ctrl::setOCP_MODE(unsigned char val){
+    //値は0x00,0x01,0x10,0x11の4種類。値が3(0x11)以上のものは0x00として扱う
+    if(val > 3) val = 0;
+
+    //writeValueの対象部分をゼロにする
+    writeValue1 &= 0xFFCF;
+
+    switch(val){
+        case 0: writeValue1 |= OCP_MODE_CURRENTLIMIT; break;
+        case 1: writeValue1 |= OCP_MODE_OC_LATCH_SHUTDOWN; break;
+        case 2: writeValue1 |= OCP_MODE_REPORTONLY; break;
+        case 3: writeValue1 |= OCP_MODE_OC_DISABLE; break;
+    }
+
+    //シリアル出力
+    if(hasSerial){
+        pc->printf("Register1 temporary value changed, [GATE_CURRENT]\r\n\tval = 0x%08x, writeValue1 = 0x%08x\r\n", val, writeValue1);
+    }
+}
+
+//コントロールレジスタ:OC_ADJ_SETの書き込み  =============================
+void drv8301ctrl::setOC_ADJ(unsigned char val){
+    //値は0(0x00)から31(0x1f)まで。31以上は0として扱う
+    if(val > 31) val = 0;
+
+    //writeValueの対象部分をゼロにする
+    writeValue1 &= 0xF83F;
+
+    switch(val){
+        case 0: writeValue1 |= OC_ADJ_SET_ADJUST_0_060; break;
+        case 1: writeValue1 |= OC_ADJ_SET_ADJUST_0_068; break;
+        case 2: writeValue1 |= OC_ADJ_SET_ADJUST_0_076; break;
+        case 3: writeValue1 |= OC_ADJ_SET_ADJUST_0_086; break;
+        case 4: writeValue1 |= OC_ADJ_SET_ADJUST_0_097; break;
+        case 5: writeValue1 |= OC_ADJ_SET_ADJUST_0_109; break;
+        case 6: writeValue1 |= OC_ADJ_SET_ADJUST_0_123; break;
+        case 7: writeValue1 |= OC_ADJ_SET_ADJUST_0_138; break;
+        case 8: writeValue1 |= OC_ADJ_SET_ADJUST_0_155; break;
+        case 9: writeValue1 |= OC_ADJ_SET_ADJUST_0_175; break;
+        case 10: writeValue1 |= OC_ADJ_SET_ADJUST_0_197; break;
+        case 11: writeValue1 |= OC_ADJ_SET_ADJUST_0_222; break;
+        case 12: writeValue1 |= OC_ADJ_SET_ADJUST_0_250; break;
+        case 13: writeValue1 |= OC_ADJ_SET_ADJUST_0_282; break;
+        case 14: writeValue1 |= OC_ADJ_SET_ADJUST_0_317; break;
+        case 15: writeValue1 |= OC_ADJ_SET_ADJUST_0_358; break;
+        case 16: writeValue1 |= OC_ADJ_SET_ADJUST_0_403; break;
+        case 17: writeValue1 |= OC_ADJ_SET_ADJUST_0_454; break;
+        case 18: writeValue1 |= OC_ADJ_SET_ADJUST_0_511; break;
+        case 19: writeValue1 |= OC_ADJ_SET_ADJUST_0_576; break;
+        case 20: writeValue1 |= OC_ADJ_SET_ADJUST_0_648; break;
+        case 21: writeValue1 |= OC_ADJ_SET_ADJUST_0_730; break;
+        case 22: writeValue1 |= OC_ADJ_SET_ADJUST_0_822; break;
+        case 23: writeValue1 |= OC_ADJ_SET_ADJUST_0_926; break;
+        case 24: writeValue1 |= OC_ADJ_SET_ADJUST_1_043; break;
+        case 25: writeValue1 |= OC_ADJ_SET_ADJUST_1_175; break;
+        case 26: writeValue1 |= OC_ADJ_SET_ADJUST_1_324; break;
+        case 27: writeValue1 |= OC_ADJ_SET_ADJUST_1_491; break;
+        case 28: writeValue1 |= OC_ADJ_SET_ADJUST_1_679; break;
+        case 29: writeValue1 |= OC_ADJ_SET_ADJUST_1_892; break;
+        case 30: writeValue1 |= OC_ADJ_SET_ADJUST_2_131; break;
+        case 31: writeValue1 |= OC_ADJ_SET_ADJUST_2_400; break;
+    }
+
+    //シリアル出力
+    if(hasSerial){
+        pc->printf("Register1 temporary value changed, [OC_ADJ_SET]\r\n\tval = 0x%08x, writeValue1 = 0x%08x\r\n", val, writeValue1);
+    }
+}
+
+//コントロールレジスタ:OC_ADJ_SETの書き込み:実際の値に近いものを書き込む  ==============
+void drv8301ctrl::setOC_ADJ(float realVal){
+    //値は0.06から2.4まで。それ以上は0.06として扱う
+    realVal = (realVal < 0.06f) ? 0.06f : (realVal > 2.4f) ? 2.4f : realVal;
+
+    //writeValueの対象部分をゼロにする
+    writeValue1 &= 0xF83F;
+
+    //ifで振り分けていく・・・しかないのか・・・?
+    if(realVal < 0.068f) writeValue1 |= OC_ADJ_SET_ADJUST_0_060;
+    else if(realVal < 0.076f) writeValue1 |= OC_ADJ_SET_ADJUST_0_068;
+    else if(realVal < 0.086f) writeValue1 |= OC_ADJ_SET_ADJUST_0_076;
+    else if(realVal < 0.097f) writeValue1 |= OC_ADJ_SET_ADJUST_0_086;
+    else if(realVal < 0.109f) writeValue1 |= OC_ADJ_SET_ADJUST_0_097;
+    else if(realVal < 0.123f) writeValue1 |= OC_ADJ_SET_ADJUST_0_109;
+    else if(realVal < 0.138f) writeValue1 |= OC_ADJ_SET_ADJUST_0_123;
+    else if(realVal < 0.155f) writeValue1 |= OC_ADJ_SET_ADJUST_0_138;
+    else if(realVal < 0.175f) writeValue1 |= OC_ADJ_SET_ADJUST_0_155;
+    else if(realVal < 0.197f) writeValue1 |= OC_ADJ_SET_ADJUST_0_175;
+    else if(realVal < 0.222f) writeValue1 |= OC_ADJ_SET_ADJUST_0_197;
+    else if(realVal < 0.250f) writeValue1 |= OC_ADJ_SET_ADJUST_0_222;
+    else if(realVal < 0.282f) writeValue1 |= OC_ADJ_SET_ADJUST_0_250;
+    else if(realVal < 0.317f) writeValue1 |= OC_ADJ_SET_ADJUST_0_282;
+    else if(realVal < 0.358f) writeValue1 |= OC_ADJ_SET_ADJUST_0_317;
+    else if(realVal < 0.403f) writeValue1 |= OC_ADJ_SET_ADJUST_0_358;
+    else if(realVal < 0.454f) writeValue1 |= OC_ADJ_SET_ADJUST_0_403;
+    else if(realVal < 0.511f) writeValue1 |= OC_ADJ_SET_ADJUST_0_454;
+    else if(realVal < 0.576f) writeValue1 |= OC_ADJ_SET_ADJUST_0_511;
+    else if(realVal < 0.648f) writeValue1 |= OC_ADJ_SET_ADJUST_0_576;
+    else if(realVal < 0.730f) writeValue1 |= OC_ADJ_SET_ADJUST_0_648;
+    else if(realVal < 0.822f) writeValue1 |= OC_ADJ_SET_ADJUST_0_730;
+    else if(realVal < 0.926f) writeValue1 |= OC_ADJ_SET_ADJUST_0_822;
+    else if(realVal < 1.043f) writeValue1 |= OC_ADJ_SET_ADJUST_0_926;
+    else if(realVal < 1.175f) writeValue1 |= OC_ADJ_SET_ADJUST_1_043;
+    else if(realVal < 1.324f) writeValue1 |= OC_ADJ_SET_ADJUST_1_175;
+    else if(realVal < 1.491f) writeValue1 |= OC_ADJ_SET_ADJUST_1_324;
+    else if(realVal < 1.679f) writeValue1 |= OC_ADJ_SET_ADJUST_1_491;
+    else if(realVal < 1.892f) writeValue1 |= OC_ADJ_SET_ADJUST_1_679;
+    else if(realVal < 2.131f) writeValue1 |= OC_ADJ_SET_ADJUST_1_892;
+    else if(realVal < 2.400f) writeValue1 |= OC_ADJ_SET_ADJUST_2_131;
+    else writeValue1 |= OC_ADJ_SET_ADJUST_2_400;
+
+    //シリアル出力
+    if(hasSerial){
+        pc->printf("Register1 temporary value changed, [OC_ADJ_SET]\r\n\tval = %2.3f, writeValue1 = 0x%08x\r\n", realVal, writeValue1);
+    }
+}
+
+//コントロールレジスタ:OCTW_MODEの書き込み  ==============================
+void drv8301ctrl::setOCTW_MODE(unsigned char val){
+    //値は0x00,0x01,0x10,0x11の4種類。値が3(0x11)以上のものは0x00として扱う
+    if(val > 3) val = 0;
+
+    //writeValueの対象部分をゼロにする
+    writeValue2 &= 0xFFFC;
+
+    switch(val){
+        case 0: writeValue2 |= OCTW_MODE_REPORT_OT_OC_BOTH; break;
+        case 1: writeValue2 |= OCTW_MODE_REPORT_OVERTEMP_ONLY; break;
+        case 2: writeValue2 |= OCTW_MODE_REPORT_OVERCURRENT_ONLY; break;
+        case 3: writeValue2 |= OCTW_MODE_REPORT_RESERVED; break;
+    }
+
+    //シリアル出力
+    if(hasSerial){
+        pc->printf("Register2 temporary value changed, [OCTW_MODE]\r\n\tval = 0x%08x, writeValue1 = 0x%08x\r\n", val, writeValue2);
+    }
+}
+
+//コントロールレジスタ:GAINの書き込み  ===================================
+void drv8301ctrl::setGAIN(unsigned char val){
+    //値は0x00,0x01,0x10,0x11の4種類。値が3(0x11)以上のものは0x00として扱う
+    if(val > 3) val = 0;
+
+    //writeValueの対象部分をゼロにする
+    writeValue2 &= 0xFFF3;
+
+    switch(val){
+        case 0: writeValue2 |= SHUNTGAIN_GAIN_10V_PER_V; break;
+        case 1: writeValue2 |= SHUNTGAIN_GAIN_20V_PER_V; break;
+        case 2: writeValue2 |= SHUNTGAIN_GAIN_40V_PER_V; break;
+        case 3: writeValue2 |= SHUNTGAIN_GAIN_80V_PER_V; break;
+    }
+
+    //シリアル出力
+    if(hasSerial){
+        pc->printf("Register2 temporary value changed, [GAIN]\r\n\tval = 0x%08x, writeValue1 = 0x%08x\r\n", val, writeValue2);
+    }
+}
+
+//コントロールレジスタ:DC_CAL_CH1の書き込み  =============================
+void drv8301ctrl::setDC_CAL_CH1_Enabled(bool enable){
+    //writeValueの対象部分をゼロにする
+    writeValue2 &= 0xFFEF;
+
+    //引数がtrueならDC_CALを有効にする
+    writeValue2 |= enable ? DC_CAL_CH1_ENABLE : DC_CAL_CH1_DISABLE;
+
+    //シリアル出力
+    if(hasSerial){
+        pc->printf(
+            "Register2 temporary value changed, [DC_CAL_CH1]\r\n\tval = %s, writeValue1 = 0x%08x\r\n",
+            enable ? "true" : "false",
+            writeValue2
+        );
+    }
+}
+
+//コントロールレジスタ:DC_CAL_CH2の書き込み  =============================
+void drv8301ctrl::setDC_CAL_CH2_Enabled(bool enable){
+    //writeValueの対象部分をゼロにする
+    writeValue2 &= 0xFFDF;
+
+    //引数がtrueならDC_CALを有効にする
+    writeValue2 |= enable ? DC_CAL_CH1_ENABLE : DC_CAL_CH1_DISABLE;
+
+    //シリアル出力
+    if(hasSerial){
+        pc->printf(
+            "Register2 temporary value changed, [DC_CAL_CH2]\r\n\tval = %s, writeValue1 = 0x%08x\r\n",
+            enable ? "true" : "false",
+            writeValue2
+        );
+    }
+}
+
+//コントロールレジスタ:OC_TOFFの書き込み  ================================
+void drv8301ctrl::setOC_TOFF_CycleByCycle(bool enable){
+    //writeValueの対象部分をゼロにする
+    writeValue2 &= 0xFFBF;
+
+    //引数がtrueならOC_TOFFをCycleByCycleにする
+    writeValue2 |= enable ? OC_TOFF_CYCLE_BY_CYCLE : OC_TOFF_OFF_TIME_CONTROL;
+
+    //シリアル出力
+    if(hasSerial){
+        pc->printf(
+            "Register2 temporary value changed, [OC_TOFF]\r\n\tval = %s, writeValue1 = 0x%08x\r\n",
+            enable ? "true" : "false",
+            writeValue2
+        );
+    }
+}
+
+//EN_GATEを有効にする
+void drv8301ctrl::gateEnable(){
+    DRV8301_GATE_ACTIVE;
+    wait_us(20);
+}
+
+//EN_GATEを無効にする
+void drv8301ctrl::gateDisable(){
+    DRV8301_GATE_INACTIVE;
+    wait_us(20);
+}
+
+//状態をリセットする(ON-OFF-ON)
+void drv8301ctrl::gateReset(){
+    DRV8301_GATE_ACTIVE;
+    wait_us(15);
+    DRV8301_GATE_INACTIVE;
+    wait_us(15);
+    DRV8301_GATE_ACTIVE;
+    wait_us(15);
+}
diff -r 000000000000 -r 72d833823fd5 DRV8301CTRL.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DRV8301CTRL.h	Wed Aug 31 17:03:35 2016 +0000
@@ -0,0 +1,263 @@
+/* Copyright (c) 2016 Yajirushi(Cursor)
+ *
+ * Released under the MIT license
+ * http://opensource.org/licenses/mit-license.php
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "mbed.h"
+
+#ifndef DRV8301CTRL_H
+#define DRV8301CTRL_H
+
+// ##### BEGIN:ここからユーザーが変更する部分(Change setting, if you need.) ####
+
+//DRV8301 SPI FREQUENCY(SPIの周波数:Max=5MHz)
+#define DRV8301CTRL_FREQ 1000000
+
+// ##### END:ここまで                                                      #####
+
+//STATUS & CONTROL REGISTERS
+#define DRV8301REG_WRITEMODE 0x0000
+#define DRV8301REG_READMODE 0x8000
+#define DRV8301REG_STATUS1 0x0000
+#define DRV8301REG_STATUS2 0x0800
+#define DRV8301REG_CTRL1 0x1000
+#define DRV8301REG_CTRL2 0x1800
+
+//ENUM STATUS & CONTROL VALUES
+enum CTRL1_GATE_CURRENT{
+    GATE_CURRENT_PEAKCURRENT_1_7A = 0x0000,
+    GATE_CURRENT_PEAKCURRENT_0_7A = 0x0001,
+    GATE_CURRENT_PEAKCURRENT_0_25A = 0x0002,
+    GATE_CURRENT_PEAKCURRENT_RESERVED = 0x0003
+};
+enum CTRL1_GATE_RESET{
+    GATE_RESET_NORMAL = 0x0000,
+    GATE_RESET_RESETGATE_LATCHED_FAULT = 0x0004
+};
+enum CTRL1_PWM_MODE{
+    PWM_MODE_PWMLINES_6 = 0x0000,
+    PWM_MODE_PWMLINES_3 = 0x0008
+};
+enum CTRL1_OCP_MODE{
+    OCP_MODE_CURRENTLIMIT = 0x0000,
+    OCP_MODE_OC_LATCH_SHUTDOWN = 0x0010,
+    OCP_MODE_REPORTONLY = 0x0020,
+    OCP_MODE_OC_DISABLE = 0x0030
+};
+enum CTRL1_OC_ADJ{
+    OC_ADJ_SET_ADJUST_0_060=0x0000,
+    OC_ADJ_SET_ADJUST_0_068=0x0040,
+    OC_ADJ_SET_ADJUST_0_076=0x0080,
+    OC_ADJ_SET_ADJUST_0_086=0x00C0,
+    OC_ADJ_SET_ADJUST_0_097=0x0100,
+    OC_ADJ_SET_ADJUST_0_109=0x0140,
+    OC_ADJ_SET_ADJUST_0_123=0x0180,
+    OC_ADJ_SET_ADJUST_0_138=0x01C0,
+    OC_ADJ_SET_ADJUST_0_155=0x0200,
+    OC_ADJ_SET_ADJUST_0_175=0x0240,
+    OC_ADJ_SET_ADJUST_0_197=0x0280,
+    OC_ADJ_SET_ADJUST_0_222=0x02C0,
+    OC_ADJ_SET_ADJUST_0_250=0x0300,
+    OC_ADJ_SET_ADJUST_0_282=0x0340,
+    OC_ADJ_SET_ADJUST_0_317=0x0380,
+    OC_ADJ_SET_ADJUST_0_358=0x03C0,
+    OC_ADJ_SET_ADJUST_0_403=0x0400,
+    OC_ADJ_SET_ADJUST_0_454=0x0440,
+    OC_ADJ_SET_ADJUST_0_511=0x0480,
+    OC_ADJ_SET_ADJUST_0_576=0x04C0,
+    OC_ADJ_SET_ADJUST_0_648=0x0500,
+    OC_ADJ_SET_ADJUST_0_730=0x0540,
+    OC_ADJ_SET_ADJUST_0_822=0x0580,
+    OC_ADJ_SET_ADJUST_0_926=0x05C0,
+    OC_ADJ_SET_ADJUST_1_043=0x0600,
+    OC_ADJ_SET_ADJUST_1_175=0x0640,
+    OC_ADJ_SET_ADJUST_1_324=0x0680,
+    OC_ADJ_SET_ADJUST_1_491=0x06C0,
+    OC_ADJ_SET_ADJUST_1_679=0x0700,
+    OC_ADJ_SET_ADJUST_1_892=0x0740,
+    OC_ADJ_SET_ADJUST_2_131=0x0780,
+    OC_ADJ_SET_ADJUST_2_400=0x07C0
+};
+enum CTRL2_OCTW_MODE{
+    OCTW_MODE_REPORT_OT_OC_BOTH = 0x0000,
+    OCTW_MODE_REPORT_OVERTEMP_ONLY = 0x0001,
+    OCTW_MODE_REPORT_OVERCURRENT_ONLY = 0x0002,
+    OCTW_MODE_REPORT_RESERVED = 0x0003
+};
+enum CTRL2_SHUNTGAIN{
+    SHUNTGAIN_GAIN_10V_PER_V = 0x0000,
+    SHUNTGAIN_GAIN_20V_PER_V = 0x0004,
+    SHUNTGAIN_GAIN_40V_PER_V = 0x0008,
+    SHUNTGAIN_GAIN_80V_PER_V = 0x000C
+};
+enum CTRL2_DC_CAL_CH1{
+    DC_CAL_CH1_ENABLE = 0x0000,
+    DC_CAL_CH1_DISABLE = 0x0010
+};
+enum CTRL2_DC_CAL_CH2{
+    DC_CAL_CH2_ENABLE = 0x0000,
+    DC_CAL_CH2_DISABLE = 0x0020
+};
+enum CTRL2_OC_TOFF{
+    OC_TOFF_CYCLE_BY_CYCLE = 0x0000,
+    OC_TOFF_OFF_TIME_CONTROL = 0x0040
+};
+
+//DRV8301 Control Class ========================================================
+class drv8301ctrl{
+public:
+    //Constructor (Overload +3)
+    drv8301ctrl(Serial *serial, SPI *spi, PinName csel, PinName en_gate);
+    drv8301ctrl(Serial *serial, SPI *spi, DigitalOut *csel, DigitalOut *en_gate);
+    drv8301ctrl(SPI *spi, PinName csel, PinName en_gate);
+    drv8301ctrl(SPI *spi, DigitalOut *csel, DigitalOut *en_gate);
+
+    //Destructor
+    ~drv8301ctrl();
+
+private:
+    Serial *pc;
+    SPI *si;
+    DigitalOut *cs, *gate;
+
+    bool hasSerial;
+    unsigned short writeValue1, writeValue2;
+    unsigned char devID;
+
+    //SPI read/write command
+    int spi_cmd(int val, bool debug=true);
+
+public:
+
+    //initialize:初期化
+    void init(bool reset_iface=true);
+
+    //read status register1:(ステータスレジスタ1の読み取り)
+    //FAULT, GVDD_UV, PVDD_UV, OTSD, OTW,
+    //FETHA_OC, FETLA_OC, FETHB_OC, FETLB_OC, FETHC_OC, FETLC_OC
+    unsigned short readStatus1();
+
+    //read status register2:(ステータスレジスタ2の読み取り)
+    //GVDD_OV, DEVICE_ID
+    unsigned short readStatus2();
+
+    //read status:FAULT
+    bool readFault();
+    //read status:GVDD_UV(GVDD under voltage)
+    bool readGVDD_UV();
+    //read status:PVDD_UV(PVDD under voltage)
+    bool readPVDD_UV();
+    //read status:OTSD(Over Temperature ShutDown: over 150 degree C)
+    bool readOTSD();
+    //read status:OTW(Over Temperature Warning: over 130 degree C)
+    bool readOTW();
+    //read status:FETHA_OC(MOSFET A High-Side Over Current: ref OC_ADJ)
+    bool readFETHA_OC();
+    //read status:FETLA_OC(MOSFET A Low-Side Over Current: ref OC_ADJ)
+    bool readFETLA_OC();
+    //read status:FETHB_OC(MOSFET B High-Side Over Current: ref OC_ADJ)
+    bool readFETHB_OC();
+    //read status:FETLB_OC(MOSFET B Low-Side Over Current: ref OC_ADJ)
+    bool readFETLB_OC();
+    //read status:FETHC_OC(MOSFET C High-Side Over Current: ref OC_ADJ)
+    bool readFETHC_OC();
+    //read status:FETLC_OC(MOSFET C Low-Side Over Current: ref OC_ADJ)
+    bool readFETLC_OC();
+    //read status:GVDD_OV(GVDD over voltage)
+    bool readGVDD_OV();
+    //read status:DEVICE_ID
+    unsigned char readDEVICE_ID();
+
+    //read control register1:(コントロールレジスタ1の読み取り)
+    //GATE_CURRENT, GATE_RESET, PWM_MODE, OCP_MODE, OC_ADJ_SET
+    unsigned short readCtrl1();
+
+    //read control register2:(コントロールレジスタ2の読み取り)
+    //OCTW_MODE, GAIN, DC_CAL_CH1, DC_CAL_CH2, OC_TOFF
+    unsigned short readCtrl2();
+
+    //read settings:GATE_CURRENT(MOSFET Gate drive peak current)
+    unsigned char readGATE_CURRENT(); //HexValue
+    float readValGATE_CURRENT(); //RealValue
+    //read settings:GATE_RESET(MOSFET Gate reset mode)
+    bool readGATE_RESETisNormal();
+    //read settings:PWM_MODE(6-pwm or 3-pwm)
+    bool readPWM_MODEis6PWM();
+    //read settings:OCP_MODE(Over Current Protection mode)
+    unsigned char readOCP_MODE();
+    //read settings:OC_ADJ_SET(Over Curent Adjust set)
+    unsigned char readOC_ADJ_SET(); //HexValue
+    float readValOC_ADJ_SET(); //RealValue
+    //read settings:OCTW_MODE(Over Current and Temperature Warning mode)
+    unsigned char readOCTW_MODE();
+    //read settings:GAIN(Shunt amp gain)
+    unsigned char readGAIN();
+    //read settings:DC_CAL_CH1(Calibration Shunt amp CH-1)
+    bool readDC_CAL_CH1isEnabled();
+    //read settings:DC_CAL_CH2(Calibration Shunt amp CH-2)
+    bool readDC_CAL_CH2isEnabled();
+    //read settings:OC_TOFF(Over Current MOSFET gate off mode)
+    bool readOC_TOFFisCycleByCycle();
+
+    //write control register1:(コントロールレジスタ1へ書き込み)
+    bool writeCtrl1(unsigned short val=0xffff);
+
+    //write control register2:(コントロールレジスタ2へ書き込み)
+    bool writeCtrl2(unsigned short val=0xffff);
+
+    //writeValue clear:(内部に保持しているレジスタの仮の値を消去)
+    void resetWriteValue1();
+    void resetWriteValue2();
+
+    //writeValue direct update:(内部に保持しているレジスタの仮の値を更新)
+    void updateWriteValue1(unsigned short val);
+    void updateWriteValue2(unsigned short val);
+
+    //set value:GATE_CURRENT(MOSFET Gate drive peak current)
+    void setGATE_CURRENT(unsigned char hexVal);
+    void setGATE_CURRENT(float realVal);
+    //set value:GATE_RESET(MOSFET Gate reset mode)
+    void setGATE_RESET(bool isNormal);
+    //set value:PWM_MODE(6-pwm or 3-pwm)
+    void setPWM_MODE(bool is6PWM);
+    //set value:OCP_MODE(Over Current Protection mode)
+    void setOCP_MODE(unsigned char val);
+    //set value:OC_ADJ_SET(Over Curent Adjust set)
+    void setOC_ADJ(unsigned char hexVal);
+    void setOC_ADJ(float realVal);
+    //set value:OCTW_MODE(Over Current and Temperature Warning mode)
+    void setOCTW_MODE(unsigned char val);
+    //set value:GAIN(Shunt amp gain)
+    void setGAIN(unsigned char val);
+    //set value:DC_CAL_CH1(Calibration Shunt amp CH-1)
+    void setDC_CAL_CH1_Enabled(bool enable);
+    //set value:DC_CAL_CH2(Calibration Shunt amp CH-2)
+    void setDC_CAL_CH2_Enabled(bool enable);
+    //set value:OC_TOFF(Over Current MOSFET gate off mode)
+    void setOC_TOFF_CycleByCycle(bool enable);
+
+    //EN_GATE on,off:(EN_GATEピンの状態セット)
+    void gateEnable();
+    void gateDisable();
+    void gateReset();
+};
+
+#endif