#include #include #include #include #include #define _XTAL_FREQ 4000000 // CONFIG #pragma config FOSC = INTRCIO // Oscillator Selection bits (INTOSC oscillator: I/O function on RA4/OSC2/CLKOUT pin, I/O function on RA5/OSC1/CLKIN) #pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled) #pragma config PWRTE = ON // Power-up Timer Enable bit (PWRT enabled) #pragma config MCLRE = OFF // RA3/MCLR pin function select (RA3/MCLR pin function is digital I/O, MCLR internally tied to VDD) #pragma config BOREN = ON // Brown-out Detect Enable bit (BOD enabled) #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) #define BUTTON_ACTIVE (PORTAbits.RA0 == 0) #define VF_LOW PORTAbits.RA1 = 0 #define VF_HIGH PORTAbits.RA1 = 1 #define RST RA2 #define RST_T TRISA2 // common cathode LED #define LED_MASK_OFF 0b00000000; #define LED_MASK_RED 0b00100000; #define LED_MASK_GREEN 0b00010000; #define LED_MASK_YELLOW 0b00110000; // common anode LED //#define LED_MASK_OFF 0b00110000; //#define LED_MASK_RED 0b00010000; //#define LED_MASK_GREEN 0b00100000; //#define LED_MASK_YELLOW 0b00000000; enum eMode { m50Hz, m60Hz }; enum eMode CurrentMode; enum eMode NewMode; enum eFunction { fIdle, fReset, fSelecting }; enum eFunction Function; uint8_t press_time; bit old_button_state; void load_from_ee(void); void save_to_ee(void); void reset_pulse(void); void update_mode_pin(enum eMode M); void update_mode_led(enum eMode M); void init(void); void main() { init(); load_from_ee(); update_mode_pin(CurrentMode); update_mode_led(CurrentMode); Function = fIdle; while(1) { if(BUTTON_ACTIVE) // button pressed { __delay_ms(100); switch(Function) { case fIdle: Function = fReset; // idle -> reset PORTC = (PORTC & 0b00000111) | LED_MASK_OFF; break; case fReset: press_time++; if(press_time == 10) { press_time = 0; Function = fSelecting; // reset -> selecting if(CurrentMode == m50Hz) NewMode = m60Hz; else NewMode = m50Hz; update_mode_led(NewMode); } break; case fSelecting: press_time++; if(press_time == 10) { press_time = 0; if(NewMode == m50Hz) NewMode = m60Hz; else NewMode = m50Hz; update_mode_led(NewMode); } break; } } else // button not pressed { switch(Function) { case fIdle: // still idle break; case fReset: // released after short press reset_pulse(); Function = fIdle; press_time = 0; break; case fSelecting: // released after long press if(NewMode != CurrentMode) { CurrentMode = NewMode; update_mode_pin(CurrentMode); } Function = fIdle; press_time = 0; break; } } } } void load_from_ee(void) { CurrentMode = eeprom_read(0x00); if(CurrentMode > m60Hz) { CurrentMode = m50Hz; save_to_ee(); } } void save_to_ee(void) { eeprom_write(0x00, CurrentMode); } void reset_pulse() { RST = 0; RST_T = 0; __delay_ms(200); RST_T = 1; RST = 1; } void update_mode_pin(enum eMode M) { switch(M) { case m50Hz: VF_LOW; break; case m60Hz: VF_HIGH; break; } } void update_mode_led(enum eMode M) { switch(M) { case m50Hz: PORTC = (PORTC & 0b00000111) | LED_MASK_RED; break; case m60Hz: PORTC = (PORTC & 0b00000111) | LED_MASK_GREEN; break; } } void init(void) { CMCON = 0x07; // disable comparator PORTA = 0b00000000; TRISA = 0b00001101; WPUA = 0b00000001; // weak pull-up on input from reset switch OPTION_REGbits.nRAPU = 0; PORTC = 0b00000000; TRISC = 0b00001000; }