Пример #1
0
        /*
         * static void Test()
         * {
         *      var ser = new SerialQueue("COM5", 250000);
         *      ser.Start();
         *
         *      Thread.Sleep(100);
         *
         *      MemoryStream buffer = new MemoryStream();
         *      int res = 0;
         *
         *      var cq = new KlipperSharp.command_queue();
         *      MemoryStream msg = new MemoryStream(16);
         *
         *      while (true)
         *      {
         *              KlipperSharp.queue_message qm;
         *              ser.pull(out qm);
         *
         *              msg.Position = 0;
         *              msg.SetLength(0);
         *              for (var i = SerialQueue.MESSAGE_HEADER_SIZE;
         *                      i < qm.len - SerialQueue.MESSAGE_TRAILER_SIZE; i++)
         *              {
         *                      msg.WriteByte(qm.msg[i]);
         *              }
         *              msg.Position = 0;
         *              var code = msg.ReadByte();
         *
         *              Console.WriteLine();
         *              Console.WriteLine($"MSG code:{code} {(qm.receive_time - qm.sent_time) * 1000}ms");
         *
         *              if (code == 0)
         *              {
         *                      Console.WriteLine("identify_response");
         *                      var offset = msg.parse(false);
         *                      var len = msg.ReadByte();
         *                      if (len > 0)
         *                      {
         *                              var buf = new byte[len];
         *                              var read = msg.Read(buf, 0, len);
         *                              if (read != len)
         *                                      Console.WriteLine("Error");
         *
         *                              buffer.Write(buf, 0, read);
         *                              res += read;
         *
         *                              Console.WriteLine($"Read bytes {buffer.Length}; {read}/{len}");
         *                      }
         *                      if (len < 40)
         *                      {
         *                              Console.WriteLine("download done");
         *                              res = -1;
         *
         *                              //var final = ZlibDecompress(buffer.ToArray());
         *                              //var jsonText = Encoding.ASCII.GetString(final);
         *                              //var xml = XDocument.Load(JsonReaderWriterFactory.CreateJsonReader(Encoding.ASCII.GetBytes(jsonText), new XmlDictionaryReaderQuotas()));
         *                              //xml.Save("identify.xml");
         *
         *                              //Assert.AreEqual(PROGMEM, buffer.ToArray());
         *
         *                              break;
         *                      }
         *              }
         *              else
         *              {
         *                      //Console.WriteLine($"{qm.receive_time * 1000} code:{code}");
         *              }
         *              if (res != -1)
         *              {
         *                      Console.WriteLine($"identify: get data {res}");
         *                      //{ 1, "identify offset=%u count=%c" }, uint32, byte
         *                      msg.Position = 0;
         *                      msg.SetLength(0);
         *                      msg.WriteByte(1);
         *                      msg.encode(res);
         *                      msg.encode(40);
         *                      ser.send(cq, msg.ToArray(), (int)msg.Length);
         *              }
         *
         *      }
         *      Console.ReadKey();
         * }
         */

        // Return a message read from the serial port (or wait for one if none
        // available)
        static void serialqueue_pull(out queue_message pqm)
        {
            //pthread_mutex_lock(&sq->lock);
            // Wait for message to be available
            while (receive_queue.Count == 0)
            {
                //if (pollreactor_is_exit(&sq->pr))
                //    goto exit;
                //sq->receive_waiting = 1;
                //int ret = pthread_cond_wait(&sq->cond, &sq->lock);
                //if (ret)
                //    report_errno("pthread_cond_wait", ret);
            }

            // Remove message from queue
            queue_message qm;

            receive_queue.TryDequeue(out qm);

            // Copy message
            pqm = qm;
            //pqm = new queue_message();
            //memcpy(pqm->msg, qm->msg, qm->len);
            //pqm.len = qm.len;
            //pqm.sent_time = qm.sent_time;
            //pqm.receive_time = qm.receive_time;
            //debug_queue_add(&sq->old_receive, qm);

            //pthread_mutex_unlock(&sq->lock);
            return;

            //exit:
            //	pqm = new queue_message();
            //	pqm.len = -1;
            //pthread_mutex_unlock(&sq->lock);
        }
Пример #2
0
        static void build_and_send_command(double eventtime)
        {
            queue_message output = new queue_message();

            output.len = MESSAGE_HEADER_SIZE;

            while (ready_bytes != 0)
            {
                // Find highest priority message (message with lowest req_clock)
                ulong         min_clock = MAX_CLOCK;
                command_queue cq        = null;
                queue_message qm        = new queue_message();
                foreach (var q in pending_queues)
                {
                    queue_message m;
                    if (!q.ready_queue.TryPeek(out m) && m.req_clock < min_clock)
                    {
                        min_clock = m.req_clock;
                        cq        = q;
                        qm        = m;
                    }
                }
                // Append message to outgoing command
                if (output.len + qm.len > MESSAGE_MAX - MESSAGE_TRAILER_SIZE)
                {
                    break;
                }
                cq.ready_queue.TryDequeue(out qm);
                if (cq.ready_queue.Count == 0 && cq.stalled_queue.Count == 0)
                {
                    pending_queues.Remove(cq);
                }

                Buffer.MemoryCopy(qm.msg, &output.msg[output.len], MESSAGE_MAX, qm.len);
                //memcpy(output.msg[output.len], qm.msg, qm.len);

                output.len  += qm.len;
                ready_bytes -= qm.len;
            }

            // Fill header / trailer
            output.len += MESSAGE_TRAILER_SIZE;
            output.msg[MESSAGE_POS_LEN] = output.len;
            output.msg[MESSAGE_POS_SEQ] = (byte)(MESSAGE_DEST | (send_seq & MESSAGE_SEQ_MASK));
            int crc = Crc16_ccitt(new ReadOnlySpan <byte>(output.msg, output.len - MESSAGE_TRAILER_SIZE));

            output.msg[output.len - MESSAGE_TRAILER_CRC]     = (byte)(crc >> 8);
            output.msg[output.len - MESSAGE_TRAILER_CRC + 1] = (byte)(crc & 0xff);
            output.msg[output.len - MESSAGE_TRAILER_SYNC]    = MESSAGE_SYNC;

            // Send message
            fixed(byte *psendBuffer = sendBuffer)
            {
                *((queue_message *)psendBuffer) = output;
            }

            serialPort.Write(sendBuffer, 0, output.len);
            //int ret = write(sq->serial_fd, output->msg, output->len);
            //if (ret < 0)
            //	report_errno("write", ret);
            bytes_write += output.len;
            if (eventtime > idle_time)
            {
                idle_time = eventtime;
            }
            idle_time          += output.len * baud_adjust;
            output.sent_time    = eventtime;
            output.receive_time = idle_time;
            if (sent_queue.Count == 0)
            {
                //	pollreactor_update_timer(&sq->pr, SQPT_RETRANSMIT, sq->idle_time + sq->rto);
                retransmitTimer = idle_time + rto;
            }
            if (rtt_sample_seq != 0)
            {
                rtt_sample_seq = send_seq;
            }
            send_seq++;
            need_ack_bytes += output.len;
            sent_queue.Enqueue(output);
        }
Пример #3
0
        static void handle_message(int length, double eventtime)
        {
            //Console.Write(eventtime + " ");
            //PrintByteArray(input_buf, length);

            // Calculate receive sequence number
            ulong rseq = (receive_seq & ~MESSAGE_SEQ_MASK) | (input_buf[MESSAGE_POS_SEQ] & MESSAGE_SEQ_MASK);

            if (rseq < receive_seq)
            {
                rseq += MESSAGE_SEQ_MASK + 1;
            }

            if (rseq != receive_seq)
            {
                // New sequence number
                update_receive_seq(eventtime, rseq);
            }
            if (length == MESSAGE_MIN)
            {
                // Ack/nak message
                if (last_ack_seq < rseq)
                {
                    last_ack_seq = rseq;
                }
                else if (rseq > ignore_nak_seq && sent_queue.Count != 0)
                {
                    // Duplicate Ack is a Nak - do fast retransmit
                    //pollreactor_update_timer(&sq->pr, SQPT_RETRANSMIT, PR_NOW);
                    retransmitTimer = PR_NOW;
                }
            }

            if (length > MESSAGE_MIN)
            {
                // Add message to receive queue
                queue_message qm = new queue_message(input_buf, (byte)length);
                qm.sent_time     = (rseq > retransmit_seq ? last_receive_sent_time : 0.0);
                qm.receive_time  = GetTime();               //get_monotonic(); // must be time post read()
                qm.receive_time -= baud_adjust * length;
                receive_queue.Enqueue(qm);
                //check_wake_receive(sq);


                Console.WriteLine($"receive time {(qm.receive_time - qm.sent_time) * 1000}ms");

                //{ 0, "identify_response offset=%u data=%.*s" }, uint32, buffer
                MemoryStream msg = new MemoryStream(length);
                for (var i = MESSAGE_HEADER_SIZE; i < length - MESSAGE_TRAILER_SIZE; i++)
                {
                    msg.WriteByte(input_buf[i]);
                }
                msg.Position = 0;
                var code = msg.ReadByte();

                if (code == 0)
                {
                    Console.WriteLine("identify_response");
                    var offset = msg.parse(false);
                    var len    = msg.ReadByte();
                    if (len > 0)
                    {
                        var buf  = new byte[len];
                        var read = msg.Read(buf, 0, len);
                        if (read != len)
                        {
                            Console.WriteLine("Error");
                        }

                        buffer.Write(buf, 0, read);
                        res += read;

                        Console.WriteLine($"Read bytes {buffer.Length}; {read}/{len}");
                    }
                    if (len < 40)
                    {
                        Console.WriteLine("download done");
                        res = -1;

                        var final    = ZlibDecompress(buffer.ToArray());
                        var jsonText = Encoding.ASCII.GetString(final);
                        //System.Text.Json.JsonDocument doc = System.Text.Json.JsonDocument.Parse(jsonText);
                        var xml = XDocument.Load(JsonReaderWriterFactory.CreateJsonReader(Encoding.ASCII.GetBytes(jsonText), new XmlDictionaryReaderQuotas()));
                        xml.Save("identify.xml");
                        //Console.WriteLine(Encoding.ASCII.GetString(final));
                    }
                }
                else
                {
                    Console.WriteLine($"{eventtime * 1000} code:{code}; seq:{rseq}; len:{length}");
                    var text = Encoding.ASCII.GetString(input_buf, 1 + MESSAGE_HEADER_SIZE, length - MESSAGE_TRAILER_SIZE);
                    Console.WriteLine(text);
                }
            }

            if (length > MESSAGE_MIN && res != -1)
            {
                Console.WriteLine(eventtime + " identify get data " + res + " seq:" + send_seq);
                //{ 1, "identify offset=%u count=%c" }, uint32, byte
                MemoryStream msg = new MemoryStream(16);
                msg.WriteByte(1);
                msg.encode(res);
                msg.encode(40);
                Send(msg);
            }
        }