Closed d-two closed 4 years ago
Whilst this is A WAY to solve the problem I will look at an easier to maintain for other boards. I will look at weekend at updating all versions to use a common define like REQUIRES_PGMSPACE as many implementations not requiring it mess up the const in flash methods. So probably something like in PS2KeyAdvanced.h
#if defined ARDUINO_ARCH_AVR
#define REQUIRES_PGM_SPACE 1
#endif
#if defined ESP8266
#define REQUIRES_PGM_SPACE 1
#endif
~~
Then change other parts to depend on REQUIRES_PGM_SPACE and CPU_FREQ
This way other ESP8xxx or other platforms can be added in one file easily.
Unfortunately things have been exceptionally busy so I will try to look at this over end of month break
Yes it is on my list to do
Been looking more closely at this and I am amazed that a part works on ESP8266 in particular removing the microsecnd delays in sending, which may work on your keyboard or by some quirk of esp8266.
The delay
#if !defined(ESP8266)
// set clock low for 60us
delayMicroseconds( 60 );
#endif
and its other associated delays are required for PS2 protocol to grab control of the PS2 comms to send data and needs to be minimum of 60 microseconds (with other delays is actually nearer 80 microseconds on tests previously here)
I would suggest a retest for ESP8266 by adding ESP8266 to disable interrupt instead.
Removing delays is likely to make it not compliant to PS2 timings
The problem is with delays crash the interrupt on the ESP, the writing is mostly working... But yes at the moment is this not perfect, i work on a solution ;-)
That is why the SAM version for 84MHz ARM uses the detatachInterrupt, which is what you need.
What happens is the change in GPIO being written on Uno/Mega has little effect as they are mainly SLOWinterrupts and operate at 12MHz, and on much faster processors the changesto GPIO (even in write mode) causes more interrupts to be generated to call the same interrupt routine continuously.
I will look at making detachInterrupt being always in the code, so will be slightly slower for Uno/Mega.
The dealys are for creating at least 100 microsecond pulse out on the signal line as this is considered a bi-directional (normally open-drain) signal line. This long pulse tells the keyboard (or mouse if you were using a PS2 mouse) to stop sending and go into receive mode. Quite a few newer keyboards than the original specification can deteect that the signal is being driven by host not keyboard quicker, but that cannot be guaranteed.
Change your #ifdefs so that the your lines are taken out around the delays and also the detachInterrupt so
Original Code
delayMicroseconds( 10 );
#if defined(ARDUINO_ARCH_SAM)
// STOP interrupt handler as Due etc. a lot faster than Uno/Mega
// Setting pin output low will cause interrupt before ready
detachInterrupt( digitalPinToInterrupt( PS2_IrqPin ) );
#endif
// set Clock LOW
digitalWrite( PS2_IrqPin, LOW );
// set clock low for 60us
delayMicroseconds( 60 );
// Set data low - Start bit
digitalWrite( PS2_DataPin, LOW );
// set clock to input_pullup
pininput( PS2_IrqPin );
#if defined(ARDUINO_ARCH_SAM)
// Restart interrupt handler as Due etc. a lot faster than Uno/Mega
attachInterrupt( digitalPinToInterrupt( PS2_IrqPin ), ps2interrupt, FALLING );
// wait clock interrupt to send data
#endif
BECOMES
delayMicroseconds( 10 );
// STOP interrupt handler as Due etc. a lot faster than Uno/Mega
// Setting pin output low will cause interrupt before ready
detachInterrupt( digitalPinToInterrupt( PS2_IrqPin ) );
// set Clock LOW
digitalWrite( PS2_IrqPin, LOW );
// set clock low for 60us
delayMicroseconds( 60 );
// Set data low - Start bit
digitalWrite( PS2_DataPin, LOW );
// set clock to input_pullup
pininput( PS2_IrqPin );
// Restart interrupt handler as Due etc. a lot faster than Uno/Mega
attachInterrupt( digitalPinToInterrupt( PS2_IrqPin ), ps2interrupt, FALLING );
// wait clock interrupt to send data
The interrupts are reenabled at end of bit twiddling
This was the first what i have tested ;-) but for ESP is this not working ...
Problems lie around how interrupts are handled and what type of interrupt are actually supported in ESP8266 as interrupt type depending on hardware and implementation for FALLING could be LOW or CHANGE or something else in reality. So disabling the interrupt earllier and ensuring re-enabled after bit twiddling but before anything is sent should work.
So Old code was
// set pins to outputs and high
digitalWrite( PS2_DataPin, HIGH );
pinMode( PS2_DataPin, OUTPUT );
digitalWrite( PS2_IrqPin, HIGH );
pinMode( PS2_IrqPin, OUTPUT );
delayMicroseconds( 10 );
#if defined(ARDUINO_ARCH_SAM)
// STOP interrupt handler as Due etc. a lot faster than Uno/Mega
// Setting pin output low will cause interrupt before ready
detachInterrupt( digitalPinToInterrupt( PS2_IrqPin ) );
#endif
// set Clock LOW
digitalWrite( PS2_IrqPin, LOW );
// set clock low for 60us
delayMicroseconds( 60 );
// Set data low - Start bit
digitalWrite( PS2_DataPin, LOW );
// set clock to input_pullup
pininput( PS2_IrqPin );
#if defined(ARDUINO_ARCH_SAM)
// Restart interrupt handler as Due etc. a lot faster than Uno/Mega
attachInterrupt( digitalPinToInterrupt( PS2_IrqPin ), ps2interrupt, FALLING );
// wait clock interrupt to send data
#endif
Try instead
// STOP interrupt handler as Due etc. a lot faster than Uno/Mega
// Setting pin output low will cause interrupt before ready
detachInterrupt( digitalPinToInterrupt( PS2_IrqPin ) );
// set pins to outputs and high
digitalWrite( PS2_DataPin, HIGH );
pinMode( PS2_DataPin, OUTPUT );
digitalWrite( PS2_IrqPin, HIGH );
pinMode( PS2_IrqPin, OUTPUT );
delayMicroseconds( 10 );
// set Clock LOW
digitalWrite( PS2_IrqPin, LOW );
// set clock low for 60us
delayMicroseconds( 60 );
// Set data low - Start bit
digitalWrite( PS2_DataPin, LOW );
// set clock to input_pullup
pininput( PS2_IrqPin );
// Restart interrupt handler as Due etc. a lot faster than Uno/Mega
attachInterrupt( digitalPinToInterrupt( PS2_IrqPin ), ps2interrupt, FALLING );
// wait clock interrupt to send data
This should work better let me know
I have test the code but, this is not work also... Just wait for my solution ;-)
I have test many things to fix this... But it won't work to send from the Interrupt the next byte... So, i will make my own small library with a handle function to check the keyboard response and send the next byte from there...
It looks like the implementation or quirks of ESP8266 do not like detachInterupt or the subsequent attach or some other interrupt Controller related issue