This is sample.

Dependencies:   USBHost mbed

このページは

イルミネーション制御用のコードページです。
使い方の説明があります。

概要

LocalFileSystem利用なのでLPC1768専用と思ってください。
"local/test.csv"ファイルが作成されます。
USBキーボードの利用が絶対です。 PCとのSerial通信も必要です。
エスケープシーケンスをちょっと利用してるので、WindowsはTeraTerm、Macはscreenコマンドをオススメします。

どんなプログラム?

プログラムの構造は 基本は2つのモードを's'キーによって切り替えて使います。(常に's'キーが有効です。)

モード内容有効なキー
入力モード数字の入力、表示、保存 (起動時はこれ)'s','0-9','\b','\r','\n' ( 'd' / 'y' )
表示モード履歴の表示のみ。キー入力で次々表示's','\r','\n'

通常の運用では入力モードでの動作になります。
キーボードのコードは

  • '\b':バックスペース(BS)
  • '\r','\n':エンターキー(LF:'\n'==0x0a)です。なんとなく'\r'足しました。

モードの説明

  • 入力モード
    • 数字(0-9)を入力するとセットされます。(2,1,3と入力すると「13」、3,0,2と入力すると「2」となります。)
    • バッファが空のときにはエンターキー'\r''\n'の入力は無視されます。
    • エンターキー('\r','\n')を入力すると
      • 1回目:確認用に表示します。(prenote)
      • 2回目:(確定され)表示・保存されます。(show,save)
      • 3回目:バッファがクリアされ待機状態になります。(Delete)
      • (4回目:バッファは空なので無視されます。)
    • 'd'を入力するとファイル削除の確認をしますので(Remove)
      • 'y'キーで削除
      • その他のキーで取り消し
    • BackSpace'\b'キーでバッファクリア(Delete)
  • 表示モード
    • エンターキー('\r','\n')を入力すると
      • 過去の保存済み数字(saved)を古い順番に表示します
      • すべて表示すると"EOF"(End Of File)と表示され入力モードに戻ります。

再起動後にファイルがある場合はそのファイルに追加編集されます。(消したい場合は入力モードで削除して)

警告

表示モードの途中で's'を入力すると、再び表示モードになったときに途中からの表示になります。
これでいい?
グローバル変数としてフラグ2つ(delete,remove)、数値2桁、数値の桁位置指示、があります。

Quote:

基本的にテストページなので好きなだけいじってください。
不明な点は福田まで。

考慮すべき点

  • 要相談
    • テンキーの場合のキー割当はどうする?
    • 既に保存した数値(already exiting!)も表示(prenote,show)まではするべき?(saveだけしない)
    • ハードウェアのソフトウェアインターフェースが不明なのでint[2]に(ASCII)グローバルで実装中。表示関数(show)は"void show(int);"がいい?
      • いやいや、10進数表示だからそのままでいい(by福田)
    • 表示モード中のモード切り替えに対して、ファイル位置を戻すべき?
    • 表示モード中に次々表示されるが、戻ることも可能にする?
    • Enterを間違えて2回押すと確定されちゃう。(4回連続入力に対しては無視)
  • ソフトウェアの気になる点
    • クラス化の必要性はある?(グローバルむき出しと構造が細かいのは精神衛生的に……)
    • 10進数2桁限定なので、3桁に対応させるべき?(対応済みコードあり)
    • (表示モード中)160行目はshow();に対応するためにもshowだけは引数ありshow(int *)or(int)にしたほうがいい。(prenoteにも渡すべきなら同様に)
    • 保存、読込フォーマットは"%02d\r\n"ですが何か?(1->"01\r\n"、23->"23\r\n"など)
    • デバッグ用にUSBシリアルに対応させる(切替仕様にす)べき?

実際の動作

ログの内容です。

[USB_INFO: /src/USBHost/USBHost/USBHost.cpp:158]New device connected: 10002c6c [hub: 0 - port: 1]
[USB_INFO: /src/USBHost/USBHostHID/USBHostKeyboard.cpp:120]New Keyboard device: VID:04fe PID:000d [dev: 10002c6c - intf: 0]
[connected]
      set :'12'
create file "/local/test.csv"
  prenote :'12'
     show :'12'
    saved :'12'
   Delete :'12'
      set :'45'
  prenote :'45'
     show :'45'
    saved :'45'
   Delete :'45'
      set :'67'
      set :'65'
      set :'45'
already exiting!
   Delete :'45'
      set :'45'
already exiting!
   Delete :'45'
mode change:Show
12
45
EOF
auto change:Number
Do you want to remove File? [y/n] "/local/test.csv"
Removed"/local/test.csv"

main.cpp

Committer:
lelect
Date:
2014-10-24
Revision:
0:318e4fa6590e
Child:
1:c50f6764f528

File content as of revision 0:318e4fa6590e:

#include "mbed.h"
#include "USBHostKeyboard.h"

#define LOG_DEBUG
#ifdef LOG_DEBUG
#define log_debug(format,...)   std::printf(format,##__VA_ARGS__)
#else
#define log_debug(format,...)
#endif

typedef enum {
    Init,
    Wait,
    Prenote,
    Delete,
} num_state_t;

typedef enum {
    EXISTING,
    NONE,

    DONE,
    CANTWRITE,
    UNKNOWN
} file_write_t;

typedef enum {
    Number =0,
    Show =!Number
} mode_key_t;
const char *const mode_string[] = {"Number","Show"};

LocalFileSystem local("local");
BusOut led(LED1,LED2,LED3,LED4);

#define NUMBER_FILE_DIRECTORY "/local/"
#define FILE_NAME_TEMPLATE "test"
#define FILE_NAME_EXTENTION "csv"
static const char *const filename = NUMBER_FILE_DIRECTORY FILE_NAME_TEMPLATE"."FILE_NAME_EXTENTION;
#define NUM_OF_NUME (2)
int remove_flag = 0;
int number_flag = 0;
int numidx = 0;
int numbers[NUM_OF_NUME];


void onKey(uint8_t);

int mode_number(int);
int mode_show(int);
void switch_mode(mode_key_t *);
void setNum(int);//'0'~'9' is guaranteed
file_write_t isExisting();
void deleteNum();
void prenoteNum();
FILE *openFile(const char *mode);
void removeFile();
void showNum();
void showList();
int saveNum();


void onKey(uint8_t key)
{
    static mode_key_t state_mode = Number;
    switch (key) {
        case 's':
            switch_mode(&state_mode);
            printf("mode change:%s\r\n",mode_string[state_mode]);
            break;
    }
    if((Number == state_mode ? mode_number : mode_show)(key)) {
        switch_mode(&state_mode);
        printf("auto change:%s\r\n",mode_string[state_mode]);
    }
}

inline void switch_mode(mode_key_t *mode)
{
    *mode = Number == *mode ? Show : Number;
}

int mode_number(int key)
{
    static num_state_t state = Init;
    switch (state) {
        case    Prenote:
            if ('\r'==key || '\n'==key) {
                showNum();
                saveNum();
                deleteNum();
            }
            state = Wait;
            if (0) {
            case Init:
                deleteNum();
                state = Wait;
            }
        case Wait:
            switch (key) {
                case '0':
                case '1':
                case '2':
                case '3':
                case '4':
                case '5':
                case '6':
                case '7':
                case '8':
                case '9':
                    setNum(key);
                    break;
                case '\n':
                case '\r'://this does not work after deleting.
                    if (number_flag) {
                        file_write_t file_state = isExisting();
                        if (NONE == file_state) {
                            prenoteNum();
                            state = Prenote;
                        } else if (EXISTING == file_state) {
                            printf("already exiting!\r\n");
                            deleteNum();
                        }
                    }
                    break;
            }
            break;
        default:
            break;
    }
    led = state;
    if (remove_flag) {
        remove_flag = 0;
        if ('y' == key)
            removeFile();
        else
            printf("Remove canceled...\r\n");
    }

    if ('d' == key) {
        printf("Do you want to remove File? [y/n] \"%s\"\r\n", filename);
        remove_flag = 1;
    } else if ('\b' == key) {
        deleteNum();
        state = Wait;
    }
    return 0;
}

int mode_show(int key)
{
//このままだとshow中にモード切り替えされるとseekは保持される。
    int c;
    static off_t seek=0;
    FILE *fp = openFile("r");
    if ('\r'==key || '\n'==key) {
        fseek(fp, seek, SEEK_SET);
        if (EOF != (fscanf(fp, "%d",&c))) {
            seek =ftell(fp);
            printf("%2d\r\n",c);
        } else {
            seek = 0;
            printf("EOF\r\n");
            fclose(fp);
            return 1;
        }
    }
    fclose(fp);
    return 0;
}

void debug_show(const char *str)
{
    if (numbers[numidx]) {
        printf("%9s :'",str);
        putchar(numbers[numidx]);
        putchar(numbers[1-numidx]);
        printf("'\r\n");
    }
}

void setNum(int ascii)
{
    if(!number_flag) {
        number_flag = 1;
    } else {
        printf("\e[1A\e[2K\e[1G");
    }
    numbers[numidx] = ascii;
    numidx = 1-numidx;
    debug_show("set");
}
void deleteNum()
{
    debug_show("Delete");
    numidx = 0;
    number_flag = 0;
    numbers[0]='0';
    numbers[1]='0';
}

void prenoteNum()
{
    debug_show("prenote");
}

void showNum()
{
    debug_show("show");
}

FILE *openFile(const char *mode)
{
    int file_existing = 0;
    FILE *fp;

    if (!file_existing) {
        if (NULL != (fp = fopen(filename, "r"))) {
            file_existing = 1;
            fclose(fp);
        } else {
            if (NULL != (fp =fopen(filename, "w"))) {
                file_existing = 1;
                printf("create file \"%s\"\r\n",filename);
                fclose(fp);
            } else {
                printf("unknow error \"%s\"\r\n",filename);
            }
        }
    }

    fp = fopen(filename, mode);
    return fp;
}

void removeFile()
{
    if(0 == remove(filename)) {
        printf("Removed\"%s\"\r\n",filename);
    } else {
        printf("could not remove file!\r\n");
    }
}

//存在の確認(retval:NONE or EXISTING)
file_write_t isExisting()
{
    FILE *fp = openFile("r");
    int c;
    char buff[2];
    int digit = 0;
    file_write_t ret = NONE;
    while (EOF != (c=getc(fp))) {
        if ('\r'==c || '\n'==c) {
            if (digit) {
                digit = 0;
                if (numbers[numidx] == buff[0] && numbers[1-numidx]==buff[1]) {
                    ret = EXISTING;
                    break;
                }
            }
        } else {
            buff[digit++] = c;
        }
    }
    fclose(fp);
    return ret;
}

//存在しなければ保存
int saveNum()
{
    file_write_t state = isExisting();
    switch (state) {
        case NONE: {
            FILE *fp = openFile("a");
            putc(numbers[numidx], fp);
            putc(numbers[1-numidx], fp);
            putc('\r', fp);
            putc('\n', fp);
            fclose(fp);
            debug_show("saved");
            return DONE;
        }
        case EXISTING:
            printf("number is existing\r\n");
            return CANTWRITE;
        default:
            break;
    }
    //  printf("WARN:not implimented %s", __func__);
    return UNKNOWN;
}


void keyboard_task(void const *)
{
    USBHostKeyboard keyboard;
    while(1) {
        while(!keyboard.connect()) {
            Thread::wait(500);
        }
        keyboard.attach(onKey);
        printf("[connected]\r\n");
        while(keyboard.connected()) {
            Thread::wait(500);
        }
    }
}
int main()
{
    Thread keyboardTask(keyboard_task, NULL, osPriorityNormal, 256 * 4);
    while(1) {
        Thread::wait(500);
    }
}