00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "ComediPulseTrainGenerator.hpp"
00019 #include <rtt/Logger.hpp>
00020
00021 #include "comedi_internal.h"
00022 #include "comedi_common.h"
00023
00024 namespace OCL
00025 {
00026 typedef unsigned int Data;
00027
00028 ComediPulseTrainGenerator::ComediPulseTrainGenerator(ComediDevice * cd, unsigned int subd,
00029 const std::string& name)
00030 : PulseTrainGeneratorInterface(name),
00031 _myCard(cd), _subDevice(subd),
00032 _pulse_width(1000000), _pulse_period(1000000), _running(false)
00033 {
00034 init();
00035 }
00036
00037 ComediPulseTrainGenerator::ComediPulseTrainGenerator(ComediDevice * cd, unsigned int subd)
00038 : _myCard(cd), _subDevice(subd),
00039 _pulse_width(1000000), _pulse_period(1000000), _running(false)
00040 {
00041 init();
00042 }
00043
00044 unsigned int ComediPulseTrainGenerator::psecs_to_timebase(psecs picos)
00045 {
00046 if (picos < _smallest_step){
00047 return 0;
00048 }
00049
00050 return (unsigned int)round( double(picos) / _smallest_step );
00051 }
00052
00053 void ComediPulseTrainGenerator::init()
00054 {
00055 Logger::In in("ComediPulseTrainGenerator");
00056 log(Info) << "Creating ComediPulseTrainGenerator" << endlog();
00057
00058 if ( _myCard->getSubDeviceType( _subDevice ) != COMEDI_SUBD_COUNTER ){
00059 log(Error) << "Comedi Counter : subdev is not a counter, Type = "
00060 << _myCard->getSubDeviceType(_subDevice) << endlog();
00061
00062 _myCard = 0;
00063 return;
00064 }
00065
00066 unsigned int nchan = 0;
00067
00068
00069
00070
00071
00072 #if OROCOS_TARGET_LXRT
00073
00074 int sdevs = comedi_get_n_subdevices(_myCard->getDevice()->it);
00075 if ( sdevs == 10 )
00076 nchan = 8;
00077 if ( sdevs == 6 )
00078 nchan = 4;
00079 #else
00080 const char* bn = comedi_get_board_name(_myCard->getDevice()->it);
00081 if ( strncmp(bn, "PCI-6602",8) == 0 )
00082 nchan = 8;
00083 if ( strncmp(bn, "PCI-6601",8) == 0 )
00084 nchan = 4;
00085 #endif
00086
00087 unsigned tbase = 0;
00088 switch(nchan){
00089 case 8:
00090
00091 _smallest_step = PSECS_IN_SECS / 80000000;
00092 _clock_period = 12500;
00093 tbase = NI_GPCT_TIMEBASE_3_CLOCK_SRC_BITS;
00094 log(Info) << "Detected NI-6602."<<endlog();
00095 break;
00096 default:
00097 log(Warning) << "Unknown Comedi Counter card? Could not determine timebase. Using a default."<<endlog();
00098 case 4:
00099
00100 _smallest_step = PSECS_IN_SECS / 20000000;
00101 _clock_period = 50000;
00102 tbase = NI_GPCT_TIMEBASE_1_CLOCK_SRC_BITS;
00103 log(Info) << "Detected NI-6601."<<endlog();
00104 break;
00105 }
00106
00107
00108
00109
00110 unsigned counter_mode = NI_GPCT_COUNTING_MODE_NORMAL_BITS;
00111
00112 counter_mode |= NI_GPCT_OUTPUT_TC_TOGGLE_BITS;
00113
00114 counter_mode |= NI_GPCT_LOADING_ON_TC_BIT;
00115
00116 counter_mode |= NI_GPCT_RELOAD_SOURCE_SWITCHING_BITS;
00117
00118 counter_mode |= NI_GPCT_COUNTING_DIRECTION_DOWN_BITS;
00119
00120 counter_mode |= NI_GPCT_LOAD_B_SELECT_BIT;
00121
00122 counter_mode |= NI_GPCT_STOP_ON_GATE_BITS;
00123
00124 counter_mode |= NI_GPCT_NO_HARDWARE_DISARM_BITS;
00125 int retval = set_counter_mode(_myCard->getDevice()->it, _subDevice, counter_mode);
00126 if(retval < 0) return;
00127
00128
00129 retval = set_clock_source(_myCard->getDevice()->it, _subDevice, tbase, _clock_period/1000);
00130 if(retval < 0) return;
00131
00132 if (retval<0)
00133 log(Error) << "Comedi Counter : Instruction to configure counter -> Pulse Train Generator failed, ret = " << retval << endlog();
00134 else
00135 log(Info) << "Comedi Counter "<< _subDevice << " now configured as Pulse Train Generator" << endlog();
00136 }
00137
00138 ComediPulseTrainGenerator::~ComediPulseTrainGenerator()
00139 {
00140 Logger::In in("ComediPulseTrainGenerator");
00141 if (!_myCard)
00142 return;
00143
00144 int ret = reset_counter(_myCard->getDevice()->it, _subDevice);
00145 if(ret<0){
00146 log(Error) << "Triggering reset on ComediPTG () failed, ret = " << ret << endlog();
00147 }
00148 }
00149
00150
00151 bool ComediPulseTrainGenerator::pulseWidthSet(psecs picos)
00152 {
00153 Logger::In in("ComediPulseTrainGenerator");
00154 if (!_myCard)
00155 return false;
00156
00157 if (picos != _pulse_width){
00158 int retval = 0;
00159 unsigned up_ticks = ( picos + _clock_period / 2) / _clock_period;
00160 unsigned down_ticks = ( _pulse_period + _clock_period / 2) / _clock_period - up_ticks;
00161
00162
00163 retval = comedi_data_write(_myCard->getDevice()->it, _subDevice, 1, 0, 0, down_ticks);
00164 if(retval < 0) return false;
00165
00166
00167 retval = comedi_data_write(_myCard->getDevice()->it, _subDevice, 2, 0, 0, up_ticks);
00168 if(retval < 0) return false;
00169
00170 _pulse_width = picos;
00171 #if 0
00172 printf("Generating pulse train on sub device %d.\n", _subDevice);
00173 printf("Period = %lld ps.\n", _pulse_period);
00174 printf("Up Time = %lld ps.\n", _pulse_width);
00175 printf("Down Time = %lld ps.\n", _pulse_period - _pulse_width);
00176 #endif
00177 }
00178 return true;
00179 }
00180
00181 bool ComediPulseTrainGenerator::pulsePeriodSet(psecs picos)
00182 {
00183 Logger::In in("ComediPulseTrainGenerator");
00184 if (!_myCard)
00185 return false;
00186
00187 if (picos != _pulse_period){
00188 int retval=0;
00189 unsigned up_ticks = (_pulse_width + _clock_period / 2) / _clock_period;
00190 unsigned down_ticks = (picos + _clock_period / 2) / _clock_period - up_ticks;
00191
00192
00193
00194
00195
00196 retval = comedi_data_write(_myCard->getDevice()->it, _subDevice, 1, 0, 0, down_ticks);
00197 if(retval < 0) return false;
00198
00199
00200 retval = comedi_data_write(_myCard->getDevice()->it, _subDevice, 2, 0, 0, up_ticks);
00201 if(retval < 0) return false;
00202
00203 _pulse_period = picos;
00204 #if 0
00205 printf("Generating pulse train on sub device %d.\n", _subDevice);
00206 printf("Period = %lld ps.\n", _pulse_period);
00207 printf("Up Time = %lld ps.\n", _pulse_width);
00208 printf("Down Time = %lld ps.\n", _pulse_period - _pulse_width);
00209 #endif
00210 }
00211 return true;
00212 }
00213
00214 bool ComediPulseTrainGenerator::start()
00215 {
00216 Logger::In in("ComediPulseTrainGenerator");
00217 if (!_myCard)
00218 return false;
00219 if (_running == false){
00220 int retval;
00221
00222 unsigned up_ticks = (_pulse_width + _clock_period / 2) / _clock_period;
00223 unsigned down_ticks = (_pulse_period + _clock_period / 2) / _clock_period - up_ticks;
00224 retval = comedi_data_write(_myCard->getDevice()->it, _subDevice, 0, 0, 0, down_ticks);
00225 if(retval < 0) return false;
00226
00227
00228 retval = comedi_data_write(_myCard->getDevice()->it, _subDevice, 1, 0, 0, down_ticks);
00229 if(retval < 0) return false;
00230
00231
00232 retval = comedi_data_write(_myCard->getDevice()->it, _subDevice, 2, 0, 0, up_ticks);
00233 if(retval < 0) return false;
00234
00235 int ret = arm(_myCard->getDevice()->it, _subDevice, NI_GPCT_ARM_IMMEDIATE);
00236 if(ret<0){
00237 log(Error) << "ComediPTG "<<_subDevice<<": start() failed, ret = " << ret << endlog();
00238 log(Error) << "pulse width: " << _pulse_width << ", pulse period: " << _pulse_period <<endlog();
00239 return false;
00240 }
00241 _running = true;
00242 }
00243 return true;
00244 }
00245
00246 bool ComediPulseTrainGenerator::stop()
00247 {
00248 Logger::In in("ComediPulseTrainGenerator");
00249 if (!_myCard)
00250 return false;
00251 if (_running == true){
00252 disarm(_myCard->getDevice()->it, _subDevice);
00253 _running = false;
00254 }
00255 return true;
00256 }
00257
00258 }