/*
Arduino Christmas Songs
Based on a project and code by Dipto Pratyaksa, updated on 31/3/13
Modified for Christmas by Joshi, on Dec 17th, 2017.
https://create.arduino.cc/projecthub/joshi/piezo-christmas-songs-fd1ae9
*/
/*
SparkFun Inventor's Kit
Example sketch 14
SHIFT REGISTER
Use a shift register to turn three pins into eight (or more!)
outputs
An integrated circuit ("IC"), or "chip", is a self-contained
circuit built into a small plastic package. (If you look closely
at your Arduino board you'll see a number of ICs.) There are
thousands of different types of ICs available that you can use
to perform many useful functions.
The 74HC595 shift register in your kit is an IC that has eight
digital outputs. To use these outputs, we'll use a new interface
called SPI (Serial Peripheral Interface). It's like the TX and
RX you're used to, but has an additional "clock" line that
controls the speed of the data transfer. Many parts use SPI
for communications, so the Arduino offers simple commands called
shiftIn() and shiftOut() to access these parts.
This IC lets you use three digital pins on your Arduino to
control eight digital outputs on the chip. And if you need
even more outputs, you can daisy-chain multiple shift registers
together, allowing an almost unlimited number of outputs from
the same three Arduino pins! See the shift register datasheet
for details:
http://www.sparkfun.com/datasheets/IC/SN74HC595.pdf
This sketch was written by SparkFun Electronics,
with lots of help from the Arduino community.
This code is completely free for any use.
Visit http://learn.sparkfun.com/products/2 for SIK information.
Visit http://www.arduino.cc to learn about the Arduino.
Version 2.0 6/2012 MDG
*/
#include <LiquidCrystal_I2C.h>
#include "pitches.h"
#define I2C_ADDR 0x27
#define LCD_COLUMNS 16
#define LCD_LINES 2
#define buttonPin 8
#define melodyPin 9
#define datapin 10
#define clockpin 11
#define latchpin 12
uint8_t previousLED = 0;
LiquidCrystal_I2C lcd(I2C_ADDR, LCD_COLUMNS, LCD_LINES);
// Jingle Bells
const int jingle_melody[] = {
NOTE_E5, NOTE_E5, NOTE_E5,
NOTE_E5, NOTE_E5, NOTE_E5,
NOTE_E5, NOTE_G5, NOTE_C5, NOTE_D5,
NOTE_E5,
NOTE_F5, NOTE_F5, NOTE_F5, NOTE_F5,
NOTE_F5, NOTE_E5, NOTE_E5, NOTE_E5, NOTE_E5,
NOTE_E5, NOTE_D5, NOTE_D5, NOTE_E5,
NOTE_D5, NOTE_G5
};
const uint8_t jingle_tempo[] = {
8, 8, 4,
8, 8, 4,
8, 8, 8, 8,
2,
8, 8, 8, 8,
8, 8, 8, 16, 16,
8, 8, 8, 8,
4, 4
};
// We Wish You a Merry Christmas
const int wish_melody[] = {
NOTE_B3,
NOTE_F4, NOTE_F4, NOTE_G4, NOTE_F4, NOTE_E4,
NOTE_D4, NOTE_D4, NOTE_D4,
NOTE_G4, NOTE_G4, NOTE_A4, NOTE_G4, NOTE_F4,
NOTE_E4, NOTE_E4, NOTE_E4,
NOTE_A4, NOTE_A4, NOTE_B4, NOTE_A4, NOTE_G4,
NOTE_F4, NOTE_D4, NOTE_B3, NOTE_B3,
NOTE_D4, NOTE_G4, NOTE_E4,
NOTE_F4
};
const uint8_t wish_tempo[] = {
4,
4, 8, 8, 8, 8,
4, 4, 4,
4, 8, 8, 8, 8,
4, 4, 4,
4, 8, 8, 8, 8,
4, 4, 8, 8,
4, 4, 4,
2
};
// Santa Claus is Coming to Town
const int santa_melody[] = {
NOTE_G4,
NOTE_E4, NOTE_F4, NOTE_G4, NOTE_G4, NOTE_G4,
NOTE_A4, NOTE_B4, NOTE_C5, NOTE_C5, NOTE_C5,
NOTE_E4, NOTE_F4, NOTE_G4, NOTE_G4, NOTE_G4,
NOTE_A4, NOTE_G4, NOTE_F4, NOTE_F4,
NOTE_E4, NOTE_G4, NOTE_C4, NOTE_E4,
NOTE_D4, NOTE_F4, NOTE_B3,
NOTE_C4
};
const uint8_t santa_tempo[] = {
8,
8, 8, 4, 4, 4,
8, 8, 4, 4, 4,
8, 8, 4, 4, 4,
8, 8, 4, 2,
4, 4, 4, 4,
4, 2, 4,
1
};
void setup()
{
lcd.init();
lcd.backlight();
pinMode(datapin, OUTPUT);
pinMode(clockpin, OUTPUT);
pinMode(latchpin, OUTPUT);
pinMode(melodyPin, OUTPUT);
pinMode(buttonPin, INPUT_PULLUP);
pinMode(13, OUTPUT);
}
void loop()
{
if (!digitalRead(buttonPin))
{
uint8_t i = 0;
lcd.setCursor(0, 0);
lcd.print("Jingle Bells ");
playSong(jingle_melody, jingle_tempo, 26);
for (i = 0; i < 3; ++i)
{
marquee();
}
lcd.setCursor(0, 0);
lcd.print("We Wish You a ");
lcd.setCursor(0, 1);
lcd.print("Merry Christmas");
playSong(wish_melody, wish_tempo, 30);
for (i = 0; i < 3; ++i)
{
marquee();
}
lcd.setCursor(0, 0);
lcd.print("Santa Claus is ");
lcd.setCursor(0, 1);
lcd.print("Coming to Town ");
playSong(santa_melody, santa_tempo, 28);
for (i = 0; i <= 7; ++i)
{
shiftWrite(i, LOW);
}
}
}
void playSong (const int notes [], const uint8_t durations [], uint8_t len)
{
for (uint8_t thisNote = 0; thisNote < len; thisNote++)
{
uint8_t index = previousLED;
while (index == previousLED)
{
index = random(8);
}
previousLED = index;
shiftWrite(index, HIGH);
int noteDuration = 1000 / durations[thisNote];
buzz(melodyPin, notes[thisNote], noteDuration);
int pauseBetweenNotes = noteDuration * 1.30;
delay(pauseBetweenNotes);
buzz(melodyPin, 0, noteDuration);
shiftWrite(index, LOW);
}
}
void buzz(uint8_t targetPin, long frequency, long length)
{
long delayValue = 1000000 / frequency / 2;
long numCycles = frequency * length / 1000;
for (long i = 0; i < numCycles; i++)
{
digitalWrite(targetPin, HIGH);
delayMicroseconds(delayValue);
digitalWrite(targetPin, LOW);
delayMicroseconds(delayValue);
}
}
void shiftWrite(uint8_t desiredPin, boolean desiredState)
{
byte data;
bitWrite(data,desiredPin,desiredState);
shiftOut(datapin, clockpin, MSBFIRST, data);
digitalWrite(latchpin, HIGH);
digitalWrite(latchpin, LOW);
}
void marquee()
{
for(uint8_t index = 0; index <= 3; index++)
{
shiftWrite(index, HIGH);
shiftWrite(index+4, HIGH);
delay(200);
shiftWrite(index, LOW);
shiftWrite(index+4, LOW);
}
}