Subversion Repositories ht46f47_simulator

Rev

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