Reproductor MIDI

From Qi-Hardware
Jump to: navigation, search

David Antonio Montoya
Daniel 2rturo Silva
Daniel Steven Moncada

Contents

[edit] Calificación

Porcentaje Presentación 20% Informe 30% Funcionamiento 50%
1 Entrega 10% 0.5 0.5 0.5
2 Entrega 30% 1 1 0
3 Entrega 20% 1 1 0

[edit] Descripción del formato MIDI

MIDI (de las siglas en inglés Musical Instruments Digital Interface) es un protocolo estandarizado para la comunicación entre dispositivos musicales (sintentizadores de audio, amplificadores, analizadores mucicales y software computacional). Hay varias formas en las que se puede dar un mensaje en formato MIDI, y a continuación se muestra:

Cada mensaje comienza con un byte de estatus, en donde el octavo bit (más significativo) es el bit de set. Después de esto, varios bytes de información se envían, en donde el bit más significativo siempre será cero. De acuerdo a esto, los bytes de información tienen valores de 7 bits (0-127 en decimal, 0x00-0x7F en hexadecimal), y los bytes de status siempre se encuentran en un rango entre 128-255 decimal, 0x80-0xFF hexadecimal.

Los mensajes MIDI deben cumplir estrictamente el tipo de mensaje, sólo exceptuando los mensajes exclusivos del sistema.

Ahora bien, los bytes del formado MIDI consisten en 10 bits, no en 8 bits como usualmente se arreglan los números binarios. Estos bits se envían a una velocidad de 31250 bits/segundo.



[edit] Diagrama de Bloques del proyecto:

3.png 4.png

Descripcion del proyecto

El proyecto consiste en un reproductor de formato MIDI (inicialmente). Para tal fin, utilizaremos la tarajeta de desarrollo SIE, que cuenta con periféricos tales como una FPGA Spartan 3E Xc3S500, y módulos para la memoria ram, un dispositvo NAND, además de puertos I/O.

Para poder llevar a cabo la reproducción del erchivo en formato MIDI, debemos guardar el archivo en la memoria (ya sea NAND, o la memoria RAM). En este punto, accederemos a las posiciones de memoria que contienen toda la inforamación del archivo. Después de esto,se envía la inforamción obtenida en la memoria a un controlador para el formato MIDI (previamente diseñado en lenguaj C) que decpdificará la información y la enviará a un conversor digital-analógico. Finalmente, la señal de audio saldrá por una etapa de potencia que amplificará la señal de salida.

Adicionalmente a esto, existe la posibilidad de aplicar un par de filtros: un filtro digital a la salida del controlador MIDI, y otro filtro analógico a la salida del conversor digital-analógico para atenuar cualquier ruido caracetrístico.

Finalmente, se implementará una interfaz gráfica, aprovechando el display LCD con el que cuenta la tarjeta de desarrollo SIE.


Descripción de tareas Hardware y Software:

Para poder llevar a cabo el proyecto, se deben dividir las tareas Software y las tareas Hardware. Como dispositivos periféricos principales tenemos un display LCD, una etapa de potencia, y por ende, un juego de periféricos que nos ayudarán a controlar la reproducción del archivo. (Play/pause, Stop, Fw, Rw); además de eso, los controladores necesarios para el uso de las memorias, ya sea la memoria flash NAND, o la memoria RAM.

Ahora bien, las tareas Software serán las propias del procesador, control de las señales de Read y Write, rutinas para llamados de interrupciones y su control, y todas las distintas señales de control para los demás dispositivos (procesador-módulo de control).


Software y hardware a utilizar en el proyecto.

El software necesario para realizar nuestro proyecto consiste en los siguientes programas: Ise Webpack: necesario para la compilación y síntesis de códigos en VHDL/Verilog. Códigos del procesador Plasma-Mips. (con códigos VHDL). Compilador de Linux GCC. Herramientas de software libre para la compilación de códigos en VHDL (GHDL) y para la simulación y su posterior visualización (GTKWave). Matlab: Resolución de dudas y posible creación de los filtros digitales. KiCad: Creación y simulación de la placa hija (PCB).

El hardware necesario para el montaje del proyecto es:

Tarjeta de desarrollo SIE. Tarjeta hija para la etapa de potencia. Display LCD (adjunto a la placa de desarrollo SIE). Controles para la reproducción.

Cronograma:

Semana Fecha Actividad
S1 16 - 22 de agosto Comprension del Procesador Plasma
S2 23 - 30 de agosto Adquisición de Información
S3 31 agosto- 06 septiembre Edición de proyecto en la wiki www.qi-hadware.com
S4 7 - 14 septiembre Propuesta del Proyecto
S5 15 - 22 septiembre Elaboración de PCB tarjeta hija
S6- S7 23 de septiembre - 8 octubre Programación de Modulo del controlador MIDI
S8 9 - 17 octubre Programacion Modulo de Conversor Digital Análogo
S9 18 - 25 octubre Manejo de Visualización LCD
S10 26 de octubre - 2 de noviembre Implementacion tarjeta hija
S11 3 - 10 de noviembre Manejo de LCD
S12 11 - 18 de noviembre Pruebas Generales
S13 19 - 26 de noviembre Entrega final

[edit] Hardware adicional

Para lograr amplificar sonido, debemos utilizar un conversor digital-analógico, de tal manera que las señales analógicas puedan ser amplificadas para ser reproducidas posteriormente. Para lograr esta conversión, utilizaremos un circuito integrado DAC 0808, cuya configuración básica nos permitirá obtener señales analógicas. Ahora bien, para amplificar estas señales, se plantea un montaje amplificador consistente en un amplificador operacional. El amplificador operacional a utilizar en este caso será un LM741. Finalmente, se utilizará un regulador de tensión que nos permitirá utilizar valores de 5V y de 3.3V en toda la placa, sin necesidad de fuentes adicionales (utilizaremos el circuito integrado LD1117S50).

[edit] Diagrama de flujo del controlador MIDI

Diagrama de flujo para el controlador MIDI

[edit] Arquitectura del proyecto

Arquitectura del proyecto

[edit] Generador de ondas seno

Para poder convertir una señal digital a una onda de sonido, podemos utilizar un generador de ondas seno, creado en VHDL. Para obtener la frecuencia deseada en nuestro generador de senos, utilizamos la siguiente ecuación:

 Fout=\frac {FTW} {2^{16}}*382\,

A continuación se muestra la tabla de los valores obtenidos:

File:Codificacion midi1.ods

El código se muestra a continuación, y la simulación también.

library ieee;
use ieee.std_logic_1164.all;
use IEEE.STD_LOGIC_arith.all;
use IEEE.STD_LOGIC_unsigned.all;
use work.sine_lut_pkg.all;
 
package dds_synthesizer_pkg is
  component dds_synthesizer
    generic(
      ftw_width : integer
      );
    port(
      clk_i   : in  std_logic;
      rst_i   : in  std_logic;
      ftw_i   : in  std_logic_vector(ftw_width-1 downto 0);
      phase_i : in  std_logic_vector(PHASE_WIDTH-1 downto 0);
      phase_o : out std_logic_vector(PHASE_WIDTH-1 downto 0);
      ampl_o  : out std_logic_vector(AMPL_WIDTH-1 downto 0)
      );
  end component;
end dds_synthesizer_pkg;
 
package body dds_synthesizer_pkg is
end dds_synthesizer_pkg;
 
-- Entity Definition
 
library ieee;
use ieee.std_logic_1164.all;
use IEEE.STD_LOGIC_arith.all;
use IEEE.STD_LOGIC_unsigned.all;
use work.sine_lut_pkg.all;
 
entity dds_synthesizer is
  generic(
    ftw_width : integer := 32
    );
  port(
    clk_i   : in  std_logic;
    rst_i   : in  std_logic;
    ftw_i   : in  std_logic_vector(ftw_width-1 downto 0);
    phase_i : in  std_logic_vector(PHASE_WIDTH-1 downto 0);
    phase_o : out std_logic_vector(PHASE_WIDTH-1 downto 0);
    ampl_o  : out std_logic_vector(AMPL_WIDTH-1 downto 0)
    );
end dds_synthesizer;
 
architecture dds_synthesizer_arch of dds_synthesizer is
 
  signal ftw_accu               : std_logic_vector(ftw_width-1 downto 0);
  signal phase                  : std_logic_vector(PHASE_WIDTH-1 downto 0);
  signal lut_in                 : std_logic_vector(PHASE_WIDTH-3 downto 0);
  signal lut_out                : std_logic_vector(AMPL_WIDTH-1 downto 0);
  signal lut_out_delay          : std_logic_vector(AMPL_WIDTH-1 downto 0);
  signal lut_out_inv_delay      : std_logic_vector(AMPL_WIDTH-1 downto 0);
  signal quadrant_2_or_4        : std_logic;
  signal quadrant_3_or_4        : std_logic;
  signal quadrant_3_or_4_delay  : std_logic;
  signal quadrant_3_or_4_2delay : std_logic;
 
begin
  phase_o         <= phase;
  quadrant_2_or_4 <= phase(PHASE_WIDTH-2);
  quadrant_3_or_4 <= phase(PHASE_WIDTH-1);
 
  lut_in <= phase(PHASE_WIDTH-3 downto 0) when quadrant_2_or_4 = '0' else conv_std_logic_vector(2**(PHASE_WIDTH-2)-conv_integer(phase(PHASE_WIDTH-3 downto 0)), PHASE_WIDTH-2);
  ampl_o <= lut_out_delay                 when quadrant_3_or_4_2delay = '0' else lut_out_inv_delay;
 
  process (clk_i, rst_i)
  begin
    if rst_i = '1' then
      ftw_accu <= (others => '0');
      phase  <= (others => '0');
      lut_out <= (others => '0');
      lut_out_delay <= (others => '0');
      lut_out_inv_delay <= (others => '0');
      quadrant_3_or_4_delay <= '0';
      quadrant_3_or_4_2delay <= '0';
    elsif clk_i'event and clk_i = '1' then
      ftw_accu <= ftw_accu + ftw_i;
      phase    <= ftw_accu(ftw_width-1 downto ftw_width-PHASE_WIDTH) + phase_i;
      if quadrant_2_or_4 = '1' and phase(PHASE_WIDTH - 3 downto 0) = conv_std_logic_vector (0, PHASE_WIDTH - 2) then
        lut_out <= conv_std_logic_vector(2**(AMPL_WIDTH - 1) - 1, AMPL_WIDTH);
      else
        lut_out <= sine_lut(conv_integer(lut_in));
      end if;
      quadrant_3_or_4_delay <= quadrant_3_or_4;
      quadrant_3_or_4_2delay <= quadrant_3_or_4_delay;
      lut_out_inv_delay <= conv_std_logic_vector(-1*conv_integer(lut_out), AMPL_WIDTH);
      lut_out_delay <= lut_out;
    end if;
  end process;
 
end dds_synthesizer_arch;

A continuación se muestra el testbench del código:

library ieee;
use ieee.std_logic_1164.all;
use IEEE.STD_LOGIC_arith.all;
use IEEE.STD_LOGIC_unsigned.all;
use work.dds_synthesizer_pkg.all;
use work.sine_lut_pkg.all;
 
entity dds_synthesizer_tb is
    generic(
      clk_period : time := 10 ns;
			ftw_width : integer := 32
   );
end dds_synthesizer_tb;
architecture dds_synthesizer_tb_arch of dds_synthesizer_tb is
 
signal clk,rst : std_logic := '0';
signal ftw : std_logic_vector(ftw_width-1 downto 0);
signal init_phase : std_logic_vector(phase_width-1 downto 0);
signal phase_out : std_logic_vector(phase_width-1 downto 0);
signal ampl_out : std_logic_vector(ampl_width-1 downto 0);
 
begin
 
	dds_synth: dds_synthesizer
  generic map(
		ftw_width   => ftw_width
  )
  port map(
		clk_i => clk,
		rst_i => rst,
		ftw_i    => ftw,
		phase_i  => init_phase,
		phase_o  => phase_out,
		ampl_o => ampl_out
  );
 
	init_phase <= (others => '0');
	ftw <= conv_std_logic_vector(2147483,ftw_width);  --20us period @ 100MHz, ftw_width=32
 
  clk <= not clk after clk_period/2;
  rst <= '1','0' after 2*clk_period;
 
end dds_synthesizer_tb_arch;

Ahora bien, se presenta la simulación del código, que presenta una onda seno:

Simulación del generador de ondas seno

[edit] Mapa de memoria

A continuación se muestra el código correspondiente al mapa de memoria:

//*--------------------------------------------------------------------
 * TITLE: Plasma Hardware Defines
 * AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
 * DATE CREATED: 12/17/05
 * FILENAME: plasma.h
 * PROJECT: Plasma CPU core
 * COPYRIGHT: Software placed into the public domain by the author.
 *    Software 'as is' without warranty.  Author liable for nothing.
 * DESCRIPTION:
 *    Plasma Hardware Defines
 *--------------------------------------------------------------------*/
#ifndef __PLASMA_H__
#define __PLASMA_H__
 
/*********** Hardware addesses ***********/
#define RAM_INTERNAL_BASE 0x00000000 //8KB
#define RAM_EXTERNAL_BASE 0x10000000 //1MB
#define RAM_EXTERNAL_SIZE 0x00100000
#define UART_BASE         0x20000000
#define UART_WRITE        0x20000000
#define UART_READ         0x20000000
#define UART_STATUS       0x20000010
#define IRQ_MASK          0x20000010
#define IRQ_STATUS        0x20000020
#define dds_synthesizer   0X20000030//Generador de ondas senoidales.
#define visualizacion     0x20000040//LCD.
#define Controles         0x20000050//Controles de reproducción (FW, RW, STOP, PAUSE).
#define Peripheric_4      0x20000060
#define ETHERNET_REG      0x20000070	
#define FLASH_BASE        0x30000000
 
/*********** GPIO out bits ***************/
#define ETHERNET_MDIO     0x00200000
#define ETHERNET_MDIO_WE  0x00400000
#define ETHERENT_MDC      0x00800000
#define ETHERNET_ENABLE   0x01000000
 
/*********** Interrupt bits **************/
#define IRQ_UART_READ_AVAILABLE  0x01
#define IRQ_UART_WRITE_AVAILABLE 0x02
#define IRQ_COUNTER18_NOT        0x04
#define IRQ_COUNTER18            0x08
#define IRQ_ETHERNET_RECEIVE     0x10
#define IRQ_ETHERNET_TRANSMIT    0x20
#define IRQ_GPIO31_NOT           0x40
#define IRQ_GPIO31               0x80
 
/*********** Ethernet buffers ************/
#define ETHERNET_RECEIVE  0x13ff0000
#define ETHERNET_TRANSMIT 0x13fe0000
 
#endif //__PLASMA_H__
Personal tools
Namespaces
Variants
Actions
Navigation
interactive
Toolbox
Print/export