15 #ifdef FAUDES_IODEVICE_SERIAL
36 #define PUSECPB ((int) 1000000.0* (8.0+1.0+1.0) / 115200.0)
37 #define PUSECXX PUSECPB
41 int serialOpen(
const std::string& devname) {
44 fd = open(devname.c_str(), O_RDWR | O_NOCTTY | O_NDELAY);
45 if(fd == -1)
return -1;
48 struct termios options;
49 tcgetattr(fd, &options);
50 cfsetispeed(&options, B115200);
51 cfsetospeed(&options, B115200);
52 options.c_cflag |= (CLOCAL | CREAD);
53 options.c_cflag &= ~CSIZE;
54 options.c_cflag |= CS8;
55 options.c_cflag &= ~PARENB;
56 options.c_cflag &= ~CSTOPB;
57 options.c_cflag &= ~CRTSCTS;
58 options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
59 options.c_iflag &= ~(IXON | IXOFF | IXANY);
60 options.c_iflag &= ~(INLCR | IGNCR | ICRNL | IUCLC | IMAXBEL);
61 options.c_oflag &= ~OPOST;
62 tcsetattr(fd, TCSANOW, &options);
64 fcntl(fd, F_SETFL, FNDELAY);
70 void serialClose(
int fd) {
75 int serialWriteBlock(
int fd,
char* data,
int len) {
84 int n=write(fd, data, len);
89 FD_DH(
"spiDevice()::serialWriteBlock(): cannot transmit");
90 return len == 0 ? 0 : -1;
94 void serialFlush(
int fd) {
97 while(read(fd, &d,1)==1) cnt++;
98 if(cnt!=0)
FD_DH(
"spiDevice()::serialFlush(): rec/drop #" << cnt);
106 int serialReadBlock(
int fd,
char* data,
int len) {
107 int n1= read(fd, data,len);
112 usleep( (len-n1)* PUSECPB + PUSECXX );
113 int n2= read(fd, data+n1,len-n1);
115 FD_DH(
"spiDevice()::serialReadBlock(): rec/drop #" << n1)
121 int n3= read(fd, data,1);
123 FD_DH(
"spiDevice()::serialReadBlock(): rec/drop #" << n1);
153 spiDevice::spiDevice(
void) : sDevice() {
154 FD_DHV(
"spiDevice(" << mName <<
")::spiDevice()");
156 mDefaultLabel =
"SpiDevice";
168 spiDevice::~spiDevice(
void) {
169 FD_DHV(
"spiDevice(" << mName <<
")::~spiDevice()");
174 void spiDevice::Clear(
void) {
179 mDeviceFiles.clear();
186 void spiDevice::Compile(
void){
188 FD_DHV(
"spiDevice(" << mName <<
")::Compile()");
192 if(mMaxBitAddress+1 > PSIZE*8) {
193 std::stringstream errstr;
194 errstr <<
"Invalid address range (must not exceed " << PSIZE*8 <<
")";
195 throw Exception(
"spiDevice:Compile", errstr.str(), 52);
198 if((!mMaster) && (mDeviceFiles.size()!=1)) {
199 std::stringstream errstr;
200 errstr <<
"Slave must have exactly one device file specified";
201 throw Exception(
"spiDevice:Compile()", errstr.str(), 52);
204 if((mMaster) && (mDeviceFiles.size()==0)) {
205 std::stringstream errstr;
206 errstr <<
"Master must have at least one device file specified";
207 throw Exception(
"spiDevice:Compile()", errstr.str(), 52);
213 void spiDevice::DoWritePreface(TokenWriter& rTw,
const std::string& rLabel,
const Type* pContext)
const {
214 FD_DHV(
"spiDevice("<<mName<<
")::DoWritePreface()");
216 sDevice::DoWritePreface(rTw,
"",pContext);
219 ftoken.SetEmpty(
"Role");
221 ftoken.InsAttributeString(
"value",
"master");
223 ftoken.InsAttributeString(
"value",
"slave");
227 for(
unsigned int i=0; i<mDeviceFiles.size(); i++) {
229 ftoken.SetEmpty(
"DeviceFile");
230 ftoken.InsAttributeString(
"value",mDeviceFiles.at(i));
237 void spiDevice::DoReadPreface(TokenReader& rTr,
const std::string& rLabel,
const Type* pContext){
239 FD_DHV(
"spiDevice("<<mName<<
")::DoReadPreface()");
241 sDevice::DoReadPreface(rTr,
"",pContext);
244 while(rTr.Peek(token)) {
246 if(token.IsBegin(
"Role")) {
247 rTr.ReadBegin(
"Role");
249 if(!token.ExistsAttributeString(
"value")) {
250 std::stringstream errstr;
251 errstr <<
"Invalid role tag" << rTr.FileLine();
252 throw Exception(
"spiDevice:Read", errstr.str(), 52);
254 std::string val=token.AttributeStringValue(
"value");
255 std::transform(val.begin(), val.end(), val.begin(), tolower);
256 if(val==
"master") mMaster =
true;
257 else if(val==
"slave") mMaster =
false;
259 std::stringstream errstr;
260 errstr <<
"Invalid role tag" << rTr.FileLine();
261 throw Exception(
"spiDevice:Read", errstr.str(), 52);
267 if(token.IsBegin(
"DeviceFile")) {
268 rTr.ReadBegin(
"DeviceFile");
269 if(!token.ExistsAttributeString(
"value")) {
270 std::stringstream errstr;
271 errstr <<
"Invalid device tag" << rTr.FileLine();
272 throw Exception(
"spiDevice:Read", errstr.str(), 52);
274 mDeviceFiles.push_back(token.AttributeStringValue(
"value"));
275 rTr.ReadEnd(
"DeviceFile");
285 void spiDevice::Start(
void) {
287 if(mState!=Down)
return;
288 FD_DH(
"spiDevice(" << mName <<
")::Start(): open devices #" << mDeviceFiles.size());
290 for(
unsigned int i=0; i<mDeviceFiles.size(); i++) {
291 int fd=serialOpen(mDeviceFiles.at(i));
293 std::stringstream errstr;
294 errstr <<
"cannot open serial line " << mDeviceFiles.at(i);
295 throw Exception(
"spiDevice()::Start()", errstr.str(), 552);
297 mPorts.push_back(fd);
300 mpImage =
new char[PSIZE];
301 memset(mpImage,0,PSIZE);
302 pOutputImage=mpImage;
305 mpOutputMask =
new char[PSIZE];
306 memset(mpOutputMask,0,PSIZE);
307 for(
int bit=0; bit<=mMaxBitAddress; bit++)
308 if(!mOutputLevelIndexMap[bit].Empty())
309 mpOutputMask[bit/8] |= (0x01 << (bit %8));
317 void spiDevice::Stop(
void) {
319 if(mState != Up && mState != StartUp)
return;
320 FD_DHV(
"spiDevice(" << mName <<
")::Stop()");
324 for(
unsigned int i=0; i< mPorts.size(); i++)
325 serialClose(mPorts.at(i));
328 if(mpImage)
delete mpImage;
332 if(mpOutputMask)
delete mpOutputMask;
340 void spiDevice::DoLoopCallback(
void) {
342 if(mState!=Up && mState!=StartUp)
return;
346 FD_DHV(
"spiDevice()::DoLoopCallBack(): master send images #" << mPorts.size());
347 for(
unsigned int i=0; i< mPorts.size(); i++) {
349 serialFlush(mPorts.at(i));
351 serialWriteBlock(mPorts.at(i),mpImage,PSIZE);
355 int err=serialReadBlock(mPorts.at(i),buffer,PSIZE);
357 FD_DHV(
"spiDevice()::DoLoopCallBack(): master received image");
359 for(
int i=0; i<PSIZE; i++)
360 mpImage[i]= (buffer[i] & ~mpOutputMask[i]) | (mpImage[i] & mpOutputMask[i]);
368 int err=serialReadBlock(mPorts.at(0),buffer,PSIZE);
370 FD_DHV(
"spiDevice()::DoLoopCallBack(): slave received image");
372 for(
int i=0; i<PSIZE; i++)
373 mpImage[i]= (buffer[i] & ~mpOutputMask[i]) | (mpImage[i] & mpOutputMask[i]);
375 serialWriteBlock(mPorts.at(0),mpImage,PSIZE);
382 bool spiDevice::DoReadSignalsPre(
void) {
383 return pInputImage!=0;
388 void spiDevice::DoReadSignalsPost(
void) {
393 bool spiDevice::DoReadSignal(
int bit){
401 return ( pInputImage[
byte] & (0x01 << (bit)) ) != 0x00;
406 bool spiDevice::DoWriteSignalsPre(
void) {
407 return pOutputImage!=0;
411 void spiDevice::DoWriteSignalsPost(
void) {
416 void spiDevice::DoWriteSignal(
int bit,
bool value){
419 FD_DHV(
"spiDevice("<<mName<<
")::DoWriteSignal(" << bit <<
", " << value <<
")");
422 int byte = (bit) / 8;
426 if(value) pOutputImage[byte] |= (0x01 << (bit));
427 else pOutputImage[byte] &= ~(0x01 << (bit));
#define FAUDES_TYPE_IMPLEMENTATION(ftype, ctype, cbase)
faudes type implementation macros, overall
Process image via serial line.
libFAUDES resides within the namespace faudes.
AutoRegisterType< mbDevice > gRtiRegisterSpiDevice("ModbusDevice")