' *********************************************** ' * g_nidaq.inc * ' *********************************************** ' extra functions not used any more in our applications FUNCTION ADC (BYVAL k?) EXPORT AS INTEGER ' If NiDAQ is used, the procedure adapts to its operational mode. #IF %DEF(%NiDAQ) LOCAL Lsb?? LOCAL value?? LOCAL newestpointindex AS LONG ' nidaq monitor LOCAL DAQstopped AS INTEGER ' nidaq monitor LOCAL point AS INTEGER ' nidaq monitor LOCAL retval AS INTEGER LOCAL dummy AS INTEGER STATIC LastCall AS DWORD SELECT CASE @pDAQparams.mode #IF %DEF(%Arcom) CASE %DAQ_ARCOM, (%DAQ_ARCOM OR %DAQ_FLASH_SINGLE_CHANNEL) ' returns ADC-kanaal (0-15) with 12 bit resolution - Arcom ADC-card LOCAL ADCadr AS WORD ADCadr = @pDAQparams.adr ! push ax ; select channel ! push dx ! mov dx, ADCadr ; base adres for arcom card ! mov ah, k? ; al will and must be zero ! out dx, ax ; 16 bit out ' start conversion ! mov al, 2 ! out dx, al ! inc dx ; Base adres + 1 ! in al, dx ; starts conversion with a dummy read ! dec dx ; Base adres ! mov al, 3 ; set pointer to register 3 ! out dx, al ! inc dx ; ADCadr + 1 ADCloop: ! in al, dx ! test al, 1 ; test bit 0 ! jnz ADCloop ; bit 0 should be 0 when ready ! inc dx ; Badr + 2 ! in ax, dx ; do a 16-bit read ! mov Lsb??, ax ; should now have the 16bit value ! pop dx ! pop ax SHIFT RIGHT Lsb??, 4 FUNCTION = Lsb?? #ENDIF CASE (%DAQ_NI OR %DAQ_DOUBLEBUFFER) ' It makes absolutely no sense calling ADC() faster than the programmed samplerate /2. ' The monitor function returns always the same value. Hence, if double buffer mode is ' active we should keep an eye on timing, and eventually return the same data... ' now, we always do a scan if ADC is called... DIM ADarr(@pDAQparams.Nrchannels -1) AS LOCAL INTEGER point = ADCScan(ADarr()) FUNCTION = ADarr(k?) EXIT FUNCTION CASE (%DAQ_NI OR %DAQ_SINGLEBUFFER) dummy = DAQ_Monitor (@pDAQparams.id, @pDAQparams.ChannelVector(k?), 0, 1,point,newestpointindex,DAQstopped) ' lsb?? = NIDAQErrorHandler(dummy,"NiDAQ ADC-monitor error in GMT ",0) FUNCTION = point EXIT FUNCTION ' CASE (%DAQ_NI OR %DAQ_CHANNELSCAN) ' ' in this case the channelscanning task should be active. ' ' later this will become a thread instead of a task! ' m = "Check function ADC in g_nih.dll" ' MessageBox hInst,m, szTitelbox,%MB_OK OR %MB_ICONSTOP OR %MB_TASKMODAL OR %MB_TOPMOST CASE %DAQ_NI, (%DAQ_NI OR %DAQ_FLASH_SINGLE_CHANNEL) ' in case the data acquisition task is not active: ' This works but it's extremely slow with National Instruments DAQPAD 6020E USB device ' For the DACCard its absolutely fine!!! dummy = AI_Read (@pDAQparams.id, k?, @pDAQparams.GainVector(k?), retval) ' lsb?? = NIDAQErrorHandler(dummy,"NiDAQ ADC-function error in GMT ",0) FUNCTION = retval EXIT FUNCTION END SELECT #ELSE FUNCTION = %False #ENDIF END FUNCTION FUNCTION LogAD (BYVAL k?) EXPORT AS INTEGER ' returns the ADC() value of the DAQ channel passed, as a 7-bit logarithmic value ' This procedure only works for 12 bit resolution DAQ with ii hardware. ' or . Channels 12, 13, 14, 15 are unipolar, but offset 2048 since they ' represent bipolar values. (acceleration channels) LOCAL linval AS INTEGER linval = ADC(k?) IF linval < %False THEN linval = %False IF k? < 12 THEN IF ISFALSE linval THEN FUNCTION = %False ELSE FUNCTION = INT(15.268 * LOG(linval)) ' 0-127 END IF ELSE linval = linval - 2048 IF ISFALSE linval THEN FUNCTION = %False ELSE FUNCTION = INT(8.38 * LOG(ABS(linval))) * SGN(linval) ' -63 to +63 END IF END IF END FUNCTION FUNCTION ADCLogScan (point() AS INTEGER) EXPORT AS INTEGER ' funktie voor book of moves hardware. (Diana or Anacomp) ' This is a macro for a multichannel LogAD function. DIM AD(@pDAQparams.nrchannels) AS LOCAL INTEGER LOCAL nr AS INTEGER nr = ADCScan(AD()) FOR nr = 0 TO @pDAQparams.nrchannels -1 IF nr < 12 THEN IF AD(nr) <= %False THEN point(nr) = %False ELSE point(nr) = INT(15.268 * LOG(AD(nr))) ' 0-127 END IF ELSE AD(nr) = AD(nr) -2048 IF ISFALSE AD(nr) THEN point(nr) = %False ELSE point(nr) = INT(8.38 * LOG(ABS(AD(nr)))) * SGN(AD(nr)) END IF END IF NEXT nr FUNCTION = nr END FUNCTION FUNCTION QADC (BYVAL k?) EXPORT AS INTEGER ' returns 7-bit value with a pure quadratic transfer curve LOCAL linval AS INTEGER LOCAL tmp AS SINGLE linval = ADC(k?) IF linval < %False THEN linval = %False IF k? < 12 THEN tmp = Linval / 364! FUNCTION = INT(tmp * tmp) ' 0-127 ELSE linval = ABS(linval - 2048) tmp = Linval / 182! FUNCTION = INT(tmp * tmp) ' 0-127 END IF END FUNCTION FUNCTION ADCScan (ADCarray()AS INTEGER) EXPORT AS INTEGER #IF %DEF(%NiDAQ) ' this function returns the most recent reading from all available DAQ channels ' the number of samples is returned in the function, the samples in the array passed. STATIC tog AS BYTE STATIC lasttime AS DWORD STATIC point() AS INTEGER LOCAL i AS BYTE LOCAL retval AS INTEGER LOCAL dummy AS INTEGER LOCAL DAQstopped AS INTEGER LOCAL newestpointindex AS LONG LOCAL m AS ASCIIZ * 200 STATIC szTitelBox AS ASCIIZ * 40 IF ISFALSE tog THEN DIM point(@pDAQparams.nrchannels-1) AS STATIC INTEGER tog = %True IF ISFALSE @pDAQparams.scanfreq THEN @pDAQparams.scanfreq = @pDAQparams.samplingrate(0) szTitelBox = "{g_nih.dll}-[ADCScan]" & CHR$(13) END IF IF timeGetTime <= lasttime THEN ' in this case the function was called faster than the samplingrate, so we can afford to return the previous ' value in ADCarray() MAT ADCarray() = point() FUNCTION = @pDAQparams.nrchannels EXIT FUNCTION ELSE lasttime = timeGetTime + (1000!/ @pDAQparams.scanfreq) END IF SELECT CASE @pDAQparams.mode CASE (%DAQ_NI OR %DAQ_DOUBLEBUFFER),(%DAQ_NI OR %DAQ_SINGLEBUFFER) dummy = DAQ_Monitor (@pDAQparams.id, -1, 0, (@pDAQparams.nrchannels),VARPTR(ADCarray(0)),newestpointindex,DAQstopped) 'IF DAQstopped = %True THEN ' ' try to start again... ' DAQparams.mode = %DAQ_NI OR %DAQ_DOUBLEBUFFER ' %DAQ_FLASH_SINGLE_CHANNEL ' InitADC ' FUNCTION = %False ' EXIT FUNCTION 'END IF MAT point() = ADCarray() ' 18.07.2002 FUNCTION = @pDAQparams.nrchannels EXIT FUNCTION CASE (%DAQ_NI OR %DAQ_FLASH_SINGLE_CHANNEL),(%DAQ_NI OR %DAQ_CHANNELSCAN) ' code for a single all-channel scan. retval = AI_Read_Scan(@pDAQparams.id,ADCarray(0)) FOR i = 0 TO @pDAQparams.nrchannels -1 point(i) = ADCarray(@pDAQparams.channelvector(i)) NEXT i MAT ADCarray() = point() FUNCTION = @pDAQparams.nrchannels CASE %False ' not initialized! FUNCTION = %False CASE ELSE FOR i = LBOUND(ADCarray) TO UBOUND(ADCarray) ADCarray(i) = ADC(i) NEXT i FUNCTION = i END SELECT #ELSE FUNCTION = %False #ENDIF END FUNCTION FUNCTION StartDataAcquisitionTask (BYVAL param AS LONG) EXPORT AS LONG #IF %DEF(%NiDAQ) ' this procedure starts data acquisition for National Instruments devices, ' DAQPAD 6020E using the USB bus ' DAQCard AI16... PCMCIA ' The parameter is: 0 (stop) ' 1 (start double buffer callback proc.) ' 3 set up for channel-scan mode ' 4 start single buffer mode - no callback. ' -1 return running operational mode ' Tested O.K. with DAQCard LOCAL i AS BYTE LOCAL retval AS INTEGER LOCAL dummy AS INTEGER LOCAL scantimebase AS INTEGER LOCAL scaninterval AS INTEGER LOCAL sampletimebase AS INTEGER LOCAL sampleinterval AS INTEGER LOCAL samplingrate AS SINGLE LOCAL ChannelString AS ASCIIZ * 5 LOCAL kanaal AS INTEGER LOCAL vrange AS INTEGER LOCAL lpGainVector AS INTEGER PTR LOCAL cbprocadres AS LONG vrange = 10 ChannelString = "AI0" cbprocadres = CODEPTR(ProcNIDAQCallback) IF ISFALSE cbprocadres THEN MSGBOX "No codepointer for callback",,FUNCNAME$ SELECT CASE param CASE -1 SELECT CASE @pDAQparams.mode CASE %False, %DAQ_NI FUNCTION = %False CASE %DAQ_NI OR %DAQ_DOUBLEBUFFER FUNCTION = %DAQ_DOUBLEBUFFER CASE %DAQ_NI OR %DAQ_CHANNELSCAN FUNCTION = %DAQ_CHANNELSCAN CASE %DAQ_NI OR %DAQ_SINGLEBUFFER FUNCTION = %DAQ_SINGLEBUFFER CASE %DAQ_NI OR %DAQ_FLASH_SINGLE_CHANNEL FUNCTION = %DAQ_FLASH_SINGLE_CHANNEL CASE %DAQ_SIMULATOR FUNCTION = %DAQ_SIMULATOR END SELECT EXIT FUNCTION CASE %False retval = DAQ_Clear (@pDAQparams.id) ' resets. IF retval < %False THEN IF retval <> %noTransferInProgError THEN ' = -10608 in Nidaq-Error-pb.inc dummy = NIDAQErrorHandler(retval,"DAQ_Clear error in g_nih [InitADC]",0) END IF END IF IF @pDAQparams.mode = %DAQ_NI OR %DAQ_DOUBLEBUFFER THEN retval = DAQ_DB_Config(@pDAQparams.id,%False) ' stop double buffered data acquisition ' dummy = NIDAQErrorHandler(retval,"[StartDataAcquisitionTask] -STOP error",0) ' geeft een fout wanneer we de cockpit verlaten met de DAQ-task aan !!! END IF IF @pDAQparams.channel = %DAQ_RADAR THEN IF qr(0).timerId THEN TimeKillEvent qr(0).timerid : qr(0).timerid = %False END IF FUNCTION = %False CASE %DAQ_DOUBLEBUFFER EnterCriticalSection CritSecDaq ' 04.12.2000 SELECT CASE @pDAQparams.channel CASE %DAQ_S8A SetDAQ2Holosound CASE %DAQ_S07 SetDAQ2Lowest8 CASE ELSE SetDAQ2AllChannels @pDAQparams.channel = %DAQ_S0F ' sample all 16 channels END SELECT leaveCriticalSection CritSecDaq FUNCTION = %DAQ_DOUBLEBUFFER CASE %DAQ_FLASH_SINGLE_CHANNEL retval = DAQ_Clear (@pDAQparams.id) ' resets. IF retval < %False THEN IF retval <> %noTransferInProgError THEN ' = -10608 in Nidaq-Error-pb.inc dummy = NIDAQErrorHandler(retval,"DAQ_Clear error in g_nih [InitADC]",0) END IF END IF ' we always first set up the AI-parameters FOR kanaal = 0 TO @pDAQparams.nrchannels -1 retval = AI_Configure%(@pDAQparams.id,kanaal,@pDAQparams.inputconfig,vrange,@pDAQparams.polarity(kanaal),0) IF retval < %False THEN dummy = NIDAQErrorHandler(retval,"AI_Config error in g_nih [StartDataAcquisitionTask]",0) ' in NiDAQEX_PB.BAS NEXT kanaal END IF NEXT kanaal CASE %DAQ_CHANNELSCAN ' was 3 ' prepares for task-scheduled scanning of all channels. ' first we set the AI characteristics FOR i = 0 TO @pDAQparams.nrchannels -1 retval = AI_Configure%(@pDAQparams.id,i,@pDAQparams.inputconfig,10,@pDAQparams.polarity(i),0) dummy = NIDAQErrorHandler(retval,"AI_Config error in {g_nih.dll} [StartDataAcquisitionTask]",0) ' in NiDAQEX_PB.BAS NEXT i retval = SCAN_Setup(@pDAQparams.id,@pDAQparams.nrchannels,BYREF @pDAQparams.ChannelVector(0),BYREF @pDAQparams.GainVector(0)) dummy = NIDAQErrorHandler(retval,"NiDAQ Scan_Start error in {g_nih}[StartDataAcquisitionTask]",0) @pDAQparams.mode = %DAQ_NI OR %DAQ_CHANNELSCAN FUNCTION = %DAQ_CHANNELSCAN CASE %DAQ_SINGLEBUFFER '4 'singlebuffermode. ' first we set the AI characteristics FOR i = 0 TO @pDAQparams.nrchannels -1 retval = AI_Configure%(@pDAQparams.id,i,@pDAQparams.inputconfig,10,@pDAQparams.polarity(i),0) dummy = NIDAQErrorHandler(retval,"DAQ AI_Config error in {g_nih.dll} [StartDataAcquisitionTask]",0) ' in NiDAQEX_PB.BAS NEXT i retval = DAQ_Rate(@pDAQparams.rate,0,sampletimebase,sampleinterval) IF ISFALSE @pDAQparams.Buffersize THEN MSGBOX "No buffersize",,FUNCNAME$ REDIM DAQbuffer(@pDAQparams.Buffersize) AS GLOBAL INTEGER @pDAQparams.pDAQbuffer = VARPTR(DAQbuffer(0)) scantimebase = 2 ' use 100kHz / 10 microsecond clock scaninterval = 100000& / @pDAQparams.samplingrate(0) sampletimebase = -3 ' use 20MHz / 50ns clock sampleinterval = INT(20000000& / 50000&) ' = 400 voor samplingrate = 50000 S/s @pDaqparams.rate = @pDAQparams.samplingrate(0) * @pDAQparams.nrchannels @pDaqparams.scanfreq = 100000& / scaninterval retval = SCAN_Setup(@pDAQparams.id,@pDAQparams.nrchannels,BYREF @pDAQparams.ChannelVector(0),BYREF @pDAQparams.GainVector(0)) dummy = NIDAQErrorHandler(retval,"NiDAQ Scan_Setup error in {g_nih}[StartDataAcquisitionTask]",0) ' this should become scanrate = 64Scans/s and sampling rate set to maximum... retval = SCAN_Start(@pDAQparams.id,BYVAL @pDAQparams.pDAQbuffer,32,sampletimebase,sampleinterval,scantimebase,scaninterval) dummy = NIDAQErrorHandler(retval,"NiDAQ Scan_Start error in {g_nih}[StartDataAcquisitionTask]",0) @pDAQparams.mode = %DAQ_NI OR %DAQ_SINGLEBUFFER FUNCTION = %DAQ_SINGLEBUFFER CASE ELSE MSGBOX "Not implemented DAQ mode requested",,FUNCNAME$ FUNCTION = %False END SELECT #ELSE FUNCTION = %False #ENDIF END FUNCTION SUB SetDAQ2Lowest8 () EXPORT #IF %DEF(%NiDAQ) ' initializes the DAQ board to sample only the lowest 8 datachannels LOCAL i AS INTEGER LOCAL retval AS INTEGER LOCAL dummy AS INTEGER LOCAL timebase AS INTEGER LOCAL sampleinterval AS INTEGER LOCAL scaninterval AS INTEGER LOCAL scantimebase AS INTEGER LOCAL sampletimebase AS INTEGER LOCAL DAQTrigVal0 AS DWORD IF StartDataAcquisitionTask (-1) <> %False THEN retval = StartDataAcquisitionTask (%False) ' stop activity, if any. Disallocates buffers. END IF ' This should set the parameters for the given sampling rate on 8 channels only (0,1,2,3,4,5,6,7) @pDAQparams.rate = %Null ' reset SetDAQ2Hardware board FOR i = 0 TO 7 @pDAQparams.samplingrate(i) = 64 @pDAQparams.ChannelVector(i) = i NEXT i scantimebase = 2 ' use 100kHz / 10 microsecond clock scaninterval = 100000& / @pDAQparams.samplingrate(0) ' = 100 * 10 microseconds = 1 ms sampletimebase = -3 ' use 20MHz / 50ns clock sampleinterval = INT(20000000& / 100000&) '50000&) ' = 400 voor samplingrate = 50000 S/s @pDaqparams.rate = @pDAQparams.samplingrate(0) * 8 ' 8 channels only @pDaqparams.scanfreq = @pDAQparams.samplingrate(0) ' = 100000& / scaninterval ' now we can recalculate the circular buffer size, for the data refreshrate we want: ' The ADCbuffer should be twice this size for double buffering: @pDAQparams.Buffersize = @pDAQparams.rate ' in aantal samples voor 1 sekonde buffer EnterCriticalSection CritSecDaq REDIM ADCbuffer(@pDAQparams.Buffersize -1) AS GLOBAL INTEGER @pDAQparams.pADCbuffer = VARPTR(ADCbuffer(0)) ' the receive-buffer may be half size, or even sized in the callback... ' REDIM DAQbuffer(0 TO (@pDAQparams.Buffersize \2)-1) AS GLOBAL INTEGER ' @pDAQparams.pDAQbuffer = VARPTR(DAQbuffer(0)) LeaveCriticalSection CritSecDaq ' first set the AI characteristics FOR i = 0 TO 7 '15 '0 to 7 retval = AI_Configure%(@pDAQparams.id,i,@pDAQparams.inputconfig,10,@pDAQparams.polarity(i),0) ' o.k. dummy = NIDAQErrorHandler(retval,"AI_Config error in {G_Nih.dll} [Low8]",0) ' in NiDAQEX_PB.BAS NEXT i ' use double buffering - to disable: DAQ_DB_Config(DAQid,%False) retval = DAQ_DB_Config(@pDAQparams.id,%True) dummy = NIDAQErrorHandler(retval,"NiDAQ DAQ_DB_Config error in {g_nih.dll}[Low8] ",0) ' This has to be the last step of building block 1. ' Building Block 2: ************************************************************************** ' Prepare for acquisition of multiple channels: retval = SCAN_SetUp(@pDAQparams.id,8,BYREF @pDAQparams.ChannelVector(0),BYREF @pDAQparams.Gainvector(0)) dummy = NIDAQErrorHandler(retval,"NiDAQ Scan_Setup error in {g_nih}[Hol]",0) retval = SCAN_Start(@pDAQparams.id,@pDAQparams.pADCbuffer,@pDAQparams.buffersize,sampletimebase,sampleinterval,scantimebase,scaninterval) dummy = NIDAQErrorHandler(retval,"NiDAQ Scan_Start error in {g_nih.dll}[Hol]",0) @pDAQparams.mode = %DAQ_NI OR %DAQ_DOUBLEBUFFER #ENDIF END SUB SUB SetDAQ2AllChannels() EXPORT LOCAL i AS INTEGER LOCAL retval AS INTEGER LOCAL dummy AS INTEGER LOCAL timebase AS INTEGER LOCAL sampleinterval AS INTEGER LOCAL samplingrate AS SINGLE LOCAL scaninterval AS INTEGER LOCAL scantimebase AS INTEGER LOCAL sampletimebase AS INTEGER LOCAL lpGainVector AS DWORD LOCAL DAQTrigVal0 AS DWORD #IF %DEF(%NiDAQ) SetDAQ2Hardware board ' some math first: ' we scannen de kanalen aan de samplingrate, en maximalizeren de samplingrate binnen elke scan tot het ' hoogste wat haalbaar is op de hardware. scantimebase = 2 ' use 100kHz / 10 microsecond clock @pDAQparams.samplingrate(0) = 64 @pDAQparams.nrchannels = 16 scaninterval = 100000& / @pDAQparams.samplingrate(0) sampletimebase = -3 ' use 20MHz / 50ns clock sampleinterval = INT(20000000& / 100000&) ' = 400 voor samplingrate = 50000 S/s ' if we take 50000&, it works on the DAQpad but not on DAQcards !!! ' we lost 2 working days on this bug !!! @pDaqparams.rate = @pDAQparams.samplingrate(0) * @pDAQparams.nrchannels @pDaqparams.scanfreq = 100000& / scaninterval ' now we can recalculate the circular buffer size, for the data refreshrate we want: ' The ADCbuffer should be twice this size for double buffering: @pDAQparams.Buffersize = @pDAQparams.rate '/ @pDAQparams.DataRefreshRate) ' in aantal samples ' now buffersize is fixed to one second. EnterCriticalSection CritSecDaq REDIM ADCbuffer(@pDAQparams.Buffersize -1) AS GLOBAL INTEGER ' 0-1023 , or 1024 integers @pDAQparams.pADCbuffer = VARPTR(ADCbuffer(0)) ' the receive-buffer may be half size, or even sized in the callback... ' REDIM DAQbuffer(0 TO (@pDAQparams.Buffersize \2)-1) AS GLOBAL INTEGER ' 0-511 , or 512 integers ' @pDAQparams.pDAQbuffer = VARPTR(DAQbuffer(0)) LeaveCriticalSection CritSecDaq ' first we set the AI characteristics FOR i = 0 TO @pDAQparams.nrchannels -1 ' @pDAQparams.ChannelVector(i)= i ' @pDAQparams.GainVector(i) = 2 ' for 5V unipolar ' @pDAQparams.samplingrate(i) = @pDAQparams.samplingrate(0) ' as read from ini file. ' @pDAQparams.polarity(i) = 1 ' for unipolar . @pDAQparams.polarity(0) retval = AI_Configure%(@pDAQparams.id,i,@pDAQparams.inputconfig,10,@pDAQparams.polarity(i),0) dummy = NIDAQErrorHandler(retval,"AI_Config error in {G_Nih.dll} 16ch",0) ' in NiDAQEX_PB.BAS NEXT i ' use double buffering - to disable: DAQ_DB_Config(DAQid,%False) retval = DAQ_DB_Config(@pDAQparams.id,%True) dummy = NIDAQErrorHandler(retval,"NiDAQ DAQ_DB_Config error in {g_nih.dll} 16ch",0) ' This has to be the last step of building block 1. ' Building Block 2: ************************************************************************** ' Prepare for acquisition of multiple channels: retval = SCAN_Setup(@pDAQparams.id,16,BYREF @pDAQparams.ChannelVector(0),BYREF @pDAQparams.GainVector(0)) dummy = NIDAQErrorHandler(retval,"NiDAQ Scan_Setup error in {g_nih} 16ch",0) ' now before starting data acquisition, we have to prepare callback messaging: ' we want a message to be send every time we acquired a half buffer of data: ' DAQTrigVal0 = (@pDAQparams.buffersize /2 ) / @pDAQparams.nrchannels ' IF DAQTrigVal0 < 2 THEN ' ' DAQTrigVal0 = 2 ' minimum 2 scans!!! ' MSGBOX "ERROR: nr scans < 2" ' END IF ' retval = Config_DAQ_Event_Message (@pDaqParams.id,1,"AI0",1,DAQTrigVal0,0,0,0,0,hDAQwnd,%NIDAQ_DB,0) ' crashes: ' retval = Config_DAQ_Event_Message (@pDaqParams.id,1,"AI0",1,DAQTrigVal0,0,0,0,0,0,%NIDAQ_DB,cbProcAdres) ' dit veroorzaakte de crash in kernel32: ' retval = Config_DAQ_Event_Message (@pDaqParams.id,1,"AI0",1,DAQTrigVal0,0,0,0,0,0,%NIDAQ_DB,CODEPTR(ProcNIDAQCallback)) ' param 1= device number ' param 2= add or remove a message 0=clear all,1=add new, 2=remove existing ' param 3= channel string = "AI0" ' param 4= 0 = send a single message ' 1 = send message on each multiple of daqtrigval0 scans = 1 ' param 5= trigger criterium value = DAQTrigVal0 = DAQparams.Buffersize / 32 ' param 6= second daqtrigval ' param 7= number of triggers to skip ' param 8= pretrig scans ' param 9= posttrigscans ' param 10 = handle ' param 11 = msg ' param 12 = callback adress ' ... ' dummy = NIDAQErrorHandler(retval,"NiDAQ Config_DAQ_Eventmsg error in {g_nih.dll}[StartDataAcquisitionTask]DB",0) ' the criterium for posting a message to the callback is the acquisition of a halfbuffer of data in ADCbuffer() retval = SCAN_Start(@pDAQparams.id,@pDAQparams.pADCbuffer,@pDAQparams.buffersize,sampletimebase,sampleinterval,scantimebase,scaninterval) dummy = NIDAQErrorHandler(retval,"NiDAQ Scan_Start error in {g_nih.dll}16ch",0) @pDAQparams.mode = %DAQ_NI OR %DAQ_DOUBLEBUFFER #ENDIF END SUB SUB SetDAQ2Holosound () EXPORT #IF %DEF(%NiDAQ) LOCAL i AS INTEGER LOCAL retval AS INTEGER LOCAL dummy AS INTEGER LOCAL timebase AS INTEGER LOCAL sampleinterval AS INTEGER LOCAL scaninterval AS INTEGER LOCAL scantimebase AS INTEGER LOCAL sampletimebase AS INTEGER LOCAL DAQTrigVal0 AS DWORD ' IF StartDataAcquisitionTask (-1) <> %False THEN ' retval = StartDataAcquisitionTask (%False) ' stop activity, if any. Disallocates buffers. ' END IF IF board <> %ii_2000 THEN MSGBOX "ERROR: Calling Holosound mode requires the ii_2000 board" ,,FUNCNAME$ EXIT SUB END IF ' This should set the parameters for 1024sps on 3 channels only (8,9,10) ' for conversion to wave audio, we would better choose a samplingrate that divides %CD_SR ' possible values are then: 900, 882, 1050, 1225 ' 1050 = 44100 / 42 @pDAQparams.rate = %Null ' reset SetDAQ2Hardware board @pDAQparams.ChannelVector(0) = 8 @pDAQparams.ChannelVector(1) = 9 @pDAQparams.ChannelVector(2) = 10 FOR i = 8 TO 10 @pDAQparams.GainVector(i-8) = 1 ' refers to channelvector remapped channels!!! ' so we need only to set 0,1,2 in fact... @pDAQparams.polarity(i) = 0 ' set to bipolar @pDAQparams.voltagerange(i) = 10 ' set to -5 to + 5 Volt @pDAQparams.samplingrate(i) = 1050 '1024 '128 '64 NEXT i scantimebase = 2 ' use 100kHz / 10 microsecond clock scaninterval = 100000& / @pDAQparams.samplingrate(8) ' = 100 * 10 microseconds = 1 ms sampletimebase = -3 ' use 20MHz / 50ns clock sampleinterval = INT(20000000& / 100000&) '50000&) ' = 400 voor samplingrate = 50000 S/s @pDaqparams.rate = @pDAQparams.samplingrate(8) * 3 ' 3 channels only @pDaqparams.scanfreq = @pDAQparams.samplingrate(8) ' = 100000& / scaninterval ' now we can recalculate the circular buffer size, for the data refreshrate we want: ' The ADCbuffer should be twice this size for double buffering: @pDAQparams.Buffersize = @pDAQparams.rate ' in aantal samples voor 1 sekonde buffer EnterCriticalSection CritSecDaq REDIM ADCbuffer(@pDAQparams.Buffersize -1) AS GLOBAL INTEGER ' 0-2999 or 3000 integers @pDAQparams.pADCbuffer = VARPTR(ADCbuffer(0)) ' the receive-buffer may be half size, or even sized in the callback... ' REDIM DAQbuffer(0 TO (@pDAQparams.Buffersize \2)-1) AS GLOBAL INTEGER ' 0-1499 , or 1500 integers ' @pDAQparams.pDAQbuffer = VARPTR(DAQbuffer(0)) LeaveCriticalSection CritSecDaq ' first set the AI characteristics FOR i = 8 TO 10 retval = AI_Configure%(@pDAQparams.id,i,@pDAQparams.inputconfig,10,@pDAQparams.polarity(i),0) ' o.k. dummy = NIDAQErrorHandler(retval,"AI_Config error in {G_Nih.dll} [Hol]",0) ' in NiDAQEX_PB.BAS NEXT i ' use double buffering - to disable: DAQ_DB_Config(DAQid,%False) retval = DAQ_DB_Config(@pDAQparams.id,%True) dummy = NIDAQErrorHandler(retval,"NiDAQ DAQ_DB_Config error in {g_nih.dll}[Hol] ",0) ' This has to be the last step of building block 1. ' Building Block 2: ************************************************************************** ' Prepare for acquisition of multiple channels: retval = SCAN_SetUp(@pDAQparams.id,3,BYREF @pDAQparams.ChannelVector(0),BYREF @pDAQparams.Gainvector(0)) dummy = NIDAQErrorHandler(retval,"NiDAQ Scan_Setup error in {g_nih}[Hol]",0) ' now before starting data acquisition, we have to prepare callback messaging: ' we want a message to be send every time we acquired a half buffer of data: ' DAQTrigVal0 = (@pDAQparams.buffersize /2 ) / 3 ' @pDAQparams.nrchannels ' IF DAQTrigVal0 < 2 THEN ' ' DAQTrigVal0 = 2 ' minimum 2 scans!!! ' MSGBOX "ERROR: nr scans < 2" ' END IF ' "AI8:10" ' retval = Config_DAQ_Event_Message (@pDaqParams.id,1,"AI0",1,DAQTrigVal0,0,0,0,0,0,%NIDAQ_DB,0) ' crashes: ' retval = Config_DAQ_Event_Message (@pDaqParams.id,1,"AI0",1,DAQTrigVal0,0,0,0,0,0,%NIDAQ_DB,cbProcAdres) ' dit veroorzaakte de crash in kernel32: ' retval = Config_DAQ_Event_Message (@pDaqParams.id,1,"AI0",1,DAQTrigVal0,0,0,0,0,0,%NIDAQ_DB,CODEPTR(ProcNIDAQCallback)) ' param 1= device number ' param 2= add or remove a message 0=clear all,1=add new, 2=remove existing ' param 3= channel string = "AI0" ' param 4= 0 = send a single message ' 1 = send message on each multiple of daqtrigval0 scans = 1 ' param 5= trigger criterium value ' param 6= second daqtrigval ' param 7= number of triggers to skip ' param 8= pretrig scans ' param 9= posttrigscans ' param 10 = handle ' param 11 = msg ' param 12 = callback adress ' ... ' dummy = NIDAQErrorHandler(retval,"NiDAQ Config_DAQ_Eventmsg error in {g_nih.dll}[StartDataAcquisitionTask]DB",0) ' the criterium for posting a message to the callback is the acquisition of a halfbuffer of data in ADCbuffer() retval = SCAN_Start(@pDAQparams.id,@pDAQparams.pADCbuffer,@pDAQparams.buffersize,sampletimebase,sampleinterval,scantimebase,scaninterval) dummy = NIDAQErrorHandler(retval,"NiDAQ Scan_Start error in {g_nih.dll}[Hol]",0) @pDAQparams.mode = %DAQ_NI OR %DAQ_DOUBLEBUFFER #ENDIF END SUB ' in the works... FUNCTION NiDAQ_Enumerate_Devices (devnames() AS STRING) EXPORT AS INTEGER ' not used yet... #IF %DEF(%NiDAQ) LOCAL i AS INTEGER LOCAL retval AS INTEGER LOCAL devid AS LONG i = 1 DO retval = Get_DAQ_Device_Info (i,%ND_DEVICE_TYPE_CODE,devid) INCR i LOOP UNTIL retval <> %NoError #ENDIF END FUNCTION FUNCTION Verify_DAQ_Device (BYVAL id AS LONG, BYVAL verb AS BYTE) EXPORT AS BYTE #IF %DEF(%NiDAQ) ' this procedure, called on menu selection in 's WinProc, checks the user selection for DAQ devices ' against whats possible on this pc. ' Should become obsolete with new version of GMT. (verification should happen before building the ' user menu). LOCAL m AS ASCIIZ * 200 LOCAL szTitelBox AS ASCIIZ * 31 LOCAL tstbyte? LOCAL prtadr AS WORD LOCAL NiId AS INTEGER IF ISFALSE pDAQparams THEN MSGBOX "ERROR - nullpointer for daqparams {g_nih.dll}-[Verify_DAQ_Device]",,FUNCNAME$ FUNCTION = %False EXIT FUNCTION END IF IF ISFALSE pDIOparams THEN MSGBOX "ERROR - nullpointer for dioparams {g_nih.dll}-[Verify_DAQ_Device]",,FUNCNAME$ FUNCTION = %False EXIT FUNCTION END IF szTitelBox = " DAQ/DIO-device setup message" ' @pDAQparams.device = "NONE" ' remmed 19.03.2001 ' @pDAQparams.nrchannels = %Null FUNCTION = %False ' default return value SELECT CASE id #IF %DEF(%Arcom) CASE %IDM_ARCOM ' we check for the physical presence of the card... ' ARCOM cards are not PNP but legacy ISA boards, thus their parameters should be set both ' in the hardware and in the .INI file. IF ISFALSE @pDAQparams.adr THEN m = "No ARCOM card I/O adress found in .INI file..." + CHR$(13) MessageBox hInst,m, szTitelbox,%MB_OK OR %MB_ICONSTOP OR %MB_TASKMODAL OR %MB_TOPMOST EXIT FUNCTION ELSE prtadr = @pDAQparams.adr ! push ax ! push dx ! mov dx, prtadr ;base IO adress should be in INI file ! mov al, &H81 ! out dx, al ! inc dx ! in al, dx ! mov tstbyte?, al ! pop dx ! pop ax END IF IF tstbyte? = &H21 THEN @pDAQparams.device = "ARCOM" @pDAQparams.nrchannels = 16 @pDAQparams.mode = %DAQ_ARCOM @pDAQparams.bBitsPerSample = 12 m= "Arcom ADC board found and selected" + CHR$(13) MessageBox hInst,m, szTitelbox,%MB_OK OR %MB_ICONASTERISK OR %MB_TASKMODAL OR %MB_TOPMOST FUNCTION = %True ELSE m = "No Arcom ADC-card found at &H" + HEX$(DAQparams.adr) + " !!!" + CHR$(13) m = m + "Either the card is not installed, or its I/O setting does not match" + CHR$(13) m = m + "the value set in the .INI file" + CHR$(13) @pDAQparams.mode = %False @pDAQparams.device = "NONE" @pDAQparams.adr = %False @pDAQparams.bBitsPerSample = %False MessageBox hInst,m, szTitelbox,%MB_OK OR %MB_ICONSTOP OR %MB_TASKMODAL OR %MB_TOPMOST END IF EXIT FUNCTION #ENDIF CASE %IDM_NIDAQ IF ISFALSE GetModuleHandle ("NiDAQ32.dll") THEN m = "Ni-DAQ driver software not installed or not found..." + CHR$(13) m = "First install the NiDAQ software from your National Instruments CD-ROM " + CHR$(13) m = "if you have a National Instruments device you want to use" + CHR$(13) m = " cannot use NI devices without these drivers" + CHR$(13) @pDAQparams.device = "NONE" @pDAQparams.mode = %False @pDAQparams.id = %False ' same for DIO-devices @pDIOparams.device = "NONE" @pDIOparams.nrports = %False @pDIOparams.id = %False MessageBox hInst,m, szTitelbox,%MB_OK OR %MB_ICONSTOP OR %MB_TASKMODAL OR %MB_TOPMOST EXIT FUNCTION ELSE LOCAL NiDaqVersion AS LONG Get_Ni_DAQ_Version NiDaqVersion m = "Ni-DAQ version = " + LEFT$(HEX$(NiDaqVersion AND &HFFFF),1) + "." + RIGHT$(HEX$(NiDaqVersion AND &HFFFF),2)+ CHR$(13) ' if we run into a pc with more than a single NI device, we have to rewrite this code... ' o.k. rewritten 30.09.2000... LOCAL md AS ASCIIZ * 40 NiId = @pDAQparams.id ' used to pass value from wndproc in gmt-main. md= FindNiDAQdevice (NiId) '(@pDAQparams.id) SELECT CASE TRIM$(UCASE$(md)) CASE "DAQPAD-6020E FOR USB" @pDAQparams.device =UCASE$(LEFT$(md,12)) @pDAQparams.nrchannels = 16 @pDAQparams.mode = %DAQ_NI @pDAQparams.bBitsPerSample = 12 m = m + "National Instruments Device found:" + CHR$(13) + md + CHR$(13) FUNCTION = %True IF verb = %verbose THEN MessageBox hInst,m, szTitelbox,%MB_OK OR %MB_ICONASTERISK OR %MB_TASKMODAL OR %MB_TOPMOST END IF @pDAQparams.id = NiId CASE "DAQCARD-AI-16E-4" @pDAQparams.device =UCASE$(LEFT$(md,16)) @pDAQparams.nrchannels = 16 @pDAQparams.mode = %DAQ_NI @pDAQparams.bBitsPerSample = 12 m = m + "National Instruments Device found:" + CHR$(13) + md + CHR$(13) FUNCTION = %True IF verb = %verbose THEN MessageBox hInst,m, szTitelbox,%MB_OK OR %MB_ICONASTERISK OR %MB_TASKMODAL OR %MB_TOPMOST END IF @pDAQparams.id = NiId CASE "DAQCARD DIO-24" ' pcmcia card for static digital I/O @pDIOparams.device = UCASE$(LEFT$(md,14)) @pDIOparams.nrports = 3 ' 3 8-bit ports @pDIOparams.mode = %DAQ_NI m = m + "National Instruments Device found:" + CHR$(13) + md + CHR$(13) FUNCTION = %True IF verb = %verbose THEN MessageBox hInst,m, szTitelbox,%MB_OK OR %MB_ICONASTERISK OR %MB_TASKMODAL OR %MB_TOPMOST END IF ' DIOid = @pDAQparams.id @pDIOparams.id = NiId CASE "DAQCARD-6533" ' high speed DIO pcmcia card @pDIOparams.device = UCASE$(LEFT$(md,12)) @pDIOparams.nrports = 4 ' 4 8-bit ports @pDIOparams.mode = %DAQ_NI m = m + "National Instruments Device found:" + CHR$(13) + md + CHR$(13) FUNCTION = %True IF verb = %verbose THEN MessageBox hInst,m, szTitelbox,%MB_OK OR %MB_ICONASTERISK OR %MB_TASKMODAL OR %MB_TOPMOST END IF @pDIOparams.id = NiId CASE "PCI-DIO-32HS" ' pci bus card 6533 device for very fast DIO @pDIOparams.device = UCASE$(LEFT$(md,12)) @pDIOparams.nrports = 4 ' 4 8-bit ports @pDIOparams.mode = %DAQ_NI m = m + "National Instruments Device found:" + CHR$(13) + md + CHR$(13) FUNCTION = %True IF verb = %verbose THEN MessageBox hInst,m, szTitelbox,%MB_OK OR %MB_ICONASTERISK OR %MB_TASKMODAL OR %MB_TOPMOST END IF @pDIOparams.id = NiId CASE "NONE","NOT IMPLEMENTED" m = m + "No National Instruments Devices found!" @pDAQparams.device = "NONE" @pDAQparams.mode = %False @pDAQparams.nrchannels = %False @pDAQparams.id = %False @pDIOparams.id = %False @pDIOparams.nrports=0 @pDIOparams.device = "NONE" @pDIOparams.mode = %False MessageBox hInst,m, szTitelbox,%MB_OK OR %MB_ICONSTOP OR %MB_TASKMODAL OR %MB_TOPMOST CASE ELSE @pDAQparams.device = "NONE" @pDAQparams.mode = %False @pDAQparams.nrchannels = %False @pDAQparams.id = %False @pDIOparams.id = %False @pDIOparams.nrports=0 @pDIOparams.device = "NONE" @pDIOparams.mode = %False m = m + "Unsupported National Instruments Device found:" + CHR$(13) + md + CHR$(13) MessageBox hInst,m, szTitelbox,%MB_OK OR %MB_ICONSTOP OR %MB_TASKMODAL OR %MB_TOPMOST END SELECT END IF EXIT FUNCTION CASE ELSE m = "Unsupported DAQ device selected..." + CHR$(13) m = "add code in module [gmt_daq.bas], procedure [Verify_DAQ_Device]" + CHR$(13) @pDAQparams.device = "NONE" @pDAQparams.mode = %False @pDAQparams.nrchannels = %False @pDAQparams.id = %False @pDIOparams.id = %False @pDIOparams.nrports=0 @pDIOparams.device = "NONE" @pDIOparams.mode = %False MessageBox hInst,m, szTitelbox,%MB_OK OR %MB_ICONSTOP OR %MB_TASKMODAL OR %MB_TOPMOST EXIT FUNCTION END SELECT #ELSE FUNCTION = %False #ENDIF END FUNCTION