Převodník z pulsní na tónovou volbuKecy úvodemJe to vina K16! Já v podstatě za nic nemůžu. K16 mi věnoval hromadu bordelu na vyhození, mezi jiným i nádherný stařičký černý bakelitový telefon s rotačním voličem. Dneska už téměř historický unikát. Telefon jsem si tedy doma připojil a po domě přes místní ústřednu do vedlejší místnosti s ním telefonoval. Bohužel, VoIP brána, kterou doma máme nepodporuje pulsní volbu, takže jsem se dál nedovolal. Začal jsem tedy hledat řešení. Zjistil jsem, že existují nějaké převodníky, které se vřadí mezi telefon a ústřednu, ale já jsem nechtěl mít zase další krabičku navíc. Chtěl jsem něco pro zabudování přímo do přístroje. A jako správný bastlič jsem dal přednost vlastní výrobě. K nastudování teorie se můžete podívat třeba do wikipedie jako já. Našel jsem na webu i návod na takové udělátko, dokonce s mým oblíbeným procesorem PIC16F84A, mělo to ale chybku. Byl tam jako generátor DTMF použit obvod HT9200A. V GESu jsem si jich mohl objednat 1000 kusů po 9 Kč. Byl by to nádherný kreténský čin - sehnat dalších 999 Kreténů a polokreténů s podobnými přístroji... Ne, nakonec se ukázalo, že by to nebylo tak hrozné - ten obvod byl v jiných webšopech k sehnání tak za dvacku. Jenže poštovné by vyšlo na několikanásobek jeho ceny. Navíc by ten můj výtvor už nebyl originál. HWTakže jsem se rozhodl to celé udělat pouze s mikroprocesorem. Použil jsem již zmíněný PIC16F84A. Na port B jsem navěsil odporovou síť, která tvoří D/A převodník. Za ní je emitorový sledovač, který DTMF signálem přitěžuje linku. Kondenzátor v bázi tranzistoru vyhlazuje schody na generovaném průběhu. Obvod se připojí paralelně na přívod telefonní linky do přístroje. Rotační volič se odpojí a připojí přímo na převodník. Místo kontaktu voliče, který je v klidu seplý vložíme do obvodu telefonu odpor několika stovek ohmů. Jeho hodnotu bude asi dobré zjistit experimentálně. Zjistil jsem, že pobočková ústředna, kterou máme doma dává do linku napětí něco málo přes 20 V a když jsem zvednul sluchátko, ten telefon linku zatížil natolik, že napětí spadlo pod 5 V. To bylo příliš málo na napájení PICu. Odpor jsem zvolil tak, aby na lince při zvednutém sluchátku zůstalo zhruba 12 V. Rotační volič je připojený tak, aby během vytáčení byl trvale sepnutý kontakt mezi D0 a D1 a pulsní spínač k nim ještě připínal D2 (viz. schéma). Paralelně ke kontaktům přerušovače jsem ještě vložil kondanzátor 100 nF - občas se stalo, že obvod díky nějakému tomu zákmitu napočítal omylem o puls víc. Tyto chyby jsem potom ještě brutálně ošetřil v kódu. Mezi bázi tranzistoru a +5 V napájecího napětí jsem při oživování ještě vložil odpor 22k, abych posunul pracovní bod tranzistoru. Jinak by zhruba čtvrtina průběhu chyběla. V zapojení, ze kterého jsem ten konec obkreslil by tranzistor buzený přímo z výstupu HT9200, který zdaleka nemá takový rozkmit signálu - neklesá pod 0,45 VDD, takže se tranzistor nikdy úplně nezavře. Tenhle odpor už jsem dobastlil ze strany spojů. U tohoto projektu jsem to vůbec nějak přehnal s miniaturizací. Zlatý lampy :-) SWČinnost obvodu je možné rozdělit do několika kroků. Po přivedení napájecího napětí je vstup zároveň RA0 v logické jedničce. Vstup RA4 slouží jako vstup časovače a počítá pulsy rotačního voliče. Když skončí vytáčení, spadne vstup RA0 do logické nuly. Procesor podle počtu natočených pulsů nastaví odpovídající kmitočty a na portu B začne generovat DTMF signál. V tuto chvíli obvod běží na energii elektrolytu, dokud se nevybije. Při rychlém sledu vytáčení číslic je logickou jedničkou na RA0 generování přerušeno a obvod se vrátí do režimu počítání pulsů. Dlouho jsem přemýšlel, jak nejlépe vygenerovat směs dvou tónů. Nakonec jsem dospěl k myšlence, že budu tóny sčítat přímo v procesoru a na výstup posílat už hotovou směs. Procesor běží na kmitočtu 8 MHz, vzorkování mi vyšlo 50 kHz. Použil jsem přitom procesor na 4 MHz - kdyby tak šly na dvojnásobek přetaktovat procesory od Intelu! DTMF používá osm tónů. Pro zvolené vzorkování jsem pro každý tón v tabulkovém procesoru spočítal úrovně jednotlivých vzorků pro jednu periodu, pro nižší tóny v rozsahu hodnot 0 až 127, pro vyšší tóny v rozsahu 0 až 128. Rutina, která generuje DTMF signál v každém vzorku přečte z tabulky hodnotu vyššího a nižšího tónu a ty sečte. Výsledkem je tedy hodnota mezi 0 a 255, kterou zapíše na port B. Je jasné, že časování je kritické. Generování výstupního signálu probíhá ve smyčce, která musí mít přesný počet cyklů aby byla dodržena vzorkovací frekvence. Ze začátku jsem měl snahu to dopočítat, ale furt mi to nějak nevycházelo. Tak jsem nakonec vyměknul a doladil to podle osciloskopu. První varianta programu neměla definovanou dobu trvání DTMF tónu. Ta, pokud nebyla předčasně ukončena vytáčením další číslice, byla dána kapacitou elektrolytu na napájecím napětí. Obvod pískal, dokud se kondenzátor nevybil. Tóny byly docela dlouhé. Zrevidoval jsem kód a ve druhé variantě jsem zavedl počítadlo, které definuje dobu trvání na 80 period nižší frekvence, což je přijatelné. Jedním z nejtěžších úkolů bylo dosáhnout vysoké spolehlivosti počítání pulsů. Rotační volič už přeci jen nemá kontakty nové a občas se mi objevil nějaký zákmit, který se mi napočítal a obvod vygeneroval špatný signál. Výše zmíněné kondenzátory pomohly vytvarovat hrany, ale to pořád nestačilo. Občas se objevil zákmit, který spustil generování tónu ještě při natahování voliče. Proto jsem zavedl hlídání hran na vstupu RA0 ve smyčkách. Před začátkem počítání pulsů jsem pak ještě přidal časovou prodlevu potřebnou k ustálení napětí na vstupu, které narůstá pomalu - nabíjí se elektrolyt. Kdo by měl zájem se trochu víc pošťourat ve vzorkování, tomu přikládám tabulku. Zabudování do přístrojeJe potřeba dát pozor na to, aby se propojovací dráty nezapletly do kontaktů voliče. No a tady je zdroják napsaný v MPLABu: ;******************************************************************************** ;* Pulse To DTMF converter * ;* K15 2008 * ;* * ;* pin assignment: * ;* PORTB - D/A converter output * ;* RA0 - dial 1 input - HIGH during dialing * ;* RA4 - dial 2 input - dialing pulses * ;******************************************************************************** __config _HS_OSC & _WDT_OFF & _CP_OFF include p16f84A.inc ;****************************************************************************** ; variables: ;****************************************************************************** LO_C equ 0x0C ; lower tone sample counter HI_C equ 0x0D ; higher sample counter LO_L equ 0x0E ; lower tone last sample address HI_L equ 0x0F ; higher tone last sample address LO_S equ 0x10 ; lower tone number of samples HI_S equ 0x11 ; higher tone number of samples TMP equ 0x12 ; auxiliary variable DUR equ 0x13 ; tone duration counter - LB DUR2 equ 0x14 ; dial startup delay ;****************************************************************************** ; main program: ;****************************************************************************** org 0x0000 bsf STATUS, RP0 ; select bank 1 clrf TRISB ; PORTB is output bsf OPTION_REG, T0CS ; TMR0 driven by RA4 bcf STATUS, RP0 ; select bank 0 INIT: clrf DUR movlw D'100' movwf DUR2 DIAL_BEGIN: decfsz DUR, F goto DIAL_BEGIN decfsz DUR2, F goto DIAL_BEGIN ; eliminate noise clrf TMR0 ; count dialing pulses - wait for RA0 going low: DIAL_END: btfsc PORTA, 0 goto DIAL_END decfsz DUR, F goto DIAL_END ; eliminate noise ; set dtmf tones: clrf PCLATH movf TMR0, W call L_BEGIN movwf LO_L movf TMR0, W call L_LEN movwf LO_S movwf LO_C movf TMR0, W call H_BEGIN movwf HI_L movf TMR0, W call H_LEN movwf HI_S movwf HI_C ; set duration counter: movlw 80 movwf DUR ; update sample counters: BEEP: movf LO_S, W decfsz LO_C, F goto BEEPa movwf LO_C BEEPa: movf HI_S, W decfsz HI_C, F goto BEEPb movwf HI_C ; compute and set output level: BEEPb: movlw 2 movwf PCLATH movf LO_C, W subwf LO_L, W call L_DATA movwf TMP movlw 3 movwf PCLATH movf HI_C, W subwf HI_L, W call H_DATA addwf TMP, W movwf PORTB ; 15 cycles from BEEP so far... + 6 cycles of calls nop nop nop nop decfsz LO_C, W goto BEEPc decfsz DUR, F BEEPc: goto BEEP ; 5 cycles clrf PORTB ; wait for another digit: WAIT: btfss PORTA, 0 goto WAIT decfsz DUR, F goto WAIT ; eliminate noise goto INIT ;****************************************************************************** ; sampling 50 kHz vaweform tables : ;****************************************************************************** radix dec L_BEGIN: addwf PCL, F dt 249, 249, 72, 72, 72, 137, 137, 137, 196, 196, 196, 249, 249, 249 ; 72, 137, 196, 249 L_LEN: addwf PCL, F dt 53, 53, 72, 72, 72, 65, 65, 65, 59, 59, 59, 53, 53, 53 ; 72, 65, 59, 53 H_BEGIN: addwf PCL, F dt 112, 112, 41, 78, 112, 41, 78, 112, 41, 78, 112, 78, 41, 112 ; 143, 143, 143, 143 H_LEN: addwf PCL, F dt 34, 34, 41, 37, 34, 41, 37, 34, 41, 37, 34, 37, 41, 34 ; 31, 31, 31, 31 ;****************************************************************************** ; Low tones: org 0x0200 L_DATA: addwf PCL, F dt 64,69,75,80,85,91,96,100,105,109,113,116,119,122,124,125,126,127,127,127,126,125,123,121,119,116,112,108,104 dt 100,95,90,85,79,74,68,63,57,52,46,41,36,31,26,22,18,14,11,8,5,3,2,0,0,0,0,1,2,4,6,9,12,15,19,23,28,33,38,43,48,54,59 dt 64,70,76,82,88,93,99,104,108,112,116,119,122,124,126,127,127,127,126,125,123,121,118,114,110,106,101,96,90,85 dt 79,73,66,60,54,48,42,36,31,26,21,17,13,9,6,4,2,0,0,0,0,1,3,5,8,11,15,19,24,29,34,40,46,52,58 dt 64,70,77,84,90,96,102,107,112,116,120,123,125,126,127,127,127,125,123,121,117,113,109,104,98,92,86,79,73,66,59 dt 52,46,39,33,27,22,17,12,9,5,3,1,0,0,0,1,3,5,8,12,17,22,27,33,39,45,52,59 dt 64,71,78,86,93,99,105,111,115,119,123,125,127,127,127,126,124,121,118,113,108,103,96,90,83,75,68,60,53,45,38,32 dt 25,19,14,10,6,3,1,0,0,0,2,4,7,11,16,21,27,33,40,48,55 ; High tones: org 0x0300 H_DATA: addwf PCL, F dt 64,74,83,92,101,108,115,120,124,127,128,128,126,123,118,113,106,98,89,80,71,61,51,42,33,25,18,12,7,3,1,0,1,3,6,11,17,25,33,42,51,61 dt 64,75,85,95,104,112,118,123,126,128,128,126,122,116,110,101,92,82,72,61,50,40,30,22,14,8,4,1,0,1,3,8,13,21,29,39,49,59 dt 64,76,87,98,107,115,121,126,128,128,125,121,115,107,97,86,75,63,51,40,29,20,12,6,2,0,0,3,7,14,22,32,42,54 dt 64,77,90,101,111,119,124,127,128,126,121,114,104,93,81,68,55,42,30,20,11,5,1,0,1,6,12,21,31,43,56 end ;****************************************************************************** Když se tak nad tím zamyslím, tak celý tenhle projekt je cvičením na použití tabulek v assembleru... A opravdu už jenom pro úplnost přikládám přeložený kód. Pod čarou: Takto upravený přístroj byste neměli připojovat do JTS. Koneckonců, JTS si ani nezaslouží, aby k ní takovýto unikát byl připojen. | |
P15/1, K15 - prosinec 2006, naposledy aktualizováno: leden 2024 |