/*******************************************************************************
 *	Da8150.cpp	Da8150 output classes
 *			T.Barnaby,	BEAM Ltd,	2007-01-23
 *******************************************************************************
 */

#include <Da8150.h>
#include <math.h>

#ifdef HAVE_DA8150
#include <da8150_lib.h>
#endif


Da8150::Da8150(){
	osampleRate = 150000000;
	onumChannels = 8;
	ocardNum = 1;
}

Da8150::~Da8150(){
	close();
}

BError Da8150::config(double sampleRate, int numChannels){
	BError			err;

	osampleRate = sampleRate;
	onumChannels = numChannels;
	
	if(osampleRate != 150000000)
		return err.set(1, "Error can only handle a sample rate of 150000000Hz\n");
	
#ifdef HAVE_DA8150
	if(da8150_Open(ocardNum)){
		return err.set(1, "Error unable to open DA8150\n");
	}
	
	da8150_SetClock(ocardNum, 150000000);
#else
	err.set(1, "No DA8150 support");
#endif
	return err;
}

void Da8150::close(){
#ifdef HAVE_DA8150
	da8150_Close(ocardNum);
#endif
}

BError Da8150::expand(BSignalList& sigs, BSignalList& newSigs){
	BError		err;
	BIter		i;
	uint32_t	nr;
	uint32_t	n;
	BSignal		sig;
	uint32_t	id = 0;
	uint32_t	nextId = 0;
	
	newSigs.clear();
	for(sigs.start(i); !sigs.isEnd(i); sigs.next(i)){
		sig = sigs[i];
		nr = sig.numRepeat;
		if(nr){
			nextId = sig.nextId;
		
			while(nr){
				n = nr;
				if(n > 16383)
					n = 16383;

				nr -= n;

				sig.numRepeat = n;
				sig.id = id++;
				if((nextId == 0) && (nr == 0))
					sig.nextId = nextId;
				else
					sig.nextId = id;
				newSigs.append(sig);
			}
		}
		else {
			sig.id = id++;
			if(sig.nextId)
				sig.nextId = id;;
			newSigs.append(sig);
		}
	}
	return err;
}

BError Da8150::output(BSignalList& sigs){
	BError		err;
	BSignalList	newSigs;

	if(err = expand(sigs, newSigs))
		return err;
		
	return rawOutput(newSigs);
}

BError Da8150::rawOutput(BSignalList& sigs){
	BError		err;

#ifdef HAVE_DA8150
	BIter		i;
	int		s;
	int		c;
	Da8150Segment	segs[sigs.number()];
	unsigned int	n;
	uint16_t*	data[sigs.number()];

//	printf("Da8150::rawOutput: %d\n", sigs.number());
	
	for(c = 0; c < 8; c++){
		for(sigs.start(i), n = 0; !sigs.isEnd(i); sigs.next(i), n++){
#ifndef ZAP
			if(c == 0)
				printf("Add DataSegment: %d NumSamples: %d Repeat: %d Next: %d\n", n, sigs[i].numSamples, sigs[i].numRepeat, sigs[i].nextId);
#endif
			data[n] = new uint16_t[sigs[i].numSamples];
			segs[n].segmentNum = sigs[i].id;
			segs[n].data = data[n];
			segs[n].numPoints = sigs[i].numSamples;
			if(n == (sigs.number() - 1))
				segs[n].numLoops = sigs[0].numRepeat;
			else
				segs[n].numLoops = sigs[n+1].numRepeat;
			segs[n].beginPadValue = 2047;
			segs[n].endPadValue = 2047;
			segs[n].trigEnable = 0;
			segs[n].nextSegNum = sigs[i].nextId;

			for(s = 0; s < sigs[i].numSamples; s++){
				data[n][s] = 2047 - short(sigs[i].data[c][s] * 2047.0);
			}
		}
		da8150_CreateSegments(ocardNum, 1 << c, sigs.number(), segs);
		for(n = 0; n < sigs.number(); n++){
			delete [] data[n];
		}
	}

	da8150_SetTriggerMode(ocardNum, D8150_MODE_RUN, D8150_TRIG_POS);
#else
	err.set(1, "No DA8150 support");
#endif
	return err;
}

BError Da8150::output(BSignal& sig){
	BSignalList	sigList;
	
	sigList.append(sig);
	
	return output(sigList);
}
