update dtmf, morse, and examples

This commit is contained in:
Morgan Redfield
2019-07-14 13:37:14 -07:00
parent 71acbbb975
commit 3d3f6a36b6
16 changed files with 727 additions and 331 deletions

View File

@@ -193,7 +193,7 @@ void HamShield::initialize(bool narrowBand) {
HSwriteWord(devAddr, 0x57, tx_data);
tx_data = 0x800D;
HSwriteWord(devAddr, 0x58, tx_data);
tx_data = 0x0EDD;
tx_data = 0x0EDB;
HSwriteWord(devAddr, 0x5A, tx_data); // sq and noise detect times
tx_data = 0x3FFF;
HSwriteWord(devAddr, 0x63, tx_data); // pre-emphasis bypass
@@ -227,7 +227,7 @@ void HamShield::initialize(bool narrowBand) {
setModeReceive();
setTxSourceMic();
setRfPower(0);
setSQLoThresh(80);
setSQLoThresh(-80);
setSQOn();
*/
setDTMFIdleTime(50);
@@ -256,11 +256,11 @@ void HamShield::setupNarrowBand() {
HSwriteWord(devAddr, 0x34, tx_data);
tx_data = 0x40C3;
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]
tx_data = 0x28D0;
HSwriteWord(devAddr, 0x3F, tx_data); // rssi3_th sq setting
tx_data = 0x203E;
tx_data = 0x20BE;
HSwriteWord(devAddr, 0x48, tx_data);
tx_data = 0x1BB7;
HSwriteWord(devAddr, 0x60, tx_data);
@@ -773,20 +773,37 @@ void HamShield::setCtcssFreqToStandard(){
setCtcssFreq(13440);
}
void HamShield::enableCtcss() {
// enable TX
HSwriteBitsW(devAddr, A1846S_CTCSS_MODE_REG, 10, 2, 3);
// enable RX
setCtcssGpioSel(1);
void HamShield::enableCtcssTx() {
HSwriteBitsW(devAddr, A1846S_CTCSS_MODE_REG, 10, 2, 3);
}
void HamShield::enableCtcssRx() {
setCtcssGpioSel(1);
HSwriteBitW(devAddr, A1846S_TX_VOICE_REG, A1846S_CTCSS_DET_BIT, 0);
HSwriteBitW(devAddr, A1846S_FILTER_REG, A1846S_CTCSS_FILTER_BYPASS, 0);
setDetCtcss();
}
void HamShield::disableCtcss() {
HSwriteBitsW(devAddr, A1846S_CTCSS_MODE_REG, 10, 2, 0);
void HamShield::enableCtcss() {
// enable TX
enableCtcssTx();
// enable RX
enableCtcssRx();
}
void HamShield::disableCtcssTx() {
HSwriteBitsW(devAddr, A1846S_CTCSS_MODE_REG, 10, 2, 0);
}
void HamShield::disableCtcssRx() {
setCtcssGpioSel(0);
disableCtcssCdcss();
}
void HamShield::disableCtcss() {
disableCtcssTx();
disableCtcssRx();
}
// match threshold
void HamShield::setCtcssDetThreshIn(uint8_t thresh) {
@@ -870,24 +887,30 @@ bool HamShield::getSQState(){
void HamShield::setSQHiThresh(int16_t sq_hi_threshold){
// Sq detect high th, rssi_cmp will be 1 when rssi>th_h_sq, unit 1dB
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(){
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;
}
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
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(){
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;
}
bool HamShield::getSquelching() {
HSreadBitW(devAddr, A1846S_FLAG_REG, A1846S_SQ_FLAG_BIT, radio_i2c_buf);
return (radio_i2c_buf[0] != 0);
}
// SQ out select
void HamShield::setSQOutSel(){
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];
}
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) {
if (tx_time > 63) {tx_time = 63;} // maxed out
// tx time is duration of DTMF Tone
@@ -1616,6 +1700,10 @@ bool HamShield::waitForChannel(long timeout = 0, long breakwindow = 0, int setRS
return false;
}
void HamShield::setupMorseRx() {
// TODO: morse timing config (e.g. dot time, dash time, etc)
}
// Get current morse code tone frequency (in Hz)
unsigned int HamShield::getMorseFreq() {
@@ -1693,6 +1781,104 @@ void HamShield::morseOut(char buffer[HAMSHIELD_MORSE_BUFFER_SIZE]) {
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 */
uint8_t HamShield::morseLookup(char letter) {

View File

@@ -32,7 +32,7 @@
#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_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_CTCSS_FREQ_REG 0x4A // ctcss_freq<15:0>
#define A1846S_CDCSS_CODE_HI_REG 0x4B // cdcss_code<23:16>
@@ -145,12 +145,12 @@
#define A1846S_SHIFT_SEL_LEN 2
// Bitfields for A1846S_SQ_THRESH_REG
#define A1846S_SQ_OPEN_THRESH_BIT 9 // sq open threshold <9:0>
#define A1846S_SQ_OPEN_THRESH_LENGTH 10
#define A1846S_SQ_OPEN_THRESH_BIT 13 // sq open threshold <6:0>
#define A1846S_SQ_OPEN_THRESH_LENGTH 7
// Bitfields for A1846S_SQ_SHUT_THRESH_REG
#define A1846S_SQ_SHUT_THRESH_BIT 9 // sq shut threshold <9:0>
#define A1846S_SQ_SHUT_THRESH_LENGTH 10
#define A1846S_SQ_SHUT_THRESH_BIT 6 // sq shut threshold <6:0>
#define A1846S_SQ_SHUT_THRESH_LENGTH 7
// Bitfields for A1846S_SQ_OUT_SEL_REG
#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_INVERT_DET_FLAG_BIT 7 // ctcss phase shift detect
#define A1846S_CSS_CMP_FLAG_BIT 2 // ctcss/cdcss compared
#define A1846S_SQ_FLAG_BIT 1 // sq final signal out from dsp
#define A1846S_VOX_FLAG_BIT 0 // vox out from dsp
#define A1846S_SQ_FLAG_BIT 0 // sq final signal out from dsp
#define A1846S_VOX_FLAG_BIT 1 // vox out from dsp
// Bitfields for A1846S_RSSI_REG
#define A1846S_RSSI_BIT 15 // RSSI readings <7:0>
@@ -217,6 +217,20 @@
#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 {
public:
@@ -299,7 +313,11 @@ class HamShield {
uint16_t getCtcssFreqMilliHz();
float getCtcssFreqHz();
void setCtcssFreqToStandard(); // freq must be 134.4Hz for standard cdcss mode
void enableCtcssTx();
void enableCtcssRx();
void enableCtcss();
void disableCtcssTx();
void disableCtcssRx();
void disableCtcss();
void setCtcssDetThreshIn(uint8_t thresh);
uint8_t getCtcssDetThreshIn();
@@ -344,6 +362,7 @@ class HamShield {
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
int16_t getSQLoThresh();
bool getSquelching();
// SQ out select
void setSQOutSel();
@@ -389,6 +408,9 @@ class HamShield {
uint16_t getDTMFDetectTime();
void setDTMFIdleTime(uint16_t idle_time); // idle time is time between DTMF Tone
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
uint16_t getDTMFTxTime();
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 findWhitespaceChannels(uint32_t buffer[],uint8_t buffsize, uint8_t dwell, uint16_t threshold);
void setupMorseRx();
unsigned int getMorseFreq();
void setMorseFreq(unsigned int morse_freq_hz);
unsigned int getMorseDotMillis();
void setMorseDotMillis(unsigned int morse_dot_dur_millis);
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 morseReverseLookup(uint8_t itu);
bool waitForChannel(long timeout, long breakwindow, int setRSSI);