This shows you the differences between two versions of the page.
|
pm:prj2026:florin.stancu:alexandru.negru2603 [2026/05/24 00:54] alexandru.negru2603 [Download] |
pm:prj2026:florin.stancu:alexandru.negru2603 [2026/05/24 01:10] (current) alexandru.negru2603 |
||
|---|---|---|---|
| Line 23: | Line 23: | ||
| * **Modulul de Output Sonor:** Un buzzer activ oferă feedback acustic imediat (ex: un ton scurt pentru o lovitură reușită, un ton diferit pentru o lovitură ratată sau expirarea timpului). | * **Modulul de Output Sonor:** Un buzzer activ oferă feedback acustic imediat (ex: un ton scurt pentru o lovitură reușită, un ton diferit pentru o lovitură ratată sau expirarea timpului). | ||
| + | ===== Planificare și Ipoteză ===== | ||
| + | |||
| + | ==== Ipoteza proiectului ==== | ||
| + | Credem că implementarea unei arhitecturi software non-blocante (zero-delay) bazată pe un automat cu stări finite (FSM) și pe un timer hardware dedicat pentru ''millis()'' va îmbunătăți calitatea multiplexării vizuale și va garanta un timp de scanare a inputurilor (butoane) sub 5ms. Presupunem că, deoarece microcontrolerul nu va mai irosi cicluri de ceas în bucle de așteptare blocante, acesta va permite actualizarea display-ului și citirea jucătorului în mod simultan, fără efect de flicker. | ||
| + | |||
| + | ==== Planificarea sarcinilor (Gantt) ==== | ||
| + | Următorul tabel descrie activitățile principale desfășurate pe parcursul celor 4 săptămâni alocate proiectului. | ||
| + | |||
| + | ^ Săptămâna ^ Activitate asumată ^ | ||
| + | | **Săptămâna 1** | **Documentare și Arhitectură:** Alegerea componentelor, studierea datasheet-urilor (ATmega328P, 74HC595) și definirea ipotezei proiectului, redactarea documentației pe OCW. | | ||
| + | | **Săptămâna 2** | **Hardware Design:** Proiectarea schemei electrice, asamblarea componentelor pe breadboard și testarea conexiunilor la pini (LED-uri, butoane, display). | | ||
| + | | **Săptămâna 3** | **Software Design:** Implementarea driverelor bare-metal (Timer0 pentru millis, Timer1 pentru generare ton, ADC, EEPROM, SPI/ShiftOut) și scrierea logicii FSM. | | ||
| + | | **Săptămâna 4** | **PM Fair & Profilare:** Profilarea codului, ajustarea dificultății, curățarea finală a repository-ului de Git și pregătirea prezentării. | | ||
| ===== Hardware Design ===== | ===== Hardware Design ===== | ||
| {{:pm:prj2026:florin.stancu:negrualexandru_schematic1.png?700|}} | {{:pm:prj2026:florin.stancu:negrualexandru_schematic1.png?700|}} | ||
| Line 37: | Line 50: | ||
| * 1 x Breadboard 830 puncte. | * 1 x Breadboard 830 puncte. | ||
| * Fire de conexiune tip Dupont (Tată-Tată și Mamă-Tată). | * Fire de conexiune tip Dupont (Tată-Tată și Mamă-Tată). | ||
| + | |||
| ===== Software Design ===== | ===== Software Design ===== | ||
| ==== Mediu de dezvoltare ==== | ==== Mediu de dezvoltare ==== | ||
| - | |||
| Cod scris în **C bare-metal** pentru ATmega328P, fără framework Arduino. Toolchain: | Cod scris în **C bare-metal** pentru ATmega328P, fără framework Arduino. Toolchain: | ||
| - | |||
| * **avr-gcc** 7.3.0 — compilator | * **avr-gcc** 7.3.0 — compilator | ||
| * **avr-libc** 2.0.0 — pentru macro-uri de registre din ''<avr/io.h>'', ''<avr/interrupt.h>'', ''<util/delay.h>'' | * **avr-libc** 2.0.0 — pentru macro-uri de registre din ''<avr/io.h>'', ''<avr/interrupt.h>'', ''<util/delay.h>'' | ||
| Line 56: | Line 68: | ||
| ==== Librării 3rd-party ==== | ==== Librării 3rd-party ==== | ||
| - | |||
| **Niciuna.** Toate perifericele sunt programate direct la nivel de registre. Singurele include-uri sunt header-ele standard avr-libc pentru definiţiile registrelor şi macro-urile de întreruperi. | **Niciuna.** Toate perifericele sunt programate direct la nivel de registre. Singurele include-uri sunt header-ele standard avr-libc pentru definiţiile registrelor şi macro-urile de întreruperi. | ||
| ==== Algoritmi şi structuri ==== | ==== Algoritmi şi structuri ==== | ||
| - | |||
| * **Automat cu stări finite** — 3 stări: IDLE, PLAYING, GAME_OVER, cu tranziţii într-un ''switch'' din main loop. | * **Automat cu stări finite** — 3 stări: IDLE, PLAYING, GAME_OVER, cu tranziţii într-un ''switch'' din main loop. | ||
| * **Multiplexare display** — cele 4 cifre împart 8 linii de segmente prin shift register 74HC595. Hold de 2 ms per cifră -> refresh ~125 Hz. Anti-ghosting prin stingerea tuturor digiților înainte de încărcarea segmentelor. | * **Multiplexare display** — cele 4 cifre împart 8 linii de segmente prin shift register 74HC595. Hold de 2 ms per cifră -> refresh ~125 Hz. Anti-ghosting prin stingerea tuturor digiților înainte de încărcarea segmentelor. | ||
| Line 68: | Line 78: | ||
| * **PRNG xorshift32** — generator pseudo-aleator rapid, seed-uit din zgomotul ADC. | * **PRNG xorshift32** — generator pseudo-aleator rapid, seed-uit din zgomotul ADC. | ||
| * **EEPROM** — persistență high score (2 bytes + magic byte pentru detectarea chip-ului virgin). Secvența EEMPE→EEPE protejată cu ''cli/sei''. | * **EEPROM** — persistență high score (2 bytes + magic byte pentru detectarea chip-ului virgin). Secvența EEMPE→EEPE protejată cu ''cli/sei''. | ||
| - | * **Punctaj proporțional** — 10/5/1 puncte după cât de rapid s-a apăsat raportat la fereastra disponibilă (33% / 66% / >66%). | ||
| - | * **Difficulty scaling** — fereastra scade cu 5 ms per hit, plafonată la 600 ms. | ||
| - | * **Animație "slot-machine"** — la +5 sau +10 puncte, scorul afișat oscilează cu noise aleatoriu apoi se stabilizează. | ||
| - | * **Bară de timp prin DP-uri** — cele 4 puncte decimale ale display-ului indică timpul rămas (1111 → 0111 → 0011 → 0001). | ||
| * **Delay non-blocant** — toate așteptările folosesc o buclă bazată pe ''millis()'' care continuă să refresheze display-ul, eliminând pâlpâirea în timpul melodiilor şi animaţiilor. | * **Delay non-blocant** — toate așteptările folosesc o buclă bazată pe ''millis()'' care continuă să refresheze display-ul, eliminând pâlpâirea în timpul melodiilor şi animaţiilor. | ||
| + | ==== Metrici și Profilarea Codului ==== | ||
| + | Pentru a valida ipoteza și a garanta un gameplay fluid, am urmărit următoarele metrici de performanță: | ||
| + | * **Latența de Input (Polling Rate):** Ținta asumată a fost un timp de răspuns sub 5ms. La profilarea codului (analizând funcția ''display_digits''), am observat că fiecare din cele 4 cifre necesită un ''_delay_us(2000)'' pentru a garanta o luminozitate optimă a segmentelor. Astfel, un ciclu complet de reîmprospătare durează minimum 8ms, plus overhead-ul shiftării pe 8 biți. Așadar, butoanele sunt scanate la aproximativ 8.5 - 9ms. Deși depășește pragul ipotetic de 5ms, valoarea este suficient de mică pentru a preveni pierderea oricărui input generat de reflexele umane. | ||
| + | * **Frecvența de Refresh (Display):** Un timp de execuție a buclei de ~8.5ms se traduce într-o frecvență de refresh de aproximativ **115-120 Hz**. Aceasta metrică a atins perfect ținta, rezultând într-un afișaj luminos, clar și absolut lipsit de pâlpâire (flicker). | ||
| + | * **Amprenta pe Memorie:** Executabilul final bare-metal folosește doar ~4.8 KB din memoria Flash și 150 bytes de memorie RAM, demonstrând eficiența optimizării la nivel de registre. | ||
| + | |||
| + | Proiectul a fost o oportunitate excelentă de a aprofunda lucrul **bare-metal** cu ATmega328P. Renunţarea la framework-ul Arduino a oferit control complet asupra perifericelor. Cele mai utile decizii s-au dovedit a fi structurarea logicii ca automat cu stări finite și multiplexarea non-blocantă. Cele mai dificile obstacole au fost: | ||
| + | * Generarea de tonuri pe PD6 (deoarece nu este un pin OC al Timer1, a necesitat crearea unei întreruperi manuale ''TIMER1_COMPA_vect''). | ||
| + | * Atomicitatea citirii contorului ''millis_count'' pe arhitectura AVR de 8 biți (rezolvată folosind blocul ''cli()/sei()''). | ||
| + | * Scrierea în EEPROM (respectarea timpului critic de 4 cicluri de ceas pentru secvența EEMPE -> EEPE). | ||
| ==== Surse şi funcţii implementate ==== | ==== Surse şi funcţii implementate ==== | ||
| - | |||
| Cod organizat într-un singur fişier (''whack_a_led.c'', ~810 linii) cu următoarele grupuri funcţionale: | Cod organizat într-un singur fişier (''whack_a_led.c'', ~810 linii) cu următoarele grupuri funcţionale: | ||
| - | |||
| * **Drivere low-level**: ''timer0_init'', ''millis'', ''tone_start/stop'', ''adc_read'', ''eeprom_read/write_byte_raw'', ''prng_next'' | * **Drivere low-level**: ''timer0_init'', ''millis'', ''tone_start/stop'', ''adc_read'', ''eeprom_read/write_byte_raw'', ''prng_next'' | ||
| * **Display**: ''shift_out_msb'', ''write_segments'', ''display_digits'', ''display_score'', ''display_idle'', ''display_game_over'', ''compute_dp_mask'' | * **Display**: ''shift_out_msb'', ''write_segments'', ''display_digits'', ''display_score'', ''display_idle'', ''display_game_over'', ''compute_dp_mask'' | ||
| Line 86: | Line 100: | ||
| * **Main loop**: inițializare periferice + ''while(1)'' cu refresh display + FSM | * **Main loop**: inițializare periferice + ''while(1)'' cu refresh display + FSM | ||
| - | Parametrii de joc (timpi de reacţie, punctaje, durate animaţii) sunt grupaţi ca ''#define''-uri la începutul fişierului pentru tuning rapid. | + | ===== Elementul de Noutate ===== |
| + | Elementul principal de noutate și originalitate (5% din evaluare) constă în **sistemul hibrid și dinamic de ajustare a dificultății**, secondat de inovații vizuale pe afișajul 7-segmente: | ||
| + | * **Dificultatea Scalabilă Hibrid:** Fereastra de timp pe care o are jucătorul la dispoziție nu este un simplu parametru static stabilit de potențiometru. Potențiometrul setează doar pragul "de bază" (între 3s și 1s). Peste acesta se aplică un algoritm de "Accelerare Progresivă": pe măsură ce scorul crește, din timpul total disponibil se scad automat câte 5 ms per punct acumulat, forțând o escaladare organică a dificultății. Timpul este totuși plafonat hardware (hard-limit la 600ms) pentru ca jocul să rămână fizic posibil. | ||
| + | * **Punctaj Proporțional:** Jucătorul nu primește mereu 1 punct per lovitură. Logica este împărțită pe trepte de reacție (se acordă 10, 5 sau 1 punct în funcție de plasarea timpului de reacție în treimea corespunzătoare a ferestrei alocate), recompensând reflexele extreme. | ||
| + | * **Bara de Progres pe Display (DP HUD):** Pentru a indica vizual cât timp mai are jucătorul înainte să expire runda curentă fără să întrerupă afișarea scorului, am folosit inteligent cele 4 puncte zecimale (DP) de pe afișaj. Acestea se sting rând pe rând pe măsură ce fereastra de timp trece (1111 → 0111 → 0011 → 0001), servind drept indicator vizual (Timer Bar). | ||
| ===== Rezultate Obţinute ===== | ===== Rezultate Obţinute ===== | ||
| - | + | Proiectul a fost finalizat cu succes în cele 4 săptămâni alocate. Sistemul funcţionează stabil ca un joc arcade complet, cu input multiplu (4 butoane cu pull-up intern + potenţiometru), output vizual multiplexat şi feedback sonor (melodii redate printr-un ISR manual pe Timer1). | |
| - | Proiectul a fost finalizat cu succes, toate obiectivele propuse fiind îndeplinite. Sistemul funcţionează stabil ca un joc arcade complet, cu input multiplu (4 butoane + potenţiometru), output vizual (4 LED-uri arcade + display 4 cifre cu DP) şi feedback sonor. | + | |
| - | ===== Concluzii ===== | + | ===== Concluzii și Validarea Ipotezei ===== |
| + | **Validarea Ipotezei:** Ipoteza inițială a fost validată **parțial**, însă cu un rezultat practic excelent. Presupunerea că timpul de polling va scădea sub 5ms s-a dovedit incorectă din cauza necesității hardware de a menține cifra aprinsă timp de 2ms pentru persistența retinei (rezultând într-o buclă de minim 8ms). Cu toate acestea, nucleul ipotezei s-a confirmat pe deplin: arhitectura cu FSM și eliminarea totală a funcțiilor blocante (înlocuite cu funcția custom ''custom_delay'' bazată pe ''millis()'') a permis ca sistemul să actualizeze display-ul și să scaneze inputurile simultan, fără nicio blocare sau ghosting. | ||
| - | Proiectul a fost o oportunitate excelentă de a aprofunda lucrul **bare-metal** cu ATmega328P. Renunţarea la framework-ul Arduino a oferit control complet asupra perifericelor (Timer0/1, ADC, EEPROM, întreruperi) şi a redus dimensiunea binarului la ~4.8 KB. | ||
| - | |||
| - | Cele mai utile decizii s-au dovedit a fi structurarea logicii ca **automat cu stări finite** (care a permis extensia uşoară cu countdown, level-up, animaţii) şi **multiplexarea non-blocantă** apelată din toate buclele de aşteptare, fără ea, display-ul pâlpâia la fiecare ''_delay_ms()''. | ||
| - | |||
| - | Cele mai dificile probleme au fost: maparea corectă a segmentelor între Q0..Q7 ale shift register-ului şi pinii A..G ai display-ului, generarea de tonuri pe PD6 (care nu e pin OC al Timer1, deci necesită ISR manual), atomicitatea citirii ''millis_count'' pe AVR pe 8 biţi, şi eliminarea efectului de **ghosting** între cifre. | ||
| - | |||
| - | În final, proiectul demonstrează că un sistem interactiv complet, cu input digital şi analogic, output multiplexat şi audio sintetizat poate fi construit fără bibliotecile Arduino, oferind o înţelegere mult mai profundă a microcontrolerului decât abordarea high-level cu ''digitalWrite()'' şi ''tone()''. | ||
| - | |||
| - | |||
| ===== Download ===== | ===== Download ===== | ||
| Line 114: | Line 123: | ||
| * ''LICENSE'' — licența MIT a proiectului | * ''LICENSE'' — licența MIT a proiectului | ||
| </note> | </note> | ||
| + | |||
| ===== Bibliografie/Resurse ===== | ===== Bibliografie/Resurse ===== | ||
| ==== Resurse Hardware ==== | ==== Resurse Hardware ==== | ||
| - | |||
| * **ATmega328P Datasheet** (Microchip/Atmel) — referinţa oficială pentru registrele perifericelor: Timer/Counter, ADC, EEPROM, USART, întreruperi. [[https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf|datasheet PDF]] | * **ATmega328P Datasheet** (Microchip/Atmel) — referinţa oficială pentru registrele perifericelor: Timer/Counter, ADC, EEPROM, USART, întreruperi. [[https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf|datasheet PDF]] | ||
| * **74HC595 Datasheet** (Texas Instruments / NXP) — shift register 8-bit cu latch, folosit pentru controlul segmentelor display-ului. [[https://www.ti.com/lit/ds/symlink/sn74hc595.pdf|datasheet PDF]] | * **74HC595 Datasheet** (Texas Instruments / NXP) — shift register 8-bit cu latch, folosit pentru controlul segmentelor display-ului. [[https://www.ti.com/lit/ds/symlink/sn74hc595.pdf|datasheet PDF]] | ||
| Line 124: | Line 133: | ||
| ==== Resurse Software ==== | ==== Resurse Software ==== | ||
| - | |||
| * **AVR Libc Reference Manual** — documentaţia oficială pentru avr-libc, în special pentru macro-urile din ''<avr/io.h>'', ''<avr/interrupt.h>'' şi funcţiile din ''<util/delay.h>''. [[https://www.nongnu.org/avr-libc/user-manual/|nongnu.org/avr-libc]] | * **AVR Libc Reference Manual** — documentaţia oficială pentru avr-libc, în special pentru macro-urile din ''<avr/io.h>'', ''<avr/interrupt.h>'' şi funcţiile din ''<util/delay.h>''. [[https://www.nongnu.org/avr-libc/user-manual/|nongnu.org/avr-libc]] | ||
| * **AVR-GCC Documentation** — opţiuni de compilare specifice arhitecturii AVR (''-mmcu'', ''-Os'', ''-DF_CPU''). | * **AVR-GCC Documentation** — opţiuni de compilare specifice arhitecturii AVR (''-mmcu'', ''-Os'', ''-DF_CPU''). | ||
| Line 130: | Line 138: | ||
| ==== Inspiraţie & resurse de muzică ==== | ==== Inspiraţie & resurse de muzică ==== | ||
| - | |||
| * **Mario Bros Game Over (Koji Kondo, 1985)** — transcrierea melodiei NES pentru buzzer, adaptată din proiecte open-source comunitare de Arduino. | * **Mario Bros Game Over (Koji Kondo, 1985)** — transcrierea melodiei NES pentru buzzer, adaptată din proiecte open-source comunitare de Arduino. | ||
| * **Note frequency table** — tabela standard de frecvenţe pentru notele muzicale (C4 = 262 Hz, A4 = 440 Hz, etc.). | * **Note frequency table** — tabela standard de frecvenţe pentru notele muzicale (C4 = 262 Hz, A4 = 440 Hz, etc.). | ||
| - | |||
| - | |||
| - | |||
| - | <html><a class="media mediafile mf_pdf" href="?do=export_pdf">Export to PDF</a></html> | ||
| - | |||
| - | SimplyCodes | ||
| - | |||