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