

#include "dev_flash.h"
#include "string.h"
#include "debug.h"
#include "mystring.h"
#include "elec_judge.h"
#include "interface/CheckerExt.h"
#include "elec_task_slot.h"


// 通用异常判定逻辑


//-- 检测器异常,1
//-- 主电容异常,2
//-- 接触异常,3
//-- 桥丝阻值异常,4
//-- 芯片异常,5
//-- 判定任务缺失,6
//-- 过流,7
//-- 短路,8






// 任务序号校验
#define INDEX_CHECK(index)\
  if(index<0||index>=e->scheme->task_num) {\
    elec_add_errcode(e,6);\
    return ;}
// 任务判定标志校验
#define TASK_FLAG_CHECK(index){\
  if(e->judge_flag[index/8]&(1<<(index%8))){\
    return;}\
  else{\
    e->judge_flag[index/8]|=(1<<(index%8));}}\
// 任务执行结果校验
#define EXE_ACK_CHECK(index)\
  (e->exe_ack[index/8]&(1<<(index%8)))?1:0
// 取任务结果的第index位
#define GET_RET_DATA(i)\
    (data[i*2]|(data[i*2+1]<<8))
// 获取第i位是否置位
#define BIT_CHECK(d,i)\
  ((d)[i/8]&(1<<(i%8)))?1:0


// 添加错误代码
static void elec_add_errcode(elec_judge_def *e,int err)
{
  int index=-1;
  for(int i=0;i<ERR_LIST_LEN;i++){
    if(e->err_list[i]==0){
      if(index<0) index=i;
    }
    if(e->err_list[i]==err){
      return;
    }
  }
  if(index>=0){
    e->err_list[index]=err;
  }
}



// 计算方案有多少个返回值
static int elec_get_ret_num(void)
{
  const scheme_def *s=check_scheme();
  const scheme_task_def *t;
  int index=0;
  for(int i=0;i<s->task_num;i++)
  {
    t=&s->task[i];
    index+=t->item_num;
  }
  return index;
}




// 通用任务判定函数
static void elec_task_judge(elec_judge_def *e,int index,uint8_t *data)
{
  INDEX_CHECK(index);
  TASK_FLAG_CHECK(index);
  const scheme_task_def *task=&e->scheme->task[index];
  uint16_t temp;
  DBG_LOG("task index=%d.",index);
  if(EXE_ACK_CHECK(index)){
    elec_add_errcode(e,task->err);
    DBG_WARN("task execute err:%d.",task->err);
  }
  for(int i=0;i<task->item_num;i++){
    temp=data[i*2]|(data[i*2+1]<<8);
    if(temp<task->range[i].min||temp>task->range[i].max){
      elec_add_errcode(e,task->range[i].err);
      DBG_WARN("task ret_index:%d vaule=%d,err:%d",i,temp,task->range[i].err);
    }
  }
}






// 检测电流
static void elec_current(elec_judge_def *e,int index,uint8_t *data)
{
  INDEX_CHECK(index);
  TASK_FLAG_CHECK(index);
  const scheme_task_def *task=&e->scheme->task[index];
  uint16_t temp,temp2;
  uint16_t short_c=e->short_circuited;
  uint16_t open_c=e->open_circuited;
  DBG_LOG("task index=%d.",index);
  if(EXE_ACK_CHECK(index)){
    elec_add_errcode(e,task->err);
    DBG_WARN("task execute err:%d.",task->err);
  }
  temp=GET_RET_DATA(0);
  temp2=GET_RET_DATA(1);
  DBG_LOG("task curr1:%d,curr2:%d",temp,temp2);
  if((temp<open_c)&&(temp2<open_c))
  {
    // 接触异常
    elec_add_errcode(e,3);
    //DBG_WARN("task ret_index:%d vaule1=%d,vaule12=%d",i,temp,task->range[i].err);
  }
  else if(((temp>task->range[0].max)&&(temp<short_c))||
    ((temp2>task->range[1].max)&&(temp2<short_c)))
  {
    // 过流
    elec_add_errcode(e,7);
  }else if((temp>short_c)&&(temp2>short_c))
  {
    // 短路
    elec_add_errcode(e,8);
  }else{
    if((temp<task->range[0].min||temp>task->range[0].max)||
      (temp2<task->range[1].min||temp2>task->range[1].max))
    {
      // 芯片异常
      elec_add_errcode(e,5);
    }
  }
}








const static elec_judge_fun g_jq_judge_table[]={
elec_task_judge,      //0 电源准备  
elec_task_judge,        //1 上电充能
elec_task_judge,    //2 设置总线电压
elec_current,       //3 获取总线电流
elec_task_judge,    //4 扫描UID
elec_task_judge,    //5 密码验证
elec_task_judge,    //6 读取芯片代码
elec_task_judge,    //7 OTP检测
elec_task_judge,    //8 工厂测试检测
elec_task_judge,    //9 读取状态
elec_task_judge,    //10 写工厂信息
elec_task_judge,    //11 充能统计
elec_task_judge,    //12 充电电压检测
elec_task_judge,    //13 延时等待
elec_task_judge,    //14 设置延时
elec_task_judge,    //15 读取延时
elec_task_judge,    //16 时钟校准
elec_task_judge,    //17 放电
elec_task_judge,    //18 复位
elec_task_judge,    //19 起爆使能
elec_task_judge,    //20 起爆充能
elec_task_judge,    //21 使能通讯末电流采集
elec_task_judge,    //22 获取通讯末电流
elec_task_judge,    //23 写OTP
elec_task_judge,    //24	读OTP
elec_task_judge,    //25 清除起爆计数
elec_task_judge,    //26 关总线
elec_task_judge,    //27 将缓存区数据写入OTP
elec_task_judge,    //28 三码写入错误
elec_task_judge,    //29 三码验证错误
elec_task_judge,    //30 测量电容压差
elec_task_judge,    //31 测量桥丝阻值
elec_task_judge,    //32 使能OTP写
elec_task_judge,    //33 写模块版本
elec_task_judge,    //34 读取版本号
elec_task_judge,    //35 写缓存数据
elec_task_judge,    //36 验证缓存数据
elec_task_judge,
elec_task_judge,
elec_task_judge,
elec_task_judge,
elec_task_judge,
elec_task_judge,
elec_task_judge,
elec_task_judge,
elec_task_judge,
elec_task_judge,
elec_task_judge,
elec_task_judge,
elec_task_judge,    //49
0,
};


const static elec_judge_fun g_xt_judge_table[]={
elec_task_judge,      //0 电源准备  
elec_task_judge,        //1 上电充能
elec_task_judge,    //2 设置总线电压
elec_current,       //3 获取总线电流
elec_task_judge,    //4 扫描UID
elec_task_judge,    //5 写配置参数
elec_task_judge,    //6 验证配置
elec_task_judge,    //7 模拟注码
elec_task_judge,    //8 充能统计
elec_task_judge,    //9 写现场值 网络id 延时
elec_task_judge,    //10比对现场值
elec_task_judge,    //11 桥丝通断检测
elec_task_judge,    //12 电容容量统计
elec_task_judge,    //13 延时等待
elec_task_judge,    //14 写管壳号/工厂信息
elec_task_judge,    //15 写UID
elec_task_judge,    //16 写密码
elec_task_judge,    //17 写入/检测备份区标志
elec_task_judge,    //18 读取备份区数据
elec_task_judge,    //19 校准
elec_task_judge,    //20 使能通讯末电流采集
elec_task_judge,    //21 获取通讯末电流
elec_task_judge,    //22 放电
elec_task_judge,    //23	在线检测
elec_task_judge,    //24 状态检测
elec_task_judge,    //25 起爆
elec_task_judge,    //26 复位
elec_task_judge,    //27 关总线	
elec_task_judge,    //28 芯片锁存
elec_task_judge,    //29 使能赋码设备
elec_task_judge,    //30 在线检测
elec_task_judge,    //31 密码验证
elec_task_judge,    //32 加载芯片配置
elec_task_judge,    //33 电容压差测试
elec_task_judge,    //34 桥丝电阻测试
elec_task_judge,    //35 检测过程中注码
elec_task_judge,    //36 验证注码
elec_task_judge,    //37 模块在线检测
elec_task_judge,    //38 验证管壳码
0,
};



const static elec_judge_fun g_ew_judge_table[]={
elec_task_judge,      //0 电源准备  
elec_task_judge,        //1 上电充能
elec_task_judge,    //2 设置总线电压
elec_task_judge,    //3 扫描UID
elec_task_judge,    //4 写配置参数
elec_current,       //5 获取总线电流
elec_task_judge,    //6 验证配置
elec_task_judge,    //7 模拟注码
elec_task_judge,    //8 充能统计
elec_task_judge,    //9 写现场值 网络id 延时
elec_task_judge,    //10比对现场值
elec_task_judge,    //11 桥丝通断检测
elec_task_judge,    //12 电容容量统计
elec_task_judge,    //13 延时等待
elec_task_judge,    //14 写管壳号/工厂信息
elec_task_judge,    //15 写UID
elec_task_judge,    //16 写密码
elec_task_judge,    //17 写入/检测备份区标志
elec_task_judge,    //18 读取备份区数据
elec_task_judge,    //19 校准
elec_task_judge,    //20 使能通讯末电流采集
elec_task_judge,    //21 获取通讯末电流
elec_task_judge,    //22 放电
elec_task_judge,    //23	在线检测
elec_task_judge,    //24 状态检测
elec_task_judge,    //25 起爆
elec_task_judge,    //26 复位
elec_task_judge,    //27 关总线	
elec_task_judge,    //28 芯片锁存
elec_task_judge,    //29 使能赋码设备
elec_task_judge,    //30 在线检测
elec_task_judge,    //31 密码验证
elec_task_judge,    //32 加载芯片配置
elec_task_judge,    //33 电容压差测试
elec_task_judge,    //34 桥丝电阻测试
elec_task_judge,    //35 检测过程中注码
elec_task_judge,    //36 验证注码
elec_task_judge,    //37 模块在线检测
elec_task_judge,    //38 升级
elec_task_judge,
elec_task_judge,
elec_task_judge,
elec_task_judge,
elec_task_judge,
elec_task_judge,
elec_task_judge,
elec_task_judge,
elec_task_judge,
elec_task_judge,
elec_task_judge,    //49
0,
};


static const elec_judge_fun *g_judge_fun_table[]={g_jq_judge_table,g_xt_judge_table,g_ew_judge_table};

static int elec_calc_judge_fun_num(const elec_judge_fun *table)
{
  int i=0;
  while(table[i]){
    i++;
  }
  return i;
}


// 根据方案获取模块芯片类型
int elec_extract_chip(int id)
{
  const scheme_def *s=check_scheme();
  if(id==0) id=s->plan_id;
  // 日bit0~bit4 月bit5~bit8 年bit9~bit15
  int sid=(id>>0)&0x7f;
  int modele=(id>>7)&0x1f;
  int chip=(id>>12)&0xf;
  int day=(id>>16)&0x1f;
  int month=(id>>21)&0xf;
  int year=((id>>25)&0x7f)+2022;
  return chip;
}



// 根据子错误找到主错误
int elec_err_classify(int err)
{
  const scheme_def *s=check_scheme();
  const marerr_def *marerr;
  if(err<=20){
    return err;
  }
  for(int i=0;i<s->marerr_num;i++){
    marerr=&s->marerr[i];
    for(int j=0;j<marerr->suberr_num;j++){
      if(marerr->suberr[j]==err)
        return marerr->err;
    }
  }
  return err;
}

// 找到异常代码序号
int elec_report_err(elec_judge_def *e)
{
  static const uint8_t pro_table[]={1,3,7,8,2,4,5,6,9,10,20,0};
  uint8_t index=0;
  for (int i=0;i<sizeof(pro_table);i++){
    for(int j=0;j<ERR_LIST_LEN;j++){
      if(e->marerr_list[j]==pro_table[i])
        return j;
      if((index==0)&&(e->marerr_list[j]!=0)){
        index=j;
      }
    }
  }
  return index;
}


static void elec_add_slot_err(elec_judge_def *e)
{
  void *slot=task_slot_init();
  int len=0;
  uint8_t *table=0;
  len=task_slot_err_table(slot,&table);
  for(int i=0;i<len;i++)
  {
    elec_add_errcode(e,table[i]);
  }
}



// 异常判断
// task_num，要判断的任务数
void elec_judge(elec_judge_def *e,int task_num,uint8_t *exe_ack,
  uint8_t *exe_flag,uint8_t *data,uint8_t *marerr,uint8_t *suberr)
{
  const scheme_task_def *task;
  memset(e,0,sizeof(elec_judge_def));
  e->scheme=check_scheme();
  if(e->scheme->plan_id==0xffffffff){
    DBG_WARN("can not find judge params.");
    return;
  }
  e->judge_fun_table=g_judge_fun_table[elec_extract_chip(e->scheme->plan_id)];
  e->judge_fun_num=elec_calc_judge_fun_num(e->judge_fun_table);
  e->short_circuited=1500;
  e->open_circuited=80;
  e->exe_ack=exe_ack;
  if(task_num>e->scheme->task_num)
    task_num=e->scheme->task_num;
  for(int i=0;i<task_num;i++)
  {
    // 只判定已执行的任务
    task=&e->scheme->task[i];
    if(BIT_CHECK(exe_flag,i)){
      if(task->taskid<e->judge_fun_num){
        e->judge_fun_table[task->taskid](e,i,data);
      }else if((task->taskid>=CHECKER_MAXID_COUNT)&&
        (task->taskid<(CHECKER_MAXID_COUNT+CHECKER_EXTID_COUNT)))
      {
        // 忽略扩展任务
      }else{
        elec_add_errcode(e,6);
      }
    }
    data+=task->item_num*2;
  }
  
  elec_add_slot_err(e);
  
  DBG_LOG("err_table:%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
    e->err_list[0],e->err_list[1],e->err_list[2],e->err_list[3],e->err_list[4],
    e->err_list[5],e->err_list[6],e->err_list[7],e->err_list[8],e->err_list[9]
  );
  for(int i=0;i<ERR_LIST_LEN;i++){
    e->marerr_list[i]=elec_err_classify(e->err_list[i]);
  }
  DBG_LOG("err_table2:%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
    e->marerr_list[0],e->marerr_list[1],e->marerr_list[2],e->marerr_list[3],e->marerr_list[4],
    e->marerr_list[5],e->marerr_list[6],e->marerr_list[7],e->marerr_list[8],e->marerr_list[9]
  );
  int index=elec_report_err(e);
  DBG_LOG("marerr report=%d",e->marerr_list[index]);
  DBG_LOG("suberr report=%d",e->err_list[index]);
  if(marerr) *marerr=e->marerr_list[index];
  if(suberr) *suberr=e->err_list[index];
}



