[[サブルーチンコールその1]]
* 概要 [#kcfaf712]
- I2Cデバイスを、より汎用的に利用するためのサブルーチン群の例です。以下のサブルーチンを含んでいます。
-- SubI2C1 ... [[サブルーチンコールその1]]のサブルーチン、そのものです。定型的なI2C制御で使っています。ram.v では、このサブルーチンを使って、I2C通信の開始、
I2C操作手順を書いたデータ列の、一つ前のアドレスに、そのデータの大きさ(ワード数)を書いたものをまとめます。データの大きさを書いたアドレスをPUSH命令を使ってサブルーチン SubI2C1に伝えます。操作手順とその大きさを複数用意して、このサブルーチン SubI2C1に引き渡すことにより、様々なI2Cデバイスの操作を行うことができます。
- [[サブルーチンコールその1]]のサブルーチン, SubI2C1を使い、I2Cの制御用データを、機能ごとに分割して呼び出しています。
* verilog [#xe156177]
- [[MiniCPUとI2Cバスの接続]]」の ram.v を以下の ram.v で置き換えて動かします。
- ram.v
 // Subroutine calling by the mini CPU.
 mem[8'h00] = 16'h1068; //           PUSHI i2cStart  // push arg1... the i2c slave Addr
 mem[8'h01] = 16'h1003; //           PUSHI Rtn0     // push the return address
 mem[8'h02] = 16'h4041; //           JMP SubI2C1    // call the subroutine
 //
 mem[8'h03] = 16'h1070; // Rtn0:     PUSHI i2cAddr  // push arg1... the i2c slave Addr
 mem[8'h04] = 16'h1006; //           PUSHI Rtn1     // push the return address
 mem[8'h05] = 16'h4041; //           JMP SubI2C1    // call the subroutine
 //
 mem[8'h06] = 16'h1090; // Rtn1:     PUSHI i2cAddrW // push arg1 ... write bit of i2cAddr
 mem[8'h07] = 16'h1009; //           PUSHI Rtn2     //
 mem[8'h08] = 16'h4041; //           JMP SubI2C1    // call the subroutine
 //
 mem[8'h09] = 16'h1098; // Rtn2:     PUSHI i2cRAck // push arg1 .... read the ack
 mem[8'h0A] = 16'h100C; //           PUSHI Rtn3     //
 mem[8'h0B] = 16'h4041; //           JMP SubI2C1    // call the subroutine
 //
 mem[8'h0C] = 16'h10B0; // Rtn3:     PUSHI i2cD1    // push arg1 ... send register number to the i2c slave
 mem[8'h0D] = 16'h100F; //           PUSHI Rtn4     //
 mem[8'h0E] = 16'h4041; //           JMP SubI2C1    // call the subroutine
 //
 mem[8'h0F] = 16'h1098; // Rtn4:     PUSHI i2cRAck  // push arg1 .... read the ack
 mem[8'h10] = 16'h1012; //           PUSHI Rtn5     // push the return address
 mem[8'h11] = 16'h4041; //           JMP SubI2C1    // call the subroutine
 //
 mem[8'h12] = 16'h1068; // Rtn5:     PUSHI i2cStart  // push arg1... the i2c slave Addr
 mem[8'h13] = 16'h1015; //           PUSHI Rtn6     // push the return address
 mem[8'h14] = 16'h4041; //           JMP SubI2C1    // call the subroutine
 //
 mem[8'h15] = 16'h1070; // Rtn6:     PUSHI i2cAddr  // push arg1 .... the i2c slave addr
 mem[8'h16] = 16'h1018; //           PUSHI Rtn7     // push the return address
 mem[8'h17] = 16'h4041; //           JMP SubI2C1    // call the subroutine
 //
 mem[8'h18] = 16'h1094; // Rtn7:     PUSHI i2cAddrR  // push arg1 .... read bit of i2cAddr
 mem[8'h19] = 16'h101B; //           PUSHI Rtn8     // push the return address
 mem[8'h1A] = 16'h4041; //           JMP SubI2C1    // call the subroutine
 //
 mem[8'h1B] = 16'h1098; // Rtn4:     PUSHI i2cRAck  // push arg1 .... read the ack
 mem[8'h1C] = 16'h101E; //           PUSHI Rtn5     // push the return address
 mem[8'h1D] = 16'h4041; //           JMP SubI2C1    // call the subroutine
 //
 mem[8'h1E] = 16'h10d0; // Rtn8:     PUSHI i2cRead    // push arg1 .... read the data from the slave
 mem[8'h1F] = 16'h1021; //           PUSHI Rtn9     // push the return address
 mem[8'h20] = 16'h4041; //           JMP SubI2C1    // call the subroutine
 //
 mem[8'h21] = 16'hD000; // Rtn9:     IN            // input msb
 mem[8'h22] = 16'h1001; //           PUSHI 1
 mem[8'h23] = 16'hF003; //           SHL
 mem[8'h24] = 16'h303A; //           POP  tmp1
 //
 mem[8'h25] = 16'h109c; //           PUSHI i2cWAck  // push arg1 .... write the ack
 mem[8'h26] = 16'h1028; //           PUSHI Rtn10     // push the return address
 mem[8'h27] = 16'h4041; //           JMP SubI2C1    // call the subroutine
 //
 mem[8'h28] = 16'h10D0; // Rtn10:    PUSHI i2cRead    // push arg1 .... read the data from the slave
 mem[8'h29] = 16'h102B; //           PUSHI Rtn11     // push the return address
 mem[8'h2A] = 16'h4041; //           JMP SubI2C1    // call the subroutine
 //
 mem[8'h2B] = 16'hD000; // Rtn11:    in             // input lsb
 mem[8'h2C] = 16'h100F; //           PUSHI 15
 mem[8'h2D] = 16'hF004; //           SHR
 mem[8'h2E] = 16'h303B; //           POP temp2
 //
 mem[8'h2F] = 16'h10A0; // Rtn12     PUSHI i2cNAck  // push arg1 .... write the ack
 mem[8'h30] = 16'h1032; //           PUSHI Rtn13     // push the return address
 mem[8'h31] = 16'h4041; //           JMP SubI2C1    // call the subroutine
 //
 mem[8'h32] = 16'h10F0; // Rtn13:    PUSHI i2cStop  // push arg1 .... write the ack
 mem[8'h33] = 16'h1035; //           PUSHI Rtn14     // push the return address
 mem[8'h34] = 16'h4041; //           JMP SubI2C1    // call the subroutine
 //
 mem[8'h35] = 16'h203A; // Rtn14:    PUSH temp1
 mem[8'h36] = 16'h203B; //           PUSH temp2
 mem[8'h37] = 16'hF006; //           BOR
 mem[8'h38] = 16'hE000; //           OUT
 mem[8'h39] = 16'h0000; //           HALT           // 
 mem[8'h3A] = 16'h0000; // temp1:
 mem[8'h3B] = 16'h0000; // temp2:
 //
 mem[8'h40] = 16'h0000; //        
 mem[8'h41] = 16'h205C; // SubI2C1:  PUSH LblJMP    // subroutine. the 1st step to make return instruction
 mem[8'h42] = 16'hF006; //           BOR            // make the return instruction using arg1 and the jump instruction
 mem[8'h43] = 16'h305B; //           POP RtnSub1    // save the return instruction
 mem[8'h44] = 16'h305D; //           POP Sub1Data2  // save the arg1
 mem[8'h45] = 16'h205D; //           PUSH Sub1Data2
 mem[8'h46] = 16'h7000; //           LD
 mem[8'h47] = 16'h3060; //           POP N
 mem[8'h48] = 16'h205D; //           PUSH Sub1Data2
 mem[8'h49] = 16'h1001; //           PUSHI 1
 mem[8'h4A] = 16'hF000; //           ADD
 mem[8'h4B] = 16'h305E; //           POP Sub1SA
 mem[8'h4C] = 16'h1000; //           PUSHI 0
 mem[8'h4D] = 16'h305F; //           POP i
 mem[8'h4E] = 16'h205F; // L1        PUSH i
 mem[8'h4F] = 16'h205E; //           PUSH Sub1SA
 mem[8'h50] = 16'hF000; //           ADD
 mem[8'h51] = 16'h7000; //           LD     ... Sub1S[i];
 mem[8'h52] = 16'hE000; //           OUT    ... print(Sub1S[i]) ;
 mem[8'h53] = 16'h205F; //           PUSH i;
 mem[8'h54] = 16'h1001; //           PUSHI 1     
 mem[8'h55] = 16'hF000; //           ADD
 mem[8'h56] = 16'h305F; //           POP i
 mem[8'h57] = 16'h205F; //           PUSH i
 mem[8'h58] = 16'h2060; //           PUSH N
 mem[8'h59] = 16'hF001; //           SUB
 mem[8'h5A] = 16'h604E; //           JNZ L1:   if(i<n) goto L1;
 mem[8'h5B] = 16'h0000; // RtnSub1:  JMP             // return
 mem[8'h5C] = 16'h4000; // LblJMP:   0x4000
 mem[8'h5D] = 16'h0000; // Sub1Data2:
 mem[8'h5E] = 16'h0000; // Sub1SA:
 mem[8'h5F] = 16'h0000; // i:
 mem[8'h60] = 16'h0000; // N:
 //
 // data for controlling i2c
 //  (MSB) ......    scl, sda (LSB)
 //
 // I2C start
 mem[8'h68] = 16'h0004; // i2cStart:  3
 mem[8'h69] = 16'h0001; //            01
 mem[8'h6A] = 16'h0003; //            11
 mem[8'h6B] = 16'h0002; //            10
 mem[8'h6C] = 16'h0000; //            00
 //
 //  I2C addr
 mem[8'h70] = 16'h0013; // i2cAddr:  x14
 mem[8'h71] = 16'h0001; //           01 
 mem[8'h72] = 16'h0003; //           11  sda 1
 mem[8'h73] = 16'h0001; //           01
 mem[8'h74] = 16'h0000; //           00
 mem[8'h75] = 16'h0002; //           10  sda 10
 mem[8'h76] = 16'h0000; //           00
 mem[8'h77] = 16'h0002; //           10  sda 100
 mem[8'h78] = 16'h0000; //           00
 mem[8'h79] = 16'h0001; //           01
 mem[8'h7A] = 16'h0003; //           11  sda 1001
 mem[8'h7B] = 16'h0001; //           01
 mem[8'h7C] = 16'h0000; //           00
 mem[8'h7D] = 16'h0002; //           10  sda 10010
 mem[8'h7E] = 16'h0000; //           00
 mem[8'h7F] = 16'h0001; //           01
 mem[8'h80] = 16'h0003; //           11  sda 100101
 mem[8'h81] = 16'h0001; //           01
 mem[8'h82] = 16'h0003; //           11  sda 1001011 .. 0x4B
 mem[8'h83] = 16'h0001; //           01
 //mem[8'h84] = 16'h0000; //           00
 //
 // I2C AddrWrite
 mem[8'h90] = 16'h0003; // i2cAddrW:  x03
 mem[8'h91] = 16'h0000; //           00
 mem[8'h92] = 16'h0002; //           10  send 0 ... write
 mem[8'h93] = 16'h0000; //           00
 //
 //  I2C AddrRead
 mem[8'h94] = 16'h0003; // i2cAddrR:  x03
 mem[8'h95] = 16'h0001; //           01
 mem[8'h96] = 16'h0003; //           11  ... read
 mem[8'h97] = 16'h0001; //           01
 //
 // I2C 
 mem[8'h98] = 16'h0003; // i2cRAck:  x03
 mem[8'h99] = 16'h0001; //           01
 mem[8'h9A] = 16'h0003; //           11  read ack 
 mem[8'h9B] = 16'h0001; //           01
 //
 // I2C Write Ack
 mem[8'h9C] = 16'h0003; // i2cWAck:  x03
 mem[8'h9D] = 16'h0000; //           00
 mem[8'h9E] = 16'h0002; //           10  send 0 ... write
 mem[8'h9F] = 16'h0000; //           00
 //
 // I2C NAck
 mem[8'hA0] = 16'h0003; // i2cNAck  x03
 mem[8'hA1] = 16'h0001; //           01
 mem[8'hA2] = 16'h0003; //           11  ... read
 mem[8'hA3] = 16'h0001; //           01
 //
 // i2cD1
 mem[8'hB0] = 16'h0011; // i2cD1:    x11
 mem[8'hB1] = 16'h0000; //           00
 mem[8'hB2] = 16'h0002; //           10   write 0
 mem[8'hB3] = 16'h0000; //           00
 mem[8'hB4] = 16'h0002; //           10   write 00
 mem[8'hB5] = 16'h0000; //           00
 mem[8'hB6] = 16'h0002; //           10   write 000
 mem[8'hB7] = 16'h0000; //           00
 mem[8'hB8] = 16'h0002; //           10   write 0000
 mem[8'hB9] = 16'h0000; //           00
 mem[8'hBA] = 16'h0002; //           10   write 00000
 mem[8'hBB] = 16'h0000; //           00
 mem[8'hBC] = 16'h0002; //           10   write 000000
 mem[8'hbd] = 16'h0000; //           00
 mem[8'hbe] = 16'h0002; //           10   write 0000000
 mem[8'hbf] = 16'h0000; //           00
 mem[8'hc0] = 16'h0002; //           10   write 00000000  .... write register 0
 mem[8'hc1] = 16'h0000; //           00
 //
 //
 mem[8'hd0] = 16'h0011; // i2cRead  x11
 mem[8'hd1] = 16'h0001; //           01
 mem[8'hd2] = 16'h0003; //           11  read 1st bit
 mem[8'hd3] = 16'h0001; //           01
 mem[8'hd4] = 16'h0003; //           11  read 2nd bit
 mem[8'hd5] = 16'h0001; //           01
 mem[8'hd6] = 16'h0003; //           11  read 3rd bit
 mem[8'hd7] = 16'h0001; //           01
 mem[8'hd8] = 16'h0003; //           11  read 4th bit
 mem[8'hd9] = 16'h0001; //           01
 mem[8'hda] = 16'h0003; //           11  read 5th bit
 mem[8'hdb] = 16'h0001; //           01
 mem[8'hdc] = 16'h0003; //           11  read 6th bit
 mem[8'hdd] = 16'h0001; //           01
 mem[8'hde] = 16'h0003; //           11  read 7th bit
 mem[8'hef] = 16'h0001; //           01
 mem[8'he0] = 16'h0003; //           11  read 8th bit
 mem[8'he1] = 16'h0001; //           01
 //
 //  stop
 mem[8'hf0] = 16'h0003; // i2cStop   x03
 mem[8'hf1] = 16'h0002; //           10  
 mem[8'hf2] = 16'h0003; //           11  stop the transfering
 mem[8'hf3] = 16'h0001; //           01


トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS