//****************************************************************************// // Library to send PS2 data from a PIC microcontroller to a computer via the // keyboard's PS2 port // // Anton Rieckert // [EMAIL="
[email protected]"]
[email protected][/EMAIL] // [URL]http://www.riecktron.co.za[/URL] //****************************************************************************// Unit PS2_Send; Implementation const lookup_table : array[65] of byte = ( 0x29 , // sp 0x16 , // ! 0x52 , // " 0x26 , // # 0x25 , // $ 0x2E , // % 0x3D , // & 0x52 , // ' 0x46 , // ( 0x45 , // ) 0x3E , // * 0x55 , // + 0x41 , // , 0x4E , // - 0x49 , // . 0x4A , // / 0x45 , // 0 0x16 , // 1 0x1E , // 2 0x26 , // 3 0x25 , // 4 0x2E , // 5 0x36 , // 6 0x3D , // 7 0x3E , // 8 0x46 , // 9 0x4C , // : 0x4C , // ; 0x41 , // < 0x55 , // = 0x49 , // > 0x4A , // ? 0x1E , // @ 0x1C , // A 0x32 , // B 0x21 , // C 0x23 , // D 0x24 , // E 0x2B , // F 0x34 , // G 0x33 , // H 0x43 , // I 0x3B , // J 0x42 , // K 0x4B , // L 0x3A , // M 0x31 , // N 0x44 , // O 0x4D , // P 0x15 , // Q 0x2D , // R 0x1B , // S 0x2C , // T 0x3C , // U 0x2A , // V 0x1D , // W 0x22 , // X 0x35 , // Y 0x1A , // Z 0x54 , // [ 0x5D , // 55 0x5B , // ] 0x36 , // ^ 0x4E , // _ 0x0E); // ' var portaddress : word; ___DATA : byte; ___CLOCK : byte; Function PS2_Send_GetParaty(data : byte) : byte; var i : byte; Begin result := 0; for i := 0 to 7 do Begin If TestBit(data, i) = 1 then inc(result); End; result := result AND %00000001; result := result XOR %00000001; End; Procedure PS2_Send_Data_Low; Begin FSR2Ptr := portaddress; ClearBit(INDF2, ___DATA); // Low FSR2Ptr := portaddress + 9; ClearBit(INDF2, ___DATA); // Output End; Procedure PS2_Send_Clock_Low; Begin FSR2Ptr := portaddress; ClearBit(INDF2, ___CLOCK); // Low FSR2Ptr := portaddress + 9; ClearBit(INDF2, ___CLOCK); // Output End; Procedure PS2_Send_Data_Idle; Begin FSR2Ptr := portaddress + 9; SetBit(INDF2, ___DATA); // Input FSR2Ptr := portaddress; SetBit(INDF2, ___DATA); // Hi End; Procedure PS2_Send_Clock_Idle; Begin FSR2Ptr := portaddress + 9; SetBit(INDF2, ___CLOCK); // Input FSR2Ptr := portaddress; SetBit(INDF2, ___CLOCK); // Hi End; Procedure PS2_Send_Ack; label Error; var i : byte; Begin i := 0; Repeat Begin FSR2Ptr := portaddress; inc(i); if i = 200 then goto Error; End; Until TestBit(INDF2, ___CLOCK) = 0; // Repeat until the computer is ready to send ack Repeat Begin FSR2Ptr := portaddress; inc(i); if i = 200 then goto Error; End; Until TestBit(INDF2, ___DATA) = 0; Repeat Begin FSR2Ptr := portaddress; End; Until TestBit(INDF2, ___CLOCK) = 1; for i := 0 to 8 do Begin Delay_22us; PS2_Send_Clock_Low; Delay_22us; PS2_Send_Clock_Idle; End; Delay_22us; PS2_Send_Data_Idle; Delay_22us; PS2_Send_Clock_Low; Delay_22us; PS2_Send_Clock_Idle; Delay_22us; PS2_Send_Data_Low; Delay_22us; PS2_Send_Clock_Low; Delay_22us; PS2_Send_Clock_Idle; PS2_Send_Data_Idle; Error: End; Procedure PS2_Send_Send(data, par : byte); var i : byte; Begin // Repeat until the computer is ready to read from the keyboard Repeat Begin FSR2Ptr := portaddress; End; Until TestBit(INDF2, ___CLOCK) = 1; // Start to send the start bit Delay_22us; PS2_Send_Data_Low; Delay_22us; PS2_Send_Clock_Low; Delay_22us; PS2_Send_Clock_Idle; // Now send the 8 bit data with LSB first for i := 0 to 7 do Begin // Delay_10us; If TestBit(data, i) = 1 then PS2_Send_Data_Idle else PS2_Send_Data_Low; PS2_Send_Clock_Low; Delay_22us; PS2_Send_Clock_Idle; End; // Send the odd paraty bit Delay_10us; if par = 1 then PS2_Send_Data_Idle else PS2_Send_Data_Low; Delay_22us; PS2_Send_Clock_Low; Delay_22us; PS2_Send_Clock_Idle; // End off with the stop bit Delay_22us; PS2_Send_Data_Idle; Delay_22us; PS2_Send_Clock_Low; Delay_22us; PS2_Send_Clock_Idle; PS2_Send_Ack; PS2_Send_Ack; End; Procedure PS2_Send_Init(var port : byte; data_pin, clock_pin : byte); Begin portaddress := @port; ___DATA := data_pin; ___CLOCK := clock_pin; PS2_Send_Clock_Idle; PS2_Send_Data_Idle; End; Procedure PS2_Send_Out(var data : array[90] of char); var i : byte; temp, par : byte; Begin for i := 0 to length(data) - 1 do Begin // Enter key if data[i] = 13 then Begin PS2_Send_Send($5A, 1); PS2_Send_Send($F0,1); PS2_Send_Send($5A, 1); End else Begin temp := data[i] - 32; // Lower case characters If ((temp > $40) AND (temp < $5E)) then Begin temp := temp - 32; temp := lookup_table[temp]; par := PS2_Send_GetParaty(temp); PS2_Send_Send(temp, par); PS2_Send_Send($F0,1); PS2_Send_Send(temp, par); End else // Upper case characters If (((temp > $1D) AND (temp < $41)) OR (temp < $0C)) OR (temp = $1A) OR (temp = $1C) then //else Begin PS2_Send_Send($12, 1); temp := lookup_table[temp]; par := PS2_Send_GetParaty(temp); PS2_Send_Send(temp, par); PS2_Send_Send($F0,1); PS2_Send_Send(temp, par); PS2_Send_Send($F0, 1); PS2_Send_Send($12, 1); End else // Numbers If ((temp > $09) AND (temp < $1A)) OR (temp = $1D) OR (temp = $1B) then Begin temp := lookup_table[temp]; par := PS2_Send_GetParaty(temp); PS2_Send_Send(temp, par); PS2_Send_Send($F0,1); PS2_Send_Send(temp, par); End; End; End; End; End.