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
© 2002 Vesta Technology