cp1616_io_controller.cpp
Go to the documentation of this file.
00001 /*********************************************************************************************/
00021 #ifndef CP1616_IO_CONTROLLER_CPP
00022 #define CP1616_IO_CONTROLLER_CPP
00023 
00024 #include <cp1616/cp1616_io_controller.h>
00025 #include <cp1616/cp1616_io_controller_callbacks.h>
00026 
00027 namespace cp1616
00028 {
00029 //Define and initialize controller instance_ to zero value
00030 Cp1616IOController *Cp1616IOController::controller_instance_ = 0;
00031 
00032 Cp1616IOController* Cp1616IOController::getControllerInstance()
00033 {
00034   if( !controller_instance_ )
00035   {
00036     controller_instance_ = new Cp1616IOController();
00037   }
00038   return controller_instance_;
00039 }
00040 
00041 Cp1616IOController::Cp1616IOController() :
00042   cp_ready_(0),
00043   sem_mod_change_(0),
00044   cp_id_(1),
00045   cp_handle_(0),
00046   cp_current_mode_(PNIO_MODE_OFFLINE),
00047   cp_local_state_(PNIO_S_GOOD),
00048   input_module_count_(0),
00049   output_module_count_(0),
00050   input_module_total_data_size_(0),
00051   output_module_total_data_size_(0)
00052 {
00053   //Allocate memory for Input module variables
00054   input_module_data_length_.resize(NUM_OF_INPUT_MODULES);
00055   input_module_state_.resize(NUM_OF_INPUT_MODULES);
00056   input_module_address_.resize(NUM_OF_INPUT_MODULES);
00057 
00058   //Allocate memory for Output module variables
00059   output_module_data_length_.resize(NUM_OF_OUTPUT_MODULES);  
00060   output_module_state_.resize(NUM_OF_OUTPUT_MODULES);
00061   output_module_address_.resize(NUM_OF_OUTPUT_MODULES);
00062 }
00063 
00064 Cp1616IOController::~Cp1616IOController()
00065 {
00066   
00067 }
00068 
00069 void Cp1616IOController::configureControllerData()
00070 {
00071   //Allocate memory registered input modules
00072   if(input_module_count_ > 0)    //if any input module available
00073   {
00074     std::vector<PNIO_UINT8> temp;  //a temporary row
00075     unsigned int i,j;
00076     
00077     for(i = 0; i < input_module_count_; i++)  //allocate memory for 2D array of input data (variable row size)
00078     {
00079       for(j = 0; j < input_module_data_length_[input_module_count_]; j++)
00080       temp.push_back(0);//fill temp row with zeros according to input_module_data_length_ values
00081 
00082       input_module_data_.push_back(temp);  //add row to input_module_data_
00083       temp.clear();                        //clear temp row
00084     }
00085      
00086 
00087     //Print InData array information
00088     ROS_INFO_STREAM("Input Data Array: [Total size: " << input_module_total_data_size_ << " bytes]");
00089     for(i = 0; i < input_module_count_; i++)
00090     {
00091       if((input_module_data_length_[i]-1) == 0)
00092       {
00093         ROS_INFO_STREAM("I: "<< input_module_address_[i].u.Addr
00094           << " - " << input_module_address_[i].u.Addr + input_module_data_length_[i] - 1
00095           << ": InData  "  << "[" << i << "]" << "[0]");
00096       }
00097       else
00098       {
00099         ROS_INFO_STREAM("I: "<< input_module_address_[i].u.Addr
00100           << " - " << input_module_address_[i].u.Addr + input_module_data_length_[i] - 1
00101           << ": InData  "  << "[" << i << "]" << "[0] ... "
00102           << "[" << i << "]" << "[" << input_module_data_length_[i]-1 << "]");
00103       }
00104     }
00105   }
00106 
00107   //Allocate memory for registered output modules
00108   if(output_module_count_ > 0)    //if any output module available
00109   {
00110     std::vector<PNIO_UINT8> temp;  //a temporary row
00111     unsigned int i,j;
00112    
00113     for(i = 0; i < output_module_count_; i++)  //allocate memory for 2D array of input data (variable row size)
00114     {
00115       for(j = 0; j < output_module_data_length_[output_module_count_]; j++)
00116       temp.push_back(0);    //fill temp row with zeros according to input_module_data_length_ values
00117 
00118       output_module_data_.push_back(temp);  //add row to input_module_data_
00119       temp.clear();                        //clear temp row
00120     }
00121 
00122     //Print OutData array information
00123     ROS_INFO_STREAM("Output Data Array: [Total size: " << output_module_total_data_size_ << " bytes]");
00124     for(i = 0; i < output_module_count_; i++)
00125     {
00126       if((output_module_data_length_[i]-1) == 0)
00127       {
00128         ROS_INFO_STREAM("I: "<< output_module_address_[i].u.Addr
00129           << " - " << output_module_address_[i].u.Addr + output_module_data_length_[i] - 1
00130           << ": OutData "  << "[" << i << "]" << "[0]");
00131       }
00132       else
00133       {
00134          ROS_INFO_STREAM("I: " << output_module_address_[i].u.Addr
00135            << " - " << output_module_address_[i].u.Addr + output_module_data_length_[i] - 1
00136            << ": OutData "  << "[" << i << "]" << "[0] ... "
00137            << "[" << i << "]" << "[" << output_module_data_length_[i]-1 << "]");
00138       }
00139     }
00140   }
00141 }
00142 
00143 int Cp1616IOController::addInputModule(unsigned int input_size, unsigned int input_start_address)
00144 {
00145   if(cp_current_mode_ == PNIO_MODE_OPERATE)
00146   {
00147     ROS_ERROR_STREAM("Not able to add Input module in Operate state!");
00148     return PNIO_ERR_SEQUENCE;
00149   }
00150   else if(input_module_count_ >= NUM_OF_INPUT_MODULES)
00151   {
00152     ROS_ERROR_STREAM("Not able to add antoher input module. Max count reached!");
00153     return PNIO_ERR_SEQUENCE;
00154   }
00155   else
00156   {
00157     //Set variables required for PNIO_data_read function
00158     input_module_data_length_[input_module_count_] = input_size;                 //number of transferred bytes
00159     input_module_state_[input_module_count_]  = PNIO_S_BAD;                      //initial Input State
00160     input_module_address_[input_module_count_].AddrType = PNIO_ADDR_LOG;         //Address type
00161     input_module_address_[input_module_count_].IODataType = PNIO_IO_IN;          //Data type
00162     input_module_address_[input_module_count_].u.Addr = input_start_address;     //Module memory address
00163 
00164     
00165     ROS_DEBUG("Input module: Size: %d I: %d - %d",
00166       input_module_data_length_[input_module_count_],
00167       input_module_address_[input_module_count_].u.Addr,
00168       input_module_address_[input_module_count_].u.Addr + input_module_data_length_[input_module_count_] - 1);
00169     
00170     input_module_count_++;                         //increment deviceInputCount
00171     input_module_total_data_size_ += input_size;   //save overall Input Size
00172 
00173     return PNIO_OK;
00174   }
00175 }
00176 
00177 int Cp1616IOController::addOutputModule(unsigned int output_size, unsigned int output_start_address)
00178 {
00179   if(cp_current_mode_ == PNIO_MODE_OPERATE)
00180   {
00181     ROS_ERROR_STREAM("Error: not able to add Output module in Operate state!");
00182     return PNIO_ERR_SEQUENCE;
00183   }
00184   else if(output_module_count_ >= NUM_OF_INPUT_MODULES)
00185   {
00186     ROS_ERROR_STREAM("Error: Not able to add antoher module. Max count reached!");
00187     return PNIO_ERR_SEQUENCE;
00188   }
00189   else
00190   {
00191     //Set variables required for PNIO_data_write function
00192     output_module_data_length_[output_module_count_] = output_size;              //number of transferred bytes
00193     output_module_state_[output_module_count_]  = PNIO_S_BAD;                    //initial Input State
00194     output_module_address_[output_module_count_].AddrType = PNIO_ADDR_LOG;       //Address type
00195     output_module_address_[output_module_count_].IODataType = PNIO_IO_OUT;       //Data type
00196     output_module_address_[output_module_count_].u.Addr = output_start_address;  //Module memory address
00197 
00198   
00199     ROS_DEBUG("Output module: Size: %d Q: %d - %d",
00200       output_module_data_length_[output_module_count_],
00201       output_module_address_[output_module_count_].u.Addr,
00202       output_module_address_[output_module_count_].u.Addr + output_module_data_length_[output_module_count_] - 1);
00203     
00204     output_module_count_++;                              //increment deviceOutputCount
00205     output_module_total_data_size_ += output_size;       //save overall Output Size
00206 
00207     return PNIO_OK;
00208   }
00209 }
00210 
00211 int Cp1616IOController::init()
00212 {
00213   PNIO_UINT32 error_code = PNIO_OK;
00214 
00215   //Configure Controller Data
00216   configureControllerData();
00217 
00218   //Open PNIO_Controller
00219   
00220   //Connect to CP and obtain handle
00221   error_code = PNIO_controller_open(
00222               cp_id_,
00223               PNIO_CEP_MODE_CTRL,
00224               &pnio_controller_callbacks::dsReadConf,
00225               &pnio_controller_callbacks::dsWriteConf,
00226               &pnio_controller_callbacks::alarmIndication,
00227               &cp_handle_);
00228 
00229   //Check errors
00230   if(error_code != PNIO_OK)
00231   {
00232     ROS_ERROR("Not able to open PNIO_controller: Error: 0x%x", (int)error_code);
00233     return (int)error_code;
00234   }
00235   else
00236     ROS_INFO_STREAM("Openning CP1616 in IO_controller mode: done");
00237 
00238   //register modeChangeIndication callback for mode changes confirmation
00239   error_code = PNIO_register_cbf(
00240                 cp_handle_,
00241                 PNIO_CBE_MODE_IND,
00242                 &pnio_controller_callbacks::modeChangeIndication);
00243 
00244   //Check errors
00245   if(error_code != PNIO_OK)
00246   {
00247     ROS_ERROR("Error in PNIO_register_cbf: callbackForModeChangeIndication: 0x%x", (int)error_code);
00248     PNIO_close(cp_handle_);
00249     return (int)error_code;
00250   }
00251 
00252   //register deviceActivation callback for device activation confirmation
00253   error_code = PNIO_register_cbf(
00254                 cp_handle_,
00255                 PNIO_CBE_DEV_ACT_CONF,
00256                 &pnio_controller_callbacks::deviceActivation);
00257 
00258   if(error_code != PNIO_OK)
00259   {
00260     ROS_ERROR_STREAM("Error in PNIO_register_cbf: callbackForDeviceActivation: 0x%x" << (int)error_code);
00261     PNIO_close(cp_handle_);
00262     return (int)error_code;
00263   }
00264 
00265   //Change CP mode to Operate
00266   error_code = changePnioMode(PNIO_MODE_OPERATE);
00267   if(error_code != PNIO_OK)
00268   {
00269       PNIO_close(cp_handle_);
00270       return (int)error_code;
00271   }
00272 
00273   //Start communication
00274   unsigned int i = 0;
00275 
00276   while(cp_ready_ == 0) //Wait for cp_ready flag to be set by alarmIndication callback
00277   {
00278     i++;
00279     usleep(WAIT_FOR_CALLBACKS_PERIOD);
00280     if(i == MAX_NUM_OF_INIT_ATTEMPTS)
00281     {
00282       ROS_ERROR_STREAM("Not able to start communication, Uninitializing...");
00283       return PNIO_ERR_NO_CONNECTION;
00284     }
00285   }
00286   return (int)error_code;  //if everything OK return PNIO_OK
00287 }
00288 
00289 int Cp1616IOController::uinit()
00290 {
00291   PNIO_UINT32 error_code = PNIO_OK;
00292 
00293   //Change CP mode to OFFLINE
00294   error_code = changePnioMode(PNIO_MODE_OFFLINE);
00295   if(error_code != PNIO_OK)
00296   {
00297       PNIO_close(cp_handle_);
00298       return (int)error_code;
00299   }
00300 
00301   error_code = PNIO_close(cp_handle_);
00302 
00303   if(error_code != PNIO_OK)
00304     ROS_ERROR_STREAM("Not able to uninitialize IO_Controller: Error 0x%x" << (int)error_code);
00305   else
00306     ROS_INFO_STREAM("Uninitializing IO_Controller: done");
00307 
00308   return (int)error_code;  //if everything OK return PNIO_OK
00309 }
00310 
00311 int Cp1616IOController::changePnioMode(PNIO_MODE_TYPE requested_mode)
00312 {
00313   PNIO_UINT32 error_code;
00314   PNIO_UINT32 valid_cp_handle = cp_handle_;
00315 
00316   //set required mode
00317   error_code = PNIO_set_mode(cp_handle_, requested_mode);
00318 
00319   if(error_code != PNIO_OK)
00320   {
00321     ROS_ERROR_STREAM("Not able to change IO_Controller mode: Error 0x%x" << (int)error_code);
00322     PNIO_close(cp_handle_);     //Close PNIO_Controller
00323     return (int)error_code;
00324   }
00325 
00326   if(cp_handle_ == valid_cp_handle)  //check if CpHandle still valid
00327   {
00328     //wait for a callback_for_mode_change_indication
00329     while(!sem_mod_change_){
00330     usleep(WAIT_FOR_CALLBACKS_PERIOD);
00331     }
00332 
00333     setSemModChange(0);
00334   }
00335 
00336   //check if the current mode is correct
00337   if(cp_current_mode_ != requested_mode)
00338   {
00339     ROS_ERROR_STREAM("Not able to set required mode: ERROR another mode recieved");
00340     PNIO_close(cp_handle_);
00341   }
00342   else
00343     ROS_INFO_STREAM("Changing IO_controller mode: done");
00344 
00345   return (int)error_code;
00346 }
00347 
00348 int Cp1616IOController::updateCyclicInputData()
00349 {
00350   PNIO_UINT32 error_code;
00351   PNIO_UINT32 bytes_read;
00352 
00353   unsigned int i;
00354 
00355   for(i = 0; i < input_module_count_; i++)
00356   {
00357     error_code = PNIO_data_read(
00358                     cp_handle_,                               // handle
00359                     &input_module_address_[i],                // pointer to device input address
00360                     input_module_data_length_[i],             // length in bytes of input
00361                     &bytes_read,                              // number of bytes read
00362                     &input_module_data_[i][0],                // pointer to input data row
00363                     cp_local_state_,                          // local status
00364                     (PNIO_IOXS*)&(input_module_state_[i]));   // remote status
00365 
00366     if(error_code != PNIO_OK)
00367       ROS_DEBUG("PNIO_read_data (PNIO_CBE_DEV_ACT_CONF,..) returned 0x%x", (int)error_code);
00368     
00369   }
00370 
00371   return (int)error_code;
00372 }
00373 
00374 int Cp1616IOController::updateCyclicOutputData()
00375 {
00376   PNIO_UINT32 error_code;
00377   unsigned int i;
00378 
00379   for(i = 0; i < output_module_count_; i++)
00380   {
00381     error_code = PNIO_data_write(
00382                     cp_handle_,                               // handle
00383                     &output_module_address_[i],               // pointer to device output address
00384                     output_module_data_length_[i],            // length in bytes of output
00385                     &output_module_data_[i][0],               // pointer to output data row
00386                     cp_local_state_,                          // local status
00387                     (PNIO_IOXS*)&(output_module_state_[i]));  // remote status
00388 
00389     if(error_code != PNIO_OK)
00390         ROS_DEBUG("PNIO_read_data (PNIO_CBE_DEV_ACT_CONF,..) returned 0x%x", (int)error_code);
00391     
00392   }
00393 
00394   return (int)error_code;
00395 }
00396 
00397 void Cp1616IOController::printOutputData(unsigned int module)
00398 {
00399     std::cout << "Output m." << module << std::dec
00400               << " [Q: " << output_module_address_[module].u.Addr
00401               << " - "  << output_module_address_[module].u.Addr + output_module_data_length_[module]-1
00402               << "]: ";
00403 
00404     for(int i = 0; i < output_module_data_length_[module]; i++)
00405         std::cout <<  std::setfill(' ') << std::setw(2) << std::hex << (int)output_module_data_[module][i] << " ";
00406 
00407     std::cout << std::endl;
00408 }
00409 
00410 void Cp1616IOController::printInputData(unsigned int module)
00411 {
00412     std::cout << "Input  m." << module << std::dec
00413                << " [I: " << input_module_address_[module].u.Addr
00414                << " - "  << input_module_address_[module].u.Addr + input_module_data_length_[module]-1
00415                << "]: ";
00416 
00417     for(int i = 0; i < input_module_data_length_[module]; i++)
00418         std::cout <<  std::setfill(' ') << std::setw(2) << std::hex << (int)input_module_data_[module][i] << " ";
00419 
00420     std::cout << std::endl;
00421 }
00422 
00423 void Cp1616IOController::setCpReady(int cp_ready_value)
00424 {
00425   cp_ready_ = cp_ready_value;
00426 }
00427 
00428 int Cp1616IOController::getCpReady()
00429 {
00430   return (cp_ready_);
00431 }
00432 
00433 void Cp1616IOController::setCpCurrentModeFlag(PNIO_MODE_TYPE mode)
00434 {
00435   if((mode == PNIO_MODE_OFFLINE) || (mode == PNIO_MODE_CLEAR) || (mode == PNIO_MODE_OPERATE))
00436     cp_current_mode_ = mode;
00437   else
00438     ROS_WARN("Not able to set cp_current_mode_ to %d state", (int)mode);
00439 }
00440 
00441 PNIO_MODE_TYPE Cp1616IOController::getCpCurrentModeFlag()
00442 {
00443   return(cp_current_mode_);
00444 }
00445 
00446 void Cp1616IOController::setSemModChange(int mod_change)
00447 {
00448   sem_mod_change_ = mod_change;
00449 }
00450 
00451 } //cp1616
00452 
00453 #endif //CP1616_IO_CONTROLLER_CPP


cp1616
Author(s):
autogenerated on Fri Aug 28 2015 13:08:36