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

📄 main-ir.c

📁 AVRusb开发的一个电脑遥控器
💻 C
字号:
/*  * Project: IR-Mouse * File desc.: This file contains IR uC functions * Author: Krzysiek Szczuka * Creation Date: 2007-02-14 * Tabsize: 4 * Copyright: (c) 2007 by Krzysiek Szczuka * License: Proprietary, free under certain conditions. See Documentation. * This Revision: $Id: main-ir.c,v 1.17 2007/03/01 22:19:34 ksz Exp $ *//* * Some code in this file is from Dick Streefland's USBtiny ir project, see * http://www.xs4all.nl/~dicks/avr/usbtiny/ for details.. */#define F_CPU   8000000L // clock frequency#include <avr/io.h>#include <avr/interrupt.h>//#include <avr/pgmspace.h>#include <avr/wdt.h>#include <inttypes.h>#include <string.h>//#include "defines.h"/******************* REMOTE CONFIG ********************************************/#ifdef PANASONIC_VEQ1141# include "panasonic_veq1141.h"#else# ifdef SANYO_PLCXT10A#  include "sanyo_plcxt10a.h"# else		// !SANYO_PLCXT10A#  error "No remote type defined!!!"# endif		// SANYO_PLCXT10A#endif		// PANASONIC_VEQ1141// If this is defined, TZEROH is compared, else TONEH (see Readme.txt)#define ZERO_TEST/******************* PINOUT CONFIG ********************************************/// LED configuration #define LED_PIN		PINB	// LED PIN#define LED_DDR		DDRB	// LED DDR#define LED_PORT	PORTB	// LED PORT#define LED_PWR		0		// power LED#define LED_PWR_ON	do { LED_PORT |= _BV(LED_PWR); } while(0)#define LED_PWR_OFF	do { LED_PORT &= ~_BV(LED_PWR); }  while(0)#define LED_IR		1		// ir signal receiving LED#define LED_IR_ON	do { LED_PORT |= _BV(LED_IR); }  while(0)#define LED_IR_OFF	do { LED_PORT &= ~_BV(LED_IR); }   while(0)#define LED_C		2		// ir signal code fits LED#define LED_C_ON	do { LED_PORT |= _BV(LED_C); }  while(0)#define LED_C_OFF	do { LED_PORT &= ~_BV(LED_C); }   while(0)#define LED_MASK	(_BV(LED_IR) | _BV(LED_PWR) | _BV(LED_C))// IR decode mode select jumper's pin#define MODE_SW_PIN	PINB#define MODE_SW_DDR	DDRB#define MODE_SW_PORT PORTB#define MODE_SW		3/******************* MISC CONFIG **********************************************//*  * The mouse sends different values depending on it's movement speed, I've used * constant value, change it to increase/decrease cursor's speed * TODO: maybe this should be increased depending in ir.count value..? */#define MOVE		0x04#define	TIMEOUT		3500	// IR transmission timeout in us#define	IR_MAX		96		// maximum number of IR data bytes#define	SCALING		8		// 7: 15,98 us period, 8: 32,11 us period               				// 9: 42.67 us period, 10: 85.33 us period               				// you shouldn't touch it (-;/******************************************************************************/// calculates time periods to save in ir.data#define calcIRTime(val) ((val + (1 << (SCALING-3-1))) >> (SCALING-3))static	struct			// {	unsigned char	length;		// length of data[]	unsigned char	count;		// incremented for each IR packet//	unsigned char	offset;		// not used	unsigned char	data[IR_MAX];	// mark/space periods}		ir;static	unsigned char			edges;		// incremented for each edgestatic	unsigned int			irdelta;static	uint32_t				lastcode = 0;static	volatile unsigned char	flags = 0;static	unsigned char    		reportBuffer[3] = {0}; #define IR_INTS_ON	do{TIMSK |= (_BV(OCIE1A) | _BV(ICIE1));} while(0)#define IR_INTS_OFF	do{TIMSK &= ~(_BV(OCIE1A) | _BV(ICIE1));} while(0)//#define IR_INTS_OFF	do{TIMSK = 0;}while(0)static char makeReport(void);static void sendReport(void);// Handler for timer1 input capture interrupt: edge on IR inputISR(TIMER1_CAPT_vect){	static	unsigned int	prev;	unsigned int			stamp;	unsigned char			delta;	stamp = ICR1;			// get time stamp	//IR_INTS_OFF;			// disable both IR interrupts	TCCR1B ^= _BV(ICES1);	// toggle edge detector	LED_IR_ON;				// switch IR LED on		delta = calcIRTime(stamp - prev);	asm volatile("" : : "r"(delta) );	// calculate delta (gcc-4.1.0)		prev  = stamp;	// update timeout value 	OCR1A = stamp + TIMEOUT * CYCLES_PER_US / 8;	if ( !(flags & (FLG_IGNORE_PACKET | FLG_MAKING_REPORT)) )	{		{			ir.length = 0;		// discard previous packet			if	( edges > 0 )			{				ir.data[edges - 1] = delta;			}		}		++edges;	}		//TIMSK &= ~_BV(TOIE0);	//IR_INTS_ON;	// reenable IR interrupts}// Handler for timer1 output compare A interrupt: IR transmission timeoutISR(TIMER1_COMPA_vect){	IR_INTS_OFF;	// disable both IR interrupts	LED_IR_OFF;				// switch LED off		if ( edges >= 40 &&		!(flags & (FLG_IGNORE_PACKET | FLG_MAKING_REPORT))		)	{		ir.count++;		ir.length = edges - 1;		// new packet is complete		flags |= FLG_IR_RECEIVED;	}	edges = 0;	flags &= ~FLG_IGNORE_PACKET;		TCCR1B &= ~_BV(ICES1);			// reset to negative edge			TCNT0 = TCNT0V;	TIMSK |= _BV(TOIE0);		IR_INTS_ON;	// reenable IR interrupts	}ISR(TIMER0_OVF_vect){	if( !edges ) {		if( (ir.count > 0) && 			( (lastcode == CLMB) || (lastcode == CRMB) ) ) {				// report released LMB/RMB			reportBuffer[0] = 0;			reportBuffer[1] = 0;			reportBuffer[2] = 0;	    	flags |= FLG_SENDING_REPORT;		    sendReport();        	flags &= ~FLG_SENDING_REPORT;        }		ir.count = 0;		lastcode = 0;	}	TCNT0 = TCNT0V;		TIMSK &= ~_BV(TOIE0);}static char makeReport(void){	unsigned char i = 0;	unsigned char retval = 0;	unsigned char cc = ir.length-2;	uint32_t code = 0;			flags |= FLG_MAKING_REPORT;		if( !(MODE_SW_PIN & _BV(MODE_SW)) && (ir.count > 0) )		code = lastcode;	else {		for ( i = 0 ; i < 24 ; i++ ) {			if (edges)				flags |= FLG_IGNORE_PACKET;		#ifdef ZERO_TEST			if( ir.data[cc] > irdelta )				code &= ~_BV(i);			else				code |= _BV(i);		#else			if( ir.data[cc] > irdelta )				code |= _BV(i);			else				code &= ~_BV(i);		#endif			cc -= 2;		}	}		flags &= ~FLG_MAKING_REPORT;			//if ( !(flags & FLG_SENDING_REPORT) ) {		switch (code) {			case CUPH:				reportBuffer[0] = 1;				reportBuffer[1] = 0;				reportBuffer[2] = -MOVE;				lastcode = code;				retval = 1;				break;			case CDOWNH:				reportBuffer[0] = 1;				reportBuffer[1] = 0;				reportBuffer[2] = MOVE;				lastcode = code;				retval = 1;				break;			case CLEFTH:				reportBuffer[0] = 1;				reportBuffer[1] = -MOVE;				reportBuffer[2] = 0;				lastcode = code;				retval = 1;				break;			case CRIGHTH:				reportBuffer[0] = 1;				reportBuffer[1] = MOVE;				reportBuffer[2] = 0;				lastcode = code;				retval = 1;				break;			case CUP:				reportBuffer[0] = 0;				reportBuffer[1] = 0;				reportBuffer[2] = -MOVE;				lastcode = code;				retval = 1;				break;			case CDOWN:				reportBuffer[0] = 0;				reportBuffer[1] = 0;				reportBuffer[2] = MOVE;				lastcode = code;				retval = 1;				break;			case CLEFT:				reportBuffer[0] = 0;				reportBuffer[1] = -MOVE;				reportBuffer[2] = 0;				lastcode = code;				retval = 1;				break;			case CRIGHT:				reportBuffer[0] = 0;				reportBuffer[1] = MOVE;				reportBuffer[2] = 0;				lastcode = code;				retval = 1;				break;			case CLMB:				reportBuffer[0] = 1;				reportBuffer[1] = 0;				reportBuffer[2] = 0;				lastcode = code;				retval = 1;				break;			case CRMB:				reportBuffer[0] = 2;				reportBuffer[1] = 0;				reportBuffer[2] = 0;				lastcode = code;				retval = 1;				break;			case CRMBH:				reportBuffer[0] = 3;				reportBuffer[1] = 0;				reportBuffer[2] = 0;				lastcode = code;				retval = 1;				break;			default:				reportBuffer[0] = 0;				reportBuffer[1] = 0;				reportBuffer[2] = 0;				break;		}	//}    return retval;}static void sendReport(void){	unsigned char i;	for ( i=0 ; i< sizeof(reportBuffer) ; i++ ) {		while(!(UCSRA & _BV(UDRE))) ;		UDR = reportBuffer[i];	}}static void hardwareInit(void){    MODE_SW_PORT |= _BV(MODE_SW);	/* pullup for ir receive mode switch */    MODE_SW_DDR &= ~_BV(MODE_SW);    LED_DDR |= LED_MASK;        TCCR1B = _BV(ICNC1)	// noise canceler, trigger on negative edge	       | _BV(CS11);	// clock source clk/8 (remember to update 8	                    // in defines.h after change this!)	// ir interrupts (OCIE1A, ICIE1)	IR_INTS_ON;	/*** UART init ***/	// baud rate	UBRRH = (unsigned char)(((F_CPU)/((BAUD_RATE)*16l)-1)>>8);
    UBRRL = (unsigned char) ((F_CPU)/((BAUD_RATE)*16l)-1);	// in this uC we only need a transmitter	UCSRB = _BV(TXEN);	// asynchronous mode, 8N1	UCSRC = _BV(UCSZ1) | _BV(UCSZ0);	// Timer0 prescaler at 1024	TCCR0B |= _BV(CS02) | _BV(CS00);	//TCNT0 = TCNT0V;	TIMSK |= _BV(TOIE0);}/* ------------------------------------------------------------------------- */int	main(void){# ifdef ZERO_TEST	irdelta = calcIRTime(TZEROH);# else	irdelta = calcIRTime(TONEH);# endif//	asm volatile("" : : "r"(irdelta) );	// let gcc calculate irdelta _NOW_ 	wdt_enable(WDTO_1S);	hardwareInit();	sei();	LED_PWR_ON;	LED_IR_OFF;	LED_C_OFF;	for(;;){		wdt_reset();		if ( (flags & FLG_IR_RECEIVED) ) {		    if ( makeReport() ) {				LED_C_ON;		    	flags |= FLG_SENDING_REPORT;			    sendReport();	        	LED_C_OFF;	        	ir.length = 0;							}			flags &= ~( FLG_SENDING_REPORT | FLG_IR_RECEIVED );		}	}	return 0;}/* ------------------------------------------------------------------------- */

⌨️ 快捷键说明

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