Jelajahi Sumber

testing and implementing commands

- Calculate A
- Page
- Jump
Klaas, Wilfried 6 tahun lalu
induk
melakukan
2ef0d6a127

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

@@ -64,7 +64,8 @@ public abstract class AbstractEmulator implements SPSEmulator {
 
   protected abstract EmulatorInternals createEmulatorInternals();
 
-  protected SPSCommandData getCommandData(byte command) {
+  @Override
+  public SPSCommandData getCommandData(byte command) {
     SPSCommandData commandData = null;
     byte commandByte = (byte) (command & (byte) 0xF0);
 

+ 4 - 2
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);
 
@@ -83,4 +83,6 @@ public interface SPSEmulator {
   EmulatorInternals getEmulatorInternals();
 
   EmulatorOutput getEmulatorOutput();
+
+  SPSCommandData getCommandData(byte command);
 }

+ 80 - 73
src/main/java/de/mcs/tools/sps/holtek/HoltekEmulator.java

@@ -112,7 +112,7 @@ public class HoltekEmulator extends AbstractEmulator implements SPSEmulator {
       @Override
       public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
         internals.setRegister("B", internals.getRegister("A"));
-        ((HoltekEmulatorInternals) internals).address++;
+        internals.incAddress(1);
         return output;
       }
     }.setName("B=A").setMnemonic("BEA").setCommandByte((byte) (SPS_EQUALS_A.getCommandByte() + 0x01))
@@ -121,8 +121,8 @@ public class HoltekEmulator extends AbstractEmulator implements SPSEmulator {
       @Override
       public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
         internals.setRegister("C", internals.getRegister("A"));
-        ((HoltekEmulatorInternals) internals).address++;
-        return HoltekEmulator.getInstance().getEmulatorOutput();
+        internals.incAddress(1);
+        return output;
       }
     }.setName("C=A").setMnemonic("CEA").setCommandByte((byte) (SPS_EQUALS_A.getCommandByte() + 0x02))
         .setCommand(SPS_EQUALS_A));
@@ -130,8 +130,8 @@ public class HoltekEmulator extends AbstractEmulator implements SPSEmulator {
       @Override
       public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
         internals.setRegister("D", internals.getRegister("A"));
-        ((HoltekEmulatorInternals) internals).address++;
-        return HoltekEmulator.getInstance().getEmulatorOutput();
+        internals.incAddress(1);
+        return output;
       }
     }.setName("D=A").setMnemonic("DEA").setCommandByte((byte) (SPS_EQUALS_A.getCommandByte() + 0x03))
         .setCommand(SPS_EQUALS_A));
@@ -140,8 +140,8 @@ public class HoltekEmulator extends AbstractEmulator implements SPSEmulator {
       public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
         HoltekEmulatorOutput emulatorOutput = (HoltekEmulatorOutput) output;
         emulatorOutput.setOutput(internals.getRegister("A"));
-        ((HoltekEmulatorInternals) internals).address++;
-        return HoltekEmulator.getInstance().getEmulatorOutput();
+        internals.incAddress(1);
+        return output;
       }
     }.setName("Output=A").setMnemonic("OEA").setCommandByte((byte) (SPS_EQUALS_A.getCommandByte() + 0x04))
         .setCommand(SPS_EQUALS_A));
@@ -153,7 +153,7 @@ public class HoltekEmulator extends AbstractEmulator implements SPSEmulator {
         byte dataOld = emulatorOutput.getOutput();
         byte data = (byte) ((dataOld & 0b00001110) + (dataNew & 0x01));
         emulatorOutput.setOutput(data);
-        ((HoltekEmulatorInternals) internals).address++;
+        internals.incAddress(1);
         return emulatorOutput;
       }
     }.setName("Output.1=A").setMnemonic("O1EA").setCommandByte((byte) (SPS_EQUALS_A.getCommandByte() + 0x05))
@@ -166,7 +166,7 @@ public class HoltekEmulator extends AbstractEmulator implements SPSEmulator {
         byte dataOld = emulatorOutput.getOutput();
         byte data = (byte) ((dataOld & 0b00001101) + ((dataNew & 0x01) << 1));
         emulatorOutput.setOutput(data);
-        ((HoltekEmulatorInternals) internals).address++;
+        internals.incAddress(1);
         return emulatorOutput;
       }
     }.setName("Output.2=A").setMnemonic("O2EA").setCommandByte((byte) (SPS_EQUALS_A.getCommandByte() + 0x06))
@@ -179,7 +179,7 @@ public class HoltekEmulator extends AbstractEmulator implements SPSEmulator {
         byte dataOld = emulatorOutput.getOutput();
         byte data = (byte) ((dataOld & 0b00001011) + ((dataNew & 0x01) << 2));
         emulatorOutput.setOutput(data);
-        ((HoltekEmulatorInternals) internals).address++;
+        internals.incAddress(1);
         return emulatorOutput;
       }
     }.setName("Output.3=A").setMnemonic("O3EA").setCommandByte((byte) (SPS_EQUALS_A.getCommandByte() + 0x07))
@@ -192,7 +192,7 @@ public class HoltekEmulator extends AbstractEmulator implements SPSEmulator {
         byte dataOld = emulatorOutput.getOutput();
         byte data = (byte) ((dataOld & 0b00000111) + ((dataNew & 0x01) << 3));
         emulatorOutput.setOutput(data);
-        ((HoltekEmulatorInternals) internals).address++;
+        internals.incAddress(1);
         return emulatorOutput;
       }
     }.setName("Output.4=A").setMnemonic("O4EA").setCommandByte((byte) (SPS_EQUALS_A.getCommandByte() + 0x08))
@@ -202,7 +202,7 @@ public class HoltekEmulator extends AbstractEmulator implements SPSEmulator {
       public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
         HoltekEmulatorOutput emulatorOutput = (HoltekEmulatorOutput) output;
         emulatorOutput.setFeature("PWM", internals.getRegister("A"));
-        ((HoltekEmulatorInternals) internals).address++;
+        internals.incAddress(1);
         return emulatorOutput;
       }
     }.setName("PWM=A").setMnemonic("PEA").setCommandByte((byte) (SPS_EQUALS_A.getCommandByte() + 0x09))
@@ -217,7 +217,7 @@ public class HoltekEmulator extends AbstractEmulator implements SPSEmulator {
       @Override
       public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
         internals.setRegister("A", internals.getRegister("B"));
-        ((HoltekEmulatorInternals) internals).address++;
+        internals.incAddress(1);
         return output;
       }
     }.setName("A=B").setMnemonic("AEB").setCommandByte((byte) (SPS_A_INPUT.getCommandByte() + 0x01))
@@ -226,7 +226,7 @@ public class HoltekEmulator extends AbstractEmulator implements SPSEmulator {
       @Override
       public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
         internals.setRegister("A", internals.getRegister("C"));
-        ((HoltekEmulatorInternals) internals).address++;
+        internals.incAddress(1);
         return output;
       }
     }.setName("A=C").setMnemonic("AEC").setCommandByte((byte) (SPS_A_INPUT.getCommandByte() + 0x02))
@@ -235,7 +235,7 @@ public class HoltekEmulator extends AbstractEmulator implements SPSEmulator {
       @Override
       public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
         internals.setRegister("A", internals.getRegister("D"));
-        ((HoltekEmulatorInternals) internals).address++;
+        internals.incAddress(1);
         return output;
       }
     }.setName("A=D").setMnemonic("AED").setCommandByte((byte) (SPS_A_INPUT.getCommandByte() + 0x03))
@@ -244,7 +244,7 @@ public class HoltekEmulator extends AbstractEmulator implements SPSEmulator {
       @Override
       public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
         internals.setRegister("A", input.getInput());
-        ((HoltekEmulatorInternals) internals).address++;
+        internals.incAddress(1);
         return output;
       }
     }.setName("A=Input").setMnemonic("AEI").setCommandByte((byte) (SPS_A_INPUT.getCommandByte() + 0x04))
@@ -254,7 +254,7 @@ public class HoltekEmulator extends AbstractEmulator implements SPSEmulator {
       public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
         boolean value = (input.getInput() & 0x01) > 0;
         internals.setRegister("A", (byte) (value ? 1 : 0));
-        ((HoltekEmulatorInternals) internals).address++;
+        internals.incAddress(1);
         return output;
       }
     }.setName("A=Input.1").setMnemonic("AEI1").setCommandByte((byte) (SPS_A_INPUT.getCommandByte() + 0x05))
@@ -264,7 +264,7 @@ public class HoltekEmulator extends AbstractEmulator implements SPSEmulator {
       public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
         boolean value = (input.getInput() & 0x02) > 0;
         internals.setRegister("A", (byte) (value ? 1 : 0));
-        ((HoltekEmulatorInternals) internals).address++;
+        internals.incAddress(1);
         return output;
       }
     }.setName("A=Input.2").setMnemonic("AEI2").setCommandByte((byte) (SPS_A_INPUT.getCommandByte() + 0x06))
@@ -274,7 +274,7 @@ public class HoltekEmulator extends AbstractEmulator implements SPSEmulator {
       public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
         boolean value = (input.getInput() & 0x04) > 0;
         internals.setRegister("A", (byte) (value ? 1 : 0));
-        ((HoltekEmulatorInternals) internals).address++;
+        internals.incAddress(1);
         return output;
       }
     }.setName("A=Input.3").setMnemonic("AEI3").setCommandByte((byte) (SPS_A_INPUT.getCommandByte() + 0x07))
@@ -284,7 +284,7 @@ public class HoltekEmulator extends AbstractEmulator implements SPSEmulator {
       public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
         boolean value = (input.getInput() & 0x08) > 0;
         internals.setRegister("A", (byte) (value ? 1 : 0));
-        ((HoltekEmulatorInternals) internals).address++;
+        internals.incAddress(1);
         return output;
       }
     }.setName("A=Input.4").setMnemonic("AEI4").setCommandByte((byte) (SPS_A_INPUT.getCommandByte() + 0x08))
@@ -293,7 +293,7 @@ public class HoltekEmulator extends AbstractEmulator implements SPSEmulator {
       @Override
       public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
         internals.setRegister("A", input.getFeature("AD1"));
-        ((HoltekEmulatorInternals) internals).address++;
+        internals.incAddress(1);
         return output;
       }
     }.setName("A=AD.1").setMnemonic("AEA1").setCommandByte((byte) (SPS_A_INPUT.getCommandByte() + 0x09))
@@ -302,7 +302,7 @@ public class HoltekEmulator extends AbstractEmulator implements SPSEmulator {
       @Override
       public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
         internals.setRegister("A", input.getFeature("AD2"));
-        ((HoltekEmulatorInternals) internals).address++;
+        internals.incAddress(1);
         return output;
       }
     }.setName("A=AD.2").setMnemonic("AEA2").setCommandByte((byte) (SPS_A_INPUT.getCommandByte() + 0x0A))
@@ -316,80 +316,90 @@ public class HoltekEmulator extends AbstractEmulator implements SPSEmulator {
     datas.add(new SPSCommandDataImpl() {
       @Override
       public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
-        ((HoltekEmulatorInternals) internals).address++;
-        return HoltekEmulator.getInstance().getEmulatorOutput();
+        internals.setRegister("A", (byte) (internals.getRegister("A") + 1));
+        internals.incAddress(1);
+        return output;
       }
     }.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();
+        internals.setRegister("A", (byte) (internals.getRegister("A") - 1));
+        internals.incAddress(1);
+        return output;
       }
     }.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();
+        internals.setRegister("A", (byte) (internals.getRegister("A") + internals.getRegister("B")));
+        internals.incAddress(1);
+        return output;
       }
     }.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();
+        internals.setRegister("A", (byte) (internals.getRegister("A") - internals.getRegister("B")));
+        internals.incAddress(1);
+        return output;
       }
     }.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();
+        internals.setRegister("A", (byte) (internals.getRegister("A") * internals.getRegister("B")));
+        internals.incAddress(1);
+        return output;
       }
     }.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();
+        internals.setRegister("A", (byte) (internals.getRegister("A") / internals.getRegister("B")));
+        internals.incAddress(1);
+        return output;
       }
     }.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();
+        internals.setRegister("A", (byte) (internals.getRegister("A") & internals.getRegister("B")));
+        internals.incAddress(1);
+        return output;
       }
     }.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();
+        internals.setRegister("A", (byte) (internals.getRegister("A") | internals.getRegister("B")));
+        internals.incAddress(1);
+        return output;
       }
     }.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();
+        internals.setRegister("A", (byte) (internals.getRegister("A") ^ internals.getRegister("B")));
+        internals.incAddress(1);
+        return output;
       }
     }.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();
+        internals.setRegister("A", (byte) (internals.getRegister("A") ^ 0xFF));
+        internals.incAddress(1);
+        return output;
       }
     }.setName("A=NOT A").setMnemonic("NOTA").setCommandByte((byte) (SPS_A_CALCULATE.getCommandByte() + 0x0A))
         .setCommand(SPS_A_CALCULATE));
@@ -402,8 +412,12 @@ public class HoltekEmulator extends AbstractEmulator implements SPSEmulator {
       SPS_PAGE.getCommandDatas().add(new SPSCommandDataImpl() {
         @Override
         public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
-          ((HoltekEmulatorInternals) internals).address++;
-          return HoltekEmulator.getInstance().getEmulatorOutput();
+          byte data = getData();
+          if (data <= 0x07) {
+            internals.setRegister(HoltekEmulatorInternals.REGISTER_PAGE, data);
+          }
+          internals.incAddress(1);
+          return output;
         }
       }.setName("Page " + Integer.toString(i)).setMnemonic("PG" + Integer.toString(i))
           .setCommandByte((byte) (SPS_PAGE.getCommandByte() + i)).setCommand(SPS_PAGE));
@@ -417,8 +431,9 @@ public class HoltekEmulator extends AbstractEmulator implements SPSEmulator {
       SPS_JUMP_UP.getCommandDatas().add(new SPSCommandDataImpl() {
         @Override
         public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
-          ((HoltekEmulatorInternals) internals).address++;
-          return HoltekEmulator.getInstance().getEmulatorOutput();
+          ((HoltekEmulatorInternals) internals).address = getData()
+              + (internals.getRegister(HoltekEmulatorInternals.REGISTER_PAGE) * 16);
+          return output;
         }
       }.setName("Jump " + Integer.toString(i)).setMnemonic("JMP" + Integer.toString(i))
           .setCommandByte((byte) (SPS_JUMP_UP.getCommandByte() + i)).setCommand(SPS_JUMP_UP));
@@ -433,7 +448,7 @@ public class HoltekEmulator extends AbstractEmulator implements SPSEmulator {
         @Override
         public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
           ((HoltekEmulatorInternals) internals).address++;
-          return HoltekEmulator.getInstance().getEmulatorOutput();
+          return output;
         }
       }.setName("C* Loop " + Integer.toString(i)).setMnemonic("CLOP" + Integer.toString(i))
           .setCommandByte((byte) (SPS_C_LOOP.getCommandByte() + i)).setCommand(SPS_C_LOOP));
@@ -448,7 +463,7 @@ public class HoltekEmulator extends AbstractEmulator implements SPSEmulator {
         @Override
         public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
           ((HoltekEmulatorInternals) internals).address++;
-          return HoltekEmulator.getInstance().getEmulatorOutput();
+          return output;
         }
       }.setName("D* Loop " + Integer.toString(i)).setMnemonic("DLOP" + Integer.toString(i))
           .setCommandByte((byte) (SPS_D_LOOP.getCommandByte() + i)).setCommand(SPS_D_LOOP));
@@ -462,7 +477,7 @@ public class HoltekEmulator extends AbstractEmulator implements SPSEmulator {
       @Override
       public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
         ((HoltekEmulatorInternals) internals).address++;
-        return HoltekEmulator.getInstance().getEmulatorOutput();
+        return output;
       }
     }.setName("A>B").setMnemonic("AGRB").setCommandByte((byte) (SPS_SKIP_IF.getCommandByte() + 0x01))
         .setCommand(SPS_SKIP_IF));
@@ -470,7 +485,7 @@ public class HoltekEmulator extends AbstractEmulator implements SPSEmulator {
       @Override
       public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
         ((HoltekEmulatorInternals) internals).address++;
-        return HoltekEmulator.getInstance().getEmulatorOutput();
+        return output;
       }
     }.setName("A<B").setMnemonic("ASMB").setCommandByte((byte) (SPS_SKIP_IF.getCommandByte() + 0x02))
         .setCommand(SPS_SKIP_IF));
@@ -478,7 +493,7 @@ public class HoltekEmulator extends AbstractEmulator implements SPSEmulator {
       @Override
       public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
         ((HoltekEmulatorInternals) internals).address++;
-        return HoltekEmulator.getInstance().getEmulatorOutput();
+        return output;
       }
     }.setName("A=B").setMnemonic("AEQB").setCommandByte((byte) (SPS_SKIP_IF.getCommandByte() + 0x03))
         .setCommand(SPS_SKIP_IF));
@@ -486,7 +501,7 @@ public class HoltekEmulator extends AbstractEmulator implements SPSEmulator {
       @Override
       public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
         ((HoltekEmulatorInternals) internals).address++;
-        return HoltekEmulator.getInstance().getEmulatorOutput();
+        return output;
       }
     }.setName("In.1=1").setMnemonic("IN11").setCommandByte((byte) (SPS_SKIP_IF.getCommandByte() + 0x04))
         .setCommand(SPS_SKIP_IF));
@@ -494,7 +509,7 @@ public class HoltekEmulator extends AbstractEmulator implements SPSEmulator {
       @Override
       public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
         ((HoltekEmulatorInternals) internals).address++;
-        return HoltekEmulator.getInstance().getEmulatorOutput();
+        return output;
       }
     }.setName("In.2=1").setMnemonic("IN21").setCommandByte((byte) (SPS_SKIP_IF.getCommandByte() + 0x05))
         .setCommand(SPS_SKIP_IF));
@@ -502,7 +517,7 @@ public class HoltekEmulator extends AbstractEmulator implements SPSEmulator {
       @Override
       public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
         ((HoltekEmulatorInternals) internals).address++;
-        return HoltekEmulator.getInstance().getEmulatorOutput();
+        return output;
       }
     }.setName("In.3=1").setMnemonic("IN31").setCommandByte((byte) (SPS_SKIP_IF.getCommandByte() + 0x06))
         .setCommand(SPS_SKIP_IF));
@@ -510,7 +525,7 @@ public class HoltekEmulator extends AbstractEmulator implements SPSEmulator {
       @Override
       public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
         ((HoltekEmulatorInternals) internals).address++;
-        return HoltekEmulator.getInstance().getEmulatorOutput();
+        return output;
       }
     }.setName("In.4=1").setMnemonic("IN41").setCommandByte((byte) (SPS_SKIP_IF.getCommandByte() + 0x07))
         .setCommand(SPS_SKIP_IF));
@@ -518,7 +533,7 @@ public class HoltekEmulator extends AbstractEmulator implements SPSEmulator {
       @Override
       public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
         ((HoltekEmulatorInternals) internals).address++;
-        return HoltekEmulator.getInstance().getEmulatorOutput();
+        return output;
       }
     }.setName("In.1=0").setMnemonic("IN10").setCommandByte((byte) (SPS_SKIP_IF.getCommandByte() + 0x08))
         .setCommand(SPS_SKIP_IF));
@@ -526,7 +541,7 @@ public class HoltekEmulator extends AbstractEmulator implements SPSEmulator {
       @Override
       public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
         ((HoltekEmulatorInternals) internals).address++;
-        return HoltekEmulator.getInstance().getEmulatorOutput();
+        return output;
       }
     }.setName("In.2=0").setMnemonic("IN20").setCommandByte((byte) (SPS_SKIP_IF.getCommandByte() + 0x09))
         .setCommand(SPS_SKIP_IF));
@@ -534,7 +549,7 @@ public class HoltekEmulator extends AbstractEmulator implements SPSEmulator {
       @Override
       public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
         ((HoltekEmulatorInternals) internals).address++;
-        return HoltekEmulator.getInstance().getEmulatorOutput();
+        return output;
       }
     }.setName("In.3=0").setMnemonic("IN30").setCommandByte((byte) (SPS_SKIP_IF.getCommandByte() + 0x0A))
         .setCommand(SPS_SKIP_IF));
@@ -542,7 +557,7 @@ public class HoltekEmulator extends AbstractEmulator implements SPSEmulator {
       @Override
       public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
         ((HoltekEmulatorInternals) internals).address++;
-        return HoltekEmulator.getInstance().getEmulatorOutput();
+        return output;
       }
     }.setName("In.4=0").setMnemonic("IN40").setCommandByte((byte) (SPS_SKIP_IF.getCommandByte() + 0x0B))
         .setCommand(SPS_SKIP_IF));
@@ -550,7 +565,7 @@ public class HoltekEmulator extends AbstractEmulator implements SPSEmulator {
       @Override
       public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
         ((HoltekEmulatorInternals) internals).address++;
-        return HoltekEmulator.getInstance().getEmulatorOutput();
+        return output;
       }
     }.setName("S1=0").setMnemonic("S10").setCommandByte((byte) (SPS_SKIP_IF.getCommandByte() + 0x0C))
         .setCommand(SPS_SKIP_IF));
@@ -558,7 +573,7 @@ public class HoltekEmulator extends AbstractEmulator implements SPSEmulator {
       @Override
       public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
         ((HoltekEmulatorInternals) internals).address++;
-        return HoltekEmulator.getInstance().getEmulatorOutput();
+        return output;
       }
     }.setName("S2=0").setMnemonic("S20").setCommandByte((byte) (SPS_SKIP_IF.getCommandByte() + 0x0D))
         .setCommand(SPS_SKIP_IF));
@@ -566,7 +581,7 @@ public class HoltekEmulator extends AbstractEmulator implements SPSEmulator {
       @Override
       public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
         ((HoltekEmulatorInternals) internals).address++;
-        return HoltekEmulator.getInstance().getEmulatorOutput();
+        return output;
       }
     }.setName("S1=1").setMnemonic("S11").setCommandByte((byte) (SPS_SKIP_IF.getCommandByte() + 0x0E))
         .setCommand(SPS_SKIP_IF));
@@ -574,7 +589,7 @@ public class HoltekEmulator extends AbstractEmulator implements SPSEmulator {
       @Override
       public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
         ((HoltekEmulatorInternals) internals).address++;
-        return HoltekEmulator.getInstance().getEmulatorOutput();
+        return output;
       }
     }.setName("S2=1").setMnemonic("S21").setCommandByte((byte) (SPS_SKIP_IF.getCommandByte() + 0x0F))
         .setCommand(SPS_SKIP_IF));
@@ -588,7 +603,7 @@ public class HoltekEmulator extends AbstractEmulator implements SPSEmulator {
         @Override
         public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
           ((HoltekEmulatorInternals) internals).address++;
-          return HoltekEmulator.getInstance().getEmulatorOutput();
+          return output;
         }
       }.setName("Call " + Integer.toString(i)).setMnemonic("CALL" + Integer.toString(i))
           .setCommandByte((byte) (SPS_CALL.getCommandByte() + i)).setCommand(SPS_CALL));
@@ -603,19 +618,11 @@ public class HoltekEmulator extends AbstractEmulator implements SPSEmulator {
       @Override
       public EmulatorOutput doWork(EmulatorInput input, EmulatorInternals internals, EmulatorOutput output) {
         ((HoltekEmulatorInternals) internals).address++;
-        return HoltekEmulator.getInstance().getEmulatorOutput();
+        return output;
       }
     }.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;

+ 23 - 12
src/main/java/de/mcs/tools/sps/holtek/HoltekEmulatorInternals.java

@@ -10,6 +10,11 @@ import de.mcs.tools.sps.EmulatorInternals;
  *
  */
 public class HoltekEmulatorInternals implements EmulatorInternals {
+  public static final String REGISTER_A = "A";
+  public static final String REGISTER_B = "B";
+  public static final String REGISTER_C = "C";
+  public static final String REGISTER_D = "D";
+  public static final String REGISTER_PAGE = "PAGE";
   int address;
   int a, b, c, d;
   int page;
@@ -47,33 +52,39 @@ public class HoltekEmulatorInternals implements EmulatorInternals {
 
   @Override
   public void setRegister(String registerName, byte data) {
-    if ("A".equals(registerName.toUpperCase())) {
+    if (REGISTER_A.equals(registerName.toUpperCase())) {
       a = data;
     }
-    if ("B".equals(registerName.toUpperCase())) {
+    if (REGISTER_B.equals(registerName.toUpperCase())) {
       b = data;
     }
-    if ("C".equals(registerName.toUpperCase())) {
+    if (REGISTER_C.equals(registerName.toUpperCase())) {
       c = data;
     }
-    if ("D".equals(registerName.toUpperCase())) {
+    if (REGISTER_D.equals(registerName.toUpperCase())) {
       d = data;
     }
+    if (REGISTER_PAGE.equals(registerName.toUpperCase())) {
+      page = data;
+    }
   }
 
   @Override
   public byte getRegister(String register) {
-    if ("A".equals(register.toUpperCase())) {
-      return (byte) a;
+    if (REGISTER_A.equals(register.toUpperCase())) {
+      return (byte) (a & 0x0F);
+    }
+    if (REGISTER_B.equals(register.toUpperCase())) {
+      return (byte) (b & 0x0F);
     }
-    if ("B".equals(register.toUpperCase())) {
-      return (byte) b;
+    if (REGISTER_C.equals(register.toUpperCase())) {
+      return (byte) (c & 0x0F);
     }
-    if ("C".equals(register.toUpperCase())) {
-      return (byte) c;
+    if (REGISTER_D.equals(register.toUpperCase())) {
+      return (byte) (d & 0x0F);
     }
-    if ("D".equals(register.toUpperCase())) {
-      return (byte) d;
+    if (REGISTER_PAGE.equals(register.toUpperCase())) {
+      return (byte) (page & 0x0F);
     }
     return 0;
   }

+ 311 - 0
src/test/java/de/mcs/tools/sps/holtek/TestHoltekCommands.java

@@ -0,0 +1,311 @@
+/**
+ * 
+ */
+package de.mcs.tools.sps.holtek;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import de.mcs.tools.sps.EmulatorInput;
+import de.mcs.tools.sps.EmulatorInternals;
+import de.mcs.tools.sps.EmulatorOutput;
+import de.mcs.tools.sps.SPSCommandData;
+import de.mcs.tools.sps.SPSEmulator;
+
+/**
+ * @author w.klaas
+ *
+ */
+public class TestHoltekCommands {
+
+  private static SPSEmulator holtekEmulator;
+  private static EmulatorInput input;
+  private static EmulatorOutput output;
+  private static EmulatorInternals internals;
+
+  @BeforeAll
+  static void setUp() throws Exception {
+    holtekEmulator = new HoltekEmulator();
+    input = new HoltekEmulatorInput();
+    output = new HoltekEmulatorOutput();
+    internals = new HoltekEmulatorInternals();
+  }
+
+  SPSCommandData getCommandData(byte command) {
+    return holtekEmulator.getCommandData(command);
+  }
+
+  @Test
+  public void test0x70Empty() {
+    SPSCommandData data = getCommandData((byte) 0x70);
+    assertNull(data);
+  }
+
+  // A = A + 1
+  @Test
+  public void testIncA() {
+    SPSCommandData data = getCommandData((byte) 0x71);
+    assertNotNull(data);
+    internals.reset();
+    internals.setRegister("A", (byte) 0x03);
+    data.doWork(input, internals, output);
+    assertEquals(0x04, internals.getRegister("A"));
+
+    internals.setRegister("A", (byte) 0x0F);
+    data.doWork(input, internals, output);
+    assertEquals(0x00, internals.getRegister("A"));
+  }
+
+  // A = A - 1
+  @Test
+  public void testDecA() {
+    SPSCommandData data = getCommandData((byte) 0x72);
+    assertNotNull(data);
+    internals.reset();
+    internals.setRegister("A", (byte) 0x03);
+    data.doWork(input, internals, output);
+    assertEquals(0x02, internals.getRegister("A"));
+
+    internals.setRegister("A", (byte) 0x00);
+    data.doWork(input, internals, output);
+    assertEquals(0x0F, internals.getRegister("A"));
+  }
+
+  // A = A + B
+  @Test
+  public void testADDB() {
+    SPSCommandData data = getCommandData((byte) 0x73);
+    assertNotNull(data);
+    internals.reset();
+    internals.setRegister("A", (byte) 0x03);
+    internals.setRegister("B", (byte) 0x04);
+    data.doWork(input, internals, output);
+    assertEquals(0x07, internals.getRegister("A"));
+
+    internals.setRegister("A", (byte) 0x07);
+    internals.setRegister("B", (byte) 0x07);
+    data.doWork(input, internals, output);
+    assertEquals(0x0e, internals.getRegister("A"));
+
+    internals.setRegister("A", (byte) 0x08);
+    internals.setRegister("B", (byte) 0x08);
+    data.doWork(input, internals, output);
+    assertEquals(0x00, internals.getRegister("A"));
+  }
+
+  // A = A - B
+  @Test
+  public void testSUBB() {
+    SPSCommandData data = getCommandData((byte) 0x74);
+    assertNotNull(data);
+    internals.reset();
+    internals.setRegister("A", (byte) 0x04);
+    internals.setRegister("B", (byte) 0x03);
+    data.doWork(input, internals, output);
+    assertEquals(0x01, internals.getRegister("A"));
+
+    internals.setRegister("A", (byte) 0x07);
+    internals.setRegister("B", (byte) 0x07);
+    data.doWork(input, internals, output);
+    assertEquals(0x00, internals.getRegister("A"));
+
+    internals.setRegister("A", (byte) 0x06);
+    internals.setRegister("B", (byte) 0x08);
+    data.doWork(input, internals, output);
+    assertEquals(0x0E, internals.getRegister("A"));
+  }
+
+  // A = A * B
+  @Test
+  public void testMULB() {
+    SPSCommandData data = getCommandData((byte) 0x75);
+    assertNotNull(data);
+    internals.reset();
+    internals.setRegister("A", (byte) 0x02);
+    internals.setRegister("B", (byte) 0x02);
+    data.doWork(input, internals, output);
+    assertEquals(0x04, internals.getRegister("A"));
+
+    internals.setRegister("A", (byte) 0x03);
+    internals.setRegister("B", (byte) 0x03);
+    data.doWork(input, internals, output);
+    assertEquals(0x09, internals.getRegister("A"));
+
+    internals.setRegister("A", (byte) 0x06);
+    internals.setRegister("B", (byte) 0x08);
+    data.doWork(input, internals, output);
+    assertEquals(0x00, internals.getRegister("A"));
+  }
+
+  // A = A / B
+  @Test
+  public void testDIVB() {
+    SPSCommandData data = getCommandData((byte) 0x76);
+    assertNotNull(data);
+    internals.reset();
+    internals.setRegister("A", (byte) 0x02);
+    internals.setRegister("B", (byte) 0x02);
+    data.doWork(input, internals, output);
+    assertEquals(0x01, internals.getRegister("A"));
+
+    internals.setRegister("A", (byte) 0x06);
+    internals.setRegister("B", (byte) 0x03);
+    data.doWork(input, internals, output);
+    assertEquals(0x02, internals.getRegister("A"));
+
+    internals.setRegister("A", (byte) 0x06);
+    internals.setRegister("B", (byte) 0x04);
+    data.doWork(input, internals, output);
+    assertEquals(0x01, internals.getRegister("A"));
+
+    internals.setRegister("A", (byte) 0x06);
+    internals.setRegister("B", (byte) 0x07);
+    data.doWork(input, internals, output);
+    assertEquals(0x00, internals.getRegister("A"));
+  }
+
+  // A = A AND B
+  @Test
+  public void testANDB() {
+    SPSCommandData data = getCommandData((byte) 0x77);
+    assertNotNull(data);
+    internals.reset();
+    internals.setRegister("A", (byte) 0x02);
+    internals.setRegister("B", (byte) 0x02);
+    data.doWork(input, internals, output);
+    assertEquals(0x02, internals.getRegister("A"));
+
+    internals.setRegister("A", (byte) 0x06);
+    internals.setRegister("B", (byte) 0x03);
+    data.doWork(input, internals, output);
+    assertEquals(0x02, internals.getRegister("A"));
+
+    internals.setRegister("A", (byte) 0x0F);
+    internals.setRegister("B", (byte) 0x00);
+    data.doWork(input, internals, output);
+    assertEquals(0x00, internals.getRegister("A"));
+
+    internals.setRegister("A", (byte) 0x0F);
+    internals.setRegister("B", (byte) 0x0F);
+    data.doWork(input, internals, output);
+    assertEquals(0x0F, internals.getRegister("A"));
+  }
+
+  // A = A OR B
+  @Test
+  public void testORB() {
+    SPSCommandData data = getCommandData((byte) 0x78);
+    assertNotNull(data);
+    internals.reset();
+    internals.setRegister("A", (byte) 0x02);
+    internals.setRegister("B", (byte) 0x02);
+    data.doWork(input, internals, output);
+    assertEquals(0x02, internals.getRegister("A"));
+
+    internals.setRegister("A", (byte) 0x06);
+    internals.setRegister("B", (byte) 0x03);
+    data.doWork(input, internals, output);
+    assertEquals(0x07, internals.getRegister("A"));
+
+    internals.setRegister("A", (byte) 0x0F);
+    internals.setRegister("B", (byte) 0x00);
+    data.doWork(input, internals, output);
+    assertEquals(0x0F, internals.getRegister("A"));
+
+    internals.setRegister("A", (byte) 0x0F);
+    internals.setRegister("B", (byte) 0x0F);
+    data.doWork(input, internals, output);
+    assertEquals(0x0F, internals.getRegister("A"));
+  }
+
+  // A = A XOR B
+  @Test
+  public void testXORB() {
+    SPSCommandData data = getCommandData((byte) 0x79);
+    assertNotNull(data);
+    internals.reset();
+    internals.setRegister("A", (byte) 0x02);
+    internals.setRegister("B", (byte) 0x02);
+    data.doWork(input, internals, output);
+    assertEquals(0x00, internals.getRegister("A"));
+
+    internals.setRegister("A", (byte) 0x06);
+    internals.setRegister("B", (byte) 0x03);
+    data.doWork(input, internals, output);
+    assertEquals(0x05, internals.getRegister("A"));
+
+    internals.setRegister("A", (byte) 0x0F);
+    internals.setRegister("B", (byte) 0x00);
+    data.doWork(input, internals, output);
+    assertEquals(0x0F, internals.getRegister("A"));
+
+    internals.setRegister("A", (byte) 0x0F);
+    internals.setRegister("B", (byte) 0x0F);
+    data.doWork(input, internals, output);
+    assertEquals(0x00, internals.getRegister("A"));
+  }
+
+  // A = NOT A
+  @Test
+  public void testNOTA() {
+    SPSCommandData data = getCommandData((byte) 0x7A);
+    assertNotNull(data);
+    internals.reset();
+    internals.setRegister("A", (byte) 0x02);
+    data.doWork(input, internals, output);
+    assertEquals(0x0D, internals.getRegister("A"));
+
+    internals.setRegister("A", (byte) 0x06);
+    data.doWork(input, internals, output);
+    assertEquals(0x09, internals.getRegister("A"));
+
+    internals.setRegister("A", (byte) 0x0F);
+    data.doWork(input, internals, output);
+    assertEquals(0x00, internals.getRegister("A"));
+
+    internals.setRegister("A", (byte) 0x00);
+    data.doWork(input, internals, output);
+    assertEquals(0x0F, internals.getRegister("A"));
+  }
+
+  // PAGE = #
+  @Test
+  public void testPage() {
+    for (int i = 0; i < 16; i++) {
+      SPSCommandData data = getCommandData((byte) (0x80 + i));
+      if (i < 0x08) {
+        assertNotNull(data);
+        internals.reset();
+        data.doWork(input, internals, output);
+        assertEquals(i, internals.getRegister(HoltekEmulatorInternals.REGISTER_PAGE));
+      } else {
+        assertNull(data);
+      }
+    }
+  }
+
+  // JUMP #
+  @Test
+  public void testJump() {
+    for (int page = 0; page < 16; page++) {
+      SPSCommandData data = getCommandData((byte) (0x80 + page));
+      if (page < 0x08) {
+        assertNotNull(data);
+        internals.reset();
+        data.doWork(input, internals, output);
+        assertEquals(page, internals.getRegister(HoltekEmulatorInternals.REGISTER_PAGE));
+        for (int x = 0; x < 16; x++) {
+          data = getCommandData((byte) (0x90 + x));
+          data.doWork(input, internals, output);
+          assertEquals((x + 16 * page), internals.getAddress());
+        }
+      } else {
+        assertNull(data);
+      }
+    }
+  }
+}