Those errors I not get in version 1.57.2
In file included from /home/holstein/Desktop/FL2100Z_PWRV1.0/PSWRtft.cpp:28:
/home/holstein/Desktop/FL2100Z_PWRV1.0/PSWRtft.h: In member function 'void PowerMeter::scale(double)':
/home/holstein/Desktop/FL2100Z_PWRV1.0/PSWRtft.h:84:37: warning: invalid conversion from 'char' to 'char*' [-fpermissive]
84 | void scale(double s) { scale(s, '\0'); }// Blank if no scale range string
| ^~~~
| |
| char
/home/holstein/Desktop/FL2100Z_PWRV1.0/PSWRtft.h:83:32: note: initializing argument 2 of 'void PowerMeter::scale(double, char*)'
83 | void scale(double s, char *range); // Scale Erases if required and then draws everything
| ~~~~~~^~~~~
In file included from /home/holstein/Desktop/FL2100Z_PWRV1.0/PSWR_T.h:43,
from /home/holstein/Desktop/FL2100Z_PWRV1.0/FL2100Z_PWRV1.0.ino:113:
/home/holstein/Desktop/FL2100Z_PWRV1.0/PSWRtft.h: In member function 'void PowerMeter::scale(double)':
/home/holstein/Desktop/FL2100Z_PWRV1.0/PSWRtft.h:84:37: warning: invalid conversion from 'char' to 'char*' [-fpermissive]
84 | void scale(double s) { scale(s, '\0'); }// Blank if no scale range string
| ^~~~
| |
| char
/home/holstein/Desktop/FL2100Z_PWRV1.0/PSWRtft.h:83:32: note: initializing argument 2 of 'void PowerMeter::scale(double, char*)'
83 | void scale(double s, char *range); // Scale Erases if required and then draws everything
| ~~~~~~^~~~~
Memory Usage on Teensy 4.0:
FLASH: code:126972, data:912576, headers:9024 free for files:983044
RAM1: variables:339552, code:124840, padding:6232 free for local variables:53664
RAM2: variables:12416 free for malloc/new:511872
Failed uploading: no upload port provided
I included the part of the program where the errors come from.
PSWRtft.cpp and PSWRtft.h
PSWRtft.ccp
#include "PSWRtft.h"
#include "PSWR_T.h"
extern var_t R; // R.low_power_floor flag/variable used with Modulation Scope
extern RA8875 tft;
//-----------------------------------------------------------------------------------------
// Initialise Dual Power Meter,
// define left x and top y coordinates;
// length x; height y;
// graph, low and high colour
//-----------------------------------------------------------------------------------------
void PowerMeter::init(int16_t xcoord, int16_t ycoord, int16_t xlen, int16_t ylen,
int16_t graphcolour, int16_t lowcolour, int16_t highcolour)
{
x = xcoord;
y = ycoord;
len = xlen;
height = ylen;
GaugeColour = graphcolour;
LowColour = lowcolour;
HighColour = highcolour;
}
void PowerMeter::init(int16_t xcoord, int16_t ycoord, int16_t xlen, int16_t ylen)
{
x = xcoord;
y = ycoord;
len = xlen;
height = ylen;
}
//-----------------------------------------------------------------------------------------
// Draw, Redraw or Erase Power Meter Scale.
// If requested action is same as last time, then nothing is done.
// First input argument is a number from 1.0 and up, divided into 10 or 11 segments
// (11 if (scale*10)%11=0 and if second input is used to indicate unit)
// Second, optional input argument, is an unit indication for the measured level,
// eg "uW", "mW", "W", "kW"
//-----------------------------------------------------------------------------------------
void PowerMeter::scale(double s, char *range)
{
if (erased) // Draw complete Graph if requested and not already drawn
{
drawframe(GaugeColour);
drawscale(s, GaugeColour, range);
printunits(GaugeColour, range);
current_scale = s;
strcpy(current_range, range);
erased = false;
}
else
{
if (current_scale != s) // Replace scale if changed
{
drawscale(current_scale, blnkColour, current_range);
drawscale(s, GaugeColour, range);
current_scale = s;
}
if (strcmp(current_range, range)) // Replace units indication if changed
{
printunits(blnkColour, current_range);
printunits(GaugeColour, range);
strcpy(current_range, range);
}
}
}
void PowerMeter::erase(void)
{
if (!erased)
{
drawframe(blnkColour);
drawscale(current_scale, blnkColour, current_range);
printunits(blnkColour, current_range);
erasegraph();
erased = true;
}
}
void PowerMeter::drawframe(int16_t colour)
{
tft.drawRect(x, y,len+2, height+2, colour); // Draw the Graph Outline
tft.drawFastHLine(x, y + height+2, len+2, colour);// Draw the Scale line below
}
void PowerMeter:
rintunits(int16_t colour, char *range)
{
tft.setFont(DroidSansMono_16);
tft.setTextColor(colour);
tft.setCursor( x+len - 4*strlen(range), y+height+9);
tft.print(range);
}
void PowerMeter::drawscale(double scale, int16_t colour, char *range)
{
double i, j, k;
uint8_t subdecimal;
int16_t offs = 0;
double divisor; // Divisor of 10 or 11.
// Certain scales are good for 11 segments, if range indication is used
if (((int)(scale*10+.1)%11) == 0) divisor = 11;
else divisor = 10;
tft.setFont(DroidSansMono_16);
tft.setTextColor(colour);
tft.drawFastVLine( x+1, y+height+2, 5, colour); // Draw the Scale
tft.setCursor( x-1, y+height+9); // 1st value
tft.print("0");
// Bars and numbers evenly spread over the full length
for (i=len/divisor, j=scale/divisor; i<=len; i+=len/divisor, j+=scale/divisor)
{
tft.drawFastVLine( x+i, y+height+2, 5, colour);
if ((i>=len-1) && (range[0]!=0)) // Units at end of scale, if used
{
; // If Units (e.g. "mW") used then do nothing here,
// printunits(...) will take care of it
}
else
{
k=j; // Figure out offset for the value to be printed, based on number of digits
offs = 3;
while ((k+.1)>=10)
{
offs += 3;
k /= 10;
}
// Decide whether we have subdecimals or not
if ((modf(j, &k) > 0.05) && (modf(j, &k) < 0.95)) subdecimal = 1;
else subdecimal = 0;
if (subdecimal) offs +=4;
tft.setCursor( x+i - offs, y+height+9);
tft.print(j, subdecimal);
}
}
for (i=len/(2*divisor); i<=len; i+=len/divisor) // Draw additional 10 inbetween midpoints
{
tft.drawFastVLine( x+i, y+height+2, 3, colour);
}
}
//-----------------------------------------------------------------------------------------
// Draw Power Meter Graph in an incremental/decremental manner
// input arguments are low value, high value and full scale value
// Note that high value shown is always same or higher than low value shown
//-----------------------------------------------------------------------------------------
void PowerMeter::graph(double lowlevel, double highlevel, double maxlevel)
{
int16_t low, high;
if (lowlevel > maxlevel) lowlevel = maxlevel; // Prepare max bounds of input values
if (highlevel > maxlevel) highlevel = maxlevel;
if (lowlevel < 0) lowlevel = 0;
if (highlevel < 0) highlevel = 0;
low = len * lowlevel / maxlevel; // Calculate length of lower level
high = len * highlevel / maxlevel; // Calculate length of higher level
if (high < low) high = low; // Higher level is never lower than lower
if (low > lastlow) // Draw an increasing low level
{
tft.fillRect(x+1+lastlow, y+1, low-lastlow, height, LowColour);
if (high > lasthigh) // Draw an increasing high level
{
if (lasthigh > low)
tft.fillRect(x+1+lasthigh, y+1, high-lasthigh, height, HighColour);
else if ((lasthigh < low) && (high != low))
tft.fillRect(x+1+low, y+1, high-low, height, HighColour);
}
else if (high < lasthigh) // Draw a decreasing high level
tft.fillRect(x+1+high, y+1, lasthigh-high, height, blnkColour);
}
else if (low < lastlow) // Draw a decreasing low level
{
if (high <= lastlow) // Adjust high level
{
if (high != low)
tft.fillRect(x+1+low, y+1, high-low, height, HighColour);
if (lasthigh != high)
tft.fillRect(x+1+high, y+1, lasthigh-high, height, blnkColour);
}
else if (high >= lastlow) // Adjust high level
{
tft.fillRect(x+1+low, y+1, lastlow-low, height, HighColour);
if (high < lasthigh)
tft.fillRect(x+1+high, y+1, lasthigh-high, height, blnkColour);
else if (high > lasthigh)
tft.fillRect(x+1+lasthigh, y+1, high-lasthigh, height, HighColour);
}
}
else if (high > lasthigh) // Draw an increasing high level while low level is unchanged
tft.fillRect(x+1+lasthigh, y+1, high-lasthigh, height, HighColour);
else if (high < lasthigh) // Draw a decreasing high level while low level is unchanged
tft.fillRect(x+1+high, y+1, lasthigh-high, height, blnkColour);
lastlow = low;
lasthigh = high;
}
void PowerMeter::erasegraph(void)
{
if (lasthigh > 0)
{
tft.fillRect(x+1, y+1, lasthigh, height, blnkColour);
lastlow = 0;
lasthigh = 0;
lastmax = 0;
}
}
//-----------------------------------------------------------------------------------------
// Initialise SWR Meter,
// define left x and top y coordinates;
// length x; height y;
// graph, lowSWR, midSWR and highSWR colour
//-----------------------------------------------------------------------------------------
void VSWRmeter::init (int16_t xcoord, int16_t ycoord, int16_t xlen, int16_t ylen,
int16_t graphcolour, int16_t lowcolour, int16_t midcolour, int16_t highcolour)
{
x = xcoord;
y = ycoord;
len = xlen;
height = ylen;
GaugeColour = graphcolour;
lSWRcolour = lowcolour;
mSWRcolour = midcolour;
hSWRcolour = highcolour;
}
void VSWRmeter::init (int16_t xcoord, int16_t ycoord, int16_t xlen, int16_t ylen)
{
x = xcoord;
y = ycoord;
len = xlen;
height = ylen;
}
//-----------------------------------------------------------------------------------------
// Draw SWR Meter Scale
// input arguments are starting x&y positions
//-----------------------------------------------------------------------------------------
void VSWRmeter::scale(void)
{
if (erased) // Draw complete Graph if requested and not already drawn
{
drawscale(GaugeColour); // Always the same
erased = false;
}
}
void VSWRmeter::erase(void)
{
if (!erased)
{
graph(2.0, 3.0, 0.0);
drawscale(blnkColour);
midthresh = 0;
highthresh = 0;
erased = true;
}
}
void VSWRmeter::drawscale(int16_t colour)
{
int16_t offs;
bool subdecimal;
double a;
double scalemark[] = { 1, 1.5, 2, 3, 4, 5, 6, 7, 8, 10 };
double scaletick[] = { 1.1, 1.2, 1.3, 1.4, 1.6, 1.7, 1.8, 1.9,
2.2, 2.4, 2.6, 2.8, 3.2, 3.4, 3.6, 3.8,
4.5, 5.5, 6.5, 9 };
tft.setFont(DroidSansMono_16);
tft.setTextColor(colour);
// Draw the Graph Outline
tft.drawRect(x, y,len+2, height+2, colour);
// Draw the Scale line below
tft.drawFastHLine(x, y+height+2, len+2, colour);
// Draw the Scale
for (uint8_t i = 0; i < 10; i++) // Draw full size scale ticks and numbers
{
offs = x+1 + len * log10(scalemark
);
tft.drawFastVLine(offs, y+height+2, 5, colour);
if ((scalemark < 10) && // Decide whether we have subdecimals or not
(modf(scalemark, &a) > 0.05) &&
(modf(scalemark, &a) < 0.95))
subdecimal = true;
else subdecimal = false;
if (subdecimal) offs -= 6; // Position text and print
else if (scalemark>=10) offs -= 11;
else offs -= 2;
tft.setCursor(offs, y+height+9);
if (scalemark<10) tft.print(scalemark, subdecimal);
else tft.print("10"); // Print indicator at highest mark
}
for (uint8_t i = 0; i < 20; i++) // Draw half size scale ticks
{
offs = x+1 + len * log10(scaletick);
tft.drawFastVLine(offs, y+height+2, 3, colour);
}
}
//-----------------------------------------------------------------------------------------
// Draw SWR Meter Graph
// input arguments are starting x&y positions, swr value, mid and high indications.
// swr, mid and high as values between 1 and infinite. mid and high for colour
// indication above set value, typically 2.0 and 3.0
//-----------------------------------------------------------------------------------------
void VSWRmeter::graph(double mid, double high, double swr)
{
int16_t barlow; // Length of SWR bar on graph
int16_t barmid = 0; // Indicate yellow above this swr level (mid threshold)
int16_t barhigh = 0; // Indicate red above this swr level (high threshold)
// Set sane limits
if (swr < 1.0) swr = 1.0;
if (mid > high) mid = high;
// We need to force a blank slate to redraw everything if scale thresholds have changed
if ((midthresh != mid) || (highthresh != high))
{
swr = 1.0; // Set SWR at 1.0:1 (eq. 0)
// Prepare scale thresholds
scalemid = len * log10(mid); // Recalculate Mid and High threshold in bar lengths
scalehigh = len * log10(high);
lastlow = scalemid; // Set previous value as the highest
lastmid = scalehigh-scalemid; // possible value, to force a redraw
lasthigh = len-scalehigh;
midthresh = mid; // And store threshold values for next comparison
highthresh = high;
}
// Prepare input values
if (swr > 10) swr = 10;
barlow = len * log10(swr); // Determine overall bar length
barhigh = barlow - scalehigh; // Determine length of high bar
if (barhigh < 0) barhigh = 0;
if (barhigh > 0) barmid = scalehigh - scalemid; // Determine length of mid bar
else barmid = barlow - scalemid;
if (barmid < 0) barmid = 0;
if (barlow > scalemid) barlow = scalemid; // Truncate low bar if needed
// Fill the bargraph
if (barlow > lastlow) // Low bar increasing
tft.fillRect(x+1+lastlow, y+1, barlow-lastlow, height, lSWRcolour); // Fill difference between old and new
else if (barlow < lastlow) // Low bar decreasing
tft.fillRect(x+1+barlow, y+1, lastlow-barlow, height, blnkColour); // Empty difference between old and new
if (barmid > lastmid) // Mid bar increasing
tft.fillRect(x+1+lastmid+scalemid, y+1, barmid-lastmid, height, mSWRcolour); // Fill difference between old and new
else if (barmid < lastmid) // Mid bar decreasing
tft.fillRect(x+1+barmid+scalemid, y+1, lastmid-barmid, height, blnkColour); // Empty difference between old and new
if (barhigh > lasthigh) // High bar increasing
tft.fillRect(x+1+lasthigh+scalehigh, y+1, barhigh-lasthigh, height,hSWRcolour); // Fill difference between old and new
else if (barhigh < lasthigh) // High bar decreasing
tft.fillRect(x+1+barhigh+scalehigh, y+1, lasthigh-barhigh, height, blnkColour); // Empty difference between old and new
lastlow = barlow;
lastmid = barmid;
lasthigh= barhigh;
}
//-----------------------------------------------------------------------------------------
// Initialise Modulation Scope,
// define left x and top y coordinates;
// length x; height y;
// border, trace, and peak colour
//-----------------------------------------------------------------------------------------
void ModulationScope::init (int16_t xcoord, int16_t ycoord, int16_t xlen, int16_t ylen,
int16_t bordercolour, int16_t tracecolour, int16_t peakcolour)
{
borderColour= bordercolour;
traceColour = tracecolour;
peakColour = peakcolour;
init(xcoord, ycoord, xlen, ylen);
}
void ModulationScope::init (int16_t xcoord, int16_t ycoord, int16_t xlen, int16_t ylen)
{
x = xcoord;
y = ycoord;
len = xlen;
if (len > SCOPE_BUFSIZE) len = SCOPE_BUFSIZE;
height = ylen;
y_axis0 = y+1 + height/2;
x_axis0 = x+1;
y_max = height/2;
}
//-----------------------------------------------------------------------------------------
// Erase Modulation Scope
//-----------------------------------------------------------------------------------------
void ModulationScope::erase(void)
{
if (!erased)
{
tft.fillRect(x, y,len+2, height+15, blnkColour); // A simple crude draw blank rectangle
for (uint16_t a=0; a<len; a++) olddata[a] = 0; // Erase scope redraw data
in_pos = 0;
out_pos = 0;
erased = true;
drawn = false;
}
}
void ModulationScope::rate(int16_t rate)
{
rateDivisor = rate;
}
//-----------------------------------------------------------------------------------------
// Update the Modulation Scope circulr buffer with one measurement
//-----------------------------------------------------------------------------------------
void ModulationScope::adddata(double level, double fullscale)
{
if (rateCount <= 0) // Only add data every 1/rateDivisor time.
{
rateCount = rateDivisor;
if (fullscale < level) fullscale = level; // Set sane limits
switch (R.low_power_floor) // Set minimum fullscale at 50x selected Low Power Floor
{
case FLOOR_TEN_mW:
if (fullscale<500.0) fullscale = 500.0; // 500 mW
break;
case FLOOR_ONE_mW:
if (fullscale < 50.0) fullscale = 50.0; // 50 mW
break;
case FLOOR_100_uW:
if (fullscale < 5) fullscale = 5; // 5 mW
break;
case FLOOR_TEN_uW:
if (fullscale < 0.5) fullscale = 0.5; // 500 uW
break;
case FLOOR_ONE_uW:
default:
if (fullscale < .05) fullscale = .05; // 50 uW
}
newdata[in_pos++] = level/fullscale*y_max; // Prepare and store incoming level
if (in_pos >= len) in_pos = 0;
}
rateCount--;
}
//-----------------------------------------------------------------------------------------
// Draw (if needed) and Update the TFT with current Modulation Scope data pending in circular buffer
//-----------------------------------------------------------------------------------------
void ModulationScope::draw(void)
{
if (!drawn)
{
tft.setFont(DroidSansMono_16);
tft.drawRect(x, y,len+2, height+3, borderColour); // Draw the Scope Outline
tft.setTextColor(borderColour);
tft.setCursor(x+len - 223, y+height + 5);
//tft.print("Modulation Scope"); // and print title
erased = false;
drawn = true;
}
}
void ModulationScope::update(void)
{
int16_t y_start, y_stop, y_len; // Coordinates to draw
draw(); // Draw scope widget if need be
while (out_pos != in_pos) // Only draw every 1/rateDivisor time.
{
if (newdata[out_pos] > olddata[out_pos]) // Draw/Add Above y0
{
y_start = y_axis0 - newdata[out_pos];
y_stop = y_axis0 - olddata[out_pos];
y_len = y_stop - y_start;
if (y_len>0) tft.drawFastVLine(x_axis0+out_pos, y_start+1, y_len, traceColour);
tft.drawPixel(x_axis0+out_pos,y_start, peakColour);
y_start = y_axis0 + olddata[out_pos]; // Draw/Add Below y0
y_stop = y_axis0 + newdata[out_pos];
y_len = y_stop - y_start;
if (y_len>0) tft.drawFastVLine(x_axis0+out_pos, y_start, y_len, traceColour);
tft.drawPixel(x_axis0+out_pos,y_stop, peakColour);
}
else if (newdata[out_pos] < olddata[out_pos])
{
y_start = y_axis0 - olddata[out_pos]; // Erase Above y0
y_stop = y_axis0 - newdata[out_pos];
y_len = y_stop - y_start;
if (y_len>0) tft.drawFastVLine(x_axis0+out_pos, y_start, y_len, blnkColour);
tft.drawPixel(x_axis0+out_pos,y_stop, peakColour);
y_start = y_axis0 + newdata[out_pos]; // Erase Below y0
y_stop = y_axis0 + olddata[out_pos];
y_len = y_stop - y_start;
if (y_len>0) tft.drawFastVLine(x_axis0+out_pos, y_start+1, y_len, blnkColour);
tft.drawPixel(x_axis0+out_pos,y_start, peakColour);
}
else if (newdata[out_pos] == 0) tft.drawPixel(x_axis0+out_pos,y_axis0, peakColour);
olddata[out_pos] = newdata[out_pos];
out_pos++;
if (out_pos >= len) out_pos = 0;
}
}
//-----------------------------------------------------------------------------------------
// Init size, shape and colour of Text LCD.
// Variables are: columns, rows; upper left corner x, y; Font_name, FG Colour, BG Colour
//-----------------------------------------------------------------------------------------
// NOTE: Max size of character array (columns * rows) is fixed at LCD_TEXTSIZE characters
// variables are columns, rows; upper left corner x, y; Font_name, FG Colour, BG Colour
void TextBox::init(int16_t _col, int16_t _row, int16_t _xoffs, int16_t _yoffs,
const ILI9341_t3_font_t &f, int16_t _fontColour, int16_t _blnkColour)
{
xoffs = _xoffs;
yoffs = _yoffs;
Col = _col;
Row = _row;
font = &f;
fontColour = _fontColour;
blnkColour = _blnkColour;
tft.setFont(*font); // Determine font size
tft.setTextColor(BLACK);
tft.setCursor(0,0);
tft.print("a"); // Print an arbitrary character to determine
fontXsize = tft.getCursorX(); // size of each char, using monospace font
tft.println();
fontYsize = tft.getCursorY();
fontYsize = fontXsize * 2.1;
tft.setCursor(0,0);
}
//-----------------------------------------------------------------------------------------
// Move characters to TFT LCD from virtual LCD
// This function only updates character positions that have changed
//-----------------------------------------------------------------------------------------
void TextBox::transfer(void)
{
uint16_t line, column, character=0;
tft.setFont(*font);
for (line = 0; line < Row; line++)
{
for (column = 0; column < Col; column++)
{
if (virt_lcd[character] != text_lcd[character]) // We have a new character to write out
{
tft.setTextColor(blnkColour);
tft.setCursor(xoffs + fontXsize*column, yoffs + fontYsize*line);
tft.print(text_lcd[character]); // Erase
tft.setTextColor(fontColour);
tft.setCursor(xoffs + fontXsize*column, yoffs + fontYsize*line);
text_lcd[character] = virt_lcd[character];
tft.print(text_lcd[character]); // Write new
}
character++;
if (character>=TEXTBOXSIZE) character=TEXTBOXSIZE; // Redundant, make sure we don't go too far
}
}
}
//-----------------------------------------------------------------------------------------
// Print to a Virtual LCD - LCD_TEXTSIZE character long string representing a Column*Row LCD
//-----------------------------------------------------------------------------------------
void TextBox::write(char ch)
{
uint16_t virt_pos;
// Print to the ColxRow size virtual LCD
virt_pos = virt_x + Col*virt_y; // Determine position on virt LCD
if ((virt_pos >= TEXTBOXSIZE) || (virt_pos >= (Col*Row))) virt_pos = 0; // At end, wrap around to beginning
virt_lcd[virt_pos++] = ch; // Place character on virt LCD
// After print, derive new x,y coordinates in our Column by Row matrix
virt_x = virt_pos;
for(virt_y = 0; virt_y < Row && virt_x >= Col;virt_y++)
{
virt_x -=Col;
}
}
void TextBox:rint(const char *ch_in)
{
uint16_t virt_len;
virt_len = strlen(ch_in); // Print to the Row*Col sized virtual LCD
for (uint16_t i = 0; i < virt_len; i++)
{
write(ch_in);
}
}
//-----------------------------------------------------------------------------------------
// SetCursor virtual LCD
//-----------------------------------------------------------------------------------------
void TextBox::setCursor(int16_t x, int16_t y)
{
virt_x = x;
virt_y = y;
}
//-----------------------------------------------------------------------------------------
// Clear virtual LCD
//-----------------------------------------------------------------------------------------
void TextBox::clear(void)
{
uint16_t lcdsize = Row * Col;
if (lcdsize > TEXTBOXSIZE) lcdsize = TEXTBOXSIZE;
for (uint16_t i=0; i<lcdsize; i++) virt_lcd=' '; // Print a lot of spaces to virt LCD
virt_x = 0;
virt_y = 0;
}
PSWRtft
Code:
ifndef _PSWRtft_h_
#define _PSWRtft_h_
#include <Arduino.h>
#include <SPI.h>
#include <RA8875.h>
#include "_fonts.h"
class PowerMeter
{
public:
//------------------------------------------------------------------------------
// Init size, shape and colour of graph
// left x; top y; length x; height y; graph, low and high colour
void init (int16_t, int16_t, int16_t, int16_t, int16_t, int16_t, int16_t);
void init (int16_t, int16_t, int16_t, int16_t);
//------------------------------------------------------------------------------
// Draw, Redraw or Erase Meter Scale. range provides optinal unit information, such as "mW", "W", "kW"
// input argument is a number from 1.0 and up, divided into 10 or 11 segments (11 if (scale*10)%11=0 )
void scale(double s, char *range); // Scale Erases if required and then draws everything
void scale(double s) { scale(s, '\0'); }// Blank if no scale range string
void erase(void); // Erases everything
//------------------------------------------------------------------------------
// Draw Meter Graph
// input arguments are low value, high value and full scale value
void graph(double, double, double);
private:
void drawscale(double, int16_t, char*); // Draws the scale for the graph. Colour to draw/erase
void printunits(int16_t, char*); // Prints an units indication at the last scale tick
void drawframe(int16_t); // Draws the frame around the graph
void erasegraph(void); // Erase the current graph contents
int16_t x = 1;
int16_t y = 15;
int16_t len = 725;
int16_t height = 70;
int16_t GaugeColour = WHITE;
int16_t LowColour = YELLOW;
int16_t HighColour = BLUE;
int16_t blnkColour = BLACK;
double lastmax; // Max Level for full readout. We have to redraw all if this changes
int16_t lastlow, lasthigh; // Prev levels for the two gauges, used to redraw only what is necessary
double current_scale = 0;
char current_range[10];
bool erased = true; // Keep track of whether graph needs to be redrawn
};
class VSWRmeter
{
public:
//------------------------------------------------------------------------------
// Init size, shape and colour of VSWR graph
// left x; top y; length x; height y; graph, low SWR, mid SWR, high SWR colour
void init (int16_t, int16_t, int16_t, int16_t, int16_t, int16_t, int16_t, int16_t);
void init (int16_t, int16_t, int16_t, int16_t);
//------------------------------------------------------------------------------
// Draw or Erase VSWR Meter Scale (no value)
void scale(void);
void erase(void); // Erases everything
//------------------------------------------------------------------------------
// Draw VSWR Meter Graph
// input arguments are mid SWR, high SWR and actual SWR input value
void graph(double, double, double);
private:
void drawscale(int16_t);
int16_t x = 1;
int16_t y = 175;
int16_t len = 725; //300
int16_t height = 70;
int16_t GaugeColour = WHITE;
int16_t lSWRcolour = GREEN;
int16_t mSWRcolour = ORANGE;
int16_t hSWRcolour = RED;
int16_t blnkColour = BLACK;
int16_t scalemid, scalehigh; // Calculated log10 of mid and high values
int16_t lastlow, lastmid, lasthigh; // Previous values, used to redraw only what is necessary
double midthresh, highthresh; // Keep track of Mid and High thresholds
bool erased = true; // Keep track of whether graph needs to be redrawn
};
#define SCOPE_BUFSIZE 781 // NOTE: Max number of iterations during one X_trace iteration
class ModulationScope
{
public:
//------------------------------------------------------------------------------
// Init size, shape and colour of Modulation Scope
// left x; top y; length x; height y; border, trace and peak colour
void init (int16_t, int16_t, int16_t, int16_t, int16_t, int16_t, int16_t);
void init (int16_t, int16_t, int16_t, int16_t);
void init (void) { init(3, 150, 781, 190); } // Default x, y coordinate settings
//------------------------------------------------------------------------------
// Draw scope if need be, and draw pending data onscreen
void update(void);
//------------------------------------------------------------------------------
// Erase the scope widget
void erase(void);
//------------------------------------------------------------------------------
// Update rate divisor
void rate(int16_t);
//------------------------------------------------------------------------------
// Add one measurement to the x axis sweep (run from within interrupt function)
// input arguments are level and fullscale
void adddata(double, double);
private:
void draw(void); // Draw scope if needed
int16_t x; //= 5;
int16_t y ; //= 5;
int16_t len; //= 310;
int16_t height; //= 180;
int16_t borderColour= GREY;
int16_t traceColour = GREEN;
int16_t peakColour = YELLOW;
int16_t blnkColour = BLACK;
int16_t y_axis0; // Start positions and y axis max deviation, derived from x,y, len, height
int16_t x_axis0;
int16_t y_max;
int16_t newdata[SCOPE_BUFSIZE]; // New data for the scope - fed with data from a circular buffer fed by the interrupt funciton
int16_t in_pos; // Two circular buffer pointers
int16_t out_pos; // this one is also current position on the x axis
int16_t olddata[SCOPE_BUFSIZE]; // Current data on the scope - to add or subtract from...
int16_t rateDivisor=1; // Rate divisor other than 1 results in only every n_th request drawn
int16_t rateCount;
bool erased = false; // Keep track of whether scope needs to be erased
bool drawn = false; // Keep track of whether scope needs to be redrawn
};
#define TEXTBOXSIZE 1800 // NOTE: Max size of character array (columns * rows) is Fixed at 1800 characters
class TextBox
{
public:
//------------------------------------------------------------------------------
// Init size, shape and colour of Text LCD.
// variables are columns, rows; upper left corner x, y; Font_name, FG Colour, BG Colour
void init (int16_t, int16_t, int16_t, int16_t, const ILI9341_t3_font_t &, int16_t, int16_t);
void init (void) { font = &DroidSansMono_20; } // Default settings
//-----------------------------------------------------------------------------------------
// Move characters to LCD from virtual LCD, only updates information that has changed
void transfer(void);
//-----------------------------------------------------------------------------------------
// Print to a Virtual LCD - Max LCD_TEXTSIZE character long string representing a Column*Row LCD
void write(char); // Write char
void print(const char *); // primitive Print command, no smart formatting
void setCursor(int16_t, int16_t); // SetCursor virtual LCD
void clear(void); // Clear virtual LCD
private:
int16_t xoffs = 330; // Graphics display offset coordinates
int16_t yoffs = 80;
int16_t Col = 40; // Default Columns and Rows
int16_t Row = 12;
int16_t fontXsize = 24; // Default font size coordinates for an 18 point font
int16_t fontYsize = 17;
char text_lcd[TEXTBOXSIZE+1]; // Character array representing what is visible on LCD
char virt_lcd[TEXTBOXSIZE+1]; // Character array representing what is pending for LCD
int16_t virt_x, virt_y; // x and y text display coordinates
const ILI9341_t3_font_t *font;
int16_t fontColour = WHITE;
int16_t blnkColour = BLACK;
};
#endif