EIC
/
EIC_sample
This is sample.
Embed:
(wiki syntax)
Show/hide line numbers
main.cpp
00001 #include "mbed.h" 00002 #include "USBHostKeyboard.h" 00003 00004 #define LOG_DEBUG 00005 #ifdef LOG_DEBUG 00006 #define log_debug(format,...) std::printf(format,##__VA_ARGS__) 00007 #else 00008 #define log_debug(format,...) 00009 #endif 00010 00011 typedef enum { 00012 Init, 00013 Wait, 00014 Prenote, 00015 Delete, 00016 } num_state_t; 00017 00018 typedef enum { 00019 Number =0, 00020 Show =!Number 00021 } mode_key_t; 00022 const char *const mode_string[] = {"Number","Show"}; 00023 00024 /*ヒープ領域に作る線形リストのノード構造体。いちいちstructって書くの面倒なんでtypedefしとく*/ 00025 typedef struct node{ 00026 int number; //レコード(数字) 00027 struct node *next; //次のノードへのポインタ 00028 }node; 00029 00030 00031 00032 LocalFileSystem local("Local"); 00033 BusOut led(LED1,LED2,LED3,LED4); 00034 /*******************ポート設定(水野)***************************/ 00035 /*通信端子*/ 00036 Serial uart_subdisplay(p9,p10); // tx,rx 00037 //Serial uart_ps(p28,p27); 00038 /*7セグの十の位(端子名はwikipediaの通り)*/ 00039 DigitalOut a10(p14); 00040 DigitalOut b10(p15); 00041 DigitalOut c10(p16); 00042 DigitalOut d10(p17); 00043 DigitalOut e10(p18); 00044 DigitalOut f10(p19); 00045 DigitalOut g10(p20); 00046 /*7セグの一の位(端子名はwikipediaの通り)*/ 00047 DigitalOut a1(p29); 00048 DigitalOut b1(p26); 00049 DigitalOut c1(p25); 00050 DigitalOut d1(p24); 00051 DigitalOut e1(p23); 00052 DigitalOut f1(p22); 00053 DigitalOut g1(p21); 00054 /*本体操作スイッチ*/ 00055 DigitalIn delete_yes(p11); 00056 DigitalIn delete_no(p12); 00057 DigitalIn on_off(p13); 00058 DigitalOut file_alart_led(p8); 00059 00060 /*グローバル変数*/ 00061 static const char *const filename = "/Local/BINGO.csv"; //ファイル名 00062 int number_flag = 0; 00063 int numidx = 0; 00064 int numbers[2] = {0,0}; //バッファ。numbers[0]が十の位、numbers[1]が一の位。ってことは、ディスプレイ系関数は配列を受け取るように変更。 00065 00066 node *entr; //線形リストの先頭アドレス。mainの中に置くと面倒なのでグローバルで。 00067 00068 00069 00070 /*プロトタイプ宣言*/ 00071 void onKey(uint8_t); 00072 int mode_number(int); 00073 int mode_show(int); 00074 void switch_mode(mode_key_t *); 00075 void setNum_new(int);//'0'~'9' is guaranteed 00076 void deleteNum(); 00077 00078 void effect(int); 00079 int main_display(int*); 00080 void power_supply_control(int,int,int,int); 00081 void power_supply_shutdown_protect(void); 00082 void start_up_file_check(void); 00083 int number_converter(int*); 00084 node* nodealloc(void); 00085 void save_file(int); 00086 void start_up_read_file(node*); 00087 node* add_node(int,node*); 00088 int kisyutu_check(); 00089 void save_data(); 00090 00091 00092 void onKey(uint8_t key)/*キーが押されたら*/ 00093 { 00094 static mode_key_t state_mode = Number; 00095 switch (key) { 00096 case 's': 00097 switch_mode(&state_mode); 00098 printf("mode change:%s\r\n",mode_string[state_mode]); 00099 break; 00100 } 00101 if((Number == state_mode ? mode_number : mode_show)(key)) { 00102 switch_mode(&state_mode); 00103 printf("auto change:%s\r\n",mode_string[state_mode]); 00104 } 00105 } 00106 00107 inline void switch_mode(mode_key_t *mode) 00108 { 00109 *mode = Number == *mode ? Show : Number; 00110 if(*mode == Number) 00111 { 00112 uart_subdisplay.printf("101\n"); //サブディスプレイ「入力モード」点灯 00113 } 00114 if(*mode == Show) 00115 { 00116 uart_subdisplay.printf("102\n"); //サブディスプレイ「復習モード」点灯 00117 } 00118 } 00119 00120 00121 int mode_number(int key) 00122 { 00123 static num_state_t state = Init; 00124 switch (state) { 00125 case Prenote: //表示確認モードのとき 00126 if ('\r'==key || '\n'==key) //エンターが押されたら 00127 { 00128 save_data(); //線形リストとファイルに保存する関数をコール 00129 00130 if(main_display(numbers)) //メインディスプレイ表示 00131 { //switch-case中にバッファを消されると死ぬので、終了のサイン戻り値を待って、 00132 deleteNum(); //バッファをクリア 00133 } 00134 } 00135 state = Wait; //入力待ちモードにセット 00136 if (0) { 00137 case Init: 00138 deleteNum(); 00139 state = Wait; 00140 } 00141 case Wait: //入力待ちモードなら 00142 switch (key) { //数字が入力されたらアスキーコードを数字に変換して収納 00143 case '0': 00144 setNum_new(0); //「値はintで欲しい」って言ったような気が・・・7セグじゃputc使えないし。 00145 break; 00146 case '1': 00147 setNum_new(1); 00148 break; 00149 case '2': 00150 setNum_new(2); 00151 break; 00152 case '3': 00153 setNum_new(3); 00154 break; 00155 case '4': 00156 setNum_new(4); 00157 break; 00158 case '5': 00159 setNum_new(5); 00160 break; 00161 case '6': 00162 setNum_new(6); 00163 break; 00164 case '7': 00165 setNum_new(7); 00166 break; 00167 case '8': 00168 setNum_new(8); 00169 break; 00170 case '9': 00171 setNum_new(9); //setnumへ渡す(バッファへ保存とサブディスプレイへの出力) 00172 break; 00173 case '\n': //エンターが押されたら 00174 case '\r': 00175 if (number_flag) //数字フラグが1なら 00176 { 00177 if((kisyutu_check()) == 0){ //既出でなければ 00178 state = Prenote; //入力確認モードへ移行 00179 uart_subdisplay.printf("111\n"); // サブディスプレイ「よろしいですか?」点灯 00180 } else if ((kisyutu_check()) == 1) { //既出なら 00181 uart_subdisplay.printf("112\n"); //サブディスプレイ「既出です」点灯 00182 wait(1.0); //を1秒点灯 00183 deleteNum(); //バッファをクリア 00184 } 00185 } 00186 break; 00187 } 00188 break; 00189 default: 00190 break; 00191 } 00192 led = state; 00193 if ('\b' == key) {//b(バックスペース)なら 00194 deleteNum(); //バッファをクリアし 00195 state = Wait; //入力待ちモードへ 00196 } 00197 return 0; 00198 } 00199 00200 /*復習 メモ:福田君のモード選択アルゴリズム → 1を返すと自動的に入力モードになる*/ 00201 00202 int mode_show(int key) 00203 { 00204 static node *current = entr; //enterのたび呼び出されるので、satatic。自動変数にしてかなり悩んだ~。だけど、復習直後に復習するとバグル。 00205 int main_output[2]; //mainディスプレイは配列入力なので欲しい。 00206 int temp; 00207 00208 if(current -> next == NULL) 00209 { 00210 return 1; //電源ON直後に復習に入れないためのフェイルセーフ。 00211 } 00212 00213 if (key == '\r' || key == '\n') 00214 { 00215 current = current-> next; //先頭リストは空、最後のリストはデータあるんで、処理前に進めとく。 00216 temp = current -> number; //線形リストから初っ端の字取り出し 00217 uart_subdisplay.printf("%d\n",temp); //サブディスプレイに表示 00218 main_output[0] = temp / 10; //INTなんで小数点以下切り捨て 00219 main_output[1] = temp - main_output[0] * 10; //一の位取り出し 00220 main_display(main_output); //メインディスプレイに表示 00221 00222 00223 if(current -> next == NULL){ //次のリストがなければ 00224 current = entr; //復習直後に復習してもバグらない。 00225 return 1; //関数を抜ける 00226 } 00227 } 00228 return 0; 00229 } 00230 00231 void deleteNum() //バッファクリア関数 00232 { 00233 number_flag = 0; 00234 numbers[0]=0; //だからーーー文字コードじゃなくてーーーーー泣 00235 numbers[1]=0; 00236 uart_subdisplay.printf("110\n"); //サブディスプレイの「よろしいですか?」と「既出です。」消す 00237 wait(0.1); //通信まち 00238 uart_subdisplay.printf("0\n"); //サブディスプレイを0に 00239 } 00240 00241 00242 void keyboard_task(void const *) //もともとあったやつ。 00243 { 00244 USBHostKeyboard keyboard; 00245 while(1) { 00246 while(!keyboard.connect()) { 00247 Thread::wait(500); 00248 } 00249 keyboard.attach(onKey); 00250 printf("[connected]\r\n"); 00251 while(keyboard.connected()) { 00252 Thread::wait(500); 00253 } 00254 } 00255 } 00256 00257 00258 /********************************************関数(水野)*****************************************************/ 00259 00260 /*setNumを整数型バージョンへ、ついでに自分のわかりやすいアルゴリズムに書き換え*/ 00261 00262 void setNum_new(int data) //バッファへセット(int用作り直し版) 00263 { 00264 if(!number_flag) { //数字フラグ(入力したか判定)が立ってなければ立てる 00265 number_flag = 1; 00266 } 00267 numbers[0] = numbers[1]; //一の位の数字を十の位に移して 00268 numbers[1] = data; //一の位を更新 00269 uart_subdisplay.printf("%d\n",number_converter(numbers)); //2桁整数に直してサブディスプレイへ出力。 00270 } 00271 00272 /*エフェクト制御*/ 00273 void effect(int effect_type) 00274 { 00275 /*理実と相談*/ 00276 } 00277 00278 /*メインディスプレイ 7セグ(下側MOSFET)制御 numbersが桁で分れてるので配列のままポインタで受け取りに変更*/ 00279 int main_display(int *data) 00280 { 00281 switch(data[0])//十の位 00282 { 00283 case 1: 00284 a10 = 1; 00285 b10 = 0; 00286 c10 = 0; 00287 d10 = 1; 00288 e10 = 1; 00289 f10 = 1; 00290 g10 = 1; 00291 break; 00292 case 2: 00293 a10 = 0; 00294 b10 = 0; 00295 c10 = 1; 00296 d10 = 0; 00297 e10 = 0; 00298 f10 = 1; 00299 g10 = 0; 00300 break; 00301 case 3: 00302 a10 = 0; 00303 b10 = 0; 00304 c10 = 0; 00305 d10 = 0; 00306 e10 = 1; 00307 f10 = 1; 00308 g10 = 0; 00309 break; 00310 case 4: 00311 a10 = 1; 00312 b10 = 0; 00313 c10 = 0; 00314 d10 = 1; 00315 e10 = 1; 00316 f10 = 0; 00317 g10 = 0; 00318 break; 00319 case 5: 00320 a10 = 0; 00321 b10 = 1; 00322 c10 = 0; 00323 d10 = 0; 00324 e10 = 1; 00325 f10 = 0; 00326 g10 = 0; 00327 break; 00328 case 6: 00329 a10 = 0; 00330 b10 = 1; 00331 c10 = 0; 00332 d10 = 0; 00333 e10 = 0; 00334 f10 = 0; 00335 g10 = 0; 00336 break; 00337 case 7: 00338 a10 = 0; 00339 b10 = 0; 00340 c10 = 0; 00341 d10 = 1; 00342 e10 = 1; 00343 f10 = 0; 00344 g10 = 1; 00345 break; 00346 case 8: 00347 a10 = 0; 00348 b10 = 0; 00349 c10 = 0; 00350 d10 = 0; 00351 e10 = 0; 00352 f10 = 0; 00353 g10 = 0; 00354 break; 00355 case 9: 00356 a10 = 0; 00357 b10 = 0; 00358 c10 = 0; 00359 d10 = 0; 00360 e10 = 1; 00361 f10 = 0; 00362 g10 = 0; 00363 break; 00364 default: // =0 00365 a10 = 0; 00366 b10 = 0; 00367 c10 = 0; 00368 d10 = 0; 00369 e10 = 0; 00370 f10 = 0; 00371 g10 = 1; 00372 break; 00373 } 00374 00375 switch(data[1])//一の位 00376 { 00377 case 1: 00378 a1 = 1; 00379 b1 = 0; 00380 c1 = 0; 00381 d1 = 1; 00382 e1 = 1; 00383 f1 = 1; 00384 g1 = 1; 00385 break; 00386 case 2: 00387 a1 = 0; 00388 b1 = 0; 00389 c1 = 1; 00390 d1 = 0; 00391 e1 = 0; 00392 f1 = 1; 00393 g1 = 0; 00394 break; 00395 case 3: 00396 a1 = 0; 00397 b1 = 0; 00398 c1 = 0; 00399 d1 = 0; 00400 e1 = 1; 00401 f1 = 1; 00402 g1 = 0; 00403 break; 00404 case 4: 00405 a1 = 1; 00406 b1 = 0; 00407 c1 = 0; 00408 d1 = 1; 00409 e1 = 1; 00410 f1 = 0; 00411 g1 = 0; 00412 break; 00413 case 5: 00414 a1 = 0; 00415 b1 = 1; 00416 c1 = 0; 00417 d1 = 0; 00418 e1 = 1; 00419 f1 = 0; 00420 g1 = 0; 00421 break; 00422 case 6: 00423 a1 = 0; 00424 b1 = 1; 00425 c1 = 0; 00426 d1 = 0; 00427 e1 = 0; 00428 f1 = 0; 00429 g1 = 0; 00430 break; 00431 case 7: 00432 a1 = 0; 00433 b1 = 0; 00434 c1 = 0; 00435 d1 = 1; 00436 e1 = 1; 00437 f1 = 0; 00438 g1 = 1; 00439 break; 00440 case 8: 00441 a1 = 0; 00442 b1 = 0; 00443 c1 = 0; 00444 d1 = 0; 00445 e1 = 0; 00446 f1 = 0; 00447 g1 = 0; 00448 break; 00449 case 9: 00450 a1 = 0; 00451 b1 = 0; 00452 c1 = 0; 00453 d1 = 0; 00454 e1 = 1; 00455 f1 = 0; 00456 g1 = 0; 00457 break; 00458 default: // =0 00459 a1 = 0; 00460 b1 = 0; 00461 c1 = 0; 00462 d1 = 0; 00463 e1 = 0; 00464 f1 = 0; 00465 g1 = 1; 00466 break; 00467 } 00468 return 1; 00469 } 00470 00471 /*電源(各色電流)制御*/ 00472 void power_supply_control(int r,int g,int b,int control) //それぞれの明るさ(%)と、制御コード 00473 { 00474 00475 } 00476 00477 00478 /*停電時の処理(ピン変化割り込み)*/ 00479 void power_supply_shutdown_protecct(void) 00480 { 00481 00482 //電源が完成したら挙動を見てどんな処理が必要か考えて実装。 00483 } 00484 00485 00486 /*起動時のファイルチェック*/ 00487 void start_up_file_check(void) 00488 { 00489 FILE *fp; 00490 if((fp = fopen(filename,"r")) != NULL) //読み込みモードでファイルが開けたら、つまりファイルがあったら 00491 { 00492 file_alart_led = 1; //「ファイルを削除しますか?」ランプ点灯 00493 fclose(fp); 00494 while(1) 00495 { 00496 if(delete_yes)//削除(3秒長押し) 00497 { 00498 wait(3.0); 00499 if(delete_yes) //削除スイッチが、3秒経過後にまだ押されてたら 00500 { 00501 fp = fopen(filename,"w"); //上書きモードで開いて白紙にして上書き保存 00502 fclose(fp); 00503 break; 00504 } 00505 } 00506 if(delete_no)//残す(停電復帰後等) 00507 { 00508 start_up_read_file(entr); //ファイルを線形リストに読み込み 00509 wait(0.1); 00510 break; 00511 } 00512 } 00513 file_alart_led = 0; //「ファイルを削除しますか?」ランプ消灯 00514 } 00515 } 00516 00517 /*桁ごとの配列を2桁の整数に変換*/ 00518 int number_converter(int *data) 00519 { 00520 int output_data; 00521 output_data = 10 * data[0] + data[1]; 00522 return output_data; 00523 } 00524 00525 00526 /*nodealloc関数。nodeサイズのメモリを確保して、確保したnode型のポインタを返す*/ 00527 node* nodealloc(void) 00528 { 00529 return (struct node*)malloc(sizeof(node)); //malloocは必ずキャストして使うこと 00530 } 00531 00532 /*ローカルストレージにバックアップをとる*/ 00533 void save_file(int data) 00534 { 00535 FILE *fp; 00536 if((fp = fopen(filename,"a")) != NULL) //追記モードで開いて 00537 { 00538 fprintf(fp,"%d\r\n",data); //数字を保存して改行 00539 fclose(fp); //ファイルを閉じる 00540 } 00541 } 00542 00543 /*停電復帰時専用。外部ファイルから線形リストに読み込み。開始ノードを引数。*/ 00544 void start_up_read_file(node *start) 00545 { 00546 int data; 00547 node *current = start; 00548 FILE *fp; 00549 if((fp=fopen(filename,"r")) != NULL) //ファイルが開けたら 00550 { 00551 while(fscanf(fp,"%d",&data) != EOF) 00552 { 00553 current = add_node(data,current); 00554 } 00555 fclose(fp); 00556 } 00557 } 00558 00559 /*線形リストを追加する すべてがアドレスで動いていることに注意。メモリ内の倉庫に対し、事務所からロケーション番号と作業を指示しているだけ。*/ 00560 node* add_node(int data,struct node *current) 00561 { 00562 struct node *temp; 00563 00564 while(current->next != NULL) //停電復帰後はスタートノード=最後もノードになってないので、最後のノードを探す。 00565 { 00566 current = current->next; 00567 } 00568 00569 temp = nodealloc(); //まずノードを作る。メモリは確保されるのでローカル変数で良い。 00570 temp -> number = data; //作ったノードに数字を保存する。 00571 temp->next = NULL; //作ったやつはケツに足すので、次につなげるのがない最終ノードにする。 00572 current->next = temp; //受け取ったやつは作ったやつの一個のリストになるため、作ったやつにつながるように書き換える。 00573 return temp; //作ったやつ(新たに最後になったやつ)のアドレスを返す。 00574 } 00575 00576 /*新たにデータを保存する(線形リストと外部ファイル)*/ 00577 void save_data() 00578 { 00579 static node *current_node = entr; //ノードのアドレスは静的変数で。最初は当然先頭で初期化 00580 int data = number_converter(numbers); //バッファの中身を2桁整数に変換 00581 save_file(data); //ファイルに保存 00582 add_node(data,current_node); //線形リストに保存 00583 } 00584 00585 /*既出チェック*/ 00586 int kisyutu_check() 00587 { 00588 node *task; //ノード型のポインタ変数。 00589 task = entr; //入り口ノードでスタート 00590 int temp; //処理用変数(バッファを2桁に変換して一旦置くよ) 00591 int flag = 0; //既出フラグ。既出なら1。ちがえば0。 00592 temp = number_converter(numbers); //2桁に変換して仮置き 00593 00594 while(task -> next != NULL){ 00595 task = task -> next; //入り口ノードは空。while停止条件のノードにはデータが存在。ってことで一個オフセット。 00596 if(task -> number == temp) //一致したらフラグを立ててループを抜ける。 00597 { 00598 flag = 1; 00599 break; 00600 } 00601 } 00602 return flag; 00603 } 00604 00605 00606 /******************************************************************************/ 00607 00608 00609 int main() 00610 { 00611 /**********************起動時の処理******************************************/ 00612 00613 /*ディスプレイの準備*/ 00614 deleteNum(); //numbersを0にして 00615 main_display(numbers); //メインディスプレイを0に 00616 uart_subdisplay.printf("0\n"); // サブディスプレイ0に 00617 wait(0.1); //通信待ち 00618 uart_subdisplay.printf("124\n");//サブディスプレイのステータスランプ全消灯 00619 00620 /*先頭ノードを用意*/ 00621 entr = nodealloc(); //entr はグローバル変数。 00622 entr -> number = 0; //先頭ノードはデータを持たないが、考慮めんどくさいんで0にしとく。。 00623 entr -> next = NULL; //とりあえず一個なのでNULL。 00624 00625 /*残留データの削除または読込*/ 00626 start_up_file_check(); 00627 00628 /*電源起動*/ 00629 00630 00631 00632 uart_subdisplay.printf("101\n"); //サブディスプレイ「入力モード」点灯 00633 /******************************************************************************/ 00634 00635 00636 Thread keyboardTask(keyboard_task, NULL, osPriorityNormal, 256 * 4); 00637 while(1) { 00638 Thread::wait(500); 00639 } 00640 }
Generated on Fri Jul 22 2022 09:16:35 by 1.7.2