Hardware components | ||||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
Software apps and online services | ||||||
| ||||||
Hand tools and fabrication machines | ||||||
|
For a long time I have put off buying an oscilloscope. Now, after purchasing it, it's time to also have an inexpensive signal generator for hobby use, essential for diagnosing audio circuits and more. Combining the two passions for electronics and computing, the best thing is to do it yourself with Arduino.
FEATURES- Output frequency between 1 Hz and 999999 Hz
- two modes of frequency variation: logarithmic and single digit
- three types of wave, sine, triangular and square
- AC or DC output coupling
- ability to sweep continuosly between two predefined frequency values
- controlled exclusively by a single knob
- integrated screen saver to preserve the life of the oled display
The output amplitude from the DDS module is not very high, on average between 550 and 650 mV peak-to-peak for the sine and triangular waveforms, much higher for the square ones, about 4.5V peak-to-peak. Of course this tends to go down inversely proportional to the frequency but up to 1MHz it is quite linear. The AD9833 DDS module is capable of generating signals up to 12 MHz which are not necessary for me. If you need to go beyond 1 MHz you can try to experiment and add a digit or two to the display, however this involves the partial redesign of the graphical interface.
The quality of the output signal also depends on the quality of the power supply so it would be better to use a linear power supply instead of a switching one as I did to reduce the size of the case that I recovered from an old project. However even with the switching module the linearity of the waveforms is quite good.
-----------------------------------------------------------------------------------------------------------------
Since some people have problems compiling the code, I add the following note:
-----------------------------------------------------------------------------------------------------------------
Pay attention to the three tabs in the "Code" section please.
The code is made up of three separate files that must be in the same folder as the main ino file.
- JX_Wave_Generator_8.7.7.ino
- JXWG_Defs.h
- JXWG_Graphics.h
-----------------------------------------------------------------------------------------------------------------
QUICK REFERENCESI used a pre-assembled relay module which has 10A contacts, because at the moment I didn't have a micro reed relay, this would be the best choice to avoid transistor diodes and resistor, when power relays are not needed. An Arduino digital PIN can deliver a maximum of 40 mA so you cannot connect an electromechanical relay with a 120/150 ohm coil directly.
ALWAYS BE VERY VERY CAREFUL when using mains voltage!
Risk of electrical shock and/or damage to your skin and eyes.
Take care of your life you only have one!
I apologize for the quality of my English, I have used Google translator extensively. Forgive me.
/*
Copyright (c) 2020 Janux
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
The configuration saving-loading code is a development of an original idea of the article
"How to Load and Save Configurations on an Arduino" by Ragnar Ranyen Homb on the Norwegian Creation website.
*/
#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);
...
This file has been truncated, please download it to see its full contents.
// This file is an integral part of the JX_WaveGenerator.ino and must be
// distributed together with the main file to allow it to function correctly.
// The same license of the main file applies to this file.
// Janux 01/04/2021 on Turin, Italy.
#ifndef JXWG_Defs
#define JXWG_Defs
#include <Wire.h>
#include <EEPROM.h>
//Encoder library, see https://www.arduino.cc/reference/en/libraries/simplerotary/
#include <SimpleRotary.h> //
//adaptation of the library for SSD1306 to the SH1106 display, see https://github.com/wonho-maker/Adafruit_SH1106
#include <Adafruit_SH1106.h>
#define DEBUG 0
#define OLED_RESET -1
Adafruit_SH1106 display(OLED_RESET);
#define PinA 5 //Encoder pin A
#define PinB 4 //Encoder pin B
#define PinS 3 //Encoder pin Switch
SimpleRotary Encoder(PinA, PinB, PinS);
//list of loop mode
#define LOGARITHMIC 0 //+workmode
#define SINGLEDIGIT 1 //+workmode
#define SWEEP 2 //+workmode
#define OPTIONS 3 //-submode of LOGARITHMIC and SINGLEDIGIT
#define OPTMODE 4 //-submode of OPTIONS
#define OPTWAVE 5 //-submode of OPTIONS
#define OPTCOUP 6 //-submode of OPTIONS
#define OPTSWEEP 7 //-submode of SWEEP
#define SWEEPEDIT 8 //-submode of OPTSWEEP
#define DIGITCHANGE 9 //-submode of SINGLEDIGIT and SWEEPEDIT
#define PinCoupling 7 //Coupling mode pin (relay pin)
//constants
#define XPOS 28
#define YPOS 21
#define DELTAX 12
#define DELTAY 4
#define SMALL 1
#define BIG 2
#define CW 1
#define CCW 2
#define PUSH 1
#define LONGPUSH 1
//Num Freq digit
#define MAXDIGIT 6
//Wave type
#define SQUARE 0
#define SINE 1
#define TRIANGLE 2
//Coupling mode
#define AC 0
#define DC 1
#define OFF 2
//Sweep status
#define STILL 0
#define BREAK 1
#define PAUSE 2
//Symbols chars
#define CURSOR 0x5F
#define ARROW 0x10
//AD9833 module Pin connection
#define DDS_FSY 9
#define DDS_CLK 10
#define DDS_DAT 11
//AD9833 Wave Type const
#define wSquare 0x28
#define wSine 0x00
#define wTriangle 0x02
//-----------------------------------------------------------------------------
// Variables declarections
//-----------------------------------------------------------------------------
//Strings constants placed in flash memory save ram space
const char str1[] PROGMEM = "JX WAVE GENERATOR"; // 18 byte
const char str2[] PROGMEM = "WELCOME"; // 8 byte
const char str3[] PROGMEM = "Hz"; // 3 byte
const char str4[] PROGMEM = "ERROR!"; // 7 byte
const char str5[] PROGMEM = "RESET"; // 6 byte //42 byte total
const char* const string_table[] PROGMEM = {str1, str2, str3, str4, str5};
char buffer[18]; //local buffer for string, make sure this is large enough for the largest string it must hold
long lFreq = 1000; //main frequency variable
long lLastFreq = 1000; //used to save the current freq value in some situations
long sweepUpPausedVal = 0; //value of sweep when pused
long sweepDnPausedVal = 0; //value of sweep when pused
long lSweep[3] = {20000, 0, 100}; //Sweep Hz default value MAX, MIN, STEP;
byte sweepStatus = STILL; //current status of the sweep process
const byte Wave[] = {wSquare, wSine, wTriangle}; //array for WaveType
volatile boolean encoderPush = false; //var used in the routine called by interrupt
char Freq[MAXDIGIT + 1]; //array for display frequency in 6 digit template "000000"
byte mode = 0; //current loop mode
byte idx = 0; //pointer to digit index (0 to 5)
byte idy = 0; //same of idx in submode
long cTime = 1; //screensaver counter
//default startup preferences
byte options[3] = {LOGARITHMIC, SINE, DC}; //mode, wavetype, couplingmode
//define others macros
#define _WorkMode options[0]
#define _setWorkMode(x) options[0]=x
#define _WaveType options[1]
#define _setWaveType(x) options[1]=x
#define _CouplingMode options[2]
#define _setCouplingMode(x) options[2]=x
#define _reservedbyte 0xFF
#define _SweepMax lSweep[0]
#define _SweepMin lSweep[1]
#define _SweepStep lSweep[2]
#define _Sweep(x) lSweep[x]
#define _setSweep(x,f) lSweep[x]=f
#define _setSweepMax(x) lSweep[0]=x
#define _setSweepMin(x) lSweep[1]=x
#define _setSweepStep(x) lSweep[2]=x
//define short functions macros
#define _clearIconsArea display.fillRect(XPOS - 11, YPOS + 18, 94, 24, BLACK)
#define _displayErrMsg displayText(XPOS + 2, YPOS, strFromFlash(3), WHITE, BLACK, BIG);
//define CONFIG consts & vars
#define CONFIG_START 32 //EEPROM Memory start location
#define CONFIG_VERSION "JXWG1" //Config version ID
//define custom type struct
typedef struct {
char version[6];
byte workmode;
byte wavetype;
byte couplingmode;
byte reservedbyte;
long sweepmax;
long sweepmin;
long sweepstep;
} config_type;
//create new struct and load it with default value
config_type CONFIG = {
CONFIG_VERSION,
_WorkMode,
_WaveType,
_CouplingMode,
_reservedbyte,
_SweepMax,
_SweepMin,
_SweepStep,
};
//define processor reset function
void(*ATmegaReset)(void) = 0;
#endif
// This file is an integral part of the JX_WaveGenerator.ino and must be
// distributed together with the main file to allow it to function correctly.
// The same license of the main file applies to this file.
// Janux 01/04/2021 on Turin, Italy.
#ifndef JXWG_Graphics
#define JXWG_Graphics
//----------------------------------------------------------------------------------------------
// Plain b&w bitmaps PROGMEM icons data
//----------------------------------------------------------------------------------------------
const byte imgLog[] PROGMEM = {
0xff, 0xff, 0xff, 0x80, 0x80, 0x00, 0x00, 0x80, 0x88, 0x00, 0x40, 0x80, 0x9c, 0x00, 0x40, 0x80,
0x88, 0x00, 0x80, 0x80, 0x88, 0x00, 0x80, 0x80, 0x88, 0x01, 0x00, 0x80, 0x88, 0x02, 0x00, 0x80,
0x88, 0x0c, 0x00, 0x80, 0x88, 0x30, 0x00, 0x80, 0x89, 0xc0, 0x00, 0x80, 0x8e, 0x00, 0x10, 0x80,
0x9f, 0xff, 0xf8, 0x80, 0x88, 0x00, 0x10, 0x80, 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x80
};
const byte imgDigit[] PROGMEM = {
0xff, 0xff, 0xff, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80,
0x9c, 0x47, 0x3e, 0x80, 0xa2, 0xc8, 0x82, 0x80, 0xa6, 0x40, 0x84, 0x80, 0xaa, 0x47, 0x0c, 0x80,
0xb2, 0x48, 0x02, 0x80, 0xa2, 0x48, 0x22, 0x80, 0x9c, 0xef, 0x9c, 0x80, 0x80, 0x00, 0x00, 0x80,
0x80, 0x00, 0x3e, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x80
};
const byte imgSweep[] PROGMEM = {
0xff, 0xff, 0xff, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x8f, 0xcf, 0x38, 0x80,
0x88, 0x49, 0x28, 0x80, 0x88, 0x49, 0x28, 0x80, 0x88, 0x49, 0x28, 0x80, 0x88, 0x49, 0x28, 0x80,
0x88, 0x49, 0x28, 0x80, 0x88, 0x49, 0x28, 0x80, 0x88, 0x49, 0x28, 0x80, 0x88, 0x49, 0x28, 0x80,
0x88, 0x49, 0x28, 0x80, 0xb8, 0x79, 0xee, 0x80, 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x80
};
const byte imgSqr[] PROGMEM = {
0xff, 0xff, 0xff, 0x80, 0x82, 0x08, 0x20, 0x80, 0x80, 0xff, 0x80, 0x80, 0x82, 0x88, 0xa0, 0x80,
0x80, 0x80, 0x80, 0x80, 0x82, 0x88, 0xa0, 0x80, 0x80, 0x80, 0x80, 0x80, 0xaa, 0xaa, 0xaa, 0x80,
0x80, 0x80, 0x80, 0x80, 0x82, 0x88, 0xa0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x82, 0x88, 0xa0, 0x80,
0xff, 0x80, 0xff, 0x80, 0x82, 0x08, 0x20, 0x80, 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x80
};
const byte imgSin[] PROGMEM = {
0xff, 0xff, 0xff, 0x80, 0x82, 0x08, 0x20, 0x80, 0x80, 0x1c, 0x00, 0x80, 0x82, 0x2a, 0x20, 0x80,
0x80, 0x41, 0x00, 0x80, 0x82, 0x49, 0x20, 0x80, 0x80, 0x80, 0x80, 0x80, 0xaa, 0xaa, 0xaa, 0x80,
0x80, 0x80, 0x80, 0x80, 0xc3, 0x08, 0x61, 0x80, 0xc1, 0x00, 0x41, 0x80, 0xa2, 0x08, 0x22, 0x80,
0x9c, 0x00, 0x1c, 0x80, 0x82, 0x08, 0x20, 0x80, 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x80
};
const byte imgTri[] PROGMEM = {
0xff, 0xff, 0xff, 0x80, 0x82, 0x08, 0x20, 0x80, 0x82, 0x00, 0x20, 0x80, 0x87, 0x08, 0x70, 0x80,
0x85, 0x00, 0x50, 0x80, 0x8a, 0x88, 0xa8, 0x80, 0x88, 0x80, 0x88, 0x80, 0xba, 0xeb, 0xae, 0x80,
0x90, 0x41, 0x04, 0x80, 0xa2, 0x2a, 0x22, 0x80, 0xa0, 0x22, 0x02, 0x80, 0xc2, 0x1c, 0x21, 0x80,
0xc0, 0x14, 0x01, 0x80, 0x82, 0x08, 0x20, 0x80, 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x80
};
const byte imgCoAc[] PROGMEM = {
0xff, 0xff, 0xff, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80,
0x9c, 0x70, 0x00, 0x80, 0xa2, 0x88, 0x00, 0x80, 0xa2, 0x80, 0xc0, 0x80, 0xa2, 0x81, 0x24, 0x80,
0xbe, 0x81, 0x24, 0x80, 0xa2, 0x88, 0x18, 0x80, 0xa2, 0x70, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80,
0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x80
};
const byte imgCoDc[] PROGMEM = {
0xff, 0xff, 0xff, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80,
0xbc, 0x70, 0x00, 0x80, 0xa2, 0x88, 0x00, 0x80, 0xa2, 0x81, 0x54, 0x80, 0xa2, 0x80, 0x00, 0x80,
0xa2, 0x81, 0xfc, 0x80, 0xa2, 0x88, 0x00, 0x80, 0xbc, 0x70, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80,
0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x80
};
const byte imgCoOff[] PROGMEM = {
0xff, 0xff, 0xff, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80,
0x9c, 0xf7, 0x80, 0x80, 0xa2, 0x84, 0x22, 0x80, 0xa2, 0x84, 0x14, 0x80, 0xa2, 0xe7, 0x08, 0x80,
0xa2, 0x84, 0x14, 0x80, 0xa2, 0x84, 0x22, 0x80, 0x9c, 0x84, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80,
0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x80
};
const byte imgSwMax[] PROGMEM = {
0xff, 0xff, 0xff, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80,
0x81, 0x00, 0x00, 0x80, 0x82, 0x00, 0x00, 0x80, 0x87, 0x01, 0x00, 0x80, 0x82, 0x03, 0x80, 0x80,
0x82, 0x07, 0xc0, 0x80, 0x82, 0x0f, 0xe0, 0x80, 0x82, 0x1f, 0xf0, 0x80, 0x80, 0x00, 0x00, 0x80,
0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x80
};
const byte imgSwMin[] PROGMEM = {
0xff, 0xff, 0xff, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80,
0x81, 0x00, 0x00, 0x80, 0x82, 0x00, 0x00, 0x80, 0x87, 0x1f, 0xf0, 0x80, 0x82, 0x0f, 0xe0, 0x80,
0x82, 0x07, 0xc0, 0x80, 0x82, 0x03, 0x80, 0x80, 0x82, 0x01, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80,
0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x80
};
const byte imgSwOpt[] PROGMEM = {
0xff, 0xff, 0xff, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80,
0x84, 0x08, 0x10, 0x80, 0x88, 0x1c, 0x38, 0x80, 0x9c, 0x3e, 0x10, 0x80, 0x88, 0x00, 0x00, 0x80,
0x88, 0x00, 0x00, 0x80, 0x88, 0x3e, 0x00, 0x80, 0x88, 0x1c, 0x38, 0x80, 0x88, 0x08, 0x00, 0x80,
0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x80
};
const byte imgSwStep[] PROGMEM = {
0xff, 0xff, 0xff, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80,
0x84, 0x08, 0x04, 0x80, 0x88, 0x0c, 0x08, 0x80, 0x9c, 0x7e, 0x1c, 0x80, 0x88, 0x7f, 0x08, 0x80,
0x88, 0x7e, 0x08, 0x80, 0x88, 0x0c, 0x08, 0x80, 0x88, 0x08, 0x08, 0x80, 0x80, 0x00, 0x00, 0x80,
0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x80
};
const byte imgSwStart[] PROGMEM = {
0xff, 0xff, 0xff, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0xc0, 0x00, 0x80,
0x80, 0xf0, 0x00, 0x80, 0x80, 0xfc, 0x00, 0x80, 0x80, 0xff, 0x00, 0x80, 0x80, 0xff, 0xc0, 0x80,
0x80, 0xff, 0xc0, 0x80, 0x80, 0xff, 0x00, 0x80, 0x80, 0xfc, 0x00, 0x80, 0x80, 0xf0, 0x00, 0x80,
0x80, 0xc0, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x80
};
const byte imgSwPause[] PROGMEM = {
0xff, 0xff, 0xff, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x81, 0xe3, 0xc0, 0x80,
0x81, 0xe3, 0xc0, 0x80, 0x81, 0xe3, 0xc0, 0x80, 0x81, 0xe3, 0xc0, 0x80, 0x81, 0xe3, 0xc0, 0x80,
0x81, 0xe3, 0xc0, 0x80, 0x81, 0xe3, 0xc0, 0x80, 0x81, 0xe3, 0xc0, 0x80, 0x81, 0xe3, 0xc0, 0x80,
0x81, 0xe3, 0xc0, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x80
};
const byte imgTurn[] PROGMEM = {
0x0f, 0x80, 0x30, 0x60, 0x47, 0x10, 0x58, 0xd0, 0x90, 0x48, 0x80, 0xe8, 0x90, 0x48, 0xb8, 0x08,
0x90, 0x48, 0x58, 0xd0, 0x47, 0x10, 0x30, 0x60, 0x0f, 0x80
};
const byte imgSwRun[] PROGMEM = {
0x00, 0x00, 0x00, 0xff, 0xff, 0xfe, 0x9b, 0xa2, 0x22, 0x6b, 0xae, 0xec, 0x7b, 0xae, 0xec, 0x9a,
0xa6, 0x62, 0xea, 0xae, 0xee, 0x6a, 0xae, 0xee, 0x9c, 0x62, 0x2e, 0xff, 0xff, 0xfe, 0x00, 0x00,
0x00
};
const byte imgSwPsd[] PROGMEM = {
0x00, 0x00, 0x00, 0xff, 0xff, 0xfe, 0x1c, 0xdb, 0x30, 0x6b, 0x5a, 0xd6, 0x6b, 0x5a, 0xf6, 0x18,
0x5b, 0x32, 0x7b, 0x5b, 0xd6, 0x7b, 0x5a, 0xd6, 0x7b, 0x67, 0x30, 0xff, 0xff, 0xfe, 0x00, 0x00,
0x00
};
//Small icons ---------------------------------------------------------------------------------
const byte imgSqrSmall[] PROGMEM = {
0x00, 0x00, 0x3e, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0xe3, 0x80, 0x00, 0x00
};
const byte imgSinSmall[] PROGMEM = {
0x00, 0x00, 0x30, 0x00, 0x48, 0x00, 0x48, 0x00, 0x84, 0x80, 0x84, 0x80, 0x03, 0x00, 0x00, 0x00
};
const byte imgTriSmall[] PROGMEM = {
0x00, 0x00, 0x20, 0x00, 0x50, 0x00, 0x88, 0x80, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00
};
const byte imgAcSmall[] PROGMEM = {
0x00, 0x00, 0x30, 0x00, 0x48, 0x00, 0x48, 0x00, 0x84, 0x80, 0x84, 0x80, 0x03, 0x00, 0x00, 0x00
};
const byte imgDcSmall[] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0x80, 0x00, 0x00, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00
};
const byte imgOffSmall[] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x14, 0x00, 0x08, 0x00, 0x14, 0x00, 0x22, 0x00, 0x00, 0x00
};
//Total program memory space used by icons data: 1148 byte
#endif
Comments