?? main-ir.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 + -