12.2. De vier lagen¶
De protocolbibliotheek is opgebouwd als een stapel van vier lagen, waarbij elke laag één enkel probleem oplost en voortbouwt op de laag eronder. De rest van het hoofdstuk loopt de stapel van onder naar boven door.
12.2.1. Transport¶
Onderaan zit de bytepijp tussen de cam en de host. Het maakt de protocolbibliotheek niet uit welke de bytes vervoert:
USB-CDC over de USB-poort waarop de cam is aangesloten. De standaard en de optie met de hoogste bandbreedte voor elke cam.
UART over een paar GPIO-pinnen op de cam, verbonden met een seriële adapter op de host. Nuttig voor headless implementaties waar de USB-poort bezet of fysiek niet toegankelijk is.
De enige taak van het transport is “bytes gaan erin, bytes komen eruit, in volgorde”. Alles boven deze laag gaat ervan uit dat het transport bytes aflevert in de volgorde waarin ze zijn geschreven, maar staat toe dat de bytes zelf beschadigd raken of dat de verbinding volledig wegvalt. Verliezende bursts (een paar ontbrekende bytes) en schone uitvallen (de hele verbinding een tijdje weg, dan weer terug) worden beide hogerop afgehandeld.
12.2.2. Framing¶
De volgende laag legt structuur op aan de bytestream. Elk bericht wordt een pakket – een header van 10 bytes, gevolgd door een payload, gevolgd door een trailer van 4 bytes. De header bevat:
Een sync-woord van 2 bytes (
0xD5AA) waarmee een ontvanger het begin van een pakket kan terugvinden na een desynchronisatie.Een volgnummer van 1 byte dat door de betrouwbaarheidslaag wordt gebruikt.
Een channel-ID van 1 byte die aangeeft tot welke logische stream het pakket behoort.
Een vlaggenveld van 1 byte voor ACK / NAK / fragment / event-bits.
Een opcode van 1 byte die protocolcommando’s, systeemcommando’s en channelcommando’s van elkaar onderscheidt.
Een payloadlengte van 2 bytes.
Een CRC van 2 bytes over de voorgaande acht headerbytes.
De payload volgt, dan een CRC van 4 bytes over de payload zelf. De twee CRC’s vangen corruptie onafhankelijk op: een omgeklapte bit in de header maakt de header-CRC ongeldig, en de ontvanger kan het pakket weggooien zonder ooit de payload te hoeven lezen.
12.2.3. Betrouwbaarheid¶
De betrouwbaarheidslaag verandert “pakketten die misschien aankomen” in “pakketten die zijn aangekomen.” Ze houdt de volgnummers in de header bij, vraagt de andere kant om bevestigingen te sturen voor elk pakket dat er een vereist, en hertransmitteert wanneer een bevestiging niet binnen een time-out aankomt. Standaard begint de hertransmissie-time-out op 500 ms en verdubbelt bij elke nieuwe poging, met drie pogingen voordat wordt opgegeven.
Elk van die gedragingen is configureerbaar in de protocol.init()-aanroep: ACK kan worden uitgeschakeld voor eenrichtingsstreams, CRC-validatie kan worden overgeslagen op perfect schone transporten, en de hertransmissieparameters kunnen worden afgestemd op trage of hoog-latente verbindingen.
12.2.4. Channels¶
De bovenste laag is wat applicatiecode ziet. Een channel is een benoemde logische stream die wordt geïdentificeerd door een channel-ID van 0 tot 31. Tot 32 channels kunnen naast elkaar bestaan op één transport; elk is onafhankelijk van de andere, geadresseerd via zijn ID in de header van elk pakket. De cam start op met vier ingebouwde channels – stdin, stdout, stream en profile – en applicatiecode registreert er meer bovenop door protocol.register() aan te roepen met een Python-klasse.
De vier lagen vermengen geen verantwoordelijkheden. Framing weet niets van channels; betrouwbaarheid weet niets van pakketinhoud; de channellaag weet niet hoe de bytes aankomen. Die scheiding is waarom een wisseling van transport (bijvoorbeeld van USB naar UART) niet doorwerkt in de channelcode, en het is wat de rest van het hoofdstuk laag voor laag begaanbaar maakt.