/*
Merry_Christmas.ino
Song title: Hark The Herald Angels Sing
Pitch levels indicator: Rainbow Lights Spectrum
By ZulNs, @Gorontalo, 25 December 2022
*/
#include "avr_singing.h"
#include <LiquidCrystal_I2C.h>
const PROGMEM uint8_t SONG[] = {
NC7, 0, 2, 3,
NC7, 3, NC7, 3, ND7, 3, NC7, 3, NAIS6, 3, NA6, 3, NAIS6, 0, 2, 3,
NG6, 3, NA6, 3, NC7, 3, NAIS6, 3, NA6, 3, NG6, 3, NA6, 0, 2, 3,
NF6, 3, NG6, 3, NAIS6, 3, NA6, 3, NG6, 3, NF6, 3, NG6, 0, 2, 3,
NG6, 3, NF6, 3, NE6, 1, ND6, 3, NC6, 0, 4, 3, NF6, 0, 2, 3, NG6, 0, 2, 3,
NA6, 0, 2, 3, NAIS6, 0, 2, 3, NA6, 0, 4, 3, NG6, 0, 4, 3, NF6, 0, 4, 3, REST, 0, 2, 3,
// Address 96
NC6, 0, 2, 3, NF6, 0, 2, 3, NF6, 1, NE6, 3, NF6, 0, 2, 3, NA6, 0, 2, 3, NA6, 0, 2, 3, NG6, 0, 2, 3,
NC7, 0, 2, 3, NC7, 0, 2, 3, NC7, 1, NAIS6, 3, NA6, 0, 2, 3, NG6, 0, 2, 3, NA6, 1, REST, 3,
REPEAT, 96, 0, 28, 0,
NC7, 0, 2, 3, NG6, 0, 2, 3, NG6, 1, NF6, 3, NE6, 0, 2, 3, ND6, 0, 2, 3, NC6, 1, REST, 3,
// Address 177
NC7, 0, 2, 3, NC7, 0, 2, 3, NC7, 1, NF6, 3, NAIS6, 0, 2, 3, NA6, 0, 2, 3, NA6, 0, 2, 3, NG6, 0, 2, 3,
REPEAT, 177, 0, 28, 0,
// Address 210
ND7, 1, ND7, 3, ND7, 0, 2, 3, NC7, 0, 2, 3, NAIS6, 0, 2, 3, NA6, 0, 2, 3, NAIS6, 1, REST, 3,
NG6, 0, 2, 3, NA6, 0, 2, 3, NC7, 1, NF6, 3, NF6, 0, 2, 3, NG6, 0, 2, 3, NA6, 1, REST, 3,
REPEAT, 210, 0, 44, 0, NF6, 1, REST, 3,
REPEAT, 0, 0, 96, 0,
REPEAT, 0, 0, 96, 0,
REPEAT, 96, 0, 77, 0,
NC6, 3, NC6, 3, NF6, 3, NA6, 3,
REPEAT, 177, 0, 90, 0,
};
#define LOWEST_TONE NC6
#define HIGHEST_TONE ND7
const uint16_t NOTE_SIZE = sizeof(SONG);
const uint8_t BUZZER = 13;
// These below pins must be support PWM output (3, 5, 6, 9, 10, and 11 on UNO board).
// Avoid using pins 3 and 11 on boards other than the Mega since the use of tone()
// function will interfere with PWM output on those pins.
const uint8_t RGB_RED_PIN = 10;
const uint8_t RGB_GREEN_PIN = 9;
const uint8_t RGB_BLUE_PIN = 6;
uint16_t freqRangeA, freqRangeB, freqRange;
LiquidCrystal_I2C lcd(0x27, 20, 4);
String str = " Especially for bros 'n sists: Ventje, Aldy, Lilis, Tirsa, Joan 'n fams, Linda, Lydia, and others... ";
void setup() {
lcd.init();
lcd.backlight();
//lcd.setCursor(0, 0);
lcd.print(F("Merry Christmas &"));
lcd.setCursor(0, 1);
lcd.print(F("Happy New Year 2023"));
freqRangeA = getFreq(LOWEST_TONE);
freqRangeB = getFreq(HIGHEST_TONE);
freqRange = freqRangeB - freqRangeA;
setOnSoundCallback(onPlayNote);
setOnMuteCallback(onMuteSpeaker);
setSpeakerPin(BUZZER);
setSong(SONG, NOTE_SIZE);
startSinging();
//noteCounter = 262;
}
void loop() {
static uint32_t strTimer;
static uint8_t strCtr;
loopSinging();
if (isSinging && millis() >= strTimer) {
lcd.setCursor(0, 3);
lcd.print(str.substring(strCtr, strCtr + 20));
strTimer = millis() + 200;
strCtr++;
if (strCtr > str.length() - 20) {
strCtr = 0;
}
}
}
void onPlayNote(uint16_t freq) {
uint16_t norm;
uint8_t val, red, green, blue, grade;
if (freq < freqRangeA) {
freq = freqRangeA;
}
else if (freq > freqRangeB) {
freq = freqRangeB;
}
freq -= freqRangeA;
norm = (float)freq / freqRange * 5.0 * 255.0;
// Uses 5.0 value instead of 6.0 to put the violet lights on top of the rainbow spectrum
val = norm / 255;
grade = norm % 255;
red = green = blue = 0;
if (bitRead(val, 0)) {
grade = 255 - grade;
}
switch (val) {
case 0:
red = 255;
green = grade;
break;
case 1:
red = grade;
green = 255;
break;
case 2:
green = 255;
blue = grade;
break;
case 3:
green = grade;
blue = 255;
break;
case 4:
blue = 255;
red = grade;
break;
case 5:
blue = grade;
red = 255;
break;
}
analogWrite(RGB_RED_PIN, red);
analogWrite(RGB_GREEN_PIN, green);
analogWrite(RGB_BLUE_PIN, blue);
}
void onMuteSpeaker() {
analogWrite(RGB_RED_PIN, 0);
analogWrite(RGB_GREEN_PIN, 0);
analogWrite(RGB_BLUE_PIN, 0);
}