// mykeyer.c // R. Traylor // 12.19.2010 // iambic keyer #define F_CPU 8000000UL //8Mhz clock #include #include #include #include //Note: ATmega48 is supplied with 8 Mhz RC internal clock enabled with //clkdiv programmed which sets internal clock to 1Mhz. // I/O allocation //ADC7 analog pin to read the speed value //PC0 when low, dot paddle closed //PC1 when low, dash paddle closed //PC2 drives the driver xistor that closes the key connection //PC3 mute2, relay output, when high, xmitter is connected to antenna //PC4 mute1, mute output, when high, reciever is muted //PC5 spare, unused //PD0 encoder a pin //PD1 encoder b pin //PD3 pin 1, OC2B compare output for sidetone //main keyer state machine states #define IDLE 0 //waiting for a paddle closure #define DIT 1 //making a dit #define DAH 2 //making a dah #define DIT_DLY 3 //intersymbol delay, one dot time #define DAH_DLY 4 //intersymbol delay, one dot time // #define FALSE 0 #define TRUE 1 // //define EEPROM storage areas uint8_t EEMEM eeprom_wds_per_min = 20; //this value only assigned during programming volatile uint8_t keyer_state = IDLE; //the keyer state volatile uint8_t timer_ena = 0; //the timer enable volatile uint8_t dit_pending = FALSE; //memory for dits volatile uint8_t dah_pending = FALSE; //memory for dahs volatile uint16_t timeout ; //one dot interval volatile uint16_t half_timeout ; //one half dot interval volatile uint8_t key = FALSE; //internal keyer output volatile int16_t ee_wait_cnt = -1; //countdown to save new setting to eeprom volatile uint8_t wds_per_min = 20; //words per minute (still need to intalize if in EEPROM?) //output state machine states #define IDLE 0 // #define A 1 // #define B 2 // #define C 3 // #define D 4 // #define E 5 // #define F 6 // #define G 7 // #define H 8 // #define I 9 // //output state machine variables volatile uint8_t output_state = IDLE; volatile uint8_t tx_dly = 0x00; volatile uint8_t mute1_timeout = 4; //500uS for audio mute to engage volatile uint8_t relay_timeout = 31; //4mS for relay to actuate volatile uint8_t tx_decay = 39; //5mS for xmit envelope to decay //functions void tx_on() {PORTC &= ~0b00000100;} //asserts key output void tx_off() {PORTC |= 0b00000100;} //deasserts key output uint8_t dit_on() {return(bit_is_clear(PINC, 0));} //returns non-zero if dit paddle on uint8_t dah_on() {return(bit_is_clear(PINC, 1));} //returns non-zero if dah paddle on /***************************** mute1 ****************************************/ void mute1(state){if(state==TRUE){PORTC |= (1< half_timeout))) { dit_pending = TRUE;} break; case (TRUE) : if(keyer_state == DIT){dit_pending = FALSE;} break; }//switch dit_pending //****************** dah pending main state machine ********************* switch(dah_pending){ //see if a dah is pending case (FALSE) : if( (dah_on() && (keyer_state == DIT) & (timer < half_timeout)) || (dah_on() && (keyer_state == DIT_DLY) & (timer > half_timeout))) {dah_pending = TRUE;} break; case (TRUE) : if(keyer_state == DAH){dah_pending = FALSE;} break; }//switch dah_pending //****************** state machine for the output sequencer ********* tx_dly--; //decrement the delay counter for the output sequencer switch(output_state){ case (IDLE) : if(key==TRUE){ tx_dly = mute1_timeout; output_state=A;} //delay from mute1 to relay on break; case (A) : mute1(TRUE); if(!tx_dly){tx_dly=relay_timeout; output_state=B;} //delay from mute2 to relay on break; case (B) : mute2(TRUE); if(!tx_dly){output_state=C;} //wait for relay break; case (C) : if(key==FALSE){tx_dly=mute1_timeout+relay_timeout+1; output_state=D;} //equalize key low else{tx_on(); TCCR2B = (1< 5){wds_per_min--; }//check, bound and possibly decrement speed else {wds_per_min = 5; } ee_wait_cnt=32760; //countdown to save new setting to eeprom break; //decrease speed case (1) : if(wds_per_min < 60){wds_per_min++; }//check, bound and possibly increment speed else {wds_per_min = 60;} ee_wait_cnt=32760; //countdown to save new setting to eeprom break; //increase speed case (-1): break; //no change } //switch //*************** see if we need to save the present speed setting ************** if(ee_wait_cnt>0){ee_wait_cnt--;} //keep counting down till its time to write else if(ee_wait_cnt==0){ //upon reaching zero, we save the setting eeprom_write_byte(&eeprom_wds_per_min, wds_per_min); //save the setting ee_wait_cnt--; //decrement to -1 to prevent more writes } } //**************** end of ISR for TIMER1_COMPA_vect *************************** //********************** startup initalization code **************************** void setup() // run once, at startup { //initalize the pins DDRC |= (1<> 1); } //do forever }//main