Differences

This shows you the differences between two versions of the page.

Link to this comparison view

si:laboratoare:02 [2022/09/14 16:15]
laura.ruse [Exerciții]
si:laboratoare:02 [2024/10/16 11:17] (current)
robert_ionut.alexa
Line 1: Line 1:
-===== Laboratorul 02. Fitbit SDK Application ​===== +===== Laboratorul 02. NuttX I2C, Senzori, LCD-uri ​=====
-La fel ca în laboratorul trecut, target-ul cu care vom lucru este un produs Fitbit, și anume **Fitbit Versa 3** sau **Fitbit Sense**. Vom utiliza //Fitbit Software Development Kit// (//SDK//) pentru a dezvolta o aplicație (app) în acest laborator, folosind mediul de dezvoltare pus la dispoziție de către Fitbit (Fitbit Studio) și simulatorul (Fitbit OS Simulator). Documentația pentru dezvoltatorii de aplicații Fitbit se poate găsi pe [[https://​dev.fitbit.com/​]].+
  
-O aplicație este de obicei un program specializat cu un scop clar (e.g. aplicație de exerciții fitness, aplicație de alarme/​timere etc.), spre deosebire ​de o [[https://​dev.fitbit.com/​build/​guides/​clockfaces/​|față de ceas]] care afișează în principiu ora și câteva statistici pentru ca utilizatorul să fie informat rapid când folosește smartwatch-ul.+În laboratorul ​de astăzi veți învăța cum să interactionați cu diferite periferice prin I2C și cum datele ​de la hardware sunt transmise utilizatorului prin diferite niveluri ​de indirectareVom explora atât noțiuni low-level (modul ​de organizare internă a memoriei unui display) cât și aspecte mai high-level (sistemul de graphics) construite peste.
  
-===== Setup =====+Un modul de kernel (sau un device driver) este o bucată specializată de cod care este compilată și adăugată la kernel-ul sistemului de operare. În acest mod, sistemul de operare are posibilitatea de a interacționa cu diferite periferice - în absența driverelor, un kernel nu ar putea accesa lumea exterioară CPU-ului. De exemplu, dacă ne dorim ca sistemul nostru să poată transfera date prin controller-ul de I2C, avem nevoie de un driver pentru I2C care să programeze aceste tranzacții de transfer de date. Analog, dacă ne dorim să interacționăm cu un senzor, avem nevoie de un device driver care știe să programeze acel senzor.
  
-<note tip>Vă recomandăm să folosiți **Windows** sau **macOS** ​pentru ​aceste laboratoare!</​note>​+<note tip> 
 +Aproximativ 80% din codul unui sistem de operare este format din codul pentru ​drivere. 
 +</​note>​
  
-Setup-ul este același ca în laboratorul trecut ([[https://​ocw.cs.pub.ro/​courses/​si/​laboratoare/​01|laboratorul 1]]).+Din punct de vedere al user-ului, driverele pot să fie expuse ​în două moduri:
  
-Mai exact, ​pentru ​a putea folosi infrastructura pusă la dispoziție ​de către Fitbit va trebui să urmați pașii: +  * char device driver - în Linux sunt folosite ​pentru ​mouse și tastaturăde exemplu, iar în NuttX pentru senzori ​și LCD, printre altelePe scurt, dispozitive cu rată mică de transfer de date, care functionează la nivel de caracter
-  - Creați-vă un cont Fitbit accesând [[https://​www.fitbit.com/​signup|acest link]]. +  ​* block device driver ​folosite ​pentru ​hdd-uri, sdd-uri, device-uri care au nevoie să transfere date la nivel de blocuri.
-  - Descărcați simulatorul (Fitbit OS Simulator) pentru [[https://​simulator-updates.fitbit.com/​download/​latest/​win|Windows]] sau [[https://​simulator-updates.fitbit.com/​download/​latest/​mac|macOS]]. Nu există support pentru Linuxdar există workarounds pentru acest lucru în cazul în care doriți să utilizați Linux la aceste laboratoare (urmați pașii ​de [[https://​github.com/​bingtimren/​fitbit-sim-starter|aici]] pentru a rula simulatorul pe Linux)+
-  - Accesați [[https://​studio.fitbit.com/​|Fitbit Studio]], mediul de dezvoltare online pus la dispoziție ​pentru ​developeri. +
-<note important>​Conectați-vă atât la Fitbit Studio, cât și la simulator cu **același** cont Fitbit creat mai sus!</​note>​+
  
-===== Exerciții ​===== +==== LTR308 - senzor de lumină ​====
-<note important>​ +
-În cadrul simulatorului setați **Versa 3** sau **Sense** ca de tip device (Settings -> Device Type). ​+
  
-Trebuie să folosiți versiunea 6.0 a SDK-ului. +=== Cum măsuram lumina? ===
-</​note>​+
  
-<note important>​ +Atunci când vorbim de unități de măsură ​pentru ​lumină ne referim la lumeni ​și luxi:
-Dacă Fitbit Studio nu se conectează la simulator, iar în simulator (la Settings) apare eroarea "​Device bridge is disconnected",​ trebuie să actualizați certificatul simulatorului. Soluția se găsește în discuția ​de [[https://​community.fitbit.com/​t5/​SDK-Development/​Simulator-SSL-Problem/​m-p/​5003032/​highlight/​true#​M16148|aici]]. Folderul este numit ''​atlas'' ​pentru ​Versa 3 și ''​vulcan''​ pentru Sense.+
  
-Pe Mac OS folderul este ''/​Applications/​Fitbit OS Simulator.app/​Contents/​Resources/​static/​devicesim/​mac/​vulcan.app/​Contents/​Resources''​ (pentru Sense).+  * lumeni reprezintă intensitatea luminoasă la sursă 
 +  * luxi reprezintă intensitatea luminoasă care cade pe un metru pătrat, în general măsurată de la 1 sau 10m distanță.
  
-</​note>​+{{ :​si:​laboratoare:​lumen_vs_lux2.png?​400 }}
  
-**0.** Ne propunem să creăm o aplicație cu luminițe (cea din GIF-ul ​de mai jos). Aplicația va avea trei butoane care pornesc/​opresc un mic spectacol ​de lumini. Pentru aceasta creați un nou proiect în [[https://​studio.fitbit.com/​|Fitbit Studio]] și alegeți template-ul //​Minimal//​. Descărcați template-ul pentru laborator ​de [[https://​drive.google.com/​file/​d/​18Yg3cV50ZhMa9pV4YM9Y5tmJ2Nlw37D8/​view?​usp=sharing|aici]] și aplicați-l în cadrul proiectului. Asigurați-vă că în ''​package.json''​ aveți setat tipul proiectului ca aplicație (**Type -> App**). Deocamdată ''​app/​index.js''​ este goliar proiectul nu va fi buildat cu succes.  +Astfel, pentru a putea măsura complet o sursă de lumină, avem nevoie ​de ambele unități de măsură. De exempluo lanternă poate emite o cantitate foarte mare de lumenidar dacă razele sunt dispersate pe o suprafață întinsă cantitatea ​de luxi rezultată va fi redusă.
-<note tip> +
-Exercițiile din laborator se rezolvă în fișierul ''​app/​index.js''​. Template-ul conține comentarii ​de tip //TODO// pentru fiecare subpunct al exercițiilor. Vom utiliza doar Device APIsdocumentația lor se află [[https://​dev.fitbit.com/​build/​reference/​device-api/​| aici]]. Limbajul ​de programare utilizat este Javascript, dar ne vom limita la funcționalitățile de bază. +
-</​note>​+
  
-{{:​si:​laboratoare:​lightsapp.png?200|}}+Altfel spus, chiar dacă ambele unități de măsură sunt relevante, intensitatea luminoasă "​reală"​ se măsoară mai degrabă prin luxi.
  
-**1.** Deocamdată ''​app/​index.js''​ este gol, iar proiectul nu va fi buildat cu succes. Pentru acest exercițiu ne propunem să avem referințe către toate elementele din ''​index.view''​ și variabile pentru a putea manipula mai ușor starea luminițelor. +=== LTR308 ===
-  - obțineți referințele către lumini și adăugați-le într-un array.<​code javascript>​ +
-import document from "​document";​+
  
-// Get all lights references by the ID defined in index.view +LTR308 este un senzor de lumină care comunică prin I2C șeste capabil ​să ofere utilizatorului intensitatea luminoasă exprimată în luxi. În NuttXsenzorii ​sunt expușprin char device-uri in ''​/dev/'' ​și pot fi accesați prin apeluri de sistem, asemănător implementării Linux.
-const lights = [ +
-  document.getElementById("​bot1"​),​ +
-  document.getElementById("​bot2"​),​ +
-  document.getElementById("​bot3"​),​ +
-  document.getElementById("​bot4"​),​ +
-  document.getElementById("​bot5"​),​ +
-  document.getElementById("​bot6"​),​ +
-  document.getElementById("​bot7"​),​ +
-  document.getElementById("​bot8"​),​ +
-  document.getElementById("​bot9"​),​ +
-  document.getElementById("​bot10"​),​ +
-]; +
-</​code>​ +
-  - obțineți referințele către cele trei butoane.<​code javascript>​ +
-const blinkLightsButton = document.getElementById("​lights-1"​);​ +
-const slideLightsButton = document.getElementById("​lights-2"​);​ +
-const customLightsButton = document.getElementById("​lights-3"​);​ +
-</​code>​ +
-  - definițdouă array-uri care să conțină culorile pentru stările când luminițele globurilor sunt aprinserespectiv când acestea ​sunt închise.<​code javascript>​ +
-// Colors for each light turned on +
-const lightOnColor = [ +
-  "#​FFA500",​ +
-  "#​FFA500",​ +
-  "#​FFA500",​ +
-  "#​FFA500",​ +
-  "#​FFA500",​ +
-  "#​FFA500",​ +
-  "#​FFA500",​ +
-  "#​FFA500",​ +
-  "#​FFA500",​ +
-  "#​FFA500",​ +
-]; +
-  +
-// Colors for each light turned off +
-const lightOffColor = [ +
-  "#​FCF4A3",​ +
-  "#​FCF4A3",​ +
-  "#​FCF4A3",​ +
-  "#​FCF4A3",​ +
-  "#​FCF4A3",​ +
-  "#​FCF4A3",​ +
-  "#​FCF4A3",​ +
-  "#​FCF4A3",​ +
-  "#​FCF4A3",​ +
-  "#​FCF4A3",​ +
-]; +
-</​code>​ +
-  - creațun array în care să țineți evidența globurilor aprinse/​stinse.<​code javascript>​ +
-const lightsOn = [ +
-  false, +
-  false, +
-  false, +
-  false, +
-  false, +
-  false, +
-  false, +
-  false, +
-  false, +
-  false, +
-]; +
-</​code>​ +
-<note tip> +
-**Explicații**:​ +
-  * Pentru a putea obține referințele către elementele UI este nevoie de [[https://​dev.fitbit.com/​build/​reference/​device-api/document/|Document API]], în care avem acces la funcția **getElementById()**. +
-  * Puteți folosi ​și alte culori dacă doriți. Pentru inspirație puteți intra [[https://​dev.fitbit.com/​build/​guides/​user-interface/​css/​|aici]]. +
-</​note>​+
  
-**2.** Pentru a putea face tranziția între jocurile ​de lumini avem nevoie de posibilitatea de a le stinge pe toate întâi. +Figura ​de mai jos ilustrează implementarea char device-urilor în Linux - astfel, fiecare periferic este liber să îșdefinească propriile metode ​de open, read, write, ioctl, close.
-  ​definițfuncția **turnOffLights()** care stinge luminițele (setează culorile pe starea ​de luminițe închise).<​code javascript>​ +
-function turnOffLights() { +
-  let i; +
-  for (i = 0; i < lights.length;​ i++) { +
-    lightsOn[i] = false; +
-    lights[i].style.fill = lightOffColor[i];​ +
-  } +
-+
-</​code>​ +
-  - apelați funcția definită anterior pentru a începe aplicația cu luminițele stinse.<code javascript>​ +
-turnOffLights();​ +
-</​code>​+
  
-**3.** Creați primul joc de lumini astfel încât atunci când apăsați primul buton toate luminițele să se aprindă și să se stingă la un interval de timp definit de voi (e.g. 200 ms). Toate butoanele trebuie să implementeze stingerea jocului de lumini deja activ pentru a nu se influența două jocuri de lumini între ele. +{{ :​si:​laboratoare:​linux_char_device.png?​550 ​}}
-  - adăugați un eveniment pentru primul buton care să execute o funcție **blinkLights()** în care veți implementa jocul de lumini.<​code javascript>​ +
-// We will recycle the same event handler +
-let intervalHandler = -1; +
-  +
-// First button event +
-blinkLightsButton.addEventListener("​click",​ (evt) => { +
-  if (intervalHandler == -1) { +
-    intervalHandler = setInterval(blinkLights,​ 200); +
-  } else { // Turn off event and cleanup +
-    clearInterval(intervalHandler);​ +
-    intervalHandler = -1; +
-    turnOffLights();​ +
-  } +
-}); +
-</​code>​ +
-  - implementați funcția **blinkLights()** care a fost dată ca parametru la subpunctul anterior (toate luminițele să se aprindă dacă erau stinse, și să se stingă dacă erau aprinse).<code javascript>​ +
-function blinkLights() { +
-  let i; +
-  for (i = 0; i < lights.length;​ i++) { +
-      if (lightsOn[i]) { +
-        lights[i].style.fill = lightOffColor[i];​ +
-      } else { +
-        lights[i].style.fill = lightOnColor[i];​ +
-      } +
-      lightsOn[i] = !lightsOn[i];​ +
-  ​} +
-} +
-</​code>​+
  
-<note tip> +Pe de altă parte, deoarece NuttX este un RTOS (Real Time Operating System) care își propune ​să aibă un memory-footprint cât mai scăzut, design-ul pentru char device-uri (ale senzorilor, dar constrângerea se respectă intr-o mare măsura și la alte periferice) este puțin schimbat. 
-**Eplicații**:​ + 
-  * Pentru a se adăuga un eveniment la apăsarea unui buton s-a utilizat funcția **addEventListener()** pe elementul buton în care s-a setat un [[https://dev.fitbit.com/build/guides/user-interface/svg-components/​buttons/#​click-events| click event]]+{{ :si:​laboratoare:​nuttx_char_device.png?​500 }} 
-  * Pentru ​apela o funcție la un anumit interval ​de se utilizeaza funcția **setInterval()** care primește ca parametri ​funcție de apelat ​și un interval ​de milisecunde în care să apeleze funcția dată, și întoarce un număr ce reprezintă ID-ul timer-ului setatPentru a dezactiva timer-ul se utilizează funcția **clearInterval()** care primește ca parametru ID-ul timer-ului. ​Pentru documentație intraț[[https://dev.fitbit.com/​build/​reference/​companion-api/​globals/​|aici]]+ 
-  * Variabila **intervalHandler** are rolul de a reține ID-ul ultimului timer setat pentru a-l putea deseta ​la următoarea apăsare de buton.+La nivelul sistemului de operare există o interfață uniformizată denumită ''​upperhalf driver''​ (''​nuttx/drivers/sensors/​sensor.c''​),​ comună tutoror senzorilor, care interceptează apelurile de sistem asociate acestoraMai departe, comenzile sunt trimise către ''​lowerhalf driver''​ (''​nuttx/drivers/sensors/ltr308.c''​) care este specific device-ului și se ocupă de interacțiunea prin I2C/SPI cu senzorul
 + 
 +O altă particularitate ​NuttX este că pentru a citi datele unui senzor nu se parcurge întregul lanț de comandă de la aplicație până în regiștri senzorului. În schimb, driver-ul creează un thread separat care se ocupă de polling, iar atunci când detectează că au venit date le trimite printr-notificare în upperhalf driver într-un buffer circular. Mai departe, datele ajung la aplicație
 + 
 +==== SSD1306 - display OLED ==== 
 + 
 +=== OLED vs LCD === 
 + 
 +Un aspect interesant când vine vorba despre display-uri este cum produc ele culoarea. Dacă în cazul unui LCD avem pixeli colorați care sunt luminați pentru a produce culorile, în cazul unui OLED avem control asupra fiecarui pixel în parte. 
 + 
 +De exemplu, pentru a produce culoarea negru un LCD va colora pixelii în negru și îi va lumina folosind ​un backlight. În schimb, deoarece un display ​de tip OLED permite control granular asupra pixelilor, este suficient ​să nu mai luminăm anumiți pixeli, iar astfel zona aceea de ecran va apărea neagră către utilizator. 
 + 
 +Astfelse spune că un display OLED poate să obțină "true darkness"​. 
 + 
 +Deși la nivel tehnic există distincția între cele două tipuri de display-uri, în NuttX ambele sunt organizate sub denumirea de LCD-uriEste responsabilitatea fiecărui driver să interfațeze corect interacțiunea cu device-ul său asociat. 
 + 
 +=== LCD driver în NuttX === 
 + 
 +Pornind de la design-ul driver-ului de senzori, putem regăsi aceleași principii și în cazul LCD-urilor. 
 + 
 +Cea mai simplă metodă de a interacționa cu un display este prin apeluri de sistem ''​ioctl()''​ pe un LCD char device. Acestea vor fi trimise mai departe către driver-ul specific display-ului care este responsabil de configurarea lui și de afișarea mesajelor. 
 + 
 +În cazul lui SSD1306, acesta poate fi accesat atât prin I2C, cât șprin SPI. Pe plăcile ESP32-Sparrow comunicația se realizează prin I2C. 
 + 
 +{{ :si:​laboratoare:​lcd_char_device.png?400 }} 
 + 
 +Dacă ar fi să ne uităm în interiorul unui display, acesta este doar o matrice de pixeli organizată pe linii și coloane. 
 + 
 +{{ :​si:​laboratoare:​lcd_gddram_layout.png?400 }} 
 + 
 +În cazul unui display cu rezoluție 128x32 precum cel de pe plăcile Sparrow, există: 
 + 
 +  * 128 de coloane adresabile individual 
 +  ​32 de rânduri adresabile la nivel de pagină, unde o pagină conține 8 rânduri. 
 + 
 +Datorită acestei organizări interne putem să scriem o coloană individuală,​ dar pentru a scrie un rând este nevoie să scriem întreaga pagină asociată rândului. 
 + 
 +{{ :​si:​laboratoare:​gddram_enlarged.png }} 
 + 
 +Char device-ul pentru ​LCD-uri este cea mai simplă metodă de interacționa cu un display din punct de vedere al consumului de memorie ​nu se face niciun fel de buffering al datelor. De exemplu, pentru a desena două linii: 
 + 
 +  * se desenează prima linie 
 +  * deoarece nu se face buffering ​la date, dacă am desena a doua linie am șterge din greșeală prima linie. Soluția este să recitim regiștri display-ului. 
 +  * acum suntem obligați să redesenăm prima linie împreună cu a doua. 
 + 
 +Următorul nivel de complexitate este reprezentat de framebuffer. Acesta introduce un API propriu, dar care în final apelează tot callback-uri din driver-ul device-ului. Poate cea mai importantă modificare față de un simplu char device este chiar în numele lui - oferă support de buffering. 
 + 
 +{{ :​si:​laboratoare:​lcd_framebuffer.png?​400 }} 
 + 
 +<note important>​ 
 +Framebuffer-ul poate fi implementat atât prin buffer software, cât și prin buffer hardware (direct în memoria display-ului). În NuttX, framebuffer-ul este întotdeauna software.
 </​note>​ </​note>​
  
-**4.** Creați al doilea joc de lumini astfel încât atunci când apăsați al doilea buton să se aprindă un singur rând de luminirestul fiind stinseLa un interval de timp definit de voi (e.g. 400 ms) să se aprindă următorul rând de lumini, iar cel anterior să se stingă. Toate butoanele trebuie să implementeze stingerea jocului ​de lumini deja activ pentru a nu se influența două jocuri de lumini între ele+Ultimul nivel de complexitate este reprezentat de subsistemul de graphics. 
-  - adăugați ​un eveniment pentru al doilea buton care să execute o funcție **slideLights()** în care veți implementa jocul de lumini.<code javascript>​ + 
-let currentLight; ​// keep track of the current lights for the slide show +{{ :​si:​laboratoare:​nuttx_graphics.png?​550 }} 
-slideLightsButton.addEventListener("​click",​ (evt) => {  ​ + 
-  if (intervalHandler ​== -1) { +Aplicațiile interacționează în mod direct atât cu biblioteca ''​nuttx/​libs/​libnx/''​cât și cu ''​nuttx/​graphics/''​Componenta principală este ''​nxglib''​ și este responsabilă de interacțiunea în mod direct cu LCD-ul folosindu-se de interfața de framebuffer explicată anterior
-    currentLight ​0; + 
-    lights[currentLight].style.fill ​lightOnColor[currentLight];​ +O altă componentă foarte importantă este ''​nxmu''​ (mu - multi-user). Astfel, se folosește ​un mecanism de tipul client-server,​ în care server-ul rulează pe un thread dedicat și serializează accesul tuturor clienților (thread-urilor) care concurează pentru acelasi display. 
-    lightsOn[currentLight] ​true; + 
-    lights[currentLight+rows].style.fill ​lightOnColor[currentLight+rows];​ +Restul componentelor le puteți găsi detaliate în [[https://​nuttx.apache.org/docs/latest/​components/​nxgraphics/​index.html|documentația oficială]] NuttX. 
-    lightsOn[currentLight+rows] ​true; + 
-  +==== Exerciții ​==== 
-    intervalHandler ​setInterval(slideLights,​ 400); + 
-  } else { // Turn off event and cleanup +**0.** Folosind comanda ''​ps''​ din linia de comandă ​shell-ului NuttXobservați că thread-ul pentru LTR308 este suspendat în waitingAcesta va fi planificat din nou pe CPU atunci când o aplicație va face un apel de sistem ''​open()''​
-    ​clearInterval(intervalHandler);​ + 
-    intervalHandler = -1; +**1.** Pentru a vă acomoda cu API-ul specific senzorilor, inspectați codul din ''​apps/​examples/​ltr308/'',​ rulați aplicația și observați output-ul de la stdout.
-    turnOffLights();​ +
-  } +
-}); +
-</​code>​ +
-  - implementați funcția ​**slideLights()** care fost dată ca parametru la subpunctul anterior (să se aprindă următorul rând de luminiiar cel anterior să se stingă).<code javascript>​ +
-function slideLights() {   +
-    lights[currentLight].style.fill = lightOffColor[currentLight];​ +
-    ​lightsOn[currentLight] = false; +
-    ​lights[currentLight+rows].style.fill = lightOffColor[currentLight+rows];​ +
-    lightsOn[currentLight+rows] = false; +
-  +
-    currentLight = (currentLight + 1) % rows; +
-    lights[currentLight].style.fill = lightOnColor[currentLight];​ +
-    lightsOn[currentLight] = true; +
-    lights[currentLight+rows].style.fill = lightOnColor[currentLight+rows];​ +
-    lightsOn[currentLight+rows] = true; +
-+
-</​code>​+
  
 <note tip> <note tip>
-**Explicații**: +**Hints:** 
-  * Variabila ​**currentLight** are rolul de a reține rândul de lumini ce a fost aprins pentru a putea fi stins după ce a trecut intervalul de timp.+  * fiecare char device asociat unui senzor este înregistrat sub ''/​dev/​uorb/​sensor_<​type>​N''​. 
 +  ​calibrarea senzorului prin apelul ​de sistem ioctl() este opțională. Pentru alte utilizări ale lui ioctl() puteți inspecta ''​sensor_ioctl()''​ din ''​nuttx/​drivers/​sensors/​sensor.c''​.
 </​note>​ </​note>​
  
-**5.** Creați al treilea joc de lumini ​după cum dorițvoiPuteți urma ca exemplu celălalte jocuri de lumini. Toate butoanele trebuie ​să implementeze stingerea jocului de lumini deja activ pentru ​nu se influența două jocuri ​de lumini între ele. +**2.** Aplicația ''​apps/​examples/​nxhello/''​ va afișa pe ecran "​Hello,​ World!" ​după care îșva termina execuțiaScopul acestui exercițiu este să afiși "​Hello,​ World!" ​de mai multe ori, într-un loop. Urmăriți pașii ​de mai jos: 
-  ​adăugați ​un eveniment pentru al treilea buton care să execute o funcție **customLights()** în care veți implementa jocul de lumini.<​code javascript>​ + 
-customLightsButton.addEventListener("​click",​ (evt) => { +<note important
-   if (intervalHandler == -1) { +Toate fișierele de tip header le puteți găsi în ''​nuttx/​include/​nuttx/''​. Puteți căuta recursiv din linia de comandă folosind ''​grep -r <string>''​
-    intervalHandler = setInterval(customLights,​ 1000); // adjust the interval timer +</note>
-  } else { // Turn off event and cleanup +
-    clearInterval(intervalHandler);​ +
-    intervalHandler = -1; +
-    turnOffLights();​ +
-  } +
-}); +
-</code+
-  - implementați funcția **customLights()** care a fost dată ca parametru la subpunctul anterior (voi definiți acest joc de lumini).<code javascript> +
-function customLights() { +
-  // TODO complete here +
-  console.log("​custom lights show"​);​ +
-} +
-</code>+
  
-**[BONUS]6.** Înlocuiți imaginea de background cu o alta la alegerea voastra. Asigurați-vă că aceasta este tot un fișier cu extensia ​.png/.jpg și dimensiune maxim 336 x 336 pentru Fitbit SensePuteți muta poziția luminilor din fișierul ​''​index.view''​. ​Distracție placuta!+  - Activați următoarele config-uri:​ 
 +    ​CONFIG_NX=y 
 +    ​CONFIG_NX_BLOCKING=y 
 +    ​CONFIG_MQ_MAXMSGSIZE=64 
 +    ​CONFIG_NXFONT_MONO5X8=y 
 +    * CONFIG_NX_DISABLE_1BPP=n 
 +    * CONFIG_NXFONTS_DISABLE_1BPP=n 
 +    * CONFIG_EXAMPLES_NXHELLO=y 
 +    * CONFIG_EXAMPLES_NXHELLO_BPP=1 
 +  - Rulați aplicația ''​nxhello''​ șinspectați output-ul. Ne interesează să aflăm cum aplicația obține date despre: 
 +    * culoarea fundalului - în cazul nostru va fi 0, deoarece display-ul este monocromatic. 
 +    * rezoluția display-ului. 
 +  - Ștergerea ecranului (a întregului ecran sau doar a unei porțiuni) se va face prin ''​nx_fill''​. Căutați prototipul ei. 
 +  - Pe baza semnăturii funcției, căutați structurile ''​struct nxgl_rect_s'' ​și mai departe ''​struct nxgl_point_s''​. 
 +  - Pentru a determina window handle-ul necesar lui ''​nx_fill''​ inspectați funcția ''​nxhello_position''​. ​Aceasta este apelată la inițializarea aplicației și este modalitatea prin care clientul primește de la server atât rezoluția display-ului cât și un handle (pointer) către o instanță a unei "​ferestre"​. 
 +  - Apelați ''​nx_fill''​ pentru a șterge ecranul, iar mai apoi reapelați ''​nxhello_hello''​.
  
 +**3. Bonus -** Modificați aplicația ''​nxhello''​ astfel încât o dată pe secundă să citiți senzorul de lumină și să afișați rezultatul pe ecran. Folosiți-vă de pthreads pentru a crea un thread separat, dedicat interacționării cu senzorul.
  
 +==== Resurse ====
  
-<​hidden>​ +  ​* [[https://nuttx.apache.org/docs/latest/components/nxgraphics/appendix.htmlNuttX Graphics Appendix]]
-Atasat se gaseste o implementare a solutiei {{ si:​laboratoare:​application_2020_index.txt |}}. +
-Din motive de securitate fisierul original a fost salvat cu extensia //"​.txt"//​.  +
-Pentru a putea fi folosit acesta trebuie redenumit la **application_2020_index.js**. +
-</​hidden>​ +
-===== Resurse ===== +
-  ​* [[https://drive.google.com/file/d/18Yg3cV50ZhMa9pV4YM9Y5tmJ2Nlw37D8/view?​usp=sharing|Template Laborator]] +
-  * [[https://dev.fitbit.com/​getting-started/​| Getting Started with Fitbit SDK]] +
-  * [[https://​dev.fitbit.com/​build/​reference/​device-api/​| Fitbit SDK - Device API Reference]] +
-  * [[https://​dev.fitbit.com/​build/​guides/​| Fitbit SDK Guides]] +
-  * [[https://​dev.fitbit.com/​build/​guides/​user-interface/​svg-components/​buttons/​Button Components Guide]]+
si/laboratoare/02.1663161335.txt.gz · Last modified: 2022/09/14 16:15 by laura.ruse
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0