Salta ai contenuti

UDA 6 — Progetto finale e documentazione

3 ore (1 di teoria + 2 di laboratorio) · Settimane 11-12 · lavoro a coppie

Al termine di questa unità:

  • sai trasformare una traccia in un piccolo progetto: requisiti, passi di lavoro, prove;
  • integri almeno due periferiche e almeno un device in interrupt in un programma che funziona;
  • documenti il codice (intestazione, commenti utili, contratto delle subroutine) e scrivi una breve relazione;
  • presenti la demo alla classe in 5 minuti e rispondi a un colloquio sul tuo codice.

Piano delle due settimane — Sett. 11: scelta della proposta, piano dei passi, primo nucleo funzionante. Sett. 12: completamento, collaudo con la checklist, demo e colloqui. Le ore di laboratorio della UDA 5 (settimana 11) possono essere anticipate sul progetto.


Finora il problema era già scritto da qualcun altro. In un progetto è tuo:

EsercizioProgetto
Requisitidatili scrivi tu (o li ricavi dalla traccia)
Dimensioneuna funzionepiù parti che collaborano
Casi limiterarivanno previsti (valore 0, sequenza vuota, tasto tenuto premuto…)
Provaun valore attesouna demo che si vede funzionare
Consegnail file .asmsorgente + relazione + presentazione

Un progetto non è “un esercizio più lungo”: è la capacità di scomporre, provare e spiegare quello che hai fatto. Anche per questo la valutazione guarda a funzionamento, qualità del codice, autonomia nel debug e documentazione (rubrica in §11).


Ogni coppia sceglie una proposta (o ne propone una equivalente da concordare col docente entro la settimana 11). Tutte integrano almeno due periferiche e almeno un device in interrupt.

#PropostaPerifericheInterruptComportamento da mostrare
1Colonna luminosakeypad, LED/7 segtimersi digita un numero: i LED contano da 0 fino a lì, poi ripartono
2Contalattinecounter/nastro, motore, LCDcounterogni pezzo sul nastro incrementa il totale; il motore avanza
3Forno controllatokiln, potenziometro, chart— (obbligatorio: usare il kiln in interrupt)il potenziometro dà il setpoint; il riscaldatore segue la temperatura; il chart traccia
4Pianolakeypad, beeper, LCDkeypadogni tasto produce una nota e compare sul display; l’ultimo tasto riproduce
5Proposta liberaa scelta (≥ 2)a scelta (≥ 1)concordata con il docente

Consiglio: scegliete la proposta guardando prima che periferiche servono. Se una periferica non vi è chiara, rileggete la sua sezione (UDA 4-5) e provatela con un mini programma di 10 righe prima di inserirla nel progetto.


Una checklist che il docente userà durante la demo:

  • ≥ 2 periferiche diverse usate davvero (non solo inizializzate);
  • ≥ 1 device gestito in interrupt (timer, counter, keypad), con vettore, I, im 2, ei, servizio bilanciato, ei + reti;
  • ≥ 1 subroutine (con contratto documentato, vedi §6);
  • codice commentato e nome del file significativo;
  • demo funzionante al simulatore, con percorso di prova preparato;
  • relazione breve (§7).

Attenzione: “usare l’interrupt” significa che il programma principale continua a lavorare mentre il device interrompe. Un servizio che fa tutto il lavoro e un main vuoto non è un buon progetto: ditelo con l’architettura, non con le parole.


1. Scomponete in passi piccoli. Elencate i passi sul quaderno, dal più semplice: accendo un LED → leggo il keypad → timer con interrupt che conta → integro. Ogni passo deve funzionare da solo prima di passare al successivo.

2. Un passo, una prova. Dopo ogni modifica: Assembla & Carica, Passo un po’, poi Esegui. Non scrivete 50 righe e sperate: il bug diventa introvabile.

3. Salvate una copia che funziona. Prima di una modifica rischiosa, copiate il listato (o salvatelo con un nome diverso): se la modifica peggiora le cose, sapete dove tornare.

4. Scheda di debug. Per ogni problema annotate tre righe:

Dove sonoCosa mi aspettavoCosa vedo
dopo il servizio, PC = …LED = 3LED = 0

La colonna di mezzo è il test; la terza è l’osservazione: la differenza è il bug.

5. Chi fa cosa. In coppia: uno scrive, l’altro controlla e prova; poi si scambiano i ruoli almeno una volta per incontro.


Nel menu esempio del simulatore (e in esempi/) ci sono due progetti completi, verificati, che coprono i due schemi tipici:

  • 11-progetto-colonna-luminosa.asm — timer in interrupt + keypad in polling;
  • 12-progetto-pianola.asm — keypad in interrupt + lavoro nel main (mailbox).

Non copiateli per la consegna: sono lì per farvi vedere come si struttura un progetto (servizio breve, stato in memoria, subroutine, commenti). Alcide da riusare: il setup del device vettorato, il servizio con push/pop bilanciati, la separazione servizio/main.

.org 0x0010
VTab: .dw servizio ; tabella dei vettori (indirizzo pari)
.org 0x0020
target: .db 0 ; valore digitato (stato condiviso!)
conta: .db 0
; main: legge il keypad (polling) e aggiorna il target
; servizio (timer): incrementa "conta", la mostra su LED e display,
; quando supera il target riparte da zero

Da osservare: il main non aspetta il timer (è il timer che “bussa”); i LED si muovono anche se il main è fermo sul keypad; la cp (hl) nel servizio confronta il conteggio col target in memoria (non nei registri del main).

.org 0x0020
tasto: .db 0xFF ; mailbox: ultimo tasto letto (0xFF = nessuno)
fine: .db 0
melodia:.ds 16
; servizio (keypad): legge il tasto e lo mette nella mailbox
; main: se c'e' un tasto nuovo lo consuma, lo mostra e lo suona;
; il tasto F riproduce tutta la melodia (subroutine "nota")

Da osservare: il servizio è breve (legge e scrive un byte); il lavoro pesante (LCD, beep, pause) resta nel main; la mailbox è il contratto tra servizio e main.

Entrambi i listati completi sono in appendice (§12) e in esempi/.


a) Intestazione in testa al file (modello):

; ---------------------------------------------------------------
; Progetto: contalattine Autori: Rossi - Bianchi, 3B ITI
; Data: 12/2026 Versione: 1.0
; Obiettivo: contare i pezzi sul nastro e mostrarli sull'LCD;
; il motore avanza a ogni pezzo.
; Porte: counter 0xE0/0xE1, motore 0xB0, LCD 0xD0, LED 0x20
; Uso: eseguire, muovere gli interruttori 0-1 per partire/fermare
; ---------------------------------------------------------------

b) Commenti utili: spiegano perché, non ripetono l’istruzione.

ld a, 0x83 ; GOOD: run + interrupt (bit0, bit1)
inc a ; BAD: incrementa A (si vede da solo)

c) Contratto delle subroutine: ogni subroutine scritta da voi ha un commento con ingressi, uscite e registri modificati:

; ascii: A = tasto (0-15) -> A = '0'..'F'
; modifica: A, flag. preserva: B, C, D, E, H, L

d) Mappa delle porte: un blocco NOME = porta all’inizio, così il codice si legge come una descrizione del sistema. Il docente la userà durante il colloquio.


Massimo due pagine (1 di testo + 1 di schema/tabelle), in chiaro:

  1. Obiettivo — cosa fa il sistema, in 3 righe (e la proposta scelta).
  2. Schema delle porte — tabella: periferica, porta, direzione, uso nel programma.
  3. Architettura — chi fa cosa: main, servizio/servizi, stato condiviso. Un diagramma a blocchi vale più di un paragrafo (freccette: evento → servizio → stato → main → uscita).
  4. Prove e collaudo — la checklist di §10 con l’esito; cosa succede nei casi limite provati.
  5. Difficoltà e soluzioni — almeno due problemi veri e come li avete risolti (è la sezione che vale di più: mostra il vostro metodo).
  6. Possibili sviluppi — una o due idee non realizzate (facoltativo).

Scaletta consigliata:

TempoCosa
0:00-0:30Che cos’è: proposta, obiettivo, in una frase
0:30-2:30Fatelo vedere: percorso di prova preparato (azioni + cosa guardare)
2:30-4:00Com’è fatto: blocco main / servizio / stato condiviso, 2-3 pezzi di codice
4:00-5:00Cosa abbiamo imparato: una difficoltà e come l’avete risolta

Prima della demo:

  • provate due volte da Reset (la seconda senza toccare nulla tra un passo e l’altro);
  • preparate il percorso di prova scritto: «premo 3 → i LED contano fino a 3»;
  • preparate il piano B: se qualcosa non parte, mostrate il listato e spiegate dove il comportamento dovrebbe comparire (una demo spiegata bene vale più di una demo muta).

Domande tipiche (2-3 minuti a coppia, sul vostro codice):

  • Mostratemi il servizio: perché avete salvato proprio quei registri?
  • Cosa succede se il tasto resta premuto? E se non arriva mai l’interrupt?
  • Dov’è lo stato condiviso tra main e servizio? Perché non in un registro?
  • Cosa cambia se la costante del timer passa da 0x10 a 0x40?
  • Perché avete scelto il polling qui e l’interrupt là?
  • Cosa fa questa istruzione? (indicata a caso nel listato)

Si risponde leggendo il codice, non a memoria: allenatevi a percorrere il listato ad alta voce, dalla prima riga al reti.


  • Il programma assembla senza errori (e rileggete gli eventuali messaggi);
  • da Reset, due esecuzioni di fila danno lo stesso comportamento;
  • casi limite: valore 0, valore massimo, sequenza vuota, comando ripetuto;
  • il main continua mentre il servizio gira (strumento: Passo e vista memoria);
  • lo stack torna al valore iniziale dopo ogni servizio (controllate SP);
  • niente HALT inattesi: se il programma si ferma, sapete spiegare perché;
  • l’intestazione è completa, le etichette hanno nomi significativi;
  • la relazione cita le porte giuste (confrontatela col blocco NOME = porta).

Indicatore0-23-56-89-10
Funzionamentonon funzionafunziona in partefunziona come richiestogestisce i casi limite
Uso delle periferiche/interruptnessuno1 periferica2 periferiche, 1 in interruptintegrazione solida e motivata
Qualità del codiceilleggibilepoco commentatochiaro e commentatostrutturato a subroutine, nomi significativi
Autonomia nel debugbloccatocon aiutoautonomoautonomo e aiuta i compagni
Documentazione/presentazioneassenteminimachiaraefficace ed essenziale

Pesi della valutazione sommativa n. 4: progetto + colloquio = 30% del voto finale.


12. Appendice — i due listati completi di riferimento

Sezione intitolata “12. Appendice — i due listati completi di riferimento”
Mostra 11 — colonna luminosa (keypad + LED + 7 seg + timer in interrupt)
KEYPAD = 0x80
KEYPAD_C = 0x81
LEDS = 0x20
SEG = 0xA0
TIM = 0x70
TIM_C = 0x71
.seg CODE (abs)
.org 0x0010
VTab: .dw servizio ; tabella dei vettori (indirizzo pari)
.org 0x0020
target: .db 0 ; valore digitato (0-15)
conta: .db 0 ; conteggio corrente
.org 0x0100
inizio:
ld sp, 0xFFFF
ld a, 0x10
out (TIM), a ; costante del timer (prova a cambiarla!)
ld a, VTab
out (TIM_C), a ; vettore = byte basso (< 0x80)
ld a, 0x83
out (TIM_C), a ; run + interrupt
ld a, 0
ld i, a ; byte alto della tabella dei vettori
im 2
ei
main:
in a, (KEYPAD)
bit 7, a ; c'e' un tasto nuovo?
jr z, main
and 0x0F ; numero del tasto (0-15)
ld (target), a ; nuovo valore da raggiungere
xor a
ld (conta), a ; si riparte da zero
jr main
servizio:
push af
push hl
ld hl, target
ld a, (conta)
inc a
cp (hl) ; ha superato il valore?
jr c, mostra
jr z, mostra ; lo raggiunge: si ferma qui
xor a ; oltre: riparte da zero
mostra:
ld (conta), a
out (LEDS), a ; la "colonna" sui LED
out (SEG), a ; lo stesso valore sul display
pop hl
pop af
ei
reti
Mostra 12 — pianola (keypad in interrupt + beeper + LCD)
KEYPAD = 0x80
KEYPAD_C = 0x81
BEEPER = 0x60
LCD = 0xD0
MAX = 16 ; lunghezza massima della melodia
.seg CODE (abs)
.org 0x0010
VTab: .dw servizio ; tabella dei vettori (indirizzo pari)
.org 0x0020
tasto: .db 0xFF ; casella: ultimo tasto letto (0xFF = nessuno)
fine: .db 0 ; quanti tasti nella melodia
melodia:.ds MAX ; i tasti suonati
.org 0x0100
inizio:
ld sp, 0xFFFF
ld a, VTab
out (KEYPAD_C), a ; vettore = byte basso (< 0x80)
ld a, 0x83
out (KEYPAD_C), a ; run + interrupt
ld a, 0
ld i, a
im 2
ei
main:
ld a, (tasto)
cp 0xFF
jr z, main ; nessun tasto nuovo: attende
ld b, a
ld a, 0xFF
ld (tasto), a ; consuma il tasto
ld a, b
cp 0x0F
jr z, riproduci ; F = riproduci la melodia
call aggiungi ; salva la nota e la mostra sull'LCD
call nota ; e la suona
jr main
; servizio del keypad: legge il tasto e lo lascia nella casella
servizio:
push af
in a, (KEYPAD) ; la lettura fa da handshake
and 0x0F
ld (tasto), a
pop af
ei
reti
; riproduci: suona tutta la melodia
riproduci:
ld a, (fine)
or a
jr z, main ; non c'e' niente da suonare
ld hl, melodia
ld b, a
ripeti:
ld a, (hl)
push hl
push bc
ld b, a
call nota
pop bc
pop hl
inc hl
djnz ripeti
jr main
; aggiungi: B = tasto (0-15) -> salva in melodia e mostra la cifra sull'LCD
aggiungi:
push af
push hl
push de
ld hl, fine
ld a, (hl)
cp MAX
jr nc, aggiungi_fine ; melodia piena
inc (hl) ; fine = fine + 1
ld e, a
ld d, 0
ld hl, melodia
add hl, de
ld (hl), b ; salva il tasto
ld a, b
call ascii
out (LCD), a ; la cifra sul display
aggiungi_fine:
pop de
pop hl
pop af
ret
; ascii: A = tasto (0-15) -> A = '0'..'F'
ascii:
cp 0x0A
jr c, cifra
add a, 0x37 ; A-F -> 'A'-'F'
ret
cifra:
add a, 0x30 ; 0-9 -> '0'-'9'
ret
; nota: B = tasto (0-15) -> un beep e una pausa (tasti bassi = piu' lunga)
nota:
push bc
push de
push hl
ld a, 1
out (BEEPER), a ; un beep
ld a, 16
sub b ; 16 - tasto: quante "battute" durare
ld l, a
ld h, 0
battuta:
ld de, 0x0600
pausa:
dec de
ld a, d
or e
jr nz, pausa
dec hl
ld a, h
or l
jr nz, battuta
pop hl
pop de
pop bc
ret

  1. Elenca i passi in cui scomporresti la tua proposta, dal più semplice al completo.
  2. Nel tuo schema, chi produce gli eventi: il main (polling) o un device (interrupt)? Perché quella scelta?
  3. Dove sta lo stato condiviso tra main e servizio? Cosa succede se lo metti in un registro?
  4. Scrivi il contratto di una tua subroutine (ingressi, uscite, registri modificati).
  5. Prepara in tre righe il percorso di prova della demo: azioni dell’utente e cosa si deve vedere.

📎 I file .asm di esempi ed esercizi si scaricano dalla pagina Materiali.

  • Compito: completare il progetto e la relazione; preparare la demo di 5 minuti; provare il colloquio leggendo il listato ad alta voce con il compagno.
  • Materiali: esempi 11 e 12 (progetti di riferimento); tracce e rubrica nella pagina “UDA 6 — Progetto finale (verifica n. 4)”; manuale (porte, interrupt, problemi frequenti).
  • Nota per il docente: i due progetti di riferimento sono coperti dai test automatici end-to-end tests/progetto-e2e.test.ts (timer → LED/display con main attivo; keypad → mailbox → LCD/beeper con riproduzione). Se la classe usa il simulatore, il comportamento atteso dei due schemi è già garantito.
  • Prossima tappa: mostra/consegna finale dei progetti e colloqui.