This program calculate location of Wi-Fi receiver, by using AP beacon. Please check the Japanese magazine "Interface 2012/12".

Dependencies:   TextLCD mbed

Files at this revision

API Documentation at this revision

Comitter:
nakata
Date:
Fri Aug 24 03:21:43 2012 +0000
Child:
1:2f2f793fcf4f
Commit message:
CQ test version

Changed in this revision

LocationHandler.h Show annotated file Show diff for this revision Revisions of this file
TextLCD.lib Show annotated file Show diff for this revision Revisions of this file
WiFiScanner.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LocationHandler.h	Fri Aug 24 03:21:43 2012 +0000
@@ -0,0 +1,79 @@
+#include <math.h>
+#include <string.h>
+
+#define NOTFOUND_MARK (-65536)
+
+struct apinfo registered_ap[] = {
+    { "ap-game-432afd", {0, 0x22, 0xcf, 0x43, 0x2a, 0xfd}, 0 },
+    { "ap-pc-432afc", {0, 0x22, 0xcf, 0x43, 0x2a, 0xfc}, 0 },
+    { "ap-game-433f85", {0, 0x22, 0xcf, 0x43, 0x3f, 0x85}, 0 },
+    { "ap-pc-433f84", {0, 0x22, 0xcf, 0x43, 0x3f, 0x84}, 0 },
+    { "ap-game-433223", {0, 0x22, 0xcf, 0x43, 0x32, 0x23}, 0 },
+    { "ap-pc-433222", {0, 0x22, 0xcf, 0x43, 0x32, 0x22}, 0 },
+    { "ap-game-4334c9", {0, 0x22, 0xcf, 0x43, 0x34, 0xc9}, 0 },
+    { "ap-pc-4334c8", {0, 0x22, 0xcf, 0x43, 0x34, 0xc8}, 0 }
+};  // this structure must be writable
+
+struct pos {
+    float x, y;
+};
+
+const struct pos registered_pos[] = {
+    {0.0, 0.0}, {0.0, 0.0}, {0.0, 100.0}, {0.0, 100.0}, 
+    {100.0, 0.0}, {100.0, 0.0}, {100.0, 100.0}, {100.0, 100.0}
+};
+
+struct pos result_pos;
+
+void LocationManagerCalcPos(int apinfo_count, struct apinfo* searched_ap)
+{
+    int i, j, k;
+    int match_count;
+    const int length_of_registered_ap = sizeof(registered_ap) / sizeof(struct apinfo);
+    float proportion;
+    float sum;
+
+    for ( i = 0; i < length_of_registered_ap; i++ ) {
+        registered_ap[i].power = NOTFOUND_MARK;
+    }
+    match_count = 0;
+    for ( i = 0; i < apinfo_count; i++ ) {
+        for ( j = 0; j < length_of_registered_ap; j++ ) {
+            for ( k = 0; k < ESSID_LEN; k++ ) {
+                if ( registered_ap[j].essid[k] == '\0' ) {
+                    break;
+                }
+                if ( searched_ap[i].essid[k] != registered_ap[j].essid[k] ) {
+                    goto no_match;
+                }
+            }
+            if ( memcmp( registered_ap[j].bssid, searched_ap[i].bssid, MACADDR_LEN) != 0 ) {
+                continue;
+            }
+            registered_ap[j].power = searched_ap[i].power;
+            match_count++;
+            break;
+no_match:;
+        }
+    }
+    
+    if ( match_count == 0 ) {
+        lcd.cls();
+        lcd.printf("location lost\nAP count %d", apinfo_count);
+        return;
+    }
+    
+    result_pos.x = result_pos.y = 0.0;
+    sum = 0.0;
+    for ( i = 0; i < length_of_registered_ap; i++ ) {
+        proportion = pow(10, registered_ap[i].power / 40.0f);   // calc dB to linear number
+        sum += proportion;
+        result_pos.x += registered_pos[i].x * proportion;
+        result_pos.y += registered_pos[i].y * proportion;
+    }
+    result_pos.x /= sum;
+    result_pos.y /= sum;
+    
+    lcd.cls();
+    lcd.printf("AP %d/%d, location x=%.1f, y=%.1f", match_count, apinfo_count, result_pos.x, result_pos.y);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TextLCD.lib	Fri Aug 24 03:21:43 2012 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/benyun/code/TextLCD/#7dd9751172e1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/WiFiScanner.h	Fri Aug 24 03:21:43 2012 +0000
@@ -0,0 +1,393 @@
+#include <string.h>
+
+#define BAUD_RATE 115200
+
+#define MULTI_CHANNEL
+#ifdef  MULTI_CHANNEL
+#define TOTAL_CHANNELS  13
+#else
+#define TOTAL_CHANNELS  1
+#endif
+#define MAX_AP_COUNT    (10 * TOTAL_CHANNELS)
+//#define PASSIVE_SCAN  // uncommnet here when you need passive scan
+
+#define CR  '\r'
+#define SHORT_WAIT  0.00032
+#define BUFF_LEN    4096
+#define ESSID_LEN   33
+#define MACADDR_LEN 6
+
+struct apinfo {
+    unsigned char essid[ESSID_LEN];
+    unsigned char bssid[MACADDR_LEN];
+    int power;
+};
+
+struct apinfo apinfos[MAX_AP_COUNT];
+int apinfo_count;
+
+Serial wifi(p13, p14);
+
+DigitalOut PRST(p15);
+DigitalOut UART_CTS(p16);
+DigitalIn  UART_RTS(p17);
+
+class WiFiScanner {
+private:
+    int sequence;
+    unsigned char buff[BUFF_LEN];
+        
+    void wifiReadWait()
+    {
+        UART_CTS = 0;
+    }
+
+    void wifiReadEnd()
+    {
+        UART_CTS = 1;
+    }
+
+    void wifiPutc(int c)
+    {
+        while (!wifi.writeable())
+            ; // empty loop body
+        wifi.putc(c);
+    }
+
+    int wifiGetc()
+    {
+        while (!wifi.readable())
+            ; // empty loop body
+        return wifi.getc();
+    }
+
+    int num2hex(int i)
+    {
+        static const char hexadecimal[] = "0123456789ABCDEF";
+    
+        if ( i < 0 || i > 15 )
+            return '0';
+
+        return ((int)hexadecimal[i]);
+    }
+
+    int hex2num(int i)
+    {
+        switch (i) {
+        case '0':
+        case '1':
+        case '2':
+        case '3':
+        case '4':
+        case '5':
+        case '6':
+        case '7':
+        case '8':
+        case '9':
+            return (i - '0');
+        case 'A':
+        case 'B':
+        case 'C':
+        case 'D':
+        case 'E':
+        case 'F':
+            return ( i - 'A' + 10);
+        case 'a':
+        case 'b':
+        case 'c':
+        case 'd':
+        case 'e':
+        case 'f':
+            return ( i - 'a' + 10);
+        }
+        return (-1);
+    }
+
+    void delayedPutc(unsigned char c)
+    {
+        wifiPutc(c);
+        wait(SHORT_WAIT);
+    }
+
+ 
+    void wifiWrite(unsigned char *data)
+    {
+        int i;
+        int len = ((int)data[3]) * 256 + data[2];
+
+        delayedPutc('*');
+        delayedPutc(num2hex((len >> 4) & 0xf));
+        delayedPutc(num2hex(len & 0xf));
+        delayedPutc('4');
+        delayedPutc(num2hex((len >> 8) & 0xf)); 
+        for ( i = 0; i < len; i++ ) {
+            if ( i == 1 ) {
+                delayedPutc(num2hex((sequence >> 4) & 0x0f));
+                delayedPutc(num2hex(sequence & 0x0f));
+            } else {
+                delayedPutc(num2hex((data[i] >> 4) & 0x0f));
+                delayedPutc(num2hex(data[i] & 0x0f));
+            }
+        }
+        delayedPutc(CR);
+        sequence++;
+    }
+
+    int wifiRead()
+    {
+        int len = 0;
+        int index = 0;
+        int c;
+    
+        wifiReadWait();
+        while (true) {
+            c = wifiGetc();
+            if ( c == CR ) {
+                if ( (index - 5) >= len * 2 ) {
+                    break;
+                }
+
+                len = 0;
+                index = 0;
+                continue;
+            }
+            if ( index == 0 ) {
+                if ( c == '*' ) {
+                    index++;
+                } else {
+                    while (wifiGetc() != CR)
+                        ;   //empty loop body
+                }
+                continue;
+            }
+
+            c = hex2num(c);
+            if ( c < 0 ) {
+                while (wifiGetc() != CR)
+                    ;   // empty loop body
+                len = 0;
+                index = 0;
+                continue;
+            }
+            if ( index == 1 ) {
+                len = c << 4;
+            } else if ( index == 2 ) {
+                len |= c;
+            } else if ( index == 3 ) {
+                if ( c != 3 ) {
+                    wifiReadEnd();
+                    return -3;
+                }
+            } else if ( index == 4 ) {
+                len |= c << 8;
+            } else if ( index & 1 ) {
+                buff[(index - 5)/2] = c << 4;
+            } else {
+                buff[(index - 5)/2] |= c;
+            }
+            index++;
+        }
+        wifiReadEnd();
+        return len;
+    }
+
+public:
+    WiFiScanner()
+    {
+        sequence = 0;
+    }
+    
+    void reset()
+    {
+        wifi.baud(BAUD_RATE);
+        wifi.format(8, Serial::None, 1);
+    
+        sequence = 0;
+        PRST = 0;       // reset BP3591
+        wait(1.0);    // perhaps needs 1 sec
+        PRST = 1;
+        UART_CTS = 1;
+    }
+
+    void serialInit()
+    {
+        int i;
+        int c = 0;
+    
+        wifiReadWait();
+        while (true) {
+            if (wifi.writeable())
+                wifiPutc('A');
+            if (wifi.readable()) {
+               if ( c == '*' ) {
+                    c = wifiGetc();
+                    if ( c == CR ) {
+                        break;
+                    }
+                } else {
+                    c = wifiGetc();
+                }
+            }
+            wait(SHORT_WAIT);  // this wait is important
+        }
+
+        while (wifi.readable())
+            wifiGetc();
+        for ( i = 0; i < 8; i++ ) {
+            delayedPutc(0xf1);
+        }
+        c = 0;
+        while (true) {
+            if (wifi.readable()) {
+                if ( c == '*' ) {
+                    c = wifiGetc();
+                    if ( c == CR ) {
+                        break;
+                    }
+                } else {
+                    c = wifiGetc();
+                }
+            }
+        }
+        wifiReadEnd();
+    }
+
+    void waitStartup()
+    {
+        int i;
+        int len = 0;
+        bool loopFlag = true;
+        for (i = 0; loopFlag || len <= 0 || wifi.readable(); i++) {
+            len = wifiRead();
+            if ( len == 8 && buff[5] == 0x00 && buff[4] == 0x3d) {
+                loopFlag = false;
+            }
+            lcd.putc('+');
+        }
+    }
+
+    void scanMode()
+    {
+        // WID_SSID
+        unsigned char cmd0[] = { 0x57, 0x00, 0x08, 0x00, 0x00, 0x30, 0x01, 0x00 };
+        wifiWrite(cmd0);
+        while ( wifiRead() <= 0 || (buff[5] != 0x00 || buff[4] != 0x05 || buff[7] != 1))
+            wait(SHORT_WAIT);
+        
+        // WID_BSS_TYPE
+        unsigned char cmd1[] = { 0x57, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00 };
+        wifiWrite(cmd1);
+        while ( wifiRead() <= 0 || (buff[5] != 0x00 || buff[4] != 0x05 || buff[7] != 1))
+            wait(SHORT_WAIT);
+        
+        // WID_BCAST_SSID
+        unsigned char cmd2[] = { 0x57, 0x00, 0x08, 0x00, 0x15, 0x00, 0x01, 0x01 };
+        wifiWrite(cmd2);
+        while ( wifiRead() <= 0 || (buff[5] != 0x00 || buff[4] != 0x05 || buff[7] != 1))
+            wait(SHORT_WAIT);
+        
+        // WID_SCAN_TYPE
+#ifdef  PASSIVE_SCAN
+        unsigned char cmd3[] = { 0x57, 0x00, 0x08, 0x00, 0x07, 0x00, 0x01, 0x00 };
+#else
+        unsigned char cmd3[] = { 0x57, 0x00, 0x08, 0x00, 0x07, 0x00, 0x01, 0x01 };
+#endif
+        wifiWrite(cmd3);
+        while ( wifiRead() <= 0 || (buff[5] != 0x00 || buff[4] != 0x05 || buff[7] != 1))
+            wait(SHORT_WAIT);
+
+        // WID_ENABLE_CHANNEL
+        unsigned char cmd4[] = { 0x57, 0x02, 0x0b, 0x00, 0x24, 0x20, 0x04, 0xff, 0x1f, 0x00, 0x00 };
+        wifiWrite(cmd4);
+        while ( wifiRead() <= 0 || (buff[5] != 0x00 || buff[4] != 0x05 || buff[7] != 1))
+            wait(SHORT_WAIT);
+
+        // WID_SITE_SURVEY
+#ifdef  MULTI_CHANNEL
+        unsigned char cmd5[] = { 0x57, 0x01, 0x08, 0x00, 0x0e, 0x00, 0x01, 0x11 };
+#else
+        unsigned char cmd5[] = { 0x57, 0x01, 0x08, 0x00, 0x0e, 0x00, 0x01, 0x01 };
+#endif
+        wifiWrite(cmd5);
+        while ( wifiRead() <= 0 || (buff[5] != 0x00 || buff[4] != 0x05 || buff[7] != 1))
+            wait(SHORT_WAIT);
+        
+        // WID_SCAN_FILTER
+#ifdef  MULTI_CHANNEL
+        unsigned char cmd6[] = { 0x57, 0x02, 0x08, 0x00, 0x36, 0x00, 0x01, 0x00 };
+#else
+        unsigned char cmd6[] = { 0x57, 0x02, 0x08, 0x00, 0x36, 0x00, 0x01, 0x00 };
+#endif
+        wifiWrite(cmd6);
+        while ( wifiRead() <= 0 || (buff[5] != 0x00 || buff[4] != 0x05 || buff[7] != 1))
+            wait(SHORT_WAIT);
+
+#ifdef  PASSIVE_SCAN
+        // WID_SITE_SURVEY_SCAN_TIME
+        unsigned char cmd7[] = { 0x57, 0x00, 0x09, 0x00, 0x0e, 0x10, 0x02, 0x00, 0x02 };
+        wifiWrite(cmd7);
+        while ( wifiRead() <= 0 || (buff[5] != 0x00 || buff[4] != 0x05 || buff[7] != 1))
+            wait(SHORT_WAIT);
+#endif
+    }
+
+    void doScan()
+    {
+        int i, len, channel;
+        int count, write_index;
+    
+        apinfo_count = 0;
+        for (channel = 0; channel < TOTAL_CHANNELS; channel++ ) {
+            myled1 = (channel >> 3) & 1;
+            myled2 = (channel >> 2) & 1;
+            myled3 = (channel >> 1) & 1;
+            myled4 = channel & 1;
+        
+            // WID_CURRENT_CHANNEL
+#ifdef  MULTI_CHANNEL
+            unsigned char cmd8[] = { 0x57, 0x02, 0x08, 0x00, 0x02, 0x00, 0x01, 0x10 };
+            cmd8[7] = channel + 1; // 1 origin
+            wifiWrite(cmd8);
+            while ( wifiRead() <= 0 || (buff[5] != 0x00 || buff[4] != 0x05 || buff[7] != 1))
+                wait(SHORT_WAIT);
+#endif
+            // WID_START_SCAN_REQ
+            unsigned char cmd9[] = { 0x57, 0x02, 0x08, 0x00, 0x1e, 0x00, 0x01, 0x01 };
+            wifiWrite(cmd9);
+            while ( wifiRead() <= 0 || (buff[5] != 0x00 || buff[4] != 0x05 || buff[7] != 1))
+                wait(SHORT_WAIT);
+
+#ifdef  PASSIVE_SCAN
+            wait(0.5);
+#else
+            wait(0.02);
+#endif
+    
+            // WID_SITE_SURVER_RESULTS
+            unsigned char cmd10[] = { 0x51, 0x03, 0x06, 0x00, 0x12, 0x30 };
+            wifiWrite(cmd10);
+            while ( (len = wifiRead()) <= 0 || (buff[5] != 0x30 || buff[4] != 0x12))
+                wait(SHORT_WAIT);
+            if ( len < 10 ) {
+                continue;
+            }
+            count = (buff[7] - 2) / 44;
+            for ( i = 0; i < count; i++ ) {
+                for ( write_index = 0; write_index < apinfo_count; write_index++) {
+                    if ( memcmp(apinfos[write_index].essid, buff + (9 + i *44), 33) == 0 &&
+                         memcmp(apinfos[write_index].bssid, buff + (9 + i * 44 + 36), 6) == 0 ) {
+                        break;  // already recorded
+                    }
+                }
+                if ( write_index == apinfo_count ) {
+                    memcpy(apinfos[write_index].essid, buff + (9 + i * 44), 33);
+                    memcpy(apinfos[write_index].bssid, buff + (9 + i * 44 + 36), 6);
+                    apinfos[write_index].power = (signed char)buff[9 + i * 44 + 42];
+                    apinfo_count++;
+                } else if ( apinfos[write_index].power < (signed char)buff[9 + i * 44 + 42] ) {
+                    apinfos[write_index].power = (signed char)buff[9 + i * 44 + 42];
+                }
+            }
+        }
+    }
+};
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Fri Aug 24 03:21:43 2012 +0000
@@ -0,0 +1,50 @@
+#include "mbed.h"
+#include "TextLCD.h"
+
+TextLCD lcd(p24, p26, p27, p28, p29, p30); // rs, e, d4-d7
+
+DigitalOut  myled1(LED1);
+DigitalOut  myled2(LED2);
+DigitalOut  myled3(LED3);
+DigitalOut  myled4(LED4);
+
+#include "WiFiScanner.h"
+#include "LocationHandler.h"
+
+int main() {
+    WiFiScanner *wifiScanner = new WiFiScanner();
+    lcd.printf("Start configuration.");
+    
+    wifiScanner->reset();
+    wifiScanner->serialInit();
+    
+    lcd.cls();
+    lcd.printf("baud rate matched.");
+    
+    wifiScanner->waitStartup();
+
+    lcd.cls();
+    lcd.printf("TMD3591AD ready.");
+    wifiScanner->scanMode();
+    
+    lcd.cls();
+    lcd.printf("start scan");
+    while (true) {
+        int i;
+        myled1 = 1;
+        myled2 = 1;
+        myled3 = 1;
+        myled4 = 1;
+        wifiScanner->doScan();
+        LocationManagerCalcPos(apinfo_count, apinfos);
+        for ( i = 1; i <= 5; i++ ) {
+            myled1 = (i >>3) & 1;
+            myled2 = (i >>2) & 1;
+            myled3 = (i >>1) & 1;
+            myled4 = i & 1;
+            wait(1.0);
+        }
+
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Fri Aug 24 03:21:43 2012 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/737756e0b479
\ No newline at end of file