Skip to content

Commit

Permalink
Merge branch 'BroeringFelipe-master'
Browse files Browse the repository at this point in the history
  • Loading branch information
Renan Augusto Starke committed Dec 17, 2019
2 parents 554f877 + 952a956 commit 004c039
Show file tree
Hide file tree
Showing 73 changed files with 165,840 additions and 8,951 deletions.
1 change: 1 addition & 0 deletions peripherals/tft/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/.metadata/
55 changes: 55 additions & 0 deletions peripherals/tft/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Controlador TFT LCD

Projeto de uma controladora para um display TFT LCD. O hardware é responsável por receber o comando de escrita e converter essa instrução por uma série de informações no display, como comandos para limpar a tela e desenhar quadrados.

## Descrição do display TFT LCD

Verificado no site de vendas do fabricante, [mcufriend](http://www.mcufriend.com/), nota-se que para o mesmo display pode haver controladoras diferentes para o mesmo produto. Devido a isso foi verificado o modelo de controladora usada no display disponível, fazendo o uso do código exemplo em arduino fornecido pelo fabricante. Assim aferiu-se que circuito integrado responsável pelo controle do display é o ILI9320.
Essa controladora possuí diferentes modos de comunicação, dentre elas, paralela de 8/9/16/18 bits e SPI. Mas fazendo a verificação da forma com que era implementado o código em arduino, verificou-se que a comunicação era feita de forma paralela de 8 bits acrescentado de 4 pinos de controle. A figura 1 apresenta o formato que o display recebe as informações.

![TFT_1](./images/figura1.png "Comunicação 8 bits do controlador TFT LCD")

Figura 1. Diagrama de blocos do controlador TFT LCD.
Fonte: [ILI9320 Datasheet](https://www.rockbox.org/wiki/pub/Main/GSoCSansaView/ILI9320DS_V0.55.pdf) (pg 51, fig 23).

Nota-se pela figura 1 que o display recebe palavras de 32 bits enviadas de 8 em 8 bits.

## Descrição dos blocos do controlador TFT LCD

![TFT_2](./images/figura2.png "Diagrama de blocos do controlador TFT LCD")

Figura 2. Diagrama de blocos do controlador TFT LCD.

* **decoder_tft:** Bloco responsável pela decodificação dos dados de entrada, convertendo em informação para as memórias;
* **boot_mem:** Memória responsável pela inicialização do display LCD;
* **data_mem:** Memória responsável por armazenar a informação que será enviada ao display LCD;
* **controller:** Bloco responsável pelo gerenciamento da leitura das memórias;
* **mux:** Bloco de seleção da entrada do bloco *writer*;
* **writer:** Bloco responsável pela conversão dos 32 bits da memória para 8 bits de saída do LCD mais os pinos CS, RS e WR.

(Ambas as memórias tem comportamento de uma fila circular, porém a memória de boot possui os pinos de escrita desativados)

## Descrição dos blocos do decoder
![TFT_3](./images/figura3.png "Diagrama de blocos do decoder")

Figura 3. Diagrama de blocos do decoder do controlador TFT LCD.

* **dec_fsm:** Bloco responsável pela decodificação do comando e escolha do respectivo bloco;
* **dec_reset:** Bloco responsável pelo reset de todos os componentes do controlador TFT LCD;
* **dec_clean:** Bloco responsável por limpar a tela;
* **dec_rect:** Bloco responsável por imprimir um retângulo na tela;

## Descrição das funções em C

![TFT_4](./images/figura4.png "Sequência de bytes")

Figura 4. Sequência de bytes enviados ao hardware.
Funções tft.h
```c
void tft_init();
void tft_clean(uint16_t color);
void tft_sqrt(uint16_t color, uint16_t x, uint16_t y, uint16_t h);
void tft_rect(uint16_t color, uint16_t x, uint16_t y, uint16_t h, uint16_t w);
```
### Bibliografia
[ILI9320 Datasheet](https://www.rockbox.org/wiki/pub/Main/GSoCSansaView/ILI9320DS_V0.55.pdf)
65 changes: 65 additions & 0 deletions peripherals/tft/boot_mem.vhd
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_textio.all;
use std.textio.all;

entity boot_mem is
port(clk : in std_logic;
rst : in std_logic;
rd_en : in std_logic;
rd_data : out unsigned(31 downto 0);
empty : out std_logic
);
end entity;

architecture rtl_boot_mem of boot_mem IS

-- Define the length of the boot memory
-- If you have 54 words in the memory, this number must be 53
constant mem_lengh : natural := 53;

type MEM is array (0 to mem_lengh) of unsigned(rd_data'range);
signal ram_block : MEM := (x"00e58000", x"00000001", x"00010100", x"00020700",
x"00031030", x"00040000", x"00080202", x"00090000",
x"000A0000", x"000C0000", x"000D0000", x"000F0000",
x"00100000", x"00110007", x"00120000", x"00130000",
x"FFFF0032", x"001017B0", x"00110007", x"FFFF000A",
x"0012013A", x"FFFF000A", x"00131A00", x"0029000c",
x"FFFF000A", x"00300000", x"00310505", x"00320004",
x"00350006", x"00360707", x"00370105", x"00380002",
x"00390707", x"003C0704", x"003D0807", x"0060A700",
x"00610001", x"006A0000", x"00210000", x"00200000",
x"00800000", x"00810000", x"00820000", x"00830000",
x"00840000", x"00850000", x"00900010", x"00920000",
x"00930003", x"00950110", x"00970000", x"00980000",
x"00070173", x"FFFF0032");

signal tail : integer range mem_lengh downto 0;
signal count : integer range mem_lengh downto 0;
signal empty_i : std_logic;

begin
-- Set the empty flag
empty <= empty_i;
empty_i <= '1' when count = 0 else '0';

-- Update the tail pointer on read and pulse valid
proc_tail : process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
tail <= 0;
else
if rd_en = '1' and empty_i = '0' then
tail <= tail + 1;
end if;

end if;
end if;
end process;

rd_data <= ram_block(tail);
count <= mem_lengh - tail;

end architecture;
77 changes: 77 additions & 0 deletions peripherals/tft/controller.vhd
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

-- Dispositivo responsavel pelo controle das memorias
entity controller is
port(
clk : in std_logic;
reset : in std_logic;
ready : in std_logic;
start : out std_logic;
mux_sel : out std_logic;
empty_1 : in std_logic;
empty_2 : in std_logic;
read_en1 : out std_logic;
read_en2 : out std_logic
);
end entity;

architecture rtl_controller of controller is
-- IDLE: Estado para espera de uma nova informacao nas memorias
-- READ: Estado para a leitura da memoria (Incremento na fila circular)
-- WRITE: Estado para o inicio do envio da informcao pelo writer
type state_type is (IDLE, READ, WRITE);
signal state : state_type;
begin
moore : process(clk, reset) is
begin
if (reset = '1') then
state <= WRITE;
elsif rising_edge(clk) then
case state is
when IDLE =>
if (ready = '1') then
state <= READ;
end if;
when READ => --
if (empty_1 = '0') then
state <= WRITE;
elsif (empty_2 = '0') then
state <= WRITE;
else
state <= IDLE;
end if;
when WRITE => --
state <= IDLE;
end case;
end if;
end process;

mealy : process(state, empty_1, empty_2)
begin
start <= '0';
read_en1 <= '0';
read_en2 <= '0';

mux_sel <= '1';

if (empty_1 = '0') then
mux_sel <= '0';
end if;

case state is
when IDLE =>
null;
when READ =>
if (empty_1 = '0') then
read_en1 <= '1';
elsif (empty_2 = '0') then
read_en2 <= '1';
end if;
when WRITE =>
start <= '1';
end case;
end process;

end architecture;
108 changes: 108 additions & 0 deletions peripherals/tft/data_mem.vhd
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_textio.all;
use std.textio.all;

entity data_mem is
generic(
RAM_WIDTH : natural := 32;
RAM_DEPTH : natural := 320;
HEAD_INIT : natural := 0
);
port(
clk : in std_logic;
rst : in std_logic;
wr_en : in std_logic;
wr_data : in unsigned(RAM_WIDTH - 1 downto 0);
rd_en : in std_logic;
rd_data : out unsigned(RAM_WIDTH - 1 downto 0);
empty : out std_logic;
full : out std_logic
);
end entity;

architecture rtl_data_mem of data_mem IS
type MEM is array (0 to RAM_DEPTH - 1) of unsigned(wr_data'range);

signal ram_block : MEM := (others => x"00000000");

subtype index_type is integer range ram_block'range;
signal head : index_type;
signal tail : index_type;

signal empty_i : std_logic;
signal full_i : std_logic;
signal fill_count_i : integer range RAM_DEPTH - 1 downto 0;

-- Increment and wrap
procedure incr(signal index : inout index_type) is
begin
if index = index_type'high then
index <= index_type'low;
else
index <= index + 1;
end if;
end procedure;

begin
empty <= empty_i;
full <= full_i;

-- Set the flags
empty_i <= '1' when fill_count_i = 0 else '0';
full_i <= '1' when fill_count_i >= RAM_DEPTH - 1 else '0';

-- Update the head pointer in write
proc_head : process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
head <= HEAD_INIT;
else

if wr_en = '1' and full_i = '0' then
incr(head);
end if;

end if;
end if;
end process;

-- Update the tail pointer on read and pulse valid
proc_tail : process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
tail <= 0;
else
if rd_en = '1' and empty_i = '0' then
incr(tail);
end if;

end if;
end if;
end process;

-- Write to and read from the RAM
proc_ram : process(clk, ram_block, tail)
begin
if rising_edge(clk) then
if wr_en = '1' then
ram_block(head) <= wr_data;
end if;
end if;
rd_data <= ram_block(tail);
end process;

-- Update the fill count
proc_count : process(head, tail)
begin
if head < tail then
fill_count_i <= head - tail + RAM_DEPTH;
else
fill_count_i <= head - tail;
end if;
end process;

end architecture;
Loading

0 comments on commit 004c039

Please sign in to comment.