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