ぼくの技術日誌

日誌って銘打っていますが、更新頻度が…

FlashAirの共有メモリにmbedでアクセスする

はじめに

FlashAirは東芝が販売しているWi-Fiアクセスポイント機能付きSDHCカードです。
通常の利用用途はSDHCカード内の画像共有を無線経由で行うといった使い方ですが、公開されているWebAPIでコマンドを送ることで、SDHCカード内部の設定を読み書きしたり、内部情報や画像を読み出すことができます。

先日、MakerFaireTokyo 2015の東芝出展ブースにて、FlashAirの「共有メモリ」機能の存在を知りました。
共有メモリはFlashAir内のデータ領域(iSDIO Register MapのReserved for Vender領域のうち、01000h~011FFh)の512byteを自由に利用することができるというものです。

今回はこのFlashAirの共有メモリについての調査とmbedで利用してみたことを書きたいと思います。

  • 方針
    1. 事前調査
    2. サンプルプログラムの実行
    3. 共有メモリAPIの調査
    4. LED点滅プログラムの追加

1. 事前調査

FlashAirの公式ページでは、ArduinoでFlashAirを使用する方法が公開されています。
FlashAir Developers - ドキュメント - Arduinoチュートリアル - iSDIO拡張コマンドの作成

特に理由はないのですが今回はmbedを使いたいと考えており、ネットで調べると、
既にmbed向けにライブラリを書いて公開されている方がいらっしゃいました。
mbed+FlashAirで直ツイート! | mbed

今回はこのライブラリを利用することにしました。作者のban4jp氏に感謝します。

2. サンプルプログラムの実行

ban4jp氏のサンプルプログラムのうち、必要になりそうなところだけを抜き出し、実行してみました。
すると、mbed LPC1768オンボードのLEDがプログラムと関係なしに点滅する異常状態になり、理由がわからず悩みましたが
サンプルプログラムからfopenを入れたところ動作しました。
どうやら、FlashAirへSDカードとしてアクセスを行う必要がある模様。

なお、遭遇したmbedの異常状態は下記。
Debugging - Handbook | mbed


サンプルプログラム(FlashAirとクライアント端末の接続を待ち、接続後にFlashAirの情報を表示して終了)

#include "mbed.h"
#include "SDFileSystem.h"
#include "iSDIO.h"

SD_iSDIO sd(p5, p6, p7, p8, "sd"); 
Serial pc(USBTX, USBRX);
DigitalOut led(LED1);

uint8_t buffer[512];

void printByte(uint8_t value) {
  pc.printf("%x", value >> 4);
  pc.printf("%x", value & 0xF);
}

void printBytes(uint8_t* p, uint32_t len) {
  for (int i = 0; i < len; ++i) {
    printByte(p[i]);
  }
}

void printIPAddress(uint8_t* p)
{
    pc.printf("%d", p[0]);
    pc.printf(".");
    pc.printf("%d", p[1]);
    pc.printf(".");
    pc.printf("%d", p[2]);
    pc.printf(".");
    pc.printf("%d", p[3]);
}

uint8_t iSDIO_status()
{
    pc.printf("\nRead iSDIO Status Register");
    // Read iSDIO Status Register (E7 1.10 2.2.2.1)
    memset(buffer, 0, 0x200);
    if (!sd.readExtMemory(1, 1, 0x400, 0x200, buffer)) {
        return false;
    }
#if 0
    for (int i = 0; i < 0x200; i++) {
        pc.printf("%2x ", buffer[i]);
        if ((i & 0xf) == 0xf) pc.printf("\n");
    }
#endif
    // Show values in the common status area.
    pc.printf("\n == iSDIO Status Registers == ");
    pc.printf("\n [0400h] Command Write Status: ");
    if (buffer[0x000] & 0x01) pc.printf("CWU ");
    if (buffer[0x000] & 0x02) pc.printf("CWA ");
    pc.printf("\n [0420h] iSDIO Status: ");
    if (buffer[0x020] & 0x01) pc.printf("CRU ");
    if (buffer[0x020] & 0x02) pc.printf("ESU ");
    if (buffer[0x020] & 0x04) pc.printf("MCU ");
    if (buffer[0x020] & 0x08) pc.printf("ASU ");
    pc.printf("\n [0422h] iSDIO Int Enable: ");
    if (buffer[0x022] & 0x01) pc.printf("CRU_ENA ");
    if (buffer[0x022] & 0x02) pc.printf("ESU_ENA ");
    if (buffer[0x022] & 0x04) pc.printf("MCU_ENA ");
    if (buffer[0x022] & 0x08) pc.printf("ASU_ENA ");
    pc.printf("\n [0424h] Error Status: ");
    if (buffer[0x024] & 0x01) pc.printf("CRE ");
    if (buffer[0x024] & 0x02) pc.printf("CWE ");
    if (buffer[0x024] & 0x04) pc.printf("RRE ");
    if (buffer[0x024] & 0x08) pc.printf("APE ");
    pc.printf("\n [0426h] Memory Status: ");
    if (buffer[0x026] & 0x01) pc.printf("MEX ");
    if (buffer[0x026] & 0x02) pc.printf("FAT ");
    for (int i = 0; i < 8; ++i) {
        uint8_t addr = 0x40 + i * 0x14;
        pc.printf("\n [04");
        printByte(addr);
        pc.printf("h] Command Response Status #");
        pc.printf("%d", i + 1);
        pc.printf(": ");
        if (buffer[addr] & 0x01) {
            pc.printf("id = ");
            pc.printf("%d", get_u16(buffer + addr + 2));
            pc.printf(", sequence id = ");
            pc.printf("%d", get_u32(buffer + addr + 4));
            pc.printf(", status = ");
            switch (buffer[addr + 8]) {
                case 0x00:
                    pc.printf("Initial");
                    break;
                case 0x01:
                    pc.printf("Command Processing");
                    break;
                case 0x02:
                    pc.printf("Command Rejected");
                    break;
                case 0x03:
                    pc.printf("Process Succeeded");
                    break;
                case 0x04:
                    pc.printf("Process Terminated");
                    break;
                default:
                    pc.printf("Process Failed ");
                    pc.printf("%h", buffer[addr + 8]);
                    break;
            }
        } else {
            pc.printf("Not registered");
        }
    }
    // Show values in the application status area.
    pc.printf("\n == Wireless LAN Status Registers ==");
    pc.printf("\n [0500h] DLNA Status: ");
    if (buffer[0x100] & 0x01) pc.printf("ULR ");
    if (buffer[0x100] & 0x02) pc.printf("DLU ");
    if (buffer[0x100] & 0x04) pc.printf("CBR ");
    if (buffer[0x100] & 0x08) pc.printf("CDR ");
    pc.printf("\n [0501h] P2P Status: ");
    if (buffer[0x101] & 0x01) pc.printf("ILU ");
    if (buffer[0x101] & 0x02) pc.printf("FLU ");
    pc.printf("\n [0502h] PTP Status: ");
    if (buffer[0x102] & 0x01) pc.printf("RPO ");
    if (buffer[0x102] & 0x02) pc.printf("RPD ");
    if (buffer[0x102] & 0x04) pc.printf("RPC ");
    if (buffer[0x102] & 0x08) pc.printf("CPI ");
    if (buffer[0x102] & 0x10) pc.printf("DPI ");
    if (buffer[0x102] & 0x20) pc.printf("CIL ");
    pc.printf("\n [0504h] Application: ");
    pc.printf((char *)buffer[0x104]);
    pc.printf("\n [0506h] WLAN: ");
    if ((buffer[0x106] & 0x01) == 0x00) pc.printf("No Scan, ");
    if ((buffer[0x106] & 0x01) == 0x01) pc.printf("Scanning, ");
    if ((buffer[0x106] & 0x06) == 0x00) pc.printf("No WPS, ");
    if ((buffer[0x106] & 0x06) == 0x02) pc.printf("WPS with PIN, ");
    if ((buffer[0x106] & 0x06) == 0x04) pc.printf("WPS with PBC, ");
    if ((buffer[0x106] & 0x08) == 0x00) pc.printf("Group Client, ");
    if ((buffer[0x106] & 0x08) == 0x08) pc.printf("Group Owner ");
    if ((buffer[0x106] & 0x10) == 0x00) pc.printf("STA, ");
    if ((buffer[0x106] & 0x10) == 0x10) pc.printf("AP, ");
    if ((buffer[0x106] & 0x60) == 0x00) pc.printf("Initial, ");
    if ((buffer[0x106] & 0x60) == 0x20) pc.printf("Infrastructure, ");
    if ((buffer[0x106] & 0x60) == 0x40) pc.printf("Wi-Fi Direct, ");
    if ((buffer[0x106] & 0x80) == 0x00) pc.printf("No Connection, ");
    if ((buffer[0x106] & 0x80) == 0x80) pc.printf("Connected, ");
    pc.printf("\n [0508h] SSID: ");
    for (int i = 0; i < 32 && buffer[0x108 + i] != 0; ++i) {
        pc.printf("%c", (char)buffer[0x108 + i]);
    }
    pc.printf("\n [0528h] Encryption Mode: ");
    switch (buffer[0x128]) {
        case 0 :
            pc.printf("Open System and no encryption");
            break;
        case 1 :
            pc.printf("Open System and WEP");
            break;
        case 2 :
            pc.printf("Shared Key and WEP");
            break;
        case 3 :
            pc.printf("WPA-PSK and TKIP");
            break;
        case 4 :
            pc.printf("WPA-PSK and AES");
            break;
        case 5 :
            pc.printf("WPA2-PSK and TKIP");
            break;
        case 6 :
            pc.printf("WPA2-PSK and AES");
            break;
        default:
            pc.printf("Unknown");
    }
    pc.printf("\n [0529h] Signal Strength: ");
    pc.printf("%d", buffer[0x129]);
    pc.printf("\n [052Ah] Channel: ");
    if (buffer[0x12A] == 0) pc.printf("No connection");
    else pc.printf("%d", buffer[0x12A]);
    pc.printf("\n [0530h] MAC Address: ");
    printBytes(buffer + 0x130, 6);
    pc.printf("\n [0540h] ID: ");
    for (int i = 0; i < 16 && buffer[0x140 + i] != 0; ++i) {
        pc.printf("%c", (char)buffer[0x140 + i]);
    }
    pc.printf("\n [0550h] IP Address: ");
    printIPAddress(buffer + 0x150);
    pc.printf("\n [0554h] Subnet Mask: ");
    printIPAddress(buffer + 0x154);
    pc.printf("\n [0558h] Default Gateway: ");
    printIPAddress(buffer + 0x158);
    pc.printf("\n [055Ch] Preferred DNS Server: ");
    printIPAddress(buffer + 0x15C);
    pc.printf("\n [0560h] Alternate DNS Server: ");
    printIPAddress(buffer + 0x160);
    pc.printf("\n [0564h] Proxy Server: ");
    if ((buffer[0x164] & 0x01) == 0x00) pc.printf("Disabled");
    if ((buffer[0x164] & 0x01) == 0x01) pc.printf("Enabled");
    pc.printf("\n [0570h] Date: ");
    pc.printf("%d", buffer[0x171] + 1980);
    pc.printf("-");
    pc.printf("%d", buffer[0x170] >> 4);
    pc.printf("-");
    pc.printf("%d", buffer[0x170] & 0xF);
    pc.printf("\n [0572h] Time: ");
    pc.printf("%d", buffer[0x173] >> 3);
    pc.printf(":");
    pc.printf("%d", buffer[0x172] << 3 | buffer[0x170] >> 3);
    pc.printf(":");
    pc.printf("%d", (buffer[0x172] & 0x1F) * 2);
    pc.printf("\n [0574h] HTTP Status: ");
    pc.printf("%d", buffer[0x174] & 0xEF);
    if ((buffer[0x174] & 0x80) == 0x00) pc.printf(" (No Processing)");
    if ((buffer[0x174] & 0x80) == 0x80) pc.printf(" (Processing)");
    pc.printf("\n [0575h] Power Save Management: ");
    if ((buffer[0x175] & 0x01) == 0x00) pc.printf("Power Save Mode Off");
    if ((buffer[0x175] & 0x01) == 0x01) pc.printf("Power Save Mode On");
    pc.printf("\n [0576h] File System Management: ");
    if ((buffer[0x176] & 0x01) == 0x00) pc.printf("FS Information may be modified");
    if ((buffer[0x176] & 0x01) == 0x01) pc.printf("FS Information shall not be modified");
    pc.printf("\n");
 
#if 0
    memset(buffer, 0, 0x200);
    if (!sd2->readExtMemory(1, 1, 0x600, 0x100, buffer)) {
        return false;
    }
 
    for (int i = 0; i < 0x100; i++) {
        pc.printf("%2x ", buffer[i]);
        if ((i & 0xf) == 0xf) pc.printf("\n");
    }
#endif
 
    return true;
}

int main() {
    
    pc.printf("Initialize FlashAir.\n");
    FILE *fp = fopen("/sd/mbed.txt", "w");
    if(fp == NULL) {
        error("Could not open file for write\n");
    }
    fclose(fp);
    
    pc.printf("Start.\n");    
    // Connection wait
    while(1) {
        memset(buffer, 0, 0x14);
        if (!sd.readExtMemory(1, 1, 0x506, 0x14, buffer)) {
            pc.printf("return\n");
            return -1;
        }
        uint8_t resp = get_u8(buffer);
        if ((resp & 0x80) != 0) {
            break;
        }
        pc.printf(".\n");
        wait_ms(1000);
    }
 
    // Dump status
    if (iSDIO_status() == false) {
        pc.printf("Failed to read status.\n");
        return -1;
    }
    
    pc.printf("End.\n");
}

3. 共有メモリAPIの調査

クライアント端末でFlashAirに接続し、共有メモリのWrite/Readコマンドを実行してみます。
コマンドの実行に成功するとブラウザに「success」と表示され、失敗するとcommand.cgiのダウンロードを行う画面が表示されます。

API仕様
https://flashair-developers.com/ja/documents/api/commandcgi/

Writeコマンドの例
http://flashair/command.cgi?op=131&ADDR=0&LEN=8&DATA=0123ABCD

Readコマンドの例
http://flashair/command.cgi?op=130&ADDR=0&LEN=8

上記のパラメータのうち、LENというデータ長とDATAという実データ部の関係性がよくわからなかったので、いくつかコマンドを実行してみました。
うまくまとめられていません…参考にする場合は要再検証…

(1)
Write len 0 data 1 =>Read len 1 == [0](0を書き込み
Write len 1 data 1 =>Read len 1 == [1](1を書き込み
Write len 2 data 1 =>Read len 1 == [1](data不足分は書き込まれない
Write len 1 data 12 =>Read len 1 == [1](len超過分は書き込まれない

Write len 3 data 124 =>Read len 1 == [1]
上記Readに続けて =>Read len 2 == [12]

(2)
Write len 2 data 12 =>Read len 2 == [12]
続いて
Write len 1 data 34 =>Read len 2 == [32](2がそのまま

(3)
Write len 0 data 12 => Read len 2 == [12]
Write len 0 data 123456 => Read len 6 == [123456]
つまり
Write len 0 data XX => 常に直前の書き込みデータを反映している

4. LED点滅プログラムの追加

2.のプログラム土台に共有メモリのユーザー領域をポールして得られた値によってLEDを点滅するプログラムを追加します。
フォーラムの情報にて、送信データはASCIIと書かれていたので、mbedプログラム内で文字を数値に変換しています。

LED点滅プログラム

#include "mbed.h"
#include "SDFileSystem.h"
#include "iSDIO.h"

SD_iSDIO sd(p5, p6, p7, p8, "sd"); 
Serial pc(USBTX, USBRX);
DigitalOut led(LED1);

uint8_t buffer[512];

void printByte(uint8_t value) {
  pc.printf("%x", value >> 4);
  pc.printf("%x", value & 0xF);
}

void printBytes(uint8_t* p, uint32_t len) {
  for (int i = 0; i < len; ++i) {
    printByte(p[i]);
  }
}

void printIPAddress(uint8_t* p)
{
    pc.printf("%d", p[0]);
    pc.printf(".");
    pc.printf("%d", p[1]);
    pc.printf(".");
    pc.printf("%d", p[2]);
    pc.printf(".");
    pc.printf("%d", p[3]);
}

uint8_t iSDIO_status()
{
    pc.printf("\nRead iSDIO Status Register");
    // Read iSDIO Status Register (E7 1.10 2.2.2.1)
    memset(buffer, 0, 0x200);
    if (!sd.readExtMemory(1, 1, 0x400, 0x200, buffer)) {
        return false;
    }
#if 0
    for (int i = 0; i < 0x200; i++) {
        pc.printf("%2x ", buffer[i]);
        if ((i & 0xf) == 0xf) pc.printf("\n");
    }
#endif
    // Show values in the common status area.
    pc.printf("\n == iSDIO Status Registers == ");
    pc.printf("\n [0400h] Command Write Status: ");
    if (buffer[0x000] & 0x01) pc.printf("CWU ");
    if (buffer[0x000] & 0x02) pc.printf("CWA ");
    pc.printf("\n [0420h] iSDIO Status: ");
    if (buffer[0x020] & 0x01) pc.printf("CRU ");
    if (buffer[0x020] & 0x02) pc.printf("ESU ");
    if (buffer[0x020] & 0x04) pc.printf("MCU ");
    if (buffer[0x020] & 0x08) pc.printf("ASU ");
    pc.printf("\n [0422h] iSDIO Int Enable: ");
    if (buffer[0x022] & 0x01) pc.printf("CRU_ENA ");
    if (buffer[0x022] & 0x02) pc.printf("ESU_ENA ");
    if (buffer[0x022] & 0x04) pc.printf("MCU_ENA ");
    if (buffer[0x022] & 0x08) pc.printf("ASU_ENA ");
    pc.printf("\n [0424h] Error Status: ");
    if (buffer[0x024] & 0x01) pc.printf("CRE ");
    if (buffer[0x024] & 0x02) pc.printf("CWE ");
    if (buffer[0x024] & 0x04) pc.printf("RRE ");
    if (buffer[0x024] & 0x08) pc.printf("APE ");
    pc.printf("\n [0426h] Memory Status: ");
    if (buffer[0x026] & 0x01) pc.printf("MEX ");
    if (buffer[0x026] & 0x02) pc.printf("FAT ");
    for (int i = 0; i < 8; ++i) {
        uint8_t addr = 0x40 + i * 0x14;
        pc.printf("\n [04");
        printByte(addr);
        pc.printf("h] Command Response Status #");
        pc.printf("%d", i + 1);
        pc.printf(": ");
        if (buffer[addr] & 0x01) {
            pc.printf("id = ");
            pc.printf("%d", get_u16(buffer + addr + 2));
            pc.printf(", sequence id = ");
            pc.printf("%d", get_u32(buffer + addr + 4));
            pc.printf(", status = ");
            switch (buffer[addr + 8]) {
                case 0x00:
                    pc.printf("Initial");
                    break;
                case 0x01:
                    pc.printf("Command Processing");
                    break;
                case 0x02:
                    pc.printf("Command Rejected");
                    break;
                case 0x03:
                    pc.printf("Process Succeeded");
                    break;
                case 0x04:
                    pc.printf("Process Terminated");
                    break;
                default:
                    pc.printf("Process Failed ");
                    pc.printf("%h", buffer[addr + 8]);
                    break;
            }
        } else {
            pc.printf("Not registered");
        }
    }
    // Show values in the application status area.
    pc.printf("\n == Wireless LAN Status Registers ==");
    pc.printf("\n [0500h] DLNA Status: ");
    if (buffer[0x100] & 0x01) pc.printf("ULR ");
    if (buffer[0x100] & 0x02) pc.printf("DLU ");
    if (buffer[0x100] & 0x04) pc.printf("CBR ");
    if (buffer[0x100] & 0x08) pc.printf("CDR ");
    pc.printf("\n [0501h] P2P Status: ");
    if (buffer[0x101] & 0x01) pc.printf("ILU ");
    if (buffer[0x101] & 0x02) pc.printf("FLU ");
    pc.printf("\n [0502h] PTP Status: ");
    if (buffer[0x102] & 0x01) pc.printf("RPO ");
    if (buffer[0x102] & 0x02) pc.printf("RPD ");
    if (buffer[0x102] & 0x04) pc.printf("RPC ");
    if (buffer[0x102] & 0x08) pc.printf("CPI ");
    if (buffer[0x102] & 0x10) pc.printf("DPI ");
    if (buffer[0x102] & 0x20) pc.printf("CIL ");
    pc.printf("\n [0504h] Application: ");
    pc.printf((char *)buffer[0x104]);
    pc.printf("\n [0506h] WLAN: ");
    if ((buffer[0x106] & 0x01) == 0x00) pc.printf("No Scan, ");
    if ((buffer[0x106] & 0x01) == 0x01) pc.printf("Scanning, ");
    if ((buffer[0x106] & 0x06) == 0x00) pc.printf("No WPS, ");
    if ((buffer[0x106] & 0x06) == 0x02) pc.printf("WPS with PIN, ");
    if ((buffer[0x106] & 0x06) == 0x04) pc.printf("WPS with PBC, ");
    if ((buffer[0x106] & 0x08) == 0x00) pc.printf("Group Client, ");
    if ((buffer[0x106] & 0x08) == 0x08) pc.printf("Group Owner ");
    if ((buffer[0x106] & 0x10) == 0x00) pc.printf("STA, ");
    if ((buffer[0x106] & 0x10) == 0x10) pc.printf("AP, ");
    if ((buffer[0x106] & 0x60) == 0x00) pc.printf("Initial, ");
    if ((buffer[0x106] & 0x60) == 0x20) pc.printf("Infrastructure, ");
    if ((buffer[0x106] & 0x60) == 0x40) pc.printf("Wi-Fi Direct, ");
    if ((buffer[0x106] & 0x80) == 0x00) pc.printf("No Connection, ");
    if ((buffer[0x106] & 0x80) == 0x80) pc.printf("Connected, ");
    pc.printf("\n [0508h] SSID: ");
    for (int i = 0; i < 32 && buffer[0x108 + i] != 0; ++i) {
        pc.printf("%c", (char)buffer[0x108 + i]);
    }
    pc.printf("\n [0528h] Encryption Mode: ");
    switch (buffer[0x128]) {
        case 0 :
            pc.printf("Open System and no encryption");
            break;
        case 1 :
            pc.printf("Open System and WEP");
            break;
        case 2 :
            pc.printf("Shared Key and WEP");
            break;
        case 3 :
            pc.printf("WPA-PSK and TKIP");
            break;
        case 4 :
            pc.printf("WPA-PSK and AES");
            break;
        case 5 :
            pc.printf("WPA2-PSK and TKIP");
            break;
        case 6 :
            pc.printf("WPA2-PSK and AES");
            break;
        default:
            pc.printf("Unknown");
    }
    pc.printf("\n [0529h] Signal Strength: ");
    pc.printf("%d", buffer[0x129]);
    pc.printf("\n [052Ah] Channel: ");
    if (buffer[0x12A] == 0) pc.printf("No connection");
    else pc.printf("%d", buffer[0x12A]);
    pc.printf("\n [0530h] MAC Address: ");
    printBytes(buffer + 0x130, 6);
    pc.printf("\n [0540h] ID: ");
    for (int i = 0; i < 16 && buffer[0x140 + i] != 0; ++i) {
        pc.printf("%c", (char)buffer[0x140 + i]);
    }
    pc.printf("\n [0550h] IP Address: ");
    printIPAddress(buffer + 0x150);
    pc.printf("\n [0554h] Subnet Mask: ");
    printIPAddress(buffer + 0x154);
    pc.printf("\n [0558h] Default Gateway: ");
    printIPAddress(buffer + 0x158);
    pc.printf("\n [055Ch] Preferred DNS Server: ");
    printIPAddress(buffer + 0x15C);
    pc.printf("\n [0560h] Alternate DNS Server: ");
    printIPAddress(buffer + 0x160);
    pc.printf("\n [0564h] Proxy Server: ");
    if ((buffer[0x164] & 0x01) == 0x00) pc.printf("Disabled");
    if ((buffer[0x164] & 0x01) == 0x01) pc.printf("Enabled");
    pc.printf("\n [0570h] Date: ");
    pc.printf("%d", buffer[0x171] + 1980);
    pc.printf("-");
    pc.printf("%d", buffer[0x170] >> 4);
    pc.printf("-");
    pc.printf("%d", buffer[0x170] & 0xF);
    pc.printf("\n [0572h] Time: ");
    pc.printf("%d", buffer[0x173] >> 3);
    pc.printf(":");
    pc.printf("%d", buffer[0x172] << 3 | buffer[0x170] >> 3);
    pc.printf(":");
    pc.printf("%d", (buffer[0x172] & 0x1F) * 2);
    pc.printf("\n [0574h] HTTP Status: ");
    pc.printf("%d", buffer[0x174] & 0xEF);
    if ((buffer[0x174] & 0x80) == 0x00) pc.printf(" (No Processing)");
    if ((buffer[0x174] & 0x80) == 0x80) pc.printf(" (Processing)");
    pc.printf("\n [0575h] Power Save Management: ");
    if ((buffer[0x175] & 0x01) == 0x00) pc.printf("Power Save Mode Off");
    if ((buffer[0x175] & 0x01) == 0x01) pc.printf("Power Save Mode On");
    pc.printf("\n [0576h] File System Management: ");
    if ((buffer[0x176] & 0x01) == 0x00) pc.printf("FS Information may be modified");
    if ((buffer[0x176] & 0x01) == 0x01) pc.printf("FS Information shall not be modified");
    pc.printf("\n");
 
#if 0
    memset(buffer, 0, 0x200);
    if (!sd2->readExtMemory(1, 1, 0x600, 0x100, buffer)) {
        return false;
    }
 
    for (int i = 0; i < 0x100; i++) {
        pc.printf("%2x ", buffer[i]);
        if ((i & 0xf) == 0xf) pc.printf("\n");
    }
#endif
 
    return true;
}

int main() {
    
    pc.printf("Initialize FlashAir.\n");
    FILE *fp = fopen("/sd/mbed.txt", "w");
    if(fp == NULL) {
        error("Could not open file for write\n");
    }
    fclose(fp);
    
    pc.printf("Start.\n");    
    // Connection wait
    while(1) {
        memset(buffer, 0, 0x14);
        if (!sd.readExtMemory(1, 1, 0x506, 0x14, buffer)) {
            pc.printf("return\n");
            return -1;
        }
        uint8_t resp = get_u8(buffer);
        if ((resp & 0x80) != 0) {
            break;
        }
        pc.printf(".\n");
        wait_ms(1000);
    }
 
    // Dump status
    if (iSDIO_status() == false) {
        pc.printf("Failed to read status.\n");
        return -1;
    }

    // 追加部分ここから
    while(1) {
        memset(buffer, 0, 0x1);
        if (!sd.readExtMemory(1, 1, 0x1000, 0x1, buffer)) {
            pc.printf("return\n");
            return -1;
        }
        uint8_t usr = get_u8(buffer);
        int val = atoi((const char*)&usr);
        pc.printf("read:%d\n", val);
            
        if (val == 0) {
            led = false;
        } else {
            led = true;
        }
        wait_ms(1000);
    }
    // 追加部分ここまで
    
    pc.printf("End.\n");
}

mbedにプログラムを書き込んだ後、PCからFlashAirへ2.で試したAPIコマンドを送ります。

ON(DATAは数値0以外でLED点灯)
http://flashair/command.cgi?op=131&ADDR=0&LEN=1&DATA=1

OFF
http://flashair/command.cgi?op=131&ADDR=0&LEN=1&DATA=0

f:id:yosuke_kirihata:20150811173415j:plain

LEDを点滅させることができました!

さいごに

 FlashAirでユーザーが使用できる共有メモリ領域は512byteあるので、いろいろできそうですね!
 #いろいろを考えられるようになりたいなぁ。