#include "N76E003.h"
typedef bit bool;
enum{
false = 0,
true = 1,
};
#define uint8 unsigned char
#define SET_BIT0 0x01
#define SET_BIT1 0x02
#define SET_BIT2 0x04
#define SET_BIT3 0x08
#define SET_BIT4 0x10
#define SET_BIT5 0x20
#define SET_BIT6 0x40
#define SET_BIT7 0x80
uint8 setBit8(uint8 hexnum,bool a)
{
hexnum = (hexnum & ~SET_BIT7);
if(a==true)
{
hexnum |= SET_BIT7;
}
return hexnum;
}
uint8 setBitN(uint8 hexnum,uint8 N,bool B)//N between [0-7], B = true or false
{
uint8 temp;
switch(N)
{
case 0: temp=SET_BIT0; break;
case 1: temp=SET_BIT1; break;
case 2: temp=SET_BIT2; break;
case 3: temp=SET_BIT3; break;
case 4: temp=SET_BIT4; break;
case 5: temp=SET_BIT5; break;
case 6: temp=SET_BIT6; break;
case 7: temp=SET_BIT7; break;
default: break;
}
hexnum = (hexnum & ~temp);
if(B==true) {hexnum |= temp;}
return hexnum;
}
#define G_COL 5
#define G_ROW 4
#define keyNum G_COL*G_ROW
#define Slave_address 0xF0
/**********************Custom instruction----high 4 bit************************/
#define GET_read_length 0x10
#define READ_keyValue 0x20
#define SET_DEBOUNCE_TIME 0x30
#define GET_DebounceTime 0x40
#define INTO_LPM 0x50
/*----------------------------------------------------------------------------*/
////------------------- Define Port as Quasi mode -------------------
#define P00_Quasi_Mode P0M1&=~SET_BIT0;P0M2&=~SET_BIT0
#define P01_Quasi_Mode P0M1&=~SET_BIT1;P0M2&=~SET_BIT1
#define P02_Quasi_Mode P0M1&=~SET_BIT2;P0M2&=~SET_BIT2
#define P03_Quasi_Mode P0M1&=~SET_BIT3;P0M2&=~SET_BIT3
#define P04_Quasi_Mode P0M1&=~SET_BIT4;P0M2&=~SET_BIT4
#define P05_Quasi_Mode P0M1&=~SET_BIT5;P0M2&=~SET_BIT5
#define P06_Quasi_Mode P0M1&=~SET_BIT6;P0M2&=~SET_BIT6
#define P07_Quasi_Mode P0M1&=~SET_BIT7;P0M2&=~SET_BIT7
#define P10_Quasi_Mode P1M1&=~SET_BIT0;P1M2&=~SET_BIT0
#define P11_Quasi_Mode P1M1&=~SET_BIT1;P1M2&=~SET_BIT1
#define P12_Quasi_Mode P1M1&=~SET_BIT2;P1M2&=~SET_BIT2
#define P13_Quasi_Mode P1M1&=~SET_BIT3;P1M2&=~SET_BIT3
#define P14_Quasi_Mode P1M1&=~SET_BIT4;P1M2&=~SET_BIT4
#define P15_Quasi_Mode P1M1&=~SET_BIT5;P1M2&=~SET_BIT5
#define P16_Quasi_Mode P1M1&=~SET_BIT6;P1M2&=~SET_BIT6
#define P17_Quasi_Mode P1M1&=~SET_BIT7;P1M2&=~SET_BIT7
#define P20_Quasi_Mode P2M1&=~SET_BIT0;P2M2&=~SET_BIT0
#define P30_Quasi_Mode P3M1&=~SET_BIT0;P3M2&=~SET_BIT0
////------------------- Define Port as Push Pull mode -------------------
#define P00_PushPull_Mode P0M1|=SET_BIT0;P0M2&=~SET_BIT0
#define P01_PushPull_Mode P0M1|=SET_BIT1;P0M2&=~SET_BIT1
#define P02_PushPull_Mode P0M1&=~SET_BIT2;P0M2|=SET_BIT2
#define P03_PushPull_Mode P0M1&=~SET_BIT3;P0M2|=SET_BIT3
#define P04_PushPull_Mode P0M1&=~SET_BIT4;P0M2|=SET_BIT4
#define P05_PushPull_Mode P0M1&=~SET_BIT5;P0M2|=SET_BIT5
#define P06_PushPull_Mode P0M1&=~SET_BIT6;P0M2|=SET_BIT6
#define P07_PushPull_Mode P0M1&=~SET_BIT7;P0M2|=SET_BIT7
#define P10_PushPull_Mode P1M1&=~SET_BIT0;P1M2|=SET_BIT0
#define P11_PushPull_Mode P1M1&=~SET_BIT1;P1M2|=SET_BIT1
#define P12_PushPull_Mode P1M1&=~SET_BIT2;P1M2|=SET_BIT2
#define P13_PushPull_Mode P1M1&=~SET_BIT3;P1M2|=SET_BIT3
#define P14_PushPull_Mode P1M1&=~SET_BIT4;P1M2|=SET_BIT4
#define P15_PushPull_Mode P1M1&=~SET_BIT5;P1M2|=SET_BIT5
#define P16_PushPull_Mode P1M1&=~SET_BIT6;P1M2|=SET_BIT6
#define P17_PushPull_Mode P1M1&=~SET_BIT7;P1M2|=SET_BIT7
#define P20_PushPull_Mode P2M1&=~SET_BIT0;P2M2|=SET_BIT0
#define P30_PushPull_Mode P3M1&=~SET_BIT0;P3M2|=SET_BIT0
////------------------- Define Port as Input Only mode -------------------
#define P00_Input_Mode P0M1|=SET_BIT0;P0M2&=~SET_BIT0
#define P01_Input_Mode P0M1|=SET_BIT1;P0M2&=~SET_BIT1
#define P02_Input_Mode P0M1|=SET_BIT2;P0M2&=~SET_BIT2
#define P03_Input_Mode P0M1|=SET_BIT3;P0M2&=~SET_BIT3
#define P04_Input_Mode P0M1|=SET_BIT4;P0M2&=~SET_BIT4
#define P05_Input_Mode P0M1|=SET_BIT5;P0M2&=~SET_BIT5
#define P06_Input_Mode P0M1|=SET_BIT6;P0M2&=~SET_BIT6
#define P07_Input_Mode P0M1|=SET_BIT7;P0M2&=~SET_BIT7
#define P10_Input_Mode P1M1|=SET_BIT0;P1M2&=~SET_BIT0
#define P11_Input_Mode P1M1|=SET_BIT1;P1M2&=~SET_BIT1
#define P12_Input_Mode P1M1|=SET_BIT2;P1M2&=~SET_BIT2
#define P13_Input_Mode P1M1|=SET_BIT3;P1M2&=~SET_BIT3
#define P14_Input_Mode P1M1|=SET_BIT4;P1M2&=~SET_BIT4
#define P15_Input_Mode P1M1|=SET_BIT5;P1M2&=~SET_BIT5
#define P16_Input_Mode P1M1|=SET_BIT6;P1M2&=~SET_BIT6
#define P17_Input_Mode P1M1|=SET_BIT7;P1M2&=~SET_BIT7
#define P20_Input_Mode P2M1|=SET_BIT0;P2M2&=~SET_BIT0
#define P30_Input_Mode P3M1|=SET_BIT0;P3M2&=~SET_BIT0
////-------------------Define Port as Open Drain mode -------------------
#define P00_OpenDrain_Mode P0M1|=SET_BIT0;P0M2|=SET_BIT0
#define P01_OpenDrain_Mode P0M1|=SET_BIT1;P0M2|=SET_BIT1
#define P02_OpenDrain_Mode P0M1|=SET_BIT2;P0M2|=SET_BIT2
#define P03_OpenDrain_Mode P0M1|=SET_BIT3;P0M2|=SET_BIT3
#define P04_OpenDrain_Mode P0M1|=SET_BIT4;P0M2|=SET_BIT4
#define P05_OpenDrain_Mode P0M1|=SET_BIT5;P0M2|=SET_BIT5
#define P06_OpenDrain_Mode P0M1|=SET_BIT6;P0M2|=SET_BIT6
#define P07_OpenDrain_Mode P0M1|=SET_BIT7;P0M2|=SET_BIT7
#define P10_OpenDrain_Mode P1M1|=SET_BIT0;P1M2|=SET_BIT0
#define P11_OpenDrain_Mode P1M1|=SET_BIT1;P1M2|=SET_BIT1
#define P12_OpenDrain_Mode P1M1|=SET_BIT2;P1M2|=SET_BIT2
#define P13_OpenDrain_Mode P1M1|=SET_BIT3;P1M2|=SET_BIT3
#define P14_OpenDrain_Mode P1M1|=SET_BIT4;P1M2|=SET_BIT4
#define P15_OpenDrain_Mode P1M1|=SET_BIT5;P1M2|=SET_BIT5
#define P16_OpenDrain_Mode P1M1|=SET_BIT6;P1M2|=SET_BIT6
#define P17_OpenDrain_Mode P1M1|=SET_BIT7;P1M2|=SET_BIT7
#define P20_OpenDrain_Mode P2M1|=SET_BIT0;P2M2|=SET_BIT0
#define P30_OpenDrain_Mode P3M1|=SET_BIT0;P3M2|=SET_BIT0
/************************pin definition********************************/
sbit C1=P1^7;
sbit C2=P3^0;
sbit C3=P0^7;
sbit C4=P0^6;
sbit C5=P0^5;
sbit D1=P0^1;
sbit D2=P0^2;
sbit D3=P0^3;
sbit D4=P0^4;
sbit led_red=P1^0;
sbit led_green=P1^5;
sbit led_blue=P0^0;
sbit i2c_SDA = P1^4;
sbit i2c_SCL = P1^3;
sbit i2c_INT = P1^2;
/************************************************************************/
code const uint8 scan_arr[]={0x10,0x08,0x04,0x02,0x01};//High level detection
uint8 data_received[2];
uint8 data_send[20];
uint8 col_buf[G_COL]={0x00,0x00,0x00,0x00,0x00};//Column value representation
uint8 last_col_buf[G_COL]={0x00,0x00,0x00,0x00,0x00};
uint8 ket[keyNum];//The point of time that marks a key event.
//Whether the time point of a key event marking a key can be changed
uint8 ket_en_recorded[G_COL]={0x00,0x00,0x00,0x00,0x00};
uint8 keyEventArray[keyNum];
uint8 total;//The number of key events
uint8 writeIndex=0,readIndex=0;
uint8 T0_cnt=0;
uint8 debounceTime=10;
//The following are the variables set relative to the I2C-Master
uint8 length_send;//byte length of master should to read
uint8 length_receive=1;//Assume that the i2c-master sends one byte to the slave
bool en_scan;
bit BIT_TMP;
void timer0_init()
{
TMOD&=0xF0;TMOD|=0x01;//TIMER0_MODE1_ENABLE 16bit
CKCON &= ~SET_BIT4;
ET0 = 1;//enable Timer0 interrupt
EA = 1;
TR0 = 1;//Timer0 run
}
void port_init()
{
//set all scan port to Input_Mode
P17_Input_Mode;
P30_Input_Mode;
P07_Input_Mode;
P06_Input_Mode;
P05_Input_Mode;
//set all data port to open-drain
P01_OpenDrain_Mode;
P02_OpenDrain_Mode;
P03_OpenDrain_Mode;
P04_OpenDrain_Mode;
//set led port to push-pull mode
P10_PushPull_Mode;
P15_PushPull_Mode;
//Initialize the scan pin
C1=C2=C3=C4=C5=0;
}
void init_I2C()
{
I2CPX=0;//set SCL=P1.3 SDA=P1.4
//set SDA and SCL port to Quasi mode
P14_Quasi_Mode;
P13_Quasi_Mode;
P12_Quasi_Mode;
i2c_SDA=1;//set SDA and SCL pins high
i2c_SCL=1;
BIT_TMP=EA;
TA=0xAA;TA=0x55;SFRS=0x01;P1SR|=SET_BIT2;TA=0xAA;TA=0x55;SFRS=0x00;
EA=BIT_TMP;
EIE |= SET_BIT0;//enable I2C interrupt by setting IE1 bit 0
EA= 1;
I2ADDR=Slave_address;//define own slave address
I2CEN = 1; //enable I2C circuit
AA=1;//the AA bit should be set to enable acknowledging its own slave address.
}
void setScanTTL(uint8 ttl)
{
C1=(ttl & 0x10)>>4; C2=(ttl & 0x08)>>3; C3=(ttl & 0x04)>>2; C4=(ttl & 0x02)>>1; C5=(ttl & 0x01);
}
void keyScan()
{
bool uncertain_changs=false;
static uint8 scan_colIndex=0;
uint8 col_diffPart=0;
if(en_scan)
{
uint8 d1,d2,d3,d4;
uint8 col_bit=0;
d1=D1; d2=D2; d3=D3; d4=D4;
setScanTTL(0x00);
col_buf[scan_colIndex] = (d1 << 3)|(d2 << 2)|(d3 << 1)|d4;
col_diffPart = col_buf[scan_colIndex] ^ last_col_buf[scan_colIndex];
if(col_diffPart>0)
{
for(col_bit=0;col_bit < G_ROW; col_bit++)//
{
if((col_diffPart>>col_bit) & 0x01)//If the state of a key is changed
{
if(!(ket_en_recorded[scan_colIndex]>>col_bit & 0x01))//Prevent coverage record
{
ket[scan_colIndex*G_ROW+col_bit]=T0_cnt;//Record the moment of a key event
ket_en_recorded[scan_colIndex] = setBitN(ket_en_recorded[scan_colIndex],col_bit,1);//
}
uncertain_changs=true;
}
else//If the state of a key is not changed,Allow to record the moment of this key event.
{
ket_en_recorded[scan_colIndex] = setBitN(ket_en_recorded[scan_colIndex],col_bit,0);
}
}
}
if(uncertain_changs)
{
uint8 j=0;
for(j=0;j>j) & 0x01)//Find the button of the state change in column scan_colIndex.
{
if(T0_cnt-ket[scan_colIndex*G_ROW+j] >= debounceTime)//debounce
{
bool nowStat = (col_buf[scan_colIndex]>>j) & 0x01;
bool lastStat = (last_col_buf[scan_colIndex]>>j) & 0x01;
if(nowStat != lastStat)//只记录按键状态发生变化的事件
{
if((nowStat == 1) && (lastStat == 0))//pressed
{keyEventArray[writeIndex%keyNum] = setBit8(scan_colIndex*G_ROW+j,1);}
else if((nowStat == 0) && (lastStat == 1))//released
{keyEventArray[writeIndex%keyNum] = setBit8(scan_colIndex*G_ROW+j,0);}
writeIndex++;
total++;
last_col_buf[scan_colIndex] = col_buf[scan_colIndex]; //update last_col_buf[scan_colIndex]
i2c_INT=0;//send interrupt to i2c-master
}// else do nothing
//Finish the key event processing,Allow to record the moment of this key event.
ket_en_recorded[scan_colIndex] = setBitN(ket_en_recorded[scan_colIndex],j,0);
}
}//end if(col_diffPart>>j & 0x01)
}// end for j
uncertain_changs=false;//Only after each scan gets the variable is true to enter this statement.
}// end if(uncertain_changes)
scan_colIndex++;
en_scan=false;
}
else
{
if(scan_colIndex >= G_COL)
{
scan_colIndex=0;
}
setScanTTL(scan_arr[scan_colIndex]);/*set scan TTL*/
/*********Prevent short-circuit from combination key**********/
switch(scan_colIndex)
{
case 0: P17_PushPull_Mode; P30_Input_Mode; P07_Input_Mode; P06_Input_Mode; P05_Input_Mode; break;
case 1: P17_Input_Mode; P30_PushPull_Mode; P07_Input_Mode; P06_Input_Mode; P05_Input_Mode; break;
case 2: P17_Input_Mode; P30_Input_Mode; P07_PushPull_Mode; P06_Input_Mode; P05_Input_Mode; break;
case 3: P17_Input_Mode; P30_Input_Mode; P07_Input_Mode; P06_PushPull_Mode; P05_Input_Mode; break;
case 4: P17_Input_Mode; P30_Input_Mode; P07_Input_Mode; P06_Input_Mode; P05_PushPull_Mode; break;
default: break;
}
}
}
void into_SleepMode_wait()
{
}
void execute_cmd(uint8 cmd)
{
uint8 i=0;
switch(cmd)
{
case GET_read_length:
length_send=1;//此时回复给i2c-master一字节
data_send[0]=total;
break;
case READ_keyValue: //此时回复给i2c-master length_send个字节
{
length_send = total;//表示i2c-slave 要发送的字节数
for(i=0;i