Main Page   Modules   Alphabetical List   Data Structures   File List   Data Fields   Related Pages  

Coprocessor.c

00001 /*Coprocessor.c
00002 Coprocessor Device interface functions
00003 and tasklet parsing calls.
00004 Nathan Z. Gustavson
00005 emac.inc
00006 7/22/03
00007 see coprocessor.h
00008  */
00012 #include <stdlib.h>
00013 #include <stdio.h>
00014 #include <string.h>
00015 #include <sys/ioctl.h>
00016 #include <unistd.h>
00017 #include <sys/types.h>
00018 #include <asm/types.h>
00019 #include <sys/stat.h>
00020 #include <fcntl.h>
00021 #include <signal.h>
00022 #include <sched.h>
00023 #include <sys/resource.h>
00024 #include <sys/io.h>
00025 #include <signal.h>
00026 #include <packet.h>
00027 #include <coprocessor.h>
00028 #include <counter.h>
00029 
00030 typedef struct Cop_DataBlock
00031 {
00032 __u8 *data;
00033 int size;
00034 }Cop_DataBlock;
00035 
00036 
00044 int CopParsePacket(Cop_Data *data);
00045 
00051 int CopGetPacket(Cop_Data *data, Cop_DataBlock *block);
00052 
00058 int CopPacketMask(Cop_Data *data, Cop_DataBlock *block);
00059 
00065 int CopPacketStart(Cop_Data *data, Cop_DataBlock *block);
00066 
00067 
00071 void CopPackBreak(Cop_Data *data);
00072 
00073 
00074 static int BlockPull(Cop_DataBlock *block,__u8 *buffer, int count)
00075 {
00076 int tcount = 0;
00077 
00078 while((block->size)&&(count))
00079 {
00080 *buffer = *block->data; 
00081 GENDEBUG("pulled %c from block\n",*buffer);
00082 ++block->data;
00083 ++buffer;
00084 
00085 block->size--;
00086 tcount++;
00087 count--;
00088 }
00089 
00090 
00091 return tcount;
00092 }
00093 
00094 
00095 int CopPacketStart(Cop_Data *data, Cop_DataBlock *block)
00096 {
00097 GENDEBUG("Parsing for a Header\r\n");
00098 
00099 while(1)
00100     {
00101       
00102     if(!(BlockPull(block,&data->packet[DELIMITER],1)))
00103         break;
00104 
00105       
00106       if((DLMIN<=data->packet[DELIMITER])&&(data->packet[DELIMITER]<=DLMAX))
00107         {
00108 
00109          data->psize = 1;
00110          return SUCCESS;
00111         }
00112 
00113       if(data->packetdata.extended==TRUE)
00114         {
00115          data->psize = 1;
00116          data->packet[DELIMITER] = (char)EXT_TRANS(data->packet[DELIMITER]);   
00117          return SUCCESS;
00118 
00119         }       
00120 
00121     
00122     }
00123 
00124 return FAILURE;
00125 }
00126 
00127 int CopPacketMask(Cop_Data *data, Cop_DataBlock *block)
00128 {
00129 GENDEBUG("Parsing for packet mask\n");
00130 /*use pull block because you can distinguish pulled NULL from pulled nothing*/
00131 
00132 if(BlockPull(block,&data->packet[MASKNIB],1))
00133   {
00134     if((DLMIN<=data->packet[MASKNIB])&&(data->packet[MASKNIB]<=DLMAX))
00135       {/*new header received, restart.*/
00136     CopPackBreak(data);
00137     return FAILURE;
00138       }
00139 
00140     
00141     data->psize = 2;
00142     PcpkParseHeader(&data->packet[0],&data->packetdata);
00143    
00144     if(data->packetdata.extended==TRUE)
00145     {//extended packet protocol
00146       data->psize=0;/*reset for extended header*/
00147       data->ptogo=0;
00148     }
00149     else
00150         data->ptogo = 2*data->packetdata.datanum*data->packetdata.datasize;
00151     
00152 
00153     return SUCCESS;
00154   }
00155 
00156 return FAILURE;
00157 }
00158 
00159 
00160 /*called if header received in the middle of a packet*/
00161 void CopPackBreak(Cop_Data *data)
00162 {
00163 GENDEBUG("New Header received, restart packet\n");
00164 data->packet[DELIMITER] = data->packet[MASKNIB];
00165 data->psize = 1;
00166 return;
00167 }
00168 
00169 
00170 
00171 
00172 
00173 int CopGetPacket(Cop_Data *data, Cop_DataBlock *block)
00174 {
00175 int retval = 0;
00176 GENDEBUG("getting packet\n");
00177 
00178 while(data->ptogo>0)//counting bug, fixed on 8/22/02 NZG
00179   {
00180     
00181     if(BlockPull(block,&data->packet[data->psize],1))
00182     {
00183     //data->packet[data->psize] = FifoPull(fifo);
00184     if((DLMIN<=data->packet[data->psize])&&(data->packet[data->psize]<=DLMAX))
00185       {
00186         data->packet[MASKNIB] = data->packet[data->psize];
00187         CopPackBreak(data);
00188         return FAILURE;
00189       }
00190     
00191     data->ptogo--;
00192     data->psize++;
00193       }
00194     else
00195       break;
00196 
00197   }
00198 
00199 
00200 GENDEBUG("ptogo is %u at end of get packet\n",data->ptogo);
00201 
00202 if(data->ptogo==0)
00203      retval = CopParsePacket(data);
00204 
00205 
00206 return retval;
00207 }
00208 
00209 
00210 
00211 /*
00212 CopParsePacket
00213 hardware specific packet parsing function.
00214 interpretes the data from the packets and 
00215 performs actions based upon it.
00216 */
00217 
00218 int CopParsePacket(Cop_Data *data)
00219 {
00220 void *datapntr = data->packetdata.data;
00221 RG_ParseMask *parsemask = &data->parsemask;
00222 unsigned long long cross_stamp;
00223 int channel;
00224 
00225 GENDEBUG("Parsing Packet data\n");
00226 PcpkParseData(&data->packet[0],&data->packetdata);
00227 
00228 GENDEBUG("data parsed assigning data\n");
00229 switch(data->packetdata.type)
00230   {
00231  case EXTNULCMD:
00232     GENDEBUG("null command no data assigned\n");
00233     break;
00234  
00235   
00236   case VERSIONINFO:
00237     GENDEBUG("version info returned\n");
00238     data->version.version = ((__u8 *)datapntr)[0];
00239     strcpy(data->version.date,(datapntr+1));
00240   break;
00241    
00242     
00243    /*analog to digital data*/
00244   case ADBLK0:
00245     GENDEBUG("Internal AD channel %x returned\n",(unsigned int)data->packetdata.maskcnt);    
00246     data->Internal_AD[data->packetdata.maskcnt] = *(__u16 *)datapntr;
00247     parsemask->Internal_AD|=BITMASK(data->packetdata.maskcnt);
00248     break;
00249   
00250 
00251   case ADBLK1:
00252     GENDEBUG("External Analog to digital channel, mask = %x, data =%x\n",data->packetdata.maskcnt,*(__u16 *)datapntr);
00253     data->External_AD[data->packetdata.maskcnt] = *(__u16 *)datapntr; 
00254     parsemask->External_AD|=BITMASK(data->packetdata.maskcnt);
00255     break;
00256     /*Digital IO data*/
00257 
00258   
00259   case PRTIN0:
00260     GENDEBUG("Digital Port Data\n"); 
00261     if(data->packetdata.maskcnt&0x08)
00262       data->Digital[0] = *((__u8 *)datapntr);
00263     if(data->packetdata.maskcnt&0x04)
00264       data->Digital[1] = ((__u8 *)datapntr)[1];
00265       break;
00266 
00267   
00268 
00269     /*CAN Message*/
00270   case CAN:
00271     GENDEBUG("Can Data\n");   
00272     if(data->CAN_message);
00273       data->CAN_message = datapntr;
00274     break;
00275     
00276 
00277     /*Keypad Data*/
00278   case KEYPAD:
00279     GENDEBUG("Keypad Data\n");
00280       data->Key = *(char *)datapntr;
00281     break;
00282 
00283   case SER422:
00284     GENDEBUG("422 Data\n");                            
00285     ((__u8 *)datapntr)[data->packetdata.maskcnt] = 0;
00286     
00287     if((strlen(data->RS422_string)+data->packetdata.maskcnt)>RS422BUFSIZE)
00288       break;
00289 
00290     strcat(data->RS422_string,datapntr);
00291     break;
00292 
00293   case SER232:
00294     GENDEBUG("232 Data\n");   
00295     ((__u8 *)datapntr)[data->packetdata.maskcnt] = 0;
00296 
00297     if((strlen(data->RS232_string)+data->packetdata.maskcnt)>RS232BUFSIZE)
00298       break;
00299     
00300     strcat(data->RS232_string, datapntr);
00301     break;
00302     
00303   case COUNTER:
00304         GENDEBUG("Counter data\n");
00305     if(data->packetdata.maskcnt>7)
00306       break;
00307 
00308     data->counter_data[data->packetdata.maskcnt].counter = ((__u16 *)(datapntr))[0];
00309     parsemask->counter|=BITMASK(data->packetdata.maskcnt);
00310     break;
00311 
00312   case COUNTERD://configuration data returned, update the shadow with hardware
00313   channel =  ((__u16 *)(datapntr))[0];
00314   data->counter_config[channel].trigger =  ((__u16 *)(datapntr))[1];
00315   data->counter_config[channel].threshold =  ((__u16 *)(datapntr))[2];
00316   data->counter_config[channel].flags =  ((__u16 *)(datapntr))[3];
00317   parsemask->counter|=BITMASK(channel);
00318   break;
00319 
00320 
00321 case PWMCON://configuration data returned, update the shadow with hardware
00322   channel =  ((__u16 *)(datapntr))[0];
00323   data->PWM_config[channel].pwm =  channel;
00324   data->PWM_config[channel].frequency =  ((__u16 *)(datapntr))[1];
00325   data->PWM_config[channel].duty =  ((__u16 *)(datapntr))[2];
00326   data->PWM_config[channel].delay =  ((__u16 *)(datapntr))[3];
00327   parsemask->pwm|=BITMASK(channel);
00328   break;
00329 
00330 
00331 
00332 
00333   case ICNOTIFY:
00334 //update count_data variables to reflect timestamp passed by ICNOTIFY
00335     channel =  ((__u16 *)(datapntr))[0];
00336 
00337     GENDEBUG("counter zero detection, channel %x\n",channel);
00338 
00339     //data->counter_data[channel].countstart = ((__u16 *)(datapntr))[1];
00340 
00341     cross_stamp = ((__u16 *)(datapntr))[2];
00342     cross_stamp <<=16;
00343     cross_stamp += ((__u16 *)(datapntr))[3];
00344 
00345     if(channel<COUNTNUM)
00346         {
00347         data->counter_data[channel].zerocross++; //this was a zerocrossing
00348         data->counter_data[channel].laststart = data->counter_data[channel].countstart; //save the last start
00349         //data->counter_data[channel].countstart = ((__u16 *)(datapntr))[1]; //this is typically zero if it's a zerocross
00350 
00351 
00352           if(!(data->counter_config[channel].flags&AUTOSTOP))//if counter didn't stop then countstart has changed
00353             {
00354              if(data->counter_config[channel].flags&AUTOLOAD)//autoreload mean counter starts at threshold
00355                 data->counter_data[channel].countstart=data->counter_config[channel].threshold;
00356              else
00357                 data->counter_data[channel].countstart=0xffff;//wraparound
00358             }
00359 
00360         }
00361     else
00362         {
00363         channel-=COUNTNUM;//this was a counter start
00364         data->counter_data[channel].zerocross = 0;
00365         data->counter_data[channel].countstart = ((__u16 *)(datapntr))[1];//get the start value
00366         }
00367     data->counter_data[channel].laststamp =  data->counter_data[channel].timestamp;
00368     data->counter_data[channel].timestamp = cross_stamp;
00369     parsemask->zero|=BITMASK(channel);
00370     break;
00371     
00372   }//end of switch(type)
00373 
00374 data->psize=0;/*reset and get ready for the next packet*/
00375 data->ptogo=0;
00376 
00377 return(data->packetdata.type);
00378 }
00379 
00380 static void CopInit(Cop_Data *CopData)
00381 {
00382 int num;
00383 CopData->psize=0;
00384 CopData->ptogo=0;
00385 CopData->Datarxd=TRUE;
00386 CopData->packetdata.extended=FALSE;
00387 CopData->packetdata.mult = 0;
00388 CopData->RS232_string[0] = 0;
00389 CopData->RS422_string[0] = 0;
00390 CopData->CAN_message  = NULL;
00391 
00392 for(num=0;num<COUNTNUM;num++)//initialize counter data
00393   {
00394   CopData->counter_config[num].counter = num;
00395   CopData->counter_config[num].trigger = 0;
00396   CopData->counter_config[num].threshold = 0;
00397   CopData->counter_config[num].flags =0;
00398   CopData->counter_data[num].counter =0;
00399   CopData->counter_data[num].countstart =0;
00400   CopData->counter_data[num].timestamp =0;
00401   CopData->counter_data[num].laststamp =0;
00402   CopData->counter_data[num].zerocross =0;
00403   }
00404 
00405 for(num=0;num<PWMNUM;num++)//initialize PWM data
00406 {
00407 CopData->PWM_config[num].pwm = num;
00408 CopData->PWM_config[num].frequency = 0;
00409 CopData->PWM_config[num].duty = 0;
00410 CopData->PWM_config[num].delay = 0;
00411 }
00412 
00413 
00414 }
00415 
00416 
00417 
00418 Cop_Data *CopDeviceCreate(int flags)
00419 {
00420 Cop_Data *Cop = malloc(sizeof(Cop_Data)); 
00421 CopInit(Cop);
00422 return(Cop);
00423 }
00424 
00425 int CopDeviceDestroy(Cop_Data *Cop)
00426 {
00427 free(Cop);
00428 return 0;
00429 }
00430 
00431 static int COPclearmem(Cop_Data *Cop)
00432 {
00433 Cop->RS232_string[0] = 0;
00434 Cop->RS422_string[0] = 0;
00435 return 0;
00436 }
00437 
00438 __u32 E12_Packet_Route(Cop_Data *Cop, unsigned char *data, int datasize)
00439 {
00440 Cop_DataBlock datablock;
00441 int type = 0; 
00442 __u32 retval=0;
00443 datablock.size = datasize;
00444 datablock.data = data;
00445 
00446 memset(&Cop->parsemask,0,sizeof(RG_ParseMask));/*new parse clear old mask*/
00447 
00448 
00449 while(datablock.size)
00450   {
00451     if(Cop->psize==0)
00452       CopPacketStart(Cop,&datablock);
00453 
00454     if(Cop->psize==1)
00455       CopPacketMask(Cop,&datablock);
00456     
00457     if(Cop->psize>1)
00458       type = CopGetPacket(Cop,&datablock);
00459 
00460     retval |= BITMASK(type);//build bitmask of returned types
00461   }
00462 return retval;
00463 }
00464 
00465 /*parse data from fd until one of the flags in bitmask is set.
00466 An alternative to the  E12_Packet_Route function.
00467 */
00468 __u32 E12_Parse_Until(int fd, Cop_Data *Cop, __u32 bitmask )
00469 {
00470 Cop_DataBlock datablock;
00471 int type = 0;
00472 __u32 typemask=0;
00473 char buffer[1000];
00474 int loopcount=0;
00475 
00476 memset(&Cop->parsemask,0,sizeof(RG_ParseMask));/*new parse clear old mask*/
00477 
00478 while(!(typemask&bitmask))
00479 {
00480 
00481   datablock.size = read(fd,buffer,sizeof(buffer));//read data
00482   datablock.data = buffer;
00483 
00484   while(datablock.size)
00485     {
00486       if(Cop->psize==0)
00487         CopPacketStart(Cop,&datablock);
00488 
00489       if(Cop->psize==1)
00490         CopPacketMask(Cop,&datablock);
00491 
00492       if(Cop->psize>1)
00493         type = CopGetPacket(Cop,&datablock);
00494 
00495       typemask |= BITMASK(type);//build bitmask of returned types
00496     }
00497 if(loopcount++==1000)//timeout for non-blocking mode
00498   return 0;
00499 }
00500 return typemask;
00501 }
00502 
00503 
00504 int UpdatetHardwareCounterInfo(int fd, Cop_Data *Cop)
00505 {
00506 int counter;
00507 int parseneeded = 0xff;
00508 
00509 for(counter=0;counter<COUNTNUM;counter++)
00510   E12_CountCfg_Req(fd, counter);//request config packets for all the counters
00511 
00512 while(parseneeded)
00513   {
00514   E12_Parse_Until(fd, Cop, BITMASK(COUNTERD));//parse until a config packet is received.
00515   parseneeded&=~(Cop->parsemask.counter);//clear bits from parseneeded until all the bits have been cleared.
00516   }
00517 
00518 return 0;
00519 }
00520 
00521 int UpdatetHardwarePWMInfo(int fd, Cop_Data *Cop)
00522 {
00523 int pwm;
00524 int parseneeded = 0xffff;
00525 
00526 for(pwm=0;pwm<PWMNUM;pwm++)
00527   E12_PWMCfg_Req(fd, pwm);//request config packets for all the pwms
00528 
00529 while(parseneeded)
00530   {
00531   E12_Parse_Until(fd, Cop, BITMASK(PWMCON));//parse until a config packet is received.
00532   parseneeded&=~(Cop->parsemask.pwm);//clear bits from parseneeded until all the bits have been cleared.
00533   }
00534 
00535 return 0;
00536 }
00537 
00538 
00539 int e12packetout(int fd,__u8 device,__u8 maskcnt,void *data)
00540 {
00541 __u8 *packet = PcpkPackGen(device,maskcnt,data);
00542 write(fd,packet,strlen(packet));
00543 free(packet);
00544 return 0;
00545 }
00546          
00547 
00548 
00549 int E12_PWMControl(int fd,int pwm, int frequency, int duty,Cop_Data *Cop)
00550 {
00551 PWMconfig *config = &Cop->PWM_config[pwm];
00552 //shadow the variables and provide a config structure to pass to e12packetout
00553 config->pwm = pwm;
00554 config->frequency = frequency;
00555 config->duty  = duty;
00556 config->delay = 0;
00557 
00558 if(pwm<COUNTNUM)
00559   {
00560     Cop->counter_config[pwm].flags=0;
00561     Cop->counter_config[pwm].threshold = 0;
00562     Cop->counter_config[pwm].trigger = 0; //this turns off the counter on that channel, if enabled
00563   }
00564 
00565 e12packetout(fd,PWMCON,0x0F,config);
00566 return 0;
00567 }
00568 
00569 int E12_PWMCfg_Req(int fd, int pwm)
00570 {
00571 PWMconfig config;
00572 config.pwm=pwm+PWMNUM;//request for countconfig
00573 e12packetout(fd,PWMCON,0x0f,&config);
00574 return 0;
00575 }
00576 
00577 
00578 int E12_CountConfig(int fd, int counter, int trigger, int threshold,int flags,Cop_Data *Cop)
00579 {
00580 countconfig *config = &Cop->counter_config[counter];
00581 Cop->PWM_config[counter].frequency = 0;//this turns off the PWM on that channel, if enabled
00582 Cop->PWM_config[counter].duty = 0;
00583 //shadow the variables and provide a config structure to pass to e12packetout
00584 config->trigger = trigger;
00585 config->threshold = threshold;
00586 config->flags = flags;
00587 
00588 e12packetout(fd,COUNTERD,0x0F,config);
00589 return 0;
00590 } 
00591 
00592 int E12_CountCfg_Req(int fd, int counter)
00593 {
00594 countconfig config;
00595 config.counter=counter+COUNTNUM;//request for countconfig
00596 e12packetout(fd,COUNTERD,0x0f,&config);
00597 return 0;
00598 }
00599 
00600 
00601 int E12_CounterReadRQ(int fd, int counter)
00602 {
00603 int command =0; //command arguement for further protocol expansions
00604 e12packetout(fd,COUNTER,counter,&command);
00605 return 0;
00606 }
00607 
00608 int E12_CounterLoad(int fd, int counter, int data, Cop_Data *Cop)
00609 {
00610 e12packetout(fd,COUNTER,counter+8,&data);
00611 //Cop->counter_data[counter].countstart=data; //update countstart element
00612 return 0;
00613 }
00614 
00615 
00616 int E12_CounterCalcFreq(int counter, Cop_Data *Cop)
00617 {
00618 unsigned long timediff_ms = (Cop->counter_data[counter].timestamp - Cop->counter_data[counter].laststamp);
00619 unsigned long count_ms = Cop->counter_data[counter].laststart*(unsigned long)1000;
00620 unsigned int freq=0;
00621 
00622 if(timediff_ms!=0)
00623    freq =  count_ms/timediff_ms;
00624 return(freq);
00625 }
00626 
00627 
00628 int E12_CountCommand(int fd, int counter,int command)
00629 {
00630 __u16 commandstruct[4];
00631 commandstruct[0] = counter;
00632 commandstruct[1] = command;
00633 commandstruct[2] = 0x77;//currently unused
00634 commandstruct[3] = 0x77;//currently unused
00635 e12packetout(fd,ICNOTIFY,0x0f,commandstruct);
00636 return 0;
00637 }       
00638 
00639 
00640 
00641 
00642 int E12_Digitalout(int fd, __u8 data,int port)
00643 {
00644 __u8 mask = 8>>port;
00645 __u8 dataa[4];
00646 
00647 dataa[port] = data;
00648 
00649 if(port>1)
00650   return -1;
00651 
00652 e12packetout(fd,PRTOUT,mask,dataa);
00653 return 0;
00654 }
00655 
00656 
00657 //requests the status of both digital ports
00658 int E12_Digital_Req(int fd)
00659 {
00660 __u8 placeholder;
00661 e12packetout(fd,DREQ,0x0C,&placeholder);
00662 return 0;
00663 }
00664 
00665 
00666 int E12_Digital_Cfg(int fd, __u8 mask, int port)
00667 {
00668 
00669 __u8 pmask = 8>>port;
00670 __u8 maska[4];
00671 
00672 maska[port] = mask;
00673 
00674 if(port>1)
00675   return -1;
00676 
00677 e12packetout(fd,PRTCFG0,pmask,maska);
00678 return 0;
00679 }
00680 
00681 
00682 int E12_Internal_AtoD_Req(int fd, int channel)
00683 {
00684 e12packetout(fd,ADREQ0,channel,NULL);
00685 return 0;
00686 }
00687 
00688 int E12_External_AtoD_Req(int fd, int channel)
00689 {
00690 e12packetout(fd,ADREQ1,channel,NULL);
00691 return 0;
00692 }
00693 
00694 
00695 int E12_AtoD_Req(int fd, int channel)
00696 {
00697 if(channel<INTERNAL_ATOD_NUM)
00698   E12_Internal_AtoD_Req(fd, channel);
00699 else
00700   {
00701   channel-=INTERNAL_ATOD_NUM;
00702   E12_External_AtoD_Req(fd, channel);
00703   }
00704 return 0;
00705 }
00706 
00707 
00708 int E12_DtoA_Write(int fd, int channel,int data)
00709 {
00710 __u8 mask = 8>>channel;
00711 __u16 dataa[4];
00712 dataa[channel] = data;
00713 e12packetout(fd,DAQ,mask,dataa);
00714 return 0;
00715 }
00716 
00717 int E12_Serial_Write(int fd, int port, int numchars,char *buffer)
00718 {
00719 int charnum=0;
00720 int chars_tx;
00721 
00722 if(!(chars_tx=numchars%15))
00723   chars_tx = 15;
00724 
00725 while(charnum<numchars)
00726   {
00727 
00728 switch(port)
00729   {
00730   case RS232PORT:
00731     e12packetout(fd,RS232DATA,chars_tx,&buffer[charnum]);
00732     break;
00733 
00734   case RS422PORT:
00735     e12packetout(fd,RS422DATA,chars_tx,&buffer[charnum]);
00736     break;
00737   }
00738 
00739 charnum+=chars_tx;
00740 
00741 chars_tx = 15;
00742   }
00743 
00744 
00745 return charnum;
00746 }
00747 
00748 
00749 int E12_Serial_Config(int fd, int port, int baud,int mode)
00750 {
00751 Serconfig config;
00752 config.id = port;
00753 config.mode = mode;
00754 config.baud = baud;
00755 e12packetout(fd,SERCFG,0x0F,&config);
00756 return 0;
00757 }
00758 

Generated on Thu Jan 8 09:51:00 2004 for PCM-37e12 by doxygen1.2.15