This unit will emulate an IBM compatible AT keyboard. It will receive data via a RS-232 port and transmit using a standard 5 pin DIN connector. The PIC16F84 micro controller, will translate between the ASCII values received from the RS-232 and the keyboard scan codes expected from a standard keyboard.
The user will be able to use one keyboard at the transmitting station to send
information to both the transmitting and receiving PCs.
The emulator is designed to function exactly like a PC keyboard. The main difference being extended keys. Many of the extended keys such as the function keys, do not transmit ASCII data. That is the ASCII codes sent are often the same as those sent by other keys. For this reason alternate keys have been used.
The emulator will interpret CTRL characters as many of these keys. Instead of using function keys 1 through 10 the user will use CTRLk-A, CTRL-B, CTRL-C etc. CTRL-Z has been programmed to act as CTRL-ALT-DEL. This way the user still has the majority of the functions of the standard keyboard.
The MAX232 chip converts the RS-232 signal coming from the COM port of the transmitting system into recognizable logic levels. This is required because of the definition of logic levels used in the protocol. RS-232 states that a logic level of zero may be represented by a voltage level between -25V and -3V, and a logic level of one can be between +3V and +25V. This leaves an undefined region between -3V to +3V.
The transmitting PC sends the ASCII code using RS-232 levels to the MAX232. It is then the job of the MAX232 to translate these levels into a signal recognized by the PIC. The PIC receives this information using one line, RA0. Each ASCII value is received in a serial stream, and assembled into a byte by the PIC.
In transmitting to the receiving system, two lines of the PIC are used. These
lines are both connected directly to the keyboard connector, with both having 4k
pull up resistors. Both default to inputs, becoming outputs only when
transmitting. If they remain outputs when not transmitting it causes the
receiving PC to lock up.
After reading in the data, the PIC assembles each bit received into a one byte package. This package is the ASCII code of the key pressed on the transmitting PC. Both the reading and assembly are done using the following segment of code:
ReceiveNextBit btfss PORTA,RECEIVE goto ReceiveZero bsf STATUS,C goto ShiftIncomingData ReceiveZero bcf STATUS,C ShiftIncomingData rrf keypressed,f call Delay3 call Delay3 decfsz bit_count,f goto ReceiveNextBitThe stop bit has already been detected; therefore the loop executes eight times. (bit_count is loaded with 8) First the RECEIVE is checked to determine its logic level, line 2. The carry bit is set to the same value as the incoming data and then shifted into the keypressed register using the RRF command. Doing this shift eight times has the effect of moving the data from the MSB position to the LSB, with each new bit of data falling in behind the previous one. When the bit_count register hits zero, the PIC stops polling for data thus ignoring the parity and stop bits.
The main hurdle when converting the ASCII values into scan codes is the fact that the ASCII represents characters whereas the keyboard scan codes represent keys. For example the capital letter 'A' has an ASCII value of 41 hex and a scan code of 1C hex. Looking at the small 'a' we see that the ASCII value is 61 hex and the scan code is also 1C hex, the same as the capital letter. When dealing with the scan codes, differentiating between certain characters is done through the shift key. This means that the PIC must determine whether to send the scan code alone or proceeded by a shift code. This is done through a sequence of tests to determine where in the ASCII table the character falls, and if a shift needed or not
This code is transmitted to the receiving PC via RB0 and RB1, using a set frequency and data package pattern. The data is first disassembled using the carry flag and RRF command, the RRF command is used in conjunction with bit set and bit clear. Each time through the loop the LSB of the scan_code register is checked. If a one is detected, the DATABIT of PORTB is set and if a zero is detected, it is cleared, lines 6 and 11. The register is then shifted to the right, causing the LSB to overflow into the carry bit and the next bit becomes the LSB. The loop then repeats beginning with the check of the LSB.
The frequency of approximately 13kHz is taken care of by the call to a set delay. This delay is half of the required time delay. It must be done in this manner because the data must be sent when the clock line is low. By splitting the delay into two chunks it means that PIC can perform tasks such as sending data between each call. Nop's are used to balance out the frequency. Each instruction executed by the PIC while the clock line is either high or low changes the frequency. By using one nop for every instruction used to send the data the frequency remains fairly accurate.
One important aspect of the PIC to PC transmission is the calculation of the parity bit. The keyboard uses odd parity, which means that every piece of data sent must have an odd number of ones. When sending the scan codes, the PIC must also calculate the parity bit. This is done by keeping track of the number of ones sent and XORing the result with FF. Each time a one is sent, the parity register is incremented by one. Depending on the number of ones sent, the LSB of the parity bit will either be 1 or 0. If there is an odd number of ones, it means that the LSB of parity register will be one. When a one is XORed with a one, the result (parity bit) is zero. Similarly if an even number of ones is sent, the LSB of the parity register will be zero. XORed with a one, the zero becomes one. It is crucial that this calculation is correct, since if the parity bit is incorrect the PC will not recognize the code sent.
Upon completion of the transmission, the PIC returns to scanning for a low
pulse on RA0, creating an infinite loop.
Download Code in MPASM format. This is the
final version, with all basic keys as well as some extended keys functioning.
The prototype emulator was tested using two standard PCs, a transmitter and a receiver. The transmitter used Procom Plus to send ASCII data via COM1. (Note: Any program that sends ASCII data may be used.) The receiver was used Notepad (standard version packaged with Windows 95) to display the data and a 5 pin DIN with a PS/2 converter to receive.
On the whole the results were good, with accuracy close to one hundred percent. All letters, numbers and punctuation were sent with no problems. The tests were performed using a typing speed of approximately 45 words per minute. With an average word length of 6 characters, this translates to approximately 4.5 characters per second. Using a clock speed of 4MHz, the PIC is processing one instruction every microsecond, more than adequate to handle even the fastest typist.
Some problems are encountered when extended keys and the mouse are used. Often the extended keys that are not dealt with send the same ASCII values as keys that are dealt with. This means that if a user were to press the HOME key for example they may end up with an 'A'. Similarly, when the mouse is used within the Procom Plus window, it sends ASCII values to the COM port. The result is a string of unpredictable output on the receiving end. These problems are encountered because of the limitations of the ASCII codes and the program used to access and send data via the COM port. By making substitutions and making the user aware of these known problems, the emulator can be used in almost the same manner as a standard PC keyboard.
The one area where the emulator fails is during the boot up procedure. During
a regular system boot up, the PC polls its keyboard connector checking for a
keyboard. Once the PC sends the signal to the keyboard, the keyboard then
replies with an acknowledgement that it is indeed a keyboard. If the PC does not
receive this acknowledgement, the boot up procedure is halted. The emulator is
unable to detect the signal from the PC and therefore unable to send the
acknowledgement. This failure is the result of both inaccurate delays and the
inability to decipher when the PC sends its signal. This problem is partly
solved by the fact that the emulator can indeed send a F1 signal. When the boot
up is halted, it can be restarted by pressing the F1 key. Therefore when the
system halts, the user can press