/* * File: main.c * Author: PaPa2 * * Created on 2018/06/17, 15:57 */ #include // CONFIG1 #pragma config FOSC = INTOSC // Oscillator Selection bits #pragma config WDTE = OFF // Watchdog Timer Enable bit #pragma config PWRTE = OFF // Active Low, Power-up Timer Enable bit //#pragma config PWRTE = ON // Active Low, Power-up Timer Enable bit //#pragma config MCLRE = OFF // RA3/MCLR pin function select bit #pragma config MCLRE = ON // RA3/MCLR pin function select bit ??????ON?? #pragma config BOREN = ON // Brown Out Reset Selection bits #pragma config IESO = ON // Internal External Switchover bit #pragma config FCMEN = ON // Fail-Safe Clock Monitor Enabled bit #pragma config LVP = OFF // Low Voltage Programming Enable bit #define _XTAL_FREQ 8000000 #define SET -1 #define CLR 0 #define CHS_MASK 0x7c #define AN0 0 #define AN1 1 #define AN2 2 #define AN3 3 #define AN4 4 #define AN5 5 #define AN6 6 #define AN7 7 #define ADC_AVE_MODE 0 /* ADC平均値モード */ #define ADC_MAX_MODE 1 /* ADC MAXモード */ /* * I/O port assign * RA0 : IR RX in * RA1 : LED CTRL out * RA2 : IR TX out(PWM) * RA3 : Not Use(Only MCLR) * RA4 : Audio SW1 Analog in * RA5 : BUZZER CTRL out */ /* IO port define */ #define BUZCTRL RA0 #define LEDCTRL RA1 #define IR_TX RA2 #define AN_SWIN RA4 #define IR_RX RA5 #define ANALOG_CH 3 #define LED_ON 0 #define LED_OFF 1 /* ステアリングスイッチ抵抗閾AD値 */ /* これ以上の場合スイッチONと判断する */ /* 上から順に評価する */ #define SH_SW_ALL_OFF 869 #define SH_SW_MODE 725 #define SH_SW_CH_UP 545 #define SH_SW_CH_DN 356 #define SH_SW_VOL_UP 180 #define SH_SW_VOL_DN 0 /* スイッチ番号 */ #define SW_ALL_OFF 0 #define SW_MODE 1 /* 通常:MODE, 長押し:BAND */ #define SW_CH_UP 2 /* 通常:CH UP */ #define SW_CH_DN 3 /* 通常:CH DN */ #define SW_VOL_UP 4 /* 通常:VOL UP, 長押し:広域- */ #define SW_VOL_DN 5 /* 通常:VOL DN, 長押し:+詳細 */ /* IR番号 */ #define IR_MODE 0 #define IR_CH_UP 1 #define IR_CH_DN 2 #define IR_VOL_UP 3 #define IR_VOL_DN 4 #define IR_MODE_LONG 5 #define IR_1ST_CODE 6 #define IR_EXEC_2ND 7 #define IR_WIDE_2ND 8 #define IR_NALLOW_2ND 9 /* IR送信用PWM START/STOP */ #define PWM_START 0x2c #define PWM_STOP 0x20 #define CCP1PIN RA2 /* NECフォーマット */ #define NEC_READER_ON 9000 /* Reader Code Hi : 9.0ms */ #define NEC_READER_OFF 4500 /* Reader Code Low : 4.5ms */ #define NEC_DATA_ON 570 /* Data Code Hi : 0.56ms */ #define NEC_DATA_BITON 1600 /* Data Code Low(1b) : 1.7ms */ #define NEC_DATA_BITOFF 510 /* Data Code Low(0b) : 0.56ms */ #define NEC_DATA_END 28 /* 全体で108ms */ #define BYTE_SIZE 0x08 /* 1byte : 8bit */ #define NEC_CODE_SIZE 0x04 /* NEC Data Size : 4byte */ /* 設定保管用EEPROM */ #define BIT_CLICK_SOUND 0x1 /* Bit 0 0:Sound OFF, 1:Sound ON */ #define BIT_MODE_LONG_IR 0x2 /* Bit 1 0:BAND code, 1:EXEC code */ #define BIT_IR_PWM_FREQ 0xC /* Bit 3:2 00:- , 01:36KHz, 10:38KHz, 11:40KHz */ #define PWM_FREQ_36K 0x4 #define PWM_FREQ_38K 0x8 #define PWM_FREQ_40K 0xC #define CONFIG_EEP 0 __EEPROM_DATA(0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF); /* スイッチ長押し判定時間(x100m秒) */ #define LONG_PUSH_SW_MODE 10 /*============================================================================= * ROMデータ クラリオン リモコン RCB-202 *============================================================================*/ const unsigned char ir_table_RCB202[10][4] ={ { 0x86, 0x60, 0x03, 0xfc }, /* MODE(SOURCE) */ { 0x86, 0x60, 0x17, 0xe8 }, /* CH UP */ { 0x86, 0x60, 0x16, 0xe9 }, /* CH DOWN */ { 0x86, 0x60, 0x1b, 0xe4 }, /* VOL UP */ { 0x86, 0x60, 0x1d, 0xe2 }, /* VOL DOWN */ { 0x86, 0x60, 0x0a, 0xf5 }, /* BAND(ALBUM) */ { 0x83, 0x3b, 0xff, 0x00 }, /* 1st code of 2 bytes code*/ { 0x83, 0x3b, 0x1e, 0xe1 }, /* EXEC 2nd code */ { 0x83, 0x3b, 0x0b, 0xf4 }, /* WIDE 2nd code (広域-) */ { 0x83, 0x3b, 0x06, 0xf9 } /* NALLOW 2nd code (+詳細) */ }; /*============================================================================= * 変数 *============================================================================*/ unsigned int t10ms, t10ms2, t100ms, t100ms2, t1s; char click_sound, mode_long_ir, ir_freq; unsigned char sw_state, sw_state_old; unsigned char t_time; /* 赤外線基本時間 T (x 4us) */ unsigned char eep_work; /*============================================================================= * 割り込み *============================================================================*/ void interrupt intr(void){ /* 10ms Timer1 割り込み */ if (TMR1IE == 1 && TMR1IF == 1){ /* Every 10ms */ TMR1 = 63035; TMR1IF = 0; t10ms++; t10ms2++; /* 100msカウント */ if(t10ms >= 10){ t10ms = 0; t100ms++; t100ms2++; } /* 1秒カウント */ if(t100ms >= 10){ /* 100ms x 10 -> 1sec */ t100ms = 0; t1s++; } } } /*==============================================================================*/ /* ブザー音だし */ /* time_ms : 音の長さ x 0.5ms */ /*==============================================================================*/ void beep(unsigned int time_ms){ BUZCTRL = 1; while(time_ms){ __delay_us(500); --time_ms; } BUZCTRL = 0; } /*============================================================================== * NEC_reader_send *===============================================================================*/ void NEC_reader_send(void) { CCP1CON = PWM_START; /* 38KHz PWM Start */ __delay_us(NEC_READER_ON); /* 9.0ms : Hi */ CCP1CON = PWM_STOP; /* PWM Stop */ PORTAbits.CCP1PIN = 0; /* IR Pin : Low で終了 */ __delay_us(NEC_READER_OFF); /* 4.5ms : Low */ return; } /*============================================================================== * NEC_data_bit_ON_send *===============================================================================*/ void NEC_data_bit_ON_send(void) { CCP1CON = PWM_START; /* 38KHz PWM Start */ __delay_us(NEC_DATA_ON); /* 0.56ms : Hi */ CCP1CON = PWM_STOP; /* PWM Stop */ PORTAbits.CCP1PIN = 0; /* IR Pin : Low で終了 */ __delay_us(NEC_DATA_BITON); /* 1.7ms : Low */ return; } /*============================================================================== * NEC_data_bit_OFF_send *===============================================================================*/ void NEC_data_bit_OFF_send(void) { CCP1CON = PWM_START; /* 38KHz PWM Start */ __delay_us(NEC_DATA_ON); /* 0.56ms : Hi */ CCP1CON = PWM_STOP; /* PWM Stop */ PORTAbits.CCP1PIN = 0; /* IR Pin : Low で終了 */ __delay_us(NEC_DATA_BITOFF); /* 0.56ms : Low */ return; } /*============================================================================== * NEC_stopbit_send *===============================================================================*/ void NEC_stopbit_send(void) { CCP1CON = PWM_START; /* 38KHz PWM Start */ __delay_us(NEC_DATA_ON); /* 0.56ms : Hi */ CCP1CON = PWM_STOP; /* PWM Stop */ PORTAbits.CCP1PIN = 0; /* IR Pin : Low で終了 */ return; } /*============================================================================== * IR_NEC_format *===============================================================================*/ void IR_NEC_format(unsigned char* tbl_p) { unsigned char i, j; /* Reader Code Output */ NEC_reader_send(); /* カスタムコード/データコード (4byte) 出力 */ for (i=0;i adc_tmp) adc_tmp = adc_int; }else{ adc_long = adc_long + (unsigned long)adc_int; } } if(mode == ADC_MAX_MODE){ adc_long = (unsigned long)adc_tmp; }else{ adc_long = adc_long / (unsigned long)(ave_num); } adc_h = (unsigned char)(adc_long >> 8); adc_l = (unsigned char)adc_long; return ((unsigned int)adc_long); } /*============================================================================= * ステアリングスイッチの状態をsw_stateに読み込む *============================================================================*/ void sw_read(void){ unsigned int ad_data; /* スイッチ読み込み */ ad_data = adc_read((char)ANALOG_CH, 10, (char)ADC_AVE_MODE); if(ad_data > SH_SW_ALL_OFF) { sw_state = SW_ALL_OFF; }else if(ad_data > SH_SW_MODE) { sw_state = SW_MODE; }else if(ad_data > SH_SW_CH_UP) { sw_state = SW_CH_UP; }else if(ad_data > SH_SW_CH_DN) { sw_state = SW_CH_DN; }else if(ad_data > SH_SW_VOL_UP) { sw_state = SW_VOL_UP; }else { sw_state = SW_VOL_DN; } } /*============================================================================= * LED点滅とブザー音 *============================================================================*/ #define LED_ONCE 0 #define LED_TWICE 1 #define LED_3TIMES 2 void led_beep(char flg){ switch(flg){ case LED_ONCE: /* 1回 */ LEDCTRL = LED_OFF; beep(50); LEDCTRL = LED_ON; break; case LED_TWICE: /* 2回 */ LEDCTRL = LED_OFF; beep(50); LEDCTRL = LED_ON; __delay_ms(200); LEDCTRL = LED_OFF; beep(50); LEDCTRL = LED_ON; break; case LED_3TIMES: /* 3回 */ LEDCTRL = LED_OFF; beep(50); LEDCTRL = LED_ON; __delay_ms(200); LEDCTRL = LED_OFF; beep(50); LEDCTRL = LED_ON; __delay_ms(200); LEDCTRL = LED_OFF; beep(50); LEDCTRL = LED_ON; break; default: break; } } /*============================================================================= * 設定モード * VOL DOWN : クリックサウンドの設定 * VOL UP : MODEボタン長押しのIRコード設定 * CH DOWN : 赤外線変調周波数の設定 *============================================================================*/ void config_mode(void){ t100ms2 = 0; while(1){ t10ms2 = 0; while(t10ms2 < 10); /* 100ms待ってからスイッチ読み込み */ /* LED フリッカ */ if(t100ms2 > 4){ t100ms2 = 0; LEDCTRL = ~LEDCTRL; } /* ステアリングスイッチ読み込み */ sw_read(); if(sw_state != sw_state_old){ if(click_sound) beep(1); switch(sw_state){ case SW_VOL_DN: /* クリックサウンドの設定 */ if(click_sound){ click_sound = CLR; eep_work = (unsigned char)(eep_work & ~BIT_CLICK_SOUND); led_beep(LED_ONCE); }else { click_sound = SET; eep_work = (unsigned char)(eep_work | BIT_CLICK_SOUND); led_beep(LED_TWICE); } break; case SW_VOL_UP: /* MODEボタン長押しのIRコード設定 */ if(mode_long_ir){ mode_long_ir = CLR; eep_work = (unsigned char)(eep_work & ~BIT_MODE_LONG_IR); led_beep(LED_ONCE); }else { mode_long_ir = SET; eep_work = (unsigned char)(eep_work | BIT_MODE_LONG_IR); led_beep(LED_TWICE); } break; case SW_CH_DN: switch(ir_freq){ case PWM_FREQ_36K: ir_freq = PWM_FREQ_38K; led_beep(LED_TWICE); break; case PWM_FREQ_38K: ir_freq = PWM_FREQ_40K; led_beep(LED_3TIMES); break; case PWM_FREQ_40K: ir_freq = PWM_FREQ_36K; led_beep(LED_ONCE); break; default: break; } eep_work = (unsigned char)((eep_work & ~BIT_IR_PWM_FREQ) | ir_freq); break; case SW_CH_UP: break; case SW_MODE: break; case SW_ALL_OFF: break; default: break; } sw_state_old = sw_state; eeprom_write(CONFIG_EEP, eep_work); } } } /*============================================================================= * メイン *============================================================================*/ void main(void) { unsigned char tmp; /* CPU Clock 設定 */ OSCCON = 0b01110010; /* Clock 8MHz internal */ /* PORT A (1b:Input 0b:Output) */ ANSELA = 0b00010000; /* RA4のみAnalog */ TRISA = 0b11111000; /* bit2,1,0出力 */ PORTA = 0b00000000; WPUA = 0b00101000; /* Port A Weak Pull Up */ /* A/Dコンバータ設定 */ ADCON0 = 0b00010001; /* FOSC/32 = 4us, AD enable */ ADCON1 = 0b10100000; /* Right justified, VDD, VSS */ /* OPTION REG, TIMER0 設定 */ OPTION_REG = 0b00000010; /* Prescaler -> 1:8 (4us) */ TMR0IE = 0; /* Timer0 Interrupt Disable */ /* TIMER1 設定 */ T1CON = 0b00110001; /* 16bit mode RD16:1 */ /* Prescaler -> 1:8 */ /* Clock Source -> Internal */ /* Timer1 -> Start */ TMR1IE = 0; /* Timer1 Interrupt Disable */ TMR1 = 63035; /* Timer1 Value Set */ TMR1IF = 0; /* Timer1 Interrupt Flag Clear */ /* EEPROM設定値読み込み */ eep_work = eeprom_read(CONFIG_EEP); if(eep_work & BIT_CLICK_SOUND) click_sound = SET; else click_sound = CLR; if(eep_work & BIT_MODE_LONG_IR) mode_long_ir = SET; else mode_long_ir = CLR; /* PWM用 TIMER2 赤外線キャリア周波数設定の設定 */ /* PWM Period = [(PR2) + 1] * 4 * Tosc * (TMR2 Prescale Value) */ /* PWM Pulse Width = (CCPR1L:CCP1CON<5:4>) * Tosc * (TMR2 prescale Value) */ /* Note: Tosc = 1/Fosc = 125ns */ ir_freq = (char)(eep_work & BIT_IR_PWM_FREQ); switch(ir_freq){ case PWM_FREQ_40K: PR2 = 49; /* =40KHz (1cycle = 25us) */ CCPR1L = 0b00011001; /* =0x64=100 Duty 50%, PulseWidth=12.5us */ break; /* CCP1CON<5:4>は設定省略 */ case PWM_FREQ_36K: PR2 = 54; /* ≒36KHz (1cycle = 27.5us) */ CCPR1L = 0b00011011; /* =0x6e=110Duty 50%, PulseWidth=13.75us */ break; /* CCP1CON<5:4>は設定省略 */ default: PR2 = 52; /* ≒37.8KHz (1cycle = 26.5us) */ CCPR1L = 0b00011010; /* =0x6a=106 Duty 50%, PulseWidth=13.25us */ break; } /* PWM用 TIMER2 赤外線キャリア周波数設定の設定 */ TMR2IF = 0; /* Timer2 Interrupt Flag Clear */ T2CON = 0b00000000; /* Prescaler = 1:1   */ TMR2ON = 1; /* Timer 2 Enable */ t10ms = t100ms = t1s = 0; sw_state = sw_state_old = SW_ALL_OFF; /* 電源ON後の安定時間待ち */ __delay_ms(300); TMR1IE = 1; PEIE = 1; GIE = 1; /* 起動時にスイッチが押されているか */ sw_read(); /* MODEスイッチが押されている場合、設定モード */ if(sw_state == SW_MODE){ beep(300); __delay_ms(100); beep(300); config_mode(); } /* 通常モード */ beep(80); while(1){ t10ms2 = 0; while(t10ms2 < 5); /* 50ms待ってからスイッチ読み込み */ /* ステアリングスイッチ読み込み */ do{ sw_read(); tmp = sw_state; sw_read(); }while(tmp != sw_state); /* 各スイッチ処理 */ /* CH_UP, CH_DNは押したときに赤外線が出る */ /* その他は離したときに赤外線が出る */ /* CH_UP,CH_DNはリピートあり */ switch(sw_state){ case SW_VOL_DN: /* 長押し時間計測開始 */ t100ms2 = 0; /* 長押し検出のためスイッチOFF or タイムアウトまで待つ */ while((sw_state == SW_VOL_DN) && (t100ms2 <= LONG_PUSH_SW_MODE)) sw_read(); /* 長押し時の処理 */ if(t100ms2 > LONG_PUSH_SW_MODE){ if(click_sound) beep(20); send_ir(IR_NALLOW_2ND); sw_state_old = SW_VOL_DN; } /* 通常スイッチ処理 */ else if(sw_state_old == SW_ALL_OFF){ send_ir(IR_VOL_DN); } break; case SW_VOL_UP: /* 長押し時間計測開始 */ t100ms2 = 0; /* 長押し検出のためスイッチOFF or タイムアウトまで待つ */ while((sw_state == SW_VOL_UP) && (t100ms2 <= LONG_PUSH_SW_MODE)) sw_read(); /* 長押し時の処理 */ if(t100ms2 > LONG_PUSH_SW_MODE){ if(click_sound) beep(20); send_ir(IR_WIDE_2ND); sw_state_old = SW_VOL_UP; } /* 通常スイッチ処理 */ else if(sw_state_old == SW_ALL_OFF){ send_ir(IR_VOL_UP); } break; case SW_CH_DN: send_ir(IR_CH_DN); sw_state_old = sw_state; break; case SW_CH_UP: send_ir(IR_CH_UP); sw_state_old = sw_state; break; case SW_MODE: /* 長押し時間計測開始 */ t100ms2 = 0; /* 長押し検出のためスイッチOFF or タイムアウトまで待つ */ while((sw_state == SW_MODE) && (t100ms2 <= LONG_PUSH_SW_MODE)) sw_read(); /* 長押し時の処理 */ if(t100ms2 > LONG_PUSH_SW_MODE){ if(click_sound) beep(20); if(mode_long_ir) send_ir(IR_1ST_CODE); else send_ir(IR_MODE_LONG); sw_state_old = SW_MODE; } /* 通常スイッチ処理 */ else if(sw_state_old == SW_ALL_OFF){ send_ir(IR_MODE); } break; case SW_ALL_OFF: sw_state_old = sw_state; break; default: break; } } }