Close

Basic Release

A project log for EXPS/2

External PS/2 keyboard for Gradiente Expert MSX computer

danjovicdanjovic 04/09/2021 at 04:100 Comments

Basic Release is ready on GitHub, developed on Arduino IDE. I should migrate to plain C code now that I have finished to debug my own PS/2 kebyboard library.

By the way I spent some time to find something that now seems obvious but hard to observe on the logic analyzer that is the rise time of the wired or connections for the PS/2 keyboard:

In a given moment during the beginning of the communication with the keyboard it is necessary to release the CLOCK line then wait for the keybard to pull down the CLOCK line.

When that operation is done on the ps2.h library, there is no explicit delay after releasing the line, because the Arduino (wiring) DigitalWrite command takes a while to process.

  golo(_ps2clk);  _delay_us(300);
  golo(_ps2data); _delay_us(10);
  gohi(_ps2clk);                  // start bit
	while (digitalRead(_ps2clk) == HIGH); /* wait for device to take control of clock */
	

But the line takes some time to recover, 440 ns from  0 to approximately 3.0 Volts (positive threshold for the ATMega328):


To correct that problem I have added a 5 microseconds delay after the release of the CLK line to give such line some time to recover.
  // 2)   Bring the Data line low.
  dropDAT();  _delay_us(10);

  // 3)   Release the Clock line.
  releaseCLK();   _delay_us(5); // give some time for the line to raise

  // 4)   Wait for the device to bring the Clock line low.
  waitCLKfall();

Worth to mention that the functions above are indeed macros dealing directly with the microcontroller registers.

// Hardware definition
#define DAT_DDR  DDRB
#define DAT_PIN  PINB
#define DAT_PORT PORTB
#define DAT_BIT  0

#define CLK_DDR  DDRB
#define CLK_PIN  PINB
#define CLK_PORT PORTB
#define CLK_BIT  1

#define dropDAT()    do { DAT_DDR  |=  (1 << DAT_BIT); DAT_PORT &= ~(1 << DAT_BIT); } while(0)
#define dropCLK()    do { CLK_DDR  |=  (1 << CLK_BIT); CLK_PORT &= ~(1 << CLK_BIT); } while(0)

#define releaseDAT() do {  DAT_DDR  &= ~(1 << DAT_BIT); DAT_PORT |=  (1 << DAT_BIT); } while (0)
#define releaseCLK() do {  CLK_DDR  &= ~(1 << CLK_BIT); CLK_PORT |=  (1 << CLK_BIT); } while (0)

#define readDAT()  (DAT_PIN & (1 << DAT_BIT))
#define readCLK()  (CLK_PIN & (1 << CLK_BIT))
//
#define waitDATrise()  do {} while (!readDAT())
#define waitDATfall()  do {} while ( readDAT())

#define waitCLKrise()  do {} while (!readCLK())
#define waitCLKfall()  do {} while ( readCLK())

Discussions