Compare commits

...

8 Commits

14 changed files with 1641 additions and 1490 deletions

149
TeensyDSP/DSP.cpp Normal file
View File

@ -0,0 +1,149 @@
//======================================================================
// DSP.cpp
//======================================================================
#include "DSP.h"
#include <Audio.h>
#include <i2c_t3.h>
//#include <Wire.h>
//#include <SPI.h>
//#include <SD.h>
//#include <SerialFlash.h>
#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
//======================================================================

42
TeensyDSP/DSP.h Normal file
View File

@ -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
//======================================================================

18
TeensyDSP/Debug.h Normal file
View File

@ -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

186
TeensyDSP/HamFuncs.h Normal file
View File

@ -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

141
TeensyDSP/Nextion.cpp Normal file
View File

@ -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]);
}

126
TeensyDSP/Nextion.h Normal file
View File

@ -0,0 +1,126 @@
#ifndef __Nextion_h__
#define __Nextion_h__
#include <Arduino.h>
#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

5
TeensyDSP/Sensors.cpp Normal file
View File

@ -0,0 +1,5 @@
#include "Sensors.h"
UBitxSensors Sensors;
ADC adc;

342
TeensyDSP/Sensors.h Normal file
View File

@ -0,0 +1,342 @@
#ifndef __Sensor_h__
#define __Sensor_h__
#include <ADC.h>
#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 <typename T, int N>
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<int, uBitxSensorsAvgSamples> sMeter;
TrailingAverage<float, uBitxSensorsAvgSamples> fwdPwr;
TrailingAverage<float, uBitxSensorsAvgSamples> revPwr;
TrailingAverage<float, uBitxSensorsAvgSamples> vswr;
TrailingAverage<float, uBitxSensorsAvgSamples> supply;
};
extern UBitxSensors Sensors;
#endif

45
TeensyDSP/TR.cpp Normal file
View File

@ -0,0 +1,45 @@
//======================================================================
// TR.cpp
//======================================================================
#include <Arduino.h>
#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
//======================================================================

169
TeensyDSP/TR.h Normal file
View File

@ -0,0 +1,169 @@
//======================================================================
// TR.h
//======================================================================
#ifndef __TR_h__
#define __TR_h__
#include <Bounce2.h>
#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
//======================================================================

View File

@ -7,30 +7,23 @@ KD8CEC, Ian Lee
**********************************************************************/
#include <arduino.h>
#include <Arduino.h>
#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

File diff suppressed because it is too large Load Diff

View File

@ -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 <arduino.h>
#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<n-1;i++) {
if (i < j) {
tx = x[i];
ty = y[i];
x[i] = x[j];
y[i] = y[j];
x[j] = tx;
y[j] = ty;
}
k = i2;
while (k <= j) {
j -= k;
k >>= 1;
}
j += k;
}
/* Compute the FFT */
c1 = -1.0;
c2 = 0.0;
l2 = 1;
for (l=0;l<m;l++)
{
l1 = l2;
l2 <<= 1;
u1 = 1.0;
u2 = 0.0;
for (j=0;j<l1;j++)
{
for (i=j;i<n;i+=l2)
{
i1 = i + l1;
t1 = u1 * x[i1] - u2 * y[i1];
t2 = u1 * y[i1] + u2 * x[i1];
x[i1] = x[i] - t1;
y[i1] = y[i] - t2;
x[i] += t1;
y[i] += t2;
}
z = u1 * c1 - u2 * c2;
u2 = u1 * c2 + u2 * c1;
u1 = z;
}
c2 = sqrt((1.0 - c1) / 2.0);
if (dir == 1)
c2 = -c2;
c1 = sqrt((1.0 + c1) / 2.0);
}
/* Scaling for forward transform */
/*
if (dir == 1) {
for (i=0;i<n;i++) {
x[i] /= n;
y[i] /= n;
}
}
return 1;
*/
//return(TRUE);
}
double coeff;
void CalculateCoeff(uint8_t freqIndex)
{
float omega;
int targetFrequency = freqIndex * 50 + 300;
int k = (int) (0.5 + ((DECODE_MORSE_SAMPLESIZE * targetFrequency) / SAMPLE_PREQUENCY));
omega = (2.0 * PI * k) / DECODE_MORSE_SAMPLESIZE;
coeff = 2.0 * cos(omega);
}
//=====================================================================
//The CW Decode code refers to the site code below.
//https://k2jji.org/2014/09/18/arduino-base-cw-decoder/
//Some code has been modified, but the original comments remain intact.
// code below is optimal for use in Arduino.
//Thanks to OZ1JHM
//KD8CEC
//=====================================================================
///////////////////////////////////////////////////////////////////////
// CW Decoder made by Hjalmar Skovholm Hansen OZ1JHM VER 1.01 //
// Feel free to change, copy or what ever you like but respect //
// that license is http://www.gnu.org/copyleft/gpl.html //
// Discuss and give great ideas on //
// https://groups.yahoo.com/neo/groups/oz1jhm/conversations/messages //
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
// Read more here http://en.wikipedia.org/wiki/Goertzel_algorithm //
// if you want to know about FFT the http://www.dspguide.com/pdfbook.htm //
///////////////////////////////////////////////////////////////////////////
//int magnitudelimit = 50;
//int magnitudelimit_low = 50;
int magnitudelimit = 30;
int magnitudelimit_low = 30;
char realstate = LOW;
char realstatebefore = LOW;
char filteredstate = LOW;
char filteredstatebefore = LOW;
long laststarttime = 0;
int nbtime = 6; /// ms noise blanker
long starttimehigh;
long highduration;
long lasthighduration;
long hightimesavg;
long lowtimesavg;
long startttimelow;
long lowduration;
char code[20];
uint8_t stop = LOW;
int wpm;
uint8_t cwDecodeHz = 9;
extern void SendCommandStr(char varIndex, char* sendValue);
void printascii(int asciinumber)
{
char rstDecode[4] = {0, 0, 0, 0};
if (asciinumber == 3)
{
}
else if (asciinumber == 4)
{
}
else if (asciinumber == 6)
{
}
else
{
rstDecode[0] = asciinumber;
}
SendCommandStr('b', rstDecode);
//Serial.write(asciinumber);
//if (writeCount++ > 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;
}

View File

@ -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.h>
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