diff --git a/examples/CTCSS/CTCSS.ino b/examples/CTCSS/CTCSS.ino new file mode 100644 index 0000000..0bb9ad3 --- /dev/null +++ b/examples/CTCSS/CTCSS.ino @@ -0,0 +1,174 @@ +/* Hamshield + * Example: CTCSS + * This is a simple example to demonstrate HamShield receive + * and transmit functionality using CTCSS. The HamShield will + * have audio output muted until it receives the correct + * sub-audible tone. It does this by polling a tone detection + * flag on the HamShield, but it's also possible to do this + * using interrupts if you connect GPIO0 from the HamShield + * to your Arduino (code for that not provided). + * + * Setup: + * Connect the HamShield to your Arduino. Screw the antenna + * into the HamShield RF jack. Plug a pair of headphones into + * the HamShield. Connect the Arduino to wall power and then + * to your computer via USB. Set the CTCSS tone that you + * want to use in the setup() function below. + * After uploading this program to your Arduino, open the + * Serial Monitor. Press the button on the HamShield to begin + * setup. The sketch then works exactly like the HandyTalkie + * example, with the exception that only valid CTCSS coded + * receptions are put out to the headset. +*/ + +#include + +// create object for radio +HamShield radio; + +#define LED_PIN 13 +#define RSSI_REPORT_RATE_MS 5000 + +#define PWM_PIN 3 +#define RESET_PIN A3 +#define SWITCH_PIN 2 + +bool currently_tx; + +uint32_t freq; +float ctcss_tone; +bool muted; + +unsigned long rssi_timeout; + +void setup() { + // NOTE: if not using PWM out, it should be held low to avoid tx noise + pinMode(PWM_PIN, OUTPUT); + digitalWrite(PWM_PIN, LOW); + + // prep the switch + pinMode(SWITCH_PIN, INPUT_PULLUP); + + // set up the reset control pin + pinMode(RESET_PIN, OUTPUT); + digitalWrite(RESET_PIN, LOW); + + + // initialize serial communication + Serial.begin(9600); + Serial.println("press the switch to begin..."); + + while (digitalRead(SWITCH_PIN)); + + // let the AU ot of reset + digitalWrite(RESET_PIN, HIGH); + delay(5); // wait for device to come up + + Serial.println("beginning radio setup"); + + // verify connection + Serial.println("Testing device connections..."); + Serial.println(radio.testConnection() ? "RDA radio connection successful" : "RDA radio connection failed"); + + // initialize device + Serial.println("Initializing I2C devices..."); + radio.initialize(); // initializes automatically for UHF 12.5kHz channel + + Serial.println("setting default Radio configuration"); + radio.dangerMode(); + + // set frequency + Serial.println("changing frequency"); + + radio.setSQOff(); + freq = 446000; + radio.frequency(freq); + + // set to receive + + radio.setModeReceive(); + currently_tx = false; + Serial.print("config register is: "); + Serial.println(radio.readCtlReg()); + Serial.println(radio.readRSSI()); + + radio.setRfPower(0); + + // CTCSS Setup code + ctcss_tone = 103.5; + radio.setCtcss(ctcss_tone); + radio.enableCtcss(); + + // mute audio until we get a CTCSS tone + radio.setMute(); + muted = true; + + // configure Arduino LED for + pinMode(LED_PIN, OUTPUT); + rssi_timeout = 0; + +} + +void loop() { + // handle CTCSS tone detection + if (!currently_tx) { + // check for CTCSS tone + if (radio.getCtcssToneDetected()) { + if (muted) { + muted = false; + radio.setUnmute(); + Serial.println("tone"); + } + } else { + if (!muted) { + muted = true; + radio.setMute(); + Serial.println("no tone"); + } + } + } + + // handle manual transmit + if (!digitalRead(SWITCH_PIN)) + { + if (!currently_tx) + { + currently_tx = true; + + // set to transmit + radio.setModeTransmit(); + Serial.println("Tx"); + //radio.setTxSourceMic(); + //radio.setRfPower(1); + } + } else if (currently_tx) { + radio.setModeReceive(); + currently_tx = false; + Serial.println("Rx"); + } + + // handle serial commands + if (Serial.available()) { + if (Serial.peek() == 'r') { + Serial.read(); + digitalWrite(RESET_PIN, LOW); + delay(1000); + digitalWrite(RESET_PIN, HIGH); + radio.initialize(); // initializes automatically for UHF 12.5kHz channel + } else { + Serial.setTimeout(40); + freq = Serial.parseInt(); + Serial.flush(); + radio.frequency(freq); + Serial.print("set frequency: "); + Serial.println(freq); + } + } + + // periodically read RSSI and print to screen + if (!currently_tx && (millis() - rssi_timeout) > RSSI_REPORT_RATE_MS) + { + Serial.println(radio.readRSSI()); + rssi_timeout = millis(); + } +} diff --git a/src/HamShield.cpp b/src/HamShield.cpp index 9a2a500..7a73828 100644 --- a/src/HamShield.cpp +++ b/src/HamShield.cpp @@ -827,7 +827,10 @@ uint8_t HamShield::getCtcssDetThreshOut() { return (uint8_t) radio_i2c_buf[0]; } - +bool HamShield::getCtcssToneDetected() { + HSreadBitW(devAddr, A1846S_FLAG_REG, A1846S_CTCSS1_FLAG_BIT, radio_i2c_buf); + return (radio_i2c_buf[0] != 0); +} // cdcss codes void HamShield::setCdcssCode(uint16_t code) { @@ -1133,6 +1136,13 @@ uint16_t HamShield::getFMCssDeviation(){ } // RX voice range +void HamShield::setMute() { + HSwriteBitW(devAddr, A1846S_CTL_REG, A1846S_MUTE_BIT, 1); +} +void HamShield::setUnmute() { + HSwriteBitW(devAddr, A1846S_CTL_REG, A1846S_MUTE_BIT, 0); +} + void HamShield::setVolume1(uint16_t volume){ HSwriteBitsW(devAddr, A1846S_RX_VOLUME_REG, A1846S_RX_VOL_1_BIT, A1846S_RX_VOL_1_LENGTH, volume); } diff --git a/src/HamShield.h b/src/HamShield.h index dff7488..e5314ed 100644 --- a/src/HamShield.h +++ b/src/HamShield.h @@ -51,7 +51,6 @@ #define A1846S_SQ_OUT_SEL_REG 0x54 // see sq #define A1846S_FILTER_REG 0x58 #define A1846S_CTCSS_THRESH_REG 0x5B -#define A1846S_FLAG_REG 0x5C // holds flags for different statuses #define A1846S_RSSI_REG 0x1B // holds RSSI (unit 1dB) #define A1846S_VSSI_REG 0x1A // holds VSSI (unit mV) @@ -171,8 +170,8 @@ #define A1846S_CTCSS_FILTER_BYPASS 3 // Bitfields for A1846S_FLAG_REG -#define A1846S_RXON_RF_FLAG_BIT 10 // 1 when rxon is enabled -#define A1846S_TXON_RF_FLAG_BIT 9 // 1 when txon is enabled +#define A1846S_CTCSS1_FLAG_BIT 9 // 1 when rxon 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_CSS_CMP_FLAG_BIT 2 // ctcss/cdcss compared #define A1846S_SQ_FLAG_BIT 1 // sq final signal out from dsp @@ -310,6 +309,7 @@ class HamShield { uint8_t getCtcssDetThreshIn(); void setCtcssDetThreshOut(uint8_t thresh); uint8_t getCtcssDetThreshOut(); + bool getCtcssToneDetected(); // Ctcss_sel // 1 = ctcss_cmp/cdcss_cmp out via gpio @@ -413,6 +413,8 @@ class HamShield { uint16_t getFMCssDeviation(); // RX voice range + void setMute(); + void setUnmute(); void setVolume1(uint16_t volume); uint16_t getVolume1(); void setVolume2(uint16_t volume);