12.2. De fyra lagren

Protokollbiblioteket är byggt som en stack av fyra lager, där vart och ett löser ett enda problem och bygger på lagret under sig. Resten av kapitlet går igenom stacken nedifrån och upp.

En lodrät stack av fyra namngivna lager: transport längst ner (USB eller UART), ramhantering ovanför (pakethuvud med CRC), tillförlitlighet ovanför det (sekvensnummer, ACK / NAK, omsändningar) och kanaler högst upp (namngivna logiska strömmar).

12.2.1. Transport

Längst ner finns byterör mellan kameran och värden. Protokollbiblioteket bryr sig inte om vilket av dem som bär byten:

  • USB-CDC över USB-porten som kameran är ansluten till. Standardvalet och alternativet med högst bandbredd för varje kamera.

  • UART över ett par GPIO-stift på kameran anslutna till en serieadapter på värden. Användbart för huvudlösa driftsättningar där USB-porten är upptagen eller inte är fysiskt åtkomlig.

Transportens enda uppgift är ”byte går in, byte kommer ut, i ordning”. Allt ovanför detta lager antar att transporten levererar byte i den ordning de skrevs, men tillåter att byten själva kan vara skadade eller att länken helt bryts. Förlustfyllda skurar (några byte saknas) och rena avbrott (hela länken borta en stund, sedan tillbaka) hanteras båda högre upp.

12.2.2. Ramhantering

Nästa lager upp påtvingar struktur på byteströmmen. Varje meddelande blir ett paket – en header på 10 byte följd av en nyttolast följd av ett släp på 4 byte. Headern bär:

  • Ett synkord på 2 byte (0xD5AA) som låter en mottagare återfinna början av ett paket efter en desynkronisering.

  • Ett sekvensnummer på 1 byte som används av tillförlitlighetslagret.

  • Ett kanal-ID på 1 byte som anger vilken logisk ström paketet tillhör.

  • Ett flaggfält på 1 byte för bitarna ACK / NAK / fragment / händelse.

  • En opkod på 1 byte som skiljer mellan protokollkommandon, systemkommandon och kanalkommandon.

  • En nyttolastlängd på 2 byte.

  • En CRC på 2 byte över de föregående åtta headerbyten.

Nyttolasten följer, sedan en CRC på 4 byte över själva nyttolasten. De två CRC:erna fångar korruption oberoende av varandra: en omkastad bit i headern ogiltigförklarar header-CRC:n, och mottagaren kan kasta paketet utan att någonsin behöva läsa nyttolasten.

12.2.3. Tillförlitlighet

Tillförlitlighetslagret omvandlar ”paket som kanske anländer” till ”paket som har anlänt”. Det spårar sekvensnumren i headern, ber den andra sidan skicka bekräftelser för varje paket som kräver en, och sänder om när en bekräftelse inte anländer inom en timeout. Som standard börjar omsändningstimeouten på 500 ms och fördubblas vid varje nytt försök, med tre försök innan den ger upp.

Var och en av dessa beteenden är konfigurerbar i anropet protocol.init(): ACK kan stängas av för enkelriktade strömmar, CRC-validering kan hoppas över på helt rena transporter, och omsändningsparametrarna kan justeras för långsamma länkar eller länkar med hög latens.

12.2.4. Kanaler

Det översta lagret är vad applikationskod ser. En kanal är en namngiven logisk ström som identifieras av ett kanal-ID från 0 till 31. Upp till 32 kanaler kan samexistera på en transport; var och en är oberoende av de andra och adresseras med sitt ID i varje pakets header. Kameran startar med fyra inbyggda kanaler – stdin, stdout, stream och profile – och applikationskod registrerar fler ovanpå genom att anropa protocol.register() med en Python-klass.

De fyra lagren blandar inte ansvarsområden. Ramhantering vet inget om kanaler; tillförlitlighet vet inget om paketinnehåll; kanallagret vet inte hur byten anländer. Den separationen är varför ett transportbyte (USB till UART, till exempel) inte fortplantar sig upp i kanalkoden, och det är vad som gör att resten av kapitlet kan gås igenom ett lager i taget.