compresión y comunicación de datos con un...

80
Compresión y comunicación de datos con un microcontrolador PIC TITULACIÓN: Ingeniería Técnica Industrial en Electrónica Industrial AUTOR: Miguel Periago de la Torre DIRECTOR: Nicolau Cañellas Alberich FECHA: Junio 2007

Upload: lamcong

Post on 14-Mar-2018

217 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

Compresión y comunicación de datos con un

microcontrolador PIC

TITULACIÓN: Ingeniería Técnica Industrial en Electrónica Industrial

AUTOR: Miguel Periago de la Torre DIRECTOR: Nicolau Cañellas Alberich

FECHA: Junio 2007

Page 2: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

1. MEMORIA DESCRIPTIVA 3 1.1 INTRODUCCIÓN 3

1.1.1 Antecedentes 3 1.1.2 Objetivos 3

1.2 SOLUCIÓN ADOPTADA 3 1.2.1 Descripción de nuestro Sistema. 4 1.2.2 El bus USB 4

1.2.2.1 ¿Qué es? 4 1.2.2.2 Características generales del USB 5 1.2.2.3 La topología del bus 7 1.2.2.4 La capa física 9 1.2.2.5 El host USB 10 1.2.2.6 El controlador del host 10 1.2.2.7 Dispositivos USB 12 1.2.2.8 HUBS 13 1.2.2.9 Arquitectura Externa 14 1.2.2.10 Arquitectura Interna 15 1.2.2.11 Funciones 16 1.2.2.12 La capa lógica 17 1.2.2.13 El flujo de datos del bus USB 18 1.2.2.14 Endpoints y direcciones de dispositivo 18 1.2.2.15 Tuberías 19 1.2.2.16 Tipos de transferencias 20 1.2.2.17 El protocolo y las transferencias 21

1.2.3 Microcontroladores PIC. 25 1.2.3.1 Microcontroladores: características generales. 25 1.2.3.2 Arquitectura del microcontrolador. 25 1.2.3.3 El procesador. 26 1.2.3.4 El procesador PIC18F4455. 28 1.2.3.5 Puerto serie rs-232 29

1.2.4 Memoria RAM externa. 29 1.3 DESCRIPCIÓN DE NUESTRO SISTEMA 30 1.4 SOFTWARE CONTROLADOR DE LAS COMUNICACIONES USB. 30 1.5 COMPRESION DE LOS DATOS 31

1.5.1 Conceptos previos 31 1.5.2 Algoritmos ESTADÍSTICOS 32 1.5.3 Algoritmo Huffman 32

1.5.3.1 Algoritmo Shannon-Fano 32 1.5.3.2 Algoritmos Aritméticos 33 1.5.3.3 Algoritmos Predictivos 33

1.5.4 Algoritmos BASADOS EN DICCIONARIO 33 1.5.4.1 Algoritmo Run-Length 33 1.5.4.2 Algoritmo LZW 34 1.5.4.3 Algoritmo LZ77 34

1.5.5 Algoritmo elegido para implementar en nuestro software. 35 1.5.6 Factor de compresión 35

1.6 GESTIÓN DE LOS DATOS 36 1.6.1 Descripción general 36 1.6.2 Formato del protocolo de comunicación. 37 1.6.3 Proceso de lectura de datos y carga en la memoria RAM. 38

1.7 DESCRIPCIÓN CIRCUITAL 40 1.8 SOFTWARE DEL PC 41

2 MEMORIA DE CÁLCULO 43 2.1 INTRODUCCIÓN 43 2.2 HARDWARE 43 2.3 CÓDIGO DEL PIC. 45

3. APENDICE 57

2

Page 3: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

1. MEMORIA DESCRIPTIVA 1.1 INTRODUCCIÓN

Lo que se pretende con este proyecto, básicamente, es crear un sistema capaz de transmitir datos recibidos de un PC a través de un bus rápido y enviarlos a traves de un bus lento, utilizando un microcontrolador. Los buses en cuestión son el bus usb y el bus serie del microcontrolador.

Esto lo vamos a hacer utilizando un microcontrolador tipo pic y una memoria RAM externa.

Además, los datos que vamos a enviar a través de la comunicación serie rs-232 van a estar comprimidos. De esta manera vamos a poder amortiguar la diferencia de velocidades de transmisión/recepción que existe entre el bus USB y la rs-232.

Para la compresión vamos a utilizar un algoritmo de compresión del tipo LZ77 integrado en el software del microcontrolador.

1.1.1 Antecedentes Se desea realizar un equipo de adquisición y gestión de datos para un podólogo. Es

necesario enviar una cantidad importante de datos hacia el periférico, por lo que necesitamos un sistema que nos permita enviar los datos en el menor tiempo posible.

1.1.2 Objetivos El objetivo de este proyecto es realizar el diseño tanto del software como del

hardware, destinado a la gestión, lo más eficiente posible, de los datos recibidos desde el PC via USB para después enviarlos, via RS-232.

Para que la transmisión sea eficiente vamos a comprimir los datos recibidos

utilizando un algoritmo de compresión. Una vez comprimidos, los vamos a enviar a través del bus serie.

Hemos elegido enviar los datos a través de un bus serie porque así va a ser

fácilmente portable a cualquier otro tipo de comunicación, por ejemplo radiofrecuencia. Existen módulos en el mercado que envían datos por radiofrecuencia a partir de datos recibidos vía serie. La radiofrecuencia no era el objetivo de este proyecto por esa razón enviamos los datos vía serie y en proyectos posteriores quizás se incluirá esta mejora. 1.2 SOLUCIÓN ADOPTADA

La elección del microcontrolador es muy importante. Nosotros decidimos utilizar un microcontrolador pic 18F4455. Este micro dispone tanto de comunicaciones usb 2.0 (alta velocidad) como de comunicación serie.

Dada la cantidad de datos a manejar, la memoria ram interna del propio micro nos

es insuficiente para gestionar las comunicaciones eficientemente, así que hemos incluido una memoria RAM externa de 1 Mbit (131.072 bytes) asíncrona, en nuestro sistema. Esta memoria la podemos manejar utilizando los pines de entrada/salida del micro, vamos a

3

Page 4: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

necesitar 17 pines para direcciones, 8 para datos y 1 pin para control de lectura/escritura. El micro escogido cumple con estos requisitos.

1.2.1 Descripción de nuestro Sistema.

El software que vamos a diseñar se compone básicamente de 4 elementos principales:

- Un driver que nos gestione todas las comunicaciones usb de alta velocidad. - Un algoritmo que nos comprima los datos que nos llegan por el bus usb. - Un driver que nos gestione la memria RAM externa. - Un driver que nos gestione las comunicaciones serie. Este es el diagrama de bloques del software de nuestro sistema.

Figura 1: Diagrama de bloques.

Además de estos elementos del software, vamos a tener una parte de aplicación que va a ser la que va a pasar los datos de un elemento a otro, es decir, se va a encargar de coger los datos que llegan por USB a través del driver USB, pasarlos a el algoritmo de compresión y una vez comprimidos pasarlos al bus serie a través del driver rs-232. Mas tarde explicaremos mas detalles de esta aplicación.

Ahora vamos a ir describiendo con más profundidad cada uno de los principales

elementos de nuestro proyecto.

1.2.2 El bus USB

1.2.2.1 ¿Qué es?

4

Page 5: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

El USB o Universal Serial Bus es una interfaz para la transmisión serie de datos y distribución de energía desarrollado por empresas líderes del sector de las telecomunicaciones y de los ordenadores y que ha sido introducida en el mercado de los PC´s y periféricos para mejorar las lentas interfaces serie rs-232 y paralelo. Provee una mayor velocidad de transferencia (de hasta 100 veces más rápido) comparado con el puerto Paralelo de 25-pin y el Serial DB-9, DB-25, rs-232 que son los puertos que se encuentran en la mayoría de los computadores. Tenía en un principio como objetivo el conectar periféricos relativamente lentos (ratones, impresoras, cámaras digitales, unidades zip, etc.) de una forma realmente sencilla, rápida y basada en comunicaciones serie, aunque por sus características también podía conectarse hasta discos duros.

Figura 2: Velocidad del bus USB

Esta interfaz de 4 hilos distribuye 5V para la alimentación y puede transmitir datos a una velocidad de hasta 480 Mbps en su versión 2.0. Es un bus serie que hace posible la conexión de hasta 127 periféricos a una única puerta de un PC, con detección y configuración automáticas, siendo esto posible con el PC conectado a la red y sin tener que instalar software adicional, y sin tener que reiniciar el ordenador (plug and play, algo que con los puertos convencionales serie y paralelo no sucedía. Tampoco hay que preocuparse por conflictos de IRQs o instalar tarjetas de adaptador para cada periférico. Estos periféricos pueden ser: Ratones, teclados, impresoras, escáneres, grabadoras, discos duros, módems, cámaras digitales...

1.2.2.2 Características generales del USB

La especificación del USB proporciona una serie de características que pueden ser distribuidas en categorías. Estas características son comunes para todas las versiones (desde la 1.0 hasta la 2.0) · Fácil uso para los usuarios: · Modelo simple para el cableado y los conectores · Detalles eléctricos aislados del usuario (terminaciones del bus) · Periféricos auto-identificativos · Periféricos acoplados y reconfigurados dinámicamente (Hot Swappable) · Flexibilidad · Amplio rango de tamaños de paquetes, permitiendo variedad de opciones de buffering de dispositivos · Gran variedad de tasas de datos de dispositivos acomodando el tamaño de buffer para los paquetes y las latencias · Control de flujo para el manejo del buffer construido en el protocolo · Ancho de banda isócrono · Se garantiza un ancho de banda y bajas latencias apropiadas para telefonía, audio, ... · Cantidad de trabajo isócrono que puede usar el ancho de banda completo del bus. · Control de flujo para el manejo del buffer construido en el protocolo

5

Page 6: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

· Amplia gama de aplicaciones y cargas de trabajo · Adecuando el ancho de banda desde unos pocos kbs hasta varios Mbs · Soporta tanto el tipo de transferencia isócrono como el asíncrono sobre el mismo conjunto de cables. · Conexiones múltiples, soportando operaciones concurrentes de varios dispositivos. · Soporta hasta 127 dispositivos físicos. · Soporta la transferencia de múltiples datos y flujos de mensajes entre el host y los dispositivos · Robustez · Manejo de errores y mecanismos de recuperación ante fallos implementados en el protocolo. · Inserción dinámica de dispositivos · Soporte para la identificación de dispositivos defectuosos. · Implementación de bajo coste · Sub canal de bajo coste a 1.5 Mbs · Conectores y cables de bajo coste · Adecuado para el desarrollo de periféricos de bajo coste

En este proyecto se utilizaran la especificaciones del bus USB 2.0. Estas son sus

características: USB 2.0

Esta versión que salió al mercado a mitad del 2000, tras la unión al consorcio de otras 3 compañías (Hewlett Packard, Philips y Lucent), con lo que volvían a ser siete las integrantes del USB-IF.

Como principal característica nos encontramos con un aumento de velocidad hasta 480 Mbps (casi 40 veces la velocidad anterior) con una diferencia de coste casi mínimo. De este aumento de velocidad le viene el nombre de Hi-Speed, que es fácil de confundir con Full-Speed . Full-Speed era el término que se le daba a las versiones USB 1.x que alcanzaban 12 Mbps, por lo que se debe tener en cuenta a la hora de hablar sobre ello.

Este incremento de velocidad a permitido sustituir en muchos casos el interfaz SCSI por el USB.

En total USB 2.0 soporta tres tipos distintos de velocidad: · Hi-Speed 480 Mbps · Full-Speed 12 Mbps · Low-Speed 1.5 Mbps

El alcance de uso para la versión USB 2.0 se ve incrementada notablemente

respecto a sus predecesoras.

RENDIMIENTO APLICACIONES ATRIBUTOSVELOCIDAD BAJA Teclado y ratón Bajo coste

Dispositivos Interactivos

Periféricos de entretenimiento (juegos y realidad virtual)

(Des)Conexión en caliente

10-100 Kb/s Configuración del Monitor Fácil uso Múltiples periféricos

VELOCIDAD MEDIA

6

Page 7: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

Teléfono ISDN/RDSI Bajo coste Audio PBX (Des)Conexion en caliente Video comprimido POTS Fácil uso 500 Kb/s - 10 Mb/s Audio Múltiples dispositivos

Garantizado el ancho de banda Garantizada la latencia

VELOCIDAD ALTA Video Video Gran ancho de banda Unidades de almacenamiento Discos duros y grabadoras Latencia garantizada

Video Comprimido Fácil uso 25-500 Mb/s

Básicamente, USB 2.0 incluye todo lo que ofrece USB 1.1 y añade el modo de alta

velocidad. USB 2.0 también usa el mismo tipo de cables y conectores para conectar los dispositivos de alta velocidad, sin embargo los hubs USB clásicos ralentizarán los dispositivos USB 2.0. Otro requisito es que es necesario un controlador de host para USB 2.0 si queremos tener disponibles la conexión de alta velocidad con un dispositivo de este tipo.

Los hubs USB 2.0 tienen ahora mucho mas trabajo que hacer que en el USB 1.1 ya que necesitan manejar todo el tráfico de tres tipo de dispositivos con velocidades distintas. Conectando un dispositivo USB 1.1 en uno USB 2.0 funcionaría bien, pero no lo haría si lo hiciéramos al revés, además de ralentizarse a 12 Mbps, posiblemente, el sistema operativo avisaría de su mal uso.

La forma de distinguir si tu ordenador tiene USB de alta velocidad es mediante los logotipos registrados por el grupo promotor del USB (el USB-IF), que como se puede ver más arriba está etiquetado en rojo con Hi-Speed. Dicho logotipo sólo lo pueden usar las empresas desarrolladas de hardware que hayan pasados los tests del USB-IF

Cabe destacar que el USB 2.0 es simplemente una extensión y nunca llegara a reemplazar completamente al 1.1 ya que hay productos como teclados genéricos, ratones, joysticks o altavoces que no requieren la gran velocidad que ofrece la tecnología USB 2.0. Sólo dispositivos de alta velocidad como webcams o sistemas de alta capacidad necesitarán el máximo de velocidad, aunque los ordenadores los fabriquen sólo con puertos USB 2.0.

1.2.2.3 La topología del bus El Universal Serial Bus conecta los dispositivos USB con el host USB. La

interconexión física USB es una topología de estrellas apiladas donde un hub es el centro de cada estrella. Cada segmento de cable es una conexión punto-a-punto entre el host y los hubs o función, o un hub conectado a otro hub o función.

El número máximo de dispositivos que puede conectar USB es de 127, pero debido a las constantes de tiempo permitidas para los tiempos de propagación del hub y el cable, el número máximo de capas permitido es de siete (incluida la capa raíz) con un máximo de longitud de cable entre el hub y el dispositivo de 5 metros. Cabe destacar que en siete capas, sólo se soportan cinco hubs que no sean raíz en una ruta de comunicación entre el host y cualquier dispositivo. Un dispositivo compuesto ocupa dos capas, por eso, no puede ser activado si está acoplado en la última capa de nivel siete. Sólo las funciones pueden ponerse en este nivel.

7

Page 8: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

Figura 3: Estructura de capas del bus USB La topología del bus USB se puede dividir en tres partes:

• La capa física: Como están conectados los elementos físicamente • La capa lógica: Los roles y las responsabilidades de los elementos USB • La relación software del cliente-función: Como se ven mutuamente el

software del cliente y los interfaces de las funciones relacionadas.

Figura 4: Diagrama de flujo

8

Page 9: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

1.2.2.4 La capa física La arquitectura física del USB se centra en las piezas de plástico y de metal con las

que el usuario debe tratar para construir un entorno USB. Cada entorno físico USB esta compuesto por cinco tipos de componentes:

• El host • El controlador del host • Los enlaces • Los dispositivos • Los hubs

Los dispositivos están conectados físicamente al host a través de una topología en

estrella, como se ilustra en la figura. Los puntos de acople están provistos de una clase de dispositivos USB llamados hubs, los cuales tienen puntos de acople adicionales llamados puertos. Estos hubs se conectan a otros dispositivos a través de enlaces (cables de cuatro hilos).

El host proporciona uno o mas puntos de acople a través del hub raíz. Para prevenir

los acoples circulares, se impone una estructura ordenada por capas en la topología de estrella y como resultado se obtiene una configuración al estilo de un árbol como se ve en la figura.

Todas las comunicaciones físicas son iniciadas por el host. Esto quiere decir que cada milisegundo, o en cada ventana de tiempo que el bus lo permita, el host preguntará por nuevos dispositivos en el bus USB. Además el host inicia todas las transacciones físicas y soporta todas las transferencias de datos sobre la capa física

9

Page 10: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

Figura5:Topología del bus.

1.2.2.5 El host USB El host es el sistema de computación completo, incluyendo el software y el

hardware, sobre el cual se sostiene el USB. El host tiene la habilidad de procesar y gestionar los cambios de configuración que

puedan ocurrir en el bus durante su funcionamiento. El host gestiona el sistema y los recursos del bus como el uso de la memoria del sistema, la asignación del ancho de banda del bus y la alimentación del bus. El host también ayuda al usuario con la configuración automática de los dispositivos conectados y reaccionando cuando son desconectados.

Un host puede soportar uno o mas buses USB. El host gestiona cada bus independientemente de los demás. Los recursos específicos del bus como el ancho de banda asignado son únicos a cada bus. Cada bus está conectado al host a través de un controlador del host.

Sólo hay un host en cualquier sistema USB. Desde el interfaz USB hasta el sistema de host del ordenador es lo que se le llama controlador de host y puede estar implementado como combinación de hardware, firmware o software. Integrado dentro del sistema de host hay un hub raíz que provee de un mayor número de puntos de acople al sistema.

Siempre que es posible, el software del USB usa el interfaz existente del sistema de host para gestionar las interacciones superiores. Por ejemplo, si un sistema de host usa la Gestión de Energía Avanzada (APM), el software del USB conecta al APM para interceptar, suspender las notificaciones.

1.2.2.6 El controlador del host

10

Page 11: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

El controlador de host está formado por el hardware y el software que permite a los dispositivos USB ser conectados al host. Este controlador es el agente iniciador del bus, es decir es el que comienza las transferencias en el bus. El controlador de bus es el maestro en un bus USB. Otros buses como PCI, permiten la presencia de múltiples maestros donde cada uno arbitra sus accesos al bus. El la arquitectura USB sólo hay un controlador de host por cada bus USB y por eso no hay arbitración para el acceso al bus.

Como las transferencias de datos de los dispositivos pueden ser basadas en datos o en la disponibilidad espacial del dispositivo, la mayoría de los controladores de host están implementados como dispositivos maestros de bus PCI. Esto permite al controlador de host iniciar una transferencia de datos en el bus del sistema cuando le sea necesario, sin requerir la intervención del host de la CPU para cada transferencia. El controlador se comporta como un bus maestro PCI multicanal programable para dar soporte a las necesidades de transferencia de datos de múltiples dispositivos conectados al bus USB.

Figura 6: Controlador de bus USB. Esta figura muestra una vista conceptual del controlador de bus USB. La parte software consiste en el driver del controlador de host (HCD). Este

software interactúa con el hardware del controlador de host a través del interfaz hardware/software.

La parte hardware del controlador de host consiste en un hub raíz que proporciona los puertos USB y los buffers de datos (colas) donde son almacenadas cuando son movidas a/desde memoria.

El host USB interactúa con los dispositivos USB a través del controlador. Las

funciones básicas del controlador de host son: · Detectar la inserción o desconexión de dispositivos USB · Gestionar el flujo de control entre el host y los dispositivos · Gestionar el flujo de datos entre el host y los dispositivos · Coleccionar estadísticas de actividad y estado · Proveer una cantidad limitada de energía a los dispositivos conectados

Hay dos implementaciones estandarizadas de la parte hardware de los controladores de host USB. Ambas proporcionan la misma funcionalidad y rendimiento para la interconexión. Estas implementaciones son:

• El Universal Host Controller Inteface (UHCI) definido por Intel • Open Host Controller Interface (OpenHCI o OHCI) definido por

Microsoft

11

Page 12: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

UHCI esta definido como que la parte software tiene una gran responsabilidad para

mantener el hardware en funcionamiento. Esto permite a esta implementación ser relativamente simple y realizarse con un bajo número de puertas.

OHCI esta definida como que la parte hardware tiene más responsabilidad por el mantenimiento del flujo de datos, para que la parte software tenga menos trabajo que hacer. Esta otra implementación tiende a ser más compleja y tiene una cantidad mayor de puertas que la UHCI

1.2.2.7 Dispositivos USB Un dispositivo es una colección de funcionalidad que lleva a cabo algún propósito

de utilidad. Por ejemplo, un dispositivo podría ser un ratón, un teclado, una cámara... Pueden haber múltiples dispositivos simultáneamente en el mismo bus. Cada dispositivo lleva consigo información que puede ser útil para identificar sus características. La información que describe al dispositivo se encuentra asociada con el canal de control. Esta información se divide en tres categorías:

• Estándar: Esta es la información cuya definición es común a todos los

dispositivos USB e incluye elementos como la identificación del fabricante, la clase, la gestión de energia....

• Clase: La definición de esta información varía dependiendo del aparato. Es una clasificación de los dispositivos en cuanto a sus prestaciones.

• USB Vendor: El fabricante del periférico puede poner aquí cualquier información deseada. El software del host es capaz de determinar el tipo de dispositivo conectado

haciendo uso de esta información y de un direccionamiento individual. Todos los dispositivos USB son accedidos por una dirección USB que es asignada dinámicamente cuando se conecta, asignándole también un número. Cada aparato soporta además uno o más canales a través de los cuales el host puede comunicarse con el dispositivo. Una vez ha sido reconocido e identificado el dispositivo, el software del host puede hacer que los drivers del dispositivo apropiados obtengan el control del nuevo dispositivo conectado.

Cuando desconectamos el dispositivo, la dirección puede ser reutilizada para el próximo dispositivo conectado.

En cuanto a los tipos de dispositivos nos encontramos con dos clases: • Hubs, que proporcionan los puntos de acople adicionales al USB. • Funciones, que le dan al sistema la funcionalidad (HIDs, impresoras,

unidades de almacenamiento...)

12

Page 13: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

1.2.2.8 HUBS

Figura 7: HUB tipico Los hubs son un elemento clave en la arquitectura Plug and Play del USB. Un bus tradicional puede ser dividido en segmentos de bus individuales conectados

por puentes. Cada segmento tiene un número limitado de puntos de conexión debido a la limitada energía y la carga del bus. En la arquitectura USB, el número de puntos de conexión de dispositivos se expande añadiendo dispositivos únicos llamados HUBs o concentradores. Estos dispositivos expanden la arquitectura del USB de dos formas:

• Incrementando los puntos de conexión a través de puertos adicionales • Proporcionando energía a los dispositivos al expandir el bus

Los HUBs sirven para simplificar la conectividad USB desde la perspectiva del usuario y proporcionar robustez y complejidad a un precio relativamente bajo. Según esta arquitectura, se pueden expandir el bus acoplando hubs adicionales, interconectando dichos hubs mediante enlaces. Cada hub convierte un punto simple de conexión en múltiples puntos, donde estos puntos de conexión se les llama puertos.

13

Page 14: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

1.2.2.9 Arquitectura Externa Un hub requiere tener un puerto de subida y de 1 a N de bajada.

Figura 8: Arquitectura externa

El puerto de subida (upstream port) de un hub conecta el hub al host. Es el que

eléctricamente está mas cerca del controlador de host. Está numerado como el puerto 0. Los puertos de bajada permiten la conexión a otro hub o a una función. Están

numerados del 1 al N. Son los que más lejos están del controlador de host. Los hubs pueden detectar conexiones y desconexiones en cada puerto de bajada y activar la distribución de energía para cada dispositivo de bajada. Cada puerto puede ser individualmente activado para cada dispositivo high-,full- o low-speed.

Los hubs tienen dos formas de obtención de la energía: A través del puerto de subida (bus-powered) o de una fuente externa (self-powered).

14

Page 15: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

1.2.2.10 Arquitectura Interna Un hub USB 1.x consiste en:

• El repetidor HUB, que es el responsable de gestionar la conectividad entre el puerto de subida y el de bajada, los cuales están operando a la misma velocidad.

• El controlador del hub hace posible el acceso del hub al host y viceversa. Para la versión USB 2.0 hay un tercer elemento:

• Traductor de transacciones que proporciona los mecanismos que dan soporte a los dispositivos full-/low-speed tras el hub mientras se transmiten todos los datos entre el host y el hub en el modo hi-speed

Figura 9: Arquitectura interna Los hubs tienen diferente comportamiento en cuanto a conectividad dependiendo si

están propagando el tráfico de paquetes, reanudando la señalización o están en estado idle. 1. Conectividad de Señalización de Paquetes (Fig. A)

El repetidor del hub contiene un puerto que debe estar siempre conectado en la dirección de subida, que es la conexión al host y uno o mas puertos de bajada (la de los dispositivos). La conectividad de subida es la conectividad hacia el host y la de bajada hacia el dispositivo. Un hub también tiene un estado idle durante el cual el hub no está conectado. En este estado, todos los puertos del hub están en modo recepción esperando empezar el siguiente paquete. Si un puerto de bajada está activo (en un estado donde puede propagar la señal a través del hub) y el hub detecta el comienzo de un paquete en ese puerto, se establece la conexión en dirección al puerto de subida del hub, pero no a cualquier otro puerto de bajada. Esto significa que cuando un dispositivo o un hub transmite un paquete de subida, solo los hubs en línea entre el dispositivo que transmite y el host verán el paquete.

15

Page 16: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

En la dirección de bajada, los hubs operan en modo broadcast. Cuando un hub detecta el comienzo de un paquete en su puerto de subida, establece la conexión a todos los puertos activos de bajada. Si un puerto no esta activo no se propaga la señal de bajada por él.

2. Reanudación de la conexión (Fig. B) Los hubs tienen distinto comportamiento para la reanudación de la señal de subida y bajada. Un hub que está suspendido emite la señal de continuidad de su puerto de subida a todos sus puertos de bajada activos. Si un hub está suspendido y detecta la reanudación de la señal de un puerto de bajada suspendido o activo, el hub emite esa señal de subida a todos sus puertos activos incluyendo el puerto que inicio la secuencia de reanudación, pero no a los desactivados o suspendidos.

Figura 10: Conexiones del bus

1.2.2.11 Funciones Una función es un dispositivo USB que es capaz de transmitir y recibir datos o

información de control sobre el bus. Típicamente se implementa como un periférico separado con un cable que se conecta en un puerto del hub. Sin embargo hay una gran flexibilidad a la hora de construir dispositivos. Una función simple pueden dar una funcionalidad simple (un micrófono, unos altavoces...) o puede estar compuesto en distintos tipos de funcionalidad, como unos altavoces con un panel LCD. Este tipo de dispositivos se les llama función múltiples o composite device (dispositivo compuesto).

Otra forma de construir productos con múltiples funciones es creando un compound device (que significa también dispositivo compuesto). Este es el término usado cuando un hub está acoplado junto a múltiples dispositivos USB dentro de un mismo paquete. El usuario verá una sola unidad en el extremo del cable, pero internamente tiene un hub y varios dispositivos. Este tipo de "paquetes" tienen una dirección de bus para cada

16

Page 17: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

uno de los componentes, en contraposición a los composite devices que tienen una única dirección.

Un buen ejemplo de un dispositivo compuesto sería un teclado USB que tuviera una conexión adicional para ratón. A pesar de que el teclado es un periférico, en este caso se le puede acoplar un ratón y por supuesto se necesitaría de un hub interno en el teclado para que esto pueda funcionar.

Figura 11: Composición típica

Cada función contiene la información sobre la configuración que describe su

capacidad y requisitos en cuestión de recursos. Antes de que una función pueda ser usado debe ser configurado por el host.

Algunos ejemplos de funciones pueden ser los siguientes:

• Una interfaz humana (HID) como ratón, teclado, tablas digitalizadoras o controladores de juegos • Dispositivos de imágenes: cámaras, escáneres o impresoras • Dispositivos de almacenamiento: CD-ROMs, DVDs disqueteras...

1.2.2.12 La capa lógica

El punto de vista lógico presenta capas y abstracciones que son relevantes para los distintos diseñadores e implementadores. La arquitectura lógica describe como unir el hardware del dispositivo USB a un driver del dispositivo en el host para que tenga el comportamiento que el usuario final desea.

La vista lógica de esta conexión es la mostrada en el esquema siguiente. En el podemos ver como el host proporciona conexión al dispositivo, donde esta conexión es a través de un simple enlace USB. La mayoría de los demás buses como PCI, ISA, etc proporcionan múltiples conexiones al dispositivos y los drivers lo manipulan mediante algunas combinaciones de estas conexiones (I/O y direcciones de memoria, interrupciones y canales DMA).

Físicamente el USB tiene sólo un cable simple de bus que es compartido por todos los dispositivos del bus. Sin embargo, desde el punto de vista lógico cada dispositivo tiene su propia conexión punto a punto al host.

17

Page 18: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

Figura 12: Capa logica

Si lo miramos desde el punto de vista lógico, los hubs son también dispositivos

pero no se muestran en la figura para la simplificación del esquema. Aunque la mayoría de las actividades de los hosts o de los dispositivos lógicos usan

esta perspectiva lógica, el host mantiene el conocimiento de la topología física para dar soporte al proceso de desconexión de los hubs. Cuando se quita un hub, todos los dispositivos conectados a él son quitados también de la vista lógica de la topología.

1.2.2.13 El flujo de datos del bus USB Un dispositivo USB desde un punto de vista lógico hay que entenderlo como una

serie de endpoints, a su vez los endpoints se agrupan en conjuntos que dan lugar a interfaces, las cuales permiten controlar la función del dispositivo.

Como ya se ha visto la comunicación entre el host y un dispositivo físico USB se puede dividir en tres niveles o capas. En el nivel mas bajo el controlador de host USB se comunica con la interfaz del bus utilizando el cable USB, mientras que en un nivel superior el software USB del sistema se comunica con el dispositivo lógico utilizando la tubería de control por defecto ("Default Control Pipe"). En lo que al nivel de función se refiere, el software cliente establece la comunicación con las interfaces de la función a través de tuberías asociadas a endpoints.

1.2.2.14 Endpoints y direcciones de dispositivo Cada dispositivo USB está compuesto por una colección de endpoints

independientes, y una dirección única asignada por el sistema en tiempo de conexión de forma dinámica. A su vez cada endpoint dispone de un identificador único dentro del dispositivo al que pertenece, a este identificador se le conoce como número de endpoint y viene asignado de fábrica. Cada endpoint tiene una determinada orientación de flujo de datos. La combinación de dirección, número de endpoint y orientación, permite referenciar cada endpoint de forma inequívoca. Cada endpoint es por si solo una conexión simple que soporta un flujo de datos en una única dirección, bien de entrada o bien de salida.

Cada endpoint se caracteriza por: • Frecuencia de acceso al bus requerida • Ancho de banda requerido • Número de endpoint • Tratamiento de errores requerido • Máximo tamaño de paquete que el endpoint puede enviar o recibir • Tipo de transferencia para el endpoint • La orientación en la que se transmiten los datos

18

Page 19: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

Existen dos endpoints especiales que todos los dispositivos deben tener, los endpoints con número 0 de entrada y de salida, que deben de implementar un método de control por defecto al que se le asocia la tubería de control por defecto. Estos endpoints están siempre accesibles mientras que el resto no lo estarán hasta que no hayan sido configurados por el host.

1.2.2.15 Tuberías Una tubería USB es una asociación entre uno o dos endpoints en un dispositivo, y

el software en el host. Las tuberías permiten mover datos entre software en el host, a través de un buffer, y un endpoint en un dispositivo. Hay dos tipos de tuberías:

• Stream: Los datos se mueven a través de la tubería sin una estructura definida.

• Mensaje: Los datos se mueven a través de la tubería utilizando una estructura USB. Además una tubería se caracteriza por:

• Demanda de acceso al bus y uso del ancho de banda • Un tipo de transferencia • Las características asociadas a los endpoints

Como ya se ha comentado, la tubería que esta formada por dos endpoints con número cero se denomina tubería de control por defecto. Esta tubería está siempre disponible una vez se ha conectado el dispositivo y ha recibido un reseteo del bus. El resto de tuberías aparecen después que se configure el dispositivo. La tubería de control por defecto es utilizada por el software USB del sistema para obtener la identificación y requisitos de configuración del dispositivo, y para configurar al dispositivo.

El software cliente normalmente realiza peticiones para transmitir datos a una tubería vía IRPs y entonces, o bien espera, o bien es notificado de que se ha completado la petición. El software cliente puede causar que una tubería devuelva todas las IRPs pendientes. El cliente es notificado de que una IRP se ha completado cuando todas las transacciones del bus que tiene asociadas se han completado correctamente, o bien porque se han producido errores.

Una IRP puede necesitar de varias tandas para mover los datos del cliente al bus. La cantidad de datos en cada tanda será el tamaño máximo de un paquete excepto el último paquete de datos que contendrá los datos que faltan. De modo que un paquete recibido por el cliente que no consiga llenar el buffer de datos de la IRP puede interpretarse de diferentes modos en función de las expectativas del cliente, si esperaba recibir una cantidad variable de datos considerará que se trata del último paquete de datos, sirviendo pues como delimitador de final de datos, mientras que si esperaba una cantidad específica de datos lo tomará como un error.

Streams: No necesita que los datos se transmitan con una cierta estructura. Las tuberías stream son siempre unidireccionales y los datos se transmiten de forma secuencial: "first in, first out". Están pensadas para interactuar con un único cliente, por lo que no se mantiene ninguna política de sincronización entre múltiples clientes en caso de que así sea. Un stream siempre se asocia a un único endpoint en una determinada orientación.

Mensajes: A diferencia de lo que ocurre con los streams, en los mensajes la interacción de la tubería con el endpoint consta de tres fases. Primero se realiza una petición desde el host al dispositivo, después se transmiten los datos en la dirección apropiada, finalmente un tiempo después se pasa a la fase estado. Para poder llevar a acabo este paradigma es necesario que los datos se transmitan siguiendo una determinada estructura.

19

Page 20: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

Las tuberías de mensajes permiten la comunicación en ambos sentidos, de hecho la tubería de control por defecto es una tubería de mensajes. El software USB del sistema se encarga de que múltiples peticiones no se envíen a la tuberia de mensajes concurrentemente. Un dispositivo ha de dar únicamente servicio a una petición de mensaje en cada instante por cada tubería de mensajes. Una tubería de mensajes se asocia a un par de endpoints de orientaciones opuestas con el mismo número de endpoint.

1.2.2.16 Tipos de transferencias La interpretación de los datos que se transmitan a través de las tuberías,

independientemente de que se haga siguiendo o no una estructura USB definida, corre a cargo del dispositivo y del software cliente. No obstante, USB proporciona cuatro tipos de transferencia de datos sobre las tuberías para optimizar la utilización del bus en función del tipo de servicio que ofrece la función.

Estos cuatro tipos son: • Transferencias de control • Transferencias isócronas • Transferencias de interrupción • Transferencias de bultos ("Bulk")

Transferencias de controlEs el único tipo de transferencia que utiliza tuberías de mensajes, soporta por lo

tanto comunicaciones de tipo configuración/comando/estado entre el software cliente y su función. Una transferencia de tipo control se compone de una transacción de setup del host a la función, cero o mas transacciones de datos en la dirección indicada en la fase de setup, y por último una transacción de estado de la función al host. La transacción de estado devolverá éxito cuando el endpoint haya completado satisfactoriamente la operación que se había solicitado.

Por lo tanto este tipo de transferencia esta pensado para configurar, obtener información, y en general para manipular el estado de los dispositivos. El tamaño máximo de datos que se transmiten por el bus viene determinado por el endpoint. En dispositivos de velocidad media los posibles tamaños máximos son de 8, 16, 32 o 64 bytes, en velocidad baja el tamaño es de 8 bytes y en velocidad alta 64 bytes. El porcentaje de (micro)frame utilizado ronda el 30% en velocidad baja, 5% en velocidad media y el 2% en alta.

El endpoint puede estar ocupado durante la fase de envío de datos y la fase de estado, en esos casos el endpoint indica al host que se encuentra ocupado, invitando al host a intentarlo mas tarde. Si el endpoint recibe un mensaje de setup y se encontraba en mitad de una transferencia de control, aborta la transferencia actual y pasa a la nueva que acaba de recibir. Normalmente el host no inicia una nueva transferencia de control con un endpoint hasta que no ha acabado la actual, si bien debido a problemas de transmisión el host puede considerar que se han producido errores y pasar a la siguiente. USB proporciona detección y recuperación, vía retransmisión, de errores en las transferencias de control.

Transferencias isócronas

Hacen uso de tuberías stream. Garantiza un acceso al bus USB con una latencia limitada, asegura una transmisión constante de los datos a través de la tubería siempre y cuando se suministren datos, además en caso de que la entrega falle debido a errores no se intenta reenviar los datos.

20

Page 21: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

USB limita el máximo tamaño de datos para los endpoints con tipo de transferencia isócrona a 1023 bytes para los endpoints de velocidad media y 1024 bytes para velocidad alta. De hecho las transferencias isócronas solo se pueden usar en dispositivos de velocidad alta o media. En función de la cantidad de datos que se estén transmitiendo en un momento dado, en velocidad media el porcentaje de frame utilizado puede variar desde un 1% hasta un 69%, mientras que el porcentaje de microframe utilizado en velocidad alta varía entre un 1% y un 41%.

Tranferencias de interrupción

Utiliza tuberías stream. Este tipo de transferencia está diseñado para servicios que envían o reciben datos de forma infrecuente. Esta trasferencia garantiza el máximo servicio para la tubería durante el periodo en el que envía. En caso de error al enviar los datos se reenvían en el próximo periodo de envío de datos.

El tamaño de paquete de datos máximo es de 1024 bytes para alta velocidad, 64 bytes para velocidad media y 8 bytes para baja velocidad. En ningún caso se precisa que los paquetes sean de tamaño máximo, es decir, no es necesario rellenar los paquetes que no alcancen el máximo. Cuando en una transferencia de interrupción se necesite transmitir mas datos de los que permite el paquete máximo, todos los paquetes a excepción del último paquete deben de tener el tamaño máximo. De modo que la transmisión de un paquete se ha llevado a cabo cuando se ha recibido la cantidad exacta esperada o bien, se ha recibido un paquete que no alcanza el tamaño máximo. El porcentaje de (micro)frame utilizado ronda el 13% en velocidad baja y el 2.5% en velocidad media, mientras que en velocidad alta para cantidades similares utilizadas para obtener los anteriores porcentajes se obtienen resultados del 1%, pero para cantidades muy superiores se puede llegar a una utilización del 42%.

Transferencias de bultos ("Bulk")

Hace uso de tuberías stream. Esta diseñado para dispositivos que necesitan transmitir grandes cantidades datos en un momento determinado sin importar mucho el ancho de banda disponible en ese momento. Esta transferencia garantiza el acceso al USB con el ancho de banda disponible, además en caso de error se garantiza el reenvío de los datos. Por lo tanto este tipo de transferencia garantiza la entrega de los datos pero no un determinado ancho de banda o latencia.

El tamaño máximo de paquete de datos para velocidad media es de 8, 16, 32 o 64 bytes, mientras que en velocidad alta es de 512 bytes. Los dispositivos de velocidad baja no disponen de endpoints con este tipo de transferencia. No es necesario que los paquetes se rellenen para alcanzar el tamaño máximo. El porcentaje de frame utilizado en velocidad media en función del número de bytes enviados varía entre el 1% y el 5%, mientras que el porcentaje de microframe en velocidad alta varía entre un 1% y un 5%, eso sí, teniendo en cuenta mayor cantidad de datos.

1.2.2.17 El protocolo y las transferencias En este apartado se muestra de forma general las transacciones que se realizan, y

las particularidades de cada tipo de transferencia. De forma general toda función en principio está esperando a que el host le envíe un paquete, si este paquete es de tipo token entonces cambia el estado de la función iniciándose una transacción. También se debe de tener en cuenta, que cuando o bien el host, o bien una función se encuentran en un estado que no es el de reposo, aparecen los timeouts como otra causa de error.

21

Page 22: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

Transferencias de bulto ("Bulk")

En las transferencias de bulto se puede hablar en parte de transacciones de bulto, pues la idea es enviar datos de paquete en paquete sin que tenga que haber un flujo de datos continuo. La diferencia reside en que si hablamos de transferencia, no se puede considerar que haya terminado hasta que el host haya conseguido enviar los datos, o bien que después de varios intentos fallidos de un error.

Cada transacción de bulto se puede dividir en tres fases: token, datos y "handshake", si bien gracias al token PING pueden haber transacciones de dos fases: token y "handshake". A continuación un esquema de una transacción de bultos.

Figura 13: Transferencia tipo bulk. Transferencias de control Estas transferencias constan de tres fases: transacción setup, fase de datos y

transacción de estado. La transacción siempre la inicia el host, y sirve para enviar información de control para indicar al endpoint que se quiere realizar. El siguiente esquema representa una transacción setup.

22

Page 23: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

Figura 14: Transferencia de control. A continuación se inicia la fase de transferencia de datos, que consiste en una

secuencia de transacciones de datos siempre en la misma dirección alternando DATA0 y DATA1. Esta fase no es obligatoria, la dirección se establece en la fase setup. Finalmente tiene lugar una transacción estado, esta transacción es idéntica a una transacción de bultos. La dirección de esta transacción es siempre la contraria a la de la fase de transferencia de datos, y si esta no existiese, la dirección es del endpoint al host.

Transferencias de interrupción

Las transferencias de interrupción son solamente transacciones de tipo IN y OUT. Desde el punto de vista de las transacciones es muy similar a una transferencia de bultos. A continuación el esquema de una transacción de interrupción.

23

Page 24: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

Figura 15: Transferencia de interrupción

Transferencias isócronas Una transferencia isócrona se plantea como una secuencia de transacciones muy

sencillas para enviar o recibir datos. Estas transacciones no utilizan "handshakes" y por lo tanto no se reenvían paquetes, ya que el objetivo de la transferencia es simular un flujo constante de datos. A continuación un esquema de una transacción.

Figura 16: Transferencia isócrona.

24

Page 25: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

1.2.3 Microcontroladores PIC.

1.2.3.1 Microcontroladores: características generales. Un microcontrolador es un computador completo (microprocesador + E/S + memoria

+ otros periféricos), aunque de limitadas prestaciones, que esta contenido con el chip de un circuito integrado programable y se destina a gobernar una sola tarea con el programa que reside en su memoria, sus líneas de entrada/salida soportan el conexionado de los sensores y actuadotes del dispositivo a controlar.

1.2.3.2 Arquitectura del microcontrolador.

La arquitectura tradicional de computadoras y microprocesadores se basa en el esquema propuesto por John Von Neumann, en el cual la unidad central de proceso, o CPU, esta conectada a una memoria única que contiene las instrucciones del programa y los datos (Fig. 2.4).

El tamaño de la unidad de datos o instrucciones esta fijado por el ancho del bus de la memoria. Es decir que un microprocesador de 8 bits, que tiene además un bus de 8 bits que lo conecta con la memoria, deberá manejar datos e instrucciones de una o más unidades de 8 bits (bytes) de longitud. Cuando deba acceder a una instrucción o dato de más de un byte de longitud, deberá realizar más de un acceso a la memoria. Por otro lado este bus único limita la velocidad de operación del microprocesador, ya que no se puede buscar de memoria una nueva instrucción, antes de que finalicen las transferencias de datos que pudieran resultar de la instrucción anterior. Es decir que las dos principales limitaciones de esta arquitectura tradicional son:

- Que la longitud de las instrucciones esta limitada por la unidad de longitud de los datos, por lo tanto el microprocesador debe hacer varios accesos a memoria para buscar instrucciones complejas. - Que la velocidad de operación (o ancho de banda de operación) esta limitada por el

efecto de cuello de botella que significa un bus único para datos e instrucciones que impide superponer ambos tiempos de acceso.

La arquitectura von Neumann permite el diseño de programas con código

automodificable, práctica bastante usada en las antiguas computadoras que solo tenían acumulador y pocos modos de direccionamiento, pero innecesaria, en las computadoras modernas.

25

Page 26: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

Arquitectura Von Newmann

La arquitectura Harvard y sus ventajas: La arquitectura conocida como Harvard, consiste simplemente en un esquema en el

que el CPU esta conectado a dos memorias por intermedio de dos buses separados. Una de las memorias contiene solamente las instrucciones del programa, y es llamada memoria de Programa. La otra memoria solo almacena los datos y es llamada Memoria de Datos (Fig. 2.5). Ambos buses son totalmente independientes y pueden ser de distintos anchos. Para un procesador de Set de Instrucciones Reducido, o RISC (Reduced Instrucción Set Computer), el set de instrucciones y el bus de la memoria de programa pueden diseñarse de manera tal que todas las instrucciones tengan una sola posición de memoria de programa de longitud.

Además, como los buses son independientes, el CPU puede estar accediendo a los datos para completar la ejecución de una instrucción, y al mismo tiempo estar leyendo la próxima instrucción a ejecutar.

Se puede observar claramente que las principales ventajas de esta arquitectura son: • Que el tamaño de las instrucciones no esta relacionado con el de los datos, y por lo

tanto puede ser optimizado para que cualquier instrucción ocupe una sola posición de memoria de programa, logrando así mayor velocidad y menor longitud de programa.

• Que el tiempo de acceso a las instrucciones puede superponerse con el de los datos, logrando una mayor velocidad de operación. Una pequeña desventaja de los procesadores con arquitectura Harvard, es que deben poseer instrucciones especiales para acceder a tablas de valores constantes que pueda ser necesario incluir en los programas, ya que estas tablas se encontraran físicamente en la memoria de programa (por ejemplo en la EPROM de un microprocesador). (Fig. 2.5)

Figura 17: Arquitectura Harvard

Los microcontroladores PIC 18FXXX poseen arquitectura Harvard, con una memoria

de datos de 2048 Bytes, 256 bytes de EEPROM, una memoria de programa de 16.384 Instrucciones.

1.2.3.3 El procesador.

Es el elemento más importante del microcontrolador y determina sus principales características, tanto a nivel hardware como software. Se encarga de direccionar la memoria de instrucciones, recibir la instrucción en su curso, su descodificación y la ejecución de la operación que implica dicha instrucción, así como la búsqueda de los operándoos y el almacenamiento del resultado.

Existen tres orientaciones en cuanto a la arquitectura u funcionalidad de los procesadores actuales.

CISC: Un gran número de procesadores usados en los microcontroladores están basados en la filosofía CISC (Computadores de Juego de Instrucciones Complejo).

26

Page 27: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

Disponen de mas de 80 instrucciones maquina en su repertorio algunas de las cuales son muy sofisticadas y potentes, requiriendo muchos ciclos para una ejecución. Existen tres orientaciones en cuanto a la arquitectura y funcionalidad de los procesadores actuales.

RISC: Tanto la industria de los computadores comerciales como la de los microcontroladores están decantándose hacia la filosofía RISC (Computadores de Juego de Instrucciones Reducido). En estos procesadores el repertorio de instrucciones maquine es muy reducido y las instrucciones son simples y, generalmente, se ejecutan en un ciclo. La sencillez y rapidez de las instrucciones permiten optimizar el hardware y el software del procesador.

SISC: (Computadores de Juego de Instrucciones Especifico): En los microcontroladores destinados a aplicaciones muy concretas, el juego de instrucciones, además de ser muy reducido, es “especifico”, es decir, las instrucciones se adaptan a las necesidades de la aplicación prevista.

27

Page 28: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

1.2.3.4 El procesador PIC18F4455.

Figura 18: PIC18F4455

28

Page 29: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

1.2.3.5 Puerto serie rs-232

Para el envío de los datos desde nuestro dispositivo hacia el exterior hemos utilizado una comunicación serie. El envío de los datos a través de este bus es bastante sencillo y lo hemos elegido por la versatilidad que ofrece este bus.

Además, la idea inicial de este proyecto era enviar los datos a través de un sistema de radio frecuencia, así que seria muy sencillo adaptar nuestro dispositivo a uno con una antena ya que el protocolo de envío de datos vía rs-232 es muy similar al envío por radio frecuencia. Incluso existen módulos en el mercado que realizan esta operación, reciben datos vía serie y los envían por radio frecuencia.

La comunicación con el puerto serie es una de las mas utilizadas para comunicaciones asíncronas, requerimiento imprescindible para nuestro sistema, ya que no sabemos cuando nos van a llegar los datos.

1.2.4 Memoria RAM externa.

Debido a la cantidad de datos que tenemos que manejar, la memoria RAM interna del microcontrolador no es suficiente, así que hemos decidido instalar una memoria RAM externa de 1 MBit.

Esta memoria es asíncrona, no necesita ningún tipo de entrada de reloj para su sincronización. Dispone de un bus de direcciones (17 pines) y un bus de datos (8 pines). Por la tanto, podremos guardar un byte en cada posición de memoria.

El acceso a los datos es sencillo. Con nuestro microcontrolador tenemos acceso tanto al bus de direcciones como al de datos, así que lo único que tenemos que hacer es poner la dirección deseada en el bus de direcciones y leer o escribir en el bus de datos. Para seleccionar si queremos leer o escribir, disponemos del pin WE (Write enable), que también controlamos a través de una salida del microcontrolador.

El inconveniente que tenemos al utilizar esta memoria, es que cada vez que queremos

acceder a ella tenemos que codificar la dirección deseada en los pines de entrada/salida. Teniendo en cuanta que son 17 pines, y que la dirección a manejar es un valor de 32 bits, nuestro microcontrolador tarda un tiempo en realizar todas las operaciones necesarias. Si lo multiplicamos por todos los accesos a memoria requeridos cada vez que recibimos un paquete de datos, hace que nuestro sistema se ralentice. En el futuro se podría buscar una mejora para esto, ya sea poniendo una memoria con un bus de direcciones mas pequeño, o un microcontrolador con mas memoria RAM.

29

Page 30: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

1.3 DESCRIPCIÓN DE NUESTRO SISTEMA

La arquitectura de nuestro sistema es la mostrada en la siguiente figura:

Figura 19: Nuestro sistema Básicamente nuestro software esta compuesto por tres elementos principales: - Las comunicaciones (USB y RS-232). - La gestión de los distintos buffers del sistema. - El algoritmo de compresión de los datos. A continuación pasaremos a describir cada una de estas partes de nuestro software.

1.4 SOFTWARE CONTROLADOR DE LAS COMUNICACIONES USB.

Para gestionar las comunicaciones del bus usb hemos utilizado el firmware que nos proporciona el propio fabricante del microcontrolador (Microchip), integrandolo en nuestro sofware.

Esta librería esta implementada siguiendo la especificación USB 2.0. Para gestionar las comunicaciones USB, lo que hemos tenido que hacer es incluir una

llamada a la función principal del driver USB cada vez que el bus genera una interrupción, para darle servicio a esta.

Lo que nosotros vamos a utilizar son las funciones que nos proporciona el driver para enviar datos o leer los datos recibidos.

El firmware es configurable a cualquier tipo de transferencia USB, ya sea de tipo bulk, por interrupción o síncrona.

Nosotros vamos a configurar el sistema para que funcione con transferencias del tipo interrupción, ya que los datos que nos llegan desde el PC no los recibimos de forma continuada, sino que nos llegan en forma de ráfagas.

30

Page 31: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

1.5 COMPRESION DE LOS DATOS Para comprimir los datos vamos a integrar en nuestro sistema un algoritmo de

compresión. A la hora de escoger el algoritmo de compresión debemos tener en cuenta que tipo de

algoritmo necesitamos. Sabemos que debe ser de tipo loseless, lo que quiere decir que no hay pérdida de datos durante la compresión. Debemos de asegurar que los datos después del proceso de compresión/descompresión son exactamente los mismos que antes de pasar por el proceso.

También debemos tener en cuenta el factor de compresión, ya que esto va a hacer que realmente sea eficiente en nuestro sistema la compresión de datos en relación a la velocidad de nuestro sistema.

Vamos a repasar brevemente los principales algoritmos de compresión más usados.

1.5.1 Conceptos previos Básicamente la compresión consiste en tomar una trama de símbolos y transformarlos

en códigos/claves. Si la compresión es eficiente, las claves resultantes ocuparán menor espacio que los símbolos originales. La decisión de obtener una codificación a partir de ciertos símbolos (o conjunto de ellos) está basada en un modelo. El modelo es simplemente una colección de datos y reglas usados para procesar a la entrada símbolos y determinar su correspondiente codificación a la salida. Por ejemplo un programa usa el modelo para definir aproximadamente las probabilidades para cada símbolo y el codificador para producir una codificación apropiada basada en esas probabilidades.

Los conceptos de modelo y codificación son cosas diferentes. Usualmente la gente cae en el error de emplear el término de "codificación" para referirse a todo el proceso de compresión de datos en vez de considerarlo como un simple componente de ese proceso. Por ejemplo, "codificación Huffman" y "codificación Run-Length" se suele caer en el error de ser descritas como técnicas de compresión de datos, cuando de hecho solo son métodos de codificación usados en conjunción con un modelo de compresión de datos.

Dentro de las tecnicas de compresión de datos, y atendiendo a la reversibilidad de la

información original, hay dos grandes familias: -Tecnicas de compresion "lowless" ó sin perdida (para datos en los que es

imprescindible que no se pierda nada de información, como por ejemplo registros de bases de datos, ficheros ejecutables, hojas de cálculo...etc).

-Tecnicas de compresion "lossy" ó con perdida (para datos en los que se permite cierta pérdida de información "sin que se note demasiado", como por ejemplo en ficheros en MP3, imagenes en JPEG, PNG...etc. Aquí una pequeña disminución en la calidad final no se nota demasiado, pero influye muy positivamente en la reducción del peso del fichero).

En este proyecto nos vamos a centrar únicamente en la compresión "lowless" sin

pérdida, es decir, técnicas que nos garantizan que no habrá ningún tipo de pérdida de información al comprimirlos (factor fundamental para comprimir y recuperar programas, ficheros de bases de datos...etc).

Tipos de compresión lowless:

31

Page 32: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

- Algoritmos Estadísticos - Algoritmos basados en diccionario (ó sustitucionales).

1.5.2 Algoritmos ESTADÍSTICOS Utilizan las propiedades estadísticas de la fuente para mejorar la codificación (a cada

mensaje de la fuente asigna una cadena de símbolos del alfabeto de salida). Se trata de aprovechar la redundancia de información de la fuente para conseguir esa compresión.

1.5.3 Algoritmo Huffman

Se basa en crear un árbol binario completo, que representa la codificación de los mensajes de la fuente, en el que cada nodo intermedio es menor que sus hijos (y la raiz el menor de todos). Los nodos-hoja contienen cada uno de los mensajes emitidos por la fuente. El código para cada mensaje se construye siguiendo el camino desde el nodo raíz hasta la hoja que representa el mensaje. Además, si el decodificador implementa el mismo árbol usado para comprimir, la decodificación no será más que leer bits e ir siguiendo el camino desde la raíz del árbol hasta las hojas en función del valor de esos bits. Al llegar a la hoja habremos llegado al mensaje.

La codificación es inversamente proporcional a la probabilidad de aparición del mensaje. Al mensaje más redundante, que se repita más, se le dará una codificación más corta asignándole menos símbolos del alfabeto de salida y ahorrando así espacio.

En cada paso se recogen los dos nodos con menor probabilidad del árbol y se crea un

nodo padre para ambos que contendrá la probabilidad sumada de los dos. Los nodos con menor probabilidad irán quedando al fondo.

Generalmente los descompresores de este tipo no tiene posibilidad de conocer previamente las probabilidades de los mensajes, pues sólo recibe los códigos asignados a los mensajes; en consecuencia el árbol ya procesado ha de ser pasado al descompresor, junto con los datos. Esto representa una carga adicional al fichero comprimido que resta en parte la eficiencia de esta técnica. Por ello una de las soluciones es hacer que estos algoritmos sean "adaptativos": se construye el árbol dinámicamente tanto por el compresor como por el descompresor, y así no estaremos obligados a pasarle al descompresor el árbol. Dependiendo del compresor, se suelen utilizar diferentes implementaciones "adaptativas" para los compresores.

1.5.3.1 Algoritmo Shannon-Fano

Construye un árbol como Huffman, pero en vez de partir desde las hojas a la raiz, este

algoritmo parte desde la raiz hacia las hojas. Inicialmente considera a todos los mensajes en un solo conjunto. En cada etapa, se

intenta dividir el conjunto en dos conjuntos con la probabilidad más parecida posible entre ambos (para conseguir que, a mayor probabilidad, obtener conjuntos con menos elementos). Se asigna un bit con valor 0 ó 1 a cada uno de estos dos nuevos conjuntos y se va repitiendo el proceso de manera recursiva para cada nuevo conjunto creado hasta llegar a conjuntos con un solo elemento que representarán un mensaje.

32

Page 33: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

1.5.3.2 Algoritmos Aritméticos Se basan también en las probabilidades de repetición de los mensajes a la entrada,

aunque su metodología es my distinta. Lo que hacen es representar un valor del intervalo [0,1] con mayor numero de decimales -mayor precision- cuanto mayor sea la información de los datos a comprimir. Basicamente va dividiendo el intervalo [0,1] sucesivamente hasta obtener un numero -dentro de ese intervalo- que utilice menos bits para representar toda la entrada. Así el decompresor podrá reconstruir la entrada con ese número más la información del numero de elementos codificados y sus probabilidades correspondientes. Es un proceso bastante eficiente, aunque como se acaba de decir las probabilidades deben ser incluidas en el fichero comprimido. Por ello se suelen utilizar también modelos adaptativos, que cambian dinámicamente con la entrada.

1.5.3.3 Algoritmos Predictivos Intentan predecir el siguiente mensaje de la entrada en base a lo que se sabe de la

entrada procesada en ese momento. Si el mensaje de la entrada coincide con el predicho la codificación se podrá hacer con menos bits. En caso contrario se hará con más bits (que permitan la sincronización con el decompresor a la hora de mantener las mismas tablas internas; así ya no necesitamos incluirlas en el fichero comprimido). Son adaptativos.

En consecuencia suelen ser más rápidos que las técnicas anteriores, tanto para

compresión como decompresión, y además no son difíciles de programar (sí su mejora). Son muy malos cuando hay mucha redundancia, así que en la práctica se suelen usar en conjunción con otras técnicas de compresión para tratar los casos en que hay excesiva redundancia (por ejemplo el Run-Length).

1.5.4 Algoritmos BASADOS EN DICCIONARIO Son las técnicas más utilizadas, generalmente se las implementa en conjunción con

compresores estadísticos.

1.5.4.1 Algoritmo Run-Length Ó tambien denominado RLE (Run Length Encoding). Es el mas simple y a la vez el

más ineficiente. Lo incluyo aquí porque se podría considerar que utiliza un diccionario deslizante para predecir el siguiente carácter de la entrada. Realmente se le considera ya algo "primitivo". Además hay diferentes formas de implementarlo, todas ellas patentadas.

Busca repeticiones consecutivas de un mismo símbolo y lo que hace es almacenar en un byte el número de esas repeticiones consecutivas y en el segundo byte el escribe el símbolo. Como ejemplo:

17 48 (el byte 48 se repite 17 veces) Demuestra gran eficiencia cuando hay un alto número de repeticiones consecutivas de

un determinado byte. La unidad básica serían dos bytes, el primero indica el numero de

33

Page 34: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

veces que se repite el segundo. Básicamente se utiliza para crear archivos tipo BMP o PCX sin gradaciones de color.

Era utilizado por el ARC, entre otros.

1.5.4.2 Algoritmo LZW Pertenece a la familia de los LZ78 (Liv & Zempel). Es un algoritmo Greedy

Adaptativo. Es el que implementan la mayoría de los programas de compresión. Fue publicado por primera vez en 1984 en IEEE Computer por Terry Welch. Actualmente esta técnica está patentada por Unisys.

En la codificación, al principio el compresor parte de un diccionario en el que se han

introducido todas las cadenas de longitud 1, es decir, 256 cadenas que constan de un solo carácter (los caracteres ASCII). Añadir una cadena al diccionario significa asignarle un identificador secuencial consecutivo a partir de la anterior cadena. Como al principio las primeras 256 posiciones están ocupadas el siguiente número a asignar es el 257. Este número ya no cabe en 8 bits, por lo que las salidas (los identificadores de las cadenas ya reconocidas) del algoritmo son al principio de 9 bits e irán aumentando conforme se vaya quedando pequeño el diccionario.

Durante el proceso, se van añadiendo nuevas cadenas de longitud mayor. Al identificarse cadenas más largas con un número de varios bits, la compresión resulta bastante efectiva. El proceso de compresión es:

La descompresión es más sencilla, aunque tiene que construir el mismo árbol. El

descompresor recibe inicialmente códigos de 9 bits que usará como índices en el diccionario. Mantendrá el diccionario actualizado a partir de esa información. El proceso de decompresión es el siguiente:

Se ha visto que el diccionario iba creciendo a medida que se iban insertando nuevas

cadenas en él. Sin embargo hemos de ser conscientes de que la memoria es finita y hay que poner tope a esa inserción. Además, a medida que el diccionario vaya creciendo, se utilizarán más bits para identificar a cada cadena, con lo que para las cadenas cortas (que son también las más probables) se conseguirá una codificación pobre e ineficiente, puesto que ahorrará pocos bits. Una vez puesto un tope (digamos de 12 a 14 bits, es decir, entre 4096 y 16384 cadenas), está claro que el diccionario se llenará y habrá que eliminar las cadenas que guarda. Algunos modelos desechan todas las cadenas del diccionario y lo "vacían completamente", otros aprovechan las cadenas que más se han usado y la dejan en el diccionario; no hay una condición única que nos asegure que una ú otra opción será mejor.

1.5.4.3 Algoritmo LZ77

Es más utilizado que el LZ78 (posiblemente por tener menos problemas de propiedad). Es una técnica presente en multitud de modelos de compresión pues tiene tantas decisiones de diseño que cada uno es implementado de manera distinta a los demás. Esto hace que no se puedan patentar o que se puedan saltar de una forma u otra las patentes actuales. Como ejemplo de compresores que lo usan sería: ARJ, PKZIP, RAR, etc).

34

Page 35: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

El LZ77 mantiene también un registro de los últimos caracteres procesados de la entrada, pero en este caso no construye un diccionario explícito. En cada momento, el algoritmo se encuentra procesando en un punto de la entrada los "n" caracteres anteriores que forman la "historia" del algoritmo ó "ventana" (lo que equivale al diccionario). Los caracteres posteriores al punto actual forman el llamado "buffer de adelantamiento". En cada paso, la cadena que comienza en el punto actual de la entrada se busca hacia atrás en la "historia". Si se encuentra una coincidencia que sea lo suficientemente larga como para tenerla en cuenta, a la salida se sustituye la cadena coincidente por un par que indica el "desplazamiento hacia atrás" y la "longitud" de la coincidencia con la cadena hacia atrás. Como los pares "desplazamiento, longitud" ocupan menos que la cadena que coincidió, se obtiene compresión. Si no se encuentra una coincidencia, la salida es una copia literal de la entrada. Posteriormente se avanza la ventana (es decir, se avanza en la entrada) bien de longitud si hubo coincidencia, bien un carácter si no la hubo. El hecho de ir desplazando la ventana sobre la entrada hace que a estos algoritmos se les llame también de "ventana deslizante". Cuanto más grande sea la ventana, mayor será la compresión (más grande es la historia sobre la que se buscan posibles coincidencias y mayor la probabilidad de encontrar una coincidencia más larga), aunque para una ventana grande necesitaremos más bits para codificar los valores del desplazamiento. Por ello el tamaño de ventana más apropiado debería ser uno que haga que el campo de desplazamiento quepa en pocos bits.

El descompresor es muy sencillo, ya que su "ventana" está formada por los datos que

ha decomprimido anteriormente, y, cuando recibe un par (desplazamiento, longitud), sólo tiene que copiar a la salida la longitud de bytes que están en el desplazamiento de los bytes antes. En el caso de recibir un literal, este es copiado tal cual a la salida.

1.5.5 Algoritmo elegido para implementar en nuestro software.

Después de estudiar los diferentes tipos de algoritmos existentes para implementar en nuestro software, decidimos implementar un algoritmo del tipo LZ77.

Las razones de utilizar este algoritmo y no otro son: - Sencillez de implementación, por lo tanto menor espacio tanto en la memoria

FLASH como en la RAM, factor muy importante dado que la cantidad de memoria disponible en el pic es reducida.

- Factor de compresión del tipo de datos a tratar alto. - Velocidad de compresión aceptable para nuestro sistema.

1.5.6 Factor de compresión

Después de realizar varias pruebas del algoritmo con diferentes tipos de datos hemos obtenido diferentes factores de compresión.

Estos son los resultados:

Tipo de archivo Tamaño original(bytes)

Tamaño comprimido(bytes)

Factor de compresión

Xls 45000 32432 0,72 Pdf 45000 37988 0,84 Doc 45000 23109 0,51 Zip 45000 41124 0,91

35

Page 36: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

Podemos ver que el factor de compresión depende mucho del tipo de datos que a

comprimir. Por ejemplo, si los datos ya han pasado por un proceso de compresión como seria el caso de los datos en formato zip o pdf, el factor de compresión es muy bajo. Donde realmente es eficiente el algoritmo es cuando comprimimos datos que no han sido tratados previamente, como son los datos en formato doc. Los datos que nosotros vamos a recibir no están tratados por ningún algoritmo similar al nuestro, por lo que el factor de compresión que vamos a obtener va estar en torno al 50 %.

Esto hace que realmente sea útil integrar el algoritmo en nuestro sistema.

1.6 GESTIÓN DE LOS DATOS

1.6.1 Descripción general Para la gestión de los datos hemos utilizado una memoria ram externa ya que la

memoria ram de la que dispone el pic (2 Kbytes) era insuficiente para una gestión eficaz de los datos.

Hemos escogido una memoria de 1 Mbit (131.072 bytes), memoria fácilmente

manejable por nuestro pic de 40 pines. Hemos creado varios buffers dentro de la memoria ram externa. Básicamente, la

gestión de los datos se realiza mediante dos buffers de entrada de datos, y un buffer de salida donde se encuentran los datos ya comprimidos.

Los dos buffers de entrada y el de salida son de 43.690 bytes cada uno. La razón de tener dos buffers de entrada es poder estar recibiendo datos a la vez que se

realiza la tarea de compresión. Mientras el primer buffer de entrada se va llenando, el segundo se va comprimiendo y enviando al exterior y viceversa.

Los datos que enviamos al exterior se envían mediante comunicación rs-232. Aquí nos

surge un problema, ya que la velocidad de transmisión del USB 2.0 es mucho mayor que la velocidad de la comunicación rs-232. El hecho de comprimir los datos amortigua esta diferencia.

Datos recibidos

USB 2.0 (Mbits/s)

Datos enviados (bits/s)

(baudios) Velocidad de transmisión 12 19200

Por lo tanto, con esta diferencia de velocidad necesitariomos 625 segundos para enviar

los datos que nos llegan por usb en 1 segundo. Si aplicamos un factor de compresión de 0,7 estos son los resultados:

Datos recibidoscomprimidos

USB 2.0 (Mbits/s)

Datos enviados (baudios)

Velocidad de transmisión 8,4 19200

36

Page 37: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

Ahora, necesitamos unos 437 segundos para enviar los datos. Por lo tanto no vamos a poder aprovechar toda la velocidad de transmisión que nos

ofrece el usb 2.0, ya que el hecho de utilizar la comunicación rs-232 nos introduce mucho retraso.

Este seria un diagrama de tiempo para nuestro sistema:

Recepción de datos

Compresión Envío rs-232

Recepción de datos

Compresión Envío rs-232

Buffer1

Buffer2 Espera

t

349 ms 12.74 sec

349 ms 12.74 sec

1.6.2 Formato del protocolo de comunicación. Nuestro sistema va a tener que comunicarse con un pc, así que es necesario que este

sepa cuando estamos listos para recibir datos y cuando no. Para ello, vamos a implementar tanto en la aplicación que envía los datos a través del

usb, como en nuestro periférico, una serie de comandos. Esto nos va a permitir atender diferentes peticiones, que son: - Leer versión del software del periférico. - Testear la RAM. Se escribe y se lee un valor en una posición de RAM aleatoria. - Comienzo de recepción de datos. Prepara al dispositivo para recibir datos. - Fin de envío de datos. Detiene la recepción de datos y da paso a la finalización de la

compresión de datos y envio.

37

Page 38: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

1.6.3 Proceso de lectura de datos y carga en la memoria RAM. Vamos a explicar cual es el proceso de recepción, compresión y envío de los datos

cada vez que se recibe una petición por parte del host (PC).

¿Hay Datos en Buffer

USB?

Si

No

Carga de datos en el RAM Buffer activo

¿Final de paquete?

Compresión Si

Envío RS-232

¿Buffer activo lleno?

No Activar buffer complementario

No Si

Figura 20: Diagrama de flujo de los datos recibidos.

Este es el diagrama de flujo de la gestión de los datos en nuestro sistema. Lo que

hacemos es cada vez que nos llega una interrupción por parte del bus usb, comprobamos si este ha colocado datos en el buffer usb (allí donde el driver del bus deposita los datos cuando acaba la transacción).

Si hay datos en el buffer, estos los copiamos en uno de nuestros 2 buffers externos

ubicados en la memoria ram externa. Cuando recibimos el comando de fin de recepción de datos comienza la compresión y el envío vía rs-232.

Si los datos recibidos consiguen llenar el primer buffer, lo que hacemos es activar el

segundo buffer para ir guardando allí los datos mientras se van comprimiendo los datos del primer buffer y se van enviando, para así no hacer esperar al PC en el envío de datos.

Una vez comprimidos los datos del primer buffer, este podría ir llenándose de nuevo

con datos nuevos, y mientras este se va llenando, los datos del segundo buffer se pueden ir comprimiendo y enviando. Y así sucesivamente hasta que el host (PC) comunique que ha terminado la transferencia de datos.

38

Page 39: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

Debido a la diferencia de velocidad y entre la comunicación USB y la comunicación serie, va haber momentos en que uno de los buffers de entrada va a estar lleno y el otro no habrá terminado traspasar la información al buffer de salida. En ese momento lo que vamos a hacer es comunicar al host (PC) que el sistema esta ocupado y que no puede recibir más datos. Una vez que el sistema quede libre, se informa al host que ya se puede continuar con la transferencia.

39

Page 40: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

1.7 DESCRIPCIÓN CIRCUITAL

El hardware de nuestro sistema esta compuesto, básicamente, por el microcontrolador pic y la memoria RAM externa. Hemos utilizado los diferentes puertos del microcontrolador para poder manejar la memoria RAM.

Este seria el diagrama de bloques:

Figura 21: Bloques del periférico.

Los puertos B, C y D los utilizamos como bus de direcciones, mientras que los puertos A y E como bus de datos.

Esta seria la asignación detallada de los pines: Bus de direcciones:

A0 : RC1 A1 : RC2 A2 : RD0 A3 : RD1 A4 : RD2 A5 : RD3 A6 : RD4 A7 : RD5 A8 : RD6 A9 : RD7 A10 : RB0 A11 : RB1 A12 : RB2 A13 : RB3 A14 : RB4 A15 : RB5 A16 : RB6

Bus de datos:

40

Page 41: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

D0 : RA0 D1 : RA2 D2 : RA3 D3 : RA4 D4 : RA5 D5 : RE0 D6 : RE1 D7 : RE2 Read/Write enable pin:

W : RB7 Además vamos a utilizar las comunicaciones USB y RS-232 de las que dispone

nuestro pic, para la transmisión y recepción de datos con el PC.

1.8 SOFTWARE DEL PC

Para comunicarnos con nuestro dispositivo vamos a necesitar un software en el pc. Nosotros lo que vamos a implementar es una aplicación que comunique con el

dispositivo, que le envie y lea datos en el formato esperado. La idea es que en un futuro se desarrolle una aplicación más potente para aprovechar las posibilidades de este dispositivo usb. Esta aplicación la vamos a utilizar para el testeo del dispositivo.

También vamos a necesitar un archivo del tipo *.inf, para que el sistema operativo

del pc (windows XP en este caso), reconozca el dispositivo y podomos enviar y recibir datos.

La aplicación la hemos desarrollado con la herramienta C++ builder. Vamos a explicar con un poco mas de detalle las características de la aplicación. El

aspecto de la aplicación es el siguiente:

41

Page 42: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

Figura 22: Aplicación del host.

Vamos a ir comentando cada uno de las funciones de la aplicación. LeerMPBUSAPI Version: Nos devuelve en forma de texto la versión de la dll que

utiliza la aplicación para comunicarse con el dispositivo. Esta dll nos la proporciona el fabricante del microcontrolador, Microchip.

Buscar dispositivos: Busca si hay algún dispositivo conocido conectado al PC. Nos

dirá si nuestro periférico esta conectado y si el sistema operativo del PC lo ha detectado correctamente.

Leer USB software version: Nos devuelve la versión del software del dispositivo.

Esto nos permitirá conocer la versión de software instalada en el dispositivo, muy útil si tuviéramos que actualizar el software.

Enviar un ficero al dispositivo: envía un fichero de datos para que el dispositivo lo

comprima y lo devuelva vía rs232. Esta es la función principal que vamos a utilizar para testear nuestro dispositivo.

Test RAM: Comprueba que la RAM esta funcionando correctamente.

42

Page 43: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

43

2 MEMORIA DE CÁLCULO 2.1 INTRODUCCIÓN

El objetivo de este apartado del proyecto el análisis y la justificación con los cálculos y programas correspondientes de aquellos apartados donde se crea necesaria su especificación. 2.2 HARDWARE

En este apartado vamos a entrar en más detalle en la construcción de nuestro periférico.

Este es el esquema de conexionado de todos los componentes que forman nuestro

periférico.

Figura 23: Esquemático del periférico

La parte mas destacable del esquemático es la conexión entre el pic y la memoria

RAM. Podemos ver tanto el bus de datos como el bus de direcciones al que están conectados los dos componentes.

La mayor parte de los componentes existentes en la placa son los componentes

necesarios para la configuración de los dos integrados principales, como es el cristal de 20 MHz del pic.

Hemos colocado un conector donde poder conectar el programador del pic. También podemos conectar un emulador para “debugar” el código que hemos desarrollado.

0

RB7

A16

A11

A12

A12

U1

PIC18F4455 IP

123456789

1011121314151617181920

4039383736353433323130292827262524232221

MCLRRA0RA1RA2RA3RA4RA5RE0RE1RE2VDDVSSOSC1OSC2RC0RC1RC2VUSBRD0RD1

RB7RB6RB5RB4RB3RB2RB1RB0VDDVSSRD7RD6RD5RD4RC7RC6RC5RC4RD3RD2

<Doc> <Rev Code>

USB DATA LOGER COMPRESSOR

A

1 1Tuesday , January 24, 2006

Title

Size Document Number Rev

Date: Sheet of

RB4

RB4A4

D6

D7

A6

P1

CONNECTOR DB9

594837261

R74K7

0

A5

U2

M68AF127B

123456789

10111213141516

32313029282726252423222120191817

NCA16A14A12A7A6A5A4A3A2A1A0DQ0DQ1DQ2Vss

VCCA15

EW

A13A8A9

A11G

A10E1

DQ7DQ6DQ5DQ4DQ3

0

D6

0

C2

15PF

A7

ICD

CON6

123456

C5

100uF

A3

MCLR

A13

HC49-3H

20MHz

C3

470nF

0

A8A9

A13A6

Vbus

D5

C1

15PF

D2

D2

A1

C4

0.1uF

A1

Vbus

D0

A16

0

A2

R3

1K

A10

A2D+

Vbus

D4

D1

D-

A16

D7

0

R21K

R4

4K7

D3

D1

RB7

A10

A15

A5

D5

A8

00

A0

D3

Vbus

A4

D0

Vbus

A9

J1

CON4

1234

Vbus

A14

A15A14

J2

JUMPER

1 2

A13

R5 4K7

0

D4

Vbus

A3A11

A7

A0

MCLR

Vbus

D2RA-LED

Page 44: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

Hemos colocado un conector donde conectar el cable serie, así podremos conectar

nuestro PC con el periférico. Una vez visto el conexionado pasamos a ver el layout del circuito impreso. TOP

Figura 24: cara top

44

Page 45: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

BOTTOM

Figura 25: Cara bottom

2.3 CÓDIGO DEL PIC.

El código lo hemos desarrollado utilizando el lenguaje ANSI C. Este código lo

hemos compilando utilizando el propio compilador que nos proporciona el fabricante del PIC, Microchip.

Vamos a pasar a mostrar el código en ANSI C que se va a ejecutar en nuestro periférico, comentando los aspectos principales de este.

Funcion main: Esta es la función principal del periférico, en ella se da servicio al

driver USB, que controla el estado de los buffers de entrada/salida de datos así como a nuestra función que comprime los datos de nuestros buffers situados en la memoria RAM externa. int main(void) { InitializeSystem(); while(1) { USBTasks(); // USB Tasks DataCompressControl(); }//end while }//end main

45

Page 46: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

Funcion InitializeSystem: en ella se inicializa nuestro sistema. Se inicializa la RAM, el driver USB, se habilitan las interrupciones y se inicializa la comunicación RS-232. static void InitializeSystem(void) { ep2Bo = ep2Bi; //Para que el linker mapee esta variable. #if defined(USE_USB_BUS_SENSE_IO) tris_usb_bus_sense |= INPUT_PIN; // See io_cfg.h #endif #if defined(USE_SELF_POWER_SENSE_IO) tris_usb_bus_sense |= 0x04; #endif RAM_IO_Init(); mInitializeUSBDriver(); // See usbdrv.h UIE = 0xFF; // Enable all usb interrupts mEnableInterrupt(); InitializeUSART(); RC0 = 1U; /* toogle led on */ }//end InitializeSystem

Función high_isr: Aquí se dan servicio a las interrupciones. Tenemos una que sirve al driver USB y otra que periódicamente, activada por un timer comprueba si nos han llegado datos a través del bus USB y los carga en la memoria RAM externa.

void high_isr(void) { if (PIR2bits.USBIF) { PIR2bits.USBIF = 0; if(UCFGbits.UTEYE!=1) { USBDriverService(); // Interrupt or polling method } } if (INTCONbits.TMR0IF) { INTCONbits.TMR0IF = 0; DataLoadControl(); TMR0H = 0xD2; // Write high byte to Timer0 TMR0L = 0x1F; // Write low byte to Timer0 a++; if (a >= (word)1000) { a = 0; b++; MP_LED_Toggle(); } } }

Ahora pasamos a mostrar las diferentes funciones del algoritmo de compresión de datos. Básicamente lo que hace es recorrer el buffer de datos situado en la memoria y los va poniendo una vez comprimidos en nuestro buffer de salida.

/************************************************************************* * _LZ_StringCompare() - Return maximum length string match. *************************************************************************/

46

Page 47: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

static unsigned int _LZ_StringCompare( unsigned long str1, unsigned long str2, unsigned int minlen, unsigned int maxlen ) { unsigned int len; //for( len = minlen; (len < maxlen) && (str1[len] == str2[len]); ++ len ); for( len = minlen; (len < maxlen) && (RAM_Read_Data(str1+len) == RAM_Read_Data(str2+len)); ++ len ); return len; } /************************************************************************* * _LZ_WriteVarSize() - Write unsigned integer with variable number of * bytes depending on value. *************************************************************************/ static int _LZ_WriteVarSize( unsigned int x, unsigned long buf ) { unsigned int y; int num_bytes, i, b; /* Determine number of bytes needed to store the number x */ y = x >> 3; for( num_bytes = 5; num_bytes >= 2; -- num_bytes ) { if( y & 0xfe000000 ) break; y <<= 7; } /* Write all bytes, seven bits in each, with 8:th bit set for all */ /* but the last byte. */ for( i = num_bytes-1; i >= 0; -- i ) { b = (x >> (i*7)) & 0x0000007f; if( i > 0 ) { b |= 0x00000080; } //*buf ++ = (unsigned char) b; RAM_Write_Data((unsigned char) b, buf++); //todo revisar } /* Return number of bytes written */ return num_bytes; } /************************************************************************* * PUBLIC FUNCTIONS * *************************************************************************/ /************************************************************************* * LZ_Compress() - Compress a block of data using an LZ77 coder.

47

Page 48: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

* in - Input (uncompressed) buffer. * out - Output (compressed) buffer. This buffer must be 0.4% larger * than the input buffer, plus one byte. * insize - Number of input bytes. * The function returns the size of the compressed data. *************************************************************************/ int LZ_Compress( unsigned long IN_Adress, unsigned long OUT_Adress, unsigned int insize ) { hist_Ptr1 = (unsigned int *)histogram; /* Do we have anything to compress? */ if( insize < 1 ) { return 0; } /* Create histogram */ for( i = 0; i < 256; ++ i ) { hist_Ptr1[ i ] = 0; } for( i = 0; i < insize; ++ i ) { Aux = RAM_Read_Data(IN_Adress + i); Aux1 = hist_Ptr1[ Aux ]; Aux1++; hist_Ptr1[ Aux ] = Aux1; } /* Find the least common byte, and use it as the code marker */ marker = 0; for( i = 1; i < 256; ++ i ) { if( hist_Ptr1[ i ] < hist_Ptr1[ marker ] ) { marker = i; } } /* Remember the repetition marker for the decoder */ //out[ 0 ] = marker; RAM_Write_Data(marker,OUT_Adress); /* Start of compression */ inpos = 0; outpos = 1; /* Main compression loop */ bytesleft = insize; do { /* Determine most distant position */ if( inpos > LZ_MAX_OFFSET ) maxoffset = LZ_MAX_OFFSET; else maxoffset = inpos; /* Get pointer to current position */ //ptr1 = &in[ inpos ];

48

Page 49: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

ptr1 = IN_Adress + inpos; /* Search history window for maximum length string match */ bestlength = 3; bestoffset = 0; for( offset = 3; offset <= maxoffset; ++ offset ) { /* Get pointer to candidate string */ //ptr2 = &ptr1[ -offset ]; ptr2 = ptr1 - offset; /* Quickly determine if this is a candidate (for speed) */ //if( (ptr1[ 0 ] == ptr2[ 0 ]) && // (ptr1[ bestlength ] == ptr2[ bestlength ]) ) if ( (RAM_Read_Data(ptr1) == RAM_Read_Data(ptr2)) && (RAM_Read_Data(ptr1 + bestlength) == RAM_Read_Data(ptr2 + bestlength)) ) { /* Determine maximum length for this offset */ maxlength = (bytesleft < offset ? bytesleft : offset); /* Count maximum length match at this offset */ length = _LZ_StringCompare( ptr1, ptr2, 0, maxlength ); /* Better match than any previous match? */ if( length > bestlength ) { bestlength = length; bestoffset = offset; } } } /* Was there a good enough match? */ if( (bestlength >= 8) || ((bestlength == 4) && (bestoffset <= 0x0000007f)) || ((bestlength == 5) && (bestoffset <= 0x00003fff)) || ((bestlength == 6) && (bestoffset <= 0x001fffff)) || ((bestlength == 7) && (bestoffset <= 0x0fffffff)) ) { //out[ outpos ++ ] = (unsigned char) marker; RAM_Write_Data( marker,OUT_Adress + outpos); outpos++; //outpos += _LZ_WriteVarSize( bestlength, &out[ outpos ] ); outpos += _LZ_WriteVarSize( bestlength, OUT_Adress + outpos ); //outpos += _LZ_WriteVarSize( bestoffset, &out[ outpos ] ); outpos += _LZ_WriteVarSize( bestoffset, OUT_Adress + outpos ); inpos += bestlength; bytesleft -= bestlength; } else { /* Output single byte (or two bytes if marker byte) */ //symbol = in[ inpos ++ ]; symbol = RAM_Read_Data(IN_Adress + inpos); inpos++; //out[ outpos ++ ] = symbol; RAM_Write_Data(symbol,OUT_Adress + outpos); outpos++;

49

Page 50: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

if( symbol == marker ) { //out[ outpos ++ ] = 0; RAM_Write_Data(0,OUT_Adress + outpos); outpos++; } -- bytesleft; } } while( bytesleft > 3 ); /* Dump remaining bytes, if any */ while( inpos < insize ) { //if( in[ inpos ] == marker ) if( RAM_Read_Data(IN_Adress + inpos) == marker ) { //out[ outpos ++ ] = marker; RAM_Write_Data(marker,OUT_Adress + outpos++); //out[ outpos ++ ] = 0; RAM_Write_Data(0,OUT_Adress + outpos++); } else { //out[ outpos ++ ] = in[ inpos ]; Aux = RAM_Read_Data(IN_Adress + inpos); RAM_Write_Data(Aux,OUT_Adress + outpos); } ++ inpos; } return outpos; }

Función DataLoadControl: esta función la hemos codificado utilizando una herramienta generadora de código a través del diagrama de estados que nosotros diseñamos. Lo que se hace aquí es cargar los datos en los buffers de entrada para que luego los datos sean comprimidos. Mostramos primero el diagrama de estados y luego el código generado.

50

Page 51: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

Figura 26:

Diagrama de estados de la carga de datos

·BUFFER_1_LOAD·#entry: Ext_Ram_Addr = 0U;#during: BufferLoad();#exit: IN_Size = Ext_Ram_Addr; StartCompress = START_COMP_BUFF_1;

·BUFFER_2_LOAD·#entry: Ext_Ram_Addr= (BUFFER_1_MAX + 64U);#during: BufferLoad();#exit: IN_Size = Ext_Ram_Addr - (BUFFER_1_MAX + 60U); StartCompress = START_COMP_BUFF_2;

((Ext_Ram_Addr >= BUFFER_1_MAX) || StopLoadData)/SystemBusy();

((Ext_Ram_Addr >= BUFFER_2_MAX) ||StopLoadData)/SystemBusy();

·WAIT2·#entry: StopLoadData = 0;#during: SystemBusy();

(!ProcessingBuffer2)/SystemBusy();

·WAIT1·#entry: StopLoadData = 0;#during: SystemBusy();

(!ProcessingBuffer1)

void DataLoadControl(void) { #if defined(FSM_DEBUG) debug_transNumber = 0; #endif /* Next state analyser. */ switch(ind_DataLoadControl){ case i_BUFFER_1_LOAD: /* Entry check */ if(entryFsm.flg == 0){ entryFsm.flg = 1; /* Entry actions */ Ext_Ram_Addr = 0U; } /* State actions (Moore). */ BufferLoad(); /* Next state selection. */ if(((Ext_Ram_Addr >= BUFFER_1_MAX) || StopLoadData)){ /* Exit actions. */ IN_Size = Ext_Ram_Addr; StartCompress = START_COMP_BUFF_1; /* Transition actions (Meally). */ SystemBusy(); /* Pointing to the next state. */

51

Page 52: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

ind_DataLoadControl = i_WAIT2; #if defined(FSM_DEBUG) debug_transNumber = 1; #endif /* Reset entry flag */ entryFsm.flg = 0; } break; case i_BUFFER_2_LOAD: /* Entry check */ if(entryFsm.flg == 0){ entryFsm.flg = 1; /* Entry actions */ Ext_Ram_Addr= (BUFFER_1_MAX + 64U); } /* State actions (Moore). */ BufferLoad(); /* Next state selection. */ if(((Ext_Ram_Addr >= BUFFER_2_MAX) || StopLoadData)){ /* Exit actions. */ IN_Size = Ext_Ram_Addr - (BUFFER_1_MAX + 60U); StartCompress = START_COMP_BUFF_2; /* Transition actions (Meally). */ SystemBusy(); /* Pointing to the next state. */ ind_DataLoadControl = i_WAIT1; #if defined(FSM_DEBUG) debug_transNumber = 1; #endif /* Reset entry flag */ entryFsm.flg = 0; } break; case i_WAIT2: /* Entry check */ if(entryFsm.flg == 0){ entryFsm.flg = 1; /* Entry actions */ StopLoadData = 0; } /* State actions (Moore). */ SystemBusy(); /* Next state selection. */ if((!ProcessingBuffer2)){ /* Transition actions (Meally). */ SystemBusy(); /* Pointing to the next state. */ ind_DataLoadControl = i_BUFFER_2_LOAD; #if defined(FSM_DEBUG) debug_transNumber = 1; #endif /* Reset entry flag */ entryFsm.flg = 0; } break; case i_WAIT1: /* Entry check */ if(entryFsm.flg == 0){ entryFsm.flg = 1; /* Entry actions */

52

Page 53: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

StopLoadData = 0; } /* State actions (Moore). */ SystemBusy(); /* Next state selection. */ if((!ProcessingBuffer1)){ /* Pointing to the next state. */ ind_DataLoadControl = i_BUFFER_1_LOAD; #if defined(FSM_DEBUG) debug_transNumber = 1; #endif /* Reset entry flag */ entryFsm.flg = 0; } break; } } /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ /* Ending code proposed by the user (Start). */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ void BufferLoad(void) { Data_Read_Size = USBGenRead((byte*)&DataPacket,sizeof(DataPacket)); if (Data_Read_Size != (byte)0U) { /* Write data to external ram */ switch(DataPacket.Cmd) { case READ_VERSION: /*dataPacket._byte[1] is len */ DataPacket._byte[2] = 0; DataPacket._byte[3] = 1; counter=0x04; MP_LED_Toggle(); break; case 2: RAM_Write_Data(3,0x45); RAM_Write_Data(2,0xFF); DataPacket._byte[2] = RAM_Read_Data(0x45); DataPacket._byte[3] = RAM_Read_Data(0xFF); counter=0x04; MP_LED_Toggle(); break; case LOAD_DATA: for (i = 1; i <= (Data_Read_Size - 2); i++) { /*Le resto los commands */ RAM_Write_Data(DataPacket.Data[i],Ext_Ram_Addr); /*Loading in Ram */ Ext_Ram_Addr++; } DataPacket._byte[2] = 0; DataPacket._byte[3] = Data_Read_Size; counter=0x04; MP_LED_Toggle(); break; case STOP_LOAD_DATA: DataPacket._byte[2] = 0; DataPacket._byte[3] = Ext_Ram_Addr;

53

Page 54: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

StopLoadData = 1; counter = 0x04; MP_LED_Toggle(); break; } if (!mUSBGenTxIsBusy()) { /*Tell to the PC the response */ USBGenWrite((byte*)&DataPacket,counter); } } } void SystemBusy(void) { Data_Read_Size = USBGenRead((byte*)&DataPacket,sizeof(DataPacket)); if (Data_Read_Size != (byte)0U) { DataPacket._byte[2] = 0xFF; DataPacket._byte[3] = 0xFF; counter=0x04; /*Telling to the PC that the system is busy */ MP_LED_Toggle(); if (!mUSBGenTxIsBusy()) { /*Tell to the PC the response */ USBGenWrite((byte*)&DataPacket,counter); } } }

Funcion DataCompressControl: Esta función es un diagrama de estados también. Lo que hacemos aquí es controlar cuando el buffer esta lleno y una vez a sucedido esto llamamos al algoritmo de compresión para que comprima los datos. Una vez hecho esto, enviamos los datos vía RS-232.

Mostramos el diagrama de estados y el código generado.

54

Page 55: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

Si se pasa del tamañodel buffer vuelvo al estado inicial.

·IDLE·

·BUFFER_1_COMPRESS· CompressedDataSize = LZ_Compress((dword)0x00,OUT_ADR,IN_Size);

[1]StartCompress == START_COMP_BUFF_1/ProcessingBuffer1 = 1;

·BUFFER_2_COMPRESS· /*CompressedDataSize = LZ_Compress((dword)BUFFER1, OUT_ADR,IN_Size);*/

[2]StartCompress == START_COMP_BUFF_2/ProcessingBuffer2 = 1;

·STATE_3·#entry: StartCompress = 0U;

·STATE_1·#entry: BufferOutIndex = 0UL;#during: if (TXSTAbits.TRMT) { TXREG = RAM_Read_Data(OUT_ADR + BufferOutIndex); BufferOutIndex++; }#exit: ProcessingBuffer1 = 0U; ProcessingBuffer2 = 0U;

((BufferOutIndex == CompressedDataSize) || (BufferOutIndex > (dword)(0xAAAB)))

Figura 27: Diagrama de estados de la compresión de los datos

void DataCompressControl(void) { #if defined(FSM_DEBUG) debug_transNumber = 0; #endif /* Next state analyser. */ switch(ind_DataCompressControl){ case i_IDLE: /* Next state selection. */ if(StartCompress == START_COMP_BUFF_1){ /* [1]. */ /* Transition actions (Meally). */ ProcessingBuffer1 = 1; /* Pointing to the next state. */ ind_DataCompressControl = i_BUFFER_1_COMPRESS; #if defined(FSM_DEBUG) debug_transNumber = 1; #endif }else if(StartCompress == START_COMP_BUFF_2){ /* [2]. */ /* Transition actions (Meally). */ ProcessingBuffer2 = 1; /* Pointing to the next state. */ ind_DataCompressControl = i_BUFFER_2_COMPRESS; #if defined(FSM_DEBUG) debug_transNumber = 2; #endif

55

Page 56: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

} break; case i_BUFFER_1_COMPRESS: /* State actions (Moore). */ CompressedDataSize = LZ_Compress((dword)0x00,OUT_ADR,IN_Size); /* Next state selection. */ { /* Pointing to the next state. */ ind_DataCompressControl = i_STATE_1; #if defined(FSM_DEBUG) debug_transNumber = 1; #endif } break; case i_BUFFER_2_COMPRESS: /* State actions (Moore). */ /*CompressedDataSize = LZ_Compress((dword)BUFFER1, OUT_ADR,IN_Size);*/ /* Next state selection. */ { /* Pointing to the next state. */ ind_DataCompressControl = i_STATE_1; #if defined(FSM_DEBUG) debug_transNumber = 1; #endif } break; case i_STATE_3: /* Entry check */ if(entryFsm.flg == 0){ entryFsm.flg = 1; /* Entry actions */ StartCompress = 0U; } /* Next state selection. */ { /* Pointing to the next state. */ ind_DataCompressControl = i_IDLE; #if defined(FSM_DEBUG) debug_transNumber = 1; #endif /* Reset entry flag */ entryFsm.flg = 0; } break; case i_STATE_1: /* Entry check */ if(entryFsm.flg == 0){ entryFsm.flg = 1; /* Entry actions */ BufferOutIndex = 0UL; } /* State actions (Moore). */ if (TXSTAbits.TRMT) { TXREG = RAM_Read_Data(OUT_ADR + BufferOutIndex); BufferOutIndex++; } /* Next state selection. */ if(((BufferOutIndex == CompressedDataSize) || (BufferOutIndex > (dword)(0xAAAB)))){

56

Page 57: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

/* Exit actions. */ ProcessingBuffer1 = 0U; ProcessingBuffer2 = 0U; /* Pointing to the next state. */ ind_DataCompressControl = i_STATE_3; #if defined(FSM_DEBUG) debug_transNumber = 1; #endif /* Reset entry flag */ entryFsm.flg = 0; } break; } }

3. APENDICE

Aquí vamos a mostrar el código que hemos desarrollado para la aplicación del PC.

// Global Vars char vid_pid[]= "vid_04d8&pid_000c"; char out_pipe[]= "\\MCHP_EP1"; char in_pipe[]= "\\MCHP_EP1"; DWORD temp; HINSTANCE libHandle; HANDLE myOutPipe; HANDLE myInPipe; //--------------------------------------------------------------------------- // Prototypes void GetSummary(void); void LoadDLL(void); void GetUSBDemoFWVersion(void); void SendFile(void); long GetFileSize( FILE *f ); DWORD SendReceivePacket(BYTE *SendData, DWORD SendLength, BYTE *ReceiveData, DWORD *ReceiveLength, UINT SendDelay, UINT ReceiveDelay); void CheckInvalidHandle(void); //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { LoadDLL(); } //--------------------------------------------------------------------------- void GetSummary(void) { HANDLE tempPipe = INVALID_HANDLE_VALUE; DWORD count = 0;

57

Page 58: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

DWORD max_count; max_count = MPUSBGetDeviceCount(vid_pid); Form1->Edit1->Text = IntToStr(max_count) + " device(s) with " + vid_pid + " currently attached." ; // Note: // The total number of devices using the generic driver could be // bigger than max_count. They could have different vid & pid numbers. // This means if max_count is 2, the valid instance index do not // necessary have to be '0' and '1'. // // Below is a sample code for searching for all valid instance indexes. // MAX_NUM_MPUSB_DEV is defined in _mpusbapi.h count = 0; for(int i = 0; i < MAX_NUM_MPUSB_DEV; i++) { tempPipe = MPUSBOpen(i,vid_pid,NULL,MP_READ,0); if(tempPipe != INVALID_HANDLE_VALUE) { Form1->Edit1->Text = "Instance Index " + IntToStr(i); MPUSBClose(tempPipe); count++; } if(count == max_count) break; }//end for }//end GetSummary //--------------------------------------------------------------------------- void LoadDLL(void) { libHandle = NULL; libHandle = LoadLibrary("mpusbapi"); if(libHandle == NULL) { Form1->Edit1->Text = "Error loading mpusbapi.dll"; } else { MPUSBGetDLLVersion=(DWORD(*)(void))\ GetProcAddress(libHandle,"_MPUSBGetDLLVersion"); MPUSBGetDeviceCount=(DWORD(*)(PCHAR))\ GetProcAddress(libHandle,"_MPUSBGetDeviceCount"); MPUSBOpen=(HANDLE(*)(DWORD,PCHAR,PCHAR,DWORD,DWORD))\ GetProcAddress(libHandle,"_MPUSBOpen"); MPUSBWrite=(DWORD(*)(HANDLE,PVOID,DWORD,PDWORD,DWORD))\ GetProcAddress(libHandle,"_MPUSBWrite"); MPUSBRead=(DWORD(*)(HANDLE,PVOID,DWORD,PDWORD,DWORD))\ GetProcAddress(libHandle,"_MPUSBRead"); MPUSBReadInt=(DWORD(*)(HANDLE,PVOID,DWORD,PDWORD,DWORD))\ GetProcAddress(libHandle,"_MPUSBReadInt"); MPUSBClose=(BOOL(*)(HANDLE))GetProcAddress(libHandle,"_MPUSBClose");

58

Page 59: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

if((MPUSBGetDeviceCount == NULL) || (MPUSBOpen == NULL) || (MPUSBWrite == NULL) || (MPUSBRead == NULL) || (MPUSBClose == NULL) || (MPUSBGetDLLVersion == NULL) || (MPUSBReadInt == NULL)) Form1->Edit1->Text = "GetProcAddress Error"; }//end if else }//end LoadDLL //--------------------------------------------------------------------------- void GetUSBDemoFWVersion(void) { // First we need to open data pipes... DWORD selection; fflush(stdin); //printf("Enter a valid instance index to open a USB connection: "); //scanf("%d",&selection); selection = 0; myOutPipe = MPUSBOpen(selection,vid_pid,out_pipe,MP_WRITE,0); myInPipe = MPUSBOpen(selection,vid_pid,out_pipe,MP_READ,0); if(myOutPipe == INVALID_HANDLE_VALUE || myInPipe == INVALID_HANDLE_VALUE) { Form1->Edit1->Text = "Failed to open data pipes."; return; }//end if // The default demo firmware application has a defined application // level protocol. // To read the firmware version, the host must send the READ_VERSION // command which is defined as 0x00, follows by the length of the // expected result, in this case is 2 bytes, major version, and minor // version. // i.e. <READ_VERSION><0x02> // // The response packet from the board has the following format: // <READ_VERSION><0x02><MINOR_VER><MAJOR_VER> // The receive buffer size must be equal to or larger than the maximum // endpoint size it is communicating with. In this case, 64 bytes. BYTE send_buf[64],receive_buf[64]; DWORD RecvLength=4; #define READ_VERSION 0 send_buf[0] = READ_VERSION; // Command send_buf[1] = 0x02; // Expected length of the result if(SendReceivePacket(send_buf,2,receive_buf,&RecvLength,1000,1000) == 1) { if(RecvLength == 4 && receive_buf[0] == READ_VERSION && receive_buf[1] == 0x02) { Form1->Edit1->Text = "USB PFC Mperiago Version " + IntToStr(receive_buf[3]) + "." + IntToStr(receive_buf[2]);

59

Page 60: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

} } else Form1->Edit1->Text = "USB Operation Failed"; // Let's close the data pipes since we have nothing left to do.. MPUSBClose(myOutPipe); MPUSBClose(myInPipe); myOutPipe = myInPipe = INVALID_HANDLE_VALUE; }//end GetUSBDemoFWVersion void SendFile(void) { #define LOAD_DATA 0x10 #define PACKET_SIZE (BYTE)2 DWORD selection; fflush(stdin); BYTE send_buf[64],receive_buf[64],i,* in,Transmited_OK=1,string[64],FailCount=0,FailCount2=0; DWORD RecvLength=4,buff_index=1,delay; FILE *f; unsigned int insize,bufsize; /* Abrir y cargar el fichero en memoria */ f = fopen( Form1->Edit2->Text.c_str(), "r" ); if( !f ) { Form1->Edit1->Text = "no se puede abrir el fichero!"; return; } insize = GetFileSize( f ); if( insize < 1 ) { Form1->Edit1->Text = "fichero vacio!"; fclose( f ); return; } bufsize = (insize*104+50)/100 + 384; in = (unsigned char *) malloc( insize + 2*bufsize ); if( !in ) { Form1->Edit1->Text = "sin memoria!"; fclose( f ); return; } fread( in, 1, insize, f ); fclose( f ); //printf("Enter a valid instance index to open a USB connection: "); //scanf("%d",&selection); selection = 0; myOutPipe = MPUSBOpen(selection,vid_pid,out_pipe,MP_WRITE,0); myInPipe = MPUSBOpen(selection,vid_pid,out_pipe,MP_READ,0); if(myOutPipe == INVALID_HANDLE_VALUE || myInPipe == INVALID_HANDLE_VALUE) { Form1->Edit1->Text = "Failed to open data pipes."; return; }//end if

60

Page 61: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

SendMessage(Form1->ProgressBar1->Handle,PBM_SETRANGE, 0, MAKELPARAM(0, insize)); Form1->ProgressBar1->Position = 0; while ((buff_index <= insize) && (FailCount < 10)) { /* Se carga el siguiente paquete de datos */ if (Transmited_OK) { for (i=0; i<PACKET_SIZE; i++) { send_buf[i] = 0; } send_buf[0] = LOAD_DATA; send_buf[1] = 0x02; for (i=2;(i<PACKET_SIZE && (buff_index <= insize));i++) { send_buf[i] = in[buff_index]; // Le paso los paqutes al pic buff_index++; } } if (SendReceivePacket(send_buf,i,receive_buf,&RecvLength,3000,3000)==1) { //Le envio el paquete y espero respuesta if(RecvLength == 4 && receive_buf[0] == LOAD_DATA && receive_buf[1] == 0x02) { Form1->Edit1->Text = "Positive Reponse" + IntToStr(receive_buf[3]); if ((receive_buf[3] == 0xFF) && (receive_buf[2]==0xFF)) { Transmited_OK = 0; FailCount = 0; } else { Transmited_OK = 1; } Form1->ProgressBar1->StepBy(i-1); } else { Transmited_OK = 0; FailCount++; FailCount2++; if (FailCount == 10) Form1->Edit1->Text = "No response from device"; } } else { Form1->Edit1->Text = "USB Operation Failed"; FailCount++; } } #define STOP_LOAD_DATA 0x20 send_buf[0] = STOP_LOAD_DATA; send_buf[1] = 0x02; SendReceivePacket(send_buf,2,receive_buf,&RecvLength,3000,3000); //Le envio el paquete y espero respuesta if(RecvLength == 4 && receive_buf[0] == STOP_LOAD_DATA && receive_buf[1] == 0x02)

61

Page 62: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

{ Form1->Edit1->Text = "Transaction finished. Data Loaded with " + IntToStr(FailCount2) + " Errors"; } // Let's close the data pipes since we have nothing left to do.. MPUSBClose(myOutPipe); MPUSBClose(myInPipe); myOutPipe = myInPipe = INVALID_HANDLE_VALUE; } long GetFileSize( FILE *f ) { long pos, size; pos = ftell( f ); fseek( f, 0, SEEK_END ); size = ftell( f ); fseek( f, pos, SEEK_SET ); return size; } //--------------------------------------------------------------------------- ///////////////////////////////////////////////////////////////////////////// // // A typical application would send a command to the target device and expect // a response. // SendReceivePacket is a wrapper function that facilitates the // send command / read response paradigm // // SendData - pointer to data to be sent // SendLength - length of data to be sent // ReceiveData - Points to the buffer that receives the data read from the call // ReceiveLength - Points to the number of bytes read // SendDelay - time-out value for MPUSBWrite operation in milliseconds // ReceiveDelay - time-out value for MPUSBRead operation in milliseconds // DWORD SendReceivePacket(BYTE *SendData, DWORD SendLength, BYTE *ReceiveData, DWORD *ReceiveLength, UINT SendDelay, UINT ReceiveDelay) { DWORD SentDataLength; DWORD ExpectedReceiveLength = *ReceiveLength; if(myOutPipe != INVALID_HANDLE_VALUE && myInPipe != INVALID_HANDLE_VALUE) { if(MPUSBWrite(myOutPipe,SendData,SendLength,&SentDataLength,SendDelay)) { if(MPUSBRead(myInPipe,ReceiveData, ExpectedReceiveLength, ReceiveLength,ReceiveDelay))

62

Page 63: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

{ if(*ReceiveLength == ExpectedReceiveLength) { return 1; // Success! } else if(*ReceiveLength < ExpectedReceiveLength) { return 2; // Partially failed, incorrect receive length }//end if else } else CheckInvalidHandle(); } else CheckInvalidHandle(); }//end if return 0; // Operation Failed }//end SendReceivePacket //--------------------------------------------------------------------------- void CheckInvalidHandle(void) { if(GetLastError() == ERROR_INVALID_HANDLE) { // Most likely cause of the error is the board was disconnected. MPUSBClose(myOutPipe); MPUSBClose(myInPipe); myOutPipe = myInPipe = INVALID_HANDLE_VALUE; }//end if else Form1->Edit1->Text = "Error Code: " + GetLastError(); }//end CheckInvalidHandle void __fastcall TForm1::Button1Click(TObject *Sender) { temp = MPUSBGetDLLVersion(); Edit1->Text = "MPUSBAPI Version: " + IntToStr(HIWORD(temp)) + "." + IntToStr(LOWORD(temp)); } void __fastcall TForm1::Button4Click(TObject *Sender) { OpenDialog1->Filter = "Data Files (*.dat)|*.DAT"; OpenDialog1->Execute(); Edit2->Text = OpenDialog1->FileName; SendFile(); } //--------------------------------------------------------------------------- void __fastcall TForm1::Button3Click(TObject *Sender) { GetUSBDemoFWVersion(); } //---------------------------------------------------------------------------

63

Page 64: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

void __fastcall TForm1::Button2Click(TObject *Sender) { GetSummary(); } //--------------------------------------------------------------------------- void __fastcall TForm1::Exit1Click(TObject *Sender) { Form1->Close(); } //--------------------------------------------------------------------------- void __fastcall TForm1::Button5Click(TObject *Sender) { fflush(stdin); DWORD selection; //printf("Enter a valid instance index to open a USB connection: "); //scanf("%d",&selection); selection = 0; myOutPipe = MPUSBOpen(selection,vid_pid,out_pipe,MP_WRITE,0); myInPipe = MPUSBOpen(selection,vid_pid,out_pipe,MP_READ,0); if(myOutPipe == INVALID_HANDLE_VALUE || myInPipe == INVALID_HANDLE_VALUE) { Form1->Edit1->Text = "Failed to open data pipes."; return; }//end if BYTE send_buf[64],receive_buf[64]; DWORD RecvLength=4; #define TEST_RAM 2 send_buf[0] = TEST_RAM; // Command send_buf[1] = 0x02; // Expected length of the result if(SendReceivePacket(send_buf,2,receive_buf,&RecvLength,1000,1000) == 1) { if(RecvLength == 4 && receive_buf[0] == TEST_RAM && receive_buf[1] == 0x02) { if ((IntToStr(receive_buf[3]) == 2) && (IntToStr(receive_buf[2])== 3)) { Form1->Edit1->Text = "Ram OK "; } else { Form1->Edit1->Text = "Ram Not OK "; } } } else

64

Page 65: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

Form1->Edit1->Text = "USB Operation Failed"; // Let's close the data pipes since we have nothing left to do. MPUSBClose(myOutPipe); MPUSBClose(myInPipe); myOutPipe = myInPipe = INVALID_HANDLE_VALUE; } //---------------------------------------------------------------------------

Ahora vamos a mostrar el código del driver USB. Fichero usbgen.c:

void USBGenInitEP(void) { usbgen_rx_len = 0; USBGEN_UEP = EP_OUT_IN|HSHK_EN; // Enable 2 data pipes /* * Do not have to init Cnt of IN pipes here. * Reason: Number of bytes to send to the host * varies from one transaction to * another. Cnt should equal the exact * number of bytes to transmit for * a given IN transaction. * This number of bytes will only * be known right before the data is * sent. */ USBGEN_BD_OUT.Cnt = sizeof(usbgen_out); // Set buffer size USBGEN_BD_OUT.ADR = (byte*)&usbgen_out; // Set buffer address USBGEN_BD_OUT.Stat._byte = _USIE|_DAT0|_DTSEN;// Set status USBGEN_BD_IN.ADR = (byte*)&usbgen_in; // Set buffer address USBGEN_BD_IN.Stat._byte = _UCPU|_DAT1; // Set buffer status }//end USBGenInitEP void USBGenWrite(byte *buffer, byte len) { byte i; /* * Value of len should be equal to or smaller than USBGEN_EP_SIZE. * This check forces the value of len to meet the precondition. */ if(len > USBGEN_EP_SIZE) len = USBGEN_EP_SIZE; /* * Copy data from user's buffer to dual-ram buffer */ for (i = 0; i < len; i++) usbgen_in[i] = buffer[i]; USBGEN_BD_IN.Cnt = len; mUSBBufferReady(USBGEN_BD_IN);

65

Page 66: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

}//end USBGenWrite byte USBGenRead(byte *buffer, byte len) { usbgen_rx_len = 0; if(!mUSBGenRxIsBusy()) { /* * Adjust the expected number of bytes to equal * the actual number of bytes received. */ if(len > USBGEN_BD_OUT.Cnt) len = USBGEN_BD_OUT.Cnt; /* * Copy data from dual-ram buffer to user's buffer */ for(usbgen_rx_len = 0; usbgen_rx_len < len; usbgen_rx_len++) buffer[usbgen_rx_len] = usbgen_out[usbgen_rx_len]; /* * Prepare dual-ram buffer for next OUT transaction */ USBGEN_BD_OUT.Cnt = sizeof(usbgen_out); mUSBBufferReady(USBGEN_BD_OUT); }//end if return usbgen_rx_len; }//end USBGenRead

Fichero usb9.c:

void USBCheckStdRequest(void) { if(SetupPkt.RequestType != STANDARD) return; switch(SetupPkt.bRequest) { case SET_ADR: ctrl_trf_session_owner = MUID_USB9; usb_device_state = ADR_PENDING_STATE; // Update state only /* See USBCtrlTrfInHandler() in usbctrltrf.c for the next step */ break; case GET_DSC: USBStdGetDscHandler(); break; case SET_CFG: USBStdSetCfgHandler(); break; case GET_CFG: ctrl_trf_session_owner = MUID_USB9; pSrc.bRam = (byte*)&usb_active_cfg; // Set Source usb_stat.ctrl_trf_mem = _RAM; // Set memory type LSB(wCount) = 1; // Set data count break; case GET_STATUS:

66

Page 67: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

USBStdGetStatusHandler(); break; case CLR_FEATURE: case SET_FEATURE: USBStdFeatureReqHandler(); break; case GET_INTF: ctrl_trf_session_owner = MUID_USB9; pSrc.bRam = (byte*)&usb_alt_intf+SetupPkt.bIntfID; // Set source usb_stat.ctrl_trf_mem = _RAM; // Set memory type LSB(wCount) = 1; // Set data count break; case SET_INTF: ctrl_trf_session_owner = MUID_USB9; usb_alt_intf[SetupPkt.bIntfID] = SetupPkt.bAltID; break; case SET_DSC: case SYNCH_FRAME: default: break; }//end switch }//end USBCheckStdRequest void USBStdGetDscHandler(void) { if(SetupPkt.bmRequestType == 0x80) { switch(SetupPkt.bDscType) { case DSC_DEV: ctrl_trf_session_owner = MUID_USB9; pSrc.bRom = (rom byte*)&device_dsc; wCount._word = sizeof(device_dsc); // Set data count break; case DSC_CFG: ctrl_trf_session_owner = MUID_USB9; pSrc.bRom = *(USB_CD_Ptr+SetupPkt.bDscIndex); wCount._word = *(pSrc.wRom+1); // Set data count break; case DSC_STR: ctrl_trf_session_owner = MUID_USB9; pSrc.bRom = *(USB_SD_Ptr+SetupPkt.bDscIndex); wCount._word = *pSrc.bRom; // Set data count break; }//end switch usb_stat.ctrl_trf_mem = _ROM; // Set memory type }//end if }//end USBStdGetDscHandler void USBStdSetCfgHandler(void) { ctrl_trf_session_owner = MUID_USB9; mDisableEP1to15(); // See usbdrv.h

67

Page 68: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

ClearArray((byte*)&usb_alt_intf,MAX_NUM_INT); usb_active_cfg = SetupPkt.bCfgValue; if(SetupPkt.bCfgValue == 0) usb_device_state = ADDRESS_STATE; else { usb_device_state = CONFIGURED_STATE; /* Modifiable Section */ #if defined(USB_USE_GEN) // See autofiles\usbcfg.h USBGenInitEP(); #endif /* End modifiable section */ }//end if(SetupPkt.bcfgValue == 0) }//end USBStdSetCfgHandler void USBStdGetStatusHandler(void) { CtrlTrfData._byte0 = 0; // Initialize content CtrlTrfData._byte1 = 0; switch(SetupPkt.Recipient) { case RCPT_DEV: ctrl_trf_session_owner = MUID_USB9; /* * _byte0: bit0: Self-Powered Status [0] Bus-Powered [1] Self-Powered * bit1: RemoteWakeup [0] Disabled [1] Enabled */ if(self_power == 1) // self_power defined in io_cfg.h CtrlTrfData._byte0|=0b000000001; // Set bit0 if(usb_stat.RemoteWakeup == 1) // usb_stat defined in usbmmap.c CtrlTrfData._byte0|=0b00000010; // Set bit1 break; case RCPT_INTF: ctrl_trf_session_owner = MUID_USB9; // No data to update break; case RCPT_EP: ctrl_trf_session_owner = MUID_USB9; /* * _byte0: bit0: Halt Status [0] Not Halted [1] Halted */ pDst.bRam = (byte*)&ep0Bo+(SetupPkt.EPNum*8)+(SetupPkt.EPDir*4); if(*pDst.bRam & _BSTALL) // Use _BSTALL as a bit mask CtrlTrfData._byte0=0x01;// Set bit0 break; }//end switch if(ctrl_trf_session_owner == MUID_USB9) { pSrc.bRam = (byte*)&CtrlTrfData; // Set Source usb_stat.ctrl_trf_mem = _RAM; // Set memory type

68

Page 69: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

LSB(wCount) = 2; // Set data count }//end if(...) }//end USBStdGetStatusHandler void USBStdFeatureReqHandler(void) { if((SetupPkt.bFeature == DEVICE_REMOTE_WAKEUP)&& (SetupPkt.Recipient == RCPT_DEV)) { ctrl_trf_session_owner = MUID_USB9; if(SetupPkt.bRequest == SET_FEATURE) usb_stat.RemoteWakeup = 1; else usb_stat.RemoteWakeup = 0; }//end if if((SetupPkt.bFeature == ENDPOINT_HALT)&& (SetupPkt.Recipient == RCPT_EP)&& (SetupPkt.EPNum != 0)) { ctrl_trf_session_owner = MUID_USB9; /* Must do address calculation here */ pDst.bRam = (byte*)&ep0Bo+(SetupPkt.EPNum*8)+(SetupPkt.EPDir*4); if(SetupPkt.bRequest == SET_FEATURE) *pDst.bRam = _USIE|_BSTALL; else { if(SetupPkt.EPDir == 1) // IN *pDst.bRam = _UCPU; else *pDst.bRam = _USIE|_DAT0|_DTSEN; }//end if }//end if }//end USBStdFeatureReqHandler

Fichero usbctrltrf.c:

void USBCtrlEPService(void) { if(USTAT == EP00_OUT) { if(ep0Bo.Stat.PID == SETUP_TOKEN) // EP0 SETUP USBCtrlTrfSetupHandler(); else // EP0 OUT USBCtrlTrfOutHandler(); } else if(USTAT == EP00_IN) // EP0 IN USBCtrlTrfInHandler(); }//end USBCtrlEPService void USBCtrlTrfSetupHandler(void) { byte i; /* Stage 1 */ ctrl_trf_state = WAIT_SETUP; ctrl_trf_session_owner = MUID_NULL; // Set owner to NULL wCount._word = 0;

69

Page 70: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

/* Stage 2 */ USBCheckStdRequest(); // See system\usb9\usb9.c /* Modifiable Section */ // Insert other USB Device Class Request Handlers here /* End Modifiable Section */ /* Stage 3 */ USBCtrlEPServiceComplete(); }//end USBCtrlTrfSetupHandler void USBCtrlTrfOutHandler(void) { if(ctrl_trf_state == CTRL_TRF_RX) { USBCtrlTrfRxService(); /* * Don't have to worry about overwriting _KEEP bit * because if _KEEP was set, TRNIF would not have been * generated in the first place. */ if(ep0Bo.Stat.DTS == 0) ep0Bo.Stat._byte = _USIE|_DAT1|_DTSEN; else ep0Bo.Stat._byte = _USIE|_DAT0|_DTSEN; } else // CTRL_TRF_TX USBPrepareForNextSetupTrf(); }//end USBCtrlTrfOutHandler void USBCtrlTrfInHandler(void) { mUSBCheckAdrPendingState(); // Must check if in ADR_PENDING_STATE if(ctrl_trf_state == CTRL_TRF_TX) { USBCtrlTrfTxService(); if(ep0Bi.Stat.DTS == 0) ep0Bi.Stat._byte = _USIE|_DAT1|_DTSEN; else ep0Bi.Stat._byte = _USIE|_DAT0|_DTSEN; } else // CTRL_TRF_RX USBPrepareForNextSetupTrf(); }//end USBCtrlTrfInHandler void USBCtrlTrfTxService(void) { WORD byte_to_send; /* * First, have to figure out how many byte of data to send. */ if(wCount._word < EP0_BUFF_SIZE)

70

Page 71: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

byte_to_send._word = wCount._word; else byte_to_send._word = EP0_BUFF_SIZE; /* * Next, load the number of bytes to send to BC9..0 in buffer descriptor */ ep0Bi.Stat.BC9 = 0; ep0Bi.Stat.BC8 = 0; ep0Bi.Stat._byte |= MSB(byte_to_send); ep0Bi.Cnt = LSB(byte_to_send); /* * Subtract the number of bytes just about to be sent from the total. */ wCount._word = wCount._word - byte_to_send._word; pDst.bRam = (byte*)&CtrlTrfData; // Set destination pointer if(usb_stat.ctrl_trf_mem == _ROM) // Determine type of memory source { while(byte_to_send._word) { *pDst.bRam = *pSrc.bRom; pDst.bRam++; pSrc.bRom++; byte_to_send._word--; }//end while(byte_to_send._word) } else // RAM { while(byte_to_send._word) { *pDst.bRam = *pSrc.bRam; pDst.bRam++; pSrc.bRam++; byte_to_send._word--; }//end while(byte_to_send._word) }//end if(usb_stat.ctrl_trf_mem == _ROM) }//end USBCtrlTrfTxService void USBCtrlTrfRxService(void) { WORD byte_to_read; MSB(byte_to_read) = 0x03 & ep0Bo.Stat._byte; // Filter out last 2 bits LSB(byte_to_read) = ep0Bo.Cnt; /* * Accumulate total number of bytes read */ wCount._word = wCount._word + byte_to_read._word; pSrc.bRam = (byte*)&CtrlTrfData; while(byte_to_read._word) {

71

Page 72: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

*pDst.bRam = *pSrc.bRam; pDst.bRam++; pSrc.bRam++; byte_to_read._word--; }//end while(byte_to_read._word) }//end USBCtrlTrfRxService void USBCtrlEPServiceComplete(void) { if(ctrl_trf_session_owner == MUID_NULL) { /* * If no one knows how to service this request then stall. * Must also prepare EP0 to receive the next SETUP transaction. */ ep0Bo.Cnt = EP0_BUFF_SIZE; ep0Bo.ADR = (byte*)&SetupPkt; ep0Bo.Stat._byte = _USIE|_BSTALL; ep0Bi.Stat._byte = _USIE|_BSTALL; } else // A module has claimed ownership of the control transfer session. { if(SetupPkt.DataDir == DEV_TO_HOST) { if(SetupPkt.wLength < wCount._word) wCount._word = SetupPkt.wLength; USBCtrlTrfTxService(); ctrl_trf_state = CTRL_TRF_TX; /* * Control Read: * <SETUP[0]><IN[1]><IN[0]>...<OUT[1]> | <SETUP[0]> * 1. Prepare OUT EP to respond to early termination * * NOTE: * If something went wrong during the control transfer, * the last status stage may not be sent by the host. * When this happens, two different things could happen * depending on the host. * a) The host could send out a RESET. * b) The host could send out a new SETUP transaction * without sending a RESET first. * To properly handle case (b), the OUT EP must be setup * to receive either a zero length OUT transaction, or a * new SETUP transaction. * * Since the SETUP transaction requires the DTS bit to be * DAT0 while the zero length OUT status requires the DTS * bit to be DAT1, the DTS bit check by the hardware should * be disabled. This way the SIE could accept either of * the two transactions. * * Furthermore, the Cnt byte should be set to prepare for * the SETUP data (8-byte or more), and the buffer address * should be pointed to SetupPkt. */ ep0Bo.Cnt = EP0_BUFF_SIZE; ep0Bo.ADR = (byte*)&SetupPkt; ep0Bo.Stat._byte = _USIE; // Note: DTSEN is 0!

72

Page 73: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

/* * 2. Prepare IN EP to transfer data, Cnt should have * been initialized by responsible request owner. */ ep0Bi.ADR = (byte*)&CtrlTrfData; ep0Bi.Stat._byte = _USIE|_DAT1|_DTSEN; } else // (SetupPkt.DataDir == HOST_TO_DEV) { ctrl_trf_state = CTRL_TRF_RX; /* * Control Write: * <SETUP[0]><OUT[1]><OUT[0]>...<IN[1]> | <SETUP[0]> * * 1. Prepare IN EP to respond to early termination * * This is the same as a Zero Length Packet Response * for control transfer without a data stage */ ep0Bi.Cnt = 0; ep0Bi.Stat._byte = _USIE|_DAT1|_DTSEN; /* * 2. Prepare OUT EP to receive data. */ ep0Bo.Cnt = EP0_BUFF_SIZE; ep0Bo.ADR = (byte*)&CtrlTrfData; ep0Bo.Stat._byte = _USIE|_DAT1|_DTSEN; }//end if(SetupPkt.DataDir == DEV_TO_HOST) }//end if(ctrl_trf_session_owner == MUID_NULL) /* * PKTDIS bit is set when a Setup Transaction is received. * Clear to resume packet processing. */ UCONbits.PKTDIS = 0; }//end USBCtrlEPServiceComplete void USBPrepareForNextSetupTrf(void) { ctrl_trf_state = WAIT_SETUP; // See usbctrltrf.h ep0Bo.Cnt = EP0_BUFF_SIZE; // Defined in usbcfg.h ep0Bo.ADR = (byte*)&SetupPkt; ep0Bo.Stat._byte = _USIE|_DAT0|_DTSEN; // EP0 buff dsc init, see usbmmap.h ep0Bi.Stat._byte = _UCPU; // EP0 IN buffer initialization }//end USBPrepareForNextSetupTrf

Fichero usbdrv.c:

void USBCheckBusStatus(void) { #define USB_BUS_ATTACHED 1 #define USB_BUS_DETACHED 0 if(usb_bus_sense == USB_BUS_ATTACHED) // Is USB bus attached? { if(UCONbits.USBEN == 0) // Is the module off?

73

Page 74: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

USBModuleEnable(); // Is off, enable it } else { if(UCONbits.USBEN == 1) // Is the module on? USBModuleDisable(); // Is on, disable it }//end if(usb_bus_sense...) /* * After enabling the USB module, it takes some time for the voltage * on the D+ or D- line to rise high enough to get out of the SE0 condition. * The USB Reset interrupt should not be unmasked until the SE0 condition is * cleared. This helps preventing the firmware from misinterpreting this * unique event as a USB bus reset from the USB host. */ if(usb_device_state == ATTACHED_STATE) { if(!UCONbits.SE0) { UIR = 0; // Clear all USB interrupts UIE = 0; // Mask all USB interrupts UIEbits.URSTIE = 1; // Unmask RESET interrupt UIEbits.IDLEIE = 1; // Unmask IDLE interrupt usb_device_state = POWERED_STATE; }//end if // else wait until SE0 is cleared }//end if(usb_device_state == ATTACHED_STATE) }//end USBCheckBusStatus void USBModuleEnable(void) { UCON = 0; UIE = 0; // Mask all USB interrupts UCONbits.USBEN = 1; // Enable module & attach to bus usb_device_state = ATTACHED_STATE; // Defined in usbmmap.c & .h }//end USBModuleEnable void USBModuleDisable(void) { UCON = 0; // Disable module & detach from bus UIE = 0; // Mask all USB interrupts usb_device_state = DETACHED_STATE; // Defined in usbmmap.c & .h }//end USBModuleDisable void USBSoftDetach(void) { USBModuleDisable(); }//end USBSoftDetach void USBDriverService(void) {

74

Page 75: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

/* * Pointless to continue servicing if USB cable is not even attached. */ if(usb_device_state == DETACHED_STATE) return; /* * Task A: Service USB Activity Interrupt */ if(UIRbits.ACTVIF && UIEbits.ACTVIE) USBWakeFromSuspend(); /* * Pointless to continue servicing if the device is in suspend mode. */ if(UCONbits.SUSPND==1) return; /* * Task B: Service USB Bus Reset Interrupt. * When bus reset is received during suspend, ACTVIF will be set first, * once the UCONbits.SUSPND is clear, then the URSTIF bit will be asserted. * This is why URSTIF is checked after ACTVIF. */ if(UIRbits.URSTIF && UIEbits.URSTIE) USBProtocolResetHandler(); /* * Task C: Service other USB interrupts */ if(UIRbits.IDLEIF && UIEbits.IDLEIE) USBSuspend(); if(UIRbits.SOFIF && UIEbits.SOFIE) USB_SOF_Handler(); if(UIRbits.STALLIF && UIEbits.STALLIE) USBStallHandler(); if(UIRbits.UERRIF && UIEbits.UERRIE) USBErrorHandler(); /* * Pointless to continue servicing if the host has not sent a bus reset. * Once bus reset is received, the device transitions into the DEFAULT * state and is ready for communication. */ if(usb_device_state < DEFAULT_STATE) return; /* * Task D: Servicing USB Transaction Complete Interrupt */ if(UIRbits.TRNIF && UIEbits.TRNIE) { /* * USBCtrlEPService only services transactions over EP0. * It ignores all other EP transactions. */ USBCtrlEPService(); /* * Other EP can be serviced later by responsible device class firmware. * Each device driver knows when an OUT or IN transaction is ready by * checking the buffer ownership bit. * An OUT EP should always be owned by SIE until the data is

75

Page 76: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

ready. * An IN EP should always be owned by CPU until the data is ready. * * Because of this logic, it is not necessary to save the USTAT value * of non-EP0 transactions. */ UIRbits.TRNIF = 0; }//end if(UIRbits.TRNIF && UIEbits.TRNIE) }//end USBDriverService void USBSuspend(void) { /* * NOTE: Do not clear UIRbits.ACTVIF here! * Reason: * ACTVIF is only generated once an IDLEIF has been generated. * This is a 1:1 ratio interrupt generation. * For every IDLEIF, there will be only one ACTVIF regardless of * the number of subsequent bus transitions. * * If the ACTIF is cleared here, a problem could occur when: * [ IDLE ][bus activity -> * <--- 3 ms -----> ^ * ^ ACTVIF=1 * IDLEIF=1 * # # # # (#=Program polling flags) * ^ * This polling loop will see both * IDLEIF=1 and ACTVIF=1. * However, the program services IDLEIF first * because ACTIVIE=0. * If this routine clears the only ACTIVIF, * then it can never get out of the suspend * mode. */ UIEbits.ACTVIE = 1; // Enable bus activity interrupt UIRbits.IDLEIF = 0; UCONbits.SUSPND = 1; // Put USB module in power conserve // mode, SIE clock inactive /* * At this point the PIC can go into sleep,idle, or * switch to a slower clock, etc. */ /* Modifiable Section */ /* End Modifiable Section */ }//end USBSuspend void USBWakeFromSuspend(void) { /*

76

Page 77: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

* If using clock switching, this is the place to restore the * original clock frequency. */ UCONbits.SUSPND = 0; UIEbits.ACTVIE = 0; UIRbits.ACTVIF = 0; }//end USBWakeFromSuspend void USBRemoteWakeup(void) { static word delay_count; if(usb_stat.RemoteWakeup == 1) // Check if RemoteWakeup function { // has been enabled by the host. USBWakeFromSuspend(); // Unsuspend USB modue UCONbits.RESUME = 1; // Start RESUME signaling /* Modifiable Section */ delay_count = 1800U; // Set RESUME line for 1-13 ms do { delay_count--; }while(delay_count); /* End Modifiable Section */ UCONbits.RESUME = 0; }//endif }//end USBRemoteWakeup void USB_SOF_Handler(void) { /* Callback routine here */ UIRbits.SOFIF = 0; }//end USB_SOF_Handler void USBStallHandler(void) { /* * Does not really have to do anything here, * even for the control endpoint. * All BDs of Endpoint 0 are owned by SIE right now, * but once a Setup Transaction is received, the ownership * for EP0_OUT will be returned to CPU. * When the Setup Transaction is serviced, the ownership * for EP0_IN will then be forced back to CPU by firmware. * * NOTE: Above description is not quite true at this point. * It seems the SIE never returns the UOWN bit to CPU, * and a TRNIF is never generated upon successful * reception of a SETUP transaction. * Firmware work-around is implemented below. */

77

Page 78: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

if(UEP0bits.EPSTALL == 1) { USBPrepareForNextSetupTrf(); // Firmware Work-Around UEP0bits.EPSTALL = 0; } UIRbits.STALLIF = 0; }//end USBStallHandler void USBErrorHandler(void) { UIRbits.UERRIF = 0; }//end USBErrorHandler void USBProtocolResetHandler(void) { UEIR = 0; // Clear all USB error flags UIR = 0; // Clears all USB interrupts UEIE = 0b10011111; // Unmask all USB error interrupts UIE = 0b01111011; // Enable all interrupts except ACTVIE UADDR = 0x00; // Reset to default address mDisableEP1to15(); // Reset all non-EP0 UEPn registers UEP0 = EP_CTRL|HSHK_EN; // Init EP0 as a Ctrl EP, see usbdrv.h while(UIRbits.TRNIF == 1) // Flush any pending transactions UIRbits.TRNIF = 0; UCONbits.PKTDIS = 0; // Make sure packet processing is enabled USBPrepareForNextSetupTrf(); // Declared in usbctrltrf.c usb_stat.RemoteWakeup = 0; // Default status flag to disable usb_active_cfg = 0; // Clear active configuration usb_device_state = DEFAULT_STATE; }//end USBProtocolResetHandler /* Auxiliary Function */ void ClearArray(byte* startAdr,byte count) { *startAdr; while(count) { _asm clrf POSTINC0,0 _endasm count--; }//end while }//end ClearArray

Fichero usbdsc.c:

#pragma romdata /* Device Descriptor */ rom USB_DEV_DSC device_dsc= {

78

Page 79: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

sizeof(USB_DEV_DSC), // Size of this descriptor in bytes DSC_DEV, // DEVICE descriptor type 0x0200, // USB Spec Release Number in BCD format 0x00, // Class Code 0x00, // Subclass code 0x00, // Protocol code EP0_BUFF_SIZE, // Max packet size for EP0, see usbcfg.h 0x04D8, // Vendor ID 0x000C, // Product ID: PICDEM FS USB (DEMO Mode) 0x0000, // Device release number in BCD format 0x01, // Manufacturer string index 0x02, // Product string index 0x00, // Device serial number string index 0x01 // Number of possible configurations }; /* Configuration 1 Descriptor */ CFG01= { /* Configuration Descriptor */ sizeof(USB_CFG_DSC), // Size of this descriptor in bytes DSC_CFG, // CONFIGURATION descriptor type sizeof(cfg01), // Total length of data for this cfg 1, // Number of interfaces in this cfg 1, // Index value of this configuration 0, // Configuration string index _DEFAULT, // Attributes, see usbdefs_std_dsc.h 50, // Max power consumption (2X mA) /* Interface Descriptor */ sizeof(USB_INTF_DSC), // Size of this descriptor in bytes DSC_INTF, // INTERFACE descriptor type 0, // Interface Number 0, // Alternate Setting Number 2, // Number of endpoints in this intf 0x00, // Class code 0x00, // Subclass code 0x00, // Protocol code 0, // Interface string index /* Endpoint Descriptors */ sizeof(USB_EP_DSC),DSC_EP,_EP01_OUT,_INT,USBGEN_EP_SIZE,32, sizeof(USB_EP_DSC),DSC_EP,_EP01_IN,_INT,USBGEN_EP_SIZE,32 }; rom struct{byte bLength;byte bDscType;word string[1];}sd000={ sizeof(sd000),DSC_STR,0x0409}; rom struct{byte bLength;byte bDscType;word string[25];}sd001={ sizeof(sd001),DSC_STR, 'M','i','c','r','o','c','h','i','p',' ', 'T','e','c','h','n','o','l','o','g','y',' ','I','n','c','.'}; rom struct{byte bLength;byte bDscType;word string[33];}sd002={ sizeof(sd002),DSC_STR, 'P','F','C',' ','M','i','g','u','e','l',' ','P','e','r', 'i','a','g','o',' ','B','o','a','r','d',' ','(',' ',')', ' ','2','0','0','6'}; rom const unsigned char *rom USB_CD_Ptr[]={&cfg01,&cfg01}; rom const unsigned char *rom USB_SD_Ptr[]={&sd000,&sd001,&sd002};

79

Page 80: Compresión y comunicación de datos con un ...deeea.urv.cat/public/PROPOSTES/pub/pdf/1033pub.pdfPFC: compresión y comunicación de datos con un microcontrolador PIC El USB o Universal

PFC: compresión y comunicación de datos con un microcontrolador PIC

#pragma code

80