//
//  axis.cpp - machine axis implementation
//
//  $Id: axis.cpp 53 2014-02-07 19:39:59Z brian $ 
//
//  Copyright (c) 1999-2014 by Precision Micro Control Corp. All rights reserved.
//
#include "stdafx.h"

// Initialization file sections for each axis, these strings must exist as
// static data for Application Variable Classes. 
static char* AxisSection[] = {
	NULL,
	"XAXIS", "YAXIS", "ZAXIS",
	"UAXIS", "VAXIS", "WAXIS"
};

Axis::Axis(int id, int mnemonic) :
	m_id(id), m_mnemonic(mnemonic)
{
	// Initialize member Application Variables so they can save and restore themselves	
	m_axis.Init(0, AxisSection[m_id], CTRLR_AXIS_NUM_ENTRY);
	m_slave_axis.Init(0, AxisSection[m_id], SLAVE_AXIS_NUM_ENTRY);
	Scale.Init(UNDEFINED_DIM_UNIT, 0.0, AxisSection[m_id], SCALE_ENTRY);
	MachineOffset.Init(DEFAULT_DIM_UNIT, 0.0, AxisSection[m_id], MACHINE_OFFSET_ENTRY);
	ProgramOffset.Init(DEFAULT_DIM_UNIT, 0.0, AxisSection[m_id], PROGRAM_OFFSET_ENTRY);
	RapidRate.Init(DEFAULT_DIM_UNIT,DEFAULT_PER_UNIT, 0.0, AxisSection[m_id], RAPID_RATE_ENTRY);
	RapidAccel.Init(DEFAULT_DIM_UNIT,DEFAULT_PER_UNIT, 0.0, AxisSection[m_id], RAPID_ACCEL_ENTRY);
	RapidDecel.Init(DEFAULT_DIM_UNIT,DEFAULT_PER_UNIT, 0.0, AxisSection[m_id], RAPID_DECEL_ENTRY);
	LowerLimit.Init(DEFAULT_DIM_UNIT, 0.0, AxisSection[m_id], LOWER_LIMIT_ENTRY);
	UpperLimit.Init(DEFAULT_DIM_UNIT, 0.0, AxisSection[m_id], UPPER_LIMIT_ENTRY);

	// Provide a default readout format string	
	ReadoutFormat = "%#+ 14f";
}

void Axis::Initialize(int axis_num)
{
	m_axis = axis_num;
	m_slave_axis = 0;
	Scale.Set(DEFAULT_DIM_UNIT,1.0);
	MachineOffset.Set(DEFAULT_DIM_UNIT, 0.0);
	ProgramOffset.Set(DEFAULT_DIM_UNIT, 0.0);
	RapidRate.Set(DEFAULT_DIM_UNIT, DEFAULT_PER_UNIT, 0.0);
	RapidAccel.Set(DEFAULT_DIM_UNIT, DEFAULT_PER_UNIT, 0.0);
	RapidDecel.Set(DEFAULT_DIM_UNIT, DEFAULT_PER_UNIT, 0.0);
	UpperLimit.Set(DEFAULT_DIM_UNIT, 0.0);
	LowerLimit.Set(DEFAULT_DIM_UNIT, 0.0);
}

void Axis::SaveData(const char* ini_file)
{
	CMachine* pTheMachine = theApp.GetMachine();
	int precision = pTheMachine->GetSetupPrecision();
	
	m_axis.Erase(ini_file);		// Clear section for this axis

	m_axis.Save(ini_file);
	m_slave_axis.Save(ini_file);
	Scale.Save(ini_file, precision);
	MachineOffset.Save(ini_file, precision);
	ProgramOffset.Save(ini_file, precision);
	RapidRate.Save(ini_file, precision);
	RapidAccel.Save(ini_file, precision);
	RapidDecel.Save(ini_file, precision);
	LowerLimit.Save(ini_file, precision);
	UpperLimit.Save(ini_file, precision);
}

void Axis::RestoreData(const char* ini_file)
{
	m_axis.Restore(ini_file);
	m_slave_axis.Restore(ini_file);
	Scale.Restore(ini_file);
	MachineOffset.Restore(ini_file);
	ProgramOffset.Restore(ini_file);
	RapidRate.Restore(ini_file);
	RapidAccel.Restore(ini_file);
	RapidDecel.Restore(ini_file);
	LowerLimit.Restore(ini_file);
	UpperLimit.Restore(ini_file);
}

void Axis::Configure(std::fstream& cfg_file)
{
	// Place comment in configuration file
	cfg_file << ";" << GetMnemonic() << " axis configuration" << std::endl;
	
	// Generate configuration commands for motion controller
	cfg_file << GetMnemonic() << "AXIS=" << GetAxis() << std::endl;
	
	if (GetAxis())		// Only configure axes that exist (axis number != 0)
	{
		cfg_file << GetMnemonic() << "SLAVE=" << GetSlaveAxis() << std::endl;
	
		// Configuration data in both english and metric units
		for (int units = ENGLISH; units <= METRIC; units++)
		{
			cfg_file << (const char*)UnitsName[units] << std::endl;

			DIM_UNIT dim_unit;
			PER_UNIT per_unit;
			if (units == ENGLISH)
			{
				dim_unit = theApp.GetMachine()->PartPrgmEnglishDimUnit.Get();
				per_unit = theApp.GetMachine()->PartPrgmEnglishPerUnit.Get();
			}
			else
			{
				dim_unit = theApp.GetMachine()->PartPrgmMetricDimUnit.Get();
				per_unit = theApp.GetMachine()->PartPrgmMetricPerUnit.Get();
			}

			cfg_file << GetMnemonic() << "SCALE=" << Scale.Get(dim_unit) << std::endl;
			cfg_file << GetMnemonic() << "MACHINEOFFSET=" << MachineOffset.Get(dim_unit) << std::endl;
			cfg_file << GetMnemonic() << "PROGRAMOFFSET=" << ProgramOffset.Get(dim_unit) << std::endl;
			cfg_file << GetMnemonic() << "RATECONV=" << 1.0 / PerUnitMultiplier[per_unit] << std::endl;
			cfg_file << GetMnemonic() << "RAPIDRATE=" << RapidRate.Get(dim_unit, per_unit) << std::endl;
			cfg_file << GetMnemonic() << "RAPIDACCEL=" << RapidAccel.Get(dim_unit, per_unit) << std::endl;
			cfg_file << GetMnemonic() << "RAPIDDECEL=" << RapidDecel.Get(dim_unit, per_unit) << std::endl;
			cfg_file << GetMnemonic() << "LOWLIMIT=" << LowerLimit.Get(dim_unit) << std::endl;
			cfg_file << GetMnemonic() << "UPLIMIT=" << UpperLimit.Get(dim_unit) << std::endl;
			
			if (units == theApp.GetMachine()->GetDefaultUnits())
			{
				double scale = Scale.Get(dim_unit);
				scale = fabs(scale);			// get absolute value of scale
				
				if (scale > 100000000.0)
					ReadoutFormat = "%#+ 14.9f";
				else if (scale > 10000000.0)
					ReadoutFormat = "%#+ 14.8f";
				else if (scale > 1000000.0)
					ReadoutFormat = "%#+ 14.7f";
				else if (scale > 100000.0)
					ReadoutFormat = "%#+ 14.6f";
				else if (scale > 10000.0)
					ReadoutFormat = "%#+ 14.5f";
				else if (scale > 1000.0)
					ReadoutFormat = "%#+ 14.4f";
				else if (scale > 100.0)
					ReadoutFormat = "%#+ 14.3f";
				else if (scale > 10.0)
					ReadoutFormat = "%#+ 14.2f";
				else if (scale > 1.0)
					ReadoutFormat = "%#+ 14.1f";
				else
					ReadoutFormat = "%#+ 14.0f";
			}
		}
	}
}

void Axis::SetProgramZero()
{
	if (GetAxis() != 0)		// Only zero if axis doesn't exist
	{
		DIM_UNIT dim_unit;
		if (theApp.GetMachine()->GetDefaultUnits() == ENGLISH)
			dim_unit = theApp.GetMachine()->PartPrgmEnglishDimUnit.Get();
		else
			dim_unit = theApp.GetMachine()->PartPrgmMetricDimUnit.Get();

		ProgramOffset.Set(dim_unit,GetPosition());
	}
}

void Axis::Direction(WORD dir)
{
	if (m_axis)
		theApp.GetMachine()->MtnCtrlr.Direction(m_axis, dir);
}

void Axis::EnableAxis(int state)
{
	if (m_axis)
		theApp.GetMachine()->MtnCtrlr.EnableAxis(m_axis, state);
}

void Axis::Go(void)
{
	if (m_axis)
		theApp.GetMachine()->MtnCtrlr.Go(m_axis);
}

void Axis::MoveAbsolute(double position)
{
	if (m_axis)
		theApp.GetMachine()->MtnCtrlr.MoveAbsolute(m_axis, position);
}

void Axis::MoveRelative(double distance)
{
	if (m_axis)
		theApp.GetMachine()->MtnCtrlr.MoveRelative(m_axis, distance);
}

void Axis::SetAcceleration(double accel)
{
	if (m_axis)
		theApp.GetMachine()->MtnCtrlr.SetAcceleration(m_axis, accel);
}

void Axis::SetDeceleration(double decel)
{
	if (m_axis)
		theApp.GetMachine()->MtnCtrlr.SetDeceleration(m_axis, decel);
}

void Axis::SetOperatingMode(WORD master, WORD mode)
{
	if (m_axis)
		theApp.GetMachine()->MtnCtrlr.SetOperatingMode(m_axis, master, mode);
}

void Axis::SetVelocity(double vel)
{
	if (m_axis)
		theApp.GetMachine()->MtnCtrlr.SetVelocity(m_axis, vel);
}

void Axis::SetVelocityOverride(double value)
{
	if (m_axis)
		theApp.GetMachine()->MtnCtrlr.SetVelocityOverride(m_axis, value);
}

void Axis::Stop(void)
{
	if (m_axis)
		theApp.GetMachine()->MtnCtrlr.Stop(m_axis);
}

long Axis::GetStatus()
{
	if (m_axis)
		return theApp.GetMachine()->MtnCtrlr.GetStatus(m_axis);
	else
		return 0;
}

long Axis::DecodeStatus(DWORD status, long bit)
{
	if (m_axis)
		return theApp.GetMachine()->MtnCtrlr.DecodeStatus(status, bit);
	else
		return 0;
}

double Axis::GetPosition(void)
{
	if (m_axis)
		return theApp.GetMachine()->MtnCtrlr.GetPosition(m_axis);
	else
		return 0;
}

double Axis::GetOptimal(void)
{
	if (m_axis)
		return theApp.GetMachine()->MtnCtrlr.GetOptimal(m_axis);
	else
		return 0;
}

double Axis::GetTarget(void)
{
	if (m_axis)
		return theApp.GetMachine()->MtnCtrlr.GetTarget(m_axis);
	else
		return 0;
}
