/*------------------------------------------------------------------ | | Control circuit for the M0UKD sensor keyer | | (C) Dietmar Krause, DL2SBA, 2016 | http://www.dl2sba.com | | This software is licended under | | https://creativecommons.org/licenses/by-nc/4.0/ | https://creativecommons.org/licenses/by-nc/4.0/deed.de | | | The CPU polls in 1s interval the input PB3 | If low level is detected on PB3, the power on PB2 is enabled to power the sensor keyer | If NO high level is found on PB0/PB1 within 15min, the power on PB2 is turned off | | So you have to pull PB3 low for maximum of 1s to power up the keyer | | PB0 Dash or Dot - active high | PB1 Dash or Dot - active high | PB2 Power to keyer | PB3 pull low to wake up | PB5 do not connect - Reset pin | | Sensor keyer made by | http://m0ukd.com/homebrew/capacitive-cw-touch-key-circuits/ | | Define the macro TEST to run it on a breadboard with internal pull-ups | on PB0 + PB1 | -------------------------------------------------------------------*/ #include #include #include #include // #define TEST 1 // timeout counter uint32_t timeout = 0; #define WDT_FAST_TICKS 8 #define TIMEOUT_S 15 * 60 #define TIMEOUT_TICKS TIMEOUT_S * WDT_FAST_TICKS // // flash the led the // - given ms on // - given ms off void flashLed(int wait) { // PB2 on PORTB |= 0b00000100; _delay_ms(wait); PORTB &= 0b11111011; _delay_ms(wait); } // // Statemachine // States #define STATE_INIT 0 #define STATE_ON 1 #define STATE_WAIT_KEY 2 // // State variable uint8_t state = STATE_INIT; // // set the watchdog timeout to 1s void setWatchdogSlow(void) { WDTCR = _BV(WDIE) // Enable WDT Interrupt | _BV(WDP2) // timeout 1s | _BV(WDP1); } // // set the watchdog timeout to 125ms = 1/8s void setWatchdogFast(void) { WDTCR = _BV(WDIE) // Enable WDT Interrupt | _BV(WDP0) // timeout 0.125s | _BV(WDP1); } // // called whenever the watchdog triggers // ISR(WDT_vect) { // Disable sleepmode of CPU sleep_disable(); // state machine // initial state if ( state == STATE_INIT ) { // turn pullup on only at PB3 PORTB = 0b00001000; // wait for input to settle _delay_us(100); // is PINB3 low? if ( ( PINB & 0b00001000 ) == 0 ) { // yes // wait for key to settle _delay_ms(50); // wait for user to release key while ( ( PINB & 0b00001000 ) == 0 ); // switch state engine state = STATE_ON; // setup fast watchdog setWatchdogFast(); } // turn all pullups off PORTB = 0b00000000; } else if ( state == STATE_ON ) { // reset timeout timeout = 0; #ifdef TEST // switch keyer on PB2 = 1 // turn pullup on at PB0+PB1 // PB2 on PORTB |= 0b00001111; #else // switch keyer on PB2 = 1 // keep pullup on PB3 = 1 PORTB |= 0b00001100; #endif // now wait for key state = STATE_WAIT_KEY; } else if ( state == STATE_WAIT_KEY ) { // check if the power on button is pressed if (( PINB & 0b00001000 ) == 0 ) { // yes // wait for key to settle _delay_ms(50); // wait for user to release key while ( ( PINB & 0b00001000 ) == 0 ); // switch off keyer at PB2 // turn pullup off all pullups and PORTB = 0b00000000; // restart state engine state = STATE_INIT; // switch to slow watchdog setWatchdogSlow(); // any morse key down? } else if (( PINB & 0b00000011 ) > 0 ) { // yes // reset timeout timeout = 0; } else { // no // increment timeout timeout += 1; // timeout reached? if ( timeout > TIMEOUT_TICKS ) { // yes // switch off keyer at PB2 // turn pullup off at PB0+PB1 PORTB = 0b00000000; // restart state engine state = STATE_INIT; // switch to slow watchdog setWatchdogSlow(); } } } sleep_enable(); // Enable Sleep Mode } void setup(void) { DDRB = 0b00000100; // PB2 is output PORTB = 0b00000000; // disable all pullups flashLed(100); flashLed(100); flashLed(100); flashLed(100); // disable ADC uses ~300uA ADCSRA &= ~(1< Go to WDT ISR ****************************/ } } } int main(void) { setup(); loop(); return 0; }