7 Commits
main ... 时钟

Author SHA1 Message Date
unlockable
ee1ee0540e Add alphabetical letters. 2023-09-06 13:03:38 +08:00
unlockable
215cd94bfc 显示字母 2023-08-25 17:31:07 +08:00
unlockable
bb6e024d65 计时器。 2023-08-25 17:23:50 +08:00
unlockable
93aba929ad 显示数字。 2023-08-25 14:47:28 +08:00
unlockable
3ba8d7606a 数字字体。 2023-08-25 14:22:00 +08:00
unlockable
cfaf8cd59d Merge branch 'main' into 时钟 2023-08-24 18:29:22 +08:00
unlockable
0aa14d2a39 数字时钟字体测试。 2023-08-24 17:53:14 +08:00

View File

@@ -1,10 +1,43 @@
#include "TimerOne.h"
#define TIME_PER_LAYER_IN_US 700
#define TIME_PER_LAYER_IN_US 800
#define BUS_START_PIN 22
#define CLOCK_START_PIN 30
#define SW_START_PIN 38
const uint16_t numbers[10] = {
0xF6F, 0x592, 0xE57, 0xE8F, 0x979, 0xF8F, 0xF3F, 0xE54, 0xFEF, 0xFCF,
};
const uint64_t letters[26]{
0x3C66667E666666, // A
0x7C66667C66667C, // B
0x3C66606060663C, // C
0x7C66666666667C, // D
0x7E60607C60607E, // E
0x7E60607C606060, // F
0x3C6660606E663C, // G
0x6666667E666666, // H
0x3C18181818183C, // I
0x1E0C0C0C6C6C38, // J
0x666C7870786C66, // K
0x6060606060607E, // L
0x63777F6B636363, // M
0x63737B6F676363, // N
0x3C66666666663C, // O
0x7C6666667C6060, // P
0x3C6666666E3C06, // Q
0x7C66667C786C66, // R
0x3C66603C06663C, // S
0x7E5A1818181818, // T
0x6666666666663C, // U
0x66666666663C18, // V
0x6363636B7F7763, // W
0x6363361C366363, // X
0x6666663C181818, // Y
0x7E060C1830607E, // Z
};
class Cube {
private:
static int layer_count;
@@ -28,7 +61,9 @@ public:
// In LED_status:
// 0 = off
// 4 = brightest
digitalWrite(BUS_START_PIN + j, ((LED_status[layer_count][i] >> (j * 2)) & 3) >= (3 - brightness_count));
digitalWrite(BUS_START_PIN + j,
((LED_status[layer_count][i] >> (j * 2)) & 3) >=
(3 - brightness_count));
}
digitalWrite(CLOCK_START_PIN + i, HIGH);
digitalWrite(CLOCK_START_PIN + i, LOW);
@@ -42,14 +77,148 @@ public:
return;
}
brightness %= 4;
LED_status[z][x] = (LED_status[z][x] & (~(3 << (y * 2)))) | (brightness << (y * 2));
LED_status[z][x] =
(LED_status[z][x] & (~(3 << (y * 2)))) | (brightness << (y * 2));
}
static int get_status(int x, int y, int z) {
return LED_status[z][x] >> (y * 2) & 3;
}
static void clear() {
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
LED_status[i][j] = 0;
}
}
}
static void draw_num(int x, int y, int z, int num, int direction,
int brightness) {
// 0 = look along x
// 1 = look reverse x
// 2 = look along y
// 3 = look reverse y
if (num > 9 || num < 0) {
return;
}
switch (direction) {
case 0: {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
if ((numbers[num] >> (11 - (i + j * 3))) & 1) {
Cube::set_status(x, y - i, z - j, brightness);
} else {
Cube::set_status(x, y - i, z - j, 0);
}
}
}
break;
}
case 1: {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
if ((numbers[num] >> (11 - (i + j * 3))) & 1) {
Cube::set_status(x, y + i, z - j, brightness);
} else {
Cube::set_status(x, y + i, z - j, 0);
}
}
}
break;
}
case 2: {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
if ((numbers[num] >> (11 - (i + j * 3))) & 1) {
Cube::set_status(x + i, y, z - j, brightness);
} else {
Cube::set_status(x + i, y, z - j, 0);
}
}
}
break;
}
case 3: {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
if ((numbers[num] >> (11 - (i + j * 3))) & 1) {
Cube::set_status(x - i, y, z - j, brightness);
} else {
Cube::set_status(x - i, y, z - j, 0);
}
}
}
break;
}
}
}
static void draw_letter(int x, int y, int z, int num, int direction, int brightness) {
// 0 = look along x
// 1 = look reverse x
// 2 = look along y
// 3 = look reverse y
if (num > 26 || num < 0) {
return;
}
switch (direction) {
case 0: {
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
if ((letters[num] >> (63 - (i + j * 8))) & 1) {
Cube::set_status(x, y - i, z - j, brightness);
} else {
Cube::set_status(x, y - i, z - j, 0);
}
}
}
break;
}
case 1: {
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
if ((letters[num] >> (63 - (i + j * 8))) & 1) {
Cube::set_status(x, y + i, z - j, brightness);
} else {
Cube::set_status(x, y + i, z - j, 0);
}
}
}
break;
}
case 2: {
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
if ((letters[num] >> (63 - (i + j * 8))) & 1) {
Cube::set_status(x + i, y, z - j, brightness);
} else {
Cube::set_status(x + i, y, z - j, 0);
}
}
}
break;
}
case 3: {
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
if ((letters[num] >> (63 - (i + j * 8))) & 1) {
Cube::set_status(x - i, y, z - j, brightness);
} else {
Cube::set_status(x - i, y, z - j, 0);
}
}
}
break;
}
}
}
};
int Cube::layer_count = 0;
int Cube::brightness_count = 0;
int Cube::LED_status[8][8] = {0};
int bright = 3;
int char_num = 0;
void setup() {
for (int i = 22; i < 46; i++) {
@@ -62,17 +231,32 @@ void setup() {
Serial.begin(115200);
cli();
TCCR4A = 0; // set entire TCCR1A register to 0
TCCR4B = 0; // same for TCCR1B
TCNT4 = 0; // initialize counter value to 0
// set compare match register for 1hz increments
OCR4A = 15624 / 1; // = (16*10^6) / (1*1024) - 1 (must be <65536)
// turn on CTC mode
TCCR4B |= (1 << WGM12);
// Set CS12 and CS10 bits for 1024 prescaler
TCCR4B |= (1 << CS12) | (1 << CS10);
// enable timer compare interrupt
TIMSK4 |= (1 << OCIE4A);
sei();
randomSeed(analogRead(0));
}
void loop() {
for (int i = 7; i >= 0; i--) {
for (int j = 0; j < 8; j++) {
for (int k = 0; k < 8; k++) {
Cube::set_status(i, j, k, bright);
delay(5);
}
}
}
bright = (bright + 1) % 4;
// Ref:
// https://raw.githubusercontent.com/wiki/olikraus/u8glib/fontpic/u8g_font_u8glib_4.png
// Serial.println(i);
Cube::draw_letter(7, 7, 7, char_num, 3, 3);
delay(1000);
}
ISR(TIMER4_COMPA_vect) {
char_num = (char_num + 1) % 26;
Serial.println(char_num);
}