// 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;


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:
      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 > 10){
         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:
      //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 > 50){
         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:
      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 > 50){
         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:
      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 > 50){
         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........................
.............................................................
...........................................................*/
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;
   // Tắt chân TRISTATE
   // delay chớp đèn 1 nhịp dài và 2 nhịp ngắn
   //led_off();
   digitalWrite(OUT_TRISTATE, LOW);   // out kich chan TRISTATE
   // Tắt chân PWRDN
   // delay chớp đèn 1 nhịp dài và 2 nhịp ngắn
   led_off();
   digitalWrite(OUT_PWRDN, LOW);      // out kich chan PWRDN
   // Tắt chân OUT_3VCC
   // delay chớp đèn 1 nhịp dài và 2 nhịp ngắn
// led_off();
//  digitalWrite(OUT_3VCC, LOW);       // out kich nguon 3.3 luoi ic cong suat
   // Tắt chân OUT_52VCC
   // delay chớp đèn 1 nhịp dài và 2 nhịp ngắn
   led_off();
   digitalWrite(OUT_52VCC, LOW);      // out kich nguon 52VCC
   // delay(500);
   // 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 = 200;
     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_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; 
        }
      }
      // nếu đủ điều kiện thì bật hoạt tắt Mute
      if(mute_vale_up > 4){
          digitalWrite(OUT_TRISTATE, HIGH);   //  kích chan TRISTATE
          delayMicroseconds(50);
          mute_vale_up = 0;
          mute_vale_down = 0;
       }
      if((mute_vale_down > 8)){
        //  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(1000);
  }
  // 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(5000);
   auto_shutdown_value = 0;
   delay(100);
  }
 // 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)){

      }
    }
  }
}