
#include <basespikingchannel.h>


//********* Code for BaseSpikingChannel::OneCell ***********************

BaseSpikingChannel::OneCell::OneCell() : IntegratorNeuron_cpm()
{
  xOffset=0; yOffset=0;
}

void BaseSpikingChannel::OneCell::xml_ize()
{
  xmlClass::add_param(xOffset,"x-offset");
  xmlClass::add_param(yOffset,"y-offset");
  xmlClass::add_param(Devs::id,"mvaspike-id");
}


//*********    Code for BaseSpikingChannel   ***************************


void BaseSpikingChannel::checkStatus(void)
{
  if(done)
  {
    cerr<<"Error in BaseSpikingChannel: You're changing parameter of a filter after it has started to function."<<endl;
    exit(0);
  }
}


void BaseSpikingChannel::allocateValues(void)
{
	//cout<<"Random initialization is set at: "<<randomInit<<endl;
}


BaseSpikingChannel::BaseSpikingChannel(double stepp)
{
  step=stepp;

  g_leak=50;
  tau_refr=0.003;
  noise_refr=0.0;
  noiseV=0.0;
  delta_g_adap=0.0;
  tau_g_adap=0.0;
  E_adap=0.0;
  done=false;
  randomInit=false;
}


void BaseSpikingChannel::xml_ize ()
{

  xmlClass::add_param(g_leak,"g-leak__Hz");
  xmlClass::add_param(tau_refr,"refr-mean__sec");
  xmlClass::add_param(noise_refr,"refr-stdev__sec");
  xmlClass::add_param(noiseV,"sigma-V");
  xmlClass::add_param(delta_g_adap,"delta-g-adap__Hz");
  xmlClass::add_param(tau_g_adap,"tau-g-adap__sec");
  xmlClass::add_param(E_adap,"E-adap");
  xmlClass::add_param(randomInit,"random-init");

  xmlClass::add_child( units , "all-units" );
  xmlRegister<2, OneCell> ( units , xml_names("", "unit") );
  xmlRegister<2, OneCell_adap> (units ,"unit-adap-version" );
}


BaseSpikingChannel::~BaseSpikingChannel(void)
{
  for(uint i=0;i<units.size();++i) delete[] units[i];
}

void BaseSpikingChannel::create_new_unit(double xx, double yy)
{
  if(delta_g_adap==0)
    units.push_back(new OneCell());
  else
    units.push_back(new OneCell_adap());

  units.back()->set_g_leak(g_leak);      //spiking properties from class ConductanceNeuron
  units.back()->tau_refr=this->tau_refr;
  units.back()->noise_refr=this->noise_refr;
  units.back()->set_noiseV(noiseV);
  units.back()->set_step(step);             //the IntegratorNeuron parameter

  units.back()->xOffset=xx;  //OneCell properties
  units.back()->yOffset=yy;

  if(randomInit){
	  units.back()->set_V ( ranf() );
  }
  
 if(delta_g_adap)			//the IntegratorNeuron_adap properties
  {
    OneCell_adap * temp = dynamic_cast<OneCell_adap*>(units.back());
    temp->set_delta_g_adap (delta_g_adap );
    temp->set_tau_g_adap (tau_g_adap );
    temp->set_E_adap (E_adap );
  }

}

//Channel parameter definition functions :

void BaseSpikingChannel::set_step(double s)
{
  checkStatus();
  step=s;
}

void BaseSpikingChannel::set_g_leak(double f)
{
  checkStatus();
  g_leak=f;
}
void BaseSpikingChannel::set_tau_refr(double f)
{
  checkStatus();
  tau_refr=f;
}
void BaseSpikingChannel::set_noise_refr(double f)
{
  checkStatus();
  noise_refr=f;
}
void BaseSpikingChannel::set_noiseV(double f)
{
  checkStatus();
  noiseV=f;
}



//Feeding an image to the retina.

void BaseSpikingChannel::feedInput(const CImg<double> & image)
{
  if (!done) allocateValues();

  double xMid=image.dimx()/2.0, yMid=image.dimy()/2.0;
  for(uint ind=0;ind<units.size();++ind)   units[ind]->feedInput(image,xMid,yMid);
}


