12.3. รูปแบบแพ็กเก็ต

ทุกไบต์ที่ข้ามสายสัญญาณระหว่างกล้องและโฮสต์เป็นส่วนหนึ่งของแพ็กเก็ต แพ็กเก็ตเริ่มต้นด้วยเฮดเดอร์ 10 ไบต์ ตามด้วยเพย์โหลดที่มีความยาวผันแปร และสิ้นสุดด้วย CRC ท้าย 4 ไบต์ ไม่มีไบต์อื่นปรากฏบนสายสัญญาณ เมื่อโฮสต์เห็น sync word 2 ไบต์แล้ว ไบต์ถัดไปคือเฮดเดอร์ตามลำดับที่แน่นอนนี้

A horizontal layout of a protocol packet showing the 10-byte header (sync word, sequence number, channel ID, flags, opcode, payload length, header CRC) followed by the variable-length payload and a 4-byte payload CRC.

12.3.1. เฮดเดอร์

สิบไบต์ บรรจุโดยไม่มีการเติมช่องว่าง แต่ละฟิลด์:

  • sync -- คำ 16 บิต 0xD5AA ในลำดับ little-endian ไบต์ที่ 0 บนสายสัญญาณคือ 0xAA ไบต์ที่ 1 คือ 0xD5 ตัวรับที่สแกนไบต์สามารถหาจุดเริ่มต้นของแพ็กเก็ตโดยค้นหาคู่ AA D5 ทุกสิ่งก่อนหน้าจะถูกถือว่าเป็นขยะ การเลือกค่านี้เป็นเจตนา: 0xAA และ 0xD5 แทบไม่ปรากฏในข้อความที่พิมพ์ได้ และคู่นี้ไม่น่าจะเกิดขึ้นโดยบังเอิญในกลางเพย์โหลด

  • seq -- หนึ่งไบต์ ตัวนับที่เพิ่มขึ้นทีละหนึ่งสำหรับแต่ละแพ็กเก็ตที่ส่งในทิศทางที่กำหนด ตัวรับตรวจสอบว่า sequence number ของแพ็กเก็ตถัดไปเป็นไปตามที่คาดหวัง หากไม่ใช่ reliability layer จะขอให้ส่งซ้ำ

  • chan -- หนึ่งไบต์ channel ID ที่แพ็กเก็ตนี้属于 ช่องสัญญาณ 0..31 สามารถใช้งานได้ ช่องในตัว stdin, stdout, stream และ profile (ตามตัวเลือก) ใช้ ID คงที่ที่กล้องสงวนไว้

  • flags -- หนึ่งไบต์ บิตฟิลด์ที่บอกตัวรับวิธีตีความแพ็กเก็ต:

    • บิต 0 ACK -- แพ็กเก็ตนี้เป็นการยืนยันรับรองของแพ็กเก็ตก่อนหน้า

    • บิต 1 NAK -- แพ็กเก็ตนี้ปฏิเสธแพ็กเก็ตก่อนหน้า

    • บิต 2 RTX -- แพ็กเก็ตนี้เป็นการส่งซ้ำ

    • บิต 3 ACK_REQ -- ผู้ส่งต้องการให้แพ็กเก็ตนี้ได้รับการยืนยัน

    • บิต 4 FRAGMENT -- มีชิ้นส่วนเพิ่มเติมตามมาในข้อความที่ใหญ่กว่า

    • บิต 5 EVENT -- แพ็กเก็ตนี้บรรจุเหตุการณ์ช่องสัญญาณแทนข้อมูล

    • บิต 6 และ 7 สงวนไว้

  • opcode -- หนึ่งไบต์ รหัสคำสั่งหรือการตอบกลับ ไลบรารีโปรโตคอลสงวนช่วง opcode ตามวัตถุประสงค์:

    • 0x00..0x0F -- คำสั่งโปรโตคอล (SYNC, GET_CAPS, SET_CAPS, STATS, VERSION)

    • 0x10..0x1F -- คำสั่งระบบ (RESET, BOOT, INFO, EVENT, MEMORY)

    • 0x20..0x2F -- คำสั่งช่องสัญญาณ (LIST, POLL, LOCK, UNLOCK, SHAPE, SIZE, READ, WRITE, IOCTL, EVENT)

  • len -- สองไบต์ little-endian จำนวนไบต์เพย์โหลดที่ตามหลังเฮดเดอร์ ความยาวศูนย์ถูกต้องตามกฎ การยืนยันรับรองและคำสั่งขนาดเล็กหลายรายการไม่มีเพย์โหลด

  • crc -- สองไบต์ CRC-16 เหนือแปดไบต์เฮดเดอร์ก่อนหน้า ตัวรับที่ได้รับเฮดเดอร์ที่มี CRC ไม่ถูกต้องจะทิ้งแพ็กเก็ตทั้งหมดโดยไม่ดูเพย์โหลดด้วยซ้ำ

12.3.2. เพย์โหลด

ศูนย์ไบต์หรือมากกว่า ถือเป็นข้อมูลทึบแสงโดย framing layer สิ่งที่อยู่ในเพย์โหลดขึ้นอยู่กับ opcode: สำหรับการตอบกลับ CHANNEL_READ คือข้อมูลช่องสัญญาณจริง สำหรับการตอบกลับ GET_CAPS คือโครงสร้างคงที่ขนาดเล็ก สำหรับการเขียนช่องสัญญาณคือสิ่งที่โฮสต์ส่ง

ขนาดเพย์โหลดสูงสุดขึ้นอยู่กับขนาดบัฟเฟอร์โปรโตคอลของกล้อง (ดูตารางต่อบอร์ดใน protocol.init()) ข้อความที่ยาวเกินขีดจำกัดจะถูกแบ่งออกเป็นชิ้นส่วนโดยตั้ง flag FRAGMENT บนทุกชิ้นยกเว้นชิ้นสุดท้าย

12.3.3. CRC ท้าย

สี่ไบต์ CRC-32 เหนือเพย์โหลด ตรวจจับความเสียหายที่ header CRC ไม่สามารถมองเห็นได้ โดยเฉพาะบนเพย์โหลดยาวที่ข้อผิดพลาดหนึ่งบิตกลางเฟรมจะผ่านไปได้อย่างอื่น

การแบ่งการตรวจสอบความสมบูรณ์ออกเป็น CRC สองตัวเป็นเจตนา Header CRC ปกป้องฟิลด์ framing เอง โดยเฉพาะความยาวเพย์โหลด หากไม่มี header CRC แยกต่างหาก การกลับบิตเดียวในไบต์ความยาวจะทำให้ตัวรับอ่านจำนวนไบต์เพย์โหลดผิดและหลุดซิงค์จากสตรีมไบต์โดยสิ้นเชิง เมื่อมี header CRC เฮดเดอร์ที่เสียหายจะถูกปฏิเสธทันทีและตัวรับจะสแกนหา sync word ถัดไปใหม่ จากนั้น payload CRC ปกป้องเนื้อหาข้อความเป็นข้อกังวลแยกต่างหาก ดังนั้นการกลับบิตในข้อมูลจะถูกรายงานว่าเป็นเพย์โหลดเสียหายแทนที่จะเข้าใจผิดว่าเป็นข้อผิดพลาด framing

รูปแบบนี้เล็กพอที่จะเดินผ่านทีละไบต์ และความจริงที่ว่าทุกแพ็กเก็ตมีเลย์เอาต์เดียวกัน ได้แก่ sync แล้วเฮดเดอร์ แล้วเพย์โหลด แล้ว CRC หมายความว่าตัวแยกวิเคราะห์ที่เขียนด้วยมือพอดีหน้าจอหนึ่ง นั่นคือเหตุผลที่การใช้งานโฮสต์ขนาดเล็กใน C, Python หรือ Rust เป็นโปรเจ็กต์สุดสัปดาห์ ส่วนไลบรารีโปรโตคอลคือเวอร์ชัน Python ที่ดูแลรักษาในแต่ละฝ่าย