/************************************************************************
*									*
*       Maxon Digital EC Servoamplifier RS232 Protocol Interface        *
*									*
*           Copyright (C) 2009, Centre for Autonomous Systems           *
*           Copyright (C) 2009, University of New South Wales           *
*                   Copyright (C) 2009, John Zaitseff                   *
*									*
************************************************************************/

/*
  Author:  John Zaitseff <J.Zaitseff@unsw.edu.au>
  Date:    13th October, 2009
  Version: 1.1

  $Id$

  This file, "desapi.h", provides an interface to the Maxon Digital EC
  Servoamplifier using the RS232 protocol.  This allows your program to
  communicate with a DES module (such as Maxon 4QEC motor controllers)
  using a standard serial port.  The interface (API) has been based on
  the one provided by Maxon in their Windows DESCMD.DLL library, but is
  not identical.


  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License along
  with this program; if not, write to the Free Software Foundation, Inc.,
  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/


#ifndef __MAXON_DES_API_H
#define __MAXON_DES_API_H 1


// Handle C++ by wrapping the whole header file with "extern C"
#ifdef __cplusplus
extern "C" {
#endif


/************************************************************************
*                         Included header files                         *
************************************************************************/

#include <stdint.h>
#include <termios.h>


/************************************************************************
*                    Constants and type definitions                     *
************************************************************************/

// Bit masks for des_readsysstatus()
enum des_sysstatus_masks {
    DES_SYSSTATUS_ENCODERFOUND_MASK	= 0x0001,
    DES_SYSSTATUS_HALLSENSORFOUND_MASK	= 0x0002,
    DES_SYSSTATUS_ROTORFOUND_MASK	= 0x0004,
    DES_SYSSTATUS_SAVINGSYSPARAMS_MASK	= 0x0008,
    DES_SYSSTATUS_MAXCURRENT_MASK	= 0x0080,
    DES_SYSSTATUS_CURRENTREGION_MASK	= 0x0100,
    DES_SYSSTATUS_ERRORS_MASK		= 0x0200,
    DES_SYSSTATUS_SOFTWAREENABLED_MASK	= 0x0400,
    DES_SYSSTATUS_DEBOUNCING_MASK	= 0x0800,
    DES_SYSSTATUS_OFFSETCURRENT_MASK	= 0x1000,
    DES_SYSSTATUS_BRAKING_MASK		= 0x2000,
    DES_SYSSTATUS_POWERSTAGE1_MASK	= 0x4000,
    DES_SYSSTATUS_POWERSTAGE2_MASK	= 0x8000,
    DES_SYSSTATUS_POWERSTAGE_MASK	= 0xC000
};

// Bit masks for des_readerror()
enum des_error_masks {
    DES_ERROR_HALLSENSOR_MASK		= 0x0001,
    DES_ERROR_INDEXPROCESSING_MASK	= 0x0002,
    DES_ERROR_ENCODERRESOLUTION_MASK	= 0x0004,
    DES_ERROR_HALLSENSOR3_MASK		= 0x0008,
    DES_ERROR_OVERCURRENT_MASK		= 0x0010,
    DES_ERROR_OVERVOLTAGE_MASK		= 0x0020,
    DES_ERROR_OVERSPEED_MASK		= 0x0040,
    DES_ERROR_SUPPLYVOLTAGE_MASK	= 0x0080,
    DES_ERROR_ANGLEDETECTION_MASK	= 0x0100,
    DES_ERROR_OVERTEMP_MASK		= 0x0800,
    DES_ERROR_PARAMETER_MASK		= 0x2000,
    DES_ERROR_ERRORS_MASK		= 0x8000
};

// Values for des_enable()
enum des_enable {
    DES_DISABLE			= 0,
    DES_ENABLE			= 1
};

// Parameter and variable numbers for des_readtempparam(), etc
typedef enum des_parameters {
    // DES System Parameters
    DES_SP_BAUDRATE		=  0,
    DES_SP_SYSCONFIG		=  1,
    DES_SP_CURREGGAINP		=  2,
    DES_SP_CURREGGAINI		=  3,
    DES_SP_MAXCUROUTPUT		=  4,
    DES_SP_SPEEDREGGAINP	=  5,
    DES_SP_SPEEDREGGAINI	=  6,
    DES_SP_POSREGGAINP		=  7,
    DES_SP_POSREGGAINI		=  8,
    DES_SP_POSREGGAIND		=  9,
    DES_SP_MAXSPEEDERROR	= 10,
    DES_SP_SETTINGUNITGAIN	= 11,
    DES_SP_SETTINGUNITOFFSET	= 12,
    DES_SP_SETTINGUNITDELAY	= 13,
    DES_SP_PEAKCURRENT		= 14,
    DES_SP_MAXCONTCURRENT	= 15,
    DES_SP_THERMCONST		= 16,
    DES_SP_MAXSPEED		= 17,
    DES_SP_ACCELERATION		= 18,
    DES_SP_SPEEDCONSTANT	= 19,
    DES_SP_ENCRESOLUTION	= 20,
    DES_SP_POLEPAIRNUMBER	= 21,
    DES_SP_QEP2RPMFACTOR	= 22,
    DES_SP_RPM2QEPFACTOR	= 23,
    DES_SP_INDEXOFFSET		= 24,
    DES_SP_PWMPERIOD		= 25,
    DES_SP_MAXDUTYCYCLE		= 26,
    DES_SP_CURDETPHUOFFSET	= 27,
    DES_SP_CURDETPHVOFFSET	= 28,
    DES_SP_ADCONVOFFSET		= 29,
    DES_SP_CAN_MODULEID		= 30,
    DES_SP_CAN_SERVICEID	= 31,
    DES_SP_CAN_RPDOID		= 32,
    DES_SP_CAN_TPDOID		= 33,
    DES_SP_CAN_BCR1		= 34,
    DES_SP_CAN_BCR2		= 35,
    DES_SP_CAN_OPMODE		= 36,
    DES_SP_CAN_RSDOID		= 37,
    DES_SP_CAN_TSDOID		= 38,
    DES_SP_CAN_RTR0ID		= 39,
    DES_SP_CAN_RTR1ID		= 40,
    DES_SP_CAN_CONFIG		= 41,
    DES_SP_CAN_LIFEGUARDTIME	= 42,
    DES_SP_ERRORPROC		= 43,
    DES_SP_MAXSPEEDCUR		= 44,
    DES_SP_HALLANGLEOFFS	= 45,
    DES_SP_MAXANGLEMPY1		= 46,
    DES_SP_MAXANGLEMPYN		= 47,

    // DES Status Variables
    DES_SV_SYSOPSTATUS		= 128,
    DES_SV_CURRENTDETDAXIS	= 129,
    DES_SV_CURRENTMEANQAXIS	= 130,
    DES_SV_CURRENTSETVALUE	= 131,
    DES_SV_RELROTORPOSITION	= 132,
    DES_SV_SPEEDSETVALUE	= 133,
    DES_SV_SPEEDMEANVALUE	= 134,
    DES_SV_POSSETVALUE		= 135,		// Reserved
    DES_SV_POSDETVALUE		= 136,		// NB: 32-bit parameter
    DES_SV_STANDARDERROR	= 137,
    DES_SV_CAN_ERROR		= 138,
    DES_SV_CURRENTDETQAXIS	= 139,
    DES_SV_SPEEDDETVALUE	= 140,
    DES_SV_ERRORHISTORY1	= 141,
    DES_SV_ERRORHISTORY2	= 142,
    DES_SV_ENCODERCNTR		= 143,
    DES_SV_ENCODERCNTRIDX	= 144,
    DES_SV_HALLSENSORPATTERN	= 145,
    DES_SV_ADC_SETIN		= 146,
    DES_SV_ADC_NTC1		= 147,
    DES_SV_ADC_NTC2		= 148,
    DES_SV_ADC_GAIN		= 149,
    DES_SV_ADC_IMAX		= 150,
    DES_SV_ADC_OFFSET		= 151,
    DES_SV_ADC_NMAX		= 152,
    DES_SV_DIGITALVALUES	= 153
} des_parameter_t;

// Values for DES_SP_BAUDRATE
enum des_sp_baudrate {
    DES_SP_BAUDRATE_9600	= 0,
    DES_SP_BAUDRATE_14400	= 1,
    DES_SP_BAUDRATE_19200	= 2,
    DES_SP_BAUDRATE_38400	= 3,
    DES_SP_BAUDRATE_57600	= 4,
    DES_SP_BAUDRATE_115200	= 5
};

// Values and bit masks for DES_SP_SYSCONFIG
enum des_sp_sysconfig {
    DES_SP_SYSCONFIG_SOFTWARE_MASK		= 0x0001,
    DES_SP_SYSCONFIG_ACCELERATION_MASK		= 0x0002,
    DES_SP_SYSCONFIG_REGULATIONMODE_MASK	= 0x000C,
      DES_SP_SYSCONFIG_CURRENTREGULATION	= 0x0004,
      DES_SP_SYSCONFIG_SPEEDREGULATION		= 0x0000,
    DES_SP_SYSCONFIG_MONITORSIGNAL_MASK		= 0x0010,
    DES_SP_SYSCONFIG_STOPMOTORSIGNAL_MASK	= 0x0080,
    DES_SP_SYSCONFIG_MAXSPEEDSIGNAL_MASK	= 0x0100,
    DES_SP_SYSCONFIG_OFFSETSIGNAL_MASK		= 0x0200,
    DES_SP_SYSCONFIG_MAXCURRENTSIGNAL_MASK	= 0x0400,
    DES_SP_SYSCONFIG_REGGAINSIGNAL_MASK		= 0x0800,
    DES_SP_SYSCONFIG_ENABLESIGNAL_MASK		= 0x1000,
    DES_SP_SYSCONFIG_SELECTMONITORSIGNAL_MASK	= 0x2000,
    DES_SP_SYSCONFIG_SERVICEMODE_MASK		= 0x4000,
    DES_SP_SYSCONFIG_REGULATIONSIGNAL_MASK	= 0x8000,
      DES_SP_SYSCONFIG_USESOFTWARE_MASK		= (
	DES_SP_SYSCONFIG_SOFTWARE_MASK		  |
	DES_SP_SYSCONFIG_STOPMOTORSIGNAL_MASK	  |
	DES_SP_SYSCONFIG_MAXSPEEDSIGNAL_MASK	  |
	DES_SP_SYSCONFIG_OFFSETSIGNAL_MASK	  |
	DES_SP_SYSCONFIG_MAXCURRENTSIGNAL_MASK	  |
	DES_SP_SYSCONFIG_REGGAINSIGNAL_MASK	  |
	DES_SP_SYSCONFIG_ENABLESIGNAL_MASK	  |
	DES_SP_SYSCONFIG_SELECTMONITORSIGNAL_MASK |
	DES_SP_SYSCONFIG_REGULATIONSIGNAL_MASK    ),
    DES_SP_SYSCONFIG_USESOFTWARE		= (
     // ~DES_SP_SYSCONFIG_SOFTWARE_MASK		  |
	DES_SP_SYSCONFIG_STOPMOTORSIGNAL_MASK	  |
	DES_SP_SYSCONFIG_MAXSPEEDSIGNAL_MASK	  |
	DES_SP_SYSCONFIG_OFFSETSIGNAL_MASK	  |
	DES_SP_SYSCONFIG_MAXCURRENTSIGNAL_MASK	  |
	DES_SP_SYSCONFIG_REGGAINSIGNAL_MASK	  |
	DES_SP_SYSCONFIG_ENABLESIGNAL_MASK	  |
	DES_SP_SYSCONFIG_SELECTMONITORSIGNAL_MASK |
	DES_SP_SYSCONFIG_REGULATIONSIGNAL_MASK    )
};

// IsMust constants
typedef enum des_ismust_types {
    DES_ISMUST_MEAN		= 0,
    DES_ISMUST_REALTIME		= 1
} des_ismust_t;


// Suggested minimum timing constants for usleep()
enum des_delays {
    DES_RESET_DELAY		= 250000,	// Delay after reset, in usec
    DES_EPROTO_DELAY		= 1000,		// Delay after EPROTO
    DES_TIMEOUT_DELAY		= 500000	// Delay for DES to time out
};


// Structure for des_readalltempparams() and des_setalltempparams()
#define DES_SYSPARAM_T_MEMBERS 48	// Number of members in des_sysparam_t
typedef struct des_sysparams {
    uint16_t baudrate;			// DES_SP_BAUDRATE
    uint16_t sysconfig;			// DES_SP_SYSCONFIG
    int16_t  curreggainp;		// DES_SP_CURREGGAINP
    int16_t  curreggaini;		// DES_SP_CURREGGAINI
    int16_t  maxcuroutput;		// DES_SP_MAXCUROUTPUT
    int16_t  speedreggainp;		// DES_SP_SPEEDREGGAINP
    int16_t  speedreggaini;		// DES_SP_SPEEDREGGAINI
    int16_t  posreggainp;		// DES_SP_POSREGGAINP
    int16_t  posreggaini;		// DES_SP_POSREGGAINI
    int16_t  posreggaind;		// DES_SP_POSREGGAIND
    int16_t  maxspeederror;		// DES_SP_MAXSPEEDERROR
    int16_t  settingunitgain;		// DES_SP_SETTINGUNITGAIN
    int16_t  settingunitoffset;		// DES_SP_SETTINGUNITOFFSET
    int16_t  settingunitdelay;		// DES_SP_SETTINGUNITDELAY
    int16_t  peakcurrent;		// DES_SP_PEAKCURRENT
    int16_t  maxcontcurrent;		// DES_SP_MAXCONTCURRENT
    int16_t  thermconst;		// DES_SP_THERMCONST
    int16_t  maxspeed;			// DES_SP_MAXSPEED
    int16_t  acceleration;		// DES_SP_ACCELERATION
    int16_t  speedconstant;		// DES_SP_SPEEDCONSTANT
    int16_t  encresolution;		// DES_SP_ENCRESOLUTION
    uint16_t polepairnumber;		// DES_SP_POLEPAIRNUMBER
    int16_t  qep2rpmfactor;		// DES_SP_QEP2RPMFACTOR
    int16_t  rpm2qepfactor;		// DES_SP_RPM2QEPFACTOR
    int16_t  indexoffset;		// DES_SP_INDEXOFFSET
    int16_t  pwmperiod;			// DES_SP_PWMPERIOD
    int16_t  maxdutycycle;		// DES_SP_MAXDUTYCYCLE
    uint16_t curdetphuoffset;		// DES_SP_CURDETPHUOFFSET
    uint16_t curdetphvoffset;		// DES_SP_CURDETPHVOFFSET
    uint16_t adconvoffset;		// DES_SP_ADCONVOFFSET
    uint16_t can_moduleid;		// DES_SP_CAN_MODULEID
    uint16_t can_serviceid;		// DES_SP_CAN_SERVICEID
    uint16_t can_rpdoid;		// DES_SP_CAN_RPDOID
    uint16_t can_tpdoid;		// DES_SP_CAN_TPDOID
    uint16_t can_bcr1;			// DES_SP_CAN_BCR1
    uint16_t can_bcr2;			// DES_SP_CAN_BCR2
    uint16_t can_opmode;		// DES_SP_CAN_OPMODE
    uint16_t can_rsdoid;		// DES_SP_CAN_RSDOID
    uint16_t can_tsdoid;		// DES_SP_CAN_TSDOID
    uint16_t can_rtr0id;		// DES_SP_CAN_RTR0ID
    uint16_t can_rtr1id;		// DES_SP_CAN_RTR1ID
    uint16_t can_config;		// DES_SP_CAN_CONFIG
    uint16_t can_lifeguardtime;		// DES_SP_CAN_LIFEGUARDTIME
    uint16_t errorproc;			// DES_SP_ERRORPROC
    int16_t  maxspeedcur;		// DES_SP_MAXSPEEDCUR
    int16_t  hallangleoffs;		// DES_SP_HALLANGLEOFFS
    uint16_t maxanglempy1;		// DES_SP_MAXANGLEMPY1
    uint16_t maxanglempyn;		// DES_SP_MAXANGLEMPYN
} des_sysparam_t;


// Array definition for des_recorddata()
#define DES_RECORDEDDATA_T_SIZE 256	// Number of elements in des_recordeddata_t array
typedef uint16_t des_recordeddata_t[DES_RECORDEDDATA_T_SIZE];


/************************************************************************
*                           Library functions                           *
************************************************************************/

/*
  Function:   des_open - Open the device used to communicate with the DES
  Parameters: path  - device path (typ. "/dev/ttyUSB0")
              speed - serial port baud rate, from <termios.h> (typ. B38400)
  Returns:    int   - file descriptor, or -1 if error

  This function opens the device used to communicate with the DES via the
  serial port.  The device is opened, the mode is set to 8N1 raw with no
  handshaking, and the file descriptor (a non-negative number) is
  returned.

  If an error occurs, -1 is returned and errno is set appropriately.
  Possible errors (in errno) include, amongst others, EACCES (permission
  denied), ENOENT (no such file) and ENOTTY (not a serial port).

  Note that nothing is actually sent or received on the serial port
  device during the execution of this function!
*/
extern int des_open (const char *path, speed_t speed);


/*
  Function:   des_close - Close the device used to communicate with the DES
  Parameters: fd  - file descriptor previously opened with des_open()
  Returns:    int - 0 on success, -1 on error (with errno set)

  This function closes the file descriptor previously opened with
  des_open().  Following usual Unix semantics (and in agreement with all
  other functions in this API apart from des_open()), zero is returned on
  success, -1 on failure (with errno being set appropriately).

  Note that this function does NOT communicate with the DES connected to
  the serial port!
*/
extern int des_close (int fd);


/*
  Function:   des_readsysstatus - Read the system status on the DES
  Parameters: fd        - file descriptor previously opened with des_open()
              sysstatus - pointer to system status result variable
  Returns:    int       - 0 on success, -1 on error (with errno set)

  This function reads the system status of the DES into the variable
  pointed to by sysstatus.  The system status consists of 16 1-bit flags;
  the enum des_sysstatus_masks may be used to test these bits, as
  documented in the DES Communications Guide.

  If the system status could not be read from the DES, -1 is returned
  with errno being set appropriately.  Possible errors include ETIMEDOUT
  (connection timed out) if the DES does not respond within a number of
  seconds, and EPROTO (protocol error) if a CRC error is detected in
  either transmission or reception of data.
*/
extern int des_readsysstatus (int fd, uint16_t *sysstatus);


/*
  Function:   des_readerror - Read the error status on the DES
  Parameters: fd    - file descriptor previously opened with des_open()
              error - pointer to error status result variable
  Returns:    int   - 0 on success, -1 on error (with errno set)

  This function reads the error status of the DES into the variable
  pointed to by error.  The error status consists of 16 1-bit flags
  (although not all are currently used); the enum des_error_masks may be
  used to test these bits, as documented in the DES Communications Guide.
  Note that des_clearerror() should be called once the error status has
  been noted.

  As with all functions in the API (apart from des_open()), 0 is returned
  on success.  If the error status could not be read from the DES, -1 is
  returned and errno is set appropriately; possible errors include
  ETIMEDOUT (connection timed out) and EPROTO (protocol error).
*/
extern int des_readerror (int fd, uint16_t *error);


/*
  Function:   des_clearerror - Clear error status on the DES
  Parameters: fd  - file descriptor previously opened with des_open()
  Returns:    int - 0 on success, -1 on error (with errno set)

  This function informs the DES that the error status has been noted; the
  DES then clears any system errors (as much as are possible) and
  continues operation.

  As with all functions in this API (apart from des_open()), zero is
  returned on success.  If an error occurs, -1 is returned and errno is
  set appropriately; possible errors include ETIMEDOUT (connection timed
  out) and EPROTO (protocol error).
*/
extern int des_clearerror (int fd);


/*
  Function:   des_reset - Reset the DES firmware
  Parameters: fd  - file descriptor previously opened with des_open()
  Returns:    int - 0 on success, -1 on error (with errno set)

  This function resets the DES firmware, clearing all values stored in
  its temporary memory.  Calls to this function should be followed by a
  call to usleep() with at least DES_RESET_DELAY delay.

  As with all functions in this API (apart from des_open()), zero is
  returned on success.  If an error occurs, -1 is returned and errno is
  set appropriately; possible errors include ETIMEDOUT (connection timed
  out) and EPROTO (protocol error).
*/
extern int des_reset (int fd);


/*
  Function:   des_enable - Enable or disable the DES output stage
  Parameters: fd     - file descriptor previously opened with des_open()
              enable - true to enable the DES, false to disable
  Returns:    int    - 0 on success, -1 on error (with errno set)

  This function enables or disables the output stage of the DES (ie,
  supplies current to the motor or switches the current off).  Note that
  the DES must be already configured for software setting of the enable
  bit for this function to have any effect: bit 12 of DES variable
  DES_SP_SYSCONFIG (ie, DES_SP_SYSCONFIG_ENABLESIGNAL_MASK) must be set
  to 1 using des_settempparam(fd, DES_SP_SYSCONFIG, ...).

  As with all functions in this API (apart from des_open()), zero is
  returned on success.  If an error occurs, -1 is returned and errno is
  set appropriately; possible errors include ETIMEDOUT (connection timed
  out) and EPROTO (protocol error).
*/
extern int des_enable (int fd, int enable);


/*
  Function:   des_readtempparam - Read a parameter from DES temporary memory
  Parameters: fd    - file descriptor previously opened with des_open()
              param - system parameter number
              var   - pointer to result
  Returns:    int   - 0 on success, -1 on error (with errno set)

  This function reads a system parameter or status variable from the
  DES's temporary memory and places it into the variable pointed to by
  var.  The parameter/variable number is contained in param, one of the
  DES_SP_xxx or DES_SV_xxx values in the enum des_parameters.  var must
  point to a variable of either type uint16_t or type int16_t (as
  appropriate); if param is DES_SV_POSDETVALUE, var must point to a
  variable of type int32_t (or uint32_t).

  As with all functions in this API (apart from des_open()), zero is
  returned on success.  If an error occurs, -1 is returned and errno is
  set appropriately; possible errors include ETIMEDOUT (connection timed
  out) and EPROTO (protocol error).
*/
extern int des_readtempparam (int fd, des_parameter_t param, void *var);


/*
  Function:   des_settempparam - Write a parameter to DES temporary memory
  Parameters: fd    - file descriptor previously opened with des_open()
              param - system parameter number
              val   - value to send to DES
  Returns:    int   - 0 on success, -1 on error (with errno set)

  This function writes a system parameter value in val to the DES's
  temporary memory.  The parameter number is contained in param, one of
  the DES_SP_xxx (and possibly DES_SV_xxx) values in enum des_parameters.
  Note that most DES parameters accept only values contained within the
  uint16_t or int16_t ranges; only DES_SV_POSDETVALUE accepts a 32-bit
  value.

  As with all functions in this API (apart from des_open()), zero is
  returned on success.  If an error occurs, -1 is returned and errno is
  set appropriately; possible errors include ETIMEDOUT (connection timed
  out) and EPROTO (protocol error).
*/
extern int des_settempparam (int fd, des_parameter_t param, int val);


/*
  Function:   des_resettempparam - Restore system parameters from EEPROM
  Parameters: fd  - file descriptor previously opened with des_open()
  Returns:    int - 0 on success, -1 on error (with errno set)

  This function copies all system parameters from permanent (EEPROM)
  memory on the DES into temporary memory.

  As with all functions in this API (apart from des_open()), zero is
  returned on success.  If an error occurs, -1 is returned and errno is
  set appropriately; possible errors include ETIMEDOUT (connection timed
  out) and EPROTO (protocol error).
*/
extern int des_resettempparam (int fd);


/*
  Function:   des_savetempparam - Save temporary parameters into EEPROM
  Parameters: fd  - file descriptor previously opened with des_open()
  Returns:    int - 0 on success, -1 on error (with errno set)

  This function copies all system parameters from temporary memory on the
  DES into permanent (EEPROM) memory.  Be very careful in storing system
  parameters: it is possible to set the DES into a state from which it is
  difficult to recover.

  Once this function has been executed successfully, the caller should
  wait until the system parameters have been written.  This may be done
  by checking bit 3 (DES_SYSSTATUS_SAVINGSYSPARAMS_MASK) of the system
  status, as returned by des_readsysstatus().

  As with all functions in this API (apart from des_open()), zero is
  returned on success.  If an error occurs, -1 is returned and errno is
  set appropriately; possible errors include ETIMEDOUT (connection timed
  out) and EPROTO (protocol error).
*/
extern int des_savetempparam (int fd);


/*
  Function:   des_readalltempparam - Read all temporary system parameters
  Parameters: fd    - file descriptor previously opened with des_open()
              param - non-NULL pointer to system parameters structure
  Returns:    int   - 0 on success, -1 on error (with errno set)

  This function reads all system parameters contained in des_sysparam_t
  from the DES's temporary memory and places them into the structure
  pointed to by param.

  As with all functions in this API (apart from des_open()), zero is
  returned on success.  If an error occurs, -1 is returned and errno is
  set appropriately; possible errors include ETIMEDOUT (connection timed
  out) and EPROTO (protocol error).  EINVAL (invalid parameter) is
  returned in errno if param is a NULL pointer.
*/
extern int des_readalltempparam (int fd, des_sysparam_t *param);


/*
  Function:   des_setalltempparam - Write all temporary system parameters
  Parameters: fd    - file descriptor previously opened with des_open()
              param - non-NULL pointer to system parameters structure
  Returns:    int   - 0 on success, -1 on error (with errno set)

  This function writes all system parameters contained in des_sysparam_t,
  and pointed to by param, to the DES's temporary memory.  param may
  point to a read-only (const) copy of the parameters.

  The preferred method of setting all system parameters is to fill a
  des_sysparam_t structure by calling des_readalltempparam(), modifying
  that structure appropriately, then calling des_setalltempparam().

  As with all functions in this API (apart from des_open()), zero is
  returned on success.  If an error occurs, -1 is returned and errno is
  set appropriately; possible errors include ETIMEDOUT (connection timed
  out) and EPROTO (protocol error).  EINVAL (invalid parameter) is
  returned in errno if param is a NULL pointer.
*/
extern int des_setalltempparam (int fd, const des_sysparam_t *param);


/*
  Function:   des_readversion - Read version numbers from the DES
  Parameters: fd          - file descriptor previously opened with des_open()
              softversion - pointer to software version result variable
              hardversion - pointer to hardware version result variable
              appnum      - pointer to application number result variable
              appversion  - pointer to application version result variable
  Returns:    int         - 0 on success, -1 on error (with errno set)

  This function queries the DES for various version numbers and stores
  them in the result variables pointed to by softversion, hardversion,
  appnum and appversion.  One or more of these pointers may be NULL, in
  which case the appropriate version number is not so stored.

  As with all functions in this API (apart from des_open()), zero is
  returned on success.  If an error occurs, -1 is returned and errno is
  set appropriately; possible errors include ETIMEDOUT (connection timed
  out) and EPROTO (protocol error).
*/
extern int des_readversion (int fd, uint16_t *softversion,
			    uint16_t *hardversion, uint16_t *appnum,
			    uint16_t *appversion);


/*
  Function:   des_setdefaultsysparam - Reset temporary parameters to defaults
  Parameters: fd  - file descriptor previously opened with des_open()
  Returns:    int - 0 on success, -1 on error (with errno set)

  This function resets all temporary system parameters to their default
  values (which may be different from the values stored in permanent
  EEPROM memory).

  As with all functions in this API (apart from des_open()), zero is
  returned on success.  If an error occurs, -1 is returned and errno is
  set appropriately; possible errors include ETIMEDOUT (connection timed
  out) and EPROTO (protocol error).
*/
extern int des_setdefaultsysparam (int fd);


/*
  Function:   des_setvelocity - Set the motor's velocity
  Parameters: fd       - file descriptor previously opened with des_open()
              velocity - new velocity in rpm
  Returns:    int      - 0 on success, -1 on error (with errno set)

  This function sets the motor's new target velocity to velocity,
  measured in revolutions per minute (rpm).  It only has effect when
  speed regulation mode is selected (ie, when bits 2 and 3 of the system
  config variable, DES_SP_SYSCONFIG, are cleared to zero) and when
  "setting by software" is in force (bit 0 of DES_SP_SYSCONFIG set to
  zero).

  If velocity is positive, the motor moves counter-clockwise; if
  negative, clockwise.  If velocity is zero, the motor stops and
  effectively brakes: the output stage on the DES is still active, with
  the DES maintaining the requested velocity (of zero).

  If bit 1 (DES_SP_SYSCONFIG_ACCELERATION_MASK) of DES_SP_SYSCONFIG is
  set to zero, the DES causes the motor to smoothly ramp up or down to
  the requested velocity; the DES_SP_ACCELERATION system parameter
  controls the rate of acceleration in this case.

  As with all functions in this API (apart from des_open()), zero is
  returned on success.  If an error occurs, -1 is returned and errno is
  set appropriately; possible errors include ETIMEDOUT (connection timed
  out) and EPROTO (protocol error).
*/
extern int des_setvelocity (int fd, int16_t velocity);


/*
  Function:   des_setcurrent - Set the motor's current amplitude
  Parameters: fd      - file descriptor previously opened with des_open()
              current - new current in mA
  Returns:    int     - 0 on success, -1 on error (with errno set)

  This function sets the motor's new target current amplitude to current,
  measured in mA.  It only has effect when current regulation mode is
  selected (ie, when bit 2 of the system configuration variable,
  DES_SP_SYSCONFIG, is set to one, and bit 3 is set to zero) and when
  "setting by software" is in force (bit 0 of DES_SP_SYSCONFIG set to
  zero).  If current is positive, the motor moves counter-clockwise; if
  negative, clockwise.

  As with all functions in this API (apart from des_open()), zero is
  returned on success.  If an error occurs, -1 is returned and errno is
  set appropriately; possible errors include ETIMEDOUT (connection timed
  out) and EPROTO (protocol error).
*/
extern int des_setcurrent (int fd, int16_t current);


/*
  Function:   des_stopmotion - Stop or restart the motor
  Parameters: fd  - file descriptor previously opened with des_open()
  Returns:    int - 0 on success, -1 on error (with errno set)

  This function stops the motor if it is currently moving, or restarts it
  with the previous velocity if it is currently stopped (with a previous
  call to des_stopmotion()).  It only has effect when speed regulation
  mode is selected.

  Note that the motor is stopped or restarted WITHOUT using the
  DES_SP_ACCELERATION system parameter, ie, the stop/restart is an abrupt
  on-off step.

  As with all functions in this API (apart from des_open()), zero is
  returned on success.  If an error occurs, -1 is returned and errno is
  set appropriately; possible errors include ETIMEDOUT (connection timed
  out) and EPROTO (protocol error).
*/
extern int des_stopmotion (int fd);


/*
  Function:   des_readvelocityismust - Read effective and requested velocities
  Parameters: fd           - file descriptor previously opened with des_open()
              type         - DES_ISMUST_MEAN or DES_ISMUST_REALTIME
              isvelocity   - pointer to mean or effective velocity result
              mustvelocity - pointer to requested velocity result variable
  Returns:    int          - 0 on success, -1 on error (with errno set)

  This function queries the DES for either the mean (averaged; if type ==
  DES_ISMUST_MEAN) or effective (actual; if type == DES_ISMUST_REALTIME)
  motor velocity in rpm and stores it in the variable pointed to by
  isvelocity.  It also stores the last requested velocity into the
  variable pointed to by mustvelocity.  Either result variable pointer
  may be NULL, in which case the corresponding velocity is not so stored.

  Note that the "last requested velocity" may be lower than that
  requested by a call to des_setvelocity() if acceleration or
  deceleration is in progress.

  Calling this function is essentially the same as multiple calls to
  des_readtempparam() with param set to, in turn, DES_SV_SPEEDDETVALUE,
  DES_SV_SPEEDMEANVALUE and DES_SV_SPEEDSETVALUE.

  As with all functions in this API (apart from des_open()), zero is
  returned on success.  If an error occurs, -1 is returned and errno is
  set appropriately; possible errors include ETIMEDOUT (connection timed
  out) and EPROTO (protocol error).
*/
extern int des_readvelocityismust (int fd, des_ismust_t type,
				   int16_t *isvelocity, int16_t *mustvelocity);


/*
  Function:   des_readcurrentismust - Read effective and requested currents
  Parameters: fd         - file descriptor previously opened with des_open()
              type       - DES_ISMUST_MEAN or DES_ISMUST_REALTIME
              isqcurrent - pointer to mean or effective Q-axis current
              isdcurrent - pointer to mean or effective D-axis current
              mustcuramp - pointer to requested current result variable
  Returns:    int        - 0 on success, -1 on error (with errno set)

  This function queries the DES for either the mean (averaged; if type ==
  DES_ISMUST_MEAN) or effective (actual; if type == DES_ISMUST_REALTIME)
  current components and stores them in the variables pointed to by
  isqcurrent (Q-axis component, in mA) and isdcurrent (D-axis component,
  in mA).  The requested current amplitude in mA is stored in the
  variable pointed to by mustcuramp.  If any pointer is NULL, the
  corresponding value is not stored.

  According to the DES Communications Guide, the Q-axis component of the
  current can be used to derive motor torque; the D-axis component should
  be around zero.

  If the DES is in speed regulation mode, the "requested current value"
  is the one requested by the DES itself.

  Calling this function is essentially the same as multiple calls to
  des_readtempparam() with param set to, in turn, DES_SV_CURRENTDETDAXIS,
  DES_SV_CURRENTMEANQAXIS, DES_SV_CURRENTDETQAXIS and
  DES_SV_CURRENTSETVALUE.

  As with all functions in this API (apart from des_open()), zero is
  returned on success.  If an error occurs, -1 is returned and errno is
  set appropriately; possible errors include ETIMEDOUT (connection timed
  out) and EPROTO (protocol error).
*/
extern int des_readcurrentismust (int fd, des_ismust_t type,
				  int16_t *isqcurrent, int16_t *isdcurrent,
				  int16_t *mustcuramp);


/*
  Function:   des_setuprecorder - Set up the data recorder in the DES
  Parameters: fd           - file descriptor previously opened with des_open()
              sampleperiod - sampling period in units of 0.1ms
              param        - system parameter number
  Returns:    int          - 0 on success, -1 on error (with errno set)

  This function sets up the data recorder in the DES, so that it is ready
  to record the values of the system parameter or status variable param
  every sampleperiod * 0.1ms for 256 samples.

  Note that, due to a limitation of the implementation, sampleperiod must
  be less than 292 (29.2ms).  This is so that the entire data packet
  returned by des_recorddata() fits in the DES_VTIME time-out (7.5sec).

  As with all functions in this API (apart from des_open()), zero is
  returned on success.  If an error occurs, -1 is returned and errno is
  set appropriately; possible errors include ETIMEDOUT (connection timed
  out) and EPROTO (protocol error).
*/
extern int des_setuprecorder (int fd, uint16_t sampleperiod,
			      des_parameter_t param);


/*
  Function:   des_recorddata - Start recording data for 256 samples
  Parameters: fd      - file descriptor previously opened with des_open()
              jumpamp - jump amplitude to write to system parameter
              data    - pointer to returned data (uint16_t[256])
  Returns:    int     - 0 on success, -1 on error (with errno set)

  This function starts recording data on the DES for 256 samples.  If
  jumpamp is not zero, it is written out to the system parameter
  previously indicated by a call to des_setuprecorder() just before
  recording starts.  Sampled data is returned to the 256-element array
  pointed to by data.

  As with all functions in this API (apart from des_open()), zero is
  returned on success.  If an error occurs, -1 is returned and errno is
  set appropriately; possible errors include ETIMEDOUT (connection timed
  out) and EPROTO (protocol error).
*/
extern int des_recorddata (int fd, uint16_t jumpamp, des_recordeddata_t data);


/*
  Function:   des_readnvariables - Read a number of parameters synchronously
  Parameters: fd       - file descriptor previously opened with des_open()
              num      - number of variables to read
              params[] - array of system parameter numbers
              data[]   - array of results
  Returns:    int      - 0 on success, -1 on error (with errno set)

  This function reads a number of system parameters or status variables
  from the DES's temporary memory and places them into the data[] array.
  The system parameter or status variable numbers should be placed into a
  constant array, params[]; the results are stored in data[] in the same
  order.  num is the size of the params[] and data[] arrays; it must be
  between 1 and 256 inclusive.

  The effect of calling des_readnvariables() is similar to calling
  des_readtempparam() for each parameter/variable number, except that in
  the former case all values are queried at the same moment in time (ie,
  synchronously).

  As with all functions in this API (apart from des_open()), zero is
  returned on success.  If an error occurs, -1 is returned and errno is
  set appropriately; possible errors include ETIMEDOUT (connection timed
  out) and EPROTO (protocol error).  EINVAL (invalid parameter) is
  returned in errno if params or data is a NULL pointer, or if num is out
  of range (1-256 inclusive).
*/
extern int des_readnvariables (int fd, int num, const des_parameter_t params[],
			       uint16_t data[]);

#ifdef __cplusplus
}
#endif

#endif // __MAXON_DES_API_H
