// Path: src/main/java/com/sketchy/hardware/Direction.java
// public enum Direction {
// 	BACKWARD(-1), NONE(0), FORWARD(1);
// 
// 	private int value;
// 	
//     private Direction(int value) {
//     	this.value = value;
//     }
// 
//     public static Direction fromValue(int value){
//     	if (value==0) {
//     		return NONE;
//     	} else if (value>0){
//     		return FORWARD;
//     	} else {
//     		return BACKWARD;
//     	}
//     }
//     
//     
//     public int getValue() {
// 		return value;
// 	}
//     
// }
// 
// Path: src/main/java/com/sketchy/hardware/HardwareController.java
// public abstract class HardwareController {
// 
// 	//protected HardwareControllerProperties properties = null; 
// 	// This is to ensure that the Constructor in subclasses is created
// 	protected HardwareController(HardwareControllerProperties properties){}
// 	
// 	private static HardwareController _this = null;
// 	
// 	public abstract HardwareControllerProperties getProperties();
// 
// 	public synchronized static HardwareController getInstance() throws Exception {
// 		if (_this==null){
// 			throw new Exception("Instance not created. Use newInstance(HardwareControllerProperties properties) first!");
// 		}
// 		return _this;
// 	}
// 		
// 	public synchronized static HardwareController newInstance(HardwareControllerProperties properties) throws Exception {
// 		Class<? extends HardwareController> controllerClass = properties.getImplementationClass();
// 		
// 		try{
// 			if (_this!=null){
// 				// existing instance
// 				_this.shutDown();
// 				_this=null;
// 			}
// 			
// 			Constructor<? extends HardwareController> constructor = controllerClass.getConstructor(new Class[]{properties.getClass()});
// 			_this=constructor.newInstance(new Object[]{properties});
// 		} catch (IllegalAccessException e){
// 			throw new Exception("Error Getting HardwareController Instance from Class '" + controllerClass.getName() + "'! " + e.toString());
// 		} catch (InstantiationException e){
// 			throw new Exception("Error Getting HardwareController Instance from Class '" + controllerClass.getName() + "'!" + e.toString());
// 		} catch (InvocationTargetException e){
// 			throw new Exception(e.getTargetException().getMessage());
// 		}
// 		
// 		return _this;
// 	}
// 
// 	public abstract void penUp();
// 
// 	public abstract void penDown();
// 		
// 	// Based on Bresenham's line algorithm
// 	public void moveMotors(int leftSteps, int rightSteps, long delayInMicroSeconds) throws Exception {
// 		// Just return if no steps occurring
// 		if ((leftSteps==0) && (rightSteps==0)) return;
// 		
// 		boolean swapSteps=Math.abs(rightSteps) > Math.abs(leftSteps);
// 	    if (swapSteps){
// 	    	int temp=leftSteps;
// 	    	leftSteps=rightSteps;
// 	    	rightSteps=temp;
// 	    }
// 
// 	    Direction leftMotorDirection =  Direction.fromValue(leftSteps);
// 	    Direction rightMotorDirection = Direction.fromValue(rightSteps);
// 		
// 	    leftSteps = Math.abs(leftSteps);  
// 	    rightSteps = Math.abs(rightSteps);  
// 	    
//         int error=leftSteps/2;
//         for (int steps=0;steps<leftSteps;steps++){
// 	    	Direction stepRight=Direction.NONE;
//         	error-=rightSteps;
//         	if(error<0){
//         		stepRight=rightMotorDirection;
//         		error+=leftSteps;
//         	}
//         	if (swapSteps){
//         		stepMotors(stepRight, leftMotorDirection, delayInMicroSeconds);
//         	} else {
//         		stepMotors(leftMotorDirection, stepRight, delayInMicroSeconds);
//         	}
// 	    }
// 	}
// 	
// 	public abstract void stepMotors(Direction leftMotorDirection, Direction rightMotorDirection, long delayInMicroSeconds);
// 	
// 	public abstract void enableMotors();
// 	
// 	public abstract void disableMotors();
// 
// 	public abstract void shutDown();
// 		
// 	@SuppressWarnings("unchecked")
// 	public static Map<String, String> getHardwareControllerClassMap() throws Exception { 
// 		List<Class<?>> classes = ClassScanner.getClassesForPackage("com.sketchy.hardware.impl", MetaDataObject.class);
// 		Map<String, String> classMap = new LinkedHashMap<String, String>();
// 		for (Class<?> clazz:classes){
// 			Class<HardwareControllerProperties> hardwareControllerClass = (Class<HardwareControllerProperties>) clazz;
// 			Class<HardwareController> implementationClass = (Class<HardwareController>) hardwareControllerClass.newInstance().getImplementationClass();
// 			classMap.put(implementationClass.getName(), clazz.getName());
// 		}
// 		return classMap;
// 	}
// 	
// }


import java.io.File;
import org.apache.commons.io.FileUtils;
import com.pi4j.wiringpi.Gpio;
import com.sketchy.hardware.Direction;
import com.sketchy.hardware.HardwareController;
	}
	
	public synchronized void penUp(){
		if (properties.getPenUpPosition()!=lastPosition){
			try{
				int penUpValue=(int) ((SERVO_MAX_VALUE-SERVO_MIN_VALUE)/100.0*properties.getPenUpPosition()+SERVO_MIN_VALUE);
				String servoPenUpCommand = buildServoCommand(properties.getPenPinNumber(), penUpValue);
				FileUtils.writeStringToFile(servoPipeFile, servoPenUpCommand);
			} catch (Exception e){
				throw new RuntimeException(e.getMessage());
			}
			Gpio.delayMicroseconds(properties.getPenUpPeriodInMilliseconds()*1000);
			lastPosition=properties.getPenUpPosition();
		}
	}
	
	public synchronized void penDown(){
		if (properties.getPenDownPosition()!=lastPosition){
			try{
				int penDownValue=(int) ((SERVO_MAX_VALUE-SERVO_MIN_VALUE)/100.0*properties.getPenDownPosition()+SERVO_MIN_VALUE);
				String servoPenDownCommand = buildServoCommand(properties.getPenPinNumber(), penDownValue);
				FileUtils.writeStringToFile(servoPipeFile, servoPenDownCommand);
			} catch (Exception e){
				throw new RuntimeException(e.getMessage());
			}
			Gpio.delayMicroseconds(properties.getPenDownPeriodInMilliseconds()*1000);
			lastPosition=properties.getPenDownPosition();
		}
	}
	
// Path: src/main/java/com/sketchy/hardware/Direction.java
// public enum Direction {
// 	BACKWARD(-1), NONE(0), FORWARD(1);
// 
// 	private int value;
// 	
//     private Direction(int value) {
//     	this.value = value;
//     }
// 
//     public static Direction fromValue(int value){
//     	if (value==0) {
//     		return NONE;
//     	} else if (value>0){
//     		return FORWARD;
//     	} else {
//     		return BACKWARD;
//     	}
//     }
//     
//     
//     public int getValue() {
// 		return value;
// 	}
//     
// }
// 
// Path: src/main/java/com/sketchy/hardware/HardwareController.java
// public abstract class HardwareController {
// 
// 	//protected HardwareControllerProperties properties = null; 
// 	// This is to ensure that the Constructor in subclasses is created
// 	protected HardwareController(HardwareControllerProperties properties){}
// 	
// 	private static HardwareController _this = null;
// 	
// 	public abstract HardwareControllerProperties getProperties();
// 
// 	public synchronized static HardwareController getInstance() throws Exception {
// 		if (_this==null){
// 			throw new Exception("Instance not created. Use newInstance(HardwareControllerProperties properties) first!");
// 		}
// 		return _this;
// 	}
// 		
// 	public synchronized static HardwareController newInstance(HardwareControllerProperties properties) throws Exception {
// 		Class<? extends HardwareController> controllerClass = properties.getImplementationClass();
// 		
// 		try{
// 			if (_this!=null){
// 				// existing instance
// 				_this.shutDown();
// 				_this=null;
// 			}
// 			
// 			Constructor<? extends HardwareController> constructor = controllerClass.getConstructor(new Class[]{properties.getClass()});
// 			_this=constructor.newInstance(new Object[]{properties});
// 		} catch (IllegalAccessException e){
// 			throw new Exception("Error Getting HardwareController Instance from Class '" + controllerClass.getName() + "'! " + e.toString());
// 		} catch (InstantiationException e){
// 			throw new Exception("Error Getting HardwareController Instance from Class '" + controllerClass.getName() + "'!" + e.toString());
// 		} catch (InvocationTargetException e){
// 			throw new Exception(e.getTargetException().getMessage());
// 		}
// 		
// 		return _this;
// 	}
// 
// 	public abstract void penUp();
// 
// 	public abstract void penDown();
// 		
// 	// Based on Bresenham's line algorithm
// 	public void moveMotors(int leftSteps, int rightSteps, long delayInMicroSeconds) throws Exception {
// 		// Just return if no steps occurring
// 		if ((leftSteps==0) && (rightSteps==0)) return;
// 		
// 		boolean swapSteps=Math.abs(rightSteps) > Math.abs(leftSteps);
// 	    if (swapSteps){
// 	    	int temp=leftSteps;
// 	    	leftSteps=rightSteps;
// 	    	rightSteps=temp;
// 	    }
// 
// 	    Direction leftMotorDirection =  Direction.fromValue(leftSteps);
// 	    Direction rightMotorDirection = Direction.fromValue(rightSteps);
// 		
// 	    leftSteps = Math.abs(leftSteps);  
// 	    rightSteps = Math.abs(rightSteps);  
// 	    
//         int error=leftSteps/2;
//         for (int steps=0;steps<leftSteps;steps++){
// 	    	Direction stepRight=Direction.NONE;
//         	error-=rightSteps;
//         	if(error<0){
//         		stepRight=rightMotorDirection;
//         		error+=leftSteps;
//         	}
//         	if (swapSteps){
//         		stepMotors(stepRight, leftMotorDirection, delayInMicroSeconds);
//         	} else {
//         		stepMotors(leftMotorDirection, stepRight, delayInMicroSeconds);
//         	}
// 	    }
// 	}
// 	
// 	public abstract void stepMotors(Direction leftMotorDirection, Direction rightMotorDirection, long delayInMicroSeconds);
// 	
// 	public abstract void enableMotors();
// 	
// 	public abstract void disableMotors();
// 
// 	public abstract void shutDown();
// 		
// 	@SuppressWarnings("unchecked")
// 	public static Map<String, String> getHardwareControllerClassMap() throws Exception { 
// 		List<Class<?>> classes = ClassScanner.getClassesForPackage("com.sketchy.hardware.impl", MetaDataObject.class);
// 		Map<String, String> classMap = new LinkedHashMap<String, String>();
// 		for (Class<?> clazz:classes){
// 			Class<HardwareControllerProperties> hardwareControllerClass = (Class<HardwareControllerProperties>) clazz;
// 			Class<HardwareController> implementationClass = (Class<HardwareController>) hardwareControllerClass.newInstance().getImplementationClass();
// 			classMap.put(implementationClass.getName(), clazz.getName());
// 		}
// 		return classMap;
// 	}
// 	
// }


// Path: src/main/java/com/sketchy/hardware/impl/RaspberryPIServoController.java
import java.io.File;
import org.apache.commons.io.FileUtils;
import com.pi4j.wiringpi.Gpio;
import com.sketchy.hardware.Direction;
import com.sketchy.hardware.HardwareController;

	}
	
	public synchronized void penUp(){
		if (properties.getPenUpPosition()!=lastPosition){
			try{
				int penUpValue=(int) ((SERVO_MAX_VALUE-SERVO_MIN_VALUE)/100.0*properties.getPenUpPosition()+SERVO_MIN_VALUE);
				String servoPenUpCommand = buildServoCommand(properties.getPenPinNumber(), penUpValue);
				FileUtils.writeStringToFile(servoPipeFile, servoPenUpCommand);
			} catch (Exception e){
				throw new RuntimeException(e.getMessage());
			}
			Gpio.delayMicroseconds(properties.getPenUpPeriodInMilliseconds()*1000);
			lastPosition=properties.getPenUpPosition();
		}
	}
	
	public synchronized void penDown(){
		if (properties.getPenDownPosition()!=lastPosition){
			try{
				int penDownValue=(int) ((SERVO_MAX_VALUE-SERVO_MIN_VALUE)/100.0*properties.getPenDownPosition()+SERVO_MIN_VALUE);
				String servoPenDownCommand = buildServoCommand(properties.getPenPinNumber(), penDownValue);
				FileUtils.writeStringToFile(servoPipeFile, servoPenDownCommand);
			} catch (Exception e){
				throw new RuntimeException(e.getMessage());
			}
			Gpio.delayMicroseconds(properties.getPenDownPeriodInMilliseconds()*1000);
			lastPosition=properties.getPenDownPosition();
		}
	}
	
	public synchronized void stepMotors(Direction leftMotorDirection, Direction rightMotorDirection, long delayInMicroSeconds){