227 lines
7.1 KiB
C
227 lines
7.1 KiB
C
#include <Arduino.h>
|
|
#include <U8g2lib.h>
|
|
#include <Wire.h>
|
|
|
|
#include "bitmap.h"
|
|
|
|
#define SCREEN_WIDTH 128
|
|
#define SCREEN_HEIGHT 32 // 0.91 inch OLED is usually 128x32
|
|
|
|
// Custom Pins
|
|
#define OLED_SCL 12 // MISO = D6 = OLED_SCL
|
|
#define OLED_SDA 13 // MOSI = D7 = OLED_SDA
|
|
#define UNUSED_PIN 14 // SCK = D5 (reserved when need reset pin)
|
|
#define OLED_RESET -1 // Or 0 if display has a reset pin
|
|
U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE, /* clock=*/ OLED_SCL, /* data=*/ OLED_SDA); // pin remapping with ESP8266 HW I2C
|
|
|
|
uint8_t displayContrast = 96;
|
|
uint8_t battLevelNum = 4;
|
|
uint8_t battBlockWidth = 15; uint8_t battBlockHeight = 14;
|
|
uint8_t battBlockGap = 3;
|
|
|
|
//for demo
|
|
uint8_t dispDemoIdx = 0;
|
|
|
|
void displaySplash(){
|
|
u8g2.setContrast(255);
|
|
//u8g2.drawXBMP(0, 0, 128, 32, splash_logo_bitmap);
|
|
u8g2.drawXBMP(0, 0, 128, 32, splash_logo_bitmap_inverted);
|
|
u8g2.sendBuffer();
|
|
}
|
|
|
|
void drawBatteryBlocks(int8_t x, int8_t y, int8_t nFilled){
|
|
int8_t xp = x+((battBlockWidth+battBlockGap)*battLevelNum);
|
|
xp-=battBlockGap;
|
|
int8_t yp = y;
|
|
u8g2.setDrawColor(1);
|
|
for (int8_t i=0; i<battLevelNum; i++){
|
|
xp-=battBlockWidth;
|
|
if (i<nFilled){
|
|
u8g2.drawRBox(xp, yp, battBlockWidth, battBlockHeight, 2); //Draws a filled box with rounded
|
|
}else{
|
|
u8g2.drawRFrame(xp, yp, battBlockWidth, battBlockHeight, 2); //Draws an empty frame with rounded corners.
|
|
}
|
|
xp-=battBlockGap;
|
|
}
|
|
}
|
|
|
|
void drawBatteryCase(int8_t x, int8_t y, uint8_t style){
|
|
//u8g2.drawLine(x, y, x+(battBlockWidth+battBlockGap)*battLevelNum), y);
|
|
int8_t sideGap = 4;
|
|
int8_t xpe = (x+((battBlockWidth+battBlockGap)*battLevelNum)) - battBlockGap;
|
|
int8_t w = ((battBlockWidth+battBlockGap)*battLevelNum) - battBlockGap;
|
|
u8g2.setDrawColor(1);
|
|
//u8g2.drawLine(x-sideGap, y-sideGap, xpe+sideGap, y-sideGap);
|
|
u8g2.drawRFrame(x-sideGap, y-sideGap, w+sideGap+sideGap, battBlockHeight+sideGap+sideGap, 3);
|
|
//kepala batre
|
|
int8_t headW = 5;
|
|
int8_t headH = battBlockHeight-2;
|
|
int8_t yc = y+(battBlockHeight/2);
|
|
//u8g2.drawRFrame(x-(sideGap+headW), y+sideGap, headW, battBlockHeight, 3);
|
|
if (style==0){
|
|
u8g2.drawRFrame(x-(sideGap+headW), yc-(headH/2), headW+1, headH, 1);
|
|
}else if (style==1){
|
|
u8g2.drawRBox(x-(sideGap+headW), yc-(headH/2), headW+1, headH, 1);
|
|
}else if (style==2 || style==3){
|
|
u8g2.drawRFrame(x-(sideGap+headW), yc-(headH/2), headW+1, headH, 1);
|
|
u8g2.setDrawColor(0);
|
|
int8_t xp = (x-(sideGap+headW)) + headW;
|
|
int8_t yp = yc-(headH/2);
|
|
if (style==2) u8g2.drawLine(xp, yp+1, xp, yp+(headH-2)); //rigid
|
|
if (style==3) u8g2.drawLine(xp, yp+0, xp, yp+(headH-1)); //curved or sleek
|
|
}
|
|
}
|
|
|
|
void drawBatteryPercentage(int8_t x, int8_t y, int8_t textWidth, int8_t percentage){
|
|
//draw text right aligned
|
|
String s = String(percentage) + "%";
|
|
char char_array[6];
|
|
s.toCharArray(char_array, s.length()+1);
|
|
u8g2.setFont(u8g2_font_ncenB08_tr); // choose a suitable font
|
|
int8_t w = u8g2.getStrWidth(char_array); //note: current string width calculation is still not 100% perfect as the initial offset is part of the returned width.
|
|
int8_t xp = x + (textWidth-w);
|
|
u8g2.setDrawColor(1);
|
|
u8g2.drawStr(xp,y,char_array);
|
|
}
|
|
|
|
void drawActiveTransmission(int8_t x, int8_t y, bool inArrow, bool outArrow){
|
|
u8g2.setDrawColor(1);
|
|
if (inArrow) u8g2.drawXBMP(x, y, 2, 4, active_data_2x4_in_bitmap);
|
|
if (outArrow) u8g2.drawXBMP(x+3, y, 2, 4, active_data_2x4_out_bitmap);
|
|
}
|
|
|
|
void drawWifi(int8_t x, int8_t y, uint8_t level){
|
|
//power 0 = not drawn
|
|
u8g2.setDrawColor(1);
|
|
if (level==1) u8g2.drawXBMP(x, y, 16, 16, wifi2_lv1_bitmap);
|
|
if (level==2) u8g2.drawXBMP(x, y, 16, 16, wifi2_lv2_bitmap);
|
|
if (level>2) u8g2.drawXBMP(x, y, 16, 16, wifi2_lv3_bitmap);
|
|
}
|
|
|
|
void drawWifiAndTransmission(int8_t x, int8_t y, uint8_t level, bool inArrow, bool outArrow){
|
|
//power 0 = not drawn
|
|
drawWifi(x, y+1, level);
|
|
drawActiveTransmission(x+11, y+12, inArrow, outArrow);
|
|
}
|
|
|
|
void drawPower(int8_t x, int8_t y, bool timed){
|
|
u8g2.setDrawColor(1);
|
|
if (timed){
|
|
u8g2.drawXBMP(x, y, 16, 16, timer_16x16_bitmap);
|
|
}else{
|
|
u8g2.drawXBMP(x, y, 16, 16, power_bitmap);
|
|
}
|
|
}
|
|
|
|
void drawBolt(int8_t x, int8_t y){
|
|
u8g2.setDrawColor(1);
|
|
u8g2.drawXBMP(x, y, 16, 16, bolt_16x16_bitmap);
|
|
}
|
|
|
|
void drawCharging(int8_t x, int8_t y, bool reduced){
|
|
u8g2.setDrawColor(1);
|
|
if (reduced){
|
|
u8g2.drawXBMP(x, y, 7, 8, charging_7x8_bitmap);
|
|
}else{
|
|
u8g2.drawXBMP(x, y, 7, 8, charge_fast_7x8_bitmap);
|
|
}
|
|
}
|
|
|
|
void drawWarning(int8_t x, int8_t y, uint8_t mode){
|
|
u8g2.setDrawColor(1);
|
|
if (mode==0){
|
|
u8g2.drawXBMP(x, y, 16, 16, warn_16x16_bitmap);
|
|
}else if (mode==1){
|
|
u8g2.drawXBMP(x, y, 16, 16, error_16x16_bitmap);
|
|
}else if (mode==2){
|
|
u8g2.drawXBMP(x, y, 16, 16, fatal_16x16_bitmap);
|
|
}
|
|
}
|
|
|
|
void initDisplay(bool showSplash){
|
|
pinMode(UNUSED_PIN, INPUT);
|
|
u8g2.begin();
|
|
u8g2.setContrast(displayContrast);
|
|
if (showSplash){
|
|
displaySplash();
|
|
}else{
|
|
u8g2.setContrast(displayContrast);
|
|
u8g2.clearBuffer();
|
|
u8g2.sendBuffer();
|
|
}
|
|
}
|
|
|
|
void clearDisplay(){
|
|
u8g2.clearBuffer();
|
|
}
|
|
|
|
void sendDisplay(){
|
|
u8g2.sendBuffer();
|
|
}
|
|
|
|
void drawString(int8_t x, int8_t y, String s){
|
|
u8g2.setFont(u8g2_font_ncenB08_tr);
|
|
char char_array[32];
|
|
s.toCharArray(char_array, s.length()+1);
|
|
char_array[s.length()] = 0;
|
|
u8g2.setDrawColor(1);
|
|
u8g2.drawStr(x, y, char_array);
|
|
}
|
|
|
|
uint8_t stringWidth(String s){
|
|
char char_array[32];
|
|
s.toCharArray(char_array, s.length()+1);
|
|
char_array[s.length()] = 0;
|
|
u8g2.setFont(u8g2_font_ncenB08_tr); // choose a suitable font
|
|
return u8g2.getStrWidth(char_array);
|
|
}
|
|
|
|
uint8_t stringCenterX(String s){
|
|
char char_array[32];
|
|
s.toCharArray(char_array, s.length()+1);
|
|
u8g2.setFont(u8g2_font_ncenB08_tr); // choose a suitable font
|
|
uint8_t w = u8g2.getStrWidth(char_array);
|
|
return (SCREEN_WIDTH-w)/2;
|
|
}
|
|
|
|
uint8_t stringRightSideX(String s){
|
|
char char_array[32];
|
|
s.toCharArray(char_array, s.length()+1);
|
|
u8g2.setFont(u8g2_font_ncenB08_tr); // choose a suitable font
|
|
uint8_t w = u8g2.getStrWidth(char_array);
|
|
return (SCREEN_WIDTH-w);
|
|
}
|
|
|
|
void displayDemoRoutine1(){
|
|
u8g2.setContrast(displayContrast);
|
|
u8g2.clearBuffer();
|
|
//drawBatteryBlock(5,5, true);
|
|
drawBatteryBlocks(55, 4, dispDemoIdx);
|
|
drawBatteryCase(55, 4, 2);
|
|
|
|
//u8g2.setDrawColor(1);
|
|
//u8g2.setFont(u8g2_font_ncenB08_tr); // choose a suitable font
|
|
//u8g2.drawStr(100,32,"100%");
|
|
drawBatteryPercentage(100,32,28, 25*dispDemoIdx);
|
|
|
|
if (dispDemoIdx<=3) drawPower(0,0, dispDemoIdx>=2);
|
|
if (dispDemoIdx==1 || dispDemoIdx==3) drawBolt(20,0);
|
|
|
|
//drawWifi(0, 16, dispDemoIdx);
|
|
//drawActiveTransmission(11,28, (dispDemoIdx==1 || dispDemoIdx==3)?true:false, (dispDemoIdx==2 || dispDemoIdx==3)?true:false);
|
|
|
|
drawWifiAndTransmission(0, 16, dispDemoIdx, (dispDemoIdx==1 || dispDemoIdx==3)?true:false, (dispDemoIdx==2 || dispDemoIdx==3)?true:false);
|
|
|
|
drawCharging(88, 24, dispDemoIdx==4);
|
|
|
|
drawWarning(20,16, dispDemoIdx);
|
|
u8g2.setFont(u8g2_font_ncenB08_tr);
|
|
if (dispDemoIdx==0) u8g2.drawStr(39, 32, "OVER.");
|
|
if (dispDemoIdx==1) u8g2.drawStr(39, 32, "N0 BAT.");
|
|
if (dispDemoIdx==2) u8g2.drawStr(39, 32, "SHORT");
|
|
|
|
dispDemoIdx++;
|
|
if (dispDemoIdx > 4) dispDemoIdx = 0;
|
|
u8g2.sendBuffer();
|
|
}
|