/*
 *  Copyright (c) 2003 by Matt Cross <matt@dragonflyhollow.org>
 *
 *  This file is part of the firemarshalbill package.
 *
 *  Firemarshalbill is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  Firemarshalbill is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with Firemarshalbill; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

/*
 * API for configuring & using a TPU channel in PTA mode.
 */



#include	<cfxbios.h>		// Persistor BIOS and I/O Definitions
#include	<cfxpico.h>		// Persistor PicoDOS Definitions
#include <stdio.h>
#include "pta.h"

/* Constants used locally */
#define PTA_HSR_NONE		0x0
#define PTA_HSR_INIT		0x3

void pta_stop(ushort chan)
{

  /* Disable interrupts from this channel. */
  TPU.CIER &= ~(1 << chan);

  /* Clear outstandinf interrupt (if any). */
  TPU.CISR &= ~(1 << chan);
  
  /* Disable the channel by clearing the two channel priority bits */

  if (chan < 8)
    {
      TPU.CPR1 &= (short int) ~(0x3 << (chan*2));
    }
  else
    {
      TPU.CPR0 &= (short int) ~(0x3 << ((chan - 8) * 2));
    }
    
    return;
}


int pta_start(ushort chan, ushort count, IEVCWrapper *isr,ushort MODE)
{
  
  int vector;
  ushort chan_cntrl;
  /* Disable interrupts from this channel. */
  TPU.CIER &= ~(1 << chan);

  /* Clear outstandinf interrupt (if any). */
  TPU.CISR &= ~(1 << chan);

  /* Set interrupt level for CPU service of TPU interrupts */
  TPU.TICR |= 0x0600;

 // printf("TICR = %x \n",TPU.TICR);

  /* Set-up the ISR. */
  vector = (TPU.TICR & 0x00F0) | chan;
  IEVInsertCFunct(isr,vector);


  /* step one: disable the channel by clearing the two channel priority bits */
  if (chan < 8)
    {
      TPU.CPR1 &= (short int) ~(0x3 << (chan*2));
    }
  else
    {
      TPU.CPR0 &= (short int) ~(0x3 << ((chan - 8) * 2));
    }

  /* Enale interrupts from this channel. */

   TPU.CIER |= (1 << chan);

  /* step two: select the PTA function on the channels by writing the
     PTA function number to the function select bits. */
  if (chan < 4)
    {
      TPU.CFSR3 &= (short int) ~(0xF << (chan * 4));
      TPU.CFSR3 |= (short int) (PTA << (chan * 4));
    }
  else if (chan < 8)
    {
      TPU.CFSR2 &= (short int) ~(0xF << ((chan - 4) * 4));
      TPU.CFSR2 |= (short int) (PTA << ((chan - 4) * 4));
    }
  else if (chan < 12)
    {
      TPU.CFSR1 &= (short int) ~(0xF << ((chan - 8) * 4));
      TPU.CFSR1 |= (short int) (PTA << ((chan - 8) * 4));
    }
  else
    {
      TPU.CFSR0 &= (short int) ~(0xF << ((chan - 12) * 4));
      TPU.CFSR0 |= (short int) (PTA << ((chan - 12) * 4));
    }

  /* step three: initialize parameter ram. */
  TPRAM[chan][1] = ((unsigned) count & 0xff) << 8;
  TPRAM[chan][2] = 0;
  TPRAM[chan][3] = 0;
  TPRAM[chan][4] = 0;
  TPRAM[chan][5] = 0;
  
  
  /* step four: configure CHANNEL_CONTROL HSQ bits. */
  
  chan_cntrl = (0x00f0 & MODE) | 0x0003;
  
  if(MODE & 0x0002)  //Period Measurement
  {
  	if(MODE & 0x0001)  // Start on falling edge
  		chan_cntrl |= 0x0008;
  	else			   // Start on rising edge
  		chan_cntrl |= 0x0004;
  }
  else				// Pulse Width Measurement
   chan_cntrl |= 0x000c;
  
  printf("MODE = %x  chan_cntrl = %x\n",MODE,chan_cntrl);
  
  TPRAM[chan][0] = chan_cntrl;
  
  if (chan < 8)
    {
      TPU.HSQR1 &= (short int) ~(0x3 << (chan*2));
	  TPU.HSQR1 |= (short int) ((MODE & 0x0003) << (chan*2));
    }
  else
    {
      TPU.HSQR0 &= (short int) ~(0x3 << ((chan - 8) * 2));
	  TPU.HSQR0 |= (short int) ((MODE & 0x0003) << ((chan - 8) * 2));
    }

  /* step five: Issue an HSR to the channel to initialize. */
  if (chan < 8)
    {
      TPU.HSRR1 &= (short int) ~(0x3 << (chan*2));
      TPU.HSRR1 |= (short int) (PTA_HSR_INIT << (chan*2));
    }
  else
    {
      TPU.HSRR0 &= (short int) ~(0x3 << ((chan - 8) * 2));
      TPU.HSRR0 |= (short int) (PTA_HSR_INIT << ((chan - 8) * 2));
    }

  /* step six: Enable servicing by assigning the H, M, or L priority
     to the channel priority bits */
  if (chan < 8)
    {
      TPU.CPR1 |= (short int) (0x3 << (chan*2));
    }
  else
    {
      TPU.CPR0 |= (short int) (0x3 << ((chan - 8) * 2));
    }


  if (chan < 8)
    {
      while((short int)0x0000 !=
	    (short int)(TPU.HSRR1 & (short int)(0x3 << (chan*2))))
	  {
	  /* pause here and do nothing until after the tpu function is
             serviced. */
	  }
    }
  else
    {
      while((short int)0x0000 !=
	    (short int)(TPU.HSRR0 & (short int)(0x3 << ((chan - 8) * 2))))
	  {
	  /* pause here and do nothing until after the tpu function is
             serviced. */
	  }
    }

return 1;

}