//**************************************************************************** // wigwag.c - Open Source Wig-Wag Project // // Written in 2012 by Greg McHugh, gregmchugh@hotmail.com // // Creative Commons CC0 1.0 Universal Public Domain Dedication // To the extent possible under law, the author(s) have dedicated all copyright // and related and neighboring rights to this software to the public domain // worldwide. This software is distributed without any warranty. // For more detailed information on this public domain dedication, see // http://creativecommons.org/publicdomain/zero/1.0/ //**************************************************************************** // // This software is designed to be flashed into the PIC12F683 microcontroller // contained in the Open Source Wig-Wag controller. Details on the functional // requirements for the software are provided in the description of the // controller module. // // Target Hardware: Open Source Wig-Wag Controller Rev. B // Target Micro: Microchip PIC12F683 // Development Tools: MPLAB IDE Ver. 8.84 // HI-TECH C Compiler (Lite Mode) Ver. 9.83 // PICkit 1 Flash Starter Kit // PICkit 1 Classic Flash Ver. 1.74 // // Version History: Ver. 0.1 - Release for hardware integration testing // //**************************************************************************** #include // Set up the Configuration Bits for the Micro (see PIC12F683 Datasheet). // In-circuit debug requires the external reset line (MCLR) to be active // and the Power Up Timer to be disabled. #ifdef __DEBUG __CONFIG( FCMEN_OFF & IESO_OFF & BOREN_OFF & CPD_OFF & CP_OFF & MCLRE_ON & PWRTE_OFF & WDTE_OFF & FOSC_INTOSCIO ); #else __CONFIG( FCMEN_OFF & IESO_OFF & BOREN_OFF & CPD_OFF & CP_OFF & MCLRE_OFF & PWRTE_OFF & WDTE_OFF & FOSC_INTOSCIO ); #endif // Hardware I/O Definitions // // Notes: Hardware switch inputs read Low when switch is activated // Wig-Wag mode is indicated by both switch inputs High // Output pins are set High to activate Lamps #define DIGINRAW1 GP0 // Steady On Command Input GP0 #define DIGINRAW2 GP1 // Lamps Off Command Input GP1 #define LAMP1ON 0b00100000 // Lamp 1 Control Output GP5 #define LAMP2ON 0b00010000 // Lamp 2 Control Output GP4 #define BOTHLAMPSON 0b00110000 // Both Lamps On #define BOTHLAMPSOFF 0b00000000 // Both Lamps Off // DeBounce Definitions // // Notes: The major source for bounce in this application is the closure of // hardware switches which ground input pins and transition the inputs // from High to Low. See the DeBounce function for details on the logic // used to debounce the raw inputs and the use of the following // parameters in the debounce logic. Note that protection is also // provided for transitions from Low to High. #define VALIDHIGHCOUNT1 5 // Number of constant raw readings needed to #define VALIDLOWCOUNT1 20 // trigger valid debounced input values for #define VALIDHIGHCOUNT2 5 // the two input pins. Values can be adjusted #define VALIDLOWCOUNT2 20 // for specific switch characteristics. // Wig-Wag Logic Definitions #define WIGWAGSWITCHTIME 750 // Time duration for wig-wag interval, measured // in main loop cycles. #define OFF 0 #define ON 1 // Function Prototypes void DeBounce( unsigned char DigInRaw, unsigned char *DigIn, unsigned char *LowCount, unsigned char *HighCount, unsigned char ValidLowCount, unsigned char ValidHighCount ); //*************************************************************************** // Main() - Main Routine //*************************************************************************** void main(void) { unsigned char DigIn1 = 1; // DeBounced digital inputs. Initialized unsigned char DigIn2 = 0; // to the Lamps Off mode. unsigned char HighCount1 = 0; // Counts for the number of constant High unsigned char LowCount1 = 0; // or Low raw input readings. Only one unsigned char HighCount2 = 0; // counter is active depending on the unsigned char LowCount2 = 0; // last raw value. unsigned char WigWag = OFF; // Wig-Wag state, set to OFF or ON unsigned int WigWagTimer = 0; // Timer for wig-wag interval //*************** // Initialization //*************** // Set Up Micro I/O GPIO = 0b00000000; // From initialization example in datasheet CMCON0 = 0b00000111; // Configure comparator inputs as digital I/O ANSEL = 0b00000000; // Configure A/D inputs as digital I/O TRISIO = 0b00001111; // GPIO 0,1,2,3 inputs, GPIO 4,5 outputs GPIO = BOTHLAMPSOFF; // Initialize Both Lamps Off // Set up a 1 millisec Main Processing Loop. With the default // 4MHz internal clock, Timer0 is driven at 1MHz, and with a // 1:4 prescale will overflow every 1.024 millisec (8 bit timer). OPTION_REG = 0b11010001; // Timer0 internal clock, 1:4 prescale TMR0 = 0; // Clear Timer0 to start the count T0IF = 0; // Clear Timer0 overflow flag //********************* // Main Processing Loop //********************* while(1) { if ( T0IF ) // Check for Timer0 overflow { T0IF = 0; // Reset Timer0 overflow flag DeBounce( DIGINRAW1, &DigIn1, &LowCount1, &HighCount1, VALIDLOWCOUNT1, VALIDHIGHCOUNT1 ); DeBounce( DIGINRAW2, &DigIn2, &LowCount2, &HighCount2, VALIDLOWCOUNT2, VALIDHIGHCOUNT2 ); // Control Lamps based on current debounced inputs if ( DigIn1 && DigIn2 ) // High-High = Wig-Wag { if ( !WigWag ) { WigWag = ON; // Initialize Wig-Wag mode GPIO = LAMP1ON; // Start wig-wag with Lamp 1 WigWagTimer = 0; } else if ( ++WigWagTimer == WIGWAGSWITCHTIME ) { GPIO ^= BOTHLAMPSON; // XOR flips both Lamps WigWagTimer = 0; } } else if ( DigIn1 ) // High-Low = Both Lamps off { GPIO = BOTHLAMPSOFF; WigWag = OFF; } else if ( DigIn2 ) // Low-High = Both Lamps on { GPIO = BOTHLAMPSON; WigWag = OFF; } else // Low-Low = Undefined state { GPIO = BOTHLAMPSOFF; WigWag = OFF; } } } } //***************************************************************************** // DeBounce Function - Looks for a series of constant raw inputs to produce // a valid debounced input. The debounced value will not // be changed until a valid series of raw inputs occurs // indicating a change in value. The specific number of // constant inputs that will trigger the debounce can // be specified for each switch input and for transitions // from Low to High and from High to Low. Note that only // one counter is active at any time depending on the // state of the last raw input processed. //**************************************************************************** void DeBounce( unsigned char DigInRaw, unsigned char *DigIn, unsigned char *LowCount, unsigned char *HighCount, unsigned char ValidLowCount, unsigned char ValidHighCount ) { if ( DigInRaw && (*HighCount < ValidHighCount) ) //Check for High input { ++*HighCount; *LowCount = 0; if ( *HighCount == ValidHighCount ) *DigIn = DigInRaw; } else if ( !DigInRaw && (*LowCount < ValidLowCount) ) // Check for Low input { ++*LowCount; *HighCount = 0; if ( *LowCount == ValidLowCount ) *DigIn = DigInRaw; } }