Skip to content

Instantly share code, notes, and snippets.

@azyobuzin
Created July 17, 2018 16:04
Show Gist options
  • Save azyobuzin/4bab0368806a4e7d92434561097634f1 to your computer and use it in GitHub Desktop.
Save azyobuzin/4bab0368806a4e7d92434561097634f1 to your computer and use it in GitHub Desktop.
校歌への思い
#include <avr/eeprom.h>
uint8_t EEMEM eeprom_data[64];
// MIDI 番号
#define AS4 70
#define B4 71
#define C5 72
#define CS5 73
#define D5 74
#define DS5 75
#define E5 76
#define F5 77
#define FS5 78
#define G5 79
#define GS5 80
#define A5 81
#define AS5 82
#define B5 83
#define C6 84
#define CS6 85
#define D6 86
#define DS6 87
#define E6 88
#define F6 89
#define MIN_NOTE_NUM AS4
#define D(note_num, len) (((note_num - MIN_NOTE_NUM + 1) << 3) | (len - 1))
#define R(len) (len - 1)
static const uint8_t EEPROM_DATA1[] = {
// われら新しい 真理を創る
D(DS6, 6),
D(C6, 2),
D(AS5, 2),
D(G5, 2),
D(DS5, 3),
D(C6, 1),
D(AS5, 8),
D(G5, 2),
R(2),
D(G5, 3),
D(DS5, 1),
D(C6, 4),
D(AS5, 4),
D(AS4, 4),
D(F5, 4),
D(DS5, 8),
R(2),
// 東京電大 われらが母校
D(DS5, 2),
D(G5, 3),
D(AS5, 1),
D(DS6, 8),
R(2),
D(C6, 2),
D(GS5, 3),
D(C6, 1),
D(AS5, 8),
R(2),
D(G5, 2),
D(DS5, 3),
D(C6, 1),
D(AS5, 8),
R(2),
D(G5, 2),
D(G5, 4),
D(F5, 8),
R(4),
};
static const uint8_t EEPROM_DATA2[] = {
// ああ讃えんかな その伝統
D(AS4, 4),
D(DS5, 8),
R(2),
D(F5, 2),
D(G5, 2),
D(AS5, 2),
D(DS6, 4),
D(C6, 4),
D(AS5, 2),
R(2),
D(DS5, 3),
D(G5, 1),
D(AS5, 6),
D(C6, 2),
D(AS5, 2),
D(G5, 2),
D(AS4, 3),
D(F5, 1),
D(DS5, 8),
};
// クロック周波数(1/8分周)
#define F_CPU 1.2e6
// _delay_loop_2 の1回あたりのサイクル
#define CYCLES_DELAY_LOOP_2 4
#include <math.h>
#include <stdbool.h>
#include <avr/io.h>
#include <util/delay.h>
#include "eeprom_data.h"
// 16分音符の長さ
#define WAIT_MS 125.0
const uint8_t IN_MEM_DATA[] = {
// 日輪は天にかがやき
D(AS4, 4),
D(DS5, 4),
D(DS5, 3),
D(DS5, 1),
D(DS5, 4),
R(2),
D(F5, 2),
D(G5, 3),
D(G5, 1),
D(G5, 2),
D(GS5, 2),
D(AS5, 4),
D(AS5, 2),
R(2),
// 白雲は富士に沸きたつ
D(DS5, 4),
D(C6, 4),
D(C6, 3),
D(C6, 1),
D(GS5, 4),
D(DS6, 3),
D(DS6, 1),
D(D6, 2),
D(C6, 2),
D(AS5, 2),
D(AS5, 2),
D(G5, 2),
R(2),
// 朋がらよ 眉あげよ
D(DS5, 4),
D(DS5, 3),
D(F5, 1),
D(G5, 4),
D(AS5, 4),
D(G5, 2),
D(G5, 4),
D(DS5, 2),
D(G5, 4),
D(F5, 2),
R(2),
// 大いなる歴史の中で
D(DS5, 3),
D(DS5, 1),
D(AS4, 2),
D(DS5, 2),
D(G5, 6),
D(DS5, 2),
D(F5, 3),
D(G5, 1),
D(GS5, 2),
D(C6, 2),
D(AS5, 4),
D(G5, 2),
R(2),
};
static void play_note(uint8_t note_data)
{
uint8_t note_num = (note_data >> 3) + MIN_NOTE_NUM - 1;
uint16_t cycles;
uint16_t times;
bool is_rest = false;
#define CASE(n) \
case n: \
{ \
const double pitch = 1.0 / (440.0 * pow(2, (n - 69) / 12.0)); \
cycles = (uint16_t)(pitch / 2.0 / ((1.0 / F_CPU) * CYCLES_DELAY_LOOP_2)); \
times = (uint16_t)(WAIT_MS / (pitch * 1000.0)); \
break; \
}
switch (note_num)
{
// コンパイル時に事前計算させるために、すべてのケースを展開
CASE(AS4);
CASE(B4);
CASE(C5);
CASE(CS5);
CASE(D5);
CASE(DS5);
CASE(E5);
CASE(F5);
CASE(FS5);
CASE(G5);
CASE(GS5);
CASE(A5);
CASE(AS5);
CASE(B5);
CASE(C6);
CASE(CS6);
CASE(D6);
CASE(DS6);
CASE(E6);
CASE(F6);
default:
is_rest = true;
}
uint8_t len = note_data & 0b111;
for (uint8_t i = 0; i <= len; i++)
{
if (is_rest)
{
_delay_ms(WAIT_MS);
}
else
{
for (uint16_t j = 0; j < times; j++)
{
PORTB |= 1 << PORTB4;
_delay_loop_2(cycles);
PORTB &= ~(1 << PORTB4);
_delay_loop_2(cycles);
}
}
}
}
static void play(void)
{
for (uint8_t i = 0; i < sizeof(IN_MEM_DATA); i++)
play_note(IN_MEM_DATA[i]);
for (uint8_t i = 0; i < sizeof(EEPROM_DATA1) + sizeof(EEPROM_DATA2); i++)
{
eeprom_busy_wait();
play_note(eeprom_read_byte(&eeprom_data[i]));
}
}
int main(void)
{
DDRB = 0b11100;
PORTB = 0b00011;
while (1)
{
if ((~PINB & 0b00001) == 0)
continue;
PORTB |= 0b00100;
play();
PORTB &= ~0b00100;
}
}
#include <avr/io.h>
#include "eeprom_data.h"
int main(void) {
DDRB = 0b00100;
PORTB = 0b00100;
eeprom_busy_wait();
eeprom_write_block(EEPROM_DATA1, eeprom_data, sizeof(EEPROM_DATA1));
eeprom_busy_wait();
PORTB = 0;
while (1) { }
}
#include <avr/io.h>
#include "eeprom_data.h"
int main(void) {
DDRB = 0b00100;
PORTB = 0b00100;
eeprom_busy_wait();
eeprom_write_block(EEPROM_DATA2, eeprom_data + sizeof(EEPROM_DATA1), sizeof(EEPROM_DATA2));
eeprom_busy_wait();
PORTB = 0;
while (1) { }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment