Z8530.java
     1: //========================================================================================
     2: //  Z8530.java
     3: //    en:SCC -- Serial Communication Controller
     4: //    ja:SCC -- シリアルコミュニケーションコントローラ
     5: //  Copyright (C) 2003-2025 Makoto Kamada
     6: //
     7: //  This file is part of the XEiJ (X68000 Emulator in Java).
     8: //  You can use, modify and redistribute the XEiJ if the conditions are met.
     9: //  Read the XEiJ License for more details.
    10: //  https://stdkmd.net/xeij/
    11: //========================================================================================
    12: 
    13: //----------------------------------------------------------------------------------------
    14: //  マウス
    15: //    マウスイベントとマウスモーションイベントで取得したデータを返す
    16: //  RS-232C
    17: //    ターミナルに接続
    18: //----------------------------------------------------------------------------------------
    19: 
    20: package xeij;
    21: 
    22: import java.awt.event.*;  //ActionEvent,ActionListener,ComponentAdapter,ComponentEvent,ComponentListener,FocusAdapter,FocusEvent,FocusListener,InputEvent,KeyAdapter,KeyEvent,KeyListener,MouseAdapter,MouseEvent,MouseListener,MouseMotionAdapter,MouseWheelEvent,WindowAdapter,WindowEvent,WindowListener,WindowStateListener
    23: import java.lang.*;  //Boolean,Character,Class,Comparable,Double,Exception,Float,IllegalArgumentException,Integer,Long,Math,Number,Object,Runnable,SecurityException,String,StringBuilder,System
    24: import java.util.*;  //ArrayList,Arrays,Calendar,GregorianCalendar,HashMap,Map,Map.Entry,Timer,TimerTask,TreeMap
    25: import javax.swing.*;  //AbstractButton,AbstractSpinnerModel,Box,ButtonGroup,DefaultListModel,ImageIcon,JApplet,JButton,JCheckBox,JCheckBoxMenuItem,JComponent,JDialog,JFileChooser,JFrame,JLabel,JList,JMenu,JMenuBar,JMenuItem,JPanel,JRadioButton,JScrollPane,JSpinner,JTextArea,JTextField,JTextPane,JViewport,ScrollPaneConstants,SpinnerListModel,SpinnerNumberModel,SwingConstants,SwingUtilities,UIManager,UIDefaults,UnsupportedLookAndFeelException
    26: import javax.swing.event.*;  //CaretEvent,CaretListener,ChangeEvent,ChangeListener,DocumentEvent,DocumentListener,ListSelectionListener
    27: 
    28: public class Z8530 {
    29: 
    30:   public static final boolean SCC_DEBUG_ON = false;
    31:   public static int sccDebugOn;  //1=Port0B,2=Port1A,4=Interrupt
    32:   public static JMenu sccDebugMenu;
    33: 
    34:   public static double sccFreq = 5000000.0;  //SCCの動作周波数
    35: 
    36:   //ポート
    37:   public static final int SCC_0B_COMMAND = 0x00e98001;
    38:   public static final int SCC_0B_DATA    = 0x00e98003;
    39:   public static final int SCC_1A_COMMAND = 0x00e98005;
    40:   public static final int SCC_1A_DATA    = 0x00e98007;
    41: 
    42:   //割り込み
    43:   //  ベクタ
    44:   //    0  ポート0B送信バッファ空(マウス送信)
    45:   //    1  ポート0B外部/ステータス変化
    46:   //    2  ポート0B受信バッファフル(マウス受信)
    47:   //    3  ポート0B特別受信条件
    48:   //    4  ポート1A送信バッファ空(RS-232C送信)
    49:   //    5  ポート1A外部/ステータス変化
    50:   //    6  ポート1A受信バッファフル(RS-232C受信)
    51:   //    7  ポート1A特別受信条件
    52:   //  マスク
    53:   //    0x80  常に0
    54:   //    0x40  常に0
    55:   //    0x20  ポート1A受信バッファフル(RS-232C受信)
    56:   //    0x10  ポート1A送信バッファ空(RS-232C送信)
    57:   //    0x08  ポート1A外部/ステータス変化
    58:   //    0x04  ポート0B受信バッファフル(マウス受信)
    59:   //    0x02  ポート0B送信バッファ空(マウス送信)
    60:   //    0x01  ポート0B外部/ステータス変化
    61:   //  優先順位
    62:   //    高い  1A受信バッファフル(RS-232C受信)
    63:   //          1A送信バッファ空(RS-232C送信)
    64:   //          1A外部/ステータス変化
    65:   //          0B受信バッファフル(マウス受信)
    66:   //          0B送信バッファ空(マウス送信)
    67:   //    低い  0B外部/ステータス変化
    68:   //!!! マウス送信、外部/ステータス変化、特別受信条件の割り込みは未実装
    69:   public static int sccInterruptVector;  //非修飾ベクタ。WR2
    70:   public static int sccVectorInclude;  //WR9&0x11
    71:   //  マウス受信割り込み
    72:   public static final int SCC_0B_RECEIVE_VECTOR = 2;
    73:   public static final int SCC_0B_RECEIVE_MASK = 0x04;
    74:   public static int scc0bReceiveMask;  //マスク
    75:   public static int scc0bReceiveRR3;  //RR3のペンディングビット。割り込み発生でセット
    76:   public static int scc0bReceiveRequest;  //リクエスト。割り込み発生でセット、受け付けでクリア
    77:   public static int scc0bReceiveVector;  //修飾ベクタ
    78:   //  RS-232C受信割り込み
    79:   public static final int SCC_1A_RECEIVE_VECTOR = 6;
    80:   public static final int SCC_1A_RECEIVE_MASK = 0x20;
    81:   public static int scc1aReceiveMask;  //マスク
    82:   public static int scc1aReceiveRR3;  //RR3のペンディングビット。割り込み発生でセット、IUSリセットでクリア
    83:   public static int scc1aReceiveRequest;  //リクエスト。割り込み発生でセット、受け付けでクリア
    84:   public static int scc1aReceiveVector;  //修飾ベクタ
    85:   //  RS-232C送信割り込み
    86:   public static final int SCC_1A_SEND_VECTOR = 4;
    87:   public static final int SCC_1A_SEND_MASK = 0x10;
    88:   public static int scc1aSendMask;  //マスク
    89:   public static int scc1aSendRR3;  //RR3のペンディングビット。割り込み発生でセット
    90:   public static int scc1aSendRequest;  //リクエスト。割り込み発生でセット、受け付けでクリア
    91:   public static int scc1aSendVector;  //修飾ベクタ
    92: 
    93:   //ポート0B マウス
    94:   public static int scc0bRegisterNumber;
    95:   public static int scc0bRts;  //RTS(0または1)
    96:   public static int scc0bBaudRateGen;  //WR13<<8|WR12
    97:   public static int scc0bInputCounter;  //マウスデータのカウンタ。0~2
    98:   public static int scc0bData1;
    99:   public static int scc0bData2;
   100: 
   101:   public static final boolean SCC_FSX_MOUSE = true;  //true=SX-Windowをシームレスにする
   102:   public static int sccFSXMouseHook;  //FSX.Xのマウス受信データ処理ルーチンのアドレス
   103:   public static int sccFSXMouseWork;  //FSX.Xのマウスワークのアドレス
   104: 
   105:   //ポート1A RS-232C
   106:   public static final int SCC_1A_INPUT_BITS = 16;
   107:   public static final int SCC_1A_INPUT_SIZE = 1 << SCC_1A_INPUT_BITS;
   108:   public static final int SCC_1A_INPUT_MASK = SCC_1A_INPUT_SIZE - 1;
   109:   public static int scc1aRegisterNumber;
   110:   public static final int[] scc1aInputBuffer = new int[SCC_1A_INPUT_SIZE];  //RS-232C受信バッファ。データはゼロ拡張済み
   111:   public static int scc1aInputRead;  //RS-232C受信バッファから次に読み出すデータの位置。read==writeのときバッファエンプティ
   112:   public static int scc1aInputWrite;  //RS-232C受信バッファに次に書き込むデータの位置。(write+1&SCC_1A_INPUT_MASK)==readのときバッファフル
   113:   //  ボーレート
   114:   public static int scc1aBRGEnable;  //WR14のbit0。true=ボーレートジェネレータ動作
   115:   public static int scc1aClockModeShift;  //WR4のbit6-7。0=2^0,1=2^4,2=2^5,3=2^6
   116:   public static int scc1aBaudRateGen;  //WR13<<8|WR12
   117:   public static long scc1aInterval;  //転送間隔(XEiJ.TMR_FREQ単位)
   118:   //  通信設定
   119:   public static int scc1aRxBits;  //WR3のbit7-6。00=5bit,01=7bit,10=6bit,11=8bit。RR8の未使用ビットは1
   120:   public static int scc1aRxEnable;  //WR3のbit0。1=enable
   121:   public static int scc1aStop;  //WR4のbit3-2。01=s1,10=s1.5,11=s2
   122:   public static int scc1aParity;  //WR4のbit1-0。x0=pn,01=po,11=pe
   123:   public static int scc1aTxBits;  //WR5のbit6-5。00=1-5bit,01=7bit,10=6bit,11=8bit。1-5bitのとき1111000x,111000xx,11000xxx,1000xxxx,000xxxxx
   124:   public static int scc1aTxEnable;  //WR5のbit3。1=enable
   125: 
   126: 
   127:   //sccInit ()
   128:   //  初期化
   129:   public static void sccInit () {
   130: 
   131:     sccFreq = 5000000 < Settings.sgsGetInt ("sccfreq") ? 7372800.0 : 5000000.0;
   132: 
   133:     if (SCC_DEBUG_ON) {
   134:       sccDebugOn = 2;
   135:       sccDebugMenu = 
   136:         ComponentFactory.createMenu (
   137:           "SCC",
   138:           ComponentFactory.createCheckBoxMenuItem ((sccDebugOn & 1) != 0, "Port 0B", new ActionListener () {
   139:             @Override public void actionPerformed (ActionEvent ae) {
   140:               sccDebugOn = (sccDebugOn & ~1) | (((JCheckBoxMenuItem) ae.getSource ()).isSelected () ? 1 : 0);
   141:             }
   142:           }),
   143:           ComponentFactory.createCheckBoxMenuItem ((sccDebugOn & 2) != 0, "Port 1A", new ActionListener () {
   144:             @Override public void actionPerformed (ActionEvent ae) {
   145:               sccDebugOn = (sccDebugOn & ~2) | (((JCheckBoxMenuItem) ae.getSource ()).isSelected () ? 2 : 0);
   146:             }
   147:           }),
   148:           ComponentFactory.createCheckBoxMenuItem ((sccDebugOn & 4) != 0, "Interrupt", new ActionListener () {
   149:             @Override public void actionPerformed (ActionEvent ae) {
   150:               sccDebugOn = (sccDebugOn & ~4) | (((JCheckBoxMenuItem) ae.getSource ()).isSelected () ? 4 : 0);
   151:             }
   152:           })
   153:           );
   154:     }
   155: 
   156:     //scc1aInputBuffer = new int[SCC_1A_INPUT_SIZE];
   157: 
   158:     sccReset ();
   159: 
   160:   }  //sccInit()
   161: 
   162: 
   163:   //sccTini ()
   164:   //  後始末
   165:   public static void sccTini () {
   166:     Settings.sgsPutInt ("sccfreq", (int) sccFreq);
   167:   }
   168: 
   169: 
   170:   //リセット
   171:   public static void sccReset () {
   172:     //割り込み
   173:     sccInterruptVector = 0x00;
   174:     sccVectorInclude = 0x00;
   175:     scc0bReceiveMask = 0;
   176:     scc0bReceiveRR3 = 0;
   177:     scc0bReceiveRequest = 0;
   178:     scc0bReceiveVector = 0;
   179:     scc1aReceiveMask = 0;
   180:     scc1aReceiveRR3 = 0;
   181:     scc1aReceiveRequest = 0;
   182:     scc1aReceiveVector = 0;
   183:     scc1aSendMask = 0;
   184:     scc1aSendRR3 = 0;
   185:     scc1aSendRequest = 0;
   186:     scc1aSendVector = 0;
   187:     //マウス
   188:     scc0bRegisterNumber = 0;
   189:     scc0bRts = 0;
   190:     scc0bBaudRateGen = 31;  //4800bps。(5000000/2/16)/4800-2=30.552。(5000000/2/16)/(31+2)=4734.848=4800*0.986
   191:     scc0bInputCounter = 0;
   192:     scc0bData1 = 0;
   193:     scc0bData2 = 0;
   194:     if (SCC_FSX_MOUSE) {
   195:       sccFSXMouseHook = 0;
   196:       sccFSXMouseWork = 0;
   197:     }
   198:     //RS-232C
   199:     scc1aRegisterNumber = 0;
   200:     Arrays.fill (scc1aInputBuffer, 0);
   201:     scc1aInputRead = 0;
   202:     scc1aInputWrite = 0;
   203:     scc1aRxBits = 3;  //b8
   204:     scc1aRxEnable = 0;
   205:     scc1aStop = 1;  //s1
   206:     scc1aParity = 0;  //pn
   207:     scc1aTxBits = 3;
   208:     scc1aTxEnable = 0;
   209:     scc1aBRGEnable = 0;
   210:     scc1aClockModeShift = 4;  //1/16
   211:     scc1aBaudRateGen = 14;  //9600bps
   212:     double rate = sccFreq / (double) ((scc1aBaudRateGen + 2) << (scc1aClockModeShift + 1));
   213:     double bits = (1.0 +  //start
   214:                    (scc1aRxBits == 0 ? 5.0 :
   215:                     scc1aRxBits == 1 ? 7.0 :
   216:                     scc1aRxBits == 2 ? 6.0 : 8.0) +  //data
   217:                    ((scc1aParity & 1) == 0 ? 0.0 : 1.0) +  //parity
   218:                    (scc1aStop == 0 ? 0.0 :
   219:                     scc1aStop == 1 ? 1.0 :
   220:                     scc1aStop == 2 ? 1.5 : 2.0));  //stop
   221:     double interval = bits / rate;
   222:     scc1aInterval = Math.round (interval * (double) XEiJ.TMR_FREQ);
   223:     //
   224:     RS232CTerminal.trmAUXReset ();
   225:   }  //sccReset()
   226: 
   227:   //割り込み受付
   228:   //  コアが割り込み要求を受け付けたときに呼び出す
   229:   //  割り込みベクタ番号を返す
   230:   //  割り込み要求を取り下げる場合は0を返す
   231:   //  オートベクタを使用するデバイスはオートベクタの番号を返すこと
   232:   public static int sccAcknowledge () {
   233:     int d = 0;
   234:     //優先順位は固定
   235:     if (scc1aReceiveRequest != 0) {  //1A受信バッファフル(RS-232C受信)
   236:       scc1aReceiveRequest = 0;
   237:       d = scc1aReceiveVector;
   238:     } else if (scc1aSendRequest != 0) {  //1A送信バッファ空(RS-232C送信)
   239:       scc1aSendRequest = 0;
   240:       d = scc1aSendVector;
   241:     } else if (scc0bReceiveRequest != 0) {  //0B受信バッファフル(マウス受信)
   242:       scc0bReceiveRequest = 0;
   243:       d = scc0bReceiveVector;
   244:     }
   245:     if (SCC_DEBUG_ON && (sccDebugOn & 4) != 0) {
   246:       System.out.printf ("%08x sccAcknowledge()=0x%02x\n", XEiJ.regPC0, d);
   247:     }
   248:     return d;
   249:   }  //sccAcknowledge()
   250: 
   251:   //割り込み終了
   252:   //  コアが割り込み処理を終了したときに呼び出す
   253:   //  まだ処理されていない割り込みが残っていたら再度割り込み要求を出す
   254:   public static void sccDone () {
   255:     if (SCC_DEBUG_ON && (sccDebugOn & 4) != 0) {
   256:       System.out.printf ("%08x sccDone()\n", XEiJ.regPC0);
   257:     }
   258:     if ((scc1aReceiveRequest | scc1aSendRequest | scc0bReceiveRequest) != 0) {
   259:       XEiJ.mpuIRR |= XEiJ.MPU_SCC_INTERRUPT_MASK;
   260:     }
   261:   }  //sccDone()
   262: 
   263:   //sccUpdateVector ()
   264:   //  scc0bReceiveVector,scc1aReceiveVector,scc1aSendVectorを更新する
   265:   //  sccInterruptVector,sccVectorIncludeを更新したら呼び出す
   266:   public static void sccUpdateVector () {
   267:     if (sccVectorInclude == 0x00) {  //(WR9&0x01)==0x00
   268:       scc0bReceiveVector = sccInterruptVector;
   269:       scc1aReceiveVector = sccInterruptVector;
   270:       scc1aSendVector    = sccInterruptVector;
   271:     } else if (sccVectorInclude == 0x01) {  //(WR9&0x11)==0x01
   272:       int t = sccInterruptVector & 0b11110001;
   273:       scc0bReceiveVector = t | SCC_0B_RECEIVE_VECTOR << 1;
   274:       scc1aReceiveVector = t | SCC_1A_RECEIVE_VECTOR << 1;
   275:       scc1aSendVector    = t | SCC_1A_SEND_VECTOR << 1;
   276:     } else {  //(WR9&0x11)==0x11
   277:       int t = sccInterruptVector & 0b10001111;
   278:       scc0bReceiveVector = t | SCC_0B_RECEIVE_VECTOR << 4;
   279:       scc1aReceiveVector = t | SCC_1A_RECEIVE_VECTOR << 4;
   280:       scc1aSendVector    = t | SCC_1A_SEND_VECTOR << 4;
   281:     }
   282:     if (SCC_DEBUG_ON && (sccDebugOn & 4) != 0) {
   283:       System.out.printf ("scc0bReceiveVector=0x%02x\n", scc0bReceiveVector);
   284:       System.out.printf ("scc1aReceiveVector=0x%02x\n", scc1aReceiveVector);
   285:       System.out.printf ("scc1aSendVector=0x%02x\n", scc1aSendVector);
   286:     }
   287:   }  //sccUpdateVector()
   288: 
   289:   //d = sccReadByte (a, peek)
   290:   //  リードバイト
   291:   public static int sccReadByte (int a, boolean peek) {
   292:     XEiJ.mpuClockTime += XEiJ.busWaitTime.scc;
   293:     int d = 0;
   294:     switch (a & 7) {
   295:       //------------------------------------------------
   296:     case SCC_0B_COMMAND & 7:  //ポート0Bコマンド読み出し
   297:       switch (scc0bRegisterNumber) {
   298:       case 0:  //RR0
   299:         //  0x80  ブレークまたはアボート
   300:         //  0x40  送信アンダーラン
   301:         //  0x20  CTS(0=送信禁止,1=送信許可)
   302:         //  0x10  SYNC
   303:         //  0x08  DCD
   304:         //  0x04  送信バッファ空
   305:         //  0x02  ボーレートカウント0
   306:         //  0x01  受信バッファフル
   307:         d = scc0bInputCounter < 3 ? 0x25 : 0x24;
   308:         break;
   309:       case 2:  //RR2
   310:         //修飾割り込みベクタ
   311:         //  ポート0BのRR2はWR2に設定したベクタを割り込み要求で加工して返す
   312:         d = (scc1aReceiveRequest != 0 ? scc1aReceiveVector :  //1A受信バッファフル(RS-232C受信)
   313:              scc1aSendRequest != 0 ? scc1aSendVector :  //1A送信バッファ空(RS-232C送信)
   314:              scc0bReceiveRequest != 0 ? scc0bReceiveVector :  //0B受信バッファフル(マウス受信)
   315:              sccInterruptVector);
   316:         break;
   317:       case 3:  //RR3
   318:         //ポート0BのRR3は常に0
   319:         //  ポート0Bの割り込みペンディングを見るときはポート1AのRR3を参照する
   320:         //d = 0;
   321:         break;
   322:       case 12:  //RR12
   323:         d = scc0bBaudRateGen & 0xff;
   324:         break;
   325:       case 13:  //RR13
   326:         d = scc0bBaudRateGen >> 8 & 0xff;
   327:         break;
   328:       default:
   329:         if (SCC_DEBUG_ON && sccDebugOn != 0) {
   330:           System.out.println ("unimplemented register");
   331:         }
   332:       }
   333:       if (peek) {
   334:         break;
   335:       }
   336:       scc0bRegisterNumber = 0;
   337:       break;
   338:       //------------------------------------------------
   339:     case SCC_0B_DATA & 7:  //ポート0Bデータ読み出し(マウス受信)
   340:       if (scc0bInputCounter == 0) {  //1バイト目
   341:         d = Mouse.musExtraData;
   342:         if (XEiJ.mpuClockTime < Mouse.musWheelReleaseTime) {
   343:           d |= Mouse.musWheelButton;
   344:         }
   345:         if (peek) {
   346:           break;
   347:         }
   348:         Mouse.musExtraData = Mouse.musData;
   349:         if (!Mouse.musOnScreen) {  //ホストのマウスカーソルがスクリーン上にない
   350:           //Mouse.musShow ();
   351:           if (Mouse.musCursorNumber != 1 && Mouse.musCursorAvailable) {
   352:             Mouse.musCursorNumber = 1;
   353:             XEiJ.pnlPanel.setCursor (Mouse.musCursorArray[1]);  //ホストのマウスカーソルを表示する
   354:           }
   355:           scc0bData1 = scc0bData2 = 0;
   356:         } else if (Mouse.musSeamlessOn) {  //シームレス
   357:           int on, dx, dy, coeff = 256;
   358:           if (XEiJ.currentMPU < Model.MPU_MC68LC040) {  //MMUなし
   359:             if (SCC_FSX_MOUSE &&
   360:                 sccFSXMouseHook != 0 &&  //FSX.Xが常駐している
   361:                 MainMemory.mmrRls (0x0938) == sccFSXMouseHook) {  //マウス受信データ処理ルーチンがFSX.Xを指している。SX-Windowが動作中
   362:               on = MainMemory.mmrRws (sccFSXMouseWork + 0x2e) == 0 ? 1 : 0;  //SX-Windowのマウスカーソルの表示状態。Obscureのときは表示されているとみなす
   363:               int xy = MainMemory.mmrRls (sccFSXMouseWork + 0x0a);
   364:               dx = (xy >> 16) - CRTC.crtR10TxXPort;  //SX-Windowのマウスカーソルの見かけのX座標
   365:               dy = (short) xy - CRTC.crtR11TxYPort;  //SX-Windowのマウスカーソルの見かけのY座標
   366:               coeff = MainMemory.mmrRwz (sccFSXMouseWork + 0x04);  //ポインタの移動量。係数*256
   367:             } else {  //SX-Windowが動作中ではない
   368:               on = MainMemory.mmrRbs (0x0aa2);  //IOCSのマウスカーソルの表示状態
   369:               int xy = MainMemory.mmrRls (0x0ace);
   370:               dx = xy >> 16;  //IOCSのマウスカーソルのX座標
   371:               dy = (short) xy;  //IOCSのマウスカーソルのY座標
   372:               if (Mouse.musFollowScrollOn) {
   373:                 dx -= CRTC.crtR10TxXPort;
   374:                 dy -= CRTC.crtR11TxYPort;
   375:               }
   376:             }
   377:           } else {  //MMUあり
   378:             if (SCC_FSX_MOUSE &&
   379:                 sccFSXMouseHook != 0 &&  //FSX.Xが常駐している
   380:                 MC68060.mmuPeekLongData (0x0938, 1) == sccFSXMouseHook) {  //マウス受信データ処理ルーチンがFSX.Xを指している。SX-Windowが動作中
   381:               on = MC68060.mmuPeekWordSignData (sccFSXMouseWork + 0x2e, 1) == 0 ? 1 : 0;  //SX-Windowのマウスカーソルの表示状態。Obscureのときは表示されているとみなす
   382:               int xy = MC68060.mmuPeekLongData (sccFSXMouseWork + 0x0a, 1);
   383:               dx = (xy >> 16) - CRTC.crtR10TxXPort;  //SX-Windowのマウスカーソルの見かけのX座標
   384:               dy = (short) xy - CRTC.crtR11TxYPort;  //SX-Windowのマウスカーソルの見かけのY座標
   385:               coeff = MC68060.mmuPeekWordZeroData (sccFSXMouseWork + 0x04, 1);  //ポインタの移動量。係数*256
   386:             } else {  //SX-Windowが動作中ではない
   387:               on = MC68060.mmuPeekByteSignData (0x0aa2, 1);  //IOCSのマウスカーソルの表示状態
   388:               int xy = MC68060.mmuPeekLongData (0x0ace, 1);
   389:               dx = xy >> 16;  //IOCSのマウスカーソルのX座標
   390:               dy = (short) xy;  //IOCSのマウスカーソルのY座標
   391:               if (Mouse.musFollowScrollOn) {
   392:                 dx -= CRTC.crtR10TxXPort;
   393:                 dy -= CRTC.crtR11TxYPort;
   394:               }
   395:             }
   396:           }
   397:           dx = Mouse.musScreenX - dx;  //X方向の移動量
   398:           dy = Mouse.musScreenY - dy;  //Y方向の移動量
   399:           if (Mouse.musEdgeAccelerationOn) {  //縁部加速を行う
   400:             final int range = 10;  //加速領域の幅
   401:             final int speed = 10;  //移動速度
   402:             if (Mouse.musScreenX < range) {
   403:               dx = -speed;  //左へ
   404:             } else if (XEiJ.pnlScreenWidth - range <= Mouse.musScreenX) {
   405:               dx = speed;  //右へ
   406:             }
   407:             if (Mouse.musScreenY < range) {
   408:               dy = -speed;  //上へ
   409:             } else if (XEiJ.pnlScreenHeight - range <= Mouse.musScreenY) {
   410:               dy = speed;  //下へ
   411:             }
   412:           }
   413:           if (on != 0) {  //X68000のマウスカーソルが表示されている
   414:             //Mouse.musHide ();
   415:             if (Mouse.musCursorNumber != 0 && Mouse.musCursorAvailable) {
   416:               Mouse.musCursorNumber = 0;
   417:               XEiJ.pnlPanel.setCursor (Mouse.musCursorArray[0]);  //ホストのマウスカーソルを消す
   418:             }
   419:           } else {  //X68000のマウスカーソルが表示されていない
   420:             //Mouse.musShow ();
   421:             if (Mouse.musCursorNumber != 1 && Mouse.musCursorAvailable) {
   422:               Mouse.musCursorNumber = 1;
   423:               XEiJ.pnlPanel.setCursor (Mouse.musCursorArray[1]);  //ホストのマウスカーソルを表示する
   424:             }
   425:           }
   426:           if (coeff != 256 && coeff != 0) {
   427:             //SX-Windowのポインタの移動量の補正
   428:             dx = (dx << 8) / coeff;
   429:             dy = (dy << 8) / coeff;
   430:           }
   431:           //  Mouse.MUS_DEACCELERATION_TABLEの値が127を越えることはないのでシームレスでオーバーフローフラグがセットされることはない
   432:           //  rbzで返すので負数のときのゼロ拡張を忘れないこと
   433:           scc0bData1 = (dx == 0 ? 0 : dx >= 0 ?
   434:                         Mouse.MUS_DEACCELERATION_TABLE[Math.min (1024, dx)] :
   435:                         -Mouse.MUS_DEACCELERATION_TABLE[Math.min (1024, -dx)] & 0xff);
   436:           scc0bData2 = (dy == 0 ? 0 : dy >= 0 ?
   437:                         Mouse.MUS_DEACCELERATION_TABLE[Math.min (1024, dy)] :
   438:                         -Mouse.MUS_DEACCELERATION_TABLE[Math.min (1024, -dy)] & 0xff);
   439:         } else if (!XEiJ.frmIsActive) {  //エクスクルーシブだがフォーカスがない
   440:           //Mouse.musShow ();
   441:           if (Mouse.musCursorNumber != 1 && Mouse.musCursorAvailable) {
   442:             Mouse.musCursorNumber = 1;
   443:             XEiJ.pnlPanel.setCursor (Mouse.musCursorArray[1]);  //ホストのマウスカーソルを表示する
   444:           }
   445:           scc0bData1 = scc0bData2 = 0;
   446:           Mouse.musExclusiveStart = true;  //フォーカスを得たときエクスクルーシブに切り替えた直後のように振る舞う
   447:         } else {  //エクスクルーシブ
   448:           //Mouse.musHide ();
   449:           if (Mouse.musCursorNumber != 0 && Mouse.musCursorAvailable) {
   450:             Mouse.musCursorNumber = 0;
   451:             XEiJ.pnlPanel.setCursor (Mouse.musCursorArray[0]);  //ホストのマウスカーソルを消す
   452:           }
   453:           int dx, dy;
   454:           if (XEiJ.PNL_ROTATION_ON) {
   455:             int ox = (XEiJ.pnlScreenX1 + XEiJ.pnlScreenX2) >> 1;  //左スクリーンの中央のパネル座標
   456:             int oy = (XEiJ.pnlScreenY1 + XEiJ.pnlScreenY2) >> 1;
   457:             int tx = Mouse.musPanelX - ox;  //マウスカーソルの左スクリーンの中央からのパネル方向ベクトル
   458:             int ty = Mouse.musPanelY - oy;
   459:             XEiJ.rbtRobot.mouseMove (XEiJ.pnlGlobalX + ox,
   460:                                      XEiJ.pnlGlobalY + oy);  //マウスカーソルを左スクリーンの中央に戻す
   461:             dx = (int) Math.round (XEiJ.pnlInverseL00 * (double) tx + XEiJ.pnlInverseL01 * (double) ty);  //パネル方向ベクトルをスクリーン方向ベクトルに変換する
   462:             dy = (int) Math.round (XEiJ.pnlInverseL10 * (double) tx + XEiJ.pnlInverseL11 * (double) ty);
   463:           } else {
   464:             int ox = XEiJ.pnlScreenX1 + (XEiJ.pnlZoomWidth >> 1);  //画面の中央
   465:             int oy = XEiJ.pnlScreenY1 + (XEiJ.pnlZoomHeight >> 1);
   466:             XEiJ.rbtRobot.mouseMove (XEiJ.pnlGlobalX + ox, XEiJ.pnlGlobalY + oy);  //マウスカーソルを画面の中央に戻す
   467:             dx = Mouse.musPanelX - ox;
   468:             dy = Mouse.musPanelY - oy;
   469:           }
   470:           if (Mouse.musExclusiveStart) {  //エクスクルーシブに切り替えた直後
   471:             //エクスクルーシブに切り替えた直後の1回だけ相対位置を無視する
   472:             //  エクスクルーシブに切り替える直前にマウスカーソルが画面の中央から離れていると切り替えた瞬間に画面の端に飛んでしまう
   473:             dx = 0;
   474:             dy = 0;
   475:             Mouse.musExclusiveStart = false;
   476:           }
   477:           //  上下左右のレスポンスが非対称になると気持ち悪いので冗長に書く
   478:           //  rbzで返すので負数のときのゼロ拡張を忘れないこと
   479:           if (dx != 0) {
   480:             if (dx >= 0) {
   481:               //dx = dx * Mouse.musSpeedRatioX + 32768 >> 16;
   482:               dx = dx * Mouse.musSpeedRatioX >> 16;
   483:               if (127 < dx) {
   484:                 d |= 0x10;
   485:                 dx = 127;
   486:               }
   487:             } else {
   488:               //dx = -(-dx * Mouse.musSpeedRatioX + 32768 >> 16);
   489:               dx = -(-dx * Mouse.musSpeedRatioX >> 16);
   490:               if (dx < -128) {
   491:                 d |= 0x20;
   492:                 dx = -128;
   493:               }
   494:               dx &= 0xff;
   495:             }
   496:           }
   497:           if (dy != 0) {
   498:             if (dy >= 0) {
   499:               //dy = dy * Mouse.musSpeedRatioY + 32768 >> 16;
   500:               dy = dy * Mouse.musSpeedRatioY >> 16;
   501:               if (127 < dy) {
   502:                 d |= 0x40;
   503:                 dy = 127;
   504:               }
   505:             } else {
   506:               //dy = -(-dy * Mouse.musSpeedRatioY + 32768 >> 16);
   507:               dy = -(-dy * Mouse.musSpeedRatioY >> 16);
   508:               if (dy < -128) {
   509:                 d |= 0x80;
   510:                 dy = -128;
   511:               }
   512:               dy &= 0xff;
   513:             }
   514:           }
   515:           scc0bData1 = dx;
   516:           scc0bData2 = dy;
   517:         }  //if シームレス else エクスクルーシブ
   518:         scc0bInputCounter = 1;
   519:       } else if (scc0bInputCounter == 1) {  //2バイト目
   520:         d = scc0bData1;
   521:         if (peek) {
   522:           break;
   523:         }
   524:         scc0bInputCounter = 2;
   525:       } else if (scc0bInputCounter == 2) {  //3バイト目
   526:         d = scc0bData2;
   527:         if (peek) {
   528:           break;
   529:         }
   530:         scc0bInputCounter = 3;
   531:       }
   532:       break;
   533:       //------------------------------------------------
   534:     case SCC_1A_COMMAND & 7:  //ポート1Aコマンド読み出し
   535:       switch (scc1aRegisterNumber) {
   536:       case 0:  //RR0
   537:         //  bit7  Break/Abort
   538:         //  bit6  Tx Underrun/EOM
   539:         //  bit5  0=/CTS is High  相手が受信バッファに余裕がないから送るのやめてと言っている
   540:         //        1=/CTS is Low   相手が受信バッファに余裕があるから送っていいよと言っている
   541:         //  bit4  Sync/Hunt
   542:         //  bit3  DCD
   543:         //  bit2  Tx Buffer Empty(1=空)
   544:         //  bit1  Zero Count
   545:         //  bit0  Rx Character Available
   546:         d = RS232CTerminal.trmAUXReadCommand ();
   547:         break;
   548:       case 2:  //RR2
   549:         //非修飾割り込みベクタ
   550:         //  ポート1AのRR2はWR2に設定したベクタをそのまま返す
   551:         d = sccInterruptVector;
   552:         break;
   553:       case 3:  //RR3
   554:         //割り込みペンディング
   555:         //  RR3リクエストからインサービスまでの間セットされている
   556:         //  許可されていない割り込みのビットはセットされない
   557:         d = scc1aReceiveRR3 | scc1aSendRR3 | scc0bReceiveRR3;
   558:         break;
   559:       case 12:  //RR12
   560:         d = scc1aBaudRateGen & 0xff;
   561:         break;
   562:       case 13:  //RR13
   563:         d = scc1aBaudRateGen >> 8 & 0xff;
   564:         break;
   565:       default:
   566:         if (SCC_DEBUG_ON && sccDebugOn != 0) {
   567:           System.out.println ("unimplemented register");
   568:         }
   569:       }
   570:       if (peek) {
   571:         break;
   572:       }
   573:       scc1aRegisterNumber = 0;
   574:       break;
   575:       //------------------------------------------------
   576:     case SCC_1A_DATA & 7:  //ポート1Aデータ読み出し(RS-232C受信)
   577:       d = RS232CTerminal.trmAUXReadData ();
   578:       break;
   579:       //------------------------------------------------
   580:     default:
   581:       d = 0xff;
   582:     }
   583:     if (SCC_DEBUG_ON && ((a & 4) == 0 ? (sccDebugOn & 1) != 0 : (sccDebugOn & 2) != 0)) {
   584:       System.out.printf ("%08x sccRead(0x%08x)=0x%02x\n", XEiJ.regPC0, a, d);
   585:     }
   586:     return d;
   587:   }  //sccReadByte
   588: 
   589: 
   590: 
   591:   //sccWriteByte (a, d)
   592:   //  ライトバイト
   593:   public static void sccWriteByte (int a, int d) {
   594:     XEiJ.mpuClockTime += XEiJ.busWaitTime.scc;
   595:     d &= 0xff;
   596:     if (SCC_DEBUG_ON && ((a & 4) == 0 ? (sccDebugOn & 1) != 0 : (sccDebugOn & 2) != 0)) {
   597:       System.out.printf ("%08x sccWrite(0x%08x,0x%02x)\n", XEiJ.regPC0, a, d);
   598:     }
   599:     switch (a & 7) {
   600:       //------------------------------------------------
   601:     case SCC_0B_COMMAND & 7:  //ポート0Bコマンド書き込み
   602:       switch (scc0bRegisterNumber) {
   603:       case 0:  //WR0
   604:         if ((d & 0xf0) == 0) {  //レジスタ選択
   605:           scc0bRegisterNumber = d;
   606:         } else if (d == 0x38) {  //IUSリセット。割り込み処理が終了し、次の割り込みを受け付ける
   607:           if (scc0bReceiveRR3 != 0) {
   608:             scc0bReceiveRR3 = 0;
   609:             if (scc0bInputCounter < 3) {  //3バイト受信するまで割り込み要求を続ける
   610:               if (scc0bReceiveMask != 0) {
   611:                 scc0bReceiveRR3 = SCC_0B_RECEIVE_MASK;
   612:                 scc0bReceiveRequest = SCC_0B_RECEIVE_MASK;
   613:                 XEiJ.mpuIRR |= XEiJ.MPU_SCC_INTERRUPT_MASK;
   614:               }
   615:             }
   616:           }
   617:         } else if (d == 0x10) {  //ステータス割り込みリセット
   618:         } else if (d == 0x30) {  //エラーリセット
   619:         } else if (d == 0x80) {  //送信CRCジェネレータリセット
   620:         } else {
   621:           if (SCC_DEBUG_ON && sccDebugOn != 0) {
   622:             System.out.println ("unimplemented command");
   623:           }
   624:         }
   625:         return;
   626:       case 1:  //WR1
   627:         scc0bReceiveMask = (d & 0x18) != 0 ? SCC_0B_RECEIVE_MASK : 0;
   628:         if ((d & 0xec) != 0x00) {
   629:           if (SCC_DEBUG_ON && sccDebugOn != 0) {
   630:             System.out.println ("unimplemented interrupt mode");
   631:           }
   632:         }
   633:         break;
   634:       case 2:  //WR2
   635:         sccInterruptVector = d;  //割り込みベクタ
   636:         if (SCC_DEBUG_ON && sccDebugOn != 0) {
   637:           System.out.printf ("sccInterruptVector=0x%02x\n", sccInterruptVector);
   638:         }
   639:         sccUpdateVector ();
   640:         break;
   641:       case 3:  //WR3
   642:         if (d == 0xc0) {  //受信禁止
   643:         } else if (d == 0xc1) {  //受信許可
   644:         } else {
   645:           if (SCC_DEBUG_ON && sccDebugOn != 0) {
   646:             System.out.println ("unimplemented receiver configuration");
   647:           }
   648:         }
   649:         break;
   650:       case 4:  //WR4
   651:         break;
   652:       case 5:  //WR5
   653:         //  0x80  DTR
   654:         //  0x60  ビット長(0x00=5bit,0x20=7bit,0x40=6bit,0x60=8bit)
   655:         //  0x10  ブレーク
   656:         //  0x08  送信許可
   657:         //  0x04  CRC-16
   658:         //  0x02  RTS
   659:         //  0x01  送信CRC
   660:         {
   661:           int rts = d >> 1 & 1;
   662:           if ((~scc0bRts & rts) != 0) {  //RTS=0→1。MSCTRL=H→Lとなってマウスに送信要求が出される
   663:             scc0bInputCounter = 0;
   664:             //マウスデータ受信開始
   665:             if (scc0bReceiveMask != 0) {
   666:               scc0bReceiveRR3 = SCC_0B_RECEIVE_MASK;
   667:               scc0bReceiveRequest = SCC_0B_RECEIVE_MASK;
   668:               XEiJ.mpuIRR |= XEiJ.MPU_SCC_INTERRUPT_MASK;
   669:             }
   670:           }
   671:           scc0bRts = rts;
   672:           if ((d & 0x75) == 0x60) {
   673:           } else {
   674:             if (SCC_DEBUG_ON && sccDebugOn != 0) {
   675:               System.out.println ("unimplemented sender configuration");
   676:             }
   677:           }
   678:         }
   679:         break;
   680:       case 6:  //WR6
   681:         break;
   682:       case 7:  //WR7
   683:         break;
   684:       case 9:  //WR9
   685:         if ((d & 0xc0) == 0x40) {  //ポート0Bリセット
   686:           scc0bRts = 0;
   687:         } else if ((d & 0xc0) == 0x80) {  //ポート1Aリセット
   688:         } else if ((d & 0xc0) == 0xc0) {  //ハードウェアリセット
   689:           scc0bRts = 0;
   690:         }
   691:         sccVectorInclude = d & 0x11;
   692:         if (SCC_DEBUG_ON && sccDebugOn != 0) {
   693:           System.out.printf ("sccVectorInclude=0x%02x\n", sccVectorInclude);
   694:         }
   695:         sccUpdateVector ();
   696:         if ((d & 0x26) != 0x00) {
   697:           if (SCC_DEBUG_ON && sccDebugOn != 0) {
   698:             System.out.println ("unimplemented interrupt configuration");
   699:           }
   700:         }
   701:         break;
   702:       case 10:  //WR10
   703:         if (d == 0x00) {
   704:         } else {
   705:           if (SCC_DEBUG_ON && sccDebugOn != 0) {
   706:             System.out.println ("unimplemented SDLC configuration");
   707:           }
   708:         }
   709:         break;
   710:       case 11:  //WR11
   711:         if (d == 0x50) {  //TRxCは入力
   712:         } else if (d == 0x56) {  //TRxCからボーレートジェネレータを出力
   713:         } else {
   714:           if (SCC_DEBUG_ON && sccDebugOn != 0) {
   715:             System.out.println ("unimplemented clock control");
   716:           }
   717:         }
   718:         break;
   719:       case 12:  //WR12
   720:         scc0bBaudRateGen = (scc0bBaudRateGen & ~0xff) | d;
   721:         break;
   722:       case 13:  //WR13
   723:         scc0bBaudRateGen = d << 8 | (scc0bBaudRateGen & 0xff);
   724:         break;
   725:       case 14:  //WR14
   726:         if (d == 0x02) {  //ボーレートジェネレータ停止
   727:         } else if (d == 0x03) {  //ボーレートジェネレータ動作
   728:         } else {
   729:           if (SCC_DEBUG_ON && sccDebugOn != 0) {
   730:             System.out.println ("unimplemented DPLL configuration");
   731:           }
   732:         }
   733:         break;
   734:       case 15:  //WR15
   735:         if (d == 0x00) {
   736:         } else if (d == 0x80) {
   737:         } else if (d == 0x88) {
   738:         } else {
   739:           if (SCC_DEBUG_ON && sccDebugOn != 0) {
   740:             System.out.println ("unimplemented status interrupt configuration");
   741:           }
   742:         }
   743:         break;
   744:       default:
   745:         if (SCC_DEBUG_ON && sccDebugOn != 0) {
   746:           System.out.println ("unimplemented register");
   747:         }
   748:       }
   749:       scc0bRegisterNumber = 0;
   750:       return;
   751:       //------------------------------------------------
   752:     case SCC_0B_DATA & 7:  //ポート0Bデータ書き込み(マウス送信)
   753:       return;
   754:       //------------------------------------------------
   755:     case SCC_1A_COMMAND & 7:  //ポート1Aコマンド書き込み
   756:       switch (scc1aRegisterNumber) {
   757:       case 0:  //WR0
   758:         if ((d & 0xf0) == 0) {  //レジスタ選択
   759:           scc1aRegisterNumber = d;
   760:         } else if (d == 0x38) {  //IUSリセット。割り込み処理が終了し、次の割り込みを受け付ける
   761:           scc1aReceiveRR3 = 0;
   762:         } else if (d == 0x10) {  //ステータス割り込みリセット
   763:         } else if (d == 0x30) {  //エラーリセット
   764:         } else if (d == 0x80) {  //送信CRCジェネレータリセット
   765:         } else {
   766:           if (SCC_DEBUG_ON && sccDebugOn != 0) {
   767:             System.out.println ("unimplemented command");
   768:           }
   769:         }
   770:         return;
   771:       case 1:  //WR1
   772:         //  Z85C30UM 5-4
   773:         //  WR1
   774:         //    bit7    WAIT/DMA Request Enable
   775:         //    bit6    /WAIT/DMA Request Function
   776:         //    bit5    WAIT/DMA Request On Receive/Transmit
   777:         //    bit4-3  00=Rx Int Disable
   778:         //            01=Rx Int On First Character or Special Condition
   779:         //            10=Int On All Rx Characters or Special Condition
   780:         //            11=Rx Int On Special Condition Only
   781:         //    bit2    Parity is Special Condition
   782:         //    bit1    Tx Int Enable
   783:         //    bit0    Ext Int Enable
   784:         scc1aReceiveMask = (d & 0x18) != 0 ? SCC_1A_RECEIVE_MASK : 0;  //Rx Int Enable
   785:         scc1aSendMask = (d & 0x02) != 0 ? SCC_1A_SEND_MASK : 0;  //Tx Int Enable
   786:         if ((d & 0xe3) != 0x00) {
   787:           if (SCC_DEBUG_ON && sccDebugOn != 0) {
   788:             System.out.println ("unimplemented interrupt mode");
   789:           }
   790:         }
   791:         break;
   792:       case 2:  //WR2
   793:         sccInterruptVector = d;  //割り込みベクタ
   794:         if (SCC_DEBUG_ON && sccDebugOn != 0) {
   795:           System.out.printf ("sccInterruptVector=0x%02x\n", sccInterruptVector);
   796:         }
   797:         sccUpdateVector ();
   798:         break;
   799:       case 3:  //WR3
   800:         //  Z85C30UM 5-7
   801:         //  WR3
   802:         //    bit7-6  00=Rx 5 Bits/Character
   803:         //            01=Rx 7 Bits/Character
   804:         //            10=Rx 6 Bits/Character
   805:         //            10=Rx 8 Bits/Character
   806:         //    bit5    1=Auto Enables
   807:         //    bit4    1=Enter Hunt Mode
   808:         //    bit3    1=Rx CRC Enable
   809:         //    bit2    1=Address Search Mode (SDLC)
   810:         //    bit1    1=Sync Characster Load Inhibit
   811:         //    bit0    1=Rx Enable
   812:         if ((d & 0x3e) == 0x00) {
   813:           scc1aRxBits = d >> 6;
   814:         } else {
   815:           if (SCC_DEBUG_ON && sccDebugOn != 0) {
   816:             System.out.println ("unimplemented receiver configuration");
   817:           }
   818:         }
   819:         break;
   820:       case 4:  //WR4
   821:         //  Z85C30UM 5-8
   822:         //  WR4
   823:         //    bit7-6  00=X1 Clock Mode
   824:         //            01=X16 Clock Mode
   825:         //            10=X32 Clock Mode
   826:         //            11=X64 Clock Mode
   827:         //    bit5-4  00=8-Bit Sync Character
   828:         //            01=16-Bit Sync Character
   829:         //            10=SDLC Mode (01111110 Flag)
   830:         //            11=External Sync Mode
   831:         //    bit3-2  00=Sync Modes Enable
   832:         //            01=1 Stop Bit/Character
   833:         //            10=1 1/2 Stop Bits/Character
   834:         //            11=2 Stop Bits/Character
   835:         //    bit1    0=Parity ODD
   836:         //            1=Parity EVEN
   837:         //    bit0    1=Parity Enable
   838:         scc1aClockModeShift = d >> 6 == 0 ? 0 : (d >> 6) + 3;  //0=2^0,1=2^4,2=2^5,3=2^6
   839:         scc1aStop = d >> 2 & 3;
   840:         scc1aParity = d & 3;
   841:         break;
   842:       case 5:  //WR5
   843:         //  Z85C30UM 5-9
   844:         //  WR5
   845:         //    bit7    0=/DTR is High
   846:         //            1=/DTR is Low(準備完了)
   847:         //    bit6-5  00=Tx 5 Bits(Or Less)/Character
   848:         //            01=Tx 7 Bits/Character
   849:         //            10=Tx 6 Bits/Character
   850:         //            11=Tx 8 Bits/Character
   851:         //    bit4    1=Send Break
   852:         //    bit3    1=Tx Enable
   853:         //    bit2    0=SDLC
   854:         //            1=CRC-16
   855:         //    bit1    0=/RTS is High  自分が受信バッファに余裕がない(3/4)から送るのやめてと言う
   856:         //            1=/RTS is Low   自分が受信バッファに余裕がある(1/4)から送っていいよと言う
   857:         //    bit0    1=Tx CRC Enable
   858:         if ((d & 0x15) == 0x00) {
   859:           RS232CTerminal.trmAUXSetNotReceiving ((d & 0x02) == 0);
   860:           scc1aTxBits = d >> 5 & 3;
   861:           scc1aTxEnable = d >> 3 & 1;
   862:         } else {
   863:           if (SCC_DEBUG_ON && sccDebugOn != 0) {
   864:             System.out.println ("unimplemented sender configuration");
   865:           }
   866:         }
   867:         break;
   868:       case 6:  //WR6
   869:         break;
   870:       case 7:  //WR7
   871:         break;
   872:       case 9:  //WR9
   873:         if ((d & 0xc0) == 0x40) {  //ポート0Bリセット
   874:           scc0bRts = 0;
   875:         } else if ((d & 0xc0) == 0x80) {  //ポート1Aリセット
   876:           scc1aBRGEnable = 0;
   877:           scc1aRxEnable = 0;
   878:           scc1aTxEnable = 0;
   879:           RS232CTerminal.trmAUXReset ();
   880:         } else if ((d & 0xc0) == 0xc0) {  //ハードウェアリセット
   881:           scc0bRts = 0;
   882:           scc1aBRGEnable = 0;
   883:           scc1aRxEnable = 0;
   884:           scc1aTxEnable = 0;
   885:           RS232CTerminal.trmAUXReset ();
   886:         }
   887:         sccVectorInclude = d & 0x11;
   888:         if (SCC_DEBUG_ON && sccDebugOn != 0) {
   889:           System.out.printf ("sccVectorInclude=0x%02x\n", sccVectorInclude);
   890:         }
   891:         sccUpdateVector ();
   892:         if ((d & 0x2e) != 0x08) {
   893:           if (SCC_DEBUG_ON && sccDebugOn != 0) {
   894:             System.out.println ("unimplemented interrupt configuration");
   895:           }
   896:         }
   897:         break;
   898:       case 10:  //WR10
   899:         if (d == 0x00) {
   900:         } else {
   901:           if (SCC_DEBUG_ON && sccDebugOn != 0) {
   902:             System.out.println ("unimplemented SDLC configuration");
   903:           }
   904:         }
   905:         break;
   906:       case 11:  //WR11
   907:         if (d == 0x50) {  //TRxCは入力
   908:         } else if (d == 0x56) {  //TRxCからボーレートジェネレータを出力
   909:         } else {
   910:           if (SCC_DEBUG_ON && sccDebugOn != 0) {
   911:             System.out.println ("unimplemented clock control");
   912:           }
   913:         }
   914:         break;
   915:       case 12:  //WR12
   916:         //  Z85C30UM 5-18
   917:         //  WR12
   918:         //    bit7-0  Lower Byte Of Time Constant
   919:         //
   920:         //                                   5000000
   921:         //      WR13-WR12                Clock Frequency
   922:         //    Time Constant = -------------------------------------- - 2
   923:         //                    2 x (Desired Rate) x (BR Clock Period)
   924:         //                                            WR4 bit7-6
   925:         //
   926:         //    5000000/(2*(0+2)*16)=78125  76800*1.017
   927:         //    5000000/(2*(2+2)*16)=39062.5  38400*1.017
   928:         //    5000000/(2*(3+2)*16)=31250
   929:         //    5000000/(2*(6+2)*16)=19531.25  19200*1.017
   930:         //    5000000/(2*(14+2)*16)=9765.625  9600*1.017
   931:         //    5000000/(2*(30+2)*16)=4882.8125  4800*1.017
   932:         scc1aBaudRateGen = (scc1aBaudRateGen & ~0xff) | d;
   933:         break;
   934:       case 13:  //WR13
   935:         //  Z85C30UM 5-19
   936:         //  WR13
   937:         //    bit7-0  Upper Byte Of Time Constant
   938:         scc1aBaudRateGen = d << 8 | (scc1aBaudRateGen & 0xff);
   939:         break;
   940:       case 14:  //WR14
   941:         //  Z85C30UM 5-19
   942:         //  WR14
   943:         //    bit7-5  000=Null Command
   944:         //            001=Enter Search Mode
   945:         //            010=Reset Missing Clock
   946:         //            011=Disable DPLL
   947:         //            100=Set Source = BR Generator
   948:         //            101=Set Source = /RTxC
   949:         //            110=Set FM Mode
   950:         //            111=Set NRZI Mode
   951:         //    bit4    1=Local Loopback
   952:         //    bit3    1=Auto Echo
   953:         //    bit2    1=/DTR/Request Function
   954:         //    bit1    BR Generator Source
   955:         //            0=/RTxC pin or XTAL oscillator
   956:         //            1=SCC's PCLK input
   957:         //    bit0    1=BR Generator Enable
   958:         if ((d & 0xfe) == 0x02) {
   959:           scc1aBRGEnable = d & 1;
   960:           if (scc1aBRGEnable != 0) {  //1が書き込まれたとき
   961:             //本来は、ボーレートジェネレータのカウンタの初期値はゼロカウントまたはリセットでロードされる
   962:             //一般的に、
   963:             //動作間隔を決めるカウンタの初期値が上位と下位に分かれていて、ゼロカウントで初期値がロードされる仕組みのとき、
   964:             //上位または下位のどちらか一方を書き換えた直後にゼロカウントになると予期しない初期値がロードされてしまうので、
   965:             //カウンタを止めてから初期値を書き換えるのが作法である
   966:             //それならばボーレートジェネレータの再開をボーレート変更完了の合図として使えるはずだが、
   967:             //tmsio.xとbsio.xがカウンタを止めずにボーレートを変更してしまっているため、その方法が使えない
   968:             //ここではBaud Rate Generator Enableに1が書き込まれたら必ず設定を更新する
   969:             RS232CTerminal.trmReflectSettings (1);
   970:           }
   971:         } else {
   972:           if (SCC_DEBUG_ON && sccDebugOn != 0) {
   973:             System.out.println ("unimplemented DPLL configuration");
   974:           }
   975:         }
   976:         break;
   977:       case 15:  //WR15
   978:         //  Z85C30UM 5-20
   979:         //  WR15
   980:         //    bit7  Break/Abort IE
   981:         //    bit6  Tx Underrun/EOM IE
   982:         //    bit5  CTS IE
   983:         //    bit4  Sync/Hunt IE
   984:         //    bit3  DCD IE
   985:         //    bit2  SDLC FIFO Enable (Reserved on NMOS)
   986:         //    bit1  Zero Count IE
   987:         //    bit0  WR7' SDLC Feature Enable (Reserved on NMOS/CMOS)
   988:         if (d == 0x00) {
   989:         } else if (d == 0x80) {
   990:         } else if (d == 0x88) {
   991:         } else {
   992:           if (SCC_DEBUG_ON && sccDebugOn != 0) {
   993:             System.out.println ("unimplemented status interrupt configuration");
   994:           }
   995:         }
   996:         break;
   997:       default:
   998:         if (SCC_DEBUG_ON && sccDebugOn != 0) {
   999:           System.out.println ("unimplemented register");
  1000:         }
  1001:       }
  1002:       scc1aRegisterNumber = 0;
  1003:       return;
  1004:       //------------------------------------------------
  1005:     case SCC_1A_DATA & 7:  //ポート1Aデータ書き込み(RS-232C送信)
  1006:       RS232CTerminal.trmAUXWriteData (d);
  1007:       return;
  1008:       //------------------------------------------------
  1009:     default:
  1010:       ;
  1011:     }
  1012:   }  //sccWriteByte
  1013: 
  1014: 
  1015: 
  1016: }  //class Z8530
  1017: 
  1018: 
  1019: