#include #include #include #include "txrx.c" #define begin { #define end } //define some useful maps to bits #define MOUSE_CLK_OUT PORTC.1 #define MOUSE_CLK_IN PINC.0 #define MOUSE_DATA_OUT PORTC.5 #define MOUSE_DATA_IN PINC.4 #define KEYBOARD_CLK_OUT PORTC.3 #define KEYBOARD_CLK_IN PINC.2 #define KEYBOARD_DATA_OUT PORTC.7 #define KEYBOARD_DATA_IN PINC.6 //define PS/2 data line states #define IDLE 0 #define INHIBIT 1 #define BUSY 2 #define WAIT_FOR_REQUEST 3 #define REQUEST 4 #define POWEROFF 5 // boolean defines #define TRUE 1 #define FALSE 0 // RX defines #define tx_id 163 #define MAX_RX_LENGTH 32 char k; unsigned char my_rx_data[MAX_RX_LENGTH]; #define MOUSE 1 #define KEYBOARD 2 #define LowLetter 0 #define CapLetter 1 #define Number 2 #define Punct 3 //an ascii list of the english letters sorted by frequency (sub 32 to get upper case) //the letters are: e t a i o n s h r d l c u m w f g y p b v k j x q z flash char letter[26] ={101,116,97,111,105,110,115,104,114,100,108,99,117,109,119,102,103,121,112,98,118,107,106,120,113,122}; //numbers : 0 1 2 3 4 5 6 7 8 9 flash char numbers[10] = {48,49,50,51,52,53,54,55,56,57}; //other characters (punctuation) //sorted for frequency: . , : ; ? ! " ' / ( ) * + - = # $ % & flash char punct[19] = {46,44,58,59,63,33,34,39,47,40,41,42,43,45,61,35,36,37,38}; char userMode; //user mode 0 = mouse; 1 = keyboard; char charMode; //charater mode, 0:low lett 1:cap lett 2:numb 3:punc 5:backspace char charLen[4] = {26,26,10,19}; //number of characters available in current mode signed char nextChar; char newChar; signed char stepX, stepY, btnClick; int blinkCount; char bsCount; char key, prev_key; // byte declarations unsigned char mouse_byte_index; unsigned char mouse_transmit_byte; unsigned char mouse_transmit_parity; unsigned char mouse_receive_byte; unsigned char mouse_receive_bit; unsigned char mouse_previous_byte; unsigned char mouse_resend_byte; // clock state machine declarations unsigned char mouse_clock_state; unsigned char mouse_next_clock_state; unsigned char mouse_state; unsigned char mouse_transmit; unsigned char mouse_receive; // mouse packet declarations unsigned char gen_mouse_packet; unsigned int mouse_count; unsigned char mouse_delay; // mouse packet unsigned char mouse_byte; // keyboard packet unsigned char key_byte; // byte declarations unsigned char keyboard_byte_index; unsigned char keyboard_transmit_byte; unsigned char keyboard_transmit_parity; unsigned char keyboard_receive_byte; unsigned char keyboard_receive_bit; unsigned char keyboard_previous_byte; unsigned char keyboard_resend_byte; // clock state machine declarations unsigned char keyboard_clock_state; unsigned char keyboard_next_clock_state; unsigned char keyboard_state; unsigned char keyboard_transmit; unsigned char keyboard_receive; // keyboard packet declarations unsigned char gen_keyboard_packet; unsigned int keyboard_count; unsigned char keyboard_delay; #define RISE 0 #define HIGH 1 #define FALL 2 #define LOW 3 // queue declarations #define QUEUELEN 100 unsigned char mouse_queue[QUEUELEN]; //queue of data sent by keyboard. (first in, first out) unsigned char mouse_queueFull; //indicates if queue is full unsigned char mouse_queueEmpty;//indicates if queue is empty unsigned char mouse_queueIn; //indicates where to put data into queue unsigned char mouse_queueOut; //indicates where to take data out of queue unsigned char keyboard_queue[QUEUELEN]; //queue of data sent by keyboard. (first in, first out) unsigned char keyboard_queueFull; //indicates if queue is full unsigned char keyboard_queueEmpty;//indicates if queue is empty unsigned char keyboard_queueIn; //indicates where to put data into queue unsigned char keyboard_queueOut; //indicates where to take data out of queue // PS/2 Host Command set. #define ERROR 0xFC #define RESET 0xFF #define RESEND 0xFE #define SET_MAKE 0xFD #define SET_MAKE_BREAK 0xFC #define SET_TYPE 0xFB #define SET_ALL_TYPE_MAKE_BREAK 0xFA #define SET_ALL_MAKE 0xF9 #define SET_ALL_MAKE_BREAK 0xF8 #define SET_ALL_TYPE 0xF7 #define SET_DEFAULT 0xF6 #define DIS_DATA_REPORT 0xF5 #define EN_DATA_REPORT 0xF4 #define SET_SAMPLE_RATE 0xF3 #define GET_DEVICE_ID 0xF2 #define SET_REMOTE_MODE 0xF0 // for mouse #define SET_SCAN_CODE 0xF0 // for keyboard #define SET_WRAP_MODE 0xEE // for mouse #define ECHO 0xEE // for keyboard #define SET_LED 0xED #define RESET_WRAP_MODE 0xEC #define READ_DATA 0xEB #define SET_STREAM_MODE 0xEA #define STATUS_REQ 0xE9 #define SET_RES 0xE8 #define SET_SCALING21 0xE7 #define SET_SCALING11 0xE6 #define ACK 0xFA #define SELF_TEST_PASS 0xAA #define INIT 0x00 #define SCALING21 0x02 // mouse declarations unsigned char mouse_deviceID; unsigned char mouse_data_reporting; unsigned char mouse_sample_rate; unsigned char mouse_scaling; // 0 = 1:1, 1 = 2:1 unsigned char mouse_resolution; unsigned char mouse_waiting_for_sample_rate; unsigned char mouse_waiting_for_resolution; // keyboard declarations unsigned char keyboard_deviceID[2]; unsigned char keyboard_data_reporting; unsigned char keyboard_waiting_for_sample_rate; unsigned char keyboard_waiting_for_led; // Function prototypes void initialize(void); //all the usual mcu stuff // function prototypes unsigned char mouse_queuePut(unsigned char); unsigned char mouse_queueGet(void); void mouse_process_command(unsigned char); unsigned char keyboard_queuePut(unsigned char); unsigned char keyboard_queueGet(void); void keyboard_process_command(unsigned char); unsigned char getParity(unsigned char); // mouse function void mouse_init(void); void mouse_send(signed char, signed char, unsigned char, unsigned char, unsigned char); //keyboard function void keyboard_init(void); void keyboard_send(char,char); void setMode(char); // this interrupt should run every 20us or 1/4 period of the clock interrupt [TIM0_COMP] void timer0_overflow(void) begin if (mouse_queueEmpty == TRUE) mouse_count++; if (mouse_count >= 500) // 100 samples a second begin gen_mouse_packet = TRUE; mouse_count = 0; end if (mouse_delay > 0) mouse_delay--; // state machine for transmitting a byte to Host if (mouse_transmit && mouse_delay == 0) begin // update the next clock state mouse_clock_state = mouse_next_clock_state; // do the appropriate command based on the state of the clock switch (mouse_clock_state) begin case RISE: // start or end a byte transmission switch (mouse_byte_index) begin case 0: // get a new byte to be xmitted if (mouse_queueEmpty == FALSE) // get data off the queue to be xmitted begin mouse_transmit_byte = mouse_queueGet(); mouse_transmit_parity = getParity(mouse_transmit_byte); //delay_us(150); // used to wait until host is ready mouse_delay = 7; end break; case 11: // finished transmission mouse_transmit = FALSE; // transmit finished mouse_byte_index = 0; // reset byte index break; default: break; end if (mouse_delay == 0) begin // set the new clock state MOUSE_CLK_OUT = 1; mouse_next_clock_state = HIGH; break; // end of RISE end case HIGH: // can begin writing data to host // state machine ensure we transmit the correct bit from the PS/2 byte switch (mouse_byte_index) begin case 0: MOUSE_DATA_OUT = 0; break; case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: MOUSE_DATA_OUT = mouse_transmit_byte & 0x01; mouse_transmit_byte = mouse_transmit_byte >> 1; break; case 9: MOUSE_DATA_OUT = mouse_transmit_parity; break; case 10: MOUSE_DATA_OUT = 1; break; default: break; end // update the byte index mouse_byte_index++; // update the clock state mouse_next_clock_state = FALL; break; // end of HIGH case FALL: // clock transitions to low MOUSE_CLK_OUT=0; // pull the clock to 0 mouse_next_clock_state = LOW; // set the next clock state to low break; // end of FALL case LOW: // clock is low - nothing happens here mouse_next_clock_state = RISE; // next clock state is rising break; // end of RISE end end if (mouse_receive) begin // get the next clock state mouse_clock_state = mouse_next_clock_state; switch (mouse_clock_state) begin case RISE: // all receiving done on the rising edge of the clock MOUSE_CLK_OUT = 1; // get the bit off the data line // and place into the receive_byte if (mouse_byte_index >=0 && mouse_byte_index < 8) begin mouse_receive_bit = MOUSE_DATA_IN; mouse_receive_byte = ((mouse_receive_bit & 0x01) << mouse_byte_index) | mouse_receive_byte; end // update variables for the next state if (mouse_byte_index < 11) begin mouse_next_clock_state = HIGH; mouse_byte_index++; end break; case HIGH: switch (mouse_byte_index) begin case 10: MOUSE_DATA_OUT = 0; break; case 11: MOUSE_DATA_OUT = 1; // send ACK // terminate receive operation and reset mouse_receive = FALSE; mouse_byte_index = 0; // process the received command mouse_process_command(mouse_receive_byte); mouse_receive_byte = 0; mouse_receive_bit = 0; break; default: break; end mouse_next_clock_state = FALL; break; case FALL: // hosts transmits on the falling edge MOUSE_CLK_OUT = 0; mouse_next_clock_state = LOW; break; case LOW: mouse_next_clock_state = RISE; break; end end switch (mouse_state) begin case IDLE: // enter inhibt state if clock is trying to be pulled // low by host when device is trying to make high if ((mouse_clock_state == HIGH || mouse_clock_state == RISE) && MOUSE_CLK_IN == 0) // host trying to pull CLK low! begin mouse_state = INHIBIT; // go to the INHIBIT state mouse_next_clock_state = LOW; // turn off the clock mouse_transmit = FALSE; // mouse can no longer transmit mouse_receive = FALSE; // mouse can no longer receive end else // check if mouse needs to be in BUSY state -- anything on queue? begin if(mouse_queueEmpty == FALSE) begin mouse_state = BUSY; // transition to busy state mouse_transmit = TRUE; // allow mouse to transmit mouse_receive = FALSE; // make sure we don't receive! mouse_next_clock_state = RISE; // turn on the clock mouse_byte_index = 0; // reset the byte index for transmit end else // otherwise we should just stay in IDLE begin mouse_state = IDLE; end end break; case BUSY: // again check if host is trying to inhibt // by pulling the clock low when it should be high if ((mouse_clock_state == HIGH || mouse_clock_state == RISE) && MOUSE_CLK_IN == 0) begin mouse_state = INHIBIT; // go to the INHIBIT state mouse_next_clock_state = LOW; // turn off the clock mouse_transmit = FALSE; // mouse can no longer transmit mouse_receive = FALSE; // mouse can no longer receive end else // go back to IDLE if mouse has nothing to send or receive begin if ( !(mouse_transmit|| mouse_receive) ) mouse_state = IDLE; else mouse_state = BUSY; // otherwise stay BUSY end break; case INHIBIT: // if we enter the INHIBIT state before we finish sending // a byte, we should save the byte & resend! if(mouse_byte_index > 0 && mouse_byte_index < 10) begin mouse_resend_byte = TRUE; end // reset the byte index mouse_byte_index = 0; // check for REQUEST state // first, the host must release the CLK if (MOUSE_CLK_IN == 1) begin mouse_state = WAIT_FOR_REQUEST; // next, we check for DATA line to go low end else // stay in INHIBIT state begin mouse_state = INHIBIT; mouse_transmit = FALSE; mouse_receive = FALSE; mouse_next_clock_state = LOW; end break; case WAIT_FOR_REQUEST: // check if the data line has gone low if(MOUSE_DATA_IN == 0) begin mouse_state = REQUEST; // go to REQUEST state mouse_next_clock_state = RISE; // turn on the clock end else begin // we must be in the IDLE state because both // CLK & DATA are high mouse_state = IDLE; mouse_next_clock_state = RISE; end break; case REQUEST: // get ready to receive data from the host mouse_transmit = FALSE; mouse_receive = TRUE; mouse_byte_index = 0; mouse_next_clock_state = FALL; // host sends data on falling edge // In case we get another INHIBIT state if ((mouse_clock_state == HIGH || mouse_clock_state == RISE) && MOUSE_CLK_IN == 0) begin mouse_state = INHIBIT; mouse_next_clock_state = LOW; mouse_transmit = FALSE; mouse_receive = FALSE; end else if (mouse_transmit || mouse_receive) // go to BUSY state to process data mouse_state = BUSY; else mouse_state = REQUEST; // otherwise stay in REQUEST until data comes break; end//end switch if (keyboard_queueEmpty == TRUE) keyboard_count++; if (keyboard_count >= 15000) // 5 samples a second begin gen_keyboard_packet = TRUE; keyboard_count = 0; end if (keyboard_delay > 0) keyboard_delay--; // state machine for transmitting a byte to Host if (keyboard_transmit && keyboard_delay == 0) begin // update the next clock state keyboard_clock_state = keyboard_next_clock_state; // do the appropriate command based on the state of the clock switch (keyboard_clock_state) begin case RISE: // start or end a byte transmission switch (keyboard_byte_index) begin case 0: // get a new byte to be xmitted if (keyboard_queueEmpty == FALSE) // get data off the queue to be xmitted begin keyboard_transmit_byte = keyboard_queueGet(); keyboard_transmit_parity = getParity(keyboard_transmit_byte); //delay_us(150); // used to wait until host is ready keyboard_delay = 7; end break; case 11: // finished transmission keyboard_transmit = FALSE; // transmit finished keyboard_byte_index = 0; // reset byte index break; default: break; end if (keyboard_delay == 0) begin // set the new clock state KEYBOARD_CLK_OUT = 1; keyboard_next_clock_state = HIGH; break; // end of RISE end case HIGH: // can begin writing data to host // state machine ensure we transmit the correct bit from the PS/2 byte switch (keyboard_byte_index) begin case 0: KEYBOARD_DATA_OUT = 0; break; case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: KEYBOARD_DATA_OUT = keyboard_transmit_byte & 0x01; keyboard_transmit_byte = keyboard_transmit_byte >> 1; break; case 9: KEYBOARD_DATA_OUT = keyboard_transmit_parity; break; case 10: KEYBOARD_DATA_OUT = 1; break; default: break; end // update the byte index keyboard_byte_index++; // update the clock state keyboard_next_clock_state = FALL; break; // end of HIGH case FALL: // clock transitions to low KEYBOARD_CLK_OUT=0; // pull the clock to 0 keyboard_next_clock_state = LOW; // set the next clock state to low break; // end of FALL case LOW: // clock is low - nothing happens here keyboard_next_clock_state = RISE; // next clock state is rising break; // end of RISE end end if (keyboard_receive) begin // get the next clock state keyboard_clock_state = keyboard_next_clock_state; switch (keyboard_clock_state) begin case RISE: // all receiving done on the rising edge of the clock KEYBOARD_CLK_OUT = 1; // get the bit off the data line // and place into the receive_byte if (keyboard_byte_index >=0 && keyboard_byte_index < 8) begin keyboard_receive_bit = KEYBOARD_DATA_IN; keyboard_receive_byte = ((keyboard_receive_bit & 0x01) << keyboard_byte_index) | keyboard_receive_byte; end // update variables for the next state if (keyboard_byte_index < 11) begin keyboard_next_clock_state = HIGH; keyboard_byte_index++; end break; case HIGH: switch (keyboard_byte_index) begin case 10: KEYBOARD_DATA_OUT = 0; break; case 11: KEYBOARD_DATA_OUT = 1; // send ACK // terminate receive operation and reset keyboard_receive = FALSE; keyboard_byte_index = 0; // process the received command keyboard_process_command(keyboard_receive_byte); keyboard_receive_byte = 0; keyboard_receive_bit = 0; break; default: break; end keyboard_next_clock_state = FALL; break; case FALL: // hosts transmits on the falling edge KEYBOARD_CLK_OUT = 0; keyboard_next_clock_state = LOW; break; case LOW: keyboard_next_clock_state = RISE; break; end end switch (keyboard_state) begin case IDLE: // enter inhibt state if clock is trying to be pulled // low by host when device is trying to make high if ((keyboard_clock_state == HIGH || keyboard_clock_state == RISE) && KEYBOARD_CLK_IN == 0) // host trying to pull CLK low! begin keyboard_state = INHIBIT; // go to the INHIBIT state keyboard_next_clock_state = LOW; // turn off the clock keyboard_transmit = FALSE; // keyboard can no longer transmit keyboard_receive = FALSE; // keyboard can no longer receive end else // check if keyboard needs to be in BUSY state -- anything on queue? begin if(keyboard_queueEmpty == FALSE) begin keyboard_state = BUSY; // transition to busy state keyboard_transmit = TRUE; // allow keyboard to transmit keyboard_receive = FALSE; // make sure we don't receive! keyboard_next_clock_state = RISE; // turn on the clock keyboard_byte_index = 0; // reset the byte index for transmit end else // otherwise we should just stay in IDLE begin keyboard_state = IDLE; end end break; case BUSY: // again check if host is trying to inhibt // by pulling the clock low when it should be high if ((keyboard_clock_state == HIGH || keyboard_clock_state == RISE) && KEYBOARD_CLK_IN == 0) begin keyboard_state = INHIBIT; // go to the INHIBIT state keyboard_next_clock_state = LOW; // turn off the clock keyboard_transmit = FALSE; // keyboard can no longer transmit keyboard_receive = FALSE; // keyboard can no longer receive end else // go back to IDLE if keyboard has nothing to send or receive begin if ( !(keyboard_transmit|| keyboard_receive) ) keyboard_state = IDLE; else keyboard_state = BUSY; // otherwise stay BUSY end break; case INHIBIT: // if we enter the INHIBIT state before we finish sending // a byte, we should save the byte & resend! if(keyboard_byte_index > 0 && keyboard_byte_index < 10) begin keyboard_resend_byte = TRUE; end // reset the byte index keyboard_byte_index = 0; // check for REQUEST state // first, the host must release the CLK if (KEYBOARD_CLK_IN == 1) begin keyboard_state = WAIT_FOR_REQUEST; // next, we check for DATA line to go low end else // stay in INHIBIT state begin keyboard_state = INHIBIT; keyboard_transmit = FALSE; keyboard_receive = FALSE; keyboard_next_clock_state = LOW; end break; case WAIT_FOR_REQUEST: // check if the data line has gone low if(KEYBOARD_DATA_IN == 0) begin keyboard_state = REQUEST; // go to REQUEST state keyboard_next_clock_state = RISE; // turn on the clock end else begin // we must be in the IDLE state because both // CLK & DATA are high keyboard_state = IDLE; keyboard_next_clock_state = RISE; end break; case REQUEST: // get ready to receive data from the host keyboard_transmit = FALSE; keyboard_receive = TRUE; keyboard_byte_index = 0; keyboard_next_clock_state = FALL; // host sends data on falling edge // In case we get another INHIBIT state if ((keyboard_clock_state == HIGH || keyboard_clock_state == RISE) && KEYBOARD_CLK_IN == 0) begin keyboard_state = INHIBIT; keyboard_next_clock_state = LOW; keyboard_transmit = FALSE; keyboard_receive = FALSE; end else if (keyboard_transmit || keyboard_receive) // go to BUSY state to process data keyboard_state = BUSY; else keyboard_state = REQUEST; // otherwise stay in REQUEST until data comes break; end//end switch end //insert data into queue. Return 1 if queue full, or 0 if inserted data sucessfully unsigned char mouse_queuePut(unsigned char d) begin if (mouse_queueFull==TRUE) //check if queue is full return(TRUE); mouse_queue[mouse_queueIn]=d; //insert d into queue mouse_queueIn++; //increment where to stick in the next d value mouse_queueEmpty=FALSE; //indicate queue isnt' empty anymore if (mouse_queueIn==QUEUELEN) //if reached the end of the queue mouse_queueIn=0; //wrap around to the beginning if (mouse_queueIn==mouse_queueOut) //if queueIn caught up to queueOut mouse_queueFull=TRUE; //indicate queue is full return(0); end //get data out of queue. Return 0 if queue empty or the actual data if not empty unsigned char mouse_queueGet(void) begin char d; if(mouse_resend_byte == TRUE) // in case we need to resend data due to an INHIBIT begin mouse_resend_byte = FALSE; return mouse_previous_byte; end if (mouse_queueEmpty==TRUE) //check if queue is empty return(0); d=mouse_queue[mouse_queueOut]; //get data out of queue mouse_queueOut++; //increment location where to get next d value mouse_queueFull=FALSE; //indicate queue isn't full anymore if (mouse_queueOut==QUEUELEN) //if reached the end of the queue mouse_queueOut=0; //wrap around to the beginning if (mouse_queueOut==mouse_queueIn) //if queueOut caught up to queueIn mouse_queueEmpty=TRUE; //indicate queue is empty mouse_previous_byte = d; // save the byte we just popped // in case we need to resend it. return(d); //return the data from queue end //insert data into queue. Return 1 if queue full, or 0 if inserted data sucessfully unsigned char keyboard_queuePut(unsigned char d) begin if (keyboard_queueFull==TRUE) //check if queue is full return(TRUE); keyboard_queue[keyboard_queueIn]=d; //insert d into queue keyboard_queueIn++; //increment where to stick in the next d value keyboard_queueEmpty=FALSE; //indicate queue isnt' empty anymore if (keyboard_queueIn==QUEUELEN) //if reached the end of the queue keyboard_queueIn=0; //wrap around to the beginning if (keyboard_queueIn==keyboard_queueOut) //if queueIn caught up to queueOut keyboard_queueFull=TRUE; //indicate queue is full return(0); end //get data out of queue. Return 0 if queue empty or the actual data if not empty unsigned char keyboard_queueGet(void) begin char d; if(keyboard_resend_byte == TRUE) // in case we need to resend data due to an INHIBIT begin keyboard_resend_byte = FALSE; return keyboard_previous_byte; end if (keyboard_queueEmpty==TRUE) //check if queue is empty return(0); d=keyboard_queue[keyboard_queueOut]; //get data out of queue keyboard_queueOut++; //increment location where to get next d value keyboard_queueFull=FALSE; //indicate queue isn't full anymore if (keyboard_queueOut==QUEUELEN) //if reached the end of the queue keyboard_queueOut=0; //wrap around to the beginning if (keyboard_queueOut==keyboard_queueIn) //if queueOut caught up to queueIn keyboard_queueEmpty=TRUE; //indicate queue is empty keyboard_previous_byte = d; // save the byte we just popped // in case we need to resend it. return(d); //return the data from queue end //calculate the parity of a character unsigned char getParity(unsigned char x) begin unsigned char temp, i; temp=1; for(i=0;i<8;i++) begin temp=temp^(x&1); x>>=1; end return temp; end void mouse_process_command(unsigned char host_command) begin //delay_us(50); // do this stuff at rising edge of CLK if (host_command == RESET) begin mouse_queueIn = 0; mouse_queueOut = 0; mouse_queueEmpty = TRUE; mouse_queueFull = FALSE; delay_us(500); end // Acknowledge the incoming request mouse_queuePut(ACK); // we received a byte w/ the new resolution if(mouse_waiting_for_resolution) begin // check for valid resolution if(host_command >= 0 && host_command <= 3) mouse_resolution = host_command; else mouse_queuePut(ERROR); mouse_waiting_for_resolution = FALSE; return; end // we received a byte w/ the new sample rate if(mouse_waiting_for_sample_rate) begin // check for valid sample rate if(host_command >= 10 && host_command <= 200) mouse_sample_rate = host_command; else // bad sample rate mouse_queuePut(ERROR); mouse_waiting_for_sample_rate = FALSE; return; end switch (host_command) begin case RESET: // RESET mouse_deviceID = 0x03; // create a device ID mouse_queuePut(SELF_TEST_PASS); // respond w/ self-test passed (0xAA) mouse_queuePut(mouse_deviceID); // send host device ID mouse_data_reporting = 0; // disable data reporting mouse_sample_rate = 100; // set the sampling rate to 100 mouse_scaling = 0; // set scaling to 1:1 mouse_resolution = 0x02; // set resolution to 4 break; case RESEND: // Host requests for resending of data mouse_resend_byte = TRUE; break; case EN_DATA_REPORT: // Enabling of data reporting PORTB.7 = 0; // indicates mouse was detected mouse_data_reporting = TRUE; break; case SET_SCALING11: // set scaling 1:1 mouse_scaling = 0; break; case SET_SCALING21: // set scaling 2:1 mouse_scaling = 1; break; case GET_DEVICE_ID: // host requests device ID mouse_queuePut(mouse_deviceID); break; case SET_RES: // host requests to set resolution // host sends next byte with valid resolution // set a flag to get this byte mouse_waiting_for_resolution = TRUE; break; case STATUS_REQ: //status request respond 0xFA, 0x00, 0x02, 0x64 mouse_queuePut(0x00); // have to create the right byte here ... mouse_queuePut(mouse_resolution); mouse_queuePut(mouse_sample_rate); break; case SET_SAMPLE_RATE: // host requests setting of sample rate // host sends next byte with valid sample rate // set a flag to get this byte mouse_waiting_for_sample_rate = TRUE; break; case DIS_DATA_REPORT: // disable data reporting mouse_data_reporting = FALSE; break; case SET_DEFAULT: // set default values mouse_data_reporting = FALSE; mouse_sample_rate = 100; mouse_resolution = 4; break; default: break; end end void keyboard_process_command(unsigned char host_command) begin //delay_us(50); // do this stuff at rising edge of CLK if (host_command == RESET) begin keyboard_queueIn = 0; keyboard_queueOut = 0; keyboard_queueEmpty = TRUE; keyboard_queueFull = FALSE; delay_us(500); end // Acknowledge the incoming request keyboard_queuePut(ACK); // we received a byte w/ the new sample rate if(keyboard_waiting_for_sample_rate) begin keyboard_waiting_for_sample_rate = FALSE; return; end // we received a byte w/ the LED status if(keyboard_waiting_for_led) begin // acknowledge keyboard_queuePut(ACK); //Running keyboard_data_reporting = TRUE; PORTB.6 = 0; keyboard_waiting_for_led = FALSE; return; end switch (host_command) begin case RESET: // RESET keyboard_deviceID[0] = 0xAB; // create a device ID keyboard_deviceID[1] = 0x83; keyboard_queuePut(SELF_TEST_PASS); // respond w/ self-test passed (0xAA) keyboard_queuePut(keyboard_deviceID[0]); // send host device ID keyboard_queuePut(keyboard_deviceID[1]); PORTB.6 = 1; keyboard_data_reporting = FALSE; // disable data reporting break; case RESEND: // Host requests for resending of data keyboard_resend_byte = TRUE; break; case SET_MAKE: case SET_MAKE_BREAK: case SET_TYPE: case SET_ALL_TYPE_MAKE_BREAK: case SET_ALL_MAKE: case SET_ALL_MAKE_BREAK: case SET_ALL_TYPE: keyboard_queuePut(ACK); break; case EN_DATA_REPORT: // Enabling of data reporting PORTB.6 = 0; // indicates keyboard was detected keyboard_data_reporting = TRUE; break; case GET_DEVICE_ID: // host requests device ID keyboard_queuePut(keyboard_deviceID[0]); // send host device ID keyboard_queuePut(keyboard_deviceID[1]); break; case SET_SAMPLE_RATE: // host requests setting of sample rate // host sends next byte with valid sample rate // set a flag to get this byte keyboard_waiting_for_sample_rate = TRUE; break; case DIS_DATA_REPORT: // disable data reporting keyboard_data_reporting = FALSE; break; case SET_DEFAULT: // set default values keyboard_data_reporting = FALSE; break; case SET_LED: keyboard_queuePut(ACK); keyboard_waiting_for_led = TRUE; break; default: break; end end void initialize(void) begin ADMUX = 0b01000000; //ADLAR is not set ADCSRA = 0b11000111; //Enable & Start ADC w/ division factor of 128 OCR0=5; //20 uSec TIMSK=2; //turn on timer 0 cmp-match ISR TCCR0=0b00001011; //prescalar to 64 and Clr-on-match // setup Port C for PS/2 communication DDRC = 0b10101010; PORTC = 0b10101010; // setup LEDs for debugging DDRB = 0xFF; PORTB = 0xFF; DDRD.2 = 1; PORTD.2 = 0; // counter to be used in ISR mouse_count = 0; mouse_delay = 0; keyboard_count = 0; keyboard_delay = 0; // initialize our outputs MOUSE_CLK_OUT = 1; MOUSE_DATA_OUT = 1; KEYBOARD_CLK_OUT = 1; KEYBOARD_DATA_OUT = 1; //crank up the ISRs #asm sei #endasm end void mouse_init() begin // initialize the queue mouse_queueEmpty = TRUE; mouse_queueFull = FALSE; mouse_queueIn = 0; mouse_queueOut =0; // initialize the states mouse_byte_index = 0; // where we are in byte mouse_state = IDLE; // state of the mouse mouse_clock_state = HIGH; // state of the clock mouse_next_clock_state = HIGH; // what clock will be changing to mouse_transmit = mouse_receive = 0; // init byte vars mouse_transmit_byte = 0xFA; mouse_receive_byte = 0x00; mouse_previous_byte = 0x00; mouse_resend_byte = FALSE; gen_mouse_packet = FALSE; // init mouse vars mouse_deviceID = 0x03; mouse_data_reporting = FALSE; mouse_sample_rate = 0; mouse_scaling = 0; mouse_resolution = 0; mouse_waiting_for_sample_rate = FALSE; mouse_waiting_for_resolution = FALSE; // let the host know the mouse is connected mouse_queuePut(SELF_TEST_PASS); mouse_queuePut(INIT); end void keyboard_init() begin // initialize the queue keyboard_queueEmpty = TRUE; keyboard_queueFull = FALSE; keyboard_queueIn = 0; keyboard_queueOut =0; // initialize the states keyboard_byte_index = 0; // where we are in byte keyboard_state = IDLE; // state of the keyboard keyboard_clock_state = HIGH; // state of the clock keyboard_next_clock_state = HIGH; // what clock will be changing to keyboard_transmit = keyboard_receive = 0; // init byte vars keyboard_transmit_byte = 0xFA; keyboard_receive_byte = 0x00; keyboard_previous_byte = 0x00; keyboard_resend_byte = FALSE; gen_keyboard_packet = FALSE; // init keyboard vars keyboard_deviceID[0] = 0xAB; keyboard_deviceID[1] = 0x83; keyboard_data_reporting = FALSE; keyboard_waiting_for_sample_rate = FALSE; keyboard_waiting_for_led = FALSE; // let the host know the keyboard is connected keyboard_queuePut(SELF_TEST_PASS); keyboard_queuePut(INIT); end void mouse_send(signed char Xmove, signed char Ymove, unsigned char Leftbutton, unsigned char Middlebutton, unsigned char Rightbutton) begin if (gen_mouse_packet == TRUE) begin gen_mouse_packet = FALSE; mouse_byte = 0x08; mouse_byte = mouse_byte | (((Ymove >> 7)&0x1)<<5) | (((Xmove >> 7)&0x1)<<4) | ((Middlebutton&0x1) <<2) | ((Rightbutton&0x1)<<1) | (Leftbutton & 0x1); mouse_queuePut(mouse_byte); mouse_queuePut(Xmove); mouse_queuePut(Ymove); end end void keyboard_send(char key, char breakCode) begin char shift = FALSE; if (charMode == LowLetter) begin switch (key) begin case 8: key_byte = 0x66; break; case 'a': key_byte = 0x1C; break; case 'b': key_byte = 0x32; break; case 'c': key_byte = 0x21; break; case 'd': key_byte = 0x23; break; case 'e': key_byte = 0x24; break; case 'f': key_byte = 0x2B; break; case 'g': key_byte = 0x34; break; case 'h': key_byte = 0x33; break; case 'i': key_byte = 0x43; break; case 'j': key_byte = 0x3B; break; case 'k': key_byte = 0x42; break; case 'l': key_byte = 0x4B; break; case 'm': key_byte = 0x3A; break; case 'n': key_byte = 0x31; break; case 'o': key_byte = 0x44; break; case 'p': key_byte = 0x4D; break; case 'q': key_byte = 0x15; break; case 'r': key_byte = 0x2D; break; case 's': key_byte = 0x1B; break; case 't': key_byte = 0x2C; break; case 'u': key_byte = 0x3C; break; case 'v': key_byte = 0x2A; break; case 'w': key_byte = 0x1D; break; case 'x': key_byte = 0x22; break; case 'y': key_byte = 0x35; break; case 'z': key_byte = 0x1A; break; end end else if (charMode == CapLetter) begin shift = TRUE; switch (key) begin case 8: key_byte = 0x66; break; case 'A': key_byte = 0x1C; break; case 'B': key_byte = 0x32; break; case 'C': key_byte = 0x21; break; case 'D': key_byte = 0x23; break; case 'E': key_byte = 0x24; break; case 'F': key_byte = 0x2B; break; case 'G': key_byte = 0x34; break; case 'H': key_byte = 0x33; break; case 'I': key_byte = 0x43; break; case 'J': key_byte = 0x3B; break; case 'K': key_byte = 0x42; break; case 'L': key_byte = 0x4B; break; case 'M': key_byte = 0x3A; break; case 'N': key_byte = 0x31; break; case 'O': key_byte = 0x44; break; case 'P': key_byte = 0x4D; break; case 'Q': key_byte = 0x15; break; case 'R': key_byte = 0x2D; break; case 'S': key_byte = 0x1B; break; case 'T': key_byte = 0x2C; break; case 'U': key_byte = 0x3C; break; case 'V': key_byte = 0x2A; break; case 'W': key_byte = 0x1D; break; case 'X': key_byte = 0x22; break; case 'Y': key_byte = 0x35; break; case 'Z': key_byte = 0x1A; break; end end else if (charMode == Number) begin switch (key) begin case 8: key_byte = 0x66; break; case '0': key_byte = 0x45; break; case '1': key_byte = 0x16; break; case '2': key_byte = 0x1E; break; case '3': key_byte = 0x26; break; case '4': key_byte = 0x25; break; case '5': key_byte = 0x2E; break; case '6': key_byte = 0x36; break; case '7': key_byte = 0x3D; break; case '8': key_byte = 0x3E; break; case '9': key_byte = 0x46; break; end end else begin switch (key) begin case 8: key_byte = 0x66; break; case '.': key_byte = 0x49; break; case ',': key_byte = 0x41; break; case ':': key_byte = 0x4C; shift = TRUE; break; case ';': key_byte = 0x4C; break; case '?': key_byte = 0x4A; shift = TRUE; break; case '!': key_byte = 0x16; shift = TRUE; break; case '\"': key_byte = 0x52; shift = TRUE; break; case '\'': key_byte = 0x52; break; case '/': key_byte = 0x4A; break; case '(': key_byte = 0x46; break; case ')': key_byte = 0x45; break; case '*': key_byte = 0x3E; break; case '+': key_byte = 0x55; shift = TRUE; break; case '-': key_byte = 0x4E; shift = TRUE; break; case '=': key_byte = 0x55; break; case '#': key_byte = 0x26; shift = TRUE; break; case '$': key_byte = 0x25; shift = TRUE; break; case '%': key_byte = 0x2E; shift = TRUE; break; case '&': key_byte = 0x3D; shift = TRUE; break; end end if (breakCode == FALSE) if (shift == TRUE) begin keyboard_queuePut(0x12); // shift keyboard_queuePut(key_byte); end else begin keyboard_queuePut(key_byte); end else if (shift == TRUE) begin keyboard_queuePut(0xF0); keyboard_queuePut(key_byte); keyboard_queuePut(0xF0); keyboard_queuePut(0x12); // shift end else begin keyboard_queuePut(0xF0); keyboard_queuePut(key_byte); end end //set user mode to mosue or keyboard void setMode(char mode) begin userMode = mode; charMode = LowLetter; nextChar = 0; newChar = TRUE; blinkCount = 0; bsCount = 0; prev_key = 0; key = 0; end void main(void) begin initialize(); while (keyboard_data_reporting == FALSE) begin keyboard_init(); delay_ms(200); end while (mouse_data_reporting == FALSE) begin mouse_init(); delay_ms(200); end //TXRX init txrx_init(0,1,249,1);//RX only - 4000 baud - led on rx_reset(MAX_RX_LENGTH); setMode(MOUSE); // begin real work while (TRUE) begin // if receive data if(rxdone()==1) begin k=0; init_getrx(); while(rx_empty()!=1) begin my_rx_data[k] = get_next_rx_data(); k++; end // 0 - 170 // 1 - start_char // 2 - ID // 3 - length // 4 to x - payload rx_reset(MAX_RX_LENGTH); if (userMode == MOUSE) begin if (my_rx_data[2] == tx_id) begin stepX = 0; stepY = 0; btnClick = 0; // mouse Y movement if (my_rx_data[5] == 0) stepY = 9; else if (my_rx_data[5] == 42) stepY = 6; else if (my_rx_data[5] == 84) stepY = 3; else if (my_rx_data[5] == 168) stepY = -3; else if (my_rx_data[5] == 210) stepY = -6; else if (my_rx_data[5] == 255) stepY = -9; // mouse X movement if (my_rx_data[4] == 0) stepX = -9; else if (my_rx_data[4] == 42) stepX = -6; else if (my_rx_data[4] == 84) stepX = -3; else if (my_rx_data[4] == 168) stepX = 3; else if (my_rx_data[4] == 210) stepX = 6; else if (my_rx_data[4] == 255) stepX = 9; if (my_rx_data[6] == 255) begin blinkCount++; end else begin //long blink to switch to keyboard mode if (blinkCount >= 80) begin setMode(KEYBOARD); btnClick = 1; end //short blink to click else if (blinkCount >= 10) begin btnClick = 1; end blinkCount = 0; end // send mouse signal to pc mouse_send(stepX,stepY,btnClick,0,0); end end else if (userMode == KEYBOARD) begin if (my_rx_data[2] == tx_id && gen_keyboard_packet == TRUE) begin gen_keyboard_packet = FALSE; // send break code of previous character if (prev_key != 0) begin keyboard_send(prev_key,TRUE); end // send actual character if (prev_key != key && newChar == FALSE) begin keyboard_send(key,FALSE); prev_key = key; end else begin if (my_rx_data[4] > 168) begin // scroll down character switch (charMode) begin case LowLetter: key = letter[nextChar++]; break; case CapLetter: key = letter[nextChar++]-32; break; case Number: key = numbers[nextChar++]; break; case Punct: key = punct[nextChar++]; break; end if (nextChar == charLen[charMode]) nextChar = 0; if (newChar == FALSE) begin keyboard_send(8,FALSE); prev_key = 8; end else newChar = FALSE; end else if (my_rx_data[4] < 84) begin // scroll down character nextChar--; if (nextChar == -1) nextChar = charLen[charMode]-1; switch (charMode) begin case LowLetter: key = letter[nextChar]; break; case CapLetter: key = letter[nextChar]-32; break; case Number: key = numbers[nextChar]; break; case Punct: key = punct[nextChar]; break; end if (newChar == FALSE) begin keyboard_send(8,FALSE); prev_key = 8; end else newChar = FALSE; end else if (my_rx_data[5] < 84) begin // change character mode nextChar = 0; if (charMode == 3) charMode = 0; else charMode++; switch (charMode) begin case LowLetter: key = letter[nextChar++]; break; case CapLetter: key = letter[nextChar++]-32; break; case Number: key = numbers[nextChar++]; break; case Punct: key = punct[nextChar++]; break; end if (newChar == FALSE) begin keyboard_send(8,FALSE); prev_key = 8; end else newChar = FALSE; end else if (my_rx_data[5] > 168) begin // backspace bsCount++; if (bsCount == 3) begin keyboard_send(8,FALSE); prev_key = key = 8; bsCount = 0; end end if (my_rx_data[6] == 255) begin blinkCount++; end else begin // long blink to switch to mouse mode if (blinkCount >= 10) begin setMode(MOUSE); end //short blink to start new character else if (blinkCount >= 2) begin newChar = TRUE; nextChar = 0; end blinkCount = 0; end end end end end end end