Added WSPR and Reduce Program size

This commit is contained in:
phdlee 2018-03-09 22:02:10 +09:00
parent fb2c9d2cc3
commit a26978f573
8 changed files with 443 additions and 95 deletions

View File

@ -297,7 +297,7 @@ void controlAutoCW(){
displayScrolStep = 0;
}
printLineFromEEPRom(0, 2, cwStartIndex + displayScrolStep + CW_DATA_OFSTADJ, cwEndIndex + CW_DATA_OFSTADJ);
printLineFromEEPRom(0, 2, cwStartIndex + displayScrolStep + CW_DATA_OFSTADJ, cwEndIndex + CW_DATA_OFSTADJ, 0);
byte diplayAutoCWLine = 0;
if ((displayOption1 & 0x01) == 0x01)

79
ubitx_20/ubitx.h Normal file
View File

@ -0,0 +1,79 @@
/*************************************************************************
header file for C++ by KD8CEC
-----------------------------------------------------------------------------
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
**************************************************************************/
#define WSPR_COUNT 443 //WSPR_MESSAGE_COUNT
#define WSPR_MESSAGE1 444 //
#define WSPR_MESSAGE2 490 //
#define WSPR_MESSAGE3 536 //
#define WSPR_MESSAGE4 582 //
#define WSPR_BAND_COUNT 3
#define TX_SSB 0
#define TX_CW 1
extern void printLine1(const char *c);
extern void printLine2(const char *c);
extern void printLineF(char linenmbr, const __FlashStringHelper *c);
extern void printLineFromEEPRom(char linenmbr, char lcdColumn, byte eepromStartIndex, byte eepromEndIndex, char offsetType);
extern byte delay_background(unsigned delayTime, byte fromType);
extern int btnDown(void);
extern char c[30];
extern char b[30];
extern unsigned long frequency;
#define printLineF1(x) (printLineF(1, x))
#define printLineF2(x) (printLineF(0, x))
/**
* The second set of 16 pins on the Raduino's bottom connector are have the three clock outputs and the digital lines to control the rig.
* This assignment is as follows :
* Pin 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
* GND +5V CLK0 GND GND CLK1 GND GND CLK2 GND D2 D3 D4 D5 D6 D7
* These too are flexible with what you may do with them, for the Raduino, we use them to :
* - TX_RX line : Switches between Transmit and Receive after sensing the PTT or the morse keyer
* - CW_KEY line : turns on the carrier for CW
*/
#define TX_RX (7)
#define CW_TONE (6)
#define TX_LPF_A (5)
#define TX_LPF_B (4)
#define TX_LPF_C (3)
#define CW_KEY (2)
//we directly generate the CW by programmin the Si5351 to the cw tx frequency, hence, both are different modes
//these are the parameter passed to startTx
#define TX_SSB 0
#define TX_CW 1
extern void si5351bx_init(void);
extern void si5351bx_setfreq(uint8_t clknum, uint32_t fout);
extern void si5351_set_calibration(int32_t cal);
extern void initOscillators(void);
extern void Set_WSPR_Param(void);
extern void TXSubFreq(unsigned long P2);
extern void startTx(byte txMode, byte isDisplayUpdate);
extern void stopTx(void);
extern void SendWSPRManage(void);
extern byte WsprMSGCount;

View File

@ -38,6 +38,7 @@
*/
#include <Wire.h>
#include <EEPROM.h>
#include "ubitx.h"
/**
The main chip which generates upto three oscillators of various frequencies in the
@ -589,7 +590,7 @@ void startTx(byte txMode, byte isDisplayUpdate){
updateDisplay();
}
void stopTx(){
void stopTx(void){
inTx = 0;
digitalWrite(TX_RX, 0); //turn off the tx
@ -1109,7 +1110,8 @@ void setup()
//Serial.begin(9600);
lcd.begin(16, 2);
printLineF(1, F("CECBT v1.04"));
//printLineF(1, F("CECBT v1.05"));
printLineF(1, F("CE v1.05_W"));
Init_Cat(38400, SERIAL_8N1);
initMeter(); //not used in this build
@ -1117,7 +1119,7 @@ void setup()
if (userCallsignLength > 0 && ((userCallsignLength & 0x80) == 0x80)) {
userCallsignLength = userCallsignLength & 0x7F;
printLineFromEEPRom(0, 0, 0, userCallsignLength -1); //eeprom to lcd use offset (USER_CALLSIGN_DAT)
printLineFromEEPRom(0, 0, 0, userCallsignLength -1, 0); //eeprom to lcd use offset (USER_CALLSIGN_DAT)
delay(500);
}
else {

View File

@ -32,14 +32,6 @@ void updateLine2Buffer(char isDirectCall)
if (ritOn)
{
strcpy(line2Buffer, "RitTX:");
/*
line2Buffer[0] = 'R';
line2Buffer[1] = 'i';
line2Buffer[2] = 't';
line2Buffer[3] = 'T';
line2Buffer[4] = 'X';
line2Buffer[5] = ':';
*/
//display frequency
tmpFreq = ritTxFrequency;

View File

@ -10,8 +10,7 @@
* - If the menu item is clicked on, then it is selected,
* - If the menu item is NOT clicked on, then the menu's prompt is to be displayed
*/
#define printLineF1(x) (printLineF(1, x))
#define printLineF2(x) (printLineF(0, x))
#include "ubitx.h"
//Current Frequency and mode to active VFO by KD8CEC
void FrequencyToVFO(byte isSaveFreq)
@ -64,11 +63,13 @@ void menuBand(int btn){
btnPressCount = 0;
if (tuneTXType > 0) { //Just toggle 0 <-> 2, if tuneTXType is 100, 100 -> 0 -> 2
tuneTXType = 0;
printLineF2(F("General mode"));
//printLineF2(F("General mode"));
printLineF2(F("General"));
}
else {
tuneTXType = 2;
printLineF2(F("Ham band mode"));
//printLineF2(F("Ham band mode"));
printLineF2(F("Ham band"));
}
delay_background(1000, 0);
printLine2ClearAndUpdate();
@ -179,7 +180,7 @@ void menuIFSSetup(int btn){
if (isIFShift == 1)
printLineF2(F("IF Shift Change?"));
else
printLineF2(F("IF Shift:Off, On?"));
printLineF2(F("IF Shift On?"));
}
else {
isIFShift = 1;
@ -219,9 +220,11 @@ void menuIFSSetup(int btn){
if (btnDown() || ifShiftValue == 0)
{
isIFShift = 0;
printLineF2(F("IF Shift is OFF"));
//printLineF2(F("IF Shift is OFF"));
//printLineF2(F("OFF"));
//clearLine2();
setFrequency(frequency);
delay_background(1500, 0);
//delay_background(1500, 0);
}
//menuOn = 0;
@ -339,7 +342,8 @@ void menuCHMemory(int btn, byte isMemoryToVfo){
if (selectChannel >= 20 || selectChannel <=-1)
{
strcpy(c, "Exit setup?");
//strcpy(c, "Exit setup?");
strcpy(c, "Exit?");
}
else
{
@ -603,9 +607,9 @@ void menuVfoToggle(int btn)
void menuRitToggle(int btn){
if (!btn){
if (ritOn == 1)
printLineF2(F("RIT:On, Off?"));
printLineF2(F("RIT Off?"));
else
printLineF2(F("RIT:Off, On?"));
printLineF2(F("RIT On?"));
}
else {
if (ritOn == 0){
@ -633,20 +637,21 @@ void menuSplitOnOff(int btn){
else {
if (splitOn == 1){
splitOn = 0;
printLineF2(F("Split Off!"));
//printLineF2(F("Split Off!"));
printLineF2(F("[OFF]"));
}
else {
splitOn = 1;
if (ritOn == 1)
ritOn = 0;
printLineF2(F("Split On!"));
//printLineF2(F("Split On!"));
printLineF2(F("[ON]"));
}
menuClearExit(500);
}
}
//Function to disbled transmission
//by KD8CEC
void menuTxOnOff(int btn, byte optionType){
@ -756,23 +761,29 @@ void menuCWSpeed(int btn){
menuClearExit(1000);
}
void displayEmptyData(void){
printLineF2(F("Empty data"));
delay_background(2000, 0);
}
//Builtin CW Keyer Logic by KD8CEC
void menuCWAutoKey(int btn){
if (!btn){
printLineF2(F("CW AutoKey Mode?"));
return;
printLineF2(F("Memory Keyer"));
return;
}
//Check CW_AUTO_MAGIC_KEY and CW Text Count
EEPROM.get(CW_AUTO_COUNT, cwAutoTextCount);
if (EEPROM.read(CW_AUTO_MAGIC_KEY) != 0x73 || cwAutoTextCount < 1)
{
printLineF2(F("Empty CW data"));
delay_background(2000, 0);
displayEmptyData();
return;
}
printLineF1(F("Press PTT to Send"));
//printLineF1(F("Press PTT to Send"));
printLineF1(F("PTT to Send"));
delay_background(500, 0);
updateDisplay();
beforeCWTextIndex = 255; //255 value is for start check
@ -780,6 +791,27 @@ void menuCWAutoKey(int btn){
menuOn = 0;
}
//Standalone WSPR Beacone
void menuWSPRSend(int btn){
if (!btn){
printLineF2(F("WSPR Beacon"));
return;
}
WsprMSGCount = EEPROM.read(WSPR_COUNT);
if (WsprMSGCount < 1)
{
displayEmptyData();
return;
}
SendWSPRManage();
menuClearExit(1000);
}
//Modified by KD8CEC
void menuSetupCwDelay(int btn){
int knob = 0;
@ -836,12 +868,6 @@ void menuSetupTXCWInterval(int btn){
}
printLineF1(F("Press, set Delay"));
/*
strcpy(b, "Start Delay:");
itoa(tmpTXCWInterval,c, 10);
strcat(b, c);
printLine2(b);
*/
delay_background(300, 0);
while(!btnDown()){
@ -1261,8 +1287,6 @@ void doMenu(){
while (!btnDown())
{
//Check_Cat(0); //To prevent disconnections
//delay(50); //debounce
delay_background(50, 0);
if (isNeedDisplay) {
@ -1307,42 +1331,87 @@ void doMenu(){
btnState = btnDown();
if (i > 0){
if (modeCalibrate && select + i < 220)
if (modeCalibrate && select + i < 240)
select += i;
if (!modeCalibrate && select + i < 120)
if (!modeCalibrate && select + i < 130)
select += i;
}
//if (i < 0 && select - i >= 0)
if (i < 0 && select - i >= -10)
select += i; //caught ya, i is already -ve here, so you add it
if (select < -5)
menuExit(btnState);
else if (select < 10)
menuBand(btnState);
else if (select < 20)
menuVfoToggle(btnState);
else if (select < 30)
menuSelectMode(btnState);
else if (select < 40)
menuRitToggle(btnState);
else if (select < 50)
menuIFSSetup(btnState);
else if (select < 60)
menuCWSpeed(btnState);
else if (select < 70)
menuSplitOnOff(btnState); //SplitOn / off
else if (select < 80)
menuCHMemory(btnState, 0); //VFO to Memroy
else if (select < 90)
menuCHMemory(btnState, 1); //Memory to VFO
else if (select < 100)
menuCWAutoKey(btnState);
else if (select < 110)
menuSetup(btnState);
else if (select < 120)
menuExit(btnState);
//if -> switch reduce program memory 200byte
switch (select / 10)
{
case 0 :
menuBand(btnState);
break;
case 1 :
menuVfoToggle(btnState);
break;
case 2 :
menuSelectMode(btnState);
break;
case 3 :
menuRitToggle(btnState);
break;
case 4 :
menuIFSSetup(btnState);
break;
case 5 :
menuCWSpeed(btnState);
break;
case 6 :
menuSplitOnOff(btnState); //SplitOn / off
break;
case 7 :
menuCHMemory(btnState, 0); //VFO to Memroy
break;
case 8 :
menuCHMemory(btnState, 1); //Memory to VFO
break;
case 9 :
menuCWAutoKey(btnState);
break;
case 10 :
menuWSPRSend(btnState);
break;
case 11 :
menuSetup(btnState);
break;
case 12 :
menuExit(btnState);
break;
case 13 :
menuSetupCalibration(btnState); //crystal
break;
case 14 :
menuSetupCarrier(btnState); //lsb
break;
case 15 :
menuSetupCWCarrier(btnState); //lsb
break;
case 16 :
menuSetupCwTone(btnState);
break;
case 17 :
menuSetupCwDelay(btnState);
break;
case 18 :
menuSetupTXCWInterval(btnState);
break;
case 19 :
menuSetupKeyType(btnState);
break;
case 20 :
menuADCMonitor(btnState);
break;
case 21 :
menuTxOnOff(btnState, 0x01); //TX OFF / ON
break;
default :
menuExit(btnState); break;
}
/*
else if (select < 130 && modeCalibrate)
menuSetupCalibration(btnState); //crystal
@ -1366,30 +1435,6 @@ void doMenu(){
menuExit(btnState);
*/
else if (modeCalibrate)
{
if (select < 130)
menuSetupCalibration(btnState); //crystal
else if (select < 140)
menuSetupCarrier(btnState); //lsb
else if (select < 150)
menuSetupCWCarrier(btnState); //lsb
else if (select < 160)
menuSetupCwTone(btnState);
else if (select < 170)
menuSetupCwDelay(btnState);
else if (select < 180)
menuSetupTXCWInterval(btnState);
else if (select < 190)
menuSetupKeyType(btnState);
else if (select < 200)
menuADCMonitor(btnState);
else if (select < 210)
menuTxOnOff(btnState, 0x01); //TX OFF / ON
else if (select < 220)
menuExit(btnState);
}
Check_Cat(0); //To prevent disconnections
}

View File

@ -1,3 +1,19 @@
/************************************************************************************
* KD8CEC
* kd8cec@gmail.com http://www.hamskey.com
*
* Merge two SI5351 Librarys
* KE7ER's fixed vco and variable Clocks Configure values
* G3ZIL's fixed Clock Configure Value and variable VCO
* * I have combined the two libraries above. All licenses follow the above library.
*
* PLL-A is generated by fixing 850Mhz clock. All output clocks use PLL-A to
* generate the frequency. This is the method used in QRP radios such as uBITX.
* When switching to WSPR transmission mode, PLL-B operates for the base frequency to transmit WSPR.
* The output clock channel that controls the frequency is connected to the PLL-B.
* The WSPR protocol is generated by changing the clock of the PLL-B.
************************************************************************************/
// ************* SI5315 routines - tks Jerry Gaffke, KE7ER ***********************
// An minimalist standalone set of Si5351 routines.
@ -119,5 +135,29 @@ void initOscillators(){
si5351bx_setfreq(0, cwmCarrier + (isIFShift ? ifShiftValue : 0));
}
//============================================================
// ADD FUNCTIONS by KD8CEC
//============================================================
uint8_t Wspr_Reg1[8] = {0xFF,0xFE, 0x00, 0, 0, 0, 0, 0}; //3, 4, 5, 6, 7
uint8_t Wspr_Reg2[8] = {0, 1, 0, 0, 0, 0, 0, 0}; //2, 3, 4
void Set_WSPR_Param(void)
{
i2cWrite(18, 128);
i2cWriten(34, Wspr_Reg1, 8);
i2cWriten(58, Wspr_Reg2, 8);
i2cWrite(177, 128);
i2cWrite(18, 111);
si5351bx_clken &= ~(1 << 2);
i2cWrite(3, si5351bx_clken);
}
void TXSubFreq(unsigned long P2)
{
i2cWrite(40, (P2 & 65280) >> 8);
i2cWrite(41, P2 & 255);
}

View File

@ -9,7 +9,7 @@
//#define printLineF2(x) (printLineF(0, x))
//returns true if the button is pressed
int btnDown(){
int btnDown(void){
if (digitalRead(FBUTTON) == HIGH)
return 0;
else
@ -173,7 +173,7 @@ void printLineF(char linenmbr, const __FlashStringHelper *c)
}
#define LCD_MAX_COLUMN 16
void printLineFromEEPRom(char linenmbr, char lcdColumn, byte eepromStartIndex, byte eepromEndIndex) {
void printLineFromEEPRom(char linenmbr, char lcdColumn, byte eepromStartIndex, byte eepromEndIndex, char offsetTtype) {
if ((displayOption1 & 0x01) == 0x01)
linenmbr = (linenmbr == 0 ? 1 : 0); //Line Toggle
@ -182,7 +182,7 @@ void printLineFromEEPRom(char linenmbr, char lcdColumn, byte eepromStartIndex, b
for (byte i = eepromStartIndex; i <= eepromEndIndex; i++)
{
if (++lcdColumn <= LCD_MAX_COLUMN)
lcd.write(EEPROM.read(USER_CALLSIGN_DAT + i));
lcd.write(EEPROM.read((offsetTtype == 0 ? USER_CALLSIGN_DAT : WSPR_MESSAGE1) + i));
else
break;
}

190
ubitx_20/ubitx_wspr.cpp Normal file
View File

@ -0,0 +1,190 @@
/**********************************************************************************
WSPR SENDER for uBITX by KD8CEC
Some of the code that sends WSPR referenced the code in G3ZIL.
Thanks to G3ZIL for sharing great code.
Due to the limited memory of uBITX, I have implemented at least only a few of the codes in uBITX.
Thanks for testing
Beta Tester :
-----------------------------------------------------------------------------
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
**********************************************************************************/
#include <arduino.h>
#include <EEPROM.h>
#include "ubitx.h"
//begin of test
byte WsprToneCode[164];
long lastTime=0;
unsigned long TX_MSNB_P2; // Si5351 register MSNB_P2 PLLB for Tx
unsigned long TX_P2; // Variable values for MSNB_P2 which defines the frequencies for the data
extern int enc_read(void);
byte WsprMSGCount = 0;
#define PTT (A3)
#define WSPR_BAND1 401
extern uint8_t Wspr_Reg1[8]; //3, 4, 5, 6, 7
extern uint8_t Wspr_Reg2[8]; //2, 3, 4
void SendWSPRManage()
{
int knob = 0;
byte knobPosition = 0;
char isNeedDisplayInfo = 0;
char nowSelectedIndex = 0;
char nowWsprStep = 0; //0 : select Message, 1 : select band, 2 : send
char selectedWsprMessageIndex = -1;
char selectedWsprBandIndex = -1;
unsigned long WsprTXFreq = 0;
unsigned int WsprMultiChan = 0;
unsigned long prevFreq;
char loopIndex;
delay_background(500, 0);
//Readed WsprMSGCount, WsprTone
while(1)
{
knob = enc_read();
if (knobPosition > 0 && knob < 0)
knobPosition--;
else if (knob > 0 && (knobPosition <= (nowWsprStep == 0 ? WsprMSGCount : WSPR_BAND_COUNT) * 10 -2))
knobPosition++;
nowSelectedIndex = knobPosition / 10;
if (nowWsprStep == 0) //select Message status
{
printLineF2(F("WSPR:"));
if (selectedWsprMessageIndex != nowSelectedIndex)
{
selectedWsprMessageIndex = nowSelectedIndex;
int wsprMessageBuffIndex = selectedWsprMessageIndex * 46;
//Display WSPR Name tag
printLineFromEEPRom(0, 6, wsprMessageBuffIndex, wsprMessageBuffIndex + 4, 1);
//Load WSPR Tonecode
//Read Tone Code
for (int i = 0; i < 41; i++)
{
byte readData = EEPROM.read(WSPR_MESSAGE1 + 5 + (wsprMessageBuffIndex) + i); //NAME TAG 5, MESSAGE 41 = 46
WsprToneCode[i * 4 + 0] = readData & 3;
WsprToneCode[i * 4 + 1] = (readData >> 2) & 3;
WsprToneCode[i * 4 + 2] = (readData >> 4) & 3;
WsprToneCode[i * 4 + 3] = (readData >> 6) & 3;
}
}
else if (btnDown())
{
nowWsprStep = 1; //Change Status to Select Band
knobPosition = 0;
nowSelectedIndex = 0;
delay_background(500, 0);
}
}
else if (nowWsprStep == 1)
{
//printLineF2(F("Select Band"));
if (selectedWsprBandIndex != nowSelectedIndex)
{
selectedWsprBandIndex = nowSelectedIndex;
int bandBuffIndex = WSPR_BAND1 + selectedWsprBandIndex * 14;
EEPROM.get(bandBuffIndex, WsprTXFreq);
EEPROM.get(bandBuffIndex + 4, WsprMultiChan);
/*
//3, 4, 5, 6, 7
Wspr_Reg1[3] = EEPROM.read(bandBuffIndex + 6);
Wspr_Reg1[4] = EEPROM.read(bandBuffIndex + 7);
Wspr_Reg1[5] = EEPROM.read(bandBuffIndex + 8);
Wspr_Reg1[6] = EEPROM.read(bandBuffIndex + 9);
Wspr_Reg1[7] = EEPROM.read(bandBuffIndex + 10);
*/
for (loopIndex = 3; loopIndex < 8; loopIndex++)
Wspr_Reg1[loopIndex] = EEPROM.read(bandBuffIndex + loopIndex + 3);
/*
Wspr_Reg2[2] = EEPROM.read(bandBuffIndex + 11);
Wspr_Reg2[3] = EEPROM.read(bandBuffIndex + 12);
Wspr_Reg2[4] = EEPROM.read(bandBuffIndex + 13);
*/
//2, 3, 4
for (loopIndex = 2; loopIndex < 5; loopIndex++)
Wspr_Reg2[loopIndex] = EEPROM.read(bandBuffIndex + loopIndex + 9);
TX_MSNB_P2 = ((unsigned long)Wspr_Reg1[5] & 0x0F) << 16 | ((unsigned long)Wspr_Reg1[6]) << 8 | Wspr_Reg1[7];
}
ltoa(WsprTXFreq, b, DEC);
if (digitalRead(PTT) == 0)
strcpy(c, "SEND:");
else
strcpy(c, "PTT->");
strcat(c, b);
printLine1(c);
if (digitalRead(PTT) == 0)
{
//printLineF1(F("Transmitting"));
//SEND WSPR
prevFreq = frequency;
frequency = WsprTXFreq;
startTx(TX_CW, 0);
//Start WSPR
Set_WSPR_Param();
digitalWrite(CW_KEY, 1);
for (int i = 0; i < 162; i++)
{ // Now this is the message loop
lastTime = millis(); // Store away the time when the last message symbol was sent
TX_P2 = TX_MSNB_P2 + WsprMultiChan * WsprToneCode[i]; // This represents the 1.46 Hz shift and is correct only for the bands specified in the array
TXSubFreq(TX_P2); // TX at the appropriate channel frequency for....
//if (btnDown())
// break;
while (millis() < lastTime + 683){} // .... 0,683 seconds
}
digitalWrite(CW_KEY, 0);
stopTx();
frequency = prevFreq;
selectedWsprBandIndex = -1;
} //end of PTT Check
else if (btnDown())
{
return;
}
} //end of status check
//delay_background(50, 1);
} //end of while
}