📄 keyboard side.c
字号:
/******************************************
* Wireless Keyboard - Hejnar, Leventhal
* Keyboard Side Code
*/
#include <Mega32.h>
//connect the DAT line to B.0 which is pin 1 on the chip (Yellow)
//connect the CLK line to B.2 which is pin 3 on the chip (Blue)
#define rDAT PIND.7
#define rCLK PIND.3
#define wDAT PORTD.7
#define wCLK PORTD.3
#define TRUE 1
#define FALSE 0
#define QUEUELEN 200
char receive; //indicate that int2 interrupt should work as reciever (if 1) or tranmsitter (if 0)
char countIn; //count how many Low CLK pulses we have seen as we receive data from keyboard
char countOut; //count how many Low CLK pulses we have seen as we transmitt data to keyboard
unsigned char dataIn; //will store the data bits coming in from the keyboard
unsigned char dataOut; //will store the data bits we are sending out to the keyboard
char parityIn; //will store the calculated parity of data coming in from the keyboard
char parityOut; //will store the calculated parity of data we are sending out to the keyboard
char pError; //will store if there was a parity error in data sent by keyboard
char queue[QUEUELEN]; //queue of data sent by keyboard. (first in, first out)
char queueFull; //indicates if queue is full
char queueEmpty;//indicates if queue is empty
char queueIn; //indicates where to put data into queue
char queueOut; //indicates where to take data out of queue
char rxDone; //indicate done receiving frame
char txDone; //indicate done transmitting frame
char t2visits; //times gone into timer2 interrupt without any resets of the counter
void initialize(void); //initialize mcu
void initializeKyBd(void);//initialize keyboard
char queuePut(char d); //put data into queue
char queueGet(void); //get data from queue
void TXtoKyBd(char d); //send command to keyboard
void RXfromKyBd(void); //receive data from keyboard
//insert data into queue. Return 1 if queue full, or 0 if inserted data sucessfully
char queuePut(char d)
{
if (queueFull==TRUE)//check if queue is full
return(TRUE);
queue[queueIn]=d; //insert d into queue
queueIn++; //increment where to stick in the next d value
queueEmpty=FALSE; //indicate queue isnt' empty anymore
if (queueIn==QUEUELEN) //if reached the end of the queue
queueIn=0; //wrap around to the beginning
if (queueIn==queueOut) //if queueIn caught up to queueOut
queueFull=TRUE; //indicate queue is full
return(0);
}
//get data out of queue. Return 0 if queue empty or the actual data if not empty
char queueGet(void)
{
char d;
if (queueEmpty==TRUE) //check if queue is empty
return(0);
d=queue[queueOut]; //get data out of queue
queueOut++; //increment location where to get next d value
queueFull=FALSE; //indicate queue isn't full anymore
if (queueOut==QUEUELEN) //if reached the end of the queue
queueOut=0; //wrap around to the beginning
if (queueOut==queueIn) //if queueOut caught up to queueIn
queueEmpty=TRUE;//indicate queue is empty
return(d); //return the data from queue
}
//on every falling clock edge generated by the keyboard, either receives or sends data
interrupt [EXT_INT1] void external_int1(void)
{
//when receiving data
if(receive==TRUE)
{
countIn++; //count how many clock pulses we have seen
//if countIn=1, then seeing the start bit
//if countIn=2 to 9, then seeing data bits 0 to 7
//if countIn=10, then seeing the parity bit
//if countIn=11, then seeing the stop bit
if (countIn==1)//seeing start bit
{
dataIn=0;
rxDone=FALSE; //receiving not done (just starting)
//set up timer0 to check for no clock transition in 200uSec
TCNT0=0; //reset timer0
TCCR0=0x0B; //put timer0 into compare match mode, prescaler of 64;
TIMSK=(TIMSK&0xFD)|0x02; //make bit1=1 to enable compare match interrupt;
TIFR=TIFR&0xFD; //make bit1=0 to clear the timer0 comp match flag (just in case its set)
}
else if ((countIn>1) && (countIn<10)) //data bits being sent
{
TCNT0=0; //reset timer0 since saw a clock signal
TIFR=TIFR&0xFD;//make bit1=0 to clear the timer0 comp match flag (just in case its set)
dataIn=dataIn>>1;//shift data right by 1
if (rDAT==1) //if DAT line is 1
{
dataIn=dataIn|0x80; //shift in a received bit of 1. (0 shifted in automatically)
parityIn++; //update the parity
}
}
else if (countIn==10) //parity bit being sent
{
TCNT0=0; //reset timer0 since saw a clock signal
TIFR=TIFR&0xFD; //set bit1=0 to clear the timer0 comp match flag (just in case its set)
//partiy should be odd
if ((parityIn+rDAT)&0x01) //if (calculated parity+ rDAT) is odd,
pError=FALSE; //then no parity error
else
pError=TRUE; //otherewise there was a parity error
}
else if (countIn==11) //stop bit being sent
{
TCCR0=0x00; //stop timer0 since seen last clock
TCNT0=0; //reset timer0
TIMSK=TIMSK&0xFD; //set bit1=0 to disable timer0 interrupt
TIFR=TIFR&0xFD; //set bit1=0 to clear the timer0 comp match flag just in case
//don't pass along responses to RF that are meant only for the microcontroller or if there was a parity error
// parityError BAT successful Ack BAT error
if(!pError && (dataIn!=0xAA) && (dataIn!=0xFA) && (dataIn!=0xFC))
{
//AGC set up and syncronization
queuePut(0xAA);
queuePut(0xAA);
queuePut(0xAA);
queuePut(0xAA);
queuePut(0xAA);
queuePut(0xAA);
queuePut(0xAA);
queuePut(0xAA);
queuePut(0xAA);
queuePut(0xAA);
queuePut(0xAA);
queuePut(0xAA);
queuePut(0xAA);
queuePut(0xAA);
queuePut(0xAA);
queuePut(0xAA);
queuePut(0xFF);
queuePut(dataIn); //insert data into queue
}
rxDone=TRUE; //indicate that we have received a frame
countIn=0; //reset count since have seen the end of frame
parityIn=0; //clear parity for next time
}
}
//when sending data, writing stuff onto the DAT line when clock is low so
//that the data is valid when clock goes high and the keyboard reads it
else
{
countOut++; //coutn how many clock pulses we have seen
//if countOut=1, then seeing ourselves pulling line low to inhibit communication
//if countOut=2 to 9 then we will be sending data bits 0 to 7
//if countOut=10, then we will be sending out the parity bit
//if countOut=11, then we will be sending out the stop bit
//if countOut=12, then seeing the "ack" bit
if (countOut==1) //seeing ourslves pulling the line low to inhibit communication
{
//set up timer so that we keep CLK low for at least 100uSec
TCCR1A=0x00; //normal waveform generation
TCCR1B=0x01; //normal waveform generation and full clock speed (16MHz)
TCNT1=0; //reset timer1 to 0
OCR1A=2240; //140uSec*16MHz=2240cycles
TIMSK=(TIMSK&0xEF)|0x10; //set bit4=1 to 1 to enable Output Compare A match interrupt
//set up timer0 to check for no clock transition in 200uSec
TCNT0=0; //reset timer0
TCCR0=0x0B; //put timer0 into compare match mode, prescaler of 64;
TIMSK=(TIMSK&0xFD)|0x02; //set bit1=1 to enable compare match interrupt;
TIFR=TIFR&0xFD; //set bit1=0 to clear the timer0 comp match flag (just in case its set)
parityOut=0; //reset parity
txDone=FALSE; //transmitting not done(just starting)
}
else if (countOut>1 &&countOut<10) //data bits being sent
{
TCNT0=0; //reset timer0 since saw a clock signal
TIFR=TIFR&0xFD; //set bit1=0 to clear the timer0 comp match flag just in case
if (dataOut&0x01)//if lowest bit is a 1
{
wDAT=1; //write out a 1 to the keyboard
parityOut++; //calculate the parity
}
else
wDAT=0; //write out a 0 to the keybard
dataOut=dataOut>>1;//shift data right by 1 to get next bit next time
}
else if (countOut==10)//send parity bit
{
TCNT0=0; //reset timer0 since saw a clock signal
TIFR=TIFR&0xFD; //set bit1=0 to clear the timer0 comp match flag (just in case its set)
if(parityOut&0x01) //if parity is odd
wDAT=0; //write out a 0 to the keyboard
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -