Mq4Double MarketInfo(Mq4String symbol, int type)
{
	var symbolObject = GetSymbol(symbol);
	switch (type)
	{
		case MODE_LOW:
			return GetSeries(symbol, PERIOD_D1).Low.LastValue;
		case MODE_HIGH:
			return GetSeries(symbol, PERIOD_D1).High.LastValue;
		case MODE_DIGITS:
			return symbolObject.Digits;
		case MODE_TIME:
			return TimeCurrent();
		case MODE_ASK:
			return symbolObject.Ask;
		case MODE_BID:
			return symbolObject.Bid;
		case MODE_SPREAD:
			return symbolObject.Spread / symbolObject.TickSize;
		case MODE_PROFITCALCMODE:
			return 0;
		case MODE_FREEZELEVEL:
			return 0;
		case MODE_TRADEALLOWED:
			return 1;
		case MODE_POINT:
			return symbolObject.TickSize;
		case MODE_TICKSIZE:
			return symbolObject.TickSize;
		case MODE_SWAPTYPE:
			return 0;
		case MODE_MARGINCALCMODE:
			return 0;
        case MODE_STOPLEVEL:
            return symbolObject.TickSize;    
        case MODE_MINLOT:
            return symbolObject.ToLotsVolume(symbolObject.VolumeMin);    
        case MODE_MAXLOT:
            return symbolObject.ToLotsVolume(symbolObject.VolumeMax);  
        case MODE_LOTSTEP:
            return symbolObject.ToLotsVolume(symbolObject.VolumeStep);   
        case MODE_TICKVALUE:
            return symbolObject.TickValue;    
        case MODE_LOTSIZE:
            return symbolObject.ToNotNormalizedUnitsVolume(1);
        case MODE_MARGINREQUIRED:
            return symbolObject.ToNotNormalizedUnitsVolume(1) / Account.Leverage * symbolObject.Ask * symbolObject.TickValue / symbolObject.TickSize;
	}
	return 0;
}
// TODO: the largest value for series 4000 is 54s which doesn't fit into unsigned long!!!
void Measurement::SetTimebaseInPs(unsigned long picoseconds)
{
	FILE_LOG(logDEBUG3) << "Measurement::SetTimebaseInPs (ps=" << picoseconds << ")";

	unsigned long i, result;

	if(GetSeries() == PICO_6000) {
		// it doesn't go beyond a certain minimum level
		if(picoseconds < 200) {
			picoseconds = 200;
		}
		if(picoseconds < 6400) {
			// it could be round() instead of floor()
			timebase = (unsigned long)floor(log2((double)(picoseconds/200)));
		} else {
			timebase = (unsigned long)(picoseconds/6400+4);
		}
	} else { /* 4223, 4224, 4423, 4424 only */
		if(picoseconds < 12500) {
			picoseconds = 12500;
		}
		if(picoseconds < 100000) {
			timebase = (unsigned long)floor(log2((double)(picoseconds/12500)));
		} else {
			timebase = (unsigned long)(picoseconds/50000+1);
		}
	}
}
// TODO: we might want to use multiple buffers at the same time
void Measurement::WriteDataBin(FILE *f, int channel)
{
	Timing t;
	long size_written;
	int i, j;

	const unsigned int length_datachunk = 1000000;
	char data_8bit[1000000];
	// std::vector<char>data_8bit(1000);

	std::cerr << "Write binary data for channel " << (char)('A'+channel) << " ... ";
	t.Start();
	// TODO: test if file exists
	if(channel < 0 || channel >= GetNumberOfChannels()) {
		throw "You can only write data for channels 0 - (N-1).";
	} else {
		if(GetChannel(channel)->IsEnabled()) {

			/*
			size_written = fwrite(data[channel], sizeof(short), GetLengthFetched(), f);
			// make sure the data is written
			fflush(f);
			if(size_written < GetLengthFetched()) {
				FILE_LOG(logERROR) << "Measurement::WriteDataBin didn't manage to write to file.";
			}*/
			// TODO: if only 8 bits
			int length_fetched   = GetLengthFetched();
			// int length_datachunk = data_8bit.size();
			for(i=0; i<length_fetched; i+=length_datachunk) {
				if(GetSeries() == PICO_6000) {
					for(j=0; j<length_datachunk && i+j<length_fetched; j++) {
						data_8bit[j] = data[channel][i+j] >> 8;
					}
					size_written = fwrite(data_8bit, sizeof(char), j, f);
				} else {
					// TODO: test!!!
					size_written = fwrite(data[channel]+1, sizeof(data[0][0]), j, f);
				}
				fflush(f);
				if(size_written < j) {
					FILE_LOG(logERROR) << "Measurement::WriteDataBin didn't manage to write to file.";
				}
			}
			// size_written = fwrite(data[channel], sizeof(short), GetLengthFetched(), f);
			// make sure the data is written
			// fflush(f);
			// if(size_written < GetLengthFetched()) {
			// 	FILE_LOG(logERROR) << "Measurement::WriteDataBin didn't manage to write to file.";
			// }
		} else {
double Measurement::GetTimebaseInNs()
{
	FILE_LOG(logDEBUG3) << "Measurement::GetTimebaseInNs";

	if(GetSeries() == PICO_6000) {
		if(timebase<6) {
			return 0.2*(1<<timebase);
		} else {
			return (timebase-4.0)*6.4;
		}
	} else {
		if(timebase<4) {
			return 12.5*(1<<timebase);
		} else {
			return (timebase-1.0)*50.0;
		}
	}
	return 0;
}
// this sets the timebase to picoscope
void Measurement::SetTimebaseInPicoscope()
{
	FILE_LOG(logDEBUG3) << "Measurement::SetTimebaseInPicoscope";

	float time_interval_ns;

	// 4000
	if(GetSeries() == PICO_4000) {
		FILE_LOG(logDEBUG2) << "ps4000GetTimebase2(handle=" << GetHandle() << ", timebase=" << GetTimebase() << ", length=" << GetLength() << ", &time_interval_ns, oversample=0, maxSamples=NULL, segmentIndex=0)";
		GetPicoscope()->SetStatus(ps4000GetTimebase2(
			GetHandle(),       // handle
			GetTimebase(),     // timebase
			GetLength(),       // noSamples
			&time_interval_ns, // timeIntervalNanoseconds
			0,                 // oversample (TODO if needed)
			NULL,              // maxSamples - the maximum number of samples available
			0));               // segmentIndex - the index of the memory segment to use
	// 6000
	} else {
		FILE_LOG(logDEBUG2) << "ps6000GetTimebase2(handle=" << GetHandle() << ", timebase=" << GetTimebase() << ", length=" << GetLength() << ", &time_interval_ns, oversample=0, maxSamples=NULL, segmentIndex=0)";
		GetPicoscope()->SetStatus(ps6000GetTimebase2(
			GetHandle(),       // handle
			GetTimebase(),     // timebase
			GetLength(),       // noSamples
			&time_interval_ns, // timeIntervalNanoseconds
			0,                 // oversample (TODO if needed)
			NULL,              // maxSamples - the maximum number of samples available
			0));               // segmentIndex - the index of the memory segment to use
		FILE_LOG(logDEBUG2) << "-> time_interval_ns=" << time_interval_ns << " ns";
	}
	if(GetPicoscope()->GetStatus() != PICO_OK) {
		std::cerr << "Unable to set the requested timebase (" << GetTimebase()
		          << ") and sample number (" << GetLength() << ")" << std::endl;
		throw Picoscope::PicoscopeException(GetPicoscope()->GetStatus());
	}

	std::cerr << "-- Setting timebase; the interval will be " << time_interval_ns << " ns\n";
	timebase_reported_by_osciloscope = (double)time_interval_ns;
}
unsigned long Measurement::GetNextDataBulk()
{
	FILE_LOG(logDEBUG3) << "Measurement::GetNextDataBulk";

	unsigned long i, j, index;
	short *overflow;
	uint32_t traces_asked_for, length_of_trace_fetched;
	// unsigned long length_of_trace_askedfor, length_of_trace_fetched;
	Timing t;

	// std::cerr << "(GetNextDataBulk: " << GetNextIndex() << ", " << GetMaxTracesToFetch() << ")\n";

	// it makes no sense to read any further: we are already at the end
	if(GetNextIndex() >= GetNTraces()) {
		std::cerr << "Stop fetching data from ociloscope." << std::endl;
		return 0UL;
	}

/*
	try {
		for(i=0; i<GetNumberOfChannels(); i++) {
			if(GetChannel(i)->IsEnabled()) {
				delete [] data[i];
				data[i] = new short[GetMaxTracesToFetch()*GetLength()];
			}
		}
	} catch(...) {
		std::cerr << "Unable to allocate memory in Measurement::AllocateMemoryBlock." << std::endl;
		throw;
	}
/**/

	traces_asked_for = GetMaxTracesToFetch();
	if(GetNextIndex() + traces_asked_for > GetNTraces()) {
		traces_asked_for = GetNTraces() - GetNextIndex();
	}
	// allocate buffers
	for(i=0; i<GetNumberOfChannels(); i++) {
		if(GetChannel(i)->IsEnabled()) {
			FILE_LOG(logDEBUG4) << "Measurement::GetNextDataBulk - memset data[i]" << GetLength()*traces_asked_for*sizeof(short);
			memset(data[i], 0, GetLength()*traces_asked_for*sizeof(short));
			FILE_LOG(logDEBUG4) << "done";
		}
		for(j=0; j<traces_asked_for; j++) {
			index = j+GetNextIndex();
			if(GetChannel(i)->IsEnabled()) {
				if(data_allocated[i] == false) {
					throw "Unable to get data. Memory is not allocated.";
				}
				if(GetSeries() == PICO_4000) {
					// GetPicoscope()->SetStatus(ps4000SetDataBufferBulk(
					// 	GetHandle(),                  // handle
					// 	(PS4000_CHANNEL)i,            // channel
					// 	data[i],                      // *buffer
					// 	GetMaxTraceLengthToFetch())); // bufferLength
					GetPicoscope()->SetStatus(ps4000SetDataBufferBulk(
						GetHandle(),                // handle
						(PS4000_CHANNEL)i,          // channel
						&data[i][j*GetLength()],    // *buffer
						GetLength(),                // bufferLength
						index));                    // waveform
				} else {
					// unsigned long dj = (j+GetNextIndex()/GetMaxTracesToFetch())%traces_asked_for;
					// std::cerr << "-- (set data buffer bulk: [" << i << "][" << dj
					// 	<< "], len:" << GetLength() << ", index:" << index
					// 	<< ", from:" << GetNextIndex()
					// 	<< ", to:" << GetNextIndex()+traces_asked_for-1 << "\n";
					GetPicoscope()->SetStatus(ps6000SetDataBufferBulk(
						GetHandle(),                // handle
						(PS6000_CHANNEL)i,          // channel
						&data[i][j*GetLength()],    // *buffer
						GetLength(),                // bufferLength
						index,                      // waveform
						PS6000_RATIO_MODE_NONE));   // downSampleRatioMode
				}
				if(GetPicoscope()->GetStatus() != PICO_OK) {
					std::cerr << "Unable to set memory for channel." << std::endl;
					throw Picoscope::PicoscopeException(GetPicoscope()->GetStatus());
				}
			}
		}
	}
	// fetch data
	// length_of_trace_fetched = length_of_trace_askedfor;
	std::cerr << "Get data for traces " << GetNextIndex() << "-" << GetNextIndex()+traces_asked_for << " (" << 100.0*(GetNextIndex()+traces_asked_for)/GetNTraces() << "%) ... ";
	overflow = new short[traces_asked_for];
	memset(overflow, 0, traces_asked_for*sizeof(short));
	// std::cerr << "-- x1\n";
	t.Start();
	// std::cerr << "length of buffer: " << data_length[0] << ", length of requested trace: " << length_of_trace_askedfor << " ... ";
	if(GetSeries() == PICO_4000) {
		length_of_trace_fetched = GetLength();
		GetPicoscope()->SetStatus(ps4000GetValuesBulk(
			GetHandle(),                // handle
			&length_of_trace_fetched,   // *noOfSamples
			// TODO: start index
			GetNextIndex(),             // fromSegmentIndex
			GetNextIndex()+traces_asked_for-1, // toSegmentIndex
			// this could also be min(GetMaxTraceLengthToFetch(),wholeLength-startindex)
			overflow));                // *overflow
	} else {
		// TODO: not sure about this ...
		length_of_trace_fetched = GetLength();
		GetPicoscope()->SetStatus(ps6000GetValuesBulk(
			GetHandle(),                // handle
			&length_of_trace_fetched,   // *noOfSamples
			// TODO: start index
			GetNextIndex(),             // fromSegmentIndex
			GetNextIndex()+traces_asked_for-1, // toSegmentIndex
			// this could also be min(GetMaxTraceLengthToFetch(),wholeLength-startindex)
			1,                          // downSampleRatio
			PS6000_RATIO_MODE_NONE,     // downSampleRatioMode
			overflow));                // *overflow
	}
	t.Stop();
	// std::cerr << "-- x2\n";
	if(GetPicoscope()->GetStatus() != PICO_OK) {
		std::cerr << "Unable to set memory for channel." << std::endl;
		throw Picoscope::PicoscopeException(GetPicoscope()->GetStatus());
	}
	for(i=0; i<traces_asked_for; i++) {
		for(j=0; i<GetNumberOfChannels(); i++) {
			if(overflow[i] & (1<<j)) {
				FILE_LOG(logWARNING) << "Warning: Overflow on channel " << (char)('A'+j) << " of trace " << i+GetNextIndex() << ".\n";
			}
		}
	}
	delete [] overflow;
	// if(length_of_trace_fetched != length_of_trace_askedfor) {
	// 	std::cerr << "Warning: The number of read samples was smaller than requested.\n";
	// }

	// getting timestamps
	int64_t *timestamps;
	PS6000_TIME_UNITS *timeunits;

	timestamps = new int64_t[traces_asked_for];
	timeunits  = new PS6000_TIME_UNITS[traces_asked_for];

	if(GetSeries() == PICO_4000) {
		// NOT YET IMPLEMENTED
	} else {
		FILE_LOG(logDEBUG2) << "ps6000GetValuesTriggerTimeOffsetBulk64(handle=" << GetHandle() << ", *timestamps, *timeunits, fromSegmentIndex=" << GetNextIndex() << ", toSegmentIndex=" << GetNextIndex()+traces_asked_for-1 << ")";
		GetPicoscope()->SetStatus(ps6000GetValuesTriggerTimeOffsetBulk64(
			GetHandle(),                // handle
			timestamps,                 // *times
			timeunits,                  // *timeUnits
			GetNextIndex(),                      // fromSegmentIndex
			GetNextIndex()+traces_asked_for-1)); // toSegmentIndex
	}
	if(GetPicoscope()->GetStatus() != PICO_OK) {
		std::cerr << "Unable to get timestamps." << std::endl;
		throw Picoscope::PicoscopeException(GetPicoscope()->GetStatus());
	}

	// for(i=0; i<traces_asked_for; i++) {
	// 	std::cerr << "time " << i << ": " << timestamps[i] << "\n";
	// }
	SetRate(traces_asked_for, timestamps[0], timeunits[0], timestamps[traces_asked_for-1], timeunits[traces_asked_for-1]);
	// if(timeunits[0] != timeunits[traces_asked_for-1]) {
	// 	FILE_LOG(logWARNING) << "time unit of the first and last sample differ; rate is not reliable; TIMING seems to be broken anyway";
	// }

	delete [] timestamps;
	delete [] timeunits;


	std::cerr << "OK ("<< t.GetSecondsDouble() <<"s)\n";

	// std::cerr << "length of trace fetched: " << length_of_trace_fetched << "\n";
	// std::cerr << "total length: " << traces_asked_for*length_of_trace_fetched << "\n";

	SetLengthFetched(traces_asked_for*length_of_trace_fetched);
	// std::cerr << "-- next index is now " << GetNextIndex() << ", will be set to " << GetNextIndex() + traces_asked_for << "\n";
	SetNextIndex(GetNextIndex()+traces_asked_for);
	// std::cerr << "-- next index is now " << GetNextIndex() << "\n";
	// std::cerr << "-- return value " << traces_asked_for << "\n";

	return traces_asked_for;
}
// TODO: we might want to use multiple buffers at the same time
// returns the length of data
// TODO: the first part only needs to be called once; so we should move the code at the end of RunBlock
//       unless we want to alternate between allocated memory (to enable parallel readouts)
unsigned long Measurement::GetNextData()
{
	FILE_LOG(logDEBUG3) << "Measurement::GetNextData";

	int i;
	short overflow=0;
	uint32_t length_of_trace_askedfor, length_of_trace_fetched;
	Timing t;

	// it makes no sense to read any further: we are already at the end
	if(GetNextIndex() >= GetLength()) {
		std::cerr << "Stop fetching data from osciloscope." << std::endl;
		return 0UL;
	}

	length_of_trace_askedfor = GetMaxTraceLengthToFetch();
	if(GetNextIndex() + length_of_trace_askedfor > GetLength()) {
		length_of_trace_askedfor = GetLength() - GetNextIndex();
	}
	// allocate buffers
	for(i=0; i<GetNumberOfChannels(); i++) {
		if(GetChannel(i)->IsEnabled()) {
			if(data_allocated[i] == false) {
				throw "Unable to get data. Memory is not allocated.";
			}
			if(GetSeries() == PICO_4000) {
				FILE_LOG(logDEBUG2) << "ps4000SetDataBuffer(handle=" << GetHandle() << ", channel=" << i << ", *buffer=<data[i]>, bufferLength=" << GetMaxTraceLengthToFetch() << ")";
				GetPicoscope()->SetStatus(ps4000SetDataBuffer(
					GetHandle(),                  // handle
					(PS4000_CHANNEL)i,            // channel
					data[i],                      // *buffer
					GetMaxTraceLengthToFetch())); // bufferLength
			} else {
				FILE_LOG(logDEBUG2) << "ps6000SetDataBuffer(handle=" << GetHandle() << ", channel=" << i << ", *buffer=<data[i]>, bufferLength=" << GetMaxTraceLengthToFetch() << ", downSampleRatioMode=PS6000_RATIO_MODE_NONE)";
				GetPicoscope()->SetStatus(ps6000SetDataBuffer(
					GetHandle(),                // handle
					(PS6000_CHANNEL)i,          // channel
					data[i],                    // *buffer
					GetMaxTraceLengthToFetch(), // bufferLength
					PS6000_RATIO_MODE_NONE));   // downSampleRatioMode
			}
			if(GetPicoscope()->GetStatus() != PICO_OK) {
				std::cerr << "Unable to set memory for channel." << std::endl;
				throw Picoscope::PicoscopeException(GetPicoscope()->GetStatus());
			}
		}
	}
	// fetch data
	length_of_trace_fetched = length_of_trace_askedfor;
	std::cerr << "Get data for points " << GetNextIndex() << "-" << GetNextIndex()+length_of_trace_askedfor << " (" << 100.0*(GetNextIndex()+length_of_trace_askedfor)/GetLength() << "%) ... ";
	t.Start();
	// std::cerr << "length of buffer: " << data_length[0] << ", length of requested trace: " << length_of_trace_askedfor << " ... ";
	if(GetSeries() == PICO_4000) {
		FILE_LOG(logDEBUG2) << "ps4000GetValues(handle=" << GetHandle() << ", startIndex=" << GetNextIndex() << ", *noOfSamples=" << length_of_trace_fetched << ", downSampleRatio=1, downSampleRatioMode=PS4000_RATIO_MODE_NONE, segmentIndex=0, *overflow)";
		GetPicoscope()->SetStatus(ps4000GetValues(
			GetHandle(),                // handle
			// TODO: start index
			GetNextIndex(),             // startIndex
			// this could also be min(GetMaxTraceLengthToFetch(),wholeLength-startindex)
			&length_of_trace_fetched,   // *noOfSamples
			1,                          // downSampleRatio
			PS4000_RATIO_MODE_NONE,     // downSampleRatioMode
			0,                          // segmentIndex
			&overflow));                // *overflow
		FILE_LOG(logDEBUG2) << "-> length_of_trace_fetched=" << length_of_trace_fetched << "\n";
	} else {
		FILE_LOG(logDEBUG2) << "ps6000GetValues(handle=" << GetHandle() << ", startIndex=" << GetNextIndex() << ", *noOfSamples=" << length_of_trace_fetched << ", downSampleRatio=1, downSampleRatioMode=PS6000_RATIO_MODE_NONE, segmentIndex=0, *overflow)";
		GetPicoscope()->SetStatus(ps6000GetValues(
			GetHandle(),                // handle
			// TODO: start index
			GetNextIndex(),             // startIndex
			// this could also be min(GetMaxTraceLengthToFetch(),wholeLength-startindex)
			&length_of_trace_fetched,   // *noOfSamples
			1,                          // downSampleRatio
			PS6000_RATIO_MODE_NONE,     // downSampleRatioMode
			0,                          // segmentIndex
			&overflow));                // *overflow
		FILE_LOG(logDEBUG2) << "-> length_of_trace_fetched=" << length_of_trace_fetched << "\n";
	}
	t.Stop();
	if(GetPicoscope()->GetStatus() != PICO_OK) {
		std::cerr << "Unable to set memory for channel." << std::endl;
		throw Picoscope::PicoscopeException(GetPicoscope()->GetStatus());
	}
	if(overflow) {
		for(i=0; i<GetNumberOfChannels(); i++) {
			if(overflow & (1<<i)) {
				std::cerr << "Warning: Overflow on channel " << (char)('A'+i) << ".\n";
			}
		}
	}
	if(length_of_trace_fetched != length_of_trace_askedfor) {
		std::cerr << "Warning: The number of read samples was smaller than requested.\n";
	}
	std::cerr << "OK ("<< t.GetSecondsDouble() <<"s)\n";
	SetLengthFetched(length_of_trace_fetched);
	SetNextIndex(GetNextIndex()+length_of_trace_fetched);

	return length_of_trace_fetched;
}
void Measurement::RunBlock()
{
	FILE_LOG(logDEBUG3) << "Measurement::RunBlock";

	int i;
	Timing t;
	uint32_t max_length=0;

	// we will have to start reading our data from beginning again
	SetNextIndex(0);
	// test if channel settings have already been passed to picoscope
	// and only pass them again if that isn't the case
	FILE_LOG(logDEBUG4) << "Measurement::RunBlock - we have " << GetNumberOfChannels() << " channels";
	for(i=0; i<GetNumberOfChannels(); i++) {
		FILE_LOG(logDEBUG4) << "Measurement::RunBlock - setting channel " << (char)('A'+i) << " (which holds index " << GetChannel(i)->GetIndex() << ")";
		GetChannel(i)->SetChannelInPicoscope();
	}
	// this fixes the timebase if more than a single channel is selected
	FixTimebase();
	// timebase
	SetTimebaseInPicoscope();
	// trigger
	if(IsTriggered()) {
		GetTrigger()->SetTriggerInPicoscope();
	}

	// for rapid block mode
	if(GetNTraces() > 1) {
		// TODO - check that GetLength()*GetNumberOfEnabledChannels()*GetNTraces() doesn't exceed the limit
		if(GetSeries() == PICO_4000) {
			FILE_LOG(logDEBUG2) << "ps4000SetNoOfCaptures(handle=" << GetHandle() << ", nCaptures=" << GetNTraces() << ")";
			GetPicoscope()->SetStatus(ps4000SetNoOfCaptures(
				GetHandle(),    // handle
				GetNTraces())); // nCaptures
		} else {
			FILE_LOG(logDEBUG2) << "ps6000SetNoOfCaptures(handle=" << GetHandle() << ", nCaptures=" << GetNTraces() << ")";
			GetPicoscope()->SetStatus(ps6000SetNoOfCaptures(
				GetHandle(),    // handle
				GetNTraces())); // nCaptures
		}
		if(GetPicoscope()->GetStatus() != PICO_OK) {
			std::cerr << "Unable to set number of captures to " << GetNTraces() << std::endl;
			throw Picoscope::PicoscopeException(GetPicoscope()->GetStatus());
		}
		if(GetSeries() == PICO_4000) {
			FILE_LOG(logDEBUG2) << "ps4000MemorySegments(handle=" << GetHandle() << ", nSegments=" << GetNTraces() << ", &max_length=" << max_length << ")";
			GetPicoscope()->SetStatus(ps4000MemorySegments(
				GetHandle(),   // handle
				GetNTraces(),  // nSegments
				&max_length));
			FILE_LOG(logDEBUG2) << "->ps4000MemorySegments(... max_length=" << max_length << ")";
		} else {
			FILE_LOG(logDEBUG2) << "ps6000MemorySegments(handle=" << GetHandle() << ", nSegments=" << GetNTraces() << ", &max_length=" << max_length << ")";
			GetPicoscope()->SetStatus(ps6000MemorySegments(
				GetHandle(),   // handle
				GetNTraces(),  // nSegments
				&max_length));
			FILE_LOG(logDEBUG2) << "->ps6000MemorySegments(... max_length=" << max_length << ")";
		}
		if(GetPicoscope()->GetStatus() != PICO_OK) {
			std::cerr << "Unable to set number of segments to " << GetNTraces() << std::endl;
			throw Picoscope::PicoscopeException(GetPicoscope()->GetStatus());
		}
		if(max_length < GetLength()) { // TODO: times number of enabled channels
			std::cerr << "The maximum length of trace you can get with " << GetNTraces()
			          << " traces is " << max_length << ", but you requested " << GetLength() << "\n";
			throw;
		}
		if(GetSeries() == PICO_4000) {
			FILE_LOG(logDEBUG2) << "ps4000SetNoOfCaptures(handle=" << GetHandle() << ", nCaptures=" << GetNTraces() << ")";
			GetPicoscope()->SetStatus(ps4000SetNoOfCaptures(
				GetHandle(),    // handle
				GetNTraces())); // nCaptures
		} else {
			FILE_LOG(logDEBUG2) << "ps6000SetNoOfCaptures(handle=" << GetHandle() << ", nCaptures=" << GetNTraces() << ")";
			GetPicoscope()->SetStatus(ps6000SetNoOfCaptures(
				GetHandle(),    // handle
				GetNTraces())); // nCaptures
		}
		if(GetPicoscope()->GetStatus() != PICO_OK) {
			std::cerr << "Unable to set number of captures to " << GetNTraces() << std::endl;
			throw Picoscope::PicoscopeException(GetPicoscope()->GetStatus());
		}
	}

	//std::cerr << "\nPress a key to start fetching the data ...\n";
	//_getch();

	t.Start();
	GetPicoscope()->SetReady(false);
	if(GetSeries() == PICO_4000) {
		FILE_LOG(logDEBUG2) << "ps4000RunBlock(handle=" << GetHandle() << ", noOfPreTriggerSamples=" << GetLengthBeforeTrigger() << ", noOfPostTriggerSamples=" << GetLengthAfterTrigger() << ", timebase=" << timebase << ", oversample=1, *timeIndisposedMs=NULL, segmentIndex=0, lpReady=CallBackBlock, *pParameter=NULL)";
		GetPicoscope()->SetStatus(ps4000RunBlock(
			GetHandle(),              // handle
			GetLengthBeforeTrigger(), // noOfPreTriggerSamples
			GetLengthAfterTrigger(),  // noOfPostTriggerSamples
			timebase,                 // timebase
			1,                        // ovesample
			NULL,                     // *timeIndisposedMs
			0,                        // segmentIndex
			CallBackBlock,            // lpReady
			NULL));                   // *pParameter
	} else {
		FILE_LOG(logDEBUG2) << "ps6000RunBlock(handle=" << GetHandle() << ", noOfPreTriggerSamples=" << GetLengthBeforeTrigger() << ", noOfPostTriggerSamples=" << GetLengthAfterTrigger() << ", timebase=" << timebase << ", oversample=1, *timeIndisposedMs=NULL, segmentIndex=0, lpReady=CallBackBlock, *pParameter=NULL)";
		GetPicoscope()->SetStatus(ps6000RunBlock(
			GetHandle(),              // handle
			GetLengthBeforeTrigger(), // noOfPreTriggerSamples
			GetLengthAfterTrigger(),  // noOfPostTriggerSamples
			timebase,                 // timebase
			1,                        // ovesample
			NULL,                     // *timeIndisposedMs
			0,                        // segmentIndex
			CallBackBlock,            // lpReady
			NULL));                   // *pParameter
	}
	if(GetPicoscope()->GetStatus() != PICO_OK) {
		std::cerr << "Unable to start collecting samples" << std::endl;
		throw Picoscope::PicoscopeException(GetPicoscope()->GetStatus());
	} else {
		std::cerr << "Start collecting samples in "
		          << ((GetNTraces() > 1) ? "rapid " : "") << "block mode ... ";
	}
	// TODO: maybe we want it to be asynchronous
	// TODO: catch the _kbhit event!!!
	// while (!Picoscope::IsReady() && !_kbhit()) {
	while (!Picoscope::IsReady()) {
		Sleep(200);
	}
	t.Stop();
	std::cerr << "OK (" << t.GetSecondsDouble() << "s)\n";

	// sets the index from where we want to start reading data to zero
	SetNextIndex(0UL);
}