12.2. Cele patru niveluri

Biblioteca de protocol este construită ca o stivă de patru niveluri, fiecare rezolvând o singură problemă și construind pe nivelul de sub el. Restul capitolului parcurge stiva de jos în sus.

O stivă verticală de patru niveluri etichetate: transport la bază (USB sau UART), încadrare deasupra (antet de pachet cu CRC), fiabilitate deasupra acesteia (numere de secvență, ACK / NAK, retransmisii) și canale în vârf (fluxuri logice denumite).

12.2.1. Transport

La bază se află conducta de octeți dintre cameră și gazdă. Bibliotecii de protocol nu îi pasă care dintre ele transportă octeții:

  • USB-CDC peste portul USB în care este conectată camera. Opțiunea implicită și cu cea mai mare lățime de bandă pentru fiecare cameră.

  • UART peste o pereche de pini GPIO de pe cameră conectați la un adaptor serial de pe gazdă. Util pentru implementări fără afișaj, unde portul USB este ocupat sau nu este accesibil fizic.

Singura sarcină a transportului este „octeții intră, octeții ies, în ordine”. Tot ce se află deasupra acestui nivel presupune că transportul livrează octeții în ordinea în care au fost scriși, dar permite ca octeții înșiși să fie corupți sau ca legătura să cadă complet. Atât rafalele cu pierderi (câțiva octeți lipsă), cât și căderile curate (întreaga legătură dispărută o vreme, apoi revenită) sunt gestionate la niveluri superioare.

12.2.2. Încadrare

Următorul nivel impune o structură fluxului de octeți. Fiecare mesaj devine un pachet – un antet de 10 octeți urmat de o sarcină utilă urmată de o terminație de 4 octeți. Antetul transportă:

  • Un cuvânt de sincronizare de 2 octeți (0xD5AA) care permite unui receptor să regăsească începutul unui pachet după o desincronizare.

  • Un număr de secvență de 1 octet folosit de nivelul de fiabilitate.

  • Un ID de canal de 1 octet care indică fluxul logic căruia îi aparține pachetul.

  • Un câmp de indicatori de 1 octet pentru biții ACK / NAK / fragment / eveniment.

  • Un cod de operație de 1 octet care distinge comenzile de protocol, comenzile de sistem și comenzile de canal.

  • O lungime a sarcinii utile de 2 octeți.

  • Un CRC de 2 octeți peste cei opt octeți de antet anteriori.

Urmează sarcina utilă, apoi un CRC de 4 octeți peste sarcina utilă însăși. Cele două CRC-uri detectează corupția independent: un bit inversat în antet invalidează CRC-ul antetului, iar receptorul poate elimina pachetul fără a avea nevoie vreodată să citească sarcina utilă.

12.2.3. Fiabilitate

Nivelul de fiabilitate transformă „pachetele care ar putea ajunge” în „pachetele care au ajuns.” Urmărește numerele de secvență din antet, cere celeilalte părți să trimită confirmări pentru fiecare pachet care necesită una și retransmite atunci când o confirmare nu ajunge într-un interval de timp. În mod implicit, intervalul de timp pentru retransmisie începe la 500 ms și se dublează la fiecare reîncercare, cu trei reîncercări înainte de a renunța.

Fiecare dintre aceste comportamente este configurabil în apelul protocol.init(): ACK poate fi dezactivat pentru fluxurile unidirecționale, validarea CRC poate fi omisă pe transporturile perfect curate, iar parametrii de retransmisie pot fi reglați pentru legături lente sau cu latență ridicată.

12.2.4. Canale

Nivelul superior este ceea ce vede codul de aplicație. Un canal este un flux logic denumit, identificat printr-un ID de canal de la 0 la 31. Până la 32 de canale pot coexista pe un transport; fiecare este independent de celelalte, adresat prin ID-ul său în antetul fiecărui pachet. Camera pornește cu patru canale încorporate – stdin, stdout, stream și profile – iar codul de aplicație înregistrează mai multe deasupra apelând protocol.register() cu o clasă Python.

Cele patru niveluri nu amestecă responsabilitățile. Încadrarea nu știe nimic despre canale; fiabilitatea nu știe nimic despre conținutul pachetelor; nivelul de canal nu știe cum ajung octeții. Această separare este motivul pentru care o schimbare de transport (de la USB la UART, de exemplu) nu se propagă în sus în codul canalului și este ceea ce face ca restul capitolului să poată fi parcurs câte un nivel pe rând.