# Duda con frecuencímetro (con 16F84) y prescaler (U664) hasta 1,3 GHz



## trifoncar (Sep 12, 2013)

Hola foreros!
   Tengo una duda en el montaje de un frecuencímetro (de Phil Rice con 16F84A) 
https://sites.google.com/site/vk3bhr/home/fm2 y el prescaler que él indica, el U664BS según el esquema de Miroslav Sinko https://sites.google.com/site/vk3bhr/home/fm2/prescale  con el fin de obtener un frecuencímetro que llegue hasta los 1,3 MHz.

Es un proyecto que dejé "congelado" hace un tiempo y que ahora retomo.

He efectuado el montaje de ambos y he logrado mediciones de lo más erróneas y variadas para un cristal oscilador de 100 MHz. He introducido cambios hasta dar con uno que me satisface, pero no entiendo la razón.
He eliminado R3, D1 y D2 del circuito del prescaler y, para el cristal oscilador de 100,00 MHz obtengo una lectura de 99,93xxxx MHz, que considero razonablemente precisa.

¿Alguien podría decirme a que puede ser debido? 

Gracias

P.D.: He querido adjuntar fotos pero me pide id y pw una y otra vez (??)

​


----------



## Fogonazo (Sep 12, 2013)

Los diodos que eliminaste son la protección del IC pre-scaler, al eliminarlos dejaste sin protección el IC


*Edit*
Los diodos deben ser del tipo Schottky, ¿ Que es lo que colocaste ?


----------



## miguelus (Sep 12, 2013)

trifoncar dijo:


> Hola foreros!
> Tengo una duda en el montaje de un frecuencímetro (de Phil Rice con 16F84A)
> https://sites.google.com/site/vk3bhr/home/fm2 y el prescaler que él indica, el U664BS según el esquema de Miroslav Sinko https://sites.google.com/site/vk3bhr/home/fm2/prescale  con el fin de obtener un frecuencímetro que llegue hasta los 1,3 MHz.
> 
> ...



Buenos días.

Vallamos por partes Primero. 

El Frecuencímetro sin Prescaler ¿Te funciona bien?

D1, D2 tienen como misión proteger al Divisor ante señales de mucho nivel, no los quites.

R1, R2, R3 es un Atenuador de entrada el nivel de atenuación es  de ~ -3dB

Te aconsejo que dejes el Atenuador y los dos Diodos.

Este tipo de divisores tienen la fea costumbre de ponerse a oscilar si no hay ninguna señal en su entrada, esto no supone mayor problema ya que cuando hay señal suficiente, el Divisor funcionará sin problemas.

Te encuenta que la impedancia de entrada al circuito del Prescaler es de 50Ω, si lo conectas directamente a un circuito Oscilador, es muy probable que este deje de oscilar o lo haga de una manera errática, lo correcto es medir por medio de una pequeña capacidad ~ 1pF - 10pf , todo dependerá de la frecuencia y de los niveles que quieras medir.

En ocasiones es aconsejable acoplarse al circito a medir por medio de una pequeña sonda realizada con un cable coaxial terminado en un pequeña Bobina de una espira, esa espira se acerca al circuito a medir.

Si deseas alguna aclaración solo tienes que preguntar.

Sal U2


----------



## Daniel Lopes (Sep 12, 2013)

Hola a todos, !saludos cordeales!, yo personalmiente prefiro un oscilador a cristal entre 4 a 10 Mhz , donde els oscilan en modo fudamental y osciladores con frequenzia arriba 25Mhz operan en modo overton o sea modo harmonico y la estabilidad y precisiõn ja no es mas tan buena. Otro punto mui inportante que no puede sener orbidado es la qualidad de la base de tienpo enpleada en el frequencimetro , caso sea pobre tenemos medidas mediocres.Lo mas recomendado es una base de tienpo en torno de 10Mhz armado en una camara Termica (horno termico ) para manter la frequencia lo mas estable que possible .Para una buena calibraciõn podemos hacer uso de un padrõn enbasado en un GPS que garantiza una precisiõn mui buena a un costo razonable.
!Fuerte abrazo!
Att.
Daniel lopes


----------



## trifoncar (Sep 12, 2013)

Fogonazo comentó:


> Los diodos deben ser del tipo Schottky, ¿ Que es lo que colocaste ?



He colocado dos 1n4148

miguelus comentó:


> El Frecuencímetro sin Prescaler ¿Te funciona bien?



desde 4 a 18,43 MHz funciona correctamente (mínimas desviaciones).
Incluso con 48 y 100 MHz, pero supongo que obtengo los armónicos, es decir, para 48 obtengo 16, y para 100 obtengo cerca de 20 MHz.

miguelus comentó:


> Ten en cuenta que la impedancia de entrada al circuito del Prescaler es de 50Ω, si lo conectas directamente a un circuito Oscilador, es muy probable que este deje de oscilar o lo haga de una manera errática, lo correcto es medir por medio de una pequeña capacidad ~ 1pF - 10pf , todo dependerá de la frecuencia y de los niveles que quieras medir.



En el esquema hay un condensador de 1 nF a la entrada de la patilla 2. ¿No es suficiente?

Gracias por los comentarios.


----------



## miguelus (Sep 12, 2013)

Buenas tardes.

Los Diodos 1N4148 no sirven para este propósito, ten en cuenta que pretendes realizar medidas hasta 1,3Ghz.

Busca Diodos tipo schottky p.e. BAT42, BAT48... son muy varatos y en Madrid los tienen en todos los lados (menos en Carrefour y en algún otro sitio)

El Condensador de 1nF que hay en la entrada, para frecuencias altas es prácticamente un corto... XC = 1/ωC  lo que significa que a 100Mhz tiene 1,6Ω y a  1Ghz tiene 0,16Ω.

La razón medir por medio de un condensador de muy bajo valor es influir lo mínimo posible en el circuito en el que vamos a hacer la medida.

El Condensador de 1nF tiene como misión bloquear la componente DC que pudiéra haber  en el circuito que estamos midiendo, así evitamos averiar la entrada del Prescaler.

Un parámetro a tener en cuenta de este Prescaler es que su rango mínimo de funcionamiento es de ~30Mhz.

Hace tiempo compré varios U664B  y algunos llegarón a dividir hasta con 26Mhz.

Hay que tener en cuenta que este Divisor, U664B  divide por 64, si introduces 1,3Ghz en su salida habrá 20,3125 Mhz  por lo que el Frecuencímetro tendrá que ser capaz de medirla ya que, según dice su autor, puede llegar hasta 60Mhz.

Sal U2


----------



## Fogonazo (Sep 12, 2013)

trifoncar dijo:


> . . . .He colocado dos 1n4148


Como para 1.3GHz  


> . . . En el esquema hay un condensador de 1 nF a la entrada de la patilla 2. ¿No es suficiente?


Yo creo que esta perfecto.
Miguelus te habla de otro capacitor en serie con la señal que limite la carga sobre el oscilador que armaste. 

No leí las características del IC Prescaler, pero esa configuración de protección recorta la señal a uno 700mV, tal vez el prescaler necesite una mayor señal de entrada


----------



## miguelus (Sep 12, 2013)

Fogonazo dijo:


> Como para 1.3GHz
> 
> Yo creo que esta perfecto.
> Miguelus te habla de otro capacitor en serie con la señal que limite la carga sobre el oscilador que armaste.
> ...



Buenas tardes.

Con esos Diodos, la señal se recorta a ~200mV. Ese Divisor (como la mayoría de los Divisores de este tipo) con menos de 100mV, incluso en 1,3Ghz, ya tiene suficiente nivel para dividir.

Sal U2


----------



## trifoncar (Sep 12, 2013)

Acabo de seguir vuestros consejos (Miguelus y Fogonazo):
  - cambiando los 1N448 por 1N5819
  - poniendo un condensador de muy bajo valor en serie antes de la entrada al prescaler

 y he obtenido los siguientes resultados para un circuito oscilador compacto de 100,00 MHz:

0 (abierto)300,018304 MHz    (sin conectar al prescaler)
1,0 pF	300,01856 MHz
3,3 pF	300,01900 MHz
6   pF	205,70000 MHz      (en paralelo 2,7 y 3,3)
10 pF	100,00670 MHz
15 pF	142,00000 MHz  (he probado con dos diferentes y me ha dado lo mismo (??))
22 pF	100,00600 MHz
27 pF	100,00600 MHz
47 pF	100,00600 MHz

Creo que, salvo el tema puntual de los 15 pF, a partir de 10pF obtengo medidas correctas de la frecuencia.

¡¡Muchas gracias de nuevo, amigos!!


----------



## Fogonazo (Sep 12, 2013)

A esas frecuencias se hace crítico el diseño del PCB, distribucion y tipo de componentes, material del sustrato y muchos Etc´s mas.
¿ Como es el diseño ?


----------



## tiago (Sep 12, 2013)

Por aquí montamos algunos pequeños aparatos, entre ellos el frecuencimetro. Tengo que decir que funciona muy bien para hacer mediciones simples.

*Problema con LC Meter*

Saludos.


----------



## trifoncar (Sep 12, 2013)

> Fogonazo dijo:
> A esas frecuencias se hace crítico el diseño del PCB, distribucion y tipo de componentes, material del sustrato y muchos Etc´s mas.
> ¿ Como es el diseño ?



Lo tengo todo en un protoboard. Aún no me había preocupado por el diseño debido a que no conseguía encontrar una solución a la estabilidad de la medida (hasta hoy gracias a vosotros).
Ahora me quedaría saber qué valores debe de tener el condensador en serie (que me habéis indicado) en función de la frecuencia a medir. Ya sé que para 100 MHz me vn bien desde 10 a 47 pF, pero desconozco los valores necesarios para frecuencias mayores (hasta 1,3 GHz). Una vez conocido ese tema, me volcaré con el diseño, por lo que intentaré informarme y os pediré ayuda en ese campo.

Tiago dijo: 


> Por aquí montamos algunos pequeños aparatos, entre ellos el frecuencimetro. Tengo que decir que funciona muy bien para hacer mediciones simples.
> 
> Problema con LC Meter


hace un tiempo participé en ese hilo, haciendo muchas preguntas y aportando nada más que un granito de arena (el datasheet del U664). Me ayudasteis mucho. Gracias de nuevo.


----------



## Fogonazo (Sep 12, 2013)

Con una protoboar *! Nunca ¡* vas a conseguir una medición fiable, estable y repetible en altas frecuencias.

A mas de 1MHz las protoboar *NO sirven* o dan resultados inciertos.


----------



## trifoncar (Sep 12, 2013)

Fogonazo dijo,


> Con una protoboar ! Nunca ¡ vas a conseguir una medición fiable, estable y repetible en altas frecuencias.
> 
> A mas de 1MHz las protoboar NO sirven o dan resultados inciertos.



 Lo sé desde hace tiempo, pero siempre pruebo los montajes en protoboard antes de hacerlo en pcb. Soy un simple aficionado a la electrónica -con muy pocos conocimientos sobre el tema- pero me gusta experimentar y montar aparatos. No tengo muchos medios técnicos, ni un taller donde llevarlos a cabo. Para mi montar un protoboard antes de decidirme a hacer la placa es una cuestión de logística (tengo que atacar las placas en la cocina de mi casa). ¡Ojalá tuviese una habitación taller para ello!  

Ahora las pruebas las estoy haciendo con 100 MHz porque es el único oscilador que tengo de más de 50 MHz (no tengo transmisores o Walkie Talkie). 

De cualquier forma .... los datos que he obtenido y he mostrado en el comentario #9 (aunque estén redondeados algunos al tercer decimal) parecen relativamente fiables a partir de los 10pF ..

¿Hay alguna fórmula para calcular la capacidad del condensador en serie en función de la frecuencia a medir?

Gracias por el comentario


----------



## Daniel Lopes (Sep 12, 2013)

Hola a todos, yo de plenissimo acuerdo con Don Fogonaso lo Protoboard no sirve para experimentos en RF, sendo la montagen mas apropriada y conocida como : "Marrathan" la qual es mui discutida por aca .
Lo protoboard no contiene plano de tierra o sea un bueno retorno a massa indispesable para un correcto funcionamiento de circuitos de RF y las capacitancias parasitas entre los contactos son demasiados para un bueno desenpeño de circuitos RF.
Portanto caro Trifoncar orbide lo uso de protoboard en montagens de alta frequencia (RF).
!Fuerte abrazo!
Att.
Daniel Lopes.


----------



## Fogonazo (Sep 12, 2013)

Ver el archivo adjunto 5415
​


----------



## trifoncar (Sep 12, 2013)

Tomo nota de que lo que me parece ver para cuando intente diseñar el pcb:
- un gran plano de masa dominando la mayor parte posible de la placa
- minimizar hasta límites increíbles las patillas de los componentes
- minimizar al máximo la distancia entre los componentes
- utilizar componentes smd (si se puede ?)
Supongo que es el mensaje de la foto (prefiero no pensar en los calificativos personales inherentes a la misma )

Muchas gracias Fogonazo.


----------



## Fogonazo (Sep 12, 2013)

trifoncar dijo:


> Tomo nota de que lo que me parece ver para cuando intente diseñar el pcb:
> - un gran plano de masa dominando la mayor parte posible de la placa
> - minimizar hasta límites increíbles las patillas de los componentes
> - minimizar al máximo la distancia entre los componente
> ...



La foto posee un link


----------



## trifoncar (Sep 12, 2013)

Gracias Fogonazo, no me había percatado de ello  pss:.   Ya tengo "deberes" para los próximos días.

¿Alguna contestación para aquello del valor ideal del "condensador serie" en función de la frecuencia a medir?

Un saludo


----------



## miguelus (Sep 12, 2013)

Buenas noches.

Voy a intentar contestar a tu pregunta...

En relación al valor del Condensador, en principio no hay una forma "Científica" de calcular el valor del Condensador ya que depende de muchos factores.

En el Post#6 te decía...

_Te encuenta que la impedancia de entrada al circuito del Prescaler es de 50Ω, si lo conectas directamente a un circuito Oscilador, es muy probable que este deje de oscilar o lo haga de una manera errática, lo correcto es medir por medio de una pequeña capacidad ~ 1pF - 10pf , todo dependerá de la frecuencia y de los niveles que quieras medir._

Lo que se pretende en este caso, como siempre que se hace una medida, es que el medidor influya lo menos posible en el circuito a medir.
Lo ideal es que el medidor tenga una impedancia de entrada muy alta, cuanto más alta mejor, de esta forma evítamos "molestar" al circuito que genera una señal.

Esto está muy bien para tensiones continuas o alternas de baja frecuencia, pero a medida que vamos subiendo de frecuencia este requisito se hace muy difícil de obtener.

Si te molestas en mirar las características de Frecuencímetros Comerciales, verás que normalmente tienen dos rangos de medida.

El primero es de frecuencias hasta 50Mhz o 100Mhz con una impedancia de entrada de 1MΩ
El segundo rango de medida es para frecuencias superiores, esta entrada siempre es de 50Ω

Pero utilizar 50Ω como impedancia de entrada acarrea los problemas que he comentado al principio.

El truco es aumentar virtualmente la impedancia de entrada cuando estamos trabajando con la entrada de 50Ω, esto lo podemos lograr con un Condensador de poca capacidad, recuerda XC = 1/ωC pero esto tiene el inconveniente de que el valor de C es dependiente de la frecuencia, hay que tratar de poner el valor más bajo con el que el Frecuencímetro funcione.

En tu caso, medir sobre un módulo Oscilador a cuarzo no tendría que influir  el hecho de medir conectando directamente la entrada del Frecuencímetro con la salida del Oscilador.

En el mercado existen sondas de RF de alta impedancia pero su precio, lógicamente, es muy elevado.

Espero haber aclarado tus dudas (o seguramente he creado alguna más  )

Sal U2


----------



## trifoncar (Sep 12, 2013)

Miguelus, creo que capto lo que has explicado.

Muchas gracias por las aclaraciones. Voy a estudiarme el proyecto "Manhatan" de Fogonazo y después, con lo que me habeis comentado, me pondre a buscar un diseño o diseñar una pcb.

¡Gracias de nuevo!


----------



## Daniel Lopes (Sep 13, 2013)

Hola a todos, quanto a la sonda de alta impedancia acalarada por Don Miguelus yo me recuerdo tener mirado un proyecto de una donde el es conposta de circuito activo con transistores tipo MosFet dual gate y transistores npn de alta frequencia , portanto dame un poco de tienpo para localizar por aca y subo con mucho gusto.
!fuerte abrazo!
Att.
Daniel Lopes.


----------



## trifoncar (Sep 14, 2013)

Espero con muchas ganas poder verlo, Daniel.

He estado ordenando y sintetizando mis ideas hasta conseguir un bloque de diagramas del montaje que pretendo hacer y os lo dejo aquí por si os apetece comentarme algo.

También me he estado sumergiendo en el mundo del sistema Manhattan de montaje (efectivamente ... todo un mundo) y tendré que utilizarlo (como me indicaba Fogonazo) en el montaje del prescaler.

El esquema del Frecuencímetro es el de la página de Phil Rice (comentado en el post #1), el esquema del Prescaler es el también comentado de Miroslav Sinko (también comentado en el post #1), y el esquema del oscilador a cristal lo encontré en 

http://www.creatronica.com.ar/osciladores_transistores.htm

pero está en muchos otros sitios. También me he basado en algunas de las buenas ideas de Asterión al que , desde aquí, quiero felicitar, y de unos cuantos foreros más (Tiago, Miguelus, Crimson, etc..) que me ayudaron en el foro "Problema con L/C meter".

Gracias amigos.


----------



## Daniel Lopes (Sep 15, 2013)

Hola a todos, como promesia es deuda dejo aca lo articulo de como armar una sonda de alta inpedancia para alta frequencia. Yo espero que aprecien.
!Fuerte abrazo!
Att.
Daniel Lopes.


----------



## trifoncar (Sep 16, 2013)

Dándole vueltas al montaje que quiero hacer, he logrado comprobar que hay un oscilador (he probado un montón) sencillo que permite comprobar los cristales desde 4 hasta 33,8 MHz (no los tengo mayores sin sobretonos).

No recuerdo si alguien de este u otro foro me lo facilitó, o si lo localicé yo por la web. De cualquier forma, si alguien me ayudó ... ¡Muchas gracias!.

El circuito en cuestión -según el esquema- funciona de 2 a 8 MHz, y yo he comprobado de 4 a 8 Mhz. De hecho continúa un poco más con un poco de error. Pero, *quitando el condensador C1 .... funciona perfectamente desde los 12 hasta los 33,8 MHz* (no dispongo de cristales sin sobretonos de mayor frecuencia, ni sé si existen sin sobretonos).

El frecuencímetro funciona perfectamente con este oscilador y puede incluirse como circuito probador de cristales (supongo que ya se conocerá, pero para mi es nuevo) dentro del proyecto que quiero construir. Ünicamente hay que tener en cuenta que he tenido que alimentar el circuito oscilador con 9V (también he comprobado que funciona con 12 V, pero no lo hace con 5V) y en el circuito habla de hasta 30 V (?).

Un saludo.

P.D.: Os pido disculpas, si consideráis que son perogrulladas.


----------



## Daniel Lopes (Sep 17, 2013)

Hola caro trifoncar voi subir un circuito para probar cristales dame un poco de tienpo para escanear .
Att.
Daniel Lopes.


----------



## trifoncar (Sep 17, 2013)

daniel lopes dijo:


> Hola caro trifoncar voi subir un circuito para probar cristales dame un poco de tienpo para escanear .
> Att.
> Daniel Lopes.



Daniel, el circuito que he subido dos post más arriba funciona perfectamente, al menos entre 2 y 34 MHz. con la salvedad arriba indicada. 

Me interesaria algún circuito oscilador que pueda generar en la banda 30-100 MHz para poder probar el tope del frecuencímetro sin prescaler (creo que entre 45 y 55 MHz), y la frecuencia mínima del frecuencímetro con prescaler (que debe de rondar los 60 MHz). He probado varios, pero no logro que me funcionen correctamente (entre ellos, uno de Colpitts que promete desde 30 hasta 300 MHz en http://es.wikipedia.org/wiki/Oscilador_Colpitts).

Adjunto el circuito de Colpitts que infructuosamente he probado.

Un saludo


----------



## Daniel Lopes (Sep 17, 2013)

trifoncar dijo:


> Daniel, el circuito que he subido dos post más arriba funciona perfectamente, al menos entre 2 y 34 MHz. con la salvedad arriba indicada.
> 
> Me interesaria algún circuito oscilador que pueda generar en la banda 30-100 MHz para poder probar el tope del frecuencímetro sin prescaler (creo que entre 45 y 55 MHz), y la frecuencia mínima del frecuencímetro con prescaler (que debe de rondar los 60 MHz). He probado varios, pero no logro que me funcionen correctamente (entre ellos, uno de Colpitts que promete desde 30 hasta 300 MHz en http://es.wikipedia.org/wiki/Oscilador_Colpitts).
> 
> ...


Bueno si queres un oscilador de VHF solamiente para chequear tu frequencimetro arme un transmissorzito de FM lo qual existe una infinidad aca mismo en nese foro y no injecte audio solamiente la alimentaciõn preferencialmiente bien regulada y listo.
!Fuerte abrazo!
Att.
Daniel Lopes.


----------



## miguelus (Sep 17, 2013)

Buenas noches rifoncar

Te voy a decir como reformar el circuito Oscilador que has posteado.

Ahora no puedo publicar el esquema pero espero que puedas seguir la explicación...

El Transistor el mismo

R1 = 470Ω
R2 = 5K6
R3 = 15K
C1 = 68pF
C2 = 68pF pero conectado entre Base y Emisor (ahora esta entre Colector y Emisor)
Quitas la Bobina que hay entre Colector y Vcc y pones una Resitencia de 470Ω
Quita C3
Pon en la Base un Condensador de 1nF, el otro lado del Condensador, de momento lo dejamos al aire.
Ahora puedes hacer varias Bobinas p.e. de entre 500nH y 50nH.
Para calcular las Bobinas emplea el "mini Ring Core Calculator" está por Internet y es gratuíto.
La Bobina la conectas entre el extremo libre del Condensador de 1nF y masa.

La salida del Oscilador es por el Colector y a través de un Condensador de 47pF.

Este Osciador es muy adecuado para frecuencias entre 30 y 70Mhz.

Si quieres puedes ponerle un Cuarzo de 3º sobre tono, ajustas la bobina para que ocile en una frecuencia muy próxima a la del Cuarzo, a continuación levantas el extremo de la Bobina que va a masa, intercalas el Cuarzo y este oscilará a la frecuencia del sobretono.
En ocasiones, y dependiendo del Cuarzo, será conveniente poner en paralelo con el mismo una Resistencia de 560Ω.

Sal U2


----------



## trifoncar (Sep 17, 2013)

miguelus dijo:


> Buenas noches rifoncar
> 
> Te voy a decir como reformar el circuito Oscilador que has posteado.
> 
> ...



He dibujado (un poco mal, ¡vaya diseño!   ) un esquema con las variaciones que me ha parecido entender en tu post. ¿Podrías indicarme si es correcto?

Gracias.


----------



## miguelus (Sep 17, 2013)

trifoncar dijo:


> He dibujado (un poco mal, ¡vaya diseño!   ) un esquema con las variaciones que me ha parecido entender en tu post. ¿Podrías indicarme si es correcto?
> 
> Gracias.



Buenos días.

Lo has entendido perfectamente 

Como te comentaba en el post anterior, puedes poner un Cuarzo de 3º sobretono entre la bobina y masa, el circuito oscilará en la frecuencia del cuarzo.

Sal U2


----------



## trifoncar (Sep 18, 2013)

miguelus dijo:


> Buenos días.
> 
> Lo has entendido perfectamente
> 
> ...



Gracias Miguelus.

He incluído el cristal (adjunto esquema) en el circuito. No te extrañes si te digo que lo he comprobado unas veinte veces. No me funciona. No sé que ocurre con los osciladores, pero no consigo que me funcionen. 

He imaginado que quizá la frecuencia obtenida fuese mayor del límite de frecuencia de conteo para el 16F84, y he incluido el prescaler sin éxito. 
He incluído una bobina de mayor inductancia (y esta vez sin prescaler) para asegurarme de que quedaba muy por debajo del límite del tope de frecuencia del 16F84 y ...nada.

Enfin. No sé dónde puede estar el fallo. He comprobado el frecuencímetro un montón de veces intercaladas entre las pruebas con este circuito ... y funciona bien.

Cualquier indicio de solución a este problema será muy bien recibida. Gracias Miguelus.


----------



## miguelus (Sep 18, 2013)

trifoncar dijo:


> Gracias Miguelus.
> 
> He incluído el cristal (adjunto esquema) en el circuito. No te extrañes si te digo que lo he comprobado unas veinte veces. No me funciona. No sé que ocurre con los osciladores, pero no consigo que me funcionen.
> 
> ...



Buenas noches.

El circuito que has dibujado es correcto y tiene que funcionar.

Te puedo decir que lo vengo utilizando desde hace muchos años (o más).

Siempre lo utilizo con Cuarzos de 3º y 5º sobretono, con frecuencias de entre 27Mhz y 90Mhz

En muchas ocasiones lo empleo así, tal como está, en otras ocasiones le sigue una etapa multiplicadora para obtener frecuencias superiores multiplos del Cuarzo.
Ahora estoy haciendo un Receptor, la primera F.I está en 180Mhz, la segunda F.I. está en 10,7Mhz, el Cuarzo oscila en 33,860Mhz y le sigue una etapa x5 y obtengo los 169,300Mhz que necesito para la primera conversión.

Sal U2


----------



## trifoncar (Sep 18, 2013)

miguelus dijo:


> Buenas noches.
> 
> El circuito que has dibujado es correcto y tiene que funcionar.
> 
> ...



Voy a seguir insistiendo para localizar mi error. Estoy demasiado ilusionado con este proyecto como para abandonar a la primera de cambio.

Ensayaré más veces y analizaré el circuito. Algo debo de estar haciendo mal.

Muchas gracias. Te mantendré informado.


----------



## miguelus (Sep 18, 2013)

Buenas noches de nuevo trifoncar.

Dos cosas...

Hay una cosa que no consta en el esquema pero son esas cosas que siempre se suponen  Enla alimentación hay que poner siempre, por lo menos un Condensador de desacoplo, pon un Condensador de 100nF entre Positivo y Masa.

Otra cosa, si no temolesta contestar ¿Para qué necesitas este Frecuencímetro?.

Sal U2


----------



## trifoncar (Sep 18, 2013)

miguelus dijo:


> Buenas noches de nuevo trifoncar.
> 
> Dos cosas...
> 
> ...



He probado con el condensador de 100 nF y sigue igual. Alguna vez leí que a partir de 50 MHz empiezan a afectar "los espíritus" 

Tengo espíritu de ingeniero y las inexactitudes (en el campo físico-experimental) me deprimen. Y sé que la electrónica de alta frecuencia se parece más a una ciencia de tipo "predecible" que a una ciencia exacta.

Tuve un "ahuyenta-perros" que de repente dejó de funcionar. Compré uno nuevo y funcionaba muy mal. Me informé sobre la frecuencia idónea para un buen funcionamiento. Luego me aslató la duda de cómo medir esa freuencia.

Por otra parte, poco después, construí un receptor de radio basado en el pic TDA7000 que me funcionó a la primera. Advertían que variando el número de espiras de la bobina de sintonia variaría la frecuencia de sintonía -cosa que asumí sin dudar porque tengo unos conocimientos básicos de electrónica- y varié el número de espiras hasta quintuplicarlo, y lo reduje varias veces e ... intentando conocer las frecuencias de las emisoras que escuchaba (en Madrid, es decir, un centenar de ellas) seguía abarcando el mismo rango de frecuencias; lo mismo de daba poner 3 espiras que 30; sintonizaba el mismo abanico de emisoras ( una vez que las localizaba por mi equipo de radio). Me volví "majareta" escuchando en el recién construído receptor y buscando en el equipo de música la misma frecuencia. Ese arduo trabajo me "descolocó" bastante, ya que no tenía referencia de la frecuencia en la que me estaba moviendo. No sabía si estaba en FM o en banda ciudadana o en la de la poli o en la de los inalambricos.  etc. Perdí un timepo increíble en aquel asunto. Construí un medidor de inductancias que no me ayudó mucho. Busqué como un poseso un ingenio que -al igual que mi equipo HiFi- indicase la frecuencia en la que me estaba moviendo ...y localicé los frecuencímetros.

Desde ahí hasta la situación actual es fácil de adivinar. ¿Porqué hasta 1,3 GHz? pues porque además de la banda de FM me gustaría adquirir señales mas altas. En algún sitio leí sobre un receptor que llegaba a esas frecuencias (algo relacionado con imágenes de los satélites y demás).

En resumen .... saber por dónde me estoy "moviendo".

Espero haber contestado tu pregunta, Miguelus.

Disculpa/disculpad la extensión.

Un saludo, y gracias.


----------



## miguelus (Sep 19, 2013)

No hay que desanimar , en la Electrónica y concretamente en la RF, es como dicen los gallegos "Las meigas no existen pero haberlas Haylas".

Te diré que de Pic entiendo menos que nada, circuitos con Pic habré hecho uno o ninguno .. bueno sí, he hecho un medidor LC, este medidor está basado en una 16F84 y curiosamente funciona igual de bien que un medidor Agilent de varios miles de $.

Lo que comentas del TDA7000... pues no me extraña que pase lo que comentas, lo que no llego a comprender es la razón por la que Philipis llegó a comercializar ese integrado 

Para hacer medidas en un oscilador y saber si está oscilando  haz lo siguiente...
 En la punta Positiva del Polímetro pon un Choque de 1µH o más, deja las patitas lo más cortas posibles.

Ahora mide la tensión en la Base del Transistor Oscilador, a continuación mide la tensión en el Emisor, el valor de estas tensiones, en principio, no es importante, *lo importante es que el Emisor tiene que tener .6Voltios menos que la base*, esto indica que el Transistor está bien polarizado.

Ahora conecta y desconecta el Cuarzo, la tensión de Emisor tendrá que variar. Si la tensión en el Emisor no varía significa que el Transistor no oscila.

En los tiempos de las Válvulas se decía “Oscilador que no oscila algo tiene en la Rejilla”.

Otra forma de medir es haciéndote una pequeña sonda de RF y  midiendo en la salida del Condensador que hay en el Colector, esto se hace con un Diodo tipo OA90 y un Condensador de 10nF.

Lo ideal sería  tener un Osciloscopio o, mejor aún, un Analizador de Espectros.

Haz alguna medida y coméntala.

Sal U2


----------



## miguelus (Sep 19, 2013)

Buenas tardes.

Esta mañana he tenido un rato libre y he hecho algunas pruebas con el Oscilador en cuestión.

He probado con varios Transistores y con todos ha funcionado, yo utilizo el BF199.

He probado con varios Cuarzos de entre 10Mhz y 80Mhz, siempre ha oscilado.

Hay que reseñar que los Cuarzos de 3º Sobre Tono, si los conectamos sin la Resistencia de 470Ω oscilarán muy cerca de su frecuencia fundamental.

Igualmente en los Cuarzos cortados para oscilar en Fundamental, si ponemos la Resistencia, oscilan en su 3º Sobre tono, esto último no pasa con todos los Cuarzos que he probado...

Tendré que estudiar más acerca de los Cuarzos :estudiando::estudiando:

Seguramente, si subimos los valores de los Condensadores de Realimentacón p.e. a 120pF podremos probar Cuarzos de frecuencias inferiores de 10 Mhz, si tengo algo de tiempo lo miraré 

Sal U2


----------



## trifoncar (Sep 19, 2013)

Buenas ...

Miguelus, he efectuado las medidas en el transistor y he obtenido 1.097 mV para la Base y 499 mV para el Emisor, por lo que deduzco que está bien polarizado. 
Por otra parte, al conectar o desconectar el cuarzo, la tensión en el emisor no varía.

Tengo auténtica envidia al leer las pruebas que has llevado a cabo esta mañana.
No logro entender que me está ocurriendo con un circuito tan sencillo para que no funcione. Quizá estoy pasando por alto algún detalle.

Subo un par de fotos sobre el circuito oscilador (LC) y, otra sobre el frecuencímetro, el prescaler y el módulo oscilador a 100 MHz. Como verás, está en protoboard (hasta que no funcione todo no hago las pcb), pero -excepto el oscilador LC- todo parece funcionar correctamente. Ya comenté que mido perfectamente los cristales desde 4 a 33,8 MHz, y con prescaler los 100 MHz del módulo oscilador. Pero me falta comprobar la banda 34 - 70 u 80 MHz y luego, por encima de los 100 MHz.

Un saludo

P.D.: el circuito oscilador LC, lo alimento con 9V.
El frecuencímetro queda bastante poco visible por las pinzas que sujetan el BFR91, y las que sujetan el trimmer. Lo siento.


----------



## tiago (Sep 19, 2013)

Con las protoboard vas a tener ese problema. Deberias descartarlo.
Monta el oscilador en Manhattan y prueba a ver.

Por cierto, ¿Hiciste pruebas con un condensador de baja capacidad a la entrada del frecuencímetro?.
Si es así, ¿Que resultados has obtenido?

Saludos.


----------



## trifoncar (Sep 19, 2013)

Si, creo que debo de haceros caso de una vez. Me estaba "haciendo el remolón" porque quería que todo me funcionase en protoboard antes de "remangarme" y meterme en faena; pero creo que no me queda otro remedio.

Voy a hacer el montaje según el sistema Manhattan y ya os contaré.

Gracias a todos, en especial a Miguelus por su paciencia e interés.

Un saludo a todos!


----------



## miguelus (Sep 19, 2013)

trifoncar dijo:


> Buenas ...
> 
> Miguelus, he efectuado las medidas en el transistor y he obtenido 1.097 mV para la Base y 499 mV para el Emisor, por lo que deduzco que está bien polarizado.
> Por otra parte, al conectar o desconectar el cuarzo, la tensión en el emisor no varía.
> ...



Buenas noches de nuevo

 Mal empezamos, con esas tensiones en el Transitor no creo que pueda funcionar.

Unas tensiones correctas (las que yo he medido)...

Base 2,2Vcc
Emisor 1,5Vcc
Colector 7,4

Lo alimento con 9Vcc.

Revisa los valores de las Resistencias veo una de 10K que no está en el esquema.

Antes de seguir avanzando vamos a olvidarnos de la Bobina, en su lugar pon un puente.

Con ese tipo de montaje, no esperes que la cosa funcione en mas de unos pocos Mhz.

Sal U2


----------



## trifoncar (Sep 19, 2013)

Si es la de arriba a la izquierda (R3), es de 15 K. El color en la foto ha quedado un poco oscuro.
Cambiando los valores de R3 y R2 he conseguido Vc:7,25 - Vb:1,64 y Ve:1,01

El voltaje en el emisor no varía al poner-quitar el cristal.



No corrijo el mensaje anterior. Pongo aquí los cambios.

He cambiado la R1 desde 470R a 2K2 y R3 desde 15 K a 10 K. Ahora obtengo Vc=7,25v - Vb=2,05v - Ve=1,47v

Al quitar o volver a poner el cristal, no varia Ve.

Algo es algo

Un saludo

P.D.: El cristal que utilizo de 48MHz he comprobado que está bien.
Aunque en la foto aparece otra bobina (hice muchas pruebas) la que estoy utilizando ahora es de unos 320 nH


----------



## trifoncar (Sep 20, 2013)

No hay como descansar un poco y reiniciar la búsqueda.
He sustituido el 2N2222 por un BF199 que tenía (y teniendo en cuenta el diferente orden de patillas) y me ha funcionado a la primera, pero obtengo la frecuencia fundamental, no el tercer sobretono. El cristal marca 48 MHz y obtengo 15,993 MHz. Sin embargo, creo que este circuito es para obtener el tercer sobretono ¿es correcto?

Un saludo


----------



## miguelus (Sep 20, 2013)

trifoncar dijo:


> No hay como descansar un poco y reiniciar la búsqueda.
> He sustituido el 2N2222 por un BF199 que tenía (y teniendo en cuenta el diferente orden de patillas) y me ha funcionado a la primera, pero obtengo la frecuencia fundamental, no el tercer sobretono. El cristal marca 48 MHz y obtengo 15,993 MHz. Sin embargo, creo que este circuito es para obtener el tercer sobretono ¿es correcto?
> 
> Un saludo



Buenos días.

El circuito, en principio, está diseñado para oscilar en Sobretono 3º, 5º...

Para ello tiene que estar conectada la Resistencia de 470Ω en paralelo con el cuarzo, si no la conectas el circuito oscilará en la frecuencia fundamental del Cuarzo.

Para facilitar y ajustar la frecuencia correcta es conveniente que esté la bobina.

Conecta el circuito solo con la bobina (en lugar del Cuarzo pon un puente), cuando esté oscilando en la frecuencia correcta quita el puente y pon el Cuarzo, la Bobina servirá para ajustar la frecuencia correcta +- unos cientos de Hz.

Jamás he montado nada en Protoboard, dan resultados impredecibles y más en RF.

Sal U2


----------



## trifoncar (Sep 20, 2013)

Hola foreros!

Al final me tiré a la piscina e hice el circuito del oscilador con el sistema "Manhattan". 
Justo acabar de montarlo, me dí cuenta de que había colocado el transistor al revés 

He conseguido cambiarlo y, si antes era una chapuza, ahora lo es y además lo parece  . Aunque la cuestión es que funcione.

He puesto varias conexiones que permiten intercambiar los componentes o cables. Uno es la salida al prescaler, otro para insertar la bobina y un tercero para insertar un cristal.

Miguelus, he intentado seguir tus directrices y, tras conseguir poner una bobina (directa a tierra y sin el cristal), que me produjese más o menos 100MHz, al insertar el cristal obtengo casi siempre 120 MHz. No lo entiendo, porque si la frecuencia fundamental es 20 MHz, 120 no es ni x3, ni x5, ni x7, sino x6.

Subo tres fotos; una del circuito, otra del sistema completo con frecuencímetro y prescaler (donde se puede ver en la pantalla 120,005696 MHz) y una tercera donde puede verse un cristal utilizado de 100 MHz (no un módulo que tengo de esa misma frecuencia).

Un saludo



        Bien, llevo como media hora viendo 120,0003xx  ó  120,0004xx ó  120,0005xx en la pantallita. Creo que es suficiente y no es una casualidad ya que la variación, es de aproximadamente una millonésima.

No entiendo bien el funcionamiento de los armónicos ni entiendo bien el circuito así que -abusando de vuestra confianza-os iré preguntando. 

         Me gustaría llevar hasta la máxima frecuencia con este circuito y no sé si con un cristal de frecuencia fundamental 38,3868 podría llegar a su 5º (169,344 MHz) o a su 7º armónico (237,0816 MHz), pero no recuerdo el límite para este circuito.

Quiero agradecer a Miguelus por la atención y la paciencia que ha tenido conmigo, a Fogonazo, tiago y Daniel, por animarme a meterme con el proyecto Manhattan. y al resto de los foreros por su atención y comprensión.

Un saludo


----------



## miguelus (Sep 20, 2013)

Buenas noches.

Cuando parece que vamos avanzando nos encontramos con otros problemas  

Bien lo que comentas del cuarzo de 38,3868Mhz, en primer lugar no hay Cuarzos (o sería rarísimo) que estén tallados para oscilar en esa frecuencia como fundamental, con toda seguridad es un 3º Sobre tono, su frecuencia fundamental será ~12,7956Mhz

Lo que comentas del Cuarzo de 100 Mhz y que el Frecuencímetro marca 120Mhz...

Veamos...

El montaje que estas empleando es algo parecido al denominado "Manjatan", pero sería más lógico llamarlo "Trifoncar Manjatan"  ya que estás empleando conexiones muy largas  y en esas frecuencias puedes tener resonancias descontroladas.

Seguramente ese Cuarzo de 100Mhz es un 5º Sobre tono y está oscilando en su fundamental, 20Mhz.

Los Osciladores suelen tener muchos armónicos y por cuestiones de Inductancias y Capacidades parásitas puede ser que tengas una resonancia cerca de 120Mhz y al Amplificador del Frecuencímetro le sea más cómodo amplificar ese 6º armónico que es precisamente 120Mhz.

No hay que confundir los armónicos con los Sobre tonos.

Seguramente si se monta ese circuito en una placa con conexiones muy cortas todos esos fenómenos extraños y los "Posterguéis" desaparecen, recordemos que en RF no existen las Meigas pero "haberlas hailas" 

Piensa una cosa, si tu frecuencímetro está marcando 120Mhz, significa que por lo menos, en esa frecuencia, funciona, cuando tengas todo bien montado la cosa mejorará 

Sal U2


----------



## trifoncar (Sep 21, 2013)

miguelus dijo:


> Buenas noches.
> 
> Cuando parece que vamos avanzando nos encontramos con otros problemas
> 
> ...



Perdón, el cristal es de 33,8688 MHz, y no de 38,3868 (¡¡¡vaya lío me monté entre los treses, el seis y los ochos!!!)

Lo supe en cuanto me toco soldar el condensador de 1 nF y las dos resistencias a Vcc. Pero es que no tenía ganas de hacer un nuevo corte en la placa de cobre para la Vcc. En cuanto pueda haré un nuevo "Trifonhattan". 

Gracias por los comentarios, siempre ayudan.

Tengo una duda. Resulta que al poner una bobina a tierra (es decir, sin cristal), obtengo una frecuencia en el frecuencímetro que está determinada por la inductancia de la bobina y la capacidad del circuito oscilador. Pues bien, he insertado varias bobinas de diferentes valores (de las que he calculado su valor con el programa que me indicaste) y he obtenido que el valor de la capacidad del circuito resonante está entre 1,8 y unos 7 pF. Yo creo que tenían que salirme unos 34 pF (dos condensadores de 68 pF en serie). ¿Estoy confundido o hay otra explicación?

Un saludo y, de nuevo, muchas gracias.


----------



## miguelus (Sep 21, 2013)

Buenas tardes Trifoncar.

Ten en cuenta que con el montaje "Trifonhattan".  tienes muchas inductancias y capacidades parásitas por lo que el Circuito Equivalente sería difícil de adivinar, también tienes la capacidades  del Transistor.

Sal U2


----------



## trifoncar (Sep 21, 2013)

Esto me empieza a recordar a aquello de que "la mecánica newtoniana empieza a perder su efectividad según se va elevando la velocidad y sus leyes pasan a ser mayormente dependientes de los términos cuánticos". En electrónica, toda la electrónica clásica empieza a perder efectividad según se va elevando la frecuencia y sus leyes "vaya usted a saber de qué dependen". 

He efectuado cientos de pruebas y comprobado infinidad de valores ¿Dependerá de las meigas? ¿de la cercanía de la manos al circuito?¿de la cercanía del teléfono móvil?¿de la cercanía de otras bobinas?¿de las herramientas que tengo cerca del circuito? Seguramente es que lo he montado mal.

Si no me animo a montar el circuito Manhattan de nuevo mejor planificado, me compraré unos walkie-talkie para probar la frecuencia en torno a los 44x MHz.

Gracias Miguelus, la verdad es que estoy descubriendo un nuevo mundo con esto de los cristales gracias a tí. Espero rematar este circuito y, luego abordar otro hasta 200 MHz, pero necesito un transistor con Ft> 2.000 MHz.

Un saludo


----------



## Daniel Lopes (Sep 21, 2013)

Hola trifoncar lo transistor que buscas puede sener un BFR91 o BFR 96, o MRF901 o MRF911 eses transistores tienem un Ft mui elevado (algunos Ghz ) .
!Fuerte abrazo !
Att.
Daniel Lopes.


----------



## trifoncar (Sep 22, 2013)

daniel lopes dijo:


> Hola trifoncar lo transistor que buscas puede sener un BFR91 o BFR 96, o MRF901 o MRF911 eses transistores tienem un Ft mui elevado (algunos Ghz ) .
> !Fuerte abrazo !
> Att.
> Daniel Lopes.



¡Hola Daniel!

Gracias por la información. Tengo únicamente un BFR91 pero lo estoy utilizando en el frecuencímetro; aunque -ahora que lo pienso- este nunca recibirá más de 1.300.000.000/64 (en caso de utilizar el prescaler  U664) ó 2.400.000/256 (si utilizo un MB506) y eso significan 20,3 ó 9,375 MHz con prescaler y como son como máximo 50 ó 60 MHz sin prescaler ...... creo que no me hace falta un BFR91 a la entrada del frecuencímetro, bastará con uno que llegue a los 100 ó 200 MHz.

Un saludo



daniel lopes dijo:


> Hola trifoncar lo transistor que buscas puede sener un BFR91 o BFR 96, o MRF901 o MRF911 eses transistores tienem un Ft mui elevado (algunos Ghz ) .
> !Fuerte abrazo !
> Att.
> Daniel Lopes.



¡Hola Daniel!

Gracias por la información. Tengo únicamente un BFR91 pero lo estoy utilizando en el frecuencímetro; aunque -ahora que lo pienso- este nunca recibirá más de 1.300.000.000/64 (en caso de utilizar el prescaler  U664) ó 2.400.000/256 (si utilizo un MB506) y eso significan 20,3 ó 9,375 MHz con prescaler y como son como máximo 50 ó 60 MHz sin prescaler ...... creo que no me hace falta un BFR91 a la entrada del frecuencímetro, bastará con uno que llegue a los 100 ó 200 MHz.

Un saludo





tiago dijo:


> Con las protoboard vas a tener ese problema. Deberias descartarlo.
> Monta el oscilador en Manhattan y prueba a ver.
> 
> Por cierto, ¿Hiciste pruebas con un condensador de baja capacidad a la entrada del frecuencímetro?.
> ...



Te pido disculpas, Tiago, no respondí a tu pregunta, aunque creo que puse unos resultados en el post #9 que son los datos obtenidos tras poner una pequeña capacidad a la entrada del prescaler que supongo contestarían a tu pregunta. Efectivamente a partir de 10 ó 20 pF la lectura es correcta.

Un saludo


----------



## Daniel Lopes (Sep 22, 2013)

trifoncar dijo:


> ¡Hola Daniel!
> 
> Gracias por la información. Tengo únicamente un BFR91 pero lo estoy utilizando en el frecuencímetro; aunque -ahora que lo pienso- este nunca recibirá más de 1.300.000.000/64 (en caso de utilizar el prescaler  U664) ó 2.400.000/256 (si utilizo un MB506) y eso significan 20,3 ó 9,375 MHz con prescaler y como son como máximo 50 ó 60 MHz sin prescaler ...... creo que no me hace falta un BFR91 a la entrada del frecuencímetro, bastará con uno que llegue a los 100 ó 200 MHz.
> 
> ...


Bueno el MB506 del Fujitsu es un preescaler dibisor por 256 hasta 2.5Ghz entonses hay que inserir esa dibisiõn en tu frequencimetro , yo tengo un frequencimetro marca Optoelectronics lo qual hace uso de uno y tiene como base de tienpo un cristal de 10.000Mhz sin preescaler ( medida directa)y otro de 3,90625Mhz quando hace uso del preescaler de modo corregir automacticamiente la medida en su display. 
!Fuerte abrazo!
Att.
Daniel lopes.


----------



## miguelus (Sep 23, 2013)

Bunas noches.

Trifoncar dijo...

_Esto me empieza a recordar a aquello de que "la mecánica newtoniana empieza a perder su efectividad según se va elevando la velocidad y sus leyes pasan a ser mayormente dependientes de los términos cuánticos". En electrónica, toda la electrónica clásica empieza a perder efectividad según se va elevando la frecuencia y sus leyes "vaya usted a saber de qué dependen". _

Pues estás equivocado Trifoncar, cuando subes de frecuencia 3Ghz... 6Ghz... 18Ghz las cosas empiezan a funcionar como está previsto, no suelen estar presentes las "Meigas".
El problema es el coste de la Instrumentación, un simple par de cables de medida puede salir por 4000 (cuatro mil) U$  y un Analizador de Redes  un montón (o más).

Sal U2


----------



## trifoncar (Sep 26, 2013)

Hola Daniel,

el prescaler que tengo es el U664BS y divide por 64. El software que tengo cargado en el pic está preparado para dividir por 64. En cuanto tenga el MB506 indagaré para ver la forma de cambiar el soft del pic.



miguelus dijo:


> Bunas noches.
> 
> Trifoncar dijo...
> 
> ...



Hola Miguelus,

Vale hombre! Ya veo que no está a mi alcance   

Me he dedicado estos dos últimos días a intentar "pillar" la frecuencia de la radio FM con TDA7000, pero la frecuencia que me sale en el frecuencímetro es muy aleatoria y siempre está por encima unos 25 ó 30 MHz .  Ante mi desesperación por lo inutil del experimento, recordé lo que me dijo Daniel sobre construir una pequeña emisora de FM, y me he animado con ello. Muchas gracias a EinSoldiatGott por su hilo https://www.forosdeelectronica.com/f22/transmisor-fm-2130/  Estuve mirando unos cuantos y al final me animé con este, que funciona y ha servido para mis fines. 
Una vez montada la emisora de FM he estado un montón de tiempo intentando localizar por todo el dial alguna interferencia, algún ruido, algo que delatase a mi emisora y no había forma; hasta que hoy ¡lo he conseguido!  :babear:

Por fín y de una forma inequívoca, he logrado comprobar en dos frecuencias diferentes la exactitud del frecuencímetro. Aunque en el receptor la señal de sintonía de mi "emisorita" abarcaba entre 250 y 300 KHz, la zona central era aproximadamente entre 50 y 100 KHz menos de lo que marcaba el frecuencímetro; supongo que es la famosa FI del PIC que es de 75 KHz si no me equivoco.

Por cierto -y aunque sé que no os va a gustar nada- todo estaba en protoboard: el frecuencímetro, el prescaler, el receptor con TDA7000 y la emisora de FM. Pero por supuesto que lo próximo que haré será preparar los circuitos en Manhattan (no en "Trifonhattán")    Tendré en cuenta los comentarios recibidos, lo leído por el foro de Fogonazo (gracias¡) y lo leído en otros foros.

Me queda probar una frecuencia relativamente alta pero estoy en busca de un walkie-talkie que emita en 446 y que ya le he pedido prestado a un amigo. También intentaré localizar un micrófono inalámbrico de los que emiten sobre los 86x MHz; con ello cerraría la etapa de pruebas con el prescaler U664BS (habría probado con éxito la zona de los 90-110, 446 y 86x MHz, que para mí son suficientes para dar por hecho que el frecuencímetro funciona perfectamente con este prescaler.

¡Muchas gracias a todos!

Un saludo. Os mantendré al tanto de mis avances.

P.D.: El protoboard (o placa de pruebas) pequeño que no está conectado es el montaje del receptor con TDA7000


----------



## trifoncar (Oct 15, 2013)

Hola foreros,

He subido un video  sobre unas pruebas del frecuencímetro (con 16F84A) y prescaler (con U664BS) en protoboard 



 Sé que incumple la lógica de montaje en circuitos de -relativamente- alta frecuencia, pero me gusta intentarlo en protoboard siempre que puedo, ya que a veces hay que cambiar el valor de algunos componentes y eso, con componentes soldados es mucho más complicado.
Una vez decididos los componentes y su valor, y comprobado su correcto funcionamiento, efectúo el montaje en placa.
El video es un poco largo y, por ser mi primer vídeo, tiene muchos defectos. Espero que seáis benévolos. Pero me ha alegrado comprobar que a pesar de estar hecho en protoboard, la medición de la frecuencia me ha dado un resultado de un 0,016 % (poco más de una diezmilésima parte) de error con respecto a los datos del manual del walkie talkie a unos niveles de 446 MHz, en los ocho canales de que dispone; y en todos ellos me ha dado la misma desviación (0,016 %).

Un saludo.


----------



## FailSafe (Oct 15, 2013)

Lo tienes puesto como privado y no se puede ver


----------



## trifoncar (Oct 15, 2013)

Acabo de corregirlo a público. Pero me he dado cuenta de que después de cambiar la resolución, no se ve bien la lectura del frecuencímetro. Tendré que repetir la conversión del video; lo siento.
Espero acabar de corregirlo en una horas.



FailSafe dijo:


> Lo tienes puesto como privado y no se puede ver




Acabo de reformarlo (incluso la resolución porque era un poco "penosa").  Y a pesar de todo cuesta ver la frecuencia en el LCD. Lo siento. Espero  hacer mejor los futuros videos.

Gracias por la advertencia, Failsafe.

Un saludo


----------



## trifoncar (Oct 30, 2013)

Os pido ayuda sobre un fichero fuente para el pic 16F84 que controlará un frecuencímetro. El fichero lo he bajado de la página de Phil Rice (https://sites.google.com/site/vk3bhr/home/fm2/prescale), donde lo tiene publicado y a disposición del público.
El problema es que el fichero está preparado para un prescaler que divide la frecuencia de entrada por 64 y yo lo quiero cambiar ahora para aplicar un prescaler que divide por 256. En el fichero que os envío eso lo hace pero con el factor 64 (no el 256 que yo necesitaría).

Es decir, el prescaler envia al 16F84 una señal con una frecuencia que será 1/256 la frecuencia original. El 16f84 deberá de multiplicar esa frecuencia que recibe por 256 para dar una lectura correcta de la frecuencia original.

Mis escasos conocimientos de programación no me permiten llegar a saber los cambios que tendría que efectuar para ello.

¿Podría alguien echarme una mano?

Adjunto la dirección del fichero fuente

Muchas gracias.
Archivos https://sites.google.com/site/vk3bhr/home/fm2/presource


```
;*******************************************************************
;
;    "Digital" Frequency display with /64 prescaler & no offsets
;
;    Crystal freq. = 4.000MHz +/- a bit
;
;*******************************************************************
;
;    First, let us choose our weapon - 16F84 or 16F628
;

;    Comment out the next line [;#define F84] if using a 16F628

#define    F84

#ifndef    F84
    #define    F628
#endif


;*******************************************************************
;
;    Some Testing Stuff(tm)
;

;#define    testing        1    ; Comment out when testing finished

;#define    Two_Line    1    ; Un-comment for two line displays


;************************ REVISION HISTORY *************************
;
;    FM1.000    Originally from FM3/4 9:39pm 14 May 2002
;        As implemented in experimental 3.5MHz receiver
;
;*******************************************************************
;
;    FM1.003    Fixed? major silliness in LO-IF code
;        Re-wrote USB/LSB suffix code
;        Added #defines for crook displays
;        Added #defines for two line displays
;        Wrapped #ifdef ... endif around debugging code
;
;*******************************************************************
;
;    FM1.004    Added code to allow user to fix crook display
;        Deleted #defines for crook displays
;        Pin 18 is now input. 1 = good display, 0 = crook
;
;*******************************************************************
;
;    FM2.000    New Hardware! Deleted external counter & gating
;        Now uses the same scheme as the LC Meter, with the
;        third byte of the count implemented in the PIC.
;        Basically, the "output" of the timer register is
;        counted within the gate timing loop.
;
;*******************************************************************
;
;    FM2.001    Discovered that I don't need to use RA0 as a gate
;        cos RA4 can be used as a timer input, even when
;        defined as an output - all that is required is to
;        set it high to count or low to inhibit.
;        Jeez, Microchip are smart arses.
;        I dunno why I didn't spot this long ago.
;        (Can't be used on the LC Meter, cos its oscillator
;        needs to be clamped HIGH, not low as in this case).
;
;*******************************************************************
;
;    FM2.002    Added 9600 baud serial output via RA0
;
;*******************************************************************
;
;    FM2.003    Rewrote RollOver subroutine to use INTCON,T0IF bit.
;        Incorporated two bits from OvrFlow counter
;        to extend range to over 80MHz.
;
;*******************************************************************
;
;    FM2.004    Changed to 32 bit counting.
;
;*******************************************************************
;
;    FM2.005    Added "Calibrate" mode.
;
;*******************************************************************
;
;    FM2.006    Moved "divide by 4" to increase resolution of
;        the stored IF offsets
;
;*******************************************************************
;
;    FM2.007    Moved "check for rollover" out of the inner MS400
;        timing loop and adjusted loop count appropriately
;        The aim - to improve the resolution of the software
;        calibration by a factor of around 13 to 15 times.
;
;*******************************************************************
;
;    fm2b.007    Ported to 16F628
;    FM2c.007    Introduced macros
;    fm2.008        Renumbered
;
;*******************************************************************
;
;    fm2.009        Cleaned up AM IF Offset calculation
;            Converted some inline code to subroutines
;            Created new 32 bit "copy" macro
;            Adjusted calibration slightly
;            Added a "Processor =" message
;            Removed advertising.
;
;*******************************************************************
;
;    ghzfm.000    Added multiply by 64
;            Rendered offsets ineffective
;            changed display format to
;            xxxx.xxxxxx MHz
;            Gate time now 1.000 Second
;
;
;
;*******************************************************************
;o-----o-----o-----o-----o-----o-----o-----o-----o-----o-----o-----o
;*******************************************************************
;
;    Some frequently used code fragments
;    Use macros to make mistreaks consistently.
;
;-------------------------------------------------------------------
;    Select Register Bank 0

bank0    macro
    errorlevel    +302        ; Re-enable bank warning
    bcf        STATUS,RP0    ; Select Bank 0
    endm

;-------------------------------------------------------------------
;    Select Register Bank 1

bank1    macro
    bsf        STATUS,RP0    ; Select Bank 1
    errorlevel    -302        ; disable warning
    endm

;-------------------------------------------------------------------
;    Copy a 32 bit thing from one place to another

copy    macro    from,to

    movf    from+0,W
    movwf    to+0

    movf    from+1,W
    movwf    to+1

    movf    from+2,W
    movwf    to+2

    movf    from+3,W
    movwf    to+3

    endm

;*******************************************************************
;
;    CPU configuration
;

#ifdef    F84
    MESSG        "Processor = 16F84"
    #define     RAMStart    0x0C    ; by VK3BHR
    processor    16f84
    include        <p16f84.inc>
    __config    _HS_OSC & _PWRTE_ON & _WDT_OFF
#endif

#ifdef    F628
    MESSG        "Processor = 16F628"
    #define     RAMStart    0x20
    processor    16f628
    include        <p16f628.inc>
    __config    _HS_OSC & _PWRTE_ON & _WDT_OFF & _CP_OFF & _BODEN_ON & _LVP_OFF
#endif

;*******************************************************************
;
;    I/O configuration
;


#define S_out    PORTA,0x00    ; 9600 baud serial out
#define PUFF    PORTA,0x00    ; Testing counter out

;#define    FIXIT    PORTA,0x01    ; 1 = "good display"
                ; 0 = do CRLF at "chr 8"

#define    PSC    PORTA,0x01    ; 1 = multiply by 64
                
#define    ENA    PORTA,0x02    ; Display "E"
#define    RS    PORTA,0x03    ; Display "RS"
#define    CLAMP    PORTA,0x04    ; Pull-down the timer input

#define    Store    PORTB,0x04    ; Pin 10, 0 = Measure BFO
#define    Add_LO    PORTB,0x05    ; Pin 11, 0 = RF := LO + IF
                ;         1 = RF := | LO + (-IF) |
#define    BFO_Lo    PORTB,0x06    ; Pin 12, 0 = BFO on lower freq.
#define    BFO_Hi    PORTB,0x07    ; Pin 13, 0 = BFO on higher freq.

#define    Prg_FLG    FLAGS,0x05
#define    AMflag    FLAGS,0x03    ; 0 = Don't print USB/LSB suffix

#define    beq    bz        ; Motorola syntax branches
#define    BEQ    bz
#define    BNE    bnz
#define    bne    bnz

#define    BCC    bnc
#define    bcc    bnc
#define    BCS    bc
#define    bcs    bc

#define    BRA    goto
#define    bra    goto

;*******************************************************************
;
;    file register declarations: uses only registers in bank0
;    bank 0 file registers begin at 0x20 in the 16F628
;
;*******************************************************************

    cblock    RAMStart

    dbg0:4            ; Debugging stuff
    dbg1:4
    dbg2:4
    dbg3:4
    dbg4:4
    dbg5:4


    bcd:5            ; BCD, MSD first 

    SBflag            ; 0 = Lower BFO frequency
                ; 1 = Higher

    COUNT            ; Bin to BCD convert (bit count)
    cnt            ;                    (BCD BYTES)


    CHR
    TEMP            ; DATS/Putchr temporary
    pmsg_t            ; Used by PMSG

    FLAGS

    S_Wtemp            ; "debug" Variables
    S_count
    D_Wtemp
    D_Stemp
    D_FSR
    D_hex
    
    endc

#ifdef    F84
Part2    equ    D_hex+1        ; Just tack on end
#endif

#ifdef    F628
Part2    equ    0x70        ; $70-7F Visible from all banks
#endif

    cblock    Part2

    COUNT1            ; Used by delay routines
    COUNT2            ; Timing (100ms)
    COUNT3            ; Timing (100ms)
    COUNT4            ; Timing (400ms)

    AccA:4            ; Binary, MSByte first

    AccB:4            ; Intermediate frequency

    Hold:4            ; Used in "cal" mode

    endc

;**********************************************************
;
;    Begin Executable Stuff(tm)
;

    org    0

GO    clrwdt            ; 0 << Reset
    clrf    INTCON        ; 1 No interrupts

#ifdef    F628
    movlw    0x07        ; 2 Comparator off
    movwf    CMCON        ; 3
#endif

    goto    START        ; 4 << Interrupt.

;**********************************************************
;
;    Part of string printer
;

pmsub    movwf    PCL        ; Goto W
    nop            ; Just in case
pm_end    return

;**********************************************************
;
;    Text Strings (stored in RETLWs)
;

mhz    dt    " MHz",0
Spaces    dt    " ",0
USB    dt    "U",0
LSB    dt    "L",0
Prog    dt    "P",0
Cal    dt    "C",0

#ifdef    Two_Line

adv3    dt    "1234567890ABCDEF",0

 endif

;**********************************************************
;
;    Main Program
;

START    call    InitIO        ; INITIALISE PORTS
    CLRF    PORTA
    CLRF    PORTB
    bsf    S_out        ; Serial output to idle
    
    CALL    LCDINIT         ; INITIALIZE LCD MODULE    

;    MOVLW    adv1        ; Sign on
;    call    pmsg

;    btfss    FIXIT        ; Test input 1 = just return
;    CALL    LINE2        ; 0 = fix bad display

;    movlw    adv2
;    call    pmsg
    
;    CALL    MS512        ; Delay for about 1 sec.
;    CALL    MS512        ; 0.512 sec x 2

    CALL    CLEAR

;**********************************************************
;
;    Check if in "Calibrate" mode
;

    btfsc    Store        ; If grounded initially
    goto    newbit        ; then were in "cal"

    MOVLW    0xfa        ; Set initial counter        
    MOVWF    Hold+0        ; value

    MOVLW    0xff        ; 
    MOVWF    Hold+1        ; for a 4 MHZ XTAL

    MOVLW    0x5f
    MOVWF    Hold+2            

    MOVLW    0x00        ; Unused
    MOVWF    Hold+3            

GetCal    call    Measure    
    call    Display
    movlw    Cal        ; Say "we're calibrating"
    call    pmsg
    CALL    HOME

;
;    Adjust Cal value
;

cal_dn    btfsc    BFO_Lo
    goto    cal_up
    
    incf    Hold+2,f    ; Add 1
    bne    inc_xit
    incf    Hold+1,f
    bne    inc_xit
    incf    Hold+0,f
inc_xit    goto    StorCal

cal_up    btfsc    BFO_Hi
    goto    StorCal

;
;    Hold := Hold + (1-)    ; Subtract 1
;

Hadd_2    movlw    0xff        ; Process LS byte
    addwf    Hold+2,F
    bcc    Hadd_1        ; If no carry,do next

    incf    Hold+1,f    ; Else roll over higher
    bne    Hadd_1        ; bytes as appropriate

    incf    Hold+0,f    ; may roll over MSByte
        
Hadd_1    movlw    0xff        ; Process next byte
    addwf    Hold+1,F
    bcc    Hadd_0        ; If no carry,do next

    incf    Hold+0,f    ; may roll over MSByte
        
Hadd_0    movlw    0xff        ; Process next byte
    addwf    Hold+0,F

;
;    Time to save "Cal" value?
;

StorCal    btfss    Store        ; Ready to store it?
    goto    GetCal

    call    MS512        ; Delay 0.5 sec

    btfss    Store        ; De-bounce
    goto    GetCal

    copy    Hold,AccB    ; Write EEPROM from AccB

    movlw    0x10        ; EEADR of Cal value
    call    EE_WR


;**********************************************************
;
;    Begin a new measurement cycle
;

newbit    movlw    0x10        ; EEADR of Cal value
    call    EE_RD        ; in AccB
    
    copy    AccB,Hold    ; Get timing "constant"

    call    HOME        ; Display ready

    clrf    SBflag        ; 0 = Lower BFO frequency
                ; 1 = Higher

    bcf    AMflag        ; 0 = No USB/LSB suffix

    bcf    Prg_FLG

    btfsc    Store        ; Doing "BFO STORE"?
    goto    GetOffs

    call    MS512        ; Delay 0.5 sec

    btfsc    Store        ; De-bounce
    goto    GetOffs

GetIf    call    Measure        ; Get freq in AccA:4

    copy    AccA,AccB    ; For EEPROM Writing

    call    Display        ; Display freq in AccA
    
    movlw    Prog        ; Say "we're programming"
    call    pmsg
    CALL    HOME

    btfss    Store        ; Ready to store it?
    goto    GetIf

    call    MS512        ; Delay 0.5 sec

    btfss    Store        ; De-bounce
    goto    GetIf

    bsf    Prg_FLG        ; Flag "to be stored"

GetOffs    btfss    BFO_Hi        ; Which Offset??
    goto    Get2        ; Point @ EEPROM

    btfss    BFO_Lo        ; 4 bytes each
    goto    Ch2        ; BFO low link only
    goto    Ch3        ; No links

Get2    btfss    BFO_Lo
    goto    Ch0        ; Both links
    goto    Ch1        ; BFO high link only

Ch0    movlw    0x00        ; Offset channel 0 (both links fitted)
    goto    EndOff

Ch1    bsf    AMflag        ; We're gunna print
    comf    SBflag,f    ; that BFO is on higher frequency
    movlw    0x04        ; Offset channel 1 (BFO_Hi link fitted)
    goto    EndOff

Ch2    bsf    AMflag        ; We're gunna print
                ; that BFO is on lower frequency
    movlw    0x08        ; Offset channel 2 (BFO_Lo link fitted)
    goto    EndOff

Ch3    movlw    0x0C        ; Offset channel 3 (no links fitted)
;    goto    EndOff

EndOff    btfsc    Prg_FLG        ; Storing Offset?
    goto    Do_St        ; If not, then

    call    EE_RD        ; must be reading.
    goto    Do_Meas

Do_St    call    EE_WR

;
;    Now have IF in AccB
;

Do_Meas    call    Measure        ; Measure Local Osc Freq.

;
;    Now have LO in "AccA"
;        and  IF in "AccB"
;

Add_Sub    btfss    Add_LO        ; Add or Sub LO freq?
    goto    AddLSB        ; Clear = just add

    call    MinusA        ; RF := |IF - LO|
                ; SBflag is OK

AddLSB    call    AplusB

;
;    Fix overflow. If negative then make positive
;

    btfss    AccA+0,7    ; Set? (=Overflow)
    goto    OK2go        ; Clear = OK 2 print
    
    call    MinusA        ; Make positive and
    comf    SBflag,f    ; Swap USB/LSB

;
;    Display resulting number in AccA
;

OK2go    call    Display        ; display result at last

;
;    Print suffix - USB, LSB or nuffin
;    Now disabled

    btfsc    AMflag        ; Do we print at all?
    goto    trySBf

    movlw    Spaces        ; nuffin = spaces
    goto    EndMsg

trySBf    btfsc    SBflag,0    ; Which sideband?
    goto    pLSB

    movlw    USB        ; USB obviously
    goto    EndMsg

pLSB    movlw    LSB        ; LSB
;    goto    EndMsg

EndMsg    call    pmsg        ; Print selected trailer


#ifdef    Two_Line

    CALL    LINE2        ; WRITE second LINE

    movlw    adv3
    call    pmsg
 endif

    goto    newbit        ; Start next measurement


;**********************************************************
;
;    AccA := AccA + AccB
;

AplusB    movf    AccB+3,W    ; Process LSB
    addwf    AccA+3,F
    bcc    Add_2        ; If no carry,do next

    incf    AccA+2,f    ; Else roll over higher
    bne    Add_2        ; bytes as appropriate

    incf    AccA+1,f
    bne    Add_2

    incf    AccA+0,f    ; may roll over MSByte
    
Add_2    movf    AccB+2,W    ; Process next byte
    addwf    AccA+2,F
    bcc    Add_1        ; If no carry,do next

    incf    AccA+1,f    ; Else roll over higher
    bne    Add_1        ; bytes as appropriate

    incf    AccA+0,f    ; may roll over MSByte
        
Add_1    movf    AccB+1,W    ; Process next byte
    addwf    AccA+1,F
    bcc    Add_0        ; If no carry,do next

    incf    AccA+0,f    ; may roll over MSByte
        
Add_0    movf    AccB+0,W    ; Process next byte
    addwf    AccA+0,F
    return


;**********************************************************
;
;    Negate number in AccA (2's complement form)
;

MinusA    comf    AccA+0,f    ; Complement all bits
    comf    AccA+1,f    ; of number
    comf    AccA+2,f
    comf    AccA+3,f
    
    incf    AccA+3,f    ; Add 1
    bne    N_xit
    incf    AccA+2,f
    bne    N_xit
    incf    AccA+1,f
    bne    N_xit
    incf    AccA+0,f

N_xit    return

;**********************************************************
;
;    Divide AccA:4 by 4
;
;**********************************************************

Div4    call    Div2        ; Divide AccA:4 by 4

;**********************************************************
;
;    Divide AccA:4 by 2
;
;**********************************************************

Div2    rrf    AccA+0,f
    rrf    AccA+1,f    
    rrf    AccA+2,f
    rrf    AccA+3,f
    bcf    AccA+0,7    ; Possible bad carry in.
    return

;**********************************************************
;
;    Multiply AccA:4 by 64
;
;**********************************************************

Mul64    call    Mul2
    call    Mul2
    call    Mul2
    call    Mul2
    call    Mul2        ; then fall through

;**********************************************************
;
;    Multiply AccA:4 by 2
;
;**********************************************************

Mul2    rlf    AccA+3,f
    rlf    AccA+2,f    
    rlf    AccA+1,f
    rlf    AccA+0,f
    bcf    AccA+3,0    ; Possible bad carry in.
    return
;**********************************************************
;
;    Print String addressed by W
;    Note: Strings are in program space
;

pmsg    movwf    pmsg_t        ; Temp for pointer

pm1    movf    pmsg_t,W    ; Get current pointer
    call    pmsub
    andlw    0xff        ; Test returned value
    beq    pm_end        ; NULL = All done
    call    DATS
    incf    pmsg_t,F
    goto    pm1

;**********************************************************
;
;    Delay for 1000ms (trimmed for actual clock freq)
;    Check for Timer register roll over and count 'em
;
;    Uses: W, COUUNT1, COUNT2, COUNT3 & others
;
;**********************************************************

MS1000    MOVF    Hold+0,w    ; 100 MS DELAY LOOP        
    MOVWF    COUNT1        ; 4 MHZ XTAL

    MOVF    Hold+1,w    ; Count up
    MOVWF    COUNT2        ; to 24 bit overflow

    MOVF    Hold+2,w
    MOVWF    COUNT3

L3    INCFSZ    COUNT3,F
    GOTO    L3
    
    call    RollOver    ; Check for Timer0 RollOver

    INCFSZ    COUNT2,F
    GOTO    L3

    INCFSZ    COUNT1,F
    GOTO    L3

    RETLW    0

;**********************************************************
;
;    SEND A COMMAND BYTE TO LCD DISPLAY MODULE    
;

STROBE    BCF    RS        ; SELECT COMMAND REGISTER
    GOTO    CM

;**********************************************************
;
;    Put a BCD nybble to display
;

PutNyb    ANDLW    0x0F        ; MASK OFF OTHER PACKED BCD DIGIT
    ADDLW    0x30        ; Convert BIN to ASCII

;**********************************************************
;
;    Put a data byte to display
;

DATS    movwf    TEMP        ; Save character for LCD
    call    putchr
    movf    TEMP,w
    
    BSF    RS        ; SELECT DATA REGISTER
CM    MOVWF    CHR        ; STORE CHAR TO DISPLAY
    SWAPF    CHR,W        ; SWAP UPPER AND LOWER NIBBLES (4 BIT MODE)

    call    PB_dly

    MOVF    CHR,W        ; GET CHAR AGAIN 

;**********************************************************
;
;    Put 4 bits to LCD & wait (untrimmed)
;

PB_dly    ANDLW    0x0F        ; MASK OFF UPPER 4 BITS
    MOVWF    PORTB        ; SEND DATA TO DISPLAY        
    BSF    ENA        ; ENA HIGH
    NOP            
    BCF    ENA        ; ENA LOW 
                ; Fall into 200us DELAY subroutine

;**********************************************************
;
;    Delay for 200us (untrimmed)
;
;    Uses: W, COUNT1
;
;**********************************************************

D200us
DELAY    MOVLW    0x42        ; DELAY 200us
    MOVWF    COUNT1    

NXT5    DECFSZ    COUNT1,F
    GOTO    NXT5    

    RETLW    0

;**********************************************************
;
;    Delay for 2ms (untrimmed)
;
;    Uses: W, COUNT2, COUNT1
;
;**********************************************************

MS2    MOVLW    0x0A        ; DELAY 2ms
    MOVWF    COUNT2

LP15    call    D200us

    DECFSZ    COUNT2,F
    GOTO    LP15

    RETLW    0        

;**********************************************************
;
;    Delay for 512ms (untrimmed)
;
;    Uses: W, COUNT3, COUNT2, COUNT1
;
;**********************************************************

MS512    clrw            ; 0 -> 256 loops

;**********************************************************
;
;    Delay for multiples of 2ms (untrimmed)
;
;    Uses: W, COUNT3, COUNT2, COUNT1
;
;**********************************************************

MS2xW    MOVWF    COUNT3    

LPx15    call    MS2

    DECFSZ    COUNT3,F
    GOTO    LPx15

    RETLW    0        

;******************************************************************
;
;    Convert 32-bit binary number at <AccA:4> into a bcd number
;    at <bcd:5>. Uses Mike Keitz's procedure for handling bcd 
;    adjust. Microchip AN526
;

B2_BCD

b2bcd    movlw    .32        ; 32-bits
    movwf    COUNT        ; make cycle counter

    clrf    bcd+0        ; clear result area
    clrf    bcd+1
    clrf    bcd+2
    clrf    bcd+3
    clrf    bcd+4
    
b2bcd2  movlw    bcd        ; make pointer
    movwf    FSR
    movlw    .5        ; Number of BCD bytes?
    movwf    cnt        ; 2 BCD digits per byte

; Mike's routine:

b2bcd3    movlw    0x33    
        addwf    INDF,f        ; add to both nybbles
        btfsc    INDF,3        ; test if low result > 7
        andlw    0xf0        ; low result >7 so take the 3 out
        btfsc    INDF,7        ; test if high result > 7
        andlw    0x0f        ; high result > 7 so ok
        subwf    INDF,f        ; any results <= 7, subtract back
        incf    FSR,f        ; point to next
        decfsz    cnt,f
        goto    b2bcd3
        
        rlf    AccA+3,f    ; get another bit
        rlf    AccA+2,f
        rlf    AccA+1,f
        rlf    AccA+0,f

        rlf    bcd+4,f        ; put it into bcd
        rlf    bcd+3,f
        rlf    bcd+2,f
        rlf    bcd+1,f
        rlf    bcd+0,f

        decfsz    COUNT,f        ; all done?
        goto    b2bcd2        ; no, loop
        return            ; yes


;*********** INITIALISE LCD MODULE 4 BIT MODE ***********************

LCDINIT    CALL    MS512        ; Wait 0.512 sec for LCD  RESET

    BCF    RS        ; REGISTER SELECT LOW
    BCF    ENA        ; ENABLE LINE LOW
    
    MOVLW    0x03        ; 1
    call    PB_dly
    
    CALL    MS512        ; WAIT FOR DISPLAY TO CATCH UP

    MOVLW    0x03        ; 2
    call    PB_dly

    MOVLW    0x03        ; 3
    call    PB_dly

    MOVLW    0x02        ; Fn set 4 bits
    call    PB_dly
    
    MOVLW    0x28        ; DISPLAY 2 Line , 5x7 Dot's
    CALL    STROBE        ; Suggested by PA0EJH
    CALL    DELAY        
    
    MOVLW    0x0C        ; 0x0C DISPLAY ON
    CALL    STROBE
    CALL    DELAY        
    
    MOVLW    0x06        ; 0x06 ENTRY MODE SET
    CALL    STROBE
    CALL    DELAY

    MOVLW    0x01        ; 0x01 CLEAR DISPLAY
    CALL    STROBE
    CALL    MS2

    RETLW    0


;************ MOVE TO START OF LINE 2 *****************

LINE2    MOVLW    0xC0        ; ADDRESS FOR SECOND LINE OF DISPLAY
    CALL    STROBE
    goto    DELAY


;************ CLEAR DISPLAY ***************************

CLEAR    MOVLW    0x01        ; COMMAND TO CLEAR DISPLAY
    CALL    STROBE
    goto    MS2        ; LONGER DELAY NEEDED WHEN CLEARING DISPLAY


;*********** MOVE TO HOME *****************************

HOME    call    crlf        ; Serial

    MOVLW    0x02        ; COMMAND TO HOME LCD DISPLAY
    CALL    STROBE
    goto    MS2


;********************************************************************
;       Initialise Input & Output devices
;********************************************************************

InitIO    bank1

    movlw    0x37        ; Option register
    movwf    OPTION_REG    ; Port B weak pull-up enabled
                ; INTDEG Don't care
                ; Count RA4/T0CKI
                ; Count on falling edge
                ; Prescale Timer/counter
                ; divide Timer/counter by 256

                ; PORTA:-
    movlw    0x02        ; initialise data direction
                ; 1 = input, 0 = output
                ;
                ; PORTA has 5 pins     4 3 2 1 0
                ; 0x02       =   0 0 0 0 0 0 1 0
                ;
    movwf    TRISA        ; PORTA<0>   = Serial + Debugging Out
                ; PORTA<1>   = FIXIT (input)
                ; PORTA<2>   = LCD "E" Out
                ; PORTA<3>   = LCD "RS" Out
                ; PORTA<4>   = "Input" with pull-down
                ;              Actually an output.
                ; PORTA<5:7> = not implemented in 16F84
                ;
                ; PORTB:-
    movlw    0xf0        ; initialise data direction
                ; PORTB has 8 pins
                ; port pin       7 6 5 4 3 2 1 0
                ; 0xf0       =   1 1 1 1 0 0 0 0
                ;
    movwf    TRISB        ; PORTB<0>   = LCD "DB4"
                ; PORTB<1>   =     "DB5"
                ; PORTB<2>   =     "DB6"
                ; PORTB<3>   =     "DB7"
                ; PORTB<4>   = Input
                ; PORTB<5>   = Input
                ; PORTB<6>   = Input
                ; PORTB<7>   = Input

    bank0

    return    

;**********************************************************
;
;    Measure Frequency. Stash in "AccA:4"
;

Measure    bcf    CLAMP        ; CLOSE GATE for safety

    bsf    PORTB,2        ; For compatibility with
    bsf    PORTB,3        ; Version 1 hardware
    
    bcf    INTCON,T0IF    ; Clear any previous overflow
  
    CLRF    TMR0        ; RESET INTERNAL COUNT (INCLUDING PRESCALER)
                ; See page 27 Section 6.0

    CLRF    AccA+0        ; Ready to receive 32 bit number
    CLRF    AccA+1
    CLRF    AccA+2
    CLRF    AccA+3

    bsf    CLAMP        ; OPEN GATE

    CALL    MS1000        ; 1.0 sec DELAY

    bcf    CLAMP        ; CLOSE GATE (COUNT COMPLETE)
    nop            ; and allow time for
    nop            ; the registers to catch up
    nop
    nop
    nop
    
    call    RollOver    ; Final check, just in case

    MOVF    TMR0,W        
    MOVWF    AccA+2

;    Now empty the prescaler

PSC1    bank1

    bcf    OPTION_REG,T0SE    ; Clock the prescaler
    nop
    bsf    OPTION_REG,T0SE

    bank0
    
    DECF    AccA+3,F    ; Decrement the counter
    
    movf    TMR0,W        ; Has TMR0 changed?
    xorwf    AccA+2,W    ; if unchanged, XOR -> 0

    beq    PSC1
        
; AccA : AccA+1 : AccA+2 : AccA+3 now holds 32 bit result
; Rollover subroutine has set AccA+0 and AccA+1 suitably.

    return

;**********************************************************
;
;    Account for TMR0 overflows when counting
;    Check at regular intervals and handle as
;    necessary.
;
;    Needs to be done at less than 936us (@ 70MHz in)
;    intervals, or else it can lose counts.
;

RollOver

    btfss    INTCON,T0IF    ; Rolled over?
    goto    RO3        ; No

RO1    bcf    INTCON,T0IF    ; Yes. ACK!

    INCF    AccA+1,f    ; Count it
    bne    RO2        ; Overflowed?

    incf    AccA+0,f    ; No need to check

RO2    return

;    Balance path lengths

RO3    nop
    nop
    goto    RO2

;**********************************************************
;
;    Display frequency
;
;    Display contents of AccA+0...AccA+3 on LCD
;    First convert to BCD, Then ASCII (nybble at a time)
;
;    In this version, multiply ACCA:4 by 64 since gate
;    time = 1.0 second and ext prescale=64
;

Display    btfsc    PSC        ; 1 = prescaler active = *64        

    call    Mul64        ; Account for prescaler

    CALL    B2_BCD        ; CONVERT all AccA TO BCD

;    Perform Leading Zero Blanking on first 3 digits

    swapf    bcd+0,W        ; 1000's of MHz
    andlw    0x0F        ; MASK OFF OTHER PACKED BCD DIGIT
    bne    NoB1K

    MOVLW    0x20        ; YES PRINT A BLANK SPACE
    CALL    DATS

    movf    bcd+0,W        ; 100's of MHz
    andlw    0x0F        ; MASK OFF OTHER PACKED BCD DIGIT
    bne    NoB100

    MOVLW    0x20        ; YES PRINT A BLANK SPACE
    CALL    DATS

    swapf    bcd+1,W        ; 10's of MHz
    andlw    0x0F        ; MASK OFF OTHER PACKED BCD DIGIT
    bne    NoB10

    MOVLW    0x20        ; YES PRINT A BLANK SPACE
    CALL    DATS

    goto    NoB1

;    Handle rest of number non blanked

NoB1K    SWAPF    bcd+0,W        ; 1000's of MHz
    CALL    PutNyb

NoB100    MOVF    bcd+0,W        ; 100's of MHz
    CALL    PutNyb

NoB10    SWAPF    bcd+1,W        ; 10's of MHz
    CALL    PutNyb

NoB1    MOVF    bcd+1,W        ; 1's of MHz
    CALL    PutNyb

    MOVLW    '.'        ; Decimal Point
    CALL    DATS

    SWAPF    bcd+2,W        ; 100's of KHz
    CALL    PutNyb

    MOVF    bcd+2,W        ; 10's of KHz
    CALL    PutNyb

    SWAPF    bcd+3,W        ; 1's of KHz
    CALL    PutNyb

    CALL    LINE2
    
    MOVF    bcd+3,W        ; 100's of Hz
    CALL    PutNyb

    SWAPF    bcd+4,W        ; 10's of Hz
    CALL    PutNyb

    MOVF    bcd+4,W        ; 1's of Hz
    CALL    PutNyb

    movlw    mhz        ; WRITE " Mhz" AT end OF LINE
    goto    pmsg        ; includes RETURN


;********************************************************************
;    Read EEPROM into "AccB"  (AccB must be visible in both
;    W -> memory to read          memory banks 0 & 1)
;********************************************************************    

EE_RD

#ifdef    F628
    bank1
#endif

    MOVWF    EEADR        ; Address to read

#ifdef    F628
    bank0
#endif
    
    XORLW    0x0C        ; Special case (no links)
    BEQ    AVERAGE

    CALL    EE_R
    MOVWF    AccB+0

    CALL    EE_Rinc
    MOVWF    AccB+1

    CALL    EE_Rinc
    MOVWF    AccB+2

    CALL    EE_Rinc
    MOVWF    AccB+3

    RETURN

;--------------------------------------------------------------------

#ifdef F84

EE_Rinc    INCF    EEADR,F        ; bump address

EE_R    bank1
    BSF    EECON1,RD    ; EE Read
    bank0
    MOVF    EEDATA,W    ; W = EEDATA

    RETURN
#endif

;--------------------------------------------------------------------

#ifdef    F628

EE_Rinc    bank1
    INCF    EEADR,F        ; bump address

EE_R    bank1
    BSF    EECON1,RD    ; EE Read
    MOVF    EEDATA,W    ; W = EEDATA
    bank0

    RETURN
#endif

;--------------------------------------------------------------------

AVERAGE    movlw    0x04        ; AM - use avg BFO freq.
    call    EE_RD        ; Read in one BFO freq
    copy    AccB,AccA    ; Into AccA

    movlw    0x08        ; Then second
    call    EE_RD        ; into AccB

    call    AplusB        ; Add 'em
    call    Div2        ; get average in AccA
    copy    AccA,AccB    ; and in AccB
    return
    

;********************************************************************
;    Write EEPROM from "AccB"  (AccB must be visible in both
;    W -> memory to write          memory banks 0 & 1)
;********************************************************************    

#ifdef    F84

EE_WR    MOVWF    EEADR        ; Address to write

    MOVF    AccB+0,W    ; Data byte #0
    CALL    EE_W

    MOVF    AccB+1,W    ; Data byte #1
    CALL    EE_Winc

    MOVF    AccB+2,W    ; Data byte #2
    CALL    EE_Winc

    MOVF    AccB+3,W    ; Data byte #3
    CALL    EE_Winc

    RETURN

EE_Winc    INCF    EEADR,F        ; bump address
    
EE_W    MOVWF    EEDATA
    bank1
    BSF    EECON1,WREN    ; Enable Write
    MOVLW    0x55        ;
    MOVWF    EECON2        ; Write 0x55
    MOVLW    0xAA        ;
    MOVWF    EECON2        ; Write 0xAA
    BSF    EECON1,WR    ; Set WR bit (begin write)

EE_W2    BTFSC    EECON1,WR    ; Wait for write to finish
    GOTO    EE_W2

    BCF    EECON1,EEIF    ; clear interrupts
    bank0

    RETURN    

#endif

;--------------------------------------------------------------------

#ifdef    F628

EE_WR    bank1
    MOVWF    EEADR        ; Address to write

    MOVF    AccB+0,W    ; Data byte #0
    CALL    EE_W

    MOVF    AccB+1,W    ; Data byte #1
    CALL    EE_Winc

    MOVF    AccB+2,W    ; Data byte #2
    CALL    EE_Winc

    MOVF    AccB+3,W    ; Data byte #3
    CALL    EE_Winc

    bank0
    RETURN

    errorlevel    -302    ; In Bank 2

EE_Winc    INCF    EEADR,F        ; bump address
    
EE_W    MOVWF    EEDATA
    BSF    EECON1,WREN    ; Enable Write
    MOVLW    0x55        ;
    MOVWF    EECON2        ; Write 0x55
    MOVLW    0xAA        ;
    MOVWF    EECON2        ; Write 0xAA
    BSF    EECON1,WR    ; Set WR bit (begin write)

EE_W2    BTFSC    EECON1,WR    ; Wait for write to finish
    GOTO    EE_W2

    bank0
    BCF    PIR1,EEIF    ; clear interrupts
    bank1
    RETURN    

    errorlevel    +302
#endif


;********************************************************************
;    Testing counter 
;********************************************************************    

ctest    movlw    0xfe        ; MS byte of loop count
    movwf    COUNT3        ; Counted upward till it overflows

    movlw    0x1d
    movwf    COUNT2

    movlw    0xc0
    movwf    COUNT1

cloop    bcf    PUFF        ; Toggle counter input once
    bsf    PUFF

    incfsz    COUNT1,f
    goto    cloop

    incfsz    COUNT2,f
    goto    cloop

    incfsz    COUNT3,f
    goto    cloop

    return

;***********************************************************************
;
;    Debugging Memory & Register dump
;

debug
    MOVWF    D_Wtemp        ; Copy W to temp register,
    SWAPF    STATUS,W    ; Swap status to be saved into W
    MOVWF    D_Stemp        ; Save status to D_Stemp register
    movf    FSR,W        ; Save FSR
    movwf    D_FSR
    
    movlw    0x57        ; W=
    call    putchr
    movlw    0x3d
    call    putchr

    movf    D_Wtemp,w
    call    hex_2
    
    movlw    0x20        ; 2 spaces, just to be neat
    call    putchr
    movlw    0x20
    call    putchr
    
    movlw    0x53        ; SR=
    call    putchr
    movlw    0x52
    call    putchr
    movlw    0x3d
    call    putchr

    movf    D_Stemp,w
    call    hex_2
    
    call    crlf        ; Serial

    clrf    FSR        ; Ready for memory dump

D_loop    movf    0,W        ; Read indirect
    call    hex_2
    movlw    0x20
    call    putchr
    incf    FSR,f        ; to next byte

    movf    FSR,w        ; end of line?
    andlw    0x0F
    bne    next_ln

    call    crlf
    bra    chk4end

next_ln    andlw    0x03        ; Groups of 4
    bne    chk4end

    movlw    0x20
    call    putchr

chk4end    movf    FSR,w        ; All done?
    xorlw    0x80
    bne    D_loop

    call    crlf
    call    crlf
    
    movf    D_FSR,W        ; Restore FSR
    movwf    FSR
    
    SWAPF    D_Stemp,W    ; Swap nibbles in D_Stemp register
                ; and place result into W

    MOVWF    STATUS        ; Move W into STATUS register
                ; (sets bank to original state)
    SWAPF    D_Wtemp,F    ; Swap nibbles in D_Wtemp and place result in D_Wtemp
    SWAPF    D_Wtemp,W    ; Swap nibbles in D_Wtemp and place result into W
    
    return

    
;***********************************************************************
;
;    Print CRLF to serial
;

crlf    movlw    0x0d        ; CRLF
    call    putchr
    movlw    0x0a
    goto    putchr

;***********************************************************************
;
;    Print W as 2 Hex digits
;

hex_2    movwf    D_hex
    swapf    D_hex,w        ; Get big bit
    call    hex_3

    movf    D_hex,w        ; Get little bit

hex_3    andlw    0x0f        ; keep bottom 4 bits
    addlw    0xF6
    bcc    hex_4
    addlw    0x07        ; binary A -> ASCII A
hex_4    addlw    0x3A        ; binary 0 -> ASCII 0
;    goto    putchr

;********************************************************
;
;    Output Routines for PIC16F84
;    
;    Clock is 4.0 MHz.
;    ie. 1.0 us per cycle = 4/Fosc.
;
;    9600 Baud  = 104.17 us
;               = 104.17   CPU cycles
;
;********************************************************
;
;    Output the character in W. Assumes Mac is ready.
;       
;    Uses W
;

putchr    movwf    S_Wtemp        ; Character being output

    movlw    0x08        ; Bit count
    movwf    S_count

    bcf    S_out        ; Send a 0 - Start bit

put_clp    movlw    0xE7        ; Delay "104" cycles
txd_0    addlw    0x01
    bne    txd_0

    rrf    S_Wtemp,f    ; Transmit a bit
    bcs    t_0

    bcf    S_out        ; Send a 0
    bra    tx_1

t_0    bsf    S_out        ; Send a 1

tx_1    decfsz    S_count,f    ; Done all bits?
    goto    put_clp

    movlw    0xE7        ; Delay for last data
txd_1    addlw    0x01
    bne    txd_1

    bsf    S_out        ; Transmit two stop bit

    movlw    0xCD
txd_9    addlw    0x01
    bne    txd_9
    
    return
 
;********************************************************************
;    Tail End Charlie
;********************************************************************    
; initialize eeprom locations

        ORG 0x2100

        DE  0x00, 0x00, 0x00, 0x00    ; Unused (reserved for later)
        DE  0x00, 0x00, 0x00, 0x00    ; IF Offset 1 Low  BFO ????
        DE  0x00, 0x00, 0x00, 0x00    ; IF Offset 2 High BFO ????
        DE  0x00, 0x00, 0x00, 0x00    ; IF Offset 3 No   BFO -AM-
        DE  0xfa, 0xff, 0x5f, 0x00    ; 4.000 MHz initial calibration


     END
```


----------



## miguelus (Oct 31, 2013)

Buenos días trifocar.

En la página del proyecto del Frecuecímetro tienes el ASM de las versiónes para /20 y /64, si comparas ambos ASM verás las diferencias que hay entre ambas

*Div/64...*


```
[I];**********************************************************
;
;    Divide AccA:4 by 4
;
;**********************************************************

Div4    call    Div2        ; Divide AccA:4 by 4

;**********************************************************
;
;    Divide AccA:4 by 2
;
;**********************************************************

Div2    rrf    AccA+0,f
    rrf    AccA+1,f    
    rrf    AccA+2,f
    rrf    AccA+3,f
    bcf    AccA+0,7    ; Possible bad carry in.
    return

;**********************************************************
;
;    Multiply AccA:4 by 64
;
;**********************************************************

Mul64    call    Mul2
    call    Mul2
    call    Mul2
    call    Mul2
    call    Mul2        ; then fall through

;**********************************************************
;
;    Multiply AccA:4 by 2
;
;**********************************************************

Mul2    rlf    AccA+3,f
    rlf    AccA+2,f    
    rlf    AccA+1,f
    rlf    AccA+0,f
    bcf    AccA+3,0    ; Possible bad carry in.
    return
;**********************************************************
;
;    Print String addressed by W
;    Note: Strings are in program space
;

pmsg    movwf    pmsg_t        ; Temp for pointer

pm1    movf    pmsg_t,W    ; Get current pointer
    call    pmsub
    andlw    0xff        ; Test returned value
    beq    pm_end        ; NULL = All done
    call    DATS
    incf    pmsg_t,F
    goto    pm1[/I]

[B]Div/20[/B]

[I];**********************************************************
;
;    Divide AccA:4 by 4
;
;**********************************************************

Div4    call    Div2        ; Divide AccA:4 by 4

;**********************************************************
;
;    Divide AccA:4 by 2
;
;**********************************************************

Div2    rrf    AccA+0,f
    rrf    AccA+1,f    
    rrf    AccA+2,f
    rrf    AccA+3,f
    bcf    AccA+0,7    ; Possible bad carry in.
    return

;**********************************************************
;
;    Multiply AccA:4 by 20
;
;    AccA = (AccA*4 + AccA) * 4
;
;**********************************************************

Mul20    call    S_push        ; Copy AccA into AccB
    call    Mul2        ; x2
    call    Mul2        ; x4
    call    AplusB        ; x5
    call    Mul2        ; x10
    call    Mul2        ; x20
    return

;**********************************************************
;
;    Multiply AccA:4 by 64
;
;**********************************************************

Mul64    call    Mul2
    call    Mul2
    call    Mul2
    call    Mul2
    call    Mul2        ; then fall through

;**********************************************************
;
;    Multiply AccA:4 by 2
;
;**********************************************************

Mul2    rlf    AccA+3,f
    rlf    AccA+2,f    
    rlf    AccA+1,f
    rlf    AccA+0,f
    bcf    AccA+3,0    ; Possible bad carry in.
    return

;**********************************************************
;
;    Push Copy of AccA into AccB
;

S_push    copy    AccA,AccB
    return[/I]
```

Comparando ambas rutinas es posible llegar a alguna conclusión 

Si únicamente vas a utilizar el Frecuecímetro con el Divisor /256 puedes cambiar el Cristal por uno de 1Mhz y utilizar la versión /64 y ver que pasa.

Sal U2


----------



## trifoncar (Oct 31, 2013)

Gracias Miguelus,

 la verdad es que ya me había fijado e incluso había intentado encontrar -por diferencias- una solución rápida, pero no le dediqué mucho tiempo y abandoné enseguida.

Ahora que me lo has puesto un poco más fácil con tu comentario, lo voy a intentar con un poco más de calma.

Gracias de nuevo.

Un saludo

P.D. He probado el frecuencímetro con el prescaler MB506 /64 y funciona perfectamente a 100 y a 446 Mhz que son las dos únicas pruebas que he efectuado.


----------



## trifoncar (Oct 31, 2013)

Hola de nuevo,

he estado pegándome con el código asm y no avanzo. Supongo que en realidad -al ser cuatro registros de 8 bytes (creo que Acca) cada uno- debería de ser avanzar los valores e cada registro al registro anterior en las mismas posiciones, pero no sé como llevarlo a cabo.

¿Alguien puede indicarme cuales son las modificaciones que debo de efectuar para cambiar el archivo original que divide por 64 a uno nuevo que divida por 256?

La verdad es que si pido ayuda aquí es porque -para efectuar ese pequeño paso- considero que no me compensa dedicar unos meses a aprender a programar. 

Muchas gracias


----------



## ricbevi (Oct 31, 2013)

trifoncar dijo:


> Hola de nuevo,
> 
> he estado pegándome con el código asm y no avanzo. Supongo que en realidad -al ser cuatro registros de 8 bytes (creo que Acca) cada uno- debería de ser avanzar los valores e cada registro al registro anterior en las mismas posiciones, pero no sé como llevarlo a cabo.
> 
> ...



Hola...Yo no se mucho de programación en asembler pero por que no probas con esta modificación en la multiplicación a ver si es así(mientras aparece alguien con conocimiento en el tema dispuesto a ayudar). 
Saludos.
Ric.


```
;*******************************************************************
;
;    "Digital" Frequency display with /64 prescaler & no offsets
;
;    Crystal freq. = 4.000MHz +/- a bit
;
;*******************************************************************
;
;    First, let us choose our weapon - 16F84 or 16F628
;

;    Comment out the next line [;#define F84] if using a 16F628

#define    F84

#ifndef    F84
    #define    F628
#endif


;*******************************************************************
;
;    Some Testing Stuff(tm)
;

;#define    testing        1    ; Comment out when testing finished

;#define    Two_Line    1    ; Un-comment for two line displays


;************************ REVISION HISTORY *************************
;
;    FM1.000    Originally from FM3/4 9:39pm 14 May 2002
;        As implemented in experimental 3.5MHz receiver
;
;*******************************************************************
;
;    FM1.003    Fixed? major silliness in LO-IF code
;        Re-wrote USB/LSB suffix code
;        Added #defines for crook displays
;        Added #defines for two line displays
;        Wrapped #ifdef ... endif around debugging code
;
;*******************************************************************
;
;    FM1.004    Added code to allow user to fix crook display
;        Deleted #defines for crook displays
;        Pin 18 is now input. 1 = good display, 0 = crook
;
;*******************************************************************
;
;    FM2.000    New Hardware! Deleted external counter & gating
;        Now uses the same scheme as the LC Meter, with the
;        third byte of the count implemented in the PIC.
;        Basically, the "output" of the timer register is
;        counted within the gate timing loop.
;
;*******************************************************************
;
;    FM2.001    Discovered that I don't need to use RA0 as a gate
;        cos RA4 can be used as a timer input, even when
;        defined as an output - all that is required is to
;        set it high to count or low to inhibit.
;        Jeez, Microchip are smart arses.
;        I dunno why I didn't spot this long ago.
;        (Can't be used on the LC Meter, cos its oscillator
;        needs to be clamped HIGH, not low as in this case).
;
;*******************************************************************
;
;    FM2.002    Added 9600 baud serial output via RA0
;
;*******************************************************************
;
;    FM2.003    Rewrote RollOver subroutine to use INTCON,T0IF bit.
;        Incorporated two bits from OvrFlow counter
;        to extend range to over 80MHz.
;
;*******************************************************************
;
;    FM2.004    Changed to 32 bit counting.
;
;*******************************************************************
;
;    FM2.005    Added "Calibrate" mode.
;
;*******************************************************************
;
;    FM2.006    Moved "divide by 4" to increase resolution of
;        the stored IF offsets
;
;*******************************************************************
;
;    FM2.007    Moved "check for rollover" out of the inner MS400
;        timing loop and adjusted loop count appropriately
;        The aim - to improve the resolution of the software
;        calibration by a factor of around 13 to 15 times.
;
;*******************************************************************
;
;    fm2b.007    Ported to 16F628
;    FM2c.007    Introduced macros
;    fm2.008        Renumbered
;
;*******************************************************************
;
;    fm2.009        Cleaned up AM IF Offset calculation
;            Converted some inline code to subroutines
;            Created new 32 bit "copy" macro
;            Adjusted calibration slightly
;            Added a "Processor =" message
;            Removed advertising.
;
;*******************************************************************
;
;    ghzfm.000    Added multiply by 64
;            Rendered offsets ineffective
;            changed display format to
;            xxxx.xxxxxx MHz
;            Gate time now 1.000 Second
;
;
;
;*******************************************************************
;o-----o-----o-----o-----o-----o-----o-----o-----o-----o-----o-----o
;*******************************************************************
;
;    Some frequently used code fragments
;    Use macros to make mistreaks consistently.
;
;-------------------------------------------------------------------
;    Select Register Bank 0

bank0    macro
    errorlevel    +302        ; Re-enable bank warning
    bcf        STATUS,RP0    ; Select Bank 0
    endm

;-------------------------------------------------------------------
;    Select Register Bank 1

bank1    macro
    bsf        STATUS,RP0    ; Select Bank 1
    errorlevel    -302        ; disable warning
    endm

;-------------------------------------------------------------------
;    Copy a 32 bit thing from one place to another

copy    macro    from,to

    movf    from+0,W
    movwf    to+0

    movf    from+1,W
    movwf    to+1

    movf    from+2,W
    movwf    to+2

    movf    from+3,W
    movwf    to+3

    endm

;*******************************************************************
;
;    CPU configuration
;

#ifdef    F84
    MESSG        "Processor = 16F84"
    #define     RAMStart    0x0C    ; by VK3BHR
    processor    16f84
    include        <p16f84.inc>
    __config    _HS_OSC & _PWRTE_ON & _WDT_OFF
#endif

#ifdef    F628
    MESSG        "Processor = 16F628"
    #define     RAMStart    0x20
    processor    16f628
    include        <p16f628.inc>
    __config    _HS_OSC & _PWRTE_ON & _WDT_OFF & _CP_OFF & _BODEN_ON & _LVP_OFF
#endif

;*******************************************************************
;
;    I/O configuration
;


#define S_out    PORTA,0x00    ; 9600 baud serial out
#define PUFF    PORTA,0x00    ; Testing counter out

;#define    FIXIT    PORTA,0x01    ; 1 = "good display"
                ; 0 = do CRLF at "chr 8"

#define    PSC    PORTA,0x01    ; 1 = multiply by 64
                
#define    ENA    PORTA,0x02    ; Display "E"
#define    RS    PORTA,0x03    ; Display "RS"
#define    CLAMP    PORTA,0x04    ; Pull-down the timer input

#define    Store    PORTB,0x04    ; Pin 10, 0 = Measure BFO
#define    Add_LO    PORTB,0x05    ; Pin 11, 0 = RF := LO + IF
                ;         1 = RF := | LO + (-IF) |
#define    BFO_Lo    PORTB,0x06    ; Pin 12, 0 = BFO on lower freq.
#define    BFO_Hi    PORTB,0x07    ; Pin 13, 0 = BFO on higher freq.

#define    Prg_FLG    FLAGS,0x05
#define    AMflag    FLAGS,0x03    ; 0 = Don't print USB/LSB suffix

#define    beq    bz        ; Motorola syntax branches
#define    BEQ    bz
#define    BNE    bnz
#define    bne    bnz

#define    BCC    bnc
#define    bcc    bnc
#define    BCS    bc
#define    bcs    bc

#define    BRA    goto
#define    bra    goto

;*******************************************************************
;
;    file register declarations: uses only registers in bank0
;    bank 0 file registers begin at 0x20 in the 16F628
;
;*******************************************************************

    cblock    RAMStart

    dbg0:4            ; Debugging stuff
    dbg1:4
    dbg2:4
    dbg3:4
    dbg4:4
    dbg5:4


    bcd:5            ; BCD, MSD first 

    SBflag            ; 0 = Lower BFO frequency
                ; 1 = Higher

    COUNT            ; Bin to BCD convert (bit count)
    cnt            ;                    (BCD BYTES)


    CHR
    TEMP            ; DATS/Putchr temporary
    pmsg_t            ; Used by PMSG

    FLAGS

    S_Wtemp            ; "debug" Variables
    S_count
    D_Wtemp
    D_Stemp
    D_FSR
    D_hex
    
    endc

#ifdef    F84
Part2    equ    D_hex+1        ; Just tack on end
#endif

#ifdef    F628
Part2    equ    0x70        ; $70-7F Visible from all banks
#endif

    cblock    Part2

    COUNT1            ; Used by delay routines
    COUNT2            ; Timing (100ms)
    COUNT3            ; Timing (100ms)
    COUNT4            ; Timing (400ms)

    AccA:4            ; Binary, MSByte first

    AccB:4            ; Intermediate frequency

    Hold:4            ; Used in "cal" mode

    endc

;**********************************************************
;
;    Begin Executable Stuff(tm)
;

    org    0

GO    clrwdt            ; 0 << Reset
    clrf    INTCON        ; 1 No interrupts

#ifdef    F628
    movlw    0x07        ; 2 Comparator off
    movwf    CMCON        ; 3
#endif

    goto    START        ; 4 << Interrupt.

;**********************************************************
;
;    Part of string printer
;

pmsub    movwf    PCL        ; Goto W
    nop            ; Just in case
pm_end    return

;**********************************************************
;
;    Text Strings (stored in RETLWs)
;

mhz    dt    " MHz",0
Spaces    dt    " ",0
USB    dt    "U",0
LSB    dt    "L",0
Prog    dt    "P",0
Cal    dt    "C",0

#ifdef    Two_Line

adv3    dt    "1234567890ABCDEF",0

 endif

;**********************************************************
;
;    Main Program
;

START    call    InitIO        ; INITIALISE PORTS
    CLRF    PORTA
    CLRF    PORTB
    bsf    S_out        ; Serial output to idle
    
    CALL    LCDINIT         ; INITIALIZE LCD MODULE    

;    MOVLW    adv1        ; Sign on
;    call    pmsg

;    btfss    FIXIT        ; Test input 1 = just return
;    CALL    LINE2        ; 0 = fix bad display

;    movlw    adv2
;    call    pmsg
    
;    CALL    MS512        ; Delay for about 1 sec.
;    CALL    MS512        ; 0.512 sec x 2

    CALL    CLEAR

;**********************************************************
;
;    Check if in "Calibrate" mode
;

    btfsc    Store        ; If grounded initially
    goto    newbit        ; then were in "cal"

    MOVLW    0xfa        ; Set initial counter        
    MOVWF    Hold+0        ; value

    MOVLW    0xff        ; 
    MOVWF    Hold+1        ; for a 4 MHZ XTAL

    MOVLW    0x5f
    MOVWF    Hold+2            

    MOVLW    0x00        ; Unused
    MOVWF    Hold+3            

GetCal    call    Measure    
    call    Display
    movlw    Cal        ; Say "we're calibrating"
    call    pmsg
    CALL    HOME

;
;    Adjust Cal value
;

cal_dn    btfsc    BFO_Lo
    goto    cal_up
    
    incf    Hold+2,f    ; Add 1
    bne    inc_xit
    incf    Hold+1,f
    bne    inc_xit
    incf    Hold+0,f
inc_xit    goto    StorCal

cal_up    btfsc    BFO_Hi
    goto    StorCal

;
;    Hold := Hold + (1-)    ; Subtract 1
;

Hadd_2    movlw    0xff        ; Process LS byte
    addwf    Hold+2,F
    bcc    Hadd_1        ; If no carry,do next

    incf    Hold+1,f    ; Else roll over higher
    bne    Hadd_1        ; bytes as appropriate

    incf    Hold+0,f    ; may roll over MSByte
        
Hadd_1    movlw    0xff        ; Process next byte
    addwf    Hold+1,F
    bcc    Hadd_0        ; If no carry,do next

    incf    Hold+0,f    ; may roll over MSByte
        
Hadd_0    movlw    0xff        ; Process next byte
    addwf    Hold+0,F

;
;    Time to save "Cal" value?
;

StorCal    btfss    Store        ; Ready to store it?
    goto    GetCal

    call    MS512        ; Delay 0.5 sec

    btfss    Store        ; De-bounce
    goto    GetCal

    copy    Hold,AccB    ; Write EEPROM from AccB

    movlw    0x10        ; EEADR of Cal value
    call    EE_WR


;**********************************************************
;
;    Begin a new measurement cycle
;

newbit    movlw    0x10        ; EEADR of Cal value
    call    EE_RD        ; in AccB
    
    copy    AccB,Hold    ; Get timing "constant"

    call    HOME        ; Display ready

    clrf    SBflag        ; 0 = Lower BFO frequency
                ; 1 = Higher

    bcf    AMflag        ; 0 = No USB/LSB suffix

    bcf    Prg_FLG

    btfsc    Store        ; Doing "BFO STORE"?
    goto    GetOffs

    call    MS512        ; Delay 0.5 sec

    btfsc    Store        ; De-bounce
    goto    GetOffs

GetIf    call    Measure        ; Get freq in AccA:4

    copy    AccA,AccB    ; For EEPROM Writing

    call    Display        ; Display freq in AccA
    
    movlw    Prog        ; Say "we're programming"
    call    pmsg
    CALL    HOME

    btfss    Store        ; Ready to store it?
    goto    GetIf

    call    MS512        ; Delay 0.5 sec

    btfss    Store        ; De-bounce
    goto    GetIf

    bsf    Prg_FLG        ; Flag "to be stored"

GetOffs    btfss    BFO_Hi        ; Which Offset??
    goto    Get2        ; Point @ EEPROM

    btfss    BFO_Lo        ; 4 bytes each
    goto    Ch2        ; BFO low link only
    goto    Ch3        ; No links

Get2    btfss    BFO_Lo
    goto    Ch0        ; Both links
    goto    Ch1        ; BFO high link only

Ch0    movlw    0x00        ; Offset channel 0 (both links fitted)
    goto    EndOff

Ch1    bsf    AMflag        ; We're gunna print
    comf    SBflag,f    ; that BFO is on higher frequency
    movlw    0x04        ; Offset channel 1 (BFO_Hi link fitted)
    goto    EndOff

Ch2    bsf    AMflag        ; We're gunna print
                ; that BFO is on lower frequency
    movlw    0x08        ; Offset channel 2 (BFO_Lo link fitted)
    goto    EndOff

Ch3    movlw    0x0C        ; Offset channel 3 (no links fitted)
;    goto    EndOff

EndOff    btfsc    Prg_FLG        ; Storing Offset?
    goto    Do_St        ; If not, then

    call    EE_RD        ; must be reading.
    goto    Do_Meas

Do_St    call    EE_WR

;
;    Now have IF in AccB
;

Do_Meas    call    Measure        ; Measure Local Osc Freq.

;
;    Now have LO in "AccA"
;        and  IF in "AccB"
;

Add_Sub    btfss    Add_LO        ; Add or Sub LO freq?
    goto    AddLSB        ; Clear = just add

    call    MinusA        ; RF := |IF - LO|
                ; SBflag is OK

AddLSB    call    AplusB

;
;    Fix overflow. If negative then make positive
;

    btfss    AccA+0,7    ; Set? (=Overflow)
    goto    OK2go        ; Clear = OK 2 print
    
    call    MinusA        ; Make positive and
    comf    SBflag,f    ; Swap USB/LSB

;
;    Display resulting number in AccA
;

OK2go    call    Display        ; display result at last

;
;    Print suffix - USB, LSB or nuffin
;    Now disabled

    btfsc    AMflag        ; Do we print at all?
    goto    trySBf

    movlw    Spaces        ; nuffin = spaces
    goto    EndMsg

trySBf    btfsc    SBflag,0    ; Which sideband?
    goto    pLSB

    movlw    USB        ; USB obviously
    goto    EndMsg

pLSB    movlw    LSB        ; LSB
;    goto    EndMsg

EndMsg    call    pmsg        ; Print selected trailer


#ifdef    Two_Line

    CALL    LINE2        ; WRITE second LINE

    movlw    adv3
    call    pmsg
 endif

    goto    newbit        ; Start next measurement


;**********************************************************
;
;    AccA := AccA + AccB
;

AplusB    movf    AccB+3,W    ; Process LSB
    addwf    AccA+3,F
    bcc    Add_2        ; If no carry,do next

    incf    AccA+2,f    ; Else roll over higher
    bne    Add_2        ; bytes as appropriate

    incf    AccA+1,f
    bne    Add_2

    incf    AccA+0,f    ; may roll over MSByte
    
Add_2    movf    AccB+2,W    ; Process next byte
    addwf    AccA+2,F
    bcc    Add_1        ; If no carry,do next

    incf    AccA+1,f    ; Else roll over higher
    bne    Add_1        ; bytes as appropriate

    incf    AccA+0,f    ; may roll over MSByte
        
Add_1    movf    AccB+1,W    ; Process next byte
    addwf    AccA+1,F
    bcc    Add_0        ; If no carry,do next

    incf    AccA+0,f    ; may roll over MSByte
        
Add_0    movf    AccB+0,W    ; Process next byte
    addwf    AccA+0,F
    return


;**********************************************************
;
;    Negate number in AccA (2's complement form)
;

MinusA    comf    AccA+0,f    ; Complement all bits
    comf    AccA+1,f    ; of number
    comf    AccA+2,f
    comf    AccA+3,f
    
    incf    AccA+3,f    ; Add 1
    bne    N_xit
    incf    AccA+2,f
    bne    N_xit
    incf    AccA+1,f
    bne    N_xit
    incf    AccA+0,f

N_xit    return

;**********************************************************
;
;    Divide AccA:4 by 4
;
;**********************************************************

Div4    call    Div2        ; Divide AccA:4 by 4

;**********************************************************
;
;    Divide AccA:4 by 2
;
;**********************************************************

Div2    rrf    AccA+0,f
    rrf    AccA+1,f    
    rrf    AccA+2,f
    rrf    AccA+3,f
    bcf    AccA+0,7    ; Possible bad carry in.
    return

;**********************************************************
;
;    Multiply AccA:4 by 64
;
;**********************************************************

Mul64    call    Mul2
    call    Mul2
    call    Mul2
    call    Mul2
    call    Mul2        ; then fall through
    call    Mul2
    call    Mul2
    
;**********************************************************
;
;    Multiply AccA:4 by 2
;
;**********************************************************

Mul2    rlf    AccA+3,f
    rlf    AccA+2,f    
    rlf    AccA+1,f
    rlf    AccA+0,f
    bcf    AccA+3,0    ; Possible bad carry in.
    return
;**********************************************************
;
;    Print String addressed by W
;    Note: Strings are in program space
;

pmsg    movwf    pmsg_t        ; Temp for pointer

pm1    movf    pmsg_t,W    ; Get current pointer
    call    pmsub
    andlw    0xff        ; Test returned value
    beq    pm_end        ; NULL = All done
    call    DATS
    incf    pmsg_t,F
    goto    pm1

;**********************************************************
;
;    Delay for 1000ms (trimmed for actual clock freq)
;    Check for Timer register roll over and count 'em
;
;    Uses: W, COUUNT1, COUNT2, COUNT3 & others
;
;**********************************************************

MS1000    MOVF    Hold+0,w    ; 100 MS DELAY LOOP        
    MOVWF    COUNT1        ; 4 MHZ XTAL

    MOVF    Hold+1,w    ; Count up
    MOVWF    COUNT2        ; to 24 bit overflow

    MOVF    Hold+2,w
    MOVWF    COUNT3

L3    INCFSZ    COUNT3,F
    GOTO    L3
    
    call    RollOver    ; Check for Timer0 RollOver

    INCFSZ    COUNT2,F
    GOTO    L3

    INCFSZ    COUNT1,F
    GOTO    L3

    RETLW    0

;**********************************************************
;
;    SEND A COMMAND BYTE TO LCD DISPLAY MODULE    
;

STROBE    BCF    RS        ; SELECT COMMAND REGISTER
    GOTO    CM

;**********************************************************
;
;    Put a BCD nybble to display
;

PutNyb    ANDLW    0x0F        ; MASK OFF OTHER PACKED BCD DIGIT
    ADDLW    0x30        ; Convert BIN to ASCII

;**********************************************************
;
;    Put a data byte to display
;

DATS    movwf    TEMP        ; Save character for LCD
    call    putchr
    movf    TEMP,w
    
    BSF    RS        ; SELECT DATA REGISTER
CM    MOVWF    CHR        ; STORE CHAR TO DISPLAY
    SWAPF    CHR,W        ; SWAP UPPER AND LOWER NIBBLES (4 BIT MODE)

    call    PB_dly

    MOVF    CHR,W        ; GET CHAR AGAIN 

;**********************************************************
;
;    Put 4 bits to LCD & wait (untrimmed)
;

PB_dly    ANDLW    0x0F        ; MASK OFF UPPER 4 BITS
    MOVWF    PORTB        ; SEND DATA TO DISPLAY        
    BSF    ENA        ; ENA HIGH
    NOP            
    BCF    ENA        ; ENA LOW 
                ; Fall into 200us DELAY subroutine

;**********************************************************
;
;    Delay for 200us (untrimmed)
;
;    Uses: W, COUNT1
;
;**********************************************************

D200us
DELAY    MOVLW    0x42        ; DELAY 200us
    MOVWF    COUNT1    

NXT5    DECFSZ    COUNT1,F
    GOTO    NXT5    

    RETLW    0

;**********************************************************
;
;    Delay for 2ms (untrimmed)
;
;    Uses: W, COUNT2, COUNT1
;
;**********************************************************

MS2    MOVLW    0x0A        ; DELAY 2ms
    MOVWF    COUNT2

LP15    call    D200us

    DECFSZ    COUNT2,F
    GOTO    LP15

    RETLW    0        

;**********************************************************
;
;    Delay for 512ms (untrimmed)
;
;    Uses: W, COUNT3, COUNT2, COUNT1
;
;**********************************************************

MS512    clrw            ; 0 -> 256 loops

;**********************************************************
;
;    Delay for multiples of 2ms (untrimmed)
;
;    Uses: W, COUNT3, COUNT2, COUNT1
;
;**********************************************************

MS2xW    MOVWF    COUNT3    

LPx15    call    MS2

    DECFSZ    COUNT3,F
    GOTO    LPx15

    RETLW    0        

;******************************************************************
;
;    Convert 32-bit binary number at <AccA:4> into a bcd number
;    at <bcd:5>. Uses Mike Keitz's procedure for handling bcd 
;    adjust. Microchip AN526
;

B2_BCD

b2bcd    movlw    .32        ; 32-bits
    movwf    COUNT        ; make cycle counter

    clrf    bcd+0        ; clear result area
    clrf    bcd+1
    clrf    bcd+2
    clrf    bcd+3
    clrf    bcd+4
    
b2bcd2  movlw    bcd        ; make pointer
    movwf    FSR
    movlw    .5        ; Number of BCD bytes?
    movwf    cnt        ; 2 BCD digits per byte

; Mike's routine:

b2bcd3    movlw    0x33    
        addwf    INDF,f        ; add to both nybbles
        btfsc    INDF,3        ; test if low result > 7
        andlw    0xf0        ; low result >7 so take the 3 out
        btfsc    INDF,7        ; test if high result > 7
        andlw    0x0f        ; high result > 7 so ok
        subwf    INDF,f        ; any results <= 7, subtract back
        incf    FSR,f        ; point to next
        decfsz    cnt,f
        goto    b2bcd3
        
        rlf    AccA+3,f    ; get another bit
        rlf    AccA+2,f
        rlf    AccA+1,f
        rlf    AccA+0,f

        rlf    bcd+4,f        ; put it into bcd
        rlf    bcd+3,f
        rlf    bcd+2,f
        rlf    bcd+1,f
        rlf    bcd+0,f

        decfsz    COUNT,f        ; all done?
        goto    b2bcd2        ; no, loop
        return            ; yes


;*********** INITIALISE LCD MODULE 4 BIT MODE ***********************

LCDINIT    CALL    MS512        ; Wait 0.512 sec for LCD  RESET

    BCF    RS        ; REGISTER SELECT LOW
    BCF    ENA        ; ENABLE LINE LOW
    
    MOVLW    0x03        ; 1
    call    PB_dly
    
    CALL    MS512        ; WAIT FOR DISPLAY TO CATCH UP

    MOVLW    0x03        ; 2
    call    PB_dly

    MOVLW    0x03        ; 3
    call    PB_dly

    MOVLW    0x02        ; Fn set 4 bits
    call    PB_dly
    
    MOVLW    0x28        ; DISPLAY 2 Line , 5x7 Dot's
    CALL    STROBE        ; Suggested by PA0EJH
    CALL    DELAY        
    
    MOVLW    0x0C        ; 0x0C DISPLAY ON
    CALL    STROBE
    CALL    DELAY        
    
    MOVLW    0x06        ; 0x06 ENTRY MODE SET
    CALL    STROBE
    CALL    DELAY

    MOVLW    0x01        ; 0x01 CLEAR DISPLAY
    CALL    STROBE
    CALL    MS2

    RETLW    0


;************ MOVE TO START OF LINE 2 *****************

LINE2    MOVLW    0xC0        ; ADDRESS FOR SECOND LINE OF DISPLAY
    CALL    STROBE
    goto    DELAY


;************ CLEAR DISPLAY ***************************

CLEAR    MOVLW    0x01        ; COMMAND TO CLEAR DISPLAY
    CALL    STROBE
    goto    MS2        ; LONGER DELAY NEEDED WHEN CLEARING DISPLAY


;*********** MOVE TO HOME *****************************

HOME    call    crlf        ; Serial

    MOVLW    0x02        ; COMMAND TO HOME LCD DISPLAY
    CALL    STROBE
    goto    MS2


;********************************************************************
;       Initialise Input & Output devices
;********************************************************************

InitIO    bank1

    movlw    0x37        ; Option register
    movwf    OPTION_REG    ; Port B weak pull-up enabled
                ; INTDEG Don't care
                ; Count RA4/T0CKI
                ; Count on falling edge
                ; Prescale Timer/counter
                ; divide Timer/counter by 256

                ; PORTA:-
    movlw    0x02        ; initialise data direction
                ; 1 = input, 0 = output
                ;
                ; PORTA has 5 pins     4 3 2 1 0
                ; 0x02       =   0 0 0 0 0 0 1 0
                ;
    movwf    TRISA        ; PORTA<0>   = Serial + Debugging Out
                ; PORTA<1>   = FIXIT (input)
                ; PORTA<2>   = LCD "E" Out
                ; PORTA<3>   = LCD "RS" Out
                ; PORTA<4>   = "Input" with pull-down
                ;              Actually an output.
                ; PORTA<5:7> = not implemented in 16F84
                ;
                ; PORTB:-
    movlw    0xf0        ; initialise data direction
                ; PORTB has 8 pins
                ; port pin       7 6 5 4 3 2 1 0
                ; 0xf0       =   1 1 1 1 0 0 0 0
                ;
    movwf    TRISB        ; PORTB<0>   = LCD "DB4"
                ; PORTB<1>   =     "DB5"
                ; PORTB<2>   =     "DB6"
                ; PORTB<3>   =     "DB7"
                ; PORTB<4>   = Input
                ; PORTB<5>   = Input
                ; PORTB<6>   = Input
                ; PORTB<7>   = Input

    bank0

    return    

;**********************************************************
;
;    Measure Frequency. Stash in "AccA:4"
;

Measure    bcf    CLAMP        ; CLOSE GATE for safety

    bsf    PORTB,2        ; For compatibility with
    bsf    PORTB,3        ; Version 1 hardware
    
    bcf    INTCON,T0IF    ; Clear any previous overflow
  
    CLRF    TMR0        ; RESET INTERNAL COUNT (INCLUDING PRESCALER)
                ; See page 27 Section 6.0

    CLRF    AccA+0        ; Ready to receive 32 bit number
    CLRF    AccA+1
    CLRF    AccA+2
    CLRF    AccA+3

    bsf    CLAMP        ; OPEN GATE

    CALL    MS1000        ; 1.0 sec DELAY

    bcf    CLAMP        ; CLOSE GATE (COUNT COMPLETE)
    nop            ; and allow time for
    nop            ; the registers to catch up
    nop
    nop
    nop
    
    call    RollOver    ; Final check, just in case

    MOVF    TMR0,W        
    MOVWF    AccA+2

;    Now empty the prescaler

PSC1    bank1

    bcf    OPTION_REG,T0SE    ; Clock the prescaler
    nop
    bsf    OPTION_REG,T0SE

    bank0
    
    DECF    AccA+3,F    ; Decrement the counter
    
    movf    TMR0,W        ; Has TMR0 changed?
    xorwf    AccA+2,W    ; if unchanged, XOR -> 0

    beq    PSC1
        
; AccA : AccA+1 : AccA+2 : AccA+3 now holds 32 bit result
; Rollover subroutine has set AccA+0 and AccA+1 suitably.

    return

;**********************************************************
;
;    Account for TMR0 overflows when counting
;    Check at regular intervals and handle as
;    necessary.
;
;    Needs to be done at less than 936us (@ 70MHz in)
;    intervals, or else it can lose counts.
;

RollOver

    btfss    INTCON,T0IF    ; Rolled over?
    goto    RO3        ; No

RO1    bcf    INTCON,T0IF    ; Yes. ACK!

    INCF    AccA+1,f    ; Count it
    bne    RO2        ; Overflowed?

    incf    AccA+0,f    ; No need to check

RO2    return

;    Balance path lengths

RO3    nop
    nop
    goto    RO2

;**********************************************************
;
;    Display frequency
;
;    Display contents of AccA+0...AccA+3 on LCD
;    First convert to BCD, Then ASCII (nybble at a time)
;
;    In this version, multiply ACCA:4 by 64 since gate
;    time = 1.0 second and ext prescale=64
;

Display    btfsc    PSC        ; 1 = prescaler active = *64        

    call    Mul64        ; Account for prescaler

    CALL    B2_BCD        ; CONVERT all AccA TO BCD

;    Perform Leading Zero Blanking on first 3 digits

    swapf    bcd+0,W        ; 1000's of MHz
    andlw    0x0F        ; MASK OFF OTHER PACKED BCD DIGIT
    bne    NoB1K

    MOVLW    0x20        ; YES PRINT A BLANK SPACE
    CALL    DATS

    movf    bcd+0,W        ; 100's of MHz
    andlw    0x0F        ; MASK OFF OTHER PACKED BCD DIGIT
    bne    NoB100

    MOVLW    0x20        ; YES PRINT A BLANK SPACE
    CALL    DATS

    swapf    bcd+1,W        ; 10's of MHz
    andlw    0x0F        ; MASK OFF OTHER PACKED BCD DIGIT
    bne    NoB10

    MOVLW    0x20        ; YES PRINT A BLANK SPACE
    CALL    DATS

    goto    NoB1

;    Handle rest of number non blanked

NoB1K    SWAPF    bcd+0,W        ; 1000's of MHz
    CALL    PutNyb

NoB100    MOVF    bcd+0,W        ; 100's of MHz
    CALL    PutNyb

NoB10    SWAPF    bcd+1,W        ; 10's of MHz
    CALL    PutNyb

NoB1    MOVF    bcd+1,W        ; 1's of MHz
    CALL    PutNyb

    MOVLW    '.'        ; Decimal Point
    CALL    DATS

    SWAPF    bcd+2,W        ; 100's of KHz
    CALL    PutNyb

    MOVF    bcd+2,W        ; 10's of KHz
    CALL    PutNyb

    SWAPF    bcd+3,W        ; 1's of KHz
    CALL    PutNyb

    CALL    LINE2
    
    MOVF    bcd+3,W        ; 100's of Hz
    CALL    PutNyb

    SWAPF    bcd+4,W        ; 10's of Hz
    CALL    PutNyb

    MOVF    bcd+4,W        ; 1's of Hz
    CALL    PutNyb

    movlw    mhz        ; WRITE " Mhz" AT end OF LINE
    goto    pmsg        ; includes RETURN


;********************************************************************
;    Read EEPROM into "AccB"  (AccB must be visible in both
;    W -> memory to read          memory banks 0 & 1)
;********************************************************************    

EE_RD

#ifdef    F628
    bank1
#endif

    MOVWF    EEADR        ; Address to read

#ifdef    F628
    bank0
#endif
    
    XORLW    0x0C        ; Special case (no links)
    BEQ    AVERAGE

    CALL    EE_R
    MOVWF    AccB+0

    CALL    EE_Rinc
    MOVWF    AccB+1

    CALL    EE_Rinc
    MOVWF    AccB+2

    CALL    EE_Rinc
    MOVWF    AccB+3

    RETURN

;--------------------------------------------------------------------

#ifdef F84

EE_Rinc    INCF    EEADR,F        ; bump address

EE_R    bank1
    BSF    EECON1,RD    ; EE Read
    bank0
    MOVF    EEDATA,W    ; W = EEDATA

    RETURN
#endif

;--------------------------------------------------------------------

#ifdef    F628

EE_Rinc    bank1
    INCF    EEADR,F        ; bump address

EE_R    bank1
    BSF    EECON1,RD    ; EE Read
    MOVF    EEDATA,W    ; W = EEDATA
    bank0

    RETURN
#endif

;--------------------------------------------------------------------

AVERAGE    movlw    0x04        ; AM - use avg BFO freq.
    call    EE_RD        ; Read in one BFO freq
    copy    AccB,AccA    ; Into AccA

    movlw    0x08        ; Then second
    call    EE_RD        ; into AccB

    call    AplusB        ; Add 'em
    call    Div2        ; get average in AccA
    copy    AccA,AccB    ; and in AccB
    return
    

;********************************************************************
;    Write EEPROM from "AccB"  (AccB must be visible in both
;    W -> memory to write          memory banks 0 & 1)
;********************************************************************    

#ifdef    F84

EE_WR    MOVWF    EEADR        ; Address to write

    MOVF    AccB+0,W    ; Data byte #0
    CALL    EE_W

    MOVF    AccB+1,W    ; Data byte #1
    CALL    EE_Winc

    MOVF    AccB+2,W    ; Data byte #2
    CALL    EE_Winc

    MOVF    AccB+3,W    ; Data byte #3
    CALL    EE_Winc

    RETURN

EE_Winc    INCF    EEADR,F        ; bump address
    
EE_W    MOVWF    EEDATA
    bank1
    BSF    EECON1,WREN    ; Enable Write
    MOVLW    0x55        ;
    MOVWF    EECON2        ; Write 0x55
    MOVLW    0xAA        ;
    MOVWF    EECON2        ; Write 0xAA
    BSF    EECON1,WR    ; Set WR bit (begin write)

EE_W2    BTFSC    EECON1,WR    ; Wait for write to finish
    GOTO    EE_W2

    BCF    EECON1,EEIF    ; clear interrupts
    bank0

    RETURN    

#endif

;--------------------------------------------------------------------

#ifdef    F628

EE_WR    bank1
    MOVWF    EEADR        ; Address to write

    MOVF    AccB+0,W    ; Data byte #0
    CALL    EE_W

    MOVF    AccB+1,W    ; Data byte #1
    CALL    EE_Winc

    MOVF    AccB+2,W    ; Data byte #2
    CALL    EE_Winc

    MOVF    AccB+3,W    ; Data byte #3
    CALL    EE_Winc

    bank0
    RETURN

    errorlevel    -302    ; In Bank 2

EE_Winc    INCF    EEADR,F        ; bump address
    
EE_W    MOVWF    EEDATA
    BSF    EECON1,WREN    ; Enable Write
    MOVLW    0x55        ;
    MOVWF    EECON2        ; Write 0x55
    MOVLW    0xAA        ;
    MOVWF    EECON2        ; Write 0xAA
    BSF    EECON1,WR    ; Set WR bit (begin write)

EE_W2    BTFSC    EECON1,WR    ; Wait for write to finish
    GOTO    EE_W2

    bank0
    BCF    PIR1,EEIF    ; clear interrupts
    bank1
    RETURN    

    errorlevel    +302
#endif


;********************************************************************
;    Testing counter 
;********************************************************************    

ctest    movlw    0xfe        ; MS byte of loop count
    movwf    COUNT3        ; Counted upward till it overflows

    movlw    0x1d
    movwf    COUNT2

    movlw    0xc0
    movwf    COUNT1

cloop    bcf    PUFF        ; Toggle counter input once
    bsf    PUFF

    incfsz    COUNT1,f
    goto    cloop

    incfsz    COUNT2,f
    goto    cloop

    incfsz    COUNT3,f
    goto    cloop

    return

;***********************************************************************
;
;    Debugging Memory & Register dump
;

debug
    MOVWF    D_Wtemp        ; Copy W to temp register,
    SWAPF    STATUS,W    ; Swap status to be saved into W
    MOVWF    D_Stemp        ; Save status to D_Stemp register
    movf    FSR,W        ; Save FSR
    movwf    D_FSR
    
    movlw    0x57        ; W=
    call    putchr
    movlw    0x3d
    call    putchr

    movf    D_Wtemp,w
    call    hex_2
    
    movlw    0x20        ; 2 spaces, just to be neat
    call    putchr
    movlw    0x20
    call    putchr
    
    movlw    0x53        ; SR=
    call    putchr
    movlw    0x52
    call    putchr
    movlw    0x3d
    call    putchr

    movf    D_Stemp,w
    call    hex_2
    
    call    crlf        ; Serial

    clrf    FSR        ; Ready for memory dump

D_loop    movf    0,W        ; Read indirect
    call    hex_2
    movlw    0x20
    call    putchr
    incf    FSR,f        ; to next byte

    movf    FSR,w        ; end of line?
    andlw    0x0F
    bne    next_ln

    call    crlf
    bra    chk4end

next_ln    andlw    0x03        ; Groups of 4
    bne    chk4end

    movlw    0x20
    call    putchr

chk4end    movf    FSR,w        ; All done?
    xorlw    0x80
    bne    D_loop

    call    crlf
    call    crlf
    
    movf    D_FSR,W        ; Restore FSR
    movwf    FSR
    
    SWAPF    D_Stemp,W    ; Swap nibbles in D_Stemp register
                ; and place result into W

    MOVWF    STATUS        ; Move W into STATUS register
                ; (sets bank to original state)
    SWAPF    D_Wtemp,F    ; Swap nibbles in D_Wtemp and place result in D_Wtemp
    SWAPF    D_Wtemp,W    ; Swap nibbles in D_Wtemp and place result into W
    
    return

    
;***********************************************************************
;
;    Print CRLF to serial
;

crlf    movlw    0x0d        ; CRLF
    call    putchr
    movlw    0x0a
    goto    putchr

;***********************************************************************
;
;    Print W as 2 Hex digits
;

hex_2    movwf    D_hex
    swapf    D_hex,w        ; Get big bit
    call    hex_3

    movf    D_hex,w        ; Get little bit

hex_3    andlw    0x0f        ; keep bottom 4 bits
    addlw    0xF6
    bcc    hex_4
    addlw    0x07        ; binary A -> ASCII A
hex_4    addlw    0x3A        ; binary 0 -> ASCII 0
;    goto    putchr

;********************************************************
;
;    Output Routines for PIC16F84
;    
;    Clock is 4.0 MHz.
;    ie. 1.0 us per cycle = 4/Fosc.
;
;    9600 Baud  = 104.17 us
;               = 104.17   CPU cycles
;
;********************************************************
;
;    Output the character in W. Assumes Mac is ready.
;       
;    Uses W
;

putchr    movwf    S_Wtemp        ; Character being output

    movlw    0x08        ; Bit count
    movwf    S_count

    bcf    S_out        ; Send a 0 - Start bit

put_clp    movlw    0xE7        ; Delay "104" cycles
txd_0    addlw    0x01
    bne    txd_0

    rrf    S_Wtemp,f    ; Transmit a bit
    bcs    t_0

    bcf    S_out        ; Send a 0
    bra    tx_1

t_0    bsf    S_out        ; Send a 1

tx_1    decfsz    S_count,f    ; Done all bits?
    goto    put_clp

    movlw    0xE7        ; Delay for last data
txd_1    addlw    0x01
    bne    txd_1

    bsf    S_out        ; Transmit two stop bit

    movlw    0xCD
txd_9    addlw    0x01
    bne    txd_9
    
    return
 
;********************************************************************
;    Tail End Charlie
;********************************************************************    
; initialize eeprom locations

        ORG 0x2100

        DE  0x00, 0x00, 0x00, 0x00    ; Unused (reserved for later)
        DE  0x00, 0x00, 0x00, 0x00    ; IF Offset 1 Low  BFO ????
        DE  0x00, 0x00, 0x00, 0x00    ; IF Offset 2 High BFO ????
        DE  0x00, 0x00, 0x00, 0x00    ; IF Offset 3 No   BFO -AM-
        DE  0xfa, 0xff, 0x5f, 0x00    ; 4.000 MHz initial calibration

END
```


----------



## trifoncar (Oct 31, 2013)

ricbevi dijo:


> Hola...Yo no se mucho de programación en asembler pero por que no probas con esta modificación en la multiplicación a ver si es así(mientras aparece alguien con conocimiento en el tema dispuesto a ayudar).
> Saludos.
> Ric.
> 
> [/code]



     

¡¡Muchísimas gracias Ric!!  El código funciona maravillosamente bien. He comprobado que los saltos de frecuencia ahora me los da de 256 en 256 hercios y he comprobado la medición de frecuencia con unos walkies y es correcta.

Te agradezco muchísimo el haberme ahorrado un montón de horas volviéndome loco con el "source" que no domino.

No sé si te parecerá abusar, pero lo que ahora me ocurre es que, así como en la página de Phil Rice https://sites.google.com/site/vk3bhr/home/fm2/prescale aparecen dos ficheros HEX (prehex1 y Prehex2) para presentación en 1 o dos líneas del LCD (display) me he encontrado que el fichero fuente (source) que tan amable y exitosamente has arreglado para *256, la presentación la hace en dos líneas del LCD. ¿Podrías decirme como arreglarlo? o quizá sea mucho pedir; si fuese así, disculpa por el posible abuso.

Un saludo

Gerardo


----------



## miguelus (Nov 1, 2013)

Buenos días trifoncar.

¿Has probado a poner un Display de 16x1?

Sal U2


----------



## trifoncar (Nov 1, 2013)

miguelus dijo:


> Buenos días trifoncar.
> 
> ¿Has probado a poner un Display de 16x1?
> 
> Sal U2



Hola Miguelus,

No sé si comprendo lo que dices, pero puedo decirte que todos los displays que tengo son de 16x2.

Un saludo


----------



## trifoncar (Nov 1, 2013)

Estoy "tocando" el código fuente del pic para intentar que me aparezca la frecuencia en una única línea y me está asaltando una duda "existencial", a saber: el tiempo que dedica el programa fuente a leer las instrucciones ¿hay que tenerlo en cuenta a la hora del cálculo de la frecuencia? es decir, ¿afecta a la medición de la frecuencia?

Me da la impresión de que mientras el pic lee el programa está perdiendo tiempo midiendo la frecuencia. ¿Es esto así? ¿Habría que tener en cuenta los ciclos de reloj que pierde el programa ejecutando las instrucciones?

¿O mientras el pic lee los pulsos no se dedica a otra cosa y no pierde ciclos de reloj leyendo el código fuente?

Un saludo


----------



## miguelus (Nov 1, 2013)

En cuanto a tus inquietudes acerca de la forma en la que este Frecuencímetro realiza la medida, es de suponer que el mismo está programado con la cabeza y su forma de funcionar es similar a un Frecuencímetro convencional.

Un frecuencímetro convencional tiene un tiempo de Puerta, durante este tiempo los impulsos de entrada pasan a un contador, después de un  tiempo se corta la entrada a los contadores e inmediatamente son mostrados en el Display, mientras se visualiza la cuenta los contadores son reseteados y se comienza una nueva cuenta.

El programa tiene que funcionar de una manera similar, hay que suponer que mientras se realiza la cuenta por el Registro TMR0 (Pin 3), el software puede estar realizando otra función, pero cada cierto tiempo, p.e 1 segundo el software se detiene y lee el TMR0 que contendrá los impulsos recibidos.

Leer y seguir el programa no es una tarea sencilla, todo dependerá de los conocimientos de ensamblador que poseas hay cosas que se intuyen, afortunadamente podemos hacer todos los cambios que queramos, al ensamblar el programa y ponerlo en el PIC podemos ver que es lo ha pasado.

Sal U2


----------



## ricbevi (Nov 1, 2013)

trifoncar dijo:


> ¡¡Muchísimas gracias Ric!!  El código funciona maravillosamente bien. He comprobado que los saltos de frecuencia ahora me los da de 256 en 256 hercios y he comprobado la medición de frecuencia con unos walkies y es correcta.
> 
> Te agradezco muchísimo el haberme ahorrado un montón de horas volviéndome loco con el "source" que no domino.
> 
> ...



Me alegro que era así lo del factor de multiplicación...prueba con mandar a GND el pin 18 que en algun momento el autor lo penso para solucionar dicho problema pero el programa ha sufrido muchas modificaciones y no se si se encuentra activa dicha función en ese pin.
Reitero que la programación en el lenguaje asembler del PIC no es mi fuerte.
Si no encuentras respuesta en este Sub-foro deberías plantear el problema especifico del dispaly en el de "*Microcontroladores y sistemas embebidos* " donde se encuentran los que realmente saben del tema(programación).
Suerte.

Ric.


----------



## miguelus (Nov 2, 2013)

Buenos días.

El Pin 18 (A0) Puesto a "1" provoca que el Frecuencímetro funcione en modo "Normal" esto es, sin ningún factor de división, la frecuencia máxima que podemos medir es de ~85Mhz.

Si el Pin 18 lo ponemos a "0" provoca que el Frecuencímetro tenga en cuenta el factor de división del Prescaler.

Si ponemos un Display de 16x2 (16 caracteres y 2 Líneas) la visualización se mostrará en dos Líneas, en la superior aparecerá la frecuencia y en la inferior mostrará la palabra "MHZ" (igual que en la foto del Post #64).

Si ponemos un Display de 16x1 (16 caracteres y 1 Línea) la visualización se mostrará, lógicamente, en una sola Línea, en primer lugar mostrará la frecuencia y a continuación la palabra "MHZ".

A mí me pasa como a recbyvi, la programación de PIC no es mi fuerte (en realidad dudo si hay algo que verdaderamente sea mi fuerte 

Analizando por encima el ASM he visto algo que podría ser el principio para empezar a analizar, total no pondremos a nadie en peligro… 

Casi al principio podemos ver la siguiente instrucción… 

_;#define    Two_Line    1    ; Un-comment for two line displays_

    Esta instrucción, tal como está, no hace nada pero si quitamos “;” que hay al princio quedará así…

_#define    Two_Line    1    ; Un-comment for two line displays_

Ahora la instrucción si que se ejecutará, le estamos diciendo que el Display es de dos Líneas.

Más adelante podemos encontrar la siguiente instrucción…

_#ifdef    Two_Line


#endif_


Todo lo que haya entre estas dos Líneas se ejecutará. Si no hemos quitado ";" en la primera instrucción el programa se saltará este bloque de instrucciones

Esto aparece varias veces durante el programa.

Jugando con lo que hay entre las dos instrucciones, podemos hacer que el programa se comporte de otra forma, me refiero a la forma de visualizar.

Antes de hacer cambio alguno hay que tener la precaución de guardar una copia del ASM, de esta forma evitaremos perderlo 

Sal U2


----------



## trifoncar (Nov 2, 2013)

Gracias por los comentarios.
Ric, efectivamente en una primera versión del código, el pin 18 era para seleccionar si el display era de una o dos líneas, pero al hacer el autor las modificaciones para admitir un prescaler, el pin 18 pasó a sel el indicador de si debía o no multiplicar por el factor del prescaler ( 64 en el modelo de Phil Rice)
Estoy lejos de mi casa pasando el puente, pero el viernes por la mañana estuve analizando las líneas de código.
El pin 18 conectado a tierra provoca el funcionamiento normal del frecuencímetro, y conectado a Vdd funciona con el factor del prescaler definido por las líneas de código, que en mi caso ahora es 256.
Hice la prueba de quitar el punto y la coma a la línea que comentas, Miguelus.
Con ";" me aparecen el número entero de Mhz, el punto y los tres primeros decimales en la primera línea del display, y los decimales 4°, 5° y 6° seguido de MHz en la segunda línea, como puede verse en la última foto que he posteado un poco más arriba.
Quitándo ";" en la primera línea aparece lo mismo, y en la segunda línea aparece la cadena de caracteres "1234567890ABCDEF" que lo he visto en una de las líneas del código. De hecho, cambié esa línea de código para poner la cadena "16F84/MB506:x256" y me apareció en la segunda línea.

 ------------
------------- (ver Razón para Editar)

Un saludo y, gracias de nuevo.


----------



## trifoncar (Nov 3, 2013)

Por no alargar un mensaje ya de por sí muy extenso, abro un nuevo post aquí.

He localizado la rutina que escribe los datos en dos líneas, y es:


*;    Handle rest of number non blanked

NoB1K    SWAPF    bcd+0,W        ; 1000's of MHz  ---------->  gigahercios
    CALL    PutNyb

NoB100    MOVF    bcd+0,W        ; 100's of MHz    ---------->  centenas de Mhz
    CALL    PutNyb

NoB10    SWAPF    bcd+1,W        ; 10's of MHz     ---------->  decenas de Mhz
    CALL    PutNyb

NoB1    MOVF    bcd+1,W        ; 1's of MHz          ---------->  unidades de Mhz
    CALL    PutNyb

    MOVLW    '.'        ; Decimal Point                    ---------->  pone un punto decimal
    CALL    DATS

    SWAPF    bcd+2,W        ; 100's of KHz             ---------->  centenas de Khz
    CALL    PutNyb

    MOVF    bcd+2,W        ; 10's of KHz                 ---------->  decenas de Khz
    CALL    PutNyb

    SWAPF    bcd+3,W        ; 1's of KHz                 ---------->  unidades de Khz
    CALL    PutNyb

    CALL    LINE2                                                ---------->  llama a la subrutina de salto de línea

    MOVF    bcd+3,W        ; 100's of Hz                  ---------->  centenares de Hz
    CALL    PutNyb

    SWAPF    bcd+4,W        ; 10's of Hz                  ---------->  decenas de Hz
    CALL    PutNyb

    MOVF    bcd+4,W        ; 1's of Hz                      ---------->  unidades de Hz
    CALL    PutNyb

    movlw    mhz        ; WRITE " Mhz" AT end OF LINE  ---------->  escribe " Mhz" a continuación
    goto    pmsg        ; includes RETURN
*

El lunes, podré hacer nuevas pruebas modificando el código relacionado con estas líneas e intentando suprimir ese molesto salto de línea.

Por otra parte, ya que tengo un prescaler que alcanza los 2,4 Ghz, intenté localizar la frecuencia de mi router wifi porque tengo entendido que trabaja a 2,4 Ghz. pero el frecuencímetro no me pilla la señal; además creo que debería de captar la señal del wifi de una tableta ¿no?

Un saludo


----------



## ricbevi (Nov 3, 2013)

"@trifoncar" Prueba de esta forma a ver que pasa....comente la llamada a la sub-rutina de la linea 2 del dispay en el proceso de impresión.


```
;*******************************************************************
;
;    "Digital" Frequency display with /64 prescaler & no offsets
;
;    Crystal freq. = 4.000MHz +/- a bit
;
;*******************************************************************
;
;    First, let us choose our weapon - 16F84 or 16F628
;

;    Comment out the next line [;#define F84] if using a 16F628

#define    F84

#ifndef    F84
    #define    F628
#endif


;*******************************************************************
;
;    Some Testing Stuff(tm)
;

;#define    testing        1    ; Comment out when testing finished

;#define    Two_Line    1    ; Un-comment for two line displays


;************************ REVISION HISTORY *************************
;
;    FM1.000    Originally from FM3/4 9:39pm 14 May 2002
;        As implemented in experimental 3.5MHz receiver
;
;*******************************************************************
;
;    FM1.003    Fixed? major silliness in LO-IF code
;        Re-wrote USB/LSB suffix code
;        Added #defines for crook displays
;        Added #defines for two line displays
;        Wrapped #ifdef ... endif around debugging code
;
;*******************************************************************
;
;    FM1.004    Added code to allow user to fix crook display
;        Deleted #defines for crook displays
;        Pin 18 is now input. 1 = good display, 0 = crook
;
;*******************************************************************
;
;    FM2.000    New Hardware! Deleted external counter & gating
;        Now uses the same scheme as the LC Meter, with the
;        third byte of the count implemented in the PIC.
;        Basically, the "output" of the timer register is
;        counted within the gate timing loop.
;
;*******************************************************************
;
;    FM2.001    Discovered that I don't need to use RA0 as a gate
;        cos RA4 can be used as a timer input, even when
;        defined as an output - all that is required is to
;        set it high to count or low to inhibit.
;        Jeez, Microchip are smart arses.
;        I dunno why I didn't spot this long ago.
;        (Can't be used on the LC Meter, cos its oscillator
;        needs to be clamped HIGH, not low as in this case).
;
;*******************************************************************
;
;    FM2.002    Added 9600 baud serial output via RA0
;
;*******************************************************************
;
;    FM2.003    Rewrote RollOver subroutine to use INTCON,T0IF bit.
;        Incorporated two bits from OvrFlow counter
;        to extend range to over 80MHz.
;
;*******************************************************************
;
;    FM2.004    Changed to 32 bit counting.
;
;*******************************************************************
;
;    FM2.005    Added "Calibrate" mode.
;
;*******************************************************************
;
;    FM2.006    Moved "divide by 4" to increase resolution of
;        the stored IF offsets
;
;*******************************************************************
;
;    FM2.007    Moved "check for rollover" out of the inner MS400
;        timing loop and adjusted loop count appropriately
;        The aim - to improve the resolution of the software
;        calibration by a factor of around 13 to 15 times.
;
;*******************************************************************
;
;    fm2b.007    Ported to 16F628
;    FM2c.007    Introduced macros
;    fm2.008        Renumbered
;
;*******************************************************************
;
;    fm2.009        Cleaned up AM IF Offset calculation
;            Converted some inline code to subroutines
;            Created new 32 bit "copy" macro
;            Adjusted calibration slightly
;            Added a "Processor =" message
;            Removed advertising.
;
;*******************************************************************
;
;    ghzfm.000    Added multiply by 64
;            Rendered offsets ineffective
;            changed display format to
;            xxxx.xxxxxx MHz
;            Gate time now 1.000 Second
;
;
;
;*******************************************************************
;o-----o-----o-----o-----o-----o-----o-----o-----o-----o-----o-----o
;*******************************************************************
;
;    Some frequently used code fragments
;    Use macros to make mistreaks consistently.
;
;-------------------------------------------------------------------
;    Select Register Bank 0

bank0    macro
    errorlevel    +302        ; Re-enable bank warning
    bcf        STATUS,RP0    ; Select Bank 0
    endm

;-------------------------------------------------------------------
;    Select Register Bank 1

bank1    macro
    bsf        STATUS,RP0    ; Select Bank 1
    errorlevel    -302        ; disable warning
    endm

;-------------------------------------------------------------------
;    Copy a 32 bit thing from one place to another

copy    macro    from,to

    movf    from+0,W
    movwf    to+0

    movf    from+1,W
    movwf    to+1

    movf    from+2,W
    movwf    to+2

    movf    from+3,W
    movwf    to+3

    endm

;*******************************************************************
;
;    CPU configuration
;

#ifdef    F84
    MESSG        "Processor = 16F84"
    #define     RAMStart    0x0C    ; by VK3BHR
    processor    16f84
    include        <p16f84.inc>
    __config    _HS_OSC & _PWRTE_ON & _WDT_OFF
#endif

#ifdef    F628
    MESSG        "Processor = 16F628"
    #define     RAMStart    0x20
    processor    16f628
    include        <p16f628.inc>
    __config    _HS_OSC & _PWRTE_ON & _WDT_OFF & _CP_OFF & _BODEN_ON & _LVP_OFF
#endif

;*******************************************************************
;
;    I/O configuration
;


#define S_out    PORTA,0x00    ; 9600 baud serial out
#define PUFF    PORTA,0x00    ; Testing counter out

;#define    FIXIT    PORTA,0x01    ; 1 = "good display"
                ; 0 = do CRLF at "chr 8"

#define    PSC    PORTA,0x01    ; 1 = multiply by 64
                
#define    ENA    PORTA,0x02    ; Display "E"
#define    RS    PORTA,0x03    ; Display "RS"
#define    CLAMP    PORTA,0x04    ; Pull-down the timer input

#define    Store    PORTB,0x04    ; Pin 10, 0 = Measure BFO
#define    Add_LO    PORTB,0x05    ; Pin 11, 0 = RF := LO + IF
                ;         1 = RF := | LO + (-IF) |
#define    BFO_Lo    PORTB,0x06    ; Pin 12, 0 = BFO on lower freq.
#define    BFO_Hi    PORTB,0x07    ; Pin 13, 0 = BFO on higher freq.

#define    Prg_FLG    FLAGS,0x05
#define    AMflag    FLAGS,0x03    ; 0 = Don't print USB/LSB suffix

#define    beq    bz        ; Motorola syntax branches
#define    BEQ    bz
#define    BNE    bnz
#define    bne    bnz

#define    BCC    bnc
#define    bcc    bnc
#define    BCS    bc
#define    bcs    bc

#define    BRA    goto
#define    bra    goto

;*******************************************************************
;
;    file register declarations: uses only registers in bank0
;    bank 0 file registers begin at 0x20 in the 16F628
;
;*******************************************************************

    cblock    RAMStart

    dbg0:4            ; Debugging stuff
    dbg1:4
    dbg2:4
    dbg3:4
    dbg4:4
    dbg5:4


    bcd:5            ; BCD, MSD first 

    SBflag            ; 0 = Lower BFO frequency
                ; 1 = Higher

    COUNT            ; Bin to BCD convert (bit count)
    cnt            ;                    (BCD BYTES)


    CHR
    TEMP            ; DATS/Putchr temporary
    pmsg_t            ; Used by PMSG

    FLAGS

    S_Wtemp            ; "debug" Variables
    S_count
    D_Wtemp
    D_Stemp
    D_FSR
    D_hex
    
    endc

#ifdef    F84
Part2    equ    D_hex+1        ; Just tack on end
#endif

#ifdef    F628
Part2    equ    0x70        ; $70-7F Visible from all banks
#endif

    cblock    Part2

    COUNT1            ; Used by delay routines
    COUNT2            ; Timing (100ms)
    COUNT3            ; Timing (100ms)
    COUNT4            ; Timing (400ms)

    AccA:4            ; Binary, MSByte first

    AccB:4            ; Intermediate frequency

    Hold:4            ; Used in "cal" mode

    endc

;**********************************************************
;
;    Begin Executable Stuff(tm)
;

    org    0

GO    clrwdt            ; 0 << Reset
    clrf    INTCON        ; 1 No interrupts

#ifdef    F628
    movlw    0x07        ; 2 Comparator off
    movwf    CMCON        ; 3
#endif

    goto    START        ; 4 << Interrupt.

;**********************************************************
;
;    Part of string printer
;

pmsub    movwf    PCL        ; Goto W
    nop            ; Just in case
pm_end    return

;**********************************************************
;
;    Text Strings (stored in RETLWs)
;

mhz    dt    " MHz",0
Spaces    dt    " ",0
USB    dt    "U",0
LSB    dt    "L",0
Prog    dt    "P",0
Cal    dt    "C",0

#ifdef    Two_Line

adv3    dt    "1234567890ABCDEF",0

 endif

;**********************************************************
;
;    Main Program
;

START    call    InitIO        ; INITIALISE PORTS
    CLRF    PORTA
    CLRF    PORTB
    bsf    S_out        ; Serial output to idle
    
    CALL    LCDINIT         ; INITIALIZE LCD MODULE    

;    MOVLW    adv1        ; Sign on
;    call    pmsg

;    btfss    FIXIT        ; Test input 1 = just return
;    CALL    LINE2        ; 0 = fix bad display

;    movlw    adv2
;    call    pmsg
    
;    CALL    MS512        ; Delay for about 1 sec.
;    CALL    MS512        ; 0.512 sec x 2

    CALL    CLEAR

;**********************************************************
;
;    Check if in "Calibrate" mode
;

    btfsc    Store        ; If grounded initially
    goto    newbit        ; then were in "cal"

    MOVLW    0xfa        ; Set initial counter        
    MOVWF    Hold+0        ; value

    MOVLW    0xff        ; 
    MOVWF    Hold+1        ; for a 4 MHZ XTAL

    MOVLW    0x5f
    MOVWF    Hold+2            

    MOVLW    0x00        ; Unused
    MOVWF    Hold+3            

GetCal    call    Measure    
    call    Display
    movlw    Cal        ; Say "we're calibrating"
    call    pmsg
    CALL    HOME

;
;    Adjust Cal value
;

cal_dn    btfsc    BFO_Lo
    goto    cal_up
    
    incf    Hold+2,f    ; Add 1
    bne    inc_xit
    incf    Hold+1,f
    bne    inc_xit
    incf    Hold+0,f
inc_xit    goto    StorCal

cal_up    btfsc    BFO_Hi
    goto    StorCal

;
;    Hold := Hold + (1-)    ; Subtract 1
;

Hadd_2    movlw    0xff        ; Process LS byte
    addwf    Hold+2,F
    bcc    Hadd_1        ; If no carry,do next

    incf    Hold+1,f    ; Else roll over higher
    bne    Hadd_1        ; bytes as appropriate

    incf    Hold+0,f    ; may roll over MSByte
        
Hadd_1    movlw    0xff        ; Process next byte
    addwf    Hold+1,F
    bcc    Hadd_0        ; If no carry,do next

    incf    Hold+0,f    ; may roll over MSByte
        
Hadd_0    movlw    0xff        ; Process next byte
    addwf    Hold+0,F

;
;    Time to save "Cal" value?
;

StorCal    btfss    Store        ; Ready to store it?
    goto    GetCal

    call    MS512        ; Delay 0.5 sec

    btfss    Store        ; De-bounce
    goto    GetCal

    copy    Hold,AccB    ; Write EEPROM from AccB

    movlw    0x10        ; EEADR of Cal value
    call    EE_WR


;**********************************************************
;
;    Begin a new measurement cycle
;

newbit    movlw    0x10        ; EEADR of Cal value
    call    EE_RD        ; in AccB
    
    copy    AccB,Hold    ; Get timing "constant"

    call    HOME        ; Display ready

    clrf    SBflag        ; 0 = Lower BFO frequency
                ; 1 = Higher

    bcf    AMflag        ; 0 = No USB/LSB suffix

    bcf    Prg_FLG

    btfsc    Store        ; Doing "BFO STORE"?
    goto    GetOffs

    call    MS512        ; Delay 0.5 sec

    btfsc    Store        ; De-bounce
    goto    GetOffs

GetIf    call    Measure        ; Get freq in AccA:4

    copy    AccA,AccB    ; For EEPROM Writing

    call    Display        ; Display freq in AccA
    
    movlw    Prog        ; Say "we're programming"
    call    pmsg
    CALL    HOME

    btfss    Store        ; Ready to store it?
    goto    GetIf

    call    MS512        ; Delay 0.5 sec

    btfss    Store        ; De-bounce
    goto    GetIf

    bsf    Prg_FLG        ; Flag "to be stored"

GetOffs    btfss    BFO_Hi        ; Which Offset??
    goto    Get2        ; Point @ EEPROM

    btfss    BFO_Lo        ; 4 bytes each
    goto    Ch2        ; BFO low link only
    goto    Ch3        ; No links

Get2    btfss    BFO_Lo
    goto    Ch0        ; Both links
    goto    Ch1        ; BFO high link only

Ch0    movlw    0x00        ; Offset channel 0 (both links fitted)
    goto    EndOff

Ch1    bsf    AMflag        ; We're gunna print
    comf    SBflag,f    ; that BFO is on higher frequency
    movlw    0x04        ; Offset channel 1 (BFO_Hi link fitted)
    goto    EndOff

Ch2    bsf    AMflag        ; We're gunna print
                ; that BFO is on lower frequency
    movlw    0x08        ; Offset channel 2 (BFO_Lo link fitted)
    goto    EndOff

Ch3    movlw    0x0C        ; Offset channel 3 (no links fitted)
;    goto    EndOff

EndOff    btfsc    Prg_FLG        ; Storing Offset?
    goto    Do_St        ; If not, then

    call    EE_RD        ; must be reading.
    goto    Do_Meas

Do_St    call    EE_WR

;
;    Now have IF in AccB
;

Do_Meas    call    Measure        ; Measure Local Osc Freq.

;
;    Now have LO in "AccA"
;        and  IF in "AccB"
;

Add_Sub    btfss    Add_LO        ; Add or Sub LO freq?
    goto    AddLSB        ; Clear = just add

    call    MinusA        ; RF := |IF - LO|
                ; SBflag is OK

AddLSB    call    AplusB

;
;    Fix overflow. If negative then make positive
;

    btfss    AccA+0,7    ; Set? (=Overflow)
    goto    OK2go        ; Clear = OK 2 print
    
    call    MinusA        ; Make positive and
    comf    SBflag,f    ; Swap USB/LSB

;
;    Display resulting number in AccA
;

OK2go    call    Display        ; display result at last

;
;    Print suffix - USB, LSB or nuffin
;    Now disabled

    btfsc    AMflag        ; Do we print at all?
    goto    trySBf

    movlw    Spaces        ; nuffin = spaces
    goto    EndMsg

trySBf    btfsc    SBflag,0    ; Which sideband?
    goto    pLSB

    movlw    USB        ; USB obviously
    goto    EndMsg

pLSB    movlw    LSB        ; LSB
;    goto    EndMsg

EndMsg    call    pmsg        ; Print selected trailer


#ifdef    Two_Line

    CALL    LINE2        ; WRITE second LINE

    movlw    adv3
    call    pmsg
 endif

    goto    newbit        ; Start next measurement


;**********************************************************
;
;    AccA := AccA + AccB
;

AplusB    movf    AccB+3,W    ; Process LSB
    addwf    AccA+3,F
    bcc    Add_2        ; If no carry,do next

    incf    AccA+2,f    ; Else roll over higher
    bne    Add_2        ; bytes as appropriate

    incf    AccA+1,f
    bne    Add_2

    incf    AccA+0,f    ; may roll over MSByte
    
Add_2    movf    AccB+2,W    ; Process next byte
    addwf    AccA+2,F
    bcc    Add_1        ; If no carry,do next

    incf    AccA+1,f    ; Else roll over higher
    bne    Add_1        ; bytes as appropriate

    incf    AccA+0,f    ; may roll over MSByte
        
Add_1    movf    AccB+1,W    ; Process next byte
    addwf    AccA+1,F
    bcc    Add_0        ; If no carry,do next

    incf    AccA+0,f    ; may roll over MSByte
        
Add_0    movf    AccB+0,W    ; Process next byte
    addwf    AccA+0,F
    return


;**********************************************************
;
;    Negate number in AccA (2's complement form)
;

MinusA    comf    AccA+0,f    ; Complement all bits
    comf    AccA+1,f    ; of number
    comf    AccA+2,f
    comf    AccA+3,f
    
    incf    AccA+3,f    ; Add 1
    bne    N_xit
    incf    AccA+2,f
    bne    N_xit
    incf    AccA+1,f
    bne    N_xit
    incf    AccA+0,f

N_xit    return

;**********************************************************
;
;    Divide AccA:4 by 4
;
;**********************************************************

Div4    call    Div2        ; Divide AccA:4 by 4

;**********************************************************
;
;    Divide AccA:4 by 2
;
;**********************************************************

Div2    rrf    AccA+0,f
    rrf    AccA+1,f    
    rrf    AccA+2,f
    rrf    AccA+3,f
    bcf    AccA+0,7    ; Possible bad carry in.
    return

;**********************************************************
;
;    Multiply AccA:4 by 64
;
;**********************************************************

Mul64    call    Mul2
    call    Mul2
    call    Mul2
    call    Mul2
    call    Mul2        ; then fall through
    call    Mul2
    call    Mul2
    
;**********************************************************
;
;    Multiply AccA:4 by 2
;
;**********************************************************

Mul2    rlf    AccA+3,f
    rlf    AccA+2,f    
    rlf    AccA+1,f
    rlf    AccA+0,f
    bcf    AccA+3,0    ; Possible bad carry in.
    return
;**********************************************************
;
;    Print String addressed by W
;    Note: Strings are in program space
;

pmsg    movwf    pmsg_t        ; Temp for pointer

pm1    movf    pmsg_t,W    ; Get current pointer
    call    pmsub
    andlw    0xff        ; Test returned value
    beq    pm_end        ; NULL = All done
    call    DATS
    incf    pmsg_t,F
    goto    pm1

;**********************************************************
;
;    Delay for 1000ms (trimmed for actual clock freq)
;    Check for Timer register roll over and count 'em
;
;    Uses: W, COUUNT1, COUNT2, COUNT3 & others
;
;**********************************************************

MS1000    MOVF    Hold+0,w    ; 100 MS DELAY LOOP        
    MOVWF    COUNT1        ; 4 MHZ XTAL

    MOVF    Hold+1,w    ; Count up
    MOVWF    COUNT2        ; to 24 bit overflow

    MOVF    Hold+2,w
    MOVWF    COUNT3

L3    INCFSZ    COUNT3,F
    GOTO    L3
    
    call    RollOver    ; Check for Timer0 RollOver

    INCFSZ    COUNT2,F
    GOTO    L3

    INCFSZ    COUNT1,F
    GOTO    L3

    RETLW    0

;**********************************************************
;
;    SEND A COMMAND BYTE TO LCD DISPLAY MODULE    
;

STROBE    BCF    RS        ; SELECT COMMAND REGISTER
    GOTO    CM

;**********************************************************
;
;    Put a BCD nybble to display
;

PutNyb    ANDLW    0x0F        ; MASK OFF OTHER PACKED BCD DIGIT
    ADDLW    0x30        ; Convert BIN to ASCII

;**********************************************************
;
;    Put a data byte to display
;

DATS    movwf    TEMP        ; Save character for LCD
    call    putchr
    movf    TEMP,w
    
    BSF    RS        ; SELECT DATA REGISTER
CM    MOVWF    CHR        ; STORE CHAR TO DISPLAY
    SWAPF    CHR,W        ; SWAP UPPER AND LOWER NIBBLES (4 BIT MODE)

    call    PB_dly

    MOVF    CHR,W        ; GET CHAR AGAIN 

;**********************************************************
;
;    Put 4 bits to LCD & wait (untrimmed)
;

PB_dly    ANDLW    0x0F        ; MASK OFF UPPER 4 BITS
    MOVWF    PORTB        ; SEND DATA TO DISPLAY        
    BSF    ENA        ; ENA HIGH
    NOP            
    BCF    ENA        ; ENA LOW 
                ; Fall into 200us DELAY subroutine

;**********************************************************
;
;    Delay for 200us (untrimmed)
;
;    Uses: W, COUNT1
;
;**********************************************************

D200us
DELAY    MOVLW    0x42        ; DELAY 200us
    MOVWF    COUNT1    

NXT5    DECFSZ    COUNT1,F
    GOTO    NXT5    

    RETLW    0

;**********************************************************
;
;    Delay for 2ms (untrimmed)
;
;    Uses: W, COUNT2, COUNT1
;
;**********************************************************

MS2    MOVLW    0x0A        ; DELAY 2ms
    MOVWF    COUNT2

LP15    call    D200us

    DECFSZ    COUNT2,F
    GOTO    LP15

    RETLW    0        

;**********************************************************
;
;    Delay for 512ms (untrimmed)
;
;    Uses: W, COUNT3, COUNT2, COUNT1
;
;**********************************************************

MS512    clrw            ; 0 -> 256 loops

;**********************************************************
;
;    Delay for multiples of 2ms (untrimmed)
;
;    Uses: W, COUNT3, COUNT2, COUNT1
;
;**********************************************************

MS2xW    MOVWF    COUNT3    

LPx15    call    MS2

    DECFSZ    COUNT3,F
    GOTO    LPx15

    RETLW    0        

;******************************************************************
;
;    Convert 32-bit binary number at <AccA:4> into a bcd number
;    at <bcd:5>. Uses Mike Keitz's procedure for handling bcd 
;    adjust. Microchip AN526
;

B2_BCD

b2bcd    movlw    .32        ; 32-bits
    movwf    COUNT        ; make cycle counter

    clrf    bcd+0        ; clear result area
    clrf    bcd+1
    clrf    bcd+2
    clrf    bcd+3
    clrf    bcd+4
    
b2bcd2  movlw    bcd        ; make pointer
    movwf    FSR
    movlw    .5        ; Number of BCD bytes?
    movwf    cnt        ; 2 BCD digits per byte

; Mike's routine:

b2bcd3    movlw    0x33    
        addwf    INDF,f        ; add to both nybbles
        btfsc    INDF,3        ; test if low result > 7
        andlw    0xf0        ; low result >7 so take the 3 out
        btfsc    INDF,7        ; test if high result > 7
        andlw    0x0f        ; high result > 7 so ok
        subwf    INDF,f        ; any results <= 7, subtract back
        incf    FSR,f        ; point to next
        decfsz    cnt,f
        goto    b2bcd3
        
        rlf    AccA+3,f    ; get another bit
        rlf    AccA+2,f
        rlf    AccA+1,f
        rlf    AccA+0,f

        rlf    bcd+4,f        ; put it into bcd
        rlf    bcd+3,f
        rlf    bcd+2,f
        rlf    bcd+1,f
        rlf    bcd+0,f

        decfsz    COUNT,f        ; all done?
        goto    b2bcd2        ; no, loop
        return            ; yes


;*********** INITIALISE LCD MODULE 4 BIT MODE ***********************

LCDINIT    CALL    MS512        ; Wait 0.512 sec for LCD  RESET

    BCF    RS        ; REGISTER SELECT LOW
    BCF    ENA        ; ENABLE LINE LOW
    
    MOVLW    0x03        ; 1
    call    PB_dly
    
    CALL    MS512        ; WAIT FOR DISPLAY TO CATCH UP

    MOVLW    0x03        ; 2
    call    PB_dly

    MOVLW    0x03        ; 3
    call    PB_dly

    MOVLW    0x02        ; Fn set 4 bits
    call    PB_dly
    
    MOVLW    0x28        ; DISPLAY 2 Line , 5x7 Dot's
    CALL    STROBE        ; Suggested by PA0EJH
    CALL    DELAY        
    
    MOVLW    0x0C        ; 0x0C DISPLAY ON
    CALL    STROBE
    CALL    DELAY        
    
    MOVLW    0x06        ; 0x06 ENTRY MODE SET
    CALL    STROBE
    CALL    DELAY

    MOVLW    0x01        ; 0x01 CLEAR DISPLAY
    CALL    STROBE
    CALL    MS2

    RETLW    0


;************ MOVE TO START OF LINE 2 *****************

LINE2    MOVLW    0xC0        ; ADDRESS FOR SECOND LINE OF DISPLAY
    CALL    STROBE
    goto    DELAY


;************ CLEAR DISPLAY ***************************

CLEAR    MOVLW    0x01        ; COMMAND TO CLEAR DISPLAY
    CALL    STROBE
    goto    MS2        ; LONGER DELAY NEEDED WHEN CLEARING DISPLAY


;*********** MOVE TO HOME *****************************

HOME    call    crlf        ; Serial

    MOVLW    0x02        ; COMMAND TO HOME LCD DISPLAY
    CALL    STROBE
    goto    MS2


;********************************************************************
;       Initialise Input & Output devices
;********************************************************************

InitIO    bank1

    movlw    0x37        ; Option register
    movwf    OPTION_REG    ; Port B weak pull-up enabled
                ; INTDEG Don't care
                ; Count RA4/T0CKI
                ; Count on falling edge
                ; Prescale Timer/counter
                ; divide Timer/counter by 256

                ; PORTA:-
    movlw    0x02        ; initialise data direction
                ; 1 = input, 0 = output
                ;
                ; PORTA has 5 pins     4 3 2 1 0
                ; 0x02       =   0 0 0 0 0 0 1 0
                ;
    movwf    TRISA        ; PORTA<0>   = Serial + Debugging Out
                ; PORTA<1>   = FIXIT (input)
                ; PORTA<2>   = LCD "E" Out
                ; PORTA<3>   = LCD "RS" Out
                ; PORTA<4>   = "Input" with pull-down
                ;              Actually an output.
                ; PORTA<5:7> = not implemented in 16F84
                ;
                ; PORTB:-
    movlw    0xf0        ; initialise data direction
                ; PORTB has 8 pins
                ; port pin       7 6 5 4 3 2 1 0
                ; 0xf0       =   1 1 1 1 0 0 0 0
                ;
    movwf    TRISB        ; PORTB<0>   = LCD "DB4"
                ; PORTB<1>   =     "DB5"
                ; PORTB<2>   =     "DB6"
                ; PORTB<3>   =     "DB7"
                ; PORTB<4>   = Input
                ; PORTB<5>   = Input
                ; PORTB<6>   = Input
                ; PORTB<7>   = Input

    bank0

    return    

;**********************************************************
;
;    Measure Frequency. Stash in "AccA:4"
;

Measure    bcf    CLAMP        ; CLOSE GATE for safety

    bsf    PORTB,2        ; For compatibility with
    bsf    PORTB,3        ; Version 1 hardware
    
    bcf    INTCON,T0IF    ; Clear any previous overflow
  
    CLRF    TMR0        ; RESET INTERNAL COUNT (INCLUDING PRESCALER)
                ; See page 27 Section 6.0

    CLRF    AccA+0        ; Ready to receive 32 bit number
    CLRF    AccA+1
    CLRF    AccA+2
    CLRF    AccA+3

    bsf    CLAMP        ; OPEN GATE

    CALL    MS1000        ; 1.0 sec DELAY

    bcf    CLAMP        ; CLOSE GATE (COUNT COMPLETE)
    nop            ; and allow time for
    nop            ; the registers to catch up
    nop
    nop
    nop
    
    call    RollOver    ; Final check, just in case

    MOVF    TMR0,W        
    MOVWF    AccA+2

;    Now empty the prescaler

PSC1    bank1

    bcf    OPTION_REG,T0SE    ; Clock the prescaler
    nop
    bsf    OPTION_REG,T0SE

    bank0
    
    DECF    AccA+3,F    ; Decrement the counter
    
    movf    TMR0,W        ; Has TMR0 changed?
    xorwf    AccA+2,W    ; if unchanged, XOR -> 0

    beq    PSC1
        
; AccA : AccA+1 : AccA+2 : AccA+3 now holds 32 bit result
; Rollover subroutine has set AccA+0 and AccA+1 suitably.

    return

;**********************************************************
;
;    Account for TMR0 overflows when counting
;    Check at regular intervals and handle as
;    necessary.
;
;    Needs to be done at less than 936us (@ 70MHz in)
;    intervals, or else it can lose counts.
;

RollOver

    btfss    INTCON,T0IF    ; Rolled over?
    goto    RO3        ; No

RO1    bcf    INTCON,T0IF    ; Yes. ACK!

    INCF    AccA+1,f    ; Count it
    bne    RO2        ; Overflowed?

    incf    AccA+0,f    ; No need to check

RO2    return

;    Balance path lengths

RO3    nop
    nop
    goto    RO2

;**********************************************************
;
;    Display frequency
;
;    Display contents of AccA+0...AccA+3 on LCD
;    First convert to BCD, Then ASCII (nybble at a time)
;
;    In this version, multiply ACCA:4 by 64 since gate
;    time = 1.0 second and ext prescale=64
;

Display    btfsc    PSC        ; 1 = prescaler active = *64        

    call    Mul64        ; Account for prescaler

    CALL    B2_BCD        ; CONVERT all AccA TO BCD

;    Perform Leading Zero Blanking on first 3 digits

    swapf    bcd+0,W        ; 1000's of MHz
    andlw    0x0F        ; MASK OFF OTHER PACKED BCD DIGIT
    bne    NoB1K

    MOVLW    0x20        ; YES PRINT A BLANK SPACE
    CALL    DATS

    movf    bcd+0,W        ; 100's of MHz
    andlw    0x0F        ; MASK OFF OTHER PACKED BCD DIGIT
    bne    NoB100

    MOVLW    0x20        ; YES PRINT A BLANK SPACE
    CALL    DATS

    swapf    bcd+1,W        ; 10's of MHz
    andlw    0x0F        ; MASK OFF OTHER PACKED BCD DIGIT
    bne    NoB10

    MOVLW    0x20        ; YES PRINT A BLANK SPACE
    CALL    DATS

    goto    NoB1

;    Handle rest of number non blanked

NoB1K    SWAPF    bcd+0,W        ; 1000's of MHz
    CALL    PutNyb

NoB100    MOVF    bcd+0,W        ; 100's of MHz
    CALL    PutNyb

NoB10    SWAPF    bcd+1,W        ; 10's of MHz
    CALL    PutNyb

NoB1    MOVF    bcd+1,W        ; 1's of MHz
    CALL    PutNyb

    MOVLW    '.'        ; Decimal Point
    CALL    DATS

    SWAPF    bcd+2,W        ; 100's of KHz
    CALL    PutNyb

    MOVF    bcd+2,W        ; 10's of KHz
    CALL    PutNyb

    SWAPF    bcd+3,W        ; 1's of KHz
    CALL    PutNyb

;    CALL    LINE2
    
    MOVF    bcd+3,W        ; 100's of Hz
    CALL    PutNyb

    SWAPF    bcd+4,W        ; 10's of Hz
    CALL    PutNyb

    MOVF    bcd+4,W        ; 1's of Hz
    CALL    PutNyb

    movlw    mhz        ; WRITE " Mhz" AT end OF LINE
    goto    pmsg        ; includes RETURN


;********************************************************************
;    Read EEPROM into "AccB"  (AccB must be visible in both
;    W -> memory to read          memory banks 0 & 1)
;********************************************************************    

EE_RD

#ifdef    F628
    bank1
#endif

    MOVWF    EEADR        ; Address to read

#ifdef    F628
    bank0
#endif
    
    XORLW    0x0C        ; Special case (no links)
    BEQ    AVERAGE

    CALL    EE_R
    MOVWF    AccB+0

    CALL    EE_Rinc
    MOVWF    AccB+1

    CALL    EE_Rinc
    MOVWF    AccB+2

    CALL    EE_Rinc
    MOVWF    AccB+3

    RETURN

;--------------------------------------------------------------------

#ifdef F84

EE_Rinc    INCF    EEADR,F        ; bump address

EE_R    bank1
    BSF    EECON1,RD    ; EE Read
    bank0
    MOVF    EEDATA,W    ; W = EEDATA

    RETURN
#endif

;--------------------------------------------------------------------

#ifdef    F628

EE_Rinc    bank1
    INCF    EEADR,F        ; bump address

EE_R    bank1
    BSF    EECON1,RD    ; EE Read
    MOVF    EEDATA,W    ; W = EEDATA
    bank0

    RETURN
#endif

;--------------------------------------------------------------------

AVERAGE    movlw    0x04        ; AM - use avg BFO freq.
    call    EE_RD        ; Read in one BFO freq
    copy    AccB,AccA    ; Into AccA

    movlw    0x08        ; Then second
    call    EE_RD        ; into AccB

    call    AplusB        ; Add 'em
    call    Div2        ; get average in AccA
    copy    AccA,AccB    ; and in AccB
    return
    

;********************************************************************
;    Write EEPROM from "AccB"  (AccB must be visible in both
;    W -> memory to write          memory banks 0 & 1)
;********************************************************************    

#ifdef    F84

EE_WR    MOVWF    EEADR        ; Address to write

    MOVF    AccB+0,W    ; Data byte #0
    CALL    EE_W

    MOVF    AccB+1,W    ; Data byte #1
    CALL    EE_Winc

    MOVF    AccB+2,W    ; Data byte #2
    CALL    EE_Winc

    MOVF    AccB+3,W    ; Data byte #3
    CALL    EE_Winc

    RETURN

EE_Winc    INCF    EEADR,F        ; bump address
    
EE_W    MOVWF    EEDATA
    bank1
    BSF    EECON1,WREN    ; Enable Write
    MOVLW    0x55        ;
    MOVWF    EECON2        ; Write 0x55
    MOVLW    0xAA        ;
    MOVWF    EECON2        ; Write 0xAA
    BSF    EECON1,WR    ; Set WR bit (begin write)

EE_W2    BTFSC    EECON1,WR    ; Wait for write to finish
    GOTO    EE_W2

    BCF    EECON1,EEIF    ; clear interrupts
    bank0

    RETURN    

#endif

;--------------------------------------------------------------------

#ifdef    F628

EE_WR    bank1
    MOVWF    EEADR        ; Address to write

    MOVF    AccB+0,W    ; Data byte #0
    CALL    EE_W

    MOVF    AccB+1,W    ; Data byte #1
    CALL    EE_Winc

    MOVF    AccB+2,W    ; Data byte #2
    CALL    EE_Winc

    MOVF    AccB+3,W    ; Data byte #3
    CALL    EE_Winc

    bank0
    RETURN

    errorlevel    -302    ; In Bank 2

EE_Winc    INCF    EEADR,F        ; bump address
    
EE_W    MOVWF    EEDATA
    BSF    EECON1,WREN    ; Enable Write
    MOVLW    0x55        ;
    MOVWF    EECON2        ; Write 0x55
    MOVLW    0xAA        ;
    MOVWF    EECON2        ; Write 0xAA
    BSF    EECON1,WR    ; Set WR bit (begin write)

EE_W2    BTFSC    EECON1,WR    ; Wait for write to finish
    GOTO    EE_W2

    bank0
    BCF    PIR1,EEIF    ; clear interrupts
    bank1
    RETURN    

    errorlevel    +302
#endif


;********************************************************************
;    Testing counter 
;********************************************************************    

ctest    movlw    0xfe        ; MS byte of loop count
    movwf    COUNT3        ; Counted upward till it overflows

    movlw    0x1d
    movwf    COUNT2

    movlw    0xc0
    movwf    COUNT1

cloop    bcf    PUFF        ; Toggle counter input once
    bsf    PUFF

    incfsz    COUNT1,f
    goto    cloop

    incfsz    COUNT2,f
    goto    cloop

    incfsz    COUNT3,f
    goto    cloop

    return

;***********************************************************************
;
;    Debugging Memory & Register dump
;

debug
    MOVWF    D_Wtemp        ; Copy W to temp register,
    SWAPF    STATUS,W    ; Swap status to be saved into W
    MOVWF    D_Stemp        ; Save status to D_Stemp register
    movf    FSR,W        ; Save FSR
    movwf    D_FSR
    
    movlw    0x57        ; W=
    call    putchr
    movlw    0x3d
    call    putchr

    movf    D_Wtemp,w
    call    hex_2
    
    movlw    0x20        ; 2 spaces, just to be neat
    call    putchr
    movlw    0x20
    call    putchr
    
    movlw    0x53        ; SR=
    call    putchr
    movlw    0x52
    call    putchr
    movlw    0x3d
    call    putchr

    movf    D_Stemp,w
    call    hex_2
    
    call    crlf        ; Serial

    clrf    FSR        ; Ready for memory dump

D_loop    movf    0,W        ; Read indirect
    call    hex_2
    movlw    0x20
    call    putchr
    incf    FSR,f        ; to next byte

    movf    FSR,w        ; end of line?
    andlw    0x0F
    bne    next_ln

    call    crlf
    bra    chk4end

next_ln    andlw    0x03        ; Groups of 4
    bne    chk4end

    movlw    0x20
    call    putchr

chk4end    movf    FSR,w        ; All done?
    xorlw    0x80
    bne    D_loop

    call    crlf
    call    crlf
    
    movf    D_FSR,W        ; Restore FSR
    movwf    FSR
    
    SWAPF    D_Stemp,W    ; Swap nibbles in D_Stemp register
                ; and place result into W

    MOVWF    STATUS        ; Move W into STATUS register
                ; (sets bank to original state)
    SWAPF    D_Wtemp,F    ; Swap nibbles in D_Wtemp and place result in D_Wtemp
    SWAPF    D_Wtemp,W    ; Swap nibbles in D_Wtemp and place result into W
    
    return

    
;***********************************************************************
;
;    Print CRLF to serial
;

crlf    movlw    0x0d        ; CRLF
    call    putchr
    movlw    0x0a
    goto    putchr

;***********************************************************************
;
;    Print W as 2 Hex digits
;

hex_2    movwf    D_hex
    swapf    D_hex,w        ; Get big bit
    call    hex_3

    movf    D_hex,w        ; Get little bit

hex_3    andlw    0x0f        ; keep bottom 4 bits
    addlw    0xF6
    bcc    hex_4
    addlw    0x07        ; binary A -> ASCII A
hex_4    addlw    0x3A        ; binary 0 -> ASCII 0
;    goto    putchr

;********************************************************
;
;    Output Routines for PIC16F84
;    
;    Clock is 4.0 MHz.
;    ie. 1.0 us per cycle = 4/Fosc.
;
;    9600 Baud  = 104.17 us
;               = 104.17   CPU cycles
;
;********************************************************
;
;    Output the character in W. Assumes Mac is ready.
;       
;    Uses W
;

putchr    movwf    S_Wtemp        ; Character being output

    movlw    0x08        ; Bit count
    movwf    S_count

    bcf    S_out        ; Send a 0 - Start bit

put_clp    movlw    0xE7        ; Delay "104" cycles
txd_0    addlw    0x01
    bne    txd_0

    rrf    S_Wtemp,f    ; Transmit a bit
    bcs    t_0

    bcf    S_out        ; Send a 0
    bra    tx_1

t_0    bsf    S_out        ; Send a 1

tx_1    decfsz    S_count,f    ; Done all bits?
    goto    put_clp

    movlw    0xE7        ; Delay for last data
txd_1    addlw    0x01
    bne    txd_1

    bsf    S_out        ; Transmit two stop bit

    movlw    0xCD
txd_9    addlw    0x01
    bne    txd_9
    
    return
 
;********************************************************************
;    Tail End Charlie
;********************************************************************    
; initialize eeprom locations

        ORG 0x2100

        DE  0x00, 0x00, 0x00, 0x00    ; Unused (reserved for later)
        DE  0x00, 0x00, 0x00, 0x00    ; IF Offset 1 Low  BFO ????
        DE  0x00, 0x00, 0x00, 0x00    ; IF Offset 2 High BFO ????
        DE  0x00, 0x00, 0x00, 0x00    ; IF Offset 3 No   BFO -AM-
        DE  0xfa, 0xff, 0x5f, 0x00    ; 4.000 MHz initial calibration

END
```

Ric.


----------



## trifoncar (Nov 3, 2013)

Gracias Ric,

No lo podré probar hasta mañana lunes por la tarde ya que estoy fuera de mi domicilio y regresaré mañana.

Un saludo


----------



## trifoncar (Nov 4, 2013)

Hola de nuevo!

Ya de regreso del “puente” he podido efectuar las pruebas que quería hacer para intentar evitar que los datos de la frecuencia saliesen repartidos en las dos líneas del display.

Como la más cómoda era la de Ric, ya que me había dejado el código con una modificación efectuada, lo he compilado y lo he probado.
Bien, pues ¡Funciona perfectamente! ¡Gracias de nuevo, Ric! Has acertado con tu modificación. El frecuencímetro marca perfectamente y con todos los datos en la primera línea. Para no entender mucho de programación, como dices, ¡a mí me lo has arreglado perfectamente! 

	Debido a que funciona correctamente, me he animado a subir un nuevo vídeo con las mismas pruebas que efectué anteriormente, pero con el prescaler MB506, a saber:

-	con un módulo oscilador de 100,00 Mhz 
-	con un walkie (de ocho canales) que trabaja en 446 Mhz

Con el módulo oscilador ade 100,00 Mhz no he logrado medir la frecuencia fundamental. Siempre se me ha deslizado a 300,00 Mientras que con el prescaler U664BS y un pequeño condensador en serie no hubo problemas.

Con los walkies ha ido todo muy bien. He puesto los datos que he obtenido en una prueba anterior, en una hoja de cálculo que se ve en el video, para no alargar demasiado la duración del mismo, pero los datos son prácticamente los mismos como se verá en dicho video.

La precisión es realmente buena ya que las desviaciones respecto de las frecuencias por canal detalladas en el manual (y que también se ven en la tercera columna de la hoja de cálculo del video) son del orden de varias diezmillonésimas o lo que es lo mismo, del orden de uno a tres cientos de hercios. Como el prescaler está dividiendo por 256, es aproximadamente esa la desviación. Es decir, mínima, bajo mi punto de vista.

	Con esto, queda comprobado perfectamente el funcionamiento del frecuencímetro de Phil Rice sin prescaler (probado por mí hasta 33,3 Mhz), con prescaler U664BS (utilizando el divisor 64) (en 100.00, de 87 a 108 Mhz [emisora de FM] y 446 Mhz), y con el prescaler MB506 utilizando el divisor /256 (a 100,00 con la salvedad indicada, y 446 Mhz).

	Me gustaría poder probarlo a frecuencias más elevadas, en particular con el MB506, porque teóricamente llega a 2,4 Ghz, pero no dispongo de fuente con esa frecuencia ya que, aunque creía que detectaría el wifi de un router, he podido leer en varios sitios que emiten muy corto espacio de tiempo a esa frecuencia y además, está muy “desparramada” o no concentrada.

	Tampoco dispongo, de momento, de micrófonos inalámbricos que creo que trabajan sobre los 860 Mhz, pero si algún día consigo alguno, lo probaré y lo haré saber aquí.

	Por lo demás, iré exponiendo aquí los avances en el montaje definitivo sobre placa, con fotos y videos (el prescaler en “Manhattan”).

Un saludo y, gracias de nuevo a Ric, Miguelus, Fogonazo y resto de foreros.

P.D.: Varias veces he dicho multiplicador en vez de divisor, espero que me disculpéis.

Video:


----------



## ricbevi (Nov 4, 2013)

"@trifoncar" me alegro que te funcione las modificaciones...ya que vi el video y veo como visualiza en el display los datos te adjunto algo para que pruebes a ver que pasa y si te gusta.
En programación/computación ando desde el '79 y algo por mas "burro" que uno sea aprende, pero es complicado analizar algo echo por otra persona y entenderlo para así modificar lo a nuestro gusto. Desde hace mucho solo uso lenguajes de alto nivel por eso decía que no es mi fuerte el asembler. Mí primer frecuencimetro lo realice por los años 80 y obviamente no era con microprocesador si no en base al 74C926, como prescaler usaba el 74LS90 en baja frecuencia y el 11C90 en alta frecuencia y el método de medición era el descripto por "Miguelus" de "ventana" de 0.1S, 1S y 10S para mediciones mas justas.
Te sugiero para completar este post que en la medida de lo posible subas los esquemáticos de la modificaciones para así serle de utilidad a futuros consultantes.  
Suerte con la pasada en limpio del circuito.
Saludos.

Ric.


```
;*******************************************************************
;
;    "Digital" Frequency display with /64 prescaler & no offsets
;
;    Crystal freq. = 4.000MHz +/- a bit
;
;*******************************************************************
;
;    First, let us choose our weapon - 16F84 or 16F628
;

;    Comment out the next line [;#define F84] if using a 16F628

#define    F84

#ifndef    F84
    #define    F628
#endif


;*******************************************************************
;
;    Some Testing Stuff(tm)
;

;#define    testing        1    ; Comment out when testing finished

;#define    Two_Line    1    ; Un-comment for two line displays


;************************ REVISION HISTORY *************************
;
;    FM1.000    Originally from FM3/4 9:39pm 14 May 2002
;        As implemented in experimental 3.5MHz receiver
;
;*******************************************************************
;
;    FM1.003    Fixed? major silliness in LO-IF code
;        Re-wrote USB/LSB suffix code
;        Added #defines for crook displays
;        Added #defines for two line displays
;        Wrapped #ifdef ... endif around debugging code
;
;*******************************************************************
;
;    FM1.004    Added code to allow user to fix crook display
;        Deleted #defines for crook displays
;        Pin 18 is now input. 1 = good display, 0 = crook
;
;*******************************************************************
;
;    FM2.000    New Hardware! Deleted external counter & gating
;        Now uses the same scheme as the LC Meter, with the
;        third byte of the count implemented in the PIC.
;        Basically, the "output" of the timer register is
;        counted within the gate timing loop.
;
;*******************************************************************
;
;    FM2.001    Discovered that I don't need to use RA0 as a gate
;        cos RA4 can be used as a timer input, even when
;        defined as an output - all that is required is to
;        set it high to count or low to inhibit.
;        Jeez, Microchip are smart arses.
;        I dunno why I didn't spot this long ago.
;        (Can't be used on the LC Meter, cos its oscillator
;        needs to be clamped HIGH, not low as in this case).
;
;*******************************************************************
;
;    FM2.002    Added 9600 baud serial output via RA0
;
;*******************************************************************
;
;    FM2.003    Rewrote RollOver subroutine to use INTCON,T0IF bit.
;        Incorporated two bits from OvrFlow counter
;        to extend range to over 80MHz.
;
;*******************************************************************
;
;    FM2.004    Changed to 32 bit counting.
;
;*******************************************************************
;
;    FM2.005    Added "Calibrate" mode.
;
;*******************************************************************
;
;    FM2.006    Moved "divide by 4" to increase resolution of
;        the stored IF offsets
;
;*******************************************************************
;
;    FM2.007    Moved "check for rollover" out of the inner MS400
;        timing loop and adjusted loop count appropriately
;        The aim - to improve the resolution of the software
;        calibration by a factor of around 13 to 15 times.
;
;*******************************************************************
;
;    fm2b.007    Ported to 16F628
;    FM2c.007    Introduced macros
;    fm2.008        Renumbered
;
;*******************************************************************
;
;    fm2.009        Cleaned up AM IF Offset calculation
;            Converted some inline code to subroutines
;            Created new 32 bit "copy" macro
;            Adjusted calibration slightly
;            Added a "Processor =" message
;            Removed advertising.
;
;*******************************************************************
;
;    ghzfm.000    Added multiply by 64
;            Rendered offsets ineffective
;            changed display format to
;            xxxx.xxxxxx MHz
;            Gate time now 1.000 Second
;
;
;
;*******************************************************************
;o-----o-----o-----o-----o-----o-----o-----o-----o-----o-----o-----o
;*******************************************************************
;
;    Some frequently used code fragments
;    Use macros to make mistreaks consistently.
;
;-------------------------------------------------------------------
;    Select Register Bank 0

bank0    macro
    errorlevel    +302        ; Re-enable bank warning
    bcf        STATUS,RP0    ; Select Bank 0
    endm

;-------------------------------------------------------------------
;    Select Register Bank 1

bank1    macro
    bsf        STATUS,RP0    ; Select Bank 1
    errorlevel    -302        ; disable warning
    endm

;-------------------------------------------------------------------
;    Copy a 32 bit thing from one place to another

copy    macro    from,to

    movf    from+0,W
    movwf    to+0

    movf    from+1,W
    movwf    to+1

    movf    from+2,W
    movwf    to+2

    movf    from+3,W
    movwf    to+3

    endm

;*******************************************************************
;
;    CPU configuration
;

#ifdef    F84
    MESSG        "Processor = 16F84"
    #define     RAMStart    0x0C    ; by VK3BHR
    processor    16f84
    include        <p16f84.inc>
    __config    _HS_OSC & _PWRTE_ON & _WDT_OFF
#endif

#ifdef    F628
    MESSG        "Processor = 16F628"
    #define     RAMStart    0x20
    processor    16f628
    include        <p16f628.inc>
    __config    _HS_OSC & _PWRTE_ON & _WDT_OFF & _CP_OFF & _BODEN_ON & _LVP_OFF
#endif

;*******************************************************************
;
;    I/O configuration
;


#define S_out    PORTA,0x00    ; 9600 baud serial out
#define PUFF    PORTA,0x00    ; Testing counter out

;#define    FIXIT    PORTA,0x01    ; 1 = "good display"
                ; 0 = do CRLF at "chr 8"

#define    PSC    PORTA,0x01    ; 1 = multiply by 64
                
#define    ENA    PORTA,0x02    ; Display "E"
#define    RS    PORTA,0x03    ; Display "RS"
#define    CLAMP    PORTA,0x04    ; Pull-down the timer input

#define    Store    PORTB,0x04    ; Pin 10, 0 = Measure BFO
#define    Add_LO    PORTB,0x05    ; Pin 11, 0 = RF := LO + IF
                ;         1 = RF := | LO + (-IF) |
#define    BFO_Lo    PORTB,0x06    ; Pin 12, 0 = BFO on lower freq.
#define    BFO_Hi    PORTB,0x07    ; Pin 13, 0 = BFO on higher freq.

#define    Prg_FLG    FLAGS,0x05
#define    AMflag    FLAGS,0x03    ; 0 = Don't print USB/LSB suffix

#define    beq    bz        ; Motorola syntax branches
#define    BEQ    bz
#define    BNE    bnz
#define    bne    bnz

#define    BCC    bnc
#define    bcc    bnc
#define    BCS    bc
#define    bcs    bc

#define    BRA    goto
#define    bra    goto

;*******************************************************************
;
;    file register declarations: uses only registers in bank0
;    bank 0 file registers begin at 0x20 in the 16F628
;
;*******************************************************************

    cblock    RAMStart

    dbg0:4            ; Debugging stuff
    dbg1:4
    dbg2:4
    dbg3:4
    dbg4:4
    dbg5:4


    bcd:5            ; BCD, MSD first 

    SBflag            ; 0 = Lower BFO frequency
                ; 1 = Higher

    COUNT            ; Bin to BCD convert (bit count)
    cnt            ;                    (BCD BYTES)


    CHR
    TEMP            ; DATS/Putchr temporary
    pmsg_t            ; Used by PMSG

    FLAGS

    S_Wtemp            ; "debug" Variables
    S_count
    D_Wtemp
    D_Stemp
    D_FSR
    D_hex
    
    endc

#ifdef    F84
Part2    equ    D_hex+1        ; Just tack on end
#endif

#ifdef    F628
Part2    equ    0x70        ; $70-7F Visible from all banks
#endif

    cblock    Part2

    COUNT1            ; Used by delay routines
    COUNT2            ; Timing (100ms)
    COUNT3            ; Timing (100ms)
    COUNT4            ; Timing (400ms)

    AccA:4            ; Binary, MSByte first

    AccB:4            ; Intermediate frequency

    Hold:4            ; Used in "cal" mode

    endc

;**********************************************************
;
;    Begin Executable Stuff(tm)
;

    org    0

GO    clrwdt            ; 0 << Reset
    clrf    INTCON        ; 1 No interrupts

#ifdef    F628
    movlw    0x07        ; 2 Comparator off
    movwf    CMCON        ; 3
#endif

    goto    START        ; 4 << Interrupt.

;**********************************************************
;
;    Part of string printer
;

pmsub    movwf    PCL        ; Goto W
    nop            ; Just in case
pm_end    return

;**********************************************************
;
;    Text Strings (stored in RETLWs)
;

mhz    dt    " MHz",0
Spaces    dt    " ",0
USB    dt    "U",0
LSB    dt    "L",0
Prog    dt    "P",0
Cal    dt    "C",0

#ifdef    Two_Line

adv3    dt    "1234567890ABCDEF",0

 endif

;**********************************************************
;
;    Main Program
;

START    call    InitIO        ; INITIALISE PORTS
    CLRF    PORTA
    CLRF    PORTB
    bsf    S_out        ; Serial output to idle
    
    CALL    LCDINIT         ; INITIALIZE LCD MODULE    

;    MOVLW    adv1        ; Sign on
;    call    pmsg

;    btfss    FIXIT        ; Test input 1 = just return
;    CALL    LINE2        ; 0 = fix bad display

;    movlw    adv2
;    call    pmsg
    
;    CALL    MS512        ; Delay for about 1 sec.
;    CALL    MS512        ; 0.512 sec x 2

    CALL    CLEAR

;**********************************************************
;
;    Check if in "Calibrate" mode
;

    btfsc    Store        ; If grounded initially
    goto    newbit        ; then were in "cal"

    MOVLW    0xfa        ; Set initial counter        
    MOVWF    Hold+0        ; value

    MOVLW    0xff        ; 
    MOVWF    Hold+1        ; for a 4 MHZ XTAL

    MOVLW    0x5f
    MOVWF    Hold+2            

    MOVLW    0x00        ; Unused
    MOVWF    Hold+3            

GetCal    call    Measure    
    call    Display
    movlw    Cal        ; Say "we're calibrating"
    call    pmsg
    CALL    HOME

;
;    Adjust Cal value
;

cal_dn    btfsc    BFO_Lo
    goto    cal_up
    
    incf    Hold+2,f    ; Add 1
    bne    inc_xit
    incf    Hold+1,f
    bne    inc_xit
    incf    Hold+0,f
inc_xit    goto    StorCal

cal_up    btfsc    BFO_Hi
    goto    StorCal

;
;    Hold := Hold + (1-)    ; Subtract 1
;

Hadd_2    movlw    0xff        ; Process LS byte
    addwf    Hold+2,F
    bcc    Hadd_1        ; If no carry,do next

    incf    Hold+1,f    ; Else roll over higher
    bne    Hadd_1        ; bytes as appropriate

    incf    Hold+0,f    ; may roll over MSByte
        
Hadd_1    movlw    0xff        ; Process next byte
    addwf    Hold+1,F
    bcc    Hadd_0        ; If no carry,do next

    incf    Hold+0,f    ; may roll over MSByte
        
Hadd_0    movlw    0xff        ; Process next byte
    addwf    Hold+0,F

;
;    Time to save "Cal" value?
;

StorCal    btfss    Store        ; Ready to store it?
    goto    GetCal

    call    MS512        ; Delay 0.5 sec

    btfss    Store        ; De-bounce
    goto    GetCal

    copy    Hold,AccB    ; Write EEPROM from AccB

    movlw    0x10        ; EEADR of Cal value
    call    EE_WR


;**********************************************************
;
;    Begin a new measurement cycle
;

newbit    movlw    0x10        ; EEADR of Cal value
    call    EE_RD        ; in AccB
    
    copy    AccB,Hold    ; Get timing "constant"

    call    HOME        ; Display ready

    clrf    SBflag        ; 0 = Lower BFO frequency
                ; 1 = Higher

    bcf    AMflag        ; 0 = No USB/LSB suffix

    bcf    Prg_FLG

    btfsc    Store        ; Doing "BFO STORE"?
    goto    GetOffs

    call    MS512        ; Delay 0.5 sec

    btfsc    Store        ; De-bounce
    goto    GetOffs

GetIf    call    Measure        ; Get freq in AccA:4

    copy    AccA,AccB    ; For EEPROM Writing

    call    Display        ; Display freq in AccA
    
    movlw    Prog        ; Say "we're programming"
    call    pmsg
    CALL    HOME

    btfss    Store        ; Ready to store it?
    goto    GetIf

    call    MS512        ; Delay 0.5 sec

    btfss    Store        ; De-bounce
    goto    GetIf

    bsf    Prg_FLG        ; Flag "to be stored"

GetOffs    btfss    BFO_Hi        ; Which Offset??
    goto    Get2        ; Point @ EEPROM

    btfss    BFO_Lo        ; 4 bytes each
    goto    Ch2        ; BFO low link only
    goto    Ch3        ; No links

Get2    btfss    BFO_Lo
    goto    Ch0        ; Both links
    goto    Ch1        ; BFO high link only

Ch0    movlw    0x00        ; Offset channel 0 (both links fitted)
    goto    EndOff

Ch1    bsf    AMflag        ; We're gunna print
    comf    SBflag,f    ; that BFO is on higher frequency
    movlw    0x04        ; Offset channel 1 (BFO_Hi link fitted)
    goto    EndOff

Ch2    bsf    AMflag        ; We're gunna print
                ; that BFO is on lower frequency
    movlw    0x08        ; Offset channel 2 (BFO_Lo link fitted)
    goto    EndOff

Ch3    movlw    0x0C        ; Offset channel 3 (no links fitted)
;    goto    EndOff

EndOff    btfsc    Prg_FLG        ; Storing Offset?
    goto    Do_St        ; If not, then

    call    EE_RD        ; must be reading.
    goto    Do_Meas

Do_St    call    EE_WR

;
;    Now have IF in AccB
;

Do_Meas    call    Measure        ; Measure Local Osc Freq.

;
;    Now have LO in "AccA"
;        and  IF in "AccB"
;

Add_Sub    btfss    Add_LO        ; Add or Sub LO freq?
    goto    AddLSB        ; Clear = just add

    call    MinusA        ; RF := |IF - LO|
                ; SBflag is OK

AddLSB    call    AplusB

;
;    Fix overflow. If negative then make positive
;

    btfss    AccA+0,7    ; Set? (=Overflow)
    goto    OK2go        ; Clear = OK 2 print
    
    call    MinusA        ; Make positive and
    comf    SBflag,f    ; Swap USB/LSB

;
;    Display resulting number in AccA
;

OK2go    call    Display        ; display result at last

;
;    Print suffix - USB, LSB or nuffin
;    Now disabled

    btfsc    AMflag        ; Do we print at all?
    goto    trySBf

    movlw    Spaces        ; nuffin = spaces
    goto    EndMsg

trySBf    btfsc    SBflag,0    ; Which sideband?
    goto    pLSB

    movlw    USB        ; USB obviously
    goto    EndMsg

pLSB    movlw    LSB        ; LSB
;    goto    EndMsg

EndMsg    call    pmsg        ; Print selected trailer


#ifdef    Two_Line

    CALL    LINE2        ; WRITE second LINE

    movlw    adv3
    call    pmsg
 endif

    goto    newbit        ; Start next measurement


;**********************************************************
;
;    AccA := AccA + AccB
;

AplusB    movf    AccB+3,W    ; Process LSB
    addwf    AccA+3,F
    bcc    Add_2        ; If no carry,do next

    incf    AccA+2,f    ; Else roll over higher
    bne    Add_2        ; bytes as appropriate

    incf    AccA+1,f
    bne    Add_2

    incf    AccA+0,f    ; may roll over MSByte
    
Add_2    movf    AccB+2,W    ; Process next byte
    addwf    AccA+2,F
    bcc    Add_1        ; If no carry,do next

    incf    AccA+1,f    ; Else roll over higher
    bne    Add_1        ; bytes as appropriate

    incf    AccA+0,f    ; may roll over MSByte
        
Add_1    movf    AccB+1,W    ; Process next byte
    addwf    AccA+1,F
    bcc    Add_0        ; If no carry,do next

    incf    AccA+0,f    ; may roll over MSByte
        
Add_0    movf    AccB+0,W    ; Process next byte
    addwf    AccA+0,F
    return


;**********************************************************
;
;    Negate number in AccA (2's complement form)
;

MinusA    comf    AccA+0,f    ; Complement all bits
    comf    AccA+1,f    ; of number
    comf    AccA+2,f
    comf    AccA+3,f
    
    incf    AccA+3,f    ; Add 1
    bne    N_xit
    incf    AccA+2,f
    bne    N_xit
    incf    AccA+1,f
    bne    N_xit
    incf    AccA+0,f

N_xit    return

;**********************************************************
;
;    Divide AccA:4 by 4
;
;**********************************************************

Div4    call    Div2        ; Divide AccA:4 by 4

;**********************************************************
;
;    Divide AccA:4 by 2
;
;**********************************************************

Div2    rrf    AccA+0,f
    rrf    AccA+1,f    
    rrf    AccA+2,f
    rrf    AccA+3,f
    bcf    AccA+0,7    ; Possible bad carry in.
    return

;**********************************************************
;
;    Multiply AccA:4 by 64
;
;**********************************************************

Mul64    call    Mul2
    call    Mul2
    call    Mul2
    call    Mul2
    call    Mul2        ; then fall through
    call    Mul2
    call    Mul2
    
;**********************************************************
;
;    Multiply AccA:4 by 2
;
;**********************************************************

Mul2    rlf    AccA+3,f
    rlf    AccA+2,f    
    rlf    AccA+1,f
    rlf    AccA+0,f
    bcf    AccA+3,0    ; Possible bad carry in.
    return
;**********************************************************
;
;    Print String addressed by W
;    Note: Strings are in program space
;

pmsg    movwf    pmsg_t        ; Temp for pointer

pm1    movf    pmsg_t,W    ; Get current pointer
    call    pmsub
    andlw    0xff        ; Test returned value
    beq    pm_end        ; NULL = All done
    call    DATS
    incf    pmsg_t,F
    goto    pm1

;**********************************************************
;
;    Delay for 1000ms (trimmed for actual clock freq)
;    Check for Timer register roll over and count 'em
;
;    Uses: W, COUUNT1, COUNT2, COUNT3 & others
;
;**********************************************************

MS1000    MOVF    Hold+0,w    ; 100 MS DELAY LOOP        
    MOVWF    COUNT1        ; 4 MHZ XTAL

    MOVF    Hold+1,w    ; Count up
    MOVWF    COUNT2        ; to 24 bit overflow

    MOVF    Hold+2,w
    MOVWF    COUNT3

L3    INCFSZ    COUNT3,F
    GOTO    L3
    
    call    RollOver    ; Check for Timer0 RollOver

    INCFSZ    COUNT2,F
    GOTO    L3

    INCFSZ    COUNT1,F
    GOTO    L3

    RETLW    0

;**********************************************************
;
;    SEND A COMMAND BYTE TO LCD DISPLAY MODULE    
;

STROBE    BCF    RS        ; SELECT COMMAND REGISTER
    GOTO    CM

;**********************************************************
;
;    Put a BCD nybble to display
;

PutNyb    ANDLW    0x0F        ; MASK OFF OTHER PACKED BCD DIGIT
    ADDLW    0x30        ; Convert BIN to ASCII

;**********************************************************
;
;    Put a data byte to display
;

DATS    movwf    TEMP        ; Save character for LCD
    call    putchr
    movf    TEMP,w
    
    BSF    RS        ; SELECT DATA REGISTER
CM    MOVWF    CHR        ; STORE CHAR TO DISPLAY
    SWAPF    CHR,W        ; SWAP UPPER AND LOWER NIBBLES (4 BIT MODE)

    call    PB_dly

    MOVF    CHR,W        ; GET CHAR AGAIN 

;**********************************************************
;
;    Put 4 bits to LCD & wait (untrimmed)
;

PB_dly    ANDLW    0x0F        ; MASK OFF UPPER 4 BITS
    MOVWF    PORTB        ; SEND DATA TO DISPLAY        
    BSF    ENA        ; ENA HIGH
    NOP            
    BCF    ENA        ; ENA LOW 
                ; Fall into 200us DELAY subroutine

;**********************************************************
;
;    Delay for 200us (untrimmed)
;
;    Uses: W, COUNT1
;
;**********************************************************

D200us
DELAY    MOVLW    0x42        ; DELAY 200us
    MOVWF    COUNT1    

NXT5    DECFSZ    COUNT1,F
    GOTO    NXT5    

    RETLW    0

;**********************************************************
;
;    Delay for 2ms (untrimmed)
;
;    Uses: W, COUNT2, COUNT1
;
;**********************************************************

MS2    MOVLW    0x0A        ; DELAY 2ms
    MOVWF    COUNT2

LP15    call    D200us

    DECFSZ    COUNT2,F
    GOTO    LP15

    RETLW    0        

;**********************************************************
;
;    Delay for 512ms (untrimmed)
;
;    Uses: W, COUNT3, COUNT2, COUNT1
;
;**********************************************************

MS512    clrw            ; 0 -> 256 loops

;**********************************************************
;
;    Delay for multiples of 2ms (untrimmed)
;
;    Uses: W, COUNT3, COUNT2, COUNT1
;
;**********************************************************

MS2xW    MOVWF    COUNT3    

LPx15    call    MS2

    DECFSZ    COUNT3,F
    GOTO    LPx15

    RETLW    0        

;******************************************************************
;
;    Convert 32-bit binary number at <AccA:4> into a bcd number
;    at <bcd:5>. Uses Mike Keitz's procedure for handling bcd 
;    adjust. Microchip AN526
;

B2_BCD

b2bcd    movlw    .32        ; 32-bits
    movwf    COUNT        ; make cycle counter

    clrf    bcd+0        ; clear result area
    clrf    bcd+1
    clrf    bcd+2
    clrf    bcd+3
    clrf    bcd+4
    
b2bcd2  movlw    bcd        ; make pointer
    movwf    FSR
    movlw    .5        ; Number of BCD bytes?
    movwf    cnt        ; 2 BCD digits per byte

; Mike's routine:

b2bcd3    movlw    0x33    
        addwf    INDF,f        ; add to both nybbles
        btfsc    INDF,3        ; test if low result > 7
        andlw    0xf0        ; low result >7 so take the 3 out
        btfsc    INDF,7        ; test if high result > 7
        andlw    0x0f        ; high result > 7 so ok
        subwf    INDF,f        ; any results <= 7, subtract back
        incf    FSR,f        ; point to next
        decfsz    cnt,f
        goto    b2bcd3
        
        rlf    AccA+3,f    ; get another bit
        rlf    AccA+2,f
        rlf    AccA+1,f
        rlf    AccA+0,f

        rlf    bcd+4,f        ; put it into bcd
        rlf    bcd+3,f
        rlf    bcd+2,f
        rlf    bcd+1,f
        rlf    bcd+0,f

        decfsz    COUNT,f        ; all done?
        goto    b2bcd2        ; no, loop
        return            ; yes


;*********** INITIALISE LCD MODULE 4 BIT MODE ***********************

LCDINIT    CALL    MS512        ; Wait 0.512 sec for LCD  RESET

    BCF    RS        ; REGISTER SELECT LOW
    BCF    ENA        ; ENABLE LINE LOW
    
    MOVLW    0x03        ; 1
    call    PB_dly
    
    CALL    MS512        ; WAIT FOR DISPLAY TO CATCH UP

    MOVLW    0x03        ; 2
    call    PB_dly

    MOVLW    0x03        ; 3
    call    PB_dly

    MOVLW    0x02        ; Fn set 4 bits
    call    PB_dly
    
    MOVLW    0x28        ; DISPLAY 2 Line , 5x7 Dot's
    CALL    STROBE        ; Suggested by PA0EJH
    CALL    DELAY        
    
    MOVLW    0x0C        ; 0x0C DISPLAY ON
    CALL    STROBE
    CALL    DELAY        
    
    MOVLW    0x06        ; 0x06 ENTRY MODE SET
    CALL    STROBE
    CALL    DELAY

    MOVLW    0x01        ; 0x01 CLEAR DISPLAY
    CALL    STROBE
    CALL    MS2

    RETLW    0


;************ MOVE TO START OF LINE 2 *****************

LINE2    MOVLW    0xC0        ; ADDRESS FOR SECOND LINE OF DISPLAY
    CALL    STROBE
    goto    DELAY


;************ CLEAR DISPLAY ***************************

CLEAR    MOVLW    0x01        ; COMMAND TO CLEAR DISPLAY
    CALL    STROBE
    goto    MS2        ; LONGER DELAY NEEDED WHEN CLEARING DISPLAY


;*********** MOVE TO HOME *****************************

HOME    call    crlf        ; Serial

    MOVLW    0x02        ; COMMAND TO HOME LCD DISPLAY
    CALL    STROBE
    goto    MS2


;********************************************************************
;       Initialise Input & Output devices
;********************************************************************

InitIO    bank1

    movlw    0x37        ; Option register
    movwf    OPTION_REG    ; Port B weak pull-up enabled
                ; INTDEG Don't care
                ; Count RA4/T0CKI
                ; Count on falling edge
                ; Prescale Timer/counter
                ; divide Timer/counter by 256

                ; PORTA:-
    movlw    0x02        ; initialise data direction
                ; 1 = input, 0 = output
                ;
                ; PORTA has 5 pins     4 3 2 1 0
                ; 0x02       =   0 0 0 0 0 0 1 0
                ;
    movwf    TRISA        ; PORTA<0>   = Serial + Debugging Out
                ; PORTA<1>   = FIXIT (input)
                ; PORTA<2>   = LCD "E" Out
                ; PORTA<3>   = LCD "RS" Out
                ; PORTA<4>   = "Input" with pull-down
                ;              Actually an output.
                ; PORTA<5:7> = not implemented in 16F84
                ;
                ; PORTB:-
    movlw    0xf0        ; initialise data direction
                ; PORTB has 8 pins
                ; port pin       7 6 5 4 3 2 1 0
                ; 0xf0       =   1 1 1 1 0 0 0 0
                ;
    movwf    TRISB        ; PORTB<0>   = LCD "DB4"
                ; PORTB<1>   =     "DB5"
                ; PORTB<2>   =     "DB6"
                ; PORTB<3>   =     "DB7"
                ; PORTB<4>   = Input
                ; PORTB<5>   = Input
                ; PORTB<6>   = Input
                ; PORTB<7>   = Input

    bank0

    return    

;**********************************************************
;
;    Measure Frequency. Stash in "AccA:4"
;

Measure    bcf    CLAMP        ; CLOSE GATE for safety

    bsf    PORTB,2        ; For compatibility with
    bsf    PORTB,3        ; Version 1 hardware
    
    bcf    INTCON,T0IF    ; Clear any previous overflow
  
    CLRF    TMR0        ; RESET INTERNAL COUNT (INCLUDING PRESCALER)
                ; See page 27 Section 6.0

    CLRF    AccA+0        ; Ready to receive 32 bit number
    CLRF    AccA+1
    CLRF    AccA+2
    CLRF    AccA+3

    bsf    CLAMP        ; OPEN GATE

    CALL    MS1000        ; 1.0 sec DELAY

    bcf    CLAMP        ; CLOSE GATE (COUNT COMPLETE)
    nop            ; and allow time for
    nop            ; the registers to catch up
    nop
    nop
    nop
    
    call    RollOver    ; Final check, just in case

    MOVF    TMR0,W        
    MOVWF    AccA+2

;    Now empty the prescaler

PSC1    bank1

    bcf    OPTION_REG,T0SE    ; Clock the prescaler
    nop
    bsf    OPTION_REG,T0SE

    bank0
    
    DECF    AccA+3,F    ; Decrement the counter
    
    movf    TMR0,W        ; Has TMR0 changed?
    xorwf    AccA+2,W    ; if unchanged, XOR -> 0

    beq    PSC1
        
; AccA : AccA+1 : AccA+2 : AccA+3 now holds 32 bit result
; Rollover subroutine has set AccA+0 and AccA+1 suitably.

    return

;**********************************************************
;
;    Account for TMR0 overflows when counting
;    Check at regular intervals and handle as
;    necessary.
;
;    Needs to be done at less than 936us (@ 70MHz in)
;    intervals, or else it can lose counts.
;

RollOver

    btfss    INTCON,T0IF    ; Rolled over?
    goto    RO3        ; No

RO1    bcf    INTCON,T0IF    ; Yes. ACK!

    INCF    AccA+1,f    ; Count it
    bne    RO2        ; Overflowed?

    incf    AccA+0,f    ; No need to check

RO2    return

;    Balance path lengths

RO3    nop
    nop
    goto    RO2

;**********************************************************
;
;    Display frequency
;
;    Display contents of AccA+0...AccA+3 on LCD
;    First convert to BCD, Then ASCII (nybble at a time)
;
;    In this version, multiply ACCA:4 by 64 since gate
;    time = 1.0 second and ext prescale=64
;

Display    btfsc    PSC        ; 1 = prescaler active = *64        

    call    Mul64        ; Account for prescaler

    CALL    B2_BCD        ; CONVERT all AccA TO BCD

;    Perform Leading Zero Blanking on first 3 digits

    swapf    bcd+0,W        ; 1000's of MHz
    andlw    0x0F        ; MASK OFF OTHER PACKED BCD DIGIT
    bne    NoB1K

    MOVLW    0x20        ; YES PRINT A BLANK SPACE
    CALL    DATS

    movf    bcd+0,W        ; 100's of MHz
    andlw    0x0F        ; MASK OFF OTHER PACKED BCD DIGIT
    bne    NoB100

    MOVLW    0x20        ; YES PRINT A BLANK SPACE
    CALL    DATS

    swapf    bcd+1,W        ; 10's of MHz
    andlw    0x0F        ; MASK OFF OTHER PACKED BCD DIGIT
    bne    NoB10

    MOVLW    0x20        ; YES PRINT A BLANK SPACE
    CALL    DATS

    goto    NoB1

;    Handle rest of number non blanked

NoB1K    SWAPF    bcd+0,W        ; 1000's of MHz
    CALL    PutNyb

NoB100    MOVF    bcd+0,W        ; 100's of MHz
    CALL    PutNyb

NoB10    SWAPF    bcd+1,W        ; 10's of MHz
    CALL    PutNyb

NoB1    MOVF    bcd+1,W        ; 1's of MHz
    CALL    PutNyb

    MOVLW    '.'        ; Decimal Point
    CALL    DATS

    SWAPF    bcd+2,W        ; 100's of KHz
    CALL    PutNyb

    MOVF    bcd+2,W        ; 10's of KHz
    CALL    PutNyb

    SWAPF    bcd+3,W        ; 1's of KHz
    CALL    PutNyb

;    CALL    LINE2

    MOVLW    ','        ; Decimal Coma 
    CALL    DATS
    
    MOVF    bcd+3,W        ; 100's of Hz
    CALL    PutNyb

    SWAPF    bcd+4,W        ; 10's of Hz
    CALL    PutNyb

    MOVF    bcd+4,W        ; 1's of Hz
    CALL    PutNyb

    movlw    mhz        ; WRITE " Mhz" AT end OF LINE
    goto    pmsg        ; includes RETURN


;********************************************************************
;    Read EEPROM into "AccB"  (AccB must be visible in both
;    W -> memory to read          memory banks 0 & 1)
;********************************************************************    

EE_RD

#ifdef    F628
    bank1
#endif

    MOVWF    EEADR        ; Address to read

#ifdef    F628
    bank0
#endif
    
    XORLW    0x0C        ; Special case (no links)
    BEQ    AVERAGE

    CALL    EE_R
    MOVWF    AccB+0

    CALL    EE_Rinc
    MOVWF    AccB+1

    CALL    EE_Rinc
    MOVWF    AccB+2

    CALL    EE_Rinc
    MOVWF    AccB+3

    RETURN

;--------------------------------------------------------------------

#ifdef F84

EE_Rinc    INCF    EEADR,F        ; bump address

EE_R    bank1
    BSF    EECON1,RD    ; EE Read
    bank0
    MOVF    EEDATA,W    ; W = EEDATA

    RETURN
#endif

;--------------------------------------------------------------------

#ifdef    F628

EE_Rinc    bank1
    INCF    EEADR,F        ; bump address

EE_R    bank1
    BSF    EECON1,RD    ; EE Read
    MOVF    EEDATA,W    ; W = EEDATA
    bank0

    RETURN
#endif

;--------------------------------------------------------------------

AVERAGE    movlw    0x04        ; AM - use avg BFO freq.
    call    EE_RD        ; Read in one BFO freq
    copy    AccB,AccA    ; Into AccA

    movlw    0x08        ; Then second
    call    EE_RD        ; into AccB

    call    AplusB        ; Add 'em
    call    Div2        ; get average in AccA
    copy    AccA,AccB    ; and in AccB
    return
    

;********************************************************************
;    Write EEPROM from "AccB"  (AccB must be visible in both
;    W -> memory to write          memory banks 0 & 1)
;********************************************************************    

#ifdef    F84

EE_WR    MOVWF    EEADR        ; Address to write

    MOVF    AccB+0,W    ; Data byte #0
    CALL    EE_W

    MOVF    AccB+1,W    ; Data byte #1
    CALL    EE_Winc

    MOVF    AccB+2,W    ; Data byte #2
    CALL    EE_Winc

    MOVF    AccB+3,W    ; Data byte #3
    CALL    EE_Winc

    RETURN

EE_Winc    INCF    EEADR,F        ; bump address
    
EE_W    MOVWF    EEDATA
    bank1
    BSF    EECON1,WREN    ; Enable Write
    MOVLW    0x55        ;
    MOVWF    EECON2        ; Write 0x55
    MOVLW    0xAA        ;
    MOVWF    EECON2        ; Write 0xAA
    BSF    EECON1,WR    ; Set WR bit (begin write)

EE_W2    BTFSC    EECON1,WR    ; Wait for write to finish
    GOTO    EE_W2

    BCF    EECON1,EEIF    ; clear interrupts
    bank0

    RETURN    

#endif

;--------------------------------------------------------------------

#ifdef    F628

EE_WR    bank1
    MOVWF    EEADR        ; Address to write

    MOVF    AccB+0,W    ; Data byte #0
    CALL    EE_W

    MOVF    AccB+1,W    ; Data byte #1
    CALL    EE_Winc

    MOVF    AccB+2,W    ; Data byte #2
    CALL    EE_Winc

    MOVF    AccB+3,W    ; Data byte #3
    CALL    EE_Winc

    bank0
    RETURN

    errorlevel    -302    ; In Bank 2

EE_Winc    INCF    EEADR,F        ; bump address
    
EE_W    MOVWF    EEDATA
    BSF    EECON1,WREN    ; Enable Write
    MOVLW    0x55        ;
    MOVWF    EECON2        ; Write 0x55
    MOVLW    0xAA        ;
    MOVWF    EECON2        ; Write 0xAA
    BSF    EECON1,WR    ; Set WR bit (begin write)

EE_W2    BTFSC    EECON1,WR    ; Wait for write to finish
    GOTO    EE_W2

    bank0
    BCF    PIR1,EEIF    ; clear interrupts
    bank1
    RETURN    

    errorlevel    +302
#endif


;********************************************************************
;    Testing counter 
;********************************************************************    

ctest    movlw    0xfe        ; MS byte of loop count
    movwf    COUNT3        ; Counted upward till it overflows

    movlw    0x1d
    movwf    COUNT2

    movlw    0xc0
    movwf    COUNT1

cloop    bcf    PUFF        ; Toggle counter input once
    bsf    PUFF

    incfsz    COUNT1,f
    goto    cloop

    incfsz    COUNT2,f
    goto    cloop

    incfsz    COUNT3,f
    goto    cloop

    return

;***********************************************************************
;
;    Debugging Memory & Register dump
;

debug
    MOVWF    D_Wtemp        ; Copy W to temp register,
    SWAPF    STATUS,W    ; Swap status to be saved into W
    MOVWF    D_Stemp        ; Save status to D_Stemp register
    movf    FSR,W        ; Save FSR
    movwf    D_FSR
    
    movlw    0x57        ; W=
    call    putchr
    movlw    0x3d
    call    putchr

    movf    D_Wtemp,w
    call    hex_2
    
    movlw    0x20        ; 2 spaces, just to be neat
    call    putchr
    movlw    0x20
    call    putchr
    
    movlw    0x53        ; SR=
    call    putchr
    movlw    0x52
    call    putchr
    movlw    0x3d
    call    putchr

    movf    D_Stemp,w
    call    hex_2
    
    call    crlf        ; Serial

    clrf    FSR        ; Ready for memory dump

D_loop    movf    0,W        ; Read indirect
    call    hex_2
    movlw    0x20
    call    putchr
    incf    FSR,f        ; to next byte

    movf    FSR,w        ; end of line?
    andlw    0x0F
    bne    next_ln

    call    crlf
    bra    chk4end

next_ln    andlw    0x03        ; Groups of 4
    bne    chk4end

    movlw    0x20
    call    putchr

chk4end    movf    FSR,w        ; All done?
    xorlw    0x80
    bne    D_loop

    call    crlf
    call    crlf
    
    movf    D_FSR,W        ; Restore FSR
    movwf    FSR
    
    SWAPF    D_Stemp,W    ; Swap nibbles in D_Stemp register
                ; and place result into W

    MOVWF    STATUS        ; Move W into STATUS register
                ; (sets bank to original state)
    SWAPF    D_Wtemp,F    ; Swap nibbles in D_Wtemp and place result in D_Wtemp
    SWAPF    D_Wtemp,W    ; Swap nibbles in D_Wtemp and place result into W
    
    return

    
;***********************************************************************
;
;    Print CRLF to serial
;

crlf    movlw    0x0d        ; CRLF
    call    putchr
    movlw    0x0a
    goto    putchr

;***********************************************************************
;
;    Print W as 2 Hex digits
;

hex_2    movwf    D_hex
    swapf    D_hex,w        ; Get big bit
    call    hex_3

    movf    D_hex,w        ; Get little bit

hex_3    andlw    0x0f        ; keep bottom 4 bits
    addlw    0xF6
    bcc    hex_4
    addlw    0x07        ; binary A -> ASCII A
hex_4    addlw    0x3A        ; binary 0 -> ASCII 0
;    goto    putchr

;********************************************************
;
;    Output Routines for PIC16F84
;    
;    Clock is 4.0 MHz.
;    ie. 1.0 us per cycle = 4/Fosc.
;
;    9600 Baud  = 104.17 us
;               = 104.17   CPU cycles
;
;********************************************************
;
;    Output the character in W. Assumes Mac is ready.
;       
;    Uses W
;

putchr    movwf    S_Wtemp        ; Character being output

    movlw    0x08        ; Bit count
    movwf    S_count

    bcf    S_out        ; Send a 0 - Start bit

put_clp    movlw    0xE7        ; Delay "104" cycles
txd_0    addlw    0x01
    bne    txd_0

    rrf    S_Wtemp,f    ; Transmit a bit
    bcs    t_0

    bcf    S_out        ; Send a 0
    bra    tx_1

t_0    bsf    S_out        ; Send a 1

tx_1    decfsz    S_count,f    ; Done all bits?
    goto    put_clp

    movlw    0xE7        ; Delay for last data
txd_1    addlw    0x01
    bne    txd_1

    bsf    S_out        ; Transmit two stop bit

    movlw    0xCD
txd_9    addlw    0x01
    bne    txd_9
    
    return
 
;********************************************************************
;    Tail End Charlie
;********************************************************************    
; initialize eeprom locations

        ORG 0x2100

        DE  0x00, 0x00, 0x00, 0x00    ; Unused (reserved for later)
        DE  0x00, 0x00, 0x00, 0x00    ; IF Offset 1 Low  BFO ????
        DE  0x00, 0x00, 0x00, 0x00    ; IF Offset 2 High BFO ????
        DE  0x00, 0x00, 0x00, 0x00    ; IF Offset 3 No   BFO -AM-
        DE  0xfa, 0xff, 0x5f, 0x00    ; 4.000 MHz initial calibration

END
```


----------



## miguelus (Nov 4, 2013)

Buenas noches.

Como comenta ricbevi, es muy difícil modificar un programa hecho por otra persona y más cuando la programación no es lo nuestro.

Estos días de fiesta he estado jugando algo con el Prográmita pero con la versión "simple" sin preescaler.

La razón es que tengo varios Frecuencímetros y el rango hasta los 2,4Ghz lo tengo cubierto.

Pero necesitaba uno para acoplarlo a un oscilador para comprobar Cristales de Cuarzo.

He estado jugando con la versión sin Prescaler, he quitado toda la parte del programa que gestiona la salida RS232 ya que no lo necesitaba.

He hecho una modificación que creo que es muy útil, la modificación gestiona la forma de visualizar la Frecuencia...

*00.000000Mhz* lo visualiza de otra manera...
*00.000.000 - Mhz*. Esto produce una visualización más amigable

Por medio de un Puente (luego será un interruptor) la visualización la hace de esta forma...

*00.000 - Mhz* ya que para muchas medidas es suficiente con tres decimales.

He anulado toda la parte que gestiona USB, LSB, CAL...

Ahora estoy tratando de quitar del programa todas estas Rutinas, pero tengo poco tiempo para estos menesteres 

Este Frecuencímetro no es una gran cosa, pero suficiente para muchas aplicaciones en las que se necesita tener un medidor dedicado para medir una frecuencia.

Otra modificación futura será poner una base de tiempo de mejor calidad que un simple Cuarzo

Mis felicitaciones a ricbevi por el magnífico trabajo que ha relalizado en los Post anteriores  

Sal U2


----------



## trifoncar (Nov 4, 2013)

Hola de nuevo!

 Ric, he probado tu nuevo código y es mucho más "amigable". Me gusta.
Ya tenía pensado recapitular un poco lo aparecido y modificado hasta ahora, pero antes quería encontrar una explicación al porqué no me aparece la frecuencia fundamental al intentar medir la frecuencia del módulo oscilador de 100,00 Mhz (aparecen 299,990xxx Mhz) que probablemente pueda corregirse con un condensador y alguna resistencia. También quería "redondear" las pruebas con una lectura entre 800 y 2.400 Mhz. antes de decidir los circuitos definitivos, pero bueno, ya veremos.

Miguelus, tu experimentación del fin de semana ha ido por el mismo camino que el de Ric, hacia una más cómoda lectura de la frecuencia. Estoy, también,  deseando disponer de ese código


----------



## trifoncar (Nov 5, 2013)

Hola una vez más,

  he logrado solucionar la medición correcta del módulo oscilador de 100,00 Mhz; un día de estos subiré todos los esquemas.

Por cierto, pongo 100,00 Mhz. con dos decimales porque es lo que pone en el módulo, y yo entiendo que su precisión llega -por lo menos- hasta el cero del segundo decimal, por lo que -de ser así- la frecuencia a la que oscilará estará entre 99,995 y 100,005. Si alguien sabe que estoy equivocado, por favor, que me corrija. 

De hecho, si calibro el frecuencímetro a la frecuencia exacta del manual del walkie que tengo, al medir la frecuencia del módulo oscilador obtengo 99,994368, que se encuentra justo en la frontera inferior que he indicado (un pelín por debajo, exactamente 632 hz menos, de ese límite inferior de 99,995 Mhz).

Me interesaba mucho solucionar la precisión de la medida del módulo oscilador porque quiero incluirlo en el montaje como referencia de medida para calibrar el frecuencímetro siempre que haga falta.

Una cosa más que se me ha olvidado comentar en el segundo post con vídeo que ya he subido.
El prescaler MB506 toma la señal del walkie sin antena ni cable de ningún tipo estando incluso a un metro de distancia del circuito del prescaler.

Un saludo


----------



## trifoncar (Nov 5, 2013)

Otra vez por aquí,

  iré explicando toda la evolución que estoy experimentando con el montaje que da título a este hilo, incluído el cambio de prescaler (MB506).

  En los últimos post he insistido en utilizar la división /256. ¿Alguien se imagina la razón?

Todo el empeño en dividir por 256 provenía de la suposición (falsa) de que para alcanzar el tope de frecuencia (2,4 Ghz) del prescaler debería de utilizar la división máxima.     :cabezon:

  Bien, en la hoja de especificaciones (datasheet) del MB506 pone que el techo de frecuencia para dicho prescaler es de 2,4 Ghz ...... y eso lo absorbe y lo procesa; y además lo divide por 64, 128 ó 256.

Entonces resulta que *2,4 Ghz son 2.576.980.378 Hz y si lo divido por 256 obtengo 10.066.330 Hz*. que es una frecuencia que el pic 16F84A puede procesar sin ningún problema ya que alcanza los 50 Mhz con garantías.
*Si divido esos 2,4 Ghz por 128 obtengo 20.132.659 Hz*.
*Y si lo divido por 64 obtengo 40.265.318 Hz*

E*l pic 16F84A puede procesar hasta los 50 Mhz y ... por lo visto algo más, pero de cualquier forma, suficiente para procesar esos 40.265.318 Hz que se obtienen al dividir los 2,4 Ghz por 64, por lo que no me hace falta dividir por 256, ya que -incluso con 2,4 Ghz de frecuencia de entrada- el 18F84 puede procesar la frecuencia resultante dividida por 64 y además así se obtiene una precisión cuatro veces mayor que si se dividiese por 256. *

Por favor, si alguien cree que esta deducción no es correcta, que lo comente.

Si efectivamente es así, volveré al código de /64



Un saludo


----------



## crimson (Nov 6, 2013)

Hola trifoncar, yo hice el de DL4YHF, no me acuerdo con qué PIC, creo que era uno como los que usas vos, y llegó cómodo a los 50MHz...











Saludos C


----------



## miguelus (Nov 6, 2013)

Buenos días.

Trifoncar. 

Me alegri que el proyecto esté avanzando en la buena direccíon

Con esos Módulos Osciladores, tienes que tener en cuenta que no están diseñados para ofrecer una gran precisión, pueden tener una tolerancia superior a las +- 10 partes por millón.

Esto se traduce que 100,000 Mhz puede ser 99,999 o 100,001 (+- 1 Khz) 

Como te comenté en un Post anterior, la precisión de un Frecuencímetro está definida por su base de tiempos, en tu caso es el Cuarzo de 4Mhz, el cuál, seguramente es un Cuarzo de lo más normal, de los que venden en las tiendas de Componentes . Para un Frecuencímetro "Serio" esto es inaceptable.

Lo ideal sería, que cuando lo tengas todo bien ordenado y bien motado, pusieras una Base de Tiempo más "Decente" 

En este Frecuencímetro no tiene mucho sentido emplear una resolución de hasta 1Hz, otra cosa sería que empleásemos una buena Base de Tiempos.

Quitándole las tres últimas cifras, el Frecuencímetro va sobrado.

Esto lo he resuelto en la versión basica de software, pero en la versión con Preescaler no lo he intentado ya que para ello he utilizado precisamente ese Bit para cambiar de resolución máxima a resolución reducida, al final lo dejaré con la resolución reducida.

En lo referente a la relación de división del Prescaler  64/128/256, con una division de /64 tienes suficiente para 2,4Ghz, pero no creo que puedas medir Señales WI-FI ya que estas son de muy poca potencia.

Sal U2


----------



## trifoncar (Nov 6, 2013)

crimson dijo:


> Hola trifoncar, yo hice el de DL4YHF, no me acuerdo con qué PIC, creo que era uno como los que usas vos, y llegó cómodo a los 50MHz...
> http://4.bp.blogspot.com/-TA_SeUzgeLg/T4o6pgnu9hI/AAAAAAAAAIU/1MTeqA76bBQ/s1600/dl4yhf1.jpg
> 
> http://3.bp.blogspot.com/-99IerD83xSw/T4o7S1SqoUI/AAAAAAAAAIk/5UcaCnv-W7g/s1600/dl4yhf2.jpg
> ...



Gracias por la información, Crimson,

me parece ver que el pic de la segunda imagen es un *16F628A*.

---------------

Miguelus, gracias también por la información.

Se me ocurren varias preguntas para hacerte.

*¿Es acertado por mi parte poner el módulo oscilador como base para calibrar el frecuencímetro?* Me explico; comentas que dichos módulos osciladores no se caracterizan por su precisión; pues bien, creo que no importa que no sea muy preciso, pero si que importa que sea constante. Si yo supiese que oscila a 99,994750 Mhz y que varía muy poco en su frecuencia de oscilación, creo que podría servir perfectamente para cailbrar; pero si oscila de forma variable entre 99,995 y 100,005 la cosa cambia.
No sé si he explicado la diferencia. Mi duda es si ese tipo de módulos es inexacto pero de frecuencia constante, o por el contrario es inexacto y variable.

Por otra parte, me interesa mucho el cristal del circuito. Yo he puesto el de 4,000 Mhz porque es el que figura en el esquema y al que se refiere el fichero Hex, pero no tengo ningún interés especial en mantenerlo, sobretodo si con otro cristal puedo mejorar la precisión. 
¿*La cosa sería tan fácil como cambiar el cristal y el software?*
¿En que medida se notaría la mejora en la precisión?

Un saludo


----------



## miguelus (Nov 6, 2013)

Buenas tardes.

El tema de la calibración es algo peliagudo, todo depende de la precisión que necesites.

Te pondré un ejemplo, en mi Empresa todo el Instrumental que se utiliza, desde el más simple Multímetro, incluso las llaves Dinamométricas, Generadores, Analizadores, tienen que tener el certificado de calibración dentro de fecha, en caso contrário no se pueden utilizar aunque funcionen perfectamente.

Otra cosa es lo que utilizamos en casa.

Un Frecuencímetro tiene que tener una buena Base de Tiempos, no es suficiente que sea Térmicamente estable, también tiene que estar en la frecuencia correcta.

El Módulo oscilador de 100Mhz que estás empleando no es lo más adecuado, estos Módulos no están diseñados para ese fin.

Cuando mides la frecuencia con tu Frecuencímetro siempre tendrás la duda de dónde esta el error de la medida, el error puede estar en la Frecuencia del Cuarzo de 4Mhz o en el Oscilador de 100Mhz.

La verdad es que, para la mayoría de la aplicaciones "Caseras" no hay que ser tan meticuloso.

Yo, particularmente, tengo un Oscilador de 10Mhz de muy alta estabilidad y precisión, este Oscilador lo utilizo como referencia de los Generadores de RF y Frecuencímetros y Analizador de Espectros, periodicamento lo llevo a mi trabajo y (en secreto  ) lo calibro.

Al Frecuencímetro que nos ocupa se le podría poner un oscilador externo de buena precisión, 

No sé si será fácil encontrar uno de 4Mhz en el mercado, todo sería cuestión de buscar.
Seguramente habría que cambiar una instrucción en el código para configurar el Pic con Oscilador externo.

Pero sinceramente, no creo que sea necesário meterse en ese charco, para casi todo lo que pretendas hacer, así como está, vas a tener suficiente.

En cuanto a lo de "constancia" del Módulo oscilador, tu mismo lo puedes evaluar, vigila la frecuencia de oscilación, con un Soldador caliéntalo, veras la deriva.

Haz lo mismo con el Cuarzo de 4Mhz.

Sal U2


----------



## trifoncar (Nov 7, 2013)

Hola de nuevo,

 Miguelus, con tu argumentación del post anterior me has convencido. Efectivamente .... ¿para que requiero tanta precisión? .... para nada. Si que es cierto que me encantaría construir algo realmente preciso, pero ni los componentes son precisos. Y si se quieren adquirir unos muy precisos, resultan demasiado costosos.
Así que tomaré como referencia de calibración la frecuencia del manual de los walkies que me han prestado y cuando necesite "afinarlos" me acercaré a ver al que me los ha prestado y lo calibraré.
Supongo que la frecuencia de emisión de unos walkies medio decentes será bastante precisa, así que  ... decidido. Aunque mantendré el módulo oscilador en el conjunto con el fin de obtener una calibración "menos precisa".

Cambiando de tema, ahora que vuelvo con la división/multiplicación por 64 resulta que no hay forma de obtener los 100,00 Mhz del módulo oscilador. Siempre obtengo 299,99xxxxx ó 199,99xxxx ¿A que puede ser debido? He combinado resistencias, condensadores y bobinas de todo tipo. Un problema añadido es que no encuentro referencia alguna de este módulo (AQ 100,00 Mhz) en internet (adjunto foto). Si alguien me puede ayudar estaría agradecidísimo.

Lo que no me quedó claro es lo del cuarzo. Yo tengo cristales de mayor frecuencia que 4,000 Mhz. ¿Los puedo utilizar para obtener una mayor precisión?

Un saludo, y gracias de nuevo.

foto : https://www.forosdeelectronica.com/attachment.php?attachmentid=76854&d=1343228408


----------



## miguelus (Nov 7, 2013)

Buenas noches.

El Cambiar la frecuencia del Cristal de Cuarzo del PIC supone tener que cambiar el código ya que este tiene en cuenta la frecuencia del Cuarzo y la duración de las instrucciones.

Por otra parte la precisión de los Osciladores  se mide en PPP (Partes Por Millón) por lo que si quieres que el Oscilador sea de mejor precisión y mejor estabilidad la única solución es emplear una base de tiempos de mayor calidad (y por supuesto de mayor precio  )

En cuanto a que midas 200Mhz con el Oscilador de 100Mhz...

Lo primero ¿Con los Walkis mide bien la Frecuencia?, si esto es afirmativo no te preocupes demasiado el Frecuencímetro está bien, esos Osciladores pueden hacer cosas raras como tener un armónico en esa frecuencia, yo no me preocuparía demasiado.
Ten en cuenta que los Prescaler son dispositivos de Banda Ancha y pueden tener más sensibilidad en unas frecuencias que en otras.
Igualmente, la forma en la que hayas realizado el montaje puede influir en que, el Prescaler, se comporte de forma distinta en unas frecuencias que en otras.


Sal U2


----------



## trifoncar (Nov 7, 2013)

No me ha quedado claro si cambiando el cristal de 4 Mhz por uno de -p.ej. 27 Mhz,- y arreglando el código covenientemente puedo mejorar la precisión del frecuencímetro.

La frecuencia de los walkies la mide correctamente, 446,0xxxxx Mhz. El problema es el módulo oscilador.

Un saludo.


----------



## trifoncar (Nov 8, 2013)

Hola de nuevo,

me he animado a subir los esquemas de los circuitos que estoy manejando y, tras unas horas de diseño, he logrado dibujarlos.

Por supuesto que están sometidos a revisión ya que -a pesar de haberlos comprobado- siempre puede haberse deslizado algún error.
Estos circuitos los tengo funcionando en protoboard (mi próximo trabajo será pasarlos a placa) y , como ya he comentado anteriormente, están comprobados en frecuencias de hasta 446 Mhz.
El diseño del prescaler lo he preparado para que trabaje como divisor por 64, ya que es suficiente para que dentro de las frecuencias que puede manejar el pic 16F84A (llega con seguridad a unos 50) , pueda alcanzarse *teóricamente *el máximo de entrada en el prescaler (2,4 Ghz).

La entrada de la señal al prescaler se puede medir directamente sin sonda (ha sido mi caso al medir la señal de un walkie estando hasta a 2 metros de distancia), o mediante una sencilla sonda, que yo también he probado con éxito.

Las fotos del montaje y videos están en post anteriores.

Un saludo y muchas gracias a todos.

P.D.: no me preguntéis por qué esos valores, simplemente porque han funcionado en las pruebas que he efectuado. Espero con ansiedad críticas y sugerencias de cara a posibles mejoras.


----------



## Daniel Lopes (Nov 8, 2013)

trifoncar dijo:


> Hola de nuevo,
> 
> me he animado a subir los esquemas de los circuitos que estoy manejando y, tras unas horas de diseño, he logrado dibujarlos.
> 
> ...


Con lo uso del preescaler MB506 de la Fujitsu tenemos una divisiõn de 256 bastando para eso unir los terminales "3"(sw1) y "4"(sw2) para lo "5" (gnd), asi fornindo una frequencia mas baja para lo PIC.Estuve estudiando con cariño lo diagrama esquemactico del lo preescaler MB506 que usteds subiste  y detectei alguns equivocos: 01) lo resistor "R2" no es necessario puede eliminarlo , 02)lo correcto valor de "R3" es 2,2Kohmios y no 22Kohmios, 03)lo terminal "5"(gnd) es Gnd y tiene que sener ligado a tierra o 0 Voltios, 04) lo terminal "8"(/in) deve sener conectado a la tierra por un capacitor de 1nF "C7" solamiente eso y nadas mas , 05) lo terminal "8"(/in) no deve sener conectado a lo terminal "5"(gnd), 06) lo resistor "R6" no es necessario y deve sener eliminado.
Tudo eso que aca aclaro es enbasado en informaciones de lo fabricante fornido en la hoja de datos (datasheet).
!Fuerte abrazo!
Att.
Daniel Lopes.


----------



## trifoncar (Nov 8, 2013)

Gracias Daniel,

en relación a la escala del divisor lo comenté en el post #80.

En cuanto a tus comentarios 3), 5) y 6) lo tengo bien en el circuito peor lo he puesto mal en el esquema. Yo lo tengo conectado  a tierra, lo que pasa es que lo conecté a continuación del condensador C7 y la resistencia R6 ya en tierra , y no antes, como he puesto en el esquema. 

Paso a corregir el esquema original, si no te importa.

El resto de los comentarios, voy a llevarlos a cabo en el circuito.

Gracias!



Hola de nuevo,

Daniel, en relación a tus comentarios, he actuado de la forma siguiente:

1)  he quitado la resistencia R2
2)  he cambiado el valor de R3 desde 22 a 2,2 KOhmios pero me distorsiona la medición. He vuelto a dejar la original de 22 KOhmios
3) era un error al trascribir del circuito al esquema - corregido en el esquema
4) he eliminado R6 y al no variar la lectura lo he corregido también en el esquema
5) era un error al trascribir del circuito al esquema - corregido en el esquema
6) creo que es lo mismo que el 4)

Muchas gracias de nuevo

Un saludo


----------



## Daniel Lopes (Nov 8, 2013)

Bueno quanto a los dos diodos antiparalelo de proteccion que enpleaste en lo circuito preescaler lo mejor seria canbiarlos por diodos tipo 1N5711 que son proyectados especiamente para andar en RF, enquanto que los 1N5819 no son y si uso es en fuentes comutadas. yo experimentaria un potenciometro de 100Kohmios en "R3" de lo circuito PIC de modo hacer lo BFR91 andar lo mejor possible.Quanto a los conponientes "R4", "R5" y "C6"  yo no miro funciõn en els asi creo que pueden sener eliminados sin peñas .
Att.
Daniel Lopes.


----------



## trifoncar (Nov 8, 2013)

Las resistencias R4 y R5 muy probablemente las habré copiado de varios esquemas en los que formaban parte de un esquema más amplio y harían las veces de un divisor de tensión.

Voy a quitarlas para comprobar si afectan.

En cuanto al condensador C6 de 1 uF, es parte del esquema de Phil Rice https://387ebf42-a-62cb3a1a-s-sites.googlegroups.com/site/vk3bhr/home/fm2/fm2.gif?attachauth=ANoY7cpOs5yiT5Nj9qDHguxcRyD7Bgg60cwTn_Oq_pM7glZkAu7N-OXV-6uxgHJqwa161KF69-thy7b9zxeMdCVLyuI2gQps7mHV5Z_OLI_pcyvZylP-UNpRYOgSx-qcRuYo4m2Dtewb_XmPMmz3V-HOz5YB_NAFtbMgbUf2QW1TLX084k0iITZ3lxPv95A8tVS_tW0C4vdFW_T1Rhti51BPfWeIKg1Rgg%3D%3D&attredirects=0

y no me he atrevido a quitarlo; lo que pasa es que yo lo he trasladado el condensador y el transistor BFR91 desde el circuito del frecuencímetro al circuito del prescaler, para tenerlo más cerca del prescaler antes de amplificar la señal.

Un saludo.



He comprobado que -efectivamente- las resistencias R4 y R5 no parece que tengan ninguna función en este circuito, por lo que paso a eliminarlas del circuito.

Un saludo



La verdad es que -gracias a tí, Daniel- el esquema va quedando más claro, sin rudimentos superfluos.

Gracias otra vez.

Un saludo


----------



## trifoncar (Nov 9, 2013)

daniel lopes dijo:


> Bueno quanto a los dos diodos antiparalelo de proteccion que enpleaste en lo circuito preescaler lo mejor seria canbiarlos por diodos tipo 1N5711 que son proyectados especiamente para andar en RF, enquanto que los 1N5819 no son y si uso es en fuentes comutadas. yo experimentaria un potenciometro de 100Kohmios en "R3" de lo circuito PIC de modo hacer lo BFR91 andar lo mejor possible.Quanto a los conponientes "R4", "R5" y "C6"  yo no miro funciõn en els asi creo que pueden sener eliminados sin peñas .
> Att.
> Daniel Lopes.



En cuanto a los diodos, no tengo ningún 1N5711, ni BAT42 ó BAT48 (que sugirió Miguelus). Pensé que los 1N5819 servirían para este proyecto.

Respecto de la resistencia R3 (del circuito del prescaler) para hacer ajustar el punto de  funcionamiento del BFR91, hay una resistencia (R3 de 10 K en el circuito del frecuencímetro), cuyo valor se puede ajustar ajustar para conseguir un Vce en el entorno 1,8 - 2,2 V

Un saludo

P.D.: quizá compliqué un poco el asunto al sustraer el BFR91 del esquema del frecuencímetro para incluirlo en el esquema del prescaler, con el fin de acordarme acercar todo lo posible el transistor a la salida de la señal del frecuencímetro; precaución que no sé si tiene mucho fundamento.
Hoy voy a intentar adquirir unos nuevos diodos para el prescaler con el fin de sustituir los 1N5819


----------



## Daniel Lopes (Nov 9, 2013)

Bueno , la salida del MB506 tiene una excursion aproximadamiente de 1,2 Voltios pico a pico lo que es mui poco para que lo PIC entienda ,asi lo BFR91 anda como una interface ECL/TTL , lo ideal seria tener en manos un osciloscopio de banda ancha suficiente para poder mirar la amplidud de salida de lo colector del BFR91 y austar "R3" para maxima amplitud de salida en el . Creo que lo BFR91 puede sener canbiado por un 2N2369 o mismo un 2N2222 , una sensible mejora seria agregar un preamplificador banda ancha en la entrada del preescaler MB506 , pero tiene que sener un que responda hasta Ghz , un bueno tipo es la linea "MAR" del fabricante americano "Mini-Circuits" donde els responden de DC hasta varios Ghz y son casados en 50 Ohmios tanto salida como entrada.
!Fuerte abrazo !
Att.
Daniel Lopes.


----------



## miguelus (Nov 10, 2013)

Buenas noche.

 Trifoncar, los Diodos propuestos (BAT42 o BAT48) los puedes comprar en cualquier comercio de componentes de Madrid, p.e. en Conectrol, son ridiculamente baratos 

Sa U2


----------



## trifoncar (Nov 10, 2013)

miguelus dijo:


> Buenas noche.
> 
> Trifoncar, los Diodos propuestos (BAT42 o BAT48) los puedes comprar en cualquier comercio de componentes de Madrid, p.e. en Conectrol, son ridiculamente baratos
> 
> Sa U2



Fuí el sábado a Merchán (Alcobendas) con el fin de comprar BAT48 y 1N 5711, y volví con los primeros, ya que de los otros no tenían.
Ya los he sustituído. Creo que esta semana entrante voy a empezar el diseño de las placas.
El único "pero...." va a ser la medición de la frecuencia de la radio con  TDA7000.

Un saludo


----------



## SERGIOD (Nov 10, 2013)

crimson dijo:


> Hola trifoncar, yo hice el de DL4YHF, no me acuerdo con qué PIC, creo que era uno como los que usas vos, y llegó cómodo a los 50MHz...
> http://4.bp.blogspot.com/-TA_SeUzgeLg/T4o6pgnu9hI/AAAAAAAAAIU/1MTeqA76bBQ/s1600/dl4yhf1.jpg
> 
> http://3.bp.blogspot.com/-99IerD83xSw/T4o7S1SqoUI/AAAAAAAAAIk/5UcaCnv-W7g/s1600/dl4yhf2.jpg
> ...



Una consulta tienes el enlace principal de ese proyecto


----------



## trifoncar (Nov 10, 2013)

SERGIOD dijo:


> Una consulta tienes el enlace principal de ese proyecto



No sé exactamente si te refieres al proyecto/s que comenta Crimson o al original que planteo yo. De ser lo segundo, paso a describírtelo.

Algunos de los enlaces están en el post #1 (el resto son mezcla de varios y/o modificados por mí). Los últimos esquemas probados con éxito están en el post #88.

Originalmente el hilo comenzó sobre el frecuencímetro con un 16F84 y el prescaler U664 (hasta 1,3 Ghz). Posteriormente, cambié el prescaler por el MB506 que alcanza teóricamente 2,4 Ghz

Un saludo


----------



## SERGIOD (Nov 10, 2013)

El que planteo crimson ya que el pcb se ve genial


----------



## Daniel Lopes (Nov 11, 2013)

Quanto a medir la frequencia de lo TDA7000 es necessario enplear un buffer con alta inpedancia de entrada de modo a no cargar lo oscilador local del TDA7000 ,y despues es necessario subtrair 70Khz( FI ) de la medida que es mirada en la pantalha.
Att.
Daniel Lopes.


----------



## trifoncar (Nov 11, 2013)

daniel lopes dijo:


> Quanto a medir la frequencia de lo TDA7000 es necessario enplear un buffer con alta inpedancia de entrada de modo a no cargar lo oscilador local del TDA7000 ,y despues es necessario subtrair 70Khz( FI ) de la medida que es mirada en la pantalha.
> Att.
> Daniel Lopes.



Hola Daniel,

He seguido las instrucciones de alguien que lo ha conseguido, y son éstas:

*He montado el transistor -un BF256- y he seguido las siguientes indicaciones:

- Compuerta/Gate línea 1ª -> 50KΩ -> masa
- Compuerta/Gate línea 2ª -> 5 a 10pF -> señal RF del pin 6 del TDA7000 (oscilador local)
- Source/Fuente/Surtidor -> 220 a 390 Ω -> masa
- Drenador/Drain -> alimentación

He utilizado 
prueba a)    conexión directa al oscilador local del TDA7000 y tierra
prueba b)    cable con dos espiras de 1cm de diámetro

Lo he alimentado primero con +5V y después con +9V, he probado con varios valores de las resistencias y del condensador.*

No he conseguido medidas fiables.

Un saludo


----------



## Daniel Lopes (Nov 11, 2013)

Quizaz lo nivel fornido por lo source del BF256 sea mui pequeño para que lo MB506 entienda de premera , asi una sugerencia es agregar un amplificador enbasado en un BFR91 entre lo source de lo BF256 y la entrada del MB506.
Att.
Daniel Lopes.


----------



## crimson (Nov 12, 2013)

SERGIOD dijo:


> Una consulta tienes el enlace principal de ese proyecto


 Hola SERGIOD, es éste:
http://www.qsl.net/dl4yhf/freq_counter/freq_counter.html
 no sé cual el el código porque me lo dieron ya programado, el tema completo está acá.
Saludos C


----------



## cosmico74 (May 9, 2014)

Que tal!Saludos toda la comunidad...Pues  retomando el post original...les quiero comentar que hace tiempo arme el frecuencimetro Hasta 50 mhz y me quede con las ganas de ampliarlo a mas frecuencias pero no habia podido por que no conseguia el IC U664 (Prescaler),pero ya me lo trajeron y bueno pues mi duda es la siguiente:
En el circuito del prescaler veo un transistor
NPN KSY71 mi pregunta es si lo puedo sustituir por cualquier NPN por ejemplo el 2N2222...etc.,                                                   
Sobre los diodos ya Fogonazo comento que tienen que ser del tipo Schottky.
Gracias...


----------



## tiago (May 10, 2014)

Yo, a ese mismo montaje le coloqué un BFR 91 que funciona perfecto.

Ver el archivo adjunto 33823

Saludos.


----------



## trifoncar (Jul 3, 2014)

tiago dijo:


> Yo, a ese mismo montaje le coloqué un BFR 91 que funciona perfecto.
> 
> Ver el archivo adjunto 33823
> 
> Saludos.



Hola a todos!

Tiago, ¿cómo logras hacer esos cortes tan limpios en la lámina de cobre? me tiene intrigado y asombrado. 

Un saludo


----------



## tiago (Jul 3, 2014)

Hola @trifoncar

Sencillamente con una placa fotosensible y el correspondiente fotolito. Si lo necesitas, está en el hilo donde se desarrolló el frecuencímetro.

Saludos.


----------



## trifoncar (Jul 5, 2014)

tiago dijo:


> Hola @trifoncar
> 
> Sencillamente con una placa fotosensible y el correspondiente fotolito. Si lo necesitas, está en el hilo donde se desarrolló el frecuencímetro.
> 
> Saludos.



Gracias por la información, tiago.

-----------------

Por otra parte, tengo un *módulo TX de 433,92 Mhz* que transmite en modo de modulación: ASK / OOK y al que *he podido medir su frecuencia* con el frecuencímetro objeto de este post (pic 16F84), pero con el prescaler MB506 porque tiene un límite de frecuencia tope superior más alto que el U664.

Compré los módulos *NRF905* (433/868/915 MHz) y *NRF24L01* (2,4 Ghz)  con el fin de intentar probar el frecuencímetro a esas frecuencias, pero *acabo de recibir una información sobre que probablemente esté intentando medir algo que no voy a poder hacer, ya que el NRF905 y el NRF24L01 emiten en GFSK RF transceiver IC -eso pone en los datasheet-*.

¿Alguien podría corroborar o desmentir la veracidad de esa opinión?


----------



## miguelus (Jul 5, 2014)

Buenas noches Trifoncar

Cuando utilizamos un Frecuencímetro, nos podemos encontrar que el mismo no mide correctamente la frecuencia de ciertos Transmisores,

Si analizamos cómo funciona un Frecuencímetro, podemos llegar a entender sus limitaciones.

Los Frecuencímetros miden la cantidad de ciclos que le entran en una unidad de tiempo, de esta forma podemos medir una frecuencia, pero si esta frecuencia no es estable o está variando muy rápidamente, la visualización será muy errática.

Las modulaciones en cualquier tipo de frecuencia... FM, ASK, etc. no permiten que el Frecuencímetro pueda hacer medidas fiables.

Para medir correctamente las frecuencias con este tipo de modulaciones, tendríamos que intentar hacer que el Transmisor emita únicamente la portadora sin ningún tipo de modulación, de esta forma si que podríamos medir su frecuencia.

Otra forma sería hacer varias medidas, cuantas más mejor, y hacer un promedio.

En ciertos sistemas y para aplicaciones muy (muy) especiales   lo que se hace es procesar la señal recibida y quitar todo tipo de modulación, tanto la AM como la FM, de esta forma dejamos solo la portadora.

Contestando a  tu pregunta.

Con ese tipo de Frecuencímetro es normal que se tengan dificultades para medir correctamente la frecuencia de ese tipo de Transmisiones.

Sal U2


----------



## tiago (Jul 5, 2014)

En todo caso, para medir la frecuencia, deriva a masa la entrada de modulación.

Saludos.


----------



## trifoncar (Jul 5, 2014)

Gracias por las explicaciones, siempre brillantes, Miguelus.

Aunque como soy de formación matemática y estadística, y gran amante de las grandes leyes, queda un rescoldo de duda en mi interior.

Paso a explicarme. Si la FM funciona a una media de -pongamos por redondear- 100 Mhz y se caracteriza por ser de frecuencia variable pero simétrica respecto de la portadora, ¿ no cabría esperar que tras cien millones de oscilaciones por segundo, su valor medio fuese prácticamente ese mismo valor de la portadora?

Yo mido perfectamente la FM si tengo en cuenta laF.I.

También mido bien el módulo de RF que transmite en ASK a 433,92 Mhz. Obtengo 433,89xxxx.

También consigo medir la señal de dos wakies emitiendo en 446,009 Mhz emitiendo en FM -F3E. Obtengo 446,0112xx

¿No podría medir un módulo NRF905 que emite en GFSK a , p.ej. 915 Mhz?
¿No es también una modulación de frecuencia?
¿No se compensarán todas las desviaciones sobre el valor central, al repetirse el ciclo unas 900.000.000 de veces por segundo, debido a la simetría respecto de ese valor central?

No sé en que consiste la modulación por desplazamiento de frecuencia gaussiana, vamos ...... ¡es que no tengo ni idea!  y debo de suponer que tú, Miguelus, que debes de haber trabajado toda la vida en ello, sabes de lo que hablas, y supongo que Tiago, idem de idem. ¿Tan especial es la GFSK?

Un saludo y perdonad si mi ignorancia resulta un poco atrevida.

Tiago, perdona pero no llego a entender -y me gustaría- tu último post. Podrías explicarlo de forma aún más sencilla.

Gracias


----------



## tiago (Jul 6, 2014)

Hola Trifoncar.
En base a lo que ha comentado Miguelus, la recomedación que te doy (Por norma general) es que conectes a masa la entrada de modulación de los equipos antes de medir frecuencia. De esa forma, te aseguras de tener portadora en absoluto silencio y evitar alteraciones en la medida por causa de ruidos que puedan colarse por la etapa de audio.
Hay casos que te vendrá muy bien tomar éste tipo de precauciones, y otros casos, si son entradas de audio o datos digitales, que dará casi que lo mismo. Pero es una costumbre que pienso que no te perjudicará en ningún momento.

Saludos.


----------



## trifoncar (Jul 6, 2014)

Gracias Tiago. Intentaré tenerlo siempre en cuenta.

En aplicación a mi caso actual, con el módulo NRF905, he estado buscando información y me da la impresión de que la modulación (Marchester encoded) se lleva a cabo intermente dentro del chip y no tengo acceso directo a ello a través de ningún pin. Esto sospecho después de haber leído durante un buen rato el datasheet. Por lo que deduzco que en este caso no podría hacer la conexión que me recomiendas.

Subo un diagrama de bloques del chip por si alguien tiene tiempo y ganas, y puede corregirme.

Ver el archivo adjunto 113302

Un saludo


----------



## J2C (Jul 6, 2014)

Trifoncar

Si bien es totalmente correcto lo que han comentado tanto Miguelus como Tiago; es también cierto que quienes hemos trabajado con equipos de transmisión analógicos y/o digitales conocemos que durante la protocolización de los mismos se los *engaña* para poder medir ciertos parámetros, en este caso la frecuencia ya que no es un equipo profesional.


Tomando la información de la datasheet del *nRF905* y buscando en Wikipedia (castellano que esta muy simplificado) respecto a *GFSK* y *Codificación Manchester*, en este caso la forma de medir la frecuencia es ingresar un dato a transmitir constante de 1 lógico ó 0 lógico.

No he profundizado realmente que señales se deben manipular en el *nRF905* dado que posee una interfaz SPI y no la conozco. Mirando muy por arriba se deberá fijar que este siempre en Tx, supongo que deberá recibir las señales correspondientes a la interfaz SPI: *CSN* (0 lógico), *SCK* (de la frecuencia/velocidad correspondiente) y finalmente *MOSI* (1 ó 0 lógico constante). 

Te pediría que antes de repreguntar algo al respecto busques artículos universitarios de GFSK y Codificación Manchester y leelos, estoy seguro que por tu formación los comprenderás enseguida.


Finalmente hago la salvedad que en equipos de telecomunicaciones digitales de alta capacidad en µOndas se suelen medir los osciladores para asegurar la frecuencia.


Saludos, JuanKa.-

P.D.: Todos en algún momento tenemos tiempo y ganas, tu también deberías preveer de tener ambas  !!.


----------



## trifoncar (Jul 7, 2014)

Hola de nuevo,

muchas gracias JC2 por responder y por la información.



J2C dijo:


> Trifoncar
> P.D.: Todos en algún momento tenemos tiempo y ganas, tu también deberías preveer de tener ambas  !!.



En realidad creo que no me faltan. Creo que quizá no he sabido comunicar bien lo que quería decir. Me refería a que si alguien disponía de tiempo y tenía a bien el ayudarme, sería bien recibido. Mi última intención es molestar o requerir. sé que esto es voluntario y agradezco mucho la ayuda.



J2C dijo:


> Trifoncar
> Te pediría que antes de repreguntar algo al respecto busques artículos universitarios de GFSK y Codificación Manchester y leelos, estoy seguro que por tu formación los comprenderás enseguida.



 No entiendo muy bien a que te refieres con "repreguntar". En realidad, cuando no entiendo algo, mi último recurso es pedir ayuda a terceros. Busco y rebusco en la web antes de molestar. Agradezco siempre la ayuda y ayudo en lo que puedo.

No sé que es lo que te ha empujado a pensar que mi grado de formación es suficiente para entender sobre GFSK y Codificación Manchester, p.ej., pero no tengo N.P.I. como decimos por aquí. El hecho de trasladar ciertos términos de un datasheet no implica que los domine.  Yo no soy Técnico Electrónico, soy economista (licenciado en Ciencias Económicas) con algún año de carrera universitaria de ingeniería de telecomunicaciones pero lo abandoné enseguida; pero siempre conservé una atracción especial por este campo y, por disponer últimamente de más tiempo libre, estoy llevando a cabo determinados  montajes.



J2C dijo:


> Tomando la información de la datasheet del *nRF905* y buscando en Wikipedia (castellano que esta muy simplificado) respecto a *GFSK* y *Codificación Manchester*, en este caso la forma de medir la frecuencia es ingresar un dato a transmitir constante de 1 lógico ó 0 lógico.
> 
> No he profundizado realmente que señales se deben manipular en el *nRF905* dado que posee una interfaz SPI y no la conozco. Mirando muy por arriba se deberá fijar que este siempre en Tx, supongo que deberá recibir las señales correspondientes a la interfaz SPI: *CSN* (0 lógico), *SCK* (de la frecuencia/velocidad correspondiente) y finalmente *MOSI* (1 ó 0 lógico constante).



y para muestra .... un botón .... no entiendo nada de lo que comentas en este párrafo, pero  ... por favor ... no te enfades por este comentario; lo único que expresa es la cruda realidad.

Lo único que pretendo es aclarar que SIEMPRE, SIEMPRE, busco antes de preguntar, y que mi preparación en este campo es bastante baja, a pesar de lo que pueda parecer. Como dice una tía mía: " .... y el undécimo ....... no molestarás". Esa nunca sería mi intención.

Muchas gracias de nuevo, J2C.

Cambiando de tema, como compré un módulo de "Software Defined Radio" que se conecta al PC vía USB y que escanea señales de RF hasta 1,9 Ghz (según creo) estoy intentando averiguar si estoy haciendo consiguiendo hacer transmitir al módulo emisor NRF905, aunque quizá esté intentando hacer algo merecedor de una excomunión electrónica     No sé si podrá detectar el tipo de señal emitido por dicho dispositivo; intentaré averiguarlo.

Gracias a todos de nuevo


----------



## trifoncar (Feb 19, 2018)

Hola de nuevo, foreros.

Tras tres años y medio retomo este hilo porque necesito ayuda para ampliar el proyecto.
He estado pensando si abrir un hilo nuevo .. pero me ha parecido conveniente continuarlo.

Al retomar el tema he vuelto a crear una nueva placa con el esquema de Phil Rice y funciona perfectamente bien, con y sin prescaler. Le he puesto el prescaler original -U664BS- porque resulta muy fiable en cuanto a sus componentes adicionales (he visto un montón de diferentes montajes para el MB506 y me cuesta mucho dar con uno que funcione acertadamente) y, aunque se agota en 1,3 GHz, me resulta más que suficiente, y lo he apoyado como siempre, en el BFR-91, como amplificador de señal.

He medido con muy buena precisión desde 20 Hz hasta 434 MHz (no tengo ninguna fuente de frecuencia superior aunque espero tenerla en uno o dos meses, se trata de un transmisor de 915 MHz.)

Hasta ahora las mediciones las he efectuado con señal introducida directamente por conductor  físico (cable), con la excepción de un transmisor de 433,92 MHz y un módulo oscilador de 100,00 MHz con los que hice y he hecho pruebas satisfactorias pero a muy corta distancia.

Ahora quiero añadir la funcionalidad de que capte señales inalámbricas no tan próximas, y para ello me animé a crear un circuito amplificador con un MAR-6+, pero al no encontrarlo en el proveedor habitual, compré un GALI-84.

Creo que nunca había soldado un componente tan pequeño .

Adjunto el esquema creado












Pero ahora me falta el circuito de antena ....y no tengo ni conocimientos, ni la más mínima idea de ello. Es más, no sé si he hecho bien al incorporar este circuito con el mmic. Pretendo utilizarlo de forma inalámbrica para medir frecuencias de forma inalámbrica en el entorno 110 - 1.300 MHz.

Alguna ayuda?

Un saludo de nuevo, chicos


----------



## ricbevi (Feb 20, 2018)

A esa frecuencia te sugiero todo SMD y sobre FR4 doble cara
Un capacitor de 10pF a 100MHz tiene de reactancia capacitiva aproximadamente 2Ω,  a 1GHz debería tener 10 veces menos(0.2Ω) yo no usaría mas grande de ese valor en la entrada y salida por que no tiene sentido a menos que quieras amplificar toda señal que ande dando vuelta de mas baja frecuencia.
El tema es como siempre, un compromiso en lo que se espera recibir y lo que hay que sacrificar para recibirlo.   
Si haces un súper amplificador de banda ancha, no esperes que el frecuencímetro no se vuelva loco cuando lo conectes en ambientes tan saturados de ruidos y RF como los actuales.
Saludos.

Ric.


----------



## trifoncar (Feb 21, 2018)

Me has hecho ver que lo que pretendo (pretendía) es casi una quimera.

Supongo que el amplificador monolítico es más para un escáner de frecuencias que para un frecuencímetro que únicamente ofrecerá la lectura de la frecuencia más potente, dentro de todas las que capte, y no siempre será la que pretendemos medir; así que voy a quedarme con las prestaciones que me ofrece el frecuencímetro de Phil Rice con entrada por cable eléctrico, que ya es bastante.

Por cierto, me construí una tabla de de impedancia capacitativa en función de la frecuencia y de la capacidad y al leerlo para 10 pF y 100 MHz obtengo 159 Ω. ¿Estoy confundido?

Muchas gracias por tus comentarios, Ricbevi. Siempre que entro en este foro ... aprendo algo.
Es de agradecer.

Un saludo!


----------



## ricbevi (Feb 26, 2018)

trifoncar dijo:


> Me has hecho ver que lo que pretendo (pretendía) es casi una quimera.
> 
> Supongo que el amplificador monolítico es más para un escáner de frecuencias que para un frecuencímetro que únicamente ofrecerá la lectura de la frecuencia más potente, dentro de todas las que capte, y no siempre será la que pretendemos medir; así que voy a quedarme con las prestaciones que me ofrece el frecuencímetro de Phil Rice con entrada por cable eléctrico, que ya es bastante.
> 
> ...



Si esta mal mi calculo...me comí uno ceros en la conversión de frecuencia y F a pF...lo de dos era por que redondee si daba 1.59Ω a 2Ω. De todas formas si incrementas sin control la ganancia del amplificador a la entrada, se volverá loco el frecuencímetro ante cualquier señal y te dificultara la real medición. El otro problema que tendrás es que ante una presencia de señal fuerte corres el riesgo de quemar la etapa. Tengo varios frecuencímetros portátiles de antenistas amigos quemados por aquí por ese motivo(se lo olvidaron prendidos cerca de una antena irradiante con el emisor prendido.
Como siempre lo difícil es conseguir el punto de equilibrio.
Saludos.

Ric.


----------



## trifoncar (Mar 19, 2018)

Pensaba que te había contestado.
Disculpa por el retraso en hacerlo.
Gracias de nuevo por tu respuesta. Ya veo que el frecuencímetro no tiene problemas para entrada directa por línea; pero el tema inalámbrico ... es otro cantar.

Un saludo


----------



## trifoncar (May 21, 2018)

He tardado mucho en montar este proyecto en pcb, pero al final lo llevé a cabo hace un mes aproximadamente.

Debido a la gran ayuda aquí recibida, me siento obligado a subir algunas fotos del producto final, en el que ha primado la simplicidad ( hace dos o tres años acometí el proyecto de forma muy ambiciosa, pero cuya complejidad acabó por no resultar ni práctica, ni efectiva, ja..ja..ja) y en la que me he encontrado con que si hubiese cambiado el diseño en algunos aspectos, hubiese resultado mejor … pero lo he dejado así.



El esquema del circuito es el tantas veces comentado y mostrado en este hilo, de Phil Rice. El prescaler (y su circuito, que pertenece a Miroslav Sinko) también están aquí descritos.





El frecuencímetro dispone una entrada para alimentación de entre 8 y 12 voltios (instalé en su interior un 7805 para tener estabilizada la tensión de entrada) y cinco contactos de comunicación con el exterior (gnd, pin 18, +5V, punto E y punto D). El pin 18 se utiliza para indicar al pic si debe multiplicar x64 la cuenta de pulsos recibidos, o dejar la cuenta tal cual. Los puntos D y E son los dos de salida del amplificador BFR-91, al que he situado fuera, cerca del origen de la señal.



Decidí situar en el exterior los circuitos del amplificador, el prescaler y -en su caso- el atenuador y los diodos de seguridad, así como los circuitos para otros tipos de entrada.

Quiero mostrar su funcionamiento desde unos 100 Hz hasta 433 MHz. He intentado conseguir un módulo transmisor muy barato que anuncian que funciona en la banda de 900 MHz pero es una engañifa; habría que cambiar unos elementos smd y no tengo herramientas para ello, así que el tope lo he puesto en la señal de un transmisor típico de 433,92 MHz. El prescaler puede funcionar hasta los 1,3 GHz.




Esta última imagen es un "pantallazo" del programa SDR# que recoge la señal del cristal de 16 MHz (mostrada también por el frecuencímetro, en la foto anterior)

En los próximos días subiré unos videos para poder ver el funcionamiento del mismo.

De momento, para aquellos que puedan estar interesados en este proyecto simple, pero con un instrumento que puede servir muy bien a algunos aficionados, muestro la lista de las pruebas que subiré en los próximos días.



Un saludo


----------



## trifoncar (May 22, 2018)

Hola

Hoy voy a subir el primero de los tests del frecuencímetro.

Comprende la franja que va desde los 80 Hz hasta los 20.154 Hz que me permite la aplicación que voy a utilizar y que aprovecha la tarjeta de sonido para generar frecuencia cuya salida es la del altavoz del ordenador.  Funciona desde unos 50 Hz, pero no lo pruebo en el video hasta unos 80 Hz porque tendría que cambiar unos mini-conmutadores para evitar el atenuador de la placa y me resulta complicado con la cámara y el frecuencímetro de por medio.







	Mensaje automáticamente combinado: May 22, 2018

Ahora subo la segunda prueba del frecuencímetro que esta vez mide la frecuencia de salida de un generador de ultrasonidos de unos 25 KHz


----------



## trifoncar (May 23, 2018)

Hola de nuevo.

Continúo con las pruebas del frecuencímetro. Hoy abordo la medición de la señal creada por un oscilador astable basado en el circuito integrado TS555CN.

Esta fase comprende tres pruebas para cubrir de alguna forma el ámbito existente entre las pruebas efectuadas ayer y las pruebas que efectuaré con cristales.
Para ello utilizaré un mismo condensador de 1.405 pF (valor real) y tres grupos de resistencias cuyos valores aparecen en el video.
Tropecé con el problema de que las frecuencias mostradas se encuentran muy lejos de las teóricas obtenidas por las fórmulas asociadas a dicho componente y … me las tuve que ingeniar para llevar a buen puerto la prueba.

Siento no haberme dado cuenta de que dejaba fuera de la imagen del video la frecuencia sintonizada, pero de alguna forma puede leerse en las marcas del eje de abcisas. Procuraré no olvidarlo para los próximos videos.

Muchas gracias de nuevo por vuestra atención






Un saludo

P.D.: En el video comento que el frecuencímetro se alimenta de una fuente de tensión de entre 8 y 12 voltios; es un error, se trata de un regulador de tensión (7809) que lo alimento con un transformador de 12 voltios en continua, conectado a la red eléctrica.


----------



## Indalecio13 (May 23, 2018)

Hola trifoncar, me interesa el analizador de espectros que utilizas. He buscado en google por SDR# y no encuentro nada, solo hablan de Radio Definida por Software.
¿Podrias ampliar la info al respecto, caracteristicas del analizador, si utiliza algun hardware adicional, donde leer mas acerca de el, etc.?
Te agradezco por anticipado.

Saludos.


----------



## ricbevi (May 23, 2018)

Indalecio13 dijo:


> Hola trifoncar, me interesa el analizador de espectros que utilizas. He buscado en google por SDR# y no encuentro nada, solo hablan de Radio Definida por Software.
> ¿Podrias ampliar la info al respecto, caracteristicas del analizador, si utiliza algun hardware adicional, donde leer mas acerca de el, etc.?
> Te agradezco por anticipado.
> 
> Saludos.



Mira aquí en este subforo esta tratado el tema de SDR(usa el buscador con la frase "SDR") . Es como un PenDrive con antena que recibe hasta 1.3GHz o mas según cual sea.

Como software hay varios, yo uso el SDRSharp.

Saludos.

Ric.


----------



## trifoncar (May 24, 2018)

Hola de nuevo

Retomo las pruebas del frecuencímetro ahora con cristales. El ámbito estará comprendido entre los 1,8 y los 100 MHz. Por debajo de 30 Mhz. será sin prescaler, y por encima de dicho valor sí lo utilizaré.

Debido a que esta vez está muy claro lo que tiene que marcar el frecuencímetro, no utilizaré ninguna herramienta externa de comprobación (como tuve que hacerlo en el último video), a excepción del test del cristal de 100 MHz. que requerirá de un analizador de espectros para intentar comprender la problemática de los cristales trabajando en sobretonos de orden "alto" (5º en ese caso).

El analizador que utilizaré será la versión gratuita de la compañía Touchstone, en particular su “Touchstone: RF Spectrum Analyzer Software” en su versión gratuita 10.9979.0  que puede encontrarse en:
Touchstone — RF Spectrum Analyzer Software

En esta prueba utilizo el frecuencímetro objeto de estas pruebas, y una placa pcb con el circuito probador de cristales.
https://www.forosdeelectronica.com/galeria/placa-con-circuito-de-medición-de-cristales.47/full

También utilizaré el analizador de espectro indicado anteriormente, los cristales objeto de la prueba, y una serie de condensadores necesarios.











Gracias por la visita y un saludo


----------



## trifoncar (May 25, 2018)

Hola,
Retomo de nuevo la exposición de los videos sobre las pruebas de funcionamiento del frecuencímetro; esta vez probandolo con un módulo de 64 MHz, otro de 155,52 Mhz, y con unos auriculares inalámbricos cuya señal de mayor potencia emite sobre los 260 MHz.

Con el primer módulo, aprovecharé también para probarlo en su tercer armónico (192 MHz)






Originalmente un video contenía la prueba de ambos módulos, pero debido a que me olvidé conectar unos cables antes de llevar a cabo la prueba con el segundo módulo, corté esos instantes y creé un nuevo video más corto de la segunda prueba, aunque ha resultado una entrada un poco abrupta, pero más corta.






Y ahora la prueba con los auriculares inalámbricos de 260 MHz.






Aprovecho para subir las fotos de los cristales utilizados en un video anterior, y otras de los módulos osciladores porque no se llegaba a leer su identificación en los videos.

View media item 52
View media item 53
View media item 54

Con esto, únicamente me quedará por subir un video de la prueba con un transmisor de 433, 92 MHz para completar mi objetivo.

Una vez finalizado, me gustaría recibir críticas y sugerencias, así como posibles aclaraciones a temas no suficientemente bien explicados.

Muchas gracias por la visita

Un saludo

	Mensaje automáticamente combinado: May 25, 2018


----------



## Indalecio13 (May 25, 2018)

Que buenos momentos he pasado gracias a cristales como ese gris de la foto. El popular canal 14 de los 11 metros.
Allá por los años 70, me pasaba practicamente todo mi tiempo libre cacharreando con emisoras, antenas y receptores.
Desde el sur de España me hice QSO's con muchas provincias españolas, casi toda Italia, muchos paises de America Latina y algunos de Europa.
La radio en aquellos tiempos era como el internet actual, con la ventaja de que casi todos los aparatos los haciamos los propios aficionados.

Saludos.


----------



## trifoncar (May 26, 2018)

Hola, Indalecio,

perdona por no haber contestado antes.

El software SDR# se utliza con un "dongle" RTL-SDR. SDR significa "software defined radio".
El hardware que yo utilizo  va desde los 24 MHz hasta los 1.700 MHz. Pero tiene un ancho de banda de 2,4 MHz.

Los tienes desde unos pocos euros. El software es gratuito.


Tengo un hilo *(aquí)* donde comento varias de sus facetas y posibilidades.

También hay programas gratis de amplio expectro como el "Panoramio" o "Touchstone"

Creo que también están comentados en ese hilo.

Allí podrás ver unas cuantas fotografías del dispositivo

Y si quieres un poco de historia sobre el descubrimiento de la faceta de escáner de frecuencias de este dispositivo, te sugiero que leas el siguiente  *artículo*.

Un saludo


----------



## Indalecio13 (May 26, 2018)

trifoncar dijo:


> Hola, Indalecio,
> 
> perdona por no haber contestado antes.
> 
> ...



Gracias trifoncar. No hay problema, como respondio Ricbevi, me entretuve leyendo e investigando el tema. Tambien visite tu hilo y lo lei.
Hace unos dias pedi un cacharrito de esos con los CI recomendados y estoy esperando que llegue para empezar a jugar con el. Tambien quiero hacerme con una antena de banda ancha, tipo discono para ver que se recibe por aca.
Me llamo mucho la atencion el tema del seguimiento de aeronaves y vere si me funciona. Yo vivo a solo 25 Km de un aeropuerto y por aqui sobrevuelan algunos aviones en proceso de aterrizaje o despegue.

Saludos.


----------



## trifoncar (May 29, 2018)

Daniel Lopes dijo:


> Hola a todos, !saludos cordeales!, yo personalmiente prefiro un oscilador a cristal entre 4 a 10 Mhz , donde els oscilan en modo fudamental y osciladores con frequenzia arriba 25Mhz operan en modo overton o sea modo harmonico y la estabilidad y precisiõn ja no es mas tan buena. Otro punto mui inportante que no puede sener orbidado es la qualidad de la base de tienpo enpleada en el frequencimetro , caso sea pobre tenemos medidas mediocres.Lo mas recomendado es una base de tienpo en torno de 10Mhz armado en una camara Termica (horno termico ) para manter la frequencia lo mas estable que possible .Para una buena calibraciõn podemos hacer uso de un padrõn enbasado en un GPS que garantiza una precisiõn mui buena a un costo razonable.
> !Fuerte abrazo!
> Att.
> Daniel lopes



Daniel, sé que ha pasado mucho tiempo desde este post tuyo (sep-2013), pero estoy muy interesado en saber cómo puedo hacer uso de un patrón basado en un GPS.

¿Puedes ayudarme?


----------



## Daniel Lopes (May 29, 2018)

trifoncar dijo:


> Daniel, sé que ha pasado mucho tiempo desde este post tuyo (sep-2013), pero estoy muy interesado en saber cómo puedo hacer uso de un patrón basado en un GPS.
> 
> ¿Puedes ayudarme?


Hay receptores de GPS que posuen salida de 10Mhz y o 1PPS (un pulso por segundo) , hay que buscar por esa opción en lo mercado especializado.
Los 10Mhz pueden sener utilizados directamente como referencia de tu frequenzimetro , ya lo PPS ese tiene que servir como referencia de un PLL para generar una frequenzia deseada como referenzia de tu frequenzimetro.
!Suerte en las buscas!.
Att,
Daniel Lopes.


----------



## trifoncar (May 29, 2018)

Daniel Lopes dijo:


> Hay receptores de GPS que posuen salida de 10Mhz y o 1PPS (un pulso por segundo) , hay que buscar por esa opción en lo mercado especializado.
> Los 10Mhz pueden sener utilizados directamente como referencia de tu frequenzimetro , ya lo PPS ese tiene que servir como referencia de un PLL para generar una frequenzia deseada como referenzia de tu frequenzimetro.
> !Suerte en las buscas!.
> Att,
> Daniel Lopes.



Gracias por la información.

De cualquier forma, estoy buscando alguna referencia directa y cómoda en frecuencia. ¿No existe alguna baliza o similar en radio frecuencia que emita a una frecuencia precisa y sirva de referencia para calibrar?


----------



## ricbevi (May 29, 2018)

trifoncar dijo:


> Gracias por la información.
> 
> De cualquier forma, estoy buscando alguna referencia directa y cómoda en frecuencia. ¿No existe alguna baliza o similar en radio frecuencia que emita a una frecuencia precisa y sirva de referencia para calibrar?



Revisa aquí  . Se llama WWV y cuando hice mis primeros frecuencímetros y por carecer de patrones "fiables" a parte de los 50Hz de la linea, los ajuste un un transeptor y la señal en 10MHz, primero sintonice con el oído de entonces las bandas laterales a "batido 0" y luego pase a emisión con portadora y ajuste que leyeran 10MHz.

Recientemente tuve tiempo y un service monitor de marca y recién adquirido y patronado en USA con certificaciones y los re-calibre pero la diferencias estaban en el orden de los ciclos para mediciones de 10MHz que son las que hago directamente con el IC (ICM7216), luego lleva prescalers. 

Saludos.

Ric.


----------



## trifoncar (Jun 12, 2018)

Hola de nuevo,
Iba a disculparme por el retraso en mostrar la última prueba .. pero no creo que lo haya echado en falta nadie..Ja..ja..ja

Hoy muestro a través de un nuevo video, el funcionamiento del frecuencímetro con un transmisor de 433.92 Mhz. Con ello concluyo las pruebas que pretendía efectuar y muestro el resumen de los resultados obtenidos.






Dichos resultados pueden variar un poco respecto de los resultados mostrados en los videos anteriores (no son significativos) y es debido a que he ajustado el frecuencímetro con el fin de mejorar su precisión. Esa mejora o corrección la he llevado a cabo con el software del programa, que posibilita llevarla a cabo a través de unos pines dedicados para ello.

En mi modesta opinión, y dado el escaso coste de los componentes necesarios para su construcción, creo que sus prestaciones son realmente buenas para dicho coste. No he probado ninguno de los frecuencímetros chinos que ya se anuncian a precio bajo, pero seguro que no tardarán en sorprendernos.

Yo estoy realmente satisfecho con este frecuencímetro; no lo utilizo a nivel profesional y no necesito una precisión extraordinaria.

Dejo una imagen con los resultados obtenidos en las diferentes pruebas.







Salud … y muchas gracias por vuestra visita!


----------

