Pfc

  • August 2019
  • PDF

This document was uploaded by user and they confirmed that they have the permission to share it. If you are author or own the copyright of this book, please report to us by using this DMCA report form. Report DMCA


Overview

Download & View Pfc as PDF for free.

More details

  • Words: 41,446
  • Pages: 141
ÍNDEX CAPÍTOL 1: Introducció ........................................................................................................... 1 CAPÍTOL 2: Descripció dels elements hardware ...................................................................... 3 2.1. TAS3001C....................................................................................................................... 3 2.2. PIC18F2620 .................................................................................................................... 4 2.3. TLC320AD77C............................................................................................................... 6 2.4. TPA1517 ......................................................................................................................... 7 2.5. TPA152 ........................................................................................................................... 7 2.6. LM317............................................................................................................................. 7 2.7. TLV2264 ......................................................................................................................... 8 CAPÍTOL 3: Fonaments teòrics................................................................................................. 9 3.1. L’EQUALITZADOR ...................................................................................................... 9 3.2. DISSENY DE FILTRES BIQUAD DIGITALS PER L’EQUALITZACIÓ DIGITAL D’ÀUDIO............................................................................................................................... 9 3.2.1. Shelving filters ....................................................................................................... 11 3.2.2. Peaking filters......................................................................................................... 14 3.3. EL BUS I2C .................................................................................................................. 25 3.4. ICD 2 ............................................................................................................................. 28 3.5. LCD INTERFACE........................................................................................................ 30 CAPÍTOL 4: Implementació.................................................................................................... 35 4.1. CONSIDERACIONS I DECISIONS PRÈVIES AL DISSENY .................................. 35 4.2. DISSENY HARDWARE.............................................................................................. 37 4.2.1. Alimentació ............................................................................................................ 38 4.2.2. Front-end ................................................................................................................ 38 4.2.3. Back-end................................................................................................................. 38 4.2.4. Amplificadors de potència ..................................................................................... 39 4.2.5. Convertidor AD/DA............................................................................................... 39 4.2.6. Microcontrolador.................................................................................................... 40 4.2.7. Processador d’àudio ............................................................................................... 40 4.3. DISSENY SOFTWARE ............................................................................................... 41 4.3.1. Inicialització del microcontrolador ........................................................................ 42 4.3.2. Inicialització de les variables ................................................................................. 43 4.3.3. Actualització dels registres del TAS3001 .............................................................. 44 4.3.4. Submenú de volum................................................................................................. 48 4.3.5. Menú equalitzador gràfic ....................................................................................... 50 4.3.6. Menú equalitzador predefinit ................................................................................. 52 4.3.7. Menú equalitzador paramètric................................................................................ 53 4.3.8. Sortida dels submenús............................................................................................ 55 4.3.9. Funcions LCD ........................................................................................................ 55 4.3.10. Funcions I2C ........................................................................................................ 58 CAPÍTOL 5: Conclusions ........................................................................................................ 61 Bibliografia............................................................................................................................... 63 Annexos.................................................................................................................................... 65

CAPÍTOL 1: Introducció

CAPÍTOL 1: Introducció L’objectiu del projecte és realitzar el disseny i el muntatge d’un equalitzador digital d’àudio basat en el circuit integrat TAS3001 de Texas Instruments. L’equalitzador que es dissenyarà, està pensat per a la seva utilització en caixes acústiques autoamplificades, i per aquest motiu, introduirem en el circuit dos amplificadors de potència d’àudio, un per auriculars i un altre per altaveus. El TAS3001 és un processador d’àudio digital d’alta qualitat a un preu econòmic. Per a la seva utilització necessitarem afegir un convertidor analògic/digital i digital/analògic i un microcontrolador que rebrà els senyals de control externs i enviarà la informació necessària al TAS3001 per a la seva configuració. En aquest projecte l’objectiu principal serà aprofitar al màxim les prestacions del TAS3001, malgrat que això, encarirà el preu final del circuit. En les conclusions explicarem possibles modificacions que podríem fer per abaratir el circuit. A continuació es troba una breu explicació del contingut del projecte: - Capítol 2: S’explicaran les característiques principals dels circuits integrats utilitzats en el disseny de l’equalitzador. - Capítol 3: Es donarà la teoria necessària per al disseny del circuit. Primer s’explicaran els mètodes que hi ha per obtenir els coeficients dels filtres biquad. A continuació s’explicarà els diferents protocols i interfícies per la interconnexió dels circuits integrats. - Capítol 4: En aquest capítol explicarem el disseny del circuit. Primer s’explicaran les consideracions prèvies al disseny. A continuació explicarem els blocs que formen el disseny hardware de l’equalitzador. Per acabar, explicarem mitjançant diagrames de blocs sense entrar en gaire detall en el programa el disseny software de l’equalitzador. - Capítol 5: S’exposaran les conclusions i les possibles modificacions del circuit dissenyat. - Annexos: Entrarem en més detall en alguns aspectes del disseny. En els annexos, apareixeran el disseny esquemàtic del circuit, el circuit imprès i el programa utilitzats.

1

CAPÍTOL 2: Descripció dels elements hardware

CAPÍTOL 2: Descripció dels elements hardware 2.1. TAS3001C El TAS3001C és un processador d’àudio digital de 32 bits d’alta qualitat amb unes funcions de processament prefixades. Com podem veure en el diagrama de blocs que hi ha a la figura 2.1, el TAS disposa de quatre blocs de processament del senyal. El primer bloc ens proporciona la possibilitat d’escalar de -∞ a 18dB i mesclar dos senyals estèreo prèviament al processat que s’aplicarà al senyal mesclat. El segon consisteix en un equalitzador paramètric que el formen sis filtres biquadràtics connectats en cascada per cada canal estèreo (sis pel dret i sis per l’esquerre), cada un disposa de cinc coeficients de 24 bits (4.20). El tercer bloc el formen els controls de baixos i aguts (bass and treble) que, a diferència dels filtres biquad el filtrat ha de ser el mateix pel canal dret i l’esquerra i la seva freqüència de tall dependrà de la freqüència de mostreig. Per últim, el quart bloc controla el volum o mute del senyal, en aquest cas, a diferència de l’anterior bloc, el volum pot ser diferent per cada canal.

Figura 2.1: Diagrama de blocs funcional del TAS3001C

El TAS3001 a partir d’un PLL intern genera tots els senyal de rellotge necessaris a partir d’un rellotge exterior de freqüència 256 vegades la freqüència de mostreig. Les freqüències de mostreig suportades pel TAS van des de 32kHz fins 96kHz. En quan a les entrades i sortides disposa d’una entrada de control I2C, que opera en mode estàndard fins una velocitat de 100kbps, per on rep els coeficients necessaris per controlar tots els blocs de processament. També disposa de dues entrades i una sortida digital sèrie. Hi ha deu tipus de formats possibles per aquestes entrades i sortida que són el left-justified, el rightjustified i el I2S tots ells amb una longitud per les dades de 16, 18 o 20 bits amb freqüència de rellotge de 64 vegades la freqüència de mostreig. A més, el mode de 16 bits left-justified també pot funcionar amb una freqüència de rellotge de 32 vegades la freqüència de mostreig. El format de transmissió i el de recepció poden ser diferents. Els senyal de rellotge necessaris per la transmissió i recepció dels senyals sèrie els genera el TAS3001 i disposa de dues sortides amb aquests rellotges per poder proporciona-les a altres components.

3

CAPÍTOL 2: Descripció dels elements hardware

2.2. PIC18F2620 El PIC18F2620 pertany a la família de microcontroladors d’altes prestacions PIC18 de Microchip, les prestacions del qual explicarem a continuació.

CPU: - Execució de fins a 10 MIPS. - Arquitectura RISC (Reduced Instruction Set Computer) optimitzada per al compilador en C mitjançant 8 noves instruccions i un mode d’adreçament indexat (Extended Instruction Set). - Multiplicador hardware 8x8 en un únic cicle. - Arquitectura Harvard (característica genèrica de tots els PIC): Disposa de dos busos d’adreces, un per la memòria de programa i un altre per la memòria de dades per poder accedir de manera simultània a ambdues memòries.

Sistema: - Ofereix deu opcions per a l’oscil·lador. Quatre d’elles utilitzant cristalls o ressonadors ceràmics externs, dos utilitzant rellotges externs, dos amb circuits RC i dos utilitzant els rellotges interns. Disposa d’un oscil·lador intern que pot proveir dos senyals de rellotge, un amb una freqüència fonamental 8MHz i un altre anomenat INTRC que proporciona una freqüència aproximada de 31kHz. El rellotge de 8MHz es pot escalar obtenin rellotges en un marge de freqüències que va de 31kHz a 4MHz. A més, disposa de un PLL multiplicador en freqüència que permet freqüències de rellotge de fins a 40MHz, tan utilitzant l’oscil·lador intern com l’extern. - Fail-Safe Clock Monitor: Mitjançant la monitorització de la font principal de rellotge, si es detecta una fallada d’aquest el sistema passa a utilitzar el rellotge intern permetent que continui en funcionament en baixa velocitat apagant de manera segura la aplicació. - Two-Speed Start-Up: Permet la utilització del rellotge intern fins que el rellotge principal estigui disponible. - Self-Programmability: El dispositiu és capaç d’escriure el seu propi espai de memòria de programa mitjançant un control de software intern. - Temporitzador Whatchdog amb un oscil·lador separat RC. - Ampli rang de tensió d’operació de 2.0V a 5.5V. - Disposa de 64Kbytes (32Kinstruccions) de memòria de programa que permet fins a 100.000 cicles d’esborrat/escriptura. - Disposa de 1Kbyte de memòria EEPROM que permet fins a 1.000.000 cicles d’esborrat/escriptura i és capaç de mantenir les dades més de 40 anys. - Disposa de 3968 bytes de memòria RAM de dades.

nanoWatt Power Managed Modes: - Run, Idle i Sleep modes. - La família de productes PIC18F2525/2620/4525/4620 incorporen una gamma de característiques que redueixen el consum de potència durant el seu funcionament.

Característiques analògiques: - 10 canals de convertidor analògic digital de 10bits amb freqüència de mostreig de 100K mostres per segon. - Mòdul de reset Brown-out programable. - Mòdul de detecció de baixa tensió programable. - Dos mòduls comparadors amb multiplexació d’entrada.

4

CAPÍTOL 2: Descripció dels elements hardware

Perifèrics: - Port sèrie MSSP (Master Synchonous Serial Port): suporta SPI ™ i I2C™ en mode mestre i esclau. - Mòdul EUSART (Enhanced Universal Synchronous Asynchronous Receiver Transmitter) incluent suport al bus LIN (Local Interconnect Network). Suporta RS-485, RS-232 (utilitzant l’oscil·lador intern) i LIN 1.2. - Quatre mòduls temporitzadors. - Dos mòduls CPP (Capture/Compare/PWM (Pulse Width Modulation)).

Figura 2.2: Diagrama de blocs del PIC18F2620

5

CAPÍTOL 2: Descripció dels elements hardware

2.3. TLC320AD77C El TLC320AD77C és un convertidor estèreo analògic-digital digital-analògic de 24 bits delta-sigma dissenyat per aplicacions de consum que necessitin un alt rendiment en la conversió digital del senyal d’àudio a un preu assequible. Permet una gran varietat d’opcions a escollir en quan al format per a l’entrada i sortida sèrie del senyal digital d’àudio. A més permet freqüències de mostreig des dels 16kHz fins als 96kHz. Les seves característiques principals són les següents: - Convertidor ADC i DAC de 24 delta sigma estèreo: Pot transmetre i rebre dades amb una longitud de 16, 20 o 24 bits. Es capaç de treballar amb un ampli rang de freqüències de mostreig, des dels 16kHz fins els 96kHz. El rellotge principal pot ser de 256 o 384 vegades la freqüència de mostreig. Funciona amb una tensió d’alimentació de 3.3V. Posseeix una tensió de referència interna de bandgap. - Convertidor estèreo ADC: La entrada analògica és diferencial. En el mode normal de velocitat té un sobremostreig de 128x. Ofereix altes prestacions ja que té una relació senyal soroll i un marge dinàmic de 100dB. Disposa d’un filtre digital pas alt. - Convertidor estèreo DAC: La sortida analògica és unipolar. En el mode normal de velocitat té un sobremostreig de 128x. Ofereix altes prestacions ja que té una relació senyal soroll i un marge dinàmic de 100dB. - Filtre de De-Emphasis digital: Només per a les freqüències de mostreig de 32kHz, 44.1kHz i 48kHz. - Característiques especials: Proporciona una alta tolerància al Jitter, té bones característiques de fase i proporciona un excel·lent índex de rebuig en l’alimentació.

Figura 2.3: Diagrama de blocs del TLC320AD77C

6

CAPÍTOL 2: Descripció dels elements hardware

2.4. TPA1517 El TPA1517 és un amplificador de potència d’àudio que conté dos amplificadors idèntics capaços d’entregar un nivell de potència mig per canal de 6W amb una distorsió harmònica total (THD+N) del 10% o 5W per un THD+N del 1%. El guany en cada canal és constant i el seu valor és de 20dB. Permet ser alimentat amb un ample marge de tensions que va des dels 9.5V als 18V. Aquest amplificador està disponible en un encapsulat PowerPAD de 20 potes, de muntatge superficial, tèrmicament millorat patentat per Texas Instruments que ens permet reduir l’espai de muntatge en la placa mantenint unes excepcionals característiques tèrmiques.

Figura 2.4: Guany i fase en funció de la freqüència del TPA1517

2.5. TPA152 El TPA152 és un amplificador de potència que és capaç de proporcionar una potència de 75mW per canal per una càrrega de 32Ω amb una distorsió harmònica total de menys d’un 0.1% a 1kHz i de menys del 0.2% per la resta de freqüències en el marge de 20Hz a 20kHz. Per una càrrega de 10kΩ el THD+N és millor que el 0.005% a 1kHz i menys del 0.01% per la resta de freqüències de 20Hz a 20kHz. Es pot utilitzar com a buffer de sortida per a codificadors d’àudio en sistemes de PC. També es recomana utilitzar-lo com amplificador per auriculars o per línies de sortida de altes prestacions. Incorpora un circuit de depop per reduir els transitoris durant la posada en marxa, l’apagada o el mode mute. També incorpora un sistema de protecció tèrmica i contra curtcircuit. El guany de l’amplificador es regula mitjançant dues resistències externes per cada entrada. Lencapsulat és de SOIC de 8 pins de muntatge superficial que redueix espai en la placa i facilita el muntatge automatitzat.

2.6. LM317 El LM317 és un regulador de tensió de tres terminals que és capaç d’entregar un corrent de més de 1.5A per un marge de tensions de sortida que va des de 1.2V a 37V. Es molt fàcil d’utilitzar ja que només cal fixar el valor de dues resistències externes per determinar el valor de la tensió de sortida. A més està encapsulat en encapsulats estàndard de transistors que permet que sigui fàcilment manejable. 7

CAPÍTOL 2: Descripció dels elements hardware

A més d’oferir prestacions superiors als regulador fixes, el LM317 ofereix protecció contra sobrecàrrega de tensió i tèrmica encara que el terminal d’ajust no estigui connectat. El LM317 a més de com a regulador de tensió, també es pot utilitzar per altres funcions com un regulador de sortida programable o com a regulador de corrent si es situa una resistència entre el terminal d’ajust i el de sortida.

2.7. TLV2264 El TLV2264 disposa de quatre amplificadors operacionals de baixa tensió. Els operacionals ofereixen una sortida “rail-to-rail” per incrementar el marge dinàmic tan amb alimentació simple com dividida. El marge de tensions d’alimentació és de 2.7V a 8V. Necessita poca corrent d’alimentació (corrent màxima de 500µA) per poder ser utilitzat en aplicacions on s’alimenta amb batèries però mantenint unes bones prestacions en ac. El seu rendiment en quan a soroll ha estat millorat amb respecte a altres generacions prèvies d’amplificadors ( 12nV / Hz a la freqüència de 1kHz ). El TLV2264 ofereix una alta impedància d’entrada i baix soroll, la qual cosa és beneficiosa per senyals petits d’entrada que provenen de fonts d’alta impedància. Aquest amplificadors són útils en aplicacions com detectors remots o aparells de monitoritzarció de mà. També gràcies a la sortida “rail-to-rail” és de gran utilitat com a interfície amb convertidors analògicdigitals.

8

CAPÍTOL 3: Fonaments teòrics

CAPÍTOL 3: Fonaments teòrics 3.1. L’EQUALITZADOR En el processament d’àudio, l’equalització és el procés de canvi de l’espectre d’un senyal d’àudio. La seva funció consisteix en corregir la deformació freqüencial del senyal deguda al canal pel que viatja aquest i deixar-la idealment com el senyal original. Un exemple de la possible utilització d’un equalitzador seria en un concert en directe en el que s’utilitzen micròfons i altaveus, ja que es pot produir acoblament entre ells. Altres utilitzacions poden ser per exemple per compensar les funcions de transferència no ideals d’uns altaveus o un micròfon. El terme equalitzador, però, s’utilitza també per filtres d’àudio que s’utilitzen per modificar l’espectre del so segons els gustos del usuari. D’aquest tipus d’equalitzadors se’n poden trobar en gairebé en tots els productes d’àudio de consum com ràdio per cotxe, microcadenes hifi o televisors. A diferència d’altres filtres com els pas baix, pas alt o pas banda que atenuen l’espectre per sobre o per sota de la freqüència de tall, els equalitzadors augmenten o disminueixen l’espectre en una banda determinada, sense modificar la resta del espectre. Els filtres utilitzats per als equalitzadors d’àudio són el filtre shelving, tant pas alt com pas baix i el filtre peaking, ja que tenen la propietat que hem dit anteriorment. El disseny d’aquests filtres serà explicat detalladament en els punts 3.2.1 i 3.2.2. Els dos tipus principals de equalitzadors són, l’equalitzador gràfic i l’equalitzador paramètric. L’equalitzador gràfic, és un equalitzador multibanda en el qual es pot variar el guany dels filtres mentre que les freqüències i els amples de banda són fixes. Normalment aquest tipus d’equalitzadors estan formats per controls lliscants, un per cada filtre de manera que les posicions d’aquests controls dibuixen la resposta freqüencial de l’equalitzador. Per això, s’anomena equalitzador gràfic. Als equalitzadors que tenen les mateixes propietats però que tenen controls rotatoris, se’ls anomena equalitzadors rotatoris. Els equalitzador paramètrics també són multibanda, però, a diferencia dels gràfics, en aquests es poden controlar tos els paràmetres dels filtres, l’ample de banda, la freqüència central i el guany. Segons el disseny dels filtres que utilitzem en un equalitzador, els podem classificar en equalitzadors amb Q proporcional o Q constat depenent de si el factor de qualitat varia en funció del guany o no. També es diferencien els equalitzadors segons si la seva resposta és simètrica o no. Els de resposta simètrica, són els que si posem dos filtres amb la mateixa Q, en la mateixa freqüència, però un amb un guany de G dB, i l’altre amb un guany de –G dB, la seva resposta freqüencial equivalent és de 0 dB per totes les freqüències.

3.2. DISSENY DE FILTRES BIQUAD DIGITALS PER L’EQUALITZACIÓ DIGITAL D’ÀUDIO Els filtres biquad són filtres IIR que tenen el numerador i denominador de segon ordre, la funció de transferència dels quals és la següent: b0 b b + 1 z −1 + 2 z −2 b0 + b1 z −1 + b2 z −2 a0 a0 a0 H ( z) = H ( z) = (3.1) (3.2) −1 −2 a a0 + a1 z + a 2 z 1 + 1 z −1 + a2 z −2 a0 a0 Per al disseny d’aquest tipus de filtres s’utilitzen filtres analògics i es transformen mitjançant diferents tècniques en filtres digitals. La transformació més comunament utilitzada 9

CAPÍTOL 3: Fonaments teòrics

és la transformada bilineal, que consisteix en que, partint de la funció de transferència del 1 − z −1 (3.3) obtenim la funció de filtre analògic H(s), aplicant la transformació s = 1 + z −1 transferència del filtre digital. Un punt en z es relaciona amb un únic punt en s i, a més, si el punt de z es troba sobre la circumferència de radi unitat, aquest té com imatge en s un punt amb part real nul·la: − jω ω 1− e 1 − jω1 = j tan 1 = jΩ1 (3.4) z1 = e ⎯ ⎯→ s1 = − jω1 2 1+ e Com a conseqüència obtenim que una component freqüencial Ω en el domini analògic, queda relacionada amb una component freqüencial ω en el domini digital mitjançant la següent expressió: 2πf ω (3.5) on ω = (3.6) Ω = tan 2 FS El principal problema d’aquesta transformació, és la deformació que es produeix al limitar en banda la resposta freqüencial del filtre, especialment en les freqüències més properes a la freqüència de Nyquist (Fs/2), on Fs és la freqüència de mostreig. Mitjançant la fórmula anterior podem preservar alguns paràmetres específics com l’ample de banda o la freqüència de tall entre altres. Malgrat això la resposta freqüencial del filtre digital es deforma considerablement en comparació amb la resposta del filtre analògic. Per aquest motiu no hi ha una solució única per cada tipus de filtre d’àudio. Un cop explicat el funcionament bàsic de la transformada bilineal, ja podem explicar els passos a seguir per calcular els coeficients de la funció de transferència del filtre digital. Primerament partim de la funció de transferència del filtre analògic, a la qual li haurem d’aplicar les condicions necessàries depenent del tipus de filtre (shelving o peaking) per poder obtenir els coeficients d’aquest filtre en funció dels paràmetres que ens interessin, com per exemple l’ample de banda, el factor de qualitat o la freqüència de tall i els guanys en aquestes freqüències. Un cop obtinguts els coeficients ens quedaran en funció dels paràmetres que haurem escollit. Per reduir la deformació que ens produirà la transformació bilineal, haurem de ficar les freqüències analògiques en funció de les freqüències que volem obtenir en el domini digital, aconseguint així, que al aplicar la transformació bilineal, les freqüències característiques en el domini digital siguin les desitjades. Arribat a aquest punt, només cal aplicar la transformació bilineal per obtenir els coeficients del filtre digital. Un altre transformació que, encara que s’utilitza molt menys també trobem a la bibliografia i dona bons resultats, és la transformada z (matched z transform) en la qual la transformació ve donada per la següent fórmula: s+a⎯ ⎯→ 1 − z −1e − aTS (3.7) ( s + a − jb)( s + a + jb) ⎯ ⎯→1 − 2 z −1e − aTS cos(bTS ) + e −2 aTS z −2 (3.8) En aquest cas, no hi ha limitació en banda a la freqüència de Nyquist, però degut al aliasing, aquesta transformada també ens produeix una deformació en la resposta freqüencial del filtre digital a les freqüències properes a la freqüència de Nyquist. A més, es produeix un desplaçament en contínua de la resposta freqüencial (en dB), però com coneixem el guany del filtre a 0Hz aquest problema es pot solucionar fàcilment multiplicant la resposta freqüencial per un factor de escala. En els següents punts analitzarem més detalladament els diferents dissenys que existeixen pels filtres shelving i peaking, i els compararem per escollir quin es el que utilitzarem en el nostre equalitzador.

10

CAPÍTOL 3: Fonaments teòrics

3.2.1. SHELVING FILTERS Hi ha dos tipus de filtres shelving, el pas baix i el pas alt. Aquest filtres tenen la característica de que la seva resposta freqüencial té guany igual a 1 per totes les freqüències excepte en les freqüències superiors (per els pas alt) o inferiors (per els pas baix) a la freqüència de tall ωc. Les funcions de transferència d’aquests filtres en el domini analògic són les següents: s 2 + 2 AΩ C s + A 2 Ω C2 H LF Shelving ( s ) = 2 (3.9) s + 2 BΩ C s + B 2 Ω C2 A 2 s 2 + 2 AΩ C s + Ω C2 H HF Shelving ( s ) = 2 2 (3.10) B s + 2 BΩ C s + Ω C2 El primer que cal fer per dissenyar aquests filtres és aplicar les condicions necessàries per obtenir els valors de A i B en funció de altres paràmetres més útils com són el guany i el guany en la freqüència de tall:

H LF ( e

j0

) = H (1) = 10

G

20 dB

= K

H (e ΩC ) = 10

GB

H HF (e j∞ ) = 10

o

20 dB

G

20 dB

=K

(3.11)

= K B (3.12)

Si apliquem aquestes condicions a les equacions 3.9 i 3.10 obtenim els següent valors per A i B: K ( K B − 1) + K B ( K B − 1) A = B K (3.14) B= (3.13) K 2 − K B2 Un cop obtinguts els valors de A i B només tenim que aplicar la transformació que utilitzarem per calcular els coeficients del filtre digital. El primer mètode utilitzat serà la transformada bilineal i, per tant, haurem d’aplicar l’equació 3.3 a les equacions 3.9 i 3.10. També caldrà predeformar el valor de Ω C segons la equació 3.5 per obtenir el guany K B en la freqüència digital ωc. Els coeficients obtinguts són els següents: ⎛ω ⎞ ⎛ω ⎞ ⎛ω ⎞ ⎛ω ⎞ b0 LF = 1 + 2 A tan ⎜ C ⎟ + A 2 tan 2 ⎜ C ⎟ b0 HF = A 2 + 2 A tan ⎜ C ⎟ + tan 2 ⎜ C ⎟ ⎝ 2 ⎠ ⎝ 2 ⎠ ⎝ 2 ⎠ ⎝ 2 ⎠ b1

LF

b2

LF

a0

LF

a1

LF

a2

LF

⎛ω ⎞ = −2 + 2 A 2 tan 2 ⎜ C ⎟ ⎝ 2 ⎠

b1

HF

⎛ω ⎞ ⎛ω ⎞ = 1 − 2 A tan ⎜ C ⎟ + A 2 tan 2 ⎜ C ⎟ ⎝ 2 ⎠ ⎝ 2 ⎠

b2

HF

⎛ω ⎞ ⎛ω ⎞ = 1 + 2 B tan ⎜ C ⎟ + B 2 tan 2 ⎜ C ⎟ ⎝ 2 ⎠ ⎝ 2 ⎠

a0

HF

⎛ω ⎞ = −2 + 2 B 2 tan 2 ⎜ C ⎟ ⎝ 2 ⎠

a1

HF

⎛ω ⎞ ⎛ω ⎞ = 1 − 2 B tan ⎜ C ⎟ + B 2 tan 2 ⎜ C ⎟ ⎝ 2 ⎠ ⎝ 2 ⎠

a2

HF

(3.15)

⎛ω ⎞ = −2 A 2 + 2 tan 2 ⎜ C ⎟ ⎝ 2 ⎠ ⎛ω ⎞ ⎛ω ⎞ = A 2 − 2 A tan ⎜ C ⎟ + tan 2 ⎜ C ⎟ ⎝ 2 ⎠ ⎝ 2 ⎠ ⎛ω ⎞ ⎛ω ⎞ = B 2 + 2 B tan ⎜ C ⎟ + tan 2 ⎜ C ⎟ ⎝ 2 ⎠ ⎝ 2 ⎠ ⎛ω ⎞ = −2 B 2 + 2 tan 2 ⎜ C ⎟ ⎝ 2 ⎠ ⎛ω ⎞ ⎛ω ⎞ = B 2 − 2 B tan ⎜ C ⎟ + tan 2 ⎜ C ⎟ ⎝ 2 ⎠ ⎝ 2 ⎠ (3.16)

També podem obtenir els coeficients del filtre digital a partir de la transformada z aplicant les equacions 3.7 i 3.8 a les funcions de transferència dels filtres 3.9 i 3.10. Com em dit en el punt 3.2 caldrà aplicar un factor d’escala que hem de multiplicar per la funció de transferència o multiplicar-lo pels coeficients del numerador de la funció de transferència. Els valors de A i B seran els mateixos (3.13 i 3.14) que hem utilitzat en l’altre transformació, ja

11

CAPÍTOL 3: Fonaments teòrics

que aquests els hem calculat al marge de la transformació que se li apliqui després. Els coeficients obtinguts per aquesta transformació són els següents: b 0 HF = SCALE HF b1

b0

LF

= SCALE LF

b1

LF

= SCALE LF − 2e − AΩCTS

b2

LF

= SCALE LF

a0

LF

=1

[ [e

]

LF

= −2e

a2

LF

= (e − BΩCTS ) 2

− AΩ C TS 2

b2

HF

= SCALE

a0

HF

=1

a1

HF

a2 (3.17)

SCALE LF =

[1 − 2e

− AΩ C TS

(

+ e

HF

= −2e

HF

⎡ − ⎛⎜ Ω C ⎢e ⎝ A ⎢⎣

⎤ ⎥ ⎥⎦

2

⎞ ⎟TS ⎠

⎞ ⎟ ⎟ ⎠

2

(3.18) 2

) ] /[1 − 2e

⎛Ω ⎞ −⎜ C ⎟TS ⎝ B ⎠

⎞ ⎟TS ⎠

⎤ ⎥ ⎥⎦

⎛ Ω ⎞ − ⎜ C ⎟TS ⎝ B ⎠

⎛ − ⎛⎜ Ω C = ⎜e ⎝ B ⎜ ⎝

(A / B) − AΩ C TS 2

1 − 2e SCALE HF =

HF

⎞ ⎟TS ⎠

]

− BΩ C TS

a1

HF

= SCALE

⎛ Ω ⎡ −⎜ C ⎢− 2e ⎝ A ⎢⎣

(

− BΩ C TS

⎛ −⎛⎜ ΩC ⎞⎟TS + ⎜e ⎝ B ⎠ ⎜ ⎝

⎞ ⎟ ⎟ ⎠

+ e − BΩCTS

)] 2

(3.19)

2

2

(3.20)

⎛ −⎛⎜ ΩC ⎞⎟TS ⎞ 1 − 2e + ⎜e ⎝ A ⎠ ⎟ ⎜ ⎟ ⎝ ⎠ Un cop dissenyats els dos tipus de filtres només queda comparar-los entre ells. Per veure més clarament les limitacions dels filtres representarem les respostes freqüencials dels filtres per una freqüència de tall elevada: ⎛Ω ⎞ −⎜ C ⎟TS ⎝ A ⎠

12

CAPÍTOL 3: Fonaments teòrics

Figura 3.1: Filtre shelving pas baix amb ωc =2kHz

Figura 3.2: Filtre shelving pas alt amb ωc =8kHz

Si en fixem en el mòdul de la resposta freqüencial del filtre shelving pas baix (Figura 3.2) per les dues transformades utilitzades obtenim respostes molt similars a la del filtre analògic.

13

CAPÍTOL 3: Fonaments teòrics

La transformada bilineal, però, ens dona pitjors resultats que la transformada z a mida que anem pujant la freqüència de tall. Això es degut a que, al aplicar la transformada bilineal els valors dels guanys del filtre analògic a infinit passen a ser els valors dels guanys a les freqüències properes a la freqüència de Nyquist en el filtre digital. Si la freqüència de tall del filtre dissenyat és molt elevada, llavors el valor del guany a les freqüències properes a la freqüència de Nyquist encara no hauria de ser la unitat, però la transformació bilineal, fa que el guany en aquestes freqüències sigui de 0dB, deformant-nos així la resposta freqüencial. En el filtre shelving pas alt, l’efecte de deformació que causa la transformada bilineal per les altes freqüències ens afecta molt més del que ho feia en el filtre pas baix. De fet només podem preservar el guany per la freqüència de tall aplicant l’equació 3.6, però la resta queden deformades al aplicar la transformada bilineal. Amb la transformada z, en canvi obtenim una resposta molt similar a la del filtre analògic per gairebé totes les freqüències. Només es produeix una petita deformació per freqüències molt properes a la freqüència de Nyquist, però la diferència amb el filtre analògic es casi menyspreable i, a més, l’error més gran és a les freqüències més altes les quals gairebé ni són audibles.

3.2.2. PEAKING FILTERS Els filtres peaking són filtres pas banda que tenen un guany igual a 1, excepte en la freqüència central ωc i al seu voltant. La funció de transferència d’aquest filtre en el domini analògic és la següent: s 2 + AΩ C s + Ω C2 (3.21) H peaking ( s ) = 2 s + BΩ C s + Ω C2 Com em dit anteriorment a partir d’aquest filtre digital podem obtenir diferents filtres digitals segons l’elecció de les condicions que escollim en el càlcul del coeficients de la funció de transferència del filtre digital. La major part dels articles que trobem a la hora de dissenyar els filtres peaking, parteixen de les mateixes quatre condicions que són les següents: -El guany en contínua i a la freqüència de Nyquist ha de ser zero dB o equivalent per al filtre analògic si li apliquem la transformada bilineal a partir de la equació 3.5 (el guany a la freqüència de Nyquist del filtre digital és el guany que ha de tenir el filtre analògic en infinit) obtenim les següents condicions: H (e j 0 ) = H (1) = 1 (3.22) H (e j∞ ) = 1 (3.23) -A una determinada freqüència Ω C hi ha d’haver un màxim o mínim segons si el filtre és notch o peak: 2 ∂ ∂ H (e jΩ ) =0 o H (e jΩ ) = 0 (3.24) Ω =ΩC Ω =ΩC ∂Ω ∂Ω -A la mateixa freqüència Ω C el guany ha de ser de G dB: H (e ΩC ) = 10

G

20 dB

=K

(3.25)

A partir d’aquestes quatre condicions es poden derivar diverses solucions, ja que tenim cinc variables. Les diverses solucions que podem obtenir depenen de com es defineix l’ample de banda o el factor de qualitat. En els articles: [2] J. A. Moorer, [3] S. A. White, [4] P. A. Regalia and S. K. Mitra, [6] D. C. Massie podem trobar el disseny dels coeficients a partir de les condicions explicades anteriorment. [7] R. Bristow-Johnson partint de les mateixes quatre condicions proposa expressar l’ample de banda en octaves i compara els diversos sistemes utilitzats en els articles que em enumerat anteriorment obtenint expressions generalitzades per 14

CAPÍTOL 3: Fonaments teòrics

a tots aquests sistemes. Per aquest motiu, a continuació només explicarem el desenvolupament per el càlcul dels coeficients que es segueix en aquest últim article donant les modificacions necessàries que caldria per obtenir els coeficients que ens proposen en els altres articles. Les tres primeres condicions es compleixen de manera directa i la quarta es compleix si A=K·B. La cinquena condició consisteix en que, per dos freqüències el filtre haurà de tindre un guany determinat que anomenarem KB: H (e Ω ) = 10

GB

20 dB

= K B (3.26)

Si es soluciona aquesta equació, s’obtenen dos valors de freqüències que compleixen aquesta condició, un major que la freqüència central i un menor. Com només ens queda una variable pel disseny del filtre, aquesta es calcularà a partir de la diferència d’aquest dos que és l’ample de banda. Un cop ja hem trobat la última variable amb aquesta última condició, ja només cal aplicar la transformada bilineal a la funció de transferència y la equació 3.5 a les freqüències tal com hem explicat en el punt 3.2. La solució genèrica que obtenim per als coeficients, independentment la elecció del guany a les freqüències de tall y de la manera en que s’expressi el ample de banda (octaves, radians/mostra...) és la següent: b0 = 1 + γ K b1 = −2 cos(ω C ) b2 = 1 − γ K

γ a0 = 1 +

(3.27)

K

a1 = −2 cos(ω C ) a2 = 1 − γ

K El paràmetre γ depen de l’ample de banda. A continuació explicarem les diferents eleccions del ample de banda pels articles que, mencionats anteriorment, donarem el valor de γ per cada un dels casos: - En el mètode de [2] J. A. Moorer es defineix l’ample de banda com la diferència entre les dues freqüències en radians normalitzades en les que el guany es K B.

K B2 − 1 ⎛ BW ⎞ tan⎜ ⎟ (3.28) 2 2 K − KB ⎝ 2 ⎠ - En [4] P. A. Regalia and S. K. Mitra i [6] D. C. Massie l’ample de banda es defineix per una KB fixa i el valor de γ es pot calcular amb la fórmula anterior substituint

γ = K

K B = 1 2 K 2 − 1 . El valor de γ obtingut és el següent: ⎛ BW ⎞ ⎟ (3.29) ⎝ 2 ⎠ - En el mètode de [3] S. A. White es defineix l’ample de banda com la diferència de les freqüències normalitzades en que el guany és 3dB per als filtres de realçament (boost) o − 3dB per als filtres atenuadors (cut). El valor que obtenim per γ és:

γ = K tan⎜

15

CAPÍTOL 3: Fonaments teòrics

Figura 3.3: Característiques dels filtres de [3] S. A. White

⎧ K2 −2 K> 2 K ⎪⎪ ⎛ BW ⎞ 2 K< 12 γ = (3.30) tan ⎜ ⎟ on P = ⎨ 1 − 2 K P 2 ⎝ ⎠ ⎪ indefinit 126dB o el guany es divideix per dos (GB=G/2) en el cas en que 0G>-6dB. A continuació en la figura 3.4 es mostra el mòdul de la resposta freqüencial per aquest filtre amb un ample de banda d’una octava comparat amb el filtre analògic:

16

CAPÍTOL 3: Fonaments teòrics

Figura 3.4: Filtre peaking a 1kHz i 15kHz preservant BW

Com podem veure en la figura 3.4, el filtre es comporta correctament per baixes freqüències però a mida que anem pujant la freqüència central del filtre aquest es deforma de manera considerable degut a la transformada bilineal. Per freqüències centrals elevades en el filtre analògic, el guany a la freqüència de Nyquist és molt superior a zero, mentre que en filtre digital el guany a aquesta freqüència ha de ser zero (ja que és el mateix que té el filtre analògic en infinit). Això fa que la freqüència de tall superior del filtre digital sigui inferior a la del analògic i que com en les condicions que hem aplicat fem que es mantingui l’ample de banda, la freqüència de tall inferior del filtre digital també és inferior a la del filtre analògic produint-se la deformació que observem en la gràfica. Una possible variació que es pot fer al dissenyar el filtre, és mantenir la freqüència de tall inferior en lloc de l’ample de banda. Aquesta manera de dissenyar el filtre la trobem en [5] D. J. Shpak i l’analitzarem a continuació. Per al disseny del següent filtre, les quatre primeres condicions seran les mateixes que en el filtre anterior i la cinquena també amb la diferència que en aquest cas en lloc d’aplicar-la per les dos freqüències i fer que es mantingui l’ample de banda, només l’aplicarem per la freqüència de tall inferior fent que es mantingui després d’aplicar la transformada bilineal. H (e Ω1 ) = 10

GB

20 dB

= K B (3.32)

Les quatre primeres condicions es compleixen igual que en el filtre anterior per A=K·B. Si apliquem la cinquena condició (equació 3.32) obtenim el valor de B per qualsevol valor de KB:

B=

(Ω

2 C

− Ω12

) (K 2

2 B

Ω C Ω1 K 2 − K B2

17

)

−1

(3.33)

CAPÍTOL 3: Fonaments teòrics

Cal recordar, que en la fórmula anterior caldrà aplicar la fórmula 3.5 Per obtenir els valors de freqüència analògica en funció de la digital. Un cop tenim el valor de A i B només cal aplicar la transformada bilineal tal com hem fet en el cas anterior i d’aquesta manera obtenim els següents coeficients per aquest nou disseny del filtre: ⎛ω ⎞ ⎛ω ⎞ b0 = 1 + tan 2 ⎜ C ⎟ + B tan⎜ C ⎟ ⎝ 2 ⎠ ⎝ 2 ⎠

⎛ ⎛ω ⎞ ⎞ b1 = 2⎜⎜ tan 2 ⎜ C ⎟ − 1⎟⎟ ⎝ 2 ⎠ ⎠ ⎝ ⎛ω ⎞ ⎛ω ⎞ b2 = 1 + tan 2 ⎜ C ⎟ − B tan⎜ C ⎟ ⎝ 2 ⎠ ⎝ 2 ⎠ ⎛ω ⎞ 2⎛ω ⎞ a 0 = 1 + tan ⎜ C ⎟ + A tan⎜ C ⎟ ⎝ 2 ⎠ ⎝ 2 ⎠

(3.34)

⎛ ⎛ω ⎞ ⎞ a1 = 2⎜⎜ tan 2 ⎜ C ⎟ − 1⎟⎟ ⎝ 2 ⎠ ⎠ ⎝ ⎛ω ⎞ ⎛ω ⎞ a 2 = 1 + tan 2 ⎜ C ⎟ − A tan⎜ C ⎟ ⎝ 2 ⎠ ⎝ 2 ⎠ A continuació, en la figura 3.5 mostrem una gràfica del mòdul de la resposta freqüencial del filtre utilitzant els coeficients que acabem de calcular. En la representació utilitzarem els mateixos paràmetres de definició de ample de banda, el mateix ample de banda i les mateixes freqüències centrals per poder comparar-los millor entre ells.

Figura 3.5: Filtre peaking a 1kHz i 15kHz preservant ω1

Com podem veure en la figura 3.5, el mòdul de la resposta freqüencial per als filtres amb freqüència central elevada és més similar al del filtre analògic que en el primer cas per a 18

CAPÍTOL 3: Fonaments teòrics

freqüències inferiors a la freqüència central. Per a freqüències superiors, però, el primer filtre es comportava millor, però com que les freqüències més altes són les menys audibles podem considerar que en general la resposta del segon filtre ens proporciona millors resultats. A part del filtre de [5] D. J. Shpak que acabem de veure, hi ha un altre tipus de filtre alternatiu al primer disseny que és el que proposa [8] S. J. Orfanidis. La idea bàsica de aquest nou filtre és modificar el filtre analògic per fer que aquest tingui un guany no nul quan s=∞, d’aquesta manera aconseguim que el filtre digital tingui el guany que vulguem en la freqüència de Nyquist que serà el guany que té el filtre analògic original a aquesta freqüència. La funció de transferència del filtre analògic del qual partirem per dissenyar els coeficients d’aquest nou filtre és el següent: K s 2 + Bs + K 0W 2 H (s) = 1 2 (3.35) s + As + W 2 A partir d’aquest filtre veiem que dos condicions es compleixen de manera immediata: per s=0 el guany és K0 i per s=∞ el guany és K1. Les tres condicions restants són les mateixes que en el primer filtre i són les equacions 3.24, 3.25 i 3.26. Com em fet en els casos anteriors, el primer que cal fer és aplicar les condicions a la funció de transferència 3.35 i d’aquesta manera s’obtenen els següents valors per W, B i A:

W2 =

K 2 − K 12 2 Ω0 , K 2 − K 02

C+D

A=

K 2 − K B2

B=

,

K 2 C − K B2 D K 2 − K B2

(3.36)

En [8] S. J. Orfanidis es preserva l’ample de banda per tant la condició 3.26 s’aplica a la freqüència de tall superior i inferior i com no és possible preservar les dos freqüències de tall ja que hi ha tres variables (W,A,B) i tres condicions, es calculen les variables en funció de la diferència de les dues, l’ample de banda. D’aquesta manera els paràmetres C i D ens queden en funció de la freqüència central i de l’ample de banda segons les següents expressions:

(

(K − K )(K )(K − K ))

C = (∆Ω ) K B2 − K 12 − 2W 2 K B2 − K 0 K 1 − 2

D = 2W

2

(K

2

− K 0 K1 −

(K

2

−K

2 0

2

2 B

2 1

2 0

2 B

− K 12

))

(3.37)

Per tal de reduir l’efecte de deformació que ens produeix la transformada bilineal igual que en els casos anteriors, haurem d’aplicar la fórmula 3.5 per obtenir les expressions de Ω0 i de l’ample de banda que són les següents: ⎛ K B2 − K 02 K 2 − K 12 2 ⎞⎟ ⎛ ∆ω ⎞ ⎛ω ⎞ Ω 0 = tan⎜ 0 ⎟ , ∆ω = ⎜1 + Ω 0 tan⎜ ⎟ (3.38) 2 2 2 2 ⎜ ⎟ ⎝ 2 ⎠ K K K K − − ⎝ 2 ⎠ B 1 0 ⎝ ⎠ Arribat a aquest punt, ja només resta aplicar la transformada bilineal per obtenir els coeficients del filtre digital que són els següents: b0 = K 1 + K 0W 2 + B

b1 = −2( K 1 − K 0W 2 ) b2 = K 1 + K 0W 2 − B 2 a0 = 1 + W + A

(3.39)

a1 = −2(1 − W 2 ) a2 = 1 + W 2 − A Totes les fórmules anteriors del filtre de [8] S. J. Orfanidis han estat calculats per valors genèrics de K0, K1 i KB. Aquests valors de guany hauran de ser els mateixos que en el filtre analògic original 3.21. Per tan, el guany en contínua K0 haurà de ser zero dB, el guany a les freqüències de tall serà el mateix que hem utilitzat en els altres filtres per poder comparar-los i

19

CAPÍTOL 3: Fonaments teòrics

el guany a la freqüència de Nyquist l’haurem de calcular a partir del mòdul de la resposta freqüencial que obtenim a partir de la fórmula 3.21. El valor del guany a la freqüència de Nyquist ens quedarà en funció de A i B que els haurem de calcular amb les mateixes condicions 3.24 i 3.26 (Cal recordar que no són els mateixos valors que hem obtingut anteriorment ja que aquells estaven calculats amb el filtre analògic modificat). Un cop calculat el valor de K1 si a més li apliquem l’equació 3.38 obtenim el següent valor: K 2π 2 (∆ω ) 2 ( K B2 − K 02 ) K 02 (ω 02 − π ) 2 + K 2 − K B2 2 K1 = (3.40) π 2 (∆ω ) 2 ( K B2 − K 02 ) 2 2 (ω 0 − π ) + K 2 − K B2 Un cop hem trobat tots els valors de tots els coeficients ja podem representar el mòdul de la resposta freqüencial que és a continuació:

Figura 3.6: Filtre peaking a 1kHz i 15kHz preservant BW i freqüència de Nyquist

Com podem observar en la figura 3.6 el mòdul de la resposta freqüencial es deforma molt menys en les freqüències properes a la de Nyquist degut a la preservació del guany a aquesta freqüència tan si la comparem amb el primer cas com amb el segon. Per un altre banda, en les freqüències que estan per sota de la freqüència central el filtre [5] D. J. Shpak, que mantenia la freqüència de tall inferior, tenia una resposta més similar a la del filtre analògic. Malgrat que el filtre de [8] S. J. Orfanidis ens dona molt bons resultats en gairebé totes les freqüències, per filtres amb freqüències centrals molt properes a la freqüència de Nyquist amb amples de banda considerablement grans, aquest es deforma força. La deformació del filtre es produeix quan el guany a la freqüència de tall superior, és menor al guany a la freqüència de Nyquist. Aquest error també es produïa en [7] R. Bristow-Johnson. En la figura 3.7 es pot veure clarament la deformació que acabem de descriure:

20

CAPÍTOL 3: Fonaments teòrics

Figura 3.7: Filtre peaking a 16kHz preservant BW=2octaves i freqüència de Nyquist

Com hem vist anteriorment en el segon filtre, que preservava la freqüència de tall superior, és el que ens donava millors resultats per freqüències inferiors a la freqüència central, mentre que aquest últim que preservava el guany a la freqüència de Nyquist ens dona millors resultats per a freqüències superiors. A més, degut a la condició de preservar l’ample de banda per a certs casos com el de la figura anterior tenim problemes. Per totes aquestes raons sembla raonable modificar el filtre de [8] S. J. Orfanidis per mantenir la freqüència de tall inferior com fèiem en el filtre de [5] D. J. Shpak. Per fer aquesta modificació, només cal aplicar la última condició (3.26) al filtre analògic (3.35) per obtenir el nou valor de A. Com el valor de B depèn de A aquest també l’haurem de modificar mentre que els valors de W i D seran els mateixos i no utilitzarem la C ja que s’obtenia a partir d’aplicar la darrera condició. Si realitzem els càlculs necessaris els valors que obtenim per A i B són els següents: K 2 (Ω 2 − W 2 ) 2 − ( K 1Ω12 − K 0W 2 ) 2 + DΩ12 A2 = B 1 , B 2 = − D + K 2 A 2 (3.41) 2 2 2 ( K − K B )Ω 1 Com és normal, a la freqüència de tall inferior també li haurem d’aplicar la correcció segons la fórmula 3.5. Els valors dels guanys també seran els mateixos que en el cas anterior. Els coeficients 3.39 tampoc varien ja que aquests els hem calculat aplicant la transformada bilineal al filtre analògic modificat sense tenir en compte si manteníem la freqüència de tall o l’ample de banda. Si recalculem els coeficients amb els nous valors de A i B obtenim les següents gràfiques:

21

CAPÍTOL 3: Fonaments teòrics

Figura 3.8: Filtre peaking a 1kHz i 15kHz preservant ω1 i freqüència de Nyquist

Com podem observar en la figura 3.8 aquest últim filtre dissenyat és el que ens proporciona el mòdul de la resposta freqüencial més similar al filtre analògic. A més el filtre funciona correctament per a tots els valors de freqüències centrals possibles i per tots els amples de banda, no com l’anterior. Com a conclusió podríem dir que dels filtres que es poden dissenyar a partir de la transformada bilineal, els que preserven el guany a la freqüència de Nyquist tenen una resposta més similar al filtre analògic tant preservant l’ample de banda com la freqüència de tall. Si a més, el fet de que es mantingui l’ample de banda no és rellevant, l’últim filtre és el més similar. Per tal de poder comparar els errors que es produeixen (en dB) en cada un dels casos que hem exposat respecte al filtre analògic a continuació en la figura 3.9 es mostra una gràfica de la diferencia del mòdul entre cada un dels filtres i el filtre analògic:

22

CAPÍTOL 3: Fonaments teòrics

Figura 3.9: Error en filtre peaking a 16kHz amb ample de banda de una octava

Igual que hem fet en els filtres de shelving, els peaking també es poden transformar en digital mitjançant la transformada z. En l’article de [9] J. R. Clark, E. C. Ifeachor, G. M. Rogers, P. W. J. and Van Eelvelt aquesta és la tècnica que proposen com la que dona millors resultats, però en realitat, amb el nou sistema que acabem de proposar anteriorment, modificat el filtre de Orfanidis per mantenir la freqüència de tall inferior, obtenim filtres més similars al ideal per les freqüencies centrals més properes a la freqüència de Nyquist amb amples de banda considerablement elevats. Malgrat que els resultats que obtindrem no seran millors, a continuació explicarem també aquesta sistema per acabar de mostrar totes les possibilitats que tenim en el disseny dels filtres digital de àudio en aquest document. El primer que haurem de fer, com en els casos anteriors, és aplicar les cinc condicions al filtre analògic (3.21) per obtenir els valors de A i de B. A continuació apliquem les fórmules 3.7 i 3.8 corresponents a la transformada z al mateix filtre i obtenim els coeficients del filtre digital. Igual que em fet en el disseny dels filtres shelving s’haurà de calcular el factor de escala, que és el guany que hi ha freqüència zero en el filtre quan encara no se l’hi ha multiplicat aquest factor. Cal recordar que en aquesta transformada no cal aplicar la predeformació de les freqüències, per aquest motiu els coeficients ens quedaran en funció de les freqüències analògiques que són les digitals multiplicades per la freqüència de mostreig. Després de seguir tots aquets passos que acabem d’explicar els coeficients ens queden de la següent manera:

B=

K B2 − K 02 ∆Ω , K 2 − K B2

A = GB

23

(3.42)

CAPÍTOL 3: Fonaments teòrics

b 0 = SCALE

[

b1 = SCALE − 2 e − ( A Ω C / 2 ) TS cos( Ω C2 − ( A Ω C / 2 ) 2 T S )

[

b 2 = SCALE e − ( A Ω C / 2 ) TS

]

]

2

(3.43)

a0 = 1 a1 = − 2 e − ( B Ω C / 2 ) TS cos( Ω C2 − ( B Ω C / 2 ) 2 T S ) a 2 = ( e − ( B Ω C / 2 ) TS ) 2 SCALE LF =

( / 2) T ) + (e

1 − 2e − ( BΩC / 2 )TS cos( Ω C2 − ( BΩ C / 2) 2 TS ) + e − ( BΩC / 2)TS

) )

2 2

(3.44)

− ( AΩ C / 2 )TS 2 1 − 2e −( AΩC / 2)TS cos( Ω C2 − ( AΩ C S A partir d’aquests coeficients ja podem obtenir la gràfica del mòdul de la resposta freqüencial:

Figura 3.10: Filtre peaking a 1kHz i 15kHz amb transformada MZT

Com podem veure en la figura 3.10, el filtre com en els altres casos funciona correctament per les freqüències més baixes, mentre que per freqüències altes i amples de banda grans, es produeix una distorsió considerable. En aquest cas la distorsió és diferent, ja que en els altres manteníem el guany a la freqüència central mentre que amb el disseny dels coeficients a partir de la transformada MZT la distorsió consisteix en un increment de guany en la freqüència central. Aquest increment de guany podria produir un efecte de cliping. En el article de [9] J. R. Clark es proposen dues solucions per millorar aquest filtre de les quals aquí només n’explicarem una. Si s’observa la distorsió del filtre de la figura 3.15 i es compara amb la distorsió dels filtre de [5] D. J. Shpak en el que es predistorsiona el valor de F i de Q es pot veure que els dos sistemes tenen distorsions oposades a freqüències properes a la de Nyquist. Per aquest motiu, es proposa fer el promig dels dos filtres que s’aconsegueix simplement 24

CAPÍTOL 3: Fonaments teòrics

promitjant els coeficients dels dos sintemes. El resultat obtingut el podem observar en la figura 3.11 en la que observem que la resposta freqüencial és força propera a la ideal, però per alguns casos en que la freqüència central és molt propera a la freqüència de Nyquist aquest es deforma donant pitjors resultats que el filtre de Orfanidis modificat.

Figura 3.11: Filtre peaking a 1kHz i 15kHz amb promig MZT/BZT

3.3. EL BUS I2C En la realització de diversos tipus de dissenys tan en l’àmbit de les telecomunicacions com l’electrònica de consum o l’electrònica industrial, es troben diverses similituds entre ells. Gairebé tots els sistemes es composen de un dispositiu intel·ligent de control com un microcontrolador, i aquest està envoltat d’altres circuits com per exemple memòries EEPROM, RAM, dispositius LCD o convertidors de dates entre altres i tots han d’anar connectats entre ells. Aprofitant aquestes similituds, amb l’intenció de beneficiar a dissenyadors i fabricants, a més de maximitzar l’eficiència hardware i simplificar els circuits, Philips va dissenyar un bus bidireccional de només dos fils per al control entre circuits integrats anomenat bus I2C (Inter-Integrated Circuit). Les principals característiques del bus I2C són les següents: - Només necessita dues línies, la primera s’anomena SDA (Serial Data Line) i s’utilitza per a la transmissió sèrie de dades i la segona és el rellotge sèrie SCL (Serial Clock Line). - Cada dispositiu que està connectat a al bus disposa de una única adreça. Els dispositius que actuen com a master poden ser transmissors o receptors. - Està pensat per a la transmissió bidireccional sèrie de paraules de buit bits amb una velocitat de fins a 100kbit/s en el mode Standard-mode, fins a 400kbit/s en Fast-mode i fins a 3.4Mbit/s en el mode High-speed mode. - El chip conté un filtre per eliminar pics de tensió per poder preservar les dades.

25

CAPÍTOL 3: Fonaments teòrics

- El nombre de circuits integrats que podem connectar al bus està limitat per la capacitat màxima de 400pF.

Figura 3.12: Exemple connexió de ICs amb el bus I2C

El bus I2C va ser creat a principis dels anys 80 amb una velocitat de transmissió de 100kbit/s i 7 bits d’adreçament. La primera versió de les especificacions és de l’any 1992 i introdueix alguna millora respecte al original. A partir d’aquesta van aparèixer dos versions més, la versió 2.0 al any 1998 i la 2.1 al any 2000. A continuació descriurem resumidament les millores que oferia cada versió: - Versió 1.0: S’elimina la programació software de l’adreça dels dispositius esclaus i el mode de funcionament low-speed mode. S’afegeix el mode Fast-mode que permet una velocitat de transmissió de fins a 4kbit/s. També s’incorpora l’adreçament de 10 bits que fa possible l’adreçament de 1024 esclaus addicionals. - Versió 2.0: S’incrementa la velocitat de transmissió fins a 3.4Mbit/s amb el mode Highspeed mode. A més s’afegeixen diverses modificacions per poder connectar amb el bus I2C circuits integrats amb diferent tensions d’alimentació. - Versió 2.1: Només afegeix petites modificacions per al mode High-speed. Com hem dit anteriorment en el bus I2C hi pot haver més d’un dispositiu que actui com a mestre i aquests poden tant transmetre com rebre dades. També hi ha diversos tipus de modes de funcionament amb diferents velocitats de transmissió i adreçament de 7 o 10 bits. Com podem veure les especificacions genèriques per a totes aquestes possibilitats poden ser molt extenses. Per aquest motiu, en aquest punt només explicarem el necessari per poder utilitzar el bus I2C amb el TAS3001 que és el que ens limita el seu ús. La configuració del PIC, necessària per adaptar-se a les limitacions del TAS3001 l’explicarem en el punt 4.3. En el TAS3001 el bus I2C només s’utilitza per enviar-li els valors dels registres que controlen el volum, bass, treble, mesclador i els coeficients dels filtres. Per tant, només pot ser esclau i només pot rebre dades. A més utilitza el mode estàndard i, per tant, la velocitat màxima a la que se li poden enviar dades és de 100kbit/s i la seva adreça serà de 7 bits. Les entrades SDA i SCL són drenador obert i per tant han d’anar connectades amb resistències de pull-up. Una particularitat del TAS3001 que hem de tenir en compte és que abans de fer reset manté les línies SDA i SCL a nivell baix i pot provocar errors amb altres dispositius que intentin utilitzar el bus abans del reset. En el nostre cas, com en els dos únics dispositius que utilitzen el bus I2C són el PIC18F2620 com a mestre i el TAS3001 com esclau i el PIC també serà l’encarregat d’enviar-li el senyal de reset al TAS3001, només cal tenir-ho en compte a l’hora de programar el PIC i enviar el senyal de reset abans de començar a utilitzar el bus I2C. Per a començar la transmissió de dades el primer que cal, és que el dispositiu mestre generi el senyal de START que ho fa mitjançat una transició de nivell alt a baix de la línea SDA mentre la línea SCL es manté a nivell alt. Un cop finalitzada la condició de START, el mestre genera el senyal de rellotge per SCL i per SDA transmet els primers 8 bits. Els set primers són els corresponents a la adreça del dispositiu esclau amb el que es vòl comunicar i el vuitè ha de ser igual a 1 si el mestre vòl rebre dades (read) o igual a 0 si vòl transmetre’n (write). Quan ja s’han transmès els vuit bits

26

CAPÍTOL 3: Fonaments teòrics

el dispositiu esclau ha de generar un senyal de confirmació (acknowledge) que consisteix en ficar a nivell baix la línia SDA en el següent període del rellotge. Al rebre el senyal de confirmació el mestre ja pot començar a transmetre els següent byte de dades de la mateixa manera que ho ha fet al enviar l’adreça. En el cas particular del TAS3001 aquest segon byte que se l’hi ha d’enviar es correspon a la subadreça del registre que volem actualitzar. Hi un registre de control anomenat MCR, els de bass, treble i volum, dos pels mescladors i un per cada filtre biquad. El número de bytes que enviarem després de la subadreça depèn del registre que es vulgui actualitzar. Després de cada byte enviat el master ha d’esperar que el esclau generi el senyal de confirmació. Després de haver enviat totes les dades necessàries per al registre que es vulgui actualitzar, el master haurà de generar la condició de STOP que consisteix en mantindre el senyal de rellotge a nivell alt mentre es fa una transició de nivell baix a alt en la línea de dades SDA. A continuació en la figura 3.13 es pot observar una seqüència de transmissió completa pel bus I2C:

Figura 3.13: Seqüència de transmissió de dades pel bus I2C

Cal assegurar-se en la programació del PIC, que per cada subadreça a continuació s’envien tots els bytes necessaris de dades per no produir errors en el processador d’àudio. Per exemple, si enviem l’adreça de registre 04h que és el del volum, a continuació caldrà enviar sis bytes. En el cas de que succeís algun error, per tal de resetejar la interfície I2C del TAS3001, cal enviar a la subadreça 00h 16 bytes iguals a zero per tornar a un estat conegut. El TAS3001 emet dos tipus d’estats d’espera. El primer tipus són de curta durada, aproximadament 25µs, i els genera després d’enviar els senyals de acknowledge quan ha rebut bytes de dades. No es generen aquests estats d’espera després de la recepció de la adreça del dispositiu ni la del registre. En la figura següent podem veure clarament quan es generen aquests estats d’espera: Figura 3.14: Exemple de cicles d’espera en el bus I2C

El segon tipus d’estat d’espera només es genera després de modificar els registres de volum i to (treble i bass). Aquest temps d’espera són necessaris perquè el TAS3001 executa algoritmes de interpolació per a l’actualització dels nous valors de volum, bass i treble. L’intèrval de temps necessari per actualitzar el volum amb una freqüència de mostreig de 44kHz és de 41ms i per l’actualització dels filtres de to depèn del salt que es produeixi. En el pitjor cas en que es produeixi una transició de 18dB a -18dB el temps d’espera pot arribar a ser de fins a 153ms. Aquest cicle d’espera, no es produeix durant la instrucció de canvi del volum o to, sinó que es produeix en la següent instrucció després d’enviar el acknowledge del primer byte de dades rebut. Si no es tenen en compte aquest estats d’espera i s’enviés una senyal de stop durant aquest cicle d’espera el bloc I2C del TAS3001 quedaria en un estat desconegut que fins i tot podria causar que enviés dades incorrectes al bloc de processament. Durant els cicles d’espera que hem explicat anteriorment el TAS3001 manté la línea SCL a nivell baix. Si el master està preparat per aquest temps d’espera monitoritza la línea SCL fins que l’esclau l’allibera i llavors segueix transmetent les dades restants. Si el master no disposa

27

CAPÍTOL 3: Fonaments teòrics

d’aquesta funció, cal implementar retards fixes en el microcontrolador per esperar aquest cicles d’espera.

Figura 3.15: Captura de transmissió pel bus I2C del PI18F2620

3.4. ICD 2 El ICD 2 és una eina de desenvolupament de baix cost de Microchip que ens permet programar i debugar els microcontroladors PIC un cop muntats en la placa. Les tècniques utilitzades són In-Circuit Debugger (ICD) i In-Circuit Serial Programmer™ (ICSP™). Les característiques principals que ens ofereix el MPLAB ICD 2 són les següents: - Ens permet executar el codi instrucció a instrucció a temps real. - Ens permet introduir pauses en el codi (breakpoints), i visualitzar i modificar variables i registres. - Ens permet depurar el programa amb el PIC muntat a la placa (ICD). - Monitoritza la tensió VDD. - Conté LEDs de diagnosi. - Interfície d’usuari amb MPLAB IDE. - Es pot connectar al PC mitjançant RS-232 o USB. El ICD és una eina que permet fer algunes coses de manera més econòmica que abans només es podien fer amb un emulador In-Circuit Emulator (ICE). Per poder aprofitar els avantatges del ICD cal tenir en compte en el disseny algunes limitacions: - El ICD requereix l’ús exclusiu d’alguns recursos tan hardware com software (com per exemple algunes entrades del PIC, espai de memòria, control de la CPU i emmagatzemant en la pila). Això es degut a que el ICD a diferència del ICE utilitza part del hardware i del software per realitzar alguna funció de ICE. Això ho podem veure més clarament en la figura 3.16.

28

CAPÍTOL 3: Fonaments teòrics

Figura 3.16: Condicions per la utilització del ICD 2

- La placa ha de disposar d’algun rellotge i estar en funcionament. - El procés de depuració (debug) només es possible quan tots els components de la placa estan en funcionament. Malgrat aquestes limitacions, si les tenim en compte a l’hora de dissenyar la placa, el ICD ens aporta alguns avantatges: - Encara que el sistema estigui en producció, sempre es pot incorporar el connector del ICD per tal de testejar, depurar o reprogramar l’aplicació sense ser necessari l’extracció del microcontrolador. - També dona la possibilitat de reprogramar el firmware sense necessitat d’utilitzar cap altre connexió o equipament. Com hem dit anteriorment cal dedicar alguns recursos de PIC per poder utilitzar el depurador. Els recursos necessaris són els següents: - El pin MCLR no es podrà utilitzar com a pin digital de entrada/sortida durant el procés de depuració (debugging). - MCLR i VPP són compartits en el procés de programació. - La programació ICSP de baixa tensió haurà de estar deshabilitada en el dispositius que permetin aquest tipus de programació. - Els pins RB6 i RB7 no estaran disponibles per altres funcions durant el procés de de programació o depuració. - Dos nivells de la pila no estaran disponibles. A mes degut a que el ICD 2 necessita controlar la pila els registres TOS estaran reservats. - La memòria de programa utilitzada pel ICD 2 seran del 0xFD80 al 0xFFFF. - Els registres utilitzats són de 0xEF4 a 0xEFF. Les connexions del ICD 2 a la placa es realitzarà mitjançant un connector RJ12 segons es mostra en la figura 3.17. Cal tenir en compte al fer les connexions que no es poden connectar resistències de pull-up, condensadors ni diodes en els pins PGC/PGD i tampoc es poden connectar condensadors en el MCLR.

29

CAPÍTOL 3: Fonaments teòrics

Figura 3.17: Connector ICD 2

3.5. LCD INTERFACE La majoria de mòduls LCD alfanumèrics estan basats en el controlador LCD Hitachi HD44780A. Aquest controlador s’encarrega de la multiplexació i de les peculiaritats de la pantalla LCD proporcionant una interfície fàcil d’utilitzar amb la que podem controlar funcions del LCD com escriure caràcters, moure el cursor, esborrar caràcters, etc. El controlador del mòdul LCD es comunica amb el microcontrolador de la placa mitjançant un bus de vuit línies de dades i 3 línies de control (RS, E i RW). També es possible comunicar-se amb el controlador utilitzant un bus de dades de només quatre línies. A continuació es mostra el diagrama de blocs de un mòdul LCD en la figura 3.18:

Figura 3.18: Diagrama de blocs d’un mòdul LCD

Les tensions VDD i VSS són les corresponents a la tensió d’alimentació i massa respectivament. La tercera tensió que apareix en el diagrama de blocs anomenada V0 és una tensió compresa entre VDD i VSS que es pot regular mitjançat un potenciòmetre i serveix per regular el contrast de la pantalla LCD. La línia de control R/W indica si estem en mode lectura a nivell alt, o en mode escriptura a nivell baix. La línia RS (Register Selelct) a nivell alt indica que s’envia o es rep un registre de dades, mentre que a nivell baix indica que s’envia un registre d’instrucció en mode escriptura o en mode lectura serveix com a comptador d’adreça o “Busy flag”. Per últim la línia E (Enable) indica quan es poden començar a llegir o escriure en el bus de dades mitjançant un flanc de baixada. Els mòduls LCD disposen de tres tipus de memòries. La primera és la memòria CGRAM que és una memòria volàtil de 64 bytes en la que podem emmagatzemar fins a 8 caràcters personalitzats per poder ser mostrats per pantalla. La memòria CGROM és no volàtil i du emmagatzemats tots els caràcters que podem imprimir en pantalla que normalment són 208 30

CAPÍTOL 3: Fonaments teòrics

caràcters. A continuació en la figura 3.19 es mostren tots els caràcters estàndard que hi ha normalment integrats (caràcters ascii i grecs) en els mòduls LCD tant els de la CGRAM com els de la CGROM amb les seves corresponents adreces.

Figura 3.19: Caràcters dels mòduls LCD

Per últim, la memòria DDRAM, és on s’emmagatzema la l’adreça dels caràcters que es mostren per pantalla. Aquesta memòria té una capacitat de 80 bytes i en cada un del qual es pot emmagatzemar l’adreça d’un caràcter. Si la pantalla és de 2 files i 16 columnes els primers 40 bytes són els corresponents a la primera fila i els següents 40 a la segona però només podrem visualitzar 16 d’aquest 40 caràcters. El sistema que s’utilitza per mostra els caràcters per pantalla és com una finestra lliscant tal com es mostra a la figura 3.20.

Figura 3.20: Funcionament de la memòria DDRAM del LCD

A continuació descriurem les instruccions de control i visualització necessàries per comunicant-se amb el mòdul LCD: - Clear display: Esborra tots els caràcters que hi ha impresos en pantalla escrivint en totes les adreces de la DDRAM el valor 20h que es correspon al símbol d’un espai en blanc. En el comptador d’adreça AC hi introdueix el valor 00h retornant el cursor a la posició original (El primer caràcter de l’esquerra de la primera línia)

31

CAPÍTOL 3: Fonaments teòrics

RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 0 0 0 0 0 0 0 0 0 1 - Return home: El cursor torna a la posició original canviant el valor del comptador d’adreça a 00h. En aquest cas, el contingut de la memòria DDRAM no varia i per tant no modifica els caràcters que apareixen en pantalla. RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 0 0 0 0 0 0 0 0 1 - Entry Mode Set: Si SH és a nivell baix, mou el cursor a la dreta incrementant el valor de l’adreça de la DDRAM si està a nivell alt. A nivell baix decrementa el valor de l’adreça de la DDRAM movent el cursor a l’esquerra. Si el valor de SH és igual a “1” el contingut de la pantalla es desplaça a la dreta o a l’esquerra segons si I/D esta a nivell baix o alt respectivament. Amb aquesta instrucció no es produeix desplaçament del cursor ni la pantalla sinó que només indica el tipus de moviment que hi haurà després d‘algunes instruccions com les de lectura o escriptura de les memòries. RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 0 0 0 0 0 0 0 1 I/D SH - Display ON/OFF Control: Amb el valor de D s’indica si volem que la pantalla estigui engegada o apagada, amb C indiquem si volem que el cursor sigui visible (ON) o no (OFF) i amb B es selecciona si volem que el cursor parpellegi (Blink ON) o sigui fixa (Blink OFF). En tots els casos el nivell alt indica que s’activi la funció (ON) mentre que el nivell baix que es desactivi (OFF). RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 0 0 0 0 0 0 1 D C B - Cursor or Display Shift: Amb aquesta instrucció podem desplaçar el cursor o el contingut de la pantalla (cada línia es desplaça per separat) sense escriure ni llegir dades. El cursor es desplaça a la segona línia quan arribem al dígit 40 de la primera línia. Per un valor de S/C igual a “0” desplacem el cursor incrementant o decrementant el valor de AC mentre que per un valor igual a “1” es desplaçarà la pantalla sense variar el valor de AC. Quan desplacem la pantalla el cursor es desplaçarà amb la pantalla. El valor de R/L indica si la pantalla o el cursor es desplacen a l’esquerra quan val “0” o a la dreta quan val “1”. RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 0 0 0 0 0 1 S/C R/L - Function Set: Aquesta és una instrucció de configuració. El bit DL serveix per seleccionar si utilitzarem el mode de transferència de dades de 4 bits (DL=”0”) o de 8 bits (DL=”1”). El valor de N indica si s’utilitza el mode de 1 línia o de 2 línies segons si està a nivell baix o alt respectivament. Per últim quan F està a nivell baix indica que els caràcters tenen un format de 5x8 punts i quan està a nivell alt de 5x11 punts. RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 0 0 0 0 1 DL N F - Set CGRAM Address: Introdueix una adreça de la CGRAM a AC per que apunti a aquella adreça. RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 0 0 0 1 AC5 AC4 AC3 AC2 AC1 AC0 - Set DDRAM Address: Introdueix una adreça de la DDRAM a AC per que apunti a aquella adreça. RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 0 0 1 AC6 AC5 AC4 AC3 AC2 AC1 AC0

32

CAPÍTOL 3: Fonaments teòrics

- Ready Busy flag and Address: Aqueta instrucció ens permet conèixer si el controlador del mòdul LCD està executant alguna operació interna. Si el bit BF està a nivell alt significa que alguna operació està en procés i cal esperar a que canviï a nivell baix per poder enviar-li la següent instrucció. A més amb aquesta instrucció també es pot llegir el valor del comptador d’adreces. RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 0 1 BF AC6 AC5 AC4 AC3 AC2 AC1 AC0 - Write Data to RAM: Aquesta instrucció permet escriure 8 bits de dades en les memòries CGRAM o DDRAM. Les dades s’escriuen en la memòria CGRAM o DDRAM segons si la instrucció que hem enviat anteriorment era “Set DDRAM Address” o “Set CGRAM Address”. Un cop s’ha escrit el valor en la memòria, el valor de AC s’incrementa o decrementa segons haguem escollit en la instrucció “Entry mode”. RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 1 0 D7 D6 D5 D4 D3 D2 D1 D0 - Read Data to RAM: Aquesta instrucció funciona com la anterior però en aquest cas és de lectura. RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 1 1 D7 D6 D5 D4 D3 D2 D1 D0 Per inicialitzar el mòdul LCD correctament cal enviar unes determinades instruccions abans de començar a utilitzar la pantalla normalment. La seqüència d’instruccions que cal enviar es troba en la figura 3.21.

Figura 3.21: Inicialització del mòdul LCD amb interfície de 4 bits

33

CAPÍTOL 4: Implementació

CAPÍTOL 4: Implementació 4.1. CONSIDERACIONS I DECISIONS PRÈVIES AL DISSENY En el punt 2 hem descrit els circuits integrats que utilitzaríem per realitzar l’equalitzador digital i les propietats que tenen. Amb aquests components però són moltes les opcions que tenim a l’hora de dissenyar el nostre equalitzador. En aquest punt decidirem cóm controlarem l’equalitzador (polsadors, “sliders”, controls rotatoris,...) i quin tipus d’equalitzadors utilitzarem (paramètrics, gràfics,...). El primer que hem de tindre en compte, és que al processador d’àudio li hem d’enviar els coeficients dels filtres biquad en format 4.20. En el apartat 3.1 hem explicat diferents mètodes amb els quals podem dissenyar els coeficient a partir d’altres paràmetres més fàcils d’utilitzar com l’ample de banda, el guany i la freqüència central. Com amb el microcontrolador no podem fer el càlcul dels coeficients a partir d’aquest paràmetres, els haurem de calcular prèviament amb MATLAB, i emmagatzemar-los en la memòria de programa del microcontrolador. Això implica que el nombre de filtres que podrem utilitzar està limitat per la memòria de programa del microcontrolador i que no podrem controlar els paràmetres de manera lineal sinó escalonada. Una possible opció seria dissenyar un equalitzador gràfic que es controles mitjançant controls lliscants però aquest només podria ser de 6 bandes. També serià possible implementar un equalitzador paramètric però si sigués de 6 bandes, necessitaríem 18 controls rotatius per controlar tots els paràmetres i seria necessari utilitzar un microcontrolador amb més entrades com per exemple el PIC18F4620. Com hem dit anteriorment la variació dels paràmetres no podrà ser contínua, sinó que serà escalonada, i per això, podem utilitzar polsadors en comptes de controls rotatius o del tipus “sliders”. Si, a més, afegim una pantalla LCD ens permetrà controlar tots els paràmetres mitjançant els mateixos polsadors. L’ús del LCD els permet implementar qualsevol tipus d’equalitzador que desitgem limitat al espai de memòria de programa del microcontrolador. A més com només necessitem el LCD i tres polsadors, la mida del equalitzador podrà ser més reduïda. També ens facilita el procés de depuració en el disseny. Per tots els motius descrits anteriorment per al control del equalitzador utilitzarem una pantalla LCD alfanumèrica de 16 dígits de dues línies i tres polsadors. Per la pantalla es mostraran tots els menús necessaris per el control de l’equalitzador i ens podrem desplaçar per ells amb els polsador de pujar i baixar. Amb aquests polsadors també es pujaran o baixaran els valors dels paràmetres dels filtres. El tercer polsador serà el de selecció i s’utilitzarà per entrar a submenús i seleccionar els valors del paràmetres. En el nostre circuit implementarem un equalitzador paramètric de sis filtres. La freqüència central de cada filtre es podrà escollir entre 30 freqüències des de 25Hz fins a 20kHz amb una separació entre elles de 1/3 d’octava. Utilitzarem les freqüències centrals ISO que parteixen de la freqüència de 1000Hz i la resta es calculen a partir d’aquesta amb una separació de 1/3 d’octava. Per cada una d’aquestes freqüències es podran escollir 4 amples de banda que es corresponen a 2,1,2/3 i 1/3 d’octava. A més, per totes les combinacions de freqüències i amples de banda que hem dit podrem seleccionar guanys de -12dB a 12dB en passos de 1dB. Per emmagatzemar cada un d’aquest filtres necessitem 16 bytes en la memòria de programa i per tant la memòria de programa que ocuparà la taula de coeficients del filtre paramètric serà de aproximadament 48kbytes.

35

CAPÍTOL 4: Implementació

De tots els filtres que hem explicat en el apartat 3.1, el que utilitzarem per generar els coeficients serà el filtre peaking que preserva la freqüència de Nyquist i la freqüència de tall inferior. L’ample de banda el definirem com la diferència de freqüències entre les que el guany es redueix en 3dB per guanys superiors a 6dB o el guany es divideix per 2 (en dB) quan és inferior. Per guanys negatius el filtre serà simètric, per tant dos filtres amb la mateixa freqüència central i el mateix ample de banda, però amb guanys oposats en cascada donarien una resposta plana de 0dB. Per calcular els coeficients en el cas de guanys negatius només cal canviar els coeficients del numerador pels del denominador i viceversa. Malgrat això, com al TAS3001 se l’hi envien només cinc coeficients corresponents als de l’equació 3.2, no podem intercanviar-los ja que els hauríem de dividir tots per b0/a0 i això no ho podem fer amb el microcontrolador. El programa de MATLAB que utilitzarem per generar les taules amb els coeficients es troba en l’annex. Com que disposem de més espai en la memòria, i l’espai que ocuparan les taules corresponents a un equalitzador gràfic en comparació a les del equalitzador paramètric és menyspreable, hem decidit incloure un equalitzador gràfic en el nostre circuit. Per adaptan-se a la recomanació ISO de les freqüències centrals l’equalitzador gràfic implementat serà de 5 bandes, una amb freqüència central a 1000Hz i dos més per sobre i dos per sota amb una separació entre bandes de 2 octaves. El guany dels filtres del equalitzador gràfic es podrà variar entre -12dB i 12dB amb salts de 1dB. Per l’equalitzador gràfic utilitzarem dos filtres shleving, un pas alt i un pas baix i tres filtres peaking. Els coeficients dels filtres shelving els calcularem mitjançant el sistema que utilitzava la transformada MZT. Com que els coeficients es calculen prèviament i s’emmagatzemen en la memòria, no cal que ens preocupem del cost computacional degut al càlcul dels coeficients. Per aquest motiu per als tres filtres peaking del equalitzador gràfic calcularem els coeficients com la mitja entre el mètode basat en la transformada MZT i el mètode que preserva el guany a la freqüència de Nyquist i a la freqüència de tall inferior. El programa de MTLAB necessari per obtenir aquestes taules també es troba en l’annex. També introduirem equalitzadors predefinits com hi ha en molts productes d’àudio d’electrònica de consum. Aquets filtres realcen o atenuen determinades freqüències en funció de les característiques dels diferents tipus de música. Normalment trobem filtres predefinits del tipus jazz, rock, classic o pop entre altres. Les taules per aquests filtres gairebé no ens ocuparan memòria. Els controls de baixos i aguts no s’utilitzaran ja que si els utilitzéssim addicionalment als filtres dels equalitzadors, al sumar-se els guanys dels dos filtres podríem obtenir guanys de fins a 30dB. Aquests guanys tant elevats no són necessaris i ens farien que haguéssim d’atenuar el senyal massa en el mesclador perquè aquest no es distorsionés. També hi hauria la opció d’afegir, a més de l’equalitzador paramètric, el gràfic i el predefinit, una quarta opció que consistís en un control de greus i aguts però de fet podem controlar els greus i aguts amb els filtres shelving del equalitzador gràfic i per tant seria redundant afegir aquesta quarta opció. Per decidir com utilitzarem el control de volum i el mesclador ens ficarem en el pitjor cas possible. El cas més desfavorable seria que la senyal analògica d’entrada al convertidor tingues el recorregut màxim (4V pic a pic). Si aquest senyal un cop convertit a digital el passem per un filtre amb un guany de 12dB, serà necessari atenuar l’entrada 12dB prèviament al filtrat. El control de volum ens permetrà variar-lo des de 0 fins a 30 on el 0 es correspon al Mute, en el 1 tindrem un guany de -70dB i a partir d’aquí el guany variarà s’incrementarà 2.5dB per cada pas fins el 30 en que l guany serà de 0dB. Que el guany per el volum màxim sigui de 0dB ho hem fet perquè si el senyal d’entrada te recorregut màxim i el passem pel mesclador que l’atenua 12dB però desprès el filtrem i l’amplifiquem 12dB el guany màxim en el control

36

CAPÍTOL 4: Implementació

de volum només pot ser de 0dB. Les dades que haurem d’enviar per actualitzar el volum també s’emmagatzemarà en forma de taules en la memòria de programa. Durant el procés de selecció dels paràmetres que controlaran els equalitzadors, per cada canvi que es realitzi en un paràmetre se l’hi enviaran els coeficients corresponents al TAS3001. Per exemple, si en l’equalitzador gràfic modifiquem el guany a una certa freqüència de 0dB a 12dB, per cada dB que pugem se li enviarà al TAS3001 els cinc coeficients del filtre que estem modificant i modificarem el valor de la variable que emmagatzema el paràmetre modificat. D’aqueta manera l’usuari del equalitzador podrà escoltar els efectes del processament del senyal mentre està modificat els paràmetres. Per aquest motiu les variables es guardaran en la memòria RAM, ja que és molt més fàcil d’accedir-hi i suporta molts més cicles de lectura/escriptura que la memòria EEPROM. Només s’emmagatzemaran en la memòria EEPROM quan el filtre sigui definitiu i es surti dels menús de selecció dels filtres. Això servirà per poder recuperar els filtres que s’estaven utilitzant abans d’apagar l’equalitzador quan aquest es torni a engegar.

4.2. DISSENY HARDWARE El disseny hardware ha estat realitzat amb el programa OrCAD. Primerament amb el Capture CIS s’ha realitzat el disseny esquemàtic. Un cop realitzat aquest s’ha passat al disseny del circuit imprès amb el programa Layout. Tots els detalls d’aquest disseny es troben en els annexos i en aquest punt només s’explicaran els blocs que composen el hardware i la seva interconnexió. Podem dividir el circuit en tres grans blocs. El primer és el d’alimentació que serà l’encarregat de proporcionar les diferents tensions que necessita cada un dels elements hardware. El segon, es correspon a la part digital i està format pel microcontrolador y el processador digital d’àudio. Aquest últim, anirà lligat al bloc analògic mitjançant el convertidor analògic-digital digital-analògic. El bloc analògic estarà composat per les etapes de frond-end i back-end, un amplificador de potència per auriculars i un altre per altaveus.

Figura 4.1: Diagrama de blocs del disseny hardware

37

CAPÍTOL 4: Implementació

4.2.1. ALIMENTACIÓ Es la part del circuit encarregada de proporcionar la tensió necessària a la resta de components. Està composada bàsicament per tres LM317 que a partir d’una font d’alimentació externa que l’hi ha de proporcionar una tensió de com a mínim 15V, ens proporcionaran les tensions necessàries. Una de les tensions obtingudes serà de 5V i s’utilitzarà per alimentar els TLV2264 que es troben en els circuits de front-end i de back-end, el microcontrolador i l’amplificador per auriculars. Un altre LM317 ens proporcionarà una tensió de 3.3V i l’utilitzarem per alimentar el codificador i el processador d’àudio. A partir d’aquesta tensió i mitjançant un divisor de tensió obtindrem una tensió de 3.3/2V necessària pel frot-end. Per últim, un altre regulador de tensió serà l’encarregat de donar una alimentació de 12V a l’amplificador de potencia d’àudio. Tant la connexió a massa com les alimentacions de 3.3 i 5V, són necessàries tant en la part digital com en la part analògica. Per tal de que la part digital no ens contamini la part analògica, les alimentacions que ens proporcionen els reguladors no aniran directament connectades als elements sinó que separarem amb una bobina l’alimentació proporcionada pel regulador i la que alimentarà la part analògica (AVCC). De igual manera es farà amb l’alimentació de la part digital (DVCC) que es separarà també amb un altre bobina de la tensió de sortida del regulador.

4.2.2. FRONT-END El front-end és el circuit encarregat de condicionar el senyal d’àudio d’entrada que ens arribarà mitjançant un connector RCA estèreo per poder-lo connectar al convertidor. Malgrat que seria possible connectar directament el senyal d’entrada al convertidor no ho farem perquè es reduirien considerablement les prestacions del TLC320AD77C. Una de les funcions del front-end consisteix en amplificar el senyal d’entrada perquè arribi a l’entrada del convertidor amb l’amplitud màxima que permet que és de 4Vpp. D’aquesta manera aconseguim reduir al màxim l’error de conversió. El TLC320AD77C processa en mode diferencial el senyal analògic des de l’entrada fins que aquest es converteix en digital. Amb això s’aconsegueix el rebuig en mode comú de possibles interferències. Com el senyal d’entrada és unipolar el circuit de front-end també s’encarregarà de transformar aquest en una senyal diferencial. Així a partir del senyal d’entrada i d’una tensió contínua de 3.3/2V obtindrem AINRM i AINRP. Com el senyal desitjat és AINRM menys AINRP i els dos provenen de la mateixa entrada unipolar, les possibles interferències que hi podia haver en el senyal d’entrada seran pressents en les dos, per això al restar-les eliminem les interferències com s’ha dit anteriorment. A més aquest circuit també conté un filtre pas baix antialiasing. Per realitzar tot això s’ha optat per utilitzar el circuit que es proposa en el datasheet del convertidor que analitzarem amb més detall en els anexos. Aquest circuit s’implementarà amb un TLV2264 que incorpora quatre amplificadors operacionals que són els necessaris pels dos circuits de front-end (dos pel canal dret i dos per a l’esquerre).

4.2.3. BACK-END A la sortida del convertidor s’obté un senyal unipolar que és la conversió del senyal digital d’entrada invertit. A més, en el datasheet s’aconsella que el senyal de sortida es filtri per

38

CAPÍTOL 4: Implementació

eliminar el soroll d’altes freqüències. Per aquest dos motius, és necessari afegir a la sortida de cada canal un circuit de back-end que ens proporcionarà a la sortida un senyal no invertit en relació al senyal digital d’entrada i ens filtrarà pas baix el senyal. Les sortides dels back-end aniran connectades a una sortida exterior mitjançant un connector RCA estèreo. Per implementar aquest circuit, ens basarem en el que es proposa en el datasheet del convertidor afegint alguna modificació, ja que el circuit proposat ens retallaria el senyal obtenint a la sortida només la part positiva d’aquest. En els anexos es troba l’anàlisi més detallat d’aquest circuit. Els amplificadors operacional utilitzats seran els mateixos que em utilitzat en el circuit de front-end.

4.2.4. AMPLIFICADORS DE POTÈNCIA El circuit inclourà dos amplificadors de potència, un per auriculars implementat amb el TPA152 i un altre per altaveus implementat amb el TPA1517. Els dos aniran acompanyats de components passius els valors i la funcionalitat dels quals s’exposen en els anexos. L’entrada del amplificador per auriculars serà directament la que ens proporciona el convertidor. La sortida d’aquest amplificador anirà connectada a un connector jack de 6.35mm. L’amplificador per altaveus rebrà el senyal de sortida de l’etapa de back-end ja que a diferència del TPA152, no necessita la senyal invertida a la entrada. La sortida anirà a un connector al qual se li podran connectar els altaveus.

4.2.5. CONVERTIDOR AD/DA El convertidor rebrà el senyal estèreo d’àudio provinent del circuit de front-end. Un cop aquest s’hagi transformat a digital s’enviarà per la sortida SDOUT al processador d’àudio. Per un altre banda rebrà el senyal digital un cop processat pel TAS3001C per l’entrada SDIN i el tornarà a transformar en analògic. Com a sortida analògica tindrem dos senyals unipolars, AOUTR i AOUTL corresponents al canal dret i al canal esquerre. També obtindrem VCOM que és la tensió de referència en mode comú. A part de les entrades d’àudio tant analògiques com digitals que hem comentat anteriorment, el convertidor també necessita tres entrades de rellotge i una entrada de reset. L’entrada de Powerdown/reset arribarà del microcontrolador, i serà la mateixa que utilitzarem per fer reset al TAS3001C. Les tres entrades de rellotge seran les generades pel TAS3001C. La primera s’anomena MCLK (Master clock) i la seva freqüència és de 256×fs, on fs és la freqüència de mostreig. La segona és SCLK (shift clock) que és la freqüència de bit de la senyal digital d’àudio i té un valor de 64×fs. Per últim tenim el LRCLK la freqüència del qual és la freqüència de mostreig. A més, de les entrades que provenen de components exteriors el TLC320AD77C té altres entrades que serveixen per configurar-lo i que aquest sigui compatible amb el TAS3001C. El valor de SPDMOD (speed mode) ha de ser 0 ja que la freqüència de mostreig es trobà en el marge de 16kHz a 48kHz, que és el mode normal de velocitat. El TLC320AD77C disposa de vuit maneres de transmetre el senyal estèreo d’àudio digital. Haurem de connectar MOD2 a DVCC i MOD1 i MOD0 a massa per seleccionar el mode IIS de vint bits. Per últim, caldrà connectar DEM1 i DEM0 a DVCC per desactivar el mode de Deemphasis.

39

CAPÍTOL 4: Implementació

4.2.6. MICROCONTROLADOR El microcontrolador disposarà de tres entrades que provindran de tres micropolsadors que hi haurà a la placa per facilitar la seva utilització en el laboratori, a més, s’inclourà un connector per poder ficar polsadors exteriors. També hi haurà un altre polsador que anirà connectat a l’entrada de reset MCLR del PIC. Per últim, caldrà proporcionar-li un senyal de rellotge que provindrà del mateix generador de rellotge que utilitzarem per al processador d’àudio. El microcontrolador anirà connectat al processador d’àudio mitjançant el bus I2C. El PIC18F2620 disposa de dos pins específics per aquest protocol que són RC3 i RC4 que es corresponen a SCL i SDA. Una altra sortida del microcontrolador anirà a les entrades de reset del TAS3001C i del convertidor. Hi haurà set sortides del PIC que serviran per controlar el LCD que aniran connectades a un connector de setze potes. Quatre d’aquestes sortides s’utilitzen per enviar dades mentre que la resta seran de control. Les sortides de control del LCD seran: E (Enable), R/W (read/write) i RS (register select) les funcions de les quals hem explicat en el punt 3.4. Al connector del LCD a més de les sortides del PIC, també hi haurem de connectar les alimentacions. Una Vss que connectarem a la massa digital, l’altre és Vdd, que és l’alimentació de tot el mòdul que conté LCD la qual connectarem a l’alimentació digital de 5V i, per últim, V0 que és l’alimentació de la pantalla LCD que connectarem a una tensió intermitja que regularem amb un potenciòmetre. La placa disposarà d’un connector del tipus RJ12 que és el necessari per connectar el MPLAB® ICD2 (In-Circuit Debugger) que és l’instrument que utilitzarem en el laboratori per programar el PIC18F2620. D’aquesta manera, podrem programar el PIC un cop instal·lat a la placa mitjançant el sistema ICSPTM. El RJ12 anirà connectat als pins del microcontrolador MCLR, RB6 i RB7, a massa i a la tensió d’alimentació digital de 5V.

4.2.7. PROCESSADOR D’ÀUDIO El processador d’àudio, rebrà el senyal digital d’àudio provinent del convertidor per l’entrada SDIN1 i un cop processada la retornarà al convertidor per la sortida SDOUT. La entrada de rellotge MCLK vindrà del generador de rellotge IQXO-22/-23, que com hem dit en el punt anterior, és el mateix que utilitzem per proporcionar el senyal de rellotge al microcontrolador. Però, com el senyal de rellotge proporcionat és de 5V d’amplitud, perquè sigui compatible amb el TAS3001C haurem d’incloure un divisor de tensió que redueixi l’amplitud del senyal de 5V a 3.3V. A partir d’aquest rellotge el mateix TAS3001C és capaç de generar els rellotges SCLKOUT i LRCLKOUT els quals tornaran a entrar al TAS3001C per les entrades SCLK i LRCLK. Com hem dit anteriorment, aquests senyals de rellotge també els utilitzarà el convertidor. Per últim, explicarem les entrades que provenen del PIC18F2620. Un és el senyal de reset, i l’altre és el bus I2C per el qual arribarà tota la informació necessària per controlar el processador. Com els pins SDA i SCL utilitzats en el bus I2C són drenador obert cal ficar resistències de pull-up que van entre aquests pins i l’alimentació digital de 3.3V. Per configurar l’adreça que tindrà el TAS3001C connectarem les entrades CS2 i CS1 a massa perquè tingui l’adreça 0x68 ja que l’adreça es correspon al 01101-CS2-CS1.

40

CAPÍTOL 4: Implementació

4.3. DISSENY SOFTWARE Per al disseny software, utilitzarem l’entorn de desenvolupament integrat que ens ofereix Microchip anomenat MPLAB IDE. El llenguatge de programació que utilitzarem, serà l’ensamblador basant-se en les instruccions suportades per l’ensamblador MPASM. El MPLAB IDE també ens permet depurar i programar la placa mitjançant l’eina ICD 2 que hem explicat en apartats anteriors.

Figura 4.2: Diagrama de blocs del disseny software

En la figura 4.2, es mostra el diagrama de blocs del programa principal. El primer que realitzarà el programa al iniciar-se el microcontrolador serà configurar totes les entrades i sortides per poder comunicar-se amb la resta de components que controla que són els polsadors, la pantalla LCD i el processador d’àudio. Seguidament, es llegiran de la memòria EEPROM tots els paràmetres que s’havien emmagatzemat corresponents a la configuració del TAS3001. Aquest paràmetres es guarden a la memòria RAM per poder treballar amb ells i modificar-los més fàcilment que, si només els emmagatzeméssim a la memòria EPROM. Un cop tenim aquests paràmetres s’enviaran pel bus I2C els valors dels registres corresponents per configurar el TAS3001 i que comenci a realitzar el processament digital d’àudio. Un cop acabat el procés d’inicialització descrit anteriorment s’entrarà en un bucle infinit durant el qual es mostrarà per pantalla el missatge de menú principal i s’esperarà a que algun dels polsadors sigui premut. Si són polsats els polsadors de pujar o baixar anirem directament al submenú que controla el volum. Només es retornarà al menú principal tornant a prémer el polsador de selecció o quan el control hagi arribat al seu límit superior o inferior i es torni a prémer el polsador de pujar o baixar respectivament. Si es prem el polsador de selecció s’entrarà en els submenús del equalitzador. Per detectar que s’ha premut un posador es testeja el valor de les entrades corresponents als polsadors i considerem que un polsador ha estat premut quan el valor de la entrada val “0” . Per evitar que mentre el posador està premut es detecti com més de una pulsació podríem esperar fins que el valor de l’entrada sigués “1”. Durant el principi de la pulsació es generen rebots que poden fer que encara que no deixem de polsar el polsador el senyal d’entrada valgui “1”. Per solucionar aquest segon problema, podem implementar retards de 100ms. 41

CAPÍTOL 4: Implementació

Contemplant aquest dos fets, s’ha decidit que després de que es premi un polsador, es comprovarà el valor de l’entrada cada 100ms fins que aquest passi a valer “1”, moment en el qual considerarem que el polsador ha deixat de ser premut. El primer submenú que apareixerà serà el de l’equalitzador gràfic. A partir d’aquest submenú amb els polsadors de pujar i baixar ens mourem per la resta de submenús de manera rotativa. La resta de submenús es corresponen al del equalitzador predefinit, l’equalitzador paramètric i sortida dels submenús. En cada un d’aquests submenús es treurà per pantalla el nom del submenú i igual que en el menú principal entrarem en un bucle infinit fins que l’usuari torni a prémer algun polsador. Si estan en algun submenú, es prem el polsador de selecció entrarem en el menú de modificació d’aquell tipus d’equalitzador. Si ens trobem en el submenú de sortida al prémer el polsador de selecció, tornarem al menú principal. En el pas en el que sortim dels submenús per tornar al menú principal serà quan guardarem tots els paràmetres que ens permeten actualitzar els registres del TAS3001 en la memòria EEPROM. Aquest valors són els que utilitzem al iniciar el microcontrolador per actualitzar els registres.

4.3.1. INICIALITZACIÓ DEL MICROCONTROLADOR El primer que es fa en el procés d’inicialització és inicialitzar el LCD. Per fer-ho cridarem a una funció anomenada LCDInit que explicarem amb més detall més endavant. Bàsicament el que fa és configurar les sortides del microcontrolador que controlen el LCD i a continuació inicialitza el mòdul LCD tal com s’indica en la figura 3.21. A continuació configurarem el port sèrie MSSP perquè funcioni en mode I2C com a master. Per utilitzar el mode estàndard de velocitat a 100kHz, que es el que necessitem per comunicant-se amb el TAS3001, cal deshabilitar el control de slew rate posant a “1” el bit SMP del registre SSPSTAT. A continuació, cal indicar que el microcontrolador serà el dispositiu mestre en el bus I2C introduït el valor 1000B en els bits SSPM3:SSPM0 del registre SSPCON1. També haurem de canviar a “1” el bit SSPEN del registre SSPCON1 per habilitar el port sèrie i configurar els pin SDA i SCL com a ports sèrie. En el mode de funcionament mestre cal configurar la freqüència del rellotge SCL segons la següent fórmula: clock = FOSC/(4 * (SSPADD + 1)). Com la freqüència màxima suportada pel dispositiu esclau (el TAS3001) és de 100kHz, el valor que haurem d’introduir en el registre SSPADD és el 29H. També haurem de ficar a “1” els bits 3 i 4 del registre TRISC per configurar els pins SDA i SCL com sortides. Per últim només queda configurar el port A. Els pins del port A del 0 al 2 estan connectats als polsadors, i per tant, els haurem de configurar com entrades i el pin tres l’utilitzarem per enviar el senyal de reset a el TAS3001 i al convertidor i, per tant, s’haurà de configurar com a sortida. Per aconseguir el funcionament desitjat haurem de posar a “1” els bits 0,1 i 2 del registre TRISA. També cal configurar el registre ADCON1 per configurar que totes les entrades són digitals. Per acabar, introduirem en el registre CMCON el valor 07H per deshabilitar les funcions de comparador. Arribat a aquest punt, ja tenim configurades totes les entrades i sortides del microcontrolador. El següent que cal fer es enviar el senyal de reset al TAS3001 i al convertidor. Mentre no enviem el senyal de reset, no és possible comunicar-se mitjançant el bus I2C amb el TAS3001, ja que manté les línies SDA i SCL a nivell baix. Per fer el reset, primer fiquem el bit 3 del registre PORTA a “1”, després el tornem a posar a “0” per generar el senyal de reset i el mantenim 10ms. El convertidor necessita que el senyal de reset es mantingui a nivell baix durant 10ns i el TAS3001 durant deu cicles del rellotge MCLK. Seguidament tornarem a posar la sortida del reset a nivell alt i esperarem 10ms més. La operació de reinicialització en el TAS3001 necessita aproximadament 5ms per ser completada. Després de inicialitzar el TAS3001 tots els filtres del equalitzador, el bass i el 42

CAPÍTOL 4: Implementació

treble s’inicialitzen a 0dB (passa tot), el volum està en mute i el mesclador deixa passar el senyal d’àudio del canal 1 (0dB) mentre que no deixa passar el del canal 2 (mute).

4.3.2. INICIALITZACIÓ DE LES VARIABLES En aquest punt l’únic, el que farem es recuperar els valors de les variables corresponents a la configuració del TAS3001 de la EEPROM per emmagatzemar-les en la memòria de RAM de dades. Com em dit en el punt 4.1, aquestes variables són les corresponents als últims equalitzadors que es van utilitzar abans de desconnectar la placa. A continuació es mostra el codi necessari per llegir cada una de les variables: MOVLW MOVWF MOVLW MOVWF BCF BCF BSF MOVFF

d'0' EEADRH d'0' EEADR EECON1, EEPGD EECON1, CFGS EECON1, RD EEDATA, V

El primer que cal fer és indicar l’adreça de la dada que volem llegir i ficar-la als registres EEADRH i EEADR. Seguidament, indiquem que volem llegir la memòria de dades EEPROM ficant a “0” el bit EEPGD i CFGS del registre EECON1. A continuació indiquem, ficant el bit RD del mateix registre a “1” que volem que s’inici el procés de lectura de la EEPROM. Un cop s’ha llegit la dada de la EEPROM podem accedir a ella mitjançant el registre EEDATA el qual copiarem en la memòria RAM. Les variables que utilitzarem per a la configuració del TAS3001, estan pensades per facilitar el càlcul de la adreça on es troben les dades que haurem d’enviar pel bus I2C. Les variables són les següents: - Una variable anomenada V en la que emmagatzemarem el valor del volum. El valor de V podrà ser de 0 a 30 i es correspon a la línea de taula de volum que s’haurà d’enviar al TAS3001. - Cinc variables corresponents al guany de l’equalitzador gràfic anomenades G_BiquadX_g on X va de 0 a 4, un per cada filtre. El seu valor va de 0 per un guany de -12dB a 24 per un guany de 12dB. Un increment en el valor de la variable correspon a un increment de un dB del guany. - Sis variables anomenades G_BiquadX on X és el numero del filtre al que correspon el guany emmagatzemat en la variable (de 0 a 5). El valor de la variable anirà de 0 per un guany de -12dB a 24 per un guany de 12dB igual que en l’equalitzador gràfic. - Sis variables que controlen l’ample de banda dels filtres de l’equalitzador paramètric. S’anomenen Q_BiquadX i X indica el número de filtre. El valor d’aquesta variable és 0 per un ample de banda de 2 octaves, 1 per 1 octava, 2 per 2/3 d’octava i 3 per 1/3 d’octava. - Sis variables més anomenades f0_BiquadX contindran informació de la freqüència central del filtre X. El seu valor anirà de 0 per una freqüència de 25Hz a 29 per una freqüència de 20kHz. Cada increment de la variable suposa un increment de 1/3 d’octava en la freqüència central del filtre corresponent. - L’última variable indicarà l’equalitzador que s’està utilitzant. Si el seu valor és 0, vòl dir que s’està utilitzant l’equalitzador gràfic, si és 1 l’equalitzador predefinit i per un valor igual a 2 l’equalitzador utilitzat serà el paramètric.

43

CAPÍTOL 4: Implementació

4.3.3. ACTUALITZACIÓ DELS REGISTRES DEL TAS3001 Després d’enviar el senyal de reset al TAS3001 és necessari enviar el valor del registre MCR (Master Control Register). El valor del d’aquest registre és 1XXXXXXXB on X significa que no ha estat inicialitzat i el “1” en el setè bit significa que el TAS3001 està en mode de càrrega ràpida (fast speed mode). Mentre està en aquest mode és possible actualitzar els valors dels registres del equalitzador sense cap retard de processament, ja que no accepta senyal d’àudio i per tant tampoc el processa. Els valors dels registres de bass i treble no es poden carregar en aquest mode i els valors dels del mesclador i el volum si que es pot, però no és recomanable. Per tant, el primer que farem és enviar tots els coeficients de tots els filtres de l’equalitzador al TAS3001. Els coeficients els obtindrem a partir de les variables que hem recuperat de la memòria EEPROM. Per a la inicialització dels registres del equalitzador només cal cridar a la funció load_EQ que explicarem en més detall més endavant. Un cop hem carregat tots els registres del equalitzador, ja podem inicialitzar el valor del registre MCR. Per fer-ho cridarem la funció send_MCR que explicarem més endavant. Quan ja hem actualitzat el registre MCR el TAS3001, comença a funcionar en mode normal i haurem d’enviar els valor dels registres del mesclador i el valor del volum. Les funcions utilitzades seran update_mixer i update_volum. A continuació explicarem totes funcions utlitzades en aquest punt. Per totes les funcions que explicarem a continuació, són necessaries les funcions relacionades amb el bus I2C. Aquestes funcions s’explicaran amb detall en el punt 4.3.10. També en el punt 4.3.10 explicarem la manera com s’utilitzen aquestes funcions, en el ordre en que s’han de cridar, etc. En aquest punt només explicarem el que hem d’enviar sense entrar en detall de com ho fem.

4.3.3.1. Load_EQ: El primer que cal fer és mirar el valor de la variable Quin_EQ per saber l’equalitzador que tenim que carregar en el TAS3001. Segons el seu valor el programa saltarà a load_EQ_grafic, load_EQ_predefinit o load_EQ_parametric.

4.3.3.2. Load_EQ_gràfic: Com que les taules són les mateixes per tots els filtres, i per actualitzar cada filtre l’únic que varia és la subadreça que enviem al TAS3001 al principi de la transmissió, per no repetir per tots els filtres el mateix codi, utilitzarem una funció que s’anomenarà update_EQ_graf. A la funció update_EQ_graf l’hi haurem de passar el guany per una variable que anomenarem G i el filtre que volem actualitzar per un altre variable anomenada filtre. Per tant, per carregar l’equalitzador gràfic haurem de repetir 6 vegades el mateix codi. Copiarem el valor de G_BiquadX_g a G i a filtre hi ficarem el valor de X+1. Això ho repetirem per tots els valors de X des de 0 a 5. Com l’equalitzador gràfic només utilitza 5 filtres el sisè l’haurem de configurar passa tot cridat a la funció update_filtre que explicarem més endavant en load_EQ_paramètric.

4.3.3.3. Load_EQ_predefinit: En aquest cas, l’únic que cal fer és cridar a la funció update_EQ_predef.

44

CAPÍTOL 4: Implementació

4.3.3.4. Load_EQ_parametric: El funcionament és el mateix que en load_EQ_gràfic, amb l’única diferència que en aquest cas es cridarà a la funció update_filtre en lloc de update_EQ_graf. A aquesta funció a més del guany l’hi haurem de passar els valors de freqüència central f0_BiquadX mitjançant una variable anomenada f0 i l’ample de banda Q_BiquadX que li passarem per la variable Q. Igual que en el cas de l’equalitzador gràfic, caldrà passar les variables i cridar a la funció update_filtre sis cops, un per cada filtre.

4.3.3.5. Send_MCR: El valor del amb el qual actualitzarem el registre MCR és el que veiem en la taula següent: FL SC E1 E0 F1 F0 W1 W0 0 1 1 0 1 0 1 0 El valor de FL es fica a “0” per començar a treballar en mode normal. La resta de bits serveixen per configurar l’interfície entre el convertidor i el TAS3001. Recordem que en el convertidor ho configuràvem mitjançant les entrades MOD2, MOD1 i MOD0. Perquè aquest dos dispositius siguin compatibles, haurem de ficar SC a “1” per indicar que la freqüència del rellotge SCLK ha de ser 64 vegades la freqüència de mostreig. Introduint el valor 10B als bits E(1,0) i F(1,0) indiquem que tant la entrada (F) com la sortida (E) sèrie del senyal d’àudio utilitzaran el mode de transmissió IIS. Amb el valor de W indicarem la longitud de les paraules de dades que enviarem en el nostre cas en mode IIS. El valor 10B dels bits W indiquen una longitud de paraula de 20 bits.

4.3.3.6. Update_mixer: El valor de guany del mesclador després d’haver fet el reset, és de 0dB per la entrada 1 i la entrada 2 està en mute. Com només entrarà senyal d’àudio per la entrada 1, la 2 la deixarem com està. El mesclador de la entrada 1, però, s’haurà de modificar perquè el guany sigui igual a -12dB com hem dit en el punt 4.1. El valor que haurem d’enviar pel bus I2C per obtenir aquest guany l’obtenim del manual del manual del TAS3001. Haurem d’enviar a la subadreça del registre del mesclador 3 bytes que són el 0x04, 0x04 i el 0xDE.

4.3.3.7. Update_volum: Per actualitzar el volum cal enviar 3 bytes al TAS3001, però, com en la memòria de programa només podem guardar paraules de 16 bits, cada valor del volum ocuparà 4 bytes de memòria. Per actualitzar el volum, el primer que fem és obtenir l’adreça de la primera posició de memòria de programa on es troba la taula de volum i la emmagatzemarem en els registres TBLPTRL, TBLPTRH i TBLPTRU. Després multiplicarem per 4 (els bytes que ocupa les dades que hem d’enviar per cada valor de volum) el valor de la variable V on es troba el volum que hem seleccionat. El valor obtingut es sumarà a l’adreça obtinguda anteriorment i es guardarà als mateixos registres. Aquestes adreces les guardarem per tornar a llegir les mateixes dades després ja que les hem d’enviar dues vegades (una pel volum del canal dret i una pel volum del canal esquerre). Un cop tenim la adreça, ja podem llegir els tres bytes de dades i enviar-los pel bus I2C després d’haver enviat la subadreça del registre de volum. A continuació les tornarem a llegir i enviar un altre vegada. Quan haguem enviat els sis bytes, ja podem tancar la comunicació amb el TAS3001.

45

CAPÍTOL 4: Implementació

4.3.3.8. Update_EQ_graf El primer que es farà en aquesta funció, és llegir el valor de la variable filtre que se li envia. Un cop coneixem el filtre que volem actualitzar, copiem en TASDATA la subadreça del registre corresponent al filtre del canal esquerre, i en un altre variable hi copiem la del canal dret. En aquest cas, a diferència del volum, la transmissió dels coeficients del canal dret i els del canal esquerre, es realitzen en dos transmissions separades a subadreces diferents. També és necessari obtenir l’adreça de la primera posició de memòria de la taula on es troben els coeficients del filtre. En el cas de l’equalitzador gràfic a cada filtre biquad li correspon una freqüència central i una taula. Les taules estan formades per 25 files de 16 bytes cada una i cada fila es correspon a un valor de guany. Els 16 bytes de cada fila es corresponen a els 5 coeficients en format 4.20 que cal enviar. En realitat només serien necessaris 15 bytes, però, com hem dit per el cas de la taula de volum en la memòria de programa, emmagatzemarem paraules de 2 bytes i, per tant, per als 5 coeficients necessitem ocupar 16 bytes dels quals només en llegirem els 15 primers. L’adreça de la primera posició de memòria la guardarem en els registres TBLPTRL, TBLPTRH i TBLPTRU. A partir del valor de guany que li haurem passat per la variable G calcularem la posició de la memòria en que es troben els coeficients corresponents a aquest valor multiplicant-lo per 16. El valor obtingut de la multiplicació de G per 16, li sumarem a l’adreça de la primera posició de memòria de la taula i ho tornarem a emmagatzemar als mateixos registres. Igual que fèiem en el cas del volum guardarem en tres variables els valors dels registres on s’emmagatzema l’adreça. Això ho fem ja que cada cop que llegim un valor de la memòria de programa l’adreça s’incrementa i com haurem de tornar a llegir els mateixos valors ja que el filtre és el mateix pel canal dret i per l’esquerra cal emmagatzemar-los abans de que es modifiquin. Un cop ja disposem de l’adreça on es troben els coeficients que volem enviar, ja podem començar a enviar l’adreça del TAS3001 pel bus I2C. Seguidament enviarem la primera dada que es troba en TASDATA que es correspon a la subadreça del registre del canal esquerra del filtre que volem actualitzar. Un cop enviades l’adreça i la subadreça, el programa haurà de llegir els valors que es troben en la posició de memòria que apunten els registres TBLPTRL, TBLPTRH i TBLPTRU. A mida que es van llegint els anem enviant al TAS3001 pel bus I2C. Quan ja haguem enviat els 15 bytes s’envia la condició de STOP. Un cop actualitzat el registre del canal esquerre, recuperem l’adreça de la posició de memòria on es troben els coeficients que hem d’enviar. També recuperem la subadreça del registre del canal dret i la copiem a TASDATA. Seguidament es procedeix a actualitzar el registre del filtre del canal dret de la mateixa manera que hem fet amb el canal esquerra. Quan la transmissió dels coeficients ha finalitzat es surt de la funció.

4.3.3.9. Update_EQ_predef La taula que conté els coeficients corresponents a l’equalitzador predefinit està formada per 5 blocs, un per cada tipus de filtre (menys l’uniforme). Cada bloc està format per 6 files de 16 bytes, una per cada filtre. Per tant per obtenir l’adreça on es troben els coeficients que volem enviar, primer obtenim l’adreça del inici de la taula i desprès li sumem el resultat de multiplicar el valor de Quin_EQ_pre (que pot ser de 0 a 4 ja que pel 5, que és l’uniforme, no hi ha taules) per 96 (16 bytes * 6 files). L’adreça obtinguda, igual que en l’apartat anterior, la guardarem a TBLPTRL, TBLPTRH i TBLPTRU. Un cop tenim l’adreça dels coeficients que volem enviar, enviarem els coeficients al TAS3001 de la mateixa manera que ho fèiem en update_EQ_graf. En aquest cas, però, cal enviar els coeficients dels sis filtres. Quan s’acabin d’enviar els coeficients del primer filtre els valors de l’adreça que es troba en TBLPTRL, TBLPTRH i TBLPTRU apuntarà a la 46

CAPÍTOL 4: Implementació

primera posició dels coeficients del segon filtre. Per tant només caldrà canviar la subadreça del biquad i tornar a repetir el mateix procés que en el primer filtre. Aixó es repetirà fins que haguem actualitzat tots els filtres del TAS3001. Al principi es comprovarà el valor de Quin _EQ_pre i, si és igual a 5 (uniforme) el procés que seguirem serà completament diferent al de la resta d’equalitzadors predefinits. En aquest cas enviarem un senyal de reset al TAS3001 que ens deixarà tots els filtres biquad passa tot. A continuació caldrà actualitzar el valor del registre MCR cridant a la funció send_MCR. També modificarem el guany del mesclador mitjançant la funció update_mixer i el volum mitjançant la funció update_volum.

4.3.3.10. Update_filtre Aquesta funció és molt similar a la funció update_EQ_graf. L’única diferència està en l’obtenció de la posició de memòria on es troben els coeficients que volem enviar. Per poderho entendre cal explicar en detall com organitzarem en memòria els coeficients segons els paràmetres del equalitzador. La taula del equalitzador paramètric està composada per 4 blocs, un per cada ample de banda. Cada un d’aquests blocs conté 30 subblocs cada un dels quals es correspon a un valor de freqüència central. Cada subbloc el formen 25 files corresponents als 25 valors possibles de guany. Igual que en el cas de les taules del equalitzador gràfic cada fila conté 16 bytes, 15 dels quals són els coeficients corresponents al filtre. Per poder conèixer la posició de memòria en la que es troben els coeficients que volem enviar, el primer que cal fer és obtenir l’adreça en la que es troba el principi de la taula. A continuació a partir del valor de Q li sumarem a la adreça de la primera posició de memòria 12000 multiplicat pel valor de Q (recordem que el valor de Q anava de 0 a 3). El valor 12000 prové de calcular la mida que ocupa cada bloc, multiplicant 30 (número de freqüències centrals possibles) per 25 (número de guanys per cada freqüència) i per 16 que és el número de bytes que ocupa cada una de les opcions. D’aquesta manera l’adreça apuntarà a la primera posició de memòria corresponent a un ample banda determinat. Cada subtaula corresponent a una freqüència conté 25 files de 16 bytes cada una. Per tant per arribar a la primera posició de memòria de la subtaula corresponent a la freqüència indicada per f0 caldrà multiplicar el valor de f0 per 25*16 i sumar el resultat a l’adreça calculada anteriorment a partir del valor de Q. Per acabar serà necessari igual que fèiem en l’equalitzador gràfic sumar a l’adreça el valor de la variable G corresponent al guany multiplicada per 16. Com hem dit al principi, la resta de funció és molt similar a la funció update_EQ_grafic. Depenent del filtre que vulguem actualitzar guardarem la subadreça del registre d’un canal a TASDATA i l’altre en una altre variable. Després d’obtenir l’adreça on es troben els coeficients que volem enviar, la guardem per quan enviem els coeficients pel filtre de l’altre canal que seran els mateixos. A continuació s’envien els 15 bytes dels coeficients al TAS3001 a la subadreça que hem guardat a TASDATA i seguidament els tornem a enviar a l’altre subadreça. Un cop s’han enviat tots els coeficients es surt de la funció.

47

CAPÍTOL 4: Implementació

4.3.4. SUBMENÚ DE VOLUM

Figura 4.3: Diagrama de blocs del submenú de volum

Quan arribem al submenú de volum prement el polsador DOWN el primer que es fa és mirar si el control de volum està ja en el seu límit inferior. Si es així es retorna al menú principal. En cas de que el volum no estigui en el mínim, es decrementa la variable V i es crida a la funció update_volum que hem explicat en l’apartat anterior per enviar el nou volum al TAS3001. També es cridarà a la funció LCD_V que mostrarà per pantalla el nou volum seleccionat. En aquest cas, en el que els polsadors no s’utilitzen per canviar de menú, sinó que s’utilitzen per canviar variables, no esperarem a que es deixin de prémer els polsadors sinó que si l’usuari manté premut el polsador el paràmetre seguirà canviant cada cert temps. En aquest cas després d’enviar el nou volum al processador d’àudio i mostrar el seu valor per pantalla, es produirà un retard de 250ms i després es comprovarà si el polsador segueix estant premut. Si s’ha deixat de prémer el polsador es mantindrà el missatge en pantalla i passarem a un bucle infinit esperant a que es polsi algun polsador. Si per el contrari el polsador es manté premut tornarem al principi a comprovar si estem en el mínim i es repetirà el que em explicat fins ara. Això es repetirà consecutivament fins que s’arribi al mínim i tornem al menú principal o fins que es deixi de prémer. En el bucle infinit en el que s’entra quan es deixa de prémer el polsador, es testegen totes les entrades corresponents als polsadors repetidament fins que algun es prem. Si es prem DOWN es torna a la part de programa en la que es comparava el volum amb el mímim volum. Si es prem UP es procedeix a pujar el volum. Si es prem SET es retorna al menú principal. En el cas en que es vulgui pujar el volum el procediment que es seguirà serà exactament el mateix que per baixar-lo. La única diferència és que en aquest cas on parlàvem del polsador DOWN ara es el UP i el volum el compararem al el volum màxim, no amb el mínim. En la figura 4.3 es pot veure clarament el funcionament del programa que acabem d’explicar. A continuació explicarem les funcions utilitzades en aquest punt que no hagin estat explicades en punts anteriors.

4.3.4.1. LCD_V Aquesta funció ens mostrarà per pantalla el missatge “volum”, un espai en blanc i el valor del volum. En aquest apartat explicarem en detall com s’envia aquest missatge a pantalla i en la resta de funcions similars com LCD_G o LCD_Q només indicarem el missatge que s’envia

48

CAPÍTOL 4: Implementació

i explicarem les petites diferències que hi hagi. Per aquesta funció, és necessari utilitzar funcions relacionades amb el LCD que s’expliquen en més detall en el apartat 4.3.9. La manera com enviem un caràcter a la pantalla, és la mateixa per tots. El primer que cal fer és passar el caràcter que volem enviar a la variable temp_wr i després es crida a la funció d_write que escriurà el caràcter en la pantalla i mourà el cursor a la següent posició. El primer que cal fer és cridar la funció LCDLine_1 per enviar el cursor a la primera posició de la primera línia del LCD. Seguidament enviem caràcter a caràcter primer 4 espais en blanc “ ” i després “Volum”. A continuació s’envia un altre espai “ ” i es copia el valor de V al registre W per a continuació cridar a la funció XLCDPutNumber que mostra per pantalla el número que li hem passat per W. Per acabar d’omplir la primera línia enviem quatre caràcters més en blanc. Quan ja hem escrit tota la primera línia cridem a la funció LCDLine_2 per que el cursor es mogui al principi de la segona línia del LCD. A continuació s’han d’enviar 16 caràcters en blanc. En la primera línia enviaven els caràcters d’un en un perquè, segons el volum, el número que es mostra és diferent. Si féssim taules amb el contingut de tota la fila caldria emmagatzemar 16 bytes per cada línia i en el cas del volum necessitaríem 30 línies i per LCD_G, LCD_Q i altres necessitaríem molt espai de memòria. Per aquest motiu s’utilitza la funció XLCDPutNumber. Per la segona línia, però, com per a tots els casos, hem d’escriure en pantalla el mateix, emmagatzemem la línia en la memòria de programa. Per escriure aquesta línia cal cridar la funció stan_char_2 després de haver introduït en la variable ptr_pos el número de la fila on es troba el que volem escriure de la taula de missatges per al LCD.

4.3.4.2. XLCDPutNumber Com hem dit anteriorment, aquesta funció mostra per pantalla el número que li passem pel registre W. Per fer-ho, cal obtenir les desenes i les unitats per separat. El sistema que utilitzarem serà comparar el número amb 10, i si és més gran, incrementarem en 1 el número de desenes i l’hi restarem 10 al número original fins que aquest sigui menor que 10. El número que ens queda després de haver restat totes les desenes són les unitats. Un cop hem obtingut el valor de desenes i unitats cal obtenir el codi ASCII dels dos valors. Això es pot aconseguir fàcilment sumant als números 48. Un cop s’ha sumat 48 als valors de les desenes i unitats ja es poden enviar els dos valors al LCD.

4.3.4.3. Stan_char_1 Aquesta funció escriurà una línia sencera en el LCD. La línia de la taula del LCD que haurà d’escriure se li passarà mitjançant la variable ptr_pos. El primer que farà és moure el cursor a la primera posició de la primera línia mitjançant la funció LCDLine_1. A continuació cal obtenir l’adreça de la primera posició de memòria on es troba la taula del LCD. A continuació hem de multiplicar el valor de ptr_pos que és la línia on es troba el que volem escriure per 16 bytes que és la mida de cada línia. El valor obtingut li sumarem a la adreça i obtindrem la adreça de la posició de memòria que ocupen les dades que volem enviar. Un cop ja es té la adreça, s’entra en un bucle que es repetirà 16 vegades, una per cada caràcter. En aquest bucle el que es farà és llegir cada cop un caràcter i enviar-lo al LCD. Quan s’hagin enviat els 16 caràcters que composen la línia del LCD es sortirà de la funció.

49

CAPÍTOL 4: Implementació

4.3.4.4. Stan_char_2 Aquesta funció és idèntica a stan_char_1 excepte en el principi on en lloc de cridar a la funció LCDLine_1 es crida a la funció LCDLine_2 ja que aquesta funció serveix per escriure la segona línia del LCD.

4.3.5. MENÚ EQUALITZADOR GRÀFIC

Figura 4.4: Diagrama de blocs del menú equalitzador gràfic

Quan desde el submenú de l’equalitzador gràfic es prem el polsador SET el primer que es fa és comprovar quin és l’equalitzador que s’està utilitzant en aquell moment comparant la variable Quin_EQ amb 0, que és valor que tindria si s’estigués utilitzant l’equalitzador gràfic. Si el seu valor és diferent de 0 caldrà canviar-lo a 0 i cridar a la funció load_EQ per carregar els coeficients corresponents als últims paràmetres que havíem emmagatzemat corresponents a l’últim equalitzador gràfic utilitzat. Aquesta funció, és la mateixa que hem utilitzat al inici del programa i es pot trobar explicada en detall en el punt 4.3.3.1. Un cop enviats tots els coeficients al TAS3001 si ha estat necessari, es mostrarà per pantalla la freqüència corresponent al primer filtre que es 63Hz. Per mostrar per pantalla aquest missatge utilitzarem les funcions explicades en l’apartat anterior stan_char_1 i stan_char_2 passant per la variable ptr_pos la posició que ocupa el missatge que volem enviar en la taula del LCD. Quan ja s’ha mostrat per pantalla el missatge corresponent, s’entra en un bucle infinit en el que el programa espera a que l’usuari premi algun polsador. Amb els polsadors UP i DOWN ens desplaçarem per les diferents bandes que formen l’equalitzador gràfic de manera rotativa. La seqüència que es seguirà a partir de la banda de 63Hz i si polsem UP serà la següent: 63Hz, 250Hz, 1kHz, 4kHz, 16kHz i sortida del menú de l’equalitzador gràfic. Un cop arribem a la opció de sortida si tornem a prémer UP es tronarà a 63Hz. Amb el polsador DOWN recorrerem el camí invers. Per cada una de les bandes el procediment serà el mateix que en la

50

CAPÍTOL 4: Implementació

de 63Hz, es mostrarà per pantalla la freqüència que correspongui, i s’esperarà en un bucle infinit fins que es premi algun polsador. Per a qualsevol de les bandes, si mentre estem en bucle infinit es prem el polsador SET, el primer que es farà és indicar el filtre que volem modificar. Si ens trobem en el filtre de 63Hz introduirem un 1 en la variable filtre, per el filtre de 250Hz el valor de filtre haurà de ser 2 i així consecutivament fins al filtre de 16kHz per al qual el valor de la variable filtre haurà de ser 5. Un cop hem indicat el filtre que volem modificar cal introduir el valor de la variable G_BiquadX_g en la variable G on X+1 és el valor de filtre. Un cop introduït aquest valor cridarem a la funció show_G_g que mostrarà per pantalla el valor de guany i el podrem modificar. Quan es retorni de la funció el valor del nou guany del filtre que haguem seleccionat es trobarà en la variable G i l’haurem de tornar a emmagatzemar en la variable corresponent G_BiquadX_g. Quan acabem de modificar un valor de guany d’un filtre i sortim anirem directament a mostrar la freqüència següent. En el cas en que ens trobem en l’opció de sortida si premem el polsador SET sortirem del menú de l’equalitzador gràfic i tornarem al submenú de selecció de equalitzador mostrant per pantalla el missatge del equalitzador gràfic. Per tots els casos que hem explicat després de la pulsació d’un polsador esperarem a que aquest es deixi de prémer de la mateixa manera que fèiem en el menú principal.

4.3.5.1. Show_G_g El funcionament d’aquesta funció és molt similar a la funció show_V. El primer que caldrà fer serà cridar a la funció LCD_G que ens mostrarà per pantalla el missatge “Guany=” i a continuació el valor del guany actual. Quan es retorni d’aquesta funció entrarem en un bucle infinit esperant a que es premi algun polsador. Si es prem el polsador UP es comprovarà que el control de guany no hagi arribat al seu límit superior. Si la variable G té el valor màxim permès, tornarem al bucle infinit a esperar a que es torni a polsar un altre polsador. Si pel contrari encarà no ens trobem en el màxim, incrementarem en 1 el valor de la variable G i cridarem a la funció update_EQ_graf que ja hem explicat en el punt 4.3.3.8. Aquesta ens actualitzarà els registres del TAS3001 del filtre corresponent que recordem que ho indiquem mitjançant la variable filtre que ja ha estat actualitzada. Això es fa perquè a mida que l’usuari variï el valor de guany, pugui escoltar la variació per cada increment. Després d’enviar el nou filtre al processador d’àudio es procedirà a mostrar per pantalla el nou valor de guany mitjançant la mateixa funció LCD_G. Igual que fèiem per al volum, si el polsador es manté premut continuarem augmentant el guany seguint el mateix procediment (comprovar màxim, enviar coeficients al TAS3001 i mostrar el nou valor per pantalla). Si el polsador no es manté premut es tornarà al bucle infinit a esperar que hi hagi noves pulsacions. En el cas en que es premi DOWN en lloc de UP, el procediment serà el mateix però en aquest cas comprovant el límit inferior i decrementant el valor de G. Si mentre estem en bucle infinit es prem SET esperarem a que es deixi de prémer i sortirem de la funció.

4.3.5.2. LCD_G Aquesta funció ens servirà tant per mostrar el guany en el cas del equalitzador gràfic com en el paramètric. Per entendre aquesta funció cal recordar com emmagatzemàvem el valor del guany pels dos casos i a quins valors de guanys es corresponien. El valor del guany el guardàvem en la variable G_BiquadX_g o G_BiquadX i podia prendre valors de 0 a 24. Per 51

CAPÍTOL 4: Implementació

un valor de la variable de 0 el guany és de -12dB i per un valor de 24 el guany és de 12dB i per valors intermedis cada increment de la variable suposa un increment de un dB en el guany. Per tant el valor de guany que haurem de mostrar per pantalla serà el valor la variable G menys 12. El valor de G el copiarem a Gbis perque aquest no es modifiqui al restar-li 12. Per començar a escriure la primera línia cridem a la funció LCDLine_1 i a continuació escriurem 4 espais en blanc al LCD igual que fèiem en LCD_V. Seguit dels quatre espais escrivim el missatge “Guany=” caràcter a caràcter. A continuació, cal escriure el valor de guany i per fer-ho haurem de restar 12 al valor que conte Gbis. Si de la resta obtenim un número positiu es procedirà a copiar-lo a W i cridar a la funció XLCDPutNumber. Si pel contrari el número obtingut és negatiu a bans de cridar a la funció XLCDPutNumber caldrà escriure el caràcter “-” i negar en complement a dos el valor de Gbis per obtenir el mateix valor en positiu. En el cas en que haguem escrit un valor positiu, a continuació enviarem 4 caràcters en blanc mentre que en cas en que haguem escrit el “-” només escriurem 3 caràcters en blanc. A continuació escriurem a la segona fila els 16 caràcters en blanc tal com fèiem en LCD_V utlitzant la funció Stan_char_2.

4.3.6. MENÚ EQUALITZADOR PREDEFINIT

Figura 4.5: Diagrama de blocs del menú equalitzador predefinit

Quan ens trobem en el submenú de l’equalitzador predefinit i es prem el polsador SET, el primer que es fa és comprovar el valor de Quin_EQ. Si el seu valor és igual a “1” significa que els filtres que estem utilitzant en el TAS3001 són els corresponents a l’equalitzador predefinit i per tant no cal carregar-los. Si per el contrari el valor és diferent a “1” el ficarem a “1” i enviarem al TAS3001 els coeficients corresponents a l’últim equalitzador predefinit que s’hagi utilitzat cridant a la funció update_EQ_predef. Un cop ja tenim els filtres desitjats en el TAS3001 mostrarem per pantalla l’equalitzador seleccionat. Per fer-ho escriurem en la variable ptr_pos la línia en que es troba el primer missatge corresponent al equalitzador predefinit que és “ROCK” i li sumarem el valor de la variable Quin_EQ_pre, ja que en les línies successives es troben la resta de missatges. Un valor de Quin_EQ_pre igual a 0 es correspon al equalitzador ROCK i un valor igual a 5 es correspon al UNIFORME. Cada un dels valors intermedis es corresponen a la resta d’equalitzadors que podem veure en la figura 4.5 en el sentit contrari a les agulles de rellotge.

52

CAPÍTOL 4: Implementació

Seguidament es mostrarà el missatge per pantalla de la mateixa manera que fèiem en la resta de missatges. A continuació s’entra en un bucle infinit a l’espera de que es premi algun polsador. Tal com s’observa en la figura 4.5 prement UP i DOWN ens desplaçarem pels diferent tipus d’equalitzador predefinit. Cada cop que es premi un dels dos polsadors modificarem el valor de Quin_EQ_pre, cridarem a la funció update_EQ_predef, i mostrarem per pantalla l’equalitzador que hem seleccionat. Estant en qualsevol dels equalitzadors predefinits, si es prem el polsador SET, com els coeficients corresponents ja estan carregats en el TAS3001, es sortirà directament tornat al submenú del equalitzador predefinit. Totes les funcions utilitzades han estat explicades en apartats anteriors.

4.3.7. MENÚ EQUALITZADOR PARAMÈTRIC

Figura 4.6: Diagrama de blocs del menú equalitzador paramètric

El funcionament d’aquest menú és molt similar al del menú de l’equalitzador gràfic. En aquest cas també tenim un menú rotatori per el qual ens podem desplaçar mitjançant els polsadors UP i DOWN. En aquest cas, però, com la freqüència central del filtre varia el missatge que apareix en pantalla no és la freqüència sinó que mostrem el missatge “Filtre X” on X pren els valors de 1 a 6. També, al principi si s’estava utilitzant un altre filtre carregarem els coeficients dels últims filtres que havien estat utilitzats en l’equalitzador paramètric. Un altre diferència és que en aquest cas l’usuari pot escollir l’ample de banda i la freqüència central a més del guany. Per aquest motiu el procediment a seguir quan estem en 53

CAPÍTOL 4: Implementació

un filtre i polsem SET serà diferent al de l’equalitzador gràfic. A continuació explicarem en detall que farà el programa en aquest cas. Per a poder utilitzar les mateixes funcions per tots els filtres, el primer que cal fer al polsar SET és emmagatzemar en la variable filtre el número del filtre que anem a modificar. A continuació copiarem en les variables genèriques G,Q i f0 els valors actuals dels paràmetres corresponents al filtre que volem modificar. Copiarem el valor de G_BiquadX a G, Q_BiquadX a Q i f0_BiquadX a f0 on X+1 és el número del filtre modificarem. A continuació cridarem a la funció show_freq que ens mostrarà per pantalla la freqüència central actual i ens permetrà variar-la entre un límit superior i un límit inferior. Quan es retorna de la funció cal guardar el nou valor de freqüència que es troba a f0 a la variable f0_BiquadX corresponent. A continuació procedirem de la mateixa manera per modificar l’ample de banda i el guany cridant a les funcions show_Q i show_G. Al acabar de modificar tots els paràmetres es mostrarà per pantalla el següent filtre.

4.3.7.1. Show_freq Aqueta funció és equivalent a la funció show_G_g, només cal canviar les variables per les seves equivalents en el cas de freqüència i el mateix pels valors màxims i mínims. La única diferencia és que en aquest cas per mostrar per pantalla el valor de la freqüència cridarem a la funció LCD_freq. També cal tenir en compte que per enviar els coeficients al TAS3001 en lloc d’utilitzar la funció update_EQ_graf serà necessari utilitzar la funció update_filtre.

4.3.7.2. Show_Q Aquesta funció és equivalent a la anterior però en aquest cas en que es canvia l’ample de banda. La funció utilitzada per mostrar per pantalla el valor de l’ample de banda és LCD_Q.

4.3.7.3. Show_G Aquesta funció també és equivalent a les funcions que acabem d’explicar. Per actualitzar el valor de guany que es mostra per pantalla es crida a la funció LCD_G que és la mateixa en les dues funcions show_G_g i show_G i per això no la expliquem a continuació.

4.3.7.4. LCD_freq Aquesta funció és diferent a la que mostrava el volum o el guany ja que en aquest cas no es pot mostrar el valor de la freqüència a partir de la variable que ens diu la freqüència que estem utilitzant. Tots els missatges de totes les possibles freqüències estaran emmagatzemats a la taula del LCD. Els missatges de les freqüències es troben al principi de la taula del LCD i per tant la línia en el que es troben és directament el valor que tenim en f0 que recordem que va de 0 a 29. Per tant només caldrà cridar a la funció LCDLine_1, copiar el valor de f0 a ptr_pos i cridar a la funció stan_char_1. A la segona fila del LCD hi escriurem els 16 caràcters en blanc.

4.3.7.5. LCD_Q Aquesta funció és igual que l’anterior amb l’única diferència que, en aquest cas, els missatges corresponents a l’ample de banda no es troben al principi de la taula. Per aquest

54

CAPÍTOL 4: Implementació

motiu el valor que escriurem a ptr_pos serà el valor que tenim en Q més 47 que és la línia de la taula del LCD en la que es troba el primer missatge corresponent al ample de banda.

4.3.8. SORTIDA DELS SUBMENÚS En la sortida dels submenús el que fem es guardar tots els paràmetres dels filtres mitjançant la funció save_EQ a la memòria EEPROM i tornar al menú principal.

4.3.8.1. Save_EQ En aquesta funció emmagatzemarem les variables descrites en el punt 4.3.2 per si s’apaga l’equalitzador poder recuperar-les al tornar a iniciar-lo. El primer que cal fer és indicar l’adreça de la memòria EEPROM en la que volem emmagatzemar la variable introduint-la en els registres EEADRH i EEADR. A continuació introduirem el byte que volem emmagatzemar en el registre EEDATA. Per accedir a la memòria EEPROM hem de ficar a “0” els bits EEPGD i CFGS del registre EECON1. Per habilitar la opció d’escriptura es fica a “1” el bit WREN del mateix registre. Per a deshabilitar les interrupcions posarem a “0” el bit GIE del registre INTCON. A continuació, per poder escriure en la memòria EEPROM s’ha de seguir una seqüència que consisteix en escriure primer el valor 55h i després el 0AAh en el registre EECON2. Un cop s’ha realitzat aquesta seqüència ja es pot començar la escriptura posant a 1 el bit WR del registre EECON1. El programa espera a que s’acabi el procés d’escriptura esperant a que el valor de WR torni a ser “0” i a continuació es tornen a habilitar les interrupcions i es deshabilita l’escriptura a la EEPROM tornat el bit GIE i WREN al seu valor original. MOVLW MOVWF MOVLW MOVWF MOVF MOVWF BCF BCF BSF BCF MOVLW MOVWF MOVLW MOVWF BSF BTFSC BRA BSF BCF

d'0' EEADRH d'0' EEADR V,W EEDATA EECON1, EEPGD EECON1, CFGS EECON1, WREN INTCON, GIE 55h EECON2 0AAh EECON2 EECON1, WR EECON1, WR $-2 INTCON, GIE EECON1, WREN

4.3.9. FUNCIONS LCD Totes les funcions necessàries per poder utilitzar el mòdul LCD es trobaran en l’arxiu LCD.asm, i es podran utilitzar en el programa principal definint les funcions com externes (EXTERN) en el programa principal i com a globals (GLOBAL) en el programa que es troba en LCD.asm. A part de les funcions també definirem temp_wr com a variable global per

55

CAPÍTOL 4: Implementació

poder modificar-la des de el programa principal on la definirem com a variable externa. Totes aquestes funcions les explicarem a continuació.

4.3.9.1. LCDLine_1 Aquesta funció ens permet moure el cursor a la primera posició de la primera línia del LCD. Per fer-ho és necessari enviar una instrucció mitjançant la funció i_write perquè RS i R/W siguin “0”. Els bits de dades els passarem per la variable temp_wr i el seu valor serà 80h on el “1” en el bit setè significa que enviem una adreça de la DDRAM i la resta de bits és la adreça.

4.3.9.2. LCDLine_2 Aquesta funció és equivalent a la anterior però, en aquest cas, l’adreça es 40h i per tant com el bit 8 ha de ser “1” el valor que passarem per temp_wr serà C0h.

4.3.9.3. d_write El primer que fa aquesta funció és comprovar si el LCD està ocupat i esperar fins que estigui lliure. Això ho fem cridant a la funció LCDBusy. A continuació posem a “1” el bit C del registre STATUS que és el valor que ha de prendre RS per indicar que volem escriure dades. Per acabar cridem a la funció LCDWrite.

4.3.9.4. i_write Aquesta funció només es diferència de l’anterior en que, com volem escriure una instrucció el valor de RS i, per tant, el que passarem pel bit C ha de ser igual a “0” en aquest cas.

4.3.9.5. rlcd Aquesta funció és del tipus macro i se li passarà un valor. Si el valor és igual a “1” posarem el bit C del registre STATUS a “1” i cridarem la funció LCDRead. Sinó es posarà el bit C a “0” i també es cridarà la mateixa funció LCDRead.

4.3.9.6. LCDInit El primer que fem en aquesta funció és configurar les línies de control com a sortides. A continuació, seguirem l’esquema de la figura 3.21. Primer enviarem el valor 3h tres cops utilitzant la funció LCDWriteNibble (el valor de temp_wr haurà de ser 30h) separats dels retards corresponents que implementarem amb la funció DelayXCycles. Després enviarem el valor 2h també amb LCDWriteNibble i a partir d’aquí ja es podran enviar bytes complets utilitzant la funció LCDWrite. A partir d’aquest punt els bytes que haurem d’enviar no es corresponen amb els de la figura ja que configurarem el LCD de manera diferent. A continuació explicarem els valors dels bytes que enviarem i tots s’enviaran de la mateixa manera. Només caldrà copiar el valor que correspongui en temp_wr i cridar a la funció i_write. La primera instrucció es correspon a Function Set (punt 3.5) i enviant el valor 28h seleccionarem el mode de 4 bits, dos files i el format del caràcter de 5x8.

56

CAPÍTOL 4: Implementació

La segona instrucció és Display ON/OFF Control amb la que indicarem que el LCD estigui en ON, el cursor OFF i el parpelleig ON, enviant pel bus de dades el valor 0Dh. Amb la següent instrucció Clear display netejarem la pantalla. A continuació indicarem que volem que el cursor es mogui a la dreta sense desplaçament de la pantalla mitjançant la instrucció Entry Mode Set. El valor del bus de dades haurà de ser 06h. Per últim, amb la funció Set DDRAM Address introduirem la adreça 00h de la DDRAM enviant el valor 80h.

4.3.9.7. LCDWriteNibble Aquesta funció només envia al LCD els 4 bits superiors de la variable temp_wr. El primer que cal fer és posar la sortida corresponent a R/W a nivell baix i la corresponent a RS a nivell baix o alt segons indiqui el valor del bit C del registre STATUS. A continuació és necessari configurar els pins per on enviarem les dades com a sortides. Amb la execució d’aquesta part de codi i un petit retard constituït per dos NOPs ja passa el temps mínim necessari per poder ficar a nivell alt la sortida E. Durant el temps que E ha d’estar a nivell alt fiquem a les sortides de dades el que volem enviar que són els bits del 4 al 7 de la variable temp_wr. Després d’executar dos NOPs tornem el valor de E a nivell baix per indicar al LCD que ja pot llegir les dades.

4.3.9.8. LCDWrite Com hem vist en l’apartat anterior LCDWriteNibble envia només 4 bits. Per enviar el byte complet que es troba en la variable temp_wr cal enviar-lo en dos vegades i aixó és el que fa aquesta funció. El primer que fa es cridar a la funció LCDWriteNibble per escriure els bits més alts. A continuació mitjançant la instrucció swapf canviem l’ordre dels bits de temp_wr. Per exemple, si en la variable temp_wr tenim ABCDEFGH, al utilitzar aquesta instrucció el valor de temp_wr ens queda EFGHABCD. Un cop canviada la posició dels bits tornem a cridar la funció LCDWriteNibble perquè enviï la resta de bits al LCD. A continuació mitjançant la instrucció swapf tornem a temp_wr wl seu valor inicial.

4.3.9.9. LCDRead El funcionament d’aquesta funció és molt similar al de LCDWriteNibble. El primer que fem és configurar els pins del bus de dades com a entrades. A continuació modifiquem el valor de RS segons el valor que se li passa pel bit C del registre STATUS. També posem la sortida corresponent a R/W a nivell alt per indicar que volem llegir. Després d’un petit retard posem a nivell alt la sortida corresponent a E. Després d’un petit retard ja podem llegir les dades. Les dades es llegiran bit a bit i les emmagatzemarem en la posició corresponent de la variable temp_rd. Un cop llegits els quatre primers bits, ho indiquem al mòdul LCD tornant la sortida E a nivell baix. Després d’un altre petit retard tornem a posar a nivell alt la sortida E per llegir els bits restants. Un cop llegits tornarem a nivell baix E i sortirem de la funció.

57

CAPÍTOL 4: Implementació

4.3.9.10. LCDBusy Aquesta funció ens permetrà saber si el controlador està ocupat mitjançant la instrucció Ready Busy flag. El primer que cal fer és cridar a la funció rlcd passant-li el valor 0 ja que es tracta d’una instrucció. Un cop executada aquesta funció tenim el valor que s’ha llegit a temp_rd. Si el valor del bit 7 de temp_rd és igual a 0, vòl dir que no està ocupat i sortirem de la funció. Si el seu valor és igual a 1, tornarem a repetir el mateix procés fins que valgui 0.

4.3.9.11. DelayXCycles Aqueta funció consisteix en un bucle que decrementa el valor de la variable delay repetidament fins que aquesta val 0 i surt de la funció.

4.3.10. FUNCIONS I2C Igual que en el cas de les funcions necessàries per comunicar-se amb el LCD per utilitzar el bus I2C també tenim un programa amb totes les funcions necessàries que rep el nom de I2C.asm. Per poder utilitzar aquestes funcions des de el programa principal les definirem coma GLOBAL i en el programa principal com a EXTERN. Les variables TASADDR i TASDATA també les definirem com a globals per poder ser utilitzades des de el programa principal. A continuació s’explicaran les funcions que conté aquest programa.

4.3.10.1. WakeSlave Aquesta funció genera la condició de START del bus I2C. Per fer-ho només cal ficar a “1” el bit SEN del registre SSPCON2. A continuació s’esperà en un bucle infinit fins que el valor de SEN torni a valer “0”, moment en el qual es surt de la funció.

4.3.10.2. WrADDR Aqueta funció enviarà pel bus I2C l’adreça del dispositiu esclau i s’esperarà fins que l’esclau enviï el senyal de reconeixement ACK. El primer que es fa és posar a “0” el bit SSPIF del registre PIR1. A continuació es copia el valor de TASADDR al registre SSPBUF i ens esperem a que l’adreça s’hagi enviat testejant el valor de SSPIF fins que aquest torna a valer “1”. Això, vòl dir que l’adreça ja ha estat enviada. A continuació, ens esperarem fins que es rebi el senyal de reconeixement testejant el valor del bit ACKSTAT del registre SSPCON2 fins que aquest valgui “0”, moment en el qual es sortirà de la funció.

4.3.10.3. WrDATA Aquesta funció és quasi igual que la funció anterior WrADDR. La única diferència és que en aquets ca el valor que introduïm en SSPBUF serà el valor que conté la variable TASDATA ja que aquesta funció serveix per enviar dades al pel bus I2C.

58

CAPÍTOL 4: Implementació

4.3.10.4. Stop La condició de STOP es genera posant a “1” el bit PEN del registre SSPCON2. Un cop fet això s’ha d’esperar ha que s’acabi d’enviar testejant el valor de PEN que canviarà automàticament quan s’hagi acabat d’enviar el STOP.

4.3.10.5. Utilització de les funcions El procés a seguir a la hora d’actualitzar els valors dels registres del TAS3001 sempre serà el mateix sigui quin sigui el registre que volem actualitzar. Abans de començar a explicar aquest procés, cal dir que per fer més entenedor el programa, mitjançant “#define” hem assignat noms a les adreces i subadreces. Al valor de l’adreça I2C del TAS3001 se l’anomena slave_addres i les subadreces dels registres reben el nom del registre i es troben definides en l’arxiu subaddres.def. El primer que cal fer, és copiar slave_addres a TASADDR i la subadreça del registre a TASDATA que són les variables que utilitzen les funcions explicades anteriorment per enviar al TAS3001. Un cop fet això ja es pot cridar a la funció WakeSlave i, a continuació, a WrADDR i WrDATA. Segudament, cal enviar tants bytes com siguin necessaris depenent del registre que es vulgui actualitzar. Només cal copiar el valor que volem enviar en TASDATA i cridar a la funció WrDATA tants cops com variables vulguem enviar. Després d’enviar totes les dades haurem de cridar a la funció Stop.

59

CAPÍTOL 5: Conclusions

CAPÍTOL 5: Conclusions Per arribar al disseny final del equalitzador digital d’àudio ha estat necessari el muntatge de tres plaques. La primera placa muntada era de pitjor qualitat i va ocasionar molts problemes no només a nivell de hardware, sinó que també a nivell software. Malgrat això amb aquesta placa connectada a una placa de proves de microchip amb el PIC18F452 es va dissenyar la major part del programa, i vaig adquirir tots els coneixement necessaris que hem van permetre aconseguir que les següents versions funcionessin correctament. Per a la segona versió de la placa, es van modificar alguns footprints que eren incorrectes, i es va fabricar una placa de major qualitat que la primera. Amb aquesta segona versió es van muntar dos plaques, una amb el PIC18F2520, i un altre amb el PIC18F2620 i les dues funcionen correctament. El motiu per el que es va canviar el microcontrolador es que en el primer no podíem introduir totes les taules de coeficients desitjades i es va optar per utilitzar el PIC18F2620 que ens permetia utilitzar el mateix software que en el PIC18F2520 però que tenia el doble de memòria de programa. L’equalitzador dissenyat, disposa d’una entrada de senyal d’àudio estèreo RCA i tres sortides, una RCA per on surt el senyal no amplificat, un altre del tipus jack que es correspon a la sortida amplificada per auriculars i la tercera que proporciona el senyal amplificat on es poden connectar altaveus. L’equalitzador es controla mitjançant tres polsadors un de pujada, un de baixada i un de selecció i un mòdul LCD on es mostren les diferents opcions que es poden seleccionar. Mitjançant el circuit dissenyat, podem controlar el volum de sortida i filtrar el senyal d’entrada amb tres tipus diferents d’equalitzadors. Un dels equalitzadors, és un equalitzador gràfic de cinc bandes que ens permet modificar el guany de cada banda de -12dB a 12dB amb salts de 1dB. El segon és un equalitzador paramètric de sis bandes. Per cada una de les bandes podem escollir 4 amples de banda, 30 freqüències centrals separades 1/3 d’octava entre elles i modificar el guany de -12dB a 12dB amb salts de 1dB. El tercer, és un equalitzador predefinit que ens permet escollir entre 6 tipus d’equalitzadors diferents. Em aconseguit aprofitar al màxim les prestacions del TAS3001 tal com es pretenia. Però per aconseguir-ho hem utilitzat un mòdul LCD i un PIC de gama alta i això ha encarit el disseny final considerablement. Partint de la idea original de dissenyar l’equalitzador pensat per a la seva utilització en caixes acústiques no existeixen gaires possibilitats de línies futures. L’únic que podríem fer és dissenyar una tercera versió en la que modifiquéssim els footprints dels connectors ja que els components per als que es van crear estan actualment descatalogats. Això ens permetria soldar els connectors directament a la placa. Un altre possible modificació, seria permetre que els amplificadors de potència es poguessin desconnectar ja que en la placa dissenyada sempre estan actius i si no s’utilitzen consumeixen potència innecessariament i s’escalfen més els reguladors de tensió. Partint del disseny realitzat en aquest projecte es podria simplificar i dissenyar altres tipus de filtres més econòmics també basats en el TAS3001. Una possible opció seria la que es proposa en el manual del TAS3001 en la que els filtres serien fixes i servirien per equalitzar la resposta freqüencial no lineal d’uns altaveus o un micròfon. En aquest cas no serien necessaris els amplificador de potencia ni els connectors per altaveus i auriculars. Al no haver-hi els amplificadors tampoc serien necessaris els reguladors de tensió de 12V i 5V. Tampoc caldria cap dispositiu com el LCD ni els polsadors per controlar els filtres ja que serien fixes. Per aquest aplicació només caldria un microcontrolador que disposés de bus I2C i d’una petita memòria per emmagatzemar només els coeficients de sis filtres, el convertidor

61

CAPÍTOL 5: Conclusions

A/D D/A d’àudio amb les etapes de front i back-end, el generador rellotge, i un regulador de tensió. El mateix tipus de circuit descrit anteriorment es podria utilitzar com a filtre de “crossover” per altaveus de varies vies.

62

Bibliografia

Bibliografia ARTICLES [1] G. W. McNally, “Digital Audio: Recursive Digital Filtering for High Quality Audio Signals,” BBC, Research Dept. Rep. 1981/10, 1981. [2] J. A. Moorer, “The Manifold Joys of Conformal Mapping: Applications to Digital Filtering in the Studio”, J. Audio Eng. Soc., vol. 31, No. 11, 1983. [3] S. A. White, “Design of digital Peaking or Notch Digital Filter for Digital Audio Equalization,” presented at the 78th Convention of the Audio Engineering Society, J. Audio Eng. Soc., vol. 34, No. 6, 1986 June. [4] P. A. Regalia and S. K. Mitra, “Tunable Digital Frequency Response Equalization Filters,” IEEE Trans. Acoust., Speech, Signal Process., Vol. ASSP-35, No. 1 ,1987. [5] D. J. Shpak, “Analytical Design of Biquadratic Parametric Filters”, IEEE Pacific Rim Conference on Communications, Computers and Signal Processing, May 9-10, 1991. [6] D. C. Massie, “An Engineering Study of the Four-Multiply Normalized Ladder Filter”, J. Audio Eng. Soc., vol. 41, No. 7/8, 1993. [7] R. Bristow-Johnson, “The Equivalence of Various Methods of Computing Biquad Coefficients for Audio Parametric Equalizers,” presented at the 97th Convention of the AES, San Francisco, November 1994, AES Preprint 3906. [8] S. J. Orfanidis, “Digital Parametric Equalizer Design With Prescribed Nyquist Gain”, presented at the 101th Convention of the Audio Engineering Society, J. Audio Eng. Soc., vol. 45, p. 444, 1997 June. [9] J. R. Clark, E. C. Ifeachor, G. M. Rogers, P. W. J. and Van Eelvelt, “Techniques for Generating Digital Equalizer Coefficients”, Manuscript received 1999 September 29, J. Audio Eng. Soc.,vol. 48, No.4, 2000April.

DOCUMENTACIÓ [10] Philips Semiconductors, “The I2C-Bus Specification”, versiò 2.1, Gener del 2000. [11] Microchip®, “In-Circuit Serial Programming™ (ICSP™) Guide”, Maig de 2003. [12] Microchip®, “MPLAB® ICD 2 In-Circuit Debugger User’s Guide”, 2005. [13] Microchip®, “PIC18 Configuration Settings Addendum”, 2005. [14] Microchip®, “MPASM™ Assembler, MPLINK™ Object Linker, MPLIB™ Object Librarian User’s Guide”, 2005. [15] Microchip®, “MPLAB® IDE User’s Guide”, 2005. [16] Microchip®, “PIC18F2525/2620/4525/4620 Data Sheet”, 2004. [17] National Semiconductor Corporation, “LM117/LM317A/LM317 3-Terminal Adjustable Regulator Data Sheet”, Juny de 2005. [18] Texas Instruments, “TAS3001C Digital Audio Processor Data Manual”, Març de 2004. [19] Texas Instruments, “TLC320AD77C Data Manual”, 1999. [20] Texas Instruments, “TLV226x, TLV226xA Data Sheet”, 2001. [21] Texas Instruments, “TPA152 Data Sheet”, 2000. [22] Texas Instruments, “TPA1517 Data Sheet”, 2004. [23] Cadence, “OrCAD Layout® User’s Guide”, Product Version 10.0, Juny de 2003. [24] Cadence, “OrCAD Capture User’s Guide”, Product Version 10.0, Juny de 2003. [25] HITACHI, “HD44780U (LCD-II) (Dot Matrix Liquid Crystal Display Controller/Driver)”. 63

Bibliografia

WEB [26] R. Allred, Texas Instruments, Dallas, Second-order IIR Filters will support cascade implementations, http://www.planetanalog.com/showArticle?articleID=12802683 [27] http://www.stelioscellar.com/AVR/SerialLCD/serial_lcd_interface_using_avr.htm [28] http://www.todopic.com.ar [29] http://www.mikroe.com/en/books/

64

Annexos

Annexos

Contingut I. DISSENY ESQUEMÀTIC DEL CIRCUIT ......................................................................... 69 I.1. Alimentació.................................................................................................................... 69 I.2. Front-end........................................................................................................................ 70 I.3. Back-end ........................................................................................................................ 72 I.4. Convertidor AD/DA....................................................................................................... 74 I.5. Amplificadors de potència ............................................................................................. 75 I.6. Microcontrolador ........................................................................................................... 77 I.7. Processador d’àudio ....................................................................................................... 78 II. DISSENY DEL CIRCUIT IMPRÈS ................................................................................... 81 III. GENERACIÓ DE TAULES .............................................................................................. 85 III.1. Programa per la generació de la taula del equalitzador gràfic .................................... 85 III.2. Programa per la generació de la taula de l’equalitzador paramètric ........................... 90 III.3. Taula del equalitzador predefinit................................................................................. 92 IV. PROGRAMA ..................................................................................................................... 93 IV.1. I2C.asm ....................................................................................................................... 93 IV.2. LCD.asm ..................................................................................................................... 94 IV.3. PFC.asm ...................................................................................................................... 99

67

Annex I: Disseny esquemàtic del circuit

I. DISSENY ESQUEMÀTIC DEL CIRCUIT I.1. ALIMENTACIÓ Per explicar com funcionarà el circuit d’alimentació ens fixarem en el que proporciona una tensió de 5V per referir-nos als noms dels components, però com es veu clarament la resta són iguals. El LM317 està dissenyat per proporcionar entre la sortida OUT i ADJ una diferència de tensió de 1.25V a la qual anomenen VREF. També minimitza i fa constant el valor del corrent de sortida de ADJ el qual és de 100µA. Si partim de la configuració bàsica del regulador només amb les dos resistències, eliminant els condensadors i els diodes obtenim la tensió de sortida fent la suma de VREF (la que cau en R2) més la tensió que cau en R5 obtenint la següent fórmula: V R5 VOUT = VREF + (I ADJ + REF )R5 = VREF (1 + ) + I ADJ R5 R2 R2 Amb l’anterior fórmula, si fixem el valor de R2, per obtenir qualsevol tensió de sortida només hem de calcular el valor de R5. Així si fixem R2=R3=R7=1200Ω per obtenir una tensió de sortida de 5V el valor de R5 hauria de ser de 3430Ω i per obtenir les tensions de sortida de 3.3V i 12V el valor de R6 i R8 hauria de ser de 1870Ω i 9840Ω respectivament. Com no existeixen resistències d’aquests valors, els valors de les resistències utilitzades en el laboratori seran del valor més proper possible. Això no suposa cap problema ja que els components que haurem de connectar accepten un cert marge en el valor de l’alimentació que necessiten. El condensador que connectem entre la sortida ADJ i massa serveix per eliminar el possible arrissat de la tensió de sortida. Amb una capacitat de 10µF s’obté un rebuig d’arrissat de 80dB. Malgrat que el LM317 ens proporciona una sortida constant, certs valors de la capacitat exterior podrien causar oscil·lacions no desitjades. Per evitar la possibilitat de que es pogués produir aquest efecte s’inclou un condensador de 1µF a la sortida del regulador. A vegades, és necessari incorporar diodes de protecció per evitar que els condensadors es puguin descarregar a punts de baix corrent del regulador de tensió. En les especificacions del regulador ens diu que no cal afegir el diode pel condensador de sortida si el seu valor és menor de 25µF. Tampoc cal afehir-lo a la sortida si la tensió de sortida és menor que 25V i el condensador de la sortida ADJ és de 10µF. Malgrat això, encara que no els muntarem a la placa hem decidit deixar l’espai per si decidíssim afegir-los. En el regulador de tensió que ens proporciona una tensió de 3.3V hem afegit un divisor de tensió per proporcionar la tensió de 3.3/2V que necessita el circuit de front-end. A partir de la tensió que ens proporcionen els reguladors alimentarem tant la part digital com la analògica del circuit menys la de 12V que només alimentarà l’amplificador de potència per altaveus. Per tal de separar l’alimentació analògica de la digital afegirem dos bobines en cada regulador.

69

Annex I: Disseny esquemàtic del circuit

Figura I.1: Esquemàtic alimentació

I.2. FRONT-END Com hem dit en el punt 4.2.2 el circuit utilitzat de front-end és el que s’aconsella en el manual del convertidor. A continuació tenim el disseny esquemàtic del circuit i les simulacions que ens mostren el correcte funcionament del circuit. En la figura I.3 podem observar en la segona gràfica, el senyal d’entrada i en la primera les dues sortides del senyal diferencial. En la tercera es pot observar la resta entre les dos sortides i podem comprovar que la seva amplitud es de 4Vpp com havíem dit. En la figura I.4 observem la resposta freqüencial del circuit que com esperàvem és pas banda, ja la que la capacitat d’entrada elimina la contínua i la resta de circuit filtra pas baix el senyal com hem explicat en el punt 4.2.2.

70

Annex I: Disseny esquemàtic del circuit

Figura I.2: Esquemàtic front-end

Figura I.3: Resposta temporal del circuit de front-end

71

Annex I: Disseny esquemàtic del circuit

Figura I.4: Resposta freqüencial del circuit de front-end

I.3. BACK-END El circuit utilitzat per la etapa de back-end és similar al que trobem en el manual del convertidor. En el manual afegeixen una resistència en paral·lel al condensador C10 i C13 però aquesta fa de divisor de tensió i provoca que tinguem a la sortida el senyal retallat. Per aquet motiu, en el circuit utilitzat que és el de la figura I.5 hem elimitat aquesta resistència. Si simulem el circuit obtenim la figura I.6 on podem observar que el senyal de sortida està invertit respecte el d’entrada tal com hem explicat en el punt 4.2.3. En la figura I.7 tenim la representació de la resposta freqüencial del circuit que observem que filtra el senyal pas baix tal com esperàvem. Encara que no s’apreciï en aquesta figura s’elimina la component contínua gràcies a les capacitat C9 i C12.

72

Annex I: Disseny esquemàtic del circuit

Figura I.5: Esquemàtic back-end

Figura I.6: Resposta temporal del circuit de back-end

73

Annex I: Disseny esquemàtic del circuit

Figura I.7: Resposta freqüencial del circuit de back-end

I.4. CONVERTIDOR AD/DA A continuació es mostra el disseny esquemàtic del convertidor les entrades i sortides del qual hem explicat en el punt 4.2.5. Les alimentacions i tensions de referència estan connectades seguint les indicacions que es troben en el manual del TLC320AD77C.

74

Annex I: Disseny esquemàtic del circuit

Figura I.8: Esquemàtic convertidor AD/DA

I.5. AMPLIFICADORS DE POTÈNCIA Per al disseny de l’amplificador per altaveus ens hem basat en la configuració bàsica que es proposa en el manual del TPA1517. Al senyal d’entrada se li suma una component contínua de 2.1V i la sortida conté una component contínua de tensió igual a la meitat de la tensió d’alimentació. Qualsevol component contínua que es tingui en la entrada serà amplificada i ens degradarà el bon funcionament del amplificador. Per aquest motiu cal introduir en el circuit capacitats d’acoblament en alterna en sèrie tant a la entrada com a la sortida. Per l’elecció dels valors de les capacitats cal tenir en compte que els seus valors han de ser suficientment grans com per deixar passar el senyal de freqüència mínima desitjada. Al mateix temps, la capacitat d’entrada ha de ser suficientment petita perquè la constant de temps d’entrada (RC) sigui menor que la de sortida, per evitar l’efecte de “popping” al posar-lo en marxa. Tenint en compte aquestes condicions i que la resistència d’entrada té un valor de 60kΩ escollim per a les capacitats d’entrada un valor de 1µF i per a les de sortida de 470µF. També cal afegir un condensador de bypass (C33) el valor del qual l’escolliren perquè la seva constant de temps sigui superior a les constants de temps d’entrada i de sortida (unes 5 vegades superior). Si tenim en compte que la resistència d’entrada és de 7.5kΩ, un valor de 2.2µF per aquest condensador ens funcionarà correctament. També inclourem una capacitat a la entrada de la tensió d’alimentació de 1µF. La entrada M/SB ens selecciona el mode de funcionament entre standby, mute o normal. En el nostre cas, el funcionament sempre serà normal i per això connectarem aquesta entrada amb una resistència sèrie de 10KΩ a la tensió d’alimentació, ja que per una entrada en M/SB de 9.3V a 22V es selecciona el mode normal. El circuit que utilitzem en l’amplificador per auriculars també és l’aconsellat en el manual del TPA152. Per explicar com hem escollit els valors dels components ens referirem només

75

Annex I: Disseny esquemàtic del circuit

als del canal dret. Els valors dels component en el canal esquerre es troben de la mateixa manera i les seus valors són els mateixos que en el canal dret. El primer que cal fer, és trobar els valor de les resistències R40 i R41 que ens serveixen per escollir el guany que volem que tingui l’amplificador segons la fórmula G=-R40/R41. Amb una càrrega a la sortida de 32Ω, la potència màxima es correspon a una tensió de 1.55V. Si volem obtenir aquesta tensió màxima a la sortida per la entrada màxima de 0.7Vrms, el guany ha de ser de 2.21, i per aquest motiu, escollim un valor de R41=20kΩ i R40=45kΩ. En el manual del TPA152 diu que per valors de R40 superiors a 50kΩ l’amplificador pot ser inestable. Com el nostre valor és molt proper a aquest límit hem decidit afegir un condensador de 5pF en paral·lel tal com ens diu el manual per evitar possibles problemes. Aquest condensador farà que el senyal d’entrada es filtri pas baix amb una freqüència de tall de 707kHz. També cal introduir capacitats sèrie a les entrades per aconseguir que l’amplificador tingui la tensió contínua desitjada a la entrada. Aquest condensador junt amb la resistència d’entrada R41 ens filtrarà el senyal pas alt. En el nostre cas amb un condensador de 1µF, la freqüència de tall serà de 8Hz. El condensador C38 és de desacoblament per disminuïr el THD i eliminar oscil·lacions. També és necessari connectar a la entrada bypass un condensador la funció principal del qual és reduir el soroll de “pop” al posar-se en marxa. Es necessari que compleixi la condició C39·160kΩ≥R40·C36 on 160kΩ és el valor de la resistència d’entrada de la entrada bypass. Amb un valor d’aquesta capacitat de 1µF es satisfà la condició. Per acabar, també cal afegir capacitats sèrie per eliminar la component contínua a les sortides. En aquest cas hauran de ser de valors més elevats, ja que la resistència de càrrega és molt inferior (32Ω). El valor escollit per aquestes capacitats és de 330µF que ens filtraran pas alt el senyal amb una freqüència de tall de 15Hz. També afegirem la resistència R43 per fer que encara que no hi hagi connectat res a la sortida el condensador estigui carregat. D’aquesta manera s’eviten sorolls de pop al carregar-se ràpidament el condensador quan es connecten els auriculars. La resistència R42 assegura la descàrrega del condensador en apagar l’amplificador.

76

Annex I: Disseny esquemàtic del circuit

Figura I.9: Esquemàtic amplificadors de potència

I.6. MICROCONTROLADOR Les entrades i sortides que connectarem al microcontrolador ja han estat explicades en el punt 4.2.6 i en la figura següent es poden observar els ports que corresponen a cada entrada i sortida. A part dels connectors i del microcontrolador hem introduït resistències de pull-up entre la tensió d’alimentació i els polsadors. Aquesta resistència és suficientment petita en comparació a la resistència d’entrada com perquè si no es prem cap polsador tinguem a l’entrada la tensió d’alimentació. Si es prem el polsador la entrada queda connectada a massa i la tensió cau en la resistència de pul-up. També podem observar un potenciòmetre que permet regular la tensió a V0, entre 0 i Vdd que permet regular la intensitat dels caràcters en el LCD.

77

Annex I: Disseny esquemàtic del circuit

Figura I.10: Esquemàtic microcontrolador

I.7. PROCESSADOR D’ÀUDIO En la figura següent es mostra el disseny esquemàtic del processador d’àudio i del rellotge. Les entrades i sortides han estat explicades en el punt 4.2.7. Totes les capacitat i resistències són les que es troben en el manual del TAS3001. Les sortides corresponents al bus I2C del PIC són en drenador obert i per tant quan ha de valdre “0” es fiquen a nivell baix mentre que quan ha de valdre “1” la sortida és com un circuit obert. Per aquest motiu, cal afegir resistències de pull-up entre l’entrada del TAS3001C i la tensió d’alimentació. D’aquesta manera quan la sortida és a nivell baix, la tensió cau en la resistència mentre que quan és circuit obert tenim la tensió d’alimentació a la entrada del TAS3001. El rellotge que connectem al TAS3001 com hem dit anteriorment no pot ser directament el generador de rellotge ja que el seu senyal de sortida té una amplitud de 5V. Per aquest motiu, fiquem dos resistències que formaran un divisor de tensió que ens proporcionarà el senyal de rellotge de l’amplitud desitjada. Els valors de les resistències han de ser petits ja que per la freqüència de 12MHz un valor elevat de les resistències juntament amb les capacitats d’entrada del TAS3001 ens filtrarien el senyal de rellotge.

78

Annex I: Disseny esquemàtic del circuit

Figura I.11: Esquemàtic processador d’àudio

79

Annex II: Disseny del circuit imprès

II. DISSENY DEL CIRCUIT IMPRÈS Durant el disseny del circuit imprès, s’han realitzat diverses versions amb diferents números de capes. De totes les versions dissenyades hem escollit la de dos capes per motius econòmics i de tamany. Amb una sola capa el circuit era massa gran i amb 4 capes el tamany era molt similar al de dos. En quan als components utlitzats, la majoria són de muntatge superficial menys alguns condensadors de capacitats molt elevades que són molt cars. Un cop decidit el tipus de components que utilitzarem i el número de capes de la PCB hem situat els components en la placa. El primer que hem tingut en compte, és que cal separar la placa en tres parts, una digital, un altre analògica i l’alimentació, i entre la part digital i analògica cal situar el convertidor. També per comoditat a l’hora de trobar els components de cada part del circuit (processador, microcontrolador, front-end, ...) hem situat els components de cada part junts en la placa. L’últim aspecte a tenir en compte a l’hora de situar els components ha estat el ficar juntes totes les entrades i sortides analògiques a un costat de la placa i les entrades dels polsadors i el LCD al altre costat.

a) TOP

81

Annex II: Disseny del circuit imprès

b) Bottom Figura II.1: Posicionament dels elements hardware

Un cop situats tots els components a la placa, cal dibuixar les pistes que uniran els components. El primer que hem de tenir en compte és el mateix que en l’apartat anterior. Les pistes de la part digital no poden passar per la part analògica i viceversa. El rutejat l’hem fet automàtic amb una amplada de pistes de 0.008” per totes les pistes menys les d’alimentació que tenen una amplada de 0.016”. La distància mínima entre pistes, és també de 0.08”.Un cop fet el rutejat automàtic, hem dibuixat les pistes que restaven per connectar.

a) TOP

82

Annex II: Disseny del circuit imprès

b) BOTTOM Figura II.2: Rutejat de la placa

A continuació es mostren diverses captures captures del circuit definitiu:

a) Segona versió

b) Tercera versió

83

Annex II: Disseny del circuit imprès

c) Muntatge en caixa Figura II.3: Imatges del equalitzador

84

Annex III: Generació de taules

III. GENERACIÓ DE TAULES En aquest apartat es troben els programes que hem utilitzat en MATLAB per generar les taules corresponents a l’equalitzador paramètric i l’equalitzador gràfic. També inclourem les taules corresponents al equalitzador predefinit ja que en aquest cas les hem generat manualment.

III.1. PROGRAMA PER LA GENERACIÓ DE LA TAULA DEL EQUALITZADOR GRÀFIC Aquest programa genera els coeficients del filtre shelving pas baix per a tots els valors de guanys possibles (de -12dB a 12dB), els transforma al format 4.20 i els emmagatzema al fitxer EQ_graf_tab.asm. A continuació genera els filtres peaking també per a tots els guanys per les tres freqüències centrals i després de convertir-los al format 4.20 els escriu al fitxer. També es realitza el mateix procediment per al filtre pas alt shelving. Amb aquest programa obtenim una taula que conté quatre subblocs, un per cada freqüència central. Cada un d’aquests subblocs està format per 25 files, la primera corresponent al guany -12dB i la última corresponent a 12dB. Les files intermèdies es corresponen al guany de la fila anterior +1dB. En cada una d’aquestes files apareixerà la paraula “DATA” i a continuació 16bytes separat per comes de dos en dos bytes. L’últim byte sempre contindrà el valor 0x00 ja que cada coeficient només necessita 15bytes. res=23437; Fs=46875; f0=[63; 250; 1000; 4000; 16000]; oct=2; dBgain=[-12; -11; -10; -9; -8; -7; -6; -5; -4; -3; -2; -1; 0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12]; w0=[0; 0; 0; 0; 0]; Wc=[0; 0; 0; 0; 0]; G=[0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0]; G0=1; GB=[0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0]; A=[0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0]; B=[0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0]; P=[0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0]; SCALE=[0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0]; Wc=2*pi*f0; Ts=1/Fs; fid = fopen('EQ_graf_tab.asm','w'); for k= 1:25 G(k)=10^(abs(dBgain(k))/20); if (abs(dBgain(k)))>=6 GB(k)=10^((abs(dBgain(k))-3)/20); else GB(k)=10^((abs(dBgain(k))/2)/20); end Wc(1)=2*pi*f0(1)*2^(oct/2); B(k)=sqrt(((G(k)-GB(k)^2)-(GB(k)*(G(k)-1)))/(GB(k)^2-G(k)^2)); A(k)=B(k)*sqrt(G(k)); SCALE(k)=((A(k)/B(k))^2)/((1-2*exp(-A(k)*Wc(1)*Ts)+(exp(-A(k)*Wc(1)*Ts))^2)/(1-2*exp(-B(k)*Wc(1)*Ts)+(exp(B(k)*Wc(1)*Ts))^2)); if dBgain(k)<0 a1(k,1)=SCALE(k); a1(k,2)=SCALE(k)*(-2*exp(-A(k)*Wc(1)*Ts)); a1(k,3)=SCALE(k)*(exp(-A(k)*Wc(1)*Ts))^2; b1(k,1)=1; b1(k,2)=-2*exp(-B(k)*Wc(1)*Ts);

85

Annex III: Generació de taules b1(k,3)=(exp(-B(k)*Wc(1)*Ts))^2; elseif dBgain(k)>0 b1(k,1)=SCALE(k); b1(k,2)=SCALE(k)*(-2*exp(-A(k)*Wc(1)*Ts)); b1(k,3)=SCALE(k)*(exp(-A(k)*Wc(1)*Ts))^2; a1(k,1)=1; a1(k,2)=-2*exp(-B(k)*Wc(1)*Ts); a1(k,3)=(exp(-B(k)*Wc(1)*Ts))^2; else b1(k,1)=1; b1(k,2)=1; b1(k,3)=1; a1(k,1)=1; a1(k,2)=1; a1(k,3)=1; end a(k,1)=a1(k,2)/a1(k,1); a(k,2)=a1(k,3)/a1(k,1); a(k,3)=b1(k,1)/a1(k,1); a(k,4)=b1(k,2)/a1(k,1); a(k,5)=b1(k,3)/a1(k,1); end cq=(2^-20)*fix(a*(2^20)); n=(2^20)*cq; for k= 1:25 for i= 1:5 if cq(k,i)<0 n(k,i)=n(k,i)+(2^24); end end end fprintf(fid,'\nEQ_biquad_1\n') sprintf('\nEQ_biquad_1\n') for k=1:25 n1(k,1)=fix(n(k,1)/(2^16)); n1(k,2)=fix((n(k,1)-(n1(k,1)*(2^16)))/(2^8)); n1(k,3)=fix(n(k,1)-(n1(k,1)*(2^16))-(n1(k,2)*(2^8))); end for k=1:25 n2(k,1)=fix(n(k,2)/(2^16)); n2(k,2)=fix((n(k,2)-(n2(k,1)*(2^16)))/(2^8)); n2(k,3)=fix(n(k,2)-(n2(k,1)*(2^16))-(n2(k,2)*(2^8))); end for k=1:25 n3(k,1)=fix(n(k,3)/(2^16)); n3(k,2)=fix((n(k,3)-(n3(k,1)*(2^16)))/(2^8)); n3(k,3)=fix(n(k,3)-(n3(k,1)*(2^16))-(n3(k,2)*(2^8))); end for k=1:25 n4(k,1)=fix(n(k,4)/(2^16)); n4(k,2)=fix((n(k,4)-(n4(k,1)*(2^16)))/(2^8)); n4(k,3)=fix(n(k,4)-(n4(k,1)*(2^16))-(n4(k,2)*(2^8))); end for k=1:25 n5(k,1)=fix(n(k,5)/(2^16)); n5(k,2)=fix((n(k,5)-(n5(k,1)*(2^16)))/(2^8)); n5(k,3)=fix(n(k,5)-(n5(k,1)*(2^16))-(n5(k,2)*(2^8))); end for k= 1:25 fprintf(fid,' DATA 0x%02X%02X, 0x%02X%02X, 0x%02X%02X, 0x%02X%02X, 0x%02X%02X, 0x%02X%02X, 0x%02X%02X, 0x%02X00\n',n3(k,1),n3(k,2),n3(k,3),n4(k,1),n4(k,2),n4(k,3),n5(k,1),n5(k,2),n5(k,3),n1(k,1),n1(k,2),n1(k,3),n2(k,1),n2(k,2),n2(k,3)); % El %02X significa que imprimeixi en hexadecimal sempre amb dos % digits encara que només en tingui un el número i el 0ées perqué no % deixi espais, sino que fiqui 0 a l'esquerra, per exemple la D la % escriu 0D, el F5 F5...... end

86

Annex III: Generació de taules

for j= 2:4 w0=2*pi*f0(j)/Fs; w1=((f0(j)/2^(oct/2))*2*pi)/Fs; Dw=2*pi*((f0(j)*2^(oct/2)-f0(j)/2^(oct/2))/Fs); bw=(f0(j)*2^(oct/2)-f0(j)/2^(oct/2)); BW=Dw; for k= 1:25 G(k)=10^(abs(dBgain(k))/20); if (abs(dBgain(k)))>=6 GB(k)=10^((abs(dBgain(k))-3)/20); else GB(k)=10^((abs(dBgain(k))/2)/20); end F(k) = abs(G(k)^2 - GB(k)^2); G00(k) = abs(G(k)^2 - G0^2); F00(k) = abs(GB(k)^2 - G0^2); num(k) = G0^2 * (w0^2 - pi^2)^2 + G(k)^2 * F00(k) * pi^2 * Dw^2 / F(k); den(k) = (w0^2 - pi^2)^2 + F00(k) * pi^2 * Dw^2 / F(k); G1(k) = sqrt(num(k)/den(k)); G01(k) = abs(G(k)^2 - G0*G1(k)); G11(k) = abs(G(k)^2 - G1(k)^2); F01(k) = abs(GB(k)^2 - G0*G1(k)); F11(k) = abs(GB(k)^2 - G1(k)^2); W2(k) = sqrt(G11(k) / G00(k)) * tan(w0/2)^2; DW(k) = (1 + sqrt(F00(k) / F11(k)) * W2(k)) * tan(Dw/2); C(k) = F11(k) * DW(k)^2 - 2 * W2(k) * (F01(k)- sqrt(F00(k) * F11(k))); D(k) = 2 * W2(k) * (G01(k) - sqrt(G00(k) * G11(k))); A(k) = sqrt((C(k) + D(k)) / F(k)); B(k) = sqrt((G(k)^2 * C(k) + GB(k)^2 * D(k)) / F(k)); if dBgain(k)<0 a1(k,1)=(G1(k) + G0*W2(k) + B(k))/ (1 + W2(k) + A(k)); a1(k,2)=(-2*(G1(k) - G0*W2(k)))/ (1 + W2(k) + A(k)); a1(k,3)=(G1(k) - B(k) + G0*W2(k))/ (1 + W2(k) + A(k)); b1(k,1)=1; b1(k,2)=(-2*(1 - W2(k)))/ (1 + W2(k) + A(k)); b1(k,3)=(1 + W2(k) - A(k))/ (1 + W2(k) + A(k)); elseif dBgain(k)>0 b1(k,1)=(G1(k) + G0*W2(k) + B(k))/ (1 + W2(k) + A(k)); b1(k,2)=(-2*(G1(k) - G0*W2(k)))/ (1 + W2(k) + A(k)); b1(k,3)=(G1(k) - B(k) + G0*W2(k))/ (1 + W2(k) + A(k)); a1(k,1)=1; a1(k,2)=(-2*(1 - W2(k)))/ (1 + W2(k) + A(k)); a1(k,3)=(1 + W2(k) - A(k))/ (1 + W2(k) + A(k)); else b1(k,1)=1; b1(k,2)=1; b1(k,3)=1; a1(k,1)=1; a1(k,2)=1; a1(k,3)=1; end %MZT B(k)=bw*2*pi*sqrt((GB(k)^2-1)/(G(k)^2-GB(k)^2))/Wc(j); A(k)=G(k)*B(k); b2(k,1)=1; b2(k,2)=-2*exp(-B(k)*Wc(j)*Ts/2)*cos(Ts*sqrt(Wc(j)^2-(B(k)*Wc(j)/2)^2)); b2(k,3)=(exp(-B(k)*Wc(j)*Ts/2))^2; a2(k,1)=1; a2(k,2)=-2*exp(-A(k)*Wc(j)*Ts/2)*cos(Ts*sqrt(Wc(j)^2-(A(k)*Wc(j)/2)^2)); a2(k,3)=(exp(-A(k)*Wc(j)*Ts/2))^2;

87

Annex III: Generació de taules SCALE=(b2(k,1)+b2(k,2)+b2(k,3))/(a2(k,1)+a2(k,2)+a2(k,3)); if dBgain(k)<0 a2(k,1)=SCALE; a2(k,2)=SCALE*(-2*exp(-A(k)*Wc(j)*Ts/2)*cos(Ts*sqrt(Wc(j)^2-(A(k)*Wc(j)/2)^2))); a2(k,3)=SCALE*(exp(-A(k)*Wc(j)*Ts/2))^2; b2(k,1)=1; b2(k,2)=-2*exp(-B(k)*Wc(j)*Ts/2)*cos(Ts*sqrt(Wc(j)^2-(B(k)*Wc(j)/2)^2)); b2(k,3)=(exp(-B(k)*Wc(j)*Ts/2))^2; elseif dBgain(k)>0 b2(k,1)=SCALE; b2(k,2)=SCALE*(-2*exp(-A(k)*Wc(j)*Ts/2)*cos(Ts*sqrt(Wc(j)^2-(A(k)*Wc(j)/2)^2))); b2(k,3)=SCALE*(exp(-A(k)*Wc(j)*Ts/2))^2; a2(k,1)=1; a2(k,2)=-2*exp(-B(k)*Wc(j)*Ts/2)*cos(Ts*sqrt(Wc(j)^2-(B(k)*Wc(j)/2)^2)); a2(k,3)=(exp(-B(k)*Wc(j)*Ts/2))^2; else b2(k,1)=1; b2(k,2)=1; b2(k,3)=1; a2(k,1)=1; a2(k,2)=1; a2(k,3)=1; end %AVERAGED N-BZT/MZT a(k,1)=(a1(k,2)+a2(k,2))/(a1(k,1)+a2(k,1)); a(k,2)=(a1(k,3)+a2(k,3))/(a1(k,1)+a2(k,1)); a(k,3)=(b1(k,1)+b2(k,1))/(a1(k,1)+a2(k,1)); a(k,4)=(b1(k,2)+b2(k,2))/(a1(k,1)+a2(k,1)); a(k,5)=(b1(k,3)+b2(k,3))/(a1(k,1)+a2(k,1)); end cq=(2^-20)*fix(a*(2^20)); n=(2^20)*cq; for k= 1:25 for i= 1:5 if cq(k,i)<0 n(k,i)=n(k,i)+(2^24); end end end fprintf(fid,'\nEQ_biquad_%g\n',j) for k=1:25 n1(k,1)=fix(n(k,1)/(2^16)); n1(k,2)=fix((n(k,1)-(n1(k,1)*(2^16)))/(2^8)); n1(k,3)=fix(n(k,1)-(n1(k,1)*(2^16))-(n1(k,2)*(2^8))); end for k=1:25 n2(k,1)=fix(n(k,2)/(2^16)); n2(k,2)=fix((n(k,2)-(n2(k,1)*(2^16)))/(2^8)); n2(k,3)=fix(n(k,2)-(n2(k,1)*(2^16))-(n2(k,2)*(2^8))); end for k=1:25 n3(k,1)=fix(n(k,3)/(2^16)); n3(k,2)=fix((n(k,3)-(n3(k,1)*(2^16)))/(2^8)); n3(k,3)=fix(n(k,3)-(n3(k,1)*(2^16))-(n3(k,2)*(2^8))); end for k=1:25 n4(k,1)=fix(n(k,4)/(2^16)); n4(k,2)=fix((n(k,4)-(n4(k,1)*(2^16)))/(2^8)); n4(k,3)=fix(n(k,4)-(n4(k,1)*(2^16))-(n4(k,2)*(2^8))); end for k=1:25 n5(k,1)=fix(n(k,5)/(2^16)); n5(k,2)=fix((n(k,5)-(n5(k,1)*(2^16)))/(2^8)); n5(k,3)=fix(n(k,5)-(n5(k,1)*(2^16))-(n5(k,2)*(2^8))); end

88

Annex III: Generació de taules

for k= 1:25 fprintf(fid,' DATA 0x%02X%02X, 0x%02X%02X, 0x%02X%02X, 0x%02X%02X, 0x%02X%02X, 0x%02X%02X, 0x%02X%02X, 0x%02X00\n',n3(k,1),n3(k,2),n3(k,3),n4(k,1),n4(k,2),n4(k,3),n5(k,1),n5(k,2),n5(k,3),n1(k,1),n1(k,2),n1(k,3),n2(k,1),n2(k,2),n2(k,3)); % El %02X significa que imprimeixi en hexadecimal sempre amb dos % digits encara que només en tingui un el número i el 0 és perque no % deixi espais sino que fiqui 0 a l'esquerra, per exemple la D la % escriu 0D, el F5 F5...... end end for k= 1:25 G(k)=10^(abs(dBgain(k))/20); if (abs(dBgain(k)))>=6 GB(k)=10^((abs(dBgain(k))-3)/20); else GB(k)=10^((abs(dBgain(k))/2)/20); end Wc(5)=2*pi*f0(5)/2^(oct/2); B(k)=sqrt(((G(k)-GB(k)^2)-(GB(k)*(G(k)-1)))/(GB(k)^2-G(k)^2)); A(k)=B(k)*sqrt(G(k)); SCALE(k)=(1-2*exp(-Wc(5)*Ts/B(k))+(exp(-Wc(5)*Ts/B(k)))^2)/(1-2*exp(-Wc(5)*Ts/A(k))+(exp(-Wc(5)*Ts/A(k)))^2); if dBgain(k)<0 a1(k,1)=SCALE(k); a1(k,2)=SCALE(k)*(-2*exp(-Wc(5)*Ts/A(k))); a1(k,3)=SCALE(k)*(exp(-Wc(5)*Ts/A(k)))^2; b1(k,1)=1; b1(k,2)=-2*exp(-Wc(5)*Ts/B(k)); b1(k,3)=(exp(-Wc(5)*Ts/B(k)))^2; elseif dBgain(k)>0 b1(k,1)=SCALE(k); b1(k,2)=SCALE(k)*(-2*exp(-Wc(5)*Ts/A(k))); b1(k,3)=SCALE(k)*(exp(-Wc(5)*Ts/A(k)))^2; a1(k,1)=1; a1(k,2)=-2*exp(-Wc(5)*Ts/B(k)); a1(k,3)=(exp(-Wc(5)*Ts/B(k)))^2; else b1(k,1)=1; b1(k,2)=1; b1(k,3)=1; a1(k,1)=1; a1(k,2)=1; a1(k,3)=1; end a(k,1)=a1(k,2)/a1(k,1); a(k,2)=a1(k,3)/a1(k,1); a(k,3)=b1(k,1)/a1(k,1); a(k,4)=b1(k,2)/a1(k,1); a(k,5)=b1(k,3)/a1(k,1); end cq=(2^-20)*fix(a*(2^20)); n=(2^20)*cq; for k= 1:25 for i= 1:5 if cq(k,i)<0 n(k,i)=n(k,i)+(2^24); end end end fprintf(fid,'\nEQ_biquad_5\n') sprintf('\nEQ_biquad_5\n') for k=1:25 n1(k,1)=fix(n(k,1)/(2^16)); n1(k,2)=fix((n(k,1)-(n1(k,1)*(2^16)))/(2^8));

89

Annex III: Generació de taules n1(k,3)=fix(n(k,1)-(n1(k,1)*(2^16))-(n1(k,2)*(2^8))); end for k=1:25 n2(k,1)=fix(n(k,2)/(2^16)); n2(k,2)=fix((n(k,2)-(n2(k,1)*(2^16)))/(2^8)); n2(k,3)=fix(n(k,2)-(n2(k,1)*(2^16))-(n2(k,2)*(2^8))); end for k=1:25 n3(k,1)=fix(n(k,3)/(2^16)); n3(k,2)=fix((n(k,3)-(n3(k,1)*(2^16)))/(2^8)); n3(k,3)=fix(n(k,3)-(n3(k,1)*(2^16))-(n3(k,2)*(2^8))); end for k=1:25 n4(k,1)=fix(n(k,4)/(2^16)); n4(k,2)=fix((n(k,4)-(n4(k,1)*(2^16)))/(2^8)); n4(k,3)=fix(n(k,4)-(n4(k,1)*(2^16))-(n4(k,2)*(2^8))); end for k=1:25 n5(k,1)=fix(n(k,5)/(2^16)); n5(k,2)=fix((n(k,5)-(n5(k,1)*(2^16)))/(2^8)); n5(k,3)=fix(n(k,5)-(n5(k,1)*(2^16))-(n5(k,2)*(2^8))); end for k= 1:25 fprintf(fid,' DATA 0x%02X%02X, 0x%02X%02X, 0x%02X%02X, 0x%02X%02X, 0x%02X%02X, 0x%02X%02X, 0x%02X%02X, 0x%02X00\n',n3(k,1),n3(k,2),n3(k,3),n4(k,1),n4(k,2),n4(k,3),n5(k,1),n5(k,2),n5(k,3),n1(k,1),n1(k,2),n1(k,3),n2(k,1),n2(k,2),n2(k,3)); % El %02X significa que imprimeixi en hexadecimal sempre amb dos % digits encara que només en tingui un el número i el 0 és perqué no % deixi espais sino que fiqui 0 a l'esquerra, per exemple la D la % escriu 0D, el F5 F5...... end fclose(fid)

III.2. PROGRAMA PER LA GENERACIÓ DE LA TAULA DE L’EQUALITZADOR PARAMÈTRIC El funcionament d’aquest programa, és molt similar al anterior però en aquest cas per a tots els paràmetres utilitzem el mateix tipus de filtre. Es calcularan els coeficients per 4 amples de banda diferents, per cada ample de banda es calcularà els coeficient per les 30 freqüències i per cada freqüència calcularem els coeficients per cada un dels 25 guanys possibles. El contingut de les taules estarà format per 4 subblocs corresponents als 4 amples de banda possibles. Cada un d’aquests subblocs es separarà en 30 subblocs més, cada un corresponent a una freqüència. Per últim cada un d’aquest subblocs contindrà 25 línies amb el mateix format que hem explicat en el apartat anterior, una per cada possible valor de guany. Al principi de cada subbloc de freqüència escriurem un comentari on hi haurà escrit l’ample de banda i la freqüència que li correspon al bloc de 25 files que hi ha a continuació. Fs=46875; f0=[25; 31.5; 40; 50; 63; 80; 100; 125; 160; 200; 250; 315; 400; 500; 630; 800; 1000; 1250; 1600; 2000; 2500; 3150; 4000; 5000; 6300; 8000; 10000; 12500; 16000; 20000]; oct=[2; 1; 2/3; 1/3]; dBgain=[-12; -11; -10; -9; -8; -7; -6; -5; -4; -3; -2; -1; 0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12]; fid = fopen('parametric.asm','w'); for m= 1:4 for j= 1:30 w0=2*pi*f0(j)/Fs; w1=((f0(j)/2^(oct(m)/2))*2*pi)/Fs; Dw=2*pi*((f0(j)*2^(oct(m)/2)-f0(j)/2^(oct(m)/2))/Fs); G0=1; for k= 1:25 G(k)=10^(abs(dBgain(k))/20); if (abs(dBgain(k)))>=6

90

Annex III: Generació de taules GB(k)=10^((abs(dBgain(k))-3)/20); else GB(k)=10^((abs(dBgain(k))/2)/20); end F(k) = abs(G(k)^2 - GB(k)^2); G00(k) = abs(G(k)^2 - G0^2); F00(k) = abs(GB(k)^2 - G0^2); num(k) = G0^2 * (w0^2 - pi^2)^2 + G(k)^2 * F00(k) * pi^2 * Dw^2 / F(k); den(k) = (w0^2 - pi^2)^2 + F00(k) * pi^2 * Dw^2 / F(k); G1(k) = sqrt(num(k)/den(k)); G01(k) = abs(G(k)^2 - G0*G1(k)); G11(k) = abs(G(k)^2 - G1(k)^2); F01(k) = abs(GB(k)^2 - G0*G1(k)); F11(k) = abs(GB(k)^2 - G1(k)^2); W2(k) = sqrt(G11(k) / G00(k)) * tan(w0/2)^2; DW(k) = (1 + sqrt(F00(k) / F11(k)) * W2(k)) * tan(Dw/2); C(k) = F11(k) * DW(k)^2 - 2 * W2(k) * (F01(k)- sqrt(F00(k) * F11(k))); D(k) = 2 * W2(k) * (G01(k) - sqrt(G00(k) * G11(k))); A(k) = sqrt((GB(k)^2*(tan(w1/2)^2-W2(k))^2-(G1(k)*tan(w1/2)^2-G0*W2(k))^2+D(k)*tan(w1/2)^2)/((G(k)^2-GB(k)^2)*tan(w1/2)^2)); B(k) = sqrt(-D(k)+G(k)^2*A(k)^2); if dBgain(k)<0 a0=(G1(k) + G0*W2(k) + B(k))/ (1 + W2(k) + A(k)); a(k,1)=((-2*(G1(k) - G0*W2(k)))/ (1 + W2(k) + A(k)))/a0; a(k,2)=((G1(k) - B(k) + G0*W2(k))/ (1 + W2(k) + A(k)))/a0; a(k,3)=1/a0; a(k,4)=((-2*(1 - W2(k)))/ (1 + W2(k) + A(k)))/a0; a(k,5)=((1 + W2(k) - A(k))/ (1 + W2(k) + A(k)))/a0; elseif dBgain(k)>0 a(k,1)=(-2*(1 - W2(k)))/ (1 + W2(k) + A(k)); a(k,2)=(1 + W2(k) - A(k))/ (1 + W2(k) + A(k)); a(k,3)=(G1(k) + G0*W2(k) + B(k))/ (1 + W2(k) + A(k)); a(k,4)=(-2*(G1(k) - G0*W2(k)))/ (1 + W2(k) + A(k)); a(k,5)=(G1(k) - B(k) + G0*W2(k))/ (1 + W2(k) + A(k)); else a(k,1)=1; a(k,2)=1; a(k,3)=1; a(k,4)=1; a(k,5)=1; end end cq=(2^-20)*fix(a*(2^20)); n=(2^20)*cq; for k= 1:25 for i= 1:5 if cq(k,i)<0 n(k,i)=n(k,i)+(2^24); end end end fprintf(fid,'\n;Q=%g ,f=%g ; cada fila es suma un dB, de -12dB a 12 dB de guany\n\n',oct(m),f0(j)) for k=1:25 n1(k,1)=fix(n(k,1)/(2^16)); n1(k,2)=fix((n(k,1)-(n1(k,1)*(2^16)))/(2^8)); n1(k,3)=fix(n(k,1)-(n1(k,1)*(2^16))-(n1(k,2)*(2^8))); end for k=1:25 n2(k,1)=fix(n(k,2)/(2^16)); n2(k,2)=fix((n(k,2)-(n2(k,1)*(2^16)))/(2^8)); n2(k,3)=fix(n(k,2)-(n2(k,1)*(2^16))-(n2(k,2)*(2^8))); end for k=1:25 n3(k,1)=fix(n(k,3)/(2^16)); n3(k,2)=fix((n(k,3)-(n3(k,1)*(2^16)))/(2^8));

91

Annex III: Generació de taules n3(k,3)=fix(n(k,3)-(n3(k,1)*(2^16))-(n3(k,2)*(2^8))); end for k=1:25 n4(k,1)=fix(n(k,4)/(2^16)); n4(k,2)=fix((n(k,4)-(n4(k,1)*(2^16)))/(2^8)); n4(k,3)=fix(n(k,4)-(n4(k,1)*(2^16))-(n4(k,2)*(2^8))); end for k=1:25 n5(k,1)=fix(n(k,5)/(2^16)); n5(k,2)=fix((n(k,5)-(n5(k,1)*(2^16)))/(2^8)); n5(k,3)=fix(n(k,5)-(n5(k,1)*(2^16))-(n5(k,2)*(2^8))); end for k= 1:25 fprintf(fid,' DATA 0x%02X%02X, 0x%02X%02X, 0x%02X%02X, 0x%02X%02X, 0x%02X%02X, 0x%02X%02X, 0x%02X%02X, 0x%02X00\n',n3(k,1),n3(k,2),n3(k,3),n4(k,1),n4(k,2),n4(k,3),n5(k,1),n5(k,2),n5(k,3),n1(k,1),n1(k,2),n1(k,3),n2(k,1),n2(k,2),n2(k,3)); % El %02X significa que imprimeixi en hexadecimal sempre amb dos % digits encara que només en tingui un el número i el 0 és perqué no % deixi espais sino que fiqui 0 a l'esquerra, per exemple la D la % escriu 0D, el F5 F5...... end end end fclose(fid)

III.3. TAULA DEL EQUALITZADOR PREDEFINIT Com hem dit en la introducció aquest filtres han estat generats de manera manual i després s’han passat els coeficients al format 4.20. Per aquest motiu no hi ha un programa per a la generació d’aquestes taules i en aquest apartat incloem directament les taules. EQ_predefinit ;Rock DATA 0x110D, 0x23E3, 0x62EE, 0x0BB0, 0x10E3, 0x827C, 0x0C9D, 0xA500 DATA 0x1000, 0x00E0, 0x4348, 0x0FBC, 0xFFE0, 0x4348, 0x0FBC, 0xFF00 DATA 0x1000, 0x00E0, 0x4348, 0x0FBC, 0xFFE0, 0x4348, 0x0FBC, 0xFF00 DATA 0x1000, 0x2DEB, 0xA7D0, 0x0604, 0xD7EB, 0xA7DF, 0x0604, 0xF500 DATA 0x100F, 0xD6E0, 0x7A7B, 0x0F77, 0x1CE0, 0x7A38, 0x0F86, 0xAF00 DATA 0x1854, 0x5BE0, 0x0B36, 0x0A75, 0xEBED, 0x89B0, 0x054B, 0xCD00 ;Jazz DATA 0x1000, 0x00E0, 0x4099, 0x0FC0, 0x8AE0, 0x4099, 0x0FC0, 0x8B00 DATA 0x1000, 0x01E0, 0x8275, 0x0F82, 0x11E0, 0x8275, 0x0F82, 0x1300 DATA 0x1000, 0x3BF5, 0x612D, 0x03F6, 0xA1F5, 0x614A, 0x03F6, 0xC000 DATA 0x1000, 0x2DEB, 0xA7D0, 0x0604, 0xD7EB, 0xA7DF, 0x0604, 0xF500 DATA 0x100F, 0xD6E0, 0x7A7B, 0x0F77, 0x1CE0, 0x7A38, 0x0F86, 0xAF00 DATA 0x1854, 0x5BE0, 0x0B36, 0x0A75, 0xEBED, 0x89B0, 0x054B, 0xCD00 ;Clasic DATA 0x1000, 0x00E0, 0x4099, 0x0FC0, 0x8AE0, 0x4099, 0x0FC0, 0x8B00 DATA 0x1000, 0x01E0, 0x8275, 0x0F82, 0x11E0, 0x8275, 0x0F82, 0x1300 DATA 0x1000, 0x12E4, 0xC210, 0x0B7C, 0xA3E4, 0xC212, 0x0B7C, 0xB300 DATA 0x1000, 0x3BF5, 0x612D, 0x03F6, 0xA1F5, 0x614A, 0x03F6, 0xC000 DATA 0x1016, 0xDFE0, 0x8FFF, 0x0F5B, 0x46E0, 0x8F8B, 0x0F71, 0xB100 DATA 0x1739, 0x94E1, 0xAB7F, 0x09E0, 0x86ED, 0x5FDD, 0x0565, 0xBC00 ;Dance DATA 0x110D, 0x23E3, 0x62EE, 0x0BB0, 0x10E3, 0x827C, 0x0C9D, 0xA500 DATA 0x1000, 0x00E0, 0x4099, 0x0FC0, 0x8AE0, 0x4099, 0x0FC0, 0x8B00 DATA 0x1000, 0x01E0, 0x8275, 0x0F82, 0x11E0, 0x8275, 0x0F82, 0x1300 DATA 0x1000, 0x12E4, 0xC210, 0x0B7C, 0xA3E4, 0xC212, 0x0B7C, 0xB300 DATA 0x1000, 0x3BF5, 0x612D, 0x03F6, 0xA1F5, 0x614A, 0x03F6, 0xC000 DATA 0x1000, 0x2DEB, 0xA7D0, 0x0604, 0xD7EB, 0xA7DF, 0x0604, 0xF500 ;Pop DATA 0x110D, 0x23E3, 0x62EE, 0x0BB0, 0x10E3, 0x827C, 0x0C9D, 0xA500 DATA 0x1000, 0x12E4, 0xC210, 0x0B7C, 0xA3E4, 0xC212, 0x0B7C, 0xB300 DATA 0x1000, 0x3BF5, 0x612D, 0x03F6, 0xA1F5, 0x614A, 0x03F6, 0xC000 DATA 0x1000, 0x2DEB, 0xA7D0, 0x0604, 0xD7EB, 0xA7DF, 0x0604, 0xF500 DATA 0x0FF8, 0xF4E0, 0xAA36, 0x0F5E, 0x52E0, 0xAA5A, 0x0F57, 0x6B00 DATA 0x0DE9, 0x60EF, 0x20E6, 0x051C, 0xD9EB, 0xBECB, 0x0668, 0x5400

92

Annex IV: Programa

IV. PROGRAMA IV.1. I2C.ASM list p=18f2620 #include p18f2620.inc D_I2C_DATA TASADDR TASDATA

UDATA res 1 res 1

GLOBAL TASADDR GLOBAL TASDATA PROGRAM

CODE

; sends start bit, slave address ; if ACK not recieved, sends restart, tries again ; execution can get stuck in this loop if slave not present ; can be used to poll slave status (retries until slave responds) WakeSlave bsf btfsc goto

SSPCON2,SEN SSPCON2,SEN $-2

; Send start bit ; Has SEN cleared yet? ; No, loop back to test.

return GLOBAL WakeSlave ; writes EEPROM memory address, hangs if no ACK WrADDR bcf movff

PIR1,SSPIF TASADDR,SSPBUF

; clear interrupt flag ; move EEPROM address to SSPBUF

btfss goto

PIR1,SSPIF $-2

; has SSP completed sending Address? ; no, loop back to test

btfsc goto

SSPCON2,ACKSTAT $-2

; has slave sent ACK? ; no, try again

return GLOBAL WrADDR ; Sends one byte of data to slave, hangs if no ACK WrDATA bcf

PIR1,SSPIF

; clear interrupt flag

movff btfss goto

TASDATA,SSPBUF PIR1,SSPIF $-2

; move data to SSPBUF ; has SSP completed sending data to EEPROM? ; no, loop back to test

btfsc goto

SSPCON2,ACKSTAT $-2

; has slave sent ACK? ; no, try again

return GLOBAL WrDATA ; Sends stop bit, waits until sent Stop bsf btfsc goto

SSPCON2,PEN SSPCON2,PEN $-2

; send stop bit ; has stop bit been sent? ; no, loop back to test

return GLOBAL Stop

93

Annex IV: Programa

END

IV.2. LCD.ASM list p=18f2620 #include p18f2620.inc #define #define #define #define

LCD_D4 LCD_D5 LCD_D6 LCD_D7

PORTB, 0 PORTB, 1 PORTB, 2 PORTB, 3

; LCD data bits

#define #define #define #define

LCD_D4_DIR LCD_D5_DIR LCD_D6_DIR LCD_D7_DIR

TRISB, 0 TRISB, 1 TRISB, 2 TRISB, 3

; LCD data bits

#define #define #define

LCD_E LCD_RW LCD_RS

PORTC, 7 PORTC, 6 PORTC, 5

; LCD E clock ; LCD read/write line ; LCD register select line

#define #define #define

LCD_E_DIR LCD_RW_DIR LCD_RS_DIR

TRISC, 7 TRISC, 6 TRISC, 5

#define #define

LCD_INS LCD_DATA

0 1

D_LCD_DATA

UDATA

COUNTER delay temp_wr temp_rd

res res res res

1 1 1 1

GLOBAL temp_wr PROGRAM

CODE

;INSTRUCTION RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 ; 0 0 1 X X X X X X X ;Esta instrucció envia direccion para cursor LCDLine_1 movlw movwf rcall return GLOBAL LCDLine_2 movlw movwf rcall return GLOBAL

0x80 temp_wr i_write

;envia la direccion 00H -> 00 1 0000000

LCDLine_1 0xC0 temp_wr i_write

;envia la direccion 40H -> 00 1 1000000

LCDLine_2

d_write rcall LCDBusy bsf STATUS, C rcall LCDWrite return GLOBAL d_write

;para que RS sea 1

i_write rcall bcf rcall return GLOBAL

LCDBusy STATUS, C LCDWrite

;para que RS sea 0

i_write

94

Annex IV: Programa rlcd

macro

MYREGISTER

IF MYREGISTER == 1 bsf STATUS, C rcall LCDRead ELSE bcf STATUS, C rcall LCDRead ENDIF endm LCDInit clrf

PORTC

bcf bcf bcf

LCD_E_DIR LCD_RW_DIR LCD_RS_DIR

;configure control lines ;para que sean salidas

movlw movwf

0x0F ADCON1

movlw movwf

0xff COUNTER

;para que sean salidas digitales ;el o es analógico pero no nos afecta ;en este caso sólo utilizamos 1,2,3 ; Wait ~15ms @ 20 MHz

movlw movwf rcall decfsz bra

0xFF delay DelayXCycles COUNTER,F lil1

lil1

;INSTRUCTION RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 ; 0 0 0 0 1 DL N F - ;DL=1 ->8 bit DL=0 ->4 bit with MPU ;N= -> 1 line N=1 ->2 lines ;F=0 -> 5x8 puntos F=1 -> 5x11 puntos movlw movwf bcf rcall

b'00110000' temp_wr STATUS,C LCDWriteNibble

;#1 Send control sequence

movlw movwf

0xff COUNTER

;Wait ~4ms @ 20 MHz

movlw movwf rcall decfsz bra

0xFF delay DelayXCycles COUNTER,F lil2

;para que RS sea 0

lil2

;INSTRUCTION RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 ; 0 0 0 0 1 DL N F - ;DL=1 ->8 bit DL=0 ->4 bit with MPU ;N= -> 1 line N=1 ->2 lines ;F=0 -> 5x8 puntos F=1 -> 5x11 puntos movlw movwf bcf rcall

b'00110000' temp_wr STATUS,C LCDWriteNibble

;#2 Send control sequence

movlw movwf rcall

0xFF delay DelayXCycles

;Wait ~100us @ 20 MHz

;INSTRUCTION RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 ; 0 0 0 0 1 DL N F - ;DL=1 ->8 bit DL=0 ->4 bit with MPU ;N=0 -> 1 line N=1 ->2 lines ;F=0 -> 5x8 puntos F=1 -> 5x11 puntos movlw movwf bcf rcall

b'00110000' temp_wr STATUS,C LCDWriteNibble

;#3 Send control sequence

95

Annex IV: Programa

movlw movwf rcall

;test delay 0xFF delay DelayXCycles

;Wait ~100us @ 20 MHz

;4 bits, 1 linea, 5x8 puntos movlw movwf bcf rcall

b'00100000' temp_wr STATUS,C LCDWriteNibble

;#4 set 4-bit

rcall

LCDBusy

;Busy?

;RS sea 0

;4 bits, 2 lineas, 5x8 puntos movlw movwf rcall

b'00101000' temp_wr i_write

;#5 Function set

;INSTRUCTION RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 ; 0 0 0 0 0 0 1 D C B ;D=0 ->dispaly ON D=1 ->dispaly ON ;C=0 ->cursor OFF C=1 ->cursor ON ;B=0 ->parpadeo OFF B=1 ->parpadeo ON ;dispaly ON, cursor OFF, parpadeo ON movlw movwf rcall

b'00001101' temp_wr i_write

;#6 Display = ON

;INSTRUCTION RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 ; 0 0 0 0 0 0 0 0 0 1 ;dispaly clear, cursor a primera posicion primera linea movlw movwf rcall

b'00000001' temp_wr i_write

;#7 Display Clear

;INSTRUCTION RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 ; 0 0 0 0 0 0 0 1 I/D SH ;I/D=0->cursor/blinc mueve izquierda, direccion DDRAM decrementa 1 ;I/D=1->cursor/blinc mueve derecha, direccion DDRAM incrementa 1 ;SH=0->no shift SH=1->shift del display entero izquierda o ;derecha segun el valor de I/D ;hacia la derecha, no shift movlw movwf rcall

b'00000110' temp_wr i_write

;#8 Entry Mode

;DDRAM addresss 0000

; ; ;

movlw movwf rcall

b'10000000' temp_wr i_write

movlw movwf call

b'00000010' temp_wr i_write

;return home

return GLOBAL LCDInit ; _ ______________________________ ; RS _>--<______________________________ ; _____ ; RW \_____________________________ ; __________________ ; E ____________/ \___ ; _____________ ______ ; DB _____________>--------------<______

96

Annex IV: Programa

LCDWriteNibble btfss bcf btfsc bsf

STATUS, C LCD_RS STATUS, C LCD_RS

; Set the register select

bcf

LCD_RW

; Set write mode

bcf bcf bcf bcf

LCD_D4_DIR LCD_D5_DIR LCD_D6_DIR LCD_D7_DIR

; Set data bits to outputs

NOP NOP

; Small delay

bsf

LCD_E

; Setup to clock data

btfss bcf btfsc bsf btfss bcf btfsc bsf btfss bcf btfsc bsf btfss bcf btfsc bsf

temp_wr, 7 LCD_D7 temp_wr, 7 LCD_D7 temp_wr, 6 LCD_D6 temp_wr, 6 LCD_D6 temp_wr, 5 LCD_D5 temp_wr, 5 LCD_D5 temp_wr, 4 LCD_D4 temp_wr, 4 LCD_D4

; Set high nibble

LCD_E

; Send the data

NOP NOP bcf return LCDWrite ; rcall LCDBusy rcall LCDWriteNibble ;cambia posicion de los bits. Ej: ABCDEFGH -> EFGHABCD swapf temp_wr,F rcall LCDWriteNibble swapf temp_wr,F return GLOBAL LCDWrite ; _____ _____________________________________________________ ; RS _____>--<_____________________________________________________ ; ____________________________________________________ ; RW _________/ ; ____________________ ____________________ ; E ____________/ \____/ \__ ; _________________ __________ ___ ; DB _________________>--------------<__________>--------------<___ LCDRead bsf bsf bsf bsf

LCD_D4_DIR LCD_D5_DIR LCD_D6_DIR LCD_D7_DIR

; Set data bits to inputs

btfss bcf btfsc bsf

STATUS, C LCD_RS STATUS, C LCD_RS

; Set the register select

bsf

LCD_RW

;Read = 1

97

Annex IV: Programa NOP NOP bsf

LCD_E

; Setup to clock data

btfss bcf btfsc bsf btfss bcf btfsc bsf btfss bcf btfsc bsf btfss bcf btfsc bsf

LCD_D7 temp_rd, 7 LCD_D7 temp_rd, 7 LCD_D6 temp_rd, 6 LCD_D6 temp_rd, 6 LCD_D5 temp_rd, 5 LCD_D5 temp_rd, 5 LCD_D4 temp_rd, 4 LCD_D4 temp_rd, 4

; Get high nibble

bcf

LCD_E

; Finished reading the data

LCD_E

; Setup to clock data

btfss bcf btfsc bsf btfss bcf btfsc bsf btfss bcf btfsc bsf btfss bcf btfsc bsf

LCD_D7 temp_rd, 3 LCD_D7 temp_rd, 3 LCD_D6 temp_rd, 2 LCD_D6 temp_rd, 2 LCD_D5 temp_rd, 1 LCD_D5 temp_rd, 1 LCD_D4 temp_rd, 0 LCD_D4 temp_rd, 0

; Get low nibble

bcf

LCD_E

; Finished reading the data

NOP NOP NOP NOP

NOP NOP NOP NOP NOP NOP NOP NOP bsf NOP NOP

FinRd return LCDBusy ; Check BF rlcd btfsc bra return

LCD_INS temp_rd, 7 LCDBusy

GLOBAL LCDBusy DelayXCycles decfsz

delay,F

98

Annex IV: Programa bra return

DelayXCycles

END

IV.3. PFC.ASM list p=18f2620 #include p18f2620.inc #include "subaddres.def" #define

slave_addres

B'01101000'

#define #define #define #define #define #define #define #define #define #define

max_f0 min_f0 min_Q max_Q min_G_g max_G_g min_G max_G min_V max_V

d'29' d'0' d'0' d'3' d'0' d'24' d'0' d'24' d'0' d'30'

;Program Configuration Registers CONFIG OSC=EC CONFIG CP0 = OFF, CP1 = OFF, CP2 = OFF, CP3 = OFF CONFIG WRT0 = OFF, WRT1 = OFF, WRT2 = OFF, WRT3 = OFF CONFIG EBTR0 = OFF, EBTR1 = OFF, EBTR2 = OFF, EBTR3 = OFF EXTERN LCDInit, temp_wr, d_write, i_write, LCDLine_1, LCDLine_2, LCDWrite, LCDBusy EXTERN WakeSlave, WrADDR, WrDATA, Stop, TASDATA, TASADDR UDATA R_ADDR TBLOW TBHIGH ptr_c OLDTBLL OLDTBLH OLDTBLU NEXTDATA xmilisec ymilisec cont_delay ptr_pos ptr_count ASCII_C ASCII_D ASCII_U BINARI V T B G_Biquad0_g G_Biquad1_g G_Biquad2_g G_Biquad3_g G_Biquad4_g G_Biquad0 G_Biquad1 G_Biquad2 G_Biquad3 G_Biquad4 G_Biquad5 f0_Biquad0 f0_Biquad1 f0_Biquad2 f0_Biquad3 f0_Biquad4 f0_Biquad5 Q_Biquad0 Q_Biquad1

RES RES RES RES RES RES RES RES RES RES RES RES RES RES RES RES RES RES RES RES RES RES RES RES RES RES RES RES RES RES RES RES RES RES RES RES RES RES RES

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

;# ms en delay ;variable para delay ;variable para delay ;variables para mostrar número porLCD ;hay que pasarlo a ASCII

;guan per equalitzador gràfic

;guany per equalitzador paramètric

;f0 per equalitzador paramètric

;Q per equalitzador paramètric

99

Annex IV: Programa Q_Biquad2 Q_Biquad3 Q_Biquad4 Q_Biquad5 Gain i filtre G f0 Q Gbis Quin_EQ Quin_EQ_pre k

RES RES RES RES RES RES RES RES RES RES RES RES RES RES

STARTUP

CODE

NOP goto NOP NOP NOP PROGRAM

1 1 1 1 1 1 1 1 1 1 1 1 1 1

Main

;de 0 a 24, correspon a guanys de -12dB a 12dB (intèrvals de 1dB) ;de 0 a 29, correspon a freqüències de 25Hz a 20kHz (separades 1/3 d'octava) ;de 0 a 3 , correspon a Q de 2,1,2/3 i 1/3 de octava ;per la funció LCD_G ;0->EQ_grafic, 1->EQ_predefinit, 2->EQ_paramètric ;0->rock ,1->jazz ,2->clasica ,3->dance ,4->pop ,5->uniforme

;go to start of main code

CODE

Main include

"ini_placa.asm"

include

"ini_var.asm"

;TAS3001 fast mode call load_EQ ;Modificar registro MSR para normal mode call send_MCR ;TAS3001 normal mode call update_mixer call update_volum include

"menu.asm"

include

"EQpred_menu.asm"

include

"EQgraf_menu.asm"

include

"EQparam_menu.asm"

include

"func.asm"

include

"update_vars.asm"

include

"LCD_func.asm"

include

"load_EQ.asm"

include

"save_EQ.asm"

include

"send_TAS.asm"

include

"LCD_tab.asm"

include

"EQ_param_tab.asm"

include

"EQ_predef_tab.asm"

include

"EQ_graf_tab.asm"

include

"Volum_tab.asm"

END

100

Annex IV: Programa

Ini_placa.asm call

LCDInit

clrf clrf

PORTB TRISB

; configure SSP for hardware master mode I2C bsf SSPSTAT,SMP bsf SSPCON1,SSPM3 bsf SSPCON1,SSPEN movlw movwf

0x29 SSPADD

clrf movlw movwf

PORTC 018h TRISC

clrf

PORTA

bsf bsf bsf bcf

TRISA,0 TRISA,1 TRISA,2 TRISA,3

movlw movwf

0Fh ADCON1

movlw movwf

07h CMCON

bsf movlw call bcf movlw call bsf movlw call

PORTA,3 d'10' delay_ms PORTA,3 d'10' delay_ms PORTA,3 d'10' delay_ms

clrf

PORTC

bsf bsf bsf bsf

TRISC,3 PORTC,3 TRISC,4 PORTC,4

; I2C slew rate control disabled ; I2C master mode in hardware ; enable SSP module ; set I2C clock rate to 100kHz ;clock = FOSC / (4 * (SSPADD+1)) ;SSPADD=d'29' ;00011xxx

;xxxx0111 ;make switch RA0 an Input ;make switch RA1 an Input ;make switch RA2 an Input ;make switch RA2 an Output

;Configure comparators ;for digital input

;hacer reset al TAS y al codec

;esperar 5ms para TAS listo

; I2C SCL pin is input ; (will be controlled by SSP) ; I2C SDA pin is input ; (will be controlled by SSP)

Ini_var.asm ;recuperem V MOVLW MOVWF MOVLW MOVWF BCF BCF BSF MOVFF

d'0' EEADRH d'0' EEADR EECON1, EEPGD EECON1, CFGS EECON1, RD EEDATA, V

; Data Memory Address to read ; Point to DATA memory ; Access EEPROM ; EEPROM Read ; W = EEDATA

;recuperem T MOVLW MOVWF MOVLW MOVWF BCF BCF BSF MOVFF

d'0' EEADRH d'1' EEADR EECON1, EEPGD EECON1, CFGS EECON1, RD EEDATA, T

; Data Memory Address to read ; Point to DATA memory ; Access EEPROM ; EEPROM Read ; W = EEDATA

;recuperem B

101

Annex IV: Programa MOVLW MOVWF MOVLW MOVWF BCF BCF BSF MOVFF

d'0' EEADRH d'2' EEADR EECON1, EEPGD EECON1, CFGS EECON1, RD EEDATA, B

; Data Memory Address to read ; Point to DATA memory ; Access EEPROM ; EEPROM Read ; W = EEDATA

;recuperem G_Biquad0_g MOVLW d'0' MOVWF EEADRH MOVLW d'3' MOVWF EEADR BCF EECON1, EEPGD BCF EECON1, CFGS BSF EECON1, RD MOVFF EEDATA, G_Biquad0_g

; Data Memory Address to read ; Point to DATA memory ; Access EEPROM ; EEPROM Read ; W = EEDATA

;recuperem G_Biquad1_g MOVLW d'0' MOVWF EEADRH MOVLW d'4' MOVWF EEADR BCF EECON1, EEPGD BCF EECON1, CFGS BSF EECON1, RD MOVFF EEDATA, G_Biquad1_g

; Data Memory Address to read ; Point to DATA memory ; Access EEPROM ; EEPROM Read ; W = EEDATA

;recuperem G_Biquad2_g MOVLW d'0' MOVWF EEADRH MOVLW d'5' MOVWF EEADR BCF EECON1, EEPGD BCF EECON1, CFGS BSF EECON1, RD MOVFF EEDATA, G_Biquad2_g

; Data Memory Address to read ; Point to DATA memory ; Access EEPROM ; EEPROM Read ; W = EEDATA

;recuperem G_Biquad3_g MOVLW d'0' MOVWF EEADRH MOVLW d'6' MOVWF EEADR BCF EECON1, EEPGD BCF EECON1, CFGS BSF EECON1, RD MOVFF EEDATA, G_Biquad3_g

; Data Memory Address to read ; Point to DATA memory ; Access EEPROM ; EEPROM Read ; W = EEDATA

;recuperem G_Biquad4_g MOVLW d'0' MOVWF EEADRH MOVLW d'7' MOVWF EEADR BCF EECON1, EEPGD BCF EECON1, CFGS BSF EECON1, RD MOVFF EEDATA, G_Biquad4_g

; Data Memory Address to read ; Point to DATA memory ; Access EEPROM ; EEPROM Read ; W = EEDATA

;recuperem G_Biquad0 MOVLW d'0' MOVWF EEADRH MOVLW d'8' MOVWF EEADR BCF EECON1, EEPGD BCF EECON1, CFGS BSF EECON1, RD MOVFF EEDATA, G_Biquad0

; Data Memory Address to read ; Point to DATA memory ; Access EEPROM ; EEPROM Read ; W = EEDATA

;recuperem G_Biquad1 MOVLW d'0' MOVWF EEADRH MOVLW d'9' MOVWF EEADR BCF EECON1, EEPGD BCF EECON1, CFGS

; Data Memory Address to read ; Point to DATA memory ; Access EEPROM

102

Annex IV: Programa BSF EECON1, RD MOVFF EEDATA, G_Biquad1

; EEPROM Read ; W = EEDATA

;recuperem G_Biquad2 MOVLW d'0' MOVWF EEADRH MOVLW d'10' MOVWF EEADR BCF EECON1, EEPGD BCF EECON1, CFGS BSF EECON1, RD MOVFF EEDATA, G_Biquad2

; Data Memory Address to read ; Point to DATA memory ; Access EEPROM ; EEPROM Read ; W = EEDATA

;recuperem G_Biquad3 MOVLW d'0' MOVWF EEADRH MOVLW d'11' MOVWF EEADR BCF EECON1, EEPGD BCF EECON1, CFGS BSF EECON1, RD MOVFF EEDATA, G_Biquad3

; Data Memory Address to read ; Point to DATA memory ; Access EEPROM ; EEPROM Read ; W = EEDATA

;recuperem G_Biquad4 MOVLW d'0' MOVWF EEADRH MOVLW d'12' MOVWF EEADR BCF EECON1, EEPGD BCF EECON1, CFGS BSF EECON1, RD MOVFF EEDATA, G_Biquad4

; Data Memory Address to read ; Point to DATA memory ; Access EEPROM ; EEPROM Read ; W = EEDATA

;recuperem G_Biquad5 MOVLW d'0' MOVWF EEADRH MOVLW d'13' MOVWF EEADR BCF EECON1, EEPGD BCF EECON1, CFGS BSF EECON1, RD MOVFF EEDATA, G_Biquad5

; Data Memory Address to read ; Point to DATA memory ; Access EEPROM ; EEPROM Read ; W = EEDATA

;recuperem f0_Biquad0 MOVLW d'0' MOVWF EEADRH MOVLW d'14' MOVWF EEADR BCF EECON1, EEPGD BCF EECON1, CFGS BSF EECON1, RD MOVFF EEDATA, f0_Biquad0

; Data Memory Address to read ; Point to DATA memory ; Access EEPROM ; EEPROM Read ; W = EEDATA

;recuperem f0_Biquad1 MOVLW d'0' MOVWF EEADRH MOVLW d'15' MOVWF EEADR BCF EECON1, EEPGD BCF EECON1, CFGS BSF EECON1, RD MOVFF EEDATA, f0_Biquad1

; Data Memory Address to read ; Point to DATA memory ; Access EEPROM ; EEPROM Read ; W = EEDATA

;recuperem f0_Biquad2 MOVLW d'0' MOVWF EEADRH MOVLW d'16' MOVWF EEADR BCF EECON1, EEPGD BCF EECON1, CFGS BSF EECON1, RD MOVFF EEDATA, f0_Biquad2

; Data Memory Address to read ; Point to DATA memory ; Access EEPROM ; EEPROM Read ; W = EEDATA

;recuperem f0_Biquad3 MOVLW d'0' MOVWF EEADRH

103

Annex IV: Programa MOVLW MOVWF BCF BCF BSF MOVFF

d'17' EEADR EECON1, EEPGD EECON1, CFGS EECON1, RD EEDATA, f0_Biquad3

; Data Memory Address to read ; Point to DATA memory ; Access EEPROM ; EEPROM Read ; W = EEDATA

;recuperem f0_Biquad4 MOVLW d'0' MOVWF EEADRH MOVLW d'18' MOVWF EEADR BCF EECON1, EEPGD BCF EECON1, CFGS BSF EECON1, RD MOVFF EEDATA, f0_Biquad4

; Data Memory Address to read ; Point to DATA memory ; Access EEPROM ; EEPROM Read ; W = EEDATA

;recuperem f0_Biquad5 MOVLW d'0' MOVWF EEADRH MOVLW d'19' MOVWF EEADR BCF EECON1, EEPGD BCF EECON1, CFGS BSF EECON1, RD MOVFF EEDATA, f0_Biquad5

; Data Memory Address to read ; Point to DATA memory ; Access EEPROM ; EEPROM Read ; W = EEDATA

;recuperem Q_Biquad0 MOVLW d'0' MOVWF EEADRH MOVLW d'20' MOVWF EEADR BCF EECON1, EEPGD BCF EECON1, CFGS BSF EECON1, RD MOVFF EEDATA, Q_Biquad0

; Data Memory Address to read ; Point to DATA memory ; Access EEPROM ; EEPROM Read ; W = EEDATA

;recuperem Q_Biquad1 MOVLW d'0' MOVWF EEADRH MOVLW d'21' MOVWF EEADR BCF EECON1, EEPGD BCF EECON1, CFGS BSF EECON1, RD MOVFF EEDATA, Q_Biquad1

; Data Memory Address to read ; Point to DATA memory ; Access EEPROM ; EEPROM Read ; W = EEDATA

;recuperem Q_Biquad2 MOVLW d'0' MOVWF EEADRH MOVLW d'22' MOVWF EEADR BCF EECON1, EEPGD BCF EECON1, CFGS BSF EECON1, RD MOVFF EEDATA, Q_Biquad2

; Data Memory Address to read ; Point to DATA memory ; Access EEPROM ; EEPROM Read ; W = EEDATA

;recuperem Q_Biquad3 MOVLW d'0' MOVWF EEADRH MOVLW d'23' MOVWF EEADR BCF EECON1, EEPGD BCF EECON1, CFGS BSF EECON1, RD MOVFF EEDATA, Q_Biquad3

; Data Memory Address to read ; Point to DATA memory ; Access EEPROM ; EEPROM Read ; W = EEDATA

;recuperem Q_Biquad4 MOVLW d'0' MOVWF EEADRH MOVLW d'24' MOVWF EEADR BCF EECON1, EEPGD BCF EECON1, CFGS BSF EECON1, RD MOVFF EEDATA, Q_Biquad4

; Data Memory Address to read ; Point to DATA memory ; Access EEPROM ; EEPROM Read ; W = EEDATA

104

Annex IV: Programa

;recuperem Q_Biquad5 MOVLW d'0' MOVWF EEADRH MOVLW d'25' MOVWF EEADR BCF EECON1, EEPGD BCF EECON1, CFGS BSF EECON1, RD MOVFF EEDATA, Q_Biquad5

; Data Memory Address to read ; Point to DATA memory ; Access EEPROM ; EEPROM Read ; W = EEDATA

;recuperem Quin_EQ MOVLW d'0' MOVWF EEADRH MOVLW d'26' MOVWF EEADR BCF EECON1, EEPGD BCF EECON1, CFGS BSF EECON1, RD MOVFF EEDATA, Quin_EQ

; Data Memory Address to read ; Point to DATA memory ; Access EEPROM ; EEPROM Read ; W = EEDATA

;recuperem Quin_EQ_pre MOVLW d'0' MOVWF EEADRH MOVLW d'27' MOVWF EEADR BCF EECON1, EEPGD BCF EECON1, CFGS BSF EECON1, RD MOVFF EEDATA, Quin_EQ_pre

; Data Memory Address to read ; Point to DATA memory ; Access EEPROM ; EEPROM Read ; W = EEDATA

Menu.asm Wait_white movlw movwf call call movlw movwf call

.37 ptr_pos stan_char_1 LCDLine_2 .35 ptr_pos stan_char_2

Wait btfss goto btfss goto btfss goto goto

PORTA,0 show_menu_EQgraf PORTA,1 up_vol PORTA,2 down_vol Wait

show_menu_EQgraf call call call movlw movwf call call movlw movwf call movlw call

wait_set wait_up wait_down .38 ptr_pos stan_char_1 LCDLine_2 .30 ptr_pos stan_char_2 d'250' delay_ms

elec_menu_EQgraf btfss goto btfss goto btfss goto bra

PORTA,0 load_EQgraf PORTA,1 show_menu_EQpredef PORTA,2 show_exit_menu elec_menu_EQgraf

;ha sido pulsado SET? ;ha sido pulsado UP? ;ha sido pulsado DOWN?

;ha sido pulsado SET? ;ha sido pulsado UP? ;ha sido pulsado DOWN?

105

Annex IV: Programa show_menu_EQpredef call wait_up call wait_down call wait_set movlw .38 movwf ptr_pos call stan_char_1 call LCDLine_2 movlw .31 movwf ptr_pos call stan_char_2 movlw d'250' call delay_ms elec_menu_EQpredef btfss PORTA,0 goto Menu_EQpredef btfss PORTA,1 goto show_menu_EQparam btfss PORTA,2 goto show_menu_EQgraf bra elec_menu_EQpredef

;ha sido pulsado SET? ;ha sido pulsado UP? ;ha sido pulsado DOWN?

show_menu_EQparam call wait_up call wait_down call wait_set movlw .38 movwf ptr_pos call stan_char_1 call LCDLine_2 movlw .39 movwf ptr_pos call stan_char_2 movlw d'250' call delay_ms elec_menu_EQparam btfss PORTA,0 goto load_EQparam btfss PORTA,1 goto show_exit_menu btfss PORTA,2 goto show_menu_EQpredef bra elec_menu_EQparam show_exit_menu call call call movlw movwf call call movlw movwf call movlw call

wait_up wait_down wait_set .34 ptr_pos stan_char_1 LCDLine_2 .35 ptr_pos stan_char_2 d'250' delay_ms

elec_exit_menu btfss bra btfss goto btfss goto bra

PORTA,0 exit_menu PORTA,1 show_menu_EQgraf PORTA,2 show_menu_EQparam elec_exit_menu

;ha sido pulsado SET? ;ha sido pulsado UP? ;ha sido pulsado DOWN?

;ha sido pulsado SET? ;ha sido pulsado UP? ;ha sido pulsado DOWN?

exit_menu call call goto

wait_set save_EQ Wait_white

106

Annex IV: Programa

EQpred_menu.asm Menu_EQpredef movlw cpfseq bra bra

d'1' Quin_EQ load_EQpred show_EQpred

load_EQpred movlw movwf call

d'1' Quin_EQ update_EQ_predef

show_EQpred call call call call movlw addwf movwf call call movlw movwf call movlw call

wait_up wait_down wait_set LCDLine_1 .51 Quin_EQ_pre,W ptr_pos stan_char_1 LCDLine_2 .33 ptr_pos stan_char_2 d'250' delay_ms

elec_EQpred btfss goto btfss goto btfss goto bra

PORTA,0 exit_EQpred PORTA,1 up_EQpred PORTA,2 down_EQpred elec_EQpred

up_EQpred movlw cpfseq bra movlw movwf bra

d'5' Quin_EQ_pre inc_EQpred d'0' Quin_EQ_pre inc_EQpred_bis

inc_EQpred incf

Quin_EQ_pre,1

inc_EQpred_bis call goto

update_EQ_predef show_EQpred

down_EQpred movlw cpfseq bra movlw movwf

d'0' Quin_EQ_pre dec_EQpred d'6' Quin_EQ_pre

dec_EQpred decf call goto

Quin_EQ_pre,1 update_EQ_predef show_EQpred

exit_EQpred goto

show_menu_EQpredef

;ha sido pulsado SET? ;ha sido pulsado UP? ;ha sido pulsado DOWN?

EQgraf_menu.asm load_EQgraf movlw cpfsgt

d'0' Quin_EQ

107

Annex IV: Programa bra movlw movwf call

show_EQgraf_1_band d'0' Quin_EQ load_EQ

show_EQgraf_1_band call wait_up call wait_down call wait_set movlw .4 movwf ptr_pos call stan_char_1 call LCDLine_2 movlw .33 movwf ptr_pos call stan_char_2 movlw d'250' call delay_ms elec_EQgraf_1_band btfss goto btfss goto btfss goto bra

PORTA,0 EQgraf_1_band PORTA,1 show_EQgraf_2_band PORTA,2 show_exit_EQgraf elec_EQgraf_1_band

;ha sido pulsado SET? ;ha sido pulsado UP? ;ha sido pulsado DOWN?

show_EQgraf_2_band call wait_up call wait_down call wait_set movlw .10 movwf ptr_pos call stan_char_1 call LCDLine_2 movlw .33 movwf ptr_pos call stan_char_2 movlw d'250' call delay_ms elec_EQgraf_2_band btfss goto btfss goto btfss goto bra

PORTA,0 EQgraf_2_band PORTA,1 show_EQgraf_3_band PORTA,2 show_EQgraf_1_band elec_EQgraf_2_band

;ha sido pulsado SET? ;ha sido pulsado UP? ;ha sido pulsado DOWN?

show_EQgraf_3_band call wait_up call wait_down call wait_set movlw .16 movwf ptr_pos call stan_char_1 call LCDLine_2 movlw .33 movwf ptr_pos call stan_char_2 movlw d'250' call delay_ms elec_EQgraf_3_band btfss goto btfss goto btfss goto bra

PORTA,0 EQgraf_3_band PORTA,1 show_EQgraf_4_band PORTA,2 show_EQgraf_2_band elec_EQgraf_3_band

;ha sido pulsado SET? ;ha sido pulsado UP? ;ha sido pulsado DOWN?

show_EQgraf_4_band call wait_up

108

Annex IV: Programa call call movlw movwf call call movlw movwf call movlw call elec_EQgraf_4_band btfss goto btfss goto btfss goto bra

wait_down wait_set .22 ptr_pos stan_char_1 LCDLine_2 .33 ptr_pos stan_char_2 d'250' delay_ms PORTA,0 EQgraf_4_band PORTA,1 show_EQgraf_5_band PORTA,2 show_EQgraf_3_band elec_EQgraf_4_band

;ha sido pulsado SET? ;ha sido pulsado UP? ;ha sido pulsado DOWN?

show_EQgraf_5_band call wait_up call wait_down call wait_set movlw .28 movwf ptr_pos call stan_char_1 call LCDLine_2 movlw .33 movwf ptr_pos call stan_char_2 movlw d'250' call delay_ms elec_EQgraf_5_band btfss goto btfss goto btfss goto bra

PORTA,0 EQgraf_5_band PORTA,1 show_exit_EQgraf PORTA,2 show_EQgraf_4_band elec_EQgraf_5_band

show_exit_EQgraf call call call movlw movwf call call movlw movwf call movlw call elec_exit_EQgraf btfss goto btfss goto btfss goto bra

PORTA,0 show_menu_EQgraf PORTA,1 show_EQgraf_1_band PORTA,2 show_EQgraf_5_band elec_exit_EQgraf

EQgraf_1_band call movlw movwf movff call movff goto

wait_set d'1' filtre G_Biquad0_g,G show_G_g G,G_Biquad0_g show_EQgraf_2_band

;ha sido pulsado SET? ;ha sido pulsado UP? ;ha sido pulsado DOWN?

wait_up wait_down wait_set .34 ptr_pos stan_char_1 LCDLine_2 .36 ptr_pos stan_char_2 d'250' delay_ms ;ha sido pulsado SET? ;ha sido pulsado UP? ;ha sido pulsado DOWN?

EQgraf_2_band

109

Annex IV: Programa call movlw movwf movff call movff goto

wait_set d'2' filtre G_Biquad1_g,G show_G_g G,G_Biquad1_g show_EQgraf_3_band

EQgraf_3_band call movlw movwf movff call movff goto

wait_set d'3' filtre G_Biquad2_g,G show_G_g G,G_Biquad2_g show_EQgraf_4_band

EQgraf_4_band call movlw movwf movff call movff goto

wait_set d'4' filtre G_Biquad3_g,G show_G_g G,G_Biquad3_g show_EQgraf_5_band

EQgraf_5_band call movlw movwf movff call movff goto

wait_set d'5' filtre G_Biquad4_g,G show_G_g G,G_Biquad4_g show_exit_EQgraf

EQparam_menu.asm load_EQparam movlw cpfslt bra movlw movwf call

d'2' Quin_EQ show_EQparam_1_band d'2' Quin_EQ load_EQ

show_EQparam_1_band call wait_up call wait_down call wait_set movlw .40 movwf ptr_pos call stan_char_1 call LCDLine_2 movlw .33 movwf ptr_pos call stan_char_2 movlw d'250' call delay_ms elec_EQparam_1_band btfss PORTA,0 goto EQparam_1_band btfss PORTA,1 goto show_EQparam_2_band btfss PORTA,2 goto show_exit_EQparam bra elec_EQparam_1_band

;ha sido pulsado SET? ;ha sido pulsado UP? ;ha sido pulsado DOWN?

show_EQparam_2_band call wait_up call wait_down call wait_set movlw .41 movwf ptr_pos

110

Annex IV: Programa call call movlw movwf call movlw call

stan_char_1 LCDLine_2 .33 ptr_pos stan_char_2 d'250' delay_ms

elec_EQparam_2_band btfss PORTA,0 goto EQparam_2_band btfss PORTA,1 goto show_EQparam_3_band btfss PORTA,2 goto show_EQparam_1_band bra elec_EQparam_2_band

;ha sido pulsado SET? ;ha sido pulsado UP? ;ha sido pulsado DOWN?

show_EQparam_3_band call wait_up call wait_down call wait_set movlw .42 movwf ptr_pos call stan_char_1 call LCDLine_2 movlw .33 movwf ptr_pos call stan_char_2 movlw d'250' call delay_ms elec_EQparam_3_band btfss PORTA,0 goto EQparam_3_band btfss PORTA,1 goto show_EQparam_4_band btfss PORTA,2 goto show_EQparam_2_band bra elec_EQparam_3_band

;ha sido pulsado SET? ;ha sido pulsado UP? ;ha sido pulsado DOWN?

show_EQparam_4_band call wait_up call wait_down call wait_set movlw .43 movwf ptr_pos call stan_char_1 call LCDLine_2 movlw .33 movwf ptr_pos call stan_char_2 movlw d'250' call delay_ms elec_EQparam_4_band btfss PORTA,0 goto EQparam_4_band btfss PORTA,1 goto show_EQparam_5_band btfss PORTA,2 goto show_EQparam_3_band bra elec_EQparam_4_band

;ha sido pulsado SET? ;ha sido pulsado UP? ;ha sido pulsado DOWN?

show_EQparam_5_band call wait_up call wait_down call wait_set movlw .44 movwf ptr_pos call stan_char_1 call LCDLine_2 movlw .33 movwf ptr_pos call stan_char_2 movlw d'250' call delay_ms

111

Annex IV: Programa

elec_EQparam_5_band btfss PORTA,0 goto EQparam_5_band btfss PORTA,1 goto show_EQparam_6_band btfss PORTA,2 goto show_EQparam_4_band bra elec_EQparam_5_band

;ha sido pulsado SET? ;ha sido pulsado UP? ;ha sido pulsado DOWN?

show_EQparam_6_band call wait_up call wait_down call wait_set movlw .45 movwf ptr_pos call stan_char_1 call LCDLine_2 movlw .33 movwf ptr_pos call stan_char_2 movlw d'250' call delay_ms elec_EQparam_6_band btfss PORTA,0 goto EQparam_6_band btfss PORTA,1 goto show_exit_EQparam btfss PORTA,2 goto show_EQparam_5_band bra elec_EQparam_6_band show_exit_EQparam call call call movlw movwf call call movlw movwf call movlw call

wait_up wait_down wait_set .34 ptr_pos stan_char_1 LCDLine_2 .46 ptr_pos stan_char_2 d'250' delay_ms

elec_exit_EQparam btfss goto btfss goto btfss goto bra

PORTA,0 show_menu_EQparam PORTA,1 show_EQparam_1_band PORTA,2 show_EQparam_6_band elec_exit_EQparam

EQparam_1_band call movlw movwf movff movff movff call movff call movff call movff goto

wait_set d'1' filtre G_Biquad0,G Q_Biquad0,Q f0_Biquad0,f0 show_freq f0,f0_Biquad0 show_Q Q,Q_Biquad0 show_G G,G_Biquad0 show_EQparam_2_band

EQparam_2_band call movlw movwf movff

wait_set d'2' filtre G_Biquad1,G

;ha sido pulsado SET? ;ha sido pulsado UP? ;ha sido pulsado DOWN?

;ha sido pulsado SET? ;ha sido pulsado UP? ;ha sido pulsado DOWN?

112

Annex IV: Programa movff movff call movff call movff call movff goto

Q_Biquad1,Q f0_Biquad1,f0 show_freq f0,f0_Biquad1 show_Q Q,Q_Biquad1 show_G G,G_Biquad1 show_EQparam_3_band

EQparam_3_band call movlw movwf movff movff movff call movff call movff call movff goto

wait_set d'3' filtre G_Biquad2,G Q_Biquad2,Q f0_Biquad2,f0 show_freq f0,f0_Biquad2 show_Q Q,Q_Biquad2 show_G G,G_Biquad2 show_EQparam_4_band

EQparam_4_band call movlw movwf movff movff movff call movff call movff call movff goto

wait_set d'4' filtre G_Biquad3,G Q_Biquad3,Q f0_Biquad3,f0 show_freq f0,f0_Biquad3 show_Q Q,Q_Biquad3 show_G G,G_Biquad3 show_EQparam_5_band

EQparam_5_band call movlw movwf movff movff movff call movff call movff call movff goto

wait_set d'5' filtre G_Biquad4,G Q_Biquad4,Q f0_Biquad4,f0 show_freq f0,f0_Biquad4 show_Q Q,Q_Biquad4 show_G G,G_Biquad4 show_EQparam_6_band

EQparam_6_band call movlw movwf movff movff movff call movff call movff call movff goto

wait_set d'6' filtre G_Biquad5,G Q_Biquad5,Q f0_Biquad5,f0 show_freq f0,f0_Biquad5 show_Q Q,Q_Biquad5 show_G G,G_Biquad5 show_exit_EQparam

Func.asm delay_ms movwf

xmilisec

;save # of millisecs in w to delay.

113

Annex IV: Programa incf

xmilisec,f

;adjust to account for initial decrement. ;first (outer) loop.

dcfsnz return movlw movwf

xmilisec,f

;update first (outer) loop ;done when xmillisec=0.

movlw movwf

d'251' ymilisec

decfsz bra decfsz bra bra

ymilisec,f loopb cont_delay loopa loop_ms

loop_ms d'4' cont_delay

loopa ;second (inner) loop ;250 loops (240+1 becomes 251)

loopb ;update 256 part of inner loop. ;1 usec per loop ;continue with next outer loop

;wait_set:espera a que se deje de pulsar set wait_set movlw call

d'100' delay_ms

;anti rebotes 100 ms

btfss bra return

PORTA,0 pushed

;han dejado de pulsar SET? ;NO->me espero a que se deje de pulsar

pushed

;wait_up:espera a que se deje de pulsar up wait_up movlw call

d'100' delay_ms

;anti rebotes 100 ms

btfss bra return

PORTA,1 pushed_1

;han dejado de pulsar SET? ;NO->me espero a que se deje de pulsar

pushed_1

;wait_down:espera a que se deje de pulsar down wait_down movlw call pushed_2 btfss bra return

d'100' delay_ms

;anti rebotes 100 ms

PORTA,2 pushed_2

;han dejado de pulsar SET? ;NO->me espero a que se deje de pulsar

Update_vars.asm show_freq movf call bucle_show_freq btfss bra btfss goto btfss goto bra

f0,W LCD_freq PORTA,0 fin_show_freq PORTA,1 up_f0 PORTA,2 down_f0 bucle_show_freq

;ha sido pulsado SET? ;ha sido pulsado UP? ;ha sido pulsado DOWN?

up_f0 movlw cpfslt goto incf call call movlw call btfsc

max_f0 f0 bucle_show_freq f0,F update_filtre LCD_freq d'250' delay_ms PORTA,1

;comprovar no máximo ;MÁXIMO->volver a esperar otra pulsación ;NO_MÁXIMO->incrementar f0 ;si se mantiene pulsado ;sigue subiendo cada 250 ms ;Todavía pulsado?

114

Annex IV: Programa bra bra

bucle_show_freq up_f0

movlw cpfsgt goto decf call call movlw call btfsc bra bra

min_f0 f0 bucle_show_freq f0,F update_filtre LCD_freq d'250' delay_ms PORTA,1 bucle_show_freq down_f0

;NO->esperar otra pulsación ;SI->volver a subir f0

down_f0

fin_show_freq call return

;comprovar no mínimo ;MÍNIMO->volver a esperar otra pulsación ;NO_MÍNIMO->decrementar f0 ;si se mantiene pulsado ;sigue subiendo cada 250 ms ;Todavia pulsado? ;NO->esperar otra pulsación ;SI->volver a subir f0

wait_set

show_Q movf call bucle_show_Q btfss bra btfss goto btfss goto bra

Q,W LCD_Q PORTA,0 fin_show_Q PORTA,1 up_Q PORTA,2 down_Q bucle_show_Q

;ha sido pulsado SET? ;ha sido pulsado UP? ;ha sido pulsado DOWN?

up_Q movlw cpfslt goto incf call call movlw call btfsc bra bra

max_Q Q bucle_show_Q Q,F update_filtre LCD_Q d'250' delay_ms PORTA,1 bucle_show_Q up_Q

movlw cpfsgt goto decf call call movlw call btfsc bra bra

min_Q Q bucle_show_Q Q,F update_filtre LCD_Q d'250' delay_ms PORTA,1 bucle_show_Q down_Q

;comprovar no máximo ;MÁXIMO->volver a esperar otra pulsación ;NO_MÁXIMO->incrementar Q ;si se mantiene pulsado ;sigue subiendo cada 250 ms ;Todavía pulsado? ;NO->esperar otra pulsación ;SI->volver a subir Q

down_Q

fin_show_Q call return

;comprovar no mínimo ;MÍNIMO->volver a esperar otra pulsación ;NO_MÍNIMO->decrementar Q ;si se mantiene pulsado ;sigue subiendo cada 250 ms ;Todavia pulsado? ;NO->esperar otra pulsación ;SI->volver a subir Q

wait_set

show_G_g call bucle_show_G_g btfss bra btfss goto btfss goto bra

LCD_G PORTA,0 fin_show_G_g PORTA,1 up_G_g PORTA,2 down_G_g bucle_show_G_g

;ha sido pulsado SET? ;ha sido pulsado UP? ;ha sido pulsado DOWN?

up_G_g

115

Annex IV: Programa movlw cpfslt goto incf call movf call movlw call btfsc bra bra

max_G_g G bucle_show_G_g G,F update_EQ_graf G,W LCD_G d'250' delay_ms PORTA,1 bucle_show_G_g up_G_g

down_G_g movlw cpfsgt goto decf call movf call movlw call btfsc bra bra

min_G_g G bucle_show_G_g G,F update_EQ_graf G,W LCD_G d'250' delay_ms PORTA,1 bucle_show_G_g down_G_g

fin_show_G_g call return

;comprovar no máximo ;MÁXIMO->volver a esperar otra pulsación ;NO_MÁXIMO->incrementar G

;si se mantiene pulsado ;sigue subiendo cada 250 ms ;Todavía pulsado? ;NO->esperar otra pulsación ;SI->volver a subir G

;comprovar no mínimo ;MÍNIMO->volver a esperar otra pulsación ;NO_MÍNIMO->decrementar G

;si se mantiene pulsado ;sigue subiendo cada 250 ms ;Todavia pulsado? ;NO->esperar otra pulsación ;SI->volver a subir G

wait_set

show_G call bucle_show_G btfss bra btfss goto btfss goto bra

LCD_G PORTA,0 fin_show_G PORTA,1 up_G PORTA,2 down_G bucle_show_G

;ha sido pulsado SET? ;ha sido pulsado UP? ;ha sido pulsado DOWN?

up_G movlw cpfslt goto incf call call movlw call btfsc bra bra

max_G G bucle_show_G G,F update_filtre LCD_G d'250' delay_ms PORTA,1 bucle_show_G up_G

movlw cpfsgt goto decf call call movlw call btfsc bra bra

min_G G bucle_show_G G,F update_filtre LCD_G d'250' delay_ms PORTA,1 bucle_show_G down_G

;comprovar no máximo ;MÁXIMO->volver a esperar otra pulsación ;NO_MÁXIMO->incrementar G ;si se mantiene pulsado ;sigue subiendo cada 250 ms ;Todavía pulsado? ;NO->esperar otra pulsación ;SI->volver a subir G

down_G

fin_show_G call return bucle_show_V btfss bra

;comprovar no mínimo ;MÍNIMO->volver a esperar otra pulsación ;NO_MÍNIMO->decrementar G ;si se mantiene pulsado ;sigue subiendo cada 250 ms ;Todavia pulsado? ;NO->esperar otra pulsación ;SI->volver a subir G

wait_set

PORTA,0 fin_show_V

;ha sido pulsado SET?

116

Annex IV: Programa btfss goto btfss goto bra

PORTA,1 up_vol PORTA,2 down_vol bucle_show_V

;ha sido pulsado UP?

movlw cpfslt bra incf call call movlw call btfsc bra bra

max_V V fin_show_V V,F update_volum LCD_V d'250' delay_ms PORTA,1 bucle_show_V up_vol

;si se mantiene pulsado ;sigue subiendo cada 250 ms ;Todavía pulsado? ;NO->esperar otra pulsación ;SI->volver a subir V

movlw cpfsgt bra decf call call movlw call btfsc bra bra

min_V V fin_show_V V,F update_volum LCD_V d'250' delay_ms PORTA,1 bucle_show_V down_vol

;si se mantiene pulsado ;sigue subiendo cada 250 ms ;Todavía pulsado? ;NO->esperar otra pulsación ;SI->volver a subir V

;ha sido pulsado DOWN?

up_vol

down_vol

fin_show_V call goto

wait_set Wait_white

LCD_func.asm stan_char_1 call movlw movwf movlw movwf movlw movwf movlw movwf movf mullw movf addwf movf addwfc clrf addwfc

LCDLine_1 .16 ptr_count UPPER stan_table TBLPTRU HIGH stan_table TBLPTRH LOW stan_table TBLPTRL ptr_pos,W d'16' PRODL,W TBLPTRL,F PRODH,W TBLPTRH,F WREG TBLPTRU,F

stan_next_char_1 tblrd movff call

*+ TABLAT,temp_wr d_write

decfsz bra

;mvoe cursor to line 1 ;1-full line of LCD

;send character to LCD

ptr_count,F stan_next_char_1

;move pointer to next char

LCDLine_2 .16 ptr_count UPPER stan_table TBLPTRU HIGH stan_table

;move cursor to line 2 ;1-full line of LCD

return stan_char_2 call movlw movwf movlw movwf movlw

117

Annex IV: Programa movwf movlw movwf movf mullw movf addwf movf addwfc clrf addwfc stan_next_char_2 tblrd movff call decfsz bra

TBLPTRH LOW stan_table TBLPTRL ptr_pos,W d'16' PRODL,W TBLPTRL,F PRODH,W TBLPTRH,F WREG TBLPTRU,F *+ TABLAT,temp_wr d_write ptr_count,F stan_next_char_2

;send character to LCD ;move pointer to next char

return XLCDPutNumber clrf ASCII_C clrf ASCII_D clrf ASCII_U movwf BINARI movlw d'100' centenas cpfslt BINARI bra dec_cen bra decenas dec_cen subwf BINARI,1 incf ASCII_C bra centenas decenas movlw d'10' decenas_loop cpfslt BINARI bra dec_dec bra unidades dec_dec subwf BINARI,1 incf ASCII_D bra decenas_loop unidades incf BINARI unidades_loop dcfsnz BINARI bra mostrar_numeros incf ASCII_U bra unidades_loop mostrar_numeros movf ASCII_C,0 clrf BINARI cpfseq BINARI bra aqui bra mostrar_decena_unidades aqui addlw d'48' movwf temp_wr call d_write mostrar_decena_unidades movf ASCII_D,0 addlw d'48' movwf temp_wr call d_write movf ASCII_U,0 addlw d'48' movwf temp_wr call d_write return LCD_freq call movff

LCDLine_1 f0,ptr_pos

118

Annex IV: Programa call call movlw movwf call return

stan_char_1 LCDLine_2 .33 ptr_pos stan_char_2

call movlw addwf movwf call call movlw movwf call return

LCDLine_1 d'47' Q,W ptr_pos stan_char_1 LCDLine_2 .33 ptr_pos stan_char_2

movff

G,Gbis

call movlw movwf

LCDLine_1 d'4' i

movlw movwf call decf movlw cpfseq bra

"" temp_wr d_write i d'0' i loopd

movlw movwf call movlw movwf call movlw movwf call movlw movwf call movlw movwf call movlw movwf call movlw subwf movlw btfsc bra negf movlw movwf call movf call movlw movwf bra

"G" temp_wr d_write "u" temp_wr d_write "a" temp_wr d_write "n" temp_wr d_write "y" temp_wr d_write "=" temp_wr d_write d'12' Gbis,F d'0' STATUS,C G_positiva Gbis "-" temp_wr d_write Gbis,0 XLCDPutNumber d'3' i loope

movf call movlw movwf

Gbis,0 XLCDPutNumber d'4' i

movlw movwf call decf

"" temp_wr d_write i

LCD_Q

LCD_G LCD_G_g

loopd

G_positiva

loope

119

Annex IV: Programa movlw cpfseq bra

d'0' i loope

call movlw movwf call

LCDLine_2 .33 ptr_pos stan_char_2

movlw call

d'250' delay_ms

return LCD_V call movlw movwf

LCDLine_1 d'4' i

movlw movwf call decf movlw cpfseq bra

"" temp_wr d_write i d'0' i looph

movlw movwf call movlw movwf call movlw movwf call movlw movwf call movlw movwf call movlw movwf call movf call movlw movwf

"V" temp_wr d_write "o" temp_wr d_write "l" temp_wr d_write "u" temp_wr d_write "m" temp_wr d_write "" temp_wr d_write V,0 XLCDPutNumber d'4' i

movlw movwf call decf movlw cpfseq bra

"" temp_wr d_write i d'0' i loopi

call movlw movwf call

LCDLine_2 .33 ptr_pos stan_char_2

movlw call

d'250' delay_ms

looph

loopi

return

Load_EQ.asm load_EQ movlw cpfsgt bra

d'0' Quin_EQ load_EQ_grafic

120

Annex IV: Programa movlw cpfsgt bra movlw cpfsgt bra load_EQ_grafic movlw movwf movff call movlw movwf movff call movlw movwf movff call movlw movwf movff call movlw movwf movff call movlw movwf movlw movwf movlw movwf movlw movwf call bra load_EQ_predefinit call bra load_EQ_parametric movlw movwf movff movff movff call movlw movwf movff movff movff call movlw movwf movff movff movff call movlw movwf movff movff movff call movlw movwf movff movff movff call movlw movwf movff movff

d'1' Quin_EQ load_EQ_predefinit d'2' Quin_EQ load_EQ_parametric d'1' filtre G_Biquad0_g,G update_EQ_graf d'2' filtre G_Biquad1_g,G update_EQ_graf d'3' filtre G_Biquad2_g,G update_EQ_graf d'4' filtre G_Biquad3_g,G update_EQ_graf d'5' filtre G_Biquad4_g,G update_EQ_graf d'6' filtre d'6' G d'0' f0 d'0' Q update_filtre fin_load_EQ

;el 6 no s'utilitza en el gràfic, fiquem pasa tot

update_EQ_predef fin_load_EQ d'1' filtre G_Biquad0,G f0_Biquad0,f0 Q_Biquad0,Q update_filtre d'2' filtre G_Biquad1,G f0_Biquad1,f0 Q_Biquad1,Q update_filtre d'3' filtre G_Biquad2,G f0_Biquad2,f0 Q_Biquad2,Q update_filtre d'4' filtre G_Biquad3,G f0_Biquad3,f0 Q_Biquad3,Q update_filtre d'5' filtre G_Biquad4,G f0_Biquad4,f0 Q_Biquad4,Q update_filtre d'6' filtre G_Biquad5,G f0_Biquad5,f0

121

Annex IV: Programa movff call fin_load_EQ return

Q_Biquad5,Q update_filtre

Save_EQ.asm save_EQ ;guardem V MOVLW MOVWF MOVLW MOVWF MOVF MOVWF BCF BCF BSF BCF MOVLW MOVWF MOVLW MOVWF BSF BTFSC BRA BSF BCF

d'0' EEADRH d'0' EEADR V,W EEDATA EECON1, EEPGD EECON1, CFGS EECON1, WREN INTCON, GIE 55h EECON2 0AAh EECON2 EECON1, WR EECON1, WR $-2 INTCON, GIE EECON1, WREN

;guardem T MOVLW MOVWF MOVLW MOVWF MOVF MOVWF BCF BCF BSF BCF MOVLW MOVWF MOVLW MOVWF BSF BTFSC BRA BSF BCF

d'0' EEADRH d'1' EEADR T,W EEDATA EECON1, EEPGD EECON1, CFGS EECON1, WREN INTCON, GIE 55h EECON2 0AAh EECON2 EECON1, WR EECON1, WR $-2 INTCON, GIE EECON1, WREN

;guardem B MOVLW MOVWF MOVLW MOVWF MOVF MOVWF BCF BCF BSF BCF MOVLW MOVWF MOVLW MOVWF BSF BTFSC BRA BSF BCF

d'0' EEADRH d'2' EEADR B,W EEDATA EECON1, EEPGD EECON1, CFGS EECON1, WREN INTCON, GIE 55h EECON2 0AAh EECON2 EECON1, WR EECON1, WR $-2 INTCON, GIE EECON1, WREN

; Data Memory Address to write ; Data Memory Value to write ; Point to DATA memory ; Access EEPROM ; Enable writes ; Disable Interrupts ; Write 55h ; Write 0AAh ; Set WR bit to begin write ; Wait for write to complete ; Enable Interrupts ; Disable writes on write complete (EEIF

; Data Memory Address to write ; Data Memory Value to write ; Point to DATA memory ; Access EEPROM ; Enable writes ; Disable Interrupts ; Write 55h ; Write 0AAh ; Set WR bit to begin write ; Wait for write to complete ; Enable Interrupts ; Disable writes on write complete (EEIF

; Data Memory Address to write ; Data Memory Value to write ; Point to DATA memory ; Access EEPROM ; Enable writes ; Disable Interrupts ; Write 55h ; Write 0AAh ; Set WR bit to begin write ; Wait for write to complete ; Enable Interrupts ; Disable writes on write complete (EEIF

122

Annex IV: Programa

;guardem G_Biquad0_g MOVLW d'0' MOVWF EEADRH MOVLW d'3' MOVWF EEADR MOVF G_Biquad0_g,W MOVWF EEDATA BCF EECON1, EEPGD BCF EECON1, CFGS BSF EECON1, WREN BCF INTCON, GIE MOVLW 55h MOVWF EECON2 MOVLW 0AAh MOVWF EECON2 BSF EECON1, WR BTFSC EECON1, WR BRA $-2 BSF INTCON, GIE BCF EECON1, WREN ;guardem G_Biquad1_g MOVLW d'0' MOVWF EEADRH MOVLW d'4' MOVWF EEADR MOVF G_Biquad1_g,W MOVWF EEDATA BCF EECON1, EEPGD BCF EECON1, CFGS BSF EECON1, WREN BCF INTCON, GIE MOVLW 55h MOVWF EECON2 MOVLW 0AAh MOVWF EECON2 BSF EECON1, WR BTFSC EECON1, WR BRA $-2 BSF INTCON, GIE BCF EECON1, WREN ;guardem G_Biquad2_g MOVLW d'0' MOVWF EEADRH MOVLW d'5' MOVWF EEADR MOVF G_Biquad2_g,W MOVWF EEDATA BCF EECON1, EEPGD BCF EECON1, CFGS BSF EECON1, WREN BCF INTCON, GIE MOVLW 55h MOVWF EECON2 MOVLW 0AAh MOVWF EECON2 BSF EECON1, WR BTFSC EECON1, WR BRA $-2 BSF INTCON, GIE BCF EECON1, WREN ;guardem G_Biquad3_g MOVLW d'0' MOVWF EEADRH MOVLW d'6' MOVWF EEADR MOVF G_Biquad3_g,W MOVWF EEDATA BCF EECON1, EEPGD BCF EECON1, CFGS BSF EECON1, WREN BCF INTCON, GIE MOVLW 55h

; Data Memory Address to write ; Data Memory Value to write ; Point to DATA memory ; Access EEPROM ; Enable writes ; Disable Interrupts ; Write 55h ; Write 0AAh ; Set WR bit to begin write ; Wait for write to complete ; Enable Interrupts ; Disable writes on write complete (EEIF

; Data Memory Address to write ; Data Memory Value to write ; Point to DATA memory ; Access EEPROM ; Enable writes ; Disable Interrupts ; Write 55h ; Write 0AAh ; Set WR bit to begin write ; Wait for write to complete ; Enable Interrupts ; Disable writes on write complete (EEIF

; Data Memory Address to write ; Data Memory Value to write ; Point to DATA memory ; Access EEPROM ; Enable writes ; Disable Interrupts ; Write 55h ; Write 0AAh ; Set WR bit to begin write ; Wait for write to complete ; Enable Interrupts ; Disable writes on write complete (EEIF

; Data Memory Address to write ; Data Memory Value to write ; Point to DATA memory ; Access EEPROM ; Enable writes ; Disable Interrupts

123

Annex IV: Programa MOVWF MOVLW MOVWF BSF BTFSC BRA BSF BCF

EECON2 0AAh EECON2 EECON1, WR EECON1, WR $-2 INTCON, GIE EECON1, WREN

;guardem G_Biquad4_g MOVLW d'0' MOVWF EEADRH MOVLW d'7' MOVWF EEADR MOVF G_Biquad4_g,W MOVWF EEDATA BCF EECON1, EEPGD BCF EECON1, CFGS BSF EECON1, WREN BCF INTCON, GIE MOVLW 55h MOVWF EECON2 MOVLW 0AAh MOVWF EECON2 BSF EECON1, WR BTFSC EECON1, WR BRA $-2 BSF INTCON, GIE BCF EECON1, WREN ;guardem G_Biquad0 MOVLW d'0' MOVWF EEADRH MOVLW d'8' MOVWF EEADR MOVF G_Biquad0,W MOVWF EEDATA BCF EECON1, EEPGD BCF EECON1, CFGS BSF EECON1, WREN BCF INTCON, GIE MOVLW 55h MOVWF EECON2 MOVLW 0AAh MOVWF EECON2 BSF EECON1, WR BTFSC EECON1, WR BRA $-2 BSF INTCON, GIE BCF EECON1, WREN ;guardem G_Biquad1 MOVLW d'0' MOVWF EEADRH MOVLW d'9' MOVWF EEADR MOVF G_Biquad1,W MOVWF EEDATA BCF EECON1, EEPGD BCF EECON1, CFGS BSF EECON1, WREN BCF INTCON, GIE MOVLW 55h MOVWF EECON2 MOVLW 0AAh MOVWF EECON2 BSF EECON1, WR BTFSC EECON1, WR BRA $-2 BSF INTCON, GIE BCF EECON1, WREN

; Write 55h ; Write 0AAh ; Set WR bit to begin write ; Wait for write to complete ; Enable Interrupts ; Disable writes on write complete (EEIF

; Data Memory Address to write ; Data Memory Value to write ; Point to DATA memory ; Access EEPROM ; Enable writes ; Disable Interrupts ; Write 55h ; Write 0AAh ; Set WR bit to begin write ; Wait for write to complete ; Enable Interrupts ; Disable writes on write complete (EEIF

; Data Memory Address to write ; Data Memory Value to write ; Point to DATA memory ; Access EEPROM ; Enable writes ; Disable Interrupts ; Write 55h ; Write 0AAh ; Set WR bit to begin write ; Wait for write to complete ; Enable Interrupts ; Disable writes on write complete (EEIF

; Data Memory Address to write ; Data Memory Value to write ; Point to DATA memory ; Access EEPROM ; Enable writes ; Disable Interrupts ; Write 55h ; Write 0AAh ; Set WR bit to begin write ; Wait for write to complete ; Enable Interrupts ; Disable writes on write complete (EEIF

;guardem G_Biquad2 MOVLW d'0' MOVWF EEADRH MOVLW d'10'

124

Annex IV: Programa MOVWF MOVF MOVWF BCF BCF BSF BCF MOVLW MOVWF MOVLW MOVWF BSF BTFSC BRA BSF BCF

EEADR G_Biquad2,W EEDATA EECON1, EEPGD EECON1, CFGS EECON1, WREN INTCON, GIE 55h EECON2 0AAh EECON2 EECON1, WR EECON1, WR $-2 INTCON, GIE EECON1, WREN

;guardem G_Biquad3 MOVLW d'0' MOVWF EEADRH MOVLW d'11' MOVWF EEADR MOVF G_Biquad3,W MOVWF EEDATA BCF EECON1, EEPGD BCF EECON1, CFGS BSF EECON1, WREN BCF INTCON, GIE MOVLW 55h MOVWF EECON2 MOVLW 0AAh MOVWF EECON2 BSF EECON1, WR BTFSC EECON1, WR BRA $-2 BSF INTCON, GIE BCF EECON1, WREN ;guardem G_Biquad4 MOVLW d'0' MOVWF EEADRH MOVLW d'12' MOVWF EEADR MOVF G_Biquad4,W MOVWF EEDATA BCF EECON1, EEPGD BCF EECON1, CFGS BSF EECON1, WREN BCF INTCON, GIE MOVLW 55h MOVWF EECON2 MOVLW 0AAh MOVWF EECON2 BSF EECON1, WR BTFSC EECON1, WR BRA $-2 BSF INTCON, GIE BCF EECON1, WREN ;guardem G_Biquad5 MOVLW d'0' MOVWF EEADRH MOVLW d'13' MOVWF EEADR MOVF G_Biquad5,W MOVWF EEDATA BCF EECON1, EEPGD BCF EECON1, CFGS BSF EECON1, WREN BCF INTCON, GIE MOVLW 55h MOVWF EECON2 MOVLW 0AAh MOVWF EECON2 BSF EECON1, WR BTFSC EECON1, WR

; Data Memory Address to write ; Data Memory Value to write ; Point to DATA memory ; Access EEPROM ; Enable writes ; Disable Interrupts ; Write 55h ; Write 0AAh ; Set WR bit to begin write ; Wait for write to complete ; Enable Interrupts ; Disable writes on write complete (EEIF

; Data Memory Address to write ; Data Memory Value to write ; Point to DATA memory ; Access EEPROM ; Enable writes ; Disable Interrupts ; Write 55h ; Write 0AAh ; Set WR bit to begin write ; Wait for write to complete ; Enable Interrupts ; Disable writes on write complete (EEIF

; Data Memory Address to write ; Data Memory Value to write ; Point to DATA memory ; Access EEPROM ; Enable writes ; Disable Interrupts ; Write 55h ; Write 0AAh ; Set WR bit to begin write ; Wait for write to complete ; Enable Interrupts ; Disable writes on write complete (EEIF

; Data Memory Address to write ; Data Memory Value to write ; Point to DATA memory ; Access EEPROM ; Enable writes ; Disable Interrupts ; Write 55h ; Write 0AAh ; Set WR bit to begin write ; Wait for write to complete

125

Annex IV: Programa BRA BSF BCF

$-2 INTCON, GIE EECON1, WREN

;guardem f0_Biquad0 MOVLW d'0' MOVWF EEADRH MOVLW d'14' MOVWF EEADR MOVF f0_Biquad0,W MOVWF EEDATA BCF EECON1, EEPGD BCF EECON1, CFGS BSF EECON1, WREN BCF INTCON, GIE MOVLW 55h MOVWF EECON2 MOVLW 0AAh MOVWF EECON2 BSF EECON1, WR BTFSC EECON1, WR BRA $-2 BSF INTCON, GIE BCF EECON1, WREN ;guardem f0_Biquad1 MOVLW d'0' MOVWF EEADRH MOVLW d'15' MOVWF EEADR MOVF f0_Biquad1,W MOVWF EEDATA BCF EECON1, EEPGD BCF EECON1, CFGS BSF EECON1, WREN BCF INTCON, GIE MOVLW 55h MOVWF EECON2 MOVLW 0AAh MOVWF EECON2 BSF EECON1, WR BTFSC EECON1, WR BRA $-2 BSF INTCON, GIE BCF EECON1, WREN ;guardem f0_Biquad2 MOVLW d'0' MOVWF EEADRH MOVLW d'16' MOVWF EEADR MOVF f0_Biquad2,W MOVWF EEDATA BCF EECON1, EEPGD BCF EECON1, CFGS BSF EECON1, WREN BCF INTCON, GIE MOVLW 55h MOVWF EECON2 MOVLW 0AAh MOVWF EECON2 BSF EECON1, WR BTFSC EECON1, WR BRA $-2 BSF INTCON, GIE BCF EECON1, WREN ;guardem f0_Biquad3 MOVLW d'0' MOVWF EEADRH MOVLW d'17' MOVWF EEADR MOVF f0_Biquad3,W MOVWF EEDATA BCF EECON1, EEPGD BCF EECON1, CFGS

; Enable Interrupts ; Disable writes on write complete (EEIF

; Data Memory Address to write ; Data Memory Value to write ; Point to DATA memory ; Access EEPROM ; Enable writes ; Disable Interrupts ; Write 55h ; Write 0AAh ; Set WR bit to begin write ; Wait for write to complete ; Enable Interrupts ; Disable writes on write complete (EEIF

; Data Memory Address to write ; Data Memory Value to write ; Point to DATA memory ; Access EEPROM ; Enable writes ; Disable Interrupts ; Write 55h ; Write 0AAh ; Set WR bit to begin write ; Wait for write to complete ; Enable Interrupts ; Disable writes on write complete (EEIF

; Data Memory Address to write ; Data Memory Value to write ; Point to DATA memory ; Access EEPROM ; Enable writes ; Disable Interrupts ; Write 55h ; Write 0AAh ; Set WR bit to begin write ; Wait for write to complete ; Enable Interrupts ; Disable writes on write complete (EEIF

; Data Memory Address to write ; Data Memory Value to write ; Point to DATA memory ; Access EEPROM

126

Annex IV: Programa BSF BCF MOVLW MOVWF MOVLW MOVWF BSF BTFSC BRA BSF BCF

EECON1, WREN INTCON, GIE 55h EECON2 0AAh EECON2 EECON1, WR EECON1, WR $-2 INTCON, GIE EECON1, WREN

;guardem f0_Biquad4 MOVLW d'0' MOVWF EEADRH MOVLW d'18' MOVWF EEADR MOVF f0_Biquad4,W MOVWF EEDATA BCF EECON1, EEPGD BCF EECON1, CFGS BSF EECON1, WREN BCF INTCON, GIE MOVLW 55h MOVWF EECON2 MOVLW 0AAh MOVWF EECON2 BSF EECON1, WR BTFSC EECON1, WR BRA $-2 BSF INTCON, GIE BCF EECON1, WREN ;guardem f0_Biquad5 MOVLW d'0' MOVWF EEADRH MOVLW d'19' MOVWF EEADR MOVF f0_Biquad5,W MOVWF EEDATA BCF EECON1, EEPGD BCF EECON1, CFGS BSF EECON1, WREN BCF INTCON, GIE MOVLW 55h MOVWF EECON2 MOVLW 0AAh MOVWF EECON2 BSF EECON1, WR BTFSC EECON1, WR BRA $-2 BSF INTCON, GIE BCF EECON1, WREN ;guardem Q_Biquad0 MOVLW d'0' MOVWF EEADRH MOVLW d'20' MOVWF EEADR MOVF Q_Biquad0,W MOVWF EEDATA BCF EECON1, EEPGD BCF EECON1, CFGS BSF EECON1, WREN BCF INTCON, GIE MOVLW 55h MOVWF EECON2 MOVLW 0AAh MOVWF EECON2 BSF EECON1, WR BTFSC EECON1, WR BRA $-2 BSF INTCON, GIE BCF EECON1, WREN

; Enable writes ; Disable Interrupts ; Write 55h ; Write 0AAh ; Set WR bit to begin write ; Wait for write to complete ; Enable Interrupts ; Disable writes on write complete (EEIF

; Data Memory Address to write ; Data Memory Value to write ; Point to DATA memory ; Access EEPROM ; Enable writes ; Disable Interrupts ; Write 55h ; Write 0AAh ; Set WR bit to begin write ; Wait for write to complete ; Enable Interrupts ; Disable writes on write complete (EEIF

; Data Memory Address to write ; Data Memory Value to write ; Point to DATA memory ; Access EEPROM ; Enable writes ; Disable Interrupts ; Write 55h ; Write 0AAh ; Set WR bit to begin write ; Wait for write to complete ; Enable Interrupts ; Disable writes on write complete (EEIF

; Data Memory Address to write ; Data Memory Value to write ; Point to DATA memory ; Access EEPROM ; Enable writes ; Disable Interrupts ; Write 55h ; Write 0AAh ; Set WR bit to begin write ; Wait for write to complete ; Enable Interrupts ; Disable writes on write complete (EEIF

;guardem Q_Biquad1

127

Annex IV: Programa MOVLW MOVWF MOVLW MOVWF MOVF MOVWF BCF BCF BSF BCF MOVLW MOVWF MOVLW MOVWF BSF BTFSC BRA BSF BCF

d'0' EEADRH d'21' EEADR Q_Biquad1,W EEDATA EECON1, EEPGD EECON1, CFGS EECON1, WREN INTCON, GIE 55h EECON2 0AAh EECON2 EECON1, WR EECON1, WR $-2 INTCON, GIE EECON1, WREN

;guardem Q_Biquad2 MOVLW d'0' MOVWF EEADRH MOVLW d'22' MOVWF EEADR MOVF Q_Biquad2,W MOVWF EEDATA BCF EECON1, EEPGD BCF EECON1, CFGS BSF EECON1, WREN BCF INTCON, GIE MOVLW 55h MOVWF EECON2 MOVLW 0AAh MOVWF EECON2 BSF EECON1, WR BTFSC EECON1, WR BRA $-2 BSF INTCON, GIE BCF EECON1, WREN ;guardem Q_Biquad3 MOVLW d'0' MOVWF EEADRH MOVLW d'23' MOVWF EEADR MOVF Q_Biquad3,W MOVWF EEDATA BCF EECON1, EEPGD BCF EECON1, CFGS BSF EECON1, WREN BCF INTCON, GIE MOVLW 55h MOVWF EECON2 MOVLW 0AAh MOVWF EECON2 BSF EECON1, WR BTFSC EECON1, WR BRA $-2 BSF INTCON, GIE BCF EECON1, WREN ;guardem Q_Biquad4 MOVLW d'0' MOVWF EEADRH MOVLW d'24' MOVWF EEADR MOVF Q_Biquad4,W MOVWF EEDATA BCF EECON1, EEPGD BCF EECON1, CFGS BSF EECON1, WREN BCF INTCON, GIE MOVLW 55h MOVWF EECON2 MOVLW 0AAh

; Data Memory Address to write ; Data Memory Value to write ; Point to DATA memory ; Access EEPROM ; Enable writes ; Disable Interrupts ; Write 55h ; Write 0AAh ; Set WR bit to begin write ; Wait for write to complete ; Enable Interrupts ; Disable writes on write complete (EEIF

; Data Memory Address to write ; Data Memory Value to write ; Point to DATA memory ; Access EEPROM ; Enable writes ; Disable Interrupts ; Write 55h ; Write 0AAh ; Set WR bit to begin write ; Wait for write to complete ; Enable Interrupts ; Disable writes on write complete (EEIF

; Data Memory Address to write ; Data Memory Value to write ; Point to DATA memory ; Access EEPROM ; Enable writes ; Disable Interrupts ; Write 55h ; Write 0AAh ; Set WR bit to begin write ; Wait for write to complete ; Enable Interrupts ; Disable writes on write complete (EEIF

; Data Memory Address to write ; Data Memory Value to write ; Point to DATA memory ; Access EEPROM ; Enable writes ; Disable Interrupts ; Write 55h

128

Annex IV: Programa MOVWF BSF BTFSC BRA BSF BCF

EECON2 EECON1, WR EECON1, WR $-2 INTCON, GIE EECON1, WREN

;guardem Q_Biquad5 MOVLW d'0' MOVWF EEADRH MOVLW d'25' MOVWF EEADR MOVF Q_Biquad5,W MOVWF EEDATA BCF EECON1, EEPGD BCF EECON1, CFGS BSF EECON1, WREN BCF INTCON, GIE MOVLW 55h MOVWF EECON2 MOVLW 0AAh MOVWF EECON2 BSF EECON1, WR BTFSC EECON1, WR BRA $-2 BSF INTCON, GIE BCF EECON1, WREN ;guardem Quin_EQ MOVLW MOVWF MOVLW MOVWF MOVF MOVWF BCF BCF BSF BCF MOVLW MOVWF MOVLW MOVWF BSF BTFSC BRA BSF BCF

d'0' EEADRH d'26' EEADR Quin_EQ,W EEDATA EECON1, EEPGD EECON1, CFGS EECON1, WREN INTCON, GIE 55h EECON2 0AAh EECON2 EECON1, WR EECON1, WR $-2 INTCON, GIE EECON1, WREN

;guardem Quin_EQ_pre MOVLW d'0' MOVWF EEADRH MOVLW d'27' MOVWF EEADR MOVF Quin_EQ_pre,W MOVWF EEDATA BCF EECON1, EEPGD BCF EECON1, CFGS BSF EECON1, WREN BCF INTCON, GIE MOVLW 55h MOVWF EECON2 MOVLW 0AAh MOVWF EECON2 BSF EECON1, WR BTFSC EECON1, WR BRA $-2 BSF INTCON, GIE BCF EECON1, WREN

; Write 0AAh ; Set WR bit to begin write ; Wait for write to complete ; Enable Interrupts ; Disable writes on write complete (EEIF

; Data Memory Address to write ; Data Memory Value to write ; Point to DATA memory ; Access EEPROM ; Enable writes ; Disable Interrupts ; Write 55h ; Write 0AAh ; Set WR bit to begin write ; Wait for write to complete ; Enable Interrupts ; Disable writes on write complete (EEIF

; Data Memory Address to write ; Data Memory Value to write ; Point to DATA memory ; Access EEPROM ; Enable writes ; Disable Interrupts ; Write 55h ; Write 0AAh ; Set WR bit to begin write ; Wait for write to complete ; Enable Interrupts ; Disable writes on write complete (EEIF

; Data Memory Address to write ; Data Memory Value to write ; Point to DATA memory ; Access EEPROM ; Enable writes ; Disable Interrupts ; Write 55h ; Write 0AAh ; Set WR bit to begin write ; Wait for write to complete ; Enable Interrupts ; Disable writes on write complete (EEIF

return

Send_TAS.asm

129

Annex IV: Programa send_MCR movlw slave_addres movwf TASADDR call WakeSlave call WrADDR movlw MCR movwf TASDATA call WrDATA ;el valor de MCR debe ser 01101010 ;C7=0->normal operation ;C6=1->SCLK = 64 × fs ;C5 C4=10-> Outpu I2S ;C3 C2=10-> Input I2S ;C1 C0=10->Serial port 20 bits movlw b'01101010' movwf TASDATA call WrDATA call Stop return

;TAS3001 I2C address ; gets slave attention ; sends TAS3001 address ; sends subadres to slave

; sends data to slave ; send stop bit

;el valor de mixer haurà de ser -12 dB perque en els filtres la ;amplificació màxima es de 12 dB i en el volum el valor màxim serà de 0 ;així aconseguim que encara que la entrada tingui el maxim recorregut ;possible no es saturi mai update_mixer movlw movwf call call movlw movwf call movlw movwf call movlw movwf call movlw movwf call call return

slave_addres TASADDR WakeSlave WrADDR Mixer_1 TASDATA WrDATA 0x04 TASDATA WrDATA 0x04 TASDATA WrDATA 0xDE TASDATA WrDATA Stop

update_filtre movlw CPFSGT bra movlw CPFSGT bra movlw CPFSGT bra movlw CPFSGT bra movlw CPFSGT bra bra

d'1' filtre update_biquad1 d'2' filtre update_biquad2 d'3' filtre update_biquad3 d'4' filtre update_biquad4 d'5' filtre update_biquad5 update_biquad6

update_biquad1 movlw movwf movlw movwf goto

L_Biquad0 TASDATA R_Biquad0 R_ADDR dos_octavas

update_biquad2 movlw movwf movlw movwf goto

L_Biquad1 TASDATA R_Biquad1 R_ADDR dos_octavas

;TAS3001 I2C address ; gets slave attention ; sends TAS3001 address ; sends subadres to slave ; sends data to slave ; sends data to slave ; sends data to slave ; send stop bit

130

Annex IV: Programa

update_biquad3 movlw movwf movlw movwf goto

L_Biquad2 TASDATA R_Biquad2 R_ADDR dos_octavas

update_biquad4 movlw movwf movlw movwf goto

L_Biquad3 TASDATA R_Biquad3 R_ADDR dos_octavas

update_biquad5 movlw movwf movlw movwf goto

L_Biquad4 TASDATA R_Biquad4 R_ADDR dos_octavas

update_biquad6 movlw movwf movlw movwf

L_Biquad5 TASDATA R_Biquad5 R_ADDR

dos_octavas movlw CPFSEQ bra movlw movwf movlw movwf bra

d'0' Q una_octava 0x00 TBLOW 0x00 TBHIGH update_biquad

una_octava movlw CPFSEQ bra movlw movwf movlw movwf bra

d'1' Q dos_tercios_octava 0xE0 TBLOW 0x2E TBHIGH update_biquad

dos_tercios_octava movlw CPFSEQ bra movlw movwf movlw movwf bra

d'2' Q un_tercio_octava 0xC0 TBLOW 0x5D TBHIGH update_biquad

un_tercio_octava movlw movwf movlw movwf

0xA0 TBLOW 0x8C TBHIGH

update_biquad movlw movwf movlw movwf movlw movwf movlw movwf movlw mulwf

UPPER EQ_parametric TBLPTRU HIGH EQ_parametric TBLPTRH LOW EQ_parametric TBLPTRL d'8' ptr_c d'200' f0

;16*25=400

131

Annex IV: Programa movf PRODL,W addwf TBLOW,F movf PRODH,W addwfc TBHIGH,F movf PRODL,W addwf TBLOW,F movf PRODH,W addwfc TBHIGH,F movlw d'16' mulwf G movf PRODL,W addwf TBLOW,F movf PRODH,W addwfc TBHIGH,F movf TBLOW,W addwf TBLPTRL,F movff TBLPTRL,OLDTBLL movf TBHIGH,W addwfc TBLPTRH,F movff TBLPTRH,OLDTBLH clrf WREG addwfc TBLPTRU,F movff TBLPTRU,OLDTBLU movlw slave_addres ;TAS3001 I2C address movwf TASADDR call WakeSlave ; gets slave attention call WrADDR ; sends TAS3001 address ;de update_biquadX ya tenemos la subdireccion del biquad en TASDATA call WrDATA ; sends subadres to slave stan_next_byte_L tblrd movff tblrd movff dcfsnz bra call movff call bra

*+ TABLAT,NEXTDATA *+ TABLAT,TASDATA ptr_c,F stan_last_byte_L WrDATA NEXTDATA,TASDATA WrDATA stan_next_byte_L

stan_last_byte_L call call movlw movwf movff movff movff movff call call call

WrDATA Stop d'8' ptr_c R_ADDR,TASDATA OLDTBLL,TBLPTRL OLDTBLH,TBLPTRH OLDTBLU,TBLPTRU WakeSlave WrADDR WrDATA

stan_next_byte_R tblrd movff tblrd movff dcfsnz bra call movff call bra

*+ TABLAT,NEXTDATA *+ TABLAT,TASDATA ptr_c,F stan_last_byte_R WrDATA NEXTDATA,TASDATA WrDATA stan_next_byte_R

stan_last_byte_R call call return

WrDATA Stop

;move pointer to next byte ; sends data to slave ; sends data to slave

; sends data to slave ; send stop bit

; gets slave attention ; sends TAS3001 address ; sends subadres to slave

;move pointer to next byte ; sends data to slave ; sends data to slave

; sends data to slave ; send stop bit

update_EQ_graf movlw d'1' CPFSGT filtre bra update_biquad1_g

132

Annex IV: Programa movlw CPFSGT bra movlw CPFSGT bra movlw CPFSGT bra bra

d'2' filtre update_biquad2_g d'3' filtre update_biquad3_g d'4' filtre update_biquad4_g update_biquad5_g

update_biquad1_g movlw movwf movlw movwf movlw movwf movlw movwf movlw movwf bra

L_Biquad0 TASDATA R_Biquad0 R_ADDR UPPER EQ_biquad_1 TBLPTRU HIGH EQ_biquad_1 TBLPTRH LOW EQ_biquad_1 TBLPTRL update_biquad_g

update_biquad2_g movlw movwf movlw movwf movlw movwf movlw movwf movlw movwf bra

UPPER EQ_biquad_2 TBLPTRU HIGH EQ_biquad_2 TBLPTRH LOW EQ_biquad_2 TBLPTRL L_Biquad1 TASDATA R_Biquad1 R_ADDR update_biquad_g

update_biquad3_g movlw movwf movlw movwf movlw movwf movlw movwf movlw movwf bra

UPPER EQ_biquad_3 TBLPTRU HIGH EQ_biquad_3 TBLPTRH LOW EQ_biquad_3 TBLPTRL L_Biquad2 TASDATA R_Biquad2 R_ADDR update_biquad_g

update_biquad4_g movlw movwf movlw movwf movlw movwf movlw movwf movlw movwf bra

UPPER EQ_biquad_4 TBLPTRU HIGH EQ_biquad_4 TBLPTRH LOW EQ_biquad_4 TBLPTRL L_Biquad3 TASDATA R_Biquad3 R_ADDR update_biquad_g

update_biquad5_g movlw movwf movlw movwf movlw movwf movlw movwf movlw movwf bra

UPPER EQ_biquad_5 TBLPTRU HIGH EQ_biquad_5 TBLPTRH LOW EQ_biquad_5 TBLPTRL L_Biquad4 TASDATA R_Biquad4 R_ADDR update_biquad_g

133

Annex IV: Programa update_biquad_g movlw d'8' movwf ptr_c movf G,W mullw d'16' movf PRODL,W addwf TBLPTRL,F movff TBLPTRL,OLDTBLL movf PRODH,W addwfc TBLPTRH,F movff TBLPTRH,OLDTBLH clrf WREG addwfc TBLPTRU,F movff TBLPTRU,OLDTBLU movlw slave_addres ;TAS3001 I2C address movwf TASADDR call WakeSlave ; gets slave attention call WrADDR ; sends TAS3001 address ;de update_biquadX ya tenemos la subdireccion del biquad en TASDATA call WrDATA ; sends subadres to slave stan_next_byte_L_g tblrd movff tblrd movff dcfsnz bra call movff call bra

*+ TABLAT,NEXTDATA *+ TABLAT,TASDATA ptr_c,F stan_last_byte_L_g WrDATA NEXTDATA,TASDATA WrDATA stan_next_byte_L_g

stan_last_byte_L_g call call movlw movwf movff movff movff movff call call call

WrDATA Stop d'8' ptr_c R_ADDR,TASDATA OLDTBLL,TBLPTRL OLDTBLH,TBLPTRH OLDTBLU,TBLPTRU WakeSlave WrADDR WrDATA

stan_next_byte_R_g tblrd movff tblrd movff dcfsnz bra call movff call bra

*+ TABLAT,NEXTDATA *+ TABLAT,TASDATA ptr_c,F stan_last_byte_R_g WrDATA NEXTDATA,TASDATA WrDATA stan_next_byte_R_g

stan_last_byte_R_g call WrDATA call Stop return update_EQ_predef movlw cpfslt bra movlw movwf movlw movwf movlw movwf movlw movwf movlw

;move pointer to next byte ; sends data to slave ; sends data to slave

; sends data to slave ; send stop bit

; gets slave attention ; sends TAS3001 address ; sends subadres to slave

;move pointer to next byte ; sends data to slave ; sends data to slave

; sends data to slave ; send stop bit

d'5' Quin_EQ_pre EQ_pre_blank UPPER EQ_predefinit TBLPTRU HIGH EQ_predefinit TBLPTRH LOW EQ_predefinit TBLPTRL d'0' k L_Biquad0

134

Annex IV: Programa movwf movlw movwf movf mullw movf addwf movf addwfc clrf addwfc

TASDATA R_Biquad0 R_ADDR Quin_EQ_pre,W d'96' PRODL,W TBLPTRL,F PRODH,W TBLPTRH,F WREG TBLPTRU,F

transmetre_predef movlw movwf movff movff movff movlw movwf call call call

d'8' ptr_c TBLPTRL,OLDTBLL TBLPTRH,OLDTBLH TBLPTRU,OLDTBLU slave_addres TASADDR WakeSlave WrADDR WrDATA

stan_next_byte_L_p tblrd movff tblrd movff dcfsnz bra call movff call bra

*+ TABLAT,NEXTDATA *+ TABLAT,TASDATA ptr_c,F stan_last_byte_L_p WrDATA NEXTDATA,TASDATA WrDATA stan_next_byte_L_p

stan_last_byte_L_p call call movlw movwf movff movff movff movff call call call

WrDATA Stop d'8' ptr_c R_ADDR,TASDATA OLDTBLL,TBLPTRL OLDTBLH,TBLPTRH OLDTBLU,TBLPTRU WakeSlave WrADDR WrDATA

stan_next_byte_R_p tblrd movff tblrd movff dcfsnz bra call movff call bra

*+ TABLAT,NEXTDATA *+ TABLAT,TASDATA ptr_c,F stan_last_byte_R_p WrDATA NEXTDATA,TASDATA WrDATA stan_next_byte_R_p

stan_last_byte_R_p call call incf movlw cpfseq bra movlw movwf movlw movwf bra

WrDATA Stop k,1 d'1' k biquad_predef_2 L_Biquad1 TASDATA R_Biquad1 R_ADDR transmetre_predef

biquad_predef_2 movlw

d'2'

;TAS3001 I2C address ; gets slave attention ; sends TAS3001 address ; sends subadres to slave

;move pointer to next byte ; sends data to slave ; sends data to slave

; sends data to slave ; send stop bit

; gets slave attention ; sends TAS3001 address ; sends subadres to slave

;move pointer to next byte ; sends data to slave ; sends data to slave

; sends data to slave ; send stop bit

135

Annex IV: Programa cpfseq bra movlw movwf movlw movwf bra

k biquad_predef_3 L_Biquad2 TASDATA R_Biquad2 R_ADDR transmetre_predef

biquad_predef_3 movlw cpfseq bra movlw movwf movlw movwf bra

d'3' k biquad_predef_4 L_Biquad3 TASDATA R_Biquad3 R_ADDR transmetre_predef

biquad_predef_4 movlw cpfseq bra movlw movwf movlw movwf bra

d'4' k biquad_predef_5 L_Biquad4 TASDATA R_Biquad4 R_ADDR transmetre_predef

biquad_predef_5 movlw cpfseq bra movlw movwf movlw movwf bra

d'5' k fin_biquad_predef L_Biquad5 TASDATA R_Biquad5 R_ADDR transmetre_predef

EQ_pre_blank bsf PORTA,3 movlw d'10' call delay_ms bcf PORTA,3 movlw d'10' call delay_ms bsf PORTA,3 movlw d'10' call delay_ms ;Modificar registro MSR para normal mode call send_MCR ;TAS3001 normal mode call update_mixer call update_volum

;hacer reset al TAS y al codec

;esperar 5ms para TAS listo

fin_biquad_predef return update_volum movlw movwf movlw movwf movlw movwf movlw movwf movf mullw movf addwf movff movf addwfc movff clrf addwfc

Vol TASDATA UPPER Volum TBLPTRU HIGH Volum TBLPTRH LOW Volum TBLPTRL V,W d'4' PRODL,W TBLPTRL,F TBLPTRL,OLDTBLL PRODH,W TBLPTRH,F TBLPTRH,OLDTBLH WREG TBLPTRU,F

136

Annex IV: Programa movff TBLPTRU,OLDTBLU movlw slave_addres ;TAS3001 I2C address movwf TASADDR call WakeSlave ; gets slave attention call WrADDR ; sends TAS3001 address ;de update_biquadX ya tenemos la subdireccion del biquad en TASDATA call WrDATA ; sends subadres to slave tblrd *+ movff TABLAT,NEXTDATA tblrd *+ movff TABLAT,TASDATA call WrDATA ; sends data to slave movff NEXTDATA,TASDATA call WrDATA ; sends data to slave tblrd *+ movff TABLAT,NEXTDATA tblrd *+ movff TABLAT,TASDATA call WrDATA ; sends data to slave movff OLDTBLL,TBLPTRL movff OLDTBLH,TBLPTRH movff OLDTBLU,TBLPTRU tblrd *+ movff TABLAT,NEXTDATA tblrd *+ movff TABLAT,TASDATA call WrDATA ; sends data to slave movff NEXTDATA,TASDATA call WrDATA ; sends data to slave tblrd *+ movff TABLAT,NEXTDATA tblrd *+ movff TABLAT,TASDATA call WrDATA ; sends data to slave call Stop ; send stop bit return

LCD_tab.asm stan_table ; ; data data data data data data data data data data data data data data data data data data data data data data data data data data data data data data data data

;table for standard code "XXXXXXXXXXXXXXXX" ptr: " f=25 Hz " ;0 " f=31.5 Hz " ;16*1 " f=40 Hz " ;16*2 " f=50 Hz " ; " f=63 Hz " ;16*4 " f=80 Hz " ; " f=100 Hz " ; " f=125 Hz " ; " f=160 Hz " ; " f=200 Hz " ; " f=250 Hz " ;16*10 " f=315 Hz " ; " f=400 Hz " ; " f=500 Hz " ; " f=630 Hz " ; " f=800 Hz " ; " f=1 kHz " ;16*16 " f=1.25 kHz " ; " f=1.6 kHz " ; " f=2 kHz " ; " f=2.5 kHz " ; " f=3.15 kHz " ; " f=4 kHz " ;16*22 " f=5 kHz " ; " f=6.3 kHz " ; " f=8 kHz " ; " f=10 kHz " ; " f=12.5 kHz " ; " f=16 kHz " ;16*28 " f=20 kHz " ;16*29 " Grafic " ;30 " Predefinit " ;31

137

Annex IV: Programa data data data data data data data data data data data data data data data data data data data data data data data data data

" " " " " Exit " " Menu " " EQ. Grafic " " PFC " " Equalitzador " " Parametric " " Filtre 1 " " Filtre 2 " " Filtre 3 " " Filtre 4 " " Filtre 5 " " Filtre 6 " " EQ. Parametric " " BW=2 octavas " " BW=1 octava " " BW=2/3 octava " " BW=1/3 octava " " ROCK " " JAZZ " " CLASICA " " DANCE " " POP " " UNIFORME "

;32 ;33 ;34 ;35 ;36 ;37 ;38 ;39 ;40 ;41 ;42 ;43 ;44 ;45 ;46 ;47 ;48 ;49 ;50 ;51 ;52 ;53 ;54 ;55 ;56

Volum_tab.asm Volum DATA 0x0000, 0x0000 ;Mute DATA 0x0000, 0x1500 ;-70.0 DATA 0x0000, 0x1C00 DATA 0x0000, 0x2500 ;-65.0 DATA 0x0000, 0x3100 DATA 0x0000, 0x4200 ;-60 DATA 0x0000, 0x5700 DATA 0x0000, 0x7500 ;-55 DATA 0x0000, 0x9B00 DATA 0x0000, 0xCF00 ;-50 DATA 0x0001, 0x1400 DATA 0x0001, 0x7100 ;-45 DATA 0x0001, 0xEB00 DATA 0x0002, 0x8F00 ;-40 DATA 0x0003, 0x6A00 DATA 0x0004, 0x8D00 ;-35 DATA 0x0006, 0x1200 DATA 0x0008, 0x1800 ;-30 DATA 0x000A, 0xCC00 DATA 0x000E, 0x6500 ;-25 DATA 0x0013, 0x3300 DATA 0x0019, 0x9A00 ;-20 DATA 0x0022, 0x2300 DATA 0x002D, 0x8600 ;-15 DATA 0x003C, 0xB500 DATA 0x0050, 0xF400 ;-10 DATA 0x006B, 0xF400 DATA 0x008F, 0xF600 ;-5 DATA 0x00BF, 0xF900 DATA 0x0100, 0x0000 ;0 DATA 0x0155, 0x6200 DATA 0x01FE, 0xCA00

Subaddres.def #define #define #define #define #define #define #define

MCR Vol Treb Bass Mixer_1 Mixer_2 L_Biquad0

01h 04h 05h 06h 07h 08h 0Ah

138

Annex IV: Programa #define #define #define #define #define #define #define #define #define #define #define

L_Biquad1 L_Biquad2 L_Biquad3 L_Biquad4 L_Biquad5 R_Biquad0 R_Biquad1 R_Biquad2 R_Biquad3 R_Biquad4 R_Biquad5

0Bh 0Ch 0Dh 0Eh 0Fh 13h 14h 15h 16h 17h 18h

139

Related Documents

Pfc
November 2019 13
Pfc
August 2019 24
Pfc Converter
April 2020 16
M-pfc
May 2020 12
Pfc R01
October 2019 20
Pfc R02
October 2019 11