Kompresija
Cilj
Efikasnije korištenje memorije.
Bitovi i bajtovi
...
uint8_t _wall; // 1 byte stores statuses ...
uint8_t _surface; // 1 byte stores surface ...
...
Pogledajmo dio koda iz mrm-robot-maze.h, prikazan lijevo.
Prva riječ u redu je "uint8_t", što znači da deklariramo varijablu tipa bajt, koja se sastoji od 8 bitova. U ovom času nećemo detaljno proučavati ova 2 pojma, koji se uče u osnovnoj školi. Ukratko, bit ima 2 stanja (ima-nema, je-nije, 0-1, itd.). Bajt se sastoji od 8 bitova.
Druga riječ je ime varijable. U prvom redu je to "_wall". "_" obično ide na početak imena interne varijable klase.
Kako programiramo mikrokontroler, moramo prihvatiti činjenicu da raspolažemo s malo memorije i moramo ju koristiti štedljivo. Svaki "_wall" sprema podatke o zidovima oko pločice. Znači, za svaku pločicu je jedan "_wall", koji sprema više podataka. Mogli smo staviti za svaku pločicu 4 varijable: "ZidGore", "ZidDolje", "ZidLijevo", "ZidDesno", gdje bi svaka spramala postoji li zid i koje je vrste. Međutim, mi smo sve uspjeli utrpati u jednu varijablu. Zašto i kako?
Odgovor na "zašto" je lagan: zato da trošimo 1 bajt po pločici, umjesto 4. Pločica može biti jako puno i zgodno je trošiti samo četvrtinu memorije.
Odgovor na "kako" je: koristili smo bitove. Prva 2 bita su jedan zid, druga 2 drugi, itd.
Čitanje bitova
Pogledajmo bajt s lijeve strane. Sastoji se od 8 bitova. Svaki bit može biti u 2 stanja. Uobičajeno se koristi 0 za jedno stanje, 1 za drugo. Što 0 i 1 znače, to je na nama da odredimo, ovo je samo način kako zapisati podatak u varijablu. Znači, prvi bit je "0", drugi je "1", itd.
Ako malo razmaknemo parove bitova, recimo da je zid gore označe kao 3. par (ne znači da je tako u programu, ovo je samo primjer), "01".
Kako pročitati iz varijable što je zapisano u 3. paru?
Drugim riječima, recimo da program ide kao lijevo i da se u varijablu "_wall" spremi broj iz našeg primjera. Ako konstanta počinje s "0b", onda je ona binarna i u tom slučaju će broj biti baš kao što želimo. Ovdje se nećemo baviti bazama brojevnog sustava.
Uglavnom, kako kasnije u programu pročitati koji su bitovi na 5. i 6. mjestu (naš par)?
Poslužit ćemo se operacijom "bit shift", koja pomiče sve bitova nadesno za dani broj mjesta. U našem slučaju pomičemo za 2 mjesta, kako bi 7. i 8. bit nestali, a 5. i 6. se pomaknuli na njihovo mjesto.
Nakon izvršene operacije će u "_wall" ostati upisan broj s lijeve strane. Razmaci su tu za lakše čitanje, inače se ne upisuju. Još samo da maknemo ostatak od 6 lijevih bitova.
_wall = _wall & 0b00000011;
Koristimo još jednu operaciju na bitovima, logičko "i". Operacija se piše "&". Rezultat će biti usporedba svakog bita s lijeve i desne strane operatora i izvršenje logičke "i" operacije. Nju opet nećemo objašnjavati jer je iz osnovnoškolske informatike.
Efektivno će iz "_wall" biti odrezano prvih 6 bitova jer su tu nule. Zadnja 2 će ostati netaknuta.
Sad je u "_wall" ostao samo "01", 3. par, što smo i htjeli.
Što znači "01", što druge kombinacije, to sami određujemo. Recimo "00" bi moglo biti "ne zna se ima li zida". "01" zid i na njemu nema žrtve. Itd. Još jedan način pakiranja podataka u bitove.
Zadatak: probajte zbrojiti sve znamenke binarnog broja.
Npr. 01010101 daje 4. Da se olakša učitavanje podataka, koristite samo ovu vrijednost, ali algoritam mora raditi za sve druge.
Rješenje
void RobotLine::loop() {
uint8_t number = 0b01010101;
uint8_t total = 0;
while (number > 0){
total += number & 1;
number = number >> 1;
}
}
Primjedbe
Projekt "Uvod u robotiku" sufinanciran je iz Europskog socijalnog fonda, poziv "Jačanje kapaciteta organizacija civilnoga društva za popularizaciju STEM-a".
Relevantne stranice:
Sadržaj vježbe za virtualne radionice isključiva je odgovornost Hrvatskog društva za robotiku.