C:\Arduino (the directory we launch sketches from.)
/*Arduino controlled Fox Hunting Xmtr and / or Beacon
Code cobbled together from various sources
http://ttg.org.au/arduino_fox.php
http://www.wt4y.com/arduino-fox-controller
http://www.wcar.ca/photo-gallery/fox-tx/
Pin A0 is the input for DMTF, see pic for pin out
Pin 5 is the square wave output for the Morse Code, see pic for pin out
Pin 7 is Push to Talk pin (low = PTT, Signal to relay
Useing your DMTF
1 = Start CW
2 = Start Voice
3 =
5 = hi in morse code
6 = Call sing you entered
7 = 73
*/
#include <DTMF.h>
#include "pitches.h"
/*#define debug 1
#if debug == 1
#define debug(x) debug(x)
#define debugln(x) debugln(x)
#else
#define debug(x)
#define debugln(x)
#endif */
int sensorPin = A0; //The following block used by DTMF
float n = 128.0;
float sampling_rate = 8926.0;
DTMF dtmf = DTMF(n, sampling_rate);
float d_mags[8];
char thischar;
int xmit = 0; // if xmit = 0, don't transmit CW
int xmit_voice = 0; // if xmit_voice = 0, don't transmit Voice
int pause = 400; // pause between transmissions, 22 = 1 second (approx)
int whichOne = 1; // choose which melody to play
int numNotes = 13; // Set Default
int holdIt = 0;
// Added here
int mario_melody[] = {
NOTE_E7, NOTE_E7, 0, NOTE_E7,
0, NOTE_C7, NOTE_E7, 0,
NOTE_G7, 0, 0, 0,
NOTE_G6, 0, 0, 0,
NOTE_C7, 0, 0, NOTE_G6,
0, 0, NOTE_E6, 0,
0, NOTE_A6, 0, NOTE_B6,
0, NOTE_AS6, NOTE_A6, 0,
NOTE_G6, NOTE_E7, NOTE_G7,
NOTE_A7, 0, NOTE_F7, NOTE_G7,
0, NOTE_E7, 0,NOTE_C7,
NOTE_D7, NOTE_B6, 0, 0,
NOTE_C7, 0, 0, NOTE_G6,
0, 0, NOTE_E6, 0,
0, NOTE_A6, 0, NOTE_B6,
0, NOTE_AS6, NOTE_A6, 0,
NOTE_G6, NOTE_E7, NOTE_G7,
NOTE_A7, 0, NOTE_F7, NOTE_G7,
0, NOTE_E7, 0,NOTE_C7,
NOTE_D7, NOTE_B6, 0, 0
};
int mario_note_durations[] = {
12, 12, 12, 12,
12, 12, 12, 12,
12, 12, 12, 12,
12, 12, 12, 12,
12, 12, 12, 12,
12, 12, 12, 12,
12, 12, 12, 12,
12, 12, 12, 12,
9, 9, 9,
12, 12, 12, 12,
12, 12, 12, 12,
12, 12, 12, 12,
12, 12, 12, 12,
12, 12, 12, 12,
12, 12, 12, 12,
12, 12, 12, 12,
9, 9, 9,
12, 12, 12, 12,
12, 12, 12, 12,
12, 12, 12, 12,
};
// To here
int starWarsMelody[] = {
// Dart Vader theme (Imperial March) - Star wars
// Score available at https://musescore.com/user/202909/scores/1141521
// The tenor saxophone part was used
NOTE_AS4,8, NOTE_AS4,8, NOTE_AS4,8,//1
NOTE_F5,2, NOTE_C6,2,
NOTE_AS5,8, NOTE_A5,8, NOTE_G5,8, NOTE_F6,2, NOTE_C6,4,
NOTE_AS5,8, NOTE_A5,8, NOTE_G5,8, NOTE_F6,2, NOTE_C6,4,
NOTE_AS5,8, NOTE_A5,8, NOTE_AS5,8, NOTE_G5,2, NOTE_C5,8, NOTE_C5,8, NOTE_C5,8,
NOTE_F5,2, NOTE_C6,2,
NOTE_AS5,8, NOTE_A5,8, NOTE_G5,8, NOTE_F6,2, NOTE_C6,4,
NOTE_AS5,8, NOTE_A5,8, NOTE_G5,8, NOTE_F6,2, NOTE_C6,4, //8
NOTE_AS5,8, NOTE_A5,8, NOTE_AS5,8, NOTE_G5,2, NOTE_C5,-8, NOTE_C5,16,
NOTE_D5,-4, NOTE_D5,8, NOTE_AS5,8, NOTE_A5,8, NOTE_G5,8, NOTE_F5,8,
NOTE_F5,8, NOTE_G5,8, NOTE_A5,8, NOTE_G5,4, NOTE_D5,8, NOTE_E5,4,NOTE_C5,-8, NOTE_C5,16,
NOTE_D5,-4, NOTE_D5,8, NOTE_AS5,8, NOTE_A5,8, NOTE_G5,8, NOTE_F5,8,
NOTE_C6,-8, NOTE_G5,16, NOTE_G5,2, 0,8, NOTE_C5,8,//13
NOTE_D5,-4, NOTE_D5,8, NOTE_AS5,8, NOTE_A5,8, NOTE_G5,8, NOTE_F5,8,
NOTE_F5,8, NOTE_G5,8, NOTE_A5,8, NOTE_G5,4, NOTE_D5,8, NOTE_E5,4,NOTE_C6,-8, NOTE_C6,16,
NOTE_F6,4, NOTE_DS6,8, NOTE_CS6,4, NOTE_C6,8, NOTE_AS5,4, NOTE_GS5,8, NOTE_G5,4, NOTE_F5,8,
NOTE_C6,1
};
int impMarchMelody[] = {
// Dart Vader theme (Imperial March) - Star wars
// Score available at https://musescore.com/user/202909/scores/1141521
// The tenor saxophone part was used
NOTE_A4,-4, NOTE_A4,-4, NOTE_A4,16, NOTE_A4,16, NOTE_A4,16, NOTE_A4,16, NOTE_F4,8, 0,8,
NOTE_A4,-4, NOTE_A4,-4, NOTE_A4,16, NOTE_A4,16, NOTE_A4,16, NOTE_A4,16, NOTE_F4,8, 0,8,
NOTE_A4,4, NOTE_A4,4, NOTE_A4,4, NOTE_F4,-8, NOTE_C5,16,
NOTE_A4,4, NOTE_F4,-8, NOTE_C5,16, NOTE_A4,2,//4
NOTE_E5,4, NOTE_E5,4, NOTE_E5,4, NOTE_F5,-8, NOTE_C5,16,
NOTE_A4,4, NOTE_F4,-8, NOTE_C5,16, NOTE_A4,2,
NOTE_A5,4, NOTE_A4,-8, NOTE_A4,16, NOTE_A5,4, NOTE_GS5,-8, NOTE_G5,16, //7
NOTE_DS5,16, NOTE_D5,16, NOTE_DS5,8, 0,8, NOTE_A4,8, NOTE_DS5,4, NOTE_D5,-8, NOTE_CS5,16,
NOTE_C5,16, NOTE_B4,16, NOTE_C5,16, 0,8, NOTE_F4,8, NOTE_GS4,4, NOTE_F4,-8, NOTE_A4,-16,//9
NOTE_C5,4, NOTE_A4,-8, NOTE_C5,16, NOTE_E5,2,
NOTE_A5,4, NOTE_A4,-8, NOTE_A4,16, NOTE_A5,4, NOTE_GS5,-8, NOTE_G5,16, //7
NOTE_DS5,16, NOTE_D5,16, NOTE_DS5,8, 0,8, NOTE_A4,8, NOTE_DS5,4, NOTE_D5,-8, NOTE_CS5,16,
NOTE_C5,16, NOTE_B4,16, NOTE_C5,16, 0,8, NOTE_F4,8, NOTE_GS4,4, NOTE_F4,-8, NOTE_A4,-16,//9
NOTE_A4,4, NOTE_F4,-8, NOTE_C5,16, NOTE_A4,2,
};
int pinkMelody[] = {
0,2, 0,4, 0,8, NOTE_DS4,8,
NOTE_E4,-4, 0,8, NOTE_FS4,8, NOTE_G4,-4, 0,8, NOTE_DS4,8,
NOTE_E4,-8, NOTE_FS4,8, NOTE_G4,-8, NOTE_C5,8, NOTE_B4,-8, NOTE_E4,8, NOTE_G4,-8, NOTE_B4,8,
NOTE_AS4,2, NOTE_A4,-16, NOTE_G4,-16, NOTE_E4,-16, NOTE_D4,-16,
NOTE_E4,2, 0,4, 0,8, NOTE_DS4,4,
NOTE_E4,-4, 0,8, NOTE_FS4,8, NOTE_G4,-4, 0,8, NOTE_DS4,8,
NOTE_E4,-8, NOTE_FS4,8, NOTE_G4,-8, NOTE_C5,8, NOTE_B4,-8, NOTE_G4,8, NOTE_B4,-8, NOTE_E5,8,
NOTE_DS5,1,
NOTE_D5,2, 0,4, 0,8, NOTE_DS4,8,
NOTE_E4,-4, 0,8, NOTE_FS4,8, NOTE_G4,-4, 0,8, NOTE_DS4,8,
NOTE_E4,-8, NOTE_FS4,8, NOTE_G4,-8, NOTE_C5,8, NOTE_B4,-8, NOTE_E4,8, NOTE_G4,-8, NOTE_B4,8,
NOTE_AS4,2, NOTE_A4,-16, NOTE_G4,-16, NOTE_E4,-16, NOTE_D4,-16,
NOTE_E4,-4, 0,4,
0,4, NOTE_E5,-8, NOTE_D5,8, NOTE_B4,-8, NOTE_A4,8, NOTE_G4,-8, NOTE_E4,-8,
NOTE_AS4,16, NOTE_A4,-8, NOTE_AS4,16, NOTE_A4,-8, NOTE_AS4,16, NOTE_A4,-8, NOTE_AS4,16, NOTE_A4,-8,
NOTE_G4,-16, NOTE_E4,-16, NOTE_D4,-16, NOTE_E4,16, NOTE_E4,16, NOTE_E4,2,
};
// notes in the melody:
int melody1[] = {
198, 198, 220, 264, 297, 330, 330, 352, 352, 352, 264, 297, 330 // My attempt at Hail to Purdue
};
int melody2[] = {
NOTE_G4, NOTE_E4, NOTE_C4, NOTE_C4, NOTE_C4, NOTE_D4, NOTE_E4, NOTE_F4, NOTE_G4, NOTE_G4, NOTE_G4, NOTE_E4
};
// note durations: 4 = quarter note, 8 = eighth note, etc.:
int noteDurations1[] = {
4, 4, 4, 8, 8, 8, 8, 8, 4, 4, 4, 4, 4
};
int noteDurations2[] = {
4, 4, 4, 8, 8, 4, 8, 8, 4, 4, 4, 4, 4
};
int val = 0; // variable to store the read value
#define PTT 7
#define BUZZER_PIN 5 // send music and cw out this pin
#define VOICE_PIN 2 // send signal for soundboard
#define REC_LT 13 // Indication of a signal received
#define BUZZER_FREQUENCY 700 // cw pitch
char beaconstring[] = "CQ KXXXX/FOX CQ KXXXX/FOX"; // change to your call sign
char idstring[] = "DE KXXXX"; // change to your call sign
int lenVoiceFile = 17000; // Length of the voice file being used 1000 = 1 second however this is used twice so multiply by 2 as there seems to be a problem over 33 seconds
int randNumber;
char chartemp[4] ;
char incomingByte = 0;
//int morseOutput = 4; //Pin for receiving Morse output - attach LED to this pin
int interval = 60; //length of time for one dot - basic unit of measurement; one interval occurs between each dot or dash; dash is equivalent to 3 dots; 7 dots between words
String alphabet = "abcdefghijklmnopqrstuvwxyz1234567890/ ";
String ALPHABET = alphabet;
String morseCode[] = {
".-", // A
"-...", // B
"-.-.", // C
"-..", // D
".", // E
"..-.", // F
"--.", // G
"....", // H
"..", // I
".---", // J
"-.-", // K
".-..", // L
"--", // M
"-.", // N
"---", // O
".--.", // P
"--.-", // Q
".-.", // R
"...", // S
"-", // T
"..-", // U
"...-", // V
".--", // W
"-..-", // X
"-.--", // Y
"--..", // Z
".----", // 1
"..---", // 2
"...--", // 3
"....-", // 4
".....", // 5
"-....", // 6
"--...", // 7
"---..", // 8
"----.", // 9
"-----", // 0
"-..-.", // forward slash
" " //space character
};
//added
int tempo = 120;
int notesSW = sizeof(starWarsMelody) / sizeof(starWarsMelody[0]) / 2;
int notesP = sizeof(pinkMelody) / sizeof(pinkMelody[0]) / 2;
int notesIM = sizeof(pinkMelody) / sizeof(pinkMelody[0]) / 2;
int wholenote = (60000 * 4) / tempo;
int divider = 0, noteDuration = 0;//added
void setup() {
pinMode(PTT, OUTPUT);
digitalWrite(PTT, LOW);
pinMode(VOICE_PIN, OUTPUT);
digitalWrite(VOICE_PIN, LOW);
digitalWrite(REC_LT, LOW);
Serial.begin(9600);
// pinMode(morseOutput, OUTPUT);
ALPHABET.toUpperCase();
randomSeed(analogRead(0)); // in case random delays between
// transmissions are used
}
void loop() {
for (int x = 0; x < pause; x ++) // while waiting between transmissions, look for DTMF
{
dtmf.sample(sensorPin);
dtmf.detect(d_mags, 506);
thischar = dtmf.button(d_mags, 1800.);
if (thischar) { // decide what to do if DTMF tone is received
digitalWrite(REC_LT, HIGH);
switch (thischar) {
case 49: // the number 1
xmit = 1; // set the flag to enable CW transmissions
xmit_voice = 0; // turn off the voice if it was on
Serial.print("1 selected, sending ");
Serial.println(beaconstring);
break;
case 50: // the number 2
xmit_voice = 1; // set the flag to enable voice transmissions
xmit = 0; // turn off the CW if it was on
Serial.println("2 selected, sending voice");
break;
case 51: // the number 3
Serial.println("3 selected, sending Star Wars");
numNotes = 13;
delay(1000);
digitalWrite(REC_LT, LOW);
break;
case 52: // the number 4
Serial.println("4 selected, sending Star Wars Imperial March");
numNotes = 12;
delay(1000);
digitalWrite(REC_LT, LOW);
break;
case 53: //number 5 // Sends morse code for "hi"
Serial.println("5 selected, sending HI");
digitalWrite(PTT, HIGH);
delay(2000);
digitalWrite(REC_LT, LOW);
sendLetter('h');
sendLetter('i');
digitalWrite(PTT, LOW);
delay(2000);
break;
case 54: //number 6 // Sends morse code with callsing from line 41
Serial.print("6 selected, sending ");
Serial.println(idstring);
digitalWrite(PTT, HIGH);
delay(2000);
digitalWrite(REC_LT, LOW);
for (int i = 0; i < sizeof(idstring); i++){
sendLetter(idstring[i]);
}
digitalWrite(PTT, LOW);
delay(2000);
break;
case 55: //number 7 // Sends morse code saying "73"
Serial.println("7 selected, sending 73");
digitalWrite(PTT, HIGH);
delay(2000);
digitalWrite(REC_LT, LOW);
sendLetter('7');
sendLetter('3');
digitalWrite(PTT, LOW);
delay(2000);
break;
case 56: // the number 8
Serial.println("8 selected, sending Super Mario");
numNotes = 14;
delay(1000);
digitalWrite(REC_LT, LOW);
break;
case 57: // the number 9
Serial.println("9 selected, sending Pink Panther");
numNotes = 15;
delay(1000);
digitalWrite(REC_LT, LOW);
break;
default: // any other number, turn off transmissions
Serial.print("Any other #: ");
Serial.println(thischar);
delay(1000);
digitalWrite(REC_LT, LOW);
xmit = 0; // set the flag to disable transmissions
xmit_voice = 0;
break;
}
}
delay(1);
}
digitalWrite(REC_LT, LOW);
if (xmit_voice == 1)
{
digitalWrite(PTT, HIGH);
Serial.print("Begin Voice: ");
delay(1000); // delay 1 seconds after PTT to account for race condition
// This is for the Adafruit Soundboard
digitalWrite(VOICE_PIN, HIGH); // Key the soundboard
delay(100);
val = digitalRead(VOICE_PIN); // read the input pin
Serial.println(val);
digitalWrite(VOICE_PIN, LOW); // Switch for soundboard is momentary
Serial.print("Delay for ");
Serial.print(lenVoiceFile * 2/1000);
Serial.println(" seconds for sound file to end.");
delay(lenVoiceFile); // Adjust this to the length of the sound file being sent.
delay(lenVoiceFile); // Adjust this to the length of the sound file being sent.
Serial.println("End voice");
digitalWrite(PTT, LOW); // drop the PTT and wait a while
// End of Adafruit Soundboard
}
if (xmit == 1)
{
digitalWrite(PTT, HIGH);
Serial.println("Begin CW");
delay(2000); // delay 2 seconds after PTT to account for race condition
val = digitalRead(VOICE_PIN); // read the input pin
// play a little melody
for (int thisNote = 0; thisNote < numNotes; thisNote++) {
// to calculate the note duration, take one second
// divided by the note type.
//e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc.
int noteDuration = 1000 / noteDurations1[thisNote];
holdIt = numNotes;
if (numNotes == 13)
{
numNotes = 1; // So it will only play once.
playStarWars();
}
else if (numNotes == 14)
{
numNotes = 1; // So it will only play once.
for (int i = 0; i < sizeof(mario_melody) / sizeof(int); i++) {
int noteDuration = 1000 / mario_note_durations[i];
tone(BUZZER_PIN, mario_melody[i], noteDuration);
int pauseBetweenNotes = noteDuration * 1.30;
delay(pauseBetweenNotes);
noTone(BUZZER_PIN);
}
}
else if (numNotes == 15)
{
numNotes = 1; // So it will only play once.
playPinkPanther();
}
else if (numNotes == 12)
{
numNotes = 1; // So it will only play once.
playImpMarch();
}
else
{
int noteDuration = 1000 / noteDurations2[thisNote];
tone(BUZZER_PIN, melody2[thisNote], noteDuration);
}
// to distinguish the notes, set a minimum time between them.
// the note's duration + 30% seems to work well:
int pauseBetweenNotes = noteDuration * 1.30;
delay(pauseBetweenNotes);
// stop the tone playing:
noTone(BUZZER_PIN);
}
numNotes = holdIt;
delay(1000); //one second between melody and beaconstring
for (int i = 0; i < sizeof(beaconstring); i++){
sendLetter(beaconstring[i]);
}
delay(1000);
Serial.println("End CW");
digitalWrite(PTT, LOW); // drop the PTT and wait a while
// randNumber = random(10000, 20000); // remove comments and add comments to delay(5000)
// Serial.print(randNumber); // to use random delays
// Serial.println();
// delay(randNumber);
// delay(5000);
}
}
// End of Loop()
// Functions follow
void sendLetter (char c) {
int i;
for (i = 0; i < alphabet.length(); i = i + 1) {
if (alphabet[i] == c || ALPHABET[i] == c) {
//Serial.print(c);
sendMorseCode(morseCode[i]);
return;
}
}
if (c == '\n')
Serial.println();
}
void sendMorseCode (String tokens) {
int i;
for (i = 0; i < tokens.length(); i = i + 1) {
switch (tokens[i]) {
case '-':
sendDash();
break;
case '.':
sendDot();
break;
case ' ':
sendEndOfWord();
break;
}
}
morseOutputOff(2);
Serial.print(" ");
}
void sendEndOfWord() {
morseOutputOff(4);
}
//basic functions - Morse code concepts
void sendDot() {
tone(BUZZER_PIN, BUZZER_FREQUENCY);
morseOutputOn(1);
noTone(BUZZER_PIN);
morseOutputOff(1);
Serial.print(".");
}
void sendDash() {
tone(BUZZER_PIN, BUZZER_FREQUENCY);
morseOutputOn(3);
noTone(BUZZER_PIN);
morseOutputOff(1);
Serial.print("-");
}
//Low level functions - how the actions are accomplished
// n = number of intervals
// interval is a fixed length of time determined at start, for example 200 milliseconds
void morseOutputOn (int n) {
// example: morseOutputOn(1) means turn output on and keep it on for 1 interval
// morseOutputOn(3) means turn output on and keep it on for 3 intervals
//
// digitalWrite(morseOutput, HIGH);
delay(n * interval);
}
void morseOutputOff (int n) {
// digitalWrite(morseOutput, LOW);
delay(n * interval);
}
void playStarWars () {
for (int thisNote = 0; thisNote < notesSW * 2; thisNote = thisNote + 2) {
// calculates the duration of each note
divider = starWarsMelody[thisNote + 1];
if (divider > 0) {
// regular note, just proceed
noteDuration = (wholenote) / divider;
} else if (divider < 0) {
// dotted notes are represented with negative durations!!
noteDuration = (wholenote) / abs(divider);
noteDuration *= 1.5; // increases the duration in half for dotted notes
}
// we only play the note for 90% of the duration, leaving 10% as a pause
tone(BUZZER_PIN, starWarsMelody[thisNote], noteDuration*0.9);
// Wait for the specief duration before playing the next note.
delay(noteDuration);
// stop the waveform generation before the next note.
noTone(BUZZER_PIN);
}
}
void playPinkPanther () {
for (int thisNote = 0; thisNote < notesP * 2; thisNote = thisNote + 2) {
// calculates the duration of each note
divider = pinkMelody[thisNote + 1];
if (divider > 0) {
// regular note, just proceed
noteDuration = (wholenote) / divider;
} else if (divider < 0) {
// dotted notes are represented with negative durations!!
noteDuration = (wholenote) / abs(divider);
noteDuration *= 1.5; // increases the duration in half for dotted notes
}
// we only play the note for 90% of the duration, leaving 10% as a pause
tone(BUZZER_PIN, pinkMelody[thisNote], noteDuration*0.9);
// Wait for the specief duration before playing the next note.
delay(noteDuration);
// stop the waveform generation before the next note.
noTone(BUZZER_PIN);
}
}
void playImpMarch () {
for (int thisNote = 0; thisNote < notesIM * 2; thisNote = thisNote + 2) {
// calculates the duration of each note
divider = impMarchMelody[thisNote + 1];
if (divider > 0) {
// regular note, just proceed
noteDuration = (wholenote) / divider;
} else if (divider < 0) {
// dotted notes are represented with negative durations!!
noteDuration = (wholenote) / abs(divider);
noteDuration *= 1.5; // increases the duration in half for dotted notes
}
// we only play the note for 90% of the duration, leaving 10% as a pause
tone(BUZZER_PIN, impMarchMelody[thisNote], noteDuration*0.9);
// Wait for the specief duration before playing the next note.
delay(noteDuration);
// stop the waveform generation before the next note.
noTone(BUZZER_PIN);
}
}