Subversion Repositories ht46f47_simulator

Rev

Rev 2 | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. unit HT46F47;
  2.  
  3. interface
  4.  
  5. type
  6.   Nibble = 0..15;
  7.  
  8.   TRom = array[0..$FF] of byte;
  9.  
  10.   TWaitEvent = procedure(milliseconds: integer) of object;
  11.  
  12.   THT46F47 = class(TObject)
  13.   strict private
  14.     procedure WaitMs(milliseconds: integer);
  15.   strict protected
  16.     FOnWait: TWaitEvent;
  17.     // ROM
  18.     // Registers
  19.     FPC: byte;
  20.     FReturnAddress: byte;
  21.     FPage: Nibble;
  22.     FRegA: Nibble;
  23.     FRegB: Nibble;
  24.     FRegC: Nibble;
  25.     FRegD: Nibble;
  26.     FCalledOnce: boolean;
  27.     // In
  28.     FS1: boolean;
  29.     FS2: boolean;
  30.     FDIn: Nibble;
  31.     FAD1: Nibble;
  32.     FAD2: Nibble;
  33.     // Out
  34.     FPWM: Nibble;
  35.     FPortOut: Nibble;
  36.   public
  37.     // ROM
  38.     ROM: TRom;
  39.     property FROM: TRom read ROM;
  40.     // Registers
  41.     property PC: byte read FPC;
  42.     property ReturnAddress: byte read FReturnAddress;
  43.     property Page: Nibble read FPage;
  44.     property RegA: Nibble read FRegA;
  45.     property RegB: Nibble read FRegB;
  46.     property RegC: Nibble read FRegC;
  47.     property RegD: Nibble read FRegD;
  48.     // In
  49.     property S1: boolean read FS1 write FS1;
  50.     property S2: boolean read FS2 write FS2;
  51.     property DIn: Nibble read FDIn write FDIn;
  52.     property AD1: Nibble read FAD1 write FAD1;
  53.     property AD2: Nibble read FAD2 write FAD2;
  54.     // Out
  55.     property PWM: Nibble read FPWM;
  56.     property PortOut: Nibble read FPortOut;
  57.     // Functions
  58.     property OnWait: TWaitEvent read FOnWait write FOnWait;
  59.     constructor Create;
  60.     procedure Step;
  61.     procedure Reset;
  62.   end;
  63.  
  64. implementation
  65.  
  66. uses
  67.   SysUtils, Forms;
  68.  
  69. { THT46F47 }
  70.  
  71. constructor THT46F47.Create;
  72. var
  73.   i: integer;
  74. begin
  75.   for i := Low(FROM) to High(FROM) do
  76.   begin
  77.     ROM[i] := $00;
  78.   end;
  79.   Reset;
  80. end;
  81.  
  82. procedure THT46F47.Reset;
  83. begin
  84.   // Internal
  85.   FPC := 0;
  86.   FReturnAddress := 0;
  87.   FPage := 0;
  88.   FRegA := 0; // Note: The registers don't seem to be reset in the actual chip, if a "soft reset" is done
  89.   FRegB := 0;
  90.   FRegC := 0;
  91.   FRegD := 0;
  92.   FCalledOnce := false;
  93.   // In
  94.   FS1 := false;
  95.   FS2 := false;
  96.   FDIn := 0;
  97.   FAD1 := 0;
  98.   FAD2 := 0;
  99.   // Out
  100.   FPWM := 0;
  101.   FPortOut := 0;
  102. end;
  103.  
  104. procedure THT46F47.Step;
  105. var
  106.   Instruction: byte;
  107.   ProgramCounterNext: Byte;
  108.   ProgramCounterCurrent: Byte;
  109. begin
  110.   Instruction := FROM[FPC];
  111.  
  112.   ProgramCounterCurrent := FPC;
  113.   ProgramCounterNext := FPC+1;
  114.  
  115.   try
  116.     (*
  117.     ----------------------------------------------------
  118.     Code        Assembly        Alternative     Comment
  119.     ----------------------------------------------------
  120.     10  LED 0000        PORT 0
  121.     11  LED 0001        PORT 1
  122.     12  LED 0010        PORT 2
  123.     13  LED 0011        PORT 3
  124.     14  LED 0100        PORT 4
  125.     15  LED 0101        PORT 5
  126.     16  LED 0110        PORT 6
  127.     17  LED 0111        PORT 7
  128.     18  LED 1000        PORT 8
  129.     19  LED 1001        PORT 9
  130.     1A  LED 1010        PORT 10
  131.     1B  LED 1011        PORT 11
  132.     1C  LED 1100        PORT 12
  133.     1D  LED 1101        PORT 13
  134.     1E  LED 1110        PORT 14
  135.     1F  LED 1111        PORT 15
  136.     *)
  137.     if (Instruction >= $10) and (Instruction <= $1F) then
  138.     begin
  139.       FPortOut := Instruction and $F;
  140.     end;
  141.  
  142.     (*
  143.     ----------------------------------------------------
  144.     Code        Assembly        Alternative     Comment
  145.     ----------------------------------------------------
  146.     20  WAIT 1ms
  147.     21  WAIT 2ms
  148.     22  WAIT 5ms
  149.     23  WAIT 10ms
  150.     24  WAIT 20ms
  151.     25  WAIT 50ms
  152.     26  WAIT 100ms
  153.     27  WAIT 200ms
  154.     28  WAIT 500ms
  155.     29  WAIT 1s
  156.     2A  WAIT 2s
  157.     2B  WAIT 5s
  158.     2C  WAIT 10s
  159.     2D  WAIT 20s
  160.     2E  WAIT 30s
  161.     2F  WAIT 60s
  162.     *)
  163.     case Instruction of
  164.       $20: WaitMs(1);      // WAIT 1ms
  165.       $21: WaitMs(2);      // WAIT 2ms
  166.       $22: WaitMs(5);      // WAIT 5ms
  167.       $23: WaitMs(10);     // WAIT 10ms
  168.       $24: WaitMs(20);     // WAIT 20ms
  169.       $25: WaitMs(50);     // WAIT 50ms
  170.       $26: WaitMs(100);    // WAIT 100ms
  171.       $27: WaitMs(200);    // WAIT 200ms
  172.       $28: WaitMs(500);    // WAIT 500ms
  173.       $29: WaitMs(1000);   // WAIT 1s
  174.       $2A: WaitMs(2000);   // WAIT 2s
  175.       $2B: WaitMs(5000);   // WAIT 5s
  176.       $2C: WaitMs(10000);  // WAIT 10s
  177.       $2D: WaitMs(20000);  // WAIT 20s
  178.       $2E: WaitMs(30000);  // WAIT 30s
  179.       $2F: WaitMs(60000);  // WAIT 60s
  180.     end;
  181.  
  182.     (*
  183.     ----------------------------------------------------
  184.     Code        Assembly        Alternative     Comment
  185.     ----------------------------------------------------
  186.     30  JUMP -0         HALT
  187.     31  JUMP -1
  188.     32  JUMP -2
  189.     33  JUMP -3
  190.     34  JUMP -4
  191.     35  JUMP -5
  192.     36  JUMP -6
  193.     37  JUMP -7
  194.     38  JUMP -8
  195.     39  JUMP -9
  196.     3A  JUMP -10
  197.     3B  JUMP -11
  198.     3C  JUMP -12
  199.     3D  JUMP -13
  200.     3E  JUMP -14
  201.     3F  JUMP -15
  202.     *)
  203.     if (Instruction >= $30) and (Instruction <= $3F) then
  204.     begin
  205.       ProgramCounterNext := ProgramCounterCurrent - (Instruction and $F);
  206.     end;
  207.  
  208.     (*
  209.     ----------------------------------------------------
  210.     Code        Assembly        Alternative     Comment
  211.     ----------------------------------------------------
  212.     40  SET A=0
  213.     41  SET A=1
  214.     42  SET A=2
  215.     43  SET A=3
  216.     44  SET A=4
  217.     45  SET A=5
  218.     46  SET A=6
  219.     47  SET A=7
  220.     48  SET A=8
  221.     49  SET A=9
  222.     4A  SET A=10
  223.     4B  SET A=11
  224.     4C  SET A=12
  225.     4D  SET A=13
  226.     4E  SET A=14
  227.     4F  SET A=15
  228.     *)
  229.     if (Instruction >= $40) and (Instruction <= $4F) then
  230.     begin
  231.       FRegA := Instruction and $F;
  232.     end;
  233.  
  234.     (*
  235.     ----------------------------------------------------
  236.     Code        Assembly        Alternative     Comment
  237.     ----------------------------------------------------
  238.     50
  239.     51  SET B=A
  240.     52  SET C=A
  241.     53  SET D=A
  242.     54  SET Dout=A
  243.     55  SET Dout.0=A.0
  244.     56  SET Dout.1=A.0
  245.     57  SET Dout.2=A.0
  246.     58  SET Dout.3=A.0
  247.     59  SET PWM=A
  248.     5A
  249.     5B
  250.     5C
  251.     5D
  252.     5E
  253.     5F
  254.     *)
  255.     case Instruction of
  256.       $51: FRegB := FRegA;     // SET B=A
  257.       $52: FRegC := FRegA;     // SET C=A
  258.       $53: FRegD := FRegA;     // SET D=A
  259.       $54: FPortOut := FRegA;  // SET Dout=A
  260.       $55: FPortOut := ((FRegA and 1) shl 0) + (PortOut and 14); // SET Dout.0=A.0
  261.       $56: FPortOut := ((FRegA and 1) shl 1) + (PortOut and 13); // SET Dout.1=A.0
  262.       $57: FPortOut := ((FRegA and 1) shl 2) + (PortOut and 11); // SET Dout.2=A.0
  263.       $58: FPortOut := ((FRegA and 1) shl 3) + (PortOut and  7); // SET Dout.3=A.0
  264.       $59: FPWM := FRegA;      // SET PWM=A
  265.     end;
  266.  
  267.     (*
  268.     ----------------------------------------------------
  269.     Code        Assembly        Alternative     Comment
  270.     ----------------------------------------------------
  271.     60
  272.     61  SET A=B
  273.     62  SET A=C
  274.     63  SET A=D
  275.     64  SET A=Din
  276.     65  SET A=Din.0
  277.     66  SET A=Din.1
  278.     67  SET A=Din.2
  279.     68  SET A=Din.3
  280.     69  SET A=AD1
  281.     6A  SET A=AD2
  282.     6B
  283.     6C
  284.     6D
  285.     6E
  286.     6F
  287.     *)
  288.     case Instruction of
  289.       $61: FRegA := FRegB; // SET A=B
  290.       $62: FRegA := FRegC; // SET A=C
  291.       $63: FRegA := FRegD; // SET A=D
  292.       $64: FRegA := DIn;  // SET A=Din
  293.       $65: FRegA := (DIn and 1) shr 0;  // SET A=Din.0
  294.       $66: FRegA := (DIn and 2) shr 1;  // SET A=Din.1
  295.       $67: FRegA := (DIn and 4) shr 1;  // SET A=Din.2
  296.       $68: FRegA := (DIn and 8) shr 1;  // SET A=Din.3
  297.       $69: FRegA := AD1;
  298.       $6A: FRegA := AD2;
  299.     end;
  300.  
  301.     (*
  302.     ----------------------------------------------------
  303.     Code        Assembly        Alternative     Comment
  304.     ----------------------------------------------------
  305.     70
  306.     71  SET A=A+1
  307.     72  SET A=A-1
  308.     73  SET A=A+B
  309.     74  SET A=A-B
  310.     75  SET A=A*B
  311.     76  SET A=A/B
  312.     77  SET A=A&B                       AND
  313.     78  SET A=A|B                       OR
  314.     79  SET A=A^B                       XOR
  315.     7A  SET A=~A                        NOT
  316.     7B
  317.     7C
  318.     7D
  319.     7E
  320.     7F
  321.     *)
  322.     case Instruction of
  323.       $71: FRegA := FRegA + 1;      // SET A=A+1
  324.       $72: FRegA := FRegA - 1;      // SET A=A-1
  325.       $73: FRegA := FRegA + FRegB;   // SET A=A+B
  326.       $74: FRegA := FRegA - FRegB;   // SET A=A-B
  327.       $75: FRegA := FRegA * FRegB;   // SET A=A*B
  328.       $76: begin
  329.              if FRegB = 0 then
  330.                FRegA := $F // this is the actual behavior of the microchip (program 40 51 45 76 54 30)
  331.              else
  332.                FRegA := FRegA div FRegB; // SET A=A/B
  333.            end;
  334.       $77: FRegA := FRegA and FRegB; // SET A=A&B                       AND
  335.       $78: FRegA := FRegA  or FRegB; // SET A=A|B                       OR
  336.       $79: FRegA := FRegA xor FRegB; // SET A=A^B                       XOR
  337.       $7A: FRegA := not FRegA;      // SET A=~A                 NOT
  338.     end;
  339.  
  340.     (*
  341.     ----------------------------------------------------
  342.     Code        Assembly        Alternative     Comment
  343.     ----------------------------------------------------
  344.     80  PAGE 0                          Page is used by JUMP, CALL, CTIMES and DTIMES
  345.     81  PAGE 1
  346.     82  PAGE 2
  347.     83  PAGE 3
  348.     84  PAGE 4
  349.     85  PAGE 5
  350.     86  PAGE 6
  351.     87  PAGE 7
  352.     88  PAGE 8
  353.     89  PAGE 9
  354.     8A  PAGE A
  355.     8B  PAGE B
  356.     8C  PAGE C
  357.     8D  PAGE D
  358.     8E  PAGE E
  359.     8F  PAGE F
  360.     *)
  361.     if (Instruction >= $80) and (Instruction <= $8F) then
  362.     begin
  363.       FPage := Instruction and $F;
  364.     end;
  365.  
  366.     (*
  367.     ----------------------------------------------------
  368.     Code        Assembly        Alternative     Comment
  369.     ----------------------------------------------------
  370.     90  JUMP <PAGE>0
  371.     91  JUMP <PAGE>1
  372.     92  JUMP <PAGE>2
  373.     93  JUMP <PAGE>3
  374.     94  JUMP <PAGE>4
  375.     95  JUMP <PAGE>5
  376.     96  JUMP <PAGE>6
  377.     97  JUMP <PAGE>7
  378.     98  JUMP <PAGE>8
  379.     99  JUMP <PAGE>9
  380.     9A  JUMP <PAGE>A
  381.     9B  JUMP <PAGE>B
  382.     9C  JUMP <PAGE>C
  383.     9D  JUMP <PAGE>D
  384.     9E  JUMP <PAGE>E
  385.     9F  JUMP <PAGE>F
  386.     *)
  387.     if (Instruction >= $90) and (Instruction <= $9F) then
  388.     begin
  389.       ProgramCounterNext := (FPage shl 4) + (Instruction and $F);
  390.     end;
  391.  
  392.     (*
  393.     ----------------------------------------------------
  394.     Code        Assembly        Alternative     Comment
  395.     ----------------------------------------------------
  396.     A0  CTIMES <PAGE>0                  IF C>0 THEN ( C=C-1 ; JUMP <PAGE>X ) ELSE CONTINUE
  397.     A1  CTIMES <PAGE>1
  398.     A2  CTIMES <PAGE>2
  399.     A3  CTIMES <PAGE>3
  400.     A4  CTIMES <PAGE>4
  401.     A5  CTIMES <PAGE>5
  402.     A6  CTIMES <PAGE>6
  403.     A7  CTIMES <PAGE>7
  404.     A8  CTIMES <PAGE>8
  405.     A9  CTIMES <PAGE>9
  406.     AA  CTIMES <PAGE>A
  407.     AB  CTIMES <PAGE>B
  408.     AC  CTIMES <PAGE>C
  409.     AD  CTIMES <PAGE>D
  410.     AE  CTIMES <PAGE>E
  411.     AF  CTIMES <PAGE>F
  412.     *)
  413.     if (Instruction >= $A0) and (Instruction <= $AF) then
  414.     begin
  415.       if FRegC > 0 then
  416.       begin
  417.         Dec(FRegC);
  418.         FReturnAddress     := ProgramCounterCurrent;
  419.         ProgramCounterNext := (FPage shl 4) + (Instruction and $F);
  420.       end;
  421.     end;
  422.  
  423.     (*
  424.     ----------------------------------------------------
  425.     Code        Assembly        Alternative     Comment
  426.     ----------------------------------------------------
  427.     B0  DTIMES <PAGE>0                  IF D>0 THEN ( D=D-1 ; JUMP <PAGE>X ) ELSE CONTINUE
  428.     B1  DTIMES <PAGE>1
  429.     B2  DTIMES <PAGE>2
  430.     B3  DTIMES <PAGE>3
  431.     B4  DTIMES <PAGE>4
  432.     B5  DTIMES <PAGE>5
  433.     B6  DTIMES <PAGE>6
  434.     B7  DTIMES <PAGE>7
  435.     B8  DTIMES <PAGE>8
  436.     B9  DTIMES <PAGE>9
  437.     BA  DTIMES <PAGE>A
  438.     BB  DTIMES <PAGE>B
  439.     BC  DTIMES <PAGE>C
  440.     BD  DTIMES <PAGE>D
  441.     BE  DTIMES <PAGE>E
  442.     BF  DTIMES <PAGE>F
  443.     *)
  444.     if (Instruction >= $B0) and (Instruction <= $BF) then
  445.     begin
  446.       if FRegD > 0 then
  447.       begin
  448.         Dec(FRegD);
  449.         FReturnAddress     := ProgramCounterCurrent;
  450.         ProgramCounterNext := (FPage shl 4) + (Instruction and $F);
  451.       end;
  452.     end;
  453.  
  454.     (*
  455.     ----------------------------------------------------
  456.     Code        Assembly        Alternative     Comment
  457.     ----------------------------------------------------
  458.     C0
  459.     C1  SKIP_IF A>B
  460.     C2  SKIP_IF A<B
  461.     C3  SKIP_IF A=B
  462.     C4  SKIP_IF Din.0=1
  463.     C5  SKIP_IF Din.1=1
  464.     C6  SKIP_IF Din.2=1
  465.     C7  SKIP_IF Din.3=1
  466.     C8  SKIP_IF Din.0=0
  467.     C9  SKIP_IF Din.1=0
  468.     CA  SKIP_IF Din.2=0
  469.     CB  SKIP_IF Din.3=0
  470.     CC  SKIP_IF S1=0
  471.     CD  SKIP_IF S2=0
  472.     CE  SKIP_IF S1=1
  473.     CF  SKIP_IF S2=1
  474.     *)
  475.     case Instruction of
  476.       $C1: if FRegA > FRegB then Inc(ProgramCounterNext);
  477.       $C2: if FRegA < FRegB then Inc(ProgramCounterNext);
  478.       $C3: if FRegA = FRegB then Inc(ProgramCounterNext);
  479.       $C4: if ((Din and 1) shr 0) = 1 then Inc(ProgramCounterNext);
  480.       $C5: if ((Din and 2) shr 1) = 1 then Inc(ProgramCounterNext);
  481.       $C6: if ((Din and 4) shr 2) = 1 then Inc(ProgramCounterNext);
  482.       $C7: if ((Din and 8) shr 3) = 1 then Inc(ProgramCounterNext);
  483.       $C8: if ((Din and 1) shr 0) = 0 then Inc(ProgramCounterNext);
  484.       $C9: if ((Din and 2) shr 1) = 0 then Inc(ProgramCounterNext);
  485.       $CA: if ((Din and 4) shr 2) = 0 then Inc(ProgramCounterNext);
  486.       $CB: if ((Din and 8) shr 3) = 0 then Inc(ProgramCounterNext);
  487.       $CC: if S1 = false then Inc(ProgramCounterNext);
  488.       $CD: if S2 = false then Inc(ProgramCounterNext);
  489.       $CE: if S1 = true then Inc(ProgramCounterNext);
  490.       $CF: if S2 = true then Inc(ProgramCounterNext);
  491.     end;
  492.  
  493.     (*
  494.     ----------------------------------------------------
  495.     Code        Assembly        Alternative     Comment
  496.     ----------------------------------------------------
  497.     D0  CALL <PAGE>0
  498.     D1  CALL <PAGE>1
  499.     D2  CALL <PAGE>2
  500.     D3  CALL <PAGE>3
  501.     D4  CALL <PAGE>4
  502.     D5  CALL <PAGE>5
  503.     D6  CALL <PAGE>6
  504.     D7  CALL <PAGE>7
  505.     D8  CALL <PAGE>8
  506.     D9  CALL <PAGE>9
  507.     DA  CALL <PAGE>A
  508.     DB  CALL <PAGE>B
  509.     DC  CALL <PAGE>C
  510.     DD  CALL <PAGE>D
  511.     DE  CALL <PAGE>E
  512.     DF  CALL <PAGE>F
  513.     *)
  514.     if (Instruction >= $D0) and (Instruction <= $DF) then
  515.     begin
  516.       FCalledOnce        := true;
  517.       FReturnAddress     := ProgramCounterNext;
  518.       ProgramCounterNext := (FPage shl 4) + (Instruction and $F)
  519.     end;
  520.  
  521.     (*
  522.     ----------------------------------------------------
  523.     Code        Assembly        Alternative     Comment
  524.     ----------------------------------------------------
  525.     E0  RET
  526.     *)
  527.     if Instruction = $E0 then
  528.     begin
  529.       if not FCalledOnce then
  530.       begin
  531.         // "Freeze" is the behavior of the actual chip (see test program 41 54 27 42 54 27 E0 7A 27 54 33)
  532.         ProgramCounterNext := ProgramCounterCurrent;
  533.       end
  534.       else
  535.       begin
  536.         ProgramCounterNext := FReturnAddress;
  537.       end;
  538.     end;
  539.   finally
  540.     FPC := ProgramCounterNext;
  541.   end;
  542. end;
  543.  
  544. procedure THT46F47.WaitMs(milliseconds: integer);
  545. begin
  546.   if Assigned(FOnWait) then
  547.     FOnWait(milliseconds)
  548.   else
  549.     Sleep(milliseconds);
  550. end;
  551.  
  552. end.
  553.