update dtmf, morse, and examples
This commit is contained in:
parent
71acbbb975
commit
3d3f6a36b6
|
@ -52,7 +52,7 @@ void setup() {
|
||||||
Serial.begin(9600);
|
Serial.begin(9600);
|
||||||
|
|
||||||
radio.initialize();
|
radio.initialize();
|
||||||
radio.frequency(145570);
|
radio.frequency(144390); // default aprs frequency in North America
|
||||||
radio.setRfPower(0);
|
radio.setRfPower(0);
|
||||||
radio.setVolume1(0xFF);
|
radio.setVolume1(0xFF);
|
||||||
radio.setVolume2(0xFF);
|
radio.setVolume2(0xFF);
|
||||||
|
|
|
@ -36,7 +36,7 @@ void setup() {
|
||||||
Serial.println("Setting radio to its defaults..");
|
Serial.println("Setting radio to its defaults..");
|
||||||
radio.initialize();
|
radio.initialize();
|
||||||
radio.setRfPower(0);
|
radio.setRfPower(0);
|
||||||
radio.frequency(146520);
|
radio.frequency(432100); // 70cm calling frequency
|
||||||
radio.setModeReceive();
|
radio.setModeReceive();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -75,13 +75,11 @@ void setup() {
|
||||||
radio.initialize(); // initializes automatically for UHF 12.5kHz channel
|
radio.initialize(); // initializes automatically for UHF 12.5kHz channel
|
||||||
|
|
||||||
Serial.println("setting default Radio configuration");
|
Serial.println("setting default Radio configuration");
|
||||||
radio.dangerMode();
|
|
||||||
|
|
||||||
// set frequency
|
// set frequency
|
||||||
Serial.println("changing frequency");
|
Serial.println("changing frequency");
|
||||||
|
|
||||||
radio.setSQOff();
|
freq = 432100; // 70cm calling frequency
|
||||||
freq = 446000;
|
|
||||||
radio.frequency(freq);
|
radio.frequency(freq);
|
||||||
|
|
||||||
// set to receive
|
// set to receive
|
||||||
|
@ -92,6 +90,11 @@ void setup() {
|
||||||
Serial.println(radio.readCtlReg());
|
Serial.println(radio.readCtlReg());
|
||||||
Serial.println(radio.readRSSI());
|
Serial.println(radio.readRSSI());
|
||||||
|
|
||||||
|
// set up squelch
|
||||||
|
radio.setSQLoThresh(-80);
|
||||||
|
radio.setSQHiThresh(-70);
|
||||||
|
radio.setSQOn();
|
||||||
|
|
||||||
radio.setRfPower(0);
|
radio.setRfPower(0);
|
||||||
|
|
||||||
// CTCSS Setup code
|
// CTCSS Setup code
|
||||||
|
|
|
@ -72,7 +72,7 @@ void setup() {
|
||||||
//radio.setSQOff();
|
//radio.setSQOff();
|
||||||
|
|
||||||
Serial.println("setting frequency to: ");
|
Serial.println("setting frequency to: ");
|
||||||
freq = 432250;
|
freq = 432100; // 70cm calling frequency
|
||||||
radio.frequency(freq);
|
radio.frequency(freq);
|
||||||
Serial.print(radio.getFrequency());
|
Serial.print(radio.getFrequency());
|
||||||
Serial.println("kHz");
|
Serial.println("kHz");
|
||||||
|
@ -104,38 +104,18 @@ void setup() {
|
||||||
Serial.println("ready");
|
Serial.println("ready");
|
||||||
}
|
}
|
||||||
|
|
||||||
char rx_dtmf_buf[255];
|
|
||||||
int rx_dtmf_idx = 0;
|
|
||||||
void loop() {
|
void loop() {
|
||||||
|
|
||||||
// look for tone
|
// look for tone
|
||||||
if (radio.getDTMFSample() != 0) {
|
char m = radio.DTMFRxLoop();
|
||||||
uint16_t code = radio.getDTMFCode();
|
if (m != 0) {
|
||||||
|
Serial.print(m);
|
||||||
rx_dtmf_buf[rx_dtmf_idx++] = code2char(code);
|
|
||||||
|
|
||||||
// reset after this tone
|
|
||||||
int j = 0;
|
|
||||||
while (j < 4) {
|
|
||||||
if (radio.getDTMFSample() == 0) {
|
|
||||||
j++;
|
|
||||||
} else {
|
|
||||||
j = 1;
|
|
||||||
}
|
|
||||||
delay(10);
|
|
||||||
}
|
|
||||||
// reset read
|
|
||||||
//radio.enableDTMFReceive();
|
|
||||||
} else if (rx_dtmf_idx > 0) {
|
|
||||||
rx_dtmf_buf[rx_dtmf_idx] = '\0'; // NULL terminate the string
|
|
||||||
Serial.println(rx_dtmf_buf);
|
|
||||||
rx_dtmf_idx = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Is it time to send tone?
|
// Is it time to send tone?
|
||||||
if (Serial.available()) {
|
if (Serial.available()) {
|
||||||
// get first code
|
// get first code
|
||||||
uint8_t code = char2code(Serial.read());
|
uint8_t code = radio.DTMFchar2code(Serial.read());
|
||||||
|
|
||||||
// start transmitting
|
// start transmitting
|
||||||
radio.setDTMFCode(code); // set first
|
radio.setDTMFCode(code); // set first
|
||||||
|
@ -151,7 +131,7 @@ void loop() {
|
||||||
delay(10);
|
delay(10);
|
||||||
}
|
}
|
||||||
if (Serial.available()) {
|
if (Serial.available()) {
|
||||||
code = char2code(Serial.read());
|
code = radio.DTMFchar2code(Serial.read());
|
||||||
if (code == 255) code = 0xE; // throw a * in there so we don't break things with an invalid code
|
if (code == 255) code = 0xE; // throw a * in there so we don't break things with an invalid code
|
||||||
radio.setDTMFCode(code); // set first
|
radio.setDTMFCode(code); // set first
|
||||||
} else {
|
} else {
|
||||||
|
@ -170,38 +150,3 @@ void loop() {
|
||||||
radio.setTxSourceMic();
|
radio.setTxSourceMic();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t char2code(char c) {
|
|
||||||
uint8_t code;
|
|
||||||
if (c == '#') {
|
|
||||||
code = 0xF;
|
|
||||||
} else if (c=='*') {
|
|
||||||
code = 0xE;
|
|
||||||
} else if (c >= 'A' && c <= 'D') {
|
|
||||||
code = c - 'A' + 0xA;
|
|
||||||
} else if (c >= '0' && c <= '9') {
|
|
||||||
code = c - '0';
|
|
||||||
} else {
|
|
||||||
// invalid code, skip it
|
|
||||||
code = 255;
|
|
||||||
}
|
|
||||||
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
|
|
||||||
char code2char(uint16_t code) {
|
|
||||||
char c;
|
|
||||||
if (code < 10) {
|
|
||||||
c = '0' + code;
|
|
||||||
} else if (code < 0xE) {
|
|
||||||
c = 'A' + code - 10;
|
|
||||||
} else if (code == 0xE) {
|
|
||||||
c = '*';
|
|
||||||
} else if (code == 0xF) {
|
|
||||||
c = '#';
|
|
||||||
} else {
|
|
||||||
c = '?'; // invalid code
|
|
||||||
}
|
|
||||||
|
|
||||||
return c;
|
|
||||||
}
|
|
|
@ -57,8 +57,8 @@ void setup() {
|
||||||
radio.setMorseFreq(600);
|
radio.setMorseFreq(600);
|
||||||
radio.setMorseDotMillis(100);
|
radio.setMorseDotMillis(100);
|
||||||
|
|
||||||
// Configure the HamShield to operate on 438.000MHz
|
// Configure the HamShield
|
||||||
radio.frequency(438000);
|
radio.frequency(432300); // 70cm beacon frequency
|
||||||
|
|
||||||
Serial.println("Radio Configured.");
|
Serial.println("Radio Configured.");
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,8 +61,8 @@ void setup() {
|
||||||
radio.setMorseFreq(600);
|
radio.setMorseFreq(600);
|
||||||
radio.setMorseDotMillis(100);
|
radio.setMorseDotMillis(100);
|
||||||
|
|
||||||
// Configure the HamShield to operate on 438.000Mhz
|
// Configure the HamShield frequency
|
||||||
radio.frequency(438000);
|
radio.frequency(432400);
|
||||||
|
|
||||||
Serial.println("Radio configured.");
|
Serial.println("Radio configured.");
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,13 +72,12 @@ void setup() {
|
||||||
radio.initialize(); // initializes automatically for UHF 12.5kHz channel
|
radio.initialize(); // initializes automatically for UHF 12.5kHz channel
|
||||||
|
|
||||||
Serial.println("setting default Radio configuration");
|
Serial.println("setting default Radio configuration");
|
||||||
radio.dangerMode();
|
|
||||||
|
|
||||||
// set frequency
|
// set frequency
|
||||||
Serial.println("changing frequency");
|
Serial.println("changing frequency");
|
||||||
|
|
||||||
radio.setSQOff();
|
radio.setSQOff();
|
||||||
freq = 446000;
|
freq = 432100; // 70cm calling frequency
|
||||||
radio.frequency(freq);
|
radio.frequency(freq);
|
||||||
|
|
||||||
// set to receive
|
// set to receive
|
||||||
|
|
|
@ -126,7 +126,7 @@ void setup() {
|
||||||
Serial.println("changing frequency");
|
Serial.println("changing frequency");
|
||||||
|
|
||||||
radio.setSQOff();
|
radio.setSQOff();
|
||||||
freq = 446000;
|
freq = 432100; // 70cm calling frequency
|
||||||
radio.frequency(freq);
|
radio.frequency(freq);
|
||||||
|
|
||||||
// set to receive
|
// set to receive
|
||||||
|
|
|
@ -36,28 +36,9 @@
|
||||||
// Note that all timing is defined in terms of MORSE_DOT relative durations
|
// Note that all timing is defined in terms of MORSE_DOT relative durations
|
||||||
// You may want to tweak those timings below
|
// You may want to tweak those timings below
|
||||||
|
|
||||||
#define SYMBOL_END_TIME 5 //millis
|
|
||||||
#define CHAR_END_TIME (MORSE_DOT*2.7)
|
|
||||||
#define MESSAGE_END_TIME (MORSE_DOT*8)
|
|
||||||
|
|
||||||
#define MIN_DOT_TIME (MORSE_DOT-30)
|
|
||||||
#define MAX_DOT_TIME (MORSE_DOT+55)
|
|
||||||
#define MIN_DASH_TIME (MORSE_DOT*3-30)
|
|
||||||
#define MAX_DASH_TIME (MORSE_DOT*3+55)
|
|
||||||
|
|
||||||
|
|
||||||
HamShield radio;
|
HamShield radio;
|
||||||
|
|
||||||
uint32_t last_tone_check; // track how often we check for morse tones
|
|
||||||
uint32_t tone_in_progress; // track how long the current tone lasts
|
|
||||||
uint32_t space_in_progress; // track how long since the last tone
|
|
||||||
uint8_t rx_morse_char;
|
|
||||||
uint8_t rx_morse_bit;
|
|
||||||
bool bits_to_process;
|
|
||||||
|
|
||||||
char rx_msg[128];
|
|
||||||
uint8_t rx_idx;
|
|
||||||
|
|
||||||
// Run our start up things here
|
// Run our start up things here
|
||||||
void setup() {
|
void setup() {
|
||||||
// NOTE: if not using PWM out, it should be held low to avoid tx noise
|
// NOTE: if not using PWM out, it should be held low to avoid tx noise
|
||||||
|
@ -93,68 +74,19 @@ void setup() {
|
||||||
radio.setMorseDotMillis(MORSE_DOT);
|
radio.setMorseDotMillis(MORSE_DOT);
|
||||||
|
|
||||||
radio.lookForTone(MORSE_FREQ);
|
radio.lookForTone(MORSE_FREQ);
|
||||||
|
radio.setupMorseRx();
|
||||||
|
|
||||||
// Configure the HamShield to operate on 438.000MHz
|
// Configure the HamShield frequency
|
||||||
radio.frequency(432000);
|
radio.frequency(432100); // 70cm calling frequency
|
||||||
radio.setModeReceive();
|
radio.setModeReceive();
|
||||||
|
|
||||||
Serial.println("Radio Configured.");
|
Serial.println("Radio Configured.");
|
||||||
last_tone_check = millis();
|
|
||||||
space_in_progress = 0; // haven't checked yet
|
|
||||||
tone_in_progress = 0; // not currently listening to a tone
|
|
||||||
rx_morse_char = 0; // haven't found any tones yet
|
|
||||||
rx_idx = 0;
|
|
||||||
rx_morse_bit = 1;
|
|
||||||
bits_to_process = false;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
// are we receiving anything
|
char rx_char = radio.morseRxLoop();
|
||||||
if (radio.toneDetected()) {
|
if (rx_char != 0) {
|
||||||
space_in_progress = 0;
|
Serial.print(rx_char);
|
||||||
if (tone_in_progress == 0) {
|
|
||||||
// start a new tone
|
|
||||||
tone_in_progress = millis();
|
|
||||||
//Serial.print('t');
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// keep track of how long the silence is
|
|
||||||
if (space_in_progress == 0) space_in_progress = millis();
|
|
||||||
|
|
||||||
// we wait for a bit of silence before ending the last
|
|
||||||
// symbol in order to smooth out the detector
|
|
||||||
if ((millis() - space_in_progress) > SYMBOL_END_TIME)
|
|
||||||
{
|
|
||||||
if (tone_in_progress != 0) {
|
|
||||||
// end the last tone
|
|
||||||
uint16_t tone_time = millis() - tone_in_progress;
|
|
||||||
tone_in_progress = 0;
|
|
||||||
//Serial.println(tone_time);
|
|
||||||
handleTone(tone_time);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// we might be done with a character if the space is long enough
|
|
||||||
if (((millis() - space_in_progress) > CHAR_END_TIME) && bits_to_process) {
|
|
||||||
char m = parseMorse();
|
|
||||||
bits_to_process = false;
|
|
||||||
if (m != 0) {
|
|
||||||
rx_msg[rx_idx++] = m;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// we might be done with a message if the space is long enough
|
|
||||||
if ((millis() - space_in_progress) > MESSAGE_END_TIME) {
|
|
||||||
if (rx_idx > 0) {
|
|
||||||
// we got a message, print it now
|
|
||||||
rx_msg[rx_idx] = '\0'; // null terminate
|
|
||||||
Serial.println(rx_msg);
|
|
||||||
rx_idx = 0; // reset message buffer
|
|
||||||
}
|
|
||||||
rx_morse_char = 0;
|
|
||||||
rx_morse_bit = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// should we send anything
|
// should we send anything
|
||||||
|
@ -181,9 +113,9 @@ void loop() {
|
||||||
radio.morseOut(morse_buf);
|
radio.morseOut(morse_buf);
|
||||||
|
|
||||||
// We're done sending the message, set the radio back into recieve mode.
|
// We're done sending the message, set the radio back into recieve mode.
|
||||||
|
Serial.println("sent");
|
||||||
radio.setModeReceive();
|
radio.setModeReceive();
|
||||||
radio.lookForTone(MORSE_FREQ);
|
radio.lookForTone(MORSE_FREQ);
|
||||||
Serial.println("sent");
|
|
||||||
} else {
|
} else {
|
||||||
// If we get here, the channel is busy. Let's also print out the RSSI.
|
// If we get here, the channel is busy. Let's also print out the RSSI.
|
||||||
Serial.print("The channel was busy. RSSI: ");
|
Serial.print("The channel was busy. RSSI: ");
|
||||||
|
@ -192,34 +124,4 @@ void loop() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleTone(uint16_t tone_time) {
|
|
||||||
//Serial.println(tone_time);
|
|
||||||
if (tone_time > MIN_DOT_TIME && tone_time < MAX_DOT_TIME) {
|
|
||||||
// add a dot
|
|
||||||
//Serial.print(".");
|
|
||||||
bits_to_process = true;
|
|
||||||
//nothing to do for this bit position, since . = 0
|
|
||||||
} else if (tone_time > MIN_DASH_TIME && tone_time < MAX_DASH_TIME) {
|
|
||||||
// add a dash
|
|
||||||
//Serial.print("-");
|
|
||||||
bits_to_process = true;
|
|
||||||
rx_morse_char += rx_morse_bit;
|
|
||||||
}
|
|
||||||
|
|
||||||
// prep for the next bit
|
|
||||||
rx_morse_bit = rx_morse_bit << 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
char parseMorse() {
|
|
||||||
// if morse_char is a valid morse character, return the character
|
|
||||||
// if morse_char is an invalid (incomplete) morse character, return 0
|
|
||||||
|
|
||||||
|
|
||||||
//if (rx_morse_bit != 1) Serial.println(rx_morse_char, BIN);
|
|
||||||
rx_morse_char += rx_morse_bit; // add the terminator bit
|
|
||||||
// if we got a char, then print it
|
|
||||||
char c = radio.morseReverseLookup(rx_morse_char);
|
|
||||||
rx_morse_char = 0;
|
|
||||||
rx_morse_bit = 1;
|
|
||||||
return c;
|
|
||||||
}
|
|
|
@ -54,7 +54,7 @@ void setup() {
|
||||||
// Tell the HamShield to start up
|
// Tell the HamShield to start up
|
||||||
radio.initialize();
|
radio.initialize();
|
||||||
radio.setRfPower(0);
|
radio.setRfPower(0);
|
||||||
radio.frequency(145500);
|
radio.frequency(446000);
|
||||||
// put your setup code here, to run once:
|
// put your setup code here, to run once:
|
||||||
//dds.setReferenceClock(34965/4);
|
//dds.setReferenceClock(34965/4);
|
||||||
dds.start();
|
dds.start();
|
||||||
|
|
|
@ -15,22 +15,32 @@
|
||||||
* R1;
|
* R1;
|
||||||
* [Just a space]
|
* [Just a space]
|
||||||
|
|
||||||
|
|
||||||
|
// see also: https://github.com/EnhancedRadioDevices/HamShield/wiki/HamShield-Serial-Mode
|
||||||
|
|
||||||
Commands:
|
Commands:
|
||||||
|
|
||||||
Mode ASCII Description Implemented
|
Mode ASCII Description
|
||||||
-------------- ----------- -------------------------------------------------------------------------------------------------------------------------------------------- -----------------
|
-------------- ----------- --------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
Transmit space Space must be received at least every 500 mS Yes
|
Transmit space Space must be received at least every 500 mS
|
||||||
Receive not space If space is not received and/or 500 mS timeout of space occurs, unit will go into receive mode Yes
|
Receive not space If space is not received and/or 500 mS timeout of space occurs, unit will go into receive mode
|
||||||
Bandwidth E<mode>; for 12.5KHz mode is 0, for 25KHz, mode is 1 No
|
Frequency F<freq>; Set the receive frequency in KHz, if offset is disabled, this is the transmit frequency
|
||||||
Frequency F<freq>; Set the receive frequency in KHz, if offset is disabled, this is the transmit frequency No
|
|
||||||
Morse Out M<text>; A small buffer for morse code (32 chars)
|
Morse Out M<text>; A small buffer for morse code (32 chars)
|
||||||
Power level P<level>; Set the power amp level, 0 = lowest, 15 = highest No
|
Morse In N; Sets mode to Morse In, listening for Morse
|
||||||
Enable Offset R<state>; 1 turns on repeater offset mode, 0 turns off repeater offset mode No
|
Power level P<level>; Set the power amp level, 0 = lowest, 15 = highest
|
||||||
Squelch S<level>; Set the squelch level No
|
Enable Offset R<state>; 1 turns on repeater offset mode, 0 turns off repeater offset mode
|
||||||
TX Offset T<freq>; The absolute frequency of the repeater offset to transmit on in KHz No
|
Squelch S<level>; Set the squelch level
|
||||||
RSSI ?; Respond with the current receive level in - dBm (no sign provided on numerical response) No
|
TX Offset T<freq>; The absolute frequency of the repeater offset to transmit on in KHz
|
||||||
Voice Level ^; Respond with the current voice level (VSSI)
|
RSSI ? Respond with the current receive level in - dBm (no sign provided on numerical response)
|
||||||
|
Voice Level ^ Respond with the current voice level (VSSI), only valid when transmitting
|
||||||
|
DTMF Out D<vals>; A small buffer for DTMF out (only 0-9,A,B,C,D,*,# accepted)
|
||||||
|
DTMF In B; Sets mode to DTMF In, listening for DTMF
|
||||||
|
PL Tone Tx A<val>; Sets PL tone for TX, value is tone frequency in Hz (float), set to 0 to disable
|
||||||
|
PL Tone Rx C<val>; Sets PL tone for RX, value is tone frequency in Hz (float), set to 0 to disable
|
||||||
|
Volume 1 V1<val>; Set volume 1 (value between 0 and 15)
|
||||||
|
Volume 2 V2<val>; Set volume 2 (value between 0 and 15)
|
||||||
|
KISS TNC K; Move to KISS TNC mode (send ^; to move back to normal mode). NOT IMPELEMENTED YET
|
||||||
|
Normal Mode _ Move to Normal mode from any other mode (except TX)
|
||||||
|
|
||||||
Responses:
|
Responses:
|
||||||
|
|
||||||
|
@ -42,23 +52,44 @@ Error X<code>; Indicates an error code. The numerical value is the type
|
||||||
Value :<value>; In response to a query
|
Value :<value>; In response to a query
|
||||||
Status #<value>; Unsolicited status message
|
Status #<value>; Unsolicited status message
|
||||||
Debug Msg @<text>; 32 character debug message
|
Debug Msg @<text>; 32 character debug message
|
||||||
|
Rx Msg R<text>; up to 32 characters of received message, only if device is in DTMF or Morse Rx modes
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
// Note that the following are not yet implemented
|
||||||
|
// TODO: change get_value so it's intuitive
|
||||||
|
// TODO: Squelch open and squelch shut independently controllable
|
||||||
|
// TODO: pre/de emph filter
|
||||||
|
// TODO: walkie-talkie
|
||||||
|
// TODO: KISS TNC
|
||||||
|
|
||||||
#include "HamShield.h"
|
#include "HamShield.h"
|
||||||
|
|
||||||
#define MIC_PIN 3
|
#define MIC_PIN 3
|
||||||
#define RESET_PIN A3
|
#define RESET_PIN A3
|
||||||
#define SWITCH_PIN 2
|
#define SWITCH_PIN 2
|
||||||
|
|
||||||
int state;
|
enum {TX, NORMAL, DTMF, MORSE, KISS};
|
||||||
|
|
||||||
|
int state = NORMAL;
|
||||||
|
bool rx_ctcss = false;
|
||||||
|
bool muted = false;
|
||||||
|
|
||||||
int txcount = 0;
|
int txcount = 0;
|
||||||
long timer = 0;
|
long timer = 0; // Transmit timer to track timeout (send space to reset)
|
||||||
long freq = 144390;
|
|
||||||
long tx = 0;
|
long freq = 432100; // 70cm calling frequency, receive frequency and default transmit frequency
|
||||||
|
long tx_freq = 0; // transmit frequency if repeater is on
|
||||||
|
int pwr = 0; // tx power
|
||||||
|
|
||||||
char cmdbuff[32] = "";
|
char cmdbuff[32] = "";
|
||||||
int temp = 0;
|
int temp = 0;
|
||||||
int repeater = 0;
|
|
||||||
|
bool repeater = false; // true if transmit and receive operate on different frequencies
|
||||||
|
char pl_rx_buffer[32]; // pl tone rx buffer
|
||||||
|
char pl_tx_buffer[32]; // pl tone tx buffer
|
||||||
|
|
||||||
float ctcssin = 0;
|
float ctcssin = 0;
|
||||||
float ctcssout = 0;
|
float ctcssout = 0;
|
||||||
int cdcssin = 0;
|
int cdcssin = 0;
|
||||||
|
@ -67,10 +98,8 @@ int cdcssout = 0;
|
||||||
|
|
||||||
HamShield radio;
|
HamShield radio;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
// NOTE: if not using PWM out, it should be held low to avoid tx noise
|
// NOTE: if not using PWM out (MIC pin), it should be held low to avoid tx noise
|
||||||
pinMode(MIC_PIN, OUTPUT);
|
pinMode(MIC_PIN, OUTPUT);
|
||||||
digitalWrite(MIC_PIN, LOW);
|
digitalWrite(MIC_PIN, LOW);
|
||||||
|
|
||||||
|
@ -80,7 +109,6 @@ void setup() {
|
||||||
// set up the reset control pin
|
// set up the reset control pin
|
||||||
pinMode(RESET_PIN, OUTPUT);
|
pinMode(RESET_PIN, OUTPUT);
|
||||||
digitalWrite(RESET_PIN, HIGH);
|
digitalWrite(RESET_PIN, HIGH);
|
||||||
delay(5); // wait for device to come up
|
|
||||||
|
|
||||||
Serial.begin(9600);
|
Serial.begin(9600);
|
||||||
Serial.println(";;;;;;;;;;;;;;;;;;;;;;;;;;");
|
Serial.println(";;;;;;;;;;;;;;;;;;;;;;;;;;");
|
||||||
|
@ -90,111 +118,282 @@ void setup() {
|
||||||
Serial.print(result,DEC);
|
Serial.print(result,DEC);
|
||||||
Serial.println(";");
|
Serial.println(";");
|
||||||
radio.initialize(); // initializes automatically for UHF 12.5kHz channel
|
radio.initialize(); // initializes automatically for UHF 12.5kHz channel
|
||||||
Serial.println("*START;");
|
|
||||||
radio.frequency(freq);
|
radio.frequency(freq);
|
||||||
radio.setVolume1(0xF);
|
radio.setVolume1(0xF);
|
||||||
radio.setVolume2(0xF);
|
radio.setVolume2(0xF);
|
||||||
radio.setModeReceive();
|
radio.setModeReceive();
|
||||||
radio.setTxSourceMic();
|
radio.setTxSourceMic();
|
||||||
radio.setRfPower(0);
|
radio.setRfPower(pwr);
|
||||||
radio.setSQLoThresh(80);
|
radio.setSQLoThresh(-80);
|
||||||
|
radio.setSQHiThresh(-70);
|
||||||
radio.setSQOn();
|
radio.setSQOn();
|
||||||
|
Serial.println("*START;");
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
|
|
||||||
if(Serial.available()) {
|
if(Serial.available()) {
|
||||||
|
|
||||||
int text = Serial.read();
|
int text = Serial.read(); // get the first char to see what the upcoming command is
|
||||||
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
|
// we handle commands differently based on what state we're in
|
||||||
|
|
||||||
case 10:
|
case TX:
|
||||||
if(text == 32) { timer = millis();}
|
// we're currently transmitting
|
||||||
|
// if we got a space, reset our transmit timeout
|
||||||
|
if(text == ' ') { timer = millis();}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0:
|
case NORMAL:
|
||||||
switch(text) {
|
switch(text) {
|
||||||
|
case ' ': // space - transmit
|
||||||
case 32: // space - transmit
|
if(repeater == true && tx_freq != 0) { radio.frequency(tx_freq); }
|
||||||
if(repeater == 1) { radio.frequency(tx); }
|
muted = false; // can't mute (for PL tones) during tx
|
||||||
|
radio.setUnmute();
|
||||||
radio.setModeTransmit();
|
radio.setModeTransmit();
|
||||||
state = 10;
|
state = TX;
|
||||||
Serial.println("#TX,ON;");
|
Serial.println("#TX,ON;");
|
||||||
timer = millis();
|
timer = millis();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 63: // ? - RSSI
|
case '?': // ? - RSSI
|
||||||
Serial.print(":");
|
Serial.print(":");
|
||||||
Serial.print(radio.readRSSI(),DEC);
|
Serial.print(radio.readRSSI(),DEC);
|
||||||
Serial.println(";");
|
Serial.println(";");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 65: // A - CTCSS In
|
case '^': // ^ - VSSI (voice) level
|
||||||
getValue();
|
Serial.print(":");
|
||||||
ctcssin = atof(cmdbuff);
|
Serial.print(radio.readVSSI(),DEC);
|
||||||
radio.setCtcss(ctcssin);
|
Serial.println(";");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 66: // B - CTCSS Out
|
case 'F': // F - frequency
|
||||||
break;
|
|
||||||
|
|
||||||
case 67: // C - CTCSS Enable
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 68: // D - CDCSS Enable
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 70: // F - frequency
|
|
||||||
getValue();
|
getValue();
|
||||||
freq = atol(cmdbuff);
|
freq = atol(cmdbuff);
|
||||||
if(radio.frequency(freq) == true) { Serial.print("@"); Serial.print(freq,DEC); Serial.println(";!;"); } else { Serial.println("X1;"); }
|
if(radio.frequency(freq) == true) {
|
||||||
|
Serial.print("@");
|
||||||
|
Serial.print(freq,DEC);
|
||||||
|
Serial.println(";!;");
|
||||||
|
} else {
|
||||||
|
Serial.println("X1;");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'M':
|
case 'P': // P - power level
|
||||||
getValue();
|
|
||||||
radio.setModeTransmit();
|
|
||||||
delay(300);
|
|
||||||
radio.morseOut(cmdbuff);
|
|
||||||
state = 10;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 80: // P - power level
|
|
||||||
getValue();
|
getValue();
|
||||||
temp = atol(cmdbuff);
|
temp = atol(cmdbuff);
|
||||||
radio.setRfPower(temp);
|
radio.setRfPower(temp);
|
||||||
|
Serial.println("!;");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 82: // R - repeater offset mode
|
case 'S': // S - squelch
|
||||||
|
getValue();
|
||||||
|
temp = atol(cmdbuff);
|
||||||
|
if (temp < -2 && temp > -130) {
|
||||||
|
radio.setSQLoThresh(temp);
|
||||||
|
radio.setSQHiThresh(temp+2);
|
||||||
|
radio.setSQOn();
|
||||||
|
Serial.print(temp);
|
||||||
|
Serial.println("!;");
|
||||||
|
} else {
|
||||||
|
Serial.println("X!;");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'R': // R - repeater offset mode
|
||||||
getValue();
|
getValue();
|
||||||
temp = atol(cmdbuff);
|
temp = atol(cmdbuff);
|
||||||
if(temp == 0) { repeater = 0; }
|
if(temp == 0) { repeater = 0; }
|
||||||
if(temp == 1) { repeater = 1; }
|
if(temp == 1) { repeater = 1; }
|
||||||
|
Serial.println("!;");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 83: // S - squelch
|
case 'T': // T - transmit offset
|
||||||
getValue();
|
getValue();
|
||||||
temp = atol(cmdbuff);
|
tx_freq = atol(cmdbuff);
|
||||||
radio.setSQLoThresh(temp);
|
Serial.println("!;");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 84: // T - transmit offset
|
case 'M': // M - Morse
|
||||||
getValue();
|
getValue();
|
||||||
tx = atol(cmdbuff);
|
if(repeater == true && tx_freq != 0) { radio.frequency(tx_freq); }
|
||||||
|
muted = false; // can't mute (for PL tones) during tx
|
||||||
|
radio.setUnmute();
|
||||||
|
radio.setModeTransmit();
|
||||||
|
delay(300);
|
||||||
|
radio.morseOut(cmdbuff);
|
||||||
|
if(repeater == true) { radio.frequency(freq); }
|
||||||
|
radio.setModeReceive();
|
||||||
|
Serial.println("!;");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'N': // N - set to Morse in Mode
|
||||||
|
morse_rx_setup();
|
||||||
|
state = MORSE;
|
||||||
|
Serial.println("!;");
|
||||||
|
break;
|
||||||
|
|
||||||
case 94: // ^ - VSSI (voice) level
|
case 'D': // D - DTMF Out
|
||||||
Serial.print(":");
|
dtmfSetup();
|
||||||
Serial.print(radio.readVSSI(),DEC);
|
getValue();
|
||||||
Serial.println(";");
|
dtmf_out(cmdbuff);
|
||||||
|
Serial.println("!;");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'B': // B - set to DTMF in Mode
|
||||||
|
dtmfSetup();
|
||||||
|
radio.enableDTMFReceive();
|
||||||
|
state = DTMF;
|
||||||
|
Serial.println("!;");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'A': // A - TX PL Tone configuration command
|
||||||
|
pl_tone_tx();
|
||||||
|
Serial.println("!;");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'C': // C - RX PL Tone configuration command
|
||||||
|
pl_tone_rx();
|
||||||
|
Serial.println("!;");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'V': // V - set volume
|
||||||
|
getValue();
|
||||||
|
temp = cmdbuff[0];
|
||||||
|
if (temp == 0x31) {
|
||||||
|
temp = atol(cmdbuff + 1);
|
||||||
|
radio.setVolume1(temp);
|
||||||
|
Serial.println("!;");
|
||||||
|
} else if (temp == 0x32) {
|
||||||
|
temp = atol(cmdbuff + 1);
|
||||||
|
radio.setVolume2(temp);
|
||||||
|
Serial.println("!;");
|
||||||
|
} else {
|
||||||
|
// not a valid volume command
|
||||||
|
while (Serial.available()) { Serial.read(); }
|
||||||
|
Serial.println("X!;");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'K': // K - switch to KISS TNC mode
|
||||||
|
//state = KISS;
|
||||||
|
//TODO: set up KISS
|
||||||
|
Serial.println("X1;");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// unknown command, flush the input buffer and wait for next one
|
||||||
|
Serial.println("X1;");
|
||||||
|
while (Serial.available()) { Serial.read(); }
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case KISS:
|
||||||
|
if (Serial.peek() == '_') {
|
||||||
|
state = NORMAL;
|
||||||
|
if (rx_ctcss) {
|
||||||
|
radio.enableCtcss();
|
||||||
|
muted = true; // can't mute (for PL tones) during tx
|
||||||
|
radio.setMute();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO: handle KISS TNC
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MORSE:
|
||||||
|
if (text == '_') { state = NORMAL; }
|
||||||
|
if (text == 'M') { // tx message
|
||||||
|
getValue();
|
||||||
|
if(repeater == true && tx_freq != 0) { radio.frequency(tx_freq); }
|
||||||
|
muted = false; // can't mute (for PL tones) during tx
|
||||||
|
radio.setUnmute();
|
||||||
|
radio.setModeTransmit();
|
||||||
|
delay(300);
|
||||||
|
radio.morseOut(cmdbuff);
|
||||||
|
if(repeater == true) { radio.frequency(freq); }
|
||||||
|
radio.setModeReceive();
|
||||||
|
} else {
|
||||||
|
// not a valid cmd
|
||||||
|
while (Serial.available()) { Serial.read(); }
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DTMF:
|
||||||
|
if (text == '_') { state = NORMAL; }
|
||||||
|
if (text == 'D') { // tx message
|
||||||
|
getValue();
|
||||||
|
dtmf_out(cmdbuff);
|
||||||
|
} else {
|
||||||
|
// not a valid cmd
|
||||||
|
while (Serial.available()) { Serial.read(); }
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// we're in an invalid state, reset to safe settings
|
||||||
|
while (Serial.available()) { Serial.read(); }
|
||||||
|
radio.frequency(freq);
|
||||||
|
radio.setModeReceive();
|
||||||
|
state = NORMAL;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
if(state == 10) {
|
|
||||||
if(millis() > (timer + 500)) { Serial.println("#TX,OFF;");radio.setModeReceive(); if(repeater == 1) { radio.frequency(freq); } state = 0; txcount = 0; }
|
// now handle any state related functions
|
||||||
|
switch (state) {
|
||||||
|
case TX:
|
||||||
|
if(millis() > (timer + 500)) {
|
||||||
|
Serial.println("#TX,OFF;");
|
||||||
|
radio.setModeReceive();
|
||||||
|
if(repeater == true) { radio.frequency(freq); }
|
||||||
|
if (rx_ctcss) {
|
||||||
|
radio.setMute();
|
||||||
|
muted = true;
|
||||||
|
}
|
||||||
|
txcount = 0;
|
||||||
|
state = NORMAL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NORMAL:
|
||||||
|
// deal with rx ctccs if necessary
|
||||||
|
if (rx_ctcss) {
|
||||||
|
if (radio.getCtcssToneDetected()) {
|
||||||
|
if (muted) {
|
||||||
|
muted = false;
|
||||||
|
radio.setUnmute();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!muted) {
|
||||||
|
muted = true;
|
||||||
|
radio.setMute();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DTMF:
|
||||||
|
dtmf_rx(); // wait for DTMF reception
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MORSE:
|
||||||
|
morse_rx(); // wait for Morse reception
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get rid of any trailing whitespace in the serial buffer
|
||||||
|
if (Serial.available()) {
|
||||||
|
char cpeek = Serial.peek();
|
||||||
|
while (cpeek == ' ' || cpeek == '\r' || cpeek == '\n')
|
||||||
|
{
|
||||||
|
Serial.read();
|
||||||
|
cpeek = Serial.peek();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,23 +403,159 @@ void getValue() {
|
||||||
for(;;) {
|
for(;;) {
|
||||||
if(Serial.available()) {
|
if(Serial.available()) {
|
||||||
temp = Serial.read();
|
temp = Serial.read();
|
||||||
if(temp == 59) { cmdbuff[p] = 0; Serial.print("@");
|
if(temp == 59) {
|
||||||
for(int x = 0; x < 32; x++) { Serial.print(cmdbuff[x]);}
|
cmdbuff[p] = 0;
|
||||||
Serial.println();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
cmdbuff[p] = temp;
|
cmdbuff[p] = temp;
|
||||||
p++;
|
p++;
|
||||||
if(p == 32) {
|
if(p == 32) {
|
||||||
Serial.print("@");
|
|
||||||
for(int x = 0; x < 32; x++) {
|
|
||||||
Serial.println(cmdbuff[x]);
|
|
||||||
}
|
|
||||||
|
|
||||||
cmdbuff[0] = 0;
|
cmdbuff[0] = 0;
|
||||||
|
return;
|
||||||
Serial.println("X0;"); return; } // some sort of alignment issue? lets not feed junk into whatever takes this string in
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void dtmfSetup() {
|
||||||
|
radio.setVolume1(6);
|
||||||
|
radio.setVolume2(0);
|
||||||
|
radio.setDTMFDetectTime(24); // time to detect a DTMF code, units are 2.5ms
|
||||||
|
radio.setDTMFIdleTime(50); // time between transmitted DTMF codes, units are 2.5ms
|
||||||
|
radio.setDTMFTxTime(60); // duration of transmitted DTMF codes, units are 2.5ms
|
||||||
|
}
|
||||||
|
|
||||||
|
void dtmf_out(char * out_buf) {
|
||||||
|
if (out_buf[0] == ';' || out_buf[0] == 0) return; // empty message
|
||||||
|
|
||||||
|
uint8_t i = 0;
|
||||||
|
uint8_t code = radio.DTMFchar2code(out_buf[i]);
|
||||||
|
|
||||||
|
// start transmitting
|
||||||
|
radio.setDTMFCode(code); // set first
|
||||||
|
radio.setTxSourceTones();
|
||||||
|
if(repeater == true && tx_freq != 0) { radio.frequency(tx_freq); }
|
||||||
|
muted = false; // can't mute during transmit
|
||||||
|
radio.setUnmute();
|
||||||
|
radio.setModeTransmit();
|
||||||
|
delay(300); // wait for TX to come to full power
|
||||||
|
|
||||||
|
bool dtmf_to_tx = true;
|
||||||
|
while (dtmf_to_tx) {
|
||||||
|
// wait until ready
|
||||||
|
while (radio.getDTMFTxActive() != 1) {
|
||||||
|
// wait until we're ready for a new code
|
||||||
|
delay(10);
|
||||||
|
}
|
||||||
|
if (i < 32 && out_buf[i] != ';' && out_buf[i] != 0) {
|
||||||
|
code = radio.DTMFchar2code(out_buf[i]);
|
||||||
|
if (code == 255) code = 0xE; // throw a * in there so we don't break things with an invalid code
|
||||||
|
radio.setDTMFCode(code); // set first
|
||||||
|
} else {
|
||||||
|
dtmf_to_tx = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
|
||||||
|
while (radio.getDTMFTxActive() != 0) {
|
||||||
|
// wait until this code is done
|
||||||
|
delay(10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// done with tone
|
||||||
|
radio.setModeReceive();
|
||||||
|
if (repeater == true) {radio.frequency(freq);}
|
||||||
|
radio.setTxSourceMic();
|
||||||
|
}
|
||||||
|
|
||||||
|
void dtmf_rx() {
|
||||||
|
char m = radio.DTMFRxLoop();
|
||||||
|
if (m != 0) {
|
||||||
|
// Note: not doing buffering of messages,
|
||||||
|
// we just send a single morse character
|
||||||
|
// whenever we get it
|
||||||
|
Serial.print('R');
|
||||||
|
Serial.print(m);
|
||||||
|
Serial.println(';');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: morse config info
|
||||||
|
|
||||||
|
void morse_rx_setup() {
|
||||||
|
// Set the morse code characteristics
|
||||||
|
radio.setMorseFreq(MORSE_FREQ);
|
||||||
|
radio.setMorseDotMillis(MORSE_DOT);
|
||||||
|
|
||||||
|
radio.lookForTone(MORSE_FREQ);
|
||||||
|
|
||||||
|
radio.setupMorseRx();
|
||||||
|
}
|
||||||
|
|
||||||
|
void morse_rx() {
|
||||||
|
char m = radio.morseRxLoop();
|
||||||
|
|
||||||
|
if (m != 0) {
|
||||||
|
// Note: not doing buffering of messages,
|
||||||
|
// we just send a single morse character
|
||||||
|
// whenever we get it
|
||||||
|
Serial.print('R');
|
||||||
|
Serial.print(m);
|
||||||
|
Serial.println(';');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void pl_tone_tx() {
|
||||||
|
memset(pl_tx_buffer,0,32);
|
||||||
|
uint8_t ptr = 0;
|
||||||
|
while(1) {
|
||||||
|
if(Serial.available()) {
|
||||||
|
uint8_t buf = Serial.read();
|
||||||
|
if(buf == 'X') { return; }
|
||||||
|
if(buf == ';') { pl_tx_buffer[ptr] = 0; program_pl_tx(); return; }
|
||||||
|
if(ptr == 31) { return; }
|
||||||
|
pl_tx_buffer[ptr] = buf; ptr++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void program_pl_tx() {
|
||||||
|
float pl_tx = atof(pl_tx_buffer);
|
||||||
|
radio.setCtcss(pl_tx);
|
||||||
|
|
||||||
|
if (pl_tx == 0) {
|
||||||
|
radio.disableCtcssTx();
|
||||||
|
} else {
|
||||||
|
radio.enableCtcssTx();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void pl_tone_rx() {
|
||||||
|
memset(pl_rx_buffer,0,32);
|
||||||
|
uint8_t ptr = 0;
|
||||||
|
while(1) {
|
||||||
|
if(Serial.available()) {
|
||||||
|
uint8_t buf = Serial.read();
|
||||||
|
if(buf == 'X') { return; }
|
||||||
|
if(buf == ';') { pl_rx_buffer[ptr] = 0; program_pl_rx(); return; }
|
||||||
|
if(ptr == 31) { return; }
|
||||||
|
pl_rx_buffer[ptr] = buf; ptr++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void program_pl_rx() {
|
||||||
|
float pl_rx = atof(pl_rx_buffer);
|
||||||
|
radio.setCtcss(pl_rx);
|
||||||
|
if (pl_rx == 0) {
|
||||||
|
rx_ctcss = false;
|
||||||
|
radio.setUnmute();
|
||||||
|
muted = false;
|
||||||
|
radio.disableCtcssRx();
|
||||||
|
} else {
|
||||||
|
rx_ctcss = true;
|
||||||
|
radio.setMute();
|
||||||
|
muted = true;
|
||||||
|
radio.enableCtcssRx();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -106,7 +106,7 @@ void setup() {
|
||||||
int result = radio.testConnection();
|
int result = radio.testConnection();
|
||||||
Serial.println(result);
|
Serial.println(result);
|
||||||
radio.initialize();
|
radio.initialize();
|
||||||
radio.frequency(446000);
|
radio.frequency(432400);
|
||||||
radio.setVolume1(0xF);
|
radio.setVolume1(0xF);
|
||||||
radio.setVolume2(0xF);
|
radio.setVolume2(0xF);
|
||||||
radio.setModeReceive();
|
radio.setModeReceive();
|
||||||
|
|
|
@ -249,7 +249,7 @@ void setup() {
|
||||||
Serial.println("Setting radio to its defaults..");
|
Serial.println("Setting radio to its defaults..");
|
||||||
radio.initialize();
|
radio.initialize();
|
||||||
radio.setRfPower(0);
|
radio.setRfPower(0);
|
||||||
radio.frequency(144025);
|
radio.frequency(145010);
|
||||||
|
|
||||||
radio.setModeTransmit();
|
radio.setModeTransmit();
|
||||||
voice.say(spKILO); // to change these to the words you would like to say, or a ham radio call sign - uncomment above encoded words
|
voice.say(spKILO); // to change these to the words you would like to say, or a ham radio call sign - uncomment above encoded words
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
name=HamShield
|
name=HamShield
|
||||||
version=1.1.2
|
version=1.1.3
|
||||||
author=Morgan Redfield <morgan@enhancedradio.com>, Casey Halverson <casey@enhancedradio.com>
|
author=Morgan Redfield <morgan@enhancedradio.com>, Casey Halverson <casey@enhancedradio.com>
|
||||||
maintainer=Morgan Redfield <morgan@enhancedradio.com>
|
maintainer=Morgan Redfield <morgan@enhancedradio.com>
|
||||||
sentence=A library for use with HamShield by Enhanced Radio Devices.
|
sentence=A library for use with HamShield by Enhanced Radio Devices.
|
||||||
|
|
|
@ -193,7 +193,7 @@ void HamShield::initialize(bool narrowBand) {
|
||||||
HSwriteWord(devAddr, 0x57, tx_data);
|
HSwriteWord(devAddr, 0x57, tx_data);
|
||||||
tx_data = 0x800D;
|
tx_data = 0x800D;
|
||||||
HSwriteWord(devAddr, 0x58, tx_data);
|
HSwriteWord(devAddr, 0x58, tx_data);
|
||||||
tx_data = 0x0EDD;
|
tx_data = 0x0EDB;
|
||||||
HSwriteWord(devAddr, 0x5A, tx_data); // sq and noise detect times
|
HSwriteWord(devAddr, 0x5A, tx_data); // sq and noise detect times
|
||||||
tx_data = 0x3FFF;
|
tx_data = 0x3FFF;
|
||||||
HSwriteWord(devAddr, 0x63, tx_data); // pre-emphasis bypass
|
HSwriteWord(devAddr, 0x63, tx_data); // pre-emphasis bypass
|
||||||
|
@ -227,7 +227,7 @@ void HamShield::initialize(bool narrowBand) {
|
||||||
setModeReceive();
|
setModeReceive();
|
||||||
setTxSourceMic();
|
setTxSourceMic();
|
||||||
setRfPower(0);
|
setRfPower(0);
|
||||||
setSQLoThresh(80);
|
setSQLoThresh(-80);
|
||||||
setSQOn();
|
setSQOn();
|
||||||
*/
|
*/
|
||||||
setDTMFIdleTime(50);
|
setDTMFIdleTime(50);
|
||||||
|
@ -256,11 +256,11 @@ void HamShield::setupNarrowBand() {
|
||||||
HSwriteWord(devAddr, 0x34, tx_data);
|
HSwriteWord(devAddr, 0x34, tx_data);
|
||||||
tx_data = 0x40C3;
|
tx_data = 0x40C3;
|
||||||
HSwriteWord(devAddr, 0x3A, tx_data); // modu_det_sel sq setting
|
HSwriteWord(devAddr, 0x3A, tx_data); // modu_det_sel sq setting
|
||||||
tx_data = 0x0407;
|
tx_data = 0x0F1E;
|
||||||
HSwriteWord(devAddr, 0x3C, tx_data); // pk_det_th sq setting [8:7]
|
HSwriteWord(devAddr, 0x3C, tx_data); // pk_det_th sq setting [8:7]
|
||||||
tx_data = 0x28D0;
|
tx_data = 0x28D0;
|
||||||
HSwriteWord(devAddr, 0x3F, tx_data); // rssi3_th sq setting
|
HSwriteWord(devAddr, 0x3F, tx_data); // rssi3_th sq setting
|
||||||
tx_data = 0x203E;
|
tx_data = 0x20BE;
|
||||||
HSwriteWord(devAddr, 0x48, tx_data);
|
HSwriteWord(devAddr, 0x48, tx_data);
|
||||||
tx_data = 0x1BB7;
|
tx_data = 0x1BB7;
|
||||||
HSwriteWord(devAddr, 0x60, tx_data);
|
HSwriteWord(devAddr, 0x60, tx_data);
|
||||||
|
@ -773,20 +773,37 @@ void HamShield::setCtcssFreqToStandard(){
|
||||||
setCtcssFreq(13440);
|
setCtcssFreq(13440);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HamShield::enableCtcss() {
|
void HamShield::enableCtcssTx() {
|
||||||
// enable TX
|
|
||||||
HSwriteBitsW(devAddr, A1846S_CTCSS_MODE_REG, 10, 2, 3);
|
HSwriteBitsW(devAddr, A1846S_CTCSS_MODE_REG, 10, 2, 3);
|
||||||
|
}
|
||||||
|
|
||||||
// enable RX
|
void HamShield::enableCtcssRx() {
|
||||||
setCtcssGpioSel(1);
|
setCtcssGpioSel(1);
|
||||||
HSwriteBitW(devAddr, A1846S_TX_VOICE_REG, A1846S_CTCSS_DET_BIT, 0);
|
HSwriteBitW(devAddr, A1846S_TX_VOICE_REG, A1846S_CTCSS_DET_BIT, 0);
|
||||||
HSwriteBitW(devAddr, A1846S_FILTER_REG, A1846S_CTCSS_FILTER_BYPASS, 0);
|
HSwriteBitW(devAddr, A1846S_FILTER_REG, A1846S_CTCSS_FILTER_BYPASS, 0);
|
||||||
setDetCtcss();
|
setDetCtcss();
|
||||||
}
|
}
|
||||||
void HamShield::disableCtcss() {
|
|
||||||
|
void HamShield::enableCtcss() {
|
||||||
|
// enable TX
|
||||||
|
enableCtcssTx();
|
||||||
|
|
||||||
|
// enable RX
|
||||||
|
enableCtcssRx();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HamShield::disableCtcssTx() {
|
||||||
HSwriteBitsW(devAddr, A1846S_CTCSS_MODE_REG, 10, 2, 0);
|
HSwriteBitsW(devAddr, A1846S_CTCSS_MODE_REG, 10, 2, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HamShield::disableCtcssRx() {
|
||||||
|
setCtcssGpioSel(0);
|
||||||
disableCtcssCdcss();
|
disableCtcssCdcss();
|
||||||
}
|
}
|
||||||
|
void HamShield::disableCtcss() {
|
||||||
|
disableCtcssTx();
|
||||||
|
disableCtcssRx();
|
||||||
|
}
|
||||||
|
|
||||||
// match threshold
|
// match threshold
|
||||||
void HamShield::setCtcssDetThreshIn(uint8_t thresh) {
|
void HamShield::setCtcssDetThreshIn(uint8_t thresh) {
|
||||||
|
@ -870,24 +887,30 @@ bool HamShield::getSQState(){
|
||||||
void HamShield::setSQHiThresh(int16_t sq_hi_threshold){
|
void HamShield::setSQHiThresh(int16_t sq_hi_threshold){
|
||||||
// Sq detect high th, rssi_cmp will be 1 when rssi>th_h_sq, unit 1dB
|
// Sq detect high th, rssi_cmp will be 1 when rssi>th_h_sq, unit 1dB
|
||||||
uint16_t sq = 137 + sq_hi_threshold;
|
uint16_t sq = 137 + sq_hi_threshold;
|
||||||
HSwriteWord(devAddr, A1846S_SQ_OPEN_THRESH_REG, sq);
|
HSwriteBitsW(devAddr, A1846S_SQ_OPEN_THRESH_REG, A1846S_SQ_OPEN_THRESH_BIT, A1846S_SQ_OPEN_THRESH_LENGTH, sq);
|
||||||
}
|
}
|
||||||
int16_t HamShield::getSQHiThresh(){
|
int16_t HamShield::getSQHiThresh(){
|
||||||
HSreadWord(devAddr, A1846S_SQ_OPEN_THRESH_REG, radio_i2c_buf);
|
HSreadBitsW(devAddr, A1846S_SQ_OPEN_THRESH_REG, A1846S_SQ_OPEN_THRESH_BIT, A1846S_SQ_OPEN_THRESH_LENGTH, radio_i2c_buf);
|
||||||
|
|
||||||
return radio_i2c_buf[0] - 137;
|
return radio_i2c_buf[0] - 137;
|
||||||
}
|
}
|
||||||
void HamShield::setSQLoThresh(int16_t sq_lo_threshold){
|
void HamShield::setSQLoThresh(int16_t sq_lo_threshold){
|
||||||
// Sq detect low th, rssi_cmp will be 0 when rssi<th_l_sq && time delay meet, unit 1 dB
|
// Sq detect low th, rssi_cmp will be 0 when rssi<th_l_sq && time delay meet, unit 1 dB
|
||||||
uint16_t sq = 137 + sq_lo_threshold;
|
uint16_t sq = 137 + sq_lo_threshold;
|
||||||
HSwriteWord(devAddr, A1846S_SQ_SHUT_THRESH_REG, sq);
|
HSwriteBitsW(devAddr, A1846S_SQ_SHUT_THRESH_REG, A1846S_SQ_SHUT_THRESH_BIT, A1846S_SQ_SHUT_THRESH_LENGTH, sq);
|
||||||
}
|
}
|
||||||
int16_t HamShield::getSQLoThresh(){
|
int16_t HamShield::getSQLoThresh(){
|
||||||
HSreadWord(devAddr, A1846S_SQ_SHUT_THRESH_REG, radio_i2c_buf);
|
HSreadBitsW(devAddr, A1846S_SQ_SHUT_THRESH_REG, A1846S_SQ_SHUT_THRESH_BIT, A1846S_SQ_SHUT_THRESH_LENGTH, radio_i2c_buf);
|
||||||
|
|
||||||
return radio_i2c_buf[0] - 137;
|
return radio_i2c_buf[0] - 137;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool HamShield::getSquelching() {
|
||||||
|
HSreadBitW(devAddr, A1846S_FLAG_REG, A1846S_SQ_FLAG_BIT, radio_i2c_buf);
|
||||||
|
return (radio_i2c_buf[0] != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// SQ out select
|
// SQ out select
|
||||||
void HamShield::setSQOutSel(){
|
void HamShield::setSQOutSel(){
|
||||||
HSwriteBitW(devAddr, A1846S_SQ_OUT_SEL_REG, A1846S_SQ_OUT_SEL_BIT, 1);
|
HSwriteBitW(devAddr, A1846S_SQ_OUT_SEL_REG, A1846S_SQ_OUT_SEL_BIT, 1);
|
||||||
|
@ -998,6 +1021,67 @@ uint16_t HamShield::getDTMFIdleTime() {
|
||||||
return radio_i2c_buf[0];
|
return radio_i2c_buf[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char HamShield::DTMFRxLoop() {
|
||||||
|
char m = 0;
|
||||||
|
if (getDTMFSample() != 0) {
|
||||||
|
uint16_t code = getDTMFCode();
|
||||||
|
|
||||||
|
m = DTMFcode2char(code);
|
||||||
|
|
||||||
|
// reset after this tone
|
||||||
|
int j = 0;
|
||||||
|
while (j < 4) {
|
||||||
|
if (getDTMFSample() == 0) {
|
||||||
|
j++;
|
||||||
|
} else {
|
||||||
|
j = 1;
|
||||||
|
}
|
||||||
|
delay(10);
|
||||||
|
}
|
||||||
|
// reset read
|
||||||
|
//enableDTMFReceive();
|
||||||
|
}
|
||||||
|
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char HamShield::DTMFcode2char(uint16_t code) {
|
||||||
|
char c;
|
||||||
|
if (code < 10) {
|
||||||
|
c = '0' + code;
|
||||||
|
} else if (code < 0xE) {
|
||||||
|
c = 'A' + code - 10;
|
||||||
|
} else if (code == 0xE) {
|
||||||
|
c = '*';
|
||||||
|
} else if (code == 0xF) {
|
||||||
|
c = '#';
|
||||||
|
} else {
|
||||||
|
c = '?'; // invalid code
|
||||||
|
}
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t HamShield::DTMFchar2code(char c) {
|
||||||
|
uint8_t code;
|
||||||
|
if (c == '#') {
|
||||||
|
code = 0xF;
|
||||||
|
} else if (c=='*') {
|
||||||
|
code = 0xE;
|
||||||
|
} else if (c >= 'A' && c <= 'D') {
|
||||||
|
code = c - 'A' + 0xA;
|
||||||
|
} else if (c >= '0' && c <= '9') {
|
||||||
|
code = c - '0';
|
||||||
|
} else {
|
||||||
|
// invalid code, skip it
|
||||||
|
code = 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void HamShield::setDTMFTxTime(uint16_t tx_time) {
|
void HamShield::setDTMFTxTime(uint16_t tx_time) {
|
||||||
if (tx_time > 63) {tx_time = 63;} // maxed out
|
if (tx_time > 63) {tx_time = 63;} // maxed out
|
||||||
// tx time is duration of DTMF Tone
|
// tx time is duration of DTMF Tone
|
||||||
|
@ -1616,6 +1700,10 @@ bool HamShield::waitForChannel(long timeout = 0, long breakwindow = 0, int setRS
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HamShield::setupMorseRx() {
|
||||||
|
// TODO: morse timing config (e.g. dot time, dash time, etc)
|
||||||
|
}
|
||||||
|
|
||||||
// Get current morse code tone frequency (in Hz)
|
// Get current morse code tone frequency (in Hz)
|
||||||
|
|
||||||
unsigned int HamShield::getMorseFreq() {
|
unsigned int HamShield::getMorseFreq() {
|
||||||
|
@ -1693,6 +1781,104 @@ void HamShield::morseOut(char buffer[HAMSHIELD_MORSE_BUFFER_SIZE]) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// returns '\0' if no valid morse char found yet
|
||||||
|
char HamShield::morseRxLoop() {
|
||||||
|
static uint32_t last_tone_check = 0; // track how often we check for morse tones
|
||||||
|
static uint32_t tone_in_progress; // track how long the current tone lasts
|
||||||
|
static uint32_t space_in_progress; // track how long since the last tone
|
||||||
|
static uint8_t rx_morse_char;
|
||||||
|
static uint8_t rx_morse_bit;
|
||||||
|
static bool bits_to_process;
|
||||||
|
|
||||||
|
if (last_tone_check == 0) {
|
||||||
|
last_tone_check = millis();
|
||||||
|
space_in_progress = 0; // haven't checked yet
|
||||||
|
tone_in_progress = 0; // not currently listening to a tone
|
||||||
|
rx_morse_char = 0; // haven't found any tones yet
|
||||||
|
rx_morse_bit = 1;
|
||||||
|
bits_to_process = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
char m = 0;
|
||||||
|
|
||||||
|
// are we receiving anything
|
||||||
|
if (toneDetected()) {
|
||||||
|
space_in_progress = 0;
|
||||||
|
if (tone_in_progress == 0) {
|
||||||
|
// start a new tone
|
||||||
|
tone_in_progress = millis();
|
||||||
|
//Serial.print('t');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// keep track of how long the silence is
|
||||||
|
if (space_in_progress == 0) space_in_progress = millis();
|
||||||
|
|
||||||
|
// we wait for a bit of silence before ending the last
|
||||||
|
// symbol in order to smooth out the detector
|
||||||
|
if ((millis() - space_in_progress) > SYMBOL_END_TIME)
|
||||||
|
{
|
||||||
|
if (tone_in_progress != 0) {
|
||||||
|
// end the last tone
|
||||||
|
uint16_t tone_time = millis() - tone_in_progress;
|
||||||
|
tone_in_progress = 0;
|
||||||
|
//Serial.println(tone_time);
|
||||||
|
bits_to_process = handleMorseTone(tone_time, bits_to_process, &rx_morse_char, &rx_morse_bit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// we might be done with a character if the space is long enough
|
||||||
|
if (((millis() - space_in_progress) > CHAR_END_TIME) && bits_to_process) {
|
||||||
|
m = parseMorse(rx_morse_char, rx_morse_bit);
|
||||||
|
bits_to_process = false;
|
||||||
|
rx_morse_char = 0;
|
||||||
|
rx_morse_bit = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// we might be done with a message if the space is long enough
|
||||||
|
if ((millis() - space_in_progress) > MESSAGE_END_TIME) {
|
||||||
|
rx_morse_char = 0;
|
||||||
|
rx_morse_bit = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HamShield::handleMorseTone(uint16_t tone_time, bool bits_to_process,
|
||||||
|
uint8_t * rx_morse_char, uint8_t * rx_morse_bit) {
|
||||||
|
//Serial.println(tone_time);
|
||||||
|
if (tone_time > MIN_DOT_TIME && tone_time < MAX_DOT_TIME) {
|
||||||
|
// add a dot
|
||||||
|
//Serial.print(".");
|
||||||
|
bits_to_process = true;
|
||||||
|
//nothing to do for this bit position, since . = 0
|
||||||
|
} else if (tone_time > MIN_DASH_TIME && tone_time < MAX_DASH_TIME) {
|
||||||
|
// add a dash
|
||||||
|
//Serial.print("-");
|
||||||
|
bits_to_process = true;
|
||||||
|
*rx_morse_char += *rx_morse_bit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// prep for the next bit
|
||||||
|
*rx_morse_bit = *rx_morse_bit << 1;
|
||||||
|
|
||||||
|
return bits_to_process;
|
||||||
|
}
|
||||||
|
|
||||||
|
char HamShield::parseMorse(uint8_t rx_morse_char, uint8_t rx_morse_bit) {
|
||||||
|
// if morse_char is a valid morse character, return the character
|
||||||
|
// if morse_char is an invalid (incomplete) morse character, return 0
|
||||||
|
|
||||||
|
|
||||||
|
//if (rx_morse_bit != 1) Serial.println(rx_morse_char, BIN);
|
||||||
|
rx_morse_char += rx_morse_bit; // add the terminator bit
|
||||||
|
// if we got a char, then print it
|
||||||
|
char c = morseReverseLookup(rx_morse_char);
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Morse code lookup table */
|
/* Morse code lookup table */
|
||||||
|
|
||||||
uint8_t HamShield::morseLookup(char letter) {
|
uint8_t HamShield::morseLookup(char letter) {
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
#define A1846S_TH_L_VOX_REG 0x64 // register holds vox low (shut) threshold bits
|
#define A1846S_TH_L_VOX_REG 0x64 // register holds vox low (shut) threshold bits
|
||||||
#define A1846S_FM_DEV_REG 0x43 // register holds fm deviation settings
|
#define A1846S_FM_DEV_REG 0x43 // register holds fm deviation settings
|
||||||
#define A1846S_RX_VOLUME_REG 0x44 // register holds RX volume settings
|
#define A1846S_RX_VOLUME_REG 0x44 // register holds RX volume settings
|
||||||
#define A1846S_SQ_OPEN_THRESH_REG 0x48 // see sq
|
#define A1846S_SQ_OPEN_THRESH_REG 0x49 // see sq
|
||||||
#define A1846S_SQ_SHUT_THRESH_REG 0x49 // see sq
|
#define A1846S_SQ_SHUT_THRESH_REG 0x49 // see sq
|
||||||
#define A1846S_CTCSS_FREQ_REG 0x4A // ctcss_freq<15:0>
|
#define A1846S_CTCSS_FREQ_REG 0x4A // ctcss_freq<15:0>
|
||||||
#define A1846S_CDCSS_CODE_HI_REG 0x4B // cdcss_code<23:16>
|
#define A1846S_CDCSS_CODE_HI_REG 0x4B // cdcss_code<23:16>
|
||||||
|
@ -145,12 +145,12 @@
|
||||||
#define A1846S_SHIFT_SEL_LEN 2
|
#define A1846S_SHIFT_SEL_LEN 2
|
||||||
|
|
||||||
// Bitfields for A1846S_SQ_THRESH_REG
|
// Bitfields for A1846S_SQ_THRESH_REG
|
||||||
#define A1846S_SQ_OPEN_THRESH_BIT 9 // sq open threshold <9:0>
|
#define A1846S_SQ_OPEN_THRESH_BIT 13 // sq open threshold <6:0>
|
||||||
#define A1846S_SQ_OPEN_THRESH_LENGTH 10
|
#define A1846S_SQ_OPEN_THRESH_LENGTH 7
|
||||||
|
|
||||||
// Bitfields for A1846S_SQ_SHUT_THRESH_REG
|
// Bitfields for A1846S_SQ_SHUT_THRESH_REG
|
||||||
#define A1846S_SQ_SHUT_THRESH_BIT 9 // sq shut threshold <9:0>
|
#define A1846S_SQ_SHUT_THRESH_BIT 6 // sq shut threshold <6:0>
|
||||||
#define A1846S_SQ_SHUT_THRESH_LENGTH 10
|
#define A1846S_SQ_SHUT_THRESH_LENGTH 7
|
||||||
|
|
||||||
// Bitfields for A1846S_SQ_OUT_SEL_REG
|
// Bitfields for A1846S_SQ_OUT_SEL_REG
|
||||||
#define A1846S_SQ_OUT_SEL_BIT 7 // sq_out_sel
|
#define A1846S_SQ_OUT_SEL_BIT 7 // sq_out_sel
|
||||||
|
@ -168,8 +168,8 @@
|
||||||
#define A1846S_CTCSS2_FLAG_BIT 8 // 1 when txon is enabled
|
#define A1846S_CTCSS2_FLAG_BIT 8 // 1 when txon is enabled
|
||||||
#define A1846S_INVERT_DET_FLAG_BIT 7 // ctcss phase shift detect
|
#define A1846S_INVERT_DET_FLAG_BIT 7 // ctcss phase shift detect
|
||||||
#define A1846S_CSS_CMP_FLAG_BIT 2 // ctcss/cdcss compared
|
#define A1846S_CSS_CMP_FLAG_BIT 2 // ctcss/cdcss compared
|
||||||
#define A1846S_SQ_FLAG_BIT 1 // sq final signal out from dsp
|
#define A1846S_SQ_FLAG_BIT 0 // sq final signal out from dsp
|
||||||
#define A1846S_VOX_FLAG_BIT 0 // vox out from dsp
|
#define A1846S_VOX_FLAG_BIT 1 // vox out from dsp
|
||||||
|
|
||||||
// Bitfields for A1846S_RSSI_REG
|
// Bitfields for A1846S_RSSI_REG
|
||||||
#define A1846S_RSSI_BIT 15 // RSSI readings <7:0>
|
#define A1846S_RSSI_BIT 15 // RSSI readings <7:0>
|
||||||
|
@ -217,6 +217,20 @@
|
||||||
#define HAMSHIELD_PSK31_FREQ 1000
|
#define HAMSHIELD_PSK31_FREQ 1000
|
||||||
|
|
||||||
|
|
||||||
|
// Morse Configuration
|
||||||
|
|
||||||
|
#define MORSE_FREQ 600
|
||||||
|
#define MORSE_DOT 150 // ms
|
||||||
|
|
||||||
|
#define SYMBOL_END_TIME 5 //millis
|
||||||
|
#define CHAR_END_TIME (MORSE_DOT*2.7)
|
||||||
|
#define MESSAGE_END_TIME (MORSE_DOT*8)
|
||||||
|
|
||||||
|
#define MIN_DOT_TIME (MORSE_DOT-30)
|
||||||
|
#define MAX_DOT_TIME (MORSE_DOT+55)
|
||||||
|
#define MIN_DASH_TIME (MORSE_DOT*3-30)
|
||||||
|
#define MAX_DASH_TIME (MORSE_DOT*3+55)
|
||||||
|
|
||||||
|
|
||||||
class HamShield {
|
class HamShield {
|
||||||
public:
|
public:
|
||||||
|
@ -299,7 +313,11 @@ class HamShield {
|
||||||
uint16_t getCtcssFreqMilliHz();
|
uint16_t getCtcssFreqMilliHz();
|
||||||
float getCtcssFreqHz();
|
float getCtcssFreqHz();
|
||||||
void setCtcssFreqToStandard(); // freq must be 134.4Hz for standard cdcss mode
|
void setCtcssFreqToStandard(); // freq must be 134.4Hz for standard cdcss mode
|
||||||
|
void enableCtcssTx();
|
||||||
|
void enableCtcssRx();
|
||||||
void enableCtcss();
|
void enableCtcss();
|
||||||
|
void disableCtcssTx();
|
||||||
|
void disableCtcssRx();
|
||||||
void disableCtcss();
|
void disableCtcss();
|
||||||
void setCtcssDetThreshIn(uint8_t thresh);
|
void setCtcssDetThreshIn(uint8_t thresh);
|
||||||
uint8_t getCtcssDetThreshIn();
|
uint8_t getCtcssDetThreshIn();
|
||||||
|
@ -344,6 +362,7 @@ class HamShield {
|
||||||
int16_t getSQHiThresh();
|
int16_t getSQHiThresh();
|
||||||
void setSQLoThresh(int16_t sq_lo_threshold); // Sq detect low th, rssi_cmp will be 0 when rssi<th_l_sq && time delay meet, unit 1dB
|
void setSQLoThresh(int16_t sq_lo_threshold); // Sq detect low th, rssi_cmp will be 0 when rssi<th_l_sq && time delay meet, unit 1dB
|
||||||
int16_t getSQLoThresh();
|
int16_t getSQLoThresh();
|
||||||
|
bool getSquelching();
|
||||||
|
|
||||||
// SQ out select
|
// SQ out select
|
||||||
void setSQOutSel();
|
void setSQOutSel();
|
||||||
|
@ -389,6 +408,9 @@ class HamShield {
|
||||||
uint16_t getDTMFDetectTime();
|
uint16_t getDTMFDetectTime();
|
||||||
void setDTMFIdleTime(uint16_t idle_time); // idle time is time between DTMF Tone
|
void setDTMFIdleTime(uint16_t idle_time); // idle time is time between DTMF Tone
|
||||||
uint16_t getDTMFIdleTime();
|
uint16_t getDTMFIdleTime();
|
||||||
|
char DTMFRxLoop();
|
||||||
|
char DTMFcode2char(uint16_t code);
|
||||||
|
uint8_t DTMFchar2code(char c);
|
||||||
void setDTMFTxTime(uint16_t tx_time); // tx time is duration of DTMF Tone
|
void setDTMFTxTime(uint16_t tx_time); // tx time is duration of DTMF Tone
|
||||||
uint16_t getDTMFTxTime();
|
uint16_t getDTMFTxTime();
|
||||||
uint16_t disableDTMF();
|
uint16_t disableDTMF();
|
||||||
|
@ -482,11 +504,15 @@ class HamShield {
|
||||||
uint32_t scanChannels(uint32_t buffer[],uint8_t buffsize, uint8_t speed, uint16_t threshold);
|
uint32_t scanChannels(uint32_t buffer[],uint8_t buffsize, uint8_t speed, uint16_t threshold);
|
||||||
uint32_t findWhitespaceChannels(uint32_t buffer[],uint8_t buffsize, uint8_t dwell, uint16_t threshold);
|
uint32_t findWhitespaceChannels(uint32_t buffer[],uint8_t buffsize, uint8_t dwell, uint16_t threshold);
|
||||||
|
|
||||||
|
void setupMorseRx();
|
||||||
unsigned int getMorseFreq();
|
unsigned int getMorseFreq();
|
||||||
void setMorseFreq(unsigned int morse_freq_hz);
|
void setMorseFreq(unsigned int morse_freq_hz);
|
||||||
unsigned int getMorseDotMillis();
|
unsigned int getMorseDotMillis();
|
||||||
void setMorseDotMillis(unsigned int morse_dot_dur_millis);
|
void setMorseDotMillis(unsigned int morse_dot_dur_millis);
|
||||||
void morseOut(char buffer[HAMSHIELD_MORSE_BUFFER_SIZE]);
|
void morseOut(char buffer[HAMSHIELD_MORSE_BUFFER_SIZE]);
|
||||||
|
char morseRxLoop();
|
||||||
|
bool handleMorseTone(uint16_t tone_time, bool bits_to_process, uint8_t * rx_morse_char, uint8_t * rx_morse_bit);
|
||||||
|
char parseMorse(uint8_t rx_morse_char, uint8_t rx_morse_bit);
|
||||||
uint8_t morseLookup(char letter);
|
uint8_t morseLookup(char letter);
|
||||||
uint8_t morseReverseLookup(uint8_t itu);
|
uint8_t morseReverseLookup(uint8_t itu);
|
||||||
bool waitForChannel(long timeout, long breakwindow, int setRSSI);
|
bool waitForChannel(long timeout, long breakwindow, int setRSSI);
|
||||||
|
|
Loading…
Reference in New Issue