commit ad5d1ae7a27f0ae273b461b422ae9ce2f053f30d Author: Rene Arnhold Date: Mon Aug 10 22:13:47 2020 +0200 first commit diff --git a/include/README b/include/README new file mode 100644 index 0000000..194dcd4 --- /dev/null +++ b/include/README @@ -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 diff --git a/include/imgs.h b/include/imgs.h new file mode 100644 index 0000000..e39f270 --- /dev/null +++ b/include/imgs.h @@ -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 +}; \ No newline at end of file diff --git a/lib/DFRobot_ST7687S_Widgets/DFRobot_ST7687S_Widgets.cpp b/lib/DFRobot_ST7687S_Widgets/DFRobot_ST7687S_Widgets.cpp new file mode 100644 index 0000000..9c8afac --- /dev/null +++ b/lib/DFRobot_ST7687S_Widgets/DFRobot_ST7687S_Widgets.cpp @@ -0,0 +1,342 @@ + +#include +#include + +#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; +} \ No newline at end of file diff --git a/lib/DFRobot_ST7687S_Widgets/DFRobot_ST7687S_Widgets.h b/lib/DFRobot_ST7687S_Widgets/DFRobot_ST7687S_Widgets.h new file mode 100644 index 0000000..f92b715 --- /dev/null +++ b/lib/DFRobot_ST7687S_Widgets/DFRobot_ST7687S_Widgets.h @@ -0,0 +1,44 @@ +#include + +#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[]; +}; \ No newline at end of file diff --git a/lib/README b/lib/README new file mode 100644 index 0000000..6debab1 --- /dev/null +++ b/lib/README @@ -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 +#include + +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 diff --git a/platformio.ini b/platformio.ini new file mode 100644 index 0000000..941c02d --- /dev/null +++ b/platformio.ini @@ -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 \ No newline at end of file diff --git a/src/config.h b/src/config.h new file mode 100644 index 0000000..20bf680 --- /dev/null +++ b/src/config.h @@ -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 \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..fa6587a --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,212 @@ +#include +#include +#include +#include +#include +#include +#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); +} \ No newline at end of file diff --git a/test/README b/test/README new file mode 100644 index 0000000..df5066e --- /dev/null +++ b/test/README @@ -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