ubitx-v5x/TeensyDSP/TeensyDSP.ino

1008 lines
24 KiB
Arduino
Raw Normal View History

2018-08-04 02:23:20 +00:00
/*
FFT, CW Decode for uBITX
KD8CEC, Ian Lee
2019-04-11 13:37:24 +00:00
Version : 0.8
2018-08-04 02:23:20 +00:00
-----------------------------------------------------------------------
License : See fftfunctions.cpp for FFT and CW Decode.
**********************************************************************/
#include <i2c_t3.h> // using i2c_t3 library for multiple I2C busses
2018-08-04 02:23:20 +00:00
#include <EEPROM.h>
2021-01-21 05:26:38 +00:00
#include "TeensyDSP.h"
2018-08-04 02:23:20 +00:00
#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
//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', };
2018-08-04 02:23:20 +00:00
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
//===================================================================
//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)
//
//===================================================================
2018-08-04 02:23:20 +00:00
#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];
2018-08-04 02:23:20 +00:00
#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;
/*!
@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)
2018-08-04 02:23:20 +00:00
{
if (varType == SWS_HEADER_STR_TYPE)
{
softSTRHeader[4] = varIndex;
for (unsigned i = 0; i < sizeof(softSTRHeader)/sizeof(softSTRHeader[0]); i++)
Serial1.write(softSTRHeader[i]);
2018-08-04 02:23:20 +00:00
}
else
{
softINTHeader[4] = varIndex;
for (unsigned i = 0; i < sizeof(softINTHeader)/sizeof(softINTHeader[0]); i++)
Serial1.write(softINTHeader[i]);
2018-08-04 02:23:20 +00:00
}
}
/*!
@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)
2018-08-04 02:23:20 +00:00
{
sendHeader(SWS_HEADER_INT_TYPE, varIndex);
2018-08-04 02:23:20 +00:00
memset(softTemp, 0, 20);
ultoa(sendValue, softTemp, DEC);
Serial1.print(softTemp);
Serial1.write(0xff);
Serial1.write(0xff);
Serial1.write(0xff);
2018-08-04 02:23:20 +00:00
}
/*!
@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)
2018-08-04 02:23:20 +00:00
{
sendHeader(SWS_HEADER_INT_TYPE, varIndex);
2018-08-04 02:23:20 +00:00
memset(softTemp, 0, 20);
ltoa(sendValue, softTemp, DEC);
Serial1.print(softTemp);
Serial1.write(0xff);
Serial1.write(0xff);
Serial1.write(0xff);
2018-08-04 02:23:20 +00:00
}
/*!
@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)
2018-08-04 02:23:20 +00:00
{
sendHeader(SWS_HEADER_STR_TYPE, varIndex);
2018-08-04 02:23:20 +00:00
Serial1.print(sendValue);
Serial1.write('\"');
Serial1.write(0xFF);
Serial1.write(0xFF);
Serial1.write(0xFF);
2018-08-04 02:23:20 +00:00
}
2019-04-11 13:37:24 +00:00
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)
2018-08-04 02:23:20 +00:00
{
softBuff1Num[4] = varIndex;
softBuff1Num[10] = sendValue + 0x30; // convert to character digit
2018-08-04 02:23:20 +00:00
for (unsigned i = 0; i < sizeof(softBuff1Num)/sizeof(softBuff1Num[0]); i++)
Serial1.write(softBuff1Num[i]);
2018-08-04 02:23:20 +00:00
}
//=======================================================
//END OF Nextion Protocol
//=======================================================
int i2cCommand = 0;
2018-08-04 02:23:20 +00:00
void CalculateCoeff(uint8_t freqIndex);
char forwardBuff[MAX_FORWARD_BUFF_LENGTH + 1];
static int nowBuffIndex = 0;
2018-08-04 02:23:20 +00:00
static char etxCount = 0;
static char nowSendingProtocol = 0;
uint8_t SMeterToUartSend = 0; //0 : Send, 1: Idle
uint8_t SMeterToUartIdleCount = 0;
#define SMeterToUartInterval 4
char DSPType = 1; //0 : Not Use, 1 : FFT, 2 : Morse Decoder, 3 : RTTY Decoder
char FFTToUartIdleCount = 0;
#define FFTToUartInterval 2
elapsedMillis sinceForward = 0;
2018-08-04 02:23:20 +00:00
uint8_t responseCommand = 0; //
uint8_t TXStatus = 0; //0:RX, 1:TX
void responseConfig()
2018-08-04 02:23:20 +00:00
{
if (responseCommand == 2)
{
unsigned long returnValue = 0;
if (DSPType == 0)
{
returnValue = 94; //None
}
else if (DSPType == 1)
{
returnValue = 95; //Spectrum (FFT) mode
}
else if (DSPType == 2)
{
returnValue = 100 + cwDecodeHz;
}
returnValue = returnValue << 8;
returnValue = returnValue | (SMeterToUartSend & 0xFF);
returnValue = returnValue << 8;
uint8_t tmpValue = 0;
if (magnitudelimit_low > 255)
tmpValue = 255;
else if (magnitudelimit_low < 1)
tmpValue = 0;
else
tmpValue = magnitudelimit_low;
returnValue = returnValue | (tmpValue & 0xFF);
sendCommandUL('v', returnValue); //Return data
sendCommandUL('g', 0x6A); //Return data
2018-08-04 02:23:20 +00:00
}
responseCommand = 0;
}
//Result : if found .val=, 1 else 0
/*!
@brief Parse commands...
*/
char commandParser(int lastIndex)
2018-08-04 02:23:20 +00:00
{
//Analysing Forward data
2018-08-04 02:23:20 +00:00
//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
//pm.vv.val=3848953628\xFF\xFF\xFF
//1234567890XXX
//
int startIndex = 0;
//Loop back command has 13 ~ 23
if (lastIndex < 13)
{
return 0;
}
//Protocol MAX Length : 22
if (lastIndex >= 22)
{
startIndex = lastIndex - 22;
}
else
{
startIndex = 0;
}
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
2018-08-04 02:23:20 +00:00
{
uint8_t command1 = forwardBuff[i-6]; //v
uint8_t command2 = forwardBuff[i-5]; //v
2018-08-04 02:23:20 +00:00
// i-4 //.
forwardBuff[lastIndex - 2] = 0;
long commandVal=atol(&forwardBuff[i + 1]);
uint8_t *readBuff = (uint8_t *)&commandVal;
2018-08-04 02:23:20 +00:00
//Loop Back
if (command1 == 'v' && command2 == 'v')
{
int calcChecksum = readBuff[0] + readBuff[1] + readBuff[2];
2018-08-04 02:23:20 +00:00
calcChecksum = calcChecksum % 256;
//Correct Checksum and Receiver is DSP Moudle protocol v1.0
if (calcChecksum == readBuff[3] && readBuff[2] == 0x6A)
2018-08-04 02:23:20 +00:00
{
//Serial1.print("Correct Checksum Command : ");
//Serial1.println(readBuff[1]);
uint8_t cmd1 = readBuff[1];
2018-08-04 02:23:20 +00:00
if (cmd1 == 94)
{
DSPType = 0;
EEPROM.put(EEPROM_DSPTYPE, DSPType);
}
else if (cmd1 == 95)
{
//Serial1.println("Spectrum Mode");
2018-08-04 02:23:20 +00:00
DSPType = 1;
EEPROM.put(EEPROM_DSPTYPE, DSPType);
}
else if (cmd1 >= 100 && cmd1 <= 145)
{
cwDecodeHz = cmd1 - 100;
CalculateCoeff(cwDecodeHz);
DSPType = 2;
EEPROM.put(EEPROM_DSPTYPE, DSPType);
EEPROM.put(EEPROM_CW_FREQ, cwDecodeHz);
}
else if (cmd1 > 1 && cmd1 <= 5) //2~5 : Request Configuration
{
responseCommand = cmd1;
}
else if (cmd1 == 50 || cmd1 == 51) //Set Configuration
{
SMeterToUartSend = (cmd1 == 51);
EEPROM.put(EEPROM_SMETER_UART, SMeterToUartSend);
}
else if (cmd1 >= 146 && cmd1 <= 156 )
{
//Save Mode
magnitudelimit_low = (cmd1 - 146) * 10;
EEPROM.put(EEPROM_CW_MAG_LOW, magnitudelimit_low);
} //end of if
} //end of check Checksum
} //end of check Protocol (vv)
else if (command1 == 'c' && command2 == 't') //TX, RX
{
if (commandVal == 0) //RX
{
TXStatus = 0;
SMeterToUartIdleCount = 0;
}
else if (commandVal == 1) //TX
{
TXStatus = 1;
SMeterToUartIdleCount = 0;
}
}
return 1;
} //end of check Protocol (.val)
} //end of for
//Not found Protocol (.val=
return 0;
}
2018-08-04 02:23:20 +00:00
//#define PROTOCOL_TIMEOUT = 100
/*!
@brief Forwards serial data from the RX line to the TX line.
*/
void forwardData(void)
2018-08-04 02:23:20 +00:00
{
char recvChar;
2018-08-04 02:23:20 +00:00
if (Serial1.available() > 0)
2018-08-04 02:23:20 +00:00
{
Serial1.flush();
// Check RX buffer for available data.
while (Serial1.available() > 0)
2018-08-04 02:23:20 +00:00
{
recvChar = char(Serial1.read());
2018-08-04 02:23:20 +00:00
forwardBuff[nowBuffIndex] = recvChar;
2018-08-04 02:23:20 +00:00
if (recvChar == 0xFF) // found ETX
2018-08-04 02:23:20 +00:00
{
etxCount++; // Nextion protocol, ETX: 0xFF, 0xFF, 0xFF
2018-08-04 02:23:20 +00:00
if (etxCount >= 3)
{
// Finished Protocol
if (commandParser(nowBuffIndex) == 1)
2018-08-04 02:23:20 +00:00
{
nowSendingProtocol = 0; // finished 1 set command
2018-08-04 02:23:20 +00:00
etxCount = 0;
nowBuffIndex = 0;
}
}
}
else
{
nowSendingProtocol = 1; // sending data
etxCount = 0;
2018-08-04 02:23:20 +00:00
}
Serial1.write(recvChar);
sinceForward = 0;
2018-08-04 02:23:20 +00:00
nowBuffIndex++;
if (nowBuffIndex > MAX_FORWARD_BUFF_LENGTH - 2)
2018-08-04 02:23:20 +00:00
{
nowBuffIndex = 0;
}
}
2018-08-04 02:23:20 +00:00
Serial1.flush();
}
2018-08-04 02:23:20 +00:00
else
{
// check timeout
2018-08-04 02:23:20 +00:00
}
}
void SendMeterData(uint8_t isSend)
2018-08-04 02:23:20 +00:00
{
//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;
if (isSend == 1)
{
if (L_scaledSMeter != scaledSMeter)
{
L_scaledSMeter = scaledSMeter;
sendCommand1Num(CMD_SMETER, L_scaledSMeter);
2018-08-04 02:23:20 +00:00
}
}
}
void grepADC(void)
2018-08-04 02:23:20 +00:00
{
int readValue = 0;
2018-08-04 02:23:20 +00:00
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();
readValue = analogRead(SIGNAL_METER_ADC);;
FFTReal[i] = readValue;
2018-08-04 02:23:20 +00:00
FFTImag[i] = 0;
if (ADC_MAX < readValue)
2018-08-04 02:23:20 +00:00
{
ADC_MAX = readValue;
2018-08-04 02:23:20 +00:00
}
if (ADC_MIN > readValue)
2018-08-04 02:23:20 +00:00
{
ADC_MIN = readValue;
2018-08-04 02:23:20 +00:00
}
while(micros() < (currentms + SAMPLE_INTERVAL)){}
} //end of for
}
void sendFFTData(void)
2018-08-04 02:23:20 +00:00
{
int readValue = 0;
2018-08-04 02:23:20 +00:00
for (int i = 0; i < 11; i++)
Serial1.write(responseHeader[i]);
2018-08-04 02:23:20 +00:00
for(int i = 1; i < 64; i++)
{
readValue = (int)(FFTReal[i]);
if (readValue < 0)
2018-08-04 02:23:20 +00:00
{
readValue = 0;
2018-08-04 02:23:20 +00:00
}
else if (readValue>255)
2018-08-04 02:23:20 +00:00
{
readValue=255;
2018-08-04 02:23:20 +00:00
}
Serial1.write(hexCodes[readValue >> 4]);
Serial1.write(hexCodes[readValue & 0xf]);
2018-08-04 02:23:20 +00:00
}
for (int i = 0; i < 4; i++)
Serial1.write(responseFooter[i]);
2018-08-04 02:23:20 +00:00
}
void setup()
{
// load configuration
2018-08-04 02:23:20 +00:00
EEPROM.get(EEPROM_DSPTYPE, DSPType);
if (DSPType > 5)
{
DSPType = 1;
}
// signal meter
2018-08-04 02:23:20 +00:00
EEPROM.get(EEPROM_SMETER_UART, SMeterToUartSend);
if (SMeterToUartSend > 2)
{
SMeterToUartSend = 1;
}
// something with CW decoding...
2018-08-04 02:23:20 +00:00
EEPROM.get(EEPROM_CW_FREQ, cwDecodeHz);
if (cwDecodeHz > 40 || cwDecodeHz < 1)
{
cwDecodeHz = 9;
}
// EEPROM_CW_MAG_LOW
2018-08-04 02:23:20 +00:00
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:
// 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...");
2018-08-04 02:23:20 +00:00
}
void i2cReceiveEvent(size_t numBytes)
2018-08-04 02:23:20 +00:00
{
int readCommand = 0;
2018-08-04 02:23:20 +00:00
while (Wire1.available() > 0) // for Last command
2018-08-04 02:23:20 +00:00
{
readCommand = Wire1.read();
2018-08-04 02:23:20 +00:00
}
if (0x50 <= readCommand && readCommand <= 0x59)
{
i2cCommand = readCommand;
2018-08-04 02:23:20 +00:00
}
}
void i2cRequestEvent(void)
2018-08-04 02:23:20 +00:00
{
int maxValue = 0;
int minValue = 30000;
int readValue = 0;
2018-08-04 02:23:20 +00:00
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)
2018-08-04 02:23:20 +00:00
{
Wire1.write(scaledSMeter);
2018-08-04 02:23:20 +00:00
}
else if (i2cCommand == I2CMETER_UNCALCS)
2018-08-04 02:23:20 +00:00
{
//Wire1.write(ADC_DIFF);
2018-08-04 02:23:20 +00:00
//8292Hz
for(int i=0; i < 7; i++)
{
curr = micros();
readValue = analogRead(SIGNAL_METER_ADC);;
2018-08-04 02:23:20 +00:00
if (readValue > maxValue)
2018-08-04 02:23:20 +00:00
{
maxValue = readValue;
2018-08-04 02:23:20 +00:00
}
if (readValue < minValue)
2018-08-04 02:23:20 +00:00
{
minValue = readValue;
2018-08-04 02:23:20 +00:00
}
while(micros() < (curr + 127)){} //8Khz / 7
} //end of for
readValue = maxValue - minValue;
readValue = readValue * readValue;
//readValue = readValue / 2;
if (readValue < 0)
2018-08-04 02:23:20 +00:00
{
readValue = 0;
2018-08-04 02:23:20 +00:00
}
else if (readValue > 255)
2018-08-04 02:23:20 +00:00
{
readValue = 255;
2018-08-04 02:23:20 +00:00
}
Wire1.write(readValue);
2018-08-04 02:23:20 +00:00
}
else if (i2cCommand == I2CMETER_CALCP)
2018-08-04 02:23:20 +00:00
{
readValue = analogRead(POWER_METER_ADC); //POWER
Wire1.write(readValue);
2018-08-04 02:23:20 +00:00
}
else if (i2cCommand == I2CMETER_CALCR) //SWR
2018-08-04 02:23:20 +00:00
{
readValue = analogRead(SWR_METER_ADC);
Wire1.write(readValue);
2018-08-04 02:23:20 +00:00
}
}
extern void Decode_Morse(float magnitude);
extern double coeff;
#define LAST_TIME_INTERVAL 159
2019-04-11 13:37:24 +00:00
//int SWRAdcValue = 0;
float adcFWD = 0;
float adcRWD = 0;
uint16_t adjustPower = 230;
float swrMeasured;
int clcCount = 0;
2018-08-04 02:23:20 +00:00
// for boot delay, a lot of data to transfer
// Delay 2.5 Sec
2018-08-06 02:58:41 +00:00
byte isBooted = 0;
2018-08-04 02:23:20 +00:00
void loop()
{
char isProcess = 0; // 0: init, 1: complete ADC sampling, 2: complete FFT
2018-08-04 02:23:20 +00:00
isProcess = 0;
2018-08-06 02:58:41 +00:00
forwardData();
2018-08-06 02:58:41 +00:00
if (isBooted < 100)
{
//Delay 20msec
for (int i = 0; i < 20; i++)
{
forwardData();
2018-08-06 02:58:41 +00:00
delay(1);
}
isBooted++;
return;
}
2018-08-04 02:23:20 +00:00
//===========================================
//TRANSCEIVER STATUS : RX
//===========================================
if (TXStatus == 1) //TX Mode
{
2019-04-11 13:37:24 +00:00
/*
int readValue = 0;
2018-08-04 02:23:20 +00:00
SMeterToUartIdleCount++;
if (SMeterToUartIdleCount > 130) //SWR
{
//SWR Send
sendCommandL('m', SWRAdcValue);
sendCommand1Num('m', 3);
2018-08-04 02:23:20 +00:00
SMeterToUartIdleCount = 0;
}
else if (SMeterToUartIdleCount == 100) //POWER 500msec interval
{
readValue = analogRead(POWER_METER_ADC );
2018-08-04 02:23:20 +00:00
SWRAdcValue = analogRead(SWR_METER_ADC);
sendCommandL('m', readValue);
sendCommand1Num('m',2);
2018-08-04 02:23:20 +00:00
//PWR Send
}
2019-04-11 13:37:24 +00:00
*/
//************************************************
//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();
2018-08-04 02:23:20 +00:00
2019-04-11 13:37:24 +00:00
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;
}
else
{
swrMeasured = ((1 + Vratio)/ (1 - Vratio));
}
//For Version 0.8
//Send SWR Information using Receive Signal Meter Protocol
scaledSMeter = (int)(swrMeasured + 0.5);
if (scaledSMeter > 9)
{
scaledSMeter = 9;
}
if (L_scaledSMeter != scaledSMeter)
{
L_scaledSMeter = scaledSMeter;
sendCommand1Num(CMD_SMETER, L_scaledSMeter);
2019-04-11 13:37:24 +00:00
}
//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);
2019-04-11 13:37:24 +00:00
//SMeterToUartIdleCount = 0;
//Send Power Information
int readValue = (int)(PWR * 100);
sendCommandL('m', readValue);
sendCommand1Num('m',2);
2019-04-11 13:37:24 +00:00
//Delay 250msec ~ 500msec for Nextion LCD Processing (using m protocol)
for (int i = 0; i < 10; i++)
{
forwardData();
2019-04-11 13:37:24 +00:00
if (TXStatus != 1) //if TX -> RX break
{
break;
}
delay(25);
} //end of delay time
//Send SWR
readValue = (int)(swrMeasured * 100);
sendCommandL('m', readValue);
sendCommand1Num('m', 3);
2019-04-11 13:37:24 +00:00
//delay(50);
//return;
}
delay(30);
2018-08-04 02:23:20 +00:00
return; //Do not processing ADC, FFT, Decode Morse or RTTY, only Power and SWR Data Return
}
//===========================================
//TRANSCEIVER STATUS : RX
//===========================================
//===========================================
// ADC Sampling
//===========================================
if (nowSendingProtocol == 0) //Idle Status
{
nowADCSampling = 1; //Mark => Start Sampling
grepADC();
2018-08-04 02:23:20 +00:00
//if(nowADCSampling == 2) //Marked ? While ADC Sampling, receive I2C
//{
// nowADCSampling = 0; //Mark => Finish Sampling
// i2cRequestEvent();
2018-08-04 02:23:20 +00:00
//}
nowADCSampling = 0; //Mark => Finish Sampling
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
}
forwardData();
2018-08-04 02:23:20 +00:00
//===========================================
// Send Signal Meter to UART
//===========================================
if (SMeterToUartSend == 1) //SMeter To Uart Send
{
//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();
2018-08-04 02:23:20 +00:00
//Check Response Command
if (responseCommand > 0 && sinceForward > LAST_TIME_INTERVAL)
2018-08-04 02:23:20 +00:00
{
responseConfig();
2018-08-04 02:23:20 +00:00
}
//===================================================================================
// DSP Routine
//===================================================================================
if (DSPType == 1 && sinceForward > LAST_TIME_INTERVAL) // spectrum: FFT => send To UART
2018-08-04 02:23:20 +00:00
{
FFTToUartIdleCount = 0;
if (isProcess == 1)
{
FFT(FFTReal, FFTImag, SAMPLESIZE, 7);
isProcess = 2;
}
forwardData();
2018-08-04 02:23:20 +00:00
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();
2018-08-04 02:23:20 +00:00
if (isProcess == 3)
{
if (nowSendingProtocol == 0) //Idle Status
{
sendFFTData();
2018-08-04 02:23:20 +00:00
}
}
}
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++)
2018-08-04 02:23:20 +00:00
{
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
//======================================================================