#include "JXWG_Defs.h"
#include "JXWG_Graphics.h"
void setup() {
//if you are using a simple encoder and 3x10K pullup resistors, apply this settings below
pinMode(PinA, INPUT);
pinMode(PinB, INPUT);
pinMode(PinS, INPUT);
//if you are using a simple encoder whitout 3x10K resistors use next tree row
//pinMode(PinA, INPUT_PULLUP);
//pinMode(PinB, INPUT_PULLUP);
//pinMode(PinS, INPUT_PULLUP);
//MOST PCB WELDED ENCODERS ALREADY HAVE PULLUP RESISTORS ON PIN A AND B BUT NOT ON SWITCH PIN
//then use the settings below
//pinMode(PinA, INPUT);
//pinMode(PinB, INPUT);
//pinMode(PinS, INPUT_PULLUP);
digitalWrite(PinA, HIGH);
digitalWrite(PinB, HIGH);
digitalWrite(PinS, HIGH);
pinMode(PinCoupling, OUTPUT); //Coupling Mode
Encoder.setDebounceDelay(5);
display.begin(SH1106_SWITCHCAPVCC, 0x3C); //initialize with the I2C addr 0x3C (for the 128x64)
display.clearDisplay();
//display.setRotation(2); //uncomment this line if you want to mount the display upside down
Wire.begin(); // join i2c bus as master
TWBR = 5; // freq=615kHz period=1.625uS
//Assigns encoder switch push event to interrupt 1 Pin 3 of Arduino
attachInterrupt(digitalPinToInterrupt(PinS), encoderSwitch, FALLING);
DDS_Init(); //Initialize the DDS module;
setConfig(); //Load config and set startup values
} //---> end setup()
void loop() {
JX_WaveGenerator_MAIN();
}
//-----------------------------------------------------------------------------------------------------------------------------------------
// JX WaveGenerator MAIN function
//-----------------------------------------------------------------------------------------------------------------------------------------
void JX_WaveGenerator_MAIN() {
byte encoderSpin = Encoder.rotate(); //Encoder rotation direction 1=CW, 2=CCW
byte encoderLongPush = Encoder.pushLong(1000); //encoder long push event
long lStep = 0; //current frequency step value
long wTime = 600000; //10 min
if (encoderPush) delay(250);
if (encoderSpin) {
cTime = millis();
} else {
if (millis() - cTime > wTime) {
ScreenSaver();
}
}
switch (mode) {
case LOGARITHMIC: //0
//-----------------------------------------------------------------------------------------------------------------------------------
// mode LOGARITHMIC: Encoder rotation change frequency in logaritmic step 1,10,100,1000,10000,100000 Hz
//-----------------------------------------------------------------------------------------------------------------------------------
if (encoderSpin) {
if (lFreq >= 1) {
lStep = AutoStep(lFreq, encoderSpin); //Calculate logaritmic step
} else if (_CouplingMode == OFF) { //if coupling mode is set to OFF
resetCouplingMode(); //set default coupling mode when Frequency is not 0
encoderSpin = 0; //skip first spin
}
if (encoderSpin == CW && lFreq <= 999999 - lStep) { //spin CW increment the frequency
lFreq += lStep;
}
if (encoderSpin == CCW && lFreq >= lStep + 1) { //spin CCW decrement the frequency
lFreq -= lStep;
}
DDS_FrequencySet(lFreq, Wave[_WaveType]); //send the frequency value to DDS module
displayFrequency(lFreq); //send formatted freq to display
lLastFreq = lFreq; //save current freq
}
//-----------------------------------------------------------------------------------------------------------------------------------
// workmode LOGARITHMIC: Encoder push switch to OPTIONS mode
//-----------------------------------------------------------------------------------------------------------------------------------
if (encoderPush) {
encoderPush = false; //Clear push flag
drawSymbol(1); //draw arrow symbol
selectIcon(0, WHITE); //draw a border around first icon
idx = 0; idy = 0; //reset pointers var
mode = OPTIONS; //go to mode OPTIONS
}
break; //end mode LOGARITHMIC
case SINGLEDIGIT: //1
//-------------------------------------------------------------------------------------------------------------
// submode SINGLEDIGIT: Encoder rotation move cursor left and right
//-------------------------------------------------------------------------------------------------------------
if (encoderSpin) {
if (encoderSpin == CW && idx < MAXDIGIT + 2) idx++; //clockwise increase pointer
if (encoderSpin == CCW && idx > 0) idx--; //counterclockwise decrease pointer
//------------------------------------------------------------------------------------------------------------
// when idx is from 0 to 5 select frequency digits
//------------------------------------------------------------------------------------------------------------
if (idx >= 0 && idx < MAXDIGIT) { //if the current position is within the digits
drawSymbol(0); //draw up arrow
selectDigit(idx); //show cursor at current position and delete previous
if (idx == 5) selectIcon(0, BLACK); //hide first icon selection
}
//------------------------------------------------------------------------------------------------------------
// when idx is from 6 to 8 select icons
//------------------------------------------------------------------------------------------------------------
if (idx >= MAXDIGIT && idx <= MAXDIGIT + 2) { //if the current position is beyond the digits
hideCursor(MAXDIGIT - 1); //hide cursor at last digit
drawSymbol(1); //draw dn arrow
selectIcon(idx - MAXDIGIT, WHITE); //select icon
}
}
//-----------------------------------------------------------------------------------------------------------------------------------
// submode SINGLEDIGIT: Encoder push event
//-----------------------------------------------------------------------------------------------------------------------------------
if (encoderPush) {
encoderPush = false;
//-------------------------------------------------------------------------------------------------------------
// if a digit from 0 to 5 are selected go to mode DIGITCHANGE
//-------------------------------------------------------------------------------------------------------------
if (idx <= MAXDIGIT - 1) {
hideCursor(idx); //flash cursor
delay(250); //for
selectDigit(idx); //visual confirmation
drawSymbol(2); //draw turn icon
mode = DIGITCHANGE; //change mode
}
//-------------------------------------------------------------------------------------------------------------
// otherwise there is an icon selected then go to OPTIONS
//-------------------------------------------------------------------------------------------------------------
else {
if (idx >= MAXDIGIT && idx <= MAXDIGIT + 2) {
idy = idx - MAXDIGIT;
selectOption(idy);
idy = options[idy];
}
}
}
break; //end mode SINGLEDIGIT
case SWEEP://2
//----------------------------------------------------------------------------------------------------------------
// workmode SWEEP: Encoder rotation move cursor left and right for option selection
//----------------------------------------------------------------------------------------------------------------
if (encoderSpin) {
if (encoderSpin == CW && idy < 2) idy++;
if (encoderSpin == CCW && idy > 0) idy--;
selectIcon(idy, WHITE);
}
if (encoderPush) {
//-----------------------------------------------------------------------------------------------------------------------------------
// workmode SWEEP: Encoder push go to OPTIONS, SWEEP OPTIONS or START/STOP sweep
//-----------------------------------------------------------------------------------------------------------------------------------
encoderPush = false;
switch (idy) {
case 0:
lFreq = atol(Freq);
selectOption(idy);
idy = options[idy];
delay(100);
if (_WorkMode != 2) displayFrequency(lLastFreq);
SweepReset();
break;
case 1:
lFreq = atol(Freq);
drawSymbol(9);
drawSymbol(1);
displaySweepIcons();
selectIcon(0, WHITE);
idy = 0;
displayFrequency(_Sweep(idy));
delay(100);
SweepReset();
mode = OPTSWEEP;
break;
case 2:
//** sweepStatus: STILL 0 (never started), 1 BREAK, 2 PAUSE **
if (sweepStatus == STILL || sweepStatus == PAUSE) {
drawSymbol(3); //draw pause icon
selectIcon(2, WHITE); //select icon
FrequencySweep(); //run sweep
}
else { //if paused
drawSymbol(4); //draw play icon
sweepStatus = PAUSE;
}
break;
}
}
if (sweepStatus == PAUSE) flashIcon(250); //flashing pause text
break; //end mode SWEEP
case OPTIONS://3
if (encoderLongPush) reset();
//-----------------------------------------------------------------------------------------------------------------------------------
// mode OPTIONS: Encoder spin select option to change (workmode, wavetype, couplingmode)
//-----------------------------------------------------------------------------------------------------------------------------------
if (encoderSpin) {
if (encoderSpin == CW && idy < 2) idy++;
if (encoderSpin == CCW && idy > 0) idy--;
selectIcon(idy, WHITE);
}
//-----------------------------------------------------------------------------------------------------------------------------------
// mode OPTIONS: Encoder push switch to relative mode
//-----------------------------------------------------------------------------------------------------------------------------------
if (encoderPush) {
encoderPush = false;
//selectIcon(idy, BLACK);
selectOption(idy);
hideCursor(0);
idy = options[idy];
}
break; //end mode OPTIONS
case OPTMODE://4
//-----------------------------------------------------------------------------------------------------------------------------------
// mode OPTMODE: Encoder spin select mode icons (logarithmic, singledigit, sweep)
//-----------------------------------------------------------------------------------------------------------------------------------
if (encoderSpin) {
if (encoderSpin == CW && idy < 2) idy++;
if (encoderSpin == CCW && idy > 0) idy--;
selectIcon(idy, WHITE);
}
//-----------------------------------------------------------------------------------------------------------------------------------
// mode OPTMODE: Encoder push select workmode to set (stored in option[0])
//-----------------------------------------------------------------------------------------------------------------------------------
if (encoderPush) {
encoderPush = false;
byte pMode = _WorkMode;
switch (idy) {
case 0:
hideCursor(0);
drawSymbol(0);
lFreq = lLastFreq;
displayFrequency(lFreq);
_setWorkMode(LOGARITHMIC);
break;
case 1:
drawSymbol(0);
selectDigit(0);
lFreq = lLastFreq;
displayFrequency(lFreq);
_setWorkMode(SINGLEDIGIT);
break;
case 2:
lLastFreq = lFreq;
displayFrequency(_SweepMin); //ready to start
_setWorkMode(SWEEP);
break;
}
mode = _WorkMode;
if (pMode != _WorkMode) saveConfig();
if (_CouplingMode == OFF) resetCouplingMode();
idx = 0;
drawAllIcons();
}
break; //end mode OPTMODE
case OPTWAVE://5
//----------------------------------------------------------------------------------------------------------------
// mode OPTWAVE: Encoder rotation move cursor left and right for wave selection (sqr, sin, tri)
//----------------------------------------------------------------------------------------------------------------
if (encoderSpin) {
if (encoderSpin == CW && idy < 2) idy++;
if (encoderSpin == CCW && idy > 0) idy--;
selectIcon(idy, WHITE);
}
//--------------------------------------------------------------------------------------------------------------------
// mode OPTWAVE: Encoder push set new wave type
//--------------------------------------------------------------------------------------------------------------------
if (encoderPush) {
encoderPush = false;
if (_WaveType != idy) {
_setWaveType(idy);
saveConfig();
}
UpdateFrequency(); //updates wavetype
drawAllIcons();
idx = 0;
mode = _WorkMode;
}
break; //end mode OPTWAVE
case OPTCOUP://6
//----------------------------------------------------------------------------------------------------------------
// mode OPTCOUP: Encoder rotation move cursor left and right for coupling mode selection
//----------------------------------------------------------------------------------------------------------------
if (encoderSpin) {
if (encoderSpin == CW && idy < 2) idy++;
if (encoderSpin == CCW && idy > 0) idy--;
selectIcon(idy, WHITE);
}
//--------------------------------------------------------------------------------------------------------------------
// mode OPTCOUP: Encoder push select current coupling mode
//--------------------------------------------------------------------------------------------------------------------
if (encoderPush) {
encoderPush = false;
setCouplingMode(idy);
drawAllIcons();
idx = 0;
mode = _WorkMode;
}
break; //end mode OPTCOUP
case OPTSWEEP://7
//--------------------------------------------------------------------------------------------------------------------
// mode OPTSWEEP: Encoder spin select sweep values to edit
//--------------------------------------------------------------------------------------------------------------------
if (encoderSpin) {
if (encoderSpin == CW && idy < 2) idy++; //clockwise increase pointer
if (encoderSpin == CCW && idy > 0) idy--; //counterclockwise decrease pointer
selectIcon(idy, WHITE); //select first icon
displayFrequency(_Sweep(idy)); //display current sweep value
}
if (encoderPush) {
encoderPush = false;
//--------------------------------------------------------------------------------------------------------------------
// mode OPTSWEEP: Encoder push confirm sweep values to edit
//--------------------------------------------------------------------------------------------------------------------
drawSymbol(0);
selectDigit(0);
selectIcon(idy, WHITE);
idx = 0;
displayFrequency(_Sweep(idy));
mode = SWEEPEDIT;
}
break; //end mode OPTSWEEP
case SWEEPEDIT://8
//--------------------------------------------------------------------------------------------------------------
// mode SWEEPEDIT: Encoder spin select digit to change
//--------------------------------------------------------------------------------------------------------------
if (encoderSpin) {
if (encoderSpin == CW && idx < MAXDIGIT - 1) idx++; //clockwise increase pointer
if (encoderSpin == CCW && idx > 0) idx--; //counterclockwise decrease pointer
selectDigit(idx);
}
//--------------------------------------------------------------------------------------------------------------
// mode SWEEPEDIT: Encoder longpush exit from edit and return to SWEEP
//--------------------------------------------------------------------------------------------------------------
if (encoderLongPush == LONGPUSH) {
encoderPush = false;
drawAllIcons();
displayFrequency(_SweepMin);
hideCursor(idx);
_setWorkMode(SWEEP);
SweepReset();
mode = _WorkMode;
delay(250);
}
if (encoderPush) {
encoderPush = false;
//-------------------------------------------------------------------------------------------------------------
// mode SWEEPEDIT: Encoder push go to mode DIGITCHANGE
//-------------------------------------------------------------------------------------------------------------
hideCursor(idx); //flash cursor
delay(250); //for
selectDigit(idx); //visual confirmation
drawSymbol(2); //draw turn icon
mode = DIGITCHANGE; //change mode
}
break;//end mode SWEEPEDIT
case DIGITCHANGE://9
//---------------------------------------------------------------------------------------------------------
// mode DIGITCHANGE: Encoder longpush exit from DIGITCHANGE when in SWEEP mode
//---------------------------------------------------------------------------------------------------------
if (encoderLongPush == LONGPUSH && _WorkMode == SWEEP) {
encoderPush = false;
hideCursor(idx);
drawSymbol(1);
mode = OPTSWEEP;
delay(250);
}
//---------------------------------------------------------------------------------------------------------
// mode DIGITCHANGE: Encoder rotation change digit value (0 -> 9 ->0 and so on)
//---------------------------------------------------------------------------------------------------------
if (encoderSpin) { //encoder rotation
if (encoderSpin == CW) { //clockwise direction
Freq[idx]++; if (Freq[idx] > '9') Freq[idx] = '0';
} else { //counter clockwise direction
Freq[idx]--; if (Freq[idx] < '0') Freq[idx] = '9';
}
updateDigit(idx, Freq[idx]); //update digit on display
}
//---------------------------------------------------------------------------------------------------------
// mode DIGITCHANGE: Encoder push return to mode SINGLEDIGIT or SWEEPEDIT
//---------------------------------------------------------------------------------------------------------
if (encoderPush) { //encoder push flag set by interrupt
encoderPush = false; //reset event flag
hideCursor(idx); //flash cursor
delay(250); //for
selectDigit(idx); //visual confirmation
drawSymbol(0);
if (_WorkMode == SWEEP) {
long ltemp = _Sweep(idy) ; //save value
_setSweep(idy, atol(Freq)); //convert new value from array to long
if (_SweepMax > 0 && _SweepMax > _SweepMin && _SweepStep > 0) { //check congruency of the new sweep value
if (_Sweep(idy) != ltemp) saveConfig(); //if value has changed write new value in EEPROM
displayFrequency(_Sweep(idy));
mode = SWEEPEDIT; //change mode
} else {
_displayErrMsg; //display error message stored in flash mem
delay(1000);
_setSweep(idy, ltemp); //restore saved value
displayFrequency(_Sweep(idy)); //redisplay value
drawSymbol(2); //redraw turn icon
}
} else { //if not in sweep mode
if (_CouplingMode == OFF) { //if coupling mode if OFF
lLastFreq = atol(Freq); //save current frequency
resetCouplingMode(); //set default coupling mode
}
UpdateFrequency(); //send frequency to DDS Module
mode = SINGLEDIGIT; //change mode
}
}
break; //end mode DIGITCHANGE
default:
break;
}
}
//-----------------------------------------------------------------------------------------------------------------------------------
// Push encoder event - Called by interrupt
//-----------------------------------------------------------------------------------------------------------------------------------
void encoderSwitch(void) {
encoderPush = true;
}
//-----------------------------------------------------------------------------------------------------------------------------------
// Utility functions
//-----------------------------------------------------------------------------------------------------------------------------------
// Draw graphics interface
//----------------------------------------------------------------------------------------------------------------
void drawInterface() {
display.clearDisplay();
display.display();
delay(1000);
display.drawRoundRect(0, 0, 128, 64, 3, WHITE); //draw external frame
display.fillRect(1, 1, 126, 14, WHITE); //draw caption frame
displayText(12, 4, strFromFlash(0), BLACK, WHITE, SMALL); //print caption title
delay(1000);
if (cTime == 1) { //only on power on
displayText(XPOS - 6, YPOS + 10, strFromFlash(1), WHITE, BLACK, BIG); //show Welcom message
delay(1000);
display.fillRect(2, 16, display.width() - 3, 35, BLACK); //clear Welcome message
cTime = 0;
}
display.display();
displayText(XPOS + 84, YPOS + 4, strFromFlash(2), WHITE, BLACK, SMALL); //print "Hz"
sprintf(Freq, "%06li", lFreq); //put frequency value into char array with template "000000"
for (int i = MAXDIGIT - 1; i >= 0; i--) {
display.drawChar(XPOS + 2 + i * DELTAX, YPOS, Freq[i] , WHITE, BLACK, BIG); //Display with animation effect from right to left
display.display();
}
}//end drawInterface()
//----------------------------------------------------------------------------------------------------------------
// Print string in x,y pos with specified colors and size
//----------------------------------------------------------------------------------------------------------------
void displayText(byte x, byte y, const char *str, byte foreColor, byte backColor, byte textSize) {
display.setTextSize(textSize); //textsize: SMALL or BIG global const
display.setTextColor(foreColor, backColor); //colors WHITE or BLACK global const of the library
display.setCursor(x, y); //set the cursor position
display.print(str); //str is the pointer to the string of chars
display.display(); //update display
}
//----------------------------------------------------------------------------------------------------------------
// Copies element [i] of the string_table array from flash memory to the ram buffer and returns the pointer to the buffer
//----------------------------------------------------------------------------------------------------------------
char* strFromFlash(byte i) {
strcpy_P(buffer, (char*)pgm_read_word(&(string_table[i])));
return (char*)buffer;
}
//----------------------------------------------------------------------------------------------------------------
// Draw or clear a border around selected icon after clearing border of the previous one
//----------------------------------------------------------------------------------------------------------------
void selectIcon(byte icon, byte color) {
static byte prevIcon;
display.drawRect(XPOS - 10 + prevIcon * 32, YPOS + 19, 29, 20, BLACK);
display.drawRect(XPOS - 10 + icon * 32, YPOS + 19, 29, 20, color);
display.display();
prevIcon = icon;
}
//----------------------------------------------------------------------------------------------------------------
// Display all workmode icons
//----------------------------------------------------------------------------------------------------------------
void displayWorkModeIcons(void) {
byte const *bitmap[3] = {imgLog, imgDigit, imgSweep};
_clearIconsArea;
for (byte i = 0; i <= 2; i++) {
display.drawBitmap(XPOS - 8 + i * 32, YPOS + 21, bitmap[i], 25, 16, WHITE);
}
display.display();
}
//----------------------------------------------------------------------------------------------------------------
// Display all wavetype icons
//----------------------------------------------------------------------------------------------------------------
void displayWaveTypeIcons(void) {
byte const *bitmap[3] = {imgSqr, imgSin, imgTri};
_clearIconsArea;
for (byte i = 0; i <= 2; i++) {
display.drawBitmap(XPOS - 8 + i * 32, YPOS + 21, bitmap[i], 25, 16, WHITE);
}
display.display();
}
//----------------------------------------------------------------------------------------------------------------
// Display all coupling mode icons
//----------------------------------------------------------------------------------------------------------------
void displayCouplingModeIcons(void) {
byte const *bitmap[3] = {imgCoAc, imgCoDc, imgCoOff};
_clearIconsArea;
for (byte i = 0; i <= 2; i++) {
display.drawBitmap(XPOS - 8 + i * 32, YPOS + 21, bitmap[i], 25, 16, WHITE);
}
display.display();
}
//----------------------------------------------------------------------------------------------------------------
// Display all sweep icons
//----------------------------------------------------------------------------------------------------------------
void displaySweepIcons(void) {
byte const *bitmap[3] = {imgSwMax, imgSwMin, imgSwStep};
_clearIconsArea;
for (byte i = 0; i <= 2; i++) {
display.drawBitmap(XPOS - 8 + i * 32, YPOS + 21, bitmap[i], 25, 16, WHITE);
}
display.display();
}
//----------------------------------------------------------------------------------------------------------------
// Draw all icons
//----------------------------------------------------------------------------------------------------------------
void drawAllIcons(void) {
_clearIconsArea;
drawModeIcon();
if (_WorkMode == SWEEP || _WorkMode == SWEEPEDIT ) {
display.drawBitmap(XPOS + 24, YPOS + 21, imgSwOpt, 25, 16, WHITE);
display.drawBitmap(XPOS + 56, YPOS + 21, imgSwStart, 25, 16, WHITE);
drawSymbol(1);
idy = 2;
selectIcon(idy, WHITE); //ready to sweep
drawSmallWaveIcon();
drawSmallCouplingIcon();
}
else {
drawWaveIcon();
drawCouplingIcon();
drawSymbol(0);
if (_WorkMode == SINGLEDIGIT) selectDigit(0);
}
display.display();
}
//----------------------------------------------------------------------------------------------------------------
// Draws the icon based on the value of relative option
//----------------------------------------------------------------------------------------------------------------
void drawModeIcon(void) {
byte x = XPOS - 8, y = YPOS + 21;
byte const *bitmap[3] = {imgLog, imgDigit, imgSweep};
display.fillRect(x, y, 25, 16, BLACK);
display.drawBitmap(x, y, bitmap[_WorkMode], 25, 16, WHITE);
display.display();
}
void drawWaveIcon(void) {
byte x = XPOS + 24, y = YPOS + 21;
const byte *bitmap[3] = {imgSqr, imgSin, imgTri};
display.fillRect(x, y, 25, 16, BLACK);
display.drawBitmap(x, y, bitmap[_WaveType], 25, 16, WHITE);
display.display();
drawSmallWaveIcon();
}
void drawCouplingIcon(void) {
byte x = XPOS + 56, y = YPOS + 21;
const byte *bitmap[3] = {imgCoAc, imgCoDc, imgCoOff};
display.fillRect(x, y, 25, 16, BLACK);
display.drawBitmap(x, y, bitmap[_CouplingMode], 25, 16, WHITE);
display.display();
drawSmallCouplingIcon();
}
//----------------------------------------------------------------------------------------------------------------
// Draws small wave icon based on the value of relative option
//----------------------------------------------------------------------------------------------------------------
void drawSmallWaveIcon(void) {
byte x = 114, y = 41;
const byte *bitmap[3] = {imgSqrSmall, imgSinSmall, imgTriSmall};
display.fillRect(x, y, 9, 8, BLACK);
display.drawBitmap(x, y, bitmap[_WaveType], 9, 8, WHITE);
display.display();
}
//----------------------------------------------------------------------------------------------------------------
// Draws small coupling icon based on the value of relative option
//----------------------------------------------------------------------------------------------------------------
void drawSmallCouplingIcon(void) {
byte x = 114, y = 50;
const byte *bitmap[3] = {imgAcSmall, imgDcSmall, imgOffSmall};
display.fillRect(x, y, 9, 8, BLACK);
display.drawBitmap(x, y, bitmap[_CouplingMode], 9, 8, WHITE);
display.display();
}
//----------------------------------------------------------------------------------------------------------------
// Show cursor at x position
//----------------------------------------------------------------------------------------------------------------
void showCursor(byte x) {
display.drawChar(XPOS + 2 + x * DELTAX, YPOS + DELTAY, CURSOR, WHITE, WHITE, BIG);
display.display();
}
//----------------------------------------------------------------------------------------------------------------
// Hide cursor at x position
//----------------------------------------------------------------------------------------------------------------
void hideCursor(byte x) {
display.drawChar(XPOS + 2 + x * DELTAX, YPOS + DELTAY, CURSOR, BLACK, BLACK, BIG);
display.display();
}
//----------------------------------------------------------------------------------------------------------------
// Show cursor at x position after hiding previous one
//----------------------------------------------------------------------------------------------------------------
void selectDigit(byte x) {
static byte lastDigit;
hideCursor(lastDigit);
display.drawChar(XPOS + 2 + x * DELTAX, YPOS + DELTAY, CURSOR, WHITE, WHITE, BIG);
display.display();
lastDigit = x;
}
//----------------------------------------------------------------------------------------------------------------
// Update single digit frequency to chr value
//----------------------------------------------------------------------------------------------------------------
void updateDigit(byte digit, char chr) {
display.drawChar(XPOS + 2 + digit * DELTAX, YPOS, chr , WHITE, BLACK, BIG);
display.display();
}
//----------------------------------------------------------------------------------------------------------------
// Drwaw or clear some symbols/icons
//----------------------------------------------------------------------------------------------------------------
void drawSymbol(byte symbol) {
switch (symbol) {
case 0: //Top arrow
display.fillRect(2, 20, 25, 16, BLACK);
display.fillRect(2, 43, 14, 16, BLACK);
display.drawChar(XPOS - 20 , YPOS + 4, ARROW, WHITE, BLACK, SMALL); //draw top arrow top
break;
case 1: //Bottom arrow
display.fillRect(2, 20, 25, 16, BLACK);
display.fillRect(2, 43, 14, 16, BLACK);
display.drawChar(XPOS - 20 , YPOS + 25, ARROW, WHITE, BLACK, SMALL); //draw bottom arrow
break;
case 2: //Turn icon
display.fillRect(2, 20, 25, 16, BLACK);
display.drawBitmap(XPOS - 21, YPOS + 1, imgTurn, 13, 13, WHITE); //draw turn icon
break;
case 3: //Play icons
display.fillRect(4, 23, 23, 11, BLACK); //clear pause icon
display.drawBitmap(4, 23, imgSwRun, 23, 11, WHITE); //draw sweep icon
display.fillRect(XPOS + 56, YPOS + 21, 25, 16, BLACK); //clear icon area
display.drawBitmap(XPOS + 56, YPOS + 21, imgSwPause, 25, 16, WHITE); //drwaw sweep play symbol icon
break;
case 4: //Pause icons
display.fillRect(4, 23, 23, 11, BLACK); //clear sweep icon
display.drawBitmap(4, 23, imgSwPsd, 23, 11, WHITE); //draw pause icon
display.fillRect(XPOS + 56, YPOS + 21, 25, 16, BLACK); //clear icon area
display.drawBitmap(XPOS + 56, YPOS + 21, imgSwStart, 25, 16, WHITE); //draw sweep pause symbol icon
break;
case 9: //Simply clear symbol area
display.fillRect(2, 20, 25, 16, BLACK); //clear top symbol area
display.fillRect(2, 43, 14, 16, BLACK); //clear bottom symbol area
break;
default:
break;
}
display.display();
}
//---------------------------------------------------------------------------------------------------------------
// Set current frequency in DDS module, if frequency is 0 it will be set to 1
//---------------------------------------------------------------------------------------------------------------
void UpdateFrequency(void) {
lFreq = atol(Freq); //convert char array to long
if (lFreq < 1) { //the frequency at zero makes no sense
++Freq[MAXDIGIT - 1]; //increase the right most digit
lFreq = 1; //set frequency to 1
}
displayFrequency(lFreq); //update the display
DDS_FrequencySet(lFreq, Wave[_WaveType]); //send the frequency value to DDS module
lLastFreq = lFreq; //save current freq
}
//---------------------------------------------------------------------------------------------------------------
// Display the frequency with the six-zero template
//---------------------------------------------------------------------------------------------------------------
void displayFrequency(long f) {
sprintf(Freq, "%06li", f); //convert long to char with template '000000'
displayText(XPOS + 2, YPOS, Freq , WHITE, BLACK, BIG); //print frequency on display
display.display(); //refresh display
}
//---------------------------------------------------------------------------------------------------------------
// Reset coupling mode to default
//---------------------------------------------------------------------------------------------------------------
void resetCouplingMode(void) {
if (lFreq == 0 && _CouplingMode == OFF) {
setCouplingMode(AC);
drawCouplingIcon();
}
}
//---------------------------------------------------------------------------------------------------------------
// Set a specific coupling mode
//---------------------------------------------------------------------------------------------------------------
void setCouplingMode(byte cMode) {
byte pMode = _CouplingMode;
switch (cMode) {
case 0:
if (lLastFreq > 0) lFreq = lLastFreq;
digitalWrite(PinCoupling, LOW);
_setCouplingMode(AC);
break;
case 1:
if (lLastFreq > 0) lFreq = lLastFreq;
digitalWrite(PinCoupling, HIGH);
_setCouplingMode(DC);
break;
case 2:
lLastFreq = lFreq;
lFreq = 0;
digitalWrite(PinCoupling, LOW);
_setCouplingMode(OFF);
break;
}
DDS_FrequencySet(lFreq, Wave[_WaveType]);
displayFrequency(lFreq);
if (cMode != pMode) saveConfig();
}
//---------------------------------------------------------------------------------------------------------------
// Select options
//---------------------------------------------------------------------------------------------------------------
void selectOption(byte opt) {
selectIcon(opt, BLACK);
switch (opt) {
case 0: //workMode;
displayWorkModeIcons();
selectIcon(_WorkMode, WHITE);
mode = OPTMODE;
break;
case 1: //waveType;
displayWaveTypeIcons();
selectIcon(_WaveType, WHITE);
mode = OPTWAVE;
break;
case 2: //couplingMode;
displayCouplingModeIcons();
selectIcon(_CouplingMode, WHITE);
mode = OPTCOUP;
break;
}
}
//----------------------------------------------------------------------------------------------------------------
// Calculate logarithmic steps of the frequency
//----------------------------------------------------------------------------------------------------------------
long AutoStep(long value, byte spin) {
if (spin == CW) {
if (value >= 100000) return 100000;
if (value >= 10000) return 10000;
if (value >= 1000) return 1000;
if (value >= 100) return 100;
if (value >= 10) return 10;
if (value >= 1) return 1;
return 0; // Invalid value
}
else {
if (value <= 10) return 1;
if (value <= 100) return 10;
if (value <= 1000) return 100;
if (value <= 10000) return 1000;
if (value <= 100000) return 10000;
if (value <= 1000000) return 100000;
return 0; // Invalid value
}
}
//-------------------------------------------------------------------------------------------
// Start Sweep or restart it from where it came from before the pause
//-------------------------------------------------------------------------------------------
void FrequencySweep() {
do {
if (sweepDnPausedVal == 0) { //if sweepDown has not been stopped
if (sweepUpPausedVal > 0) { //and sweepUp has been stopped
sweepUpPausedVal = SweepUp(sweepUpPausedVal); //continues from current value
}
else {
sweepUpPausedVal = SweepUp(_SweepMin); //else start from min
}
}
if (sweepStatus != BREAK) { //if sweep has been stopped
if (sweepDnPausedVal > 0) { //and sweepDn has been stopped
sweepDnPausedVal = SweepDn(sweepDnPausedVal); //continues from current value
}
else {
sweepDnPausedVal = SweepDn(_SweepMax); //else start from max
}
}
} while (sweepStatus != BREAK); //continues sweep until stopped
}
//-----------------------------------------------------------------------------------------
// Sweep Up from sweepmin push encoder to pause
//-----------------------------------------------------------------------------------------
long SweepUp(long sweepmin) {
long f;
for (f = sweepmin ; f < _SweepMax ; f += _SweepStep) {
DDS_FrequencySet(f, Wave[_WaveType]);
displayFrequency(f);
if (encoderPush) {
sweepStatus = BREAK;
break;
}
}
if (sweepStatus == BREAK) return f;
return 0;
}
//-----------------------------------------------------------------------------------------
// Sweep down from sweepmax push encoder to pause
//-----------------------------------------------------------------------------------------
long SweepDn(long sweepmax) {
long f;
for (f = sweepmax; f > _SweepMin ; f -= _SweepStep) {
DDS_FrequencySet(f, Wave[_WaveType]);
displayFrequency(f);
if (encoderPush) {
sweepStatus = BREAK;
break;
}
}
if (sweepStatus == BREAK)return f;
return 0;
}
//-----------------------------------------------------------------------------------------
// Clear global sweep vars and restore display
//-----------------------------------------------------------------------------------------
void SweepReset(void) {
sweepStatus = STILL;
sweepUpPausedVal = 0;
sweepDnPausedVal = 0;
display.fillRect(4, 23, 23, 11, BLACK); //clear sweep text
display.display();
}
//-----------------------------------------------------------------------------------------
// Flash sweep pause icon
//-----------------------------------------------------------------------------------------
void flashIcon(int interval) {
static long previousMillis;
static boolean picShow;
if (millis() - previousMillis >= interval) {
previousMillis = millis();
picShow = !picShow;
if (picShow) {
display.drawBitmap(4, 23, imgSwPsd, 23, 11, WHITE); //drwaw sweep pause icon
display.display();
} else {
display.fillRect(4, 23, 23, 11, BLACK); //clear sweep pause icon
display.display();
}
}
}
//-----------------------------------------------------------------------------------------
// Arduino software reset
//-----------------------------------------------------------------------------------------
void reset(void) {
display.fillRect(1, 16, 125, 46, BLACK);
display.display();
displayText(30, 30, strFromFlash(4), WHITE, BLACK, BIG);
char str[2];
for (byte i = 3; i > 0; i--) {
sprintf(str, "%d", i);
displayText(95, 30, str, WHITE, BLACK, BIG);
...