#include "pitch.h"
#define TIMER 20 // タイマー時間 (秒)
#define HALF_TIMER 10 // 「残り時間が半分」の時間 (秒)
#define SOON_TIMER 3 // 「もうすぐ」の時間 (秒)
#define SW_PIN A5 // スイッチ接続端子
#define SW_ON 0 // スイッチONの電圧計の値 (pullup)
#define SW_OFF 1 // スイッチOFFの電圧計の値 (pullup)
#define LED_PIN 12 // 1秒毎に点滅するLED接続端子
#define LED_ON_INTERVAL 50 // LED点点灯時間 (ミリ秒)
#define LED_OFF_INTERVAL 950 // LED消灯時間 (ミリ秒)
#define FULL_PIN 8 // 「残り時間十分」の時のLEDの接続端子
#define HALF_PIN 6 // 「残り時間半分」の時のLEDの接続端子
#define SOON_PIN 4 // 「もうすぐ」の時のLEDの接続端子
const int timeIndicator[] = {FULL_PIN, HALF_PIN, SOON_PIN};
typedef struct { // 配列を関数の引数に使用するための型
int *array; // 配列のポインタ
int num; // 配列の要素数
} arrayInfo;
#define SPEAKER_PIN A0 // スピーカー接続端子
#define ALARM_TONE 1760 // アラーム音の周波数
//----------------------------------------------------------------------------------
void ledBlink(bool alarm=false) {
if(alarm) {
tone(SPEAKER_PIN, ALARM_TONE);
}
// LEDをONにする
digitalWrite(LED_PIN, HIGH);
delay(LED_ON_INTERVAL);
if(alarm) {
noTone(SPEAKER_PIN);
}
// LEDをOFFにする
digitalWrite(LED_PIN, LOW);
delay(LED_OFF_INTERVAL);
}
// 指定したインデックスのLEDだけ点灯させる
void setLedIdx(arrayInfo led, int idx, int value=HIGH, bool onlyOne=true) {
int reverseValue = (value == LOW) ? HIGH : LOW;
for(int i=0; i < led.num; i++) {
if(idx == i) {
digitalWrite(led.array[i], value);
}else{
if(onlyOne) {
digitalWrite(led.array[i], reverseValue);
}
}
}
}
void setTimeIndicator(int remainingTime) { // 残り時間をLEDの点灯で表示する
arrayInfo led {timeIndicator, sizeof(timeIndicator)/sizeof(int)};
switch(remainingTime) {
case TIMER: // 「残り時間十分」の時のLED制御
setLedIdx(led, 0);
break;
case HALF_TIMER: // 「残り時間が半分」の時のLED制御
setLedIdx(led, 1);
break;
case SOON_TIMER: // 「もうすぐ」の時のLED制御
setLedIdx(led, 2);
break;
case 0: // 全てのLEDを消灯
setLedIdx(led, -1);
break;
}
}
//----------------------------------------------------------------------------------
void sound(int alarmTone, int toneDelayTime=0, int noToneDelayTime=0) {
tone(SPEAKER_PIN, alarmTone);
delay(toneDelayTime);
noTone(SPEAKER_PIN);
delay(noToneDelayTime);
}
void alarm() {
sound(ALARM_TONE, 60, 60);
sound(ALARM_TONE, 60, 60);
sound(ALARM_TONE, 120);
}
//----------------------------------------------------------------------------------
void melody() {
// メロディーの配列
int melody[] = {DO_4, RE_4, MI_4, REST, RE_4, DO_4};
int dulation[] = { 2, 1, 2, 2, 1, 1};
int dulationBase = 200;
// メロディー再生
for(int i=0; i < sizeof(melody)/sizeof(int); i++) {
if(melody[i] == REST) {
noTone(SPEAKER_PIN);
}else{
tone(SPEAKER_PIN, melody[i]);
}
delay(dulation[i] * dulationBase);
}
noTone(SPEAKER_PIN); // 音を止める
}
//----------------------------------------------------------------------------------
void setup() {
// LED接続端子を出力制御にする
pinMode(LED_PIN, OUTPUT);
pinMode(FULL_PIN, OUTPUT);
pinMode(HALF_PIN, OUTPUT);
pinMode(SOON_PIN, OUTPUT);
// スイッチ接続端子を入力制御(プルアップ)にする
pinMode(SW_PIN, INPUT_PULLUP);
//シリアルモニタの初期化
Serial.begin(9600);
}
void loop() {
// スイッチが押されるまで待つ
while(digitalRead(SW_PIN)==SW_OFF) {
}
// 指定した時間、LEDを点滅させる
for(int i=0; i < TIMER; i++) {
int remainingTime = TIMER - i;
setTimeIndicator(remainingTime);
if(remainingTime == HALF_TIMER || remainingTime <= SOON_TIMER) {
ledBlink(true); // LEDの点灯に合わせてアラームを鳴らす
}else{
ledBlink();
}
}
//alarm(); // アラームを鳴らす
melody(); // メロディーを鳴らす
setTimeIndicator(0); // LEDを消灯
// SW_PIN端子のデジタル電圧計の値を送信する
Serial.println(digitalRead(SW_PIN));
}
//----------------------------------------------------------------------------------