Dispositivo de comunicaciones inalambricas (FM)

From Qi-Hardware
Jump to: navigation, search

Contents

[edit] Integrantes: Nelson Andres Hernandez.

[edit] Calificación

Porcentaje Presentación 20% Informe 30% Funcionamiento 50%
1 Entrega 10% 0.5 0.5 0.5
2 Entrega 30% 1.7 1.7 1.7
3 Entrega 30% 0 0 0 NO ASISTIERON A LA ENTREGA NOV 5 / 2010


4 Entrega 30% -- -- --



Con el objetivo de fomentar el desarrollo de nuevas aplicaciones y campos de operación para la plataforma SIE, nos enfocaremos en la codificación de un modulo receptor inalámbrico RFM22B, el cual opera a 433/868/915MHz de acuerdo con las bandas de transmisión reservadas para la industria (ISM), con una tensión de operación de 1.8v – 3.6v y un bajo consumo de corriente, convirtiéndolo en una solución de comunicación para sistemas alimentados por medio de una batería.

El RFM22B opera en un tiempo TDD (time Division Duplexing) para su transceptor, en donde el dispositivo varía entre la recepción y transmisión de datos. Se emplea un Single Convertion Mixer para disminuir la señal modulada en FSK/GFSK/OOK a una frecuencia IF. Posteriormente la señal pasa por un PGA (Programmable Gain amplifier) y un ADC de alto rendimiento, siendo filtrada, demodulada y empaquetada de tal forma que podamos trabajar sobre la señal con una mayor confiabilidad que con un sistema análogo.

La señal demodulada pasa es direccionada a una salida del GPIO o a un bus estándar SPI () de acuerdo con la lectura de los 64 Byte RX FIFO.

Un oscilador local (LO) de alta fiabilidad es empleado para la transmisión y recepción. El LO es generado a partir de un PLL, el cual es diseñado para soportar diferentes agrupaciones de datos y frecuencias de salida.

[edit] APLICACION COMERCIAL: SISTEMA DE SEGURIDAD INALAMBRICA "DETECTOR DE MOVIMIENTO"

La tarjeta SIE sera empleada para configurar un detector de movimiento por medio de un sensor ubicado en algun punto (en un lugar con acceso restringido por ejemplo), el sensor envia una señal al modulo transmisor del RFM22B, el cual, por medio de la tarjeta SIE, envia una señal FM al modulo receptor ubicado a cierta distancia del transmisor, el modulo transmisor recibe la señal y despues del procesamiento, muestra un mensaje en la pantalla LCD de la tarjeta indicando que algun objeto fue detectado. El sensor de movimiento empleado se construye usando un integrado LM567 conectado como en el siguiente circuito:

http://www.electronicafacil.net/circuitos/Detector-de-proximidad-por-infrarrojos.html

El funcionamiento del circuito se basa en emitir una ráfaga de señales luminosas infrarrojas las cuales al rebotar contra un objeto cercano se reciben por otro componente. Al ser recibidas el sistema detecta proximidad con lo que el Led de salida se acciona (brilla). Este led se remueve del circuito y los pines se toman como la salida, la cual es digital : encendido(1) o apagado (0).

El circuito integrado es un generador/decodificador de tonos que bien cumple con las necesidades de este diseño. Tanto el fotodiodo como el fototransistor deberán estar situados con unidades de enfoque adecuadas para mejorar el alcance. Con simples reflectores de Led´s se pueden obtener alcances del orden del metro. Con lentes convexas se pueden cubrir distancias de cinco metros. Es conveniente sacrificar algo de rango pero colocar filtros UV y SUNLIGHT los cuales no dejan entrar al fototransistor (elemento receptor) los rayos del sol.

Para accionar circuitos externos bastará con reemplazar el led por un optoacoplador, el cual accionará por medio de su transistor interno el circuito a comandar. alimentación:

   * V max: simple 5v dc
   * I  max: 0.1A 

El sensor se conectara a la tarjeta sie de la siguiente forma:

SENSOR

[edit] Diagrama de bloques

  1. Descripción Básica del Hardware a emplear.
Interfaz del usuario

[edit] Bus Serial Peripheral Interface (SPI)

Interfaz del usuario

SPI es un bus de tres líneas, sobre el cual se transmiten paquetes de información de 8 bits. En donde cada una de las tres líneas porta la información entre los diferentes dispositivos conectados al bus, dos de ellas transfieren los datos y la tercera se encarga del direccionamiento del CLOCK. Cada dispositivo conectado al bus puede actuar como transmisor o receptor al mismo tiempo, por lo cual este tipo de comunicación serial es FULL DUPLEX.

Los dispositivos conectados al bus son definidos como maestro y esclavo; cada esclavo es controlado a través del bus por medio de una línea de selección (CHIP SELECT o SELECT SLAVE), por lo general una línea de selección es dedicada para cada esclavo; el cual es seleccionado por medio de un nivel lógico bajo (0) a través de la línea de CHIP SELECT. Los datos sobre este bus pueden ser transmitidos a razón de casi 0Bits/seg a 1MBits/seg. Los datos son transmitidos en bloques de 8Bits donde el MSB es el primero en enviarse.

Para un tiempo TI, solo existirá un maestro sobre el bus; en dicho caso cualquier dispositivo esclavo debe cambiarse a un estado de alta impedancia a través de la línea CHIP SELECT.

El bus SPI emplea un registro de desplazamiento simple para la transmisión de información.

[edit] Modos de operación para el CLOCK.

La transferencia de datos se realiza de manera sincrónica, siendo un bit transferido por cada ciclo del clock. Siendo así, la mayoría de las interfaces del SPI posee dos bits de configuración, el CPOL (CLOCK Polarity) y CPHA (CLOCK Phase). CPOL determina si el estado de IDLE de la línea del CLOCK esta en bajo o si se encuentra en un estado alto. CPHA determina en que cambio de estado del CLOCK los datos sufre de un corrimiento lateral; si CPHA =0 los datos de la línea MOSI son detectados en un ciclo de bajada y los de la línea MISO se detectan en un flanco de subida.

De acuerdo con lo planteado para la transferencia de datos dos dispositivos SPI que deseen comunicarse debe tener la misma Polaridad de CLOCK (CPOL) y la misma FASE (CPHA). A continuación presentamos de forma mas detallada los diferentes modos de operación del SPI, de acuerdo con los valores de CPOL y CPHA. Cuando el bit de Polaridad del CLOCK determina el nivel del estado de Idle del CLOCK y el bit de Fase del Clock determina que flanco recibe un nuevo dato sobre el bus; el modo de operación esta determinado por el dispositivo esclavo.

Entonces si CPOL está en un 0 lógico y no existe la transferencia de datos el dispositivo maestro mantiene la línea SCLK en bajo. Si en cambio el CPOL es 1, el maestro libera la línea SCLK alta.

Con respecto a la señal de CPHA, conjuntamente con CPOL, controlan que nuevos datos serán enviados por medio del bus. Entonces si CPHA =1 los datos sufren un desplazamiento sobre la línea de MOSI según el valor de CPOL.

  • Si CPOL =1, los datos se transmiten en un flanco de bajada del CLOCK y se leen en un flanco de subida del CLOCK.
Transmisión de datos
  • Si CPOL=0, los datos se transmiten en un flanco de subida del CLOCK y se leen en un flanco de bajada.
Transmisión de datos
  • Si CPHA=0, la transferencia de daos comienza en el primer flanco del CLOCK y todas las operaciones subsecuentes dentro del byte ocurren en cada cambio de estado del CLOCK.
Transmisión de datos

[edit] Cronograma de actividades

Cronograma

[edit] Diagramas y PSB

[edit] Versión 1.0

[edit] Versión 1.1 (final)

[edit] Comunicación Procesador-Módulo RFM22B Recepción

Cuando el procesador necesite el servicio del periférico RFM22B, debe colocar en el bus de direcciones la dirección asignada al mismo, esto hará que el decodificador de direcciones active su señal de habilitación. El modulo RFM22B establece la comunicación con el procesador la cuál puede ser para de lectura (recepción de los datos que vienen del sensor de movimiento o recepción de los datos que vienen de la antena en modo receptor) o para esrcitura (envío de la señal procesada hacia la antena en modo transmisor).

Cuando un el Módulo RFM22B necesita ser atendido por el procesador, activa su señal IRQ, esta es procesada por el PIC, el cual determina si eleva esta solicitud al procesador. Si la señal es dirigida al procesador, este consulta el estado del PIC para determinar la fuente de la interrupción y de esta forma determinar la rutina de atención.

MODULO RFM22B

1.Modo Lectura. si el procesador realiza una operación de lectura, activará la señal nRD y el Módulo RFM22B tomará el control del bus de datos. La señal nCS2 se coloca en un nivel lógico bajo, la señal RDWR_n en alto, con lo que la función (~RDWR_n(0) | nCS2(0)) toma un valor de 0 activando el buffer tri-estado, con lo que el bus de datos de salida del modulo RFM22B es conectado al bus de datos del procesador.

2.Modo Escritura. Si el procesador realiza una operación de escritura activará la señal nRW, colocará en el bus de datos la información a transmitir y el modulo RFM22B la leerá. El buffer tri-estado se encuentra en alta impedancia ((~RDWR_n (1) | nCS2 (0)) = 1) y desactivado.

[edit] Comunicación Modulo RFM22B-PIC Transmisión

El Controlador de Interrupciones Programable (PIC) está encargado de realizar las siguientes tareas:

   * Procesamiento de la señal proveniente del sensor de movimiento.
   * Control del Módulo RFM22B transmisor por medio de configuración de GPIO
   * Interfaz con el Módulo para la transmisión. 

La figura muestra dos posibles formas de conexión para el modulo RFM22B con un PIC configurado como microcontrolador para la transmisión de la señal proveniente del sensor.

RFM22B PIC

[edit] Bloque de comunicación SPI en Verilog y descripción de la programación del PIC

1. Módulo RFM22B El modulo RFM22B posee una interfaz de comunicacion SPI la cual recibe tres señales provenientes de la tarjeta SIE. 1.1 Señales provenientes de la tarjeta SIE: a)nwe: señal que indica el tiempo de escritura de datos en el modulo RFM22, interactua con el bloque "Write Pulse Generator" junto con la señal ncs. b)RDWR: Señal que indica el modo de operacion: 1 para escritura y 0 para lectura. c)addr[6:0]: Es el bus de direcciones necesarias para cualquiera de los modos de operacion: se usa para escribir los datos en los registros con esas direcciones (en modo escritura) o para leer los datos en los registros con esas direcciones (en modo lectura). d)RFM_data[7:0]: Es el bus que contiene los datos que serán escritos en las correspondientes direcciones en modo escritura, en modo lectura, sus datos son ignorados y se van reemplazando por los datos contenidos en SDO con cada flanco de subida. La siguiente figura ilustra el diagrama de estados de la interfaz SPI. Los estados de escritura y lectura son como se explicaron anteriormente, el estado IDLE es el estado de inactividad o podria considerarse como un estado de inicializacion.

ESTADOS_RFM22

1.2 Señales entrantes al Modulo RFM22B. a)SDI: Señal de 8 bits que transmite los datos y las direcciones de la siguiente forma: En los primeros 8 flancos de subida de la señal del clock (SCLK) se transmite la señal de escritura o lectura RDWR [0] y las direcciones [7:1], en los siguientes 8 flancos se transmiten los datos [7:0]. Las direcciones se usan para seleccionar uno de los 128 registros de control de 8-bits que posee el modulo y los 8 bit de datos se escriben en dicho registro en modo escritur; en modo letura solo se usan los 7 bits de direcciones y se ignoran los datos. b) SCLK: Señal del clock proveniente de la tarjeta, aunque se puede hacer un divisor dentro del SPI a partir del clock "clk" y generarla, con un frecuencia, como maximo, de 10MHz. c) nSEL: Es un pulso que indica el tiempo que el modulo RFM22 debe ser escrito o debe ser leído por la tarjeta. En alto (1) no hay lectura ni estritura, en bajo (0) se efectua alguna de las operaciones dependiendo de RDWR.

SPI_1

El módulo RFM22 posee una señal de salida SDO la cual se encarga de entregar los datos contenidos en las direcciones que indique la señal SDI en modo lectura, en este modo los datos contenidos en SDI son ignorados.

SPI_2


2.Simulaciones.

La siguiente figura muestra la simulacion efectuada para las siguientes entradas: addr[7:0]=8H'8A, wrBus[8:0]=8h'AA, el bit que determina la escritura o la lectura es el bit addr[0].

Vemos que cuando la addr[0] es (0) la señal de rdBus toma los valores de SDO , esto se hace cargando cada valor de SDO en el bus de rdBus a medida que el clock esta activo, la carga termina en 8 flancos por medio del buffer tri-states; mientras que cuando RDWR es (1), la señal SDI toma siempre los valores de addr junto con rdBus a medida que el clock se ejecuta, alternando cada 8 flancos entre direcciones y datos.

A) ESCRITURA
ESCRITURA
B) LECTURA
LECTURA

3. Código Implementado:

Como en todo lenguaje de programacion el algoritmo para la configuracion de un periferico con comunicacion SPI, inicia con la definicon de las variables propias del SPI, en donde SDIN y SDOUT son los datos de entrada y salida con respecto al periferico; addr indica la ubicacion de los datos y Nsel determina el estado de operacion.

  1.  // ---- Include Files --------------------------------------------------
  2.   `timescale 1ns / 1ps
  3.   module RFM_peripheral(  clk, reset, cs, SCLK, SDIN,SDOUT, 
  4.                          addr, rdBus, wrBus,Nsel, we);
  5.  
  6.      input   clk, reset, cs, we;
  7.       input   [10:0] addr;
  8.      input   [7:0] wrBus;
  9.      output  SCLK,Nsel;
  10.      output  [7:0] rdBus;
  11.      inout   SDIN, SDOUT; 
  12.  
  13.      reg  [7:0]   rdBus;
  14.      wire we;
  15.  
  16.      reg  [15:0] array_in ;
  17.  
  18.      //SPI registers
  19.      reg [32:0] DIVCLK=500;
  20.      reg SPI_wr = 0,w_st1=0, Nsel1=1;
  21.      reg SCLK_buffer = 0;
  22.      reg SDIN_buffer = 0;
  23.       reg busy = 0, load_in = 0, rdwr;
  24.       reg pulse = 0, clkdiv_en  = 0;
  25.       wire fallingSCLK;
  26.  
  27.      reg [15:0] in_buffer=0;
  28.      reg [15:0] out_buffer;
  29.      reg [32:0] clkcount = 0;
  30.     reg [5:0] pulsecount = 0;
  31.  
  32.     assign fallingSCLK = pulsecount[0];


Con respecto al control realizado sobre el SPI, se inicilizan las variables que determinan el estado del SPI, el Clock sobre el cual opera el periferico y el estado estado de operacion del Bus de tranferencia de datos (transmision o recepcion); pasando asi a la configuracion del bus y la ionterrpcion necesaria para el cambio de estado. se define "array_in" como el arreglo de entrada total al SPI, definiendo a Addr y wrBus como los datos a leer o escribir; para la seleccion de lectura o escritura en el periferico se toma el bit mas un valor de 0 cuando se esta leyendo y cuando vale 1 se realiza la escritura en un registro determinado por la Addr que acompana al dato.

Se define el pulsecount como el numero de pulsos necesario para llevar cabo la transferencia completa de datos ademas de el tiempo necesario para el cambio de estado determinado por Nsel. Siendo mas detallado, con respecto al estado de Busy este nos permite observar cuando el bus es capaz de recibir o transmitir datos, dado que al estar activado en una operacion de lectuta impide que se escriba al mismo tiempo y viceversa.

La asignacion de Nsel nos permite manejar un tiempo de espera para el cambio d lectura a escritura, con una duracion minima de cinco flancos de clock qu aseguran que la tranferencia de datos realizada se lleve por completo y evitemos modificaciones en la informacion.


  1.     always @(posedge clk)
  2.       if(reset) begin
  3.           {w_st1, pulsecount, clkdiv_en, busy,Nsel1, SPI_wr} <= 0;
  4.      end else begin
  5.  
  6.     if(we & cs) begin 
  7.  	array_in<={addr[7:0],wrBus[7:0]};
  8.  	SPI_wr<=1;
  9.  	rdwr<=addr[7];
  10.         Nsel1<=0;
  11.  	end
  12.  	else if (in_buffer==array_in) array_in<=0;
  13.  
  14.         case (w_st1)
  15.               0: begin  
  16.                      if(SPI_wr) begin
  17.                          clkdiv_en  <= 1;
  18.                           load_in <= 1;
  19.                          w_st1 <= 1; busy <= 1;
  20.                      end
  21.                  end
  22.              1: begin
  23.  			            SPI_wr<=0;
  24.                       load_in <= 0;
  25.                       if(pulse)  
  26.                           pulsecount <= pulsecount + 1;   
  27.                       else if (pulsecount > 35) begin 
  28.                            clkdiv_en  <= 0; busy <= 0; 
  29.                            w_st1 <= 0; pulsecount <= 0; 
  30.  				Nsel1<=1;
  31.                       end
  32.                  end
  33.            endcase
  34.       end


Para la configuracion de un periferico que funciona por medio de un protocolo serial la asignacion de SCLK determian la velocidad de transferencia de informacion a traves del bus y permite el funcionamiento y la sincronizacion del dipositivo.


  1.  // SPI Clock Generator
  2.       always@(posedge clk)
  3.          if (clkdiv_en) begin
  4.             if(clkcount < DIVCLK) begin
  5.                     clkcount <= clkcount + 1; pulse <=0;
  6.             end else begin
  7.                  clkcount <= 0; pulse <=1;
  8.                  if((pulsecount>0) && (pulsecount < 33)) 
  9.                      SCLK_buffer <= ~SCLK_buffer;
  10.             end
  11.          end else  begin
  12.              SCLK_buffer <= 0; pulse <=0;
  13.          end


Para finalizar la explicación del modulo SPI, los procesos de recepción y transmisión de información son llevados a cabo por medio del manejo de un registro de desplazamiento el cual opera durante un tiempo menor al maximo valor definido por el pulsecount, logrando realizar la carga completa de los datos. En la recepción el proceso mas transcendental es la asignacion de rdBus al buffer de salida con un corriemiento de un Bit, de acuerdo al valor de "rdwr". en el caso de la transmision se lee el arreglo completo de la informacion array_in[15:0].

Con respecto al proceso de transmición cargamos en el buffer de entrada los datos correspondiente al arreglo array_in [15:0] , realizando la transmición de la informacion por medio de un registro de corriemiento.

  1.     // SPI Receptor
  2.       always@(posedge clk)
  3.      begin
  4.          if((fallingSCLK & pulse) && (pulsecount < 33)) begin
  5.              out_buffer <= out_buffer << 1;
  6.  			//if (pulsecount>16) begin
  7.  			out_buffer[0] <= SDOUT;
  8.  			//if (pulsecount>30)
  9.  				if(rdwr==0) rdBus<=out_buffer[8:1];
  10.  						 // end
  11.          end
  12.      end
  13.  
  14.      // SPI Transmitter
  15.      always@(posedge clk)
  16.      begin
  17.          if(load_in) in_buffer <= array_in[15:0]; 
  18.          if(!fallingSCLK & pulse) begin
  19.              SDIN_buffer <= in_buffer[15];
  20.              in_buffer <= in_buffer << 1;
  21.          end
  22.      end
  23.  
  24.      assign SCLK = SCLK_buffer;
  25.      assign SDIN = SDIN_buffer;    
  26.      assign Nsel=Nsel1;
  27.  endmodule

[edit] MODIFICACIÓN DE REGISTROS INTERNOS DEL MODULO RFM22B

Para este proceso, las direcciones (addr) y los datos (wdBus) se envian desde ESPACIO DE USUARIO. Usamos el codigo "jz_init_sram" para enviarlos por medio de la variable "virtual_addr", de la siguiente forma:

Virtual_addr["dirección del registro al cual se va a enviar el dato (en decimal)"]="dato a escribir(en hexadecimal)"

Se debe tener en cuenta que el primer bit de el numero decimal que representa la dirección debe ser "1" para escritura y "0" para lectura, por ejemplo se que quiere escribir el registro "0x09" se debe colocar en la dirección el numero "137=10001001" y si se quiere leer se coloca el numero "9=00001001".

[edit] Descripción Driver

Para el diseño del driver encargado de la gestion y inicializacion del dispositivo de recepción RFM, tomamos como guia el montaje y logica planteada del IRQ, modificando la definición de las funciaones princiaples a realizar de la “struct file_operations fops ”, logrando obtener:


  1. struct file_operations fops = {
  2.   .owner  = THIS_MODULE,
  3.   .write  = device_write,
  4.   .open   = device_open,
  5.   .release = device_release
  6.  
  7. };


Posteriormente se emplea la funcion outb, popia de la librería <asm/io.h>, la cual realiza la escritura sobre los registros de operación del RFM, de acuerdo con las especificaciones planteads para la recepción; siendo el caso acontinuacion presentamos algunas de las asignaciones realizadas al RFM:

  1.  ioaddress = __ioremap(FPGA_BASE, 0x4000, _CACHE_UNCACHED);
  2.        printk(KERN_ALERT  "Setting to RX Mode\n");
  3. /*      Setting to Receiver Mode     */
  4. outb(0x00, ioaddress+(4*(0x06 + 0x80)));
  5.  test=0; 
  6.   while(test==0) test=inb(ioaddress+40);
  7. outb(0x01, ioaddress+(4*(0x07 + 0x80)));
  8.  test=0;
  9.   while(test==0) test=inb(0xb5000000+40);
  10. outb(0x7f, ioaddress+(4*(0x09 + 0x80)));
  11.  test=0; 
  12.   while(test==0) test=inb(ioaddress+40);
  13. outb(0x05, ioaddress+(4*(0x0A + 0x80))); 
  14.   test=0;
  15.   while(test==0) test=inb(0xb5000000+40);
  16. outb(0xf4, ioaddress+(4*(0x0B + 0x80))); 
  17.   test=0;
  18. ….


Con la definición inicial de los valores especificos para los registros de operación del del RFM, apsamos a la detección y apertura del dispositivo, aunque nustros proceso se limita a la lectura del dispisitivo definimos la función de escritura para una mayor robustez del driver. Para finalizar realizamos la asignacion final de los registros del RFM, por medio de la función “echo” siendo ejecutado una sola vez el proceso de asignación durante el tiempo de operación del dispositivo.

  1. static int device_open(struct inode *inode, struct file *file)
  2. {
  3.   if (is_device_open)
  4.     return -EBUSY;
  5.  
  6.   is_device_open = 1;
  7.  
  8.   try_module_get(THIS_MODULE);
  9.  
  10.   return SUCCESS;
  11. }
  12.  
  13. static int device_release(struct inode *inode, struct file *file)
  14. { 
  15.   is_device_open = 0;  
  16.  
  17.   module_put(THIS_MODULE);
  18.  
  19.   return 0;
  20. }
  21.  
  22. static ssize_t 
  23. device_write(struct file *filp, const char *buff, size_t count, loff_t * off)
  24. {
  25.   const char cmd = buff[0];
  26.  
  27.   if(cmd=='W')
  28.   {
  29. irq_enabled=1;
  30.        printk(KERN_ALERT  "Setting to Tx Mode\n");
  31. /*      Setting to Receiver Mode     */
  32. outb(0x00, ioaddress+(4*(0x06 + 0x80)));
  33.  test=0; 
  34.   while(test==0) test=inb(ioaddress+40);
  35. outb(0x09, ioaddress+(4*(0x07 + 0x80)));
  36.  test=0;
  37.   while(test==0) test=inb(0xb5000000+40);
  38. outb(0x7f, ioaddress+(4*(0x09 + 0x80)));
  39.  test=0; 
  40.   while(test==0) test=inb(ioaddress+40);
  41. outb(0x05, ioaddress+(4*(0x0A + 0x80))); 
  42.   test=0;
  43.   while(test==0) test=inb(0xb5000000+40);
  44. outb(0xf4, ioaddress+(4*(0x0B + 0x80))); 
  45.   test=0;
  46.   while(test==0) test=inb(0xb5000000+40);
  47. outb(0xfd, ioaddress+(4*(0x0c + 0x80)));
  48. test=0;
  49. ….

Para el proceso de transmision se emple los misma estructura descrita con anteriridad, modificando los registros de inicializacion del RFM por los de transmicion, logrando obtener la siguiente estructura:


  1. static int device_open(struct inode *inode, struct file *file)
  2. {
  3.   if (is_device_open)
  4.     return -EBUSY;
  5.  
  6.   is_device_open = 1;
  7.  
  8.   try_module_get(THIS_MODULE);
  9.  
  10.   return SUCCESS;
  11. }
  12.  
  13. static int device_release(struct inode *inode, struct file *file)
  14. { 
  15.   is_device_open = 0;  
  16.  
  17.   module_put(THIS_MODULE);
  18.  
  19.   return 0;
  20. }
  21.  
  22. static ssize_t 
  23. device_write(struct file *filp, const char *buff, size_t count, loff_t * off)
  24. {
  25.   const char cmd = buff[0];
  26.  
  27.   if(cmd=='W')
  28.   {
  29.        printk(KERN_ALERT  "Setting to Tx Mode\n");
  30. /*      Setting to Transmitter Mode     */
  31. outb(0x00, ioaddress+(4*(0x06 + 0x80)));
  32.  test=0; 
  33.   while(test==0) test=inb(ioaddress+40);
  34. outb(0x01, ioaddress+(4*(0x07 + 0x80)));
  35.  test=0;
  36.   while(test==0) test=inb(0xb5000000+40);
  37. outb(0x7f, ioaddress+(4*(0x09 + 0x80)));
  38.  test=0; 
  39.   while(test==0) test=inb(ioaddress+40);
  40. outb(0x05, ioaddress+(4*(0x0A + 0x80))); 
  41.   test=0;
  42.   while(test==0) test=inb(0xb5000000+40);
  43. outb(0xf4, ioaddress+(4*(0x0B + 0x80))); 
  44.   test=0;
  45.   while(test==0) test=inb(0xb5000000+40);
  46. outb(0xef, ioaddress+(4*(0x0c + 0x80)));
  47. test=0;
  48. ….

[edit] Interfaz con el usuario

A continuación presentaremos el desarrollo de la aplicación del entrono gráfico del proyecto, por medio del programador Qt-creator; permitiéndonos obtener los datos de configuración y salida de nuestro proyecto y ser presentados de forma sencilla al usuario. Creamos 2 programas en QT, uno para recepcion y o tro para transmision. El grafico en ambos LCD de las tarjetas SIE sera el mismo, mientras que el codigo mainwindow de cada programa cambiara, uno lee datos desde el registro de la memoria FIFO y el otro los escribe al comparar el pulso generado desde el sensor.

El código para el programa de transmision es el siguiente:

Transmision:

  1. #include "mainwindow.h"
  2. #include "ui_mainwindow.h"
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5.  
  6. MainWindow::MainWindow(QWidget *parent) :
  7.     QMainWindow(parent),
  8.     ui(new Ui::MainWindow)
  9. {
  10.     ui->setupUi(this);
  11.     RAM=initFPGA_RAM();
  12.     LED=initGPIO_LED();
  13.     iter=0;
  14.  
  15.     startTimer(1000);
  16. }
  17.  
  18. MainWindow::~MainWindow()
  19. {
  20.     delete ui;
  21. }
  22.  
  23. JZ_PIO *
  24. MainWindow::initGPIO_LED()
  25. {
  26.     JZ_PIO *pio;
  27.  
  28.     pio = jz_gpio_map (LED_PORT);
  29.     jz_gpio_as_output (pio, LED_PIN);
  30.     jz_gpio_clear_pin (pio, LED_PIN);
  31.  
  32.     return pio;
  33. }
  34.  
  35. JZ_REG *
  36. MainWindow::initFPGA_RAM()
  37. {
  38.     JZ_PIO *pio;
  39.     JZ_PIO *pio1;
  40.     JZ_REG *virt_addr;
  41.  
  42.     pio = jz_gpio_map (CS2_PORT);
  43.     jz_gpio_as_func (pio, CS2_PIN, 0);
  44.  
  45.     pio1 = jz_gpio_map (TEST_PORT);
  46.    jz_gpio_as_input(pio1, TEST_PIN);
  47.  
  48.     virt_addr = (JZ_REG *) (jz_mmap(0x13010000) + 0x18);
  49.  
  50.     if (*virt_addr != 0x0FFF7700)
  51.     {
  52.         *virt_addr = 0x0FFF7700;
  53.         printf ("RFM: Configuring CS2 8 bits and 0 WS: %08X\n", *virt_addr);
  54.     }
  55.     else
  56.         printf ("RFM: CS2, already configured: %08X\n", *virt_addr);
  57.  
  58.     virt_addr = (JZ_REG *) jz_mmap (0x14000000);
  59.  
  60.     return virt_addr;
  61. }
  62.  
  63.  
  64. void
  65. MainWindow::timerEvent(QTimerEvent*)
  66. {
  67.     QString plain_text;
  68.     printf ("Reading Sensor..\n");
  69.     a=RAM[512 + 10];
  70.     /***************************/
  71. if (a==0x00)
  72.   {
  73.                 count=255;
  74.                 RAM[500]=0;
  75.                 usleep (15000);
  76.                 ui->label_2->setPixmap(QPixmap("on.jpg"));
  77.                 printf ("Sending Data Enable..\n");
  78.             }
  79. else
  80. {
  81.                 count=0;
  82.                 RAM[500]=0;
  83.                 usleep (15000);
  84.  
  85.                                     ui->label_2->setPixmap(QPixmap("off.jpg"));
  86.                                      printf ("Sending Data Disdable..\n");
  87. }
  88.  
  89.  
  90.                     RAM[500]=0;
  91.                     while(test==0)
  92.                     test=RAM[10];
  93.                     RAM[0x7f + 0x80]=count;
  94.                     test=0;
  95.                     while(test==0)
  96.                         test=RAM[10];
  97.                     RAM[0x05 + 0x80]=0x04;
  98.                     test=0;
  99.                     while(test==0)
  100.                         test=RAM[10];
  101.                     RAM[0x03 + 0x00]=0x04;
  102.                     test=0;
  103.                     while(test==0)
  104.                         test=RAM[10];
  105.                     RAM[0x04 + 0x00]=0x04;
  106.                     test=0;
  107.                     while(test==0)
  108.                         test=RAM[10];
  109.                     RAM[0x07 + 0x80]=0x09;
  110.                     test=0;
  111.                    usleep (150000);
  112.  
  113.  
  114. }

El anterior codigo mapea la direccion de la FPGA y se lee el registro que determina si el sensor esta apagado o enecendido, si esta enecendido, envia a la direccion de la memoria FIFO del RFM22b y escribe un valor, el cual sera comparado para encender un led en la pantalla de QT en el codigo de la recepcion.

Recepcion:

  1. MainWindow::timerEvent(QTimerEvent*)
  2. {
  3.     QString plain_text;
  4.     /***************************/
  5.  
  6.             RAM[0x7f] =0;
  7.             usleep (500);
  8.             printf ("Reading Sensor..\n");
  9.             i=RAM[0x7f];
  10.             printf ("i= %d\n",i);
  11.  
  12.                             if(i==255)
  13.                             {
  14.                                  printf ("Receiving Data Enable..\n");
  15.                               ui->label_2->setPixmap(QPixmap("on.jpg"));
  16.                             }
  17.                             else
  18.                             {
  19.                                  printf ("Receiving Data Disdable..\n");
  20.                                 ui->label_2->setPixmap(QPixmap("off.jpg"));
  21.                             }
  22.  
  23.  
  24.  
  25.                             RAM[0x03 + 0x00]=0x00;
  26.                             test=0;
  27.                             while(test==0)
  28.                                 test=RAM[10];
  29.                             RAM[0x04 + 0x00]=0x00;
  30.                             test=0;
  31.                             while(test==0)
  32.                                 test=RAM[10];
  33.                             test=0;
  34.                             RAM[0x07 + 0x80]=0x05;
  35.                             while(test==0)
  36.                                 test=RAM[10];
  37.  
  38.  
  39.  
  40.  
  41.  
  42.    // ui->plainTextEdit->appendPlainText(plain_text);
  43. }

El anterior codigo respecto al de la transmision solo cambia con la lectura de los datos desde la FIFO del modulo RFM22B para compararlo y encender un led en la pantalla.


[edit] Montaje Final

[edit] Estudio Económico.

tomando en cuenta que el grupo de trabajo esta compuesto por 2 personas, cada una de ellas encargada de un área en especifico, ya sea diseño o construcción e implementación del prototipo: siendo el caso, siendo el tiempo disponible para el desarrollo del proyecto de 14 semanas, durante las cuales se empleo mínimo una hora diaria de tiempo para el trabajo especifico en el desarrollo de los objetivos planteados.

considerando el tiempo de trabajo, las condiciones de entrega y la presentación de los adelantos del diseño hasta llegar a un prototipo con un nivel de robustez considerable, se llego a la desicion de cobrar por cada una de las horas de trabajo una suma de $50.000 , dando como resultado un costo por mano de obra de $4.900.000, a los cuales se le sumara el costo de los insumos y herramientas empleadas, como:

  • 2 SIE, con un costo generalizado de $ 400.000
  • 3 PCB's de prueba con un costo de $ 110.000
  • 2 Pcb's finales con un costo de $ 74.000
  • Materiales (conectores, sensores y dispositivos electrónicos en general) con un costo general de $ 50.000

Siendo el costo total del prototipo entregado a la fecha con sus respectivas pruebas igual a: $ 634.000

[edit] Referencias

http://forum.modtronix.com/index.php?topic=399.0

http://tomoyo.sourceforge.jp/cgi-bin/lxr/source/drivers/spi/spi.c

http://docwiki.gumstix.org/Sample_code/C/SPI

http://wiki.freaks-unidos.net/linux%20drivers

Personal tools
Namespaces
Variants
Actions
Navigation
interactive
Toolbox
Print/export