#include "Timer.h" //載入計時器程式庫
Timer t0,t1,t2; //建立計時器(Timer)物件
int LED_L[]={11,10,9,8}; //LED陣列_左側4顆接腳
int LED_R[]={7,6,5,4}; //LED陣列_右側4顆接腳
int SEG[]={22,24,26,28,30,32,34}; //七段顯示器之a,b,c,d,e,f,g 接腳
int led_state[]={0,0,0}; //記錄目前點亮燈號(LED為0-3,七段為0-6),初值皆為0
int MODE[]={0,0,0}; //記錄各裝置之亮燈模式(0-4),初值皆為0
//亮燈模式,0:左至右單燈,1:左至右逐燈,2:右至左單燈,3:右至左逐燈,4:全亮
void flash(int device,int *pin,int cnt,boolean on){ //控制亮燈副程式
//device:裝置號(0~2),*pin:接腳陣列之指標,cnt:LED數(4/7),on:亮燈形態(0/1)
if(led_state[device] > cnt-1) //要點亮LED燈號,超出範圍(0~cnt-1)時
led_state[device]=0; //回到點亮燈號0(最左或七段之a)
int state=led_state[device]; //記錄點亮燈號狀態至變數state
for(int i=0;i<cnt;i++) //使燈全不亮
digitalWrite(pin[i],!on);//!為邏輯反相運算
switch(MODE[device]){ //依照裝置之模式選不同亮法
case 0: digitalWrite(pin[state],on);break;//模式0,左至右,單燈亮
case 1: for(int i=0;i<=state;i++) //模式1,左至右(七段為a->g),逐燈亮
digitalWrite(pin[i],on);break;
case 2: digitalWrite(pin[(cnt-1)-state],on);break;//模式2,右至左,單燈亮
case 3: for(int i=0;i<=state;i++) //模式3,右至左(七段為g->a),逐燈亮
digitalWrite(pin[(cnt-1)-i],on);break;
case 4: for(int i=0;i<cnt;i++) //模式4,全亮
digitalWrite(pin[i],on);
}//switch()結束
led_state[device]++;//改成亮下個燈
}//flash()副程式結束
void t0_ISR(){ //t0計時器中斷副程式,改變LED左側4燈狀態
flash(0,LED_L,4,0);//呼叫控制亮燈副程式,裝置號0,接腳放在LED_L[],4燈,0亮
}//t0_ISR()中斷副程式結束
void t1_ISR(){ //t1計時器中斷副程式,改變LED右側4燈狀態
flash(1,LED_R,4,0);//呼叫控制亮燈副程式,裝置號1,接腳放在LED_R[],4燈,0亮
}//t1_ISR()中斷副程式結束
void t2_ISR(){ //t2計時器中斷副程式,改變七段顯示器狀態
flash(2,SEG,7,1);//呼叫控制亮燈副程式,裝置號2,接腳放在SEG[],7燈,1亮
}//t2_ISR()中斷副程式結束
void setup() { //初值化設定
Serial.begin(9600); //串列埠傳輸鮑率為9600
for(int i=0;i<4;i++) {
pinMode(LED_L[i], OUTPUT); //LED陣列之左側4顆為輸出
digitalWrite(LED_L[i],1); //LED陣列之左側4顆為不亮
pinMode(LED_R[i], OUTPUT); //LED陣列之右側4顆為輸出
digitalWrite(LED_R[i],1); //LED陣列之右側4顆為不亮
}//for迴圈結束
for(int i=0;i<7;i++) {
pinMode(SEG[i], OUTPUT); //七段顯示器之a,b,c,d,e,f,g為輸出
digitalWrite(SEG[i],0); //七段顯示器之a,b,c,d,e,f,g為輸出為不亮
}//for迴圈結束
t0.every(800,t0_ISR);//設定LED左4顆顯示方式,固定每0.8秒,呼叫副程式t0_ISR()
t1.every(400,t1_ISR);//設定LED右4顆顯示方式,固定每0.4秒,呼叫副程式t1_ISR()
t2.every(200,t2_ISR);//設定七段顯示器顯示方式,固定每0.2秒,呼叫副程式t2_ISR()
Serial.println("輸入裝置號碼(0-2)可進入不同模式(0-4)");//印出字串換行
Serial.println("模式0:左至右單燈亮,模式1:左至右逐燈亮");//印出字串換行
Serial.println("模式2:右至左單燈亮,模式3:右至左逐燈亮,模式4:全亮");//印出字串換行
}//初值化設定setup()結束
void loop() {//無窮迴圈
if(Serial.available()){ //若序列埠有輸入
char keyin=Serial.read(); //序列埠輸入之字元紀錄至keyin變數
if(keyin>='0' && keyin<='2') { //若輸入字元為'0'~'2'
int device = keyin-'0'; //輸入之字元'0'~'2'轉成裝置號碼0-2
Serial.print("=>改變裝置號"); //印出字串,不換行
Serial.print(device); //印出要改變之裝置號,不換行
MODE[device]++; //輸入之裝置,進入下一模式
if(MODE[device]>4) //若超出模式範圍(0-4)
MODE[device]=0; //回到模式0
Serial.print("=>至模式"); //印出字串,不換行
Serial.println(MODE[device]); //印出改變裝置之模式,並換行
for(int d=0;d<3;d++){ //印出0:LED左4顆、1:右4顆及2:七段顯示器之模式
Serial.print("裝置");Serial.print(d);//印出裝置號,不換行
Serial.print("目前為模式");Serial.println(MODE[d]);//印出裝置模式,換行
}//for(d=0~2)結束
}//if(keyin='0'~'2')結束
}//if(Serial.available())結束
t0.update(); //檢查更新計時器t0
t1.update(); //檢查更新計時器t1
t2.update(); //檢查更新計時器t2
}//無窮迴圈loop()結束