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
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
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
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
00072 if(input_module_count_ > 0)
00073 {
00074 std::vector<PNIO_UINT8> temp;
00075 unsigned int i,j;
00076
00077 for(i = 0; i < input_module_count_; i++)
00078 {
00079 for(j = 0; j < input_module_data_length_[input_module_count_]; j++)
00080 temp.push_back(0);
00081
00082 input_module_data_.push_back(temp);
00083 temp.clear();
00084 }
00085
00086
00087
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
00108 if(output_module_count_ > 0)
00109 {
00110 std::vector<PNIO_UINT8> temp;
00111 unsigned int i,j;
00112
00113 for(i = 0; i < output_module_count_; i++)
00114 {
00115 for(j = 0; j < output_module_data_length_[output_module_count_]; j++)
00116 temp.push_back(0);
00117
00118 output_module_data_.push_back(temp);
00119 temp.clear();
00120 }
00121
00122
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
00158 input_module_data_length_[input_module_count_] = input_size;
00159 input_module_state_[input_module_count_] = PNIO_S_BAD;
00160 input_module_address_[input_module_count_].AddrType = PNIO_ADDR_LOG;
00161 input_module_address_[input_module_count_].IODataType = PNIO_IO_IN;
00162 input_module_address_[input_module_count_].u.Addr = input_start_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_++;
00171 input_module_total_data_size_ += 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
00192 output_module_data_length_[output_module_count_] = output_size;
00193 output_module_state_[output_module_count_] = PNIO_S_BAD;
00194 output_module_address_[output_module_count_].AddrType = PNIO_ADDR_LOG;
00195 output_module_address_[output_module_count_].IODataType = PNIO_IO_OUT;
00196 output_module_address_[output_module_count_].u.Addr = output_start_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_++;
00205 output_module_total_data_size_ += output_size;
00206
00207 return PNIO_OK;
00208 }
00209 }
00210
00211 int Cp1616IOController::init()
00212 {
00213 PNIO_UINT32 error_code = PNIO_OK;
00214
00215
00216 configureControllerData();
00217
00218
00219
00220
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
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
00239 error_code = PNIO_register_cbf(
00240 cp_handle_,
00241 PNIO_CBE_MODE_IND,
00242 &pnio_controller_callbacks::modeChangeIndication);
00243
00244
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
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
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
00274 unsigned int i = 0;
00275
00276 while(cp_ready_ == 0)
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;
00287 }
00288
00289 int Cp1616IOController::uinit()
00290 {
00291 PNIO_UINT32 error_code = PNIO_OK;
00292
00293
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;
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
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_);
00323 return (int)error_code;
00324 }
00325
00326 if(cp_handle_ == valid_cp_handle)
00327 {
00328
00329 while(!sem_mod_change_){
00330 usleep(WAIT_FOR_CALLBACKS_PERIOD);
00331 }
00332
00333 setSemModChange(0);
00334 }
00335
00336
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_,
00359 &input_module_address_[i],
00360 input_module_data_length_[i],
00361 &bytes_read,
00362 &input_module_data_[i][0],
00363 cp_local_state_,
00364 (PNIO_IOXS*)&(input_module_state_[i]));
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_,
00383 &output_module_address_[i],
00384 output_module_data_length_[i],
00385 &output_module_data_[i][0],
00386 cp_local_state_,
00387 (PNIO_IOXS*)&(output_module_state_[i]));
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 }
00452
00453 #endif //CP1616_IO_CONTROLLER_CPP