Gli standard
Per
l’Italia come per altri paesi europei, l’ European Telecommunications
Standards Institute ha imposto l’adozione del protocollo FSK
(Frequency-shift keying) per la trasmissione del numero del chiamante
(CLI[P]: Caller ID Identifier [Protocol] ). Gli standard di riferimento
sono ETS 200 778-1, ETS 200 778-2, ETS 300 648, ETS 300
659-1, L’
Italia impiega lo standard definito dall’americana Bellcore a livello
trasporto, e due formati di dati relativi al CLIP: Multiple Data
Message Format (MDMF) e Single Data Message Format (SDMF). A
livello analogico, l’ FSK prevede la modulazione di una portante
tramite shift della sua frequenza tra due valori predefiniti, indicanti
i due valori binari che vengono trasmessi ad un rate di 1200 baud:
L’invio
dei dati CLI avviene durante la pausa tra il primo ed il secondo
squillo, a patto di aver abilitato il servizio tramite il proprio
operatore. Il DTMF è usato solo per le interazioni con servizi
telefonici, dopo l’instauro della comunicazione voce, e per via della
sua lentezza non è stato adottato per la trasmissione del CLI
(attenzione ad applicazioni che gesticono il CLIP pubblicate su siti
stranieri basati sulla semplice decodifica del DTMF, magari
decodificato con un MT8870, che non possono assolutamente funzionare in
Italia!). I bit vengono trasmessi a partire dal meno significativo.
Nello schema seguente il dato &egegrave; inviato dopo una treno
di
bit di sincronizzazione, non accompagnato da clock.
Il formato del dato inviato nel
caso SDMF (formato Single Data) è come nel seguente esempio:
(Hex)
04
12
30
39 33 30 31 32 32
34 36 30 39
35
35 35 31 32 31
32 51
Ovvero:
04
|
Message Type: 4=SDMF
|
12
|
Numero di bytes che seguono
esclusa la checksum (dec 18)
|
30 39 33 30
|
“0930”: 30 Settembre in
notazione anglosassone
|
31 32 32 34
|
“1224”: Ore 12 e 24 locali
in notazione H24
|
36 30 39
|
“609”: Area Code
|
35 35 35
|
“555”: Prefisso
|
31 32 31 32
|
“1212”: Numero di telefono
|
51
|
Checksum
|
Caso di chiamate “Private” in
SDMF:
04
09
30
39 33 30 31 32 32
34 50
0E
In
questo caso il numero completo di prefissi è sostituito da una “P” (hex
50). Nel caso di chiamate “Fuori Area” viene invece inviata una “O”
(hex 4F).
Esempio di dato inviato in
formato MDMF (Multiple Data):
(Hex)
80
20
01
08
30
33 32 34 30 39 30 32 07
08
4A
4F 48 4E 20 44 4F 45 02
0A
38
30 30 35 35 35 31 32 31 32 84
80
|
Message Type: 80=MDMF
|
20
|
Numero di bytes che seguono
esclusa la checksum (dec 18)
|
01
|
Data Type:
1=Date&Time
|
08
|
Numero di byte per il campo
Date&Time
|
30 33 32 34
|
“0324”: 24 Marzo in
notazione anglosassone
|
30 39 30 32
|
“0902”: Ore 9 e 02 locali
in notazione H24
|
07
|
Data Type: 7=Name
|
08
|
Numero di byte per il campo
Name
|
4A 4F 48 4E 20 44 4D 45
|
“JOHN DOE”
|
02
|
Data Type: 2=Numero di
telefono
|
0A
|
Numero di byte per il campo
Numero di telefono (dec 10)
|
38 30 30 35 35 35 31
32 31 32
|
8005551212
|
84
|
Checksum
|
I possibili valori per Data Type
sono:
1
- Date & Time
2
- Phone number
4
- Number not present
7
- Name
8
- Name not present
Anche
in questo caso, una chiamata privata è contrassegnata dal carattere “O”
o “P”, come per l’ SDMF. Il Type usato sarà in questo
caso hex 08 per il Nome e hex 04 per in Numero, con lunghezza pari ad 1 .
Caso di chiamate “Private” in
MDMF:
(Hex)
80
10
01
08
30
33 32 34 30 39 30 32 08
01
50
04
01
50
25
La
Checksum che viene inviata è il complemento a 2 della somma dei numeri
precedenti. Calcolando la somma modulo 256 di tutti i valori ricevuti
inclusa la Checksum, dobbiamo ottenere 0 (zero) per convalidare la
bontà della ricezione. Considerando che la ri-trasmissione non è
supportata da questo e da ogni protocollo unidirezionale, i dati sono
da considerare persi se la checksum non è rispettata. In tal
caso
non si procederà alla gestione del rifiuto.
Principio di funzionamento e
caratteristiche del filtro
Dopo
una ricerca, ho acquistato un MT88E39 della Mitel, che converte il
segnale analogico FSK e comunica i dati convertiti in binario ad una
MCU tramite una interfaccia seriale a tre fili. Questo chip può restare
in stand-by assorbendo una frazione di micro-ampere, in assenza di
segnale. Un circuito separato basato su foto accoppiatore rileva lo
squillo di chiamata e risveglia l’MCU dallo stato a basso consumo
(tecnologia Nanowatt di Microchip), che a sua volta attiva il
ricevitore e si prepara all’arrivo dei bit di dati, letti da una
procedura attivata dall’interrupt sul Data Clock. In stand-by, tutto il
circuito deve assorbire una frazione di micro-ampere, consentendo di
sfruttare la tensione di linea per accumulare lentamente
anche un
po’ di energia in più che sarà necessaria per gestire la fase
operativa. Una volta ricevuto lo stream FSK, la presenza di una
numerazione Nascosta o Non disponibile fa impegnare ed immediatamente
disimpegnare la linea. Lo schema della sezione analogica a monte del
chip di ricezione è derivato dalla Application Note della casa
costruttrice. I valori dei componenti sono ottenuti sia da calcoli che
da tentativi empirici. Occorre ridurre il guadagno in modo da evitare
che il rumore venga interpretato come “Portante” dal chip. Questo si
ottiene ruotando il trimmer di sensibilità, in fase di taratura, fino a
far spegnere il led che indica la presenza della portante FSK, ed
andando un po’ oltre. Si può impiegare direttamente una resistenza in
luogo del trimmer, una volta stabilito il valore ottimale. Il
microcontrollore impiegato è un minuscolo ed economico PIC12F683 a 8
PIN Dual-In-Line. Il tutto sta comodamente in una scatolina che va
interposta tra telefono e linea. Nessuna alimentazione è richiesta. Il
condensatore da 2200 uF permette di alimentare PIC e Chip Mitel senza
problemi per il tempo necessario alla gestione del segnale, e fornisce
anche l’energia per la commutazione. L’unica segnalazione è costituita
dai led Verde (Portante) e Rosso che indica il rilevamento ed
il
rifiuto di una numerazione nascosta, con conseguente abbattimento della
chiamata in arrivo. Il segnale FSK viene inviato solo dopo il primo
squillo, che pertanto sentiremo. Peraltro, questo ci avvisa
dell’avvenuto rifiuto. Si potrebbero estendere all’infinito le funzioni
del dispositivo, che diventerebbe “un altro oggetto”, per esempio, una
sorta di “Chi è” evoluto. Si potrebbe anche connettere il telefono solo
dopo il rilevamento del segnale FSK, in modo da evitare anche il primo
squillo. Eccetera… ma lascio a voi le possibili varianti.
Algoritmo
Il programma ha quattro entry
point:
Segue
lo pseudo codice delle procedure e funzioni che compongono il programma
di gestione, eseguito dal microcontrollore. Per chi fosse interessato,
ho creato un programma di simulazione in FreeBasic (http://www.freebasic.net/) scaricabile dal link in fondo alla pagina.
Sempre in fondo alla pagina è
disponibile il sorgente MikroC del programma di gestione.
Funzione CollectBit
Questa
funzione raccoglie il bit dal pin DATA e lo memorizza nella posizione
puntata da BitIdx dell'array DataBit ad 8 posizioni. L'indice viene azzerato nella
procedura di inizializzazione, prima dello Sleep.
DataBit(BitIdx)=GET INPUT DATA;
// Legge il bit
dal pin DATA
BitIdx++;
// Si posiziona al prossimo bit
Funzione CollectByte
Questa funzione memorizza il
byte raccolto e punta al prossimo byte del buffer Data
Data(Idx)=DataBit;
//
Memorizza il byte raccolto
Idx++;
// Si posiziona al prossimo
byte
Funzione ProcessData
La
procedura di gestione dei dati raccolti rileva l’arrivo di una chiamata
anonima e, in questo caso, alza per un breve intervallo di tempo il pin
di output che impegna la linea, interrompendo così la chiamata in
corso. La stringa viene analizzata con un automa a stati, descritto
dalla seguente tabella. Lo stato 0 viene impostato esternamente prima
di chiamare la funzione ProcessData:
Stato corrente
|
Azione
|
Nuovo stato
|
0 (Stato iniziale)
|
ResetData (punta all’inizio
del buffer di lettura)
|
1
|
1 (inizio stringa)
|
MTyp
= GetByte
// Tipo di
messaggio
MLen
= GetByte
// Lunghezza
(esclusa la checksum)
CASE MTyp
Hex
4: SDMF
//
Single Data Message
Hex
80: MDMF
// Multiple Data
Message
ELSE
// Messaggio
sconosciuto
|
2
3
99
|
2 (SDMF)
|
DateTime=GetString (8)
// Data e ora
Number=GetString(MLen-8) //
Numero
|
4
|
3 (MDMF)
|
FTyp = GetByte
//
Tipo di campo
FLen
= GetByte
// Lunghezza del
campo
CASE
FTyp
Hex
1: DateTime = GetString(FLen)
Hex
2: Number = GetString(FLen)
Hex
4: Number = GetString(FLen)
Hex
7: Name = GetString(FLen)
Hex
8: Name = GetString(FLen)
END
CASE
IF
EndData
//
Fine del buffer
ELSE
// Lettura
prossimo campo
|
4
3
|
4
(Analisi)
|
ChkSum=GetByte
// Lettura della Checksum
IF
DataSum MOD 256 = 0
// Checksum OK
AND
Number = “P” or Number = “O” set Rifiuto=1
|
99
|
99 (Fine stringa)
|
IF Rifiuto RifiutaChiamata
RETURN TO CALLER
|
0
|
Funzione ResetData
Questa
funzione posiziona l’indice Idx all’inizio del buffer di lettura,
resetta il cumulo dei byte letti, e azzera la flag di “Abilitazione del
rifiuto” che sarà usata a fine lettura per decidere se riagganciare la
chiamata.
Idx=0;
// Reset dell’
indice all’inizio del dato
Rifiuto=0;
// Reset
flag di abilitazione del rifiuto
DataSum=0;
// Reset
somma dei byte ricevuti
Funzione GetByte
Questa
funzione fornisce al chiamante il prossimo byte del dato raccolto
durante la ricezione, come comunicato dal chip MT88E39. Inoltre,
provvede ad aggiornare la somma dei valori letti, che sarà usata alla
fine della lettura per la verifica della Checksum.
Idx++;
// Punta al prossimo byte di Data
IF
NOT EndData
DataSum = DataSum + Data(Idx);
// Aggiorna la somma dei byte letti (esclusa checksum)
RETURN Data(Idx);
// Torna al chiamante
il byte letto da Data
Funzione GetString(BufLen)
Questa funzione legge da Data il
numero di byte indicato, restituendo il puntatore alla stringa
costruita con i valori letti.
S=””;
// Inizializzazione della stringa statica di appoggio
FOR
(i=Idx; i<=Idx+BufLen; i++) {
// Loop sui byte del buffer
S(i)=GetByte;
//
Raccolta del byte i-esimo
}
RETURN S
Funzione
EndData
Torna True se è stata raggiunta
la fine del buffer dati.
IF Idx >= MLen
THEN
RETURN
True;
// Fine del
buffer Data
ELSE
RETURN
False;
// Fine buffer non
raggiunta
Funzione RifiutaChiamata
Questa
funzione emette un impulso di breve durata sul Pin che pilota
il
relè di impegno linea, abbattendo così la chiamata in corso e
addebitando al chiamante lo scatto alla risposta.
Per
contenere il consumo di corrente, e quindi poter alimentare il tutto
tramite linea telefonica, è bene non emungere non più di 2 mA
dalla stessa, altrimenti la centrale interpreta l’innalzamento di
consumo oltre i 5 mA come un “Impegno linea”, ponendosi in modalità
comunicazione, e quindi abbassa la tensione, emette il tono di linea
libera, ed attende la composizione di un numero telefonico da chiamare.
I componenti scelti e le modalità del loro utilizzo hanno le
caratteristiche utili per ottenere questo scopo.
Il
chip ricevitore MT88E39 e la MCU PIC12F683 restano in modalità basso
consumo fino al sopraggiungere di uno squillo di chiamata, rivelato dal
foto accoppiatore H11G2 (o similari) che alza a livello alto il pin GP5
della MCU, stimolando un Interrupt-On-Change che risveglia il
processore avviando l’algoritmo di gestione. Questo riattiva il
ricevitore della Mitel, e resta in ascolto dei dati che questo comunica
tramite seriale a tre fili (DR, DATA, DCLK) su GP 0-2. L’impegno della
linea avviene attivando il relè a stato solido LH1156. La scelta del
SSR è sempre dettata dalla necessità di consumare poco. In questo caso
la commutazione avviene a fronte di un dispendio di circa 3 mA. Per far
fronte a questo e ad altri picchi di consumo, l' energia è attinta come
detto prima da un condensatore da 2200 uF che si carica dalla linea
tramite una resistenza da 18 Kohm, fino alla tensione di zener, di 5.1
volts. Ovviamente, col trascorrere dei secondi in modalità attiva, la
tensione disponibile inizia a scendere ma, nel breve tempo necessario
per gestire tutta la procedura, resta comunque ben al di sopra delle
tensioni minime di lavoro dei componenti impiegati. Ho questo
dispositivo collegato dal mese di Maggio 2014 sulla mia linea
telefonica ed
ha sempre inesorabilmente punito tutti i chiamanti anonimi! Se avete
altri apparecchi che consumano corrente dalla linea telefonica, occorre
valutare se il sovrappiù di 2 mA porta all'impegno linea col consumo
complessivo. In questo caso dovrete optare per una pila a litio ed una
circuiteria di stabilizzazione. Dato il basso assorbimento, una pila
dovrebbe durare 1-2 anni. Lascio a voi il divertimento di progettare
questa variante. Due led segnalano la ricezione di un dato valido
(Verde) e l'abbattimento della chiamata perchè rilevata come anonima
(Rosso).
Realizzazione
pratica
Avendo
iniziato a progettare hardware e software usando una breadboard, ho
dovuto montare il chip ricevitore su un adattatore SOIP-PDIP. Poi ho
mantenuto questo montaggio anche nel circuito definitivo. Se voleste
riprogettare lo stampato, potreste anche pensare di adottare la
versione SOIP del microcontrollore, per ridurre ulteriormente lo spazio
occupato. Seguono immagini del circuito realizzato ed inscatolato. Si
possono montare due led distinti, come ho fatto io, oppure un led
bicolore. Io ho preferito un codino per la connessione alla linea
telefonica, ma si può montare una presa telefonica da CS. Scaricate dai
link in fondo alla pagina la versione ad alta risoluzione del CS e il
file HEX per programmare il microcontrollore. Ho messo a disposizione
anche l'intero progetto MikroC per chi volesse trarne utili spunti. I
commenti nel codice sono auto-esplicativi per abitudine, essendo un
informatico per professione da alcuni decenni. Sul lato componenti ho
attaccato una stampa su carta adesiva, per facilitare il montaggio.
Links
PDF dello schema elettrico
PDF della lista dei componenti
PDF del Circuito stampato singola
faccia, pronto per l'incisione
PDF del circuito con i componenti
Sorgente
e zipfile del progetto MikroC per il Pic
File HEX per programmare direttamente il
Pic
Simulatore in FB per algoritmo
Datasheet del
ricevitore-convertitore Mitel MT88E39
Datasheet del microcontrollore
PIC12F683
Datasheet del Solid State Relay
LH1156