Introdução à Programação


ISCTE

Ano lectivo de 1999/2000

1º Semestre


Trabalho Final

Simulador de circuitos lógicos simples

O objectivo do trabalho final é o desenvolvimento de um programa que permita a simulação de pequenos circuitos lógicos.  Os circuitos lógicos são especificados pelo utilizador através de ficheiros de configuração com um formato que se descreve abaixo.  É também parte integrante deste trabalho final o desenvolvimento de um circuito (circuitos) lógico(s) que permitam somar dois inteiros sem sinal de 8 dígitos binários (bit) e a sua visualização num LCD simulado (ver Problema 3).

1  Introdução aos conceitos básicos

1.1  Portas lógicas

As portas lógicas básicas são unidades dos circuitos lógicos que efectuam operações lógicas sobre bits.  Cada tipo de porta corresponde a uma operação lógica em particular.  As portas lógicas têm entradas e saídas.  As saídas (se existirem) de uma dada porta lógica são o resultado da operação lógica respectiva sobre as entradas (se existirem).  As portas lógicas básicas dos circuitos que é necessário simular neste trabalho são: AND, NAND, OR, NOR, XOR, NOT, ZERO, ONE.  É ainda necessário simular uma pseudo-porta SHOW, uma pseudo-porta LCD, e tipos especiais de portas, com número arbitrário de entradas e saídas, correspondentes a circuitos lógicos completos.

Por convenção as portas lógicas são normalmente descritas como operando sobre dígitos binários (bits) que podem ter os valores 0 e 1.  É possível associar o valor lógico V ao bit 1 e o valor lógico F ao bit 0.  Se assim for, as portas lógicas básicas a usar neste trabalho podem ser descritas como se segue:

AND

Entradas: pelo menos duas.
Saídas: apenas uma, calculada como a conjunção (e) dos valores lógicos das entradas.
Exemplo: uma porta AND com 2 entradas V e F tem como saída F.

NAND

Entradas: pelo menos duas.
Saídas: apenas uma, calculada como a negação da conjunção (e) dos valores lógicos das entradas.
Exemplo: uma porta NAND com 2 entradas V e F tem como saída V.

OR

Entradas: pelo menos duas.
Saídas: apenas uma, calculada como a disjunção (ou) dos valores lógicos das entradas.
Exemplo: uma porta OR com 2 entradas V e F tem como saída V.

NOR

Entradas: pelo menos duas.
Saídas: apenas uma, calculada como a negação da disjunção (ou) dos valores lógicos das entradas.
Exemplo: uma porta NOR com 2 entradas V e F tem como saída F.

XOR

Entradas: exactamente duas.
Saídas: apenas uma, calculada como a disjunção exclusiva (oux) dos valores lógicos das entradas.
Exemplo: uma porta XOR com 2 entradas V e V tem como saída F.

NOT

Entradas: exactamente uma.
Saídas: apenas uma, calculada como a negação do valor lógico da entrada.
Exemplo: uma porta NOT com entrada V tem como saída F.

ZERO

Entradas: nenhuma.
Saídas: apenas uma, sempre com valor lógico F.

ONE

Entradas: nenhuma.
Saídas: apenas uma, sempre com valor lógico V.

SHOW

Entradas: pelo menos uma.
Saídas: nenhuma.
Função: ao ser simulada esta pseudo-porta escreve no ecrã os valores lógicos da entrada como uma sequência de dígitos binários.
Exemplo: se a porta tiver três entradas com valores V, F e F (da primeira para a última), então a sua simulação deve mostrar no ecrã a sequência de dígitos "100".
Utilização: usa-se como uma forma de observar valores lógicos internos de um circuito para efeitos de depuração.

LCD

Entradas: pelo menos sete e sempre um múltiplo de sete.
Saídas: nenhuma.
Função: ao ser simulada esta pseudo-porta mostra no ecrã uma sequência de LCD correspondentes cada um a um conjunto de sete entradas, que assinalam quais os segmentos do LCD activos (ver problema 3).
Exemplo: se a porta tiver 14 entradas com valores F, F, V, F, F, V, F, V, F, V, V, V, F, e V (da primeira para a última), então a sua simulação deve mostrar no ecrã o seguinte texto:
    _ 
  | _|
  ||_

Outras

Entradas: qualquer número.
Saídas: qualquer número.
Função: sempre que uma porta lógica tiver outro nome que não os acima, então esse nome é o nome de um ficheiro de configuração de um circuito lógico completo que faz parte do circuito em simulação.

1.2  Circuitos

Um circuito lógico é constituido por um conjunto de portas lógicas interligadas.  Cada circuito tem entradas (ligadas às entradas de portas lógicas) e saídas (vindas de saídas de portas lógicas).  Cada circuito pode ser visto como produzindo uma operação lógica complexa.

Por exemplo, abaixo encontra-se um circuito que implementa uma disjunção exclusiva usando apenas as portas elementares AND, OR e NOT (note-se a numeração de portas, entradas e saídas):
 
 

O circuito acima, de nome "oux", depois de definido pode ser usado em outros circuitos.  O circuito abaixo constroi uma disjunção exclusiva de três entradas e inclui uma pseudo-porta para depuração do circuito  (note-se a numeração de portas, entradas e saídas):

Nota importante: nestas figuras um número sobre uma porta lógica indica o número dessa porta, um número junto de uma entrada de uma porta indica o número dessa entrada nessa porta, um número junto de uma saída de uma porta indica o número dessa saída nessa porta, um número junto de uma entrada do circuito indica o número dessa entrada do circuito e um número junto de uma saída do circuito indica o número dessa saída do circuito.

Definição de circuitos

A definição de um circuito é feita através de um ficheiro com o seguinte formato (os comentários não deverão aparecer no ficheiro):
Uma linha de comentários (mesmo que vazia)

nº_de_entradas_do_circuito nº_de_saídas_do_circuito
nº_de_portas

// Lista das portas:

// Porta 0:
nome_da_porta nº_de_entradas nº_de_saídas
    // Lista das ligações às entradas da porta 0, por ordem:
    nº_da_porta nº_da_saída_dessa_porta // entrada 0
    nº_da_porta nº_da_saída_dessa_porta // entrada 1
    // ...
    nº_da_porta nº_da_saída_dessa_porta // entrada nº_de_entradas - 1

// Porta 1:
nome_da_porta nº_de_entradas nº_de_saídas
    // Lista das ligações às entradas da porta 1, por ordem:
    nº_da_porta nº_da_saída_dessa_porta // entrada 0
    nº_da_porta nº_da_saída_dessa_porta // entrada 1
    // ...
    nº_da_porta nº_da_saída_dessa_porta // entrada nº_de_entradas - 1

// ...

// Porta nº_de_portas - 1:
nome_da_porta nº_de_entradas nº_de_saídas
    // Lista das ligações às entradas da porta nº_de_portas - 1, por ordem:
    nº_da_porta nº_da_saída_dessa_porta // entrada 0
    nº_da_porta nº_da_saída_dessa_porta // entrada 1
    // ...
    nº_da_porta nº_da_saída_dessa_porta // entrada nº_de_entradas - 1

// Lista das ligações às saídas do circuito, por ordem:
nº_da_porta nº_da_saída_dessa_porta // saída 0 do circuito
nº_da_porta nº_da_saída_dessa_porta // saída 1 do circuito
// ...
nº_da_porta nº_da_saída_dessa_porta // saída nº_de_saídas_do_circuito - 1 do circuito

Notas:
  1. Todas as portas, entradas e saídas são numeradas a partir de zero (0).
  2. O nome da porta poderá ser AND, NAND, OR, NOR, XOR, NOT, ZERO, ONE, SHOW ou LCD (sempre em maiúsculas), correspondentes às descrições da secção anterior.  Qualquer outro nome deverá ser interpretado como o nome de um ficheiro de configuração de um circuito lógico a ser utilizado dentro do circuito lógico em causa (ver exemplos abaixo).
  3. O número de entradas e saídas das portas tem de ser sempre especificado e lido, mesmo que a porta em causa tenha um número fixo de entradas e/ou saídas (e.g., numa porta NOT).
  4. Uma entrada de uma porta pode vir das entradas do circuito.  Para o indicar, o nº_da_porta dado na ligação em causa deve ser igual ao número total de portas no circuito (nº_de_portas), sendo nesse caso nº_da_saída_dessa_porta o número da entrada do circuito desejada.
  5. Com excepção do caso apresentado na nota anterior, a entrada de uma porta só pode estar ligada a saídas de portas especificadas anteriormente, i.e., com um número menor.  Isto permite que a simulação do circuito seja muito, mas mesmo muito mais simples, pois as portas podem ser simuladas pela ordem da especificação!
O circuito que implementa a disjunção exclusiva à custa das portas AND, OR e NOT (ver figura acima) pode ser especificado por um ficheiro de nome oux contendo:
Circuito que implementa o ou exclusivo à custa de AND, OR e NOT:

2 1
5

NOT 1 1
    5 1

NOT 1 1
    5 0

AND 2 1
    5 0
    0 0

AND 2 1
    1 0
    5 1

OR 2 1
    2 0
    3 0

4 0

O circuito que implementa uma disjunção exclusiva de três entradas e inclui uma pseudo-porta para depuração do circuito pode ser especificado por um ficheiro de nome oux3 contendo:
Circuito que implementa o ou exclusivo de três entradas:

3 1
3

oux 2 1
    3 0
    3 1

SHOW 1 0
    0 0

oux 2 1
    0 0
    3 2

2 0

2  Interface do programa

O programa desenvolvido deverá poder ser invocado (na consola) como se segue.  A negrito as entradas do utilizador, e a itálico o pronto do computador:
a?????@mercurio ~...?????> circuito
circuito - um simulador de circuitos lógicos.
Utilização:
        circuito ficheiro [padrão]
onde:
        ficheiro - nome do ficheiro contendo especificação do circuito.
        padrão - sequência de 0 e 1 com tantos dígitos quantas as entradas
        do circuito.  Qualquer caracter diferente de 0 é considerado 
        representar o dígito 1.
a?????@mercurio ~...?????> circuito oux 11
Circuito oux: 2 × 1
Entradas: 11
Saídas: 0
a?????@mercurio ~...?????> circuito oux3 110
Circuito oux3: 3 × 1
Entradas: 110
0
Saídas: 0
a?????@mercurio ~...?????> circuito somador-8-bits-LCD 1000001010111100
Circuito somador-8-bits-LCD: 16 × 0
Entradas: 1000001010111100
    _  _ 
  | _||_ 
  | _||_ 
Saídas:
Isto é, se o programa for invocado sem argumentos de linha de comando, deve escrever uma mensagem de ajuda.  Se for invocado com argumentos, o primeiro corresponde ao nome do ficheiro de configuração do circuito a simular e o segundo ao padrão de bits a passar-lhe como entrada (se existir).  Nesse caso o programa começa por ler a especificação do circuito, escreve o nome do circuito e o seu número de entradas e saídas, escreve as entradas, simula o circuito (a simulação pode escrever no ecrã se incluir directa ou indirectamente pseudo-portas SHOW ou LCD), e finalmente escreve as saídas.

Os exemplos acima usam os ficheiros de configuração oux e oux3 (ver acima neste enunciado) e o ficheiro de configuração somador-8-bits-LCD, a desenvolver pelos alunos (ver mais abaixo).

3  Implementação

3.1  Lendo argumentos de comando de linha e usando a classe string

Tal como os outros comandos Linux, como o cp (copy) etc., também os programas escritos em C++ aceitam argumentos de linha de comandos.  Suponha que o seguinte programa era compilado e que o ficheiro executável (linguagem máquina) correspondente se chama testa-argumentos.
#include <iostream>

// Para se poder usar a classe string, que serve para manipular cadeias de caracteres (texto):
#include <string>

using namespace std;

int main(int numero_de_argumentos, char* argumentos[])
{
    if(numero_de_argumentos <= 0)
        cout << "Estranho!  Não deveria acontecer!" << endl;
    else {
        string argumento = argumentos[0];
        cout << "O nome do programa é: " << argumento << '.' << endl;
        for(int i = 1; i != numero_de_argumentos; ++i) {
            argumento = argumentos[i];
            cout << "O argumento " << i << " é " << argumento << '.'
                 << endl;
        }
        cout << "O último argumento aos pedacinhos é:" << endl;
        for(string::size_type i = 0; i != argumento.size(); ++i)
            cout << argumento[i] << endl;
    }
}

A execução do programa resultaria em (a negrito as entradas do utilizador, e a itálico o pronto do computador):
a?????@mercurio ~...?????> testa-argumentos
O nome do programa é: testa-argumentos.
O último argumento aos pedacinhos é:
t
e
s
t
a
-
a
r
g
u
m
e
n
t
o
s
a?????@mercurio ~...?????> testa-argumentos 1 dois 34
O nome do programa é: testa-argumentos.
O argumento 1 é 1.
O argumento 2 é dois.
O argumento 3 é 34.
O último argumento aos pedacinhos é:
3
4
O programa exemplifica também uma utilização simples da classe string.

Nota: quando executar o programa em modo de depuração pode passar argumentos de linha de comando após o comando r:

(gdb) r 1 dois 34

3.2  Abrindo canais para leitura de ficheiros

Depois de ser fazer #include <iostream> há (pelo menos) três canais que ficam estabelecidos: cin, cout e cerr.  O primeiro é um canal de entrada e está normalmente ligado ao teclado.  O segundo é um canal de saída e está normalmente associado ao ecrã (ou à janela da consola de comandos...).  O terceiro difere do segundo em pouco, mas deve ser usado para escrever mensagens de erro.

É possível abrir canais de leitura (entrada) e escrita (saída) ligados a ficheiros no disco do computador.  Para isso é necessário fazer #include <fstream>, e definir variáveis dos tipos ifstream (para leitura) e ofstream (para escrita), passando o nome do ficheiro ao seu construtor.  O nome do ficheiro deve ser passado na forma de uma cadeia de caracteres clássica do C++ (i.e., uma matriz de caracteres com um terminador especial), e não uma string.  A abertura de um canal de escrita para um ficheiro é destrutiva: se existir o ficheiro é esvaziado imediatamente.  Os canais ligados a ficheiros podem ser lidos ou escritos como os três canais pré-estabelecidos já referidos, usando por exemplo os operadores de extracção >> e inserção <<.

Por exemplo, o próximo programa lê um ficheiro (notas1) consistindo numa sequência de linhas contendo um número de aluno e duas notas e produz um ficheiro consistindo numa sequência semelhante, mas com a média das notas (arredondada para cima):

#include <fstream>
#include <string>

using namespace std;

int main()
{
    // Guardar nomes dos ficheiros em string:
    string nome_entrada = "notas1";
    string nome_saida = "notas2";

    // Abertura do canal de entrada (usa-se a função membro string::c_str() para se obter
    // o nome do ficheiro na forma de uma cadeia de caracteres clássica):
    ifstream entrada(nome_entrada.c_str());

    // Quando interpretado como um bool, um canal tem valor true se estiver  estabelecido e
    // tudo tiver corrido bem até então:
    if(!entrada) {
        cerr << "O ficheiro '" << nome_entrada << "' não parece existir!"
             << endl;
        return 1;
    }

    ofstream saida(nome_saida.c_str());

    if(!saida) {
        cerr << "O ficheiro '" << nome_saida
             << "' não pôde ser criado/esvasiado!" << endl;
        return 1;
    }

    int numero, nota1, nota2;
    while(entrada >> numero >> nota1 >> nota2)
        // A guarda deste ciclo são três operações de extracção.  Cada uma devolve (uma referência
        // para) o canal de entrada.  O canal devolvido pela última operação é interpretado como
        // um bool pelo while.  Assim, logo que a leitura falhar, presumivelmente por se ter
        // atingido o fim do ficheiro de entrada, o ciclo termina.
        saida << ' ' << numero << ' ' << (nota1 + nota2 + 1) / 2 << endl;

    // Os canais são fechados automaticamente quando a função main() termina.
}

3.3  Classes obrigatórias

Deverão existir (pelo menos) três classes no seu programa: LCD (desenvolvida no Problema 3), Circuito e Porta.

A classe Circuito deve suportar as seguintes operações:

  1. Um construtor (o único) que recebe o nome do ficheiro de configuração do circuito (da classe string) como argumento (para converter uma string numa cadeia de caracteres clássica do C++ use a função membro string::c_str()).  Deve ler o ficheiro de configuração e construir as estruturas de dados internas que o representam (usando a classe Porta para representar cada porta e a classe modelo vector para guardar o conjunto das portas).  Devem ser verificados todos os possíveis erros no ficheiro de configuração.
  2. Uma função membro vector<bool> simula(const vector<bool>& entradas) que, dado o vector de entradas entradas, simule o circuito e devolva o correspondente vector de saídas.  Se a dimensão do vector de entradas não corresponder ao número de entradas do circuito, o programa deve abortar com uma mensagem de erro.
A classe Porta é usada pela classe Circuito.  Deve suportar as seguintes operações:
  1. Um construtor que recebe o nome da porta (uma string), o número de entradas e o número de saídas.
  2. Uma função membro vector<bool> simula(const vector<bool>& entradas) que, dado o vector de entradas entradas, simule a porta lógica e devolva o correspondente vector de saídas.  Se a dimensão do vector de entradas não corresponder ao número de entradas da porta, o programa deve abortar com uma mensagem de erro.

3.4  Programa de teste

Antes de desenvolver o programa completo desenvolva o essencial das classes Porta (considere primeiro apenas as portas NOT, AND e OR) e Circuito, e teste-as com o programa abaixo.  Depois complete o programa.
#include <iostream>
#include <vector>
...

using namespace std;

... // Definição de classes, funções, procedimentos, etc.

int main()
{
    Circuito circuito("oux");
    vector<bool> e(2);
    e[0] = false;
    e[1] = false;
    vector<bool> r = circuito.simula(e);
    if(r[0])
        cout << "Erro com 0 0!" << endl;
    e[0] = false;
    e[1] = true;
    r = circuito.simula(e);
    if(!r[0])
        cout << "Erro com 0 1!" << endl;
    e[0] = true;
    e[1] = false;
    r = circuito.simula(e);
    if(!r[0])
        cout << "Erro com 1 0!" << endl;
    e[0] = true;
    e[1] = true;
    r = circuito.simula(e);
    if(r[0])
        cout << "Erro com 1 1!" << endl;
}

4  Somador de oito bits

O trabalho inclui o desenvolvimento de um circuito somador-8-bits-LCD com 16 bits de entrada e nenhum bit de saída que mostre através da pseudo-porta LCD o valor hexadecimal da soma dos inteiros sem sinal representados pelos primeiros e últimos 8 bits da entrada (assume-se sempre que o bit mais significativo é o que corresponde à entrada com número mais baixo).

Para o desenvolvimento deste circuito é conveniente seguir os passos abaixo:

  1. Desenvolver um circuito semi-somador (half adder).  Tem duas entradas e duas saídas.  As entradas são somadas e o resultado é colocado na segunda saída, sendo a primeira saída usada para colocar o bit de transporte.
  2. Usando o circuito semi-somador anterior, desenvolver um circuito somador completo (full adder). Tem três entradas e duas saídas.  A primeira entrada é o transporte de uma soma anterior qualquer.  As duas outras entradas devem ser somadas com o transporte e o resultado colocado na segunda saída, sendo a primeira saída usada para colocar o bit de transporte.
  3. Usando o circuito somador completo anterior, desenvolver um circuito somador completo de quatro bits.  Este circuito tem nove entradas e cinco saídas.  A primeira entrada é o transporte de uma soma anterior qualquer.  As restantes entradas correspondem a dois números de quatro bits.  Os dois números e o transporte são somados, colocando-se o transporte (bit mais significativo) na primeira saída e o restante resultado (quatro bits) nas quatro saídas restantes.
  4. Usando o circuito somador completo de quatro bits anterior, desenvolver um circuito semi-somador de oito bits.  Este circuito tem 16 entradas e nove saídas.  As saídas correspondem à soma dos dois números inteiros sem sinal representados pelas entrada.
  5. Usando o circuito semi-somador de oito bits anterior e o circuito conversor de hexadecimal para LCD de sete segmentos fornecido em anexo, fazer o circuito completo.  Note que, como o resultado da soma tem nove bits, necessitará de usar três conversores para LCD de sete segmentos, sendo que num deles as três entradas mais significativas devem ser ligados a uma porta ZERO.
Atenção!  Esta parte do trabalho é a menos importante!  Ataque-a apenas quando tiver o simulador a funcionar sem problemas!

5  Condições de entrega e avaliação

5.1  Condições de entrega

Este trabalho será resolvido em grupo.  A resolução deste trabalho deve ser entregue até segunda-feira, 17 de Janeiro de 2000.  A resolução deve ser entregue pessoalmente a um dos docentes da disciplina e consta de uma disquete, devidamente identificada, contendo apenas os ficheiros onde se encontra o código C++ (extensão .C) e a especificação dos circuitos lógicos a simular (sem extensão).  Estes ficheiros devem também ser enviados via correio electrónico para Manuel.Sequeira@iscte.pt.  Deverá ser entregue também um relatório em papel, usando o modelo publicado para os problemas 2 e 3, e que conterá obrigatoriamente a listagem do código C++ e, opcionalmente, um pequeno texto de no máximo uma página explicando as opções tomadas para a resolução.

A entrega do problema fora do prazo implica a penalização de meio valor por cada dia útil de atraso (i.e., 18 de Janeiro, -0,5 valores; 19 de Janeiro -1 valores; 20 de Janeiro -1,5 valores; 21 de Janeiro -2 valores; 24 de Janeiro -2,5 valores) não se aceitando trabalhos após segunda-feira, 24 de Janeiro de 2000, até às 13:00h.

As datas das orais e das inscrições nas orais serão anunciadas logo que possível.

5.2  Avaliação

A avaliação do trabalho terá em conta não só a correcta execução do programa, mas também, e principalmente, a correcta estruturação dos dados e métodos, funções e procedimentos que compõem o programa e ainda a sua legibilidade.  Valorizar-se-á mais a simplicidade que a eficiência.  Valorizar-se-á também código C++ correctamente comentado (mas não excessivamente, não vale a pena comentar o óbvio).

A nota deste trabalho será dada apenas após uma discussão, individual, com cada um dos elementos do grupo. Nesta discussão qualquer elemento do grupo terá de demonstrar um total conhecimento do programa e ser capaz de operar as alterações que forem pedidas.  Nessa oral poderão também ser feitas perguntas sobre a matéria em geral.  A nota final dependerá não só da qualidade do trabalho, mas também, e principalmente, do conhecimento do mesmo programa e da matéria em geral e da capacidade de resolver problemas em C++ demonstrados nessa discussão.

Quaisquer funcionalidades extra que não tenham sido pedidas no enunciado, tais como menus sofisticados, interfaces com janelas, etc., não serão avaliadas.

Anexos

conversor-hexadecimal-LCD-7-segmentos

Conversor de hexadecimal para LCD 7 de segmentos.
4 7
7
conversor-hexadecimal-LCD-7-segmentos-segmento-0 4 1
        7 0
        7 1
        7 2
        7 3
conversor-hexadecimal-LCD-7-segmentos-segmento-1 4 1
        7 0
        7 1
        7 2
        7 3
conversor-hexadecimal-LCD-7-segmentos-segmento-2 4 1
        7 0
        7 1
        7 2
        7 3
conversor-hexadecimal-LCD-7-segmentos-segmento-3 4 1
        7 0
        7 1
        7 2
        7 3
conversor-hexadecimal-LCD-7-segmentos-segmento-4 4 1
        7 0
        7 1
        7 2
        7 3
conversor-hexadecimal-LCD-7-segmentos-segmento-5 4 1
        7 0
        7 1
        7 2
        7 3
conversor-hexadecimal-LCD-7-segmentos-segmento-6 4 1
        7 0
        7 1
        7 2
        7 3
0 0
1 0
2 0
3 0
4 0
5 0
6 0

conversor-hexadecimal-LCD-7-segmentos-segmento-0

Conversor de hexadecimal para LCD 7 de segmentos (segmento 0).
4 1
9
NOT 1 1
        9 0
NOT 1 1
        9 1
NOT 1 1
        9 2
NOT 1 1
        9 3
XOR 2 1
        9 0
        9 1
OR 3 1
        4 0
        9 2
        3 0
OR 4 1
        9 0
        1 0
        9 2
        9 3
OR 4 1
        0 0
        9 1
        2 0
        3 0
AND 3 1
        5 0
        6 0
        7 0
8 0

conversor-hexadecimal-LCD-7-segmentos-segmento-1

Conversor de hexadecimal para LCD 7 de segmentos (segmento 1).
4 1
10
NOT 1 1
        10 0
NOT 1 1
        10 1
NOT 1 1
        10 2
NOT 1 1
        10 3
AND 2 1
        10 0
        1 0
AND 2 1
        10 0
        10 2
AND 3 1
        0 0
        10 1
        2 0
AND 2 1
        10 1
        3 0
AND 2 1
        2 0
        3 0
OR 5 1
        4 0
        5 0
        6 0
        7 0
        8 0
9 0

conversor-hexadecimal-LCD-7-segmentos-segmento-2

Conversor de hexadecimal para LCD 7 de segmentos (segmento 2).
4 1
10
NOT 1 1
        10 0
NOT 1 1
        10 1
NOT 1 1
        10 2
NOT 1 1
        10 3
AND 2 1
        0 0
        1 0
AND 3 1
        10 0
        2 0
        10 3
AND 3 1
        0 0
        10 2
        10 3
AND 3 1
        0 0
        2 0
        3 0
AND 2 1
        1 0
        3 0
OR 5 1
        4 0
        5 0
        6 0
        7 0
        8 0
9 0

conversor-hexadecimal-LCD-7-segmentos-segmento-3

Conversor de hexadecimal para LCD 7 de segmentos (segmento 3).
4 1
8
NOT 1 1
        8 0
NOT 1 1
        8 1
NOT 1 1
        8 2
NOT 1 1
        8 3
OR 3 1
        8 0
        8 1
        8 2
OR 4 1
        0 0
        1 0
        8 2
        8 3
OR 4 1
        8 0
        1 0
        2 0
        3 0
AND 3 1
        4 0
        5 0
        6 0
7 0

conversor-hexadecimal-LCD-7-segmentos-segmento-4

Conversor de hexadecimal para LCD 7 de segmentos (segmento 4).
4 1
6
NOT 1 1
        6 1
NOT 1 1
        6 3
OR 2 1
        6 0
        1 0
OR 3 1
        6 1
        6 2
        1 0
OR 3 1
        6 0
        0 0
        6 2
AND 3 1
        2 0
        3 0
        4 0
5 0

conversor-hexadecimal-LCD-7-segmentos-segmento-5

Conversor de hexadecimal para LCD 7 de segmentos (segmento 5).
4 1
7
NOT 1 1
        7 0
NOT 1 1
        7 1
NOT 1 1
        7 2
OR 4 1
        7 0
        7 1
        2 0
        7 3
OR 3 1
        0 0
        1 0
        2 0
OR 3 1
        0 0
        1 0
        7 3
AND 3 1
        3 0
        4 0
        5 0
6 0

conversor-hexadecimal-LCD-7-segmentos-segmento-6

Conversor de hexadecimal para LCD 7 de segmentos (segmento 6).
4 1
9
NOT 1 1
        9 0
NOT 1 1
        9 1
NOT 1 1
        9 2
NOT 1 1
        9 3
OR 4 1
        9 0
        1 0
        9 2
        9 3
OR 4 1
        0 0
        9 1
        2 0
        9 3
OR 3 1
        1 0
        2 0
        3 0
OR 4 1
        9 0
        9 1
        9 2
        3 0
AND 4 1
        4 0
        5 0
        6 0
        7 0
8 0