/********************************  espmsg.h  *******************************
 * $Source: /home/cvs/ESP/gen2/software/msp430/dwarves/espmsg.h,v $
 *  Copyright (C) 2003 MBARI
 *
 *  MBARI Proprietary Information. All rights reserved.
 * $Id: espmsg.h,v 1.15 2004/11/19 05:13:23 brent Exp $
 *
 * ESP "dwarf" node command message formats
 *
 *  These messages are defined in terms of structs without pad
 *  bytes and where all multibyte quantities are assumed to be
 *  stored in "network" byte order e.g. most significant bytes first
 *  On the MSP430, this means that, in practice, these struts 
 *  cannot be used and are primarily here for documentation purposes.
 *
 *****************************************************************************/

#ifndef espmsg_h
#define espmsg_h

#include "types.h"    //standard types
#include "servobits.h" //constants for servo and shaft control and msgs
#include "heater.h"
enum ESPmsgCmd {  //message types -- first byte of each ESP dwarf command

  ESPmsgNOP,          //do nothing
  ESPmsgEchoCmd,      //echo received request to back source node
  ESPmsgDupAdr,       //broadcast to host to warn it of duplicate I2C addresses
  
  solenoidConfigCmd,    //configure solenoid control
  solenoidStatusCmd,    //solenoid status query/reply
  solenoidPulseCmd,     //pulse solenoids
  solenoidHoldCmd,      //hold solenoids
  
  shaftConfigCmd,       //configure shaft control
  shaftStatusCmd,       //shaft status query/reply
  shaftRotateCmd,       //move shaft
  
  thermalConfigCmd,     //configure thermal control
  thermalStatusCmd,     //query/reply
  thermalProgramCmd,    //used to be define/query thermal program
  thermalRunCmd,        //run thermal program

  servoConfigCmd,       //configure servo channel
  servoStatusCmd,       //servo status query/reply
  servoAbsMoveCmd,      //move servo to absolute position
  servoRelMoveCmd,      //move servo relative to current position
  servoOnCmd,         //hold current position
  servoGoalCmd,         //query/reply current servo goal
  servoGripCmd,		//close gripper
  servoReleaseCmd,	//open gripper
  servoGPIOCmd,		//read/write general purpose bits
  servoOffCmd,			//turn of PWM
 
  ESPmsgCmds 
};


/**********  Solenoid Control Messages  ********************/

struct ESPdupMsg  { //duplicate address message
  enum ESPmsgCmd cmd;        //ESPmsgDupAdr
  byte  dupAdr;         //source address to which two or more nodes respond
};

struct solenoidConfigMsg  { //each solenoid tic = 1/64 seconds
  enum ESPmsgCmd cmd;         //solenoidConfigCmd
  byte  pulseDuration;  // in tics
};

struct solenoidConfigRequest {
  byte dst;
  enum ESPmsgCmd cmd;         //solenoidConfigCmd
};

struct solenoidConfigReply { 
  enum ESPmsgCmd cmd;      //solenoidConfigCmd
  byte pulseDuration;      // in tics
  byte quanity;            //# of solenoids available
};

struct solenoidStatusRequest {
  byte dst;
  enum ESPmsgCmd cmd;         //solenoidStatusCmd
};

struct solenoidStatusReply { 
  enum ESPmsgCmd cmd;             //solenoidStatusCmd
  byte pulseWidthRemaining; //# of ticks before the end of the current pulse
  byte state[1];            //4 solenoid states per byte (variable length array)
};

//adjacent pairs of bits in each state byte:
//(lowest numbered channel corresponds to the least significant bit pair)
enum {
  solenoidStateOFF,
  solenoidStateUP,
  solenoidStateDOWN,
  solenoidStateReserved
};  


struct solenoidPulseMsg {
  enum ESPmsgCmd cmd;       //solenoidPulseCmd
  byte direction[1];        //4 pulse commands per byte (variable length array)
};

struct solenoidHoldMsg {
  enum ESPmsgCmd cmd;       //solenoidPulseCmd
  byte direction[1];        //4 pulse commands per byte (variable length array)
};

//adjacent pairs of bits in each direction byte:
//(lowest numbered channel corresponds to the least significant bit pair)
enum {
  solenoidDirectionNOP,
  solenoidDirectionUP,
  solenoidDirectionDOWN,
  solenoidDirectionSTOP
};  



/**********  Shaft Rotation Control Messages  ********************/

struct shaftConfigMsg  { //each shaft tic = 1/64 seconds
  enum ESPmsgCmd cmd;    //shaftConfigCmd
  byte     shaftNumber;  //zero is the 1st shaft
  umsg16   maxError;     //max acceptable positioning error
  byte     maxCurrent;   //maximum motor current
};

struct shaftConfigRequest {
  enum ESPmsgCmd cmd;    //shaftConfigCmd
  byte     shaftNumber;  //shaft on which configuration data is requested
};

struct shaftConfigReply  { //each shaft tic = 1/64 seconds
  enum ESPmsgCmd cmd;    //shaftConfigCmd
  umsg16   maxError;     //max acceptable positioning error
  byte     maxCurrent;   //maximum motor current
};

struct shaftStatusRequest { 
  enum ESPmsgCmd cmd;   //shaftStatusCmd
  byte     shaftNumber; //shaft on which status is requested
  umsg16   repeatRate;  //optional repeat rate (tics/report)
};

struct shaftStatusReply { 
  enum ESPmsgCmd cmd;   //shaftStatusCmd
  umsg16   angle;       //current angle [0..65535]
  //remaining fields sent only if shaft is moving
  umsg16   goal;        //goal angle [0..65535]
  int8     current;     //current shaft motor current
};

struct shaftRotateRequest {
  enum ESPmsgCmd cmd;   //shaftRotateCmd
  byte     shaftNumber;
  umsg16   goal;        //angle in counts (2^16 == 360 degrees)
  int8     direction;   //+1 = CW, -1 = CCW, 0 = fastest way
};

  
struct shaftRotateReply {
  enum ESPmsgCmd cmd;      //shaftRotateCmd
  umsg16   angle;          //actual angle in counts (2^16 == 360 degrees)
  enum shaftReason reason; //optional error code byte (non-zero implies error)
};


/**********  Servo Control Messages  ********************/

struct servoConfig {  //core configuration parameters (not a message in itself!)
  enum servoOption optionMask; //configuration options
  servoPosition thresholdOffset; //at threshold goal := position + this
  servoPosition maxPositionErr;  //max acceptable position error in counts
  msg16PID  gain;         //PID gains
  umsg16    maxSpeed;     //max allowable speed  (counts/tic)
  umsg16    minSpeed;     //min permissible progress in count/tic)
  uint16    accel;        //(counts/tic**2)
  uint8     maxCurrent;     //max motor drive current
  int8      maxDeltaPress;  //max difference between inlet and outlet press.
  uint8     maxInPress;     //max inlet pressure
  uint8     maxOutPress;    //max outlet pressure
  uint8     minInPress;     //min inlet pressure
  uint8     minOutPress;    //min outlet pressure
};

struct servoConfigMsg {   //one servo tic == 1/32 seconds
  enum ESPmsgCmd  cmd;    //servoConfigCmd
  byte      channel;      //servo channel 0 or 1
  struct servoConfig item;  //configuration block
};

struct servoOffMsg {  //request channel hold its current position
  enum ESPmsgCmd  cmd;     //servoOffCmd
  byte      channel;       //servo channel 0 or 1
};

struct servoConfigRequest {
  enum ESPmsgCmd  cmd;       //servoConfigCmd
  byte        channel;       //servo channel 0 or 1
};

struct servoConfigReply {   //one servo tic == 1/32 seconds
  enum ESPmsgCmd  cmd;      //servoConfigCmd
  struct servoConfig item;  //configuration block
};
  
struct servoStatusRequest {  //request channel's current status
  enum ESPmsgCmd  cmd;       //servoStatusCmd
  byte      channel;      //servo channel 0 or 1
  umsg16    repeatRate;   //optional repeat rate in tics/report
};

struct servoStatusReply {  //channel's current status
  enum ESPmsgCmd   cmd;       //servoStatusCmd
  struct servoStatus state;   //core servoStatus
};

struct servoMoveRequest {  //absolute or relative move
  enum ESPmsgCmd  cmd;        //servoAbsMoveCmd or servoRelMoveCmd
  byte      channel;
  servoPosition goal;     //target position or relative offest
};

struct servoMoveReply {    //when move is complete...
  enum ESPmsgCmd   cmd;       //servoAbsMoveCmd or servoRelMoveCmd
// subsequent fields are present only if an error occurred
  enum servoReason    reason;       //why the command aborted
  struct servoStatus  stateAtAbort; //detailed status of servo at that instant
};

struct servoOnRequest {  //request channel hold its current position
  enum ESPmsgCmd  cmd;     //servoHoldCmd
  byte      channel;       //servo channel 0 or 1
};

struct servoOnReply {    //when servo hold fails...
  enum ESPmsgCmd   cmd;       //servoAbsMoveCmd or servoRelMoveCmd
// subsequent fields are present only if an error occurred
  enum servoReason    reason;       //why the command aborted
  struct servoStatus  stateAtAbort; //detailed status of servo at that instant
};

struct servoGoalRequest {  //query current servo goal
  enum ESPmsgCmd   cmd;       //servoGoalCmd
  byte             channel;   //servo channel 0 or 1
};

struct servoGoalReply {
  enum ESPmsgCmd   cmd;       //servoGoalCmd
  enum ESPmsgCmd   servoMode; //Hold, AbsMove, RelMove, or ESPmsgNOP if off
  servoPosition    goal;      //omitted if servoMode == ESPmsgNOP
};

struct servoGPIORequest{
  enum ESPmsgCmd   cmd;       //servoGPIOCmd
  byte channel;
};
struct servoGPIOReply{
  enum ESPmsgCmd   cmd;       //servoGPIOCmd
  byte bitMask;		//LSB is the only bit used
};
struct servoGPIOMsg{
  enum ESPmsgCmd   cmd;       //servoGPIOCmd
  byte channel;
  byte bitMask;		//LSB is the only bit used
};
struct servoGripRequest{
  enum ESPmsgCmd   cmd;       //servoGrip or Release
  byte channel;  
};
struct servoGripReply{
  enum ESPmsgCmd   cmd;       //servoGrip or Release
  enum servoReason reason;	//error code see docs  
};

/**********  Thermal Control Messages  ********************/


struct thermalConfigMsg  { 
  enum ESPmsgCmd cmd;   //thermalConfigCmd
  msg16PID  heating, cooling;  //PID gains for heating and cooling 
};

struct thermalConfigRequest {  //response is a struct ThermalConfigMsg
  enum ESPmsgCmd cmd;   //thermalConfigCmd
};
struct thermalConfigReply {   //one servo tic == 1/32 seconds
  enum ESPmsgCmd  cmd;      //servoConfigCmd
  msg16PID  heating, cooling;  //PID gains for heating and cooling
};
  

struct thermalStatusRequest {
  enum ESPmsgCmd cmd;   //thermalStatusCmd
  umsg16   repeatRate;  //optional repeat rate (tics/report) 
};

struct thermalStatusReply {
  enum ESPmsgCmd cmd;   //thermalStatusCmd
  msg16    currentTemperature;   //hundredths of degrees Celsius
  //subsequent fields only appear if a thermal program is running
  umsg16   elapsedTics;          //tics since start of the current program
  byte     heaterPwr, coolerPwr; //current heater and cooler power levels
            //0 == off, 0xff == full power
};

struct thermalRunRequest {
  enum ESPmsgCmd  cmd;        //thermalRunCmd
  thermalStep step[1];  //variable length array
};

struct thermalRunReply {
  enum ESPmsgCmd  cmd;        //thermalRunCmd
  byte completionCode ;  //non-zero implies error
  umsg16  elapsedTics;  //cmd duration
};

struct thermalProgramRequest {  //return the thermal program
  enum ESPmsgCmd  cmd;        //thermalProgramCmd
};

struct thermalProgramReply {  //same struct as thermalRunRequest
  enum ESPmsgCmd  cmd;       //thermalProgramCmd
  thermalStep step[1];  //variable length array
};


#endif
