// // QRSS/FSKCW/DFCW Beacon Keyer // // Hans Summers G0UPL, 2012 // const char msg[] = "CALLSIGN "; // Message - put your callsign here, in capital letters // Remember to put a space at the end! const unsigned int speeds[] = {1, 30, 60, 100}; // Speeds for: 12wpm, QRSS3, QRSS6, QRSS10 #define KEY 0 // Keying is on pin 0 #define ATT 1 // Attenuator is on pin 1 (inverted keying) #define LED 13 // Standard Arduino LED output on pin 11 #define FSK 11 // FSK is generated by the PWM (analog) output on pin 11 #define MODE_NONE 0 // Mode NONE means the Power Amplifier is disabled #define MODE_QRSS 1 // QRSS mode (i.e. ordinary CW) #define MODE_FSKCW 2 // FSK CW mode #define MODE_DFCW 3 // DFCW mode #define FSK_HIGH 160 // Analog value for when FSK is high #define FSK_LOW 100 // Analog value for when FSK is low #define SWITCH1 7 // Switch pin definitions #define SWITCH2 6 #define SWITCH3 5 #define SWITCH4 4 // // Arduino setup function // void setup() { pinMode(KEY, OUTPUT); // Define Keying, attenuator, LED and FSK pins as outputs pinMode(ATT, OUTPUT); pinMode(LED, OUTPUT); pinMode(FSK, OUTPUT); pinMode(SWITCH1, INPUT); // Define Switch pins as inputs pinMode(SWITCH2, INPUT); pinMode(SWITCH3, INPUT); pinMode(SWITCH4, INPUT); digitalWrite(SWITCH1, true); // Enable internal pull-ups on switch inputs digitalWrite(SWITCH2, true); digitalWrite(SWITCH3, true); digitalWrite(SWITCH4, true); } // // Arduino loop function // void loop() { static unsigned long milliPrev; // Static variable stores previous millisecond count unsigned long milliNow; milliNow = millis(); // Get millisecond counter value if (milliNow != milliPrev) // If one millisecond has elapsed, call the beacon() function { milliPrev = milliNow; beacon(); } } // // function returns the encoded CW pattern for the character passed in // byte charCode(char c) { switch (c) { case 'A': return B11111001; break; // A .- case 'B': return B11101000; break; // B -... case 'C': return B11101010; break; // C -.-. case 'D': return B11110100; break; // D -.. case 'E': return B11111100; break; // E . case 'F': return B11100010; break; // F ..-. case 'G': return B11110110; break; // G --. case 'H': return B11100000; break; // H .... case 'I': return B11111000; break; // I .. case 'J': return B11100111; break; // J .--- case 'K': return B11110101; break; // K -.- case 'L': return B11100100; break; // L .-.. case 'M': return B11111011; break; // M -- case 'N': return B11111010; break; // N -. case 'O': return B11110111; break; // O --- case 'P': return B11100110; break; // P .--. case 'Q': return B11101101; break; // Q --.- case 'R': return B11110010; break; // R .-. case 'S': return B11110000; break; // S ... case 'T': return B11111101; break; // T - case 'U': return B11110001; break; // U ..- case 'V': return B11100001; break; // V ...- case 'W': return B11110011; break; // W .-- case 'X': return B11101001; break; // X -..- case 'Y': return B11101011; break; // Y -.-- case 'Z': return B11101100; break; // Z --.. case '0': return B11011111; break; // 0 ----- case '1': return B11001111; break; // 1 .---- case '2': return B11000111; break; // 2 ..--- case '3': return B11000011; break; // 3 ...-- case '4': return B11000001; break; // 4 ....- case '5': return B11000000; break; // 5 ..... case '6': return B11010000; break; // 6 -.... case '7': return B11011000; break; // 7 --... case '8': return B11011100; break; // 8 ---.. case '9': return B11011110; break; // 9 ----. case ' ': return B11101111; break; // Space case '/': return B11010010; break; // / -..-. default: return charCode(' '); } } // // Sets the FSK value (shift of the RF carrier) // void setFSK(boolean high) { if (high) analogWrite(FSK, FSK_HIGH); else analogWrite(FSK, FSK_LOW); } // // Enables the Power Amplifier and disables the attenuator // void setRF(boolean on) { digitalWrite(KEY, on); digitalWrite(ATT, !on); } // // This function is called 1000 times per second // void beacon() { static byte timerCounter; // Counter to get to divide by 100 to get 10Hz static int ditCounter; // Counter to time the length of each dit static byte pause; // Generates the pause between characters static byte msgIndex = 255; // Index into the message static byte character; // Bit pattern for the character being sent static byte key; // State of the key static byte charBit; // Which bit of the bit pattern is being sent static byte ditSpeed; // Index into the speeds array - controls the dit speed static byte mode; // What mode is being sent (None, QRSS, FSK/CW or DFCW) static boolean dah; // True when a dah is being sent byte divisor; // Divide 1kHz by 100 normally, but by 33 when sending DFCW) // Read the switches, to set the mode and speed mode = digitalRead(SWITCH1) + 2 * digitalRead(SWITCH2); ditSpeed = digitalRead(SWITCH3) + 2 * digitalRead(SWITCH4); if (mode == MODE_DFCW) // Divisor is 33 for DFCW, to get the correct timing divisor = 33; // (inter-symbol gap is 1/3 of a dit) else divisor = 100; timerCounter++; // 1000Hz at this point if (timerCounter == divisor) // Divides by 100 (or 33 for DFCW) { timerCounter = 0; // 10 Hz here (30Hz for DFCW) ditCounter++; // Generates the correct dit-length if (ditCounter >= speeds[ditSpeed]) { ditCounter = 0; if (!pause) { // Pause is set to 2 after the last symbol of the character has been sent key--; // This generates the correct pause between characters (3 dits) if ((!key) && (!charBit)) { if (mode == MODE_DFCW) pause = 3; // DFCW needs an extra delay to make it 4/3 dit-length else pause = 2; } } else pause--; // Key becomes 255 when the current symbol (dit or dah) has been sent if (key == 255) { // If the last symbol of the character has been sent, get the next character if (!charBit) { // Increment the message character index msgIndex++; // Reset to the start of the message when the end is reached if (!msg[msgIndex]) msgIndex = 0; // Get the encoded bit pattern for the morse character character = charCode(msg[msgIndex]); // Start at the 7'th (leftmost) bit of the bit pattern charBit = 7; // Look for 0 signifying start of coding bits while (character & (1<