// *********************************************************
// Morse_Oscillater ATtiny202 Sleep within 60sec LED
// Piezo = Pin 2 Key = Pin5 Button = Pin4
// Tone 500Hz - 1000Hz up/50Hz
// XRQTechLab 2025.09.07
// **********************************************************
#include <avr/io.h>
#include <EEPROM.h>
#include <avr/sleep.h>
#include <avr/interrupt.h>
#define BUZZER_PIN 0 // PA6 → 物理ピン2(割り込み対応)
#define KEY_PIN 3 // PA2 → 物理ピン5(割り込み対応)
#define BTN_PIN 2 // PA1 → 物理ピン4(ポーリング)
#define LED_PIN 4 // PA4 → 物理ピン7(スリープ状態表示用)
volatile bool wakeUpFlag = false;
bool keyWasPressed = false;
uint16_t toneFreq = 500;
unsigned long lastInputTime = 0;
void setup() {
pinMode(BUZZER_PIN, OUTPUT);
pinMode(KEY_PIN, INPUT_PULLUP);
pinMode(BTN_PIN, INPUT_PULLUP);
pinMode(LED_PIN, OUTPUT); // LEDピンを出力に設定
digitalWrite(LED_PIN, HIGH); // 起動時は点灯
attachInterrupt(digitalPinToInterrupt(KEY_PIN), wakeISR, FALLING); //key input
attachInterrupt(digitalPinToInterrupt(BTN_PIN), wakeISR, FALLING); //but input
uint8_t storedFreq = EEPROM.read(0);
uint16_t freq = 500 + storedFreq * 50;
toneFreq = (freq >= 500 && freq <= 1000) ? freq : 500;
lastInputTime = millis();
sei(); // 割り込み有効化
}
void loop() {
// スリープ復帰後の処理
if (wakeUpFlag) {
wakeUpFlag = false;
lastInputTime = millis(); // 起床後タイマーリセット
digitalWrite(LED_PIN, HIGH); // 起床時にLED点灯
}
// スリープ判定(60秒無操作)
if (millis() - lastInputTime > 60000) {
goToSleep();
return; // スリープ後はloopの残りをスキップ
}
// KEY入力処理
if (digitalRead(KEY_PIN) == LOW) {
lastInputTime = millis();
if (!keyWasPressed) {
tone(BUZZER_PIN, toneFreq);
keyWasPressed = true;
}
} else {
if (keyWasPressed) {
noTone(BUZZER_PIN);
keyWasPressed = false;
}
}
// BTN入力処理
if (digitalRead(BTN_PIN) == LOW) {
delay(50);
if (digitalRead(BTN_PIN) == LOW) {
lastInputTime = millis();
toneFreq += 50;
if (toneFreq > 1000) toneFreq = 500;
EEPROM.write(0, (toneFreq - 500) / 50);
confirmTone();
while (digitalRead(BTN_PIN) == LOW);
}
}
}
void confirmTone() {
for (int i = 0; i < 3; i++) {
tone(BUZZER_PIN, toneFreq);
delay(150);
noTone(BUZZER_PIN);
delay(150);
}
}
void goToSleep() {
noTone(BUZZER_PIN);
digitalWrite(LED_PIN, LOW); // スリープ時にLED消灯
sleep_enable();
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_cpu(); // ここで停止、割り込みで復帰
sleep_disable();
}
void wakeISR() {
wakeUpFlag = true;
}