/* * File: main.c * Author: nishi * * Created on 2017/08/15, 10:18 */ #include /*============================================================================= * コンフィグレーション *============================================================================*/ // CONFIG1 #pragma config DEBUG = ON // In-Circuit Debugger Mode bit (In_Circuit Debugger enabled, RB6/ICSPCLK and RB7/ICSPDAT are dedicated to the debugger) #pragma config FOSC = INTRC_NOCLKOUT// Oscillator Selection bits (INTOSCIO oscillator: I/O function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN) #pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled and can be enabled by SWDTEN bit of the WDTCON register) #pragma config PWRTE = ON // Power-up Timer Enable bit (PWRT enabled) #pragma config MCLRE = ON // RE3/MCLR pin function select bit (RE3/MCLR pin function is MCLR) #pragma config CP = OFF // Code Protection bit (Program memory code protection is disabled) #pragma config CPD = OFF // Data Code Protection bit (Data memory code protection is disabled) #pragma config BOREN = ON // Brown Out Reset Selection bits (BOR enabled) #pragma config IESO = ON // Internal External Switchover bit (Internal/External Switchover mode is enabled) #pragma config FCMEN = ON // Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is enabled) #pragma config LVP = ON // Low Voltage Programming Enable bit (RB3/PGM pin has PGM function, low voltage programming enabled) // CONFIG2 #pragma config BOR4V = BOR21V // Brown-out Reset Selection bit (Brown-out Reset set to 2.1V) #pragma config WRT = OFF // Flash Program Memory Self Write Enable bits (Write protection off) /*============================================================================= * 定数定義 *============================================================================*/ #define _XTAL_FREQ 8000000 #define CHS_MASK 0x3c #define AN0 0 #define AN1 1 #define AN2 2 #define AN3 3 #define ADC_AVE_MODE 0 /* ADC読込時、平均を取る */ #define ADC_MAX_MODE 1 /* ADC読込時、MAX値とする */ /* pwr_state ステート値 */ #define ST_PWROFF 0 #define ST_PWRON 1 #define ST_SLEEP 2 /* usb_flag STATUS */ #define IN_USE 0 #define IN_COUNT 1 #define TIME_UP 2 #define USB_TIME_UP 30 /* HDD USB Power OFF Time Up second. */ /* IO port define (RB3 = PGM) */ #define USB0 RB0 #define USB1 RB1 #define USB2 RB2 #define USB3 RB7 #define USB_PB_BITS 0x0F #define HDD0 RC4 #define HDD1 RC5 #define HDD2 RC6 #define HDD3 RC7 #define HDD_PC_BITS 0xF0 #define AN_THRM AN0 #define SW1 RB4 #define SW2 RC0 #define SW3 RB5 /* 2099FV IO port define */ #define IO_OE RA4 #define IO_LCK RC3 #define IO_CLOCK RA6 #define IO_DATA RA7 #define LED1_MESSAGE 0x1 #define LED28_LINKACT 0x2 #define LED27_POWER 0x4 #define LED26_ACC4 0x8 #define LED25_ACC3 0x10 #define LED24_ACC2 0x20 #define LED23_ACC1 0x40 #define LED31_FAIL4 0x80 #define LED33_FAIL3 0x100 #define LED32_FAIL2 0x200 #define LED30_FAIL1 0x400 #define LED_ACC_ALL 0x078 #define LED_OTHER 0x7 #define LED_ALL 0x7ff /* 温度チェック間隔 */ #define TEMP_UP_TIME 30 /* Sec */ /* 電源断可能温度 */ #define NORMAL_TEMP 40 /* ℃ */ /* FAN回転数チェック間隔 */ #define FAN_RPM_CHK_TIME 5 /* Sec */ /*============================================================================= * EEPROMデータ *============================================================================*/ #define EEPROM_TEMP_DATA 0x0 /* 温度データ開始アドレス */ /* サーミスタ 103AT 温度変換テーブル(Vref=5V時のADC値)High, Low 順*/ /* 0-3℃ */ __EEPROM_DATA(0x02,0xf7,0x02,0xee,0x02,0xe5,0x02,0xdb); /* 4-7℃ */ __EEPROM_DATA(0x02,0xd2,0x02,0xc8,0x02,0xbf,0x02,0xb5); /* 8-11℃ */ __EEPROM_DATA(0x02,0xab,0x02,0xa1,0x02,0x97,0x02,0x8d); /* 12-15℃ */ __EEPROM_DATA(0x02,0x83,0x02,0x79,0x02,0x6f,0x02,0x65); /* 16-19℃ */ __EEPROM_DATA(0x02,0x5a,0x02,0x50,0x02,0x46,0x02,0x3c); /* 20-23℃ */ __EEPROM_DATA(0x02,0x32,0x02,0x28,0x02,0x1d,0x02,0x13); /* 24-27℃ */ __EEPROM_DATA(0x02,0x09,0x02,0x00,0x01,0xf6,0x01,0xec); /* 28-31℃ */ __EEPROM_DATA(0x01,0xe2,0x01,0xd9,0x01,0xcf,0x01,0xc6); /* 32-35℃ */ __EEPROM_DATA(0x01,0xbc,0x01,0xb3,0x01,0xaa,0x01,0xa1); /* 36-39℃ */ __EEPROM_DATA(0x01,0x98,0x01,0x8f,0x01,0x87,0x00,0x7e); /* 40-43℃ */ __EEPROM_DATA(0x01,0x76,0x01,0x6d,0x01,0x65,0x01,0x5d); /* 44-47℃ */ __EEPROM_DATA(0x01,0x56,0x01,0x4e,0x01,0x46,0x01,0x3f); /* 48-51℃ */ __EEPROM_DATA(0x01,0x38,0x01,0x30,0x01,0x29,0x01,0x22); /* 52-55℃ */ __EEPROM_DATA(0x01,0x1c,0x01,0x15,0x01,0x0f,0x01,0x08); /* 56-59℃ */ __EEPROM_DATA(0x01,0x02,0x00,0xfc,0x00,0xf6,0x00,0xf0); /* 60-63℃ */ __EEPROM_DATA(0x00,0xeb,0x00,0xe5,0x00,0xe0,0x00,0xda); /* 64-67℃ */ __EEPROM_DATA(0x00,0xd5,0x00,0xd0,0x00,0xcb,0x00,0xc7); /* 68-71℃ */ __EEPROM_DATA(0x00,0xc2,0x00,0xbd,0x00,0xb9,0x00,0xb4); /* 72-75℃ */ __EEPROM_DATA(0x00,0xb0,0x00,0xac,0x00,0xa8,0x00,0xa4); /* 76-79℃ */ __EEPROM_DATA(0x00,0xa0,0x00,0x9c,0x00,0x99,0x00,0x95); /* 80-83℃ */ __EEPROM_DATA(0x00,0x92,0x00,0x8e,0x00,0x8b,0x00,0x88); /* 84-87℃ */ __EEPROM_DATA(0x00,0x85,0x00,0x81,0x00,0x7e,0x00,0x7c); /* 88-91℃ */ __EEPROM_DATA(0x00,0x79,0x00,0x76,0x00,0x73,0x00,0x71); /* 92-95℃ */ __EEPROM_DATA(0x00,0x6e,0x00,0x6c,0x00,0x69,0x00,0x67); /* 96-99℃ */ __EEPROM_DATA(0x00,0x64,0x00,0x62,0x00,0x60,0x00,0x5e); /*============================================================================= * ROMデータ *============================================================================*/ /* 温度 vs FAN PWMテーブル */ #define PWM_NUMBER 7 const unsigned char temp_thd[PWM_NUMBER]= {50,45,40,35,30,25,20}; /* 温度 ℃ */ const unsigned char fan_pwm[PWM_NUMBER+1] = {100,70,55,40,30,20,10,2}; /* PWM % */ const unsigned int fan_rpm[PWM_NUMBER+1] = {3200, 3100, 2600, 2100, 1800, 1400, 1200, 900}; /* FAN 回転数 RPM */ /*============================================================================= * 変数 *============================================================================*/ unsigned char adc_h, adc_l; /* AD 結果 work */ char current_temp; /* 現在温度 */ unsigned int pwm; /* 200 = 100% = 100us */ unsigned int t10ms, t10ms_dec, t100ms, t100ms2, t1s, t1s2, t1s_dec; char usb_flag[4]; unsigned int usb_timer[4]; unsigned int ccpr1_copy; unsigned int led_out_data; /* out data for 2099FV */ char portb_copy; unsigned char in_data[4], out_data[4]; /*============================================================================= * 割り込み処理 *============================================================================*/ void interrupt intr(void){ /* 10ms Timer0 処理 */ if (T0IE == 1 && T0IF == 1){ /* Every 10ms */ TMR0 = 100; T0IF = 0; t10ms++; --t10ms_dec; /* 100msカウント */ if(t10ms >= 10){ t10ms = 0; t100ms++; t100ms2++; } /* 1秒カウント */ if(t100ms >= 10){ /* 100ms x 10 -> 1sec */ t100ms = 0; usb_timer[0]++; usb_timer[1]++; usb_timer[2]++; usb_timer[3]++; t1s++; t1s2++; --t1s_dec; } /* 1時間カウント */ if(t1s >= 3600){ t1s = 0; } } /* USB Power ON でSleepから復帰 */ if(RBIF && IOCB){ portb_copy = PORTB; RBIF = 0; } /* CCPR1 Capture Intr */ if(CCP1IE == 1 && CCP1IF == 1){ ccpr1_copy = CCPR1; TMR1 = 0; CCP1IF = 0; } } /*============================================================================= * ADC読込処理 *============================================================================*/ unsigned int adc_read(char ch, int ave_num, char mode){ unsigned int adc_int; /* ADC値の平均用 */ unsigned int adc_tmp; unsigned long adc_long; unsigned char k; adc_long = 0; adc_tmp = 0; for(k=0; k 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); } /*============================================================================= * 温度測定 *============================================================================*/ unsigned char temp(void){ char n,t; unsigned int ad_data; unsigned int temp_data; t = EEPROM_TEMP_DATA; ad_data = adc_read(AN_THRM, 10, ADC_AVE_MODE); for (n=0; n<100; n++){ temp_data = ((eeprom_read(t) << 8) + eeprom_read(t+1)); if(ad_data >= temp_data) break; t += 2; } current_temp = n; return n; } /*============================================================================= * LED制御 *============================================================================*/ void led_ctrl(void){ unsigned int led_copy, data_bit, led_out; unsigned char n; led_copy = led_out_data; data_bit = 0; for (n=0; n<12; n++){ data_bit = data_bit + (led_copy & 1); led_copy = led_copy >> 1; data_bit = data_bit << 1; } data_bit = ~data_bit; for (n=0; n<12; n++){ data_bit = data_bit >> 1; led_out = data_bit & 1; IO_DATA = led_out; IO_CLOCK = 0; __delay_us(1); IO_CLOCK = 1; __delay_us(1); } IO_LCK = 0; __delay_us(1); IO_LCK = 1; } /*============================================================================= * HDD USB電源ON/OFFチェック *============================================================================*/ void usb_check(unsigned char num){ unsigned char n; unsigned int led_work; led_work = 0; /* USB電源ON/OFF状態読込 */ switch(num){ case 0: in_data[0] = PORTBbits.USB0; break; case 1: in_data[1] = PORTBbits.USB1; break; case 2: in_data[2] = PORTBbits.USB2; break; case 3: in_data[3] = PORTBbits.USB3; break; default: break; } /* HDD電源 ON/OFF制御 */ if(in_data[num]){ usb_flag[num] = IN_USE; out_data[num] = 1; /* HDD Power ON */ }else{ /* 電源ON → OFFへのカウント開始 */ if(usb_flag[num] == IN_USE){ usb_timer[num] = 0; usb_flag[num] = IN_COUNT; out_data[num] = 1; /* HDD Power ON継続 */ } /* カウント終了 → HDD電源OFF処理 */ else if((usb_flag[num] == IN_COUNT) && (usb_timer[num] > USB_TIME_UP)){ usb_flag[num] = TIME_UP; out_data[num] = 0; /* HDD Power OFF */ } } switch(num){ case 0: PORTCbits.HDD0 = out_data[0]; break; case 1: PORTCbits.HDD1 = out_data[1]; break; case 2: PORTCbits.HDD2 = out_data[2]; break; case 3: PORTCbits.HDD3 = out_data[3]; break; default: break; } /* ACCESS LED ON or OFF */ led_work = (led_out_data >> 3) & 0xf; n = 0; while(n<4){ if(usb_flag[n] != TIME_UP){ led_work = led_work | 1; } led_work = led_work << 1; n++; } led_work = led_work << 2; led_out_data = (led_out_data & ~LED_ACC_ALL) | led_work & LED_ACC_ALL; led_ctrl(); } /*============================================================================= * MAIN *============================================================================*/ void main(void) { char pwr_state; unsigned int n, fan_num; unsigned char now_temp; unsigned int fan_val; unsigned long fan_freq; /* CPU Clock 設定 */ OSCCON = 0b01110001; /* Clock 8MHz internal */ /* PORT A/B/C 入出力設定 (1b:Input 0b:Output) */ TRISA = 0b00000011; /* Port A 入出力設定 */ PORTA = 0b01100000; /* PortA */ WPUB = 0b01110000; /* Port B Weak PullUp */ TRISB = 0b11111111; /* Port B 入出力設定 */ IOCB = 0b10110111; /* Port B IOC intr */ PORTB = 0b00000000; /* PortB */ TRISC = 0b00000111; /* Port C 入出力設定 */ PORTC = 0b00000000; /* PortC */ /* A/Dコンバータ設定 */ ANSEL = 0b00000011; /* Use AN0-1 */ ANSELH = 0b00000000; /* Use ANxx */ ADCON0 = 0b10000001; /* FOSC/32 = 4us, AD enable */ ADCON1 = 0b10000000; /* Right justified, VDD, VSS */ /* コンパレータ設定 Use C12IN1-, C2OUT, C2Vref */ CM1CON0 = 0; /* Comparator 1 Disable */ CM2CON0 = 0b10110101; /* Comparator 2 Enable, Invert C2OUT */ CM2CON1 = 0b00010010; /* */ SRCON = 0b00000000; VRCON = 0b00101011; /* CVref=3.1V */ /* キャプチャ設定 */ CCP1CON = 0b00000110; /* CCP1 is Capture mode. Every 4 rising edge */ CCP1IE = 1; CCP1IF = 0; /* TIMER0 設定(タイマ割り込み用) */ OPTION_REG = 0b00000110; /* Prescaler -> 1:128 (64us) */ TMR0 = 100; /* ≒ 10ms */ T0IE = 1; T0IF = 0; /* TIMER1 設定(キャプチャ用) */ T1CON = 0b00110001; /* 16bit mode RD16:1 */ /* Prescaler -> 1:8 */ /* Clock Source -> Internal */ /* Timer1 -> Start */ TMR1IE = 0; /* Timer1 Interrupt Disable */ TMR1 = 0; /* Timer1 Value Set */ TMR1IF = 0; /* Timer1 Interrupt Flag Clear */ /* PWM用 TIMER2 設定 */ PR2 = 50; /* PWM Cycle 10KHz */ CCP2CON = 0b00001100; /* PWM Mode & Duty 2LSB */ CCPR2L = 0b00110011; /* Duty 100%=0xC8+4, 8MSB */ CCPR2H = 0; TMR2IE = 0; /* Timer2 Interrupt Disable */ TMR2IF = 0; /* Timer2 Interrupt Flag Clear */ T2CON = 0b00000001; /* Prescaler = 1:4 */ TMR2ON = 1; /* Timer 2 Enable */ TRISC = 0b00000101; /* Port C 入出力設定 */ pwr_state = ST_PWRON; t1s = 0; fan_num = 0; usb_flag[0] = usb_flag[1] = usb_flag[2] = usb_flag[3] = TIME_UP; usb_timer[0] = usb_timer[1] = usb_timer[2] = usb_timer[3] = 0; out_data[0] = out_data[1] = out_data[2] = out_data[3] = 0; RBIF = 0; RBIE = 1; /* PORTB Change Intr Enb. */ PEIE = 1; /* Perifheral Intr Enb. */ GIE = 1; /* LED */ led_out_data = LED27_POWER; led_ctrl(); for(n = 0; n<4; n++){ t1s2 = 0; usb_check(n); while(t1s2 < 7); } while(1){ switch(pwr_state){ case ST_PWRON: led_out_data |= LED27_POWER; led_ctrl(); /* HDD USB ON/OFF CHECK */ for(n = 0; n<4; n++){ usb_check(n); } /* 温度チェック */ if(t1s >= TEMP_UP_TIME){ t1s = 0; now_temp = temp(); // now_temp = 51; /* FAN PWM設定 */ for(n=0; n < PWM_NUMBER; n++){ if(now_temp > temp_thd[n]){ break; } } fan_num = n; pwm = (fan_pwm[n] * 2); CCPR2L = pwm >> 2; t1s2 = 0; } /* 低温かつ全USB OFF時はSLEEPする */ if(now_temp < NORMAL_TEMP){ if(usb_flag[0] == TIME_UP && usb_flag[1] == TIME_UP && usb_flag[2] == TIME_UP && usb_flag[3] == TIME_UP){ pwr_state = ST_SLEEP; } } /* FAN回転数チェック */ if(t1s2 > FAN_RPM_CHK_TIME){ t1s2 = 0; fan_val = ccpr1_copy; /* FAN 1回転時間 (x 4uS) */ fan_freq = 60000000UL / (unsigned long)fan_val; fan_val = (unsigned int)fan_freq; /* 設定回転数以上か? */ if(fan_val < fan_rpm[fan_num]) { led_out_data |= LED1_MESSAGE; /* FAN 回転数不足 */ }else { led_out_data &= ~LED1_MESSAGE; /* 正常 */ } led_ctrl(); } break; case ST_SLEEP: led_out_data = led_out_data & ~LED27_POWER; led_ctrl(); SLEEP(); /* USB Power ONで復帰する */ __delay_ms(1000); pwr_state = ST_PWRON; break; default: break; } } }