⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ps2.c

📁 利用AVR 单片机实现 PS2键盘标 程序
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "SN8P2201.h"
#include "sn8_mcu_main.h"
#include "sn8_usb_driver.h"
#include "cmn.h"
//#include "source\ibus.h"
#include "ps2.h"
#include "kb_table.h"
#include "ibus.h"

// ----- definition ---- //

// for Keyboard
#pragma rambank 1
u8 led_sta,codeset;		 // KB led status, kb codeset
u8 rd_pc_kb_buf[2];		// rd_pc_kb_buf[1] 是上一次接收到的字节的缓存
u8 pc_kb_buf[10];		// send to pc data buffer
u8 pc_kb_bufcnt;		// 计数器,总是指向下一空白的buffer
#pragma rambank off

// for mouse
u8 rd_pc_mc_buf[2];		// rd_pc_mc_buf[1] 是上一次接收到的字节的缓存
u8 pc_mc_buf[8];		// send to pc data buffer and counter
u8 pc_mc_bufcnt;		// 计数器,总是指向下一空白的buffer
u8 s_rate,mc_mode = STREAM;		// 采样速率,模式,default is stream
bit f_mc_enb;			// until recv 0xf4, set the f_mc_enb

// for makecoe, breakcode

bit f_lc_mc,f_ls_mc,f_la_mc,f_lg_mc,f_rc_mc,f_rs_mc,f_ra_mc,f_rg_mc;
bit f_k1_mc,f_k1_ext,f_k1_spc,f_k2_mc,f_k2_ext,f_k2_spc,f_k3_mc,f_k3_ext,f_k3_spc;
bit f_type_dly,f_need_type;
u8 k1_buf,k2_buf,k3_buf;

bit f_key_press,f_need_type;
u8 type_dlycnt,	typecnt,type_buf,last_key;

// 
bit f_first_f4 = 0;
void add_type_buf( u8 data );

void ps2_init(void)
{
	KB_CKM = 0;
	KB_DAM = 0;
	MC_CKM = 0;
	MC_DAM = 0;
	FPS2ENB = 1;
	#if(ICE_MODE == 1)
		FP61M = 1;
		FP61 = 1;
	#endif
}

void ps2_disable(void)
{
	FPS2ENB = 0;
	#if(ICE_MODE == 1)
		FP61 = 0;
	#endif	
}
/*F**************************************************************************
* NAME:	rd_pc_kb	
*----------------------------------------------------------------------------
* PARAMS:  None
*
* return:	True or fail
*   
*----------------------------------------------------------------------------
* PURPOSE: read one byte data from pc, suppose the start status has been 
*	betected by main   
*----------------------------------------------------------------------------
*****************************************************************************/
bool rd_pc_kb(void)
{
	u8 x,temp;
	bit p = 1,p_temp;

	temp = 0;
	KB_CKM = 1;
	KB_DAM = 0;
	// read 8bit data	
	for(x=0;x<8;x++)  
	{
		dly_20us();
		KB_CK = 0;
		dly_40us();
		KB_CK = 1;
		dly_10us(); // dly_20us   // 因为下面的语句要使用20+条汇编,要占用时间,so用dly10us差不多了
		if(KB_DA == 1)
		{
			//p = ~p;
			if(p) p = 0;
			else p = 1;
			temp |= 0x01u<<x;

		}
		else
		{
			temp &= ~(0x01u<<x);
		}

	}
	// read parity bit
	dly_20us();
	KB_CK = 0;
	dly_40us();
	KB_CK = 1;
	dly_20us();
	if(KB_DA == 1)
	{
		p_temp = 1;
	}
	else
	{
		p_temp = 0;
	}
	// read stop bit
	dly_20us();
	KB_CK = 0;
	dly_40us();
	KB_CK = 1;
	dly_20us();
	if(KB_DA == 0)
	{
		return fail;
	}
	// ack
	dly_10us();
	dly_5us();
	KB_DAM = 1;
	KB_DA = 0;
	dly_5us();
	KB_CKM = 1;
	KB_CK = 0;
	dly_40us();
	KB_CK = 1;
	dly_5us();
	KB_DA = 1;
	KB_DAM = 0;
	KB_CKM = 0;

	// check data
	if (p == p_temp)
	{
		rd_pc_kb_buf[0] = temp;
		return true;
	}
	else
	{
		return fail;
	}
	
}


/*F**************************************************************************
* NAME:	bool wr_pc_kb
*----------------------------------------------------------------------------
* PARAMS:  None
*
* return:	True or fail
*   
*----------------------------------------------------------------------------
* PURPOSE: 
*   
*----------------------------------------------------------------------------
*****************************************************************************/
bool wr_pc_kb(u8 data)
{
	u8 x;
	bit p = 1;

	KB_CKM = 0;
	KB_DAM = 0;

	// check if the bus is busy
	if(KB_CK == 0)
	{
		dly_20us();
		if(KB_CK == 0)
		{
			return fail;
		}
		
	}
	dly_40us();
	dly_5us();
	if(KB_CK == 0)
	{
		return fail;
	}
	if(KB_DA == 0)
	{
		return fail;
	}

	// --- start transmit --- //
	
	KB_CKM = 1;
	KB_DAM = 1;
	// tx start bit
	KB_DA = 0;
	dly_20us();
	KB_CK = 0;
	dly_40us();
	KB_CK = 1;
	dly_20us();
	// tx 8bit data
	for(x=0;x<8;x++)
	{
		//if( (data&(0x01<<x)) == 1 )  // 小心!
		//if( data&(0x01<<x))
		if(data&0x01)
		{
			//p = ~p;
			if(p) p = 0;
			else p = 1;
			KB_DA = 1;
		}
		else
		{
			KB_DA = 0;
		}
		dly_10us();
		KB_CK = 0;
		dly_40us();
		KB_CK = 1;
		dly_20us();
		// test if host driven the ck
		KB_CKM = 0;
		if(KB_CK == 0)
		{
			KB_CKM = 0;
			KB_DAM = 0;
			return fail;
		}
		KB_CKM = 1;
		data = data>>0x01;
	}
	// tx parity bit
	if( p )
	{
		KB_DA = 1;
	}
	else
	{
		KB_DA = 0;
	}
	dly_20us();
	KB_CK = 0;
	dly_40us();
	KB_CK = 1;
	dly_20us();
	KB_CKM = 0;
	if(KB_CK == 0)
	{
		KB_CKM = 0;
		KB_DAM = 0;
		return fail;
	}
	KB_CKM = 1;

	// stop bit
	KB_DA = 1;
	dly_20us();
	KB_CK = 0;
	dly_40us();
	KB_CK = 1;
	KB_CKM = 0;
	dly_20us();
	KB_DAM = 0;

	//dly_40us();
	//dly_10us();
	// dly50us太少了,在Vista里会出错,但是XP就不会
	dly_100us();
	dly_100us();
	dly_100us();
	dly_100us();
	dly_100us();
	dly_100us();

	return true;

}

/*F**************************************************************************
* NAME:	pc_kb_prc	
*----------------------------------------------------------------------------
* PARAMS:  None
*
* return:	None
*   
*----------------------------------------------------------------------------
* PURPOSE: 
*   处理从PC收到的数据
*----------------------------------------------------------------------------
*****************************************************************************/
void pc_kb_prc(void)
{
	u8 data;
	data = rd_pc_kb_buf[0];
	
	if( data == 0xfe ) // resend 
	{
		return;
	}
	else if(data == 0xee) //echo
	{
		add_pc_kb_buf(0xee);
	}
	else if( data == 0xf2 )
	{
		add_pc_kb_buf(0xfa);
		add_pc_kb_buf(0xab);
		add_pc_kb_buf(0x83);

		f_led_rpt_enb = 0;
		// boot 
		f_boot = 1;
		bootcnt= 0;
	}
	else if( data == 0xf4 )
	{
		f_led_rpt_enb = 0;
		// boot 
		f_boot = 1;
		bootcnt= 0;
	}
	else if( data < 0x08u )
	{
		if(rd_pc_kb_buf[1] == 0xed)
		{
			led_sta = data;
			set_report_byte_0 = 0;		// 为了适应USB KB,统一转成USB的格式
			if(led_sta & 0x01)	set_report_byte_0 |= 0x04;		// Scroll Lock
			if(led_sta & 0x02)	set_report_byte_0 |= 0x01;		// Number Lock
			if(led_sta & 0x04)	set_report_byte_0 |= 0x02;		// Caps Lock
			f_led_sta_new = 1;
			//led_times++;
			//if(led_times > 1)
			//{
			//	f_led_rpt_enb = 1;
			//}
		}
		else if(rd_pc_kb_buf[1] == 0xf0)
		{
			if(data < 0x04u )
			{
				codeset = data;
			} 
		}
		add_pc_kb_buf(0xfa);
	}
	else if(data == 0xff)
	{
		pc_kb_bufcnt = 0;			// clear buffer
		add_pc_kb_buf(0xfa);
		add_pc_kb_buf(0xaa);

		f_led_rpt_enb = 0;
		// boot 
		f_boot = 1;
		bootcnt= 0;

	}
	else // 暂时不处理其它的数据
	{
		add_pc_kb_buf(0xfa);
	}
	rd_pc_kb_buf[1] = data;   // 暂存收到的数据以便下一次分析

}
/*F**************************************************************************
* NAME:		
*----------------------------------------------------------------------------
* PARAMS:  None
*
* return:	None
*   
*----------------------------------------------------------------------------
* PURPOSE: 
*   
*----------------------------------------------------------------------------
*****************************************************************************/
void add_pc_kb_buf( u8 data )
{
	pc_kb_buf[pc_kb_bufcnt] = data;
	pc_kb_bufcnt++;
	if(pc_kb_bufcnt == 10)  // if overflow, 删掉前面的缓冲
	{
		//pc_kb_bufcnt = 7;
		rm_pc_kb_buf();
	}
}
// 从缓冲区删除最前面那一个byte
void rm_pc_kb_buf(void)
{
/*	u8 x;
	
// 编译出错,为什么?
for(x=0;x<7;x++)
	{
		pc_kb_buf[x] = pc_kb_buf[x+1];
	}
	pc_kb_buf[7] = 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -