static char rcsid[] = "$Id: SynG_ron.c,v 1.0 1997/08/18 23:57:06 venkat Exp $";
#define VOLTAGE 0
#define CAF   1
#define CAS   2
#define POSTVOLTAGE 3
#define EK 4
#define TH 1000 

#include "SynGS_ext.h" 
static int      DEBUG_SynG = 0;
static double   savedata[3];

/*
 * Graded synaptic transmission designed specifically for leech HN cells.
 * Needs presynaptic calcium currents (ICaF and ICaS) and presynaptic membrane
 * potential as input.  The output is the synaptic conductance.  In addition,
 * this object can calculate the synpatic current if it is given the 
 * postsynaptic membrane potential.  This is useful only for the purpose of 
 * plotting the synaptic current.  The simuation will work without calculating
 * synaptic current because the postsynaptic compartment calculates the 
 * current based on the postsynaptic Vm and the synaptic reversal potential.
 *
 * This object was modified from synchan.c by J. Lu and A. Hill
 */

int SynG(channel,action)
   register struct SynG_type *channel;
   Action  *action;
{
   double  dt;
   int CAS_msg_in = 1,CAF_msg_in = 1,volt_msg_in = 1,pvolt_msg_in =1; /*CHECK*/
   MsgIn   *msg;
   long double  V, ICaF, ICaS, I_Ca, Ainf, Atau, tmp, PV, g;
   int	n;
  
   if(Debug(DEBUG_SynG) > 1)
      ActionHeader("SynG",channel,action);
    
   SELECT_ACTION(action)
   {
   case INIT:
      channel->Gk = 0;
      break;
 
   case PROCESS:
      MSGLOOP(channel,msg)
         {
         case VOLTAGE:           /* get presynaptic membrane potential */
            V = MSGVALUE(msg,0);
	    break;

	 case CAF:               /* get presynaptic ICaF   */ 
            ICaF= MSGVALUE(msg,0);
            break;
	 
         case CAS:               /* get presynaptic ICaS   */
	    ICaS= MSGVALUE(msg, 0);
	    break;

         case POSTVOLTAGE:       /* get postsynaptic membrane potential */
            PV = MSGVALUE(msg,0);
            break;

         case EK:                /* reversal potential Ek */
            channel->Ek = MSGVALUE(msg,0);
            break;
	 }  

      /* calculate state variables and conductance */ 
      dt = Clockrate(channel);

      /* calculate Ainf, a voltage dependent threshold */  
      /* Ainf=A1+A2/(1+exp(A3*(V+A4))); units=Amperes */
      Ainf=channel->A1+channel->A2/(1+exp(channel->A3*(V+channel->A4)));

       /* exponential euler; A5 = tau, units =sec */
      channel->A=(channel->A)*exp(-dt/channel->A5)+Ainf*(1-exp(-dt/channel->A5));

      /* calculte the effective Ca influx
       * I_Ca is the total Ca minus the threshold
       * units=Amperes*/
      I_Ca=ICaF+ICaS-(channel->A);  
      if (I_Ca < 0) I_Ca=0.0;

      /* calculate P; d[P]/dt=ICa-B[P]; exponential euler */
      channel->P=(channel->P)*exp(-(channel->B)*dt)+ \
      I_Ca/(channel->B)*(1-exp(-(channel->B)*dt));

      /* raise P to a power; P^POWER/(P^POWER+C) is a function
       * that rises exponetially, but is saturating */
      tmp=pow(channel->P, channel->POWER);
      channel->R =tmp/(tmp+channel->C);   
      g = channel->Gbar * channel->R; 

      /* calculate the transmembrane current using the postsynaptic Vm */
      channel->Gk = g;
      channel->Ik = (channel->Ek - PV) * g;
      break;      /* end of case PROCESS */

   case RESET:
      channel->Gk  = 0;
      channel->Ik  = 0;
      channel->A   = 0;
      channel->P   = 0;
      channel->R   = 0;
      break;

   case CHECK:
      volt_msg_in = 0;
      CAF_msg_in = 0;
      CAS_msg_in = 0;
      pvolt_msg_in = 0;

      MSGLOOP(channel,msg)
         {
	 case VOLTAGE: 
	    volt_msg_in = 1;
	    break;
          
	 case CAF:            
            CAF_msg_in = 1;
            break;
	 
         case CAS:            
	    CAS_msg_in = 1;
	    break;

         case POSTVOLTAGE:
            pvolt_msg_in = 1;
            break;

	 }  

         if (volt_msg_in == 0)
	    ErrorMessage("SynG","No membrane potential.", channel);
	   
         if (CAF_msg_in == 0)
	    ErrorMessage("SynG","No ICaF.", channel);

         if (CAS_msg_in == 0)
	    ErrorMessage("SynG","No ICaS.", channel);

         if (pvolt_msg_in == 0)
            ErrorMessage("SynG","No postsynaptic memb. potential.", channel);
        
         if ((channel->Gbar) < 0)
            ErrorMessage("SynG","Gbar must be >= 0.", channel);
        

      break; /* CHECK */  

case SAVE2:
      savedata[0] = (double)(channel->A);
      savedata[1] = (double)(channel->P);
      n=2;
      fwrite(&n,sizeof(int),1,(FILE*)action->data);
      fwrite(savedata,sizeof(double),2,(FILE*)action->data);
      break; /* SAVE2 */

case RESTORE2:
	fread(&n,sizeof(int),1,(FILE*)action->data);
	if (n != 2) {
	    ErrorMessage("SynG_ron","Invalid savedata length",channel);
	    return(n);
	}
	fread(savedata,sizeof(double),2,(FILE*)action->data);
	channel->A = savedata[0];
	channel->P = savedata[1];
	break;  /* RESTORE2 */

default:
	InvalidAction("SynG_ron", channel ,action);
	break;

 
   }
      
      return (0);
}