################################################################################
# Copyright © 2024 Analog Devices Inc. All Rights Reserved.
# This software is proprietary to Analog Devices, Inc. and its licensors.
################################################################################

from ..ic.tmc_ic import TMCIc
from ..features.motor_control_ic import MotorControlIc


class TMC5272(TMCIc):
    """
    The TMC5272 is a high-performance dual-axis stepper motor controller and driver IC for two phase stepper motors
    with serial communication interfaces (SPI and UART). Supply voltage: 2.1-20V.
    """
    def __init__(self, parent_eval):
        super().__init__(self.__class__.__name__, self.__doc__)
        self._parent = parent_eval
        self.motors = [self.MotorTypeA(parent_eval, self, 0),
                       self.MotorTypeA(parent_eval, self, 1)]

    class MotorTypeA(MotorControlIc):
        """
        Motor class for the generic motor.
        """
        def __init__(self, parent_eval, ic, axis):
            MotorControlIc.__init__(self, parent_eval, ic, axis)

    class REG:
        """
        Define all registers of the TMC5272.
        """
        GCONF                = 0x00
        GSTAT                = 0x01
        IFCNT                = 0x02
        SLAVECONF            = 0x03
        IOIN                 = 0x04
        DRV_CONF             = 0x05
        GLOBAL_SCALER        = 0x06
        RAMPMODE             = 0x07
        MSLUT_ADDR           = 0x08
        MSLUT_SEL_START      = 0x09
        M0_X_COMPARE         = 0x10
        M0_X_COMPARE_REPEAT  = 0x11
        M0_IHOLD_IRUN        = 0x12
        M0_TPOWERDOWN        = 0x13
        M0_TSTEP             = 0x14
        M0_TPWMTHRS          = 0x15
        M0_TCOOLTHRS         = 0x16
        M0_THIGH             = 0x17
        M0_XACTUAL           = 0x18
        M0_VACTUAL           = 0x19
        M0_AACTUAL           = 0x1A
        M0_VSTART            = 0x1B
        M0_A1                = 0x1C
        M0_V1                = 0x1D
        M0_A2                = 0x1E
        M0_V2                = 0x1F
        M0_AMAX              = 0x20
        M0_VMAX              = 0x21
        M0_DMAX              = 0x22
        M0_D2                = 0x23
        M0_D1                = 0x24
        M0_VSTOP             = 0x25
        M0_TVMAX             = 0x26
        M0_TZEROWAIT         = 0x27
        M0_XTARGET           = 0x28
        M0_VDCMIN            = 0x29
        M0_SW_MODE           = 0x2A
        M0_RAMP_STAT         = 0x2B
        M0_XLATCH            = 0x2C
        M0_POSITION_PI_CTRL  = 0x2D
        M0_X_ENC             = 0x2E
        M0_ENCMODE           = 0x2F
        M0_ENC_CONST         = 0x30
        M0_ENC_STATUS        = 0x31
        M0_ENC_LATCH         = 0x32
        M0_ENC_DEVIATION     = 0x33
        M0_VIRTUAL_STOP_L    = 0x34
        M0_VIRTUAL_STOP_R    = 0x35
        M0_MSCNT             = 0x36
        M0_MSCURACT          = 0x37
        M0_CHOPCONF          = 0x38
        M0_COOLCONF          = 0x39
        M0_DCCTRL            = 0x3A
        M0_DRV_STATUS        = 0x3B
        M0_PWMCONF           = 0x3C
        M0_PWM_SCALE         = 0x3D
        M0_PWM_AUTO          = 0x3E
        M0_SG4_THRS          = 0x3F
        M0_SG4_RESULT        = 0x40
        M0_SG4_IND           = 0x41
        M1_X_COMPARE         = 0x45
        M1_X_COMPARE_REPEAT  = 0x46
        M1_IHOLD_IRUN        = 0x47
        M1_TPOWERDOWN        = 0x48
        M1_TSTEP             = 0x49
        M1_TPWMTHRS          = 0x4A
        M1_TCOOLTHRS         = 0x4B
        M1_THIGH             = 0x4C
        M1_XACTUAL           = 0x4D
        M1_VACTUAL           = 0x4E
        M1_AACTUAL           = 0x4F
        M1_VSTART            = 0x50
        M1_A1                = 0x51
        M1_V1                = 0x52
        M1_A2                = 0x53
        M1_V2                = 0x54
        M1_AMAX              = 0x55
        M1_VMAX              = 0x56
        M1_DMAX              = 0x57
        M1_D2                = 0x58
        M1_D1                = 0x59
        M1_VSTOP             = 0x5A
        M1_TVMAX             = 0x5B
        M1_TZEROWAIT         = 0x5C
        M1_XTARGET           = 0x5D
        M1_VDCMIN            = 0x5E
        M1_SW_MODE           = 0x5F
        M1_RAMP_STAT         = 0x60
        M1_XLATCH            = 0x61
        M1_POSITION_PI_CTRL  = 0x62
        M1_X_ENC             = 0x63
        M1_ENCMODE           = 0x64
        M1_ENC_CONST         = 0x65
        M1_ENC_STATUS        = 0x66
        M1_ENC_LATCH         = 0x67
        M1_ENC_DEVIATION     = 0x68
        M1_VIRTUAL_STOP_L    = 0x69
        M1_VIRTUAL_STOP_R    = 0x6A
        M1_MSCNT             = 0x6B
        M1_MSCURACT          = 0x6C
        M1_CHOPCONF          = 0x6D
        M1_COOLCONF          = 0x6E
        M1_DCCTRL            = 0x6F
        M1_DRV_STATUS        = 0x70
        M1_PWMCONF           = 0x71
        M1_PWM_SCALE         = 0x72
        M1_PWM_AUTO          = 0x73
        M1_SG4_THRS          = 0x74
        M1_SG4_RESULT        = 0x75
        M1_SG4_IND           = 0x76

    class FIELD:
        """
        Define all register bitfields of the TMC5272.

        Each field is defined as a tuple consisting of ( Address, Mask, Shift ).

        The name of the register is written as a comment behind each tuple. This is
        intended for IDE users viewing the definition of a field by hovering over
        it. This allows the user to see the corresponding register name of a field
        without opening this file and searching for the definition.
        """
        GCONF_M0_EN_PWM_MODE                = ( 0x00, 0x00000001,  0 )
        GCONF_M0_MULTISTEP_FILT             = ( 0x00, 0x00000002,  1 )
        GCONF_M0_SHAFT                      = ( 0x00, 0x00000004,  2 )
        GCONF_M0_DIAG0_ERROR                = ( 0x00, 0x00000008,  3 )
        GCONF_DIAG0_OTPW                    = ( 0x00, 0x00000010,  4 )
        GCONF_DIAG0_STALL_STEP              = ( 0x00, 0x00000020,  5 )
        GCONF_DIAG1_STALL_DIR               = ( 0x00, 0x00000040,  6 )
        GCONF_M0_DIAG1_INDEX                = ( 0x00, 0x00000080,  7 )
        GCONF_DIAG0_INT_PUSHPULL            = ( 0x00, 0x00000100,  8 )
        GCONF_DIAG1_POSCOMP_PUSHPULL        = ( 0x00, 0x00000200,  9 )
        GCONF_M0_SMALL_HYSTERESIS           = ( 0x00, 0x00000400, 10 )
        GCONF_M0_STOP_ENABLE                = ( 0x00, 0x00000800, 11 )
        GCONF_M0_DIRECT_MODE                = ( 0x00, 0x00001000, 12 )
        GCONF_M0_SD                         = ( 0x00, 0x00002000, 13 )
        GCONF_M0_DRV_ENN                    = ( 0x00, 0x00004000, 14 )
        GCONF_QSC_STS_ENA                   = ( 0x00, 0x00008000, 15 )
        GCONF_M1_EN_PWM_MODE                = ( 0x00, 0x00010000, 16 )
        GCONF_M1_MULTISTEP_FILT             = ( 0x00, 0x00020000, 17 )
        GCONF_M1_SHAFT                      = ( 0x00, 0x00040000, 18 )
        GCONF_DIAG0_INTOUT_SEL              = ( 0x00, 0x00180000, 19 )
        GCONF_DIAG1_X_COMP_SEL              = ( 0x00, 0x00600000, 21 )
        GCONF_M1_DIAG1_INDEX                = ( 0x00, 0x00800000, 23 )
        GCONF_M1_SMALL_HYSTERESIS           = ( 0x00, 0x01000000, 24 )
        GCONF_M1_STOP_ENABLE                = ( 0x00, 0x02000000, 25 )
        GCONF_M1_DIRECT_MODE                = ( 0x00, 0x04000000, 26 )
        GCONF_M1_SD                         = ( 0x00, 0x08000000, 27 )
        GCONF_M1_DRV_ENN                    = ( 0x00, 0x10000000, 28 )
        GSTAT_RESET                         = ( 0x01, 0x00000001,  0 )
        GSTAT_M0_DRV_ERR                    = ( 0x01, 0x00000002,  1 )
        GSTAT_UV_CP                         = ( 0x01, 0x00000004,  2 )
        GSTAT_REGISTER_RESET                = ( 0x01, 0x00000008,  3 )
        GSTAT_VM_UVLO                       = ( 0x01, 0x00000010,  4 )
        GSTAT_M1_DRV_ERR                    = ( 0x01, 0x00000020,  5 )
        IFCNT                               = ( 0x02, 0x000000FF,  0 )
        SLAVECONF_SLAVEADDR                 = ( 0x03, 0x000000FF,  0 )
        SLAVECONF_SENDDELAY                 = ( 0x03, 0x00000F00,  8 )
        ADC_TEMPERATURE                     = ( 0x04, 0x000001FE,  1 )
        ADC_EN                              = ( 0x04, 0x00000200,  9 )
        IOIN_SEL_OSCILLATOR                 = ( 0x04, 0x00000800, 11 )
        IOIN_EXT_RES_DET                    = ( 0x04, 0x00001000, 12 )
        IOIN_OUTPUT                         = ( 0x04, 0x00002000, 13 )
        QSC_STATUS                          = ( 0x04, 0x00008000, 15 )
        IOIN_SILICON_RV                     = ( 0x04, 0x00070000, 16 )
        IOIN_VERSION                        = ( 0x04, 0xFF000000, 24 )
        M0_FSR                                 = ( 0x05, 0x00000003,  0 )
        M0_FSR_IREF                            = ( 0x05, 0x0000000C,  2 )
        DRV_CONF_M0_EN_EMERGENCY_DISABLE    = ( 0x05, 0x00000010,  4 )
        DRV_CONF_M0_SEL_EM_STOP_SRC         = ( 0x05, 0x00000020,  5 )
        M1_FSR                                 = ( 0x05, 0x000000C0,  6 )
        M1_FSR_IREF                         = ( 0x05, 0x00000300,  8 )
        DRV_CONF_M1_EN_EMERGENCY_DISABLE    = ( 0x05, 0x00000400, 10 )
        DRV_CONF_M1_SEL_EM_STOP_SRC         = ( 0x05, 0x00000800, 11 )
        DRV_CONF_M0_STANDSTILL_TIME         = ( 0x05, 0x00070000, 16 )
        DRV_CONF_M1_STANDSTILL_TIME         = ( 0x05, 0x00700000, 20 )
        GLOBAL_SCALER_GLOBALSCALER_M0_A     = ( 0x06, 0x000000FF,  0 )
        GLOBAL_SCALER_GLOBALSCALER_M0_B     = ( 0x06, 0x0000FF00,  8 )
        GLOBAL_SCALER_GLOBALSCALER_M1_A     = ( 0x06, 0x00FF0000, 16 )
        GLOBAL_SCALER_GLOBALSCALER_M1_B     = ( 0x06, 0xFF000000, 24 )
        RAMPMODE_M0_RAMPMODE                = ( 0x07, 0x00000003,  0 )
        RAMPMODE_M1_RAMPMODE                = ( 0x07, 0x0000000C,  2 )
        RAMPMODE_RAMP0_HOLD                 = ( 0x07, 0x00000100,  8 )
        RAMPMODE_RAMP1_HOLD                 = ( 0x07, 0x00000200,  9 )
        MSLUT_ADDR                          = ( 0x08, 0x0000001F,  0 )
        MSLUT_SEL_START_MSLUT_DATA          = ( 0x09, 0xFFFFFFFF,  0 )
        M0_X_COMPARE                        = ( 0x10, 0xFFFFFFFF,  0 )
        M0_X_COMPARE_REPEAT                 = ( 0x11, 0x00FFFFFF,  0 )
        M0_IHOLD_IRUN_IHOLD                 = ( 0x12, 0x0000001F,  0 )
        M0_IHOLD_IRUN_IRUN                  = ( 0x12, 0x00001F00,  8 )
        IHOLDDELAY                          = ( 0x12, 0x000F0000, 16 )
        IRUNDELAY                           = ( 0x12, 0x0F000000, 24 )
        TPOWERDOWN                          = ( 0x13, 0x000000FF,  0 )
        TSTEP                               = ( 0x14, 0x000FFFFF,  0 )
        TPWMTHRS                            = ( 0x15, 0x000FFFFF,  0 )
        TCOOLTHRS                           = ( 0x16, 0x000FFFFF,  0 )
        THIGH                               = ( 0x17, 0x000FFFFF,  0 )
        M0_XACTUAL                          = ( 0x18, 0xFFFFFFFF,  0 )
        VACTUAL                             = ( 0x19, 0x00FFFFFF,  0 )
        M0_AACTUAL                          = ( 0x1A, 0x00FFFFFF,  0 )
        M0_VSTART                           = ( 0x1B, 0x0003FFFF,  0 )
        M0_A1                               = ( 0x1C, 0x0003FFFF,  0 )
        M0_V1                               = ( 0x1D, 0x000FFFFF,  0 )
        M0_A2                               = ( 0x1E, 0x0003FFFF,  0 )
        M0_V2                               = ( 0x1F, 0x000FFFFF,  0 )
        M0_AMAX                             = ( 0x20, 0x0003FFFF,  0 )
        M0_VMAX                             = ( 0x21, 0x007FFFFF,  0 )
        M0_DMAX                             = ( 0x22, 0x0003FFFF,  0 )
        M0_D2                               = ( 0x23, 0x0003FFFF,  0 )
        M0_D1                               = ( 0x24, 0x0003FFFF,  0 )
        M0_VSTOP                            = ( 0x25, 0x0003FFFF,  0 )
        M0_TVMAX                            = ( 0x26, 0x0000FFFF,  0 )
        M0_TZEROWAIT                        = ( 0x27, 0x0000FFFF,  0 )
        M0_XTARGET                          = ( 0x28, 0xFFFFFFFF,  0 )
        M1_VDCMIN_VDCMIN                    = ( 0x29, 0x007FFFFF,  0 )
        M0_SW_MODE_STOP_L_ENABLE            = ( 0x2A, 0x00000001,  0 )
        M0_SW_MODE_STOP_R_ENABLE            = ( 0x2A, 0x00000002,  1 )
        M0_SW_MODE_POL_STOP_L               = ( 0x2A, 0x00000004,  2 )
        M0_SW_MODE_POL_STOP_R               = ( 0x2A, 0x00000008,  3 )
        M0_SW_MODE_SWAP_LR                  = ( 0x2A, 0x00000010,  4 )
        M0_SW_MODE_LATCH_L_ACTIVE           = ( 0x2A, 0x00000020,  5 )
        M0_SW_MODE_LATCH_L_INACTIVE         = ( 0x2A, 0x00000040,  6 )
        M0_SW_MODE_LATCH_R_ACTIVE           = ( 0x2A, 0x00000080,  7 )
        M0_SW_MODE_LATCH_R_INACTIVE         = ( 0x2A, 0x00000100,  8 )
        M0_SW_MODE_EN_LATCH_ENCODER         = ( 0x2A, 0x00000200,  9 )
        SG_STOP                             = ( 0x2A, 0x00000400, 10 )
        M0_SW_MODE_EN_SOFTSTOP              = ( 0x2A, 0x00000800, 11 )
        M0_SW_MODE_EN_VIRTUAL_STOP_L        = ( 0x2A, 0x00001000, 12 )
        M0_SW_MODE_EN_VIRTUAL_STOP_R        = ( 0x2A, 0x00002000, 13 )
        M0_SW_MODE_VIRTUAL_STEP_ENC         = ( 0x2A, 0x00004000, 14 )
        M0_RAMP_STAT_STATUS_STOP_L          = ( 0x2B, 0x00000001,  0 )
        M0_RAMP_STAT_STATUS_STOP_R          = ( 0x2B, 0x00000002,  1 )
        M0_RAMP_STAT_STATUS_LATCH_L         = ( 0x2B, 0x00000004,  2 )
        M0_RAMP_STAT_STATUS_LATCH_R         = ( 0x2B, 0x00000008,  3 )
        M0_RAMP_STAT_EVENT_STOP_L           = ( 0x2B, 0x00000010,  4 )
        M0_RAMP_STAT_EVENT_STOP_R           = ( 0x2B, 0x00000020,  5 )
        M0_RAMP_STAT_EVENT_STOP_SG          = ( 0x2B, 0x00000040,  6 )
        M0_RAMP_STAT_EVENT_POS_REACHED      = ( 0x2B, 0x00000080,  7 )
        M0_RAMP_STAT_VELOCITY_REACHED       = ( 0x2B, 0x00000100,  8 )
        M0_RAMP_STAT_POSITION_REACHED       = ( 0x2B, 0x00000200,  9 )
        M0_RAMP_STAT_VZERO                  = ( 0x2B, 0x00000400, 10 )
        M0_RAMP_STAT_T_ZEROWAIT_ACTIVE      = ( 0x2B, 0x00000800, 11 )
        M0_RAMP_STAT_SECOND_MOVE            = ( 0x2B, 0x00001000, 12 )
        M0_RAMP_STAT_STATUS_SG              = ( 0x2B, 0x00002000, 13 )
        M0_RAMP_STAT_STATUS_VIRTUAL_STOP_L  = ( 0x2B, 0x00004000, 14 )
        M0_RAMP_STAT_STATUS_VIRTUAL_STOP_R  = ( 0x2B, 0x00008000, 15 )
        M0_XLATCH                           = ( 0x2C, 0xFFFFFFFF,  0 )
        P_POSITION                          = ( 0x2D, 0x000003FF,  0 )
        TOLERANCE                           = ( 0x2D, 0x00FF0000, 16 )
        TOL_ON_POS_REACHED                  = ( 0x2D, 0x10000000, 28 )
        M0_X_ENC                            = ( 0x2E, 0xFFFFFFFF,  0 )
        M0_ENCMODE_POL_A                    = ( 0x2F, 0x00000001,  0 )
        M0_ENCMODE_POL_B                    = ( 0x2F, 0x00000002,  1 )
        M0_ENCMODE_POL_N                    = ( 0x2F, 0x00000004,  2 )
        M0_ENCMODE_IGNORE_AB                = ( 0x2F, 0x00000008,  3 )
        M0_ENCMODE_CLR_CONT                 = ( 0x2F, 0x00000010,  4 )
        M0_ENCMODE_CLR_ONCE                 = ( 0x2F, 0x00000020,  5 )
        M0_ENCMODE_POS_NEG_EDGE             = ( 0x2F, 0x000000C0,  6 )
        M0_ENCMODE_CLR_ENC_X                = ( 0x2F, 0x00000100,  8 )
        M0_ENCMODE_LATCH_X_ACT              = ( 0x2F, 0x00000200,  9 )
        M0_ENCMODE_ENC_SEL_DECIMAL          = ( 0x2F, 0x00000400, 10 )
        M0_ENCMODE_NBEMF_ABN_SEL            = ( 0x2F, 0x00000800, 11 )
        BEMF_HYST                           = ( 0x2F, 0x00007000, 12 )
        M0_ENCMODE_BEMF_BLANK_TIME          = ( 0x2F, 0x00FF0000, 16 )
        BEMF_FILTER_SEL                     = ( 0x2F, 0x30000000, 28 )
        M0_ENC_CONST                        = ( 0x30, 0xFFFFFFFF,  0 )
        M0_ENC_STATUS_N_EVENT               = ( 0x31, 0x00000001,  0 )
        M0_ENC_STATUS_DEVIATION_WARN        = ( 0x31, 0x00000002,  1 )
        M0_ENC_LATCH                        = ( 0x32, 0xFFFFFFFF,  0 )
        M0_ENC_DEVIATION                    = ( 0x33, 0x000FFFFF,  0 )
        M0_VIRTUAL_STOP_L                   = ( 0x34, 0xFFFFFFFF,  0 )
        M0_VIRTUAL_STOP_R                   = ( 0x35, 0xFFFFFFFF,  0 )
        M0_MSCNT                            = ( 0x36, 0x000003FF,  0 )
        M0_MSCURACT_CUR_A                   = ( 0x37, 0x000001FF,  0 )
        M0_MSCURACT_CUR_B                   = ( 0x37, 0x01FF0000, 16 )
        CHOPCONF_TOFF                       = ( 0x38, 0x0000000F,  0 )
        M0_CHOPCONF_HSTRT_TFD210            = ( 0x38, 0x00000070,  4 )
        CHOPCONF_HEND_OFFSET                = ( 0x38, 0x00000780,  7 )
        M0_CHOPCONF_FD3                     = ( 0x38, 0x00000800, 11 )
        M0_CHOPCONF_DISFDCC                 = ( 0x38, 0x00001000, 12 )
        CHOPCONF_CHM                        = ( 0x38, 0x00004000, 14 )
        CHOPCONF_TBL                        = ( 0x38, 0x00018000, 15 )
        CHOPCONF_VHIGHFS                    = ( 0x38, 0x00040000, 18 )
        CHOPCONF_VHIGHCHM                   = ( 0x38, 0x00080000, 19 )
        M0_CHOPCONF_TPFD                    = ( 0x38, 0x00F00000, 20 )
        M0_CHOPCONF_MRES                    = ( 0x38, 0x0F000000, 24 )
        M0_CHOPCONF_INTPOL                  = ( 0x38, 0x10000000, 28 )
        M0_CHOPCONF_DEDGE                   = ( 0x38, 0x20000000, 29 )
        M0_CHOPCONF_DISS2G                  = ( 0x38, 0x40000000, 30 )
        M0_CHOPCONF_DISS2VS                 = ( 0x38, 0x80000000, 31 )
        SEMIN                               = ( 0x39, 0x0000000F,  0 )
        SEUP                                = ( 0x39, 0x00000060,  5 )
        SEMAX                               = ( 0x39, 0x00000F00,  8 )
        SEDN                                = ( 0x39, 0x00006000, 13 )
        SEIMIN                              = ( 0x39, 0x00008000, 15 )
        SGT                                 = ( 0x39, 0x007F0000, 16 )
        SFILT                               = ( 0x39, 0x01000000, 24 )
        M0_DCCTRL_DC_TIME                   = ( 0x3A, 0x000003FF,  0 )
        M0_DCCTRL_DC_SG                     = ( 0x3A, 0x00FF0000, 16 )
        M0_DRV_STATUS_SG_RESULT             = ( 0x3B, 0x000003FF,  0 )
        M0_DRV_STATUS_S2VSA                 = ( 0x3B, 0x00001000, 12 )
        M0_DRV_STATUS_S2VSB                 = ( 0x3B, 0x00002000, 13 )
        STEALTH                             = ( 0x3B, 0x00004000, 14 )
        M0_DRV_STATUS_FSACTIVE              = ( 0x3B, 0x00008000, 15 )
        M0_DRV_STATUS_CS_ACTUAL             = ( 0x3B, 0x001F0000, 16 )
        M0_DRV_STATUS_STALLGUARD            = ( 0x3B, 0x01000000, 24 )
        M0_DRV_STATUS_OT                    = ( 0x3B, 0x02000000, 25 )
        M0_DRV_STATUS_OTPW                  = ( 0x3B, 0x04000000, 26 )
        M0_DRV_STATUS_S2GA                  = ( 0x3B, 0x08000000, 27 )
        M0_DRV_STATUS_S2GB                  = ( 0x3B, 0x10000000, 28 )
        M0_DRV_STATUS_OLA                   = ( 0x3B, 0x20000000, 29 )
        M0_DRV_STATUS_OLB                   = ( 0x3B, 0x40000000, 30 )
        M0_DRV_STATUS_STST                  = ( 0x3B, 0x80000000, 31 )
        PWMCONF_PWM_OFS                     = ( 0x3C, 0x000000FF,  0 )
        PWM_GRAD                            = ( 0x3C, 0x0000FF00,  8 )
        PWMCONF_PWM_FREQ                    = ( 0x3C, 0x00030000, 16 )
        PWMCONF_PWM_AUTOSCALE               = ( 0x3C, 0x00040000, 18 )
        M0_PWMCONF_PWM_AUTOGRAD             = ( 0x3C, 0x00080000, 19 )
        FREEWHEEL                           = ( 0x3C, 0x00300000, 20 )
        M0_PWMCONF_PWM_MEAS_SD_ENABLE       = ( 0x3C, 0x00400000, 22 )
        PWMCONF_PWM_DIS_REG_STST            = ( 0x3C, 0x00800000, 23 )
        M0_PWMCONF_PWM_REG                  = ( 0x3C, 0x0F000000, 24 )
        M0_PWMCONF_PWM_LIM                  = ( 0x3C, 0xF0000000, 28 )
        M0_PWM_SCALE_PWM_SCALE_SUM          = ( 0x3D, 0x000003FF,  0 )
        M0_PWM_SCALE_PWM_SCALE_AUTO         = ( 0x3D, 0x01FF0000, 16 )
        M0_PWM_AUTO_PWM_OFS_AUTO            = ( 0x3E, 0x000000FF,  0 )
        M0_PWM_AUTO_PWM_GRAD_AUTO           = ( 0x3E, 0x00FF0000, 16 )
        SG4_THRS                            = ( 0x3F, 0x000000FF,  0 )
        FILT_EN                             = ( 0x3F, 0x00000100,  8 )
        SG_ANGLE_OFFSET                     = ( 0x3F, 0x00000200,  9 )
        M0_SG4_RESULT_SG_RESULT             = ( 0x40, 0x000003FF,  0 )
        M0_SG4_IND_SG4_IND_0                = ( 0x41, 0x000000FF,  0 )
        M0_SG4_IND_SG4_IND_1                = ( 0x41, 0x0000FF00,  8 )
        M0_SG4_IND_SG4_IND_2                = ( 0x41, 0x00FF0000, 16 )
        M0_SG4_IND_SG4_IND_3                = ( 0x41, 0xFF000000, 24 )
        M1_X_COMPARE                        = ( 0x45, 0xFFFFFFFF,  0 )
        M1_X_COMPARE_REPEAT                 = ( 0x46, 0x00FFFFFF,  0 )
        M1_IHOLD_IRUN_IHOLD                 = ( 0x47, 0x0000001F,  0 )
        M1_IHOLD_IRUN_IRUN                  = ( 0x47, 0x00001F00,  8 )
        #IHOLDDELAY                          = ( 0x47, 0x000F0000, 16 )
        #IRUNDELAY                           = ( 0x47, 0x0F000000, 24 )
        #TPOWERDOWN                          = ( 0x48, 0x000000FF,  0 )
        #TSTEP                               = ( 0x49, 0x000FFFFF,  0 )
        #TPWMTHRS                            = ( 0x4A, 0x000FFFFF,  0 )
        #TCOOLTHRS                           = ( 0x4B, 0x000FFFFF,  0 )
        #THIGH                               = ( 0x4C, 0x000FFFFF,  0 )
        M1_XACTUAL                          = ( 0x4D, 0xFFFFFFFF,  0 )
        #VACTUAL                             = ( 0x4E, 0x00FFFFFF,  0 )
        M1_AACTUAL                          = ( 0x4F, 0x00FFFFFF,  0 )
        M1_VSTART                           = ( 0x50, 0x0003FFFF,  0 )
        M1_A1                               = ( 0x51, 0x0003FFFF,  0 )
        M1_V1                               = ( 0x52, 0x000FFFFF,  0 )
        M1_A2                               = ( 0x53, 0x0003FFFF,  0 )
        M1_V2                               = ( 0x54, 0x000FFFFF,  0 )
        M1_AMAX                             = ( 0x55, 0x0003FFFF,  0 )
        M1_VMAX                             = ( 0x56, 0x007FFFFF,  0 )
        M1_DMAX                             = ( 0x57, 0x0003FFFF,  0 )
        M1_D2                               = ( 0x58, 0x0003FFFF,  0 )
        M1_D1                               = ( 0x59, 0x0003FFFF,  0 )
        M1_VSTOP                            = ( 0x5A, 0x0003FFFF,  0 )
        M1_TVMAX                            = ( 0x5B, 0x0000FFFF,  0 )
        M1_TZEROWAIT                        = ( 0x5C, 0x0000FFFF,  0 )
        M1_XTARGET                          = ( 0x5D, 0xFFFFFFFF,  0 )
        #M1_VDCMIN_VDCMIN                    = ( 0x5E, 0x007FFFFF,  0 )
        M1_SW_MODE_STOP_L_ENABLE            = ( 0x5F, 0x00000001,  0 )
        M1_SW_MODE_STOP_R_ENABLE            = ( 0x5F, 0x00000002,  1 )
        M1_SW_MODE_POL_STOP_L               = ( 0x5F, 0x00000004,  2 )
        M1_SW_MODE_POL_STOP_R               = ( 0x5F, 0x00000008,  3 )
        M1_SW_MODE_SWAP_LR                  = ( 0x5F, 0x00000010,  4 )
        M1_SW_MODE_LATCH_L_ACTIVE           = ( 0x5F, 0x00000020,  5 )
        M1_SW_MODE_LATCH_L_INACTIVE         = ( 0x5F, 0x00000040,  6 )
        M1_SW_MODE_LATCH_R_ACTIVE           = ( 0x5F, 0x00000080,  7 )
        M1_SW_MODE_LATCH_R_INACTIVE         = ( 0x5F, 0x00000100,  8 )
        M1_SW_MODE_EN_LATCH_ENCODER         = ( 0x5F, 0x00000200,  9 )
        #SG_STOP                             = ( 0x5F, 0x00000400, 10 )
        M1_SW_MODE_EN_SOFTSTOP              = ( 0x5F, 0x00000800, 11 )
        M1_SW_MODE_EN_VIRTUAL_STOP_L        = ( 0x5F, 0x00001000, 12 )
        M1_SW_MODE_EN_VIRTUAL_STOP_R        = ( 0x5F, 0x00002000, 13 )
        M1_SW_MODE_VIRTUAL_STEP_ENC         = ( 0x5F, 0x00004000, 14 )
        M1_RAMP_STAT_STATUS_STOP_L          = ( 0x60, 0x00000001,  0 )
        M1_RAMP_STAT_STATUS_STOP_R          = ( 0x60, 0x00000002,  1 )
        M1_RAMP_STAT_STATUS_LATCH_L         = ( 0x60, 0x00000004,  2 )
        M1_RAMP_STAT_STATUS_LATCH_R         = ( 0x60, 0x00000008,  3 )
        M1_RAMP_STAT_EVENT_STOP_L           = ( 0x60, 0x00000010,  4 )
        M1_RAMP_STAT_EVENT_STOP_R           = ( 0x60, 0x00000020,  5 )
        M1_RAMP_STAT_EVENT_STOP_SG          = ( 0x60, 0x00000040,  6 )
        M1_RAMP_STAT_EVENT_POS_REACHED      = ( 0x60, 0x00000080,  7 )
        M1_RAMP_STAT_VELOCITY_REACHED       = ( 0x60, 0x00000100,  8 )
        M1_RAMP_STAT_POSITION_REACHED       = ( 0x60, 0x00000200,  9 )
        M1_RAMP_STAT_VZERO                  = ( 0x60, 0x00000400, 10 )
        M1_RAMP_STAT_T_ZEROWAIT_ACTIVE      = ( 0x60, 0x00000800, 11 )
        M1_RAMP_STAT_SECOND_MOVE            = ( 0x60, 0x00001000, 12 )
        M1_RAMP_STAT_STATUS_SG              = ( 0x60, 0x00002000, 13 )
        M1_RAMP_STAT_STATUS_VIRTUAL_STOP_L  = ( 0x60, 0x00004000, 14 )
        M1_RAMP_STAT_STATUS_VIRTUAL_STOP_R  = ( 0x60, 0x00008000, 15 )
        M1_XLATCH                           = ( 0x61, 0xFFFFFFFF,  0 )
        #P_POSITION                          = ( 0x62, 0x000003FF,  0 )
        #TOLERANCE                           = ( 0x62, 0x00FF0000, 16 )
        #TOL_ON_POS_REACHED                  = ( 0x62, 0x10000000, 28 )
        M1_X_ENC                            = ( 0x63, 0xFFFFFFFF,  0 )
        M1_ENCMODE_POL_A                    = ( 0x64, 0x00000001,  0 )
        M1_ENCMODE_POL_B                    = ( 0x64, 0x00000002,  1 )
        M1_ENCMODE_POL_N                    = ( 0x64, 0x00000004,  2 )
        M1_ENCMODE_IGNORE_AB                = ( 0x64, 0x00000008,  3 )
        M1_ENCMODE_CLR_CONT                 = ( 0x64, 0x00000010,  4 )
        M1_ENCMODE_CLR_ONCE                 = ( 0x64, 0x00000020,  5 )
        M1_ENCMODE_POS_NEG_EDGE             = ( 0x64, 0x000000C0,  6 )
        M1_ENCMODE_CLR_ENC_X                = ( 0x64, 0x00000100,  8 )
        M1_ENCMODE_LATCH_X_ACT              = ( 0x64, 0x00000200,  9 )
        M1_ENCMODE_ENC_SEL_DECIMAL          = ( 0x64, 0x00000400, 10 )
        M1_ENCMODE_NBEMF_ABN_SEL            = ( 0x64, 0x00000800, 11 )
        #BEMF_HYST                           = ( 0x64, 0x00007000, 12 )
        M1_ENCMODE_BEMF_BLANK_TIME          = ( 0x64, 0x00FF0000, 16 )
        #BEMF_FILTER_SEL                     = ( 0x64, 0x30000000, 28 )
        M1_ENC_CONST                        = ( 0x65, 0xFFFFFFFF,  0 )
        M1_ENC_STATUS_N_EVENT               = ( 0x66, 0x00000001,  0 )
        M1_ENC_STATUS_DEVIATION_WARN        = ( 0x66, 0x00000002,  1 )
        M1_ENC_LATCH                        = ( 0x67, 0xFFFFFFFF,  0 )
        M1_ENC_DEVIATION                    = ( 0x68, 0x000FFFFF,  0 )
        M1_VIRTUAL_STOP_L                   = ( 0x69, 0xFFFFFFFF,  0 )
        M1_VIRTUAL_STOP_R                   = ( 0x6A, 0xFFFFFFFF,  0 )
        M1_MSCNT                            = ( 0x6B, 0x000003FF,  0 )
        M1_MSCURACT_CUR_A                   = ( 0x6C, 0x000001FF,  0 )
        M1_MSCURACT_CUR_B                   = ( 0x6C, 0x01FF0000, 16 )
        #CHOPCONF_TOFF                       = ( 0x6D, 0x0000000F,  0 )
        M1_CHOPCONF_HSTRT_TFD210            = ( 0x6D, 0x00000070,  4 )
        #CHOPCONF_HEND_OFFSET                = ( 0x6D, 0x00000780,  7 )
        M1_CHOPCONF_FD3                     = ( 0x6D, 0x00000800, 11 )
        M1_CHOPCONF_DISFDCC                 = ( 0x6D, 0x00001000, 12 )
        #CHOPCONF_CHM                        = ( 0x6D, 0x00004000, 14 )
        #CHOPCONF_TBL                        = ( 0x6D, 0x00018000, 15 )
        #CHOPCONF_VHIGHFS                    = ( 0x6D, 0x00040000, 18 )
        #CHOPCONF_VHIGHCHM                   = ( 0x6D, 0x00080000, 19 )
        M1_CHOPCONF_TPFD                    = ( 0x6D, 0x00F00000, 20 )
        M1_CHOPCONF_MRES                    = ( 0x6D, 0x0F000000, 24 )
        M1_CHOPCONF_INTPOL                  = ( 0x6D, 0x10000000, 28 )
        M1_CHOPCONF_DEDGE                   = ( 0x6D, 0x20000000, 29 )
        M1_CHOPCONF_DISS2G                  = ( 0x6D, 0x40000000, 30 )
        M1_CHOPCONF_DISS2VS                 = ( 0x6D, 0x80000000, 31 )
        #SEMIN                               = ( 0x6E, 0x0000000F,  0 )
        #SEUP                                = ( 0x6E, 0x00000060,  5 )
        #SEMAX                               = ( 0x6E, 0x00000F00,  8 )
        #SEDN                                = ( 0x6E, 0x00006000, 13 )
        #SEIMIN                              = ( 0x6E, 0x00008000, 15 )
        #SGT                                 = ( 0x6E, 0x007F0000, 16 )
        #SFILT                               = ( 0x6E, 0x01000000, 24 )
        M1_DCCTRL_DC_TIME                   = ( 0x6F, 0x000003FF,  0 )
        M1_DCCTRL_DC_SG                     = ( 0x6F, 0x00FF0000, 16 )
        M1_DRV_STATUS_SG_RESULT             = ( 0x70, 0x000003FF,  0 )
        M1_DRV_STATUS_S2VSA                 = ( 0x70, 0x00001000, 12 )
        M1_DRV_STATUS_S2VSB                 = ( 0x70, 0x00002000, 13 )
        #STEALTH                             = ( 0x70, 0x00004000, 14 )
        M1_DRV_STATUS_FSACTIVE              = ( 0x70, 0x00008000, 15 )
        M1_DRV_STATUS_CS_ACTUAL             = ( 0x70, 0x001F0000, 16 )
        M1_DRV_STATUS_STALLGUARD            = ( 0x70, 0x01000000, 24 )
        M1_DRV_STATUS_OT                    = ( 0x70, 0x02000000, 25 )
        M1_DRV_STATUS_OTPW                  = ( 0x70, 0x04000000, 26 )
        M1_DRV_STATUS_S2GA                  = ( 0x70, 0x08000000, 27 )
        M1_DRV_STATUS_S2GB                  = ( 0x70, 0x10000000, 28 )
        M1_DRV_STATUS_OLA                   = ( 0x70, 0x20000000, 29 )
        M1_DRV_STATUS_OLB                   = ( 0x70, 0x40000000, 30 )
        M1_DRV_STATUS_STST                  = ( 0x70, 0x80000000, 31 )
        #PWMCONF_PWM_OFS                     = ( 0x71, 0x000000FF,  0 )
        #PWM_GRAD                            = ( 0x71, 0x0000FF00,  8 )
        #PWMCONF_PWM_FREQ                    = ( 0x71, 0x00030000, 16 )
        #PWMCONF_PWM_AUTOSCALE               = ( 0x71, 0x00040000, 18 )
        M1_PWMCONF_PWM_AUTOGRAD             = ( 0x71, 0x00080000, 19 )
        #FREEWHEEL                           = ( 0x71, 0x00300000, 20 )
        M1_PWMCONF_PWM_MEAS_SD_ENABLE       = ( 0x71, 0x00400000, 22 )
        M1_PWMCONF_PWM_DIS_REG_STST         = ( 0x71, 0x00800000, 23 )
        M1_PWMCONF_PWM_REG                  = ( 0x71, 0x0F000000, 24 )
        M1_PWMCONF_PWM_LIM                  = ( 0x71, 0xF0000000, 28 )
        M1_PWM_SCALE_PWM_SCALE_SUM          = ( 0x72, 0x000003FF,  0 )
        M1_PWM_SCALE_PWM_SCALE_AUTO         = ( 0x72, 0x01FF0000, 16 )
        M1_PWM_AUTO_PWM_OFS_AUTO            = ( 0x73, 0x000000FF,  0 )
        M1_PWM_AUTO_PWM_GRAD_AUTO           = ( 0x73, 0x00FF0000, 16 )
        #SG4_THRS                            = ( 0x74, 0x000000FF,  0 )
        #FILT_EN                             = ( 0x74, 0x00000100,  8 )
        #SG_ANGLE_OFFSET                     = ( 0x74, 0x00000200,  9 )
        M1_SG4_RESULT_SG_RESULT             = ( 0x75, 0x000003FF,  0 )
        M1_SG4_IND_SG4_IND_0                = ( 0x76, 0x000000FF,  0 )
        M1_SG4_IND_SG4_IND_1                = ( 0x76, 0x0000FF00,  8 )
        M1_SG4_IND_SG4_IND_2                = ( 0x76, 0x00FF0000, 16 )
        M1_SG4_IND_SG4_IND_3                = ( 0x76, 0xFF000000, 24 )