// constants won't change. They're used here to set pin numbers:
byte ledPin = 13;           // led bao trang thai
byte ledPinon = 8;          // led bao trang thai nguồn on

// các chân input
const int Button_on_off = 2;    // Nút Bật/Tắt nguồn
const int pin_on_off = 9;       // Chân bật nguồn. 0=Off , 1=on 
const int PVDD_DET_pin = 10;    // Chân nhận tín hiệu PVDD DET Overload
const int DC_DET_pin = 11;      // Chân nhận tín hiệu  DC DET

const int Audio_input_R = A0;    // Chân nhận tín hiệu nhiệt độ IC
const int Audio_input_L = A1;    // Chân nhận tín hiệu nhiệt độ IC
const int TH_WARN_pin = A2;     // Chân nhận tín hiệu nhiệt độ IC
const int DET_52VCC_pin = A3;   // Chân báo điện áp vào 52VCC Cấp IC CS
const int pin_key = A4;         // Bàn phím 
const int pin_IRF_IN = A5;      // Chân IR

// các chân output
const int OUT_IR_OUT = 3;        // out kich chan TRISTATE
const int OUT_TRISTATE = 4;     // out kich chan TRISTATE
const int OUT_PWRDN = 5;        // out kich chan PWRDN
const int OUT_52VCC = 6;        // out kich nguon 52VCC
const int OUT_3VCC = 7;         // out kich nguon 3.3 luôi hệ thống
const int pin_on_off_ic = 12;   // kich nguồn luôi chip

// khai bao bien luu trang thai cac chan dau vao
byte ledState = LOW;         // variable for reading the pushbutton status
byte ledonState = LOW;         // variable for reading the pushbutton status
// enable_power = 0 trạng thái bình thường
// enable_power = 1 trạng thái bật nguồn dùng button
// enable_power = 2 trạng thái tắt nguồn dùng button
// enable_power = 3 trạng thái bật nguồn dùng pin on/off
// enable_power = 4 trạng thái tắt nguồn dùng pin on/off
int enable_power = 0; 
// value_on_off = 0 báo chưa bật nguồn
// value_on_off = 1 báo đã bật nguồn
int value_on_off = 0;
int mute_vale_down = 0;
int mute_vale_up = 0;
// error_power = 0 trạng thái bình thường
// error_power = 1 trạng thái lỗi nguồn 52 VCC
// error_power = 2 trạng thái lỗi Overload
// error_power = 3 trạng thái lỗi DC out
// error_power = 4 trạng thái lỗi high team
int error_power = 0;
// team_DCout = 0 trạng thái bình thường
// team_DCout = 1 trạng thái dò DC không cho phép bật lại nguồn
// chi rút nguồn máy hoặc đợi máy tự tắt nguồn
int team_DCout = 0; 

int team_value_Button = 0;    // Lưu giá trị nhấn phím
int team_value_pin = 0;       // Lưu giá trị on off pin
int auto_shutdown_value = 0;
int team_button = 0;
// pow_busy = 0 nguồn đang hoạt động bình thường
// pow_busy = 1 nguồn đang bận

int pow_busy = 0;

int value_audio_R = 0;
int value_audio_L = 0;

int count_error = 0;
int count_mute = 0;
int mute_vale_down_old = 0;
int mute_vale_up_old = 0;


void setup() {
  // put your setup code here, to run once:
  // khao bao chan output
  pinMode(ledPin, OUTPUT);        // Chân báo led
  pinMode(ledPinon, OUTPUT);      // Chân báo led on
  pinMode(OUT_52VCC, OUTPUT);   // Chân kích hoạt nguồn 52v
  pinMode(OUT_3VCC, OUTPUT);      // Chân khích hoạt nguồn 3v
  pinMode(OUT_PWRDN, OUTPUT);     // Chân kích hoạt IC công suất
  pinMode(OUT_TRISTATE, OUTPUT);  // Chân Mute
  pinMode(OUT_IR_OUT, OUTPUT);    // Chân điều khiển Led IR
  pinMode(pin_on_off_ic, OUTPUT); // Chân điều khiển tắt nguồn toàn hệ thống
  
  // khai bao chan input:
  pinMode(Button_on_off, INPUT);  // chân nhận tín hiệu nút nhấn on/off
  pinMode(PVDD_DET_pin, INPUT);   // chân nhận tín hiệu báo quá tải
  pinMode(DC_DET_pin, INPUT);     // chân nhận tín hiệu báo dò DC
  pinMode(TH_WARN_pin, INPUT);    // chân nhận tín hiệu báo nhiệt độ
  pinMode(DET_52VCC_pin, INPUT);  // chân nhận tín hiệu báo nguồn 52v
  pinMode(pin_on_off, INPUT);     // chân nhận tín hiệu bật tắt
  pinMode(Audio_input_R, INPUT);  // Đọc tín hiệu audio vào
  pinMode(Audio_input_L, INPUT);  // Đọc tín hiệu audio vào
  pinMode(pin_IRF_IN, INPUT);     // Đọc tín hiệu điều khiển hồng ngoại
  pinMode(pin_key, INPUT);        // Đọc bàn phím 

  // khai bao trang thai chan input
  digitalWrite(Button_on_off, LOW);  // trạng thái nut nhấn là Low
  delay(10);
  digitalWrite(pin_on_off, LOW);     // trạng thái chân là Low
  delay(10);  
  digitalWrite(PVDD_DET_pin, LOW);   // trạng thái chân là Low
  delay(10);
  digitalWrite(DC_DET_pin, LOW);     // trạng thái chân là Low
  delay(10);
  digitalWrite(TH_WARN_pin, LOW);    // trạng thái chân là Low
  delay(10);
  digitalWrite(DET_52VCC_pin, LOW);  // trạng thái chânn là Low
  delay(10);
  digitalWrite(pin_IRF_IN, LOW);      // trạng thái chân là Low
  delay(10);
  digitalWrite(Audio_input_R, LOW);  // trạng thái chânn là Low
  delay(10);
  digitalWrite(Audio_input_L, LOW);  // trạng thái chân là Low
  delay(10);
  digitalWrite(pin_key, LOW);      // trạng thái chân là low
  delay(10);

  // khai bao trang thai chan output
  digitalWrite(ledPin, LOW);         // trạng thái chân là Low
  delay(10);
  digitalWrite(ledPinon, LOW);         // trạng thái chân là Low
  delay(10);
  digitalWrite(OUT_52VCC, LOW);      // trạng thái chân là Low
  delay(10);
  digitalWrite(OUT_3VCC, LOW);      // trạng thái chân là Low
  delay(10);
  digitalWrite(OUT_PWRDN, LOW);     // trạng thái chân là Low
  delay(10);
  digitalWrite(OUT_TRISTATE, LOW);  // trạng thái chân là Low
  delay(10);
  digitalWrite(OUT_IR_OUT, LOW);    // trạng thái chân là Low
  delay(10);
  digitalWrite(pin_on_off_ic, HIGH); // trạng thái chân là High
  delay (100);
  // dùng ngắt cạnh xuống làm ngắt khi nhấn phím
  attachInterrupt(0, Power_on_off, FALLING);
  delay(1000);
}

void loop() {
/*....................................................
......................................................
...............Chương Trình Chính.....................
......................................................
.....................................................*/
/*.................Bật Nguồn............................*/
// enable_power = 0 trạng thái bình thường
// enable_power = 1 trạng thái bật nguồn dùng button
// enable_power = 2 trạng thái tắt nguồn dùng button
// enable_power = 3 trạng thái bật nguồn dùng pin on/off
// enable_power = 4 trạng thái tắt nguồn dùng pin on/off
// value_on_off = 0 tức chưa bật nguồn
// error_power = 0 tức không có lỗi
/* ..........................................................*/
/* ....................Bật - Tắt nguồn.......................*/
/* ..........................................................*/
// Bật nguồn
    Power_on_off_pin();  // Bật tắt nguồn bằng chân kích mở nguồn

 if((enable_power == 1)||(enable_power == 3)){
   if((value_on_off == 0)&&(error_power == 0)){
      power_on();
    }
  }
// Tắt nguồn
 if((enable_power==2)||(enable_power==4)){
    power_off();      // Tắt máy
   //if((value_on_off == 1)){power_off();}
  }
// Nếu máy không bị lỗi thì kiểm tra các chức năng
// nếu máy bị lỗi thì máy đã dừng hoạt đoạt, nên không cần phải kiểm tra
 if(error_power == 0){
    check_52v();         // kiểm tra nguồn 52v
    check_overload();    // kiểm tra overload
    check_DC_out();      // kiểm tra DC out
    check_temperature(); // kiểm tra nhiệt độ
    check_audio_Mute();  // Check kiểm tra Mute
    //Key_input();       // Quét bàn phím
  }
  auto_shutdown();    // tự động tắt máy
 /* Bảng mã lỗi
 Đèn nhấp nháy liên tục báo đang bật nguồn
 Đèn sáng trong 5 giây sau đó đèn chớp tắt 2 lần báo đang tắt nguồn
 Đèn sáng trong 5 giây sau đó đèn chớp tắt 5 lần báo lỗi Overload
 Đèn sáng trong 5 giây sau đó đèn chớp tắt 7 lần báo lỗi nguồn 52v
 Đèn sáng trong 5 giây sau đó đèn chớp tắt 10 lần báo lỗi DC out
 Đèn sáng trong 5 giây sau đó đèn chớp tắt 12 lần báo lỗi nhiệt độ cao
 */
 
 switch (error_power) {
    case 1: // Báo lỗi nguồn 52v
      count_error = count_error + 1;
      error_52v_activate();     // gọi gọi hàm error 52v
      // sau 50 lần lặp lại báo lỗi. 
      // nếu máy vẫn đang ở chế độ lỗi(chưa bấm nút nguồn để tắt)
      // thi tự động reset lại máy
      if (count_error > 100){
         error_power = 0;     // Reset error_power
         value_on_off = 0;    // Reset value_on_off
         count_error = 0;     // Reset count_error
         power_on();          // Bật lại nguồn
        }
      break;
    case 2: // báo lỗi overload
      //gọi gọi hàm error Overload
      count_error = count_error + 1;
      error_overload_activate();     //gọi gọi hàm error 52v
      // sau 50 lần lặp lại báo lỗi. 
      // nếu máy vẫn đang ở chế độ lỗi(chưa bấm nút nguồn để tắt)
      // thi tự động reset lại máy
      if (count_error > 100){
         error_power = 0;       // Reset error_power
         value_on_off = 0;      // Reset value_on_off
         count_error = 0;       // Reset count_error
         power_on();            // Bật lại nguồn
        }
      break;

    case 3: // báo lỗi DC out
      count_error = count_error + 1;
      error_dc_out_activate();     //gọi gọi hàm error DC out
      // sau 50 lần lặp lại báo lỗi. 
      // nếu máy vẫn đang ở chế độ lỗi(chưa bấm nút nguồn để tắt)
      // thi tự động reset lại máy
      if (count_error > 100){
         error_power = 0;       // Reset error_power
         value_on_off = 0;      // Reset value_on_off
         count_error = 0;       // Reset count_error
         power_off();           // Tắt nguồn
        }
      break;

    case 4: // báo lỗi nhiệt độ cao
      count_error = count_error + 1;
      error_temperature_high_activate();   //gọi gọi hàm error high Team
      // sau 50 lần lặp lại báo lỗi. 
      // nếu máy vẫn đang ở chế độ lỗi(chưa bấm nút nguồn để tắt)
      // thi tự động reset lại máy
      if (count_error > 100){
         error_power = 0;       // Reset error_power
         value_on_off = 0;      // Reset value_on_off
         count_error = 0;       // Reset count_error
         power_on();            // Bật lại nguồn
        }
      break;
    default: 
      // mặc định là không làm gì cả
      // bạn có thể có default: hoặc không
      break;
  }
}

/*...........................................................
.............................................................
.....................Chương Trình Con........................
.............................................................
...........................................................*/
// nhận phím bật nguồn
void Power_on_off(){
/* ...................Bật nguồn..........................
        enable_power = 0 trạng thái bình thường
        enable_power = 1 trạng thái bật nguồn dùng button
        enable_power = 2 trạng thái tắt nguồn dùng button 
        kiểm tra máy đang ở trạng thái nào, nếu đang trạng thái tắt
        nguồn thì chuyển sang bặt nguồn bằng nút nhấn
        ....................................................... */
/* ...................Bật nguồn..........................*/
// máy không bị lỗi và nguồn chưa bật thì cho phép bật nguồn
 if((enable_power == 0)&&(error_power == 0)&&(value_on_off == 0)&&(pow_busy == 0)){
   // Nếu không dò nguồn DC thì cho phép bật máy
   if(team_DCout == 0){enable_power = 1;}

  }
 /* ...................Tắt nguồn..........................*/
 // nếu máy đang bật thì tắt máy
 if((enable_power == 1)||(enable_power == 3)){
   if ((value_on_off == 1)&&(pow_busy == 0)){
      enable_power = 2;  // tắt nguồn
      // cho phép tắt máy khi nguồn lỗi
      // không cho phép tắt máy khi dò nguồn DC
      //if (error_power != 3) {error_power = 0;}  
      error_power = 0;
    }
 }
  /* ...................Tắt nguồn..........................*/
 // nếu máy đang bật thì tắt máy
 if((enable_power == 1)||(enable_power == 3)){
   if ((error_power != 0)&&(pow_busy == 0)){
      enable_power = 2;  // tắt nguồn
      // cho phép tắt máy khi nguồn lỗi
      // không cho phép tắt máy khi dò nguồn DC
      //if (error_power != 3) {error_power = 0;}  
      error_power = 0;
    }
 }
}
// thay hàm delay để thực hiện quét các chức năng khác khi bật nguồn
void delay_scan_input(int value_in){
  ledState = HIGH; 
  // ledonState = LOW;
  for(int i = 0; i <= 5; i++){
   for(int j = 0; j <= value_in; j++){
     // thực hiện việc quét các input đầu vào 
     check_52v();             // Kiểm tra nguồn 52v
     check_overload();        // Kiểm tra Overload
     check_DC_out();          // Kiểm tra Overload
     //check_temperature();   // Bật máy không cần kiểm tra nhiệt độ
     delayMicroseconds(100);
     if(error_power !=0)break;   // nếu có lỗi sảy ra thì thoát khỏi vòng lặp
    }
    check_temperature();   // Kiểm tra nhiệt độ
   //ledState = HIGH; 
   ledState = !ledState;            // đảo trạng thái led
   digitalWrite(ledPin, ledState);  // suất ra led
   //delay(1000);
   ledonState = !ledonState;
   digitalWrite(ledPinon, ledonState);  // suất ra led
   // delay(1000);
   if(error_power !=0)break;   // nếu có lỗi nguồn sảy ra thì thoát khỏi delay
  }
}

// Bat nguon
void power_on(){
   // Bật nguồn ic công xuất cần tuân theo trình tự sau
   // Bật nguồn 52v cấp cho ic công xuất
   // Bật nguồn 3.3v cấp cho ic công xuất
   // Kích chân PWRDN của ic công suất
   // Kích chân TRISTATE của ic công suất
   pow_busy = 1; // đưa nguồn về chế độ đang mở, không nhận phím
   delayMicroseconds(100);
   digitalWrite(pin_on_off_ic, HIGH);  // Bật nguồn hệ thống
   delay_scan_input(5000);             // báo đèn trước khi bật nguồn
   // Mở nguồn 3v3
   digitalWrite(OUT_3VCC, HIGH);   // kich nguon 3.3 luoi ic cong suat
   delay_scan_input(5000);         // delay và scan thông tin nguồn
   delay_scan_input(5000);         // delay và scan thông tin nguồn
   delay_scan_input(5000);         // delay và scan thông tin nguồn

   digitalWrite(OUT_52VCC, HIGH);      // out kich nguon 52VCC
   delay_scan_input(5000);             // delay và scan thông tin nguồn
   //delay_scan_input(5000);           // delay và scan thông tin nguồn
   // khi value_on_off = 0 hàm delay_scan_input chỉ là hàm delay
   // khi value_on_off = 1 hàm delay_scan_input là hàm delay và scan thông tin nguồn
   value_on_off = 1;                   // Báo nguồn đã bật
   delay_scan_input(5000);             // delay và scan thông tin nguồn
   delay_scan_input(5000);             // delay và scan thông tin nguồn
   // nếu nguồn không bị lỗi thì mở OUT_PWRDN
   if (error_power == 0){digitalWrite(OUT_PWRDN, HIGH);}  // kich chan PWRDN
   delay_scan_input(5000);         // delay và scan thông tin nguồn
   // if (error_power == 0){digitalWrite(OUT_TRISTATE, HIGH);}  //  kich chan TRISTATE
   // delay_scan_input(500);
   digitalWrite(ledPin, LOW);     // 
   digitalWrite(ledPinon, HIGH);  // bật đèn báo nguồn đã bật
   delay(300);
   pow_busy = 0;  // nguồn bình thường được phép nhận nhận phím
   delay(300);
  }
// Tắt nguồn
void power_off(){
   // Tắt nguồn ic công xuất cần tuân theo trình tự sau
   // Tắt chân TRISTATE của ic công suất
   // Tắt chân PWRDN của ic công suất
   // Tắt nguồn 3.3v cấp cho ic công xuất
   // Tắt nguồn 52v cấp cho ic công xuất   
   pow_busy = 1; // đưa nguồn về chế độ đang mở, không nhận phím
   delayMicroseconds(100);
   digitalWrite(ledPin, LOW);
   digitalWrite(ledPinon, LOW);
   ledState = LOW;
   ledonState = LOW;
   //led_off();   // delay chớp đèn 1 nhịp dài và 2 nhịp ngắn
   digitalWrite(OUT_TRISTATE, LOW);   // Tắt chân TRISTATE
   led_off();   // delay chớp đèn 1 nhịp dài và 2 nhịp ngắn
   digitalWrite(OUT_PWRDN, LOW);      // Tắt chân PWRDN
   led_off();   // delay chớp đèn 1 nhịp dài và 2 nhịp ngắn
   digitalWrite(OUT_52VCC, LOW);      // Tắt chân OUT_52VCC
   // tiếp tục nháy đèn thêm 20 lần với tốc độ nhanh hơn
   for(int i = 0; i <= 8; i++){
     ledState = !ledState;
     digitalWrite(ledPin, ledState);
     ledonState = !ledonState;
     digitalWrite(ledPinon, ledonState);
     delay(500);
      for(int j = 0; j <= 4; j++){
        ledState = !ledState;
        digitalWrite(ledPin, ledState);
        ledonState = !ledonState;
        digitalWrite(ledPinon, ledonState);
        delay(200);
      }
    }
    digitalWrite(ledPin, LOW);
    digitalWrite(ledPinon, LOW);  // suất ra led
    enable_power = 0; // báo máy đã tắt
    delay(300);
    value_on_off = 0; // báo nguồn đã tắt
    delay(300);
    pow_busy = 0;  // nguồn bình thường được phép nhận nhận phím
    delayMicroseconds(100);
    count_error = 0;  // Reset count_error
    delay(300);
 }
// báo led khi tắt nguồn
void led_off(){
  for(int i = 0; i <= 2; i++){
     ledState = !ledState;
     digitalWrite(ledPin, ledState);
     ledonState = !ledonState;
     digitalWrite(ledPinon, ledonState);
     delay(1000);
     for(int j = 0; j <= 4; j++){
       delay(300);
       ledState = !ledState;
       digitalWrite(ledPin, ledState);
       ledonState = !ledonState;
       digitalWrite(ledPinon, ledonState);
      }
    }
  }
// Bật nguồn bằng chân điện áp 
void Power_on_off_pin(){
   /*..............................................................
   nếu pin on/off kích hoạt. kiểm tra máy đang bật hay không.
   nếu máy đang bật, thì bỏ qua
   nếu máy tắt thì thực hiện tiếp
   ..............................................................*/
   if (digitalRead(pin_on_off)==HIGH){    
      if(enable_power == 0){
       int j = 0;
       for(int i=0;i<=10;i++){
         if (digitalRead(pin_on_off) == HIGH){
           delayMicroseconds(200);
           j++;
          }
         }
       // sau 10 lần quét phím nếu số lần nhận được button ở mức thấp > 3
       // thì đưa team_value_Button = 1. báo button đã được nhấn.
       if (j>5){
        // dò nguồn DC thì không cho mở nguồn lại
        if(team_DCout == 0){ enable_power = 3;}
        j = 0;
       }
      }
    }
    // kiểm tra tắt nguồn
   if (digitalRead(pin_on_off)==LOW){    
      if(enable_power == 3){
       int j = 0;
       for(int i=0;i<=10;i++){
         if (digitalRead(pin_on_off) == LOW){
           delayMicroseconds(200);
           j++;
          }
        }
       // sau 10 lần quét phím nếu số lần nhận được button ở mức thấp > 3
       // thì đưa team_value_Button = 1. báo button đã được nhấn.
       if (j>5){
         enable_power = 4;
          j = 0;
       }
      }
    }
  }
/*.......................................................................*/
/*......................Hàm kiểm tra nguồn 52v...........................*/
/*.......................................................................*/
 /*........................Check nguồn 52................................
 nếu máy đang chạy, kiểm tra nguồn 52v có hay không nếu không có tắt máy
 và chuyển sang nỗi error_power = 1 báo lỗi 52v
 .......................................................................*/
void check_52v(){
  if((digitalRead(DET_52VCC_pin) == LOW)&&(value_on_off == 1)&&(error_power == 0)){
    if((enable_power == 1)||(enable_power == 3)){
      int j = 0;
      for(int i=0;i<=10;i++){
       if (digitalRead(DET_52VCC_pin) == LOW){
         delayMicroseconds(200);
         j++;
        }
      }
      // Nếu chân 52v ở mức thấp tiến hành tắt máy và báo lỗi
      if (j>3){
       digitalWrite(OUT_TRISTATE, LOW);   // ngưng kích kich chan TRISTATE
       delayMicroseconds(100);
       digitalWrite(OUT_PWRDN, LOW);      // ngưng kích kich chan PWRDN
       delayMicroseconds(100);
       digitalWrite(OUT_52VCC, LOW);      // tắt nguồn 52VCC
//       digitalWrite(OUT_3VCC, LOW);       // tắt nguồn 3.3 luoi ic cong suat
       delay(100);
       digitalWrite(ledPinon, LOW);  // suất ra led
       value_on_off = 0;      // Reset value_on_off
       error_power = 1;      // báo lỗi 52v
       j = 0;                // Reset j
        //delay(2000);
      }
    }
  }
}
// Hiển thị báo mã lỗi
// mã lỗi khi mất nguồn 52v
void error_52v_activate(){
   // sáng trong 5 giây sau đó đèn chớp tắt 7 lần thể hiện mã lỗi
   digitalWrite(ledPinon, LOW);
   digitalWrite(ledPin, HIGH);
   //delay(5000);
   // delay và kiểm tra san input
    for(int i=0; i<=10000;i++){
      delayMicroseconds(100);
      if(error_power == 0)break;
    }
   // chop tat den 7 lan
   for (int j=1; j<=16; j++){
     // delay và kiểm tra san input
     for(int i=0; i<=2000;i++){
       delayMicroseconds(100);
       if(error_power == 0)break;
      }
     ledState = !ledState;
     digitalWrite(ledPin, ledState);
     if(error_power == 0)break;
    }
 }

/*.......................................................................*/
/*......................Hàm kiểm tra Overload............................*/
/*......................................................................*/
 /*........................Check Overload................................
 nếu máy đang chạy, kiểm tra Overload nếu máy đang lỗi Overload thì tắt máy
 và chuyển sang nỗi error_power = 2 báo lỗi Overload
 .......................................................................*/
void check_overload(){
  if((digitalRead(PVDD_DET_pin) == LOW)&&(value_on_off == 1)&&(error_power == 0)){
    if((enable_power == 1)||(enable_power == 3)){
      int j = 0;
      for(int i=0;i<=10;i++){
        if (digitalRead(PVDD_DET_pin) == LOW){
          delayMicroseconds(200);
          j++;
        }
      }
      // Nếu chân overload ở mức thấp tiến hành tắt máy và báo lỗi
      if (j>3){
       digitalWrite(OUT_TRISTATE, LOW);   // ngưng kích kich chan TRISTATE
       delayMicroseconds(100);
       digitalWrite(OUT_PWRDN, LOW);      // ngưng kích kich chan PWRDN
       delayMicroseconds(100);
       digitalWrite(OUT_52VCC, LOW);      // tắt nguồn 52VCC
//       digitalWrite(OUT_3VCC, LOW);       // tắt nguồn 3.3 luoi ic cong suat
       delay(100);
       digitalWrite(ledPinon, LOW);  // suất ra led
       value_on_off = 0;      // Reset value_on_off
       error_power = 2;      // báo lỗi overload
       j = 0;                // Reset j
      }
    }
  }
}
// Báo lỗi Overload
void error_overload_activate(){
   // sáng trong 5 giây sau đó đèn chớp tắt 5 lần thể hiện mã lỗi
   digitalWrite(ledPinon, LOW);
   digitalWrite(ledPin, HIGH);
   //delay(5000);
   // delay và kiểm tra san input
    for(int i=0; i<=10000;i++){
      delayMicroseconds(100);
      if(error_power == 0)break;
    }
   // chop tat den 5 lan
   for (int j=1; j<=12; j++){
     // delay và kiểm tra san input
     for(int i=0; i<=2000;i++){
       delayMicroseconds(100);
       if(error_power == 0)break;
     }
     ledState = !ledState;
     digitalWrite(ledPin, ledState);
     if(error_power == 0)break;
    }
  }
/*.......................................................................*/
/*........................Hàm kiểm tra DC Out............................*/
/*.......................................................................*/
/*............................Check DC Out................................
nếu máy đang chạy, kiểm tra DC Out nếu máy đang lỗi DC Out thì tắt máy
và chuyển sang nỗi error_power = 3 báo lỗi DC out.
với lỗi này không cho phép tắt máy 
........................................................................*/ 
void check_DC_out(){
  if((digitalRead(DC_DET_pin) == LOW)&&(value_on_off == 1)&&(error_power == 0)){
    if((enable_power == 1)||(enable_power == 3)){
      int j = 0;
      for(int i=0;i<=10;i++){
        if (digitalRead(DC_DET_pin) == LOW){
          delayMicroseconds(200);
          j++;
        }
      }
      // Nếu chân DC Out ở mức thấp tiến hành tắt máy và báo lỗi
      if (j>3){
       digitalWrite(OUT_TRISTATE, LOW);   // ngưng kích kich chan TRISTATE
       delayMicroseconds(100);
       digitalWrite(OUT_PWRDN, LOW);      // ngưng kích kich chan PWRDN
       delayMicroseconds(100);
       digitalWrite(OUT_52VCC, LOW);      // tắt nguồn 52VCC
//       digitalWrite(OUT_3VCC, LOW);       // tắt nguồn 3.3 luoi ic cong suat
       delay(100);
       digitalWrite(ledPinon, LOW);  // suất ra led
       delayMicroseconds(100);
       value_on_off = 0;      // Reset value_on_off
       error_power = 3;              // báo lỗi DC out ra loa
       delayMicroseconds(100);
       team_DCout = 1;              // Lưu giá trị DCout
       delayMicroseconds(100);
       j = 0;                  // Reset j

      }
    }
  }
}
// báo loi DC out
void error_dc_out_activate(){
   // sáng trong 5 giây sau đó đèn chớp tắt 10 lần thể hiện mã lỗi
   digitalWrite(ledPinon, LOW);
   digitalWrite(ledPin, HIGH);
   //delay(5000);
   // delay và kiểm tra san input
    for(int i=0; i<=10000;i++){
      delayMicroseconds(100);
      if(error_power == 0)break;
    }
   // chop tat den 10 lan
   for (int j=1; j<=22; j++){
     // delay và kiểm tra san input
     for(int i=0; i<=2000;i++){
       delayMicroseconds(100);
       if(error_power == 0)break;
     }
     ledState = !ledState;
     digitalWrite(ledPin, ledState);
     if(error_power == 0)break;
    }
  }
 /*......................................................................*/
/*.......................Hàm kiểm tra nhiệt độ...........................*/
/*.......................................................................*/
/*........................................................................
nếu máy đang chạy, kiểm tra nhiệt độ IC công suất nếu nhiệt độ cao thì tắt máy
và chuyển sang nỗi error_power = 4 báo lỗi nhiệt độ cao.
với lỗi này không cho phép bật máy 
........................................................................*/
void check_temperature(){
  if((value_on_off == 1)&&(error_power == 0)){
    if((enable_power == 1)||(enable_power == 3)){
     int value_temperature = 0;
     for(int i=1; i<=2; i++){
       value_temperature = value_temperature + analogRead(TH_WARN_pin);
       delayMicroseconds(300);
     }
     value_temperature = value_temperature/2;
     // Nếu giá trị nhiệt độ quá cao tiến hành tắt máy và báo lỗi
      if (value_temperature < 400){
       digitalWrite(OUT_TRISTATE, LOW);   // ngưng kích kich chan TRISTATE
       delayMicroseconds(100);
       digitalWrite(OUT_PWRDN, LOW);      // ngưng kích kich chan PWRDN
       delayMicroseconds(100);
       digitalWrite(OUT_52VCC, LOW);      // tắt nguồn 52VCC
       // digitalWrite(OUT_3VCC, LOW);    // tắt nguồn 3.3 luoi ic cong suat
       delay(100);
       digitalWrite(ledPinon, LOW);  // suất ra led
       value_on_off = 0;      // Reset value_on_off
       error_power = 4;      // báo lỗi nhiệt độ cao
       delayMicroseconds(100);
      }
    }
  }
}
// báo loi nhiệt độ cao
void error_temperature_high_activate(){
   // sáng trong 5 giây sau đó đèn chớp tắt 12 lần thể hiện mã lỗi
   digitalWrite(ledPinon, LOW);
   digitalWrite(ledPin, HIGH);
   //delay(5000);
   // delay và kiểm tra san input
    for(int i=0; i<=10000;i++){
      delayMicroseconds(100);
      if(error_power == 0)break;
    }
   // chop tat den 12 lan
   for (int j=1; j<=26; j++){
     // delay và kiểm tra san input
     for(int i=0; i<=2000;i++){
       delayMicroseconds(100);
       if(error_power == 0)break;
     }
     ledState = !ledState;
     digitalWrite(ledPin, ledState);
     if(error_power == 0)break;
    }
 }
/*......................................................................*/
/*...........................Hàm kiểm Mute..............................*/
/*......................................................................*/
/*........................Check tín hiệu audio vào........................
nếu máy đang ở chế độ hoạt động bình thường thì thực hiện kiểm tra tín hiệu
audio đầu vào. có cả 2 tín hiệu audio nhỏ hơn tín hiệu cho phép thì đưa máy
về chế độ Mute.
lưu ý: tín hiệu đầu vào phải lớn hơn tín hiệu cho phép, các tín hiệu nhỏ hơn
được xem như là nhiễu và bỏ qua. 
........................................................................*/
void check_audio_Mute(){
  analogReference(DEFAULT);  // Đặt lại mức điện áp tối đa  5v hoặc 3v3 tùy vào nguồn cấp
 // analogReference(INTERNAL); // Đặt lại mức điện áp tối đa  là 1,1 V
 // analogReference(EXTERNAL); // sử dụng chân AREF làm điện áp tham chiếu khoản từ 0-5V
  delayMicroseconds(300);
  if((value_on_off == 1)&&(error_power == 0)){
    if((enable_power == 1)||(enable_power == 3)){
      // biến bỏ qua nhiễu
      // vcc = 1023
      // V singnal =  value_signal * vcc /1023
     int value_signal = 100;
     for(int j=1; j<=10; j++){
       value_audio_R = 0;
       value_audio_L = 0;
       for(int i=1; i<=2; i++){ // quét tín hiệu audio đầu vào
         value_audio_R = value_audio_R + analogRead(Audio_input_R);
         value_audio_L = value_audio_L + analogRead(Audio_input_L);       
        }
        // lấy trung bình tín hiệu đầu vào
        value_audio_R = value_audio_R/2;
        value_audio_L = value_audio_L/2;    
        // thiết lập mức tín hiệu cho phép 20*5/1024 = 0.1v
        // audio là tín hiệu ở giữa 
        // 1024/2=512
       if ((value_audio_R > 512 + value_signal)||(value_audio_L > 512 + value_signal)){
         // mute_vale_up sử dụng làm biến tạm để lưu số lần đủ điều kiện
         // mute_vale_up đủ điều kiện 10 lần mới mở để chống nhiễu biên độ cao
         mute_vale_up = mute_vale_up + 1;  
        }
       if ((value_audio_R < 512 - value_signal)||(value_audio_L < 512 - value_signal)){
         // mute_vale_down sử dụng làm biến tạm để lưu số lần đủ điều kiện
         // mute_vale_down đủ điều kiện 10 lần mới chuyển chế độ Mute để chánh
         // hiện tượng tiếng không đều(nất tiếng) khi âm lượng nhạc nhỏ
         mute_vale_up = mute_vale_up + 1;  
        }
       if ((value_audio_R > 512 - value_signal)&&(value_audio_R < 512 + value_signal)){
         // mute_vale_up sử dụng làm biến tạm để lưu số lần đủ điều kiện
         // mute_vale_up đủ điều kiện 10 lần mới mở để chống nhiễu biên độ cao
         mute_vale_down = mute_vale_down + 1; 
        }
        if ((value_audio_L > 512 - value_signal)&&(value_audio_L < 512 + value_signal)){
         // mute_vale_up sử dụng làm biến tạm để lưu số lần đủ điều kiện
         // mute_vale_up đủ điều kiện 10 lần mới mở để chống nhiễu biên độ cao
         mute_vale_down = mute_vale_down + 1; 
        }
        /*
        Hàm dùng để Reset các giá trị audio nhiễu đã đọc được.
        sau khi đọc giữ liệu của audio lưu lại giá trị đó.
        nếu giá trị audio đọc được liên tục là giá trị mute 
        thì các giá trị đọc được trước đó xem như nhiễu
        */
        count_mute = count_mute + 1;
        if(count_mute == 5){
          mute_vale_down_old = mute_vale_down;
          mute_vale_up_old = mute_vale_up;
        }
        if(count_mute == 10){
          count_mute = 0;     // Reset count_mute
          // nếu sau 5 lần quét mà giá trị của am lượng cũ không đổi thì xem như là nhiễu
          /*
          sau khi đọc giữ liệu của audio lưu lại giá trị đó.
          nếu giá trị audio đọc được liên tục là giá trị mute 
          thì các giá trị audio đọc được trước đó xem như nhiễu
          */
          if(mute_vale_up_old > mute_vale_up - 2 ){
              mute_vale_up = 0;     // Reset mute_vale_up
            }
          // nếu sau 5 lần quét mà giá trị của am lượng cũ không đổi thì xem như là nhiễu
          /*
          sau khi đọc giữ liệu của audio lưu lại giá trị đó.
          nếu giá trị audio đọc được liên tục là giá trị audio 
         thì các giá trị mute đọc được trước đó xem như nhiễu
          */
          if(mute_vale_down_old > mute_vale_down - 2 ){
          mute_vale_down = 0;   // Reset mute_vale_down
          }
        }
      }
      // nếu đủ điều kiện thì bật hoạt tắt Mute
      if(mute_vale_up > 100){
          digitalWrite(OUT_TRISTATE, HIGH);   //  kích chan TRISTATE
          delayMicroseconds(50);
          mute_vale_up = 0;
          mute_vale_down = 0;
       }
      if((mute_vale_down > 1000)){
        //  mute_vale_down = mute_vale_down + 1;
        digitalWrite(OUT_TRISTATE, LOW);   // ngưng kích kich chan TRISTATE
        delayMicroseconds(50);
        mute_vale_down = 0;
        mute_vale_up = 0;
      }
    }
  }
}
/*......................................................................*/
/*.........................Hàm Tự Động Tắt Máy..........................*/
/*......................................................................*/
/*.......................................................................
nếu máy ở trạng thái bình thường thì tiến hành đến kiểm tra
sau 5 phút không sử dụng thì tắt hệ thống nguồn
........................................................................*/
void auto_shutdown(){
  // Tắt nguồn 3.3v
  if((auto_shutdown_value == 2)||(auto_shutdown_value > 5)){
   digitalWrite(OUT_3VCC, LOW); // tắt nguồn hệ thống
   delay(500);
  }
  // thoi gian tat he thong la 5 phut
  if((auto_shutdown_value == 5)||(auto_shutdown_value > 5)){
   digitalWrite(pin_on_off_ic, LOW); // tắt nguồn hệ thống
   delay(500);
   auto_shutdown_value = 0;
   delay(15000);
  }
 // enable_power = 0 trạng thái bình thường
 // value_on_off = 0 báo chưa bật nguồn
 // error_power = 0 trạng thái bình thường
 if((enable_power == 0)&&(value_on_off == 0)&&(error_power == 0)){
    auto_shutdown_value = auto_shutdown_value + 1;
    for(int i=0; i<=600; i++){ // vong lap keo dai 1 phut
      // kiểm trả chân kích mở nguồn
      Power_on_off_pin();
      delay(100);
      // Thoát khỏi vòng lặp khi nhấn phím
      // nếu ở trạng thái DC out thì không cho thoát khỏi vòng lặp
      // chi rút nguồn máy hoặc đợi máy tự tắt nguồn
      // team_DCout = 0, máy không ở trạng thái DC out
      // nếu máy ở trạng thái mở nguồn thì thoát khỏi vòng lặp
      if((enable_power != 0)||(value_on_off != 0)||(error_power != 0)){
        if(team_DCout == 0){ // nếu máy không phải DC out thì cho thoát khỏi vòng lặp
          auto_shutdown_value = 0;
          break;
        }
      }
    }
  }else{
    auto_shutdown_value = 0;
  }
}
/*......................................................................*/
/*................................Hàm Key...............................*/
/*......................................................................*/
// pin_key = A4;         // Bàn phím 
void Key_input(){
  // pin_key sẽ luôn ở mức cao
  //analogReference(DEFAULT);  // Đặt lại mức điện áp tối đa  5v hoặc 3v3 tùy vào nguồn cấp
  //analogReference(INTERNAL); // Đặt lại mức điện áp tối đa  là 1,1 V
  //analogReference(EXTERNAL); // sử dụng chân AREF làm điện áp tham chiếu khoản từ 0-5V
  //delayMicroseconds(300);
  if((value_on_off == 1)&&(error_power == 0)){
    // 
    if((enable_power == 1)||(enable_power == 3)){
     int value_key = 0;
     for(int i=1; i<=4; i++){
       value_key = value_key + analogRead(pin_key);
     }
     value_key = value_key/4;

      // 1. Giá trị ADC đọc được  từ 30 đến 60 là phím power 
      if ((value_key > 30)&&(value_key < 60)){

      }
      // 2. Giá trị ADC đọc được  từ 90 đến 120 là phím chức năng 
      if ((value_key > 90)&&(value_key < 120)){

      }
      // 3. Giá trị ADC đọc được  từ 150 đến 180 là phím volume + 
      if ((value_key > 150)&&(value_key < 180)){

      }
      // 4. Giá trị ADC đọc được  từ 210 đến 240 là phím volume - 
      if ((value_key > 210)&&(value_key < 240)){

      }
      // 5. Giá trị ADC đọc được  từ 270 đến 300 là phím play 
      if ((value_key > 270)&&(value_key < 300)){

      }
      // 6. Giá trị ADC đọc được  từ 330 đến 360 là phím stop 
      if ((value_key > 330)&&(value_key < 360)){

      }
      // 7. Giá trị ADC đọc được  từ 390 đến 420 là phím next 
      if ((value_key > 390)&&(value_key < 420)){

      }
      // 8. Giá trị ADC đọc được  từ 450 đến 480 là phím rev 
      if ((value_key > 450)&&(value_key < 480)){

      }
      // 9. Giá trị ADC đọc được  từ 510 đến 540 là phím  
      if ((value_key > 510)&&(value_key < 540)){

      }
      // 10. Giá trị ADC đọc được  từ 570 đến 600 là phím  
      if ((value_key > 570)&&(value_key < 600)){

      }
      // 11. Giá trị ADC đọc được  từ 630 đến 660 là phím power 
      if ((value_key > 630)&&(value_key < 660)){

      }
      // 12. Giá trị ADC đọc được  từ 690 đến 720 là phím power 
      if ((value_key > 690)&&(value_key < 720)){

      }
      // 13. Giá trị ADC đọc được  từ 750 đến 780 là phím power 
      if ((value_key > 750)&&(value_key < 780)){

      }
      // 14. Giá trị ADC đọc được  từ 810 đến 840 là phím power 
      if ((value_key > 810)&&(value_key < 840)){

      }
      // 15. Giá trị ADC đọc được  từ 870 đến 900 là phím power 
      if ((value_key > 870)&&(value_key < 900)){

      }
      // 16. Giá trị ADC đọc được  từ 930 đến 960 là phím power 
      if ((value_key > 930)&&(value_key < 960)){

      }
    }
  }
}