我會帶大家看程式碼的內容
以及功用~!!
roborc.cpp
主要是用於讀取檔案以及整體架構
下面依序會有註解
#include <stdio.h> #include <stdlib.h> #include <string.h> #ifdef WINCE #include <tchar.h> #endif #ifdef USE_RBDLL #define USE_COMMON #include <roboard_dll.h> #else #define USE_COMMON #include <roboard.h> #endif #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 #include "const.h" #include "userio.h" #include "errcode.h" #include "demo.h" #include "parse.h" //#if defined(RB_MSVC_WIN32) || defined(RB_MSVC_WINCE) // #include <windows.h> //#endif #if defined(RB_MSVC_WIN32) //#define USE_SOUND #endif #ifdef USE_SOUND //聲音用 #include "fileio.h" #include <irrKlang.h> using namespace irrklang; class CMyFileFactory : public irrklang::IFileFactory { public: virtual irrklang::IFileReader* createFileReader(const ik_c8* filename) { FILEIO* file = fileio_FileOpen((char*)filename, "rb"); if (!file) return 0; return new CMyReadFile(file, filename); } protected: class CMyReadFile : public irrklang::IFileReader { public: CMyReadFile(FILEIO* openedFile, const ik_c8* filename) { File = openedFile; strcpy(Filename, filename); FileSize = (ik_s32)fileio_GetSize(openedFile); } ~CMyReadFile() { fileio_FileClose(File); } ik_s32 read(void* buffer, ik_u32 sizeToRead) { return (ik_s32)fileio_Read(buffer, 1, sizeToRead, File); } bool seek(ik_s32 finalPos, bool relativeMovement) { return fileio_Seek(File, finalPos, relativeMovement ? SEEK_CUR : SEEK_SET) == 0; } ik_s32 getSize() { return FileSize; } ik_s32 getPos() { return fileio_GetPos(File); } const ik_c8* getFileName() { return Filename; } FILEIO* File; char Filename[1024]; ik_s32 FileSize; }; //end class CMyReadFile }; //end class CMyFileFactory #endif #define MODE_CAPTURES (1) #define MODE_REPLAYS (2) #define MODE_DEMO (100) static bool overwrite = false; static bool realtime = false; static bool showmessage = true; static unsigned long replaytime = 1000L; typedef struct _PLAY{ int rbidx; int mode_idx; int frameno; char* filename; unsigned long usedchannels; }PLAY; static void showhelp(void); static bool init_rcservo(CH_t *ch, unsigned long channels, int rbidx); static void close_rcservo(void); static const char* cmdtostr(unsigned cmd); static unsigned long htol(char* str); static void writefile_frame(FILE* fp, unsigned long* width, int frameno); static void mode_captureframes(PLAY *play); static void mode_replayframes(PLAY *play); static void captureinitfrm(DEF_t *def, unsigned long *frm); static bool FindHomeFRM(DEF_t *def, ACT_NODE *act, unsigned long *frm); static void init_play(DEF_t *def, ACT_NODE *act); static void mode_playdemo(char* dirname, unsigned long idletime); /*================ function for capture frame =====================*/ static void writefile_frame(FILE* fp, unsigned long* width, int frameno) //用於寫入檔案用 { int i; fprintf(fp, "[Frame %d]\n", frameno); //寫入到fp指到的檔案 for (i=0; i<32; i++) fprintf(fp, "channel%d = %lu\n", i, width[i]); fprintf(fp, "\n"); } static void mode_captureframes(PLAY *play) { unsigned long width[32], nowtime; unsigned c = 0; int i; FILE* fp; CH_t ch[32]; showmsg("Open %s to write...", play->filename); if (overwrite == false) //&& //如果option複寫模式開啟 若是沒開啟 if ((fp = fopen(play->filename, "r")) != NULL) //判斷能否讀取fp指到的檔案 可以的話 { fclose(fp); //關閉剛剛開啟的檔 showmsg(" file already exists. overwirte? (Y/N) "); c = keyboard_waitkey(); //決定是否要複寫已存在的檔案 if ((c != 'y') && (c != 'Y')) //如果回答不是Y 則結束程式 { showmsg("...abort!\n"); return; } } if ((fp = fopen(play->filename, "w")) == NULL) //判斷寫入檔案失敗的話 { showmsg("...fail!\n"); return; } showmsg("...success\n"); if(tool_InitCapture(ch, play->usedchannels, play->mode_idx) != true) //判斷tool_InitCapture()是否成立 主要是將ch的結構初始化 在demo.cpp return; //不成立就結束 if (init_rcservo(ch, play->usedchannels, play->rbidx) == false) return; else showmsg("\n"); //init rcservo for (i=0; i<32; i++) rcservo_SetServoType(i, RCSERVO_SV_FEEDBACK, RCSERVO_FB_FASTMODE + RCSERVO_FB_DENOISE); //設定Servo的型態 rcservo_EnterCaptureMode(); //設定為CaptureMode nowtime = timer_nowtime(); //將時間紀錄至nowtime showmsg("Start Frame number : %d\n", play->frameno); while (1) { // if ((realtime != true) || (showmessage == true)) // showmsg("Pose the KONDO robot, and press any key to capture [ESC to quit] ...\n"); if(showmessage == true){ //判斷是否要顯示訊息 if(realtime == true) showmsg("Pose the KONDO robot, or press ESC to quit ...\n"); else showmsg("Pose the KONDO robot, and press any key to capture [ESC to quit] ...\n"); } if (realtime == true) //如果有realtime的話 { do { c = keyboard_getkey(); } while (((timer_nowtime() - nowtime) < replaytime) && (c != KBESC)); //執行到按ESC或時間超過replaytime為止 nowtime = timer_nowtime(); } else //沒有realtime的話 c = keyboard_waitkey(); //等待按鍵 if (c == KBESC) break; //當按鍵為ESC時離開這while迴圈 rcservo_ReadPositions(play->usedchannels, RCSERVO_CMD_POWEROFF, width); //讀取馬達的值 放入width[32]內 for (i=0; i<32; i++) //跑所有的pin腳 1~32 { if (width[i] == 0xffffffffL) //如果讀取到0xffffffff 即為讀取失敗 { showmsg("ERROR: fail to read the position of channel %d (PIN S%d) !\n", i, i + 1); width[i] = 0L; //將值改為0 } else //如果讀取成功 { if ((realtime == false) || (showmessage == true)) //依設定決定是否輸出 showmsg("The position of channel %d (PIN S%d) is %lu\n", i, i + 1, width[i]); } }//end for i... writefile_frame(fp, width, play->frameno); //呼叫writefile_frame() 即為寫入檔案 if ((realtime != true) || (showmessage == true)) showmsg("[Frame %d] captured\n\n", play->frameno); play->frameno += 1; //當前frame編號累加1 } fclose(fp); //結束時關閉開啟的檔案 close_rcservo(); //關閉rcservo } /*================ function for replay frame =====================*/ static void mode_replayframes(PLAY *play) //為第二個模式 重播模式 { DEF_t def; ACT_NODE *act; int actno = 0; if(tool_InitReplay(&def, play->filename, replaytime, play->mode_idx, actno, play->usedchannels) != true){ //主要是初始化設定 在demo.cpp showmsg("...fail to replay file : %s\n", play->filename); return; } showmsg("Open %s to load...\n", play->filename); if(init_rcservo(def.channel, play->usedchannels, play->rbidx) != true) //init rcservo return; act = tool_FindACTNode(def.acttable, actno, def.actsize); //用actno尋找act的節點 在demo.cpp if(act == NULL){ //如果沒找到 即為actno有誤 showmsg("...fail to find act number: %d\n", actno); return; } if(Servo[play->mode_idx].feedback == true) //如果是有feedback功能的馬達 rcservo_EnterPlayMode(); //那就可以直接進入PlayMode else{ //如果無此功能 showmsg("Move to Home : [Frame %d]...", act->data.frmno); //就必須要設定起始frame rcservo_EnterPlayMode_HOME(act->frm); if ((realtime != true) || (showmessage == true)) //依設定決定是否輸出 showmsg("...finish\n"); act += 1; } for(; act->type != ACT_START; act += 1){ if ((realtime != true) || (showmessage == true)) //依設定決定是否輸出 showmsg("Playing [Frame %d]...", act->data.frmno); rcservo_MoveTo(act->frm, act->time); //移動馬達 if ((realtime != true) || (showmessage == true)) //依設定決定是否輸出 showmsg("...finish\n"); if(showmessage == true){ //依設定決定是否輸出 if(realtime == true) showmsg("press ESC to quit\n\n"); else showmsg("press any key to continue [ESC to quit]\n\n"); } // if ((realtime != true) || (showmessage == true)) // showmsg("press any key to continue [ESC to quit]\n\n"); if (realtime == true){ if (keyboard_getkey() == KBESC) break; //ESC離開程式 } else{ if (keyboard_waitkey() == KBESC) break; //ESC離開程式 } } showmsg("Finish the replay process.\n"); tool_FreeDEF(&def); //將新建的空間還回去 close_rcservo(); //關閉rcservo } /*================ function for play demo =====================*/ static void captureinitfrm(DEF_t *def, unsigned long *frm) //讀取起始位置用 { rcservo_EnterCaptureMode(); //到CaptureMode unsigned long usech = 0; int i; for(i = 0; i < 32; i++){ frm[i] = 0; //預設frm為0 if(def->channel[i].pin != -1) usech += (1 << def->channel[i].pin); //有用到的channel加進去 } rcservo_ReadPositions(usech, RCSERVO_CMD_POWEROFF, frm); //讀取馬達位置 } static bool FindHomeFRM(DEF_t *def, ACT_NODE *act, unsigned long *frm) //尋找HomeFrame用 { int i; if(def->initfrm != -1){ //如果有起始位置 for(i = 0; i < 32; i++) frm[i] = def->inithome[i]; //將PWM腳位設定為起始位置 } else{ //如果沒有起始位置 while((act->type != -1) && (act->type != ACT_PLAYFRAMENO)) //判斷是否為可用的動作 act += 1; //累加動作 if(act->type == -1){ //如果無可用之動作 for(i = 0; i < def->actidx; i++){ //尋找所有可用之動作 if(def->actpool[i].type == ACT_PLAYFRAMENO) //如果有可以用的就跳出 break; } if(i == def->actidx) //如果沒有找到替代的起始動作就回傳false return false; act = &def->actpool[i]; //有找到就使用找到的 } for(i = 0; i < 32; i++) //跑32根腳位 frm[i] = act->frm[i]; //將起始位置存到frm內 } return true; } static void init_play(DEF_t *def, ACT_NODE *act) { bool feedback = true; //預設feedback為True unsigned long frm[32], read[32]; int i; for(i = 0; i < 32; i++){ //執行32次 即32個PWM if(def->channel[i].pin == -1) //沒有用到的pin就不理他 continue; if(Servo[def->channel[i].mode_idx].feedback != true){ //如果不是有feedback功能的 feedback = false; //有一個不是就改為false break; //有一個不是就跳出 } } if((feedback == true) && (def->initfrm == -1)) //若有feedback功能 且 沒有起始位置 rcservo_EnterPlayMode(); //可以直接進入PlayMode else{ if(FindHomeFRM(def, act, frm) != true){ //如果是沒有feedback功能的 那就必須要尋找起始位置 showmsg("...WARNING: no frame in this demo!\n"); return; } if(def->initfrm_mode == INIT_FRM_FALSE){ //若initfrm_mode為false captureinitfrm(def, read); //捕捉目前所在位置 for(i = 0; i < 32; i++){ if(read[i] != 0) frm[i] = read[i]; //覆蓋過去 } } rcservo_EnterPlayMode_HOME(frm); //rcservo起始位置 } return; } static void mode_playdemo(char* dirname, unsigned long idletime) { #define NOPLAY (0) #define PLAYNEXT (1) #define PLAYING (2) int i; unsigned c; DEF_t def; CMD_NODE *cmd; ACT_NODE *act; unsigned long playframe[32]; int playing = NOPLAY; bool playpause; bool playmode = false; unsigned long idleTimeOut = timer_nowtime(); showmsg("Loading %s folder\n", dirname);//show filaname if(tool_InitDemo(&def, dirname) != true) //把值設定為預設值 在demo.cpp return; showmsg("-----------------------------------> completed\n"); if (init_rcservo(def.channel, def.usedChannels, def.rbidx) == false) return; //init rcservo #ifdef USE_SOUND showmsg("Initializing Audio..."); ISoundEngine* audioEngine = createIrrKlangDevice(ESOD_AUTO_DETECT, ESEO_MULTI_THREADED | ESEO_LOAD_PLUGINS); if (!audioEngine) showmsg("...fail to initialize audio!\n"); else { showmsg("...success\n\n"); //allow the audioEngine to read audio files in a zipped file CMyFileFactory* demofileFactory = new CMyFileFactory(); audioEngine->addFileFactory(demofileFactory); demofileFactory->drop(); } #endif showmsg("\nCommand List\n=============\n"); for(i = 0; i < def.cmdidx; i++) //判斷有多少cmd指令就跑幾次迴圈 showmsg("key: %5s (%s)\n", cmdtostr(def.cmdpool[i].command), def.cmdpool[i].name);//show command showmsg("\nPress one command to play the action ([ESC] to quit)...\n"); while ((c = keyboard_getkey()) != KBESC) //執行到按鍵得到ESC為止 { switch (playing) //用switch判斷目前所在的模式 { case NOPLAY: if (timer_nowtime() >= idleTimeOut){ //當目前時間大於先前紀錄之時間時成立 會在按END鍵時成立 rcservo_EnterCaptureMode(); //stop PWM output //rcservo進入capture mode 可以停止PWM繼續輸出 playmode = false; //將playmode改為false 沒在做事 } if((cmd = tool_FindCMDNode(def.cmdtable, c, def.cmdsize)) == NULL) //把輸入的字拿去尋找相對應的節點 回傳回來 在demo.cpp break; if(playmode == false){ //若是playmode為false 沒在做事 if(def.initact != -1){ showmsg("Playing init ACT: %d\n", def.initact); act = def.initactnode; //預設動作 } else act = cmd->act; //執行下一個動作 init_play(&def, act); playmode = true; //playmode為true 有執行動作了 playing = PLAYNEXT; //playing改為PLAYNEXT playpause = false; //將playmode改為false } else{ //若playmode不為false act = cmd->act; //執行下一個動作 playing = PLAYNEXT; //playing改為PLAYNEXT playpause = false; //將playpause改為false 改為沒在做事 } break; case PLAYNEXT: if ((act == NULL) || (act->type == ACT_START)){ //如果動作為無 或動作動作型態在起點 showmsg("Finish the action.\n"); showmsg("\nPress a command to play an action ([ESC] to quit)...\n"); playing = NOPLAY; //將playing改為NOPLAY idleTimeOut = timer_nowtime() + idletime; //將idleTimeOut改為目前時間加上delay的時間 #ifdef USE_SOUND if (audioEngine) audioEngine->removeAllSoundSources(); #endif break; } switch (act->type) { case ACT_PLAYFRAMENO: //如果ACTION為移動馬達 showmsg(" Move to [Frame %d]...", act->data.frmno); rcservo_SetAction(act->frm, act->time); //rcservo設定動作為act的frame間格為act的time playing = PLAYING; //playing改為PLAYING break; case ACT_PAUSE: //如果ACTION為停止動作 showmsg(" Pause %d ms...", act->time); for (i=0; i<32; i++) playframe[i] = 0L; //將playframe改為0 基本上是會在原位置不動 rcservo_SetAction(playframe, act->time); //rcservo設定動作為act的frame間格為act的time playing = PLAYING; //playing改為PLAYING break; case ACT_PLAYSND: showmsg(" Play Audio %s...", act->data.filename); #ifdef USE_SOUND if (!audioEngine) showmsg("no audio device!"); else audioEngine->play2D(curact->data.filename, false, false, true); #else showmsg("no audio support!"); #endif showmsg("\n"); break; }//end switch (curact->type) act += 1; break; case PLAYING: if (c == KBEND) //如果按下END鍵 { showmsg("Stop\n"); rcservo_StopAction(); //rcservo停止動作 act = NULL; //將目前動作改為NULL 即為直接變為無剩餘動作 break; } else if (c == KBSPACE){ //如果按下空白鍵 playpause = (playpause == false)? true : false; //判斷應該要暫停 還是繼續 if (playpause == false){ //如果應該要繼續 showmsg("Play."); rcservo_ReleaseAction(); //rcservo繼續動作 } else{ //其他的 代表應該要暫停 showmsg("Paused."); rcservo_PauseAction(); //rcservo暫時停止動作 } } else if(c == KBPGUP){ //如果按下PAGE UP act -= 1; //把動作多扣一個 即為退到目前所在動作的前面 if((act-1)->type != ACT_START) //如果再減一個 (即為回到上一個動作) 不是起頭的話 act -= 1; //就回到上一個的前面 這樣就達到回到上個動作的效果 rcservo_StopAction(); //rcservo停止動作 即目前動作結束 } else if(c == KBPGDN){ //如果按下PAGE DONE showmsg("Skip."); rcservo_StopAction(); //rcservo停止動作 即目前動作結束 } else if((cmd = tool_FindCMDNode(def.cmdtable, c, def.cmdsize)) != NULL){ //判斷其他輸入字元 若為有效指令則執行 showmsg("Playing command: %s\n", cmd->name); act = cmd->act; //將動作改至新指令的第一個個動作 rcservo_StopAction(); //rcservo停止動作 即目前動作結束 } if (rcservo_PlayAction() == RCSERVO_PLAYEND){ //若動作已到結尾 showmsg("\n"); playing = PLAYNEXT; //將playing改為PLAYNEXT } break; }//end switch (playing) }//end while ((c = keyboard_getkey()... if (playing == PLAYING) showmsg("\n"); tool_FreeDEF(&def); #ifdef USE_SOUND if (audioEngine) audioEngine->drop(); #endif close_rcservo(); } #ifdef WINCE //winCE用 int _tmain(int argc, _TCHAR* _argv[]) //winCE的main function _tmain { char argvbuf[50][100] = {'\0'}; char* argv[50]; if (argc > 50) argc = 50; //lazy code:p for (int _argc=0; _argc<argc; _argc++) //將winCE的argv轉換為1個byte winCE的argv會是兩個byte { argv[_argc] = &(argvbuf[_argc][0]); wcstombs(argv[_argc], _argv[_argc], 100); } #else //非winCE時用 int main(int argc, char* argv[]) { #endif //讓兩個main function共用一個內容 int mode; //宣告變數mode 用於儲存輸入的模式 PLAY play = { //options用 用來存指令內容的 2, // rbidx 0, // mode_idx 0, // frameno "000.frm", // filename 0x000000ffL //usedchannel }; /* #if defined(RB_MSVC_WIN32) || defined(RB_MSVC_WINCE) DWORD Error; //, priClass; //priClass = GetPriorityClass(GetCurrentProcess()); if (!SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS)) //REALTIME_PRIORITY_CLASS or HIGH_PRIORITY_CLASS { Error = GetLastError(); errmsg("Error: failed to enter HIGH_PRIORITY mode (%d)!\n", Error); goto End; } #endif */ //parse user's arguments int i, argc_all = argc; //將argc_all 直接放入argc的值 就可以得到輸入的個數 for (i=1, argc=1; i<argc_all; i++){ //將argc從1開始 最大到argc_all if (argv[i][0] != '-') //若輸入的內容無包含'-' 即不是option argc++; //就讓argc累加1 這樣就可以知道option以外的東西共有幾個 else break; //若進入option區域則直接跳出迴圈 } if (argc <= 1){ //如果最後得到的argc沒有超過1的話 代表輸入有誤 showhelp(); //呼叫showhelp()函式 return 0; //結束程式 } //for argv[1] if ((_stricmp(argv[1], "0") == 0) || (_stricmp(argv[1], "CAPTURE") == 0)){ //判斷當第一個輸入為"0"或"CAPTURE" mode = MODE_CAPTURES; //將mode改為MODE_CAPTURES 即為(1) if (argc > 2) play.filename = argv[2]; //將第二個輸入放入play結構的filename裡 (儲存檔案名稱) if (argc > 3) play.frameno = atoi(argv[3]); //將第三個輸入放入play結構的frameno裡 (起始影格編號) } else if ((_stricmp(argv[1], "1") == 0) || (_stricmp(argv[1], "REPLAY") == 0)){ //判斷當第二個輸入為"1"或"REPLAY" mode = MODE_REPLAYS; //將mode改為MODE_REPLAYS 即為(2) if (argc > 2) play.filename = argv[2]; //將第二個輸入放入play結構的filename裡 (儲存檔案名稱) } else if ((_stricmp(argv[1], "2") == 0) || (_stricmp(argv[1], "DEMO") == 0)){ //判斷當第二個輸入為"2"或"DEMO" mode = MODE_DEMO; //將mode改為MODE_DEMO 即為(100) if (argc > 2) play.filename = argv[2]; //將第二個輸入放入play結構的filename裡 (儲存檔案名稱) else{ //如果沒有兩個以上的輸入代表沒有給予主要的檔案 showmsg("Error : Missing script directory !\n"); return 0; //結束程式 } replaytime = 15000L; //DEMO MODE預設的replaytime } else{ showhelp(); //如果有其他的 表示模式輸入錯誤 呼叫showhelp() return 0; //結束程式 } for (i=argc; i<argc_all; i++){ //繼續將argc的值給i 做到argc_all為止 也就包括了所有的options if ((_stricmp(argv[i], "-OW") == 0) || (_stricmp(argv[i], "--overwrite") == 0)){ //判斷option "-OW" "--overwrite" overwrite = true; //成立就將靜態變數overwrite改為true 以便事後判斷 continue; //繼續下一輪迴圈 } else if ((_stricmp(argv[i], "-RT") == 0) || (_stricmp(argv[i], "--realtime") == 0)){ //判斷option "-RT" "--realtime" realtime = true; //成立就將靜態變數realtime改為true 以便事後判斷 continue; //繼續下一輪迴圈 } if ((_stricmp(argv[i], "-NM") == 0) || (_stricmp(argv[i], "--nomessage") == 0)){ //判斷option "-NM" "--nomessage" showmessage = false; //成立就將靜態變數showmessage改為false 以便事後判斷 continue; //繼續下一輪迴圈 } if (i == argc_all-1) continue; // ignore last parameters //忽略最後一個參數 抓到的可能為值 而非選項 if ((argv[i][0] != '-') || (argv[i+1][0] == '-')) continue; // ignore -XX -YY //當目前的數為值 而非選項時跳過 if ((_stricmp(argv[i], "-CH") == 0) || (_stricmp(argv[i], "--channels") == 0)){ //判斷option "-CH" "--channels" play.usedchannels = htol(argv[i+1]); //成立就將值 用htol改為long型態 存入play結構中的usedchannels } else if ((_stricmp(argv[i], "-t") == 0) || (_stricmp(argv[i], "--time") == 0)){ //判斷option "-t" "--time" replaytime = atol(argv[i+1]); //成立就將值 用atol改為long型態 存入靜態變數replaytime } else if ((_stricmp(argv[i], "-SV") == 0) || (_stricmp(argv[i], "--servo") == 0)){ //判斷option "-SV" "--servo" if(tool_GetMode(argv[i+1], &play.mode_idx) != SUCCESS){ //判斷-SV的輸入是否符合規格 showmsg("Error : unknown servo : %s\n", argv[i+1]); return 0; //結束程式 } } else if ((_stricmp(argv[i], "-RB") == 0) || (_stricmp(argv[i], "--RoBoard") == 0)){ //判斷option "-RB" "--RoBoard" if(tool_GetItemRBVer(argv[i+1], &play.rbidx) != SUCCESS){ //判斷-RB的輸入是否符合規格 showmsg("Error : unknown roboard : %s\n", argv[i+1]); return 0; //結束程式 } } }//end for (i=argc... //setup log file if (err_SetLogFile("roboard.log") == false) showmsg("WARNING: can't open roboard.log for logging error messages!\n"); keyboard_init(KEYBOARD_STD); //呼叫函式keyboard_init() 在userio.cpp 引數KEYBOARD_STD為1 在userio.h switch (mode) //判斷模式 { case MODE_CAPTURES: //模式為MODE_CAPTURES = 1 mode_captureframes(&play); //呼叫函式mode_captureframes break; case MODE_REPLAYS: //模式為MODE_REPLAYS = 2 mode_replayframes(&play); //呼叫函式mode_replayframes break; case MODE_DEMO: //模式為MODE_DEMO = 100 mode_playdemo(play.filename, replaytime); //呼叫函式mode_playdeme break; } err_CloseLogFile(); keyboard_close(); return 0; } /*================ general function =====================*/ static void showhelp(void) //此函式用於要讓使用者知道該如何正確輸入用 { keyboard_init(KEYBOARD_STD); showmsg("Parameters\n"); showmsg("===========\n"); showmsg("-CH xxxxxxxx or --channels xxxxxxxx:\n"); showmsg(" Specify the PWM channels to use\n"); showmsg(" \n"); showmsg("-t xxxx or --time xxxx:\n"); showmsg(" Specify the time for realtime frame capture,\n"); showmsg(" frame replay, and demo play\n"); showmsg(" \n"); showmsg("-SV [DEFAULT, DEFAULT_NOFB, ...] or --servo [DEFAULT, DEFAULT_NOFB, ...]:\n"); showmsg(" Specify servo motors\n"); showmsg(" \n"); showmsg("[press any key to continue...]\n"); keyboard_waitkey(); showmsg("\n"); showmsg("Parameters (cont.)\n"); showmsg("===========\n"); showmsg("-RB [RB_100, RB_110, ....] or --servo [RB_100, RB_110, ....]:\n"); showmsg(" Specify servo motors\n"); showmsg(" \n"); showmsg("-OW or --overwrite:\n"); showmsg(" Always overwrite the file of storing captured frames\n"); showmsg(" \n"); showmsg("-NM or --nomessage:\n"); showmsg(" Not display messages when capturing or replaying frames,\n"); showmsg(" being useful to speed up in Realtime modes\n"); showmsg("\n"); showmsg("[press any key to continue...]\n"); keyboard_waitkey(); showmsg("\n"); showmsg("Usage examples\n"); showmsg("===============\n"); showmsg("RoBoRC.exe CAPTURES(or 0) 0000.frm -CH 0000ffff:\n"); showmsg(" Capture multiple frames of servo positions on channels 0~15.\n"); showmsg(" The frames are saved to 0000.frm.\n"); showmsg(" \n"); showmsg("RoBoRC.exe REPLAYS(or 1) 0000.frm -CH 0000ffff -t 500:\n"); showmsg(" Replay the multiple frames of servo positions in 0000.frm.\n"); showmsg(" Each frame is replayed on channels 0~15 by 500ms.\n"); showmsg(" \n"); showmsg("RoBoRC.exe DEMO(or 2) demo_directory -t 10000:\n"); showmsg(" Load the Demo in demo_directory and\n"); showmsg(" set the action idle time to 10000ms (which means that\n"); showmsg(" the servo power will be turned off if the robot\n"); showmsg(" idles over 10s after finishing an action).\n"); showmsg("\n"); showmsg("[press any key to continue...]\n");keyboard_waitkey(); showmsg("\n"); keyboard_close(); } static bool init_rcservo(CH_t *ch, unsigned long channels, int rbidx) //此函式用於將rcservo init { int i; showmsg("Set roboard version (for %s)...\n", RBVer[rbidx].name); roboio_SetRBVer(RBVer[rbidx].value); //設定RB的版本 for(i = 0; i < 32; i++){ //用迴圈跑所有的pin腳 共32根 if(ch[i].pin != -1){ //判斷ch[i]結構不為-1的pin rcservo_SetServo(ch[i].pin, Servo[ch[i].mode_idx].value); //SetServo showmsg("Initializing RCSERVO lib channel %d (PIN S%d) : %s)...\n", i, ch[i].pin + 1, Servo[ch[i].mode_idx].name); } } if (rcservo_Initialize(channels) == true) //如果Init成功 { showmsg("...success\n"); rcservo_EnableMPOS(); rcservo_SetFPS(100); return true; } showmsg("...fail!\n"); //如果Init不成功 errmsg("ERROR: RCSERVO lib fails to initialize (%s)!\n", roboio_GetErrMsg()); return false; } static void close_rcservo(void) //rcservo_Close 多加兩行輸出 { showmsg("Closing RCSERVO lib..."); rcservo_Close(); showmsg("...done\n"); } static const char* cmdtostr(unsigned cmd) { //用於將輸入的指令轉為字串 static char cmdstr[2] = {'\0', '\0'}; int i; for (i=0; i<(int)NUM_SKEY; i++) //指令共有NUM_SKEY = (17)個 在const.h if (cmd == SKey[i].value) return SKey[i].name; //對照 是否有那個key 若有就回傳那個key的名稱 cmdstr[0] = (char)cmd; //若無 則直接回傳那個key轉為char 通常為英數字 return cmdstr; } static unsigned long htol(char* str) //用於轉換16進位為long型態 { unsigned long value = 0L; for (int i=0; i<(int)strlen(str); i++) //迴圈 從0~字串長度 然後依序計算數值 value = (str[i]>'9')? value*16+(unsigned long)(str[i]-'a'+10): value*16+(unsigned long)(str[i]-'0'); return value; }
雖然看程式碼很乏味
不過多看多理解
可以助於增加自己的程式功力喔!
不過多看多理解
可以助於增加自己的程式功力喔!
0 留言:
張貼留言