00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "LOW_devDS2406.h"
00021 #include "LOW_platformMisc.h"
00022 #include "LOW_helper_msglog.h"
00023 #include "LOW_deviceFactory.h"
00024 #include "LOW_netSegment.h"
00025 #include "LOW_helper_crc.h"
00026
00027
00028
00029
00030
00031
00032
00033
00034 const string LOW_devDS2406::familyName = "DS2406";
00035
00036 int LOW_devDS2406::initHelper = initialize();
00037 int LOW_devDS2406::initialize()
00038 {
00039 LOW_deviceFactory::registerSpecificCtor( familyCode, &LOW_devDS2406::new_Instance);
00040 return 0;
00041 }
00042
00043
00044
00045
00046
00047
00048
00049
00050 LOW_device* LOW_devDS2406::new_Instance( LOW_netSegment &inNetSegment, const LOW_deviceID &inDevID)
00051 {
00052 return new LOW_devDS2406( inNetSegment, inDevID);
00053 }
00054
00055
00056
00057
00058
00059
00060
00061
00062 LOW_devDS2406::LOW_devDS2406( LOW_netSegment &inSegment, const LOW_deviceID &inDevID) :
00063 LOW_device( inSegment, inDevID, familyCode)
00064 {
00065
00066 cmd_ChannelAccess infoGet = cmd_ChannelAccess( *this,
00067 cmd_ChannelAccess::CRC_disable, chanASelect,
00068 cmd_ChannelAccess::asyncInterleaveMode,
00069 cmd_ChannelAccess::noToggleMode, cmd_ChannelAccess::readMode,
00070 cmd_ChannelAccess::resetLatches);
00071 cmd_ChannelAccess::channelInfo_t info = infoGet.getChannelInfo();
00072 isExternalPowered = info.isExternalPowered;
00073 hasPioB = info.hasPioB;
00074 }
00075
00076
00077 LOW_devDS2406::~LOW_devDS2406()
00078 {
00079 }
00080
00081
00082
00083
00084
00085
00086
00087 bool LOW_devDS2406::getIsExternalPowered() const
00088 {
00089 return isExternalPowered;
00090 }
00091
00092
00093 bool LOW_devDS2406::getHasPioB() const
00094 {
00095 return hasPioB;
00096 }
00097
00098
00099 void LOW_devDS2406::getSearchCondition( LOW_devDS2406::statusRegister_t *outStatusRegister) const
00100 {
00101 byteVec_t condReg = byteVec_t( 1);
00102
00103 cmd_ReadStatus( (uint8_t)0x07, condReg);
00104
00105 outStatusRegister->activePolarity = (activePolarity_t)(condReg[0]&0x01);
00106 outStatusRegister->sourceSelect = (sourceSelect_t)((condReg[0]>>1)&0x03);
00107 outStatusRegister->channelSelect = (chanSelect_t)((condReg[0]>>3)&0x03);
00108 outStatusRegister->channelFFQ_pioA = (pioTransistor_t)((condReg[0]>>5)&0x01);
00109 outStatusRegister->channelFFQ_pioB = (pioTransistor_t)((condReg[0]>>6)&0x01);
00110 outStatusRegister->isExternalPowered = (condReg[0]>>7)&0x01;
00111 }
00112
00113
00114 void LOW_devDS2406::setSearchCondition( const LOW_devDS2406::chanSelect_t inChanSelect,
00115 const LOW_devDS2406::sourceSelect_t inSourceSelect,
00116 const LOW_devDS2406::activePolarity_t inPolaritySelect,
00117 const LOW_devDS2406::pioTransistor_t inPioATrans,
00118 const LOW_devDS2406::pioTransistor_t inPioBTrans) const
00119 {
00120 if ( ! getHasPioB() && ( inChanSelect==chanBSelect || inChanSelect==chanBothSelect ) )
00121 throw devDS2406_error( "Channel B selected, but device has only PIO A", __FILE__, __LINE__);
00122
00123 byteVec_t condReg = byteVec_t( 1);
00124
00125 condReg[0] = 0;
00126 condReg[0] |= inPolaritySelect;
00127 condReg[0] |= inSourceSelect<<1;
00128 condReg[0] |= inChanSelect<<3;
00129 condReg[0] |= inPioATrans<<5;
00130 condReg[0] |= inPioBTrans<<6;
00131
00132 cmd_WriteStatus( (uint8_t)0x07, condReg);
00133 }
00134
00135
00136 void LOW_devDS2406::cmd_ReadMemory( const uint8_t inStartAddr, byteVec_t &outBytes) const
00137 {
00138 readMemUniversal( inStartAddr, outBytes, 128, ReadMemory_COMMAND);
00139 }
00140
00141
00142 void LOW_devDS2406::cmd_ReadStatus( const uint8_t inStartAddr, byteVec_t &outBytes) const
00143 {
00144 readMemUniversal( inStartAddr, outBytes, 8, ReadStatus_COMMAND);
00145 }
00146
00147
00148 void LOW_devDS2406::cmd_WriteStatus( const uint8_t inStartAddr, const byteVec_t &inWriteBytes) const
00149 {
00150 if ( inStartAddr+inWriteBytes.size() > 8 )
00151 throw devDS2406_error( "Too many bytes to write", __FILE__, __LINE__);
00152
00153 if ( inStartAddr==0x05 || inStartAddr==0x06 )
00154 throw devDS2406_error( "Address not writeable", __FILE__, __LINE__);
00155
00156
00157 if ( inStartAddr<=0x04 )
00158 throw devDS2406_error( "Access to address not supported in this version", __FILE__, __LINE__);
00159
00160
00161
00162 byteVec_t sendBytes = byteVec_t( 4);
00163 sendBytes[0] = WriteStatus_COMMAND;
00164 sendBytes[1] = inStartAddr&0xff;
00165 sendBytes[2] = inStartAddr>>8;
00166 sendBytes[3] = inWriteBytes[0];
00167
00168 cmd_MatchROM();
00169
00170 getLink().writeData( sendBytes);
00171
00172 uint16_t expectedCrc16 = 0x0000;
00173 expectedCrc16 |= (getLink().readDataByte() ^ 0xff);
00174 expectedCrc16 |= (getLink().readDataByte() ^ 0xff) << 8;
00175 if ( LOW_helper_CRC::calcCRC16( sendBytes) != expectedCrc16 )
00176 throw LOW_helper_CRC::crc_error( "CRC error in write operation", __FILE__, __LINE__);
00177
00178 getLink().writeData( (uint8_t)0xff);
00179
00180
00181
00182
00183 getLink().resetBus();
00184 }
00185
00186
00187
00188
00189
00190
00191
00192
00193 void LOW_devDS2406::readMemUniversal( const uint16_t inStartAddr, byteVec_t &outBytes,
00194 const uint16_t inMaxLen, const owCommand_t inCommand) const
00195 {
00196 if ( inStartAddr >= inMaxLen )
00197 throw devDS2406_error( "Illegal address to read", __FILE__, __LINE__);
00198
00199 if ( inStartAddr+outBytes.size() > inMaxLen )
00200 throw devDS2406_error( "Too many bytes to read", __FILE__, __LINE__);
00201
00202 linkLock lock( *this);
00203
00204 byteVec_t sendBytes = byteVec_t( 3);
00205 sendBytes[0] = inCommand;
00206 sendBytes[1] = inStartAddr&0xff;
00207 sendBytes[2] = inStartAddr>>8;
00208
00209 cmd_MatchROM();
00210
00211 getLink().writeData( sendBytes);
00212 getLink().readData( outBytes);
00213
00214 if ( inStartAddr+outBytes.size() == inMaxLen ) {
00215 uint16_t expectedCrc16 = 0x0000;
00216 expectedCrc16 |= (getLink().readDataByte() ^ 0xff);
00217 expectedCrc16 |= (getLink().readDataByte() ^ 0xff) << 8;
00218 if ( LOW_helper_CRC::calcCRC16( outBytes, LOW_helper_CRC::calcCRC16( sendBytes)) != expectedCrc16 )
00219 throw LOW_helper_CRC::crc_error( "CRC error in read operation", __FILE__, __LINE__);
00220 }
00221
00222 getLink().resetBus();
00223 }
00224
00225
00226
00227
00228
00229
00230
00231
00232 LOW_devDS2406::cmd_ChannelAccess::cmd_ChannelAccess(
00233 const LOW_devDS2406 &inDevice,
00234 const CRCtype_t inCRCtype, const chanSelect_t inChanSelect,
00235 const interleaveMode_t inInterleaveMode, const toggleMode_t inToggleMode,
00236 const initialMode_t inInitialMode, const activityLatchReset_t inALR) :
00237 linkLock( inDevice),
00238 device( inDevice)
00239 {
00240 if ( inChanSelect == noneSelect )
00241 throw devDS2406_error( "At least one channel must be selected", __FILE__, __LINE__);
00242
00243 if ( ! device.getHasPioB() && ( inChanSelect==chanBSelect || inChanSelect==chanBothSelect ) )
00244 throw devDS2406_error( "Channel B selected, but device has only PIO A", __FILE__, __LINE__);
00245
00246 if ( inChanSelect!=chanBothSelect && inInterleaveMode )
00247 throw devDS2406_error( "Interleave mode only available when selected both channels", __FILE__, __LINE__);
00248
00249 byteVec_t outBytes = byteVec_t( 3);
00250 outBytes[0] = ChannelAccess_COMMAND;
00251 outBytes[1] = (inCRCtype&0x3) |
00252 ((inChanSelect&0x3)<<2) |
00253 (((uint8_t)inInterleaveMode)<<4) |
00254 (((uint8_t)inToggleMode)<<5) |
00255 (((uint8_t)inInitialMode)<<6) |
00256 (((uint8_t)inALR)<<7);
00257 outBytes[2] = 0xff;
00258
00259
00260 device.cmd_MatchROM();
00261 device.getLink().writeData( outBytes);
00262
00263 uint8_t infoByte = device.getLink().readDataByte();
00264
00265 channelInfo.channelFFQ_pioA = (infoByte>>0)&0x01;
00266 channelInfo.channelFFQ_pioB = (infoByte>>1)&0x01;
00267 channelInfo.sensedLevel_pioA = (infoByte>>2)&0x01;
00268 channelInfo.sensedLevel_pioB = (infoByte>>3)&0x01;
00269 channelInfo.activityLatch_pioA = (infoByte>>4)&0x01;
00270 channelInfo.activityLatch_pioB = (infoByte>>5)&0x01;
00271 channelInfo.hasPioB = (infoByte>>6)&0x01;
00272 channelInfo.isExternalPowered = (infoByte>>7)&0x01;
00273 }
00274
00275
00276 LOW_devDS2406::cmd_ChannelAccess::~cmd_ChannelAccess()
00277 {
00278 device.getLink().resetBus();
00279 }
00280
00281
00282
00283
00284
00285
00286 LOW_devDS2406::cmd_ChannelAccess::channelInfo_t& LOW_devDS2406::cmd_ChannelAccess::getChannelInfo()
00287 {
00288 return channelInfo;
00289 }
00290
00291 bool LOW_devDS2406::cmd_ChannelAccess::readDataBit() const
00292 {
00293 return device.getLink().readDataBit();
00294 }
00295
00296 uint8_t LOW_devDS2406::cmd_ChannelAccess::readDataByte() const
00297 {
00298 return device.getLink().readDataByte();
00299 }
00300
00301 void LOW_devDS2406::cmd_ChannelAccess::readData( byteVec_t &outBytes) const
00302 {
00303 device.getLink().readData( outBytes);
00304 }
00305
00306 void LOW_devDS2406::cmd_ChannelAccess::writeData( const bool inSendBit) const
00307 {
00308 device.getLink().writeData( inSendBit);
00309 }
00310
00311 void LOW_devDS2406::cmd_ChannelAccess::writeData( const uint8_t inSendByte) const
00312 {
00313 device.getLink().writeData( inSendByte);
00314 }
00315
00316 void LOW_devDS2406::cmd_ChannelAccess::writeData( const byteVec_t &inSendBytes) const
00317 {
00318 device.getLink().writeData( inSendBytes);
00319 }