#include /* IR send program read volume -> send volume value by IR of NEC format use PIC12F683 osc internal 2MHz PWM IR carrier frequency(38kHz D=1/3) TMR0 IR ON/OFF time(0.56ms) TMR1 10ms count A/D volume data SLEEP pin assign GP2: IR signal GP3: send button(interrupt) GP4: volume(A/D) GP5: volume bias pin action button on -> read volume & send volume value(1byte) by IR continue button on -> repeat send volume value(1byte) by IR button off -> sleep mode NEC format(http://www.necel.com/faq/ja/mi_com/f_com_remo.html) carrier frequency 38kHz(D=1/3) reader code 1bit on 9.0ms off 4.5ms custom code 2byte 1: on 0.56ms off 0.56ms 0: on 0.56ms off 1.68ms data code 1byte 1: on 0.56ms off 0.56ms 0: on 0.56ms off 1.68ms ^data code 1byte 1: on 0.56ms off 0.56ms 0: on 0.56ms off 1.68ms stop code 1bit on 0.56ms off ?ms total 108ms 1cycle send 1byte */ __CONFIG( // FCMEN & // IESOEN & BORDIS & UNPROTECT & MCLRDIS & PWRTDIS & WDTDIS & // INTCLK INTIO ); #define READER_ON (255 - 138) // 9.0ms TMR0 1:32 #define READER_OFF (255 - 68) // 4.5ms TMR0 1:32 #define DATA_ON (255 - 60) // 0.56ms TMR0 1:4 #define DATA_OFF (255 - 44) // 0.56ms TMR0 1:4 #define DATA_OFF_3 (255 - 182) // 0.56ms * 3 TMR0 1:4 #define TMR1_10MS ((0xffff - 5000)>>8) // 10ms TMR1 use high byte #define BUF_SIZE 5 // 4byte( custom + custom + data + ~data) + 1byte(stop) #define REPEAT_PERIOD 20 // ir_send() repeat each 10ms * X in button on #define CNT_SLEEP 100 // time untill sleep mode : 10ms * X (X > 15) #define CUSTOM_CODE_1 0x86 #define CUSTOM_CODE_2 0x23 //#define IR_OUT GPIO5 #define VOLUM_TRIS TRISIO5 #define VOLUM_IO GPIO5 #define BUTTON GPIO3 #define pwm_start() { T2CON,TMR2ON = 1; TRISIO2 = 0; } #define pwm_stop() { T2CON,TMR2ON = 0; TRISIO2 = 1; } #define tmr0_start() { INTCON,T0IF = 0; INTCON,T0IE = 1; } #define tmr0_stop() { INTCON,T0IF = 0; INTCON,T0IE = 0; } #define tmr1_start() { PIR1,TMR1IF = 0; PIE1,TMR1IE = 1; T1CON,TMR1ON = 1; } #define tmr1_stop() { PIR1,TMR1IF = 0; PIE1,TMR1IE = 0; T1CON,TMR1ON = 0; } unsigned char cnt_bit = 0; // ir buffer index (unit:bit) unsigned char ir_buf_i = 0; // ir buffer index (unit:byte) unsigned char ir_buf[BUF_SIZE]; // ir data buffer volatile unsigned char burst = 0; // 1:burst 0:off volatile unsigned char reader = 0; // 1:reader code 0:data code volatile unsigned char ir_buf_full = 0; // 1:data sending 0:idle volatile unsigned char flg_button = 0; // 1:button on 0:button off volatile unsigned char flg_10ms = 0; // 1:10ms cnt 0:not yes 10ms void init(); // initial setup unsigned char func(unsigned char cnt, char *p); // read A/D & count up 10ms at button on void pwm_init(); // pwm setup char ir_set_char(unsigned char c); // ir set charactor void ir_send(unsigned char c); // ir data send by NEC format void adc_init(); // A/D setup unsigned char adc_read(unsigned char ch); // read A/D of ch void interrupt interrupt_func() { unsigned char c; unsigned char i; /* TMR0(IR send) */ if(INTCON,T0IF ==1){ INTCON,T0IF = 0; if(ir_buf_full == 0){ // already finished sending & other interrupt -> jump to ir send routine goto IR_SEND_END; } /* reader code */ if(reader == 1){ if(burst == 1){ TMR0 = READER_OFF; pwm_stop(); burst = 0; }else{ burst = 1; OPTION = 0x01; // TMR0 1:4 TMR0 = DATA_ON; reader = 0; // reader code finish pwm_start(); } /* data code */ } else { if(burst == 1){ pwm_stop(); burst = 0; i = cnt_bit >> 3; // ir_buf index is calucurated by cnt_bit / 8 c = ir_buf[i]; TMR0 = (c & 0x01) ? DATA_OFF_3 : DATA_OFF; ir_buf[i] = c >> 1; cnt_bit++; } else { if(cnt_bit == (32+1)){ // include stop bit cnt_bit = 0; ir_buf_full = 0; tmr0_stop(); goto IR_SEND_END; } pwm_start(); burst = 1; TMR0 = DATA_ON; } } } IR_SEND_END: /* GPIO(GPIO3 @ button) */ if(INTCON,GPIF == 1){ INTCON,GPIF = 0; if(BUTTON == 0){ flg_button = 1; }else{ flg_button = 0; } } /* TMR1 @ 10ms */ if(PIR1,TMR1IF == 1){ PIR1,TMR1IF = 0; TMR1H = TMR1_10MS; flg_10ms = 1; } } void init() { OSCTUNE = 0x01; OSCCON = 0x57; // f=2MHz TRISIO = 0b11011011; CMCON0 = 0x07; // comparator off WPU = 0b11011011; // ir out pin & volume out pin not pull up INTCON = 0xc8; // GPIE interrupt on OPTION = 0x01; // TMR0 1:4 IOC = 0x08; // GP3 enable interrupt-on-change TMR0 = DATA_OFF; T1CON = 0x00; TMR1H = TMR1_10MS; // PWM setup pwm_init(); // A/D setup adc_init(); } unsigned char func(unsigned char cnt, char *p) { if(BUTTON == 0){ *(p + (cnt & 0x03)) = adc_read(3); cnt++; }else{ cnt = 0; // tmr1_stop(); } return cnt; } main() { unsigned char ad[4]; unsigned char cnt10ms = 0; unsigned char cnt_slp = 0; unsigned int sum = 0; init(); tmr1_start(); while(1) { if(flg_10ms == 1){ flg_10ms = 0; cnt10ms = func(cnt10ms, ad); // read A/D & remove chattering if(cnt10ms == 0){ // button off cnt_slp++; }else if(cnt10ms == 4){ if(ir_buf_full == 0){ sum = ad[0] + ad[1] + ad[2] + ad[3]; ir_send(sum >> 2); // send IR data of A/D // ir_send(0x00); } } } if(cnt10ms == REPEAT_PERIOD){ // ir_send() at 10ms * N period cnt10ms = 0; } if(cnt_slp == CNT_SLEEP){ cnt_slp = 0; tmr1_stop(); VOLUM_TRIS = 1; // save volume current asm("sleep"); } if(flg_button == 1){ // almost sleep wake up flg_button = 0; /* set up */ tmr1_start(); VOLUM_TRIS = 0; VOLUM_IO = 1; cnt10ms = 0; cnt_slp = 0; cnt10ms = func(cnt10ms, ad); } } } void pwm_init() { // f=38kHz D=1/3 CCP1CON = 0x1c; CCPR1L = 0x04; PR2 = 0x0c; T2CON = 0x00; } char ir_set_char(unsigned char c) { if((ir_buf_i >= BUF_SIZE)){ return 0; } else { ir_buf[ir_buf_i++] = c; return 1; } } void ir_send(unsigned char c) { unsigned char i, j; ir_buf_full = 1; /* clear ir buffer */ for(i=0; i