Subversion Repositories shark

Rev

Rev 2 | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*****************************************************************************
* Filename:       DAC.C                                                      *      *
* Author:         Marco Ziglioli (Doctor Stein)                              *        *
* Date:           06/06/2001                                                 *          *
* Description:    Digital 2 analog conversion functions                      *
*----------------------------------------------------------------------------*
* Notes: Only module one of Analog Output Timing Module are programmed yet   *
*        No waveform staging and local buffer mode with pauses are           *
*        implemented yet                                                     *
*        Please refer to STC-DAC Technical Reference Manual and PCI E-Series *
*        Programmer Level Manual for further information                     *
*****************************************************************************/


/* This file is part of the S.Ha.R.K. Project - http://shark.sssup.it
 *
 * Copyright (C) 2001 Marco Ziglioli
 *
 * This program 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.
 *
 * This program 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 this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */




#include <drivers/pci6025e/dac.h>

//Software copies of useful registers
static WORD ao_command_1, ao_command_2, ao_personal, ao_mode_1, ao_mode_2,
            ao_mode_3, ao_output_control, ao_start_select, ao_trigger_select;

static BYTE DAC_Initialized = 0;

/*****************************************************************************
*                 void DAC_reset(void)                                       *
*----------------------------------------------------------------------------*
* Reset both two DACs and the timing system                                  *
*****************************************************************************/

void  DAC_reset(void)
{
   set(joint_reset, 5);    //Enable AOTM configuration
   DAQ_STC_Windowed_Mode_Write(JOINT_RESET, joint_reset);
   clr(joint_reset, 5);

   //Disarm Timing module
   set(ao_command_1, 13);
   DAQ_STC_Windowed_Mode_Write(AO_COMMAND_1, ao_command_1);
   clr(ao_command_1, 13);

   //Clear all registers
   DAQ_STC_Windowed_Mode_Write(AO_PERSONAL, 0x0000);
   DAQ_STC_Windowed_Mode_Write(AO_COMMAND_1, 0x0000);
   DAQ_STC_Windowed_Mode_Write(AO_COMMAND_2, 0x0000);
   DAQ_STC_Windowed_Mode_Write(AO_MODE_1, 0x0000);
   DAQ_STC_Windowed_Mode_Write(AO_MODE_2, 0x0000);
   DAQ_STC_Windowed_Mode_Write(AO_MODE_3, 0x0000);
   DAQ_STC_Windowed_Mode_Write(AO_OUTPUT_CONTROL, 0x0000);
   DAQ_STC_Windowed_Mode_Write(AO_START_SELECT, 0x0000);
   DAQ_STC_Windowed_Mode_Write(AO_TRIGGER_SELECT, 0x0000);

   //Clear software copies
   ao_personal = ao_command_1 = ao_command_2 = ao_mode_1 = ao_mode_2 =
   ao_mode_3 = ao_output_control = ao_start_select = ao_trigger_select = 0;

   //Disable related interrupt flags
   interrupt_b_enable &= 0xFE80;
   DAQ_STC_Windowed_Mode_Write(INTERRUPT_B_ENABLE, interrupt_b_enable);

   //Enable related interrupt request flags
   interrupt_b_ack |= 0x3F98;
   DAQ_STC_Windowed_Mode_Write(INTERRUPT_B_ACK, interrupt_b_ack);

   set(ao_personal, 4);
   DAQ_STC_Windowed_Mode_Write(AO_PERSONAL, ao_personal);

   set(joint_reset, 9);    //Disable AOTM configuration
   DAQ_STC_Windowed_Mode_Write(JOINT_RESET, joint_reset);
   clr(joint_reset, 9);
}

/*****************************************************************************
*                void DAC_boardInit(BYTE clock, WORD personal)               *
*----------------------------------------------------------------------------*
* Use this function to program software selectable options in the primary    *
* module. The options include source, polarity and pulsewidth of the most    *
* common used signals. This function must be executed after every invoke of  *
* DAC_reset and before executing any output operation.                       *
* Parameters:                                                                *
*        clock                                                               *
*           -bit 0:  if sets to 1 AO_IN_TIMEBASE is IN_TIMEBASE divided by 2 *
*           -bit 1:  if sets to 1 AO_OUT_TIMEBASE is IN_TIMEBASE divideb by 2*
*           -bit 2..9 NOT USED
*        personal                                                            *
*           -bit 0...1: update output signal select 0(high Z); 1(GND);       *
*                       2(enable active low); 3(enable active high)          *
*           -bit 2...4: not used (let this bit to 0)                         *
*           -bit 5:  update pulse width 0(3-3.5 AO_OUT_TIMEBASE period)      *
*                                       1(1-1.5 AO_OUT_TIMEBASE period)      *
*           -bit 6:  update pulse timabase 0(selected by AO_UPDATE pulse_Wi) *
*                                          1(selected by AO_UPDATE original) *
*           -bit 7:  not used                                                *
*           -bit 8:  DMA PIO control 0(FIFO Data interface mode)             *
*                                    1(unbuffered data interface mode)       *
*           -bit 9:  not used                                                *
*           -bit 10: enable TMRDACWR which control Analog Output FIFO        *
*           -bit 11: FIFO flags polarity 0(active low)                       *
*           -bit 12: TMRDACWR pulse width 0(3 AO_OUT_TIMEBASE period)        *
*                                         1(2 AO_OUT_TIMEBASE period)        *
*           -bit 13: not used                                                *
*           -bit 14: number of DAC packages 0(dual-DAC mode)                 *
*                                           1(single-DAC mode)               *
*           -bit 15: NOT USED                                                *
*****************************************************************************/

void  DAC_boardInit(BYTE clock, WORD personal)
{
   set(joint_reset, 5);
   DAQ_STC_Windowed_Mode_Write(JOINT_RESET, joint_reset);
   clr(joint_reset, 5);

   //Setup AOTM clock module
   clock_and_fout = (clock_and_fout & 0xFFFC) | (clock & 0x03);
   DAQ_STC_Windowed_Mode_Write(CLOCK_AND_FOUT, clock_and_fout);

   //Setup Update signal
   ao_output_control = (ao_output_control & 0xFFFC) | (personal & 0x0003);
   DAQ_STC_Windowed_Mode_Write(AO_OUTPUT_CONTROL, ao_output_control);

   ao_personal = (ao_personal & 0x229F) | (personal & 0xDD6F);
   DAQ_STC_Windowed_Mode_Write(AO_PERSONAL, ao_personal);

   clr(ao_start_select, 12);
   DAQ_STC_Windowed_Mode_Write(AO_START_SELECT, ao_start_select);

   set(joint_reset, 9);
   DAQ_STC_Windowed_Mode_Write(JOINT_RESET, joint_reset);
   clr(joint_reset, 9);
}

/*****************************************************************************
*                   void DAC_trigger(WORD trigger)                           *
*----------------------------------------------------------------------------*
* With this function you can select which is the signal which trigger the    *
* analog output operation                                                    *
* parameter:                                                                 *
*     bit 0...4:  start1 source select 0      -> bitfiled AO_START_1 pulse   *
*                                      1..10  -> PFI<0..9>                   *
*                                      11..17 -> RTSI<0..6>                  *
*     bit 5: edge detection 0(disable) 1(enable)                             *
*     bit 6: synchronization 0(disable) 1(enable)                            *
*     bit 13: start1 polarity 0(active hi) 1(active lo)                      *
*     bit 14: synchronized with BC source 0(disable) 1(enable)               *
*     bit 15: set this bit for single operation or clear for continuos mode  *
*     bit 7..12: NOT USED                                                    *
*****************************************************************************/

void  DAC_trigger(WORD trigger)
{
   set(joint_reset, 5);
   DAQ_STC_Windowed_Mode_Write(JOINT_RESET, joint_reset);
   clr(joint_reset, 5);

   //Select continuos or one shoot mode
   if(trigger&0x8000)   set(ao_mode_1, 0);
   else                 clr(ao_mode_1, 0);
   DAQ_STC_Windowed_Mode_Write(AO_MODE_1, ao_mode_1);

   //select source
   if( (trigger&0x001F) == 0 )
      ao_trigger_select = (ao_trigger_select & 0xDF80) | 0x0060;
   else
      ao_trigger_select = (ao_trigger_select & 0xDF80) | (trigger & 0x007F);

   //triger signal synchronization
   ao_trigger_select = (ao_trigger_select & 0x9FFF) | (trigger & 0x6000);
   DAQ_STC_Windowed_Mode_Write(AO_TRIGGER_SELECT, ao_trigger_select);

   clr(ao_mode_3, 11);
   DAQ_STC_Windowed_Mode_Write(AO_MODE_3, ao_mode_3);

   set(joint_reset, 9);
   DAQ_STC_Windowed_Mode_Write(JOINT_RESET, joint_reset);
   clr(joint_reset, 9);
}

/*****************************************************************************
*             void DAC_numSetup(DWORD n_updates, DWORD n_iter)               *
*----------------------------------------------------------------------------*
* Use this function to set up number of updates that must be performed and   *
* the number of buffer iterations. No Local buffered mode with pauses and    *
* waveform staging are implemented yet. Please refer to DAQ STC Technical    *
* Reference Manual for this features                                         *
* Parameters:                                                                *
*     n_updates:  number of updates in each buffer operation                 *
*     n_iter:     number of iterations that must be performed                *
*****************************************************************************/

void  DAC_numSetup(DWORD n_updates, DWORD n_iter)
{
   set(joint_reset, 5);
   DAQ_STC_Windowed_Mode_Write(JOINT_RESET, joint_reset);
   clr(joint_reset, 5);

   set(ao_mode_1, 1);
   DAQ_STC_Windowed_Mode_Write(AO_MODE_1, ao_mode_1);

   clr(ao_mode_2, 2);
   DAQ_STC_Windowed_Mode_Write(AO_MODE_2, ao_mode_2);

   //Load numbre of updates for each iteration
   DAQ_STC_Windowed_Mode_Write(AO_BC_LOAD_A_LO, (WORD)n_updates);
   DAQ_STC_Windowed_Mode_Write(AO_BC_LOAD_A_HI, (WORD)(n_updates>>16));

   set(ao_command_1, 5);
   DAQ_STC_Windowed_Mode_Write(AO_COMMAND_1, ao_command_1);
   clr(ao_command_1, 5);

   clr(ao_mode_2, 11);
   DAQ_STC_Windowed_Mode_Write(AO_MODE_2, ao_mode_2);

   //load number of iteration
   DAQ_STC_Windowed_Mode_Write(AO_UC_LOAD_A_LO, (WORD)n_iter);
   DAQ_STC_Windowed_Mode_Write(AO_UC_LOAD_A_HI, (WORD)(n_iter>>16));

   set(ao_command_1, 7);
   DAQ_STC_Windowed_Mode_Write(AO_COMMAND_1, ao_command_1);
   clr(ao_command_1, 7);

   set(joint_reset, 9);
   DAQ_STC_Windowed_Mode_Write(JOINT_RESET, joint_reset);
   clr(joint_reset, 9);
}

/*****************************************************************************
*               void DAC_update(BYTE source, BYTE ui)                        *
*----------------------------------------------------------------------------*
* Use this function to select the update event. No waveform staging or local *
* buffer mode with pauses are implemented yet.                               *
* Parameters:                                                                *
*        source:  bit 0..4: update signal source                             *
*                 bit 5:    polarity of update signal                        *
*                 bit 6..7  NOT USED                                         *
*        ui    :  bit 0..4: UI source select                                 *
*                 bit 5:    polarity of UI signal                            *
*                 bit 6..7: NOT USED                                         *
*****************************************************************************/

void  DAC_update(BYTE source, BYTE ui)
{
   set(joint_reset, 5);
   DAQ_STC_Windowed_Mode_Write(JOINT_RESET, joint_reset);
   clr(joint_reset, 5);

   if( (source&0x1F)==0 ){
      clr(ao_command_2, 11);

      ao_mode_1 &= 0x07FF;
      clr(ao_mode_1, 4);
      if( (ui&0x1F)==0 ){
         ao_mode_1 &= 0xF83F;
         clr(ao_mode_1, 3);
      } else {
         if( (ui&0x1F)==20 ){
            ao_mode_1 = (ao_mode_1 & 0xF83F) | 0x0500;
            clr(ao_mode_1, 3);
         } else {
            ao_mode_1 = (ao_mode_1 & 0xF83F) | (((WORD)ui & 0x001F)<<6);
            if(ui & 0x20) set(ao_mode_1, 3);
            else          clr(ao_mode_1, 3);
         }
      }
   } else {
      if( (source&0x1F)==19 ){
         set(ao_command_2, 11);
         ao_mode_1 = (ao_mode_1 & 0x07FF) | 0x9800;
         clr(ao_mode_1, 4);
      } else {
         set(ao_command_2, 11);
         ao_mode_1 = (ao_mode_1 & 0x07FF) | (((WORD)source&0x001F)<<11);
         if(source&0x20)   set(ao_mode_1, 4);
         else              clr(ao_mode_1, 4);
      }
   }

   DAQ_STC_Windowed_Mode_Write(AO_COMMAND_2, ao_command_2);
   DAQ_STC_Windowed_Mode_Write(AO_MODE_1, ao_mode_1);

   set(joint_reset, 9);
   DAQ_STC_Windowed_Mode_Write(JOINT_RESET, joint_reset);
   clr(joint_reset, 9);
}

/*****************************************************************************
*              void DAC_channel(BYTE num)                                    *
*----------------------------------------------------------------------------*
* Use this function to select hom many analog input channel must be updated  *
* every UPDATE event                                                         *
* Parameters:  multi:   if it's different from 0 multiple channel feature are*
*                       enabled                                              *
*              num:     number of channels that must be updated              *
* Note: With PCI6025E only two channel (DAC0 DAC1) are available             *
*****************************************************************************/

void DAC_channel(BYTE multi, BYTE num)
{
   set(joint_reset, 5);
   DAQ_STC_Windowed_Mode_Write(JOINT_RESET, joint_reset);
   clr(joint_reset, 5);

   if(multi)   set(ao_mode_1, 5);
   else        clr(ao_mode_1, 5);

   ao_output_control = (ao_output_control & 0xFC3F) | (((WORD)num&0x0F)<<6);

   DAQ_STC_Windowed_Mode_Write(AO_MODE_1, ao_mode_1);
   DAQ_STC_Windowed_Mode_Write(AO_OUTPUT_CONTROL, ao_output_control);

   set(joint_reset, 9);
   DAQ_STC_Windowed_Mode_Write(JOINT_RESET, joint_reset);
   clr(joint_reset, 9);
}

/*****************************************************************************
*              void DAC_LDACSourceUpdate(BYTE pref)                          *
*----------------------------------------------------------------------------*
* Use this function to set source and update mode for LDAC<0..1> signals     *
* Parameter:   pref: bit 0: LDAC0 source; if 0 LDAC will output on UPDATE    *
*                                         else will output on UPDATE2        *
*                    bit 1: DAC0 update mode; 0 DAC will update immediately  *
*                                             1 timed update mode            *
*                    bit 2: same of bit 0 but for LDAC1                      *
*                    bit 3: same of bit 1 but for DAC1                       *
*                    bit 4..7 NOT USED                                       *
*****************************************************************************/

void  DAC_LDACSourceUpdate(BYTE pref)
{
   set(joint_reset, 5);
   DAQ_STC_Windowed_Mode_Write(JOINT_RESET, joint_reset);
   clr(joint_reset, 5);

   ao_command_1 = (ao_command_1 & 0xFFE1) | (((WORD)pref&0x001E)<<1);
   DAQ_STC_Windowed_Mode_Write(AO_COMMAND_1, ao_command_1);

   set(joint_reset, 9);
   DAQ_STC_Windowed_Mode_Write(JOINT_RESET, joint_reset);
   clr(joint_reset, 9);
}

/*****************************************************************************
*              void DAC_stopError(BYTE error)                                *
*----------------------------------------------------------------------------*
* Use this function to set up the error conditions upon which the Timing     *
* Module of Analog Output will stop                                          *
* Parameter:   error:   bit 0 Stop on BC_TC error                            *
*                       bit 1 Stop on BC_TC Trigger error                    *
*                       bit 2 Stop on Overrun error                          *
*                       bit 3..7 NOT USED                                    *
* Set this bits means that Timing Module will stop. Clear this bits means    *
* Timing Module ignores error.                                               *
*****************************************************************************/

void  DAC_stopError(BYTE error)
{
   set(joint_reset, 5);
   DAQ_STC_Windowed_Mode_Write(JOINT_RESET, joint_reset);
   clr(joint_reset, 5);

   ao_mode_3 = (ao_mode_3 & 0xFFC7) | (((WORD)error & 0x0038)<<3);
   DAQ_STC_Windowed_Mode_Write(AO_MODE_3, ao_mode_3);

   set(joint_reset, 9);
   DAQ_STC_Windowed_Mode_Write(JOINT_RESET, joint_reset);
   clr(joint_reset, 9);
}

/*****************************************************************************
*              void DAC_FIFOFlags(BYTE flags)                                *
*----------------------------------------------------------------------------*
* Use this function to select the data FIFO condition on which Interrupt or  *
* DMA request are asserted                                                   *
* Parameter:   flags:   bit 0..1 0 generate on empty FIFO                    *
*                                1 generate on less than half full FIFO      *
*                                2 generate on less than full FIFO           *
*                                3 generate on less than half full FIFO but  *
*                                  keep asserted until FIFO is full          *
*                       bit 2..7 NOT USED                                    *
*****************************************************************************/

void  DAC_FIFOFlags(BYTE flags)
{
   set(joint_reset, 5);
   DAQ_STC_Windowed_Mode_Write(JOINT_RESET, joint_reset);
   clr(joint_reset, 5);

   ao_mode_2 = (ao_mode_2 & 0x1FFF) | (((WORD)flags & 0x0003) << 14);
   DAQ_STC_Windowed_Mode_Write(AO_MODE_2, ao_mode_2);

   set(joint_reset, 9);
   DAQ_STC_Windowed_Mode_Write(JOINT_RESET, joint_reset);
   clr(joint_reset, 9);
}

/*****************************************************************************
*              void DAC_enableInterrupts(WORD itr)                           *
*----------------------------------------------------------------------------*
* With this function it's possible to enable event on which Timing Module    *
* can generate Interrupt Request                                             *
* Parameter:   int:  bit 0: BC_TC Interrupt                                  *
*                    bit 1: START1 Interrupt                                 *
*                    bit 2: UPDATE Interrupt                                 *
*                    bit 3: START Interrupt                                  *
*                    bit 4: NOT USED                                         *
*                    bit 5: Error Interrupt                                  *
*                    bit 6: UC_TC Interrupt                                  *
*                    bit 7: NOT USED                                         *
*                    bit 8: FIFO Interrupt                                   *
*                    bit 9..15 NOT USED                                      *
* Set bits to enable interrupt generation or clear to avoid interrupt        *
* generation                                                                 *
*****************************************************************************/

void  DAC_enableInterrupts(WORD itr)
{
   interrupt_b_enable = (interrupt_b_enable & 0xFE90) | (itr & 0x016F);

   DAQ_STC_Windowed_Mode_Write(INTERRUPT_B_ENABLE, interrupt_b_enable);
}

/*****************************************************************************
*                       void DAC_arm(void)                                   *
*----------------------------------------------------------------------------*
* With this function Analog Output counters will be armed and the first value*
* is preloaded into DACs                                                     *
*****************************************************************************/

void  DAC_arm(void)
{
   set(ao_mode_3, 2);
   DAQ_STC_Windowed_Mode_Write(AO_MODE_3, ao_mode_3);

   clr(ao_mode_3, 2);
   DAQ_STC_Windowed_Mode_Write(AO_MODE_3, ao_mode_3);

   while( (DAQ_STC_Windowed_Mode_Read(JOINT_STATUS_2) & 0x0020) != 0 );

   ao_command_1 |= 0x0540;
   DAQ_STC_Windowed_Mode_Write(AO_COMMAND_1, ao_command_1);
}

/*****************************************************************************
*                 void DAC_startOperation(void)                              *
*----------------------------------------------------------------------------*
* If software trigger was previously selected this function initiate an      *
* analog output operation. If trigger wasn't software driven this function   *
* has no effects                                                             *
*****************************************************************************/

void  DAC_startOperation(void)
{
   set(ao_command_2, 0);
   DAQ_STC_Windowed_Mode_Write(AO_COMMAND_2, ao_command_2);
   clr(ao_command_2, 0);
}

/*****************************************************************************
*                         void DAC_Init(void)                                *
*----------------------------------------------------------------------------*
* This function must be called previously any DAC settings or DAC operations *
* It preapers the envirorment to work with DACs in right way and calls the   *
* reset function (DAC_reset)                                                 *
*****************************************************************************/

void  DAC_Init(void)
{
   DAC_Initialized = 1;
   /*DAC0: Bipolar mode, Internal referenced, ReGlitch disabled*/
   Immediate_Writew(DAC_CONFIG, 0x0001);

   /*DAC1: Bipolar mode, Internal referenced, ReGlitch disabled*/
   Immediate_Writew(DAC_CONFIG, 0x0101);

   DAC_reset();
}

/*****************************************************************************
*                 void DAC_output(BYTE DAC_ID, WORD value)                   *
*----------------------------------------------------------------------------*
* Write "value" in "DAC_ID" register and put out the releted analog value    *
* Parameters:  DAC_ID:  This can be DAC0 or DAC1                             *
*              value:   first 12-bit output value                            *
*                       last 4 bits NOT USED                                 *
*****************************************************************************/

void  DAC_output(BYTE DAC_ID, WORD value)
{
   if(DAC_Initialized){
      if(DAC_ID)  Immediate_Writew(DAC1_DATA, (value & 0x0FFF));
      else        Immediate_Writew(DAC0_DATA, (value & 0x0FFF));
   }
}
/*End of file:    DAC.C*/