示例#1
0
        public byte size; /// 読み出しバイト数

        #endregion Fields

        #region Methods

        public CommandStruct Clone()
        {
            CommandStruct image = new CommandStruct();

            image.Cmd = this.Cmd;
            image.Address = this.Address;
            image.size = this.size;

            if (this.Data != null)
            {
                image.Data = new ushort[this.Data.Length];
                for (int i = 0; i < Data.Length; i++)
                {
                    image.Data[i] = this.Data[i];
                }
            }

            return image;
        }
        /// <summary>
        /// コマンドを実行します。
        /// </summary>
        /// <param name="cmd"></param>
        protected void execCommand(CommandStruct cmd, CommandStruct cmd2 = null)
        {
            CommandStruct res = new CommandStruct();

            // 共用メモリの更新
            switch (cmd.Cmd)
            {
                case 'r' : /* 読み込み要求Ack処理 */
                case 'W':  /* 書き込み要求処理 */
                    // 機械メモリに書き込み
                    Array.Copy(cmd.Data, 0, machineMem, cmd.Address, cmd.size);
                    Array.Copy(cmd.Data, 0, pcMem, cmd.Address, cmd.size);

                    // メモリ書き換えイベント発生
                    if (memoryDataChange != null)
                    {
                        MemChangeEventArgs e = new MemChangeEventArgs();
                        e.Address = sendAckCommand.Address;
                        e.Count = sendAckCommand.size;

                        ctl.Invoke(memoryDataChange, new object[] { this, e });
                        ts.TraceInformation("メモリ書き換えイベント");
                    }
                    ts.TraceInformation(cmd.ToString());

                    break;

                case 'w': /* 書き込み要求Ack処理 */
                    Array.Copy(pcMem, cmd2.Address, machineMem, cmd2.Address, cmd2.Data.Length);
                    cmd2.Cmd = 'w';
                    ts.TraceInformation(cmd2.ToString());
                    break;

                case 'R': /* 読み込み要求処理 */
                    ts.TraceInformation(cmd.ToString());
                    break;
            }
        }
示例#3
0
        /// <summary>
        /// バイトデータをデコードしてコマンドを識別します。
        /// デコードできない場合、または、チェックサムが異なる場合は、
        /// 例外が発生します。
        /// </summary>
        /// <param name="byteImage">コマンドデータ</param>
        /// <returns>コマンドイメージクラスを返却</returns>
        public static CommandStruct decodeCommand(byte []byteImage)
        {
            CommandStruct cmdImage = new CommandStruct();

            Debug.Assert(byteImage != null);

            // STBチェック
            if (byteImage[0] != STB)
            {
                throw new ArgumentException("STB異常");
            }

            // コマンド種別チェック
            char cmd = (char)byteImage[2];
            if (cmd != 'r' && cmd != 'R' &&
                cmd != 'w' && cmd != 'W')
            {
                throw new ArgumentException("コマンド異常");
            }

            // 受信バイト数とデータ数が合わない場合は、エラー
            if ((byteImage.Length - 4) != byteImage[1])
            {
                throw new ArgumentException("サイズ異常");
            }

            // ENBチェック
            if (byteImage.Last() != ENB)
            {
                throw new ArgumentException("ENB異常");
            }

            // データを取得
            cmdImage.Cmd = cmd;

            switch (cmd)
            {
                case 'R': /* 読み込み要求 */
                    {
                        cmdImage.Address = BitConverter.ToUInt16(byteImage, 3);

                        // チェックサムチェック
                        byte orgFcs = byteImage[6];
                        byte calcFcs = CalcChecksum(byteImage, 6);

                        // チェックサムエラー
                        if (orgFcs != calcFcs)
                        {
                            throw new ArgumentException("チェックサム異常(R)");
                        }

                        cmdImage.size = byteImage[5];
                    }
                    break;

                case 'w': /* 書き込みAck  */
                    {
                        // チェックサムチェック
                        byte orgFcs = byteImage[3];
                        byte calcFcs = CalcChecksum(byteImage, 3);

                        // チェックサムエラー
                        if (orgFcs != calcFcs)
                        {
                            throw new ArgumentException("チェックサム異常(w)");
                        }
                    }
                    break;

                case 'W': /* 書き込み要求 */
                case 'r': /* 読み込みAck */
                    {
                        cmdImage.Address = BitConverter.ToUInt16(byteImage, 3);

                        byte count = (byte)((byteImage[1] - 3) / 2);       /* データ数 */
                        int n = 5;                              /* データ開始位置  */

                        // バイト数をセット
                        cmdImage.size = count;

                        // チェックサムチェック
                        byte orgFcs = byteImage[byteImage.Length - 2];
                        byte calcFcs = CalcChecksum(byteImage, byteImage.Length - 2);

                        // チェックサムエラー
                        if (orgFcs != calcFcs)
                        {
                            throw new ArgumentException("チェックサム異常(W)");
                        }

                        // データ部分をデコード
                        cmdImage.Data = new ushort[count];
                        for (int i = 0; i < count; i++)
                        {
                            cmdImage.Data[i] = BitConverter.ToUInt16(byteImage, n);
                            n += 2;
                        }
                    }
                    break;
            }

            return cmdImage;
        }
示例#4
0
        /// <summary>
        /// 送ったコマンドに対応するAckかチェックします。
        /// </summary>
        /// <param name="sent"></param>
        /// <param name="ack"></param>
        /// <returns></returns>
        public static bool CheckAckCommand(CommandStruct sent, CommandStruct ack)
        {
            if (sent.Cmd.ToString().ToLower() != ack.Cmd.ToString())
            {
                return false;
            }

            return true;
        }
        /// <summary>
        /// 送信処理
        /// </summary>
        protected void sendTask()
        {
            switch (sendStatus)
            {
                case SendStatus.Ready : /* 送信予約待ち */
                    // 送信データありの場合
                    if (sendQueue.Count > 0)
                    {
                        // コマンドを取り出す
                        sendCommand = ((CommandStruct)sendQueue.Peek()).Clone();
                        isPolling = false;
                    }
                    // ポーリングタイムアウト発生
                    else if (isPolling)
                    {
                        sendCommand = new CommandStruct();
                        sendCommand.Cmd = 'R';
                        sendCommand.Address = 0x000A;
                        sendCommand.size = 1;
                    }
                    // それ以外
                    else {
                        return;
                    }

                    // リトライ回数を初期化
                    sendRetryCount = 0;
                    sendStatus = SendStatus.Sending;
                    break;

                case SendStatus.Sending :   /* 送信中 */
                    // コマンドをバイト列に変換する
                    byte[] cmd = sendCommand.Encode();

                    // コマンドを送信する。
                    try {
                        write(cmd, 0, cmd.Length);
                        sendTimer.Restart();
                        sendStatus = SendStatus.AckWaiting;
                    }
                    catch
                    {
                        ts.TraceInformation("Write処理失敗");
                        execSendRetry();
                        return;
                    }

                    break;

                case SendStatus.AckWaiting :    /* Ack待ち */
                    // タイムアウト発生の場合はリトライ処理を行う。
                    if (sendTimer.ElapsedMilliseconds > timeout)
                    {
                        ts.TraceInformation("Ack待ちタイムアウトが発生");
                        execSendRetry();
                        return;
                    }
                    break;

                case SendStatus.CommandProcessing :		/* コマンド実行 */
                    // 不正Ackの場合は、リトライを行う。
                    if (CommandUtil.CheckAckCommand(sendCommand, sendAckCommand) == false)
                    {
                        ts.TraceInformation("不正Ack受信");
                        execSendRetry();
                        return;
                    }

                    // Online状態でなければ、Onlineに切り替え
                    if (status != Status.Online)
                    {
                        // 切断理由をリセットする
                        comError = SystemConstants.COM_ERROR_NORMAL;

                        // StatusをOnlineにする。
                        status = Status.Online;

                        // 接続イベント発生
                        if (connstatusChange != null)
                        {
                            ConnStatusEventArgs e = new ConnStatusEventArgs();
                            e.EventCode = SystemConstants.EVENT_CONNECT;

                            ctl.Invoke(connstatusChange, new object[] { this, e });
                        }
                    }

                    // コマンド実行
                    execCommand(sendAckCommand, sendCommand);

                    // ポーリング通信の場合
                    if (isPolling) {
                        // ポーリング状態の解除
                        isPolling = false;
                    }
                    // キューからのデータ指示の場合
                    else {
                        // キューから1件データを削除する
                        sendQueue.Dequeue();
                    }

                    sendStatus = SendStatus.Ready;
                    break;
            }
        }
        /// <summary>
        /// Ack返信処理
        /// </summary>
        /// <param name="cmd"></param>
        protected void respondAck(CommandStruct cmd)
        {
            byte[] commandImage = null;

            // レスポンス処理
            if (cmd.Cmd == 'W')
            {
                commandImage = CommandUtil.EncodeCommand('w');
            }
            else if (cmd.Cmd == 'R')
            {
                ushort[] data = new ushort[cmd.size];

                //Array.Copy(machineMem, cmd.Address, data, 0, cmd.size);
                for (int i = 0; i < cmd.size; i++) {
                    data[i] = (ushort)machineMem[cmd.Address+i];
                }

                commandImage = CommandUtil.EncodeCommand('r', cmd.Address, data);
            }

            // データ送信
            try {
                write(commandImage, 0, commandImage.Length);
            }
            catch
            {
                ts.TraceInformation("Ack返信処理で例外発生");
            }
        }
        /// <summary>
        /// 受信処理
        /// </summary>
        protected void recvTask()
        {
            int bytesToRead = 0;

            switch (recvStatus)
            {
                case RecvStatus.Ready:

                    // バイト数チェック
                    try {
                        bytesToRead = serialPort.BytesToRead;
                        if (bytesToRead < 1)
                        {
                            return;
                        }

                        // ヘッダチェック
                        read(buffer, 0, 1);
                    }
                    catch {
                        ts.TraceInformation("readで例外発生");
                        return;
                    }

                    // 受信ヘッダチェック
                    if (CommandUtil.CheckHeader(buffer) == false)
                    {
                        ts.TraceInformation("受信ヘッダチェック異常");
                        return;
                    }
                    recvStatus = RecvStatus.HeaderReading;
                    break;

                case RecvStatus.HeaderReading :

                    // バイト数チェック
                    try {
                        bytesToRead = serialPort.BytesToRead;
                        if (bytesToRead < 1)
                        {
                            return;
                        }

                        // ヘッダチェック
                        read(buffer, 1, 1);
                    }
                    catch {
                        ts.TraceInformation("readで例外発生");
                        return;
                    }

                    recvStatus = RecvStatus.CommandProcessing;
                    break;

                case RecvStatus.CommandProcessing:
                    // 本文チェック
                    byte bodyLength = buffer[1];
                    try
                    {
                        // 本文の長さ以上のデータが読み込めれば続行する。
                        bytesToRead = serialPort.BytesToRead;
                        if (bytesToRead < bodyLength+2)
                        {
                            return;
                        }

                        // 本文読み込み
                        read(buffer, 2, bodyLength + 2);

                        // コマンドをデコードする
                        byte[] byteImage = new byte[bodyLength + 4];
                        Array.Copy(buffer, byteImage, bodyLength + 4);
                        recvCommand = CommandUtil.decodeCommand(byteImage);

                        // Ackを受信した場合
                        if (recvCommand.Cmd == 'w' ||
                            recvCommand.Cmd == 'r')
                        {
                            // 状態異常時
                            if (sendStatus != SendStatus.AckWaiting) {
                                ts.TraceInformation("AckWaiting以外でAckを受け取ったため無視します。");
                            }
                            // 正常時
                            else {
                                sendStatus = SendStatus.CommandProcessing;
                                sendAckCommand = recvCommand.Clone();
                            }
                        }
                        // Ack以外のコマンドを受信した場合
                        else {
                            // コマンド実行
                            execCommand(recvCommand);

                            // Ackの返信
                            respondAck(recvCommand);
                        }
                    }
                    catch
                    {
                        ts.TraceInformation("コマンド受信異常");
                    }

                    // シーケンスを終了
                    recvStatus = RecvStatus.Ready;
                    break;
            }
        }