// initiate transmission of a packet
void EZRoboNetDevice::sendPacket(EZPacket* pack) {
    byte theReceiver = pack->ReceiverID;
    CurrentPacket = packet2Bytes(pack);
    // disposing pack now...
    disposePacket(pack);
    // retrieving length of raw packet data
    CurrentPacketLength = getRawPacketLength(CurrentPacket);
    
    // computing number of frames required
    TotalFrames = CurrentPacketLength /  MAX_FRAME_PAYLOAD_LENGTH +1;
    
    // zeroing number of frames sent
    FramesSent = 0;
    // Clearing the timeout flag
    PacketSendTimeout = false;
    // marking the starting time for possible timeouts
    TransmissionStartTime = millis();
    // Setting Packet receiver Global
    PacketReceiverID = theReceiver;
    // setting state to sending...
    state = stSending;
    // now sending first frame
    sendNextFrame();

}
void disposePacketBuffer(BCSPStack * stack, PacketBuffer *buf) 
{
	Packet * pkt ;
	while (peekAtPacketInBuffer(buf))
	{
		pkt = SYNCBLKgetPacketFromBuffer(stack,buf) ;
		disposePacket(stack,pkt) ;
	}
}
// clear the Packet Queue, reset the flags
void EZRoboNetDevice::resetPacketTransceiver() {
  ReceivedPacketsNum = 0;
  int i;
  for (i=0; i<2; i++) 
    if (ReceivedPackets[i]!=NULL) {
      disposePacket(ReceivedPackets[i]);
      ReceivedPackets[i] = NULL;
    }
  clearFlags();
}
void BCSPshutdownStack(BCSPStack * stack)
{
	
	Packet * pkt ;
	int  c ;
	//run the scheduler to ensure that user transfer requests queues are drained
	//it's also important to empty the output buffer.  This ensures that the 
	//SlipSender can't get blocked and so a pending abort can be processed,
	//resulting in a coherent stack state.  Without this, SLIPinputPacket can be 
	//a packet that has just been aborted and called back

	while (numEntriesInByteBuffer(&stack->SLIPByteOutput)) 
			readByteFromByteBuffer(stack,&stack->SLIPByteOutput) ;
	//also drain the input buffer for completeness
	while (numEntriesInByteBuffer(&stack->SLIPByteInput)) 
			readByteFromByteBuffer(stack,&stack->SLIPByteInput) ;
	 

	scheduler(stack,0) ;
	
	//now return all packets to the packet pool, calling callbacks as we go...
	//NB - once we start disposing of packets, pool-accounting is 
	//in an unstable state and we must not attempt to get any packets back out again

	disposePacket(stack,stack->SLIPInputPacket) ;
	
	disposePacketBuffer(stack,&stack->MUXUnreliableInput) ;
	disposePacketBuffer(stack,&stack->MUXUnreliableInput) ;
	disposePacketBuffer(stack,&stack->SEQInput) ;
	//now do the receive side ...
	disposePacketBuffer(stack,&stack->PacketDelivererInput) ;
	disposePacketBuffer(stack,&stack->LinkEstablishmentInput) ;
	disposePacketBuffer(stack,&stack->RCVInputBuffer) ;
	disposePacket(stack,stack->theSLIPState.RCVpkt) ;


	//clear transfer request that never got associated with packets...
	disposeTransferRequestQueue(stack,&stack->requestRouterInput) ;
	for (c = 0 ; c < 16 ; c++)
		disposeTransferRequestQueue(stack,&stack->readRequests[c]) ;


	//now empty out the xmit window - it's possible that someone tried to do a write 
	//and then link-establishment failed.

	rollbackXMITWindow(stack,&stack->theXMITWindow) ;
	while ((pkt = ASYNCBLKremoveFirstUnsentPacketFromWindow(stack,&stack->theXMITWindow)))
	{
	    if (pkt != stack->SLIPInputPacket) disposePacket(stack,pkt) ;
	}


	//now all the packets should be back in the packet pool with their
	//callbacks having been cancelled and memory returned.  The only thing
	//left to do is to return the packets themselves.
	while (peekAtPacketInBuffer(&stack->thePacketPool.buffer))
	{
		pkt = SYNCBLKgetPacketFromBuffer(stack,&stack->thePacketPool.buffer) ;
		stack->environment->releasePacket(stack->environment->envState,pkt) ;
	}
	
}