This is sample.

Dependencies:   USBHost mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

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 }