Jelajahi Sumber

adding holtek emualtor classes: NOP, PORT, WAIT, JMP -

Wilfried Klaas 6 tahun lalu
induk
melakukan
bdbdab63f2

+ 4 - 3
.classpath

@@ -13,19 +13,20 @@
 	</classpathentry>
 	<classpathentry kind="src" output="target/test-classes" path="src/test/java">
 		<attributes>
+			<attribute name="test" value="true"/>
 			<attribute name="optional" value="true"/>
 			<attribute name="maven.pomderived" value="true"/>
-			<attribute name="test" value="true"/>
 		</attributes>
 	</classpathentry>
 	<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
 		<attributes>
-			<attribute name="maven.pomderived" value="true"/>
 			<attribute name="test" value="true"/>
+			<attribute name="maven.pomderived" value="true"/>
 		</attributes>
 	</classpathentry>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-10">
 		<attributes>
+			<attribute name="module" value="true"/>
 			<attribute name="maven.pomderived" value="true"/>
 		</attributes>
 	</classpathentry>

+ 4 - 4
.settings/org.eclipse.jdt.core.prefs

@@ -1,9 +1,9 @@
 eclipse.preferences.version=1
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
-org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=10
+org.eclipse.jdt.core.compiler.compliance=10
 org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
 org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
 org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
-org.eclipse.jdt.core.compiler.release=disabled
-org.eclipse.jdt.core.compiler.source=1.8
+org.eclipse.jdt.core.compiler.release=enabled
+org.eclipse.jdt.core.compiler.source=10

+ 35 - 16
src/main/java/de/mcs/tools/sps/AbstractEmulator.java

@@ -15,10 +15,11 @@ public abstract class AbstractEmulator implements SPSEmulator {
 
   protected byte[] programMemory;
   private boolean debug;
-  protected int address;
-  protected int a, b, c, d;
   private boolean active;
   private TOutputCallback outputCallback;
+  private EmulatorInput emulatorInput;
+  private EmulatorOutput emulatorOutput;
+  private EmulatorInternals emulatorInternals;
 
   @Override
   public abstract List<SPSCommand> getCommands();
@@ -38,6 +39,11 @@ public abstract class AbstractEmulator implements SPSEmulator {
   @Override
   public void startProgram(boolean debug) {
     this.debug = debug;
+    if (emulatorInput == null) {
+      emulatorInput = createEmulatorInput();
+    }
+    emulatorOutput = createEmulatorOutput();
+    emulatorInternals = createEmulatorInternals();
     reset();
     active = true;
     if (outputCallback != null) {
@@ -52,6 +58,12 @@ public abstract class AbstractEmulator implements SPSEmulator {
 
   protected abstract void callNextCommand();
 
+  protected abstract EmulatorInput createEmulatorInput();
+
+  protected abstract EmulatorOutput createEmulatorOutput();
+
+  protected abstract EmulatorInternals createEmulatorInternals();
+
   protected SPSCommandData getCommandData(byte command) {
     SPSCommandData commandData = null;
     byte commandByte = (byte) (command & (byte) 0xF0);
@@ -70,21 +82,13 @@ public abstract class AbstractEmulator implements SPSEmulator {
   }
 
   protected void runCommand(SPSCommandData commandData) {
-    commandData.doWork();
+    EmulatorOutput emulatorOutput = commandData.doWork(getEmulatorInput(), getEmulatorInternals(), getEmulatorOutput());
     if (outputCallback != null) {
-      outputCallback.onOutput(getEmulatorOutput());
+      outputCallback.onOutput(emulatorOutput);
     }
   }
 
-  protected abstract EmulatorOutput getEmulatorOutput();
-
-  protected void reset() {
-    address = 0;
-    a = 0;
-    b = 0;
-    c = 0;
-    d = 0;
-  }
+  protected abstract void reset();
 
   @Override
   public void addCallback(TOutputCallback callback) {
@@ -107,8 +111,23 @@ public abstract class AbstractEmulator implements SPSEmulator {
   }
 
   @Override
-  public EmulatorInternals getInternals() {
-    return null;
-  }
+  public void setEmulatorInput(EmulatorInput input) {
+    this.emulatorInput = input;
+  };
+
+  @Override
+  public EmulatorInput getEmulatorInput() {
+    return emulatorInput;
+  };
+
+  @Override
+  public EmulatorInternals getEmulatorInternals() {
+    return emulatorInternals;
+  };
+
+  @Override
+  public EmulatorOutput getEmulatorOutput() {
+    return emulatorOutput;
+  };
 
 }

+ 5 - 0
src/main/java/de/mcs/tools/sps/EmulatorInput.java

@@ -0,0 +1,5 @@
+package de.mcs.tools.sps;
+
+public interface EmulatorInput {
+
+}

+ 10 - 0
src/main/java/de/mcs/tools/sps/EmulatorInternals.java

@@ -11,4 +11,14 @@ package de.mcs.tools.sps;
  */
 public interface EmulatorInternals {
 
+  void reset();
+
+  int getAddress();
+
+  void incAddress(int i);
+
+  void setDelay(long l);
+
+  long getDelay();
+
 }

+ 2 - 0
src/main/java/de/mcs/tools/sps/EmulatorOutput.java

@@ -11,4 +11,6 @@ package de.mcs.tools.sps;
  */
 public interface EmulatorOutput {
 
+  void reset();
+
 }

+ 1 - 1
src/main/java/de/mcs/tools/sps/SPSCommandData.java

@@ -35,6 +35,6 @@ public interface SPSCommandData {
   /**
    * here the work should be done
    */
-  void doWork();
+  EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output);
 
 }

+ 11 - 4
src/main/java/de/mcs/tools/sps/SPSCommandDataImpl.java

@@ -7,7 +7,7 @@ package de.mcs.tools.sps;
  * @author w.klaas
  *
  */
-public class SPSCommandDataImpl implements SPSCommandData {
+public abstract class SPSCommandDataImpl implements SPSCommandData {
 
   String name;
   String mnemonic;
@@ -80,14 +80,21 @@ public class SPSCommandDataImpl implements SPSCommandData {
     return this;
   }
 
+  /**
+   * @param command
+   *          the command to set
+   * @return this instance
+   */
+  public byte getData() {
+    return (byte) (getCommandByte() & (byte) 0x0F);
+  }
+
   @Override
   public String toString() {
     return String.format("%s (%s): %.2X", getMnemonic(), getName(), getCommandByte());
   }
 
   @Override
-  public void doWork() {
-
-  }
+  public abstract EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output);
 
 }

+ 15 - 4
src/main/java/de/mcs/tools/sps/SPSEmulator.java

@@ -38,8 +38,8 @@ public interface SPSEmulator {
    * starting the program with or without debug mode
    * 
    * @param debug
-   *          if debug = <code>true</code> than the program will stop on every step, otherwise only the callbacks will
-   *          be called
+   *          if debug = <code>true</code> than the program will stop on every
+   *          step, otherwise only the callbacks will be called
    */
   void startProgram(boolean debug);
 
@@ -68,8 +68,19 @@ public interface SPSEmulator {
   void stop();
 
   /**
+   * setting the input for the emulator
    * 
-   * @return the actual emualtor internals
+   * @param input
    */
-  EmulatorInternals getInternals();
+  void setEmulatorInput(EmulatorInput input);
+
+  EmulatorInput getEmulatorInput();
+
+  /**
+   * 
+   * @return the actual emulator internals
+   */
+  EmulatorInternals getEmulatorInternals();
+
+  EmulatorOutput getEmulatorOutput();
 }

+ 0 - 316
src/main/java/de/mcs/tools/sps/holtec/HoltecEmulator.java

@@ -1,316 +0,0 @@
-/**
- * 
- */
-package de.mcs.tools.sps.holtec;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import de.mcs.tools.sps.AbstractEmulator;
-import de.mcs.tools.sps.EmulatorOutput;
-import de.mcs.tools.sps.SPSCommand;
-import de.mcs.tools.sps.SPSCommandData;
-import de.mcs.tools.sps.SPSCommandDataImpl;
-import de.mcs.tools.sps.SPSCommandImpl;
-import de.mcs.tools.sps.SPSEmulator;
-
-/**
- * @author w.klaas
- *
- */
-public class HoltecEmulator extends AbstractEmulator implements SPSEmulator {
-  private List<SPSCommand> commands = new ArrayList<>();
-  {
-    commands.add(SPS_NOP);
-    commands.add(SPS_PORT);
-    commands.add(SPS_WAIT);
-    commands.add(SPS_JUMP_DOWN);
-    commands.add(SPS_A_EQUALS);
-    commands.add(SPS_EQUALS_A);
-    commands.add(SPS_A_INPUT);
-    commands.add(SPS_A_CALCULATE);
-    commands.add(SPS_PAGE);
-    commands.add(SPS_JUMP_UP);
-    commands.add(SPS_C_LOOP);
-    commands.add(SPS_D_LOOP);
-    commands.add(SPS_SKIP_IF);
-    commands.add(SPS_CALL);
-    commands.add(SPS_RETURN);
-  }
-
-  private static SPSCommand SPS_NOP = new SPSCommandImpl().setName("no operation").setMnemonic("NOP")
-      .setCommandByte((byte) 0x00);
-  static {
-    SPS_NOP.getCommandDatas().add(new SPSCommandDataImpl().setName("nop").setMnemonic("NOP")
-        .setCommandByte((byte) (SPS_NOP.getCommandByte())).setCommand(SPS_NOP));
-  }
-
-  private static SPSCommand SPS_PORT = new SPSCommandImpl().setName("Port Output").setMnemonic("PORT")
-      .setCommandByte((byte) 0x10);
-
-  static {
-    for (int i = 0; i < 16; i++) {
-      SPS_PORT.getCommandDatas()
-          .add(new SPSCommandDataImpl().setName("Port " + Integer.toString(i)).setMnemonic("PO" + Integer.toString(i))
-              .setCommandByte((byte) (SPS_PORT.getCommandByte() + i)).setCommand(SPS_PORT));
-    }
-  }
-
-  private static SPSCommand SPS_WAIT = new SPSCommandImpl().setName("WAIT").setMnemonic("WAIT")
-      .setCommandByte((byte) 0x20);
-  static {
-    List<SPSCommandData> datas = SPS_WAIT.getCommandDatas();
-    datas.add(new SPSCommandDataImpl().setName("Wait 1ms").setMnemonic("D1M")
-        .setCommandByte((byte) SPS_WAIT.getCommandByte()).setCommand(SPS_WAIT));
-    datas.add(new SPSCommandDataImpl().setName("Wait 2ms").setMnemonic("D2M")
-        .setCommandByte((byte) SPS_WAIT.getCommandByte()).setCommand(SPS_WAIT));
-    datas.add(new SPSCommandDataImpl().setName("Wait 5ms").setMnemonic("D5M")
-        .setCommandByte((byte) SPS_WAIT.getCommandByte()).setCommand(SPS_WAIT));
-    datas.add(new SPSCommandDataImpl().setName("Wait 10ms").setMnemonic("D10M")
-        .setCommandByte((byte) SPS_WAIT.getCommandByte()).setCommand(SPS_WAIT));
-    datas.add(new SPSCommandDataImpl().setName("Wait 20ms").setMnemonic("D20M")
-        .setCommandByte((byte) SPS_WAIT.getCommandByte()).setCommand(SPS_WAIT));
-    datas.add(new SPSCommandDataImpl().setName("Wait 50ms").setMnemonic("D50M")
-        .setCommandByte((byte) SPS_WAIT.getCommandByte()).setCommand(SPS_WAIT));
-    datas.add(new SPSCommandDataImpl().setName("Wait 100ms").setMnemonic("D100M")
-        .setCommandByte((byte) SPS_WAIT.getCommandByte()).setCommand(SPS_WAIT));
-    datas.add(new SPSCommandDataImpl().setName("Wait 200ms").setMnemonic("D200M")
-        .setCommandByte((byte) SPS_WAIT.getCommandByte()).setCommand(SPS_WAIT));
-    datas.add(new SPSCommandDataImpl().setName("Wait 500ms").setMnemonic("D500M")
-        .setCommandByte((byte) SPS_WAIT.getCommandByte()).setCommand(SPS_WAIT));
-    datas.add(new SPSCommandDataImpl().setName("Wait 1s").setMnemonic("D1S")
-        .setCommandByte((byte) SPS_WAIT.getCommandByte()).setCommand(SPS_WAIT));
-    datas.add(new SPSCommandDataImpl().setName("Wait 2s").setMnemonic("D2S")
-        .setCommandByte((byte) SPS_WAIT.getCommandByte()).setCommand(SPS_WAIT));
-    datas.add(new SPSCommandDataImpl().setName("Wait 5s").setMnemonic("D5S")
-        .setCommandByte((byte) SPS_WAIT.getCommandByte()).setCommand(SPS_WAIT));
-    datas.add(new SPSCommandDataImpl().setName("Wait 10s").setMnemonic("D10S")
-        .setCommandByte((byte) SPS_WAIT.getCommandByte()).setCommand(SPS_WAIT));
-    datas.add(new SPSCommandDataImpl().setName("Wait 20s").setMnemonic("D20S")
-        .setCommandByte((byte) SPS_WAIT.getCommandByte()).setCommand(SPS_WAIT));
-    datas.add(new SPSCommandDataImpl().setName("Wait 30s").setMnemonic("D30S")
-        .setCommandByte((byte) SPS_WAIT.getCommandByte()).setCommand(SPS_WAIT));
-    datas.add(new SPSCommandDataImpl().setName("Wait 60s").setMnemonic("D60S")
-        .setCommandByte((byte) SPS_WAIT.getCommandByte()).setCommand(SPS_WAIT));
-  }
-
-  private static SPSCommand SPS_JUMP_DOWN = new SPSCommandImpl().setName("jump back").setMnemonic("JMP-")
-      .setCommandByte((byte) 0x30);
-  static {
-    for (int i = 0; i < 16; i++) {
-      SPS_JUMP_DOWN.getCommandDatas()
-          .add(new SPSCommandDataImpl().setName("Jump -" + Integer.toString(i)).setMnemonic("JN" + Integer.toString(i))
-              .setCommandByte((byte) (SPS_JUMP_DOWN.getCommandByte() + i)).setCommand(SPS_JUMP_DOWN));
-    }
-  }
-
-  private static SPSCommand SPS_A_EQUALS = new SPSCommandImpl().setName("Set A").setMnemonic("A=")
-      .setCommandByte((byte) 0x40);
-  static {
-    for (int i = 0; i < 16; i++) {
-      SPS_A_EQUALS.getCommandDatas()
-          .add(new SPSCommandDataImpl().setName("A= " + Integer.toString(i)).setMnemonic(String.format("A%02d", i))
-              .setCommandByte((byte) (SPS_A_EQUALS.getCommandByte() + i)).setCommand(SPS_A_EQUALS));
-    }
-  }
-
-  private static SPSCommand SPS_EQUALS_A = new SPSCommandImpl().setName("=A").setMnemonic("=A")
-      .setCommandByte((byte) 0x50);
-  static {
-    List<SPSCommandData> datas = SPS_EQUALS_A.getCommandDatas();
-    datas.add(new SPSCommandDataImpl().setName("B=A").setMnemonic("BEA")
-        .setCommandByte((byte) (SPS_EQUALS_A.getCommandByte() + 0x01)).setCommand(SPS_EQUALS_A));
-    datas.add(new SPSCommandDataImpl().setName("C=A").setMnemonic("CEA")
-        .setCommandByte((byte) (SPS_EQUALS_A.getCommandByte() + 0x02)).setCommand(SPS_EQUALS_A));
-    datas.add(new SPSCommandDataImpl().setName("D=A").setMnemonic("DEA")
-        .setCommandByte((byte) (SPS_EQUALS_A.getCommandByte() + 0x03)).setCommand(SPS_EQUALS_A));
-    datas.add(new SPSCommandDataImpl().setName("Output=A").setMnemonic("OEA")
-        .setCommandByte((byte) (SPS_EQUALS_A.getCommandByte() + 0x04)).setCommand(SPS_EQUALS_A));
-    datas.add(new SPSCommandDataImpl().setName("Output.1=A").setMnemonic("O1EA")
-        .setCommandByte((byte) (SPS_EQUALS_A.getCommandByte() + 0x05)).setCommand(SPS_EQUALS_A));
-    datas.add(new SPSCommandDataImpl().setName("Output.2=A").setMnemonic("O2EA")
-        .setCommandByte((byte) (SPS_EQUALS_A.getCommandByte() + 0x06)).setCommand(SPS_EQUALS_A));
-    datas.add(new SPSCommandDataImpl().setName("Output.3=A").setMnemonic("O3EA")
-        .setCommandByte((byte) (SPS_EQUALS_A.getCommandByte() + 0x07)).setCommand(SPS_EQUALS_A));
-    datas.add(new SPSCommandDataImpl().setName("Output.4=A").setMnemonic("O4EA")
-        .setCommandByte((byte) (SPS_EQUALS_A.getCommandByte() + 0x08)).setCommand(SPS_EQUALS_A));
-    datas.add(new SPSCommandDataImpl().setName("PWM=A").setMnemonic("PEA")
-        .setCommandByte((byte) (SPS_EQUALS_A.getCommandByte() + 0x09)).setCommand(SPS_EQUALS_A));
-  }
-
-  private static SPSCommand SPS_A_INPUT = new SPSCommandImpl().setName("A=(some input)").setMnemonic("AEI")
-      .setCommandByte((byte) 0x60);
-  static {
-    List<SPSCommandData> datas = SPS_A_INPUT.getCommandDatas();
-    datas.add(new SPSCommandDataImpl().setName("A=B").setMnemonic("AEB")
-        .setCommandByte((byte) (SPS_A_INPUT.getCommandByte() + 0x01)).setCommand(SPS_A_INPUT));
-    datas.add(new SPSCommandDataImpl().setName("A=C").setMnemonic("AEC")
-        .setCommandByte((byte) (SPS_A_INPUT.getCommandByte() + 0x02)).setCommand(SPS_A_INPUT));
-    datas.add(new SPSCommandDataImpl().setName("A=D").setMnemonic("AED")
-        .setCommandByte((byte) (SPS_A_INPUT.getCommandByte() + 0x03)).setCommand(SPS_A_INPUT));
-    datas.add(new SPSCommandDataImpl().setName("A=Input").setMnemonic("AEI")
-        .setCommandByte((byte) (SPS_A_INPUT.getCommandByte() + 0x04)).setCommand(SPS_A_INPUT));
-    datas.add(new SPSCommandDataImpl().setName("A=Input.1").setMnemonic("AEI1")
-        .setCommandByte((byte) (SPS_A_INPUT.getCommandByte() + 0x05)).setCommand(SPS_A_INPUT));
-    datas.add(new SPSCommandDataImpl().setName("A=Input.2").setMnemonic("AEI2")
-        .setCommandByte((byte) (SPS_A_INPUT.getCommandByte() + 0x06)).setCommand(SPS_A_INPUT));
-    datas.add(new SPSCommandDataImpl().setName("A=Input.3").setMnemonic("AEI3")
-        .setCommandByte((byte) (SPS_A_INPUT.getCommandByte() + 0x07)).setCommand(SPS_A_INPUT));
-    datas.add(new SPSCommandDataImpl().setName("A=Input.4").setMnemonic("AEI4")
-        .setCommandByte((byte) (SPS_A_INPUT.getCommandByte() + 0x08)).setCommand(SPS_A_INPUT));
-    datas.add(new SPSCommandDataImpl().setName("A=AD.1").setMnemonic("AEA1")
-        .setCommandByte((byte) (SPS_A_INPUT.getCommandByte() + 0x09)).setCommand(SPS_A_INPUT));
-    datas.add(new SPSCommandDataImpl().setName("A=AD.2").setMnemonic("AEA2")
-        .setCommandByte((byte) (SPS_A_INPUT.getCommandByte() + 0x0A)).setCommand(SPS_A_INPUT));
-  }
-
-  private static SPSCommand SPS_A_CALCULATE = new SPSCommandImpl().setName("Calculate with A").setMnemonic("CALC")
-      .setCommandByte((byte) 0x70);
-  static {
-    List<SPSCommandData> datas = SPS_A_CALCULATE.getCommandDatas();
-    datas.add(new SPSCommandDataImpl().setName("A=A+1").setMnemonic("INCA")
-        .setCommandByte((byte) (SPS_A_CALCULATE.getCommandByte() + 0x01)).setCommand(SPS_A_CALCULATE));
-    datas.add(new SPSCommandDataImpl().setName("A=A-1").setMnemonic("DECA")
-        .setCommandByte((byte) (SPS_A_CALCULATE.getCommandByte() + 0x02)).setCommand(SPS_A_CALCULATE));
-    datas.add(new SPSCommandDataImpl().setName("A=A+B").setMnemonic("ADDB")
-        .setCommandByte((byte) (SPS_A_CALCULATE.getCommandByte() + 0x03)).setCommand(SPS_A_CALCULATE));
-    datas.add(new SPSCommandDataImpl().setName("A=A-B").setMnemonic("SUBB")
-        .setCommandByte((byte) (SPS_A_CALCULATE.getCommandByte() + 0x04)).setCommand(SPS_A_CALCULATE));
-    datas.add(new SPSCommandDataImpl().setName("A=A*B").setMnemonic("MULB")
-        .setCommandByte((byte) (SPS_A_CALCULATE.getCommandByte() + 0x05)).setCommand(SPS_A_CALCULATE));
-    datas.add(new SPSCommandDataImpl().setName("A=A/B").setMnemonic("DIVB")
-        .setCommandByte((byte) (SPS_A_CALCULATE.getCommandByte() + 0x06)).setCommand(SPS_A_CALCULATE));
-    datas.add(new SPSCommandDataImpl().setName("A=A AND B").setMnemonic("ANDB")
-        .setCommandByte((byte) (SPS_A_CALCULATE.getCommandByte() + 0x07)).setCommand(SPS_A_CALCULATE));
-    datas.add(new SPSCommandDataImpl().setName("A=A OR B").setMnemonic("ORB")
-        .setCommandByte((byte) (SPS_A_CALCULATE.getCommandByte() + 0x08)).setCommand(SPS_A_CALCULATE));
-    datas.add(new SPSCommandDataImpl().setName("A=A XOR B").setMnemonic("XORB")
-        .setCommandByte((byte) (SPS_A_CALCULATE.getCommandByte() + 0x09)).setCommand(SPS_A_CALCULATE));
-    datas.add(new SPSCommandDataImpl().setName("A=NOT A").setMnemonic("NOTA")
-        .setCommandByte((byte) (SPS_A_CALCULATE.getCommandByte() + 0x0A)).setCommand(SPS_A_CALCULATE));
-  }
-
-  private static SPSCommand SPS_PAGE = new SPSCommandImpl().setName("Page").setMnemonic("PG")
-      .setCommandByte((byte) 0x80);
-  static {
-    for (int i = 0; i < 8; i++) {
-      SPS_PAGE.getCommandDatas()
-          .add(new SPSCommandDataImpl().setName("Page " + Integer.toString(i)).setMnemonic("PG" + Integer.toString(i))
-              .setCommandByte((byte) (SPS_PAGE.getCommandByte() + i)).setCommand(SPS_PAGE));
-    }
-  }
-
-  private static SPSCommand SPS_JUMP_UP = new SPSCommandImpl().setName("Jump").setMnemonic("JMP")
-      .setCommandByte((byte) 0x90);
-  static {
-    for (int i = 0; i < 16; i++) {
-      SPS_JUMP_UP.getCommandDatas()
-          .add(new SPSCommandDataImpl().setName("Jump " + Integer.toString(i)).setMnemonic("JMP" + Integer.toString(i))
-              .setCommandByte((byte) (SPS_JUMP_UP.getCommandByte() + i)).setCommand(SPS_JUMP_UP));
-    }
-  }
-
-  private static SPSCommand SPS_C_LOOP = new SPSCommandImpl().setName("C* Loop").setMnemonic("CLOP")
-      .setCommandByte((byte) 0xA0);
-  static {
-    for (int i = 0; i < 16; i++) {
-      SPS_C_LOOP.getCommandDatas()
-          .add(new SPSCommandDataImpl().setName("C* Loop " + Integer.toString(i))
-              .setMnemonic("CLOP" + Integer.toString(i)).setCommandByte((byte) (SPS_C_LOOP.getCommandByte() + i))
-              .setCommand(SPS_C_LOOP));
-    }
-  }
-
-  private static SPSCommand SPS_D_LOOP = new SPSCommandImpl().setName("D* Loop").setMnemonic("DLOP")
-      .setCommandByte((byte) 0xB0);
-  static {
-    for (int i = 0; i < 16; i++) {
-      SPS_D_LOOP.getCommandDatas()
-          .add(new SPSCommandDataImpl().setName("D* Loop " + Integer.toString(i))
-              .setMnemonic("DLOP" + Integer.toString(i)).setCommandByte((byte) (SPS_D_LOOP.getCommandByte() + i))
-              .setCommand(SPS_D_LOOP));
-    }
-  }
-
-  private static SPSCommand SPS_SKIP_IF = new SPSCommandImpl().setName("Skip if").setMnemonic("SKIP")
-      .setCommandByte((byte) 0xC0);
-  static {
-    SPS_SKIP_IF.getCommandDatas().add(new SPSCommandDataImpl().setName("A>B").setMnemonic("AGRB")
-        .setCommandByte((byte) (SPS_SKIP_IF.getCommandByte() + 0x01)).setCommand(SPS_SKIP_IF));
-    SPS_SKIP_IF.getCommandDatas().add(new SPSCommandDataImpl().setName("A<B").setMnemonic("ASMB")
-        .setCommandByte((byte) (SPS_SKIP_IF.getCommandByte() + 0x02)).setCommand(SPS_SKIP_IF));
-    SPS_SKIP_IF.getCommandDatas().add(new SPSCommandDataImpl().setName("A=B").setMnemonic("AEQB")
-        .setCommandByte((byte) (SPS_SKIP_IF.getCommandByte() + 0x03)).setCommand(SPS_SKIP_IF));
-    SPS_SKIP_IF.getCommandDatas().add(new SPSCommandDataImpl().setName("In.1=1").setMnemonic("IN11")
-        .setCommandByte((byte) (SPS_SKIP_IF.getCommandByte() + 0x04)).setCommand(SPS_SKIP_IF));
-    SPS_SKIP_IF.getCommandDatas().add(new SPSCommandDataImpl().setName("In.2=1").setMnemonic("IN21")
-        .setCommandByte((byte) (SPS_SKIP_IF.getCommandByte() + 0x05)).setCommand(SPS_SKIP_IF));
-    SPS_SKIP_IF.getCommandDatas().add(new SPSCommandDataImpl().setName("In.3=1").setMnemonic("IN31")
-        .setCommandByte((byte) (SPS_SKIP_IF.getCommandByte() + 0x06)).setCommand(SPS_SKIP_IF));
-    SPS_SKIP_IF.getCommandDatas().add(new SPSCommandDataImpl().setName("In.4=1").setMnemonic("IN41")
-        .setCommandByte((byte) (SPS_SKIP_IF.getCommandByte() + 0x07)).setCommand(SPS_SKIP_IF));
-    SPS_SKIP_IF.getCommandDatas().add(new SPSCommandDataImpl().setName("In.1=0").setMnemonic("IN10")
-        .setCommandByte((byte) (SPS_SKIP_IF.getCommandByte() + 0x08)).setCommand(SPS_SKIP_IF));
-    SPS_SKIP_IF.getCommandDatas().add(new SPSCommandDataImpl().setName("In.2=0").setMnemonic("IN20")
-        .setCommandByte((byte) (SPS_SKIP_IF.getCommandByte() + 0x09)).setCommand(SPS_SKIP_IF));
-    SPS_SKIP_IF.getCommandDatas().add(new SPSCommandDataImpl().setName("In.3=0").setMnemonic("IN30")
-        .setCommandByte((byte) (SPS_SKIP_IF.getCommandByte() + 0x0A)).setCommand(SPS_SKIP_IF));
-    SPS_SKIP_IF.getCommandDatas().add(new SPSCommandDataImpl().setName("In.4=0").setMnemonic("IN40")
-        .setCommandByte((byte) (SPS_SKIP_IF.getCommandByte() + 0x0B)).setCommand(SPS_SKIP_IF));
-    SPS_SKIP_IF.getCommandDatas().add(new SPSCommandDataImpl().setName("S1=0").setMnemonic("S10")
-        .setCommandByte((byte) (SPS_SKIP_IF.getCommandByte() + 0x0C)).setCommand(SPS_SKIP_IF));
-    SPS_SKIP_IF.getCommandDatas().add(new SPSCommandDataImpl().setName("S2=0").setMnemonic("S20")
-        .setCommandByte((byte) (SPS_SKIP_IF.getCommandByte() + 0x0D)).setCommand(SPS_SKIP_IF));
-    SPS_SKIP_IF.getCommandDatas().add(new SPSCommandDataImpl().setName("S1=1").setMnemonic("S11")
-        .setCommandByte((byte) (SPS_SKIP_IF.getCommandByte() + 0x0E)).setCommand(SPS_SKIP_IF));
-    SPS_SKIP_IF.getCommandDatas().add(new SPSCommandDataImpl().setName("S2=1").setMnemonic("S21")
-        .setCommandByte((byte) (SPS_SKIP_IF.getCommandByte() + 0x0F)).setCommand(SPS_SKIP_IF));
-  };
-
-  private static SPSCommand SPS_CALL = new SPSCommandImpl().setName("Call").setMnemonic("CALL")
-      .setCommandByte((byte) 0xD0);
-  static {
-    for (int i = 0; i < 16; i++) {
-      SPS_CALL.getCommandDatas()
-          .add(new SPSCommandDataImpl().setName("Call " + Integer.toString(i)).setMnemonic("CALL" + Integer.toString(i))
-              .setCommandByte((byte) (SPS_CALL.getCommandByte() + i)).setCommand(SPS_CALL));
-    }
-  }
-
-  private static SPSCommand SPS_RETURN = new SPSCommandImpl().setName("return").setMnemonic("RET")
-      .setCommandByte((byte) 0xE0);
-  static {
-    SPS_RETURN.getCommandDatas().add(new SPSCommandDataImpl().setName("Return").setMnemonic("RET")
-        .setCommandByte((byte) (SPS_RETURN.getCommandByte())).setCommand(SPS_RETURN));
-  }
-
-  @Override
-  public List<SPSCommand> getCommands() {
-    return commands;
-  }
-
-  @Override
-  public int getProgramSize() {
-    return 128;
-  }
-
-  @Override
-  protected void reset() {
-    super.reset();
-    System.out.println("holtec emulator resettet");
-  }
-
-  @Override
-  protected void callNextCommand() {
-    byte command = programMemory[address];
-    SPSCommandData commandData = getCommandData(command);
-    runCommand(commandData);
-    address++;
-  }
-
-  @Override
-  protected EmulatorOutput getEmulatorOutput() {
-    return new EmulatorOutput() {
-    };
-  }
-}

+ 619 - 0
src/main/java/de/mcs/tools/sps/holtec/HoltekEmulator.java

@@ -0,0 +1,619 @@
+/**
+ * 
+ */
+package de.mcs.tools.sps.holtec;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import de.mcs.tools.sps.AbstractEmulator;
+import de.mcs.tools.sps.EmulatorInput;
+import de.mcs.tools.sps.EmulatorInternals;
+import de.mcs.tools.sps.EmulatorOutput;
+import de.mcs.tools.sps.SPSCommand;
+import de.mcs.tools.sps.SPSCommandData;
+import de.mcs.tools.sps.SPSCommandDataImpl;
+import de.mcs.tools.sps.SPSCommandImpl;
+import de.mcs.tools.sps.SPSEmulator;
+
+/**
+ * @author w.klaas
+ *
+ */
+public class HoltekEmulator extends AbstractEmulator implements SPSEmulator {
+  private List<SPSCommand> commands = new ArrayList<>();
+  {
+    commands.add(SPS_NOP);
+    commands.add(SPS_PORT);
+    commands.add(SPS_WAIT);
+    commands.add(SPS_JUMP_DOWN);
+    commands.add(SPS_A_EQUALS);
+    commands.add(SPS_EQUALS_A);
+    commands.add(SPS_A_INPUT);
+    commands.add(SPS_A_CALCULATE);
+    commands.add(SPS_PAGE);
+    commands.add(SPS_JUMP_UP);
+    commands.add(SPS_C_LOOP);
+    commands.add(SPS_D_LOOP);
+    commands.add(SPS_SKIP_IF);
+    commands.add(SPS_CALL);
+    commands.add(SPS_RETURN);
+  }
+
+  private static SPSCommand SPS_NOP = new SPSCommandImpl().setName("no operation").setMnemonic("NOP")
+      .setCommandByte((byte) 0x00);
+  static {
+    SPS_NOP.getCommandDatas().add(new SPSCommandDataNOP().setName("nop").setMnemonic("NOP")
+        .setCommandByte((byte) (SPS_NOP.getCommandByte())).setCommand(SPS_NOP));
+  }
+
+  private static SPSCommand SPS_PORT = new SPSCommandImpl().setName("Port Output").setMnemonic("PORT")
+      .setCommandByte((byte) 0x10);
+  static {
+    for (int i = 0; i < 16; i++) {
+      SPS_PORT.getCommandDatas().add(new SPSCommandDataImpl() {
+        @Override
+        public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
+          byte data = getData();
+          HoltekEmulatorOutput emulatorOutput = (HoltekEmulatorOutput) HoltekEmulator.getInstance().getEmulatorOutput();
+          emulatorOutput.d0 = (data & (byte) 0x01) > 0;
+          emulatorOutput.d1 = (data & (byte) 0x02) > 0;
+          emulatorOutput.d2 = (data & (byte) 0x04) > 0;
+          emulatorOutput.d3 = (data & (byte) 0x08) > 0;
+          internals.incAddress(1);
+          return emulatorOutput;
+        }
+      }.setName("Port " + Integer.toString(i)).setMnemonic("PO" + Integer.toString(i))
+          .setCommandByte((byte) (SPS_PORT.getCommandByte() + i)).setCommand(SPS_PORT));
+    }
+  }
+
+  private static SPSCommand SPS_WAIT = new SPSCommandImpl().setName("WAIT").setMnemonic("WAIT")
+      .setCommandByte((byte) 0x20);
+  static {
+    List<SPSCommandData> datas = SPS_WAIT.getCommandDatas();
+    for (int i = 0; i < 16; i++) {
+      datas.add(
+          new SPSCommandDataWait().setName(SPSCommandDataWait.getName(i)).setMnemonic(SPSCommandDataWait.getMnemonic(i))
+              .setCommandByte((byte) (SPS_WAIT.getCommandByte() + i)).setCommand(SPS_WAIT));
+    }
+  }
+
+  private static SPSCommand SPS_JUMP_DOWN = new SPSCommandImpl().setName("jump back").setMnemonic("JMP-")
+      .setCommandByte((byte) 0x30);
+  static {
+    for (int i = 0; i < 16; i++) {
+      SPS_JUMP_DOWN.getCommandDatas()
+          .add(new SPSCommandDataJumpDown().setName("Jump -" + Integer.toString(i))
+              .setMnemonic("JN" + Integer.toString(i)).setCommandByte((byte) (SPS_JUMP_DOWN.getCommandByte() + i))
+              .setCommand(SPS_JUMP_DOWN));
+    }
+  }
+
+  private static SPSCommand SPS_A_EQUALS = new SPSCommandImpl().setName("Set A").setMnemonic("A=")
+      .setCommandByte((byte) 0x40);
+  static {
+    for (int i = 0; i < 16; i++) {
+      SPS_A_EQUALS.getCommandDatas().add(new SPSCommandDataImpl() {
+        @Override
+        public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
+          ((HoltekEmulatorInternals) internals).address++;
+          return HoltekEmulator.getInstance().getEmulatorOutput();
+        }
+      }.setName("A= " + Integer.toString(i)).setMnemonic(String.format("A%02d", i))
+          .setCommandByte((byte) (SPS_A_EQUALS.getCommandByte() + i)).setCommand(SPS_A_EQUALS));
+    }
+  }
+
+  private static SPSCommand SPS_EQUALS_A = new SPSCommandImpl().setName("=A").setMnemonic("=A")
+      .setCommandByte((byte) 0x50);
+  static {
+    List<SPSCommandData> datas = SPS_EQUALS_A.getCommandDatas();
+    datas.add(new SPSCommandDataImpl() {
+      @Override
+      public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
+        ((HoltekEmulatorInternals) internals).address++;
+        return HoltekEmulator.getInstance().getEmulatorOutput();
+      }
+    }.setName("B=A").setMnemonic("BEA").setCommandByte((byte) (SPS_EQUALS_A.getCommandByte() + 0x01))
+        .setCommand(SPS_EQUALS_A));
+    datas.add(new SPSCommandDataImpl() {
+      @Override
+      public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
+        ((HoltekEmulatorInternals) internals).address++;
+        return HoltekEmulator.getInstance().getEmulatorOutput();
+      }
+    }.setName("C=A").setMnemonic("CEA").setCommandByte((byte) (SPS_EQUALS_A.getCommandByte() + 0x02))
+        .setCommand(SPS_EQUALS_A));
+    datas.add(new SPSCommandDataImpl() {
+      @Override
+      public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
+        ((HoltekEmulatorInternals) internals).address++;
+        return HoltekEmulator.getInstance().getEmulatorOutput();
+      }
+    }.setName("D=A").setMnemonic("DEA").setCommandByte((byte) (SPS_EQUALS_A.getCommandByte() + 0x03))
+        .setCommand(SPS_EQUALS_A));
+    datas.add(new SPSCommandDataImpl() {
+      @Override
+      public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
+        ((HoltekEmulatorInternals) internals).address++;
+        return HoltekEmulator.getInstance().getEmulatorOutput();
+      }
+    }.setName("Output=A").setMnemonic("OEA").setCommandByte((byte) (SPS_EQUALS_A.getCommandByte() + 0x04))
+        .setCommand(SPS_EQUALS_A));
+    datas.add(new SPSCommandDataImpl() {
+      @Override
+      public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
+        ((HoltekEmulatorInternals) internals).address++;
+        return HoltekEmulator.getInstance().getEmulatorOutput();
+      }
+    }.setName("Output.1=A").setMnemonic("O1EA").setCommandByte((byte) (SPS_EQUALS_A.getCommandByte() + 0x05))
+        .setCommand(SPS_EQUALS_A));
+    datas.add(new SPSCommandDataImpl() {
+      @Override
+      public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
+        ((HoltekEmulatorInternals) internals).address++;
+        return HoltekEmulator.getInstance().getEmulatorOutput();
+      }
+    }.setName("Output.2=A").setMnemonic("O2EA").setCommandByte((byte) (SPS_EQUALS_A.getCommandByte() + 0x06))
+        .setCommand(SPS_EQUALS_A));
+    datas.add(new SPSCommandDataImpl() {
+      @Override
+      public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
+        ((HoltekEmulatorInternals) internals).address++;
+        return HoltekEmulator.getInstance().getEmulatorOutput();
+      }
+    }.setName("Output.3=A").setMnemonic("O3EA").setCommandByte((byte) (SPS_EQUALS_A.getCommandByte() + 0x07))
+        .setCommand(SPS_EQUALS_A));
+    datas.add(new SPSCommandDataImpl() {
+      @Override
+      public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
+        ((HoltekEmulatorInternals) internals).address++;
+        return HoltekEmulator.getInstance().getEmulatorOutput();
+      }
+    }.setName("Output.4=A").setMnemonic("O4EA").setCommandByte((byte) (SPS_EQUALS_A.getCommandByte() + 0x08))
+        .setCommand(SPS_EQUALS_A));
+    datas.add(new SPSCommandDataImpl() {
+      @Override
+      public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
+        ((HoltekEmulatorInternals) internals).address++;
+        return HoltekEmulator.getInstance().getEmulatorOutput();
+      }
+    }.setName("PWM=A").setMnemonic("PEA").setCommandByte((byte) (SPS_EQUALS_A.getCommandByte() + 0x09))
+        .setCommand(SPS_EQUALS_A));
+  }
+
+  private static SPSCommand SPS_A_INPUT = new SPSCommandImpl().setName("A=(some input)").setMnemonic("AEI")
+      .setCommandByte((byte) 0x60);
+  static {
+    List<SPSCommandData> datas = SPS_A_INPUT.getCommandDatas();
+    datas.add(new SPSCommandDataImpl() {
+      @Override
+      public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
+        ((HoltekEmulatorInternals) internals).address++;
+        return HoltekEmulator.getInstance().getEmulatorOutput();
+      }
+    }.setName("A=B").setMnemonic("AEB").setCommandByte((byte) (SPS_A_INPUT.getCommandByte() + 0x01))
+        .setCommand(SPS_A_INPUT));
+    datas.add(new SPSCommandDataImpl() {
+      @Override
+      public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
+        ((HoltekEmulatorInternals) internals).address++;
+        return HoltekEmulator.getInstance().getEmulatorOutput();
+      }
+    }.setName("A=C").setMnemonic("AEC").setCommandByte((byte) (SPS_A_INPUT.getCommandByte() + 0x02))
+        .setCommand(SPS_A_INPUT));
+    datas.add(new SPSCommandDataImpl() {
+      @Override
+      public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
+        ((HoltekEmulatorInternals) internals).address++;
+        return HoltekEmulator.getInstance().getEmulatorOutput();
+      }
+    }.setName("A=D").setMnemonic("AED").setCommandByte((byte) (SPS_A_INPUT.getCommandByte() + 0x03))
+        .setCommand(SPS_A_INPUT));
+    datas.add(new SPSCommandDataImpl() {
+      @Override
+      public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
+        ((HoltekEmulatorInternals) internals).address++;
+        return HoltekEmulator.getInstance().getEmulatorOutput();
+      }
+    }.setName("A=Input").setMnemonic("AEI").setCommandByte((byte) (SPS_A_INPUT.getCommandByte() + 0x04))
+        .setCommand(SPS_A_INPUT));
+    datas.add(new SPSCommandDataImpl() {
+      @Override
+      public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
+        ((HoltekEmulatorInternals) internals).address++;
+        return HoltekEmulator.getInstance().getEmulatorOutput();
+      }
+    }.setName("A=Input.1").setMnemonic("AEI1").setCommandByte((byte) (SPS_A_INPUT.getCommandByte() + 0x05))
+        .setCommand(SPS_A_INPUT));
+    datas.add(new SPSCommandDataImpl() {
+      @Override
+      public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
+        ((HoltekEmulatorInternals) internals).address++;
+        return HoltekEmulator.getInstance().getEmulatorOutput();
+      }
+    }.setName("A=Input.2").setMnemonic("AEI2").setCommandByte((byte) (SPS_A_INPUT.getCommandByte() + 0x06))
+        .setCommand(SPS_A_INPUT));
+    datas.add(new SPSCommandDataImpl() {
+      @Override
+      public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
+        ((HoltekEmulatorInternals) internals).address++;
+        return HoltekEmulator.getInstance().getEmulatorOutput();
+      }
+    }.setName("A=Input.3").setMnemonic("AEI3").setCommandByte((byte) (SPS_A_INPUT.getCommandByte() + 0x07))
+        .setCommand(SPS_A_INPUT));
+    datas.add(new SPSCommandDataImpl() {
+      @Override
+      public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
+        ((HoltekEmulatorInternals) internals).address++;
+        return HoltekEmulator.getInstance().getEmulatorOutput();
+      }
+    }.setName("A=Input.4").setMnemonic("AEI4").setCommandByte((byte) (SPS_A_INPUT.getCommandByte() + 0x08))
+        .setCommand(SPS_A_INPUT));
+    datas.add(new SPSCommandDataImpl() {
+      @Override
+      public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
+        ((HoltekEmulatorInternals) internals).address++;
+        return HoltekEmulator.getInstance().getEmulatorOutput();
+      }
+    }.setName("A=AD.1").setMnemonic("AEA1").setCommandByte((byte) (SPS_A_INPUT.getCommandByte() + 0x09))
+        .setCommand(SPS_A_INPUT));
+    datas.add(new SPSCommandDataImpl() {
+      @Override
+      public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
+        ((HoltekEmulatorInternals) internals).address++;
+        return HoltekEmulator.getInstance().getEmulatorOutput();
+      }
+    }.setName("A=AD.2").setMnemonic("AEA2").setCommandByte((byte) (SPS_A_INPUT.getCommandByte() + 0x0A))
+        .setCommand(SPS_A_INPUT));
+  }
+
+  private static SPSCommand SPS_A_CALCULATE = new SPSCommandImpl().setName("Calculate with A").setMnemonic("CALC")
+      .setCommandByte((byte) 0x70);
+  static {
+    List<SPSCommandData> datas = SPS_A_CALCULATE.getCommandDatas();
+    datas.add(new SPSCommandDataImpl() {
+      @Override
+      public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
+        ((HoltekEmulatorInternals) internals).address++;
+        return HoltekEmulator.getInstance().getEmulatorOutput();
+      }
+    }.setName("A=A+1").setMnemonic("INCA").setCommandByte((byte) (SPS_A_CALCULATE.getCommandByte() + 0x01))
+        .setCommand(SPS_A_CALCULATE));
+    datas.add(new SPSCommandDataImpl() {
+      @Override
+      public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
+        ((HoltekEmulatorInternals) internals).address++;
+        return HoltekEmulator.getInstance().getEmulatorOutput();
+      }
+    }.setName("A=A-1").setMnemonic("DECA").setCommandByte((byte) (SPS_A_CALCULATE.getCommandByte() + 0x02))
+        .setCommand(SPS_A_CALCULATE));
+    datas.add(new SPSCommandDataImpl() {
+      @Override
+      public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
+        ((HoltekEmulatorInternals) internals).address++;
+        return HoltekEmulator.getInstance().getEmulatorOutput();
+      }
+    }.setName("A=A+B").setMnemonic("ADDB").setCommandByte((byte) (SPS_A_CALCULATE.getCommandByte() + 0x03))
+        .setCommand(SPS_A_CALCULATE));
+    datas.add(new SPSCommandDataImpl() {
+      @Override
+      public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
+        ((HoltekEmulatorInternals) internals).address++;
+        return HoltekEmulator.getInstance().getEmulatorOutput();
+      }
+    }.setName("A=A-B").setMnemonic("SUBB").setCommandByte((byte) (SPS_A_CALCULATE.getCommandByte() + 0x04))
+        .setCommand(SPS_A_CALCULATE));
+    datas.add(new SPSCommandDataImpl() {
+      @Override
+      public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
+        ((HoltekEmulatorInternals) internals).address++;
+        return HoltekEmulator.getInstance().getEmulatorOutput();
+      }
+    }.setName("A=A*B").setMnemonic("MULB").setCommandByte((byte) (SPS_A_CALCULATE.getCommandByte() + 0x05))
+        .setCommand(SPS_A_CALCULATE));
+    datas.add(new SPSCommandDataImpl() {
+      @Override
+      public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
+        ((HoltekEmulatorInternals) internals).address++;
+        return HoltekEmulator.getInstance().getEmulatorOutput();
+      }
+    }.setName("A=A/B").setMnemonic("DIVB").setCommandByte((byte) (SPS_A_CALCULATE.getCommandByte() + 0x06))
+        .setCommand(SPS_A_CALCULATE));
+    datas.add(new SPSCommandDataImpl() {
+      @Override
+      public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
+        ((HoltekEmulatorInternals) internals).address++;
+        return HoltekEmulator.getInstance().getEmulatorOutput();
+      }
+    }.setName("A=A AND B").setMnemonic("ANDB").setCommandByte((byte) (SPS_A_CALCULATE.getCommandByte() + 0x07))
+        .setCommand(SPS_A_CALCULATE));
+    datas.add(new SPSCommandDataImpl() {
+      @Override
+      public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
+        ((HoltekEmulatorInternals) internals).address++;
+        return HoltekEmulator.getInstance().getEmulatorOutput();
+      }
+    }.setName("A=A OR B").setMnemonic("ORB").setCommandByte((byte) (SPS_A_CALCULATE.getCommandByte() + 0x08))
+        .setCommand(SPS_A_CALCULATE));
+    datas.add(new SPSCommandDataImpl() {
+      @Override
+      public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
+        ((HoltekEmulatorInternals) internals).address++;
+        return HoltekEmulator.getInstance().getEmulatorOutput();
+      }
+    }.setName("A=A XOR B").setMnemonic("XORB").setCommandByte((byte) (SPS_A_CALCULATE.getCommandByte() + 0x09))
+        .setCommand(SPS_A_CALCULATE));
+    datas.add(new SPSCommandDataImpl() {
+      @Override
+      public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
+        ((HoltekEmulatorInternals) internals).address++;
+        return HoltekEmulator.getInstance().getEmulatorOutput();
+      }
+    }.setName("A=NOT A").setMnemonic("NOTA").setCommandByte((byte) (SPS_A_CALCULATE.getCommandByte() + 0x0A))
+        .setCommand(SPS_A_CALCULATE));
+  }
+
+  private static SPSCommand SPS_PAGE = new SPSCommandImpl().setName("Page").setMnemonic("PG")
+      .setCommandByte((byte) 0x80);
+  static {
+    for (int i = 0; i < 8; i++) {
+      SPS_PAGE.getCommandDatas().add(new SPSCommandDataImpl() {
+        @Override
+        public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
+          ((HoltekEmulatorInternals) internals).address++;
+          return HoltekEmulator.getInstance().getEmulatorOutput();
+        }
+      }.setName("Page " + Integer.toString(i)).setMnemonic("PG" + Integer.toString(i))
+          .setCommandByte((byte) (SPS_PAGE.getCommandByte() + i)).setCommand(SPS_PAGE));
+    }
+  }
+
+  private static SPSCommand SPS_JUMP_UP = new SPSCommandImpl().setName("Jump").setMnemonic("JMP")
+      .setCommandByte((byte) 0x90);
+  static {
+    for (int i = 0; i < 16; i++) {
+      SPS_JUMP_UP.getCommandDatas().add(new SPSCommandDataImpl() {
+        @Override
+        public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
+          ((HoltekEmulatorInternals) internals).address++;
+          return HoltekEmulator.getInstance().getEmulatorOutput();
+        }
+      }.setName("Jump " + Integer.toString(i)).setMnemonic("JMP" + Integer.toString(i))
+          .setCommandByte((byte) (SPS_JUMP_UP.getCommandByte() + i)).setCommand(SPS_JUMP_UP));
+    }
+  }
+
+  private static SPSCommand SPS_C_LOOP = new SPSCommandImpl().setName("C* Loop").setMnemonic("CLOP")
+      .setCommandByte((byte) 0xA0);
+  static {
+    for (int i = 0; i < 16; i++) {
+      SPS_C_LOOP.getCommandDatas().add(new SPSCommandDataImpl() {
+        @Override
+        public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
+          ((HoltekEmulatorInternals) internals).address++;
+          return HoltekEmulator.getInstance().getEmulatorOutput();
+        }
+      }.setName("C* Loop " + Integer.toString(i)).setMnemonic("CLOP" + Integer.toString(i))
+          .setCommandByte((byte) (SPS_C_LOOP.getCommandByte() + i)).setCommand(SPS_C_LOOP));
+    }
+  }
+
+  private static SPSCommand SPS_D_LOOP = new SPSCommandImpl().setName("D* Loop").setMnemonic("DLOP")
+      .setCommandByte((byte) 0xB0);
+  static {
+    for (int i = 0; i < 16; i++) {
+      SPS_D_LOOP.getCommandDatas().add(new SPSCommandDataImpl() {
+        @Override
+        public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
+          ((HoltekEmulatorInternals) internals).address++;
+          return HoltekEmulator.getInstance().getEmulatorOutput();
+        }
+      }.setName("D* Loop " + Integer.toString(i)).setMnemonic("DLOP" + Integer.toString(i))
+          .setCommandByte((byte) (SPS_D_LOOP.getCommandByte() + i)).setCommand(SPS_D_LOOP));
+    }
+  }
+
+  private static SPSCommand SPS_SKIP_IF = new SPSCommandImpl().setName("Skip if").setMnemonic("SKIP")
+      .setCommandByte((byte) 0xC0);
+  static {
+    SPS_SKIP_IF.getCommandDatas().add(new SPSCommandDataImpl() {
+      @Override
+      public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
+        ((HoltekEmulatorInternals) internals).address++;
+        return HoltekEmulator.getInstance().getEmulatorOutput();
+      }
+    }.setName("A>B").setMnemonic("AGRB").setCommandByte((byte) (SPS_SKIP_IF.getCommandByte() + 0x01))
+        .setCommand(SPS_SKIP_IF));
+    SPS_SKIP_IF.getCommandDatas().add(new SPSCommandDataImpl() {
+      @Override
+      public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
+        ((HoltekEmulatorInternals) internals).address++;
+        return HoltekEmulator.getInstance().getEmulatorOutput();
+      }
+    }.setName("A<B").setMnemonic("ASMB").setCommandByte((byte) (SPS_SKIP_IF.getCommandByte() + 0x02))
+        .setCommand(SPS_SKIP_IF));
+    SPS_SKIP_IF.getCommandDatas().add(new SPSCommandDataImpl() {
+      @Override
+      public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
+        ((HoltekEmulatorInternals) internals).address++;
+        return HoltekEmulator.getInstance().getEmulatorOutput();
+      }
+    }.setName("A=B").setMnemonic("AEQB").setCommandByte((byte) (SPS_SKIP_IF.getCommandByte() + 0x03))
+        .setCommand(SPS_SKIP_IF));
+    SPS_SKIP_IF.getCommandDatas().add(new SPSCommandDataImpl() {
+      @Override
+      public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
+        ((HoltekEmulatorInternals) internals).address++;
+        return HoltekEmulator.getInstance().getEmulatorOutput();
+      }
+    }.setName("In.1=1").setMnemonic("IN11").setCommandByte((byte) (SPS_SKIP_IF.getCommandByte() + 0x04))
+        .setCommand(SPS_SKIP_IF));
+    SPS_SKIP_IF.getCommandDatas().add(new SPSCommandDataImpl() {
+      @Override
+      public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
+        ((HoltekEmulatorInternals) internals).address++;
+        return HoltekEmulator.getInstance().getEmulatorOutput();
+      }
+    }.setName("In.2=1").setMnemonic("IN21").setCommandByte((byte) (SPS_SKIP_IF.getCommandByte() + 0x05))
+        .setCommand(SPS_SKIP_IF));
+    SPS_SKIP_IF.getCommandDatas().add(new SPSCommandDataImpl() {
+      @Override
+      public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
+        ((HoltekEmulatorInternals) internals).address++;
+        return HoltekEmulator.getInstance().getEmulatorOutput();
+      }
+    }.setName("In.3=1").setMnemonic("IN31").setCommandByte((byte) (SPS_SKIP_IF.getCommandByte() + 0x06))
+        .setCommand(SPS_SKIP_IF));
+    SPS_SKIP_IF.getCommandDatas().add(new SPSCommandDataImpl() {
+      @Override
+      public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
+        ((HoltekEmulatorInternals) internals).address++;
+        return HoltekEmulator.getInstance().getEmulatorOutput();
+      }
+    }.setName("In.4=1").setMnemonic("IN41").setCommandByte((byte) (SPS_SKIP_IF.getCommandByte() + 0x07))
+        .setCommand(SPS_SKIP_IF));
+    SPS_SKIP_IF.getCommandDatas().add(new SPSCommandDataImpl() {
+      @Override
+      public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
+        ((HoltekEmulatorInternals) internals).address++;
+        return HoltekEmulator.getInstance().getEmulatorOutput();
+      }
+    }.setName("In.1=0").setMnemonic("IN10").setCommandByte((byte) (SPS_SKIP_IF.getCommandByte() + 0x08))
+        .setCommand(SPS_SKIP_IF));
+    SPS_SKIP_IF.getCommandDatas().add(new SPSCommandDataImpl() {
+      @Override
+      public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
+        ((HoltekEmulatorInternals) internals).address++;
+        return HoltekEmulator.getInstance().getEmulatorOutput();
+      }
+    }.setName("In.2=0").setMnemonic("IN20").setCommandByte((byte) (SPS_SKIP_IF.getCommandByte() + 0x09))
+        .setCommand(SPS_SKIP_IF));
+    SPS_SKIP_IF.getCommandDatas().add(new SPSCommandDataImpl() {
+      @Override
+      public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
+        ((HoltekEmulatorInternals) internals).address++;
+        return HoltekEmulator.getInstance().getEmulatorOutput();
+      }
+    }.setName("In.3=0").setMnemonic("IN30").setCommandByte((byte) (SPS_SKIP_IF.getCommandByte() + 0x0A))
+        .setCommand(SPS_SKIP_IF));
+    SPS_SKIP_IF.getCommandDatas().add(new SPSCommandDataImpl() {
+      @Override
+      public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
+        ((HoltekEmulatorInternals) internals).address++;
+        return HoltekEmulator.getInstance().getEmulatorOutput();
+      }
+    }.setName("In.4=0").setMnemonic("IN40").setCommandByte((byte) (SPS_SKIP_IF.getCommandByte() + 0x0B))
+        .setCommand(SPS_SKIP_IF));
+    SPS_SKIP_IF.getCommandDatas().add(new SPSCommandDataImpl() {
+      @Override
+      public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
+        ((HoltekEmulatorInternals) internals).address++;
+        return HoltekEmulator.getInstance().getEmulatorOutput();
+      }
+    }.setName("S1=0").setMnemonic("S10").setCommandByte((byte) (SPS_SKIP_IF.getCommandByte() + 0x0C))
+        .setCommand(SPS_SKIP_IF));
+    SPS_SKIP_IF.getCommandDatas().add(new SPSCommandDataImpl() {
+      @Override
+      public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
+        ((HoltekEmulatorInternals) internals).address++;
+        return HoltekEmulator.getInstance().getEmulatorOutput();
+      }
+    }.setName("S2=0").setMnemonic("S20").setCommandByte((byte) (SPS_SKIP_IF.getCommandByte() + 0x0D))
+        .setCommand(SPS_SKIP_IF));
+    SPS_SKIP_IF.getCommandDatas().add(new SPSCommandDataImpl() {
+      @Override
+      public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
+        ((HoltekEmulatorInternals) internals).address++;
+        return HoltekEmulator.getInstance().getEmulatorOutput();
+      }
+    }.setName("S1=1").setMnemonic("S11").setCommandByte((byte) (SPS_SKIP_IF.getCommandByte() + 0x0E))
+        .setCommand(SPS_SKIP_IF));
+    SPS_SKIP_IF.getCommandDatas().add(new SPSCommandDataImpl() {
+      @Override
+      public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
+        ((HoltekEmulatorInternals) internals).address++;
+        return HoltekEmulator.getInstance().getEmulatorOutput();
+      }
+    }.setName("S2=1").setMnemonic("S21").setCommandByte((byte) (SPS_SKIP_IF.getCommandByte() + 0x0F))
+        .setCommand(SPS_SKIP_IF));
+  };
+
+  private static SPSCommand SPS_CALL = new SPSCommandImpl().setName("Call").setMnemonic("CALL")
+      .setCommandByte((byte) 0xD0);
+  static {
+    for (int i = 0; i < 16; i++) {
+      SPS_CALL.getCommandDatas().add(new SPSCommandDataImpl() {
+        @Override
+        public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
+          ((HoltekEmulatorInternals) internals).address++;
+          return HoltekEmulator.getInstance().getEmulatorOutput();
+        }
+      }.setName("Call " + Integer.toString(i)).setMnemonic("CALL" + Integer.toString(i))
+          .setCommandByte((byte) (SPS_CALL.getCommandByte() + i)).setCommand(SPS_CALL));
+    }
+  }
+
+  private static SPSCommand SPS_RETURN = new SPSCommandImpl().setName("return").setMnemonic("RET")
+      .setCommandByte((byte) 0xE0);
+  private static HoltekEmulator instance;
+  static {
+    SPS_RETURN.getCommandDatas().add(new SPSCommandDataImpl() {
+      @Override
+      public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
+        ((HoltekEmulatorInternals) internals).address++;
+        return HoltekEmulator.getInstance().getEmulatorOutput();
+      }
+    }.setName("Return").setMnemonic("RET").setCommandByte((byte) (SPS_RETURN.getCommandByte())).setCommand(SPS_RETURN));
+  }
+
+  protected static HoltekEmulator getInstance() {
+    return instance;
+  }
+
+  public HoltekEmulator() {
+    instance = this;
+  }
+
+  @Override
+  public List<SPSCommand> getCommands() {
+    return commands;
+  }
+
+  @Override
+  public int getProgramSize() {
+    return 128;
+  }
+
+  @Override
+  protected void reset() {
+    getEmulatorOutput().reset();
+    getEmulatorInternals().reset();
+    System.out.println("holtec emulator resettet");
+
+  }
+
+  @Override
+  protected void callNextCommand() {
+    byte command = programMemory[getEmulatorInternals().getAddress()];
+    SPSCommandData commandData = getCommandData(command);
+    runCommand(commandData);
+  }
+
+  @Override
+  protected EmulatorInput createEmulatorInput() {
+    return new HoltekEmulatorInput();
+  }
+
+  @Override
+  protected EmulatorOutput createEmulatorOutput() {
+    return new HoltekEmulatorOutput();
+  }
+
+  @Override
+  protected EmulatorInternals createEmulatorInternals() {
+    return new HoltekEmulatorInternals();
+  }
+
+}

+ 14 - 0
src/main/java/de/mcs/tools/sps/holtec/HoltekEmulatorInput.java

@@ -0,0 +1,14 @@
+/**
+ * 
+ */
+package de.mcs.tools.sps.holtec;
+
+import de.mcs.tools.sps.EmulatorInput;
+
+/**
+ * @author w.klaas
+ *
+ */
+public class HoltekEmulatorInput implements EmulatorInput {
+
+}

+ 48 - 0
src/main/java/de/mcs/tools/sps/holtec/HoltekEmulatorInternals.java

@@ -0,0 +1,48 @@
+/**
+ * 
+ */
+package de.mcs.tools.sps.holtec;
+
+import de.mcs.tools.sps.EmulatorInternals;
+
+/**
+ * @author w.klaas
+ *
+ */
+public class HoltekEmulatorInternals implements EmulatorInternals {
+  int address;
+  int a, b, c, d;
+  int page;
+  long delay;
+
+  @Override
+  public void reset() {
+    address = 0x00;
+    a = 0;
+    b = 0;
+    c = 0;
+    d = 0;
+    page = 0;
+  }
+
+  @Override
+  public int getAddress() {
+    return address;
+  }
+
+  @Override
+  public void incAddress(int i) {
+    address += i;
+  }
+
+  @Override
+  public void setDelay(long l) {
+    delay = l;
+  }
+
+  @Override
+  public long getDelay() {
+    return delay;
+  }
+
+}

+ 26 - 0
src/main/java/de/mcs/tools/sps/holtec/HoltekEmulatorOutput.java

@@ -0,0 +1,26 @@
+/**
+ * 
+ */
+package de.mcs.tools.sps.holtec;
+
+import de.mcs.tools.sps.EmulatorOutput;
+
+/**
+ * @author w.klaas
+ *
+ */
+public class HoltekEmulatorOutput implements EmulatorOutput {
+
+  boolean d0, d1, d2, d3;
+  int pwm;
+
+  @Override
+  public void reset() {
+    d0 = false;
+    d1 = false;
+    d2 = false;
+    d3 = false;
+    pwm = 0;
+  }
+
+}

+ 35 - 0
src/main/java/de/mcs/tools/sps/holtec/SPSCommandDataJumpDown.java

@@ -0,0 +1,35 @@
+/**
+ * 
+ */
+package de.mcs.tools.sps.holtec;
+
+import de.mcs.tools.sps.EmulatorInput;
+import de.mcs.tools.sps.EmulatorInternals;
+import de.mcs.tools.sps.EmulatorOutput;
+import de.mcs.tools.sps.SPSCommandDataImpl;
+
+/**
+ * @author w.klaas
+ *
+ */
+public class SPSCommandDataJumpDown extends SPSCommandDataImpl {
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * de.mcs.tools.sps.SPSCommandDataImpl#doWork(de.mcs.tools.sps.EmulatorInput,
+   * de.mcs.tools.sps.EmulatorInternals)
+   */
+  @Override
+  public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
+    byte data = getData();
+    if ((data >= 0) && (data < 16)) {
+      internals.incAddress(-1 * data);
+    } else {
+      throw new IllegalArgumentException(String.format("jump target %d illegal", data));
+    }
+    return output;
+  }
+
+}

+ 30 - 0
src/main/java/de/mcs/tools/sps/holtec/SPSCommandDataNOP.java

@@ -0,0 +1,30 @@
+/**
+ * 
+ */
+package de.mcs.tools.sps.holtec;
+
+import de.mcs.tools.sps.EmulatorInput;
+import de.mcs.tools.sps.EmulatorInternals;
+import de.mcs.tools.sps.EmulatorOutput;
+import de.mcs.tools.sps.SPSCommandDataImpl;
+
+/**
+ * @author w.klaas
+ *
+ */
+public class SPSCommandDataNOP extends SPSCommandDataImpl {
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * de.mcs.tools.sps.SPSCommandDataImpl#doWork(de.mcs.tools.sps.EmulatorInput,
+   * de.mcs.tools.sps.EmulatorInternals)
+   */
+  @Override
+  public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
+    internals.incAddress(1);
+    return output;
+  }
+
+}

+ 72 - 0
src/main/java/de/mcs/tools/sps/holtec/SPSCommandDataWait.java

@@ -0,0 +1,72 @@
+/**
+ * 
+ */
+package de.mcs.tools.sps.holtec;
+
+import de.mcs.tools.sps.EmulatorInput;
+import de.mcs.tools.sps.EmulatorInternals;
+import de.mcs.tools.sps.EmulatorOutput;
+import de.mcs.tools.sps.SPSCommandDataImpl;
+
+/**
+ * @author w.klaas
+ *
+ */
+public class SPSCommandDataWait extends SPSCommandDataImpl {
+
+  private static final long[] WAIT_TIMES = new long[] {
+      // @formatter-off
+      1, 2, 5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000, 20000, 30000, 60000
+      // @formatter-on
+  };
+
+  private static final String[] WAIT_NAMES = new String[] {
+      // @formatter-off
+      "1ms", "2ms", "5ms", "10ms", "20ms", "50ms", "100ms", "200ms", "500ms", "1s", "2s", "5s", "10s", "20s", "30s",
+      "60s"
+      // @formatter-on
+  };
+
+  static String getName(int i) {
+    return String.format("Wait %s", WAIT_NAMES[i]);
+  }
+
+  static String getMnemonic(int i) {
+    return String.format("D", WAIT_NAMES[i]).toUpperCase();
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see
+   * de.mcs.tools.sps.SPSCommandDataImpl#doWork(de.mcs.tools.sps.EmulatorInput,
+   * de.mcs.tools.sps.EmulatorInternals)
+   */
+  @Override
+  public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
+    byte data = getData();
+    if ((data >= 0) && (data < 16)) {
+      try {
+        internals.setDelay(WAIT_TIMES[data]);
+        long delay = WAIT_TIMES[data];
+        if (delay <= 100) {
+          Thread.sleep(delay);
+        } else {
+          long count = delay / 100;
+          while (count > 0) {
+            count--;
+            Thread.sleep(100);
+            internals.setDelay(count * 100);
+          }
+        }
+      } catch (InterruptedException e) {
+        e.printStackTrace();
+      }
+    } else {
+      throw new IllegalArgumentException(String.format("Wait time %d illegal", data));
+    }
+    internals.incAddress(1);
+    return output;
+  }
+
+}

+ 77 - 15
src/test/java/de/mcs/tools/sps/holtec/TestHoltecEmualtor.java → src/test/java/de/mcs/tools/sps/holtec/TestHoltekEmulator.java

@@ -1,7 +1,9 @@
 package de.mcs.tools.sps.holtec;
 
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 
 import java.util.ArrayList;
@@ -18,20 +20,20 @@ import de.mcs.tools.sps.SPSEmulator;
 import de.mcs.tools.sps.TOutputCallback;
 import de.mcs.tools.sps.exceptions.WrongProgramSizeException;
 
-class TestHoltecEmualtor implements TOutputCallback {
+class TestHoltekEmulator implements TOutputCallback {
 
-  private SPSEmulator holtectEmulator;
+  private SPSEmulator holtekEmulator;
 
   @BeforeEach
   void setUp() throws Exception {
-    holtectEmulator = new HoltecEmulator();
-    holtectEmulator.addCallback(this);
+    holtekEmulator = new HoltekEmulator();
+    holtekEmulator.addCallback(this);
   }
 
   @Test
   void testOutputAllCommands() {
     System.out.println("command list holtect");
-    List<SPSCommand> commands = holtectEmulator.getCommands();
+    List<SPSCommand> commands = holtekEmulator.getCommands();
     commands.forEach(c -> {
       List<SPSCommandData> commandDatas = c.getCommandDatas();
       System.out.printf("Command %s(%s):", c.getMnemonic(), c.getName());
@@ -44,20 +46,20 @@ class TestHoltecEmualtor implements TOutputCallback {
 
   @Test
   void testProgramSize() throws WrongProgramSizeException {
-    assertEquals(128, holtectEmulator.getProgramSize());
+    assertEquals(128, holtekEmulator.getProgramSize());
     byte[] prgMemory = new byte[128];
-    holtectEmulator.loadProgram(prgMemory);
+    holtekEmulator.loadProgram(prgMemory);
   }
 
   @Test
   void testWrongProgramSize() throws WrongProgramSizeException {
     byte[] prgMemory = new byte[129];
-    Throwable exception = assertThrows(WrongProgramSizeException.class, () -> holtectEmulator.loadProgram(prgMemory));
+    Throwable exception = assertThrows(WrongProgramSizeException.class, () -> holtekEmulator.loadProgram(prgMemory));
   }
 
   @Test
   void testCommandArray() {
-    List<SPSCommand> commands = holtectEmulator.getCommands();
+    List<SPSCommand> commands = holtekEmulator.getCommands();
     assertEquals(15, commands.size());
     for (SPSCommand spsCommand : commands) {
       switch (spsCommand.getCommandByte()) {
@@ -118,11 +120,11 @@ class TestHoltecEmualtor implements TOutputCallback {
     outputList.clear();
     internalList.clear();
     byte[] prg = new byte[] { 0x00, 0x00, 0x00 };
-    holtectEmulator.loadProgram(prg);
-    holtectEmulator.startProgram(true);
-    holtectEmulator.nextStep();
-    holtectEmulator.nextStep();
-    holtectEmulator.nextStep();
+    holtekEmulator.loadProgram(prg);
+    holtekEmulator.startProgram(true);
+    holtekEmulator.nextStep();
+    holtekEmulator.nextStep();
+    holtekEmulator.nextStep();
 
     assertEquals(4, outputList.size());
     assertEquals(4, internalList.size());
@@ -134,6 +136,66 @@ class TestHoltecEmualtor implements TOutputCallback {
   @Override
   public void onOutput(EmulatorOutput output) {
     outputList.add(output);
-    internalList.add(holtectEmulator.getInternals());
+    internalList.add(holtekEmulator.getEmulatorInternals());
   }
+
+  @Test
+  void testPort() throws WrongProgramSizeException {
+    byte[] prg = new byte[] { 0x10, 0x1F, 0x10 };
+    holtekEmulator.loadProgram(prg);
+    holtekEmulator.startProgram(true);
+    holtekEmulator.nextStep();
+    HoltekEmulatorOutput emulatorOutput = (HoltekEmulatorOutput) holtekEmulator.getEmulatorOutput();
+    assertFalse(emulatorOutput.d0);
+    assertFalse(emulatorOutput.d1);
+    assertFalse(emulatorOutput.d2);
+    assertFalse(emulatorOutput.d3);
+    holtekEmulator.nextStep();
+    assertTrue(emulatorOutput.d0);
+    assertTrue(emulatorOutput.d1);
+    assertTrue(emulatorOutput.d2);
+    assertTrue(emulatorOutput.d3);
+    holtekEmulator.nextStep();
+    assertFalse(emulatorOutput.d0);
+    assertFalse(emulatorOutput.d1);
+    assertFalse(emulatorOutput.d2);
+    assertFalse(emulatorOutput.d3);
+  }
+
+  @Test
+  void testDelay() throws WrongProgramSizeException {
+    byte[] prg = new byte[] { 0x29, 0x2C };
+    holtekEmulator.loadProgram(prg);
+    holtekEmulator.startProgram(true);
+    long start = System.currentTimeMillis();
+    holtekEmulator.nextStep();
+    long delta = System.currentTimeMillis() - start;
+    assertTrue(delta > 900 && delta < 1100);
+    start = System.currentTimeMillis();
+    holtekEmulator.nextStep();
+    delta = System.currentTimeMillis() - start;
+    assertTrue(delta > 9000 && delta < 10100);
+  }
+
+  @Test
+  void testJumpDown() throws WrongProgramSizeException {
+    byte[] prg = new byte[] { 0x00, 0x00, 0x32 };
+    holtekEmulator.loadProgram(prg);
+    holtekEmulator.startProgram(true);
+    holtekEmulator.nextStep();
+    holtekEmulator.nextStep();
+    int addr = holtekEmulator.getEmulatorInternals().getAddress();
+    holtekEmulator.nextStep();
+    assertEquals(0x00, holtekEmulator.getEmulatorInternals().getAddress());
+
+    prg = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39 };
+    holtekEmulator.loadProgram(prg);
+    holtekEmulator.startProgram(true);
+    holtekEmulator.nextStep();
+    holtekEmulator.nextStep();
+    addr = holtekEmulator.getEmulatorInternals().getAddress();
+    holtekEmulator.nextStep();
+    assertEquals(0x03, holtekEmulator.getEmulatorInternals().getAddress());
+  }
+
 }