/*
 *
 * $Id: ax12.h 1 2008-07-30 09:24:06Z mschneider $
 * $URL: svn://localhost/Bioloid/trunk/ax12.h $
 
 * \version   $Rev: 1 $
 * \author    Markus Schneider
 * \date      17.07.08
 *
 */

#ifndef AX12_H
#define AX12_H

#include "dynamixel_defs.h"

//--- Control Table Address ---
#define AX12_MODEL_NUMBER_L           0
#define AX12_MODOEL_NUMBER_H          1
#define AX12_VERSION                  2
#define AX12_ID                       3
#define AX12_BAUD_RATE                4
#define AX12_RETURN_DELAY_TIME        5
#define AX12_CW_ANGLE_LIMIT_L         6
#define AX12_CW_ANGLE_LIMIT_H         7
#define AX12_CCW_ANGLE_LIMIT_L        8
#define AX12_CCW_ANGLE_LIMIT_H        9
#define AX12_SYSTEM_DATA2            10
#define AX12_LIMIT_TEMPERATURE       11
#define AX12_MIN_LIMIT_VOLTAGE       12
#define AX12_MAX_LIMIT_VOLTAGE       13
#define AX12_MAX_TORQUE_L            14
#define AX12_MAX_TORQUE_H            15
#define AX12_RETURN_LEVEL            16
#define AX12_ALARM_LED               17
#define AX12_ALARM_SHUTDOWN          18
#define AX12_OPERATING_MODE          19
#define AX12_DOWN_CALIBRATION_L      20
#define AX12_DOWN_CALIBRATION_H      21
#define AX12_UP_CALIBRATION_L        22
#define AX12_UP_CALIBRATION_H        23
#define AX12_TORQUE_ENABLE           24
#define AX12_LED                     25
#define AX12_CW_COMPLIANCE_MARGIN    26
#define AX12_CCW_COMPLIANCE_MARGIN   27
#define AX12_CW_COMPLIANCE_SLOPE     28
#define AX12_CCW_COMPLIANCE_SLOPE    29
#define AX12_GOAL_POSITION_L         30
#define AX12_GOAL_POSITION_H         31
#define AX12_MOVING_SPEED_L          32
#define AX12_MOVING_SPEED_H          33
#define AX12_TORQUE_LIMIT_L          34
#define AX12_TORQUE_LIMIT_H          35
#define AX12_PRESENT_POSITION_L      36
#define AX12_PRESENT_POSITION_H      37
#define AX12_PRESENT_SPEED_L         38
#define AX12_PRESENT_SPEED_H         39
#define AX12_PRESENT_LOAD_L          40
#define AX12_PRESENT_LOAD_H          41
#define AX12_PRESENT_VOLTAGE         42
#define AX12_PRESENT_TEMPERATURE     43
#define AX12_REGISTERED_INSTRUCTION  44
#define AX12_MOVING                  46
#define AX12_LOCK                    47
#define AX12_PUNCH_L                 48
#define AX12_PUNCH_H                 49

#include "dynamixel.h"

class AX12 : public Dynamixel
{
public:
  // Constuctor, needs ID of Dynamixel actuators and a serial connection
  AX12(const byte id, Connection *conn);
  
  // ID. The unique ID number assigned to each Dynamixel actuators for identifying them. 
  // Different IDs are required for each Dynamixel actuators that are on the same network.
  virtual int setID(const byte id);  
  
  // Model Number.   For AX-12, this value is 0X000C (12) 
  virtual int getModelNumber(word *buff) const;
  
  // Firmware Version
  virtual int getVersion(byte *buff) const;
  
  // Baud Rate. Determines the communication speed. The computation is done by the 
  // following formula. Speed (BPS) = 2000000 / (Address4 + 1) 
  virtual int getBaudRate(byte *buff) const;
  virtual int setBaudRate(const byte value) const;  
  
  // Return Delay Time. The time it takes for the Status Packet to return after the Instruction 
  // Packet is sent. The delay time is given by 2uSec * Address5 value.
  virtual int getReturnDelayTime(byte *buff) const;
  virtual int setReturnDelayTime(const byte value) const; 
  
  // Operating Angle Limit. Sets the Dynamixel actuator’s operating angle range. The Goal 
  // Position needs to be within the range of: CW Angle Limit <= Goal Position <= CCW 
  // Angle Limit. An Angle Limit Error will occur if the Goal Position is set outside this range 
  // set by the operating angle limits. 
  virtual int getCWAngleLimit(word *buff) const;
  virtual int getCCWAngleLimmit(word *buff) const;
  virtual int setCWAngleLimit(const word value) const;
  virtual int setCCWAngleLimmit(const word value) const;  
  
  // the Highest Limit Temperature. The upper limit of the Dynamixel actuator’s operating 
  // temperature. If the internal temperature of the Dynamixel actuator gets higher than this 
  // value, the Over Heating Error Bit (Bit 2 of the Status Packet) will return the value 1, and 
  // an alarm will be set by Address 17, 18. The values are in Degrees Celsius. 
  virtual int getLimitTemperature(byte *buff) const;
  virtual int setLimitTemperature(const byte value) const;
  
  // the Lowest (Highest) Limit Voltage. The upper and lower limits of the Dynamixel 
  // actuator’s operating voltage. If the present voltage (Address 42) is out of the specified 
  // range, a Voltage Range Error Bit  (Bit 0 of the Status Packet) will return the value 1, 
  // and an alarm will be set by Address 17, 18. The values are 10 times the actual voltage 
  // value. For example, if the Address 12 value is 80, then the lower voltage limit is set to 8V.     
  virtual int getMinLimitVoltage(byte *buff) const;
  virtual int getMaxLimitVoltage(byte *buff) const;
  virtual int setMinLimitVoltage(const byte value) const;
  virtual int setMaxLimitVoltage(const byte value) const;  
  
  // Max Torque. The maximum torque output for the Dynamixel actuator. When this value 
  // is set to 0, the Dynamixel actuator enters the Free Run mode. There are two locations 
  // where this maximum torque limit is defined; in the EEPROM (Address 0X0E, 0x0F) and 
  // in the RAM (Address 0x22, 0x23). When the power is turned on, the maximum torque 
  // limit value defined in the EEPROM is copied to the location in the RAM. The torque of 
  // the Dynamixel actuator is limited by the values located in the 
  // RAM (Address 0x22, 0x23).   
  virtual int getMaxTorque(word *buff) const;
  virtual int setMaxTorque(const word value) const;
  
  // Status Return Level. Determines whether the Dynamixel actuator will return a Status 
  // Packet after receiving an Instruction Packet. 
  // +-----------+-----------------------------------------+
  // | Address16 | Returning the Status Packet             |
  // |     0     | Do not respond to any instructions      |
  // |     1     | Respond only to READ_DATA instructions  |
  // |     2     | Respond to all instructions             |
  // +-----------+-----------------------------------------+
  // In the case of an instruction which uses the Broadcast ID (0XFE) the Status Packet will 
  // not be returned regardless of the Address 0x10 value. 
  virtual int getReturnLevel(byte *buff) const;
  virtual int setReturnLevel(const byte value) const;
  
  // Alarm LED. If the corresponding Bit is set to 1, the LED blinks when an Error occurs. 
  // +-------+-----------------------------------------------------------------+
  // | Bit   | Function                                                        |
  // | Bit 7 | 0                                                               |
  // | Bit 6 | If set to 1, the LED blinks when an Instruction Error occurs    |
  // | Bit 5 | If set to 1, the LED blinks when an Overload Error occurs       |
  // | Bit 4 | If set to 1, the LED blinks when a Checksum Error occurs        |
  // | Bit 3 | If set to 1, the LED blinks when a Range Error occurs           |
  // | Bit 2 | If set to 1, the LED blinks when an Overheating Error occurs    |
  // | Bit 1 | If set to 1, the LED blinks when an Angle Limit Error occurs    |
  // | Bit 0 | If set to 1, the LED blinks when an Input Voltage Error occurs  |
  // +-------+-----------------------------------------------------------------+
  // This function operates following the “OR” logical operation of all bits. For example, if the 
  // value is set to 0X05, the LED will blink when an Input Voltage Error occurs or when an 
  // Overheating Error occurs. Upon returning to a normal condition from an error state, the 
  // LED stops blinking after 2 seconds.     
  virtual int getAlarmLed(byte *buff) const;
  virtual int setAlarmLed(const byte value) const;
  
  // Alarm Shutdown. If the corresponding Bit is set to a 1, the Dynamixel actuator’s torque 
  // will be turned off when an error occurs. 
  // +-------+-----------------------------------------------------------------+
  // | Bit   | Function                                                        |
  // | Bit 7 | 0                                                               |
  // | Bit 6 | If set to 1, torque off when an Instruction Error occurs        |
  // | Bit 5 | If set to 1, torque off when an Overload Error occurs           |
  // | Bit 4 | If set to 1, torque off when a Checksum Error occurs            |
  // | Bit 3 | If set to 1, torque off when a Range Error occurs               |
  // | Bit 2 | If set to 1, torque off when an Overheating Error occurs        |
  // | Bit 1 | If set to 1, torque off when an Angle Limit Error occurs        |
  // | Bit 0 | If set to 1, torque off when an Input Voltage Error occurs      |
  // +-------+-----------------------------------------------------------------+
  // This function operates following the “OR” logical operation of all bits. However, unlike 
  // the Alarm LED, after returning to a normal condition, it maintains the torque off status. 
  // To recover, the Torque Enable (Address0X18) needs to be reset to 1.   
  virtual int getAlarmShutdown(byte *buff) const;
  virtual int setAlarmShutdown(const byte value) const;
  
  // Calibration. Data used for compensating for the differences between the 
  // potentiometers used in the Dynamixel units. The user cannot change this data. 
  // The following (from Address 0x18) is in the RAM area. 
  virtual int getDownCalibration(word *buff) const;  
  virtual int getUpCalibration(word *buff) const;
  
  // Torque Enable. When the power is first turned on, the Dynamixel actuator enters the 
  // Torque Free Run condition (zero torque). Setting the value in Address 0x18 to 1 enables 
  // the torque. 
  virtual int getTorqueEnable(byte *buff) const;
  virtual int setTorqueEnable(const byte value) const;
  
  // LED.  The LED turns on when set to 1 and turns off if set to 0. 
  virtual int getLed(byte *buff) const;
  virtual int setLed(const byte value) const;
  
  // Compliance Margin and Slope. The compliance of the Dynamixel actuator is defined 
  // by setting the compliance Margin and Slope. This feature can be utilized for absorbing 
  // shocks at the output shaft.
  virtual int getCWComplianceMargin(byte *buff) const;
  virtual int getCCWComplicanceMargin(byte *buff) const;
  virtual int getCWComplianceSlope(byte *buff) const;
  virtual int getCCWComplicanceSlope(byte *buff) const; 
  virtual int setCWComplianceMargin(const byte value) const;
  virtual int setCCWComplicanceMargin(const byte value) const;
  virtual int setCWComplianceSlope(const byte value) const;
  virtual int setCCWComplicanceSlope(const byte value) const;   
  
  // Goal Position Requested angular position for the Dynamixel actuator output to move to. 
  // Setting this value to 0x3ff moves the output shaft to the position at 300°. 
  virtual int getGoalPosition(word *buff) const;
  virtual int setGoalPosition(const word value) const;

  // Moving Speed. Sets the angular velocity of the output moving to the Goal Position. 
  // Setting this value to its maximum value of 0x3ff moves the output with an angular 
  // velocity of 114 RPM, provided that there is enough power supplied (The lowest velocity 
  // is when this value is set to 1. When set to 0, the velocity is the largest possible for the 
  // supplied voltage, e.g. no velocity control is applied.) 
  virtual int getMovingSpeed(word *buff) const;
  virtual int setMovingSpeed(const word value) const;
  
  // Gets both Position and Speed with 1 Packet
  virtual int getGoalPositionSpeed(word *position, word *speed) const;
  
  // Sets both Position and Speed with 1 Packet
  virtual int setGoalPositionSpeed(const word position, const word speed) const;  
  
  virtual int getTorqueLimit(word *buff) const;
  virtual int setTorqueLimit(const word value) const;
  
  // Present Position. Current angular position of the Dynamixel actuator output.
  virtual int getPresentPosition(word *buff) const;
  
  // Present Speed. Current angular velocity of the Dynamixel actuator output. 
  virtual int getPresentSpeed(word *buff) const;
  
  // Gets present position and speed with 1 packet
  virtual int getPresentPositionSpeed(word *position, word *speed) const;

  // Gets present position, load and speed with 1 packet
  virtual int getPresentPositionSpeedLoad(word *position, word *speed, word *load) const;  
  
  // Present Load. The magnitude of the load on the operating Dynamixel actuator. Bit 10 is 
  // the direction of the load. 
  // +-------+-------+----------------+---+---+---+---+---+---+---+---+---+---+
  // |  BIT  | 15~11 |       10       | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
  // | Value |   0   | Load Direction |               Load Value              |
  // +-------+-------+----------------+---+---+---+---+---+---+---+---+---+---+ 
  // Load Direction = 0 : CCW Load,   Load Direction = 1: CW Load 
  virtual int getPresentLoad(word *buff) const;
  
  // Present Voltage. The voltage currently applied to the Dynamixel actuator. The value is 
  // 10 times the actual voltage. For example, 10V is represented as 100 (0x64). 
  virtual int getPresentVoltage(byte *buff) const;
  
  // Present Temperature. The internal temperature of the Dynamixel actuator in Degrees 
  // Celsius. 
  virtual int getPresentTemperature(byte *buff) const;
  
  // Registered Instruction. Set to 1 when an instruction is assigned by the REG_WRITE 
  // command. Set to 0 after it completes the assigned instruction by the Action command.  
  virtual int getRegisteredInstruction(byte *buff) const;
  virtual int setRegisteredInstruction(const byte value) const;
  
  // Moving. Set to 1 when the Dynamixel actuator is moving by its own power. 
  virtual int getMoving(byte *buff) const;
  
  // Lock. If set to 1, only Address 0x18 to 0x23 can be written to and other areas cannot. 
  // Once locked, it can only be unlocked by turning the power off. 
  virtual int getLock(byte *buff) const;
  virtual int setLock(const byte value) const;
  
  // Punch. The minimum current supplied to the motor during operation. The initial value is 
  // set to 0x20 and its maximum value is 0x3ff.   
  virtual int getPunch(word *buff) const;
  virtual int setPunch(const word value) const; 

};

#endif
