2020/04/10

Diagnosticando avrdude + USBasp + arduino IDE

Estaba intentando programar un ATMega328p para un proyecto y quise usar ArduinoIDE en lugar del baremetal que había usado para otro proyecto de próxima publicación.


Elegí:

Board: Arduino Duemilanove por que tiene ATMega328p
Processor: ATMega328p
Port: /dev/ttyS0
Programmer: USBasp



Cuando quise hacer el burn con Sketch -> Upload Using Programmer, me dijo:


An error occurred while uploading the sketch
avrdude: Warning: cannot open USB device: Permission denied
avrdude: error: could not find USB device with vid=0x16c0 pid=0x5dc vendor='www.fischl.de' product='USBasp'



Pensé que la corrección había sido modificar una regla de udev tal que agregara un symlink, pero al final probé sin ese symlink y ArduinoIDE pudo programar ok, ya que según comprendí luego, avrdude sabe como hallar el programador, probablemente utilizando libusb.

Realmente no sé que fué lo que cambió para que funcionara.




Lo que sigue son mis aventuras diagnosticando y probando, habiendo asumido  que tenía que aparecer /dev/ttyACM0.


Lo primero fue fijarme si aparecía de algún modo como dispositivo usb, si:

$ lsusb
Bus 003 Device 007: ID 16c0:05dc Van Ooijen Technische Informatica shared ID for use with libusb

Luego con más detalles

$ sudo lsusb -v

Bus 003 Device 007: ID 16c0:05dc Van Ooijen Technische Informatica shared ID for use with libusb
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               1.10
  bDeviceClass          255 Vendor Specific Class
  bDeviceSubClass         0
  bDeviceProtocol         0
  bMaxPacketSize0         8
  idVendor           0x16c0 Van Ooijen Technische Informatica
  idProduct          0x05dc shared ID for use with libusb
  bcdDevice            1.02
  iManufacturer           1 www.fischl.de
  iProduct                2 USBasp
  iSerial                 0
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength           18
    bNumInterfaces          1
    bConfigurationValue     1
    iConfiguration          0
    bmAttributes         0x80
      (Bus Powered)
    MaxPower               50mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           0
      bInterfaceClass         0 (Defined at Interface level)
      bInterfaceSubClass      0
      bInterfaceProtocol      0
      iInterface              0
Device Status:     0x0000
  (Bus Powered)


Para verificar si aparecía en algún lado de /dev, hice unos finds y diffs:



$ find /dev > ~/antes

conecté el programador

$ find /dev > ~/despues

diff ~/antes ~/despues --side-by-side

$ diff ~/antes ~/despues  --side-by-side | grep ">"

                        >    /dev/vboxusb/003/007
                        >    /dev/char/189:262
                        >    /dev/bus/usb/003/007


Ese vboxusb me hizo pensar que quizás virtualbox estaba apropiándose del dispositivo, tal como le pasó a alguien con modemmanager.


$ sudo service virtualbox stop
$ sudo service virtualbox-guest-utils stop

¿Podría ser que aún estando apagada alguna virtual tuviera un filtro y me estuviera tomando el dispositivo? Revisé la configuración de cada virtual y ninguna tenía configurados filtros usb.

Tambien ejecuté :

$ VBoxManage list usbfilters
Global USB Device Filters:
<none>

Luego hice el mismo proceso para un teensy que anda ok:



    >    /dev/serial
    >    /dev/serial/by-path
    >    /dev/serial/by-path/pci-0000:00:12.0-usb-0:1:1.0
    >    /dev/serial/by-id
    >    /dev/serial/by-id/usb-Teensyduino_USB_Serial_12345-if00
    >    /dev/ttyACM0
    >    /dev/vboxusb/003/007
    >    /dev/char/166:0
    >    /dev/char/189:262
    >    /dev/bus/usb/003/007

No es virtualbox.


Pasé a ver que ocurría con udev.



$ sudo udevadm monitor

# USBasp

KERNEL[x.x] add /devices/pci0000:00/0000:00:12.0/usb3/3-1 (usb)
KERNEL[x.x] add /devices/pci0000:00/0000:00:12.0/usb3/3-1/3-1:1.0 (usb)
UDEV  [x.x] add /devices/pci0000:00/0000:00:12.0/usb3/3-1 (usb)
UDEV  [x.x] add /devices/pci0000:00/0000:00:12.0/usb3/3-1/3-1:1.0 (usb))



# Como curiosidad, iCEstick con máquina recién iniciada

KERNEL[x.x] add /module/usbserial (module)
KERNEL[x.x] add /bus/usb-serial (bus)
KERNEL[x.x] add /bus/usb/drivers/usbserial (drivers)
KERNEL[x.x] add /bus/usb/drivers/usbserial_generic (drivers)
KERNEL[x.x] add /bus/usb-serial/drivers/generic (drivers)
UDEV  [x.x] add /module/usbserial (module)
UDEV  [x.x] add /bus/usb-serial (bus)
UDEV  [x.x] add /bus/usb/drivers/usbserial (drivers)
UDEV  [x.x] add /bus/usb/drivers/usbserial_generic (drivers)
UDEV  [x.x] add /bus/usb-serial/drivers/generic (drivers)
KERNEL[x.x] add /module/ftdi_sio (module)
KERNEL[x.x] add /bus/usb/drivers/ftdi_sio (drivers)
KERNEL[x.x] add /bus/usb-serial/drivers/ftdi_sio (drivers)
KERNEL[x.x] add /devices/pci0000:00/0000:00:12.2/usb1/1-1/1-1:1.0/ttyUSB0 (usb-serial)
UDEV  [x.x] add /module/ftdi_sio (module)
KERNEL[x.x] add /devices/pci0000:00/0000:00:12.2/usb1/1-1/1-1:1.0/ttyUSB0/tty/ttyUSB0 (tty)
UDEV  [x.x] add /bus/usb-serial/drivers/ftdi_sio (drivers)
KERNEL[x.x] add /devices/pci0000:00/0000:00:12.2/usb1/1-1/1-1:1.1/ttyUSB1 (usb-serial)
UDEV  [x.x] add /bus/usb/drivers/ftdi_sio (drivers)
KERNEL[x.x] add /devices/pci0000:00/0000:00:12.2/usb1/1-1/1-1:1.1/ttyUSB1/tty/ttyUSB1 (tty)
UDEV  [x.x] add /devices/pci0000:00/0000:00:12.2/usb1/1-1/1-1:1.1 (usb)
UDEV  [x.x] add /devices/pci0000:00/0000:00:12.2/usb1/1-1/1-1:1.1/ttyUSB1 (usb-serial)
UDEV  [x.x] add /devices/pci0000:00/0000:00:12.2/usb1/1-1/1-1:1.1/ttyUSB1/tty/ttyUSB1 (tty)
UDEV  [x.x] add /devices/pci0000:00/0000:00:12.2/usb1/1-1/1-1:1.0 (usb)
UDEV  [x.x] add /devices/pci0000:00/0000:00:12.2/usb1/1-1/1-1:1.0/ttyUSB0 (usb-serial)
UDEV  [x.x] add /devices/pci0000:00/0000:00:12.2/usb1/1-1/1-1:1.0/ttyUSB0/tty/ttyUSB0 (tty)

# iCEstick antes de reiniciar, los demás drivers ya los había cargado hace semanas.

KERNEL[x.x] add /devices/pci0000:00/0000:00:10.0/usb5/5-2 (usb)
KERNEL[x.x] add /devices/pci0000:00/0000:00:10.0/usb5/5-2/5-2:1.0 (usb)
KERNEL[x.x] add /devices/pci0000:00/0000:00:10.0/usb5/5-2/5-2:1.0/ttyUSB0 (usb-serial)
KERNEL[x.x] add /devices/pci0000:00/0000:00:10.0/usb5/5-2/5-2:1.0/ttyUSB0/tty/ttyUSB0 (tty)
KERNEL[x.x] add /devices/pci0000:00/0000:00:10.0/usb5/5-2/5-2:1.1 (usb)
KERNEL[x.x] add /devices/pci0000:00/0000:00:10.0/usb5/5-2/5-2:1.1/ttyUSB1 (usb-serial)
KERNEL[x.x] add /devices/pci0000:00/0000:00:10.0/usb5/5-2/5-2:1.1/ttyUSB1/tty/ttyUSB1 (tty)


# Así se vé un teensy:

KERNEL[x.x] add /devices/pci0000:00/0000:00:12.0/usb3/3-1 (usb)
KERNEL[x.x] add /devices/pci0000:00/0000:00:12.0/usb3/3-1/3-1:1.0 (usb)
KERNEL[x.x] add /devices/pci0000:00/0000:00:12.0/usb3/3-1/3-1:1.1 (usb)
UDEV  [x.x] add /devices/pci0000:00/0000:00:12.0/usb3/3-1 (usb)
UDEV  [x.x] add /devices/pci0000:00/0000:00:12.0/usb3/3-1/3-1:1.1 (usb)
KERNEL[x.x] add /module/cdc_acm (module)
UDEV  [x.x] add /module/cdc_acm (module)
KERNEL[x.x] add /devices/pci0000:00/0000:00:12.0/usb3/3-1/3-1:1.0/tty/ttyACM0 (tty)
KERNEL[x.x] add /bus/usb/drivers/cdc_acm (drivers)
UDEV  [x.x] add /devices/pci0000:00/0000:00:12.0/usb3/3-1/3-1:1.0 (usb)
UDEV  [x.x] add /bus/usb/drivers/cdc_acm (drivers)
UDEV  [x.x] add /devices/pci0000:00/0000:00:12.0/usb3/3-1/3-1:1.0/tty/ttyACM0 (tty)


Información específica del dispositivo, el número cambia con respecto a otros listados por ser distintas inserciones

$ sudo udevadm  info -a -n /dev/bus/usb/003/003 ;

  looking at device '/devices/pci0000:00/0000:00:12.0/usb3/3-1':
    KERNEL=="3-1"
    SUBSYSTEM=="usb"
    DRIVER=="usb"
    ATTR{authorized}=="1"
    ATTR{avoid_reset_quirk}=="0"
    ATTR{bConfigurationValue}=="1"
    ATTR{bDeviceClass}=="ff"
    ATTR{bDeviceProtocol}=="00"
    ATTR{bDeviceSubClass}=="00"
    ATTR{bMaxPacketSize0}=="8"
    ATTR{bMaxPower}=="50mA"
    ATTR{bNumConfigurations}=="1"
    ATTR{bNumInterfaces}==" 1"
    ATTR{bcdDevice}=="0102"
    ATTR{bmAttributes}=="80"
    ATTR{busnum}=="3"
    ATTR{configuration}==""
    ATTR{devnum}=="3"
    ATTR{devpath}=="1"
    ATTR{idProduct}=="05dc"
    ATTR{idVendor}=="16c0"
    ATTR{ltm_capable}=="no"
    ATTR{manufacturer}=="www.fischl.de"
    ATTR{maxchild}=="0"
    ATTR{product}=="USBasp"
    ATTR{quirks}=="0x0"
    ATTR{removable}=="unknown"
    ATTR{speed}=="1.5"
    ATTR{urbnum}=="9"
    ATTR{version}==" 1.10"



Probé un montón de combinaciones de rules, sin éxito, en particular comprobé que estaba siendo llamda con un RUN:


SUBSYSTEM=="usb", ACTION=="add", RUN+="/trigger.sh"


trigger.sh sólo imprime un archivo.


Miré con más detalle:


$ sudo udevadm monitor -k -u -p


UDEV  [1025.922712] add      /devices/pci0000:00/0000:00:12.0/usb3/3-1 (usb)
ACTION=add
BUSNUM=003
DEVNAME=/dev/bus/usb/003/003
DEVNUM=003
DEVPATH=/devices/pci0000:00/0000:00:12.0/usb3/3-1
DEVTYPE=usb_device
DRIVER=usb
ID_BUS=usb
ID_MODEL=USBasp
ID_MODEL_ENC=USBasp
ID_MODEL_FROM_DATABASE=shared ID for use with libusb
ID_MODEL_ID=05dc
ID_REVISION=0102
ID_SERIAL=www.fischl.de_USBasp
ID_VENDOR=www.fischl.de
ID_VENDOR_ENC=www.fischl.de
ID_VENDOR_FROM_DATABASE=Van Ooijen Technische Informatica
ID_VENDOR_ID=16c0
MAJOR=189
MINOR=258
PRODUCT=16c0/5dc/102
SEQNUM=2787
SUBSYSTEM=usb
TYPE=255/0/0
USEC_INITIALIZED=1025910393



Compará con un Teensy:



UDEV  [1129.307311] add      /devices/pci0000:00/0000:00:12.0/usb3/3-1 (usb)
ACTION=add
BUSNUM=003
DEVNAME=/dev/bus/usb/003/004
DEVNUM=004
DEVPATH=/devices/pci0000:00/0000:00:12.0/usb3/3-1
DEVTYPE=usb_device
DRIVER=usb
ID_BUS=usb
ID_MM_DEVICE_IGNORE=1
ID_MM_PORT_IGNORE=1
ID_MODEL=USB_Serial
ID_MODEL_ENC=USB\x20Serial
ID_MODEL_FROM_DATABASE=Teensyduino Serial
ID_MODEL_ID=0483
ID_REVISION=0100
ID_SERIAL=Teensyduino_USB_Serial_12345
ID_SERIAL_SHORT=12345
ID_USB_INTERFACES=:020201:0a0000:
ID_VENDOR=Teensyduino
ID_VENDOR_ENC=Teensyduino
ID_VENDOR_FROM_DATABASE=Van Ooijen Technische Informatica
ID_VENDOR_ID=16c0
MAJOR=189
MINOR=259
MTP_NO_PROBE=1
PRODUCT=16c0/483/100
SEQNUM=2791
SUBSYSTEM=usb
TYPE=2/0/0
USEC_INITIALIZED=1129295449





Me fije que no estuviera en blacklist

$ grep -i 16c0 /lib/udev/rules.d/77-mm-usb-device-blacklist.rules
$ grep -i 05dc /lib/udev/rules.d/77-mm-usb-device-blacklist.rules



Listé el hardware:

$ sudo lshw

              *-usb:0 UNCLAIMED
                   description: Generic USB device
                   product: USBasp
                   vendor: www.fischl.de
                   physical id: 1
                   bus info: usb@3:1
                   version: 1.02
                   capabilities: usb-1.10
                   configuration: maxpower=50mA speed=1Mbit/s

Bien, es lo que estaba suponiendo.

Finalmente asocié el UNCLAIMED con ID_MODEL_FROM_DATABASE=shared ID for use with libusb, dejé de intentar que aparezca /dev/ttyACM0 y probé y funcionó. Así que todo esto servirá para diagnosticar otro problema en otro momento.


Me he servido al menos de:


  • https://andreasrohner.at/posts/Electronics/How-to-fix-device-permissions-for-the-USBasp-programmer/
  • https://forums.virtualbox.org/viewtopic.php?f=35&t=82639
  • https://wiki.webevaluation.nl/arduino_programmers_errors
  • https://opensource.com/article/18/11/udev

2020/04/05

Generador precario de señales cuadradas con FPGA

Contexto



No estabas leyendo aún pues no terminé con mi intento de hacer que un 8051 recuperado de un disco rígido ejecutara un programa mío usando la ROM externa, cuando nos vimos en la necesidad de demultiplexar datos y direcciones de la ROM y no teníamos un 74ls373 sino un 74ls374 que tiene señal de clock entonces le queríamos dar ese clock, muy alto y no sabemos electrónica básica así que vamos usar una FPFA en forma de iCEstick.

Va a estar en uno de estos días en
https://seguridad-agile.blogspot.com/2020/04/rescatando-un-8051.html

 

Mejor explicado:


Quiero usar una FPGA como generador de señales con frecuencias de hasta 12 Mhz, que por un lado es lo que necesito para otro proyecto y por el otro es lo que me da un iCEstick.


Para programar necesito usar Lattice iCEcube2 que tengo instalado en una máquina virtual con una licencia que venció en el 2018, casi sin usarla, lamentablemente no me di cuenta y la "quemé" por decir de una manera.

Lo más fácil debe ser obtener una nueva licencia, pero eso es un conocimiento de gestión y burocracia, no quiero decir que no lo necesite, pero no tengo ganas de adquirirlo o reforzarlo, así que tomaré un

<desvío>

y le cambiaré la fecha para que iCEcube piense que el tiempo no ha pasado.

Cuando arranque debo tener la precaución de que no tome la fecha y hora por NTP y setearle en el BIOS la fecha que quiero.

Para lo primero basta con desconectar de la red:



Ejemplo sobre otra máquina virtual cualquiera


Luego fijarse cuándo fué la última vez que la encendiste poniéndo el cursor sobre la máquina, como para que no viaje al pasado, luego calculás el tiempo y le cambiás el BIOS:








VBoxManage modifyvm "CIAA Linux" --biossystemtimeoffset  -69379200000

siendo  -31536000000 * 2.2 =  -69379200000,  esto es un año y 10 semanas para atrás, no fué tan difícil, ni califica de subdesvio.



</desvío> 

La vida no es fácil, en esa virtual no tenía mi proyecto de blinky que es el que pienso adaptar, está en otra cuya clave no recuerdo y es Windows 10 y debo tomar otro

<desvío>

Quise montar con una recetita que tenía para luego ejecutar chntpw, pero no, así que tomé otro camino, arrancar desde un linux, pero por ser uefi se resistó.

Mi receta fué:
  • Decirle a virtualbox que no arranque del disco, sólo de cdrom.
  • Conectarle un boot uefi, tenía un puppy.
  • Ver las particiones con fdisk
  • Montarla con mount
  • Ubicarme en el lugar correcto 
  • Ejecutar chntpw -i y pedirle blanqueo, que es lo que no sé ve pues es lo que sigue, pero ya me aburrí de esto.
 



</desvío>

Habiendo tomado el control de la situación, sólo tengo que adaptar el ejemplo de blinky para que en lugar de prender y apagar leds a una velocidad humanamente perceptible, prenda y apague pines a varios Mhz.

¡Maldición! No es Verilog, es VHDL, que es lo que había aprendido originalmente de FPGA y luego olvidé por falta de uso. Tengo entonces varios desafíos:

  • Recuperar VHDL, no debería haber problema pues es sólo mirar fijo.
  • Obtener el clock más alto posible, fácil, mirando el archivo .scf del proyecto hallé definido un clock CLK_32MHZ.
  • Identificar los pines, no hay problema, es sólo mirar una tablita en algún lado.
  • Grabarlo desde la virtual, supongo que ya lo hice antes sin problemas.
  • Hacer la adaptación eléctrica, dado que el alto es 3.3 y no va a leer, no debería haber problema.



Al blinky original lo había toqueteado para mostrar sequencias de leds distintas, pero eso fue hace ya dos años antes de saber casi nada.


Aunque a un nivel muy íntimo entiendo bastante lo que hice y los porqués, no quiero intentar explicarlo pues probablemente esa explicación no sólo sea mala si no perjudicial.

Estos son los pasos que seguí, más que nada como nota para mí, no estoy haciendo un tutorial de VHDL en iCEcube2 Lattice, ahora estoy en sintonía con Verilog en Vivado Xilinx. Podría mejor partir del ejemplo Verilog, pero está bueno ponerle un poco de dificultad, de hecho mi primer lenguaje fué VHDL.


Asi que esto, a menos que tengas exactamente el mismo equipo probablemente no te sirva para nada y puedas saltar hasta el código VHDL.

Si hubiese querido (podido) usar un proyecto nuevo, tendría que haber:


  • New Project
  • Device Family: iCE40
  • Device :       HX1K
  • Device Package: TQ144
  • Next
  • Buscar la carpeta del proyecto
  • Crear un archivo .v
  • Incorporarlo a design files
  • Abrir el archivo y copiar y pegar todo lo que quieras


No se pueden abrir dos proyectos a la vez, pero si dos IDEs a la vez cada una con su proyecto.

No pude hacer un proyecto de cero. Tomé entonces el camino habitual de tomar el blinky que funciona y tras bastante renegar llegué a esto:


library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

entity Blink is
  port(
    pmod1  : out std_logic;
    pmod2  : out std_logic;
    pmod3  : out std_logic;
    pmod4  : out std_logic;
    clk    : in  std_logic
  );
end Blink;

architecture Behavior of Blink is
  signal count : std_logic_vector(23 downto 0);
begin
  pmod1 <= clk;
  pmod2 <= count(0);
  pmod3 <= count(1);
  pmod4 <= count(2);

  process(clk)
    begin
      count <= count + 1;
    end process;
end Behavior;

Si algo te parece raro puede ser por que quité el código que a la vez hace un blink rotativo con los cuatro leds y blinky central.

No es mucha magia, en pmod1 tenés la 12Mhz, en pmod2 6Mhz y así...

Puse esto en los constraints, pero no me preguntes exactamente en qué archivos:

define_clock -name {icetest|clk} {p:icetest|clk} 
   -period 7.838 -clockgroup Autoconstr_clkgroup_0
   -rise 0.000 -fall 3.919 -route 0.000

set_io clk 21

set_io pmod1 78
set_io pmod2 79
set_io pmod3 80



Le das a

Run all

y tenés un

Bit Stream Generator succeeded

Fijate que si modificaste un archivo y no lo salvaste, iCEcube2 es bastante incapaz... de avistarte.

Luego abrís el Diamond Programmer, todo lo que sigue está en:

https://www.latticesemi.com/icestick -> documentation -> iCEstick User Manual

  • Blank project
  • Detect cable ( a mi me aparece cable HW-usbn-2b (ftdi) port ftusb-0 )
  • device family ice40
  • device ice40hx1k
  • operation
    • access mode: spi flash programming
    • vendor: micron
    • device spi-n25q032
    • package : 8 pin vdfpn8
  •  file: implmnt -> sbt -> outputs -> bitmap -> file.bin


Si tenes la IDE en una virtual como yo, no te olvides de (re)conectar el dispositivo con:

  • virtual box -> devices -> sub -> lattice ftusb





Si la próxima vez que intentar programar la FPGA te equivocás por que no ajustaste todo bien, tipo dispositivo y método de acceso y de ahí en más te dice error de programación, configurás bien y le das un "erase all", restaurás la configuración y si tenés la misma suerte que yo, vuelve a andar

Sólo me queda el último punto, que la salida de 3.3v pueda alimentar un chip de 5v como un arduino o un 8051 y a la vez no se dañe.

Para eso tengo que mirar fijo los siguiente conceptos:

  • HMOS por el lado del 8051
  • SB_LVCMOS por el lado del iCEstick
¿SB_LVCMOS? ¿Cómo me enteré que el iCEstick usa eso? Muy fácil, por el reporte de pines:

78, PIO, pmod1, Output, , SB_LVCMOS, No Pull Up, Simple Output, rightBank
79, PIO, pmod2, Output, , SB_LVCMOS, No Pull Up, Simple Output, rightBank
80, PIO, pmod3, Output, , SB_LVCMOS, No Pull Up, Simple Output, rightBank
81, PIO, pmod4, Output, , SB_LVCMOS, No Pull Up, Simple Output, rightBank

¿HMOS? más fácil aún, lo dice la datasheet del 8051.

He expresado al menos últimamente mi aversión a usar google para resolver problemas, pero mi electrónica es tan precaria y llevo tantas horas a lo largo de tantos días acercándome a un final tan incierto que estoy dispuesto a casi cualquier cosa.

how to connect a SB_LVCMOS output to a HMOS input

O no se llama así o a nadie le ha interesado hacer o es tán fácil que nadie lo ha publicado o google no sabe.

Puedo aflojar un poco ahora que aprendí que HMOS es High Density NMOS y quitar SB, pues en todos los resultado previos aparece LVCMOS.

how to connect a LVCMOS output to a NMOS input

Mis conocimientos de electrónica son muy básicos e insuficientes para resolver esto con un transistor, cosa que intenté, pero sólo funcionó hasta unos 180Khz, para frecuencias mayores hace falta saber más.

Lo que hice entones fué usar un 74ls08, que es una puerta AND y que dice según su datasheet que con 2v le alcanza para pensar que es un true y que tiene una frecuencia de trabajo mucho mayor.



Fijate que cuadradita que estaba la señal azul en la imagen anterior

Quedó horrible la adaptación a 5v, apuesto a que eso se debe a la ausencia de algunos capacitores en los lugares apropiados, si alguien de embebidos o que sepa electróncia lee esto y se apiada de mí, me va a corregir.

Conclusión

  • He podido obtener una POC de un generador de señales cuadradas usando un FPGA que daba por inaproblechable.
  • Para usarlo con 3.3v está ok.
  • Tiene hardcodeadas la cuatro frecuencias, algún día encararé generarle algún tipo de posibilidad de variar.
  • Con la adaptación a 5, está horrible, luego sabré si funciona para mi proyecto de 8051