// © RiceMotion ( Robert Carl Rice ) 2012-2016 - All rights reserved


// This software makes use of tools and libraries obtained from open source projects or released for

// use by relevant hardware manufactures. However, this software is NOT a part of any open source project.

// It is released only on a "need to know" basis for beta testers of the "RiceCNC Interpolation Engine".

// Recipents of this source code must respect the confidential nature of this software and prevent any

// distribution that could result in counterfeit copies of the "RiceCNC Interpolation Engine".


// © RiceMotion ( Robert Carl Rice ) 2012-2016 - All rights reserved

#include <MachineCommands.h>

#include <Machine.h>

#include <SetCoolant.h>

#include <Coolants.h>

#include <Probe.h>

#include <AnalogPin.h>

#include <InputPin.h>

#include <DoorAjar.h>



void

     Machine::auxilaryControl(

          char*     commandPtr,

          String* msgPtr ) {


     char* data     = commandPtr + 1;


     switch ( *commandPtr ) {


// in-band - acknowledge immediately

          case COOLANT_ON_OFF:

          queueCommand(

               new SetCoolant( data ) );

          *msgPtr

               +=     String( AUXILARY_CONTROL )

               +     String( COOLANT_ON_OFF );

          break;


          case CLAMP_ON_OFF:

          queueCommand(

               new SetCoolant( data ) );

          *msgPtr

               +=     String( AUXILARY_CONTROL )

               +     String( CLAMP_ON_OFF );

          break;


          case AUX_ON_OFF:

          queueCommand(

               new SetCoolant( data ) );

          *msgPtr

               +=     String( AUXILARY_CONTROL )

               +     String( AUX_ON_OFF );

          break;


          case CONFIGURE_COOLANT :

          configureCoolant(

               data,

               msgPtr );

          break;


          case CONFIGURE_PROBE :

          configureProbe(

               data,

               msgPtr );

          break;


          case CONFIGURE_DOOR_AJAR :

          configureDoorAjar(

               data,

               msgPtr );

          break;


          case CLEAR_ANALOG_COMMAND :

          clearAnalogCommand(

               msgPtr );

          break;


          case CREATE_ANALOG :

          createAnalog(

               data,

               msgPtr );

          break;


          case CLEAR_DIGITAL_COMMAND :

          clearDigitalCommand(

               msgPtr );

          break;


          case CREATE_DIGITAL :

          createDigital(

               data,

               msgPtr );

          break;


          default :

          *msgPtr

               +=     *commandPtr

               +     "E Invalid Machine Command - Ignored"; }; };



void

     Machine::clearAnalogCommand(  String* msgPtr ) {


     *msgPtr

          +=     String( AUXILARY_CONTROL )

          +     String( CLEAR_ANALOG_COMMAND );


     clearAnalog(); };



void

     Machine::clearDigitalCommand( String* msgPtr ) {


     *msgPtr

          +=     String( AUXILARY_CONTROL )

          +     String( CLEAR_DIGITAL_COMMAND )

          +     "\n";


     clearDigital(); };



void

     Machine::configureCoolant(

          char*          data,

          String*          msgPtr ) { // This is also used for aux outputs


     *msgPtr

          +=     String( AUXILARY_CONTROL )

          +     String( CONFIGURE_COOLANT );


     uint32_t outputNumber = 0;

     sscanf( data,

          "%lu",

          &outputNumber );

  

     int index = outputNumber - 1;

     if ( index < 0 || index >= AuxOutputs ) {

          *msgPtr          += " Invalid index";

          return; };


     if ( coolants[ index ] ) {

          delete coolants[ index ];

          coolants[ index ] = NULL; };

  

     Coolant* newCoolant = new Coolant();

     if ( ! newCoolant->validate( data, msgPtr ) ) {

          delete newCoolant;

          snprintf( data, 40,

               " Output %lu Unassigned",

               outputNumber );

          *msgPtr    += String( data ); }


     else {

          coolants[ index ] = newCoolant; }; };



void

     Machine::configureDoorAjar(

          char*          data,

          String*          msgPtr ) {


     *msgPtr

          +=     String( AUXILARY_CONTROL )

          +     String( CONFIGURE_DOOR_AJAR );


     if ( doorAjar )

          delete doorAjar;

  

     doorAjar     = new DoorAjar();

     if ( ! doorAjar->validate( data, msgPtr ) ) {

          delete doorAjar;

          doorAjar     = NULL;

          *msgPtr          += " No Door Ajar"; }; };



void

     Machine::configureProbe(

          char*          data,

          String*          msgPtr ) {


     *msgPtr

          +=     String( AUXILARY_CONTROL )

          +     String( CONFIGURE_PROBE );


     if ( probe )

          delete probe;

  

     probe = new Probe( data, msgPtr );

     if ( ! probe->isValid() ) {

          delete probe;

          probe          = NULL;

          *msgPtr          += " No Probe"; }; };



void

     Machine::createAnalog(

          char*          data,

          String*          msgPtr ) {


     *msgPtr

          +=     String( AUXILARY_CONTROL )

          +     String( CREATE_ANALOG );


     AnalogPin* newAnalog     = new AnalogPin( data, msgPtr );

     if ( newAnalog->pin ) {

          uint16_t newID     = newAnalog->id();

          // Now add to chain or replace existing analog with the same pin number

          AnalogPin** analogPtrPtr     = &firstAnalog;

          while ( *analogPtrPtr ) {

               AnalogPin*  analogPtr     = *analogPtrPtr;

               if ( analogPtr->id()  == newID ) {

                    newAnalog->nextAnalogPin  = analogPtr->nextAnalogPin;

                    delete analogPtr;

                    break; }; // replace

               analogPtrPtr     = &analogPtr->nextAnalogPin; };

          *analogPtrPtr    = newAnalog; }


     else

          delete newAnalog; };



void

     Machine::createDigital(

          char*          data,

          String*          msgPtr ) {


     *msgPtr

          +=     String( AUXILARY_CONTROL )

          +     String( CREATE_DIGITAL );


     InputPin* newInputPin     = new InputPin( data, msgPtr );


     if ( newInputPin->valid() ) {

          uint16_t newID = newInputPin->id();

          // Now add to chain or replace existing pin with the same pin number

          InputPin** inputPinPtrPtr   = &firstDigital;

          while ( *inputPinPtrPtr ) {

               InputPin*  inputPinPtr    = *inputPinPtrPtr;

               if ( inputPinPtr->id() == newID ) {

                    newInputPin->nextInputPin  = inputPinPtr->nextInputPin;

                    delete inputPinPtr;

                    break; }; // replace

               inputPinPtrPtr    = &inputPinPtr->nextInputPin; };

          *inputPinPtrPtr   = newInputPin; }


     else

          delete newInputPin; };