first commit

This commit is contained in:
Rene Arnhold 2020-08-10 22:13:47 +02:00
commit ad5d1ae7a2
9 changed files with 851 additions and 0 deletions

39
include/README Normal file
View File

@ -0,0 +1,39 @@
This directory is intended for project header files.
A header file is a file containing C declarations and macro definitions
to be shared between several project source files. You request the use of a
header file in your project source file (C, C++, etc) located in `src` folder
by including it, with the C preprocessing directive `#include'.
```src/main.c
#include "header.h"
int main (void)
{
...
}
```
Including a header file produces the same results as copying the header file
into each source file that needs it. Such copying would be time-consuming
and error-prone. With a header file, the related declarations appear
in only one place. If they need to be changed, they can be changed in one
place, and programs that include the header file will automatically use the
new version when next recompiled. The header file eliminates the labor of
finding and changing all the copies as well as the risk that a failure to
find one copy will result in inconsistencies within a program.
In C, the usual convention is to give header files names that end with `.h'.
It is most portable to use only letters, digits, dashes, and underscores in
header file names, and at most one dot.
Read more about using header files in official GCC documentation:
* Include Syntax
* Include Operation
* Once-Only Headers
* Computed Includes
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html

117
include/imgs.h Normal file
View File

@ -0,0 +1,117 @@
// 'ThrottleFault', 25x25px
uint8_t RegenBrakeFaultBMP [] = {
0x01, 0x80, 0xc0, 0x00, 0x07, 0x00, 0x70, 0x00, 0x0e, 0x3e, 0x38, 0x00, 0x18, 0xff, 0x8c, 0x00,
0x33, 0xc1, 0xe6, 0x00, 0x27, 0x00, 0x73, 0x00, 0x6c, 0x80, 0x1b, 0x00, 0x4c, 0xc0, 0x1b, 0x00,
0xd8, 0xc6, 0x0d, 0x80, 0x98, 0xce, 0x0c, 0x80, 0xb0, 0xde, 0x06, 0x80, 0xb0, 0x76, 0x06, 0x80,
0xb0, 0x26, 0x06, 0x80, 0xb0, 0x06, 0x06, 0x80, 0xb0, 0x26, 0x46, 0x80, 0x98, 0x36, 0xcc, 0x80,
0xd8, 0x1f, 0x8d, 0x80, 0x4c, 0x0f, 0x19, 0x00, 0x6c, 0x06, 0x1b, 0x00, 0x67, 0x00, 0x73, 0x00,
0x33, 0xc1, 0xe6, 0x00, 0x18, 0xff, 0x8c, 0x00, 0x0e, 0x3e, 0x38, 0x00, 0x03, 0x00, 0x70, 0x00,
0x01, 0x80, 0xc0, 0x00
};
uint8_t ThrottleFaultBMP [] = {
0xc0, 0x00, 0x01, 0x80, 0x70, 0x00, 0x07, 0x00, 0x38, 0x00, 0x0e, 0x00, 0x0c, 0x1c, 0x18, 0x00,
0x06, 0x3e, 0x30, 0x00, 0x02, 0x3e, 0x60, 0x00, 0x03, 0x3e, 0x60, 0x00, 0x01, 0x3e, 0x60, 0x00,
0x01, 0xbe, 0xc0, 0x00, 0x00, 0xbe, 0x80, 0x00, 0x00, 0xbe, 0x80, 0x00, 0x00, 0xbe, 0x80, 0x00,
0x00, 0x9c, 0x80, 0x00, 0x00, 0x9c, 0x80, 0x00, 0x00, 0x9c, 0x80, 0x00, 0x00, 0x9c, 0x80, 0x00,
0x01, 0x88, 0xc0, 0x00, 0x01, 0x08, 0x40, 0x00, 0x03, 0x00, 0x60, 0x00, 0x03, 0x08, 0x60, 0x00,
0x06, 0x1c, 0x30, 0x00, 0x0c, 0x3e, 0x18, 0x00, 0x38, 0x1c, 0x0e, 0x00, 0x60, 0x08, 0x07, 0x00,
0xc0, 0x00, 0x01, 0x80
};
uint8_t Battery0BMP [] {
0x00, 0xff, 0xc0, 0x00, 0x03, 0xff, 0xf0, 0x00, 0x7f, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x80,
0xff, 0xff, 0xff, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80,
0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80,
0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80,
0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80,
0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80,
0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80,
0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80,
0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80,
0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80,
0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80,
0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xff, 0xff, 0xff, 0x80,
0xff, 0xff, 0xff, 0x80, 0x7f, 0xff, 0xff, 0x00
};
uint8_t Battery1BMP [] {
0x00, 0xff, 0xc0, 0x00, 0x03, 0xff, 0xf0, 0x00, 0x7f, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x80,
0xff, 0xff, 0xff, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80,
0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80,
0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80,
0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80,
0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80,
0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80,
0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80,
0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80,
0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xef, 0xff, 0xfb, 0x80,
0xef, 0xff, 0xfb, 0x80, 0xef, 0xff, 0xfb, 0x80, 0xef, 0xff, 0xfb, 0x80, 0xef, 0xff, 0xfb, 0x80,
0xef, 0xff, 0xfb, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xff, 0xff, 0xff, 0x80,
0xff, 0xff, 0xff, 0x80, 0x7f, 0xff, 0xff, 0x00
};
uint8_t Battery2BMP [] {
0x00, 0xff, 0xc0, 0x00, 0x03, 0xff, 0xf0, 0x00, 0x7f, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x80,
0xff, 0xff, 0xff, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80,
0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80,
0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80,
0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80,
0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80,
0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80,
0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xef, 0xff, 0xfb, 0x80,
0xef, 0xff, 0xfb, 0x80, 0xef, 0xff, 0xfb, 0x80, 0xef, 0xff, 0xfb, 0x80, 0xef, 0xff, 0xfb, 0x80,
0xef, 0xff, 0xfb, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xef, 0xff, 0xfb, 0x80,
0xef, 0xff, 0xfb, 0x80, 0xef, 0xff, 0xfb, 0x80, 0xef, 0xff, 0xfb, 0x80, 0xef, 0xff, 0xfb, 0x80,
0xef, 0xff, 0xfb, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xff, 0xff, 0xff, 0x80,
0xff, 0xff, 0xff, 0x80, 0x7f, 0xff, 0xff, 0x00
};
uint8_t Battery3BMP [] {
0x00, 0xff, 0xc0, 0x00, 0x03, 0xff, 0xf0, 0x00, 0x7f, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x80,
0xff, 0xff, 0xff, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80,
0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80,
0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80,
0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80,
0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xef, 0xff, 0xfb, 0x80,
0xef, 0xff, 0xfb, 0x80, 0xef, 0xff, 0xfb, 0x80, 0xef, 0xff, 0xfb, 0x80, 0xef, 0xff, 0xfb, 0x80,
0xef, 0xff, 0xfb, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xef, 0xff, 0xfb, 0x80,
0xef, 0xff, 0xfb, 0x80, 0xef, 0xff, 0xfb, 0x80, 0xef, 0xff, 0xfb, 0x80, 0xef, 0xff, 0xfb, 0x80,
0xef, 0xff, 0xfb, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xef, 0xff, 0xfb, 0x80,
0xef, 0xff, 0xfb, 0x80, 0xef, 0xff, 0xfb, 0x80, 0xef, 0xff, 0xfb, 0x80, 0xef, 0xff, 0xfb, 0x80,
0xef, 0xff, 0xfb, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xff, 0xff, 0xff, 0x80,
0xff, 0xff, 0xff, 0x80, 0x7f, 0xff, 0xff, 0x00
};
uint8_t Battery4BMP [] {
0x00, 0xff, 0xc0, 0x00, 0x03, 0xff, 0xf0, 0x00, 0x7f, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x80,
0xff, 0xff, 0xff, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80,
0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80,
0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xef, 0xff, 0xfb, 0x80,
0xef, 0xff, 0xfb, 0x80, 0xef, 0xff, 0xfb, 0x80, 0xef, 0xff, 0xfb, 0x80, 0xef, 0xff, 0xfb, 0x80,
0xef, 0xff, 0xfb, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xef, 0xff, 0xfb, 0x80,
0xef, 0xff, 0xfb, 0x80, 0xef, 0xff, 0xfb, 0x80, 0xef, 0xff, 0xfb, 0x80, 0xef, 0xff, 0xfb, 0x80,
0xef, 0xff, 0xfb, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xef, 0xff, 0xfb, 0x80,
0xef, 0xff, 0xfb, 0x80, 0xef, 0xff, 0xfb, 0x80, 0xef, 0xff, 0xfb, 0x80, 0xef, 0xff, 0xfb, 0x80,
0xef, 0xff, 0xfb, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xef, 0xff, 0xfb, 0x80,
0xef, 0xff, 0xfb, 0x80, 0xef, 0xff, 0xfb, 0x80, 0xef, 0xff, 0xfb, 0x80, 0xef, 0xff, 0xfb, 0x80,
0xef, 0xff, 0xfb, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xff, 0xff, 0xff, 0x80,
0xff, 0xff, 0xff, 0x80, 0x7f, 0xff, 0xff, 0x00
};
uint8_t Battery5BMP [] {
0x00, 0xff, 0xc0, 0x00, 0x03, 0xff, 0xf0, 0x00, 0x7f, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x80,
0xff, 0xff, 0xff, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xef, 0xff, 0xfb, 0x80,
0xef, 0xff, 0xfb, 0x80, 0xef, 0xff, 0xfb, 0x80, 0xef, 0xff, 0xfb, 0x80, 0xef, 0xff, 0xfb, 0x80,
0xef, 0xff, 0xfb, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xef, 0xff, 0xfb, 0x80,
0xef, 0xff, 0xfb, 0x80, 0xef, 0xff, 0xfb, 0x80, 0xef, 0xff, 0xfb, 0x80, 0xef, 0xff, 0xfb, 0x80,
0xef, 0xff, 0xfb, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xef, 0xff, 0xfb, 0x80,
0xef, 0xff, 0xfb, 0x80, 0xef, 0xff, 0xfb, 0x80, 0xef, 0xff, 0xfb, 0x80, 0xef, 0xff, 0xfb, 0x80,
0xef, 0xff, 0xfb, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xef, 0xff, 0xfb, 0x80,
0xef, 0xff, 0xfb, 0x80, 0xef, 0xff, 0xfb, 0x80, 0xef, 0xff, 0xfb, 0x80, 0xef, 0xff, 0xfb, 0x80,
0xef, 0xff, 0xfb, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xef, 0xff, 0xfb, 0x80,
0xef, 0xff, 0xfb, 0x80, 0xef, 0xff, 0xfb, 0x80, 0xef, 0xff, 0xfb, 0x80, 0xef, 0xff, 0xfb, 0x80,
0xef, 0xff, 0xfb, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x03, 0x80, 0xff, 0xff, 0xff, 0x80,
0xff, 0xff, 0xff, 0x80, 0x7f, 0xff, 0xff, 0x00
};

View File

@ -0,0 +1,342 @@
#include <DFRobot_ST7687S_Latch.h>
#include <DFRobot_ST7687S_Widgets.h>
#include "BLEDevice.h"
DFRobot_ST7687S_Widgets::DFRobot_ST7687S_Widgets(uint8_t pin_cs, uint8_t pin_cd, uint8_t pin_wr, uint8_t pin_rck)
: DFRobot_ST7687S_Latch (pin_cs, pin_cd, pin_wr, pin_rck) {
uint8_t old_needle_pos[] = {0, 0, 0, 0};
uint8_t needle_pos[] = {0, 0, 0, 0};
bool labels_written = false;
}
void DFRobot_ST7687S_Widgets::AmpMeter(int value)
{
int i = 0;
int j = 0;
int i2 = 0;
int j2 = 0;
int color = 0;
int _lineWidth = getLineWidth();
int _value = map(value, 0, AMPMETER_MAX, AMPMETER_OPEN, AMPMETER_CLOSE);
setLineWidth(3);
for (int p = AMPMETER_OPEN; p < AMPMETER_CLOSE; p = p + 50) {
if (_value <= p) {
color = rainbow(map(p, AMPMETER_OPEN, AMPMETER_CLOSE, 63, 127));
}
else {
color = DISPLAY_DARKGREEN;
}
i = AMPMETER_RADIUS * (cos(PI * p / 2000));
j = AMPMETER_RADIUS * (sin(PI * p / 2000));
i2 = (AMPMETER_RADIUS - 5) * (cos(PI * p / 2000));
j2 = (AMPMETER_RADIUS - 5) * (sin(PI * p / 2000));
drawLine(i, j, i2, j2, color);
}
}
void DFRobot_ST7687S_Widgets::PasDisplay(int value) {
setTextSize(PAS_TEXTSIZE);
setTextColor(PAS_COLOR);
setCursor((width / 2) - (PAS_TEXTSIZE * 2), (height / 2) - (PAS_TEXTSIZE * 4));
print(value);
}
void DFRobot_ST7687S_Widgets::Tacho() {
int i = 0;
int j = 0;
int i2 = 0;
int j2 = 0;
bool thick_line = true;
fillCircle(0, 0, 3, DISPLAY_CYAN);
for (int p = TACHO_OPEN; p < TACHO_CLOSE; p++) {
i = TACHO_RADIUS * (cos(PI * p / 2000));
j = TACHO_RADIUS * (sin(PI * p / 2000));
drawPixel(i, j, DISPLAY_CYAN);
}
for (int p = TACHO_OPEN; p < TACHO_CLOSE; p = p + 230) {
i = TACHO_RADIUS * (cos(PI * p / 2000));
j = TACHO_RADIUS * (sin(PI * p / 2000));
i2 = (TACHO_RADIUS - 5) * (cos(PI * p / 2000));
j2 = (TACHO_RADIUS - 5) * (sin(PI * p / 2000));
if (thick_line) {
setLineWidth(3);
thick_line = false;
}
else {
setLineWidth(1);
thick_line = true;
}
drawLine(i, j, i2, j2, DISPLAY_CYAN);
}
}
void DFRobot_ST7687S_Widgets::TachoLabels() {
int16_t label_x = 0;
int16_t label_y = 0;
int label_val = 0;
bool label_line = true;
for (int p = TACHO_OPEN; p < TACHO_CLOSE; p = p + 230) {
if (label_line) {
label_line = false;
label_x = ((TACHO_RADIUS - 15) * (cos(PI * p / 2000))) + 64;
label_y = ((TACHO_RADIUS - 17) * (sin(PI * p / 2000))) + 64;
setTextColor(DISPLAY_WHITE);
setTextBackground(CBC_DISPLAY_BACKCOLOR);
setTextSize(1);
setCursor(label_x + 60, label_y + 64);
if (label_val == 0 ) {
labelText(&label_x, &label_y, " ");
labelText(&label_x, &label_y, "0");
}
else if (label_val == 1 ) {
labelText(&label_x, &label_y, "1");
labelText(&label_x, &label_y, "0");
}
else if (label_val == 2 ) {
labelText(&label_x, &label_y, "2");
labelText(&label_x, &label_y, "0");
}
else if (label_val == 3 ) {
labelText(&label_x, &label_y, "3");
labelText(&label_x, &label_y, "0");
}
else if (label_val == 4 ) {
labelText(&label_x, &label_y, "4");
labelText(&label_x, &label_y, "0");
}
else if (label_val == 5 ) {
labelText(&label_x, &label_y, "5");
labelText(&label_x, &label_y, "0");
}
else if (label_val == 6 ) {
labelText(&label_x, &label_y, "6");
labelText(&label_x, &label_y, "0");
}
label_val += 1;
}
else {
label_line = true;
}
}
labels_written = true;
}
void DFRobot_ST7687S_Widgets::TachoNeedle(uint8_t speed) {
int _lineWidth = getLineWidth();
setLineWidth(TACHO_NEEDLE_WIDTH);
drawLine(needle_pos[0], needle_pos[1], needle_pos[2], needle_pos[3], CBC_DISPLAY_BACKCOLOR);
if (speed > TACHO_MAX_SPEED)
speed = TACHO_MAX_SPEED;
float needle_value = map(speed, 0, TACHO_MAX_SPEED, TACHO_OPEN, TACHO_CLOSE);
needle_pos[0] = TACHO_NEEDLE_LENGTH * (cos(PI * needle_value / 2000));
needle_pos[1] = TACHO_NEEDLE_LENGTH * (sin(PI * needle_value / 2000));
needle_pos[2] = 4 * (cos(PI * needle_value / 2000));
needle_pos[3] = 4 * (sin(PI * needle_value / 2000));
old_needle_pos[0] = needle_pos[0];
old_needle_pos[1] = needle_pos[1];
old_needle_pos[2] = needle_pos[2];
old_needle_pos[3] = needle_pos[3];
drawLine(needle_pos[0], needle_pos[1], needle_pos[2], needle_pos[3], TACHO_NEEDLE_COLOR);
setLineWidth(_lineWidth);
TachoLabels();
}
void DFRobot_ST7687S_Widgets::labelText(int16_t* pX, int16_t* pY, const char* ch)
{
uint8_t characterBuffer[32] = {0};
uint8_t rslt = 0;
uint8_t i = 0, j = 0, k = 0;
uint8_t var1 = 0;
uint8_t textWidth = 0, textHeight = 0;
while(*ch) {
rslt = pfCharacterFont((uint8_t*) ch, characterBuffer, &textWidth, &textHeight);
// fillRect(*pX - cursorX, *pY - cursorY, textWidth * textSize, textHeight * textSize, textBackground);
ch += rslt;
Serial.print(ch);
for(i = 0; i < textWidth; i ++) {
var1 = characterBuffer[i];
for(j = 0; j < 8; j ++) {
if(var1 & (0x01 << j)) {
for(k = 0; k < textSize; k ++) {
//if( (!labels_written) || (isAtOldNeedle(*pX + i + k - cursorX, *pY + j - cursorY, old_needle_pos[0], old_needle_pos[1], old_needle_pos[2], old_needle_pos[3]) ) ) {
// drawPixel(*pX + i + k - cursorX, *pY + j - cursorY, TACHO_LABEL_COLOR);
//}
drawPixel(*pX + i + k - cursorX, *pY + j - cursorY, TACHO_LABEL_COLOR);
}
}
}
}
*pX += textWidth * textSize;
}
}
/*
bool DFRobot_ST7687S_Widgets::isAtOldNeedle(int16_t xpoint, int16_t ypoint, int16_t x0, int16_t y0, int16_t x1, int16_t y1) {
int16_t dx = abs(x1 - x0), dy = abs(y1 - y0);
uint8_t steep = 0;
eDirection_t eDirection = calcLineDirection(x0, y0, x1, y1);
if(dx < dy) {
steep = 1;
swap_int16(x0, y0);
swap_int16(x1, y1);
swap_int16(dx, dy);
}
int8_t dirX = (x1 - x0) > 0 ? 1 : -1;
int8_t dirY = (y1 - y0) > 0 ? 1 : -1;
int16_t endX = x0, endY = y0;
int32_t var1 = dy * 2;
int32_t var2 = (dy - dx) * 2;
int32_t var3 = dy * 2 -dx;
if(steep) {
while(endX != x1) {
if(var3 < 0) {
var3 += var1;
} else {
endY += dirY;
var3 += var2;
}
// drawPixel(endY, endX, color);
// drawPixelWidth(endY, endX, eDirection, color);
if(lineWidth == 1) {
// drawPixel(endY, endX, color);
if ( (xpoint == endY) && (ypoint == endX) ) {
Serial.println("redraw");
return true;
}
}
else if(lineWidth > 1) {
if(eDirection == eDIRECTION_HORIZONTAL) {
//drawHLine(endY - (lineWidth / 2), endX, lineWidth, color);
int8_t direction = 1;
int16_t var1 = endY + lineWidth;
if(lineWidth < 0) {
direction = -1;
}
for(; endY != var1; endY += direction) {
// drawPixel(endY, endX, color);
if( (xpoint == endY) && (xpoint == endX) ) {
Serial.println("redraw");
return true;
}
}
}
else {
// drawVLine(endY, endX - (lineWidth / 2), lineWidth, color);
int8_t direction = 1;
int16_t var1 = endX + lineWidth;
if(lineWidth < 0) {
direction = -1;
}
for(; endX != var1; endX += direction) {
// drawPixel(endY, endX, color);
if ( (xpoint == endY) && (ypoint == endX) ) {
Serial.println("redraw");
return true;
}
}
}
}
endX += dirX;
}
} else {
while(endX != x1) {
if(var3 < 0) {
var3 += var1;
} else {
endY += dirY;
var3 += var2;
}
// drawPixel(endX, endY, color);
// drawPixelWidth(endX, endY, eDirection, color);
if(lineWidth == 1) {
// drawPixel(endX, endY, color);
if ( (xpoint == endX) && (ypoint == endY) ) {
Serial.println("redraw");
return true;
}
}
else if(lineWidth > 1) {
if(eDirection == eDIRECTION_HORIZONTAL) {
// drawHLine(endX - (lineWidth / 2), endY, lineWidth, color);
int8_t direction = 1;
int16_t var1 = endX + lineWidth;
if(lineWidth < 0) {
direction = -1;
}
for(; endX != var1; endX += direction) {
// drawPixel(endX, endY, color);
if ( (xpoint == endX) && (ypoint == endY) ){
Serial.println("redraw");
return true;
}
}
}
else {
// drawVLine(endX, endY - (lineWidth / 2), lineWidth, color);
int8_t direction = 1;
int16_t var1 = endY + lineWidth;
if(lineWidth < 0) {
direction = -1;
}
for(; endY != var1; endY += direction) {
// drawPixel(endX, endY, color);
if ( (xpoint == endX) && (ypoint == endY) ) {
Serial.println("redraw");
return true;
}
}
}
}
endX += dirX;
}
}
return false;
}
*/
unsigned int DFRobot_ST7687S_Widgets::rainbow(byte value) {
// Value is expected to be in range 0-127
// The value is converted to a spectrum colour from 0 = blue through to 127 = red
byte red = 0; // Red is the top 5 bits of a 16 bit colour value
byte green = 0; // Green is the middle 6 bits
byte blue = 0; // Blue is the bottom 5 bits
byte quadrant = value / 32;
if (quadrant == 0) {
blue = 31;
green = 2 * (value % 32);
red = 0;
}
if (quadrant == 1) {
blue = 31 - (value % 32);
green = 63;
red = 0;
}
if (quadrant == 2) {
blue = 0;
green = 63;
red = value % 32;
}
if (quadrant == 3) {
blue = 0;
green = 63 - 2 * (value % 32);
red = 31;
}
return (red << 11) + (green << 5) + blue;
}

View File

@ -0,0 +1,44 @@
#include <DFRobot_ST7687S_Latch.h>
#define CBC_DISPLAY_BACKCOLOR DISPLAY_BLACK
#define TACHO_RADIUS 60
#define TACHO_DEFAULT_COLOR DISPLAY_CYAN
#define TACHO_BOOST_COLOR DISPLAY_RED
#define TACHO_LABEL_COLOR DISPLAY_WHITE
#define TACHO_OPEN 1500
#define TACHO_CLOSE TACHO_OPEN + 2995
#define TACHO_NEEDLE_LENGTH 50
#define TACHO_NEEDLE_COLOR DISPLAY_GREEN
#define TACHO_NEEDLE_WIDTH 3
#define TACHO_MAX_SPEED 65
#define AMPMETER_OPEN 2000
#define AMPMETER_CLOSE TACHO_OPEN + 2000
#define AMPMETER_RADIUS 64
#define AMPMETER_MAX 100
#define PAS_TEXTSIZE 5
#define PAS_COLOR DISPLAY_CYAN
#define REGENBRAKE_FAULT_COLOR DISPLAY_ORANGE
#define THROTTLE_FAULT_COLOR DISPLAY_ORANGE
class DFRobot_ST7687S_Widgets : public DFRobot_ST7687S_Latch {
public:
DFRobot_ST7687S_Widgets (uint8_t pin_cs, uint8_t pin_cd, uint8_t pin_wr, uint8_t pin_rck);
void Tacho();
void AmpMeter(int value);
void TachoLabels();
void TachoNeedle(uint8_t speed);
void drawLine2(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color);
void PasDisplay(int value);
private:
void labelText(int16_t* pX, int16_t* pY, const char* ch);
unsigned int rainbow(byte value);
bool labels_written;
int8_t old_needle_pos[];
int8_t needle_pos[];
};

46
lib/README Normal file
View File

@ -0,0 +1,46 @@
This directory is intended for project specific (private) libraries.
PlatformIO will compile them to static libraries and link into executable file.
The source code of each library should be placed in a an own separate directory
("lib/your_library_name/[here are source files]").
For example, see a structure of the following two libraries `Foo` and `Bar`:
|--lib
| |
| |--Bar
| | |--docs
| | |--examples
| | |--src
| | |- Bar.c
| | |- Bar.h
| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
| |
| |--Foo
| | |- Foo.c
| | |- Foo.h
| |
| |- README --> THIS FILE
|
|- platformio.ini
|--src
|- main.c
and a contents of `src/main.c`:
```
#include <Foo.h>
#include <Bar.h>
int main (void)
{
...
}
```
PlatformIO Library Dependency Finder will find automatically dependent
libraries scanning project source files.
More information about PlatformIO Library Dependency Finder
- https://docs.platformio.org/page/librarymanager/ldf.html

19
platformio.ini Normal file
View File

@ -0,0 +1,19 @@
; PlatformIO Project Configuration File
;
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
[env:esp32dev]
platform = espressif32
board = esp32dev
framework = arduino
build_flags = -Wl,-V
monitor_speed = 115200
lib_deps =
https://github.com/racsnet/DFRobot_ST7687S
https://github.com/DFRobot/DFRobot_Display

21
src/config.h Normal file
View File

@ -0,0 +1,21 @@
#define RAYVOLT_DUMMY "30:ae:a4:e0:3a:a6"
#define RAYVOLT_BIKE "3c:a3:08:a0:8f:68"
#define TFT_LEFT_PIN_CS 5
#define TFT_LEFT_PIN_WR 17
#define TFT_LEFT_PIN_RS 16
#define TFT_LEFT_PIN_LCK 4
#define TFT_RIGHT_PIN_CS 13
#define TFT_RIGHT_PIN_WR 17
#define TFT_RIGHT_PIN_RS 16
#define TFT_RIGHT_PIN_LCK 4
#define BTN_RIGHT_LOWER 33
#define BTN_RIGHT_CENTER 35
#define BTN_RIGHT_HIGHER 34
#define TOUCH_BUTTON 12
#define TOUCH_THRESHOLD 15
#define BTN_COOLDOWN 50

212
src/main.cpp Normal file
View File

@ -0,0 +1,212 @@
#include <Arduino.h>
#include <stdlib.h>
#include <stdint.h>
#include <config.h>
#include <DFRobot_ST7687S_Widgets.h>
#include <imgs.h>
#include "BLEDevice.h"
DFRobot_ST7687S_Widgets tft_left(TFT_LEFT_PIN_CS, TFT_LEFT_PIN_RS, TFT_LEFT_PIN_WR, TFT_LEFT_PIN_LCK);
DFRobot_ST7687S_Widgets tft_right(TFT_RIGHT_PIN_CS, TFT_RIGHT_PIN_RS, TFT_RIGHT_PIN_WR, TFT_RIGHT_PIN_LCK);
bool doConnect = false;
bool connected = false;
bool doScan = false;
int btn_checked = millis();
static BLEUUID serviceUUID("0000ffe0-0000-1000-8000-00805f9b34fb");
static BLEUUID charUUID("0000ffe1-0000-1000-8000-00805f9b34fb");
static BLERemoteCharacteristic* pRemoteCharacteristic;
static BLEAdvertisedDevice* myDevice;
// TODO: check request length
// uint8_t status_request[] = { 0x66, 0x41, 0x02, 0x05, 0x00, 0xAE, 0x00, 0x00, 0x30, 0xDD, 0xFC, 0x3F, 0xF0, 0xDC, 0xFC, 0x3F, 0x66, 0x10, 0x94, 0xEE, 0x13, 0x00, 0x00, 0x00 };
uint8_t old_speed = 0;
uint8_t status_request[] = { 0x66, 0x41, 0x02, 0x05, 0x00, 0xAE };
uint8_t last_bike_status[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
uint8_t bike_status[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
float calc_speed() {
int rmp = (int) (60.0d / (((double) ((bike_status[2] * 255) + bike_status[3])) / 1000.0d));
uint8_t tempSpeed = (int) ((((double) rmp) * ((((double) ((float) 27) / 39.37f)) * 3.141592653589793d) / 1000.0d) * 60.0d);
return tempSpeed;
}
static void notifyCallback(BLERemoteCharacteristic* pBLERemoteCharacteristic, uint8_t* pData, size_t length, bool isNotify) {
if ( (length == 9) && (pData[0] ==0x66) && (pData[1] ==0x41) && (pData[2] ==0x05) ) {
for (int i = 0; i < length; i++) {
last_bike_status[i] = bike_status[i];
bike_status[i] = pData[i];
}
}
else {
Serial.print("size: ");
Serial.print(length);
Serial.print(" | data: ");
for (int i = 0; i < length; i++) {
Serial.print(pData[i], HEX);
Serial.print(" ");
}
Serial.println("");
}
}
class MyClientCallback : public BLEClientCallbacks {
void onConnect(BLEClient* pclient) { }
void onDisconnect(BLEClient* pclient) { connected = false; }
};
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
void onResult(BLEAdvertisedDevice advertisedDevice) {
if (advertisedDevice.getAddress().equals(BLEAddress(RAYVOLT_BIKE))) {
BLEDevice::getScan()->stop();
myDevice = new BLEAdvertisedDevice(advertisedDevice);
doConnect = true;
doScan = true;
}
if (advertisedDevice.getAddress().equals(BLEAddress(RAYVOLT_DUMMY))) {
BLEDevice::getScan()->stop();
myDevice = new BLEAdvertisedDevice(advertisedDevice);
doConnect = true;
doScan = true;
}
}
};
bool connectToServer() {
BLEClient* pClient = BLEDevice::createClient();
pClient->setClientCallbacks(new MyClientCallback());
pClient->connect(myDevice);
BLERemoteService* pRemoteService = pClient->getService(serviceUUID);
if (pRemoteService == nullptr) {
pClient->disconnect();
return false;
}
pRemoteCharacteristic = pRemoteService->getCharacteristic(charUUID);
if (pRemoteCharacteristic == nullptr) {
pClient->disconnect();
return false;
}
if(pRemoteCharacteristic->canRead()) {
std::string value = pRemoteCharacteristic->readValue();
}
if(pRemoteCharacteristic->canNotify())
pRemoteCharacteristic->registerForNotify(notifyCallback);
connected = true;
return true;
}
void process_status() {
// TODO: ERRORS OverVoltage / Undervoltage / BLE_ERROR
/*
Serial.print("bike_status");
for (int i = 0; i < sizeof(bike_status); i++) {
Serial.print(bike_status[i], BIN);
Serial.print(" ");
}
Serial.println("");
*/
if( ((last_bike_status[7] >> 0) & 1) != ((bike_status[7] >> 0) & 1) ) {
if((bike_status[7] >> 0) & 1) {
Serial.println("rbs error");
tft_right.drawBmp(RegenBrakeFaultBMP, -30, 30, 25, 25, 1, REGENBRAKE_FAULT_COLOR);
}
else {
tft_right.fillRect(-30, 30, 25, 25, CBC_DISPLAY_BACKCOLOR);
}
}
if( ((last_bike_status[7] >> 1) & 1) != ((bike_status[7] >> 1) & 1) ) {
if((bike_status[7] >> 1) & 1) {
tft_right.drawBmp(ThrottleFaultBMP, 5, 30, 25, 25, 1, THROTTLE_FAULT_COLOR);
}
else {
tft_right.fillRect(5, 30, 25, 25, CBC_DISPLAY_BACKCOLOR);
}
}
}
void setup() {
Serial.begin(115200);
pinMode(BTN_RIGHT_LOWER, INPUT);
pinMode(BTN_RIGHT_CENTER, INPUT);
pinMode(BTN_RIGHT_HIGHER, INPUT);
tft_left.begin(ST7687S_Rotation_270);
tft_left.fillScreen(CBC_DISPLAY_BACKCOLOR);
tft_right.begin(ST7687S_Rotation_90);
tft_right.fillScreen(CBC_DISPLAY_BACKCOLOR);
tft_right.AmpMeter(50);
tft_right.PasDisplay((status_request[3]) - 2);
// tft_right.fillRect(-30, 30, 25, 25, DISPLAY_GREEN);
// tft_right.drawBmp(RegenBrakeFaultBMP, -30, 30, 25, 25, 1, DISPLAY_ORANGE);
// tft_right.fillRect(5, 30, 25, 25, DISPLAY_GREEN);
// tft_right.drawBmp(ThrottleFaultBMP, 5, 30, 25, 25, 1, DISPLAY_ORANGE);
tft_right.drawBmp(Battery5BMP, 30, -28, 25, 50, 1, DISPLAY_GREEN);
tft_left.Tacho();
tft_left.TachoLabels();
tft_left.TachoNeedle(35);
// tft_left.drawLine2(0 ,0, -45, -45, DISPLAY_DARKGREY);
BLEDevice::init("");
BLEScan* pBLEScan = BLEDevice::getScan();
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
pBLEScan->setInterval(1349);
pBLEScan->setWindow(449);
pBLEScan->setActiveScan(true);
pBLEScan->start(5, false);
}
void loop() {
if (touchRead(TOUCH_BUTTON) < TOUCH_THRESHOLD) {
Serial.println("touch detected");
}
if (doConnect == true) {
if (connectToServer()) { Serial.println("connected"); }
else { Serial.println("failed to connect"); }
doConnect = false;
}
if (connected) {
pRemoteCharacteristic->writeValue(status_request, sizeof(status_request));
if ( (digitalRead(BTN_RIGHT_LOWER)) && (millis() - btn_checked > BTN_COOLDOWN) ) {
btn_checked = millis();
if (status_request[3] > 2 ) {
status_request[3]--;
tft_right.PasDisplay((status_request[3]) - 2);
}
}
else if ( (digitalRead(BTN_RIGHT_CENTER)) && (millis() - btn_checked > BTN_COOLDOWN) ) {
btn_checked = millis();
}
else if ( (digitalRead(BTN_RIGHT_HIGHER)) && (millis() - btn_checked > BTN_COOLDOWN) ) {
btn_checked = millis();
if (status_request[3] < 5 ) {
status_request[3]++;
tft_right.PasDisplay((status_request[3]) - 2);
}
}
process_status();
}
else if(doScan){
Serial.println("disconnected");
// BLEDevice::getScan()->start(0); // this is just eample to start scan after disconnect, most likely there is better way to do it in arduino
}
delay(250);
}

11
test/README Normal file
View File

@ -0,0 +1,11 @@
This directory is intended for PIO Unit Testing and project tests.
Unit Testing is a software testing method by which individual units of
source code, sets of one or more MCU program modules together with associated
control data, usage procedures, and operating procedures, are tested to
determine whether they are fit for use. Unit testing finds problems early
in the development cycle.
More information about PIO Unit Testing:
- https://docs.platformio.org/page/plus/unit-testing.html