; 12 — Progetto di riferimento: "pianola"  (UDA 6, proposta 4)
; Keypad + beeper + LCD, con interrupt del keypad.
;
; Il servizio di interrupt legge il tasto e lo lascia in una "casella" in
; memoria; il programma principale lo aggiunge alla melodia, lo mostra
; sull'LCD e lo suona col beeper (pausa piu' lunga per i tasti bassi).
; Il tasto F riproduce tutta la sequenza.
;
; Porte: keypad 0x80/0x81, beeper 0x60, LCD 0xD0.

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
