]> rtime.felk.cvut.cz Git - CanFestival-3.git/blobdiff - drivers/can_peak_win32/can_peak_win32.c
- add RTAI support
[CanFestival-3.git] / drivers / can_peak_win32 / can_peak_win32.c
index 9b58721daaaef883ab948fdd0ea0fe07dd78ed2e..d1e71dc93e490808d89e35320c5e6e49d29b36a6 100644 (file)
@@ -20,147 +20,246 @@ License along with this library; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
 
+#if defined(WIN32) && !defined(__CYGWIN__)
+#define usleep(micro) Sleep(micro%1000 ? (micro/1000) + 1 : (micro/1000))
+#else
 #include <stdio.h>
 #include <string.h>
-#include <stdlib.h>
 #include <errno.h>
-#include <stddef.h> /* for NULL */
-#include <sys/ioctl.h>
 #include <fcntl.h>
-#include <signal.h>
-#include <sys/time.h>
-#include <unistd.h>
+#endif
 
-/* driver pcan pci for Peak board */
-//#include "libpcan.h"
-//#include "pcan.h"
-
-#include <applicfg.h>
-#include "timer.h"
+#include "cancfg.h"
 #include "can_driver.h"
-#include "timers_driver.h"
-
-#define MAX_NB_CAN_PORTS 1
+#include "def.h"
+#ifndef extra_PCAN_init_params
+       #define extra_PCAN_init_params /**/
+#else
+       #define extra_PCAN_init_params\
+               ,getenv("PCANHwType") ? strtol(getenv("PCANHwType"),NULL,0):0\
+               ,getenv("PCANIO_Port") ? strtol(getenv("PCANIO_Port"),NULL,0):0\
+               ,getenv("PCANInterupt") ? strtol(getenv("PCANInterupt"),NULL,0):0
+#endif
 
-typedef struct {
-  char used;
-  TASK_HANDLE receiveTask;
-  CO_Data* d;
-} CANPort;
+static s_BOARD *first_board = NULL;
+#ifdef PCAN2_HEADER_
+static s_BOARD *second_board = NULL;
+#endif
 
-CANPort canports[MAX_NB_CAN_PORTS] = {{0,},};
+//pthread_mutex_t PeakCan_mutex = PTHREAD_MUTEX_INITIALIZER;
 
 // Define for rtr CAN message
-#define CAN_INIT_TYPE_ST_RTR MSGTYPE_STANDARD | MSGTYPE_RTR 
+#define CAN_INIT_TYPE_ST_RTR MSGTYPE_STANDARD | MSGTYPE_RTR
 
-/*********functions which permit to communicate with the board****************/
-UNS8 canReceive(CAN_HANDLE fd0, Message *m)
+/***************************************************************************/
+int TranslateBaudeRate(char* optarg){
+       if(!strcmp( optarg, "1M")) return CAN_BAUD_1M;
+       if(!strcmp( optarg, "500K")) return CAN_BAUD_500K;
+       if(!strcmp( optarg, "250K")) return CAN_BAUD_250K;
+       if(!strcmp( optarg, "125K")) return CAN_BAUD_125K;
+       if(!strcmp( optarg, "100K")) return CAN_BAUD_100K;
+       if(!strcmp( optarg, "50K")) return CAN_BAUD_50K;
+       if(!strcmp( optarg, "20K")) return CAN_BAUD_20K;
+       if(!strcmp( optarg, "10K")) return CAN_BAUD_10K;
+       if(!strcmp( optarg, "5K")) return CAN_BAUD_5K;
+       if(!strcmp( optarg, "none")) return 0;
+       return 0x0000;
+}
+
+void
+canInit (s_BOARD *board)
 {
-  UNS8 data; 
-  TPCANMsg peakMsg;
-  if ((errno = CAN_Read(& peakMsg))) {         // Blocks until no new message or error.
-    perror("!!! Peak board : error of reading. (from f_can_receive function) \n");
-    return 1;
-  }
-  m->cob_id.w = peakMsg.ID;   
-  if (peakMsg.MSGTYPE == CAN_INIT_TYPE_ST)             /* bits of MSGTYPE_*/
-    m->rtr = 0;
-  else 
-    m->rtr = 1;
-  m->len = peakMsg.LEN;                                        /* count of data bytes (0..8) */
-  for(data = 0  ; data < peakMsg.LEN ; data++)                                 
-    m->data[data] = peakMsg.DATA[data];                /* data bytes, up to 8 */
-  
-  return 0;
+       int baudrate;
+       
+#ifdef PCAN2_HEADER_
+       // if not the first handler
+       if(second_board == (s_BOARD *)board)
+               if(baudrate = TranslateBaudeRate(board->baudrate))
+                       CAN2_Init (baudrate,
+                         CAN_INIT_TYPE_ST extra_PCAN_init_params);
+#endif
+       if(first_board == (s_BOARD *)board)
+               if(baudrate = TranslateBaudeRate(board->baudrate))
+                       CAN_Init (baudrate,
+                         CAN_INIT_TYPE_ST extra_PCAN_init_params);
 }
 
-void canReceiveLoop(CAN_HANDLE fd0)
+/*********functions which permit to communicate with the board****************/
+UNS8
+canReceive_driver (CAN_HANDLE fd0, Message * m)
 {
-       CO_Data* d = ((CANPort*)fd0)->d;
-       Message m;
-       while (1) {
-               if(!canReceive(fd0, &m))
+       UNS8 data;
+       TPCANMsg peakMsg;
+       DWORD Res;
+       do{
+               // We read the queue looking for messages.
+               // 
+               //pthread_mutex_lock (&PeakCan_mutex);
+#ifdef PCAN2_HEADER_
+               // if not the first handler
+               if(second_board == (s_BOARD *)fd0)
+                       Res = CAN2_Read (&peakMsg);
+               else
+#endif
+               if(first_board == (s_BOARD *)fd0)
+                       Res = CAN_Read (&peakMsg);
+               else
+                       Res = CAN_ERR_BUSOFF;
+               // A message was received
+               // We process the message(s)
+               // 
+               if (Res == CAN_ERR_OK)
                {
-                       EnterMutex();
-                       canDispatch(d, &m);
-                       LeaveMutex();
+                       // if something different that 11bit or rtr... problem
+                       if (peakMsg.MSGTYPE & ~(MSGTYPE_STANDARD | MSGTYPE_RTR))
+                       {
+                               if (peakMsg.MSGTYPE == CAN_ERR_BUSOFF)
+                               {
+                                       printf ("!!! Peak board read : re-init\n");
+                                       canInit((s_BOARD*) fd0);
+                                       usleep (10000);
+                               }
+       
+                               // If status, return status if 29bit, return overrun
+                               //pthread_mutex_unlock (&PeakCan_mutex);
+                               return peakMsg.MSGTYPE ==
+                                       MSGTYPE_STATUS ? peakMsg.DATA[2] : CAN_ERR_OVERRUN;
+                       }
+                       m->cob_id = peakMsg.ID;
+                       
+                       if (peakMsg.MSGTYPE == CAN_INIT_TYPE_ST)        /* bits of MSGTYPE_ */
+                               m->rtr = 0;
+                       else
+                               m->rtr = 1;
+                       m->len = peakMsg.LEN;   /* count of data bytes (0..8) */
+                       for (data = 0; data < peakMsg.LEN; data++)
+                               m->data[data] = peakMsg.DATA[data];     /* data bytes, up to 8 */
+#if defined DEBUG_MSG_CONSOLE_ON
+                       MSG("in : ");
+                       print_message(m);
+#endif
                }else{
-//                     printf("canReceive returned error\n");
-                       break;
+               //pthread_mutex_unlock (&PeakCan_mutex);
+               //if (Res != CAN_ERR_OK)
+               //{
+                       if (!
+                               (Res & CAN_ERR_QRCVEMPTY || Res & CAN_ERR_BUSLIGHT
+                                || Res & CAN_ERR_BUSHEAVY))
+                       {
+                               printf ("canReceive returned error (%d)\n", Res);
+                               return 1;
+                       }
+                       usleep (1000);          
                }
-       }
+       }while(Res != CAN_ERR_OK);
+       return 0;
 }
 
 /***************************************************************************/
-UNS8 canSend(CAN_HANDLE fd0, Message *m)
+UNS8
+canSend_driver (CAN_HANDLE fd0, Message * m)
 {
-  UNS8 data;
-  TPCANMsg peakMsg;
-  peakMsg.ID=m -> cob_id.w;                                    /* 11/29 bit code */
-  if(m->rtr == 0)      
-    peakMsg.MSGTYPE = CAN_INIT_TYPE_ST;       /* bits of MSGTYPE_*/
-  else {
-    peakMsg.MSGTYPE = CAN_INIT_TYPE_ST_RTR;       /* bits of MSGTYPE_*/
-  }
-  peakMsg.LEN = m->len;   
-                               /* count of data bytes (0..8) */
-  for(data = 0 ; data <  m->len; data ++)
-       peakMsg.DATA[data] = m->data[data];             /* data bytes, up to 8 */
-  
-  if((errno = CAN_Write(& peakMsg))) {
-    perror("!!! Peak board : error of writing. (from canSend function) \n");
-    return 1;
-  }
-  return 0;
+       UNS8 data;
+       TPCANMsg peakMsg;
+       peakMsg.ID = m->cob_id; /* 11/29 bit code */
+       if (m->rtr == 0)
+               peakMsg.MSGTYPE = CAN_INIT_TYPE_ST;     /* bits of MSGTYPE_ */
+       else
+       {
+               peakMsg.MSGTYPE = CAN_INIT_TYPE_ST_RTR; /* bits of MSGTYPE_ */
+       }
+       peakMsg.LEN = m->len;
+       /* count of data bytes (0..8) */
+       for (data = 0; data < m->len; data++)
+               peakMsg.DATA[data] = m->data[data];     /* data bytes, up to 8 */
+       
+       do
+       {
+#ifdef PCAN2_HEADER_
+               // if not the first handler
+               if(second_board == (s_BOARD *)fd0)
+               {
+                       errno = CAN2_Write (&peakMsg);
+               }
+               else 
+#endif
+               if(first_board == (s_BOARD *)fd0)
+                       {
+                               errno = CAN_Write (&peakMsg);
+                       }
+               else 
+                       goto fail;
+               if (errno)
+               {
+                       if (errno == CAN_ERR_BUSOFF)
+                       {
+                               printf ("!!! Peak board write : re-init\n");
+                               canInit((s_BOARD*)fd0);
+                               usleep (10000);
+                       }
+                       usleep (1000);
+               }
+       }
+       while (errno != CAN_ERR_OK);
+#if defined DEBUG_MSG_CONSOLE_ON
+       MSG("out : ");
+       print_message(m);
+#endif
+       return 0;
+fail:
+       return 1;
+}
 
+/***************************************************************************/
+UNS8 canChangeBaudRate_driver( CAN_HANDLE fd, char* baud)
+{
+       printf("canChangeBaudRate not yet supported by this driver\n");
+       return 0;
 }
 
 /***************************************************************************/
-CAN_HANDLE canOpen(s_BOARD *board)
+CAN_HANDLE
+canOpen_driver (s_BOARD * board)
 {
-  HANDLE fd0 = NULL;
   char busname[64];
   char* pEnd;
-  int i;  
-  
-  for(i=0; i < MAX_NB_CAN_PORTS; i++)
+       
+  //printf ("Board Busname=%d.\n",strtol(board->busname, &pEnd,0));
+  if (strtol(board->busname, &pEnd,0) == 0)
   {
-       if(!canports[i].used)
-               break;
+      first_board = board;
+      printf ("First Board selected\n");
+      canInit(board);  
+      return (CAN_HANDLE)board;
   }
-  if(canports[i].used)
+  #ifdef PCAN2_HEADER_
+  if (strtol(board->busname, &pEnd,0) == 1)
   {
-       perror("can_peak_win32.c: no more can port available with this pcan library\n");
-       perror("can_peak_win32.c: please link another executable with another pcan lib\n");
-       return NULL;
+      second_board = board;
+      printf ("Second Board selected\n");
+      canInit(board);  
+      return (CAN_HANDLE)board;
   }
-//  if(strtol(board->busname, &pEnd,0) >= 0)
-//  {
-//    sprintf(busname,"/dev/pcan%s",board->busname);
-//    fd0 = LINUX_CAN_Open(busname, O_RDWR);
-//  }
-
-  if (i==MAX_NB_CAN_PORTS || fd0 == NULL)
-    {
-      fprintf (stderr, "Open failed.\n");
-      return (CAN_HANDLE)NULL;
-    }
-
-   CAN_Init(board->baudrate, CAN_INIT_TYPE_ST);
-
-   canports[i].used = 1;
-
-   canports[i].d = board->d;
-   CreateReceiveTask((CANPort*) &canports[i], &canports[i].receiveTask);
-
-   return (CANPort*) &canports[i];
+  #endif
+  return NULL;
 }
 
 /***************************************************************************/
-int canClose(CAN_HANDLE fd0)
+int
+canClose_driver (CAN_HANDLE fd0)
 {
-  CAN_Close();
-  ((CANPort*)fd0)->used = 0;
-  WaitReceiveTaskEnd(&((CANPort*)fd0)->receiveTask);
-  return 0;
+#ifdef PCAN2_HEADER_
+       // if not the first handler
+       if(second_board == (s_BOARD *)fd0)
+       {
+               CAN2_Close ();
+               second_board = (s_BOARD *)NULL;
+       }else   
+#endif
+       if(first_board == (s_BOARD *)fd0)
+       {
+               CAN_Close ();
+               first_board = (s_BOARD *)NULL;
+       }
+       return 0;
 }