I am working on a project where I'm reading input from a ps2 keyboard, converting keycodes to ASCII (using the Ps2KeyboardHost library of Steve Benz, which I don't think is related), with the intention of sending the ASCII down a serial port to a computer, read back serial data from the serial port, and then send that data (possibly modified) down another serial port to a line printer. I wrote some code to loop back the two serial ports so that what I write out one should arrive at the other end and get echoed back, and I should read it back on the originating serial port, to make sure that's all working before I go farther. Things seem to be mostly working (leaving aside some flow control problems still to be worked out), but if I put the two serial ports (Serial1 and Serial2) into SERIAL_7E1 at any baud rate I've tried, I get garbled output. Here's the code:
Right now the keyboard input is just triggering the Serial2.println() function, which I was using to try to stress the prototype code.
I am doing the cross-over of RX-TX and RTS-CTS on the RS-232 side of a couple of Sparkfun level shifter boards: https://www.sparkfun.com/products/11189
With SERIAL_7E1, I get something like:
If I switch to SERIAL_8N1 (or SERIAL_8E1 or SERIAL_8N2), the output isn't garbled:
I'm using arduino-1.8.9 and current teensyduino, which I just (re)installed a few days ago.
Code:
#include "ps2_Keyboard.h"
#include "ps2_NeutralTranslator.h"
#include "ps2_SimpleDiagnostics.h"
static const int clockPin = 4;
static const int dataPin = 5;
int unshiftTable[70] = {
0x7F, 0x1B, 0x08, 0x09, 0x0A, 0x20,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
0x2E, 0x0A, 0x2B, 0x2D, 0x2A, 0x2F,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
0x27, 0x2C, 0x2D, 0x2E, 0x2F, -1,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
0x7A, 0x3B, 0x5C, 0x5B, 0x5D, 0x3D
};
int shiftTable[70] = {
0x7F, 0x1B, 0x08, -1, 0x0A, 0x20,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
0x28, 0x21, 0x40, 0x23, 0x24, 0x25, 0x5E, 0x26, 0x2A, 0x28,
0x22, 0x3C, 0x5F, 0x3E, 0x3F, -1,
0x7E, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
0x5A, 0x3A, 0x7C, 0x7B, 0x7D, 0x2B
};
int keycode2ascii(uint16_t c) {
// check for special bits so we can bail
if (c & ~0x607F) {
return -1;
}
if (!(c & 0x2000)) {
if (c & 0x4000) {
return shiftTable[(c & 0x7F) - 0x1A];
} else {
return unshiftTable[(c & 0x7F) - 0x1A];
}
} else {
// handle CTRL
// for CTRL-letter, nuke shift bit
if ((c & 0xFF) >= 0x41 && (c & 0xFF) <= 0x5A) {
c = c & ~0x4000;
}
if (c >= 0x2041 && c <= 0x205A) {
return c & 0x1F;
}
switch (c) {
case 0x6032: // ^@
return 0;
case 0x205D: // ^[
return 0x1B;
case 0x205C: // ^BACKSLASH
return 0x1C;
case 0x205E: // ^]
return 0x1D;
case 0x6036: // ^^
return 0x1E;
case 0x603C: // ^_
return 0x1F;
}
}
return -1;
}
typedef ps2::SimpleDiagnostics<32> Diagnostics;
static Diagnostics diagnostics;
static ps2::Keyboard<dataPin,clockPin,16,Diagnostics> ps2Keyboard(diagnostics);
#define Printer Serial1
#define Computer Serial2
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
ps2Keyboard.begin();
Printer.begin(9600,SERIAL_7E1);
Printer.attachRts(2);
Printer.attachCts(20);
Computer.begin(9600,SERIAL_7E1);
Computer.attachRts(11);
Computer.attachCts(23);
}
static ps2::NeutralTranslator translator;
void loop() {
// diagnostics.setLedIndicator<LED_BUILTIN, ps2::DiagnosticsLedBlink::heartbeat>();
int fromComputer;
int fromPrinter;
if (Computer.available() > 0) {
fromComputer = Computer.read();
Serial.printf("%c",fromComputer);
}
if (Printer.available() > 0) {
fromPrinter = Printer.read();
Printer.write(fromPrinter);
Printer.flush();
// Serial.printf("printer: %c\n",fromPrinter);
}
ps2::KeyboardOutput scanCode = ps2Keyboard.readScanCode();
if (scanCode != ps2::KeyboardOutput::none) {
// Serial.println((byte)scanCode, HEX);
ps2::KeyCode translated = translator.translatePs2Keycode(scanCode);
if (translated != ps2::KeyCode::PS2_NONE) {
int c = keycode2ascii(translated);
if (c >= 0) {
// Serial.printf("0x%04x %02x %c\n",translated,c,c);
// Serial.printf("keyboard: %c\n",c);
// Computer.write(c);
if(Computer.availableForWrite() > 0) {
Computer.println("THIS IS A REALLY LONG STRING");
Computer.flush();
} else {
Serial.printf("cannot write yet\n");
}
}
}
}
}
Right now the keyboard input is just triggering the Serial2.println() function, which I was using to try to stress the prototype code.
I am doing the cross-over of RX-TX and RTS-CTS on the RS-232 side of a couple of Sparkfun level shifter boards: https://www.sparkfun.com/products/11189
With SERIAL_7E1, I get something like:
Code:
01:54:57.370 -> �H�S��S�A���A��Y���NG�S���NG�
01:54:57.569 -> �H�S��S�A���A��Y���NG�S���NG�
01:54:58.067 -> �H�S��S�A���A��Y���NG�S���NG�
01:54:58.134 -> �H�S��S�A���A��Y���NG�S���NG�
01:54:58.233 -> �H�S��S�A���A��Y���NG�S���NG�
If I switch to SERIAL_8N1 (or SERIAL_8E1 or SERIAL_8N2), the output isn't garbled:
Code:
01:56:03.094 -> THIS IS A REALLY LONG STRING
01:56:03.592 -> THIS IS A REALLY LONG STRING
01:56:03.659 -> THIS IS A REALLY LONG STRING
01:56:03.758 -> THIS IS A REALLY LONG STRING
I'm using arduino-1.8.9 and current teensyduino, which I just (re)installed a few days ago.