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

Dependents:   BLDC1Axis_DRV8301CTRL

DRV8301CTRL.cpp

Committer:
Yajirushi
Date:
2016-08-31
Revision:
0:72d833823fd5

File content as of revision 0:72d833823fd5:

#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);
}