4.14. Osnove CSI-ja

Modul csi način je na koji Python kod upravlja senzorom kamere. Svaka skripta koja snima sličicu slijedi isti trodijelni oblik: uvozi na vrhu, jednokratna konfiguracija u sredini i while True petlja na dnu koja iz kamere dohvaća sličice jednu po jednu.

4.14.1. Tipična petlja

import csi, image, time

csi0 = csi.CSI()
csi0.reset()
csi0.pixformat(csi.RGB565)
csi0.framesize(csi.QVGA)

clock = time.clock()
while True:
    clock.tick()
    img = csi0.snapshot()
    # process img here
    print(clock.fps())

4.14.2. Što svaki poziv radi

import csi, image, time

Uvodi tri modula. csi upravlja senzorom, image definira klasu Image koju snapshot() vraća, a time pruža pomoćnik time.clock() koji se koristi za mjerenje broja sličica u sekundi.

csi.CSI()

Konstruira instancu CSI koja omata jedan fizički senzor kamere. Konstruktor zahtijeva periferiju kamere i bilježi konfiguraciju za pojedini senzor. Kamere s jednim senzorom imaju jednu instancu CSI; kamere s dva senzora (boja plus toplinski, boja plus događajni) imaju dvije, od kojih se svaka odabire argumentom cid konstruktoru.

csi0.reset()

Napaja i konfigurira senzor. Prema zadanim postavkama pulsira pin za resetiranje senzora, zatim upisuje I2C registre senzora u poznato početno stanje. Naknadni konfiguracijski pozivi – pixformat, framesize, automatske upravljačke ručice – guraju više upisa registara preko iste I2C upravljačke sabirnice.

csi0.pixformat(csi.RGB565)

Upisuje registre senzora koji biraju izlazni format piksela. Dostupni izbori su formati koje je predstavila stranica formati piksela: RGB565, GRAYSCALE, BAYER, YUV422 i JPEG na senzorima koji ga podržavaju.

csi0.framesize(csi.QVGA)

Upisuje registre koji biraju izlaznu razlučivost. QVGA je 320 × 240; imenovane veličine sežu do WQXGA2 (2592 × 1944, oko 5 MP) na senzorima koji ih podržavaju. Funkcionira i prilagođena (width, height) n-torka, sve dok se poklapa s izlaznim mogućnostima senzora.

clock = time.clock()

Stvara pomoćnik za sat. Svaki poziv funkcije clock.tick() unutar petlje bilježi vrijeme početka iteracije; time.clock.fps() izvještava o nedavnoj brzini petlje u sličicama u sekundi.

img = csi0.snapshot()

Snima jednu sličicu iz senzora i vraća je kao Image. Mehanika načina na koji ta sličica završava u memoriji vrijedi pobližeg razmatranja.

4.14.3. Kako snapshot popunjava memoriju

Senzor isporučuje piksele na sabirnici podataka piksela opisanoj u sabirnice senzora brzinom od stotina megabajta u sekundi – predaleko brzo da bi ih CPU kopirao piksel po piksel u softveru.

Umjesto toga, MCU prebacuje prijenos na izravni pristup memoriji (DMA) – hardverski pogon odvojen od CPU-a koji kopira bajtove s jednog mjesta na drugo unutar MCU-a bez ikakvog uključivanja CPU-a. Ulazna periferija kamere hvata svaki dolazni bajt piksela u mali FIFO na čipu; one ISP faze koje se izvode na strani MCU-a obrađuju podatke usput; a DMA pogon upisuje gotove piksele u međuspremnik sličice u RAM-u na odgovarajućem odmaku piksela. Ništa u tom lancu ne treba CPU nakon što je DMA kanal programiran.

Kada se pozove snapshot():

  1. CSI upravljački program programira DMA pogon s adresom međuspremnika sličice, duljinom prijenosa (vrijednost jedne sličice piksela) i povratnim pozivom za prekid DMA-gotovo.

  2. Upravljački program omogućuje ulaznu periferiju kamere i čeka da senzor signalizira početak sljedeće sličice.

  3. Dok senzor izlučuje sličicu, periferija predaje svaki bajt piksela kroz ISP i dalje na DMA pogon, koji upisuje rezultat u RAM na sljedećem odmaku međuspremnika sličice. CPU je slobodan izvoditi drugi kod tijekom prijenosa.

  4. Kada stigne posljednji piksel sličice, DMA okida svoj prekid gotovo, upravljački program omata međuspremnik sličice u Image, a snapshot() ga vraća korisničkom kodu.

Vraćeni Image ne posjeduje kopiju podataka piksela – pokazuje na jedan od međuspremnika sličica kamere u RAM-u. Koliko međuspremnika sličica kamera zadržava i kako se oni predaju između DMA-a i korisničkog koda pri svakom pozivu funkcije snapshot(), ovisi o načinu međuspremanja koji je aplikacija odabrala putem framebuffers().