RoBoard魔人的機器人日誌

2012/4/17

[RoBoard文件中譯版] RoBoIO 1.80 Introduction

RoBoIO 1.80 Introduction
原文版: http://www.roboard.com/Files/Code/RoBoard_Training_SW_v18b.pdf

先翻譯到SPI~
之後的內容將會隨著每周更新喔~!

Download Link: http://db.tt/JkJHobbZ
Share:

2012/4/6

[RoBoRC最終回] 介紹程式碼demo

終於來到最終回了

而demo這個也是本魔認為最麻煩的一個

這邊有用到蠻複雜的結構

以及demo需要把之前好幾回的東西整合起來思考 ((因為它有init

總之來看看吧~

demo.h
#ifndef __DEMO_H
#define __DEMO_H

#include "defines.h"

#define CMD_MAXNAMELEN  (256)

typedef struct _FRM_NODE                  //frame節點
{
 int frmno;                     //編號
 unsigned long frm[32];                  //內容   32個PWM
 struct _FRM_NODE *next;                  //下一個節點
}FRM_NODE;

typedef struct _ACT_NODE                  //動作的節點
{
 int type;                     //型態
 int time;                     //時間
 int actno;                     //編號
 unsigned long *frm;
 union{                      //union型別   選一個用
  int frmno;                    //編號
  char *filename;                   //檔案名稱
 }data;
 struct _ACT_NODE *next;                  //下一個節點
}ACT_NODE;
//-- values for ACT_t.type
 #define  ACT_START   (0)
 #define  ACT_PAUSE   (1)
 #define  ACT_PLAYFRAMENO (2)
 #define  ACT_PLAYSND  (3)

typedef struct _CMD_NODE                  //指令的節點
{
 int command;                    //指令編號
 int actno;                     //動作的編號
 char name[CMD_MAXNAMELEN+1];                //指令名稱
 ACT_NODE *act;                    //對應到的動作結點
 struct _CMD_NODE *next;                  //下一個節點
}CMD_NODE;

typedef struct _CH_t                   //channel的節點
{
 int pin;                     //腳位編號
 int mode_idx;                    //模式
 int offset;                     //偏移值
}CH_t;

typedef struct {                    //主要架構

 int rbidx;                     
 int initact;                    
 ACT_NODE *initactnode;
 int initfrm;
 int initfrm_mode;
 unsigned long usedChannels;
 unsigned long *inithome;
 CH_t channel[32];

 int actidx;
 int actsize;
 ACT_NODE *actpool;
 ACT_NODE **acttable;

 int frmidx;
 int frmsize;
 FRM_NODE *frmpool;
 FRM_NODE **frmtable;

 int cmdidx;
 int cmdsize;
 CMD_NODE *cmdpool;
 CMD_NODE **cmdtable;

// int SND_maxNum; //unused at the moment

} DEF_t;
//-- value for initfrm_mode
#define INIT_FRM_FALSE (0)
#define INIT_FRM_TRUE (1)

#ifdef __cplusplus
extern "C" {
#endif

CMD_NODE *tool_FindCMDNode(CMD_NODE **table, int command, int size);
ACT_NODE *tool_FindACTNode(ACT_NODE **table, int actno, int size);

bool tool_InitCapture(CH_t *channel, unsigned long usedch, int mode_idx);
bool tool_InitDemo(DEF_t *def, char *dirname);
bool tool_InitReplay(DEF_t *def, char *filename, int replaytime, int mode_idx, int actno, unsigned long usedchannels);

#ifdef __cplusplus
}
#endif

#endif

demo.cpp
#include <math.h>
#include <stdlib.h>
#include "demo.h"
#include "parse.h"
#include "errcode.h"
#include "fileio.h"

static int prime(int n);
static int HashFun(int n, int base);

static ACT_NODE *SearchACT(ACT_NODE *node, int actno);
static CMD_NODE *SearchCMD(CMD_NODE *node, int cmd);
static FRM_NODE *SearchFRM(FRM_NODE *node, int frmno);

static int GetTotalACT(ACT_NODE *pool, int idx);
static int InsertACT(ACT_NODE ***table, ACT_NODE *pool, int total, int size);
static int InsertCMD(CMD_NODE ***table, CMD_NODE *pool, int total, int size);
static int InsertFRM(FRM_NODE ***table, FRM_NODE *pool, int total, int size);

static ACT_NODE *map_FindACTNode(ACT_NODE **table, int actno, int size);
static CMD_NODE *map_FindCMDNode(CMD_NODE **table, int command, int size);
static FRM_NODE *map_FindFRMNode(FRM_NODE **table, int frmno, int size);
static int map_MappingACT(FRM_NODE **table, ACT_NODE *actpool, int actidx, int size);
static int map_MappingCMD(ACT_NODE **table, CMD_NODE *cmdpool, int cmdidx, int size);
static int map_MappingDEF(DEF_t *def);

static void SetFrame(FRM_NODE *pool, CH_t *ch, int idx);

static int FRMToACT(DEF_t *def, char *filename, int actno, int time);

/* ==================  hash function ==================*/
static int prime(int n)                   //尋找比n大  且最接近n的質數
{
 int i, j, size, max;
 int *array;
 max = (int)sqrt((double)n) + 1;
 size = max * max;
 array = (int *)malloc(sizeof(int) * size);
 for(i = 0; i < size; i++)
  array[i] = 0;
 for(i = 2; i < max; i++){
  if(array[i] == 0){
   for(j = 2*i; j < size; j += i)
    array[j] = 1;
  }
 }
 for(i = n; i < size; i++){
  if(array[i] == 0)
   break;
 }
 free(array);
 return i;
}

static int HashFun(int n, int base)                //雜湊  取base次方 再mod base
{
 return (n ^ base) % base;
}

/* ==================  general function ==================*/
static ACT_NODE *SearchACT(ACT_NODE *node, int actno)           //尋找ACT_NODE內編號actno的節點
{
 while(node != NULL){
  if(node->actno == actno)
   break;
  node = node->next;
 }
 return node;
}

static CMD_NODE *SearchCMD(CMD_NODE *node, int cmd)            //尋找CMD_NODE內編號cmd的節點
{
 while(node != NULL){
  if(node->command == cmd)
   break;
  node = node->next;
 }
 return node;
}

/* ==================  insert function ==================*/
static FRM_NODE *SearchFRM(FRM_NODE *node, int frmno)           //尋找FRM_NODE內編號frmno的節點
{
 while(node != NULL){
  if(node->frmno == frmno)
   break;;
  node = node->next;
 }
 return node;
}


static int GetTotalACT(ACT_NODE *pool, int idx)             //得到action的總個數
{
 int i, total;
 total = 0;
 for(i = 0; i < idx - 1; i++){
  if(pool[i].type == ACT_START)
   total += 1;
 }
 return total;
}

static int InsertACT(ACT_NODE ***table, ACT_NODE *pool, int total, int size)     //建造ACT的表格
{
 int i, idx;
 if(size == 0)
  return SUCCESS;
 *table = (ACT_NODE **)malloc(sizeof(ACT_NODE *) * size);
 if(*table == NULL)
  return MEMORY_ERROR;
 for(i = 0; i < size; i++)
  (*table)[i] = NULL;
 for(i = 0; i < total - 1; i++){
  if(pool[i].type == ACT_START){
   idx = HashFun(pool[i].actno, size);
   if(SearchACT((*table)[idx], pool[i].actno) != NULL){
    errcode_SetErrACT(pool[i].actno);
    return MAP_REPEAT_ACTNO;
   }
   pool[i].next = (*table)[idx];
   (*table)[idx] = &pool[i];
  }
 }
 return SUCCESS;
}

static int InsertCMD(CMD_NODE ***table, CMD_NODE *pool, int total, int size)     //建造CMD的表格
{
 int i, idx;
 if(size == 0)
  return SUCCESS;
 *table = (CMD_NODE **)malloc(sizeof(CMD_NODE *) * size);
 if(*table == NULL)
  return MEMORY_ERROR;
 for(i = 0; i < size; i++)
  (*table)[i] = NULL;
 for(i = 0; i < total; i++){
  idx = HashFun(pool[i].command, size);
  if(SearchCMD((*table)[idx], pool[i].command) != NULL){
   errcode_SetErrCMD(pool[i].command);
   return MAP_REPEAT_CMD;
  }
  pool[i].next = (*table)[idx];
  (*table)[idx] = &pool[i];
 }
 return SUCCESS;
}

static int InsertFRM(FRM_NODE ***table, FRM_NODE *pool, int total, int size)     //建造FRM的表格
{
 int i, idx;
 if(size == 0)
  return SUCCESS;
 *table = (FRM_NODE **)malloc(sizeof(FRM_NODE *) * size);
 if(*table == NULL)
  return MEMORY_ERROR;
 for(i = 0; i < size; i++)
  (*table)[i] = NULL;
 for(i = 0; i < total; i++){
  idx = HashFun(pool[i].frmno, size);
  if(SearchFRM((*table)[idx], pool[i].frmno) != NULL){
   errcode_SetErrFRM(pool[i].frmno);
   return MAP_REPEAT_FRMNO;
  }
  pool[i].next = (*table)[idx];
  (*table)[idx] = &pool[i];
 }
 return SUCCESS;
}

static int InsertTable(DEF_t *def)                //計算table大小  以及創建table
{
 int status;
 def->actsize = prime((int)(GetTotalACT(def->actpool, (def->actidx)) * 1.5));
 def->cmdsize = prime((int)(def->cmdidx * 1.5));
 def->frmsize = prime((int)(def->frmidx * 1.5));
 status = InsertACT(&def->acttable, def->actpool, def->actidx, def->actsize);
 if(status == SUCCESS)
  status = InsertCMD(&def->cmdtable, def->cmdpool, def->cmdidx, def->cmdsize);
 if(status == SUCCESS)
  status = InsertFRM(&def->frmtable, def->frmpool, def->frmidx, def->frmsize);
 return status;
}

/* ==================  function for mapping  ==================*/
static ACT_NODE *map_FindACTNode(ACT_NODE **table, int actno, int size)       //回傳ACT table內的actno   若已有使用則回傳下一個
{
 ACT_NODE *p;
 int idx;
 if(table == NULL)
  return NULL;
 idx = HashFun(actno, size);
 p = SearchACT(table[idx], actno);
 if(p == NULL)
  return p;
 return p + 1;
}

static CMD_NODE *map_FindCMDNode(CMD_NODE **table, int command, int size)      //回傳CMD table內的command
{
 int idx;
 if(table == NULL)
  return NULL;
 idx = HashFun(command, size);
 return SearchCMD(table[idx], command);
}

static FRM_NODE *map_FindFRMNode(FRM_NODE **table, int frmno, int size)       //回傳FRM table內的frmno
{
 int idx;
 if(table == NULL)
  return NULL;
 idx = HashFun(frmno, size);
 return SearchFRM(table[idx], frmno);
}

static int map_MappingACT(FRM_NODE **table, ACT_NODE *actpool, int actidx, int size)   //mapping FRM編號
{
 int i;
 FRM_NODE *p;
 for(i = 0; i < actidx; i++){
  if(actpool[i].type == ACT_PLAYFRAMENO){
   p = map_FindFRMNode(table, actpool[i].data.frmno, size);
   if(p == NULL){
    errcode_SetErrFRM(actpool[i].data.frmno);
    return MAP_NOFINDFRM;
   }
   actpool[i].frm = p->frm;
  }
 }
 return SUCCESS;
}

static int map_MappingCMD(ACT_NODE **table, CMD_NODE *cmdpool, int cmdidx, int size)   //mapping act編號
{
 int i;
 ACT_NODE *p;
 for(i = 0; i < cmdidx; i++){
  p = map_FindACTNode(table, cmdpool[i].actno, size);
  if(p == NULL){
   errcode_SetErrACT(cmdpool[i].actno);
   return MAP_NOFINDACT;
  }
  cmdpool[i].act = p;
 }
 return SUCCESS;
}

static int map_MappingDEF(DEF_t *def)               //mapping  def的所有NODE
{
 FRM_NODE *p;
 int status;
 if(def->initfrm != -1){
  p = map_FindFRMNode(def->frmtable, def->initfrm, def->frmsize);
  if(p == NULL){
   errcode_SetErrFRM(def->initfrm);
   return MAP_NOFINDINITFRM;
  }
  def->inithome = p->frm;
 }
 if(def->initact != -1){
        def->initactnode = map_FindACTNode(def->acttable, def->initact, def->actsize);
  if(def->initactnode == NULL){
   errcode_SetErrACT(def->initact);
   return MAP_NOFINEINITACT;
  }
 }
 status = map_MappingACT(def->frmtable, def->actpool, def->actidx, def->frmsize);
 if(status == SUCCESS)
  status = map_MappingCMD(def->acttable, def->cmdpool, def->cmdidx, def->actsize);
 return status;
}

/* ==================  function for offset  ==================*/
static void SetFrame(FRM_NODE *pool, CH_t *ch, int idx)           //將偏移植算入frame
{
 int i, j;
 unsigned long temp[32];
 for(i = 0; i < idx; i++){
  for(j = 0; j < 32; j++)
   temp[j] = pool[i].frm[j];
  for(j = 0; j < 32; j++){
   if(ch[j].pin != -1)
    pool[i].frm[ch[j].pin] = temp[j] + ch[j].offset;
  }
 }
}

/* ==================  function for replay frame  ==================*/
int FRMToACT(DEF_t *def, char *filename, int actno, int time)         //設定一些預設值   replay mode用  
{
 FILEIO *fp;
    INI_ITEM_t item;
 ACT_NODE *act;
 int status = SUCCESS;
 fp = ini_FileOpen(filename);
 if(fp == NULL)
  return FRM_OFFSET + OPEN_FILE_FAIL;
 act = &def->actpool[def->actidx];
 act->type = ACT_START;
 act->actno = actno;
 status = tool_InsertACTPool(&def->actpool, &def->actidx);
 while ((status == SUCCESS) && (ini_ReadNextItem(fp, &item) != INI_FILEEND))
 {
  act = &def->actpool[def->actidx];
  switch(item.type)
        {
            case INI_GROUPTITLE:
    act->type = ACT_PLAYFRAMENO;
    act->time = time;
    status = tool_GetGroupFRM(item.itemname, &act->data.frmno);
    if(status == SUCCESS)
     status = tool_InsertACTPool(&def->actpool, &def->actidx);
                break;
        }
    }
 ini_FileClose(fp);
 act = &def->actpool[def->actidx];
 act->type = ACT_START;
 act->actno = -1;
 status = tool_InsertACTPool(&def->actpool, &def->actidx);
 return status;
}

/* ==================  tool function ==================*/
CMD_NODE *tool_FindCMDNode(CMD_NODE **table, int command, int size)
{
 return map_FindCMDNode(table, command, size);
}

ACT_NODE *tool_FindACTNode(ACT_NODE **table, int actno, int size)
{
 return map_FindACTNode(table, actno, size);
}

bool tool_InitCapture(CH_t *channel, unsigned long usedch, int mode_idx)      //init Capture mode
{
 int i;
 for(i = 0; i < 32; i++)
  channel[i].pin = -1;

 for(i = 0; i < 32; i++){
     if((usedch & (1L << i)) != 0){
            channel[i].pin = i;
            channel[i].offset = 0;
            channel[i].mode_idx = mode_idx;
       }
 }
 return true;
}

bool tool_InitReplay(DEF_t *def, char *filename, int replaytime, int mode_idx, int actno, unsigned long usedchannels) //init replay mode
{
 int i;
 int status;
 status = tool_InitDEF(def);
 for(i = 0; i < 32; i++){
  if((usedchannels & (1L << i)) != 0){
            def->channel[i].pin = i;
            def->channel[i].offset = 0;
            def->channel[i].mode_idx = mode_idx;
        }
 }
 if(status == SUCCESS)
  status = tool_ParseFile_FRM(def, filename);
 if(status == SUCCESS)
  status = FRMToACT(def, filename, actno, replaytime);
 if(status == SUCCESS)
  status = InsertTable(def);
 if(status == SUCCESS)
  status = map_MappingACT(def->frmtable, def->actpool, def->actidx, def->frmsize);
 if(status == SUCCESS)
  return true;
    errcode_ShowErr(status);
    return false;
}

bool tool_InitDemo(DEF_t *def, char *dirname)             //init demo mode
{
    int status;
 status = tool_InitDEF(def);
 if(status == SUCCESS)
  status = tool_ReadFile(dirname, def);
 SetFrame(def->frmpool, def->channel, def->frmidx);
 if(status == SUCCESS)
  status = InsertTable(def);
 if(status == SUCCESS)
        status = map_MappingDEF(def);
 if(status == SUCCESS)
        return true;
    errcode_ShowErr(status);
 return false;
}


基本上這樣子RoBoRC就告一段落了

相信學到這邊大家應該也都對RoBoRC有相當的了解!

以上!
Share:

2012/3/26

[RoBoRC第七回] 介紹程式碼parse

本周介紹的RoBoRC程式碼為parse

它是用於demo mode所需文件的開檔及解析內容

再看這篇的同時 資料結構可能要學好 不然可能會不知道它在做什麼事情

parse.h
#ifndef __PARSETOOL_H
#define __PARSETOOL_H
#include "demo.h"

#ifdef __cplusplus
extern "C" {
#endif

int tool_GetItemRBVer(char *str, int *rbidx);
int tool_GetMode(char *str, int *mode_idx);
int tool_GetGroupFRM(char *str, int *frmno);
int tool_InsertACTPool(ACT_NODE **pool, int *idx);
int tool_ParseFile_FRM(DEF_t *def, char *filename);
int tool_ReadFile(char* dirname, DEF_t* def);
int tool_InitDEF(DEF_t *def);
void tool_FreeDEF(DEF_t *def);

#ifdef __cplusplus
}
#endif

#endif




parse.cpp
#include <string.h>
#include <stdlib.h>
#include "errcode.h"
#include "userio.h"
#include "const.h"
#include "fileio.h"
#include "parse.h"

#if defined(RB_LINUX)
    #define _stricmp  strcasecmp
    #define _strnicmp strncasecmp
#elif defined(RB_BC_DOS) || defined(RB_DJGPP)
    #define _stricmp  stricmp
    #define _strnicmp strnicmp
#endif

#define OUT 0
#define IN 1

#define BASE_CMD (2)
#define BASE_ACT (2)
#define BASE_FRM (2)

static char FileDir[255];
static char FullFileDir[511];

static char* GetPath(char* filename);

static int txt_GetItemCH(INI_ITEM_t *item, int *ch, int *value);
static int def_ParseFile_TXT(DEF_t *def, char *filename);

static void frm_InitFRM(FRM_NODE *node);
static int frm_GetGroupFRM(char *str, int *frmno);
static int frm_InsertPool(FRM_NODE **pool, int *idx);
static int frm_GetItemCH(INI_ITEM_t *item, int *ch, int *value);
static int def_ParseFile_FRM(DEF_t *def, char *filename);

static void act_InitACT(ACT_NODE *node);
static int act_GetGroupACT(char *str, int *actno);
static int act_InsertPool(ACT_NODE **pool, int *idx);
static int act_ParseItem(DEF_t *def, INI_ITEM_t *item);
static int act_GetItemMTF(char *str, int *frmno, int *time);
static int act_GetItemPause(char *str, int *time);
static int act_GetItemSnd(char *str, char **filename);
static int def_ParseFile_ACT(DEF_t *def, char *filename);

static void cmd_InitCMD(CMD_NODE *node);
static int cmd_CheckCMD(CMD_NODE *cmd);
static int cmd_InsertPool(CMD_NODE **pool, int *idx);
static int cmd_InsertCMD(DEF_t *def, CMD_NODE *cmd);
static int cmd_GetItemACT(char *str, int *actno);
static int def_ParseFile_CMD(DEF_t *def, char *filename);

static int def_ParseItem_Settings(DEF_t* def, INI_ITEM_t* item);
static int def_GetItemInitFrm(char *str, int *frmno, int *mode);
static int def_GetValueFrmMode(char *str, int *mode);
static int def_ParseItem_Channels(DEF_t* def, INI_ITEM_t* item);
static int def_GetCH(char *str, int *ch);
static int def_GetPINS(char *str, int *pin);
static int def_GetMode(char *str, int *mode_idx);
static int def_GetItemRBVer(char *str, int *rbidx);
static int def_ParseItem_File(DEF_t *def, INI_ITEM_t *item);
static int def_ParseFile_DEF(char* filename, DEF_t* def);

static char* GetPath(char* filename)  //the user should not modify the return string   //合併檔案位置的字
{
// if((int)strcspn(dirname, "/"))
 strcpy(FullFileDir, FileDir); //avoid the case where filepath == DEMOFILE_bufpath
 return strcat(FullFileDir, filename);
}

/*===========================  tool for offset file  ===========================*/
static int txt_GetItemCH(INI_ITEM_t *item, int *ch, int *value)         //抓取channel的編號   與偏移的值
{
 int sign, status;
 char *str;
 sign = 1;
 status = ini_GetCH(item->itemname, ch);              //抓取channel的編號  在fileio.cpp
 if(status != SUCCESS)
  return TXT_OFFSET + INVALID_NAME;              
 if(item->itemvalue[0] == '-'){
  sign = -1;
  str = ini_RemoveSpace(&item->itemvalue[1]);            //清空前後的空白  在fileio.cpp
 }
 else if(item->itemvalue[0] == '+')
  str = ini_RemoveSpace(&item->itemvalue[1]);            
 else
  str = item->itemvalue;
 status = ini_GetValue(str, value);               //將字串轉為數字  在fileio.cpp
 if(status != SUCCESS)
  return TXT_OFFSET + INVALID_VALUE;              
 *value *= sign;                    //正負號
 return SUCCESS;
}

static int def_ParseFile_TXT(DEF_t *def, char *filename)          //去改變各個channel的偏移值
{
 int status = SUCCESS;
 int ch, value;
 unsigned long flag = 0L;
 INI_ITEM_t item;
 FILEIO *fp;

 fp = ini_FileOpen(GetPath(filename));              //開啟檔案
 if(fp == NULL)
  return TXT_OFFSET + OPEN_FILE_FAIL;

 while ((status == SUCCESS) && (ini_ReadNextItem(fp, &item) != INI_FILEEND))     //讀取內容  改為INI_ITEM_t形式
 {
  status = txt_GetItemCH(&item, &ch, &value);
  if(status == SUCCESS){
   if((flag & (1L << ch)) != 0) //check repeat           //檢查是否重複用過
    return TXT_REPEAT_CH;
   def->channel[ch].offset = value;             //依照讀取到的內容改變def的channel[].offset
   flag |= (1L << ch);                 //用過的把該bit改為1
  }
 }

 ini_FileClose(fp);
 return status;
}

/*===========================  tool for frm file  ===========================*/
static void frm_InitFRM(FRM_NODE *node)               //預設frm的值
{
 int i;
 node->frmno = -1;
 for(i = 0; i < 32; i++)
  node->frm[i] = 0L;
 node->next = NULL;
}

static int frm_GetGroupFRM(char *str, int *frmno)            //取得frame的編號
{
 int status;
 status = ini_ParseNumber_pre(str, "Frame", frmno);           //取得frame的編號
 if(status == SUCCESS)
  return status;
 return FRM_OFFSET + INVALID_GROUP;
}

static int frm_GetItemCH(INI_ITEM_t *item, int *ch, int *value)         //取得各個channel的位置的值
{
 int status;
 status = ini_GetCH(item->itemname, ch);              //取得channel的編號
 if(status != SUCCESS)
  return FRM_OFFSET + INVALID_NAME;
 status = ini_GetValue(item->itemvalue, value);            //取得位置的值
 if(status != SUCCESS)
  return FRM_OFFSET + INVALID_VALUE;
 return SUCCESS;

}

static int frm_InsertPool(FRM_NODE **pool, int *idx)           //倍增空間
{
 int i;
 int size;
 *idx += 1;
 if(*idx % BASE_FRM == 0){
  size = *idx * 2;
  *pool = (FRM_NODE *)realloc(*pool, sizeof(FRM_NODE) * size);
  if(*pool == NULL)
   return MEMORY_ERROR;
  for(i = *idx; i < size; i++)
   frm_InitFRM(&(*pool)[i]);
 }
 return SUCCESS;
}

static int def_ParseFile_FRM(DEF_t *def, char *filename)
{
 #define OUT 0
 #define IN 1
 int flag = OUT;
 int status = SUCCESS;
 int ch, value;
 unsigned long flagch = 0L;
 INI_ITEM_t item;
 FILEIO *fp;
 FRM_NODE *node;

 fp = ini_FileOpen(GetPath(filename));              //開啟檔案
 if(fp == NULL)
  return FRM_OFFSET + OPEN_FILE_FAIL;

 while ((status == SUCCESS) && (ini_ReadNextItem(fp, &item)) != INI_FILEEND)     //讀取內容  改為INI_ITEM_t形式
 {
  switch(item.type){                  //依照type來分別做
   case INI_GROUPTITLE:                //如果是title    即為[Frame N]
    if(flag == OUT)                 
     flag = IN;                 //標記未讀取過改為已讀取過
    else
     status = frm_InsertPool(&def->frmpool, &def->frmidx);      //有需要時倍增節點空間
    flagch = 0L;
    node = &def->frmpool[def->frmidx];
    status = frm_GetGroupFRM(item.itemname, &node->frmno);       //取得frame的編號
    break;
   case INI_GROUPITEM:                 //如果是item    即為channel1 = 1300
    if(flag == OUT)                 //如果標記為未讀過  代表沒有title
     status = FRM_OFFSET + NOGROUP_ITEM;
    if(status == SUCCESS)
     status = frm_GetItemCH(&item, &ch, &value);         //取得item的channel編號
    if(status == SUCCESS){
     if((flagch & (1L << ch)) != 0)            //防止重複讀取用
      return FRM_REPEAT_CH;
     node->frm[ch] = value;              //把值填入節點中
     flagch |= (1L << ch);
    }
    break;
   case INI_UNKNOWNITEM:                //讀到不知明物體
    return FRM_OFFSET + UNKNOWN_LINE;
  }
 }
 ini_FileClose(fp);
 if(status == SUCCESS)
  status = frm_InsertPool(&def->frmpool, &def->frmidx);
 return status;
}

/*===========================  tool for act file  ===========================*/
static void act_InitACT(ACT_NODE *node)               //預設act的值
{
 node->actno = -1;
 node->frm = NULL;
 node->next = NULL;
 node->time = -1;
 node->data.frmno = -1;
}

static int act_GetItemSnd(char *str, char **filename)           //複製檔案名稱   聲音用
{
 int i;
 i = (int)strlen(str);
 if(i == 0)
  return ACT_OFFSET + INVALID_VALUE;
 *filename = (char *)malloc(sizeof(char) * (i+1));
 if(filename == NULL)
  return MEMORY_ERROR;
 strcpy(*filename, str);
 return SUCCESS;
}

static int act_GetItemPause(char *str, int *time)            //抓出時間的值
{
 int status;
 status = ini_ParseNumber_post(str, "ms", time);
 if(status != SUCCESS)
  return ACT_OFFSET + INVALID_VALUE;
 return status;
}

static int act_GetItemMTF(char *str, int *frmno, int *time)          //讀取MoveToFrame
{
 char *str1, *str2;
 int status;
 status = ini_DivideString(str, &str1, &str2, ",");           //分割字串以","為中間點
 if(status == INI_DIVIDE_FAIL)
  return ACT_OFFSET + INVALID_VALUE;
 status = ini_GetValue(str1, frmno);               //抓取str1的值  即為frame的編號
 if(status != SUCCESS)
  return ACT_INVALID_FRMNO;
 status = ini_ParseNumber_post(str2, "ms", time);           //抓取str2的值  即為時間的值
 if(status != SUCCESS)
  return ACT_INVALID_TIME;
 return status;
}

static int act_ParseItem(DEF_t *def, INI_ITEM_t *item)           //分辨指令
{
 ACT_NODE *node;
 node = &def->actpool[def->actidx];
 int status;
 if(ini_IsItem(item, "MoveToFrame")){
  node->type = ACT_PLAYFRAMENO;               //如果指令為MoveToFrame  則要讀取兩個值
  status = act_GetItemMTF(item->itemvalue, &node->data.frmno, &node->time);
 }
 else if(ini_IsItem(item, "Pause")){
  node->type = ACT_PAUSE;                 //如果指令為Pause  則要讀一個值
  status = act_GetItemPause(item->itemvalue, &node->time);
 }
 else if(ini_IsItem(item, "playsnd")){
  node->type = ACT_PLAYSND;                //如果指令為playsnd     則要給檔案名稱
  status = act_GetItemSnd(item->itemvalue, &node->data.filename);
 }
 else                      //其他沒看過的指令就回傳錯誤訊息
  status = ACT_OFFSET + INVALID_NAME;
 if(status == SUCCESS)
  status = act_InsertPool(&def->actpool, &def->actidx);
 return status;
}

static int act_InsertPool(ACT_NODE **pool, int *idx)           //倍增節點
{
 int i;
 int size;
 *idx += 1;
 if(*idx % BASE_ACT == 0){
  size = *idx * 2;
  *pool = (ACT_NODE *)realloc(*pool, sizeof(ACT_NODE) * size);
  if(*pool == NULL)
   return MEMORY_ERROR;
  for(i = *idx; i < size; i++)
   act_InitACT(&(*pool)[i]);
 }
 return SUCCESS;
}

static int act_GetGroupACT(char *str, int *actno)            //取得Action編號
{
 int status;
 status = ini_ParseNumber_pre(str, "Action", actno);           //取得Action編號
 if(status == SUCCESS)
  return status;
 return ACT_OFFSET + INVALID_GROUP;
}

static int def_ParseFile_ACT(DEF_t *def, char *filename)
{
 #define OUT 0
 #define IN 1
 int flag = OUT;
 int status = SUCCESS;
 INI_ITEM_t item;
 ACT_NODE *node;
 FILEIO *fp;

 fp = ini_FileOpen(GetPath(filename));              //開啟檔案
 if(fp == NULL)
  return ACT_OFFSET + OPEN_FILE_FAIL;
 while ((status == SUCCESS) && (ini_ReadNextItem(fp, &item)) != INI_FILEEND)     //讀取內容   改為INI_ITEM_t形式
 {
  node = &def->actpool[def->actidx];
  switch(item.type){                  //依型態做事
   case INI_GROUPTITLE:                //如果是title   即為[Action N]
    if(flag == OUT) 
     flag = IN;                 //標記改為已讀取
    status = act_GetGroupACT(item.itemname, &node->actno);       //讀取Action的編號
    if(status == SUCCESS){
     node->type = ACT_START;              //節點type改為ACT_START
     status = act_InsertPool(&def->actpool, &def->actidx);
    }
    break;
   case INI_GROUPITEM:                 //如果是item
    if(flag == IN)                 //如果標記為未讀過  代表沒有title
     status = act_ParseItem(def, &item);           //要依照指令去分別編寫
    else
     status = ACT_OFFSET + NOGROUP_ITEM;
    break;
   case INI_UNKNOWNITEM:
    return ACT_OFFSET + UNKNOWN_LINE;
  }
 }
 ini_FileClose(fp);
// follow code are move to def_ParseFile_DEF for not only one act file case
// node = &def->actpool[def->actidx];
// node->type = ACT_START;
// node->actno = -1;
// status = act_InsertPool(&def->actpool, &def->actidx);
 return status;
}

/*===========================  tool for cmd file  ===========================*/
static void cmd_InitCMD(CMD_NODE *node)               //預設cmd的值
{
 node->actno = -1;
 node->command = -1;
 node->name[0] = '\0';
 node->next = NULL;

}

static int cmd_GetItemCMD(char *str, int *cmd)             //讀取cmd的值
{
 int i;
 if(strlen(str) == 1){                  //先判斷指令是否為正常的英文
  if(str[0] >= 'A' && str[0] <= 'Z')
   *cmd = str[0];
  else if(str[0] >= 'a' && str[0] <= 'z')
   *cmd = str[0] - 'a' + 'A';
  else
   return CMD_OFFSET + INVALID_VALUE;
 }
 else{                      //或是特殊的按鍵   EX: F1
  for(i = 0; i < NUM_SKEY; i++){
   if(_stricmp(str, SKey[i].name) == 0)
    break;
  }
  if(i == NUM_SKEY)                  //全部找完   還不在範圍內  代表有誤
   return CMD_OFFSET + INVALID_VALUE;
  *cmd = SKey[i].value;                 //將指令改為特定的值
 }
 return SUCCESS;
}

static int cmd_GetItemACT(char *str, int *actno)            //取得act的編號
{
 int status;
 status = ini_GetValue(str, actno);               //取得act的編號
 if(status != SUCCESS)
  return CMD_OFFSET + INVALID_VALUE;
 return SUCCESS;
}

static int cmd_CheckCMD(CMD_NODE *cmd)               //檢查有沒有缺少的
{
 if(cmd->actno == -1)
  return CMD_NO_ACTNO;
 if(cmd->command == -1)
  return CMD_NO_CMD;
 if(strlen(cmd->name) == 0)
  return CMD_NO_NAME;
 return SUCCESS;
}

static int cmd_InsertPool(CMD_NODE **pool, int *idx)           //倍增節點
{
 int i;
 int size;
 *idx += 1;
 if(*idx % BASE_CMD == 0){
  size = *idx * 2;
  *pool = (CMD_NODE *)realloc(*pool, sizeof(CMD_NODE) * size);
  if(*pool == NULL)
   return MEMORY_ERROR;
  for(i = *idx; i < size; i++)
   cmd_InitCMD(&(*pool)[i]);
 }
 return SUCCESS;
}

static int cmd_InsertCMD(DEF_t *def, CMD_NODE *cmd)            //要插入新指令時用
{
 int status = SUCCESS;
 status = cmd_CheckCMD(cmd);                 //檢查有沒有少東西
 if(status == SUCCESS)
  status = cmd_InsertPool(&def->cmdpool, &def->cmdidx);         //倍增節點用
 return status;
}

static int def_ParseFile_CMD(DEF_t *def, char *filename)
{
 int status = SUCCESS;
 int flag = OUT;
 CMD_NODE *cmd;
 INI_ITEM_t item;
 FILEIO *fp;

 fp = ini_FileOpen(GetPath(filename));              //開啟檔案
 if(fp == NULL)
  return CMD_OFFSET + OPEN_FILE_FAIL;
 while ((status == SUCCESS) && (ini_ReadNextItem(fp, &item) != INI_FILEEND))     //讀取內容   改為INI_ITEM_t形式
 {
  switch(item.type){                  //依型態判斷要做什麼
   case INI_GROUPTITLE:                //如果是title   即為[Command]
    if(ini_IsGroup(&item, "command")){            //判斷title
     if(flag == IN) // insert before cmd           //有新增過的話
      status = cmd_InsertCMD(def, cmd);          
     else
      flag = IN;
    }
    else
     return CMD_OFFSET + INVALID_GROUP;
    cmd = &def->cmdpool[def->cmdidx];
    break;
   case INI_GROUPITEM:                 //如果是item   即name = XXX   command = XX...
    if(flag == OUT)                 //沒標記過代表沒有Title  格式有誤
     return CMD_OFFSET + NOGROUP_ITEM;
    if(ini_IsItem(&item, "name"))             
     strcpy(cmd->name, item.itemvalue);           //name只要複製名稱就好
    else if(ini_IsItem(&item, "action"))           
     status = cmd_GetItemACT(item.itemvalue, &cmd->actno);      //action   要取得action的編號
    else if(ini_IsItem(&item, "command"))
     status = cmd_GetItemCMD(item.itemvalue, &cmd->command);      //command   要讀出按鍵的值
    else
     return CMD_OFFSET + INVALID_NAME;
    break;
   case INI_UNKNOWNITEM:
    return CMD_OFFSET + UNKNOWN_LINE;
  }
 }
 if(status == SUCCESS)
  status = cmd_InsertCMD(def, cmd);
 ini_FileClose(fp);
 return status;
}

/*===========================  tool for def file  ===========================*/

static int def_GetCH(char *str, int *ch)              //抓channel的編號
{
 int status;
 status = ini_GetCH(str, ch);                //抓channel的編號
 if(status == SUCCESS)
  return SUCCESS;
 return DEF_CH_INVALID_CH;
}

static int def_GetPINS(char *str, int *pin)              //抓pin的編號
{
 int status;
 status = ini_ParseNumber_pre(str, "S", pin);            //抓pin的編號
 *pin -= 1;                     //判斷重複用
 if(status == SUCCESS)
 if((*pin <= 31) && (*pin >= 0))                //判斷要為S0 ~ S31
  return SUCCESS;
 return DEF_CH_INVALID_PIN;
}

static int def_GetMode(char *str, int *mode_idx)
{
 int i;
 for(i = 0; i < NUM_SERVO; i++){                //執行NUM_SERVO個servo名稱
  if(_stricmp(str, Servo[i].name) == 0)             //判斷輸入的servo是否正確
   break;
 }
 if(i < NUM_SERVO){                   
  *mode_idx = i;
  return SUCCESS;
 }
 else                      //如果不是中途跳出   代表輸入的內容不在範圍內
  return DEF_CH_INVALID_MODE;
}

static int def_ParseItem_Channels(DEF_t* def, INI_ITEM_t* item)         //抓channels group的內容
{
 int status;
 int ch, pin, mode_idx;
 char *str1, *str2;
 status = def_GetCH(item->itemname, &ch);             //抓channel 的編號

 if(status == SUCCESS)
  status = ini_DivideString(item->itemvalue, &str1, &str2, ",");       //以","分割字串
 if(status == SUCCESS)
  status = def_GetPINS(str1, &pin);              //抓pin的編號
 if(status == SUCCESS)
  status = def_GetMode(str2, &mode_idx);             //抓模式的字串
 if(status == SUCCESS){
  if(def->channel[ch].pin != -1)               //判斷重複用
   return DEF_CH_REPEAT_CH;
  if((def->usedChannels & (1L << pin)) != 0)            //判斷重複用    
   return DEF_CH_REPEAT_PIN;
  def->usedChannels |= (1L << pin);              //把要用的channel加進去
  def->channel[ch].pin = pin;
  def->channel[ch].mode_idx = mode_idx;
 }
 return status;
}

static int def_GetValueFrmMode(char *str, int *mode)           //判斷字串 true/false
{
 if((str == NULL) || (_stricmp(str, "false") == 0))
  *mode = INIT_FRM_FALSE;
 else if(_stricmp(str, "true") == 0)
  *mode = INIT_FRM_TRUE;
 else          
  return DEF_SET_INVALID_MODE;
 return SUCCESS;
}

static int def_GetItemRBVer(char *str, int *rbidx)            //抓取RB型號
{
 int i;
 for(i = 0; i < NUM_RBVer; i++){                //執行NUM_RBVer次   即RB型號個數
  if(_stricmp(str, RBVer[i].name) == 0)
   break;
 }
 if(i < NUM_RBVer){
  *rbidx = i;
  return SUCCESS;
 }             
 else                      //如果不是中途跳出   代表輸入的內容不在範圍內
  return DEF_SET_OFFSET + INVALID_VALUE;
}

static int def_GetItemInitFrm(char *str, int *frmno, int *mode)         //抓取HomeFrame的內容  
{
 int status;
 char *str1, *str2;
 status = ini_DivideString(str, &str1, &str2, ",");           //以","作分隔分開字串
 if(status == INI_DIVIDE_FAIL){
  str1 = str;
  str2 = NULL;
 }
 status = ini_GetValue(str1, frmno);               //取得frm編號
 if(status != SUCCESS)
  return DEF_SET_INVALID_FRMNO;
 status = def_GetValueFrmMode(str2, mode);             //判斷字串 true/false
 return status;
}

static int def_ParseItem_Settings(DEF_t* def, INI_ITEM_t* item)         //判斷settings group的內容   以便去做各種事情
{
 int status = SUCCESS;

 if (ini_IsItem(item, "initaction") == true){            //判斷item是否為initaction
  status = ini_GetValue(item->itemvalue, &def->initact);         //抓取值
  if(status != SUCCESS)
   return DEF_SET_OFFSET + INVALID_VALUE;
 }
 else if(ini_IsItem(item, "homeframe") == true)            //判斷item是否為homeframe
  status = def_GetItemInitFrm(item->itemvalue, &def->initfrm, &def->initfrm_mode);  //抓取HomeFrame的內容 
 else if(ini_IsItem(item, "roboard") == true)            //判斷item是否為roboard 
  status = def_GetItemRBVer(item->itemvalue, &def->rbidx);        //抓取RB型號
 else
  status = DEF_SET_OFFSET + INVALID_NAME;

 return status;
}

static int def_ParseItem_File(DEF_t *def, INI_ITEM_t *item)          //中繼站   來什麼就去開什麼黨來讀
{
 int status;

 if (ini_IsItem(item, "cmd") == true)
  status = def_ParseFile_CMD(def, item->itemvalue);
 else if(ini_IsItem(item, "act") == true)
  status = def_ParseFile_ACT(def, item->itemvalue);
 else if(ini_IsItem(item, "frame") == true)
  status = def_ParseFile_FRM(def, item->itemvalue);
 else if(ini_IsItem(item, "offset") == true)
  status = def_ParseFile_TXT(def, item->itemvalue);
 else
  status = DEF_FIL_OFFSET + INVALID_NAME;
 return status;
}


static int def_ParseFile_DEF(char* filename, DEF_t* def)
{
    #define DEFGROUP_INFO      (0)
    #define DEFGROUP_FILES     (1)
    #define DEFGROUP_CHANNELS  (2)
    #define DEFGROUP_SETTINGS  (3)
 #define DEFGROUP_UNSET     (4)
 FILEIO *fp;
    INI_ITEM_t item;
 int gflag = DEFGROUP_UNSET;
 int status = SUCCESS;

// demofile_InitialDEF(def);
 fp = ini_FileOpen(GetPath(filename));              //開啟檔案
 if(fp == NULL)
  return DEF_OFFSET + OPEN_FILE_FAIL;

 while ((status == SUCCESS) && (ini_ReadNextItem(fp, &item) != INI_FILEEND))     //讀取內容   並轉成INI_ITEM_t結構內容
 {
  switch(item.type)
        {
            case INI_GROUPTITLE:                //如果是title   即為[Info]...
    if (ini_IsGroup(&item, "Info") == true)
     gflag = DEFGROUP_INFO;         
    else if (ini_IsGroup(&item, "Files") == true)
     gflag = DEFGROUP_FILES;         
    else if (ini_IsGroup(&item, "Channels") == true)
     gflag = DEFGROUP_CHANNELS;
    else if (ini_IsGroup(&item, "Settings") == true)
     gflag = DEFGROUP_SETTINGS;
    else
     status = DEF_OFFSET + INVALID_GROUP;
                break;
            case INI_GROUPITEM:                 //如果是item   即為 XXX = XXXX...
    switch(gflag)                 //依照gflag去分別看
    {
     case DEFGROUP_CHANNELS:
      status = def_ParseItem_Channels(def, &item);
      break;
     case DEFGROUP_SETTINGS:
      status = def_ParseItem_Settings(def, &item);
      break;
     case DEFGROUP_FILES:
      status = def_ParseItem_File(def, &item);
      break;
     case DEFGROUP_INFO:
      break;
     case DEFGROUP_UNSET:
      status = DEF_OFFSET + NOGROUP_ITEM;

    }
                break;
   case INI_UNKNOWNITEM:
    if(gflag != DEFGROUP_INFO)
    status = DEF_OFFSET + UNKNOWN_LINE;
    break;
        } //end switch(item...
    } //end while(ini_...

 ini_FileClose(fp);                   //關閉檔案
 // Set "end" for last action 
 if(status == SUCCESS){
  def->actpool[def->actidx].type = ACT_START;
  def->actpool[def->actidx].actno = -1;
  status = act_InsertPool(&def->actpool, &def->actidx);
 }
 return status;

}

/*===========================  tool function   ===========================*/
int tool_GetItemRBVer(char *str, int *rbidx)
{
 return def_GetItemRBVer(str, rbidx);
}

int tool_GetMode(char *str, int *mode_idx)
{
 return def_GetMode(str, mode_idx);
}

int tool_GetGroupFRM(char *str, int *frmno)
{
 return frm_GetGroupFRM(str, frmno);
}

int tool_InsertACTPool(ACT_NODE **pool, int *idx)
{
 return act_InsertPool(pool, idx);
}

int tool_ParseFile_FRM(DEF_t *def, char *filename)
{
 strcpy(FileDir, "");
 return def_ParseFile_FRM(def, filename);
}

int tool_ReadFile(char* dirname, DEF_t* def)
{
 int i;
 char filename[255];
 i = (int)strlen(dirname);

 strcpy(FileDir, dirname);
 if(FileDir[i-1] != '/')
  strcat(FileDir, "/");

 while (( i = (int)strcspn(dirname, "/\\")) != strlen(dirname))
  dirname = &dirname[i + 1];
 strcpy(filename, dirname);
 strcat(filename, ".def");
 return def_ParseFile_DEF(filename, def);
}

int tool_InitDEF(DEF_t *def)                 //初始化DEF_t的值
{
 int i;

 def->usedChannels = 0L;
 def->initact = -1;
 def->initfrm = -1;
 def->initfrm_mode = INIT_FRM_FALSE;
 def->inithome = NULL;
 def->initactnode = NULL;
 for (i=0; i<32; i++) {
  def->channel[i].pin = -1;
  def->channel[i].mode_idx = 0;
  def->channel[i].offset = 0;
 }

 def->actidx = 0;
 def->actpool = (ACT_NODE *)malloc(sizeof(ACT_NODE) * BASE_ACT);
 def->acttable = NULL;

 def->cmdidx = 0;
 def->cmdpool = (CMD_NODE *)malloc(sizeof(CMD_NODE) * BASE_CMD);
 def->cmdtable = NULL;

 def->frmidx = 0;
 def->frmpool = (FRM_NODE *)malloc(sizeof(FRM_NODE) * BASE_FRM);
 def->frmtable = NULL;

 if((def->actpool == NULL) || (def->cmdpool == NULL) || (def->frmpool == NULL))
  return MEMORY_ERROR;
 for(i = 0; i < BASE_ACT; i++)
  act_InitACT(&def->actpool[i]);
 for(i = 0; i < BASE_CMD; i++)
  cmd_InitCMD(&def->cmdpool[i]);
 for(i = 0; i < BASE_FRM; i++)
  frm_InitFRM(&def->frmpool[i]);
 return SUCCESS;
}

void tool_FreeDEF(DEF_t *def)                 //刪掉創出來的空間
{
 free(def->actpool);
 free(def->cmdpool);
 free(def->frmpool);
 free(def->acttable);
 free(def->cmdtable);
 free(def->frmtable);
}


Share:

2012/3/19

[RoBoRC第六回] 介紹程式碼userio

這一次要介紹的是userio

userio主要是使用於接收key的值及一些常用的函式

什麼?

覺得接收key很簡單?

當然...在一平台下會認為接收key很簡單

但這userio可是適用於各個平台!

不管是LINUX,WINCE...等等

幾乎都可以執行

接下來就來研究看看吧!



userio.h
#ifndef __USERIO_H
#define __USERIO_H

#include "defines.h"


#ifdef __cplusplus
extern "C" {
#endif

//MESSAGE
bool msg_SetLogFile(char* logfile);
void msg_CloseLogFile(void);

void showmsg(const char* fmt, ...);


//KEYBOARD:
void keyboard_init(int type);
#define KEYBOARD_STD    (1)
#define KEYBOARD_ADV    (2)

void keyboard_close(void);

unsigned keyboard_getkey(void);
unsigned keyboard_waitkey(void);
#define KBENTER         (0x000d)
#define KBTAB           (0x0009)
#define KBESC           (0x001b)
#define KBBACKSPACE     (0x0008)
#define KBSPACE         (0x0020)

#define KBLEFT          (0x0025)
#define KBRIGHT         (0x0027)
#define KBUP            (0x0026)
#define KBDOWN          (0x0028)

#define KBHOME          (0x0024)
#define KBEND           (0x0023)
#define KBPGUP          (0x0021)
#define KBPGDN          (0x0022)

#define KBINS           (0x002d)
#define KBDEL           (0x002e)

#define KBF1            (0x0070)
#define KBF2            (0x0071)
#define KBF3            (0x0072)
#define KBF4            (0x0073)
#define KBF5            (0x0074)
#define KBF6            (0x0075)
#define KBF7            (0x0076)
#define KBF8            (0x0077)
#define KBF9            (0x0078)
#define KBF10           (0x0079)
#define KBF11           (0x007a)
#define KBF12           (0x007b)

#define KBSHIFT         (0x0010)
#define KBLSHIFT        (0x00a0)
#define KBRSHIFT        (0x00a1)
#define KBCTRL          (0x0011)
#define KBLCTRL         (0x00a2)
#define KBRCTRL         (0x00a3)
#define KBALT           (0x0012)
#define KBLALT          (0x00a4)
#define KBRALT          (0x00a5)

#ifdef __cplusplus
}
#endif
#endif





userio.cpp
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>

#ifdef USE_RBDLL
 #define  USE_COMMON
 #include <roboard_dll.h>
#else
 #define  USE_COMMON
 #include <roboard.h>
#endif
#include "userio.h"


#if defined(RB_LINUX)
    #include <unistd.h>
    //#include <termios.h>
    #include <ncurses.h>
#elif defined(RB_MSVC_WIN32)
    #include <windows.h>
    #include <conio.h>
#elif defined(RB_MSVC_WINCE)
    #include <windows.h>
#elif defined(RB_BC_DOS) || defined(RB_DJGPP)
    #include <conio.h>
    #define _getch getch
    #define _kbhit kbhit
#endif

#define KEYBOARD_NOUSE  (0)
static int keyboard_inUse = KEYBOARD_NOUSE;



/*****************  Common Message Functions  ******************/
static FILE* MSG_outputDevice = stdout;

bool msg_SetLogFile(char* logfile) {
    msg_CloseLogFile();

 if (logfile == NULL)                  //logfile為NULL  就把MSG_outputDevice也改為NULL  回傳true
 {
  MSG_outputDevice = NULL;
  return true;
 }

 if ((MSG_outputDevice = fopen(logfile, "w")) != NULL) return true;       //如果開啟logfile成功  回傳true

 MSG_outputDevice = stdout;
    return false;
}

void msg_CloseLogFile(void) {                 //確定MSG_outputDevice為stdout
    if ((MSG_outputDevice != stdout) && (MSG_outputDevice != NULL))
        fclose(MSG_outputDevice);

 MSG_outputDevice = stdout;
}


#ifdef _MANAGED
 #pragma managed(push, off)
#endif
void showmsg(const char* fmt, ...) {               //show message在螢幕上
    char buf[256];
    va_list args;

 va_start(args, fmt);
 vsprintf(buf, fmt, args);
 va_end(args);

    #ifdef RB_LINUX
        if ((keyboard_inUse == KEYBOARD_STD) && (MSG_outputDevice == stdout))
        {
            printw("%s", buf);
            refresh();
            return;
        }
    #endif

 fprintf(MSG_outputDevice, "%s", buf);
    fflush(MSG_outputDevice);
}
#ifdef _MANAGED
 #pragma managed(pop)
#endif
/*-------------- end of Common Message Functions --------------*/



/*****************  Common Keyboard Functions  *****************/
static unsigned keymap[512] = 
    {
        0, 0, 0, 0, 0, 0, 0, 0, KBBACKSPACE, KBTAB, 0, 0, 0, KBENTER, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, KBESC, 0, 0, 0, 0,
        KBSPACE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',   0,   0,   0,   0,   0,   0,
          0, 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
        'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',   0,  0 ,   0,   0,   0,
          0, 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
        'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',   0,  0 ,   0,   0,   0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, KBF1, KBF2, KBF3, KBF4, KBF5,
        KBF6, KBF7, KBF8, KBF9, KBF10, 0, 0, KBHOME, KBUP, KBPGUP, 0, KBLEFT, 0, KBRIGHT, 0, KBEND,
        KBDOWN, KBPGDN, KBINS, KBDEL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, KBF11, KBF12, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
    };


void keyboard_init(int type) {                 //init keyboard
    if (keyboard_inUse != KEYBOARD_NOUSE) return; else keyboard_inUse = type;
    switch (type)
    {
        case KEYBOARD_STD:
            #if defined(RB_LINUX)
                initscr();
                cbreak();
                nonl();
                noecho();
                scrollok(stdscr, TRUE);
                nodelay(stdscr, TRUE);
                intrflush(stdscr,FALSE);
                keypad(stdscr,TRUE);
                refresh();
            #elif defined(RB_MSVC_WINCE)
    keyboard_getkey();
            #endif
   return;
        case KEYBOARD_ADV:
   return;
    }

 keyboard_inUse = KEYBOARD_NOUSE;
}

void keyboard_close(void) {                  //close keyboard
    if (keyboard_inUse == KEYBOARD_NOUSE) return;

    switch (keyboard_inUse)
    {
        case KEYBOARD_STD:
            #if defined(RB_LINUX)
                endwin();
            #elif defined(RB_MSVC_WINCE)
                fflush(stdin);
            #endif
            break;
        case KEYBOARD_ADV:
            break;
    }

    keyboard_inUse = KEYBOARD_NOUSE;
}


static unsigned keyboard_getkey_std(void) {              //讀取keyboard的值   適用各種平台
    #if defined(RB_LINUX)
        int c = getch();
        
        if ((c == 27) || ((c >= 0x20) && (c <= 0x7f))) return keymap[c];
    
        switch (c)
        {
            case KEY_BACKSPACE:
            case 127: //some linux maps BACKSPACE to delete (127)
                return KBBACKSPACE;
            case KEY_ENTER:
            case '\r':
                return KBENTER;
            case '\t':
                return KBTAB;
    
            case KEY_UP:    return KBUP;
            case KEY_DOWN:  return KBDOWN;
            case KEY_LEFT:  return KBLEFT;
            case KEY_RIGHT: return KBRIGHT;
    
            case KEY_HOME:  return KBHOME;
            case KEY_END:   return KBEND;
            case KEY_NPAGE: return KBPGDN;
            case KEY_PPAGE: return KBPGUP;
    
            case KEY_IC:    return KBINS;
            case KEY_DC:    return KBDEL;

            case KEY_F(1):  return KBF1;
            case KEY_F(2):  return KBF2;
            case KEY_F(3):  return KBF3;
            case KEY_F(4):  return KBF4;
            case KEY_F(5):  return KBF5;
            case KEY_F(6):  return KBF6;
            case KEY_F(7):  return KBF7;
            case KEY_F(8):  return KBF8;
            case KEY_F(9):  return KBF9;
            case KEY_F(10): return KBF10;
            case KEY_F(11): return KBF11;
            case KEY_F(12): return KBF12;

            case ERR:       return 0;
        }
        
        return 0;
    #elif defined(RB_MSVC_WINCE)
        static bool          vkeystat[256] = {false};
        static unsigned long vkeytime[256] = {0L};

        int c;
        unsigned firstkey = 0;
        
        for (c=0; c<512; c++)
        {
            if ((keymap[c] == 0) || ((c >= 'a') && (c <= 'z'))) continue;

            if ((GetAsyncKeyState(keymap[c]) & 0x8000) == 0)
                vkeystat[keymap[c]] = false;
            else
            if (vkeystat[keymap[c]] == false)
            {
    vkeystat[keymap[c]] = true;
                vkeytime[keymap[c]] = timer_nowtime() + 800L;
                if (firstkey == 0) firstkey = keymap[c];
            }
   else
   if (timer_nowtime() > vkeytime[keymap[c]])
   {
                vkeytime[keymap[c]] = timer_nowtime() + 90L;
                if (firstkey == 0) firstkey = keymap[c];
   }
        }

        return firstkey;
    #else
        int c;
        
        if (!_kbhit()) return 0; else c = _getch();

        if ((c != 0) && (c != 0xe0))
            return keymap[c];
        else
            return keymap[_getch() + 256];
    #endif
}


unsigned keyboard_getkey(void) {                //根據keyboard的狀態來回傳
    switch (keyboard_inUse)
    {
  case KEYBOARD_STD:
            return keyboard_getkey_std();
        case KEYBOARD_ADV:
         return 0;
    }//end switch (keyboard_inUse)

 return 0;
}

unsigned keyboard_waitkey(void) {                //等待按完一個按鍵才繼續動作
    unsigned c;

    if (keyboard_inUse == KEYBOARD_NOUSE) return 0;

 while ((c = keyboard_getkey()) == 0);
 return c;
}
/*----------------- end of Keyboard Functions -----------------*/

Share:

2012/3/12

[RoBoRC第五回] 介紹程式碼const & errcode

本周的RoBoRC介紹兩個程式

const 以及 errcode

別緊張

這兩個都沒有很難

本周就輕鬆一下吧~

const.h
這裡主要是定義結構用

#ifndef __CONST_H
#define __CONST_H

#define NUM_SERVO (17)
#define NUM_RBVer (7)
#define NUM_SKEY  (17)

typedef struct _strint_{
 const char* name;
 unsigned int value;
}STRINT;

typedef struct _servo_{
 const char* name;
 unsigned int value;
 bool feedback;
}_SERVO;

typedef _SERVO SERVO[NUM_SERVO];
typedef STRINT SKEY[NUM_SKEY];
typedef STRINT RBVER[NUM_RBVer];

extern SERVO Servo;
extern RBVER RBVer;
extern SKEY SKey;

#endif



const.cpp
剛剛定義結構的內容   有servo,RBver等

#include "rcservo.h"
#include "userio.h"
#include "common.h"
#include "const.h"

 
_SERVO Servo[] = {
    {"DEFAULT", RCSERVO_SERVO_DEFAULT, true},
    {"DEFAULT_NOFB", RCSERVO_SERVO_DEFAULT_NOFB, false},
    {"KONDO_KRS786", RCSERVO_KONDO_KRS786, true},
    {"KONDO_KRS788", RCSERVO_KONDO_KRS788, true},
    {"KONDO_KRS78X", RCSERVO_KONDO_KRS78X, true},
    {"KONDO_KRS4014", RCSERVO_KONDO_KRS4014, true},
    {"KONDO_KRS4024", RCSERVO_KONDO_KRS4024, true},
    {"HITEC_HSR8498", RCSERVO_HITEC_HSR8498, true},
    {"FUTABA_S3003", RCSERVO_FUTABA_S3003, false},
    {"SHAYYE_SYS214050", RCSERVO_SHAYYE_SYS214050, false},
    {"TOWERPRO_MG995", RCSERVO_TOWERPRO_MG995, false},
    {"TOWERPRO_MG996", RCSERVO_TOWERPRO_MG996, false},
    {"DMP_RS0263", RCSERVO_DMP_RS0263, false},
 {"DMP_RS1270", RCSERVO_DMP_RS1270, false},
 {"GWS_S777", RCSERVO_GWS_S777, false},
 {"GWS_S03T", RCSERVO_GWS_S03T, false},
 {"GWS_MICRO", RCSERVO_GWS_MICRO, false}
};

STRINT RBVer[] = {
 {"RB_100b1", RB_100b1},
 {"RB_100b2", RB_100b2},
 {"RB_100b3", RB_100b3},
 {"RB_100", RB_100},
 {"RB_100RD", RB_100RD},
 {"RB_110", RB_110},
 {"RB_050", RB_050}
};

STRINT SKey[] = {
    {"F1",  KBF1},
    {"F2",  KBF2},
    {"F3",  KBF3},
    {"F4",  KBF4},
    {"F5",  KBF5},
    {"F6",  KBF6},
    {"F7",  KBF7},
    {"F8",  KBF8},
    {"F9",  KBF9},
    {"F10", KBF10},
    {"F11", KBF11},
    {"F12", KBF12},
    {"ENTER", KBENTER},
// {"SPACE", KBSPACE},
    {"UP",    KBUP},
    {"DOWN",  KBDOWN},
    {"LEFT",  KBLEFT},
    {"RIGHT", KBRIGHT}
// {"PGUP",  KBPGUP},
// {"PGDN",  KBPGDN}
};

errcode.h
顧名思義,error code用    將一些錯誤條件define為值

#ifndef __ERRCODE_H
#define __ERRCODE_H

#define SUCCESS 0

// ================= demofile error cede ==================
// for general case
#define OFFSET     0
#define OPEN_FILE_FAIL   (OFFSET+0)
#define UNKNOWN_LINE   (OFFSET+1) //not [XXX] , XX = YY
#define INVALID_GROUP   (OFFSET+2) 
#define NOGROUP_ITEM   (OFFSET+3)
#define INVALID_NAME   (OFFSET+4)
#define INVALID_VALUE   (OFFSET+5)


// for def file
#define DEF_OFFSET    100
// in  [setting] group
#define DEF_SET_OFFSET   200
#define DEF_SET_INVALID_FRMNO (DEF_SET_OFFSET+6)
#define DEF_SET_INVALID_MODE (DEF_SET_OFFSET+7)
// in [channel] group
#define DEF_CH_OFFSET   300
#define DEF_CH_INVALID_CH  (DEF_CH_OFFSET+6)
#define DEF_CH_REPEAT_CH  (DEF_CH_OFFSET+7)
#define DEF_CH_INVALID_PIN  (DEF_CH_OFFSET+8)
#define DEF_CH_REPEAT_PIN  (DEF_CH_OFFSET+9)
#define DEF_CH_INVALID_MODE  (DEF_CH_OFFSET+10)
// in [Files] group
#define DEF_FIL_OFFSET   400
// for cmd file
#define CMD_OFFSET    500
#define CMD_NO_ACTNO   (CMD_OFFSET+6)
#define CMD_NO_CMD    (CMD_OFFSET+7)
#define CMD_NO_NAME    (CMD_OFFSET+8)


// for act file
#define ACT_OFFSET    600
#define ACT_INVALID_FRMNO  (ACT_OFFSET+6)
#define ACT_INVALID_TIME  (ACT_OFFSET+7)

// for frm file
#define FRM_OFFSET    700
#define FRM_REPEAT_CH   (FRM_OFFSET+6)

// for offset file
#define TXT_OFFSET    800
#define TXT_REPEAT_CH   (TXT_OFFSET+6)
// +++++++++++++++++++++++ end +++++++++++++++++++++++


// code for fileio
#define FILEIO_OFFSET   900
#define INI_FILEEND    (FILEIO_OFFSET+0)
#define INI_INVALID_CH   (FILEIO_OFFSET+1)
#define INI_INVALID_VALUE  (FILEIO_OFFSET+2) 
#define INI_DIVIDE_FAIL   (FILEIO_OFFSET+3) //string doesn't have separate char
#define INI_DIVIDE_STR1   (FILEIO_OFFSET+4)
#define INI_DIVIDE_STR2   (FILEIO_OFFSET+5)
#define INI_INVALID_NO   (FILEIO_OFFSET+6)
#define INI_INVALIDCHANNEL  (FILEIO_OFFSET+7)
#define INI_NUMPRE_NULL   (FILEIO_OFFSET+8)
#define INI_NUMPRE_INVALID  (FILEIO_OFFSET+9)
#define INI_NUMPRE_FAIL   (FILEIO_OFFSET+10)
#define INI_NUMPOST_NULL  (FILEIO_OFFSET+11)  // str = NULL
#define INI_NUMPOST_INVALID  (FILEIO_OFFSET+12) // unit error
#define INI_NUMPOST_FAIL  (FILEIO_OFFSET+13) // value error

//memory error
#define MEMORY_ERROR   (1000)

// fode for map
#define MAP_OFFSET    1100
#define MAP_NOFINDINITFRM  (MAP_OFFSET+0)
#define MAP_NOFINDFRM   (MAP_OFFSET+1)
#define MAP_REPEAT_FRMNO  (MAP_OFFSET+2)
#define MAP_NOFINEINITACT  (MAP_OFFSET+3)
#define MAP_NOFINDACT   (MAP_OFFSET+4)
#define MAP_REPEAT_ACTNO  (MAP_OFFSET+5)
#define MAP_REPEAT_CMD   (MAP_OFFSET+6)

#ifdef __cplusplus
extern "C" {
#endif

void errcode_ShowErr(int code);
void errcode_SetErrStr(const char *str);
void errcode_SetErrGroup(const char *str);
void errcode_SetErrFRM(const int frmno);
void errcode_SetErrACT(const int actno);
void errcode_SetErrCMD(const int cmd);

#ifdef __cplusplus
}
#endif

#endif


errcode.cpp
error code輸出錯誤訊息用

#include <string.h>
#include "errcode.h"
#include "userio.h"
#include "const.h"

#define DIVISOR  100
#define DEF   (DEF_OFFSET / DIVISOR)
#define DEF_SET  (DEF_SET_OFFSET / DIVISOR)
#define DEF_CH  (DEF_CH_OFFSET / DIVISOR)
#define DEF_FILE (DEF_FIL_OFFSET / DIVISOR)
#define CMD   (CMD_OFFSET / DIVISOR)
#define ACT   (ACT_OFFSET / DIVISOR)
#define FRM   (FRM_OFFSET / DIVISOR)
#define TXT   (TXT_OFFSET / DIVISOR)
#define MAP   (MAP_OFFSET / DIVISOR)

static char ErrLine[1024] = "";
static char ErrFile[256] = "";
static char ErrGroup[256] = "";
static int errfrm;
static int erract;
static char errcmd[10];

static void def_ErrShow(int code);
static void def_SetErrShow(int code);
static void def_CHErrShow(int code);
static void def_FileErrShow(int code);
static void cmd_ErrShow(int code);
static void act_ErrShow(int code);
static void frm_ErrShow(int code);
static void txt_ErrShow(int code);
static void map_ErrShow(int code);

static void map_ErrShow(int code)
{
 int i = code % DIVISOR;
 const char *str[] = {
  "map : can't find initial frame : %d\n",
  "map : an act has an undefined frame : %d\n",
  "map : repeat frame number : %d\n",
  "map : can't find initial action : %d\n",
  "map : a command point to an undefined act : %d\n",
  "map : repeat action  number : %d\n",
  "map : repeat command : %s\n"
 };
 switch(i){
  case 0: case 1: case 2:
   showmsg(str[i], errfrm);
   break;
  case 3: case 4: case 5:
   showmsg(str[i], erract);
   break;
  case 6:
   showmsg(str[i], errcmd);
   break;
 }
}

static void def_SetErrShow(int code)
{
 int i = code % DIVISOR;
 strcpy(ErrFile,"def");
 strcpy(ErrGroup, "Setting");
 const char *str[] = {
  "Open %s file fail\n",
  "%s file : unknown line : %s\n",
  "%s file : invalid group : %s\n",
  "%s file : no group item : %s\n",
  "%s file : invalid item name appears in group %s : %s",
  "%s file : invalid item value appears in group %s : %s",
  "%s file : invalid frame number appears in group %s : %s",
  "%s file : invalid initial frame mode appears in group %s : %s"
 };
 switch(i){
  case 0:
   showmsg(str[i], ErrFile);
   break;
  case 1: case 2: case 3:
   showmsg(str[i], ErrFile, ErrLine);
   break;
  default:
   showmsg(str[i], ErrFile, ErrGroup, ErrLine);
   break;
 }
}

static void def_CHErrShow(int code)
{
 int i = code % DIVISOR;
 strcpy(ErrFile,"def");
 strcpy(ErrGroup, "Channels");
 const char *str[] = {
  "Open %s file fail\n",
  "%s file : unknown line : %s\n",
  "%s file : invalid group : %s\n",
  "%s file : no group item : %s\n",
  "%s file : invalid item name appears in group %s : %s",
  "%s file : invalid item value appears in group %s : %s",
  "%s file : invalid channel appears in group %s : %s",
  "%s file : repeat channel appears in group %s : %s",
  "%s file : invalid pin appears in group %s : %s",
  "%s file : repeat pin appears in group %s : %s",
  "%s file : invalid servo mode appears in group %s : %s"
 };
 switch(i){
  case 0:
   showmsg(str[i], ErrFile);
   break;
  case 1: case 2: case 3:
   showmsg(str[i], ErrFile, ErrLine);
   break;
  default:
   showmsg(str[i], ErrFile, ErrGroup, ErrLine);
   break;
 }
}

static void def_FileErrShow(int code)
{
 int i = code % DIVISOR;
 strcpy(ErrFile,"def");
 strcpy(ErrGroup, "Files");
 const char *str[] = {
  "Open %s file fail\n",
  "%s file : unknown line : %s\n",
  "%s file : invalid group : %s\n",
  "%s file : no group item : %s\n",
  "%s file : invalid item name appears in group %s : %s",
  "%s file : invalid item value appears in group %s : %s"
 };
 switch(i){
  case 0:
   showmsg(str[i], ErrFile);
   break;
  case 1: case 2: case 3:
   showmsg(str[i], ErrFile, ErrLine);
   break;
  default:
   showmsg(str[i], ErrFile, ErrGroup, ErrLine);
   break;
 }
}

static void cmd_ErrShow(int code)
{
 int i = code % DIVISOR;
 strcpy(ErrFile,"cmd");
 const char *str[] = {
  "Open %s file fail\n",
  "%s file : unknown line : %s\n",
  "%s file : invalid group : %s\n",
  "%s file : no group item : %s\n",
  "%s file : invalid item name appears : %s\n",
  "%s file : invalid item value appears : %s\n",
  "%s file : a command don't define active number\n",
  "%s file : a command don't define command key\n",
  "%s file : a command don't define command name\n",
 };
 switch(i){
  case 0: case 6: case 7: case 8: case 9:
   showmsg(str[i], ErrFile);
   break;
  case 1: case 2: case 3: case 4: case 5:
   showmsg(str[i], ErrFile, ErrLine);
   break;
 }
}

static void act_ErrShow(int code)
{
 int i = code % DIVISOR;
 strcpy(ErrFile,"act");
 const char *str[] = {
  "Open %s file fail\n",
  "%s file : unknown line : %s\n",
  "%s file : invalid group : %s\n",
  "%s file : no group item : %s\n",
  "%s file : invalid item name appears in group %s : %s",
  "%s file : invalid item value appears in group %s : %s",
  "%s file : invalid frame number in group %s : %s",
  "%s file : incalid time appears in group %s : %s"
 };
 switch(i){
  case 0:
   showmsg(str[i], ErrFile);
   break;
  case 1: case 2: case 3:
   showmsg(str[i], ErrFile, ErrLine);
   break;
  default:
   showmsg(str[i], ErrFile, ErrGroup, ErrLine);
   break;
 }
}

static void frm_ErrShow(int code)
{
 int i = code % DIVISOR;
 strcpy(ErrFile,"frm");
 const char *str[] = {
  "Open %s file fail\n",
  "%s file : unknown line : %s\n",
  "%s file : invalid group : %s\n",
  "%s file : no group item : %s\n",
  "%s file : invalid item name appears in group %s : %s",
  "%s file : invalid item value appears in group %s : %s",
  "%s file : repeat channal in group %s : %s"
 };
 switch(i){
  case 0:
   showmsg(str[i], ErrFile);
   break;
  case 1: case 2: case 3:
   showmsg(str[i], ErrFile, ErrLine);
   break;
  default:
   showmsg(str[i], ErrFile, ErrGroup, ErrLine);
   break;
 }
}

static void txt_ErrShow(int code)
{
 int i = code % DIVISOR;
 strcpy(ErrFile,"offset");
 const char *str[] = {
  "Open %s file fail\n",
  "%s file : unknown line : %s\n",
  "%s file : invalid group : %s\n",
  "%s file : no group item : %s\n",
  "%s file : invalid item name appears : %s",
  "%s file : invalid item value appears : %s",
  "%s file : repeat channal : %s",
 };
 switch(i){
  case 0:
   showmsg(str[i], ErrFile);
   break;
  default:
   showmsg(str[i], ErrFile, ErrLine);
   break;
 }
}

static void def_ErrShow(int code)
{
 int i = code % DIVISOR;
 strcpy(ErrFile,"def");
 const char *str[] = {
  "Open %s file fail\n",
  "%s file : unknown line : %s\n",
  "%s file : invalid group : %s\n",
  "%s file : no group item : %s\n",
  "%s file : invalid item name appears in group %s : %s",
  "%s file : invalid item value appears in group %s : %s"
 };
 switch(i){
  case 0:
   showmsg(str[i], ErrFile);
   break;
  case 1: case 2: case 3:
   showmsg(str[i], ErrFile, ErrLine);
   break;
  default:
   showmsg(str[i], ErrFile, ErrGroup, ErrLine);
   break;
 }
}

void errcode_ShowErr(int code)
{
 int i;
 i = code / DIVISOR;
 switch(i){
  case DEF:
   def_ErrShow(code);
   break;
  case DEF_SET:
   def_SetErrShow(code);
   break;
  case DEF_CH:
   def_CHErrShow(code);
   break;
  case DEF_FILE:
   def_FileErrShow(code);
   break;
  case CMD:
   cmd_ErrShow(code);
   break;
  case ACT:
   act_ErrShow(code);
   break;
  case FRM:
   frm_ErrShow(code);
   break;
  case TXT:
   txt_ErrShow(code);
   break;
  case MAP:
   map_ErrShow(code);
 }
 showmsg("\nPress any key to quit\n");
 keyboard_waitkey();
}

void errcode_SetErrFRM(const int frmno)
{
 errfrm = frmno;
}

void errcode_SetErrACT(const int actno)
{
 erract = actno;
}
void errcode_SetErrGroup(const char *str)
{
 strcpy(ErrGroup, str);
}

void errcode_SetErrStr(const char *str)
{
 strcpy(ErrLine, str);
}

void errcode_SetErrCMD(const int cmd)
{
 int i;
 if((cmd > 'A') && (cmd < 'Z')){
  errcmd[0] = cmd;
  errcmd[1] = '\0';
 }
 else{
  for(i = 0; i < NUM_SKEY; i++){
   if(cmd == SKey[i].value)
    strcpy(errcmd, SKey[i].name);
  }
 }
}  





基本上這邊講的都蠻簡單的

也可以當作複習基本功囉~

下次開始就要進入較麻煩的部分了

敬請期待

Share:
技術提供:Blogger.

追蹤者