#ifndef MACS_H
#define MACS_H

#include <TObject.h>

#include "nodedrv.h"
#include "base/timer.h"

class Macs : public NodeDrv, public TObject
{
private:
    BYTE_t   fMacId;

    LWORD_t  fVelRes;
    LWORDS_t fVel;

    LWORDS_t fPos;
    Timer    fPosTime;

    LWORDS_t fPdoPos;
    Timer    fPdoTime;

    BYTE_t   fPosActive;
    BYTE_t   fRpmActive;

    TTimer  *fTimeout;
    Bool_t   fTimerOn;
    LWORD_t  fGuardTime;
    double   fTimeoutTime;

    LWORD_t string(BYTE_t b0=0, BYTE_t b1=0, BYTE_t b2=0, BYTE_t b3=0)
    {
        return (LWORD_t)(b0<<24 | b1<<16 | b2<<8 | b3);
    }

    void ResetTimeout();
    Bool_t HandleTimer(TTimer *t);

public:
    Macs(const BYTE_t nodeid, const char *name=NULL, MLog &out=gLog);
    virtual ~Macs();

    void InitDevice(Network *);

    void StartDevice();
    void StopDevice();

    void HandleSDO(WORD_t idx, BYTE_t subidx, LWORD_t val, struct timeval *tv);
    void HandleSDOOK(WORD_t idx, BYTE_t subidx);
    void HandleSDOError(LWORD_t data)           { NodeDrv::HandleSDOError(data); }

    void HandlePDO1(BYTE_t *data, struct timeval *tv);
    void HandlePDO2(BYTE_t *data, struct timeval *tv);

    void SendMsg(BYTE_t data[6]);
    void SendMsg(BYTE_t d0=0, BYTE_t d1=0, BYTE_t d2=0,
                 BYTE_t d3=0, BYTE_t d4=0, BYTE_t d5=0);

    void ReqPos();
    void ReqVel();
    void ReqAxEnd();
    void ReqVelRes();
    void SetHome(LWORDS_t pos=0, WORD_t maxtime=25);
    void SetAcceleration(LWORD_t acc);
    void SetDeceleration(LWORD_t dec);
    void SetVelocity(LWORD_t vel);
    void SetNoWait(BYTE_t flag=TRUE);
    void SetRpmMode(BYTE_t mode=TRUE);
    void SetRpmVelocity(LWORDS_t cvel);
    void SetPDO1On(BYTE_t flag=TRUE);
    void SetPosEndswitch(LWORDS_t val);
    void SetNegEndswitch(LWORDS_t val);

    void EnableEndswitches(bool neg=true, bool pos=true);

    void StartVelSync();
    void StartPosSync();

    void StartRelPos(LWORDS_t pos);
    void StartAbsPos(LWORDS_t pos);

    void SetTimeoutTime(LWORD_t ms);
    void ReqTimeoutTime();

    void EnableTimeout(bool enable=true, LWORDS_t ms=-1);

    void StopMotor();

    int IsPositioning() { return fPosActive; }

    double GetTime();
    double GetMjd();

    double GetPdoTime();
    double GetPdoMjd();

    LWORDS_t GetPdoPos() { return fPdoPos; }

    LWORDS_t GetPos()    { return fPos; }
    LWORDS_t GetVel()    { return fVel; }
    LWORD_t  GetVelRes() { return fVelRes; } // Velocity units (would be 100 for %)

    void HandleError();
};

#endif
