Álvaro de Rada / X_NUCLEO_PLC01A1

Components/Interfaces/PLC_class.cpp

Committer:
apalmieri
Date:
2016-02-19
Revision:
0:b66a560b6618

File content as of revision 0:b66a560b6618:

/**
 ******************************************************************************
 * @file    PLC_class.h
 * @author  AST/CL
 * @version V1.0.0
 * @date    Feb 9th, 2016
 * @brief   This file contains the abstract class describing the interface of a
 *          generic component.
 ******************************************************************************
 * @attention
 *
 * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *   1. Redistributions of source code must retain the above copyright notice,
 *      this list of conditions and the following disclaimer.
 *   2. Redistributions in binary form must reproduce the above copyright notice,
 *      this list of conditions and the following disclaimer in the documentation
 *      and/or other materials provided with the distribution.
 *   3. Neither the name of STMicroelectronics nor the names of its contributors
 *      may be used to endorse or promote products derived from this software
 *      without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 ******************************************************************************
 */
 
 /* Includes ------------------------------------------------------------------*/


#include "PLC_class.h"

/**
  * @brief      Mirrors input data  
  * @param      Input channel state buffer
  * @retval     Input buffer state
  */
uint8_t PLC::signalMirror(uint8_t In_Array)
{
  return(In_Array);
}

void PLC::handleFreezeTo(void)
{
    freezeTo = true;
}

/**
  * @brief      Freeze selected output for a given time
  * @param      Output channels to be freezed
  * @param      Duration of freeze
  * @retval     Output value
  */
uint8_t PLC::outputFreeze(uint8_t N_Channel, uint16_t msec)
{
  if(freezeTo) {
      timeout.detach();
      return(0x00);
  } else if(!attached) {
      attached = true;
      timeout.attach(this, &PLC::handleFreezeTo, msec/1000);
  }
  
  return N_Channel;
}

/**
  * @brief      Regroup output buffer according to out_Array  
  * @param      Regroup array
  * @retval     Value
  */
uint8_t PLC::outputRegroup(uint8_t Out_Array)
{
  return(Out_Array);
}

/**
  * @brief      Sum all the inputs at high state 
  * @param      Input channel state data
  * @retval     Value corresponding to the sum of inputs at high
  */
uint8_t PLC::inputSum(uint8_t* Buffer, uint8_t In_Array)
{
  
  uint8_t inputChannelsOn = 0;
  uint8_t count = 0;
  *Buffer = In_Array;

  for(count = 0; count<8; count++)
  {
    if((In_Array & 0x01) == 0x01)
      inputChannelsOn++;
    
    In_Array = In_Array >> 1;
  }
  
  return inputChannelsOn;
  
}

/**
  * @brief      Set the output channels on/off 
  * @param      Output to set
  * @retval     Output value 
  */
uint8_t PLC::setOutput(uint8_t Out_Array)
{
  return(Out_Array); 
}

/**
  * @brief      AND Inputs for selected output channels
  * @param      Input channels state
  * @param      Outputs to be AND with inputs
  * @retval     Result of AND operation
  */
uint8_t PLC::inputsAND(uint8_t In_Array, uint8_t Out_Channel)
{
  uint8_t outArray = 0;
  outArray = In_Array & Out_Channel;
  
  return outArray;
}

/**
  * @brief      OR Inputs for selected output channels
  * @param      Input channels state
  * @param      Outputs to be OR with inputs
  * @retval     Result of OR operation
  */
uint8_t PLC::inputsOR(uint8_t In_Array, uint8_t Out_Channel)
{
  uint8_t outArray = 0;
  outArray = In_Array | Out_Channel;
  
  return outArray;
}

/**
  * @brief      NOT Inputs
  * @param      Input channels state
  * @retval     Result of OR operation
  */
uint8_t PLC::inputsNOT(uint8_t In_Array)
{
  uint8_t outArray = 0;
  In_Array = ~(In_Array);
  outArray = In_Array;
  
  return outArray;
}

/**
  * @brief      XOR Inputs for selected output channels
  * @param      Input channels state
  * @param      Outputs to be XOR with inputs
  * @retval     Result of XOR operation
  */
uint8_t PLC::inputsXOR(uint8_t In_Array, uint8_t Out_Channel)
{
  uint8_t outArray = 0;
  outArray = In_Array ^ Out_Channel;
  
  return outArray;
}

/**
  * @brief      Calculate and set parity bits for Ssrelay transmission
  * @param      Output value buffer
  * @retval     None
  */
void PLC::outputParityBits(uint8_t* Buffer)
{
  uint8_t Parity_Cal0 = 0x00;
  uint8_t Parity_Cal1 = 0x00;
  uint8_t Parity_Cal2 = 0x00;
  uint8_t Parity_Cal3 = 0x00;
  uint8_t Parity_Cal4 = 0x00;
  uint8_t Parity_Cal5 = 0x00;
  uint8_t Parity_Cal6 = 0x00;
  uint8_t Parity_Cal7 = 0x00;
  uint8_t nP0 = 0x00;
  uint8_t P0 = 0x00;
  uint8_t P1 = 0x00;
  uint8_t P2 = 0x00;

  Parity_Cal0 = Buffer[1] & 0x80;
  Parity_Cal0 = Parity_Cal0>>7;
  
  Parity_Cal1 = Buffer[1] & 0x40;
  Parity_Cal1 = Parity_Cal1>>6;
  
  Parity_Cal2 = Buffer[1] & 0x20;
  Parity_Cal2 = Parity_Cal2>>5;
  
  Parity_Cal3 = Buffer[1] & 0x10;
  Parity_Cal3 = Parity_Cal3>>4;
  
  Parity_Cal4 = Buffer[1] & 0x08;
  Parity_Cal4 = Parity_Cal4>>3;
  
  Parity_Cal5 = Buffer[1] & 0x04;
  Parity_Cal5 = Parity_Cal5>>2;
  
  Parity_Cal6 = Buffer[1] & 0x02;
  Parity_Cal6 = Parity_Cal6>>1;
  
  Parity_Cal7 = Buffer[1] & 0x01;
 
  
  /* Caluculate parity bits based on output data */
  P2 = ((Parity_Cal7^Parity_Cal5)^Parity_Cal3)^Parity_Cal1;
  if(P2 == 0x01) 
    P2 = 0x08;
  else
    P2 = 0x00;
 
  P1 = ((Parity_Cal6^Parity_Cal4)^Parity_Cal2)^Parity_Cal0;
  if(P1 == 0x01)
    P1 = 0x04;
  else
    P1 = 0x00;
  
  P0 = ((((((Parity_Cal7^Parity_Cal6)^Parity_Cal5)^Parity_Cal4)^Parity_Cal3)
         ^Parity_Cal2)^Parity_Cal1)^Parity_Cal0;
  if(P0 == 0x01)
    P0 = 0X02;
  else
    P0 = 0x00;
  
  nP0 = 0x00;
  if(P0 == 0x02)
    nP0 = 0x00;
  else
    nP0 = 0x01;
  
  /* Set Ssrelay_TxBuffer parity bits field */
  Buffer[0] = P2|P1|P0|nP0;
}

/**
  * @brief      Toggle selected output for given frequency
  * @param      Output channels to be toggled
  * @retval     None
  */
void PLC::outputCycling(void)
{
    if(!attached) {
          attached = true;
          ticker.attach(this, &PLC::toggleOutput, 0.3);
    }

}

void PLC::toggleOutput(void)
{
  /* Reset & set CS1 to refresh VNI watchdog */
  plcIn.setInputSPI(0);
  plcIn.setInputSPI(1);

  outBuff[1] = ~(outBuff[1]);

  /* Parity bits calculation */
  outputParityBits(outBuff);

  /* Transmit data to VNI on SPI */
  plcOut.Ssrelay_SetOutput(outBuff);
}

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/