diff --git a/TeensyDSP/DSP.cpp b/TeensyDSP/DSP.cpp new file mode 100644 index 0000000..9d29f06 --- /dev/null +++ b/TeensyDSP/DSP.cpp @@ -0,0 +1,149 @@ +//====================================================================== +// DSP.cpp +//====================================================================== + +#include "DSP.h" + +#include +#include +//#include +//#include +//#include +//#include + +#define RX_AUDIO_CH 0 + +#define TX_MIC_IN_CH 0 +#define TX_LINE_IN_CH 0 +#define TX_USB_IN_CH1 1 +#define TX_USB_IN_CH2 2 + +UBitxDSP DSP; + +//static struct { + + // GUItool: begin automatically generated code + AudioInputI2S lineIn; //xy=137,220 + AudioInputUSB usbIn; //xy=142,326 + AudioMixer4 rxAudio; //xy=394,134 + AudioMixer4 txAudio; //xy=398,322 + AudioOutputAnalog spkrOut; //xy=774,104 + AudioOutputUSB usbOut; //xy=774,138 + AudioOutputI2S lineOut; //xy=776,236 + AudioConnection patchCord1(lineIn, 0, rxAudio, 0); + AudioConnection patchCord2(lineIn, 1, txAudio, 0); + AudioConnection patchCord3(usbIn, 0, txAudio, 1); + AudioConnection patchCord4(usbIn, 1, txAudio, 2); + AudioConnection patchCord5(rxAudio, spkrOut); + AudioConnection patchCord6(rxAudio, 0, lineOut, 0); + AudioConnection patchCord7(rxAudio, 0, usbOut, 0); + AudioConnection patchCord8(rxAudio, 0, usbOut, 1); + AudioConnection patchCord9(txAudio, 0, lineOut, 1); + AudioControlSGTL5000 audioCtrl; //xy=403,463 + // GUItool: end automatically generated code + +//} audio; + +void UBitxDSP::begin() { + AudioMemory(20); + audioCtrl.enable(); + audioCtrl.volume(0.0); // headphone volume... + audioCtrl.muteHeadphone(); // ...not used by UBitxDSP + + for (int i = 0; i < 4; i++) { + if (i == RX_AUDIO_CH) + rxAudio.gain(i, 1.0); + else + rxAudio.gain(i, 0.0); + } + + for (int i = 0; i < 4; i++) { + txAudio.gain(i, 0.0); + } + + // SETUP THE AUDIO INPUTS + + // Rig (Line) Input (RX) + audioCtrl.inputSelect(AUDIO_INPUT_LINEIN); + audioCtrl.unmuteLineout(); + audioCtrl.lineInLevel(5, 5); // RX, TX + audioCtrl.lineOutLevel(29, 29); //RX, TX + + // Mic Input (TX) + audioCtrl.micGain(0); // TODO: set value + + // Line Input (TX) + + // USB Input (TX) + + // SETUP THE AUDIO OUTPUTS + + // Speaker Output (RX) + spkrOut.analogReference(INTERNAL); + + // Line Output (RX) + + // USB Output (RX) + + // Rig (Line) Output (TX) + + // Default to RX. + rx(); +} + +void UBitxDSP::end() { +} + +void UBitxDSP::rx() { + // mute all tx audio + for (int i = 0; i < 4; i++) { + txAudio.gain(i, 0.0); + } + // select line in for rx + audioCtrl.inputSelect(AUDIO_INPUT_LINEIN); + // restore rx audio + rxAudio.gain(RX_AUDIO_CH, 1.0); // restore the RX audio +} + +void UBitxDSP::txMicIn() { + // mute the rx audio + rxAudio.gain(RX_AUDIO_CH, 0.0); + // restore the tx mic audio + audioCtrl.inputSelect(AUDIO_INPUT_MIC); + for (int i = 0; i < 4; i++) { + if (i == TX_MIC_IN_CH) + txAudio.gain(i, 1.0); + else + txAudio.gain(i, 0.0); + } +} + +void UBitxDSP::txLineIn() { + // mute the rx audio + rxAudio.gain(RX_AUDIO_CH, 0.0); + // restore the tx line in audio + audioCtrl.inputSelect(AUDIO_INPUT_LINEIN); + for (int i = 0; i < 4; i++) { + if (i == TX_LINE_IN_CH) + txAudio.gain(i, 1.0); + else + txAudio.gain(i, 0.0); + } +} + +void UBitxDSP::txUSBIn() { + // mute the rx audio + rxAudio.gain(RX_AUDIO_CH, 0.0); + // restore the tx usb in audio + audioCtrl.inputSelect(AUDIO_INPUT_LINEIN); + for (int i = 0; i < 4; i++) { + if (i == TX_USB_IN_CH1 || i == TX_USB_IN_CH2) + txAudio.gain(i, 1.0); + else + txAudio.gain(i, 0.0); + } +} + +//====================================================================== +// EOF +//====================================================================== diff --git a/TeensyDSP/DSP.h b/TeensyDSP/DSP.h new file mode 100644 index 0000000..c4e92da --- /dev/null +++ b/TeensyDSP/DSP.h @@ -0,0 +1,42 @@ +//====================================================================== +// DSP.h +//====================================================================== + +#ifndef __DSP_h__ +#define __DSP_h__ + +#include "Debug.h" + +enum TRState { + TRANSMIT, + RECEIVE +}; + +enum RxAudioIn { + RIG_AUDIO +}; + +enum TxAudioIn { + MIC_IN, + LINE_IN, + USB_IN +}; + +class UBitxDSP { + public: + UBitxDSP() {}; + void begin(); + void end(); + void rx(); + void txMicIn(); + void txLineIn(); + void txUSBIn(); +}; + +extern UBitxDSP DSP; + +#endif + +//====================================================================== +// EOF +//====================================================================== diff --git a/TeensyDSP/Debug.h b/TeensyDSP/Debug.h new file mode 100644 index 0000000..31a94c8 --- /dev/null +++ b/TeensyDSP/Debug.h @@ -0,0 +1,18 @@ +#ifndef __Debug_h__ +#define __Debug_h__ + +#define DEBUG + +#ifdef DEBUG +#define DBGPRINT(MSG) do { Serial.print("DBG: "); Serial.print(MSG); } while (0) +#define DBGPRINTLN(MSG) do { Serial.print("DBG: "); Serial.println(MSG); } while (0) +#define DBGNEWLINE() do { Serial.println(); } while (0) +#define DBGCMD(CMD) do { Serial.println("DBG: "); Serial.println(#CMD); CMD; } while (0) +#else +#define DBGPRINT(MSG) do {} while (0) +#define DBGPRINTLN(MSG) do {} while (0) +#define DBGNEWLINE() do {} while (0) +#define DBGCMD(CMD) do { CMD; } while (0) +#endif + +#endif diff --git a/TeensyDSP/HamFuncs.h b/TeensyDSP/HamFuncs.h new file mode 100644 index 0000000..05ca52f --- /dev/null +++ b/TeensyDSP/HamFuncs.h @@ -0,0 +1,186 @@ +#ifndef __HamFuncs_h__ +#define __HamFuncs_h__ + +/**********************************************************************/ + +#ifndef HF_PWR_DEFAULT_LOAD +#define HF_PWR_DEFAULT_LOAD 50.0 +#endif + +#ifndef HF_VSWR_MAX_REPORTED +#define HF_VSWR_MAX_REPORTED 9.9 +#endif + +#ifndef HF_BRIDGE_FWD_VRECT +#define HF_BRIDGE_FWD_VRECT 0.25 +#endif + +#ifndef HF_BRIDGE_FWD_TURNS +#define HF_BRIDGE_FWD_TURNS 10.0 +#endif + +#ifndef HF_BRIDGE_REV_VRECT +#define HF_BRIDGE_REV_VRECT 0.25 +#endif + +#ifndef HF_BRIDGE_REV_TURNS +#define HF_BRIDGE_REV_TURNS 10.0 +#endif + +#ifndef HF_ADC_DEFAULT_BITS +#define HF_ADC_DEFAULT_BITS 10 +#endif + +#ifndef HF_ADC_DEFAULT_VREF +#define HF_ADC_DEFAULT_VREF 3.3 +#endif + +/**********************************************************************/ + +namespace HF { + + const float pwrDefaultLoad = HF_PWR_DEFAULT_LOAD; + const float vswrMaxReported = HF_VSWR_MAX_REPORTED; + const float bridgeFwdVrect = HF_BRIDGE_FWD_VRECT; + const float bridgeFwdTurns = HF_BRIDGE_FWD_TURNS; + const float bridgeRevVrect = HF_BRIDGE_REV_VRECT; + const float bridgeRevTurns = HF_BRIDGE_REV_TURNS; + const unsigned adcDefaultBits = HF_ADC_DEFAULT_BITS; + const float adcDefaultVref = HF_ADC_DEFAULT_VREF; + + const float rms = sqrt(2.0) / 2.0; + + /********************************************************************/ + + /*! + * @brief Calculate the output voltage of a resistive divider + * network, given the input voltage and the values of the + * resistors. The input voltage is applied to R1, the output + * voltage is taken from the junction of R1 and R2, and R2 is + * connected to ground. + * @param Vin + * Input voltage. + * @param R1 + * Input resistor (ohms). Input voltage is measured between + * the top of this resistor and ground. + * @param R2 + * Output resistor (ohms). Output voltage is measured + * between the top of this resistor and ground. + * @return Output voltage. + */ + inline float divOut(float Vin, float R1, float R2) { + return Vin * R2 / (R1 + R2); + } + + /*! + * @brief Calculate the input voltage of a resistive divider + * network, given the output voltage and the values of the + * resistors. The input voltage is applied to R1, the output + * voltage is taken from the junction of R1 and R2, and R2 is + * connected to ground. + * @param Vout + * Output voltage. + * @param R1 + * Input resistor (ohms). Input voltage is measured between + * the top of this resistor and ground. + * @param R2 + * Output resistor (ohms). Output voltage is measured between + * the top of this resistor and ground. + * @return Input voltage. + */ + inline float divIn(float Vout, float R1, float R2) { + return Vout * (R1 + R2) / R2; + } + + /*! + * @brief Calculate and return the power in watts, given a + * resistance and the voltage across the resistance. + * @param V + * Voltage across the load. + * @param R + * (optional) Resistance of the load (ohms). If not provided, + * a default is used (HF_PWR_DEFAULT_LOAD). + * @return Power dissipated (watts). This is calculated as + * P = V^2/R. + */ + inline float P(float V, float R = pwrDefaultLoad) { + return (V * V) / R; + } + + /*! + * @brief Calculate and return the Voltage Standing Wave Ratio + * (VSWR) based on the given forward and reverse voltages. + * @param Vfwd + * Measured forward voltage. + * @param Vrev + * Measured reverse voltage. + * @param VSWRmax + * (optional) Maximum reported VSWR. The output will be + * clamped to this value if necessary (HF_VSWR_MAX_REPORTED). + * @return Voltage Standing Wave Ratio (VSWR). This is calculated + * as VSWR = (Vfwd + Vrev) / (Vfwd - Vrev). + */ + inline float VSWR(float Vfwd, float Vrev, float VSWRmax = vswrMaxReported) { + if (Vfwd - Vrev == 0.0) { + return VSWRmax; + } else { + float swr = (Vfwd + Vrev) / (Vfwd - Vrev); + return (swr > VSWRmax ? VSWRmax : swr); + } + } + + /*! + * @brief Calculate and return the forward RMS input voltage across + * a Stockton bridge. + * @param Vout + * Rectified output voltage (e.g. read via an ADC). + * @param Vrect + * (optional) Voltage drop across the rectifier diode. If + * not provided, a default is used (HF_BRIDGE_FWD_VRECT). + * @param turns + * (optional) Coupling transformer turns ratio. If not + * provided, a default is used (HF_BRIDGE_FWD_TURNS). + * @return Input voltage (i.e. the actual forward voltage). + */ + inline float bridgeFwd(float Vout, float Vrect = bridgeFwdVrect, float turns = bridgeFwdTurns) { + return (Vout + Vrect) * turns * rms; + } + + /*! + * @brief Calculate and return the reverse RMS input voltage across + * a Stockton bridge. + * @param Vout + * Rectified output voltage (e.g. read via an ADC). + * @param Vrect + * (optional) Voltage drop across the rectifier diode. If + * not provided, a default is used (HF_BRIDGE_REV_VRECT). + * @param turns + * (optional) Coupling transformer turns ratio. If not + * provided, a default is used (HF_BRIDGE_REV_TURNS). + * @return Input voltage (i.e. the actual reverse voltage). + */ + inline float bridgeRev(float Vout, float Vrect = bridgeRevVrect, float turns = bridgeRevTurns) { + return (Vout + Vrect) * turns * rms; + } + + /*! + * @brief Calculate and return the input voltage to an Analog-to- + * Digital Converter (ADC) given the resolution (number of + * bits) and the voltage reference of the ADC. + * @param counts + * Value of the ADC measurement (in unitless counts). + * @param res + * (optional) Resolution (in bits) of the ADC. If not + * provided, the default is used (HF_ADC_DEFAULT_BITS). + * @param Vref + * (optional) Voltage reference of the ADC. If not + * provided, the default is used (HF_ADC_DEFAULT_VREF). + * @return Input voltage to the ADC. + */ + inline float adcIn(unsigned counts, unsigned res = adcDefaultBits, float Vref = adcDefaultVref) { + return float(counts) * Vref / float(1 << res); + } + +}; + +#endif diff --git a/TeensyDSP/Nextion.cpp b/TeensyDSP/Nextion.cpp new file mode 100644 index 0000000..2c4d85e --- /dev/null +++ b/TeensyDSP/Nextion.cpp @@ -0,0 +1,141 @@ +#include "Nextion.h" + +char L_nowdisp = -1; //Sended nowdisp +char L_vfoActive; //vfoActive +unsigned long L_vfoCurr; //vfoA +byte L_vfoCurr_mode; //vfoA_mode +unsigned long L_vfoA; //vfoA +byte L_vfoA_mode; //vfoA_mode +unsigned long L_vfoB; //vfoB +byte L_vfoB_mode; //vfoB_mode +char L_ritOn; +unsigned long L_ritTxFrequency; //ritTxFrequency +char L_inTx; +byte L_isDialLock; //byte isDialLock +byte L_Split; //isTxType +byte L_TXStop; //isTxType +byte L_tuneStepIndex; //byte tuneStepIndex +byte L_scaledSMeter; //scaledSMeter +unsigned long L_sideTone; //sideTone +byte L_cwKeyType; //L_cwKeyType 0: straight, 1 : iambica, 2: iambicb +unsigned int L_cwSpeed; //cwSpeed +byte L_cwDelayTime; //cwDelayTime +byte L_delayBeforeCWStartTime; //byte delayBeforeCWStartTime +byte L_attLevel; +byte L_isIFShift; //1 = ifShift, 2 extend +int L_ifShiftValue; +byte L_sdrModeOn; +byte scaledSMeter = 0; +float calcVSWR = 0.0; +float L_calcVSWR = 0.0; +byte scaledVSWR = 0; +byte L_scaledVSWR = 0; +int fwdPower = 0; +int L_fwdPower = 0; +int revPower = 0; +int L_revPower = 0; + + +//Control must have prefix 'v' or 's' +char softSTRHeader[11] = {'p', 'm', '.', 's', '0', '.', 't', 'x', 't', '=', '\"'}; +char softINTHeader[10] = {'p', 'm', '.', 'v', '0', '.', 'v', 'a', 'l', '='}; + +char softTemp[20]; + +/*! + @brief Send a string or numeric variable to the Nextion LCD. + @param varType + The type of the variable being sent to the Nextion LCD. + @param varIndex + The index (ID) of the variable being sent to the Nextion LCD. + */ +void sendHeader(char varType, char varIndex) +{ + if (varType == SWS_HEADER_STR_TYPE) + { + softSTRHeader[4] = varIndex; + for (unsigned i = 0; i < sizeof(softSTRHeader)/sizeof(softSTRHeader[0]); i++) + Serial1.write(softSTRHeader[i]); + } + else + { + softINTHeader[4] = varIndex; + for (unsigned i = 0; i < sizeof(softINTHeader)/sizeof(softINTHeader[0]); i++) + Serial1.write(softINTHeader[i]); + } +} + +/*! + @brief Send an unsigned long variable to the Nextion LCD. + @param varIndex + The index (ID) of the variable being sent to the Nextion LCD. + @param sendValue + The value of the variable being sent to the Nextion LCD. + */ +void sendCommandUL(char varIndex, unsigned long sendValue) +{ + sendHeader(SWS_HEADER_INT_TYPE, varIndex); + + memset(softTemp, 0, 20); + ultoa(sendValue, softTemp, DEC); + Serial1.print(softTemp); + Serial1.write(0xff); + Serial1.write(0xff); + Serial1.write(0xff); +} + +/*! + @brief Send a (signed) long variable to the Nextion LCD. + @param varIndex + The index (ID) of the variable being sent to the Nextion LCD. + @param sendValue + The value of the variable being sent to the Nextion LCD. + */ +void sendCommandL(char varIndex, long sendValue) +{ + sendHeader(SWS_HEADER_INT_TYPE, varIndex); + + memset(softTemp, 0, 20); + ltoa(sendValue, softTemp, DEC); + Serial1.print(softTemp); + Serial1.write(0xff); + Serial1.write(0xff); + Serial1.write(0xff); +} + +/*! + @brief Send a string variable to the Nextion LCD. + @param varIndex + The index (ID) of the variable being sent to the Nextion LCD. + @param sendValue + The value of the variable being sent to the Nextion LCD. + */ +void sendCommandStr(char varIndex, const char* sendValue) +{ + sendHeader(SWS_HEADER_STR_TYPE, varIndex); + + Serial1.print(sendValue); + Serial1.write('\"'); + Serial1.write(0xFF); + Serial1.write(0xFF); + Serial1.write(0xFF); +} + +unsigned char softBuff1Num[14] = {'p', 'm', '.', 'c', '0', '.', 'v', 'a', 'l', '=', 0, 0xFF, 0xFF, 0xFF}; + +/*! + @brief Send a single digit variable to the Nextion LCD. + @param varIndex + The index (ID) of the variable being sent to the Nextion LCD. + Values 0~9 are: Mode, nowDisp, ActiveVFO, IsDialLock, IsTxtType, IsSplitType. + @param sendValue + The value of the variable being sent to the Nextion LCD. + */ +void sendCommand1Num(char varIndex, char sendValue) +{ + softBuff1Num[4] = varIndex; + softBuff1Num[10] = sendValue + 0x30; // convert to character digit + + for (unsigned i = 0; i < sizeof(softBuff1Num)/sizeof(softBuff1Num[0]); i++) + Serial1.write(softBuff1Num[i]); +} diff --git a/TeensyDSP/Nextion.h b/TeensyDSP/Nextion.h new file mode 100644 index 0000000..8d02d77 --- /dev/null +++ b/TeensyDSP/Nextion.h @@ -0,0 +1,126 @@ +#ifndef __Nextion_h__ +#define __Nextion_h__ + +#include +#include "Debug.h" + +#define SWS_HEADER_CHAR_TYPE 'c' //1Byte Protocol Prefix +#define SWS_HEADER_INT_TYPE 'v' //Numeric Protocol Prefex +#define SWS_HEADER_STR_TYPE 's' //for TEXT Line compatiable Character LCD Control + +//=================================================================== +//Begin of Nextion LCD Protocol +// +// v0~v9, va~vz : Numeric (Transceiver -> Nextion LCD) +// s0~s9 : String (Text) (Transceiver -> Nextion LCD) +// vlSendxxx, vloxxx: Reserve for Nextion (Nextion LCD -> Transceiver) +// +//=================================================================== + +#define CMD_NOW_DISP '0' //c0 +extern char L_nowdisp; //Sended nowdisp + +#define CMD_VFO_TYPE 'v' //cv +extern char L_vfoActive; //vfoActive + +#define CMD_CURR_FREQ 'c' //vc +extern unsigned long L_vfoCurr; //vfoA +#define CMD_CURR_MODE 'c' //cc +extern byte L_vfoCurr_mode; //vfoA_mode + +#define CMD_VFOA_FREQ 'a' //va +extern unsigned long L_vfoA; //vfoA +#define CMD_VFOA_MODE 'a' //ca +extern byte L_vfoA_mode; //vfoA_mode + +#define CMD_VFOB_FREQ 'b' //vb +extern unsigned long L_vfoB; //vfoB +#define CMD_VFOB_MODE 'b' //cb +extern byte L_vfoB_mode; //vfoB_mode + +#define CMD_IS_RIT 'r' //cr +extern char L_ritOn; +#define CMD_RIT_FREQ 'r' //vr +extern unsigned long L_ritTxFrequency; //ritTxFrequency + +#define CMD_IS_TX 't' //ct +extern char L_inTx; + +#define CMD_IS_DIALLOCK 'l' //cl +extern byte L_isDialLock; //byte isDialLock + +#define CMD_IS_SPLIT 's' //cs +extern byte L_Split; //isTxType +#define CMD_IS_TXSTOP 'x' //cx +extern byte L_TXStop; //isTxType + +#define CMD_TUNEINDEX 'n' //cn +extern byte L_tuneStepIndex; //byte tuneStepIndex + +#define CMD_SMETER 'p' //cs +extern byte L_scaledSMeter; //scaledSMeter + +#define CMD_SIDE_TONE 't' //vt +extern unsigned long L_sideTone; //sideTone +#define CMD_KEY_TYPE 'k' //ck +extern byte L_cwKeyType; //L_cwKeyType 0: straight, 1 : iambica, 2: iambicb + +#define CMD_CW_SPEED 's' //vs +extern unsigned int L_cwSpeed; //cwSpeed + +#define CMD_CW_DELAY 'y' //vy +extern byte L_cwDelayTime; //cwDelayTime + +#define CMD_CW_STARTDELAY 'e' //ve +extern byte L_delayBeforeCWStartTime; //byte delayBeforeCWStartTime + +#define CMD_ATT_LEVEL 'f' //vf +extern byte L_attLevel; + +extern byte L_isIFShift; //1 = ifShift, 2 extend +#define CMD_IS_IFSHIFT 'i' //ci + +extern int L_ifShiftValue; +#define CMD_IFSHIFT_VALUE 'i' //vi + +extern byte L_sdrModeOn; +#define CMD_SDR_MODE 'j' //cj + +#define CMD_UBITX_INFO 'm' //cm Complete Send uBITX Information + +//Once Send Data, When boot +//arTuneStep, When boot, once send +//long arTuneStep[5]; + +#define CMD_AR_TUNE1 '1' //v1 +#define CMD_AR_TUNE2 '2' //v2 +#define CMD_AR_TUNE3 '3' //v3 +#define CMD_AR_TUNE4 '4' //v4 +#define CMD_AR_TUNE5 '5' //v5 + +//int idleStep = 0; +extern byte scaledSMeter; + +extern float calcVSWR; +extern float L_calcVSWR; + +extern byte scaledVSWR; +extern byte L_scaledVSWR; + +extern int fwdPower; +extern int L_fwdPower; + +extern int revPower; +extern int L_revPower; + +void sendHeader(char varType, char varIndex); +void sendCommandUL(char varIndex, unsigned long sendValue); +void sendCommandL(char varIndex, long sendValue); +void sendCommandStr(char varIndex, const char* sendValue); +void sendCommand1Num(char varIndex, char sendValue); + +//======================================================= +//END OF Nextion Protocol +//======================================================= + +#endif diff --git a/TeensyDSP/Sensors.cpp b/TeensyDSP/Sensors.cpp new file mode 100644 index 0000000..7fa682c --- /dev/null +++ b/TeensyDSP/Sensors.cpp @@ -0,0 +1,5 @@ +#include "Sensors.h" + +UBitxSensors Sensors; + +ADC adc; diff --git a/TeensyDSP/Sensors.h b/TeensyDSP/Sensors.h new file mode 100644 index 0000000..4f0cd52 --- /dev/null +++ b/TeensyDSP/Sensors.h @@ -0,0 +1,342 @@ +#ifndef __Sensor_h__ +#define __Sensor_h__ + +#include +#include "Debug.h" +#include "HamFuncs.h" + +/**********************************************************************/ + +#ifndef UBITX_SENSORS_S_METER_PIN +#define UBITX_SENSORS_S_METER_PIN 27 +#endif + +#ifndef UBITX_SENSORS_FWD_PWR_PIN +#define UBITX_SENSORS_FWD_PWR_PIN 20 +#endif + +#ifndef UBITX_SENSORS_REV_PWR_PIN +#define UBITX_SENSORS_REV_PWR_PIN 28 +#endif + +#ifndef UBITX_SENSORS_SUPPLY_PIN +#define UBITX_SENSORS_SUPPLY_PIN 21 +#endif + +#ifndef UBITX_SENSORS_AVG_SAMPLES +#define UBITX_SENSORS_AVG_SAMPLES 16 +#endif + +#ifndef UBITX_SENSORS_S_METER_R1 +#define UBITX_SENSORS_S_METER_R1 22000.0 +#endif + +#ifndef UBITX_SENSORS_S_METER_R2 +#define UBITX_SENSORS_S_METER_R2 33000.0 +#endif + +#ifndef UBITX_SENSORS_FWD_PWR_R1 +#define UBITX_SENSORS_FWD_PWR_R1 22000.0 +#endif + +#ifndef UBITX_SENSORS_FWD_PWR_R2 +#define UBITX_SENSORS_FWD_PWR_R2 33000.0 +#endif + +#ifndef UBITX_SENSORS_REV_PWR_R1 +#define UBITX_SENSORS_REV_PWR_R1 22000.0 +#endif + +#ifndef UBITX_SENSORS_REV_PWR_R2 +#define UBITX_SENSORS_REV_PWR_R2 33000.0 +#endif + +#ifndef UBITX_SENSORS_SUPPLY_R1 +#define UBITX_SENSORS_SUPPLY_R1 56000.0 +#endif + +#ifndef UBITX_SENSORS_SUPPLY_R2 +#define UBITX_SENSORS_SUPPLY_R2 10000.0 +#endif + +#ifndef UBITX_SENSORS_S_METER_LVL0 +#define UBITX_SENSORS_S_METER_LVL0 2 +#endif + +#ifndef UBITX_SENSORS_S_METER_LVL1 +#define UBITX_SENSORS_S_METER_LVL1 4 +#endif + +#ifndef UBITX_SENSORS_S_METER_LVL2 +#define UBITX_SENSORS_S_METER_LVL2 8 +#endif + +#ifndef UBITX_SENSORS_S_METER_LVL3 +#define UBITX_SENSORS_S_METER_LVL3 16 +#endif + +#ifndef UBITX_SENSORS_S_METER_LVL4 +#define UBITX_SENSORS_S_METER_LVL4 32 +#endif + +#ifndef UBITX_SENSORS_S_METER_LVL5 +#define UBITX_SENSORS_S_METER_LVL5 64 +#endif + +#ifndef UBITX_SENSORS_S_METER_LVL6 +#define UBITX_SENSORS_S_METER_LVL6 128 +#endif + +#ifndef UBITX_SENSORS_S_METER_LVL7 +#define UBITX_SENSORS_S_METER_LVL7 256 +#endif + +#ifndef UBITX_SENSORS_S_METER_LVL8 +#define UBITX_SENSORS_S_METER_LVL8 512 +#endif + +/**********************************************************************/ + +const int uBitxSensorsSMeterPin = UBITX_SENSORS_S_METER_PIN; +const int uBitxSensorsFwdPwrPin = UBITX_SENSORS_FWD_PWR_PIN; +const int uBitxSensorsRevPwrPin = UBITX_SENSORS_REV_PWR_PIN; +const int uBitxSensorsSupplyPin = UBITX_SENSORS_SUPPLY_PIN; +const int uBitxSensorsAvgSamples = UBITX_SENSORS_AVG_SAMPLES; +const float uBitxSensorsSMeterR1 = UBITX_SENSORS_S_METER_R1; +const float uBitxSensorsSMeterR2 = UBITX_SENSORS_S_METER_R2; +const float uBitxSensorsFwdPwrR1 = UBITX_SENSORS_FWD_PWR_R1; +const float uBitxSensorsFwdPwrR2 = UBITX_SENSORS_FWD_PWR_R2; +const float uBitxSensorsRevPwrR1 = UBITX_SENSORS_REV_PWR_R1; +const float uBitxSensorsRevPwrR2 = UBITX_SENSORS_REV_PWR_R2; +const float uBitxSensorsSupplyR1 = UBITX_SENSORS_SUPPLY_R1; +const float uBitxSensorsSupplyR2 = UBITX_SENSORS_SUPPLY_R2; + +const int uBitxSensorsSMeterValues[] = { + UBITX_SENSORS_S_METER_LVL0, + UBITX_SENSORS_S_METER_LVL1, + UBITX_SENSORS_S_METER_LVL2, + UBITX_SENSORS_S_METER_LVL3, + UBITX_SENSORS_S_METER_LVL4, + UBITX_SENSORS_S_METER_LVL5, + UBITX_SENSORS_S_METER_LVL6, + UBITX_SENSORS_S_METER_LVL7, + UBITX_SENSORS_S_METER_LVL8 +}; + +const int uBitxSensorsSMeterLevels = sizeof(uBitxSensorsSMeterValues) / + sizeof(uBitxSensorsSMeterValues[0]); + +extern ADC adc; + +/**********************************************************************/ + +/*! + * @brief Class that maintains a "trailing average" of the last X + * samples provided. It is a template that can be instantiated + * with both the (numeric) data type that is being stored and + * averaged, as well as the number of samples to maintain the + * trailing average across. + */ +template +class TrailingAverage { + public: + /*! + * @brief Create a new TrailingAverage object. Data type averaged, + * and number of elements to average, are determined when the + * template is instantiated. + */ + TrailingAverage(): + average(T(0)), + current(0), + divisor(T(N)) + { + for (int i = 0; i < N; i++) { + data[i] = T(0); + } + } + + /*! + * @brief Add a new element to the average. The current last (Nth) + * element is removed, and the new element is added. + * @param val + * The new element/value to incorporate into the average. + */ + inline void add(T val) { + int last = (current - 1) % N; + average -= data[last]; + current = (current + 1) % N; + average += data[current] / divisor; + } + + /*! + * @brief Read the current value of the average. + * @return The current average. + */ + inline T read() { + return average; + } + + private: + T data[N]; + T average; + int current; + T divisor; +}; + +/**********************************************************************/ + +/*! + * @brief Class that handles the various sensors in the uBitx: + * S-Meter, forward/reverse power and SWR, and supply voltage. + */ +class UBitxSensors { + public: + /*! + * @brief Create a new UBitxSensors object. It uses the default + * S-Meter, Forward Power, Reverse Power, and Supply Voltage + * ADC pins. + */ + UBitxSensors(): + sMeterPin(uBitxSensorsSMeterPin), + fwdPwrPin(uBitxSensorsFwdPwrPin), + revPwrPin(uBitxSensorsRevPwrPin), + supplyPin(uBitxSensorsSupplyPin) + { + pinMode(sMeterPin, INPUT); // analog + pinMode(fwdPwrPin, INPUT); // analog + pinMode(revPwrPin, INPUT); // analog + pinMode(supplyPin, INPUT); // analog + } + + /*! + * @brief Update the value of the S-Meter by reading the associated + * ADC pin. + */ + inline void updateSMeter() { + int value = adc.analogRead(sMeterPin); + sMeter.add(value); + } + + /*! + * @brief Update the value of the Forward and Reverse Power + * measurements by reading the associated ADC pin. + */ + void updatePower() { + ADC::Sync_result value = adc.analogSyncRead(fwdPwrPin, revPwrPin); + + float fwdV = HF::adcIn(value.result_adc0); + float revV = HF::adcIn(value.result_adc1); + + fwdV = HF::divIn(fwdV, uBitxSensorsFwdPwrR1, uBitxSensorsFwdPwrR2); + fwdV = HF::bridgeFwd(fwdV); + + revV = HF::divIn(revV, uBitxSensorsRevPwrR1, uBitxSensorsRevPwrR2); + revV = HF::bridgeFwd(revV); + + fwdPwr.add(HF::P(fwdV)); + revPwr.add(HF::P(revV)); + vswr.add(HF::VSWR(fwdV, revV)); + } + + /*! + * @brief Update the value of the Supply Voltage measurement by + * reading the associated ADC pin. + */ + inline void updateSupply() { + float value = HF::adcIn(adc.analogRead(supplyPin)); + value = HF::divIn(value, uBitxSensorsSupplyR1, uBitxSensorsSupplyR2); + supply.add(value); + } + + /*! + * @brief Return the unscaled value of the S-Meter reading. + * @return Unscaled S-Meter reading. + */ + inline int sMeterUnscaled() { + return sMeter.read(); + } + + /*! + * @brief Return the scaled value of the S-Meter reading. This + * is the value that is used to directly control the S-Meter + * display on the Nextion LCD. + * @return Scaled S-Meter reading. + */ + int sMeterScaled() { + float sig = sMeter.read(); + // small number of elements; just doing a linear search + for (int i = uBitxSensorsSMeterLevels; i > 0; i--) { + if (sig > uBitxSensorsSMeterValues[i - 1]) { + return i; + } + } + return 0; + } + + /*! + * @brief Return the current Forward Power measurement. + * @return Forward Power measurement. + */ + inline float Pfwd() { + return fwdPwr.read(); + } + + /*! + * @brief Return the current Reverse Power measurement. + * @return Reverse Power measurement. + */ + inline float Prev() { + return revPwr.read(); + } + + /*! + * @brief Return the current Voltage Standing Wave Ration (VSWR). + * @return Current VSWR calculation. + */ + inline float VSWR() { + return vswr.read(); + } + + /*! + * @brief Return the current Voltage Standing Wave Ration (VSWR), + * scaled for the Nextion display protocol. + * @return Current VSWR calculation (scaled). + */ + float scaledVSWR() { + int val = int(vswr.read()); + if (val < 0) { + return 0; + } else if (val > uBitxSensorsSMeterLevels) { + return uBitxSensorsSMeterLevels; + } else { + return val; + } + } + + /*! + * @brief Return the current Supply Voltage measurement. + * @return Current Supply Voltage. + */ + inline float supplyVoltage() { + return supply.read(); + } + + private: + + // Pins + int sMeterPin; + int fwdPwrPin; + int revPwrPin; + int supplyPin; + + // Buffers for averages + TrailingAverage sMeter; + TrailingAverage fwdPwr; + TrailingAverage revPwr; + TrailingAverage vswr; + TrailingAverage supply; +}; + +extern UBitxSensors Sensors; + +#endif diff --git a/TeensyDSP/TR.cpp b/TeensyDSP/TR.cpp new file mode 100644 index 0000000..5ed1e1c --- /dev/null +++ b/TeensyDSP/TR.cpp @@ -0,0 +1,45 @@ +//====================================================================== +// TR.cpp +//====================================================================== + +#include +#include "TR.h" + +UBitxTR TR(DSP); + +void UBitxTR::update(bool cw) { + updatePTT(); + updateVOX(); + updateKey(); + + if (isTX) { + // If we are currently transmitting, then ANY T/R release (key + // release) will result in exitting transmit... except for VOX + // and CAT which can only function as a release if it was enabled. + if (pttReleased() || keyReleased() || + (voxEnabled && voxDeactivated()) || + (catEnabled && catDeactivated())) { + // first, stop transmitting; then, setup RX audio + DBGCMD( setRX() ); + DBGCMD( dsp.rx() ); + } + } else { + if ((pttEnabled && pttPressed()) || (voxEnabled && voxActivated())) { + // first, setup TX audio; then, start transmitting (from Mic) + DBGCMD( dsp.txMicIn() ); + DBGCMD( setTX() ); + } else if (keyEnabled && keyPressed()) { + // first, setup TX audio; then, start transmitting (from Line In) + DBGCMD( dsp.txLineIn() ); + DBGCMD( setTX() ); + } else if (catEnabled && catActivated()) { + // first, setup TX audio; then, start transmitting (USB) + DBGCMD( dsp.txUSBIn() ); + DBGCMD( setTX() ); + } + } +} + +//====================================================================== +// EOF +//====================================================================== diff --git a/TeensyDSP/TR.h b/TeensyDSP/TR.h new file mode 100644 index 0000000..6b4345f --- /dev/null +++ b/TeensyDSP/TR.h @@ -0,0 +1,169 @@ +//====================================================================== +// TR.h +//====================================================================== + +#ifndef __TR_h__ +#define __TR_h__ + +#include +#include "Debug.h" +#include "DSP.h" + +#define UBITX_TR_OUT_PIN 2 +#define UBITX_TR_PTT_PIN 3 +#define UBITX_TR_VOX_PIN 4 +#define UBITX_TR_KEY_PIN 5 + +const int uBitxTROutPin = UBITX_TR_OUT_PIN; +const int uBitxTRPttPin = UBITX_TR_PTT_PIN; +const int uBitxTRVoxPin = UBITX_TR_VOX_PIN; +const int uBitxTRKeyPin = UBITX_TR_KEY_PIN; + +class UBitxTR { + public: + UBitxTR(UBitxDSP& d, int out = uBitxTROutPin, int p = uBitxTRPttPin, int v = uBitxTRVoxPin, int k = uBitxTRKeyPin): + dsp(d), outPin(out), pttPin(p), voxPin(v), keyPin(k) {} + + void begin() { + pinMode(outPin, OUTPUT); + pinMode(voxPin, INPUT_PULLUP); + pinMode(keyPin, INPUT_PULLUP); + ptt.attach(pttPin, INPUT_PULLUP); + ptt.interval(5); + + // default configuration: PTT, key, and CAT enabled; VOX disabled + DBGCMD( enablePTT() ); + DBGCMD( disableVOX() ); + DBGCMD( enableKey() ); + DBGCMD( enableCAT() ); + } + + inline void enablePTT() { pttEnabled = true; } + inline void enableVOX() { voxEnabled = true; } + inline void enableKey() { keyEnabled = true; } + inline void enableCAT() { catEnabled = true; } + inline void disablePTT() { pttEnabled = false; } + inline void disableVOX() { voxEnabled = false; } + inline void disableKey() { keyEnabled = false; } + inline void disableCAT() { catEnabled = false; } + + + inline void catTX() { + L_catActive = catActive; + catActive = true; + } + + inline void catRX() { + L_catActive = catActive; + catActive = false; + } + +//====================================================================== + + inline bool transmitting() { return isTX; } + inline bool receiving() { return !isTX; } + + /*! + * @brief Check if any of the PTT's have been pressed or released + * since the last update. Only one thing is allowed to occur + * based on an order of precedence. The highest priority is + * to stop transmitting. + * + * @param cw + * True if CW mode is currently active; false otherwise. + * Different/faster logic is used in CW mode. + */ + void update(bool cw = false); + + void end() { + } + + private: + + inline void setTX() { + digitalWrite(outPin, LOW); + isTX = true; + } + + inline void setRX() { + isTX = false; + digitalWrite(outPin, HIGH); + } + + inline void updatePTT() { + ptt.update(); + } + + inline bool pttPressed() { + return ptt.fell(); + } + + inline bool pttReleased() { + return ptt.rose(); + } + + inline void updateVOX() { + L_voxActive = voxActive; + voxActive = (digitalRead(voxPin) == LOW); + } + + inline bool voxActivated() { + return (L_voxActive != voxActive) && L_voxActive; + } + + inline bool voxDeactivated() { + return (L_voxActive != voxActive) && voxActive; + } + + inline void updateKey() { + L_keyDown = keyDown; + keyDown = (digitalRead(keyPin) == LOW); + } + + inline bool keyPressed() { + return (L_keyDown != keyDown) && L_keyDown; + } + + inline bool keyReleased() { + return (L_keyDown != keyDown) && keyDown; + } + + inline bool catActivated() { + return (L_catActive != catActive) && L_catActive; + } + + inline bool catDeactivated() { + return (L_catActive != catActive) && catActive; + } + + UBitxDSP& dsp; + + Bounce ptt; + + int outPin; + int pttPin; + int voxPin; + int keyPin; + + bool isTX = false; + + bool pttEnabled = false; + bool voxEnabled = false; + bool keyEnabled = false; + bool catEnabled = false; + + bool voxActive = false; + bool L_voxActive = false; + bool keyDown = false; + bool L_keyDown = false; + bool catActive = false; + bool L_catActive = false; +}; + +extern UBitxTR TR; + +#endif + +//====================================================================== +// EOF +//====================================================================== diff --git a/TeensyDSP/TeensyDSP.h b/TeensyDSP/TeensyDSP.h index c64d26c..744a39d 100644 --- a/TeensyDSP/TeensyDSP.h +++ b/TeensyDSP/TeensyDSP.h @@ -7,30 +7,23 @@ KD8CEC, Ian Lee **********************************************************************/ -#include +#include +#include "Debug.h" +#include "DSP.h" +#include "Nextion.h" +#include "Sensors.h" +#include "TR.h" //================================================================ //COMMUNICATION SECTION //================================================================ -#define USE_SW_SERIAL - -extern void SWSerial_Write(uint8_t b); -extern void SWSerial_Print(uint8_t *b); - -#ifdef USE_SW_SERIAL - extern void SWSerial_Begin(long speedBaud); - extern int SWSerial_Available(void); - extern int SWSerial_Read(void); -#else - -#define PRINT_MAX_LENGTH 30 -#endif //================================================================ -//FFT and Decode Morse +// FFT and Decode Morse //================================================================ + #define FFTSIZE 64 -#define SAMPLE_PREQUENCY 6000 +#define SAMPLE_FREQUENCY 6000 #define SAMPLESIZE (FFTSIZE * 2) #define DECODE_MORSE_SAMPLESIZE 48 @@ -38,8 +31,9 @@ extern uint8_t cwDecodeHz; extern int magnitudelimit_low; //================================================================ -//EEPROM Section +// EEPROM Section //================================================================ + #define MAX_FORWARD_BUFF_LENGTH 128 #define EEPROM_DSPTYPE 100 #define EEPROM_SMETER_UART 111 @@ -52,8 +46,9 @@ extern int magnitudelimit_low; #define EEPROM_RTTYDECODEHZ 130 //================================================================ -//DEFINE for I2C Command +// DEFINE for I2C Command //================================================================ + //S-Meter Address #define I2CMETER_ADDR 0x58 //changed from 0x6A //VALUE TYPE============================================ @@ -68,9 +63,3 @@ extern int magnitudelimit_low; //SWR #define I2CMETER_CALCR 0x55 //Calculated SWR Meter #define I2CMETER_UNCALCR 0x54 //Uncalculated SWR Meter - -#define SIGNAL_METER_ADC A7 -#define POWER_METER_ADC A3 -#define SWR_METER_ADC A2 - - diff --git a/TeensyDSP/TeensyDSP.ino b/TeensyDSP/TeensyDSP.ino index ee00a25..31c5f68 100644 --- a/TeensyDSP/TeensyDSP.ino +++ b/TeensyDSP/TeensyDSP.ino @@ -1,203 +1,30 @@ /* -FFT, CW Decode for uBITX -KD8CEC, Ian Lee + FFT, CW Decode for uBITX + KD8CEC, Ian Lee -Version : 0.8 ------------------------------------------------------------------------ -License : See fftfunctions.cpp for FFT and CW Decode. + Version : 0.8 + ----------------------------------------------------------------------- + License : See fftfunctions.cpp for FFT and CW Decode. **********************************************************************/ -#include +#include +#include // using i2c_t3 library for multiple I2C busses #include #include "TeensyDSP.h" -#define SWS_HEADER_CHAR_TYPE 'c' //1Byte Protocol Prefix -#define SWS_HEADER_INT_TYPE 'v' //Numeric Protocol Prefex -#define SWS_HEADER_STR_TYPE 's' //for TEXT Line compatiable Character LCD Control +//const uint8_t responseHeader[11]={'p', 'm', '.', 's', 'p', '.', 't', 'x', 't', '=', '"'}; //for Spectrum from DSP +//const uint8_t responseFooter[4]={'"', 0xFF, 0xFF, 0xFF}; +//const char hexCodes[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', }; -//Control must have prefix 'v' or 's' -char softSTRHeader[11] = {'p', 'm', '.', 's', '0', '.', 't', 'x', 't', '=', '\"'}; -char softINTHeader[10] = {'p', 'm', '.', 'v', '0', '.', 'v', 'a', 'l', '='}; - -char softTemp[20]; - -const uint8_t ResponseHeader[11]={'p', 'm', '.', 's', 'p', '.', 't', 'x', 't', '=', '"'}; //for Spectrum from DSP -const uint8_t ResponseFooter[4]={'"', 0xFF, 0xFF, 0xFF}; -const char HexCodes[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', }; - -void FFT(double *x,double *y, int n, long m); - -double FFTReal[SAMPLESIZE]; -double FFTImag[SAMPLESIZE]; -int ADC_MAX = 0; -int ADC_MIN = 0; -int ADC_DIFF = 0; unsigned long SAMPLE_INTERVAL = 0; -char nowADCSampling = 0; //prevent for loss signal +int i2cCommand = 0; +//void calculateCoeff(uint8_t freqIndex); +uint8_t cwDecodeHz = 9; +int magnitudelimit_low = 30; -//=================================================================== -//Begin of Nextion LCD Protocol -// -// v0~v9, va~vz : Numeric (Transceiver -> Nextion LCD) -// s0~s9 : String (Text) (Transceiver -> Nextion LCD) -// vlSendxxx, vloxxx: Reserve for Nextion (Nextion LCD -> Transceiver) -// -//=================================================================== -#define CMD_NOW_DISP '0' //c0 -char L_nowdisp = -1; //Sended nowdisp - -#define CMD_VFO_TYPE 'v' //cv -char L_vfoActive; //vfoActive - -#define CMD_CURR_FREQ 'c' //vc -unsigned long L_vfoCurr; //vfoA -#define CMD_CURR_MODE 'c' //cc -byte L_vfoCurr_mode; //vfoA_mode - -#define CMD_VFOA_FREQ 'a' //va -unsigned long L_vfoA; //vfoA -#define CMD_VFOA_MODE 'a' //ca -byte L_vfoA_mode; //vfoA_mode - -#define CMD_VFOB_FREQ 'b' //vb -unsigned long L_vfoB; //vfoB -#define CMD_VFOB_MODE 'b' //cb -byte L_vfoB_mode; //vfoB_mode - -#define CMD_IS_RIT 'r' //cr -char L_ritOn; -#define CMD_RIT_FREQ 'r' //vr -unsigned long L_ritTxFrequency; //ritTxFrequency - -#define CMD_IS_TX 't' //ct -char L_inTx; - -#define CMD_IS_DIALLOCK 'l' //cl -byte L_isDialLock; //byte isDialLock - -#define CMD_IS_SPLIT 's' //cs -byte L_Split; //isTxType -#define CMD_IS_TXSTOP 'x' //cx -byte L_TXStop; //isTxType - -#define CMD_TUNEINDEX 'n' //cn -byte L_tuneStepIndex; //byte tuneStepIndex - -#define CMD_SMETER 'p' //cs -byte L_scaledSMeter; //scaledSMeter - -#define CMD_SIDE_TONE 't' //vt -unsigned long L_sideTone; //sideTone -#define CMD_KEY_TYPE 'k' //ck -byte L_cwKeyType; //L_cwKeyType 0: straight, 1 : iambica, 2: iambicb - -#define CMD_CW_SPEED 's' //vs -unsigned int L_cwSpeed; //cwSpeed - -#define CMD_CW_DELAY 'y' //vy -byte L_cwDelayTime; //cwDelayTime - -#define CMD_CW_STARTDELAY 'e' //ve -byte L_delayBeforeCWStartTime; //byte delayBeforeCWStartTime - -#define CMD_ATT_LEVEL 'f' //vf -byte L_attLevel; - -byte L_isIFShift; //1 = ifShift, 2 extend -#define CMD_IS_IFSHIFT 'i' //ci - -int L_ifShiftValue; -#define CMD_IFSHIFT_VALUE 'i' //vi - -byte L_sdrModeOn; -#define CMD_SDR_MODE 'j' //cj - -#define CMD_UBITX_INFO 'm' //cm Complete Send uBITX Information - -//Once Send Data, When boot -//arTuneStep, When boot, once send -//long arTuneStep[5]; -#define CMD_AR_TUNE1 '1' //v1 -#define CMD_AR_TUNE2 '2' //v2 -#define CMD_AR_TUNE3 '3' //v3 -#define CMD_AR_TUNE4 '4' //v4 -#define CMD_AR_TUNE5 '5' //v5 - -//int idleStep = 0; -byte scaledSMeter = 0; - -//send data for Nextion LCD -void SendHeader(char varType, char varIndex) -{ - if (varType == SWS_HEADER_STR_TYPE) - { - softSTRHeader[4] = varIndex; - for (int i = 0; i < 11; i++) - SWSerial_Write(softSTRHeader[i]); - } - else - { - softINTHeader[4] = varIndex; - for (int i = 0; i < 10; i++) - SWSerial_Write(softINTHeader[i]); - } -} - -void SendCommandUL(char varIndex, unsigned long sendValue) -{ - SendHeader(SWS_HEADER_INT_TYPE, varIndex); - - memset(softTemp, 0, 20); - ultoa(sendValue, softTemp, DEC); - SWSerial_Print(softTemp); - SWSerial_Write(0xff); - SWSerial_Write(0xff); - SWSerial_Write(0xff); -} - -void SendCommandL(char varIndex, long sendValue) -{ - SendHeader(SWS_HEADER_INT_TYPE, varIndex); - - memset(softTemp, 0, 20); - ltoa(sendValue, softTemp, DEC); - SWSerial_Print(softTemp); - SWSerial_Write(0xff); - SWSerial_Write(0xff); - SWSerial_Write(0xff); -} - -void SendCommandStr(char varIndex, char* sendValue) -{ - SendHeader(SWS_HEADER_STR_TYPE, varIndex); - - SWSerial_Print(sendValue); - SWSerial_Write('\"'); - SWSerial_Write(0xFF); - SWSerial_Write(0xFF); - SWSerial_Write(0xFF); -} - -unsigned char softBuff1Num[14] = {'p', 'm', '.', 'c', '0', '.', 'v', 'a', 'l', '=', 0, 0xFF, 0xFF, 0xFF}; -void SendCommand1Num(char varType, char sendValue) //0~9 : Mode, nowDisp, ActiveVFO, IsDialLock, IsTxtType, IsSplitType -{ - softBuff1Num[4] = varType; - softBuff1Num[10] = sendValue + 0x30; - - for (int i = 0; i < 14; i++) - SWSerial_Write(softBuff1Num[i]); -} - -//======================================================= -//END OF Nextion Protocol -//======================================================= - -int I2CCommand = 0; -void CalculateCoeff(uint8_t freqIndex); - -char ForwardBuff[MAX_FORWARD_BUFF_LENGTH + 1]; -static char nowBuffIndex = 0; +char forwardBuff[MAX_FORWARD_BUFF_LENGTH + 1]; +static int nowBuffIndex = 0; static char etxCount = 0; static char nowSendingProtocol = 0; @@ -209,10 +36,13 @@ char DSPType = 1; //0 : Not Use, 1 : FFT, 2 : Morse Decoder, 3 : RTTY Decoder char FFTToUartIdleCount = 0; #define FFTToUartInterval 2 -unsigned long lastForwardmili = 0; +elapsedMillis sinceForward = 0; uint8_t responseCommand = 0; // -uint8_t TXStatus = 0; //0:RX, 1:TX -void ResponseConfig() +bool isTX = false; + +/**********************************************************************/ + +void responseConfig() { if (responseCommand == 2) { @@ -229,7 +59,7 @@ void ResponseConfig() { returnValue = 100 + cwDecodeHz; } - + returnValue = returnValue << 8; returnValue = returnValue | (SMeterToUartSend & 0xFF); returnValue = returnValue << 8; @@ -238,24 +68,28 @@ void ResponseConfig() tmpValue = 255; else if (magnitudelimit_low < 1) tmpValue = 0; - else + else tmpValue = magnitudelimit_low; returnValue = returnValue | (tmpValue & 0xFF); - - SendCommandUL('v', returnValue); //Return data - SendCommandUL('g', 0x6A); //Return data + + sendCommandUL('v', returnValue); //Return data + sendCommandUL('g', 0x6A); //Return data } responseCommand = 0; } //Result : if found .val=, 1 else 0 -char CommandPasrser(int lastIndex) +/*! + @brief Parse commands... +*/ + +char commandParser(int lastIndex) { - //Analysing Forwrd data - //59 58 68 4A 1C 5F 6A E5 FF FF 73 + //Analysing Forward data + //59 58 68 4A 1C 5F 6A E5 FF FF 73 //Find Loopback protocol // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 - //70 6D 2E 76 76 2E 76 61 6C 3D 33 38 34 38 39 35 33 36 32 38 FF FF FF + //70 6D 2E 76 76 2E 76 61 6C 3D 33 38 34 38 39 35 33 36 32 38 FF FF FF //pm.vv.val=3848953628\xFF\xFF\xFF //1234567890XXX // @@ -280,82 +114,27 @@ char CommandPasrser(int lastIndex) for (int i = lastIndex - 3; i >= startIndex + 7; i--) { //Find = - if (ForwardBuff[i-3] == 'v' && ForwardBuff[i-2] == 'a' && ForwardBuff[i-1] == 'l' && ForwardBuff[i] == '=') //0x3D + if (forwardBuff[i - 3] == 'v' && forwardBuff[i - 2] == 'a' && forwardBuff[i - 1] == 'l' && forwardBuff[i] == '=') //0x3D { - uint8_t command1 = ForwardBuff[i-6]; //v - uint8_t command2 = ForwardBuff[i-5]; //v - // i-4 //. - ForwardBuff[lastIndex - 2] = 0; - long commandVal=atol(&ForwardBuff[i + 1]); - uint8_t *ReadBuff = (uint8_t *)&commandVal; - + uint8_t command1 = forwardBuff[i - 6]; //v + uint8_t command2 = forwardBuff[i - 5]; //v + // i-4 //. + forwardBuff[lastIndex - 2] = 0; + long commandVal = atol(&forwardBuff[i + 1]); + uint8_t *readBuff = (uint8_t *)&commandVal; + //Loop Back if (command1 == 'v' && command2 == 'v') { - //=========================================================== - //Test Code 1 - /* - long tmpVal = 0; - Serial.print("Found :"); - for (int k = i + 1; k <= lastIndex - 3; k++) - { - Serial.write(ForwardBuff[k]); - } - Serial.println(); - Serial.print("Reverse :"); - for (int k = lastIndex - 3; k >= i + 1; k--) - { - Serial.write(ForwardBuff[k]); - } - Serial.println(); - - ForwardBuff[lastIndex - 2] = 0; - - tmpVal=atol(&ForwardBuff[i + 1]); - Serial.println(tmpVal); - - uint8_t *ReadBuff = (uint8_t *)&tmpVal; - char buff[10]; - sprintf(buff, "%x,%x,%x,%x", ReadBuff[0], ReadBuff[1], ReadBuff[2], ReadBuff[3]); - Serial.println(buff); - - int calcChecksumA = ReadBuff[0] + ReadBuff[1] + ReadBuff[2]; - calcChecksumA = calcChecksumA % 256; - - if (calcChecksumA == ReadBuff[3]) - { - Serial.print("Correct Checksum : "); - Serial.print(ReadBuff[3]); - Serial.print(":"); - Serial.println(calcChecksumA); - } - //End of Test Code - */ - - /* - //Test Code 2 - Serial.print("Found :"); - Serial.print(startIndex); - Serial.print(","); - Serial.print(lastIndex); - Serial.print(":"); - for (int k = i + 1; k <= lastIndex - 3; k++) - { - Serial.write(ForwardBuff[k]); - } - Serial.println(""); - //End of Tet Code 2 - */ - - int calcChecksum = ReadBuff[0] + ReadBuff[1] + ReadBuff[2]; + int calcChecksum = readBuff[0] + readBuff[1] + readBuff[2]; calcChecksum = calcChecksum % 256; //Correct Checksum and Receiver is DSP Moudle protocol v1.0 - if (calcChecksum == ReadBuff[3] && ReadBuff[2] == 0x6A) + if (calcChecksum == readBuff[3] && readBuff[2] == 0x6A) { - //Serial.print("Correct Checksum Command : "); - //Serial.println(ReadBuff[1]); - uint8_t cmd1 = ReadBuff[1]; + //Serial1.print("Correct Checksum Command : "); + //Serial1.println(readBuff[1]); + uint8_t cmd1 = readBuff[1]; if (cmd1 == 94) { DSPType = 0; @@ -363,14 +142,14 @@ char CommandPasrser(int lastIndex) } else if (cmd1 == 95) { - //Serial.println("Spectrum Mode"); + //Serial1.println("Spectrum Mode"); DSPType = 1; EEPROM.put(EEPROM_DSPTYPE, DSPType); } else if (cmd1 >= 100 && cmd1 <= 145) { cwDecodeHz = cmd1 - 100; - CalculateCoeff(cwDecodeHz); + //calculateCoeff(cwDecodeHz); DSPType = 2; EEPROM.put(EEPROM_DSPTYPE, DSPType); EEPROM.put(EEPROM_CW_FREQ, cwDecodeHz); @@ -396,12 +175,12 @@ char CommandPasrser(int lastIndex) { if (commandVal == 0) //RX { - TXStatus = 0; + isTX = false; SMeterToUartIdleCount = 0; } else if (commandVal == 1) //TX { - TXStatus = 1; + isTX = true; SMeterToUartIdleCount = 0; } } @@ -414,32 +193,38 @@ char CommandPasrser(int lastIndex) return 0; } + + //#define PROTOCOL_TIMEOUT = 100 -int ForwardData(void) + +/*! + @brief Forwards serial data from the RX line to the TX line. +*/ + +void forwardData(void) { - uint8_t recvChar; + char recvChar; - if (Serial.available() > 0) + if (Serial1.available() > 0) { -#ifndef USE_SW_SERIAL - Serial.flush(); -#endif - //Check RX Buffer - while (Serial.available() > 0) + Serial1.flush(); + + // Check RX buffer for available data. + while (Serial1.available() > 0) { - recvChar = Serial.read(); + recvChar = char(Serial1.read()); - ForwardBuff[nowBuffIndex] = recvChar; + forwardBuff[nowBuffIndex] = recvChar; - if (recvChar == 0xFF) //found ETX + if (recvChar == 0xFF) // found ETX { - etxCount++; //Nextion Protocol, ETX : 0xFF, 0xFF, 0xFF + etxCount++; // Nextion protocol, ETX: 0xFF, 0xFF, 0xFF if (etxCount >= 3) { - //Finished Protocol - if (CommandPasrser(nowBuffIndex) == 1) + // Finished Protocol + if (commandParser(nowBuffIndex) == 1) { - nowSendingProtocol = 0; //Finished 1 Set Command + nowSendingProtocol = 0; // finished 1 set command etxCount = 0; nowBuffIndex = 0; } @@ -447,568 +232,439 @@ int ForwardData(void) } else { - etxCount = 0x00; - nowSendingProtocol = 1; //Sending Data + nowSendingProtocol = 1; // sending data + etxCount = 0; } - - SWSerial_Write(recvChar); - lastForwardmili = millis(); + + Serial1.write(recvChar); + sinceForward = 0; nowBuffIndex++; - if (nowBuffIndex > MAX_FORWARD_BUFF_LENGTH -2) + if (nowBuffIndex > MAX_FORWARD_BUFF_LENGTH - 2) { nowBuffIndex = 0; } - } //end of while + } -#ifndef USE_SW_SERIAL - Serial.flush(); -#endif - - //lastReceivedTime = millis(); - } //end if (Serial.available + Serial1.flush(); + } else { - //check Timeout - + // check timeout } } -int SendMeterData(uint8_t isSend) -{ - //basic : 1.5Khz - int newScaledSMeter = 0; - //if (ADC_DIFF > 26) //-63dBm : S9 + 10dBm - if (ADC_DIFF > 26) //-63dBm : S9 + 10dBm (subtract loss rate) - //if (ADC_DIFF > 55) //-63dBm : S9 + 15dBm - { - newScaledSMeter = 8; - } - else if (ADC_DIFF > 11) //~ -72 S9 - { - newScaledSMeter = 7; - } - else if (ADC_DIFF > 8) - { - newScaledSMeter = 6; - } - else if (ADC_DIFF > 6) //~-80 S7 - //else if (ADC_DIFF > 5) //~-80 S7 - { - newScaledSMeter = 5; - } - else if (ADC_DIFF > 4) - { - newScaledSMeter = 4; //79 S8 - } - else if (ADC_DIFF > 3) - { - newScaledSMeter = 3; //-81 ~ -78 => S7 - } - else if (ADC_DIFF > 2) - { - newScaledSMeter = 2; // -88 ~ -82 => S7 or S6 - } - else if (ADC_DIFF > 1) //-93 ~ -89 => S5 or S4 - { - newScaledSMeter = 1; - } - else // ~ -93.0dBm ~S3 or S4 - { - newScaledSMeter = 0; - } +/**********************************************************************/ -/* -1 : with noise (not use 0 ~ S3) -2 : -93 ~ -89 -3 : -88 ~ -81 -4 : -80 ~ -78 -5 : -77 ~ -72 -6 : -71 ~ -69 - */ - - scaledSMeter = newScaledSMeter; +void sendMeterData(uint8_t isSend) +{ + scaledSMeter = Sensors.sMeterScaled(); + + /* + 1 : with noise (not use 0 ~ S3) + 2 : -93 ~ -89 + 3 : -88 ~ -81 + 4 : -80 ~ -78 + 5 : -77 ~ -72 + 6 : -71 ~ -69 + */ if (isSend == 1) { if (L_scaledSMeter != scaledSMeter) { L_scaledSMeter = scaledSMeter; - SendCommand1Num(CMD_SMETER, L_scaledSMeter); + sendCommand1Num(CMD_SMETER, L_scaledSMeter); } } } +/**********************************************************************/ -void GrepADC(void) +//void sendFFTData(void) +//{ +// int readValue = 0; +// for (int i = 0; i < 11; i++) +// Serial1.write(responseHeader[i]); +// +// for(int i = 1; i < 64; i++) +// { +// readValue = (int)(FFTReal[i]); +// if (readValue < 0) +// { +// readValue = 0; +// } +// else if (readValue>255) +// { +// readValue=255; +// } +// Serial1.write(hexCodes[readValue >> 4]); +// Serial1.write(hexCodes[readValue & 0xf]); +// } +// +// for (int i = 0; i < 4; i++) +// Serial1.write(responseFooter[i]); +//} + +void setup() { - int readedValue = 0; - unsigned long currentms = 0; - int readSampleCount = 0; - - if (DSPType == 2 || DSPType == 0) //Decode Morse - { - readSampleCount = DECODE_MORSE_SAMPLESIZE; - } - else if (DSPType == 3) //Decode RTTY - { - readSampleCount = DECODE_MORSE_SAMPLESIZE; - } - else - { - readSampleCount = SAMPLESIZE; - } - - ADC_MAX = 0; - ADC_MIN = 30000; - - for(int i=0; i < readSampleCount; i++) - { - currentms = micros(); - readedValue = analogRead(SIGNAL_METER_ADC);; - FFTReal[i] = readedValue; - FFTImag[i] = 0; - - if (ADC_MAX < readedValue) - { - ADC_MAX = readedValue; - } - - if (ADC_MIN > readedValue) - { - ADC_MIN = readedValue; - } - - while(micros() < (currentms + SAMPLE_INTERVAL)){} - } //end of for -} - -void SendFFTData(void) -{ - int readedValue = 0; - for (int i = 0; i < 11; i++) - SWSerial_Write(ResponseHeader[i]); - - for(int i = 1; i < 64; i++) - { - readedValue = (int)(FFTReal[i]); - if (readedValue < 0) - { - readedValue = 0; - } - else if (readedValue>255) - { - readedValue=255; - } - SWSerial_Write(HexCodes[readedValue >> 4]); - SWSerial_Write(HexCodes[readedValue & 0xf]); - } - - for (int i = 0; i < 4; i++) - SWSerial_Write(ResponseFooter[i]); -} - -void setup() -{ - //Load Configuration + // load configuration EEPROM.get(EEPROM_DSPTYPE, DSPType); if (DSPType > 5) { DSPType = 1; } - //Signal Meter + // signal meter EEPROM.get(EEPROM_SMETER_UART, SMeterToUartSend); if (SMeterToUartSend > 2) { SMeterToUartSend = 1; } - // + + // something with CW decoding... EEPROM.get(EEPROM_CW_FREQ, cwDecodeHz); if (cwDecodeHz > 40 || cwDecodeHz < 1) { cwDecodeHz = 9; } - //EEPROM_CW_MAG_LOW + // EEPROM_CW_MAG_LOW EEPROM.get(EEPROM_CW_MAG_LOW, magnitudelimit_low); if (magnitudelimit_low > 1000 || magnitudelimit_low < 1) { magnitudelimit_low = 50; } - - // put your setup code here, to run once: - Wire.begin(I2CMETER_ADDR); //j : S-Meter Slave Address - //Wire.begin(0x21); //j : S-Meter Slave Address - Wire.onReceive(I2CReceiveEvent); // - Wire.onRequest(I2CRequestEvent); - -#ifdef USE_SW_SERIAL - SWSerial_Begin(9600); -#endif - Serial.begin(9600, SERIAL_8N1); - Serial.flush(); - SAMPLE_INTERVAL = round(1000000 * (1.0 / SAMPLE_PREQUENCY)); - CalculateCoeff(cwDecodeHz); //Set 750Hz //9 * 50 + 300 = 750Hz - //Serial.println("Start..."); + // put your setup code here, to run once: + + // slave Wire1 configuration for communication with the Raduino + Wire1.begin(I2CMETER_ADDR); + Wire1.onReceive(i2cReceiveEvent); + Wire1.onRequest(i2cRequestEvent); + + // Serial1 configuration for communication with Raduino (RX) and Nextion (TX) + Serial1.begin(9600, SERIAL_8N1); + Serial1.flush(); + + SAMPLE_INTERVAL = round(1000000 * (1.0 / SAMPLE_FREQUENCY)); + //calculateCoeff(cwDecodeHz); //Set 750Hz //9 * 50 + 300 = 750Hz + //Serial1.println("Start..."); + + DBGCMD( DSP.begin() ); + DBGCMD( TR.begin() ); } -void I2CReceiveEvent(void) +/*! + @brief Receive a command via I2C. The most recent command will be received, which will + indicate which data the DSP should be preparing to return. + @param numBytes + Number of bytes received--not used in this procedure. +*/ +void i2cReceiveEvent(size_t numBytes) { - int readCommand = 0; // byte를 읽어 int로 변환 - - while(Wire.available() > 0) // for Last command + int readCommand = 0; + + while (Wire1.available() > 0) // for Last command { - readCommand = Wire.read(); + readCommand = Wire1.read(); + // KC4UPR: Note that this looks to be only reading the last command, i.e. + // if multiple commands have been queued up, only the last will get executed. } if (0x50 <= readCommand && readCommand <= 0x59) { - I2CCommand = readCommand; + i2cCommand = readCommand; } } -void I2CRequestEvent(void) +/*! + @brief Respond to a request from the I2C Master (Raduino). Returns the appropriate data + based on whatever command was previously issued. +*/ +void i2cRequestEvent(void) { - int maxValue = 0; - int minValue = 30000; - int readedValue = 0; - unsigned long curr = 0; + //int maxValue = 0; + //int minValue = 30000; + //int readValue = 0; + //unsigned long curr = 0; - //if (nowADCSampling == 1) //Now Sampling ADC's - //{ - // nowADCSampling = 2; //when finished ADC Sampling, response I2CRequest Event - // return; - //} //end of if - - if (I2CCommand == I2CMETER_CALCS) - { - Wire.write(scaledSMeter); - } - else if (I2CCommand == I2CMETER_UNCALCS) - { - //Wire.write(ADC_DIFF); - //8292Hz - for(int i=0; i < 7; i++) - { - curr = micros(); - readedValue = analogRead(SIGNAL_METER_ADC);; + switch (i2cCommand) { + case I2CMETER_CALCS: + // Returns an already-calculated S-meter value. + Wire1.write(scaledSMeter); + break; - if (readedValue > maxValue) - { - maxValue = readedValue; - } + case I2CMETER_UNCALCS: + // Returns a raw signal strength value. + Wire1.write(Sensors.sMeterUnscaled() >> 2); // divided by 4... do we want this? + break; - if (readedValue < minValue) - { - minValue = readedValue; - } - while(micros() < (curr + 127)){} //8Khz / 7 - } //end of for + case I2CMETER_CALCP: + // Returns a raw forward power value. + Wire1.write(fwdPower); + break; - readedValue = maxValue - minValue; - readedValue = readedValue * readedValue; - //readedValue = readedValue / 2; - if (readedValue < 0) - { - readedValue = 0; - } - else if (readedValue > 255) - { - readedValue = 255; - } - Wire.write(readedValue); - } - else if (I2CCommand == I2CMETER_CALCP) - { - readedValue = analogRead(POWER_METER_ADC); //POWER - Wire.write(readedValue); - } - else if (I2CCommand == I2CMETER_CALCR) //SWR - { - readedValue = analogRead(SWR_METER_ADC); - Wire.write(readedValue); + case I2CMETER_CALCR: + // Returns a raw reverse power value. + Wire1.write(revPower); + break; + + default: + break; } } -extern void Decode_Morse(float magnitude); -extern double coeff; - +//extern void Decode_Morse(float magnitude); +//extern double coeff; #define LAST_TIME_INTERVAL 159 -//int SWRAdcValue = 0; -float adcFWD = 0; -float adcRWD = 0; -uint16_t adjustPower = 230; -float swrMeasured; - -int clcCount = 0; - - -//for boot Delay, a alot of data transfer -//Delay 2.5 Sec +// for boot delay, a lot of data to transfer +// Delay 2.5 Sec byte isBooted = 0; -void loop() -{ - char isProcess = 0; //0 : Init, 1 : Complete ADC Sampling, 2 : Complete FFT - isProcess = 0; +//====================================================================== +// ADC PROCESSES +//====================================================================== + +elapsedMillis sinceFrameMillis = 0; +elapsedMillis sinceADCMillis = 0; + +#define FRAME_RATE 40 +#define FRAME_INTERVAL_MS (1000/FRAME_RATE) + +const int frameIntervalMillis = FRAME_INTERVAL_MS; + +#define ADC_SAMPLE_RATE 120 +#define ADC_INTERVAL_MS (1000/ADC_SAMPLE_RATE) + +const int adcIntervalMillis = ADC_INTERVAL_MS; + +//====================================================================== +// MAIN LOOP +//====================================================================== + +#ifdef DEBUG +int frameCounter = 0; +#endif + +void loop() +{ + //char isProcess = 0; // 0: init, 1: complete ADC sampling, 2: complete FFT + //isProcess = 0; + + forwardData(); - ForwardData(); if (isBooted < 100) { //Delay 20msec for (int i = 0; i < 20; i++) { - ForwardData(); + forwardData(); delay(1); } isBooted++; return; } - //=========================================== - //TRANSCEIVER STATUS : RX - //=========================================== - if (TXStatus == 1) //TX Mode - { - /* - int readedValue = 0; - SMeterToUartIdleCount++; - if (SMeterToUartIdleCount > 130) //SWR - { - //SWR Send - SendCommandL('m', SWRAdcValue); - SendCommand1Num('m', 3); - SMeterToUartIdleCount = 0; - } - else if (SMeterToUartIdleCount == 100) //POWER 500msec interval - { - readedValue = analogRead(POWER_METER_ADC ); - SWRAdcValue = analogRead(SWR_METER_ADC); - SendCommandL('m', readedValue); - SendCommand1Num('m',2); - //PWR Send - } - */ + if (sinceFrameMillis > frameIntervalMillis) { + // Do stuff that we do once per frame--I/O. + // TODO: debug output (frame skipping / utilization). + sinceFrameMillis = 0; - //************************************************ - //Read FWD and RWD - adcFWD = adcFWD * 0.8 + analogRead(A2) * 0.2; - adcRWD = adcRWD * 0.8 + analogRead(A3) * 0.2; - - if (adcRWD > adcFWD) - { - adcRWD = adcFWD; - } - - //for Realtime LCD Display - ForwardData(); - - if (clcCount++ > 10) - { - //Calculated Power and swr and Send Information - clcCount = 0; - - //Calc PWR - float PWR = pow(adcFWD, 2); - PWR = PWR / adjustPower / 100; - - //Calc SWR - float Vratio = adcRWD / adcFWD; - if (adcRWD < 0.05 && adcFWD < 0.05) - { - //No signal - swrMeasured = 0; - } - else if (Vratio > 0.99) - { - swrMeasured = 1999; +#ifdef DEBUG + // For debugging, output some debug info every 1.0" (40 frames @ 40 Hz). + frameCounter++; + if (frameCounter % 40 == 0) { + Serial.print("DBG: Frame: "); + Serial.print(frameCounter); + if (isTX) { + Serial.print(", Loop State: TX"); + } else { + Serial.print(", Loop State: RX"); } - else - { - swrMeasured = ((1 + Vratio)/ (1 - Vratio)); + if (TR.transmitting()) { + Serial.println(", TR State: TX"); + } else { + Serial.println(", TR State: RX"); + } + Serial.print("DBG: S-Meter Raw: "); + Serial.print(Sensors.sMeterUnscaled()); + Serial.print(", S-Meter Scaled: "); + Serial.println(scaledSMeter); + Serial.print("DBG: VSWR Calc: "); + Serial.print(calcVSWR, 2); + Serial.print(", VSWR Scaled: "); + Serial.print(scaledVSWR); + Serial.print(", FWD PWR: "); + Serial.print(fwdPower, 2); + Serial.print(", REV PWR: "); + Serial.println(revPower, 2); + } +#endif + + TR.update(); + + if (isTX) { + calcVSWR = Sensors.VSWR(); + scaledVSWR = byte(Sensors.scaledVSWR()); + fwdPower = Sensors.Pfwd(); + revPower = Sensors.Prev(); + + // Send SWR meter information. + if (L_scaledVSWR != scaledVSWR) { + L_scaledVSWR = scaledVSWR; + sendCommand1Num(CMD_SMETER, scaledVSWR); } - //For Version 0.8 - //Send SWR Information using Receive Signal Meter Protocol - scaledSMeter = (int)(swrMeasured + 0.5); - if (scaledSMeter > 9) - { - scaledSMeter = 9; + // Send forward power. + if (L_fwdPower != fwdPower) { + L_fwdPower = fwdPower; + sendCommandL('m', fwdPower * 100); // watts x 100? + sendCommand1Num('m', 2); } - if (L_scaledSMeter != scaledSMeter) - { - L_scaledSMeter = scaledSMeter; - SendCommand1Num(CMD_SMETER, L_scaledSMeter); + // Send reverse power. + //if (L_revPower != revPower) { + // L_revPower = revPower; + // sendCommandL('m', revPower * 100); // watts x 100? + // sendCommand1Num('m', 2); + //} + + // Does there need to be some kind of 250-500ms delay after this??? + // Delay 250msec ~ 500msec for Nextion LCD Processing (using m protocol) + //for (int i = 0; i < 10; i++) { + // forwardData(); + // if (!isTX) { //if TX -> RX break + // break; + // } + // delay(25); + //} //end of delay time + + // Send SWR. + if (L_calcVSWR != calcVSWR) { + L_calcVSWR = calcVSWR; + sendCommandL('m', int(calcVSWR * 100.0)); // SWR x 100? + sendCommand1Num('m', 3); } - //For Version 1.0 - //need mod uBITX firmware and Nextion LCD and add Power adjust value option (uBITX Manager) - //Send Information - //SWR Send - //SendCommandL('m', SWRAdcValue); - //SendCommand1Num('m', 3); - //SMeterToUartIdleCount = 0; - //Send Power Information - int readedValue = (int)(PWR * 100); - SendCommandL('m', readedValue); - SendCommand1Num('m',2); + } else { // RX - //Delay 250msec ~ 500msec for Nextion LCD Processing (using m protocol) - - for (int i = 0; i < 10; i++) + // Send Signal Meter to UART + if (SMeterToUartSend == 1 && nowSendingProtocol == 0) //SMeter To Uart Send { - ForwardData(); - if (TXStatus != 1) //if TX -> RX break - { - break; - } - delay(25); - } //end of delay time - - //Send SWR - readedValue = (int)(swrMeasured * 100); - SendCommandL('m', readedValue); - SendCommand1Num('m', 3); - - //delay(50); - //return; + //nowSendingProtocol -> not finished data forward, (not found 0xff, 0xff, 0xff yet) + sendMeterData(1); + } else { + sendMeterData(0); //only calculate Signal Level + } + } - - delay(30); - return; //Do not processing ADC, FFT, Decode Morse or RTTY, only Power and SWR Data Return + + // Forward any data that came in while we were updating stuff. + forwardData(); } - //=========================================== - //TRANSCEIVER STATUS : RX - //=========================================== - //=========================================== - // ADC Sampling - //=========================================== - if (nowSendingProtocol == 0) //Idle Status - { - nowADCSampling = 1; //Mark => Start Sampling - GrepADC(); - - //if(nowADCSampling == 2) //Marked ? While ADC Sampling, receive I2C - //{ - // nowADCSampling = 0; //Mark => Finish Sampling - // I2CRequestEvent(); - //} - nowADCSampling = 0; //Mark => Finish Sampling + if (sinceADCMillis > adcIntervalMillis) { + // Do stuff that we do once per ADC interval--ADC colllection. + // TODO: debug output (frame skipping / utilization). + sinceADCMillis = 0; - int newDiff = ADC_MAX - ADC_MIN; //Calculated for Signal Meter (ADC_DIFF => Signal Strength) - //ADC_DIFF = ((ADC_DIFF * 7) + (newDiff * 3)) / 10; - ADC_DIFF = newDiff; - isProcess = 1; //Mark => Complete ADC Sampling + if (isTX) { + Sensors.updatePower(); + } else { // RX + Sensors.updateSMeter(); + Sensors.updateSupply(); + } + + // Forward any data that came in while we were reading sensors. + //forwardData(); } - ForwardData(); - - //=========================================== - // Send Signal Meter to UART - //=========================================== - if (SMeterToUartSend == 1) //SMeter To Uart Send + // Check Response Command + if (responseCommand > 0 && sinceForward > LAST_TIME_INTERVAL) { - //When selected Morse decode mode, not send signal Meter - //if ((DSPType != 2) && (SMeterToUartIdleCount++ > (SMeterToUartInterval * (DSPType == 1 ? 1 : 12)))) - //User Option - if (SMeterToUartIdleCount++ > (SMeterToUartInterval * (DSPType == 1 ? 1 : 12))) - { - //nowSendingProtocol -> not finished data forward, (not found 0xff, 0xff, 0xff yet) - if (nowSendingProtocol == 0 && isProcess == 1) //Complete ADC Sampling and Idle status - { - SendMeterData(1); - SMeterToUartIdleCount = 0; - } - } - } //end of if - else - { - SendMeterData(0); //only calculate Signal Level - } - - ForwardData(); - - //Check Response Command - if (responseCommand > 0 && millis() > lastForwardmili + LAST_TIME_INTERVAL) - { - ResponseConfig(); + responseConfig(); } - //=================================================================================== - // DSP Routine - //=================================================================================== - if (DSPType == 1 && millis() > lastForwardmili + LAST_TIME_INTERVAL) //Spectrum : FFT => Send To UART - { - FFTToUartIdleCount = 0; - - if (isProcess == 1) - { - FFT(FFTReal, FFTImag, SAMPLESIZE, 7); - isProcess = 2; - } - - ForwardData(); - - if (isProcess == 2) - { - for (uint16_t k = 0; k < SAMPLESIZE; k++) - { - FFTReal[k] = sqrt(FFTReal[k] * FFTReal[k] + FFTImag[k] * FFTImag[k]); - } - - isProcess = 3; - } - - ForwardData(); - - if (isProcess == 3) - { - if (nowSendingProtocol == 0) //Idle Status - { - SendFFTData(); - } - } - } - else if (DSPType == 2) //Decode Morse - { - //Implement Goertzel_algorithm - //https://en.wikipedia.org/wiki/Goertzel_algorithm + // //=========================================== + // //TRANSCEIVER STATUS : RX + // //=========================================== + // //=================================================================================== + // // DSP Routine + // //=================================================================================== + // if (DSPType == 1 && sinceForward > LAST_TIME_INTERVAL) // spectrum: FFT => send To UART + // { + // FFTToUartIdleCount = 0; + // + // if (isProcess == 1) + // { + // FFT(FFTReal, FFTImag, SAMPLESIZE, 7); + // isProcess = 2; + // } + // + // forwardData(); + // + // if (isProcess == 2) + // { + // for (uint16_t k = 0; k < SAMPLESIZE; k++) + // { + // FFTReal[k] = sqrt(FFTReal[k] * FFTReal[k] + FFTImag[k] * FFTImag[k]); + // } + // + // isProcess = 3; + // } + // + // forwardData(); + // + // if (isProcess == 3) + // { + // if (nowSendingProtocol == 0) //Idle Status + // { + // sendFFTData(); + // } + // } + // } + // else if (DSPType == 2) //Decode Morse + // { + // //Implement Goertzel_algorithm + // //https://en.wikipedia.org/wiki/Goertzel_algorithm + // + // /* + // ω = 2 * π * Kterm / Nterms; + // cr = cos(ω); + // ci = sin(ω); + // coeff = 2 * cr; + // + // sprev = 0; + // sprev2 = 0; + // for each index n in range 0 to Nterms-1 + // s = x[n] + coeff * sprev - sprev2; + // sprev2 = sprev; + // sprev = s; + // end + // + // power = sprev2 * sprev2 + sprev * sprev - coeff * sprev * sprev2; + // */ + // double Q1 = 0; + // double Q2 = 0; + // + // for (unsigned index = 0; index < DECODE_MORSE_SAMPLESIZE; index++) + // { + // float Q0; + // Q0 = coeff * Q1 - Q2 + FFTReal[index]; + // Q2 = Q1; + // Q1 = Q0; + // } + // double magnitudeSquared = (Q1*Q1)+(Q2*Q2)-Q1*Q2*coeff; // we do only need the real part // + // double magnitude = sqrt(magnitudeSquared); + // + // Decode_Morse(magnitude); + // } //end of if - /* - ω = 2 * π * Kterm / Nterms; - cr = cos(ω); - ci = sin(ω); - coeff = 2 * cr; - - sprev = 0; - sprev2 = 0; - for each index n in range 0 to Nterms-1 - s = x[n] + coeff * sprev - sprev2; - sprev2 = sprev; - sprev = s; - end - - power = sprev2 * sprev2 + sprev * sprev - coeff * sprev * sprev2; - */ - double Q1 = 0; - double Q2 = 0; - - for (char index = 0; index < DECODE_MORSE_SAMPLESIZE; index++) - { - float Q0; - Q0 = coeff * Q1 - Q2 + FFTReal[index]; - Q2 = Q1; - Q1 = Q0; - } - double magnitudeSquared = (Q1*Q1)+(Q2*Q2)-Q1*Q2*coeff; // we do only need the real part // - double magnitude = sqrt(magnitudeSquared); - - Decode_Morse(magnitude); - } //enf of if -} //end of main +} + +//====================================================================== +// EOF +//====================================================================== diff --git a/TeensyDSP/fftfunctions.cpp b/TeensyDSP/fftfunctions.cpp deleted file mode 100644 index 81bffda..0000000 --- a/TeensyDSP/fftfunctions.cpp +++ /dev/null @@ -1,362 +0,0 @@ -/* -FFTFunctions for Nextion LCD and Control MCU -This code is for FFT and CW Decode. -KD8CEC, Ian Lee ------------------------------------------------------------------------ -//The section on CW decode logic is specified at the bottom of this code. -License : I follow the license of the previous code and I do not add any extra constraints. -I hope that the Comment I made or the Comment of OZ1JHM will be maintained. -**********************************************************************/ -#include -#include "TeensyDSP.h" - -// Code Referency : http://paulbourke.net/miscellaneous/dft/ -// DFT, FFT Wiritten by Paul Bourke, June 1993 -void FFT(double *x,double *y, int n, long m) -{ - long i,i1,j,k,i2,l,l1,l2; - double c1,c2,tx,ty,t1,t2,u1,u2,z; - short int dir = 0; - - /* Do the bit reversal */ - i2 = n >> 1; - j = 0; - for (i=0;i>= 1; - } - j += k; - } - - /* Compute the FFT */ - c1 = -1.0; - c2 = 0.0; - l2 = 1; - - for (l=0;l 20) - //{ - //writeCount = 0; - //Serial.println(""); - //} -} - -uint8_t docode() -{ - if (strcmp(code,".-") == 0) printascii(65); - if (strcmp(code,"-...") == 0) printascii(66); - if (strcmp(code,"-.-.") == 0) printascii(67); - if (strcmp(code,"-..") == 0) printascii(68); - if (strcmp(code,".") == 0) printascii(69); - if (strcmp(code,"..-.") == 0) printascii(70); - if (strcmp(code,"--.") == 0) printascii(71); - if (strcmp(code,"....") == 0) printascii(72); - if (strcmp(code,"..") == 0) printascii(73); - if (strcmp(code,".---") == 0) printascii(74); - if (strcmp(code,"-.-") == 0) printascii(75); - if (strcmp(code,".-..") == 0) printascii(76); - if (strcmp(code,"--") == 0) printascii(77); - if (strcmp(code,"-.") == 0) printascii(78); - if (strcmp(code,"---") == 0) printascii(79); - if (strcmp(code,".--.") == 0) printascii(80); - if (strcmp(code,"--.-") == 0) printascii(81); - if (strcmp(code,".-.") == 0) printascii(82); - if (strcmp(code,"...") == 0) printascii(83); - if (strcmp(code,"-") == 0) printascii(84); - if (strcmp(code,"..-") == 0) printascii(85); - if (strcmp(code,"...-") == 0) printascii(86); - if (strcmp(code,".--") == 0) printascii(87); - if (strcmp(code,"-..-") == 0) printascii(88); - if (strcmp(code,"-.--") == 0) printascii(89); - if (strcmp(code,"--..") == 0) printascii(90); - - if (strcmp(code,".----") == 0) printascii(49); - if (strcmp(code,"..---") == 0) printascii(50); - if (strcmp(code,"...--") == 0) printascii(51); - if (strcmp(code,"....-") == 0) printascii(52); - if (strcmp(code,".....") == 0) printascii(53); - if (strcmp(code,"-....") == 0) printascii(54); - if (strcmp(code,"--...") == 0) printascii(55); - if (strcmp(code,"---..") == 0) printascii(56); - if (strcmp(code,"----.") == 0) printascii(57); - if (strcmp(code,"-----") == 0) printascii(48); - - if (strcmp(code,"..--..") == 0) printascii(63); - if (strcmp(code,".-.-.-") == 0) printascii(46); - if (strcmp(code,"--..--") == 0) printascii(44); - if (strcmp(code,"-.-.--") == 0) printascii(33); - if (strcmp(code,".--.-.") == 0) printascii(64); - if (strcmp(code,"---...") == 0) printascii(58); - if (strcmp(code,"-....-") == 0) printascii(45); - if (strcmp(code,"-..-.") == 0) printascii(47); - - if (strcmp(code,"-.--.") == 0) printascii(40); - if (strcmp(code,"-.--.-") == 0) printascii(41); - if (strcmp(code,".-...") == 0) printascii(95); - if (strcmp(code,"...-..-") == 0) printascii(36); - if (strcmp(code,"...-.-") == 0) printascii(62); - if (strcmp(code,".-.-.") == 0) printascii(60); - if (strcmp(code,"...-.") == 0) printascii(126); - ////////////////// - // The specials // - ////////////////// - if (strcmp(code,".-.-") == 0) printascii(3); - if (strcmp(code,"---.") == 0) printascii(4); - if (strcmp(code,".--.-") == 0) printascii(6); - -} - -void Decode_Morse(float magnitude) -{ - //magnitudelimit auto Increase - if (magnitude > magnitudelimit_low) - { - magnitudelimit = (magnitudelimit +((magnitude - magnitudelimit)/6)); /// moving average filter - } - - if (magnitudelimit < magnitudelimit_low) - magnitudelimit = magnitudelimit_low; - - if(magnitude > magnitudelimit*0.6) // just to have some space up - realstate = HIGH; - else - realstate = LOW; - - if (realstate != realstatebefore) - laststarttime = millis(); - - if ((millis()-laststarttime) > nbtime) - { - if (realstate != filteredstate) - { - filteredstate = realstate; - } - } - - if (filteredstate != filteredstatebefore) - { - if (filteredstate == HIGH) - { - starttimehigh = millis(); - lowduration = (millis() - startttimelow); - } - - if (filteredstate == LOW) - { - startttimelow = millis(); - highduration = (millis() - starttimehigh); - - if (highduration < (2*hightimesavg) || hightimesavg == 0) - { - hightimesavg = (highduration+hightimesavg+hightimesavg)/3; // now we know avg dit time ( rolling 3 avg) - } - - if (highduration > (5*hightimesavg) ) - { - hightimesavg = highduration+hightimesavg; // if speed decrease fast .. - } - } - } - - /////////////////////////////////////////////////////////////// - // now we will check which kind of baud we have - dit or dah // - // and what kind of pause we do have 1 - 3 or 7 pause // - // we think that hightimeavg = 1 bit // - /////////////////////////////////////////////////////////////// - - if (filteredstate != filteredstatebefore) - { - stop = LOW; - if (filteredstate == LOW) - { - if (highduration < (hightimesavg*2) && highduration > (hightimesavg*0.6)) /// 0.6 filter out false dits - { - strcat(code,"."); - } - if (highduration > (hightimesavg*2) && highduration < (hightimesavg*6)) - { - strcat(code,"-"); - wpm = (wpm + (1200/((highduration)/3)))/2; //// the most precise we can do ;o) - } - } - - if (filteredstate == HIGH) - { - float lacktime = 1; - if(wpm > 25)lacktime=1.0; /// when high speeds we have to have a little more pause before new letter or new word - if(wpm > 30)lacktime=1.2; - if(wpm > 35)lacktime=1.5; - - if (lowduration > (hightimesavg*(2*lacktime)) && lowduration < hightimesavg*(5*lacktime)) // letter space - { - docode(); - code[0] = '\0'; - } - if (lowduration >= hightimesavg*(5*lacktime)) - { // word space - docode(); - code[0] = '\0'; - printascii(32); - } - } - } - - if ((millis() - startttimelow) > (highduration * 6) && stop == LOW) - { - docode(); - code[0] = '\0'; - stop = HIGH; - } - - /* - if(filteredstate == HIGH) - { - digitalWrite(ledPin, HIGH); - tone(audioOutPin,target_freq); - } - else - { - digitalWrite(ledPin, LOW); - noTone(audioOutPin); - } -*/ - - realstatebefore = realstate; - lasthighduration = highduration; - filteredstatebefore = filteredstate; -} - diff --git a/TeensyDSP/uart_forward.cpp b/TeensyDSP/uart_forward.cpp deleted file mode 100644 index 66976c8..0000000 --- a/TeensyDSP/uart_forward.cpp +++ /dev/null @@ -1,355 +0,0 @@ -/* -Softserial for Nextion LCD and Control MCU -KD8CEC, Ian Lee ------------------------------------------------------------------------ -It is a library rewritten in C format based on SoftwareSerial.c. -I tried to use as much as possible without modifying the SoftwareSerial. -But eventually I had to modify the code. - -I rewrote it in C for the following reasons. - - Problems occurred when increasing Program Size and Program Memory - - We had to reduce the program size. - Of course, Software Serial is limited to one. - - reduce the steps for transmitting and receiving - -useage -extern void SWSerial_Begin(long speedBaud); -extern void SWSerial_Write(uint8_t b); -extern int SWSerial_Available(void); -extern int SWSerial_Read(void); -extern void SWSerial_Print(uint8_t *b); - -If you use Softwreserial library instead of this library, you can modify the code as shown below. -I kept the function name of SoftwareSerial so you only need to modify a few lines of code. - -define top of source code -#include -SoftwareSerial sSerial(10, 11); // RX, TX - -replace source code -SWSerial_Begin to sSerial.begin -SWSerial_Write to sSerial.write -SWSerial_Available to sSerial.available -SWSerial_Read to sSerial.read - -KD8CEC, Ian Lee ------------------------------------------------------------------------ -License -All licenses for the source code are subject to the license of the original source SoftwareSerial Library. -However, if you use or modify this code, please keep the all comments in this source code. -KD8CEC ------------------------------------------------------------------------ -License from SoftwareSerial ------------------------------------------------------------------------ -SoftwareSerial.cpp (formerly NewSoftSerial.cpp) - -Multi-instance software serial library for Arduino/Wiring --- Interrupt-driven receive and other improvements by ladyada - (http://ladyada.net) --- Tuning, circular buffer, derivation from class Print/Stream, - multi-instance support, porting to 8MHz processors, - various optimizations, PROGMEM delay tables, inverse logic and - direct port writing by Mikal Hart (http://www.arduiniana.org) --- Pin change interrupt macros by Paul Stoffregen (http://www.pjrc.com) --- 20MHz processor support by Garrett Mace (http://www.macetech.com) --- ATmega1280/2560 support by Brett Hagman (http://www.roguerobotics.com/) - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public -License along with this library; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -The latest version of this library can always be found at -http://arduiniana.org. - */ -#include "TeensyDSP.h" - -#ifdef USE_SW_SERIAL -//================================================================ -//Public Variable -//================================================================ -#define TX_PIN 9 -#define RX_PIN 8 -#define _SS_MAX_RX_BUFF 35 // RX buffer size -#define PRINT_MAX_LENGTH 30 - -//================================================================ -//Internal Variable from SoftwareSerial.c and SoftwareSerial.h -//================================================================ -//variable from softwareserial.c and softwareserial.h -static uint8_t swr_receive_buffer[_SS_MAX_RX_BUFF]; - -volatile uint8_t *_transmitPortRegister; //Write Port Register -uint8_t transmit_RegMask; //use Mask bit 1 -uint8_t transmit_InvMask; //use mask bit 0 - -volatile uint8_t *_receivePortRegister; //Read Port Register -uint8_t _receiveBitMask; - -//delay value for Bit -uint16_t _tx_delay; - -//delay value for Receive -uint16_t _rx_delay_stopbit; -uint16_t _rx_delay_centering; -uint16_t _rx_delay_intrabit; - -//Customize for uBITX Protocol -int8_t receiveIndex = 0; -int8_t receivedCommandLength = 0; -int8_t ffCount = 0; - -//Values for Receive Buffer -//uint16_t _buffer_overflow; -//static volatile uint8_t _receive_buffer_head; -//static volatile uint8_t _receive_buffer_tail; - -//Values for Interrupt (check Start Bit) -volatile uint8_t *_pcint_maskreg; -uint8_t _pcint_maskvalue; - -//================================================================ -//Internal Function from SoftwareSerial.c -//================================================================ -uint16_t subtract_cap(uint16_t num, uint16_t sub) -{ - if (num > sub) - return num - sub; - else - return 1; -} - -inline void tunedDelay(uint16_t delay) -{ - _delay_loop_2(delay); -} - -void setRxIntMsk(bool enable) -{ - if (enable) - *_pcint_maskreg |= _pcint_maskvalue; - else - *_pcint_maskreg &= ~_pcint_maskvalue; -} - -uint8_t rx_pin_read() -{ - return *_receivePortRegister & _receiveBitMask; -} - -// -// The receive routine called by the interrupt handler -// -void softSerail_Recv() -{ -#if GCC_VERSION < 40302 -// Work-around for avr-gcc 4.3.0 OSX version bug -// Preserve the registers that the compiler misses -// (courtesy of Arduino forum user *etracer*) - asm volatile( - "push r18 \n\t" - "push r19 \n\t" - "push r20 \n\t" - "push r21 \n\t" - "push r22 \n\t" - "push r23 \n\t" - "push r26 \n\t" - "push r27 \n\t" - ::); -#endif - - uint8_t d = 0; - - // If RX line is high, then we don't see any start bit - // so interrupt is probably not for us - if (!rx_pin_read()) //Start Bit - { - // Disable further interrupts during reception, this prevents - // triggering another interrupt directly after we return, which can - // cause problems at higher baudrates. - setRxIntMsk(false); - - // Wait approximately 1/2 of a bit width to "center" the sample - tunedDelay(_rx_delay_centering); - - // Read each of the 8 bits - for (uint8_t i=8; i > 0; --i) - { - tunedDelay(_rx_delay_intrabit); - d >>= 1; - - if (rx_pin_read()) - d |= 0x80; - } - - if (receivedCommandLength == 0) //check Already Command - { - //Set Received Data - swr_receive_buffer[receiveIndex++] = d; - - //Finded Command - if (d == 0x73 && ffCount > 1 && receiveIndex > 6) - { - receivedCommandLength = receiveIndex; - receiveIndex = 0; - ffCount = 0; - } - else if (receiveIndex > _SS_MAX_RX_BUFF) - { - //Buffer Overflow - receiveIndex = 0; - ffCount = 0; - } - else if (d == 0xFF) - { - ffCount++; - } - else - { - ffCount = 0; - } - } - - // skip the stop bit - tunedDelay(_rx_delay_stopbit); - - // Re-enable interrupts when we're sure to be inside the stop bit - setRxIntMsk(true); - } - -#if GCC_VERSION < 40302 -// Work-around for avr-gcc 4.3.0 OSX version bug -// Restore the registers that the compiler misses - asm volatile( - "pop r27 \n\t" - "pop r26 \n\t" - "pop r23 \n\t" - "pop r22 \n\t" - "pop r21 \n\t" - "pop r20 \n\t" - "pop r19 \n\t" - "pop r18 \n\t" - ::); -#endif -} - -ISR(PCINT0_vect) -{ - softSerail_Recv(); -} - -//================================================================ -//Public Function from SoftwareSerial.c and modified and create -//================================================================ -// Read data from buffer -void SWSerial_Read(uint8_t * receive_cmdBuffer) -{ - for (int i = 0; i < receivedCommandLength; i++) - receive_cmdBuffer[i] = swr_receive_buffer[i]; -} - -void SWSerial_Write(uint8_t b) -{ - volatile uint8_t *reg = _transmitPortRegister; - uint8_t oldSREG = SREG; - uint16_t delay = _tx_delay; - - cli(); // turn off interrupts for a clean txmit - - // Write the start bit - *reg &= transmit_InvMask; - - tunedDelay(delay); - - // Write each of the 8 bits - for (uint8_t i = 8; i > 0; --i) - { - if (b & 1) // choose bit - *reg |= transmit_RegMask; // send 1 - else - *reg &= transmit_InvMask; // send 0 - - tunedDelay(delay); - b >>= 1; - } - - // restore pin to natural state - *reg |= transmit_RegMask; - - SREG = oldSREG; // turn interrupts back on - tunedDelay(_tx_delay); -} - -void SWSerial_Print(uint8_t *b) -{ - for (int i = 0; i < PRINT_MAX_LENGTH; i++) - { - if (b[i] == 0x00) - break; - else - SWSerial_Write(b[i]); - } -} - -void SWSerial_Begin(long speedBaud) -{ - //INT TX_PIN - digitalWrite(TX_PIN, HIGH); - pinMode(TX_PIN, OUTPUT); - transmit_RegMask = digitalPinToBitMask(TX_PIN); //use Bit 1 - transmit_InvMask = ~digitalPinToBitMask(TX_PIN); //use Bit 0 - _transmitPortRegister = portOutputRegister(digitalPinToPort(TX_PIN)); - - //INIT RX_PIN - pinMode(RX_PIN, INPUT); - digitalWrite(RX_PIN, HIGH); // pullup for normal logic! - _receiveBitMask = digitalPinToBitMask(RX_PIN); - _receivePortRegister = portInputRegister(digitalPinToPort(RX_PIN)); - - //Set Values - uint16_t bit_delay = (F_CPU / speedBaud) / 4; - _tx_delay = subtract_cap(bit_delay, 15 / 4); - - if (digitalPinToPCICR(RX_PIN)) - { - _rx_delay_centering = subtract_cap(bit_delay / 2, (4 + 4 + 75 + 17 - 23) / 4); - _rx_delay_intrabit = subtract_cap(bit_delay, 23 / 4); - _rx_delay_stopbit = subtract_cap(bit_delay * 3 / 4, (37 + 11) / 4); - *digitalPinToPCICR(RX_PIN) |= _BV(digitalPinToPCICRbit(RX_PIN)); - _pcint_maskreg = digitalPinToPCMSK(RX_PIN); - _pcint_maskvalue = _BV(digitalPinToPCMSKbit(RX_PIN)); - - tunedDelay(_tx_delay); // if we were low this establishes the end - } - - //Start Listen - setRxIntMsk(true); -} -#else -void SWSerial_Write(uint8_t b) -{ - Serial.write(b); - //Serial.flush(); -} - -void SWSerial_Print(uint8_t *b) -{ - for (int i = 0; i < PRINT_MAX_LENGTH; i++) - { - if (b[i] == 0x00) - break; - else - SWSerial_Write(b[i]); - } -} - -#endif -