#include #include #include #include #include #include #include #include // ======================================== // SICK communication data packet structure // ======================================== class SickLMSPacket { public: SickLMSPacket(int l=0); ~SickLMSPacket(); int Resize(int newsize); int Setup(unsigned char cmd,unsigned char dest=0); int CalculateCRC(void); int SetCRC(void); int CheckCRC(void); void Dump(void); unsigned char *GetAllByte(void) { return buff; } unsigned char *GetDataArea(void) { return buff+5; } unsigned char GetCMD(void) { return buff[4]; } int GetAllSize(void) { return len+7; } int GetDataSize(void) { return len; } protected: unsigned char *buff; // packet it self int len; }; SickLMSPacket::SickLMSPacket(int l) { buff=NULL; Resize(l); } SickLMSPacket::~SickLMSPacket() { if(buff) delete[] buff; } int SickLMSPacket::Resize(int newsize) { if(buff) delete[] buff; len=newsize; buff=new unsigned char [len+7]; // {STX, ADR, LL, LH, CMD, ([] , ST,) CRCL,CRCH } return 0; } int SickLMSPacket::Setup(unsigned char cmd, unsigned char dest) { if(buff==NULL) return -1; buff[0]=0x02; // STX buff[1]=dest; buff[2]=(len+1)&0xff; // {STX, ADR, LL, LH, << CMD, ([] , ST,)>> CRCL,CRCH } buff[3]=((len+1)>>8)&0xff; buff[4]=cmd; return 0; } int SickLMSPacket::CalculateCRC(void) { if(buff==NULL) return 0; unsigned short crc; unsigned char abdata[2]; unsigned char *d=buff; int l=len+5; crc=0; abdata[0]=0; while(l--) { abdata[1]=abdata[0]; abdata[0]=*d; d++; if(crc & 0x8000) { crc=(crc&0x7fff)<<1; crc^=0x8005; // GEN_POL } else { crc<<=1; } crc^=((unsigned short)(abdata[0])|((unsigned short)(abdata[1])<<8)); } // printf("CRC: %04X\n",crc); return crc; } int SickLMSPacket::SetCRC(void) { if(buff==NULL) return -1; unsigned short crc=CalculateCRC(); buff[len+5]=crc&0xff; buff[len+6]=(crc>>8)&0xff; return 0; } int SickLMSPacket::CheckCRC(void) { if(buff==NULL) return -1; unsigned short crc=CalculateCRC(); if((buff[len+5]!=(crc&0xff))|| (buff[len+6]!=((crc>>8)&0xff))) return -1; return 0; } void SickLMSPacket::Dump(void) { if(buff==NULL) { printf("Invalid buffer\n"); return ; } switch(buff[0]) { case 0x02: //STX printf("S02 "); break; case 0x06: // ACK printf("ACK\n"); return; case 0x10: // DLE printf("DLE\n"); return; case 0x15: // NACK printf("NACK\n"); return; default: printf("!%02X ",buff[0]); } int l,i; printf("A%02X ",buff[1]); printf("LL%02X ",buff[2]); printf("LH%02X ",buff[3]); printf("C%02X ",buff[4]); l=len; putchar('['); for(i=0;iSetCRC(); int l=p->GetAllSize(); unsigned char *d=p->GetAllByte(); while(l) { int r=write(fd,d,l); if(r<0) { perror("SickLMSIF::SendPacket"); return -1; } d+=r; l-=r; } return 0; } SickLMSPacket *SickLMSIF::ReceivePacket(int block) { int r; do { if(workmode==0) // init { workpos=0; worklen=0; workmode++; } if(workmode==1) // recieve header part (4byte) { r=read(fd,workbuff+workpos,4-workpos); if(r<0) { if(errno==EAGAIN) r=0; else { perror("SickLMSIF::ReceivePacket"); return NULL; } } if((r==0)&&(!block)) break; if(r==0) { /*usleep(500);*/ continue; } workpos+=r; // printf("|%d|",workpos); if((workbuff[0]==0x06) || // ACK (workbuff[0]==0x10) || // DLE (workbuff[0]==0x15)) // NACK { SickLMSPacket *p=new SickLMSPacket; (p->GetAllByte())[0]=workbuff[0]; workbuff[0]=workbuff[1]; workbuff[1]=workbuff[2]; workbuff[2]=workbuff[3]; workpos--; return p; } if(workpos==4) workmode=2; } if(workmode==2) { int len=workbuff[2]|((unsigned short)(workbuff[3])<<8); len=len-1; if(workpack==NULL) workpack=new SickLMSPacket(len); memcpy(workpack->GetAllByte(),workbuff,4); workmode=3; workpos=4; worklen=len+1+2; // CMD, [DATA,ST] CRC*2 } if(workmode==3) { r=read(fd,workpack->GetAllByte()+workpos,worklen); // printf("%d",r); if(r<0) { if(errno==EAGAIN) r=0; else { perror("SickLMSIF::ReceivePacket"); return NULL; } } if((r==0)&&(!block)) break; if(r==0) { /*usleep(1000);*/ continue; } worklen-=r; workpos+=r; if(worklen==0) break; } } while(block); if((workmode==3)&&(worklen==0)) { workmode=0; SickLMSPacket *r=workpack; workpack=NULL; return r; } return NULL; } int SickLMSIF::LSCheckStatus(void) // CMD 31 { SickLMSPacket p(0); p.Setup(0x31); p.SetCRC(); SendPacket(&p); return 0; } int SickLMSIF::LSReset(void) // CMD 10 { SickLMSPacket p(0); p.Setup(0x10); p.SetCRC(); SendPacket(&p); return 0; } int SickLMSIF::LSSetOperationMode(unsigned char mode) { SickLMSPacket p(1); p.Setup(0x20); p.GetDataArea()[0]=mode; p.SetCRC(); SendPacket(&p); return 0; } int SickLMSIF::LSRequestMeasure(int lmsn) // CMD 30 { SickLMSPacket p(1); p.Setup(0x30); p.GetDataArea()[0]=lmsn; // for LMI400 only lmsn-0x01 2byte p.GetDataArea()[0]=0x01; p.SetCRC(); SendPacket(&p); return 0; } int SickLMSIF::LSChangeVariant(unsigned int mode) // CMD 3B, LMSCV { SickLMSPacket p(4); p.Setup(0x3b); p.GetDataArea()[0]=(mode>>16)&0xff; p.GetDataArea()[1]=(mode>>24)&0xff; p.GetDataArea()[2]=(mode )&0xff; p.GetDataArea()[3]=(mode>> 8)&0xff; p.SetCRC(); SendPacket(&p); return 0; } int SickLMSIF::WaitACK(int rc) { if(!valid) return -1; SickLMSPacket *r; int dc=0,ec=0; #ifdef DEBUGPRINT printf("\nwait ack"); #endif while(1) { r=ReceivePacket(0); if(r==NULL) { usleep(10000); #ifdef DEBUGPRINT putchar('='); fflush(stdout); // no receive, wait #endif dc++; if(dc>50) return -1; continue; } dc=0; unsigned char m=r->GetAllByte()[0]; delete r; if((m==0x06)|| (m==0x10)|| (m==0x15)) break; else { #ifdef DEBUGPRINT puts("Not ACK"); #endif ec++; if(ec>20) return -1; } } for(int i=0;iDump(); if(r->CheckCRC()<0) { puts("CRC Error"); } else {puts("CRC OK"); } switch(r->GetCMD()) { case 0x90: // startup message l=r->GetDataSize(); printf("Init message: %*.*s\n",l,l,r->GetDataArea()); break; case 0xb0: // measured value; unsigned char *d=r->GetDataArea(); unsigned short *w; w=(unsigned short *)(d); printf("res %s ",(w[0]&(1<<14))?"1mm":"1cm"); if(w[0]&(1<<13)) printf("PScan %d ",((w[0]>>11)&3)*25); else printf("CScan "); l=w[0]&0x3ff; printf("%d data\n",l); for(i=0;i