Tasmota/lib/lib_display/arduino-tm1637/SevenSegmentFun.cpp

255 lines
6.5 KiB
C++

#include "SevenSegmentFun.h"
const PROGMEM uint8_t levelVerticalMap[4] = {
TM1637_CHAR_HOR_LEVEL_0,
TM1637_CHAR_HOR_LEVEL_1,
TM1637_CHAR_HOR_LEVEL_2,
TM1637_CHAR_HOR_LEVEL_3
};
SevenSegmentFun::SevenSegmentFun(uint8_t pinClk, uint8_t pinDIO) :
SevenSegmentExtended(pinClk, pinDIO)
{
randomSeed(analogRead(0));
};
// 9 levels ( 0, 12.5, 25, 37.4, 50, 62.5, 75.0, 87.5, 100)
void SevenSegmentFun::printLevelVertical(uint8_t level, bool leftToRight) {
level = (level > 100?100:level);
float levelScale = (100 / (TM1637_MAX_COLOM * 2.0));
uint8_t barsOn = float(level) / levelScale;
uint8_t d = leftToRight == true?0:TM1637_MAX_COLOM-1;
for (uint8_t i=0; i < TM1637_MAX_COLOM; i++) {
if (barsOn - (2 * (i + 1)) >= 0) {
_rawBuffer[d] = TM1637_CHAR_VERT_LEVEL_II;
} else if (barsOn - (2 * (i + 1)) >= 1) {
_rawBuffer[d] = (leftToRight == true)?TM1637_CHAR_VERT_LEVEL_I0:TM1637_CHAR_VERT_LEVEL_0I;
} else {
_rawBuffer[d] = 0;
}
if (leftToRight == true) {d++;}
else {d--;};
};
printRaw(_rawBuffer, TM1637_MAX_COLOM, 0);
};
void SevenSegmentFun::printLevelVertical(uint8_t level, bool leftToRight, uint8_t symbol) {
level /= (100 / TM1637_MAX_COLOM);
level = (level > TM1637_MAX_COLOM)?TM1637_MAX_COLOM:level;
for( uint8_t i=0; i < TM1637_MAX_COLOM;i++) {
if ( ( i < level && leftToRight ) || ( i >= ( TM1637_MAX_COLOM - level ) && !leftToRight) ) {
_rawBuffer[i] = symbol;
} else {
_rawBuffer[i] = 0;
}
};
printRaw(_rawBuffer, TM1637_MAX_COLOM, 0);
};
void SevenSegmentFun::nightrider(uint8_t repeats, uint16_t d, uint8_t symbol) {
uint8_t buffer[((TM1637_MAX_COLOM * 2) - 1)] = {0, };
for ( uint8_t i= 0; i < ((TM1637_MAX_COLOM * 2) - 1); i++) {
if ( i == (TM1637_MAX_COLOM - 1) ) {
buffer[i] = symbol;
} else {
buffer[i] = 0;
}
};
for( int8_t r=0; r < repeats; r++) {
for (int8_t i = (TM1637_MAX_COLOM - 1); i > 0; i--) {
printRaw( &buffer[i],4,0);
delay(d);
};
for ( int8_t i = 0; i < (TM1637_MAX_COLOM - 1); i++) {
printRaw( &buffer[i], TM1637_MAX_COLOM, 0);
delay(d);
};
}
}
// 5 levels ( 0, 33, 66, 100)
void SevenSegmentFun::printLevelHorizontal( uint8_t levels[4] ) {
for (uint8_t i=0; i < TM1637_MAX_COLOM;i++) {
levels[i] /= (100 / 3);
levels[i] = ( levels[i] > 3)?3:levels[i];
_rawBuffer[i] = pgm_read_byte_near(levelVerticalMap + levels[i]);
};
printRaw(_rawBuffer, TM1637_MAX_COLOM, 0);
}
void SevenSegmentFun::scrollingText(const char* str, uint8_t repeats) {
uint8_t buffer[TM1637_MAX_CHARS];
size_t length = encode(&buffer[3], str, TM1637_MAX_CHARS);
uint8_t paddingBegin = TM1637_MAX_COLOM - 1;
uint8_t totalPadding = (2 * paddingBegin) + 1;
// padd with three spaces in front
for(uint8_t i=0; i < paddingBegin; i++) {
buffer[i] = 0;
};
// padd with four spaces at the end (empty scree)
for(uint8_t i = length + paddingBegin; i < length + totalPadding ; i++) {
buffer[i] = 0;
};
for( ; repeats != 0; repeats--) {
printRaw(buffer, length + totalPadding);
if ( repeats > 250 ) { // more than 250 -> forever
repeats++;
}
};
}
void SevenSegmentFun::snake(uint8_t repeats, uint16_t d) {
uint8_t outerEdges = (4 * TM1637_MAX_LINES) + (TM1637_MAX_COLOM * 2);
uint8_t widthEdged = (TM1637_MAX_COLOM * 2);
// number of repeats/rounds
for ( uint8_t r=0; r < repeats; r++) {
// 12 steps for all outer edges
for (uint8_t i=0; i < outerEdges; i++) {
for (uint8_t j=0; j < TM1637_MAX_COLOM; j++) {
// set segments
// top edges
if ( i == j) {
_rawBuffer[j] =TM1637_CHAR_SNAKE_0;
}
// top right edge
else if ( i == TM1637_MAX_COLOM && j == 3) {
_rawBuffer[j] =TM1637_CHAR_SNAKE_1;
}
// bottom left edge
else if ( i == (TM1637_MAX_COLOM + 1) && j == 3) {
_rawBuffer[j] =TM1637_CHAR_SNAKE_2;
}
// bottom edges
else if ( i + j == (widthEdged + 1) ) {
_rawBuffer[j] =TM1637_CHAR_SNAKE_3;
}
// bottom left edge
else if ( i == (widthEdged + 2) && j == 0) {
_rawBuffer[j] =TM1637_CHAR_SNAKE_4;
}
// top left edge
else if ( i == (widthEdged + 3) && j == 0) {
_rawBuffer[j] =TM1637_CHAR_SNAKE_5;
} else {
_rawBuffer[j] = 0;
};
};
printRaw(_rawBuffer, 4, 0);
delay(d);
}
};
}
void SevenSegmentFun::bombTimer(uint8_t hours, uint8_t min, uint16_t speed) {
// maximum speed is 60000 -> 1min per ms
speed = (speed > 60000)?60000:speed;
uint16_t d = 60000 / speed;
// copy start minute
int8_t m = min;
int8_t h;
for ( h=hours; h >= 0; h--) {
for ( ; m >= 0; m--) {
printTime((uint8_t)h, (uint8_t)m);
delay(d);
};
m = 59; // reset minute timer
};
blink();
};
void SevenSegmentFun::bombTimer(uint8_t hours, uint8_t min, uint16_t speed, char* str) {
bombTimer(hours, min, speed);
print(str);
blink();
};
void SevenSegmentFun::bouncingBall(uint16_t moves, uint16_t d, bool runForever) {
int8_t wallRight = TM1637_MAX_COLOM - 1;
int8_t wallBottom = TM1637_MAX_LINES;
// start at top left
int8_t x = 0; int8_t y = 0;
int8_t newX; int8_t newY;
// default speed is 1 x right and 2 y down
int8_t vx = 1; int8_t vy = 1;
bool flipVx = false; bool flipVy = false;
// print initial state
printBall(x, y);
for ( ; moves != 0; moves--) {
newX = x + vx;
newY = y + vy;
// check if ball has hit the wall
if (newX > wallRight || newX < 0 ) {
vx = vx * -1;
newX = x + vx;
// random flip other direction as well
flipVy = (random(3) == 1);
};
if ( newY > wallBottom || newY < 0) {
vy = vy * -1;
newY = y + vy;
// random flip other direction as well
flipVx = (random(3) == 1);
};
if ( flipVy ) {
newY = y;
} else if ( flipVx ) {
newX = x;
};
// set new coordinates
x = newX; y = newY;
printBall(x, y);
delay(d);
if (runForever) {
moves++;
};
};
}
void SevenSegmentFun::printBall( const int8_t x, const int8_t y ) {
// uint8_t buffer[4] = {0,0,0,0};
// buffer[x] = (y > 0)?TM1637_CHAR_BALL_LOW:TM1637_CHAR_BALL_HIGH;
// printRaw(buffer);
uint8_t symbol = (y > 0)?TM1637_CHAR_BALL_LOW:TM1637_CHAR_BALL_HIGH;
print4Bit(x, y, symbol);
};
void SevenSegmentFun::print4Bit( const uint8_t x, const uint8_t y, uint8_t symbol) {
uint8_t buffer[4] = {0,0,0,0};
buffer[x] = symbol;
printRaw(buffer);
}