Commits

cleemesser committed 52909f0

modified to run again on opensuse11, disabled GetTerminalNameDevPrevix

Comments (0)

Files changed (6)

 cimport numpy as c_np
 
 from nidaqmx cimport *
-from utils cimport CHK, CHKng, GetTerminalNameWithDevPrefix
+from utils cimport CHK, CHKng
 
 from stdio cimport *
 

contAOwCallback.pyx

File contents unchanged.
-"""
-A place to test how to use cython and DAQmx
-
-tests are in test_daqmxcalls.py
-
-test1() and test2()
--------------------
-  smoke tests to create tasks
-
-test3(): 
---------
-  the basic ideas behind the callback function for continuous analog input
-  just prints out the bit
-
-test4():
---------
-  is supposed to allow for a python function as the callback but I'm not sure if it is working
-
-test5():  
---------
-is to memmap a file 'testmmap.dat' 
-every N samples, a dma read to that target is performed placing the length of the read
-into the first point of thearray
-
-test6(): like test5 but callback runs in another thread per DAQmxRegisterxxx
-
-
-Needed: cython compatible queue or signal to tell other parts of
-program to do things from a callaback.  Then is then used to notifed
-subscribing processes that they can know to re-read the memmap'd data.
-
-"""
-# see basic_numpy_to_c.pyx for reference
-# still in learning phase
-
-
-
-from stdlib cimport *
-from stdio cimport *
-
-import numpy 
-cimport numpy as c_np
-
-from nidaqmx cimport *
-
-# now write declaratios to DAQmx
-
-# probably should declare this public api and move to nidaqmx.pyx /pxd
-cdef int32 GetTerminalNameWithDevPrefix(TaskHandle taskHandle, char terminalName[],
-                                        char triggerName[]) :
-    """leave with gil for now"""
-    cdef:
-        int32	error=0
-        char	device[256]
-        int32	productCategory
-        uInt32	numDevices,i=1
-        uInt32  nameIndx=0
-
-    # translated from C--wow once I understand what's going on here this could really use a cleanup
-
-
-    CHK(DAQmxGetTaskNumDevices(taskHandle,&numDevices))
-    # print 'numDevices:', numDevices
-    while i<=numDevices:
-        CHK (DAQmxGetNthTaskDevice(taskHandle,i,device,256))
-        # print "device: ", device
-        i+=1
-        CHK (DAQmxGetDevProductCategory(device,&productCategory))
-        if (productCategory!=DAQmx_Val_CSeriesModule) and (productCategory!=DAQmx_Val_SCXIModule) :
-            triggerName[nameIndx] = '/'
-            nameIndx += 1
-            strcat(strcat(strcpy(&triggerName[nameIndx],device),"/"),terminalName)
-            # print "triggerName, device, terminalName", triggerName, device, terminalName
-            break
-
-    return error
-######################################################################################
-# configuration
-######################################################################################
-
-# AcqMode
-# for USB, use:
-# for PCI use DAQmx_Val_NRSE
-
-AcqMode=DAQmx_Val_RSE # one of DAQmx_Val_NRSE, DAQmx_Val_RSE or differential
-
-### globals ###
-cdef int gIntVar=1
-cdef int* p_gIntVar= &(gIntVar)
-cdef TaskHandle  gWriteTask=0
-cdef TaskHandle* gWriteTaskPtr=NULL
-
-# functions meant to communicate into clevel stuff from python
-
-def set_global_int_var(newval):
-    print "before: ", gIntVar
-    # assert type(newval) == type(1)
-    # note: it doesn't work to simply assign to gIntVar=newval
-    # in the code, it seems like it must be creating a temporary local variable in
-    # the function so it doesn't affect the global gIntVar
-    p_gIntVar[0] = <int> newval
-    print "after: ", gIntVar
-    return 0
-
-cpdef int get_global_int_var():
-    return gIntVar
-
-def create_special_memmap_ndarray(filename, N):
-    """
-    create a float64 memmapped array that also stores it's own
-    [0] = maximum length
-    [1] = used length
-    [2-4] -> user data
-    [5] -> array data starts
-
-    within the shared array itself
-    actual data starts at offset location mm[5]
-    """
-    mm = numpy.memmap(filename, dtype='float64', mode='w+', shape=(N+5,))
-    mm[0] = N
-    mm[1] = 0
-    return mm
-
-def createTask(name):
-    cdef TaskHandle task
-    cdef int32 res
-    res = 0
-    res = DAQmxCreateTask(name, &task)
-    return res
-
-cdef char gErrbuf[1000]  # these are static by default
-cdef unsigned int gErrbufSize = 1000
-cdef float64 g_aiData[10000]
-
-cpdef CHK(int32 err):
-    """a simple error checking routine, needs gil because raises python exception"""
-    if err < 0:
-        DAQmxGetErrorString(err,gErrbuf,gErrbufSize)
-        raise RuntimeError('nidaq call failed with error %d: %s'%(err,repr(gErrbuf)))
-
-cdef int32 CHKng(int32 err) nogil:
-    """
-    a simple error checking routine, avoid raising python exception
-    so can be nogil
-    """
-    if err < 0:
-        DAQmxGetErrorString(err,gErrbuf,gErrbufSize)
-        printf("nidaq call failed with error %d: %s", err,gErrbuf)
-    if err > 0:
-        DAQmxGetErrorString(err,gErrbuf,gErrbufSize)
-        printf("nidaq call warning %d: %s", err,gErrbuf)
-
-    return err
-
-cdef int32 print_every_n_cb(TaskHandle taskHandle, int32 eventType, uInt32 nSamples, void *callbackData) nogil:
-    # first try
-    cdef int32 error =0
-    cdef int32 readAI=0
-    cdef int32 ii=0
-    cdef int32 res
-    cdef int Nsamples=50
-
-
-    printf("In callback-nSamples: %d", nSamples)
-    res=DAQmxReadAnalogF64(taskHandle,nSamples, #num samples per channel
-                           10.0,DAQmx_Val_GroupByChannel,g_aiData,10000,&readAI,NULL)
-    printf("read %d - data:", readAI)
-    for ii from 0 <= ii < Nsamples:  # pyrex style loop
-        printf("%f ", g_aiData[ii])
-    printf("\n")
-
-
-    return res
-
-## callback functions: it's not clear what python functions you can call
-cdef int32 print_every_n_sharedvar_cb(TaskHandle taskHandle, int32 eventType, uInt32 nSamples, void *callbackData) nogil:
-    # first try
-    cdef int error =0
-    cdef int* sharedptr=<int*>callbackData
-
-    printf("callback shared: %d\n", sharedptr[0])
-
-
-    return error
-
-
-cdef int32 print_every_n_sharedvar_stop_cb(TaskHandle taskHandle, int32 eventType, uInt32 nSamples, void *callbackData) nogil:
-    # first try
-    # some interesting results, without stoppping task, don't see to reach whole thing
-    # if first stop gWriteTask, then write stuff,see 25ms delay
-    cdef int error =0
-    cdef int* sharedptr=<int*>callbackData
-    cdef float64 wa[100]
-    cdef int32 samplesWritten=0
-    
-    printf("callback shared: %d\n", sharedptr[0])
-    if sharedptr[0] == 0:
-        printf("trying to stop\n")
-
-        for error from 0 <= error < 100: # for ii from 0 <= ii < Nsamples:
-            wa[error] = -2.0
-        error =0
-        printf("wa[10]=%f\n", wa[10])
-
-        if gWriteTask:
-            printf("setting output to zero\n")
-
-            error = DAQmxWriteAnalogF64(gWriteTask,50, True,10.0,
-                                        DAQmx_Val_GroupByChannel,
-                                        wa,
-                                        &samplesWritten, NULL)
-
-            CHKng(error)
-            # try a quick stop/start
-            DAQmxStopTask  ( gWriteTask)
-            CHKng(DAQmxStartTask(gWriteTask))
-            printf("WriteAnalogF64 written: %d, error=%d\n", samplesWritten, error )
-        printf("sending stop\n")
-        CHKng(DAQmxStopTask  ( taskHandle))
-        if gWriteTask:
-            error = CHKng(DAQmxStopTask  ( gWriteTask))
-
-        printf("done sending stop error=%d\n", error)
-        
-
-    return error
-
-
-    
-cdef int32 every_n_python_cb(TaskHandle taskHandle, int32 eventType, uInt32 nSamples, void *callbackData) with gil:
-    # need the gil because using a python object, will get uninformative crash if you forget
-    printf("inside every_n_python_cb: %d, %d\n", nSamples, eventType)
-    # callbackData should be a python function cast to void*
-    (<object>callbackData)() # does this need to be an object ptr?
-    printf("did callback every_n_python_cb\n")
-    return 0
-
-
-#MemmapArrFloat64:
-#    float64 *data
-#    [0] -> maxlength
-#    [1] -> current used
-#    [2-4] -> user data
-#    [5] -> array data starts
-
-    
- 
-cdef int32 every_n_readto_memmap_cb(TaskHandle taskHandle, int32 eventType, uInt32 nSamples, void *callbackData) nogil:
-     """ requires that the callbackData is a pointer to a  float64 (mmapped) array"""
-     
-     cdef:
-         float64 *arrp = <float64*>callbackData
-         float64 *datap = arrp+5
-         uInt32  arrsize = <uInt32>arrp[0] # force it down
-         int32 res
-         int32 error =0
-         int32 readAI=0
-
-     printf("arrsize: %d. saw nSamples %d\n", arrsize, nSamples)
-     res=DAQmxReadAnalogF64(taskHandle,nSamples, #num samples per channel
-                            10.0,#timeout
-                            DAQmx_Val_GroupByChannel,
-                            datap,
-                            arrsize,
-                            &readAI, NULL)
-     printf("read %d\n", readAI)
-     arrp[1] = readAI
-     # hidden info
-     arrp[2] += 1.0
-     printf("mmap_arr read[%f] data[0]: %f\n", arrp[2], datap[0])
-     return res
-
-
-class ContAIOWithNCallback(object):
-    """single channel chanN analog input and output
-    outputwaveform and inputbuffer and numpy arrays dtype float64 """
-    def __init__(self, chanN, c_np.ndarray[c_np.float64_t,ndim=1] outputwaveform, c_np.ndarray inputbuffer, sampleRate, N):
-        self.chanN = chanN
-        self.outputwaveform = outputwaveform
-        self.inputbuffer = inputbuffer
-        self.samplerate = sampleRate
-        self.N = N # check back every N samples
-        self.periodLength = len(outputwaveform)
-
-    def setup(self):
-        cdef TaskHandle aitask, aotask
-        cdef int32 res
-        cdef char trigName[256]
-        name = 'testname'
-        cdef uInt64 periodLength=self.periodLength
-        
-        res = 0
-        # analog in task first
-        res = DAQmxCreateTask(name, &aitask)
-        CHK(DAQmxCreateAIVoltageChan(aitask,"Dev1/ai0","",AcqMode,-10.0,10.0,DAQmx_Val_Volts,NULL))
-
-        CHK(DAQmxCfgSampClkTiming(aitask, "", self.samplerate,DAQmx_Val_Rising,DAQmx_Val_ContSamps, periodLength))
-
-        # now setup the output task 
-        CHK (GetTerminalNameWithDevPrefix(aitask,"ai/SampleClock",trigName)) #task,terminalName, triggerName
-        print "trigName:", trigName
-        CHK (DAQmxCreateTask("",&aotask))
-        CHK (DAQmxCreateAOVoltageChan(aotask,"Dev1/ao0","",-10.0,10.0, DAQmx_Val_Volts, NULL))
-
-        CHK (DAQmxCfgSampClkTiming(aotask,trigName,self.samplerate,DAQmx_Val_Rising,DAQmx_Val_ContSamps, periodLength))
-
-        CHK (DAQmxRegisterEveryNSamplesEvent(aitask,DAQmx_Val_Acquired_Into_Buffer,periodLength,0,<DAQmxEveryNSamplesEventCallbackPtr>print_every_n_cb,NULL))
-	# CHK (DAQmxRegisterDoneEvent(aitask,0,DoneCallback,NULL));
-
-        #CHK (DAQmxWriteAnalogF64(aotask,periodLength, 0,10,DAQmx_Val_GroupByChannel,
-	#	&(outputsamples[0]), &(sampleswritten[0]), NULL));
-
-        self.aitask = aitask
-        self.aotask = aotask
-
-    def setup2(self, pycall):
-        """try using a python function as a callback with a shim"""
-        cdef TaskHandle aitask, aotask
-        cdef int32 res
-        cdef char trigName[256]
-        name = 'testname'
-        cdef uInt64 periodLength=self.periodLength
-        
-        res = 0
-        # analog in task first
-        res = DAQmxCreateTask(name, &aitask)
-        CHK(DAQmxCreateAIVoltageChan(aitask,"Dev1/ai0","",AcqMode,-10.0,10.0,DAQmx_Val_Volts,NULL))
-
-        CHK(DAQmxCfgSampClkTiming(aitask, "", self.samplerate,DAQmx_Val_Rising,DAQmx_Val_ContSamps, periodLength))
-
-        # now setup the output task 
-        CHK (GetTerminalNameWithDevPrefix(aitask,"ai/SampleClock",trigName)) #task,terminalName, triggerName
-        print "trigName:", trigName
-        CHK(DAQmxCreateTask("",&aotask))
-        CHK(DAQmxCreateAOVoltageChan(aotask,"Dev1/ao0","",-10.0,10.0, DAQmx_Val_Volts, NULL))
-
-        CHK(DAQmxCfgSampClkTiming(aotask,trigName,self.samplerate,DAQmx_Val_Rising,DAQmx_Val_ContSamps, periodLength))
-
-        
-        CHK(DAQmxRegisterEveryNSamplesEvent(
-            aitask,
-            DAQmx_Val_Acquired_Into_Buffer,
-            periodLength,
-            0, # options 0-> in same thread
-            <DAQmxEveryNSamplesEventCallbackPtr>every_n_python_cb,
-            (<void*>pycall) ))
-        
-	# CHK (DAQmxRegisterDoneEvent(aitask,0,DoneCallback,NULL));
-
-        #CHK (DAQmxWriteAnalogF64(aotask,periodLength, 0,10,DAQmx_Val_GroupByChannel,
-	#	&(outputsamples[0]), &(sampleswritten[0]), NULL));
-
-        self.aitask = aitask
-        self.aotask = aotask
-
-
-    def setup3(self):
-        """this setup looks at using a shared global integer pointer to pass data into the every n callback function"""
-        cdef TaskHandle aitask, aotask
-        cdef int32 res
-        cdef char trigName[256]
-        name = 'testname'
-        cdef int32 sampleswritten=0
-        cdef uInt64 periodLength=self.periodLength
-
-        printf("periodLength: %d\n", periodLength)
-        
-        res = 0
-        
-        # analog in task first
-        res = DAQmxCreateTask(name, &aitask)
-        CHK(DAQmxCreateAIVoltageChan(aitask,"Dev1/ai0","",AcqMode,-10.0,10.0,DAQmx_Val_Volts,NULL))
-
-        CHK(DAQmxCfgSampClkTiming(aitask, "", self.samplerate,DAQmx_Val_Rising,DAQmx_Val_ContSamps, periodLength))
-
-        # now setup the output task 
-        CHK (GetTerminalNameWithDevPrefix(aitask,"ai/SampleClock",trigName)) #task,terminalName, triggerName
-        print "trigName:", trigName
-        CHK (DAQmxCreateTask("",&aotask))
-        CHK (DAQmxCreateAOVoltageChan(aotask,"Dev1/ao0","",-10.0,10.0, DAQmx_Val_Volts, NULL))
-
-        CHK (DAQmxCfgSampClkTiming(aotask,trigName,self.samplerate,DAQmx_Val_Rising,DAQmx_Val_ContSamps, periodLength))
-
-        # this works
-        # CHK (DAQmxRegisterEveryNSamplesEvent(aitask,DAQmx_Val_Acquired_Into_Buffer,periodLength,0,<DAQmxEveryNSamplesEventCallbackPtr>print_every_n_cb,NULL))
-        CHK (DAQmxRegisterEveryNSamplesEvent(aitask,DAQmx_Val_Acquired_Into_Buffer,periodLength,0,<DAQmxEveryNSamplesEventCallbackPtr>print_every_n_sharedvar_cb, <void*>p_gIntVar ))
-	# CHK (DAQmxRegisterDoneEvent(aitask,0,DoneCallback,NULL));
-
-        
-        # DAQmxWriteAnalogF64(AOtaskHandle, 1000, FALSE, 10.0, DAQmx_Val_GroupByChannel, AOdata, NULL, NULL))
-        print self.outputwaveform.dtype, self.outputwaveform
-
-        cdef c_np.ndarray contarr = self.outputwaveform  # demand only continuous array?
-        self.contarr=contarr 
-        cdef c_np.float64_t* odataptr = <c_np.float64_t*> contarr.data
-        cdef double f64[10]
-        for ii in range(10):
-            f64[ii] = ii
-        for ii in range(50):
-            printf("%f ",odataptr[ii])
-            
-        printf("data pointer: %p\n", odataptr)
-
-        CHK (DAQmxWriteAnalogF64(aotask,periodLength, False,10.0,
-                                 DAQmx_Val_GroupByChannel,
-                                 odataptr,
-                                 NULL, NULL));
-
-        self.aitask = aitask
-        self.aotask = aotask
-
-
-    def setup4(self):
-        """what does this do
-        - cb uses a global shared int pointer"""
-        cdef TaskHandle aitask
-        cdef int32 res
-        cdef char trigName[256]
-        name = 'testname'
-        cdef int32 sampleswritten=0
-        cdef uInt64 periodLength=self.periodLength
-
-        printf("periodLength: %d\n", periodLength)
-        
-        res = 0
-        
-        # analog in task first
-        res = DAQmxCreateTask(name, &aitask)
-        CHK(DAQmxCreateAIVoltageChan(aitask,"Dev1/ai0","",AcqMode,-10.0,10.0,DAQmx_Val_Volts,NULL))
-
-        CHK(DAQmxCfgSampClkTiming(aitask, "", self.samplerate,DAQmx_Val_Rising,DAQmx_Val_ContSamps, periodLength))
-
-        # now setup the output task 
-        CHK (GetTerminalNameWithDevPrefix(aitask,"ai/SampleClock",trigName)) #task,terminalName, triggerName
-        print "trigName:", trigName
-        CHK (DAQmxCreateTask("",&gWriteTask))
-        CHK (DAQmxCreateAOVoltageChan(gWriteTask,"Dev1/ao0","",-10.0,10.0, DAQmx_Val_Volts, NULL))
-
-
-        CHK (DAQmxCfgSampClkTiming(gWriteTask,trigName,self.samplerate,DAQmx_Val_Rising,DAQmx_Val_ContSamps, periodLength))
-        # this works
-
-        CHK (DAQmxRegisterEveryNSamplesEvent(aitask,DAQmx_Val_Acquired_Into_Buffer,periodLength,0,<DAQmxEveryNSamplesEventCallbackPtr>print_every_n_sharedvar_stop_cb, <void*>p_gIntVar ))
-        
-        # DAQmxWriteAnalogF64(AOtaskHandle, 1000, FALSE, 10.0, DAQmx_Val_GroupByChannel, AOdata, NULL, NULL))
-        print self.outputwaveform.dtype, self.outputwaveform
-
-        cdef c_np.ndarray contarr = self.outputwaveform  # demand only continuous array?
-        self.contarr=contarr 
-        cdef c_np.float64_t* odataptr = <c_np.float64_t*> contarr.data
-        cdef double f64[10]
-        for ii in range(10):
-            f64[ii] = ii
-        for ii in range(50):
-            printf("%f ",odataptr[ii])
-            
-        printf("data pointer: %p\n", odataptr)
-
-        CHK (DAQmxWriteAnalogF64(gWriteTask,periodLength, False,10.0,
-                                 DAQmx_Val_GroupByChannel,
-                                 odataptr,
-                                 NULL, NULL));
-
-        self.aitask = aitask
-        self.aotask = <long>  gWriteTask
-
-
-
-
-    def setup_mmap_cb(self, c_np.ndarray[c_np.float64_t,ndim=1,mode='c'] sp_mmap_arr):
-        """
-        setup a cython callback that uses a mmapp'ed array
-        mode='c' is there for PYBUF_C_CONTIGUOUS assertion otherwise, strided is ok"""
-        cdef TaskHandle aitask, aotask
-        cdef int32 res
-        cdef char trigName[256]
-        name = 'testname'
-        cdef uInt64 periodLength=self.periodLength
-        
-        res = 0
-        # analog in task first
-        res = DAQmxCreateTask(name, &aitask)
-        CHK(DAQmxCreateAIVoltageChan(aitask,"Dev1/ai0","",AcqMode,-10.0,10.0,DAQmx_Val_Volts,NULL))
-
-        CHK(DAQmxCfgSampClkTiming(aitask, "", self.samplerate,DAQmx_Val_Rising,DAQmx_Val_ContSamps, periodLength))
-
-        # now setup the output task 
-        CHK (GetTerminalNameWithDevPrefix(aitask,"ai/SampleClock",trigName)) #task,terminalName, triggerName
-        print "trigName:", trigName
-        CHK (DAQmxCreateTask("",&aotask))
-        CHK (DAQmxCreateAOVoltageChan(aotask,"Dev1/ao0","",-10.0,10.0, DAQmx_Val_Volts, NULL))
-
-        CHK (DAQmxCfgSampClkTiming(aotask,trigName,self.samplerate,DAQmx_Val_Rising,DAQmx_Val_ContSamps, periodLength))
-
-        # CHK (DAQmxRegisterEveryNSamplesEvent(aitask,DAQmx_Val_Acquired_Into_Buffer,periodLength,0,<DAQmxEveryNSamplesEventCallbackPtr>print_every_n_cb,NULL))
-        
-        # try to switch to this in a sec
-        CHK(DAQmxRegisterEveryNSamplesEvent(
-             aitask,
-             DAQmx_Val_Acquired_Into_Buffer,
-             periodLength,
-	     0, # options 0-> in same thread
-             <DAQmxEveryNSamplesEventCallbackPtr>every_n_readto_memmap_cb,
-	     <void*>sp_mmap_arr.data))
-
-	# CHK (DAQmxRegisterDoneEvent(aitask,0,DoneCallback,NULL));
-
-        #CHK (DAQmxWriteAnalogF64(aotask,periodLength, 0,10,DAQmx_Val_GroupByChannel,
-	#	&(outputsamples[0]), &(sampleswritten[0]), NULL));
-
-        self.aitask = aitask
-        self.aotask = aotask
-
-
-    def setup_mmap_cb_otherthread(self, c_np.ndarray[c_np.float64_t,ndim=1,mode='c'] sp_mmap_arr):
-        """just like setup_mmap_cb except registered to be called in a different thread"""
-        cdef TaskHandle aitask, aotask
-        cdef int32 res
-        cdef char trigName[256]
-        name = 'testname'
-        cdef uInt64 periodLength=self.periodLength
-        
-        res = 0
-        # analog in task first
-        res = DAQmxCreateTask(name, &aitask)
-        CHK(DAQmxCreateAIVoltageChan(aitask,"Dev1/ai0","",AcqMode,-10.0,10.0,DAQmx_Val_Volts,NULL))
-
-        CHK(DAQmxCfgSampClkTiming(aitask, "", self.samplerate,DAQmx_Val_Rising,DAQmx_Val_ContSamps, periodLength))
-
-        # now setup the output task 
-        CHK (GetTerminalNameWithDevPrefix(aitask,"ai/SampleClock",trigName)) #task,terminalName, triggerName
-        print "trigName:", trigName
-        CHK (DAQmxCreateTask("",&aotask))
-        CHK (DAQmxCreateAOVoltageChan(aotask,"Dev1/ao0","",-10.0,10.0, DAQmx_Val_Volts, NULL))
-
-        CHK (DAQmxCfgSampClkTiming(aotask,trigName,self.samplerate,DAQmx_Val_Rising,DAQmx_Val_ContSamps, periodLength))
-
-        # CHK (DAQmxRegisterEveryNSamplesEvent(aitask,DAQmx_Val_Acquired_Into_Buffer,periodLength,0,<DAQmxEveryNSamplesEventCallbackPtr>print_every_n_cb,NULL))
-        
-        # try to switch to this in a sec
-        CHK(DAQmxRegisterEveryNSamplesEvent(
-             aitask,
-             DAQmx_Val_Acquired_Into_Buffer,
-             periodLength,
-	     1, # options 0-> in same thread
-             <DAQmxEveryNSamplesEventCallbackPtr>every_n_readto_memmap_cb,
-	     <void*>sp_mmap_arr.data))
-
-	# CHK (DAQmxRegisterDoneEvent(aitask,0,DoneCallback,NULL));
-
-        #CHK (DAQmxWriteAnalogF64(aotask,periodLength, 0,10,DAQmx_Val_GroupByChannel,
-	#	&(outputsamples[0]), &(sampleswritten[0]), NULL));
-
-        self.aitask = aitask
-        self.aotask = aotask
-
-        
-
-
-    def start(self):
-        self.running = True
-        CHK (DAQmxStartTask(self.aitask))
-        CHK (DAQmxStartTask(self.aotask))
-        print "Acquiring samples continuously. Press Enter to interrupt"
-        print "\nRead:\tAI\tAO\tTotal:\tAI\tDI\n"
-
-    def stop(self):
-        if  self.running == True:
-            if self.aitask: CHK(DAQmxStopTask(self.aitask))
-            if self.aotask: CHK(DAQmxStopTask(self.aotask))
-        self.running=False
-        
-    def clear(self):
-        if self.running:
-            self.stop()
-        if self.aitask:
-            if self.aitask: DAQmxClearTask(self.aitask)
-            self.aitask =0
-        if self.aotask:
-            if self.aotask: DAQmxClearTask(self.aotask)
-            self.aotask=0
-            gWriteTaskPtr=0
-
-        
-             
-        
-        
-
-        
-    
-
-
-    
-    
+"""
+A place to test how to use cython and DAQmx
+
+tests are in test_daqmxcalls.py
+
+test1() and test2()
+-------------------
+  smoke tests to create tasks
+
+test3(): 
+--------
+  the basic ideas behind the callback function for continuous analog input
+  just prints out the bit
+
+test4():
+--------
+  is supposed to allow for a python function as the callback but I'm not sure if it is working
+
+test5():  
+--------
+is to memmap a file 'testmmap.dat' 
+every N samples, a dma read to that target is performed placing the length of the read
+into the first point of thearray
+
+test6(): like test5 but callback runs in another thread per DAQmxRegisterxxx
+
+
+Needed: cython compatible queue or signal to tell other parts of
+program to do things from a callaback.  Then is then used to notifed
+subscribing processes that they can know to re-read the memmap'd data.
+
+"""
+# see basic_numpy_to_c.pyx for reference
+# still in learning phase
+
+
+
+from stdlib cimport *
+from stdio cimport *
+
+import numpy 
+cimport numpy as c_np
+
+from nidaqmx cimport *
+
+# now write declaratios to DAQmx
+
+# probably should declare this public api and move to nidaqmx.pyx /pxd
+
+# cdef int32 GetTerminalNameWithDevPrefix(TaskHandle taskHandle, char terminalName[],
+#                                         char triggerName[]) :
+#     """leave with gil for now"""
+#     cdef:
+#         int32	error=0
+#         char	device[256]
+#         int32	productCategory
+#         uInt32	numDevices,i=1
+#         uInt32  nameIndx=0
+
+#     # translated from C--wow once I understand what's going on here this could really use a cleanup
+
+
+#     CHK(DAQmxGetTaskNumDevices(taskHandle,&numDevices))
+#     # print 'numDevices:', numDevices
+#     while i<=numDevices:
+#         CHK (DAQmxGetNthTaskDevice(taskHandle,i,device,256))
+#         # print "device: ", device
+#         i+=1
+#         CHK (DAQmxGetDevProductCategory(device,&productCategory))
+#         if (productCategory!=DAQmx_Val_CSeriesModule) and (productCategory!=DAQmx_Val_SCXIModule) :
+#             triggerName[nameIndx] = '/'
+#             nameIndx += 1
+#             strcat(strcat(strcpy(&triggerName[nameIndx],device),"/"),terminalName)
+#             # print "triggerName, device, terminalName", triggerName, device, terminalName
+#             break
+
+#     return error
+######################################################################################
+# configuration
+######################################################################################
+
+# AcqMode
+# for USB, use:
+# for PCI use DAQmx_Val_NRSE
+
+AcqMode=DAQmx_Val_RSE # one of DAQmx_Val_NRSE, DAQmx_Val_RSE or differential
+
+### globals ###
+cdef int gIntVar=1
+cdef int* p_gIntVar= &(gIntVar)
+cdef TaskHandle  gWriteTask=0
+cdef TaskHandle* gWriteTaskPtr=NULL
+
+# functions meant to communicate into clevel stuff from python
+
+def set_global_int_var(newval):
+    print "before: ", gIntVar
+    # assert type(newval) == type(1)
+    # note: it doesn't work to simply assign to gIntVar=newval
+    # in the code, it seems like it must be creating a temporary local variable in
+    # the function so it doesn't affect the global gIntVar
+    p_gIntVar[0] = <int> newval
+    print "after: ", gIntVar
+    return 0
+
+cpdef int get_global_int_var():
+    return gIntVar
+
+def create_special_memmap_ndarray(filename, N):
+    """
+    create a float64 memmapped array that also stores it's own
+    [0] = maximum length
+    [1] = used length
+    [2-4] -> user data
+    [5] -> array data starts
+
+    within the shared array itself
+    actual data starts at offset location mm[5]
+    """
+    mm = numpy.memmap(filename, dtype='float64', mode='w+', shape=(N+5,))
+    mm[0] = N
+    mm[1] = 0
+    return mm
+
+def createTask(name):
+    cdef TaskHandle task
+    cdef int32 res
+    res = 0
+    res = DAQmxCreateTask(name, &task)
+    return res
+
+cdef char gErrbuf[1000]  # these are static by default
+cdef unsigned int gErrbufSize = 1000
+cdef float64 g_aiData[10000]
+
+cpdef CHK(int32 err):
+    """a simple error checking routine, needs gil because raises python exception"""
+    if err < 0:
+        DAQmxGetErrorString(err,gErrbuf,gErrbufSize)
+        raise RuntimeError('nidaq call failed with error %d: %s'%(err,repr(gErrbuf)))
+
+cdef int32 CHKng(int32 err) nogil:
+    """
+    a simple error checking routine, avoid raising python exception
+    so can be nogil
+    """
+    if err < 0:
+        DAQmxGetErrorString(err,gErrbuf,gErrbufSize)
+        printf("nidaq call failed with error %d: %s", err,gErrbuf)
+    if err > 0:
+        DAQmxGetErrorString(err,gErrbuf,gErrbufSize)
+        printf("nidaq call warning %d: %s", err,gErrbuf)
+
+    return err
+
+cdef int32 print_every_n_cb(TaskHandle taskHandle, int32 eventType, uInt32 nSamples, void *callbackData) nogil:
+    # first try
+    cdef int32 error =0
+    cdef int32 readAI=0
+    cdef int32 ii=0
+    cdef int32 res
+    cdef int Nsamples=50
+
+
+    printf("In callback-nSamples: %d", nSamples)
+    res=DAQmxReadAnalogF64(taskHandle,nSamples, #num samples per channel
+                           10.0,DAQmx_Val_GroupByChannel,g_aiData,10000,&readAI,NULL)
+    printf("read %d - data:", readAI)
+    for ii from 0 <= ii < Nsamples:  # pyrex style loop
+        printf("%f ", g_aiData[ii])
+    printf("\n")
+
+
+    return res
+
+## callback functions: it's not clear what python functions you can call
+cdef int32 print_every_n_sharedvar_cb(TaskHandle taskHandle, int32 eventType, uInt32 nSamples, void *callbackData) nogil:
+    # first try
+    cdef int error =0
+    cdef int* sharedptr=<int*>callbackData
+
+    printf("callback shared: %d\n", sharedptr[0])
+
+
+    return error
+
+
+cdef int32 print_every_n_sharedvar_stop_cb(TaskHandle taskHandle, int32 eventType, uInt32 nSamples, void *callbackData) nogil:
+    # first try
+    # some interesting results, without stoppping task, don't see to reach whole thing
+    # if first stop gWriteTask, then write stuff,see 25ms delay
+    cdef int error =0
+    cdef int* sharedptr=<int*>callbackData
+    cdef float64 wa[100]
+    cdef int32 samplesWritten=0
+    
+    printf("callback shared: %d\n", sharedptr[0])
+    if sharedptr[0] == 0:
+        printf("trying to stop\n")
+
+        for error from 0 <= error < 100: # for ii from 0 <= ii < Nsamples:
+            wa[error] = -2.0
+        error =0
+        printf("wa[10]=%f\n", wa[10])
+
+        if gWriteTask:
+            printf("setting output to zero\n")
+
+            error = DAQmxWriteAnalogF64(gWriteTask,50, True,10.0,
+                                        DAQmx_Val_GroupByChannel,
+                                        wa,
+                                        &samplesWritten, NULL)
+
+            CHKng(error)
+            # try a quick stop/start
+            DAQmxStopTask  ( gWriteTask)
+            CHKng(DAQmxStartTask(gWriteTask))
+            printf("WriteAnalogF64 written: %d, error=%d\n", samplesWritten, error )
+        printf("sending stop\n")
+        CHKng(DAQmxStopTask  ( taskHandle))
+        if gWriteTask:
+            error = CHKng(DAQmxStopTask  ( gWriteTask))
+
+        printf("done sending stop error=%d\n", error)
+        
+
+    return error
+
+
+    
+cdef int32 every_n_python_cb(TaskHandle taskHandle, int32 eventType, uInt32 nSamples, void *callbackData) with gil:
+    # need the gil because using a python object, will get uninformative crash if you forget
+    printf("inside every_n_python_cb: %d, %d\n", nSamples, eventType)
+    # callbackData should be a python function cast to void*
+    (<object>callbackData)() # does this need to be an object ptr?
+    printf("did callback every_n_python_cb\n")
+    return 0
+
+
+#MemmapArrFloat64:
+#    float64 *data
+#    [0] -> maxlength
+#    [1] -> current used
+#    [2-4] -> user data
+#    [5] -> array data starts
+
+    
+ 
+cdef int32 every_n_readto_memmap_cb(TaskHandle taskHandle, int32 eventType, uInt32 nSamples, void *callbackData) nogil:
+     """ requires that the callbackData is a pointer to a  float64 (mmapped) array"""
+     
+     cdef:
+         float64 *arrp = <float64*>callbackData
+         float64 *datap = arrp+5
+         uInt32  arrsize = <uInt32>arrp[0] # force it down
+         int32 res
+         int32 error =0
+         int32 readAI=0
+
+     printf("arrsize: %d. saw nSamples %d\n", arrsize, nSamples)
+     res=DAQmxReadAnalogF64(taskHandle,nSamples, #num samples per channel
+                            10.0,#timeout
+                            DAQmx_Val_GroupByChannel,
+                            datap,
+                            arrsize,
+                            &readAI, NULL)
+     printf("read %d\n", readAI)
+     arrp[1] = readAI
+     # hidden info
+     arrp[2] += 1.0
+     printf("mmap_arr read[%f] data[0]: %f\n", arrp[2], datap[0])
+     return res
+
+
+class ContAIOWithNCallback(object):
+    """single channel chanN analog input and output
+    outputwaveform and inputbuffer and numpy arrays dtype float64 """
+    def __init__(self, chanN, c_np.ndarray[c_np.float64_t,ndim=1] outputwaveform, c_np.ndarray inputbuffer, sampleRate, N):
+        self.chanN = chanN
+        self.outputwaveform = outputwaveform
+        self.inputbuffer = inputbuffer
+        self.samplerate = sampleRate
+        self.N = N # check back every N samples
+        self.periodLength = len(outputwaveform)
+
+    def setup(self):
+        cdef TaskHandle aitask, aotask
+        cdef int32 res
+        cdef char trigName[256]
+        name = 'testname'
+        cdef uInt64 periodLength=self.periodLength
+        
+        res = 0
+        # analog in task first
+        res = DAQmxCreateTask(name, &aitask)
+        CHK(DAQmxCreateAIVoltageChan(aitask,"Dev1/ai0","",AcqMode,-10.0,10.0,DAQmx_Val_Volts,NULL))
+
+        CHK(DAQmxCfgSampClkTiming(aitask, "", self.samplerate,DAQmx_Val_Rising,DAQmx_Val_ContSamps, periodLength))
+
+        # now setup the output task
+        trigName.value = r'Dev1/ai/SampleClock'
+        # CHK (GetTerminalNameWithDevPrefix(aitask,"ai/SampleClock",trigName)) #task,terminalName, triggerName
+        print "trigName:", trigName
+        CHK (DAQmxCreateTask("",&aotask))
+        CHK (DAQmxCreateAOVoltageChan(aotask,"Dev1/ao0","",-10.0,10.0, DAQmx_Val_Volts, NULL))
+
+        CHK (DAQmxCfgSampClkTiming(aotask,trigName,self.samplerate,DAQmx_Val_Rising,DAQmx_Val_ContSamps, periodLength))
+
+        CHK (DAQmxRegisterEveryNSamplesEvent(aitask,DAQmx_Val_Acquired_Into_Buffer,periodLength,0,<DAQmxEveryNSamplesEventCallbackPtr>print_every_n_cb,NULL))
+	# CHK (DAQmxRegisterDoneEvent(aitask,0,DoneCallback,NULL));
+
+        #CHK (DAQmxWriteAnalogF64(aotask,periodLength, 0,10,DAQmx_Val_GroupByChannel,
+	#	&(outputsamples[0]), &(sampleswritten[0]), NULL));
+
+        self.aitask = aitask
+        self.aotask = aotask
+
+    def setup2(self, pycall):
+        """try using a python function as a callback with a shim"""
+        cdef TaskHandle aitask, aotask
+        cdef int32 res
+        cdef char trigName[256]
+        name = 'testname'
+        cdef uInt64 periodLength=self.periodLength
+        
+        res = 0
+        # analog in task first
+        res = DAQmxCreateTask(name, &aitask)
+        CHK(DAQmxCreateAIVoltageChan(aitask,"Dev1/ai0","",AcqMode,-10.0,10.0,DAQmx_Val_Volts,NULL))
+
+        CHK(DAQmxCfgSampClkTiming(aitask, "", self.samplerate,DAQmx_Val_Rising,DAQmx_Val_ContSamps, periodLength))
+
+        # now setup the output task 
+        # CHK (GetTerminalNameWithDevPrefix(aitask,"ai/SampleClock",trigName)) #task,terminalName, triggerName
+        print "trigName:", trigName
+        CHK(DAQmxCreateTask("",&aotask))
+        CHK(DAQmxCreateAOVoltageChan(aotask,"Dev1/ao0","",-10.0,10.0, DAQmx_Val_Volts, NULL))
+
+        CHK(DAQmxCfgSampClkTiming(aotask,trigName,self.samplerate,DAQmx_Val_Rising,DAQmx_Val_ContSamps, periodLength))
+
+        
+        CHK(DAQmxRegisterEveryNSamplesEvent(
+            aitask,
+            DAQmx_Val_Acquired_Into_Buffer,
+            periodLength,
+            0, # options 0-> in same thread
+            <DAQmxEveryNSamplesEventCallbackPtr>every_n_python_cb,
+            (<void*>pycall) ))
+        
+	# CHK (DAQmxRegisterDoneEvent(aitask,0,DoneCallback,NULL));
+
+        #CHK (DAQmxWriteAnalogF64(aotask,periodLength, 0,10,DAQmx_Val_GroupByChannel,
+	#	&(outputsamples[0]), &(sampleswritten[0]), NULL));
+
+        self.aitask = aitask
+        self.aotask = aotask
+
+
+    def setup3(self):
+        """this setup looks at using a shared global integer pointer to pass data into the every n callback function"""
+        cdef TaskHandle aitask, aotask
+        cdef int32 res
+        cdef char trigName[256]
+        name = 'testname'
+        cdef int32 sampleswritten=0
+        cdef uInt64 periodLength=self.periodLength
+
+        printf("periodLength: %d\n", periodLength)
+        
+        res = 0
+        
+        # analog in task first
+        res = DAQmxCreateTask(name, &aitask)
+        CHK(DAQmxCreateAIVoltageChan(aitask,"Dev1/ai0","",AcqMode,-10.0,10.0,DAQmx_Val_Volts,NULL))
+
+        CHK(DAQmxCfgSampClkTiming(aitask, "", self.samplerate,DAQmx_Val_Rising,DAQmx_Val_ContSamps, periodLength))
+
+        # now setup the output task 
+        trigName.value = r'Dev1/ai/SampleClock'
+        # CHK (GetTerminalNameWithDevPrefix(aitask,"ai/SampleClock",trigName)) #task,terminalName, triggerName
+        print "trigName:", trigName
+        CHK (DAQmxCreateTask("",&aotask))
+        CHK (DAQmxCreateAOVoltageChan(aotask,"Dev1/ao0","",-10.0,10.0, DAQmx_Val_Volts, NULL))
+
+        CHK (DAQmxCfgSampClkTiming(aotask,trigName,self.samplerate,DAQmx_Val_Rising,DAQmx_Val_ContSamps, periodLength))
+
+        # this works
+        # CHK (DAQmxRegisterEveryNSamplesEvent(aitask,DAQmx_Val_Acquired_Into_Buffer,periodLength,0,<DAQmxEveryNSamplesEventCallbackPtr>print_every_n_cb,NULL))
+        CHK (DAQmxRegisterEveryNSamplesEvent(aitask,DAQmx_Val_Acquired_Into_Buffer,periodLength,0,<DAQmxEveryNSamplesEventCallbackPtr>print_every_n_sharedvar_cb, <void*>p_gIntVar ))
+	# CHK (DAQmxRegisterDoneEvent(aitask,0,DoneCallback,NULL));
+
+        
+        # DAQmxWriteAnalogF64(AOtaskHandle, 1000, FALSE, 10.0, DAQmx_Val_GroupByChannel, AOdata, NULL, NULL))
+        print self.outputwaveform.dtype, self.outputwaveform
+
+        cdef c_np.ndarray contarr = self.outputwaveform  # demand only continuous array?
+        self.contarr=contarr 
+        cdef c_np.float64_t* odataptr = <c_np.float64_t*> contarr.data
+        cdef double f64[10]
+        for ii in range(10):
+            f64[ii] = ii
+        for ii in range(50):
+            printf("%f ",odataptr[ii])
+            
+        printf("data pointer: %p\n", odataptr)
+
+        CHK (DAQmxWriteAnalogF64(aotask,periodLength, False,10.0,
+                                 DAQmx_Val_GroupByChannel,
+                                 odataptr,
+                                 NULL, NULL));
+
+        self.aitask = aitask
+        self.aotask = aotask
+
+
+    def setup4(self):
+        """what does this do
+        - cb uses a global shared int pointer"""
+        cdef TaskHandle aitask
+        cdef int32 res
+        cdef char trigName[256]
+        name = 'testname'
+        cdef int32 sampleswritten=0
+        cdef uInt64 periodLength=self.periodLength
+
+        printf("periodLength: %d\n", periodLength)
+        
+        res = 0
+        
+        # analog in task first
+        res = DAQmxCreateTask(name, &aitask)
+        CHK(DAQmxCreateAIVoltageChan(aitask,"Dev1/ai0","",AcqMode,-10.0,10.0,DAQmx_Val_Volts,NULL))
+
+        CHK(DAQmxCfgSampClkTiming(aitask, "", self.samplerate,DAQmx_Val_Rising,DAQmx_Val_ContSamps, periodLength))
+
+        # now setup the output task 
+        trigName.value = r'Dev1/ai/SampleClock'
+        # CHK (GetTerminalNameWithDevPrefix(aitask,"ai/SampleClock",trigName)) #task,terminalName, triggerName
+        print "trigName:", trigName
+        CHK (DAQmxCreateTask("",&gWriteTask))
+        CHK (DAQmxCreateAOVoltageChan(gWriteTask,"Dev1/ao0","",-10.0,10.0, DAQmx_Val_Volts, NULL))
+
+
+        CHK (DAQmxCfgSampClkTiming(gWriteTask,trigName,self.samplerate,DAQmx_Val_Rising,DAQmx_Val_ContSamps, periodLength))
+        # this works
+
+        CHK (DAQmxRegisterEveryNSamplesEvent(aitask,DAQmx_Val_Acquired_Into_Buffer,periodLength,0,<DAQmxEveryNSamplesEventCallbackPtr>print_every_n_sharedvar_stop_cb, <void*>p_gIntVar ))
+        
+        # DAQmxWriteAnalogF64(AOtaskHandle, 1000, FALSE, 10.0, DAQmx_Val_GroupByChannel, AOdata, NULL, NULL))
+        print self.outputwaveform.dtype, self.outputwaveform
+
+        cdef c_np.ndarray contarr = self.outputwaveform  # demand only continuous array?
+        self.contarr=contarr 
+        cdef c_np.float64_t* odataptr = <c_np.float64_t*> contarr.data
+        cdef double f64[10]
+        for ii in range(10):
+            f64[ii] = ii
+        for ii in range(50):
+            printf("%f ",odataptr[ii])
+            
+        printf("data pointer: %p\n", odataptr)
+
+        CHK (DAQmxWriteAnalogF64(gWriteTask,periodLength, False,10.0,
+                                 DAQmx_Val_GroupByChannel,
+                                 odataptr,
+                                 NULL, NULL));
+
+        self.aitask = aitask
+        self.aotask = <long>  gWriteTask
+
+
+
+
+    def setup_mmap_cb(self, c_np.ndarray[c_np.float64_t,ndim=1,mode='c'] sp_mmap_arr):
+        """
+        setup a cython callback that uses a mmapp'ed array
+        mode='c' is there for PYBUF_C_CONTIGUOUS assertion otherwise, strided is ok"""
+        cdef TaskHandle aitask, aotask
+        cdef int32 res
+        cdef char trigName[256]
+        name = 'testname'
+        cdef uInt64 periodLength=self.periodLength
+        
+        res = 0
+        # analog in task first
+        res = DAQmxCreateTask(name, &aitask)
+        CHK(DAQmxCreateAIVoltageChan(aitask,"Dev1/ai0","",AcqMode,-10.0,10.0,DAQmx_Val_Volts,NULL))
+
+        CHK(DAQmxCfgSampClkTiming(aitask, "", self.samplerate,DAQmx_Val_Rising,DAQmx_Val_ContSamps, periodLength))
+
+        # now setup the output task 
+        trigName.value = r'Dev1/ai/SampleClock'
+        # CHK (GetTerminalNameWithDevPrefix(aitask,"ai/SampleClock",trigName)) #task,terminalName, triggerName
+        print "trigName:", trigName
+        CHK (DAQmxCreateTask("",&aotask))
+        CHK (DAQmxCreateAOVoltageChan(aotask,"Dev1/ao0","",-10.0,10.0, DAQmx_Val_Volts, NULL))
+
+        CHK (DAQmxCfgSampClkTiming(aotask,trigName,self.samplerate,DAQmx_Val_Rising,DAQmx_Val_ContSamps, periodLength))
+
+        # CHK (DAQmxRegisterEveryNSamplesEvent(aitask,DAQmx_Val_Acquired_Into_Buffer,periodLength,0,<DAQmxEveryNSamplesEventCallbackPtr>print_every_n_cb,NULL))
+        
+        # try to switch to this in a sec
+        CHK(DAQmxRegisterEveryNSamplesEvent(
+             aitask,
+             DAQmx_Val_Acquired_Into_Buffer,
+             periodLength,
+	     0, # options 0-> in same thread
+             <DAQmxEveryNSamplesEventCallbackPtr>every_n_readto_memmap_cb,
+	     <void*>sp_mmap_arr.data))
+
+	# CHK (DAQmxRegisterDoneEvent(aitask,0,DoneCallback,NULL));
+
+        #CHK (DAQmxWriteAnalogF64(aotask,periodLength, 0,10,DAQmx_Val_GroupByChannel,
+	#	&(outputsamples[0]), &(sampleswritten[0]), NULL));
+
+        self.aitask = aitask
+        self.aotask = aotask
+
+
+    def setup_mmap_cb_otherthread(self, c_np.ndarray[c_np.float64_t,ndim=1,mode='c'] sp_mmap_arr):
+        """just like setup_mmap_cb except registered to be called in a different thread"""
+        cdef TaskHandle aitask, aotask
+        cdef int32 res
+        cdef char trigName[256]
+        name = 'testname'
+        cdef uInt64 periodLength=self.periodLength
+        
+        res = 0
+        # analog in task first
+        res = DAQmxCreateTask(name, &aitask)
+        CHK(DAQmxCreateAIVoltageChan(aitask,"Dev1/ai0","",AcqMode,-10.0,10.0,DAQmx_Val_Volts,NULL))
+
+        CHK(DAQmxCfgSampClkTiming(aitask, "", self.samplerate,DAQmx_Val_Rising,DAQmx_Val_ContSamps, periodLength))
+
+        # now setup the output task
+        trigName.value = r'Dev1/ai/SampleClock'
+        # CHK (GetTerminalNameWithDevPrefix(aitask,"ai/SampleClock",trigName)) #task,terminalName, triggerName
+        print "trigName:", trigName
+        CHK (DAQmxCreateTask("",&aotask))
+        CHK (DAQmxCreateAOVoltageChan(aotask,"Dev1/ao0","",-10.0,10.0, DAQmx_Val_Volts, NULL))
+
+        CHK (DAQmxCfgSampClkTiming(aotask,trigName,self.samplerate,DAQmx_Val_Rising,DAQmx_Val_ContSamps, periodLength))
+
+        # CHK (DAQmxRegisterEveryNSamplesEvent(aitask,DAQmx_Val_Acquired_Into_Buffer,periodLength,0,<DAQmxEveryNSamplesEventCallbackPtr>print_every_n_cb,NULL))
+        
+        # try to switch to this in a sec
+        CHK(DAQmxRegisterEveryNSamplesEvent(
+             aitask,
+             DAQmx_Val_Acquired_Into_Buffer,
+             periodLength,
+	     1, # options 0-> in same thread
+             <DAQmxEveryNSamplesEventCallbackPtr>every_n_readto_memmap_cb,
+	     <void*>sp_mmap_arr.data))
+
+	# CHK (DAQmxRegisterDoneEvent(aitask,0,DoneCallback,NULL));
+
+        #CHK (DAQmxWriteAnalogF64(aotask,periodLength, 0,10,DAQmx_Val_GroupByChannel,
+	#	&(outputsamples[0]), &(sampleswritten[0]), NULL));
+
+        self.aitask = aitask
+        self.aotask = aotask
+
+        
+
+
+    def start(self):
+        self.running = True
+        CHK (DAQmxStartTask(self.aitask))
+        CHK (DAQmxStartTask(self.aotask))
+        print "Acquiring samples continuously. Press Enter to interrupt"
+        print "\nRead:\tAI\tAO\tTotal:\tAI\tDI\n"
+
+    def stop(self):
+        if  self.running == True:
+            if self.aitask: CHK(DAQmxStopTask(self.aitask))
+            if self.aotask: CHK(DAQmxStopTask(self.aotask))
+        self.running=False
+        
+    def clear(self):
+        if self.running:
+            self.stop()
+        if self.aitask:
+            if self.aitask: DAQmxClearTask(self.aitask)
+            self.aitask =0
+        if self.aotask:
+            if self.aotask: DAQmxClearTask(self.aotask)
+            self.aotask=0
+            gWriteTaskPtr=0
+
+        
+             
+        
+        
+
+        
+    
+
+
+    
+    
File contents unchanged.
-# This clearly compiles with VS 2008, probably would work with mingw32 gcc4.4 too
-from distutils.core import setup
-from distutils.extension import Extension
-from Cython.Distutils import build_ext
-import os
-
-## configuration
-inc_dirs = [r'e:/Python26/Lib/site-packages/numpy/core/include', r'./']
-lib_dirs = [r'./', r'e:/Programs/NationaInstruments/NI-DAQ/DAQmx ANSI C Dev/lib/msvc']
-
-# libs = ['nicaiu'] # worked for mingw
-libs = ['NIDAQmx'] # worked for MSVC 9, maybe mingw too
-
-nidaqmx = Extension("nidaqmx", ["nidaqmx.pyx"],
-                         include_dirs=inc_dirs,
-                         library_dirs=lib_dirs,
-                         libraries=libs)
-
-callbacks =  Extension("callbacks", ["callbacks.pyx"],
-                         include_dirs=inc_dirs,
-                         library_dirs=lib_dirs,
-                         libraries=libs)
-
-ext_modules = [callbacks,
-               Extension("daqmxcalls", ["daqmxcalls.pyx"],
-                         include_dirs=inc_dirs,
-                         library_dirs=lib_dirs,
-                         libraries=libs),
-               Extension("utils", ["utils.pyx"],
-                         include_dirs=inc_dirs,
-                         library_dirs=lib_dirs,
-                         libraries=libs),
-                         
-             ]
-
-setup(
-    author='Chris Lee-Messer',
-    cmdclass = {'build_ext': build_ext},
-    ext_modules = ext_modules,
-
-)
+#!/usr/bin/env python
+# this clearly compiles with VS 2008, probably would work with mingw32 gcc4.4 too
+from distutils.core import setup
+from distutils.extension import Extension
+from Cython.Distutils import build_ext
+import os, sys
+
+## configuration
+print "sys.platform:", sys.platform
+if sys.platform == 'linux2':
+    inc_dirs = [r"/usr/lib/python2.5/site-packages/numpy/core/include",
+               r'/usr/local/natinst/nidaqmx/include', r'.']
+    lib_dirs = [r'/usr/local/lib', r'.']
+    libs = ['nidaqmx','m'] # worked on opensuse 11
+elif sys.platform == 'nt':
+    inc_dirs = [r'e:/Python26/Lib/site-packages/numpy/core/include', r'./']
+    lib_dirs = [r'./', r'e:/Programs/NationaInstruments/NI-DAQ/DAQmx ANSI C Dev/lib/msvc']
+    libs = ['NIDAQmx'] # worked for MSVC 9, maybe mingw too
+    # libs = ['nicaiu'] # worked for mingw
+
+
+
+
+nidaqmx = Extension("nidaqmx", ["nidaqmx.pyx"],
+                         include_dirs=inc_dirs,
+                         library_dirs=lib_dirs,
+                         libraries=libs)
+
+callbacks =  Extension("callbacks", ["callbacks.pyx"],
+                         include_dirs=inc_dirs,
+                         library_dirs=lib_dirs,
+                         libraries=libs)
+
+ext_modules = [callbacks,
+               Extension("daqmxcalls", ["daqmxcalls.pyx"],
+                         include_dirs=inc_dirs,
+                         library_dirs=lib_dirs,
+                         libraries=libs),
+               Extension("utils", ["utils.pyx"],
+                         include_dirs=inc_dirs,
+                         library_dirs=lib_dirs,
+                         libraries=libs),
+                         
+             ]
+
+setup(
+    author='Chris Lee-Messer',
+    cmdclass = {'build_ext': build_ext},
+    ext_modules = ext_modules,
+
+)
-from stdlib cimport *
-from stdio cimport *
-from nidaqmx cimport *
-
-# Static variables ideally
-DEF ERRORBUFSIZE = 1000
-cdef char gErrbuf[ERRORBUFSIZE]  # these are static by default
-cdef unsigned int gErrbufSize = ERRORBUFSIZE # may be able to get this out
-
-
-cpdef CHK(int32 err):
-    """a simple error checking routine, needs gil because raises python exception"""
-    if err < 0:
-        DAQmxGetErrorString(err,gErrbuf,gErrbufSize)
-        raise RuntimeError('nidaq call failed with error %d: %s'%(err,repr(gErrbuf)))
-
-cdef public int32 CHKng(int32 err) nogil:
-    """
-    a simple error checking routine, avoid raising python exception
-    so can be nogil
-    """
-    if err < 0:
-        DAQmxGetErrorString(err,gErrbuf,gErrbufSize)
-        printf("nidaq call failed with error %d: %s", err,gErrbuf)
-    if err > 0:
-        DAQmxGetErrorString(err,gErrbuf,gErrbufSize)
-        printf("nidaq call warning %d: %s", err,gErrbuf)
-
-    return err
-
-
-# probably should declare this public api and move to nidaqmx.pyx /pxd
-cdef public int32 GetTerminalNameWithDevPrefix(TaskHandle taskHandle, char terminalName[],
-                                        char triggerName[]) nogil:
-    """this is based upon the examples in the NI-DAQmx directories"""
-    cdef:
-        int32	error=0
-        char	device[256]
-        int32	productCategory
-        uInt32	numDevices,i=1
-        uInt32  nameIndx=0
-
-    # translated from C--wow once I understand what's going on here this could really use a cleanup
-
-
-    CHKng(DAQmxGetTaskNumDevices(taskHandle,&numDevices))
-    # print 'numDevices:', numDevices
-    while i<=numDevices:
-        CHKng (DAQmxGetNthTaskDevice(taskHandle,i,device,256))
-        # print "device: ", device
-        i+=1
-        CHKng (DAQmxGetDevProductCategory(device,&productCategory))
-        if (productCategory!=DAQmx_Val_CSeriesModule) and (productCategory!=DAQmx_Val_SCXIModule) :
-            triggerName[nameIndx] = '/'
-            nameIndx += 1
-            strcat(strcat(strcpy(&triggerName[nameIndx],device),"/"),terminalName)
-            # print "triggerName, device, terminalName", triggerName, device, terminalName
-            break
-
-    return error
+from stdlib cimport *
+from stdio cimport *
+from nidaqmx cimport *
+
+# Static variables ideally
+DEF ERRORBUFSIZE = 1000
+cdef char gErrbuf[ERRORBUFSIZE]  # these are static by default
+cdef unsigned int gErrbufSize = ERRORBUFSIZE # may be able to get this out
+
+
+cpdef CHK(int32 err):
+    """a simple error checking routine, needs gil because raises python exception"""
+    if err < 0:
+        DAQmxGetErrorString(err,gErrbuf,gErrbufSize)
+        raise RuntimeError('nidaq call failed with error %d: %s'%(err,repr(gErrbuf)))
+
+cdef public int32 CHKng(int32 err) nogil:
+    """
+    a simple error checking routine, avoid raising python exception
+    so can be nogil
+    """
+    if err < 0:
+        DAQmxGetErrorString(err,gErrbuf,gErrbufSize)
+        printf("nidaq call failed with error %d: %s", err,gErrbuf)
+    if err > 0:
+        DAQmxGetErrorString(err,gErrbuf,gErrbufSize)
+        printf("nidaq call warning %d: %s", err,gErrbuf)
+
+    return err
+
+
+IF UNAME_SYSNAME == "Windows":
+    # probably should declare this public api and move to nidaqmx.pyx /pxd
+    cdef public int32 GetTerminalNameWithDevPrefix(TaskHandle taskHandle, char terminalName[],
+                                            char triggerName[]) nogil:
+        """this is based upon the examples in the NI-DAQmx directories"""
+        cdef:
+            int32	error=0
+            char	device[256]
+            int32	productCategory
+            uInt32	numDevices,i=1
+            uInt32  nameIndx=0
+
+        # translated from C--wow once I understand what's going on here this could really use a cleanup
+
+
+        CHKng(DAQmxGetTaskNumDevices(taskHandle,&numDevices))
+        # print 'numDevices:', numDevices
+        while i<=numDevices:
+            CHKng (DAQmxGetNthTaskDevice(taskHandle,i,device,256))
+            # print "device: ", device
+            i+=1
+            CHKng (DAQmxGetDevProductCategory(device,&productCategory))
+            if (productCategory!=DAQmx_Val_CSeriesModule) and (productCategory!=DAQmx_Val_SCXIModule) :
+                triggerName[nameIndx] = '/'
+                nameIndx += 1
+                strcat(strcat(strcpy(&triggerName[nameIndx],device),"/"),terminalName)
+                # print "triggerName, device, terminalName", triggerName, device, terminalName
+                break
+
+        return error