Rework with new classes, debugging 24-hour timer
This commit is contained in:
parent
67008e8502
commit
e74850574c
|
@ -1,6 +1,6 @@
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2016 Dirtbags
|
Copyright © 2020 Neale Pickett
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -12,10 +12,10 @@ furnished to do so, subject to the following conditions:
|
||||||
The above copyright notice and this permission notice shall be included in all
|
The above copyright notice and this permission notice shall be included in all
|
||||||
copies or substantial portions of the Software.
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
The software is provided "as is", without warranty of any kind, express or
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
implied, including but not limited to the warranties of merchantability,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
fitness for a particular purpose and noninfringement. In no event shall the
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
authors or copyright holders be liable for any claim, damages or other
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
liability, whether in an action of contract, tort or otherwise, arising from,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
out of or in connection with the software or the use or other dealings in the
|
||||||
SOFTWARE.
|
software.
|
|
@ -0,0 +1,4 @@
|
||||||
|
FQBN = adafruit:samd:adafruit_trinket_m0
|
||||||
|
|
||||||
|
install: holiday-lights.ino
|
||||||
|
arduino --upload --board $(FQBN) $@
|
|
@ -0,0 +1,12 @@
|
||||||
|
TIME FOR SOME INFORMATION THEORY!
|
||||||
|
|
||||||
|
We need to pack morse code. The most efficient packing I can think of is a stream of base 3 ints:
|
||||||
|
0 = END, 1 = DIT, 2 = DAH
|
||||||
|
|
||||||
|
We have to encode into 8-bit bytes, so the smallest atomic (quick to index) encoded chunk is:
|
||||||
|
int('22222', 3) = 242
|
||||||
|
|
||||||
|
Given the last int must be 0, we can encode anything up to length 4.
|
||||||
|
But I need to encode the prosign ARK = .-.-.-.- length 8.
|
||||||
|
So I need two bytes.
|
||||||
|
Well, if I'm going to use two bytes, I may as well just encode a length and a bitmask.
|
|
@ -0,0 +1,7 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define DURATION_MILLISECOND 1L
|
||||||
|
#define DURATION_SECOND (1000 * DURATION_MILLISECOND)
|
||||||
|
#define DURATION_MINUTE (60 * DURATION_SECOND)
|
||||||
|
#define DURATION_HOUR (60 * DURATION_MINUTE)
|
||||||
|
#define DURATION_DAY (24 * DURATION_HOUR)
|
|
@ -4,7 +4,9 @@
|
||||||
|
|
||||||
#include <FastLED.h>
|
#include <FastLED.h>
|
||||||
#include "bounce2.h"
|
#include "bounce2.h"
|
||||||
|
#include "durations.h"
|
||||||
#include "morse.h"
|
#include "morse.h"
|
||||||
|
#include "pulse.h"
|
||||||
|
|
||||||
// Do you want it to run forever, or cycle every 24 hours?
|
// Do you want it to run forever, or cycle every 24 hours?
|
||||||
#ifdef TINY
|
#ifdef TINY
|
||||||
|
@ -14,8 +16,10 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Which pin your LED strip is connected to
|
// Which pin your LED strip is connected to
|
||||||
#ifdef TINY
|
#if defined(TINY)
|
||||||
#define NEOPIXEL_PIN 3
|
#define NEOPIXEL_PIN 3
|
||||||
|
#elif defined(ADAFRUIT_TRINKET_M0)
|
||||||
|
#define NEOPIXEL_PIN 2
|
||||||
#else
|
#else
|
||||||
#define NEOPIXEL_PIN 6
|
#define NEOPIXEL_PIN 6
|
||||||
#endif
|
#endif
|
||||||
|
@ -35,42 +39,40 @@
|
||||||
// How many milliseconds between activity in one group
|
// How many milliseconds between activity in one group
|
||||||
#define DELAY_MS 600
|
#define DELAY_MS 600
|
||||||
|
|
||||||
|
// Each group has this percentage chance of
|
||||||
|
#define GROUP_UPDATE_PROBABILITY 25
|
||||||
|
|
||||||
// What percentage chance a chosen light has of being on
|
// What percentage chance a chosen light has of being on
|
||||||
#define ACTIVITY 40
|
#define ACTIVITY 40
|
||||||
|
|
||||||
// Which pixel to flash messages in morse code: -1 = disable
|
// Which pixel to flash messages in morse code: -1 = disable
|
||||||
#define MORSE_PIXEL 8
|
#define MORSE_PIXEL 8
|
||||||
#define MORSE_COLOR 0x880000
|
#define MORSE_COLOR CRGB::Red
|
||||||
|
|
||||||
// How long a dit lasts
|
// How long a dit lasts
|
||||||
#define DIT_DURATION_MS 100
|
#define DIT_DURATION_MS 150
|
||||||
|
|
||||||
// Color for all-white mode
|
// Color for all-white mode
|
||||||
#define WHITE 0x886655
|
#define WHITE 0x886655
|
||||||
|
|
||||||
// Some units of time
|
|
||||||
#define MILLISECOND 1L
|
|
||||||
#define SECOND (1000 * MILLISECOND)
|
|
||||||
#define MINUTE (60 * SECOND)
|
|
||||||
#define HOUR (60 * MINUTE)
|
|
||||||
#define DAY (24 * HOUR)
|
|
||||||
|
|
||||||
// The Neopixel library masks interrupts while writing.
|
// The Neopixel library masks interrupts while writing.
|
||||||
// This means you lose time.
|
// This means you lose time.
|
||||||
// How much time do you lose?
|
// How much time do you lose?
|
||||||
// I'm guessing 10 minutes a day.
|
// I'm guessing 10 minutes a day.
|
||||||
|
|
||||||
#define SNOSSLOSS_DAY (DAY - (10 * MINUTE))
|
#define SNOSSLOSS_DAY (DURATION_DAY - (10 * DURATION_MINUTE))
|
||||||
#define ON_FOR (5 * HOUR)
|
#define ON_FOR (5 * DURATION_HOUR)
|
||||||
|
|
||||||
const char *messages[] = {
|
#define ARK "\x03\x04"
|
||||||
"seasons greetings",
|
const char *message = (
|
||||||
"happy holiday",
|
|
||||||
"merry xmas",
|
"seasons greetings" ARK
|
||||||
"happy new year",
|
"happy holiday" ARK
|
||||||
"CQ CQ OF9X",
|
"merry xmas" ARK
|
||||||
};
|
"happy new year" ARK
|
||||||
const int nmessages = sizeof(messages) / sizeof(*messages);
|
"CQ CQ OF9X" ARK
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
// These colors mirror pretty closely some cheapo LED lights we have
|
// These colors mirror pretty closely some cheapo LED lights we have
|
||||||
const uint32_t colors[] = {
|
const uint32_t colors[] = {
|
||||||
|
@ -100,80 +102,67 @@ void setup() {
|
||||||
pinMode(LED_BUILTIN, OUTPUT);
|
pinMode(LED_BUILTIN, OUTPUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool strandUpdate(bool white) {
|
Pulse mainPulse = Pulse(DELAY_MS);
|
||||||
static unsigned long nextEventMillis = 0;
|
|
||||||
unsigned long now = millis();
|
|
||||||
static int group = 0;
|
|
||||||
|
|
||||||
if (now < nextEventMillis) {
|
bool strandUpdate(bool white) {
|
||||||
|
if (!mainPulse.Ticked()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int pos = (group * LEDS_PER_GROUP) + random(LEDS_PER_GROUP);
|
for (int group = 0; group < NUM_GROUPS; ++group) {
|
||||||
if (random(100) < ACTIVITY) {
|
int pos = (group * LEDS_PER_GROUP) + random(LEDS_PER_GROUP);
|
||||||
uint32_t color;
|
if (random(100) < GROUP_UPDATE_PROBABILITY) {
|
||||||
|
if (random(100) < ACTIVITY) {
|
||||||
|
uint32_t color;
|
||||||
|
|
||||||
if (white) {
|
if (white) {
|
||||||
color = WHITE;
|
color = WHITE;
|
||||||
} else {
|
} else {
|
||||||
color = colors[random(ncolors)];
|
color = colors[random(ncolors)];
|
||||||
|
}
|
||||||
|
leds[pos] = color;
|
||||||
|
} else {
|
||||||
|
leds[pos] = 0;
|
||||||
|
}
|
||||||
|
group = (group + 1) % NUM_GROUPS;
|
||||||
}
|
}
|
||||||
leds[pos] = color;
|
|
||||||
} else {
|
|
||||||
leds[pos] = 0;
|
|
||||||
}
|
}
|
||||||
group = (group + 1) % NUM_GROUPS;
|
|
||||||
|
|
||||||
nextEventMillis = now + (DELAY_MS / NUM_GROUPS);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool morseUpdate() {
|
|
||||||
static MorseEncoder enc;
|
|
||||||
static unsigned long nextEventMillis = 0;
|
|
||||||
static bool ARK = true;
|
|
||||||
unsigned long now = millis();
|
|
||||||
bool ret = false;
|
|
||||||
|
|
||||||
if (now >= nextEventMillis) {
|
|
||||||
nextEventMillis = now + DIT_DURATION_MS;
|
|
||||||
if (!enc.Tick()) {
|
|
||||||
ARK = !ARK;
|
|
||||||
if (ARK) {
|
|
||||||
enc.SetText("ARK");
|
|
||||||
enc.Quiet(MORSE_PAUSE_WORD);
|
|
||||||
} else {
|
|
||||||
#ifdef TINY
|
|
||||||
// I have tried twenty different ways to make this work on the ATTINY,
|
|
||||||
// including a big switch statement. It always freezes the program.
|
|
||||||
// I give up. Maybe it's a compiler bug having to do with a modulo.
|
|
||||||
enc.SetText(messages[0]);
|
|
||||||
#else
|
|
||||||
enc.SetText(messages[now % nmessages]);
|
|
||||||
#endif
|
|
||||||
enc.Quiet(200);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ret = true;
|
|
||||||
}
|
|
||||||
leds[MORSE_PIXEL] = enc.Transmitting ? MORSE_COLOR : 0;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool black() {
|
bool black() {
|
||||||
static unsigned long nextEventMillis = 0;
|
if (!mainPulse.Ticked()) {
|
||||||
unsigned long now = millis();
|
|
||||||
|
|
||||||
if (now < nextEventMillis) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
FastLED.clear();
|
FastLED.clear();
|
||||||
|
|
||||||
nextEventMillis = now + (DELAY_MS / NUM_GROUPS); // Keep timing consistent
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool morseUpdate() {
|
||||||
|
static MorseEncoder enc;
|
||||||
|
static Pulse pulse = Pulse(DIT_DURATION_MS);
|
||||||
|
|
||||||
|
leds[MORSE_PIXEL] = enc.Transmitting ? MORSE_COLOR : CRGB::Black;
|
||||||
|
if (pulse.Ticked()) {
|
||||||
|
if (!enc.Tick()) {
|
||||||
|
enc.SetText(message);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool millisUpdate() {
|
||||||
|
unsigned long now = millis();
|
||||||
|
for (int i = 0; i < sizeof(unsigned long) * 8; ++i) {
|
||||||
|
leds[i] = CHSV(0, 255, bitRead(now, i) ? 32 : 0);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
static bool white = false;
|
static bool white = false;
|
||||||
bool update = false;
|
bool update = false;
|
||||||
|
@ -188,6 +177,7 @@ void loop() {
|
||||||
update |= morseUpdate();
|
update |= morseUpdate();
|
||||||
} else {
|
} else {
|
||||||
update |= black();
|
update |= black();
|
||||||
|
update |= millisUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (update) {
|
if (update) {
|
||||||
|
|
212
morse.cpp
212
morse.cpp
|
@ -1,42 +1,122 @@
|
||||||
#include "morse.h"
|
#include "morse.h"
|
||||||
|
|
||||||
// Each morse dit/dah is stored as a nybble
|
struct MorseSign {
|
||||||
|
// Length of this sign. If Length is 0, Bits is the duration of a pause.
|
||||||
#define dit 1
|
uint8_t Length;
|
||||||
#define dah 3
|
uint8_t Bits;
|
||||||
|
|
||||||
#define Pack(a, b, c, d) ((a << 0) | (b << 2) | (c << 4) | (d << 6))
|
|
||||||
#define Unpack(m, pos) ((m >> (pos * 2)) & 0b11)
|
|
||||||
|
|
||||||
const uint8_t MorseLetters[] = {
|
|
||||||
Pack(dit, dah, 0, 0), // A
|
|
||||||
Pack(dah, dit, dit, dit), // B
|
|
||||||
Pack(dah, dit, dah, dit), // C
|
|
||||||
Pack(dah, dit, dit, 0), // D
|
|
||||||
Pack(dit, 0, 0, 0), // E
|
|
||||||
Pack(dit, dit, dah, dit), // F
|
|
||||||
Pack(dah, dah, dit, 0), // G
|
|
||||||
Pack(dit, dit, dit, dit), // H
|
|
||||||
Pack(dit, dit, 0, 0), // I
|
|
||||||
Pack(dit, dah, dah, dah), // J
|
|
||||||
Pack(dah, dit, dah, 0), // K
|
|
||||||
Pack(dit, dah, dit, dit), // L
|
|
||||||
Pack(dah, dah, 0, 0), // M
|
|
||||||
Pack(dah, dit, 0, 0), // N
|
|
||||||
Pack(dah, dah, dah, 0), // O
|
|
||||||
Pack(dit, dah, dah, dit), // P
|
|
||||||
Pack(dah, dah, dit, dah), // Q
|
|
||||||
Pack(dit, dah, dit, 0), // R
|
|
||||||
Pack(dit, dit, dit, 0), // S
|
|
||||||
Pack(dah, 0, 0, 0), // T
|
|
||||||
Pack(dit, dit, dah, 0), // U
|
|
||||||
Pack(dit, dit, dit, dah), // V
|
|
||||||
Pack(dit, dah, dah, 0), // W
|
|
||||||
Pack(dah, dit, dit, dah), // X
|
|
||||||
Pack(dah, dit, dah, dah), // Y
|
|
||||||
Pack(dah, dah, dit, dit), // Z
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const struct MorseSign GetMorseSign(char c) {
|
||||||
|
switch (c) {
|
||||||
|
case 3: // ETX - End of Text
|
||||||
|
return (struct MorseSign){8, 0b01010101};
|
||||||
|
case 4: // EOT - End of Transmission
|
||||||
|
return (struct MorseSign){0, MORSE_PAUSE_TRANSMISSION};
|
||||||
|
case ' ':
|
||||||
|
return (struct MorseSign){0, MORSE_PAUSE_WORD};
|
||||||
|
case '0':
|
||||||
|
return (struct MorseSign){5, 0b11111};
|
||||||
|
case '1':
|
||||||
|
return (struct MorseSign){5, 0b01111};
|
||||||
|
case '2':
|
||||||
|
return (struct MorseSign){5, 0b00111};
|
||||||
|
case '3':
|
||||||
|
return (struct MorseSign){5, 0b00011};
|
||||||
|
case '4':
|
||||||
|
return (struct MorseSign){5, 0b00001};
|
||||||
|
case 5:
|
||||||
|
return (struct MorseSign){5, 0b00000};
|
||||||
|
case 6:
|
||||||
|
return (struct MorseSign){5, 0b10000};
|
||||||
|
case 7:
|
||||||
|
return (struct MorseSign){5, 0b11000};
|
||||||
|
case 8:
|
||||||
|
return (struct MorseSign){5, 0b11100};
|
||||||
|
case 9:
|
||||||
|
return (struct MorseSign){5, 0b11110};
|
||||||
|
case 'a':
|
||||||
|
case 'A':
|
||||||
|
return (struct MorseSign){2, 0b01};
|
||||||
|
case 'b':
|
||||||
|
case 'B':
|
||||||
|
return (struct MorseSign){4, 0b1000};
|
||||||
|
case 'c':
|
||||||
|
case 'C':
|
||||||
|
return (struct MorseSign){4, 0b1010};
|
||||||
|
case 'd':
|
||||||
|
case 'D':
|
||||||
|
return (struct MorseSign){3, 0b100};
|
||||||
|
case 'e':
|
||||||
|
case 'E':
|
||||||
|
return (struct MorseSign){1, 0b0};
|
||||||
|
case 'f':
|
||||||
|
case 'F':
|
||||||
|
return (struct MorseSign){4, 0b0010};
|
||||||
|
case 'g':
|
||||||
|
case 'G':
|
||||||
|
return (struct MorseSign){3, 0b110};
|
||||||
|
case 'h':
|
||||||
|
case 'H':
|
||||||
|
return (struct MorseSign){4, 0b0000};
|
||||||
|
case 'i':
|
||||||
|
case 'I':
|
||||||
|
return (struct MorseSign){2, 0b00};
|
||||||
|
case 'j':
|
||||||
|
case 'J':
|
||||||
|
return (struct MorseSign){4, 0b0111};
|
||||||
|
case 'k':
|
||||||
|
case 'K':
|
||||||
|
return (struct MorseSign){3, 0b101};
|
||||||
|
case 'l':
|
||||||
|
case 'L':
|
||||||
|
return (struct MorseSign){4, 0b0100};
|
||||||
|
case 'm':
|
||||||
|
case 'M':
|
||||||
|
return (struct MorseSign){2, 0b11};
|
||||||
|
case 'n':
|
||||||
|
case 'N':
|
||||||
|
return (struct MorseSign){2, 0b10};
|
||||||
|
case 'o':
|
||||||
|
case 'O':
|
||||||
|
return (struct MorseSign){3, 0b111};
|
||||||
|
case 'p':
|
||||||
|
case 'P':
|
||||||
|
return (struct MorseSign){4, 0b0110};
|
||||||
|
case 'q':
|
||||||
|
case 'Q':
|
||||||
|
return (struct MorseSign){4, 0b1101};
|
||||||
|
case 'r':
|
||||||
|
case 'R':
|
||||||
|
return (struct MorseSign){3, 0b010};
|
||||||
|
case 's':
|
||||||
|
case 'S':
|
||||||
|
return (struct MorseSign){3, 0b000};
|
||||||
|
case 't':
|
||||||
|
case 'T':
|
||||||
|
return (struct MorseSign){1, 0b1};
|
||||||
|
case 'u':
|
||||||
|
case 'U':
|
||||||
|
return (struct MorseSign){3, 0b001};
|
||||||
|
case 'v':
|
||||||
|
case 'V':
|
||||||
|
return (struct MorseSign){4, 0b0001};
|
||||||
|
case 'w':
|
||||||
|
case 'W':
|
||||||
|
return (struct MorseSign){3, 0b011};
|
||||||
|
case 'x':
|
||||||
|
case 'X':
|
||||||
|
return (struct MorseSign){4, 0b1001};
|
||||||
|
case 'y':
|
||||||
|
case 'Y':
|
||||||
|
return (struct MorseSign){4, 0b1011};
|
||||||
|
case 'z':
|
||||||
|
case 'Z':
|
||||||
|
return (struct MorseSign){4, 0b1100};
|
||||||
|
default:
|
||||||
|
return (struct MorseSign){0, 0};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MorseEncoder::MorseEncoder() {
|
MorseEncoder::MorseEncoder() {
|
||||||
SetText("");
|
SetText("");
|
||||||
}
|
}
|
||||||
|
@ -46,7 +126,7 @@ MorseEncoder::MorseEncoder(const char *s) {
|
||||||
|
|
||||||
void MorseEncoder::SetText(const char *s) {
|
void MorseEncoder::SetText(const char *s) {
|
||||||
p = s;
|
p = s;
|
||||||
crumb = 0;
|
bit = 0;
|
||||||
ticksLeft = 0;
|
ticksLeft = 0;
|
||||||
Transmitting = false;
|
Transmitting = false;
|
||||||
}
|
}
|
||||||
|
@ -75,45 +155,29 @@ bool MorseEncoder::Tick() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If that was the end of the letter, we have to pause more
|
const struct MorseSign sign = GetMorseSign(*p);
|
||||||
if (crumb == 4) {
|
if (sign.Length == 0) {
|
||||||
crumb = 0;
|
// Pause
|
||||||
++p;
|
|
||||||
ticksLeft = MORSE_PAUSE_LETTER - MORSE_DIT;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (*p) {
|
|
||||||
case '\0':
|
|
||||||
return false;
|
|
||||||
case 'a' ... 'z':
|
|
||||||
Transmitting = true;
|
|
||||||
ticksLeft = Unpack(MorseLetters[*p - 'a'], crumb++);
|
|
||||||
break;
|
|
||||||
case 'A' ... 'Z':
|
|
||||||
Transmitting = true;
|
|
||||||
ticksLeft = Unpack(MorseLetters[*p - 'A'], crumb++);
|
|
||||||
break;
|
|
||||||
case ' ':
|
|
||||||
crumb = 0;
|
|
||||||
++p;
|
|
||||||
Transmitting = false;
|
|
||||||
ticksLeft = MORSE_PAUSE_WORD - MORSE_DIT;
|
|
||||||
break;
|
|
||||||
default: // this should never happen! Transmit for a word pause to indicate weirdness.
|
|
||||||
crumb = 0;
|
|
||||||
++p;
|
|
||||||
Transmitting = true;
|
|
||||||
ticksLeft = MORSE_PAUSE_WORD;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (0 == ticksLeft) {
|
|
||||||
// Unpack can return 0 if there are fewer than 4 emissions for a letter.
|
|
||||||
// In that case, we 're done with the letter.
|
|
||||||
crumb = 0;
|
|
||||||
++p;
|
|
||||||
Transmitting = false;
|
Transmitting = false;
|
||||||
ticksLeft = MORSE_PAUSE_LETTER - MORSE_DIT;
|
ticksLeft = sign.Bits - (MORSE_PAUSE_LETTER - MORSE_DIT);
|
||||||
|
++p;
|
||||||
|
bit = 0;
|
||||||
|
} else if (bit == sign.Length) {
|
||||||
|
// All done with that sign!
|
||||||
|
Transmitting = false;
|
||||||
|
ticksLeft = MORSE_PAUSE_LETTER;
|
||||||
|
++p;
|
||||||
|
bit = 0;
|
||||||
|
} else {
|
||||||
|
// Sign
|
||||||
|
uint8_t bitMask = 1 << (sign.Length - bit - 1);
|
||||||
|
Transmitting = true;
|
||||||
|
if (sign.Bits & bitMask) {
|
||||||
|
ticksLeft = MORSE_DAH;
|
||||||
|
} else {
|
||||||
|
ticksLeft = MORSE_DIT;
|
||||||
|
}
|
||||||
|
++bit;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
3
morse.h
3
morse.h
|
@ -6,6 +6,7 @@
|
||||||
#define MORSE_DAH 3
|
#define MORSE_DAH 3
|
||||||
#define MORSE_PAUSE_LETTER 3
|
#define MORSE_PAUSE_LETTER 3
|
||||||
#define MORSE_PAUSE_WORD 6
|
#define MORSE_PAUSE_WORD 6
|
||||||
|
#define MORSE_PAUSE_TRANSMISSION 50
|
||||||
|
|
||||||
class MorseEncoder {
|
class MorseEncoder {
|
||||||
public:
|
public:
|
||||||
|
@ -35,6 +36,6 @@ class MorseEncoder {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const char *p;
|
const char *p;
|
||||||
uint8_t crumb;
|
uint8_t bit;
|
||||||
int ticksLeft;
|
int ticksLeft;
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
#include "pulse.h"
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
Pulse::Pulse(unsigned long period) {
|
||||||
|
this->period = period;
|
||||||
|
this->nextEventMillis = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Pulse::Ticked() {
|
||||||
|
unsigned long now = millis();
|
||||||
|
|
||||||
|
if (now >= nextEventMillis) {
|
||||||
|
Until(period, now);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Pulse::Until(unsigned long next, unsigned long now) {
|
||||||
|
nextEventMillis = now + next;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Pulse::Until(unsigned long next) {
|
||||||
|
Until(next, millis());
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
#pragma once
|
||||||
|
#include "durations.h"
|
||||||
|
|
||||||
|
class Pulse {
|
||||||
|
public:
|
||||||
|
Pulse(unsigned long period);
|
||||||
|
|
||||||
|
/** Ticked tells you if a period has elapsed. */
|
||||||
|
bool Ticked();
|
||||||
|
|
||||||
|
/** Until sets the duration of the next period. */
|
||||||
|
void Until(unsigned long next);
|
||||||
|
void Until(unsigned long next, unsigned long now);
|
||||||
|
|
||||||
|
unsigned long period;
|
||||||
|
unsigned long nextEventMillis;
|
||||||
|
};
|
2
test.cpp
2
test.cpp
|
@ -4,7 +4,7 @@
|
||||||
// gcc -D test_main=main -o test morse.cpp test.cpp && ./test
|
// gcc -D test_main=main -o test morse.cpp test.cpp && ./test
|
||||||
|
|
||||||
int test_main(int argc, char *argv[]) {
|
int test_main(int argc, char *argv[]) {
|
||||||
MorseEncoder enc = MorseEncoder("SOS ck ck ark");
|
MorseEncoder enc = MorseEncoder("SOS ck ck \x03");
|
||||||
while (enc.Tick()) {
|
while (enc.Tick()) {
|
||||||
if (enc.Transmitting) {
|
if (enc.Transmitting) {
|
||||||
printf("#");
|
printf("#");
|
||||||
|
|
Loading…
Reference in New Issue