#ifndef SHAFTENCODER_H
#define SHAFTENCODER_H

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

class TGLabel;

class ShaftEncoder : public NodeDrv
{
private:
    LWORDS_t fPos;   // ticks
    WORDS_t  fVel;   // ticks per 5ms
    WORDS_t  fAcc;   // ticks per 25ms^2
    WORDS_t  fTurn;  // Number of turn
    LWORD_t  fTicks; // Number of ticks per turn
    WORD_t   fTurns; // Number of possible turns

    TGLabel  *fLabel;     //
    LWORDS_t  fUpdPos;    // ticks
    //    WORDS_t   fUpdVel;    // ticks per 5ms
    //    WORDS_t   fUpdAcc;    // ticks per 25ms^2

    bool fPosHasChanged;  //!

    Timer fTime;

    void HandlePDOType0(BYTE_t *data, timeval_t *tv);
    void HandlePDOType1(BYTE_t *data, timeval_t *tv);
    void HandlePDOType2(BYTE_t *data, timeval_t *tv);

    void ReqPos();

    void Init();
    void CheckConnection();

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

    void StopDevice();

    void SetDisplay(TGLabel *label) { fLabel = label; }

    void HandleSDO(WORD_t idx, BYTE_t subidx, LWORD_t val, timeval_t *tv);
    void HandleSDOOK(WORD_t idx, BYTE_t subidx, LWORD_t data, timeval_t *tv);
    /*
     void HandleSDOOK(WORD_t idx, BYTE_t subidx, timeval_t *tv) { NodeDrv::HandleSDOOK(idx, subidx, tv); }
     void HandleSDOError(LWORD_t data)           { NodeDrv::HandleSDOError(data); }
     */
    void HandlePDO1(BYTE_t *data, timeval_t *tv) { HandlePDOType2(data, tv); }
    void HandlePDO2(BYTE_t *data, timeval_t *tv) { HandlePDOType2(data, tv); }

    LWORDS_t GetPos() { return IsZombieNode() ? 0 : fPos+fTurn*fTicks; } // FIXME? 0?
    LWORD_t  GetPhysRes() { return fTicks; }

    double GetTime();
    double GetMjd();

    void SetPreset(LWORD_t pre=0);

    void DisplayVal();

    bool PosHasChanged() const { return fPosHasChanged; }
    void ResetPosHasChanged() { fPosHasChanged = false; }

    ClassDef(ShaftEncoder, 0)
};

#endif
