#ifndef LIBDAQCTL_H
#define LIBDAQCTL_H

struct daqctl {
	/* The below data members are only safe to read in a callback OR when
	 * daqctl_process() is NOT running. (e.g. not safe to read in a signal
	 * handler or in another thread) 
	 *
	 * last_16bit[8] contains the result of a DSP low-pass IIR filter that
	 * uses multiple readings to attempt to interpolate an extra 4 bits.
	 */
	int fd;
	unsigned long long nsamples;
	long long last[16];
	unsigned short last_16bit[8];
	unsigned long long counter[4];
	long long quad[2];

	/* Callback functions: 
	 *   posedge - called when a posedge is detected on a digital input
	 *   negedge - called when a negedge is detected on a digital input
	 *   analog - called for every acquired analog sample channel
	 *   digital - called on every acquired DIO sampling
	 *   digital_change - called whenever a DIO input change is detected
	 */
	void (*posedge)(struct daqctl *, int);
	void (*negedge)(struct daqctl *, int);
	void (*analog)(struct daqctl *, int, int);
	void (*digital)(struct daqctl *, long long);
	void (*digital_change)(struct daqctl *, long long, long long);

	/* Private -- new instances should all start zeroed-out */
	int seq;
	unsigned int chans;
	unsigned int rem;
	unsigned short b[8];
	int bidx;
};

#define PWM_DUTY_PCT(x)	((0xfff * (x) / 100 ) << 1)
#define PWM_DUTY(x) ((x) << 1)
#define PWM_FREQ(x) ((x) << 13)
#define PWM_FREQ_IS_SAMPLERATE (1<<30)
#define PWM_FREQ_NOT_SAMPLERATE (3<<30)

extern int daqctl_connect(char *hostspec, char *args);
extern int daqctl_pwmspec(int sk, char *spec); 
extern int daqctl_setoutput(int sk, int pin, unsigned int val); 
extern int daqctl_process(struct daqctl *d); 
extern int daqctl_flushreq(int sk);
#endif
