#include        <math.h>
 
#include        <stdio.h>
 
#include        <string.h>
 
#include        <fcntl.h>      /* open */
 
#include        <unistd.h>     /* exit */
 
#include        <sys/ioctl.h>  /* ioctl */
 
#include        "libusmc.h"
 
#include        "usmctypes.h"
 
 
 
 
 
#define         USB_ERROR(errCode)              (errCode|0x00000000L)
 
// Linux kernel errors or'ed with this value
 
// to distinguish them from usb errors.
 
#define         LINKRN_ERROR(errCode)   (errCode|0x10000000L)
 
#define         HIBYTE(w)                       ((w&0xff00)>>8)
 
#define         LOBYTE(w)                       (w&0x00ff)
 
#define         HIWORD(dw)                      ((dw&0xffff0000)>>16)
 
#define         LOWORD(dw)                      (dw&0x0000ffff)
 
#define         PACK_WORD(w)                    (HIBYTE(w)|(LOBYTE(w)<<8))
 
//#define               PACK_WORD(w)                    (LOBYTE(w)|(HIBYTE(w)<<8))
 
#define         PACK_DWORD(w)                   (HIBYTE(HIWORD(w))| \
 
                                                                         (LOBYTE(HIWORD(w))<<8)| \
 
                                                                         (HIBYTE(LOWORD(w))<<16)| \
 
                                                                         (LOBYTE(LOWORD(w))<<24))
 
 
 
 
 
// DLL data:
 
BOOL                 g_IsInitialized = FALSE;
 
USMC_Devices         g_devices;
 
USMC_Mode            g_deviceMode            [32];
 
USMC_Parameters      g_deviceParameters      [32];
 
USMC_StartParameters g_deviceStartParameters [32];
 
DWORD                g_devicesVersions [32];
 
char                 g_lastErrDesc     [256];   // Null-terminated ASCII error description string.
 
 
 
 
 
// Error string descriptions:
 
static char * errDesc [] = {
 
        "0x???????? ( Unknown )",
 
        "0x00000000 ( Success )",
 
/*      "0x00000001 ( USB CRC )",
 
        "0x00000002 ( USB Bit stuffing )",
 
        "0x00000003 ( USB Data toggle mismatch )",
 
 
 
        "0x00000004 ( USB Stall )",
 
        "0x00000005 ( USB Device not responding )",
 
        "0x00000006 ( USB PID check failure )",
 
        "0x00000007 ( USB Unexpected PID )",
 
        "0x00000008 ( USB Data overrun )",
 
 
 
        "0x00000009 ( USB Data underrun )",
 
        "0x0000000C ( USB Buffer overrun )",
 
        "0x0000000D ( USB Buffer underrun )",
 
        "0x0000000E ( USB Not accessed )",
 
        "0x0000000F ( USB Not accessed alt )",
 
 
 
        "0x00000100 ( USB Isochronous )",
 
        "0x00000101 ( USB Canceled )",
 
        "0x00000103 ( USB Not complete )",
 
        "0x00000104 ( USB Client buffer )",*/
 
        "0x14141414 ( USMC Not initialized )",
 
        //"0x00000006 ( USMC Reffered Device not connected )",
 
        //"0x00000012 ( DeviceManager error - driver function called with invalid arguments )",
 
        "0x14141415 ( USMC No devices connected )"
 
};
 
 
 
 
 
// Internal-use functions prototypes:
 
DWORD  SetLastErr  ( const char * str, DWORD dwErrCode );
 
char * ErrCode2Str ( DWORD dwErrCode );
 
int    clamp       ( int val, int min, int max );
 
float  clampf      ( float val, float min, float max );
 
DWORD  IOCTRL       ( DWORD Device, 
 
                                         DWORD dwCode, 
 
                                         PVOID pInBuf, 
 
                                         DWORD dwInBufSize,
 
                                         PVOID pOutBuf,
 
                                         DWORD dwOutBufSize );
 
 
 
 
 
 
 
 
 
//      Function: SetLastErr ()
 
//      Argument list:
 
//              const char * str √ in √ Null-terminated ASCII error description.
 
//      DWORD dwErrCode - in - optional - error code supplied with description.
 
//      Return value:
 
//              DWORD - modified error code.
 
//      Remarks:
 
//              The SetLastErr () sets description of last occured error.
 
DWORD SetLastErr ( const char * str, DWORD dwErrCode )
 
{
 
        if ( dwErrCode == -USMC_ERROR_REF_DEV_DISCONNECTED )
 
                sprintf ( ( char * ) g_lastErrDesc
, "Error: %s. Code: %s", str
, "Reffered device disconnected" );  
        else if ( dwErrCode != 1 )
 
                sprintf ( ( char * ) g_lastErrDesc
, "Error: %s. Code: %d", str
, ( signed int ) dwErrCode 
);  
 
 
        //if ( dwErrCode != 1 )
 
        //      sprintf ( ( char * ) g_lastErrDesc, "Error: %s. Code: %s", str, ErrCode2Str ( dwErrCode ) );
 
        //else
 
        //      sprintf ( ( char * ) g_lastErrDesc, "Error: %s.", str );
 
 
 
 
 
        return  dwErrCode;
 
}
 
 
 
 
 
 
 
 
 
//      Function: ErrCode2Str ()
 
//      Argument list:
 
//              DWORD dwErrCode √ in √ error code returned by any operation.
 
//      Return value:
 
//      char * - string equivalent for specified numerical error code.
 
//      Remarks:
 
//      There is no need to free error string obtained with this function:
 
//      return value points to static dll variable.
 
char * ErrCode2Str ( DWORD dwErrCode )
 
{
 
        switch ( dwErrCode )
 
        {
 
/*      case USB_NO_ERROR:
 
                return  errDesc [1]; break;
 
        case USB_CRC_ERROR:
 
                return  errDesc [2]; break;
 
        case USB_BIT_STUFFING_ERROR:
 
                return  errDesc [3]; break;
 
        case USB_DATA_TOGGLE_MISMATCH_ERROR:
 
                return  errDesc [4]; break;
 
        case USB_STALL_ERROR:
 
                return  errDesc [5]; break;
 
        case USB_DEVICE_NOT_RESPONDING_ERROR:
 
                return  errDesc [6]; break;
 
        case USB_PID_CHECK_FAILURE_ERROR:
 
                return  errDesc [7]; break;
 
        case USB_UNEXPECTED_PID_ERROR:
 
                return  errDesc [8]; break;
 
        case USB_DATA_OVERRUN_ERROR:
 
                return  errDesc [9]; break;
 
        case USB_DATA_UNDERRUN_ERROR:
 
                return  errDesc [10]; break;
 
        case USB_BUFFER_OVERRUN_ERROR:
 
                return  errDesc [11]; break;
 
        case USB_BUFFER_UNDERRUN_ERROR:
 
                return  errDesc [12]; break;
 
        case USB_NOT_ACCESSED_ERROR:
 
                return  errDesc [13]; break;
 
        case USB_NOT_ACCESSED_ALT:
 
                return  errDesc [14]; break;
 
        case USB_ISOCH_ERROR:
 
                return  errDesc [15]; break;
 
        case USB_CANCELED_ERROR:
 
                return  errDesc [16]; break;
 
        case USB_NOT_COMPLETE_ERROR:
 
                return  errDesc [17]; break;
 
        case USB_CLIENT_BUFFER_ERROR:
 
                return  errDesc [18]; break;
 
        case USMC_ERROR_NOT_INITIALIZED:
 
                return  errDesc [19]; break;
 
        case USMC_ERROR_REF_DEV_DISCONNECTED:
 
                return  errDesc [20]; break;
 
        case LINKRN_ERROR ( ERROR_BAD_ARGUMENTS ):
 
                return  errDesc [21]; break;
 
        case USMC_ERROR_NO_DEVICES_CONNECTED:
 
                return  errDesc [22]; break;*/
 
        default:
 
                return  errDesc [0]; break;
 
        }
 
}
 
 
 
 
 
 
 
 
 
int clamp ( int val, int min, int max )
 
{
 
        return  val > max ? max : ( val < min ? min : val );
 
}
 
 
 
 
 
 
 
 
 
float clampf ( float val, float min, float max )
 
{
 
        return  val > max ? max : ( val < min ? min : val );
 
}
 
 
 
 
 
 
 
//      Function: InitDefaultValues ()
 
//              Initializes structures with default values.
 
//      Return Value:
 
//              The InitDefaultValues function has no return values.
 
void InitDefaultValues ()
 
{
 
        int i;
 
 
 
        for ( i = 0 ; i < 32 ; i++ )
 
        {
 
                memset ( &g_deviceMode 
[i
], 0, sizeof ( USMC_Mode 
) );  
                memset ( &g_deviceParameters 
[i
], 0, sizeof ( USMC_Parameters 
) );  
                memset ( &g_deviceStartParameters 
[i
], 0, sizeof ( USMC_StartParameters 
) );  
 
 
                // USMC_Mode defaults:
 
                g_deviceMode [i].PReg      = TRUE;
 
                g_deviceMode [i].Tr1En     = TRUE;
 
                g_deviceMode [i].Tr2En     = TRUE;
 
                g_deviceMode [i].RotTrOp   = TRUE;
 
                g_deviceMode [i].SyncOUTEn = TRUE;
 
                g_deviceMode [i].SyncINOp  = TRUE;
 
                g_deviceMode [i].SyncCount = 4;
 
 
 
                // USMC_Parameters defaults:
 
                g_deviceParameters [i].MaxTemp    = 70.0f;
 
                g_deviceParameters [i].AccelT     = 200.0f;
 
                g_deviceParameters [i].DecelT     = 200.0f;
 
                g_deviceParameters [i].BTimeout1  = 500.0f;
 
                g_deviceParameters [i].BTimeout2  = 500.0f;
 
                g_deviceParameters [i].BTimeout3  = 500.0f;
 
                g_deviceParameters [i].BTimeout4  = 500.0f;
 
                g_deviceParameters [i].BTO1P      = 200.0f;
 
                g_deviceParameters [i].BTO2P      = 300.0f;
 
                g_deviceParameters [i].BTO3P      = 400.0f;
 
                g_deviceParameters [i].BTO4P      = 500.0f;
 
                g_deviceParameters [i].MinP       = 500.0f;
 
                g_deviceParameters [i].BTimeoutR  = 500.0f;
 
                g_deviceParameters [i].LoftPeriod = 500.0f;
 
                g_deviceParameters [i].RTDelta    = 200;
 
                g_deviceParameters [i].RTMinError = 15;
 
                g_deviceParameters [i].EncMult    = 2.5f;
 
                g_deviceParameters [i].MaxLoft    = 32;
 
                g_deviceParameters [i].PTimeout   = 100.0f;
 
                g_deviceParameters [i].SynOUTP    = 1;
 
                g_deviceParameters [i].StartPos   = 0;
 
 
 
                // USMC_StartParameters defaults:
 
                g_deviceStartParameters [i].SDivisor = 8;
 
                g_deviceStartParameters [i].LoftEn   = TRUE;
 
                g_deviceStartParameters [i].SlStart  = TRUE;
 
        }
 
}
 
 
 
 
 
 
 
 
 
//      Function: IOCTRL ()
 
//              Encapsulates DeviceIoControl call ( internal use ).
 
//      Parameters:
 
//              [in]  Device: device number to call DeviceIoControl on.
 
//              [in]  dwCode: IO Control code for operation.
 
//              [out] pInBuf: buffer pointer to store returned data in.
 
//              [in]  dwInBufSize: size of in buffer.
 
//              [in]  pOutBuf: buffer pointer to send data from.
 
//              [in]  dwOutBufSize: size of out buffer.
 
//      Return Value:
 
//              DWORD; zero means succes, other value - error code.
 
//      Remarks:
 
//              Call this function with Device == -1 when devices wasn't enumerated yet.
 
//      The IOCTRL () function DOES NOT sets error description. This routine must 
 
//      be completed by caller function to specify most appropriate information: where
 
//      error has occured and with which operation it associated.
 
DWORD IOCTRL ( DWORD Device, 
 
                          DWORD dwCode, 
 
                          PVOID pInBuf, 
 
                          DWORD dwInBufSize,
 
                          PVOID pOutBuf,
 
                          DWORD dwOutBufSize )
 
{
 
        DWORD  deviceNumber;
 
        char   deviceName [128];        // Device name in form Prefix + DeviceNumber + ":\0".
 
        DWORD  dwErr;
 
        int    hFile;
 
        char * buf;
 
 
 
        dwErr = 0;
 
 
 
        deviceNumber = Device == -1 ? 0 : Device;
 
        sprintf ( deviceName
, "/dev/usmc%d", deviceNumber 
);  
 
 
        hFile = open ( deviceName, 0 );
 
 
 
        if ( hFile == -1 )
 
                return  -USMC_ERROR_REF_DEV_DISCONNECTED;
 
 
 
 
 
        if ( pInBuf && dwInBufSize ) {
 
                buf = pInBuf;
 
        } else if ( pOutBuf && dwOutBufSize ) {
 
                buf = pOutBuf;
 
        }
 
 
 
 
 
        dwErr = ioctl ( hFile,
 
                        dwCode, 
 
                        buf );
 
 
 
        close ( hFile );
 
 
 
        return  dwErr;
 
}
 
 
 
 
 
 
 
 
 
DWORD USMC_Init ( USMC_Devices * Str )
 
{
 
        int nod;
 
        DWORD i;
 
 
 
        nod = 0;
 
        Str -> NOD = 0;
 
        Str -> Serial = Str -> Version = NULL;
 
 
 
        if ( !g_IsInitialized )
 
        {
 
                //InitializeCriticalSection ( &g_Lock );
 
                g_IsInitialized = TRUE;
 
        }
 
 
 
        //EnterCriticalSection ( &g_Lock );
 
        DWORD dwRes = IOCTRL ( -1, 
 
                                                  IOCTL_GET_NOD, 
 
                                                  ( PVOID ) &nod, 
 
                                                  1, NULL, 0 );
 
 
 
        if ( ( int ) dwRes < 0 )
 
                return  USMC_SUCCESS;   // No devices connected, so return NOD = 0.
 
        else
 
                Str -> NOD = nod;
 
 
 
 
 
        // Enumerate connected devices:
 
        Str 
-> Serial  
= ( char ** ) malloc ( ( ssize_t 
) ( sizeof ( char * ) * 32 ) ); 
        Str 
-> Version 
= ( char ** ) malloc ( ( ssize_t 
) ( sizeof ( char * ) * 32 ) ); 
 
 
        for ( i = 0 ; i < Str -> NOD; i++ )
 
        {
 
                char * serial  
= ( char * ) malloc ( ( ssize_t 
) 16 );  
                char * version 
= ( char * ) malloc ( ( ssize_t 
) 6 );  
 
 
                dwRes = IOCTRL ( i, 
 
                                                IOCTL_GET_SERIAL, 
 
                                                ( PVOID ) serial, 
 
                                                16, NULL, 0 );
 
 
 
                if ( ( int ) dwRes < 0 )
 
                {
 
                        dwRes = SetLastErr ( "USMC_Init () failed during IOCTRL ( IOCTL_GET_SERIAL ) call", dwRes );
 
                        Str -> NOD = 0;
 
                        Str -> Serial = Str -> Version = NULL;
 
 
 
                        return  dwRes;
 
                }
 
 
 
 
 
                dwRes = IOCTRL ( i, 
 
                                                IOCTL_GET_VERSION, 
 
                                                ( PVOID ) version, 
 
                                                6, NULL, 0 );
 
 
 
                if ( ( int ) dwRes < 0 )
 
                {
 
                        dwRes = SetLastErr ( "USMC_Init () failed during IOCTRL ( IOCTL_GET_VERSION ) call", dwRes );
 
                        Str -> NOD = 0;
 
                        Str -> Serial = Str -> Version = NULL;
 
 
 
                        return  dwRes;
 
                }
 
 
 
 
 
                Str -> Serial [i] = serial;
 
 
 
                ( Str 
-> Version 
[i
] ) = ( char * ) malloc ( ( ssize_t 
) 4 );  
                memcpy ( Str 
-> Version 
[i
], version 
+ 2, ( ssize_t 
) 4 );  
 
 
                //strupr ( Str -> Version [i] );
 
                sscanf ( Str 
-> Version 
[i
], "%X", &g_devicesVersions 
[i
] );  
        }
 
 
 
 
 
        g_devices = *Str;
 
        InitDefaultValues ();
 
 
 
        //LeaveCriticalSection ( &g_Lock );
 
        
 
 
 
        return  USMC_SUCCESS;
 
}
 
 
 
 
 
 
 
 
 
DWORD USMC_GetState ( DWORD Device, USMC_State * Str )
 
{
 
        if ( !g_IsInitialized )
 
                return  SetLastErr ( "USMC_GetState () failed", -USMC_ERROR_NOT_INITIALIZED );
 
 
 
 
 
 
 
        STATE_PACKET getStateData;
 
 
 
        //EnterCriticalSection ( &g_Lock );
 
        DWORD dwRes = IOCTRL ( Device, 
 
                                                  IOCTL_GET_STATE, 
 
                                                  ( PVOID ) &getStateData,
 
                                                  11, NULL, 0 );
 
        //LeaveCriticalSection ( &g_Lock );
 
 
 
        if ( ( int ) dwRes < 0 )
 
                return  SetLastErr ( "USMC_GetState () failed during IOCTRL ( IOCTL_GET_STATE ) call", dwRes );
 
 
 
 
 
        Str -> AReset    = getStateData.AFTRESET;
 
        Str -> CurPos    = ( ( signed int ) getStateData.CurPos ) / 8;
 
        Str -> CW_CCW    = getStateData.CW_CCW;
 
        Str -> EmReset   = getStateData.EMRESET;
 
        Str -> FullPower = getStateData.REFIN;
 
        Str -> FullSpeed = getStateData.FULLSPEED;
 
        Str -> Loft      = getStateData.LOFT;
 
        Str -> Power     = getStateData.RESET;
 
        Str -> RotTr     = getStateData.ROTTR;
 
        Str -> RotTrErr  = getStateData.ROTTRERR;
 
        Str -> RUN       = getStateData.RUN;
 
        /*Str -> SDivisor= See below;*/
 
        Str -> SyncIN    = getStateData.SYNCIN;
 
        Str -> SyncOUT   = getStateData.SYNCOUT;
 
        /*Str -> Temp    = See below;*/
 
        Str -> Trailer1  = getStateData.TRAILER1;
 
        Str -> Trailer2  = getStateData.TRAILER2;
 
        /*Str -> Voltage = See below;*/
 
 
 
        Str -> SDivisor  = ( BYTE ) ( 1 << ( getStateData.M2 << 1 | getStateData.M1 ) );
 
        double t      = ( double ) getStateData.Temp;
 
 
 
        if ( g_devicesVersions [Device] < 0x2400 )
 
        {
 
                t = t * 3.3 / 65536.0;
 
                t = t * 10.0 / ( 5.0 - t );
 
                t 
= ( 1.0 / 298.0 ) + ( 1.0 / 3950.0 ) * log ( t 
/ 10.0 ); 
                t = 1.0 / t - 273.0;
 
        }
 
        else
 
        {
 
                t = ( ( t * 3.3 * 100.0 / 65536.0 ) - 50.0 );
 
        }
 
 
 
 
 
        Str -> Temp    = ( float ) t;
 
        Str -> Voltage = ( float ) ( ( ( double ) getStateData.Voltage ) / 65536.0 * 3.3 * 20.0 );
 
        Str -> Voltage = Str -> Voltage < 5.0f ? 0.0f : Str -> Voltage;
 
 
 
 
 
        return  USMC_SUCCESS;
 
}
 
 
 
 
 
 
 
 
 
DWORD USMC_SaveParametersToFlash ( DWORD Device )
 
{
 
        if ( !g_IsInitialized )
 
                return  SetLastErr ( "USMC_SaveParametersToFlash () failed", -USMC_ERROR_NOT_INITIALIZED );
 
 
 
 
 
        //EnterCriticalSection ( &g_Lock );
 
        DWORD dwRes = IOCTRL ( Device, 
 
                                                  IOCTL_SAVE_PARAMETERS, 
 
                                                  NULL, 0, NULL, 0 );
 
        //LeaveCriticalSection ( &g_Lock );
 
 
 
 
 
        if ( ( int ) dwRes < 0 )
 
                return  SetLastErr ( "USMC_SaveParametersToFlash () failed during IOCTRL ( IOCTL_SAVE_PARAMETERS ) call", dwRes );
 
 
 
 
 
 
 
        return  USMC_SUCCESS;
 
}
 
 
 
 
 
 
 
 
 
DWORD USMC_GetMode ( DWORD Device, USMC_Mode * Str )
 
{
 
        if ( !g_IsInitialized )
 
                return  SetLastErr ( "USMC_GetMode () failed", -USMC_ERROR_NOT_INITIALIZED );
 
 
 
 
 
        *Str = g_deviceMode [Device];
 
 
 
 
 
        return  USMC_SUCCESS;
 
}
 
 
 
 
 
 
 
 
 
DWORD USMC_SetMode ( DWORD Device, USMC_Mode * Str )
 
{
 
        if ( !g_IsInitialized )
 
                return  SetLastErr ( "USMC_SetMode () failed", -USMC_ERROR_NOT_INITIALIZED );
 
 
 
 
 
        MODE_PACKET setModeData;
 
        // Byte 0:
 
        setModeData.PMODE     = Str -> PMode;
 
        setModeData.REFINEN   = Str -> PReg;
 
        setModeData.RESETD    = Str -> ResetD;
 
        setModeData.EMRESET   = Str -> EMReset;
 
        setModeData.TR1T      = Str -> Tr1T;
 
        setModeData.TR2T      = Str -> Tr2T;
 
        setModeData.ROTTRT    = Str -> RotTrT;
 
        setModeData.TRSWAP    = Str -> TrSwap;  
 
        // Byte 1:
 
        setModeData.TR1EN     = Str -> Tr1En;
 
        setModeData.TR2EN     = Str -> Tr2En;
 
        setModeData.ROTTREN   = Str -> RotTeEn;
 
        setModeData.ROTTROP   = Str -> RotTrOp;
 
        setModeData.BUTT1T    = Str -> Butt1T;
 
        setModeData.BUTT2T    = Str -> Butt2T;
 
        /*setModeData.BUTSWAP = ...;*/
 
        setModeData.RESETRT   = Str -> ResetRT;
 
        // Byte 2:
 
        setModeData.SNCOUTEN  = Str -> SyncOUTEn;
 
        setModeData.SYNCOUTR  = Str -> SyncOUTR;
 
        setModeData.SYNCINOP  = Str -> SyncINOp;
 
        setModeData.SYNCOPOL  = Str -> SyncInvert;
 
        setModeData.ENCODER   = Str -> EncoderEn;
 
        setModeData.INVENC    = Str -> EncoderInv;
 
        setModeData.RESBENC   = Str -> ResBEnc;
 
        setModeData.RESENC    = Str -> ResEnc;
 
 
 
        setModeData.SYNCCOUNT = PACK_DWORD ( Str -> SyncCount );
 
 
 
        // Save parameters within DLL for further USMC_GetMode () calls:
 
        //EnterCriticalSection ( &g_Lock );
 
        g_deviceMode [Device] = *Str;
 
 
 
        DWORD dwRes = IOCTRL ( Device, 
 
                                                  IOCTL_SET_MODE, 
 
                                                  NULL, 0, 
 
                                                  ( PVOID ) &setModeData, 7 );
 
        //LeaveCriticalSection ( &g_Lock );
 
 
 
 
 
        if ( ( int ) dwRes < 0 )
 
                return  SetLastErr ( "USMC_SetMode () failed during IOCTRL ( IOCTL_SET_MODE ) call", dwRes );
 
 
 
 
 
        return  USMC_SUCCESS;
 
}
 
 
 
 
 
 
 
 
 
DWORD USMC_GetParameters ( DWORD Device, USMC_Parameters * Str )
 
{
 
        if ( !g_IsInitialized )
 
                return  SetLastErr ( "USMC_GetParameters () failed", -USMC_ERROR_NOT_INITIALIZED );
 
 
 
 
 
        *Str = g_deviceParameters [Device];
 
 
 
 
 
        return  USMC_SUCCESS;
 
}
 
 
 
 
 
 
 
 
 
DWORD USMC_SetParameters ( DWORD Device, USMC_Parameters * Str )
 
{
 
        if ( !g_IsInitialized )
 
                return  SetLastErr ( "USMC_SetParameters () failed", -USMC_ERROR_NOT_INITIALIZED );
 
 
 
 
 
        PARAMETERS_PACKET setParametersData;
 
 
 
        /*=====================*/
 
        /* ----Conversion:---- */
 
        /*=====================*/
 
        setParametersData.DELAY1       = ( BYTE ) clamp ( ( int ) ( Str -> AccelT / 98.0f + 0.5f ), 1, 15 );
 
        setParametersData.DELAY2       = ( BYTE ) clamp ( ( int ) ( Str -> DecelT / 98.0f + 0.5f ), 1, 15 );
 
        setParametersData.RefINTimeout = ( WORD ) ( clampf ( Str -> PTimeout , 1.0f, 9961.0f ) / 0.152f + 0.5f );
 
        setParametersData.BTIMEOUT1    = PACK_WORD ( ( WORD ) ( clampf ( Str -> BTimeout1, 1.0f, 9961.0f ) / 0.152f + 0.5f ) );
 
        setParametersData.BTIMEOUT2    = PACK_WORD ( ( WORD ) ( clampf ( Str -> BTimeout2, 1.0f, 9961.0f ) / 0.152f + 0.5f ) );
 
        setParametersData.BTIMEOUT3    = PACK_WORD ( ( WORD ) ( clampf ( Str -> BTimeout3, 1.0f, 9961.0f ) / 0.152f + 0.5f ) );
 
        setParametersData.BTIMEOUT4    = PACK_WORD ( ( WORD ) ( clampf ( Str -> BTimeout4, 1.0f, 9961.0f ) / 0.152f + 0.5f ) );
 
        setParametersData.BTIMEOUTR    = PACK_WORD ( ( WORD ) ( clampf ( Str -> BTimeoutR, 1.0f, 9961.0f ) / 0.152f + 0.5f ) );
 
        setParametersData.BTIMEOUTD    = PACK_WORD ( ( WORD ) ( clampf ( Str -> BTimeoutD, 1.0f, 9961.0f ) / 0.152f + 0.5f ) );
 
        setParametersData.MINPERIOD    = PACK_WORD ( ( WORD ) ( 65536.0f - ( 125000.0f / clampf ( Str -> MinP , 2.0f, 625.0f ) ) + 0.5f ) );
 
        setParametersData.BTO1P        = PACK_WORD ( ( WORD ) ( 65536.0f - ( 125000.0f / clampf ( Str -> BTO1P, 2.0f, 625.0f ) ) + 0.5f ) );
 
        setParametersData.BTO2P        = PACK_WORD ( ( WORD ) ( 65536.0f - ( 125000.0f / clampf ( Str -> BTO2P, 2.0f, 625.0f ) ) + 0.5f ) );
 
        setParametersData.BTO3P        = PACK_WORD ( ( WORD ) ( 65536.0f - ( 125000.0f / clampf ( Str -> BTO3P, 2.0f, 625.0f ) ) + 0.5f ) );
 
        setParametersData.BTO4P        = PACK_WORD ( ( WORD ) ( 65536.0f - ( 125000.0f / clampf ( Str -> BTO4P, 2.0f, 625.0f ) ) + 0.5f ) );
 
        setParametersData.MAX_LOFT     = PACK_WORD ( ( WORD ) ( clamp ( Str -> MaxLoft, 1, 1023 ) * 64 ) );
 
 
 
        if ( g_devicesVersions [Device] < 0x2407 )
 
        {
 
                setParametersData.STARTPOS = 0x00000000L;
 
        }
 
        else
 
        {
 
                setParametersData.STARTPOS = PACK_DWORD ( Str -> StartPos * 8 & 0xFFFFFF00 );
 
        }
 
 
 
 
 
        setParametersData.RTDelta    = PACK_WORD ( ( WORD ) ( clamp ( Str -> RTDelta   , 4, 1023 ) * 64 ) );
 
        setParametersData.RTMinError = PACK_WORD ( ( WORD ) ( clamp ( Str -> RTMinError, 4, 1023 ) * 64 ) );
 
 
 
        double t = ( double ) clampf ( Str -> MaxTemp, 0.0f, 100.0f );
 
 
 
        if ( g_devicesVersions [Device] < 0x2400 )
 
        {
 
                t 
= 10.0 * exp ( 3950.0 * ( 1.0 / ( t 
+ 273.0 ) - 1.0 / 298.0 ) ); 
                t = ( ( 5 * t / ( 10 + t ) ) * 65536.0 / 3.3 + 0.5 );
 
        }
 
        else
 
        {
 
                t = ( t + 50.0 ) / 330.0 * 65536.0;
 
                t = ( t + 0.5f );
 
        }
 
 
 
 
 
        setParametersData.MaxTemp    = PACK_WORD ( ( WORD ) t );
 
        setParametersData.SynOUTP    = Str -> SynOUTP;
 
        setParametersData.LoftPeriod = Str -> LoftPeriod == 0.0f ? 0 :
 
                                                                         PACK_WORD ( ( WORD ) ( 65536.0f - ( 125000.0f / clampf ( Str -> LoftPeriod, 16.0f, 5000.0f ) ) + 0.5f ) );
 
        setParametersData.EncVSCP    = ( BYTE ) ( Str -> EncMult * 4.0f + 0.5f );
 
//setParametersData.EncVSCP = 1;        ///////////
 
 
 
        memset ( setParametersData.
Reserved, 0, 15 );  
        //unsigned char testBuf [sizeof ( PARAMETERS_PACKET )];
 
        //memcpy ( ( void * ) testBuf, ( const void * ) &setParametersData, ( size_t ) sizeof ( PARAMETERS_PACKET ) );
 
        /*=======================*/
 
        /* ----Deconversion:---- */
 
        /*=======================*/
 
        Str -> AccelT    = setParametersData.DELAY1 * 98.0f;
 
        Str -> DecelT    = setParametersData.DELAY2 * 98.0f;
 
        Str -> PTimeout  = ( float ) ( setParametersData.RefINTimeout * 0.152f );
 
        Str -> BTimeout1 = ( float ) ( PACK_WORD ( setParametersData.BTIMEOUT1 ) * 0.152f );
 
        Str -> BTimeout2 = ( float ) ( PACK_WORD ( setParametersData.BTIMEOUT2 ) * 0.152f );
 
        Str -> BTimeout3 = ( float ) ( PACK_WORD ( setParametersData.BTIMEOUT3 ) * 0.152f );
 
        Str -> BTimeout4 = ( float ) ( PACK_WORD ( setParametersData.BTIMEOUT4 ) * 0.152f );
 
        Str -> BTimeoutR = ( float ) ( PACK_WORD ( setParametersData.BTIMEOUTR ) * 0.152f );
 
        Str -> BTimeoutD = ( float ) ( PACK_WORD ( setParametersData.BTIMEOUTD ) * 0.152f );
 
        Str -> MinP      = 125000.0f / ( 65536.0f - ( float ) ( PACK_WORD ( setParametersData.MINPERIOD ) ) );
 
        Str -> BTO1P     = 125000.0f / ( 65536.0f - ( float ) ( PACK_WORD ( setParametersData.BTO1P ) ) );
 
        Str -> BTO2P     = 125000.0f / ( 65536.0f - ( float ) ( PACK_WORD ( setParametersData.BTO2P ) ) );
 
        Str -> BTO3P     = 125000.0f / ( 65536.0f - ( float ) ( PACK_WORD ( setParametersData.BTO3P ) ) );
 
        Str -> BTO4P     = 125000.0f / ( 65536.0f - ( float ) ( PACK_WORD ( setParametersData.BTO4P ) ) );
 
        Str -> MaxLoft   = PACK_WORD ( setParametersData.MAX_LOFT ) / 64;
 
 
 
        if( g_devicesVersions [Device] < 0x2407 )
 
        {
 
                Str -> StartPos = 0x00000000L;
 
        }
 
        else
 
        {
 
                Str -> StartPos = PACK_DWORD ( setParametersData.STARTPOS ) / 8;
 
        }
 
 
 
 
 
        Str -> RTDelta    = PACK_WORD ( setParametersData.RTDelta )    / 64;
 
        Str -> RTMinError = PACK_WORD ( setParametersData.RTMinError ) / 64;
 
 
 
        if ( g_devicesVersions [Device] < 0x2400 )
 
        {
 
                t = ( double )( PACK_WORD ( setParametersData.MaxTemp ) );
 
                t = t * 3.3 / 65536.0; 
 
                t = 10.0 * t / ( 5.0 - t );
 
                t 
= ( 1.0 / 298.0 ) + ( 1.0 / 3950.0 ) * log ( t 
/ 10.0 ); 
                t = 1.0 / t - 273.0;
 
        }
 
        else
 
        {
 
                t = ( double ) ( PACK_WORD ( setParametersData.MaxTemp ) );
 
                t = ( t * 3.3 * 100.0 / 65536.0 ) - 50.0;
 
        }
 
 
 
 
 
        Str -> MaxTemp = ( float ) t;
 
 
 
        Str -> SynOUTP = setParametersData.SynOUTP;
 
        Str -> LoftPeriod = PACK_WORD ( setParametersData.LoftPeriod ) == 0 ? 0.0f :
 
                                         125000.0f / ( 65536.0f - ( float ) ( PACK_WORD ( setParametersData.LoftPeriod ) ) );
 
        Str -> EncMult = ( ( float ) setParametersData.EncVSCP ) / 4.0f;
 
 
 
        // Save parameters within DLL for further USMC_GetParameters () calls:
 
        //EnterCriticalSection ( &g_Lock );
 
        g_deviceParameters [Device] = *Str;
 
 
 
        DWORD dwRes = IOCTRL ( Device, 
 
                                                  IOCTL_SET_PARAMETERS, 
 
                                                  NULL, 0, 
 
                                                  ( PVOID ) &setParametersData, 57 );
 
        //LeaveCriticalSection ( &g_Lock );
 
 
 
 
 
        if ( ( int ) dwRes < 0 )
 
                return  SetLastErr ( "USMC_SetParameters () failed during IOCTRL ( IOCTL_SET_PARAMETERS ) call", dwRes );
 
 
 
 
 
        return  USMC_SUCCESS;
 
}
 
 
 
 
 
 
 
 
 
DWORD USMC_GetStartParameters ( DWORD Device, USMC_StartParameters * Str )
 
{
 
        if ( !g_IsInitialized )
 
                return  SetLastErr ( "USMC_GetStartParameters () failed", -USMC_ERROR_NOT_INITIALIZED );
 
 
 
 
 
        *Str = g_deviceStartParameters [Device];
 
 
 
 
 
        return  USMC_SUCCESS;
 
}
 
 
 
 
 
 
 
 
 
DWORD USMC_Start ( DWORD Device, int DestPos, 
 
                                                           float * Speed, 
 
                                                           USMC_StartParameters * Str )
 
{
 
        if ( !g_IsInitialized )
 
                return  SetLastErr ( "USMC_Start () failed", -USMC_ERROR_NOT_INITIALIZED );
 
 
 
 
 
        GO_TO_PACKET goToData;
 
 
 
        /*=====================*/
 
        /* ----Conversion:---- */
 
        /*=====================*/
 
        goToData.DestPos     = ( DWORD ) ( DestPos * 8 );
 
        goToData.TimerPeriod = PACK_WORD ( ( WORD  ) ( 65536.0f - ( 1000000.0f / clampf ( *Speed, 16.0f, 5000.0f ) ) + 0.5f ) );
 
        switch ( Str -> SDivisor )
 
        {
 
        case 1:
 
                goToData.M1 = goToData.M2 = 0;
 
                break;
 
        case 2:
 
                goToData.M1 = 1;
 
                goToData.M2 = 0;
 
                break;
 
        case 4:
 
                goToData.M1 = 0;
 
                goToData.M2 = 1;
 
                break;
 
        case 8:
 
                goToData.M1 = 1;
 
                goToData.M2 = 1;
 
                break;
 
        }
 
        //goToData.M1          = Str -> SDivisor && 0x01;
 
        //goToData.M2          = Str -> SDivisor && 0x02;
 
        goToData.DEFDIR      = Str -> DefDir;
 
        goToData.LOFTEN      = Str -> LoftEn;
 
        goToData.SLSTRT      = Str -> SlStart;
 
        goToData.WSYNCIN     = Str -> WSyncIN;
 
        goToData.SYNCOUTR    = Str -> SyncOUTR;
 
        goToData.FORCELOFT   = Str -> ForceLoft;
 
 
 
 
 
        /*=======================*/
 
        /* ----Deconversion:---- */
 
        /*=======================*/
 
        *Speed        = 1000000.0f / ( 65536.0f - ( float ) PACK_WORD ( goToData.TimerPeriod ) );
 
        Str -> SDivisor = 1 << ( ( goToData.M2 << 1 ) | goToData.M1 );
 
 
 
        // Save start parameters within DLL for further USMC_GetStartParameters () calls:
 
        //EnterCriticalSection ( &g_Lock );
 
        g_deviceStartParameters [Device] = *Str;
 
 
 
        DWORD dwRes = IOCTRL ( Device, 
 
                                                  IOCTL_GO_TO, 
 
                                                  NULL, 0, 
 
                                                  ( PVOID ) &goToData, 7 );
 
        //LeaveCriticalSection ( &g_Lock );
 
 
 
 
 
        if ( ( int ) dwRes < 0 )
 
                return  SetLastErr ( "USMC_Start () failed during IOCTRL ( IOCTL_GO_TO ) call", dwRes );
 
 
 
 
 
        return  USMC_SUCCESS;
 
}
 
 
 
 
 
 
 
 
 
DWORD USMC_Stop ( DWORD Device )
 
{
 
        if ( !g_IsInitialized )
 
                return  SetLastErr ( "USMC_Stop () failed", -USMC_ERROR_NOT_INITIALIZED );
 
 
 
 
 
        //EnterCriticalSection ( &g_Lock );
 
        DWORD dwRes = IOCTRL ( Device, 
 
                                                  IOCTL_STOP_STEP_MOTOR, 
 
                                                  NULL, 0, NULL, 0 );
 
        //LeaveCriticalSection ( &g_Lock );
 
 
 
 
 
        if ( ( int ) dwRes < 0 )
 
                return  SetLastErr ( "USMC_Stop () failed during IOCTRL ( IOCTL_STOP_STEP_MOTOR ) call", dwRes );
 
 
 
 
 
        return  USMC_SUCCESS;
 
}
 
 
 
 
 
 
 
 
 
DWORD USMC_SetCurrentPosition ( DWORD Device, int Position )
 
{
 
        if ( !g_IsInitialized )
 
                return  SetLastErr ( "USMC_SetCurrentPosition () failed", -USMC_ERROR_NOT_INITIALIZED );
 
 
 
 
 
        Position *= 8;
 
        Position &= 0xFFFFFFE0;
 
        //EnterCriticalSection ( &g_Lock );
 
        DWORD dwRes = IOCTRL ( Device, 
 
                                                  IOCTL_SET_CURRENT_POSITION, 
 
                                                  NULL, 0, 
 
                                                  ( PVOID ) &Position, 4 );
 
        //LeaveCriticalSection ( &g_Lock );
 
 
 
 
 
        if ( ( int ) dwRes < 0 )
 
                return  SetLastErr ( "USMC_SetCurrentPosition () failed during IOCTRL ( IOCTL_SET_CURRENT_POSITION ) call", dwRes );
 
 
 
 
 
        return  USMC_SUCCESS;
 
}
 
 
 
 
 
 
 
 
 
DWORD USMC_GetEncoderState ( DWORD Device, USMC_EncoderState * Str )
 
{
 
        if ( !g_IsInitialized )
 
                return  SetLastErr ( "USMC_GetEncoderState () failed", -USMC_ERROR_NOT_INITIALIZED );
 
 
 
 
 
        if ( g_devicesVersions [Device] < 0x2410 )
 
                return  USMC_SUCCESS;
 
 
 
 
 
        //EnterCriticalSection ( &g_Lock );
 
        ENCODER_STATE_PACKET getEncoderStateData;
 
 
 
        DWORD dwRes = IOCTRL ( Device, 
 
                                                  IOCTL_GET_ENCODER_STATE, 
 
                                                  ( PVOID ) &getEncoderStateData,
 
                                                  8, NULL, 0 );
 
        //LeaveCriticalSection ( &g_Lock );
 
 
 
 
 
        if ( ( int ) dwRes < 0 )
 
                return  SetLastErr ( "USMC_GetEncoderState () failed during IOCTRL ( IOCTL_GET_STATE ) call", dwRes );
 
 
 
 
 
        Str -> ECurPos    = getEncoderStateData.ECurPos;
 
        Str -> EncoderPos = getEncoderStateData.EncPos;
 
 
 
 
 
        return  USMC_SUCCESS;
 
}
 
 
 
 
 
 
 
 
 
void USMC_GetLastErr ( char * str, ssize_t len )
 
{
 
        //EnterCriticalSection ( &g_Lock );
 
        if ( strlen ( g_lastErrDesc 
) > len 
)  
                memcpy ( str
, g_lastErrDesc
, len 
);  
        else
 
                strcpy ( str
, ( const char * ) g_lastErrDesc 
);  
        //LeaveCriticalSection ( &g_Lock );
 
}
 
 
 
 
 
 
 
 
 
DWORD USMC_Close ( void )
 
{
 
        if ( !g_IsInitialized )
 
                return  SetLastErr ( "USMC_Close () failed", -USMC_ERROR_NOT_INITIALIZED );
 
 
 
 
 
        return  USMC_SUCCESS;
 
}