ST / X_NUCLEO_PLC01A1

Dependents:   HelloWorld_PLC01A1

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers XNucleoPLC01A1.cpp Source File

XNucleoPLC01A1.cpp

Go to the documentation of this file.
00001 /**
00002  ******************************************************************************
00003  * @file    XNucleoPLC01A1.cpp
00004  * @author  AST/CL
00005  * @version V1.1.0
00006  * @date    February 23rd, 2016
00007  * @brief   Implementation file for the X_NUCLEO_PLC01A1 expansion board.
00008  ******************************************************************************
00009  * @attention
00010  *
00011  * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
00012  *
00013  * Redistribution and use in source and binary forms, with or without modification,
00014  * are permitted provided that the following conditions are met:
00015  *   1. Redistributions of source code must retain the above copyright notice,
00016  *      this list of conditions and the following disclaimer.
00017  *   2. Redistributions in binary form must reproduce the above copyright notice,
00018  *      this list of conditions and the following disclaimer in the documentation
00019  *      and/or other materials provided with the distribution.
00020  *   3. Neither the name of STMicroelectronics nor the names of its contributors
00021  *      may be used to endorse or promote products derived from this software
00022  *      without specific prior written permission.
00023  *
00024  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00025  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00026  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00027  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
00028  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00029  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00030  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00031  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00032  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00033  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00034  *
00035  ******************************************************************************
00036  */
00037  
00038  
00039 /* Includes ------------------------------------------------------------------*/
00040 
00041 /* ACTION 1 ------------------------------------------------------------------*
00042  * Include here platform specific header files.                               *
00043  *----------------------------------------------------------------------------*/
00044 #include "mbed.h"
00045 /* ACTION 2 ------------------------------------------------------------------*
00046  * Include here expansion board specific header files.                        *
00047  *----------------------------------------------------------------------------*/
00048 #include "XNucleoPLC01A1.h"
00049 
00050 
00051 /**
00052   * @brief      Mirrors input data  
00053   * @param      Input channel state buffer
00054   * @retval     Input buffer state
00055   */
00056 uint8_t XNucleoPLC01A1::signal_mirror(uint8_t In_Array)
00057 {
00058   return(In_Array);
00059 }
00060 
00061 void XNucleoPLC01A1::handle_freeze_to(void)
00062 {
00063     freezeTo = true;
00064 }
00065 
00066 /**
00067   * @brief      Freeze selected output for a given time
00068   * @param      Output channels to be freezed
00069   * @param      Duration of freeze
00070   * @retval     Output value
00071   */
00072 uint8_t XNucleoPLC01A1::output_freeze(uint8_t N_Channel, uint16_t msec)
00073 {
00074   if (freezeTo) {
00075       timeout.detach();
00076       return(0x00);
00077   } else if(!attached) {
00078       attached = true;
00079       timeout.attach(callback(this, &XNucleoPLC01A1::handle_freeze_to), chrono::microseconds(msec*1000));
00080   }
00081   
00082   return N_Channel;
00083 }
00084 
00085 /**
00086   * @brief      Regroup output buffer according to out_Array  
00087   * @param      Regroup array
00088   * @retval     Value
00089   */
00090 uint8_t XNucleoPLC01A1::output_regroup(uint8_t Out_Array)
00091 {
00092   return(Out_Array);
00093 }
00094 
00095 /**
00096   * @brief      Sum all the inputs at high state 
00097   * @param      Input channel state data
00098   * @retval     Value corresponding to the sum of inputs at high
00099   */
00100 uint8_t XNucleoPLC01A1::input_sum(uint8_t* Buffer, uint8_t In_Array)
00101 {
00102   
00103   uint8_t inputChannelsOn = 0;
00104   uint8_t count = 0;
00105   *Buffer = In_Array;
00106 
00107   for(count = 0; count<8; count++)
00108   {
00109     if ((In_Array & 0x01) == 0x01) {
00110       inputChannelsOn++;
00111     }
00112     
00113     In_Array = In_Array >> 1;
00114   }
00115   
00116   return inputChannelsOn;
00117   
00118 }
00119 
00120 /**
00121   * @brief      Set the output channels on/off 
00122   * @param      Output to set
00123   * @retval     Output value 
00124   */
00125 uint8_t XNucleoPLC01A1::set_output(uint8_t Out_Array)
00126 {
00127   return(Out_Array); 
00128 }
00129 
00130 /**
00131   * @brief      AND Inputs for selected output channels
00132   * @param      Input channels state
00133   * @param      Outputs to be AND with inputs
00134   * @retval     Result of AND operation
00135   */
00136 uint8_t XNucleoPLC01A1::inputs_and(uint8_t In_Array, uint8_t Out_Channel)
00137 {
00138   uint8_t outArray = 0;
00139   outArray = In_Array & Out_Channel;
00140   
00141   return outArray;
00142 }
00143 
00144 /**
00145   * @brief      OR Inputs for selected output channels
00146   * @param      Input channels state
00147   * @param      Outputs to be OR with inputs
00148   * @retval     Result of OR operation
00149   */
00150 uint8_t XNucleoPLC01A1::inputs_or(uint8_t In_Array, uint8_t Out_Channel)
00151 {
00152   uint8_t outArray = 0;
00153   outArray = In_Array | Out_Channel;
00154   
00155   return outArray;
00156 }
00157 
00158 /**
00159   * @brief      NOT Inputs
00160   * @param      Input channels state
00161   * @retval     Result of OR operation
00162   */
00163 uint8_t XNucleoPLC01A1::inputs_not(uint8_t In_Array)
00164 {
00165   uint8_t outArray = 0;
00166   In_Array = ~(In_Array);
00167   outArray = In_Array;
00168   
00169   return outArray;
00170 }
00171 
00172 /**
00173   * @brief      XOR Inputs for selected output channels
00174   * @param      Input channels state
00175   * @param      Outputs to be XOR with inputs
00176   * @retval     Result of XOR operation
00177   */
00178 uint8_t XNucleoPLC01A1::inputs_xor(uint8_t In_Array, uint8_t Out_Channel)
00179 {
00180   uint8_t outArray = 0;
00181   outArray = In_Array ^ Out_Channel;
00182   
00183   return outArray;
00184 }
00185 
00186 /**
00187   * @brief      Calculate and set parity bits for Ssrelay transmission
00188   * @param      Output value buffer
00189   * @retval     None
00190   */
00191 void XNucleoPLC01A1::output_parity_bits(uint8_t* Buffer)
00192 {
00193   uint8_t Parity_Cal0 = 0x00;
00194   uint8_t Parity_Cal1 = 0x00;
00195   uint8_t Parity_Cal2 = 0x00;
00196   uint8_t Parity_Cal3 = 0x00;
00197   uint8_t Parity_Cal4 = 0x00;
00198   uint8_t Parity_Cal5 = 0x00;
00199   uint8_t Parity_Cal6 = 0x00;
00200   uint8_t Parity_Cal7 = 0x00;
00201   uint8_t nP0 = 0x00;
00202   uint8_t P0 = 0x00;
00203   uint8_t P1 = 0x00;
00204   uint8_t P2 = 0x00;
00205 
00206   Parity_Cal0 = Buffer[1] & 0x80;
00207   Parity_Cal0 = Parity_Cal0>>7;
00208   
00209   Parity_Cal1 = Buffer[1] & 0x40;
00210   Parity_Cal1 = Parity_Cal1>>6;
00211   
00212   Parity_Cal2 = Buffer[1] & 0x20;
00213   Parity_Cal2 = Parity_Cal2>>5;
00214   
00215   Parity_Cal3 = Buffer[1] & 0x10;
00216   Parity_Cal3 = Parity_Cal3>>4;
00217   
00218   Parity_Cal4 = Buffer[1] & 0x08;
00219   Parity_Cal4 = Parity_Cal4>>3;
00220   
00221   Parity_Cal5 = Buffer[1] & 0x04;
00222   Parity_Cal5 = Parity_Cal5>>2;
00223   
00224   Parity_Cal6 = Buffer[1] & 0x02;
00225   Parity_Cal6 = Parity_Cal6>>1;
00226   
00227   Parity_Cal7 = Buffer[1] & 0x01;
00228  
00229   
00230   /* Caluculate parity bits based on output data */
00231   P2 = ((Parity_Cal7^Parity_Cal5)^Parity_Cal3)^Parity_Cal1;
00232   if (P2 == 0x01) {
00233     P2 = 0x08;
00234   } else {
00235     P2 = 0x00;
00236   }
00237  
00238   P1 = ((Parity_Cal6^Parity_Cal4)^Parity_Cal2)^Parity_Cal0;
00239   if (P1 == 0x01) {
00240     P1 = 0x04;
00241   } else {
00242     P1 = 0x00;
00243   }
00244   
00245   P0 = ((((((Parity_Cal7^Parity_Cal6)^Parity_Cal5)^Parity_Cal4)^Parity_Cal3)
00246          ^Parity_Cal2)^Parity_Cal1)^Parity_Cal0;
00247   if (P0 == 0x01) {
00248     P0 = 0X02;
00249   } else {
00250     P0 = 0x00;
00251   }
00252   
00253   nP0 = 0x00;
00254   if (P0 == 0x02) {
00255     nP0 = 0x00;
00256   } else {
00257     nP0 = 0x01;
00258   }
00259   
00260   /* Set Ssrelay_TxBuffer parity bits field */
00261   Buffer[0] = P2|P1|P0|nP0;
00262 }
00263 
00264 /**
00265   * @brief      Toggle selected output for given frequency
00266   * @param      Output channels to be toggled
00267   * @retval     None
00268   */
00269 void XNucleoPLC01A1::output_cycling(void)
00270 {
00271   if (!attached) {
00272     attached = true;
00273     ticker.attach(callback(this, &XNucleoPLC01A1::toggle_output), chrono::microseconds(3*100*1000));
00274   }
00275 }
00276 
00277 void XNucleoPLC01A1::toggle_output(void)
00278 {
00279   /* Reset & set CS1 to refresh VNI watchdog */
00280   plcIn.set_input_spi(0);
00281   plcIn.set_input_spi(1);
00282 
00283   outBuff[1] = ~(outBuff[1]);
00284 
00285   /* Parity bits calculation */
00286   output_parity_bits(outBuff);
00287 
00288   /* Transmit data to VNI on SPI */
00289   plcOut.ssrelay_set_output(outBuff);
00290 }
00291 
00292 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/