#include <Arduino.h>
#include <EEPROM.h>
#include <Encoder.h>

// 数码管value:0~9
byte smg[10] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90};

// 数码管位选引脚
int com[4] = {6, 5, 4, 3};

// 旋转编码器引脚
#define CLK PIN_A3
#define SW PIN_A4
#define DT PIN_A5

// 蜂鸣器引脚
#define BEEP PIN_A2

// 是否停止计时
boolean isStop = false;

// 旋转编码器类
Encoder encoder(CLK, DT);

// 倒计时时间值
int times[] = {5, 10, 15, 20, 30, 45, 100, 130, 200, 230, 300, 400, 500, 600, 700, 800, 900, 1000, 1500, 2000, 3000};

// 选择的时间编号
byte selectedTimeIndex = 0;

//
int numTimes = 19;

// minute值
int TimerMinute = 19;

// second值
int TimerSecond = 59;

// 旋转编码器值
int encoderVal = 0;

// 同时写入8个引脚的一个字节值
void Write8Pins(int *pin, byte cmd)
{
	for (int i = 0; i < 8; i++)
	{
		pinMode(pin[i], OUTPUT);
		digitalWrite(pin[i], cmd % 2);
		cmd /= 2;
	}
}

// 数码管显示指定值
void displaySMG(int COM, int value)
{
	for (int i = 0; i < 4; i++)
	{
		pinMode(com[i], OUTPUT);
		digitalWrite(com[i], LOW);
	}
	digitalWrite(com[COM], HIGH);
	int pin[8] = {7, 8, 9, 10, 11, 12, 13, 14};
	Write8Pins(pin, smg[value]);
}

// 读取旋转编码器的旋转
int getEncoderTurn()
{ // return -1，0，or +1
	static int oldA = LOW;
	static int oldB = LOW;
	int result = 0;
	int newA = digitalRead(CLK);
	int newB = digitalRead(DT);
	if (newA != oldA || newB != oldB)
	{ // something has changed
		if (oldA == LOW && newA == HIGH)
		{
			result = -(oldB * 2 - 1);
		}
	}
	oldA = newA;
	oldB = newB;
	return result;
}

// 改变预设时间
void changeSetTime(int value)
{
	selectedTimeIndex += value;
	if (selectedTimeIndex < 0)
	{
		selectedTimeIndex = numTimes;
	}
	else if (selectedTimeIndex > numTimes)
	{
		selectedTimeIndex = 0;
	}
	TimerMinute = times[selectedTimeIndex] / 100;
	TimerSecond = times[selectedTimeIndex] % 100;
}

// 更新时间
void updateTime()
{
	static unsigned long lastMillis;	// 记录上次的毫秒数
	unsigned long curMillis = millis(); // 当前毫秒数
	// 已经过了1秒
	if (curMillis > (lastMillis + 1000) && (TimerMinute > 0 || TimerSecond > 0))
	{
		// 实现滴答声
		// Serial.println("666");
		digitalWrite(BEEP, HIGH);
		delay(10);
		digitalWrite(BEEP, LOW);
		// 处理进位
		if (TimerSecond == 0)
		{
			TimerSecond = 59;
			TimerMinute--;
		}
		else
		{
			TimerSecond--;
		}
		lastMillis = curMillis; // 更新豪秒数
	}
}

void setup()
{
	// put your setup code here, to run once:
	Serial.begin(115200);
	pinMode(SW, INPUT);
	pinMode(CLK, INPUT);
	pinMode(DT, INPUT);
	pinMode(BEEP, OUTPUT);
	// selectedTimeIndex = EEPROM.read(0);
	// TimerMinute = times[selectedTimeIndex] / 100;
	// TimerSecond = times[selectedTimeIndex] % 100;
}

void loop()
{
	// put your main code here, to run repeatedly:
	// 读取旋转编码器的值
	encoderVal = getEncoderTurn();
	// 旋转编码器按键按下
	if (!digitalRead(SW))
	{
		isStop = !isStop;
		digitalWrite(BEEP, LOW);
		// 等待按键抬起
		while (!digitalRead(SW))
			;
		// EEPROM.write(0, selectedTimeIndex);
	}
	// 计时暂停状态
	if (isStop)
	{
		changeSetTime(encoderVal);
	}
	else
	{
		updateTime();
	}
	Serial.println(encoderVal);
	// 计时结束蜂鸣器报警
	if (TimerMinute == 0 && TimerSecond ==0)
	{
		digitalWrite(BEEP, HIGH);
	}
	displaySMG(0, TimerMinute / 10);
	delay(3);
	displaySMG(1, TimerMinute % 10);
	delay(3);
	displaySMG(2, TimerSecond / 10);
	delay(3);
	displaySMG(3, TimerSecond % 10);
	delay(3);
}
