mirror of
https://github.com/geekammo/MicroView-Arduino-Library.git
synced 2026-02-20 03:21:30 +01:00
Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cfc8b5cb68 | ||
|
|
a4a45b7e6d | ||
|
|
601881997d | ||
|
|
2a7b01cfbc | ||
|
|
b35e3f2e01 | ||
|
|
66405a0972 | ||
|
|
82f3863036 | ||
|
|
301bd6acf5 | ||
|
|
80a0c70c34 | ||
|
|
c75d14abff | ||
|
|
1aa32fb0c2 | ||
|
|
5e24583c31 | ||
|
|
b05451f4c6 | ||
|
|
0d8545d6f8 | ||
|
|
8ae691c4c2 | ||
|
|
12a9c5c2ac | ||
|
|
68f0c20fd5 | ||
|
|
38be4163c0 |
364
MicroView.cpp
364
MicroView.cpp
@@ -604,47 +604,62 @@ void MicroView::circleFill(uint8_t x0, uint8_t y0, uint8_t radius) {
|
||||
|
||||
/** \brief Draw filled circle with color and mode.
|
||||
|
||||
Draw filled circle with radius using color and mode at x,y of the screen buffer.
|
||||
Draw filled circle with radius using color and mode at x,y of the screen
|
||||
buffer. Uses the Bresenham circle algorithm with a few modifications to
|
||||
paint the circle without overlapping draw operations.
|
||||
*/
|
||||
void MicroView::circleFill(uint8_t x0, uint8_t y0, uint8_t radius, uint8_t color, uint8_t mode) {
|
||||
// Don't bother trying to draw something totally offscreen
|
||||
if (x0 - radius >= LCDWIDTH || y0 - radius >= LCDHEIGHT) {
|
||||
return;
|
||||
}
|
||||
|
||||
// High-level algorithm overview:
|
||||
// Scan horizontally from left to right, then top to bottom, checking if each pixel
|
||||
// is within the circle. We use uint16_t's because even the small screen squares beyond 8 bits.
|
||||
uint16_t radiusSq = radius * radius;
|
||||
|
||||
// Optimization: define the start and end onscreen
|
||||
uint16_t xStart = max(0, x0-radius);
|
||||
uint16_t xEnd = min(LCDWIDTH-1, x0+radius);
|
||||
uint16_t yStart = max(0, y0-radius);
|
||||
uint16_t yEnd = min(LCDHEIGHT-1, y0+radius);
|
||||
|
||||
// scan horizontally...
|
||||
for (uint16_t x = xStart; x <= xEnd; ++x) {
|
||||
// Optimization: Record where if we have intersected the circle on this vertical
|
||||
// scan. Once we have intersected, then don't intersect anymore, don't bother
|
||||
// drawing; we've exited the circle.
|
||||
bool intersected = false;
|
||||
|
||||
// Optimization: relative x squared only changes with the outer loop/the horizontal scan.
|
||||
uint16_t rx2 = (x-x0) * (x-x0);
|
||||
|
||||
// Scan vertically...
|
||||
for (uint16_t y = yStart; y <= yEnd; ++y) {
|
||||
uint16_t ry2 = (y-y0) * (y-y0);
|
||||
if (rx2 + ry2 <= radiusSq) {
|
||||
pixel(x, y, color, mode);
|
||||
intersected = true;
|
||||
void MicroView::circleFill(uint8_t x0, uint8_t y0, uint8_t radius, uint8_t
|
||||
color, uint8_t mode) {
|
||||
int8_t x = radius;
|
||||
int8_t y = 0;
|
||||
int8_t radiusError = 1 - x;
|
||||
int8_t y_last = y0 + x;
|
||||
int8_t y_low;
|
||||
int8_t x_alt;
|
||||
int8_t x_alt_max;
|
||||
while (x >= y) {
|
||||
pixel(x + x0, y + y0, color, mode);
|
||||
x_alt = (x0 - x);
|
||||
x_alt_max = x0 + x;
|
||||
while (x_alt < x_alt_max) {
|
||||
pixel(x_alt, y + y0, color, mode);
|
||||
x_alt++;
|
||||
}
|
||||
if (y != x) {
|
||||
pixel(y + x0, x + y0, color, mode);
|
||||
pixel(y + x0, y0 - x, color, mode);
|
||||
}
|
||||
if (y != 0) {
|
||||
pixel(x + x0, y0 - y, color, mode);
|
||||
x_alt = (x0 - x);
|
||||
x_alt_max = x0 + x;
|
||||
while (x_alt < x_alt_max) {
|
||||
pixel(x_alt, y0 - y, color, mode);
|
||||
x_alt++;
|
||||
}
|
||||
else if (intersected) {
|
||||
// We've left the circle. Move on to the next horizontal scan line.
|
||||
break;
|
||||
if (y != x) {
|
||||
pixel(x0 - y, x + y0, color, mode);
|
||||
pixel(x0 - y, y0 - x, color, mode);
|
||||
if (y_last > y0 + x) {
|
||||
x_alt = x0 - y + 1;
|
||||
x_alt_max = x0 + y;
|
||||
y_last = y0 + x;
|
||||
y_low = y0 - x;
|
||||
while (x_alt < x_alt_max) {
|
||||
pixel(x_alt, y_last, color, mode);
|
||||
pixel(x_alt, y_low, color, mode);
|
||||
x_alt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
y++;
|
||||
if (radiusError<0) {
|
||||
radiusError += 2 * y + 1;
|
||||
} else {
|
||||
x--;
|
||||
radiusError += 2 * (y - x + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1361,25 +1376,28 @@ int MicroView::readSerial(void)
|
||||
|
||||
The MicroViewWidget class is the parent class for child widget like MicroViewSlider and MicroViewGauge.
|
||||
*/
|
||||
MicroViewWidget::MicroViewWidget(uint8_t newx, uint8_t newy, int16_t min, int16_t max) {
|
||||
setX(newx);
|
||||
setY(newy);
|
||||
value=0;
|
||||
setMinValue(min);
|
||||
setMaxValue(max);
|
||||
MicroViewWidget::MicroViewWidget(uint8_t newx, uint8_t newy, int16_t min, int16_t max):
|
||||
posX(newx),
|
||||
posY(newy),
|
||||
minValue(min),
|
||||
maxValue(max),
|
||||
value(min)
|
||||
{
|
||||
valLen=getInt16PrintLen(value);
|
||||
setMaxValLen();
|
||||
}
|
||||
|
||||
/** \brief Get widget x position. */
|
||||
uint8_t MicroViewWidget::getX() { return x; }
|
||||
uint8_t MicroViewWidget::getX() { return posX; }
|
||||
|
||||
/** \brief Get widget y position. */
|
||||
uint8_t MicroViewWidget::getY() { return y; }
|
||||
uint8_t MicroViewWidget::getY() { return posY; }
|
||||
|
||||
/** \brief Set widget x position. */
|
||||
void MicroViewWidget::setX(uint8_t newx) { x = newx; }
|
||||
void MicroViewWidget::setX(uint8_t newx) { posX = newx; }
|
||||
|
||||
/** \brief Set widget y position. */
|
||||
void MicroViewWidget::setY(uint8_t newy) { y = newy; }
|
||||
void MicroViewWidget::setY(uint8_t newy) { posY = newy; }
|
||||
|
||||
/** \brief Get minimum value.
|
||||
|
||||
@@ -1403,44 +1421,61 @@ int16_t MicroViewWidget::getValue() { return value; }
|
||||
|
||||
The minimum value of the widget is set to the variable passed in.
|
||||
*/
|
||||
void MicroViewWidget::setMinValue(int16_t min) { minValue=min; }
|
||||
void MicroViewWidget::setMinValue(int16_t min) {
|
||||
minValue = min;
|
||||
setMaxValLen();
|
||||
}
|
||||
|
||||
/** \brief Set maximum value.
|
||||
|
||||
The maximum value of the widget is set to the variable passed in.
|
||||
*/
|
||||
void MicroViewWidget::setMaxValue(int16_t max) { maxValue=max; }
|
||||
|
||||
/** \brief Get the maximum possible print lenth of the value
|
||||
|
||||
Return the maximum number of characters that would be printed using printf("%d", value) for the current value range.
|
||||
*/
|
||||
uint8_t MicroViewWidget::getMaxValLen() {
|
||||
uint8_t minLen, maxLen;
|
||||
|
||||
maxLen = getInt16PrintLen(maxValue);
|
||||
minLen = getInt16PrintLen(minValue);
|
||||
return maxLen >= minLen ? maxLen : minLen;
|
||||
void MicroViewWidget::setMaxValue(int16_t max) {
|
||||
maxValue = max;
|
||||
setMaxValLen();
|
||||
}
|
||||
|
||||
/** \brief Set current value.
|
||||
/** \brief Get the maximum possible print length of the value
|
||||
|
||||
The current value of the widget is set to the variable passed in.
|
||||
Return the maximum number of characters that would be printed using uView.print(value) for the current value range.
|
||||
*/
|
||||
void MicroViewWidget::setValue(int16_t val) {
|
||||
if ((val<=maxValue) && (val>=minValue)){
|
||||
value=val;
|
||||
this->draw();
|
||||
uint8_t MicroViewWidget::getMaxValLen() { return maxValLen; }
|
||||
|
||||
/** \brief Set current value and update widget.
|
||||
|
||||
The current value of the widget is set to the variable passed in and the widget is drawn with the new value.
|
||||
*/
|
||||
void MicroViewWidget::setValue(int16_t val) {
|
||||
setValue(val, true);
|
||||
}
|
||||
|
||||
/** \brief Set current value with optional update.
|
||||
|
||||
The current value of the widget is set to the variable passed in. The widget is drawn with the new value if the doDraw argument is true.
|
||||
*/
|
||||
void MicroViewWidget::setValue(int16_t val, boolean doDraw) {
|
||||
if ((val<=maxValue) && (val>=minValue)) {
|
||||
value = val;
|
||||
valLen = getInt16PrintLen(val);
|
||||
if (doDraw) {
|
||||
this->draw();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** \brief Get the print length of the value.
|
||||
|
||||
Return the number of characters that would be printed using uView.print(value) for the current value.
|
||||
*/
|
||||
uint8_t MicroViewWidget::getValLen() { return valLen; }
|
||||
|
||||
/** \brief MicroView Widget reDraw routine.
|
||||
|
||||
Redraws the widget.
|
||||
*/
|
||||
void MicroViewWidget::reDraw() {
|
||||
needFirstDraw=true;
|
||||
this->drawFace();
|
||||
this->drawPointer(); // initial pointer (will be erased)
|
||||
this->draw();
|
||||
}
|
||||
|
||||
@@ -1449,12 +1484,22 @@ void MicroViewWidget::reDraw() {
|
||||
The value is right justified with leading spaces, within a field the length of the maximum posible for the widget's value range.
|
||||
*/
|
||||
void MicroViewWidget::drawNumValue(int16_t value) {
|
||||
char strBuffer[7];
|
||||
char formatStr[] = "%1d";
|
||||
|
||||
formatStr[1] = '0' + getMaxValLen(); // Set the field width for the value range
|
||||
sprintf(strBuffer, formatStr, value);
|
||||
uView.print(strBuffer);
|
||||
for (uint8_t i = maxValLen - getInt16PrintLen(value); i > 0; i--) {
|
||||
uView.print(" ");
|
||||
}
|
||||
uView.print(value);
|
||||
}
|
||||
|
||||
/* Set the maximum number of characters that would be printed
|
||||
using uView.print(value) for the current value range.
|
||||
*/
|
||||
void MicroViewWidget::setMaxValLen() {
|
||||
uint8_t minLen, maxLen;
|
||||
|
||||
maxLen = getInt16PrintLen(maxValue);
|
||||
minLen = getInt16PrintLen(minValue);
|
||||
maxValLen = maxLen >= minLen ? maxLen : minLen;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------------
|
||||
@@ -1469,13 +1514,15 @@ void MicroViewWidget::drawNumValue(int16_t value) {
|
||||
|
||||
Initialise the MicroViewSlider widget with default style.
|
||||
*/
|
||||
MicroViewSlider::MicroViewSlider(uint8_t newx, uint8_t newy, int16_t min, int16_t max):MicroViewWidget(newx, newy, min, max) {
|
||||
style=0;
|
||||
totalTicks=30;
|
||||
noValDraw=false;
|
||||
prevValue=getMinValue();
|
||||
needFirstDraw=true;
|
||||
MicroViewSlider::MicroViewSlider(uint8_t newx, uint8_t newy, int16_t min, int16_t max):
|
||||
MicroViewWidget(newx, newy, min, max),
|
||||
style(0),
|
||||
totalTicks(30),
|
||||
noValDraw(false),
|
||||
prevValue(value)
|
||||
{
|
||||
drawFace();
|
||||
drawPointer(); // Initial pointer (will be erased)
|
||||
draw();
|
||||
}
|
||||
|
||||
@@ -1484,7 +1531,10 @@ MicroViewSlider::MicroViewSlider(uint8_t newx, uint8_t newy, int16_t min, int16_
|
||||
Initialise the MicroViewSlider widget with style WIDGETSTYLE0 or WIDGETSTYLE1 or WIDGETSTYLE2 (like 0, but vertical) or WIDGETSTYLE3 (like 1, but vertical).
|
||||
Add WIDGETNOVALUE to the style to suppress displaying the numeric value. E.g. WIDGETSTYLE0 + WIDGETNOVALUE
|
||||
*/
|
||||
MicroViewSlider::MicroViewSlider(uint8_t newx, uint8_t newy, int16_t min, int16_t max, uint8_t sty):MicroViewWidget(newx, newy, min, max) {
|
||||
MicroViewSlider::MicroViewSlider(uint8_t newx, uint8_t newy, int16_t min, int16_t max, uint8_t sty):
|
||||
MicroViewWidget(newx, newy, min, max),
|
||||
prevValue(value)
|
||||
{
|
||||
noValDraw = sty & WIDGETNOVALUE; // set "no value draw" flag as specified
|
||||
|
||||
switch(sty & ~WIDGETNOVALUE) {
|
||||
@@ -1506,9 +1556,8 @@ MicroViewSlider::MicroViewSlider(uint8_t newx, uint8_t newy, int16_t min, int16_
|
||||
break;
|
||||
}
|
||||
|
||||
prevValue=getMinValue();
|
||||
needFirstDraw=true;
|
||||
drawFace();
|
||||
drawPointer(); // Initial pointer (will be erased)
|
||||
draw();
|
||||
}
|
||||
|
||||
@@ -1517,32 +1566,30 @@ MicroViewSlider::MicroViewSlider(uint8_t newx, uint8_t newy, int16_t min, int16_
|
||||
Draw image/diagram representing the widget's face.
|
||||
*/
|
||||
void MicroViewSlider::drawFace() {
|
||||
uint8_t offsetX, offsetY, endOffset;
|
||||
offsetX=getX();
|
||||
offsetY=getY();
|
||||
uint8_t endOffset;
|
||||
|
||||
//Horizontal styles, style 0 or 1
|
||||
if (style==0 || style==1) {
|
||||
endOffset = offsetX + totalTicks + 2;
|
||||
endOffset = posX + totalTicks + 2;
|
||||
// Draw minor ticks
|
||||
for (uint8_t i=offsetX+1; i<endOffset; i+=2) {
|
||||
uView.lineV(i, offsetY+5, 3);
|
||||
for (uint8_t i=posX+1; i<endOffset; i+=2) {
|
||||
uView.lineV(i, posY+5, 3);
|
||||
}
|
||||
// Draw extensions for major ticks
|
||||
for (uint8_t i=offsetX+1; i<endOffset; i+=10) {
|
||||
uView.lineV(i, offsetY+3, 2);
|
||||
for (uint8_t i=posX+1; i<endOffset; i+=10) {
|
||||
uView.lineV(i, posY+3, 2);
|
||||
}
|
||||
}
|
||||
//Vertical styles, style 2 or 3
|
||||
else {
|
||||
endOffset = offsetY + totalTicks + 2;
|
||||
endOffset = posY + totalTicks + 2;
|
||||
// Draw minor ticks
|
||||
for (uint8_t i=offsetY+1; i<=endOffset; i+=2) {
|
||||
uView.lineH(offsetX, i, 3);
|
||||
for (uint8_t i=posY+1; i<=endOffset; i+=2) {
|
||||
uView.lineH(posX, i, 3);
|
||||
}
|
||||
// Draw extensions for major ticks
|
||||
for (uint8_t i=offsetY+1; i<=endOffset; i+=10) {
|
||||
uView.lineH(offsetX+3, i, 2);
|
||||
for (uint8_t i=posY+1; i<=endOffset; i+=10) {
|
||||
uView.lineH(posX+3, i, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1552,35 +1599,24 @@ void MicroViewSlider::drawFace() {
|
||||
Convert the current value of the widget and draw the ticker representing the value.
|
||||
*/
|
||||
void MicroViewSlider::draw() {
|
||||
// Draw the initial pointer or erase the previous pointer
|
||||
drawPointer();
|
||||
|
||||
if (needFirstDraw) {
|
||||
needFirstDraw=false;
|
||||
}
|
||||
else {
|
||||
prevValue=getValue();
|
||||
// Draw current pointer
|
||||
drawPointer();
|
||||
}
|
||||
drawPointer(); // Erase the previous pointer
|
||||
prevValue=value;
|
||||
drawPointer(); // Draw the current pointer
|
||||
|
||||
// Draw numeric value if required
|
||||
if (!noValDraw) {
|
||||
uint8_t offsetX = getX();
|
||||
uint8_t offsetY = getY();
|
||||
|
||||
switch(style) {
|
||||
case 0:
|
||||
uView.setCursor(offsetX+totalTicks+4, offsetY+1);
|
||||
uView.setCursor(posX+totalTicks+4, posY+1);
|
||||
break;
|
||||
case 1:
|
||||
uView.setCursor(offsetX, offsetY+10);
|
||||
uView.setCursor(posX, posY+10);
|
||||
break;
|
||||
case 2:
|
||||
uView.setCursor(offsetX+1, offsetY+totalTicks+4);
|
||||
uView.setCursor(posX+1, posY+totalTicks+4);
|
||||
break;
|
||||
default:
|
||||
uView.setCursor(offsetX+9, offsetY);
|
||||
uView.setCursor(posX+9, posY);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1591,18 +1627,16 @@ void MicroViewSlider::draw() {
|
||||
// Use XOR mode to erase or draw the pointer for prevValue
|
||||
void MicroViewSlider::drawPointer() {
|
||||
uint8_t tickPosition;
|
||||
uint8_t offsetX = getX();
|
||||
uint8_t offsetY = getY();
|
||||
|
||||
if (style==0 || style==1) { // Horizontal
|
||||
tickPosition = ((float)(uint16_t)(prevValue-getMinValue())/(float)(uint16_t)(getMaxValue()-getMinValue()))*totalTicks;
|
||||
uView.lineH(offsetX+tickPosition,offsetY, 3, WHITE, XOR);
|
||||
uView.pixel(offsetX+1+tickPosition,offsetY+1, WHITE, XOR);
|
||||
tickPosition = ((float)(uint16_t)(prevValue-minValue)/(float)(uint16_t)(maxValue-minValue))*totalTicks;
|
||||
uView.lineH(posX+tickPosition, posY, 3, WHITE, XOR);
|
||||
uView.pixel(posX+1+tickPosition, posY+1, WHITE, XOR);
|
||||
}
|
||||
else { // Vertical
|
||||
tickPosition = ((float)(uint16_t)(getMaxValue()-prevValue)/(float)(uint16_t)(getMaxValue()-getMinValue()))*totalTicks;
|
||||
uView.lineV(offsetX+7, offsetY+tickPosition, 3, WHITE, XOR);
|
||||
uView.pixel(offsetX+6, offsetY+1+tickPosition, WHITE, XOR);
|
||||
tickPosition = ((float)(uint16_t)(maxValue-prevValue)/(float)(uint16_t)(maxValue-minValue))*totalTicks;
|
||||
uView.lineV(posX+7, posY+tickPosition, 3, WHITE, XOR);
|
||||
uView.pixel(posX+6, posY+1+tickPosition, WHITE, XOR);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1618,13 +1652,15 @@ void MicroViewSlider::drawPointer() {
|
||||
|
||||
Initialise the MicroViewGauge widget with default style.
|
||||
*/
|
||||
MicroViewGauge::MicroViewGauge(uint8_t newx, uint8_t newy, int16_t min, int16_t max):MicroViewWidget(newx, newy, min, max) {
|
||||
style=0;
|
||||
radius=15;
|
||||
noValDraw=false;
|
||||
prevValue=getMinValue();
|
||||
needFirstDraw=true;
|
||||
MicroViewGauge::MicroViewGauge(uint8_t newx, uint8_t newy, int16_t min, int16_t max):
|
||||
MicroViewWidget(newx, newy, min, max),
|
||||
style(0),
|
||||
radius(15),
|
||||
noValDraw(false),
|
||||
prevValue(value)
|
||||
{
|
||||
drawFace();
|
||||
drawPointer(); // Initial pointer (will be erased)
|
||||
draw();
|
||||
}
|
||||
|
||||
@@ -1633,7 +1669,10 @@ MicroViewGauge::MicroViewGauge(uint8_t newx, uint8_t newy, int16_t min, int16_t
|
||||
Initialise the MicroViewGauge widget with style WIDGETSTYLE0 or WIDGETSTYLE1.
|
||||
Add WIDGETNOVALUE to the style to suppress displaying the numeric value. E.g. WIDGETSTYLE0 + WIDGETNOVALUE
|
||||
*/
|
||||
MicroViewGauge::MicroViewGauge(uint8_t newx, uint8_t newy, int16_t min, int16_t max, uint8_t sty):MicroViewWidget(newx, newy, min, max) {
|
||||
MicroViewGauge::MicroViewGauge(uint8_t newx, uint8_t newy, int16_t min, int16_t max, uint8_t sty):
|
||||
MicroViewWidget(newx, newy, min, max),
|
||||
prevValue(value)
|
||||
{
|
||||
noValDraw = sty & WIDGETNOVALUE; // set "no value draw" flag as specified
|
||||
|
||||
if ((sty & ~WIDGETNOVALUE) == WIDGETSTYLE0) {
|
||||
@@ -1644,9 +1683,9 @@ MicroViewGauge::MicroViewGauge(uint8_t newx, uint8_t newy, int16_t min, int16_t
|
||||
style=1;
|
||||
radius=23;
|
||||
}
|
||||
prevValue=getMinValue();
|
||||
needFirstDraw=true;
|
||||
|
||||
drawFace();
|
||||
drawPointer(); // Initial pointer (will be erased)
|
||||
draw();
|
||||
}
|
||||
|
||||
@@ -1655,12 +1694,9 @@ MicroViewGauge::MicroViewGauge(uint8_t newx, uint8_t newy, int16_t min, int16_t
|
||||
Draw image/diagram representing the widget's face.
|
||||
*/
|
||||
void MicroViewGauge::drawFace() {
|
||||
uint8_t offsetX, offsetY;
|
||||
float degreeSec, fromSecX, fromSecY, toSecX, toSecY;
|
||||
offsetX=getX();
|
||||
offsetY=getY();
|
||||
|
||||
uView.circle(offsetX,offsetY,radius);
|
||||
uView.circle(posX, posY, radius);
|
||||
|
||||
for (int i=150;i<=390;i+=30) { // Major tick from 150 degree to 390 degree
|
||||
degreeSec=i*(PI/180);
|
||||
@@ -1668,7 +1704,7 @@ void MicroViewGauge::drawFace() {
|
||||
fromSecY = sin(degreeSec) * (radius / 1.5);
|
||||
toSecX = cos(degreeSec) * radius;
|
||||
toSecY = sin(degreeSec) * radius;
|
||||
uView.line(1+offsetX+fromSecX,1+offsetY+fromSecY,1+offsetX+toSecX,1+offsetY+toSecY);
|
||||
uView.line(1+posX+fromSecX, 1+posY+fromSecY, 1+posX+toSecX, 1+posY+toSecY);
|
||||
}
|
||||
|
||||
if (radius>15) {
|
||||
@@ -1678,7 +1714,7 @@ void MicroViewGauge::drawFace() {
|
||||
fromSecY = sin(degreeSec) * (radius / 1.3);
|
||||
toSecX = cos(degreeSec) * radius;
|
||||
toSecY = sin(degreeSec) * radius;
|
||||
uView.line(1+offsetX+fromSecX,1+offsetY+fromSecY,1+offsetX+toSecX,1+offsetY+toSecY);
|
||||
uView.line(1+posX+fromSecX, 1+posY+fromSecY, 1+posX+toSecX, 1+posY+toSecY);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1688,27 +1724,18 @@ void MicroViewGauge::drawFace() {
|
||||
Convert the current value of the widget and draw the ticker representing the value.
|
||||
*/
|
||||
void MicroViewGauge::draw() {
|
||||
// Draw the initial pointer or erase the previous pointer
|
||||
drawPointer();
|
||||
|
||||
if (needFirstDraw) {
|
||||
needFirstDraw=false;
|
||||
}
|
||||
else {
|
||||
prevValue=getValue();
|
||||
// Draw current pointer
|
||||
drawPointer();
|
||||
}
|
||||
drawPointer(); // Erase the previous pointer
|
||||
prevValue=value;
|
||||
drawPointer(); // Draw the current pointer
|
||||
|
||||
// Draw numeric value if required
|
||||
if (!noValDraw) {
|
||||
uint8_t offsetY = getY();
|
||||
uint8_t offsetX = getX() - (getMaxValLen() * 3 - 1); // Offset left of centre to print the value
|
||||
uint8_t offsetX = posX - (maxValLen * 3 - 1); // Offset left of centre to print the value
|
||||
|
||||
if (style > 0)
|
||||
uView.setCursor(offsetX, offsetY+10);
|
||||
uView.setCursor(offsetX, posY+10);
|
||||
else
|
||||
uView.setCursor(offsetX, offsetY+11);
|
||||
uView.setCursor(offsetX, posY+11);
|
||||
|
||||
drawNumValue(prevValue);
|
||||
}
|
||||
@@ -1716,19 +1743,15 @@ void MicroViewGauge::draw() {
|
||||
|
||||
// Use XOR mode to erase or draw the pointer for prevValue
|
||||
void MicroViewGauge::drawPointer() {
|
||||
uint8_t offsetX, offsetY;
|
||||
float degreeSec, toSecX, toSecY;
|
||||
|
||||
offsetX = getX();
|
||||
offsetY = getY();
|
||||
|
||||
// total 240 degree in the widget with 150 degree starting point
|
||||
degreeSec = (((float)(uint16_t)(prevValue-getMinValue()) / (float)(uint16_t)(getMaxValue()-getMinValue())
|
||||
degreeSec = (((float)(uint16_t)(prevValue-minValue) / (float)(uint16_t)(maxValue-minValue)
|
||||
* 240) + 150) * (PI / 180);
|
||||
|
||||
toSecX = cos(degreeSec) * (radius / 1.2);
|
||||
toSecY = sin(degreeSec) * (radius / 1.2);
|
||||
uView.line(offsetX,offsetY,1+offsetX+toSecX,1+offsetY+toSecY, WHITE,XOR);
|
||||
uView.line(posX, posY, 1+posX+toSecX, 1+posY+toSecY, WHITE, XOR);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------------
|
||||
@@ -1844,11 +1867,34 @@ MicroView uView;
|
||||
|
||||
/** \brief Get the number of characters for a 16 bit signed value.
|
||||
|
||||
Return the number of characters that would be printed using printf("%d", x) for x being a signed 16 bit integer.
|
||||
Return the number of characters that would be printed using uView.print(x) for x being a signed 16 bit integer.
|
||||
*/
|
||||
uint8_t getInt16PrintLen(int16_t val) {
|
||||
char sbuf[7];
|
||||
int16_t i;
|
||||
uint8_t count;
|
||||
|
||||
return sprintf(sbuf, "%d", val);
|
||||
if (val >= 10000) {
|
||||
return 5;
|
||||
}
|
||||
|
||||
if (val <= -10000) {
|
||||
return 6;
|
||||
}
|
||||
|
||||
if (val >= 0) {
|
||||
count = 1;
|
||||
}
|
||||
else {
|
||||
count = 2;
|
||||
val = abs(val);
|
||||
}
|
||||
|
||||
i = 10;
|
||||
while (val >= i) {
|
||||
count++;
|
||||
i *= 10;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
30
MicroView.h
30
MicroView.h
@@ -230,33 +230,39 @@ private:
|
||||
|
||||
class MicroViewWidget {
|
||||
public:
|
||||
bool needFirstDraw;
|
||||
MicroViewWidget(uint8_t newx, uint8_t newy, int16_t min, int16_t max);
|
||||
uint8_t getX();
|
||||
uint8_t getY();
|
||||
void setX(uint8_t newx);
|
||||
void setY(uint8_t newy);
|
||||
|
||||
int16_t getMinValue();
|
||||
int16_t getMaxValue();
|
||||
int16_t getValue();
|
||||
void setMinValue(int16_t min);
|
||||
void setMaxValue(int16_t max);
|
||||
void setValue(int16_t val);
|
||||
void setValue(int16_t val, boolean doDraw);
|
||||
uint8_t getValLen();
|
||||
uint8_t getMaxValLen();
|
||||
/** \brief Draw widget value overridden by child class. */
|
||||
virtual void draw(){};
|
||||
/** \brief Draw widget face overridden by child class. */
|
||||
virtual void draw(){};
|
||||
/** \brief Draw widget face overridden by child class. */
|
||||
virtual void drawFace(){};
|
||||
void reDraw();
|
||||
void drawNumValue(int16_t value);
|
||||
virtual ~MicroViewWidget(){};
|
||||
private:
|
||||
uint8_t x;
|
||||
uint8_t y;
|
||||
int16_t maxValue;
|
||||
protected:
|
||||
uint8_t posX;
|
||||
uint8_t posY;
|
||||
int16_t minValue;
|
||||
int16_t maxValue;
|
||||
int16_t value;
|
||||
uint8_t valLen;
|
||||
uint8_t maxValLen;
|
||||
private:
|
||||
/** \brief Draw or erase the widget pointer. Overridden by child class. */
|
||||
virtual void drawPointer(){};
|
||||
void setMaxValLen();
|
||||
};
|
||||
|
||||
class MicroViewSlider: public MicroViewWidget{
|
||||
@@ -267,8 +273,8 @@ public:
|
||||
void drawFace();
|
||||
private:
|
||||
void drawPointer();
|
||||
uint8_t totalTicks, style;
|
||||
bool noValDraw;
|
||||
uint8_t style, totalTicks;
|
||||
boolean noValDraw;
|
||||
int16_t prevValue;
|
||||
};
|
||||
|
||||
@@ -280,8 +286,8 @@ public:
|
||||
void drawFace();
|
||||
private:
|
||||
void drawPointer();
|
||||
uint8_t radius, style;
|
||||
bool noValDraw;
|
||||
uint8_t style, radius;
|
||||
boolean noValDraw;
|
||||
int16_t prevValue;
|
||||
};
|
||||
|
||||
|
||||
11
README.md
11
README.md
@@ -92,6 +92,17 @@ void loop() {
|
||||
</code></pre>
|
||||
|
||||
## History
|
||||
**v1.23b: 29th March 2015 by Scott Allen**
|
||||
* added overloaded setValue() function to add a boolean argument doDraw which controls whether the display buffer is updated.
|
||||
|
||||
**v1.22b: 4th October 2014 by Scott Allen and Ben Lewis**
|
||||
* replaced circleFill() with a faster algorithm, better looking circle - Ben Lewis
|
||||
* replaced sprintf with dedicated code, reduced program size - Scott Allen
|
||||
* added getValLen method for widgets to return length of current value - Scott Allen
|
||||
* initialised widget with minimum value instead of 0 - Scott Allen
|
||||
* added getValLen and getMaxValLen keywords
|
||||
* modified MicroViewDemo example to use getValLen method - Scott Allen
|
||||
|
||||
**v1.21b: 22nd September 2014 by Esmit Pérez and Scott Allen**
|
||||
* re-factored code if/else with switch - Esmit Pérez
|
||||
* simplified draw() to remove redundant code - Esmit Pérez
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
MicroView Arduino Library
|
||||
Copyright (C) 2015 GeekAmmo
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
An example of using the optional second argument of the widget
|
||||
setVal() function to update a widget without drawing the changes
|
||||
to the screen buffer.
|
||||
|
||||
This, along with the widget reDraw() function, allows widgets to be
|
||||
maintained in the "background" while other things are being displayed.
|
||||
|
||||
In this example,
|
||||
a guage and a slider are both continually updated with the same
|
||||
incrementing value. The widgets are alternately switched between the
|
||||
"background" and being displayed, at random intervals.
|
||||
*/
|
||||
|
||||
#include <MicroView.h>
|
||||
|
||||
const int highVal = 100; // high value for widget range
|
||||
|
||||
int wValue = 0; // value for widgets
|
||||
|
||||
MicroViewWidget *guage1, *slider1;
|
||||
boolean guage1On, slider1On; // true if widget is being displayed
|
||||
|
||||
void setup() {
|
||||
uView.begin();
|
||||
|
||||
guage1 = new MicroViewGauge(32, 20, 0, highVal);
|
||||
guage1On = false; // begin with guage1 off screen
|
||||
uView.clear(PAGE);
|
||||
|
||||
slider1 = new MicroViewSlider(8, 16, 0, highVal);
|
||||
slider1On = true; // begin with slider1 on screen
|
||||
|
||||
// Init the random number generator using an
|
||||
// unconnected analog pin.
|
||||
randomSeed(analogRead(A0));
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// Display a widget for a random number of value increments
|
||||
for (int c = random(5, 16); c > 0; c--) {
|
||||
uView.display();
|
||||
delay(500);
|
||||
|
||||
wValue++;
|
||||
if (wValue > highVal) {
|
||||
wValue = 0;
|
||||
}
|
||||
|
||||
// If the second setValue() argument is false, then
|
||||
// the display buffer is not updated.
|
||||
//
|
||||
// In a practical application, the widgets would be set with
|
||||
// the values that are being monitored.
|
||||
guage1->setValue(wValue, guage1On);
|
||||
slider1->setValue(wValue, slider1On);
|
||||
}
|
||||
|
||||
// Switch which widget is being displayed
|
||||
uView.clear(PAGE);
|
||||
|
||||
guage1On = !guage1On;
|
||||
slider1On = !slider1On;
|
||||
|
||||
if (guage1On) {
|
||||
guage1->reDraw();
|
||||
}
|
||||
|
||||
if (slider1On) {
|
||||
slider1->reDraw();
|
||||
}
|
||||
}
|
||||
@@ -208,7 +208,7 @@ void loop() {
|
||||
|
||||
/* ==================== Demo 13 ====================
|
||||
Gauge style 1, with no numeric value.
|
||||
Value manually displayed beneath, as a letter.
|
||||
Value manually displayed as a letter.
|
||||
Range 1 to 26 (A to Z).
|
||||
================================================ */
|
||||
demoNumber(13);
|
||||
@@ -246,15 +246,15 @@ void customSlider0(int16_t val) {
|
||||
|
||||
// Update function for Demo 9
|
||||
void customSlider1(int16_t val) {
|
||||
widget1->setValue(val);
|
||||
uint8_t offsetY = widget1->getY() - 10;
|
||||
uint8_t offsetX = widget1->getX() + 14;
|
||||
uView.setCursor(offsetX, offsetY);
|
||||
uView.print(" "); // erase the previous value in case it's longer
|
||||
// calculate the offset to centre the value
|
||||
offsetX += ((widget1->getMaxValLen() - getInt16PrintLen(val)) * 3);
|
||||
offsetX += ((widget1->getMaxValLen() - widget1->getValLen()) * 3);
|
||||
uView.setCursor(offsetX, offsetY);
|
||||
uView.print(val);
|
||||
widget1->setValue(val);
|
||||
}
|
||||
|
||||
// Update function for Demo 10
|
||||
@@ -324,6 +324,7 @@ void spin(int16_t lowVal, int16_t highVal, int16_t stepSize,
|
||||
unsigned long stepDelay, void (*drawFunction)(int16_t val)) {
|
||||
drawFunction(lowVal);
|
||||
uView.display();
|
||||
prevVal = lowVal;
|
||||
delay(1500);
|
||||
|
||||
for (int16_t i = lowVal + stepSize; i <= highVal; i += stepSize) {
|
||||
|
||||
@@ -63,6 +63,8 @@ getMaxValue KEYWORD2
|
||||
setMaxValue KEYWORD2
|
||||
setMinValue KEYWORD2
|
||||
setValue KEYWORD2
|
||||
getValLen KEYWORD2
|
||||
getMaxValLen KEYWORD2
|
||||
draw KEYWORD2
|
||||
reDraw KEYWORD2
|
||||
drawFace KEYWORD2
|
||||
|
||||
Reference in New Issue
Block a user