終於來到最終回了
而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有相當的了解!
以上!