#include "stdafx.h"
#include "ClientAPI.h"
#include <string>
#include <math.h>

// insert the IP of your SP-ICE-3 
#define CARD_IP "192.168.2.138"

static rlResult markPointAndShoot(rlHandle handle);
static int printLastError(void);


int main()
{
	// establish a connection with the card
	rlHandle handle = rlConnect(CARD_IP, 49374);
	if (handle < 0)
		return printLastError();

	rlResult status;

	// Reset the card to its default settings:
	// This restores the following settings to the values that were last saved on the card:
	// - scanner configuration (such as field size, field correction, etc.)
	// - laser configuration (such as gate/LM timing parameters, power target, etc.)
	// - process variables (such as jump speed, settling times, mark speed, etc.)
	if ((status = rlSystemResetToDefaults(handle)) != rlSUCCESS) goto Cleanup;

	// Set the laser power to 60%
	rlLaserConfig lc;
	if ( ( status = rlLaserGetConfig( handle, &lc ) ) != rlSUCCESS ) goto Cleanup;
	lc.PowerScale = 0.6;
	if ( ( status = rlLaserSetConfig( handle, &lc ) ) != rlSUCCESS ) goto Cleanup;

	// Enable the laser so it responds to commands that turn on the laser.
	// Note that this does not fire the laser until e.g. LaserOn or Mark command is executed.
	if ( ( status = rlLaserArmLaser( handle, true ) ) != rlSUCCESS ) goto Cleanup;

	status = markPointAndShoot(handle);

Cleanup:
	// print any errors
	if (status != rlSUCCESS)
		printLastError();

	// disconnect from the card
	printf("Disconnecting from card...\n");
	if (rlDisconnect(handle) != rlSUCCESS)
		return printLastError();

	printf("Exiting with status = %d\n", status);
	return status;
}


/// mark a bitmap with the point and shoot algorithm
/// in this example a gradient bitmap is generated
static rlResult markPointAndShoot(rlHandle handle)
{
	rlResult result;

	int listIndex = 0;
	double jumpSpeed = 1.0;
	double markSpeed = 0.4;
	double exposureTime = 100.0;

	rlLaserConfig laserConfig;
	if ((result = rlLaserGetConfig(handle, &laserConfig)) != rlSUCCESS) return result;
	laserConfig.HotPowerTarget = ptLmWidth;
	rlLaserSetConfig(handle, &laserConfig);

	// adjust the accelerationtime and lag
	// if != 0, the execution time has to be extended
	rlScannerConfig config;
	if ((result = rlScannerGetConfig(handle, &config)) != rlSUCCESS) return result;
	config.Heads[0].Axes[0].AccelerationTime = 0;
	config.Heads[0].Axes[1].AccelerationTime = 0;
	config.Heads[0].Axes[2].AccelerationTime = 0;
	config.Heads[0].Axes[0].TrackingError = 0;
	config.Heads[0].Axes[1].TrackingError = 0;
	config.Heads[0].Axes[2].TrackingError = 0;
	if ((result = rlScannerSetConfig(handle, &config)) != rlSUCCESS) return result;

	//set process variables
	rlProcessVariables pv;
	if ((result = rlProcessGetVariables(handle, &pv)) != rlSUCCESS) return result;
	pv.MaxDwellTime = 40;
	pv.MarkDelay = 0;
	pv.JumpDelay = 0;
	pv.PolyDelay = 50;
	pv.LaserOffDelay = 0;
	pv.LaserOnDelay = 0;
	if ((result = rlProcessSetVariables(handle, &pv)) != rlSUCCESS) return result;

	double maxX = 0.3 * 0.5 * config.FieldSize.X;	

	// evade error, if list was aborted in previous run
	bool waitSuccess;
	int listId;
	rlListWaitForListDone(handle, 0, &waitSuccess, &listId);


	printf("Preparing list: index=%d...\n", listIndex);
	rlCommandListHandle list = rlListAllocate(handle);

	if ((result = rlListAppendJumpSpeed(list, jumpSpeed)) != rlSUCCESS) return result;
	if ((result = rlListAppendJumpDelay(list, 0)) != rlSUCCESS) return result;
	if ((result = rlListAppendMarkSpeed(list, markSpeed)) != rlSUCCESS) return result;
	if ((result = rlListAppendMarkDelay(list, 0)) != rlSUCCESS) return result;
	if ((result = rlListAppendLmFrequency(list, 1.0 / 200.0)) != rlSUCCESS) return result;
	if ((result = rlListAppendLmWidth(list, 200.0)) != rlSUCCESS) return result;

	const int32_t pixelCount = 100;
	uint16_t* powerValues = new uint16_t[pixelCount];
	uint16_t power = 0;
	uint16_t powerIncrement = 65535 / pixelCount;

	// generate grayscale pattern
	for (int32_t pixel = 0; pixel < pixelCount; pixel++)
	{
		powerValues[pixel] = (uint16_t)(power & 0xffffu);
		power += powerIncrement;
	}
	int32_t lineCount = 100;
	double dy = 0.3 * config.FieldSize.Y / lineCount;
	double y = -0.5 * 0.3 * config.FieldSize.Y;

	// append the same grayscale pattern for every line
	for (int32_t line = lineCount; --line >= 0; y += dy)
	{
		if ((result = rlListAppendPointAndShootLineAbs2D(list, -maxX, y, maxX, y, &exposureTime, 1, powerValues, pixelCount)) != rlSUCCESS) return result;
	}

	if ((result = rlListAppendLaserOff(list)) != rlSUCCESS) return result;

	// close the list causing its contents to be transferred to the card
	printf("Closing list: index=%d...\n", listIndex);
	if ((result = rlListSet(handle, listIndex, list, false, -1)) != rlSUCCESS) return result;

	// run the list, and wait until its execution has completed
	printf("Executing list: index=%d...\n", listIndex);
	if ((result = rlListExecute(handle, listIndex)) != rlSUCCESS) return result;

	// estimate the mark time of one bitmap (assume top-right corner as the start point)
	double executionTimeMs = lineCount * 2 * maxX / jumpSpeed;
	executionTimeMs += exposureTime * (pixelCount * lineCount);
	executionTimeMs += sqrt(pow(2 * maxX, 2) + pow(2 * y, 2)) / jumpSpeed;
	executionTimeMs *= 0.001;
	executionTimeMs += 5000;

	bool done = false;
	int32_t listID;
	printf("Waiting until list execution is done: index=%d...\n", listIndex);
	if ((result = rlListWaitForListDone(handle, (int32_t)executionTimeMs, &done, &listID)) != rlSUCCESS)
		return result;
	if (!done)
	{
		printf("Timeout: execution has not completed after %lf ms!", executionTimeMs);
		return rlERROR;
	}
	printf("Execution done: index=%d...\n", listIndex);

	// delete list on the card: this frees the card's memory occupied by the list
	printf("Deleting list: index=%d...\n", listIndex);
	if ((result = rlListDelete(handle, listIndex, true)) != rlSUCCESS)
		return result;

	// release the local list: this frees the PC's memory occupied by the card
	if ((result = rlListReleaseHandle(list)) != rlSUCCESS) return result;

	return result;
}


// helper function which displays the description of the last error
static int printLastError(void)
{
	char errBuffer[1024] = { 0 };
	rlGetLastError(errBuffer, sizeof(errBuffer) - 1);
	printf("%s", errBuffer);
	return rlERROR;
}

