Subversion Repositories shark

Rev

Blame | Last modification | View Log | RSS feed

/*
 * Project:
 *   Parallel Port S.Ha.R.K. Project
 *
 * Module:
 *   ppDrv.c
 *
 * Description:
 *   file contents description
 *
 * Coordinators:
 *   Giorgio Buttazzo    <giorgio@sssup.it>
 *   Paolo Gai           <pj@gandalf.sssup.it>
 *
 * Authors:
 *   Andrea Battistotti <btandrea@libero.it>
 *   Armando Leggio     <a_leggio@hotmail.com>
 *
 *
 * http://www.sssup.it
 * http://retis.sssup.it
 * http://shark.sssup.it
 *
 */


/**********************************************************************************************************
 * Module : ppDrv.c Author : Andrea Battistotti , Armando Leggio
 * Description: Tranfer Byte via LPT1 laplink cable...  2002 @ Pavia -
 * GNU Copyrights */


/*
 * Copyright (C) 2002 Andrea Battistotti , Armando Leggio
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * CVS : $Id: ppdrv.c,v 1.1 2002-10-28 08:03:54 pj Exp $
 */



#include <drivers/parport.h>


/* internal */
BYTE RxBuf[PP_BUF_LEN];                         /* Received bytes buffer */
BYTE TxBuf[PP_BUF_LEN];                         /* To transmit bytes buffer */

unsigned int nextByteReadyToRx;   /* pointer to first byte to read by ppOneByteRx(BYTE *c) ... */
unsigned int nextByteReadyToTx;   /* when ppbTransmit had to send a byte, send this...*/
unsigned int nextByteFreeRx;      /* when polling complete reading a byte, will save it in this loc...*/
unsigned int nextByteFreeTx;      /* when ppbTransmit had to write a byte, write it here...*/

/* define inline macro */
/* these are for cicle buffer mamagement */
#define RxPointerGap            (nextByteFreeRx-nextByteReadyToRx)
#define bytesReadyToRx      ((RxPointerGap)>=0? (RxPointerGap):PP_BUF_LEN+(RxPointerGap))
#define TxPointerGap            (nextByteFreeTx-nextByteReadyToTx)
#define bytesReadyToTx      ((TxPointerGap)>=0? (TxPointerGap):PP_BUF_LEN+(TxPointerGap))
#define freeBytesInRxBuffer (PP_BUF_LEN-bytesReadyToRx)
#define freeBytesInTxBuffer (PP_BUF_LEN-bytesReadyToTx)


/* for pp sys msg */
char SysMsg[SYS_MSG_COLS+1][SYS_MSG_LINS+1];    /* space for sys msgs... */
char bufMsg[SYS_MSG_COLS+1];                                    /* to build msgs... */

unsigned int nextMsgToRead;
unsigned int nextMsgFreeToWrite;

/* define inline macro */
/* these are for cicle buffer mamagement */
#define msgPointerGap           (nextMsgFreeToWrite-nextMsgToRead)
#define msgReadyToRead      ((msgPointerGap)>=0? (msgPointerGap):SYS_MSG_LINS+(msgPointerGap))
#define freeMsgInBuffer     (SYS_MSG_LINS-msgReadyToRead)




/* status ... */
enum ppReadingAvailableStates
{
  ppNoAllowReading,      /* writing is on...*/ 
  ppNoReading,
  ppWaitingDR_Nibble1,
  ppWaitingRTS_Nibble2,
  ppWaitingDR_Nibble2,
};

enum ppWritingAvailableStates
{
  ppNoAllowWriting,      /* reading is on...*/
  ppNoWriting,
  ppWaitingOTS_Nibble1,
  ppWaitingER_Nibble1,
  ppWaitingOTS_Nibble2,
  ppWaitingER_Nibble2
};


int ppStatusReading;
int ppStatusWriting;
BYTE ppReceivingByte;
BYTE ppTransmittingByte;


#if PP_STATS == 1
/* for internal statistic ...if activate...*/
long statReading[ppWaitingDR_Nibble2+1];
long statWriting[ppWaitingER_Nibble2+1];
#endif



/*********************************************/
/* sys msg managment */
/*********************************************/

int ppReadSysMsg(char * buf)
{
  if (!msgReadyToRead)                                  /* there is nothing to read...*/
    {
      return (PP_NOSYSMSG_EXC);
    }
  else
    {int i=0;
    while (i<SYS_MSG_COLS && SysMsg[nextMsgToRead][i])   /* !='\0'...*/
      *buf++=SysMsg[nextMsgToRead][i++];                        /* read char */
               
    *buf='\0'; 
    nextMsgToRead=++nextMsgToRead%SYS_MSG_LINS;         /* circular buffer increment */
    return (PP_SYSMSG_OK);
    }
}



int ppWriteSysMsg(char * buf, ...)
{
  char * pbufMsg=bufMsg;
  va_list args;
  bufMsg[0]='\0';
  va_start(args, buf);
  vsprintf(bufMsg,buf,args);    /* Not garatee msg len... */  
  va_end(args);

       
  if (freeMsgInBuffer < 1)
    {
      return (PP_NOFREEMSG_EXC);
    }
  else
    {int i=0;
    while ((i<SYS_MSG_COLS) && (*pbufMsg) )   /* !='\0'...*/        
      SysMsg[nextMsgFreeToWrite][i++]=*pbufMsg++;
               
    SysMsg[nextMsgFreeToWrite][i-1]='\n';
    SysMsg[nextMsgFreeToWrite][i]='\0';
    nextMsgFreeToWrite=++nextMsgFreeToWrite%SYS_MSG_LINS; /* circular buffer pointer increment */
    return (PP_SYSMSG_OK);
    }
}


/******************************************/
/*   Inizialization: this is NRT task...  */
/******************************************/

void ppInitDrv(void (*pf)(char *))
{
  /* set to zero all pointer & buffer & status... */


  while(ppNRTOpenComm()!=TRUE)   // not real-time....
    {
      if (pf!=NULL) (*pf)("Waiting Open Communcation...\n");
      ppSendER();
    }
  if (pf!=NULL) (*pf)("Open Communcation OK!\n");
}


/******************************************/
/* TX RX funtions... */
/******************************************/

int ppRxOneByte(BYTE *c)
{                  
  if (!bytesReadyToRx)                                  /* there is nothing to read...*/
    {
      return (PP_COMM_NOREADYBYTES_EXC);
    }
  else
    {
      *c=RxBuf[nextByteReadyToRx];                              /* read byte */
      nextByteReadyToRx=++nextByteReadyToRx%PP_BUF_LEN;         /* circular buffer increment */
      return (PP_COMM_OK);
    }
}


int ppTxOneByte(BYTE c)
{
  if (freeBytesInTxBuffer < 1)
    {
      return (PP_COMM_NOFREEBYTES_EXC);
    }
  else
    {
      TxBuf[nextByteFreeTx]=c;
      nextByteFreeTx=++nextByteFreeTx%PP_BUF_LEN; /* circular buffer pointer increment */

      return (PP_COMM_OK);
    }
}

int ppTxBytes(BYTE * c, unsigned int  nbyte)
{
  if (freeBytesInTxBuffer<nbyte)                                        /* if there are less than nbyte return nothing...*/
    {
      return (PP_COMM_NOFREEBYTES_EXC);
    }
  else
    { unsigned int i;
    for (i=0;i<nbyte;i++)
      {
        TxBuf[nextByteFreeTx]=*c++;
        nextByteFreeTx=++nextByteFreeTx%PP_BUF_LEN; /* circular buffer pointer increment */
      }

    return (PP_COMM_OK);
    }
}



int ppRxBytes(BYTE * c, unsigned int nbyte)
{
                 
  if (bytesReadyToRx<nbyte)           /* if there are less than nbyte return nothing...*/
    {
      return (PP_COMM_NOREADYBYTES_EXC);
    }
  else
    { unsigned int i;

    for (i=0;i<nbyte;i++)
      {
        *c++=RxBuf[nextByteReadyToRx];                          /* read byte */
                                       
#if PP_DEBUG == 1
        ppWriteSysMsg("Received value: %i %i of %i \n",RxBuf[nextByteReadyToRx],i,nbyte);
#endif
                   
        nextByteReadyToRx=++nextByteReadyToRx%PP_BUF_LEN;       /* circular buffer increment */
      }

    return (PP_COMM_OK);
    }
}




/* polling server ... */
TASK ppPollingSvr(void *arg)
{
  BYTE port;
  nextByteReadyToRx=0;
  nextByteReadyToTx=0;          
  nextByteFreeRx=0;  
  nextByteFreeTx=0;

  nextMsgToRead=0;
  nextMsgFreeToWrite=0;


  ppStatusReading=ppNoReading;
  ppStatusWriting=ppNoWriting;

  ppWriteSysMsg("Polling Server started...\n");

  task_endcycle();

  while (1)
    {
           
      /* case ppReading: read ... */
      switch (ppStatusReading)
        {
        case ppNoAllowReading: break;
       
        case ppNoReading:

          ppStatusWriting=ppNoWriting;
                         
          if(!ppIsRTS())   break;
          ppSendOTS();     /* Set Ok To Send - the other one can send... */
                                               
#if PP_DEBUG == 1
          ppWriteSysMsg(" %i : Received RTS...\n", ppStatusReading);
#endif

          ppStatusWriting=ppNoAllowWriting;
          ppStatusReading=ppWaitingDR_Nibble1;
       
        case ppWaitingDR_Nibble1:
       
#if PP_STATS == 1                              /* for internal statistic ...*/
          statReading[ppStatusReading]++;
#endif
       
       

#if PP_DEBUG == 1
          ppWriteSysMsg("Send OTS\n");
          ppWriteSysMsg("Waiting DR Nibble1\n");
#endif

          if(!ppIsDR()) break;                /* data no ready: read it next period...*/
          port = inp(RX_PORT);                       /* read  nibble    */
          ppSendER();                                                              /* send a End Read */

          ppReceivingByte = (port >> 3);             /* read LSN */
          ppStatusReading=ppWaitingRTS_Nibble2;
                               
        case ppWaitingRTS_Nibble2:
#if PP_STATS == 1                                       /* for internal statistic ...*/
          statReading[ppStatusReading]++;
#endif
       
#if PP_DEBUG == 1

          ppWriteSysMsg("Received DR Nibble1\n");
          ppWriteSysMsg("Send ER Nibble1\n");
          ppWriteSysMsg("Waiting RTS Nibble2\n");
#endif
       
          if(!ppIsRTS()) break;           /* */
          ppSendOTS();                       /* Ok To Send - the other one can send... */

          ppStatusReading=ppWaitingDR_Nibble2;
       
        case ppWaitingDR_Nibble2:
#if PP_STATS == 1                                       /* for internal statistic ...*/
          statReading[ppStatusReading]++;
#endif
#if PP_DEBUG == 1
          ppWriteSysMsg("Received RTS Nibble2\n");
          ppWriteSysMsg("Send OTS Nibble2\n");
          ppWriteSysMsg("Waiting DR Nibble2\n");
#endif

          if(!ppIsDR()) break;
          port = inp(RX_PORT);                 /* read nibble    */
          ppSendER();                          /* send a End Read */


#if PP_DEBUG == 1
          ppWriteSysMsg("Received DR Nibble2\n");
          ppWriteSysMsg("Read Nibble2\n");
          ppWriteSysMsg("Send ER Nibble2\n");
#endif



          ppReceivingByte = (ppReceivingByte & ~MSN);               /* set to zero c MSN */
          ppReceivingByte = (ppReceivingByte | ((port >> 3) << 4)); /* read MSN */


                                /* here is possible insert some ctrl ... */
                               
                               
                                /* byte is ok, so now make it available to ppRxOneByte() */
                               
          RxBuf[nextByteFreeRx]=ppReceivingByte;
          nextByteFreeRx=++nextByteFreeRx%PP_BUF_LEN; /* circular buffer pointer increment */
       
#if PP_STATS == 1
          ppWriteSysMsg("Trasmission :\n");
          ppWriteSysMsg("W_DR_1  : %d\n",statReading[ppWaitingDR_Nibble1]);
          ppWriteSysMsg("W_RTS_2 : %d\n",statReading[ppWaitingRTS_Nibble2]);
          ppWriteSysMsg("W_DR_2  : %d\n",statReading[ppWaitingDR_Nibble2]);
          ppWriteSysMsg("Received byte : %i\n",ppReceivingByte);
          statReading[ppWaitingDR_Nibble1]=0;
          statReading[ppWaitingRTS_Nibble2]=0;
          statReading[ppWaitingDR_Nibble2]=0;
#endif
          /* end reading so reset status... */
       
          ppStatusReading=ppNoReading;
          //ppStatusWriting=ppNoWriting;
          break;                                                               
        }
                       
                               
      /* case Writing: can only if this cycle not is reading... */
      switch (ppStatusWriting)
        {
                       
        case ppNoAllowWriting: break;
       
        case ppNoWriting:

          ppStatusReading=ppNoReading;

          if(!bytesReadyToTx)
            {
              break;
#if PP_DEBUG == 1
              ppWriteSysMsg("Writin break\n");
#endif
            }
          else  
            {
#if PP_DEBUG == 1
              ppWriteSysMsg("NO Writin break\n");
              ppWriteSysMsg("TX Gap: %i \n",TxPointerGap);
              ppWriteSysMsg("nextByteFreeTx: %i\n",nextByteFreeTx);
              ppWriteSysMsg("nextByteReadyToTx: %i\n",nextByteReadyToTx);
#endif
            }

          ppSendRTS();                                 /* Set On RequestToSend bit */

          ppTransmittingByte=TxBuf[nextByteReadyToTx];
       
#if PP_DEBUG == 1
          ppWriteSysMsg("pllsvr: ppTransmittingByte : %i %c \n",ppTransmittingByte,ppTransmittingByte);
#endif
                                                       
                               
          port = inp(TX_PORT) & (~TX_DATA);            /* set to zero trasmission bits */
          port = port | (ppTransmittingByte & LSN);    /* set  bits 0..3 with LSN   */
       
          ppStatusWriting=ppWaitingOTS_Nibble1;
          ppStatusReading=ppNoAllowWriting;
       
        case ppWaitingOTS_Nibble1:
#if PP_STATS == 1                          
          statWriting[ppStatusWriting]++;
#endif
       
#if PP_DEBUG == 1                              
          ppWriteSysMsg(" Send RTS Nibble1\n");
          ppWriteSysMsg(" Waiting OTS Nibble1\n");
#endif
          if(!ppIsOTS()) break;
          outp(TX_PORT,port);                   /* send nibble 1   */
          ppSendDR();                                 /* set on Data Ready bit  */


          ppStatusWriting=ppWaitingER_Nibble1;


        case ppWaitingER_Nibble1:
#if PP_STATS == 1        
          statWriting[ppStatusWriting]++;
#endif
       
#if PP_DEBUG == 1
          ppWriteSysMsg(" Send Nibble1\n");
          ppWriteSysMsg(" Send DR Nibble1\n");
          ppWriteSysMsg(" Waiting ER Nibble1\n");
#endif

          if(!ppIsER()) break;

          ppSendRTS();                                 /* send trasmission request */

          port = inp(TX_PORT) & (~TX_DATA);            /* set to zero bit trasmission bits */
          port = port | (ppTransmittingByte >> 4);     /* set  bits 0..3 with MSN   */
                               
          ppStatusWriting=ppWaitingOTS_Nibble2;
                               
        case ppWaitingOTS_Nibble2:

#if PP_STATS == 1
          statWriting[ppStatusWriting]++;
#endif

#if PP_DEBUG == 1
          ppWriteSysMsg(" Received ER Nibble1\n");
          ppWriteSysMsg(" Send RTS Nibble2\n");
          ppWriteSysMsg(" Waiting OTS Nibble2\n");
#endif

                       
          if(!ppIsOTS()) break;
          outp(TX_PORT,port);                           /* send nibble 2          */
          ppSendDR();                                   /* set on Data Ready bit  */

          ppStatusWriting=ppWaitingER_Nibble2;

        case ppWaitingER_Nibble2:
#if PP_STATS == 1                              
          statWriting[ppStatusWriting]++;
#endif
       
#if PP_DEBUG == 1
          ppWriteSysMsg(" Received OTS Nibble2\n");
          ppWriteSysMsg(" Write Nibble2\n");
          ppWriteSysMsg(" Send DR Nibble2\n");
          ppWriteSysMsg(" Waiting ER Nibble2\n");
#endif

          if(!ppIsER()) break;
       
                                /* byte is ok, so move pointer to next byte to be send... */
          nextByteReadyToTx=++nextByteReadyToTx%PP_BUF_LEN; /* circular buffer pointer increment */
                               
#if PP_STATS == 1
          ppWriteSysMsg("Reception :\n");
          ppWriteSysMsg("W_OTS_1  : %ld\n",statWriting[ppWaitingOTS_Nibble1]);
          ppWriteSysMsg("W_ER_2 : %ld\n",statWriting[ppWaitingER_Nibble2]);
          ppWriteSysMsg("W_OTS_2  : %ld\n",statWriting[ppWaitingOTS_Nibble2]);
          statWriting[ppWaitingOTS_Nibble1]=0;
          statWriting[ppWaitingER_Nibble2]=0;
          statWriting[ppWaitingOTS_Nibble2]=0;
#endif

          /* end writing. so reset status... */
          ppStatusReading=ppNoReading;
          ppStatusWriting=ppNoWriting;
        }                      
               
      task_endcycle();
    }                                                
  return (0);
}