/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */

/* By Pablo Martin and Paula Ballester,
 * Strathclyde University, Glasgow.
 * June, 2003.
*/

/* Copyright (c) 2003 Strathclyde University of Glasgow, Scotland.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code and binary code must contain
 * the above copyright notice, this list of conditions and the following
 * disclaimer.
 *
 * 2. All advertising materials mentioning features or use of this software
 * must display the following acknowledgement:
 * This product includes software developed at Strathclyde University of
 * Glasgow, Scotland.
 *
 * 3. The name of the University may not be used to endorse or promote
 * products derived from this software without specific prior written
 * permission.
 * STRATHCLYDE UNIVERSITY OF GLASGOW, MAKES NO REPRESENTATIONS
 * CONCERNING EITHER THE MERCHANTABILITY OF THIS SOFTWARE OR THE
 * SUITABILITY OF THIS SOFTWARE FOR ANY PARTICULAR PURPOSE.  The software
 * is provided "as is" without express or implied warranty of any kind.
*/


#include <delay.h>
#include <connector.h>
#include "packet.h"
#include <random.h>

// #define DEBUG
//#include <debug.h>
#include <arp.h>
#include "phy-timers.h"
#include "phy-umts.h"
#include "phy-umts-nodeb.h"
#include <mac.h>


/* ======================================================================
   Timers
   ====================================================================== */
void PhyUmtsTimer::start(Packet *p, double time)
{
	Scheduler &s = Scheduler::instance();
	assert(busy_ == 0);

	busy_ = 1;
	paused_ = 0;
	stime = s.clock();
	rtime = time;
	assert(rtime >= 0.0);

	s.schedule(this, p, rtime);
}

void PhyUmtsTimer::stop(Packet *p)
{
	Scheduler &s = Scheduler::instance();
	assert(busy_);

	if(paused_ == 0)
		s.cancel((Event *)p);

	busy_ = 0;
	paused_ = 0;
	stime = 0.0;
	rtime = 0.0;
}


void PreambleTimer::start(void)
{
	int temp;
	Scheduler &s = Scheduler::instance();
	assert(busy_ == 0);
	busy_ = 1;
	paused_ = 0;
	stime = s.clock();
	// arbitly limited the backoff timer from 4 to 12 slots.-
	// integer(K) gives a uniformly distributed integer btwn 0 and k-1
	// maybe shud backoff for some num of frames instead.
	temp =  Random::integer(8);
	rtime = (6 * 0.00125) + (double)(temp * 0.00125);
	assert(rtime >= 0.0);
	s.schedule(this, &intr, rtime);
}

void PreambleTimer::stop(void)
{
	Scheduler &s = Scheduler::instance();
	assert(busy_);
	if(paused_ == 0)
		s.cancel(&intr);
	busy_ = 0;
	paused_ = 0;
	stime = 0.0;
	rtime = 0.0;
}

void PreambleTimer::handle(Event *e)
{
	busy_ = 0;
	paused_ = 0;
	stime = 0.0;
	rtime = 0.0;
	phy->PreambleHandler();
}

void UpSlotUmtsTimer::handle(Event *e)
{
	busy_ = 0;
	paused_ = 0;
	stime = 0.0;
	rtime = 0.0;

	phy->upslotHandler(e);
}

void RachUpSlotUmtsTimer::handle(Event *e)
{
	busy_ = 0;
	paused_ = 0;
	stime = 0.0;
	rtime = 0.0;

	phy->rachupslotHandler(e);
}

/* Receive Timer */
void RxPktUmtsTimer::handle(Event *e)
{
	busy_ = 0;
	paused_ = 0;
	stime = 0.0;
	rtime = 0.0;

	phy->recvHandler(e);
}

/* Send Timer */
void TxPktUmtsTimer::handle(Event *e)
{
	busy_ = 0;
	paused_ = 0;
	stime = 0.0;
	rtime = 0.0;

	phy->sendHandler(e);
}

/* Bler Timer */
void BlerTimer::handle(Event *e)
{
	busy_ = 0;
	paused_ = 0;
	stime = 0.0;
	rtime = 0.0;

	phy->blerHandler(e);
}

/* Cell Selection Procedure */
void CellTimer::start(double time)
{
	Scheduler &s = Scheduler::instance();
	assert(busy_ == 0);

	busy_ = 1;
	paused_ = 0;
	stime = s.clock();
	rtime = time;
	assert(rtime >= 0.0);

	s.schedule(this, &intr, rtime);
}

void CellTimer::stop(void)
{
	Scheduler &s = Scheduler::instance();
	assert(busy_);
	if(paused_ == 0)
		s.cancel(&intr);
	busy_ = 0;
	paused_ = 0;
	stime = 0.0;
	rtime = 0.0;
}

void CellTimer::handle(Event *e)
{
	busy_ = 0;
	paused_ = 0;
	stime = 0.0;
	rtime = 0.0;

	phy->cellHandler();
}






void PhyNodebTimer::start(Packet *p, double time)
{
	Scheduler &s = Scheduler::instance();
	assert(busy_ == 0);

	busy_ = 1;
	paused_ = 0;
	stime = s.clock();
	rtime = time;
	assert(rtime >= 0.0);

	s.schedule(this, p, rtime);
}

void PhyNodebTimer::stop(Packet *p)
{
	Scheduler &s = Scheduler::instance();
	assert(busy_);

	if(paused_ == 0)
		s.cancel((Event *)p);

	busy_ = 0;
	paused_ = 0;
	stime = 0.0;
	rtime = 0.0;
}


void PagingTimer::start(double time)
{
	Scheduler &s = Scheduler::instance();
	assert(busy_ == 0);
	busy_ = 1;
	paused_ = 0;
	stime = s.clock();
	rtime = time;
	assert(rtime >= 0.0);
	s.schedule(this, &intr, rtime);
}

void PagingTimer::stop(void)
{
	Scheduler &s = Scheduler::instance();
	assert(busy_);
	if(paused_ == 0)
		s.cancel(&intr);
	busy_ = 0;
	paused_ = 0;
	stime = 0.0;
	rtime = 0.0;
}

void PagingTimer::handle(Event *e)
{
	busy_ = 0;
	paused_ = 0;
	stime = 0.0;
	rtime = 0.0;
	phy->PagingHandler(e);
}


void DownSlotUmtsTimer::handle(Event *e)
{
	busy_ = 0;
	paused_ = 0;
	stime = 0.0;
	rtime = 0.0;

	phy->downslotHandler(e);
}

void AichSlotUmtsTimer::handle(Event *e)
{
	busy_ = 0;
	paused_ = 0;
	stime = 0.0;
	rtime = 0.0;

	phy->aichslotHandler(e);
}

/* Receive Timer */
void RxPktNodebTimer::handle(Event *e)
{
	busy_ = 0;
	paused_ = 0;
	stime = 0.0;
	rtime = 0.0;

	phy->recvHandler(e);
}

/* Send Timer */
void TxPktNodebTimer::handle(Event *e)
{
	busy_ = 0;
	paused_ = 0;
	stime = 0.0;
	rtime = 0.0;

	phy->sendHandler(e);
}

/* Bler Timer */
void BlerNodebTimer::handle(Event *e)
{
	busy_ = 0;
	paused_ = 0;
	stime = 0.0;
	rtime = 0.0;

	phy->blerHandler(e);
}


