/////////////////////////////////////////////////////// // // // AUTO KEYER // // ON7EQ // // // /////////////////////////////////////////////////////// /* Functional description : 4 push buttons provided to trigger playback of each message. A short tap on a button will generate a "single shot" message (just like on the transceiver panel). A longer press will start the playback of corresponding message, and set the unit in repeat mode. The interval between messages (= pause) can be adjusted by a potentiometer between 1 and 20 seconds (irrespective of message lenght). Visual indication of mode : 2 possibilities, with no software change required : - One LED : flashing briefly in single shot mode, constantly lit in repeat mode, for any message played. - Four LEDs : same as above, but the LED corresponding to the message / button is lit. Can be used with buttons where LED are integrated. At any time, in any mode, the message playback can be immediately ended by depressing any button. If any button is depressed while in repeat mode, repeat mode is halted and keyer is reverting into stand-by mode. If the PTT (or footswitch, CW key...) is depressed during a pause in repeat mode (e.g. reverting to a calling station), the auto mode is halted and the keyer is reverting into stand-by mode. */ #define input1 5 // pushbutton 1 input pin (pushbutton depressed = LOW) #define input2 6 // pushbutton 2 input pin #define input3 7 // pushbutton 3 input pin #define input4 8 // pushbutton 4 input pin #define output1 9 // output 1 pin - to open collector NPN - output active = HIGH #define output2 10 // output 2 pin - to open collector NPN #define output3 11 // output 3 pin - to open collector NPN #define output4 12 // output 4 pin - to open collector NPN #define LED_output 13 // output pin - to LED - if only one LED #define LED_output1 A5 // output pin - to LED corresponding with button 4 (optional) #define LED_output2 A4 // output pin - to LED corresponding with button 3 (optional) #define LED_output3 A3 // output pin - to LED corresponding with button 2 (optional) #define LED_output4 A2 // output pin - to LED corresponding with button 1 (optional) #define PTT_read A1 // input for reading PTT (to define RX/TX status) #define Delay_pot_pin A0 // input for reading potentiometer for delay byte mode = 0; byte button = 0; byte longpress = 0; byte OneShot = 0; // one shot flag byte Repeat = 0; byte arm = 0; // arm for repress detect in repeat mode byte stop_by_PTT = 0; byte EOM_flag = 0; // end of message flag byte button_pressed = 0; int unsigned long RX_time = 0; int unsigned long RepeatInterval = 0; int unsigned long Button_time_pressed = 0; int unsigned long EOM_time = 0; //////////////////////////////////////////////////////////// //////////////////// S E T U P ////////////////////////// //////////////////////////////////////////////////////////// void setup() { pinMode (input1, INPUT); pinMode (input2, INPUT); pinMode (input3, INPUT); pinMode (input4, INPUT); //Activate pull-ups digitalWrite(input1, HIGH); digitalWrite(input2, HIGH); digitalWrite(input3, HIGH); digitalWrite(input4, HIGH); digitalWrite(PTT_read, HIGH); pinMode (output1, OUTPUT); pinMode (output2, OUTPUT); pinMode (output3, OUTPUT); pinMode (output4, OUTPUT); digitalWrite(output1, LOW); digitalWrite(output2, LOW); digitalWrite(output3, LOW); digitalWrite(output4, LOW); pinMode (LED_output, OUTPUT); pinMode (LED_output1, OUTPUT); pinMode (LED_output2, OUTPUT); pinMode (LED_output3, OUTPUT); pinMode (LED_output4, OUTPUT); digitalWrite(LED_output, LOW); digitalWrite(LED_output1, LOW); digitalWrite(LED_output2, LOW); digitalWrite(LED_output3, LOW); digitalWrite(LED_output4, LOW); } /////////////////////////////////////////// //////////// L O O P /////////////// /////////////////////////////////////////// void loop() { if (Repeat == 0) { // single shot mode button actions // check if any button depressed, and define mode if (digitalRead(input1) == LOW) button = 1; // any of 4 buttons pressed else if (digitalRead(input2) == LOW) button = 1; else if (digitalRead(input3) == LOW) button = 1; else if (digitalRead(input4) == LOW) button = 1; else { // no button pressed button = 0; // no button pressed if (button_pressed == 1) button_pressed = 0; // button was released OneShot = 0; // be ready for new pulse longpress = 0; // long press released } if ((button == 1) and (mode < 20)) { delay (30); //Crude debounce if (digitalRead(input1) == LOW) button = 11; // Button 1 effectively pressed else if (digitalRead(input2) == LOW) button = 12; // Button 1 effectively pressed else if (digitalRead(input3) == LOW) button = 13; // Button 1 effectively pressed else if (digitalRead(input4) == LOW) button = 14; // Button 1 effectively pressed else { button = 0; // it was bounce or button was released button_pressed = 0; longpress = 0; OneShot = 0; // be ready for new pulse } if ((button_pressed == 0) and (button > 10) and (button < 20)) { button_pressed = 1; // a button was depressed ! Button_time_pressed = millis(); // time stamp a button pressed } } if ((button_pressed == 1) and (millis() - Button_time_pressed > 300) ) { // check if long press on button > 0.5 sec if (longpress == 0) { // going into repeat mode longpress = 1; // button pressed for repeat mode ! if (digitalRead(input1) == LOW) mode = 21; // Button 1 else if (digitalRead(input2) == LOW) mode = 22; // Button 2 else if (digitalRead(input3) == LOW) mode = 23; // Button 3 else if (digitalRead(input4) == LOW) mode = 24; // Button 4 digitalWrite(LED_output, HIGH); // Repeat mode RX_time = millis () + 60000; // set repeat timer } } } // end single shot mode if (Repeat == 1) { // repeat mode button actions // Wait for button released = arm condition ! if ((digitalRead(input1) == LOW) // any of 4 buttons pressed ? or (digitalRead(input2) == LOW) or (digitalRead(input3) == LOW) or (digitalRead(input4) == LOW)) { delay (0) ; // do nothing } else (arm = 1); // button released, arm for repress => force stop // Wait for button pressed = exit mode ! if (((digitalRead(input1) == LOW) // any of 4 buttons pressed ? or (digitalRead(input2) == LOW) or (digitalRead(input3) == LOW) or (digitalRead(input4) == LOW)) and (arm == 1)) { arm =0; mode = 99; // Exit repeat mode } } // end repeat mode button actions //////////////////////////////////////////////////////////// /////////////// Take actions according to mode /////////// //////////////////////////////////////////////////////////// /////////////////// Single press //////////////// if ((button_pressed == 1) and (OneShot == 0) ) { digitalWrite(LED_output, HIGH); if (button == 11) { digitalWrite(output1, HIGH); digitalWrite(LED_output1, HIGH); } if (button == 12) { digitalWrite(output2, HIGH); digitalWrite(LED_output2, HIGH); } if (button == 13) { digitalWrite(output3, HIGH); digitalWrite(LED_output3, HIGH); } if (button == 14) { digitalWrite(output4, HIGH); digitalWrite(LED_output4, HIGH); } delay (100); // pulse keyer digitalWrite(output1, LOW); digitalWrite(output2, LOW); digitalWrite(output3, LOW); digitalWrite(output4, LOW); digitalWrite(LED_output, LOW); digitalWrite(LED_output1, LOW); digitalWrite(LED_output2, LOW); digitalWrite(LED_output3, LOW); digitalWrite(LED_output4, LOW); OneShot = 1; } ///////////////// Long press ////////////// if ((mode > 20) and (mode < 30)) { Repeat = 1; RepeatInterval = map(analogRead(Delay_pot_pin), 0, 1023, 1000, 20000); // 1 to 20 sec interval // Generate repeat pulse after interval, only in in RX if ((millis() - RX_time > RepeatInterval) and (EOM_flag == 1) and (analogRead(PTT_read) > 500)) { RX_time = millis (); EOM_flag = 0; if (mode == 21) digitalWrite(output1, HIGH); if (mode == 22) digitalWrite(output2, HIGH); if (mode == 23) digitalWrite(output3, HIGH); if (mode == 24) digitalWrite(output4, HIGH); digitalWrite(LED_output, LOW); digitalWrite(LED_output1, LOW); digitalWrite(LED_output2, LOW); digitalWrite(LED_output3, LOW); digitalWrite(LED_output4, LOW); delay (100); // Pulse output digitalWrite(LED_output, HIGH); if (mode == 21) digitalWrite(LED_output1, HIGH); if (mode == 22) digitalWrite(LED_output2, HIGH); if (mode == 23) digitalWrite(LED_output3, HIGH); if (mode == 24) digitalWrite(LED_output4, HIGH); digitalWrite(output1, LOW); digitalWrite(output2, LOW); digitalWrite(output3, LOW); digitalWrite(output4, LOW); } delay(50); // extra delay - allow TRX to go into TX mode and bring PTT line down if (analogRead(PTT_read) < 500) RX_time = millis () ; if ((analogRead(PTT_read) < 500) and (EOM_flag == 0)) { // Higher than 2,5 V on PTT line = RX // // RX_time = millis (); // timestamp going into RX mode. as long as in TX, RX_time is reset to millis() EOM_time = millis(); // timestamp end of message } if (analogRead(PTT_read) > 500) EOM_flag = 1; // PTT line becomes HIGH, message has been played. Required to detect subsequent stop by PTT // STOP BY PTT during pause interval if (((millis( )- EOM_time > 50)) and (millis() < (EOM_time + RepeatInterval - 50)) and (analogRead(PTT_read) < 500) and (arm == 1)) { // PTT depressed during pause between messages --> stop keyer! stop_by_PTT = 1; arm = 0; mode = 99; EOM_flag = 0; } } // end of repeat mode // EXIT REPEAT MODE if (mode == 99) { Repeat = 0; digitalWrite(LED_output, LOW); digitalWrite(LED_output1, LOW); digitalWrite(LED_output2, LOW); digitalWrite(LED_output3, LOW); digitalWrite(LED_output4, LOW); mode = 0; // check if message playing, issue a pulse to stop if ((analogRead(PTT_read) < 500) and (stop_by_PTT == 0)) { // Yes, PTT is low, and was not forced stop by keying digitalWrite(output1, HIGH); delay (100); // Pulse output digitalWrite(output1, LOW); } stop_by_PTT = 0; //wait till buttons released before looping again while ((digitalRead(input1) == LOW) // if any of 4 buttons pressed, wait till released ! or (digitalRead(input2) == LOW) or (digitalRead(input3) == LOW) or (digitalRead(input4) == LOW)) {} delay (100); } } // End of loop