Il timer possiede un contatore all'indietro che viene decrementato da un clock di frequenza 1.193.180 Hz, corrispondente a un periodo di 838,1 ns. Se il contatore viene inizializzato con un numero N, il conteggio giunge a 0 dopo N x 838,1 ns e il timer porta la sua uscita a 0 dopo di che riprende il conteggio.
Si genera in tal modo un segnale di frequenza 1193180/N Hz.
Sulla scheda del computer è montato un piccolo altoparlante che può ricevere il segnale dall'uscita del timer.
Il programma che segue preleva dalla memoria le durate che determinano il periodo delle note di un brano musicale e le invia in sequenza al contatore del timer.
Nella seguente tabella vengono fornite le frequenza e i corrispondenti conteggi di due ottave di note:
Nota | Frequenza[Hz] | Conteggio in esadecimale |
Do | 261.30 | 11D0 |
Do# | 277.18 | 10D0 |
Re | 293.66 | FDF |
Re# | 311.13 | EFA |
Mi | 329.63 | E23 |
Fa | 349.23 | D58 |
Fa# | 369.99 | C98 |
Sol | 392.00 | BE3 |
Sol# | 415.30 | B39 |
La | 440.00 | A97 |
La# | 466.16 | 9FF |
Si | 493.88 | 96F |
Do | 523.25 | 8E9 |
Do# | 554.37 | 868 |
Re | 587.33 | 7F0 |
Re# | 622.25 | 77D |
Mi | 659.26 | 712 |
Fa | 698.46 | 6AD |
Fa# | 739.99 | 64C |
Sol | 783.99 | 5F3 |
Sol# | 830.61 | 59C |
La | 880.00 | 54B |
La# | 932.33 | 4FF |
Si | 987.77 | 4B8 |
All'indirizzo di I/O 43h si trova il registro di programmazione del timer. Per prima cosa bisogna scrivere, in questo registro, il byte di programmazione 0B6h, poi bisogna inviare in successione due byte all'indirizzo di I/O 42h, che specificano la frequenza da generare. Infine bisogna porre a livello 1 i bit 0 e 1 della porta 61.
offset | Istruzione | Commento |
0100 | MOV DX, 0007 | Il brano è composto da 7 note. |
0103 | MOV SI, 0300 | le note sono memorizzate a partire dall'offset 300 rispetto a DS |
La programmazione del TIMER inizia sempre con la scrittura della "parola di comando" nel suo REGISTRO di COMANDO accessibile attraverso la PORTA 0043H , secondo lo schema: 1 0 1 1 0 1 1 0 corrispondente a 0B6h. Il significato dei bit, nell'ordine da sinistra verso destra è:
10=Canale2 11=lettura/scrittura LSB/MSB 011=Modo 3 0=bin.
offset | Istruzione | Commento |
0106 | MOV AL,B6 | |
0108 | OUT 43,AL |
Nel contatore (a 16 bit) viene scritto un valore che viene decrementato e, quando raggiunge il valore 0, il timer genera un segnale di livello basso; poichè l'accesso al contatore è disponibile attraverso un bus di 8 bit, per scrivere nel registro bisogna fare 2 accessi, prima si scrive la parte bassa e poi la parte alta (come previsto nel byte di programmazione).
offset | Istruzione | Commento |
010A | MOV AL, [SI] | si legge il primo byte della nota |
010C | INC SI | si prepara per leggere il secondo byte |
010D | OUT 42, AL | il primo byte viene scritto nel contatore |
010F | MOV AL, [SI] | si legge il secondo byte della nota |
0111 | INC SI | si prepara per leggere il primo byte della nota successiva |
0112 | OUT 42, AL | il secondo byte della nota viene scritto nel contatore |
0114 | MOV AL, 99 | |
0116 | OUT 63, AL | 99h = 10011001b predispone i port (A: input, B: output, e C: input). |
0118 | MOV AL, 03 | |
011A | OUT 61, AL | Invia un livello alto sui bit 0 e 1 del port B |
011C | CALL 0150 | Genera un ciclo di ritardo |
011F | DEC DX | Conta le note lette |
0120 | JNZ 010A | legge la nota successiva |
0122 | MOV AL, 00 | |
0124 | OUT 61, AL | Invia un livello basso sui bit 0 e 1 del port B |
offset | Istruzione | Commento |
0150 | PUSH AX | salva i registri che verranno modificati dalla routine |
0151 | PUSH BX | |
0152 | PUSH DS | |
0153 | MOV AX, 0040 | |
0156 | MOV DS, AX | Si modifica il registro DS per accedere a un segmento di sistema |
0158 | MOV BX, [006C] | il S.O. incrementa il valore all'indirizzo 0040:006C ogni 54.9 ms |
015C | MOV AX, [006C] | lo si legge in ciclo |
015F | SUB AX, BX | |
0161 | SUB AX, 0005 | dopo 5 incrementi sono trascorsi 54.9x5 ms, la durata della nota. |
0164 | JL 015C | trascorso questo tempo si ripristinano i registri |
0166 | POP DS | |
0167 | POP BX | |
0168 | POP AX | |
0169 | RET |
A partire dall'indirizzo iniziale 0300 inserire i valori per generare le note:
97 0A 6F 09 E9 08 F0 07-12 07 F3 05 E9 08
Simulare la suoneria telefonica: emettere per 5 volte una nota di 320 Hz di durata 25 ms, una nota di 480 Hz di durata 25 ms e una pausa di 2 secondi.
Lo schema a blocchi del dispositivo PPI (Programmable Peripheral Interface) 8255, mostrato a lato, evidenzia il collegamento alla CPU tramite il bus dati e le linee da 2 a 9 del bus indirizzi
.Per indirizzare i dispositivi di I/O si utilizzano solo 10 linee, perchè si presuppone che alla CPU si possano collegare al massimo 1024 periferiche. Nel caso specifico le linee A0 e A1 del bus indirizzi servono a selezionare uno dei quattro registri interni del componente.
Il registro di controllo contiene il byte di programmazione delle porte collegate alle periferiche. I tre registri dati mantengono il byte da scrivere o il byte letto sulle porte A, B e C collegate alle periferiche.
L'indirizzo base del componente è 60h (in cui A1=0 e A0=0) che corrisponde ad indirizzare il registro dati del port A. Come indicato di seguito:
60 (A1=0 e A0=1) Registro dati Port A 61 (A1=0 e A0=1) Registro dati Port B 62 (A1=1 e A0=0) Registro dati Port C 63 (A1=1 e A0=1) Registro Controllo
Il dispositivo PPI 8255 è collegato alla tastiera e al Timer.
In particolare il bit numero 1 del Port A abilita il collegamento tra il Timer e l'altoparlante interno, mentre il bit 0 del port A fornisce il segnale di abilitazione alla sezione numero 2 del timer.
Il Timer 8254 è costituito da 3 contatori programmabili che possono funzionare in modo indipendente l'uno dall'altro. Ciascun contatore riceve lo stesso segnale di clock di frequenza 1,193180 MHz. Pertanto i tre contatori si decrementano alla stessa velocità.
Ciascun contatore quando raggiunge il conteggio 0 emette un livello alto sulla sua uscita di Time Out. I contatori sono programmabili per ripetere il conteggio ciclicamente.
Gli indirizzi assegnati al dispositivo sono:
40h Contatore 0 41h Contatore 1 42h Contatore 2 43h Registro Controllo