/*
    Packetizer.c, Copyright 1.5.97 (c) by Bernard Stauffer,
    Swiss Federal Institute of Technology,
    Computer Engineering and Networks Laboratory.
 
    TOPSY -- A Teachable Operating System.
             Implementation of a tiny and simple
             micro kernel for teaching purposes.
 
    For further information, please visit http://www.tik.ee.ethz.ch/~topsy
 
    This software is provided under the terms of the GNU General Public Licence.
 
    A full copy of the GNU GPL is provided in the file COPYING found in the 
    development root of Topsy.
*/
/*
  File:                  $Source: /home/ruf/cvs_Topsy/cvs/Topsy/User/Packetizer.c,v $
  Author(s):             Bernard Stauffer 
  Affiliation:           ETH Zuerich, TIK
  Version:               $Revision: 2922 $
  Creation Date:         1.5.97
  Last Date of Change:   $Date: 2007-03-19 17:48:52 +0100 (Mon, 19 Mär 2007) $      by: $Author: baderma $
*/

#include "../Topsy/Topsy.h"
#include "../Topsy/Syscall.h"
#include "UserSupport.h"

#include "datafile.h"
#include "Packetizer.h"
#include "PacketStackGlobals.h"

#define TERMINATECHAR '\a'    /* the ASCII BELL char, used here as program end mark */



/* ---------------------------------------------------------------------------- */
/* Sender thread: reads a byte stream and packetize it                          */
/* 'chardata' is an imported text file                                          */

void PacketSender()
{

  Message       sendmsg, sendmsg_ack;
  unsigned long inputdatasize, buffersize, i,j;
  char          buffer[MAXPACKETLEN];
  char*         ptrcharfile = charfile;


  while (!packetStartFlag)
    ;                /* Wait for startFlag = true */

  /* --- Prepare all vars */

  inputdatasize = stringLength(charfile);       /* Get length of input data */

  sendmsg.id = USER;                      /* Set message id of user message (static) */
  sendmsg.msg.userMsg.p1 = buffer;        /* Set message pointer to databuffer (static) */
  sendmsg.msg.userMsg.p2 = &buffersize;   /* Set message pointer to length (static) */
  CLEAR_MSGENV(sendmsg);

  buffersize = 0;                         /* Counter for packet length */


  /* --- Main packetizer loop over the input data */

  for (i=0; i <= inputdatasize; i++)
  {          /* i: indices over input data */

    if (*ptrcharfile == '\0')
    {                 /* Test input data */
      ptrcharfile++;                            /* Skip ESCAPE char */
    }
    else
    {
      buffer[buffersize++] = *ptrcharfile++ ;   /* Copy input data to buffer */
    }

    if ((buffersize == 249) || (i == inputdatasize))
    { /* If packet assembled, send it */
      if (tmMsgSend(My_ThreadList[IRQSEND_ID], &sendmsg) == TM_MSGSENDFAILED)
      {
        display(My_ThreadList[TTY_ID],"tmMsgSend1 failed in thread Sender.\n");
      }
      else
      {                                    /* if no error, wait for ack message */
        tmMsgRecv(&My_ThreadList[IRQSEND_ID], ANYMSGTYPE, &sendmsg_ack, INFINITY);
      }

      buffersize = 0;                           /* Reset packet length counter */
    }

  }   /* End: for ... */


  /* --- The input is packetized, so send now an end mark char */

  buffer[0] = TERMINATECHAR;                    /* Termination message (BELL char) */
  buffersize = 1;
  if (tmMsgSend(My_ThreadList[IRQSEND_ID], &sendmsg) == TM_MSGSENDFAILED)
  {
    display(My_ThreadList[TTY_ID],"tmMsgSend2 failed in thread Sender.\n");
  }
  /* Wait for ack */
  tmMsgRecv(&My_ThreadList[IRQSEND_ID], ANYMSGTYPE, &sendmsg_ack, INFINITY);


  /* --- That was it. Now wait for ever, till i'm killed ... */

  while (TRUE)
    ;

}



/* ---------------------------------------------------------------------------- */
/* Receiver thread: receives packets from the IRQ thread and prints them to the CONSOLE */

void PacketReceiver()
{

  Message         recvmsg, recvmsg_ack;
  ThreadId        from;
  char            *ptrbuffer;
  unsigned long   buffersize, i;

  char s[256];


  while (!packetStartFlag)
    ;       /* Wait for startFlag = true */


  /* --- Prepare all vars */

  recvmsg_ack.id = USER;                  /* Set message id of user message (static) */
  CLEAR_MSGENV(recvmsg_ack);
  from = ANY;                             /* Set message receive id (static) */


  /* --- Main loop. (Loop for ever ...) */

  while (TRUE)
  {

    if (tmMsgRecv(&from, ANYMSGTYPE, &recvmsg, INFINITY) == TM_MSGRECVFAILED)
    {
      display(My_ThreadList[TTY_ID],"tmMsgRecv failed in thread Receiver.\n");
    }

    ptrbuffer = (char*) recvmsg.msg.userMsg.p1;     /* Copy pointer to local var */
    buffersize = *(long*) recvmsg.msg.userMsg.p2;   /* Copy length to local var */

    /* If only one char, test if BELL char. If true, ... */
    /* ... send termination message to Control thread.   */
    if ((buffersize == 1) && (*ptrbuffer == TERMINATECHAR))
    {
      tmMsgSend(My_ThreadList[CONTROL_ID], &recvmsg_ack);
      while (TRUE)
        ;              /* Loop for ever, till i'm killed ... */
    }

    /* Print received data to console */
    ioWrite(My_ThreadList[TTY_ID], ptrbuffer, &buffersize);

    /* Send back ack message */
    if (tmMsgSend(recvmsg.from, &recvmsg_ack) == TM_MSGSENDFAILED)
    {
      display(My_ThreadList[TTY_ID],"tmMsgSend failed in thread Receiver.\n");
    }

  }   /* End: while ... */

}


/* ---------------------------------------------------------------------------- */

