vast adc24.txt

Warning: if you clip this code into your program, look out for possible html code slipping in.

REM   VAST ADC24 Interface for the SBC2000-074
REM
REM   This file contains the definitions required to interface a VADC24 board
REM   via the VAST bus to an SBC2000-074. These routines are for VSTB Rev 4
REM   boards and later revisions only.
REM
REM   Author: Steven R. Wheeler
REM
REM   Copyright 1999-2000 Vesta Technology, Inc.
REM   All rights reserved.
REM
REM   Revision history:
REM     19 May 1999 - First version. More or less a translation of the C code
REM                   which implements the VMTB extension.
REM     30 Jun 1999 - Fixed minor problem in OTHER_SPI_XFER (last 2 bits of a
REM                   reception could be wrong if the final MSB was '1'.
REM      5 Aug 1999 - Got working (finally!). Final problem was an early exit
REM                   from Calibrate_VADC24() ... we were starting calibrations
REM                   before the previous calibration had ended. Added more
REM                   comments.
REM      7 Apr 2000 - Made the routines which perform VAST transfers VITAL, so
REM                   event handlers won't interfere with them.


REM   The VADC24 requires a mode 3 clock (clock active phase = 0).

REM   It makes things easier if we have a few global variables to hold some
REM   persistent values. Most of these correspond to some of the registers
REM   in the AD7714 converter chip on the VADC24.

GLOBAL Differential AS BIT
GLOBAL ADC24_Mode   AS BYTE
GLOBAL ADC24_Filter AS INTEGER


REM   Declare some generally-useful constants for later use. Note that the
REM   time limit is fairly large. Worst case for completion of an operation
REM   is calibration, which takes 9x the conversion period to complete. If
REM   background calibration is active, then each conversion takes 6x the
REM   conversion period to become complete.

CONSTANT Channels_per_Board AS INTEGER = 6
CONSTANT TIME_LIMIT AS INTEGER = 5000


REM   Declare the various registers with which we need to communicate. The
REM   registers are actually numbered 0-7, but here they've been preshifted
REM   to the bit positions where the AD7714 on the VADC24 will expect them.

CONSTANT R_Comm     AS BYTE = 0x00
CONSTANT R_Mode     AS BYTE = 0x10
CONSTANT R_FilterHi AS BYTE = 0x20
CONSTANT R_FilterLo AS BYTE = 0x30
CONSTANT R_Test     AS BYTE = 0x40
CONSTANT R_Data     AS BYTE = 0x50
CONSTANT R_Zero_Cal AS BYTE = 0x60
CONSTANT R_Full_Cal AS BYTE = 0x70


REM   Declare the various operating modes available. These are shifted
REM   into the position the AD7714 expects them in the mode register. The
REM   first set of values are the available calibration types.

CONSTANT M_Normal         AS BYTE = 0x00
CONSTANT M_Cal_Self       AS BYTE = 0x20
CONSTANT M_Cal_Zero       AS BYTE = 0x40
CONSTANT M_Cal_Full       AS BYTE = 0x60
CONSTANT M_Cal_Offset     AS BYTE = 0x80
CONSTANT M_Cal_Background AS BYTE = 0xA0
CONSTANT M_Cal_Zero_Self  AS BYTE = 0xC0
CONSTANT M_Cal_Complete   AS BYTE = 0xE0
CONSTANT M_Burnout        AS BYTE = 0x02
CONSTANT M_FSync          AS BYTE = 0x01


REM   Declare equates for the filter register contents

CONSTANT F_Bipolar  AS INTEGER = 0x0000
CONSTANT F_Unipolar AS INTEGER = 0x8000
CONSTANT F_16Bits   AS INTEGER = 0x0000
CONSTANT F_24Bits   AS INTEGER = 0x4000
CONSTANT F_Filter   AS INTEGER = 0x0FFF


REM   Declare the various channel codes. The first six values are for
REM   single-ended conversions. The next six are for differential pairs.
REM   Note that the differential pairs convert the same value for each
REM   pair. We test in code which channel is supposed to be positive
REM   with respect to the other and change sign as required.

DIM Channel_Codes[12] AS BYTE CONSTANT = [
	0, 1, 2, 3, 6, 7,
	4, 4, 5, 5, 6, 6]


REM   Given a raw channel number and a single-ended/differential indicator,
REM   return the appropriate channel value to be sent to the VADC24.

FUNCTION   Channel_Code(channel AS BYTE) AS INTEGER
	channel = (channel \ Channels_per_Board) - (Differential * Channels_per_Board)
	Channel_Code = Channel_Codes[channel]
END


REM   Given a raw gain value, return the gain selection which best matches
REM   the desired gain. These gain selections actually range from 0-7, but
REM   here they've been shifted into the position they occupy in the mode
REM   register.

FUNCTION   Gain_Value(gain AS INTEGER) AS INTEGER
	Gain_Value = 28
	IF gain < 128
		Gain_Value = 24
	ENDIF
	IF gain < 64
		Gain_Value = 20
	ENDIF
	IF gain < 32
		Gain_Value = 16
	ENDIF
	IF gain < 16
		Gain_Value = 12
	ENDIF
	IF gain < 8
		Gain_Value = 8
	ENDIF
	IF gain < 4
		Gain_Value = 4
	ENDIF
	IF gain < 2
		Gain_Value = 0
	ENDIF
END


REM   Write one byte to the VADC24. All writes go through this routine.

VITAL SUBROUTINE Write_VADC24(board AS INTEGER, value AS BYTE)
	VAST_OPEN(board)
	value = VAST_SPI_XFER(8, value)
	VAST_CLOSE(15)
END


REM   Read a byte from the VADC24. This is used for obtaining the contents of
REM   all AD7714 registers except the data register.

VITAL FUNCTION   Read_VADC24(board AS INTEGER, reg AS BYTE, channel AS BYTE) AS INTEGER
	Write_VADC24(board, reg OR 8 OR Channel_Code(channel))
	VAST_OPEN(board)
	Read_VADC24 = VAST_SPI_XFER(8, 0)
	VAST_CLOSE(15)
END


REM   If for some reason communications are lost with the VADC24, and the
REM   state of the communications interface is unknown (such as a board
REM   reset occurring during a transfer), we can force communications to a
REM   known state by sending 32 or more consecutive '1' bits to the device.

VITAL SUBROUTINE Reset_VADC24(board AS INTEGER)
LOCAL temp AS INTEGER
	VAST_OPEN(board)
	temp = VAST_SPI_XFER(16, -1)
	temp = VAST_SPI_XFER(16, -1)
	temp = VAST_SPI_XFER(16, -1)
	VAST_CLOSE(15)
END


REM   Overall initialization for the VADC24.
REM   Opmode is the operating mode, which can be any of the values in the list
REM   M_Normal to M_Cal_Full.
REM   Gain is any integer power of 2 from 1 to 128.
REM   The value of frequency can range from 4.8 Hz to 1010.52 (expressed in Hertz).
REM   It controls the update rate of the output.
REM   Size specifies the number of bits in the result. Legal values are 16 and 24.
REM   Polarity specifies bipolar (if 0) or unipolar (if non-0) conversions.
REM   Type specifies single-ended (if 0) or differential (if non-zero) conversions.
REM
REM   We leave burnout current turned off, and we leave the filter enabled.

SUBROUTINE Init_VADC24(board AS byte, opmode AS BYTE, gain AS BYTE, freq AS FLOAT, size AS BYTE, polarity AS BYTE, type AS BYTE)

	Differential = type

	ADC24_Mode = opmode OR Gain_Value(gain)

	REM   The filter value is related to frequency. It can have values in
	REM   the range from 19 through 4000.

	ADC24_Filter = (19200 / freq) + 0.5
	ADC24_Filter = MIN(ADC24_Filter, 4000)
	ADC24_Filter = MAX(ADC24_Filter,   19)

	REM   Set the boost bit if gain is too high to do without
	IF gain > 4
		ADC24_Filter = ADC24_Filter OR 0x2000
	ENDIF
	IF polarity
		ADC24_Filter = ADC24_Filter OR 0x8000
	ENDIF
	IF size > 16
		ADC24_Filter = ADC24_Filter OR 0x4000
	ENDIF

	Reset_VADC24(board)

	REM   Set up the conversion rate and other info.

	Write_VADC24(board, R_FilterHi OR Channel_Code(0))
	Write_VADC24(board, ((ADC24_Filter/2) AND 0x7FFF)/128)

	Write_VADC24(board, R_FilterLo OR Channel_Code(0))
	Write_VADC24(board, ADC24_Filter AND 0x00FF)	: REM   Filter bits

	Write_VADC24(board, R_Mode OR Channel_code(0)) 
	Write_VADC24(board, ADC24_Mode)
END


REM   This function checks the communications register to determine if the
REM   data ready flag indicates that a conversion has completed.

FUNCTION   Converted(board AS INTEGER, channel AS INTEGER) AS INTEGER
LOCAL temp AS INTEGER
	temp = Read_VADC24(board, R_Comm, channel)
	Converted = ((temp AND 0x80) = 0)
END


REM   Calibrate the system. This routine is also used for setting up background
REM   calibrations. When the VADC24 is set up to do background calibrations, the
REM   data throughput will be reduced by a factor of six. You should also do a
REM   self-calibration before setting up background calibrations, because full-
REM   scale calibration is not performed when background calibrations are active.

SUBROUTINE Calibrate_VADC24(cal_mode AS INTEGER, channel AS INTEGER, opmode AS INTEGER)
LOCAL board AS INTEGER, temp AS INTEGER, result AS INTEGER

	board = channel / Channels_per_Board
	channel = channel \ Channels_per_Board

	Write_VADC24(board, R_Mode OR Channel_Code(channel))
	Write_VADC24(board, (ADC24_Mode AND 0x1F) OR cal_mode)

	REM   If we've set up for background calibrations, then we'll do a
	REM   calibration before each conversion, so we'll never get any
	REM   "completed calibration" indication.

	IF cal_mode = M_Cal_Background
		RETURN
	ENDIF

	REM   We're not doing a background calibration. Read the mode register
	REM   until we get indication that we're done.

	FOR temp = 0 TO TIME_LIMIT
		result = Read_VADC24(board, R_Mode, channel)
		IF (result AND 0xE0) = 0
			EXIT
		ENDIF
	NEXT temp
END


REM   This function obtains a single conversion result, waiting as required
REM   for the value to become available. Conversion results are floating-point
REM   values, and are scaled so that both 24-bit and 16-bit results are within
REM   the range of integer values. This means that they can be assigned to
REM   integers and will only lose the fractional information in the LSBs.

VITAL FUNCTION AIN_VADC24(channel AS INTEGER) AS FLOAT
LOCAL board AS INTEGER
LOCAL temp AS INTEGER, timeout AS INTEGER
	board = channel / Channels_per_Board
	channel = channel \ Channels_per_Board

	REM   Wait for a conversion. If we don't get a "conversion complete"
	REM   notice soon enough, note the problem.
	timeout = -1
	FOR temp = 0 TO TIME_LIMIT
		IF Converted(board, channel)
			timeout = 0
			EXIT
		ENDIF
	NEXT temp

	IF timeout
		REM   Problem ... return an "impossible" value
		AIN_VADC24 = 65536.0
	ENDIF

	REM   Initiate a read of the data register
	Write_VADC24(board, R_DATA OR 8 OR Channel_Code(channel))

	VAST_OPEN(board)

	REM   Now we read the data register. We read the first 15 bits in
	REM   the first transfer, which will give us the integral portion
	REM   of the result. The final bit or bits will be read in the
	REM   second transfer, and will also be scaled up into the range
	REM   from 0-32767 (to keep it positive for simple arithmetic).

	temp  = VAST_SPI_XFER(15, -1)

	REM   Check for 24-bit -vs- 16-bit transfers
	IF ADC24_Filter AND 0x4000
		board = VAST_SPI_XFER( 9, -1) *    32
	ELSE
		board = VAST_SPI_XFER( 1, -1) * 16384
	ENDIF

	REM   Now that we have the pieces of the return value, combine
	REM   them into the floating-point result.
	AIN_VADC24 = temp + board / 32768.0

	VAST_CLOSE(15)

	REM   Check for bipolar (signed) results coming back
	IF (ADC24_Filter AND 0x8000) = 0
		AIN_VADC24 = -(AIN_VADC24)
	ENDIF

	REM   Check to see if we need to invert the sign to get a correct
	REM   differential polarity
	IF Differential AND (channel AND 1)
		AIN_VADC24 = -(AIN_VADC24)
	ENDIF
END

 

VestaTech Home

© 2002 Vesta Technology