Compare commits

...

2 Commits

Author SHA1 Message Date
078fa74afb Refactoring for stability, etc. Add new animation. 2023-08-27 01:24:01 +02:00
dccfbf758e Add VS Code settings. 2023-08-27 01:23:19 +02:00
19 changed files with 1849 additions and 933 deletions

1
.gitignore vendored
View File

@@ -7,7 +7,6 @@
.vscode/extensions.json .vscode/extensions.json
.vscode/ipch .vscode/ipch
.vscode/launch.json .vscode/launch.json
.vscode/settings.json
# Own folders # Own folders
_unused/ _unused/

4
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,4 @@
{
"cmake.configureOnOpen": false,
"editor.rulers": [120]
}

View File

@@ -2,6 +2,7 @@
#define ANIMATIONFUNCTIONS_H #define ANIMATIONFUNCTIONS_H
#include <Arduino.h> #include <Arduino.h>
#include "wordclock_constants.h"
enum Direction enum Direction
{ {
@@ -14,7 +15,737 @@ enum Direction
Direction next_direction(Direction dir, int d); Direction next_direction(Direction dir, int d);
int random_snake(bool init, const uint8_t len, const uint32_t color, int numSteps); int random_snake(bool init, const uint8_t len, const uint32_t color, int numSteps);
int random_tetris(bool init); int random_tetris(bool init);
int draw_heart_animation(void);
int draw_spiral(bool init, bool empty, uint8_t size); int draw_spiral(bool init, bool empty, uint8_t size);
void show_digital_clock(uint8_t hours, uint8_t minutes, uint32_t color); void show_digital_clock(uint8_t hours, uint8_t minutes, uint32_t color);
#define HEART_ANIMATION_FRAMES 5
const uint32_t heart_frames_colormap_11x11[HEART_ANIMATION_FRAMES][MATRIX_WIDTH][MATRIX_HEIGHT] =
{
{
{
0x005b000a,
0x002d0304,
0x000f0002,
0x00090001,
0x00350306,
0x00530103,
0x00310407,
0x000a0104,
0x00090001,
0x00300306,
0x00570006,
},
{
0x00330206,
0x00090000,
0x00ce0404,
0x00d70300,
0x000f0008,
0x00350306,
0x000b0100,
0x00c70600,
0x00d40201,
0x00080202,
0x00390006,
},
{
0x000a0000,
0x00db0503,
0x00940906,
0x00950a03,
0x00e20100,
0x000e0008,
0x00d00000,
0x00960806,
0x00940605,
0x00d50600,
0x000d0103,
},
{
0x00da010c,
0x00940700,
0x00580000,
0x00570104,
0x00940a0a,
0x00d40100,
0x00940a08,
0x005a0006,
0x005b0005,
0x009d0305,
0x00da0300,
},
{
0x00d70707,
0x00910a06,
0x00560202,
0x00570207,
0x00580007,
0x00900a09,
0x00540109,
0x005a0004,
0x005b0007,
0x00910a04,
0x00d40201,
},
{
0x00da0207,
0x0092070c,
0x005b0002,
0x00330005,
0x00300405,
0x00580308,
0x002e0503,
0x002c0404,
0x005a0004,
0x00970609,
0x00d80202,
},
{
0x00040402,
0x00dc0600,
0x008f0a0b,
0x00590006,
0x00310504,
0x00320406,
0x00330507,
0x00620008,
0x00960709,
0x00dd0301,
0x000d0304,
},
{
0x00330205,
0x00090100,
0x00d8020a,
0x00930906,
0x00570209,
0x00330205,
0x00580007,
0x00980808,
0x00d60200,
0x000d0003,
0x00340205,
},
{
0x00560008,
0x00340306,
0x00100001,
0x00d40a00,
0x009e0507,
0x005c0007,
0x009e0508,
0x00e50000,
0x000e0001,
0x00310305,
0x00590004,
},
{
0x00a00606,
0x00580007,
0x00350304,
0x00100001,
0x00d40404,
0x00940902,
0x00d50407,
0x00000205,
0x00350304,
0x00560108,
0x00900906,
},
{
0x00d90104,
0x008d080b,
0x0060000b,
0x00340106,
0x00050100,
0x00e00106,
0x000f0000,
0x00370003,
0x00570104,
0x00950a07,
0x00e10007,
},
},
{
{
0x00310304,
0x000b0001,
0x00da0308,
0x00d90101,
0x000b0001,
0x00310304,
0x000b0001,
0x00d60101,
0x00d60101,
0x000b0001,
0x00310304,
},
{
0x000b0001,
0x00d90101,
0x00940808,
0x00940808,
0x00d60101,
0x000b0001,
0x00d60101,
0x00940808,
0x00940808,
0x00d60101,
0x000b0001,
},
{
0x00d90101,
0x00940808,
0x00590005,
0x00590005,
0x00940808,
0x00d90101,
0x00940808,
0x00560004,
0x00590005,
0x00940808,
0x00d60101,
},
{
0x00940808,
0x00590005,
0x00370803,
0x00310304,
0x00590005,
0x00940808,
0x00590005,
0x00310304,
0x00310304,
0x00590005,
0x00940808,
},
{
0x00940808,
0x00590005,
0x002c0303,
0x00310304,
0x00310304,
0x00560004,
0x00310304,
0x00310304,
0x00310304,
0x00590005,
0x00940808,
},
{
0x00940808,
0x00590005,
0x00310304,
0x000b0001,
0x000b0001,
0x00310304,
0x000b0001,
0x00130102,
0x00310304,
0x00590005,
0x00940808,
},
{
0x00d60101,
0x00940808,
0x00590005,
0x00310304,
0x000b0001,
0x000b0001,
0x000b0001,
0x00310304,
0x00590005,
0x00940808,
0x00d90101,
},
{
0x000b0001,
0x00d90802,
0x00940808,
0x00590005,
0x00310304,
0x000b0001,
0x00310304,
0x00560004,
0x00940808,
0x00d90101,
0x000b0001,
},
{
0x00310304,
0x000b0001,
0x00d90101,
0x00940808,
0x00590005,
0x00310304,
0x00590005,
0x00940808,
0x00d90802,
0x000b0001,
0x00310304,
},
{
0x00590005,
0x00310304,
0x000b0001,
0x00d90101,
0x00940808,
0x00560004,
0x00940808,
0x00d60101,
0x000b0001,
0x00310304,
0x00560004,
},
{
0x00940808,
0x00590005,
0x00310304,
0x000b0001,
0x00d60101,
0x00940808,
0x00d60101,
0x000b0001,
0x00310304,
0x00590005,
0x00940808,
},
},
{
{
0x000b0001,
0x00d90101,
0x00940808,
0x00940808,
0x00d90101,
0x000b0001,
0x00d90101,
0x00940808,
0x00940808,
0x00d90101,
0x000b0001,
},
{
0x00d90101,
0x00940808,
0x00590005,
0x00590005,
0x00940808,
0x00d90101,
0x00940808,
0x00560004,
0x00560004,
0x00940808,
0x00d90101,
},
{
0x00940808,
0x00590005,
0x002d0303,
0x00320508,
0x00590005,
0x00940808,
0x00590005,
0x002d0303,
0x00310304,
0x00560004,
0x00940808,
},
{
0x00560004,
0x00320508,
0x000b0001,
0x000b0001,
0x00310304,
0x00590005,
0x002f0308,
0x000b0001,
0x000b0001,
0x002d0303,
0x00590005,
},
{
0x00560004,
0x002d0303,
0x000b0001,
0x000b0001,
0x000b0001,
0x00320508,
0x000b0001,
0x000b0001,
0x000b0001,
0x002d0303,
0x00590005,
},
{
0x00590005,
0x00310304,
0x000b0001,
0x00d40809,
0x00d90101,
0x000b0001,
0x00d90101,
0x00d90101,
0x000b0001,
0x003b0203,
0x00590005,
},
{
0x00940808,
0x00590005,
0x002d0303,
0x000b0001,
0x00d90101,
0x00d40809,
0x00d90101,
0x000b0001,
0x002d0303,
0x00590005,
0x00940808,
},
{
0x00d40809,
0x00940808,
0x00590005,
0x00310304,
0x000b0001,
0x00d90101,
0x000b0001,
0x00320508,
0x00590005,
0x00940808,
0x00d90101,
},
{
0x000b0001,
0x00d60101,
0x00940808,
0x005a0209,
0x002d0303,
0x000b0001,
0x00310304,
0x00560004,
0x00940808,
0x00d90101,
0x000b0001,
},
{
0x00310304,
0x000b0001,
0x00d90101,
0x00940808,
0x00590005,
0x00310304,
0x00590005,
0x00940808,
0x00d60101,
0x000b0001,
0x00310304,
},
{
0x00560004,
0x00310304,
0x000b0001,
0x00d90101,
0x00940808,
0x00590005,
0x00940808,
0x00d60101,
0x000b0001,
0x00310304,
0x00590005,
},
},
{
{
0x00d80802,
0x00940808,
0x00590004,
0x00590004,
0x00940808,
0x00d90101,
0x00940808,
0x00590004,
0x00590004,
0x00940808,
0x00d90101,
},
{
0x00940808,
0x00560004,
0x00310304,
0x00310304,
0x00560004,
0x00940808,
0x00590004,
0x002a0309,
0x00310304,
0x00590004,
0x00940808,
},
{
0x00590004,
0x00310304,
0x000b0001,
0x000b0001,
0x00310304,
0x00590004,
0x00310304,
0x000b0001,
0x000b0001,
0x00310304,
0x00560004,
},
{
0x00350408,
0x000b0001,
0x00d80802,
0x00d60101,
0x000b0001,
0x00310304,
0x000b0001,
0x00d60101,
0x00d60101,
0x000b0001,
0x00310304,
},
{
0x002c0303,
0x00130102,
0x00d60101,
0x00d60101,
0x00d80802,
0x000b0001,
0x00d90101,
0x00d60101,
0x00d80802,
0x000b0001,
0x00310304,
},
{
0x00310304,
0x000b0001,
0x00d90101,
0x00940808,
0x00940808,
0x00db0209,
0x00940808,
0x00940808,
0x00d60101,
0x000b0001,
0x00310304,
},
{
0x00590004,
0x00310304,
0x000b0001,
0x00d80802,
0x00940808,
0x00940808,
0x00940808,
0x00d90101,
0x000b0001,
0x003b0303,
0x00560004,
},
{
0x00940808,
0x00590004,
0x00350408,
0x000b0001,
0x00d90101,
0x00940808,
0x00d90101,
0x000b0001,
0x00310304,
0x00590004,
0x00940808,
},
{
0x00d90101,
0x00940808,
0x00590004,
0x002e0804,
0x00130102,
0x00d60101,
0x000b0001,
0x00310304,
0x00590004,
0x00940808,
0x00d90101,
},
{
0x000b0001,
0x00e10102,
0x00940808,
0x00590004,
0x002c0303,
0x000b0001,
0x003b0303,
0x00590004,
0x00940808,
0x00d90101,
0x000b0001,
},
{
0x00310304,
0x000b0001,
0x00d80802,
0x00940808,
0x00560004,
0x00310304,
0x00590004,
0x00940808,
0x00d90101,
0x000b0001,
0x00310304,
},
},
{
{
0x00940808,
0x00590005,
0x00310304,
0x00310304,
0x00560004,
0x00940808,
0x00590005,
0x002c0303,
0x00310304,
0x00560004,
0x00940808,
},
{
0x00560004,
0x00310304,
0x000b0001,
0x000b0001,
0x00310304,
0x00590005,
0x00310304,
0x000b0001,
0x000b0001,
0x00310304,
0x00590005,
},
{
0x00310304,
0x000b0001,
0x00d90101,
0x00d90101,
0x000b0001,
0x002c0303,
0x000b0001,
0x00d90101,
0x00cf0804,
0x000b0001,
0x00310304,
},
{
0x000b0001,
0x00d60101,
0x00940808,
0x00940808,
0x00e10102,
0x000b0001,
0x00d90101,
0x00940808,
0x00940808,
0x00d90101,
0x000b0001,
},
{
0x000b0001,
0x00d90101,
0x00940808,
0x00940808,
0x00940808,
0x00d90101,
0x00940808,
0x00940808,
0x00940808,
0x00cf0804,
0x000b0001,
},
{
0x000b0001,
0x00da0308,
0x00940808,
0x00590005,
0x00590005,
0x00940808,
0x00590005,
0x00590005,
0x00940808,
0x00d90101,
0x000b0001,
},
{
0x00310304,
0x000b0001,
0x00d90101,
0x00940808,
0x00590005,
0x00590005,
0x00560004,
0x00940808,
0x00d90101,
0x000b0001,
0x00310304,
},
{
0x005a0109,
0x00310304,
0x000b0001,
0x00d90101,
0x00940808,
0x00560004,
0x00940808,
0x00cf0804,
0x000b0001,
0x00310304,
0x00590005,
},
{
0x00940808,
0x00590005,
0x00310304,
0x000b0001,
0x00e10102,
0x00940808,
0x00d60101,
0x000b0001,
0x00310304,
0x00590005,
0x00940808,
},
{
0x00d90101,
0x00940808,
0x00590005,
0x00310304,
0x000b0001,
0x00d90101,
0x00130102,
0x00310304,
0x00590005,
0x00940808,
0x00e10102,
},
{
0x000b0001,
0x00d90101,
0x00940808,
0x00590005,
0x00310304,
0x000b0001,
0x002c0303,
0x00560004,
0x00940808,
0x00d90101,
0x00130102,
},
}};
#endif /* ANIMATIONFUNCTIONS_H */ #endif /* ANIMATIONFUNCTIONS_H */

View File

@@ -44,10 +44,10 @@ private:
uint32_t _current_grid[MATRIX_HEIGHT][MATRIX_WIDTH] = {0}; uint32_t _current_grid[MATRIX_HEIGHT][MATRIX_WIDTH] = {0};
// target representation of minutes indicator leds // target representation of minutes indicator leds
uint32_t _target_indicators[4] = {0, 0, 0, 0}; uint32_t _target_minute_indicators[4] = {0, 0, 0, 0};
// current representation of minutes indicator leds // current representation of minutes indicator leds
uint32_t _current_indicators[4] = {0, 0, 0, 0}; uint32_t _current_minute_indicators[4] = {0, 0, 0, 0};
void _draw_on_matrix(float factor); void _draw_on_matrix(float factor);
uint16_t _calc_estimated_led_current(uint32_t color); uint16_t _calc_estimated_led_current(uint32_t color);

View File

@@ -65,7 +65,5 @@ typedef enum
#define MATRIX_WIDTH 11 #define MATRIX_WIDTH 11
#define MATRIX_HEIGHT 11 #define MATRIX_HEIGHT 11
// State machine states count
#define NUM_STATES 6
#endif /* WORDCLOCK_CONSTANTS_H */ #endif /* WORDCLOCK_CONSTANTS_H */

View File

@@ -25,8 +25,12 @@ typedef enum
ST_SPIRAL, ST_SPIRAL,
ST_TETRIS, ST_TETRIS,
ST_SNAKE, ST_SNAKE,
ST_PINGPONG ST_PINGPONG,
} clock_state_en; ST_HEARTS,
NUM_STATES
} ClockState_en;
#define CURRENT_TIME_MS (system_get_time() / 1000) // use ESP time interface
int EEPROM_read_address(int address); int EEPROM_read_address(int address);
String leading_zero2digit(int value); String leading_zero2digit(int value);
@@ -38,7 +42,7 @@ void handle_current_state(void);
void handle_data_request(void); void handle_data_request(void);
void handle_led_direct(void); void handle_led_direct(void);
void load_main_color(void); void load_main_color(void);
void ntp_time_update(void); void ntp_time_update(unsigned long *last_ntp_update);
void on_state_entry(uint8_t state); void on_state_entry(uint8_t state);
void send_heartbeat(void); void send_heartbeat(void);
void set_main_color(uint8_t red, uint8_t green, uint8_t blue); void set_main_color(uint8_t red, uint8_t green, uint8_t blue);

View File

@@ -1,7 +1,7 @@
<!DOCTYPE HTML> <!-- For more information visit: https://fipsok.de --> <!DOCTYPE HTML> <!-- For more information visit: https://fipsok.de -->
<html lang="de"> <html lang="de">
<head>
<head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="style.css"> <link rel="stylesheet" href="style.css">
@@ -13,9 +13,9 @@
if (!confirm(`Wirklich formatieren? Alle Daten gehen verloren.\nDu musst anschließend fs.html wieder laden.`)) event.preventDefault(); if (!confirm(`Wirklich formatieren? Alle Daten gehen verloren.\nDu musst anschließend fs.html wieder laden.`)) event.preventDefault();
}); });
}); });
function list(to){ function list(to) {
let myList = document.querySelector('main'), noted = ''; let myList = document.querySelector('main'), noted = '';
fetch(`?sort=${to}`).then( (response) => { fetch(`?sort=${to}`).then((response) => {
return response.json(); return response.json();
}).then((json) => { }).then((json) => {
myList.innerHTML = '<nav><input type="radio" id="/" name="group" checked="checked"><label for="/"> &#128193;</label><span id="cr">+&#128193;</nav></span><span id="si"></span>'; myList.innerHTML = '<nav><input type="radio" id="/" name="group" checked="checked"><label for="/"> &#128193;</label><span id="cr">+&#128193;</nav></span><span id="si"></span>';
@@ -35,7 +35,7 @@
document.getElementById('no').classList.toggle('no'); document.getElementById('no').classList.toggle('no');
}); });
so.addEventListener('click', () => { so.addEventListener('click', () => {
list(to=++to%2); list(to = ++to % 2);
localStorage.setItem('sortBy', JSON.stringify(to)); localStorage.setItem('sortBy', JSON.stringify(to));
}); });
document.addEventListener('change', (e) => { document.addEventListener('change', (e) => {
@@ -51,7 +51,7 @@
up.removeAttribute('disabled'); up.removeAttribute('disabled');
} }
} }
document.querySelectorAll(`input[type=radio]`).forEach(el => { if (el.checked) document.querySelector('form').setAttribute('action', '/upload?f=' + el.id)}); document.querySelectorAll(`input[type=radio]`).forEach(el => { if (el.checked) document.querySelector('form').setAttribute('action', '/upload?f=' + el.id) });
}); });
document.querySelectorAll('[href^="?delete=/"]').forEach(node => { document.querySelectorAll('[href^="?delete=/"]').forEach(node => {
node.addEventListener('click', () => { node.addEventListener('click', () => {
@@ -61,20 +61,23 @@
}); });
} }
</script> </script>
</head> </head>
<body>
<body>
<h2>ESP8266 Filesystem Manager</h2> <h2>ESP8266 Filesystem Manager</h2>
<form method="post" enctype="multipart/form-data"> <form method="post" enctype="multipart/form-data">
<input id="fs" type="file" name="up[]" multiple> <input id="fs" type="file" name="up[]" multiple>
<button id="up" disabled>Upload</button> <button id="up" disabled>Upload</button>
</form> </form>
<form id="no" class="no" method="POST"> <form id="no" class="no" method="POST">
<input name="new" placeholder="Ordner Name" pattern="[^\x22/%&\\:;]{1,31}" title="Zeichen &#8220; % & / : ; \ sind nicht erlaubt." required=""> <input name="new" placeholder="Ordner Name" pattern="[^\x22/%&\\:;]{1,31}"
title="Zeichen &#8220; % & / : ; \ sind nicht erlaubt." required="">
<button>Create</button> <button>Create</button>
</form> </form>
<main></main> <main></main>
<form action="/format" method="POST"> <form action="/format" method="POST">
<button id="btn">Format LittleFS</button> <button id="btn">Format LittleFS</button>
</form> </form>
</body> </body>
</html> </html>

View File

@@ -0,0 +1,71 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="50mm"
height="50mm"
version="1.1"
viewBox="0 0 50 50"
id="svg4"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<defs
id="defs4" />
<metadata
id="metadata1">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<g
transform="translate(-60.99,-59.667)"
display="none"
id="g1">
<rect
x="-30.238001"
y="-2.0789001"
width="265.14999"
height="146.28"
fill="#1b2131"
fill-rule="evenodd"
opacity="0.998"
id="rect1" />
</g>
<g
transform="translate(-158.51 -1.487)"
stroke="#fff"
id="g2">
<rect
x="159.51"
y="2.487"
width="48"
height="48"
ry="6.8036"
fill="none"
opacity=".998"
stroke="#fff"
stroke-dashoffset="37.795"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
id="rect2" />
</g>
<g
transform="translate(-60.944598,-60.498371)"
fill="none"
stroke="#ffffff"
stroke-linejoin="round"
stroke-width="2"
id="g4">
<path
d="m 98.493049,73.311072 c -1.567368,-1.782803 -3.642384,-2.757209 -5.857002,-2.757209 -2.214619,0 -4.29598,0.981624 -5.863346,2.764427 l -0.818584,0.9311 -0.831275,-0.945536 c -1.567366,-1.782803 -3.655074,-2.771645 -5.869692,-2.771645 -2.208273,0 -4.289634,0.981625 -5.850654,2.757209 -1.567366,1.782803 -2.43037,4.15025 -2.424025,6.669271 0,2.519022 0.86935,4.87925 2.436716,6.662054 l 11.91706,13.555077 c 0.164986,0.18766 0.387082,0.28871 0.602834,0.28871 0.21575,0 0.437847,-0.0938 0.602832,-0.28149 l 11.94244,-13.533427 c 1.567367,-1.782803 2.430367,-4.150249 2.430367,-6.66927 0.006,-2.519021 -0.85031,-4.886468 -2.417671,-6.669271 z M 97.274689,85.271009 85.935081,98.118738 74.620853,85.249355 c -1.24374,-1.414693 -1.929067,-3.291328 -1.929067,-5.290666 0,-1.999337 0.678982,-3.875972 1.922721,-5.283447 1.237395,-1.407477 2.887254,-2.187003 4.638643,-2.187003 1.757735,0 3.413939,0.779526 4.657679,2.19422 l 1.43411,1.631228 c 0.336317,0.382545 0.875694,0.382545 1.212012,0 l 1.421416,-1.616792 c 1.24374,-1.414695 2.899945,-2.194219 4.651334,-2.194219 1.751392,0 3.401248,0.779524 4.644988,2.187001 1.24374,1.414694 1.922718,3.291328 1.922718,5.290666 0.0064,1.999337 -0.678978,3.875972 -1.922718,5.290666 z"
id="path1"
style="fill:#ffffff;stroke-width:0.067677" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@@ -1,11 +1,11 @@
<!DOCTYPE HTML> <!DOCTYPE HTML>
<html lang="de"> <html lang="de">
<head>
<head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<style> <style>
body {
body{
background-color: #222222; background-color: #222222;
font-family: -apple-system, font-family: -apple-system,
BlinkMacSystemFont, BlinkMacSystemFont,
@@ -23,14 +23,17 @@
animation: gradientBG 14s ease infinite forwards; animation: gradientBG 14s ease infinite forwards;
font-weight: lighter; font-weight: lighter;
} }
/** Animated background: Code By Webdevtrick ( https://webdevtrick.com ) **/ /** Animated background: Code By Webdevtrick ( https://webdevtrick.com ) **/
@-webkit-keyframes gradientBG { @-webkit-keyframes gradientBG {
0% { 0% {
background-position: 0% 50%; background-position: 0% 50%;
} }
50% { 50% {
background-position: 100% 50%; background-position: 100% 50%;
} }
100% { 100% {
background-position: 0% 50%; background-position: 0% 50%;
} }
@@ -40,9 +43,11 @@
0% { 0% {
background-position: 0% 50%; background-position: 0% 50%;
} }
50% { 50% {
background-position: 100% 50%; background-position: 100% 50%;
} }
100% { 100% {
background-position: 0% 50%; background-position: 0% 50%;
} }
@@ -58,24 +63,24 @@
} }
.buttonClass { .buttonClass {
font-size:15px; font-size: 15px;
font-family:Arial; font-family: Arial;
width:70px; width: 70px;
height:70px; height: 70px;
color:#fff; color: #fff;
font-weight:200; font-weight: 200;
border-top-left-radius:14px; border-top-left-radius: 14px;
border-top-right-radius:14px; border-top-right-radius: 14px;
border-bottom-left-radius:14px; border-bottom-left-radius: 14px;
border-bottom-right-radius:14px; border-bottom-right-radius: 14px;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
-moz-user-select: none; -moz-user-select: none;
-webkit-user-select: none; -webkit-user-select: none;
-ms-user-select:none; -ms-user-select: none;
user-select:none; user-select: none;
-o-user-select:none; -o-user-select: none;
} }
.buttonClass:hover { .buttonClass:hover {
@@ -83,8 +88,8 @@
} }
.grid-container { .grid-container {
font-size:15px; font-size: 15px;
font-family:Arial; font-family: Arial;
display: grid; display: grid;
grid-column-gap: 5px; grid-column-gap: 5px;
grid-row-gap: 5px; grid-row-gap: 5px;
@@ -101,35 +106,39 @@
.dot { .dot {
border-radius: 20%; border-radius: 20%;
display: flex; display: flex;
justify-content: center; /* align horizontal */ justify-content: center;
align-items: center; /* align vertical */ /* align horizontal */
align-items: center;
/* align vertical */
} }
.dot-mode { .dot-mode {
display: flex; display: flex;
justify-content: center; /* align horizontal */ justify-content: center;
align-items: center; /* align vertical */ /* align horizontal */
align-items: center;
/* align vertical */
} }
.active{ .active {
border: 2px solid lightgray; border: 2px solid lightgray;
} }
.mode-item{ .mode-item {
background: rgba(59, 57, 57, 0.308); background: rgba(59, 57, 57, 0.308);
} }
.mode-item:hover{ .mode-item:hover {
opacity: 0.7; opacity: 0.7;
} }
.verticalline{ .verticalline {
border-bottom: 1px solid rgba(255, 255, 255, 0.356); border-bottom: 1px solid rgba(255, 255, 255, 0.356);
text-align: center; text-align: center;
color: white; color: white;
} }
input[type="checkbox"]{ input[type="checkbox"] {
-webkit-appearance: none; -webkit-appearance: none;
-moz-appearance: none; -moz-appearance: none;
appearance: none; appearance: none;
@@ -137,8 +146,7 @@
cursor: pointer; cursor: pointer;
} }
.toggle {
.toggle{
height: 32px; height: 32px;
width: 52px; width: 52px;
border-radius: 16px; border-radius: 16px;
@@ -150,7 +158,7 @@
transition: all .2s ease; transition: all .2s ease;
} }
.toggle:after{ .toggle:after {
content: ''; content: '';
position: absolute; position: absolute;
top: 2px; top: 2px;
@@ -159,52 +167,52 @@
height: 24px; height: 24px;
border-radius: 50%; border-radius: 50%;
background: white; background: white;
box-shadow: 0 1px 2px rgba(44,44,44,.2); box-shadow: 0 1px 2px rgba(44, 44, 44, .2);
transition: all .2s cubic-bezier(.5,.1,.75,1.35); transition: all .2s cubic-bezier(.5, .1, .75, 1.35);
} }
.toggle:checked{ .toggle:checked {
border-color: lightgray; border-color: lightgray;
} }
.toggle:checked::after{ .toggle:checked::after {
transform: translatex(20px); transform: translatex(20px);
} }
label { label {
text-align: right; text-align: right;
clear: both; clear: both;
float:left; float: left;
margin-right:15px; margin-right: 15px;
vertical-align: middle; vertical-align: middle;
} }
.checkbox-container{ .checkbox-container {
display:flex; display: flex;
flex-direction: row; flex-direction: row;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
margin: 10px; margin: 10px;
} }
.headline{ .headline {
text-align: center; text-align: center;
font-weight: 200; font-weight: 200;
font-size: larger; font-size: larger;
margin-bottom: 5px; margin-bottom: 5px;
} }
.hidden{ .hidden {
display: none; display: none;
} }
.control-container{ .control-container {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
justify-content: center; justify-content: center;
} }
.wide-button-bottom{ .wide-button-bottom {
width: 80%; width: 80%;
height: 40px; height: 40px;
margin: 10px; margin: 10px;
@@ -212,62 +220,61 @@
background-color: rgba(147, 147, 158, 0.4); background-color: rgba(147, 147, 158, 0.4);
} }
.arrow-button{ .arrow-button {
width: 70px; width: 70px;
height: 70px; height: 70px;
background-color: rgba(147, 147, 158, 0.4); background-color: rgba(147, 147, 158, 0.4);
} }
.tetris-button-bottom{ .tetris-button-bottom {
width: 105px; width: 105px;
height: 40px; height: 40px;
margin: 5px; margin: 5px;
background-color: rgba(147, 147, 158, 0.4); background-color: rgba(147, 147, 158, 0.4);
} }
img{ img {
-moz-user-select: none; -moz-user-select: none;
-webkit-user-select: none; -webkit-user-select: none;
user-select: none; user-select: none;
} }
.setting-button{ .setting-button {
position: absolute; position: absolute;
padding: 10px; padding: 10px;
} }
.settings-container{ .settings-container {
height: 0px; height: 0px;
transition: height 1s; transition: height 1s;
overflow: hidden; overflow: hidden;
} }
.show{ .show {
height: 150px; height: 150px;
transition: height 1s; transition: height 1s;
} }
.number-container{ .number-container {
display:flex; display: flex;
flex-direction: row; flex-direction: row;
justify-content: left; justify-content: left;
align-items: center; align-items: center;
margin: 10px; margin: 10px;
} }
.save-button{ .save-button {
height: 30px; height: 30px;
margin: 5px; margin: 5px;
background-color: rgba(147, 147, 158, 0.4); background-color: rgba(147, 147, 158, 0.4);
} }
</style> </style>
<title>WORDCLOCK 2.0</title> <title>WORDCLOCK 2.0</title>
<link rel="icon" type="image/svg" href="./icons/clock.svg"> <link rel="icon" type="image/svg" href="./icons/clock.svg">
</head> </head>
<body oncontextmenu="return false"> <!-- prevent opening of contextmenu --> <body oncontextmenu="return false"> <!-- prevent opening of contextmenu -->
<div class="setting-button" onclick="toggleSettings()"><img src = "./icons/settings.svg" style="height:20px"/></div> <div class="setting-button" onclick="toggleSettings()"><img src="./icons/settings.svg" style="height:20px" /></div>
<h1 id="headline">WORDCLOCK 2.0</h1> <h1 id="headline">WORDCLOCK 2.0</h1>
@@ -293,23 +300,38 @@
MODE MODE
</div> </div>
<div class="grid-container"> <div class="grid-container">
<div class="grid-item mode-item"><span class="dot-mode" onclick="modechange(this, 0)"><a onclick="sendCommand('./cmd?mode=clock')" class="buttonClass" style="width: 100%;"><img src = "./icons/clock.svg" style="height:50px"/></a></span></div> <div class="grid-item mode-item"><span class="dot-mode" onclick="modechange(this, 0)"><a
<div class="grid-item mode-item"><span class="dot-mode" onclick="modechange(this, 1)"><a onclick="sendCommand('./cmd?mode=diclock')" class="buttonClass" style="width: 100%;"><img src = "./icons/diclock.svg" style="height:50px"/></a></span></div> onclick="sendCommand('./cmd?mode=clock')" class="buttonClass" style="width: 100%;"><img
<div class="grid-item mode-item"><span class="dot-mode" onclick="modechange(this, 2)"><a onclick="sendCommand('./cmd?mode=spiral')" class="buttonClass" style="width: 100%;"><img src = "./icons/spiral.svg" style="height:50px"/></a></span></div> src="./icons/clock.svg" style="height:50px" /></a></span></div>
<div class="grid-item mode-item"><span class="dot-mode" onclick="modechange(this, 3)"><a onclick="sendCommand('./cmd?mode=tetris')" class="buttonClass" style="width: 100%;"><img src = "./icons/tetris.svg" style="height:50px"/></a></span></div> <div class="grid-item mode-item"><span class="dot-mode" onclick="modechange(this, 1)"><a
<div class="grid-item mode-item"><span class="dot-mode" onclick="modechange(this, 4)"><a onclick="sendCommand('./cmd?mode=snake')" class="buttonClass" style="width: 100%;"><img src = "./icons/snake.svg" style="height:50px"/></a></span></div> onclick="sendCommand('./cmd?mode=diclock')" class="buttonClass" style="width: 100%;"><img
<div class="grid-item mode-item"><span class="dot-mode" onclick="modechange(this, 5)"><a onclick="sendCommand('./cmd?mode=pingpong')" class="buttonClass" style="width: 100%;"><img src = "./icons/pingpong.svg" style="height:50px"/></a></span></div> src="./icons/diclock.svg" style="height:50px" /></a></span></div>
<div class="grid-item mode-item"><span class="dot-mode" onclick="modechange(this, 2)"><a
onclick="sendCommand('./cmd?mode=spiral')" class="buttonClass" style="width: 100%;"><img
src="./icons/spiral.svg" style="height:50px" /></a></span></div>
<div class="grid-item mode-item"><span class="dot-mode" onclick="modechange(this, 3)"><a
onclick="sendCommand('./cmd?mode=tetris')" class="buttonClass" style="width: 100%;"><img
src="./icons/tetris.svg" style="height:50px" /></a></span></div>
<div class="grid-item mode-item"><span class="dot-mode" onclick="modechange(this, 4)"><a
onclick="sendCommand('./cmd?mode=snake')" class="buttonClass" style="width: 100%;"><img
src="./icons/snake.svg" style="height:50px" /></a></span></div>
<div class="grid-item mode-item"><span class="dot-mode" onclick="modechange(this, 5)"><a
onclick="sendCommand('./cmd?mode=pingpong')" class="buttonClass" style="width: 100%;"><img
src="./icons/pingpong.svg" style="height:50px" /></a></span></div>
<div class="grid-item mode-item"><span class="dot-mode" onclick="modechange(this, 6)"><a
onclick="sendCommand('./cmd?mode=hearts')" class="buttonClass" style="width: 100%;"><img
src="./icons/hearts.svg" style="height:50px" /></a></span></div>
</div> </div>
<div class="checkbox-container"> <div class="checkbox-container">
<label for="Nightmode" style="align-self: flex-start">Nightmode</label> <label for="Nightmode" style="align-self: flex-start">Nightmode</label>
<div> <div>
<input name= "Nightmode" id="Nightmode" type="checkbox" class="toggle"> <input name="Nightmode" id="Nightmode" type="checkbox" class="toggle">
</div> </div>
</div> </div>
<div class="checkbox-container"> <div class="checkbox-container">
<label for="AutoChange" style="align-self: flex-start">Automatic mode change</label> <label for="AutoChange" style="align-self: flex-start">Automatic mode change</label>
<div> <div>
<input name= "AutoChange" id="AutoChange" type="checkbox" class="toggle"> <input name="AutoChange" id="AutoChange" type="checkbox" class="toggle">
</div> </div>
</div> </div>
@@ -322,18 +344,30 @@
</div> </div>
<div class="control-container"> <div class="control-container">
<div class="grid-container"> <div class="grid-container">
<div class="grid-item"><span class="dot"><a onclick="sendCommand('./cmd?led=255-0-0')" class="buttonClass" style="background:rgb(255,0,0);"></a></span></div> <div class="grid-item"><span class="dot"><a onclick="sendCommand('./cmd?led=255-0-0')"
<div class="grid-item"><span class="dot"><a onclick="sendCommand('./cmd?led=255-0-128')" class="buttonClass" style="background:rgb(255,0,128);"></a></span></div> class="buttonClass" style="background:rgb(255,0,0);"></a></span></div>
<div class="grid-item"><span class="dot"><a onclick="sendCommand('./cmd?led=255-0-255')" class="buttonClass" style="background:rgb(255,0,255);"></a></span></div> <div class="grid-item"><span class="dot"><a onclick="sendCommand('./cmd?led=255-0-128')"
<div class="grid-item"><span class="dot"><a onclick="sendCommand('./cmd?led=128-0-255')" class="buttonClass" style="background:rgb(128,0,255);"></a></span></div> class="buttonClass" style="background:rgb(255,0,128);"></a></span></div>
<div class="grid-item"><span class="dot"><a onclick="sendCommand('./cmd?led=0-0-255')" class="buttonClass" style="background:rgb(0,0,255);"></a></span></div> <div class="grid-item"><span class="dot"><a onclick="sendCommand('./cmd?led=255-0-255')"
<div class="grid-item"><span class="dot"><a onclick="sendCommand('./cmd?led=0-128-255')" class="buttonClass" style="background:rgb(0,128,255);"></a></span></div> class="buttonClass" style="background:rgb(255,0,255);"></a></span></div>
<div class="grid-item"><span class="dot"><a onclick="sendCommand('./cmd?led=255-255-255')" class="buttonClass" style="background:rgb(255,255,255);"></a></span></div> <div class="grid-item"><span class="dot"><a onclick="sendCommand('./cmd?led=128-0-255')"
<div class="grid-item"><span class="dot"><a onclick="sendCommand('./cmd?led=0-255-128')" class="buttonClass" style="background:rgb(0,255,128);"></a></span></div> class="buttonClass" style="background:rgb(128,0,255);"></a></span></div>
<div class="grid-item"><span class="dot"><a onclick="sendCommand('./cmd?led=0-255-0')" class="buttonClass" style="background:rgb(0,255,0);"></a></span></div> <div class="grid-item"><span class="dot"><a onclick="sendCommand('./cmd?led=0-0-255')"
<div class="grid-item"><span class="dot"><a onclick="sendCommand('./cmd?led=128-255-0')" class="buttonClass" style="background:rgb(128,255,0);"></a></span></div> class="buttonClass" style="background:rgb(0,0,255);"></a></span></div>
<div class="grid-item"><span class="dot"><a onclick="sendCommand('./cmd?led=200-200-0')" class="buttonClass" style="background:rgb(200,200,0);"></a></span></div> <div class="grid-item"><span class="dot"><a onclick="sendCommand('./cmd?led=0-128-255')"
<div class="grid-item"><span class="dot"><a onclick="sendCommand('./cmd?led=255-128-0')" class="buttonClass" style="background:rgb(255,128,0);"></a></span></div> class="buttonClass" style="background:rgb(0,128,255);"></a></span></div>
<div class="grid-item"><span class="dot"><a onclick="sendCommand('./cmd?led=255-255-255')"
class="buttonClass" style="background:rgb(255,255,255);"></a></span></div>
<div class="grid-item"><span class="dot"><a onclick="sendCommand('./cmd?led=0-255-128')"
class="buttonClass" style="background:rgb(0,255,128);"></a></span></div>
<div class="grid-item"><span class="dot"><a onclick="sendCommand('./cmd?led=0-255-0')"
class="buttonClass" style="background:rgb(0,255,0);"></a></span></div>
<div class="grid-item"><span class="dot"><a onclick="sendCommand('./cmd?led=128-255-0')"
class="buttonClass" style="background:rgb(128,255,0);"></a></span></div>
<div class="grid-item"><span class="dot"><a onclick="sendCommand('./cmd?led=200-200-0')"
class="buttonClass" style="background:rgb(200,200,0);"></a></span></div>
<div class="grid-item"><span class="dot"><a onclick="sendCommand('./cmd?led=255-128-0')"
class="buttonClass" style="background:rgb(255,128,0);"></a></span></div>
</div> </div>
</div> </div>
</div> </div>
@@ -348,22 +382,30 @@
<div class="control-container"> <div class="control-container">
<div class="grid-container"> <div class="grid-container">
<div class="grid-item" style="grid-column: 2; grid-row: 1;"> <div class="grid-item" style="grid-column: 2; grid-row: 1;">
<div class="buttonClass arrow-button" onclick="sendCommand('./cmd?snake=up')" unselectable="on"><img src = "./icons/arrow_left.svg" style="height:30px; transform:rotate(90deg);"/></div> <div class="buttonClass arrow-button" onclick="sendCommand('./cmd?snake=up')" unselectable="on"><img
src="./icons/arrow_left.svg" style="height:30px; transform:rotate(90deg);" /></div>
</div> </div>
<div class="grid-item" style="grid-column: 1; grid-row: 2;"> <div class="grid-item" style="grid-column: 1; grid-row: 2;">
<div class="buttonClass arrow-button" onclick="sendCommand('./cmd?snake=left')" unselectable="on"><img src = "./icons/arrow_left.svg" style="height:30px;"/></div> <div class="buttonClass arrow-button" onclick="sendCommand('./cmd?snake=left')" unselectable="on">
<img src="./icons/arrow_left.svg" style="height:30px;" />
</div>
</div> </div>
<div class="grid-item" style="grid-column: 2; grid-row: 2;"> <div class="grid-item" style="grid-column: 2; grid-row: 2;">
<div class="buttonClass arrow-button" onclick="sendCommand('./cmd?snake=down')" unselectable="on"><img src = "./icons/arrow_left.svg" style="height:30px; transform:rotate(-90deg);"/></div> <div class="buttonClass arrow-button" onclick="sendCommand('./cmd?snake=down')" unselectable="on">
<img src="./icons/arrow_left.svg" style="height:30px; transform:rotate(-90deg);" />
</div>
</div> </div>
<div class="grid-item" style="grid-column: 3; grid-row: 2;"> <div class="grid-item" style="grid-column: 3; grid-row: 2;">
<div class="buttonClass arrow-button" onclick="sendCommand('./cmd?snake=right')" unselectable="on"><img src = "./icons/arrow_right.svg" style="height:30px;"/></div> <div class="buttonClass arrow-button" onclick="sendCommand('./cmd?snake=right')" unselectable="on">
<img src="./icons/arrow_right.svg" style="height:30px;" />
</div>
</div> </div>
</div> </div>
</div> </div>
<div class="control-container"> <div class="control-container">
<div class="buttonClass wide-button-bottom" onclick="sendCommand('./cmd?snake=new')" unselectable="on"><img src = "./icons/refresh.svg" style="height:30px"/></div> <div class="buttonClass wide-button-bottom" onclick="sendCommand('./cmd?snake=new')" unselectable="on"><img
src="./icons/refresh.svg" style="height:30px" /></div>
</div> </div>
</div> </div>
@@ -377,23 +419,35 @@
<div class="control-container"> <div class="control-container">
<div class="grid-container"> <div class="grid-container">
<div class="grid-item" style="grid-column: 2; grid-row: 1;"> <div class="grid-item" style="grid-column: 2; grid-row: 1;">
<div class="buttonClass arrow-button" onclick="sendCommand('./cmd?tetris=up')" unselectable="on"><img src = "./icons/arrow_left.svg" style="height:30px; transform:rotate(90deg);"/></div> <div class="buttonClass arrow-button" onclick="sendCommand('./cmd?tetris=up')" unselectable="on">
<img src="./icons/arrow_left.svg" style="height:30px; transform:rotate(90deg);" />
</div>
</div> </div>
<div class="grid-item" style="grid-column: 1; grid-row: 2;"> <div class="grid-item" style="grid-column: 1; grid-row: 2;">
<div class="buttonClass arrow-button" onclick="sendCommand('./cmd?tetris=left')" unselectable="on"><img src = "./icons/arrow_left.svg" style="height:30px;"/></div> <div class="buttonClass arrow-button" onclick="sendCommand('./cmd?tetris=left')" unselectable="on">
<img src="./icons/arrow_left.svg" style="height:30px;" />
</div>
</div> </div>
<div class="grid-item" style="grid-column: 2; grid-row: 2;"> <div class="grid-item" style="grid-column: 2; grid-row: 2;">
<div class="buttonClass arrow-button" onclick="sendCommand('./cmd?tetris=down')" unselectable="on"><img src = "./icons/arrow_left.svg" style="height:30px; transform:rotate(-90deg);"/></div> <div class="buttonClass arrow-button" onclick="sendCommand('./cmd?tetris=down')" unselectable="on">
<img src="./icons/arrow_left.svg" style="height:30px; transform:rotate(-90deg);" />
</div>
</div> </div>
<div class="grid-item" style="grid-column: 3; grid-row: 2;"> <div class="grid-item" style="grid-column: 3; grid-row: 2;">
<div class="buttonClass arrow-button" onclick="sendCommand('./cmd?tetris=right')" unselectable="on"><img src = "./icons/arrow_right.svg" style="height:30px;"/></div> <div class="buttonClass arrow-button" onclick="sendCommand('./cmd?tetris=right')" unselectable="on">
<img src="./icons/arrow_right.svg" style="height:30px;" />
</div>
</div> </div>
</div> </div>
</div> </div>
<div class="control-container"> <div class="control-container">
<div class="buttonClass tetris-button-bottom" onclick="sendCommand('./cmd?tetris=play')" unselectable="on"><img src = "./icons/refresh.svg" style="height:20px"/></div> <div class="buttonClass tetris-button-bottom" onclick="sendCommand('./cmd?tetris=play')" unselectable="on">
<div class="buttonClass tetris-button-bottom" onclick="sendCommand('./cmd?tetris=pause')" unselectable="on"><img src = "./icons/playpause.svg" style="height:20px"/></div> <img src="./icons/refresh.svg" style="height:20px" />
</div>
<div class="buttonClass tetris-button-bottom" onclick="sendCommand('./cmd?tetris=pause')" unselectable="on">
<img src="./icons/playpause.svg" style="height:20px" />
</div>
</div> </div>
</div> </div>
@@ -407,17 +461,22 @@
<div class="grid-container"> <div class="grid-container">
<div class="grid-item" style="grid-column: 1; grid-row: 1;"> <div class="grid-item" style="grid-column: 1; grid-row: 1;">
<div class="buttonClass arrow-button" style="width: 140px" onclick="sendCommand('./cmd?pong=up')" unselectable="on"><img src = "./icons/arrow_left.svg" style="height:30px; transform:rotate(90deg);"/></div> <div class="buttonClass arrow-button" style="width: 140px" onclick="sendCommand('./cmd?pong=up')"
unselectable="on"><img src="./icons/arrow_left.svg"
style="height:30px; transform:rotate(90deg);" /></div>
</div> </div>
<div class="grid-item" style="grid-column: 1; grid-row: 2;"> <div class="grid-item" style="grid-column: 1; grid-row: 2;">
<div class="buttonClass arrow-button" style="width: 140px" onclick="sendCommand('./cmd?pong=down')" unselectable="on"><img src = "./icons/arrow_left.svg" style="height:30px; transform:rotate(-90deg);"/></div> <div class="buttonClass arrow-button" style="width: 140px" onclick="sendCommand('./cmd?pong=down')"
unselectable="on"><img src="./icons/arrow_left.svg"
style="height:30px; transform:rotate(-90deg);" /></div>
</div> </div>
</div> </div>
</div> </div>
<div class="control-container"> <div class="control-container">
<div class="buttonClass wide-button-bottom" onclick="sendCommand('./cmd?pong=new')" unselectable="on"><img src = "./icons/refresh.svg" style="height:30px"/></div> <div class="buttonClass wide-button-bottom" onclick="sendCommand('./cmd?pong=new')" unselectable="on"><img
src="./icons/refresh.svg" style="height:30px" /></div>
</div> </div>
</div> </div>
@@ -428,21 +487,21 @@
var url = "./data?key=mode"; var url = "./data?key=mode";
var myVar = null; var myVar = null;
xmlhttp.onreadystatechange = function() { xmlhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) { if (this.readyState == 4 && this.status == 200) {
console.log(this.responseText); console.log(this.responseText);
myVar = JSON.parse(this.responseText); myVar = JSON.parse(this.responseText);
// set mode button state // set mode button state
var state = myVar.modeid; var state = myVar.modeid;
var modebuttons = document.getElementsByClassName("dot-mode"); var modebuttons = document.getElementsByClassName("dot-mode");
for (const element of modebuttons){ for (const element of modebuttons) {
element.classList.remove("active"); element.classList.remove("active");
} }
modebuttons[state].classList.add("active"); modebuttons[state].classList.add("active");
// set checkbox states // set checkbox states
var ckb_nightmode = document.querySelector('input[id="Nightmode"]'); var ckb_nightmode = document.querySelector('input[id="Nightmode"]');
if(myVar.nightMode == "1") { if (myVar.nightMode == "1") {
console.log("nightMode == 1"); console.log("nightMode == 1");
ckb_nightmode.checked = true; ckb_nightmode.checked = true;
} }
@@ -451,7 +510,7 @@
ckb_nightmode.checked = false; ckb_nightmode.checked = false;
} }
ckb_nightmode.addEventListener('change', () => { ckb_nightmode.addEventListener('change', () => {
if(ckb_nightmode.checked) { if (ckb_nightmode.checked) {
sendCommand("./cmd?nightmode=1"); sendCommand("./cmd?nightmode=1");
} else { } else {
sendCommand("./cmd?nightmode=0"); sendCommand("./cmd?nightmode=0");
@@ -459,7 +518,7 @@
}); });
var ckb_stateautochange = document.querySelector('input[id="AutoChange"]'); var ckb_stateautochange = document.querySelector('input[id="AutoChange"]');
if(myVar.stateAutoChange == "1") { if (myVar.stateAutoChange == "1") {
console.log("stateAutoChange == 1"); console.log("stateAutoChange == 1");
ckb_stateautochange.checked = true; ckb_stateautochange.checked = true;
} }
@@ -468,7 +527,7 @@
ckb_stateautochange.checked = false; ckb_stateautochange.checked = false;
} }
ckb_stateautochange.addEventListener('change', () => { ckb_stateautochange.addEventListener('change', () => {
if(ckb_stateautochange.checked) { if (ckb_stateautochange.checked) {
sendCommand("./cmd?stateautochange=1"); sendCommand("./cmd?stateautochange=1");
} else { } else {
sendCommand("./cmd?stateautochange=0"); sendCommand("./cmd?stateautochange=0");
@@ -486,10 +545,10 @@
xmlhttp.open("GET", url, true); xmlhttp.open("GET", url, true);
xmlhttp.send(); xmlhttp.send();
function modechange(element, value){ function modechange(element, value) {
console.log(element); console.log(element);
var modebuttons = document.getElementsByClassName("dot-mode"); var modebuttons = document.getElementsByClassName("dot-mode");
for (const element of modebuttons){ for (const element of modebuttons) {
element.classList.remove("active"); element.classList.remove("active");
} }
element.classList.add("active"); element.classList.add("active");
@@ -497,14 +556,14 @@
updateDisplay(value); updateDisplay(value);
} }
function updateDisplay(modeid){ function updateDisplay(modeid) {
var maincontainer = document.getElementsByClassName("main-container"); var maincontainer = document.getElementsByClassName("main-container");
for (const element of maincontainer){ for (const element of maincontainer) {
element.classList.add("hidden"); element.classList.add("hidden");
} }
if(myVar != null && myVar.stateAutoChange == "0"){ if (myVar != null && myVar.stateAutoChange == "0") {
switch(modeid){ switch (modeid) {
case 0: // clock case 0: // clock
document.getElementById("colorcontainer").classList.remove("hidden"); document.getElementById("colorcontainer").classList.remove("hidden");
break; break;
@@ -519,22 +578,25 @@
case 4: // snake case 4: // snake
document.getElementById("snakecontainer").classList.remove("hidden"); document.getElementById("snakecontainer").classList.remove("hidden");
break; break;
case 5: // pingping case 5: // pingpong
document.getElementById("pongcontainer").classList.remove("hidden"); document.getElementById("pongcontainer").classList.remove("hidden");
break; break;
case 6: // hearts
break;
default:
break;
} }
} }
} }
function sendCommand(command){ function sendCommand(command) {
var xmlhttp = new XMLHttpRequest(); var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", command, true); xmlhttp.open("GET", command, true);
xmlhttp.send(); xmlhttp.send();
} }
function saveSettings(){ function saveSettings() {
var nmStart = document.getElementById("nm_start"); var nmStart = document.getElementById("nm_start");
var nmEnd = document.getElementById("nm_end"); var nmEnd = document.getElementById("nm_end");
var brightnessElmt = document.getElementById("brightness"); var brightnessElmt = document.getElementById("brightness");
@@ -549,9 +611,9 @@
toggleSettings(); toggleSettings();
} }
function toggleSettings(){ function toggleSettings() {
var container = document.getElementById("settings-container"); var container = document.getElementById("settings-container");
if(container.classList.contains("show")){ if (container.classList.contains("show")) {
container.classList.remove("show"); container.classList.remove("show");
} }
else { else {
@@ -560,6 +622,6 @@
} }
</script> </script>
</body> </body>
</html> </html>

View File

@@ -1,4 +1,3 @@
/* For more information visit:https://fipsok.de */ /* For more information visit:https://fipsok.de */
body { body {
font-family: sans-serif; font-family: sans-serif;
@@ -7,72 +6,89 @@ body {
flex-flow: column; flex-flow: column;
align-items: center; align-items: center;
} }
h1,h2 {
h1,
h2 {
color: #e1e1e1; color: #e1e1e1;
text-shadow: 2px 2px 2px black; text-shadow: 2px 2px 2px black;
} }
li { li {
background-color: #feb1e2; background-color: #feb1e2;
list-style-type: none; list-style-type: none;
margin-bottom: 10px; margin-bottom: 10px;
padding: 2px 5px 1px 0; padding: 2px 5px 1px 0;
box-shadow: 5px 5px 5px rgba(0,0,0,0.7); box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.7);
} }
li a:first-child, li b {
li a:first-child,
li b {
background-color: #8f05a5; background-color: #8f05a5;
font-weight: bold; font-weight: bold;
color: white; color: white;
text-decoration:none; text-decoration: none;
padding: 2px 5px; padding: 2px 5px;
text-shadow: 2px 2px 1px black; text-shadow: 2px 2px 1px black;
cursor:pointer; cursor: pointer;
} }
li strong { li strong {
color: red; color: red;
} }
input { input {
height:35px; height: 35px;
font-size:14px; font-size: 14px;
padding-left: .3em; padding-left: .3em;
} }
label + a {
label+a {
text-decoration: none; text-decoration: none;
} }
h1 + main {
h1+main {
display: flex; display: flex;
} }
aside { aside {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
padding: 0.2em; padding: 0.2em;
} }
button { button {
height:40px; height: 40px;
width:130px; width: 130px;
font-size:16px; font-size: 16px;
margin-top: 1em; margin-top: 1em;
box-shadow: 5px 5px 5px rgba(0,0,0,0.7); box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.7);
} }
div button { div button {
background-color: #7bff97; background-color: #7bff97;
} }
nav { nav {
display: flex; display: flex;
align-items: baseline; align-items: baseline;
justify-content: space-between; justify-content: space-between;
} }
#left { #left {
align-items:flex-end; align-items: flex-end;
text-shadow: 0.5px 0.5px 1px #757474; text-shadow: 0.5px 0.5px 1px #757474;
} }
#cr { #cr {
font-weight: bold; font-weight: bold;
cursor:pointer; cursor: pointer;
font-size: 1.5em; font-size: 1.5em;
} }
#up { #up {
width: auto; width: auto;
} }
.note { .note {
background-color: #fecdee; background-color: #fecdee;
padding: 0.5em; padding: 0.5em;
@@ -81,31 +97,39 @@ nav {
max-width: 320px; max-width: 320px;
border-radius: 0.5em; border-radius: 0.5em;
} }
.no { .no {
display: none; display: none;
} }
form [title] { form [title] {
background-color: skyblue; background-color: skyblue;
font-size: 16px; font-size: 16px;
width: 125px; width: 125px;
} }
form:nth-of-type(2) { form:nth-of-type(2) {
margin-bottom: 1em; margin-bottom: 1em;
} }
[value*=Format] { [value*=Format] {
margin-top: 1em; margin-top: 1em;
box-shadow: 5px 5px 5px rgba(0,0,0,0.7); box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.7);
} }
[name="group"] { [name="group"] {
display: none; display: none;
} }
[name="group"] + label {
[name="group"]+label {
font-size: 1.5em; font-size: 1.5em;
margin-right: 5px; margin-right: 5px;
} }
[name="group"] + label::before {
[name="group"]+label::before {
content: "\002610"; content: "\002610";
} }
[name="group"]:checked + label::before {
[name="group"]:checked+label::before {
content: '\002611\0027A5'; content: '\002611\0027A5';
} }

View File

@@ -80,8 +80,8 @@ int NTPClientPlus::updateNTP()
// check if time off last ntp update is roughly in the same range: 100sec apart (validation check) // check if time off last ntp update is roughly in the same range: 100sec apart (validation check)
if (this->_lastSecsSince1900 == 0 || tempSecsSince1900 - this->_lastSecsSince1900 < 100000) if (this->_lastSecsSince1900 == 0 || tempSecsSince1900 - this->_lastSecsSince1900 < 100000)
{ {
// Only update time then // Only update time then account for delay in reading the time
this->_lastUpdate = millis() - (NTP_RECEIVE_WAIT_TIME_MS * (conn_tries + 1)); // Account for delay in reading the time this->_lastUpdate = (system_get_time() / 1000) - (NTP_RECEIVE_WAIT_TIME_MS * (conn_tries + 1));
this->_secsSince1900 = tempSecsSince1900; this->_secsSince1900 = tempSecsSince1900;
this->_currentEpoc = this->_secsSince1900 - UNIX_TIMESTAMP_1900; this->_currentEpoc = this->_secsSince1900 - UNIX_TIMESTAMP_1900;
@@ -141,7 +141,7 @@ unsigned long NTPClientPlus::getSecsSince1900() const
{ {
return this->_timeOffset + // User offset return this->_timeOffset + // User offset
this->_secsSince1900 + // seconds returned by the NTP server this->_secsSince1900 + // seconds returned by the NTP server
((millis() - this->_lastUpdate) / 1000); // Time since last update (((system_get_time() / 1000) - this->_lastUpdate) / 1000); // Time since last update
} }
/** /**
@@ -685,8 +685,8 @@ bool NTPClientPlus::updateSWChange()
void wait(unsigned long time) void wait(unsigned long time)
{ {
unsigned long start = millis(); unsigned long start = (system_get_time() / 1000);
while (millis() - start < time) while (((system_get_time() / 1000) - start) < time)
{ {
yield(); yield();
}; };

View File

@@ -21,7 +21,7 @@ void UDPLogger::set_name(String name)
void UDPLogger::log_string(String message) void UDPLogger::log_string(String message)
{ {
// wait 5 milliseconds if last send was less than 5 milliseconds before // wait 5 milliseconds if last send was less than 5 milliseconds before
if (millis() < (_lastSend + 5)) if ((system_get_time() / 1000) < (_lastSend + 5))
{ {
delay(5); delay(5);
} }
@@ -31,13 +31,13 @@ void UDPLogger::log_string(String message)
message.toCharArray(_packetBuffer, 100); message.toCharArray(_packetBuffer, 100);
_udp.print(_packetBuffer); _udp.print(_packetBuffer);
_udp.endPacket(); _udp.endPacket();
_lastSend = millis(); _lastSend = (system_get_time() / 1000);
} }
void UDPLogger::log_color_24bit(uint32_t color) void UDPLogger::log_color_24bit(uint32_t color)
{ {
uint8_t result_red = color >> 16 & 0xff; uint8_t result_red = color >> 16 & UINT8_MAX;
uint8_t result_green = color >> 8 & 0xff; uint8_t result_green = color >> 8 & UINT8_MAX;
uint8_t result_blue = color & 0xff; uint8_t result_blue = color & UINT8_MAX;
log_string(String(result_red) + ", " + String(result_green) + ", " + String(result_blue)); log_string(String(result_red) + ", " + String(result_green) + ", " + String(result_blue));
} }

View File

@@ -60,10 +60,10 @@ void Pong::loopCycle()
*/ */
void Pong::ctrlUp(uint8_t playerid) void Pong::ctrlUp(uint8_t playerid)
{ {
if (millis() > _lastButtonClick + DEBOUNCE_TIME) if ((system_get_time() / 1000) > (_lastButtonClick + DEBOUNCE_TIME))
{ {
_playerMovement[playerid] = PADDLE_MOVE_DOWN; // need to swap direction as field is rotated 180deg _playerMovement[playerid] = PADDLE_MOVE_DOWN; // need to swap direction as field is rotated 180deg
_lastButtonClick = millis(); _lastButtonClick = (system_get_time() / 1000);
} }
} }
@@ -74,10 +74,10 @@ void Pong::ctrlUp(uint8_t playerid)
*/ */
void Pong::ctrlDown(uint8_t playerid) void Pong::ctrlDown(uint8_t playerid)
{ {
if (millis() > _lastButtonClick + DEBOUNCE_TIME) if ((system_get_time() / 1000) > (_lastButtonClick + DEBOUNCE_TIME))
{ {
_playerMovement[playerid] = PADDLE_MOVE_UP; // need to swap direction as field is rotated 180deg _playerMovement[playerid] = PADDLE_MOVE_UP; // need to swap direction as field is rotated 180deg
_lastButtonClick = millis(); _lastButtonClick = (system_get_time() / 1000);
} }
} }
@@ -88,10 +88,10 @@ void Pong::ctrlDown(uint8_t playerid)
*/ */
void Pong::ctrlNone(uint8_t playerid) void Pong::ctrlNone(uint8_t playerid)
{ {
if (millis() > _lastButtonClick + DEBOUNCE_TIME) if ((system_get_time() / 1000) > (_lastButtonClick + DEBOUNCE_TIME))
{ {
_playerMovement[playerid] = PADDLE_MOVE_NONE; _playerMovement[playerid] = PADDLE_MOVE_NONE;
_lastButtonClick = millis(); _lastButtonClick = (system_get_time() / 1000);
} }
} }
@@ -102,9 +102,9 @@ void Pong::ctrlNone(uint8_t playerid)
*/ */
void Pong::initGame(uint8_t numBots) void Pong::initGame(uint8_t numBots)
{ {
(*_logger).log_string("Pong: init with " + String(numBots) + " Bots"); _logger->log_string("Pong: init with " + String(numBots) + " Bots");
resetLEDs(); resetLEDs();
_lastButtonClick = millis(); _lastButtonClick = (system_get_time() / 1000);
_numBots = numBots; _numBots = numBots;
@@ -134,11 +134,11 @@ void Pong::initGame(uint8_t numBots)
void Pong::updateBall() void Pong::updateBall()
{ {
bool hitBall = false; bool hitBall = false;
if ((millis() - _lastBallUpdate) < _ballDelay) if (((system_get_time() / 1000) - _lastBallUpdate) < _ballDelay)
{ {
return; return;
} }
_lastBallUpdate = millis(); _lastBallUpdate = (system_get_time() / 1000);
toggleLed(_ball.x, _ball.y, LED_TYPE_OFF); toggleLed(_ball.x, _ball.y, LED_TYPE_OFF);
// collision detection for player 1 // collision detection for player 1
@@ -199,7 +199,7 @@ void Pong::updateBall()
*/ */
void Pong::endGame() void Pong::endGame()
{ {
(*_logger).log_string("Pong: Game ended"); _logger->log_string("Pong: Game ended");
_gameState = GAME_STATE_END; _gameState = GAME_STATE_END;
toggleLed(_ball.x, _ball.y, LED_TYPE_BALL_RED); toggleLed(_ball.x, _ball.y, LED_TYPE_BALL_RED);
} }
@@ -210,11 +210,11 @@ void Pong::endGame()
*/ */
void Pong::updateGame() void Pong::updateGame()
{ {
if ((millis() - _lastDrawUpdate) < GAME_DELAY) if (((system_get_time() / 1000) - _lastDrawUpdate) < GAME_DELAY)
{ {
return; return;
} }
_lastDrawUpdate = millis(); _lastDrawUpdate = (system_get_time() / 1000);
// turn off paddle LEDs // turn off paddle LEDs
for (uint8_t p = 0; p < PLAYER_AMOUNT; p++) for (uint8_t p = 0; p < PLAYER_AMOUNT; p++)
@@ -297,7 +297,7 @@ uint8_t Pong::getPlayerMovement(uint8_t playerId)
*/ */
void Pong::resetLEDs() void Pong::resetLEDs()
{ {
(*_ledmatrix).flush(); _ledmatrix->flush();
} }
/** /**
@@ -328,5 +328,5 @@ void Pong::toggleLed(uint8_t x, uint8_t y, uint8_t type)
break; break;
} }
(*_ledmatrix).grid_add_pixel(x, y, color); _ledmatrix->grid_add_pixel(x, y, color);
} }

View File

@@ -58,11 +58,11 @@ void Snake::loopCycle()
*/ */
void Snake::ctrlUp() void Snake::ctrlUp()
{ {
if (millis() > _lastButtonClick + DEBOUNCE_TIME && _gameState == GAME_STATE_RUNNING) if ((system_get_time() / 1000) > _lastButtonClick + DEBOUNCE_TIME && _gameState == GAME_STATE_RUNNING)
{ {
(*_logger).log_string("Snake: UP"); _logger->log_string("Snake: UP");
_userDirection = DIRECTION_DOWN; // need to swap direction as field is rotated 180deg _userDirection = DIRECTION_DOWN; // need to swap direction as field is rotated 180deg
_lastButtonClick = millis(); _lastButtonClick = (system_get_time() / 1000);
} }
} }
@@ -72,11 +72,11 @@ void Snake::ctrlUp()
*/ */
void Snake::ctrlDown() void Snake::ctrlDown()
{ {
if (millis() > _lastButtonClick + DEBOUNCE_TIME && _gameState == GAME_STATE_RUNNING) if ((system_get_time() / 1000) > _lastButtonClick + DEBOUNCE_TIME && _gameState == GAME_STATE_RUNNING)
{ {
_logger->log_string("Snake: DOWN"); _logger->log_string("Snake: DOWN");
_userDirection = DIRECTION_UP; // need to swap direction as field is rotated 180deg _userDirection = DIRECTION_UP; // need to swap direction as field is rotated 180deg
_lastButtonClick = millis(); _lastButtonClick = (system_get_time() / 1000);
} }
} }
@@ -86,11 +86,11 @@ void Snake::ctrlDown()
*/ */
void Snake::ctrlRight() void Snake::ctrlRight()
{ {
if (millis() > _lastButtonClick + DEBOUNCE_TIME && _gameState == GAME_STATE_RUNNING) if ((system_get_time() / 1000) > _lastButtonClick + DEBOUNCE_TIME && _gameState == GAME_STATE_RUNNING)
{ {
_logger->log_string("Snake: RIGHT"); _logger->log_string("Snake: RIGHT");
_userDirection = DIRECTION_LEFT; // need to swap direction as field is rotated 180deg _userDirection = DIRECTION_LEFT; // need to swap direction as field is rotated 180deg
_lastButtonClick = millis(); _lastButtonClick = (system_get_time() / 1000);
} }
} }
@@ -100,11 +100,11 @@ void Snake::ctrlRight()
*/ */
void Snake::ctrlLeft() void Snake::ctrlLeft()
{ {
if (millis() > _lastButtonClick + DEBOUNCE_TIME && _gameState == GAME_STATE_RUNNING) if ((system_get_time() / 1000) > _lastButtonClick + DEBOUNCE_TIME && _gameState == GAME_STATE_RUNNING)
{ {
_logger->log_string("Snake: LEFT"); _logger->log_string("Snake: LEFT");
_userDirection = DIRECTION_RIGHT; // need to swap direction as field is rotated 180deg _userDirection = DIRECTION_RIGHT; // need to swap direction as field is rotated 180deg
_lastButtonClick = millis(); _lastButtonClick = (system_get_time() / 1000);
} }
} }
@@ -131,7 +131,7 @@ void Snake::initGame()
_food.y = -1; _food.y = -1;
_wormLength = MIN_TAIL_LENGTH; _wormLength = MIN_TAIL_LENGTH;
_userDirection = DIRECTION_LEFT; _userDirection = DIRECTION_LEFT;
_lastButtonClick = millis(); _lastButtonClick = (system_get_time() / 1000);
for (int i = 0; i < MAX_TAIL_LENGTH; i++) for (int i = 0; i < MAX_TAIL_LENGTH; i++)
{ {
@@ -148,7 +148,7 @@ void Snake::initGame()
*/ */
void Snake::updateGame() void Snake::updateGame()
{ {
if ((millis() - _lastDrawUpdate) > GAME_DELAY) if (((system_get_time() / 1000) - _lastDrawUpdate) > GAME_DELAY)
{ {
_logger->log_string("Snake: update game"); _logger->log_string("Snake: update game");
toggleLed(_tail[_wormLength - 1].x, _tail[_wormLength - 1].y, LED_TYPE_OFF); toggleLed(_tail[_wormLength - 1].x, _tail[_wormLength - 1].y, LED_TYPE_OFF);
@@ -197,7 +197,7 @@ void Snake::updateGame()
updateFood(); updateFood();
} }
_lastDrawUpdate = millis(); _lastDrawUpdate = (system_get_time() / 1000);
} }
} }

View File

@@ -26,7 +26,7 @@ Tetris::Tetris(LEDMatrix *myledmatrix, UDPLogger *mylogger)
{ {
_logger = mylogger; _logger = mylogger;
_ledmatrix = myledmatrix; _ledmatrix = myledmatrix;
_gameStatet = GAME_STATE_READY; _gameState = GAME_STATE_READY;
} }
/** /**
@@ -35,7 +35,7 @@ Tetris::Tetris(LEDMatrix *myledmatrix, UDPLogger *mylogger)
*/ */
void Tetris::loopCycle() void Tetris::loopCycle()
{ {
switch (_gameStatet) switch (_gameState)
{ {
case GAME_STATE_READY: case GAME_STATE_READY:
@@ -51,18 +51,18 @@ void Tetris::loopCycle()
// move faster down when allow drop // move faster down when allow drop
if (_allowdrop) if (_allowdrop)
{ {
if (millis() > _droptime + 50) if ((system_get_time() / 1000) > (_droptime + 50))
{ {
_droptime = millis(); _droptime = (system_get_time() / 1000);
shiftActiveBrick(DIR_DOWN); shiftActiveBrick(DIR_DOWN);
printField(); printField();
} }
} }
// move down with regular speed // move down with regular speed
if ((millis() - _prevUpdateTime) > (_brickSpeed * _speedtetris / 100)) if (((system_get_time() / 1000) - _prevUpdateTime) > (_brickSpeed * _speedtetris / 100))
{ {
_prevUpdateTime = millis(); _prevUpdateTime = (system_get_time() / 1000);
shiftActiveBrick(DIR_DOWN); shiftActiveBrick(DIR_DOWN);
printField(); printField();
} }
@@ -74,7 +74,7 @@ void Tetris::loopCycle()
// and create new brick at top of field // and create new brick at top of field
checkFullLines(); checkFullLines();
newActiveBrick(); newActiveBrick();
_prevUpdateTime = millis(); // Reset update time to avoid brick dropping two spaces _prevUpdateTime = (system_get_time() / 1000); // Reset update time to avoid brick dropping two spaces
} }
break; break;
case GAME_STATE_PAUSED: case GAME_STATE_PAUSED:
@@ -85,17 +85,17 @@ void Tetris::loopCycle()
if (_tetrisGameOver == true) if (_tetrisGameOver == true)
{ {
_tetrisGameOver = false; _tetrisGameOver = false;
(*_logger).log_string("Tetris: end"); _logger->log_string("Tetris: end");
everythingRed(); everythingRed();
_tetrisshowscore = millis(); _tetrisshowscore = (system_get_time() / 1000);
} }
if (millis() > (_tetrisshowscore + RED_END_TIME)) if ((system_get_time() / 1000) > (_tetrisshowscore + RED_END_TIME))
{ {
resetLEDs(); resetLEDs();
_score = _nbRowsTotal; _score = _nbRowsTotal;
showscore(); showscore();
_gameStatet = GAME_STATE_READY; _gameState = GAME_STATE_READY;
} }
break; break;
} }
@@ -107,10 +107,10 @@ void Tetris::loopCycle()
*/ */
void Tetris::ctrlStart() void Tetris::ctrlStart()
{ {
if (millis() > _lastButtonClick + DEBOUNCE_TIME) if ((system_get_time() / 1000) > _lastButtonClick + DEBOUNCE_TIME)
{ {
_lastButtonClick = millis(); _lastButtonClick = (system_get_time() / 1000);
_gameStatet = GAME_STATE_INIT; _gameState = GAME_STATE_INIT;
} }
} }
@@ -120,20 +120,20 @@ void Tetris::ctrlStart()
*/ */
void Tetris::ctrlPlayPause() void Tetris::ctrlPlayPause()
{ {
if (millis() > _lastButtonClick + DEBOUNCE_TIME) if ((system_get_time() / 1000) > _lastButtonClick + DEBOUNCE_TIME)
{ {
_lastButtonClick = millis(); _lastButtonClick = (system_get_time() / 1000);
if (_gameStatet == GAME_STATE_PAUSED) if (_gameState == GAME_STATE_PAUSED)
{ {
(*_logger).log_string("Tetris: continue"); _logger->log_string("Tetris: continue");
_gameStatet = GAME_STATE_RUNNING; _gameState = GAME_STATE_RUNNING;
} }
else if (_gameStatet == GAME_STATE_RUNNING) else if (_gameState == GAME_STATE_RUNNING)
{ {
(*_logger).log_string("Tetris: pause"); _logger->log_string("Tetris: pause");
_gameStatet = GAME_STATE_PAUSED; _gameState = GAME_STATE_PAUSED;
} }
} }
} }
@@ -144,9 +144,9 @@ void Tetris::ctrlPlayPause()
*/ */
void Tetris::ctrlRight() void Tetris::ctrlRight()
{ {
if (millis() > _lastButtonClick + DEBOUNCE_TIME && _gameStatet == GAME_STATE_RUNNING) if ((system_get_time() / 1000) > _lastButtonClick + DEBOUNCE_TIME && _gameState == GAME_STATE_RUNNING)
{ {
_lastButtonClick = millis(); _lastButtonClick = (system_get_time() / 1000);
shiftActiveBrick(DIR_RIGHT); shiftActiveBrick(DIR_RIGHT);
printField(); printField();
} }
@@ -158,9 +158,9 @@ void Tetris::ctrlRight()
*/ */
void Tetris::ctrlLeft() void Tetris::ctrlLeft()
{ {
if (millis() > _lastButtonClick + DEBOUNCE_TIME && _gameStatet == GAME_STATE_RUNNING) if ((system_get_time() / 1000) > _lastButtonClick + DEBOUNCE_TIME && _gameState == GAME_STATE_RUNNING)
{ {
_lastButtonClick = millis(); _lastButtonClick = (system_get_time() / 1000);
shiftActiveBrick(DIR_LEFT); shiftActiveBrick(DIR_LEFT);
printField(); printField();
} }
@@ -172,9 +172,9 @@ void Tetris::ctrlLeft()
*/ */
void Tetris::ctrlUp() void Tetris::ctrlUp()
{ {
if (millis() > _lastButtonClick + DEBOUNCE_TIME && _gameStatet == GAME_STATE_RUNNING) if ((system_get_time() / 1000) > _lastButtonClick + DEBOUNCE_TIME && _gameState == GAME_STATE_RUNNING)
{ {
_lastButtonClick = millis(); _lastButtonClick = (system_get_time() / 1000);
rotateActiveBrick(); rotateActiveBrick();
printField(); printField();
} }
@@ -187,10 +187,10 @@ void Tetris::ctrlUp()
void Tetris::ctrlDown() void Tetris::ctrlDown()
{ {
// longer debounce time, to prevent immediate drop // longer debounce time, to prevent immediate drop
if (millis() > _lastButtonClickr + DEBOUNCE_TIME * 5 && _gameStatet == GAME_STATE_RUNNING) if ((system_get_time() / 1000) > _lastButtonClickr + DEBOUNCE_TIME * 5 && _gameState == GAME_STATE_RUNNING)
{ {
_allowdrop = true; _allowdrop = true;
_lastButtonClickr = millis(); _lastButtonClickr = (system_get_time() / 1000);
} }
} }
@@ -221,7 +221,7 @@ void Tetris::resetLEDs()
*/ */
void Tetris::tetrisInit() void Tetris::tetrisInit()
{ {
(*_logger).log_string("Tetris: init"); _logger->log_string("Tetris: init");
clearField(); clearField();
_brickSpeed = INIT_SPEED; _brickSpeed = INIT_SPEED;
@@ -230,9 +230,9 @@ void Tetris::tetrisInit()
_tetrisGameOver = false; _tetrisGameOver = false;
newActiveBrick(); newActiveBrick();
_prevUpdateTime = millis(); _prevUpdateTime = (system_get_time() / 1000);
_gameStatet = GAME_STATE_RUNNING; _gameState = GAME_STATE_RUNNING;
} }
/** /**
@@ -318,7 +318,7 @@ void Tetris::newActiveBrick()
if (checkFieldCollision(&_activeBrick)) if (checkFieldCollision(&_activeBrick))
{ {
_tetrisGameOver = true; _tetrisGameOver = true;
_gameStatet = GAME_STATE_END; _gameState = GAME_STATE_END;
} }
} }

View File

@@ -437,3 +437,20 @@ int random_tetris(bool init)
} }
return 0; return 0;
} }
int draw_heart_animation(void)
{
static uint8_t frame_idx = 0;
for (int col = 0; col < MATRIX_WIDTH; col++)
{
for (int row = 0; row < MATRIX_HEIGHT; row++)
{
led_matrix.grid_add_pixel(col, row, heart_frames_colormap_11x11[frame_idx][col][row]);
}
}
// Increase frame index per call until HEART_ANIMATION_FRAMES - 1 for array index.
frame_idx = (frame_idx >= (HEART_ANIMATION_FRAMES - 1)) ? 0 : frame_idx + 1;
return 0;
}

View File

@@ -50,9 +50,9 @@ uint32_t LEDMatrix::color_24bit(uint8_t r, uint8_t g, uint8_t b)
*/ */
uint16_t LEDMatrix::color_24_to_16bit(uint32_t color_24bit) uint16_t LEDMatrix::color_24_to_16bit(uint32_t color_24bit)
{ {
uint8_t r = color_24bit >> 16 & 0xff; uint8_t r = color_24bit >> 16 & UINT8_MAX;
uint8_t g = color_24bit >> 8 & 0xff; uint8_t g = color_24bit >> 8 & UINT8_MAX;
uint8_t b = color_24bit & 0xff; uint8_t b = color_24bit & UINT8_MAX;
return ((uint16_t)(r & 0xF8) << 8) | return ((uint16_t)(r & 0xF8) << 8) |
((uint16_t)(g & 0xFC) << 3) | ((uint16_t)(g & 0xFC) << 3) |
(b >> 3); (b >> 3);
@@ -90,13 +90,13 @@ uint32_t LEDMatrix::wheel(uint8_t WheelPos)
*/ */
uint32_t LEDMatrix::interpolate_color_24bit(uint32_t color1, uint32_t color2, float factor) uint32_t LEDMatrix::interpolate_color_24bit(uint32_t color1, uint32_t color2, float factor)
{ {
uint8_t resultRed = color1 >> 16 & 0xff; uint8_t result_R = color1 >> 16 & UINT8_MAX;
uint8_t resultGreen = color1 >> 8 & 0xff; uint8_t result_G = color1 >> 8 & UINT8_MAX;
uint8_t resultBlue = color1 & 0xff; uint8_t result_B = color1 & UINT8_MAX;
resultRed = (uint8_t)(resultRed + (int16_t)(factor * ((int16_t)(color2 >> 16 & 0xff) - (int16_t)resultRed))); result_R = (uint8_t)(result_R + (int16_t)(factor * ((int16_t)(color2 >> 16 & UINT8_MAX) - (int16_t)result_R)));
resultGreen = (uint8_t)(resultGreen + (int16_t)(factor * ((int16_t)(color2 >> 8 & 0xff) - (int16_t)resultGreen))); result_G = (uint8_t)(result_G + (int16_t)(factor * ((int16_t)(color2 >> 8 & UINT8_MAX) - (int16_t)result_G)));
resultBlue = (uint8_t)(resultBlue + (int16_t)(factor * ((int16_t)(color2 & 0xff) - (int16_t)resultBlue))); result_B = (uint8_t)(result_B + (int16_t)(factor * ((int16_t)(color2 & UINT8_MAX) - (int16_t)result_B)));
return color_24bit(resultRed, resultGreen, resultBlue); return color_24bit(result_R, result_G, result_B);
} }
/** /**
@@ -128,19 +128,19 @@ void LEDMatrix::set_min_indicator(uint8_t pattern, uint32_t color)
// 0 -> 0000 // 0 -> 0000
if (pattern & 1) if (pattern & 1)
{ {
_target_indicators[0] = color; _target_minute_indicators[0] = color;
} }
if (pattern >> 1 & 1) if (pattern >> 1 & 1)
{ {
_target_indicators[1] = color; _target_minute_indicators[1] = color;
} }
if (pattern >> 2 & 1) if (pattern >> 2 & 1)
{ {
_target_indicators[2] = color; _target_minute_indicators[2] = color;
} }
if (pattern >> 3 & 1) if (pattern >> 3 & 1)
{ {
_target_indicators[3] = color; _target_minute_indicators[3] = color;
} }
} }
@@ -158,10 +158,6 @@ void LEDMatrix::grid_add_pixel(uint8_t x, uint8_t y, uint32_t color)
{ {
_target_grid[y][x] = color; _target_grid[y][x] = color;
} }
else
{
// logger->log_string("Index out of Range: " + String(x) + ", " + String(y));
}
} }
/** /**
@@ -179,10 +175,10 @@ void LEDMatrix::flush(void)
} }
} }
// set every minutes indicator led to 0 // set every minutes indicator led to 0
_target_indicators[0] = 0; _target_minute_indicators[0] = 0;
_target_indicators[1] = 0; _target_minute_indicators[1] = 0;
_target_indicators[2] = 0; _target_minute_indicators[2] = 0;
_target_indicators[3] = 0; _target_minute_indicators[3] = 0;
} }
/** /**
@@ -215,31 +211,31 @@ void LEDMatrix::_draw_on_matrix(float factor)
uint32_t filtered_color = 0; uint32_t filtered_color = 0;
// loop over all leds in matrix // loop over all leds in matrix
for (int s = 0; s < MATRIX_WIDTH; s++) for (uint8_t col = 0; col < MATRIX_WIDTH; col++)
{ {
for (int z = 0; z < MATRIX_HEIGHT; z++) for (uint8_t row = 0; row < MATRIX_HEIGHT; row++)
{ {
// inplement momentum as smooth transistion function // implement momentum as smooth transistion function
uint32_t filtered_color = interpolate_color_24bit(_current_grid[z][s], _target_grid[z][s], factor); filtered_color = interpolate_color_24bit(_current_grid[row][col], _target_grid[row][col], factor);
_neomatrix->drawPixel(s, z, color_24_to_16bit(filtered_color)); _neomatrix->drawPixel(col, row, color_24_to_16bit(filtered_color));
_current_grid[z][s] = filtered_color; _current_grid[row][col] = filtered_color;
total_current += _calc_estimated_led_current(filtered_color); total_current += _calc_estimated_led_current(filtered_color);
} }
} }
// loop over all minute indicator leds // loop over all minute indicator leds
for (int i = 0; i < 4; i++) for (uint8_t i = 0; i < 4; i++)
{ {
filtered_color = interpolate_color_24bit(_current_indicators[i], _target_indicators[i], factor); filtered_color = interpolate_color_24bit(_current_minute_indicators[i], _target_minute_indicators[i], factor);
_neomatrix->drawPixel(MATRIX_WIDTH - (1 + i), MATRIX_HEIGHT, color_24_to_16bit(filtered_color)); _neomatrix->drawPixel(MATRIX_WIDTH - (1 + i), MATRIX_HEIGHT, color_24_to_16bit(filtered_color));
_current_indicators[i] = filtered_color; _current_minute_indicators[i] = filtered_color;
total_current += _calc_estimated_led_current(filtered_color); total_current += _calc_estimated_led_current(filtered_color);
} }
// Check if totalCurrent reaches CURRENTLIMIT -> if yes reduce brightness // Check if totalCurrent reaches _current_limit -> if yes reduce brightness
if (total_current > _current_limit) if (total_current > _current_limit)
{ {
uint8_t new_brightness = _brightness * float(_current_limit) / float(total_current); uint8_t new_brightness = (uint8)(_brightness * (float(_current_limit) / float(total_current)));
_neomatrix->setBrightness(new_brightness); _neomatrix->setBrightness(new_brightness);
} }
_neomatrix->show(); _neomatrix->show();
@@ -319,9 +315,9 @@ void LEDMatrix::set_brightness(uint8_t brightness)
uint16_t LEDMatrix::_calc_estimated_led_current(uint32_t color) uint16_t LEDMatrix::_calc_estimated_led_current(uint32_t color)
{ {
// extract rgb values // extract rgb values
uint8_t red = color >> 16 & 0xff; uint8_t red = color >> 16 & UINT8_MAX;
uint8_t green = color >> 8 & 0xff; uint8_t green = color >> 8 & UINT8_MAX;
uint8_t blue = color & 0xff; uint8_t blue = color & UINT8_MAX;
// Linear estimation: 20mA for full brightness per LED // Linear estimation: 20mA for full brightness per LED
// (calculation avoids float numbers) // (calculation avoids float numbers)

View File

@@ -16,7 +16,6 @@ const String clock_chars_as_string = "ESRISTNFUNFVIERTELZEHNZWANZIGHVORPIKACHUNA
void draw_minute_indicator(uint8_t minutes, uint32_t color) void draw_minute_indicator(uint8_t minutes, uint32_t color)
{ {
// separate LEDs for minutes in an additional row // separate LEDs for minutes in an additional row
{
switch (minutes % 5) switch (minutes % 5)
{ {
case 1: case 1:
@@ -48,7 +47,6 @@ void draw_minute_indicator(uint8_t minutes, uint32_t color)
break; break;
} }
} }
}
} }
/** /**

View File

@@ -49,20 +49,22 @@
// DEBUG // DEBUG
uint32_t dbg_counter = 0; // TODO RM uint32_t dbg_counter = 0; // TODO RM
const String state_names[] = {"Clock", "DiClock", "Spiral", "Tetris", "Snake", "PingPong"}; const String state_names[] = {"Clock", "DiClock", "Spiral", "Tetris", "Snake", "PingPong", "Hearts"};
// PERIODS for each state (different for stateAutoChange or Manual mode) // PERIODS for each state (different for stateAutoChange or Manual mode)
const uint16_t PERIODS[2][NUM_STATES] = {{PERIOD_TIME_VISU_UPDATE, // stateAutoChange = 0 const uint16_t PERIODS[2][NUM_STATES] = {{PERIOD_TIME_VISU_UPDATE, // stateAutoChange = 0
PERIOD_TIME_VISU_UPDATE, PERIOD_TIME_VISU_UPDATE,
PERIOD_ANIMATION, PERIOD_ANIMATION,
PERIOD_TETRIS, PERIOD_TETRIS,
PERIOD_SNAKE, PERIOD_SNAKE,
PERIOD_PONG}, PERIOD_PONG,
PERIOD_ANIMATION},
{PERIOD_TIME_VISU_UPDATE, // stateAutoChange = 1 {PERIOD_TIME_VISU_UPDATE, // stateAutoChange = 1
PERIOD_TIME_VISU_UPDATE, PERIOD_TIME_VISU_UPDATE,
PERIOD_ANIMATION, PERIOD_ANIMATION,
PERIOD_ANIMATION, PERIOD_ANIMATION,
PERIOD_ANIMATION, PERIOD_ANIMATION,
PERIOD_PONG}}; PERIOD_PONG,
PERIOD_ANIMATION}};
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
// GLOBAL VARIABLES // GLOBAL VARIABLES
@@ -85,6 +87,7 @@ UDPLogger logger;
// Statics // Statics
static bool spiral_direction = false; static bool spiral_direction = false;
static unsigned long last_led_direct = 0; // time of last direct LED command (=> fall back to normal mode after timeout)
static WiFiUDP wifi_udp; static WiFiUDP wifi_udp;
static NTPClientPlus ntp_client = NTPClientPlus(wifi_udp, NTP_SERVER_URL, 1, true); static NTPClientPlus ntp_client = NTPClientPlus(wifi_udp, NTP_SERVER_URL, 1, true);
@@ -92,16 +95,6 @@ static Pong pong = Pong(&led_matrix, &logger);
static Snake snake = Snake(&led_matrix, &logger); static Snake snake = Snake(&led_matrix, &logger);
static Tetris tetris = Tetris(&led_matrix, &logger); static Tetris tetris = Tetris(&led_matrix, &logger);
// Timestamp variables
static unsigned long button_press_start = 0; // time of push button press start
static unsigned long last_led_direct = 0; // time of last direct LED command (=> fall back to normal mode after timeout)
static unsigned long last_animation_step = millis(); // time of last Matrix update
static unsigned long last_heartbeat = millis(); // time of last heartbeat sending
static unsigned long last_nightmode_check = millis(); // time of last nightmode check
static unsigned long last_ntp_update = millis() - PERIOD_NTP_UPDATE - 5000; // time of last NTP update
static unsigned long last_state_change = millis(); // time of last state change
static unsigned long last_step = millis(); // time of last animation step
static bool night_mode = false; // stores state of nightmode static bool night_mode = false; // stores state of nightmode
static bool state_auto_change = false; // stores state of automatic state change static bool state_auto_change = false; // stores state of automatic state change
static float filter_factor = DEFAULT_SMOOTHING_FACTOR; // stores smoothing factor for led transition static float filter_factor = DEFAULT_SMOOTHING_FACTOR; // stores smoothing factor for led transition
@@ -120,7 +113,6 @@ NightModeTimes_st night_mode_times = {
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
// SETUP // SETUP
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
void setup() void setup()
{ {
// put your setup code here, to run once: // put your setup code here, to run once:
@@ -196,12 +188,12 @@ void setup()
if (resetInfo->reason != REASON_SOFT_RESTART) if (resetInfo->reason != REASON_SOFT_RESTART)
{ {
// test quickly each LED // test quickly each LED
for (int r = 0; r < MATRIX_HEIGHT; r++) for (int16_t row = 0; row < MATRIX_HEIGHT; row++)
{ {
for (int c = 0; c < MATRIX_WIDTH; c++) for (int16_t col = 0; col < MATRIX_WIDTH; col++)
{ {
matrix.fillScreen(0); matrix.fillScreen(0);
matrix.drawPixel(c, r, LEDMatrix::color_24_to_16bit(colors_24bit[2])); matrix.drawPixel(col, row, LEDMatrix::color_24_to_16bit(colors_24bit[2]));
matrix.show(); matrix.show();
delay(10); delay(10);
} }
@@ -270,6 +262,7 @@ void setup()
{ {
night_mode_times.nightmode_end_min = NIGHTMODE_END_MIN; night_mode_times.nightmode_end_min = NIGHTMODE_END_MIN;
} }
logger.log_string("Nightmode starts at: " + String(night_mode_times.nightmode_start_hour) + ":" + String(night_mode_times.nightmode_start_min)); logger.log_string("Nightmode starts at: " + String(night_mode_times.nightmode_start_hour) + ":" + String(night_mode_times.nightmode_start_min));
logger.log_string("Nightmode ends at: " + String(night_mode_times.nightmode_end_hour) + ":" + String(night_mode_times.nightmode_end_min)); logger.log_string("Nightmode ends at: " + String(night_mode_times.nightmode_end_hour) + ":" + String(night_mode_times.nightmode_end_min));
@@ -286,35 +279,79 @@ void setup()
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
// LOOP // LOOP
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
void loop() void loop()
{ {
unsigned long current_time_ms = CURRENT_TIME_MS;
// Timestamp variables
static unsigned long last_animation_step = 0; // time of last animation step
static unsigned long last_matrix_update = 0; // time of last Matrix update
static unsigned long last_heartbeat = 0; // time of last heartbeat sending
static unsigned long last_nightmode_check = 0; // time of last nightmode check
static unsigned long last_ntp_update = 0; // time of last NTP update
static unsigned long last_state_change = 0; // time of last state change
handleOTA(); // handle OTA handleOTA(); // handle OTA
logger.log_string("After handleOTA"); yield();
webserver.handleClient(); // handle webserver webserver.handleClient(); // handle webserver
logger.log_string("After handleClient"); yield();
// send regularly heartbeat messages via UDP multicast
if ((current_time_ms - last_heartbeat) > PERIOD_HEARTBEAT)
{
Serial.printf("a");
Serial.println();
send_heartbeat(); // send heartbeat update send_heartbeat(); // send heartbeat update
logger.log_string("After send_heartbeat"); last_heartbeat = CURRENT_TIME_MS;
yield();
Serial.printf("A");
}
handle_current_state(); // handle current state - main process if (!night_mode && ((current_time_ms - last_animation_step) > PERIODS[state_auto_change][current_state]) && ((current_time_ms - last_led_direct) > TIMEOUT_LEDDIRECT))
logger.log_string("After handle_current_state"); {
Serial.printf("b");
handle_current_state(); // handle current state
last_animation_step = CURRENT_TIME_MS;
yield();
Serial.printf("B");
}
if ((current_time_ms - last_matrix_update) > PERIOD_MATRIX_UPDATE)
{
Serial.printf("c");
update_matrix(); // update matrix update_matrix(); // update matrix
logger.log_string("After update_matrix"); last_matrix_update = CURRENT_TIME_MS;
yield();
Serial.printf("C");
}
handle_button(); // handle button press handle_button(); // handle button press
logger.log_string("After handle_button");
if (!night_mode && state_auto_change && (current_time_ms - last_state_change > PERIOD_STATE_CHANGE))
{
Serial.printf("d");
update_state_machine(); // handle state changes update_state_machine(); // handle state changes
logger.log_string("After update_state_machine"); last_state_change = CURRENT_TIME_MS;
yield();
Serial.printf("D");
}
ntp_time_update(); // ntp time update if ((current_time_ms - last_ntp_update) > PERIOD_NTP_UPDATE)
logger.log_string("After ntp_time_update"); {
Serial.printf("e");
ntp_time_update(&last_ntp_update); // ntp time update
yield();
Serial.printf("E");
}
if ((current_time_ms - last_nightmode_check) > PERIOD_NIGHTMODE_CHECK)
{
Serial.printf("f");
check_night_mode(); // check night mode check_night_mode(); // check night mode
logger.log_string("After check_night_mode"); last_nightmode_check = CURRENT_TIME_MS;
Serial.printf("F");
}
} }
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
@@ -323,24 +360,12 @@ void loop()
void update_state_machine() void update_state_machine()
{ {
unsigned long current_time_ms = millis();
if (state_auto_change && (current_time_ms - last_state_change > PERIOD_STATE_CHANGE) && !night_mode)
{
// increment state variable and trigger state change // increment state variable and trigger state change
state_change((current_state + 1) % NUM_STATES); state_change((current_state + 1) % (uint8_t)NUM_STATES);
// save last automatic state change
last_state_change = current_time_ms;
}
} }
void handle_current_state() void handle_current_state()
{ {
unsigned long current_time_ms = millis();
// handle mode behaviours (trigger loopCycles of different modes depending on current mode)
if (!night_mode && ((current_time_ms - last_step) > PERIODS[state_auto_change][current_state]) && ((current_time_ms - last_led_direct) > TIMEOUT_LEDDIRECT))
{
switch (current_state) switch (current_state)
{ {
case ST_CLOCK: // state clock case ST_CLOCK: // state clock
@@ -412,13 +437,16 @@ void handle_current_state()
pong.loopCycle(); pong.loopCycle();
break; break;
} }
case ST_HEARTS:
{
draw_heart_animation();
break;
}
default: default:
{ {
break; break;
} }
} }
last_step = millis();
}
} }
/** /**
@@ -428,14 +456,8 @@ void handle_current_state()
*/ */
void update_matrix() void update_matrix()
{ {
unsigned long current_time_ms = millis();
// periodically write colors to matrix // periodically write colors to matrix
if ((current_time_ms - last_animation_step) > PERIOD_MATRIX_UPDATE)
{
led_matrix.draw_on_matrix_smooth(filter_factor); led_matrix.draw_on_matrix_smooth(filter_factor);
last_animation_step = current_time_ms;
}
} }
/** /**
@@ -445,17 +467,10 @@ void update_matrix()
*/ */
void send_heartbeat() void send_heartbeat()
{ {
unsigned long current_time_ms = millis(); logger.log_string("Heartbeat, state: " + state_names[current_state] + ", FreeHeap: " + ESP.getFreeHeap() +
", HeapFrag: " + ESP.getHeapFragmentation() + ", MaxFreeBlock: " + ESP.getMaxFreeBlockSize() + "\nCounter: " +
// send regularly heartbeat messages via UDP multicast
if ((current_time_ms - last_heartbeat) > PERIOD_HEARTBEAT)
{
logger.log_string("Heartbeat, state: " + state_names[current_state] + ", FreeHeap: " + ESP.getFreeHeap() + \
", HeapFrag: " + ESP.getHeapFragmentation() + ", MaxFreeBlock: " + ESP.getMaxFreeBlockSize() + "\nCounter: " + \
dbg_counter + " , Hours: " + (float)(dbg_counter) / 3600.0 + "\n"); // TODO CHANGE dbg_counter + " , Hours: " + (float)(dbg_counter) / 3600.0 + "\n"); // TODO CHANGE
last_heartbeat = current_time_ms; // Check wifi status
// Check wifi status (only if no apmode)
if (WiFi.status() != WL_CONNECTED) if (WiFi.status() != WL_CONNECTED)
{ {
Serial.println("WiFi connection lost!"); Serial.println("WiFi connection lost!");
@@ -463,7 +478,6 @@ void send_heartbeat()
led_matrix.draw_on_matrix_instant(); led_matrix.draw_on_matrix_instant();
} }
dbg_counter++; // TODO RM dbg_counter++; // TODO RM
}
} }
/** /**
@@ -473,11 +487,7 @@ void send_heartbeat()
*/ */
void check_night_mode() void check_night_mode()
{ {
unsigned long current_time_ms = millis();
// check if nightmode need to be activated // check if nightmode need to be activated
if ((current_time_ms - last_nightmode_check) > PERIOD_NIGHTMODE_CHECK)
{
int hours = ntp_client.getHours24(); int hours = ntp_client.getHours24();
int minutes = ntp_client.getMinutes(); int minutes = ntp_client.getMinutes();
@@ -489,8 +499,6 @@ void check_night_mode()
{ {
set_night_mode(false); set_night_mode(false);
} }
last_nightmode_check = current_time_ms;
}
} }
/** /**
@@ -498,14 +506,11 @@ void check_night_mode()
* *
* @param None * @param None
*/ */
void ntp_time_update() void ntp_time_update(unsigned long *last_ntp_update)
{ {
unsigned long current_time_ms = millis();
// NTP time update // NTP time update
if ((current_time_ms - last_ntp_update) > PERIOD_NTP_UPDATE)
{
int ntp_retval = ntp_client.updateNTP(); int ntp_retval = ntp_client.updateNTP();
switch (ntp_retval) switch (ntp_retval)
{ {
case NTP_UPDATE_SUCCESS: case NTP_UPDATE_SUCCESS:
@@ -516,14 +521,14 @@ void ntp_time_update()
logger.log_string("Date: " + ntp_client.getFormattedDate()); logger.log_string("Date: " + ntp_client.getFormattedDate());
logger.log_string("TimeOffset (seconds): " + String(ntp_client.getTimeOffset())); logger.log_string("TimeOffset (seconds): " + String(ntp_client.getTimeOffset()));
logger.log_string("Summertime: " + String(ntp_client.updateSWChange())); logger.log_string("Summertime: " + String(ntp_client.updateSWChange()));
last_ntp_update = millis(); *last_ntp_update = CURRENT_TIME_MS;
watchdog_counter = 30; watchdog_counter = 30;
break; break;
} }
case NTP_UPDATE_TIMEOUT: case NTP_UPDATE_TIMEOUT:
{ {
logger.log_string("NTP-Update not successful. Reason: Timeout"); logger.log_string("NTP-Update not successful. Reason: Timeout");
last_ntp_update += 10000; *last_ntp_update += 10000;
watchdog_counter--; watchdog_counter--;
break; break;
} }
@@ -534,7 +539,7 @@ void ntp_time_update()
logger.log_string("Date: " + ntp_client.getFormattedDate()); logger.log_string("Date: " + ntp_client.getFormattedDate());
logger.log_string("TimeOffset (seconds): " + String(ntp_client.getTimeOffset())); logger.log_string("TimeOffset (seconds): " + String(ntp_client.getTimeOffset()));
logger.log_string("Summertime: " + String(ntp_client.updateSWChange())); logger.log_string("Summertime: " + String(ntp_client.updateSWChange()));
last_ntp_update += 10000; *last_ntp_update += 10000;
watchdog_counter--; watchdog_counter--;
break; break;
} }
@@ -542,7 +547,7 @@ void ntp_time_update()
default: default:
{ {
logger.log_string("NTP-Update not successful. Reason: NTP time not valid (<1970)"); logger.log_string("NTP-Update not successful. Reason: NTP time not valid (<1970)");
last_ntp_update += 10000; *last_ntp_update += 10000;
watchdog_counter--; watchdog_counter--;
break; break;
} }
@@ -555,7 +560,6 @@ void ntp_time_update()
delay(100); delay(100);
ESP.restart(); ESP.restart();
} }
}
} }
/** /**
@@ -631,10 +635,9 @@ void state_change(uint8_t newState)
{ {
set_night_mode(false); // deactivate Nightmode set_night_mode(false); // deactivate Nightmode
} }
// first clear matrix
led_matrix.flush(); led_matrix.flush(); // first clear matrix
// set new state current_state = newState; // set new state
current_state = newState;
on_state_entry(current_state); on_state_entry(current_state);
logger.log_string("State change to: " + state_names[current_state]); logger.log_string("State change to: " + state_names[current_state]);
delay(5); delay(5);
@@ -680,7 +683,7 @@ void handle_led_direct()
} }
led_matrix.draw_on_matrix_instant(); led_matrix.draw_on_matrix_instant();
last_led_direct = millis(); last_led_direct = CURRENT_TIME_MS;
} }
webserver.send(200, "text/plain", message); webserver.send(200, "text/plain", message);
} }
@@ -692,28 +695,28 @@ void handle_led_direct()
*/ */
void handle_button() void handle_button()
{ {
static bool lastButtonState = false; bool button_pressed = !digitalRead(BUTTON_PIN);
bool buttonPressed = !digitalRead(BUTTON_PIN); static bool last_button_state = false;
static unsigned long button_press_start = 0; // time of push button press start
// check rising edge // check rising edge
if (buttonPressed == true && lastButtonState == false) if (button_pressed == true && last_button_state == false)
{ {
// button press start // button press start
logger.log_string("Button press started"); logger.log_string("Button press started");
button_press_start = millis(); button_press_start = CURRENT_TIME_MS;
} }
// check falling edge // check falling edge
if (buttonPressed == false && lastButtonState == true) if (button_pressed == false && last_button_state == true)
{ {
// button press ended // button press ended
if ((millis() - button_press_start) > LONG_PRESS_MS) if ((CURRENT_TIME_MS - button_press_start) > LONG_PRESS_MS)
{ {
// longpress -> nightmode // longpress -> nightmode
logger.log_string("Button press ended - long press"); logger.log_string("Button press ended - long press");
set_night_mode(true); set_night_mode(true);
} }
else if ((millis() - button_press_start) > SHORT_PRESS_MS) else if ((CURRENT_TIME_MS - button_press_start) > SHORT_PRESS_MS)
{ {
// shortpress -> state change // shortpress -> state change
logger.log_string("Button press ended - short press"); logger.log_string("Button press ended - short press");
@@ -724,11 +727,11 @@ void handle_button()
} }
else else
{ {
state_change((current_state + 1) % NUM_STATES); state_change((current_state + 1) % (uint8_t)NUM_STATES);
} }
} }
} }
lastButtonState = buttonPressed; last_button_state = button_pressed;
} }
/** /**
@@ -755,7 +758,8 @@ void load_main_color()
uint8_t red = EEPROM.read(ADR_MC_RED); uint8_t red = EEPROM.read(ADR_MC_RED);
uint8_t green = EEPROM.read(ADR_MC_GREEN); uint8_t green = EEPROM.read(ADR_MC_GREEN);
uint8_t blue = EEPROM.read(ADR_MC_BLUE); uint8_t blue = EEPROM.read(ADR_MC_BLUE);
if (int(red) + int(green) + int(blue) < 50)
if ((int(red) + int(green) + int(blue)) < 50)
{ {
main_color_clock = colors_24bit[2]; main_color_clock = colors_24bit[2];
} }
@@ -821,6 +825,10 @@ void handle_command()
{ {
state_change(ST_PINGPONG); state_change(ST_PINGPONG);
} }
else if (mode_str.equals("hearts"))
{
state_change(ST_HEARTS);
}
} }
else if (webserver.argName(0).equals("nightmode")) else if (webserver.argName(0).equals("nightmode"))
{ {
@@ -946,6 +954,7 @@ void handle_command()
pong.initGame(1); pong.initGame(1);
} }
} }
webserver.send(204, "text/plain", "No Content"); // this page doesn't send back content --> 204 webserver.send(204, "text/plain", "No Content"); // this page doesn't send back content --> 204
} }