This is a multi-part message in MIME format. ------=_NextPart_000_4331_6588_6c22 Content-Type: text/plain; format=flowed Don't know how much good it'll do you, since it's written in my own peculiar PIC assembly language, but my keyboard code is attached. No warranty, etc etc. m >From: "frax" >Reply-To: "Microcontroller discussion list - Public." >To: "Microcontroller discussion list - Public." >Subject: Re: [PIC] Single-chip PS/2 Keyboard interface >Date: Sun, 13 Feb 2005 11:46:14 +0100 > >Michael and Barry, if you're willing to share your code please do. >Im working on a PS2 project, only reading no writing, and have completed my >PS2 reading code and was just about to convert it to an IRQ version. > >/frax > ------=_NextPart_000_4331_6588_6c22 Content-Type: text/plain; name="kbd.aty"; format=flowed Content-Transfer-Encoding: 8bit Content-Disposition: attachment; filename="kbd.aty" include "..\p16f628.aty" config _WDT_OFF & _INTRC_OSC_CLKOUT & _LVP_OFF & _MCLRE_OFF varorg 0x20 byte temp org 0 call Keyboard.Init call Console.Init byte .b do call Keyboard.Rx; w => .b w = .b, ^ 0xaa loop while !STATUS w = 0xed; call Keyboard.Tx; call Keyboard.Rx w = 0x02; call Keyboard.Tx; call Keyboard.Rx // Num Lock LED w = '>'; call Console.Emit call Console.Cr do call Keyboard.Read call Console.Emit loop OutputWInHex: byte .b .b = w w = swap .b, & 0x0f; call .toHex; call Console.Emit w = .b, & 0x0f; call .toHex; call Console.Emit return/// w = .b; goto Console.Emit .toHex: temp = w w = ($+4>>8), => PCLATH w = temp, +=> PCL .table: retlw { "0123456789abcdef" } assert ($-1>>8) == (#.table>>8) Delay: byte .i, .j .i = w clr .j do do nop; nop; nop loop while --.j loop while --.i return //----- Keyboard stuff ---------------------------------------------------------------- // 2003-12-28 trying keyboard // --------+ +-------- // Kbd CLOCK| <--> |RA0 16F628 // DATA| <--> |RA1 // --------+ +-------- // // connector (bottom view) // clock --o o // o o o o -- +5 // / | // gnd data // // 2003-12-28 can read scan codes // 2003-12-30 use clock line to halt transmission while busy // 2003-12-30 trying to implement bidirectional communication // 2004-01-01 partial success; lots of resend messages from kbd // 2004-01-02 trying change of timing: change bits immediately after clock goes low // (instead of waiting for it to go high). Guess what? It works! // Also discovered that the mapping between bits and kbd LEDS isn't // what one might expect. // to do: // ASCII conversion // interrupt-driven? // Communicating with an AT keyboard. // Keyboard.Init -- initialization stuff // Keyboard.Rx -- low-level routine to read a byte from the keyboard // Keyboard.Tx -- low-level routine to send a byte to the keyboard // PORTA bits const CLOCK = 0 const DATA = 1 const LED = 2 Keyboard: // a few useful ASCII codes: const .BS = 8, .CR = 13, .ESC = 27, .TAB = 9 // some made-up codes: const .F1 = 0xF1, .F2 = 0xF2, .F3 = 0xF3, .F4 = 0xF4 const .F5 = 0xF5, .F6 = 0xF6, .F7 = 0xF7, .F8 = 0xF8 const .F9 = 0xF9, .F10 = 0xFA, .F11 = 0xFB, .F12 = 0xFC // useful scan codes: const scLSHIFT = 0x12, scRSHIFT = 0x59, scCAPSLOCK = 0x58 byte .shift // <1> = l.shift, <0> = r.shift byte .capsLock // <1> = caps lock key pressed (for auto-repeat), <0> = caps lock on .Init: w = 7, => CMCON clr PORTA STATUS = 1 bank 1 TRISA = 0, = 0 // = 1 on power-up STATUS_1 = 0 bank 0 clr .shift clr .capsLock return byte .i, .b .Rx: STATUS = 1 bank 1 TRISA = 1 // release clock line; keyboard can send now STATUS_1 = 0 bank 0 call .waitForClockLowThenHigh // start bit w = 8, => .i do // 8 data bits ror .b, <7> = 0 call .waitForClockLow if PORTA == 1 then .b<7> = 1 call .waitForClockHigh loop while --.i w = .b call .waitForClockLowThenHigh // parity bit call .waitForClockLowThenHigh // stop bit STATUS = 1 bank 1 TRISA = 0 // tell keyboard to suspend transmission STATUS_1 = 0 bank 0 return .Tx: // enter with byte to send in W .b = w PORTA = 0 STATUS = 1 bank 1 TRISA = 0 // bring data line low STATUS_1 = 0 bank 0 STATUS = 1 bank 1 TRISA = 1 // release clock line; keyboard can send now STATUS_1 = 0 bank 0 call .waitForClockLow // start bit byte .parity clr .parity w = 8, => .i do // 8 data bits w = .b, & 1 // lsb STATUS = 1 bank 1 if STATUS_1 then TRISA = 0 if !STATUS_1 then TRISA = 1 STATUS_1 = 0 bank 0 w +=> .parity ror .b call .waitForClockHighThenLow loop while --.i w = .parity, & 1 STATUS = 1 bank 1 if STATUS_1 then TRISA = 1 if !STATUS_1 then TRISA = 0 STATUS_1 = 0 bank 0 call .waitForClockHighThenLow // parity bit STATUS = 1 bank 1 TRISA = 1 // release data line STATUS_1 = 0 bank 0 call .waitForClockHighThenLow // stop bit call .waitForClockHighThenLow // ack bit (really ought to test for valid ack) STATUS = 1 bank 1 TRISA = 0 // tell keyboard to suspend transmission STATUS_1 = 0 bank 0 return .waitForClockLowThenHigh: call .waitForClockLow // and fall through .waitForClockHigh: do loop while PORTA != 1 return .waitForClockLow: do loop while PORTA != 0 return .waitForClockHighThenLow: call .waitForClockHigh goto .waitForClockLow .Read: byte .ch, .j do call .Rx; w => .ch w ^= 0xe0 if STATUS then // e0 prefix call .Rx; w => .ch // get next byte w ^= 0xf0 if STATUS then // key up call .Rx // ..eat following byte else // key down w ^= (0xf0 ^ 0x4a) // ..keypad / if STATUS then w = '/'; return endif w ^= (0x4a ^ 0x5a) // ..keypad enter if STATUS then w = .CR; return endif endif continue endif w ^= (0xe0 ^ 0xe1) if STATUS then // e1 prefix: break key w = 7, => .j do call .Rx // eat 7 following bytes: 1477E1F014F077 loop while --.j continue endif w ^= (0xe1 ^ 0xf0) if STATUS then // f0 prefix: key up call .Rx; w => .ch call .testShiftKeysUp else // key down w = .ch; call .testShiftKeysDown w ^= 0 if !STATUS then continue w = .ch .shift = .shift if STATUS then call .scanCodeToAsciiUnshifted else call .scanCodeToAsciiShifted endif if .capsLock<0> then call .convertToUpperCase return endif loop .testShiftKeysDown: w ^= scLSHIFT if STATUS then .shift<1> = 1 w = 1; return endif w ^= (scLSHIFT ^ scRSHIFT) if STATUS then .shift<0> = 1 w = 1; return endif w ^= (scRSHIFT ^ scCAPSLOCK) if STATUS then if .capsLock<1> then goto .1 // if caps lock is auto-repeating, ignore w = 0xed; call Keyboard.Tx; call Keyboard.Rx // command to set LEDs if .capsLock<0> == 0 then .capsLock<0> = 1 w = 0x06 // Num Lock & Caps Lock LEDs on else .capsLock<0> = 0 w = 0x02 // Num Lock LED (Caps Lock off) endif call Keyboard.Tx; call Keyboard.Rx .capsLock<1> = 1 .1: w = 1; return endif w = 0; return .testShiftKeysUp: w ^= scLSHIFT if STATUS then .shift<1> = 0 w ^= (scLSHIFT ^ scRSHIFT) if STATUS then .shift<0> = 0 w ^= (scRSHIFT ^ scCAPSLOCK) if STATUS then .capsLock<1> = 0 return org ($+0xff)&(~0xff) .scanCodeToAsciiUnshifted: w -= 0x84 // 0x84 items in table if STATUS then w = 0xfd return endif w += 0x84, => temp w = ($+4>>8), => PCLATH w = temp, +=> PCL .table1:retlw { 0, .F9, 0, .F5, .F3, .F1, .F2, 0, 0, .F10, .F8, .F6, .F4, .TAB, '`', 0 } retlw { 0, 0, 0, 0, 0, "q1", 0, 0, 0, "zsaw2", 0 } // 10-1f retlw { 0, "cxde43", 0, 0, " vftr5", 0 } // 20-2f retlw { 0, "nbhgy6", 0, 0, 0, "mju78", 0 } // 30-3f retlw { 0, ",kio09", 0, 0, "./l;p-", 0 } // 40-4f retlw { 0, 0, "'", 0, "[=", 0, 0, 0, 0, .CR, "]", 0, "\", 0, 0 } // 50-5f retlw { 0, 0, 0, 0, 0, 0, .BS, 0, 0, "1", 0, "47", 0, 0, 0 } // 60-6f retlw { "0.2568", .ESC, 0, .F11, "+3-*9~", .F12 } // 70-7f retlw { 0, 0, 0, .F7 } // 80-83 assert ($-1>>8) == (#.table1>>8) .convertToUpperCase: w -= 'a' if !STATUS then w += 'a' return endif w -= ('z' + 1 - 'a') if STATUS then w += ('z' + 1) return endif w -= ('a' - 'A' - ('z' + 1)) return org ($+0xff)&(~0xff) .scanCodeToAsciiShifted: w -= 0x84 // 0x84 items in table if STATUS then w = 0xfc return endif w += 0x84, => temp w = ($+4>>8), => PCLATH w = temp, +=> PCL .table2:retlw { 0, .F9, 0, .F5, .F3, .F1, .F2, 0, 0, .F10, .F8, .F6, .F4, .TAB, '~', 0 } retlw { 0, 0, 0, 0, 0, "Q!", 0, 0, 0, "ZSAW@", 0 } // 10-1f retlw { 0, "CXDE$#", 0, 0, " VFTR%", 0 } // 20-2f retlw { 0, "NBHGY^", 0, 0, 0, "MJU&*", 0 } // 30-3f retlw { 0, "?L:P_", 0 } // 40-4f retlw { 0, 0, '"', 0, "{+", 0, 0, 0, 0, .CR, "}", 0, "|", 0, 0 } // 50-5f retlw { 0, 0, 0, 0, 0, 0, .BS, 0, 0, "1", 0, "47", 0, 0, 0 } // 60-6f retlw { "0.2568", .ESC, 0, .F11, "+3-*9", 0, .F12 } // 70-7f retlw { 0, 0, 0, .F7 } // 80-83 assert ($-1>>8) == (#.table2>>8) //----------------------------------------------------------------------------------- include "lcd87.aty" ------=_NextPart_000_4331_6588_6c22 Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit -- http://www.piclist.com PIC/SX FAQ & list archive View/change your membership options at http://mailman.mit.edu/mailman/listinfo/piclist ------=_NextPart_000_4331_6588_6c22--