#define GALAAD_CNC_DLL_H ///////////////////////////////////////////////////////

// This file is for developers who wish to create a DLL so Galaad software can
// drive their CNC.
//
// Settings such as axis type, direction, gear, length, end-switch that are sent
// to the DLL are those in Galaad machine parameters. Functions that are not
// available from the DLL will be ignored unless they are essential. But if an
// essential function is missing when loading the DLL, then Galaad will abort
// the initialisation process, free the DLL and skip to simulation mode. Some
// essential functions are almost redundant, for example ReadBinaryInputs() and
// ReadOneInput(). At least one of the two must exist.
//
// Functions that move the machine or read axis positions use floating point
// values. The distance unit is the one that has been defined in Galaad (default
// is mm but it can be anything, metric, inches or whatever). Of course the axis
// gear factors indicated in Galaad machine parameters must be coherent with the
// distance unit used. Rotary axes use degrees of angle only. The motion speed
// is set in mm/s. If a rotary axis is moving alone, or is the major axis in the
// vector, then the speed is set in  /s.
//
// The DLL interface is formatted for managing up to 6 axes eventhough Galaad
// uses only 5. The 3 first axes are always X/Y/Z linear (yet parameters allow
// changing the channel of each axis). The 6th axis is used by Galaad only for
// controlling a power laser focus. If the actual CNC has less axes, then the
// DLL can simply ignore all data related to undefined axes and return 0 for
// them when asked a position.
//
// Important: a fast and fluid machining requires a local memory buffer for
// storing motion vectors and executing them instantly without transmission
// delays for acknowledging the vector just done and sending the next one. Thus
// transmission is masked and vectors are chained. When the buffer is used,
// Galaad and the machine are asynchronous. The software sends a batch of
// vectors as big as possible and monitors the transmission so the buffer does
// not overflow. The CNC must manage three tasks: execute one by one the vectors
// stored in its local buffer, receive and store new incoming vectors, and
// manage buffer indexes. This supposes that the bandwidth is large enough so
// the machine does not execute vectors faster than the transmission. For
// avoiding buffer overflow, Galaad needs to get the number of bytes currently
// available. The function GetBufferAvailSize() is called at initialisation so
// the software knows how many vectors can be sent before beginning to verify
// how full the buffer is, and continues sending is there is enough space
// has been left by vectors already executed.
//
// Bytes sent to the buffer are counted but the asynchronous mode makes
// impossible to know how many vectors have been already executed and are no
// more in the buffer. Reading the available size refreshes Galaad's count. See
// in the list below the function GetBufferAvailSize(). The commands sent to the
// buffer (mainly vectors) have each a size that Galaad must know for managing
// the buffer. So, the corresponding functions are supposed to return the number
// of bytes that each command requires for being stored. This is only for
// bufferised commands. If the functions return 0, then Galaad counts itself.
// For example, MoveTo() commands will require the number of bytes that
// corresponds to the target positions (float size is 4 bytes) for the axes
// that actually move, plus the other arguments, plus 1 DWORD (4 bytes) for
// identifying the command, the whole being aligned to the upper 32 bits. And
// it counts the same way for all other bufferisable commands such as writing
// outputs, pauses, etc.
//
// In fact, the DLL can also create and manage on the PC its own supersized
// buffer and indicate that the available size is huge. Up to you to decide if
// it is worth it.
//
// A few additional functions can manage the safety circuit, spindle, coolant
// or a signal pole. They can remain undefined if these devices are controlled
// throughout the classic input/output system.
//
// Please note that, when Galaad makes a simulation of the process, then the DLL
// is not loaded.
//
// Please do not hesitate to call for help, should you have any technical
// questions about interfacing your DLL. See Galaad website for contact links.
//
// Galaad is licenced software, copyright (c) 1992-2025 Bertrand Lenoir-Welter.

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

#define GALAAD_DLLEXPORT  __declspec(dllexport) _stdcall

// GENERAL /////////////////////////////////////////////////////////////////////

void  GALAAD_DLLEXPORT  SetTestMode();   // OPTIONAL
// Called when the developer needs to test the dialog with the DLL though there
// is not a physical CNC beyond. It is not a simulation: in this mode, the
// functions in the DLL can return random data. Function OpenPort() does not
// attempt to communicate and returns TRUE.
// This function is called only once at initialisation (if it is called).

void  GALAAD_DLLEXPORT  GetDllInfo(char *InfoStr1, char *InfoStr2,   // OPTIONAL
                                    char *InfoStr3, char *InfoStr4);
// Called only for output to Galaad debugging file. The DLL may grab information
// about the CNC hardware & firmware versions for integrating in InfoStr.
// Note that each InfoStr line cannot oversize 100 characters and must end with
// a null-character.
// This function is called only once at initialisation.

void  GALAAD_DLLEXPORT  GetDllVersion(int *Major, int *Minor);   // OPTIONAL
// Called for output to Galaad debugging file. The version numbers are also
// displayed when initialising the dialog with the CNC. Since Galaad does not
// know what is inside the DLL, the firmware version has no effect.
// This function is called only once at initialisation.



// COMMUNICATION ///////////////////////////////////////////////////////////////

BOOL GALAAD_DLLEXPORT  OpenPort(char *ErrorMsg);   // ESSENTIAL
// Called at initialisation or when reattempting to connect to the CNC. It must
// return TRUE if the communication port - or any kind of flow - could be opened
// and is available, FALSE otherwise. Reasons for FALSE are simply ignored but
// if ErrorMsg contains something, then it is displayed on Galaad window.
// ErrorMsg cannot exceed 100 characters. If it does, it will be truncated.
// Important: call to this function stops all motions in progress and clears the
// buffer. On the other hand, axis position counters, binary outputs, DAC and
// PWM are not reinitialised and remain as they are. ALso, axis settings remain
// unchanged.

void  GALAAD_DLLEXPORT  ClosePort();   // ESSENTIAL
// Called before closing Galaad machining window.
// Call to this function stops all pending motions and clears the buffer.



// INITIALISATION //////////////////////////////////////////////////////////////

void  GALAAD_DLLEXPORT  SetNumberOfAxesUsed(int Number);   // OPTIONAL
// Indicates for the DLL the number of axes that will be used. There is no
// return code: if the DLL cannot manage so many axes, then the upper axes will
// be ignored.
// This function is called once at initialisation.

void  GALAAD_DLLEXPORT  SetAxisDirection(int AxisNumber, int Invert);   // ESSENTIAL
// Set one by one the axes that must be inverted or not. AxisNumber is [0...5]
// and Invert is 0/1. Inverting an axis is valid for all motion operations
// including homing.
// This function is called once at initialisation.

void  GALAAD_DLLEXPORT  SetAxisLength(int AxisNumber, float Length);   // OPTIONAL
// Set axis maximum distance value. AxisNumber is [0...5], Length is in Galaad
// units, default being mm. This function is just for controllers that manage
// software limits. Anyway Galaad never sends a coordinate that would carry an
// axis out of the range that has been defined in its parameters. If the
// process brings an axis out of its limits, then Galaad refuses to launch it.
// This function is called once at initialisation.

void  GALAAD_DLLEXPORT  SetAxisGearFactor(int AxisNumber, float StepsPerUnit);   // ESSENTIAL
// Define the number of steps per distance unit, default being steps/mm. For a
// rotary axis, angle units are always degrees.
// This function is called only once at initialisation.

void  GALAAD_DLLEXPORT  SetRotaryAxis(int AxisNumber, int Rotary);   // OPTIONAL
// Indicates that an axis is rotary (or linear if zero). So the coordinates
// it will receive will be degrees of angle. But SetAxisGearFactor() above
// mentioned will be called anyway.
// This function is called once at initialisation.

void  GALAAD_DLLEXPORT  SetSlaveAxis(int SlaveAxis, int MasterAxis);   // OPTIONAL
// Set an axis as slave, becoming a simple copy of the master axis. This is
// often used for big tables that have 2 parallel axes at each side of the
// gantry. All motion signals (Step/Dir or whatever) sent to the master axis
// must also be sent to the slave axis regardless of its own settings. For
// example, if the slave has different gear factors than the master, or has been
// defined as rotary axis, that will be ignored. The only setting that can be
// different between master & slave is the SetAxisDirection() value because
// sometimes parallel axes are mounted head-toe.
// SetSlaveAxis() is called at initialisation, but can also be called after
// homing parallel axes so the master & the slave are separated and re-homed one
// by one for resetting the perpendicularity of the gantry. This supposes that
// master and slave have separated end-switch inputs.
// This function is not bufferised: Galaad will not call it during a cycle.

void  GALAAD_DLLEXPORT  ReleaseSlaveAxis(int SlaveAxis);   // OPTIONAL
// Release the slave axis. From now on, the axis becomes independant again. It
// keeps the settings of the master axis (length, gear, etc.) except direction.
// This function is not bufferised: Galaad will not call it during a cycle.

void  GALAAD_DLLEXPORT  SetStartStopFrequency(DWORD Frequency);   // OPTIONAL
// Set the Start/Stop frequency in Hz (not in distance units/s) for all axes.
// Some CNCs have different Start/Stop frequencies for each axis, but Galaad
// will not manage this.
// This function is called at initialisation, but can also be called during the
// process if for example Z-axis requires a different Start/Stop frequency.
// It is not bufferised: Galaad will not reset it during a cycle.

void  GALAAD_DLLEXPORT  SetAcceleration(DWORD Acceleration);   // OPTIONAL
// Set the acceleration value in Hz/s (not in distance units/s ) for all axes.
// Some CNCs may have different acceleration factors for each axis, but Galaad
// will not manage this.
// This function is called at initialisation, but can also be called during the
// process if for example Z-axis requires a different acceleration.
// It is not bufferised: Galaad will not reset it during a cycle.



// INPUTS //////////////////////////////////////////////////////////////////////

DWORD  GALAAD_DLLEXPORT  ReadBinaryInputs();   // OPTIONAL
// Get the instant states of all binary inputs. If there are no functions for
// reading the inputs, then only motion is possible. Galaad manages a maximum
// of 32 binary inputs.
// This function is not bufferised: feedback is expected immediately.

int  GALAAD_DLLEXPORT  ReadOneInput(int InputNumber);   // OPTIONAL
// Get the instant state 0/1 of one binary input. InputNumber is [0...31].
// It is not called if the above function ReadBinaryInputs() exists.
// This function is not bufferised: feedback is expected immediately.

float  GALAAD_DLLEXPORT  ReadAnalogInput(int AdcNumber);   // OPTIONAL
// Get the value from an ADC. AdcNumber is [0...3]. The DLL is supposed to know
// the number of bits of the ADC and will convert the integer value in a return
// float between 0 and 1.
// This function is not bufferised: feedback is expected immediately.

BOOL GALAAD_DLLEXPORT  CanReadInputsWhileBusy();   // OPTIONAL
// If return is TRUE, then Galaad will feel free to call ReadBinaryInputs() or
// ReadOneInput() while the machine is moving or executing its buffer.
// If this function does exist, then the software considers the return is FALSE.

BOOL GALAAD_DLLEXPORT  CanReadAdcWhileBusy();   // OPTIONAL
// If return is TRUE, then Galaad will feel free to call ReadAnalogInputs()
// while the machine is moving or executing its buffer. If this function
// does exist, then the software considers the return is FALSE.



// OUTPUTS /////////////////////////////////////////////////////////////////////

void  GALAAD_DLLEXPORT  SetOutputsAtBoot(DWORD BinOutputs);   // OPTIONAL
// Set the binary output pattern when CNC boots up. It helps setting peripheral
// devices such as safety or else before Galaad starts communicating.
// This function is called once at initialisation.

DWORD  GALAAD_DLLEXPORT  ReadBinaryOutputs();   // OPTIONAL
// Yes, outputs and not inputs. This function gets the states of binary outputs
// for synchronizing Galaad and the CNC when opening a new dialog. When opening
// a new dialog with OpenPort, Galaad considers all outputs are inactive until
// it calls this function (only at initialisation).
// This function is not bufferised: feedback is expected immediately. Anyway
// Galaad will not call it during a cycle.

int  GALAAD_DLLEXPORT  WriteBinaryOutputs(DWORD BinOutputs);   // OPTIONAL
// Set the pattern of all binary outputs in one single call.
// This function is bufferised, i.e. executed among commands sent. It returns
// the number of bytes that will be required to store it in the CNC buffer.

int  GALAAD_DLLEXPORT  WriteOneOutput(int OutputNumber, int State);   // OPTIONAL
// Set one binary output to the given state 0/1. OuputNumber is [0...31]. It is
// not called if the above function WriteBinaryOutputs() exists.
// This function is bufferised, i.e. executed among commands sent. It returns
// the number of bytes that will be required to store it in the CNC buffer.

int  GALAAD_DLLEXPORT  WriteAnalogOutput(int DacNumber, float Value);   // OPTIONAL
// Set the value of a DAC. DacNumber is [0...3]. The DLL is supposed to know
// the number of bits of the DAC and will convert the float value between 0 and
// 1 into an integer value to be sent to the CNC.
// This function is bufferised, i.e. executed among commands sent. It returns
// the number of bytes that will be required to store it in the CNC buffer.

int  GALAAD_DLLEXPORT  WritePwmOutput(int PwmNumber, int Frequency, float PulseRatio);   // OPTIONAL
// Set the PWM with Frequency (in Hz) and PulseRatio as float between 0 and 1.
// PwmNumber is [0...3]. Some controllers cannot change the PWM frequency and
// may ignore this argument. For the moment, Galaad does not use it and will set
// it by default at 8 KHz, settable directly from GALAAD.CNC parameter file.
// This function is bufferised, i.e. executed among commands sent. It returns
// the number of bytes that will be required to store it in the CNC buffer.

void  GALAAD_DLLEXPORT  WriteOneOutputNow(int OutputNumber, int State);   // OPTIONAL
// Same function as WriteOneOutput() above mentioned, except that it is called
// even if WriteBinaryOutputs() exists because the major difference with
// WriteOneOutput() is that WriteOneOutputNow() is not bufferised. It must be
// executed immediately while the CNC is moving or pausing or executing commands
// from the buffer. Galaad provides a facility for reading inputs and writing
// outputs immediately while the buffer is being executed, using that function.

void  GALAAD_DLLEXPORT  WriteAnalogOutputNow(int DacNumber, float Value);   // OPTIONAL
// Same function as WriteAnalogOutput() above mentioned, except that it must be
// executed immediately, i.e. not bufferised. See WriteOneOutputNow() above for
// more information.

void  GALAAD_DLLEXPORT  WritePwmOutputNow(int PwmNumber, int Frequency, int PulseRatio);   // OPTIONAL
// Same function as WritePwmOutput() above mentioned, except that it must be
// executed immediately, i.e. not bufferised. See WriteOneOutputNow() above for
// more information.



// SPINDLE, COOLANT, SAFETY ////////////////////////////////////////////////////

void  GALAAD_DLLEXPORT  ShutSafetyDoor();   // OPTIONAL
// For the case where the machine has an automatic door management system. This
// function is called before starting the machining process.
// This function is not bufferised, not called during an active cycle.

void  GALAAD_DLLEXPORT  OpenSafetyDoor();   // OPTIONAL
// For the case where the machine has an automatic door management system. This
// function is called at the end of the machining process.
// This function is not bufferised, not called during an active cycle.

BOOL  GALAAD_DLLEXPORT  SafetyDoorIsShut();   // OPTIONAL
// Indicates the status of the machine safety door or any safety device. It is
// called before moving axes, starting the spindle, launching a process.
// This function is optional if the DLL can manage inputs, but if it exists,
// Galaad will use it.
// This function is not bufferised: feedback is expected immediately.

int  GALAAD_DLLEXPORT  SetSpindle(int Rpm);   // OPTIONAL
// Stop the spindle if Rpm is zero, otherwise start spindle or set its rotation
// speed in Rev/minute. Note: Rpm can be negative. The spindle inertia is
// managed by Galaad with its parameters, but the DLL may manage itself some
// signal that indicates that the spindle it at the requested Rpm.
// This function is optional if the DLL can manage outputs including DAC or PWM,
// but if it exists, then Galaad will use it.
// This function is bufferised, i.e. executed among commands sent. It returns
// the number of bytes that will be required to store it in the CNC buffer.

void  GALAAD_DLLEXPORT  SetSpindleNow(int Rpm);   // OPTIONAL
// Same function as SetSpindle() above mentioned, except that it must be
// executed immediately, i.e. not bufferised. This is used along with the speed
// override if the spindle rpm must be linked to the motion speed.

int  GALAAD_DLLEXPORT  SetCoolant(int On);   // OPTIONAL
// Start (nonzero) or stop (zero) the coolant system. Galaad will send only 0/1
// because for the moment, it just manages the coolant on/off.
// This function is optional if the DLL can manage outputs, but if it exists,
// then Galaad will use it.
// This function is bufferised, i.e. executed among commands sent. It returns
// the number of bytes that will be required to store it in the CNC buffer.

int  GALAAD_DLLEXPORT  SetSignalPole(int Status);   // OPTIONAL
// Switch on/off the green/orange/red signal pole, if the machine has one.
// Status value is 0 for none, 1 for green, 2 for orange, 3 for red.
// This function is optional if the DLL can manage outputs, but if it exists,
// Galaad will use it.
// This function can be bufferised, though it is not important because it is not
// sent among buffer commands. Anyway it returns the number of bytes that will
// be required to store it in the CNC buffer.



// READ/WRITE POSITION /////////////////////////////////////////////////////////

void  GALAAD_DLLEXPORT  ReadPosition(float *fpPosX, float *fpPosY, float *fpPosZ,   // ESSENTIAL
                                     float *fpPos4, float *fpPos5, float *fpPos6);
// Get the positions of all axes.
// This function is not bufferised, i.e. feedback is expected immediately.

BOOL GALAAD_DLLEXPORT  CanReadPositionWhileBusy();   // OPTIONAL
// If return is TRUE, then Galaad will feel free to call ReadPosition() while
// the machine is moving or executing its buffer. If this function does not
// exist, then the software considers the return is FALSE.

int  GALAAD_DLLEXPORT  WritePosition(int AxisNumber, float Position);   // OPTIONAL
// Set the position of a given axis. AxisNumber is [0...5]. In most cases, the
// value sent is 0 for resetting the position counter, but it can happen that a
// rotary axis counter is reset to its current value modulo 360 to avoid making
// several unwrapping revolutions forward or backward.
// If an axis is slave, then calling this function on its number is useless.
// This function is bufferised, i.e. executed among commands sent. It returns
// the number of bytes that will be required to store it in the CNC buffer.



// MOTION //////////////////////////////////////////////////////////////////////

int  GALAAD_DLLEXPORT  MoveTo(int AxesMoving, float Speed,   // ESSENTIAL
                              DWORD MasterFrequency, int UseRamps,
                              float TargetX, float TargetY, float TargetZ,
                              float Target4, float Target5, float Target6);
// Move axes simultaneously (linear interpolation) to target positions. If there
// is a machine zero (using Homing functions), then the coordinates are always
// positive, from zero to the axis end. Note that, in this case, Galaad will
// never transmit a target coordinate that trespasses the usable range, except
// rotary axes that have no defined limits and can receive negative coordinates.
// Of course these software limits suppose that gear factors have been set
// correctly in Galaad machine parameters.
// The motion is performed at the Speed argument, given in units/s depending on
// the distance unit that is used in Galaad, default being mm/s. It corresponds
// to a tangential speed along the vector interpolation. If it can help, Galaad
// also gives the MasterFrequency which corresponds to the speed in Hz of the
// major axis. The major axis is the one that will have to run the greatest
// number of steps forward or backward to reach its target position. Therefore,
// it is the fastest one along the vector. If the CNC is using a Bresenham
// algorithm for synchronizing axes, then the highest frequency is there.
// Heading argument AxesMoving is a binary pattern that indicates which axes
// will be actually moving (others remain still at their current positions).
// This aims to save space in the local buffer if any.
// If UseRamps is nonzero, then the motion is performed using an acceleration
// ramp at the beginning of the vector and a deceleration ramp at the end,
// according to Start/Stop frequency and acceleration settings. If UseRamps is
// zero, then the motion begins and ends at Speed value, so there are no speed
// changes along the vector. If Frequency is under the Start/Stop frequency,
// then obviously there are no ramps.
// If an axis is a slave, its target position must be ignored since it follows
// the master axis. This is not supposed to occur, but we never know...
// This function is bufferised, i.e. executed among commands sent. It returns
// the number of bytes that will be required to store it in the CNC buffer.

void  GALAAD_DLLEXPORT  MoveUntilInput(int AxisNumber, int PositiveDir,   // OPTIONAL
                                       float Speed, float MaxLength,
                                       int InputNumber, int State);
// Move one axis towards the direction defined by PositiveDir (must be zero if
// direction is negative), using Start/Stop frequency and acceleration ramps.
// The motion is stopped when MaxLength is reached or if the input matches the
// level defined by State (does not even start if the input is already at the
// target state). A deceleration ramp follows the input trigger.
// The purpose of this function is find a position that touches something, e.g.
// a sensor for measuring a tool (Z-axis), a workpiece side by making a lateral
// approach (X or Y axis), a metal sheet for probing with a plasma torch, or
// anything else.
// If an axis is slave, then calling this function on its number is pointless
// and should do nothing.
// If the CNC uses TTL signals, then it may be important that the inputs have a
// low-pass filter - say 10 ms or more - for getting rid of electrical noise
// that could cause false triggers. Same for homing functions.
// This function is not supposed to be bufferised, since the stop position must
// then get into a calculation for use by the software. There are no relative
// motion commands like MoveRel().

void  GALAAD_DLLEXPORT  MoveUntilTwoInputs(int AxisNumber, int PositiveDir,   // OPTIONAL
                                           float Speed, float MaxLength,
                                           int InputNumber1, int State1,
                                           int InputNumber2, int State2);
// Same as MoveUntilInput() function, except that Input1 OR Input2 can stop
// the motion (not AND). This function is used for example when a plasma torch
// is probing the metal sheet with both an ohm sensor and a recoil sensor. If
// the ohm sensor does not trigger its input due to a dirty surface, then the
// recoil sensor will stop the lowering anyway.
// This function is not supposed to be bufferised for the moment, but it can.

void  GALAAD_DLLEXPORT  MoveUntilAnalogInput(int AxisNumber, int PositiveDir,   // OPTIONAL
                                             float Speed, float MaxLength,
                                             int AdcNumber,
                                             float FloorValue, float CeilValue);
// Same as MoveUntilInput() function, except that the motion is stopped when the
// ADC value gets out of [FloorValue...CeilingValue] range.
// This function is not supposed to be bufferised for the moment, but it can.

int  GALAAD_DLLEXPORT  HomeAxis(int AxisNumber, float Speed,   // OPTIONAL
                                int HomeInput, int HomeState,
                                float ReleaseSpeed);
// Move one axis with an acceleration ramp toward negative direction at the
// given Speed. AxisNumber is [0...5]. There is no target position: the motion
// stops when HomeInput matches HomeState level. This stop can be done with or
// without a deceleration ramp (a loss of steps has no consequences here). Then
// the axis moves back toward positive direction until HomeInput is released,
// i.e. matches the reversed state as given by HomeState^1.
// The axis position counter is automatically reset to 0 at the end. Galaad does
// not need to call WritePosition(AxisNumber,0) then.
// If an axis is slave, then calling this function on its number is pointless
// and should do nothing. On the other hand, if the axis number corresponds to a
// master, then its slave axis will follow the master to home.
// This function can be bufferised, i.e. executed among commands sent, though
// Galaad will use it directly. So it returns the number of bytes that will be
// required to store it in the CNC buffer.

int  GALAAD_DLLEXPORT  HomeTwoAxes(int AxisNumber1, int AxisNumber2,   // OPTIONAL
                                   float Speed,
                                   int HomeInput1, int HomeState1,
                                   int HomeInput2, int HomeState2,
                                   float ReleaseSpeed);
// Move two axes together toward their own negative directions at the given
// speed. AxisNumber are [0...5], typically 0 and 1 (X and Y). The procedure for
// each axis is the same as above. If the CNC is able to do it, then the first
// axis that reaches its home stops and the other continues. The releasing
// motion can be done independantly or after both axes have triggered their
// inputs.
// Both axis position counters are reset to 0 at the end.
// If one of the axes has a slave, then in fact 3 axes are moving together. This
// function is not for homing a master and its slave together, which is implicit
// when the master moves. The slave follows the master all the time, including
// homing or moving until input.
// This function can be bufferised, i.e. executed among commands sent, though
// Galaad will use it directly. It returns the number of bytes that will be
// required to store it in the CNC buffer.

void  GALAAD_DLLEXPORT  StopMotion();   // ESSENTIAL
// Stop motion in progress with a deceleration ramp, and clear the buffer. If
// the stop is sent while the buffer is being executed, then the deceleration
// ramp must be performed along the current vector and next vectors until the
// speed is null or under the StartStop frequency, so there are no losses of
// steps. A StopMotion can also be sent while homing or moving until input.
// This function is not bufferised, i.e. execution is immediate.

int  GALAAD_DLLEXPORT  EnableSpeedOverride();   // OPTIONAL
// Apply the motion speed divider set by Galaad_SetOverride().
// This function is bufferised, i.e. executed among commands sent. It returns
// the number of bytes that will be required to store it in the CNC buffer.

int  GALAAD_DLLEXPORT  DisableSpeedOverride();   // OPTIONAL
// Stop applying the motion divider value set by Galaad_SetOverride() so speed
// multiplier is reset to 100%.
// This function is bufferised, i.e. executed among commands sent. It returns
// the number of bytes that will be required to store it in the CNC buffer.

void  GALAAD_DLLEXPORT  SetSpeedOverride(float Multiplier);   // OPTIONAL
// Set the motion speed multiplier that should normally be between [0...1] but
// also upper on some CNC systems. 0 corresponds to motion stopped, and 1 to
// normal speed. Galaad will not sent an override value more than 1.5 because
// the kinematics calculation is already done when the buffer begins and
//  multiplying the speeds creates a risk of loss of steps (or pursuit error for
// a servodrive).
// Important: when SetSpeedOverride() is called, the override is automatically
// enabled without having to call EnableSpeedOverride().
// Not all CNCs can decrease the speed down to 0. If they do, then a null speed
// supposes that the CNC is idle, waiting for the speed override increase of a
// StopMotion is sent. Galaad can link the spindle to the speed override, in
// which case the spindle speed decreases along with the feed speed. This can be
// managed by Galaad though a speed potentiometer which is read from an ADC and
// the overrides (feed speed and spindle) are managed by Galaad.
// All motion speeds are concerned by the override. Galaad makes no differences
// between rapid and feed vectors, only MoveTo() commands are sent. This is why
// EnableSpeedOverride() and DisableSpeedOverride() are bufferised: feeding
// vectors are preceded by a call to EnableSpeedOverride() and rapid vectors by
// a call to DisableSpeedOverride() to make them out of reach.
// This function is not bufferised, i.e. applies immediately while a motion is
// in progress and remains valid until reset by calling DisableSpeedOverride().



// PAUSE ///////////////////////////////////////////////////////////////////////

int  GALAAD_DLLEXPORT  Pause(DWORD Milliseconds);   // OPTIONAL
// Pause during the given number of milliseconds.
// This function is obviously bufferised, i.e. executed among commands sent.
// When driving the machine in direct mode without using the buffer, then Galaad
// manages its own pauses. It returns the number of bytes that will be required
// to store it in the CNC buffer.

DWORD  GALAAD_DLLEXPORT  GetMinPause();   // OPTIONAL
// Return the minimum duration of a pause that the CNC can afford. Return value
// is in milliseconds. See Pause() function above.

int  GALAAD_DLLEXPORT  WaitUntilOneInput(int InputNumber, int State, DWORD Timeout);   // OPTIONAL
// Pause until input matches the required State or the timeout (in milliseconds)
// is reached. The use is typically for synchronizing a motion start with an
// input, for example making a multi-pass threading on a lathe that must begin
// always at the same angle position without transmission delays. Here Galaad
// sends to the buffer a pause (for having the time to transmit the following),
// then WaitUntilOneInput() for the synchro, then the threading movement. The
// CNC can start moving immediately after the input is triggered, and the delay
// between them will be always the same.
// This function is obviously bufferised, i.e. executed among commands sent.
// In direct driving mode, Galaad can manage inputs itself. It returns the
// number of bytes that will be required to store it in the CNC buffer.

int  GALAAD_DLLEXPORT  WaitUntilTwoInputs(int InputNumber1, int State1,   // OPTIONAL
                                          int InputNumber2, int State2,
                                          DWORD Timeout);
// Same function as WaitUnitOneInput() above described, except that 2 inputs can
// trigger, Input1 OR Input2.



// USER TAGS ///////////////////////////////////////////////////////////////////

int  GALAAD_DLLEXPORT  WriteUserTag(DWORD Tag);   // OPTIONAL
// Write a user's tag in CNC RAM. Tag value can be anything. This helps follow
// the buffer execution. For example, if the current of a plasma torch is
// driven directly by Galaad through an RS485 port not connected to the CNC,
// and the current must be lowered where the feed speed must decrease due to
// kinematics constraints, then there can be a tag-mark in the buffer so Galaad
// knows where the execution actually is. See ReadUserTag() below.
// So there can be several WriteUserTag commands in the buffer and they must
// change the tag value only when executed in the sequence.
// Galaad resets the tag to 0 when opening the buffer.
// This function is bufferised, i.e. executed among commands sent. It returns
// the number of bytes that will be required to store it in the CNC buffer.

DWORD  GALAAD_DLLEXPORT  ReadUserTag();   // OPTIONAL
// Read the user's tag as it has been written along buffer execution.
// This function is not bufferised: feedback is expected immediately.



// MOTION STATUS & BUFFER //////////////////////////////////////////////////////

int  GALAAD_DLLEXPORT  GetStatus();   // ESSENTIAL
// Returns the CNC status as indicated by constants below. It can be called in
// direct drive mode and in buffer mode.
// This function is not bufferised: feedback is expected immediately. In direct
// drive mode, Galaad uses GetStatus() after sending a MoveTo(), HomeAxis(), or
// MoveUntilInput() command. It enters a loop until the status returns Ready.
// In buffer mode, Galaad uses GetStatus() to get informed about what the CNC is
// currently doing, plus GetBufferAvailSize() - see below - if there are more
// vectors to be sent, plus GetPosition() for following the position on the
// screen, plus ReadBinaryInputs() or ReadOneInput() for checking critical
// inputs, plus ReadAnalogInput() for displaying the THC value of a plasma
// torch. These calls have delays in between to avoid flooding the transmission.
// For example, the position is just a comfort and so is read every 100 ms, the
// critical inputs every 50 ms, the ADC every 250 ms. These delays are settable
// in Galaad machine parameters. 

#define GALAAD_CNC_DLL_STATUS_SILENT    0
// Silent means that the function could not get the CNC status.
#define GALAAD_CNC_DLL_STATUS_READY     1
// Ready means that no motion is in progress and the buffer is empty.
#define GALAAD_CNC_DLL_STATUS_MOVING    2
// Moving means that a motion is in progress.
#define GALAAD_CNC_DLL_STATUS_PAUSING   3
// Pausing means that the CNC is executing a pause.
#define GALAAD_CNC_DLL_STATUS_BLOCKED   4
// Blocked means that the CNC cannot execute any commands.


DWORD  GALAAD_DLLEXPORT  GetBufferAvailSize();   // OPTIONAL
// Get the number of bytes that the buffer can store at the moment, decreasing
// when bufferised commands are sent and increasing when commands already
// stored have been executed. When using the buffer, Galaad keeps a margin of
// about 10 % of the buffer size, or the biggest command it can sent, which is
// a MoveTo() with all its arguments.
// This function is not bufferised: feedback is expected immediately.

void  GALAAD_DLLEXPORT  BeginBuffer();   // OPTIONAL
// Indicate that next commands, mostly MoveTo() commands are to be bufferised.
// This is sent at the beginning of a path, before lowering the tool. If the CNC
// bufferises all motion, output & pause commands, then this is useless. Anyway
// Galaad will call it before a tool-down command. By default, Galaad moves the
// tool above the path entry point, calls BeginBuffer(), sends MoveTo() commands
// for lowering the tool, plunge in the material, follow the feeding path and
// lift up at the end, then calls EndBuffer() - see below - and enters a loop
// for checking the CNC status, position, inputs. Then, when the status
// indicates that the CNC is ready, buffer empty, it turns back to direct drive
// mode, moves the tool to the XY position of the next path. It is possible to
// manage the whole cycle in one single buffer execution so Galaad does not
// re-synchronise at every path end. This must be indicated in Galaad machine
// parameters concerning the buffer.
// Obviously This function does not need to be bufferised.

void  GALAAD_DLLEXPORT  EndBuffer();   // OPTIONAL
// Indicate that no more commands will be bufferised. It is called at the end of
// a path, after the tool is lifted-up.
// This function is supposed to be bufferised but there is no need to return
// anything.

void  GALAAD_DLLEXPORT  BeginUpload();   // OPTIONAL
// This is for CNCs that can load a complete process and execute it repeatedly
// when the operator presses a start button. In upload mode, the machine is not
// supposed to execute immediately the commands it receives. So Galaad does not
// use buffer functions and expects no feedback from the CNC. No statuses, no
// positions, no inputs are read. Furthermore, Galaad does not count the bytes
// and considers the CNC is able to store all commands sent.

void  GALAAD_DLLEXPORT  EndUpload();   // OPTIONAL
// Indicate that no more commands will be uploaded. It is called at the end of
// the machining cycle.



// SPECIAL FUNCTIONS FOR PLASMA TORCH OR POWER LASER////////////////////////////

// Note: All THC functions described below concern a plasma torch as well as a
// power laser with field monitoring.

void  GALAAD_DLLEXPORT  SetThcParameters(int AxisNumber, int AdcNumber, float Reactivity);   // OPTIONAL
// Set Torch Height Control for Z-axis. AdcNumber is [0...3] for the analog
// input that reads the voltage from the torch. Reactivity is a floating point
// value as set in Galaad machine parameters.
// This function is called at the beginning of an automatic cycle and does not
// need to be bufferised.

void  GALAAD_DLLEXPORT  SetThcTarget(float AdcValue);   // OPTIONAL
// Set THC voltage target voltage value. When enabled, the THC will drive the
// Z-axis directly so the analog input matches AdcValue. The THC target is sent
// at the beginning of an automatic cycle but remains subject to changes if the
// operator decides that the torch is too high or too low. It is then possible
// to change the target on the screen or using a potentiometer.
// This function is not bufferised, execution is immediate.

int  GALAAD_DLLEXPORT  EnableThc();   // OPTIONAL
// Enable THC mode for Z-axis. The THC must not be enabled all the time along a
// cutting path. If that path is small or covers a small surface around the
// Z-probing point, then enabling the THC is useless. Also, when the path
// crosses its own trajectory, it runs over a kerf already cut and the lack of
// metal will increase the voltage so the THC makes the Z-axis plunge for
// matching the ADC target value, which should not occur. Also, when calculating
// path kinematics, the feed speed can vary, getting lower in sharp angles or
// small crooked curves. Therefore Galaad can decide that the THC will be
// disabled where the speed lowers and re-enable it later on.
// More generally, the THC compensates the variations of the metal surface,
// especially on thin rolled sheets that can distort when cut. It is not made
// for reacting all the time, except on corrugated sheets.
// This function is bufferised, i.e. executed among commands sent. It returns
// the number of bytes that will be required to store it in the CNC buffer.

int  GALAAD_DLLEXPORT  DisableThc();   // OPTIONAL
// Disable THC mode for Z-axis. It is called when Galaad decides that the path
// should not be submitted to the THC or at the end before lifting Z up.
// This function is bufferised, i.e. executed among commands sent. It returns
// the number of bytes that will be required to store it in the CNC buffer.

BOOL  GALAAD_DLLEXPORT  IsThcEnabled();   // OPTIONAL
// Returns TRUE if THC is currently enabled, FALSE otherwise. Only for display.
// This function is not bufferised: feedback is expected immediately. It is used
// mainly for displaying the process status.

void  GALAAD_DLLEXPORT  SetLaserFocus(float Position);   // OPTIONAL
// Set the focus position of a power laser head. Position is a floating point
// value set in Galaad distance units (default is mm).
// This function is not bufferised, execution is immediate. It is called once
// at the beginning of an automatic cycle. So the focus motor may perform a
// position reset before going to the position.



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

