大理水控初始版本
diff --git a/supwisdom/sp_consume.c b/supwisdom/sp_consume.c
new file mode 100644
index 0000000..587e2a4
--- /dev/null
+++ b/supwisdom/sp_consume.c
@@ -0,0 +1,729 @@
+#include "sp_util.h"
+#include "sp_constant.h"
+#include "sp_display.h"
+#include "sp_flash.h"
+#include "sp_card.h"
+#include "sp_des.h"
+#include "sp_msgpack.h"
+#include "sp_menu.h"
+#include "sp_data.h"
+#include "sp_consume.h"
+#include "sp_communicate.h"
+
+static int count = 0;
+static uint16 sp_calc_payamt_by_flowsensor(sp_pos_t* pos, sp_card_t* card)
+{
+  uint32 usedcount = 0;
+
+  if(pos->purchase.paid_num < 1)
+  {
+    //Ê×ÏÈÔ¤¿ÛÒ»±Ê
+    if(card->feepara.fee_start > 0)
+    {
+      //ǰnË®Ãâ·Ñ
+      pos->purchase.prepaid_num = card->feepara.fee_start;
+      pos->purchase.prepaid_amt = 0;
+    }
+    else
+    {
+      pos->purchase.prepaid_num = card->feepara.fee_unit;
+      pos->purchase.prepaid_amt = card->feepara.fee_amt;
+    }
+    pos->purchase.used_num = 0;
+    return 0;
+  }
+  //usedcount = sp_flowsensor_get_count()/pos->sysconf.flowsensor_uint;
+  usedcount = count/pos->sysconf.flowsensor_unit;
+  count++;
+  if(usedcount < pos->purchase.paid_num)
+  {
+    //ûÓдﵽ¿Û·ÑÁ÷Á¿
+    return 0;
+  }
+  pos->purchase.used_num = pos->purchase.paid_num;
+  pos->purchase.prepaid_num = card->feepara.fee_unit;
+  pos->purchase.prepaid_amt = card->feepara.fee_amt;
+  return 0;
+}
+
+//¼ÇÕËģʽÏû·Ñ
+uint16 sp_account_purchase(uint16 amount)
+{
+  return 0;
+}
+
+static uint8 gPICC_SNR[4];			   /* ¿¨Æ¬SNºÅ */
+
+void sp_test_card_state(sp_pos_t* pos, sp_cardworkstate_t* cardWorkState, uint32 tick)
+{
+  uint8 ret = 0;
+  sp_card_t cardpcd;
+  switch(pos->cardState.cur_state)
+  {
+  case STATE_NONE:
+    MEMCLEAR(&cardpcd, sizeof(cardpcd));
+    if(sp_card_request(&cardpcd) == 0)
+    {
+      MEMCPY(pos->cardState.snr, cardpcd.cardphyid, sizeof(cardpcd.cardphyid));
+      MEMCPY(gPICC_SNR, cardpcd.cardphyid, sizeof(cardpcd.cardphyid));
+      pos->cardState.tag_type = cardpcd.cardtype;
+      pos->cardState.cur_state = STATE_EXIST;
+      pos->cardState.firsttick = tick;
+      pos->cardState.lasttick = tick;
+    }
+    else
+    {
+      cardWorkState->errcode = RC_CARD_INVALID;
+    }
+    break;
+  case STATE_EXIST:
+    //¼ì²â¿¨ÊÇ·ñ¼ÌÐø´æÔÚ
+    if(pos->cardState.tag_type == TAG_TYPE_CPU)
+    {
+      ret = sp_check_cpu_exist();
+      if(ret)
+      {
+        pos->cardState.cur_state = STATE_NONE;
+        break;
+      }
+      else
+      {
+        memcpy(pos->cardState.snr, gPICC_SNR, 8);
+        pos->cardState.lasttick = tick;
+      }
+    }
+    break;
+  default:
+    pos->cardState.cur_state = STATE_NONE;
+    break;
+  }
+}
+
+static uint16 sp_dev_config_check(const sp_pos_t* pos)
+{
+  uint8 devphyid[4];
+  MEMCLEAR(devphyid, sizeof(devphyid));
+  if(MEMCMP(pos->devphyid, devphyid, sizeof(devphyid)) == 0)
+  {
+    return RC_DEVPHYID_NOTSET;
+  }
+  if(pos->devlogin.login_flag != 1)
+  {
+    return RC_DEV_NOT_LOGIN;
+  }
+  if(pos->sysconf.work_mode == 9)
+  {
+    return RC_DEV_FAULT;
+  }
+  if(pos->sysconf.flowsensor_unit == 0)
+  {
+    return RC_DEV_NOSET_FLOWSENSOR_UNIT;
+  }
+  return 0;
+}
+
+//¶ÁÈ¡µÚÒ»±ÊδÉÏ´«Á÷Ë®Ïû·ÑÈÕÆÚʱ¼ä
+static uint8 sp_read_unconfirm_first_record(uint8 termtime[6])
+{
+  return 1;
+}
+
+static uint16 sp_dev_offline_check(const sp_pos_t* pos)
+{
+  uint8 ret;
+  uint8 record_termtime[6];
+  uint8 ctime[6];
+  int32 nowtime;
+  int32 dtltime;
+
+  if(pos->sysconf.dev_offline_maxhour == 0)
+  {
+    return 0;
+  }
+  memset(record_termtime,0,sizeof(record_termtime));
+  ret = sp_read_unconfirm_first_record(record_termtime);
+  if(ret)
+  {
+    return 0;
+  }
+  sp_get_bcdtime(ctime);
+  nowtime = format_time_covert_secs(ctime);
+  dtltime = format_time_covert_secs(record_termtime);
+
+  /**
+  *Á÷ˮʱ¼ä´óÓÚÉ豸ʱÖÓÇÒ³¬¹ý24Сʱ
+  **/
+  if((dtltime > nowtime) &&
+      ((dtltime - nowtime) > (24*60*DELAY_TIME60s)))
+  {
+    if(sp_valve_state())
+    {
+      sp_valve_off();
+    }
+    return RC_DEV_OFFLINE_ERROR;
+  }
+  /**
+  *Á÷ˮʱ¼äСÓÚÉ豸ʱÖÓÇÒ³¬¹ýãÐÖµ
+  **/
+  if((dtltime < nowtime) &&
+      ((nowtime - dtltime) > (pos->sysconf.dev_offline_maxhour*3600)))
+  {
+    if(sp_valve_state())
+    {
+      sp_valve_off();
+    }
+    return RC_DEV_OFFLINE_ERROR;
+  }
+  return 0;
+}
+
+static uint16 sp_card_valid_check(const sp_card_t* card)
+{
+  uint8 ctime[6];
+  /*
+  if(card->cardno < 1)
+  {
+    return RC_CARDNO_EXCEPT;
+  }
+  */
+  sp_get_bcdtime(ctime);
+  if(memcmp(card->expiredate +1, ctime, 3) < 0)
+  {
+    return RC_CARD_EXPIRED;
+  }
+  return 0;
+}
+
+static uint16 sp_check_dev(const sp_pos_t* pos)
+{
+  uint16 ret = 0;
+  uint8 ctime[6];
+  MEMCLEAR(ctime, sizeof(ctime));
+  sp_get_bcdtime(ctime);
+  if(pos->load_para_status)
+  {
+    return pos->load_para_status;
+  }
+  ret = sp_dev_config_check(pos);
+  if(ret)
+  {
+    return ret;
+  }
+  ret = sp_dev_offline_check(pos);
+  if(ret)
+  {
+    return ret;
+  }
+
+  return 0;
+}
+
+static uint16 do_idle(sp_pos_t* pos)
+{
+  uint8 ctime[6];
+  MEMCLEAR(ctime, sizeof(ctime));
+  sp_get_bcdtime(ctime);
+  show_home(pos);
+  return 0;
+}
+
+static uint16 do_new(sp_pos_t* pos, sp_card_t* card)
+{
+  uint16 ret = 0;
+  sp_transdtl_t record;
+  MEMCLEAR(&record, sizeof(record));
+  card->cardtype = pos->cardState.tag_type;
+  MEMCPY(card->cardphyid, pos->cardState.snr, 4);
+  ret = sp_card_read(card);
+  if(ret)
+  {
+    ret = RC_CARD_INVALID;
+    return ret;
+  }
+  ret = sp_card_authentication(pos, card);
+  if(ret)
+  {
+    ret = RC_CARD_AUTHENTICATION;
+    return ret;
+  }
+  if(pos->load_para_status)
+  {
+    return pos->load_para_status;
+  }
+  ret = sp_dev_config_check(pos);
+  if(ret)
+  {
+    return ret;
+  }
+  ret = sp_dev_offline_check(pos);
+  if(ret)
+  {
+    return ret;
+  }
+
+  ret = sp_card_valid_check(card);
+  if(ret)
+  {
+    return ret;
+  }
+  ret = sp_prepare_behalf_transdtl(pos, card, &record);
+  if(ret)
+  {
+    return ret;
+  }
+  pos->sysconf.work_mode = 1;
+  pos->paymode = PAYMODE_CARD;
+  return 0;
+}
+
+static uint16 do_start(sp_pos_t* pos)
+{
+  MEMCLEAR(&pos->purchase,sizeof(sp_purchase_t));
+  sp_flowsensor_count_clear();
+  sp_get_bcdtime(pos->purchase.starttime);
+  sp_valve_on();
+  show_money(pos, pos->purchase.paid_sum);
+  return 0;
+}
+
+static uint16 do_work_check(const sp_pos_t* pos)
+{
+  //ÅжÏÏû·Ñ½ð¶îÈç¹û´óÓÚ20»òÕßÁ¬ÐøÏû·Ñ³¬¹ý2Сʱ£¬ÔòÍ£Ö¹³öË®
+  if(pos->purchase.used_num >= 1000 || pos->purchase.paid_sum >= 1000)
+  {
+    return RC_CARD_TIMEOUT;
+  }
+  return 0;
+}
+
+static uint16 do_work(sp_pos_t* pos, sp_card_t* card)
+{
+  uint16 ret = 0;
+  sp_valve_on();
+  ret = do_work_check(pos);
+  if(ret)
+  {
+    return ret;
+  }
+  //¼ÆËãÏû·Ñ½ð¶î
+  ret = sp_calc_payamt_by_flowsensor(pos, card);
+  if(ret)
+  {
+    return ret;
+  }
+  if(pos->purchase.prepaid_amt > 0)
+  {
+    //ĬÈϼÇÕËģʽ
+    ret = sp_account_purchase(pos->purchase.prepaid_amt);
+    if(ret)
+    {
+      return ret;
+    }
+  }
+
+  if(pos->purchase.prepaid_num > 0)
+  {
+    pos->purchase.paid_num += pos->purchase.prepaid_num;
+    pos->purchase.paid_sum += pos->purchase.prepaid_amt;
+    pos->purchase.prepaid_num = 0;
+    pos->purchase.prepaid_amt = 0;
+  }
+  show_money(pos, pos->purchase.paid_sum);
+  return 0;
+}
+
+static uint16 do_stop(sp_pos_t* pos, sp_card_t* card)
+{
+  uint16 ret;
+  sp_transdtl_t record;
+  sp_valve_off();
+
+  if(pos->purchase.paid_num > 0)
+  {
+    MEMCLEAR(&record, sizeof(record));
+    ret = sp_prepare_below_transdtl(pos, card, &record);
+    if(ret)
+    {
+      return ret;
+    }
+  }
+  pos->paymode = PAYMODE_INIT;
+  pos->sysconf.work_mode = 0;
+  count = 0;
+  MEMCLEAR(&pos->purchase, sizeof(sp_purchase_t));
+  MEMCLEAR(card, sizeof(sp_card_t));
+  return 0;
+}
+
+static void do_pause(sp_pos_t* pos)
+{
+  char msg[17];
+  MEMCLEAR(msg, sizeof(msg));
+  sp_valve_off();
+  if(pos->purchase.paid_sum > 0)
+  {
+    sprintf(msg,"¹²¼Æ %0.2fÔª",pos->purchase.paid_sum/100.0f);
+    disp_hint_info_two(pos,"½áÊø¼Æ·Ñ",msg,DELAY_TIME2s);
+  }
+  else
+  {
+    disp_hint_info_two(pos,"½áÊø¼Æ·Ñ","Ãâ·ÑʹÓÃ",DELAY_TIME2s);
+  }
+}
+
+static void do_error(sp_pos_t* pos, uint16 errcode)
+{
+  if(errcode)
+  {
+    show_error(pos,"²Ù×÷ʧ°Ü:",errcode);
+    pos->paymode = PAYMODE_INIT;
+    pos->sysconf.work_mode = 0;
+    count = 0;
+    MEMCLEAR(&pos->purchase, sizeof(sp_purchase_t));
+  }
+}
+
+static uint16 sp_card_exist_handle(sp_pos_t* pos, sp_card_t* card,
+                                   sp_cardworkstate_t* cardWorkState)
+{
+  uint16 ret = 0;
+  uint16 err = 0;
+  sp_card_t cardpcd;
+  switch(cardWorkState->current_state)
+  {
+  case CARDWORKSTATUS_NONE:
+    if(timer_get_ticker() - pos->cardState.firsttick < 1500)
+    {
+      break;
+    }
+    ret = do_new(pos, card);
+    if(ret)
+    {
+      if(0x1018 == ret || 0x2001 == ret||
+          0x1014 == ret || 0x1030 == ret)
+      {
+        if(0 == sp_card_request(&cardpcd))
+        {
+          break;
+        }
+      }
+      cardWorkState->errcode = ret;
+      cardWorkState->current_state = CARDWORKSTATUS_ERROR;
+      break;
+    }
+    cardWorkState->current_state = CARDWORKSTATUS_READY;
+    break;
+  case CARDWORKSTATUS_READY:
+    if(MEMCMP(pos->cardState.snr, card->cardphyid, 4) != 0)
+    {
+      cardWorkState->current_state = CARDWORKSTATUS_NONE;
+      break;
+    }
+    ret = do_start(pos);
+    if(ret)
+    {
+      cardWorkState->current_state = CARDWORKSTATUS_ERROR;
+      break;
+    }
+    cardWorkState->current_state = CARDWORKSTATUS_WORKING;
+    break;
+  case CARDWORKSTATUS_PAUSE:
+    cardWorkState->current_state = CARDWORKSTATUS_WORKING;
+    break;
+  case CARDWORKSTATUS_WORKING:
+    if(MEMCMP(pos->cardState.snr, card->cardphyid, 4) != 0)
+    {
+      ret = RC_NOT_SAME_CARD;
+      cardWorkState->current_state = CARDWORKSTATUS_STOPPING;
+      break;
+    }
+    cardWorkState->pause_status = 0;
+    ret = do_work(pos, card);
+    if(ret)
+    {
+      show_error(pos,"Ïû·Ñʧ°Ü",ret);
+      err = do_stop(pos, card);
+      if(err != 0)
+      {
+        ret = err;
+      }
+      cardWorkState->current_state = CARDWORKSTATUS_ERROR;
+      break;
+    }
+    if(pos->purchase.paid_num > card->waterlimit)
+    {
+      disp_hint_info(pos,"ÒÑ´ïµ¥´Î³öË®ÉÏÏÞ",DELAY_TIME2s);
+      cardWorkState->current_state = CARDWORKSTATUS_STOPPING;
+    }
+    cardWorkState->pause_tick = timer_get_ticker();
+    break;
+  case CARDWORKSTATUS_STOPPING:
+    ret = do_stop(pos, card);
+    if(ret)
+    {
+      cardWorkState->errcode = ret;
+      cardWorkState->current_state = CARDWORKSTATUS_ERROR;
+      break;
+    }
+    cardWorkState->current_state = CARDWORKSTATUS_STOPPED;
+    break;
+  case CARDWORKSTATUS_STOPPED:
+    cardWorkState->current_state = CARDWORKSTATUS_NONE;
+    break;
+  case CARDWORKSTATUS_FEECARD_WORKING:
+    if(MEMCMP(pos->cardState.snr, card->cardphyid, 4) != 0)
+    {
+      cardWorkState->current_state = CARDWORKSTATUS_NONE;
+      break;
+    }
+    //show_menu_options();
+    break;
+  case CARDWORKSTATUS_ERROR:
+    do_error(pos, cardWorkState->errcode);
+    cardWorkState->current_state = CARDWORKSTATUS_NONE;
+    break;
+  default:
+    Delay_ms(DELAY_TIME200ms);
+    cardWorkState->current_state = CARDWORKSTATUS_NONE;
+    break;
+  }
+  cardWorkState->errcode = ret;
+  return ret;
+}
+
+static uint16 sp_card_noexist_handle(sp_pos_t* pos, sp_card_t* card,
+                                     sp_cardworkstate_t* cardWorkState)
+{
+  //Óп¨µ½ÎÞ¿¨
+  uint16 ret = 0;
+  switch(cardWorkState->current_state)
+  {
+  case CARDWORKSTATUS_NONE:
+    do_idle(pos);
+    break;
+  case CARDWORKSTATUS_READY:
+    cardWorkState->current_state = CARDWORKSTATUS_NONE;
+    break;
+  case CARDWORKSTATUS_WORKING:
+    cardWorkState->current_state = CARDWORKSTATUS_PAUSE;
+    break;
+  case CARDWORKSTATUS_PAUSE:
+    if(MEMCMP(pos->cardState.snr, card->cardphyid, 4) == 0)
+    {
+      //¿¨ÄÃ×ßÒ»·ÖÖÓÖ®ÄÚĬÈÏÔÝͣʹÓÃ
+      if((timer_get_ticker() - cardWorkState->pause_tick) <= DELAY_TIME60s)
+      {
+        if(!cardWorkState->pause_status)
+        {
+          do_pause(pos);
+          show_home(pos);
+        }
+        show_home(pos);
+        cardWorkState->pause_status = 1;
+      }
+      else
+      {
+        cardWorkState->current_state = CARDWORKSTATUS_STOPPING;
+        cardWorkState->pause_status = 0;
+      }
+    }
+    else
+    {
+      cardWorkState->current_state = CARDWORKSTATUS_STOPPING;
+      cardWorkState->pause_status = 0;
+    }
+    cardWorkState->last_state = CARDWORKSTATUS_PAUSE;
+    break;
+  case CARDWORKSTATUS_STOPPING:
+    ret = do_stop(pos, card);
+    if(ret)
+    {
+      cardWorkState->current_state = CARDWORKSTATUS_ERROR;
+      break;
+    }
+    cardWorkState->current_state = CARDWORKSTATUS_STOPPED;
+    cardWorkState->tick = timer_get_ticker();
+    break;
+  case CARDWORKSTATUS_STOPPED:
+    if(timer_get_ticker() - cardWorkState->tick > DELAY_TIME3s)
+    {
+      cardWorkState->current_state = CARDWORKSTATUS_NONE;
+      cardWorkState->last_state = cardWorkState->current_state;
+      cardWorkState->tick = 0;
+    }
+    break;
+  case CARDWORKSTATUS_SET_DEV:
+    if(sp_check_passwd(pos, "É豸¹ÜÀíÃÜÂë", "\x9\x1\x4\x3\x8\x7") == 0)
+    {
+      sp_menu_options(pos);
+    }
+    cardWorkState->current_state = CARDWORKSTATUS_NONE;
+    break;
+  case CARDWORKSTATUS_ERROR:
+    do_error(pos,cardWorkState->errcode);
+    cardWorkState->current_state = CARDWORKSTATUS_NONE;
+    break;
+  default:
+    Delay_ms(DELAY_TIME200ms);
+    cardWorkState->current_state = CARDWORKSTATUS_NONE;
+    break;
+  }
+  cardWorkState->errcode = ret;
+  return ret;
+}
+
+static sp_card_t CARD;
+void sp_card_handle(sp_pos_t* pos, sp_cardworkstate_t* cardWorkState)
+{
+  if(pos->cardState.cur_state)
+  {
+    sp_card_exist_handle(pos, &CARD, cardWorkState);
+  }
+  else
+  {
+    sp_card_noexist_handle(pos, &CARD, cardWorkState);
+  }
+}
+
+void sp_confirm_paymode(sp_pos_t* pos, sp_cardworkstate_t* cardWorkState)
+{
+  uint8 keycode = SP_KEY_NONE;
+  keycode = sp_get_key();
+  //ÔÚ¿¨Ïû·ÑÔÝÍ£Çé¿öϰ´ÈÎÒâ¼üΪ½áÊøµ±Ç°Ïû·Ñ״̬
+  if(keycode >= SP_KEY_0 && keycode <= SP_KEY_ENTER && pos->cardState.cur_state == STATE_NONE
+      && cardWorkState->current_state == CARDWORKSTATUS_PAUSE && pos->paymode == PAYMODE_CARD)
+  {
+  	cardWorkState->current_state = CARDWORKSTATUS_STOPPING;
+	return;
+  }
+  //Ïû·Ñģʽ³õʼ»¯×´Ì¬Ï°´È·ÈϼüÑ¡Ôñ¶þάÂëÏû·Ñ
+  if((keycode == SP_KEY_ENTER) && (pos->paymode == PAYMODE_INIT))
+  {
+    cardWorkState->current_state = CARDWORKSTATUS_NONE;
+    pos->paymode = PAYMODE_QRCODE;
+	return;
+  }
+  //¶þάÂëģʽϰ´È¡Ïû¼üΪֹͣ¹¤×÷
+  if((pos->paymode == PAYMODE_QRCODE) && (keycode == SP_KEY_CLEAR))
+  {
+    cardWorkState->current_state = CARDWORKSTATUS_STOPPING;
+	return;
+  }
+  //°´0¼ü½øÈëÉ豸²Ù×÷½çÃæ
+  if(keycode == SP_KEY_0 && (pos->paymode == PAYMODE_INIT))
+  {
+    cardWorkState->current_state = CARDWORKSTATUS_SET_DEV;
+	return;
+  }
+}
+
+//¶þάÂëÏû·Ñ´¦Àí
+uint32 tick = 0;
+void sp_qrcode_handle(sp_pos_t* pos, sp_cardworkstate_t* cardWorkState)
+{
+  uint16 ret = 0;
+  sp_transdtl_t record;
+  MEMCLEAR(&record, sizeof(record));
+  switch(cardWorkState->current_state)
+  {
+  case CARDWORKSTATUS_NONE:
+    ret = sp_check_dev(pos);
+    if(ret)
+    {
+      cardWorkState->errcode = ret;
+      cardWorkState->current_state = CARDWORKSTATUS_ERROR;
+      break;
+    }
+    ret = sp_qrcode_init(pos, &CARD);
+    if(ret)
+    {
+      cardWorkState->errcode = ret;
+      cardWorkState->current_state = CARDWORKSTATUS_ERROR;
+      break;
+    }
+    ret = sp_prepare_behalf_transdtl(pos, &CARD, &record);
+    if(ret)
+    {
+      cardWorkState->errcode = RC_QRCODE_TIMEOUT;
+      cardWorkState->current_state = CARDWORKSTATUS_ERROR;
+      break;
+    }
+    pos->sysconf.work_mode = 1;
+    CARD.qrcode.starttime = sp_get_ticker();
+    disp_hint_info(pos, "ÕýÔÚÉú³É¶þάÂë", DELAY_TIME2s);
+    cardWorkState->last_state = cardWorkState->current_state;
+    cardWorkState->current_state = CARDWORKSTATUS_READY;
+    break;
+  case CARDWORKSTATUS_READY:
+    CARD.qrcode.nowtime = sp_get_ticker();
+    if((CARD.qrcode.nowtime - CARD.qrcode.starttime) > CARD.qrcode.validtime)
+    {
+      show_home(pos);
+      show_home_qrcode(CARD.qrcode.qrcode_url);
+      if(CARD.qrcode.nowtime - tick > DELAY_TIME3s)
+      {
+        tick = CARD.qrcode.nowtime;
+        ret = sp_qrcode_query(pos, &CARD);
+        if(!ret && CARD.qrcode.authstatus)
+        {
+          do_start(pos);
+          cardWorkState->last_state = cardWorkState->current_state;
+          cardWorkState->current_state = CARDWORKSTATUS_WORKING;
+        }
+      }
+    }
+    else
+    {
+      cardWorkState->errcode = RC_QRCODE_TIMEOUT;
+      cardWorkState->current_state = CARDWORKSTATUS_ERROR;
+    }
+    break;
+  case CARDWORKSTATUS_WORKING:
+    ret = do_work(pos, &CARD);
+    if(ret)
+    {
+      show_error(pos,"Ïû·Ñʧ°Ü",ret);
+      ret = do_stop(pos, &CARD);
+      if(ret)
+      {
+        cardWorkState->errcode = ret;
+      }
+      cardWorkState->current_state = CARDWORKSTATUS_ERROR;
+      break;
+    }
+    cardWorkState->last_state = cardWorkState->current_state;
+    cardWorkState->pause_tick = sp_get_ticker();
+    break;
+  case CARDWORKSTATUS_STOPPING:
+    if(cardWorkState->last_state == CARDWORKSTATUS_NONE
+        || cardWorkState->last_state == CARDWORKSTATUS_READY)
+    {
+      disp_hint_info(pos,"È¡ÏûË¢Âë!", DELAY_TIME2s);
+      pos->paymode = PAYMODE_INIT;
+      pos->sysconf.work_mode = 0;
+    }
+    else
+    {
+      if(cardWorkState->last_state != CARDWORKSTATUS_PAUSE)
+        do_pause(pos);
+      ret = do_stop(pos, &CARD);
+      if(ret)
+      {
+        cardWorkState->errcode = ret;
+        cardWorkState->current_state = CARDWORKSTATUS_ERROR;
+        break;
+      }
+    }
+    cardWorkState->current_state = CARDWORKSTATUS_NONE;
+    cardWorkState->last_state = cardWorkState->current_state;
+    break;
+  case CARDWORKSTATUS_ERROR:
+    do_error(pos,cardWorkState->errcode);
+    cardWorkState->current_state = CARDWORKSTATUS_NONE;
+    cardWorkState->last_state = cardWorkState->current_state;
+    break;
+  default:
+    Delay_ms(DELAY_TIME200ms);
+    break;
+  }
+}