21 janeiro 2023

PROLOGICA CP200 NANICO





Em 2017 eu resolvi construir uma réplica de um dos  computadores no qual trabalhei no projeto, quanto estava na engenharia da Prologica, o CP500 - M80C.

A história do CP500 NANICO aqui:

CP500 NANICO


Agora é a vez de me dedicar à construção de outro computador no qual trabalhei no projeto, ainda quando trabalhava no laboratório da Revista Nova Eletrônica, o CP200 NANICO. 

A história do nascimento do CP200 aqui:

HISTORIAS DOS BASTIDORES DA REVISTA NOVA ELETRÔNICA

A história do nascimento do CP500 - M80C aqui:

HISTÓRIAS DA PROLÓGICA


CP200 em sua primeira versão de gabinete (foto Wikpedia)


Como o CP500 NANICO, o CP200 NANICO terá metade do tamanho do original e sua aparência será fiel, na medida do possível. As medida foram feitas a partir de uma informação na internet sobre  as dimensões externas e outras medidas deduzidas a partir de fotos disponíveis na internet.

O coração do CP200 NANICO é um computador Raspberry Pi 3b rodando um emulador SX81 do Sinclair ZX-81, muito completo e poderoso, que pode ser baixado gratuitamente no site Retro Play Neste site ainda há outros emuladores para outras máquinas do passado.


Recursos do emulador SX81

    - Teclado virtual com várias propriedades ajustáveis

    - Barra de controle com ícones para recursos usados ​​regularmente

    - Carregue a caixa de diálogo de arquivo a qualquer momento (não é necessário usar LOAD)

    - Salve o sistema de estado com 9 slots para cada programa

    Opções de tempo de execução, incluindo um configurador de joystick

    - Configurações de RAM de 1 a 4, 16, 32, 48 e 56K

    - Quicksilva, BI-PAK ZON X-81 e som baseado em VSYNC

    - Salvamento de captura de tela usando o formato de imagem bitmap

    - Remapeamento do controle do joystick no emulador

    - Suporte completo para teclado, mouse e joystick

    - 3x dimensionamento comutável em tempo de execução em plataformas suportadas

    - Alternância de janela e tela cheia em plataformas suportadas

    - Resoluções orientadas para retrato, como 240x320

    - A capacidade de executar centralizado em qualquer resolução

    - Suporte de código-fonte para * nix, AmigaOS4 e Win32

    - Potencial máximo de portabilidade, pois requer apenas SDL


Site Retro Play aqui:

Retro Play

Site do emulador SZ81, que pode ser baixado para outras plataformas, incluindo Windows.

sz81.sourceforge.net


Testando o emulador, ainda na bancada.

Este emulador carrega muito rápido no modo Kiosk, sem telas de abertura, indo diretamente para o prompt de comando do ZX-81.


Iniciando o emulador


Raspberry Pi 3B, o coração do CP200 NANICO






CONSTRUÇÃO DO GABINETE

O gabinete está sendo construído com chapa de PVC de 1.5mm de espessura. A chapa de PVC é fácil de trabalhar, podendo ser cortada com uma tesoura e estilete.


Tampa do gabinete, montado em papelão, para conferir as formas

Tampa do gabinete desenhado na chapa da PVC

Laterais já cortadas

Chapa dobrada

Tampa colada nas laterais

Tampa montada ainda sem o berço do teclado e cortes de ventilação

Comparando o tamanho das teclas

Tampa montada, aguardando a furação para as teclas e acabamento final.

Fundo 

Fundo




Iniciando a etapa de acabamento, com as primeiras demãos de primer.








Placa de posicionamento das teclas "Frankenstein". Neste projeto não estou usando nenhuma ferramenta de corte a laser ou fresa, apenas material cortado na mão. Esta placa de posicionamento do teclado veio do projeto do CP500 Nanico, que eu tinha de reserva. Precisei cortar a placa , em acrílico, para posicionar as teclas o mais próximo possível das originais do CP200. Claro, ainda vai muita massa e lixa nesta plaquinha.

Testando alinhamento das teclas


Para a pintura precisei fazer a cor, aproximada, em uma loja de tinta automotiva. Eles preparam a cor de acordo com um catálogo de amostra e envasam em spray. Não é fácil acertar a cor sem ter um gabinete original para comparar com o catálogo, neste caso a comparação foi baseada em fotos. 

Na pintura do CP500 Nanico o código da cor, do fabricante Colorgin, foi indicação de Claudio Henrique Picolo, usada na  restauração de seu CP500 M80 C.

Código da formulação Colorgin



Gabinete já pintado

Detalhe do acabamento

Detalhe do acabamento

Gabinete quase pronto





CONSTRUÇÃO DO TECLADO

A Eletrônica do teclado usará os mesmos componentes e  firmware utilizado no CP500 NANICO, adaptados para a necessidade do simulador do ZX 81. O controlador é um Arduino Pro Micro da Spark Fun.



Tact Switch emborrachado usado no teclado

Esta plaquinha da SparkFun, Arduino Pro-Micro,  é software compatível com com Arduino Leonardo, tem como coração o microcontrolador ATMega 32U4, que possui uma interface USB nativa, podendo-se construir dispositivos HID facilmente, com é o caso do teclado.
Arduino Pro Micro


Site da SparkFun aqui:




Esquema elétrico do teclado

Placa de circuito impresso, lado da solda.

Placa de circuito impresso, lado dos componentes.


O teclado, além das funções das teclas originais do CP 200, tem outras funções adicionais através da combinação de teclas. Isto permite o acesso às funções do emulador que não existem no CP200 original.





O firmware do teclado feito no Arduino IDE
__________________________________________________________________________

// Firmware do teclado do CP200 Nanico (Arduino IDE)
// versão 1.0 - 2023
// By Everaldo R. Lima. www.alldigital.com.br
// Permitida a reprodução para uso pessoal desde que referencie ao autor
// NÃO PERMITIDO PARA USO COMERCIAL
// Possui funções adicionais, consultar o site do projeto

#include "Keyboard.h"
#include <Keypad.h>
int teclasuperior = 0;
int teclasuperior_2 = 0;
int funcao = 0;

int direita = 0;
int esquerda = 0;
int beep = 1;                         // flag de beep ligado
char shiftKey = KEY_LEFT_SHIFT;
char f8 = KEY_ESC;
char previousPressedKey;

//  Keyboard codes
/*
KEY_LEFT_CTRL     0x80
KEY_LEFT_SHIFT    0x81
KEY_LEFT_ALT      0x82
KEY_LEFT_GUI      0x83
KEY_RIGHT_CTRL    0x84
KEY_RIGHT_SHIFT   0x85
KEY_RIGHT_ALT     0x86
KEY_RIGHT_GUI     0x87

Misc keys
KEY_UP_ARROW      0xDA
KEY_DOWN_ARROW    0xD9
KEY_LEFT_ARROW    0xD8
KEY_RIGHT_ARROW   0xD7
KEY_BACKSPACE     0xB2
KEY_TAB           0xB3
KEY_RETURN        0xB0
KEY_MENU          0xED // "Keyboard Application" in USB standard
KEY_INSERT        0xD1
KEY_DELETE        0xD4
KEY_PAGE_UP       0xD3
KEY_PAGE_DOWN     0xD6
KEY_HOME          0xD2
KEY_END           0xD5
KEY_CAPS_LOCK     0xC1
KEY_PRINT_SCREEN  0xCE // Print Screen / SysRq
KEY_SCROLL_LOCK   0xCF
KEY_PAUSE         0xD0 // Pause / Break

Numeric keypad
KEY_NUM_LOCK      0xDB
KEY_KP_SLASH      0xDC
KEY_KP_ASTERISK   0xDD
KEY_KP_MINUS      0xDE
KEY_KP_PLUS       0xDF
KEY_KP_ENTER      0xE0
KEY_KP_1          0xE1
KEY_KP_2          0xE2
KEY_KP_3          0xE3
KEY_KP_4          0xE4
KEY_KP_5          0xE5
KEY_KP_6          0xE6
KEY_KP_7          0xE7
KEY_KP_8          0xE8
KEY_KP_9          0xE9
KEY_KP_0          0xEA
KEY_KP_DOT        0xEB

Function keys
KEY_F1            0xC2
KEY_F2            0xC3
KEY_F3            0xC4
KEY_F4            0xC5
KEY_F5            0xC6
KEY_F6            0xC7
KEY_F7            0xC8
KEY_F8            0xC9
KEY_F9            0xCA
KEY_F10           0xCB
KEY_F11           0xCC
KEY_F12           0xCD
KEY_F13           0xF0
KEY_F14           0xF1
KEY_F15           0xF2
KEY_F16           0xF3
KEY_F17           0xF4
KEY_F18           0xF5
KEY_F19           0xF6
KEY_F20           0xF7
KEY_F21           0xF8
KEY_F22           0xF9
KEY_F23           0xFA
KEY_F24           0xFB
*/

const byte ROWS = 5; // Quatro linhasAverage loops per second = 124518
const byte COLS = 10; // Três colunas
    
char keys [ROWS] [COLS] = {
  {'1', '2', '3', '4', '5', '6', '7', '8', '9', '0'},
  {'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p'},
  {'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 10},
  {shiftKey,'z', 'x', 'c', 'v', 'b', 'n', 'm','.', 32}, // shiftKey sem tecla na matriz
  {'[',']','-','-', '-', '-', '-','-','-','-'}    //  RESET_E / RESET_D 
};

byte rowPins [ROWS] = {10, 16, 14, 15,18}; // linhas do teclado
byte colPins [COLS] = {1, 0, 2, 3, 4, 5, 6, 7, 8, 9}; // colunas do teclado
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

void setup ()
{
  Keyboard.begin();
  keypad.setHoldTime(300);
  pinMode(A3, OUTPUT);                              // BUZZER
  pinMode(A1, INPUT_PULLUP);                        // techa shift
  pinMode(A2, INPUT_PULLUP);                        // techa shift direita
}
//
void loop () {

  if(digitalRead(A1) == LOW){                       // tratamento diferenciado para shift para permitir segurar o shift
      Keyboard.press(shiftKey); 
      teclasuperior = 1;
  }
  else{ 
          if(digitalRead(A2) == HIGH){ 
          Keyboard.release(shiftKey);
          teclasuperior = 0;
        }
  }

   if(digitalRead(A2) == LOW){                       // tratamento diferenciado para shift para permitir segurar o shift
      Keyboard.press(shiftKey); 
      teclasuperior_2 = 1;
  }
  else{ 
        if(digitalRead(A1) == HIGH){ 
          Keyboard.release(shiftKey);
          teclasuperior_2 = 0;
          teclasuperior = 0;
        }
  }
  char key = keypad.getKey();
  
  if (key == shiftKey) 
  {
  teclasuperior = 1;
  }

  if (key == '[') // ( RESET ESQUERDO )
  {
    key = NO_KEY ;
    funcao = 1;
  } 

  // HABILITO E DESABILITO BEEP DO TECLADO QUANDO DOIS SHIFTS SÃO PRESSIONADOS SIMULTANEAMENTE

  if (teclasuperior && teclasuperior_2) 
  {
            beep = (! beep);
            if (beep==1) {
                digitalWrite(A3, 1);              
                delay(20);                        // tempo do beep longo
                digitalWrite(A3, 0);
            }
             delay (500);
  }
 
  KeyState state = keypad.getState();
  if (state == PRESSED && key != NO_KEY) {
    previousPressedKey = key;
    delay(100);
  }
   
  if (state == HOLD) {
    Keyboard.print(previousPressedKey);
    delay(150);
  }
  
  if (key != NO_KEY) {
    if (funcao == 1) {
        switch (key) {

      case ']':                               //  Reset EsqueFUNCAO MAIS RESET DIREITO
          key = KEY_F12 ;                     //  F12 reseta simulador
          if (beep == 1)                      // Beep do teclado
            {
            digitalWrite(A3, 1);              
            delay(20);
            digitalWrite(A3, 0);
            
            }
             break;
case 's':                                     //  FUNCAO MAIS 0
          key = KEY_F10 ;                     //  F10 DESLIGA COMPUTADOR
          if (beep == 1)                      // Beep do teclado
            {
            digitalWrite(A3, 1);              
            delay(1000);
            digitalWrite(A3, 0);
            }
          break; 

        case 'l':                                     //  FUNCAO MAIS 1
          key = KEY_F3 ;                     //  F3 load arquivos
          if (beep == 1)                      // Beep do teclado
            {
            digitalWrite(A3, 1);              
            delay(20);
            digitalWrite(A3, 0);
            }
          break; 

        case 'v':                           //  FUNCAO MAIS 2
          key = KEY_F8 ;                      //  F8 inverte video
          if (beep == 1)                      // Beep do teclado
            {
            digitalWrite(A3, 1);              
            delay(20);
            digitalWrite(A3, 0);
            }
          break; 

        case 'r':                           //  FUNCAO MAIS 3
         
          Keyboard.press(KEY_LEFT_ALT);
          key = 'r' ;                      //  ALT-R muda resolucao
          if (beep == 1)                      // Beep do teclado
            {
            digitalWrite(A3, 1);              
            delay(20);
            digitalWrite(A3, 0);
            }
          break; 
           
       case 'j':                           //  FUNCAO MAIS 3
         
          key = '-' ;                      //  VOLUME MAIS
          if (beep == 1)                      // Beep do teclado
            {
            digitalWrite(A3, 1);              
            delay(20);
            digitalWrite(A3, 0);
            }
          break; 
          
      case 'k':                                 //  
          key = '+' ;                           //  VOLUME NENOS
          if (beep == 1)                        // Beep do teclado
            {
            digitalWrite(A3, 1);              
            delay(20);
            digitalWrite(A3, 0);
            }
          break; 

          case '1':                            //  Load arquivo
          key = KEY_ESC ;                           // ESC
          if (beep == 1)                        // Beep do teclado
            {
            digitalWrite(A3, 1);              
            delay(20);
            digitalWrite(A3, 0);
            }
          break; 

          case 'o':                           //  FUNCAO MAIS 3
          key = KEY_F2 ;                            //  Menu de opções
          if (beep == 1)                      // Beep do teclado
            {
            digitalWrite(A3, 1);              
            delay(20);
            digitalWrite(A3, 0);
            }
          break; 
          case 'b':                           //  liga ou desliga beep do teclado 
          key = NO_KEY ;                      // não envio tecla
          if (beep == 1)                      // 
            {
            beep = 0;
            }
            else
            {
              beep = 1;
            }
                                              //  VOLUME NENOS
          if (beep == 1)                      // Beep do teclado
            {
            digitalWrite(A3, 1);              
            delay(20);
            digitalWrite(A3, 0);
            }
          break; 

         case '5':                           //  
          key = KEY_LEFT_ARROW  ;             //  seta esquerda
          if (beep == 1)                      // Beep do teclado
            {
            digitalWrite(A3, 1);              
            delay(20);
            digitalWrite(A3, 0);
            }
          break; 
          
         case '6':                           //  
          key = KEY_DOWN_ARROW   ;           //  Seta para baixo
          if (beep == 1)                      // Beep do teclado
            {
            digitalWrite(A3, 1);              
            delay(20);
            digitalWrite(A3, 0);
            }
          break; 
          
        case '7':                           //  
          key = KEY_UP_ARROW    ;           //  Seta para cima
          if (beep == 1)                      // Beep do teclado
            {
            digitalWrite(A3, 1);              
            delay(20);
            digitalWrite(A3, 0);
            }
          break; 

        case '8':                           //  
          key = KEY_RIGHT_ARROW    ;       //  Seta para direita
          if (beep == 1)                      // Beep do teclado
            {
            digitalWrite(A3, 1);              
            delay(20);
            digitalWrite(A3, 0);
            }
          break; 
          }
   
   }

   
   Keyboard.press(key);
        if (beep == 1)                       // Beep do teclado
        {
        digitalWrite(A3, 1);              
        delay(1);
        digitalWrite(A3, 0);
        }
        delay(100);                       
   
    if (key != '[') 
      {
        teclasuperior_2 = 0;
        Keyboard.releaseAll();
        funcao = 0;
      }
    }
  
}
_____________________________________________________________________________

Testando o firmware

Gabinete pintado com a placa de posicionamento das teclas. Estas teclas fazem parte do teclado do CP500 NANICO , serão pintadas e adesivadas, assim como a placa de posicionamento.


Comparando o tamanho da tecla com o dedo

Etiqueta da placa do teclado
Placa do teclado com etiqueta



Desenvolvendo o teclado


Construção das teclas


As teclas foram aproveitadas do que restou do material do CP500 NANICO. As inscrições são feitas em etiquetas impressas à laser e depois envernizadas.

As teclas tem as medidas de 6x6mm

Teclas adesivadas

Placa do teclado montada

Teclado já com a eletrônica


Gabinete terminado com o teclado

Testando o teclado




Finalmente, completo!

Já estou sentindo saudades. Ele está acabado e totalmente funcional.

Totalmente funcional!

Suas entranhas

Suas entranhas



Em breve receberá uma unidade de armazenamento
Impressão 3d por
www.donati3d.com.br


O nanico rodando um software de simulador de voo do inicio dos anos 80.


Os dois Nanicos