A continuación un vídeo de prueba con este código, para que observéis el efecto:
Sin teclado físico conectado al mismo tiempo siempre funciona bien, y con éste conectado parece que va bien al principio, pero al cabo de un tiempo comienzan a suceder los efectos extraños... incluso se reinicializa el teclado físico él sólo como se puede apreciar por el apagado y encendido de luces del mismo.
Lo que sí he observado es que sin embargo, en el core de PC/XT, utilizando scancodes del set 1 va perfecto, el tiempo que lo he probado claro. Puede ser debido a que éste set es más simple que el 2, ya que no se utiliza el scancode 0xF0 para liberar la pulsación.
Aquí dejo el código dummy listo para compilar y subir desde el mismo entorno IDE de Arduino, por si lo puede probar alguien que tenga un teclado gomas con arduino o el propio ZXGO+, y un teclado físico al mismo tiempo sin Joy2PS2 de por medio:
Código: Seleccionar todo
#define HI 1
#define LO 0
#define CK1 4
#define CK2 8
#define PS2_PORT PORTC
#define PS2_DDR DDRC
#define PS2_PIN PINC
#define PS2_DAT PC3
#define PS2_CLK PC2
void ps2Mode(uint8_t pin, uint8_t mode)
{
if (mode) { //high
PS2_DDR &= ~_BV(pin); //input (Truco DDR. Como input sin estado, se pone en modo Hi-Z)
}
else { //low
PS2_DDR |= _BV(pin); //output (Truco DDR. Como output, se pone a 0v)
}
}
void ps2Init()
{
//ponemos en alto ambas señales
PS2_PORT &= ~_BV(PS2_DAT); //A 0
PS2_PORT &= ~_BV(PS2_CLK); //A 0
ps2Mode(PS2_DAT, HI);
ps2Mode(PS2_CLK, HI);
}
uint8_t ps2Stat()
{
if (!(PS2_PIN & (1 << PS2_CLK)))
return 1;
if (!(PS2_PIN & (1 << PS2_DAT)))
return 1;
return 0;
}
void sendPS2(unsigned char code)
{
//Para continuar las líneas deben estar en alto
while (ps2Stat());
unsigned char parity = 1;
uint8_t i = 0;
//iniciamos transmisión
ps2Mode(PS2_DAT, LO);
_delay_us(CK1);
ps2Mode(PS2_CLK, LO); //bit de comienzo
_delay_us(CK2);
ps2Mode(PS2_CLK, HI);
_delay_us(CK1);
//enviamos datos
for (i = 0; i < 8; ++i)
{
if (code & (1 << i))
{
ps2Mode(PS2_DAT, HI);
parity = parity ^ 1;
}
else
ps2Mode(PS2_DAT, LO);
_delay_us(CK1);
ps2Mode(PS2_CLK, LO);
_delay_us(CK2);
ps2Mode(PS2_CLK, HI);
_delay_us(CK1);
}
// Enviamos bit de paridad
if (parity)
ps2Mode(PS2_DAT, HI);
else
ps2Mode(PS2_DAT, LO);
_delay_us(CK1);
ps2Mode(PS2_CLK, LO);
_delay_us(CK2);
ps2Mode(PS2_CLK, HI);
_delay_us(CK1);
//Bit de parada
ps2Mode(PS2_DAT, HI);
_delay_us(CK1);
ps2Mode(PS2_CLK, LO);
_delay_us(CK2);
ps2Mode(PS2_CLK, HI);
_delay_us(CK1);
_delay_us(50);
}
void setup() {
// put your setup code here, to run once:
ps2Init();
delay(20000);
}
void loop() {
// put your main code here, to run repeatedly:
sendPS2(0x1C); // Key A
delay(100);
sendPS2(0xF0); // Release
sendPS2(0x1C); // Key A
delay(1000);
}
Para probarlo con el ZXGo+ o teclado arduino basado en el código de neuro, cambiar estos defines por el valor correspondiente:
Código: Seleccionar todo
#define PS2_DAT PC4
#define PS2_CLK PC5