{
"version": 1,
"author": "Ami Sung",
"editor": "wokwi",
"parts": [
{ "type": "wokwi-arduino-uno", "id": "uno", "top": 90.93, "left": -190.84,"attrs": {} },
{ "type": "board-Ssd1306", "id": "oled1", "top": 121.27, "left": 158.38,"attrs": {} },
{ "type": "wokwi-ky-040", "id": "encoder1", "top": 268.93, "left": 115.97,"attrs": {} },
{
"type": "wokwi-buzzer",
"id": "bz1",
"top": -41.84,
"left": 252.89,
"attrs": { "volume": "0.1" }
},
{
"type": "wokwi-tm1637-7segment",
"id": "sevseg1",
"top": -44.94,
"left": 37.09,
"attrs": { "color": "red" }
}
],
"connections": [
[ "sevseg1:VCC", "uno:5V", "red", [ "h29.56", "v70.22", "h-142.27", "v268.59", "h-125.71"
] ],
[ "encoder1:VCC", "uno:5V", "red", [ "h21.09", "v71.64", "h-283.92" ] ],
[ "oled1:VCC", "uno:5V", "red", [ "v-37.85", "h-100.73", "v260", "h-135.52" ] ],
[ "sevseg1:GND", "uno:GND.1", "black", [ "h-1.1", "v38.55", "h-286.37" ] ],
[ "bz1:1", "uno:GND.1", "black", [ "v16.61", "h-356.06" ] ],
[ "oled1:GND", "uno:GND.3", "black", [ "v-22.52", "h-102.93", "v-205.43", "h-95.66" ] ],
[ "encoder1:GND", "uno:GND.2", "black", [ "h14.96", "v51.4", "h-263.68" ] ],
[ "encoder1:SW", "uno:3", "gray", [ "h14.47", "v-73.42", "h-102.32", "v-157.92", "h-97.87"
] ],
[ "encoder1:DT", "uno:4", "gold", [ "h5.58", "v-54.93", "h-100.09", "v-148.29", "h-110.47"
] ],
[ "encoder1:CLK", "uno:2", "orange", [ "h-1.1", "v-35.79", "h-103.06", "v-143.84" ] ],
[ "bz1:2", "uno:10", "purple", [ "v15.53", "h50.01", "v-147.54", "h-370.71" ] ],
[ "sevseg1:DIO", "uno:5", "green", [ "h28.05", "v-57.18", "h-218.72" ] ],
[ "sevseg1:CLK", "uno:6", "green", [ "h18.41", "v-56.48", "h-224.65" ] ],
[ "oled1:SCL", "uno:A5", "blue", [ "v-34.37", "h57.64", "v303.38", "h-198.32" ] ],
[ "oled1:SDA", "uno:A4", "green", [ "v-23.17", "h61.03", "v300.18", "h-229.18" ] ]
]
}
// A simple T-rex Run game based on the 30DLIS kit
// Developed by Ishani and Arijit Sengupta
// Required libraries
#include <u8glib.h>
#include "TM1637Display.h"
// HW Pins required
#define SW 3 // RotaryEncoder SW Pin
#define DT 4 // RotaryEncoder DT Pin
#define CLK 2 // RotaryEncoder CLK pin
// Define the display connections pins:
#define DCLK 6
#define DIO 5
// pin 10 drives the buzzer
#define buzzer 10
// In Addition, this sketch uses the I2C Pins for the U8G Panel
// A1+A2
// Create display object of type TM1637 Display
// The display shows the current score
TM1637Display OurDisplay = TM1637Display(DCLK, DIO);
// Create array that turns all segments off:
const uint8_t blank[] = {0x00, 0x00, 0x00, 0x00}; //0xff is a hexidecimalnumber whose binary
// representation is all zeros
// Create the oled display object - this shows gameplay
// and welcome/win/loss messages
U8GLIB_sh1106_128x64 MY_U8g_Panel(U8G_I2c_OPT_NONE);// I2C / TWI
/*
For documentation on u8glib functions:
https://github.com/olikraus/u8glib/wiki/userreference
*/
// Sounds we use for the hit effects
#define jumpSound 700
#define blahSound 125
#define speedSound 1000
#define DBOUNCE 180
//Game states
#define gameStart 0
#define gameEnd 1
#define gamePlaying 2
volatile int gameStatus = gameStart;
//PRE-SAVED BITMAP CONSTANTS
//20 X 21
static unsigned char dinoJUMP [] U8G_PROGMEM = {
0X00, 0XFC, 0X07, 0X00, 0XFE, 0X07, 0X00, 0XEE, 0X0F, 0X00, 0XFE, 0X0F,
0X00, 0XFE, 0X0F, 0X00, 0XFE, 0X0F, 0X00, 0XFE, 0X07, 0X06, 0XFF, 0X03,
0XC3, 0XFF, 0X00, 0XE7, 0XFF, 0X00, 0XFF, 0XFF, 0X00, 0XFF, 0XFF, 0X00,
0XFF, 0X3F, 0X00, 0XFE, 0X3F, 0X00, 0XFC, 0X1F, 0X00, 0XF8, 0X1F, 0X00,
0XF0, 0X1F, 0X00, 0XF0, 0X0E, 0X00, 0X60, 0X0E, 0X00, 0XE0, 0X0E, 0X00,
0XE0, 0X1E, 0X00,
};
//20 X 21
static unsigned char dinoLeft [] U8G_PROGMEM = {
0X00, 0XFC, 0X07, 0X00, 0XFE, 0X07, 0X00, 0XEE, 0X0F, 0X00, 0XFE, 0X0F,
0X00, 0XFE, 0X0F, 0X00, 0X7E, 0X08, 0X00, 0X7E, 0X00, 0X06, 0XFF, 0X03,
0X87, 0X3F, 0X00, 0XE7, 0XFF, 0X00, 0XFF, 0XFF, 0X00, 0XFF, 0XFF, 0X00,
0XFF, 0X3F, 0X00, 0XFE, 0X3F, 0X00, 0XFC, 0X1F, 0X00, 0XF8, 0X1F, 0X00,
0XF0, 0X1F, 0X00, 0XE0, 0X1E, 0X00, 0X60, 0X00, 0X00, 0XE0, 0X00, 0X00,
0XE0, 0X00, 0X00,
};
//20 X 21
static unsigned char dinoRight [] U8G_PROGMEM = {
0X00, 0XFC, 0X07, 0X00, 0XEE, 0X07, 0X00, 0XE6, 0X0F, 0X00, 0XFE, 0X0F,
0X00, 0XFE, 0X0F, 0X00, 0XFE, 0X0F, 0X00, 0X7C, 0X00, 0X06, 0XFF, 0X03,
0XC3, 0XFF, 0X00, 0XE7, 0XFF, 0X00, 0XFF, 0XFF, 0X00, 0XFF, 0XFF, 0X00,
0XFF, 0X3F, 0X00, 0XFE, 0X3F, 0X00, 0XFC, 0X1F, 0X00, 0XF8, 0X1F, 0X00,
0XF0, 0X1F, 0X00, 0XF0, 0X0F, 0X00, 0XE0, 0X0E, 0X00, 0X00, 0X0E, 0X00,
0X00, 0X1E, 0X00,
};
//shape 0: 39 x 12
static unsigned char cloud [] U8G_PROGMEM = {
0X00, 0X00, 0XC0, 0X00, 0X00, 0X00, 0X00, 0XBE, 0X03, 0X00, 0X00, 0X00,
0X03, 0X06, 0X00, 0X00, 0X80, 0X01, 0X04, 0X00, 0X00, 0X40, 0X00, 0X1C,
0X00, 0X00, 0X40, 0X00, 0XE4, 0X03, 0X00, 0X18, 0X00, 0X00, 0X02, 0XE0,
0X0F, 0X00, 0X00, 0X0E, 0X30, 0X00, 0X00, 0X00, 0X10, 0X10, 0X00, 0X00,
0X00, 0X20, 0X12, 0X00, 0X00, 0X00, 0X40, 0X03, 0XFF, 0XFF, 0XFF, 0X7F,
};
//shape 1: 10 x 20
static unsigned char oneCactus [] U8G_PROGMEM = {
0X30, 0X00, 0X78, 0X00, 0X78, 0X00, 0X78, 0X00, 0X78, 0X01, 0XFB, 0X03,
0XFF, 0X03, 0XFF, 0X03, 0XFF, 0X03, 0XFF, 0X03, 0XFF, 0X03, 0XFF, 0X01,
0XFE, 0X00, 0X78, 0X00, 0X78, 0X00, 0X78, 0X00, 0X78, 0X00, 0X78, 0X00,
0X78, 0X00, 0X00, 0X00,
};
//shape 2: 20 x 20
static unsigned char twoCactus [] U8G_PROGMEM = {
0X30, 0XC0, 0X00, 0X38, 0XE0, 0X00, 0X38, 0XE8, 0X00, 0X38, 0XEC, 0X00,
0X38, 0XED, 0X04, 0XBB, 0XED, 0X0E, 0XBB, 0XED, 0X0E, 0XBB, 0XFD, 0X0E,
0XBB, 0XFD, 0X0E, 0XBB, 0XF9, 0X0E, 0XFF, 0XF1, 0X0F, 0XFF, 0XE0, 0X07,
0X7E, 0XE0, 0X01, 0X38, 0XE0, 0X00, 0X38, 0XE0, 0X00, 0X38, 0XE0, 0X00,
0X38, 0XE0, 0X00, 0X38, 0XE0, 0X00, 0X38, 0XE0, 0X00, 0X00, 0X00, 0X00,
};
//shape 3: 20 x 20
static unsigned char threeCactus [] U8G_PROGMEM = {
0X00, 0XC0, 0X00, 0X18, 0XC0, 0X01, 0X18, 0XC0, 0X01, 0X58, 0XD8, 0X01,
0X58, 0XFC, 0X01, 0X58, 0XFC, 0X0F, 0X78, 0XDC, 0X0F, 0X7F, 0XFC, 0X0F,
0X3B, 0XFD, 0X0D, 0X1B, 0XF9, 0X0C, 0X5B, 0XF5, 0X0F, 0X5B, 0XC5, 0X07,
0X5F, 0XE7, 0X03, 0XDE, 0XE7, 0X01, 0XD8, 0XC3, 0X01, 0X98, 0XC1, 0X01,
0X18, 0XC1, 0X01, 0X18, 0XC1, 0X01, 0X18, 0XE1, 0X01, 0X00, 0X00, 0X00,
};
//shape 4: 6 x 12
static unsigned char oneCactusSmall [] U8G_PROGMEM = {
0x0C, 0X0C, 0X3C, 0X3D, 0X2D, 0X3D, 0X1D, 0X0E, 0X0C, 0X0C, 0X0C, 0X0C,
};
//shape 5: 12 x 12
static unsigned char twoCactusSmall [] U8G_PROGMEM = {
0X0C, 0X03, 0X0C, 0X03, 0X6C, 0X0B, 0X6D, 0X0B, 0X6D, 0X0B, 0XBD, 0X0B,
0X1F, 0X0F, 0X0E, 0X03, 0X0C, 0X03, 0X0C, 0X03, 0X0C, 0X03, 0X0C, 0X03,
};
//shape 6: 17 x 12
static unsigned char threeCactusSmall [] U8G_PROGMEM = {
0X04, 0X41, 0X00, 0X0C, 0X61, 0X00, 0XFC, 0X79, 0X01, 0XFD, 0X7D, 0X01,
0X7D, 0X6D, 0X01, 0X7D, 0X7D, 0X01, 0XCF, 0XE5, 0X01, 0XCE, 0X67, 0X00,
0X8C, 0X67, 0X00, 0X0C, 0X63, 0X00, 0X0C, 0X61, 0X00, 0X0C, 0X61, 0X00,
};
static unsigned char dinoBlah [] U8G_PROGMEM = {
0X00, 0XFC, 0X00, 0X00, 0XFE, 0X07, 0X00, 0XC6, 0X0F, 0X00, 0XC6, 0X0F,
0X00, 0XCE, 0X01, 0X00, 0XFE, 0X0F, 0X00, 0XFE, 0X0F, 0X06, 0XFF, 0X03,
0X87, 0X7F, 0X0D, 0XE7, 0XFF, 0X00, 0XFF, 0XFF, 0X00, 0XFF, 0XFF, 0X00,
0XFF, 0X3F, 0X03, 0XFE, 0X3F, 0X00, 0XFC, 0X1F, 0X00, 0XF8, 0X1F, 0X00,
0XF0, 0X1F, 0X01, 0XF0, 0X0E, 0X00, 0X60, 0X0E, 0X00, 0X60, 0X0E, 0X00,
0XE0, 0X1E, 0X00,
};
static unsigned char gameOver [] U8G_PROGMEM = {
0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00,
0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00,
0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00,
0X00, 0X00, 0X00, 0XF8, 0X01, 0X02, 0X0C, 0X0C, 0X3E, 0X00, 0X78, 0X60,
0X30, 0X7C, 0XF0, 0X01, 0X0C, 0X01, 0X07, 0X14, 0X0A, 0X02, 0X00, 0X84,
0X40, 0X10, 0X04, 0X10, 0X02, 0X04, 0X00, 0X05, 0X14, 0X0A, 0X02, 0X00,
0X02, 0X41, 0X10, 0X04, 0X10, 0X02, 0X04, 0X00, 0X05, 0X14, 0X0A, 0X02,
0X00, 0X02, 0XC1, 0X18, 0X04, 0X10, 0X02, 0XC4, 0X81, 0X0D, 0X34, 0X0B,
0X3E, 0X00, 0X02, 0X81, 0X08, 0X7C, 0XF0, 0X01, 0X04, 0X81, 0X08, 0X24,
0X09, 0X02, 0X00, 0X02, 0X81, 0X0D, 0X04, 0X10, 0X01, 0X04, 0X81, 0X0F,
0X64, 0X09, 0X02, 0X00, 0X02, 0X01, 0X05, 0X04, 0X10, 0X02, 0X0C, 0XC1,
0X18, 0XC4, 0X08, 0X02, 0X00, 0X84, 0X00, 0X05, 0X04, 0X10, 0X02, 0XF8,
0X41, 0X10, 0XC4, 0X08, 0X3E, 0X00, 0X78, 0X00, 0X07, 0X7C, 0X10, 0X02,
0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00,
0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00,
0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00,
0X00, 0X00, 0X00,
};
// Other Game attributes
// Various Variables
int CurrentStateCLK;
int lastStateCLK;
int MyScore = 0;
int dinoMove = 0;
volatile int jumping = 0;
int cloudx = 128;
int obstacles [2] = {1, 4};
int obstaclex [2] = {128, 200};
int speed = 8;
unsigned long startTime = millis(), curTime;
int lastBeep = 0;
//Display the score on the 7seg display
void ShowScore () {
if (gameStatus == gamePlaying) {
curTime = millis ();
Myscore = (curTime - startTime) * speed / 1000;
ourDisplay.showNumberDecEx(Myscore);
if (Myscore / 100 > lastBeep) {
tone (buzzer, 1000, 100);
delay (150);
tone (buzzer, 1250, 100);
lastBeep = MyScore / 100;
}
}
}
void StartStopGame () {
static unsigned long last_interrupt = 0;
if (millis() - last_interrupt > DBOUNCE) {
if (gameStatus == gamePlaying) {
if (jumping == 0) {
jumping = 1;
tone (buzzer, jumpSound, 100);
}
}
else if (gameStatus == gameStart) gameStatus = gamePlaying;
else gameStatus = gameStart;
}
void resetGame () {
MyScore = 0;
startTime = millis();
obstaclex[0] = 128;
obstaclex [1] = 200;
dinoMove = 0;
}
void setup() {
OurDisplay.setBrightness(7);
OurDisplay.clear();
resetGame();
ShowScore ();
pinMode(CLK, INPUT);
pinMode(DT, INPUT);
pinMode(SW, INPUT_PULLUP);
pinMode(buzzer, OUTPUT);
attachInterrupt(digitalPinToInterrupt(SW), StartStopGame, FALLING);
}
// ************************************************
void loop(void) {
ShowScore();
My_u8g_Panel.firstPage();
do {
draw();
} while (My_u8g_Panel.nextPage() );
if (gameStatus == gamePlaying) {
moveDino();
moveCloud ();
moveObstacles();
}
}
void moveDino () {
if (jumping == 0)dinoMove = (dinoMove + 1) % 3;
else {
if (jumping == 1) {
dinoMove = dinoMove + 8;
if (dinoMove > 32) jumping = 2;
} else {
dinoMove = dinoMove - 8;
if (dinoMove < 8) {
jumping = 0;
dinoMove = 0;
}
}
}
checkCollision ();
}
void moveCloud () {
Cloudx --;
if ( cloudx < -38) cloudx = 128;
}
void moveObstacles() {
int obx = obstaclex [0];
Obx = Obx - speed;
if (Obx < -20) {
obstaclex[0] = obstaclex[1];
obstaclex[1] = obstaclex[0] + random(80, 125);
obstacles[0] = obstacles[1];
obstacles[1] = random (1,6);
}
else {
obstaclex[0] = obx;
obstaclex[1] -= speed;
}
}
//************************************************
void draw(void) {
u8g_prepare();
if (gameStatus == gameplaying) {
drawDino ();
drawShape (0, cloudx);
drawObsticles ();
}
else if (gameStatus == gameStart) {
My_u8g_Panel.drawStr( 0, 10, "Welcome to");
My_u8g_Panel.drawstr( 10, 30, "Dino!!");
My_u8g_Panel.drawStr( 0, 50, "push to begin");
resetGame();
ShowScore();
}
else {
My_u8g_Panel.drawXBMP ( 14, 12, 100, 15, gameOver);
drawDino ();
drawShape (0, cloudx);
drawObsticles ();
}
}
void drawDino (void) {
if (gameStatus == gameEnd) {
My_u8g_panel.drawXBMP( 0, 43 - dinoMove, 20, 21, dinoBlah);
return;
}
switch (dinoMove) {
case -1: My_u8g_Panel.drawXBMP( 0, 43, 20, 21, dinoBlah); break;
case 0: My_u8g_Panel.drawXBMP( 0, 43, 20, 21, dinoJump); break;
case 1: My_u8g_Panel.drawXBMP( 0, 43, 20, 21, dinoLeft); break;
case 2: My_u8g_Panel.drawXBMP( 0, 43, 20, 21, dinoRight); break;
default: My_u8g_Panel.drawXBMP( 0, 43 - dinoMove, 20, 21, dinoJump); break;
}
}
void drawShape (int shape, int x) {
switch (shape) {
case 0: My_u8g_Panel.drawXBMP( x, 5, 39, 12, cloud); break;
case 1: My_u8g_Panel.drawXBMP( X, 44, 10, 20, oneCactus); break;
case 2: My_u8g_Panel.drawXBMP( X, 44, 20, 20, twoCactus); break;
case 3: My_u8g_Panel.drawXBMP( X, 44, 20, 20, threeCactus); break;
case 4: My_u8g_Panel.drawXBMP( X, 52, 6, 12, OneCactusSmall); break;
case 5: My_u8g_Panel.drawXBMP( X, 52, 12, 12, twoCactusSmall); break;
case 6: My_u8g_Panel.drawXBMP( X, 52, 17, 12, threeCactusSmall); break;
}
}
void checkCollision () {
int obx = obstaclex [0];
int obw, obh;
switch (obstacles[0]) {
case 0: obw = 39 ; obh = 10; break;
case 1: obw = 10 ; obh = 20; break;
case 2: obw = 17 ; obh = 20; break;
case 3: obw = 17 ; obh = 20; break;
case 4: obw = 6 ; obh = 12; break;
case 5: obw = 12 ; obh = 12; break;
case 6: obw = 17 ; obh = 12; break;
}
if (obx > 15 || obx + obw < 5 || dinoMove > obh - 3) {}
else {
gameStatus = gameEnd;
tone (buzzer, 125, 100);
delay(150);
tone (buzzer, 125, 100);
}
}
void drawObsticles () {
drawShape (obstacles[0], obstaclex[0]);
drawShape (obstacles[1], obstaclex[1]);
}
void u8g_prepare(void) {
My_u8g_Panel.setFont(u8g_font_6x10);
My_u8g_Panel.setFontRefHeightExtendedText();
My_u8g_Panel.setDefaultForegroundColor();
My_u8g_Panel.setFontPosTop();
}
// Author: [email protected]
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// Version 2.1 of the License, or (at your option) any later version.
//
// This library 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#ifndef_TM1637DISPLAY_
#define_TM1637DISPLAY_
#include <inttypes.h>
#define SEG_A 0b00000001
#define SEG_B 0b00000010
#define SEG_C 0b00000100
#define SEG_D 0b00001000
#define SEG_E 0b00010000
#define SEG_F 0b00100000
#define SEG_G 0b01000000
#define SEG_DP 0b10000000
#define DEFAULT_BIT_DELAY 100
class TM1637Display {
public:
//! Initialize a TM1637Display object, setting the clock and
//! data pins.
//!
//! @param pinCLK - The number of the digital pin connected to the clock pin of the module
//! @param pinDIO - The number of the digital pin connected to the DIO pin of the module
//! @param bitDelay - The delay, in microseconds, between bit transition on the serial
//! bus connected to the display
TM1637Display(uint8_t pinClk, uint8_t pinDIO, unsigned int bitDelay = DEFAULT_BIT_DELAY);
//! Sets the brightness of the display
//!
//! The setting takes effect when a command is given to change the data being
//! displayed.
//!
//! @param brigtness A number from 0 (lowes brightness) to 7 (highest brightness)
//! @param on Turn display on or off
void setBrightness(uint8_t brightness, bool on = true);
//! Display arbitrary data on the module
//!
//! This function receives raw segment values as input and displays them. The segment data
//! is given as a byte array, each byte corresponding to a single digit. Within each byte,
//! bit 0 is segment A, bit 1 is segment B etc.
//! The function may either set the entire display or any desirable part on its own. The
first
//! digit is given by the @ref pos argument with 0 being the leftmost digit. The @reflength
//! argument is the number of digits to be set. Other digits are not affected.
//!
//! @param segments An array of size @ref length containing the raw segment values
//! @param length The number of digits to be modified
//! @param pos The position from which to start the modification (0 -leftmost, 3-
rightmost)
void setSegments(const uint8_t segments[], uint8_t length = 4, uint8_t pos = 0);
//! Clear the display
void clear();
//! Display a decimal number
//!
//! Dispaly the given argument as a decimal number.
//!
//! @param num The number to be shown
//! @param leading_zero when true, leading Zeros are displayed, otherwise unnecessary digits
are
//! blank. NOTE: leading zero is not supported with negative numbers.
//! @param length The number of digits to set. The user must ensure that the number to be
shown
//! fits to the number of digits requested (for example, if two digits are to be
displayed,
//! the numbers must be between 0 to 99)
//! @param pos The position of the most significant digit (0 - lefmost, 3 -rightmost)
void shownumberDec(int num, bool leading_zero = false, uint8_t length =4, uint8_t pos = 0);
//! Display a decimal number, with dot control
//!
//! Dispaly the given argument as a decimal number. The dots between the digits (or colon)
//! can be individually controlled.
//!
//! @param num The number to be shown
//! @param dots Dot/colon enable. The argument is a bitmask, with each bit corresponding to
a dot
//! between the digits (or colon mark, as implemented by each module). i.e.
//! For displays with dots between each digit:
//! * 0. 000(0b10000000)
//! * 00.00 (0b01000000)
//! * 000.0 (0b00100000)
//! * 0.0.0.0 (0b11100000)
//! For displays with just a colon:
//! * 00:00 (0b01000000)
//! For displays with dots and colons colon:
//! * 0.0:0.0 (0b11100000)
//! @parm leading_zero when true, leading zeros are displayed. Otherwise unnecessary digits
are
//! blank. NOTE: leading zero is not supported with negative numbers.
//! @param length The number of digits to set. The user must ensure that the number to be
shown
//! fits to the number of digits requested(for example, if two digits are to be
displayed,
//! the number must be between 0 to 99)
//! @param pos The position of the most significant digit (0 -leftmost, 3 - rightmost
void showNumberDecEx(int num, uint8_t dots = 0, bool leading_zero = false, uint8_t length =
4, uint8_t pos = 0);
//! Display a hexadecimal number, with dot control
//!
//! Display the given argument as a hexadecimal number. The dots between the digits (or
colon)
//! can be individually controlled.
//!
//! @param num The number to be shown
//! @param dots Dot/Colon enable. The argument is a bitmask, with each bit corresponding to
a dot
//! between the digits (or colon mark, as implemented by each module). i.e.
//! For displays with dots between each digit:
//! * 0.000 (0b10000000)
//! * 00.00 (0b01000000)
//! * 000.0 (0b00100000)
//! * 0.0.0.0 (0b11100000)
//! For displays with just a colon:
//! * 00:00 (0b01000000)
//! For displays with dots and colons colon:
//! * 0.0:0.0 (0b11100000)
//! @param leading_zero When true, leading zeros are displayed. Otherwise unnecessary digits
are
//! blank
//! @param length The number of digits to set. The user must ensure that the number to be
shown
//! fits to the number of digits requested (for example, if two digits are to be
displayed,
//! the number must be between 0 to 99)
//! @param pos The position of the most significant digit (0 - leftmost, 3 - rightmost)
void showNumberHerEx(uint16_t num, uint8_t dots = 0, bool leading_zero = false, uint8_t
length = 4, uint8_t pos = 0);
//! Translate a single digit into 7 segment code
//! The method accepts a number between 0 -15 and converts it to the
//! code required to display the number on a 7 segment display.
//! Numbers between 10-15 are converted to hexadecimal digits (A-F)
//!
//! @param digit A number between 0 to 15
//! @return A code representing the 7 segment image of the digit (LSB - segment A;
//! bit 6 - segment G; bit 7 - always zero)
uint8_t encodeDigit(uint8_t digit);
protected:
void bitDelay();
void start();
void stop();
bool writeByte(uint8_t b);
void showDots(uint8_t dots, uint8_t* digits);
void showNumberBaseEx(int8_t base, uint16_t num, uint8_t dots = 0, bool leading_zero =
false, uint8_t length = 4, uint8_t pos = 0);
private:
uint8_t m_pinClK;
uint8_t m_pinDIO;
uint8_t m_brightness;
unsigned int m_bitDelay;
};
#endif // _TM1637DISPLAY_
// Author: [email protected]
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or ( at your option) any later version.
//
// This library 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
extern "C" {
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
}
#include "TM1637Display.h"
#include <Arduino.h>
#define TM1637_I2C_COMM1 0X40
#define TM1637_I2C_COMM2 0XC0
#define TM1637_I2C_COMM3 0X80
//
// A
// ---
// F | | B
// -G-
// E | | C
// ---
// D
const uint8_t digitToSegment[] = {
// XGFEDCBA
0b00111111, // 0
0b00000110, // 1
0b01011011, // 2
0b01001111, // 3
0b01100110, // 4
0b01101101, // 5
0b01111101, // 6
0b00000111, // 7
0b01111111, // 8
0b01101111, // 9
0b01110111, // A
0b01111100, // b
0b00111001, // c
0b01011110, // d
0b01111001, // E
0b01110001, // F
};
static const uint8_t minu SEGMENTS = 0b01000000;
TM1637Display::TM1637Display(uint8_t pinClK, uint8_t pinDIO, unsigned int bitDelay)
{
// copy the pin numbers
m_pinClK = pinClK;
m_pinDIO = pinDIO;
m_bitDelay = bitDelay;
// Set the pin direction and default value.
// Both pins are set as inputs, allowing the pull-up resistors to pull them up
pinMode(m_pinClK, INPUT);
pinMode(m_pinDIO, INPUT);
digitalWrite(m_pinClK, LOW);
digitalWrite(m_pinDIO, LOW);
}
void TM1637Display::setBrightness(uint8_t brightness, bool on)
{
m_brightness = (brightness & 0x7) | (on? 0x08 : 0x00);
}
void TM1637Display::setSegments(const uint8_t segments[], uint8_t length, uint8_t pos)
{
// Write COMM1
start();
writeByte(TM1637_I2C_COMM1);
stop();
// Write COMM2 + first digit address
start();
writeByte(TM1637_I2C_COMM2 + (pos & 0x03));
// Write the data bytes
for (uint8_t k=0; k < length; k++)
writeByte(segments[k]);
stop();
// Write COMM3 + brightness
start();
writeByte(TM1637_I2C_COMM3 + (m_brightness & 0x0f));
stop();
}
void TM1637Display::clear()
{
uint8_t data[] = { 0, 0, 0, 0 };
setSegments(data);
}
void TM1637Display::showNumberDec(int num, bool leading_zero, uint8_t length, uint8_t pos)
{
showNumberDecEx(num, 0, leading_zero, length, pos);
}
void TM1637Display::showNumberDecEx(int num, uint8_t dots, bool leading_zero,
uint8_t length, uint8_t pos)
{
showNumberBaseEx(num < 0? -10 : 10, num < 0? -num : num, dots, leading_zero, length, pos);
}
void TM1637Display::showNumberHexEx(uint16_t num, uint8_t dots, bool leading_zero,
uint8_t length, uint8_t pos)
{
showNumberBaseEx(16, num, dots, leading_zero, length, pos);
}
void TM1637Display::showNumberBaseEx(int8_t base, uint16_t num, uint8_t dots, bool
leading_zero,
uint8_t length, uint8_t pos)
{
bool negative = false;
if (base < 0) {
base = -base;
negative = true;
}
uint8_t digits[4];
if (num == 0 && !leading_zero) {
// Singular case - take care separately
for(uint8_t i = 0; i < (length-1); i++)
digits[i] = 0;
digits[length-1] = encodeDigit(0);
}
else {
//uint8_t i = length-1;
//if (negative) {
// // Negative number, show the minus sign
// digits[i] = minusSegments;
// i--;
//}
for(int i = length-1; i >= 0; --i)
{
uint8_t digit = num % base;
if (digit == 0 && num == 0 && leading_zero == false)
// Leading zero is blank
digits[i] = 0;
else
digits[i] = encodeDigit(digit);
if (digit == 0 && num == 0 && negative) {
digits[i] = minusSegments;
negative = false;
}
num /= base;
}
if(dots != 0)
{
showDots(dots, digits);
}
}
setSegments(digit, length, pos);
}
void TM1637Display::bitDelay()
{
delayMicroseconds(m_bitDelay);
}
void TM1637Display::start()
{
pinMode(m_pinDIO, OUTPUT);
bitDelay();
}
void TM1637Display::stop()
{
pinMode(m_pinDIO, OUTPUT);
bitDelay();
pinMode(m_pinClk, INPUT);
bitDelay();
pinMode(m_pinDIO, INPUT);
bitDelay();
}
bool TM1637Display::writeByte(uint8_t b)
{
uint8_t data = b;
// 8 Data Bits
for(uint8_t i = 0; i < 8; i++) {
//CLK low
pinMode(m_pinClK, OUTPUT);
bitDelay();
// Set data bit
if (data & 0x01)
pinMode(m_pinDIO, INPUT);
else
pinMode(m_pinDIO, OUTPUT);
bitDelay();
// CLK high
pinMode(m_pinClK, INPUT);
bitDelay();
data = data >> 1;
}
// Wait for acknowledge
// CLK to zero
pinMode(m_pinClK, OUTPUT);
pinMode(m_pinDIO, INPUT);
bitDelay();
// CLK to high
pinMode(m_pinClK, INPUT);
bitDelay();
uint8_t ack = digitalRead(m_pinDIO);
if (ack == 0)
pinMode(m_pinDIO, OUTPUT);
bitDelay();
pinMode(m_pinClK, OUTPUT);
bitDelay();
return ack;
}
void TM1637Display::showDots(uint8_t dots, uint8_t* digits)
{
for(int i = 0; i < 4; ++i)
{
digits[i] |= (dots & 0x80);
dots <<= 1;
}
}
uint8_t TM1637Display::encodeDigit(uint8_t digit)
{
return digitToSegment[digit & 0x0f];
}
Loading
esp32-s3-box
esp32-s3-box