//----------------------------------------------------
/**
	\file		ctk/inc/stepper.h
	\ingroup	other
	\ingroup	all
	\brief		Nadstavba nad knihovnou krokoveho motoru pro beh o dany pocet kroku, rampovani
				<<< ALL >>>

	\author		ConTeK s.r.o., Ing. Pavel Bazika
	\version	01.01
	\date		12.01.2007

	\todo	dodat komentare nutno pockat na dokonceni stepper.c
*/
//----------------------------------------------------
#ifndef _STEPPER_H_
#define _STEPPER_H_

#include <ctktypes.h>

/////////////////////////////////////////////////////////////

//! Stav pohybu krokoveho motoru
typedef enum _STEPPER_STATE
{
	SS_STOP = 0,
	SS_RAMP_UP_START,
	SS_RAMP_UP,
	SS_CONSTANT_SPEED,
	SS_RAMP_DOWN,
	SS_SLOW_TO_POS,
	SS_RAMP_DOWN_STOP,
	SS_CHANGE_DIR
} STEPPER_STATE;

typedef uint32_t	STEPPER_REG;						//!< Typ uzivany pro citac nanokroku
typedef uint64_t	STEPPER_DOUBLEREG;					//!< Typ dvojnasobne sirky nez STEPPER_REG

static const uint32_t STEPPER_REG_MASK = 0xFFFFFFFF;	//!< Maska na STAPPER_REG
static const uint8_t STEPPER_REG_LENGTH = 32;			//!< Sirka STEPPER_REG v bitech

//! \name Definice smeru krokoveho motoru
//@{
static const bool_t SD_CW = FALSE;						//!< Clockwise
static const bool_t SD_CCW = TRUE;						//!< Counterclockwise
//@}

//! \name Konstanty povoleni ci zakazu rampovani
//@{
static const bool_t STEPPER_RAMP_ENABLED = TRUE;
static const bool_t STEPPER_RAMP_DISABLED = FALSE;
//@}

//! Typ smeru krokoveho motoru
typedef bool_t STEPPER_DIR;

/////////////////////////////////////////////////////////////
// metody

struct _STEPPER_CTX;

//! Nastaveni smeru krokoveho motoru
typedef void (*smSetDirection) (const struct _STEPPER_CTX * const _ctx, const STEPPER_DIR _dir);

//! Vola se pro provedeni mikrokroku (v prvni fazi mikrokroku)
typedef void (*smStepCommand) (const struct _STEPPER_CTX * const _ctx);

//! Vola se ve druhe fazi mikrokroku
typedef void (*smStepRelease) (const struct _STEPPER_CTX * const _ctx);

//! Pri kazdem zavolani je zjisten stav ovladace krokoveho motoru
typedef void (*smGetStatus) (struct _STEPPER_CTX * const _ctx);

//! Zjisti, kolik mikrokroku zahrnuje 1 krok
typedef uint8_t (*smGetMStepsInStep) (const struct _STEPPER_CTX * const _ctx);

//! Nastaveni smeru krokoveho motoru
typedef void (*smSetPower) (const struct _STEPPER_CTX * const _ctx, uint8_t _power);

/////////////////////////////////////////////////////////////
// callbacky

//! Volan pri shode citace kroku s danou hodnotou
typedef void (*smcbStepCompare) (struct _STEPPER_CTX * const _ctx);

//! Kontext knihovny krokovych motoru
typedef struct _STEPPER_CTX
{
	volatile STEPPER_STATE	State;					//!< Stav automatu rizeni krokoveho motoru
	bool_t			flRelease;						//!< Priznak release faze - druha faze mikrokroku
	bool_t			flEmptyTick;					//!< Nasledujici tik probehne naprazdno
	bool_t			flRampEnabled;					//!< Priznak povoleni rampovani
	bool_t			flReleaseEnabled;				//!< Priznak povoleni faze release
	uint8_t			MicrostepCount;					//!< pocet mikrokroku do jednoho kroku
	STEPPER_REG		Counter, Add;					//!< Citac aktualni hodnoty a delta, o kterou se tento pricita
	STEPPER_REG		MinSpeed, RqSpeed, Accel;		//!< Pozadavky na pokyb motoru - pocatecni rychlost, pozadovana, akcelerace (steps/s-1)
	STEPPER_REG		MPosition;						//!< Aktualni pozice v mikrokrocich
	int16_t			Position;						//!< Aktualni pozice v krocich
	STEPPER_DIR		Direction;						//!< Aktualne nastaveny smer

	STEPPER_REG		WorkingTargetMPos;				//!< Pracovni cilova pozice v mikrokrocich
	STEPPER_DIR		PosDir;							//!< Smer, pri kterem pozice roste

	smSetDirection	HWSetDirection;					//!< Metoda pro nastaveni smeru (nizsi vrstva)
	smStepCommand	HWStepCommand;					//!< Metoda pro provedeni prvni faze mikrokroku (nizsi vrstva)
	smStepRelease	HWStepRelease;					//!< Metoda pro provedeni druhe faze mikrokroku (nizsi vrstva)
	smGetStatus		HWGetStatus;					//!< Metoda pro zjisteni stavu motoru (nizsi vrstva)
	smGetMStepsInStep	HWGetMStepsInStep;			//!< Metoda pro zjisteni poctu mikrokroku v kroku
	smSetPower		HWSetPower;						//!< Metoda pro nastaveni proudu motoru (nizsi vrstva)

	STEPPER_REG		CompareRqMPos;					//!< Pozice, pri ktere se zavola callback cbStepCompare
	smcbStepCompare	cbStepCompare;					//!< Callback volany pri dosazeni pozice CompareRqMPos

	volatile bool_t flRunning;						//!< Priznak inicializovanosti knihovny

} STEPPER_CTX;


//! typ ticku krokovych motoru

typedef void (*smStepperTick) (void);

//----------------------------------------------------
/**
	\brief	Nastavi maximalni rychlost krokoveho motoru

	\param	_ctx			Kontext
	\param	_stepsPerSec	Rychlost - v celych krocich za vterinu

	\note	Meni aktualni pohyb motoru
*/
//----------------------------------------------------

void StepperSetRqSpeed(STEPPER_CTX * const _ctx, const uint16_t _stepsPerSec);


//----------------------------------------------------
/**
	\brief	Nastavi strmost nabehu a sestupu

	\param	_ctx				Kontext
	\param	_stepsPerSecPerSec	Zrychleni (zpomaleni) v krocich za vterinu za vterinu
*/
//----------------------------------------------------

void StepperSetAccel(STEPPER_CTX * const _ctx, const uint16_t _stepsPerSecPerSec);


//----------------------------------------------------
/**
	\brief	Nastavi vychozi rychlost motoru pred zacatkem rampy (po skonceni rampy)

	\param	_ctx			Kontext
	\param	_stepsPerSec	Rychlost - v celych krocich za vterinu
*/
//----------------------------------------------------

void StepperSetMinSpeed(STEPPER_CTX * const _ctx, const uint16_t _stepsPerSec);


//----------------------------------------------------
/**
	\brief	Nastavi aktualni pozici motoru v krocich

	\param	_ctx			Kontext
	\param	_position		Aktualni pozice

	Funkce slouzi ke kalibracnim ucelum. Nastavi pozici do kontextu motoru bez jeho posunu.
*/
//----------------------------------------------------

void StepperSetPosition(STEPPER_CTX * const _ctx, const int16_t _position);


//----------------------------------------------------
/**
	\brief	Ziskani pozice motoru v mikrokrocich

	\param	_ctx			Kontext

	\return		Pozice v mikrokrocich
*/
//----------------------------------------------------

STEPPER_REG StepperGetMStepPosition(const STEPPER_CTX * const _ctx);


//----------------------------------------------------
/**
	\brief	Ziskani pozice motoru v krocich

	\param	_ctx			Kontext

	\return		Pozice v krocich
*/
//----------------------------------------------------

int16_t StepperGetPosition(const STEPPER_CTX * const _ctx);


//----------------------------------------------------
/**
	\brief	Ziskani stavu motoru

	\param	_ctx			Kontext

	\return		TRUE, pokud motor bezi
*/
//----------------------------------------------------

bool_t StepperRunning(STEPPER_CTX * const _ctx);


//----------------------------------------------------
/**
	\brief	Komplexni funkce pro nastaveni rychlostnich parametru motoru

	\param	_ctx					Kontext
	\param	_rqStepsPerSec			Maximalni rychlost, v krocich za vterinu
	\param	_minStepsPerSec			Minimalni rychlost - pred zacatkem rampovani, v krocich za vterinu
	\param	_stepsPerSecPerSec		Strmost rampy (zrychleni, zpomaleni)- v krocich za vterinu za vterinu

	\note	Meni aktualni pohyb motoru
*/
//----------------------------------------------------

void StepperSetSpeed(
		STEPPER_CTX * const _ctx,
		const uint16_t _rqStepsPerSec,
		const uint16_t _minStepsPerSec,
		const uint16_t _stepsPerSecPerSec);


//----------------------------------------------------
/**
	\brief	Nastavi smer pohybu motoru

	\param	_ctx			Kontext
	\param	_dir			Smer

	\note	Meni aktualni pohyb motoru
*/
//----------------------------------------------------

void StepperSetDirection(STEPPER_CTX * const _ctx, const STEPPER_DIR _dir);


//----------------------------------------------------
/**
	\brief	Spusti krokovy motor bez rampovani na plnou rychlost (RqSpeed)

	\param	_ctx			Kontext
*/
//----------------------------------------------------

void StepperFastRun(STEPPER_CTX * const _ctx);


//----------------------------------------------------
/**
	\brief	Zastavi krokovy motor, bez rampovani

	\param	_ctx			Kontext
*/
//----------------------------------------------------

void StepperFastStop(STEPPER_CTX * const _ctx);


//----------------------------------------------------
/**
	\brief	Spusti krokovy motor, s rampou

	\param	_ctx			Kontext
*/
//----------------------------------------------------

void StepperRun(STEPPER_CTX * const _ctx);


//----------------------------------------------------
/**
	\brief	Zastavi krokovy motor, s rampou

	\param	_ctx			Kontext
*/
//----------------------------------------------------

void StepperStop(STEPPER_CTX * const _ctx);


//----------------------------------------------------
/**
	\brief	Nastavi, zda-li se ma volat faze reease

	\param	_ctx			Kontext
*/
//----------------------------------------------------

void StepperSetCallRelease(STEPPER_CTX * const _ctx, bool_t _releaseEnabled);

//----------------------------------------------------
/**
	\brief	Tik knihovny krokovych motoru

	\param	_ctx			Kontext
*/
//----------------------------------------------------

void StepperTick(STEPPER_CTX * const _ctx);


//----------------------------------------------------
/**
	\brief	Inicializace

	\param	_ctx			Kontext
	\param	_rampEnabled	Je-li TRUE, budou pouzity rampy
	\param	_posDir			Urceni smeru, pri kterem bude pozice narustat

	\return		TRUE, pokud inicializace probehla uspesne
*/
//----------------------------------------------------

bool_t StepperInitialize(STEPPER_CTX * const _ctx, const bool_t _rampEnabled, const STEPPER_DIR _posDir);


//----------------------------------------------------
/**
	\brief	Finalizace

	\param	_ctx			Kontext
*/
//----------------------------------------------------

void StepperFinalize(const STEPPER_CTX * const _ctx);


/////////////////////////////////////////////////////////////////////////
// Nadstavba nad knihovnou krokoveho motoru pro beh o dany pocet kroku //
/////////////////////////////////////////////////////////////////////////

//----------------------------------------------------
/**
	\brief	Prikaz k behu krokoveho motoru o zadany pocet kroku

	\param	_ctx			Kontext
	\param	_distance		Pocet kroku, ktery ma motor vykonat
	\param	_direction		Smer, kterym se motor bude pohybovat
	\param	_rqSpeed		Pozadovana rychlost, v krocich za vterinu
	\param	_minSpeed		Rychlost pred zacatkem/po konci rampy, v krocich za vterinu
	\param	_accel			Strmost rampy, zrychleni/zpomaleni v krocich za vterinu za vterinu
*/
//----------------------------------------------------

bool_t StepperStepCountRun(
		STEPPER_CTX * const _ctx,
		const uint16_t _distance,
		const STEPPER_DIR _direction,
		const uint16_t _rqSpeed,
		const uint16_t _minSpeed,
		const uint16_t _accel);


//----------------------------------------------------
/**
	\brief	Inicializace

	\param	_ctx			Kontext
*/
//----------------------------------------------------

bool_t StepperStepCountInitialize(STEPPER_CTX * const _ctx);


//----------------------------------------------------
/**
	\brief	Finalizace

	\param	_ctx			Kontext
*/
//----------------------------------------------------

void StepperStepCountFinalize(const STEPPER_CTX * const _ctx);

#endif /*_STEPPER_H_*/
